diff options
author | Maxime Bizon <mbizon@freebox.fr> | 2011-11-04 14:09:33 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2011-12-07 17:03:03 -0500 |
commit | 71a43927b3bfe1a42cbf7bb174b170f06fa00a1a (patch) | |
tree | ee3a342d5b69cf27bd1c3ce4fea4515e280122e7 | |
parent | 015ce7d3526be8a969390fe625cb18f958e85a51 (diff) |
MIPS: BCM63XX: Handle 64 bits irq stat register in irq code.
bcm6368 has larger irq registers, prepare for this.
Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/2898/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | arch/mips/bcm63xx/irq.c | 82 |
1 files changed, 76 insertions, 6 deletions
diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c index cdf352b040a9..11f8942b82dc 100644 --- a/arch/mips/bcm63xx/irq.c +++ b/arch/mips/bcm63xx/irq.c | |||
@@ -20,11 +20,17 @@ | |||
20 | #include <bcm63xx_irq.h> | 20 | #include <bcm63xx_irq.h> |
21 | 21 | ||
22 | static void __dispatch_internal(void) __maybe_unused; | 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; | ||
23 | 28 | ||
24 | #ifndef BCMCPU_RUNTIME_DETECT | 29 | #ifndef BCMCPU_RUNTIME_DETECT |
25 | #ifdef CONFIG_BCM63XX_CPU_6338 | 30 | #ifdef CONFIG_BCM63XX_CPU_6338 |
26 | #define irq_stat_reg PERF_IRQSTAT_6338_REG | 31 | #define irq_stat_reg PERF_IRQSTAT_6338_REG |
27 | #define irq_mask_reg PERF_IRQMASK_6338_REG | 32 | #define irq_mask_reg PERF_IRQMASK_6338_REG |
33 | #define irq_bits 32 | ||
28 | #define is_ext_irq_cascaded 0 | 34 | #define is_ext_irq_cascaded 0 |
29 | #define ext_irq_start 0 | 35 | #define ext_irq_start 0 |
30 | #define ext_irq_end 0 | 36 | #define ext_irq_end 0 |
@@ -32,6 +38,7 @@ static void __dispatch_internal(void) __maybe_unused; | |||
32 | #ifdef CONFIG_BCM63XX_CPU_6345 | 38 | #ifdef CONFIG_BCM63XX_CPU_6345 |
33 | #define irq_stat_reg PERF_IRQSTAT_6345_REG | 39 | #define irq_stat_reg PERF_IRQSTAT_6345_REG |
34 | #define irq_mask_reg PERF_IRQMASK_6345_REG | 40 | #define irq_mask_reg PERF_IRQMASK_6345_REG |
41 | #define irq_bits 32 | ||
35 | #define is_ext_irq_cascaded 0 | 42 | #define is_ext_irq_cascaded 0 |
36 | #define ext_irq_start 0 | 43 | #define ext_irq_start 0 |
37 | #define ext_irq_end 0 | 44 | #define ext_irq_end 0 |
@@ -39,7 +46,7 @@ static void __dispatch_internal(void) __maybe_unused; | |||
39 | #ifdef CONFIG_BCM63XX_CPU_6348 | 46 | #ifdef CONFIG_BCM63XX_CPU_6348 |
40 | #define irq_stat_reg PERF_IRQSTAT_6348_REG | 47 | #define irq_stat_reg PERF_IRQSTAT_6348_REG |
41 | #define irq_mask_reg PERF_IRQMASK_6348_REG | 48 | #define irq_mask_reg PERF_IRQMASK_6348_REG |
42 | #define dispatch_internal __dispatch_internal | 49 | #define irq_bits 32 |
43 | #define is_ext_irq_cascaded 0 | 50 | #define is_ext_irq_cascaded 0 |
44 | #define ext_irq_start 0 | 51 | #define ext_irq_start 0 |
45 | #define ext_irq_end 0 | 52 | #define ext_irq_end 0 |
@@ -47,13 +54,21 @@ static void __dispatch_internal(void) __maybe_unused; | |||
47 | #ifdef CONFIG_BCM63XX_CPU_6358 | 54 | #ifdef CONFIG_BCM63XX_CPU_6358 |
48 | #define irq_stat_reg PERF_IRQSTAT_6358_REG | 55 | #define irq_stat_reg PERF_IRQSTAT_6358_REG |
49 | #define irq_mask_reg PERF_IRQMASK_6358_REG | 56 | #define irq_mask_reg PERF_IRQMASK_6358_REG |
50 | #define dispatch_internal __dispatch_internal | 57 | #define irq_bits 32 |
51 | #define is_ext_irq_cascaded 1 | 58 | #define is_ext_irq_cascaded 1 |
52 | #define ext_irq_start (BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE) | 59 | #define ext_irq_start (BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE) |
53 | #define ext_irq_end (BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE) | 60 | #define ext_irq_end (BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE) |
54 | #endif | 61 | #endif |
55 | 62 | ||
56 | #define dispatch_internal __dispatch_internal | 63 | #if irq_bits == 32 |
64 | #define dispatch_internal __dispatch_internal | ||
65 | #define internal_irq_mask __internal_irq_mask_32 | ||
66 | #define internal_irq_unmask __internal_irq_unmask_32 | ||
67 | #else | ||
68 | #define dispatch_internal __dispatch_internal_64 | ||
69 | #define internal_irq_mask __internal_irq_mask_64 | ||
70 | #define internal_irq_unmask __internal_irq_unmask_64 | ||
71 | #endif | ||
57 | 72 | ||
58 | #define irq_stat_addr (bcm63xx_regset_address(RSET_PERF) + irq_stat_reg) | 73 | #define irq_stat_addr (bcm63xx_regset_address(RSET_PERF) + irq_stat_reg) |
59 | #define irq_mask_addr (bcm63xx_regset_address(RSET_PERF) + irq_mask_reg) | 74 | #define irq_mask_addr (bcm63xx_regset_address(RSET_PERF) + irq_mask_reg) |
@@ -67,9 +82,13 @@ static u32 irq_stat_addr, irq_mask_addr; | |||
67 | static void (*dispatch_internal)(void); | 82 | static void (*dispatch_internal)(void); |
68 | static int is_ext_irq_cascaded; | 83 | static int is_ext_irq_cascaded; |
69 | static unsigned int ext_irq_start, ext_irq_end; | 84 | static unsigned int ext_irq_start, ext_irq_end; |
85 | static void (*internal_irq_mask)(unsigned int irq); | ||
86 | static void (*internal_irq_unmask)(unsigned int irq); | ||
70 | 87 | ||
71 | static void bcm63xx_init_irq(void) | 88 | static void bcm63xx_init_irq(void) |
72 | { | 89 | { |
90 | int irq_bits; | ||
91 | |||
73 | irq_stat_addr = bcm63xx_regset_address(RSET_PERF); | 92 | irq_stat_addr = bcm63xx_regset_address(RSET_PERF); |
74 | irq_mask_addr = bcm63xx_regset_address(RSET_PERF); | 93 | irq_mask_addr = bcm63xx_regset_address(RSET_PERF); |
75 | 94 | ||
@@ -77,18 +96,22 @@ static void bcm63xx_init_irq(void) | |||
77 | case BCM6338_CPU_ID: | 96 | case BCM6338_CPU_ID: |
78 | irq_stat_addr += PERF_IRQSTAT_6338_REG; | 97 | irq_stat_addr += PERF_IRQSTAT_6338_REG; |
79 | irq_mask_addr += PERF_IRQMASK_6338_REG; | 98 | irq_mask_addr += PERF_IRQMASK_6338_REG; |
99 | irq_bits = 32; | ||
80 | break; | 100 | break; |
81 | case BCM6345_CPU_ID: | 101 | case BCM6345_CPU_ID: |
82 | irq_stat_addr += PERF_IRQSTAT_6345_REG; | 102 | irq_stat_addr += PERF_IRQSTAT_6345_REG; |
83 | irq_mask_addr += PERF_IRQMASK_6345_REG; | 103 | irq_mask_addr += PERF_IRQMASK_6345_REG; |
104 | irq_bits = 32; | ||
84 | break; | 105 | break; |
85 | case BCM6348_CPU_ID: | 106 | case BCM6348_CPU_ID: |
86 | irq_stat_addr += PERF_IRQSTAT_6348_REG; | 107 | irq_stat_addr += PERF_IRQSTAT_6348_REG; |
87 | irq_mask_addr += PERF_IRQMASK_6348_REG; | 108 | irq_mask_addr += PERF_IRQMASK_6348_REG; |
109 | irq_bits = 32; | ||
88 | break; | 110 | break; |
89 | case BCM6358_CPU_ID: | 111 | case BCM6358_CPU_ID: |
90 | irq_stat_addr += PERF_IRQSTAT_6358_REG; | 112 | irq_stat_addr += PERF_IRQSTAT_6358_REG; |
91 | irq_mask_addr += PERF_IRQMASK_6358_REG; | 113 | irq_mask_addr += PERF_IRQMASK_6358_REG; |
114 | irq_bits = 32; | ||
92 | is_ext_irq_cascaded = 1; | 115 | is_ext_irq_cascaded = 1; |
93 | ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE; | 116 | ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE; |
94 | ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE; | 117 | ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE; |
@@ -97,7 +120,15 @@ static void bcm63xx_init_irq(void) | |||
97 | BUG(); | 120 | BUG(); |
98 | } | 121 | } |
99 | 122 | ||
100 | dispatch_internal = __dispatch_internal; | 123 | if (irq_bits == 32) { |
124 | dispatch_internal = __dispatch_internal; | ||
125 | internal_irq_mask = __internal_irq_mask_32; | ||
126 | internal_irq_unmask = __internal_irq_unmask_32; | ||
127 | } else { | ||
128 | dispatch_internal = __dispatch_internal_64; | ||
129 | internal_irq_mask = __internal_irq_mask_64; | ||
130 | internal_irq_unmask = __internal_irq_unmask_64; | ||
131 | } | ||
101 | } | 132 | } |
102 | #endif /* ! BCMCPU_RUNTIME_DETECT */ | 133 | #endif /* ! BCMCPU_RUNTIME_DETECT */ |
103 | 134 | ||
@@ -137,6 +168,27 @@ static void __dispatch_internal(void) | |||
137 | } | 168 | } |
138 | } | 169 | } |
139 | 170 | ||
171 | static void __dispatch_internal_64(void) | ||
172 | { | ||
173 | u64 pending; | ||
174 | static int i; | ||
175 | |||
176 | pending = bcm_readq(irq_stat_addr) & bcm_readq(irq_mask_addr); | ||
177 | |||
178 | if (!pending) | ||
179 | return ; | ||
180 | |||
181 | while (1) { | ||
182 | int to_call = i; | ||
183 | |||
184 | i = (i + 1) & 0x3f; | ||
185 | if (pending & (1ull << to_call)) { | ||
186 | handle_internal(to_call); | ||
187 | break; | ||
188 | } | ||
189 | } | ||
190 | } | ||
191 | |||
140 | asmlinkage void plat_irq_dispatch(void) | 192 | asmlinkage void plat_irq_dispatch(void) |
141 | { | 193 | { |
142 | u32 cause; | 194 | u32 cause; |
@@ -168,7 +220,7 @@ asmlinkage void plat_irq_dispatch(void) | |||
168 | * internal IRQs operations: only mask/unmask on PERF irq mask | 220 | * internal IRQs operations: only mask/unmask on PERF irq mask |
169 | * register. | 221 | * register. |
170 | */ | 222 | */ |
171 | static void internal_irq_mask(unsigned int irq) | 223 | static void __internal_irq_mask_32(unsigned int irq) |
172 | { | 224 | { |
173 | u32 mask; | 225 | u32 mask; |
174 | 226 | ||
@@ -177,7 +229,16 @@ static void internal_irq_mask(unsigned int irq) | |||
177 | bcm_writel(mask, irq_mask_addr); | 229 | bcm_writel(mask, irq_mask_addr); |
178 | } | 230 | } |
179 | 231 | ||
180 | static void internal_irq_unmask(unsigned int irq) | 232 | static void __internal_irq_mask_64(unsigned int irq) |
233 | { | ||
234 | u64 mask; | ||
235 | |||
236 | mask = bcm_readq(irq_mask_addr); | ||
237 | mask &= ~(1ull << irq); | ||
238 | bcm_writeq(mask, irq_mask_addr); | ||
239 | } | ||
240 | |||
241 | static void __internal_irq_unmask_32(unsigned int irq) | ||
181 | { | 242 | { |
182 | u32 mask; | 243 | u32 mask; |
183 | 244 | ||
@@ -186,6 +247,15 @@ static void internal_irq_unmask(unsigned int irq) | |||
186 | bcm_writel(mask, irq_mask_addr); | 247 | bcm_writel(mask, irq_mask_addr); |
187 | } | 248 | } |
188 | 249 | ||
250 | static void __internal_irq_unmask_64(unsigned int irq) | ||
251 | { | ||
252 | u64 mask; | ||
253 | |||
254 | mask = bcm_readq(irq_mask_addr); | ||
255 | mask |= (1ull << irq); | ||
256 | bcm_writeq(mask, irq_mask_addr); | ||
257 | } | ||
258 | |||
189 | static void bcm63xx_internal_irq_mask(struct irq_data *d) | 259 | static void bcm63xx_internal_irq_mask(struct irq_data *d) |
190 | { | 260 | { |
191 | internal_irq_mask(d->irq - IRQ_INTERNAL_BASE); | 261 | internal_irq_mask(d->irq - IRQ_INTERNAL_BASE); |