iio: sx9310: Set various settings from DT
authorStephen Boyd <swboyd@chromium.org>
Wed, 7 Oct 2020 01:17:35 +0000 (18:17 -0700)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Sat, 10 Oct 2020 16:38:38 +0000 (17:38 +0100)
These properties need to be set during driver probe. Parse any DT
properties and replace the default register settings with the ones
parsed from DT.

Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Cc: Daniel Campello <campello@chromium.org>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: <devicetree@vger.kernel.org>
Cc: Douglas Anderson <dianders@chromium.org>
Cc: Gwendal Grignou <gwendal@chromium.org>
Cc: Evan Green <evgreen@chromium.org>
Link: https://lore.kernel.org/r/20201007011735.1346994-7-swboyd@chromium.org
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/proximity/sx9310.c

index 1809940..a2f8209 100644 (file)
 #define   SX9310_REG_PROX_CTRL0_SCANPERIOD_15MS                0x01
 #define SX9310_REG_PROX_CTRL1                          0x11
 #define SX9310_REG_PROX_CTRL2                          0x12
+#define   SX9310_REG_PROX_CTRL2_COMBMODE_MASK          GENMASK(7, 6)
+#define   SX9310_REG_PROX_CTRL2_COMBMODE_CS0_CS1_CS2_CS3 (0x03 << 6)
 #define   SX9310_REG_PROX_CTRL2_COMBMODE_CS1_CS2       (0x02 << 6)
+#define   SX9310_REG_PROX_CTRL2_COMBMODE_CS0_CS1       (0x01 << 6)
+#define   SX9310_REG_PROX_CTRL2_COMBMODE_CS3           (0x00 << 6)
+#define   SX9310_REG_PROX_CTRL2_SHIELDEN_MASK          GENMASK(3, 2)
 #define   SX9310_REG_PROX_CTRL2_SHIELDEN_DYNAMIC       (0x01 << 2)
+#define   SX9310_REG_PROX_CTRL2_SHIELDEN_GROUND                (0x02 << 2)
 #define SX9310_REG_PROX_CTRL3                          0x13
 #define   SX9310_REG_PROX_CTRL3_GAIN0_MASK             GENMASK(3, 2)
 #define   SX9310_REG_PROX_CTRL3_GAIN0_X8               (0x03 << 2)
 #define   SX9310_REG_PROX_CTRL3_GAIN12_MASK            GENMASK(1, 0)
 #define   SX9310_REG_PROX_CTRL3_GAIN12_X4              0x02
 #define SX9310_REG_PROX_CTRL4                          0x14
+#define   SX9310_REG_PROX_CTRL4_RESOLUTION_MASK                GENMASK(2, 0)
 #define   SX9310_REG_PROX_CTRL4_RESOLUTION_FINEST      0x07
+#define   SX9310_REG_PROX_CTRL4_RESOLUTION_VERY_FINE   0x06
+#define   SX9310_REG_PROX_CTRL4_RESOLUTION_FINE                0x05
+#define   SX9310_REG_PROX_CTRL4_RESOLUTION_MEDIUM      0x04
+#define   SX9310_REG_PROX_CTRL4_RESOLUTION_MEDIUM_COARSE 0x03
+#define   SX9310_REG_PROX_CTRL4_RESOLUTION_COARSE      0x02
+#define   SX9310_REG_PROX_CTRL4_RESOLUTION_VERY_COARSE 0x01
+#define   SX9310_REG_PROX_CTRL4_RESOLUTION_COARSEST    0x00
 #define SX9310_REG_PROX_CTRL5                          0x15
 #define   SX9310_REG_PROX_CTRL5_RANGE_SMALL            (0x03 << 6)
+#define   SX9310_REG_PROX_CTRL5_STARTUPSENS_MASK       GENMASK(3, 2)
 #define   SX9310_REG_PROX_CTRL5_STARTUPSENS_CS1                (0x01 << 2)
+#define   SX9310_REG_PROX_CTRL5_RAWFILT_MASK           GENMASK(1, 0)
+#define   SX9310_REG_PROX_CTRL5_RAWFILT_SHIFT          0
 #define   SX9310_REG_PROX_CTRL5_RAWFILT_1P25           0x02
 #define SX9310_REG_PROX_CTRL6                          0x16
 #define   SX9310_REG_PROX_CTRL6_AVGTHRESH_DEFAULT      0x20
 #define SX9310_REG_PROX_CTRL7                          0x17
 #define   SX9310_REG_PROX_CTRL7_AVGNEGFILT_2           (0x01 << 3)
+#define   SX9310_REG_PROX_CTRL7_AVGPOSFILT_MASK                GENMASK(2, 0)
+#define   SX9310_REG_PROX_CTRL7_AVGPOSFILT_SHIFT       0
 #define   SX9310_REG_PROX_CTRL7_AVGPOSFILT_512         0x05
 #define SX9310_REG_PROX_CTRL8                          0x18
 #define   SX9310_REG_PROX_CTRL8_9_PTHRESH_MASK         GENMASK(7, 3)
@@ -1193,9 +1212,113 @@ static int sx9310_init_compensation(struct iio_dev *indio_dev)
        return ret;
 }
 
