Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/arm/allwinner/aw_thermal.c
39507 views
1
/*-
2
* Copyright (c) 2016 Jared McNeill <[email protected]>
3
*
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
6
* are met:
7
* 1. Redistributions of source code must retain the above copyright
8
* notice, this list of conditions and the following disclaimer.
9
* 2. Redistributions in binary form must reproduce the above copyright
10
* notice, this list of conditions and the following disclaimer in the
11
* documentation and/or other materials provided with the distribution.
12
*
13
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
18
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
20
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
21
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23
* SUCH DAMAGE.
24
*/
25
26
/*
27
* Allwinner thermal sensor controller
28
*/
29
30
#include <sys/param.h>
31
#include <sys/systm.h>
32
#include <sys/eventhandler.h>
33
#include <sys/bus.h>
34
#include <sys/rman.h>
35
#include <sys/kernel.h>
36
#include <sys/sysctl.h>
37
#include <sys/reboot.h>
38
#include <sys/module.h>
39
#include <sys/cpu.h>
40
#include <sys/taskqueue.h>
41
#include <machine/bus.h>
42
43
#include <dev/ofw/ofw_bus.h>
44
#include <dev/ofw/ofw_bus_subr.h>
45
46
#include <dev/clk/clk.h>
47
#include <dev/hwreset/hwreset.h>
48
#include <dev/nvmem/nvmem.h>
49
50
#include <arm/allwinner/aw_sid.h>
51
52
#include "cpufreq_if.h"
53
#include "nvmem_if.h"
54
55
#define THS_CTRL0 0x00
56
#define THS_CTRL1 0x04
57
#define ADC_CALI_EN (1 << 17)
58
#define THS_CTRL2 0x40
59
#define SENSOR_ACQ1_SHIFT 16
60
#define SENSOR2_EN (1 << 2)
61
#define SENSOR1_EN (1 << 1)
62
#define SENSOR0_EN (1 << 0)
63
#define THS_INTC 0x44
64
#define THS_THERMAL_PER_SHIFT 12
65
#define THS_INTS 0x48
66
#define THS2_DATA_IRQ_STS (1 << 10)
67
#define THS1_DATA_IRQ_STS (1 << 9)
68
#define THS0_DATA_IRQ_STS (1 << 8)
69
#define SHUT_INT2_STS (1 << 6)
70
#define SHUT_INT1_STS (1 << 5)
71
#define SHUT_INT0_STS (1 << 4)
72
#define ALARM_INT2_STS (1 << 2)
73
#define ALARM_INT1_STS (1 << 1)
74
#define ALARM_INT0_STS (1 << 0)
75
#define THS_ALARM0_CTRL 0x50
76
#define ALARM_T_HOT_MASK 0xfff
77
#define ALARM_T_HOT_SHIFT 16
78
#define ALARM_T_HYST_MASK 0xfff
79
#define ALARM_T_HYST_SHIFT 0
80
#define THS_SHUTDOWN0_CTRL 0x60
81
#define SHUT_T_HOT_MASK 0xfff
82
#define SHUT_T_HOT_SHIFT 16
83
#define THS_FILTER 0x70
84
#define THS_CALIB0 0x74
85
#define THS_CALIB1 0x78
86
#define THS_DATA0 0x80
87
#define THS_DATA1 0x84
88
#define THS_DATA2 0x88
89
#define DATA_MASK 0xfff
90
91
#define A83T_CLK_RATE 24000000
92
#define A83T_ADC_ACQUIRE_TIME 23 /* 24Mhz/(23 + 1) = 1us */
93
#define A83T_THERMAL_PER 1 /* 4096 * (1 + 1) / 24Mhz = 341 us */
94
#define A83T_FILTER 0x5 /* Filter enabled, avg of 4 */
95
#define A83T_TEMP_BASE 2719000
96
#define A83T_TEMP_MUL 1000
97
#define A83T_TEMP_DIV 14186
98
99
#define A64_CLK_RATE 4000000
100
#define A64_ADC_ACQUIRE_TIME 400 /* 4Mhz/(400 + 1) = 100 us */
101
#define A64_THERMAL_PER 24 /* 4096 * (24 + 1) / 4Mhz = 25.6 ms */
102
#define A64_FILTER 0x6 /* Filter enabled, avg of 8 */
103
#define A64_TEMP_BASE 2170000
104
#define A64_TEMP_MUL 1000
105
#define A64_TEMP_DIV 8560
106
107
#define H3_CLK_RATE 4000000
108
#define H3_ADC_ACQUIRE_TIME 0x3f
109
#define H3_THERMAL_PER 401
110
#define H3_FILTER 0x6 /* Filter enabled, avg of 8 */
111
#define H3_TEMP_BASE 217
112
#define H3_TEMP_MUL 1000
113
#define H3_TEMP_DIV 8253
114
#define H3_TEMP_MINUS 1794000
115
#define H3_INIT_ALARM 90 /* degC */
116
#define H3_INIT_SHUT 105 /* degC */
117
118
#define H5_CLK_RATE 24000000
119
#define H5_ADC_ACQUIRE_TIME 479 /* 24Mhz/479 = 20us */
120
#define H5_THERMAL_PER 58 /* 4096 * (58 + 1) / 24Mhz = 10ms */
121
#define H5_FILTER 0x6 /* Filter enabled, avg of 8 */
122
#define H5_TEMP_BASE 233832448
123
#define H5_TEMP_MUL 124885
124
#define H5_TEMP_DIV 20
125
#define H5_TEMP_BASE_CPU 271581184
126
#define H5_TEMP_MUL_CPU 152253
127
#define H5_TEMP_BASE_GPU 289406976
128
#define H5_TEMP_MUL_GPU 166724
129
#define H5_INIT_CPU_ALARM 80 /* degC */
130
#define H5_INIT_CPU_SHUT 96 /* degC */
131
#define H5_INIT_GPU_ALARM 84 /* degC */
132
#define H5_INIT_GPU_SHUT 100 /* degC */
133
134
#define TEMP_C_TO_K 273
135
#define SENSOR_ENABLE_ALL (SENSOR0_EN|SENSOR1_EN|SENSOR2_EN)
136
#define SHUT_INT_ALL (SHUT_INT0_STS|SHUT_INT1_STS|SHUT_INT2_STS)
137
#define ALARM_INT_ALL (ALARM_INT0_STS)
138
139
#define MAX_SENSORS 3
140
#define MAX_CF_LEVELS 64
141
142
#define THROTTLE_ENABLE_DEFAULT 1
143
144
/* Enable thermal throttling */
145
static int aw_thermal_throttle_enable = THROTTLE_ENABLE_DEFAULT;
146
TUNABLE_INT("hw.aw_thermal.throttle_enable", &aw_thermal_throttle_enable);
147
148
struct aw_thermal_sensor {
149
const char *name;
150
const char *desc;
151
int init_alarm;
152
int init_shut;
153
};
154
155
struct aw_thermal_config {
156
struct aw_thermal_sensor sensors[MAX_SENSORS];
157
int nsensors;
158
uint64_t clk_rate;
159
uint32_t adc_acquire_time;
160
int adc_cali_en;
161
uint32_t filter;
162
uint32_t thermal_per;
163
int (*to_temp)(uint32_t, int);
164
uint32_t (*to_reg)(int, int);
165
int temp_base;
166
int temp_mul;
167
int temp_div;
168
int calib0, calib1;
169
uint32_t calib0_mask, calib1_mask;
170
};
171
172
static int
173
a83t_to_temp(uint32_t val, int sensor)
174
{
175
return ((A83T_TEMP_BASE - (val * A83T_TEMP_MUL)) / A83T_TEMP_DIV);
176
}
177
178
static const struct aw_thermal_config a83t_config = {
179
.nsensors = 3,
180
.sensors = {
181
[0] = {
182
.name = "cluster0",
183
.desc = "CPU cluster 0 temperature",
184
},
185
[1] = {
186
.name = "cluster1",
187
.desc = "CPU cluster 1 temperature",
188
},
189
[2] = {
190
.name = "gpu",
191
.desc = "GPU temperature",
192
},
193
},
194
.clk_rate = A83T_CLK_RATE,
195
.adc_acquire_time = A83T_ADC_ACQUIRE_TIME,
196
.adc_cali_en = 1,
197
.filter = A83T_FILTER,
198
.thermal_per = A83T_THERMAL_PER,
199
.to_temp = a83t_to_temp,
200
.calib0_mask = 0xffffffff,
201
.calib1_mask = 0xffff,
202
};
203
204
static int
205
a64_to_temp(uint32_t val, int sensor)
206
{
207
return ((A64_TEMP_BASE - (val * A64_TEMP_MUL)) / A64_TEMP_DIV);
208
}
209
210
static const struct aw_thermal_config a64_config = {
211
.nsensors = 3,
212
.sensors = {
213
[0] = {
214
.name = "cpu",
215
.desc = "CPU temperature",
216
},
217
[1] = {
218
.name = "gpu1",
219
.desc = "GPU temperature 1",
220
},
221
[2] = {
222
.name = "gpu2",
223
.desc = "GPU temperature 2",
224
},
225
},
226
.clk_rate = A64_CLK_RATE,
227
.adc_acquire_time = A64_ADC_ACQUIRE_TIME,
228
.adc_cali_en = 1,
229
.filter = A64_FILTER,
230
.thermal_per = A64_THERMAL_PER,
231
.to_temp = a64_to_temp,
232
.calib0_mask = 0xffffffff,
233
.calib1_mask = 0xffff,
234
};
235
236
static int
237
h3_to_temp(uint32_t val, int sensor)
238
{
239
return (H3_TEMP_BASE - ((val * H3_TEMP_MUL) / H3_TEMP_DIV));
240
}
241
242
static uint32_t
243
h3_to_reg(int val, int sensor)
244
{
245
return ((H3_TEMP_MINUS - (val * H3_TEMP_DIV)) / H3_TEMP_MUL);
246
}
247
248
static const struct aw_thermal_config h3_config = {
249
.nsensors = 1,
250
.sensors = {
251
[0] = {
252
.name = "cpu",
253
.desc = "CPU temperature",
254
.init_alarm = H3_INIT_ALARM,
255
.init_shut = H3_INIT_SHUT,
256
},
257
},
258
.clk_rate = H3_CLK_RATE,
259
.adc_acquire_time = H3_ADC_ACQUIRE_TIME,
260
.adc_cali_en = 1,
261
.filter = H3_FILTER,
262
.thermal_per = H3_THERMAL_PER,
263
.to_temp = h3_to_temp,
264
.to_reg = h3_to_reg,
265
.calib0_mask = 0xffffffff,
266
};
267
268
static int
269
h5_to_temp(uint32_t val, int sensor)
270
{
271
int tmp;
272
273
/* Temp is lower than 70 degrees */
274
if (val > 0x500) {
275
tmp = H5_TEMP_BASE - (val * H5_TEMP_MUL);
276
tmp >>= H5_TEMP_DIV;
277
return (tmp);
278
}
279
280
if (sensor == 0)
281
tmp = H5_TEMP_BASE_CPU - (val * H5_TEMP_MUL_CPU);
282
else if (sensor == 1)
283
tmp = H5_TEMP_BASE_GPU - (val * H5_TEMP_MUL_GPU);
284
else {
285
printf("Unknown sensor %d\n", sensor);
286
return (val);
287
}
288
289
tmp >>= H5_TEMP_DIV;
290
return (tmp);
291
}
292
293
static uint32_t
294
h5_to_reg(int val, int sensor)
295
{
296
int tmp;
297
298
if (val < 70) {
299
tmp = H5_TEMP_BASE - (val << H5_TEMP_DIV);
300
tmp /= H5_TEMP_MUL;
301
} else {
302
if (sensor == 0) {
303
tmp = H5_TEMP_BASE_CPU - (val << H5_TEMP_DIV);
304
tmp /= H5_TEMP_MUL_CPU;
305
} else if (sensor == 1) {
306
tmp = H5_TEMP_BASE_GPU - (val << H5_TEMP_DIV);
307
tmp /= H5_TEMP_MUL_GPU;
308
} else {
309
printf("Unknown sensor %d\n", sensor);
310
return (val);
311
}
312
}
313
314
return ((uint32_t)tmp);
315
}
316
317
static const struct aw_thermal_config h5_config = {
318
.nsensors = 2,
319
.sensors = {
320
[0] = {
321
.name = "cpu",
322
.desc = "CPU temperature",
323
.init_alarm = H5_INIT_CPU_ALARM,
324
.init_shut = H5_INIT_CPU_SHUT,
325
},
326
[1] = {
327
.name = "gpu",
328
.desc = "GPU temperature",
329
.init_alarm = H5_INIT_GPU_ALARM,
330
.init_shut = H5_INIT_GPU_SHUT,
331
},
332
},
333
.clk_rate = H5_CLK_RATE,
334
.adc_acquire_time = H5_ADC_ACQUIRE_TIME,
335
.filter = H5_FILTER,
336
.thermal_per = H5_THERMAL_PER,
337
.to_temp = h5_to_temp,
338
.to_reg = h5_to_reg,
339
.calib0_mask = 0xffffffff,
340
};
341
342
static struct ofw_compat_data compat_data[] = {
343
{ "allwinner,sun8i-a83t-ths", (uintptr_t)&a83t_config },
344
{ "allwinner,sun8i-h3-ths", (uintptr_t)&h3_config },
345
{ "allwinner,sun50i-a64-ths", (uintptr_t)&a64_config },
346
{ "allwinner,sun50i-h5-ths", (uintptr_t)&h5_config },
347
{ NULL, (uintptr_t)NULL }
348
};
349
350
#define THS_CONF(d) \
351
(void *)ofw_bus_search_compatible((d), compat_data)->ocd_data
352
353
struct aw_thermal_softc {
354
device_t dev;
355
struct resource *res[2];
356
struct aw_thermal_config *conf;
357
358
struct task cf_task;
359
int throttle;
360
int min_freq;
361
struct cf_level levels[MAX_CF_LEVELS];
362
eventhandler_tag cf_pre_tag;
363
364
clk_t clk_apb;
365
clk_t clk_ths;
366
};
367
368
static struct resource_spec aw_thermal_spec[] = {
369
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
370
{ SYS_RES_IRQ, 0, RF_ACTIVE },
371
{ -1, 0 }
372
};
373
374
#define RD4(sc, reg) bus_read_4((sc)->res[0], (reg))
375
#define WR4(sc, reg, val) bus_write_4((sc)->res[0], (reg), (val))
376
377
static int
378
aw_thermal_init(struct aw_thermal_softc *sc)
379
{
380
phandle_t node;
381
uint32_t calib[2];
382
int error;
383
384
node = ofw_bus_get_node(sc->dev);
385
if (nvmem_get_cell_len(node, "calibration") > sizeof(calib)) {
386
device_printf(sc->dev, "calibration nvmem cell is too large\n");
387
return (ENXIO);
388
}
389
error = nvmem_read_cell_by_name(node, "calibration",
390
(void *)&calib, nvmem_get_cell_len(node, "calibration"));
391
/* Read calibration settings from EFUSE */
392
if (error != 0) {
393
device_printf(sc->dev, "Cannot read THS efuse\n");
394
return (error);
395
}
396
397
calib[0] &= sc->conf->calib0_mask;
398
calib[1] &= sc->conf->calib1_mask;
399
400
/* Write calibration settings to thermal controller */
401
if (calib[0] != 0)
402
WR4(sc, THS_CALIB0, calib[0]);
403
if (calib[1] != 0)
404
WR4(sc, THS_CALIB1, calib[1]);
405
406
/* Configure ADC acquire time (CLK_IN/(N+1)) and enable sensors */
407
WR4(sc, THS_CTRL1, ADC_CALI_EN);
408
WR4(sc, THS_CTRL0, sc->conf->adc_acquire_time);
409
WR4(sc, THS_CTRL2, sc->conf->adc_acquire_time << SENSOR_ACQ1_SHIFT);
410
411
/* Set thermal period */
412
WR4(sc, THS_INTC, sc->conf->thermal_per << THS_THERMAL_PER_SHIFT);
413
414
/* Enable average filter */
415
WR4(sc, THS_FILTER, sc->conf->filter);
416
417
/* Enable interrupts */
418
WR4(sc, THS_INTS, RD4(sc, THS_INTS));
419
WR4(sc, THS_INTC, RD4(sc, THS_INTC) | SHUT_INT_ALL | ALARM_INT_ALL);
420
421
/* Enable sensors */
422
WR4(sc, THS_CTRL2, RD4(sc, THS_CTRL2) | SENSOR_ENABLE_ALL);
423
424
return (0);
425
}
426
427
static int
428
aw_thermal_gettemp(struct aw_thermal_softc *sc, int sensor)
429
{
430
uint32_t val;
431
432
val = RD4(sc, THS_DATA0 + (sensor * 4));
433
434
return (sc->conf->to_temp(val, sensor));
435
}
436
437
static int
438
aw_thermal_getshut(struct aw_thermal_softc *sc, int sensor)
439
{
440
uint32_t val;
441
442
val = RD4(sc, THS_SHUTDOWN0_CTRL + (sensor * 4));
443
val = (val >> SHUT_T_HOT_SHIFT) & SHUT_T_HOT_MASK;
444
445
return (sc->conf->to_temp(val, sensor));
446
}
447
448
static void
449
aw_thermal_setshut(struct aw_thermal_softc *sc, int sensor, int temp)
450
{
451
uint32_t val;
452
453
val = RD4(sc, THS_SHUTDOWN0_CTRL + (sensor * 4));
454
val &= ~(SHUT_T_HOT_MASK << SHUT_T_HOT_SHIFT);
455
val |= (sc->conf->to_reg(temp, sensor) << SHUT_T_HOT_SHIFT);
456
WR4(sc, THS_SHUTDOWN0_CTRL + (sensor * 4), val);
457
}
458
459
static int
460
aw_thermal_gethyst(struct aw_thermal_softc *sc, int sensor)
461
{
462
uint32_t val;
463
464
val = RD4(sc, THS_ALARM0_CTRL + (sensor * 4));
465
val = (val >> ALARM_T_HYST_SHIFT) & ALARM_T_HYST_MASK;
466
467
return (sc->conf->to_temp(val, sensor));
468
}
469
470
static int
471
aw_thermal_getalarm(struct aw_thermal_softc *sc, int sensor)
472
{
473
uint32_t val;
474
475
val = RD4(sc, THS_ALARM0_CTRL + (sensor * 4));
476
val = (val >> ALARM_T_HOT_SHIFT) & ALARM_T_HOT_MASK;
477
478
return (sc->conf->to_temp(val, sensor));
479
}
480
481
static void
482
aw_thermal_setalarm(struct aw_thermal_softc *sc, int sensor, int temp)
483
{
484
uint32_t val;
485
486
val = RD4(sc, THS_ALARM0_CTRL + (sensor * 4));
487
val &= ~(ALARM_T_HOT_MASK << ALARM_T_HOT_SHIFT);
488
val |= (sc->conf->to_reg(temp, sensor) << ALARM_T_HOT_SHIFT);
489
WR4(sc, THS_ALARM0_CTRL + (sensor * 4), val);
490
}
491
492
static int
493
aw_thermal_sysctl(SYSCTL_HANDLER_ARGS)
494
{
495
struct aw_thermal_softc *sc;
496
int sensor, val;
497
498
sc = arg1;
499
sensor = arg2;
500
501
val = aw_thermal_gettemp(sc, sensor) + TEMP_C_TO_K;
502
503
return sysctl_handle_opaque(oidp, &val, sizeof(val), req);
504
}
505
506
static void
507
aw_thermal_throttle(struct aw_thermal_softc *sc, int enable)
508
{
509
device_t cf_dev;
510
int count, error;
511
512
if (enable == sc->throttle)
513
return;
514
515
if (enable != 0) {
516
/* Set the lowest available frequency */
517
cf_dev = devclass_get_device(devclass_find("cpufreq"), 0);
518
if (cf_dev == NULL)
519
return;
520
count = MAX_CF_LEVELS;
521
error = CPUFREQ_LEVELS(cf_dev, sc->levels, &count);
522
if (error != 0 || count == 0)
523
return;
524
sc->min_freq = sc->levels[count - 1].total_set.freq;
525
error = CPUFREQ_SET(cf_dev, &sc->levels[count - 1],
526
CPUFREQ_PRIO_USER);
527
if (error != 0)
528
return;
529
}
530
531
sc->throttle = enable;
532
}
533
534
static void
535
aw_thermal_cf_task(void *arg, int pending)
536
{
537
struct aw_thermal_softc *sc;
538
539
sc = arg;
540
541
aw_thermal_throttle(sc, 1);
542
}
543
544
static void
545
aw_thermal_cf_pre_change(void *arg, const struct cf_level *level, int *status)
546
{
547
struct aw_thermal_softc *sc;
548
int temp_cur, temp_alarm;
549
550
sc = arg;
551
552
if (aw_thermal_throttle_enable == 0 || sc->throttle == 0 ||
553
level->total_set.freq == sc->min_freq)
554
return;
555
556
temp_cur = aw_thermal_gettemp(sc, 0);
557
temp_alarm = aw_thermal_getalarm(sc, 0);
558
559
if (temp_cur < temp_alarm)
560
aw_thermal_throttle(sc, 0);
561
else
562
*status = ENXIO;
563
}
564
565
static void
566
aw_thermal_intr(void *arg)
567
{
568
struct aw_thermal_softc *sc;
569
device_t dev;
570
uint32_t ints;
571
572
dev = arg;
573
sc = device_get_softc(dev);
574
575
ints = RD4(sc, THS_INTS);
576
WR4(sc, THS_INTS, ints);
577
578
if ((ints & SHUT_INT_ALL) != 0) {
579
device_printf(dev,
580
"WARNING - current temperature exceeds safe limits\n");
581
shutdown_nice(RB_POWEROFF);
582
}
583
584
if ((ints & ALARM_INT_ALL) != 0)
585
taskqueue_enqueue(taskqueue_thread, &sc->cf_task);
586
}
587
588
static int
589
aw_thermal_probe(device_t dev)
590
{
591
if (!ofw_bus_status_okay(dev))
592
return (ENXIO);
593
594
if (THS_CONF(dev) == NULL)
595
return (ENXIO);
596
597
device_set_desc(dev, "Allwinner Thermal Sensor Controller");
598
return (BUS_PROBE_DEFAULT);
599
}
600
601
static int
602
aw_thermal_attach(device_t dev)
603
{
604
struct aw_thermal_softc *sc;
605
hwreset_t rst;
606
int i, error;
607
void *ih;
608
609
sc = device_get_softc(dev);
610
sc->dev = dev;
611
rst = NULL;
612
ih = NULL;
613
614
sc->conf = THS_CONF(dev);
615
TASK_INIT(&sc->cf_task, 0, aw_thermal_cf_task, sc);
616
617
if (bus_alloc_resources(dev, aw_thermal_spec, sc->res) != 0) {
618
device_printf(dev, "cannot allocate resources for device\n");
619
return (ENXIO);
620
}
621
622
if (clk_get_by_ofw_name(dev, 0, "bus", &sc->clk_apb) == 0) {
623
error = clk_enable(sc->clk_apb);
624
if (error != 0) {
625
device_printf(dev, "cannot enable apb clock\n");
626
goto fail;
627
}
628
}
629
630
if (clk_get_by_ofw_name(dev, 0, "mod", &sc->clk_ths) == 0) {
631
error = clk_set_freq(sc->clk_ths, sc->conf->clk_rate, 0);
632
if (error != 0) {
633
device_printf(dev, "cannot set ths clock rate\n");
634
goto fail;
635
}
636
error = clk_enable(sc->clk_ths);
637
if (error != 0) {
638
device_printf(dev, "cannot enable ths clock\n");
639
goto fail;
640
}
641
}
642
643
if (hwreset_get_by_ofw_idx(dev, 0, 0, &rst) == 0) {
644
error = hwreset_deassert(rst);
645
if (error != 0) {
646
device_printf(dev, "cannot de-assert reset\n");
647
goto fail;
648
}
649
}
650
651
error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC | INTR_MPSAFE,
652
NULL, aw_thermal_intr, dev, &ih);
653
if (error != 0) {
654
device_printf(dev, "cannot setup interrupt handler\n");
655
goto fail;
656
}
657
658
for (i = 0; i < sc->conf->nsensors; i++) {
659
if (sc->conf->sensors[i].init_alarm > 0)
660
aw_thermal_setalarm(sc, i,
661
sc->conf->sensors[i].init_alarm);
662
if (sc->conf->sensors[i].init_shut > 0)
663
aw_thermal_setshut(sc, i,
664
sc->conf->sensors[i].init_shut);
665
}
666
667
if (aw_thermal_init(sc) != 0)
668
goto fail;
669
670
for (i = 0; i < sc->conf->nsensors; i++)
671
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
672
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
673
OID_AUTO, sc->conf->sensors[i].name,
674
CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
675
sc, i, aw_thermal_sysctl, "IK0",
676
sc->conf->sensors[i].desc);
677
678
if (bootverbose)
679
for (i = 0; i < sc->conf->nsensors; i++) {
680
device_printf(dev,
681
"%s: alarm %dC hyst %dC shut %dC\n",
682
sc->conf->sensors[i].name,
683
aw_thermal_getalarm(sc, i),
684
aw_thermal_gethyst(sc, i),
685
aw_thermal_getshut(sc, i));
686
}
687
688
sc->cf_pre_tag = EVENTHANDLER_REGISTER(cpufreq_pre_change,
689
aw_thermal_cf_pre_change, sc, EVENTHANDLER_PRI_FIRST);
690
691
return (0);
692
693
fail:
694
if (ih != NULL)
695
bus_teardown_intr(dev, sc->res[1], ih);
696
if (rst != NULL)
697
hwreset_release(rst);
698
if (sc->clk_apb != NULL)
699
clk_release(sc->clk_apb);
700
if (sc->clk_ths != NULL)
701
clk_release(sc->clk_ths);
702
bus_release_resources(dev, aw_thermal_spec, sc->res);
703
704
return (ENXIO);
705
}
706
707
static device_method_t aw_thermal_methods[] = {
708
/* Device interface */
709
DEVMETHOD(device_probe, aw_thermal_probe),
710
DEVMETHOD(device_attach, aw_thermal_attach),
711
712
DEVMETHOD_END
713
};
714
715
static driver_t aw_thermal_driver = {
716
"aw_thermal",
717
aw_thermal_methods,
718
sizeof(struct aw_thermal_softc),
719
};
720
721
DRIVER_MODULE(aw_thermal, simplebus, aw_thermal_driver, 0, 0);
722
MODULE_VERSION(aw_thermal, 1);
723
MODULE_DEPEND(aw_thermal, aw_sid, 1, 1, 1);
724
SIMPLEBUS_PNP_INFO(compat_data);
725
726