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 @@ +TWL4030: convert early interrupt mask/clear funcs to use array + +From: Paul Walmsley <paul@pwsan.com> + +Mask/clear TWL module IMRs/ISRs by iterating through arrays rather than +using a block of cut-and-pasted commands. Removes 1056 bytes of bloat. + +Signed-off-by: Paul Walmsley <paul@pwsan.com> +--- + + drivers/i2c/chips/twl4030-core.c | 302 +++++++++++++++++++++++--------------- + 1 files changed, 180 insertions(+), 122 deletions(-) + +diff --git a/drivers/i2c/chips/twl4030-core.c b/drivers/i2c/chips/twl4030-core.c +index 38c227a..776b1dd 100644 +--- a/drivers/i2c/chips/twl4030-core.c ++++ b/drivers/i2c/chips/twl4030-core.c +@@ -160,6 +160,136 @@ + + #define TWL4030_SIH_CTRL_COR_MASK (1 << 2) + ++/** ++ * struct twl4030_mod_iregs - TWL module IMR/ISR regs to mask/clear at init ++ * @mod_no: TWL4030 module number (e.g., TWL4030_MODULE_GPIO) ++ * @sih_ctrl: address of module SIH_CTRL register ++ * @reg_cnt: number of IMR/ISR regs ++ * @imrs: pointer to array of TWL module interrupt mask register indices ++ * @isrs: pointer to array of TWL module interrupt status register indices ++ * ++ * Ties together TWL4030 modules and lists of IMR/ISR registers to mask/clear ++ * during twl_init_irq(). ++ */ ++struct twl4030_mod_iregs { ++ const u8 mod_no; ++ const u8 sih_ctrl; ++ const u8 reg_cnt; ++ const u8 *imrs; ++ const u8 *isrs; ++}; ++ ++/* TWL4030 INT module interrupt mask registers */ ++static const u8 __initconst twl4030_int_imr_regs[] = { ++ TWL4030_INT_PWR_IMR1, ++ TWL4030_INT_PWR_IMR2, ++}; ++ ++/* TWL4030 INT module interrupt status registers */ ++static const u8 __initconst twl4030_int_isr_regs[] = { ++ TWL4030_INT_PWR_ISR1, ++ TWL4030_INT_PWR_ISR2, ++}; ++ ++/* TWL4030 INTERRUPTS module interrupt mask registers */ ++static const u8 __initconst twl4030_interrupts_imr_regs[] = { ++ TWL4030_INTERRUPTS_BCIIMR1A, ++ TWL4030_INTERRUPTS_BCIIMR1B, ++ TWL4030_INTERRUPTS_BCIIMR2A, ++ TWL4030_INTERRUPTS_BCIIMR2B, ++}; ++ ++/* TWL4030 INTERRUPTS module interrupt status registers */ ++static const u8 __initconst twl4030_interrupts_isr_regs[] = { ++ TWL4030_INTERRUPTS_BCIISR1A, ++ TWL4030_INTERRUPTS_BCIISR1B, ++ TWL4030_INTERRUPTS_BCIISR2A, ++ TWL4030_INTERRUPTS_BCIISR2B, ++}; ++ ++/* TWL4030 MADC module interrupt mask registers */ ++static const u8 __initconst twl4030_madc_imr_regs[] = { ++ TWL4030_MADC_IMR1, ++ TWL4030_MADC_IMR2, ++}; ++ ++/* TWL4030 MADC module interrupt status registers */ ++static const u8 __initconst twl4030_madc_isr_regs[] = { ++ TWL4030_MADC_ISR1, ++ TWL4030_MADC_ISR2, ++}; ++ ++/* TWL4030 keypad module interrupt mask registers */ ++static const u8 __initconst twl4030_keypad_imr_regs[] = { ++ TWL4030_KEYPAD_KEYP_IMR1, ++ TWL4030_KEYPAD_KEYP_IMR2, ++}; ++ ++/* TWL4030 keypad module interrupt status registers */ ++static const u8 __initconst twl4030_keypad_isr_regs[] = { ++ TWL4030_KEYPAD_KEYP_ISR1, ++ TWL4030_KEYPAD_KEYP_ISR2, ++}; ++ ++/* TWL4030 GPIO module interrupt mask registers */ ++static const u8 __initconst twl4030_gpio_imr_regs[] = { ++ REG_GPIO_IMR1A, ++ REG_GPIO_IMR1B, ++ REG_GPIO_IMR2A, ++ REG_GPIO_IMR2B, ++ REG_GPIO_IMR3A, ++ REG_GPIO_IMR3B, ++}; ++ ++/* TWL4030 GPIO module interrupt status registers */ ++static const u8 __initconst twl4030_gpio_isr_regs[] = { ++ REG_GPIO_ISR1A, ++ REG_GPIO_ISR1B, ++ REG_GPIO_ISR2A, ++ REG_GPIO_ISR2B, ++ REG_GPIO_ISR3A, ++ REG_GPIO_ISR3B, ++}; ++ ++/* TWL4030 modules that have IMR/ISR registers that must be masked/cleared */ ++static const struct twl4030_mod_iregs __initconst twl4030_mod_regs[] = { ++ { ++ .mod_no = TWL4030_MODULE_INT, ++ .sih_ctrl = TWL4030_INT_PWR_SIH_CTRL, ++ .reg_cnt = ARRAY_SIZE(twl4030_int_imr_regs), ++ .imrs = twl4030_int_imr_regs, ++ .isrs = twl4030_int_isr_regs, ++ }, ++ { ++ .mod_no = TWL4030_MODULE_INTERRUPTS, ++ .sih_ctrl = TWL4030_INTERRUPTS_BCISIHCTRL, ++ .reg_cnt = ARRAY_SIZE(twl4030_interrupts_imr_regs), ++ .imrs = twl4030_interrupts_imr_regs, ++ .isrs = twl4030_interrupts_isr_regs, ++ }, ++ { ++ .mod_no = TWL4030_MODULE_MADC, ++ .sih_ctrl = TWL4030_MADC_MADC_SIH_CTRL, ++ .reg_cnt = ARRAY_SIZE(twl4030_madc_imr_regs), ++ .imrs = twl4030_madc_imr_regs, ++ .isrs = twl4030_madc_isr_regs, ++ }, ++ { ++ .mod_no = TWL4030_MODULE_KEYPAD, ++ .sih_ctrl = TWL4030_KEYPAD_KEYP_SIH_CTRL, ++ .reg_cnt = ARRAY_SIZE(twl4030_keypad_imr_regs), ++ .imrs = twl4030_keypad_imr_regs, ++ .isrs = twl4030_keypad_isr_regs, ++ }, ++ { ++ .mod_no = TWL4030_MODULE_GPIO, ++ .sih_ctrl = REG_GPIO_SIH_CTRL, ++ .reg_cnt = ARRAY_SIZE(twl4030_gpio_imr_regs), ++ .imrs = twl4030_gpio_imr_regs, ++ .isrs = twl4030_gpio_isr_regs, ++ }, ++}; ++ + + /* Helper functions */ + static int +@@ -779,136 +909,64 @@ static int twl4030_read_cor_bit(u8 mod_no, u8 reg) + return tmp; + } + ++/** ++ * twl4030_mask_clear_intrs - mask and clear all TWL4030 interrupts ++ * @t: pointer to twl4030_mod_iregs array ++ * @t_sz: ARRAY_SIZE(t) (starting at 1) ++ * ++ * Mask all TWL4030 interrupt mask registers (IMRs) and clear all ++ * interrupt status registers (ISRs). No return value, but will WARN if ++ * any I2C operations fail. ++ */ ++static void __init twl4030_mask_clear_intrs(const struct twl4030_mod_iregs *t, ++ const u8 t_sz) ++{ ++ int i, j; ++ ++ /* ++ * N.B. - further efficiency is possible here. Eight I2C ++ * operations on BCI and GPIO modules are avoidable if I2C ++ * burst read/write transactions were implemented. Would ++ * probably save about 1ms of boot time and a small amount of ++ * power. ++ */ ++ for (i = 0; i < t_sz; i++) { ++ const struct twl4030_mod_iregs tmr = t[i]; ++ ++ for (j = 0; j < tmr.reg_cnt; j++) { ++ int cor; ++ ++ /* Mask interrupts at the TWL4030 */ ++ WARN_ON(twl4030_i2c_write_u8(tmr.mod_no, 0xff, ++ tmr.imrs[j]) < 0); ++ ++ /* Are ISRs cleared by reads or writes? */ ++ cor = twl4030_read_cor_bit(tmr.mod_no, tmr.sih_ctrl); ++ WARN_ON(cor < 0); ++ ++ /* Clear TWL4030 ISRs */ ++ WARN_ON(twl4030_i2c_clear_isr(tmr.mod_no, ++ tmr.isrs[j], cor) < 0); ++ } ++ } ++ ++ return; ++} ++ ++ + static void twl_init_irq(void) + { +- int i = 0; ++ int i; + int res = 0; +- int cor; + char *msg = "Unable to register interrupt subsystem"; + unsigned int irq_num; + + /* +- * For each TWL4030 module with ISR/IMR registers, mask all +- * interrupts and then clear any existing interrupt status bits, +- * since we initially do not have any TWL4030 module interrupt +- * handlers present. ++ * Mask and clear all TWL4030 interrupts since initially we do ++ * not have any TWL4030 module interrupt handlers present + */ +- +- /* Mask INT (PWR) interrupts at TWL4030 */ +- WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xff, +- TWL4030_INT_PWR_IMR1) < 0); +- WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xff, +- TWL4030_INT_PWR_IMR2) < 0); +- +- /* Are PWR interrupt status bits cleared by reads or writes? */ +- cor = twl4030_read_cor_bit(TWL4030_MODULE_INT, +- TWL4030_INT_PWR_SIH_CTRL); +- WARN_ON(cor < 0); +- +- /* Clear TWL4030 INT (PWR) ISRs */ +- WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_INT, +- TWL4030_INT_PWR_ISR1, cor) < 0); +- WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_INT, +- TWL4030_INT_PWR_ISR2, cor) < 0); +- +- /* Slave address 0x4A */ +- +- /* Mask BCI interrupts at TWL4030 */ +- WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, +- TWL4030_INTERRUPTS_BCIIMR1A) < 0); +- WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, +- TWL4030_INTERRUPTS_BCIIMR2A) < 0); +- WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, +- TWL4030_INTERRUPTS_BCIIMR1B) < 0); +- WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, +- TWL4030_INTERRUPTS_BCIIMR2B) < 0); +- +- /* Are BCI interrupt status bits cleared by reads or writes? */ +- cor = twl4030_read_cor_bit(TWL4030_MODULE_INTERRUPTS, +- TWL4030_INTERRUPTS_BCISIHCTRL); +- WARN_ON(cor < 0); +- +- /* Clear TWL4030 BCI ISRs */ +- WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_INTERRUPTS, +- TWL4030_INTERRUPTS_BCIISR1A, cor) < 0); +- WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_INTERRUPTS, +- TWL4030_INTERRUPTS_BCIISR2A, cor) < 0); +- WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_INTERRUPTS, +- TWL4030_INTERRUPTS_BCIISR1B, cor) < 0); +- WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_INTERRUPTS, +- TWL4030_INTERRUPTS_BCIISR2B, cor) < 0); +- +- /* MAD C */ +- /* Mask MADC interrupts at TWL4030 */ +- WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_MADC, 0xff, +- TWL4030_MADC_IMR1) < 0); +- WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_MADC, 0xff, +- TWL4030_MADC_IMR2) < 0); +- +- /* Are MADC interrupt status bits cleared by reads or writes? */ +- cor = twl4030_read_cor_bit(TWL4030_MODULE_MADC, +- TWL4030_MADC_MADC_SIH_CTRL); +- WARN_ON(cor < 0); +- +- /* Clear TWL4030 MADC ISRs */ +- WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_MADC, +- TWL4030_MADC_ISR1, cor) < 0); +- WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_MADC, +- TWL4030_MADC_ISR2, cor) < 0); +- +- /* key Pad */ +- /* Mask keypad interrupts at TWL4030 */ +- WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_KEYPAD, 0xff, +- TWL4030_KEYPAD_KEYP_IMR1) < 0); +- WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_KEYPAD, 0xff, +- TWL4030_KEYPAD_KEYP_IMR2) < 0); +- +- /* Are keypad interrupt status bits cleared by reads or writes? */ +- cor = twl4030_read_cor_bit(TWL4030_MODULE_KEYPAD, +- TWL4030_KEYPAD_KEYP_SIH_CTRL); +- WARN_ON(cor < 0); +- +- /* Clear TWL4030 keypad ISRs */ +- /* XXX does this still need to be done twice for some reason? */ +- WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_KEYPAD, +- TWL4030_KEYPAD_KEYP_ISR1, cor) < 0); +- WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_KEYPAD, +- TWL4030_KEYPAD_KEYP_ISR2, cor) < 0); +- +- /* Slave address 0x49 */ +- +- /* Mask GPIO interrupts at TWL4030 */ +- WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xff, +- REG_GPIO_IMR1A) < 0); +- WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xff, +- REG_GPIO_IMR2A) < 0); +- WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xff, +- REG_GPIO_IMR3A) < 0); +- WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xff, +- REG_GPIO_IMR1B) < 0); +- WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xff, +- REG_GPIO_IMR2B) < 0); +- WARN_ON(twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xff, +- REG_GPIO_IMR3B) < 0); +- +- /* Are GPIO interrupt status bits cleared by reads or writes? */ +- cor = twl4030_read_cor_bit(TWL4030_MODULE_GPIO, +- REG_GPIO_SIH_CTRL); +- WARN_ON(cor < 0); +- +- /* Clear TWL4030 GPIO ISRs */ +- WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_GPIO, REG_GPIO_ISR1A, +- cor) < 0); +- WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_GPIO, REG_GPIO_ISR2A, +- cor) < 0); +- WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_GPIO, REG_GPIO_ISR3A, +- cor) < 0); +- WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_GPIO, REG_GPIO_ISR1B, +- cor) < 0); +- WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_GPIO, REG_GPIO_ISR2B, +- cor) < 0); +- WARN_ON(twl4030_i2c_clear_isr(TWL4030_MODULE_GPIO, REG_GPIO_ISR3B, +- cor) < 0); ++ twl4030_mask_clear_intrs(twl4030_mod_regs, ++ ARRAY_SIZE(twl4030_mod_regs)); + + /* install an irq handler for each of the PIH modules */ + for (i = TWL4030_IRQ_BASE; i < TWL4030_IRQ_END; i++) { |