As we add support for newer versions of the TSENS IP, the current
approach isn't scaling because registers and bitfields get moved around,
requiring platform-specific hacks in the code. By moving to regmap, we
can hide the register level differences away from the code.

Define a common set of registers and bit-fields that we care about
across the various tsens IP versions.

Signed-off-by: Amit Kucheria <[email protected]>
---
 drivers/thermal/qcom/tsens-common.c |  59 ++++++-----
 drivers/thermal/qcom/tsens-v0_1.c   |  51 +++++++++-
 drivers/thermal/qcom/tsens-v2.c     | 140 ++++++++++++++++++++-----
 drivers/thermal/qcom/tsens.c        |   5 +-
 drivers/thermal/qcom/tsens.h        | 153 ++++++++++++++++++++++++++--
 5 files changed, 348 insertions(+), 60 deletions(-)

diff --git a/drivers/thermal/qcom/tsens-common.c 
b/drivers/thermal/qcom/tsens-common.c
index af87216ee407..a82e4c928a78 100644
--- a/drivers/thermal/qcom/tsens-common.c
+++ b/drivers/thermal/qcom/tsens-common.c
@@ -12,13 +12,6 @@
 #include <linux/regmap.h>
 #include "tsens.h"
 
-/* SROT */
-#define TSENS_EN               BIT(0)
-
-/* TM */
-#define STATUS_OFFSET          0x30
-#define SN_ADDR_OFFSET         0x4
-#define SN_ST_TEMP_MASK                0x3ff
 #define CAL_DEGC_PT1           30
 #define CAL_DEGC_PT2           120
 #define SLOPE_FACTOR           1000
@@ -95,18 +88,14 @@ static inline int code_to_degc(u32 adc_code, const struct 
tsens_sensor *s)
        return degc;
 }
 
