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