On 20.12.2022 03:47, Dmitry Baryshkov wrote: > MSM8974 has two sets of calibration data: main one and backup. Add > support for parsing both sets of calibration data from nvmem cells. > > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@xxxxxxxxxx> > --- Reviewed-by: Konrad Dybcio <konrad.dybcio@xxxxxxxxxx> Konrad > drivers/thermal/qcom/tsens-v0_1.c | 50 +++++++++++++++++++++++++++++++ > drivers/thermal/qcom/tsens.c | 39 +++++++++++++++++++----- > drivers/thermal/qcom/tsens.h | 1 + > 3 files changed, 82 insertions(+), 8 deletions(-) > > diff --git a/drivers/thermal/qcom/tsens-v0_1.c b/drivers/thermal/qcom/tsens-v0_1.c > index caffcf9905b9..6a11b8b196b9 100644 > --- a/drivers/thermal/qcom/tsens-v0_1.c > +++ b/drivers/thermal/qcom/tsens-v0_1.c > @@ -3,6 +3,7 @@ > * Copyright (c) 2015, The Linux Foundation. All rights reserved. > */ > > +#include <linux/nvmem-consumer.h> > #include <linux/platform_device.h> > #include "tsens.h" > > @@ -194,6 +195,50 @@ static int calibrate_8916(struct tsens_priv *priv) > return 0; > } > > +static int calibrate_8974_nvmem(struct tsens_priv *priv) > +{ > + int i, ret, mode; > + u32 p1[11], p2[11]; > + u32 backup; > + > + ret = nvmem_cell_read_variable_le_u32(priv->dev, "use_backup", &backup); > + if (ret == -ENOENT) > + dev_warn(priv->dev, "Please migrate to separate nvmem cells for calibration data\n"); > + if (ret < 0) > + return ret; > + > + mode = tsens_read_calibration(priv, 2, p1, p2, backup == BKP_SEL); > + if (mode < 0) > + return mode; > + > + if (mode == NO_PT_CALIB) { > + p1[0] += 2; > + p1[1] += 9; > + p1[2] += 3; > + p1[3] += 9; > + p1[4] += 5; > + p1[5] += 9; > + p1[6] += 7; > + p1[7] += 10; > + p1[8] += 8; > + p1[9] += 9; > + p1[10] += 8; > + } else { > + for (i = 0; i < priv->num_sensors; i++) { > + /* > + * ONE_PT_CALIB requires using addition here instead of > + * using OR operation. > + */ > + p1[i] += BIT_APPEND; > + p2[i] += BIT_APPEND; > + } > + } > + > + compute_intercept_slope(priv, p1, p2, mode); > + > + return 0; > +} > + > static int calibrate_8974(struct tsens_priv *priv) > { > int base1 = 0, base2 = 0, i; > @@ -201,6 +246,11 @@ static int calibrate_8974(struct tsens_priv *priv) > int mode = 0; > u32 *calib, *bkp; > u32 calib_redun_sel; > + int ret; > + > + ret = calibrate_8974_nvmem(priv); > + if (ret == 0) > + return 0; > > calib = (u32 *)qfprom_read(priv->dev, "calib"); > if (IS_ERR(calib)) > diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c > index 68aef0ed6182..83bf60fa9008 100644 > --- a/drivers/thermal/qcom/tsens.c > +++ b/drivers/thermal/qcom/tsens.c > @@ -70,18 +70,21 @@ char *qfprom_read(struct device *dev, const char *cname) > return ret; > } > > -int tsens_calibrate_nvmem(struct tsens_priv *priv, int shift) > +int tsens_read_calibration(struct tsens_priv *priv, int shift, u32 *p1, u32 *p2, bool backup) > { > u32 mode; > u32 base1, base2; > - u32 p1[MAX_SENSORS], p2[MAX_SENSORS]; > - char name[] = "sXX_pY"; /* s10_p1 */ > + char name[] = "sXX_pY_backup"; /* s10_p1_backup */ > int i, ret; > > if (priv->num_sensors > MAX_SENSORS) > return -EINVAL; > > - ret = nvmem_cell_read_variable_le_u32(priv->dev, "mode", &mode); > + ret = snprintf(name, sizeof(name), "mode%s", backup ? "_backup" : ""); > + if (ret < 0) > + return ret; > + > + ret = nvmem_cell_read_variable_le_u32(priv->dev, name, &mode); > if (ret == -ENOENT) > dev_warn(priv->dev, "Please migrate to separate nvmem cells for calibration data\n"); > if (ret < 0) > @@ -89,16 +92,24 @@ int tsens_calibrate_nvmem(struct tsens_priv *priv, int shift) > > dev_dbg(priv->dev, "calibration mode is %d\n", mode); > > - ret = nvmem_cell_read_variable_le_u32(priv->dev, "base1", &base1); > + ret = snprintf(name, sizeof(name), "base1%s", backup ? "_backup" : ""); > + if (ret < 0) > + return ret; > + > + ret = nvmem_cell_read_variable_le_u32(priv->dev, name, &base1); > + if (ret < 0) > + return ret; > + > + ret = snprintf(name, sizeof(name), "base2%s", backup ? "_backup" : ""); > if (ret < 0) > return ret; > > - ret = nvmem_cell_read_variable_le_u32(priv->dev, "base2", &base2); > + ret = nvmem_cell_read_variable_le_u32(priv->dev, name, &base2); > if (ret < 0) > return ret; > > for (i = 0; i < priv->num_sensors; i++) { > - ret = snprintf(name, sizeof(name), "s%d_p1", i); > + ret = snprintf(name, sizeof(name), "s%d_p1%s", i, backup ? "_backup" : ""); > if (ret < 0) > return ret; > > @@ -106,7 +117,7 @@ int tsens_calibrate_nvmem(struct tsens_priv *priv, int shift) > if (ret) > return ret; > > - ret = snprintf(name, sizeof(name), "s%d_p2", i); > + ret = snprintf(name, sizeof(name), "s%d_p2%s", i, backup ? "_backup" : ""); > if (ret < 0) > return ret; > > @@ -136,6 +147,18 @@ int tsens_calibrate_nvmem(struct tsens_priv *priv, int shift) > } > } > > + return mode; > +} > + > +int tsens_calibrate_nvmem(struct tsens_priv *priv, int shift) > +{ > + u32 p1[MAX_SENSORS], p2[MAX_SENSORS]; > + int mode; > + > + mode = tsens_read_calibration(priv, shift, p1, p2, false); > + if (mode < 0) > + return mode; > + > compute_intercept_slope(priv, p1, p2, mode); > > return 0; > diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h > index 645ae02438fa..a9ae8df9f810 100644 > --- a/drivers/thermal/qcom/tsens.h > +++ b/drivers/thermal/qcom/tsens.h > @@ -585,6 +585,7 @@ struct tsens_priv { > }; > > char *qfprom_read(struct device *dev, const char *cname); > +int tsens_read_calibration(struct tsens_priv *priv, int shift, u32 *p1, u32 *p2, bool backup); > int tsens_calibrate_nvmem(struct tsens_priv *priv, int shift); > int tsens_calibrate_common(struct tsens_priv *priv); > void compute_intercept_slope(struct tsens_priv *priv, u32 *pt1, u32 *pt2, u32 mode);