diff options
-rw-r--r-- | drivers/mfd/stmpe-i2c.c | 1 | ||||
-rw-r--r-- | drivers/mfd/stmpe-spi.c | 1 | ||||
-rw-r--r-- | drivers/mfd/stmpe.c | 97 | ||||
-rw-r--r-- | drivers/mfd/stmpe.h | 19 | ||||
-rw-r--r-- | include/linux/mfd/stmpe.h | 1 |
5 files changed, 106 insertions, 13 deletions
diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c index b11d33b1c892..373f423b1181 100644 --- a/drivers/mfd/stmpe-i2c.c +++ b/drivers/mfd/stmpe-i2c.c | |||
@@ -72,6 +72,7 @@ static int __devexit stmpe_i2c_remove(struct i2c_client *i2c) | |||
72 | 72 | ||
73 | static const struct i2c_device_id stmpe_i2c_id[] = { | 73 | static const struct i2c_device_id stmpe_i2c_id[] = { |
74 | { "stmpe610", STMPE610 }, | 74 | { "stmpe610", STMPE610 }, |
75 | { "stmpe801", STMPE801 }, | ||
75 | { "stmpe811", STMPE811 }, | 76 | { "stmpe811", STMPE811 }, |
76 | { "stmpe1601", STMPE1601 }, | 77 | { "stmpe1601", STMPE1601 }, |
77 | { "stmpe2401", STMPE2401 }, | 78 | { "stmpe2401", STMPE2401 }, |
diff --git a/drivers/mfd/stmpe-spi.c b/drivers/mfd/stmpe-spi.c index 46963a5d569f..b58c43c7ea93 100644 --- a/drivers/mfd/stmpe-spi.c +++ b/drivers/mfd/stmpe-spi.c | |||
@@ -110,6 +110,7 @@ static int __devexit stmpe_spi_remove(struct spi_device *spi) | |||
110 | 110 | ||
111 | static const struct spi_device_id stmpe_spi_id[] = { | 111 | static const struct spi_device_id stmpe_spi_id[] = { |
112 | { "stmpe610", STMPE610 }, | 112 | { "stmpe610", STMPE610 }, |
113 | { "stmpe801", STMPE801 }, | ||
113 | { "stmpe811", STMPE811 }, | 114 | { "stmpe811", STMPE811 }, |
114 | { "stmpe1601", STMPE1601 }, | 115 | { "stmpe1601", STMPE1601 }, |
115 | { "stmpe2401", STMPE2401 }, | 116 | { "stmpe2401", STMPE2401 }, |
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index 67ff3dc5bb45..fc2c6afb31e1 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c | |||
@@ -241,12 +241,14 @@ int stmpe_set_altfunc(struct stmpe *stmpe, u32 pins, enum stmpe_block block) | |||
241 | u8 regaddr = stmpe->regs[STMPE_IDX_GPAFR_U_MSB]; | 241 | u8 regaddr = stmpe->regs[STMPE_IDX_GPAFR_U_MSB]; |
242 | int af_bits = variant->af_bits; | 242 | int af_bits = variant->af_bits; |
243 | int numregs = DIV_ROUND_UP(stmpe->num_gpios * af_bits, 8); | 243 | int numregs = DIV_ROUND_UP(stmpe->num_gpios * af_bits, 8); |
244 | int afperreg = 8 / af_bits; | ||
245 | int mask = (1 << af_bits) - 1; | 244 | int mask = (1 << af_bits) - 1; |
246 | u8 regs[numregs]; | 245 | u8 regs[numregs]; |
247 | int af; | 246 | int af, afperreg, ret; |
248 | int ret; | 247 | |
248 | if (!variant->get_altfunc) | ||
249 | return 0; | ||
249 | 250 | ||
251 | afperreg = 8 / af_bits; | ||
250 | mutex_lock(&stmpe->lock); | 252 | mutex_lock(&stmpe->lock); |
251 | 253 | ||
252 | ret = __stmpe_enable(stmpe, STMPE_BLOCK_GPIO); | 254 | ret = __stmpe_enable(stmpe, STMPE_BLOCK_GPIO); |
@@ -321,6 +323,50 @@ static struct mfd_cell stmpe_keypad_cell = { | |||
321 | }; | 323 | }; |
322 | 324 | ||
323 | /* | 325 | /* |
326 | * STMPE801 | ||
327 | */ | ||
328 | static const u8 stmpe801_regs[] = { | ||
329 | [STMPE_IDX_CHIP_ID] = STMPE801_REG_CHIP_ID, | ||
330 | [STMPE_IDX_ICR_LSB] = STMPE801_REG_SYS_CTRL, | ||
331 | [STMPE_IDX_GPMR_LSB] = STMPE801_REG_GPIO_MP_STA, | ||
332 | [STMPE_IDX_GPSR_LSB] = STMPE801_REG_GPIO_SET_PIN, | ||
333 | [STMPE_IDX_GPCR_LSB] = STMPE801_REG_GPIO_SET_PIN, | ||
334 | [STMPE_IDX_GPDR_LSB] = STMPE801_REG_GPIO_DIR, | ||
335 | [STMPE_IDX_IEGPIOR_LSB] = STMPE801_REG_GPIO_INT_EN, | ||
336 | [STMPE_IDX_ISGPIOR_MSB] = STMPE801_REG_GPIO_INT_STA, | ||
337 | |||
338 | }; | ||
339 | |||
340 | static struct stmpe_variant_block stmpe801_blocks[] = { | ||
341 | { | ||
342 | .cell = &stmpe_gpio_cell, | ||
343 | .irq = 0, | ||
344 | .block = STMPE_BLOCK_GPIO, | ||
345 | }, | ||
346 | }; | ||
347 | |||
348 | static int stmpe801_enable(struct stmpe *stmpe, unsigned int blocks, | ||
349 | bool enable) | ||
350 | { | ||
351 | if (blocks & STMPE_BLOCK_GPIO) | ||
352 | return 0; | ||
353 | else | ||
354 | return -EINVAL; | ||
355 | } | ||
356 | |||
357 | static struct stmpe_variant_info stmpe801 = { | ||
358 | .name = "stmpe801", | ||
359 | .id_val = STMPE801_ID, | ||
360 | .id_mask = 0xffff, | ||
361 | .num_gpios = 8, | ||
362 | .regs = stmpe801_regs, | ||
363 | .blocks = stmpe801_blocks, | ||
364 | .num_blocks = ARRAY_SIZE(stmpe801_blocks), | ||
365 | .num_irqs = STMPE801_NR_INTERNAL_IRQS, | ||
366 | .enable = stmpe801_enable, | ||
367 | }; | ||
368 | |||
369 | /* | ||
324 | * Touchscreen (STMPE811 or STMPE610) | 370 | * Touchscreen (STMPE811 or STMPE610) |
325 | */ | 371 | */ |
326 | 372 | ||
@@ -667,6 +713,7 @@ static struct stmpe_variant_info stmpe2403 = { | |||
667 | 713 | ||
668 | static struct stmpe_variant_info *stmpe_variant_info[] = { | 714 | static struct stmpe_variant_info *stmpe_variant_info[] = { |
669 | [STMPE610] = &stmpe610, | 715 | [STMPE610] = &stmpe610, |
716 | [STMPE801] = &stmpe801, | ||
670 | [STMPE811] = &stmpe811, | 717 | [STMPE811] = &stmpe811, |
671 | [STMPE1601] = &stmpe1601, | 718 | [STMPE1601] = &stmpe1601, |
672 | [STMPE2401] = &stmpe2401, | 719 | [STMPE2401] = &stmpe2401, |
@@ -683,6 +730,11 @@ static irqreturn_t stmpe_irq(int irq, void *data) | |||
683 | int ret; | 730 | int ret; |
684 | int i; | 731 | int i; |
685 | 732 | ||
733 | if (variant->id_val == STMPE801_ID) { | ||
734 | handle_nested_irq(stmpe->irq_base); | ||
735 | return IRQ_HANDLED; | ||
736 | } | ||
737 | |||
686 | ret = stmpe_block_read(stmpe, israddr, num, isr); | 738 | ret = stmpe_block_read(stmpe, israddr, num, isr); |
687 | if (ret < 0) | 739 | if (ret < 0) |
688 | return IRQ_NONE; | 740 | return IRQ_NONE; |
@@ -769,14 +821,17 @@ static struct irq_chip stmpe_irq_chip = { | |||
769 | 821 | ||
770 | static int __devinit stmpe_irq_init(struct stmpe *stmpe) | 822 | static int __devinit stmpe_irq_init(struct stmpe *stmpe) |
771 | { | 823 | { |
824 | struct irq_chip *chip = NULL; | ||
772 | int num_irqs = stmpe->variant->num_irqs; | 825 | int num_irqs = stmpe->variant->num_irqs; |
773 | int base = stmpe->irq_base; | 826 | int base = stmpe->irq_base; |
774 | int irq; | 827 | int irq; |
775 | 828 | ||
829 | if (stmpe->variant->id_val != STMPE801_ID) | ||
830 | chip = &stmpe_irq_chip; | ||
831 | |||
776 | for (irq = base; irq < base + num_irqs; irq++) { | 832 | for (irq = base; irq < base + num_irqs; irq++) { |
777 | irq_set_chip_data(irq, stmpe); | 833 | irq_set_chip_data(irq, stmpe); |
778 | irq_set_chip_and_handler(irq, &stmpe_irq_chip, | 834 | irq_set_chip_and_handler(irq, chip, handle_edge_irq); |
779 | handle_edge_irq); | ||
780 | irq_set_nested_thread(irq, 1); | 835 | irq_set_nested_thread(irq, 1); |
781 | #ifdef CONFIG_ARM | 836 | #ifdef CONFIG_ARM |
782 | set_irq_flags(irq, IRQF_VALID); | 837 | set_irq_flags(irq, IRQF_VALID); |
@@ -808,7 +863,7 @@ static int __devinit stmpe_chip_init(struct stmpe *stmpe) | |||
808 | unsigned int irq_trigger = stmpe->pdata->irq_trigger; | 863 | unsigned int irq_trigger = stmpe->pdata->irq_trigger; |
809 | int autosleep_timeout = stmpe->pdata->autosleep_timeout; | 864 | int autosleep_timeout = stmpe->pdata->autosleep_timeout; |
810 | struct stmpe_variant_info *variant = stmpe->variant; | 865 | struct stmpe_variant_info *variant = stmpe->variant; |
811 | u8 icr = STMPE_ICR_LSB_GIM; | 866 | u8 icr; |
812 | unsigned int id; | 867 | unsigned int id; |
813 | u8 data[2]; | 868 | u8 data[2]; |
814 | int ret; | 869 | int ret; |
@@ -831,16 +886,32 @@ static int __devinit stmpe_chip_init(struct stmpe *stmpe) | |||
831 | if (ret) | 886 | if (ret) |
832 | return ret; | 887 | return ret; |
833 | 888 | ||
834 | if (irq_trigger == IRQF_TRIGGER_FALLING || | 889 | if (id == STMPE801_ID) |
835 | irq_trigger == IRQF_TRIGGER_RISING) | 890 | icr = STMPE801_REG_SYS_CTRL_INT_EN; |
836 | icr |= STMPE_ICR_LSB_EDGE; | 891 | else |
892 | icr = STMPE_ICR_LSB_GIM; | ||
893 | |||
894 | /* STMPE801 doesn't support Edge interrupts */ | ||
895 | if (id != STMPE801_ID) { | ||
896 | if (irq_trigger == IRQF_TRIGGER_FALLING || | ||
897 | irq_trigger == IRQF_TRIGGER_RISING) | ||
898 | icr |= STMPE_ICR_LSB_EDGE; | ||
899 | } | ||
837 | 900 | ||
838 | if (irq_trigger == IRQF_TRIGGER_RISING || | 901 | if (irq_trigger == IRQF_TRIGGER_RISING || |
839 | irq_trigger == IRQF_TRIGGER_HIGH) | 902 | irq_trigger == IRQF_TRIGGER_HIGH) { |
840 | icr |= STMPE_ICR_LSB_HIGH; | 903 | if (id == STMPE801_ID) |
904 | icr |= STMPE801_REG_SYS_CTRL_INT_HI; | ||
905 | else | ||
906 | icr |= STMPE_ICR_LSB_HIGH; | ||
907 | } | ||
841 | 908 | ||
842 | if (stmpe->pdata->irq_invert_polarity) | 909 | if (stmpe->pdata->irq_invert_polarity) { |
843 | icr ^= STMPE_ICR_LSB_HIGH; | 910 | if (id == STMPE801_ID) |
911 | icr ^= STMPE801_REG_SYS_CTRL_INT_HI; | ||
912 | else | ||
913 | icr ^= STMPE_ICR_LSB_HIGH; | ||
914 | } | ||
844 | 915 | ||
845 | if (stmpe->pdata->autosleep) { | 916 | if (stmpe->pdata->autosleep) { |
846 | ret = stmpe_autosleep(stmpe, autosleep_timeout); | 917 | ret = stmpe_autosleep(stmpe, autosleep_timeout); |
diff --git a/drivers/mfd/stmpe.h b/drivers/mfd/stmpe.h index a73f4c1085f2..7b8e13f5b764 100644 --- a/drivers/mfd/stmpe.h +++ b/drivers/mfd/stmpe.h | |||
@@ -105,6 +105,25 @@ int stmpe_remove(struct stmpe *stmpe); | |||
105 | #define STMPE_ICR_LSB_GIM (1 << 0) | 105 | #define STMPE_ICR_LSB_GIM (1 << 0) |
106 | 106 | ||
107 | /* | 107 | /* |
108 | * STMPE801 | ||
109 | */ | ||
110 | #define STMPE801_ID 0x0108 | ||
111 | #define STMPE801_NR_INTERNAL_IRQS 1 | ||
112 | |||
113 | #define STMPE801_REG_CHIP_ID 0x00 | ||
114 | #define STMPE801_REG_VERSION_ID 0x02 | ||
115 | #define STMPE801_REG_SYS_CTRL 0x04 | ||
116 | #define STMPE801_REG_GPIO_INT_EN 0x08 | ||
117 | #define STMPE801_REG_GPIO_INT_STA 0x09 | ||
118 | #define STMPE801_REG_GPIO_MP_STA 0x10 | ||
119 | #define STMPE801_REG_GPIO_SET_PIN 0x11 | ||
120 | #define STMPE801_REG_GPIO_DIR 0x12 | ||
121 | |||
122 | #define STMPE801_REG_SYS_CTRL_RESET (1 << 7) | ||
123 | #define STMPE801_REG_SYS_CTRL_INT_EN (1 << 2) | ||
124 | #define STMPE801_REG_SYS_CTRL_INT_HI (1 << 0) | ||
125 | |||
126 | /* | ||
108 | * STMPE811 | 127 | * STMPE811 |
109 | */ | 128 | */ |
110 | 129 | ||
diff --git a/include/linux/mfd/stmpe.h b/include/linux/mfd/stmpe.h index 342005afd347..ca1d7a347600 100644 --- a/include/linux/mfd/stmpe.h +++ b/include/linux/mfd/stmpe.h | |||
@@ -21,6 +21,7 @@ enum stmpe_block { | |||
21 | 21 | ||
22 | enum stmpe_partnum { | 22 | enum stmpe_partnum { |
23 | STMPE610, | 23 | STMPE610, |
24 | STMPE801, | ||
24 | STMPE811, | 25 | STMPE811, |
25 | STMPE1601, | 26 | STMPE1601, |
26 | STMPE2401, | 27 | STMPE2401, |