rk_tsadc.c revision 1.6.2.3 1 1.6.2.3 martin /* $NetBSD: rk_tsadc.c,v 1.6.2.3 2020/04/13 08:03:37 martin Exp $ */
2 1.6.2.2 christos
3 1.6.2.2 christos /*
4 1.6.2.2 christos * Copyright (c) 2019 Matthew R. Green
5 1.6.2.2 christos * All rights reserved.
6 1.6.2.2 christos *
7 1.6.2.2 christos * Redistribution and use in source and binary forms, with or without
8 1.6.2.2 christos * modification, are permitted provided that the following conditions
9 1.6.2.2 christos * are met:
10 1.6.2.2 christos * 1. Redistributions of source code must retain the above copyright
11 1.6.2.2 christos * notice, this list of conditions and the following disclaimer.
12 1.6.2.2 christos * 2. Redistributions in binary form must reproduce the above copyright
13 1.6.2.2 christos * notice, this list of conditions and the following disclaimer in the
14 1.6.2.2 christos * documentation and/or other materials provided with the distribution.
15 1.6.2.2 christos * 3. The name of the author may not be used to endorse or promote products
16 1.6.2.2 christos * derived from this software without specific prior written permission.
17 1.6.2.2 christos *
18 1.6.2.2 christos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 1.6.2.2 christos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 1.6.2.2 christos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 1.6.2.2 christos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 1.6.2.2 christos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 1.6.2.2 christos * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 1.6.2.2 christos * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 1.6.2.2 christos * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 1.6.2.2 christos * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 1.6.2.2 christos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 1.6.2.2 christos * SUCH DAMAGE.
29 1.6.2.2 christos */
30 1.6.2.2 christos
31 1.6.2.2 christos #include <sys/cdefs.h>
32 1.6.2.2 christos
33 1.6.2.3 martin __KERNEL_RCSID(0, "$NetBSD: rk_tsadc.c,v 1.6.2.3 2020/04/13 08:03:37 martin Exp $");
34 1.6.2.2 christos
35 1.6.2.2 christos /*
36 1.6.2.2 christos * Driver for the TSADC temperature sensor monitor in RK3328 and RK3399.
37 1.6.2.2 christos *
38 1.6.2.2 christos * TODO:
39 1.6.2.2 christos * - handle setting various temp values
40 1.6.2.2 christos * - handle DT trips/temp value defaults
41 1.6.2.2 christos * - interrupts aren't triggered (test by lowering warn/crit values), and
42 1.6.2.2 christos * once they work, make the interrupt do something
43 1.6.2.2 christos */
44 1.6.2.2 christos
45 1.6.2.2 christos #include <sys/param.h>
46 1.6.2.2 christos #include <sys/bus.h>
47 1.6.2.2 christos #include <sys/device.h>
48 1.6.2.2 christos #include <sys/intr.h>
49 1.6.2.2 christos #include <sys/systm.h>
50 1.6.2.2 christos #include <sys/time.h>
51 1.6.2.2 christos #include <sys/kmem.h>
52 1.6.2.2 christos
53 1.6.2.2 christos #include <dev/fdt/fdtvar.h>
54 1.6.2.2 christos #include <dev/fdt/syscon.h>
55 1.6.2.2 christos
56 1.6.2.2 christos #include <dev/sysmon/sysmonvar.h>
57 1.6.2.2 christos
58 1.6.2.2 christos #ifdef RKTSADC_DEBUG
59 1.6.2.2 christos #define DPRINTF(fmt, ...) \
60 1.6.2.2 christos printf("%s:%d: " fmt "\n", __func__, __LINE__, ## __VA_ARGS__)
61 1.6.2.2 christos #else
62 1.6.2.2 christos #define DPRINTF(fmt, ...)
63 1.6.2.2 christos #endif
64 1.6.2.2 christos
65 1.6.2.2 christos /* Register definitions */
66 1.6.2.2 christos #define TSADC_USER_CON 0x00
67 1.6.2.2 christos #define TSADC_USER_CON_ADC_STATUS __BIT(12)
68 1.6.2.2 christos #define TSADC_USER_CON_INTER_PD_SOC __BITS(11,6)
69 1.6.2.2 christos #define TSADC_USER_CON_START __BIT(5)
70 1.6.2.2 christos #define TSADC_USER_CON_START_MODE __BIT(4)
71 1.6.2.2 christos #define TSADC_USER_CON_ADC_POWER_CTRL __BIT(3)
72 1.6.2.2 christos #define TSADC_USER_CON_ADC_INPUT_SRC_SEL __BITS(2,0)
73 1.6.2.2 christos #define TSADC_AUTO_CON 0x04
74 1.6.2.2 christos #define TSADC_AUTO_CON_LAST_TSHUT_2CRU __BIT(25)
75 1.6.2.2 christos #define TSADC_AUTO_CON_LAST_TSHUT_2GPIO __BIT(24)
76 1.6.2.2 christos #define TSADC_AUTO_CON_SAMPLE_DLY_SEL __BIT(17)
77 1.6.2.2 christos #define TSADC_AUTO_CON_AUTO_STATUS __BIT(16)
78 1.6.2.2 christos #define TSADC_AUTO_CON_SRC1_LT_EN __BIT(13)
79 1.6.2.2 christos #define TSADC_AUTO_CON_SRC0_LT_EN __BIT(12)
80 1.6.2.2 christos #define TSADC_AUTO_CON_TSHUT_POLARITY __BIT(8)
81 1.6.2.2 christos #define TSADC_AUTO_CON_SRC1_EN __BIT(5)
82 1.6.2.2 christos #define TSADC_AUTO_CON_SRC0_EN __BIT(4)
83 1.6.2.2 christos #define TSADC_AUTO_CON_Q_SEL __BIT(1)
84 1.6.2.2 christos #define TSADC_AUTO_CON_AUTO_EN __BIT(0)
85 1.6.2.2 christos #define TSADC_INT_EN 0x08
86 1.6.2.2 christos #define TSADC_INT_EN_EOC_INT_EN __BIT(16)
87 1.6.2.2 christos #define TSADC_INT_EN_LT_INTEN_SRC1 __BIT(13)
88 1.6.2.2 christos #define TSADC_INT_EN_LT_INTEN_SRC0 __BIT(12)
89 1.6.2.2 christos #define TSADC_INT_EN_TSHUT_2CRU_EN_SRC1 __BIT(9)
90 1.6.2.2 christos #define TSADC_INT_EN_TSHUT_2CRU_EN_SRC0 __BIT(8)
91 1.6.2.2 christos #define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC1 __BIT(5)
92 1.6.2.2 christos #define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0 __BIT(4)
93 1.6.2.2 christos #define TSADC_INT_EN_HT_INTEN_SRC1 __BIT(1)
94 1.6.2.2 christos #define TSADC_INT_EN_HT_INTEN_SRC0 __BIT(0)
95 1.6.2.2 christos #define TSADC_INT_PD 0x0c
96 1.6.2.2 christos #define TSADC_INT_PD_EOC_INT_PD __BIT(16)
97 1.6.2.2 christos #define TSADC_INT_PD_LT_IRQ_SRC1 __BIT(13)
98 1.6.2.2 christos #define TSADC_INT_PD_LT_IRQ_SRC0 __BIT(12)
99 1.6.2.2 christos #define TSADC_INT_PD_TSHUT_O_SRC1 __BIT(5)
100 1.6.2.2 christos #define TSADC_INT_PD_TSHUT_O_SRC0 __BIT(4)
101 1.6.2.2 christos #define TSADC_INT_PD_HT_IRQ_SRC1 __BIT(1)
102 1.6.2.2 christos #define TSADC_INT_PD_HT_IRQ_SRC0 __BIT(0)
103 1.6.2.2 christos #define TSADC_DATA0 0x20
104 1.6.2.2 christos #define TSADC_DATA0_ADC_DATA __BITS(11,0)
105 1.6.2.2 christos #define TSADC_DATA1 0x24
106 1.6.2.2 christos #define TSADC_DATA1_ADC_DATA __BITS(11,0)
107 1.6.2.2 christos #define TSADC_COMP0_INT 0x30
108 1.6.2.2 christos #define TSADC_COMP0_INT_COMP_SRC0 __BITS(11,0)
109 1.6.2.2 christos #define TSADC_COMP1_INT 0x34
110 1.6.2.2 christos #define TSADC_COMP1_INT_COMP_SRC1 __BITS(11,0)
111 1.6.2.2 christos #define TSADC_COMP0_SHUT 0x40
112 1.6.2.2 christos #define TSADC_COMP0_SHUT_COMP_SRC0 __BITS(11,0)
113 1.6.2.2 christos #define TSADC_COMP1_SHUT 0x44
114 1.6.2.2 christos #define TSADC_COMP1_SHUT_COMP_SRC1 __BITS(11,0)
115 1.6.2.2 christos #define TSADC_HIGH_INT_DEBOUNCE 0x60
116 1.6.2.2 christos #define TSADC_HIGH_INT_DEBOUNCE_TEMP __BITS(7,0)
117 1.6.2.2 christos #define TSADC_HIGH_TSHUT_DEBOUNCE 0x64
118 1.6.2.2 christos #define TSADC_HIGH_TSHUT_DEBOUNCE_TEMP __BITS(7,0)
119 1.6.2.2 christos #define TSADC_AUTO_PERIOD 0x68
120 1.6.2.2 christos #define TSADC_AUTO_PERIOD_TEMP __BITS(31,0)
121 1.6.2.2 christos #define TSADC_AUTO_PERIOD_HT 0x6c
122 1.6.2.2 christos #define TSADC_AUTO_PERIOD_HT_TEMP __BITS(31,0)
123 1.6.2.2 christos #define TSADC_COMP0_LOW_INT 0x80
124 1.6.2.2 christos #define TSADC_COMP0_LOW_INT_COMP_SRC0 __BITS(11,0)
125 1.6.2.2 christos #define TSADC_COMP1_LOW_INT 0x84
126 1.6.2.2 christos #define TSADC_COMP1_LOW_INT_COMP_SRC1 __BITS(11,0)
127 1.6.2.2 christos
128 1.6.2.2 christos #define RK3328_TSADC_AUTO_PERIOD_TIME 250 /* 250ms */
129 1.6.2.2 christos #define RK3399_TSADC_AUTO_PERIOD_TIME 1875 /* 2.5ms */
130 1.6.2.2 christos #define TSADC_HT_DEBOUNCE_COUNT 4
131 1.6.2.2 christos
132 1.6.2.2 christos /*
133 1.6.2.2 christos * All this magic is taking from the Linux rockchip_thermal driver.
134 1.6.2.2 christos *
135 1.6.2.2 christos * VCM means "voltage common mode", but the documentation for RK3399
136 1.6.2.2 christos * does not mention this and I don't know what any of this really
137 1.6.2.2 christos * is for.
138 1.6.2.2 christos */
139 1.6.2.2 christos #define RK3399_GRF_SARADC_TESTBIT 0xe644
140 1.6.2.2 christos #define RK3399_GRF_SARADC_TESTBIT_ON (0x10001 << 2)
141 1.6.2.2 christos #define RK3399_GRF_TSADC_TESTBIT_L 0xe648
142 1.6.2.2 christos #define RK3399_GRF_TSADC_TESTBIT_VCM_EN_L (0x10001 << 7)
143 1.6.2.2 christos #define RK3399_GRF_TSADC_TESTBIT_H 0xe64c
144 1.6.2.2 christos #define RK3399_GRF_TSADC_TESTBIT_VCM_EN_H (0x10001 << 7)
145 1.6.2.2 christos #define RK3399_GRF_TSADC_TESTBIT_H_ON (0x10001 << 2)
146 1.6.2.2 christos
147 1.6.2.2 christos #define TEMP_uC_TO_uK 273150000
148 1.6.2.2 christos
149 1.6.2.2 christos #define TSHUT_MODE_CPU 0
150 1.6.2.2 christos #define TSHUT_MODE_GPIO 1
151 1.6.2.2 christos
152 1.6.2.2 christos #define TSHUT_LOW_ACTIVE 0
153 1.6.2.2 christos #define TSHUT_HIGH_ACTIVE 1
154 1.6.2.2 christos
155 1.6.2.2 christos #define TSHUT_DEF_TEMP 95000
156 1.6.2.2 christos
157 1.6.2.2 christos #define TSADC_DATA_MAX 0xfff
158 1.6.2.2 christos
159 1.6.2.2 christos #define MAX_SENSORS 2
160 1.6.2.2 christos
161 1.6.2.2 christos typedef struct rk_data_array {
162 1.6.2.2 christos uint32_t data; /* register value */
163 1.6.2.2 christos int temp; /* micro-degC */
164 1.6.2.2 christos } rk_data_array;
165 1.6.2.2 christos
166 1.6.2.2 christos struct rk_tsadc_softc;
167 1.6.2.2 christos typedef struct rk_data {
168 1.6.2.2 christos const rk_data_array *rd_array;
169 1.6.2.2 christos size_t rd_size;
170 1.6.2.2 christos void (*rd_init)(struct rk_tsadc_softc *, int, int);
171 1.6.2.2 christos bool rd_decr; /* lower values -> higher temp */
172 1.6.2.2 christos unsigned rd_min, rd_max;
173 1.6.2.2 christos unsigned rd_auto_period;
174 1.6.2.2 christos unsigned rd_num_sensors;
175 1.6.2.2 christos } rk_data;
176 1.6.2.2 christos
177 1.6.2.2 christos /* Per-sensor data */
178 1.6.2.2 christos struct rk_tsadc_sensor {
179 1.6.2.2 christos envsys_data_t s_data;
180 1.6.2.2 christos bool s_attached;
181 1.6.2.2 christos /* TSADC register offsets for this sensor */
182 1.6.2.2 christos unsigned s_data_reg;
183 1.6.2.2 christos unsigned s_comp_tshut;
184 1.6.2.2 christos unsigned s_comp_int;
185 1.6.2.2 christos /* enable bit in AUTO_CON register */
186 1.6.2.2 christos unsigned s_comp_int_en;
187 1.6.2.2 christos /* warn/crit values in micro Kelvin */
188 1.6.2.2 christos int s_warn;
189 1.6.2.2 christos int s_tshut;
190 1.6.2.2 christos };
191 1.6.2.2 christos
192 1.6.2.2 christos struct rk_tsadc_softc {
193 1.6.2.2 christos device_t sc_dev;
194 1.6.2.2 christos int sc_phandle;
195 1.6.2.2 christos bus_space_tag_t sc_bst;
196 1.6.2.2 christos bus_space_handle_t sc_bsh;
197 1.6.2.2 christos size_t sc_size;
198 1.6.2.2 christos uint32_t sc_data_mask;
199 1.6.2.2 christos void *sc_ih;
200 1.6.2.2 christos
201 1.6.2.2 christos struct sysmon_envsys *sc_sme;
202 1.6.2.2 christos struct rk_tsadc_sensor sc_sensors[MAX_SENSORS];
203 1.6.2.2 christos
204 1.6.2.2 christos struct clk *sc_clock;
205 1.6.2.2 christos struct clk *sc_clockapb;
206 1.6.2.2 christos struct fdtbus_reset *sc_reset;
207 1.6.2.2 christos struct syscon *sc_syscon;
208 1.6.2.2 christos
209 1.6.2.2 christos const rk_data *sc_rd;
210 1.6.2.2 christos };
211 1.6.2.2 christos
212 1.6.2.2 christos static int rk_tsadc_match(device_t, cfdata_t, void *);
213 1.6.2.2 christos static void rk_tsadc_attach(device_t, device_t, void *);
214 1.6.2.2 christos static int rk_tsadc_detach(device_t, int);
215 1.6.2.2 christos static int rk_tsadc_init_clocks(struct rk_tsadc_softc *);
216 1.6.2.2 christos static void rk_tsadc_init_counts(struct rk_tsadc_softc *);
217 1.6.2.2 christos static void rk_tsadc_tshut_set(struct rk_tsadc_softc *s);
218 1.6.2.2 christos static void rk_tsadc_init_tshut(struct rk_tsadc_softc *, int, int);
219 1.6.2.2 christos static void rk_tsadc_init_rk3328(struct rk_tsadc_softc *, int, int);
220 1.6.2.2 christos static void rk_tsadc_init_rk3399(struct rk_tsadc_softc *, int, int);
221 1.6.2.2 christos static void rk_tsadc_init_enable(struct rk_tsadc_softc *);
222 1.6.2.2 christos static void rk_tsadc_init(struct rk_tsadc_softc *, int, int);
223 1.6.2.2 christos static void rk_tsadc_refresh(struct sysmon_envsys *, envsys_data_t *);
224 1.6.2.2 christos static void rk_tsadc_get_limits(struct sysmon_envsys *, envsys_data_t *,
225 1.6.2.2 christos sysmon_envsys_lim_t *, uint32_t *);
226 1.6.2.2 christos
227 1.6.2.2 christos static int rk_tsadc_intr(void *);
228 1.6.2.2 christos static int rk_tsadc_data_to_temp(struct rk_tsadc_softc *, uint32_t);
229 1.6.2.2 christos static uint32_t rk_tsadc_temp_to_data(struct rk_tsadc_softc *, int);
230 1.6.2.2 christos
231 1.6.2.2 christos /* RK3328/RK3399 compatible sensors */
232 1.6.2.2 christos static const struct rk_tsadc_sensor rk_tsadc_sensors[] = {
233 1.6.2.2 christos {
234 1.6.2.2 christos .s_data = { .desc = "CPU" },
235 1.6.2.2 christos .s_data_reg = TSADC_DATA0,
236 1.6.2.2 christos .s_comp_tshut = TSADC_COMP0_SHUT,
237 1.6.2.2 christos .s_comp_int = TSADC_COMP0_INT,
238 1.6.2.2 christos .s_comp_int_en = TSADC_AUTO_CON_SRC0_EN,
239 1.6.2.2 christos /*
240 1.6.2.2 christos * XXX DT has:
241 1.6.2.2 christos * cpu_alert1: cpu_alert1 {
242 1.6.2.2 christos * temperature = <75000>;
243 1.6.2.2 christos * hysteresis = <2000>;
244 1.6.2.2 christos * cpu_crit: cpu_crit {
245 1.6.2.2 christos * temperature = <95000>;
246 1.6.2.2 christos * hysteresis = <2000>;
247 1.6.2.2 christos * pull out of here?
248 1.6.2.2 christos * do something with hysteresis? put in debounce?
249 1.6.2.2 christos *
250 1.6.2.2 christos * Note that tshut may be overriden by the board specific DT.
251 1.6.2.2 christos */
252 1.6.2.2 christos .s_warn = 75000000,
253 1.6.2.2 christos .s_tshut = 95000000,
254 1.6.2.2 christos }, {
255 1.6.2.2 christos .s_data = { .desc = "GPU" },
256 1.6.2.2 christos .s_data_reg = TSADC_DATA1,
257 1.6.2.2 christos .s_comp_tshut = TSADC_COMP1_SHUT,
258 1.6.2.2 christos .s_comp_int = TSADC_COMP1_INT,
259 1.6.2.2 christos .s_comp_int_en = TSADC_AUTO_CON_SRC1_EN,
260 1.6.2.2 christos .s_warn = 75000000,
261 1.6.2.2 christos .s_tshut = 95000000,
262 1.6.2.2 christos },
263 1.6.2.2 christos };
264 1.6.2.2 christos
265 1.6.2.2 christos /*
266 1.6.2.2 christos * Table from RK3328 manual. Note that the manual lists valid numbers as
267 1.6.2.2 christos * 4096 - number. This also means it is increasing not decreasing for
268 1.6.2.2 christos * higher temps, and the min and max are also offset from 4096.
269 1.6.2.2 christos */
270 1.6.2.2 christos #define RK3328_DATA_OFFSET (4096)
271 1.6.2.2 christos static const rk_data_array rk3328_data_array[] = {
272 1.6.2.2 christos #define ENTRY(d,C) \
273 1.6.2.2 christos { .data = RK3328_DATA_OFFSET - (d), .temp = (C) * 1000 * 1000, }
274 1.6.2.2 christos ENTRY(TSADC_DATA_MAX, -40),
275 1.6.2.2 christos ENTRY(3800, -40),
276 1.6.2.2 christos ENTRY(3792, -35),
277 1.6.2.2 christos ENTRY(3783, -30),
278 1.6.2.2 christos ENTRY(3774, -25),
279 1.6.2.2 christos ENTRY(3765, -20),
280 1.6.2.2 christos ENTRY(3756, -15),
281 1.6.2.2 christos ENTRY(3747, -10),
282 1.6.2.2 christos ENTRY(3737, -5),
283 1.6.2.2 christos ENTRY(3728, 0),
284 1.6.2.2 christos ENTRY(3718, 5),
285 1.6.2.2 christos ENTRY(3708, 10),
286 1.6.2.2 christos ENTRY(3698, 15),
287 1.6.2.2 christos ENTRY(3688, 20),
288 1.6.2.2 christos ENTRY(3678, 25),
289 1.6.2.2 christos ENTRY(3667, 30),
290 1.6.2.2 christos ENTRY(3656, 35),
291 1.6.2.2 christos ENTRY(3645, 40),
292 1.6.2.2 christos ENTRY(3634, 45),
293 1.6.2.2 christos ENTRY(3623, 50),
294 1.6.2.2 christos ENTRY(3611, 55),
295 1.6.2.2 christos ENTRY(3600, 60),
296 1.6.2.2 christos ENTRY(3588, 65),
297 1.6.2.2 christos ENTRY(3575, 70),
298 1.6.2.2 christos ENTRY(3563, 75),
299 1.6.2.2 christos ENTRY(3550, 80),
300 1.6.2.2 christos ENTRY(3537, 85),
301 1.6.2.2 christos ENTRY(3524, 90),
302 1.6.2.2 christos ENTRY(3510, 95),
303 1.6.2.2 christos ENTRY(3496, 100),
304 1.6.2.2 christos ENTRY(3482, 105),
305 1.6.2.2 christos ENTRY(3467, 110),
306 1.6.2.2 christos ENTRY(3452, 115),
307 1.6.2.2 christos ENTRY(3437, 120),
308 1.6.2.2 christos ENTRY(3421, 125),
309 1.6.2.2 christos ENTRY(0, 125),
310 1.6.2.2 christos #undef ENTRY
311 1.6.2.2 christos };
312 1.6.2.2 christos
313 1.6.2.2 christos /* Table from RK3399 manual */
314 1.6.2.2 christos static const rk_data_array rk3399_data_array[] = {
315 1.6.2.2 christos #define ENTRY(d,C) { .data = (d), .temp = (C) * 1000 * 1000, }
316 1.6.2.2 christos ENTRY(0, -40),
317 1.6.2.2 christos ENTRY(402, -40),
318 1.6.2.2 christos ENTRY(410, -35),
319 1.6.2.2 christos ENTRY(419, -30),
320 1.6.2.2 christos ENTRY(427, -25),
321 1.6.2.2 christos ENTRY(436, -20),
322 1.6.2.2 christos ENTRY(444, -15),
323 1.6.2.2 christos ENTRY(453, -10),
324 1.6.2.2 christos ENTRY(461, -5),
325 1.6.2.2 christos ENTRY(470, 0),
326 1.6.2.2 christos ENTRY(478, 5),
327 1.6.2.2 christos ENTRY(487, 10),
328 1.6.2.2 christos ENTRY(496, 15),
329 1.6.2.2 christos ENTRY(504, 20),
330 1.6.2.2 christos ENTRY(513, 25),
331 1.6.2.2 christos ENTRY(521, 30),
332 1.6.2.2 christos ENTRY(530, 35),
333 1.6.2.2 christos ENTRY(538, 40),
334 1.6.2.2 christos ENTRY(547, 45),
335 1.6.2.2 christos ENTRY(555, 50),
336 1.6.2.2 christos ENTRY(564, 55),
337 1.6.2.2 christos ENTRY(573, 60),
338 1.6.2.2 christos ENTRY(581, 65),
339 1.6.2.2 christos ENTRY(590, 70),
340 1.6.2.2 christos ENTRY(599, 75),
341 1.6.2.2 christos ENTRY(607, 80),
342 1.6.2.2 christos ENTRY(616, 85),
343 1.6.2.2 christos ENTRY(624, 90),
344 1.6.2.2 christos ENTRY(633, 95),
345 1.6.2.2 christos ENTRY(642, 100),
346 1.6.2.2 christos ENTRY(650, 105),
347 1.6.2.2 christos ENTRY(659, 110),
348 1.6.2.2 christos ENTRY(668, 115),
349 1.6.2.2 christos ENTRY(677, 120),
350 1.6.2.2 christos ENTRY(685, 125),
351 1.6.2.2 christos ENTRY(TSADC_DATA_MAX, 125),
352 1.6.2.2 christos #undef ENTRY
353 1.6.2.2 christos };
354 1.6.2.2 christos
355 1.6.2.2 christos static const rk_data rk3328_data_table = {
356 1.6.2.2 christos .rd_array = rk3328_data_array,
357 1.6.2.2 christos .rd_size = __arraycount(rk3328_data_array),
358 1.6.2.2 christos .rd_init = rk_tsadc_init_rk3328,
359 1.6.2.2 christos .rd_decr = false,
360 1.6.2.2 christos .rd_max = RK3328_DATA_OFFSET - 3420,
361 1.6.2.2 christos .rd_min = RK3328_DATA_OFFSET - 3801,
362 1.6.2.2 christos .rd_auto_period = RK3328_TSADC_AUTO_PERIOD_TIME,
363 1.6.2.2 christos .rd_num_sensors = 1,
364 1.6.2.2 christos };
365 1.6.2.2 christos
366 1.6.2.2 christos static const rk_data rk3399_data_table = {
367 1.6.2.2 christos .rd_array = rk3399_data_array,
368 1.6.2.2 christos .rd_size = __arraycount(rk3399_data_array),
369 1.6.2.2 christos .rd_init = rk_tsadc_init_rk3399,
370 1.6.2.2 christos .rd_decr = false,
371 1.6.2.2 christos .rd_max = 686,
372 1.6.2.2 christos .rd_min = 401,
373 1.6.2.2 christos .rd_auto_period = RK3399_TSADC_AUTO_PERIOD_TIME,
374 1.6.2.2 christos .rd_num_sensors = 2,
375 1.6.2.2 christos };
376 1.6.2.2 christos
377 1.6.2.2 christos static const char * const compatible_rk3328[] = {
378 1.6.2.2 christos "rockchip,rk3328-tsadc",
379 1.6.2.2 christos NULL
380 1.6.2.2 christos };
381 1.6.2.2 christos
382 1.6.2.2 christos static const char * const compatible_rk3399[] = {
383 1.6.2.2 christos "rockchip,rk3399-tsadc",
384 1.6.2.2 christos NULL
385 1.6.2.2 christos };
386 1.6.2.2 christos
387 1.6.2.2 christos #define TSADC_READ(sc, reg) \
388 1.6.2.2 christos bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
389 1.6.2.2 christos #define TSADC_WRITE(sc, reg, val) \
390 1.6.2.2 christos bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
391 1.6.2.2 christos
392 1.6.2.2 christos CFATTACH_DECL3_NEW(rk_tsadc, sizeof(struct rk_tsadc_softc),
393 1.6.2.2 christos rk_tsadc_match, rk_tsadc_attach, rk_tsadc_detach, NULL, NULL, NULL,
394 1.6.2.2 christos DVF_DETACH_SHUTDOWN);
395 1.6.2.2 christos
396 1.6.2.2 christos /* init/teardown support */
397 1.6.2.2 christos static int
398 1.6.2.2 christos rk_tsadc_match(device_t parent, cfdata_t cf, void *aux)
399 1.6.2.2 christos {
400 1.6.2.2 christos struct fdt_attach_args * const faa = aux;
401 1.6.2.2 christos
402 1.6.2.2 christos return of_match_compatible(faa->faa_phandle, compatible_rk3328) ||
403 1.6.2.2 christos of_match_compatible(faa->faa_phandle, compatible_rk3399);
404 1.6.2.2 christos }
405 1.6.2.2 christos
406 1.6.2.2 christos static void
407 1.6.2.2 christos rk_tsadc_attach(device_t parent, device_t self, void *aux)
408 1.6.2.2 christos {
409 1.6.2.2 christos struct rk_tsadc_softc * const sc = device_private(self);
410 1.6.2.2 christos struct fdt_attach_args * const faa = aux;
411 1.6.2.2 christos char intrstr[128];
412 1.6.2.2 christos const int phandle = faa->faa_phandle;
413 1.6.2.2 christos bus_addr_t addr;
414 1.6.2.2 christos int mode, polarity, tshut_temp;
415 1.6.2.2 christos
416 1.6.2.2 christos sc->sc_dev = self;
417 1.6.2.2 christos sc->sc_phandle = phandle;
418 1.6.2.2 christos sc->sc_bst = faa->faa_bst;
419 1.6.2.2 christos
420 1.6.2.2 christos aprint_naive("\n");
421 1.6.2.2 christos aprint_normal(": RK3328/3399 Temperature Sensor ADC\n");
422 1.6.2.2 christos
423 1.6.2.2 christos sc->sc_sme = sysmon_envsys_create();
424 1.6.2.2 christos
425 1.6.2.2 christos sc->sc_sme->sme_name = device_xname(self);
426 1.6.2.2 christos sc->sc_sme->sme_cookie = sc;
427 1.6.2.2 christos sc->sc_sme->sme_refresh = rk_tsadc_refresh;
428 1.6.2.2 christos sc->sc_sme->sme_get_limits = rk_tsadc_get_limits;
429 1.6.2.2 christos sc->sc_data_mask = TSADC_DATA_MAX;
430 1.6.2.2 christos
431 1.6.2.2 christos pmf_device_register(self, NULL, NULL);
432 1.6.2.2 christos
433 1.6.2.2 christos if (of_match_compatible(faa->faa_phandle, compatible_rk3328)) {
434 1.6.2.2 christos sc->sc_rd = &rk3328_data_table;
435 1.6.2.2 christos } else {
436 1.6.2.2 christos KASSERT(of_match_compatible(faa->faa_phandle, compatible_rk3399));
437 1.6.2.2 christos sc->sc_rd = &rk3399_data_table;
438 1.6.2.2 christos }
439 1.6.2.2 christos
440 1.6.2.2 christos /* Default to tshut via gpio and tshut low is active */
441 1.6.2.2 christos if (of_getprop_uint32(phandle, "rockchip,hw-tshut-mode",
442 1.6.2.2 christos &mode) != 0) {
443 1.6.2.2 christos aprint_error(": could not get TSHUT mode, default to GPIO");
444 1.6.2.2 christos mode = TSHUT_MODE_GPIO;
445 1.6.2.2 christos }
446 1.6.2.2 christos if (mode != TSHUT_MODE_CPU && mode != TSHUT_MODE_GPIO) {
447 1.6.2.2 christos aprint_error(": TSHUT mode should be 0 or 1\n");
448 1.6.2.2 christos goto fail;
449 1.6.2.2 christos }
450 1.6.2.2 christos
451 1.6.2.2 christos if (of_getprop_uint32(phandle, "rockchip,hw-tshut-polarity",
452 1.6.2.2 christos &polarity) != 0) {
453 1.6.2.2 christos aprint_error(": could not get TSHUT polarity, default to low");
454 1.6.2.2 christos polarity = TSHUT_LOW_ACTIVE;
455 1.6.2.2 christos }
456 1.6.2.2 christos if (of_getprop_uint32(phandle,
457 1.6.2.2 christos "rockchip,hw-tshut-temp", &tshut_temp) != 0) {
458 1.6.2.2 christos aprint_error(": could not get TSHUT temperature, default to %u",
459 1.6.2.2 christos TSHUT_DEF_TEMP);
460 1.6.2.2 christos tshut_temp = TSHUT_DEF_TEMP;
461 1.6.2.2 christos }
462 1.6.2.2 christos tshut_temp *= 1000; /* convert fdt ms -> us */
463 1.6.2.2 christos
464 1.6.2.2 christos memcpy(sc->sc_sensors, rk_tsadc_sensors, sizeof(sc->sc_sensors));
465 1.6.2.2 christos for (unsigned n = 0; n < sc->sc_rd->rd_num_sensors; n++) {
466 1.6.2.2 christos struct rk_tsadc_sensor *rks = &sc->sc_sensors[n];
467 1.6.2.2 christos
468 1.6.2.2 christos rks->s_data.flags = ENVSYS_FMONLIMITS;
469 1.6.2.2 christos rks->s_data.units = ENVSYS_STEMP;
470 1.6.2.2 christos rks->s_data.state = ENVSYS_SINVALID;
471 1.6.2.2 christos
472 1.6.2.2 christos if (sysmon_envsys_sensor_attach(sc->sc_sme, &rks->s_data))
473 1.6.2.2 christos goto fail;
474 1.6.2.2 christos rks->s_attached = true;
475 1.6.2.2 christos rks->s_tshut = tshut_temp;
476 1.6.2.2 christos #if 0
477 1.6.2.2 christos // testing
478 1.6.2.2 christos rks->s_tshut = 68000000;
479 1.6.2.2 christos rks->s_warn = 61000000;
480 1.6.2.2 christos #endif
481 1.6.2.2 christos }
482 1.6.2.2 christos
483 1.6.2.2 christos sc->sc_syscon = fdtbus_syscon_acquire(phandle, "rockchip,grf");
484 1.6.2.2 christos if (sc->sc_syscon == NULL) {
485 1.6.2.2 christos aprint_error(": couldn't get grf syscon\n");
486 1.6.2.2 christos goto fail;
487 1.6.2.2 christos }
488 1.6.2.2 christos if (fdtbus_get_reg(phandle, 0, &addr, &sc->sc_size) != 0) {
489 1.6.2.2 christos aprint_error(": couldn't get registers\n");
490 1.6.2.2 christos sc->sc_size = 0;
491 1.6.2.2 christos goto fail;
492 1.6.2.2 christos }
493 1.6.2.2 christos if (bus_space_map(sc->sc_bst, addr, sc->sc_size, 0, &sc->sc_bsh) != 0) {
494 1.6.2.2 christos aprint_error(": couldn't map registers\n");
495 1.6.2.2 christos sc->sc_size = 0;
496 1.6.2.2 christos goto fail;
497 1.6.2.2 christos }
498 1.6.2.2 christos
499 1.6.2.2 christos if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
500 1.6.2.2 christos aprint_error(": failed to decode interrupt\n");
501 1.6.2.2 christos goto fail;
502 1.6.2.2 christos }
503 1.6.2.2 christos
504 1.6.2.2 christos sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_VM, FDT_INTR_MPSAFE,
505 1.6.2.2 christos rk_tsadc_intr, sc);
506 1.6.2.2 christos if (sc->sc_ih == NULL) {
507 1.6.2.2 christos aprint_error_dev(self, "couldn't establish interrupt on %s\n",
508 1.6.2.2 christos intrstr);
509 1.6.2.2 christos goto fail;
510 1.6.2.2 christos }
511 1.6.2.2 christos aprint_normal_dev(self, "interrupting on %s\n", intrstr);
512 1.6.2.2 christos
513 1.6.2.2 christos if (rk_tsadc_init_clocks(sc)) {
514 1.6.2.2 christos aprint_error(": couldn't enable clocks\n");
515 1.6.2.2 christos return;
516 1.6.2.2 christos }
517 1.6.2.2 christos
518 1.6.2.2 christos /*
519 1.6.2.2 christos * Manual says to setup auto period (both), high temp (interrupt),
520 1.6.2.2 christos * high temp (shutdown), enable high temp resets (TSHUT to GPIO
521 1.6.2.2 christos * or reset chip), set the debounce times, and, finally, enable the
522 1.6.2.2 christos * controller iself.
523 1.6.2.2 christos */
524 1.6.2.2 christos rk_tsadc_init(sc, mode, polarity);
525 1.6.2.2 christos
526 1.6.2.2 christos return;
527 1.6.2.2 christos
528 1.6.2.2 christos fail:
529 1.6.2.2 christos rk_tsadc_detach(self, 0);
530 1.6.2.2 christos }
531 1.6.2.2 christos
532 1.6.2.2 christos static int
533 1.6.2.2 christos rk_tsadc_detach(device_t self, int flags)
534 1.6.2.2 christos {
535 1.6.2.2 christos struct rk_tsadc_softc *sc = device_private(self);
536 1.6.2.2 christos
537 1.6.2.2 christos pmf_device_deregister(self);
538 1.6.2.2 christos
539 1.6.2.2 christos for (unsigned n = 0; n < sc->sc_rd->rd_num_sensors; n++) {
540 1.6.2.2 christos struct rk_tsadc_sensor *rks = &sc->sc_sensors[n];
541 1.6.2.2 christos
542 1.6.2.2 christos if (rks->s_attached) {
543 1.6.2.2 christos sysmon_envsys_sensor_detach(sc->sc_sme, &rks->s_data);
544 1.6.2.2 christos rks->s_attached = false;
545 1.6.2.2 christos }
546 1.6.2.2 christos }
547 1.6.2.2 christos
548 1.6.2.2 christos sysmon_envsys_unregister(sc->sc_sme);
549 1.6.2.2 christos
550 1.6.2.2 christos if (sc->sc_clockapb)
551 1.6.2.2 christos clk_disable(sc->sc_clockapb);
552 1.6.2.2 christos if (sc->sc_clock)
553 1.6.2.2 christos clk_disable(sc->sc_clock);
554 1.6.2.2 christos
555 1.6.2.2 christos if (sc->sc_ih)
556 1.6.2.2 christos fdtbus_intr_disestablish(sc->sc_phandle, sc->sc_ih);
557 1.6.2.2 christos
558 1.6.2.2 christos if (sc->sc_size)
559 1.6.2.2 christos bus_space_unmap(sc->sc_bst, sc->sc_bsh, sc->sc_size);
560 1.6.2.2 christos
561 1.6.2.2 christos sysmon_envsys_destroy(sc->sc_sme);
562 1.6.2.2 christos
563 1.6.2.2 christos return 0;
564 1.6.2.2 christos }
565 1.6.2.2 christos
566 1.6.2.2 christos static int
567 1.6.2.2 christos rk_tsadc_init_clocks(struct rk_tsadc_softc *sc)
568 1.6.2.2 christos {
569 1.6.2.2 christos int error;
570 1.6.2.2 christos
571 1.6.2.2 christos fdtbus_clock_assign(sc->sc_phandle);
572 1.6.2.2 christos
573 1.6.2.2 christos sc->sc_reset = fdtbus_reset_get(sc->sc_phandle, "tsadc-apb");
574 1.6.2.2 christos sc->sc_clock = fdtbus_clock_get(sc->sc_phandle, "tsadc");
575 1.6.2.2 christos sc->sc_clockapb = fdtbus_clock_get(sc->sc_phandle, "apb_pclk");
576 1.6.2.2 christos if (sc->sc_reset == NULL ||
577 1.6.2.2 christos sc->sc_clock == NULL ||
578 1.6.2.2 christos sc->sc_clockapb == NULL)
579 1.6.2.2 christos return EINVAL;
580 1.6.2.2 christos
581 1.6.2.2 christos fdtbus_reset_assert(sc->sc_reset);
582 1.6.2.2 christos
583 1.6.2.2 christos error = clk_enable(sc->sc_clock);
584 1.6.2.2 christos if (error) {
585 1.6.2.2 christos fdtbus_reset_deassert(sc->sc_reset);
586 1.6.2.2 christos return error;
587 1.6.2.2 christos }
588 1.6.2.2 christos
589 1.6.2.2 christos error = clk_enable(sc->sc_clockapb);
590 1.6.2.2 christos
591 1.6.2.2 christos DELAY(20);
592 1.6.2.2 christos fdtbus_reset_deassert(sc->sc_reset);
593 1.6.2.2 christos
594 1.6.2.2 christos return error;
595 1.6.2.2 christos }
596 1.6.2.2 christos
597 1.6.2.2 christos static void
598 1.6.2.2 christos rk_tsadc_init_counts(struct rk_tsadc_softc *sc)
599 1.6.2.2 christos {
600 1.6.2.2 christos
601 1.6.2.2 christos TSADC_WRITE(sc, TSADC_AUTO_PERIOD, sc->sc_rd->rd_auto_period);
602 1.6.2.2 christos TSADC_WRITE(sc, TSADC_AUTO_PERIOD_HT, sc->sc_rd->rd_auto_period);
603 1.6.2.2 christos TSADC_WRITE(sc, TSADC_HIGH_INT_DEBOUNCE, TSADC_HT_DEBOUNCE_COUNT);
604 1.6.2.2 christos TSADC_WRITE(sc, TSADC_HIGH_TSHUT_DEBOUNCE, TSADC_HT_DEBOUNCE_COUNT);
605 1.6.2.2 christos }
606 1.6.2.2 christos
607 1.6.2.2 christos /* Configure the hardware with the tshut setup. */
608 1.6.2.2 christos static void
609 1.6.2.2 christos rk_tsadc_tshut_set(struct rk_tsadc_softc *sc)
610 1.6.2.2 christos {
611 1.6.2.2 christos uint32_t val = TSADC_READ(sc, TSADC_AUTO_CON);
612 1.6.2.2 christos
613 1.6.2.2 christos for (unsigned n = 0; n < sc->sc_rd->rd_num_sensors; n++) {
614 1.6.2.2 christos struct rk_tsadc_sensor *rks = &sc->sc_sensors[n];
615 1.6.2.2 christos uint32_t data, warndata;
616 1.6.2.2 christos
617 1.6.2.2 christos if (!rks->s_attached)
618 1.6.2.2 christos continue;
619 1.6.2.2 christos
620 1.6.2.2 christos data = rk_tsadc_temp_to_data(sc, rks->s_tshut);
621 1.6.2.2 christos warndata = rk_tsadc_temp_to_data(sc, rks->s_warn);
622 1.6.2.2 christos
623 1.6.2.2 christos DPRINTF("(%s:%s): tshut/data %d/%u warn/data %d/%u",
624 1.6.2.2 christos sc->sc_sme->sme_name, rks->s_data.desc,
625 1.6.2.2 christos rks->s_tshut, data,
626 1.6.2.2 christos rks->s_warn, warndata);
627 1.6.2.2 christos
628 1.6.2.2 christos if (data == sc->sc_data_mask) {
629 1.6.2.2 christos aprint_error_dev(sc->sc_dev,
630 1.6.2.2 christos "Failed converting critical temp %u.%06u to code",
631 1.6.2.2 christos rks->s_tshut / 1000000, rks->s_tshut % 1000000);
632 1.6.2.2 christos continue;
633 1.6.2.2 christos }
634 1.6.2.2 christos if (warndata == sc->sc_data_mask) {
635 1.6.2.2 christos aprint_error_dev(sc->sc_dev,
636 1.6.2.2 christos "Failed converting warn temp %u.%06u to code",
637 1.6.2.2 christos rks->s_warn / 1000000, rks->s_warn % 1000000);
638 1.6.2.2 christos continue;
639 1.6.2.2 christos }
640 1.6.2.2 christos
641 1.6.2.2 christos TSADC_WRITE(sc, rks->s_comp_tshut, data);
642 1.6.2.2 christos TSADC_WRITE(sc, rks->s_comp_int, warndata);
643 1.6.2.2 christos
644 1.6.2.2 christos val |= rks->s_comp_int_en;
645 1.6.2.2 christos }
646 1.6.2.2 christos TSADC_WRITE(sc, TSADC_AUTO_CON, val);
647 1.6.2.2 christos }
648 1.6.2.2 christos
649 1.6.2.2 christos static void
650 1.6.2.2 christos rk_tsadc_init_tshut(struct rk_tsadc_softc *sc, int mode, int polarity)
651 1.6.2.2 christos {
652 1.6.2.2 christos uint32_t val;
653 1.6.2.2 christos
654 1.6.2.2 christos /* Handle TSHUT temp setting. */
655 1.6.2.2 christos rk_tsadc_tshut_set(sc);
656 1.6.2.2 christos
657 1.6.2.2 christos /* Handle TSHUT mode setting. */
658 1.6.2.2 christos val = TSADC_READ(sc, TSADC_INT_EN);
659 1.6.2.2 christos if (mode == TSHUT_MODE_CPU) {
660 1.6.2.2 christos val |= TSADC_INT_EN_TSHUT_2CRU_EN_SRC1 |
661 1.6.2.2 christos TSADC_INT_EN_TSHUT_2CRU_EN_SRC0;
662 1.6.2.2 christos val &= ~(TSADC_INT_EN_TSHUT_2GPIO_EN_SRC1 |
663 1.6.2.2 christos TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0);
664 1.6.2.2 christos } else {
665 1.6.2.2 christos KASSERT(mode == TSHUT_MODE_GPIO);
666 1.6.2.2 christos val &= ~(TSADC_INT_EN_TSHUT_2CRU_EN_SRC1 |
667 1.6.2.2 christos TSADC_INT_EN_TSHUT_2CRU_EN_SRC0);
668 1.6.2.3 martin val |= TSADC_INT_EN_TSHUT_2GPIO_EN_SRC1 |
669 1.6.2.2 christos TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0;
670 1.6.2.2 christos }
671 1.6.2.2 christos TSADC_WRITE(sc, TSADC_INT_EN, val);
672 1.6.2.2 christos
673 1.6.2.2 christos /* Handle TSHUT polarity setting. */
674 1.6.2.2 christos val = TSADC_READ(sc, TSADC_AUTO_CON);
675 1.6.2.2 christos if (polarity == TSHUT_HIGH_ACTIVE)
676 1.6.2.2 christos val |= TSADC_AUTO_CON_TSHUT_POLARITY;
677 1.6.2.2 christos else
678 1.6.2.2 christos val &= ~TSADC_AUTO_CON_TSHUT_POLARITY;
679 1.6.2.2 christos TSADC_WRITE(sc, TSADC_AUTO_CON, val);
680 1.6.2.2 christos }
681 1.6.2.2 christos
682 1.6.2.2 christos static void
683 1.6.2.2 christos rk_tsadc_init_rk3328(struct rk_tsadc_softc *sc, int mode, int polarity)
684 1.6.2.2 christos {
685 1.6.2.2 christos
686 1.6.2.2 christos rk_tsadc_init_tshut(sc, mode, polarity);
687 1.6.2.2 christos rk_tsadc_init_counts(sc);
688 1.6.2.2 christos }
689 1.6.2.2 christos
690 1.6.2.2 christos static void
691 1.6.2.2 christos rk_tsadc_init_rk3399(struct rk_tsadc_softc *sc, int mode, int polarity)
692 1.6.2.2 christos {
693 1.6.2.2 christos
694 1.6.2.2 christos syscon_lock(sc->sc_syscon);
695 1.6.2.2 christos syscon_write_4(sc->sc_syscon, RK3399_GRF_TSADC_TESTBIT_L,
696 1.6.2.2 christos RK3399_GRF_TSADC_TESTBIT_VCM_EN_L);
697 1.6.2.2 christos syscon_write_4(sc->sc_syscon, RK3399_GRF_TSADC_TESTBIT_H,
698 1.6.2.2 christos RK3399_GRF_TSADC_TESTBIT_VCM_EN_H);
699 1.6.2.2 christos
700 1.6.2.2 christos DELAY(20);
701 1.6.2.2 christos syscon_write_4(sc->sc_syscon, RK3399_GRF_SARADC_TESTBIT,
702 1.6.2.2 christos RK3399_GRF_SARADC_TESTBIT_ON);
703 1.6.2.2 christos syscon_write_4(sc->sc_syscon, RK3399_GRF_TSADC_TESTBIT_H,
704 1.6.2.2 christos RK3399_GRF_TSADC_TESTBIT_H_ON);
705 1.6.2.2 christos DELAY(100);
706 1.6.2.2 christos syscon_unlock(sc->sc_syscon);
707 1.6.2.2 christos
708 1.6.2.2 christos rk_tsadc_init_counts(sc);
709 1.6.2.2 christos rk_tsadc_init_tshut(sc, mode, polarity);
710 1.6.2.2 christos }
711 1.6.2.2 christos
712 1.6.2.2 christos static void
713 1.6.2.2 christos rk_tsadc_init_enable(struct rk_tsadc_softc *sc)
714 1.6.2.2 christos {
715 1.6.2.2 christos uint32_t val;
716 1.6.2.2 christos
717 1.6.2.2 christos val = TSADC_READ(sc, TSADC_AUTO_CON);
718 1.6.2.2 christos val |= TSADC_AUTO_CON_AUTO_STATUS |
719 1.6.2.2 christos TSADC_AUTO_CON_SRC1_LT_EN | TSADC_AUTO_CON_SRC0_LT_EN;
720 1.6.2.2 christos TSADC_WRITE(sc, TSADC_AUTO_CON, val);
721 1.6.2.2 christos
722 1.6.2.2 christos /* Finally, register & enable the controller */
723 1.6.2.2 christos sysmon_envsys_register(sc->sc_sme);
724 1.6.2.2 christos
725 1.6.2.2 christos val = TSADC_READ(sc, TSADC_AUTO_CON);
726 1.6.2.2 christos val |= TSADC_AUTO_CON_AUTO_EN | TSADC_AUTO_CON_Q_SEL;
727 1.6.2.2 christos TSADC_WRITE(sc, TSADC_AUTO_CON, val);
728 1.6.2.2 christos }
729 1.6.2.2 christos
730 1.6.2.2 christos static void
731 1.6.2.2 christos rk_tsadc_init(struct rk_tsadc_softc *sc, int mode, int polarity)
732 1.6.2.2 christos {
733 1.6.2.2 christos
734 1.6.2.2 christos (*sc->sc_rd->rd_init)(sc, mode, polarity);
735 1.6.2.2 christos rk_tsadc_init_enable(sc);
736 1.6.2.2 christos }
737 1.6.2.2 christos
738 1.6.2.2 christos /* run time support */
739 1.6.2.2 christos
740 1.6.2.2 christos /* given edata, find the matching rk sensor structure */
741 1.6.2.2 christos static struct rk_tsadc_sensor *
742 1.6.2.2 christos rk_tsadc_edata_to_sensor(struct rk_tsadc_softc * const sc, envsys_data_t *edata)
743 1.6.2.2 christos {
744 1.6.2.2 christos
745 1.6.2.2 christos for (unsigned n = 0; n < sc->sc_rd->rd_num_sensors; n++) {
746 1.6.2.2 christos struct rk_tsadc_sensor *rks = &sc->sc_sensors[n];
747 1.6.2.2 christos
748 1.6.2.2 christos if (&rks->s_data == edata)
749 1.6.2.2 christos return rks;
750 1.6.2.2 christos }
751 1.6.2.2 christos return NULL;
752 1.6.2.2 christos }
753 1.6.2.2 christos
754 1.6.2.2 christos static void
755 1.6.2.2 christos rk_tsadc_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
756 1.6.2.2 christos {
757 1.6.2.2 christos struct rk_tsadc_softc * const sc = sme->sme_cookie;
758 1.6.2.2 christos struct rk_tsadc_sensor *rks = rk_tsadc_edata_to_sensor(sc, edata);
759 1.6.2.2 christos unsigned data;
760 1.6.2.2 christos int temp;
761 1.6.2.2 christos
762 1.6.2.2 christos if (rks == NULL)
763 1.6.2.2 christos return;
764 1.6.2.2 christos
765 1.6.2.2 christos data = TSADC_READ(sc, rks->s_data_reg) & sc->sc_data_mask;
766 1.6.2.2 christos temp = rk_tsadc_data_to_temp(sc, data);
767 1.6.2.2 christos
768 1.6.2.2 christos DPRINTF("(%s:%s): temp/data %d/%u",
769 1.6.2.2 christos sc->sc_sme->sme_name, rks->s_data.desc,
770 1.6.2.2 christos temp, data);
771 1.6.2.2 christos
772 1.6.2.2 christos if (temp == sc->sc_data_mask) {
773 1.6.2.2 christos edata->state = ENVSYS_SINVALID;
774 1.6.2.2 christos } else {
775 1.6.2.2 christos edata->value_cur = temp + TEMP_uC_TO_uK;
776 1.6.2.2 christos edata->state = ENVSYS_SVALID;
777 1.6.2.2 christos }
778 1.6.2.2 christos }
779 1.6.2.2 christos
780 1.6.2.2 christos static void
781 1.6.2.2 christos rk_tsadc_get_limits(struct sysmon_envsys *sme,
782 1.6.2.2 christos envsys_data_t *edata,
783 1.6.2.2 christos sysmon_envsys_lim_t *lim,
784 1.6.2.2 christos uint32_t *props)
785 1.6.2.2 christos {
786 1.6.2.2 christos struct rk_tsadc_softc *sc = sme->sme_cookie;
787 1.6.2.2 christos struct rk_tsadc_sensor *rks = rk_tsadc_edata_to_sensor(sc, edata);
788 1.6.2.2 christos
789 1.6.2.2 christos if (rks == NULL)
790 1.6.2.2 christos return;
791 1.6.2.2 christos
792 1.6.2.2 christos lim->sel_critmax = rks->s_tshut + TEMP_uC_TO_uK;
793 1.6.2.2 christos lim->sel_warnmax = rks->s_warn + TEMP_uC_TO_uK;
794 1.6.2.2 christos
795 1.6.2.2 christos *props = PROP_CRITMAX | PROP_WARNMAX;
796 1.6.2.2 christos }
797 1.6.2.2 christos
798 1.6.2.2 christos /* XXX do something with interrupts that don't happen yet. */
799 1.6.2.2 christos static int
800 1.6.2.2 christos rk_tsadc_intr(void *arg)
801 1.6.2.2 christos {
802 1.6.2.2 christos struct rk_tsadc_softc * const sc = arg;
803 1.6.2.2 christos uint32_t val;
804 1.6.2.2 christos
805 1.6.2.2 christos /* XXX */
806 1.6.2.2 christos DPRINTF("(%s): interrupted", sc->sc_sme->sme_name);
807 1.6.2.2 christos for (unsigned n = 0; n < __arraycount(rk_tsadc_sensors); n++) {
808 1.6.2.2 christos struct rk_tsadc_sensor *rks = &sc->sc_sensors[n];
809 1.6.2.2 christos
810 1.6.2.2 christos rk_tsadc_refresh(sc->sc_sme, (envsys_data_t *)rks);
811 1.6.2.2 christos }
812 1.6.2.2 christos
813 1.6.2.2 christos /* ack interrupt */
814 1.6.2.2 christos val = TSADC_READ(sc, TSADC_INT_PD);
815 1.6.2.2 christos TSADC_WRITE(sc, TSADC_INT_PD, val & ~TSADC_INT_PD_EOC_INT_PD);
816 1.6.2.2 christos
817 1.6.2.2 christos return 1;
818 1.6.2.2 christos }
819 1.6.2.2 christos
820 1.6.2.2 christos /*
821 1.6.2.2 christos * Convert TDASC data codes to temp and reverse. The manual only has codes
822 1.6.2.2 christos * and temperature values in 5 degC intervals, but says that interpolation
823 1.6.2.2 christos * can be done to achieve better resolution between these values, and that
824 1.6.2.2 christos * the spacing is linear.
825 1.6.2.2 christos */
826 1.6.2.2 christos static int
827 1.6.2.2 christos rk_tsadc_data_to_temp(struct rk_tsadc_softc *sc, uint32_t data)
828 1.6.2.2 christos {
829 1.6.2.2 christos unsigned i;
830 1.6.2.2 christos const rk_data *rd = sc->sc_rd;
831 1.6.2.2 christos
832 1.6.2.2 christos if (data > rd->rd_max || data < rd->rd_min) {
833 1.6.2.2 christos DPRINTF("data out of range (%u > %u || %u < %u)",
834 1.6.2.2 christos data, rd->rd_max, data, rd->rd_min);
835 1.6.2.2 christos return sc->sc_data_mask;
836 1.6.2.2 christos }
837 1.6.2.2 christos for (i = 1; i < rd->rd_size; i++) {
838 1.6.2.2 christos if (rd->rd_array[i].data >= data) {
839 1.6.2.2 christos int temprange, offset;
840 1.6.2.2 christos uint32_t datarange, datadiff;
841 1.6.2.2 christos unsigned first, secnd;
842 1.6.2.2 christos
843 1.6.2.2 christos if (rd->rd_array[i].data == data)
844 1.6.2.2 christos return rd->rd_array[i].temp;
845 1.6.2.2 christos
846 1.6.2.2 christos /* must interpolate */
847 1.6.2.2 christos if (rd->rd_decr) {
848 1.6.2.2 christos first = i;
849 1.6.2.2 christos secnd = i+1;
850 1.6.2.2 christos } else {
851 1.6.2.2 christos first = i;
852 1.6.2.2 christos secnd = i-1;
853 1.6.2.2 christos }
854 1.6.2.2 christos
855 1.6.2.2 christos temprange = rd->rd_array[first].temp -
856 1.6.2.2 christos rd->rd_array[secnd].temp;
857 1.6.2.2 christos datarange = rd->rd_array[first].data -
858 1.6.2.2 christos rd->rd_array[secnd].data;
859 1.6.2.2 christos datadiff = data - rd->rd_array[secnd].data;
860 1.6.2.2 christos
861 1.6.2.2 christos offset = (temprange * datadiff) / datarange;
862 1.6.2.2 christos return rd->rd_array[secnd].temp + offset;
863 1.6.2.2 christos }
864 1.6.2.2 christos }
865 1.6.2.2 christos panic("didn't find range");
866 1.6.2.2 christos }
867 1.6.2.2 christos
868 1.6.2.2 christos static uint32_t
869 1.6.2.2 christos rk_tsadc_temp_to_data(struct rk_tsadc_softc *sc, int temp)
870 1.6.2.2 christos {
871 1.6.2.2 christos unsigned i;
872 1.6.2.2 christos const rk_data *rd = sc->sc_rd;
873 1.6.2.2 christos
874 1.6.2.2 christos for (i = 1; i < rd->rd_size; i++) {
875 1.6.2.2 christos if (rd->rd_array[i].temp >= temp) {
876 1.6.2.2 christos int temprange, tempdiff;
877 1.6.2.2 christos uint32_t datarange, offset;
878 1.6.2.2 christos unsigned first, secnd;
879 1.6.2.2 christos
880 1.6.2.2 christos if (rd->rd_array[i].temp == temp)
881 1.6.2.2 christos return rd->rd_array[i].data;
882 1.6.2.2 christos
883 1.6.2.2 christos /* must interpolate */
884 1.6.2.2 christos if (rd->rd_decr) {
885 1.6.2.2 christos first = i;
886 1.6.2.2 christos secnd = i+1;
887 1.6.2.2 christos } else {
888 1.6.2.2 christos first = i;
889 1.6.2.2 christos secnd = i-1;
890 1.6.2.2 christos }
891 1.6.2.2 christos
892 1.6.2.2 christos datarange = rd->rd_array[first].data -
893 1.6.2.2 christos rd->rd_array[secnd].data;
894 1.6.2.2 christos temprange = rd->rd_array[first].temp -
895 1.6.2.2 christos rd->rd_array[secnd].temp;
896 1.6.2.2 christos tempdiff = temp - rd->rd_array[secnd].temp;
897 1.6.2.2 christos
898 1.6.2.2 christos offset = (datarange * tempdiff) / temprange;
899 1.6.2.2 christos return rd->rd_array[secnd].data + offset;
900 1.6.2.2 christos }
901 1.6.2.2 christos }
902 1.6.2.2 christos
903 1.6.2.2 christos return sc->sc_data_mask;
904 1.6.2.2 christos }
905