diff options
Diffstat (limited to 'meta/recipes-kernel/linux/linux-omap2-git/beagleboard/TWL4030-09.patch')
-rw-r--r-- | meta/recipes-kernel/linux/linux-omap2-git/beagleboard/TWL4030-09.patch | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/TWL4030-09.patch b/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/TWL4030-09.patch new file mode 100644 index 0000000000..ab6cc6d87b --- /dev/null +++ b/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/TWL4030-09.patch | |||
@@ -0,0 +1,341 @@ | |||
1 | TWL4030: convert early interrupt mask/clear funcs to use array | ||
2 | |||
3 | From: Paul Walmsley <paul@pwsan.com> | ||
4 | |||
5 | Mask/clear TWL module IMRs/ISRs by iterating through arrays rather than | ||
6 | using a block of cut-and-pasted commands. Removes 1056 bytes of bloat. | ||
7 | |||
8 | Signed-off-by: Paul Walmsley <paul@pwsan.com> | ||
9 | --- | ||
10 | |||
11 | drivers/i2c/chips/twl4030-core.c | 302 +++++++++++++++++++++++--------------- | ||
12 | 1 files changed, 180 insertions(+), 122 deletions(-) | ||
13 | |||
14 | diff --git a/drivers/i2c/chips/twl4030-core.c b/drivers/i2c/chips/twl4030-core.c | ||
15 | index 38c227a..776b1dd 100644 | ||
16 | --- a/drivers/i2c/chips/twl4030-core.c | ||
17 | +++ b/drivers/i2c/chips/twl4030-core.c | ||
18 | @@ -160,6 +160,136 @@ | ||
19 | |||
20 | #define TWL4030_SIH_CTRL_COR_MASK (1 << 2) | ||
21 | |||
22 | +/** | ||
23 | + * struct twl4030_mod_iregs - TWL module IMR/ISR regs to mask/clear at init | ||
24 | + * @mod_no: TWL4030 module number (e.g., TWL4030_MODULE_GPIO) | ||
25 | + * @sih_ctrl: address of module SIH_CTRL register | ||
26 | + * @reg_cnt: number of IMR/ISR regs | ||
27 | + * @imrs: pointer to array of TWL module interrupt mask register indices | ||
28 | + * @isrs: pointer to array of TWL module interrupt status register indices | ||
29 | + * | ||
30 | + * Ties together TWL4030 modules and lists of IMR/ISR registers to mask/clear | ||
31 | + * during twl_init_irq(). | ||
32 | + */ | ||
33 | +struct twl4030_mod_iregs { | ||
34 | + const u8 mod_no; | ||
35 | + const u8 sih_ctrl; | ||
36 | + const u8 reg_cnt; | ||
37 | + const u8 *imrs; | ||
38 | + const u8 *isrs; | ||
39 | +}; | ||
40 | + | ||
41 | +/* TWL4030 INT module interrupt mask registers */ | ||
42 | +static const u8 __initconst twl4030_int_imr_regs[] = { | ||
43 | + TWL4030_INT_PWR_IMR1, | ||
44 | + TWL4030_INT_PWR_IMR2, | ||
45 | +}; | ||
46 | + | ||
47 | +/* TWL4030 INT module interrupt status registers */ | ||
48 | +static const u8 __initconst twl4030_int_isr_regs[] = { | ||
49 | + TWL4030_INT_PWR_ISR1, | ||
50 | + TWL4030_INT_PWR_ISR2, | ||
51 | +}; | ||
52 | + | ||
53 | +/* TWL4030 INTERRUPTS module interrupt mask registers */ | ||
54 | +static const u8 __initconst twl4030_interrupts_imr_regs[] = { | ||
55 | + TWL4030_INTERRUPTS_BCIIMR1A, | ||
56 | + TWL4030_INTERRUPTS_BCIIMR1B, | ||
57 | + TWL4030_INTERRUPTS_BCIIMR2A, | ||
58 | + TWL4030_INTERRUPTS_BCIIMR2B, | ||
59 | +}; | ||
60 | + | ||
61 | +/* TWL4030 INTERRUPTS module interrupt status registers */ | ||
62 | +static const u8 __initconst twl4030_interrupts_isr_regs[] = { | ||
63 | + TWL4030_INTERRUPTS_BCIISR1A, | ||
64 | + TWL4030_INTERRUPTS_BCIISR1B, | ||
65 | + TWL4030_INTERRUPTS_BCIISR2A, | ||
66 | + TWL4030_INTERRUPTS_BCIISR2B, | ||
67 | +}; | ||
68 | + | ||
69 | +/* TWL4030 MADC module interrupt mask registers */ | ||
70 | +static const u8 __initconst twl4030_madc_imr_regs[] = { | ||
71 | + TWL4030_MADC_IMR1, | ||
72 | + TWL4030_MADC_IMR2, | ||
73 | +}; | ||
74 | + | ||
75 | +/* TWL4030 MADC module interrupt status registers */ | ||
76 | +static const u8 __initconst twl4030_madc_isr_regs[] = { | ||
77 | + TWL4030_MADC_ISR1, | ||
78 | + TWL4030_MADC_ISR2, | ||
79 | +}; | ||
80 | + | ||
81 | +/* TWL4030 keypad module interrupt mask registers */ | ||
82 | +static const u8 __initconst twl4030_keypad_imr_regs[] = { | ||
83 | + TWL4030_KEYPAD_KEYP_IMR1, | ||
84 | + TWL4030_KEYPAD_KEYP_IMR2, | ||
85 | +}; | ||
86 | + | ||
87 | +/* TWL4030 keypad module interrupt status registers */ | ||
88 | +static const u8 __initconst twl4030_keypad_isr_regs[] = { | ||
89 | + TWL4030_KEYPAD_KEYP_ISR1, | ||
90 | + TWL4030_KEYPAD_KEYP_ISR2, | ||
91 | +}; | ||
92 | + | ||
93 | +/* TWL4030 GPIO module interrupt mask registers */ | ||
94 | +static const u8 __initconst twl4030_gpio_imr_regs[] = { | ||
95 | + REG_GPIO_IMR1A, | ||
96 | + REG_GPIO_IMR1B, | ||
97 | + REG_GPIO_IMR2A, | ||
98 | + REG_GPIO_IMR2B, | ||
99 | + REG_GPIO_IMR3A, | ||
100 | + REG_GPIO_IMR3B, | ||
101 | +}; | ||
102 | + | ||
103 | +/* TWL4030 GPIO module interrupt status registers */ | ||
104 | +static const u8 __initconst twl4030_gpio_isr_regs[] = { | ||
105 | + REG_GPIO_ISR1A, | ||
106 | + REG_GPIO_ISR1B, | ||
107 | + REG_GPIO_ISR2A, | ||
108 | + REG_GPIO_ISR2B, | ||
109 | + REG_GPIO_ISR3A, | ||
110 | + REG_GPIO_ISR3B, | ||
111 | +}; | ||
112 | + | ||
113 | +/* TWL4030 modules that have IMR/ISR registers that must be masked/cleared */ | ||
114 | +static const struct twl4030_mod_iregs __initconst twl4030_mod_regs[] = { | ||
115 | + { | ||
116 | + .mod_no = TWL4030_MODULE_INT, | ||
117 | + .sih_ctrl = TWL4030_INT_PWR_SIH_CTRL, | ||
118 | + .reg_cnt = ARRAY_SIZE(twl4030_int_imr_regs), | ||
119 | + .imrs = twl4030_int_imr_regs, | ||
120 | + .isrs = twl4030_int_isr_regs, | ||
121 | + }, | ||
122 | + { | ||
123 | + .mod_no = TWL4030_MODULE_INTERRUPTS, | ||
124 | + .sih_ctrl = TWL4030_INTERRUPTS_BCISIHCTRL, | ||
125 | + .reg_cnt = ARRAY_SIZE(twl4030_interrupts_imr_regs), | ||
126 | + .imrs = twl4030_interrupts_imr_regs, | ||
127 | + .isrs = twl4030_interrupts_isr_regs, | ||
128 | + }, | ||
129 | + { | ||
130 | + .mod_no = TWL4030_MODULE_MADC, | ||
131 | + .sih_ctrl = TWL4030_MADC_MADC_SIH_CTRL, | ||
132 | + .reg_cnt = ARRAY_SIZE(twl4030_madc_imr_regs), | ||
133 | + .imrs = twl4030_madc_imr_regs, | ||
134 | + .isrs = twl4030_madc_isr_regs, | ||
135 | + }, | ||
136 | + { | ||
137 | + .mod_no = TWL4030_MODULE_KEYPAD, | ||
138 | + .sih_ctrl = TWL4030_KEYPAD_KEYP_SIH_CTRL, | ||
139 | + .reg_cnt = ARRAY_SIZE(twl4030_keypad_imr_regs), | ||
140 | + .imrs = twl4030_keypad_imr_regs, | ||
141 | + .isrs = twl4030_keypad_isr_regs, | ||
142 | + }, | ||
143 | + { | ||
144 | + .mod_no = TWL4030_MODULE_GPIO, | ||
145 | + .sih_ctrl = REG_GPIO_SIH_CTRL, | ||
146 | + .reg_cnt = ARRAY_SIZE(twl4030_gpio_imr_regs), | ||
147 | + .imrs = twl4030_gpio_imr_regs, | ||
148 | + .isrs = twl4030_gpio_isr_regs, | ||
149 | + }, | ||
150 | +}; | ||
151 | + | ||
152 | |||
153 | /* Helper functions */ | ||
154 | static int | ||
155 | @@ -779,136 +909,64 @@ static int twl4030_read_cor_bit(u8 mod_no, u8 reg) | ||
156 | return tmp; | ||
157 | } | ||
158 | |||
159 | +/** | ||
160 | + * twl4030_mask_clear_intrs - mask and clear all TWL4030 interrupts | ||
161 | + * @t: pointer to twl4030_mod_iregs array | ||
162 | + * @t_sz: ARRAY_SIZE(t) (starting at 1) | ||
163 | + * | ||
164 | + * Mask all TWL4030 interrupt mask registers (IMRs) and clear all | ||
165 | + * interrupt status registers (ISRs). No return value, but will WARN if | ||
166 | + * any I2C operations fail. | ||
167 | + */ | ||
168 | +static void __init twl4030_mask_clear_intrs(const struct twl4030_mod_iregs *t, | ||
169 | + const u8 t_sz) | ||
170 | +{ | ||
171 | + int i, j; | ||
172 | + | ||
173 | + /* | ||
174 | + * N.B. - further efficiency is possible here. Eight I2C | ||
175 | + * operations on BCI and GPIO modules are avoidable if I2C | ||
176 | + * burst read/write transactions were implemented. Would | ||
177 | + * probably save about 1ms of boot time and a small amount of | ||
178 | + * power. | ||
179 | + */ | ||
180 | + for (i = 0; i < t_sz; i++) { | ||
181 | + const struct twl4030_mod_iregs tmr = t[i]; | ||
182 | + | ||
183 | + for (j = 0; j < tmr.reg_cnt; j++) { | ||
184 | + int cor; | ||
185 | + | ||
186 | + /* Mask interrupts at the TWL4030 */ | ||
187 | + WARN_ON(twl4030_i2c_write_u8(tmr.mod_no, 0xff, | ||
188 | + tmr.imrs[j]) < 0); | ||
189 | + | ||
190 | + /* Are ISRs cleared by reads or writes? */ | ||
191 | + cor = twl4030_read_cor_bit(tmr.mod_no, tmr.sih_ctrl); | ||
192 | + WARN_ON(cor < 0); | ||
193 | + | ||
194 | + /* Clear TWL4030 ISRs */ | ||
195 | + WARN_ON(twl4030_i2c_clear_isr(tmr.mod_no, | ||
196 | + tmr.isrs[j], cor) < 0); | ||
197 | + } | ||
198 | + } | ||
199 | + | ||
200 | + return; | ||
201 | +} | ||
202 | + | ||
203 | + | ||
204 | static void twl_init_irq(void) | ||
205 | { | ||
206 | - int i = 0; | ||
207 | + int i; | ||
208 | int res = 0; | ||
209 | - int cor; | ||
210 | char *msg = "Unable to register interrupt subsystem"; | ||
211 | unsigned int irq_num; | ||
212 | |||
213 | /* | ||
214 | - * For each TWL4030 module with ISR/IMR registers, mask all | ||
215 | - * interrupts and then clear any existing interrupt status bits, | ||
216 | - * since we initially do not have any TWL4030 module interrupt | ||
217 | - * handlers present. | ||
218 | + * Mask and clear all TWL4030 interrupts since initially we do | ||
219 | + * not have any TWL4030 module interrupt handlers present | ||
220 | */ | ||
221 | - | ||
222 | - /* Mask INT (PWR) interrupts at TWL4030 */ | ||
223 | - WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xff, | ||
224 | - TWL4030_INT_PWR_IMR1) < 0); | ||
225 | - WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xff, | ||
226 | - TWL4030_INT_PWR_IMR2) < 0); | ||
227 | - | ||
228 | - /* Are PWR interrupt status bits cleared by reads or writes? */ | ||
229 | - cor = twl4030_read_cor_bit(TWL4030_MODULE_INT, | ||
230 | - TWL4030_INT_PWR_SIH_CTRL); | ||
231 | - WARN_ON(cor < 0); | ||
232 | - | ||
233 | - /* Clear TWL4030 INT (PWR) ISRs */ | ||
234 | - WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_INT, | ||
235 | - TWL4030_INT_PWR_ISR1, cor) < 0); | ||
236 | - WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_INT, | ||
237 | - TWL4030_INT_PWR_ISR2, cor) < 0); | ||
238 | - | ||
239 | - /* Slave address 0x4A */ | ||
240 | - | ||
241 | - /* Mask BCI interrupts at TWL4030 */ | ||
242 | - WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, | ||
243 | - TWL4030_INTERRUPTS_BCIIMR1A) < 0); | ||
244 | - WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, | ||
245 | - TWL4030_INTERRUPTS_BCIIMR2A) < 0); | ||
246 | - WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, | ||
247 | - TWL4030_INTERRUPTS_BCIIMR1B) < 0); | ||
248 | - WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, | ||
249 | - TWL4030_INTERRUPTS_BCIIMR2B) < 0); | ||
250 | - | ||
251 | - /* Are BCI interrupt status bits cleared by reads or writes? */ | ||
252 | - cor = twl4030_read_cor_bit(TWL4030_MODULE_INTERRUPTS, | ||
253 | - TWL4030_INTERRUPTS_BCISIHCTRL); | ||
254 | - WARN_ON(cor < 0); | ||
255 | - | ||
256 | - /* Clear TWL4030 BCI ISRs */ | ||
257 | - WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_INTERRUPTS, | ||
258 | - TWL4030_INTERRUPTS_BCIISR1A, cor) < 0); | ||
259 | - WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_INTERRUPTS, | ||
260 | - TWL4030_INTERRUPTS_BCIISR2A, cor) < 0); | ||
261 | - WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_INTERRUPTS, | ||
262 | - TWL4030_INTERRUPTS_BCIISR1B, cor) < 0); | ||
263 | - WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_INTERRUPTS, | ||
264 | - TWL4030_INTERRUPTS_BCIISR2B, cor) < 0); | ||
265 | - | ||
266 | - /* MAD C */ | ||
267 | - /* Mask MADC interrupts at TWL4030 */ | ||
268 | - WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_MADC, 0xff, | ||
269 | - TWL4030_MADC_IMR1) < 0); | ||
270 | - WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_MADC, 0xff, | ||
271 | - TWL4030_MADC_IMR2) < 0); | ||
272 | - | ||
273 | - /* Are MADC interrupt status bits cleared by reads or writes? */ | ||
274 | - cor = twl4030_read_cor_bit(TWL4030_MODULE_MADC, | ||
275 | - TWL4030_MADC_MADC_SIH_CTRL); | ||
276 | - WARN_ON(cor < 0); | ||
277 | - | ||
278 | - /* Clear TWL4030 MADC ISRs */ | ||
279 | - WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_MADC, | ||
280 | - TWL4030_MADC_ISR1, cor) < 0); | ||
281 | - WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_MADC, | ||
282 | - TWL4030_MADC_ISR2, cor) < 0); | ||
283 | - | ||
284 | - /* key Pad */ | ||
285 | - /* Mask keypad interrupts at TWL4030 */ | ||
286 | - WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_KEYPAD, 0xff, | ||
287 | - TWL4030_KEYPAD_KEYP_IMR1) < 0); | ||
288 | - WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_KEYPAD, 0xff, | ||
289 | - TWL4030_KEYPAD_KEYP_IMR2) < 0); | ||
290 | - | ||
291 | - /* Are keypad interrupt status bits cleared by reads or writes? */ | ||
292 | - cor = twl4030_read_cor_bit(TWL4030_MODULE_KEYPAD, | ||
293 | - TWL4030_KEYPAD_KEYP_SIH_CTRL); | ||
294 | - WARN_ON(cor < 0); | ||
295 | - | ||
296 | - /* Clear TWL4030 keypad ISRs */ | ||
297 | - /* XXX does this still need to be done twice for some reason? */ | ||
298 | - WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_KEYPAD, | ||
299 | - TWL4030_KEYPAD_KEYP_ISR1, cor) < 0); | ||
300 | - WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_KEYPAD, | ||
301 | - TWL4030_KEYPAD_KEYP_ISR2, cor) < 0); | ||
302 | - | ||
303 | - /* Slave address 0x49 */ | ||
304 | - | ||
305 | - /* Mask GPIO interrupts at TWL4030 */ | ||
306 | - WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xff, | ||
307 | - REG_GPIO_IMR1A) < 0); | ||
308 | - WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xff, | ||
309 | - REG_GPIO_IMR2A) < 0); | ||
310 | - WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xff, | ||
311 | - REG_GPIO_IMR3A) < 0); | ||
312 | - WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xff, | ||
313 | - REG_GPIO_IMR1B) < 0); | ||
314 | - WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xff, | ||
315 | - REG_GPIO_IMR2B) < 0); | ||
316 | - WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xff, | ||
317 | - REG_GPIO_IMR3B) < 0); | ||
318 | - | ||
319 | - /* Are GPIO interrupt status bits cleared by reads or writes? */ | ||
320 | - cor = twl4030_read_cor_bit(TWL4030_MODULE_GPIO, | ||
321 | - REG_GPIO_SIH_CTRL); | ||
322 | - WARN_ON(cor < 0); | ||
323 | - | ||
324 | - /* Clear TWL4030 GPIO ISRs */ | ||
325 | - WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_GPIO, REG_GPIO_ISR1A, | ||
326 | - cor) < 0); | ||
327 | - WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_GPIO, REG_GPIO_ISR2A, | ||
328 | - cor) < 0); | ||
329 | - WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_GPIO, REG_GPIO_ISR3A, | ||
330 | - cor) < 0); | ||
331 | - WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_GPIO, REG_GPIO_ISR1B, | ||
332 | - cor) < 0); | ||
333 | - WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_GPIO, REG_GPIO_ISR2B, | ||
334 | - cor) < 0); | ||
335 | - WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_GPIO, REG_GPIO_ISR3B, | ||
336 | - cor) < 0); | ||
337 | + twl4030_mask_clear_intrs(twl4030_mod_regs, | ||
338 | + ARRAY_SIZE(twl4030_mod_regs)); | ||
339 | |||
340 | /* install an irq handler for each of the PIH modules */ | ||
341 | for (i = TWL4030_IRQ_BASE; i < TWL4030_IRQ_END; i++) { | ||