diff options
Diffstat (limited to 'arch/sparc/kernel')
-rw-r--r-- | arch/sparc/kernel/ebus.c | 8 | ||||
-rw-r--r-- | arch/sparc/kernel/entry.S | 21 | ||||
-rw-r--r-- | arch/sparc/kernel/init_task.c | 1 | ||||
-rw-r--r-- | arch/sparc/kernel/irq.c | 111 | ||||
-rw-r--r-- | arch/sparc/kernel/irq.h | 68 | ||||
-rw-r--r-- | arch/sparc/kernel/of_device.c | 227 | ||||
-rw-r--r-- | arch/sparc/kernel/pcic.c | 1 | ||||
-rw-r--r-- | arch/sparc/kernel/process.c | 8 | ||||
-rw-r--r-- | arch/sparc/kernel/prom.c | 320 | ||||
-rw-r--r-- | arch/sparc/kernel/setup.c | 65 | ||||
-rw-r--r-- | arch/sparc/kernel/smp.c | 2 | ||||
-rw-r--r-- | arch/sparc/kernel/sparc_ksyms.c | 6 | ||||
-rw-r--r-- | arch/sparc/kernel/sun4c_irq.c | 15 | ||||
-rw-r--r-- | arch/sparc/kernel/sun4d_irq.c | 6 | ||||
-rw-r--r-- | arch/sparc/kernel/sun4d_smp.c | 1 | ||||
-rw-r--r-- | arch/sparc/kernel/sun4m_irq.c | 74 | ||||
-rw-r--r-- | arch/sparc/kernel/sun4m_smp.c | 2 | ||||
-rw-r--r-- | arch/sparc/kernel/systbls.S | 9 | ||||
-rw-r--r-- | arch/sparc/kernel/tick14.c | 6 | ||||
-rw-r--r-- | arch/sparc/kernel/time.c | 4 | ||||
-rw-r--r-- | arch/sparc/kernel/vmlinux.lds.S | 7 |
21 files changed, 462 insertions, 500 deletions
diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c index 7bb86b9cdaa..d850785b208 100644 --- a/arch/sparc/kernel/ebus.c +++ b/arch/sparc/kernel/ebus.c @@ -148,6 +148,7 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d { const struct linux_prom_registers *regs; struct linux_ebus_child *child; + struct dev_archdata *sd; const int *irqs; int i, n, len; unsigned long baseaddr; @@ -155,6 +156,8 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d dev->prom_node = dp; regs = of_get_property(dp, "reg", &len); + if (!regs) + len = 0; if (len % sizeof(struct linux_prom_registers)) { prom_printf("UGH: proplen for %s was %d, need multiple of %d\n", dev->prom_node->name, len, @@ -234,6 +237,11 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d } } + sd = &dev->ofdev.dev.archdata; + sd->prom_node = dp; + sd->op = &dev->ofdev; + sd->iommu = dev->bus->ofdev.dev.parent->archdata.iommu; + dev->ofdev.node = dp; dev->ofdev.dev.parent = &dev->bus->ofdev.dev; dev->ofdev.dev.bus = &ebus_bus_type; diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 831f540251f..88d2cefd01b 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -1,7 +1,6 @@ -/* $Id: entry.S,v 1.170 2001/11/13 00:57:05 davem Exp $ - * arch/sparc/kernel/entry.S: Sparc trap low-level entry points. +/* arch/sparc/kernel/entry.S: Sparc trap low-level entry points. * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net) * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) * Copyright (C) 1996-1999 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -129,7 +128,7 @@ trap_low: RESTORE_ALL #endif -#ifdef CONFIG_BLK_DEV_FD +#if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE) .text .align 4 .globl floppy_hardint @@ -1749,8 +1748,8 @@ fpload: __ndelay: save %sp, -STACKFRAME_SZ, %sp mov %i0, %o0 - call .umul - mov 0x1ad, %o1 ! 2**32 / (1 000 000 000 / HZ) + call .umul ! round multiplier up so large ns ok + mov 0x1ae, %o1 ! 2**32 / (1 000 000 000 / HZ) call .umul mov %i1, %o1 ! udelay_val ba delay_continue @@ -1760,11 +1759,17 @@ __ndelay: __udelay: save %sp, -STACKFRAME_SZ, %sp mov %i0, %o0 - sethi %hi(0x10c6), %o1 + sethi %hi(0x10c7), %o1 ! round multiplier up so large us ok call .umul - or %o1, %lo(0x10c6), %o1 ! 2**32 / 1 000 000 + or %o1, %lo(0x10c7), %o1 ! 2**32 / 1 000 000 call .umul mov %i1, %o1 ! udelay_val + sethi %hi(0x028f4b62), %l0 ! Add in rounding constant * 2**32, + or %g0, %lo(0x028f4b62), %l0 + addcc %o0, %l0, %o0 ! 2**32 * 0.009 999 + bcs,a 3f + add %o1, 0x01, %o1 +3: call .umul mov HZ, %o0 ! >>32 earlier for wider range diff --git a/arch/sparc/kernel/init_task.c b/arch/sparc/kernel/init_task.c index fc31de66b1c..d9d4f96360c 100644 --- a/arch/sparc/kernel/init_task.c +++ b/arch/sparc/kernel/init_task.c @@ -1,4 +1,5 @@ #include <linux/mm.h> +#include <linux/fs.h> #include <linux/module.h> #include <linux/sched.h> #include <linux/init_task.h> diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c index f257a67bcf9..b76dc03fc31 100644 --- a/arch/sparc/kernel/irq.c +++ b/arch/sparc/kernel/irq.c @@ -47,6 +47,8 @@ #include <asm/cacheflush.h> #include <asm/irq_regs.h> +#include "irq.h" + #ifdef CONFIG_SMP #define SMP_NOP2 "nop; nop;\n\t" #define SMP_NOP3 "nop; nop; nop;\n\t" @@ -268,7 +270,7 @@ void free_irq(unsigned int irq, void *dev_id) kfree(action); if (!sparc_irq[cpu_irq].action) - disable_irq(irq); + __disable_irq(irq); out_unlock: spin_unlock_irqrestore(&irq_action_lock, flags); @@ -349,34 +351,14 @@ void handler_irq(int irq, struct pt_regs * regs) set_irq_regs(old_regs); } -#ifdef CONFIG_BLK_DEV_FD -extern void floppy_interrupt(int irq, void *dev_id); - -void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs) -{ - struct pt_regs *old_regs; - int cpu = smp_processor_id(); - - old_regs = set_irq_regs(regs); - disable_pil_irq(irq); - irq_enter(); - kstat_cpu(cpu).irqs[irq]++; - floppy_interrupt(irq, dev_id); - irq_exit(); - enable_pil_irq(irq); - set_irq_regs(old_regs); - // XXX Eek, it's totally changed with preempt_count() and such - // if (softirq_pending(cpu)) - // do_softirq(); -} -#endif +#if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE) /* Fast IRQs on the Sparc can only have one routine attached to them, * thus no sharing possible. */ -int request_fast_irq(unsigned int irq, - irq_handler_t handler, - unsigned long irqflags, const char *devname) +static int request_fast_irq(unsigned int irq, + void (*handler)(void), + unsigned long irqflags, const char *devname) { struct irqaction *action; unsigned long flags; @@ -455,7 +437,6 @@ int request_fast_irq(unsigned int irq, */ flush_cache_all(); - action->handler = handler; action->flags = irqflags; cpus_clear(action->mask); action->name = devname; @@ -464,7 +445,7 @@ int request_fast_irq(unsigned int irq, sparc_irq[cpu_irq].action = action; - enable_irq(irq); + __enable_irq(irq); ret = 0; out_unlock: @@ -473,6 +454,61 @@ out: return ret; } +/* These variables are used to access state from the assembler + * interrupt handler, floppy_hardint, so we cannot put these in + * the floppy driver image because that would not work in the + * modular case. + */ +volatile unsigned char *fdc_status; +EXPORT_SYMBOL(fdc_status); + +char *pdma_vaddr; +EXPORT_SYMBOL(pdma_vaddr); + +unsigned long pdma_size; +EXPORT_SYMBOL(pdma_size); + +volatile int doing_pdma; +EXPORT_SYMBOL(doing_pdma); + +char *pdma_base; +EXPORT_SYMBOL(pdma_base); + +unsigned long pdma_areasize; +EXPORT_SYMBOL(pdma_areasize); + +extern void floppy_hardint(void); + +static irqreturn_t (*floppy_irq_handler)(int irq, void *dev_id); + +void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + struct pt_regs *old_regs; + int cpu = smp_processor_id(); + + old_regs = set_irq_regs(regs); + disable_pil_irq(irq); + irq_enter(); + kstat_cpu(cpu).irqs[irq]++; + floppy_irq_handler(irq, dev_id); + irq_exit(); + enable_pil_irq(irq); + set_irq_regs(old_regs); + // XXX Eek, it's totally changed with preempt_count() and such + // if (softirq_pending(cpu)) + // do_softirq(); +} + +int sparc_floppy_request_irq(int irq, unsigned long flags, + irqreturn_t (*irq_handler)(int irq, void *)) +{ + floppy_irq_handler = irq_handler; + return request_fast_irq(irq, floppy_hardint, flags, "floppy"); +} +EXPORT_SYMBOL(sparc_floppy_request_irq); + +#endif + int request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char * devname, void *dev_id) @@ -544,7 +580,7 @@ int request_irq(unsigned int irq, *actionp = action; - enable_irq(irq); + __enable_irq(irq); ret = 0; out_unlock: @@ -555,6 +591,25 @@ out: EXPORT_SYMBOL(request_irq); +void disable_irq_nosync(unsigned int irq) +{ + return __disable_irq(irq); +} +EXPORT_SYMBOL(disable_irq_nosync); + +void disable_irq(unsigned int irq) +{ + return __disable_irq(irq); +} +EXPORT_SYMBOL(disable_irq); + +void enable_irq(unsigned int irq) +{ + return __enable_irq(irq); +} + +EXPORT_SYMBOL(enable_irq); + /* We really don't need these at all on the Sparc. We only have * stubs here because they are exported to modules. */ diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h new file mode 100644 index 00000000000..32ef3ebd0a8 --- /dev/null +++ b/arch/sparc/kernel/irq.h @@ -0,0 +1,68 @@ +#include <asm/btfixup.h> + +/* Dave Redman (djhr@tadpole.co.uk) + * changed these to function pointers.. it saves cycles and will allow + * the irq dependencies to be split into different files at a later date + * sun4c_irq.c, sun4m_irq.c etc so we could reduce the kernel size. + * Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * Changed these to btfixup entities... It saves cycles :) + */ + +BTFIXUPDEF_CALL(void, disable_irq, unsigned int) +BTFIXUPDEF_CALL(void, enable_irq, unsigned int) +BTFIXUPDEF_CALL(void, disable_pil_irq, unsigned int) +BTFIXUPDEF_CALL(void, enable_pil_irq, unsigned int) +BTFIXUPDEF_CALL(void, clear_clock_irq, void) +BTFIXUPDEF_CALL(void, clear_profile_irq, int) +BTFIXUPDEF_CALL(void, load_profile_irq, int, unsigned int) + +static inline void __disable_irq(unsigned int irq) +{ + BTFIXUP_CALL(disable_irq)(irq); +} + +static inline void __enable_irq(unsigned int irq) +{ + BTFIXUP_CALL(enable_irq)(irq); +} + +static inline void disable_pil_irq(unsigned int irq) +{ + BTFIXUP_CALL(disable_pil_irq)(irq); +} + +static inline void enable_pil_irq(unsigned int irq) +{ + BTFIXUP_CALL(enable_pil_irq)(irq); +} + +static inline void clear_clock_irq(void) +{ + BTFIXUP_CALL(clear_clock_irq)(); +} + +static inline void clear_profile_irq(int irq) +{ + BTFIXUP_CALL(clear_profile_irq)(irq); +} + +static inline void load_profile_irq(int cpu, int limit) +{ + BTFIXUP_CALL(load_profile_irq)(cpu, limit); +} + +extern void (*sparc_init_timers)(irq_handler_t lvl10_irq); + +extern void claim_ticker14(irq_handler_t irq_handler, + int irq, + unsigned int timeout); + +#ifdef CONFIG_SMP +BTFIXUPDEF_CALL(void, set_cpu_int, int, int) +BTFIXUPDEF_CALL(void, clear_cpu_int, int, int) +BTFIXUPDEF_CALL(void, set_irq_udt, int) + +#define set_cpu_int(cpu,level) BTFIXUP_CALL(set_cpu_int)(cpu,level) +#define clear_cpu_int(cpu,level) BTFIXUP_CALL(clear_cpu_int)(cpu,level) +#define set_irq_udt(cpu) BTFIXUP_CALL(set_irq_udt)(cpu) +#endif diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index fd7f8cb668a..36383f73d68 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c @@ -1,132 +1,13 @@ #include <linux/string.h> #include <linux/kernel.h> +#include <linux/of.h> #include <linux/init.h> #include <linux/module.h> #include <linux/mod_devicetable.h> #include <linux/slab.h> - -#include <asm/errno.h> -#include <asm/of_device.h> - -/** - * 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; -} +#include <linux/errno.h> +#include <linux/of_device.h> +#include <linux/of_platform.h> static int node_match(struct device *dev, void *data) { @@ -138,7 +19,7 @@ static int node_match(struct device *dev, void *data) struct of_device *of_find_device_by_node(struct device_node *dp) { - struct device *dev = bus_find_device(&of_bus_type, NULL, + struct device *dev = bus_find_device(&of_platform_bus_type, NULL, dp, node_match); if (dev) @@ -149,38 +30,17 @@ struct of_device *of_find_device_by_node(struct device_node *dp) EXPORT_SYMBOL(of_find_device_by_node); #ifdef CONFIG_PCI -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, -}; +struct bus_type ebus_bus_type; EXPORT_SYMBOL(ebus_bus_type); #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, -}; +struct bus_type sbus_bus_type; EXPORT_SYMBOL(sbus_bus_type); #endif -struct bus_type of_bus_type = { - .name = "of", - .match = of_platform_bus_match, - .probe = of_device_probe, - .remove = of_device_remove, - .suspend = of_device_suspend, - .resume = of_device_resume, -}; -EXPORT_SYMBOL(of_bus_type); +struct bus_type of_platform_bus_type; +EXPORT_SYMBOL(of_platform_bus_type); static inline u64 of_read_addr(const u32 *cell, int size) { @@ -560,11 +420,16 @@ static struct of_device * __init scan_one_device(struct device_node *dp, { struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL); const struct linux_prom_irqs *intr; + struct dev_archdata *sd; int len, i; if (!op) return NULL; + sd = &op->dev.archdata; + sd->prom_node = dp; + sd->op = op; + op->node = dp; op->clock_freq = of_getintprop_default(dp, "clock-frequency", @@ -646,7 +511,7 @@ build_resources: build_device_resources(op, parent); op->dev.parent = parent; - op->dev.bus = &of_bus_type; + op->dev.bus = &of_platform_bus_type; if (!parent) strcpy(op->dev.bus_id, "root"); else @@ -690,14 +555,14 @@ static int __init of_bus_driver_init(void) { int err; - err = bus_register(&of_bus_type); + err = of_bus_type_init(&of_platform_bus_type, "of"); #ifdef CONFIG_PCI if (!err) - err = bus_register(&ebus_bus_type); + err = of_bus_type_init(&ebus_bus_type, "ebus"); #endif #ifdef CONFIG_SBUS if (!err) - err = bus_register(&sbus_bus_type); + err = of_bus_type_init(&sbus_bus_type, "sbus"); #endif if (!err) @@ -735,56 +600,6 @@ 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; - - rc = device_create_file(&ofdev->dev, &dev_attr_devspec); - if (rc) - device_unregister(&ofdev->dev); - - return rc; -} - -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, @@ -810,12 +625,6 @@ struct of_device* of_platform_device_create(struct device_node *np, 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/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 79177119690..f2eae457fc9 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -36,6 +36,7 @@ #include <asm/uaccess.h> #include <asm/irq_regs.h> +#include "irq.h" /* * I studied different documents and many live PROMs both from 2.30 diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 8c37f8f5adb..33f7a3ddb10 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -39,6 +39,7 @@ #include <asm/processor.h> #include <asm/psr.h> #include <asm/elf.h> +#include <asm/prom.h> #include <asm/unistd.h> /* @@ -150,7 +151,7 @@ void machine_halt(void) local_irq_enable(); mdelay(8); local_irq_disable(); - if (!serial_console && prom_palette) + if (prom_palette) prom_palette (1); prom_halt(); panic("Halt failed!"); @@ -166,7 +167,7 @@ void machine_restart(char * cmd) p = strchr (reboot_command, '\n'); if (p) *p = 0; - if (!serial_console && prom_palette) + if (prom_palette) prom_palette (1); if (cmd) prom_reboot(cmd); @@ -179,7 +180,8 @@ void machine_restart(char * cmd) void machine_power_off(void) { #ifdef CONFIG_SUN_AUXIO - if (auxio_power_register && (!serial_console || scons_pwroff)) + if (auxio_power_register && + (strcmp(of_console_device->type, "serial") || scons_pwroff)) *auxio_power_register |= AUXIO_POWER_OFF; #endif machine_halt(); diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c index eed140b3c73..cd4fb79aa3a 100644 --- a/arch/sparc/kernel/prom.c +++ b/arch/sparc/kernel/prom.c @@ -25,73 +25,9 @@ #include <asm/prom.h> #include <asm/oplib.h> -static struct device_node *allnodes; +extern struct device_node *allnodes; /* temporary while merging */ -/* use when traversing tree through the allnext, child, sibling, - * or parent members of struct device_node. - */ -static DEFINE_RWLOCK(devtree_lock); - -int of_device_is_compatible(const struct device_node *device, - const char *compat) -{ - const char* cp; - int cplen, l; - - cp = of_get_property(device, "compatible", &cplen); - if (cp == NULL) - return 0; - while (cplen > 0) { - if (strncmp(cp, compat, strlen(compat)) == 0) - return 1; - l = strlen(cp) + 1; - cp += l; - cplen -= l; - } - - return 0; -} -EXPORT_SYMBOL(of_device_is_compatible); - -struct device_node *of_get_parent(const struct device_node *node) -{ - struct device_node *np; - - if (!node) - return NULL; - - np = node->parent; - - return np; -} -EXPORT_SYMBOL(of_get_parent); - -struct device_node *of_get_next_child(const struct device_node *node, - struct device_node *prev) -{ - struct device_node *next; - - next = prev ? prev->sibling : node->child; - for (; next != 0; next = next->sibling) { - break; - } - - return next; -} -EXPORT_SYMBOL(of_get_next_child); - -struct device_node *of_find_node_by_path(const char *path) -{ - struct device_node *np = allnodes; - - for (; np != 0; np = np->allnext) { - if (np->full_name != 0 && strcmp(np->full_name, path) == 0) - break; - } - - return np; -} -EXPORT_SYMBOL(of_find_node_by_path); +extern rwlock_t devtree_lock; /* temporary while merging */ struct device_node *of_find_node_by_phandle(phandle handle) { @@ -105,81 +41,6 @@ struct device_node *of_find_node_by_phandle(phandle handle) } EXPORT_SYMBOL(of_find_node_by_phandle); -struct device_node *of_find_node_by_name(struct device_node *from, - const char *name) -{ - struct device_node *np; - - np = from ? from->allnext : allnodes; - for (; np != NULL; np = np->allnext) - if (np->name != NULL && strcmp(np->name, name) == 0) - break; - - return np; -} -EXPORT_SYMBOL(of_find_node_by_name); - -struct device_node *of_find_node_by_type(struct device_node *from, - const char *type) -{ - struct device_node *np; - - np = from ? from->allnext : allnodes; - for (; np != 0; np = np->allnext) - if (np->type != 0 && strcmp(np->type, type) == 0) - break; - - return np; -} -EXPORT_SYMBOL(of_find_node_by_type); - -struct device_node *of_find_compatible_node(struct device_node *from, - const char *type, const char *compatible) -{ - struct device_node *np; - - np = from ? from->allnext : allnodes; - for (; np != 0; np = np->allnext) { - if (type != NULL - && !(np->type != 0 && strcmp(np->type, type) == 0)) - continue; - if (of_device_is_compatible(np, compatible)) - break; - } - - return np; -} -EXPORT_SYMBOL(of_find_compatible_node); - -struct property *of_find_property(const struct device_node *np, - const char *name, - int *lenp) -{ - struct property *pp; - - for (pp = np->properties; pp != 0; pp = pp->next) { - if (strcasecmp(pp->name, name) == 0) { - if (lenp != 0) - *lenp = pp->length; - break; - } - } - return pp; -} -EXPORT_SYMBOL(of_find_property); - -/* - * Find a property with a given name for a given node - * and return the value. - */ -const void *of_get_property(const struct device_node *np, const char *name, - int *lenp) -{ - struct property *pp = of_find_property(np,name,lenp); - return pp ? pp->value : NULL; -} -EXPORT_SYMBOL(of_get_property); - int of_getintprop_default(struct device_node *np, const char *name, int def) { struct property *prop; @@ -193,36 +54,6 @@ int of_getintprop_default(struct device_node *np, const char *name, int def) } EXPORT_SYMBOL(of_getintprop_default); -int of_n_addr_cells(struct device_node *np) -{ - const int* ip; - do { - if (np->parent) - np = np->parent; - ip = of_get_property(np, "#address-cells", NULL); - if (ip != NULL) - return *ip; - } while (np->parent); - /* No #address-cells property for the root node, default to 2 */ - return 2; -} -EXPORT_SYMBOL(of_n_addr_cells); - -int of_n_size_cells(struct device_node *np) -{ - const int* ip; - do { - if (np->parent) - np = np->parent; - ip = of_get_property(np, "#size-cells", NULL); - if (ip != NULL) - return *ip; - } while (np->parent); - /* No #size-cells property for the root node, default to 1 */ - return 1; -} -EXPORT_SYMBOL(of_n_size_cells); - int of_set_property(struct device_node *dp, const char *name, void *val, int len) { struct property **prevp; @@ -271,6 +102,21 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len } EXPORT_SYMBOL(of_set_property); +int of_find_in_proplist(const char *list, const char *match, int len) +{ + while (len > 0) { + int l; + + if (!strcmp(list, match)) + return 1; + l = strlen(list) + 1; + list += l; + len -= l; + } + return 0; +} +EXPORT_SYMBOL(of_find_in_proplist); + static unsigned int prom_early_allocated; static void * __init prom_early_alloc(unsigned long size) @@ -566,6 +412,136 @@ static struct device_node * __init build_tree(struct device_node *parent, phandl return dp; } +struct device_node *of_console_device; +EXPORT_SYMBOL(of_console_device); + +char *of_console_path; +EXPORT_SYMBOL(of_console_path); + +char *of_console_options; +EXPORT_SYMBOL(of_console_options); + +extern void restore_current(void); + +static void __init of_console_init(void) +{ + char *msg = "OF stdout device is: %s\n"; + struct device_node *dp; + unsigned long flags; + const char *type; + phandle node; + int skip, tmp, fd; + + of_console_path = prom_early_alloc(256); + + switch (prom_vers) { + case PROM_V0: + case PROM_SUN4: + skip = 0; + switch (*romvec->pv_stdout) { + case PROMDEV_SCREEN: + type = "display"; + break; + + case PROMDEV_TTYB: + skip = 1; + /* FALLTHRU */ + + case PROMDEV_TTYA: + type = "serial"; + break; + + default: + prom_printf("Invalid PROM_V0 stdout value %u\n", + *romvec->pv_stdout); + prom_halt(); + } + + tmp = skip; + for_each_node_by_type(dp, type) { + if (!tmp--) + break; + } + if (!dp) { + prom_printf("Cannot find PROM_V0 console node.\n"); + prom_halt(); + } + of_console_device = dp; + + strcpy(of_console_path, dp->full_name); + if (!strcmp(type, "serial")) { + strcat(of_console_path, + (skip ? ":b" : ":a")); + } + break; + + default: + case PROM_V2: + case PROM_V3: + fd = *romvec->pv_v2bootargs.fd_stdout; + + spin_lock_irqsave(&prom_lock, flags); + node = (*romvec->pv_v2devops.v2_inst2pkg)(fd); + restore_current(); + spin_unlock_irqrestore(&prom_lock, flags); + + if (!node) { + prom_printf("Cannot resolve stdout node from " + "instance %08x.\n", fd); + prom_halt(); + } + dp = of_find_node_by_phandle(node); + type = of_get_property(dp, "device_type", NULL); + + if (!type) { + prom_printf("Console stdout lacks " + "device_type property.\n"); + prom_halt(); + } + + if (strcmp(type, "display") && strcmp(type, "serial")) { + prom_printf("Console device_type is neither display " + "nor serial.\n"); + prom_halt(); + } + + of_console_device = dp; + + if (prom_vers == PROM_V2) { + strcpy(of_console_path, dp->full_name); + switch (*romvec->pv_stdout) { + case PROMDEV_TTYA: + strcat(of_console_path, ":a"); + break; + case PROMDEV_TTYB: + strcat(of_console_path, ":b"); + break; + } + } else { + const char *path; + + dp = of_find_node_by_path("/"); + path = of_get_property(dp, "stdout-path", NULL); + if (!path) { + prom_printf("No stdout-path in root node.\n"); + prom_halt(); + } + strcpy(of_console_path, path); + } + break; + } + + of_console_options = strrchr(of_console_path, ':'); + if (of_console_options) { + of_console_options++; + if (*of_console_options == '\0') + of_console_options = NULL; + } + + prom_printf(msg, of_console_path); + printk(msg, of_console_path); +} + void __init prom_build_devicetree(void) { struct device_node **nextp; @@ -578,6 +554,8 @@ void __init prom_build_devicetree(void) allnodes->child = build_tree(allnodes, prom_getchild(allnodes->node), &nextp); + of_console_init(); + printk("PROM: Built device tree with %u bytes of memory.\n", prom_early_allocated); } diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index 64c0ed98820..f8228383895 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c @@ -146,31 +146,6 @@ static void __init process_switch(char c) } } -static void __init process_console(char *commands) -{ - serial_console = 0; - commands += 8; - /* Linux-style serial */ - if (!strncmp(commands, "ttyS", 4)) - serial_console = simple_strtoul(commands + 4, NULL, 10) + 1; - else if (!strncmp(commands, "tty", 3)) { - char c = *(commands + 3); - /* Solaris-style serial */ - if (c == 'a' || c == 'b') - serial_console = c - 'a' + 1; - /* else Linux-style fbcon, not serial */ - } -#if defined(CONFIG_PROM_CONSOLE) - if (!strncmp(commands, "prom", 4)) { - char *p; - - for (p = commands - 8; *p && *p != ' '; p++) - *p = ' '; - conswitchp = &prom_con; - } -#endif -} - static void __init boot_flags_init(char *commands) { while (*commands) { @@ -187,9 +162,7 @@ static void __init boot_flags_init(char *commands) process_switch(*commands++); continue; } - if (!strncmp(commands, "console=", 8)) { - process_console(commands); - } else if (!strncmp(commands, "mem=", 4)) { + if (!strncmp(commands, "mem=", 4)) { /* * "mem=XXX[kKmM] overrides the PROM-reported * memory size. @@ -341,41 +314,6 @@ void __init setup_arch(char **cmdline_p) smp_setup_cpu_possible_map(); } -static int __init set_preferred_console(void) -{ - int idev, odev; - - /* The user has requested a console so this is already set up. */ - if (serial_console >= 0) - return -EBUSY; - - idev = prom_query_input_device(); - odev = prom_query_output_device(); - if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) { - serial_console = 0; - } else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) { - serial_console = 1; - } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) { - serial_console = 2; - } else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OTTYA) { - prom_printf("MrCoffee ttya\n"); - serial_console = 1; - } else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OSCREEN) { - serial_console = 0; - prom_printf("MrCoffee keyboard\n"); - } else { - prom_printf("Confusing console (idev %d, odev %d)\n", - idev, odev); - serial_console = 1; - } - - if (serial_console) - return add_preferred_console("ttyS", serial_console - 1, NULL); - - return -ENODEV; -} -console_initcall(set_preferred_console); - extern char *sparc_cpu_type; extern char *sparc_fpu_type; @@ -461,7 +399,6 @@ void sun_do_break(void) prom_cmdline(); } -int serial_console = -1; int stop_a_enabled = 1; static int __init topology_init(void) diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c index 4fea3ac7bff..6724ab90f82 100644 --- a/arch/sparc/kernel/smp.c +++ b/arch/sparc/kernel/smp.c @@ -33,6 +33,8 @@ #include <asm/tlbflush.h> #include <asm/cpudata.h> +#include "irq.h" + int smp_num_cpus = 1; volatile unsigned long cpu_callin_map[NR_CPUS] __initdata = {0,}; unsigned char boot_cpu_id = 0; diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index d8e008a04e2..ef647acc479 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -143,7 +143,6 @@ EXPORT_SYMBOL(mstk48t02_regs); EXPORT_SYMBOL(set_auxio); EXPORT_SYMBOL(get_auxio); #endif -EXPORT_SYMBOL(request_fast_irq); EXPORT_SYMBOL(io_remap_pfn_range); /* P3: iounit_xxx may be needed, sun4d users */ /* EXPORT_SYMBOL(iounit_map_dma_init); */ @@ -154,8 +153,6 @@ EXPORT_SYMBOL(BTFIXUP_CALL(___xchg32)); #else EXPORT_SYMBOL(BTFIXUP_CALL(__hard_smp_processor_id)); #endif -EXPORT_SYMBOL(BTFIXUP_CALL(enable_irq)); -EXPORT_SYMBOL(BTFIXUP_CALL(disable_irq)); EXPORT_SYMBOL(BTFIXUP_CALL(mmu_unlockarea)); EXPORT_SYMBOL(BTFIXUP_CALL(mmu_lockarea)); EXPORT_SYMBOL(BTFIXUP_CALL(mmu_get_scsi_sgl)); @@ -163,6 +160,8 @@ EXPORT_SYMBOL(BTFIXUP_CALL(mmu_get_scsi_one)); EXPORT_SYMBOL(BTFIXUP_CALL(mmu_release_scsi_sgl)); EXPORT_SYMBOL(BTFIXUP_CALL(mmu_release_scsi_one)); +EXPORT_SYMBOL(BTFIXUP_CALL(pgprot_noncached)); + #ifdef CONFIG_SBUS EXPORT_SYMBOL(sbus_root); EXPORT_SYMBOL(dma_chain); @@ -262,6 +261,7 @@ EXPORT_SYMBOL(__memmove); /* Moving data to/from userspace. */ EXPORT_SYMBOL(__copy_user); EXPORT_SYMBOL(__strncpy_from_user); +EXPORT_SYMBOL(__strnlen_user); /* Networking helper routines. */ EXPORT_SYMBOL(__csum_partial_copy_sparc_generic); diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index 009e891a432..c6ac9fc5256 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -18,6 +18,7 @@ #include <linux/interrupt.h> #include <linux/slab.h> #include <linux/init.h> +#include "irq.h" #include <asm/ptrace.h> #include <asm/processor.h> @@ -40,6 +41,20 @@ static struct resource sun4c_timer_eb = { "sun4c_timer" }; static struct resource sun4c_intr_eb = { "sun4c_intr" }; #endif +/* + * Bit field defines for the interrupt registers on various + * Sparc machines. + */ + +/* The sun4c interrupt register. */ +#define SUN4C_INT_ENABLE 0x01 /* Allow interrupts. */ +#define SUN4C_INT_E14 0x80 /* Enable level 14 IRQ. */ +#define SUN4C_INT_E10 0x20 /* Enable level 10 IRQ. */ +#define SUN4C_INT_E8 0x10 /* Enable level 8 IRQ. */ +#define SUN4C_INT_E6 0x08 /* Enable level 6 IRQ. */ +#define SUN4C_INT_E4 0x04 /* Enable level 4 IRQ. */ +#define SUN4C_INT_E1 0x02 /* Enable level 1 IRQ. */ + /* Pointer to the interrupt enable byte * * Dave Redman (djhr@tadpole.co.uk) diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index 396797e20c3..e0efab2a6be 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -39,6 +39,8 @@ #include <asm/cacheflush.h> #include <asm/irq_regs.h> +#include "irq.h" + /* If you trust current SCSI layer to handle different SCSI IRQs, enable this. I don't trust it... -jj */ /* #define DISTRIBUTE_IRQS */ @@ -188,7 +190,7 @@ void sun4d_free_irq(unsigned int irq, void *dev_id) kfree(action); if (!(*actionp)) - disable_irq(irq); + __disable_irq(irq); out_unlock: spin_unlock_irqrestore(&irq_action_lock, flags); @@ -346,7 +348,7 @@ int sun4d_request_irq(unsigned int irq, else *actionp = action; - enable_irq(irq); + __enable_irq(irq); ret = 0; out_unlock: diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index 098c94f1a32..89a6de95070 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -36,6 +36,7 @@ #include <asm/cacheflush.h> #include <asm/cpudata.h> +#include "irq.h" #define IRQ_CROSS_CALL 15 extern ctxd_t *srmmu_ctx_table_phys; diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 91a803ea88b..b92d6d2d5b0 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -38,11 +38,85 @@ #include <asm/sbus.h> #include <asm/cacheflush.h> +#include "irq.h" + +/* On the sun4m, just like the timers, we have both per-cpu and master + * interrupt registers. + */ + +/* These registers are used for sending/receiving irqs from/to + * different cpu's. + */ +struct sun4m_intreg_percpu { + unsigned int tbt; /* Interrupts still pending for this cpu. */ + + /* These next two registers are WRITE-ONLY and are only + * "on bit" sensitive, "off bits" written have NO affect. + */ + unsigned int clear; /* Clear this cpus irqs here. */ + unsigned int set; /* Set this cpus irqs here. */ + unsigned char space[PAGE_SIZE - 12]; +}; + +/* + * djhr + * Actually the clear and set fields in this struct are misleading.. + * according to the SLAVIO manual (and the same applies for the SEC) + * the clear field clears bits in the mask which will ENABLE that IRQ + * the set field sets bits in the mask to DISABLE the IRQ. + * + * Also the undirected_xx address in the SLAVIO is defined as + * RESERVED and write only.. + * + * DAVEM_NOTE: The SLAVIO only specifies behavior on uniprocessor + * sun4m machines, for MP the layout makes more sense. + */ +struct sun4m_intregs { + struct sun4m_intreg_percpu cpu_intregs[SUN4M_NCPUS]; + unsigned int tbt; /* IRQ's that are still pending. */ + unsigned int irqs; /* Master IRQ bits. */ + + /* Again, like the above, two these registers are WRITE-ONLY. */ + unsigned int clear; /* Clear master IRQ's by setting bits here. */ + unsigned int set; /* Set master IRQ's by setting bits here. */ + + /* This register is both READ and WRITE. */ + unsigned int undirected_target; /* Which cpu gets undirected irqs. */ +}; + static unsigned long dummy; struct sun4m_intregs *sun4m_interrupts; unsigned long *irq_rcvreg = &dummy; +/* Dave Redman (djhr@tadpole.co.uk) + * The sun4m interrupt registers. + */ +#define SUN4M_INT_ENABLE 0x80000000 +#define SUN4M_INT_E14 0x00000080 +#define SUN4M_INT_E10 0x00080000 + +#define SUN4M_HARD_INT(x) (0x000000001 << (x)) +#define SUN4M_SOFT_INT(x) (0x000010000 << (x)) + +#define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */ +#define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */ +#define SUN4M_INT_M2S_WRITE 0x20000000 /* write buffer error */ +#define SUN4M_INT_ECC 0x10000000 /* ecc memory error */ +#define SUN4M_INT_FLOPPY 0x00400000 /* floppy disk */ +#define SUN4M_INT_MODULE 0x00200000 /* module interrupt */ +#define SUN4M_INT_VIDEO 0x00100000 /* onboard video */ +#define SUN4M_INT_REALTIME 0x00080000 /* system timer */ +#define SUN4M_INT_SCSI 0x00040000 /* onboard scsi */ +#define SUN4M_INT_AUDIO 0x00020000 /* audio/isdn */ +#define SUN4M_INT_ETHERNET 0x00010000 /* onboard ethernet */ +#define SUN4M_INT_SERIAL 0x00008000 /* serial ports */ +#define SUN4M_INT_KBDMS 0x00004000 /* keyboard/mouse */ +#define SUN4M_INT_SBUSBITS 0x00003F80 /* sbus int bits */ + +#define SUN4M_INT_SBUS(x) (1 << (x+7)) +#define SUN4M_INT_VME(x) (1 << (x)) + /* These tables only apply for interrupts greater than 15.. * * any intr value below 0x10 is considered to be a soft-int diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index 63ed19bfd02..730eb5796f8 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -31,6 +31,8 @@ #include <asm/oplib.h> #include <asm/cpudata.h> +#include "irq.h" + #define IRQ_RESCHEDULE 13 #define IRQ_STOP_CPU 14 #define IRQ_CROSS_CALL 15 diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S index 90b52d4dab9..55722840859 100644 --- a/arch/sparc/kernel/systbls.S +++ b/arch/sparc/kernel/systbls.S @@ -1,8 +1,7 @@ -/* $Id: systbls.S,v 1.103 2002/02/08 03:57:14 davem Exp $ - * systbls.S: System call entry point tables for OS compatibility. +/* systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net) * * Based upon preliminary work which is: * @@ -80,7 +79,7 @@ sys_call_table: /*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare /*300*/ .long sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy /*305*/ .long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait -/*310*/ .long sys_utimensat, sys_signalfd, sys_timerfd, sys_eventfd +/*310*/ .long sys_utimensat, sys_signalfd, sys_timerfd, sys_eventfd, sys_fallocate #ifdef CONFIG_SUNOS_EMUL /* Now the SunOS syscall table. */ @@ -198,6 +197,6 @@ sunos_sys_table: .long sunos_nosys, sunos_nosys, sunos_nosys .long sunos_nosys /*310*/ .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys + .long sunos_nosys, sunos_nosys #endif diff --git a/arch/sparc/kernel/tick14.c b/arch/sparc/kernel/tick14.c index f1a7bd19e04..707bfda8657 100644 --- a/arch/sparc/kernel/tick14.c +++ b/arch/sparc/kernel/tick14.c @@ -25,6 +25,8 @@ #include <asm/irq.h> #include <asm/io.h> +#include "irq.h" + extern unsigned long lvl14_save[5]; static unsigned long *linux_lvl14 = NULL; static unsigned long obp_lvl14[4]; @@ -62,7 +64,7 @@ void claim_ticker14(irq_handler_t handler, /* first we copy the obp handler instructions */ - disable_irq(irq_nr); + __disable_irq(irq_nr); if (!handler) return; @@ -79,6 +81,6 @@ void claim_ticker14(irq_handler_t handler, NULL)) { install_linux_ticker(); load_profile_irq(cpu, timeout); - enable_irq(irq_nr); + __enable_irq(irq_nr); } } diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 7b4612da74a..6a251332162 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -44,6 +44,8 @@ #include <asm/of_device.h> #include <asm/irq_regs.h> +#include "irq.h" + DEFINE_SPINLOCK(rtc_lock); enum sparc_clock_type sp_clock_typ; DEFINE_SPINLOCK(mostek_lock); @@ -354,7 +356,7 @@ static struct of_platform_driver clock_driver = { /* Probe for the mostek real time clock chip. */ static int __init clock_init(void) { - return of_register_driver(&clock_driver, &of_bus_type); + return of_register_driver(&clock_driver, &of_platform_bus_type); } /* Must be after subsys_initcall() so that busses are probed. Must diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S index f75a1b82278..15109c156e8 100644 --- a/arch/sparc/kernel/vmlinux.lds.S +++ b/arch/sparc/kernel/vmlinux.lds.S @@ -35,6 +35,8 @@ SECTIONS __ex_table : { *(__ex_table) } __stop___ex_table = .; + NOTES + . = ALIGN(4096); __init_begin = .; _sinittext = .; @@ -65,10 +67,7 @@ SECTIONS __initramfs_end = .; #endif - . = ALIGN(4096); - __per_cpu_start = .; - .data.percpu : { *(.data.percpu) } - __per_cpu_end = .; + PERCPU(4096) . = ALIGN(4096); __init_end = .; . = ALIGN(32); |