blob: 12b3a42e4f73977e756cf1424bbfaea27ec6ac18 [file] [log] [blame]
Siddartha Mohanadossacd24262011-08-18 11:19:00 -07001/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13/*
14 * Qualcomm MSM8960 TSENS driver
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/platform_device.h>
20#include <linux/thermal.h>
21#include <linux/interrupt.h>
22#include <linux/delay.h>
23#include <linux/slab.h>
24#include <linux/msm_tsens.h>
25#include <linux/io.h>
26
27#include <mach/msm_iomap.h>
Siddartha Mohanadoss6f8c4922011-09-21 12:16:33 -070028#include <mach/socinfo.h>
Siddartha Mohanadossacd24262011-08-18 11:19:00 -070029
30/* Trips: from very hot to very cold */
31enum tsens_trip_type {
32 TSENS_TRIP_STAGE3 = 0,
33 TSENS_TRIP_STAGE2,
34 TSENS_TRIP_STAGE1,
35 TSENS_TRIP_STAGE0,
36 TSENS_TRIP_NUM,
37};
38
39/* MSM8960 TSENS register info */
40#define TSENS_CAL_DEGC 30
41#define TSENS_MAIN_SENSOR 0
42
43#define TSENS_8960_QFPROM_ADDR0 (MSM_QFPROM_BASE + 0x00000404)
Siddartha Mohanadoss7201a162011-10-18 19:39:49 -070044#define TSENS_8960_QFPROM_SPARE_ADDR0 (MSM_QFPROM_BASE + 0x00000414)
Siddartha Mohanadossacd24262011-08-18 11:19:00 -070045#define TSENS_8960_CONFIG 0x9b
46#define TSENS_8960_CONFIG_SHIFT 0
47#define TSENS_8960_CONFIG_MASK (0xf << TSENS_8960_CONFIG_SHIFT)
48#define TSENS_CNTL_ADDR (MSM_CLK_CTL_BASE + 0x00003620)
49#define TSENS_EN BIT(0)
50#define TSENS_SW_RST BIT(1)
51#define TSENS_ADC_CLK_SEL BIT(2)
52#define SENSOR0_EN BIT(3)
53#define SENSOR1_EN BIT(4)
54#define SENSOR2_EN BIT(5)
55#define SENSOR3_EN BIT(6)
56#define SENSOR4_EN BIT(7)
57#define SENSORS_EN (SENSOR0_EN | SENSOR1_EN | \
58 SENSOR2_EN | SENSOR3_EN | SENSOR4_EN)
59#define TSENS_MIN_STATUS_MASK BIT(8)
60#define TSENS_LOWER_STATUS_CLR BIT(9)
61#define TSENS_UPPER_STATUS_CLR BIT(10)
62#define TSENS_MAX_STATUS_MASK BIT(11)
63#define TSENS_MEASURE_PERIOD 4 /* 1 sec. default */
64#define TSENS_8960_SLP_CLK_ENA BIT(26)
65
66#define TSENS_THRESHOLD_ADDR (MSM_CLK_CTL_BASE + 0x00003624)
67#define TSENS_THRESHOLD_MAX_CODE 0xff
68#define TSENS_THRESHOLD_MIN_CODE 0
69#define TSENS_THRESHOLD_MAX_LIMIT_SHIFT 24
70#define TSENS_THRESHOLD_MIN_LIMIT_SHIFT 16
71#define TSENS_THRESHOLD_UPPER_LIMIT_SHIFT 8
72#define TSENS_THRESHOLD_LOWER_LIMIT_SHIFT 0
73#define TSENS_THRESHOLD_MAX_LIMIT_MASK (TSENS_THRESHOLD_MAX_CODE << \
74 TSENS_THRESHOLD_MAX_LIMIT_SHIFT)
75#define TSENS_THRESHOLD_MIN_LIMIT_MASK (TSENS_THRESHOLD_MAX_CODE << \
76 TSENS_THRESHOLD_MIN_LIMIT_SHIFT)
77#define TSENS_THRESHOLD_UPPER_LIMIT_MASK (TSENS_THRESHOLD_MAX_CODE << \
78 TSENS_THRESHOLD_UPPER_LIMIT_SHIFT)
79#define TSENS_THRESHOLD_LOWER_LIMIT_MASK (TSENS_THRESHOLD_MAX_CODE << \
80 TSENS_THRESHOLD_LOWER_LIMIT_SHIFT)
81/* Initial temperature threshold values */
82#define TSENS_LOWER_LIMIT_TH 0x50
83#define TSENS_UPPER_LIMIT_TH 0xdf
84#define TSENS_MIN_LIMIT_TH 0x38
85#define TSENS_MAX_LIMIT_TH 0xff
86
87#define TSENS_S0_STATUS_ADDR (MSM_CLK_CTL_BASE + 0x00003628)
88#define TSENS_STATUS_ADDR_OFFSET 2
89#define TSENS_INT_STATUS_ADDR (MSM_CLK_CTL_BASE + 0x0000363c)
90
91#define TSENS_LOWER_INT_MASK BIT(1)
92#define TSENS_UPPER_INT_MASK BIT(2)
93#define TSENS_MAX_INT_MASK BIT(3)
94#define TSENS_TRDY_MASK BIT(7)
95
96#define TSENS_8960_CONFIG_ADDR (MSM_CLK_CTL_BASE + 0x00003640)
97#define TSENS_TRDY_RDY_MIN_TIME 1000
98#define TSENS_TRDY_RDY_MAX_TIME 1100
99#define TSENS_SENSOR_SHIFT 16
100#define TSENS_RED_SHIFT 8
101#define TSENS_8960_QFPROM_SHIFT 4
102#define TSENS_SENSOR0_SHIFT 3
103#define TSENS_MASK1 1
104
105#define TSENS_8660_QFPROM_ADDR (MSM_QFPROM_BASE + 0x000000bc)
106#define TSENS_8660_QFPROM_RED_TEMP_SENSOR0_SHIFT 24
107#define TSENS_8660_QFPROM_TEMP_SENSOR0_SHIFT 16
108#define TSENS_8660_QFPROM_TEMP_SENSOR0_MASK (255 \
109 << TSENS_8660_QFPROM_TEMP_SENSOR0_SHIFT)
110#define TSENS_8660_CONFIG 01
111#define TSENS_8660_CONFIG_SHIFT 28
112#define TSENS_8660_CONFIG_MASK (3 << TSENS_8660_CONFIG_SHIFT)
113#define TSENS_8660_SLP_CLK_ENA BIT(24)
114
115struct tsens_tm_device_sensor {
116 struct thermal_zone_device *tz_dev;
117 enum thermal_device_mode mode;
118 unsigned int sensor_num;
119 struct work_struct work;
120 int offset;
121 int calib_data;
122 int calib_data_backup;
123};
124
125struct tsens_tm_device {
126 bool prev_reading_avail;
127 int slope_mul_tsens_factor;
128 int tsens_factor;
129 uint32_t tsens_num_sensor;
130 enum platform_type hw_type;
131 struct tsens_tm_device_sensor sensor[0];
132};
133
134struct tsens_tm_device *tmdev;
135
136/* Temperature on y axis and ADC-code on x-axis */
137static int tsens_tz_code_to_degC(int adc_code, int sensor_num)
138{
139 int degC, degcbeforefactor;
140 degcbeforefactor = adc_code * tmdev->slope_mul_tsens_factor
141 + tmdev->sensor[sensor_num].offset;
142 if (degcbeforefactor == 0)
143 degC = degcbeforefactor;
144 else if (degcbeforefactor > 0)
145 degC = (degcbeforefactor + tmdev->tsens_factor/2)
146 / tmdev->tsens_factor;
147 else /* rounding for negative degrees */
148 degC = (degcbeforefactor - tmdev->tsens_factor/2)
149 / tmdev->tsens_factor;
150 return degC;
151}
152
153static int tsens_tz_degC_to_code(int degC, int sensor_num)
154{
155 int code = (degC * tmdev->tsens_factor -
156 tmdev->sensor[sensor_num].offset
157 + tmdev->slope_mul_tsens_factor/2)
158 / tmdev->slope_mul_tsens_factor;
159
160 if (code > TSENS_THRESHOLD_MAX_CODE)
161 code = TSENS_THRESHOLD_MAX_CODE;
162 else if (code < TSENS_THRESHOLD_MIN_CODE)
163 code = TSENS_THRESHOLD_MIN_CODE;
164 return code;
165}
166
167static int tsens_tz_get_temp(struct thermal_zone_device *thermal,
168 unsigned long *temp)
169{
170 struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
171 unsigned int code;
172
173 if (!tm_sensor || tm_sensor->mode != THERMAL_DEVICE_ENABLED || !temp)
174 return -EINVAL;
175
176 if (!tmdev->prev_reading_avail) {
177 while (!(readl_relaxed(TSENS_INT_STATUS_ADDR) &
178 TSENS_TRDY_MASK))
179 usleep_range(TSENS_TRDY_RDY_MIN_TIME,
180 TSENS_TRDY_RDY_MAX_TIME);
181 tmdev->prev_reading_avail = true;
182 }
183 code = readl_relaxed(TSENS_S0_STATUS_ADDR +
184 (tm_sensor->sensor_num << TSENS_STATUS_ADDR_OFFSET));
185 *temp = tsens_tz_code_to_degC(code, tm_sensor->sensor_num);
186
187 return 0;
188}
189
190static int tsens_tz_get_mode(struct thermal_zone_device *thermal,
191 enum thermal_device_mode *mode)
192{
193 struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
194
195 if (!tm_sensor || !mode)
196 return -EINVAL;
197
198 *mode = tm_sensor->mode;
199
200 return 0;
201}
202
203/* Function to enable the mode.
204 * If the main sensor is disabled all the sensors are disable and
205 * the clock is disabled.
206 * If the main sensor is not enabled and sub sensor is enabled
207 * returns with an error stating the main sensor is not enabled.
208 */
209static int tsens_tz_set_mode(struct thermal_zone_device *thermal,
210 enum thermal_device_mode mode)
211{
212 struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
213 unsigned int reg, mask, i;
214
215 if (!tm_sensor)
216 return -EINVAL;
217
218 if (mode != tm_sensor->mode) {
219 pr_info("%s: mode: %d --> %d\n", __func__, tm_sensor->mode,
220 mode);
221
222 reg = readl_relaxed(TSENS_CNTL_ADDR);
223
224 mask = 1 << (tm_sensor->sensor_num + TSENS_SENSOR0_SHIFT);
225 if (mode == THERMAL_DEVICE_ENABLED) {
226 if ((mask != SENSOR0_EN) && !(reg & SENSOR0_EN)) {
227 pr_info("Main sensor not enabled\n");
228 return -EINVAL;
229 }
230 writel_relaxed(reg | TSENS_SW_RST, TSENS_CNTL_ADDR);
Siddartha Mohanadoss0b9e5172011-09-29 18:54:13 -0700231 if (tmdev->hw_type == MSM_8960 ||
232 tmdev->hw_type == MSM_9615)
Siddartha Mohanadossacd24262011-08-18 11:19:00 -0700233 reg |= mask | TSENS_8960_SLP_CLK_ENA
234 | TSENS_EN;
235 else
236 reg |= mask | TSENS_8660_SLP_CLK_ENA
237 | TSENS_EN;
238 tmdev->prev_reading_avail = false;
239 } else {
240 reg &= ~mask;
241 if (!(reg & SENSOR0_EN)) {
Siddartha Mohanadoss0b9e5172011-09-29 18:54:13 -0700242 if (tmdev->hw_type == MSM_8960 ||
243 tmdev->hw_type == MSM_9615)
Siddartha Mohanadossacd24262011-08-18 11:19:00 -0700244 reg &= ~(SENSORS_EN |
245 TSENS_8960_SLP_CLK_ENA |
246 TSENS_EN);
247 else
248 reg &= ~(SENSORS_EN |
249 TSENS_8660_SLP_CLK_ENA |
250 TSENS_EN);
251
252 for (i = 1; i < tmdev->tsens_num_sensor; i++)
253 tmdev->sensor[i].mode = mode;
254
255 }
256 }
257 writel_relaxed(reg, TSENS_CNTL_ADDR);
258 }
259 tm_sensor->mode = mode;
260
261 return 0;
262}
263
264static int tsens_tz_get_trip_type(struct thermal_zone_device *thermal,
265 int trip, enum thermal_trip_type *type)
266{
267 struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
268
269 if (!tm_sensor || trip < 0 || !type)
270 return -EINVAL;
271
272 switch (trip) {
273 case TSENS_TRIP_STAGE3:
274 *type = THERMAL_TRIP_CRITICAL;
275 break;
276 case TSENS_TRIP_STAGE2:
277 *type = THERMAL_TRIP_CONFIGURABLE_HI;
278 break;
279 case TSENS_TRIP_STAGE1:
280 *type = THERMAL_TRIP_CONFIGURABLE_LOW;
281 break;
282 case TSENS_TRIP_STAGE0:
283 *type = THERMAL_TRIP_CRITICAL_LOW;
284 break;
285 default:
286 return -EINVAL;
287 }
288
289 return 0;
290}
291
292static int tsens_tz_activate_trip_type(struct thermal_zone_device *thermal,
293 int trip, enum thermal_trip_activation_mode mode)
294{
295 struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
296 unsigned int reg_cntl, reg_th, code, hi_code, lo_code, mask;
297
298 if (!tm_sensor || trip < 0)
299 return -EINVAL;
300
301 lo_code = TSENS_THRESHOLD_MIN_CODE;
302 hi_code = TSENS_THRESHOLD_MAX_CODE;
303
304 reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
305 reg_th = readl_relaxed(TSENS_THRESHOLD_ADDR);
306 switch (trip) {
307 case TSENS_TRIP_STAGE3:
308 code = (reg_th & TSENS_THRESHOLD_MAX_LIMIT_MASK)
309 >> TSENS_THRESHOLD_MAX_LIMIT_SHIFT;
310 mask = TSENS_MAX_STATUS_MASK;
311
312 if (!(reg_cntl & TSENS_UPPER_STATUS_CLR))
313 lo_code = (reg_th & TSENS_THRESHOLD_UPPER_LIMIT_MASK)
314 >> TSENS_THRESHOLD_UPPER_LIMIT_SHIFT;
315 else if (!(reg_cntl & TSENS_LOWER_STATUS_CLR))
316 lo_code = (reg_th & TSENS_THRESHOLD_LOWER_LIMIT_MASK)
317 >> TSENS_THRESHOLD_LOWER_LIMIT_SHIFT;
318 else if (!(reg_cntl & TSENS_MIN_STATUS_MASK))
319 lo_code = (reg_th & TSENS_THRESHOLD_MIN_LIMIT_MASK)
320 >> TSENS_THRESHOLD_MIN_LIMIT_SHIFT;
321 break;
322 case TSENS_TRIP_STAGE2:
323 code = (reg_th & TSENS_THRESHOLD_UPPER_LIMIT_MASK)
324 >> TSENS_THRESHOLD_UPPER_LIMIT_SHIFT;
325 mask = TSENS_UPPER_STATUS_CLR;
326
327 if (!(reg_cntl & TSENS_MAX_STATUS_MASK))
328 hi_code = (reg_th & TSENS_THRESHOLD_MAX_LIMIT_MASK)
329 >> TSENS_THRESHOLD_MAX_LIMIT_SHIFT;
330 if (!(reg_cntl & TSENS_LOWER_STATUS_CLR))
331 lo_code = (reg_th & TSENS_THRESHOLD_LOWER_LIMIT_MASK)
332 >> TSENS_THRESHOLD_LOWER_LIMIT_SHIFT;
333 else if (!(reg_cntl & TSENS_MIN_STATUS_MASK))
334 lo_code = (reg_th & TSENS_THRESHOLD_MIN_LIMIT_MASK)
335 >> TSENS_THRESHOLD_MIN_LIMIT_SHIFT;
336 break;
337 case TSENS_TRIP_STAGE1:
338 code = (reg_th & TSENS_THRESHOLD_LOWER_LIMIT_MASK)
339 >> TSENS_THRESHOLD_LOWER_LIMIT_SHIFT;
340 mask = TSENS_LOWER_STATUS_CLR;
341
342 if (!(reg_cntl & TSENS_MIN_STATUS_MASK))
343 lo_code = (reg_th & TSENS_THRESHOLD_MIN_LIMIT_MASK)
344 >> TSENS_THRESHOLD_MIN_LIMIT_SHIFT;
345 if (!(reg_cntl & TSENS_UPPER_STATUS_CLR))
346 hi_code = (reg_th & TSENS_THRESHOLD_UPPER_LIMIT_MASK)
347 >> TSENS_THRESHOLD_UPPER_LIMIT_SHIFT;
348 else if (!(reg_cntl & TSENS_MAX_STATUS_MASK))
349 hi_code = (reg_th & TSENS_THRESHOLD_MAX_LIMIT_MASK)
350 >> TSENS_THRESHOLD_MAX_LIMIT_SHIFT;
351 break;
352 case TSENS_TRIP_STAGE0:
353 code = (reg_th & TSENS_THRESHOLD_MIN_LIMIT_MASK)
354 >> TSENS_THRESHOLD_MIN_LIMIT_SHIFT;
355 mask = TSENS_MIN_STATUS_MASK;
356
357 if (!(reg_cntl & TSENS_LOWER_STATUS_CLR))
358 hi_code = (reg_th & TSENS_THRESHOLD_LOWER_LIMIT_MASK)
359 >> TSENS_THRESHOLD_LOWER_LIMIT_SHIFT;
360 else if (!(reg_cntl & TSENS_UPPER_STATUS_CLR))
361 hi_code = (reg_th & TSENS_THRESHOLD_UPPER_LIMIT_MASK)
362 >> TSENS_THRESHOLD_UPPER_LIMIT_SHIFT;
363 else if (!(reg_cntl & TSENS_MAX_STATUS_MASK))
364 hi_code = (reg_th & TSENS_THRESHOLD_MAX_LIMIT_MASK)
365 >> TSENS_THRESHOLD_MAX_LIMIT_SHIFT;
366 break;
367 default:
368 return -EINVAL;
369 }
370
371 if (mode == THERMAL_TRIP_ACTIVATION_DISABLED)
372 writel_relaxed(reg_cntl | mask, TSENS_CNTL_ADDR);
373 else {
374 if (code < lo_code || code > hi_code) {
375 pr_info("%s with invalid code %x\n", __func__, code);
376 return -EINVAL;
377 }
378 writel_relaxed(reg_cntl & ~mask, TSENS_CNTL_ADDR);
379 }
380 mb();
381 return 0;
382}
383
384static int tsens_tz_get_trip_temp(struct thermal_zone_device *thermal,
385 int trip, unsigned long *temp)
386{
387 struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
388 unsigned int reg;
389
390 if (!tm_sensor || trip < 0 || !temp)
391 return -EINVAL;
392
393 reg = readl_relaxed(TSENS_THRESHOLD_ADDR);
394 switch (trip) {
395 case TSENS_TRIP_STAGE3:
396 reg = (reg & TSENS_THRESHOLD_MAX_LIMIT_MASK)
397 >> TSENS_THRESHOLD_MAX_LIMIT_SHIFT;
398 break;
399 case TSENS_TRIP_STAGE2:
400 reg = (reg & TSENS_THRESHOLD_UPPER_LIMIT_MASK)
401 >> TSENS_THRESHOLD_UPPER_LIMIT_SHIFT;
402 break;
403 case TSENS_TRIP_STAGE1:
404 reg = (reg & TSENS_THRESHOLD_LOWER_LIMIT_MASK)
405 >> TSENS_THRESHOLD_LOWER_LIMIT_SHIFT;
406 break;
407 case TSENS_TRIP_STAGE0:
408 reg = (reg & TSENS_THRESHOLD_MIN_LIMIT_MASK)
409 >> TSENS_THRESHOLD_MIN_LIMIT_SHIFT;
410 break;
411 default:
412 return -EINVAL;
413 }
414
415 *temp = tsens_tz_code_to_degC(reg, tm_sensor->sensor_num);
416
417 return 0;
418}
419
420static int tsens_tz_get_crit_temp(struct thermal_zone_device *thermal,
421 unsigned long *temp)
422{
423 return tsens_tz_get_trip_temp(thermal, TSENS_TRIP_STAGE3, temp);
424}
425
426static int tsens_tz_set_trip_temp(struct thermal_zone_device *thermal,
427 int trip, long temp)
428{
429 struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
430 unsigned int reg_th, reg_cntl;
431 int code, hi_code, lo_code, code_err_chk;
432
433 code_err_chk = code = tsens_tz_degC_to_code(temp,
434 tm_sensor->sensor_num);
435 if (!tm_sensor || trip < 0)
436 return -EINVAL;
437
438 lo_code = TSENS_THRESHOLD_MIN_CODE;
439 hi_code = TSENS_THRESHOLD_MAX_CODE;
440
441 reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
442 reg_th = readl_relaxed(TSENS_THRESHOLD_ADDR);
443 switch (trip) {
444 case TSENS_TRIP_STAGE3:
445 code <<= TSENS_THRESHOLD_MAX_LIMIT_SHIFT;
446 reg_th &= ~TSENS_THRESHOLD_MAX_LIMIT_MASK;
447
448 if (!(reg_cntl & TSENS_UPPER_STATUS_CLR))
449 lo_code = (reg_th & TSENS_THRESHOLD_UPPER_LIMIT_MASK)
450 >> TSENS_THRESHOLD_UPPER_LIMIT_SHIFT;
451 else if (!(reg_cntl & TSENS_LOWER_STATUS_CLR))
452 lo_code = (reg_th & TSENS_THRESHOLD_LOWER_LIMIT_MASK)
453 >> TSENS_THRESHOLD_LOWER_LIMIT_SHIFT;
454 else if (!(reg_cntl & TSENS_MIN_STATUS_MASK))
455 lo_code = (reg_th & TSENS_THRESHOLD_MIN_LIMIT_MASK)
456 >> TSENS_THRESHOLD_MIN_LIMIT_SHIFT;
457 break;
458 case TSENS_TRIP_STAGE2:
459 code <<= TSENS_THRESHOLD_UPPER_LIMIT_SHIFT;
460 reg_th &= ~TSENS_THRESHOLD_UPPER_LIMIT_MASK;
461
462 if (!(reg_cntl & TSENS_MAX_STATUS_MASK))
463 hi_code = (reg_th & TSENS_THRESHOLD_MAX_LIMIT_MASK)
464 >> TSENS_THRESHOLD_MAX_LIMIT_SHIFT;
465 if (!(reg_cntl & TSENS_LOWER_STATUS_CLR))
466 lo_code = (reg_th & TSENS_THRESHOLD_LOWER_LIMIT_MASK)
467 >> TSENS_THRESHOLD_LOWER_LIMIT_SHIFT;
468 else if (!(reg_cntl & TSENS_MIN_STATUS_MASK))
469 lo_code = (reg_th & TSENS_THRESHOLD_MIN_LIMIT_MASK)
470 >> TSENS_THRESHOLD_MIN_LIMIT_SHIFT;
471 break;
472 case TSENS_TRIP_STAGE1:
473 code <<= TSENS_THRESHOLD_LOWER_LIMIT_SHIFT;
474 reg_th &= ~TSENS_THRESHOLD_LOWER_LIMIT_MASK;
475
476 if (!(reg_cntl & TSENS_MIN_STATUS_MASK))
477 lo_code = (reg_th & TSENS_THRESHOLD_MIN_LIMIT_MASK)
478 >> TSENS_THRESHOLD_MIN_LIMIT_SHIFT;
479 if (!(reg_cntl & TSENS_UPPER_STATUS_CLR))
480 hi_code = (reg_th & TSENS_THRESHOLD_UPPER_LIMIT_MASK)
481 >> TSENS_THRESHOLD_UPPER_LIMIT_SHIFT;
482 else if (!(reg_cntl & TSENS_MAX_STATUS_MASK))
483 hi_code = (reg_th & TSENS_THRESHOLD_MAX_LIMIT_MASK)
484 >> TSENS_THRESHOLD_MAX_LIMIT_SHIFT;
485 break;
486 case TSENS_TRIP_STAGE0:
487 code <<= TSENS_THRESHOLD_MIN_LIMIT_SHIFT;
488 reg_th &= ~TSENS_THRESHOLD_MIN_LIMIT_MASK;
489
490 if (!(reg_cntl & TSENS_LOWER_STATUS_CLR))
491 hi_code = (reg_th & TSENS_THRESHOLD_LOWER_LIMIT_MASK)
492 >> TSENS_THRESHOLD_LOWER_LIMIT_SHIFT;
493 else if (!(reg_cntl & TSENS_UPPER_STATUS_CLR))
494 hi_code = (reg_th & TSENS_THRESHOLD_UPPER_LIMIT_MASK)
495 >> TSENS_THRESHOLD_UPPER_LIMIT_SHIFT;
496 else if (!(reg_cntl & TSENS_MAX_STATUS_MASK))
497 hi_code = (reg_th & TSENS_THRESHOLD_MAX_LIMIT_MASK)
498 >> TSENS_THRESHOLD_MAX_LIMIT_SHIFT;
499 break;
500 default:
501 return -EINVAL;
502 }
503
504 if (code_err_chk < lo_code || code_err_chk > hi_code)
505 return -EINVAL;
506
507 writel_relaxed(reg_th | code, TSENS_THRESHOLD_ADDR);
508
509 return 0;
510}
511
512static struct thermal_zone_device_ops tsens_thermal_zone_ops = {
513 .get_temp = tsens_tz_get_temp,
514 .get_mode = tsens_tz_get_mode,
515 .set_mode = tsens_tz_set_mode,
516 .get_trip_type = tsens_tz_get_trip_type,
517 .activate_trip_type = tsens_tz_activate_trip_type,
518 .get_trip_temp = tsens_tz_get_trip_temp,
519 .set_trip_temp = tsens_tz_set_trip_temp,
520 .get_crit_temp = tsens_tz_get_crit_temp,
521};
522
523static void notify_uspace_tsens_fn(struct work_struct *work)
524{
525 struct tsens_tm_device_sensor *tm = container_of(work,
526 struct tsens_tm_device_sensor, work);
527
528 sysfs_notify(&tm->tz_dev->device.kobj,
529 NULL, "type");
530}
531
532static irqreturn_t tsens_isr(int irq, void *data)
533{
534 struct tsens_tm_device *tm = data;
535 unsigned int threshold, threshold_low, i, code, reg, sensor, mask;
536 bool upper_th_x, lower_th_x;
537 int adc_code;
538
539 reg = readl_relaxed(TSENS_CNTL_ADDR);
540 writel_relaxed(reg | TSENS_LOWER_STATUS_CLR | TSENS_UPPER_STATUS_CLR,
541 TSENS_CNTL_ADDR);
542 mask = ~(TSENS_LOWER_STATUS_CLR | TSENS_UPPER_STATUS_CLR);
543 threshold = readl_relaxed(TSENS_THRESHOLD_ADDR);
544 threshold_low = (threshold & TSENS_THRESHOLD_LOWER_LIMIT_MASK)
545 >> TSENS_THRESHOLD_LOWER_LIMIT_SHIFT;
546 threshold = (threshold & TSENS_THRESHOLD_UPPER_LIMIT_MASK)
547 >> TSENS_THRESHOLD_UPPER_LIMIT_SHIFT;
548 reg = sensor = readl_relaxed(TSENS_CNTL_ADDR);
549 sensor &= (uint32_t) SENSORS_EN;
550 sensor >>= TSENS_SENSOR0_SHIFT;
551 for (i = 0; i < tmdev->tsens_num_sensor; i++) {
552 if (sensor & TSENS_MASK1) {
553 code = readl_relaxed(TSENS_S0_STATUS_ADDR +
554 (i << TSENS_STATUS_ADDR_OFFSET));
555 upper_th_x = code >= threshold;
556 lower_th_x = code <= threshold_low;
557 if (upper_th_x)
558 mask |= TSENS_UPPER_STATUS_CLR;
559 if (lower_th_x)
560 mask |= TSENS_LOWER_STATUS_CLR;
561 if (upper_th_x || lower_th_x) {
562 /* Notify user space */
563 schedule_work(&tm->sensor[i].work);
564 adc_code = readl_relaxed(TSENS_S0_STATUS_ADDR
565 + (i << TSENS_STATUS_ADDR_OFFSET));
566 pr_info("\nTrip point triggered by "
567 "current temperature (%d degrees) "
568 "measured by Temperature-Sensor %d\n",
569 tsens_tz_code_to_degC(adc_code, i), i);
570 }
571 }
572 sensor >>= 1;
573 }
574 writel_relaxed(reg & mask, TSENS_CNTL_ADDR);
575 mb();
576 return IRQ_HANDLED;
577}
578
579static void tsens_disable_mode(void)
580{
581 unsigned int reg_cntl = 0;
582
583 reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
Siddartha Mohanadoss0b9e5172011-09-29 18:54:13 -0700584 if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615)
Siddartha Mohanadossacd24262011-08-18 11:19:00 -0700585 writel_relaxed(reg_cntl &
586 ~((((1 << tmdev->tsens_num_sensor) - 1) <<
587 TSENS_SENSOR0_SHIFT) | TSENS_8960_SLP_CLK_ENA
588 | TSENS_EN), TSENS_CNTL_ADDR);
589 else if (tmdev->hw_type == MSM_8660)
590 writel_relaxed(reg_cntl &
591 ~((((1 << tmdev->tsens_num_sensor) - 1) <<
592 TSENS_SENSOR0_SHIFT) | TSENS_8660_SLP_CLK_ENA
593 | TSENS_EN), TSENS_CNTL_ADDR);
594}
595
596static void tsens_hw_init(void)
597{
598 unsigned int reg_cntl = 0, reg_cfg = 0, reg_thr = 0;
599
600 reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
601 writel_relaxed(reg_cntl | TSENS_SW_RST, TSENS_CNTL_ADDR);
602
Siddartha Mohanadoss0b9e5172011-09-29 18:54:13 -0700603 if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615) {
Siddartha Mohanadossacd24262011-08-18 11:19:00 -0700604 reg_cntl |= TSENS_8960_SLP_CLK_ENA | TSENS_EN |
605 (TSENS_MEASURE_PERIOD << 18) |
606 TSENS_LOWER_STATUS_CLR | TSENS_UPPER_STATUS_CLR |
607 TSENS_MIN_STATUS_MASK | TSENS_MAX_STATUS_MASK |
608 (((1 << tmdev->tsens_num_sensor) - 1) <<
609 TSENS_SENSOR0_SHIFT);
610 writel_relaxed(reg_cntl, TSENS_CNTL_ADDR);
611
612 reg_cfg = readl_relaxed(TSENS_8960_CONFIG_ADDR);
613 reg_cfg = (reg_cfg & ~TSENS_8960_CONFIG_MASK) |
614 (TSENS_8960_CONFIG << TSENS_8960_CONFIG_SHIFT);
615 writel_relaxed(reg_cfg, TSENS_8960_CONFIG_ADDR);
616 } else if (tmdev->hw_type == MSM_8660) {
617 reg_cntl |= TSENS_8660_SLP_CLK_ENA | TSENS_EN |
618 (TSENS_MEASURE_PERIOD << 16) |
619 TSENS_LOWER_STATUS_CLR | TSENS_UPPER_STATUS_CLR |
620 TSENS_MIN_STATUS_MASK | TSENS_MAX_STATUS_MASK |
621 (((1 << tmdev->tsens_num_sensor) - 1) <<
622 TSENS_SENSOR0_SHIFT);
623
624 /* set TSENS_CONFIG bits (bits 29:28 of TSENS_CNTL) to '01';
625 this setting found to be optimal. */
626 reg_cntl = (reg_cntl & ~TSENS_8660_CONFIG_MASK) |
627 (TSENS_8660_CONFIG << TSENS_8660_CONFIG_SHIFT);
628
629 writel_relaxed(reg_cntl, TSENS_CNTL_ADDR);
630 }
631
632 reg_thr |= (TSENS_LOWER_LIMIT_TH << TSENS_THRESHOLD_LOWER_LIMIT_SHIFT) |
633 (TSENS_UPPER_LIMIT_TH << TSENS_THRESHOLD_UPPER_LIMIT_SHIFT) |
634 (TSENS_MIN_LIMIT_TH << TSENS_THRESHOLD_MIN_LIMIT_SHIFT) |
635 (TSENS_MAX_LIMIT_TH << TSENS_THRESHOLD_MAX_LIMIT_SHIFT);
636 writel_relaxed(reg_thr, TSENS_THRESHOLD_ADDR);
637}
638
639static int tsens_calib_sensors8660(void)
640{
641 uint32_t *main_sensor_addr, sensor_shift, red_sensor_shift;
642 uint32_t sensor_mask, red_sensor_mask;
643
644 main_sensor_addr = TSENS_8660_QFPROM_ADDR;
645 sensor_shift = TSENS_SENSOR_SHIFT;
646 red_sensor_shift = sensor_shift + TSENS_RED_SHIFT;
647 sensor_mask = TSENS_THRESHOLD_MAX_CODE << sensor_shift;
648 red_sensor_mask = TSENS_THRESHOLD_MAX_CODE << red_sensor_shift;
649 tmdev->sensor[TSENS_MAIN_SENSOR].calib_data =
650 (readl_relaxed(main_sensor_addr) & sensor_mask)
651 >> sensor_shift;
652 tmdev->sensor[TSENS_MAIN_SENSOR].calib_data_backup =
653 (readl_relaxed(main_sensor_addr)
654 & red_sensor_mask) >> red_sensor_shift;
655 if (tmdev->sensor[TSENS_MAIN_SENSOR].calib_data_backup)
656 tmdev->sensor[TSENS_MAIN_SENSOR].calib_data =
657 tmdev->sensor[TSENS_MAIN_SENSOR].calib_data_backup;
658 if (!tmdev->sensor[TSENS_MAIN_SENSOR].calib_data) {
659 pr_err("%s: No temperature sensor data for calibration"
660 " in QFPROM!\n", __func__);
661 return -ENODEV;
662 }
663
664 tmdev->sensor[TSENS_MAIN_SENSOR].offset = tmdev->tsens_factor *
665 TSENS_CAL_DEGC - tmdev->slope_mul_tsens_factor *
666 tmdev->sensor[TSENS_MAIN_SENSOR].calib_data;
667 tmdev->prev_reading_avail = false;
668 INIT_WORK(&tmdev->sensor[TSENS_MAIN_SENSOR].work,
669 notify_uspace_tsens_fn);
670
671 return 0;
672}
673
674static int tsens_calib_sensors8960(void)
675{
Siddartha Mohanadoss7201a162011-10-18 19:39:49 -0700676 uint32_t *main_sensor_addr, sensor_shift, *backup_sensor_addr;
677 uint32_t sensor_mask, i;
Siddartha Mohanadossacd24262011-08-18 11:19:00 -0700678 for (i = 0; i < tmdev->tsens_num_sensor; i++) {
679 main_sensor_addr = TSENS_8960_QFPROM_ADDR0 +
Siddartha Mohanadoss7201a162011-10-18 19:39:49 -0700680 (TSENS_8960_QFPROM_SHIFT *
681 (i & TSENS_8960_QFPROM_SHIFT >> TSENS_SENSOR0_SHIFT));
682 sensor_shift = (i % TSENS_8960_QFPROM_SHIFT) * TSENS_RED_SHIFT;
Siddartha Mohanadossacd24262011-08-18 11:19:00 -0700683 sensor_mask = TSENS_THRESHOLD_MAX_CODE << sensor_shift;
Siddartha Mohanadoss7201a162011-10-18 19:39:49 -0700684 backup_sensor_addr = TSENS_8960_QFPROM_SPARE_ADDR0 +
685 (TSENS_8960_QFPROM_SHIFT *
686 (i & TSENS_8960_QFPROM_SHIFT >> TSENS_SENSOR0_SHIFT));
Siddartha Mohanadossacd24262011-08-18 11:19:00 -0700687
688 tmdev->sensor[i].calib_data = (readl_relaxed(main_sensor_addr)
689 & sensor_mask) >> sensor_shift;
690 tmdev->sensor[i].calib_data_backup =
Siddartha Mohanadoss7201a162011-10-18 19:39:49 -0700691 (readl_relaxed(backup_sensor_addr) &
692 sensor_mask) >> sensor_shift;
Siddartha Mohanadossacd24262011-08-18 11:19:00 -0700693 if (tmdev->sensor[i].calib_data_backup)
694 tmdev->sensor[i].calib_data =
695 tmdev->sensor[i].calib_data_backup;
696
Siddartha Mohanadossacd24262011-08-18 11:19:00 -0700697 if (!tmdev->sensor[i].calib_data) {
698 pr_err("%s: No temperature sensor:%d data for"
699 " calibration in QFPROM!\n", __func__, i);
700 return -ENODEV;
701 }
702 tmdev->sensor[i].offset = tmdev->tsens_factor *
703 TSENS_CAL_DEGC - tmdev->slope_mul_tsens_factor *
704 tmdev->sensor[i].calib_data;
705 tmdev->prev_reading_avail = false;
706 INIT_WORK(&tmdev->sensor[i].work, notify_uspace_tsens_fn);
707 }
708
709 return 0;
710}
711
Siddartha Mohanadoss6f8c4922011-09-21 12:16:33 -0700712static int tsens_check_version_support(void)
713{
714 int rc = 0;
715
716 if (tmdev->hw_type == MSM_8960)
717 if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 1)
718 rc = -ENODEV;
Siddartha Mohanadoss0b9e5172011-09-29 18:54:13 -0700719
Siddartha Mohanadoss6f8c4922011-09-21 12:16:33 -0700720 return rc;
721}
722
Siddartha Mohanadossacd24262011-08-18 11:19:00 -0700723static int tsens_calib_sensors(void)
724{
725 int rc;
726
727 if (tmdev->hw_type == MSM_8660)
728 rc = tsens_calib_sensors8660();
Siddartha Mohanadoss0b9e5172011-09-29 18:54:13 -0700729 else if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615)
Siddartha Mohanadossacd24262011-08-18 11:19:00 -0700730 rc = tsens_calib_sensors8960();
731
732 return rc;
733}
734
735static int __devinit tsens_tm_probe(struct platform_device *pdev)
736{
737 int rc, i;
738 struct tsens_platform_data *pdata;
739
740 pdata = pdev->dev.platform_data;
741 if (!pdata) {
742 pr_err("No TSENS Platform data\n");
743 return -EINVAL;
744 }
745
746 tmdev = kzalloc(sizeof(struct tsens_tm_device) +
747 pdata->tsens_num_sensor *
748 sizeof(struct tsens_tm_device_sensor),
749 GFP_KERNEL);
750 if (tmdev == NULL) {
751 pr_err("%s: kzalloc() failed.\n", __func__);
752 return -ENOMEM;
753 }
754
755 tmdev->slope_mul_tsens_factor = pdata->slope;
756 tmdev->tsens_factor = pdata->tsens_factor;
757 tmdev->tsens_num_sensor = pdata->tsens_num_sensor;
758 tmdev->hw_type = pdata->hw_type;
759
Siddartha Mohanadoss6f8c4922011-09-21 12:16:33 -0700760 rc = tsens_check_version_support();
761 if (rc < 0) {
762 kfree(tmdev);
763 return rc;
764 }
765
Siddartha Mohanadossacd24262011-08-18 11:19:00 -0700766 rc = tsens_calib_sensors();
767 if (rc < 0) {
768 kfree(tmdev);
769 return rc;
770 }
771
772 platform_set_drvdata(pdev, tmdev);
773
774 tsens_hw_init();
775
776 for (i = 0; i < pdata->tsens_num_sensor; i++) {
777 char name[17];
778 snprintf(name, sizeof(name), "tsens_tz_sensor%d", i);
779 tmdev->sensor[i].mode = THERMAL_DEVICE_ENABLED;
780 tmdev->sensor[i].sensor_num = i;
781 tmdev->sensor[i].tz_dev = thermal_zone_device_register(name,
782 TSENS_TRIP_NUM, &tmdev->sensor[i],
783 &tsens_thermal_zone_ops, 0, 0, 0, 0);
784 if (tmdev->sensor[i].tz_dev == NULL) {
785 pr_err("%s: thermal_zone_device_register() failed.\n",
786 __func__);
787 rc = -ENODEV;
788 goto fail;
789 }
790 tmdev->sensor[i].mode = THERMAL_DEVICE_DISABLED;
791 }
792
793 rc = request_irq(TSENS_UPPER_LOWER_INT, tsens_isr,
794 IRQF_TRIGGER_RISING, "tsens_interrupt", tmdev);
795 if (rc < 0) {
796 pr_err("%s: request_irq FAIL: %d\n", __func__, rc);
797 for (i = 0; i < tmdev->tsens_num_sensor; i++)
798 thermal_zone_device_unregister(tmdev->sensor[i].tz_dev);
799 goto fail;
800 }
801
802 tsens_disable_mode();
803
804 pr_notice("%s: OK\n", __func__);
805 mb();
806 return 0;
807fail:
808 tsens_disable_mode();
809 platform_set_drvdata(pdev, NULL);
810 kfree(tmdev);
811 mb();
812 return rc;
813}
814
815static int __devexit tsens_tm_remove(struct platform_device *pdev)
816{
817 struct tsens_tm_device *tmdev = platform_get_drvdata(pdev);
818 int i;
819
820 tsens_disable_mode();
821 mb();
822 free_irq(TSENS_UPPER_LOWER_INT, tmdev);
823 for (i = 0; i < tmdev->tsens_num_sensor; i++)
824 thermal_zone_device_unregister(tmdev->sensor[i].tz_dev);
825 platform_set_drvdata(pdev, NULL);
826 kfree(tmdev);
827 return 0;
828}
829
830static struct platform_driver tsens_tm_driver = {
831 .probe = tsens_tm_probe,
832 .remove = __devexit_p(tsens_tm_remove),
833 .driver = {
834 .name = "tsens8960-tm",
835 .owner = THIS_MODULE,
836 },
837};
838
839static int __init tsens_init(void)
840{
841 return platform_driver_register(&tsens_tm_driver);
842}
843
844static void __exit tsens_exit(void)
845{
846 platform_driver_unregister(&tsens_tm_driver);
847}
848
849module_init(tsens_init);
850module_exit(tsens_exit);
851
852MODULE_LICENSE("GPL v2");
853MODULE_DESCRIPTION("MSM8960 Temperature Sensor driver");
854MODULE_VERSION("1.0");
855MODULE_ALIAS("platform:tsens8960-tm");