2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2019 Michal Meloun <mmel@FreeBSD.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
30 * Thermometer and thermal zones driver for RockChip SoCs.
31 * Calibration data are taken from Linux, because this part of SoC
32 * is undocumented in TRM.
35 #include <sys/param.h>
36 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/module.h>
41 #include <sys/malloc.h>
43 #include <sys/sysctl.h>
45 #include <machine/bus.h>
47 #include <dev/clk/clk.h>
48 #include <dev/hwreset/hwreset.h>
49 #include <dev/syscon/syscon.h>
50 #include <dev/ofw/ofw_bus.h>
51 #include <dev/ofw/ofw_bus_subr.h>
53 #include "syscon_if.h"
54 #include "rk_tsadc_if.h"
61 /* Global registers */
62 #define TSADC_USER_CON 0x000
63 #define TSADC_AUTO_CON 0x004
64 #define TSADC_AUTO_CON_POL_HI (1 << 8)
65 #define TSADC_AUTO_SRC_EN(x) (1 << (4 + (x)))
66 #define TSADC_AUTO_Q_SEL (1 << 1) /* V3 only */
67 #define TSADC_AUTO_CON_AUTO (1 << 0)
69 #define TSADC_INT_EN 0x008
70 #define TSADC_INT_EN_2CRU_EN_SRC(x) (1 << (8 + (x)))
71 #define TSADC_INT_EN_2GPIO_EN_SRC(x) (1 << (4 + (x)))
72 #define TSADC_INT_PD 0x00c
73 #define TSADC_DATA(x) (0x20 + (x) * 0x04)
74 #define TSADC_COMP_INT(x) (0x30 + (x) * 0x04)
75 #define TSADC_COMP_INT_SRC_EN(x) (1 << (0 + (x)))
76 #define TSADC_COMP_SHUT(x) (0x40 + (x) * 0x04)
77 #define TSADC_HIGHT_INT_DEBOUNCE 0x060
78 #define TSADC_HIGHT_TSHUT_DEBOUNCE 0x064
79 #define TSADC_AUTO_PERIOD 0x068
80 #define TSADC_AUTO_PERIOD_HT 0x06c
81 #define TSADC_COMP0_LOW_INT 0x080 /* V3 only */
82 #define TSADC_COMP1_LOW_INT 0x084 /* V3 only */
84 /* V3 GFR registers */
85 #define GRF_SARADC_TESTBIT 0x0e644
86 #define GRF_SARADC_TESTBIT_ON (0x10001 << 2)
87 #define GRF_TSADC_TESTBIT_L 0x0e648
88 #define GRF_TSADC_VCM_EN_L (0x10001 << 7)
89 #define GRF_TSADC_TESTBIT_H 0x0e64c
90 #define GRF_TSADC_VCM_EN_H (0x10001 << 7)
91 #define GRF_TSADC_TESTBIT_H_ON (0x10001 << 2)
94 #define GRF_TSADC_CON 0x0600
95 #define GRF_TSADC_ANA_REG0 (0x10001 << 0)
96 #define GRF_TSADC_ANA_REG1 (0x10001 << 1)
97 #define GRF_TSADC_ANA_REG2 (0x10001 << 2)
98 #define GRF_TSADC_TSEN (0x10001 << 8)
100 #define WR4(_sc, _r, _v) bus_write_4((_sc)->mem_res, (_r), (_v))
101 #define RD4(_sc, _r) bus_read_4((_sc)->mem_res, (_r))
103 static struct sysctl_ctx_list tsadc_sysctl_ctx
;
111 struct rk_calib_entry
{
116 struct tsadc_calib_info
{
117 struct rk_calib_entry
*table
;
127 struct tsensor
*tsensors
;
129 struct tsadc_calib_info calib_info
;
134 struct resource
*mem_res
;
135 struct resource
*irq_res
;
140 hwreset_array_t hwreset
;
143 struct tsadc_conf
*conf
;
152 static struct rk_calib_entry rk3288_calib_data
[] = {
189 struct tsensor rk3288_tsensors
[] = {
190 { .channel
= 0, .id
= 2, .name
= "reserved"},
191 { .channel
= 1, .id
= 0, .name
= "CPU"},
192 { .channel
= 2, .id
= 1, .name
= "GPU"},
195 struct tsadc_conf rk3288_tsadc_conf
= {
198 .shutdown_temp
= 95000,
199 .shutdown_mode
= 1, /* GPIO */
200 .shutdown_pol
= 0, /* Low */
201 .tsensors
= rk3288_tsensors
,
202 .ntsensors
= nitems(rk3288_tsensors
),
204 .table
= rk3288_calib_data
,
205 .nentries
= nitems(rk3288_calib_data
),
209 static struct rk_calib_entry rk3328_calib_data
[] = {
245 static struct tsensor rk3328_tsensors
[] = {
246 { .channel
= 0, .id
= 0, .name
= "CPU"},
249 static struct tsadc_conf rk3328_tsadc_conf
= {
252 .shutdown_temp
= 95000,
253 .shutdown_mode
= 0, /* CRU */
254 .shutdown_pol
= 0, /* Low */
255 .tsensors
= rk3328_tsensors
,
256 .ntsensors
= nitems(rk3328_tsensors
),
258 .table
= rk3328_calib_data
,
259 .nentries
= nitems(rk3328_calib_data
),
263 static struct rk_calib_entry rk3399_calib_data
[] = {
300 static struct tsensor rk3399_tsensors
[] = {
301 { .channel
= 0, .id
= 0, .name
= "CPU"},
302 { .channel
= 1, .id
= 1, .name
= "GPU"},
305 static struct tsadc_conf rk3399_tsadc_conf
= {
308 .shutdown_temp
= 95000,
309 .shutdown_mode
= 1, /* GPIO */
310 .shutdown_pol
= 0, /* Low */
311 .tsensors
= rk3399_tsensors
,
312 .ntsensors
= nitems(rk3399_tsensors
),
314 .table
= rk3399_calib_data
,
315 .nentries
= nitems(rk3399_calib_data
),
319 static struct rk_calib_entry rk3568_calib_data
[] = {
357 static struct tsensor rk3568_tsensors
[] = {
358 { .channel
= 0, .id
= 0, .name
= "CPU"},
359 { .channel
= 1, .id
= 1, .name
= "GPU"},
362 static struct tsadc_conf rk3568_tsadc_conf
= {
365 .shutdown_temp
= 95000,
366 .shutdown_mode
= 1, /* GPIO */
367 .shutdown_pol
= 0, /* Low */
368 .tsensors
= rk3568_tsensors
,
369 .ntsensors
= nitems(rk3568_tsensors
),
371 .table
= rk3568_calib_data
,
372 .nentries
= nitems(rk3568_calib_data
),
376 static struct ofw_compat_data compat_data
[] = {
377 {"rockchip,rk3288-tsadc", (uintptr_t)&rk3288_tsadc_conf
},
378 {"rockchip,rk3328-tsadc", (uintptr_t)&rk3328_tsadc_conf
},
379 {"rockchip,rk3399-tsadc", (uintptr_t)&rk3399_tsadc_conf
},
380 {"rockchip,rk3568-tsadc", (uintptr_t)&rk3568_tsadc_conf
},
385 tsadc_temp_to_raw(struct tsadc_softc
*sc
, int temp
)
387 struct rk_calib_entry
*tbl
;
388 int denom
, ntbl
, raw
, i
;
390 tbl
= sc
->conf
->calib_info
.table
;
391 ntbl
= sc
->conf
->calib_info
.nentries
;
393 if (temp
<= tbl
[0].temp
)
396 if (temp
>= tbl
[ntbl
- 1].temp
)
397 return (tbl
[ntbl
- 1].raw
);
399 for (i
= 1; i
< (ntbl
- 1); i
++) {
401 if (temp
== tbl
[i
].temp
)
403 if (temp
< tbl
[i
].temp
)
408 * Translated value is between i and i - 1 table entries.
409 * Do linear interpolation for it.
411 raw
= (int)tbl
[i
- 1].raw
- (int)tbl
[i
].raw
;
412 raw
*= temp
- tbl
[i
- 1].temp
;
413 denom
= tbl
[i
- 1].temp
- tbl
[i
].temp
;
414 raw
= tbl
[i
- 1].raw
+ raw
/ denom
;
419 tsadc_raw_to_temp(struct tsadc_softc
*sc
, uint32_t raw
)
421 struct rk_calib_entry
*tbl
;
422 int denom
, ntbl
, temp
, i
;
425 tbl
= sc
->conf
->calib_info
.table
;
426 ntbl
= sc
->conf
->calib_info
.nentries
;
427 descending
= tbl
[0].raw
> tbl
[1].raw
;
430 /* Raw column is in descending order. */
431 if (raw
>= tbl
[0].raw
)
432 return (tbl
[0].temp
);
433 if (raw
<= tbl
[ntbl
- 1].raw
)
434 return (tbl
[ntbl
- 1].temp
);
436 for (i
= ntbl
- 2; i
> 0; i
--) {
438 if (raw
== tbl
[i
].raw
)
439 return (tbl
[i
].temp
);
440 if (raw
< tbl
[i
].raw
)
444 /* Raw column is in ascending order. */
445 if (raw
<= tbl
[0].raw
)
446 return (tbl
[0].temp
);
447 if (raw
>= tbl
[ntbl
- 1].raw
)
448 return (tbl
[ntbl
- 1].temp
);
449 for (i
= 1; i
< (ntbl
- 1); i
++) {
451 if (raw
== tbl
[i
].raw
)
452 return (tbl
[i
].temp
);
453 if (raw
< tbl
[i
].raw
)
459 * Translated value is between i and i - 1 table entries.
460 * Do linear interpolation for it.
462 temp
= (int)tbl
[i
- 1].temp
- (int)tbl
[i
].temp
;
463 temp
*= raw
- tbl
[i
- 1].raw
;
464 denom
= tbl
[i
- 1].raw
- tbl
[i
].raw
;
465 temp
= tbl
[i
- 1].temp
+ temp
/ denom
;
470 tsadc_init_tsensor(struct tsadc_softc
*sc
, struct tsensor
*sensor
)
475 val
= RD4(sc
, TSADC_INT_EN
);
476 if (sc
->shutdown_mode
!= 0) {
477 /* Signal shutdown of GPIO pin */
478 val
&= ~TSADC_INT_EN_2CRU_EN_SRC(sensor
->channel
);
479 val
|= TSADC_INT_EN_2GPIO_EN_SRC(sensor
->channel
);
481 val
|= TSADC_INT_EN_2CRU_EN_SRC(sensor
->channel
);
482 val
&= ~TSADC_INT_EN_2GPIO_EN_SRC(sensor
->channel
);
484 WR4(sc
, TSADC_INT_EN
, val
);
486 /* Shutdown temperature */
487 val
= tsadc_raw_to_temp(sc
, sc
->shutdown_temp
);
488 WR4(sc
, TSADC_COMP_SHUT(sensor
->channel
), val
);
489 val
= RD4(sc
, TSADC_AUTO_CON
);
490 val
|= TSADC_AUTO_SRC_EN(sensor
->channel
);
491 WR4(sc
, TSADC_AUTO_CON
, val
);
493 /* Alarm temperature */
494 val
= tsadc_temp_to_raw(sc
, sc
->alarm_temp
);
495 WR4(sc
, TSADC_COMP_INT(sensor
->channel
), val
);
496 val
= RD4(sc
, TSADC_INT_EN
);
497 val
|= TSADC_COMP_INT_SRC_EN(sensor
->channel
);
498 WR4(sc
, TSADC_INT_EN
, val
);
502 tsadc_init(struct tsadc_softc
*sc
)
507 val
= 0; /* XXX Is this right? */
508 if (sc
->shutdown_pol
!= 0)
509 val
|= TSADC_AUTO_CON_POL_HI
;
511 val
&= ~TSADC_AUTO_CON_POL_HI
;
512 if (sc
->conf
->q_sel_ntc
)
513 val
|= TSADC_AUTO_Q_SEL
;
514 WR4(sc
, TSADC_AUTO_CON
, val
);
516 switch (sc
->conf
->version
) {
519 WR4(sc
, TSADC_AUTO_PERIOD
, 250); /* 250 ms */
520 WR4(sc
, TSADC_AUTO_PERIOD_HT
, 50); /* 50 ms */
521 WR4(sc
, TSADC_HIGHT_INT_DEBOUNCE
, 4);
522 WR4(sc
, TSADC_HIGHT_TSHUT_DEBOUNCE
, 4);
526 if (sc
->grf
== NULL
) {
527 /* Errata: adjust interleave to working value */
528 WR4(sc
, TSADC_USER_CON
, 13 << 6); /* 13 clks */
530 SYSCON_WRITE_4(sc
->grf
, GRF_TSADC_TESTBIT_L
,
532 SYSCON_WRITE_4(sc
->grf
, GRF_TSADC_TESTBIT_H
,
534 DELAY(30); /* 15 usec min */
536 SYSCON_WRITE_4(sc
->grf
, GRF_SARADC_TESTBIT
,
537 GRF_SARADC_TESTBIT_ON
);
538 SYSCON_WRITE_4(sc
->grf
, GRF_TSADC_TESTBIT_H
,
539 GRF_TSADC_TESTBIT_H_ON
);
540 DELAY(180); /* 90 usec min */
542 WR4(sc
, TSADC_AUTO_PERIOD
, 1875); /* 2.5 ms */
543 WR4(sc
, TSADC_AUTO_PERIOD_HT
, 1875); /* 2.5 ms */
544 WR4(sc
, TSADC_HIGHT_INT_DEBOUNCE
, 4);
545 WR4(sc
, TSADC_HIGHT_TSHUT_DEBOUNCE
, 4);
549 WR4(sc
, TSADC_USER_CON
, 0xfc0); /* 97us, at least 90us */
550 WR4(sc
, TSADC_AUTO_PERIOD
, 1622); /* 2.5ms */
551 WR4(sc
, TSADC_HIGHT_INT_DEBOUNCE
, 4);
552 WR4(sc
, TSADC_AUTO_PERIOD_HT
, 1622); /* 2.5ms */
553 WR4(sc
, TSADC_HIGHT_TSHUT_DEBOUNCE
, 4);
555 SYSCON_WRITE_4(sc
->grf
, GRF_TSADC_CON
, GRF_TSADC_TSEN
);
556 DELAY(15); /* 10 usec min */
557 SYSCON_WRITE_4(sc
->grf
, GRF_TSADC_CON
,
559 SYSCON_WRITE_4(sc
->grf
, GRF_TSADC_CON
,
561 SYSCON_WRITE_4(sc
->grf
, GRF_TSADC_CON
,
563 DELAY(100); /* 90 usec min */
570 tsadc_read_temp(struct tsadc_softc
*sc
, struct tsensor
*sensor
, int *temp
)
574 val
= RD4(sc
, TSADC_DATA(sensor
->channel
));
575 *temp
= tsadc_raw_to_temp(sc
, val
);
578 device_printf(sc
->dev
, "%s: Sensor(id: %d, ch: %d), val: %d temp: %d\n",
579 __func__
, sensor
->id
, sensor
->channel
, val
, *temp
);
580 device_printf(sc
->dev
, "%s: user_con=0x%08x auto_con=0x%08x "
581 "comp_int=0x%08x comp_shut=0x%08x\n",
582 __func__
, RD4(sc
, TSADC_USER_CON
), RD4(sc
, TSADC_AUTO_CON
),
583 RD4(sc
, TSADC_COMP_INT(sensor
->channel
)),
584 RD4(sc
, TSADC_COMP_SHUT(sensor
->channel
)));
590 tsadc_get_temp(device_t dev
, device_t cdev
, uintptr_t id
, int *val
)
592 struct tsadc_softc
*sc
;
595 sc
= device_get_softc(dev
);
597 if (id
>= sc
->conf
->ntsensors
)
600 for (i
= 0; i
< sc
->conf
->ntsensors
; i
++) {
601 if (sc
->conf
->tsensors
->id
== id
) {
602 rv
=tsadc_read_temp(sc
, sc
->conf
->tsensors
+ id
, val
);
610 tsadc_sysctl_temperature(SYSCTL_HANDLER_ARGS
)
612 struct tsadc_softc
*sc
;
618 if (req
->newptr
!= NULL
)
624 if (id
>= sc
->conf
->ntsensors
)
626 rv
= tsadc_read_temp(sc
, sc
->conf
->tsensors
+ id
, &val
);
632 rv
= sysctl_handle_int(oidp
, &val
, 0, req
);
637 tsadc_init_sysctl(struct tsadc_softc
*sc
)
640 struct sysctl_oid
*oid
, *tmp
;
642 sysctl_ctx_init(&tsadc_sysctl_ctx
);
643 /* create node for hw.temp */
644 oid
= SYSCTL_ADD_NODE(&tsadc_sysctl_ctx
,
645 SYSCTL_STATIC_CHILDREN(_hw
), OID_AUTO
, "temperature",
646 CTLFLAG_RD
| CTLFLAG_MPSAFE
, NULL
, "");
651 for (i
= sc
->conf
->ntsensors
- 1; i
>= 0; i
--) {
652 tmp
= SYSCTL_ADD_PROC(&tsadc_sysctl_ctx
,
653 SYSCTL_CHILDREN(oid
), OID_AUTO
, sc
->conf
->tsensors
[i
].name
,
654 CTLTYPE_INT
| CTLFLAG_RD
| CTLFLAG_NEEDGIANT
, sc
, i
,
655 tsadc_sysctl_temperature
, "IK", "SoC Temperature");
664 tsadc_intr(void *arg
)
666 struct tsadc_softc
*sc
;
669 sc
= (struct tsadc_softc
*)arg
;
671 val
= RD4(sc
, TSADC_INT_PD
);
672 WR4(sc
, TSADC_INT_PD
, val
);
674 /* XXX Handle shutdown and alarm interrupts. */
676 device_printf(sc
->dev
, "Alarm: device temperature "
677 "is above of shutdown level.\n");
678 } else if (val
& 0x000F) {
679 device_printf(sc
->dev
, "Alarm: device temperature "
680 "is above of alarm level.\n");
682 return (FILTER_HANDLED
);
686 tsadc_probe(device_t dev
)
689 if (!ofw_bus_status_okay(dev
))
692 if (ofw_bus_search_compatible(dev
, compat_data
)->ocd_data
== 0)
695 device_set_desc(dev
, "RockChip temperature sensors");
696 return (BUS_PROBE_DEFAULT
);
700 tsadc_attach(device_t dev
)
702 struct tsadc_softc
*sc
;
707 sc
= device_get_softc(dev
);
709 node
= ofw_bus_get_node(sc
->dev
);
710 sc
->conf
= (struct tsadc_conf
*)
711 ofw_bus_search_compatible(dev
, compat_data
)->ocd_data
;
712 sc
->alarm_temp
= 90000;
715 sc
->mem_res
= bus_alloc_resource_any(dev
, SYS_RES_MEMORY
, &rid
,
717 if (sc
->mem_res
== NULL
) {
718 device_printf(dev
, "Cannot allocate memory resources\n");
723 sc
->irq_res
= bus_alloc_resource_any(dev
, SYS_RES_IRQ
, &rid
, RF_ACTIVE
);
724 if (sc
->irq_res
== NULL
) {
725 device_printf(dev
, "Cannot allocate IRQ resources\n");
729 if ((bus_setup_intr(dev
, sc
->irq_res
, INTR_TYPE_MISC
| INTR_MPSAFE
,
730 tsadc_intr
, NULL
, sc
, &sc
->irq_ih
))) {
732 "WARNING: unable to register interrupt handler\n");
737 rv
= hwreset_array_get_ofw(dev
, 0, &sc
->hwreset
);
739 device_printf(dev
, "Cannot get resets\n");
742 rv
= clk_get_by_ofw_name(dev
, 0, "tsadc", &sc
->tsadc_clk
);
744 device_printf(dev
, "Cannot get 'tsadc' clock: %d\n", rv
);
747 rv
= clk_get_by_ofw_name(dev
, 0, "apb_pclk", &sc
->apb_pclk_clk
);
749 device_printf(dev
, "Cannot get 'apb_pclk' clock: %d\n", rv
);
753 /* grf is optional */
754 rv
= syscon_get_by_ofw_property(dev
, node
, "rockchip,grf", &sc
->grf
);
755 if (rv
!= 0 && rv
!= ENOENT
) {
756 device_printf(dev
, "Cannot get 'grf' syscon: %d\n", rv
);
760 rv
= OF_getencprop(node
, "rockchip,hw-tshut-temp",
761 &sc
->shutdown_temp
, sizeof(sc
->shutdown_temp
));
763 sc
->shutdown_temp
= sc
->conf
->shutdown_temp
;
765 rv
= OF_getencprop(node
, "rockchip,hw-tshut-mode",
766 &sc
->shutdown_mode
, sizeof(sc
->shutdown_mode
));
768 sc
->shutdown_mode
= sc
->conf
->shutdown_mode
;
770 rv
= OF_getencprop(node
, "rockchip,hw-tshut-polarity",
771 &sc
->shutdown_pol
, sizeof(sc
->shutdown_pol
));
773 sc
->shutdown_pol
= sc
->conf
->shutdown_pol
;
775 /* Wakeup controller */
776 rv
= hwreset_array_assert(sc
->hwreset
);
778 device_printf(dev
, "Cannot assert reset\n");
782 /* Set the assigned clocks parent and freq */
783 rv
= clk_set_assigned(sc
->dev
, node
);
784 if (rv
!= 0 && rv
!= ENOENT
) {
785 device_printf(dev
, "clk_set_assigned failed\n");
789 rv
= clk_enable(sc
->tsadc_clk
);
791 device_printf(dev
, "Cannot enable 'tsadc_clk' clock: %d\n", rv
);
794 rv
= clk_enable(sc
->apb_pclk_clk
);
796 device_printf(dev
, "Cannot enable 'apb_pclk' clock: %d\n", rv
);
799 rv
= hwreset_array_deassert(sc
->hwreset
);
801 device_printf(dev
, "Cannot deassert reset\n");
806 for (i
= 0; i
< sc
->conf
->ntsensors
; i
++)
807 tsadc_init_tsensor(sc
, sc
->conf
->tsensors
+ i
);
809 /* Enable auto mode */
810 val
= RD4(sc
, TSADC_AUTO_CON
);
811 val
|= TSADC_AUTO_CON_AUTO
;
812 WR4(sc
, TSADC_AUTO_CON
, val
);
814 rv
= tsadc_init_sysctl(sc
);
816 device_printf(sc
->dev
, "Cannot initialize sysctls\n");
820 OF_device_register_xref(OF_xref_from_node(node
), dev
);
821 bus_attach_children(dev
);
825 sysctl_ctx_free(&tsadc_sysctl_ctx
);
827 if (sc
->irq_ih
!= NULL
)
828 bus_teardown_intr(dev
, sc
->irq_res
, sc
->irq_ih
);
829 if (sc
->tsadc_clk
!= NULL
)
830 clk_release(sc
->tsadc_clk
);
831 if (sc
->apb_pclk_clk
!= NULL
)
832 clk_release(sc
->apb_pclk_clk
);
833 if (sc
->hwreset
!= NULL
)
834 hwreset_array_release(sc
->hwreset
);
835 if (sc
->irq_res
!= NULL
)
836 bus_release_resource(dev
, SYS_RES_IRQ
, 0, sc
->irq_res
);
837 if (sc
->mem_res
!= NULL
)
838 bus_release_resource(dev
, SYS_RES_MEMORY
, 0, sc
->mem_res
);
844 tsadc_detach(device_t dev
)
846 struct tsadc_softc
*sc
;
847 sc
= device_get_softc(dev
);
849 if (sc
->irq_ih
!= NULL
)
850 bus_teardown_intr(dev
, sc
->irq_res
, sc
->irq_ih
);
851 sysctl_ctx_free(&tsadc_sysctl_ctx
);
852 if (sc
->tsadc_clk
!= NULL
)
853 clk_release(sc
->tsadc_clk
);
854 if (sc
->apb_pclk_clk
!= NULL
)
855 clk_release(sc
->apb_pclk_clk
);
856 if (sc
->hwreset
!= NULL
)
857 hwreset_array_release(sc
->hwreset
);
858 if (sc
->irq_res
!= NULL
)
859 bus_release_resource(dev
, SYS_RES_IRQ
, 0, sc
->irq_res
);
860 if (sc
->mem_res
!= NULL
)
861 bus_release_resource(dev
, SYS_RES_MEMORY
, 0, sc
->mem_res
);
866 static device_method_t rk_tsadc_methods
[] = {
867 /* Device interface */
868 DEVMETHOD(device_probe
, tsadc_probe
),
869 DEVMETHOD(device_attach
, tsadc_attach
),
870 DEVMETHOD(device_detach
, tsadc_detach
),
872 /* TSADC interface */
873 DEVMETHOD(rk_tsadc_get_temperature
, tsadc_get_temp
),
878 static DEFINE_CLASS_0(rk_tsadc
, rk_tsadc_driver
, rk_tsadc_methods
,
879 sizeof(struct tsadc_softc
));
880 EARLY_DRIVER_MODULE(rk_tsadc
, simplebus
, rk_tsadc_driver
, NULL
, NULL
,
881 BUS_PASS_TIMER
+ BUS_PASS_ORDER_LAST
);