summaryrefslogtreecommitdiff
path: root/drivers/thermal/qcom/tsens-v1.c
diff options
context:
space:
mode:
authorAngeloGioacchino Del Regno <kholk11@gmail.com>2019-10-05 12:41:31 +0200
committerDaniel Lezcano <daniel.lezcano@linaro.org>2019-11-07 07:00:26 +0100
commit0e580290170dfb438d911c306b27d89d5b99c1d9 (patch)
tree6bc534b375e6fb7012764b8eed7311bc3dd7bfa6 /drivers/thermal/qcom/tsens-v1.c
parent573ae2d9e00c72dcbe35803e20ce2b11334e43cd (diff)
thermal: qcom: tsens-v1: Add support for MSM8956 and MSM8976
Add support for reading calibrated value from thermistors in MSM8956, MSM8976 and their APQ variants. Signed-off-by: AngeloGioacchino Del Regno <kholk11@gmail.com> Reviewed-by: Amit Kucheria <amit.kucheria@linaro.org> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191005104133.30297-2-kholk11@gmail.com
Diffstat (limited to 'drivers/thermal/qcom/tsens-v1.c')
-rw-r--r--drivers/thermal/qcom/tsens-v1.c171
1 files changed, 170 insertions, 1 deletions
diff --git a/drivers/thermal/qcom/tsens-v1.c b/drivers/thermal/qcom/tsens-v1.c
index 7d33a0c8cd3e..2d1077b64887 100644
--- a/drivers/thermal/qcom/tsens-v1.c
+++ b/drivers/thermal/qcom/tsens-v1.c
@@ -6,6 +6,7 @@
#include <linux/bitops.h>
#include <linux/regmap.h>
#include <linux/delay.h>
+#include <linux/slab.h>
#include "tsens.h"
/* ----- SROT ------ */
@@ -20,6 +21,68 @@
#define TM_HIGH_LOW_INT_STATUS_OFF 0x0088
#define TM_HIGH_LOW_Sn_INT_THRESHOLD_OFF 0x0090
+/* eeprom layout data for msm8956/76 (v1) */
+#define MSM8976_BASE0_MASK 0xff
+#define MSM8976_BASE1_MASK 0xff
+#define MSM8976_BASE1_SHIFT 8
+
+#define MSM8976_S0_P1_MASK 0x3f00
+#define MSM8976_S1_P1_MASK 0x3f00000
+#define MSM8976_S2_P1_MASK 0x3f
+#define MSM8976_S3_P1_MASK 0x3f000
+#define MSM8976_S4_P1_MASK 0x3f00
+#define MSM8976_S5_P1_MASK 0x3f00000
+#define MSM8976_S6_P1_MASK 0x3f
+#define MSM8976_S7_P1_MASK 0x3f000
+#define MSM8976_S8_P1_MASK 0x1f8
+#define MSM8976_S9_P1_MASK 0x1f8000
+#define MSM8976_S10_P1_MASK 0xf8000000
+#define MSM8976_S10_P1_MASK_1 0x1
+
+#define MSM8976_S0_P2_MASK 0xfc000
+#define MSM8976_S1_P2_MASK 0xfc000000
+#define MSM8976_S2_P2_MASK 0xfc0
+#define MSM8976_S3_P2_MASK 0xfc0000
+#define MSM8976_S4_P2_MASK 0xfc000
+#define MSM8976_S5_P2_MASK 0xfc000000
+#define MSM8976_S6_P2_MASK 0xfc0
+#define MSM8976_S7_P2_MASK 0xfc0000
+#define MSM8976_S8_P2_MASK 0x7e00
+#define MSM8976_S9_P2_MASK 0x7e00000
+#define MSM8976_S10_P2_MASK 0x7e
+
+#define MSM8976_S0_P1_SHIFT 8
+#define MSM8976_S1_P1_SHIFT 20
+#define MSM8976_S2_P1_SHIFT 0
+#define MSM8976_S3_P1_SHIFT 12
+#define MSM8976_S4_P1_SHIFT 8
+#define MSM8976_S5_P1_SHIFT 20
+#define MSM8976_S6_P1_SHIFT 0
+#define MSM8976_S7_P1_SHIFT 12
+#define MSM8976_S8_P1_SHIFT 3
+#define MSM8976_S9_P1_SHIFT 15
+#define MSM8976_S10_P1_SHIFT 27
+#define MSM8976_S10_P1_SHIFT_1 0
+
+#define MSM8976_S0_P2_SHIFT 14
+#define MSM8976_S1_P2_SHIFT 26
+#define MSM8976_S2_P2_SHIFT 6
+#define MSM8976_S3_P2_SHIFT 18
+#define MSM8976_S4_P2_SHIFT 14
+#define MSM8976_S5_P2_SHIFT 26
+#define MSM8976_S6_P2_SHIFT 6
+#define MSM8976_S7_P2_SHIFT 18
+#define MSM8976_S8_P2_SHIFT 9
+#define MSM8976_S9_P2_SHIFT 21
+#define MSM8976_S10_P2_SHIFT 1
+
+#define MSM8976_CAL_SEL_MASK 0x3
+
+#define MSM8976_CAL_DEGC_PT1 30
+#define MSM8976_CAL_DEGC_PT2 120
+#define MSM8976_SLOPE_FACTOR 1000
+#define MSM8976_SLOPE_DEFAULT 3200
+
/* eeprom layout data for qcs404/405 (v1) */
#define BASE0_MASK 0x000007f8
#define BASE1_MASK 0x0007f800
@@ -79,6 +142,30 @@
#define CAL_SEL_MASK 7
#define CAL_SEL_SHIFT 0
+static void compute_intercept_slope_8976(struct tsens_priv *priv,
+ u32 *p1, u32 *p2, u32 mode)
+{
+ int i;
+
+ priv->sensor[0].slope = 3313;
+ priv->sensor[1].slope = 3275;
+ priv->sensor[2].slope = 3320;
+ priv->sensor[3].slope = 3246;
+ priv->sensor[4].slope = 3279;
+ priv->sensor[5].slope = 3257;
+ priv->sensor[6].slope = 3234;
+ priv->sensor[7].slope = 3269;
+ priv->sensor[8].slope = 3255;
+ priv->sensor[9].slope = 3239;
+ priv->sensor[10].slope = 3286;
+
+ for (i = 0; i < priv->num_sensors; i++) {
+ priv->sensor[i].offset = (p1[i] * MSM8976_SLOPE_FACTOR) -
+ (MSM8976_CAL_DEGC_PT1 *
+ priv->sensor[i].slope);
+ }
+}
+
static int calibrate_v1(struct tsens_priv *priv)
{
u32 base0 = 0, base1 = 0;
@@ -145,7 +232,74 @@ static int calibrate_v1(struct tsens_priv *priv)
return 0;
}
-/* v1.x: qcs404,405 */
+static int calibrate_8976(struct tsens_priv *priv)
+{
+ int base0 = 0, base1 = 0, i;
+ u32 p1[11], p2[11];
+ int mode = 0, tmp = 0;
+ u32 *qfprom_cdata;
+
+ qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib");
+ if (IS_ERR(qfprom_cdata)) {
+ kfree(qfprom_cdata);
+ return PTR_ERR(qfprom_cdata);
+ }
+
+ mode = (qfprom_cdata[4] & MSM8976_CAL_SEL_MASK);
+ dev_dbg(priv->dev, "calibration mode is %d\n", mode);
+
+ switch (mode) {
+ case TWO_PT_CALIB:
+ base1 = (qfprom_cdata[2] & MSM8976_BASE1_MASK) >> MSM8976_BASE1_SHIFT;
+ p2[0] = (qfprom_cdata[0] & MSM8976_S0_P2_MASK) >> MSM8976_S0_P2_SHIFT;
+ p2[1] = (qfprom_cdata[0] & MSM8976_S1_P2_MASK) >> MSM8976_S1_P2_SHIFT;
+ p2[2] = (qfprom_cdata[1] & MSM8976_S2_P2_MASK) >> MSM8976_S2_P2_SHIFT;
+ p2[3] = (qfprom_cdata[1] & MSM8976_S3_P2_MASK) >> MSM8976_S3_P2_SHIFT;
+ p2[4] = (qfprom_cdata[2] & MSM8976_S4_P2_MASK) >> MSM8976_S4_P2_SHIFT;
+ p2[5] = (qfprom_cdata[2] & MSM8976_S5_P2_MASK) >> MSM8976_S5_P2_SHIFT;
+ p2[6] = (qfprom_cdata[3] & MSM8976_S6_P2_MASK) >> MSM8976_S6_P2_SHIFT;
+ p2[7] = (qfprom_cdata[3] & MSM8976_S7_P2_MASK) >> MSM8976_S7_P2_SHIFT;
+ p2[8] = (qfprom_cdata[4] & MSM8976_S8_P2_MASK) >> MSM8976_S8_P2_SHIFT;
+ p2[9] = (qfprom_cdata[4] & MSM8976_S9_P2_MASK) >> MSM8976_S9_P2_SHIFT;
+ p2[10] = (qfprom_cdata[5] & MSM8976_S10_P2_MASK) >> MSM8976_S10_P2_SHIFT;
+
+ for (i = 0; i < priv->num_sensors; i++)
+ p2[i] = ((base1 + p2[i]) << 2);
+ /* Fall through */
+ case ONE_PT_CALIB2:
+ base0 = qfprom_cdata[0] & MSM8976_BASE0_MASK;
+ p1[0] = (qfprom_cdata[0] & MSM8976_S0_P1_MASK) >> MSM8976_S0_P1_SHIFT;
+ p1[1] = (qfprom_cdata[0] & MSM8976_S1_P1_MASK) >> MSM8976_S1_P1_SHIFT;
+ p1[2] = (qfprom_cdata[1] & MSM8976_S2_P1_MASK) >> MSM8976_S2_P1_SHIFT;
+ p1[3] = (qfprom_cdata[1] & MSM8976_S3_P1_MASK) >> MSM8976_S3_P1_SHIFT;
+ p1[4] = (qfprom_cdata[2] & MSM8976_S4_P1_MASK) >> MSM8976_S4_P1_SHIFT;
+ p1[5] = (qfprom_cdata[2] & MSM8976_S5_P1_MASK) >> MSM8976_S5_P1_SHIFT;
+ p1[6] = (qfprom_cdata[3] & MSM8976_S6_P1_MASK) >> MSM8976_S6_P1_SHIFT;
+ p1[7] = (qfprom_cdata[3] & MSM8976_S7_P1_MASK) >> MSM8976_S7_P1_SHIFT;
+ p1[8] = (qfprom_cdata[4] & MSM8976_S8_P1_MASK) >> MSM8976_S8_P1_SHIFT;
+ p1[9] = (qfprom_cdata[4] & MSM8976_S9_P1_MASK) >> MSM8976_S9_P1_SHIFT;
+ p1[10] = (qfprom_cdata[4] & MSM8976_S10_P1_MASK) >> MSM8976_S10_P1_SHIFT;
+ tmp = (qfprom_cdata[5] & MSM8976_S10_P1_MASK_1) << MSM8976_S10_P1_SHIFT_1;
+ p1[10] |= tmp;
+
+ for (i = 0; i < priv->num_sensors; i++)
+ p1[i] = (((base0) + p1[i]) << 2);
+ break;
+ default:
+ for (i = 0; i < priv->num_sensors; i++) {
+ p1[i] = 500;
+ p2[i] = 780;
+ }
+ break;
+ }
+
+ compute_intercept_slope_8976(priv, p1, p2, mode);
+ kfree(qfprom_cdata);
+
+ return 0;
+}
+
+/* v1.x: msm8956,8976,qcs404,405 */
static const struct tsens_features tsens_v1_feat = {
.ver_major = VER_1_X,
@@ -221,3 +375,18 @@ const struct tsens_plat_data data_tsens_v1 = {
.feat = &tsens_v1_feat,
.fields = tsens_v1_regfields,
};
+
+static const struct tsens_ops ops_8976 = {
+ .init = init_common,
+ .calibrate = calibrate_8976,
+ .get_temp = get_temp_tsens_valid,
+};
+
+/* Valid for both MSM8956 and MSM8976. Sensor ID 3 is unused. */
+const struct tsens_plat_data data_8976 = {
+ .num_sensors = 11,
+ .ops = &ops_8976,
+ .hw_ids = (unsigned int[]){0, 1, 2, 4, 5, 6, 7, 8, 9, 10},
+ .feat = &tsens_v1_feat,
+ .fields = tsens_v1_regfields,
+};