ipq806x: add thermal sensor driver
[openwrt/openwrt.git] / target / linux / ipq806x / patches-4.4 / 015-3-thermal-qcom-tsens-8974-Add-support-for-8974-family-of-SoCs.patch
1 From 5e6703bd2d83548998848865cb9a9a795f31a311 Mon Sep 17 00:00:00 2001
2 From: Rajendra Nayak <rnayak@codeaurora.org>
3 Date: Thu, 5 May 2016 14:21:41 +0530
4 Subject: thermal: qcom: tsens-8974: Add support for 8974 family of SoCs
5
6 Add .calibrate support for 8974 family as part of tsens_ops.
7
8 Based on the original code by Siddartha Mohanadoss and Stephen Boyd.
9
10 Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
11 Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
12 Signed-off-by: Zhang Rui <rui.zhang@intel.com>
13 ---
14 drivers/thermal/qcom/Makefile | 2 +-
15 drivers/thermal/qcom/tsens-8974.c | 244 ++++++++++++++++++++++++++++++++++++++
16 drivers/thermal/qcom/tsens.c | 1 +
17 drivers/thermal/qcom/tsens.h | 2 +-
18 4 files changed, 247 insertions(+), 2 deletions(-)
19 create mode 100644 drivers/thermal/qcom/tsens-8974.c
20
21 --- a/drivers/thermal/qcom/Makefile
22 +++ b/drivers/thermal/qcom/Makefile
23 @@ -1,2 +1,2 @@
24 obj-$(CONFIG_QCOM_TSENS) += qcom_tsens.o
25 -qcom_tsens-y += tsens.o tsens-common.o tsens-8916.o
26 +qcom_tsens-y += tsens.o tsens-common.o tsens-8916.o tsens-8974.o
27 --- /dev/null
28 +++ b/drivers/thermal/qcom/tsens-8974.c
29 @@ -0,0 +1,244 @@
30 +/*
31 + * Copyright (c) 2015, The Linux Foundation. All rights reserved.
32 + *
33 + * This program is free software; you can redistribute it and/or modify
34 + * it under the terms of the GNU General Public License version 2 and
35 + * only version 2 as published by the Free Software Foundation.
36 + *
37 + * This program is distributed in the hope that it will be useful,
38 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
39 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40 + * GNU General Public License for more details.
41 + *
42 + */
43 +
44 +#include <linux/platform_device.h>
45 +#include "tsens.h"
46 +
47 +/* eeprom layout data for 8974 */
48 +#define BASE1_MASK 0xff
49 +#define S0_P1_MASK 0x3f00
50 +#define S1_P1_MASK 0xfc000
51 +#define S2_P1_MASK 0x3f00000
52 +#define S3_P1_MASK 0xfc000000
53 +#define S4_P1_MASK 0x3f
54 +#define S5_P1_MASK 0xfc0
55 +#define S6_P1_MASK 0x3f000
56 +#define S7_P1_MASK 0xfc0000
57 +#define S8_P1_MASK 0x3f000000
58 +#define S8_P1_MASK_BKP 0x3f
59 +#define S9_P1_MASK 0x3f
60 +#define S9_P1_MASK_BKP 0xfc0
61 +#define S10_P1_MASK 0xfc0
62 +#define S10_P1_MASK_BKP 0x3f000
63 +#define CAL_SEL_0_1 0xc0000000
64 +#define CAL_SEL_2 0x40000000
65 +#define CAL_SEL_SHIFT 30
66 +#define CAL_SEL_SHIFT_2 28
67 +
68 +#define S0_P1_SHIFT 8
69 +#define S1_P1_SHIFT 14
70 +#define S2_P1_SHIFT 20
71 +#define S3_P1_SHIFT 26
72 +#define S5_P1_SHIFT 6
73 +#define S6_P1_SHIFT 12
74 +#define S7_P1_SHIFT 18
75 +#define S8_P1_SHIFT 24
76 +#define S9_P1_BKP_SHIFT 6
77 +#define S10_P1_SHIFT 6
78 +#define S10_P1_BKP_SHIFT 12
79 +
80 +#define BASE2_SHIFT 12
81 +#define BASE2_BKP_SHIFT 18
82 +#define S0_P2_SHIFT 20
83 +#define S0_P2_BKP_SHIFT 26
84 +#define S1_P2_SHIFT 26
85 +#define S2_P2_BKP_SHIFT 6
86 +#define S3_P2_SHIFT 6
87 +#define S3_P2_BKP_SHIFT 12
88 +#define S4_P2_SHIFT 12
89 +#define S4_P2_BKP_SHIFT 18
90 +#define S5_P2_SHIFT 18
91 +#define S5_P2_BKP_SHIFT 24
92 +#define S6_P2_SHIFT 24
93 +#define S7_P2_BKP_SHIFT 6
94 +#define S8_P2_SHIFT 6
95 +#define S8_P2_BKP_SHIFT 12
96 +#define S9_P2_SHIFT 12
97 +#define S9_P2_BKP_SHIFT 18
98 +#define S10_P2_SHIFT 18
99 +#define S10_P2_BKP_SHIFT 24
100 +
101 +#define BASE2_MASK 0xff000
102 +#define BASE2_BKP_MASK 0xfc0000
103 +#define S0_P2_MASK 0x3f00000
104 +#define S0_P2_BKP_MASK 0xfc000000
105 +#define S1_P2_MASK 0xfc000000
106 +#define S1_P2_BKP_MASK 0x3f
107 +#define S2_P2_MASK 0x3f
108 +#define S2_P2_BKP_MASK 0xfc0
109 +#define S3_P2_MASK 0xfc0
110 +#define S3_P2_BKP_MASK 0x3f000
111 +#define S4_P2_MASK 0x3f000
112 +#define S4_P2_BKP_MASK 0xfc0000
113 +#define S5_P2_MASK 0xfc0000
114 +#define S5_P2_BKP_MASK 0x3f000000
115 +#define S6_P2_MASK 0x3f000000
116 +#define S6_P2_BKP_MASK 0x3f
117 +#define S7_P2_MASK 0x3f
118 +#define S7_P2_BKP_MASK 0xfc0
119 +#define S8_P2_MASK 0xfc0
120 +#define S8_P2_BKP_MASK 0x3f000
121 +#define S9_P2_MASK 0x3f000
122 +#define S9_P2_BKP_MASK 0xfc0000
123 +#define S10_P2_MASK 0xfc0000
124 +#define S10_P2_BKP_MASK 0x3f000000
125 +
126 +#define BKP_SEL 0x3
127 +#define BKP_REDUN_SEL 0xe0000000
128 +#define BKP_REDUN_SHIFT 29
129 +
130 +#define BIT_APPEND 0x3
131 +
132 +static int calibrate_8974(struct tsens_device *tmdev)
133 +{
134 + int base1 = 0, base2 = 0, i;
135 + u32 p1[11], p2[11];
136 + int mode = 0;
137 + u32 *calib, *bkp;
138 + u32 calib_redun_sel;
139 +
140 + calib = (u32 *)qfprom_read(tmdev->dev, "calib");
141 + if (IS_ERR(calib))
142 + return PTR_ERR(calib);
143 +
144 + bkp = (u32 *)qfprom_read(tmdev->dev, "calib_backup");
145 + if (IS_ERR(bkp))
146 + return PTR_ERR(bkp);
147 +
148 + calib_redun_sel = bkp[1] & BKP_REDUN_SEL;
149 + calib_redun_sel >>= BKP_REDUN_SHIFT;
150 +
151 + if (calib_redun_sel == BKP_SEL) {
152 + mode = (calib[4] & CAL_SEL_0_1) >> CAL_SEL_SHIFT;
153 + mode |= (calib[5] & CAL_SEL_2) >> CAL_SEL_SHIFT_2;
154 +
155 + switch (mode) {
156 + case TWO_PT_CALIB:
157 + base2 = (bkp[2] & BASE2_BKP_MASK) >> BASE2_BKP_SHIFT;
158 + p2[0] = (bkp[2] & S0_P2_BKP_MASK) >> S0_P2_BKP_SHIFT;
159 + p2[1] = (bkp[3] & S1_P2_BKP_MASK);
160 + p2[2] = (bkp[3] & S2_P2_BKP_MASK) >> S2_P2_BKP_SHIFT;
161 + p2[3] = (bkp[3] & S3_P2_BKP_MASK) >> S3_P2_BKP_SHIFT;
162 + p2[4] = (bkp[3] & S4_P2_BKP_MASK) >> S4_P2_BKP_SHIFT;
163 + p2[5] = (calib[4] & S5_P2_BKP_MASK) >> S5_P2_BKP_SHIFT;
164 + p2[6] = (calib[5] & S6_P2_BKP_MASK);
165 + p2[7] = (calib[5] & S7_P2_BKP_MASK) >> S7_P2_BKP_SHIFT;
166 + p2[8] = (calib[5] & S8_P2_BKP_MASK) >> S8_P2_BKP_SHIFT;
167 + p2[9] = (calib[5] & S9_P2_BKP_MASK) >> S9_P2_BKP_SHIFT;
168 + p2[10] = (calib[5] & S10_P2_BKP_MASK) >> S10_P2_BKP_SHIFT;
169 + /* Fall through */
170 + case ONE_PT_CALIB:
171 + case ONE_PT_CALIB2:
172 + base1 = bkp[0] & BASE1_MASK;
173 + p1[0] = (bkp[0] & S0_P1_MASK) >> S0_P1_SHIFT;
174 + p1[1] = (bkp[0] & S1_P1_MASK) >> S1_P1_SHIFT;
175 + p1[2] = (bkp[0] & S2_P1_MASK) >> S2_P1_SHIFT;
176 + p1[3] = (bkp[0] & S3_P1_MASK) >> S3_P1_SHIFT;
177 + p1[4] = (bkp[1] & S4_P1_MASK);
178 + p1[5] = (bkp[1] & S5_P1_MASK) >> S5_P1_SHIFT;
179 + p1[6] = (bkp[1] & S6_P1_MASK) >> S6_P1_SHIFT;
180 + p1[7] = (bkp[1] & S7_P1_MASK) >> S7_P1_SHIFT;
181 + p1[8] = (bkp[2] & S8_P1_MASK_BKP) >> S8_P1_SHIFT;
182 + p1[9] = (bkp[2] & S9_P1_MASK_BKP) >> S9_P1_BKP_SHIFT;
183 + p1[10] = (bkp[2] & S10_P1_MASK_BKP) >> S10_P1_BKP_SHIFT;
184 + break;
185 + }
186 + } else {
187 + mode = (calib[1] & CAL_SEL_0_1) >> CAL_SEL_SHIFT;
188 + mode |= (calib[3] & CAL_SEL_2) >> CAL_SEL_SHIFT_2;
189 +
190 + switch (mode) {
191 + case TWO_PT_CALIB:
192 + base2 = (calib[2] & BASE2_MASK) >> BASE2_SHIFT;
193 + p2[0] = (calib[2] & S0_P2_MASK) >> S0_P2_SHIFT;
194 + p2[1] = (calib[2] & S1_P2_MASK) >> S1_P2_SHIFT;
195 + p2[2] = (calib[3] & S2_P2_MASK);
196 + p2[3] = (calib[3] & S3_P2_MASK) >> S3_P2_SHIFT;
197 + p2[4] = (calib[3] & S4_P2_MASK) >> S4_P2_SHIFT;
198 + p2[5] = (calib[3] & S5_P2_MASK) >> S5_P2_SHIFT;
199 + p2[6] = (calib[3] & S6_P2_MASK) >> S6_P2_SHIFT;
200 + p2[7] = (calib[4] & S7_P2_MASK);
201 + p2[8] = (calib[4] & S8_P2_MASK) >> S8_P2_SHIFT;
202 + p2[9] = (calib[4] & S9_P2_MASK) >> S9_P2_SHIFT;
203 + p2[10] = (calib[4] & S10_P2_MASK) >> S10_P2_SHIFT;
204 + /* Fall through */
205 + case ONE_PT_CALIB:
206 + case ONE_PT_CALIB2:
207 + base1 = calib[0] & BASE1_MASK;
208 + p1[0] = (calib[0] & S0_P1_MASK) >> S0_P1_SHIFT;
209 + p1[1] = (calib[0] & S1_P1_MASK) >> S1_P1_SHIFT;
210 + p1[2] = (calib[0] & S2_P1_MASK) >> S2_P1_SHIFT;
211 + p1[3] = (calib[0] & S3_P1_MASK) >> S3_P1_SHIFT;
212 + p1[4] = (calib[1] & S4_P1_MASK);
213 + p1[5] = (calib[1] & S5_P1_MASK) >> S5_P1_SHIFT;
214 + p1[6] = (calib[1] & S6_P1_MASK) >> S6_P1_SHIFT;
215 + p1[7] = (calib[1] & S7_P1_MASK) >> S7_P1_SHIFT;
216 + p1[8] = (calib[1] & S8_P1_MASK) >> S8_P1_SHIFT;
217 + p1[9] = (calib[2] & S9_P1_MASK);
218 + p1[10] = (calib[2] & S10_P1_MASK) >> S10_P1_SHIFT;
219 + break;
220 + }
221 + }
222 +
223 + switch (mode) {
224 + case ONE_PT_CALIB:
225 + for (i = 0; i < tmdev->num_sensors; i++)
226 + p1[i] += (base1 << 2) | BIT_APPEND;
227 + break;
228 + case TWO_PT_CALIB:
229 + for (i = 0; i < tmdev->num_sensors; i++) {
230 + p2[i] += base2;
231 + p2[i] <<= 2;
232 + p2[i] |= BIT_APPEND;
233 + }
234 + /* Fall through */
235 + case ONE_PT_CALIB2:
236 + for (i = 0; i < tmdev->num_sensors; i++) {
237 + p1[i] += base1;
238 + p1[i] <<= 2;
239 + p1[i] |= BIT_APPEND;
240 + }
241 + break;
242 + default:
243 + for (i = 0; i < tmdev->num_sensors; i++)
244 + p2[i] = 780;
245 + p1[0] = 502;
246 + p1[1] = 509;
247 + p1[2] = 503;
248 + p1[3] = 509;
249 + p1[4] = 505;
250 + p1[5] = 509;
251 + p1[6] = 507;
252 + p1[7] = 510;
253 + p1[8] = 508;
254 + p1[9] = 509;
255 + p1[10] = 508;
256 + break;
257 + }
258 +
259 + compute_intercept_slope(tmdev, p1, p2, mode);
260 +
261 + return 0;
262 +}
263 +
264 +const struct tsens_ops ops_8974 = {
265 + .init = init_common,
266 + .calibrate = calibrate_8974,
267 + .get_temp = get_temp_common,
268 +};
269 +
270 +const struct tsens_data data_8974 = {
271 + .num_sensors = 11,
272 + .ops = &ops_8974,
273 +};
274 --- a/drivers/thermal/qcom/tsens.c
275 +++ b/drivers/thermal/qcom/tsens.c
276 @@ -68,6 +68,7 @@ static const struct of_device_id tsens_t
277 .data = &data_8916,
278 }, {
279 .compatible = "qcom,msm8974-tsens",
280 + .data = &data_8974,
281 },
282 {}
283 };
284 --- a/drivers/thermal/qcom/tsens.h
285 +++ b/drivers/thermal/qcom/tsens.h
286 @@ -87,6 +87,6 @@ void compute_intercept_slope(struct tsen
287 int init_common(struct tsens_device *);
288 int get_temp_common(struct tsens_device *, int, int *);
289
290 -extern const struct tsens_data data_8916;
291 +extern const struct tsens_data data_8916, data_8974;
292
293 #endif /* __QCOM_TSENS_H__ */