summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/TWL4030-09.patch
diff options
context:
space:
mode:
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.patch341
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 @@
1TWL4030: convert early interrupt mask/clear funcs to use array
2
3From: Paul Walmsley <paul@pwsan.com>
4
5Mask/clear TWL module IMRs/ISRs by iterating through arrays rather than
6using a block of cut-and-pasted commands. Removes 1056 bytes of bloat.
7
8Signed-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
14diff --git a/drivers/i2c/chips/twl4030-core.c b/drivers/i2c/chips/twl4030-core.c
15index 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++) {