diff options
| author | Sam Ravnborg <sam@ravnborg.org> | 2011-02-26 02:01:19 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2011-03-16 21:19:14 -0400 |
| commit | 1d05995b0880b23353741d5b2b826f7c2fd6a296 (patch) | |
| tree | 47fa622ab354f0fb88a7cb626797de186068d329 /arch/sparc | |
| parent | bbdc2661eabddd442240533a66b2290f77d89ccc (diff) | |
sparc32: introduce build_device_irq
build_device_irq() is used to encapsulate the plaform
specific details when we build an irq.
For now the default is a simple 1:1 but sun4d differs.
This patch refactors functionality - but does not change
the existing functionality.
Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc')
| -rw-r--r-- | arch/sparc/kernel/irq.h | 4 | ||||
| -rw-r--r-- | arch/sparc/kernel/irq_32.c | 8 | ||||
| -rw-r--r-- | arch/sparc/kernel/of_device_32.c | 59 | ||||
| -rw-r--r-- | arch/sparc/kernel/sun4d_irq.c | 51 |
4 files changed, 68 insertions, 54 deletions
diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h index 4b4e54f32b26..0b4d5b902165 100644 --- a/arch/sparc/kernel/irq.h +++ b/arch/sparc/kernel/irq.h | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | #include <linux/platform_device.h> | ||
| 2 | |||
| 1 | #include <asm/btfixup.h> | 3 | #include <asm/btfixup.h> |
| 2 | 4 | ||
| 3 | /* | 5 | /* |
| @@ -7,6 +9,8 @@ | |||
| 7 | */ | 9 | */ |
| 8 | struct sparc_irq_config { | 10 | struct sparc_irq_config { |
| 9 | void (*init_timers)(irq_handler_t); | 11 | void (*init_timers)(irq_handler_t); |
| 12 | unsigned int (*build_device_irq)(struct platform_device *op, | ||
| 13 | unsigned int real_irq); | ||
| 10 | }; | 14 | }; |
| 11 | extern struct sparc_irq_config sparc_irq_config; | 15 | extern struct sparc_irq_config sparc_irq_config; |
| 12 | 16 | ||
diff --git a/arch/sparc/kernel/irq_32.c b/arch/sparc/kernel/irq_32.c index b80b8bf0bf00..7c93df4099cb 100644 --- a/arch/sparc/kernel/irq_32.c +++ b/arch/sparc/kernel/irq_32.c | |||
| @@ -582,6 +582,12 @@ int probe_irq_off(unsigned long mask) | |||
| 582 | } | 582 | } |
| 583 | EXPORT_SYMBOL(probe_irq_off); | 583 | EXPORT_SYMBOL(probe_irq_off); |
| 584 | 584 | ||
| 585 | static unsigned int build_device_irq(struct platform_device *op, | ||
| 586 | unsigned int real_irq) | ||
| 587 | { | ||
| 588 | return real_irq; | ||
| 589 | } | ||
| 590 | |||
| 585 | /* djhr | 591 | /* djhr |
| 586 | * This could probably be made indirect too and assigned in the CPU | 592 | * This could probably be made indirect too and assigned in the CPU |
| 587 | * bits of the code. That would be much nicer I think and would also | 593 | * bits of the code. That would be much nicer I think and would also |
| @@ -592,6 +598,8 @@ EXPORT_SYMBOL(probe_irq_off); | |||
| 592 | 598 | ||
| 593 | void __init init_IRQ(void) | 599 | void __init init_IRQ(void) |
| 594 | { | 600 | { |
| 601 | sparc_irq_config.build_device_irq = build_device_irq; | ||
| 602 | |||
| 595 | switch (sparc_cpu_model) { | 603 | switch (sparc_cpu_model) { |
| 596 | case sun4c: | 604 | case sun4c: |
| 597 | case sun4: | 605 | case sun4: |
diff --git a/arch/sparc/kernel/of_device_32.c b/arch/sparc/kernel/of_device_32.c index 2d055a1e9cc2..a312af40ea84 100644 --- a/arch/sparc/kernel/of_device_32.c +++ b/arch/sparc/kernel/of_device_32.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <asm/leon_amba.h> | 13 | #include <asm/leon_amba.h> |
| 14 | 14 | ||
| 15 | #include "of_device_common.h" | 15 | #include "of_device_common.h" |
| 16 | #include "irq.h" | ||
| 16 | 17 | ||
| 17 | /* | 18 | /* |
| 18 | * PCI bus specific translator | 19 | * PCI bus specific translator |
| @@ -355,7 +356,8 @@ static struct platform_device * __init scan_one_device(struct device_node *dp, | |||
| 355 | if (intr) { | 356 | if (intr) { |
| 356 | op->archdata.num_irqs = len / sizeof(struct linux_prom_irqs); | 357 | op->archdata.num_irqs = len / sizeof(struct linux_prom_irqs); |
| 357 | for (i = 0; i < op->archdata.num_irqs; i++) | 358 | for (i = 0; i < op->archdata.num_irqs; i++) |
| 358 | op->archdata.irqs[i] = intr[i].pri; | 359 | op->archdata.irqs[i] = |
| 360 | sparc_irq_config.build_device_irq(op, intr[i].pri); | ||
| 359 | } else { | 361 | } else { |
| 360 | const unsigned int *irq = | 362 | const unsigned int *irq = |
| 361 | of_get_property(dp, "interrupts", &len); | 363 | of_get_property(dp, "interrupts", &len); |
| @@ -363,64 +365,13 @@ static struct platform_device * __init scan_one_device(struct device_node *dp, | |||
| 363 | if (irq) { | 365 | if (irq) { |
| 364 | op->archdata.num_irqs = len / sizeof(unsigned int); | 366 | op->archdata.num_irqs = len / sizeof(unsigned int); |
| 365 | for (i = 0; i < op->archdata.num_irqs; i++) | 367 | for (i = 0; i < op->archdata.num_irqs; i++) |
| 366 | op->archdata.irqs[i] = irq[i]; | 368 | op->archdata.irqs[i] = |
| 369 | sparc_irq_config.build_device_irq(op, irq[i]); | ||
| 367 | } else { | 370 | } else { |
| 368 | op->archdata.num_irqs = 0; | 371 | op->archdata.num_irqs = 0; |
| 369 | } | 372 | } |
| 370 | } | 373 | } |
| 371 | if (sparc_cpu_model == sun4d) { | ||
| 372 | static int pil_to_sbus[] = { | ||
| 373 | 0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0, | ||
| 374 | }; | ||
| 375 | struct device_node *io_unit, *sbi = dp->parent; | ||
| 376 | const struct linux_prom_registers *regs; | ||
| 377 | int board, slot; | ||
| 378 | |||
| 379 | while (sbi) { | ||
| 380 | if (!strcmp(sbi->name, "sbi")) | ||
| 381 | break; | ||
| 382 | |||
| 383 | sbi = sbi->parent; | ||
| 384 | } | ||
| 385 | if (!sbi) | ||
| 386 | goto build_resources; | ||
| 387 | |||
| 388 | regs = of_get_property(dp, "reg", NULL); | ||
| 389 | if (!regs) | ||
| 390 | goto build_resources; | ||
| 391 | |||
| 392 | slot = regs->which_io; | ||
| 393 | |||
| 394 | /* If SBI's parent is not io-unit or the io-unit lacks | ||
| 395 | * a "board#" property, something is very wrong. | ||
| 396 | */ | ||
| 397 | if (!sbi->parent || strcmp(sbi->parent->name, "io-unit")) { | ||
| 398 | printk("%s: Error, parent is not io-unit.\n", | ||
| 399 | sbi->full_name); | ||
| 400 | goto build_resources; | ||
| 401 | } | ||
| 402 | io_unit = sbi->parent; | ||
| 403 | board = of_getintprop_default(io_unit, "board#", -1); | ||
| 404 | if (board == -1) { | ||
| 405 | printk("%s: Error, lacks board# property.\n", | ||
| 406 | io_unit->full_name); | ||
| 407 | goto build_resources; | ||
| 408 | } | ||
| 409 | |||
| 410 | for (i = 0; i < op->archdata.num_irqs; i++) { | ||
| 411 | int this_irq = op->archdata.irqs[i]; | ||
| 412 | int sbusl = pil_to_sbus[this_irq]; | ||
| 413 | |||
| 414 | if (sbusl) | ||
| 415 | this_irq = (((board + 1) << 5) + | ||
| 416 | (sbusl << 2) + | ||
| 417 | slot); | ||
| 418 | |||
| 419 | op->archdata.irqs[i] = this_irq; | ||
| 420 | } | ||
| 421 | } | ||
| 422 | 374 | ||
| 423 | build_resources: | ||
| 424 | build_device_resources(op, parent); | 375 | build_device_resources(op, parent); |
| 425 | 376 | ||
| 426 | op->dev.parent = parent; | 377 | op->dev.parent = parent; |
diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index fc1c22f121fd..77b4a8992710 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c | |||
| @@ -440,6 +440,56 @@ static void __init sun4d_load_profile_irqs(void) | |||
| 440 | } | 440 | } |
| 441 | } | 441 | } |
| 442 | 442 | ||
| 443 | unsigned int sun4d_build_device_irq(struct platform_device *op, | ||
| 444 | unsigned int real_irq) | ||
| 445 | { | ||
| 446 | static int pil_to_sbus[] = { | ||
| 447 | 0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0, | ||
| 448 | }; | ||
| 449 | struct device_node *dp = op->dev.of_node; | ||
| 450 | struct device_node *io_unit, *sbi = dp->parent; | ||
| 451 | const struct linux_prom_registers *regs; | ||
| 452 | int board, slot; | ||
| 453 | int sbusl; | ||
| 454 | |||
| 455 | while (sbi) { | ||
| 456 | if (!strcmp(sbi->name, "sbi")) | ||
| 457 | break; | ||
| 458 | |||
| 459 | sbi = sbi->parent; | ||
| 460 | } | ||
| 461 | if (!sbi) | ||
| 462 | goto err_out; | ||
| 463 | |||
| 464 | regs = of_get_property(dp, "reg", NULL); | ||
| 465 | if (!regs) | ||
| 466 | goto err_out; | ||
| 467 | |||
| 468 | slot = regs->which_io; | ||
| 469 | |||
| 470 | /* | ||
| 471 | * If SBI's parent is not io-unit or the io-unit lacks | ||
| 472 | * a "board#" property, something is very wrong. | ||
| 473 | */ | ||
| 474 | if (!sbi->parent || strcmp(sbi->parent->name, "io-unit")) { | ||
| 475 | printk("%s: Error, parent is not io-unit.\n", sbi->full_name); | ||
| 476 | goto err_out; | ||
| 477 | } | ||
| 478 | io_unit = sbi->parent; | ||
| 479 | board = of_getintprop_default(io_unit, "board#", -1); | ||
| 480 | if (board == -1) { | ||
| 481 | printk("%s: Error, lacks board# property.\n", io_unit->full_name); | ||
| 482 | goto err_out; | ||
| 483 | } | ||
| 484 | |||
| 485 | sbusl = pil_to_sbus[real_irq]; | ||
| 486 | if (sbusl) | ||
| 487 | return (((board + 1) << 5) + (sbusl << 2) + slot); | ||
| 488 | |||
| 489 | err_out: | ||
| 490 | return real_irq; | ||
| 491 | } | ||
| 492 | |||
| 443 | static void __init sun4d_fixup_trap_table(void) | 493 | static void __init sun4d_fixup_trap_table(void) |
| 444 | { | 494 | { |
| 445 | #ifdef CONFIG_SMP | 495 | #ifdef CONFIG_SMP |
| @@ -559,6 +609,7 @@ void __init sun4d_init_IRQ(void) | |||
| 559 | BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM); | 609 | BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM); |
| 560 | 610 | ||
| 561 | sparc_irq_config.init_timers = sun4d_init_timers; | 611 | sparc_irq_config.init_timers = sun4d_init_timers; |
| 612 | sparc_irq_config.build_device_irq = sun4d_build_device_irq; | ||
| 562 | 613 | ||
| 563 | #ifdef CONFIG_SMP | 614 | #ifdef CONFIG_SMP |
| 564 | BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM); | 615 | BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM); |
