diff options
Diffstat (limited to 'arch/sparc/kernel')
26 files changed, 677 insertions, 133 deletions
diff --git a/arch/sparc/kernel/asm-offsets.c b/arch/sparc/kernel/asm-offsets.c index 1f55231f07de..29d7cfd1c970 100644 --- a/arch/sparc/kernel/asm-offsets.c +++ b/arch/sparc/kernel/asm-offsets.c @@ -10,7 +10,6 @@ * On sparc, thread_info data is static and TI_XXX offsets are computed by hand. */ -#include <linux/config.h> #include <linux/sched.h> // #include <linux/mm.h> diff --git a/arch/sparc/kernel/auxio.c b/arch/sparc/kernel/auxio.c index d3b3648362c0..118f3eca373e 100644 --- a/arch/sparc/kernel/auxio.c +++ b/arch/sparc/kernel/auxio.c @@ -5,7 +5,6 @@ #include <linux/stddef.h> #include <linux/init.h> -#include <linux/config.h> #include <linux/spinlock.h> #include <asm/oplib.h> #include <asm/io.h> diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c index d7bfc61d2879..259a559d4cea 100644 --- a/arch/sparc/kernel/cpu.c +++ b/arch/sparc/kernel/cpu.c @@ -4,7 +4,6 @@ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) */ -#include <linux/config.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/smp.h> diff --git a/arch/sparc/kernel/devices.c b/arch/sparc/kernel/devices.c index fcb0c049c3fe..adba9dfee35e 100644 --- a/arch/sparc/kernel/devices.c +++ b/arch/sparc/kernel/devices.c @@ -7,7 +7,6 @@ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) */ -#include <linux/config.h> #include <linux/kernel.h> #include <linux/threads.h> #include <linux/string.h> diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c index a7a4892956c8..81c0cbd96ff0 100644 --- a/arch/sparc/kernel/ebus.c +++ b/arch/sparc/kernel/ebus.c @@ -7,7 +7,6 @@ * Fixes for different platforms by Pete Zaitcev. */ -#include <linux/config.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/init.h> diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 887f6a160c58..a4edff4c3be3 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -8,7 +8,6 @@ * Copyright (C) 1997 Anton Blanchard (anton@progsoc.uts.edu.au) */ -#include <linux/config.h> #include <linux/errno.h> #include <asm/head.h> diff --git a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head.S index 42d3de59d19b..9a219e8b5ddb 100644 --- a/arch/sparc/kernel/head.S +++ b/arch/sparc/kernel/head.S @@ -11,7 +11,6 @@ */ #include <linux/version.h> -#include <linux/config.h> #include <linux/init.h> #include <asm/head.h> diff --git a/arch/sparc/kernel/idprom.c b/arch/sparc/kernel/idprom.c index 2e1b0f6e99d4..3a5bad525394 100644 --- a/arch/sparc/kernel/idprom.c +++ b/arch/sparc/kernel/idprom.c @@ -5,7 +5,6 @@ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) */ -#include <linux/config.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/init.h> diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index ae4c667c906f..8654b446ac9e 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -26,6 +26,7 @@ */ #include <linux/config.h> +#include <linux/module.h> #include <linux/sched.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -40,6 +41,7 @@ #include <asm/vaddrs.h> #include <asm/oplib.h> #include <asm/prom.h> +#include <asm/of_device.h> #include <asm/sbus.h> #include <asm/page.h> #include <asm/pgalloc.h> @@ -143,6 +145,21 @@ void __iomem *sbus_ioremap(struct resource *phyres, unsigned long offset, phyres->start + offset, size, name); } +void __iomem *of_ioremap(struct resource *res, unsigned long offset, + unsigned long size, char *name) +{ + return _sparc_alloc_io(res->flags & 0xF, + res->start + offset, + size, name); +} +EXPORT_SYMBOL(of_ioremap); + +void of_iounmap(void __iomem *base, unsigned long size) +{ + iounmap(base); +} +EXPORT_SYMBOL(of_iounmap); + /* */ void sbus_iounmap(volatile void __iomem *addr, unsigned long size) @@ -208,7 +225,7 @@ _sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz) pa &= PAGE_MASK; sparc_mapiorange(bus, pa, res->start, res->end - res->start + 1); - return (void __iomem *) (res->start + offset); + return (void __iomem *)(unsigned long)(res->start + offset); } /* @@ -325,7 +342,7 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, long len, u32 *dma_addrp) res->name = sdev->prom_name; } - return (void *)res->start; + return (void *)(unsigned long)res->start; err_noiommu: release_resource(res); @@ -819,7 +836,9 @@ _sparc_io_get_info(char *buf, char **start, off_t fpos, int length, int *eof, if (p + 32 >= e) /* Better than nothing */ break; if ((nm = r->name) == 0) nm = "???"; - p += sprintf(p, "%08lx-%08lx: %s\n", r->start, r->end, nm); + p += sprintf(p, "%016llx-%016llx: %s\n", + (unsigned long long)r->start, + (unsigned long long)r->end, nm); } return p-buf; diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c index aac8af5aae51..cde73327ca96 100644 --- a/arch/sparc/kernel/irq.c +++ b/arch/sparc/kernel/irq.c @@ -11,7 +11,6 @@ * Copyright (C) 1998-2000 Anton Blanchard (anton@samba.org) */ -#include <linux/config.h> #include <linux/module.h> #include <linux/sched.h> #include <linux/ptrace.h> @@ -192,11 +191,11 @@ int show_interrupts(struct seq_file *p, void *v) } #endif seq_printf(p, " %c %s", - (action->flags & SA_INTERRUPT) ? '+' : ' ', + (action->flags & IRQF_DISABLED) ? '+' : ' ', action->name); for (action=action->next; action; action = action->next) { seq_printf(p, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", + (action->flags & IRQF_DISABLED) ? " +" : "", action->name); } seq_putc(p, '\n'); @@ -244,7 +243,7 @@ void free_irq(unsigned int irq, void *dev_id) printk("Trying to free free shared IRQ%d\n",irq); goto out_unlock; } - } else if (action->flags & SA_SHIRQ) { + } else if (action->flags & IRQF_SHARED) { printk("Trying to free shared IRQ%d with NULL device ID\n", irq); goto out_unlock; } @@ -396,9 +395,9 @@ int request_fast_irq(unsigned int irq, action = sparc_irq[cpu_irq].action; if(action) { - if(action->flags & SA_SHIRQ) + if(action->flags & IRQF_SHARED) panic("Trying to register fast irq when already shared.\n"); - if(irqflags & SA_SHIRQ) + if(irqflags & IRQF_SHARED) panic("Trying to register fast irq as shared.\n"); /* Anyway, someone already owns it so cannot be made fast. */ @@ -498,11 +497,11 @@ int request_irq(unsigned int irq, actionp = &sparc_irq[cpu_irq].action; action = *actionp; if (action) { - if (!(action->flags & SA_SHIRQ) || !(irqflags & SA_SHIRQ)) { + if (!(action->flags & IRQF_SHARED) || !(irqflags & IRQF_SHARED)) { ret = -EBUSY; goto out_unlock; } - if ((action->flags & SA_INTERRUPT) != (irqflags & SA_INTERRUPT)) { + if ((action->flags & IRQF_DISABLED) != (irqflags & IRQF_DISABLED)) { printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq); ret = -EBUSY; goto out_unlock; diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index 001b8673b4bd..bc956c530376 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c @@ -129,6 +129,26 @@ static int of_device_resume(struct device * dev) return error; } +static int node_match(struct device *dev, void *data) +{ + struct of_device *op = to_of_device(dev); + struct device_node *dp = data; + + return (op->node == dp); +} + +struct of_device *of_find_device_by_node(struct device_node *dp) +{ + struct device *dev = bus_find_device(&of_bus_type, NULL, + dp, node_match); + + if (dev) + return to_of_device(dev); + + return NULL; +} +EXPORT_SYMBOL(of_find_device_by_node); + #ifdef CONFIG_PCI struct bus_type ebus_bus_type = { .name = "ebus", @@ -138,6 +158,7 @@ struct bus_type ebus_bus_type = { .suspend = of_device_suspend, .resume = of_device_resume, }; +EXPORT_SYMBOL(ebus_bus_type); #endif #ifdef CONFIG_SBUS @@ -149,12 +170,462 @@ struct bus_type sbus_bus_type = { .suspend = of_device_suspend, .resume = of_device_resume, }; +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); + +static inline u64 of_read_addr(u32 *cell, int size) +{ + u64 r = 0; + while (size--) + r = (r << 32) | *(cell++); + return r; +} + +static void __init get_cells(struct device_node *dp, + int *addrc, int *sizec) +{ + if (addrc) + *addrc = of_n_addr_cells(dp); + if (sizec) + *sizec = of_n_size_cells(dp); +} + +/* Max address size we deal with */ +#define OF_MAX_ADDR_CELLS 4 + +struct of_bus { + const char *name; + const char *addr_prop_name; + int (*match)(struct device_node *parent); + void (*count_cells)(struct device_node *child, + int *addrc, int *sizec); + u64 (*map)(u32 *addr, u32 *range, int na, int ns, int pna); + int (*translate)(u32 *addr, u64 offset, int na); + unsigned int (*get_flags)(u32 *addr); +}; + +/* + * Default translator (generic bus) + */ + +static void of_bus_default_count_cells(struct device_node *dev, + int *addrc, int *sizec) +{ + get_cells(dev, addrc, sizec); +} + +static u64 of_bus_default_map(u32 *addr, u32 *range, int na, int ns, int pna) +{ + u64 cp, s, da; + + cp = of_read_addr(range, na); + s = of_read_addr(range + na + pna, ns); + da = of_read_addr(addr, na); + + if (da < cp || da >= (cp + s)) + return OF_BAD_ADDR; + return da - cp; +} + +static int of_bus_default_translate(u32 *addr, u64 offset, int na) +{ + u64 a = of_read_addr(addr, na); + memset(addr, 0, na * 4); + a += offset; + if (na > 1) + addr[na - 2] = a >> 32; + addr[na - 1] = a & 0xffffffffu; + + return 0; +} + +static unsigned int of_bus_default_get_flags(u32 *addr) +{ + return IORESOURCE_MEM; +} + + +/* + * PCI bus specific translator + */ + +static int of_bus_pci_match(struct device_node *np) +{ + return !strcmp(np->type, "pci") || !strcmp(np->type, "pciex"); +} + +static void of_bus_pci_count_cells(struct device_node *np, + int *addrc, int *sizec) +{ + if (addrc) + *addrc = 3; + if (sizec) + *sizec = 2; +} + +static u64 of_bus_pci_map(u32 *addr, u32 *range, int na, int ns, int pna) +{ + u64 cp, s, da; + + /* Check address type match */ + if ((addr[0] ^ range[0]) & 0x03000000) + return OF_BAD_ADDR; + + /* Read address values, skipping high cell */ + cp = of_read_addr(range + 1, na - 1); + s = of_read_addr(range + na + pna, ns); + da = of_read_addr(addr + 1, na - 1); + + if (da < cp || da >= (cp + s)) + return OF_BAD_ADDR; + return da - cp; +} + +static int of_bus_pci_translate(u32 *addr, u64 offset, int na) +{ + return of_bus_default_translate(addr + 1, offset, na - 1); +} + +static unsigned int of_bus_pci_get_flags(u32 *addr) +{ + unsigned int flags = 0; + u32 w = addr[0]; + + switch((w >> 24) & 0x03) { + case 0x01: + flags |= IORESOURCE_IO; + case 0x02: /* 32 bits */ + case 0x03: /* 64 bits */ + flags |= IORESOURCE_MEM; + } + if (w & 0x40000000) + flags |= IORESOURCE_PREFETCH; + return flags; +} + +/* + * SBUS bus specific translator + */ + +static int of_bus_sbus_match(struct device_node *np) +{ + return !strcmp(np->name, "sbus") || + !strcmp(np->name, "sbi"); +} + +static void of_bus_sbus_count_cells(struct device_node *child, + int *addrc, int *sizec) +{ + if (addrc) + *addrc = 2; + if (sizec) + *sizec = 1; +} + +static u64 of_bus_sbus_map(u32 *addr, u32 *range, int na, int ns, int pna) +{ + return of_bus_default_map(addr, range, na, ns, pna); +} + +static int of_bus_sbus_translate(u32 *addr, u64 offset, int na) +{ + return of_bus_default_translate(addr, offset, na); +} + +static unsigned int of_bus_sbus_get_flags(u32 *addr) +{ + return IORESOURCE_MEM; +} + + +/* + * Array of bus specific translators + */ + +static struct of_bus of_busses[] = { + /* PCI */ + { + .name = "pci", + .addr_prop_name = "assigned-addresses", + .match = of_bus_pci_match, + .count_cells = of_bus_pci_count_cells, + .map = of_bus_pci_map, + .translate = of_bus_pci_translate, + .get_flags = of_bus_pci_get_flags, + }, + /* SBUS */ + { + .name = "sbus", + .addr_prop_name = "reg", + .match = of_bus_sbus_match, + .count_cells = of_bus_sbus_count_cells, + .map = of_bus_sbus_map, + .translate = of_bus_sbus_translate, + .get_flags = of_bus_sbus_get_flags, + }, + /* Default */ + { + .name = "default", + .addr_prop_name = "reg", + .match = NULL, + .count_cells = of_bus_default_count_cells, + .map = of_bus_default_map, + .translate = of_bus_default_translate, + .get_flags = of_bus_default_get_flags, + }, +}; + +static struct of_bus *of_match_bus(struct device_node *np) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(of_busses); i ++) + if (!of_busses[i].match || of_busses[i].match(np)) + return &of_busses[i]; + BUG(); + return NULL; +} + +static int __init build_one_resource(struct device_node *parent, + struct of_bus *bus, + struct of_bus *pbus, + u32 *addr, + int na, int ns, int pna) +{ + u32 *ranges; + unsigned int rlen; + int rone; + u64 offset = OF_BAD_ADDR; + + ranges = of_get_property(parent, "ranges", &rlen); + if (ranges == NULL || rlen == 0) { + offset = of_read_addr(addr, na); + memset(addr, 0, pna * 4); + goto finish; + } + + /* Now walk through the ranges */ + rlen /= 4; + rone = na + pna + ns; + for (; rlen >= rone; rlen -= rone, ranges += rone) { + offset = bus->map(addr, ranges, na, ns, pna); + if (offset != OF_BAD_ADDR) + break; + } + if (offset == OF_BAD_ADDR) + return 1; + + memcpy(addr, ranges + na, 4 * pna); + +finish: + /* Translate it into parent bus space */ + return pbus->translate(addr, offset, pna); +} + +static void __init build_device_resources(struct of_device *op, + struct device *parent) +{ + struct of_device *p_op; + struct of_bus *bus; + int na, ns; + int index, num_reg; + void *preg; + + if (!parent) + return; + + p_op = to_of_device(parent); + bus = of_match_bus(p_op->node); + bus->count_cells(op->node, &na, &ns); + + preg = of_get_property(op->node, bus->addr_prop_name, &num_reg); + if (!preg || num_reg == 0) + return; + + /* Convert to num-cells. */ + num_reg /= 4; + + /* Conver to num-entries. */ + num_reg /= na + ns; + + for (index = 0; index < num_reg; index++) { + struct resource *r = &op->resource[index]; + u32 addr[OF_MAX_ADDR_CELLS]; + u32 *reg = (preg + (index * ((na + ns) * 4))); + struct device_node *dp = op->node; + struct device_node *pp = p_op->node; + struct of_bus *pbus; + u64 size, result = OF_BAD_ADDR; + unsigned long flags; + int dna, dns; + int pna, pns; + + size = of_read_addr(reg + na, ns); + flags = bus->get_flags(reg); + + memcpy(addr, reg, na * 4); + + /* If the immediate parent has no ranges property to apply, + * just use a 1<->1 mapping. + */ + if (of_find_property(pp, "ranges", NULL) == NULL) { + result = of_read_addr(addr, na); + goto build_res; + } + + dna = na; + dns = ns; + + while (1) { + dp = pp; + pp = dp->parent; + if (!pp) { + result = of_read_addr(addr, dna); + break; + } + + pbus = of_match_bus(pp); + pbus->count_cells(dp, &pna, &pns); + + if (build_one_resource(dp, bus, pbus, addr, dna, dns, pna)) + break; + + dna = pna; + dns = pns; + bus = pbus; + } + + build_res: + memset(r, 0, sizeof(*r)); + if (result != OF_BAD_ADDR) { + r->start = result & 0xffffffff; + r->end = result + size - 1; + r->flags = flags | ((result >> 32ULL) & 0xffUL); + } else { + r->start = ~0UL; + r->end = ~0UL; + } + r->name = op->node->name; + } +} + +static struct of_device * __init scan_one_device(struct device_node *dp, + struct device *parent) +{ + struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL); + struct linux_prom_irqs *intr; + int len, i; + + if (!op) + return NULL; + + op->node = dp; + + op->clock_freq = of_getintprop_default(dp, "clock-frequency", + (25*1000*1000)); + op->portid = of_getintprop_default(dp, "upa-portid", -1); + if (op->portid == -1) + op->portid = of_getintprop_default(dp, "portid", -1); + + intr = of_get_property(dp, "intr", &len); + if (intr) { + op->num_irqs = len / sizeof(struct linux_prom_irqs); + for (i = 0; i < op->num_irqs; i++) + op->irqs[i] = intr[i].pri; + } else { + unsigned int *irq = of_get_property(dp, "interrupts", &len); + + if (irq) { + op->num_irqs = len / sizeof(unsigned int); + for (i = 0; i < op->num_irqs; i++) + op->irqs[i] = irq[i]; + } else { + op->num_irqs = 0; + } + } + if (sparc_cpu_model == sun4d) { + static int pil_to_sbus[] = { + 0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0, + }; + struct device_node *busp = dp->parent; + struct linux_prom_registers *regs; + int board = of_getintprop_default(busp, "board#", 0); + int slot; + + regs = of_get_property(dp, "reg", NULL); + slot = regs->which_io; + + for (i = 0; i < op->num_irqs; i++) { + int this_irq = op->irqs[i]; + int sbusl = pil_to_sbus[this_irq]; + + if (sbusl) + this_irq = (((board + 1) << 5) + + (sbusl << 2) + + slot); + + op->irqs[i] = this_irq; + } + } + + build_device_resources(op, parent); + + op->dev.parent = parent; + op->dev.bus = &of_bus_type; + if (!parent) + strcpy(op->dev.bus_id, "root"); + else + strcpy(op->dev.bus_id, dp->path_component_name); + + if (of_device_register(op)) { + printk("%s: Could not register of device.\n", + dp->full_name); + kfree(op); + op = NULL; + } + + return op; +} + +static void __init scan_tree(struct device_node *dp, struct device *parent) +{ + while (dp) { + struct of_device *op = scan_one_device(dp, parent); + + if (op) + scan_tree(dp->child, &op->dev); + + dp = dp->sibling; + } +} + +static void __init scan_of_devices(void) +{ + struct device_node *root = of_find_node_by_path("/"); + struct of_device *parent; + + parent = scan_one_device(root, NULL); + if (!parent) + return; + + scan_tree(root->child, &parent->dev); +} + static int __init of_bus_driver_init(void) { - int err = 0; + int err; + err = bus_register(&of_bus_type); #ifdef CONFIG_PCI if (!err) err = bus_register(&ebus_bus_type); @@ -163,7 +634,11 @@ static int __init of_bus_driver_init(void) if (!err) err = bus_register(&sbus_bus_type); #endif - return 0; + + if (!err) + scan_of_devices(); + + return err; } postcore_initcall(of_bus_driver_init); diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index bcfdddd0418a..bfd31aac2df3 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -10,7 +10,6 @@ * CP-1200 by Eric Brower. */ -#include <linux/config.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/init.h> @@ -746,7 +745,7 @@ void __init pci_time_init(void) writel (PCI_COUNTER_IRQ_SET(timer_irq, 0), pcic->pcic_regs+PCI_COUNTER_IRQ); irq = request_irq(timer_irq, pcic_timer_handler, - (SA_INTERRUPT | SA_STATIC_ALLOC), "timer", NULL); + (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); if (irq) { prom_printf("time_init: unable to attach IRQ%d\n", timer_irq); prom_halt(); @@ -860,7 +859,7 @@ char * __init pcibios_setup(char *str) } void pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) + resource_size_t size, resource_size_t align) { } diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 118cac84a0f5..89a28cc018c9 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -22,7 +22,6 @@ #include <linux/slab.h> #include <linux/user.h> #include <linux/a.out.h> -#include <linux/config.h> #include <linux/smp.h> #include <linux/smp_lock.h> #include <linux/reboot.h> diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c index 63b2b9bd778e..4b06dcb00ebd 100644 --- a/arch/sparc/kernel/prom.c +++ b/arch/sparc/kernel/prom.c @@ -27,6 +27,11 @@ static struct device_node *allnodes; +/* 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(struct device_node *device, const char *compat) { const char* cp; @@ -185,6 +190,84 @@ 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) +{ + 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) +{ + 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; + void *new_val; + int err; + + new_val = kmalloc(len, GFP_KERNEL); + if (!new_val) + return -ENOMEM; + + memcpy(new_val, val, len); + + err = -ENODEV; + + write_lock(&devtree_lock); + prevp = &dp->properties; + while (*prevp) { + struct property *prop = *prevp; + + if (!strcmp(prop->name, name)) { + void *old_val = prop->value; + int ret; + + ret = prom_setprop(dp->node, name, val, len); + err = -EINVAL; + if (ret >= 0) { + prop->value = new_val; + prop->length = len; + + if (OF_IS_DYNAMIC(prop)) + kfree(old_val); + + OF_MARK_DYNAMIC(prop); + + err = 0; + } + break; + } + prevp = &(*prevp)->next; + } + write_unlock(&devtree_lock); + + /* XXX Upate procfs if necessary... */ + + return err; +} +EXPORT_SYMBOL(of_set_property); + static unsigned int prom_early_allocated; static void * __init prom_early_alloc(unsigned long size) @@ -354,7 +437,9 @@ static char * __init build_full_name(struct device_node *dp) return n; } -static struct property * __init build_one_prop(phandle node, char *prev) +static unsigned int unique_id; + +static struct property * __init build_one_prop(phandle node, char *prev, char *special_name, void *special_val, int special_len) { static struct property *tmp = NULL; struct property *p; @@ -364,25 +449,34 @@ static struct property * __init build_one_prop(phandle node, char *prev) p = tmp; memset(p, 0, sizeof(*p) + 32); tmp = NULL; - } else + } else { p = prom_early_alloc(sizeof(struct property) + 32); + p->unique_id = unique_id++; + } p->name = (char *) (p + 1); - if (prev == NULL) { - prom_firstprop(node, p->name); - } else { - prom_nextprop(node, prev, p->name); - } - if (strlen(p->name) == 0) { - tmp = p; - return NULL; - } - p->length = prom_getproplen(node, p->name); - if (p->length <= 0) { - p->length = 0; + if (special_name) { + p->length = special_len; + p->value = prom_early_alloc(special_len); + memcpy(p->value, special_val, special_len); } else { - p->value = prom_early_alloc(p->length); - len = prom_getproperty(node, p->name, p->value, p->length); + if (prev == NULL) { + prom_firstprop(node, p->name); + } else { + prom_nextprop(node, prev, p->name); + } + if (strlen(p->name) == 0) { + tmp = p; + return NULL; + } + p->length = prom_getproplen(node, p->name); + if (p->length <= 0) { + p->length = 0; + } else { + p->value = prom_early_alloc(p->length + 1); + prom_getproperty(node, p->name, p->value, p->length); + ((unsigned char *)p->value)[p->length] = '\0'; + } } return p; } @@ -391,9 +485,14 @@ static struct property * __init build_prop_list(phandle node) { struct property *head, *tail; - head = tail = build_one_prop(node, NULL); + head = tail = build_one_prop(node, NULL, + ".node", &node, sizeof(node)); + + tail->next = build_one_prop(node, NULL, NULL, NULL, 0); + tail = tail->next; while(tail) { - tail->next = build_one_prop(node, tail->name); + tail->next = build_one_prop(node, tail->name, + NULL, NULL, 0); tail = tail->next; } @@ -422,6 +521,7 @@ static struct device_node * __init create_node(phandle node) return NULL; dp = prom_early_alloc(sizeof(*dp)); + dp->unique_id = unique_id++; kref_init(&dp->kref); diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index a893a9cc9534..8606ef4e52e9 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c @@ -19,7 +19,6 @@ #include <linux/a.out.h> #include <linux/tty.h> #include <linux/delay.h> -#include <linux/config.h> #include <linux/fs.h> #include <linux/seq_file.h> #include <linux/syscalls.h> @@ -496,7 +495,7 @@ static int __init topology_init(void) if (!p) err = -ENOMEM; else - register_cpu(p, i, NULL); + register_cpu(p, i); } return err; diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c index 0748d8147bbf..c9301b9143ca 100644 --- a/arch/sparc/kernel/signal.c +++ b/arch/sparc/kernel/signal.c @@ -7,7 +7,6 @@ * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) */ -#include <linux/config.h> #include <linux/sched.h> #include <linux/kernel.h> #include <linux/signal.h> diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index fd7deabf9982..5fb987fc3d63 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -9,7 +9,6 @@ #define EXPORT_SYMTAB_STROPS #define PROMLIB_INTERNAL -#include <linux/config.h> #include <linux/module.h> #include <linux/init.h> #include <linux/smp.h> diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index 0f2d8d9cbdba..4be2c86ea540 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -9,7 +9,6 @@ * Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk) */ -#include <linux/config.h> #include <linux/errno.h> #include <linux/linkage.h> #include <linux/kernel_stat.h> @@ -180,7 +179,7 @@ static void __init sun4c_init_timers(irqreturn_t (*counter_fn)(int, void *, stru irq = request_irq(TIMER_IRQ, counter_fn, - (SA_INTERRUPT | SA_STATIC_ALLOC), + (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); if (irq) { prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ); diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index 9c30e35c88f7..74eed9775ac0 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -6,7 +6,6 @@ * Heavily based on arch/sparc/kernel/irq.c. */ -#include <linux/config.h> #include <linux/errno.h> #include <linux/linkage.h> #include <linux/kernel_stat.h> @@ -108,13 +107,13 @@ found_it: seq_printf(p, "%3d: ", i); kstat_cpu(cpu_logical_map(x)).irqs[i]); #endif seq_printf(p, "%c %s", - (action->flags & SA_INTERRUPT) ? '+' : ' ', + (action->flags & IRQF_DISABLED) ? '+' : ' ', action->name); action = action->next; for (;;) { for (; action; action = action->next) { seq_printf(p, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", + (action->flags & IRQF_DISABLED) ? " +" : "", action->name); } if (!sbusl) break; @@ -161,7 +160,7 @@ void sun4d_free_irq(unsigned int irq, void *dev_id) printk("Trying to free free shared IRQ%d\n",irq); goto out_unlock; } - } else if (action->flags & SA_SHIRQ) { + } else if (action->flags & IRQF_SHARED) { printk("Trying to free shared IRQ%d with NULL device ID\n", irq); goto out_unlock; } @@ -299,13 +298,13 @@ int sun4d_request_irq(unsigned int irq, action = *actionp; if (action) { - if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) { + if ((action->flags & IRQF_SHARED) && (irqflags & IRQF_SHARED)) { for (tmp = action; tmp->next; tmp = tmp->next); } else { ret = -EBUSY; goto out_unlock; } - if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) { + if ((action->flags & IRQF_DISABLED) ^ (irqflags & IRQF_DISABLED)) { printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq); ret = -EBUSY; goto out_unlock; @@ -491,7 +490,7 @@ static void __init sun4d_init_timers(irqreturn_t (*counter_fn)(int, void *, stru irq = request_irq(TIMER_IRQ, counter_fn, - (SA_INTERRUPT | SA_STATIC_ALLOC), + (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); if (irq) { prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ); diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index a296c13ac18f..7cefa301efea 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -9,7 +9,6 @@ * Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk) */ -#include <linux/config.h> #include <linux/errno.h> #include <linux/linkage.h> #include <linux/kernel_stat.h> @@ -279,7 +278,7 @@ static void __init sun4m_init_timers(irqreturn_t (*counter_fn)(int, void *, stru irq = request_irq(TIMER_IRQ, counter_fn, - (SA_INTERRUPT | SA_STATIC_ALLOC), + (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); if (irq) { prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ); diff --git a/arch/sparc/kernel/sys_solaris.c b/arch/sparc/kernel/sys_solaris.c index fb7578554c78..c09afd96dd9c 100644 --- a/arch/sparc/kernel/sys_solaris.c +++ b/arch/sparc/kernel/sys_solaris.c @@ -4,7 +4,6 @@ * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) */ -#include <linux/config.h> #include <linux/sched.h> #include <linux/kernel.h> #include <linux/string.h> diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c index 288de276d9ff..aa0fb2efb615 100644 --- a/arch/sparc/kernel/sys_sunos.c +++ b/arch/sparc/kernel/sys_sunos.c @@ -196,7 +196,7 @@ asmlinkage int sunos_brk(unsigned long brk) * simple, it hopefully works in most obvious cases.. Easy to * fool it, but this should catch most mistakes. */ - freepages = get_page_cache_size(); + freepages = global_page_state(NR_FILE_PAGES); freepages >>= 1; freepages += nr_free_pages(); freepages += nr_swap_pages; diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S index 2856551bddf1..10df38eeae08 100644 --- a/arch/sparc/kernel/systbls.S +++ b/arch/sparc/kernel/systbls.S @@ -9,7 +9,6 @@ * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) */ -#include <linux/config.h> .data .align 4 diff --git a/arch/sparc/kernel/tick14.c b/arch/sparc/kernel/tick14.c index 591547af4c65..d3b4daac705f 100644 --- a/arch/sparc/kernel/tick14.c +++ b/arch/sparc/kernel/tick14.c @@ -74,7 +74,7 @@ void claim_ticker14(irqreturn_t (*handler)(int, void *, struct pt_regs *), if (!request_irq(irq_nr, handler, - (SA_INTERRUPT | SA_STATIC_ALLOC), + (IRQF_DISABLED | SA_STATIC_ALLOC), "counter14", NULL)) { install_linux_ticker(); diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 7dadcdb4ca42..04eb1eab6e3e 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -15,7 +15,6 @@ * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 * "A Kernel Model for Precision Timekeeping" by Dave Mills */ -#include <linux/config.h> #include <linux/errno.h> #include <linux/module.h> #include <linux/sched.h> @@ -42,6 +41,7 @@ #include <asm/sun4paddr.h> #include <asm/page.h> #include <asm/pcic.h> +#include <asm/of_device.h> extern unsigned long wall_jiffies; @@ -273,83 +273,31 @@ static __inline__ void sun4_clock_probe(void) #endif } -/* Probe for the mostek real time clock chip. */ -static __inline__ void clock_probe(void) +static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) { - struct linux_prom_registers clk_reg[2]; - char model[128]; - register int node, cpuunit, bootbus; - struct resource r; - - cpuunit = bootbus = 0; - memset(&r, 0, sizeof(r)); - - /* Determine the correct starting PROM node for the probe. */ - node = prom_getchild(prom_root_node); - switch (sparc_cpu_model) { - case sun4c: - break; - case sun4m: - node = prom_getchild(prom_searchsiblings(node, "obio")); - break; - case sun4d: - node = prom_getchild(bootbus = prom_searchsiblings(prom_getchild(cpuunit = prom_searchsiblings(node, "cpu-unit")), "bootbus")); - break; - default: - prom_printf("CLOCK: Unsupported architecture!\n"); - prom_halt(); - } + struct device_node *dp = op->node; + char *model = of_get_property(dp, "model", NULL); - /* Find the PROM node describing the real time clock. */ - sp_clock_typ = MSTK_INVALID; - node = prom_searchsiblings(node,"eeprom"); - if (!node) { - prom_printf("CLOCK: No clock found!\n"); - prom_halt(); - } + if (!model) + return -ENODEV; - /* Get the model name and setup everything up. */ - model[0] = '\0'; - prom_getstring(node, "model", model, sizeof(model)); - if (strcmp(model, "mk48t02") == 0) { + if (!strcmp(model, "mk48t02")) { sp_clock_typ = MSTK48T02; - if (prom_getproperty(node, "reg", (char *) clk_reg, sizeof(clk_reg)) == -1) { - prom_printf("clock_probe: FAILED!\n"); - prom_halt(); - } - if (sparc_cpu_model == sun4d) - prom_apply_generic_ranges (bootbus, cpuunit, clk_reg, 1); - else - prom_apply_obio_ranges(clk_reg, 1); + /* Map the clock register io area read-only */ - r.flags = clk_reg[0].which_io; - r.start = clk_reg[0].phys_addr; - mstk48t02_regs = sbus_ioremap(&r, 0, - sizeof(struct mostek48t02), "mk48t02"); + mstk48t02_regs = of_ioremap(&op->resource[0], 0, + sizeof(struct mostek48t02), + "mk48t02"); mstk48t08_regs = NULL; /* To catch weirdness */ - } else if (strcmp(model, "mk48t08") == 0) { + } else if (!strcmp(model, "mk48t08")) { sp_clock_typ = MSTK48T08; - if(prom_getproperty(node, "reg", (char *) clk_reg, - sizeof(clk_reg)) == -1) { - prom_printf("clock_probe: FAILED!\n"); - prom_halt(); - } - if (sparc_cpu_model == sun4d) - prom_apply_generic_ranges (bootbus, cpuunit, clk_reg, 1); - else - prom_apply_obio_ranges(clk_reg, 1); - /* Map the clock register io area read-only */ - /* XXX r/o attribute is somewhere in r.flags */ - r.flags = clk_reg[0].which_io; - r.start = clk_reg[0].phys_addr; - mstk48t08_regs = sbus_ioremap(&r, 0, - sizeof(struct mostek48t08), "mk48t08"); + mstk48t08_regs = of_ioremap(&op->resource[0], 0, + sizeof(struct mostek48t08), + "mk48t08"); mstk48t02_regs = &mstk48t08_regs->regs; - } else { - prom_printf("CLOCK: Unknown model name '%s'\n",model); - prom_halt(); - } + } else + return -ENODEV; /* Report a low battery voltage condition. */ if (has_low_battery()) @@ -358,6 +306,28 @@ static __inline__ void clock_probe(void) /* Kick start the clock if it is completely stopped. */ if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) kick_start_clock(); + + return 0; +} + +static struct of_device_id clock_match[] = { + { + .name = "eeprom", + }, + {}, +}; + +static struct of_platform_driver clock_driver = { + .name = "clock", + .match_table = clock_match, + .probe = clock_probe, +}; + + +/* Probe for the mostek real time clock chip. */ +static void clock_init(void) +{ + of_register_driver(&clock_driver, &of_bus_type); } void __init sbus_time_init(void) @@ -376,7 +346,7 @@ void __init sbus_time_init(void) if (ARCH_SUN4) sun4_clock_probe(); else - clock_probe(); + clock_init(); sparc_init_timers(timer_interrupt); diff --git a/arch/sparc/kernel/traps.c b/arch/sparc/kernel/traps.c index 41d45c298fb2..6a70d215fd04 100644 --- a/arch/sparc/kernel/traps.c +++ b/arch/sparc/kernel/traps.c @@ -9,7 +9,6 @@ * I hate traps on the sparc, grrr... */ -#include <linux/config.h> #include <linux/sched.h> /* for jiffies */ #include <linux/kernel.h> #include <linux/kallsyms.h> |