aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/viodasd.c77
-rw-r--r--drivers/cdrom/viocd.c128
-rw-r--r--drivers/char/hvc_beat.c4
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c6
-rw-r--r--drivers/char/viotape.c125
-rw-r--r--drivers/macintosh/adb-iop.c1
-rw-r--r--drivers/macintosh/adbhid.c21
-rw-r--r--drivers/macintosh/ans-lcd.c3
-rw-r--r--drivers/macintosh/ans-lcd.h11
-rw-r--r--drivers/macintosh/therm_adt746x.c5
-rw-r--r--drivers/macintosh/via-pmu.c2
-rw-r--r--drivers/macintosh/windfarm_smu_sat.c2
-rw-r--r--drivers/misc/hdpuftrs/hdpu_cpustate.c107
-rw-r--r--drivers/misc/hdpuftrs/hdpu_nexus.c88
-rw-r--r--drivers/mtd/maps/Kconfig2
-rw-r--r--drivers/mtd/maps/physmap_of.c349
-rw-r--r--drivers/net/ucc_geth.c2
-rw-r--r--drivers/net/ucc_geth.h1
-rw-r--r--drivers/net/ucc_geth_mii.c1
-rw-r--r--drivers/serial/Kconfig25
-rw-r--r--drivers/serial/cpm_uart/cpm_uart.h48
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c539
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm1.c18
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm1.h16
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm2.c24
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm2.h16
-rw-r--r--drivers/serial/mpc52xx_uart.c2
-rw-r--r--drivers/serial/pmac_zilog.c22
-rw-r--r--drivers/serial/uartlite.c286
-rw-r--r--drivers/video/platinumfb.c48
-rw-r--r--drivers/video/xilinxfb.c353
31 files changed, 1449 insertions, 883 deletions
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index af3969a9c96..e824b672e05 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -74,53 +74,9 @@ enum {
static DEFINE_SPINLOCK(viodasd_spinlock);
#define VIOMAXREQ 16
-#define VIOMAXBLOCKDMA 12
#define DEVICE_NO(cell) ((struct viodasd_device *)(cell) - &viodasd_devices[0])
-struct open_data {
- u64 disk_size;
- u16 max_disk;
- u16 cylinders;
- u16 tracks;
- u16 sectors;
- u16 bytes_per_sector;
-};
-
-struct rw_data {
- u64 offset;
- struct {
- u32 token;
- u32 reserved;
- u64 len;
- } dma_info[VIOMAXBLOCKDMA];
-};
-
-struct vioblocklpevent {
- struct HvLpEvent event;
- u32 reserved;
- u16 version;
- u16 sub_result;
- u16 disk;
- u16 flags;
- union {
- struct open_data open_data;
- struct rw_data rw_data;
- u64 changed;
- } u;
-};
-
-#define vioblockflags_ro 0x0001
-
-enum vioblocksubtype {
- vioblockopen = 0x0001,
- vioblockclose = 0x0002,
- vioblockread = 0x0003,
- vioblockwrite = 0x0004,
- vioblockflush = 0x0005,
- vioblockcheck = 0x0007
-};
-
struct viodasd_waitevent {
struct completion com;
int rc;
@@ -429,7 +385,7 @@ static void do_viodasd_request(struct request_queue *q)
* Probe a single disk and fill in the viodasd_device structure
* for it.
*/
-static void probe_disk(struct viodasd_device *d)
+static int probe_disk(struct viodasd_device *d)
{
HvLpEvent_Rc hvrc;
struct viodasd_waitevent we;
@@ -453,14 +409,14 @@ retry:
0, 0, 0);
if (hvrc != 0) {
printk(VIOD_KERN_WARNING "bad rc on HV open %d\n", (int)hvrc);
- return;
+ return 0;
}
wait_for_completion(&we.com);
if (we.rc != 0) {
if (flags != 0)
- return;
+ return 0;
/* try again with read only flag set */
flags = vioblockflags_ro;
goto retry;
@@ -490,15 +446,32 @@ retry:
if (hvrc != 0) {
printk(VIOD_KERN_WARNING
"bad rc sending event to OS/400 %d\n", (int)hvrc);
- return;
+ return 0;
}
+
+ if (d->dev == NULL) {
+ /* this is when we reprobe for new disks */
+ if (vio_create_viodasd(dev_no) == NULL) {
+ printk(VIOD_KERN_WARNING
+ "cannot allocate virtual device for disk %d\n",
+ dev_no);
+ return 0;
+ }
+ /*
+ * The vio_create_viodasd will have recursed into this
+ * routine with d->dev set to the new vio device and
+ * will finish the setup of the disk below.
+ */
+ return 1;
+ }
+
/* create the request queue for the disk */
spin_lock_init(&d->q_lock);
q = blk_init_queue(do_viodasd_request, &d->q_lock);
if (q == NULL) {
printk(VIOD_KERN_WARNING "cannot allocate queue for disk %d\n",
dev_no);
- return;
+ return 0;
}
g = alloc_disk(1 << PARTITION_SHIFT);
if (g == NULL) {
@@ -506,7 +479,7 @@ retry:
"cannot allocate disk structure for disk %d\n",
dev_no);
blk_cleanup_queue(q);
- return;
+ return 0;
}
d->disk = g;
@@ -538,6 +511,7 @@ retry:
/* register us in the global list */
add_disk(g);
+ return 1;
}
/* returns the total number of scatterlist elements converted */
@@ -718,8 +692,7 @@ static int viodasd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
struct viodasd_device *d = &viodasd_devices[vdev->unit_address];
d->dev = &vdev->dev;
- probe_disk(d);
- if (d->disk == NULL)
+ if (!probe_disk(d))
return -ENODEV;
return 0;
}
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index e51550db157..880b5dce3a6 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -56,30 +56,6 @@
#define VIOCD_KERN_WARNING KERN_WARNING "viocd: "
#define VIOCD_KERN_INFO KERN_INFO "viocd: "
-struct viocdlpevent {
- struct HvLpEvent event;
- u32 reserved;
- u16 version;
- u16 sub_result;
- u16 disk;
- u16 flags;
- u32 token;
- u64 offset; /* On open, max number of disks */
- u64 len; /* On open, size of the disk */
- u32 block_size; /* Only set on open */
- u32 media_size; /* Only set on open */
-};
-
-enum viocdsubtype {
- viocdopen = 0x0001,
- viocdclose = 0x0002,
- viocdread = 0x0003,
- viocdwrite = 0x0004,
- viocdlockdoor = 0x0005,
- viocdgetinfo = 0x0006,
- viocdcheck = 0x0007
-};
-
/*
* Should probably make this a module parameter....sigh
*/
@@ -131,22 +107,13 @@ static struct capability_entry capability_table[] __initdata = {
/* These are our internal structures for keeping track of devices */
static int viocd_numdev;
-struct cdrom_info {
- char rsrcname[10];
- char type[4];
- char model[3];
-};
-/*
- * This needs to be allocated since it is passed to the
- * Hypervisor and we may be a module.
- */
-static struct cdrom_info *viocd_unitinfo;
-static dma_addr_t unitinfo_dmaaddr;
-
struct disk_info {
struct gendisk *viocd_disk;
struct cdrom_device_info viocd_info;
struct device *dev;
+ const char *rsrcname;
+ const char *type;
+ const char *model;
};
static struct disk_info viocd_diskinfo[VIOCD_MAX_CD];
@@ -164,9 +131,9 @@ static int proc_viocd_show(struct seq_file *m, void *v)
for (i = 0; i < viocd_numdev; i++) {
seq_printf(m, "viocd device %d is iSeries resource %10.10s"
"type %4.4s, model %3.3s\n",
- i, viocd_unitinfo[i].rsrcname,
- viocd_unitinfo[i].type,
- viocd_unitinfo[i].model);
+ i, viocd_diskinfo[i].rsrcname,
+ viocd_diskinfo[i].type,
+ viocd_diskinfo[i].model);
}
return 0;
}
@@ -216,61 +183,6 @@ struct block_device_operations viocd_fops = {
.media_changed = viocd_blk_media_changed,
};
-/* Get info on CD devices from OS/400 */
-static void __init get_viocd_info(void)
-{
- HvLpEvent_Rc hvrc;
- int i;
- struct viocd_waitevent we;
-
- viocd_unitinfo = dma_alloc_coherent(iSeries_vio_dev,
- sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
- &unitinfo_dmaaddr, GFP_ATOMIC);
- if (viocd_unitinfo == NULL) {
- printk(VIOCD_KERN_WARNING "error allocating unitinfo\n");
- return;
- }
-
- memset(viocd_unitinfo, 0, sizeof(*viocd_unitinfo) * VIOCD_MAX_CD);
-
- init_completion(&we.com);
-
- hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
- HvLpEvent_Type_VirtualIo,
- viomajorsubtype_cdio | viocdgetinfo,
- HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
- viopath_sourceinst(viopath_hostLp),
- viopath_targetinst(viopath_hostLp),
- (u64)&we, VIOVERSION << 16, unitinfo_dmaaddr, 0,
- sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, 0);
- if (hvrc != HvLpEvent_Rc_Good) {
- printk(VIOCD_KERN_WARNING "cdrom error sending event. rc %d\n",
- (int)hvrc);
- goto error_ret;
- }
-
- wait_for_completion(&we.com);
-
- if (we.rc) {
- const struct vio_error_entry *err =
- vio_lookup_rc(viocd_err_table, we.sub_result);
- printk(VIOCD_KERN_WARNING "bad rc %d:0x%04X on getinfo: %s\n",
- we.rc, we.sub_result, err->msg);
- goto error_ret;
- }
-
- for (i = 0; (i < VIOCD_MAX_CD) && viocd_unitinfo[i].rsrcname[0]; i++)
- viocd_numdev++;
-
-error_ret:
- if (viocd_numdev == 0) {
- dma_free_coherent(iSeries_vio_dev,
- sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
- viocd_unitinfo, unitinfo_dmaaddr);
- viocd_unitinfo = NULL;
- }
-}
-
static int viocd_open(struct cdrom_device_info *cdi, int purpose)
{
struct disk_info *diskinfo = cdi->handle;
@@ -581,7 +493,6 @@ static void vio_handle_cd_event(struct HvLpEvent *event)
bevent->block_size / 512);
}
/* FALLTHROUGH !! */
- case viocdgetinfo:
case viocdlockdoor:
pwe = (struct viocd_waitevent *)event->xCorrelationToken;
return_complete:
@@ -665,22 +576,30 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
int deviceno;
struct disk_info *d;
struct cdrom_device_info *c;
- struct cdrom_info *ci;
struct request_queue *q;
+ struct device_node *node = vdev->dev.archdata.of_node;
deviceno = vdev->unit_address;
- if (deviceno >= viocd_numdev)
+ if (deviceno > VIOCD_MAX_CD)
return -ENODEV;
+ if (!node)
+ return -ENODEV;
+
+ if (deviceno >= viocd_numdev)
+ viocd_numdev = deviceno + 1;
d = &viocd_diskinfo[deviceno];
+ d->rsrcname = of_get_property(node, "linux,vio_rsrcname", NULL);
+ d->type = of_get_property(node, "linux,vio_type", NULL);
+ d->model = of_get_property(node, "linux,vio_model", NULL);
+
c = &d->viocd_info;
- ci = &viocd_unitinfo[deviceno];
c->ops = &viocd_dops;
c->speed = 4;
c->capacity = 1;
c->handle = d;
- c->mask = ~find_capability(ci->type);
+ c->mask = ~find_capability(d->type);
sprintf(c->name, VIOCD_DEVICE "%c", 'a' + deviceno);
if (register_cdrom(c) != 0) {
@@ -690,7 +609,7 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
}
printk(VIOCD_KERN_INFO "cd %s is iSeries resource %10.10s "
"type %4.4s, model %3.3s\n",
- c->name, ci->rsrcname, ci->type, ci->model);
+ c->name, d->rsrcname, d->type, d->model);
q = blk_init_queue(do_viocd_request, &viocd_reqlock);
if (q == NULL) {
printk(VIOCD_KERN_WARNING "Cannot allocate queue for %s!\n",
@@ -799,8 +718,6 @@ static int __init viocd_init(void)
/* Initialize our request handler */
vio_setHandler(viomajorsubtype_cdio, vio_handle_cd_event);
- get_viocd_info();
-
spin_lock_init(&viocd_reqlock);
ret = vio_register_driver(&viocd_driver);
@@ -816,9 +733,6 @@ static int __init viocd_init(void)
return 0;
out_free_info:
- dma_free_coherent(iSeries_vio_dev,
- sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
- viocd_unitinfo, unitinfo_dmaaddr);
vio_clearHandler(viomajorsubtype_cdio);
viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2);
out_unregister:
@@ -830,10 +744,6 @@ static void __exit viocd_exit(void)
{
remove_proc_entry("iSeries/viocd", NULL);
vio_unregister_driver(&viocd_driver);
- if (viocd_unitinfo != NULL)
- dma_free_coherent(iSeries_vio_dev,
- sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
- viocd_unitinfo, unitinfo_dmaaddr);
viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2);
vio_clearHandler(viomajorsubtype_cdio);
unregister_blkdev(VIOCD_MAJOR, VIOCD_DEVICE);
diff --git a/drivers/char/hvc_beat.c b/drivers/char/hvc_beat.c
index 6f019f19be7..e74bb949c28 100644
--- a/drivers/char/hvc_beat.c
+++ b/drivers/char/hvc_beat.c
@@ -97,7 +97,7 @@ static int hvc_beat_config(char *p)
return 0;
}
-static int hvc_beat_console_init(void)
+static int __init hvc_beat_console_init(void)
{
if (hvc_beat_useit && machine_is_compatible("Beat")) {
hvc_instantiate(0, 0, &hvc_beat_get_put_ops);
@@ -106,7 +106,7 @@ static int hvc_beat_console_init(void)
}
/* temp */
-static int hvc_beat_init(void)
+static int __init hvc_beat_init(void)
{
struct hvc_struct *hp;
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 7901d5f218e..a2894d42515 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -2253,19 +2253,19 @@ static int __devinit ipmi_of_probe(struct of_device *dev,
return ret;
}
- regsize = get_property(np, "reg-size", &proplen);
+ regsize = of_get_property(np, "reg-size", &proplen);
if (regsize && proplen != 4) {
dev_warn(&dev->dev, PFX "invalid regsize from OF\n");
return -EINVAL;
}
- regspacing = get_property(np, "reg-spacing", &proplen);
+ regspacing = of_get_property(np, "reg-spacing", &proplen);
if (regspacing && proplen != 4) {
dev_warn(&dev->dev, PFX "invalid regspacing from OF\n");
return -EINVAL;
}
- regshift = get_property(np, "reg-shift", &proplen);
+ regshift = of_get_property(np, "reg-shift", &proplen);
if (regshift && proplen != 4) {
dev_warn(&dev->dev, PFX "invalid regshift from OF\n");
return -EINVAL;
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index e12275df6ea..f1d60f0cef8 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -92,47 +92,6 @@ struct viot_devinfo_struct {
#define VIOTAPOP_SETPART 14
#define VIOTAPOP_UNLOAD 15
-struct viotapelpevent {
- struct HvLpEvent event;
- u32 reserved;
- u16 version;
- u16 sub_type_result;
- u16 tape;
- u16 flags;
- u32 token;
- u64 len;
- union {
- struct {
- u32 tape_op;
- u32 count;
- } op;
- struct {
- u32 type;
- u32 resid;
- u32 dsreg;
- u32 gstat;
- u32 erreg;
- u32 file_no;
- u32 block_no;
- } get_status;
- struct {
- u32 block_no;
- } get_pos;
- } u;
-};
-
-enum viotapesubtype {
- viotapeopen = 0x0001,
- viotapeclose = 0x0002,
- viotaperead = 0x0003,
- viotapewrite = 0x0004,
- viotapegetinfo = 0x0005,
- viotapeop = 0x0006,
- viotapegetpos = 0x0007,
- viotapesetpos = 0x0008,
- viotapegetstatus = 0x0009
-};
-
enum viotaperc {
viotape_InvalidRange = 0x0601,
viotape_InvalidToken = 0x0602,
@@ -223,14 +182,11 @@ static const struct vio_error_entry viotape_err_table[] = {
#define VIOT_WRITING 2
/* Our info on the tapes */
-struct tape_descr {
- char rsrcname[10];
- char type[4];
- char model[3];
-};
-
-static struct tape_descr *viotape_unitinfo;
-static dma_addr_t viotape_unitinfo_token;
+static struct {
+ const char *rsrcname;
+ const char *type;
+ const char *model;
+} viotape_unitinfo[VIOTAPE_MAX_TAPE];
static struct mtget viomtget[VIOTAPE_MAX_TAPE];
@@ -381,53 +337,6 @@ int tape_rc_to_errno(int tape_rc, char *operation, int tapeno)
return -err->errno;
}
-/* Get info on all tapes from OS/400 */
-static int get_viotape_info(void)
-{
- HvLpEvent_Rc hvrc;
- int i;
- size_t len = sizeof(*viotape_unitinfo) * VIOTAPE_MAX_TAPE;
- struct op_struct *op = get_op_struct();
-
- if (op == NULL)
- return -ENOMEM;
-
- viotape_unitinfo = dma_alloc_coherent(iSeries_vio_dev, len,
- &viotape_unitinfo_token, GFP_ATOMIC);
- if (viotape_unitinfo == NULL) {
- free_op_struct(op);
- return -ENOMEM;
- }
-
- memset(viotape_unitinfo, 0, len);
-
- hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
- HvLpEvent_Type_VirtualIo,
- viomajorsubtype_tape | viotapegetinfo,
- HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
- viopath_sourceinst(viopath_hostLp),
- viopath_targetinst(viopath_hostLp),
- (u64) (unsigned long) op, VIOVERSION << 16,
- viotape_unitinfo_token, len, 0, 0);
- if (hvrc != HvLpEvent_Rc_Good) {
- printk(VIOTAPE_KERN_WARN "hv error on op %d\n",
- (int)hvrc);
- free_op_struct(op);
- return -EIO;
- }
-
- wait_for_completion(&op->com);
-
- free_op_struct(op);
-
- for (i = 0;
- ((i < VIOTAPE_MAX_TAPE) && (viotape_unitinfo[i].rsrcname[0]));
- i++)
- viotape_numdev++;
- return 0;
-}
-
-
/* Write */
static ssize_t viotap_write(struct file *file, const char *buf,
size_t count, loff_t * ppos)
@@ -899,7 +808,6 @@ static void vioHandleTapeEvent(struct HvLpEvent *event)
tapeminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK;
op = (struct op_struct *)event->xCorrelationToken;
switch (tapeminor) {
- case viotapegetinfo:
case viotapeopen:
case viotapeclose:
op->rc = tevent->sub_type_result;
@@ -942,11 +850,23 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
{
int i = vdev->unit_address;
int j;
+ struct device_node *node = vdev->dev.archdata.of_node;
- if (i >= viotape_numdev)
+ if (i > VIOTAPE_MAX_TAPE)
+ return -ENODEV;
+ if (!node)
return -ENODEV;
+ if (i >= viotape_numdev)
+ viotape_numdev = i + 1;
+
tape_device[i] = &vdev->dev;
+ viotape_unitinfo[i].rsrcname = of_get_property(node,
+ "linux,vio_rsrcname", NULL);
+ viotape_unitinfo[i].type = of_get_property(node, "linux,vio_type",
+ NULL);
+ viotape_unitinfo[i].model = of_get_property(node, "linux,vio_model",
+ NULL);
state[i].cur_part = 0;
for (j = 0; j < MAX_PARTITIONS; ++j)
@@ -1044,11 +964,6 @@ int __init viotap_init(void)
goto unreg_chrdev;
}
- if ((ret = get_viotape_info()) < 0) {
- printk(VIOTAPE_KERN_WARN "Unable to obtain virtual device information");
- goto unreg_class;
- }
-
ret = vio_register_driver(&viotape_driver);
if (ret)
goto unreg_class;
@@ -1102,10 +1017,6 @@ static void __exit viotap_exit(void)
vio_unregister_driver(&viotape_driver);
class_destroy(tape_class);
unregister_chrdev(VIOTAPE_MAJOR, "viotape");
- if (viotape_unitinfo)
- dma_free_coherent(iSeries_vio_dev,
- sizeof(viotape_unitinfo[0]) * VIOTAPE_MAX_TAPE,
- viotape_unitinfo, viotape_unitinfo_token);
viopath_close(viopath_hostLp, viomajorsubtype_tape, VIOTAPE_MAXREQ + 2);
vio_clearHandler(viomajorsubtype_tape);
clear_op_struct_pool();
diff --git a/drivers/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c
index 17ef5d3c01b..44469662517 100644
--- a/drivers/macintosh/adb-iop.c
+++ b/drivers/macintosh/adb-iop.c
@@ -19,7 +19,6 @@
#include <linux/init.h>
#include <linux/proc_fs.h>
-#include <asm/bootinfo.h>
#include <asm/macintosh.h>
#include <asm/macints.h>
#include <asm/mac_iop.h>
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index b46817f699f..48d17bf6c92 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -70,7 +70,7 @@ static struct notifier_block adbhid_adb_notifier = {
#define ADB_KEY_POWER_OLD 0x7e
#define ADB_KEY_POWER 0x7f
-u8 adb_to_linux_keycodes[128] = {
+u16 adb_to_linux_keycodes[128] = {
/* 0x00 */ KEY_A, /* 30 */
/* 0x01 */ KEY_S, /* 31 */
/* 0x02 */ KEY_D, /* 32 */
@@ -134,7 +134,7 @@ u8 adb_to_linux_keycodes[128] = {
/* 0x3c */ KEY_RIGHT, /* 106 */
/* 0x3d */ KEY_DOWN, /* 108 */
/* 0x3e */ KEY_UP, /* 103 */
- /* 0x3f */ 0,
+ /* 0x3f */ KEY_FN, /* 0x1d0 */
/* 0x40 */ 0,
/* 0x41 */ KEY_KPDOT, /* 83 */
/* 0x42 */ 0,
@@ -208,7 +208,7 @@ struct adbhid {
int original_handler_id;
int current_handler_id;
int mouse_kind;
- unsigned char *keycode;
+ u16 *keycode;
char name[64];
char phys[32];
int flags;
@@ -275,7 +275,7 @@ static void
adbhid_input_keycode(int id, int keycode, int repeat)
{
struct adbhid *ahid = adbhid[id];
- int up_flag;
+ int up_flag, key;
up_flag = (keycode & 0x80);
keycode &= 0x7f;
@@ -321,8 +321,7 @@ adbhid_input_keycode(int id, int keycode, int repeat)
}
} else
ahid->flags |= FLAG_FN_KEY_PRESSED;
- /* Swallow the key press */
- return;
+ break;
case ADB_KEY_DEL:
/* Emulate Fn+delete = forward delete */
if (ahid->flags & FLAG_FN_KEY_PRESSED) {
@@ -336,9 +335,9 @@ adbhid_input_keycode(int id, int keycode, int repeat)
#endif /* CONFIG_PPC_PMAC */
}
- if (adbhid[id]->keycode[keycode]) {
- input_report_key(adbhid[id]->input,
- adbhid[id]->keycode[keycode], !up_flag);
+ key = adbhid[id]->keycode[keycode];
+ if (key) {
+ input_report_key(adbhid[id]->input, key, !up_flag);
input_sync(adbhid[id]->input);
} else
printk(KERN_INFO "Unhandled ADB key (scancode %#02x) %s.\n", keycode,
@@ -757,8 +756,8 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
input_dev->ledbit[0] = BIT(LED_SCROLLL) | BIT(LED_CAPSL) | BIT(LED_NUML);
input_dev->event = adbhid_kbd_event;
- input_dev->keycodemax = 127;
- input_dev->keycodesize = 1;
+ input_dev->keycodemax = KEY_FN;
+ input_dev->keycodesize = sizeof(hid->keycode[0]);
break;
case ADB_MOUSE:
diff --git a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c
index e54c4d9f636..73c50bc0209 100644
--- a/drivers/macintosh/ans-lcd.c
+++ b/drivers/macintosh/ans-lcd.c
@@ -14,9 +14,10 @@
#include <asm/uaccess.h>
#include <asm/sections.h>
#include <asm/prom.h>
-#include <asm/ans-lcd.h>
#include <asm/io.h>
+#include "ans-lcd.h"
+
#define ANSLCD_ADDR 0xf301c000
#define ANSLCD_CTRL_IX 0x00
#define ANSLCD_DATA_IX 0x10
diff --git a/drivers/macintosh/ans-lcd.h b/drivers/macintosh/ans-lcd.h
new file mode 100644
index 00000000000..d795b9fd2db
--- /dev/null
+++ b/drivers/macintosh/ans-lcd.h
@@ -0,0 +1,11 @@
+#ifndef _PPC_ANS_LCD_H
+#define _PPC_ANS_LCD_H
+
+#define ANSLCD_MINOR 156
+
+#define ANSLCD_CLEAR 0x01
+#define ANSLCD_SENDCTRL 0x02
+#define ANSLCD_SETSHORTDELAY 0x03
+#define ANSLCD_SETLONGDELAY 0x04
+
+#endif
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index f25685b9b7c..276945d5151 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -379,13 +379,10 @@ static int attach_one_thermostat(struct i2c_adapter *adapter, int addr,
if (thermostat)
return 0;
- th = (struct thermostat *)
- kmalloc(sizeof(struct thermostat), GFP_KERNEL);
-
+ th = kzalloc(sizeof(struct thermostat), GFP_KERNEL);
if (!th)
return -ENOMEM;
- memset(th, 0, sizeof(*th));
th->clt.addr = addr;
th->clt.adapter = adapter;
th->clt.driver = &thermostat_driver;
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 04f3973e387..f7c509b7a8e 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -410,7 +410,7 @@ static int __init via_pmu_start(void)
irq = irq_of_parse_and_map(vias, 0);
if (irq == NO_IRQ) {
- printk(KERN_ERR "via-pmu: can't map interruptn");
+ printk(KERN_ERR "via-pmu: can't map interrupt\n");
return -ENODEV;
}
if (request_irq(irq, via_pmu_interrupt, 0, "VIA-PMU", (void *)0)) {
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c
index 351982bcec1..f449d775cdf 100644
--- a/drivers/macintosh/windfarm_smu_sat.c
+++ b/drivers/macintosh/windfarm_smu_sat.c
@@ -380,10 +380,12 @@ static int __init sat_sensors_init(void)
return i2c_add_driver(&wf_sat_driver);
}
+#if 0 /* uncomment when module_exit() below is uncommented */
static void __exit sat_sensors_exit(void)
{
i2c_del_driver(&wf_sat_driver);
}
+#endif
module_init(sat_sensors_init);
/*module_exit(sat_sensors_exit); Uncomment when cleanup is implemented */
diff --git a/drivers/misc/hdpuftrs/hdpu_cpustate.c b/drivers/misc/hdpuftrs/hdpu_cpustate.c
index 276ba3c5143..aa8ce7abe92 100644
--- a/drivers/misc/hdpuftrs/hdpu_cpustate.c
+++ b/drivers/misc/hdpuftrs/hdpu_cpustate.c
@@ -19,16 +19,41 @@
#include <linux/spinlock.h>
#include <linux/miscdevice.h>
#include <linux/proc_fs.h>
+#include <linux/hdpu_features.h>
#include <linux/platform_device.h>
#include <asm/uaccess.h>
-#include <linux/hdpu_features.h>
+#include <linux/seq_file.h>
+#include <asm/io.h>
#define SKY_CPUSTATE_VERSION "1.1"
static int hdpu_cpustate_probe(struct platform_device *pdev);
static int hdpu_cpustate_remove(struct platform_device *pdev);
-struct cpustate_t cpustate;
+static unsigned char cpustate_get_state(void);
+static int cpustate_proc_open(struct inode *inode, struct file *file);
+static int cpustate_proc_read(struct seq_file *seq, void *offset);
+
+static struct cpustate_t cpustate;
+
+static const struct file_operations proc_cpustate = {
+ .open = cpustate_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
+static int cpustate_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, cpustate_proc_read, NULL);
+}
+
+static int cpustate_proc_read(struct seq_file *seq, void *offset)
+{
+ seq_printf(seq, "CPU State: %04x\n", cpustate_get_state());
+ return 0;
+}
static int cpustate_get_ref(int excl)
{
@@ -66,13 +91,13 @@ static int cpustate_free_ref(void)
return 0;
}
-unsigned char cpustate_get_state(void)
+static unsigned char cpustate_get_state(void)
{
return cpustate.cached_val;
}
-void cpustate_set_state(unsigned char new_state)
+static void cpustate_set_state(unsigned char new_state)
{
unsigned int state = (new_state << 21);
@@ -134,29 +159,6 @@ static int cpustate_release(struct inode *inode, struct file *file)
return cpustate_free_ref();
}
-/*
- * Info exported via "/proc/sky_cpustate".
- */
-static int cpustate_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- char *p = page;
- int len = 0;
-
- p += sprintf(p, "CPU State: %04x\n", cpustate_get_state());
- len = p - page;
-
- if (len <= off + count)
- *eof = 1;
- *start = page + off;
- len -= off;
- if (len > count)
- len = count;
- if (len < 0)
- len = 0;
- return len;
-}
-
static struct platform_driver hdpu_cpustate_driver = {
.probe = hdpu_cpustate_probe,
.remove = hdpu_cpustate_remove,
@@ -169,22 +171,18 @@ static struct platform_driver hdpu_cpustate_driver = {
* The various file operations we support.
*/
static const struct file_operations cpustate_fops = {
- owner:THIS_MODULE,
- open:cpustate_open,
- release:cpustate_release,
- read:cpustate_read,
- write:cpustate_write,
- fasync:NULL,
- poll:NULL,
- ioctl:NULL,
- llseek:no_llseek,
-
+ .owner = THIS_MODULE,
+ .open = cpustate_open,
+ .release = cpustate_release,
+ .read = cpustate_read,
+ .write = cpustate_write,
+ .llseek = no_llseek,
};
static struct miscdevice cpustate_dev = {
- MISC_DYNAMIC_MINOR,
- "sky_cpustate",
- &cpustate_fops
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "sky_cpustate",
+ .fops = &cpustate_fops,
};
static int hdpu_cpustate_probe(struct platform_device *pdev)
@@ -194,23 +192,31 @@ static int hdpu_cpustate_probe(struct platform_device *pdev)
int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ printk(KERN_ERR "sky_cpustate: "
+ "Invalid memory resource.\n");
+ return -EINVAL;
+ }
cpustate.set_addr = (unsigned long *)res->start;
cpustate.clr_addr = (unsigned long *)res->end - 1;
ret = misc_register(&cpustate_dev);
if (ret) {
- printk(KERN_WARNING "sky_cpustate: Unable to register misc "
- "device.\n");
+ printk(KERN_WARNING "sky_cpustate: "
+ "Unable to register misc device.\n");
cpustate.set_addr = NULL;
cpustate.clr_addr = NULL;
return ret;
}
- proc_de = create_proc_read_entry("sky_cpustate", 0, 0,
- cpustate_read_proc, NULL);
- if (proc_de == NULL)
- printk(KERN_WARNING "sky_cpustate: Unable to create proc "
- "dir entry\n");
+ proc_de = create_proc_entry("sky_cpustate", 0666, &proc_root);
+ if (!proc_de) {
+ printk(KERN_WARNING "sky_cpustate: "
+ "Unable to create proc entry\n");
+ } else {
+ proc_de->proc_fops = &proc_cpustate;
+ proc_de->owner = THIS_MODULE;
+ }
printk(KERN_INFO "Sky CPU State Driver v" SKY_CPUSTATE_VERSION "\n");
return 0;
@@ -218,21 +224,18 @@ static int hdpu_cpustate_probe(struct platform_device *pdev)
static int hdpu_cpustate_remove(struct platform_device *pdev)
{
-
cpustate.set_addr = NULL;
cpustate.clr_addr = NULL;
remove_proc_entry("sky_cpustate", NULL);
misc_deregister(&cpustate_dev);
- return 0;
+ return 0;
}
static int __init cpustate_init(void)
{
- int rc;
- rc = platform_driver_register(&hdpu_cpustate_driver);
- return rc;
+ return platform_driver_register(&hdpu_cpustate_driver);
}
static void __exit cpustate_exit(void)
diff --git a/drivers/misc/hdpuftrs/hdpu_nexus.c b/drivers/misc/hdpuftrs/hdpu_nexus.c
index 60c8b26f067..2887b214798 100644
--- a/drivers/misc/hdpuftrs/hdpu_nexus.c
+++ b/drivers/misc/hdpuftrs/hdpu_nexus.c
@@ -18,17 +18,38 @@
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/hdpu_features.h>
-
#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <asm/io.h>
static int hdpu_nexus_probe(struct platform_device *pdev);
static int hdpu_nexus_remove(struct platform_device *pdev);
+static int hdpu_slot_id_open(struct inode *inode, struct file *file);
+static int hdpu_slot_id_read(struct seq_file *seq, void *offset);
+static int hdpu_chassis_id_open(struct inode *inode, struct file *file);
+static int hdpu_chassis_id_read(struct seq_file *seq, void *offset);
static struct proc_dir_entry *hdpu_slot_id;
static struct proc_dir_entry *hdpu_chassis_id;
static int slot_id = -1;
static int chassis_id = -1;
+static const struct file_operations proc_slot_id = {
+ .open = hdpu_slot_id_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
+static const struct file_operations proc_chassis_id = {
+ .open = hdpu_chassis_id_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
static struct platform_driver hdpu_nexus_driver = {
.probe = hdpu_nexus_probe,
.remove = hdpu_nexus_remove,
@@ -37,43 +58,67 @@ static struct platform_driver hdpu_nexus_driver = {
},
};
-int hdpu_slot_id_read(char *buffer, char **buffer_location, off_t offset,
- int buffer_length, int *zero, void *ptr)
+static int hdpu_slot_id_open(struct inode *inode, struct file *file)
{
+ return single_open(file, hdpu_slot_id_read, NULL);
+}
- if (offset > 0)
- return 0;
- return sprintf(buffer, "%d\n", slot_id);
+static int hdpu_slot_id_read(struct seq_file *seq, void *offset)
+{
+ seq_printf(seq, "%d\n", slot_id);
+ return 0;
}
-int hdpu_chassis_id_read(char *buffer, char **buffer_location, off_t offset,
- int buffer_length, int *zero, void *ptr)
+static int hdpu_chassis_id_open(struct inode *inode, struct file *file)
{
+ return single_open(file, hdpu_chassis_id_read, NULL);
+}
- if (offset > 0)
- return 0;
- return sprintf(buffer, "%d\n", chassis_id);
+static int hdpu_chassis_id_read(struct seq_file *seq, void *offset)
+{
+ seq_printf(seq, "%d\n", chassis_id);
+ return 0;
}
static int hdpu_nexus_probe(struct platform_device *pdev)
{
struct resource *res;
+ int *nexus_id_addr;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- int *nexus_id_addr;
- nexus_id_addr =
- ioremap(res->start, (unsigned long)(res->end - res->start));
+ if (!res) {
+ printk(KERN_ERR "sky_nexus: "
+ "Invalid memory resource.\n");
+ return -EINVAL;
+ }
+ nexus_id_addr = ioremap(res->start,
+ (unsigned long)(res->end - res->start));
if (nexus_id_addr) {
slot_id = (*nexus_id_addr >> 8) & 0x1f;
chassis_id = *nexus_id_addr & 0xff;
iounmap(nexus_id_addr);
- } else
- printk("Could not map slot id\n");
+ } else {
+ printk(KERN_ERR "sky_nexus: Could not map slot id\n");
+ }
+
hdpu_slot_id = create_proc_entry("sky_slot_id", 0666, &proc_root);
- hdpu_slot_id->read_proc = hdpu_slot_id_read;
+ if (!hdpu_slot_id) {
+ printk(KERN_WARNING "sky_nexus: "
+ "Unable to create proc dir entry: sky_slot_id\n");
+ } else {
+ hdpu_slot_id->proc_fops = &proc_slot_id;
+ hdpu_slot_id->owner = THIS_MODULE;
+ }
hdpu_chassis_id = create_proc_entry("sky_chassis_id", 0666, &proc_root);
- hdpu_chassis_id->read_proc = hdpu_chassis_id_read;
+ if (!hdpu_chassis_id) {
+ printk(KERN_WARNING "sky_nexus: "
+ "Unable to create proc dir entry: sky_chassis_id\n");
+ } else {
+ hdpu_chassis_id->proc_fops = &proc_chassis_id;
+ hdpu_chassis_id->owner = THIS_MODULE;
+ }
+
return 0;
}
@@ -81,18 +126,19 @@ static int hdpu_nexus_remove(struct platform_device *pdev)
{
slot_id = -1;
chassis_id = -1;
+
remove_proc_entry("sky_slot_id", &proc_root);
remove_proc_entry("sky_chassis_id", &proc_root);
+
hdpu_slot_id = 0;
hdpu_chassis_id = 0;
+
return 0;
}
static int __init nexus_init(void)
{
- int rc;
- rc = platform_driver_register(&hdpu_nexus_driver);
- return rc;
+ return platform_driver_register(&hdpu_nexus_driver);
}
static void __exit nexus_exit(void)
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index cc6c7344243..6cd132c7518 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -362,7 +362,7 @@ config MTD_WALNUT
config MTD_EBONY
tristate "Flash devices mapped on IBM 440GP Ebony"
- depends on MTD_JEDECPROBE && EBONY
+ depends on MTD_JEDECPROBE && EBONY && !PPC_MERGE
help
This enables access routines for the flash chips on the IBM 440GP
Ebony board. If you have one of these boards and would like to
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index bbb42c35b69..cf75a566442 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -1,9 +1,12 @@
/*
- * Normal mappings of chips in physical memory for OF devices
+ * Flash mappings described by the OF (or flattened) device tree
*
* Copyright (C) 2006 MontaVista Software Inc.
* Author: Vitaly Wool <vwool@ru.mvista.com>
*
+ * Revised to handle newer style flash binding by:
+ * Copyright (C) 2007 David Gibson, IBM Corporation.
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
@@ -12,102 +15,157 @@
#include <linux/module.h>
#include <linux/types.h>
-#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/slab.h>
#include <linux/device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
-#include <linux/mtd/physmap.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/of_device.h>
-#include <asm/of_platform.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
-struct physmap_flash_info {
+struct of_flash {
struct mtd_info *mtd;
struct map_info map;
struct resource *res;
#ifdef CONFIG_MTD_PARTITIONS
- int nr_parts;
struct mtd_partition *parts;
#endif
};
-static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
#ifdef CONFIG_MTD_PARTITIONS
-static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
-#endif
+#define OF_FLASH_PARTS(info) ((info)->parts)
-#ifdef CONFIG_MTD_PARTITIONS
-static int parse_flash_partitions(struct device_node *node,
- struct mtd_partition **parts)
+static int parse_obsolete_partitions(struct of_device *dev,
+ struct of_flash *info,
+ struct device_node *dp)
{
- int i, plen, retval = -ENOMEM;
- const u32 *part;
- const char *name;
-
- part = of_get_property(node, "partitions", &plen);
- if (part == NULL)
- goto err;
-
- retval = plen / (2 * sizeof(u32));
- *parts = kzalloc(retval * sizeof(struct mtd_partition), GFP_KERNEL);
- if (*parts == NULL) {
- printk(KERN_ERR "Can't allocate the flash partition data!\n");
- goto err;
- }
+ int i, plen, nr_parts;
+ const struct {
+ u32 offset, len;
+ } *part;
+ const char *names;
+
+ part = of_get_property(dp, "partitions", &plen);
+ if (!part)
+ return 0; /* No partitions found */
+
+ dev_warn(&dev->dev, "Device tree uses obsolete partition map binding\n");
+
+ nr_parts = plen / sizeof(part[0]);
+
+ info->parts = kzalloc(nr_parts * sizeof(*info->parts), GFP_KERNEL);
+ if (!info->parts)
+ return -ENOMEM;
- name = of_get_property(node, "partition-names", &plen);
+ names = of_get_property(dp, "partition-names", &plen);
- for (i = 0; i < retval; i++) {
- (*parts)[i].offset = *part++;
- (*parts)[i].size = *part & ~1;
- if (*part++ & 1) /* bit 0 set signifies read only partition */
- (*parts)[i].mask_flags = MTD_WRITEABLE;
+ for (i = 0; i < nr_parts; i++) {
+ info->parts[i].offset = part->offset;
+ info->parts[i].size = part->len & ~1;
+ if (part->len & 1) /* bit 0 set signifies read only partition */
+ info->parts[i].mask_flags = MTD_WRITEABLE;
- if (name != NULL && plen > 0) {
- int len = strlen(name) + 1;
+ if (names && (plen > 0)) {
+ int len = strlen(names) + 1;
- (*parts)[i].name = (char *)name;
+ info->parts[i].name = (char *)names;
plen -= len;
- name += len;
- } else
- (*parts)[i].name = "unnamed";
+ names += len;
+ } else {
+ info->parts[i].name = "unnamed";
+ }
+
+ part++;
}
-err:
- return retval;
+
+ return nr_parts;
}
-#endif
-static int of_physmap_remove(struct of_device *dev)
+static int __devinit parse_partitions(struct of_flash *info,
+ struct of_device *dev)
+{
+ const char *partname;
+ static const char *part_probe_types[]
+ = { "cmdlinepart", "RedBoot", NULL };
+ struct device_node *dp = dev->node, *pp;
+ int nr_parts, i;
+
+ /* First look for RedBoot table or partitions on the command
+ * line, these take precedence over device tree information */
+ nr_parts = parse_mtd_partitions(info->mtd, part_probe_types,
+ &info->parts, 0);
+ if (nr_parts > 0) {
+ add_mtd_partitions(info->mtd, info->parts, nr_parts);
+ return 0;
+ }
+
+ /* First count the subnodes */
+ nr_parts = 0;
+ for (pp = dp->child; pp; pp = pp->sibling)
+ nr_parts++;
+
+ if (nr_parts == 0)
+ return parse_obsolete_partitions(dev, info, dp);
+
+ info->parts = kzalloc(nr_parts * sizeof(*info->parts),
+ GFP_KERNEL);
+ if (!info->parts)
+ return -ENOMEM;
+
+ for (pp = dp->child, i = 0; pp; pp = pp->sibling, i++) {
+ const u32 *reg;
+ int len;
+
+ reg = of_get_property(pp, "reg", &len);
+ if (!reg || (len != 2*sizeof(u32))) {
+ dev_err(&dev->dev, "Invalid 'reg' on %s\n",
+ dp->full_name);
+ kfree(info->parts);
+ info->parts = NULL;
+ return -EINVAL;
+ }
+ info->parts[i].offset = reg[0];
+ info->parts[i].size = reg[1];
+
+ partname = of_get_property(pp, "label", &len);
+ if (!partname)
+ partname = of_get_property(pp, "name", &len);
+ info->parts[i].name = (char *)partname;
+
+ if (of_get_property(pp, "read-only", &len))
+ info->parts[i].mask_flags = MTD_WRITEABLE;
+ }
+
+ return nr_parts;
+}
+#else /* MTD_PARTITIONS */
+#define OF_FLASH_PARTS(info) (0)
+#define parse_partitions(info, dev) (0)
+#endif /* MTD_PARTITIONS */
+
+static int of_flash_remove(struct of_device *dev)
{
- struct physmap_flash_info *info;
+ struct of_flash *info;
info = dev_get_drvdata(&dev->dev);
- if (info == NULL)
+ if (!info)
return 0;
dev_set_drvdata(&dev->dev, NULL);
- if (info->mtd != NULL) {
-#ifdef CONFIG_MTD_PARTITIONS
- if (info->nr_parts) {
+ if (info->mtd) {
+ if (OF_FLASH_PARTS(info)) {
del_mtd_partitions(info->mtd);
- kfree(info->parts);
+ kfree(OF_FLASH_PARTS(info));
} else {
del_mtd_device(info->mtd);
}
-#else
- del_mtd_device(info->mtd);
-#endif
map_destroy(info->mtd);
}
- if (info->map.virt != NULL)
+ if (info->map.virt)
iounmap(info->map.virt);
- if (info->res != NULL) {
+ if (info->res) {
release_resource(info->res);
kfree(info->res);
}
@@ -115,48 +173,79 @@ static int of_physmap_remove(struct of_device *dev)
return 0;
}
-static int __devinit of_physmap_probe(struct of_device *dev, const struct of_device_id *match)
+/* Helper function to handle probing of the obsolete "direct-mapped"
+ * compatible binding, which has an extra "probe-type" property
+ * describing the type of flash probe necessary. */
+static struct mtd_info * __devinit obsolete_probe(struct of_device *dev,
+ struct map_info *map)
{
struct device_node *dp = dev->node;
- struct resource res;
- struct physmap_flash_info *info;
- const char **probe_type;
const char *of_probe;
+ struct mtd_info *mtd;
+ static const char *rom_probe_types[]
+ = { "cfi_probe", "jedec_probe", "map_rom"};
+ int i;
+
+ dev_warn(&dev->dev, "Device tree uses obsolete \"direct-mapped\" "
+ "flash binding\n");
+
+ of_probe = of_get_property(dp, "probe-type", NULL);
+ if (!of_probe) {
+ for (i = 0; i < ARRAY_SIZE(rom_probe_types); i++) {
+ mtd = do_map_probe(rom_probe_types[i], map);
+ if (mtd)
+ return mtd;
+ }
+ return NULL;
+ } else if (strcmp(of_probe, "CFI") == 0) {
+ return do_map_probe("cfi_probe", map);
+ } else if (strcmp(of_probe, "JEDEC") == 0) {
+ return do_map_probe("jedec_probe", map);
+ } else {
+ if (strcmp(of_probe, "ROM") != 0)
+ dev_warn(&dev->dev, "obsolete_probe: don't know probe "
+ "type '%s', mapping as rom\n", of_probe);
+ return do_map_probe("mtd_rom", map);
+ }
+}
+
+static int __devinit of_flash_probe(struct of_device *dev,
+ const struct of_device_id *match)
+{
+ struct device_node *dp = dev->node;
+ struct resource res;
+ struct of_flash *info;
+ const char *probe_type = match->data;
const u32 *width;
int err;
-
+ err = -ENXIO;
if (of_address_to_resource(dp, 0, &res)) {
- dev_err(&dev->dev, "Can't get the flash mapping!\n");
- err = -EINVAL;
+ dev_err(&dev->dev, "Can't get IO address from device tree\n");
goto err_out;
}
- dev_dbg(&dev->dev, "physmap flash device: %.8llx at %.8llx\n",
- (unsigned long long)res.end - res.start + 1,
- (unsigned long long)res.start);
+ dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n",
+ (unsigned long long)res.start, (unsigned long long)res.end);
- info = kzalloc(sizeof(struct physmap_flash_info), GFP_KERNEL);
- if (info == NULL) {
- err = -ENOMEM;
+ err = -ENOMEM;
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
goto err_out;
- }
memset(info, 0, sizeof(*info));
dev_set_drvdata(&dev->dev, info);
+ err = -EBUSY;
info->res = request_mem_region(res.start, res.end - res.start + 1,
- dev->dev.bus_id);
- if (info->res == NULL) {
- dev_err(&dev->dev, "Could not reserve memory region\n");
- err = -ENOMEM;
+ dev->dev.bus_id);
+ if (!info->res)
goto err_out;
- }
+ err = -ENXIO;
width = of_get_property(dp, "bank-width", NULL);
- if (width == NULL) {
- dev_err(&dev->dev, "Can't get the flash bank width!\n");
- err = -EINVAL;
+ if (!width) {
+ dev_err(&dev->dev, "Can't get bank width from device tree\n");
goto err_out;
}
@@ -165,91 +254,87 @@ static int __devinit of_physmap_probe(struct of_device *dev, const struct of_dev
info->map.size = res.end - res.start + 1;
info->map.bankwidth = *width;
+ err = -ENOMEM;
info->map.virt = ioremap(info->map.phys, info->map.size);
- if (info->map.virt == NULL) {
- dev_err(&dev->dev, "Failed to ioremap flash region\n");
- err = EIO;
+ if (!info->map.virt) {
+ dev_err(&dev->dev, "Failed to ioremap() flash region\n");
goto err_out;
}
simple_map_init(&info->map);
- of_probe = of_get_property(dp, "probe-type", NULL);
- if (of_probe == NULL) {
- probe_type = rom_probe_types;
- for (; info->mtd == NULL && *probe_type != NULL; probe_type++)
- info->mtd = do_map_probe(*probe_type, &info->map);
- } else if (!strcmp(of_probe, "CFI"))
- info->mtd = do_map_probe("cfi_probe", &info->map);
- else if (!strcmp(of_probe, "JEDEC"))
- info->mtd = do_map_probe("jedec_probe", &info->map);
- else {
- if (strcmp(of_probe, "ROM"))
- dev_dbg(&dev->dev, "map_probe: don't know probe type "
- "'%s', mapping as rom\n", of_probe);
- info->mtd = do_map_probe("mtd_rom", &info->map);
- }
- if (info->mtd == NULL) {
- dev_err(&dev->dev, "map_probe failed\n");
- err = -ENXIO;
+ if (probe_type)
+ info->mtd = do_map_probe(probe_type, &info->map);
+ else
+ info->mtd = obsolete_probe(dev, &info->map);
+
+ err = -ENXIO;
+ if (!info->mtd) {
+ dev_err(&dev->dev, "do_map_probe() failed\n");
goto err_out;
}
info->mtd->owner = THIS_MODULE;
-#ifdef CONFIG_MTD_PARTITIONS
- err = parse_mtd_partitions(info->mtd, part_probe_types, &info->parts, 0);
- if (err > 0) {
- add_mtd_partitions(info->mtd, info->parts, err);
- } else if ((err = parse_flash_partitions(dp, &info->parts)) > 0) {
- dev_info(&dev->dev, "Using OF partition information\n");
- add_mtd_partitions(info->mtd, info->parts, err);
- info->nr_parts = err;
- } else
-#endif
+ err = parse_partitions(info, dev);
+ if (err < 0)
+ goto err_out;
+
+ if (err > 0)
+ add_mtd_partitions(info->mtd, OF_FLASH_PARTS(info), err);
+ else
+ add_mtd_device(info->mtd);
- add_mtd_device(info->mtd);
return 0;
err_out:
- of_physmap_remove(dev);
+ of_flash_remove(dev);
return err;
-
- return 0;
-
-
}
-static struct of_device_id of_physmap_match[] = {
+static struct of_device_id of_flash_match[] = {
+ {
+ .compatible = "cfi-flash",
+ .data = (void *)"cfi_probe",
+ },
+ {
+ /* FIXME: JEDEC chips can't be safely and reliably
+ * probed, although the mtd code gets it right in
+ * practice most of the time. We should use the
+ * vendor and device ids specified by the binding to
+ * bypass the heuristic probe code, but the mtd layer
+ * provides, at present, no interface for doing so
+ * :(. */
+ .compatible = "jedec-flash",
+ .data = (void *)"jedec_probe",
+ },
{
.type = "rom",
.compatible = "direct-mapped"
},
{ },
};
+MODULE_DEVICE_TABLE(of, of_flash_match);
-MODULE_DEVICE_TABLE(of, of_physmap_match);
-
-
-static struct of_platform_driver of_physmap_flash_driver = {
- .name = "physmap-flash",
- .match_table = of_physmap_match,
- .probe = of_physmap_probe,
- .remove = of_physmap_remove,
+static struct of_platform_driver of_flash_driver = {
+ .name = "of-flash",
+ .match_table = of_flash_match,
+ .probe = of_flash_probe,
+ .remove = of_flash_remove,
};
-static int __init of_physmap_init(void)
+static int __init of_flash_init(void)
{
- return of_register_platform_driver(&of_physmap_flash_driver);
+ return of_register_platform_driver(&of_flash_driver);
}
-static void __exit of_physmap_exit(void)
+static void __exit of_flash_exit(void)
{
- of_unregister_platform_driver(&of_physmap_flash_driver);
+ of_unregister_platform_driver(&of_flash_driver);
}
-module_init(of_physmap_init);
-module_exit(of_physmap_exit);
+module_init(of_flash_init);
+module_exit(of_flash_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
-MODULE_DESCRIPTION("Configurable MTD map driver for OF");
+MODULE_DESCRIPTION("Device tree based MTD map driver");
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 9667dac383f..d00e7d41f6a 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -2919,7 +2919,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
test = in_be16(&ugeth->p_tx_glbl_pram->temoder);
/* Function code register value to be used later */
- function_code = QE_BMR_BYTE_ORDER_BO_MOT | UCC_FAST_FUNCTION_CODE_GBL;
+ function_code = UCC_BMR_BO_BE | UCC_BMR_GBL;
/* Required for QE */
/* function code register */
diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h
index aaeb9487798..4fb95b3af94 100644
--- a/drivers/net/ucc_geth.h
+++ b/drivers/net/ucc_geth.h
@@ -44,6 +44,7 @@
struct ucc_geth {
struct ucc_fast uccf;
+ u8 res0[0x100 - sizeof(struct ucc_fast)];
u32 maccfg1; /* mac configuration reg. 1 */
u32 maccfg2; /* mac configuration reg. 2 */
diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c
index 6c257b88ce5..df884f0ad8e 100644
--- a/drivers/net/ucc_geth_mii.c
+++ b/drivers/net/ucc_geth_mii.c
@@ -32,7 +32,6 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <asm/ocp.h>
#include <linux/crc32.h>
#include <linux/mii.h>
#include <linux/phy.h>
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 81b52b7cca2..d6ae38e55d0 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -986,6 +986,31 @@ config SERIAL_PMACZILOG
PowerMac machines.
Say Y or M if you want to be able to these serial ports.
+config SERIAL_PMACZILOG_TTYS
+ bool "Use ttySn device nodes for Zilog z85c30"
+ depends on SERIAL_PMACZILOG
+ help
+ The pmac_zilog driver for the z85C30 chip on many powermacs
+ historically used the device numbers for /dev/ttySn. The
+ 8250 serial port driver also uses these numbers, which means
+ the two drivers being unable to coexist; you could not use
+ both z85C30 and 8250 type ports at the same time.
+
+ If this option is not selected, the pmac_zilog driver will
+ use the device numbers allocated for /dev/ttyPZn. This allows
+ the pmac_zilog and 8250 drivers to co-exist, but may cause
+ existing userspace setups to break. Programs that need to
+ access the built-in serial ports on powermacs will need to
+ be reconfigured to use /dev/ttyPZn instead of /dev/ttySn.
+
+ If you enable this option, any z85c30 ports in the system will
+ be registered as ttyS0 onwards as in the past, and you will be
+ unable to use the 8250 module for PCMCIA or other 16C550-style
+ UARTs.
+
+ Say N unless you need the z85c30 ports on your powermac
+ to appear as /dev/ttySn.
+
config SERIAL_PMACZILOG_CONSOLE
bool "Console on PowerMac z85c30 serial port"
depends on SERIAL_PMACZILOG=y
diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h
index a8f894c7819..32b9737759c 100644
--- a/drivers/serial/cpm_uart/cpm_uart.h
+++ b/drivers/serial/cpm_uart/cpm_uart.h
@@ -56,21 +56,21 @@ struct uart_cpm_port {
u16 rx_fifosize;
u16 tx_nrfifos;
u16 tx_fifosize;
- smc_t *smcp;
- smc_uart_t *smcup;
- scc_t *sccp;
- scc_uart_t *sccup;
- volatile cbd_t *rx_bd_base;
- volatile cbd_t *rx_cur;
- volatile cbd_t *tx_bd_base;
- volatile cbd_t *tx_cur;
+ smc_t __iomem *smcp;
+ smc_uart_t __iomem *smcup;
+ scc_t __iomem *sccp;
+ scc_uart_t __iomem *sccup;
+ cbd_t __iomem *rx_bd_base;
+ cbd_t __iomem *rx_cur;
+ cbd_t __iomem *tx_bd_base;
+ cbd_t __iomem *tx_cur;
unsigned char *tx_buf;
unsigned char *rx_buf;
u32 flags;
void (*set_lineif)(struct uart_cpm_port *);
u8 brg;
uint dp_addr;
- void *mem_addr;
+ void *mem_addr;
dma_addr_t dma_addr;
u32 mem_size;
/* helpers */
@@ -80,14 +80,18 @@ struct uart_cpm_port {
int is_portb;
/* wait on close if needed */
int wait_closing;
+ /* value to combine with opcode to form cpm command */
+ u32 command;
};
+#ifndef CONFIG_PPC_CPM_NEW_BINDING
extern int cpm_uart_port_map[UART_NR];
+#endif
extern int cpm_uart_nr;
extern struct uart_cpm_port cpm_uart_ports[UART_NR];
/* these are located in their respective files */
-void cpm_line_cr_cmd(int line, int cmd);
+void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd);
int cpm_uart_init_portdesc(void);
int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con);
void cpm_uart_freebuf(struct uart_cpm_port *pinfo);
@@ -102,34 +106,36 @@ void scc4_lineif(struct uart_cpm_port *pinfo);
/*
virtual to phys transtalion
*/
-static inline unsigned long cpu2cpm_addr(void* addr, struct uart_cpm_port *pinfo)
+static inline unsigned long cpu2cpm_addr(void *addr,
+ struct uart_cpm_port *pinfo)
{
int offset;
u32 val = (u32)addr;
+ u32 mem = (u32)pinfo->mem_addr;
/* sane check */
- if (likely((val >= (u32)pinfo->mem_addr)) &&
- (val<((u32)pinfo->mem_addr + pinfo->mem_size))) {
- offset = val - (u32)pinfo->mem_addr;
- return pinfo->dma_addr+offset;
+ if (likely(val >= mem && val < mem + pinfo->mem_size)) {
+ offset = val - mem;
+ return pinfo->dma_addr + offset;
}
/* something nasty happened */
BUG();
return 0;
}
-static inline void *cpm2cpu_addr(unsigned long addr, struct uart_cpm_port *pinfo)
+static inline void *cpm2cpu_addr(unsigned long addr,
+ struct uart_cpm_port *pinfo)
{
int offset;
u32 val = addr;
+ u32 dma = (u32)pinfo->dma_addr;
/* sane check */
- if (likely((val >= pinfo->dma_addr) &&
- (val<(pinfo->dma_addr + pinfo->mem_size)))) {
- offset = val - (u32)pinfo->dma_addr;
- return (void*)(pinfo->mem_addr+offset);
+ if (likely(val >= dma && val < dma + pinfo->mem_size)) {
+ offset = val - dma;
+ return pinfo->mem_addr + offset;
}
/* something nasty happened */
BUG();
- return 0;
+ return NULL;
}
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index cefde58dbad..b5e4478de0e 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -10,7 +10,7 @@
* Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2)
* Pantelis Antoniou (panto@intracom.gr) (CPM1)
*
- * Copyright (C) 2004 Freescale Semiconductor, Inc.
+ * Copyright (C) 2004, 2007 Freescale Semiconductor, Inc.
* (C) 2004 Intracom, S.A.
* (C) 2005-2006 MontaVista Software, Inc.
* Vitaly Bordug <vbordug@ru.mvista.com>
@@ -47,6 +47,11 @@
#include <asm/irq.h>
#include <asm/delay.h>
#include <asm/fs_pd.h>
+#include <asm/udbg.h>
+
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+#include <linux/of_platform.h>
+#endif
#if defined(CONFIG_SERIAL_CPM_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@@ -57,12 +62,6 @@
#include "cpm_uart.h"
-/***********************************************************************/
-
-/* Track which ports are configured as uarts */
-int cpm_uart_port_map[UART_NR];
-/* How many ports did we config as uarts */
-int cpm_uart_nr = 0;
/**************************************************************/
@@ -73,6 +72,11 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo);
/**************************************************************/
+#ifndef CONFIG_PPC_CPM_NEW_BINDING
+/* Track which ports are configured as uarts */
+int cpm_uart_port_map[UART_NR];
+/* How many ports did we config as uarts */
+int cpm_uart_nr;
/* Place-holder for board-specific stuff */
struct platform_device* __attribute__ ((weak)) __init
@@ -119,6 +123,7 @@ static int cpm_uart_id2nr(int id)
/* not found or invalid argument */
return -1;
}
+#endif
/*
* Check, if transmit buffers are processed
@@ -126,14 +131,14 @@ static int cpm_uart_id2nr(int id)
static unsigned int cpm_uart_tx_empty(struct uart_port *port)
{
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
- volatile cbd_t *bdp = pinfo->tx_bd_base;
+ cbd_t __iomem *bdp = pinfo->tx_bd_base;
int ret = 0;
while (1) {
- if (bdp->cbd_sc & BD_SC_READY)
+ if (in_be16(&bdp->cbd_sc) & BD_SC_READY)
break;
- if (bdp->cbd_sc & BD_SC_WRAP) {
+ if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP) {
ret = TIOCSER_TEMT;
break;
}
@@ -162,15 +167,15 @@ static unsigned int cpm_uart_get_mctrl(struct uart_port *port)
static void cpm_uart_stop_tx(struct uart_port *port)
{
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
- volatile smc_t *smcp = pinfo->smcp;
- volatile scc_t *sccp = pinfo->sccp;
+ smc_t __iomem *smcp = pinfo->smcp;
+ scc_t __iomem *sccp = pinfo->sccp;
pr_debug("CPM uart[%d]:stop tx\n", port->line);
if (IS_SMC(pinfo))
- smcp->smc_smcm &= ~SMCM_TX;
+ clrbits8(&smcp->smc_smcm, SMCM_TX);
else
- sccp->scc_sccm &= ~UART_SCCM_TX;
+ clrbits16(&sccp->scc_sccm, UART_SCCM_TX);
}
/*
@@ -179,24 +184,24 @@ static void cpm_uart_stop_tx(struct uart_port *port)
static void cpm_uart_start_tx(struct uart_port *port)
{
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
- volatile smc_t *smcp = pinfo->smcp;
- volatile scc_t *sccp = pinfo->sccp;
+ smc_t __iomem *smcp = pinfo->smcp;
+ scc_t __iomem *sccp = pinfo->sccp;
pr_debug("CPM uart[%d]:start tx\n", port->line);
if (IS_SMC(pinfo)) {
- if (smcp->smc_smcm & SMCM_TX)
+ if (in_8(&smcp->smc_smcm) & SMCM_TX)
return;
} else {
- if (sccp->scc_sccm & UART_SCCM_TX)
+ if (in_be16(&sccp->scc_sccm) & UART_SCCM_TX)
return;
}
if (cpm_uart_tx_pump(port) != 0) {
if (IS_SMC(pinfo)) {
- smcp->smc_smcm |= SMCM_TX;
+ setbits8(&smcp->smc_smcm, SMCM_TX);
} else {
- sccp->scc_sccm |= UART_SCCM_TX;
+ setbits16(&sccp->scc_sccm, UART_SCCM_TX);
}
}
}
@@ -207,15 +212,15 @@ static void cpm_uart_start_tx(struct uart_port *port)
static void cpm_uart_stop_rx(struct uart_port *port)
{
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
- volatile smc_t *smcp = pinfo->smcp;
- volatile scc_t *sccp = pinfo->sccp;
+ smc_t __iomem *smcp = pinfo->smcp;
+ scc_t __iomem *sccp = pinfo->sccp;
pr_debug("CPM uart[%d]:stop rx\n", port->line);
if (IS_SMC(pinfo))
- smcp->smc_smcm &= ~SMCM_RX;
+ clrbits8(&smcp->smc_smcm, SMCM_RX);
else
- sccp->scc_sccm &= ~UART_SCCM_RX;
+ clrbits16(&sccp->scc_sccm, UART_SCCM_RX);
}
/*
@@ -232,15 +237,14 @@ static void cpm_uart_enable_ms(struct uart_port *port)
static void cpm_uart_break_ctl(struct uart_port *port, int break_state)
{
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
- int line = pinfo - cpm_uart_ports;
pr_debug("CPM uart[%d]:break ctrl, break_state: %d\n", port->line,
break_state);
if (break_state)
- cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
+ cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);
else
- cpm_line_cr_cmd(line, CPM_CR_RESTART_TX);
+ cpm_line_cr_cmd(pinfo, CPM_CR_RESTART_TX);
}
/*
@@ -259,10 +263,11 @@ static void cpm_uart_int_tx(struct uart_port *port)
static void cpm_uart_int_rx(struct uart_port *port)
{
int i;
- unsigned char ch, *cp;
+ unsigned char ch;
+ u8 *cp;
struct tty_struct *tty = port->info->tty;
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
- volatile cbd_t *bdp;
+ cbd_t __iomem *bdp;
u16 status;
unsigned int flg;
@@ -274,13 +279,13 @@ static void cpm_uart_int_rx(struct uart_port *port)
bdp = pinfo->rx_cur;
for (;;) {
/* get status */
- status = bdp->cbd_sc;
+ status = in_be16(&bdp->cbd_sc);
/* If this one is empty, return happy */
if (status & BD_SC_EMPTY)
break;
/* get number of characters, and check spce in flip-buffer */
- i = bdp->cbd_datlen;
+ i = in_be16(&bdp->cbd_datlen);
/* If we have not enough room in tty flip buffer, then we try
* later, which will be the next rx-interrupt or a timeout
@@ -291,7 +296,7 @@ static void cpm_uart_int_rx(struct uart_port *port)
}
/* get pointer */
- cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
+ cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
/* loop through the buffer */
while (i-- > 0) {
@@ -311,10 +316,11 @@ static void cpm_uart_int_rx(struct uart_port *port)
} /* End while (i--) */
/* This BD is ready to be used again. Clear status. get next */
- bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID);
- bdp->cbd_sc |= BD_SC_EMPTY;
+ clrbits16(&bdp->cbd_sc, BD_SC_BR | BD_SC_FR | BD_SC_PR |
+ BD_SC_OV | BD_SC_ID);
+ setbits16(&bdp->cbd_sc, BD_SC_EMPTY);
- if (bdp->cbd_sc & BD_SC_WRAP)
+ if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
bdp = pinfo->rx_bd_base;
else
bdp++;
@@ -322,7 +328,7 @@ static void cpm_uart_int_rx(struct uart_port *port)
} /* End for (;;) */
/* Write back buffer pointer */
- pinfo->rx_cur = (volatile cbd_t *) bdp;
+ pinfo->rx_cur = bdp;
/* activate BH processing */
tty_flip_buffer_push(tty);
@@ -376,14 +382,14 @@ static irqreturn_t cpm_uart_int(int irq, void *data)
u8 events;
struct uart_port *port = (struct uart_port *)data;
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
- volatile smc_t *smcp = pinfo->smcp;
- volatile scc_t *sccp = pinfo->sccp;
+ smc_t __iomem *smcp = pinfo->smcp;
+ scc_t __iomem *sccp = pinfo->sccp;
pr_debug("CPM uart[%d]:IRQ\n", port->line);
if (IS_SMC(pinfo)) {
- events = smcp->smc_smce;
- smcp->smc_smce = events;
+ events = in_8(&smcp->smc_smce);
+ out_8(&smcp->smc_smce, events);
if (events & SMCM_BRKE)
uart_handle_break(port);
if (events & SMCM_RX)
@@ -391,8 +397,8 @@ static irqreturn_t cpm_uart_int(int irq, void *data)
if (events & SMCM_TX)
cpm_uart_int_tx(port);
} else {
- events = sccp->scc_scce;
- sccp->scc_scce = events;
+ events = in_be16(&sccp->scc_scce);
+ out_be16(&sccp->scc_scce, events);
if (events & UART_SCCM_BRKE)
uart_handle_break(port);
if (events & UART_SCCM_RX)
@@ -407,7 +413,6 @@ static int cpm_uart_startup(struct uart_port *port)
{
int retval;
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
- int line = pinfo - cpm_uart_ports;
pr_debug("CPM uart[%d]:startup\n", port->line);
@@ -418,15 +423,15 @@ static int cpm_uart_startup(struct uart_port *port)
/* Startup rx-int */
if (IS_SMC(pinfo)) {
- pinfo->smcp->smc_smcm |= SMCM_RX;
- pinfo->smcp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN);
+ setbits8(&pinfo->smcp->smc_smcm, SMCM_RX);
+ setbits16(&pinfo->smcp->smc_smcmr, (SMCMR_REN | SMCMR_TEN));
} else {
- pinfo->sccp->scc_sccm |= UART_SCCM_RX;
- pinfo->sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+ setbits16(&pinfo->sccp->scc_sccm, UART_SCCM_RX);
+ setbits32(&pinfo->sccp->scc_gsmrl, (SCC_GSMRL_ENR | SCC_GSMRL_ENT));
}
if (!(pinfo->flags & FLAG_CONSOLE))
- cpm_line_cr_cmd(line,CPM_CR_INIT_TRX);
+ cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX);
return 0;
}
@@ -442,7 +447,6 @@ inline void cpm_uart_wait_until_send(struct uart_cpm_port *pinfo)
static void cpm_uart_shutdown(struct uart_port *port)
{
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
- int line = pinfo - cpm_uart_ports;
pr_debug("CPM uart[%d]:shutdown\n", port->line);
@@ -462,20 +466,20 @@ static void cpm_uart_shutdown(struct uart_port *port)
/* Stop uarts */
if (IS_SMC(pinfo)) {
- volatile smc_t *smcp = pinfo->smcp;
- smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
- smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
+ smc_t __iomem *smcp = pinfo->smcp;
+ clrbits16(&smcp->smc_smcmr, SMCMR_REN | SMCMR_TEN);
+ clrbits8(&smcp->smc_smcm, SMCM_RX | SMCM_TX);
} else {
- volatile scc_t *sccp = pinfo->sccp;
- sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
- sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
+ scc_t __iomem *sccp = pinfo->sccp;
+ clrbits32(&sccp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+ clrbits16(&sccp->scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
}
/* Shut them really down and reinit buffer descriptors */
if (IS_SMC(pinfo))
- cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
+ cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);
else
- cpm_line_cr_cmd(line, CPM_CR_GRA_STOP_TX);
+ cpm_line_cr_cmd(pinfo, CPM_CR_GRA_STOP_TX);
cpm_uart_initbd(pinfo);
}
@@ -490,8 +494,8 @@ static void cpm_uart_set_termios(struct uart_port *port,
u16 cval, scval, prev_mode;
int bits, sbits;
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
- volatile smc_t *smcp = pinfo->smcp;
- volatile scc_t *sccp = pinfo->sccp;
+ smc_t __iomem *smcp = pinfo->smcp;
+ scc_t __iomem *sccp = pinfo->sccp;
pr_debug("CPM uart[%d]:set_termios\n", port->line);
@@ -586,16 +590,15 @@ static void cpm_uart_set_termios(struct uart_port *port,
* enables, because we want to put them back if they were
* present.
*/
- prev_mode = smcp->smc_smcmr;
- smcp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART;
- smcp->smc_smcmr |= (prev_mode & (SMCMR_REN | SMCMR_TEN));
+ prev_mode = in_be16(&smcp->smc_smcmr);
+ out_be16(&smcp->smc_smcmr, smcr_mk_clen(bits) | cval | SMCMR_SM_UART);
+ setbits16(&smcp->smc_smcmr, (prev_mode & (SMCMR_REN | SMCMR_TEN)));
} else {
- sccp->scc_psmr = (sbits << 12) | scval;
+ out_be16(&sccp->scc_psmr, (sbits << 12) | scval);
}
cpm_set_brg(pinfo->brg - 1, baud);
spin_unlock_irqrestore(&port->lock, flags);
-
}
static const char *cpm_uart_type(struct uart_port *port)
@@ -629,8 +632,8 @@ static int cpm_uart_verify_port(struct uart_port *port,
*/
static int cpm_uart_tx_pump(struct uart_port *port)
{
- volatile cbd_t *bdp;
- unsigned char *p;
+ cbd_t __iomem *bdp;
+ u8 *p;
int count;
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
struct circ_buf *xmit = &port->info->xmit;
@@ -640,13 +643,14 @@ static int cpm_uart_tx_pump(struct uart_port *port)
/* Pick next descriptor and fill from buffer */
bdp = pinfo->tx_cur;
- p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
+ p = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
*p++ = port->x_char;
- bdp->cbd_datlen = 1;
- bdp->cbd_sc |= BD_SC_READY;
+
+ out_be16(&bdp->cbd_datlen, 1);
+ setbits16(&bdp->cbd_sc, BD_SC_READY);
/* Get next BD. */
- if (bdp->cbd_sc & BD_SC_WRAP)
+ if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
bdp = pinfo->tx_bd_base;
else
bdp++;
@@ -665,9 +669,10 @@ static int cpm_uart_tx_pump(struct uart_port *port)
/* Pick next descriptor and fill from buffer */
bdp = pinfo->tx_cur;
- while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) {
+ while (!(in_be16(&bdp->cbd_sc) & BD_SC_READY) &&
+ xmit->tail != xmit->head) {
count = 0;
- p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
+ p = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
while (count < pinfo->tx_fifosize) {
*p++ = xmit->buf[xmit->tail];
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -676,11 +681,10 @@ static int cpm_uart_tx_pump(struct uart_port *port)
if (xmit->head == xmit->tail)
break;
}
- bdp->cbd_datlen = count;
- bdp->cbd_sc |= BD_SC_READY;
- eieio();
+ out_be16(&bdp->cbd_datlen, count);
+ setbits16(&bdp->cbd_sc, BD_SC_READY);
/* Get next BD. */
- if (bdp->cbd_sc & BD_SC_WRAP)
+ if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
bdp = pinfo->tx_bd_base;
else
bdp++;
@@ -705,7 +709,7 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
{
int i;
u8 *mem_addr;
- volatile cbd_t *bdp;
+ cbd_t __iomem *bdp;
pr_debug("CPM uart[%d]:initbd\n", pinfo->port.line);
@@ -716,13 +720,13 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
mem_addr = pinfo->mem_addr;
bdp = pinfo->rx_cur = pinfo->rx_bd_base;
for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) {
- bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
- bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
+ out_be32(&bdp->cbd_bufaddr, cpu2cpm_addr(mem_addr, pinfo));
+ out_be16(&bdp->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT);
mem_addr += pinfo->rx_fifosize;
}
- bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
- bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
+ out_be32(&bdp->cbd_bufaddr, cpu2cpm_addr(mem_addr, pinfo));
+ out_be16(&bdp->cbd_sc, BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT);
/* Set the physical address of the host memory
* buffers in the buffer descriptors, and the
@@ -731,20 +735,19 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize);
bdp = pinfo->tx_cur = pinfo->tx_bd_base;
for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) {
- bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
- bdp->cbd_sc = BD_SC_INTRPT;
+ out_be32(&bdp->cbd_bufaddr, cpu2cpm_addr(mem_addr, pinfo));
+ out_be16(&bdp->cbd_sc, BD_SC_INTRPT);
mem_addr += pinfo->tx_fifosize;
}
- bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
- bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT;
+ out_be32(&bdp->cbd_bufaddr, cpu2cpm_addr(mem_addr, pinfo));
+ out_be16(&bdp->cbd_sc, BD_SC_WRAP | BD_SC_INTRPT);
}
static void cpm_uart_init_scc(struct uart_cpm_port *pinfo)
{
- int line = pinfo - cpm_uart_ports;
- volatile scc_t *scp;
- volatile scc_uart_t *sup;
+ scc_t __iomem *scp;
+ scc_uart_t __iomem *sup;
pr_debug("CPM uart[%d]:init_scc\n", pinfo->port.line);
@@ -752,8 +755,10 @@ static void cpm_uart_init_scc(struct uart_cpm_port *pinfo)
sup = pinfo->sccup;
/* Store address */
- pinfo->sccup->scc_genscc.scc_rbase = (unsigned char *)pinfo->rx_bd_base - DPRAM_BASE;
- pinfo->sccup->scc_genscc.scc_tbase = (unsigned char *)pinfo->tx_bd_base - DPRAM_BASE;
+ out_be16(&pinfo->sccup->scc_genscc.scc_rbase,
+ (u8 __iomem *)pinfo->rx_bd_base - DPRAM_BASE);
+ out_be16(&pinfo->sccup->scc_genscc.scc_tbase,
+ (u8 __iomem *)pinfo->tx_bd_base - DPRAM_BASE);
/* Set up the uart parameters in the
* parameter ram.
@@ -761,51 +766,50 @@ static void cpm_uart_init_scc(struct uart_cpm_port *pinfo)
cpm_set_scc_fcr(sup);
- sup->scc_genscc.scc_mrblr = pinfo->rx_fifosize;
- sup->scc_maxidl = pinfo->rx_fifosize;
- sup->scc_brkcr = 1;
- sup->scc_parec = 0;
- sup->scc_frmec = 0;
- sup->scc_nosec = 0;
- sup->scc_brkec = 0;
- sup->scc_uaddr1 = 0;
- sup->scc_uaddr2 = 0;
- sup->scc_toseq = 0;
- sup->scc_char1 = 0x8000;
- sup->scc_char2 = 0x8000;
- sup->scc_char3 = 0x8000;
- sup->scc_char4 = 0x8000;
- sup->scc_char5 = 0x8000;
- sup->scc_char6 = 0x8000;
- sup->scc_char7 = 0x8000;
- sup->scc_char8 = 0x8000;
- sup->scc_rccm = 0xc0ff;
+ out_be16(&sup->scc_genscc.scc_mrblr, pinfo->rx_fifosize);
+ out_be16(&sup->scc_maxidl, pinfo->rx_fifosize);
+ out_be16(&sup->scc_brkcr, 1);
+ out_be16(&sup->scc_parec, 0);
+ out_be16(&sup->scc_frmec, 0);
+ out_be16(&sup->scc_nosec, 0);
+ out_be16(&sup->scc_brkec, 0);
+ out_be16(&sup->scc_uaddr1, 0);
+ out_be16(&sup->scc_uaddr2, 0);
+ out_be16(&sup->scc_toseq, 0);
+ out_be16(&sup->scc_char1, 0x8000);
+ out_be16(&sup->scc_char2, 0x8000);
+ out_be16(&sup->scc_char3, 0x8000);
+ out_be16(&sup->scc_char4, 0x8000);
+ out_be16(&sup->scc_char5, 0x8000);
+ out_be16(&sup->scc_char6, 0x8000);
+ out_be16(&sup->scc_char7, 0x8000);
+ out_be16(&sup->scc_char8, 0x8000);
+ out_be16(&sup->scc_rccm, 0xc0ff);
/* Send the CPM an initialize command.
*/
- cpm_line_cr_cmd(line, CPM_CR_INIT_TRX);
+ cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX);
/* Set UART mode, 8 bit, no parity, one stop.
* Enable receive and transmit.
*/
- scp->scc_gsmrh = 0;
- scp->scc_gsmrl =
- (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
+ out_be32(&scp->scc_gsmrh, 0);
+ out_be32(&scp->scc_gsmrl,
+ SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
/* Enable rx interrupts and clear all pending events. */
- scp->scc_sccm = 0;
- scp->scc_scce = 0xffff;
- scp->scc_dsr = 0x7e7e;
- scp->scc_psmr = 0x3000;
+ out_be16(&scp->scc_sccm, 0);
+ out_be16(&scp->scc_scce, 0xffff);
+ out_be16(&scp->scc_dsr, 0x7e7e);
+ out_be16(&scp->scc_psmr, 0x3000);
- scp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+ setbits32(&scp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
}
static void cpm_uart_init_smc(struct uart_cpm_port *pinfo)
{
- int line = pinfo - cpm_uart_ports;
- volatile smc_t *sp;
- volatile smc_uart_t *up;
+ smc_t __iomem *sp;
+ smc_uart_t __iomem *up;
pr_debug("CPM uart[%d]:init_smc\n", pinfo->port.line);
@@ -813,19 +817,21 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo)
up = pinfo->smcup;
/* Store address */
- pinfo->smcup->smc_rbase = (u_char *)pinfo->rx_bd_base - DPRAM_BASE;
- pinfo->smcup->smc_tbase = (u_char *)pinfo->tx_bd_base - DPRAM_BASE;
+ out_be16(&pinfo->smcup->smc_rbase,
+ (u8 __iomem *)pinfo->rx_bd_base - DPRAM_BASE);
+ out_be16(&pinfo->smcup->smc_tbase,
+ (u8 __iomem *)pinfo->tx_bd_base - DPRAM_BASE);
/*
* In case SMC1 is being relocated...
*/
#if defined (CONFIG_I2C_SPI_SMC1_UCODE_PATCH)
- up->smc_rbptr = pinfo->smcup->smc_rbase;
- up->smc_tbptr = pinfo->smcup->smc_tbase;
- up->smc_rstate = 0;
- up->smc_tstate = 0;
- up->smc_brkcr = 1; /* number of break chars */
- up->smc_brkec = 0;
+ out_be16(&up->smc_rbptr, in_be16(&pinfo->smcup->smc_rbase));
+ out_be16(&up->smc_tbptr, in_be16(&pinfo->smcup->smc_tbase));
+ out_be32(&up->smc_rstate, 0);
+ out_be32(&up->smc_tstate, 0);
+ out_be16(&up->smc_brkcr, 1); /* number of break chars */
+ out_be16(&up->smc_brkec, 0);
#endif
/* Set up the uart parameters in the
@@ -834,24 +840,24 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo)
cpm_set_smc_fcr(up);
/* Using idle charater time requires some additional tuning. */
- up->smc_mrblr = pinfo->rx_fifosize;
- up->smc_maxidl = pinfo->rx_fifosize;
- up->smc_brklen = 0;
- up->smc_brkec = 0;
- up->smc_brkcr = 1;
+ out_be16(&up->smc_mrblr, pinfo->rx_fifosize);
+ out_be16(&up->smc_maxidl, pinfo->rx_fifosize);
+ out_be16(&up->smc_brklen, 0);
+ out_be16(&up->smc_brkec, 0);
+ out_be16(&up->smc_brkcr, 1);
- cpm_line_cr_cmd(line, CPM_CR_INIT_TRX);
+ cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX);
/* Set UART mode, 8 bit, no parity, one stop.
* Enable receive and transmit.
*/
- sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+ out_be16(&sp->smc_smcmr, smcr_mk_clen(9) | SMCMR_SM_UART);
/* Enable only rx interrupts clear all pending events. */
- sp->smc_smcm = 0;
- sp->smc_smce = 0xff;
+ out_8(&sp->smc_smcm, 0);
+ out_8(&sp->smc_smce, 0xff);
- sp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN);
+ setbits16(&sp->smc_smcmr, SMCMR_REN | SMCMR_TEN);
}
/*
@@ -869,11 +875,11 @@ static int cpm_uart_request_port(struct uart_port *port)
return 0;
if (IS_SMC(pinfo)) {
- pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
- pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+ clrbits8(&pinfo->smcp->smc_smcm, SMCM_RX | SMCM_TX);
+ clrbits16(&pinfo->smcp->smc_smcmr, SMCMR_REN | SMCMR_TEN);
} else {
- pinfo->sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
- pinfo->sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+ clrbits16(&pinfo->sccp->scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+ clrbits32(&pinfo->sccp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
}
ret = cpm_uart_allocbuf(pinfo, 0);
@@ -929,6 +935,86 @@ static struct uart_ops cpm_uart_pops = {
.verify_port = cpm_uart_verify_port,
};
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+struct uart_cpm_port cpm_uart_ports[UART_NR];
+
+static int cpm_uart_init_port(struct device_node *np,
+ struct uart_cpm_port *pinfo)
+{
+ const u32 *data;
+ void __iomem *mem, *pram;
+ int len;
+ int ret;
+
+ data = of_get_property(np, "fsl,cpm-brg", &len);
+ if (!data || len != 4) {
+ printk(KERN_ERR "CPM UART %s has no/invalid "
+ "fsl,cpm-brg property.\n", np->name);
+ return -EINVAL;
+ }
+ pinfo->brg = *data;
+
+ data = of_get_property(np, "fsl,cpm-command", &len);
+ if (!data || len != 4) {
+ printk(KERN_ERR "CPM UART %s has no/invalid "
+ "fsl,cpm-command property.\n", np->name);
+ return -EINVAL;
+ }
+ pinfo->command = *data;
+
+ mem = of_iomap(np, 0);
+ if (!mem)
+ return -ENOMEM;
+
+ pram = of_iomap(np, 1);
+ if (!pram) {
+ ret = -ENOMEM;
+ goto out_mem;
+ }
+
+ if (of_device_is_compatible(np, "fsl,cpm1-scc-uart") ||
+ of_device_is_compatible(np, "fsl,cpm2-scc-uart")) {
+ pinfo->sccp = mem;
+ pinfo->sccup = pram;
+ } else if (of_device_is_compatible(np, "fsl,cpm1-smc-uart") ||
+ of_device_is_compatible(np, "fsl,cpm2-smc-uart")) {
+ pinfo->flags |= FLAG_SMC;
+ pinfo->smcp = mem;
+ pinfo->smcup = pram;
+ } else {
+ ret = -ENODEV;
+ goto out_pram;
+ }
+
+ pinfo->tx_nrfifos = TX_NUM_FIFO;
+ pinfo->tx_fifosize = TX_BUF_SIZE;
+ pinfo->rx_nrfifos = RX_NUM_FIFO;
+ pinfo->rx_fifosize = RX_BUF_SIZE;
+
+ pinfo->port.uartclk = ppc_proc_freq;
+ pinfo->port.mapbase = (unsigned long)mem;
+ pinfo->port.type = PORT_CPM;
+ pinfo->port.ops = &cpm_uart_pops,
+ pinfo->port.iotype = UPIO_MEM;
+ spin_lock_init(&pinfo->port.lock);
+
+ pinfo->port.irq = of_irq_to_resource(np, 0, NULL);
+ if (pinfo->port.irq == NO_IRQ) {
+ ret = -EINVAL;
+ goto out_pram;
+ }
+
+ return cpm_uart_request_port(&pinfo->port);
+
+out_pram:
+ iounmap(pram);
+out_mem:
+ iounmap(mem);
+ return ret;
+}
+
+#else
+
struct uart_cpm_port cpm_uart_ports[UART_NR] = {
[UART_SMC1] = {
.port = {
@@ -1072,6 +1158,7 @@ int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con)
return 0;
}
+#endif
#ifdef CONFIG_SERIAL_CPM_CONSOLE
/*
@@ -1083,11 +1170,15 @@ int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con)
static void cpm_uart_console_write(struct console *co, const char *s,
u_int count)
{
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+ struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index];
+#else
struct uart_cpm_port *pinfo =
&cpm_uart_ports[cpm_uart_port_map[co->index]];
+#endif
unsigned int i;
- volatile cbd_t *bdp, *bdbase;
- volatile unsigned char *cp;
+ cbd_t __iomem *bdp, *bdbase;
+ unsigned char *cp;
/* Get the address of the host memory buffer.
*/
@@ -1105,37 +1196,36 @@ static void cpm_uart_console_write(struct console *co, const char *s,
* Ready indicates output is ready, and xmt is doing
* that, not that it is ready for us to send.
*/
- while ((bdp->cbd_sc & BD_SC_READY) != 0)
+ while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
;
/* Send the character out.
* If the buffer address is in the CPM DPRAM, don't
* convert it.
*/
- cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
-
+ cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
*cp = *s;
- bdp->cbd_datlen = 1;
- bdp->cbd_sc |= BD_SC_READY;
+ out_be16(&bdp->cbd_datlen, 1);
+ setbits16(&bdp->cbd_sc, BD_SC_READY);
- if (bdp->cbd_sc & BD_SC_WRAP)
+ if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
bdp = bdbase;
else
bdp++;
/* if a LF, also do CR... */
if (*s == 10) {
- while ((bdp->cbd_sc & BD_SC_READY) != 0)
+ while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
;
- cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
-
+ cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
*cp = 13;
- bdp->cbd_datlen = 1;
- bdp->cbd_sc |= BD_SC_READY;
- if (bdp->cbd_sc & BD_SC_WRAP)
+ out_be16(&bdp->cbd_datlen, 1);
+ setbits16(&bdp->cbd_sc, BD_SC_READY);
+
+ if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
bdp = bdbase;
else
bdp++;
@@ -1146,22 +1236,56 @@ static void cpm_uart_console_write(struct console *co, const char *s,
* Finally, Wait for transmitter & holding register to empty
* and restore the IER
*/
- while ((bdp->cbd_sc & BD_SC_READY) != 0)
+ while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
;
- pinfo->tx_cur = (volatile cbd_t *) bdp;
+ pinfo->tx_cur = bdp;
}
static int __init cpm_uart_console_setup(struct console *co, char *options)
{
- struct uart_port *port;
- struct uart_cpm_port *pinfo;
int baud = 38400;
int bits = 8;
int parity = 'n';
int flow = 'n';
int ret;
+ struct uart_cpm_port *pinfo;
+ struct uart_port *port;
+
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+ struct device_node *np = NULL;
+ int i = 0;
+
+ if (co->index >= UART_NR) {
+ printk(KERN_ERR "cpm_uart: console index %d too high\n",
+ co->index);
+ return -ENODEV;
+ }
+
+ do {
+ np = of_find_node_by_type(np, "serial");
+ if (!np)
+ return -ENODEV;
+
+ if (!of_device_is_compatible(np, "fsl,cpm1-smc-uart") &&
+ !of_device_is_compatible(np, "fsl,cpm1-scc-uart") &&
+ !of_device_is_compatible(np, "fsl,cpm2-smc-uart") &&
+ !of_device_is_compatible(np, "fsl,cpm2-scc-uart"))
+ i--;
+ } while (i++ != co->index);
+
+ pinfo = &cpm_uart_ports[co->index];
+
+ pinfo->flags |= FLAG_CONSOLE;
+ port = &pinfo->port;
+
+ ret = cpm_uart_init_port(np, pinfo);
+ of_node_put(np);
+ if (ret)
+ return ret;
+
+#else
struct fs_uart_platform_info *pdata;
struct platform_device* pdev = early_uart_get_pdev(co->index);
@@ -1188,6 +1312,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
}
pinfo->flags |= FLAG_CONSOLE;
+#endif
if (options) {
uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -1196,12 +1321,18 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
baud = 9600;
}
+#ifdef CONFIG_PPC_EARLY_DEBUG_CPM
+ udbg_putc = NULL;
+#endif
+
+ cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);
+
if (IS_SMC(pinfo)) {
- pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
- pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+ clrbits8(&pinfo->smcp->smc_smcm, SMCM_RX | SMCM_TX);
+ clrbits16(&pinfo->smcp->smc_smcmr, SMCMR_REN | SMCMR_TEN);
} else {
- pinfo->sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
- pinfo->sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+ clrbits16(&pinfo->sccp->scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+ clrbits32(&pinfo->sccp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
}
ret = cpm_uart_allocbuf(pinfo, 1);
@@ -1217,6 +1348,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
cpm_uart_init_scc(pinfo);
uart_set_options(port, co, baud, parity, bits, flow);
+ cpm_line_cr_cmd(pinfo, CPM_CR_RESTART_TX);
return 0;
}
@@ -1232,7 +1364,7 @@ static struct console cpm_scc_uart_console = {
.data = &cpm_reg,
};
-int __init cpm_uart_console_init(void)
+static int __init cpm_uart_console_init(void)
{
register_console(&cpm_scc_uart_console);
return 0;
@@ -1252,7 +1384,81 @@ static struct uart_driver cpm_reg = {
.major = SERIAL_CPM_MAJOR,
.minor = SERIAL_CPM_MINOR,
.cons = CPM_UART_CONSOLE,
+ .nr = UART_NR,
};
+
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+static int probe_index;
+
+static int __devinit cpm_uart_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ int index = probe_index++;
+ struct uart_cpm_port *pinfo = &cpm_uart_ports[index];
+ int ret;
+
+ pinfo->port.line = index;
+
+ if (index >= UART_NR)
+ return -ENODEV;
+
+ dev_set_drvdata(&ofdev->dev, pinfo);
+
+ ret = cpm_uart_init_port(ofdev->node, pinfo);
+ if (ret)
+ return ret;
+
+ return uart_add_one_port(&cpm_reg, &pinfo->port);
+}
+
+static int __devexit cpm_uart_remove(struct of_device *ofdev)
+{
+ struct uart_cpm_port *pinfo = dev_get_drvdata(&ofdev->dev);
+ return uart_remove_one_port(&cpm_reg, &pinfo->port);
+}
+
+static struct of_device_id cpm_uart_match[] = {
+ {
+ .compatible = "fsl,cpm1-smc-uart",
+ },
+ {
+ .compatible = "fsl,cpm1-scc-uart",
+ },
+ {
+ .compatible = "fsl,cpm2-smc-uart",
+ },
+ {
+ .compatible = "fsl,cpm2-scc-uart",
+ },
+ {}
+};
+
+static struct of_platform_driver cpm_uart_driver = {
+ .name = "cpm_uart",
+ .match_table = cpm_uart_match,
+ .probe = cpm_uart_probe,
+ .remove = cpm_uart_remove,
+ };
+
+static int __init cpm_uart_init(void)
+{
+ int ret = uart_register_driver(&cpm_reg);
+ if (ret)
+ return ret;
+
+ ret = of_register_platform_driver(&cpm_uart_driver);
+ if (ret)
+ uart_unregister_driver(&cpm_reg);
+
+ return ret;
+}
+
+static void __exit cpm_uart_exit(void)
+{
+ of_unregister_platform_driver(&cpm_uart_driver);
+ uart_unregister_driver(&cpm_reg);
+}
+#else
static int cpm_uart_drv_probe(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -1380,6 +1586,7 @@ static void __exit cpm_uart_exit(void)
driver_unregister(&cpm_smc_uart_driver);
uart_unregister_driver(&cpm_reg);
}
+#endif
module_init(cpm_uart_init);
module_exit(cpm_uart_exit);
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
index 8c6324ed020..52fb044bb79 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
@@ -49,9 +49,20 @@
/**************************************************************/
-void cpm_line_cr_cmd(int line, int cmd)
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
+{
+ u16 __iomem *cpcr = &cpmp->cp_cpcr;
+
+ out_be16(cpcr, port->command | (cmd << 8) | CPM_CR_FLG);
+ while (in_be16(cpcr) & CPM_CR_FLG)
+ ;
+}
+#else
+void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
{
ushort val;
+ int line = port - cpm_uart_ports;
volatile cpm8xx_t *cp = cpmp;
switch (line) {
@@ -114,6 +125,7 @@ void scc4_lineif(struct uart_cpm_port *pinfo)
/* XXX SCC4: insert port configuration here */
pinfo->brg = 4;
}
+#endif
/*
* Allocate DP-Ram and memory buffers. We need to allocate a transmit and
@@ -167,7 +179,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
* pinfo->rx_fifosize);
- pinfo->rx_bd_base = (volatile cbd_t *)dp_mem;
+ pinfo->rx_bd_base = (cbd_t __iomem __force *)dp_mem;
pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos;
return 0;
@@ -184,6 +196,7 @@ void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
cpm_dpfree(pinfo->dp_addr);
}
+#ifndef CONFIG_PPC_CPM_NEW_BINDING
/* Setup any dynamic params in the uart desc */
int cpm_uart_init_portdesc(void)
{
@@ -279,3 +292,4 @@ int cpm_uart_init_portdesc(void)
#endif
return 0;
}
+#endif
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.h b/drivers/serial/cpm_uart/cpm_uart_cpm1.h
index 2a6477834c3..9b5465fb0bb 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm1.h
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.h
@@ -13,30 +13,32 @@
#include <asm/commproc.h>
/* defines for IRQs */
+#ifndef CONFIG_PPC_CPM_NEW_BINDING
#define SMC1_IRQ (CPM_IRQ_OFFSET + CPMVEC_SMC1)
#define SMC2_IRQ (CPM_IRQ_OFFSET + CPMVEC_SMC2)
#define SCC1_IRQ (CPM_IRQ_OFFSET + CPMVEC_SCC1)
#define SCC2_IRQ (CPM_IRQ_OFFSET + CPMVEC_SCC2)
#define SCC3_IRQ (CPM_IRQ_OFFSET + CPMVEC_SCC3)
#define SCC4_IRQ (CPM_IRQ_OFFSET + CPMVEC_SCC4)
+#endif
static inline void cpm_set_brg(int brg, int baud)
{
cpm_setbrg(brg, baud);
}
-static inline void cpm_set_scc_fcr(volatile scc_uart_t * sup)
+static inline void cpm_set_scc_fcr(scc_uart_t __iomem * sup)
{
- sup->scc_genscc.scc_rfcr = SMC_EB;
- sup->scc_genscc.scc_tfcr = SMC_EB;
+ out_8(&sup->scc_genscc.scc_rfcr, SMC_EB);
+ out_8(&sup->scc_genscc.scc_tfcr, SMC_EB);
}
-static inline void cpm_set_smc_fcr(volatile smc_uart_t * up)
+static inline void cpm_set_smc_fcr(smc_uart_t __iomem * up)
{
- up->smc_rfcr = SMC_EB;
- up->smc_tfcr = SMC_EB;
+ out_8(&up->smc_rfcr, SMC_EB);
+ out_8(&up->smc_tfcr, SMC_EB);
}
-#define DPRAM_BASE ((unsigned char *)cpm_dpram_addr(0))
+#define DPRAM_BASE ((u8 __iomem __force *)cpm_dpram_addr(0))
#endif
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
index 7b61d805ebe..882dbc17d59 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -49,9 +49,22 @@
/**************************************************************/
-void cpm_line_cr_cmd(int line, int cmd)
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
+{
+ cpm_cpm2_t __iomem *cp = cpm2_map(im_cpm);
+
+ out_be32(&cp->cp_cpcr, port->command | cmd | CPM_CR_FLG);
+ while (in_be32(&cp->cp_cpcr) & CPM_CR_FLG)
+ ;
+
+ cpm2_unmap(cp);
+}
+#else
+void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
{
ulong val;
+ int line = port - cpm_uart_ports;
volatile cpm_cpm2_t *cp = cpm2_map(im_cpm);
@@ -211,6 +224,7 @@ void scc4_lineif(struct uart_cpm_port *pinfo)
cpm2_unmap(cpmux);
cpm2_unmap(io);
}
+#endif
/*
* Allocate DP-Ram and memory buffers. We need to allocate a transmit and
@@ -221,7 +235,7 @@ void scc4_lineif(struct uart_cpm_port *pinfo)
int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
{
int dpmemsz, memsz;
- u8 *dp_mem;
+ u8 __iomem *dp_mem;
unsigned long dp_offset;
u8 *mem_addr;
dma_addr_t dma_addr = 0;
@@ -264,7 +278,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
* pinfo->rx_fifosize);
- pinfo->rx_bd_base = (volatile cbd_t *)dp_mem;
+ pinfo->rx_bd_base = (cbd_t __iomem *)dp_mem;
pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos;
return 0;
@@ -275,12 +289,13 @@ void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
dma_free_coherent(NULL, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
pinfo->rx_fifosize) +
L1_CACHE_ALIGN(pinfo->tx_nrfifos *
- pinfo->tx_fifosize), pinfo->mem_addr,
+ pinfo->tx_fifosize), (void __force *)pinfo->mem_addr,
pinfo->dma_addr);
cpm_dpfree(pinfo->dp_addr);
}
+#ifndef CONFIG_PPC_CPM_NEW_BINDING
/* Setup any dynamic params in the uart desc */
int cpm_uart_init_portdesc(void)
{
@@ -386,3 +401,4 @@ int cpm_uart_init_portdesc(void)
return 0;
}
+#endif
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.h b/drivers/serial/cpm_uart/cpm_uart_cpm2.h
index 1b3219f56c8..40006a7dce4 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.h
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.h
@@ -13,30 +13,32 @@
#include <asm/cpm2.h>
/* defines for IRQs */
+#ifndef CONFIG_PPC_CPM_NEW_BINDING
#define SMC1_IRQ SIU_INT_SMC1
#define SMC2_IRQ SIU_INT_SMC2
#define SCC1_IRQ SIU_INT_SCC1
#define SCC2_IRQ SIU_INT_SCC2
#define SCC3_IRQ SIU_INT_SCC3
#define SCC4_IRQ SIU_INT_SCC4
+#endif
static inline void cpm_set_brg(int brg, int baud)
{
cpm_setbrg(brg, baud);
}
-static inline void cpm_set_scc_fcr(volatile scc_uart_t * sup)
+static inline void cpm_set_scc_fcr(scc_uart_t __iomem *sup)
{
- sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
- sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
+ out_8(&sup->scc_genscc.scc_rfcr, CPMFCR_GBL | CPMFCR_EB);
+ out_8(&sup->scc_genscc.scc_tfcr, CPMFCR_GBL | CPMFCR_EB);
}
-static inline void cpm_set_smc_fcr(volatile smc_uart_t * up)
+static inline void cpm_set_smc_fcr(smc_uart_t __iomem *up)
{
- up->smc_rfcr = CPMFCR_GBL | CPMFCR_EB;
- up->smc_tfcr = CPMFCR_GBL | CPMFCR_EB;
+ out_8(&up->smc_rfcr, CPMFCR_GBL | CPMFCR_EB);
+ out_8(&up->smc_tfcr, CPMFCR_GBL | CPMFCR_EB);
}
-#define DPRAM_BASE ((unsigned char *)cpm_dpram_addr(0))
+#define DPRAM_BASE ((u8 __iomem __force *)cpm_dpram_addr(0))
#endif
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 35f8b86cc78..035cca02819 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -1051,7 +1051,7 @@ mpc52xx_uart_of_assign(struct device_node *np, int idx)
/* If the slot is already occupied, then swap slots */
if (mpc52xx_uart_nodes[idx] && (free_idx != -1))
mpc52xx_uart_nodes[free_idx] = mpc52xx_uart_nodes[idx];
- mpc52xx_uart_nodes[i] = np;
+ mpc52xx_uart_nodes[idx] = np;
}
static void
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c
index 0fa9f676176..794bd0f50d7 100644
--- a/drivers/serial/pmac_zilog.c
+++ b/drivers/serial/pmac_zilog.c
@@ -88,6 +88,16 @@ MODULE_LICENSE("GPL");
#define PWRDBG(fmt, arg...) printk(KERN_DEBUG fmt , ## arg)
+#ifdef CONFIG_SERIAL_PMACZILOG_TTYS
+#define PMACZILOG_MAJOR TTY_MAJOR
+#define PMACZILOG_MINOR 64
+#define PMACZILOG_NAME "ttyS"
+#else
+#define PMACZILOG_MAJOR 204
+#define PMACZILOG_MINOR 192
+#define PMACZILOG_NAME "ttyPZ"
+#endif
+
/*
* For the sake of early serial console, we can do a pre-probe
@@ -99,9 +109,10 @@ static DEFINE_MUTEX(pmz_irq_mutex);
static struct uart_driver pmz_uart_reg = {
.owner = THIS_MODULE,
- .driver_name = "ttyS",
- .dev_name = "ttyS",
- .major = TTY_MAJOR,
+ .driver_name = PMACZILOG_NAME,
+ .dev_name = PMACZILOG_NAME,
+ .major = PMACZILOG_MAJOR,
+ .minor = PMACZILOG_MINOR,
};
@@ -1587,7 +1598,7 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state)
if (pm_state.event == mdev->ofdev.dev.power.power_state.event)
return 0;
- pmz_debug("suspend, switching to state %d\n", pm_state);
+ pmz_debug("suspend, switching to state %d\n", pm_state.event);
state = pmz_uart_reg.state + uap->port.line;
@@ -1778,7 +1789,7 @@ static void pmz_console_write(struct console *con, const char *s, unsigned int c
static int __init pmz_console_setup(struct console *co, char *options);
static struct console pmz_console = {
- .name = "ttyS",
+ .name = PMACZILOG_NAME,
.write = pmz_console_write,
.device = uart_console_device,
.setup = pmz_console_setup,
@@ -1802,7 +1813,6 @@ static int __init pmz_register(void)
pmz_uart_reg.nr = pmz_ports_count;
pmz_uart_reg.cons = PMACZILOG_CONSOLE;
- pmz_uart_reg.minor = 64;
/*
* Register this driver with the serial core
diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c
index f5051cf1a0c..dfef83f1496 100644
--- a/drivers/serial/uartlite.c
+++ b/drivers/serial/uartlite.c
@@ -1,7 +1,8 @@
/*
* uartlite.c: Serial driver for Xilinx uartlite serial controller
*
- * Peter Korsgaard <jacmet@sunsite.dk>
+ * Copyright (C) 2006 Peter Korsgaard <jacmet@sunsite.dk>
+ * Copyright (C) 2007 Secret Lab Technologies Ltd.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
@@ -17,14 +18,23 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <asm/io.h>
+#if defined(CONFIG_OF)
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#endif
+#define ULITE_NAME "ttyUL"
#define ULITE_MAJOR 204
#define ULITE_MINOR 187
#define ULITE_NR_UARTS 4
-/* For register details see datasheet:
- http://www.xilinx.com/bvdocs/ipcenter/data_sheet/opb_uartlite.pdf
-*/
+/* ---------------------------------------------------------------------
+ * Register definitions
+ *
+ * For register details see datasheet:
+ * http://www.xilinx.com/bvdocs/ipcenter/data_sheet/opb_uartlite.pdf
+ */
+
#define ULITE_RX 0x00
#define ULITE_TX 0x04
#define ULITE_STATUS 0x08
@@ -46,7 +56,11 @@
#define ULITE_CONTROL_IE 0x10
-static struct uart_port ports[ULITE_NR_UARTS];
+static struct uart_port ulite_ports[ULITE_NR_UARTS];
+
+/* ---------------------------------------------------------------------
+ * Core UART driver operations
+ */
static int ulite_receive(struct uart_port *port, int stat)
{
@@ -307,6 +321,10 @@ static struct uart_ops ulite_ops = {
.verify_port = ulite_verify_port
};
+/* ---------------------------------------------------------------------
+ * Console driver operations
+ */
+
#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
static void ulite_console_wait_tx(struct uart_port *port)
{
@@ -329,7 +347,7 @@ static void ulite_console_putchar(struct uart_port *port, int ch)
static void ulite_console_write(struct console *co, const char *s,
unsigned int count)
{
- struct uart_port *port = &ports[co->index];
+ struct uart_port *port = &ulite_ports[co->index];
unsigned long flags;
unsigned int ier;
int locked = 1;
@@ -355,6 +373,31 @@ static void ulite_console_write(struct console *co, const char *s,
spin_unlock_irqrestore(&port->lock, flags);
}
+#if defined(CONFIG_OF)
+static inline void __init ulite_console_of_find_device(int id)
+{
+ struct device_node *np;
+ struct resource res;
+ const unsigned int *of_id;
+ int rc;
+
+ for_each_compatible_node(np, NULL, "xilinx,uartlite") {
+ of_id = of_get_property(np, "port-number", NULL);
+ if ((!of_id) || (*of_id != id))
+ continue;
+
+ rc = of_address_to_resource(np, 0, &res);
+ if (rc)
+ continue;
+
+ ulite_ports[id].mapbase = res.start;
+ return;
+ }
+}
+#else /* CONFIG_OF */
+static inline void __init ulite_console_of_find_device(int id) { /* do nothing */ }
+#endif /* CONFIG_OF */
+
static int __init ulite_console_setup(struct console *co, char *options)
{
struct uart_port *port;
@@ -366,11 +409,23 @@ static int __init ulite_console_setup(struct console *co, char *options)
if (co->index < 0 || co->index >= ULITE_NR_UARTS)
return -EINVAL;
- port = &ports[co->index];
+ port = &ulite_ports[co->index];
- /* not initialized yet? */
- if (!port->membase)
+ /* Check if it is an OF device */
+ if (!port->mapbase)
+ ulite_console_of_find_device(co->index);
+
+ /* Do we have a device now? */
+ if (!port->mapbase) {
+ pr_debug("console on ttyUL%i not present\n", co->index);
return -ENODEV;
+ }
+
+ /* not initialized yet? */
+ if (!port->membase) {
+ if (ulite_request_port(port))
+ return -ENODEV;
+ }
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -381,7 +436,7 @@ static int __init ulite_console_setup(struct console *co, char *options)
static struct uart_driver ulite_uart_driver;
static struct console ulite_console = {
- .name = "ttyUL",
+ .name = ULITE_NAME,
.write = ulite_console_write,
.device = uart_console_device,
.setup = ulite_console_setup,
@@ -403,7 +458,7 @@ console_initcall(ulite_console_init);
static struct uart_driver ulite_uart_driver = {
.owner = THIS_MODULE,
.driver_name = "uartlite",
- .dev_name = "ttyUL",
+ .dev_name = ULITE_NAME,
.major = ULITE_MAJOR,
.minor = ULITE_MINOR,
.nr = ULITE_NR_UARTS,
@@ -412,59 +467,111 @@ static struct uart_driver ulite_uart_driver = {
#endif
};
-static int __devinit ulite_probe(struct platform_device *pdev)
+/* ---------------------------------------------------------------------
+ * Port assignment functions (mapping devices to uart_port structures)
+ */
+
+/** ulite_assign: register a uartlite device with the driver
+ *
+ * @dev: pointer to device structure
+ * @id: requested id number. Pass -1 for automatic port assignment
+ * @base: base address of uartlite registers
+ * @irq: irq number for uartlite
+ *
+ * Returns: 0 on success, <0 otherwise
+ */
+static int __devinit ulite_assign(struct device *dev, int id, u32 base, int irq)
{
- struct resource *res, *res2;
struct uart_port *port;
+ int rc;
- if (pdev->id < 0 || pdev->id >= ULITE_NR_UARTS)
+ /* if id = -1; then scan for a free id and use that */
+ if (id < 0) {
+ for (id = 0; id < ULITE_NR_UARTS; id++)
+ if (ulite_ports[id].mapbase == 0)
+ break;
+ }
+ if (id < 0 || id >= ULITE_NR_UARTS) {
+ dev_err(dev, "%s%i too large\n", ULITE_NAME, id);
return -EINVAL;
+ }
- if (ports[pdev->id].membase)
+ if ((ulite_ports[id].mapbase) && (ulite_ports[id].mapbase != base)) {
+ dev_err(dev, "cannot assign to %s%i; it is already in use\n",
+ ULITE_NAME, id);
return -EBUSY;
+ }
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
+ port = &ulite_ports[id];
- res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res2)
- return -ENODEV;
+ spin_lock_init(&port->lock);
+ port->fifosize = 16;
+ port->regshift = 2;
+ port->iotype = UPIO_MEM;
+ port->iobase = 1; /* mark port in use */
+ port->mapbase = base;
+ port->membase = NULL;
+ port->ops = &ulite_ops;
+ port->irq = irq;
+ port->flags = UPF_BOOT_AUTOCONF;
+ port->dev = dev;
+ port->type = PORT_UNKNOWN;
+ port->line = id;
+
+ dev_set_drvdata(dev, port);
+
+ /* Register the port */
+ rc = uart_add_one_port(&ulite_uart_driver, port);
+ if (rc) {
+ dev_err(dev, "uart_add_one_port() failed; err=%i\n", rc);
+ port->mapbase = 0;
+ dev_set_drvdata(dev, NULL);
+ return rc;
+ }
- port = &ports[pdev->id];
+ return 0;
+}
- port->fifosize = 16;
- port->regshift = 2;
- port->iotype = UPIO_MEM;
- port->iobase = 1; /* mark port in use */
- port->mapbase = res->start;
- port->membase = NULL;
- port->ops = &ulite_ops;
- port->irq = res2->start;
- port->flags = UPF_BOOT_AUTOCONF;
- port->dev = &pdev->dev;
- port->type = PORT_UNKNOWN;
- port->line = pdev->id;
+/** ulite_release: register a uartlite device with the driver
+ *
+ * @dev: pointer to device structure
+ */
+static int __devinit ulite_release(struct device *dev)
+{
+ struct uart_port *port = dev_get_drvdata(dev);
+ int rc = 0;
- uart_add_one_port(&ulite_uart_driver, port);
- platform_set_drvdata(pdev, port);
+ if (port) {
+ rc = uart_remove_one_port(&ulite_uart_driver, port);
+ dev_set_drvdata(dev, NULL);
+ port->mapbase = 0;
+ }
- return 0;
+ return rc;
}
-static int ulite_remove(struct platform_device *pdev)
+/* ---------------------------------------------------------------------
+ * Platform bus binding
+ */
+
+static int __devinit ulite_probe(struct platform_device *pdev)
{
- struct uart_port *port = platform_get_drvdata(pdev);
+ struct resource *res, *res2;
- platform_set_drvdata(pdev, NULL);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
- if (port)
- uart_remove_one_port(&ulite_uart_driver, port);
+ res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res2)
+ return -ENODEV;
- /* mark port as free */
- port->membase = NULL;
+ return ulite_assign(&pdev->dev, pdev->id, res->start, res2->start);
+}
- return 0;
+static int ulite_remove(struct platform_device *pdev)
+{
+ return ulite_release(&pdev->dev);
}
static struct platform_driver ulite_platform_driver = {
@@ -476,24 +583,109 @@ static struct platform_driver ulite_platform_driver = {
},
};
+/* ---------------------------------------------------------------------
+ * OF bus bindings
+ */
+#if defined(CONFIG_OF)
+static int __devinit
+ulite_of_probe(struct of_device *op, const struct of_device_id *match)
+{
+ struct resource res;
+ const unsigned int *id;
+ int irq, rc;
+
+ dev_dbg(&op->dev, "%s(%p, %p)\n", __FUNCTION__, op, match);
+
+ rc = of_address_to_resource(op->node, 0, &res);
+ if (rc) {
+ dev_err(&op->dev, "invalid address\n");
+ return rc;
+ }
+
+ irq = irq_of_parse_and_map(op->node, 0);
+
+ id = of_get_property(op->node, "port-number", NULL);
+
+ return ulite_assign(&op->dev, id ? *id : -1, res.start+3, irq);
+}
+
+static int __devexit ulite_of_remove(struct of_device *op)
+{
+ return ulite_release(&op->dev);
+}
+
+/* Match table for of_platform binding */
+static struct of_device_id __devinit ulite_of_match[] = {
+ { .type = "serial", .compatible = "xilinx,uartlite", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ulite_of_match);
+
+static struct of_platform_driver ulite_of_driver = {
+ .owner = THIS_MODULE,
+ .name = "uartlite",
+ .match_table = ulite_of_match,
+ .probe = ulite_of_probe,
+ .remove = __devexit_p(ulite_of_remove),
+ .driver = {
+ .name = "uartlite",
+ },
+};
+
+/* Registration helpers to keep the number of #ifdefs to a minimum */
+static inline int __init ulite_of_register(void)
+{
+ pr_debug("uartlite: calling of_register_platform_driver()\n");
+ return of_register_platform_driver(&ulite_of_driver);
+}
+
+static inline void __exit ulite_of_unregister(void)
+{
+ of_unregister_platform_driver(&ulite_of_driver);
+}
+#else /* CONFIG_OF */
+/* CONFIG_OF not enabled; do nothing helpers */
+static inline int __init ulite_of_register(void) { return 0; }
+static inline void __exit ulite_of_unregister(void) { }
+#endif /* CONFIG_OF */
+
+/* ---------------------------------------------------------------------
+ * Module setup/teardown
+ */
+
int __init ulite_init(void)
{
int ret;
+ pr_debug("uartlite: calling uart_register_driver()\n");
ret = uart_register_driver(&ulite_uart_driver);
if (ret)
- return ret;
+ goto err_uart;
+ ret = ulite_of_register();
+ if (ret)
+ goto err_of;
+
+ pr_debug("uartlite: calling platform_driver_register()\n");
ret = platform_driver_register(&ulite_platform_driver);
if (ret)
- uart_unregister_driver(&ulite_uart_driver);
+ goto err_plat;
+ return 0;
+
+err_plat:
+ ulite_of_unregister();
+err_of:
+ uart_unregister_driver(&ulite_uart_driver);
+err_uart:
+ printk(KERN_ERR "registering uartlite driver failed: err=%i", ret);
return ret;
}
void __exit ulite_exit(void)
{
platform_driver_unregister(&ulite_platform_driver);
+ ulite_of_unregister();
uart_unregister_driver(&ulite_uart_driver);
}
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index 8503e733a17..cbe71a5338d 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -17,6 +17,8 @@
* more details.
*/
+#undef DEBUG
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
@@ -535,33 +537,35 @@ static int __devinit platinumfb_probe(struct of_device* odev,
volatile __u8 *fbuffer;
int bank0, bank1, bank2, bank3, rc;
- printk(KERN_INFO "platinumfb: Found Apple Platinum video hardware\n");
+ dev_info(&odev->dev, "Found Apple Platinum video hardware\n");
info = framebuffer_alloc(sizeof(*pinfo), &odev->dev);
- if (info == NULL)
+ if (info == NULL) {
+ dev_err(&odev->dev, "Failed to allocate fbdev !\n");
return -ENOMEM;
+ }
pinfo = info->par;
if (of_address_to_resource(dp, 0, &pinfo->rsrc_reg) ||
of_address_to_resource(dp, 1, &pinfo->rsrc_fb)) {
- printk(KERN_ERR "platinumfb: Can't get resources\n");
- framebuffer_release(info);
- return -ENXIO;
- }
- if (!request_mem_region(pinfo->rsrc_reg.start,
- pinfo->rsrc_reg.start -
- pinfo->rsrc_reg.end + 1,
- "platinumfb registers")) {
+ dev_err(&odev->dev, "Can't get resources\n");
framebuffer_release(info);
return -ENXIO;
}
+ dev_dbg(&odev->dev, " registers : 0x%llx...0x%llx\n",
+ (unsigned long long)pinfo->rsrc_reg.start,
+ (unsigned long long)pinfo->rsrc_reg.end);
+ dev_dbg(&odev->dev, " framebuffer: 0x%llx...0x%llx\n",
+ (unsigned long long)pinfo->rsrc_fb.start,
+ (unsigned long long)pinfo->rsrc_fb.end);
+
+ /* Do not try to request register space, they overlap with the
+ * northbridge and that can fail. Only request framebuffer
+ */
if (!request_mem_region(pinfo->rsrc_fb.start,
- pinfo->rsrc_fb.start
- - pinfo->rsrc_fb.end + 1,
+ pinfo->rsrc_fb.end - pinfo->rsrc_fb.start + 1,
"platinumfb framebuffer")) {
- release_mem_region(pinfo->rsrc_reg.start,
- pinfo->rsrc_reg.end -
- pinfo->rsrc_reg.start + 1);
+ printk(KERN_ERR "platinumfb: Can't request framebuffer !\n");
framebuffer_release(info);
return -ENXIO;
}
@@ -600,7 +604,8 @@ static int __devinit platinumfb_probe(struct of_device* odev,
bank2 = fbuffer[0x200000] == 0x56;
bank3 = fbuffer[0x300000] == 0x78;
pinfo->total_vram = (bank0 + bank1 + bank2 + bank3) * 0x100000;
- printk(KERN_INFO "platinumfb: Total VRAM = %dMB (%d%d%d%d)\n", (int) (pinfo->total_vram / 1024 / 1024),
+ printk(KERN_INFO "platinumfb: Total VRAM = %dMB (%d%d%d%d)\n",
+ (unsigned int) (pinfo->total_vram / 1024 / 1024),
bank3, bank2, bank1, bank0);
/*
@@ -644,16 +649,15 @@ static int __devexit platinumfb_remove(struct of_device* odev)
unregister_framebuffer (info);
/* Unmap frame buffer and registers */
+ iounmap(pinfo->frame_buffer);
+ iounmap(pinfo->platinum_regs);
+ iounmap(pinfo->cmap_regs);
+
release_mem_region(pinfo->rsrc_fb.start,
pinfo->rsrc_fb.end -
pinfo->rsrc_fb.start + 1);
- release_mem_region(pinfo->rsrc_reg.start,
- pinfo->rsrc_reg.end -
- pinfo->rsrc_reg.start + 1);
- iounmap(pinfo->frame_buffer);
- iounmap(pinfo->platinum_regs);
+
release_mem_region(pinfo->cmap_regs_phys, 0x1000);
- iounmap(pinfo->cmap_regs);
framebuffer_release(info);
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c
index 6ef9733a18d..6ef99b2d13c 100644
--- a/drivers/video/xilinxfb.c
+++ b/drivers/video/xilinxfb.c
@@ -6,9 +6,12 @@
* Author: MontaVista Software, Inc.
* source@mvista.com
*
- * 2002-2007 (c) MontaVista Software, Inc. This file is licensed under the
- * terms of the GNU General Public License version 2. This program is licensed
- * "as is" without any warranty of any kind, whether express or implied.
+ * 2002-2007 (c) MontaVista Software, Inc.
+ * 2007 (c) Secret Lab Technologies, Ltd.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
*/
/*
@@ -18,6 +21,7 @@
* Geert Uytterhoeven.
*/
+#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
@@ -28,9 +32,12 @@
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
-
+#if defined(CONFIG_OF)
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#endif
#include <asm/io.h>
-#include <syslib/virtex_devices.h>
+#include <linux/xilinxfb.h>
#define DRIVER_NAME "xilinxfb"
#define DRIVER_DESCRIPTION "Xilinx TFT LCD frame buffer driver"
@@ -63,12 +70,6 @@
*/
#define BYTES_PER_PIXEL 4
#define BITS_PER_PIXEL (BYTES_PER_PIXEL * 8)
-#define XRES 640
-#define YRES 480
-#define XRES_VIRTUAL 1024
-#define YRES_VIRTUAL YRES
-#define LINE_LENGTH (XRES_VIRTUAL * BYTES_PER_PIXEL)
-#define FB_SIZE (YRES_VIRTUAL * LINE_LENGTH)
#define RED_SHIFT 16
#define GREEN_SHIFT 8
@@ -77,23 +78,26 @@
#define PALETTE_ENTRIES_NO 16 /* passed to fb_alloc_cmap() */
/*
+ * Default xilinxfb configuration
+ */
+static struct xilinxfb_platform_data xilinx_fb_default_pdata = {
+ .xres = 640,
+ .yres = 480,
+ .xvirt = 1024,
+ .yvirt = 480;
+};
+
+/*
* Here are the default fb_fix_screeninfo and fb_var_screeninfo structures
*/
static struct fb_fix_screeninfo xilinx_fb_fix = {
.id = "Xilinx",
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_TRUECOLOR,
- .smem_len = FB_SIZE,
- .line_length = LINE_LENGTH,
.accel = FB_ACCEL_NONE
};
static struct fb_var_screeninfo xilinx_fb_var = {
- .xres = XRES,
- .yres = YRES,
- .xres_virtual = XRES_VIRTUAL,
- .yres_virtual = YRES_VIRTUAL,
-
.bits_per_pixel = BITS_PER_PIXEL,
.red = { RED_SHIFT, 8, 0 },
@@ -111,8 +115,9 @@ struct xilinxfb_drvdata {
u32 regs_phys; /* phys. address of the control registers */
u32 __iomem *regs; /* virt. address of the control registers */
- unsigned char __iomem *fb_virt; /* virt. address of the frame buffer */
+ void *fb_virt; /* virt. address of the frame buffer */
dma_addr_t fb_phys; /* phys. address of the frame buffer */
+ int fb_alloced; /* Flag, was the fb memory alloced? */
u32 reg_ctrl_default;
@@ -195,130 +200,136 @@ static struct fb_ops xilinxfb_ops =
.fb_imageblit = cfb_imageblit,
};
-/* === The device driver === */
+/* ---------------------------------------------------------------------
+ * Bus independent setup/teardown
+ */
-static int
-xilinxfb_drv_probe(struct device *dev)
+static int xilinxfb_assign(struct device *dev, unsigned long physaddr,
+ struct xilinxfb_platform_data *pdata)
{
- struct platform_device *pdev;
- struct xilinxfb_platform_data *pdata;
struct xilinxfb_drvdata *drvdata;
- struct resource *regs_res;
- int retval;
-
- if (!dev)
- return -EINVAL;
-
- pdev = to_platform_device(dev);
- pdata = pdev->dev.platform_data;
+ int rc;
+ int fbsize = pdata->xvirt * pdata->yvirt * BYTES_PER_PIXEL;
+ /* Allocate the driver data region */
drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
if (!drvdata) {
- printk(KERN_ERR "Couldn't allocate device private record\n");
+ dev_err(dev, "Couldn't allocate device private record\n");
return -ENOMEM;
}
dev_set_drvdata(dev, drvdata);
/* Map the control registers in */
- regs_res = platform_get_resource(pdev, IORESOURCE_IO, 0);
- if (!regs_res || (regs_res->end - regs_res->start + 1 < 8)) {
- printk(KERN_ERR "Couldn't get registers resource\n");
- retval = -EFAULT;
- goto failed1;
+ if (!request_mem_region(physaddr, 8, DRIVER_NAME)) {
+ dev_err(dev, "Couldn't lock memory region at 0x%08lX\n",
+ physaddr);
+ rc = -ENODEV;
+ goto err_region;
}
-
- if (!request_mem_region(regs_res->start, 8, DRIVER_NAME)) {
- printk(KERN_ERR
- "Couldn't lock memory region at 0x%08X\n",
- regs_res->start);
- retval = -EBUSY;
- goto failed1;
+ drvdata->regs_phys = physaddr;
+ drvdata->regs = ioremap(physaddr, 8);
+ if (!drvdata->regs) {
+ dev_err(dev, "Couldn't lock memory region at 0x%08lX\n",
+ physaddr);
+ rc = -ENODEV;
+ goto err_map;
}
- drvdata->regs = (u32 __iomem*) ioremap(regs_res->start, 8);
- drvdata->regs_phys = regs_res->start;
/* Allocate the framebuffer memory */
- drvdata->fb_virt = dma_alloc_coherent(dev, PAGE_ALIGN(FB_SIZE),
- &drvdata->fb_phys, GFP_KERNEL);
+ if (pdata->fb_phys) {
+ drvdata->fb_phys = pdata->fb_phys;
+ drvdata->fb_virt = ioremap(pdata->fb_phys, fbsize);
+ } else {
+ drvdata->fb_alloced = 1;
+ drvdata->fb_virt = dma_alloc_coherent(dev, PAGE_ALIGN(fbsize),
+ &drvdata->fb_phys, GFP_KERNEL);
+ }
+
if (!drvdata->fb_virt) {
- printk(KERN_ERR "Could not allocate frame buffer memory\n");
- retval = -ENOMEM;
- goto failed2;
+ dev_err(dev, "Could not allocate frame buffer memory\n");
+ rc = -ENOMEM;
+ goto err_fbmem;
}
/* Clear (turn to black) the framebuffer */
- memset_io((void *) drvdata->fb_virt, 0, FB_SIZE);
+ memset_io((void __iomem *)drvdata->fb_virt, 0, fbsize);
/* Tell the hardware where the frame buffer is */
xilinx_fb_out_be32(drvdata, REG_FB_ADDR, drvdata->fb_phys);
/* Turn on the display */
drvdata->reg_ctrl_default = REG_CTRL_ENABLE;
- if (pdata && pdata->rotate_screen)
+ if (pdata->rotate_screen)
drvdata->reg_ctrl_default |= REG_CTRL_ROTATE;
xilinx_fb_out_be32(drvdata, REG_CTRL, drvdata->reg_ctrl_default);
/* Fill struct fb_info */
drvdata->info.device = dev;
- drvdata->info.screen_base = drvdata->fb_virt;
+ drvdata->info.screen_base = (void __iomem *)drvdata->fb_virt;
drvdata->info.fbops = &xilinxfb_ops;
drvdata->info.fix = xilinx_fb_fix;
drvdata->info.fix.smem_start = drvdata->fb_phys;
- drvdata->info.pseudo_palette = drvdata->pseudo_palette;
-
- if (fb_alloc_cmap(&drvdata->info.cmap, PALETTE_ENTRIES_NO, 0) < 0) {
- printk(KERN_ERR "Fail to allocate colormap (%d entries)\n",
- PALETTE_ENTRIES_NO);
- retval = -EFAULT;
- goto failed3;
- }
+ drvdata->info.fix.smem_len = fbsize;
+ drvdata->info.fix.line_length = pdata->xvirt * BYTES_PER_PIXEL;
+ drvdata->info.pseudo_palette = drvdata->pseudo_palette;
drvdata->info.flags = FBINFO_DEFAULT;
- if (pdata) {
- xilinx_fb_var.height = pdata->screen_height_mm;
- xilinx_fb_var.width = pdata->screen_width_mm;
- }
drvdata->info.var = xilinx_fb_var;
+ drvdata->info.var.height = pdata->screen_height_mm;
+ drvdata->info.var.width = pdata->screen_width_mm;
+ drvdata->info.var.xres = pdata->xres;
+ drvdata->info.var.yres = pdata->yres;
+ drvdata->info.var.xres_virtual = pdata->xvirt;
+ drvdata->info.var.yres_virtual = pdata->yvirt;
+
+ /* Allocate a colour map */
+ rc = fb_alloc_cmap(&drvdata->info.cmap, PALETTE_ENTRIES_NO, 0);
+ if (rc) {
+ dev_err(dev, "Fail to allocate colormap (%d entries)\n",
+ PALETTE_ENTRIES_NO);
+ goto err_cmap;
+ }
/* Register new frame buffer */
- if (register_framebuffer(&drvdata->info) < 0) {
- printk(KERN_ERR "Could not register frame buffer\n");
- retval = -EINVAL;
- goto failed4;
+ rc = register_framebuffer(&drvdata->info);
+ if (rc) {
+ dev_err(dev, "Could not register frame buffer\n");
+ goto err_regfb;
}
+ /* Put a banner in the log (for DEBUG) */
+ dev_dbg(dev, "regs: phys=%lx, virt=%p\n", physaddr, drvdata->regs);
+ dev_dbg(dev, "fb: phys=%p, virt=%p, size=%x\n",
+ (void*)drvdata->fb_phys, drvdata->fb_virt, fbsize);
+
return 0; /* success */
-failed4:
+err_regfb:
fb_dealloc_cmap(&drvdata->info.cmap);
-failed3:
- dma_free_coherent(dev, PAGE_ALIGN(FB_SIZE), drvdata->fb_virt,
- drvdata->fb_phys);
-
+err_cmap:
+ if (drvdata->fb_alloced)
+ dma_free_coherent(dev, PAGE_ALIGN(fbsize), drvdata->fb_virt,
+ drvdata->fb_phys);
/* Turn off the display */
xilinx_fb_out_be32(drvdata, REG_CTRL, 0);
+
+err_fbmem:
iounmap(drvdata->regs);
-failed2:
- release_mem_region(regs_res->start, 8);
+err_map:
+ release_mem_region(physaddr, 8);
-failed1:
+err_region:
kfree(drvdata);
dev_set_drvdata(dev, NULL);
- return retval;
+ return rc;
}
-static int
-xilinxfb_drv_remove(struct device *dev)
+static int xilinxfb_release(struct device *dev)
{
- struct xilinxfb_drvdata *drvdata;
-
- if (!dev)
- return -ENODEV;
-
- drvdata = (struct xilinxfb_drvdata *) dev_get_drvdata(dev);
+ struct xilinxfb_drvdata *drvdata = dev_get_drvdata(dev);
#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
xilinx_fb_blank(VESA_POWERDOWN, &drvdata->info);
@@ -328,8 +339,9 @@ xilinxfb_drv_remove(struct device *dev)
fb_dealloc_cmap(&drvdata->info.cmap);
- dma_free_coherent(dev, PAGE_ALIGN(FB_SIZE), drvdata->fb_virt,
- drvdata->fb_phys);
+ if (drvdata->fb_alloced)
+ dma_free_coherent(dev, PAGE_ALIGN(drvdata->info.fix.smem_len),
+ drvdata->fb_virt, drvdata->fb_phys);
/* Turn off the display */
xilinx_fb_out_be32(drvdata, REG_CTRL, 0);
@@ -343,29 +355,168 @@ xilinxfb_drv_remove(struct device *dev)
return 0;
}
+/* ---------------------------------------------------------------------
+ * Platform bus binding
+ */
+
+static int
+xilinxfb_platform_probe(struct platform_device *pdev)
+{
+ struct xilinxfb_platform_data *pdata;
+ struct resource *res;
-static struct device_driver xilinxfb_driver = {
- .name = DRIVER_NAME,
- .bus = &platform_bus_type,
+ /* Find the registers address */
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Couldn't get registers resource\n");
+ return -ENODEV;
+ }
- .probe = xilinxfb_drv_probe,
- .remove = xilinxfb_drv_remove
+ /* If a pdata structure is provided, then extract the parameters */
+ pdata = &xilinx_fb_default_pdata;
+ if (pdev->dev.platform_data) {
+ pdata = pdev->dev.platform_data;
+ if (!pdata->xres)
+ pdata->xres = xilinx_fb_default_pdata.xres;
+ if (!pdata->yres)
+ pdata->yres = xilinx_fb_default_pdata.yres;
+ if (!pdata->xvirt)
+ pdata->xvirt = xilinx_fb_default_pdata.xvirt;
+ if (!pdata->yvirt)
+ pdata->yvirt = xilinx_fb_default_pdata.yvirt;
+ }
+
+ return xilinxfb_assign(&pdev->dev, res->start, pdata);
+}
+
+static int
+xilinxfb_platform_remove(struct platform_device *pdev)
+{
+ return xilinxfb_release(&pdev->dev);
+}
+
+
+static struct platform_driver xilinxfb_platform_driver = {
+ .probe = xilinxfb_platform_probe,
+ .remove = xilinxfb_platform_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRIVER_NAME,
+ },
+};
+
+/* ---------------------------------------------------------------------
+ * OF bus binding
+ */
+
+#if defined(CONFIG_OF)
+static int __devinit
+xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match)
+{
+ struct resource res;
+ const u32 *prop;
+ struct xilinxfb_platform_data pdata;
+ int size, rc;
+
+ /* Copy with the default pdata (not a ptr reference!) */
+ pdata = xilinx_fb_default_pdata;
+
+ dev_dbg(&op->dev, "xilinxfb_of_probe(%p, %p)\n", op, match);
+
+ rc = of_address_to_resource(op->node, 0, &res);
+ if (rc) {
+ dev_err(&op->dev, "invalid address\n");
+ return rc;
+ }
+
+ prop = of_get_property(op->node, "phys-size", &size);
+ if ((prop) && (size >= sizeof(u32)*2)) {
+ pdata.screen_width_mm = prop[0];
+ pdata.screen_height_mm = prop[1];
+ }
+
+ prop = of_get_property(op->node, "resolution", &size);
+ if ((prop) && (size >= sizeof(u32)*2)) {
+ pdata.xres = prop[0];
+ pdata.yres = prop[1];
+ }
+
+ prop = of_get_property(op->node, "virtual-resolution", &size);
+ if ((prop) && (size >= sizeof(u32)*2)) {
+ pdata.xvirt = prop[0];
+ pdata.yvirt = prop[1];
+ }
+
+ if (of_find_property(op->node, "rotate-display", NULL))
+ pdata.rotate_screen = 1;
+
+ return xilinxfb_assign(&op->dev, res.start, &pdata);
+}
+
+static int __devexit xilinxfb_of_remove(struct of_device *op)
+{
+ return xilinxfb_release(&op->dev);
+}
+
+/* Match table for of_platform binding */
+static struct of_device_id __devinit xilinxfb_of_match[] = {
+ { .compatible = "xilinx,ml300-fb", },
+ {},
};
+MODULE_DEVICE_TABLE(of, xilinxfb_of_match);
+
+static struct of_platform_driver xilinxfb_of_driver = {
+ .owner = THIS_MODULE,
+ .name = DRIVER_NAME,
+ .match_table = xilinxfb_of_match,
+ .probe = xilinxfb_of_probe,
+ .remove = __devexit_p(xilinxfb_of_remove),
+ .driver = {
+ .name = DRIVER_NAME,
+ },
+};
+
+/* Registration helpers to keep the number of #ifdefs to a minimum */
+static inline int __init xilinxfb_of_register(void)
+{
+ pr_debug("xilinxfb: calling of_register_platform_driver()\n");
+ return of_register_platform_driver(&xilinxfb_of_driver);
+}
+
+static inline void __exit xilinxfb_of_unregister(void)
+{
+ of_unregister_platform_driver(&xilinxfb_of_driver);
+}
+#else /* CONFIG_OF */
+/* CONFIG_OF not enabled; do nothing helpers */
+static inline int __init xilinxfb_of_register(void) { return 0; }
+static inline void __exit xilinxfb_of_unregister(void) { }
+#endif /* CONFIG_OF */
+
+/* ---------------------------------------------------------------------
+ * Module setup and teardown
+ */
static int __init
xilinxfb_init(void)
{
- /*
- * No kernel boot options used,
- * so we just need to register the driver
- */
- return driver_register(&xilinxfb_driver);
+ int rc;
+ rc = xilinxfb_of_register();
+ if (rc)
+ return rc;
+
+ rc = platform_driver_register(&xilinxfb_platform_driver);
+ if (rc)
+ xilinxfb_of_unregister();
+
+ return rc;
}
static void __exit
xilinxfb_cleanup(void)
{
- driver_unregister(&xilinxfb_driver);
+ platform_driver_unregister(&xilinxfb_platform_driver);
+ xilinxfb_of_unregister();
}
module_init(xilinxfb_init);