blob: f4e094ecda84f28cb6a90d224dfc56add0e334c1 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2010-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 TSENS Thermal Manager 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
25#include <linux/io.h>
26#include <mach/msm_iomap.h>
27
28/* Trips: from very hot to very cold */
29enum tsens_trip_type {
30 TSENS_TRIP_STAGE3 = 0,
31 TSENS_TRIP_STAGE2,
32 TSENS_TRIP_STAGE1,
33 TSENS_TRIP_STAGE0,
34 TSENS_TRIP_NUM,
35};
36
37#define TSENS_NUM_SENSORS 1 /* There are 5 but only 1 is useful now */
38#define TSENS_CAL_DEGC 30 /* degree C used for calibration */
39#define TSENS_QFPROM_ADDR (MSM_QFPROM_BASE + 0x000000bc)
40#define TSENS_QFPROM_RED_TEMP_SENSOR0_SHIFT 24
41#define TSENS_QFPROM_TEMP_SENSOR0_SHIFT 16
42#define TSENS_QFPROM_TEMP_SENSOR0_MASK (255 << TSENS_QFPROM_TEMP_SENSOR0_SHIFT)
43#define TSENS_SLOPE (0.702) /* slope in (degrees_C / ADC_code) */
44#define TSENS_FACTOR (1000) /* convert floating-point into integer */
45#define TSENS_CONFIG 01 /* this setting found to be optimal */
46#define TSENS_CONFIG_SHIFT 28
47#define TSENS_CONFIG_MASK (3 << TSENS_CONFIG_SHIFT)
48#define TSENS_CNTL_ADDR (MSM_CLK_CTL_BASE + 0x00003620)
49#define TSENS_EN (1 << 0)
50#define TSENS_SW_RST (1 << 1)
51#define SENSOR0_EN (1 << 3)
52#define SENSOR1_EN (1 << 4)
53#define SENSOR2_EN (1 << 5)
54#define SENSOR3_EN (1 << 6)
55#define SENSOR4_EN (1 << 7)
56#define TSENS_MIN_STATUS_MASK (1 << 8)
57#define TSENS_LOWER_STATUS_CLR (1 << 9)
58#define TSENS_UPPER_STATUS_CLR (1 << 10)
59#define TSENS_MAX_STATUS_MASK (1 << 11)
60#define TSENS_MEASURE_PERIOD 4 /* 1 sec. default as required by Willie */
61#define TSENS_SLP_CLK_ENA (1 << 24)
62#define TSENS_THRESHOLD_ADDR (MSM_CLK_CTL_BASE + 0x00003624)
63#define TSENS_THRESHOLD_MAX_CODE (0xff)
64#define TSENS_THRESHOLD_MAX_LIMIT_MASK (TSENS_THRESHOLD_MAX_CODE << 24)
65#define TSENS_THRESHOLD_MIN_LIMIT_MASK (TSENS_THRESHOLD_MAX_CODE << 16)
66#define TSENS_THRESHOLD_UPPER_LIMIT_MASK (TSENS_THRESHOLD_MAX_CODE << 8)
67#define TSENS_THRESHOLD_LOWER_LIMIT_MASK (TSENS_THRESHOLD_MAX_CODE << 0)
68/* Initial temperature threshold values */
69#define TSENS_LOWER_LIMIT_TH 0x50
70#define TSENS_UPPER_LIMIT_TH 0xdf
71#define TSENS_MIN_LIMIT_TH 0x38
72#define TSENS_MAX_LIMIT_TH 0xff
73
74#define TSENS_S0_STATUS_ADDR (MSM_CLK_CTL_BASE + 0x00003628)
75#define TSENS_INT_STATUS_ADDR (MSM_CLK_CTL_BASE + 0x0000363c)
76#define TSENS_LOWER_INT_MASK (1 << 1)
77#define TSENS_UPPER_INT_MASK (1 << 2)
78#define TSENS_TRDY_MASK (1 << 7)
79
80struct tsens_tm_device_sensor {
81 struct thermal_zone_device *tz_dev;
82 enum thermal_device_mode mode;
83 unsigned int sensor_num;
84};
85
86struct tsens_tm_device {
87 struct tsens_tm_device_sensor sensor[TSENS_NUM_SENSORS];
88 bool prev_reading_avail;
89 int offset;
90 struct work_struct work;
91};
92
93struct tsens_tm_device *tmdev;
94
95/* Temperature on y axis and ADC-code on x-axis */
96static int tsens_tz_code_to_degC(int adc_code)
97{
98 int degC, degcbeforefactor;
99 degcbeforefactor = adc_code * (int)(TSENS_SLOPE * TSENS_FACTOR)
100 + tmdev->offset;
101 if (degcbeforefactor == 0)
102 degC = degcbeforefactor;
103 else if (degcbeforefactor > 0)
104 degC = (degcbeforefactor + TSENS_FACTOR/2) / TSENS_FACTOR;
105 else /* rounding for negative degrees */
106 degC = (degcbeforefactor - TSENS_FACTOR/2) / TSENS_FACTOR;
107 return degC;
108}
109
110static int tsens_tz_degC_to_code(int degC)
111{
112 int code = (degC * TSENS_FACTOR - tmdev->offset
113 + (int)(TSENS_FACTOR * TSENS_SLOPE)/2)
114 / (int)(TSENS_FACTOR * TSENS_SLOPE);
115 if (code > 255) /* upper bound */
116 code = 255;
117 else if (code < 0) /* lower bound */
118 code = 0;
119 return code;
120}
121
122static int tsens_tz_get_temp(struct thermal_zone_device *thermal,
123 unsigned long *temp)
124{
125 struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
126 unsigned int code;
127
128 if (!tm_sensor || tm_sensor->mode != THERMAL_DEVICE_ENABLED || !temp)
129 return -EINVAL;
130
131 if (!tmdev->prev_reading_avail) {
132 while (!(readl(TSENS_INT_STATUS_ADDR) & TSENS_TRDY_MASK))
133 msleep(1);
134 tmdev->prev_reading_avail = 1;
135 }
136
137 code = readl(TSENS_S0_STATUS_ADDR + (tm_sensor->sensor_num << 2));
138 *temp = tsens_tz_code_to_degC(code);
139
140 return 0;
141}
142
143static int tsens_tz_get_mode(struct thermal_zone_device *thermal,
144 enum thermal_device_mode *mode)
145{
146 struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
147
148 if (!tm_sensor || !mode)
149 return -EINVAL;
150
151 *mode = tm_sensor->mode;
152
153 return 0;
154}
155
156static int tsens_tz_set_mode(struct thermal_zone_device *thermal,
157 enum thermal_device_mode mode)
158{
159 struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
160 unsigned int reg, mask;
161
162 if (!tm_sensor)
163 return -EINVAL;
164
165 if (mode != tm_sensor->mode) {
166 pr_info("%s: mode: %d --> %d\n", __func__, tm_sensor->mode,
167 mode);
168
169 reg = readl(TSENS_CNTL_ADDR);
170 mask = 1 << (tm_sensor->sensor_num + 3);
171 if (mode == THERMAL_DEVICE_ENABLED) {
172 writel(reg | TSENS_SW_RST, TSENS_CNTL_ADDR);
173 reg |= mask | TSENS_SLP_CLK_ENA | TSENS_EN;
174 tmdev->prev_reading_avail = 0;
175 } else {
176 reg &= ~mask;
177 if (!(reg & (((1 << TSENS_NUM_SENSORS) - 1) << 3)))
178 reg &= ~(TSENS_SLP_CLK_ENA | TSENS_EN);
179 }
180
181 writel(reg, TSENS_CNTL_ADDR);
182 }
183 tm_sensor->mode = mode;
184
185 return 0;
186}
187
188static int tsens_tz_get_trip_type(struct thermal_zone_device *thermal,
189 int trip, enum thermal_trip_type *type)
190{
191 struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
192
193 if (!tm_sensor || trip < 0 || !type)
194 return -EINVAL;
195
196 switch (trip) {
197 case TSENS_TRIP_STAGE3:
198 *type = THERMAL_TRIP_CRITICAL;
199 break;
200 case TSENS_TRIP_STAGE2:
201 *type = THERMAL_TRIP_CONFIGURABLE_HI;
202 break;
203 case TSENS_TRIP_STAGE1:
204 *type = THERMAL_TRIP_CONFIGURABLE_LOW;
205 break;
206 case TSENS_TRIP_STAGE0:
207 *type = THERMAL_TRIP_CRITICAL_LOW;
208 break;
209 default:
210 return -EINVAL;
211 }
212
213 return 0;
214}
215
216static int tsens_tz_activate_trip_type(struct thermal_zone_device *thermal,
217 int trip, enum thermal_trip_activation_mode mode)
218{
219 struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
220 unsigned int reg_cntl, reg_th, code, hi_code, lo_code, mask;
221
222 if (!tm_sensor || trip < 0)
223 return -EINVAL;
224
225 lo_code = 0;
226 hi_code = TSENS_THRESHOLD_MAX_CODE;
227
228 reg_cntl = readl(TSENS_CNTL_ADDR);
229 reg_th = readl(TSENS_THRESHOLD_ADDR);
230 switch (trip) {
231 case TSENS_TRIP_STAGE3:
232 code = (reg_th & TSENS_THRESHOLD_MAX_LIMIT_MASK) >> 24;
233 mask = TSENS_MAX_STATUS_MASK;
234
235 if (!(reg_cntl & TSENS_UPPER_STATUS_CLR))
236 lo_code = (reg_th & TSENS_THRESHOLD_UPPER_LIMIT_MASK)
237 >> 8;
238 else if (!(reg_cntl & TSENS_LOWER_STATUS_CLR))
239 lo_code = (reg_th & TSENS_THRESHOLD_LOWER_LIMIT_MASK);
240 else if (!(reg_cntl & TSENS_MIN_STATUS_MASK))
241 lo_code = (reg_th & TSENS_THRESHOLD_MIN_LIMIT_MASK)
242 >> 16;
243 break;
244 case TSENS_TRIP_STAGE2:
245 code = (reg_th & TSENS_THRESHOLD_UPPER_LIMIT_MASK) >> 8;
246 mask = TSENS_UPPER_STATUS_CLR;
247
248 if (!(reg_cntl & TSENS_MAX_STATUS_MASK))
249 hi_code = (reg_th & TSENS_THRESHOLD_MAX_LIMIT_MASK)
250 >> 24;
251 if (!(reg_cntl & TSENS_LOWER_STATUS_CLR))
252 lo_code = (reg_th & TSENS_THRESHOLD_LOWER_LIMIT_MASK);
253 else if (!(reg_cntl & TSENS_MIN_STATUS_MASK))
254 lo_code = (reg_th & TSENS_THRESHOLD_MIN_LIMIT_MASK)
255 >> 16;
256 break;
257 case TSENS_TRIP_STAGE1:
258 code = (reg_th & TSENS_THRESHOLD_LOWER_LIMIT_MASK) >> 0;
259 mask = TSENS_LOWER_STATUS_CLR;
260
261 if (!(reg_cntl & TSENS_MIN_STATUS_MASK))
262 lo_code = (reg_th & TSENS_THRESHOLD_MIN_LIMIT_MASK)
263 >> 16;
264 if (!(reg_cntl & TSENS_UPPER_STATUS_CLR))
265 hi_code = (reg_th & TSENS_THRESHOLD_UPPER_LIMIT_MASK)
266 >> 8;
267 else if (!(reg_cntl & TSENS_MAX_STATUS_MASK))
268 hi_code = (reg_th & TSENS_THRESHOLD_MAX_LIMIT_MASK)
269 >> 24;
270 break;
271 case TSENS_TRIP_STAGE0:
272 code = (reg_th & TSENS_THRESHOLD_MIN_LIMIT_MASK) >> 16;
273 mask = TSENS_MIN_STATUS_MASK;
274
275 if (!(reg_cntl & TSENS_LOWER_STATUS_CLR))
276 hi_code = (reg_th & TSENS_THRESHOLD_LOWER_LIMIT_MASK);
277 else if (!(reg_cntl & TSENS_UPPER_STATUS_CLR))
278 hi_code = (reg_th & TSENS_THRESHOLD_UPPER_LIMIT_MASK)
279 >> 8;
280 else if (!(reg_cntl & TSENS_MAX_STATUS_MASK))
281 hi_code = (reg_th & TSENS_THRESHOLD_MAX_LIMIT_MASK)
282 >> 24;
283 break;
284 default:
285 return -EINVAL;
286 }
287
288 if (mode == THERMAL_TRIP_ACTIVATION_DISABLED)
289 writel(reg_cntl | mask, TSENS_CNTL_ADDR);
290 else {
291 if (code < lo_code || code > hi_code)
292 return -EINVAL;
293 writel(reg_cntl & ~mask, TSENS_CNTL_ADDR);
294 }
295
296 return 0;
297}
298
299static int tsens_tz_get_trip_temp(struct thermal_zone_device *thermal,
300 int trip, unsigned long *temp)
301{
302 struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
303 unsigned int reg;
304
305 if (!tm_sensor || trip < 0 || !temp)
306 return -EINVAL;
307
308 reg = readl(TSENS_THRESHOLD_ADDR);
309 switch (trip) {
310 case TSENS_TRIP_STAGE3:
311 reg = (reg & TSENS_THRESHOLD_MAX_LIMIT_MASK) >> 24;
312 break;
313 case TSENS_TRIP_STAGE2:
314 reg = (reg & TSENS_THRESHOLD_UPPER_LIMIT_MASK) >> 8;
315 break;
316 case TSENS_TRIP_STAGE1:
317 reg = (reg & TSENS_THRESHOLD_LOWER_LIMIT_MASK) >> 0;
318 break;
319 case TSENS_TRIP_STAGE0:
320 reg = (reg & TSENS_THRESHOLD_MIN_LIMIT_MASK) >> 16;
321 break;
322 default:
323 return -EINVAL;
324 }
325
326 *temp = tsens_tz_code_to_degC(reg);
327
328 return 0;
329}
330
331static int tsens_tz_get_crit_temp(struct thermal_zone_device *thermal,
332 unsigned long *temp)
333{
334 return tsens_tz_get_trip_temp(thermal, TSENS_TRIP_STAGE3, temp);
335}
336
337static int tsens_tz_set_trip_temp(struct thermal_zone_device *thermal,
338 int trip, long temp)
339{
340 struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
341 unsigned int reg_th, reg_cntl;
342 int code, hi_code, lo_code, code_err_chk;
343
344 code_err_chk = code = tsens_tz_degC_to_code(temp);
345 if (!tm_sensor || trip < 0)
346 return -EINVAL;
347
348 lo_code = 0;
349 hi_code = TSENS_THRESHOLD_MAX_CODE;
350
351 reg_cntl = readl(TSENS_CNTL_ADDR);
352 reg_th = readl(TSENS_THRESHOLD_ADDR);
353 switch (trip) {
354 case TSENS_TRIP_STAGE3:
355 code <<= 24;
356 reg_th &= ~TSENS_THRESHOLD_MAX_LIMIT_MASK;
357
358 if (!(reg_cntl & TSENS_UPPER_STATUS_CLR))
359 lo_code = (reg_th & TSENS_THRESHOLD_UPPER_LIMIT_MASK)
360 >> 8;
361 else if (!(reg_cntl & TSENS_LOWER_STATUS_CLR))
362 lo_code = (reg_th & TSENS_THRESHOLD_LOWER_LIMIT_MASK);
363 else if (!(reg_cntl & TSENS_MIN_STATUS_MASK))
364 lo_code = (reg_th & TSENS_THRESHOLD_MIN_LIMIT_MASK)
365 >> 16;
366 break;
367 case TSENS_TRIP_STAGE2:
368 code <<= 8;
369 reg_th &= ~TSENS_THRESHOLD_UPPER_LIMIT_MASK;
370
371 if (!(reg_cntl & TSENS_MAX_STATUS_MASK))
372 hi_code = (reg_th & TSENS_THRESHOLD_MAX_LIMIT_MASK)
373 >> 24;
374 if (!(reg_cntl & TSENS_LOWER_STATUS_CLR))
375 lo_code = (reg_th & TSENS_THRESHOLD_LOWER_LIMIT_MASK);
376 else if (!(reg_cntl & TSENS_MIN_STATUS_MASK))
377 lo_code = (reg_th & TSENS_THRESHOLD_MIN_LIMIT_MASK)
378 >> 16;
379 break;
380 case TSENS_TRIP_STAGE1:
381 reg_th &= ~TSENS_THRESHOLD_LOWER_LIMIT_MASK;
382
383 if (!(reg_cntl & TSENS_MIN_STATUS_MASK))
384 lo_code = (reg_th & TSENS_THRESHOLD_MIN_LIMIT_MASK)
385 >> 16;
386 if (!(reg_cntl & TSENS_UPPER_STATUS_CLR))
387 hi_code = (reg_th & TSENS_THRESHOLD_UPPER_LIMIT_MASK)
388 >> 8;
389 else if (!(reg_cntl & TSENS_MAX_STATUS_MASK))
390 hi_code = (reg_th & TSENS_THRESHOLD_MAX_LIMIT_MASK)
391 >> 24;
392 break;
393 case TSENS_TRIP_STAGE0:
394 code <<= 16;
395 reg_th &= ~TSENS_THRESHOLD_MIN_LIMIT_MASK;
396
397 if (!(reg_cntl & TSENS_LOWER_STATUS_CLR))
398 hi_code = (reg_th & TSENS_THRESHOLD_LOWER_LIMIT_MASK);
399 else if (!(reg_cntl & TSENS_UPPER_STATUS_CLR))
400 hi_code = (reg_th & TSENS_THRESHOLD_UPPER_LIMIT_MASK)
401 >> 8;
402 else if (!(reg_cntl & TSENS_MAX_STATUS_MASK))
403 hi_code = (reg_th & TSENS_THRESHOLD_MAX_LIMIT_MASK)
404 >> 24;
405 break;
406 default:
407 return -EINVAL;
408 }
409
410 if (code_err_chk < lo_code || code_err_chk > hi_code)
411 return -EINVAL;
412
413 writel(reg_th | code, TSENS_THRESHOLD_ADDR);
414 return 0;
415}
416
417static struct thermal_zone_device_ops tsens_thermal_zone_ops = {
418 .get_temp = tsens_tz_get_temp,
419 .get_mode = tsens_tz_get_mode,
420 .set_mode = tsens_tz_set_mode,
421 .get_trip_type = tsens_tz_get_trip_type,
422 .activate_trip_type = tsens_tz_activate_trip_type,
423 .get_trip_temp = tsens_tz_get_trip_temp,
424 .set_trip_temp = tsens_tz_set_trip_temp,
425 .get_crit_temp = tsens_tz_get_crit_temp,
426};
427
428static void notify_uspace_tsens_fn(struct work_struct *work)
429{
430 struct tsens_tm_device *tm = container_of(work, struct tsens_tm_device,
431 work);
432 /* Currently only Sensor0 is supported. We added support
433 to notify only the supported Sensor and this portion
434 needs to be revisited once other sensors are supported */
435 sysfs_notify(&tm->sensor[0].tz_dev->device.kobj,
436 NULL, "type");
437}
438
439static irqreturn_t tsens_isr(int irq, void *data)
440{
441 unsigned int reg = readl(TSENS_CNTL_ADDR);
442
443 writel(reg | TSENS_LOWER_STATUS_CLR | TSENS_UPPER_STATUS_CLR,
444 TSENS_CNTL_ADDR);
445
446 return IRQ_WAKE_THREAD;
447}
448
449static irqreturn_t tsens_isr_thread(int irq, void *data)
450{
451 struct tsens_tm_device *tm = data;
452 unsigned int threshold, threshold_low, i, code, reg, sensor, mask;
453 bool upper_th_x, lower_th_x;
454 int adc_code;
455
456 mask = ~(TSENS_LOWER_STATUS_CLR | TSENS_UPPER_STATUS_CLR);
457 threshold = readl(TSENS_THRESHOLD_ADDR);
458 threshold_low = threshold & TSENS_THRESHOLD_LOWER_LIMIT_MASK;
459 threshold = (threshold & TSENS_THRESHOLD_UPPER_LIMIT_MASK) >> 8;
460 reg = sensor = readl(TSENS_CNTL_ADDR);
461 sensor &= (SENSOR0_EN | SENSOR1_EN | SENSOR2_EN |
462 SENSOR3_EN | SENSOR4_EN);
463 sensor >>= 3;
464 for (i = 0; i < TSENS_NUM_SENSORS; i++) {
465 if (sensor & 1) {
466 code = readl(TSENS_S0_STATUS_ADDR + (i << 2));
467 upper_th_x = code >= threshold;
468 lower_th_x = code <= threshold_low;
469 if (upper_th_x)
470 mask |= TSENS_UPPER_STATUS_CLR;
471 if (lower_th_x)
472 mask |= TSENS_LOWER_STATUS_CLR;
473 if (upper_th_x || lower_th_x) {
474 thermal_zone_device_update(
475 tm->sensor[i].tz_dev);
476
477 /* Notify user space */
478 schedule_work(&tm->work);
479 adc_code = readl(TSENS_S0_STATUS_ADDR
480 + (i << 2));
481 printk(KERN_INFO"\nTrip point triggered by "
482 "current temperature (%d degrees) "
483 "measured by Temperature-Sensor %d\n",
484 tsens_tz_code_to_degC(adc_code), i);
485 }
486 }
487 sensor >>= 1;
488 }
489 writel(reg & mask, TSENS_CNTL_ADDR);
490 return IRQ_HANDLED;
491}
492
493static int __devinit tsens_tm_probe(struct platform_device *pdev)
494{
495 unsigned int reg, i, calib_data, calib_data_backup;
496 int rc;
497
498 calib_data = (readl(TSENS_QFPROM_ADDR) & TSENS_QFPROM_TEMP_SENSOR0_MASK)
499 >> TSENS_QFPROM_TEMP_SENSOR0_SHIFT;
500 calib_data_backup = readl(TSENS_QFPROM_ADDR)
501 >> TSENS_QFPROM_RED_TEMP_SENSOR0_SHIFT;
502
503 if (calib_data_backup)
504 calib_data = calib_data_backup;
505
506 if (!calib_data) {
507 pr_err("%s: No temperature sensor data for calibration"
508 " in QFPROM!\n", __func__);
509 return -ENODEV;
510 }
511
512 tmdev = kzalloc(sizeof(struct tsens_tm_device), GFP_KERNEL);
513 if (tmdev == NULL) {
514 pr_err("%s: kzalloc() failed.\n", __func__);
515 return -ENOMEM;
516 }
517
518 platform_set_drvdata(pdev, tmdev);
519
520 tmdev->offset = TSENS_FACTOR * TSENS_CAL_DEGC
521 - (int)(TSENS_FACTOR * TSENS_SLOPE) * calib_data;
522 tmdev->prev_reading_avail = 0;
523
524 INIT_WORK(&tmdev->work, notify_uspace_tsens_fn);
525
526 reg = readl(TSENS_CNTL_ADDR);
527 writel(reg | TSENS_SW_RST, TSENS_CNTL_ADDR);
528 reg |= TSENS_SLP_CLK_ENA | TSENS_EN | (TSENS_MEASURE_PERIOD << 16) |
529 TSENS_LOWER_STATUS_CLR | TSENS_UPPER_STATUS_CLR |
530 TSENS_MIN_STATUS_MASK | TSENS_MAX_STATUS_MASK |
531 (((1 << TSENS_NUM_SENSORS) - 1) << 3);
532
533 /* set TSENS_CONFIG bits (bits 29:28 of TSENS_CNTL) to '01';
534 this setting found to be optimal. */
535 reg = (reg & ~TSENS_CONFIG_MASK) | (TSENS_CONFIG << TSENS_CONFIG_SHIFT);
536
537 writel(reg, TSENS_CNTL_ADDR);
538
539 writel((TSENS_LOWER_LIMIT_TH << 0) | (TSENS_UPPER_LIMIT_TH << 8) |
540 (TSENS_MIN_LIMIT_TH << 16) | (TSENS_MAX_LIMIT_TH << 24),
541 TSENS_THRESHOLD_ADDR);
542
543 for (i = 0; i < TSENS_NUM_SENSORS; i++) {
544 char name[17];
545 sprintf(name, "tsens_tz_sensor%d", i);
546
547 tmdev->sensor[i].mode = THERMAL_DEVICE_ENABLED;
548 tmdev->sensor[i].tz_dev = thermal_zone_device_register(name,
549 TSENS_TRIP_NUM, &tmdev->sensor[i],
550 &tsens_thermal_zone_ops, 0, 0, 0, 0);
551 if (tmdev->sensor[i].tz_dev == NULL) {
552 pr_err("%s: thermal_zone_device_register() failed.\n",
553 __func__);
554 kfree(tmdev);
555 return -ENODEV;
556 }
557 tmdev->sensor[i].sensor_num = i;
558 thermal_zone_device_update(tmdev->sensor[i].tz_dev);
559 tmdev->sensor[i].mode = THERMAL_DEVICE_DISABLED;
560 }
561
562 rc = request_threaded_irq(TSENS_UPPER_LOWER_INT, tsens_isr,
563 tsens_isr_thread, 0, "tsens", tmdev);
564 if (rc < 0) {
565 pr_err("%s: request_irq FAIL: %d\n", __func__, rc);
566 kfree(tmdev);
567 return rc;
568 }
569
570 writel(reg & ~((((1 << TSENS_NUM_SENSORS) - 1) << 3)
571 | TSENS_SLP_CLK_ENA | TSENS_EN), TSENS_CNTL_ADDR);
572 pr_notice("%s: OK\n", __func__);
573 return 0;
574}
575
576static int __devexit tsens_tm_remove(struct platform_device *pdev)
577{
578 struct tsens_tm_device *tmdev = platform_get_drvdata(pdev);
579 unsigned int reg, i;
580
581 reg = readl(TSENS_CNTL_ADDR);
582 writel(reg & ~(TSENS_SLP_CLK_ENA | TSENS_EN), TSENS_CNTL_ADDR);
583
584 for (i = 0; i < TSENS_NUM_SENSORS; i++)
585 thermal_zone_device_unregister(tmdev->sensor[i].tz_dev);
586 platform_set_drvdata(pdev, NULL);
587 free_irq(TSENS_UPPER_LOWER_INT, tmdev);
588 kfree(tmdev);
589
590 return 0;
591}
592
593static struct platform_driver tsens_tm_driver = {
594 .probe = tsens_tm_probe,
595 .remove = __devexit_p(tsens_tm_remove),
596 .driver = {
597 .name = "tsens-tm",
598 .owner = THIS_MODULE,
599 },
600};
601
602static int __init tsens_init(void)
603{
604 return platform_driver_register(&tsens_tm_driver);
605}
606
607static void __exit tsens_exit(void)
608{
609 platform_driver_unregister(&tsens_tm_driver);
610}
611
612module_init(tsens_init);
613module_exit(tsens_exit);
614
615MODULE_LICENSE("GPL v2");
616MODULE_DESCRIPTION("MSM Temperature Sensor driver");
617MODULE_VERSION("1.0");
618MODULE_ALIAS("platform:tsens-tm");