This source file includes following definitions.
- hi6220_thermal_step_to_temp
- hi6220_thermal_temp_to_step
- hi3660_thermal_step_to_temp
- hi3660_thermal_temp_to_step
- hi6220_thermal_set_lag
- hi6220_thermal_alarm_clear
- hi6220_thermal_alarm_enable
- hi6220_thermal_alarm_set
- hi6220_thermal_reset_set
- hi6220_thermal_reset_enable
- hi6220_thermal_enable
- hi6220_thermal_get_temperature
- hi3660_thermal_set_lag
- hi3660_thermal_alarm_clear
- hi3660_thermal_alarm_enable
- hi3660_thermal_alarm_set
- hi3660_thermal_get_temperature
- hi6220_thermal_sensor_select
- hi6220_thermal_hdak_set
- hi6220_thermal_irq_handler
- hi3660_thermal_irq_handler
- hi6220_thermal_get_temp
- hi3660_thermal_get_temp
- hi6220_thermal_disable_sensor
- hi3660_thermal_disable_sensor
- hi6220_thermal_enable_sensor
- hi3660_thermal_enable_sensor
- hi6220_thermal_probe
- hi3660_thermal_probe
- hisi_thermal_get_temp
- hisi_thermal_alarm_irq_thread
- hisi_thermal_register_sensor
- hisi_thermal_toggle_sensor
- hisi_thermal_probe
- hisi_thermal_remove
- hisi_thermal_suspend
- hisi_thermal_resume
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <linux/cpufreq.h>
21 #include <linux/delay.h>
22 #include <linux/interrupt.h>
23 #include <linux/module.h>
24 #include <linux/platform_device.h>
25 #include <linux/io.h>
26 #include <linux/of_device.h>
27
28 #include "thermal_core.h"
29
30 #define HI6220_TEMP0_LAG (0x0)
31 #define HI6220_TEMP0_TH (0x4)
32 #define HI6220_TEMP0_RST_TH (0x8)
33 #define HI6220_TEMP0_CFG (0xC)
34 #define HI6220_TEMP0_CFG_SS_MSK (0xF000)
35 #define HI6220_TEMP0_CFG_HDAK_MSK (0x30)
36 #define HI6220_TEMP0_EN (0x10)
37 #define HI6220_TEMP0_INT_EN (0x14)
38 #define HI6220_TEMP0_INT_CLR (0x18)
39 #define HI6220_TEMP0_RST_MSK (0x1C)
40 #define HI6220_TEMP0_VALUE (0x28)
41
42 #define HI3660_OFFSET(chan) ((chan) * 0x40)
43 #define HI3660_TEMP(chan) (HI3660_OFFSET(chan) + 0x1C)
44 #define HI3660_TH(chan) (HI3660_OFFSET(chan) + 0x20)
45 #define HI3660_LAG(chan) (HI3660_OFFSET(chan) + 0x28)
46 #define HI3660_INT_EN(chan) (HI3660_OFFSET(chan) + 0x2C)
47 #define HI3660_INT_CLR(chan) (HI3660_OFFSET(chan) + 0x30)
48
49 #define HI6220_TEMP_BASE (-60000)
50 #define HI6220_TEMP_RESET (100000)
51 #define HI6220_TEMP_STEP (785)
52 #define HI6220_TEMP_LAG (3500)
53
54 #define HI3660_TEMP_BASE (-63780)
55 #define HI3660_TEMP_STEP (205)
56 #define HI3660_TEMP_LAG (4000)
57
58 #define HI6220_CLUSTER0_SENSOR 2
59 #define HI6220_CLUSTER1_SENSOR 1
60
61 #define HI3660_LITTLE_SENSOR 0
62 #define HI3660_BIG_SENSOR 1
63 #define HI3660_G3D_SENSOR 2
64 #define HI3660_MODEM_SENSOR 3
65
66 struct hisi_thermal_data;
67
68 struct hisi_thermal_sensor {
69 struct hisi_thermal_data *data;
70 struct thermal_zone_device *tzd;
71 const char *irq_name;
72 uint32_t id;
73 uint32_t thres_temp;
74 };
75
76 struct hisi_thermal_ops {
77 int (*get_temp)(struct hisi_thermal_sensor *sensor);
78 int (*enable_sensor)(struct hisi_thermal_sensor *sensor);
79 int (*disable_sensor)(struct hisi_thermal_sensor *sensor);
80 int (*irq_handler)(struct hisi_thermal_sensor *sensor);
81 int (*probe)(struct hisi_thermal_data *data);
82 };
83
84 struct hisi_thermal_data {
85 const struct hisi_thermal_ops *ops;
86 struct hisi_thermal_sensor *sensor;
87 struct platform_device *pdev;
88 struct clk *clk;
89 void __iomem *regs;
90 int nr_sensors;
91 };
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111 static inline int hi6220_thermal_step_to_temp(int step)
112 {
113 return HI6220_TEMP_BASE + (step * HI6220_TEMP_STEP);
114 }
115
116 static inline int hi6220_thermal_temp_to_step(int temp)
117 {
118 return DIV_ROUND_UP(temp - HI6220_TEMP_BASE, HI6220_TEMP_STEP);
119 }
120
121
122
123
124
125
126
127
128
129 static inline int hi3660_thermal_step_to_temp(int step)
130 {
131 return HI3660_TEMP_BASE + step * HI3660_TEMP_STEP;
132 }
133
134 static inline int hi3660_thermal_temp_to_step(int temp)
135 {
136 return DIV_ROUND_UP(temp - HI3660_TEMP_BASE, HI3660_TEMP_STEP);
137 }
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170 static inline void hi6220_thermal_set_lag(void __iomem *addr, int value)
171 {
172 writel(DIV_ROUND_UP(value, HI6220_TEMP_STEP) & 0x1F,
173 addr + HI6220_TEMP0_LAG);
174 }
175
176 static inline void hi6220_thermal_alarm_clear(void __iomem *addr, int value)
177 {
178 writel(value, addr + HI6220_TEMP0_INT_CLR);
179 }
180
181 static inline void hi6220_thermal_alarm_enable(void __iomem *addr, int value)
182 {
183 writel(value, addr + HI6220_TEMP0_INT_EN);
184 }
185
186 static inline void hi6220_thermal_alarm_set(void __iomem *addr, int temp)
187 {
188 writel(hi6220_thermal_temp_to_step(temp) | 0x0FFFFFF00,
189 addr + HI6220_TEMP0_TH);
190 }
191
192 static inline void hi6220_thermal_reset_set(void __iomem *addr, int temp)
193 {
194 writel(hi6220_thermal_temp_to_step(temp), addr + HI6220_TEMP0_RST_TH);
195 }
196
197 static inline void hi6220_thermal_reset_enable(void __iomem *addr, int value)
198 {
199 writel(value, addr + HI6220_TEMP0_RST_MSK);
200 }
201
202 static inline void hi6220_thermal_enable(void __iomem *addr, int value)
203 {
204 writel(value, addr + HI6220_TEMP0_EN);
205 }
206
207 static inline int hi6220_thermal_get_temperature(void __iomem *addr)
208 {
209 return hi6220_thermal_step_to_temp(readl(addr + HI6220_TEMP0_VALUE));
210 }
211
212
213
214
215
216
217
218
219
220
221 static inline void hi3660_thermal_set_lag(void __iomem *addr,
222 int id, int value)
223 {
224 writel(DIV_ROUND_UP(value, HI3660_TEMP_STEP) & 0x7F,
225 addr + HI3660_LAG(id));
226 }
227
228 static inline void hi3660_thermal_alarm_clear(void __iomem *addr,
229 int id, int value)
230 {
231 writel(value, addr + HI3660_INT_CLR(id));
232 }
233
234 static inline void hi3660_thermal_alarm_enable(void __iomem *addr,
235 int id, int value)
236 {
237 writel(value, addr + HI3660_INT_EN(id));
238 }
239
240 static inline void hi3660_thermal_alarm_set(void __iomem *addr,
241 int id, int value)
242 {
243 writel(value, addr + HI3660_TH(id));
244 }
245
246 static inline int hi3660_thermal_get_temperature(void __iomem *addr, int id)
247 {
248 return hi3660_thermal_step_to_temp(readl(addr + HI3660_TEMP(id)));
249 }
250
251
252
253
254
255
256
257
258
259
260
261 static inline void hi6220_thermal_sensor_select(void __iomem *addr, int sensor)
262 {
263 writel((readl(addr + HI6220_TEMP0_CFG) & ~HI6220_TEMP0_CFG_SS_MSK) |
264 (sensor << 12), addr + HI6220_TEMP0_CFG);
265 }
266
267
268
269
270
271
272
273
274
275
276
277 static inline void hi6220_thermal_hdak_set(void __iomem *addr, int value)
278 {
279 writel((readl(addr + HI6220_TEMP0_CFG) & ~HI6220_TEMP0_CFG_HDAK_MSK) |
280 (value << 4), addr + HI6220_TEMP0_CFG);
281 }
282
283 static int hi6220_thermal_irq_handler(struct hisi_thermal_sensor *sensor)
284 {
285 struct hisi_thermal_data *data = sensor->data;
286
287 hi6220_thermal_alarm_clear(data->regs, 1);
288 return 0;
289 }
290
291 static int hi3660_thermal_irq_handler(struct hisi_thermal_sensor *sensor)
292 {
293 struct hisi_thermal_data *data = sensor->data;
294
295 hi3660_thermal_alarm_clear(data->regs, sensor->id, 1);
296 return 0;
297 }
298
299 static int hi6220_thermal_get_temp(struct hisi_thermal_sensor *sensor)
300 {
301 struct hisi_thermal_data *data = sensor->data;
302
303 return hi6220_thermal_get_temperature(data->regs);
304 }
305
306 static int hi3660_thermal_get_temp(struct hisi_thermal_sensor *sensor)
307 {
308 struct hisi_thermal_data *data = sensor->data;
309
310 return hi3660_thermal_get_temperature(data->regs, sensor->id);
311 }
312
313 static int hi6220_thermal_disable_sensor(struct hisi_thermal_sensor *sensor)
314 {
315 struct hisi_thermal_data *data = sensor->data;
316
317
318 hi6220_thermal_enable(data->regs, 0);
319 hi6220_thermal_alarm_enable(data->regs, 0);
320 hi6220_thermal_reset_enable(data->regs, 0);
321
322 clk_disable_unprepare(data->clk);
323
324 return 0;
325 }
326
327 static int hi3660_thermal_disable_sensor(struct hisi_thermal_sensor *sensor)
328 {
329 struct hisi_thermal_data *data = sensor->data;
330
331
332 hi3660_thermal_alarm_enable(data->regs, sensor->id, 0);
333 return 0;
334 }
335
336 static int hi6220_thermal_enable_sensor(struct hisi_thermal_sensor *sensor)
337 {
338 struct hisi_thermal_data *data = sensor->data;
339 int ret;
340
341
342 ret = clk_prepare_enable(data->clk);
343 if (ret)
344 return ret;
345
346
347 hi6220_thermal_reset_enable(data->regs, 0);
348 hi6220_thermal_enable(data->regs, 0);
349
350
351 hi6220_thermal_sensor_select(data->regs, sensor->id);
352
353
354 hi6220_thermal_hdak_set(data->regs, 0);
355
356
357 hi6220_thermal_set_lag(data->regs, HI6220_TEMP_LAG);
358
359
360 hi6220_thermal_alarm_set(data->regs, sensor->thres_temp);
361
362 hi6220_thermal_reset_set(data->regs, HI6220_TEMP_RESET);
363
364
365 hi6220_thermal_reset_enable(data->regs, 1);
366 hi6220_thermal_enable(data->regs, 1);
367
368 hi6220_thermal_alarm_clear(data->regs, 0);
369 hi6220_thermal_alarm_enable(data->regs, 1);
370
371 return 0;
372 }
373
374 static int hi3660_thermal_enable_sensor(struct hisi_thermal_sensor *sensor)
375 {
376 unsigned int value;
377 struct hisi_thermal_data *data = sensor->data;
378
379
380 hi3660_thermal_alarm_enable(data->regs, sensor->id, 0);
381
382
383 hi3660_thermal_set_lag(data->regs, sensor->id, HI3660_TEMP_LAG);
384
385
386 value = hi3660_thermal_temp_to_step(sensor->thres_temp);
387 hi3660_thermal_alarm_set(data->regs, sensor->id, value);
388
389
390 hi3660_thermal_alarm_clear(data->regs, sensor->id, 1);
391 hi3660_thermal_alarm_enable(data->regs, sensor->id, 1);
392
393 return 0;
394 }
395
396 static int hi6220_thermal_probe(struct hisi_thermal_data *data)
397 {
398 struct platform_device *pdev = data->pdev;
399 struct device *dev = &pdev->dev;
400 int ret;
401
402 data->clk = devm_clk_get(dev, "thermal_clk");
403 if (IS_ERR(data->clk)) {
404 ret = PTR_ERR(data->clk);
405 if (ret != -EPROBE_DEFER)
406 dev_err(dev, "failed to get thermal clk: %d\n", ret);
407 return ret;
408 }
409
410 data->sensor = devm_kzalloc(dev, sizeof(*data->sensor), GFP_KERNEL);
411 if (!data->sensor)
412 return -ENOMEM;
413
414 data->sensor[0].id = HI6220_CLUSTER0_SENSOR;
415 data->sensor[0].irq_name = "tsensor_intr";
416 data->sensor[0].data = data;
417 data->nr_sensors = 1;
418
419 return 0;
420 }
421
422 static int hi3660_thermal_probe(struct hisi_thermal_data *data)
423 {
424 struct platform_device *pdev = data->pdev;
425 struct device *dev = &pdev->dev;
426
427 data->nr_sensors = 1;
428
429 data->sensor = devm_kzalloc(dev, sizeof(*data->sensor) *
430 data->nr_sensors, GFP_KERNEL);
431 if (!data->sensor)
432 return -ENOMEM;
433
434 data->sensor[0].id = HI3660_BIG_SENSOR;
435 data->sensor[0].irq_name = "tsensor_a73";
436 data->sensor[0].data = data;
437
438 data->sensor[1].id = HI3660_LITTLE_SENSOR;
439 data->sensor[1].irq_name = "tsensor_a53";
440 data->sensor[1].data = data;
441
442 return 0;
443 }
444
445 static int hisi_thermal_get_temp(void *__data, int *temp)
446 {
447 struct hisi_thermal_sensor *sensor = __data;
448 struct hisi_thermal_data *data = sensor->data;
449
450 *temp = data->ops->get_temp(sensor);
451
452 dev_dbg(&data->pdev->dev, "tzd=%p, id=%d, temp=%d, thres=%d\n",
453 sensor->tzd, sensor->id, *temp, sensor->thres_temp);
454
455 return 0;
456 }
457
458 static const struct thermal_zone_of_device_ops hisi_of_thermal_ops = {
459 .get_temp = hisi_thermal_get_temp,
460 };
461
462 static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev)
463 {
464 struct hisi_thermal_sensor *sensor = dev;
465 struct hisi_thermal_data *data = sensor->data;
466 int temp = 0;
467
468 data->ops->irq_handler(sensor);
469
470 hisi_thermal_get_temp(sensor, &temp);
471
472 if (temp >= sensor->thres_temp) {
473 dev_crit(&data->pdev->dev,
474 "sensor <%d> THERMAL ALARM: %d > %d\n",
475 sensor->id, temp, sensor->thres_temp);
476
477 thermal_zone_device_update(sensor->tzd,
478 THERMAL_EVENT_UNSPECIFIED);
479
480 } else {
481 dev_crit(&data->pdev->dev,
482 "sensor <%d> THERMAL ALARM stopped: %d < %d\n",
483 sensor->id, temp, sensor->thres_temp);
484 }
485
486 return IRQ_HANDLED;
487 }
488
489 static int hisi_thermal_register_sensor(struct platform_device *pdev,
490 struct hisi_thermal_sensor *sensor)
491 {
492 int ret, i;
493 const struct thermal_trip *trip;
494
495 sensor->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev,
496 sensor->id, sensor,
497 &hisi_of_thermal_ops);
498 if (IS_ERR(sensor->tzd)) {
499 ret = PTR_ERR(sensor->tzd);
500 sensor->tzd = NULL;
501 dev_err(&pdev->dev, "failed to register sensor id %d: %d\n",
502 sensor->id, ret);
503 return ret;
504 }
505
506 trip = of_thermal_get_trip_points(sensor->tzd);
507
508 for (i = 0; i < of_thermal_get_ntrips(sensor->tzd); i++) {
509 if (trip[i].type == THERMAL_TRIP_PASSIVE) {
510 sensor->thres_temp = trip[i].temperature;
511 break;
512 }
513 }
514
515 return 0;
516 }
517
518 static const struct hisi_thermal_ops hi6220_ops = {
519 .get_temp = hi6220_thermal_get_temp,
520 .enable_sensor = hi6220_thermal_enable_sensor,
521 .disable_sensor = hi6220_thermal_disable_sensor,
522 .irq_handler = hi6220_thermal_irq_handler,
523 .probe = hi6220_thermal_probe,
524 };
525
526 static const struct hisi_thermal_ops hi3660_ops = {
527 .get_temp = hi3660_thermal_get_temp,
528 .enable_sensor = hi3660_thermal_enable_sensor,
529 .disable_sensor = hi3660_thermal_disable_sensor,
530 .irq_handler = hi3660_thermal_irq_handler,
531 .probe = hi3660_thermal_probe,
532 };
533
534 static const struct of_device_id of_hisi_thermal_match[] = {
535 {
536 .compatible = "hisilicon,tsensor",
537 .data = &hi6220_ops,
538 },
539 {
540 .compatible = "hisilicon,hi3660-tsensor",
541 .data = &hi3660_ops,
542 },
543 { }
544 };
545 MODULE_DEVICE_TABLE(of, of_hisi_thermal_match);
546
547 static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor,
548 bool on)
549 {
550 struct thermal_zone_device *tzd = sensor->tzd;
551
552 tzd->ops->set_mode(tzd,
553 on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED);
554 }
555
556 static int hisi_thermal_probe(struct platform_device *pdev)
557 {
558 struct hisi_thermal_data *data;
559 struct device *dev = &pdev->dev;
560 struct resource *res;
561 int i, ret;
562
563 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
564 if (!data)
565 return -ENOMEM;
566
567 data->pdev = pdev;
568 platform_set_drvdata(pdev, data);
569 data->ops = of_device_get_match_data(dev);
570
571 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
572 data->regs = devm_ioremap_resource(dev, res);
573 if (IS_ERR(data->regs)) {
574 dev_err(dev, "failed to get io address\n");
575 return PTR_ERR(data->regs);
576 }
577
578 ret = data->ops->probe(data);
579 if (ret)
580 return ret;
581
582 for (i = 0; i < data->nr_sensors; i++) {
583 struct hisi_thermal_sensor *sensor = &data->sensor[i];
584
585 ret = hisi_thermal_register_sensor(pdev, sensor);
586 if (ret) {
587 dev_err(dev, "failed to register thermal sensor: %d\n",
588 ret);
589 return ret;
590 }
591
592 ret = platform_get_irq(pdev, 0);
593 if (ret < 0)
594 return ret;
595
596 ret = devm_request_threaded_irq(dev, ret, NULL,
597 hisi_thermal_alarm_irq_thread,
598 IRQF_ONESHOT, sensor->irq_name,
599 sensor);
600 if (ret < 0) {
601 dev_err(dev, "Failed to request alarm irq: %d\n", ret);
602 return ret;
603 }
604
605 ret = data->ops->enable_sensor(sensor);
606 if (ret) {
607 dev_err(dev, "Failed to setup the sensor: %d\n", ret);
608 return ret;
609 }
610
611 hisi_thermal_toggle_sensor(sensor, true);
612 }
613
614 return 0;
615 }
616
617 static int hisi_thermal_remove(struct platform_device *pdev)
618 {
619 struct hisi_thermal_data *data = platform_get_drvdata(pdev);
620 int i;
621
622 for (i = 0; i < data->nr_sensors; i++) {
623 struct hisi_thermal_sensor *sensor = &data->sensor[i];
624
625 hisi_thermal_toggle_sensor(sensor, false);
626 data->ops->disable_sensor(sensor);
627 }
628
629 return 0;
630 }
631
632 #ifdef CONFIG_PM_SLEEP
633 static int hisi_thermal_suspend(struct device *dev)
634 {
635 struct hisi_thermal_data *data = dev_get_drvdata(dev);
636 int i;
637
638 for (i = 0; i < data->nr_sensors; i++)
639 data->ops->disable_sensor(&data->sensor[i]);
640
641 return 0;
642 }
643
644 static int hisi_thermal_resume(struct device *dev)
645 {
646 struct hisi_thermal_data *data = dev_get_drvdata(dev);
647 int i, ret = 0;
648
649 for (i = 0; i < data->nr_sensors; i++)
650 ret |= data->ops->enable_sensor(&data->sensor[i]);
651
652 return ret;
653 }
654 #endif
655
656 static SIMPLE_DEV_PM_OPS(hisi_thermal_pm_ops,
657 hisi_thermal_suspend, hisi_thermal_resume);
658
659 static struct platform_driver hisi_thermal_driver = {
660 .driver = {
661 .name = "hisi_thermal",
662 .pm = &hisi_thermal_pm_ops,
663 .of_match_table = of_hisi_thermal_match,
664 },
665 .probe = hisi_thermal_probe,
666 .remove = hisi_thermal_remove,
667 };
668
669 module_platform_driver(hisi_thermal_driver);
670
671 MODULE_AUTHOR("Xinwei Kong <kong.kongxinwei@hisilicon.com>");
672 MODULE_AUTHOR("Leo Yan <leo.yan@linaro.org>");
673 MODULE_DESCRIPTION("Hisilicon thermal driver");
674 MODULE_LICENSE("GPL v2");