Linux 4.9.74
[linux/fpc-iii.git] / drivers / thermal / qcom / tsens-8960.c
blob0451277d3a8f0fbb8246d550e887d9a5678668a3
1 /*
2 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
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.
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.
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"
22 #define CAL_MDEGC 30000
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)
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
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)
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
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
63 #define S0_STATUS_ADDR 0x3628
64 #define INT_STATUS_ADDR 0x363c
65 #define TRDY_MASK BIT(7)
66 #define TIMEOUT_US 100
68 static int suspend_8960(struct tsens_device *tmdev)
70 int ret;
71 unsigned int mask;
72 struct regmap *map = tmdev->map;
74 ret = regmap_read(map, THRESHOLD_ADDR, &tmdev->ctx.threshold);
75 if (ret)
76 return ret;
78 ret = regmap_read(map, CNTL_ADDR, &tmdev->ctx.control);
79 if (ret)
80 return ret;
82 if (tmdev->num_sensors > 1)
83 mask = SLP_CLK_ENA | EN;
84 else
85 mask = SLP_CLK_ENA_8660 | EN;
87 ret = regmap_update_bits(map, CNTL_ADDR, mask, 0);
88 if (ret)
89 return ret;
91 return 0;
94 static int resume_8960(struct tsens_device *tmdev)
96 int ret;
97 struct regmap *map = tmdev->map;
99 ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST);
100 if (ret)
101 return ret;
104 * Separate CONFIG restore is not needed only for 8660 as
105 * config is part of CTRL Addr and its restored as such
107 if (tmdev->num_sensors > 1) {
108 ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG);
109 if (ret)
110 return ret;
113 ret = regmap_write(map, THRESHOLD_ADDR, tmdev->ctx.threshold);
114 if (ret)
115 return ret;
117 ret = regmap_write(map, CNTL_ADDR, tmdev->ctx.control);
118 if (ret)
119 return ret;
121 return 0;
124 static int enable_8960(struct tsens_device *tmdev, int id)
126 int ret;
127 u32 reg, mask;
129 ret = regmap_read(tmdev->map, CNTL_ADDR, &reg);
130 if (ret)
131 return ret;
133 mask = BIT(id + SENSOR0_SHIFT);
134 ret = regmap_write(tmdev->map, CNTL_ADDR, reg | SW_RST);
135 if (ret)
136 return ret;
138 if (tmdev->num_sensors > 1)
139 reg |= mask | SLP_CLK_ENA | EN;
140 else
141 reg |= mask | SLP_CLK_ENA_8660 | EN;
143 ret = regmap_write(tmdev->map, CNTL_ADDR, reg);
144 if (ret)
145 return ret;
147 return 0;
150 static void disable_8960(struct tsens_device *tmdev)
152 int ret;
153 u32 reg_cntl;
154 u32 mask;
156 mask = GENMASK(tmdev->num_sensors - 1, 0);
157 mask <<= SENSOR0_SHIFT;
158 mask |= EN;
160 ret = regmap_read(tmdev->map, CNTL_ADDR, &reg_cntl);
161 if (ret)
162 return;
164 reg_cntl &= ~mask;
166 if (tmdev->num_sensors > 1)
167 reg_cntl &= ~SLP_CLK_ENA;
168 else
169 reg_cntl &= ~SLP_CLK_ENA_8660;
171 regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
174 static int init_8960(struct tsens_device *tmdev)
176 int ret, i;
177 u32 reg_cntl;
179 tmdev->map = dev_get_regmap(tmdev->dev, NULL);
180 if (!tmdev->map)
181 return -ENODEV;
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.
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;
195 reg_cntl = SW_RST;
196 ret = regmap_update_bits(tmdev->map, CNTL_ADDR, SW_RST, reg_cntl);
197 if (ret)
198 return ret;
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;
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;
216 reg_cntl |= EN;
217 ret = regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
218 if (ret)
219 return ret;
221 return 0;
224 static int calibrate_8960(struct tsens_device *tmdev)
226 int i;
227 char *data;
229 ssize_t num_read = tmdev->num_sensors;
230 struct tsens_sensor *s = tmdev->sensor;
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);
238 for (i = 0; i < num_read; i++, s++)
239 s->offset = data[i];
241 return 0;
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)
247 int slope, offset;
249 slope = thermal_zone_get_slope(s->tzd);
250 offset = CAL_MDEGC - slope * s->offset;
252 return adc_code * slope + offset;
255 static int get_temp_8960(struct tsens_device *tmdev, int id, int *temp)
257 int ret;
258 u32 code, trdy;
259 const struct tsens_sensor *s = &tmdev->sensor[id];
260 unsigned long timeout;
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));
276 return -ETIMEDOUT;
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,
289 const struct tsens_data data_8960 = {
290 .num_sensors = 11,
291 .ops = &ops_8960,