From de8d28b16f5614aeb12bb69c8f9a38578b8d3ada Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 22 Jun 2006 16:18:54 -0700 Subject: [SPARC64]: Convert sparc64 PCI layer to in-kernel device tree. One thing this change pointed out was that we really should pull the "get 'local-mac-address' property" logic into a helper function all the network drivers can call. Signed-off-by: David S. Miller --- arch/sparc64/kernel/ebus.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/sparc64/kernel/ebus.c') diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index c69504aa638f..3125a5b49775 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c @@ -553,7 +553,7 @@ void __init ebus_init(void) } cookie = pdev->sysdata; - ebusnd = cookie->prom_node; + ebusnd = cookie->prom_node->node; ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus)); ebus->next = NULL; @@ -578,7 +578,7 @@ void __init ebus_init(void) } ebus->is_rio = is_rio; cookie = pdev->sysdata; - ebusnd = cookie->prom_node; + ebusnd = cookie->prom_node->node; continue; } printk("ebus%d:", num_ebus); @@ -622,7 +622,7 @@ void __init ebus_init(void) break; cookie = pdev->sysdata; - ebusnd = cookie->prom_node; + ebusnd = cookie->prom_node->node; ebus->next = ebus_alloc(sizeof(struct linux_ebus)); ebus = ebus->next; -- cgit v1.2.3 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 'arch/sparc64/kernel/ebus.c') 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 From 9c10a58ed634d98114c5717e2da761d8a63f2cd4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 22 Jun 2006 19:31:11 -0700 Subject: [SPARC64]: Kill ebus/isa range and interrupt mapping struct members. Unused outside of initial bus probe scan. Signed-off-by: David S. Miller --- arch/sparc64/kernel/ebus.c | 65 ++++++++++++-------------------------------- arch/sparc64/kernel/isa.c | 68 ++++++++++++++++------------------------------ include/asm-sparc64/ebus.h | 5 ---- include/asm-sparc64/isa.h | 8 ------ 4 files changed, 41 insertions(+), 105 deletions(-) (limited to 'arch/sparc64/kernel/ebus.c') diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index 919a91d9e5de..33d79e10c653 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c @@ -283,60 +283,32 @@ static inline void *ebus_alloc(size_t size) return mem; } -static void __init ebus_ranges_init(struct linux_ebus *ebus) -{ - struct linux_prom_ebus_ranges *rngs; - int len; - - ebus->num_ebus_ranges = 0; - 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 __init ebus_intmap_match(struct linux_ebus *ebus, + struct linux_prom_registers *reg, + int *interrupt) { struct linux_prom_ebus_intmap *imap; struct linux_prom_ebus_intmask *imask; - int len; + unsigned int hi, lo, irq; + int i, len, n_imap; - ebus->num_ebus_intmap = 0; imap = of_get_property(ebus->prom_node, "interrupt-map", &len); if (!imap) - return; - - memcpy(ebus->ebus_intmap, imap, len); - ebus->num_ebus_intmap = (len / sizeof(struct linux_prom_ebus_intmap)); - - 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, - struct linux_prom_registers *reg, - int *interrupt) -{ - unsigned int hi, lo, irq; - int i; + return 0; + n_imap = len / sizeof(imap[0]); - if (!ebus->num_ebus_intmap) + imask = of_get_property(ebus->prom_node, "interrupt-map-mask", NULL); + if (!imask) return 0; - hi = reg->which_io & ebus->ebus_intmask.phys_hi; - lo = reg->phys_addr & ebus->ebus_intmask.phys_lo; - irq = *interrupt & ebus->ebus_intmask.interrupt; - for (i = 0; i < ebus->num_ebus_intmap; i++) { - if ((ebus->ebus_intmap[i].phys_hi == hi) && - (ebus->ebus_intmap[i].phys_lo == lo) && - (ebus->ebus_intmap[i].interrupt == irq)) { - *interrupt = ebus->ebus_intmap[i].cinterrupt; + hi = reg->which_io & imask->phys_hi; + lo = reg->phys_addr & imask->phys_lo; + irq = *interrupt & imask->interrupt; + for (i = 0; i < n_imap; i++) { + if ((imap[i].phys_hi == hi) && + (imap[i].phys_lo == lo) && + (imap[i].interrupt == irq)) { + *interrupt = imap[i].cinterrupt; return 0; } } @@ -598,9 +570,6 @@ void __init ebus_init(void) ebus->self = pdev; ebus->parent = pbm = cookie->pbm; - ebus_ranges_init(ebus); - ebus_intmap_init(ebus); - child = dp->child; if (!child) goto next_ebus; diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c index 8c8c5a491ad6..2693f2de549c 100644 --- a/arch/sparc64/kernel/isa.c +++ b/arch/sparc64/kernel/isa.c @@ -72,19 +72,30 @@ static struct { static int __init isa_dev_get_irq_using_imap(struct sparc_isa_device *isa_dev, struct sparc_isa_bridge *isa_br, int *interrupt, - struct linux_prom_registers *pregs) + struct linux_prom_registers *reg) { + struct linux_prom_ebus_intmap *imap; + struct linux_prom_ebus_intmap *imask; unsigned int hi, lo, irq; - int i; - - hi = pregs->which_io & isa_br->isa_intmask.phys_hi; - lo = pregs->phys_addr & isa_br->isa_intmask.phys_lo; - irq = *interrupt & isa_br->isa_intmask.interrupt; - for (i = 0; i < isa_br->num_isa_intmap; i++) { - if ((isa_br->isa_intmap[i].phys_hi == hi) && - (isa_br->isa_intmap[i].phys_lo == lo) && - (isa_br->isa_intmap[i].interrupt == irq)) { - *interrupt = isa_br->isa_intmap[i].cinterrupt; + int i, len, n_imap; + + imap = of_get_property(isa_br->prom_node, "interrupt-map", &len); + if (!imap) + return 0; + n_imap = len / sizeof(imap[0]); + + imask = of_get_property(isa_br->prom_node, "interrupt-map-mask", NULL); + if (!imask) + return 0; + + hi = reg->which_io & imask->phys_hi; + lo = reg->phys_addr & imask->phys_lo; + irq = *interrupt & imask->interrupt; + for (i = 0; i < n_imap; i++) { + if ((imap[i].phys_hi == hi) && + (imap[i].phys_lo == lo) && + (imap[i].interrupt == irq)) { + *interrupt = imap[i].cinterrupt; return 0; } } @@ -105,7 +116,8 @@ static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev, struct pci_pbm_info *pbm; int i; - if (isa_dev->bus->num_isa_intmap) { + if (of_find_property(isa_dev->bus->prom_node, + "interrupt-map", NULL)) { if (!isa_dev_get_irq_using_imap(isa_dev, isa_dev->bus, &irq_prop, @@ -218,36 +230,6 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) } } -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; @@ -288,8 +270,6 @@ void __init isa_init(void) isa_br->index = index++; isa_br->prom_node = pdev_cookie->prom_node; - get_bridge_props(isa_br); - printk("isa%d:", isa_br->index); isa_fill_devices(isa_br); diff --git a/include/asm-sparc64/ebus.h b/include/asm-sparc64/ebus.h index 876912f4d83b..545882bd3563 100644 --- a/include/asm-sparc64/ebus.h +++ b/include/asm-sparc64/ebus.h @@ -42,11 +42,6 @@ struct linux_ebus { int index; int is_rio; 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]; - int num_ebus_intmap; - struct linux_prom_ebus_intmask ebus_intmask; }; struct ebus_dma_info { diff --git a/include/asm-sparc64/isa.h b/include/asm-sparc64/isa.h index e110435b14ef..2e7fb18ec1be 100644 --- a/include/asm-sparc64/isa.h +++ b/include/asm-sparc64/isa.h @@ -29,14 +29,6 @@ struct sparc_isa_bridge { struct pci_dev *self; int index; 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; -#define linux_prom_isa_intmap linux_prom_ebus_intmap - struct linux_prom_isa_intmap isa_intmap[PROMREG_MAX]; - int num_isa_intmap; -#define linux_prom_isa_intmask linux_prom_ebus_intmask - struct linux_prom_isa_intmap isa_intmask; }; extern struct sparc_isa_bridge *isa_chain; -- cgit v1.2.3 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 'arch/sparc64/kernel/ebus.c') 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 From b5ba0740f852f4ad86ba7f21267bc77027d60703 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 23 Jun 2006 22:46:49 -0700 Subject: [SPARC64]: Make auxio a real driver. Signed-off-by: David S. Miller --- arch/sparc64/kernel/auxio.c | 109 ++++++++++++++++++++++++++++++-------------- arch/sparc64/kernel/ebus.c | 8 ---- arch/sparc64/kernel/sbus.c | 2 - 3 files changed, 74 insertions(+), 45 deletions(-) (limited to 'arch/sparc64/kernel/ebus.c') diff --git a/arch/sparc64/kernel/auxio.c b/arch/sparc64/kernel/auxio.c index db36b66a4e3c..2c42894b188f 100644 --- a/arch/sparc64/kernel/auxio.c +++ b/arch/sparc64/kernel/auxio.c @@ -110,43 +110,82 @@ void auxio_set_lte(int on) } } -void __init auxio_probe(void) +static void __devinit auxio_report_dev(struct device_node *dp) { - struct sbus_bus *sbus; - struct sbus_dev *sdev = NULL; - - for_each_sbus(sbus) { - for_each_sbusdev(sdev, sbus) { - if(!strcmp(sdev->prom_name, "auxio")) - goto found_sdev; - } - } - -found_sdev: - if (sdev) { - auxio_devtype = AUXIO_TYPE_SBUS; - auxio_register = sbus_ioremap(&sdev->resource[0], 0, - sdev->reg_addrs[0].reg_size, - "auxiliaryIO"); - } + printk(KERN_INFO "AUXIO: Found device at %s\n", + dp->full_name); +} + +static struct of_device_id auxio_match[] = { + { + .name = "auxio", + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, auxio_match); + +#ifdef CONFIG_SBUS +static int __devinit auxio_sbus_probe(struct of_device *dev, const struct of_device_id *match) +{ + struct sbus_dev *sdev = to_sbus_device(&dev->dev); + + auxio_devtype = AUXIO_TYPE_SBUS; + auxio_register = sbus_ioremap(&sdev->resource[0], 0, + sdev->reg_addrs[0].reg_size, + "auxiliaryIO"); + if (!auxio_register) + return -ENODEV; + + auxio_report_dev(dev->node); + return 0; +} + +static struct of_platform_driver auxio_sbus_driver = { + .name = "auxio", + .match_table = auxio_match, + .probe = auxio_sbus_probe, +}; +#endif + #ifdef CONFIG_PCI - else { - struct linux_ebus *ebus; - struct linux_ebus_device *edev = NULL; - - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_node->name, "auxio")) - goto ebus_done; - } - } - ebus_done: - if (edev) { - auxio_devtype = AUXIO_TYPE_EBUS; - auxio_register = - ioremap(edev->resource[0].start, sizeof(u32)); - } - } +static int __devinit auxio_ebus_probe(struct of_device *dev, const struct of_device_id *match) +{ + struct linux_ebus_device *edev = to_ebus_device(&dev->dev); + + auxio_devtype = AUXIO_TYPE_EBUS; + auxio_register = ioremap(edev->resource[0].start, sizeof(u32)); + if (!auxio_register) + return -ENODEV; + + auxio_report_dev(dev->node); + auxio_set_led(AUXIO_LED_ON); + + return 0; +} + +static struct of_platform_driver auxio_ebus_driver = { + .name = "auxio", + .match_table = auxio_match, + .probe = auxio_ebus_probe, +}; #endif + +static int __init auxio_probe(void) +{ +#ifdef CONFIG_SBUS + of_register_driver(&auxio_sbus_driver, &sbus_bus_type); +#endif +#ifdef CONFIG_PCI + of_register_driver(&auxio_ebus_driver, &ebus_bus_type); +#endif + + return 0; } + +/* Must be after subsys_initcall() so that busses are probed. Must + * be before device_initcall() because things like the floppy driver + * need to use the AUXIO register. + */ +fs_initcall(auxio_probe); diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index b390a2f3a15e..98e0a8cbeecd 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c @@ -269,10 +269,6 @@ EXPORT_SYMBOL(ebus_dma_enable); struct linux_ebus *ebus_chain = NULL; -#ifdef CONFIG_SUN_AUXIO -extern void auxio_probe(void); -#endif - static inline void *ebus_alloc(size_t size) { void *mem; @@ -630,8 +626,4 @@ void __init ebus_init(void) ++num_ebus; } pci_dev_put(pdev); /* XXX for the case, when ebusnd is 0, is it OK? */ - -#ifdef CONFIG_SUN_AUXIO - auxio_probe(); -#endif } diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index d3da23cdc264..ac05e0f692ef 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -1269,10 +1269,8 @@ int __init sbus_arch_preinit(void) void __init sbus_arch_postinit(void) { extern void firetruck_init(void); - extern void auxio_probe(void); extern void clock_probe(void); firetruck_init(); - auxio_probe(); clock_probe(); } -- cgit v1.2.3