aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@st.com>2011-11-17 00:32:23 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2012-01-08 18:37:44 -0500
commit7f7f4ea15ef4645f3888310a7a761fc2c4f689c9 (patch)
tree2e1f8b27af9a3b6a328630d24dc97fb201da3ec4
parent1cda2394e95415f1469ab8eaffd081395e112551 (diff)
mfd: Add support for stmpe variant 801
STMPE801 is a GPIO expander. Registers for 801 are much different from other variants. This patch adds support for STMPE801 in stmpe mfd driver. Signed-off-by: Bhupesh Sharma <bhupesh.sharma@st.com> Signed-off-by: Pratyush Anand <pratyush.anand@st.com> Signed-off-by: Viresh Kumar <viresh.kumar@st.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--drivers/mfd/stmpe-i2c.c1
-rw-r--r--drivers/mfd/stmpe-spi.c1
-rw-r--r--drivers/mfd/stmpe.c97
-rw-r--r--drivers/mfd/stmpe.h19
-rw-r--r--include/linux/mfd/stmpe.h1
5 files changed, 106 insertions, 13 deletions
diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c
index b11d33b1c89..373f423b118 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
73static const struct i2c_device_id stmpe_i2c_id[] = { 73static 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 46963a5d569..b58c43c7ea9 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
111static const struct spi_device_id stmpe_spi_id[] = { 111static 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 67ff3dc5bb4..fc2c6afb31e 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 */
328static 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
340static struct stmpe_variant_block stmpe801_blocks[] = {
341 {
342 .cell = &stmpe_gpio_cell,
343 .irq = 0,
344 .block = STMPE_BLOCK_GPIO,
345 },
346};
347
348static 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
357static 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
668static struct stmpe_variant_info *stmpe_variant_info[] = { 714static 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
770static int __devinit stmpe_irq_init(struct stmpe *stmpe) 822static 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 a73f4c1085f..7b8e13f5b76 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 342005afd34..ca1d7a34760 100644
--- a/include/linux/mfd/stmpe.h
+++ b/include/linux/mfd/stmpe.h
@@ -21,6 +21,7 @@ enum stmpe_block {
21 21
22enum stmpe_partnum { 22enum stmpe_partnum {
23 STMPE610, 23 STMPE610,
24 STMPE801,
24 STMPE811, 25 STMPE811,
25 STMPE1601, 26 STMPE1601,
26 STMPE2401, 27 STMPE2401,