diff options
Diffstat (limited to 'arch/sh/cchips/hd6446x/hd64461.c')
-rw-r--r-- | arch/sh/cchips/hd6446x/hd64461.c | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/arch/sh/cchips/hd6446x/hd64461.c b/arch/sh/cchips/hd6446x/hd64461.c index 50aa0c1f76ea..bcb31ae84a51 100644 --- a/arch/sh/cchips/hd6446x/hd64461.c +++ b/arch/sh/cchips/hd6446x/hd64461.c | |||
@@ -55,25 +55,22 @@ static struct irq_chip hd64461_irq_chip = { | |||
55 | 55 | ||
56 | static void hd64461_irq_demux(unsigned int irq, struct irq_desc *desc) | 56 | static void hd64461_irq_demux(unsigned int irq, struct irq_desc *desc) |
57 | { | 57 | { |
58 | unsigned short intv = ctrl_inw(HD64461_NIRR); | 58 | unsigned short intv = __raw_readw(HD64461_NIRR); |
59 | struct irq_desc *ext_desc; | ||
60 | unsigned int ext_irq = HD64461_IRQBASE; | 59 | unsigned int ext_irq = HD64461_IRQBASE; |
61 | 60 | ||
62 | intv &= (1 << HD64461_IRQ_NUM) - 1; | 61 | intv &= (1 << HD64461_IRQ_NUM) - 1; |
63 | 62 | ||
64 | while (intv) { | 63 | for (; intv; intv >>= 1, ext_irq++) { |
65 | if (intv & 1) { | 64 | if (!(intv & 1)) |
66 | ext_desc = irq_desc + ext_irq; | 65 | continue; |
67 | handle_level_irq(ext_irq, ext_desc); | 66 | |
68 | } | 67 | generic_handle_irq(ext_irq); |
69 | intv >>= 1; | ||
70 | ext_irq++; | ||
71 | } | 68 | } |
72 | } | 69 | } |
73 | 70 | ||
74 | int __init setup_hd64461(void) | 71 | int __init setup_hd64461(void) |
75 | { | 72 | { |
76 | int i; | 73 | int i, nid = cpu_to_node(boot_cpu_data); |
77 | 74 | ||
78 | if (!MACH_HD64461) | 75 | if (!MACH_HD64461) |
79 | return 0; | 76 | return 0; |
@@ -90,9 +87,26 @@ int __init setup_hd64461(void) | |||
90 | __raw_writew(0xffff, HD64461_NIMR); | 87 | __raw_writew(0xffff, HD64461_NIMR); |
91 | 88 | ||
92 | /* IRQ 80 -> 95 belongs to HD64461 */ | 89 | /* IRQ 80 -> 95 belongs to HD64461 */ |
93 | for (i = HD64461_IRQBASE; i < HD64461_IRQBASE + 16; i++) | 90 | for (i = HD64461_IRQBASE; i < HD64461_IRQBASE + 16; i++) { |
91 | unsigned int irq; | ||
92 | |||
93 | irq = create_irq_nr(i, nid); | ||
94 | if (unlikely(irq == 0)) { | ||
95 | pr_err("%s: failed hooking irq %d for HD64461\n", | ||
96 | __func__, i); | ||
97 | return -EBUSY; | ||
98 | } | ||
99 | |||
100 | if (unlikely(irq != i)) { | ||
101 | pr_err("%s: got irq %d but wanted %d, bailing.\n", | ||
102 | __func__, irq, i); | ||
103 | destroy_irq(irq); | ||
104 | return -EINVAL; | ||
105 | } | ||
106 | |||
94 | set_irq_chip_and_handler(i, &hd64461_irq_chip, | 107 | set_irq_chip_and_handler(i, &hd64461_irq_chip, |
95 | handle_level_irq); | 108 | handle_level_irq); |
109 | } | ||
96 | 110 | ||
97 | set_irq_chained_handler(CONFIG_HD64461_IRQ, hd64461_irq_demux); | 111 | set_irq_chained_handler(CONFIG_HD64461_IRQ, hd64461_irq_demux); |
98 | set_irq_type(CONFIG_HD64461_IRQ, IRQ_TYPE_LEVEL_LOW); | 112 | set_irq_type(CONFIG_HD64461_IRQ, IRQ_TYPE_LEVEL_LOW); |