Merge remote-tracking branch 'regulator/for-next'
[deliverable/linux.git] / drivers / thermal / qcom / tsens-8960.c
1 /*
2 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15 #include <linux/platform_device.h>
16 #include <linux/delay.h>
17 #include <linux/bitops.h>
18 #include <linux/regmap.h>
19 #include <linux/thermal.h>
20 #include "tsens.h"
21
22 #define CAL_MDEGC 30000
23
24 #define CONFIG_ADDR 0x3640
25 #define CONFIG_ADDR_8660 0x3620
26 /* CONFIG_ADDR bitmasks */
27 #define CONFIG 0x9b
28 #define CONFIG_MASK 0xf
29 #define CONFIG_8660 1
30 #define CONFIG_SHIFT_8660 28
31 #define CONFIG_MASK_8660 (3 << CONFIG_SHIFT_8660)
32
33 #define STATUS_CNTL_ADDR_8064 0x3660
34 #define CNTL_ADDR 0x3620
35 /* CNTL_ADDR bitmasks */
36 #define EN BIT(0)
37 #define SW_RST BIT(1)
38 #define SENSOR0_EN BIT(3)
39 #define SLP_CLK_ENA BIT(26)
40 #define SLP_CLK_ENA_8660 BIT(24)
41 #define MEASURE_PERIOD 1
42 #define SENSOR0_SHIFT 3
43
44 /* INT_STATUS_ADDR bitmasks */
45 #define MIN_STATUS_MASK BIT(0)
46 #define LOWER_STATUS_CLR BIT(1)
47 #define UPPER_STATUS_CLR BIT(2)
48 #define MAX_STATUS_MASK BIT(3)
49
50 #define THRESHOLD_ADDR 0x3624
51 /* THRESHOLD_ADDR bitmasks */
52 #define THRESHOLD_MAX_LIMIT_SHIFT 24
53 #define THRESHOLD_MIN_LIMIT_SHIFT 16
54 #define THRESHOLD_UPPER_LIMIT_SHIFT 8
55 #define THRESHOLD_LOWER_LIMIT_SHIFT 0
56
57 /* Initial temperature threshold values */
58 #define LOWER_LIMIT_TH 0x50
59 #define UPPER_LIMIT_TH 0xdf
60 #define MIN_LIMIT_TH 0x0
61 #define MAX_LIMIT_TH 0xff
62
63 #define S0_STATUS_ADDR 0x3628
64 #define INT_STATUS_ADDR 0x363c
65 #define TRDY_MASK BIT(7)
66 #define TIMEOUT_US 100
67
68 static int suspend_8960(struct tsens_device *tmdev)
69 {
70 int ret;
71 unsigned int mask;
72 struct regmap *map = tmdev->map;
73
74 ret = regmap_read(map, THRESHOLD_ADDR, &tmdev->ctx.threshold);
75 if (ret)
76 return ret;
77
78 ret = regmap_read(map, CNTL_ADDR, &tmdev->ctx.control);
79 if (ret)
80 return ret;
81
82 if (tmdev->num_sensors > 1)
83 mask = SLP_CLK_ENA | EN;
84 else
85 mask = SLP_CLK_ENA_8660 | EN;
86
87 ret = regmap_update_bits(map, CNTL_ADDR, mask, 0);
88 if (ret)
89 return ret;
90
91 return 0;
92 }
93
94 static int resume_8960(struct tsens_device *tmdev)
95 {
96 int ret;
97 struct regmap *map = tmdev->map;
98
99 ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST);
100 if (ret)
101 return ret;
102
103 /*
104 * Separate CONFIG restore is not needed only for 8660 as
105 * config is part of CTRL Addr and its restored as such
106 */
107 if (tmdev->num_sensors > 1) {
108 ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG);
109 if (ret)
110 return ret;
111 }
112
113 ret = regmap_write(map, THRESHOLD_ADDR, tmdev->ctx.threshold);
114 if (ret)
115 return ret;
116
117 ret = regmap_write(map, CNTL_ADDR, tmdev->ctx.control);
118 if (ret)
119 return ret;
120
121 return 0;
122 }
123
124 static int enable_8960(struct tsens_device *tmdev, int id)
125 {
126 int ret;
127 u32 reg, mask;
128
129 ret = regmap_read(tmdev->map, CNTL_ADDR, &reg);
130 if (ret)
131 return ret;
132
133 mask = BIT(id + SENSOR0_SHIFT);
134 ret = regmap_write(tmdev->map, CNTL_ADDR, reg | SW_RST);
135 if (ret)
136 return ret;
137
138 if (tmdev->num_sensors > 1)
139 reg |= mask | SLP_CLK_ENA | EN;
140 else
141 reg |= mask | SLP_CLK_ENA_8660 | EN;
142
143 ret = regmap_write(tmdev->map, CNTL_ADDR, reg);
144 if (ret)
145 return ret;
146
147 return 0;
148 }
149
150 static void disable_8960(struct tsens_device *tmdev)
151 {
152 int ret;
153 u32 reg_cntl;
154 u32 mask;
155
156 mask = GENMASK(tmdev->num_sensors - 1, 0);
157 mask <<= SENSOR0_SHIFT;
158 mask |= EN;
159
160 ret = regmap_read(tmdev->map, CNTL_ADDR, &reg_cntl);
161 if (ret)
162 return;
163
164 reg_cntl &= ~mask;
165
166 if (tmdev->num_sensors > 1)
167 reg_cntl &= ~SLP_CLK_ENA;
168 else
169 reg_cntl &= ~SLP_CLK_ENA_8660;
170
171 regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
172 }
173
174 static int init_8960(struct tsens_device *tmdev)
175 {
176 int ret, i;
177 u32 reg_cntl;
178
179 tmdev->map = dev_get_regmap(tmdev->dev, NULL);
180 if (!tmdev->map)
181 return -ENODEV;
182
183 /*
184 * The status registers for each sensor are discontiguous
185 * because some SoCs have 5 sensors while others have more
186 * but the control registers stay in the same place, i.e
187 * directly after the first 5 status registers.
188 */
189 for (i = 0; i < tmdev->num_sensors; i++) {
190 if (i >= 5)
191 tmdev->sensor[i].status = S0_STATUS_ADDR + 40;
192 tmdev->sensor[i].status += i * 4;
193 }
194
195 reg_cntl = SW_RST;
196 ret = regmap_update_bits(tmdev->map, CNTL_ADDR, SW_RST, reg_cntl);
197 if (ret)
198 return ret;
199
200 if (tmdev->num_sensors > 1) {
201 reg_cntl |= SLP_CLK_ENA | (MEASURE_PERIOD << 18);
202 reg_cntl &= ~SW_RST;
203 ret = regmap_update_bits(tmdev->map, CONFIG_ADDR,
204 CONFIG_MASK, CONFIG);
205 } else {
206 reg_cntl |= SLP_CLK_ENA_8660 | (MEASURE_PERIOD << 16);
207 reg_cntl &= ~CONFIG_MASK_8660;
208 reg_cntl |= CONFIG_8660 << CONFIG_SHIFT_8660;
209 }
210
211 reg_cntl |= GENMASK(tmdev->num_sensors - 1, 0) << SENSOR0_SHIFT;
212 ret = regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
213 if (ret)
214 return ret;
215
216 reg_cntl |= EN;
217 ret = regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
218 if (ret)
219 return ret;
220
221 return 0;
222 }
223
224 static int calibrate_8960(struct tsens_device *tmdev)
225 {
226 int i;
227 char *data;
228
229 ssize_t num_read = tmdev->num_sensors;
230 struct tsens_sensor *s = tmdev->sensor;
231
232 data = qfprom_read(tmdev->dev, "calib");
233 if (IS_ERR(data))
234 data = qfprom_read(tmdev->dev, "calib_backup");
235 if (IS_ERR(data))
236 return PTR_ERR(data);
237
238 for (i = 0; i < num_read; i++, s++)
239 s->offset = data[i];
240
241 return 0;
242 }
243
244 /* Temperature on y axis and ADC-code on x-axis */
245 static inline int code_to_mdegC(u32 adc_code, const struct tsens_sensor *s)
246 {
247 int slope, offset;
248
249 slope = thermal_zone_get_slope(s->tzd);
250 offset = CAL_MDEGC - slope * s->offset;
251
252 return adc_code * slope + offset;
253 }
254
255 static int get_temp_8960(struct tsens_device *tmdev, int id, int *temp)
256 {
257 int ret;
258 u32 code, trdy;
259 const struct tsens_sensor *s = &tmdev->sensor[id];
260 unsigned long timeout;
261
262 timeout = jiffies + usecs_to_jiffies(TIMEOUT_US);
263 do {
264 ret = regmap_read(tmdev->map, INT_STATUS_ADDR, &trdy);
265 if (ret)
266 return ret;
267 if (!(trdy & TRDY_MASK))
268 continue;
269 ret = regmap_read(tmdev->map, s->status, &code);
270 if (ret)
271 return ret;
272 *temp = code_to_mdegC(code, s);
273 return 0;
274 } while (time_before(jiffies, timeout));
275
276 return -ETIMEDOUT;
277 }
278
279 static const struct tsens_ops ops_8960 = {
280 .init = init_8960,
281 .calibrate = calibrate_8960,
282 .get_temp = get_temp_8960,
283 .enable = enable_8960,
284 .disable = disable_8960,
285 .suspend = suspend_8960,
286 .resume = resume_8960,
287 };
288
289 const struct tsens_data data_8960 = {
290 .num_sensors = 11,
291 .ops = &ops_8960,
292 };
This page took 0.046522 seconds and 5 git commands to generate.