Commit 498d2457 authored by Dmitry Baryshkov's avatar Dmitry Baryshkov Committed by Daniel Lezcano
Browse files

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: default avatarDmitry Baryshkov <dmitry.baryshkov@linaro.org>
Link: https://lore.kernel.org/r/20230101194034.831222-10-dmitry.baryshkov@linaro.org


Signed-off-by: default avatarDaniel Lezcano <daniel.lezcano@linaro.org>
parent 903238a3
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -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))
+10 −1
Original line number Diff line number Diff line
@@ -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))
+76 −0
Original line number Diff line number Diff line
@@ -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
+5 −0
Original line number Diff line number Diff line
@@ -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);