diff options
author | Dmitry Baryshkov <dmitry.baryshkov@linaro.org> | 2023-01-01 21:40:23 +0200 |
---|---|---|
committer | Daniel Lezcano <daniel.lezcano@linaro.org> | 2023-01-16 11:22:30 +0100 |
commit | 498d245749ce35b21121cf5297547fca64bc52db (patch) | |
tree | f7441e0433eda5380b372dcc0e6241508eec22dc /drivers/thermal/qcom/tsens.c | |
parent | 903238a33c116edf5f64f7a3fd246e6169cccfa6 (diff) |
thermal/drivers/tsens: Support using nvmem cells for calibration data
Add a unified function using nvmem cells for parsing the calibration
data rather than parsing the calibration blob manually.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Link: https://lore.kernel.org/r/20230101194034.831222-10-dmitry.baryshkov@linaro.org
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Diffstat (limited to 'drivers/thermal/qcom/tsens.c')
-rw-r--r-- | drivers/thermal/qcom/tsens.c | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index b191e19df93d..ce568a68de4a 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -70,6 +70,82 @@ char *qfprom_read(struct device *dev, const char *cname) return ret; } +int tsens_calibrate_nvmem(struct tsens_priv *priv, int shift) +{ + u32 mode; + u32 base1, base2; + u32 p1[MAX_SENSORS], p2[MAX_SENSORS]; + char name[] = "sXX_pY"; /* s10_p1 */ + int i, ret; + + if (priv->num_sensors > MAX_SENSORS) + return -EINVAL; + + ret = nvmem_cell_read_variable_le_u32(priv->dev, "mode", &mode); + if (ret == -ENOENT) + dev_warn(priv->dev, "Please migrate to separate nvmem cells for calibration data\n"); + if (ret < 0) + return ret; + + dev_dbg(priv->dev, "calibration mode is %d\n", mode); + + ret = nvmem_cell_read_variable_le_u32(priv->dev, "base1", &base1); + if (ret < 0) + return ret; + + ret = nvmem_cell_read_variable_le_u32(priv->dev, "base2", &base2); + if (ret < 0) + return ret; + + for (i = 0; i < priv->num_sensors; i++) { + ret = snprintf(name, sizeof(name), "s%d_p1", priv->sensor[i].hw_id); + if (ret < 0) + return ret; + + ret = nvmem_cell_read_variable_le_u32(priv->dev, name, &p1[i]); + if (ret) + return ret; + + ret = snprintf(name, sizeof(name), "s%d_p2", priv->sensor[i].hw_id); + if (ret < 0) + return ret; + + ret = nvmem_cell_read_variable_le_u32(priv->dev, name, &p2[i]); + if (ret) + return ret; + } + + switch (mode) { + case ONE_PT_CALIB: + for (i = 0; i < priv->num_sensors; i++) + p1[i] = p1[i] + (base1 << shift); + break; + case TWO_PT_CALIB: + for (i = 0; i < priv->num_sensors; i++) + p2[i] = (p2[i] + base2) << shift; + fallthrough; + case ONE_PT_CALIB2: + for (i = 0; i < priv->num_sensors; i++) + p1[i] = (p1[i] + base1) << shift; + break; + default: + dev_dbg(priv->dev, "calibrationless mode\n"); + for (i = 0; i < priv->num_sensors; i++) { + p1[i] = 500; + p2[i] = 780; + } + } + + compute_intercept_slope(priv, p1, p2, mode); + + return 0; +} + +int tsens_calibrate_common(struct tsens_priv *priv) +{ + return tsens_calibrate_nvmem(priv, 2); +} + /* * Use this function on devices where slope and offset calculations * depend on calibration data read from qfprom. On others the slope |