diff options
Diffstat (limited to 'drivers')
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); |