diff options
author | David S. Miller <davem@davemloft.net> | 2006-06-29 18:08:02 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-06-29 19:37:40 -0400 |
commit | 8f96cd1a69d4c43e3473406a1fdf15cd9f1de5e5 (patch) | |
tree | 34e43df9f2687720997e43a6c944c73ef61414db | |
parent | 2b1e59787198e75fb2ffb3bb4fb247da1c55ac12 (diff) |
[SPARC]: sparc32 side of of_device layer IRQ resolution.
Happily, life is much simpler on 32-bit sparc systems.
The "intr" property, preferred over the "interrupts"
property is used-as. Some minor translations of this
value happen on sun4d systems.
The stage is now set to rewrite the sparc serial driver
probing to use the of_driver framework, and then to convert
all SBUS, EBUS, and ISA drivers in-kind so that we can nuke
all those special bus frameworks.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | arch/sparc/kernel/of_device.c | 69 | ||||
-rw-r--r-- | include/asm-sparc/of_device.h | 5 |
2 files changed, 66 insertions, 8 deletions
diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index 3ebe6cc71e71..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) | |||
129 | return error; | 129 | return error; |
130 | } | 130 | } |
131 | 131 | ||
132 | static int node_match(struct device *dev, void *data) | ||
133 | { | ||
134 | struct of_device *op = to_of_device(dev); | ||
135 | struct device_node *dp = data; | ||
136 | |||
137 | return (op->node == dp); | ||
138 | } | ||
139 | |||
140 | struct of_device *of_find_device_by_node(struct device_node *dp) | ||
141 | { | ||
142 | struct device *dev = bus_find_device(&of_bus_type, NULL, | ||
143 | dp, node_match); | ||
144 | |||
145 | if (dev) | ||
146 | return to_of_device(dev); | ||
147 | |||
148 | return NULL; | ||
149 | } | ||
150 | EXPORT_SYMBOL(of_find_device_by_node); | ||
151 | |||
132 | #ifdef CONFIG_PCI | 152 | #ifdef CONFIG_PCI |
133 | struct bus_type ebus_bus_type = { | 153 | struct bus_type ebus_bus_type = { |
134 | .name = "ebus", | 154 | .name = "ebus", |
@@ -503,8 +523,8 @@ static struct of_device * __init scan_one_device(struct device_node *dp, | |||
503 | struct device *parent) | 523 | struct device *parent) |
504 | { | 524 | { |
505 | struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL); | 525 | struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL); |
506 | unsigned int *irq; | 526 | struct linux_prom_irqs *intr; |
507 | int len; | 527 | int len, i; |
508 | 528 | ||
509 | if (!op) | 529 | if (!op) |
510 | return NULL; | 530 | return NULL; |
@@ -517,11 +537,46 @@ static struct of_device * __init scan_one_device(struct device_node *dp, | |||
517 | if (op->portid == -1) | 537 | if (op->portid == -1) |
518 | op->portid = of_getintprop_default(dp, "portid", -1); | 538 | op->portid = of_getintprop_default(dp, "portid", -1); |
519 | 539 | ||
520 | irq = of_get_property(dp, "interrupts", &len); | 540 | intr = of_get_property(dp, "intr", &len); |
521 | if (irq) | 541 | if (intr) { |
522 | op->irq = *irq; | 542 | op->num_irqs = len / sizeof(struct linux_prom_irqs); |
523 | else | 543 | for (i = 0; i < op->num_irqs; i++) |
524 | op->irq = 0xffffffff; | 544 | op->irqs[i] = intr[i].pri; |
545 | } else { | ||
546 | unsigned int *irq = of_get_property(dp, "interrupts", &len); | ||
547 | |||
548 | if (irq) { | ||
549 | op->num_irqs = len / sizeof(unsigned int); | ||
550 | for (i = 0; i < op->num_irqs; i++) | ||
551 | op->irqs[i] = irq[i]; | ||
552 | } else { | ||
553 | op->num_irqs = 0; | ||
554 | } | ||
555 | } | ||
556 | if (sparc_cpu_model == sun4d) { | ||
557 | static int pil_to_sbus[] = { | ||
558 | 0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0, | ||
559 | }; | ||
560 | struct device_node *busp = dp->parent; | ||
561 | struct linux_prom_registers *regs; | ||
562 | int board = of_getintprop_default(busp, "board#", 0); | ||
563 | int slot; | ||
564 | |||
565 | regs = of_get_property(dp, "reg", NULL); | ||
566 | slot = regs->which_io; | ||
567 | |||
568 | for (i = 0; i < op->num_irqs; i++) { | ||
569 | int this_irq = op->irqs[i]; | ||
570 | int sbusl = pil_to_sbus[this_irq]; | ||
571 | |||
572 | if (sbusl) | ||
573 | this_irq = (((board + 1) << 5) + | ||
574 | (sbusl << 2) + | ||
575 | slot); | ||
576 | |||
577 | op->irqs[i] = this_irq; | ||
578 | } | ||
579 | } | ||
525 | 580 | ||
526 | build_device_resources(op, parent); | 581 | build_device_resources(op, parent); |
527 | 582 | ||
diff --git a/include/asm-sparc/of_device.h b/include/asm-sparc/of_device.h index b5ca3145d48b..80ea31f6e17f 100644 --- a/include/asm-sparc/of_device.h +++ b/include/asm-sparc/of_device.h | |||
@@ -21,7 +21,8 @@ struct of_device | |||
21 | struct device_node *node; | 21 | struct device_node *node; |
22 | struct device dev; | 22 | struct device dev; |
23 | struct resource resource[PROMREG_MAX]; | 23 | struct resource resource[PROMREG_MAX]; |
24 | unsigned int irq; | 24 | unsigned int irqs[PROMINTR_MAX]; |
25 | int num_irqs; | ||
25 | 26 | ||
26 | void *sysdata; | 27 | void *sysdata; |
27 | 28 | ||
@@ -34,6 +35,8 @@ struct of_device | |||
34 | extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name); | 35 | extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name); |
35 | extern void of_iounmap(void __iomem *base, unsigned long size); | 36 | extern void of_iounmap(void __iomem *base, unsigned long size); |
36 | 37 | ||
38 | extern struct of_device *of_find_device_by_node(struct device_node *); | ||
39 | |||
37 | extern const struct of_device_id *of_match_device( | 40 | extern const struct of_device_id *of_match_device( |
38 | const struct of_device_id *matches, const struct of_device *dev); | 41 | const struct of_device_id *matches, const struct of_device *dev); |
39 | 42 | ||