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 /arch/sparc/kernel | |
| 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>
Diffstat (limited to 'arch/sparc/kernel')
| -rw-r--r-- | arch/sparc/kernel/of_device.c | 69 |
1 files changed, 62 insertions, 7 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 | ||
