brcm63xx: add preliminary support for 3.13
[openwrt/svn-archive/archive.git] / target / linux / brcm63xx / patches-3.13 / 320-MIPS-BCM63XX-replace-irq-dispatch-code-with-a-generi.patch
1 From 01bf26c51b427e24ac69f604d33f7d9360a9e470 Mon Sep 17 00:00:00 2001
2 From: Jonas Gorski <jogo@openwrt.org>
3 Date: Thu, 18 Apr 2013 21:14:49 +0200
4 Subject: [PATCH 31/53] MIPS: BCM63XX: replace irq dispatch code with a generic
5 version
6
7 The generic version uses a variable length of u32 registers of u32/u64.
8 This allows easier support for longer registers without having to rewrite
9 verything.
10
11 This "generic" version is not slower than the old version in the best case
12 (= i == next set bit), and twice as fast in the worst case in 64 bits.
13
14 Signed-off-by: Jonas Gorski <jogo@openwrt.org>
15 ---
16 arch/mips/bcm63xx/irq.c | 130 +++++++++++++++++++++---------------------------
17 1 file changed, 56 insertions(+), 74 deletions(-)
18
19 --- a/arch/mips/bcm63xx/irq.c
20 +++ b/arch/mips/bcm63xx/irq.c
21 @@ -51,47 +51,65 @@ static inline void handle_internal(int i
22 * will resume the loop where it ended the last time we left this
23 * function.
24 */
25 -static void __dispatch_internal_32(void)
26 -{
27 - u32 pending;
28 - static int i;
29 -
30 - pending = bcm_readl(irq_stat_addr) & bcm_readl(irq_mask_addr);
31 -
32 - if (!pending)
33 - return ;
34 -
35 - while (1) {
36 - int to_call = i;
37
38 - i = (i + 1) & 0x1f;
39 - if (pending & (1 << to_call)) {
40 - handle_internal(to_call);
41 - break;
42 - }
43 - }
44 +#define BUILD_IPIC_INTERNAL(width) \
45 +void __dispatch_internal_##width(void) \
46 +{ \
47 + u32 pending[width / 32]; \
48 + unsigned int src, tgt; \
49 + bool irqs_pending = false; \
50 + static int i; \
51 + \
52 + /* read registers in reverse order */ \
53 + for (src = 0, tgt = (width / 32); src < (width / 32); src++) { \
54 + u32 val; \
55 + \
56 + val = bcm_readl(irq_stat_addr + src * sizeof(u32)); \
57 + val &= bcm_readl(irq_mask_addr + src * sizeof(u32)); \
58 + pending[--tgt] = val; \
59 + \
60 + if (val) \
61 + irqs_pending = true; \
62 + } \
63 + \
64 + if (!irqs_pending) \
65 + return; \
66 + \
67 + while (1) { \
68 + int to_call = i; \
69 + \
70 + i = (i + 1) & (width - 1); \
71 + if (pending[to_call / 32] & (1 << (to_call & 0x1f))) { \
72 + handle_internal(to_call); \
73 + break; \
74 + } \
75 + } \
76 +} \
77 + \
78 +static void __internal_irq_mask_##width(unsigned int irq) \
79 +{ \
80 + u32 val; \
81 + unsigned reg = (irq / 32) ^ (width/32 - 1); \
82 + unsigned bit = irq & 0x1f; \
83 + \
84 + val = bcm_readl(irq_mask_addr + reg * sizeof(u32)); \
85 + val &= ~(1 << bit); \
86 + bcm_writel(val, irq_mask_addr + reg * sizeof(u32)); \
87 +} \
88 + \
89 +static void __internal_irq_unmask_##width(unsigned int irq) \
90 +{ \
91 + u32 val; \
92 + unsigned reg = (irq / 32) ^ (width/32 - 1); \
93 + unsigned bit = irq & 0x1f; \
94 + \
95 + val = bcm_readl(irq_mask_addr + reg * sizeof(u32)); \
96 + val |= (1 << bit); \
97 + bcm_writel(val, irq_mask_addr + reg * sizeof(u32)); \
98 }
99
100 -static void __dispatch_internal_64(void)
101 -{
102 - u64 pending;
103 - static int i;
104 -
105 - pending = bcm_readq(irq_stat_addr) & bcm_readq(irq_mask_addr);
106 -
107 - if (!pending)
108 - return ;
109 -
110 - while (1) {
111 - int to_call = i;
112 -
113 - i = (i + 1) & 0x3f;
114 - if (pending & (1ull << to_call)) {
115 - handle_internal(to_call);
116 - break;
117 - }
118 - }
119 -}
120 +BUILD_IPIC_INTERNAL(32);
121 +BUILD_IPIC_INTERNAL(64);
122
123 asmlinkage void plat_irq_dispatch(void)
124 {
125 @@ -128,42 +146,6 @@ asmlinkage void plat_irq_dispatch(void)
126 * internal IRQs operations: only mask/unmask on PERF irq mask
127 * register.
128 */
129 -static void __internal_irq_mask_32(unsigned int irq)
130 -{
131 - u32 mask;
132 -
133 - mask = bcm_readl(irq_mask_addr);
134 - mask &= ~(1 << irq);
135 - bcm_writel(mask, irq_mask_addr);
136 -}
137 -
138 -static void __internal_irq_mask_64(unsigned int irq)
139 -{
140 - u64 mask;
141 -
142 - mask = bcm_readq(irq_mask_addr);
143 - mask &= ~(1ull << irq);
144 - bcm_writeq(mask, irq_mask_addr);
145 -}
146 -
147 -static void __internal_irq_unmask_32(unsigned int irq)
148 -{
149 - u32 mask;
150 -
151 - mask = bcm_readl(irq_mask_addr);
152 - mask |= (1 << irq);
153 - bcm_writel(mask, irq_mask_addr);
154 -}
155 -
156 -static void __internal_irq_unmask_64(unsigned int irq)
157 -{
158 - u64 mask;
159 -
160 - mask = bcm_readq(irq_mask_addr);
161 - mask |= (1ull << irq);
162 - bcm_writeq(mask, irq_mask_addr);
163 -}
164 -
165 static void bcm63xx_internal_irq_mask(struct irq_data *d)
166 {
167 internal_irq_mask(d->irq - IRQ_INTERNAL_BASE);