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>
This commit is contained in:
parent
903238a33c
commit
498d245749
@ -229,6 +229,11 @@ static int calibrate_8916(struct tsens_priv *priv)
|
||||
u32 p1[5], p2[5];
|
||||
int mode = 0;
|
||||
u32 *qfprom_cdata, *qfprom_csel;
|
||||
int ret;
|
||||
|
||||
ret = tsens_calibrate_nvmem(priv, 3);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib");
|
||||
if (IS_ERR(qfprom_cdata))
|
||||
@ -286,6 +291,11 @@ static int calibrate_8939(struct tsens_priv *priv)
|
||||
int mode = 0;
|
||||
u32 *qfprom_cdata;
|
||||
u32 cdata[4];
|
||||
int ret;
|
||||
|
||||
ret = tsens_calibrate_common(priv);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib");
|
||||
if (IS_ERR(qfprom_cdata))
|
||||
@ -486,6 +496,11 @@ static int calibrate_9607(struct tsens_priv *priv)
|
||||
u32 p1[5], p2[5];
|
||||
int mode = 0;
|
||||
u32 *qfprom_cdata;
|
||||
int ret;
|
||||
|
||||
ret = tsens_calibrate_common(priv);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib");
|
||||
if (IS_ERR(qfprom_cdata))
|
||||
|
@ -143,7 +143,11 @@ static int calibrate_v1(struct tsens_priv *priv)
|
||||
u32 p1[10], p2[10];
|
||||
u32 mode = 0, lsb = 0, msb = 0;
|
||||
u32 *qfprom_cdata;
|
||||
int i;
|
||||
int i, ret;
|
||||
|
||||
ret = tsens_calibrate_common(priv);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib");
|
||||
if (IS_ERR(qfprom_cdata))
|
||||
@ -209,6 +213,11 @@ static int calibrate_8976(struct tsens_priv *priv)
|
||||
u32 p1[11], p2[11];
|
||||
int mode = 0, tmp = 0;
|
||||
u32 *qfprom_cdata;
|
||||
int ret;
|
||||
|
||||
ret = tsens_calibrate_common(priv);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib");
|
||||
if (IS_ERR(qfprom_cdata))
|
||||
|
@ -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
|
||||
|
@ -6,6 +6,7 @@
|
||||
#ifndef __QCOM_TSENS_H__
|
||||
#define __QCOM_TSENS_H__
|
||||
|
||||
#define NO_PT_CALIB 0x0
|
||||
#define ONE_PT_CALIB 0x1
|
||||
#define ONE_PT_CALIB2 0x2
|
||||
#define TWO_PT_CALIB 0x3
|
||||
@ -17,6 +18,8 @@
|
||||
#define THRESHOLD_MAX_ADC_CODE 0x3ff
|
||||
#define THRESHOLD_MIN_ADC_CODE 0x0
|
||||
|
||||
#define MAX_SENSORS 16
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/thermal.h>
|
||||
#include <linux/regmap.h>
|
||||
@ -582,6 +585,8 @@ struct tsens_priv {
|
||||
};
|
||||
|
||||
char *qfprom_read(struct device *dev, const char *cname);
|
||||
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);
|
||||
int init_common(struct tsens_priv *priv);
|
||||
int get_temp_tsens_valid(const struct tsens_sensor *s, int *temp);
|
||||
|
Loading…
Reference in New Issue
Block a user