diff options
author | Patrice Chotard <patrice.chotard@st.com> | 2016-08-10 03:39:14 -0400 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2016-08-10 04:25:18 -0400 |
commit | 6bb9f0d93399cbde14fc6a1532341a14a85d2df4 (patch) | |
tree | dfc09db23a1cd43685e919d8f07a021919c47e75 | |
parent | bd495916f2f0a05193c45b26e21b60c9ffaa8aae (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.c | 2 | ||||
-rw-r--r-- | drivers/mfd/stmpe.c | 65 | ||||
-rw-r--r-- | drivers/mfd/stmpe.h | 21 | ||||
-rw-r--r-- | include/linux/mfd/stmpe.h | 1 |
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 | |||
563 | static 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 | |||
578 | static struct stmpe_variant_block stmpe1600_blocks[] = { | ||
579 | { | ||
580 | .cell = &stmpe_gpio_cell, | ||
581 | .irq = 0, | ||
582 | .block = STMPE_BLOCK_GPIO, | ||
583 | }, | ||
584 | }; | ||
585 | |||
586 | static 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 | |||
595 | static 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, |