diff options
Diffstat (limited to 'drivers/mfd/stmpe.c')
-rw-r--r-- | drivers/mfd/stmpe.c | 161 |
1 files changed, 135 insertions, 26 deletions
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index 94c7cc0..cfdae8a 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c @@ -469,6 +469,8 @@ static const struct mfd_cell stmpe_ts_cell = { static const u8 stmpe811_regs[] = { [STMPE_IDX_CHIP_ID] = STMPE811_REG_CHIP_ID, + [STMPE_IDX_SYS_CTRL] = STMPE811_REG_SYS_CTRL, + [STMPE_IDX_SYS_CTRL2] = STMPE811_REG_SYS_CTRL2, [STMPE_IDX_ICR_LSB] = STMPE811_REG_INT_CTRL, [STMPE_IDX_IER_LSB] = STMPE811_REG_INT_EN, [STMPE_IDX_ISR_MSB] = STMPE811_REG_INT_STA, @@ -481,7 +483,7 @@ static const u8 stmpe811_regs[] = { [STMPE_IDX_GPAFR_U_MSB] = STMPE811_REG_GPIO_AF, [STMPE_IDX_IEGPIOR_LSB] = STMPE811_REG_GPIO_INT_EN, [STMPE_IDX_ISGPIOR_MSB] = STMPE811_REG_GPIO_INT_STA, - [STMPE_IDX_GPEDR_MSB] = STMPE811_REG_GPIO_ED, + [STMPE_IDX_GPEDR_LSB] = STMPE811_REG_GPIO_ED, }; static struct stmpe_variant_block stmpe811_blocks[] = { @@ -511,7 +513,7 @@ static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks, if (blocks & STMPE_BLOCK_TOUCHSCREEN) mask |= STMPE811_SYS_CTRL2_TSC_OFF; - return __stmpe_set_bits(stmpe, STMPE811_REG_SYS_CTRL2, mask, + return __stmpe_set_bits(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL2], mask, enable ? 0 : mask); } @@ -551,25 +553,89 @@ static struct stmpe_variant_info stmpe610 = { }; /* + * STMPE1600 + * Compared to all others STMPE variant, LSB and MSB regs are located in this + * order : LSB addr + * MSB addr + 1 + * As there is only 2 * 8bits registers for GPMR/GPSR/IEGPIOPR, CSB index is MSB registers + */ + +static const u8 stmpe1600_regs[] = { + [STMPE_IDX_CHIP_ID] = STMPE1600_REG_CHIP_ID, + [STMPE_IDX_SYS_CTRL] = STMPE1600_REG_SYS_CTRL, + [STMPE_IDX_ICR_LSB] = STMPE1600_REG_SYS_CTRL, + [STMPE_IDX_GPMR_LSB] = STMPE1600_REG_GPMR_LSB, + [STMPE_IDX_GPMR_CSB] = STMPE1600_REG_GPMR_MSB, + [STMPE_IDX_GPSR_LSB] = STMPE1600_REG_GPSR_LSB, + [STMPE_IDX_GPSR_CSB] = STMPE1600_REG_GPSR_MSB, + [STMPE_IDX_GPDR_LSB] = STMPE1600_REG_GPDR_LSB, + [STMPE_IDX_GPDR_CSB] = STMPE1600_REG_GPDR_MSB, + [STMPE_IDX_IEGPIOR_LSB] = STMPE1600_REG_IEGPIOR_LSB, + [STMPE_IDX_IEGPIOR_CSB] = STMPE1600_REG_IEGPIOR_MSB, + [STMPE_IDX_ISGPIOR_LSB] = STMPE1600_REG_ISGPIOR_LSB, +}; + +static struct stmpe_variant_block stmpe1600_blocks[] = { + { + .cell = &stmpe_gpio_cell, + .irq = 0, + .block = STMPE_BLOCK_GPIO, + }, +}; + +static int stmpe1600_enable(struct stmpe *stmpe, unsigned int blocks, + bool enable) +{ + if (blocks & STMPE_BLOCK_GPIO) + return 0; + else + return -EINVAL; +} + +static struct stmpe_variant_info stmpe1600 = { + .name = "stmpe1600", + .id_val = STMPE1600_ID, + .id_mask = 0xffff, + .num_gpios = 16, + .af_bits = 0, + .regs = stmpe1600_regs, + .blocks = stmpe1600_blocks, + .num_blocks = ARRAY_SIZE(stmpe1600_blocks), + .num_irqs = STMPE1600_NR_INTERNAL_IRQS, + .enable = stmpe1600_enable, +}; + +/* * STMPE1601 */ static const u8 stmpe1601_regs[] = { [STMPE_IDX_CHIP_ID] = STMPE1601_REG_CHIP_ID, + [STMPE_IDX_SYS_CTRL] = STMPE1601_REG_SYS_CTRL, + [STMPE_IDX_SYS_CTRL2] = STMPE1601_REG_SYS_CTRL2, [STMPE_IDX_ICR_LSB] = STMPE1601_REG_ICR_LSB, + [STMPE_IDX_IER_MSB] = STMPE1601_REG_IER_MSB, [STMPE_IDX_IER_LSB] = STMPE1601_REG_IER_LSB, [STMPE_IDX_ISR_MSB] = STMPE1601_REG_ISR_MSB, [STMPE_IDX_GPMR_LSB] = STMPE1601_REG_GPIO_MP_LSB, + [STMPE_IDX_GPMR_CSB] = STMPE1601_REG_GPIO_MP_MSB, [STMPE_IDX_GPSR_LSB] = STMPE1601_REG_GPIO_SET_LSB, + [STMPE_IDX_GPSR_CSB] = STMPE1601_REG_GPIO_SET_MSB, [STMPE_IDX_GPCR_LSB] = STMPE1601_REG_GPIO_CLR_LSB, + [STMPE_IDX_GPCR_CSB] = STMPE1601_REG_GPIO_CLR_MSB, [STMPE_IDX_GPDR_LSB] = STMPE1601_REG_GPIO_SET_DIR_LSB, + [STMPE_IDX_GPDR_CSB] = STMPE1601_REG_GPIO_SET_DIR_MSB, + [STMPE_IDX_GPEDR_LSB] = STMPE1601_REG_GPIO_ED_LSB, + [STMPE_IDX_GPEDR_CSB] = STMPE1601_REG_GPIO_ED_MSB, [STMPE_IDX_GPRER_LSB] = STMPE1601_REG_GPIO_RE_LSB, + [STMPE_IDX_GPRER_CSB] = STMPE1601_REG_GPIO_RE_MSB, [STMPE_IDX_GPFER_LSB] = STMPE1601_REG_GPIO_FE_LSB, + [STMPE_IDX_GPFER_CSB] = STMPE1601_REG_GPIO_FE_MSB, [STMPE_IDX_GPPUR_LSB] = STMPE1601_REG_GPIO_PU_LSB, [STMPE_IDX_GPAFR_U_MSB] = STMPE1601_REG_GPIO_AF_U_MSB, [STMPE_IDX_IEGPIOR_LSB] = STMPE1601_REG_INT_EN_GPIO_MASK_LSB, + [STMPE_IDX_IEGPIOR_CSB] = STMPE1601_REG_INT_EN_GPIO_MASK_MSB, [STMPE_IDX_ISGPIOR_MSB] = STMPE1601_REG_INT_STA_GPIO_MSB, - [STMPE_IDX_GPEDR_MSB] = STMPE1601_REG_GPIO_ED_MSB, }; static struct stmpe_variant_block stmpe1601_blocks[] = { @@ -640,13 +706,13 @@ static int stmpe1601_autosleep(struct stmpe *stmpe, return timeout; } - ret = __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL2, + ret = __stmpe_set_bits(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL2], STMPE1601_AUTOSLEEP_TIMEOUT_MASK, timeout); if (ret < 0) return ret; - return __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL2, + return __stmpe_set_bits(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL2], STPME1601_AUTOSLEEP_ENABLE, STPME1601_AUTOSLEEP_ENABLE); } @@ -671,7 +737,7 @@ static int stmpe1601_enable(struct stmpe *stmpe, unsigned int blocks, else mask &= ~STMPE1601_SYS_CTRL_ENABLE_SPWM; - return __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL, mask, + return __stmpe_set_bits(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL], mask, enable ? mask : 0); } @@ -710,18 +776,33 @@ static struct stmpe_variant_info stmpe1601 = { */ static const u8 stmpe1801_regs[] = { [STMPE_IDX_CHIP_ID] = STMPE1801_REG_CHIP_ID, + [STMPE_IDX_SYS_CTRL] = STMPE1801_REG_SYS_CTRL, [STMPE_IDX_ICR_LSB] = STMPE1801_REG_INT_CTRL_LOW, [STMPE_IDX_IER_LSB] = STMPE1801_REG_INT_EN_MASK_LOW, [STMPE_IDX_ISR_LSB] = STMPE1801_REG_INT_STA_LOW, [STMPE_IDX_GPMR_LSB] = STMPE1801_REG_GPIO_MP_LOW, + [STMPE_IDX_GPMR_CSB] = STMPE1801_REG_GPIO_MP_MID, + [STMPE_IDX_GPMR_MSB] = STMPE1801_REG_GPIO_MP_HIGH, [STMPE_IDX_GPSR_LSB] = STMPE1801_REG_GPIO_SET_LOW, + [STMPE_IDX_GPSR_CSB] = STMPE1801_REG_GPIO_SET_MID, + [STMPE_IDX_GPSR_MSB] = STMPE1801_REG_GPIO_SET_HIGH, [STMPE_IDX_GPCR_LSB] = STMPE1801_REG_GPIO_CLR_LOW, + [STMPE_IDX_GPCR_CSB] = STMPE1801_REG_GPIO_CLR_MID, + [STMPE_IDX_GPCR_MSB] = STMPE1801_REG_GPIO_CLR_HIGH, [STMPE_IDX_GPDR_LSB] = STMPE1801_REG_GPIO_SET_DIR_LOW, + [STMPE_IDX_GPDR_CSB] = STMPE1801_REG_GPIO_SET_DIR_MID, + [STMPE_IDX_GPDR_MSB] = STMPE1801_REG_GPIO_SET_DIR_HIGH, [STMPE_IDX_GPRER_LSB] = STMPE1801_REG_GPIO_RE_LOW, + [STMPE_IDX_GPRER_CSB] = STMPE1801_REG_GPIO_RE_MID, + [STMPE_IDX_GPRER_MSB] = STMPE1801_REG_GPIO_RE_HIGH, [STMPE_IDX_GPFER_LSB] = STMPE1801_REG_GPIO_FE_LOW, + [STMPE_IDX_GPFER_CSB] = STMPE1801_REG_GPIO_FE_MID, + [STMPE_IDX_GPFER_MSB] = STMPE1801_REG_GPIO_FE_HIGH, [STMPE_IDX_GPPUR_LSB] = STMPE1801_REG_GPIO_PULL_UP_LOW, [STMPE_IDX_IEGPIOR_LSB] = STMPE1801_REG_INT_EN_GPIO_MASK_LOW, - [STMPE_IDX_ISGPIOR_LSB] = STMPE1801_REG_INT_STA_GPIO_LOW, + [STMPE_IDX_IEGPIOR_CSB] = STMPE1801_REG_INT_EN_GPIO_MASK_MID, + [STMPE_IDX_IEGPIOR_MSB] = STMPE1801_REG_INT_EN_GPIO_MASK_HIGH, + [STMPE_IDX_ISGPIOR_MSB] = STMPE1801_REG_INT_STA_GPIO_HIGH, }; static struct stmpe_variant_block stmpe1801_blocks[] = { @@ -751,22 +832,31 @@ static int stmpe1801_enable(struct stmpe *stmpe, unsigned int blocks, enable ? mask : 0); } -static int stmpe1801_reset(struct stmpe *stmpe) +static int stmpe_reset(struct stmpe *stmpe) { + u16 id_val = stmpe->variant->id_val; unsigned long timeout; int ret = 0; + u8 reset_bit; + + if (id_val == STMPE811_ID) + /* STMPE801 and STMPE610 use bit 1 of SYS_CTRL register */ + reset_bit = STMPE811_SYS_CTRL_RESET; + else + /* all other STMPE variant use bit 7 of SYS_CTRL register */ + reset_bit = STMPE_SYS_CTRL_RESET; - ret = __stmpe_set_bits(stmpe, STMPE1801_REG_SYS_CTRL, - STMPE1801_MSK_SYS_CTRL_RESET, STMPE1801_MSK_SYS_CTRL_RESET); + ret = __stmpe_set_bits(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL], + reset_bit, reset_bit); if (ret < 0) return ret; timeout = jiffies + msecs_to_jiffies(100); while (time_before(jiffies, timeout)) { - ret = __stmpe_reg_read(stmpe, STMPE1801_REG_SYS_CTRL); + ret = __stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL]); if (ret < 0) return ret; - if (!(ret & STMPE1801_MSK_SYS_CTRL_RESET)) + if (!(ret & reset_bit)) return 0; usleep_range(100, 200); } @@ -794,20 +884,39 @@ static struct stmpe_variant_info stmpe1801 = { static const u8 stmpe24xx_regs[] = { [STMPE_IDX_CHIP_ID] = STMPE24XX_REG_CHIP_ID, + [STMPE_IDX_SYS_CTRL] = STMPE24XX_REG_SYS_CTRL, + [STMPE_IDX_SYS_CTRL2] = STMPE24XX_REG_SYS_CTRL2, [STMPE_IDX_ICR_LSB] = STMPE24XX_REG_ICR_LSB, + [STMPE_IDX_IER_MSB] = STMPE24XX_REG_IER_MSB, [STMPE_IDX_IER_LSB] = STMPE24XX_REG_IER_LSB, [STMPE_IDX_ISR_MSB] = STMPE24XX_REG_ISR_MSB, [STMPE_IDX_GPMR_LSB] = STMPE24XX_REG_GPMR_LSB, + [STMPE_IDX_GPMR_CSB] = STMPE24XX_REG_GPMR_CSB, + [STMPE_IDX_GPMR_MSB] = STMPE24XX_REG_GPMR_MSB, [STMPE_IDX_GPSR_LSB] = STMPE24XX_REG_GPSR_LSB, + [STMPE_IDX_GPSR_CSB] = STMPE24XX_REG_GPSR_CSB, + [STMPE_IDX_GPSR_MSB] = STMPE24XX_REG_GPSR_MSB, [STMPE_IDX_GPCR_LSB] = STMPE24XX_REG_GPCR_LSB, + [STMPE_IDX_GPCR_CSB] = STMPE24XX_REG_GPCR_CSB, + [STMPE_IDX_GPCR_MSB] = STMPE24XX_REG_GPCR_MSB, [STMPE_IDX_GPDR_LSB] = STMPE24XX_REG_GPDR_LSB, + [STMPE_IDX_GPDR_CSB] = STMPE24XX_REG_GPDR_CSB, + [STMPE_IDX_GPDR_MSB] = STMPE24XX_REG_GPDR_MSB, [STMPE_IDX_GPRER_LSB] = STMPE24XX_REG_GPRER_LSB, + [STMPE_IDX_GPRER_CSB] = STMPE24XX_REG_GPRER_CSB, + [STMPE_IDX_GPRER_MSB] = STMPE24XX_REG_GPRER_MSB, [STMPE_IDX_GPFER_LSB] = STMPE24XX_REG_GPFER_LSB, + [STMPE_IDX_GPFER_CSB] = STMPE24XX_REG_GPFER_CSB, + [STMPE_IDX_GPFER_MSB] = STMPE24XX_REG_GPFER_MSB, [STMPE_IDX_GPPUR_LSB] = STMPE24XX_REG_GPPUR_LSB, [STMPE_IDX_GPPDR_LSB] = STMPE24XX_REG_GPPDR_LSB, [STMPE_IDX_GPAFR_U_MSB] = STMPE24XX_REG_GPAFR_U_MSB, [STMPE_IDX_IEGPIOR_LSB] = STMPE24XX_REG_IEGPIOR_LSB, + [STMPE_IDX_IEGPIOR_CSB] = STMPE24XX_REG_IEGPIOR_CSB, + [STMPE_IDX_IEGPIOR_MSB] = STMPE24XX_REG_IEGPIOR_MSB, [STMPE_IDX_ISGPIOR_MSB] = STMPE24XX_REG_ISGPIOR_MSB, + [STMPE_IDX_GPEDR_LSB] = STMPE24XX_REG_GPEDR_LSB, + [STMPE_IDX_GPEDR_CSB] = STMPE24XX_REG_GPEDR_CSB, [STMPE_IDX_GPEDR_MSB] = STMPE24XX_REG_GPEDR_MSB, }; @@ -840,7 +949,7 @@ static int stmpe24xx_enable(struct stmpe *stmpe, unsigned int blocks, if (blocks & STMPE_BLOCK_KEYPAD) mask |= STMPE24XX_SYS_CTRL_ENABLE_KPC; - return __stmpe_set_bits(stmpe, STMPE24XX_REG_SYS_CTRL, mask, + return __stmpe_set_bits(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL], mask, enable ? mask : 0); } @@ -893,6 +1002,7 @@ static struct stmpe_variant_info *stmpe_variant_info[STMPE_NBR_PARTS] = { [STMPE610] = &stmpe610, [STMPE801] = &stmpe801, [STMPE811] = &stmpe811, + [STMPE1600] = &stmpe1600, [STMPE1601] = &stmpe1601, [STMPE1801] = &stmpe1801, [STMPE2401] = &stmpe2401, @@ -919,7 +1029,8 @@ static irqreturn_t stmpe_irq(int irq, void *data) int ret; int i; - if (variant->id_val == STMPE801_ID) { + if (variant->id_val == STMPE801_ID || + variant->id_val == STMPE1600_ID) { int base = irq_create_mapping(stmpe->domain, 0); handle_nested_irq(base); @@ -982,7 +1093,7 @@ static void stmpe_irq_sync_unlock(struct irq_data *data) continue; stmpe->oldier[i] = new; - stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_IER_LSB] - i, new); + stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_IER_LSB + i], new); } mutex_unlock(&stmpe->irq_lock); @@ -1088,20 +1199,18 @@ static int stmpe_chip_init(struct stmpe *stmpe) if (ret) return ret; - if (id == STMPE1801_ID) { - ret = stmpe1801_reset(stmpe); - if (ret < 0) - return ret; - } + ret = stmpe_reset(stmpe); + if (ret < 0) + return ret; if (stmpe->irq >= 0) { - if (id == STMPE801_ID) - icr = STMPE801_REG_SYS_CTRL_INT_EN; + if (id == STMPE801_ID || id == STMPE1600_ID) + icr = STMPE_SYS_CTRL_INT_EN; else icr = STMPE_ICR_LSB_GIM; - /* STMPE801 doesn't support Edge interrupts */ - if (id != STMPE801_ID) { + /* STMPE801 and STMPE1600 don't support Edge interrupts */ + if (id != STMPE801_ID && id != STMPE1600_ID) { if (irq_trigger == IRQF_TRIGGER_FALLING || irq_trigger == IRQF_TRIGGER_RISING) icr |= STMPE_ICR_LSB_EDGE; @@ -1109,8 +1218,8 @@ static int stmpe_chip_init(struct stmpe *stmpe) if (irq_trigger == IRQF_TRIGGER_RISING || irq_trigger == IRQF_TRIGGER_HIGH) { - if (id == STMPE801_ID) - icr |= STMPE801_REG_SYS_CTRL_INT_HI; + if (id == STMPE801_ID || id == STMPE1600_ID) + icr |= STMPE_SYS_CTRL_INT_HI; else icr |= STMPE_ICR_LSB_HIGH; } |