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