mfd: Add STMPE1600 support
authorPatrice Chotard <patrice.chotard@st.com>
Wed, 10 Aug 2016 07:39:14 +0000 (09:39 +0200)
committerLee Jones <lee.jones@linaro.org>
Wed, 10 Aug 2016 08:25:18 +0000 (09:25 +0100)
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>
drivers/mfd/stmpe-i2c.c
drivers/mfd/stmpe.c
drivers/mfd/stmpe.h
include/linux/mfd/stmpe.h

index c3f4aab53b0796b169719e61a90a8a0817057e93..863c39a3353c97c871610d62f9340a661b7b6f6e 100644 (file)
@@ -57,6 +57,7 @@ static const struct of_device_id stmpe_of_match[] = {
        { .compatible = "st,stmpe610", .data = (void *)STMPE610, },
        { .compatible = "st,stmpe801", .data = (void *)STMPE801, },
        { .compatible = "st,stmpe811", .data = (void *)STMPE811, },
+       { .compatible = "st,stmpe1600", .data = (void *)STMPE1600, },
        { .compatible = "st,stmpe1601", .data = (void *)STMPE1601, },
        { .compatible = "st,stmpe1801", .data = (void *)STMPE1801, },
        { .compatible = "st,stmpe2401", .data = (void *)STMPE2401, },
@@ -101,6 +102,7 @@ static const struct i2c_device_id stmpe_i2c_id[] = {
        { "stmpe610", STMPE610 },
        { "stmpe801", STMPE801 },
        { "stmpe811", STMPE811 },
+       { "stmpe1600", STMPE1600 },
        { "stmpe1601", STMPE1601 },
        { "stmpe1801", STMPE1801 },
        { "stmpe2401", STMPE2401 },
index 1877d1ea2e7c16fecd68beafc4e15db03625c99d..cfdae8a3d77976b3a5b543551d07834069a7b45d 100644 (file)
@@ -552,6 +552,59 @@ static struct stmpe_variant_info stmpe610 = {
        .get_altfunc    = stmpe811_get_altfunc,
 };
 
+/*
+ * STMPE1600
+ * Compared to all others STMPE variant, LSB and MSB regs are located in this
+ * order :     LSB   addr
+ *             MSB   addr + 1
+ * As there is only 2 * 8bits registers for GPMR/GPSR/IEGPIOPR, CSB index is MSB registers
+ */
+
+static const u8 stmpe1600_regs[] = {
+       [STMPE_IDX_CHIP_ID]     = STMPE1600_REG_CHIP_ID,
+       [STMPE_IDX_SYS_CTRL]    = STMPE1600_REG_SYS_CTRL,
+       [STMPE_IDX_ICR_LSB]     = STMPE1600_REG_SYS_CTRL,
+       [STMPE_IDX_GPMR_LSB]    = STMPE1600_REG_GPMR_LSB,
+       [STMPE_IDX_GPMR_CSB]    = STMPE1600_REG_GPMR_MSB,
+       [STMPE_IDX_GPSR_LSB]    = STMPE1600_REG_GPSR_LSB,
+       [STMPE_IDX_GPSR_CSB]    = STMPE1600_REG_GPSR_MSB,
+       [STMPE_IDX_GPDR_LSB]    = STMPE1600_REG_GPDR_LSB,
+       [STMPE_IDX_GPDR_CSB]    = STMPE1600_REG_GPDR_MSB,
+       [STMPE_IDX_IEGPIOR_LSB] = STMPE1600_REG_IEGPIOR_LSB,
+       [STMPE_IDX_IEGPIOR_CSB] = STMPE1600_REG_IEGPIOR_MSB,
+       [STMPE_IDX_ISGPIOR_LSB] = STMPE1600_REG_ISGPIOR_LSB,
+};
+
+static struct stmpe_variant_block stmpe1600_blocks[] = {
+       {
+               .cell   = &stmpe_gpio_cell,
+               .irq    = 0,
+               .block  = STMPE_BLOCK_GPIO,
+       },
+};
+
+static int stmpe1600_enable(struct stmpe *stmpe, unsigned int blocks,
+                          bool enable)
+{
+       if (blocks & STMPE_BLOCK_GPIO)
+               return 0;
+       else
+               return -EINVAL;
+}
+
+static struct stmpe_variant_info stmpe1600 = {
+       .name           = "stmpe1600",
+       .id_val         = STMPE1600_ID,
+       .id_mask        = 0xffff,
+       .num_gpios      = 16,
+       .af_bits        = 0,
+       .regs           = stmpe1600_regs,
+       .blocks         = stmpe1600_blocks,
+       .num_blocks     = ARRAY_SIZE(stmpe1600_blocks),
+       .num_irqs       = STMPE1600_NR_INTERNAL_IRQS,
+       .enable         = stmpe1600_enable,
+};
+
 /*
  * STMPE1601
  */
@@ -949,6 +1002,7 @@ static struct stmpe_variant_info *stmpe_variant_info[STMPE_NBR_PARTS] = {
        [STMPE610]      = &stmpe610,
        [STMPE801]      = &stmpe801,
        [STMPE811]      = &stmpe811,
+       [STMPE1600]     = &stmpe1600,
        [STMPE1601]     = &stmpe1601,
        [STMPE1801]     = &stmpe1801,
        [STMPE2401]     = &stmpe2401,
@@ -975,7 +1029,8 @@ static irqreturn_t stmpe_irq(int irq, void *data)
        int ret;
        int i;
 
-       if (variant->id_val == STMPE801_ID) {
+       if (variant->id_val == STMPE801_ID ||
+           variant->id_val == STMPE1600_ID) {
                int base = irq_create_mapping(stmpe->domain, 0);
 
                handle_nested_irq(base);
@@ -1149,13 +1204,13 @@ static int stmpe_chip_init(struct stmpe *stmpe)
                return ret;
 
        if (stmpe->irq >= 0) {
-               if (id == STMPE801_ID)
+               if (id == STMPE801_ID || id == STMPE1600_ID)
                        icr = STMPE_SYS_CTRL_INT_EN;
                else
                        icr = STMPE_ICR_LSB_GIM;
 
-               /* STMPE801 doesn't support Edge interrupts */
-               if (id != STMPE801_ID) {
+               /* STMPE801 and STMPE1600 don't support Edge interrupts */
+               if (id != STMPE801_ID && id != STMPE1600_ID) {
                        if (irq_trigger == IRQF_TRIGGER_FALLING ||
                                        irq_trigger == IRQF_TRIGGER_RISING)
                                icr |= STMPE_ICR_LSB_EDGE;
@@ -1163,7 +1218,7 @@ static int stmpe_chip_init(struct stmpe *stmpe)
 
                if (irq_trigger == IRQF_TRIGGER_RISING ||
                                irq_trigger == IRQF_TRIGGER_HIGH) {
-                       if (id == STMPE801_ID)
+                       if (id == STMPE801_ID || id == STMPE1600_ID)
                                icr |= STMPE_SYS_CTRL_INT_HI;
                        else
                                icr |= STMPE_ICR_LSB_HIGH;
index f1273420c8e8b5623d17a7698d175af60d0c17a9..f7efdd8a5fc6301610a7e21593c69d7e7e07d757 100644 (file)
@@ -163,6 +163,27 @@ int stmpe_remove(struct stmpe *stmpe);
 #define STMPE811_SYS_CTRL2_GPIO_OFF    (1 << 2)
 #define STMPE811_SYS_CTRL2_TS_OFF      (1 << 3)
 
+/*
+ * STMPE1600
+ */
+#define STMPE1600_ID                   0x0016
+#define STMPE1600_NR_INTERNAL_IRQS     16
+
+#define STMPE1600_REG_CHIP_ID          0x00
+#define STMPE1600_REG_SYS_CTRL         0x03
+#define STMPE1600_REG_IEGPIOR_LSB      0x08
+#define STMPE1600_REG_IEGPIOR_MSB      0x09
+#define STMPE1600_REG_ISGPIOR_LSB      0x0A
+#define STMPE1600_REG_ISGPIOR_MSB      0x0B
+#define STMPE1600_REG_GPMR_LSB         0x10
+#define STMPE1600_REG_GPMR_MSB         0x11
+#define STMPE1600_REG_GPSR_LSB         0x12
+#define STMPE1600_REG_GPSR_MSB         0x13
+#define STMPE1600_REG_GPDR_LSB         0x14
+#define STMPE1600_REG_GPDR_MSB         0x15
+#define STMPE1600_REG_GPPIR_LSB                0x16
+#define STMPE1600_REG_GPPIR_MSB                0x17
+
 /*
  * STMPE1601
  */
index 6b26661a640ef97de939588e874028d2b90c00cb..4a827af17e598792264662beb2ed86260dfbe3eb 100644 (file)
@@ -26,6 +26,7 @@ enum stmpe_partnum {
        STMPE610,
        STMPE801,
        STMPE811,
+       STMPE1600,
        STMPE1601,
        STMPE1801,
        STMPE2401,