blob: d9f9c9ea05e9469ce61059202acf889048ac8ee9 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/*
2 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14/*
15 * Qualcomm PMIC PM8xxx Thermal Manager driver
16 */
17
18#define pr_fmt(fmt) "%s: " fmt, __func__
19
20#include <linux/module.h>
21#include <linux/err.h>
22#include <linux/string.h>
23#include <linux/kernel.h>
24#include <linux/slab.h>
25#include <linux/mutex.h>
26#include <linux/thermal.h>
27#include <linux/interrupt.h>
28#include <linux/platform_device.h>
29#include <linux/mfd/pm8xxx/core.h>
30#include <linux/mfd/pm8xxx/tm.h>
31#include <linux/completion.h>
Siddartha Mohanadoss77d106e2011-09-20 16:25:59 -070032#include <linux/mfd/pm8xxx/pm8921-adc.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070033
34/* Register TEMP_ALARM_CTRL bits */
35#define TEMP_ALARM_CTRL_ST3_SD 0x80
36#define TEMP_ALARM_CTRL_ST2_SD 0x40
37#define TEMP_ALARM_CTRL_STATUS_MASK 0x30
38#define TEMP_ALARM_CTRL_STATUS_SHIFT 4
39#define TEMP_ALARM_CTRL_THRESH_MASK 0x0C
40#define TEMP_ALARM_CTRL_THRESH_SHIFT 2
41#define TEMP_ALARM_CTRL_OVRD_ST3 0x02
42#define TEMP_ALARM_CTRL_OVRD_ST2 0x01
43#define TEMP_ALARM_CTRL_OVRD_MASK 0x03
44
45#define TEMP_STAGE_STEP 20000 /* Stage step: 20.000 C */
46#define TEMP_STAGE_HYSTERESIS 2000
47
48#define TEMP_THRESH_MIN 105000 /* Threshold Min: 105 C */
49#define TEMP_THRESH_STEP 5000 /* Threshold step: 5 C */
50
51/* Register TEMP_ALARM_PWM bits */
52#define TEMP_ALARM_PWM_EN_MASK 0xC0
53#define TEMP_ALARM_PWM_EN_SHIFT 6
54#define TEMP_ALARM_PWM_PER_PRE_MASK 0x38
55#define TEMP_ALARM_PWM_PER_PRE_SHIFT 3
56#define TEMP_ALARM_PWM_PER_DIV_MASK 0x07
57#define TEMP_ALARM_PWM_PER_DIV_SHIFT 0
58
59/* Trips: from critical to less critical */
60#define TRIP_STAGE3 0
61#define TRIP_STAGE2 1
62#define TRIP_STAGE1 2
63#define TRIP_NUM 3
64
65struct pm8xxx_tm_chip {
66 struct pm8xxx_tm_core_data cdata;
67 struct work_struct irq_work;
68 struct device *dev;
69 struct thermal_zone_device *tz_dev;
70 unsigned long temp;
71 enum thermal_device_mode mode;
72 unsigned int thresh;
73 unsigned int stage;
74 unsigned int tempstat_irq;
75 unsigned int overtemp_irq;
76 void *adc_handle;
77};
78
79enum pmic_thermal_override_mode {
80 SOFTWARE_OVERRIDE_DISABLED = 0,
81 SOFTWARE_OVERRIDE_ENABLED,
82};
83
84static inline int pm8xxx_tm_read_ctrl(struct pm8xxx_tm_chip *chip, u8 *reg)
85{
86 int rc;
87
88 rc = pm8xxx_readb(chip->dev->parent,
89 chip->cdata.reg_addr_temp_alarm_ctrl, reg);
90 if (rc)
91 pr_err("%s: pm8xxx_readb(0x%03X) failed, rc=%d\n",
92 chip->cdata.tm_name,
93 chip->cdata.reg_addr_temp_alarm_ctrl, rc);
94
95 return rc;
96}
97
98static inline int pm8xxx_tm_write_ctrl(struct pm8xxx_tm_chip *chip, u8 reg)
99{
100 int rc;
101
102 rc = pm8xxx_writeb(chip->dev->parent,
103 chip->cdata.reg_addr_temp_alarm_ctrl, reg);
104 if (rc)
105 pr_err("%s: pm8xxx_writeb(0x%03X)=0x%02X failed, rc=%d\n",
106 chip->cdata.tm_name,
107 chip->cdata.reg_addr_temp_alarm_ctrl, reg, rc);
108
109 return rc;
110}
111
112static inline int pm8xxx_tm_write_pwm(struct pm8xxx_tm_chip *chip, u8 reg)
113{
114 int rc;
115
116 rc = pm8xxx_writeb(chip->dev->parent,
117 chip->cdata.reg_addr_temp_alarm_pwm, reg);
118 if (rc)
119 pr_err("%s: pm8xxx_writeb(0x%03X)=0x%02X failed, rc=%d\n",
120 chip->cdata.tm_name,
121 chip->cdata.reg_addr_temp_alarm_pwm, reg, rc);
122
123 return rc;
124}
125
126static inline int
127pm8xxx_tm_shutdown_override(struct pm8xxx_tm_chip *chip,
128 enum pmic_thermal_override_mode mode)
129{
130 int rc;
131 u8 reg;
132
133 rc = pm8xxx_tm_read_ctrl(chip, &reg);
134 if (rc < 0)
135 return rc;
136
137 reg &= ~(TEMP_ALARM_CTRL_OVRD_MASK | TEMP_ALARM_CTRL_STATUS_MASK);
138 if (mode == SOFTWARE_OVERRIDE_ENABLED)
139 reg |= (TEMP_ALARM_CTRL_OVRD_ST3 | TEMP_ALARM_CTRL_OVRD_ST2) &
140 TEMP_ALARM_CTRL_OVRD_MASK;
141
142 rc = pm8xxx_tm_write_ctrl(chip, reg);
143
144 return rc;
145}
146
147/*
148 * This function initializes the internal temperature value based on only the
149 * current thermal stage and threshold.
150 */
151static int pm8xxx_tm_init_temp_no_adc(struct pm8xxx_tm_chip *chip)
152{
153 int rc;
154 u8 reg;
155
156 rc = pm8xxx_tm_read_ctrl(chip, &reg);
157 if (rc < 0)
158 return rc;
159
160 chip->stage = (reg & TEMP_ALARM_CTRL_STATUS_MASK)
161 >> TEMP_ALARM_CTRL_STATUS_SHIFT;
162 chip->thresh = (reg & TEMP_ALARM_CTRL_THRESH_MASK)
163 >> TEMP_ALARM_CTRL_THRESH_SHIFT;
164
165 if (chip->stage)
166 chip->temp = chip->thresh * TEMP_THRESH_MIN +
167 (chip->stage - 1) * TEMP_STAGE_STEP +
168 TEMP_THRESH_MIN;
169 else
170 chip->temp = chip->cdata.default_no_adc_temp;
171
172 return 0;
173}
174
175/*
176 * This function updates the internal temperature value based on the
177 * current thermal stage and threshold as well as the previous stage
178 */
179static int pm8xxx_tm_update_temp_no_adc(struct pm8xxx_tm_chip *chip)
180{
181 unsigned int stage;
182 int rc;
183 u8 reg;
184
185 rc = pm8xxx_tm_read_ctrl(chip, &reg);
186 if (rc < 0)
187 return rc;
188
189 stage = (reg & TEMP_ALARM_CTRL_STATUS_MASK)
190 >> TEMP_ALARM_CTRL_STATUS_SHIFT;
191 chip->thresh = (reg & TEMP_ALARM_CTRL_THRESH_MASK)
192 >> TEMP_ALARM_CTRL_THRESH_SHIFT;
193
194 if (stage > chip->stage) {
195 /* increasing stage, use lower bound */
196 chip->temp = (stage - 1) * TEMP_STAGE_STEP
197 + chip->thresh * TEMP_THRESH_STEP
198 + TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN;
199 } else if (stage < chip->stage) {
200 /* decreasing stage, use upper bound */
201 chip->temp = stage * TEMP_STAGE_STEP
202 + chip->thresh * TEMP_THRESH_STEP
203 - TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN;
204 }
205
206 chip->stage = stage;
207
208 return 0;
209}
210
211static int pm8xxx_tz_get_temp_no_adc(struct thermal_zone_device *thermal,
212 unsigned long *temp)
213{
214 struct pm8xxx_tm_chip *chip = thermal->devdata;
215 int rc;
216
217 if (!chip || !temp)
218 return -EINVAL;
219
220 rc = pm8xxx_tm_update_temp_no_adc(chip);
221 if (rc < 0)
222 return rc;
223
224 *temp = chip->temp;
225
226 return 0;
227}
228
229static int pm8xxx_tz_get_temp_pm8921_adc(struct thermal_zone_device *thermal,
230 unsigned long *temp)
231{
232 struct pm8xxx_tm_chip *chip = thermal->devdata;
233 struct pm8921_adc_chan_result result = {
234 .physical = 0lu,
235 };
236 int rc;
237
238 if (!chip || !temp)
239 return -EINVAL;
240
241 *temp = chip->temp;
242
243 rc = pm8921_adc_read(chip->cdata.adc_channel, &result);
244 if (rc < 0) {
245 pr_err("%s: adc_channel_read_result() failed, rc = %d\n",
246 chip->cdata.tm_name, rc);
247 return rc;
248 }
249
250 *temp = result.physical;
251 chip->temp = result.physical;
252
253 return 0;
254}
255
256static int pm8xxx_tz_get_mode(struct thermal_zone_device *thermal,
257 enum thermal_device_mode *mode)
258{
259 struct pm8xxx_tm_chip *chip = thermal->devdata;
260
261 if (!chip || !mode)
262 return -EINVAL;
263
264 *mode = chip->mode;
265
266 return 0;
267}
268
269static int pm8xxx_tz_set_mode(struct thermal_zone_device *thermal,
270 enum thermal_device_mode mode)
271{
272 struct pm8xxx_tm_chip *chip = thermal->devdata;
273
274 if (!chip)
275 return -EINVAL;
276
277 if (mode != chip->mode) {
278 if (mode == THERMAL_DEVICE_ENABLED)
279 pm8xxx_tm_shutdown_override(chip,
280 SOFTWARE_OVERRIDE_ENABLED);
281 else
282 pm8xxx_tm_shutdown_override(chip,
283 SOFTWARE_OVERRIDE_DISABLED);
284 }
285 chip->mode = mode;
286
287 return 0;
288}
289
290static int pm8xxx_tz_get_trip_type(struct thermal_zone_device *thermal,
291 int trip, enum thermal_trip_type *type)
292{
293 if (trip < 0 || !type)
294 return -EINVAL;
295
296 switch (trip) {
297 case TRIP_STAGE3:
298 *type = THERMAL_TRIP_CRITICAL;
299 break;
300 case TRIP_STAGE2:
301 *type = THERMAL_TRIP_HOT;
302 break;
303 case TRIP_STAGE1:
304 *type = THERMAL_TRIP_HOT;
305 break;
306 default:
307 return -EINVAL;
308 }
309
310 return 0;
311}
312
313static int pm8xxx_tz_get_trip_temp(struct thermal_zone_device *thermal,
314 int trip, unsigned long *temp)
315{
316 struct pm8xxx_tm_chip *chip = thermal->devdata;
317 int thresh_temp;
318
319 if (!chip || trip < 0 || !temp)
320 return -EINVAL;
321
322 thresh_temp = chip->thresh * TEMP_THRESH_STEP +
323 TEMP_THRESH_MIN;
324
325 switch (trip) {
326 case TRIP_STAGE3:
327 thresh_temp += 2 * TEMP_STAGE_STEP;
328 break;
329 case TRIP_STAGE2:
330 thresh_temp += TEMP_STAGE_STEP;
331 break;
332 case TRIP_STAGE1:
333 break;
334 default:
335 return -EINVAL;
336 }
337
338 *temp = thresh_temp;
339
340 return 0;
341}
342
343static int pm8xxx_tz_get_crit_temp(struct thermal_zone_device *thermal,
344 unsigned long *temp)
345{
346 struct pm8xxx_tm_chip *chip = thermal->devdata;
347
348 if (!chip || !temp)
349 return -EINVAL;
350
351 *temp = chip->thresh * TEMP_THRESH_STEP + TEMP_THRESH_MIN +
352 2 * TEMP_STAGE_STEP;
353
354 return 0;
355}
356
357static struct thermal_zone_device_ops pm8xxx_thermal_zone_ops_no_adc = {
358 .get_temp = pm8xxx_tz_get_temp_no_adc,
359 .get_mode = pm8xxx_tz_get_mode,
360 .set_mode = pm8xxx_tz_set_mode,
361 .get_trip_type = pm8xxx_tz_get_trip_type,
362 .get_trip_temp = pm8xxx_tz_get_trip_temp,
363 .get_crit_temp = pm8xxx_tz_get_crit_temp,
364};
365
366static struct thermal_zone_device_ops pm8xxx_thermal_zone_ops_pm8921_adc = {
367 .get_temp = pm8xxx_tz_get_temp_pm8921_adc,
368 .get_mode = pm8xxx_tz_get_mode,
369 .set_mode = pm8xxx_tz_set_mode,
370 .get_trip_type = pm8xxx_tz_get_trip_type,
371 .get_trip_temp = pm8xxx_tz_get_trip_temp,
372 .get_crit_temp = pm8xxx_tz_get_crit_temp,
373};
374
375static void pm8xxx_tm_work(struct work_struct *work)
376{
377 struct pm8xxx_tm_chip *chip
378 = container_of(work, struct pm8xxx_tm_chip, irq_work);
379 int rc;
380 u8 reg;
381
382 rc = pm8xxx_tm_read_ctrl(chip, &reg);
383 if (rc < 0)
384 goto bail;
385
386 if (chip->cdata.adc_type == PM8XXX_TM_ADC_NONE) {
387 rc = pm8xxx_tm_update_temp_no_adc(chip);
388 if (rc < 0)
389 goto bail;
390 pr_info("%s: Temp Alarm - stage=%u, threshold=%u, "
391 "temp=%lu mC\n", chip->cdata.tm_name, chip->stage,
392 chip->thresh, chip->temp);
393 } else {
394 chip->stage = (reg & TEMP_ALARM_CTRL_STATUS_MASK)
395 >> TEMP_ALARM_CTRL_STATUS_SHIFT;
396 chip->thresh = (reg & TEMP_ALARM_CTRL_THRESH_MASK)
397 >> TEMP_ALARM_CTRL_THRESH_SHIFT;
398 pr_info("%s: Temp Alarm - stage=%u, threshold=%u\n",
399 chip->cdata.tm_name, chip->stage, chip->thresh);
400 }
401
402 /* Clear status bits. */
403 if (reg & (TEMP_ALARM_CTRL_ST2_SD | TEMP_ALARM_CTRL_ST3_SD)) {
404 reg &= ~(TEMP_ALARM_CTRL_ST2_SD | TEMP_ALARM_CTRL_ST3_SD
405 | TEMP_ALARM_CTRL_STATUS_MASK);
406
407 pm8xxx_tm_write_ctrl(chip, reg);
408 }
409
410 thermal_zone_device_update(chip->tz_dev);
411
412 /* Notify user space */
413 if (chip->mode == THERMAL_DEVICE_ENABLED)
414 kobject_uevent(&chip->tz_dev->device.kobj, KOBJ_CHANGE);
415
416bail:
417 enable_irq(chip->tempstat_irq);
418 enable_irq(chip->overtemp_irq);
419}
420
421static irqreturn_t pm8xxx_tm_isr(int irq, void *data)
422{
423 struct pm8xxx_tm_chip *chip = data;
424
425 disable_irq_nosync(chip->tempstat_irq);
426 disable_irq_nosync(chip->overtemp_irq);
427 schedule_work(&chip->irq_work);
428
429 return IRQ_HANDLED;
430}
431
432static int pm8xxx_tm_init_reg(struct pm8xxx_tm_chip *chip)
433{
434 int rc;
435 u8 reg;
436
437 rc = pm8xxx_tm_read_ctrl(chip, &reg);
438 if (rc < 0)
439 return rc;
440
441 chip->stage = (reg & TEMP_ALARM_CTRL_STATUS_MASK)
442 >> TEMP_ALARM_CTRL_STATUS_SHIFT;
443 chip->temp = 0;
444
445 /* Use temperature threshold set 0: (105, 125, 145) */
446 chip->thresh = 0;
447 reg = (chip->thresh << TEMP_ALARM_CTRL_THRESH_SHIFT)
448 & TEMP_ALARM_CTRL_THRESH_MASK;
449 rc = pm8xxx_tm_write_ctrl(chip, reg);
450 if (rc < 0)
451 return rc;
452
453 /*
454 * Set the PMIC alarm module PWM to have a frequency of 8 Hz. This
455 * helps cut down on the number of unnecessary interrupts fired when
456 * changing between thermal stages. Also, Enable the over temperature
457 * PWM whenever the PMIC is enabled.
458 */
459 reg = (1 << TEMP_ALARM_PWM_EN_SHIFT)
460 | (3 << TEMP_ALARM_PWM_PER_PRE_SHIFT)
461 | (3 << TEMP_ALARM_PWM_PER_DIV_SHIFT);
462
463 rc = pm8xxx_tm_write_pwm(chip, reg);
464
465 return rc;
466}
467
468static int __devinit pm8xxx_tm_probe(struct platform_device *pdev)
469{
470 const struct pm8xxx_tm_core_data *cdata = pdev->dev.platform_data;
471 struct thermal_zone_device_ops *tz_ops;
472 struct pm8xxx_tm_chip *chip;
473 struct resource *res;
474 int rc = 0;
475
476 if (!cdata) {
477 pr_err("missing core data\n");
478 return -EINVAL;
479 }
480
481 chip = kzalloc(sizeof(struct pm8xxx_tm_chip), GFP_KERNEL);
482 if (chip == NULL) {
483 pr_err("kzalloc() failed.\n");
484 return -ENOMEM;
485 }
486
487 chip->dev = &pdev->dev;
488 memcpy(&(chip->cdata), cdata, sizeof(struct pm8xxx_tm_core_data));
489
490 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
491 chip->cdata.irq_name_temp_stat);
492 if (res) {
493 chip->tempstat_irq = res->start;
494 } else {
495 pr_err("temp stat IRQ not specified\n");
496 goto err_free_chip;
497 }
498
499 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
500 chip->cdata.irq_name_over_temp);
501 if (res) {
502 chip->overtemp_irq = res->start;
503 } else {
504 pr_err("over temp IRQ not specified\n");
505 goto err_free_chip;
506 }
507
508 /* Select proper thermal zone ops functions based on ADC type. */
509 if (chip->cdata.adc_type == PM8XXX_TM_ADC_PM8921_ADC)
510 tz_ops = &pm8xxx_thermal_zone_ops_pm8921_adc;
511 else
512 tz_ops = &pm8xxx_thermal_zone_ops_no_adc;
513
514 chip->tz_dev = thermal_zone_device_register(chip->cdata.tm_name,
515 TRIP_NUM, chip, tz_ops, 0, 0, 0, 0);
516 if (chip->tz_dev == NULL) {
517 pr_err("thermal_zone_device_register() failed.\n");
518 rc = -ENODEV;
519 goto err_free_chip;
520 }
521
522 rc = pm8xxx_tm_init_reg(chip);
523 if (rc < 0)
524 goto err_free_tz;
525 rc = pm8xxx_tm_shutdown_override(chip, SOFTWARE_OVERRIDE_DISABLED);
526 if (rc < 0)
527 goto err_free_tz;
528
529 if (chip->cdata.adc_type == PM8XXX_TM_ADC_NONE) {
530 rc = pm8xxx_tm_init_temp_no_adc(chip);
531 if (rc < 0)
532 goto err_free_tz;
533 }
534
535 /* Start in HW control; switch to SW control when user changes mode. */
536 chip->mode = THERMAL_DEVICE_DISABLED;
537 thermal_zone_device_update(chip->tz_dev);
538
539 INIT_WORK(&chip->irq_work, pm8xxx_tm_work);
540
541 rc = request_irq(chip->tempstat_irq, pm8xxx_tm_isr, IRQF_TRIGGER_RISING,
542 chip->cdata.irq_name_temp_stat, chip);
543 if (rc < 0) {
544 pr_err("request_irq(%d) failed: %d\n", chip->tempstat_irq, rc);
545 goto err_cancel_work;
546 }
547
548 rc = request_irq(chip->overtemp_irq, pm8xxx_tm_isr, IRQF_TRIGGER_RISING,
549 chip->cdata.irq_name_over_temp, chip);
550 if (rc < 0) {
551 pr_err("request_irq(%d) failed: %d\n", chip->overtemp_irq, rc);
552 goto err_free_irq_tempstat;
553 }
554
555 platform_set_drvdata(pdev, chip);
556
557 pr_info("OK\n");
558
559 return 0;
560
561err_free_irq_tempstat:
562 free_irq(chip->tempstat_irq, chip);
563err_cancel_work:
564 cancel_work_sync(&chip->irq_work);
565err_free_tz:
566 thermal_zone_device_unregister(chip->tz_dev);
567err_free_chip:
568 kfree(chip);
569 return rc;
570}
571
572static int __devexit pm8xxx_tm_remove(struct platform_device *pdev)
573{
574 struct pm8xxx_tm_chip *chip = platform_get_drvdata(pdev);
575
576 if (chip) {
577 platform_set_drvdata(pdev, NULL);
578 cancel_work_sync(&chip->irq_work);
579 free_irq(chip->overtemp_irq, chip);
580 free_irq(chip->tempstat_irq, chip);
581 pm8xxx_tm_shutdown_override(chip, SOFTWARE_OVERRIDE_DISABLED);
582 thermal_zone_device_unregister(chip->tz_dev);
583 kfree(chip);
584 }
585 return 0;
586}
587
588#ifdef CONFIG_PM
589static int pm8xxx_tm_suspend(struct device *dev)
590{
591 struct platform_device *pdev = to_platform_device(dev);
592 struct pm8xxx_tm_chip *chip = platform_get_drvdata(pdev);
593
594 /* Clear override bits in suspend to allow hardware control */
595 pm8xxx_tm_shutdown_override(chip, SOFTWARE_OVERRIDE_DISABLED);
596
597 return 0;
598}
599
600static int pm8xxx_tm_resume(struct device *dev)
601{
602 struct platform_device *pdev = to_platform_device(dev);
603 struct pm8xxx_tm_chip *chip = platform_get_drvdata(pdev);
604
605 /* Override hardware actions so software can control */
606 if (chip->mode == THERMAL_DEVICE_ENABLED)
607 pm8xxx_tm_shutdown_override(chip, SOFTWARE_OVERRIDE_ENABLED);
608
609 return 0;
610}
611
612static const struct dev_pm_ops pm8xxx_tm_pm_ops = {
613 .suspend = pm8xxx_tm_suspend,
614 .resume = pm8xxx_tm_resume,
615};
616
617#define PM8XXX_TM_PM_OPS (&pm8xxx_tm_pm_ops)
618#else
619#define PM8XXX_TM_PM_OPS NULL
620#endif
621
622static struct platform_driver pm8xxx_tm_driver = {
623 .probe = pm8xxx_tm_probe,
624 .remove = __devexit_p(pm8xxx_tm_remove),
625 .driver = {
626 .name = PM8XXX_TM_DEV_NAME,
627 .owner = THIS_MODULE,
628 .pm = PM8XXX_TM_PM_OPS,
629 },
630};
631
632static int __init pm8xxx_tm_init(void)
633{
634 return platform_driver_register(&pm8xxx_tm_driver);
635}
636
637static void __exit pm8xxx_tm_exit(void)
638{
639 platform_driver_unregister(&pm8xxx_tm_driver);
640}
641
642module_init(pm8xxx_tm_init);
643module_exit(pm8xxx_tm_exit);
644
645MODULE_LICENSE("GPL v2");
646MODULE_DESCRIPTION("PM8xxx Thermal Manager driver");
647MODULE_VERSION("1.0");
648MODULE_ALIAS("platform:" PM8XXX_TM_DEV_NAME);