From 5fa28ea42f28342ca6efaa2d23789f3fec5adff6 Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Fri, 23 Jun 2006 02:04:56 -0700 Subject: [PATCH] m68k: restore amikbd compatibility with 2.4 Dump the extra mapping in the amikbd interrupt handler, so old Amiga keymaps work again. Amigas need a special keymap anyway, standard keymaps are not usable and recreating all keymaps is simply not worth the trouble. Signed-off-by: Roman Zippel Cc: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/input/keyboard/amikbd.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c index 4c8fb1f8631f..f1f9db9d282c 100644 --- a/drivers/input/keyboard/amikbd.c +++ b/drivers/input/keyboard/amikbd.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -45,7 +46,7 @@ MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("Amiga keyboard driver"); MODULE_LICENSE("GPL"); -static unsigned char amikbd_keycode[0x78] = { +static unsigned char amikbd_keycode[0x78] __initdata = { [0] = KEY_GRAVE, [1] = KEY_1, [2] = KEY_2, @@ -170,12 +171,9 @@ static irqreturn_t amikbd_interrupt(int irq, void *dummy, struct pt_regs *fp) scancode >>= 1; if (scancode < 0x78) { /* scancodes < 0x78 are keys */ - - scancode = amikbd_keycode[scancode]; - input_regs(amikbd_dev, fp); - if (scancode == KEY_CAPSLOCK) { /* CapsLock is a toggle switch key on Amiga */ + if (scancode == 98) { /* CapsLock is a toggle switch key on Amiga */ input_report_key(amikbd_dev, scancode, 1); input_report_key(amikbd_dev, scancode, 0); } else { @@ -191,7 +189,7 @@ static irqreturn_t amikbd_interrupt(int irq, void *dummy, struct pt_regs *fp) static int __init amikbd_init(void) { - int i; + int i, j; if (!AMIGAHW_PRESENT(AMI_KEYBOARD)) return -EIO; @@ -214,14 +212,26 @@ static int __init amikbd_init(void) amikbd_dev->id.version = 0x0100; amikbd_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); - amikbd_dev->keycode = amikbd_keycode; - amikbd_dev->keycodesize = sizeof(unsigned char); - amikbd_dev->keycodemax = ARRAY_SIZE(amikbd_keycode); for (i = 0; i < 0x78; i++) - if (amikbd_keycode[i]) - set_bit(amikbd_keycode[i], amikbd_dev->keybit); - + set_bit(i, amikbd_dev->keybit); + + for (i = 0; i < MAX_NR_KEYMAPS; i++) { + static u_short temp_map[NR_KEYS] __initdata; + if (!key_maps[i]) + continue; + memset(temp_map, 0, sizeof(temp_map)); + for (j = 0; j < 0x78; j++) { + if (!amikbd_keycode[j]) + continue; + temp_map[j] = key_maps[i][amikbd_keycode[j]]; + } + for (j = 0; j < NR_KEYS; j++) { + if (!temp_map[j]) + temp_map[j] = 0xf200; + } + memcpy(key_maps[i], temp_map, sizeof(temp_map)); + } ciaa.cra &= ~0x41; /* serial data in, turn off TA */ request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", amikbd_interrupt); -- cgit v1.2.3-58-ga151 From 75e1fcc0b18df0a65ab113198e9dc0e98999a08c Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Fri, 23 Jun 2006 02:05:12 -0700 Subject: [PATCH] vfs: add lock owner argument to flush operation Pass the POSIX lock owner ID to the flush operation. This is useful for filesystems which don't want to store any locking state in inode->i_flock but want to handle locking/unlocking POSIX locks internally. FUSE is one such filesystem but I think it possible that some network filesystems would need this also. Also add a flag to indicate that a POSIX locking request was generated by close(), so filesystems using the above feature won't send an extra locking request in this case. Signed-off-by: Miklos Szeredi Cc: Trond Myklebust Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ia64/kernel/perfmon.c | 3 +-- drivers/input/evdev.c | 2 +- drivers/scsi/osst.c | 2 +- drivers/scsi/st.c | 2 +- fs/cifs/cifsfs.h | 2 +- fs/cifs/file.c | 2 +- fs/coda/file.c | 2 +- fs/fuse/file.c | 2 +- fs/locks.c | 2 +- fs/nfs/file.c | 4 ++-- fs/open.c | 2 +- include/linux/coda_linux.h | 2 +- include/linux/fs.h | 3 ++- ipc/mqueue.c | 2 +- 14 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/input') diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 2359e2809f50..6d7bc8ff7b3a 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -532,7 +532,6 @@ static ctl_table pfm_sysctl_root[] = { static struct ctl_table_header *pfm_sysctl_header; static int pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs); -static int pfm_flush(struct file *filp); #define pfm_get_cpu_var(v) __ia64_per_cpu_var(v) #define pfm_get_cpu_data(a,b) per_cpu(a, b) @@ -1774,7 +1773,7 @@ pfm_syswide_cleanup_other_cpu(pfm_context_t *ctx) * When caller is self-monitoring, the context is unloaded. */ static int -pfm_flush(struct file *filp) +pfm_flush(struct file *filp, fl_owner_t id) { pfm_context_t *ctx; struct task_struct *task; diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index ba325f16d077..5f561fce32d8 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -82,7 +82,7 @@ static int evdev_fasync(int fd, struct file *file, int on) return retval < 0 ? retval : 0; } -static int evdev_flush(struct file * file) +static int evdev_flush(struct file * file, fl_owner_t id) { struct evdev_list *list = file->private_data; if (!list->evdev->exist) return -ENODEV; diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index ce0ba3a174f9..4a2fed350d4e 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -4724,7 +4724,7 @@ err_out: /* Flush the tape buffer before close */ -static int os_scsi_tape_flush(struct file * filp) +static int os_scsi_tape_flush(struct file * filp, fl_owner_t id) { int result = 0, result2; struct osst_tape * STp = filp->private_data; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index ad87d73f88ee..1272dd249af3 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -1193,7 +1193,7 @@ static int st_open(struct inode *inode, struct file *filp) /* Flush the tape buffer before close */ -static int st_flush(struct file *filp) +static int st_flush(struct file *filp, fl_owner_t id) { int result = 0, result2; unsigned char cmd[MAX_COMMAND_SIZE]; diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index c98755dca868..d56c0577c710 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -74,7 +74,7 @@ extern ssize_t cifs_user_write(struct file *file, const char __user *write_data, size_t write_size, loff_t * poffset); extern int cifs_lock(struct file *, int, struct file_lock *); extern int cifs_fsync(struct file *, struct dentry *, int); -extern int cifs_flush(struct file *); +extern int cifs_flush(struct file *, fl_owner_t id); extern int cifs_file_mmap(struct file * , struct vm_area_struct *); extern const struct file_operations cifs_dir_ops; extern int cifs_dir_open(struct inode *inode, struct file *file); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 487ea8b3baaa..b4a18c1cab0a 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1417,7 +1417,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) * As file closes, flush all cached write data for this inode checking * for write behind errors. */ -int cifs_flush(struct file *file) +int cifs_flush(struct file *file, fl_owner_t id) { struct inode * inode = file->f_dentry->d_inode; int rc = 0; diff --git a/fs/coda/file.c b/fs/coda/file.c index 7c2642431fa5..cc66c681bd11 100644 --- a/fs/coda/file.c +++ b/fs/coda/file.c @@ -164,7 +164,7 @@ int coda_open(struct inode *coda_inode, struct file *coda_file) return 0; } -int coda_flush(struct file *coda_file) +int coda_flush(struct file *coda_file, fl_owner_t id) { unsigned short flags = coda_file->f_flags & ~O_EXCL; unsigned short coda_flags = coda_flags_to_cflags(flags); diff --git a/fs/fuse/file.c b/fs/fuse/file.c index fc342cf7c2cc..087f3b734f40 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -169,7 +169,7 @@ static int fuse_release(struct inode *inode, struct file *file) return fuse_release_common(inode, file, 0); } -static int fuse_flush(struct file *file) +static int fuse_flush(struct file *file, fl_owner_t id) { struct inode *inode = file->f_dentry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); diff --git a/fs/locks.c b/fs/locks.c index e588e1c265f7..f8a634ac1121 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1907,7 +1907,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner) return; lock.fl_type = F_UNLCK; - lock.fl_flags = FL_POSIX; + lock.fl_flags = FL_POSIX | FL_CLOSE; lock.fl_start = 0; lock.fl_end = OFFSET_MAX; lock.fl_owner = owner; diff --git a/fs/nfs/file.c b/fs/nfs/file.c index fade02c15e6e..fa05c027ea11 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -43,7 +43,7 @@ static int nfs_file_mmap(struct file *, struct vm_area_struct *); static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *); static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t); static ssize_t nfs_file_write(struct kiocb *, const char __user *, size_t, loff_t); -static int nfs_file_flush(struct file *); +static int nfs_file_flush(struct file *, fl_owner_t id); static int nfs_fsync(struct file *, struct dentry *dentry, int datasync); static int nfs_check_flags(int flags); static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl); @@ -188,7 +188,7 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) * */ static int -nfs_file_flush(struct file *file) +nfs_file_flush(struct file *file, fl_owner_t id) { struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data; struct inode *inode = file->f_dentry->d_inode; diff --git a/fs/open.c b/fs/open.c index a37ff861108f..5fb16e5267dc 100644 --- a/fs/open.c +++ b/fs/open.c @@ -1152,7 +1152,7 @@ int filp_close(struct file *filp, fl_owner_t id) } if (filp->f_op && filp->f_op->flush) - retval = filp->f_op->flush(filp); + retval = filp->f_op->flush(filp, id); dnotify_flush(filp, id); locks_remove_posix(filp, id); diff --git a/include/linux/coda_linux.h b/include/linux/coda_linux.h index b3ecf8f71d97..7b5c5df5cb69 100644 --- a/include/linux/coda_linux.h +++ b/include/linux/coda_linux.h @@ -36,7 +36,7 @@ extern const struct file_operations coda_ioctl_operations; /* operations shared over more than one file */ int coda_open(struct inode *i, struct file *f); -int coda_flush(struct file *f); +int coda_flush(struct file *f, fl_owner_t id); int coda_release(struct inode *i, struct file *f); int coda_permission(struct inode *inode, int mask, struct nameidata *nd); int coda_revalidate_inode(struct dentry *); diff --git a/include/linux/fs.h b/include/linux/fs.h index e917403f4d58..56d8bf0d0a77 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -683,6 +683,7 @@ extern spinlock_t files_lock; #define FL_FLOCK 2 #define FL_ACCESS 8 /* not trying to lock, just looking */ #define FL_LEASE 32 /* lease held on this file */ +#define FL_CLOSE 64 /* unlock on close */ #define FL_SLEEP 128 /* A blocking lock */ /* @@ -1025,7 +1026,7 @@ struct file_operations { long (*compat_ioctl) (struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); - int (*flush) (struct file *); + int (*flush) (struct file *, fl_owner_t id); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, struct dentry *, int datasync); int (*aio_fsync) (struct kiocb *, int datasync); diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 0a2a24b6ebe4..02e6f6798972 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -359,7 +359,7 @@ static ssize_t mqueue_read_file(struct file *filp, char __user *u_data, return count; } -static int mqueue_flush_file(struct file *filp) +static int mqueue_flush_file(struct file *filp, fl_owner_t id) { struct mqueue_inode_info *info = MQUEUE_I(filp->f_dentry->d_inode); -- cgit v1.2.3-58-ga151 From 690c8fd31f1e35985d0f35772fde514da59ec9d1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 22 Jun 2006 19:12:03 -0700 Subject: [SPARC64]: Use in-kernel PROM tree for EBUS and ISA. Signed-off-by: David S. Miller --- arch/sparc64/kernel/auxio.c | 2 +- arch/sparc64/kernel/ebus.c | 141 +++++++------- arch/sparc64/kernel/isa.c | 144 ++++++-------- arch/sparc64/kernel/power.c | 20 +- arch/sparc64/kernel/prom.c | 1 + arch/sparc64/kernel/time.c | 368 +++++++++++++++++++----------------- drivers/char/rtc.c | 4 +- drivers/input/misc/sparcspkr.c | 4 +- drivers/input/serio/i8042-sparcio.h | 10 +- drivers/sbus/char/bbc_envctrl.c | 4 +- drivers/sbus/char/bbc_i2c.c | 4 +- drivers/sbus/char/display7seg.c | 2 +- drivers/sbus/char/envctrl.c | 71 ++++--- drivers/sbus/char/flash.c | 16 +- drivers/serial/sunsab.c | 12 +- drivers/serial/sunsu.c | 4 +- include/asm-sparc64/ebus.h | 10 +- include/asm-sparc64/floppy.h | 27 ++- include/asm-sparc64/isa.h | 8 +- include/asm-sparc64/parport.h | 25 ++- sound/sparc/cs4231.c | 13 +- 21 files changed, 440 insertions(+), 450 deletions(-) (limited to 'drivers/input') diff --git a/arch/sparc64/kernel/auxio.c b/arch/sparc64/kernel/auxio.c index 8852c20c8d99..db36b66a4e3c 100644 --- a/arch/sparc64/kernel/auxio.c +++ b/arch/sparc64/kernel/auxio.c @@ -136,7 +136,7 @@ found_sdev: for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "auxio")) + if (!strcmp(edev->prom_node->name, "auxio")) goto ebus_done; } } diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index 3125a5b49775..919a91d9e5de 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c @@ -285,36 +285,38 @@ static inline void *ebus_alloc(size_t size) static void __init ebus_ranges_init(struct linux_ebus *ebus) { - int success; + struct linux_prom_ebus_ranges *rngs; + int len; ebus->num_ebus_ranges = 0; - success = prom_getproperty(ebus->prom_node, "ranges", - (char *)ebus->ebus_ranges, - sizeof(ebus->ebus_ranges)); - if (success != -1) - ebus->num_ebus_ranges = (success/sizeof(struct linux_prom_ebus_ranges)); + rngs = of_get_property(ebus->prom_node, "ranges", &len); + if (rngs) { + memcpy(ebus->ebus_ranges, rngs, len); + ebus->num_ebus_ranges = + (len / sizeof(struct linux_prom_ebus_ranges)); + } } static void __init ebus_intmap_init(struct linux_ebus *ebus) { - int success; + struct linux_prom_ebus_intmap *imap; + struct linux_prom_ebus_intmask *imask; + int len; ebus->num_ebus_intmap = 0; - success = prom_getproperty(ebus->prom_node, "interrupt-map", - (char *)ebus->ebus_intmap, - sizeof(ebus->ebus_intmap)); - if (success == -1) + imap = of_get_property(ebus->prom_node, "interrupt-map", &len); + if (!imap) return; - ebus->num_ebus_intmap = (success/sizeof(struct linux_prom_ebus_intmap)); + memcpy(ebus->ebus_intmap, imap, len); + ebus->num_ebus_intmap = (len / sizeof(struct linux_prom_ebus_intmap)); - success = prom_getproperty(ebus->prom_node, "interrupt-map-mask", - (char *)&ebus->ebus_intmask, - sizeof(ebus->ebus_intmask)); - if (success == -1) { - prom_printf("%s: can't get interrupt-map-mask\n", __FUNCTION__); + imask = of_get_property(ebus->prom_node, "interrupt-map-mask", &len); + if (!imask) { + prom_printf("EBUS: can't get interrupt-map-mask\n"); prom_halt(); } + memcpy(&ebus->ebus_intmask, imask, sizeof(ebus->ebus_intmask)); } int __init ebus_intmap_match(struct linux_ebus *ebus, @@ -341,19 +343,23 @@ int __init ebus_intmap_match(struct linux_ebus *ebus, return -1; } -void __init fill_ebus_child(int node, struct linux_prom_registers *preg, - struct linux_ebus_child *dev, int non_standard_regs) +void __init fill_ebus_child(struct device_node *dp, + struct linux_prom_registers *preg, + struct linux_ebus_child *dev, + int non_standard_regs) { - int regs[PROMREG_MAX]; - int irqs[PROMREG_MAX]; + int *regs; + int *irqs; int i, len; - dev->prom_node = node; - prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name)); - printk(" (%s)", dev->prom_name); + dev->prom_node = dp; + printk(" (%s)", dp->name); - len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs)); - dev->num_addrs = len / sizeof(regs[0]); + regs = of_get_property(dp, "reg", &len); + if (!regs) + dev->num_addrs = 0; + else + dev->num_addrs = len / sizeof(regs[0]); if (non_standard_regs) { /* This is to handle reg properties which are not @@ -370,21 +376,21 @@ void __init fill_ebus_child(int node, struct linux_prom_registers *preg, int rnum = regs[i]; if (rnum >= dev->parent->num_addrs) { prom_printf("UGH: property for %s was %d, need < %d\n", - dev->prom_name, len, dev->parent->num_addrs); - panic(__FUNCTION__); + dp->name, len, dev->parent->num_addrs); + prom_halt(); } dev->resource[i].start = dev->parent->resource[i].start; dev->resource[i].end = dev->parent->resource[i].end; dev->resource[i].flags = IORESOURCE_MEM; - dev->resource[i].name = dev->prom_name; + dev->resource[i].name = dp->name; } } for (i = 0; i < PROMINTR_MAX; i++) dev->irqs[i] = PCI_IRQ_NONE; - len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); - if ((len == -1) || (len == 0)) { + irqs = of_get_property(dp, "interrupts", &len); + if (!irqs) { dev->num_irqs = 0; /* * Oh, well, some PROMs don't export interrupts @@ -392,8 +398,8 @@ void __init fill_ebus_child(int node, struct linux_prom_registers *preg, * * Be smart about PS/2 keyboard and mouse. */ - if (!strcmp(dev->parent->prom_name, "8042")) { - if (!strcmp(dev->prom_name, "kb_ps2")) { + if (!strcmp(dev->parent->prom_node->name, "8042")) { + if (!strcmp(dev->prom_node->name, "kb_ps2")) { dev->num_irqs = 1; dev->irqs[0] = dev->parent->irqs[0]; } else { @@ -423,32 +429,32 @@ void __init fill_ebus_child(int node, struct linux_prom_registers *preg, static int __init child_regs_nonstandard(struct linux_ebus_device *dev) { - if (!strcmp(dev->prom_name, "i2c") || - !strcmp(dev->prom_name, "SUNW,lombus")) + if (!strcmp(dev->prom_node->name, "i2c") || + !strcmp(dev->prom_node->name, "SUNW,lombus")) return 1; return 0; } -void __init fill_ebus_device(int node, struct linux_ebus_device *dev) +void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev) { - struct linux_prom_registers regs[PROMREG_MAX]; + struct linux_prom_registers *regs; struct linux_ebus_child *child; - int irqs[PROMINTR_MAX]; + int *irqs; int i, n, len; - dev->prom_node = node; - prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name)); - printk(" [%s", dev->prom_name); + dev->prom_node = dp; - len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs)); - if (len == -1) { + printk(" [%s", dp->name); + + regs = of_get_property(dp, "reg", &len); + if (!regs) { dev->num_addrs = 0; goto probe_interrupts; } if (len % sizeof(struct linux_prom_registers)) { prom_printf("UGH: proplen for %s was %d, need multiple of %d\n", - dev->prom_name, len, + dev->prom_node->name, len, (int)sizeof(struct linux_prom_registers)); prom_halt(); } @@ -466,7 +472,7 @@ void __init fill_ebus_device(int node, struct linux_ebus_device *dev) dev->resource[i].end = (dev->resource[i].start + (unsigned long)regs[i].reg_size - 1UL); dev->resource[i].flags = IORESOURCE_MEM; - dev->resource[i].name = dev->prom_name; + dev->resource[i].name = dev->prom_node->name; request_resource(&dev->bus->self->resource[n], &dev->resource[i]); } @@ -475,8 +481,8 @@ probe_interrupts: for (i = 0; i < PROMINTR_MAX; i++) dev->irqs[i] = PCI_IRQ_NONE; - len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); - if ((len == -1) || (len == 0)) { + irqs = of_get_property(dp, "interrupts", &len); + if (!irqs) { dev->num_irqs = 0; } else { dev->num_irqs = len / sizeof(irqs[0]); @@ -497,7 +503,8 @@ probe_interrupts: } } - if ((node = prom_getchild(node))) { + dp = dp->child; + if (dp) { printk(" ->"); dev->children = ebus_alloc(sizeof(struct linux_ebus_child)); @@ -505,18 +512,18 @@ probe_interrupts: child->next = NULL; child->parent = dev; child->bus = dev->bus; - fill_ebus_child(node, ®s[0], - child, child_regs_nonstandard(dev)); + fill_ebus_child(dp, regs, child, + child_regs_nonstandard(dev)); - while ((node = prom_getsibling(node)) != 0) { + while ((dp = dp->sibling) != NULL) { child->next = ebus_alloc(sizeof(struct linux_ebus_child)); child = child->next; child->next = NULL; child->parent = dev; child->bus = dev->bus; - fill_ebus_child(node, ®s[0], - child, child_regs_nonstandard(dev)); + fill_ebus_child(dp, regs, child, + child_regs_nonstandard(dev)); } } printk("]"); @@ -543,7 +550,8 @@ void __init ebus_init(void) struct linux_ebus *ebus; struct pci_dev *pdev; struct pcidev_cookie *cookie; - int nd, ebusnd, is_rio; + struct device_node *dp; + int is_rio; int num_ebus = 0; pdev = find_next_ebus(NULL, &is_rio); @@ -553,20 +561,22 @@ void __init ebus_init(void) } cookie = pdev->sysdata; - ebusnd = cookie->prom_node->node; + dp = cookie->prom_node; ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus)); ebus->next = NULL; ebus->is_rio = is_rio; - while (ebusnd) { + while (dp) { + struct device_node *child; + /* SUNW,pci-qfe uses four empty ebuses on it. I think we should not consider them here, as they have half of the properties this code expects and once we do PCI hot-plug, we'd have to tweak with the ebus_chain in the runtime after initialization. -jj */ - if (!prom_getchild (ebusnd)) { + if (!dp->child) { pdev = find_next_ebus(pdev, &is_rio); if (!pdev) { if (ebus == ebus_chain) { @@ -578,22 +588,21 @@ void __init ebus_init(void) } ebus->is_rio = is_rio; cookie = pdev->sysdata; - ebusnd = cookie->prom_node->node; + dp = cookie->prom_node; continue; } printk("ebus%d:", num_ebus); - prom_getstring(ebusnd, "name", ebus->prom_name, sizeof(ebus->prom_name)); ebus->index = num_ebus; - ebus->prom_node = ebusnd; + ebus->prom_node = dp; ebus->self = pdev; ebus->parent = pbm = cookie->pbm; ebus_ranges_init(ebus); ebus_intmap_init(ebus); - nd = prom_getchild(ebusnd); - if (!nd) + child = dp->child; + if (!child) goto next_ebus; ebus->devices = ebus_alloc(sizeof(struct linux_ebus_device)); @@ -602,16 +611,16 @@ void __init ebus_init(void) dev->next = NULL; dev->children = NULL; dev->bus = ebus; - fill_ebus_device(nd, dev); + fill_ebus_device(child, dev); - while ((nd = prom_getsibling(nd)) != 0) { + while ((child = child->sibling) != NULL) { dev->next = ebus_alloc(sizeof(struct linux_ebus_device)); dev = dev->next; dev->next = NULL; dev->children = NULL; dev->bus = ebus; - fill_ebus_device(nd, dev); + fill_ebus_device(child, dev); } next_ebus: @@ -622,7 +631,7 @@ void __init ebus_init(void) break; cookie = pdev->sysdata; - ebusnd = cookie->prom_node->node; + dp = cookie->prom_node; ebus->next = ebus_alloc(sizeof(struct linux_ebus)); ebus = ebus->next; diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c index ae02c3820eab..8c8c5a491ad6 100644 --- a/arch/sparc64/kernel/isa.c +++ b/arch/sparc64/kernel/isa.c @@ -15,23 +15,19 @@ static void __init fatal_err(const char *reason) static void __init report_dev(struct sparc_isa_device *isa_dev, int child) { if (child) - printk(" (%s)", isa_dev->prom_name); + printk(" (%s)", isa_dev->prom_node->name); else - printk(" [%s", isa_dev->prom_name); + printk(" [%s", isa_dev->prom_node->name); } -static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev, - struct linux_prom_registers *pregs, - int pregs_size) +static struct linux_prom_registers * __init +isa_dev_get_resource(struct sparc_isa_device *isa_dev) { + struct linux_prom_registers *pregs; unsigned long base, len; int prop_len; - prop_len = prom_getproperty(isa_dev->prom_node, "reg", - (char *) pregs, pregs_size); - - if (prop_len <= 0) - return; + pregs = of_get_property(isa_dev->prom_node, "reg", &prop_len); /* Only the first one is interesting. */ len = pregs[0].reg_size; @@ -42,10 +38,12 @@ static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev, isa_dev->resource.start = base; isa_dev->resource.end = (base + len - 1UL); isa_dev->resource.flags = IORESOURCE_IO; - isa_dev->resource.name = isa_dev->prom_name; + isa_dev->resource.name = isa_dev->prom_node->name; request_resource(&isa_dev->bus->parent->io_space, &isa_dev->resource); + + return pregs; } /* I can't believe they didn't put a real INO in the isa device @@ -98,8 +96,8 @@ static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev, { int irq_prop; - irq_prop = prom_getintdefault(isa_dev->prom_node, - "interrupts", -1); + irq_prop = of_getintprop_default(isa_dev->prom_node, + "interrupts", -1); if (irq_prop <= 0) { goto no_irq; } else { @@ -141,16 +139,15 @@ no_irq: static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev) { - int node = prom_getchild(parent_isa_dev->prom_node); + struct device_node *dp = parent_isa_dev->prom_node->child; - if (node == 0) + if (!dp) return; printk(" ->"); - while (node != 0) { - struct linux_prom_registers regs[PROMREG_MAX]; + while (dp) { + struct linux_prom_registers *regs; struct sparc_isa_device *isa_dev; - int prop_len; isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); if (!isa_dev) { @@ -165,40 +162,24 @@ static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev) parent_isa_dev->child = isa_dev; isa_dev->bus = parent_isa_dev->bus; - isa_dev->prom_node = node; - prop_len = prom_getproperty(node, "name", - (char *) isa_dev->prom_name, - sizeof(isa_dev->prom_name)); - if (prop_len <= 0) { - fatal_err("cannot get child isa_dev OBP node name"); - prom_halt(); - } - - prop_len = prom_getproperty(node, "compatible", - (char *) isa_dev->compatible, - sizeof(isa_dev->compatible)); + isa_dev->prom_node = dp; - /* Not having this is OK. */ - if (prop_len <= 0) - isa_dev->compatible[0] = '\0'; - - isa_dev_get_resource(isa_dev, regs, sizeof(regs)); + regs = isa_dev_get_resource(isa_dev); isa_dev_get_irq(isa_dev, regs); report_dev(isa_dev, 1); - node = prom_getsibling(node); + dp = dp->sibling; } } static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) { - int node = prom_getchild(isa_br->prom_node); + struct device_node *dp = isa_br->prom_node->child; - while (node != 0) { - struct linux_prom_registers regs[PROMREG_MAX]; + while (dp) { + struct linux_prom_registers *regs; struct sparc_isa_device *isa_dev; - int prop_len; isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); if (!isa_dev) { @@ -222,24 +203,9 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) } isa_dev->bus = isa_br; - isa_dev->prom_node = node; - prop_len = prom_getproperty(node, "name", - (char *) isa_dev->prom_name, - sizeof(isa_dev->prom_name)); - if (prop_len <= 0) { - fatal_err("cannot get isa_dev OBP node name"); - prom_halt(); - } - - prop_len = prom_getproperty(node, "compatible", - (char *) isa_dev->compatible, - sizeof(isa_dev->compatible)); - - /* Not having this is OK. */ - if (prop_len <= 0) - isa_dev->compatible[0] = '\0'; + isa_dev->prom_node = dp; - isa_dev_get_resource(isa_dev, regs, sizeof(regs)); + regs = isa_dev_get_resource(isa_dev); isa_dev_get_irq(isa_dev, regs); report_dev(isa_dev, 0); @@ -248,10 +214,40 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) printk("]"); - node = prom_getsibling(node); + dp = dp->sibling; } } +static void __init get_bridge_props(struct sparc_isa_bridge *isa_br) +{ + struct device_node *dp = isa_br->prom_node; + void *pval; + int len; + + pval = of_get_property(dp, "ranges", &len); + if (pval) { + memcpy(isa_br->isa_ranges, pval, len); + isa_br->num_isa_ranges = + len / sizeof(struct linux_prom_isa_ranges); + } else { + isa_br->num_isa_ranges = 0; + } + + pval = of_get_property(dp, "interrupt-map", &len); + if (pval) { + memcpy(isa_br->isa_intmap, pval, len); + isa_br->num_isa_intmap = + (len / sizeof(struct linux_prom_isa_intmap)); + } else { + isa_br->num_isa_intmap = 0; + } + + pval = of_get_property(dp, "interrupt-map-mask", &len); + if (pval) + memcpy(&isa_br->isa_intmask, pval, + sizeof(isa_br->isa_intmask)); +} + void __init isa_init(void) { struct pci_dev *pdev; @@ -266,7 +262,6 @@ void __init isa_init(void) struct pcidev_cookie *pdev_cookie; struct pci_pbm_info *pbm; struct sparc_isa_bridge *isa_br; - int prop_len; pdev_cookie = pdev->sysdata; if (!pdev_cookie) { @@ -291,34 +286,9 @@ void __init isa_init(void) isa_br->parent = pbm; isa_br->self = pdev; isa_br->index = index++; - isa_br->prom_node = pdev_cookie->prom_node->node; - strncpy(isa_br->prom_name, pdev_cookie->prom_node->name, - sizeof(isa_br->prom_name)); - - prop_len = prom_getproperty(isa_br->prom_node, - "ranges", - (char *) isa_br->isa_ranges, - sizeof(isa_br->isa_ranges)); - if (prop_len <= 0) - isa_br->num_isa_ranges = 0; - else - isa_br->num_isa_ranges = - (prop_len / sizeof(struct linux_prom_isa_ranges)); - - prop_len = prom_getproperty(isa_br->prom_node, - "interrupt-map", - (char *) isa_br->isa_intmap, - sizeof(isa_br->isa_intmap)); - if (prop_len <= 0) - isa_br->num_isa_intmap = 0; - else - isa_br->num_isa_intmap = - (prop_len / sizeof(struct linux_prom_isa_intmap)); - - prop_len = prom_getproperty(isa_br->prom_node, - "interrupt-map-mask", - (char *) &(isa_br->isa_intmask), - sizeof(isa_br->isa_intmask)); + isa_br->prom_node = pdev_cookie->prom_node; + + get_bridge_props(isa_br); printk("isa%d:", isa_br->index); diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index 30bcaf58e3ab..75159a7843f1 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc64/kernel/power.c @@ -105,24 +105,24 @@ again: return 0; } -static int __init has_button_interrupt(unsigned int irq, int prom_node) +static int __init has_button_interrupt(unsigned int irq, struct device_node *dp) { if (irq == PCI_IRQ_NONE) return 0; - if (!prom_node_has_property(prom_node, "button")) + if (!of_find_property(dp, "button", NULL)) return 0; return 1; } -static int __init power_probe_ebus(struct resource **resp, unsigned int *irq_p, int *prom_node_p) +static int __init power_probe_ebus(struct resource **resp, unsigned int *irq_p, struct device_node **prom_node_p) { struct linux_ebus *ebus; struct linux_ebus_device *edev; for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "power")) { + if (!strcmp(edev->prom_node->name, "power")) { *resp = &edev->resource[0]; *irq_p = edev->irqs[0]; *prom_node_p = edev->prom_node; @@ -133,14 +133,14 @@ static int __init power_probe_ebus(struct resource **resp, unsigned int *irq_p, return -ENODEV; } -static int __init power_probe_isa(struct resource **resp, unsigned int *irq_p, int *prom_node_p) +static int __init power_probe_isa(struct resource **resp, unsigned int *irq_p, struct device_node **prom_node_p) { struct sparc_isa_bridge *isa_bus; struct sparc_isa_device *isa_dev; for_each_isa(isa_bus) { for_each_isadev(isa_dev, isa_bus) { - if (!strcmp(isa_dev->prom_name, "power")) { + if (!strcmp(isa_dev->prom_node->name, "power")) { *resp = &isa_dev->resource; *irq_p = isa_dev->irq; *prom_node_p = isa_dev->prom_node; @@ -155,17 +155,17 @@ void __init power_init(void) { struct resource *res = NULL; unsigned int irq; - int prom_node; + struct device_node *dp; static int invoked; if (invoked) return; invoked = 1; - if (!power_probe_ebus(&res, &irq, &prom_node)) + if (!power_probe_ebus(&res, &irq, &dp)) goto found; - if (!power_probe_isa(&res, &irq, &prom_node)) + if (!power_probe_isa(&res, &irq, &dp)) goto found; return; @@ -174,7 +174,7 @@ found: power_reg = ioremap(res->start, 0x4); printk("power: Control reg at %p ... ", power_reg); poweroff_method = machine_halt; /* able to use the standard halt */ - if (has_button_interrupt(irq, prom_node)) { + if (has_button_interrupt(irq, dp)) { if (kernel_thread(powerd, NULL, CLONE_FS) < 0) { printk("Failed to start power daemon.\n"); return; diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index fb112c3c0485..7809100034b0 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c @@ -63,6 +63,7 @@ struct device_node *of_find_node_by_path(const char *path) return np; } +EXPORT_SYMBOL(of_find_node_by_path); struct device_node *of_find_node_by_phandle(phandle handle) { diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index aa5438a4fd50..d072b8632ccd 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -756,24 +756,200 @@ retry: return -EOPNOTSUPP; } -void __init clock_probe(void) +static int __init clock_model_matches(char *model) +{ + if (strcmp(model, "mk48t02") && + strcmp(model, "mk48t08") && + strcmp(model, "mk48t59") && + strcmp(model, "m5819") && + strcmp(model, "m5819p") && + strcmp(model, "m5823") && + strcmp(model, "ds1287")) + return 0; + + return 1; +} + +static void __init __clock_assign_common(void __iomem *addr, char *model) +{ + if (model[5] == '0' && model[6] == '2') { + mstk48t02_regs = addr; + } else if(model[5] == '0' && model[6] == '8') { + mstk48t08_regs = addr; + mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02; + } else { + mstk48t59_regs = addr; + mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; + } +} + +static void __init clock_assign_clk_reg(struct linux_prom_registers *clk_reg, + char *model) +{ + unsigned long addr; + + addr = ((unsigned long) clk_reg[0].phys_addr | + (((unsigned long) clk_reg[0].which_io) << 32UL)); + + __clock_assign_common((void __iomem *) addr, model); +} + +static int __init clock_probe_central(void) { struct linux_prom_registers clk_reg[2]; - char model[128]; - int node, busnd = -1, err; - unsigned long flags; - struct linux_central *cbus; + char model[64]; + int node; + + if (!central_bus) + return 0; + + /* Get Central FHC's prom node. */ + node = central_bus->child->prom_node; + + /* Then get the first child device below it. */ + node = prom_getchild(node); + + while (node) { + prom_getstring(node, "model", model, sizeof(model)); + if (!clock_model_matches(model)) + goto next_sibling; + + prom_getproperty(node, "reg", (char *)clk_reg, + sizeof(clk_reg)); + + apply_fhc_ranges(central_bus->child, clk_reg, 1); + apply_central_ranges(central_bus, clk_reg, 1); + + clock_assign_clk_reg(clk_reg, model); + return 1; + + next_sibling: + node = prom_getsibling(node); + } + + return 0; +} + #ifdef CONFIG_PCI - struct linux_ebus *ebus = NULL; - struct sparc_isa_bridge *isa_br = NULL; +static void __init clock_isa_ebus_assign_regs(struct resource *res, char *model) +{ + if (!strcmp(model, "ds1287") || + !strcmp(model, "m5819") || + !strcmp(model, "m5819p") || + !strcmp(model, "m5823")) { + ds1287_regs = res->start; + } else { + mstk48t59_regs = (void __iomem *) res->start; + mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; + } +} + +static int __init clock_probe_one_ebus_dev(struct linux_ebus_device *edev) +{ + struct device_node *dp = edev->prom_node; + char *model; + + model = of_get_property(dp, "model", NULL); + if (!clock_model_matches(model)) + return 0; + + clock_isa_ebus_assign_regs(&edev->resource[0], model); + + return 1; +} + +static int __init clock_probe_ebus(void) +{ + struct linux_ebus *ebus; + + for_each_ebus(ebus) { + struct linux_ebus_device *edev; + + for_each_ebusdev(edev, ebus) { + if (clock_probe_one_ebus_dev(edev)) + return 1; + } + } + + return 0; +} + +static int __init clock_probe_one_isa_dev(struct sparc_isa_device *idev) +{ + struct device_node *dp = idev->prom_node; + char *model; + + model = of_get_property(dp, "model", NULL); + if (!clock_model_matches(model)) + return 0; + + clock_isa_ebus_assign_regs(&idev->resource, model); + + return 1; +} + +static int __init clock_probe_isa(void) +{ + struct sparc_isa_bridge *isa_br; + + for_each_isa(isa_br) { + struct sparc_isa_device *isa_dev; + + for_each_isadev(isa_dev, isa_br) { + if (clock_probe_one_isa_dev(isa_dev)) + return 1; + } + } + + return 0; +} +#endif /* CONFIG_PCI */ + +#ifdef CONFIG_SBUS +static int __init clock_probe_one_sbus_dev(struct sbus_bus *sbus, struct sbus_dev *sdev) +{ + struct resource *res; + char model[64]; + void __iomem *addr; + + prom_getstring(sdev->prom_node, "model", model, sizeof(model)); + if (!clock_model_matches(model)) + return 0; + + res = &sdev->resource[0]; + addr = sbus_ioremap(res, 0, 0x800UL, "eeprom"); + + __clock_assign_common(addr, model); + + return 1; +} + +static int __init clock_probe_sbus(void) +{ + struct sbus_bus *sbus; + + for_each_sbus(sbus) { + struct sbus_dev *sdev; + + for_each_sbusdev(sdev, sbus) { + if (clock_probe_one_sbus_dev(sbus, sdev)) + return 1; + } + } + + return 0; +} #endif + +void __init clock_probe(void) +{ static int invoked; + unsigned long flags; if (invoked) return; invoked = 1; - if (this_is_starfire) { xtime.tv_sec = starfire_get_time(); xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); @@ -789,183 +965,27 @@ void __init clock_probe(void) return; } - local_irq_save(flags); - - cbus = central_bus; - if (cbus != NULL) - busnd = central_bus->child->prom_node; - /* Check FHC Central then EBUSs then ISA bridges then SBUSs. * That way we handle the presence of multiple properly. * * As a special case, machines with Central must provide the * timer chip there. */ + if (!clock_probe_central() && #ifdef CONFIG_PCI - if (ebus_chain != NULL) { - ebus = ebus_chain; - if (busnd == -1) - busnd = ebus->prom_node; - } - if (isa_chain != NULL) { - isa_br = isa_chain; - if (busnd == -1) - busnd = isa_br->prom_node; - } -#endif - if (sbus_root != NULL && busnd == -1) - busnd = sbus_root->prom_node; - - if (busnd == -1) { - prom_printf("clock_probe: problem, cannot find bus to search.\n"); - prom_halt(); - } - - node = prom_getchild(busnd); - - while (1) { - if (!node) - model[0] = 0; - else - prom_getstring(node, "model", model, sizeof(model)); - if (strcmp(model, "mk48t02") && - strcmp(model, "mk48t08") && - strcmp(model, "mk48t59") && - strcmp(model, "m5819") && - strcmp(model, "m5819p") && - strcmp(model, "m5823") && - strcmp(model, "ds1287")) { - if (cbus != NULL) { - prom_printf("clock_probe: Central bus lacks timer chip.\n"); - prom_halt(); - } - - if (node != 0) - node = prom_getsibling(node); -#ifdef CONFIG_PCI - while ((node == 0) && ebus != NULL) { - ebus = ebus->next; - if (ebus != NULL) { - busnd = ebus->prom_node; - node = prom_getchild(busnd); - } - } - while ((node == 0) && isa_br != NULL) { - isa_br = isa_br->next; - if (isa_br != NULL) { - busnd = isa_br->prom_node; - node = prom_getchild(busnd); - } - } + !clock_probe_ebus() && + !clock_probe_isa() && #endif - if (node == 0) { - prom_printf("clock_probe: Cannot find timer chip\n"); - prom_halt(); - } - continue; - } - - err = prom_getproperty(node, "reg", (char *)clk_reg, - sizeof(clk_reg)); - if(err == -1) { - prom_printf("clock_probe: Cannot get Mostek reg property\n"); - prom_halt(); - } - - if (cbus != NULL) { - apply_fhc_ranges(central_bus->child, clk_reg, 1); - apply_central_ranges(central_bus, clk_reg, 1); - } -#ifdef CONFIG_PCI - else if (ebus != NULL) { - struct linux_ebus_device *edev; - - for_each_ebusdev(edev, ebus) - if (edev->prom_node == node) - break; - if (edev == NULL) { - if (isa_chain != NULL) - goto try_isa_clock; - prom_printf("%s: Mostek not probed by EBUS\n", - __FUNCTION__); - prom_halt(); - } - - if (!strcmp(model, "ds1287") || - !strcmp(model, "m5819") || - !strcmp(model, "m5819p") || - !strcmp(model, "m5823")) { - ds1287_regs = edev->resource[0].start; - } else { - mstk48t59_regs = (void __iomem *) - edev->resource[0].start; - mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; - } - break; - } - else if (isa_br != NULL) { - struct sparc_isa_device *isadev; - -try_isa_clock: - for_each_isadev(isadev, isa_br) - if (isadev->prom_node == node) - break; - if (isadev == NULL) { - prom_printf("%s: Mostek not probed by ISA\n"); - prom_halt(); - } - if (!strcmp(model, "ds1287") || - !strcmp(model, "m5819") || - !strcmp(model, "m5819p") || - !strcmp(model, "m5823")) { - ds1287_regs = isadev->resource.start; - } else { - mstk48t59_regs = (void __iomem *) - isadev->resource.start; - mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; - } - break; - } +#ifdef CONFIG_SBUS + !clock_probe_sbus() #endif - else { - if (sbus_root->num_sbus_ranges) { - int nranges = sbus_root->num_sbus_ranges; - int rngc; - - for (rngc = 0; rngc < nranges; rngc++) - if (clk_reg[0].which_io == - sbus_root->sbus_ranges[rngc].ot_child_space) - break; - if (rngc == nranges) { - prom_printf("clock_probe: Cannot find ranges for " - "clock regs.\n"); - prom_halt(); - } - clk_reg[0].which_io = - sbus_root->sbus_ranges[rngc].ot_parent_space; - clk_reg[0].phys_addr += - sbus_root->sbus_ranges[rngc].ot_parent_base; - } - } - - if(model[5] == '0' && model[6] == '2') { - mstk48t02_regs = (void __iomem *) - (((u64)clk_reg[0].phys_addr) | - (((u64)clk_reg[0].which_io)<<32UL)); - } else if(model[5] == '0' && model[6] == '8') { - mstk48t08_regs = (void __iomem *) - (((u64)clk_reg[0].phys_addr) | - (((u64)clk_reg[0].which_io)<<32UL)); - mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02; - } else { - mstk48t59_regs = (void __iomem *) - (((u64)clk_reg[0].phys_addr) | - (((u64)clk_reg[0].which_io)<<32UL)); - mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; - } - break; + ) { + printk(KERN_WARNING "No clock chip found.\n"); + return; } + local_irq_save(flags); + if (mstk48t02_regs != NULL) { /* Report a low battery voltage condition. */ if (has_low_battery()) diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index f6686fcce809..0897b0c8d528 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -928,7 +928,7 @@ static int __init rtc_init(void) #ifdef __sparc__ for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if(strcmp(edev->prom_name, "rtc") == 0) { + if(strcmp(edev->prom_node->name, "rtc") == 0) { rtc_port = edev->resource[0].start; rtc_irq = edev->irqs[0]; goto found; @@ -938,7 +938,7 @@ static int __init rtc_init(void) #ifdef __sparc_v9__ for_each_isa(isa_br) { for_each_isadev(isa_dev, isa_br) { - if (strcmp(isa_dev->prom_name, "rtc") == 0) { + if (strcmp(isa_dev->prom_node->name, "rtc") == 0) { rtc_port = isa_dev->resource.start; rtc_irq = isa_dev->irq; goto found; diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index f0fd2c4740f1..ed95dc9420dd 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c @@ -199,7 +199,7 @@ static int __init sparcspkr_init(void) for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "beep")) { + if (!strcmp(edev->prom_node->name, "beep")) { beep_name = "Sparc EBUS Speaker"; beep_event = ebus_spkr_event; beep_iobase = edev->resource[0].start; @@ -213,7 +213,7 @@ static int __init sparcspkr_init(void) /* A hack, the beep device's base lives in * the DMA isa node. */ - if (!strcmp(isa_dev->prom_name, "dma")) { + if (!strcmp(isa_dev->prom_node->name, "dma")) { beep_name = "Sparc ISA Speaker"; beep_event = isa_spkr_event, beep_iobase = isa_dev->resource.start; diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h index ed9446f6d7e3..6d66351805a2 100644 --- a/drivers/input/serio/i8042-sparcio.h +++ b/drivers/input/serio/i8042-sparcio.h @@ -74,7 +74,7 @@ static int __init i8042_platform_init(void) for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "8042")) + if (!strcmp(edev->prom_node->name, "8042")) goto edev_found; } } @@ -82,14 +82,14 @@ static int __init i8042_platform_init(void) edev_found: for_each_edevchild(edev, child) { - if (!strcmp(child->prom_name, OBP_PS2KBD_NAME1) || - !strcmp(child->prom_name, OBP_PS2KBD_NAME2)) { + if (!strcmp(child->prom_node->name, OBP_PS2KBD_NAME1) || + !strcmp(child->prom_node->name, OBP_PS2KBD_NAME2)) { i8042_kbd_irq = child->irqs[0]; kbd_iobase = ioremap(child->resource[0].start, 8); } - if (!strcmp(child->prom_name, OBP_PS2MS_NAME1) || - !strcmp(child->prom_name, OBP_PS2MS_NAME2)) + if (!strcmp(child->prom_node->name, OBP_PS2MS_NAME1) || + !strcmp(child->prom_node->name, OBP_PS2MS_NAME2)) i8042_aux_irq = child->irqs[0]; } if (i8042_kbd_irq == -1 || diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c index d89f83f769f5..1cc706e11119 100644 --- a/drivers/sbus/char/bbc_envctrl.c +++ b/drivers/sbus/char/bbc_envctrl.c @@ -575,9 +575,9 @@ int bbc_envctrl_init(void) int devidx = 0; while ((echild = bbc_i2c_getdev(devidx++)) != NULL) { - if (!strcmp(echild->prom_name, "temperature")) + if (!strcmp(echild->prom_node->name, "temperature")) attach_one_temp(echild, temp_index++); - if (!strcmp(echild->prom_name, "fan-control")) + if (!strcmp(echild->prom_node->name, "fan-control")) attach_one_fan(echild, fan_index++); } if (temp_index != 0 && fan_index != 0) { diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index 3e156e005f2e..73634371393b 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c @@ -423,7 +423,7 @@ static int __init bbc_present(void) for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "bbc")) + if (!strcmp(edev->prom_node->name, "bbc")) return 1; } } @@ -446,7 +446,7 @@ static int __init bbc_i2c_init(void) for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "i2c")) { + if (!strcmp(edev->prom_node->name, "i2c")) { if (!attach_one_i2c(edev, index)) index++; } diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index c3a51d1fae5d..d92bc8827a9e 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c @@ -184,7 +184,7 @@ static int __init d7s_init(void) for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, D7S_OBPNAME)) + if (!strcmp(edev->prom_node->name, D7S_OBPNAME)) goto ebus_done; } } diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index 19e8eddf887a..cf97e9efe9b6 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -768,16 +768,14 @@ static void envctrl_set_mon(struct i2c_child_t *pchild, * decoding tables, monitor type, optional properties. * Return: None. */ -static void envctrl_init_adc(struct i2c_child_t *pchild, int node) +static void envctrl_init_adc(struct i2c_child_t *pchild, struct device_node *dp) { - char chnls_desc[CHANNEL_DESC_SZ]; int i = 0, len; - char *pos = chnls_desc; + char *pos; + unsigned int *pval; /* Firmware describe channels into a stream separated by a '\0'. */ - len = prom_getproperty(node, "channels-description", chnls_desc, - CHANNEL_DESC_SZ); - chnls_desc[CHANNEL_DESC_SZ - 1] = '\0'; + pos = of_get_property(dp, "channels-description", &len); while (len > 0) { int l = strlen(pos) + 1; @@ -787,10 +785,13 @@ static void envctrl_init_adc(struct i2c_child_t *pchild, int node) } /* Get optional properties. */ - len = prom_getproperty(node, "warning-temp", (char *)&warning_temperature, - sizeof(warning_temperature)); - len = prom_getproperty(node, "shutdown-temp", (char *)&shutdown_temperature, - sizeof(shutdown_temperature)); + pval = of_get_property(dp, "warning-temp", NULL); + if (pval) + warning_temperature = *pval; + + pval = of_get_property(dp, "shutdown-temp", NULL); + if (pval) + shutdown_temperature = *pval; } /* Function Description: Initialize child device monitoring fan status. @@ -864,21 +865,18 @@ static void envctrl_init_voltage_status(struct i2c_child_t *pchild) static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child, struct i2c_child_t *pchild) { - int node, len, i, tbls_size = 0; - - node = edev_child->prom_node; + int len, i, tbls_size = 0; + struct device_node *dp = edev_child->prom_node; + void *pval; /* Get device address. */ - len = prom_getproperty(node, "reg", - (char *) &(pchild->addr), - sizeof(pchild->addr)); + pval = of_get_property(dp, "reg", &len); + memcpy(&pchild->addr, pval, len); /* Get tables property. Read firmware temperature tables. */ - len = prom_getproperty(node, "translation", - (char *) pchild->tblprop_array, - (PCF8584_MAX_CHANNELS * - sizeof(struct pcf8584_tblprop))); - if (len > 0) { + pval = of_get_property(dp, "translation", &len); + if (pval && len > 0) { + memcpy(pchild->tblprop_array, pval, len); pchild->total_tbls = len / sizeof(struct pcf8584_tblprop); for (i = 0; i < pchild->total_tbls; i++) { if ((pchild->tblprop_array[i].size + pchild->tblprop_array[i].offset) > tbls_size) { @@ -891,12 +889,12 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child, printk("envctrl: Failed to allocate table.\n"); return; } - len = prom_getproperty(node, "tables", - (char *) pchild->tables, tbls_size); - if (len <= 0) { + pval = of_get_property(dp, "tables", &len); + if (!pval || len <= 0) { printk("envctrl: Failed to get table.\n"); return; } + memcpy(pchild->tables, pval, len); } /* SPARCengine ASM Reference Manual (ref. SMI doc 805-7581-04) @@ -907,12 +905,11 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child, * 'NULL' monitor type. */ if (ENVCTRL_CPCI_IGNORED_NODE == pchild->addr) { + struct device_node *root_node; int len; - char prop[56]; - len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop)); - if (0 < len && (0 == strncmp(prop, "SUNW,UltraSPARC-IIi-cEngine", len))) - { + root_node = of_find_node_by_path("/"); + if (!strcmp(root_node->name, "SUNW,UltraSPARC-IIi-cEngine")) { for (len = 0; len < PCF8584_MAX_CHANNELS; ++len) { pchild->mon_type[len] = ENVCTRL_NOMON; } @@ -921,16 +918,14 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child, } /* Get the monitor channels. */ - len = prom_getproperty(node, "channels-in-use", - (char *) pchild->chnl_array, - (PCF8584_MAX_CHANNELS * - sizeof(struct pcf8584_channel))); + pval = of_get_property(dp, "channels-in-use", &len); + memcpy(pchild->chnl_array, pval, len); pchild->total_chnls = len / sizeof(struct pcf8584_channel); for (i = 0; i < pchild->total_chnls; i++) { switch (pchild->chnl_array[i].type) { case PCF8584_TEMP_TYPE: - envctrl_init_adc(pchild, node); + envctrl_init_adc(pchild, dp); break; case PCF8584_GLOBALADDR_TYPE: @@ -945,7 +940,7 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child, case PCF8584_VOLTAGE_TYPE: if (pchild->i2ctype == I2C_ADC) { - envctrl_init_adc(pchild,node); + envctrl_init_adc(pchild,dp); } else { envctrl_init_voltage_status(pchild); } @@ -1046,7 +1041,7 @@ static int __init envctrl_init(void) for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "bbc")) { + if (!strcmp(edev->prom_node->name, "bbc")) { /* If we find a boot-bus controller node, * then this envctrl driver is not for us. */ @@ -1060,14 +1055,14 @@ static int __init envctrl_init(void) */ for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "i2c")) { + if (!strcmp(edev->prom_node->name, "i2c")) { i2c = ioremap(edev->resource[0].start, 0x2); for_each_edevchild(edev, edev_child) { - if (!strcmp("gpio", edev_child->prom_name)) { + if (!strcmp("gpio", edev_child->prom_node->name)) { i2c_childlist[i].i2ctype = I2C_GPIO; envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++])); } - if (!strcmp("adc", edev_child->prom_name)) { + if (!strcmp("adc", edev_child->prom_node->name)) { i2c_childlist[i].i2ctype = I2C_ADC; envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++])); } diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index 2beb3dded087..5ae684c011f8 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c @@ -192,9 +192,11 @@ static int __init flash_init(void) } if (!sdev) { #ifdef CONFIG_PCI + struct linux_prom_registers *ebus_regs; + for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "flashprom")) + if (!strcmp(edev->prom_node->name, "flashprom")) goto ebus_done; } } @@ -202,23 +204,23 @@ static int __init flash_init(void) if (!edev) return -ENODEV; - len = prom_getproperty(edev->prom_node, "reg", (void *)regs, sizeof(regs)); - if ((len % sizeof(regs[0])) != 0) { + ebus_regs = of_get_property(edev->prom_node, "reg", &len); + if (!ebus_regs || (len % sizeof(regs[0])) != 0) { printk("flash: Strange reg property size %d\n", len); return -ENODEV; } - nregs = len / sizeof(regs[0]); + nregs = len / sizeof(ebus_regs[0]); flash.read_base = edev->resource[0].start; - flash.read_size = regs[0].reg_size; + flash.read_size = ebus_regs[0].reg_size; if (nregs == 1) { flash.write_base = edev->resource[0].start; - flash.write_size = regs[0].reg_size; + flash.write_size = ebus_regs[0].reg_size; } else if (nregs == 2) { flash.write_base = edev->resource[1].start; - flash.write_size = regs[1].reg_size; + flash.write_size = ebus_regs[1].reg_size; } else { printk("flash: Strange number of regs %d\n", nregs); return -ENODEV; diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index bfbe9dc90cca..e4c0fd2d6a9d 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -984,19 +984,19 @@ static void __init for_each_sab_edev(void (*callback)(struct linux_ebus_device * for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "se")) { + if (!strcmp(edev->prom_node->name, "se")) { callback(edev, arg); continue; - } else if (!strcmp(edev->prom_name, "serial")) { - char compat[32]; + } else if (!strcmp(edev->prom_node->name, "serial")) { + char *compat; int clen; /* On RIO this can be an SE, check it. We could * just check ebus->is_rio, but this is more portable. */ - clen = prom_getproperty(edev->prom_node, "compatible", - compat, sizeof(compat)); - if (clen > 0) { + compat = of_get_property(edev->prom_node, + "compatible", &clen); + if (compat && clen > 0) { if (strncmp(compat, "sab82532", 8) == 0) { callback(edev, arg); continue; diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 4cdb610cdd37..0268b307c01e 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1053,7 +1053,7 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up) */ for_each_ebus(ebus) { for_each_ebusdev(dev, ebus) { - if (dev->prom_node == up->port_node) { + if (dev->prom_node->node == up->port_node) { /* * The EBus is broken on sparc; it delivers * virtual addresses in resources. Oh well... @@ -1073,7 +1073,7 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up) #ifdef CONFIG_SPARC64 for_each_isa(isa_br) { for_each_isadev(isa_dev, isa_br) { - if (isa_dev->prom_node == up->port_node) { + if (isa_dev->prom_node->node == up->port_node) { /* Same on sparc64. Cool architecure... */ up->port.membase = (char *) isa_dev->resource.start; up->port.mapbase = isa_dev->resource.start; diff --git a/include/asm-sparc64/ebus.h b/include/asm-sparc64/ebus.h index 7a408a030f52..876912f4d83b 100644 --- a/include/asm-sparc64/ebus.h +++ b/include/asm-sparc64/ebus.h @@ -10,13 +10,13 @@ #include #include +#include struct linux_ebus_child { struct linux_ebus_child *next; struct linux_ebus_device *parent; struct linux_ebus *bus; - int prom_node; - char prom_name[64]; + struct device_node *prom_node; struct resource resource[PROMREG_MAX]; int num_addrs; unsigned int irqs[PROMINTR_MAX]; @@ -27,8 +27,7 @@ struct linux_ebus_device { struct linux_ebus_device *next; struct linux_ebus_child *children; struct linux_ebus *bus; - int prom_node; - char prom_name[64]; + struct device_node *prom_node; struct resource resource[PROMREG_MAX]; int num_addrs; unsigned int irqs[PROMINTR_MAX]; @@ -42,8 +41,7 @@ struct linux_ebus { struct pci_dev *self; int index; int is_rio; - int prom_node; - char prom_name[64]; + struct device_node *prom_node; struct linux_prom_ebus_ranges ebus_ranges[PROMREG_MAX]; int num_ebus_ranges; struct linux_prom_ebus_intmap ebus_intmap[PROMREG_MAX]; diff --git a/include/asm-sparc64/floppy.h b/include/asm-sparc64/floppy.h index 07ccd6f04b52..f8d57bb5570c 100644 --- a/include/asm-sparc64/floppy.h +++ b/include/asm-sparc64/floppy.h @@ -498,15 +498,14 @@ static int sun_pci_fd_test_drive(unsigned long port, int drive) #ifdef CONFIG_PCI static int __init ebus_fdthree_p(struct linux_ebus_device *edev) { - if (!strcmp(edev->prom_name, "fdthree")) + if (!strcmp(edev->prom_node->name, "fdthree")) return 1; - if (!strcmp(edev->prom_name, "floppy")) { - char compat[16]; - prom_getstring(edev->prom_node, - "compatible", - compat, sizeof(compat)); - compat[15] = '\0'; - if (!strcmp(compat, "fdthree")) + if (!strcmp(edev->prom_node->name, "floppy")) { + char *compat; + + compat = of_get_property(edev->prom_node, + "compatible", NULL); + if (compat && !strcmp(compat, "fdthree")) return 1; } return 0; @@ -524,12 +523,12 @@ static unsigned long __init isa_floppy_init(void) for_each_isa(isa_br) { for_each_isadev(isa_dev, isa_br) { - if (!strcmp(isa_dev->prom_name, "dma")) { + if (!strcmp(isa_dev->prom_node->name, "dma")) { struct sparc_isa_device *child = isa_dev->child; while (child) { - if (!strcmp(child->prom_name, + if (!strcmp(child->prom_node->name, "floppy")) { isa_dev = child; goto isa_done; @@ -614,6 +613,7 @@ static unsigned long __init sun_floppy_init(void) struct linux_ebus_device *edev = NULL; unsigned long config = 0; void __iomem *auxio_reg; + char *state_prop; for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { @@ -630,9 +630,8 @@ static unsigned long __init sun_floppy_init(void) #endif } - prom_getproperty(edev->prom_node, "status", - state, sizeof(state)); - if (!strncmp(state, "disabled", 8)) + state_prop = of_get_property(edev->prom_node, "status", NULL); + if (state_prop && !strncmp(state_prop, "disabled", 8)) return 0; FLOPPY_IRQ = edev->irqs[0]; @@ -703,7 +702,7 @@ static unsigned long __init sun_floppy_init(void) */ for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "ecpp")) { + if (!strcmp(edev->prom_node->name, "ecpp")) { config = edev->resource[1].start; goto config_done; } diff --git a/include/asm-sparc64/isa.h b/include/asm-sparc64/isa.h index 4601bbfc3e7b..e110435b14ef 100644 --- a/include/asm-sparc64/isa.h +++ b/include/asm-sparc64/isa.h @@ -9,6 +9,7 @@ #include #include +#include struct sparc_isa_bridge; @@ -16,9 +17,7 @@ struct sparc_isa_device { struct sparc_isa_device *next; struct sparc_isa_device *child; struct sparc_isa_bridge *bus; - int prom_node; - char prom_name[64]; - char compatible[64]; + struct device_node *prom_node; struct resource resource; unsigned int irq; }; @@ -29,8 +28,7 @@ struct sparc_isa_bridge { struct pci_pbm_info *parent; struct pci_dev *self; int index; - int prom_node; - char prom_name[64]; + struct device_node *prom_node; #define linux_prom_isa_ranges linux_prom_ebus_ranges struct linux_prom_isa_ranges isa_ranges[PROMREG_MAX]; int num_isa_ranges; diff --git a/include/asm-sparc64/parport.h b/include/asm-sparc64/parport.h index 56b5197d7898..d3895873e4c7 100644 --- a/include/asm-sparc64/parport.h +++ b/include/asm-sparc64/parport.h @@ -67,18 +67,17 @@ static __inline__ unsigned int get_dma_residue(unsigned int dmanr) static int ebus_ecpp_p(struct linux_ebus_device *edev) { - if (!strcmp(edev->prom_name, "ecpp")) + if (!strcmp(edev->prom_node->name, "ecpp")) return 1; - if (!strcmp(edev->prom_name, "parallel")) { - char compat[19]; - prom_getstring(edev->prom_node, - "compatible", - compat, sizeof(compat)); - compat[18] = '\0'; - if (!strcmp(compat, "ecpp")) - return 1; - if (!strcmp(compat, "ns87317-ecpp") && - !strcmp(compat + 13, "ecpp")) + if (!strcmp(edev->prom_node->name, "parallel")) { + char *compat; + + compat = of_get_property(edev->prom_node, + "compatible", NULL); + if (compat && + (!strcmp(compat, "ecpp") || + !strcmp(compat, "ns87317-ecpp") || + !strcmp(compat + 13, "ecpp"))) return 1; } return 0; @@ -94,12 +93,12 @@ static int parport_isa_probe(int count) struct sparc_isa_device *child; unsigned long base; - if (strcmp(isa_dev->prom_name, "dma")) + if (strcmp(isa_dev->prom_node->name, "dma")) continue; child = isa_dev->child; while (child) { - if (!strcmp(child->prom_name, "parallel")) + if (!strcmp(child->prom_node->name, "parallel")) break; child = child->next; } diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index b3efc9aa2916..da54d04a3e3a 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -2284,15 +2284,14 @@ static int __init cs4231_init(void) for_each_ebusdev(edev, ebus) { int match = 0; - if (!strcmp(edev->prom_name, "SUNW,CS4231")) { + if (!strcmp(edev->prom_node->name, "SUNW,CS4231")) { match = 1; - } else if (!strcmp(edev->prom_name, "audio")) { - char compat[16]; + } else if (!strcmp(edev->prom_node->name, "audio")) { + char *compat; - prom_getstring(edev->prom_node, "compatible", - compat, sizeof(compat)); - compat[15] = '\0'; - if (!strcmp(compat, "SUNW,CS4231")) + compat = of_get_property(edev->prom_node, + "compatible", NULL); + if (compat && !strcmp(compat, "SUNW,CS4231")) match = 1; } -- cgit v1.2.3-58-ga151 From a2bd4fd17926d715a470fbe0ebe05128ba410984 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 23 Jun 2006 01:44:10 -0700 Subject: [SPARC64]: Add of_device layer and make ebus/isa use it. Sparcspkr and power drivers are converted, to make sure it works. Eventually the SBUS device layer will use this as a sub-class. I really cannot cut loose on that bit until sparc32 is given the same infrastructure. Signed-off-by: David S. Miller --- arch/sparc64/kernel/Makefile | 2 +- arch/sparc64/kernel/ebus.c | 21 +++ arch/sparc64/kernel/isa.c | 37 +++++- arch/sparc64/kernel/of_device.c | 279 ++++++++++++++++++++++++++++++++++++++++ arch/sparc64/kernel/power.c | 109 ++++++++-------- drivers/input/misc/Kconfig | 2 +- drivers/input/misc/sparcspkr.c | 218 +++++++++++++++++-------------- include/asm-sparc64/ebus.h | 5 + include/asm-sparc64/isa.h | 5 + include/asm-sparc64/of_device.h | 64 +++++++++ 10 files changed, 585 insertions(+), 157 deletions(-) create mode 100644 arch/sparc64/kernel/of_device.c create mode 100644 include/asm-sparc64/of_device.h (limited to 'drivers/input') diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 7f00189ed294..86c9fe3f3e4a 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -12,7 +12,7 @@ obj-y := process.o setup.o cpu.o idprom.o \ irq.o ptrace.o time.o sys_sparc.o signal.o \ unaligned.o central.o pci.o starfire.o semaphore.o \ power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \ - visemul.o prom.o + visemul.o prom.o of_device.o obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o pci_iommu.o \ pci_psycho.o pci_sabre.o pci_schizo.o \ diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index 33d79e10c653..b390a2f3a15e 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c @@ -475,6 +475,16 @@ probe_interrupts: } } + dev->ofdev.node = dp; + dev->ofdev.dev.parent = &dev->bus->ofdev.dev; + dev->ofdev.dev.bus = &ebus_bus_type; + strcpy(dev->ofdev.dev.bus_id, dp->path_component_name); + + /* Register with core */ + if (of_device_register(&dev->ofdev) != 0) + printk(KERN_DEBUG "ebus: device registration error for %s!\n", + dev->ofdev.dev.bus_id); + dp = dp->child; if (dp) { printk(" ->"); @@ -570,6 +580,17 @@ void __init ebus_init(void) ebus->self = pdev; ebus->parent = pbm = cookie->pbm; + ebus->ofdev.node = dp; + ebus->ofdev.dev.parent = &pdev->dev; + ebus->ofdev.dev.bus = &ebus_bus_type; + strcpy(ebus->ofdev.dev.bus_id, dp->path_component_name); + + /* Register with core */ + if (of_device_register(&ebus->ofdev) != 0) + printk(KERN_DEBUG "ebus: device registration error for %s!\n", + ebus->ofdev.dev.bus_id); + + child = dp->child; if (!child) goto next_ebus; diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c index 2693f2de549c..6f16dee280a8 100644 --- a/arch/sparc64/kernel/isa.c +++ b/arch/sparc64/kernel/isa.c @@ -195,12 +195,25 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); if (!isa_dev) { - fatal_err("cannot allocate isa_dev"); - prom_halt(); + printk(KERN_DEBUG "ISA: cannot allocate isa_dev"); + return; } memset(isa_dev, 0, sizeof(*isa_dev)); + isa_dev->ofdev.node = dp; + isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev; + isa_dev->ofdev.dev.bus = &isa_bus_type; + strcpy(isa_dev->ofdev.dev.bus_id, dp->path_component_name); + + /* Register with core */ + if (of_device_register(&isa_dev->ofdev) != 0) { + printk(KERN_DEBUG "isa: device registration error for %s!\n", + isa_dev->ofdev.dev.bus_id); + kfree(isa_dev); + goto next_sibling; + } + /* Link it in. */ isa_dev->next = NULL; if (isa_br->devices == NULL) { @@ -226,6 +239,7 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) printk("]"); + next_sibling: dp = dp->sibling; } } @@ -244,6 +258,7 @@ void __init isa_init(void) struct pcidev_cookie *pdev_cookie; struct pci_pbm_info *pbm; struct sparc_isa_bridge *isa_br; + struct device_node *dp; pdev_cookie = pdev->sysdata; if (!pdev_cookie) { @@ -252,15 +267,29 @@ void __init isa_init(void) continue; } pbm = pdev_cookie->pbm; + dp = pdev_cookie->prom_node; isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL); if (!isa_br) { - fatal_err("cannot allocate sparc_isa_bridge"); - prom_halt(); + printk(KERN_DEBUG "isa: cannot allocate sparc_isa_bridge"); + return; } memset(isa_br, 0, sizeof(*isa_br)); + isa_br->ofdev.node = dp; + isa_br->ofdev.dev.parent = &pdev->dev; + isa_br->ofdev.dev.bus = &isa_bus_type; + strcpy(isa_br->ofdev.dev.bus_id, dp->path_component_name); + + /* Register with core */ + if (of_device_register(&isa_br->ofdev) != 0) { + printk(KERN_DEBUG "isa: device registration error for %s!\n", + isa_br->ofdev.dev.bus_id); + kfree(isa_br); + return; + } + /* Link it in. */ isa_br->next = isa_chain; isa_chain = isa_br; diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c new file mode 100644 index 000000000000..566aa343aa62 --- /dev/null +++ b/arch/sparc64/kernel/of_device.c @@ -0,0 +1,279 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/** + * of_match_device - Tell if an of_device structure has a matching + * of_match structure + * @ids: array of of device match structures to search in + * @dev: the of device structure to match against + * + * Used by a driver to check whether an of_device present in the + * system is in its list of supported devices. + */ +const struct of_device_id *of_match_device(const struct of_device_id *matches, + const struct of_device *dev) +{ + if (!dev->node) + return NULL; + while (matches->name[0] || matches->type[0] || matches->compatible[0]) { + int match = 1; + if (matches->name[0]) + match &= dev->node->name + && !strcmp(matches->name, dev->node->name); + if (matches->type[0]) + match &= dev->node->type + && !strcmp(matches->type, dev->node->type); + if (matches->compatible[0]) + match &= of_device_is_compatible(dev->node, + matches->compatible); + if (match) + return matches; + matches++; + } + return NULL; +} + +static int of_platform_bus_match(struct device *dev, struct device_driver *drv) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * of_drv = to_of_platform_driver(drv); + const struct of_device_id * matches = of_drv->match_table; + + if (!matches) + return 0; + + return of_match_device(matches, of_dev) != NULL; +} + +struct of_device *of_dev_get(struct of_device *dev) +{ + struct device *tmp; + + if (!dev) + return NULL; + tmp = get_device(&dev->dev); + if (tmp) + return to_of_device(tmp); + else + return NULL; +} + +void of_dev_put(struct of_device *dev) +{ + if (dev) + put_device(&dev->dev); +} + + +static int of_device_probe(struct device *dev) +{ + int error = -ENODEV; + struct of_platform_driver *drv; + struct of_device *of_dev; + const struct of_device_id *match; + + drv = to_of_platform_driver(dev->driver); + of_dev = to_of_device(dev); + + if (!drv->probe) + return error; + + of_dev_get(of_dev); + + match = of_match_device(drv->match_table, of_dev); + if (match) + error = drv->probe(of_dev, match); + if (error) + of_dev_put(of_dev); + + return error; +} + +static int of_device_remove(struct device *dev) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + + if (dev->driver && drv->remove) + drv->remove(of_dev); + return 0; +} + +static int of_device_suspend(struct device *dev, pm_message_t state) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + int error = 0; + + if (dev->driver && drv->suspend) + error = drv->suspend(of_dev, state); + return error; +} + +static int of_device_resume(struct device * dev) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + int error = 0; + + if (dev->driver && drv->resume) + error = drv->resume(of_dev); + return error; +} + +#ifdef CONFIG_PCI +struct bus_type isa_bus_type = { + .name = "isa", + .match = of_platform_bus_match, + .probe = of_device_probe, + .remove = of_device_remove, + .suspend = of_device_suspend, + .resume = of_device_resume, +}; + +struct bus_type ebus_bus_type = { + .name = "ebus", + .match = of_platform_bus_match, + .probe = of_device_probe, + .remove = of_device_remove, + .suspend = of_device_suspend, + .resume = of_device_resume, +}; +#endif + +#ifdef CONFIG_SBUS +struct bus_type sbus_bus_type = { + .name = "sbus", + .match = of_platform_bus_match, + .probe = of_device_probe, + .remove = of_device_remove, + .suspend = of_device_suspend, + .resume = of_device_resume, +}; +#endif + +static int __init of_bus_driver_init(void) +{ + int err = 0; + +#ifdef CONFIG_PCI + if (!err) + err = bus_register(&isa_bus_type); + if (!err) + err = bus_register(&ebus_bus_type); +#endif +#ifdef CONFIG_SBUS + if (!err) + err = bus_register(&sbus_bus_type); +#endif + return 0; +} + +postcore_initcall(of_bus_driver_init); + +int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) +{ + /* initialize common driver fields */ + drv->driver.name = drv->name; + drv->driver.bus = bus; + + /* register with core */ + return driver_register(&drv->driver); +} + +void of_unregister_driver(struct of_platform_driver *drv) +{ + driver_unregister(&drv->driver); +} + + +static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct of_device *ofdev; + + ofdev = to_of_device(dev); + return sprintf(buf, "%s", ofdev->node->full_name); +} + +static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL); + +/** + * of_release_dev - free an of device structure when all users of it are finished. + * @dev: device that's been disconnected + * + * Will be called only by the device core when all users of this of device are + * done. + */ +void of_release_dev(struct device *dev) +{ + struct of_device *ofdev; + + ofdev = to_of_device(dev); + + kfree(ofdev); +} + +int of_device_register(struct of_device *ofdev) +{ + int rc; + + BUG_ON(ofdev->node == NULL); + + rc = device_register(&ofdev->dev); + if (rc) + return rc; + + device_create_file(&ofdev->dev, &dev_attr_devspec); + + return 0; +} + +void of_device_unregister(struct of_device *ofdev) +{ + device_remove_file(&ofdev->dev, &dev_attr_devspec); + device_unregister(&ofdev->dev); +} + +struct of_device* of_platform_device_create(struct device_node *np, + const char *bus_id, + struct device *parent, + struct bus_type *bus) +{ + struct of_device *dev; + + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return NULL; + memset(dev, 0, sizeof(*dev)); + + dev->dev.parent = parent; + dev->dev.bus = bus; + dev->dev.release = of_release_dev; + + strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); + + if (of_device_register(dev) != 0) { + kfree(dev); + return NULL; + } + + return dev; +} + +EXPORT_SYMBOL(of_match_device); +EXPORT_SYMBOL(of_register_driver); +EXPORT_SYMBOL(of_unregister_driver); +EXPORT_SYMBOL(of_device_register); +EXPORT_SYMBOL(of_device_unregister); +EXPORT_SYMBOL(of_dev_get); +EXPORT_SYMBOL(of_dev_put); +EXPORT_SYMBOL(of_platform_device_create); +EXPORT_SYMBOL(of_release_dev); diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index 75159a7843f1..9496c7734014 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc64/kernel/power.c @@ -115,66 +115,15 @@ static int __init has_button_interrupt(unsigned int irq, struct device_node *dp) return 1; } -static int __init power_probe_ebus(struct resource **resp, unsigned int *irq_p, struct device_node **prom_node_p) +static void __devinit power_probe_common(struct of_device *dev, struct resource *res, unsigned int irq) { - struct linux_ebus *ebus; - struct linux_ebus_device *edev; - - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_node->name, "power")) { - *resp = &edev->resource[0]; - *irq_p = edev->irqs[0]; - *prom_node_p = edev->prom_node; - return 0; - } - } - } - return -ENODEV; -} - -static int __init power_probe_isa(struct resource **resp, unsigned int *irq_p, struct device_node **prom_node_p) -{ - struct sparc_isa_bridge *isa_bus; - struct sparc_isa_device *isa_dev; - - for_each_isa(isa_bus) { - for_each_isadev(isa_dev, isa_bus) { - if (!strcmp(isa_dev->prom_node->name, "power")) { - *resp = &isa_dev->resource; - *irq_p = isa_dev->irq; - *prom_node_p = isa_dev->prom_node; - return 0; - } - } - } - return -ENODEV; -} - -void __init power_init(void) -{ - struct resource *res = NULL; - unsigned int irq; - struct device_node *dp; - static int invoked; - - if (invoked) - return; - invoked = 1; - - if (!power_probe_ebus(&res, &irq, &dp)) - goto found; - - if (!power_probe_isa(&res, &irq, &dp)) - goto found; - - return; - -found: power_reg = ioremap(res->start, 0x4); + printk("power: Control reg at %p ... ", power_reg); + poweroff_method = machine_halt; /* able to use the standard halt */ - if (has_button_interrupt(irq, dp)) { + + if (has_button_interrupt(irq, dev->node)) { if (kernel_thread(powerd, NULL, CLONE_FS) < 0) { printk("Failed to start power daemon.\n"); return; @@ -188,4 +137,52 @@ found: printk("not using powerd.\n"); } } + +static struct of_device_id power_match[] = { + { + .name = "power", + }, + {}, +}; + +static int __devinit ebus_power_probe(struct of_device *dev, const struct of_device_id *match) +{ + struct linux_ebus_device *edev = to_ebus_device(&dev->dev); + struct resource *res = &edev->resource[0]; + unsigned int irq = edev->irqs[0]; + + power_probe_common(dev, res,irq); + + return 0; +} + +static struct of_platform_driver ebus_power_driver = { + .name = "power", + .match_table = power_match, + .probe = ebus_power_probe, +}; + +static int __devinit isa_power_probe(struct of_device *dev, const struct of_device_id *match) +{ + struct sparc_isa_device *idev = to_isa_device(&dev->dev); + struct resource *res = &idev->resource; + unsigned int irq = idev->irq; + + power_probe_common(dev, res,irq); + + return 0; +} + +static struct of_platform_driver isa_power_driver = { + .name = "power", + .match_table = power_match, + .probe = isa_power_probe, +}; + +void __init power_init(void) +{ + of_register_driver(&ebus_power_driver, &ebus_bus_type); + of_register_driver(&isa_power_driver, &isa_bus_type); + return; +} #endif /* CONFIG_PCI */ diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 4bad588d0e5d..a6dfc7455733 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -26,7 +26,7 @@ config INPUT_PCSPKR config INPUT_SPARCSPKR tristate "SPARC Speaker support" - depends on PCI && SPARC + depends on PCI && SPARC64 help Say Y here if you want the standard Speaker on Sparc PCI systems to be used for bells and whistles. diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index ed95dc9420dd..42c11fbf3c79 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c @@ -2,7 +2,7 @@ * Driver for PC-speaker like devices found on various Sparc systems. * * Copyright (c) 2002 Vojtech Pavlik - * Copyright (c) 2002 David S. Miller (davem@redhat.com) + * Copyright (c) 2002, 2006 David S. Miller (davem@davemloft.net) */ #include #include @@ -13,21 +13,23 @@ #include #include -#ifdef CONFIG_SPARC64 #include -#endif -MODULE_AUTHOR("David S. Miller "); +MODULE_AUTHOR("David S. Miller "); MODULE_DESCRIPTION("Sparc Speaker beeper driver"); MODULE_LICENSE("GPL"); -const char *beep_name; -static unsigned long beep_iobase; -static int (*beep_event)(struct input_dev *dev, unsigned int type, unsigned int code, int value); -static DEFINE_SPINLOCK(beep_lock); +struct sparcspkr_state { + const char *name; + unsigned long iobase; + int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value); + spinlock_t lock; + struct input_dev *input_dev; +}; static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { + struct sparcspkr_state *state = dev_get_drvdata(dev->cdev.dev); unsigned int count = 0; unsigned long flags; @@ -43,24 +45,24 @@ static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned in if (value > 20 && value < 32767) count = 1193182 / value; - spin_lock_irqsave(&beep_lock, flags); + spin_lock_irqsave(&state->lock, flags); /* EBUS speaker only has on/off state, the frequency does not * appear to be programmable. */ - if (beep_iobase & 0x2UL) - outb(!!count, beep_iobase); + if (state->iobase & 0x2UL) + outb(!!count, state->iobase); else - outl(!!count, beep_iobase); + outl(!!count, state->iobase); - spin_unlock_irqrestore(&beep_lock, flags); + spin_unlock_irqrestore(&state->lock, flags); return 0; } -#ifdef CONFIG_SPARC64 static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { + struct sparcspkr_state *state = dev_get_drvdata(dev->cdev.dev); unsigned int count = 0; unsigned long flags; @@ -76,29 +78,29 @@ static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int if (value > 20 && value < 32767) count = 1193182 / value; - spin_lock_irqsave(&beep_lock, flags); + spin_lock_irqsave(&state->lock, flags); if (count) { /* enable counter 2 */ - outb(inb(beep_iobase + 0x61) | 3, beep_iobase + 0x61); + outb(inb(state->iobase + 0x61) | 3, state->iobase + 0x61); /* set command for counter 2, 2 byte write */ - outb(0xB6, beep_iobase + 0x43); + outb(0xB6, state->iobase + 0x43); /* select desired HZ */ - outb(count & 0xff, beep_iobase + 0x42); - outb((count >> 8) & 0xff, beep_iobase + 0x42); + outb(count & 0xff, state->iobase + 0x42); + outb((count >> 8) & 0xff, state->iobase + 0x42); } else { /* disable counter 2 */ - outb(inb_p(beep_iobase + 0x61) & 0xFC, beep_iobase + 0x61); + outb(inb_p(state->iobase + 0x61) & 0xFC, state->iobase + 0x61); } - spin_unlock_irqrestore(&beep_lock, flags); + spin_unlock_irqrestore(&state->lock, flags); return 0; } -#endif -static int __devinit sparcspkr_probe(struct platform_device *dev) +static int __devinit sparcspkr_probe(struct device *dev) { + struct sparcspkr_state *state = dev_get_drvdata(dev); struct input_dev *input_dev; int error; @@ -106,18 +108,18 @@ static int __devinit sparcspkr_probe(struct platform_device *dev) if (!input_dev) return -ENOMEM; - input_dev->name = beep_name; + input_dev->name = state->name; input_dev->phys = "sparc/input0"; input_dev->id.bustype = BUS_ISA; input_dev->id.vendor = 0x001f; input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &dev->dev; + input_dev->cdev.dev = dev; input_dev->evbit[0] = BIT(EV_SND); input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); - input_dev->event = beep_event; + input_dev->event = state->event; error = input_register_device(input_dev); if (error) { @@ -125,111 +127,137 @@ static int __devinit sparcspkr_probe(struct platform_device *dev) return error; } - platform_set_drvdata(dev, input_dev); + state->input_dev = input_dev; return 0; } -static int __devexit sparcspkr_remove(struct platform_device *dev) +static int __devexit sparcspkr_remove(struct of_device *dev) { - struct input_dev *input_dev = platform_get_drvdata(dev); + struct sparcspkr_state *state = dev_get_drvdata(&dev->dev); + struct input_dev *input_dev = state->input_dev; - input_unregister_device(input_dev); - platform_set_drvdata(dev, NULL); /* turn off the speaker */ - beep_event(NULL, EV_SND, SND_BELL, 0); + state->event(input_dev, EV_SND, SND_BELL, 0); + + input_unregister_device(input_dev); + + dev_set_drvdata(&dev->dev, NULL); + kfree(state); return 0; } -static void sparcspkr_shutdown(struct platform_device *dev) +static int sparcspkr_shutdown(struct of_device *dev) { + struct sparcspkr_state *state = dev_get_drvdata(&dev->dev); + struct input_dev *input_dev = state->input_dev; + /* turn off the speaker */ - beep_event(NULL, EV_SND, SND_BELL, 0); + state->event(input_dev, EV_SND, SND_BELL, 0); + + return 0; +} + +static int __devinit ebus_beep_probe(struct of_device *dev, const struct of_device_id *match) +{ + struct linux_ebus_device *edev = to_ebus_device(&dev->dev); + struct sparcspkr_state *state; + int err; + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + state->name = "Sparc EBUS Speaker"; + state->iobase = edev->resource[0].start; + state->event = ebus_spkr_event; + spin_lock_init(&state->lock); + + dev_set_drvdata(&dev->dev, state); + + err = sparcspkr_probe(&dev->dev); + if (err) { + dev_set_drvdata(&dev->dev, NULL); + kfree(state); + } + + return 0; } -static struct platform_driver sparcspkr_platform_driver = { - .driver = { - .name = "sparcspkr", - .owner = THIS_MODULE, +static struct of_device_id ebus_beep_match[] = { + { + .name = "beep", }, - .probe = sparcspkr_probe, - .remove = __devexit_p(sparcspkr_remove), - .shutdown = sparcspkr_shutdown, + {}, }; -static struct platform_device *sparcspkr_platform_device; +static struct of_platform_driver ebus_beep_driver = { + .name = "beep", + .match_table = ebus_beep_match, + .probe = ebus_beep_probe, + .remove = sparcspkr_remove, + .shutdown = sparcspkr_shutdown, +}; -static int __init sparcspkr_drv_init(void) +static int __devinit isa_beep_probe(struct of_device *dev, const struct of_device_id *match) { - int error; + struct sparc_isa_device *idev = to_isa_device(&dev->dev); + struct sparcspkr_state *state; + int err; - error = platform_driver_register(&sparcspkr_platform_driver); - if (error) - return error; + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; - sparcspkr_platform_device = platform_device_alloc("sparcspkr", -1); - if (!sparcspkr_platform_device) { - error = -ENOMEM; - goto err_unregister_driver; - } + state->name = "Sparc ISA Speaker"; + state->iobase = idev->resource.start; + state->event = isa_spkr_event; + spin_lock_init(&state->lock); + + dev_set_drvdata(&dev->dev, state); - error = platform_device_add(sparcspkr_platform_device); - if (error) - goto err_free_device; + err = sparcspkr_probe(&dev->dev); + if (err) { + dev_set_drvdata(&dev->dev, NULL); + kfree(state); + } return 0; +} - err_free_device: - platform_device_put(sparcspkr_platform_device); - err_unregister_driver: - platform_driver_unregister(&sparcspkr_platform_driver); +static struct of_device_id isa_beep_match[] = { + { + .name = "dma", + }, + {}, +}; - return error; -} +static struct of_platform_driver isa_beep_driver = { + .name = "beep", + .match_table = isa_beep_match, + .probe = isa_beep_probe, + .remove = sparcspkr_remove, + .shutdown = sparcspkr_shutdown, +}; static int __init sparcspkr_init(void) { - struct linux_ebus *ebus; - struct linux_ebus_device *edev; -#ifdef CONFIG_SPARC64 - struct sparc_isa_bridge *isa_br; - struct sparc_isa_device *isa_dev; -#endif - - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_node->name, "beep")) { - beep_name = "Sparc EBUS Speaker"; - beep_event = ebus_spkr_event; - beep_iobase = edev->resource[0].start; - return sparcspkr_drv_init(); - } - } - } -#ifdef CONFIG_SPARC64 - for_each_isa(isa_br) { - for_each_isadev(isa_dev, isa_br) { - /* A hack, the beep device's base lives in - * the DMA isa node. - */ - if (!strcmp(isa_dev->prom_node->name, "dma")) { - beep_name = "Sparc ISA Speaker"; - beep_event = isa_spkr_event, - beep_iobase = isa_dev->resource.start; - return sparcspkr_drv_init(); - } - } + int err = of_register_driver(&ebus_beep_driver, &ebus_bus_type); + + if (!err) { + err = of_register_driver(&isa_beep_driver, &isa_bus_type); + if (err) + of_unregister_driver(&ebus_beep_driver); } -#endif - return -ENODEV; + return err; } static void __exit sparcspkr_exit(void) { - platform_device_unregister(sparcspkr_platform_device); - platform_driver_unregister(&sparcspkr_platform_driver); + of_unregister_driver(&ebus_beep_driver); + of_unregister_driver(&isa_beep_driver); } module_init(sparcspkr_init); diff --git a/include/asm-sparc64/ebus.h b/include/asm-sparc64/ebus.h index 545882bd3563..a4afe9d5703a 100644 --- a/include/asm-sparc64/ebus.h +++ b/include/asm-sparc64/ebus.h @@ -11,6 +11,7 @@ #include #include #include +#include struct linux_ebus_child { struct linux_ebus_child *next; @@ -24,6 +25,7 @@ struct linux_ebus_child { }; struct linux_ebus_device { + struct of_device ofdev; struct linux_ebus_device *next; struct linux_ebus_child *children; struct linux_ebus *bus; @@ -33,8 +35,10 @@ struct linux_ebus_device { unsigned int irqs[PROMINTR_MAX]; int num_irqs; }; +#define to_ebus_device(d) container_of(d, struct linux_ebus_device, ofdev.dev) struct linux_ebus { + struct of_device ofdev; struct linux_ebus *next; struct linux_ebus_device *devices; struct pci_pbm_info *parent; @@ -43,6 +47,7 @@ struct linux_ebus { int is_rio; struct device_node *prom_node; }; +#define to_ebus(d) container_of(d, struct linux_ebus, ofdev.dev) struct ebus_dma_info { spinlock_t lock; diff --git a/include/asm-sparc64/isa.h b/include/asm-sparc64/isa.h index 2e7fb18ec1be..d9728b9031fc 100644 --- a/include/asm-sparc64/isa.h +++ b/include/asm-sparc64/isa.h @@ -10,10 +10,12 @@ #include #include #include +#include struct sparc_isa_bridge; struct sparc_isa_device { + struct of_device ofdev; struct sparc_isa_device *next; struct sparc_isa_device *child; struct sparc_isa_bridge *bus; @@ -21,8 +23,10 @@ struct sparc_isa_device { struct resource resource; unsigned int irq; }; +#define to_isa_device(d) container_of(d, struct sparc_isa_device, ofdev.dev) struct sparc_isa_bridge { + struct of_device ofdev; struct sparc_isa_bridge *next; struct sparc_isa_device *devices; struct pci_pbm_info *parent; @@ -30,6 +34,7 @@ struct sparc_isa_bridge { int index; struct device_node *prom_node; }; +#define to_isa_bridge(d) container_of(d, struct sparc_isa_bridge, ofdev.dev) extern struct sparc_isa_bridge *isa_chain; diff --git a/include/asm-sparc64/of_device.h b/include/asm-sparc64/of_device.h new file mode 100644 index 000000000000..ceea825899ce --- /dev/null +++ b/include/asm-sparc64/of_device.h @@ -0,0 +1,64 @@ +#ifndef _ASM_SPARC64_OF_DEVICE_H +#define _ASM_SPARC64_OF_DEVICE_H +#ifdef __KERNEL__ + +#include +#include +#include + +extern struct bus_type isa_bus_type; +extern struct bus_type ebus_bus_type; +extern struct bus_type sbus_bus_type; + +/* + * The of_device is a kind of "base class" that is a superset of + * struct device for use by devices attached to an OF node and + * probed using OF properties. + */ +struct of_device +{ + struct device_node *node; /* OF device node */ + struct device dev; /* Generic device interface */ +}; +#define to_of_device(d) container_of(d, struct of_device, dev) + +extern const struct of_device_id *of_match_device( + const struct of_device_id *matches, const struct of_device *dev); + +extern struct of_device *of_dev_get(struct of_device *dev); +extern void of_dev_put(struct of_device *dev); + +/* + * An of_platform_driver driver is attached to a basic of_device on + * the ISA, EBUS, and SBUS busses on sparc64. + */ +struct of_platform_driver +{ + char *name; + struct of_device_id *match_table; + struct module *owner; + + int (*probe)(struct of_device* dev, const struct of_device_id *match); + int (*remove)(struct of_device* dev); + + int (*suspend)(struct of_device* dev, pm_message_t state); + int (*resume)(struct of_device* dev); + int (*shutdown)(struct of_device* dev); + + struct device_driver driver; +}; +#define to_of_platform_driver(drv) container_of(drv,struct of_platform_driver, driver) + +extern int of_register_driver(struct of_platform_driver *drv, + struct bus_type *bus); +extern void of_unregister_driver(struct of_platform_driver *drv); +extern int of_device_register(struct of_device *ofdev); +extern void of_device_unregister(struct of_device *ofdev); +extern struct of_device *of_platform_device_create(struct device_node *np, + const char *bus_id, + struct device *parent, + struct bus_type *bus); +extern void of_release_dev(struct device *dev); + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_OF_DEVICE_H */ -- cgit v1.2.3-58-ga151 From 6ceab8a936c302c0cea2bfe55617c76e2f5746fa Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Sun, 25 Jun 2006 05:47:13 -0700 Subject: [PATCH] random: remove redundant SA_SAMPLE_RANDOM from touchscreen drivers The core input layer is already calling add_input_randomness. Signed-off-by: Matt Mackall Cc: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/input/touchscreen/ads7846.c | 3 +-- drivers/input/touchscreen/h3600_ts_input.c | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 161afddd0f44..386023c594d7 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -773,8 +773,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) ts->last_msg = m; - if (request_irq(spi->irq, ads7846_irq, - SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING, + if (request_irq(spi->irq, ads7846_irq, SA_TRIGGER_FALLING, spi->dev.driver->name, ts)) { dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); err = -EBUSY; diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c index a18d56bdafd9..a595d386312f 100644 --- a/drivers/input/touchscreen/h3600_ts_input.c +++ b/drivers/input/touchscreen/h3600_ts_input.c @@ -399,16 +399,14 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE); if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler, - SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, - "h3600_action", &ts->dev)) { + SA_SHIRQ | SA_INTERRUPT, "h3600_action", &ts->dev)) { printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n"); err = -EBUSY; goto fail2; } if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler, - SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, - "h3600_suspend", &ts->dev)) { + SA_SHIRQ | SA_INTERRUPT, "h3600_suspend", &ts->dev)) { printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n"); err = -EBUSY; goto fail3; -- cgit v1.2.3-58-ga151