+static const struct sx9310_reg_default *
+sx9310_get_default_reg(struct sx9310_data *data, int i,
+                      struct sx9310_reg_default *reg_def)
+{
+       int ret;
+       const struct device_node *np = data->client->dev.of_node;
+       u32 combined[SX9310_NUM_CHANNELS] = { 4, 4, 4, 4 };
+       unsigned long comb_mask = 0;
+       const char *res;
+       u32 start = 0, raw = 0, pos = 0;
+
+       memcpy(reg_def, &sx9310_default_regs[i], sizeof(*reg_def));
+       if (!np)
+               return reg_def;
+
+       switch (reg_def->reg) {
+       case SX9310_REG_PROX_CTRL2:
+               if (of_property_read_bool(np, "semtech,cs0-ground")) {
+                       reg_def->def &= ~SX9310_REG_PROX_CTRL2_SHIELDEN_MASK;
+                       reg_def->def |= SX9310_REG_PROX_CTRL2_SHIELDEN_GROUND;
+               }
+
+               reg_def->def &= ~SX9310_REG_PROX_CTRL2_COMBMODE_MASK;
+               of_property_read_u32_array(np, "semtech,combined-sensors",
+                                          combined, ARRAY_SIZE(combined));
+               for (i = 0; i < ARRAY_SIZE(combined); i++) {
+                       if (combined[i] <= SX9310_NUM_CHANNELS)
+                               comb_mask |= BIT(combined[i]);
+               }
+
+               comb_mask &= 0xf;
+               if (comb_mask == (BIT(3) | BIT(2) | BIT(1) | BIT(0)))
+                       reg_def->def |= SX9310_REG_PROX_CTRL2_COMBMODE_CS0_CS1_CS2_CS3;
+               else if (comb_mask == (BIT(1) | BIT(2)))
+                       reg_def->def |= SX9310_REG_PROX_CTRL2_COMBMODE_CS1_CS2;
+               else if (comb_mask == (BIT(0) | BIT(1)))
+                       reg_def->def |= SX9310_REG_PROX_CTRL2_COMBMODE_CS0_CS1;
+               else if (comb_mask == BIT(3))
+                       reg_def->def |= SX9310_REG_PROX_CTRL2_COMBMODE_CS3;
+
+               break;
+       case SX9310_REG_PROX_CTRL4:
+               ret = of_property_read_string(np, "semtech,resolution", &res);
+               if (ret)
+                       break;
+
+               reg_def->def &= ~SX9310_REG_PROX_CTRL4_RESOLUTION_MASK;
+               if (!strcmp(res, "coarsest"))
+                       reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_COARSEST;
+               else if (!strcmp(res, "very-coarse"))
+                       reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_VERY_COARSE;
+               else if (!strcmp(res, "coarse"))
+                       reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_COARSE;
+               else if (!strcmp(res, "medium-coarse"))
+                       reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_MEDIUM_COARSE;
+               else if (!strcmp(res, "medium"))
+                       reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_MEDIUM;
+               else if (!strcmp(res, "fine"))
+                       reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_FINE;
+               else if (!strcmp(res, "very-fine"))
+                       reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_VERY_FINE;
+               else if (!strcmp(res, "finest"))
+                       reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_FINEST;
+
+               break;
+       case SX9310_REG_PROX_CTRL5:
+               ret = of_property_read_u32(np, "semtech,startup-sensor", &start);
+               if (ret) {
+                       start = FIELD_GET(SX9310_REG_PROX_CTRL5_STARTUPSENS_MASK,
+                                         reg_def->def);
+               }
+
+               reg_def->def &= ~SX9310_REG_PROX_CTRL5_STARTUPSENS_MASK;
+               reg_def->def |= FIELD_PREP(SX9310_REG_PROX_CTRL5_STARTUPSENS_MASK,
+                                          start);
+
+               ret = of_property_read_u32(np, "semtech,proxraw-strength", &raw);
+               if (ret) {
+                       raw = FIELD_GET(SX9310_REG_PROX_CTRL5_RAWFILT_MASK,
+                                       reg_def->def);
+               } else {
+                       raw = ilog2(raw);
+               }
+
+               reg_def->def &= ~SX9310_REG_PROX_CTRL5_RAWFILT_MASK;
+               reg_def->def |= FIELD_PREP(SX9310_REG_PROX_CTRL5_RAWFILT_MASK,
+                                          raw);
+               break;
+       case SX9310_REG_PROX_CTRL7:
+               ret = of_property_read_u32(np, "semtech,avg-pos-strength", &pos);
+               if (ret)
+                       break;
+
+               pos = min(max(ilog2(pos), 3), 10) - 3;
+               reg_def->def &= ~SX9310_REG_PROX_CTRL7_AVGPOSFILT_MASK;
+               reg_def->def |= FIELD_PREP(SX9310_REG_PROX_CTRL7_AVGPOSFILT_MASK,
+                                          pos);
+               break;
+       }
+
+       return reg_def;
+}
+
 static int sx9310_init_device(struct iio_dev *indio_dev)
 {
        struct sx9310_data *data = iio_priv(indio_dev);
+       struct sx9310_reg_default tmp;
        const struct sx9310_reg_default *initval;
        int ret;
        unsigned int i, val;
@@ -1213,7 +1336,7 @@ static int sx9310_init_device(struct iio_dev *indio_dev)
 
        /* Program some sane defaults. */
        for (i = 0; i < ARRAY_SIZE(sx9310_default_regs); i++) {
-               initval = &sx9310_default_regs[i];
+               initval = sx9310_get_default_reg(data, i, &tmp);
                ret = regmap_write(data->regmap, initval->reg, initval->def);
                if (ret)
                        return ret;