blob: 7398b7b5d3912d280cecb9e1fc12d9da40626ffd [file] [log] [blame]
David Collins8885f792017-01-26 14:36:34 -08001/*
David Collins08f2a842018-01-11 16:42:36 -08002 * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
David Collins8885f792017-01-26 14:36:34 -08003 *
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#define pr_fmt(fmt) "%s: " fmt, __func__
15
16#include <linux/module.h>
17#include <linux/delay.h>
18#include <linux/err.h>
19#include <linux/string.h>
20#include <linux/interrupt.h>
21#include <linux/kernel.h>
22#include <linux/regmap.h>
23#include <linux/slab.h>
24#include <linux/spmi.h>
25#include <linux/platform_device.h>
26#include <linux/of.h>
27#include <linux/of_device.h>
28#include <linux/thermal.h>
29#include <linux/qpnp/qpnp-adc.h>
30
Ram Chandrasekar5bca6482017-03-31 13:18:07 -060031#include "thermal_core.h"
32
David Collins8885f792017-01-26 14:36:34 -080033#define QPNP_TM_DRIVER_NAME "qcom,qpnp-temp-alarm"
34
35enum qpnp_tm_registers {
36 QPNP_TM_REG_TYPE = 0x04,
37 QPNP_TM_REG_SUBTYPE = 0x05,
38 QPNP_TM_REG_STATUS = 0x08,
39 QPNP_TM_REG_SHUTDOWN_CTRL1 = 0x40,
40 QPNP_TM_REG_SHUTDOWN_CTRL2 = 0x42,
41 QPNP_TM_REG_ALARM_CTRL = 0x46,
42};
43
44#define QPNP_TM_TYPE 0x09
45#define QPNP_TM_SUBTYPE_GEN1 0x08
46#define QPNP_TM_SUBTYPE_GEN2 0x09
47
48#define STATUS_STATE_MASK 0x70
49#define STATUS_STATE_SHIFT 4
50#define STATUS_STAGE_MASK 0x03
51
52#define SHUTDOWN_CTRL1_OVERRIDE_STAGE3 0x80
53#define SHUTDOWN_CTRL1_OVERRIDE_STAGE2 0x40
54#define SHUTDOWN_CTRL1_CLK_RATE_MASK 0x0C
55#define SHUTDOWN_CTRL1_CLK_RATE_SHIFT 2
56#define SHUTDOWN_CTRL1_THRESHOLD_MASK 0x03
57
58#define SHUTDOWN_CTRL2_CLEAR_STAGE3 0x80
59#define SHUTDOWN_CTRL2_CLEAR_STAGE2 0x40
60
61#define ALARM_CTRL_FORCE_ENABLE 0x80
62#define ALARM_CTRL_FOLLOW_HW_ENABLE 0x01
63
64#define TEMP_STAGE_STEP 20000 /* Stage step: 20.000 C */
65#define TEMP_STAGE_HYSTERESIS 2000
66
67#define TEMP_THRESH_MIN 105000 /* Threshold Min: 105 C */
68#define TEMP_THRESH_STEP 5000 /* Threshold step: 5 C */
69
70#define THRESH_MIN 0
71#define THRESH_MAX 3
72
73#define CLOCK_RATE_MIN 0
74#define CLOCK_RATE_MAX 3
75
76/* Trip points from most critical to least critical */
77#define TRIP_STAGE3 0
78#define TRIP_STAGE2 1
79#define TRIP_STAGE1 2
80#define TRIP_NUM 3
81
82enum qpnp_tm_adc_type {
83 QPNP_TM_ADC_NONE, /* Estimates temp based on overload level. */
84 QPNP_TM_ADC_QPNP_ADC,
85};
86
87/*
88 * Temperature in millicelcius reported during stage 0 if no ADC is present and
89 * no value has been specified via device tree.
90 */
91#define DEFAULT_NO_ADC_TEMP 37000
92
93struct qpnp_tm_chip {
94 struct delayed_work irq_work;
95 struct platform_device *pdev;
96 struct regmap *regmap;
97 struct thermal_zone_device *tz_dev;
98 const char *tm_name;
99 unsigned int subtype;
100 enum qpnp_tm_adc_type adc_type;
101 int temperature;
David Collins8885f792017-01-26 14:36:34 -0800102 unsigned int thresh;
103 unsigned int clock_rate;
104 unsigned int stage;
105 unsigned int prev_stage;
106 int irq;
107 enum qpnp_vadc_channels adc_channel;
108 u16 base_addr;
David Collins8885f792017-01-26 14:36:34 -0800109 struct qpnp_vadc_chip *vadc_dev;
110};
111
112/* Delay between TEMP_STAT IRQ going high and status value changing in ms. */
113#define STATUS_REGISTER_DELAY_MS 40
114
David Collins8885f792017-01-26 14:36:34 -0800115/* This array maps from GEN2 alarm state to GEN1 alarm stage */
116const unsigned int alarm_state_map[8] = {0, 1, 1, 2, 2, 3, 3, 3};
117
118static inline int qpnp_tm_read(struct qpnp_tm_chip *chip, u16 addr, u8 *buf,
119 int len)
120{
121 int rc;
122
123 rc = regmap_bulk_read(chip->regmap, chip->base_addr + addr, buf, len);
124
125 if (rc)
126 dev_err(&chip->pdev->dev,
127 "%s: regmap_bulk_readl failed. sid=%d, addr=%04X, len=%d, rc=%d\n",
128 __func__,
129 to_spmi_device(chip->pdev->dev.parent)->usid,
130 chip->base_addr + addr,
131 len, rc);
132
133 return rc;
134}
135
136static inline int qpnp_tm_write(struct qpnp_tm_chip *chip, u16 addr, u8 *buf,
137 int len)
138{
139 int rc;
140
141 rc = regmap_bulk_write(chip->regmap, chip->base_addr + addr, buf, len);
142
143 if (rc)
144 dev_err(&chip->pdev->dev,
145 "%s: regmap_bulk_write failed. sid=%d, addr=%04X, len=%d, rc=%d\n",
146 __func__,
147 to_spmi_device(chip->pdev->dev.parent)->usid,
148 chip->base_addr + addr,
149 len, rc);
150
151 return rc;
152}
153
David Collins8885f792017-01-26 14:36:34 -0800154static int qpnp_tm_update_temp(struct qpnp_tm_chip *chip)
155{
156 struct qpnp_vadc_result adc_result;
157 int rc;
158
159 rc = qpnp_vadc_read(chip->vadc_dev, chip->adc_channel, &adc_result);
160 if (!rc)
161 chip->temperature = adc_result.physical;
162 else
163 dev_err(&chip->pdev->dev,
164 "%s: qpnp_vadc_read(%d) failed, rc=%d\n",
165 __func__, chip->adc_channel, rc);
166
167 return rc;
168}
169
170static int qpnp_tm_get_temp_stage(struct qpnp_tm_chip *chip,
171 unsigned int *stage)
172{
173 int rc;
174 u8 reg;
175
176 rc = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, &reg, 1);
177 if (rc < 0)
178 return rc;
179
180 if (chip->subtype == QPNP_TM_SUBTYPE_GEN1)
181 *stage = reg & STATUS_STAGE_MASK;
182 else
183 *stage = (reg & STATUS_STATE_MASK) >> STATUS_STATE_SHIFT;
184
185 return 0;
186}
187
188/*
189 * This function initializes the internal temperature value based on only the
190 * current thermal stage and threshold.
191 */
192static int qpnp_tm_init_temp_no_adc(struct qpnp_tm_chip *chip)
193{
194 unsigned int stage;
195 int rc;
196
197 rc = qpnp_tm_get_temp_stage(chip, &chip->stage);
198 if (rc < 0)
199 return rc;
200
201 stage = chip->subtype == QPNP_TM_SUBTYPE_GEN1
202 ? chip->stage : alarm_state_map[chip->stage];
203
204 if (stage)
205 chip->temperature = chip->thresh * TEMP_THRESH_STEP +
206 (stage - 1) * TEMP_STAGE_STEP +
207 TEMP_THRESH_MIN;
208
209 return 0;
210}
211
212/*
213 * This function updates the internal temperature value based on the
214 * current thermal stage and threshold as well as the previous stage
215 */
216static int qpnp_tm_update_temp_no_adc(struct qpnp_tm_chip *chip)
217{
218 unsigned int stage, stage_new, stage_old;
219 int rc;
220
221 rc = qpnp_tm_get_temp_stage(chip, &stage);
222 if (rc < 0)
223 return rc;
224
225 if (chip->subtype == QPNP_TM_SUBTYPE_GEN1) {
226 stage_new = stage;
227 stage_old = chip->stage;
228 } else {
229 stage_new = alarm_state_map[stage];
230 stage_old = alarm_state_map[chip->stage];
231 }
232
233 if (stage_new > stage_old) {
234 /* increasing stage, use lower bound */
235 chip->temperature = (stage_new - 1) * TEMP_STAGE_STEP
236 + chip->thresh * TEMP_THRESH_STEP
237 + TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN;
238 } else if (stage_new < stage_old) {
239 /* decreasing stage, use upper bound */
240 chip->temperature = stage_new * TEMP_STAGE_STEP
241 + chip->thresh * TEMP_THRESH_STEP
242 - TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN;
243 }
244
245 chip->stage = stage;
246
247 return 0;
248}
249
Ram Chandrasekar5bca6482017-03-31 13:18:07 -0600250static int qpnp_tz_get_temp_no_adc(void *data, int *temperature)
David Collins8885f792017-01-26 14:36:34 -0800251{
Ram Chandrasekar5bca6482017-03-31 13:18:07 -0600252 struct qpnp_tm_chip *chip = (struct qpnp_tm_chip *)data;
David Collins8885f792017-01-26 14:36:34 -0800253 int rc;
254
255 if (!temperature)
256 return -EINVAL;
257
258 rc = qpnp_tm_update_temp_no_adc(chip);
259 if (rc < 0)
260 return rc;
261
262 *temperature = chip->temperature;
263
264 return 0;
265}
266
Ram Chandrasekar5bca6482017-03-31 13:18:07 -0600267static int qpnp_tz_get_temp_qpnp_adc(void *data, int *temperature)
David Collins8885f792017-01-26 14:36:34 -0800268{
Ram Chandrasekar5bca6482017-03-31 13:18:07 -0600269 struct qpnp_tm_chip *chip = (struct qpnp_tm_chip *)data;
David Collins8885f792017-01-26 14:36:34 -0800270 int rc;
271
272 if (!temperature)
273 return -EINVAL;
274
275 rc = qpnp_tm_update_temp(chip);
276 if (rc < 0) {
277 dev_err(&chip->pdev->dev,
278 "%s: %s: adc read failed, rc = %d\n",
279 __func__, chip->tm_name, rc);
280 return rc;
281 }
282
283 *temperature = chip->temperature;
284
285 return 0;
286}
287
Ram Chandrasekar5bca6482017-03-31 13:18:07 -0600288static struct thermal_zone_of_device_ops qpnp_thermal_zone_ops_no_adc = {
David Collins8885f792017-01-26 14:36:34 -0800289 .get_temp = qpnp_tz_get_temp_no_adc,
David Collins8885f792017-01-26 14:36:34 -0800290};
291
Ram Chandrasekar5bca6482017-03-31 13:18:07 -0600292static struct thermal_zone_of_device_ops qpnp_thermal_zone_ops_qpnp_adc = {
David Collins8885f792017-01-26 14:36:34 -0800293 .get_temp = qpnp_tz_get_temp_qpnp_adc,
David Collins8885f792017-01-26 14:36:34 -0800294};
295
296static void qpnp_tm_work(struct work_struct *work)
297{
298 struct delayed_work *dwork
299 = container_of(work, struct delayed_work, work);
300 struct qpnp_tm_chip *chip
301 = container_of(dwork, struct qpnp_tm_chip, irq_work);
302 unsigned int stage_new, stage_old;
303 int rc;
304
305 if (chip->adc_type == QPNP_TM_ADC_NONE) {
306 rc = qpnp_tm_update_temp_no_adc(chip);
307 if (rc < 0)
308 goto bail;
309 } else {
310 rc = qpnp_tm_get_temp_stage(chip, &chip->stage);
311 if (rc < 0)
312 goto bail;
313
314 rc = qpnp_tm_update_temp(chip);
315 if (rc < 0)
316 goto bail;
317 }
318
319 if (chip->subtype == QPNP_TM_SUBTYPE_GEN1) {
320 stage_new = chip->stage;
321 stage_old = chip->prev_stage;
322 } else {
323 stage_new = alarm_state_map[chip->stage];
324 stage_old = alarm_state_map[chip->prev_stage];
325 }
326
327 chip->prev_stage = chip->stage;
328
329 if (stage_new != stage_old) {
330 if (chip->subtype == QPNP_TM_SUBTYPE_GEN1)
331 pr_crit("%s: PMIC Temp Alarm - stage=%u, threshold=%u, temperature=%d mC\n",
332 chip->tm_name, chip->stage, chip->thresh,
333 chip->temperature);
334 else
335 pr_crit("%s: PMIC Temp Alarm - stage=%u, state=%u, threshold=%u, temperature=%d mC\n",
336 chip->tm_name, stage_new, chip->stage,
337 chip->thresh, chip->temperature);
338
Ram Chandrasekar5bca6482017-03-31 13:18:07 -0600339 of_thermal_handle_trip(chip->tz_dev);
David Collins8885f792017-01-26 14:36:34 -0800340 }
341
342bail:
343 return;
344}
345
346static irqreturn_t qpnp_tm_isr(int irq, void *data)
347{
348 struct qpnp_tm_chip *chip = data;
349
350 schedule_delayed_work(&chip->irq_work,
351 msecs_to_jiffies(STATUS_REGISTER_DELAY_MS) + 1);
352
353 return IRQ_HANDLED;
354}
355
356static int qpnp_tm_init_reg(struct qpnp_tm_chip *chip)
357{
358 int rc = 0;
359 u8 reg;
360
361 rc = qpnp_tm_read(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, &reg, 1);
362 if (rc < 0)
363 return rc;
364
365 if (chip->thresh < THRESH_MIN || chip->thresh > THRESH_MAX) {
366 /* Use hardware threshold value if configuration is invalid. */
367 chip->thresh = reg & SHUTDOWN_CTRL1_THRESHOLD_MASK;
368 }
369
370 if (chip->clock_rate < CLOCK_RATE_MIN
371 || chip->clock_rate > CLOCK_RATE_MAX) {
372 /* Use hardware clock rate value if configuration is invalid. */
373 chip->clock_rate = (reg & SHUTDOWN_CTRL1_CLK_RATE_MASK)
374 >> SHUTDOWN_CTRL1_CLK_RATE_SHIFT;
375 }
376
377 /*
378 * Set threshold and clock rate and also disable software override of
379 * stage 2 and 3 shutdowns.
380 */
381 reg = chip->thresh & SHUTDOWN_CTRL1_THRESHOLD_MASK;
382 reg |= (chip->clock_rate << SHUTDOWN_CTRL1_CLK_RATE_SHIFT)
383 & SHUTDOWN_CTRL1_CLK_RATE_MASK;
384 rc = qpnp_tm_write(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, &reg, 1);
385 if (rc < 0)
386 return rc;
387
388 /* Enable the thermal alarm PMIC module in always-on mode. */
389 reg = ALARM_CTRL_FORCE_ENABLE;
390 rc = qpnp_tm_write(chip, QPNP_TM_REG_ALARM_CTRL, &reg, 1);
391
392 return rc;
393}
394
395static int qpnp_tm_probe(struct platform_device *pdev)
396{
397 struct device_node *node;
398 unsigned int base;
399 struct qpnp_tm_chip *chip;
Ram Chandrasekar5bca6482017-03-31 13:18:07 -0600400 struct thermal_zone_of_device_ops *tz_ops;
David Collins8885f792017-01-26 14:36:34 -0800401 char *tm_name;
402 u32 default_temperature;
403 int rc = 0;
404 u8 raw_type[2], type, subtype;
405
406 if (!pdev || !(&pdev->dev) || !pdev->dev.of_node) {
407 dev_err(&pdev->dev, "%s: device tree node not found\n",
408 __func__);
409 return -EINVAL;
410 }
411
412 node = pdev->dev.of_node;
413
414 chip = kzalloc(sizeof(struct qpnp_tm_chip), GFP_KERNEL);
415 if (!chip)
416 return -ENOMEM;
417
418 chip->regmap = dev_get_regmap(pdev->dev.parent, NULL);
419 if (!chip->regmap) {
420 dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
421 return -EINVAL;
422 }
423
424 dev_set_drvdata(&pdev->dev, chip);
425
426 rc = of_property_read_u32(pdev->dev.of_node, "reg", &base);
427 if (rc < 0) {
428 dev_err(&pdev->dev,
429 "Couldn't find reg in node = %s rc = %d\n",
430 pdev->dev.of_node->full_name, rc);
431 goto free_chip;
432 }
433 chip->base_addr = base;
434 chip->pdev = pdev;
435
436 chip->irq = platform_get_irq(pdev, 0);
437 if (chip->irq < 0) {
438 rc = chip->irq;
439 dev_err(&pdev->dev, "%s: node is missing irq, rc=%d\n",
440 __func__, rc);
441 goto free_chip;
442 }
443
444 chip->tm_name = of_get_property(node, "label", NULL);
445 if (chip->tm_name == NULL) {
446 dev_err(&pdev->dev, "%s: node is missing label\n", __func__);
447 rc = -EINVAL;
448 goto free_chip;
449 }
450
451 tm_name = kstrdup(chip->tm_name, GFP_KERNEL);
452 if (tm_name == NULL) {
453 rc = -ENOMEM;
454 goto free_chip;
455 }
456 chip->tm_name = tm_name;
457
458 INIT_DELAYED_WORK(&chip->irq_work, qpnp_tm_work);
459
460 /* These bindings are optional, so it is okay if they are not found. */
461 chip->thresh = THRESH_MAX + 1;
462 rc = of_property_read_u32(node, "qcom,threshold-set", &chip->thresh);
463 if (!rc && (chip->thresh < THRESH_MIN || chip->thresh > THRESH_MAX))
464 dev_err(&pdev->dev,
465 "%s: invalid qcom,threshold-set=%u specified\n",
466 __func__, chip->thresh);
467
468 chip->clock_rate = CLOCK_RATE_MAX + 1;
469 rc = of_property_read_u32(node, "qcom,clock-rate", &chip->clock_rate);
470 if (!rc && (chip->clock_rate < CLOCK_RATE_MIN
471 || chip->clock_rate > CLOCK_RATE_MAX))
472 dev_err(&pdev->dev,
473 "%s: invalid qcom,clock-rate=%u specified\n", __func__,
474 chip->clock_rate);
475
476 chip->adc_type = QPNP_TM_ADC_NONE;
477 rc = of_property_read_u32(node, "qcom,channel-num", &chip->adc_channel);
478 if (!rc) {
479 if (chip->adc_channel < 0 || chip->adc_channel >= ADC_MAX_NUM) {
480 dev_err(&pdev->dev,
481 "%s: invalid qcom,channel-num=%d specified\n",
482 __func__, chip->adc_channel);
483 } else {
484 chip->adc_type = QPNP_TM_ADC_QPNP_ADC;
485 chip->vadc_dev = qpnp_get_vadc(&pdev->dev,
486 "temp_alarm");
487 if (IS_ERR(chip->vadc_dev)) {
488 rc = PTR_ERR(chip->vadc_dev);
489 if (rc != -EPROBE_DEFER)
490 pr_err("vadc property missing\n");
491 goto err_cancel_work;
492 }
493 }
494 }
495
496 if (chip->adc_type == QPNP_TM_ADC_QPNP_ADC)
497 tz_ops = &qpnp_thermal_zone_ops_qpnp_adc;
498 else
499 tz_ops = &qpnp_thermal_zone_ops_no_adc;
500
David Collins8885f792017-01-26 14:36:34 -0800501 default_temperature = DEFAULT_NO_ADC_TEMP;
502 rc = of_property_read_u32(node, "qcom,default-temp",
503 &default_temperature);
504 chip->temperature = default_temperature;
505
506 rc = qpnp_tm_read(chip, QPNP_TM_REG_TYPE, raw_type, 2);
507 if (rc) {
508 dev_err(&pdev->dev,
509 "%s: could not read type register, rc=%d\n",
510 __func__, rc);
511 goto err_cancel_work;
512 }
513 type = raw_type[0];
514 subtype = raw_type[1];
515
516 if (type != QPNP_TM_TYPE || (subtype != QPNP_TM_SUBTYPE_GEN1
517 && subtype != QPNP_TM_SUBTYPE_GEN2)) {
518 dev_err(&pdev->dev,
519 "%s: invalid type=%02X or subtype=%02X register value\n",
520 __func__, type, subtype);
521 rc = -ENODEV;
522 goto err_cancel_work;
523 }
524
525 chip->subtype = subtype;
526
527 rc = qpnp_tm_init_reg(chip);
528 if (rc) {
529 dev_err(&pdev->dev, "%s: qpnp_tm_init_reg() failed, rc=%d\n",
530 __func__, rc);
531 goto err_cancel_work;
532 }
533
534 if (chip->adc_type == QPNP_TM_ADC_NONE) {
535 rc = qpnp_tm_init_temp_no_adc(chip);
536 if (rc) {
537 dev_err(&pdev->dev,
538 "%s: qpnp_tm_init_temp_no_adc() failed, rc=%d\n",
539 __func__, rc);
540 goto err_cancel_work;
541 }
542 }
543
Ram Chandrasekar5bca6482017-03-31 13:18:07 -0600544 chip->tz_dev = thermal_zone_of_sensor_register(&pdev->dev, 0, chip,
545 tz_ops);
David Collins08f2a842018-01-11 16:42:36 -0800546 if (IS_ERR(chip->tz_dev)) {
547 rc = PTR_ERR(chip->tz_dev);
David Collins8885f792017-01-26 14:36:34 -0800548 dev_err(&pdev->dev,
David Collins08f2a842018-01-11 16:42:36 -0800549 "%s: thermal_zone_of_sensor_register() failed, rc=%d\n",
550 __func__, rc);
David Collins8885f792017-01-26 14:36:34 -0800551 goto err_cancel_work;
552 }
553
554 rc = request_irq(chip->irq, qpnp_tm_isr, IRQF_TRIGGER_RISING, tm_name,
555 chip);
556 if (rc < 0) {
557 dev_err(&pdev->dev, "%s: request_irq(%d) failed: %d\n",
558 __func__, chip->irq, rc);
559 goto err_free_tz;
560 }
561
562 return 0;
563
564err_free_tz:
Ram Chandrasekar5bca6482017-03-31 13:18:07 -0600565 thermal_zone_of_sensor_unregister(&pdev->dev, chip->tz_dev);
David Collins8885f792017-01-26 14:36:34 -0800566err_cancel_work:
567 cancel_delayed_work_sync(&chip->irq_work);
568 kfree(chip->tm_name);
569free_chip:
570 dev_set_drvdata(&pdev->dev, NULL);
571 kfree(chip);
572 return rc;
573}
574
575static int qpnp_tm_remove(struct platform_device *pdev)
576{
577 struct qpnp_tm_chip *chip = dev_get_drvdata(&pdev->dev);
578
Ram Chandrasekar5bca6482017-03-31 13:18:07 -0600579 thermal_zone_of_sensor_unregister(&pdev->dev, chip->tz_dev);
David Collins8885f792017-01-26 14:36:34 -0800580 dev_set_drvdata(&pdev->dev, NULL);
David Collins8885f792017-01-26 14:36:34 -0800581 kfree(chip->tm_name);
David Collins8885f792017-01-26 14:36:34 -0800582 free_irq(chip->irq, chip);
583 cancel_delayed_work_sync(&chip->irq_work);
584 kfree(chip);
585
586 return 0;
587}
588
David Collins8885f792017-01-26 14:36:34 -0800589static const struct of_device_id qpnp_tm_match_table[] = {
590 { .compatible = QPNP_TM_DRIVER_NAME, },
591 {}
592};
593
594static const struct platform_device_id qpnp_tm_id[] = {
595 { QPNP_TM_DRIVER_NAME, 0 },
596 {}
597};
598
599static struct platform_driver qpnp_tm_driver = {
600 .driver = {
601 .name = QPNP_TM_DRIVER_NAME,
602 .of_match_table = qpnp_tm_match_table,
603 .owner = THIS_MODULE,
David Collins8885f792017-01-26 14:36:34 -0800604 },
605 .probe = qpnp_tm_probe,
606 .remove = qpnp_tm_remove,
607 .id_table = qpnp_tm_id,
608};
609
610int __init qpnp_tm_init(void)
611{
612 return platform_driver_register(&qpnp_tm_driver);
613}
614
615static void __exit qpnp_tm_exit(void)
616{
617 platform_driver_unregister(&qpnp_tm_driver);
618}
619
620module_init(qpnp_tm_init);
621module_exit(qpnp_tm_exit);
622
623MODULE_DESCRIPTION("QPNP PMIC Temperature Alarm driver");
624MODULE_LICENSE("GPL v2");