-int get_temp_common(struct tsens_priv *priv, int id, int *temp)
+int get_temp_common(struct tsens_priv *priv, int i, int *temp)
 {
-       struct tsens_sensor *s = &priv->sensor[id];
-       u32 code;
-       unsigned int status_reg;
+       struct tsens_sensor *s = &priv->sensor[i];
        int last_temp = 0, ret;
 
-       status_reg = priv->tm_offset + STATUS_OFFSET + s->hw_id * 
SN_ADDR_OFFSET;
-       ret = regmap_read(priv->tm_map, status_reg, &code);
+       ret = regmap_field_read(priv->rf[LAST_TEMP_0 + s->hw_id], &last_temp);
        if (ret)
                return ret;
-       last_temp = code & SN_ST_TEMP_MASK;
 
        *temp = code_to_degc(last_temp, s) * 1000;
 
@@ -131,10 +120,9 @@ int __init init_common(struct tsens_priv *priv)
 {
        void __iomem *tm_base, *srot_base;
        struct resource *res;
-       u32 code;
-       int ret;
+       u32 enabled;
+       int ret, i, j;
        struct platform_device *op = of_find_device_by_node(priv->dev->of_node);
-       u16 ctrl_offset = priv->reg_offsets[SROT_CTRL_OFFSET];
 
        if (!op)
                return -EINVAL;
@@ -166,14 +154,35 @@ int __init init_common(struct tsens_priv *priv)
        if (IS_ERR(priv->tm_map))
                return PTR_ERR(priv->tm_map);
 
-       if (priv->srot_map) {
-               ret = regmap_read(priv->srot_map, ctrl_offset, &code);
-               if (ret)
-                       return ret;
-               if (!(code & TSENS_EN)) {
-                       dev_err(priv->dev, "tsens device is not enabled\n");
-                       return -ENODEV;
-               }
+       priv->rf[TSENS_EN] = devm_regmap_field_alloc(priv->dev, priv->srot_map,
+                                                    priv->fields[TSENS_EN]);
+       if (IS_ERR(priv->rf[TSENS_EN]))
+               return PTR_ERR(priv->rf[TSENS_EN]);
+       ret = regmap_field_read(priv->rf[TSENS_EN], &enabled);
+       if (ret)
+               return ret;
+       if (!enabled) {
+               dev_err(priv->dev, "tsens device is not enabled\n");
+               return -ENODEV;
+       }
+
+       priv->rf[SENSOR_EN] = devm_regmap_field_alloc(priv->dev, priv->srot_map,
+                                                     priv->fields[SENSOR_EN]);
+       if (IS_ERR(priv->rf[SENSOR_EN]))
+               return PTR_ERR(priv->rf[SENSOR_EN]);
+
+       /* now alloc regmap_fields in tm_map */
+       for (i = 0, j = LAST_TEMP_0; i < priv->num_sensors; i++, j++) {
+               priv->rf[j] = devm_regmap_field_alloc(priv->dev, priv->tm_map,
+                                                     priv->fields[j]);
+               if (IS_ERR(priv->rf[j]))
+                       return PTR_ERR(priv->rf[j]);
+       }
+       for (i = 0, j = VALID_0; i < priv->num_sensors; i++, j++) {
+               priv->rf[j] = devm_regmap_field_alloc(priv->dev, priv->tm_map,
+                                                     priv->fields[j]);
+               if (IS_ERR(priv->rf[j]))
+                       return PTR_ERR(priv->rf[j]);
        }
 
        return 0;
diff --git a/drivers/thermal/qcom/tsens-v0_1.c 
b/drivers/thermal/qcom/tsens-v0_1.c
index a6e26be1234f..02907751c201 100644
--- a/drivers/thermal/qcom/tsens-v0_1.c
+++ b/drivers/thermal/qcom/tsens-v0_1.c
@@ -6,6 +6,15 @@
 #include <linux/platform_device.h>
 #include "tsens.h"
 
+/* ----- SROT ------ */
+#define SROT_CTRL_OFF 0x0000
+
+/* ----- TM ------ */
+#define TM_INT_EN_OFF                          0x0000
+#define TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF      0x0004
+#define TM_Sn_STATUS_OFF                       0x0030
+#define TM_TRDY_OFF                            0x005c
+
 /* eeprom layout data for 8916 */
 #define MSM8916_BASE0_MASK     0x0000007f
 #define MSM8916_BASE1_MASK     0xfe000000
@@ -308,6 +317,41 @@ static int calibrate_8974(struct tsens_priv *priv)
        return 0;
 }
 
+/* v0.1: 8916, 8974 */
+
+const struct tsens_features tsens_v0_1_feat = {
+       .ver_info       = 0,
+       .crit_int       = 0,
+       .adc            = 1,
+       .srot_split     = 1,
+};
+
+/* v0.1: 8916, 8974 */
+const struct reg_field tsens_v0_1_regfields[MAX_REGFIELDS] = {
+       /* ----- SROT ------ */
+       /* CTRL_OFFSET */
+       [TSENS_EN]     = REG_FIELD(SROT_CTRL_OFF, 0,  0),
+       [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1,  1),
+
+       /* ----- TM ------ */
+       /* UPPER_LOWER_INTERRUPT_CTRL */
+       [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 0),
+       /* Sn_STATUS */
+       REG_BANK(LAST_TEMP,  0, TM_Sn_STATUS_OFF,      0, 9),
+       REG_BANK(LAST_TEMP,  1, TM_Sn_STATUS_OFF +  4, 0, 9),
+       REG_BANK(LAST_TEMP,  2, TM_Sn_STATUS_OFF +  8, 0, 9),
+       REG_BANK(LAST_TEMP,  3, TM_Sn_STATUS_OFF + 12, 0, 9),
+       REG_BANK(LAST_TEMP,  4, TM_Sn_STATUS_OFF + 16, 0, 9),
+       REG_BANK(LAST_TEMP,  5, TM_Sn_STATUS_OFF + 20, 0, 9),
+       REG_BANK(LAST_TEMP,  6, TM_Sn_STATUS_OFF + 24, 0, 9),
+       REG_BANK(LAST_TEMP,  7, TM_Sn_STATUS_OFF + 28, 0, 9),
+       REG_BANK(LAST_TEMP,  8, TM_Sn_STATUS_OFF + 32, 0, 9),
+       REG_BANK(LAST_TEMP,  9, TM_Sn_STATUS_OFF + 36, 0, 9),
+       REG_BANK(LAST_TEMP, 10, TM_Sn_STATUS_OFF + 40, 0, 9),
+       /* TRDY */
+       [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0),
+};
+
 static const struct tsens_ops ops_8916 = {
        .init           = init_common,
        .calibrate      = calibrate_8916,
@@ -317,8 +361,10 @@ static const struct tsens_ops ops_8916 = {
 const struct tsens_plat_data data_8916 = {
        .num_sensors    = 5,
        .ops            = &ops_8916,
-       .reg_offsets    = { [SROT_CTRL_OFFSET] = 0x0 },
        .hw_ids         = (unsigned int []){0, 1, 2, 4, 5 },
+
+       .feat           = &tsens_v0_1_feat,
+       .fields = tsens_v0_1_regfields,
 };
 
 static const struct tsens_ops ops_8974 = {
@@ -330,5 +376,6 @@ static const struct tsens_ops ops_8974 = {
 const struct tsens_plat_data data_8974 = {
        .num_sensors    = 11,
        .ops            = &ops_8974,
-       .reg_offsets    = { [SROT_CTRL_OFFSET] = 0x0 },
+       .feat           = &tsens_v0_1_feat,
+       .fields = tsens_v0_1_regfields,
 };
diff --git a/drivers/thermal/qcom/tsens-v2.c b/drivers/thermal/qcom/tsens-v2.c
index 8b700772d903..962e47c54dca 100644
--- a/drivers/thermal/qcom/tsens-v2.c
+++ b/drivers/thermal/qcom/tsens-v2.c
@@ -4,50 +4,70 @@
  * Copyright (c) 2018, Linaro Limited
  */
 
-#include <linux/regmap.h>
 #include <linux/bitops.h>
+#include <linux/regmap.h>
 #include "tsens.h"
 
-#define STATUS_OFFSET          0xa0
+/* ----- SROT ------ */
+#define SROT_HW_VER_OFF        0x0000
+#define SROT_CTRL_OFF          0x0004
+
+/* ----- TM ------ */
+#define TM_INT_EN_OFF                  0x0004
+#define TM_UPPER_LOWER_INT_STATUS_OFF  0x0008
+#define TM_UPPER_LOWER_INT_CLEAR_OFF   0x000c
+#define TM_UPPER_LOWER_INT_MASK_OFF    0x0010
+#define TM_CRITICAL_INT_STATUS_OFF     0x0014
+#define TM_CRITICAL_INT_CLEAR_OFF      0x0018
+#define TM_CRITICAL_INT_MASK_OFF       0x001c
+#define TM_Sn_UPPER_LOWER_THRESHOLD_OFF 0x0020
+#define TM_Sn_CRITICAL_THRESHOLD_OFF   0x0060
+#define TM_Sn_STATUS_OFF               0x00a0
+#define TM_TRDY_OFF                    0x00e4
+
 #define LAST_TEMP_MASK         0xfff
-#define STATUS_VALID_BIT       BIT(21)
 
 static int get_temp_tsens_v2(struct tsens_priv *priv, int id, int *temp)
 {
        struct tsens_sensor *s = &priv->sensor[id];
-       u32 code;
-       unsigned int status_reg;
-       u32 last_temp = 0, last_temp2 = 0, last_temp3 = 0;
+       u32 temp_idx = LAST_TEMP_0 + s->hw_id;
+       u32 valid_idx = VALID_0 + s->hw_id;
+       u32 last_temp = 0, last_temp2 = 0, last_temp3 = 0, valid;
        int ret;
 
-       status_reg = priv->tm_offset + STATUS_OFFSET + s->hw_id * 4;
-       ret = regmap_read(priv->tm_map, status_reg, &code);
+       ret = regmap_field_read(priv->rf[temp_idx], &last_temp);
        if (ret)
                return ret;
-       last_temp = code & LAST_TEMP_MASK;
-       if (code & STATUS_VALID_BIT)
+
+       ret = regmap_field_read(priv->rf[valid_idx], &valid);
+       if (ret)
+               return ret;
+
+       if (valid)
                goto done;
 
        /* Try a second time */
-       ret = regmap_read(priv->tm_map, status_reg, &code);
+       ret = regmap_field_read(priv->rf[valid_idx], &valid);
        if (ret)
                return ret;
-       if (code & STATUS_VALID_BIT) {
-               last_temp = code & LAST_TEMP_MASK;
+       ret = regmap_field_read(priv->rf[temp_idx], &last_temp2);
+       if (ret)
+               return ret;
+       if (valid) {
+               last_temp = last_temp2;
                goto done;
-       } else {
-               last_temp2 = code & LAST_TEMP_MASK;
        }
 
        /* Try a third/last time */
-       ret = regmap_read(priv->tm_map, status_reg, &code);
+       ret = regmap_field_read(priv->rf[valid_idx], &valid);
        if (ret)
                return ret;
-       if (code & STATUS_VALID_BIT) {
-               last_temp = code & LAST_TEMP_MASK;
+       ret = regmap_field_read(priv->rf[temp_idx], &last_temp3);
+       if (ret)
+               return ret;
+       if (valid) {
+               last_temp = last_temp3;
                goto done;
-       } else {
-               last_temp3 = code & LAST_TEMP_MASK;
        }
 
        if (last_temp == last_temp2)
@@ -61,19 +81,93 @@ static int get_temp_tsens_v2(struct tsens_priv *priv, int 
id, int *temp)
        return 0;
 }
 
+/* v2.x: 8996, 8998, sdm845 */
+
+const struct tsens_features tsens_v2_feat = {
+       .ver_info       = 1,
+       .crit_int       = 1,
+       .adc            = 0,
+       .srot_split     = 1,
+};
+
+const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = {
+       /* ----- SROT ------ */
+       /* VERSION */
+       [VER_MAJOR] = REG_FIELD(SROT_HW_VER_OFF, 28, 31),
+       [VER_MINOR] = REG_FIELD(SROT_HW_VER_OFF, 16, 27),
+       [VER_STEP]  = REG_FIELD(SROT_HW_VER_OFF,  0, 15),
+       /* CTRL_OFF */
+       [TSENS_EN]     = REG_FIELD(SROT_CTRL_OFF,    0,  0),
+       [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF,    1,  1),
+
+       /* ----- TM ------ */
+       /* INTERRUPT ENABLE */
+       [LOW_INT_EN]  = REG_FIELD(TM_INT_EN_OFF, 0, 0),
+       [UP_INT_EN]   = REG_FIELD(TM_INT_EN_OFF, 1, 1),
+       [CRIT_INT_EN] = REG_FIELD(TM_INT_EN_OFF, 2, 2),
+       /* UPPER_LOWER_INTERRUPTS */
+       [LOW_INT_STATUS]  = REG_FIELD(TM_UPPER_LOWER_INT_STATUS_OFF,  0, 15),
+       [UP_INT_STATUS]   = REG_FIELD(TM_UPPER_LOWER_INT_STATUS_OFF, 16, 31),
+       [LOW_INT_CLEAR]   = REG_FIELD(TM_UPPER_LOWER_INT_CLEAR_OFF,   0, 15),
+       [UP_INT_CLEAR]    = REG_FIELD(TM_UPPER_LOWER_INT_CLEAR_OFF,  16, 31),
+       [LOW_INT_MASK]    = REG_FIELD(TM_UPPER_LOWER_INT_MASK_OFF,    0, 15),
+       [UP_INT_MASK]     = REG_FIELD(TM_UPPER_LOWER_INT_MASK_OFF,   16, 31),
+       /* CRITICAL_INTERRUPT */
+       [CRIT_INT_STATUS] = REG_FIELD(TM_CRITICAL_INT_STATUS_OFF,     0, 15),
+       [CRIT_INT_CLEAR]  = REG_FIELD(TM_UPPER_LOWER_INT_STATUS_OFF,  0, 15),
+       [CRIT_INT_MASK]   = REG_FIELD(TM_UPPER_LOWER_INT_STATUS_OFF,  0, 15),
+       /* Sn_STATUS */
+       REG_BANK(LAST_TEMP,  0, TM_Sn_STATUS_OFF,       0, 11),
+       REG_BANK(LAST_TEMP,  1, TM_Sn_STATUS_OFF +  4,  0, 11),
+       REG_BANK(LAST_TEMP,  2, TM_Sn_STATUS_OFF +  8,  0, 11),
+       REG_BANK(LAST_TEMP,  3, TM_Sn_STATUS_OFF + 12,  0, 11),
+       REG_BANK(LAST_TEMP,  4, TM_Sn_STATUS_OFF + 16,  0, 11),
+       REG_BANK(LAST_TEMP,  5, TM_Sn_STATUS_OFF + 20,  0, 11),
+       REG_BANK(LAST_TEMP,  6, TM_Sn_STATUS_OFF + 24,  0, 11),
+       REG_BANK(LAST_TEMP,  7, TM_Sn_STATUS_OFF + 28,  0, 11),
+       REG_BANK(LAST_TEMP,  8, TM_Sn_STATUS_OFF + 32,  0, 11),
+       REG_BANK(LAST_TEMP,  9, TM_Sn_STATUS_OFF + 36,  0, 11),
+       REG_BANK(LAST_TEMP, 10, TM_Sn_STATUS_OFF + 40,  0, 11),
+       REG_BANK(LAST_TEMP, 11, TM_Sn_STATUS_OFF + 44,  0, 11),
+       REG_BANK(LAST_TEMP, 12, TM_Sn_STATUS_OFF + 48,  0, 11),
+       REG_BANK(LAST_TEMP, 13, TM_Sn_STATUS_OFF + 52,  0, 11),
+       REG_BANK(LAST_TEMP, 14, TM_Sn_STATUS_OFF + 56,  0, 11),
+       REG_BANK(LAST_TEMP, 15, TM_Sn_STATUS_OFF + 60,  0, 11),
+       REG_BANK(VALID,      0, TM_Sn_STATUS_OFF,      21, 21),
+       REG_BANK(VALID,      1, TM_Sn_STATUS_OFF +  4, 21, 21),
+       REG_BANK(VALID,      2, TM_Sn_STATUS_OFF +  8, 21, 21),
+       REG_BANK(VALID,      3, TM_Sn_STATUS_OFF + 12, 21, 21),
+       REG_BANK(VALID,      4, TM_Sn_STATUS_OFF + 16, 21, 21),
+       REG_BANK(VALID,      5, TM_Sn_STATUS_OFF + 20, 21, 21),
+       REG_BANK(VALID,      6, TM_Sn_STATUS_OFF + 24, 21, 21),
+       REG_BANK(VALID,      7, TM_Sn_STATUS_OFF + 28, 21, 21),
+       REG_BANK(VALID,      8, TM_Sn_STATUS_OFF + 32, 21, 21),
+       REG_BANK(VALID,      9, TM_Sn_STATUS_OFF + 36, 21, 21),
+       REG_BANK(VALID,     10, TM_Sn_STATUS_OFF + 40, 21, 21),
+       REG_BANK(VALID,     11, TM_Sn_STATUS_OFF + 44, 21, 21),
+       REG_BANK(VALID,     12, TM_Sn_STATUS_OFF + 48, 21, 21),
+       REG_BANK(VALID,     13, TM_Sn_STATUS_OFF + 52, 21, 21),
+       REG_BANK(VALID,     14, TM_Sn_STATUS_OFF + 56, 21, 21),
+       REG_BANK(VALID,     15, TM_Sn_STATUS_OFF + 60, 21, 21),
+       /* TRDY: 1=ready, 0=in progress */
+       [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0),
+};
+
 static const struct tsens_ops ops_generic_v2 = {
        .init           = init_common,
        .get_temp       = get_temp_tsens_v2,
 };
 
 const struct tsens_plat_data data_tsens_v2 = {
-       .ops            = &ops_generic_v2,
-       .reg_offsets    = { [SROT_CTRL_OFFSET] = 0x4 },
+       .ops            = &ops_generic_v2,
+       .feat           = &tsens_v2_feat,
+       .fields = tsens_v2_regfields,
 };
 
 /* Kept around for backward compatibility with old msm8996.dtsi */
 const struct tsens_plat_data data_8996 = {
        .num_sensors    = 13,
        .ops            = &ops_generic_v2,
-       .reg_offsets    = { [SROT_CTRL_OFFSET] = 0x4 },
+       .feat           = &tsens_v2_feat,
+       .fields = tsens_v2_regfields,
 };
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index 0b5be08d515f..b91a0b88d33c 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -144,9 +144,8 @@ static int tsens_probe(struct platform_device *pdev)
                else
                        priv->sensor[i].hw_id = i;
        }
-       for (i = 0; i < REG_ARRAY_SIZE; i++) {
-               priv->reg_offsets[i] = data->reg_offsets[i];
-       }
+       priv->feat = data->feat;
+       priv->fields = data->fields;
 
        if (!priv->ops || !priv->ops->init || !priv->ops->get_temp)
                return -EINVAL;
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index 27b8f74829d9..20d89f8a6c3e 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -11,6 +11,7 @@
 #define TWO_PT_CALIB           0x3
 
 #include <linux/thermal.h>
+#include <linux/regmap.h>
 
 struct tsens_priv;
 
@@ -58,10 +59,142 @@ struct tsens_ops {
        int (*get_trend)(struct tsens_priv *priv, int i, enum thermal_trend 
*trend);
 };
 
-enum reg_list {
-       SROT_CTRL_OFFSET,
+#define REG_BANK(_name, _index, _offset, _startbit, _stopbit)          \
+       [_name##_##_index] = REG_FIELD(_offset, _startbit, _stopbit)
 
-       REG_ARRAY_SIZE,
+/* reg_field IDs to use as an index into an array */
+enum regfield_ids {
+       /* ----- SROT ------ */
+       /* HW_VER */
+       VER_MAJOR = 0,
+       VER_MINOR,
+       VER_STEP,
+       /* CTRL_OFFSET */
+       TSENS_EN =  3,
+       TSENS_SW_RST,
+       SENSOR_EN,
+       CODE_OR_TEMP,
+
+       /* ----- TM ------ */
+       /* STATUS */
+       LAST_TEMP_0 = 7,
+       LAST_TEMP_1,
+       LAST_TEMP_2,
+       LAST_TEMP_3,
+       LAST_TEMP_4,
+       LAST_TEMP_5,
+       LAST_TEMP_6,
+       LAST_TEMP_7,
+       LAST_TEMP_8,
+       LAST_TEMP_9,
+       LAST_TEMP_10,
+       LAST_TEMP_11,
+       LAST_TEMP_12,
+       LAST_TEMP_13,
+       LAST_TEMP_14,
+       LAST_TEMP_15,
+       VALID_0 = 23,
+       VALID_1,
+       VALID_2,
+       VALID_3,
+       VALID_4,
+       VALID_5,
+       VALID_6,
+       VALID_7,
+       VALID_8,
+       VALID_9,
+       VALID_10,
+       VALID_11,
+       VALID_12,
+       VALID_13,
+       VALID_14,
+       VALID_15,
+       /* TRDY */
+       TRDY,
+       /* INTERRUPT ENABLE */
+       INT_EN, /* PRE-V1, V1.x */
+       LOW_INT_EN,     /* V2.x */
+       UP_INT_EN,      /* V2.x */
+       CRIT_INT_EN,    /* V2.x */
+       /* INTERRUPT_STATUS */
+       LOW_INT_STATUS,
+       UP_INT_STATUS,
+       CRIT_INT_STATUS,
+       /* INTERRUPT_CLEAR */
+       LOW_INT_CLEAR,
+       UP_INT_CLEAR,
+       CRIT_INT_CLEAR,
+       /* INTERRUPT_MASK */
+       LOW_INT_MASK,
+       UP_INT_MASK,
+       CRIT_INT_MASK,
+       /* THRESHOLD */
+       LOW_THRESH_0,
+       LOW_THRESH_1,
+       LOW_THRESH_2,
+       LOW_THRESH_3,
+       LOW_THRESH_4,
+       LOW_THRESH_5,
+       LOW_THRESH_6,
+       LOW_THRESH_7,
+       LOW_THRESH_8,
+       LOW_THRESH_9,
+       LOW_THRESH_10,
+       LOW_THRESH_11,
+       LOW_THRESH_12,
+       LOW_THRESH_13,
+       LOW_THRESH_14,
+       LOW_THRESH_15,
+       UP_THRESH_0,
+       UP_THRESH_1,
+       UP_THRESH_2,
+       UP_THRESH_3,
+       UP_THRESH_4,
+       UP_THRESH_5,
+       UP_THRESH_6,
+       UP_THRESH_7,
+       UP_THRESH_8,
+       UP_THRESH_9,
+       UP_THRESH_10,
+       UP_THRESH_11,
+       UP_THRESH_12,
+       UP_THRESH_13,
+       UP_THRESH_14,
+       UP_THRESH_15,
+       CRIT_THRESH_0,
+       CRIT_THRESH_1,
+       CRIT_THRESH_2,
+       CRIT_THRESH_3,
+       CRIT_THRESH_4,
+       CRIT_THRESH_5,
+       CRIT_THRESH_6,
+       CRIT_THRESH_7,
+       CRIT_THRESH_8,
+       CRIT_THRESH_9,
+       CRIT_THRESH_10,
+       CRIT_THRESH_11,
+       CRIT_THRESH_12,
+       CRIT_THRESH_13,
+       CRIT_THRESH_14,
+       CRIT_THRESH_15,
+
+       /* Keep last */
+       MAX_REGFIELDS
+};
+
+/**
+ * struct tsens_features - Features supported by the IP
+ * @ver_info: does the IP export version information?
+ * @crit_int: does the IP support critical interrupts?
+ * @adc:      do the sensors only output adc code (instead of temperature)?
+ * @srot_split: does the IP neatly splits the register space into SROT and TM,
+ *              with SROT only being available to secure boot firmware?
+ */
+struct tsens_features {
+       unsigned int ver_info:1;
+       unsigned int crit_int:1;
+       unsigned int adc:1;
+       unsigned int srot_split:1;
 };
 
 /**
@@ -69,13 +202,15 @@ enum reg_list {
  * @num_sensors: Number of sensors supported by platform
  * @ops: operations the tsens instance supports
  * @hw_ids: Subset of sensors ids supported by platform, if not the first n
- * @reg_offsets: Register offsets for commonly used registers
+ * @feat: features of the IP
+ * @fields: bitfield locations
  */
 struct tsens_plat_data {
        const u32               num_sensors;
        const struct tsens_ops  *ops;
-       const u16               reg_offsets[REG_ARRAY_SIZE];
        unsigned int            *hw_ids;
+       const struct tsens_features     *feat;
+       const struct reg_field          *fields;
 };
 
 /**
@@ -94,8 +229,10 @@ struct tsens_context {
  * @srot_map: pointer to SROT register address space
  * @tm_offset: deal with old device trees that don't address TM and SROT
  *             address space separately
- * @reg_offsets: array of offsets to important regs for this version of IP
+ * @rf: array of regmap_fields used to store value of the field
  * @ctx: registers to be saved and restored during suspend/resume
+ * @feat: features of the IP
+ * @fields: bitfield locations
  * @ops: pointer to list of callbacks supported by this device
  * @sensor: list of sensors attached to this device
  */
@@ -105,8 +242,10 @@ struct tsens_priv {
        struct regmap                   *tm_map;
        struct regmap                   *srot_map;
        u32                             tm_offset;
-       u16                             reg_offsets[REG_ARRAY_SIZE];
+       struct regmap_field             *rf[MAX_REGFIELDS];
        struct tsens_context            ctx;
+       const struct tsens_features     *feat;
+       const struct reg_field          *fields;
        const struct tsens_ops          *ops;
        struct tsens_sensor             sensor[0];
 };
-- 
2.17.1

Reply via email to