Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Patrice Chotard and committed by
Lee Jones
6bb9f0d9 bd495916

+84 -5
+2
drivers/mfd/stmpe-i2c.c
··· 57 57 { .compatible = "st,stmpe610", .data = (void *)STMPE610, }, 58 58 { .compatible = "st,stmpe801", .data = (void *)STMPE801, }, 59 59 { .compatible = "st,stmpe811", .data = (void *)STMPE811, }, 60 + { .compatible = "st,stmpe1600", .data = (void *)STMPE1600, }, 60 61 { .compatible = "st,stmpe1601", .data = (void *)STMPE1601, }, 61 62 { .compatible = "st,stmpe1801", .data = (void *)STMPE1801, }, 62 63 { .compatible = "st,stmpe2401", .data = (void *)STMPE2401, }, ··· 102 101 { "stmpe610", STMPE610 }, 103 102 { "stmpe801", STMPE801 }, 104 103 { "stmpe811", STMPE811 }, 104 + { "stmpe1600", STMPE1600 }, 105 105 { "stmpe1601", STMPE1601 }, 106 106 { "stmpe1801", STMPE1801 }, 107 107 { "stmpe2401", STMPE2401 },
+60 -5
drivers/mfd/stmpe.c
··· 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 609 * STMPE1601 557 610 */ 558 611 ··· 1002 949 [STMPE610] = &stmpe610, 1003 950 [STMPE801] = &stmpe801, 1004 951 [STMPE811] = &stmpe811, 952 + [STMPE1600] = &stmpe1600, 1005 953 [STMPE1601] = &stmpe1601, 1006 954 [STMPE1801] = &stmpe1801, 1007 955 [STMPE2401] = &stmpe2401, ··· 1029 975 int ret; 1030 976 int i; 1031 977 1032 - if (variant->id_val == STMPE801_ID) { 978 + if (variant->id_val == STMPE801_ID || 979 + variant->id_val == STMPE1600_ID) { 1033 980 int base = irq_create_mapping(stmpe->domain, 0); 1034 981 1035 982 handle_nested_irq(base); ··· 1204 1149 return ret; 1205 1150 1206 1151 if (stmpe->irq >= 0) { 1207 - if (id == STMPE801_ID) 1152 + if (id == STMPE801_ID || id == STMPE1600_ID) 1208 1153 icr = STMPE_SYS_CTRL_INT_EN; 1209 1154 else 1210 1155 icr = STMPE_ICR_LSB_GIM; 1211 1156 1212 - /* STMPE801 doesn't support Edge interrupts */ 1213 - if (id != STMPE801_ID) { 1157 + /* STMPE801 and STMPE1600 don't support Edge interrupts */ 1158 + if (id != STMPE801_ID && id != STMPE1600_ID) { 1214 1159 if (irq_trigger == IRQF_TRIGGER_FALLING || 1215 1160 irq_trigger == IRQF_TRIGGER_RISING) 1216 1161 icr |= STMPE_ICR_LSB_EDGE; ··· 1218 1163 1219 1164 if (irq_trigger == IRQF_TRIGGER_RISING || 1220 1165 irq_trigger == IRQF_TRIGGER_HIGH) { 1221 - if (id == STMPE801_ID) 1166 + if (id == STMPE801_ID || id == STMPE1600_ID) 1222 1167 icr |= STMPE_SYS_CTRL_INT_HI; 1223 1168 else 1224 1169 icr |= STMPE_ICR_LSB_HIGH;
+21
drivers/mfd/stmpe.h
··· 164 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 188 * STMPE1601 168 189 */ 169 190
+1
include/linux/mfd/stmpe.h
··· 26 26 STMPE610, 27 27 STMPE801, 28 28 STMPE811, 29 + STMPE1600, 29 30 STMPE1601, 30 31 STMPE1801, 31 32 STMPE2401,