mfd: stmpe: Preparations for STMPE ADC driver
authorStefan Agner <stefan@agner.ch>
Fri, 21 Dec 2018 13:46:32 +0000 (14:46 +0100)
committerLee Jones <lee.jones@linaro.org>
Wed, 16 Jan 2019 12:36:12 +0000 (12:36 +0000)
This prepares the MFD for the STMPE ADC driver. This commit introduces
devicetree settings that are used by the ADC and adds an init function.
Common ADC settings that are shared with the touchscreen driver can now
reside in the overlying MFD.

Signed-off-by: Stefan Agner <stefan@agner.ch>
Signed-off-by: Max Krummenacher <max.krummenacher@toradex.com>
Signed-off-by: Philippe Schenker <philippe.schenker@toradex.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
drivers/mfd/Kconfig
drivers/mfd/stmpe.c
include/linux/mfd/stmpe.h

index 8c5dfdce4326c8f0f8fc6b9402b18e52f15286ea..bba159e8eaa4c8e009bd3dac28597a73b3d8cf36 100644 (file)
@@ -1204,7 +1204,7 @@ config MFD_STMPE
 
          Currently supported devices are:
 
-               STMPE811: GPIO, Touchscreen
+               STMPE811: GPIO, Touchscreen, ADC
                STMPE1601: GPIO, Keypad
                STMPE1801: GPIO, Keypad
                STMPE2401: GPIO, Keypad
@@ -1217,6 +1217,7 @@ config MFD_STMPE
                GPIO: stmpe-gpio
                Keypad: stmpe-keypad
                Touchscreen: stmpe-ts
+               ADC: stmpe-adc
 
 menu "STMicroelectronics STMPE Interface Drivers"
 depends on MFD_STMPE
index 566caca4efd8ee509540b1c65df396015e37d042..f582531a8f3e2714c7cd8b833b6a897d85396ae4 100644 (file)
@@ -463,6 +463,28 @@ static const struct mfd_cell stmpe_ts_cell = {
        .num_resources  = ARRAY_SIZE(stmpe_ts_resources),
 };
 
+/*
+ * ADC (STMPE811)
+ */
+
+static struct resource stmpe_adc_resources[] = {
+       {
+               .name   = "STMPE_TEMP_SENS",
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .name   = "STMPE_ADC",
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static const struct mfd_cell stmpe_adc_cell = {
+       .name           = "stmpe-adc",
+       .of_compatible  = "st,stmpe-adc",
+       .resources      = stmpe_adc_resources,
+       .num_resources  = ARRAY_SIZE(stmpe_adc_resources),
+};
+
 /*
  * STMPE811 or STMPE610
  */
@@ -497,6 +519,11 @@ static struct stmpe_variant_block stmpe811_blocks[] = {
                .irq    = STMPE811_IRQ_TOUCH_DET,
                .block  = STMPE_BLOCK_TOUCHSCREEN,
        },
+       {
+               .cell   = &stmpe_adc_cell,
+               .irq    = STMPE811_IRQ_TEMP_SENS,
+               .block  = STMPE_BLOCK_ADC,
+       },
 };
 
 static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks,
@@ -517,6 +544,35 @@ static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks,
                                enable ? 0 : mask);
 }
 
+int stmpe811_adc_common_init(struct stmpe *stmpe)
+{
+       int ret;
+       u8 adc_ctrl1, adc_ctrl1_mask;
+
+       adc_ctrl1 = STMPE_SAMPLE_TIME(stmpe->sample_time) |
+                   STMPE_MOD_12B(stmpe->mod_12b) |
+                   STMPE_REF_SEL(stmpe->ref_sel);
+       adc_ctrl1_mask = STMPE_SAMPLE_TIME(0xff) | STMPE_MOD_12B(0xff) |
+                        STMPE_REF_SEL(0xff);
+
+       ret = stmpe_set_bits(stmpe, STMPE811_REG_ADC_CTRL1,
+                       adc_ctrl1_mask, adc_ctrl1);
+       if (ret) {
+               dev_err(stmpe->dev, "Could not setup ADC\n");
+               return ret;
+       }
+
+       ret = stmpe_set_bits(stmpe, STMPE811_REG_ADC_CTRL2,
+                       STMPE_ADC_FREQ(0xff), STMPE_ADC_FREQ(stmpe->adc_freq));
+       if (ret) {
+               dev_err(stmpe->dev, "Could not setup ADC\n");
+               return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(stmpe811_adc_common_init);
+
 static int stmpe811_get_altfunc(struct stmpe *stmpe, enum stmpe_block block)
 {
        /* 0 for touchscreen, 1 for GPIO */
@@ -1325,6 +1381,7 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum)
        struct device_node *np = ci->dev->of_node;
        struct stmpe *stmpe;
        int ret;
+       u32 val;
 
        pdata = devm_kzalloc(ci->dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata)
@@ -1342,6 +1399,15 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum)
        mutex_init(&stmpe->irq_lock);
        mutex_init(&stmpe->lock);
 
+       if (!of_property_read_u32(np, "st,sample-time", &val))
+               stmpe->sample_time = val;
+       if (!of_property_read_u32(np, "st,mod-12b", &val))
+               stmpe->mod_12b = val;
+       if (!of_property_read_u32(np, "st,ref-sel", &val))
+               stmpe->ref_sel = val;
+       if (!of_property_read_u32(np, "st,adc-freq", &val))
+               stmpe->adc_freq = val;
+
        stmpe->dev = ci->dev;
        stmpe->client = ci->client;
        stmpe->pdata = pdata;
@@ -1433,6 +1499,8 @@ int stmpe_remove(struct stmpe *stmpe)
        if (!IS_ERR(stmpe->vcc))
                regulator_disable(stmpe->vcc);
 
+       __stmpe_disable(stmpe, STMPE_BLOCK_ADC);
+
        mfd_remove_devices(stmpe->dev);
 
        return 0;
index c0353f6431f9a7403f6c6ac3686ba25dda82aa64..07f55aac93902122ae6f8bba64f05c1935cc3c99 100644 (file)
@@ -21,6 +21,9 @@
 #define STMPE_I_DRIVE(x)       (x & 0x1)
 #define STMPE_OP_MODE(x)       ((x & 0x7) << 1)
 
+#define STMPE811_REG_ADC_CTRL1 0x20
+#define STMPE811_REG_ADC_CTRL2 0x21
+
 struct device;
 struct regulator;
 
@@ -134,6 +137,12 @@ struct stmpe {
        u8 ier[2];
        u8 oldier[2];
        struct stmpe_platform_data *pdata;
+
+       /* For devices that use an ADC */
+       u8 sample_time;
+       u8 mod_12b;
+       u8 ref_sel;
+       u8 adc_freq;
 };
 
 extern int stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 data);
@@ -147,6 +156,7 @@ extern int stmpe_set_altfunc(struct stmpe *stmpe, u32 pins,
                             enum stmpe_block block);
 extern int stmpe_enable(struct stmpe *stmpe, unsigned int blocks);
 extern int stmpe_disable(struct stmpe *stmpe, unsigned int blocks);
+extern int stmpe811_adc_common_init(struct stmpe *stmpe);
 
 #define STMPE_GPIO_NOREQ_811_TOUCH     (0xf0)