aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
authorSam Ravnborg <sam@ravnborg.org>2011-02-26 02:01:19 -0500
committerDavid S. Miller <davem@davemloft.net>2011-03-16 21:19:14 -0400
commit1d05995b0880b23353741d5b2b826f7c2fd6a296 (patch)
tree47fa622ab354f0fb88a7cb626797de186068d329 /arch/sparc
parentbbdc2661eabddd442240533a66b2290f77d89ccc (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.h4
-rw-r--r--arch/sparc/kernel/irq_32.c8
-rw-r--r--arch/sparc/kernel/of_device_32.c59
-rw-r--r--arch/sparc/kernel/sun4d_irq.c51
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 */
8struct sparc_irq_config { 10struct 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};
11extern struct sparc_irq_config sparc_irq_config; 15extern 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}
583EXPORT_SYMBOL(probe_irq_off); 583EXPORT_SYMBOL(probe_irq_off);
584 584
585static 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
593void __init init_IRQ(void) 599void __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
423build_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
443unsigned 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
489err_out:
490 return real_irq;
491}
492
443static void __init sun4d_fixup_trap_table(void) 493static 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);