Merge tag 'modules-for-v5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu...
[linux-2.6-block.git] / drivers / thermal / qcom / tsens-v1.c
CommitLineData
e8c24c6f
AK
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2019, Linaro Limited
4 */
5
6#include <linux/bitops.h>
7#include <linux/regmap.h>
8#include <linux/delay.h>
9#include "tsens.h"
10
11/* ----- SROT ------ */
12#define SROT_HW_VER_OFF 0x0000
13#define SROT_CTRL_OFF 0x0004
14
15/* ----- TM ------ */
16#define TM_INT_EN_OFF 0x0000
17#define TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF 0x0004
18#define TM_Sn_STATUS_OFF 0x0044
19#define TM_TRDY_OFF 0x0084
20
21/* eeprom layout data for qcs404/405 (v1) */
22#define BASE0_MASK 0x000007f8
23#define BASE1_MASK 0x0007f800
24#define BASE0_SHIFT 3
25#define BASE1_SHIFT 11
26
27#define S0_P1_MASK 0x0000003f
28#define S1_P1_MASK 0x0003f000
29#define S2_P1_MASK 0x3f000000
30#define S3_P1_MASK 0x000003f0
31#define S4_P1_MASK 0x003f0000
32#define S5_P1_MASK 0x0000003f
33#define S6_P1_MASK 0x0003f000
34#define S7_P1_MASK 0x3f000000
35#define S8_P1_MASK 0x000003f0
36#define S9_P1_MASK 0x003f0000
37
38#define S0_P2_MASK 0x00000fc0
39#define S1_P2_MASK 0x00fc0000
40#define S2_P2_MASK_1_0 0xc0000000
41#define S2_P2_MASK_5_2 0x0000000f
42#define S3_P2_MASK 0x0000fc00
43#define S4_P2_MASK 0x0fc00000
44#define S5_P2_MASK 0x00000fc0
45#define S6_P2_MASK 0x00fc0000
46#define S7_P2_MASK_1_0 0xc0000000
47#define S7_P2_MASK_5_2 0x0000000f
48#define S8_P2_MASK 0x0000fc00
49#define S9_P2_MASK 0x0fc00000
50
51#define S0_P1_SHIFT 0
52#define S0_P2_SHIFT 6
53#define S1_P1_SHIFT 12
54#define S1_P2_SHIFT 18
55#define S2_P1_SHIFT 24
56#define S2_P2_SHIFT_1_0 30
57
58#define S2_P2_SHIFT_5_2 0
59#define S3_P1_SHIFT 4
60#define S3_P2_SHIFT 10
61#define S4_P1_SHIFT 16
62#define S4_P2_SHIFT 22
63
64#define S5_P1_SHIFT 0
65#define S5_P2_SHIFT 6
66#define S6_P1_SHIFT 12
67#define S6_P2_SHIFT 18
68#define S7_P1_SHIFT 24
69#define S7_P2_SHIFT_1_0 30
70
71#define S7_P2_SHIFT_5_2 0
72#define S8_P1_SHIFT 4
73#define S8_P2_SHIFT 10
74#define S9_P1_SHIFT 16
75#define S9_P2_SHIFT 22
76
77#define CAL_SEL_MASK 7
78#define CAL_SEL_SHIFT 0
79
80static int calibrate_v1(struct tsens_priv *priv)
81{
82 u32 base0 = 0, base1 = 0;
83 u32 p1[10], p2[10];
84 u32 mode = 0, lsb = 0, msb = 0;
85 u32 *qfprom_cdata;
86 int i;
87
88 qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib");
89 if (IS_ERR(qfprom_cdata))
90 return PTR_ERR(qfprom_cdata);
91
92 mode = (qfprom_cdata[4] & CAL_SEL_MASK) >> CAL_SEL_SHIFT;
93 dev_dbg(priv->dev, "calibration mode is %d\n", mode);
94
95 switch (mode) {
96 case TWO_PT_CALIB:
97 base1 = (qfprom_cdata[4] & BASE1_MASK) >> BASE1_SHIFT;
98 p2[0] = (qfprom_cdata[0] & S0_P2_MASK) >> S0_P2_SHIFT;
99 p2[1] = (qfprom_cdata[0] & S1_P2_MASK) >> S1_P2_SHIFT;
100 /* This value is split over two registers, 2 bits and 4 bits */
101 lsb = (qfprom_cdata[0] & S2_P2_MASK_1_0) >> S2_P2_SHIFT_1_0;
102 msb = (qfprom_cdata[1] & S2_P2_MASK_5_2) >> S2_P2_SHIFT_5_2;
103 p2[2] = msb << 2 | lsb;
104 p2[3] = (qfprom_cdata[1] & S3_P2_MASK) >> S3_P2_SHIFT;
105 p2[4] = (qfprom_cdata[1] & S4_P2_MASK) >> S4_P2_SHIFT;
106 p2[5] = (qfprom_cdata[2] & S5_P2_MASK) >> S5_P2_SHIFT;
107 p2[6] = (qfprom_cdata[2] & S6_P2_MASK) >> S6_P2_SHIFT;
108 /* This value is split over two registers, 2 bits and 4 bits */
109 lsb = (qfprom_cdata[2] & S7_P2_MASK_1_0) >> S7_P2_SHIFT_1_0;
110 msb = (qfprom_cdata[3] & S7_P2_MASK_5_2) >> S7_P2_SHIFT_5_2;
111 p2[7] = msb << 2 | lsb;
112 p2[8] = (qfprom_cdata[3] & S8_P2_MASK) >> S8_P2_SHIFT;
113 p2[9] = (qfprom_cdata[3] & S9_P2_MASK) >> S9_P2_SHIFT;
114 for (i = 0; i < priv->num_sensors; i++)
115 p2[i] = ((base1 + p2[i]) << 2);
116 /* Fall through */
117 case ONE_PT_CALIB2:
118 base0 = (qfprom_cdata[4] & BASE0_MASK) >> BASE0_SHIFT;
119 p1[0] = (qfprom_cdata[0] & S0_P1_MASK) >> S0_P1_SHIFT;
120 p1[1] = (qfprom_cdata[0] & S1_P1_MASK) >> S1_P1_SHIFT;
121 p1[2] = (qfprom_cdata[0] & S2_P1_MASK) >> S2_P1_SHIFT;
122 p1[3] = (qfprom_cdata[1] & S3_P1_MASK) >> S3_P1_SHIFT;
123 p1[4] = (qfprom_cdata[1] & S4_P1_MASK) >> S4_P1_SHIFT;
124 p1[5] = (qfprom_cdata[2] & S5_P1_MASK) >> S5_P1_SHIFT;
125 p1[6] = (qfprom_cdata[2] & S6_P1_MASK) >> S6_P1_SHIFT;
126 p1[7] = (qfprom_cdata[2] & S7_P1_MASK) >> S7_P1_SHIFT;
127 p1[8] = (qfprom_cdata[3] & S8_P1_MASK) >> S8_P1_SHIFT;
128 p1[9] = (qfprom_cdata[3] & S9_P1_MASK) >> S9_P1_SHIFT;
129 for (i = 0; i < priv->num_sensors; i++)
130 p1[i] = (((base0) + p1[i]) << 2);
131 break;
132 default:
133 for (i = 0; i < priv->num_sensors; i++) {
134 p1[i] = 500;
135 p2[i] = 780;
136 }
137 break;
138 }
139
140 compute_intercept_slope(priv, p1, p2, mode);
141
142 return 0;
143}
144
145/* v1.x: qcs404,405 */
146
147static const struct tsens_features tsens_v1_feat = {
148 .ver_major = VER_1_X,
149 .crit_int = 0,
150 .adc = 1,
151 .srot_split = 1,
152 .max_sensors = 11,
153};
154
155static const struct reg_field tsens_v1_regfields[MAX_REGFIELDS] = {
156 /* ----- SROT ------ */
157 /* VERSION */
158 [VER_MAJOR] = REG_FIELD(SROT_HW_VER_OFF, 28, 31),
159 [VER_MINOR] = REG_FIELD(SROT_HW_VER_OFF, 16, 27),
160 [VER_STEP] = REG_FIELD(SROT_HW_VER_OFF, 0, 15),
161 /* CTRL_OFFSET */
162 [TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0),
163 [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1),
164 [SENSOR_EN] = REG_FIELD(SROT_CTRL_OFF, 3, 13),
165
166 /* ----- TM ------ */
167 /* INTERRUPT ENABLE */
168 [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 0),
169
170 /* Sn_STATUS */
171 REG_FIELD_FOR_EACH_SENSOR11(LAST_TEMP, TM_Sn_STATUS_OFF, 0, 9),
172 REG_FIELD_FOR_EACH_SENSOR11(VALID, TM_Sn_STATUS_OFF, 14, 14),
173 REG_FIELD_FOR_EACH_SENSOR11(MIN_STATUS, TM_Sn_STATUS_OFF, 10, 10),
174 REG_FIELD_FOR_EACH_SENSOR11(LOWER_STATUS, TM_Sn_STATUS_OFF, 11, 11),
175 REG_FIELD_FOR_EACH_SENSOR11(UPPER_STATUS, TM_Sn_STATUS_OFF, 12, 12),
176 /* No CRITICAL field on v1.x */
177 REG_FIELD_FOR_EACH_SENSOR11(MAX_STATUS, TM_Sn_STATUS_OFF, 13, 13),
178
179 /* TRDY: 1=ready, 0=in progress */
180 [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0),
181};
182
183static const struct tsens_ops ops_generic_v1 = {
184 .init = init_common,
185 .calibrate = calibrate_v1,
186 .get_temp = get_temp_tsens_valid,
187};
188
189const struct tsens_plat_data data_tsens_v1 = {
190 .ops = &ops_generic_v1,
191 .feat = &tsens_v1_feat,
192 .fields = tsens_v1_regfields,
193};