| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: rk_tsadc.c,v 1.4 2019/05/14 07:45:03 mrg Exp $ */ | | 1 | /* $NetBSD: rk_tsadc.c,v 1.5 2019/05/15 01:24:43 mrg Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2019 Matthew R. Green | | 4 | * Copyright (c) 2019 Matthew R. Green |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -20,54 +20,51 @@ | | | @@ -20,54 +20,51 @@ |
20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | | 22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
23 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | | 23 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | | 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
25 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | | 25 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
26 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 26 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
28 | * SUCH DAMAGE. | | 28 | * SUCH DAMAGE. |
29 | */ | | 29 | */ |
30 | | | 30 | |
31 | #include <sys/cdefs.h> | | 31 | #include <sys/cdefs.h> |
32 | | | 32 | |
33 | __KERNEL_RCSID(0, "$NetBSD: rk_tsadc.c,v 1.4 2019/05/14 07:45:03 mrg Exp $"); | | 33 | __KERNEL_RCSID(0, "$NetBSD: rk_tsadc.c,v 1.5 2019/05/15 01:24:43 mrg Exp $"); |
34 | | | 34 | |
35 | /* | | 35 | /* |
36 | * Driver for the TSADC temperature sensor monitor in RK3328 and RK3399. | | 36 | * Driver for the TSADC temperature sensor monitor in RK3328 and RK3399. |
37 | * | | 37 | * |
38 | * TODO: | | 38 | * TODO: |
39 | * - handle setting various temp values | | 39 | * - handle setting various temp values |
40 | * - handle DT trips/temp value defaults | | 40 | * - handle DT trips/temp value defaults |
41 | * - interrupts aren't triggered (test by lowering warn/crit values), and | | 41 | * - interrupts aren't triggered (test by lowering warn/crit values), and |
42 | * once they work, make the interrupt do something | | 42 | * once they work, make the interrupt do something |
43 | * - fix for RK3328, and port to other rockchips (will require moving some | | | |
44 | * part into per-chipset sections, such as code<->temp tables) | | | |
45 | */ | | 43 | */ |
46 | | | 44 | |
47 | #include <sys/param.h> | | 45 | #include <sys/param.h> |
48 | #include <sys/bus.h> | | 46 | #include <sys/bus.h> |
49 | #include <sys/device.h> | | 47 | #include <sys/device.h> |
50 | #include <sys/intr.h> | | 48 | #include <sys/intr.h> |
51 | #include <sys/systm.h> | | 49 | #include <sys/systm.h> |
52 | #include <sys/time.h> | | 50 | #include <sys/time.h> |
53 | #include <sys/kmem.h> | | 51 | #include <sys/kmem.h> |
54 | | | 52 | |
55 | #include <dev/fdt/fdtvar.h> | | 53 | #include <dev/fdt/fdtvar.h> |
56 | #include <dev/fdt/syscon.h> | | 54 | #include <dev/fdt/syscon.h> |
57 | | | 55 | |
58 | #include <dev/sysmon/sysmonvar.h> | | 56 | #include <dev/sysmon/sysmonvar.h> |
59 | | | 57 | |
60 | //#define RKTSADC_DEBUG | | | |
61 | #ifdef RKTSADC_DEBUG | | 58 | #ifdef RKTSADC_DEBUG |
62 | #define DPRINTF(fmt, ...) \ | | 59 | #define DPRINTF(fmt, ...) \ |
63 | printf("%s:%d: " fmt "\n", __func__, __LINE__, ## __VA_ARGS__) | | 60 | printf("%s:%d: " fmt "\n", __func__, __LINE__, ## __VA_ARGS__) |
64 | #else | | 61 | #else |
65 | #define DPRINTF(fmt, ...) | | 62 | #define DPRINTF(fmt, ...) |
66 | #endif | | 63 | #endif |
67 | | | 64 | |
68 | /* Register definitions */ | | 65 | /* Register definitions */ |
69 | #define TSADC_USER_CON 0x00 | | 66 | #define TSADC_USER_CON 0x00 |
70 | #define TSADC_USER_CON_ADC_STATUS __BIT(12) | | 67 | #define TSADC_USER_CON_ADC_STATUS __BIT(12) |
71 | #define TSADC_USER_CON_INTER_PD_SOC __BITS(11,6) | | 68 | #define TSADC_USER_CON_INTER_PD_SOC __BITS(11,6) |
72 | #define TSADC_USER_CON_START __BIT(5) | | 69 | #define TSADC_USER_CON_START __BIT(5) |
73 | #define TSADC_USER_CON_START_MODE __BIT(4) | | 70 | #define TSADC_USER_CON_START_MODE __BIT(4) |
| @@ -149,76 +146,77 @@ __KERNEL_RCSID(0, "$NetBSD: rk_tsadc.c,v | | | @@ -149,76 +146,77 @@ __KERNEL_RCSID(0, "$NetBSD: rk_tsadc.c,v |
149 | | | 146 | |
150 | #define TEMP_uC_TO_uK 273150000 | | 147 | #define TEMP_uC_TO_uK 273150000 |
151 | | | 148 | |
152 | #define TSHUT_MODE_CPU 0 | | 149 | #define TSHUT_MODE_CPU 0 |
153 | #define TSHUT_MODE_GPIO 1 | | 150 | #define TSHUT_MODE_GPIO 1 |
154 | | | 151 | |
155 | #define TSHUT_LOW_ACTIVE 0 | | 152 | #define TSHUT_LOW_ACTIVE 0 |
156 | #define TSHUT_HIGH_ACTIVE 1 | | 153 | #define TSHUT_HIGH_ACTIVE 1 |
157 | | | 154 | |
158 | #define TSHUT_DEF_TEMP 95000 | | 155 | #define TSHUT_DEF_TEMP 95000 |
159 | | | 156 | |
160 | #define TSADC_DATA_MAX 0xfff | | 157 | #define TSADC_DATA_MAX 0xfff |
161 | | | 158 | |
162 | #define NUM_SENSORS 2 | | 159 | #define MAX_SENSORS 2 |
163 | | | 160 | |
164 | typedef struct rk_data_array { | | 161 | typedef struct rk_data_array { |
165 | uint32_t data; /* register value */ | | 162 | uint32_t data; /* register value */ |
166 | int temp; /* micro-degC */ | | 163 | int temp; /* micro-degC */ |
167 | } rk_data_array; | | 164 | } rk_data_array; |
168 | | | 165 | |
169 | struct rk_tsadc_softc; | | 166 | struct rk_tsadc_softc; |
170 | typedef struct rk_data_table { | | 167 | typedef struct rk_data { |
171 | const rk_data_array *rdt_array; | | 168 | const rk_data_array *rd_array; |
172 | size_t rdt_size; | | 169 | size_t rd_size; |
173 | void (*rdt_init)(struct rk_tsadc_softc *, int, int); | | 170 | void (*rd_init)(struct rk_tsadc_softc *, int, int); |
174 | bool rdt_decr; /* lower values -> higher temp */ | | 171 | bool rd_decr; /* lower values -> higher temp */ |
175 | unsigned rdt_min, rdt_max; | | 172 | unsigned rd_min, rd_max; |
176 | unsigned rdt_auto_period; | | 173 | unsigned rd_auto_period; |
177 | } rk_data_table; | | 174 | unsigned rd_num_sensors; |
| | | 175 | } rk_data; |
178 | | | 176 | |
179 | /* Per-sensor data */ | | 177 | /* Per-sensor data */ |
180 | struct rk_tsadc_sensor { | | 178 | struct rk_tsadc_sensor { |
181 | envsys_data_t s_data; | | 179 | envsys_data_t s_data; |
182 | bool s_attached; | | 180 | bool s_attached; |
183 | /* TSADC register offsets for this sensor */ | | 181 | /* TSADC register offsets for this sensor */ |
184 | unsigned s_data_reg; | | 182 | unsigned s_data_reg; |
185 | unsigned s_comp_tshut; | | 183 | unsigned s_comp_tshut; |
186 | unsigned s_comp_int; | | 184 | unsigned s_comp_int; |
187 | /* enable bit in AUTO_CON register */ | | 185 | /* enable bit in AUTO_CON register */ |
188 | unsigned s_comp_int_en; | | 186 | unsigned s_comp_int_en; |
189 | /* warn/crit values in micro Kelvin */ | | 187 | /* warn/crit values in micro Kelvin */ |
190 | int s_warn; | | 188 | int s_warn; |
191 | int s_tshut; | | 189 | int s_tshut; |
192 | }; | | 190 | }; |
193 | | | 191 | |
194 | struct rk_tsadc_softc { | | 192 | struct rk_tsadc_softc { |
195 | device_t sc_dev; | | 193 | device_t sc_dev; |
196 | int sc_phandle; | | 194 | int sc_phandle; |
197 | bus_space_tag_t sc_bst; | | 195 | bus_space_tag_t sc_bst; |
198 | bus_space_handle_t sc_bsh; | | 196 | bus_space_handle_t sc_bsh; |
199 | size_t sc_size; | | 197 | size_t sc_size; |
200 | uint32_t sc_data_mask; | | 198 | uint32_t sc_data_mask; |
201 | void *sc_ih; | | 199 | void *sc_ih; |
202 | | | 200 | |
203 | struct sysmon_envsys *sc_sme; | | 201 | struct sysmon_envsys *sc_sme; |
204 | struct rk_tsadc_sensor sc_sensors[NUM_SENSORS]; | | 202 | struct rk_tsadc_sensor sc_sensors[MAX_SENSORS]; |
205 | | | 203 | |
206 | struct clk *sc_clock; | | 204 | struct clk *sc_clock; |
207 | struct clk *sc_clockapb; | | 205 | struct clk *sc_clockapb; |
208 | struct fdtbus_reset *sc_reset; | | 206 | struct fdtbus_reset *sc_reset; |
209 | struct syscon *sc_syscon; | | 207 | struct syscon *sc_syscon; |
210 | | | 208 | |
211 | const rk_data_table *sc_rdt; | | 209 | const rk_data *sc_rd; |
212 | }; | | 210 | }; |
213 | | | 211 | |
214 | static int rk_tsadc_match(device_t, cfdata_t, void *); | | 212 | static int rk_tsadc_match(device_t, cfdata_t, void *); |
215 | static void rk_tsadc_attach(device_t, device_t, void *); | | 213 | static void rk_tsadc_attach(device_t, device_t, void *); |
216 | static int rk_tsadc_detach(device_t, int); | | 214 | static int rk_tsadc_detach(device_t, int); |
217 | static int rk_tsadc_init_clocks(struct rk_tsadc_softc *); | | 215 | static int rk_tsadc_init_clocks(struct rk_tsadc_softc *); |
218 | static void rk_tsadc_init_counts(struct rk_tsadc_softc *); | | 216 | static void rk_tsadc_init_counts(struct rk_tsadc_softc *); |
219 | static void rk_tsadc_tshut_set(struct rk_tsadc_softc *s); | | 217 | static void rk_tsadc_tshut_set(struct rk_tsadc_softc *s); |
220 | static void rk_tsadc_init_tshut(struct rk_tsadc_softc *, int, int); | | 218 | static void rk_tsadc_init_tshut(struct rk_tsadc_softc *, int, int); |
221 | static void rk_tsadc_init_rk3328(struct rk_tsadc_softc *, int, int); | | 219 | static void rk_tsadc_init_rk3328(struct rk_tsadc_softc *, int, int); |
222 | static void rk_tsadc_init_rk3399(struct rk_tsadc_softc *, int, int); | | 220 | static void rk_tsadc_init_rk3399(struct rk_tsadc_softc *, int, int); |
223 | static void rk_tsadc_init_enable(struct rk_tsadc_softc *); | | 221 | static void rk_tsadc_init_enable(struct rk_tsadc_softc *); |
224 | static void rk_tsadc_init(struct rk_tsadc_softc *, int, int); | | 222 | static void rk_tsadc_init(struct rk_tsadc_softc *, int, int); |
| @@ -254,29 +252,35 @@ static const struct rk_tsadc_sensor rk_t | | | @@ -254,29 +252,35 @@ static const struct rk_tsadc_sensor rk_t |
254 | .s_warn = 75000000, | | 252 | .s_warn = 75000000, |
255 | .s_tshut = 95000000, | | 253 | .s_tshut = 95000000, |
256 | }, { | | 254 | }, { |
257 | .s_data = { .desc = "GPU" }, | | 255 | .s_data = { .desc = "GPU" }, |
258 | .s_data_reg = TSADC_DATA1, | | 256 | .s_data_reg = TSADC_DATA1, |
259 | .s_comp_tshut = TSADC_COMP1_SHUT, | | 257 | .s_comp_tshut = TSADC_COMP1_SHUT, |
260 | .s_comp_int = TSADC_COMP1_INT, | | 258 | .s_comp_int = TSADC_COMP1_INT, |
261 | .s_comp_int_en = TSADC_AUTO_CON_SRC1_EN, | | 259 | .s_comp_int_en = TSADC_AUTO_CON_SRC1_EN, |
262 | .s_warn = 75000000, | | 260 | .s_warn = 75000000, |
263 | .s_tshut = 95000000, | | 261 | .s_tshut = 95000000, |
264 | }, | | 262 | }, |
265 | }; | | 263 | }; |
266 | | | 264 | |
267 | /* Table from RK3328 manual */ | | 265 | /* |
| | | 266 | * Table from RK3328 manual. Note that the manual lists valid numbers as |
| | | 267 | * 4096 - number. This also means it is increasing not decreasing for |
| | | 268 | * higher temps, and the min and max are also offset from 4096. |
| | | 269 | */ |
| | | 270 | #define RK3328_DATA_OFFSET (4096) |
268 | static const rk_data_array rk3328_data_array[] = { | | 271 | static const rk_data_array rk3328_data_array[] = { |
269 | #define ENTRY(d,C) { .data = (d), .temp = (C) * 1000 * 1000, } | | 272 | #define ENTRY(d,C) \ |
| | | 273 | { .data = RK3328_DATA_OFFSET - (d), .temp = (C) * 1000 * 1000, } |
270 | ENTRY(TSADC_DATA_MAX, -40), | | 274 | ENTRY(TSADC_DATA_MAX, -40), |
271 | ENTRY(3800, -40), | | 275 | ENTRY(3800, -40), |
272 | ENTRY(3792, -35), | | 276 | ENTRY(3792, -35), |
273 | ENTRY(3783, -30), | | 277 | ENTRY(3783, -30), |
274 | ENTRY(3774, -25), | | 278 | ENTRY(3774, -25), |
275 | ENTRY(3765, -20), | | 279 | ENTRY(3765, -20), |
276 | ENTRY(3756, -15), | | 280 | ENTRY(3756, -15), |
277 | ENTRY(3747, -10), | | 281 | ENTRY(3747, -10), |
278 | ENTRY(3737, -5), | | 282 | ENTRY(3737, -5), |
279 | ENTRY(3728, 0), | | 283 | ENTRY(3728, 0), |
280 | ENTRY(3718, 5), | | 284 | ENTRY(3718, 5), |
281 | ENTRY(3708, 10), | | 285 | ENTRY(3708, 10), |
282 | ENTRY(3698, 15), | | 286 | ENTRY(3698, 15), |
| @@ -338,54 +342,50 @@ static const rk_data_array rk3399_data_a | | | @@ -338,54 +342,50 @@ static const rk_data_array rk3399_data_a |
338 | ENTRY(616, 85), | | 342 | ENTRY(616, 85), |
339 | ENTRY(624, 90), | | 343 | ENTRY(624, 90), |
340 | ENTRY(633, 95), | | 344 | ENTRY(633, 95), |
341 | ENTRY(642, 100), | | 345 | ENTRY(642, 100), |
342 | ENTRY(650, 105), | | 346 | ENTRY(650, 105), |
343 | ENTRY(659, 110), | | 347 | ENTRY(659, 110), |
344 | ENTRY(668, 115), | | 348 | ENTRY(668, 115), |
345 | ENTRY(677, 120), | | 349 | ENTRY(677, 120), |
346 | ENTRY(685, 125), | | 350 | ENTRY(685, 125), |
347 | ENTRY(TSADC_DATA_MAX, 125), | | 351 | ENTRY(TSADC_DATA_MAX, 125), |
348 | #undef ENTRY | | 352 | #undef ENTRY |
349 | }; | | 353 | }; |
350 | | | 354 | |
351 | static const rk_data_table rk3328_data_table = { | | 355 | static const rk_data rk3328_data_table = { |
352 | .rdt_array = rk3328_data_array, | | 356 | .rd_array = rk3328_data_array, |
353 | .rdt_size = __arraycount(rk3328_data_array), | | 357 | .rd_size = __arraycount(rk3328_data_array), |
354 | .rdt_init = rk_tsadc_init_rk3328, | | 358 | .rd_init = rk_tsadc_init_rk3328, |
355 | .rdt_decr = true, | | 359 | .rd_decr = false, |
356 | .rdt_max = 3801, | | 360 | .rd_max = RK3328_DATA_OFFSET - 3420, |
357 | .rdt_min = 3420, | | 361 | .rd_min = RK3328_DATA_OFFSET - 3801, |
358 | .rdt_auto_period = RK3328_TSADC_AUTO_PERIOD_TIME, | | 362 | .rd_auto_period = RK3328_TSADC_AUTO_PERIOD_TIME, |
| | | 363 | .rd_num_sensors = 1, |
359 | }; | | 364 | }; |
360 | | | 365 | |
361 | static const rk_data_table rk3399_data_table = { | | 366 | static const rk_data rk3399_data_table = { |
362 | .rdt_array = rk3399_data_array, | | 367 | .rd_array = rk3399_data_array, |
363 | .rdt_size = __arraycount(rk3399_data_array), | | 368 | .rd_size = __arraycount(rk3399_data_array), |
364 | .rdt_init = rk_tsadc_init_rk3399, | | 369 | .rd_init = rk_tsadc_init_rk3399, |
365 | .rdt_decr = false, | | 370 | .rd_decr = false, |
366 | .rdt_max = 686, | | 371 | .rd_max = 686, |
367 | .rdt_min = 401, | | 372 | .rd_min = 401, |
368 | .rdt_auto_period = RK3399_TSADC_AUTO_PERIOD_TIME, | | 373 | .rd_auto_period = RK3399_TSADC_AUTO_PERIOD_TIME, |
| | | 374 | .rd_num_sensors = 2, |
369 | }; | | 375 | }; |
370 | | | 376 | |
371 | static const char * const compatible_rk3328[] = { | | 377 | static const char * const compatible_rk3328[] = { |
372 | #if 0 | | | |
373 | /* | | | |
374 | * does not yet report sane values. should be between 3421 and 3800, | | | |
375 | * but CPU tends to report < 1000 and the GPU reports 600-1600. | | | |
376 | */ | | | |
377 | "rockchip,rk3328-tsadc", | | 378 | "rockchip,rk3328-tsadc", |
378 | #endif | | | |
379 | NULL | | 379 | NULL |
380 | }; | | 380 | }; |
381 | | | 381 | |
382 | static const char * const compatible_rk3399[] = { | | 382 | static const char * const compatible_rk3399[] = { |
383 | "rockchip,rk3399-tsadc", | | 383 | "rockchip,rk3399-tsadc", |
384 | NULL | | 384 | NULL |
385 | }; | | 385 | }; |
386 | | | 386 | |
387 | #define TSADC_READ(sc, reg) \ | | 387 | #define TSADC_READ(sc, reg) \ |
388 | bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) | | 388 | bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) |
389 | #define TSADC_WRITE(sc, reg, val) \ | | 389 | #define TSADC_WRITE(sc, reg, val) \ |
390 | bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) | | 390 | bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) |
391 | | | 391 | |
| @@ -420,52 +420,59 @@ rk_tsadc_attach(device_t parent, device_ | | | @@ -420,52 +420,59 @@ rk_tsadc_attach(device_t parent, device_ |
420 | aprint_naive("\n"); | | 420 | aprint_naive("\n"); |
421 | aprint_normal(": RK3328/3399 Temperature Sensor ADC\n"); | | 421 | aprint_normal(": RK3328/3399 Temperature Sensor ADC\n"); |
422 | | | 422 | |
423 | sc->sc_sme = sysmon_envsys_create(); | | 423 | sc->sc_sme = sysmon_envsys_create(); |
424 | | | 424 | |
425 | sc->sc_sme->sme_name = device_xname(self); | | 425 | sc->sc_sme->sme_name = device_xname(self); |
426 | sc->sc_sme->sme_cookie = sc; | | 426 | sc->sc_sme->sme_cookie = sc; |
427 | sc->sc_sme->sme_refresh = rk_tsadc_refresh; | | 427 | sc->sc_sme->sme_refresh = rk_tsadc_refresh; |
428 | sc->sc_sme->sme_get_limits = rk_tsadc_get_limits; | | 428 | sc->sc_sme->sme_get_limits = rk_tsadc_get_limits; |
429 | sc->sc_data_mask = TSADC_DATA_MAX; | | 429 | sc->sc_data_mask = TSADC_DATA_MAX; |
430 | | | 430 | |
431 | pmf_device_register(self, NULL, NULL); | | 431 | pmf_device_register(self, NULL, NULL); |
432 | | | 432 | |
| | | 433 | if (of_match_compatible(faa->faa_phandle, compatible_rk3328)) { |
| | | 434 | sc->sc_rd = &rk3328_data_table; |
| | | 435 | } else { |
| | | 436 | KASSERT(of_match_compatible(faa->faa_phandle, compatible_rk3399)); |
| | | 437 | sc->sc_rd = &rk3399_data_table; |
| | | 438 | } |
| | | 439 | |
433 | /* Default to tshut via gpio and tshut low is active */ | | 440 | /* Default to tshut via gpio and tshut low is active */ |
434 | if (of_getprop_uint32(phandle, "rockchip,hw-tshut-mode", | | 441 | if (of_getprop_uint32(phandle, "rockchip,hw-tshut-mode", |
435 | &mode) != 0) { | | 442 | &mode) != 0) { |
436 | aprint_error(": could not get TSHUT mode, default to GPIO"); | | 443 | aprint_error(": could not get TSHUT mode, default to GPIO"); |
437 | mode = TSHUT_MODE_GPIO; | | 444 | mode = TSHUT_MODE_GPIO; |
438 | } | | 445 | } |
439 | if (mode != TSHUT_MODE_CPU && mode != TSHUT_MODE_GPIO) { | | 446 | if (mode != TSHUT_MODE_CPU && mode != TSHUT_MODE_GPIO) { |
440 | aprint_error(": TSHUT mode should be 0 or 1\n"); | | 447 | aprint_error(": TSHUT mode should be 0 or 1\n"); |
441 | goto fail; | | 448 | goto fail; |
442 | } | | 449 | } |
443 | | | 450 | |
444 | if (of_getprop_uint32(phandle, "rockchip,hw-tshut-polarity", | | 451 | if (of_getprop_uint32(phandle, "rockchip,hw-tshut-polarity", |
445 | &polarity) != 0) { | | 452 | &polarity) != 0) { |
446 | aprint_error(": could not get TSHUT polarity, default to low"); | | 453 | aprint_error(": could not get TSHUT polarity, default to low"); |
447 | polarity = TSHUT_LOW_ACTIVE; | | 454 | polarity = TSHUT_LOW_ACTIVE; |
448 | } | | 455 | } |
449 | if (of_getprop_uint32(phandle, | | 456 | if (of_getprop_uint32(phandle, |
450 | "rockchip,hw-tshut-temp", &tshut_temp) != 0) { | | 457 | "rockchip,hw-tshut-temp", &tshut_temp) != 0) { |
451 | aprint_error(": could not get TSHUT temperature, default to %u", | | 458 | aprint_error(": could not get TSHUT temperature, default to %u", |
452 | TSHUT_DEF_TEMP); | | 459 | TSHUT_DEF_TEMP); |
453 | tshut_temp = TSHUT_DEF_TEMP; | | 460 | tshut_temp = TSHUT_DEF_TEMP; |
454 | } | | 461 | } |
455 | tshut_temp *= 1000; /* convert fdt ms -> us */ | | 462 | tshut_temp *= 1000; /* convert fdt ms -> us */ |
456 | | | 463 | |
457 | memcpy(sc->sc_sensors, rk_tsadc_sensors, sizeof(sc->sc_sensors)); | | 464 | memcpy(sc->sc_sensors, rk_tsadc_sensors, sizeof(sc->sc_sensors)); |
458 | for (unsigned n = 0; n < NUM_SENSORS; n++) { | | 465 | for (unsigned n = 0; n < sc->sc_rd->rd_num_sensors; n++) { |
459 | struct rk_tsadc_sensor *rks = &sc->sc_sensors[n]; | | 466 | struct rk_tsadc_sensor *rks = &sc->sc_sensors[n]; |
460 | | | 467 | |
461 | rks->s_data.flags = ENVSYS_FMONLIMITS; | | 468 | rks->s_data.flags = ENVSYS_FMONLIMITS; |
462 | rks->s_data.units = ENVSYS_STEMP; | | 469 | rks->s_data.units = ENVSYS_STEMP; |
463 | rks->s_data.state = ENVSYS_SINVALID; | | 470 | rks->s_data.state = ENVSYS_SINVALID; |
464 | | | 471 | |
465 | if (sysmon_envsys_sensor_attach(sc->sc_sme, &rks->s_data)) | | 472 | if (sysmon_envsys_sensor_attach(sc->sc_sme, &rks->s_data)) |
466 | goto fail; | | 473 | goto fail; |
467 | rks->s_attached = true; | | 474 | rks->s_attached = true; |
468 | rks->s_tshut = tshut_temp; | | 475 | rks->s_tshut = tshut_temp; |
469 | #if 0 | | 476 | #if 0 |
470 | // testing | | 477 | // testing |
471 | rks->s_tshut = 68000000; | | 478 | rks->s_tshut = 68000000; |
| @@ -498,55 +505,48 @@ rk_tsadc_attach(device_t parent, device_ | | | @@ -498,55 +505,48 @@ rk_tsadc_attach(device_t parent, device_ |
498 | rk_tsadc_intr, sc); | | 505 | rk_tsadc_intr, sc); |
499 | if (sc->sc_ih == NULL) { | | 506 | if (sc->sc_ih == NULL) { |
500 | aprint_error_dev(self, "couldn't establish interrupt on %s\n", | | 507 | aprint_error_dev(self, "couldn't establish interrupt on %s\n", |
501 | intrstr); | | 508 | intrstr); |
502 | goto fail; | | 509 | goto fail; |
503 | } | | 510 | } |
504 | aprint_normal_dev(self, "interrupting on %s\n", intrstr); | | 511 | aprint_normal_dev(self, "interrupting on %s\n", intrstr); |
505 | | | 512 | |
506 | if (rk_tsadc_init_clocks(sc)) { | | 513 | if (rk_tsadc_init_clocks(sc)) { |
507 | aprint_error(": couldn't enable clocks\n"); | | 514 | aprint_error(": couldn't enable clocks\n"); |
508 | return; | | 515 | return; |
509 | } | | 516 | } |
510 | | | 517 | |
511 | if (of_match_compatible(faa->faa_phandle, compatible_rk3328)) { | | | |
512 | sc->sc_rdt = &rk3328_data_table; | | | |
513 | } else { | | | |
514 | KASSERT(of_match_compatible(faa->faa_phandle, compatible_rk3399)); | | | |
515 | sc->sc_rdt = &rk3399_data_table; | | | |
516 | } | | | |
517 | | | | |
518 | /* | | 518 | /* |
519 | * Manual says to setup auto period (both), high temp (interrupt), | | 519 | * Manual says to setup auto period (both), high temp (interrupt), |
520 | * high temp (shutdown), enable high temp resets (TSHUT to GPIO | | 520 | * high temp (shutdown), enable high temp resets (TSHUT to GPIO |
521 | * or reset chip), set the debounce times, and, finally, enable the | | 521 | * or reset chip), set the debounce times, and, finally, enable the |
522 | * controller iself. | | 522 | * controller iself. |
523 | */ | | 523 | */ |
524 | rk_tsadc_init(sc, mode, polarity); | | 524 | rk_tsadc_init(sc, mode, polarity); |
525 | | | 525 | |
526 | return; | | 526 | return; |
527 | | | 527 | |
528 | fail: | | 528 | fail: |
529 | rk_tsadc_detach(self, 0); | | 529 | rk_tsadc_detach(self, 0); |
530 | } | | 530 | } |
531 | | | 531 | |
532 | static int | | 532 | static int |
533 | rk_tsadc_detach(device_t self, int flags) | | 533 | rk_tsadc_detach(device_t self, int flags) |
534 | { | | 534 | { |
535 | struct rk_tsadc_softc *sc = device_private(self); | | 535 | struct rk_tsadc_softc *sc = device_private(self); |
536 | | | 536 | |
537 | pmf_device_deregister(self); | | 537 | pmf_device_deregister(self); |
538 | | | 538 | |
539 | for (unsigned n = 0; n < NUM_SENSORS; n++) { | | 539 | for (unsigned n = 0; n < sc->sc_rd->rd_num_sensors; n++) { |
540 | struct rk_tsadc_sensor *rks = &sc->sc_sensors[n]; | | 540 | struct rk_tsadc_sensor *rks = &sc->sc_sensors[n]; |
541 | | | 541 | |
542 | if (rks->s_attached) { | | 542 | if (rks->s_attached) { |
543 | sysmon_envsys_sensor_detach(sc->sc_sme, &rks->s_data); | | 543 | sysmon_envsys_sensor_detach(sc->sc_sme, &rks->s_data); |
544 | rks->s_attached = false; | | 544 | rks->s_attached = false; |
545 | } | | 545 | } |
546 | } | | 546 | } |
547 | | | 547 | |
548 | sysmon_envsys_unregister(sc->sc_sme); | | 548 | sysmon_envsys_unregister(sc->sc_sme); |
549 | | | 549 | |
550 | if (sc->sc_clockapb) | | 550 | if (sc->sc_clockapb) |
551 | clk_disable(sc->sc_clockapb); | | 551 | clk_disable(sc->sc_clockapb); |
552 | if (sc->sc_clock) | | 552 | if (sc->sc_clock) |
| @@ -588,42 +588,47 @@ rk_tsadc_init_clocks(struct rk_tsadc_sof | | | @@ -588,42 +588,47 @@ rk_tsadc_init_clocks(struct rk_tsadc_sof |
588 | | | 588 | |
589 | error = clk_enable(sc->sc_clockapb); | | 589 | error = clk_enable(sc->sc_clockapb); |
590 | | | 590 | |
591 | DELAY(20); | | 591 | DELAY(20); |
592 | fdtbus_reset_deassert(sc->sc_reset); | | 592 | fdtbus_reset_deassert(sc->sc_reset); |
593 | | | 593 | |
594 | return error; | | 594 | return error; |
595 | } | | 595 | } |
596 | | | 596 | |
597 | static void | | 597 | static void |
598 | rk_tsadc_init_counts(struct rk_tsadc_softc *sc) | | 598 | rk_tsadc_init_counts(struct rk_tsadc_softc *sc) |
599 | { | | 599 | { |
600 | | | 600 | |
601 | TSADC_WRITE(sc, TSADC_AUTO_PERIOD, sc->sc_rdt->rdt_auto_period); | | 601 | TSADC_WRITE(sc, TSADC_AUTO_PERIOD, sc->sc_rd->rd_auto_period); |
602 | TSADC_WRITE(sc, TSADC_AUTO_PERIOD_HT, sc->sc_rdt->rdt_auto_period); | | 602 | TSADC_WRITE(sc, TSADC_AUTO_PERIOD_HT, sc->sc_rd->rd_auto_period); |
603 | TSADC_WRITE(sc, TSADC_HIGH_INT_DEBOUNCE, TSADC_HT_DEBOUNCE_COUNT); | | 603 | TSADC_WRITE(sc, TSADC_HIGH_INT_DEBOUNCE, TSADC_HT_DEBOUNCE_COUNT); |
604 | TSADC_WRITE(sc, TSADC_HIGH_TSHUT_DEBOUNCE, TSADC_HT_DEBOUNCE_COUNT); | | 604 | TSADC_WRITE(sc, TSADC_HIGH_TSHUT_DEBOUNCE, TSADC_HT_DEBOUNCE_COUNT); |
605 | } | | 605 | } |
606 | | | 606 | |
607 | /* Configure the hardware with the tshut setup. */ | | 607 | /* Configure the hardware with the tshut setup. */ |
608 | static void | | 608 | static void |
609 | rk_tsadc_tshut_set(struct rk_tsadc_softc *sc) | | 609 | rk_tsadc_tshut_set(struct rk_tsadc_softc *sc) |
610 | { | | 610 | { |
611 | uint32_t val = TSADC_READ(sc, TSADC_AUTO_CON); | | 611 | uint32_t val = TSADC_READ(sc, TSADC_AUTO_CON); |
612 | | | 612 | |
613 | for (unsigned n = 0; n < NUM_SENSORS; n++) { | | 613 | for (unsigned n = 0; n < sc->sc_rd->rd_num_sensors; n++) { |
614 | struct rk_tsadc_sensor *rks = &sc->sc_sensors[n]; | | 614 | struct rk_tsadc_sensor *rks = &sc->sc_sensors[n]; |
615 | uint32_t data = rk_tsadc_temp_to_data(sc, rks->s_tshut); | | 615 | uint32_t data, warndata; |
616 | uint32_t warndata = rk_tsadc_temp_to_data(sc, rks->s_warn); | | 616 | |
| | | 617 | if (!rks->s_attached) |
| | | 618 | continue; |
| | | 619 | |
| | | 620 | data = rk_tsadc_temp_to_data(sc, rks->s_tshut); |
| | | 621 | warndata = rk_tsadc_temp_to_data(sc, rks->s_warn); |
617 | | | 622 | |
618 | DPRINTF("(%s:%s): tshut/data %d/%u warn/data %d/%u", | | 623 | DPRINTF("(%s:%s): tshut/data %d/%u warn/data %d/%u", |
619 | sc->sc_sme->sme_name, rks->s_data.desc, | | 624 | sc->sc_sme->sme_name, rks->s_data.desc, |
620 | rks->s_tshut, data, | | 625 | rks->s_tshut, data, |
621 | rks->s_warn, warndata); | | 626 | rks->s_warn, warndata); |
622 | | | 627 | |
623 | if (data == sc->sc_data_mask) { | | 628 | if (data == sc->sc_data_mask) { |
624 | aprint_error_dev(sc->sc_dev, | | 629 | aprint_error_dev(sc->sc_dev, |
625 | "Failed converting critical temp %u.%06u to code", | | 630 | "Failed converting critical temp %u.%06u to code", |
626 | rks->s_tshut / 1000000, rks->s_tshut % 1000000); | | 631 | rks->s_tshut / 1000000, rks->s_tshut % 1000000); |
627 | continue; | | 632 | continue; |
628 | } | | 633 | } |
629 | if (warndata == sc->sc_data_mask) { | | 634 | if (warndata == sc->sc_data_mask) { |
| @@ -716,37 +721,38 @@ rk_tsadc_init_enable(struct rk_tsadc_sof | | | @@ -716,37 +721,38 @@ rk_tsadc_init_enable(struct rk_tsadc_sof |
716 | | | 721 | |
717 | /* Finally, register & enable the controller */ | | 722 | /* Finally, register & enable the controller */ |
718 | sysmon_envsys_register(sc->sc_sme); | | 723 | sysmon_envsys_register(sc->sc_sme); |
719 | | | 724 | |
720 | val = TSADC_READ(sc, TSADC_AUTO_CON); | | 725 | val = TSADC_READ(sc, TSADC_AUTO_CON); |
721 | val |= TSADC_AUTO_CON_AUTO_EN | TSADC_AUTO_CON_Q_SEL; | | 726 | val |= TSADC_AUTO_CON_AUTO_EN | TSADC_AUTO_CON_Q_SEL; |
722 | TSADC_WRITE(sc, TSADC_AUTO_CON, val); | | 727 | TSADC_WRITE(sc, TSADC_AUTO_CON, val); |
723 | } | | 728 | } |
724 | | | 729 | |
725 | static void | | 730 | static void |
726 | rk_tsadc_init(struct rk_tsadc_softc *sc, int mode, int polarity) | | 731 | rk_tsadc_init(struct rk_tsadc_softc *sc, int mode, int polarity) |
727 | { | | 732 | { |
728 | | | 733 | |
729 | (*sc->sc_rdt->rdt_init)(sc, mode, polarity); | | 734 | (*sc->sc_rd->rd_init)(sc, mode, polarity); |
730 | rk_tsadc_init_enable(sc); | | 735 | rk_tsadc_init_enable(sc); |
731 | } | | 736 | } |
732 | | | 737 | |
733 | /* run time support */ | | 738 | /* run time support */ |
734 | | | 739 | |
| | | 740 | /* given edata, find the matching rk sensor structure */ |
735 | static struct rk_tsadc_sensor * | | 741 | static struct rk_tsadc_sensor * |
736 | rk_tsadc_edata_to_sensor(struct rk_tsadc_softc * const sc, envsys_data_t *edata) | | 742 | rk_tsadc_edata_to_sensor(struct rk_tsadc_softc * const sc, envsys_data_t *edata) |
737 | { | | 743 | { |
738 | | | 744 | |
739 | for (unsigned n = 0; n < NUM_SENSORS; n++) { | | 745 | for (unsigned n = 0; n < sc->sc_rd->rd_num_sensors; n++) { |
740 | struct rk_tsadc_sensor *rks = &sc->sc_sensors[n]; | | 746 | struct rk_tsadc_sensor *rks = &sc->sc_sensors[n]; |
741 | | | 747 | |
742 | if (&rks->s_data == edata) | | 748 | if (&rks->s_data == edata) |
743 | return rks; | | 749 | return rks; |
744 | } | | 750 | } |
745 | return NULL; | | 751 | return NULL; |
746 | } | | 752 | } |
747 | | | 753 | |
748 | static void | | 754 | static void |
749 | rk_tsadc_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) | | 755 | rk_tsadc_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) |
750 | { | | 756 | { |
751 | struct rk_tsadc_softc * const sc = sme->sme_cookie; | | 757 | struct rk_tsadc_softc * const sc = sme->sme_cookie; |
752 | struct rk_tsadc_sensor *rks = rk_tsadc_edata_to_sensor(sc, edata); | | 758 | struct rk_tsadc_sensor *rks = rk_tsadc_edata_to_sensor(sc, edata); |
| @@ -811,87 +817,88 @@ rk_tsadc_intr(void *arg) | | | @@ -811,87 +817,88 @@ rk_tsadc_intr(void *arg) |
811 | return 1; | | 817 | return 1; |
812 | } | | 818 | } |
813 | | | 819 | |
814 | /* | | 820 | /* |
815 | * Convert TDASC data codes to temp and reverse. The manual only has codes | | 821 | * Convert TDASC data codes to temp and reverse. The manual only has codes |
816 | * and temperature values in 5 degC intervals, but says that interpolation | | 822 | * and temperature values in 5 degC intervals, but says that interpolation |
817 | * can be done to achieve better resolution between these values, and that | | 823 | * can be done to achieve better resolution between these values, and that |
818 | * the spacing is linear. | | 824 | * the spacing is linear. |
819 | */ | | 825 | */ |
820 | static int | | 826 | static int |
821 | rk_tsadc_data_to_temp(struct rk_tsadc_softc *sc, uint32_t data) | | 827 | rk_tsadc_data_to_temp(struct rk_tsadc_softc *sc, uint32_t data) |
822 | { | | 828 | { |
823 | unsigned i; | | 829 | unsigned i; |
824 | const rk_data_table *rdt = sc->sc_rdt; | | 830 | const rk_data *rd = sc->sc_rd; |
825 | | | 831 | |
826 | if (data > rdt->rdt_max || data < rdt->rdt_min) { | | 832 | if (data > rd->rd_max || data < rd->rd_min) { |
827 | DPRINTF("data out of range (%u > %u || %u < %u)", data, rdt->rdt_max, data, rdt->rdt_min); | | 833 | DPRINTF("data out of range (%u > %u || %u < %u)", |
| | | 834 | data, rd->rd_max, data, rd->rd_min); |
828 | return sc->sc_data_mask; | | 835 | return sc->sc_data_mask; |
829 | } | | 836 | } |
830 | for (i = 1; i < rdt->rdt_size; i++) { | | 837 | for (i = 1; i < rd->rd_size; i++) { |
831 | if (rdt->rdt_array[i].data >= data) { | | 838 | if (rd->rd_array[i].data >= data) { |
832 | int temprange, offset; | | 839 | int temprange, offset; |
833 | uint32_t datarange, datadiff; | | 840 | uint32_t datarange, datadiff; |
834 | unsigned first, secnd; | | 841 | unsigned first, secnd; |
835 | | | 842 | |
836 | if (rdt->rdt_array[i].data == data) | | 843 | if (rd->rd_array[i].data == data) |
837 | return rdt->rdt_array[i].temp; | | 844 | return rd->rd_array[i].temp; |
838 | | | 845 | |
839 | /* must interpolate */ | | 846 | /* must interpolate */ |
840 | if (rdt->rdt_decr) { | | 847 | if (rd->rd_decr) { |
841 | first = i; | | 848 | first = i; |
842 | secnd = i+1; | | 849 | secnd = i+1; |
843 | } else { | | 850 | } else { |
844 | first = i; | | 851 | first = i; |
845 | secnd = i-1; | | 852 | secnd = i-1; |
846 | } | | 853 | } |
847 | | | 854 | |
848 | temprange = rdt->rdt_array[first].temp - | | 855 | temprange = rd->rd_array[first].temp - |
849 | rdt->rdt_array[secnd].temp; | | 856 | rd->rd_array[secnd].temp; |
850 | datarange = rdt->rdt_array[first].data - | | 857 | datarange = rd->rd_array[first].data - |
851 | rdt->rdt_array[secnd].data; | | 858 | rd->rd_array[secnd].data; |
852 | datadiff = data - rdt->rdt_array[secnd].data; | | 859 | datadiff = data - rd->rd_array[secnd].data; |
853 | | | 860 | |
854 | offset = (temprange * datadiff) / datarange; | | 861 | offset = (temprange * datadiff) / datarange; |
855 | return rdt->rdt_array[secnd].temp + offset; | | 862 | return rd->rd_array[secnd].temp + offset; |
856 | } | | 863 | } |
857 | } | | 864 | } |
858 | panic("didn't find range"); | | 865 | panic("didn't find range"); |
859 | } | | 866 | } |
860 | | | 867 | |
861 | static uint32_t | | 868 | static uint32_t |
862 | rk_tsadc_temp_to_data(struct rk_tsadc_softc *sc, int temp) | | 869 | rk_tsadc_temp_to_data(struct rk_tsadc_softc *sc, int temp) |
863 | { | | 870 | { |
864 | unsigned i; | | 871 | unsigned i; |
865 | const rk_data_table *rdt = sc->sc_rdt; | | 872 | const rk_data *rd = sc->sc_rd; |
866 | | | 873 | |
867 | for (i = 1; i < rdt->rdt_size; i++) { | | 874 | for (i = 1; i < rd->rd_size; i++) { |
868 | if (rdt->rdt_array[i].temp >= temp) { | | 875 | if (rd->rd_array[i].temp >= temp) { |
869 | int temprange, tempdiff; | | 876 | int temprange, tempdiff; |
870 | uint32_t datarange, offset; | | 877 | uint32_t datarange, offset; |
871 | unsigned first, secnd; | | 878 | unsigned first, secnd; |
872 | | | 879 | |
873 | if (rdt->rdt_array[i].temp == temp) | | 880 | if (rd->rd_array[i].temp == temp) |
874 | return rdt->rdt_array[i].data; | | 881 | return rd->rd_array[i].data; |
875 | | | 882 | |
876 | /* must interpolate */ | | 883 | /* must interpolate */ |
877 | if (rdt->rdt_decr) { | | 884 | if (rd->rd_decr) { |
878 | first = i; | | 885 | first = i; |
879 | secnd = i+1; | | 886 | secnd = i+1; |
880 | } else { | | 887 | } else { |
881 | first = i; | | 888 | first = i; |
882 | secnd = i-1; | | 889 | secnd = i-1; |
883 | } | | 890 | } |
884 | | | 891 | |
885 | datarange = rdt->rdt_array[first].data - | | 892 | datarange = rd->rd_array[first].data - |
886 | rdt->rdt_array[secnd].data; | | 893 | rd->rd_array[secnd].data; |
887 | temprange = rdt->rdt_array[first].temp - | | 894 | temprange = rd->rd_array[first].temp - |
888 | rdt->rdt_array[secnd].temp; | | 895 | rd->rd_array[secnd].temp; |
889 | tempdiff = temp - rdt->rdt_array[secnd].temp; | | 896 | tempdiff = temp - rd->rd_array[secnd].temp; |
890 | | | 897 | |
891 | offset = (datarange * tempdiff) / temprange; | | 898 | offset = (datarange * tempdiff) / temprange; |
892 | return rdt->rdt_array[secnd].data + offset; | | 899 | return rd->rd_array[secnd].data + offset; |
893 | } | | 900 | } |
894 | } | | 901 | } |
895 | | | 902 | |
896 | return sc->sc_data_mask; | | 903 | return sc->sc_data_mask; |
897 | } | | 904 | } |