671f461057cf404301d50667d136b8b34808e519
[librecmc/librecmc.git] /
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__ */