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 <amit.kucheria@xxxxxxxxxx> --- 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