diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-14 16:05:21 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-14 16:05:21 -0500 |
commit | 4964e0664c80680fa6b28ef91381c076a5b25c2c (patch) | |
tree | 62099c5aaeee7274bcc66bcfba35d479affa97cf /arch/mips/bcm63xx/irq.c | |
parent | 0a80939b3e6af4b0dc93bf88ec02fd7e90a16f1b (diff) | |
parent | 7bf6612e8a9d6a0b3b82e8e2611942be1258b307 (diff) |
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (119 commits)
MIPS: Delete unused function add_temporary_entry.
MIPS: Set default pci cache line size.
MIPS: Flush huge TLB
MIPS: Octeon: Remove SYS_SUPPORTS_HIGHMEM.
MIPS: Octeon: Add support for OCTEON II PCIe
MIPS: Octeon: Update PCI Latency timer and enable more error reporting.
MIPS: Alchemy: Update cpu-feature-overrides
MIPS: Alchemy: db1200: Improve PB1200 detection.
MIPS: Alchemy: merge Au1000 and Au1300-style IRQ controller code.
MIPS: Alchemy: chain IRQ controllers to MIPS IRQ controller
MIPS: Alchemy: irq: register pm at irq init time
MIPS: Alchemy: Touchscreen support on DB1100
MIPS: Alchemy: Hook up IrDA on DB1000/DB1100
net/irda: convert au1k_ir to platform driver.
MIPS: Alchemy: remove unused board headers
MTD: nand: make au1550nd.c a platform_driver
MIPS: Netlogic: Mark Netlogic chips as SMT capable
MIPS: Netlogic: Add support for XLP 3XX cores
MIPS: Netlogic: Merge some of XLR/XLP wakup code
MIPS: Netlogic: Add default XLP config.
...
Fix up trivial conflicts in arch/mips/kernel/{perf_event_mipsxx.c,
traps.c} and drivers/tty/serial/Makefile
Diffstat (limited to 'arch/mips/bcm63xx/irq.c')
-rw-r--r-- | arch/mips/bcm63xx/irq.c | 403 |
1 files changed, 333 insertions, 70 deletions
diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c index 162e11b4ed75..9a216a451d92 100644 --- a/arch/mips/bcm63xx/irq.c +++ b/arch/mips/bcm63xx/irq.c | |||
@@ -19,19 +19,187 @@ | |||
19 | #include <bcm63xx_io.h> | 19 | #include <bcm63xx_io.h> |
20 | #include <bcm63xx_irq.h> | 20 | #include <bcm63xx_irq.h> |
21 | 21 | ||
22 | static void __dispatch_internal(void) __maybe_unused; | ||
23 | static void __dispatch_internal_64(void) __maybe_unused; | ||
24 | static void __internal_irq_mask_32(unsigned int irq) __maybe_unused; | ||
25 | static void __internal_irq_mask_64(unsigned int irq) __maybe_unused; | ||
26 | static void __internal_irq_unmask_32(unsigned int irq) __maybe_unused; | ||
27 | static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused; | ||
28 | |||
29 | #ifndef BCMCPU_RUNTIME_DETECT | ||
30 | #ifdef CONFIG_BCM63XX_CPU_6338 | ||
31 | #define irq_stat_reg PERF_IRQSTAT_6338_REG | ||
32 | #define irq_mask_reg PERF_IRQMASK_6338_REG | ||
33 | #define irq_bits 32 | ||
34 | #define is_ext_irq_cascaded 0 | ||
35 | #define ext_irq_start 0 | ||
36 | #define ext_irq_end 0 | ||
37 | #define ext_irq_count 4 | ||
38 | #define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6338 | ||
39 | #define ext_irq_cfg_reg2 0 | ||
40 | #endif | ||
41 | #ifdef CONFIG_BCM63XX_CPU_6345 | ||
42 | #define irq_stat_reg PERF_IRQSTAT_6345_REG | ||
43 | #define irq_mask_reg PERF_IRQMASK_6345_REG | ||
44 | #define irq_bits 32 | ||
45 | #define is_ext_irq_cascaded 0 | ||
46 | #define ext_irq_start 0 | ||
47 | #define ext_irq_end 0 | ||
48 | #define ext_irq_count 0 | ||
49 | #define ext_irq_cfg_reg1 0 | ||
50 | #define ext_irq_cfg_reg2 0 | ||
51 | #endif | ||
52 | #ifdef CONFIG_BCM63XX_CPU_6348 | ||
53 | #define irq_stat_reg PERF_IRQSTAT_6348_REG | ||
54 | #define irq_mask_reg PERF_IRQMASK_6348_REG | ||
55 | #define irq_bits 32 | ||
56 | #define is_ext_irq_cascaded 0 | ||
57 | #define ext_irq_start 0 | ||
58 | #define ext_irq_end 0 | ||
59 | #define ext_irq_count 4 | ||
60 | #define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6348 | ||
61 | #define ext_irq_cfg_reg2 0 | ||
62 | #endif | ||
63 | #ifdef CONFIG_BCM63XX_CPU_6358 | ||
64 | #define irq_stat_reg PERF_IRQSTAT_6358_REG | ||
65 | #define irq_mask_reg PERF_IRQMASK_6358_REG | ||
66 | #define irq_bits 32 | ||
67 | #define is_ext_irq_cascaded 1 | ||
68 | #define ext_irq_start (BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE) | ||
69 | #define ext_irq_end (BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE) | ||
70 | #define ext_irq_count 4 | ||
71 | #define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6358 | ||
72 | #define ext_irq_cfg_reg2 0 | ||
73 | #endif | ||
74 | #ifdef CONFIG_BCM63XX_CPU_6368 | ||
75 | #define irq_stat_reg PERF_IRQSTAT_6368_REG | ||
76 | #define irq_mask_reg PERF_IRQMASK_6368_REG | ||
77 | #define irq_bits 64 | ||
78 | #define is_ext_irq_cascaded 1 | ||
79 | #define ext_irq_start (BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE) | ||
80 | #define ext_irq_end (BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE) | ||
81 | #define ext_irq_count 6 | ||
82 | #define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6368 | ||
83 | #define ext_irq_cfg_reg2 PERF_EXTIRQ_CFG_REG2_6368 | ||
84 | #endif | ||
85 | |||
86 | #if irq_bits == 32 | ||
87 | #define dispatch_internal __dispatch_internal | ||
88 | #define internal_irq_mask __internal_irq_mask_32 | ||
89 | #define internal_irq_unmask __internal_irq_unmask_32 | ||
90 | #else | ||
91 | #define dispatch_internal __dispatch_internal_64 | ||
92 | #define internal_irq_mask __internal_irq_mask_64 | ||
93 | #define internal_irq_unmask __internal_irq_unmask_64 | ||
94 | #endif | ||
95 | |||
96 | #define irq_stat_addr (bcm63xx_regset_address(RSET_PERF) + irq_stat_reg) | ||
97 | #define irq_mask_addr (bcm63xx_regset_address(RSET_PERF) + irq_mask_reg) | ||
98 | |||
99 | static inline void bcm63xx_init_irq(void) | ||
100 | { | ||
101 | } | ||
102 | #else /* ! BCMCPU_RUNTIME_DETECT */ | ||
103 | |||
104 | static u32 irq_stat_addr, irq_mask_addr; | ||
105 | static void (*dispatch_internal)(void); | ||
106 | static int is_ext_irq_cascaded; | ||
107 | static unsigned int ext_irq_count; | ||
108 | static unsigned int ext_irq_start, ext_irq_end; | ||
109 | static unsigned int ext_irq_cfg_reg1, ext_irq_cfg_reg2; | ||
110 | static void (*internal_irq_mask)(unsigned int irq); | ||
111 | static void (*internal_irq_unmask)(unsigned int irq); | ||
112 | |||
113 | static void bcm63xx_init_irq(void) | ||
114 | { | ||
115 | int irq_bits; | ||
116 | |||
117 | irq_stat_addr = bcm63xx_regset_address(RSET_PERF); | ||
118 | irq_mask_addr = bcm63xx_regset_address(RSET_PERF); | ||
119 | |||
120 | switch (bcm63xx_get_cpu_id()) { | ||
121 | case BCM6338_CPU_ID: | ||
122 | irq_stat_addr += PERF_IRQSTAT_6338_REG; | ||
123 | irq_mask_addr += PERF_IRQMASK_6338_REG; | ||
124 | irq_bits = 32; | ||
125 | break; | ||
126 | case BCM6345_CPU_ID: | ||
127 | irq_stat_addr += PERF_IRQSTAT_6345_REG; | ||
128 | irq_mask_addr += PERF_IRQMASK_6345_REG; | ||
129 | irq_bits = 32; | ||
130 | break; | ||
131 | case BCM6348_CPU_ID: | ||
132 | irq_stat_addr += PERF_IRQSTAT_6348_REG; | ||
133 | irq_mask_addr += PERF_IRQMASK_6348_REG; | ||
134 | irq_bits = 32; | ||
135 | ext_irq_count = 4; | ||
136 | ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6348; | ||
137 | break; | ||
138 | case BCM6358_CPU_ID: | ||
139 | irq_stat_addr += PERF_IRQSTAT_6358_REG; | ||
140 | irq_mask_addr += PERF_IRQMASK_6358_REG; | ||
141 | irq_bits = 32; | ||
142 | ext_irq_count = 4; | ||
143 | is_ext_irq_cascaded = 1; | ||
144 | ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE; | ||
145 | ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE; | ||
146 | ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358; | ||
147 | break; | ||
148 | case BCM6368_CPU_ID: | ||
149 | irq_stat_addr += PERF_IRQSTAT_6368_REG; | ||
150 | irq_mask_addr += PERF_IRQMASK_6368_REG; | ||
151 | irq_bits = 64; | ||
152 | ext_irq_count = 6; | ||
153 | is_ext_irq_cascaded = 1; | ||
154 | ext_irq_start = BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE; | ||
155 | ext_irq_end = BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE; | ||
156 | ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6368; | ||
157 | ext_irq_cfg_reg2 = PERF_EXTIRQ_CFG_REG2_6368; | ||
158 | break; | ||
159 | default: | ||
160 | BUG(); | ||
161 | } | ||
162 | |||
163 | if (irq_bits == 32) { | ||
164 | dispatch_internal = __dispatch_internal; | ||
165 | internal_irq_mask = __internal_irq_mask_32; | ||
166 | internal_irq_unmask = __internal_irq_unmask_32; | ||
167 | } else { | ||
168 | dispatch_internal = __dispatch_internal_64; | ||
169 | internal_irq_mask = __internal_irq_mask_64; | ||
170 | internal_irq_unmask = __internal_irq_unmask_64; | ||
171 | } | ||
172 | } | ||
173 | #endif /* ! BCMCPU_RUNTIME_DETECT */ | ||
174 | |||
175 | static inline u32 get_ext_irq_perf_reg(int irq) | ||
176 | { | ||
177 | if (irq < 4) | ||
178 | return ext_irq_cfg_reg1; | ||
179 | return ext_irq_cfg_reg2; | ||
180 | } | ||
181 | |||
182 | static inline void handle_internal(int intbit) | ||
183 | { | ||
184 | if (is_ext_irq_cascaded && | ||
185 | intbit >= ext_irq_start && intbit <= ext_irq_end) | ||
186 | do_IRQ(intbit - ext_irq_start + IRQ_EXTERNAL_BASE); | ||
187 | else | ||
188 | do_IRQ(intbit + IRQ_INTERNAL_BASE); | ||
189 | } | ||
190 | |||
22 | /* | 191 | /* |
23 | * dispatch internal devices IRQ (uart, enet, watchdog, ...). do not | 192 | * dispatch internal devices IRQ (uart, enet, watchdog, ...). do not |
24 | * prioritize any interrupt relatively to another. the static counter | 193 | * prioritize any interrupt relatively to another. the static counter |
25 | * will resume the loop where it ended the last time we left this | 194 | * will resume the loop where it ended the last time we left this |
26 | * function. | 195 | * function. |
27 | */ | 196 | */ |
28 | static void bcm63xx_irq_dispatch_internal(void) | 197 | static void __dispatch_internal(void) |
29 | { | 198 | { |
30 | u32 pending; | 199 | u32 pending; |
31 | static int i; | 200 | static int i; |
32 | 201 | ||
33 | pending = bcm_perf_readl(PERF_IRQMASK_REG) & | 202 | pending = bcm_readl(irq_stat_addr) & bcm_readl(irq_mask_addr); |
34 | bcm_perf_readl(PERF_IRQSTAT_REG); | ||
35 | 203 | ||
36 | if (!pending) | 204 | if (!pending) |
37 | return ; | 205 | return ; |
@@ -41,7 +209,28 @@ static void bcm63xx_irq_dispatch_internal(void) | |||
41 | 209 | ||
42 | i = (i + 1) & 0x1f; | 210 | i = (i + 1) & 0x1f; |
43 | if (pending & (1 << to_call)) { | 211 | if (pending & (1 << to_call)) { |
44 | do_IRQ(to_call + IRQ_INTERNAL_BASE); | 212 | handle_internal(to_call); |
213 | break; | ||
214 | } | ||
215 | } | ||
216 | } | ||
217 | |||
218 | static void __dispatch_internal_64(void) | ||
219 | { | ||
220 | u64 pending; | ||
221 | static int i; | ||
222 | |||
223 | pending = bcm_readq(irq_stat_addr) & bcm_readq(irq_mask_addr); | ||
224 | |||
225 | if (!pending) | ||
226 | return ; | ||
227 | |||
228 | while (1) { | ||
229 | int to_call = i; | ||
230 | |||
231 | i = (i + 1) & 0x3f; | ||
232 | if (pending & (1ull << to_call)) { | ||
233 | handle_internal(to_call); | ||
45 | break; | 234 | break; |
46 | } | 235 | } |
47 | } | 236 | } |
@@ -60,15 +249,17 @@ asmlinkage void plat_irq_dispatch(void) | |||
60 | if (cause & CAUSEF_IP7) | 249 | if (cause & CAUSEF_IP7) |
61 | do_IRQ(7); | 250 | do_IRQ(7); |
62 | if (cause & CAUSEF_IP2) | 251 | if (cause & CAUSEF_IP2) |
63 | bcm63xx_irq_dispatch_internal(); | 252 | dispatch_internal(); |
64 | if (cause & CAUSEF_IP3) | 253 | if (!is_ext_irq_cascaded) { |
65 | do_IRQ(IRQ_EXT_0); | 254 | if (cause & CAUSEF_IP3) |
66 | if (cause & CAUSEF_IP4) | 255 | do_IRQ(IRQ_EXT_0); |
67 | do_IRQ(IRQ_EXT_1); | 256 | if (cause & CAUSEF_IP4) |
68 | if (cause & CAUSEF_IP5) | 257 | do_IRQ(IRQ_EXT_1); |
69 | do_IRQ(IRQ_EXT_2); | 258 | if (cause & CAUSEF_IP5) |
70 | if (cause & CAUSEF_IP6) | 259 | do_IRQ(IRQ_EXT_2); |
71 | do_IRQ(IRQ_EXT_3); | 260 | if (cause & CAUSEF_IP6) |
261 | do_IRQ(IRQ_EXT_3); | ||
262 | } | ||
72 | } while (1); | 263 | } while (1); |
73 | } | 264 | } |
74 | 265 | ||
@@ -76,24 +267,50 @@ asmlinkage void plat_irq_dispatch(void) | |||
76 | * internal IRQs operations: only mask/unmask on PERF irq mask | 267 | * internal IRQs operations: only mask/unmask on PERF irq mask |
77 | * register. | 268 | * register. |
78 | */ | 269 | */ |
79 | static inline void bcm63xx_internal_irq_mask(struct irq_data *d) | 270 | static void __internal_irq_mask_32(unsigned int irq) |
80 | { | 271 | { |
81 | unsigned int irq = d->irq - IRQ_INTERNAL_BASE; | ||
82 | u32 mask; | 272 | u32 mask; |
83 | 273 | ||
84 | mask = bcm_perf_readl(PERF_IRQMASK_REG); | 274 | mask = bcm_readl(irq_mask_addr); |
85 | mask &= ~(1 << irq); | 275 | mask &= ~(1 << irq); |
86 | bcm_perf_writel(mask, PERF_IRQMASK_REG); | 276 | bcm_writel(mask, irq_mask_addr); |
87 | } | 277 | } |
88 | 278 | ||
89 | static void bcm63xx_internal_irq_unmask(struct irq_data *d) | 279 | static void __internal_irq_mask_64(unsigned int irq) |
280 | { | ||
281 | u64 mask; | ||
282 | |||
283 | mask = bcm_readq(irq_mask_addr); | ||
284 | mask &= ~(1ull << irq); | ||
285 | bcm_writeq(mask, irq_mask_addr); | ||
286 | } | ||
287 | |||
288 | static void __internal_irq_unmask_32(unsigned int irq) | ||
90 | { | 289 | { |
91 | unsigned int irq = d->irq - IRQ_INTERNAL_BASE; | ||
92 | u32 mask; | 290 | u32 mask; |
93 | 291 | ||
94 | mask = bcm_perf_readl(PERF_IRQMASK_REG); | 292 | mask = bcm_readl(irq_mask_addr); |
95 | mask |= (1 << irq); | 293 | mask |= (1 << irq); |
96 | bcm_perf_writel(mask, PERF_IRQMASK_REG); | 294 | bcm_writel(mask, irq_mask_addr); |
295 | } | ||
296 | |||
297 | static void __internal_irq_unmask_64(unsigned int irq) | ||
298 | { | ||
299 | u64 mask; | ||
300 | |||
301 | mask = bcm_readq(irq_mask_addr); | ||
302 | mask |= (1ull << irq); | ||
303 | bcm_writeq(mask, irq_mask_addr); | ||
304 | } | ||
305 | |||
306 | static void bcm63xx_internal_irq_mask(struct irq_data *d) | ||
307 | { | ||
308 | internal_irq_mask(d->irq - IRQ_INTERNAL_BASE); | ||
309 | } | ||
310 | |||
311 | static void bcm63xx_internal_irq_unmask(struct irq_data *d) | ||
312 | { | ||
313 | internal_irq_unmask(d->irq - IRQ_INTERNAL_BASE); | ||
97 | } | 314 | } |
98 | 315 | ||
99 | /* | 316 | /* |
@@ -102,94 +319,131 @@ static void bcm63xx_internal_irq_unmask(struct irq_data *d) | |||
102 | */ | 319 | */ |
103 | static void bcm63xx_external_irq_mask(struct irq_data *d) | 320 | static void bcm63xx_external_irq_mask(struct irq_data *d) |
104 | { | 321 | { |
105 | unsigned int irq = d->irq - IRQ_EXT_BASE; | 322 | unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; |
106 | u32 reg; | 323 | u32 reg, regaddr; |
107 | 324 | ||
108 | reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); | 325 | regaddr = get_ext_irq_perf_reg(irq); |
109 | reg &= ~EXTIRQ_CFG_MASK(irq); | 326 | reg = bcm_perf_readl(regaddr); |
110 | bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); | 327 | |
328 | if (BCMCPU_IS_6348()) | ||
329 | reg &= ~EXTIRQ_CFG_MASK_6348(irq % 4); | ||
330 | else | ||
331 | reg &= ~EXTIRQ_CFG_MASK(irq % 4); | ||
332 | |||
333 | bcm_perf_writel(reg, regaddr); | ||
334 | if (is_ext_irq_cascaded) | ||
335 | internal_irq_mask(irq + ext_irq_start); | ||
111 | } | 336 | } |
112 | 337 | ||
113 | static void bcm63xx_external_irq_unmask(struct irq_data *d) | 338 | static void bcm63xx_external_irq_unmask(struct irq_data *d) |
114 | { | 339 | { |
115 | unsigned int irq = d->irq - IRQ_EXT_BASE; | 340 | unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; |
116 | u32 reg; | 341 | u32 reg, regaddr; |
117 | 342 | ||
118 | reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); | 343 | regaddr = get_ext_irq_perf_reg(irq); |
119 | reg |= EXTIRQ_CFG_MASK(irq); | 344 | reg = bcm_perf_readl(regaddr); |
120 | bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); | 345 | |
346 | if (BCMCPU_IS_6348()) | ||
347 | reg |= EXTIRQ_CFG_MASK_6348(irq % 4); | ||
348 | else | ||
349 | reg |= EXTIRQ_CFG_MASK(irq % 4); | ||
350 | |||
351 | bcm_perf_writel(reg, regaddr); | ||
352 | |||
353 | if (is_ext_irq_cascaded) | ||
354 | internal_irq_unmask(irq + ext_irq_start); | ||
121 | } | 355 | } |
122 | 356 | ||
123 | static void bcm63xx_external_irq_clear(struct irq_data *d) | 357 | static void bcm63xx_external_irq_clear(struct irq_data *d) |
124 | { | 358 | { |
125 | unsigned int irq = d->irq - IRQ_EXT_BASE; | 359 | unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; |
126 | u32 reg; | 360 | u32 reg, regaddr; |
127 | 361 | ||
128 | reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); | 362 | regaddr = get_ext_irq_perf_reg(irq); |
129 | reg |= EXTIRQ_CFG_CLEAR(irq); | 363 | reg = bcm_perf_readl(regaddr); |
130 | bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); | ||
131 | } | ||
132 | 364 | ||
133 | static unsigned int bcm63xx_external_irq_startup(struct irq_data *d) | 365 | if (BCMCPU_IS_6348()) |
134 | { | 366 | reg |= EXTIRQ_CFG_CLEAR_6348(irq % 4); |
135 | set_c0_status(0x100 << (d->irq - IRQ_MIPS_BASE)); | 367 | else |
136 | irq_enable_hazard(); | 368 | reg |= EXTIRQ_CFG_CLEAR(irq % 4); |
137 | bcm63xx_external_irq_unmask(d); | ||
138 | return 0; | ||
139 | } | ||
140 | 369 | ||
141 | static void bcm63xx_external_irq_shutdown(struct irq_data *d) | 370 | bcm_perf_writel(reg, regaddr); |
142 | { | ||
143 | bcm63xx_external_irq_mask(d); | ||
144 | clear_c0_status(0x100 << (d->irq - IRQ_MIPS_BASE)); | ||
145 | irq_disable_hazard(); | ||
146 | } | 371 | } |
147 | 372 | ||
148 | static int bcm63xx_external_irq_set_type(struct irq_data *d, | 373 | static int bcm63xx_external_irq_set_type(struct irq_data *d, |
149 | unsigned int flow_type) | 374 | unsigned int flow_type) |
150 | { | 375 | { |
151 | unsigned int irq = d->irq - IRQ_EXT_BASE; | 376 | unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; |
152 | u32 reg; | 377 | u32 reg, regaddr; |
378 | int levelsense, sense, bothedge; | ||
153 | 379 | ||
154 | flow_type &= IRQ_TYPE_SENSE_MASK; | 380 | flow_type &= IRQ_TYPE_SENSE_MASK; |
155 | 381 | ||
156 | if (flow_type == IRQ_TYPE_NONE) | 382 | if (flow_type == IRQ_TYPE_NONE) |
157 | flow_type = IRQ_TYPE_LEVEL_LOW; | 383 | flow_type = IRQ_TYPE_LEVEL_LOW; |
158 | 384 | ||
159 | reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); | 385 | levelsense = sense = bothedge = 0; |
160 | switch (flow_type) { | 386 | switch (flow_type) { |
161 | case IRQ_TYPE_EDGE_BOTH: | 387 | case IRQ_TYPE_EDGE_BOTH: |
162 | reg &= ~EXTIRQ_CFG_LEVELSENSE(irq); | 388 | bothedge = 1; |
163 | reg |= EXTIRQ_CFG_BOTHEDGE(irq); | ||
164 | break; | 389 | break; |
165 | 390 | ||
166 | case IRQ_TYPE_EDGE_RISING: | 391 | case IRQ_TYPE_EDGE_RISING: |
167 | reg &= ~EXTIRQ_CFG_LEVELSENSE(irq); | 392 | sense = 1; |
168 | reg |= EXTIRQ_CFG_SENSE(irq); | ||
169 | reg &= ~EXTIRQ_CFG_BOTHEDGE(irq); | ||
170 | break; | 393 | break; |
171 | 394 | ||
172 | case IRQ_TYPE_EDGE_FALLING: | 395 | case IRQ_TYPE_EDGE_FALLING: |
173 | reg &= ~EXTIRQ_CFG_LEVELSENSE(irq); | ||
174 | reg &= ~EXTIRQ_CFG_SENSE(irq); | ||
175 | reg &= ~EXTIRQ_CFG_BOTHEDGE(irq); | ||
176 | break; | 396 | break; |
177 | 397 | ||
178 | case IRQ_TYPE_LEVEL_HIGH: | 398 | case IRQ_TYPE_LEVEL_HIGH: |
179 | reg |= EXTIRQ_CFG_LEVELSENSE(irq); | 399 | levelsense = 1; |
180 | reg |= EXTIRQ_CFG_SENSE(irq); | 400 | sense = 1; |
181 | break; | 401 | break; |
182 | 402 | ||
183 | case IRQ_TYPE_LEVEL_LOW: | 403 | case IRQ_TYPE_LEVEL_LOW: |
184 | reg |= EXTIRQ_CFG_LEVELSENSE(irq); | 404 | levelsense = 1; |
185 | reg &= ~EXTIRQ_CFG_SENSE(irq); | ||
186 | break; | 405 | break; |
187 | 406 | ||
188 | default: | 407 | default: |
189 | printk(KERN_ERR "bogus flow type combination given !\n"); | 408 | printk(KERN_ERR "bogus flow type combination given !\n"); |
190 | return -EINVAL; | 409 | return -EINVAL; |
191 | } | 410 | } |
192 | bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); | 411 | |
412 | regaddr = get_ext_irq_perf_reg(irq); | ||
413 | reg = bcm_perf_readl(regaddr); | ||
414 | irq %= 4; | ||
415 | |||
416 | if (BCMCPU_IS_6348()) { | ||
417 | if (levelsense) | ||
418 | reg |= EXTIRQ_CFG_LEVELSENSE_6348(irq); | ||
419 | else | ||
420 | reg &= ~EXTIRQ_CFG_LEVELSENSE_6348(irq); | ||
421 | if (sense) | ||
422 | reg |= EXTIRQ_CFG_SENSE_6348(irq); | ||
423 | else | ||
424 | reg &= ~EXTIRQ_CFG_SENSE_6348(irq); | ||
425 | if (bothedge) | ||
426 | reg |= EXTIRQ_CFG_BOTHEDGE_6348(irq); | ||
427 | else | ||
428 | reg &= ~EXTIRQ_CFG_BOTHEDGE_6348(irq); | ||
429 | } | ||
430 | |||
431 | if (BCMCPU_IS_6338() || BCMCPU_IS_6358() || BCMCPU_IS_6368()) { | ||
432 | if (levelsense) | ||
433 | reg |= EXTIRQ_CFG_LEVELSENSE(irq); | ||
434 | else | ||
435 | reg &= ~EXTIRQ_CFG_LEVELSENSE(irq); | ||
436 | if (sense) | ||
437 | reg |= EXTIRQ_CFG_SENSE(irq); | ||
438 | else | ||
439 | reg &= ~EXTIRQ_CFG_SENSE(irq); | ||
440 | if (bothedge) | ||
441 | reg |= EXTIRQ_CFG_BOTHEDGE(irq); | ||
442 | else | ||
443 | reg &= ~EXTIRQ_CFG_BOTHEDGE(irq); | ||
444 | } | ||
445 | |||
446 | bcm_perf_writel(reg, regaddr); | ||
193 | 447 | ||
194 | irqd_set_trigger_type(d, flow_type); | 448 | irqd_set_trigger_type(d, flow_type); |
195 | if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) | 449 | if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) |
@@ -208,9 +462,6 @@ static struct irq_chip bcm63xx_internal_irq_chip = { | |||
208 | 462 | ||
209 | static struct irq_chip bcm63xx_external_irq_chip = { | 463 | static struct irq_chip bcm63xx_external_irq_chip = { |
210 | .name = "bcm63xx_epic", | 464 | .name = "bcm63xx_epic", |
211 | .irq_startup = bcm63xx_external_irq_startup, | ||
212 | .irq_shutdown = bcm63xx_external_irq_shutdown, | ||
213 | |||
214 | .irq_ack = bcm63xx_external_irq_clear, | 465 | .irq_ack = bcm63xx_external_irq_clear, |
215 | 466 | ||
216 | .irq_mask = bcm63xx_external_irq_mask, | 467 | .irq_mask = bcm63xx_external_irq_mask, |
@@ -225,18 +476,30 @@ static struct irqaction cpu_ip2_cascade_action = { | |||
225 | .flags = IRQF_NO_THREAD, | 476 | .flags = IRQF_NO_THREAD, |
226 | }; | 477 | }; |
227 | 478 | ||
479 | static struct irqaction cpu_ext_cascade_action = { | ||
480 | .handler = no_action, | ||
481 | .name = "cascade_extirq", | ||
482 | .flags = IRQF_NO_THREAD, | ||
483 | }; | ||
484 | |||
228 | void __init arch_init_irq(void) | 485 | void __init arch_init_irq(void) |
229 | { | 486 | { |
230 | int i; | 487 | int i; |
231 | 488 | ||
489 | bcm63xx_init_irq(); | ||
232 | mips_cpu_irq_init(); | 490 | mips_cpu_irq_init(); |
233 | for (i = IRQ_INTERNAL_BASE; i < NR_IRQS; ++i) | 491 | for (i = IRQ_INTERNAL_BASE; i < NR_IRQS; ++i) |
234 | irq_set_chip_and_handler(i, &bcm63xx_internal_irq_chip, | 492 | irq_set_chip_and_handler(i, &bcm63xx_internal_irq_chip, |
235 | handle_level_irq); | 493 | handle_level_irq); |
236 | 494 | ||
237 | for (i = IRQ_EXT_BASE; i < IRQ_EXT_BASE + 4; ++i) | 495 | for (i = IRQ_EXTERNAL_BASE; i < IRQ_EXTERNAL_BASE + ext_irq_count; ++i) |
238 | irq_set_chip_and_handler(i, &bcm63xx_external_irq_chip, | 496 | irq_set_chip_and_handler(i, &bcm63xx_external_irq_chip, |
239 | handle_edge_irq); | 497 | handle_edge_irq); |
240 | 498 | ||
241 | setup_irq(IRQ_MIPS_BASE + 2, &cpu_ip2_cascade_action); | 499 | if (!is_ext_irq_cascaded) { |
500 | for (i = 3; i < 3 + ext_irq_count; ++i) | ||
501 | setup_irq(MIPS_CPU_IRQ_BASE + i, &cpu_ext_cascade_action); | ||
502 | } | ||
503 | |||
504 | setup_irq(MIPS_CPU_IRQ_BASE + 2, &cpu_ip2_cascade_action); | ||
242 | } | 505 | } |