aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrice Chotard <patrice.chotard@st.com>2016-08-10 03:39:14 -0400
committerLee Jones <lee.jones@linaro.org>2016-08-10 04:25:18 -0400
commit6bb9f0d93399cbde14fc6a1532341a14a85d2df4 (patch)
treedfc09db23a1cd43685e919d8f07a021919c47e75
parentbd495916f2f0a05193c45b26e21b60c9ffaa8aae (diff)
mfd: Add STMPE1600 support
STMPE1600 is a 16-bit port expander. Datasheet is available here : http://www2.st.com/content/st_com/en/products/interfaces-and-transceivers/ i-o-expanders-and-level-translators/i-o-expanders/stmpe1600.html Signed-off-by: Amelie DELAUNAY <amelie.delaunay@st.com> Signed-off-by: Patrice Chotard <patrice.chotard@st.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Lee Jones <lee.jones@linaro.org>
-rw-r--r--drivers/mfd/stmpe-i2c.c2
-rw-r--r--drivers/mfd/stmpe.c65
-rw-r--r--drivers/mfd/stmpe.h21
-rw-r--r--include/linux/mfd/stmpe.h1
4 files changed, 84 insertions, 5 deletions
diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c
index c3f4aab53b07..863c39a3353c 100644
--- a/drivers/mfd/stmpe-i2c.c
+++ b/drivers/mfd/stmpe-i2c.c
@@ -57,6 +57,7 @@ static const struct of_device_id stmpe_of_match[] = {
57 { .compatible = "st,stmpe610", .data = (void *)STMPE610, }, 57 { .compatible = "st,stmpe610", .data = (void *)STMPE610, },
58 { .compatible = "st,stmpe801", .data = (void *)STMPE801, }, 58 { .compatible = "st,stmpe801", .data = (void *)STMPE801, },
59 { .compatible = "st,stmpe811", .data = (void *)STMPE811, }, 59 { .compatible = "st,stmpe811", .data = (void *)STMPE811, },
60 { .compatible = "st,stmpe1600", .data = (void *)STMPE1600, },
60 { .compatible = "st,stmpe1601", .data = (void *)STMPE1601, }, 61 { .compatible = "st,stmpe1601", .data = (void *)STMPE1601, },
61 { .compatible = "st,stmpe1801", .data = (void *)STMPE1801, }, 62 { .compatible = "st,stmpe1801", .data = (void *)STMPE1801, },
62 { .compatible = "st,stmpe2401", .data = (void *)STMPE2401, }, 63 { .compatible = "st,stmpe2401", .data = (void *)STMPE2401, },
@@ -101,6 +102,7 @@ static const struct i2c_device_id stmpe_i2c_id[] = {
101 { "stmpe610", STMPE610 }, 102 { "stmpe610", STMPE610 },
102 { "stmpe801", STMPE801 }, 103 { "stmpe801", STMPE801 },
103 { "stmpe811", STMPE811 }, 104 { "stmpe811", STMPE811 },
105 { "stmpe1600", STMPE1600 },
104 { "stmpe1601", STMPE1601 }, 106 { "stmpe1601", STMPE1601 },
105 { "stmpe1801", STMPE1801 }, 107 { "stmpe1801", STMPE1801 },
106 { "stmpe2401", STMPE2401 }, 108 { "stmpe2401", STMPE2401 },
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index 1877d1ea2e7c..cfdae8a3d779 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -553,6 +553,59 @@ static struct stmpe_variant_info stmpe610 = {
553}; 553};
554 554
555/* 555/*
556 * STMPE1600
557 * Compared to all others STMPE variant, LSB and MSB regs are located in this
558 * order : LSB addr
559 * MSB addr + 1
560 * As there is only 2 * 8bits registers for GPMR/GPSR/IEGPIOPR, CSB index is MSB registers
561 */
562
563static const u8 stmpe1600_regs[] = {
564 [STMPE_IDX_CHIP_ID] = STMPE1600_REG_CHIP_ID,
565 [STMPE_IDX_SYS_CTRL] = STMPE1600_REG_SYS_CTRL,
566 [STMPE_IDX_ICR_LSB] = STMPE1600_REG_SYS_CTRL,
567 [STMPE_IDX_GPMR_LSB] = STMPE1600_REG_GPMR_LSB,
568 [STMPE_IDX_GPMR_CSB] = STMPE1600_REG_GPMR_MSB,
569 [STMPE_IDX_GPSR_LSB] = STMPE1600_REG_GPSR_LSB,
570 [STMPE_IDX_GPSR_CSB] = STMPE1600_REG_GPSR_MSB,
571 [STMPE_IDX_GPDR_LSB] = STMPE1600_REG_GPDR_LSB,
572 [STMPE_IDX_GPDR_CSB] = STMPE1600_REG_GPDR_MSB,
573 [STMPE_IDX_IEGPIOR_LSB] = STMPE1600_REG_IEGPIOR_LSB,
574 [STMPE_IDX_IEGPIOR_CSB] = STMPE1600_REG_IEGPIOR_MSB,
575 [STMPE_IDX_ISGPIOR_LSB] = STMPE1600_REG_ISGPIOR_LSB,
576};
577
578static struct stmpe_variant_block stmpe1600_blocks[] = {
579 {
580 .cell = &stmpe_gpio_cell,
581 .irq = 0,
582 .block = STMPE_BLOCK_GPIO,
583 },
584};
585
586static int stmpe1600_enable(struct stmpe *stmpe, unsigned int blocks,
587 bool enable)
588{
589 if (blocks & STMPE_BLOCK_GPIO)
590 return 0;
591 else
592 return -EINVAL;
593}
594
595static struct stmpe_variant_info stmpe1600 = {
596 .name = "stmpe1600",
597 .id_val = STMPE1600_ID,
598 .id_mask = 0xffff,
599 .num_gpios = 16,
600 .af_bits = 0,
601 .regs = stmpe1600_regs,
602 .blocks = stmpe1600_blocks,
603 .num_blocks = ARRAY_SIZE(stmpe1600_blocks),
604 .num_irqs = STMPE1600_NR_INTERNAL_IRQS,
605 .enable = stmpe1600_enable,
606};
607
608/*
556 * STMPE1601 609 * STMPE1601
557 */ 610 */
558 611
@@ -949,6 +1002,7 @@ static struct stmpe_variant_info *stmpe_variant_info[STMPE_NBR_PARTS] = {
949 [STMPE610] = &stmpe610, 1002 [STMPE610] = &stmpe610,
950 [STMPE801] = &stmpe801, 1003 [STMPE801] = &stmpe801,
951 [STMPE811] = &stmpe811, 1004 [STMPE811] = &stmpe811,
1005 [STMPE1600] = &stmpe1600,
952 [STMPE1601] = &stmpe1601, 1006 [STMPE1601] = &stmpe1601,
953 [STMPE1801] = &stmpe1801, 1007 [STMPE1801] = &stmpe1801,
954 [STMPE2401] = &stmpe2401, 1008 [STMPE2401] = &stmpe2401,
@@ -975,7 +1029,8 @@ static irqreturn_t stmpe_irq(int irq, void *data)
975 int ret; 1029 int ret;
976 int i; 1030 int i;
977 1031
978 if (variant->id_val == STMPE801_ID) { 1032 if (variant->id_val == STMPE801_ID ||
1033 variant->id_val == STMPE1600_ID) {
979 int base = irq_create_mapping(stmpe->domain, 0); 1034 int base = irq_create_mapping(stmpe->domain, 0);
980 1035
981 handle_nested_irq(base); 1036 handle_nested_irq(base);
@@ -1149,13 +1204,13 @@ static int stmpe_chip_init(struct stmpe *stmpe)
1149 return ret; 1204 return ret;
1150 1205
1151 if (stmpe->irq >= 0) { 1206 if (stmpe->irq >= 0) {
1152 if (id == STMPE801_ID) 1207 if (id == STMPE801_ID || id == STMPE1600_ID)
1153 icr = STMPE_SYS_CTRL_INT_EN; 1208 icr = STMPE_SYS_CTRL_INT_EN;
1154 else 1209 else
1155 icr = STMPE_ICR_LSB_GIM; 1210 icr = STMPE_ICR_LSB_GIM;
1156 1211
1157 /* STMPE801 doesn't support Edge interrupts */ 1212 /* STMPE801 and STMPE1600 don't support Edge interrupts */
1158 if (id != STMPE801_ID) { 1213 if (id != STMPE801_ID && id != STMPE1600_ID) {
1159 if (irq_trigger == IRQF_TRIGGER_FALLING || 1214 if (irq_trigger == IRQF_TRIGGER_FALLING ||
1160 irq_trigger == IRQF_TRIGGER_RISING) 1215 irq_trigger == IRQF_TRIGGER_RISING)
1161 icr |= STMPE_ICR_LSB_EDGE; 1216 icr |= STMPE_ICR_LSB_EDGE;
@@ -1163,7 +1218,7 @@ static int stmpe_chip_init(struct stmpe *stmpe)
1163 1218
1164 if (irq_trigger == IRQF_TRIGGER_RISING || 1219 if (irq_trigger == IRQF_TRIGGER_RISING ||
1165 irq_trigger == IRQF_TRIGGER_HIGH) { 1220 irq_trigger == IRQF_TRIGGER_HIGH) {
1166 if (id == STMPE801_ID) 1221 if (id == STMPE801_ID || id == STMPE1600_ID)
1167 icr |= STMPE_SYS_CTRL_INT_HI; 1222 icr |= STMPE_SYS_CTRL_INT_HI;
1168 else 1223 else
1169 icr |= STMPE_ICR_LSB_HIGH; 1224 icr |= STMPE_ICR_LSB_HIGH;
diff --git a/drivers/mfd/stmpe.h b/drivers/mfd/stmpe.h
index f1273420c8e8..f7efdd8a5fc6 100644
--- a/drivers/mfd/stmpe.h
+++ b/drivers/mfd/stmpe.h
@@ -164,6 +164,27 @@ int stmpe_remove(struct stmpe *stmpe);
164#define STMPE811_SYS_CTRL2_TS_OFF (1 << 3) 164#define STMPE811_SYS_CTRL2_TS_OFF (1 << 3)
165 165
166/* 166/*
167 * STMPE1600
168 */
169#define STMPE1600_ID 0x0016
170#define STMPE1600_NR_INTERNAL_IRQS 16
171
172#define STMPE1600_REG_CHIP_ID 0x00
173#define STMPE1600_REG_SYS_CTRL 0x03
174#define STMPE1600_REG_IEGPIOR_LSB 0x08
175#define STMPE1600_REG_IEGPIOR_MSB 0x09
176#define STMPE1600_REG_ISGPIOR_LSB 0x0A
177#define STMPE1600_REG_ISGPIOR_MSB 0x0B
178#define STMPE1600_REG_GPMR_LSB 0x10
179#define STMPE1600_REG_GPMR_MSB 0x11
180#define STMPE1600_REG_GPSR_LSB 0x12
181#define STMPE1600_REG_GPSR_MSB 0x13
182#define STMPE1600_REG_GPDR_LSB 0x14
183#define STMPE1600_REG_GPDR_MSB 0x15
184#define STMPE1600_REG_GPPIR_LSB 0x16
185#define STMPE1600_REG_GPPIR_MSB 0x17
186
187/*
167 * STMPE1601 188 * STMPE1601
168 */ 189 */
169 190
diff --git a/include/linux/mfd/stmpe.h b/include/linux/mfd/stmpe.h
index 6b26661a640e..4a827af17e59 100644
--- a/include/linux/mfd/stmpe.h
+++ b/include/linux/mfd/stmpe.h
@@ -26,6 +26,7 @@ enum stmpe_partnum {
26 STMPE610, 26 STMPE610,
27 STMPE801, 27 STMPE801,
28 STMPE811, 28 STMPE811,
29 STMPE1600,
29 STMPE1601, 30 STMPE1601,
30 STMPE1801, 31 STMPE1801,
31 STMPE2401, 32 STMPE2401,