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