1/* $OpenBSD: rktemp.c,v 1.14 2024/06/27 09:40:15 kettenis Exp $ */ 2/* 3 * Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18#include <sys/param.h> 19#include <sys/systm.h> 20#include <sys/device.h> 21#include <sys/sensors.h> 22 23#include <machine/intr.h> 24#include <machine/bus.h> 25#include <machine/fdt.h> 26 27#include <dev/ofw/openfirm.h> 28#include <dev/ofw/ofw_clock.h> 29#include <dev/ofw/ofw_misc.h> 30#include <dev/ofw/ofw_pinctrl.h> 31#include <dev/ofw/ofw_thermal.h> 32#include <dev/ofw/fdt.h> 33 34/* Registers */ 35#define TSADC_USER_CON 0x0000 36#define TSADC_USER_CON_INTER_PD_SOC_SHIFT 6 37#define TSADC_AUTO_CON 0x0004 38#define TSADC_AUTO_CON_TSHUT_POLARITY (1 << 8) 39#define TSADC_AUTO_CON_SRC_EN(ch) (1 << ((ch) + 4)) 40#define TSADC_AUTO_CON_TSADC_Q_SEL (1 << 1) 41#define TSADC_AUTO_CON_AUTO_EN (1 << 0) 42#define TSADC_INT_EN 0x0008 43#define TSADC_INT_EN_TSHUT_2CRU_EN_SRC(ch) (1 << ((ch) + 8)) 44#define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC(ch) (1 << ((ch) + 4)) 45#define TSADC_INT_PD 0x000c 46#define TSADC_INT_PD_TSHUT_O_SRC(ch) (1 << ((ch) + 4)) 47#define TSADC_DATA(ch) (0x0020 + (ch) * 4) 48#define TSADC_COMP_INT(ch) (0x0030 + (ch) * 4) 49#define TSADC_COMP_SHUT(ch) (0x0040 + (ch) * 4) 50#define TSADC_HIGHT_INT_DEBOUNCE 0x0060 51#define TSADC_HIGHT_TSHUT_DEBOUNCE 0x0064 52#define TSADC_AUTO_PERIOD 0x0068 53#define TSADC_AUTO_PERIOD_HT 0x006c 54 55/* RK3588 */ 56#define TSADC_V3_AUTO_SRC 0x000c 57#define TSADC_V3_AUTO_SRC_CH(ch) (1 << (ch)) 58#define TSADC_V3_HT_INT_EN 0x0014 59#define TSADC_V3_HT_INT_EN_CH(ch) (1 << (ch)) 60#define TSADC_V3_GPIO_EN 0x0018 61#define TSADC_V3_GPIO_EN_CH(ch) (1 << (ch)) 62#define TSADC_V3_CRU_EN 0x001c 63#define TSADC_V3_CRU_EN_CH(ch) (1 << (ch)) 64#define TSADC_V3_HLT_INT_PD 0x0024 65#define TSADC_V3_HT_INT_STATUS(ch) (1 << (ch)) 66#define TSADC_V3_DATA(ch) (0x002c + (ch) * 4) 67#define TSADC_V3_COMP_INT(ch) (0x006c + (ch) * 4) 68#define TSADC_V3_COMP_SHUT(ch) (0x010c + (ch) * 4) 69#define TSADC_V3_HIGHT_INT_DEBOUNCE 0x014c 70#define TSADC_V3_HIGHT_TSHUT_DEBOUNCE 0x0150 71#define TSADC_V3_AUTO_PERIOD 0x0154 72#define TSADC_V3_AUTO_PERIOD_HT 0x0158 73 74/* RK3568 */ 75#define RK3568_GRF_TSADC_CON 0x0600 76#define RK3568_GRF_TSADC_EN (1 << 8) 77#define RK3568_GRF_TSADC_ANA_REG(idx) (1 << (idx)) 78 79#define HREAD4(sc, reg) \ 80 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) 81#define HWRITE4(sc, reg, val) \ 82 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 83 84struct rktemp_entry { 85 int32_t temp; 86 int32_t code; 87}; 88 89/* RK3288 conversion table. */ 90const struct rktemp_entry rk3288_temps[] = { 91 { -40000, 3800 }, 92 { -35000, 3792 }, 93 { -30000, 3783 }, 94 { -25000, 3774 }, 95 { -20000, 3765 }, 96 { -15000, 3756 }, 97 { -10000, 3747 }, 98 { -5000, 3737 }, 99 { 0, 3728 }, 100 { 5000, 3718 }, 101 { 10000, 3708 }, 102 { 15000, 3698 }, 103 { 20000, 3688 }, 104 { 25000, 3678 }, 105 { 30000, 3667 }, 106 { 35000, 3656 }, 107 { 40000, 3645 }, 108 { 45000, 3634 }, 109 { 50000, 3623 }, 110 { 55000, 3611 }, 111 { 60000, 3600 }, 112 { 65000, 3588 }, 113 { 70000, 3575 }, 114 { 75000, 3563 }, 115 { 80000, 3550 }, 116 { 85000, 3537 }, 117 { 90000, 3524 }, 118 { 95000, 3510 }, 119 { 100000, 3496 }, 120 { 105000, 3482 }, 121 { 110000, 3467 }, 122 { 115000, 3452 }, 123 { 120000, 3437 }, 124 { 125000, 3421 }, 125}; 126 127const char *const rk3288_names[] = { "", "CPU", "GPU" }; 128 129/* RK3328 conversion table. */ 130const struct rktemp_entry rk3328_temps[] = { 131 { -40000, 296 }, 132 { -35000, 304 }, 133 { -30000, 313 }, 134 { -20000, 331 }, 135 { -15000, 340 }, 136 { -10000, 349 }, 137 { -5000, 359 }, 138 { 0, 368 }, 139 { 5000, 378 }, 140 { 10000, 388 }, 141 { 15000, 398 }, 142 { 20000, 408 }, 143 { 25000, 418 }, 144 { 30000, 429 }, 145 { 35000, 440 }, 146 { 40000, 451 }, 147 { 45000, 462 }, 148 { 50000, 473 }, 149 { 55000, 485 }, 150 { 60000, 496 }, 151 { 65000, 508 }, 152 { 70000, 521 }, 153 { 75000, 533 }, 154 { 80000, 546 }, 155 { 85000, 559 }, 156 { 90000, 572 }, 157 { 95000, 586 }, 158 { 100000, 600 }, 159 { 105000, 614 }, 160 { 110000, 629 }, 161 { 115000, 644 }, 162 { 120000, 659 }, 163 { 125000, 675 }, 164}; 165 166const char *const rk3308_names[] = { "CPU", "GPU" }; 167const char *const rk3328_names[] = { "CPU" }; 168 169/* RK3399 conversion table. */ 170const struct rktemp_entry rk3399_temps[] = { 171 { -40000, 402 }, 172 { -35000, 410 }, 173 { -30000, 419 }, 174 { -25000, 427 }, 175 { -20000, 436 }, 176 { -15000, 444 }, 177 { -10000, 453 }, 178 { -5000, 461 }, 179 { 0, 470 }, 180 { 5000, 478 }, 181 { 10000, 487 }, 182 { 15000, 496 }, 183 { 20000, 504 }, 184 { 25000, 513 }, 185 { 30000, 521 }, 186 { 35000, 530 }, 187 { 40000, 538 }, 188 { 45000, 547 }, 189 { 50000, 555 }, 190 { 55000, 564 }, 191 { 60000, 573 }, 192 { 65000, 581 }, 193 { 70000, 590 }, 194 { 75000, 599 }, 195 { 80000, 607 }, 196 { 85000, 616 }, 197 { 90000, 624 }, 198 { 95000, 633 }, 199 { 100000, 642 }, 200 { 105000, 650 }, 201 { 110000, 659 }, 202 { 115000, 668 }, 203 { 120000, 677 }, 204 { 125000, 685 }, 205}; 206 207const char *const rk3399_names[] = { "CPU", "GPU" }; 208 209/* RK3568 conversion table. */ 210const struct rktemp_entry rk3568_temps[] = { 211 { -40000, 1584 }, 212 { -35000, 1620 }, 213 { -30000, 1652 }, 214 { -25000, 1688 }, 215 { -20000, 1720 }, 216 { -15000, 1756 }, 217 { -10000, 1788 }, 218 { -5000, 1824 }, 219 { 0, 1856 }, 220 { 5000, 1892 }, 221 { 10000, 1924 }, 222 { 15000, 1956 }, 223 { 20000, 1992 }, 224 { 25000, 2024 }, 225 { 30000, 2060 }, 226 { 35000, 2092 }, 227 { 40000, 2128 }, 228 { 45000, 2160 }, 229 { 50000, 2196 }, 230 { 55000, 2228 }, 231 { 60000, 2264 }, 232 { 65000, 2300 }, 233 { 70000, 2332 }, 234 { 75000, 2368 }, 235 { 80000, 2400 }, 236 { 85000, 2436 }, 237 { 90000, 2468 }, 238 { 95000, 2500 }, 239 { 100000, 2536 }, 240 { 105000, 2572 }, 241 { 110000, 2604 }, 242 { 115000, 2636 }, 243 { 120000, 2672 }, 244 { 125000, 2704 }, 245}; 246 247const char *const rk3568_names[] = { "CPU", "GPU" }; 248 249/* RK3588 conversion table. */ 250const struct rktemp_entry rk3588_temps[] = { 251 { -40000, 215 }, 252 { 25000, 285 }, 253 { 85000, 350 }, 254 { 125000, 395 }, 255}; 256 257const char *const rk3588_names[] = { 258 "Top", 259 "CPU (big0)", 260 "CPU (big1)", 261 "CPU (little)", 262 "Center", 263 "GPU", 264 "NPU" 265}; 266 267struct rktemp_softc { 268 struct device sc_dev; 269 bus_space_tag_t sc_iot; 270 bus_space_handle_t sc_ioh; 271 int sc_node; 272 void *sc_ih; 273 274 bus_size_t sc_data0; 275 276 const struct rktemp_entry *sc_temps; 277 int sc_ntemps; 278 279 struct ksensor sc_sensors[7]; 280 int sc_nsensors; 281 struct ksensordev sc_sensordev; 282 283 struct thermal_sensor sc_ts; 284}; 285 286int rktemp_match(struct device *, void *, void *); 287void rktemp_attach(struct device *, struct device *, void *); 288 289const struct cfattach rktemp_ca = { 290 sizeof (struct rktemp_softc), rktemp_match, rktemp_attach 291}; 292 293struct cfdriver rktemp_cd = { 294 NULL, "rktemp", DV_DULL 295}; 296 297int rktemp_intr(void *); 298void rktemp_rk3568_init(struct rktemp_softc *); 299int32_t rktemp_calc_code(struct rktemp_softc *, int32_t); 300int32_t rktemp_calc_temp(struct rktemp_softc *, int32_t); 301int rktemp_valid(struct rktemp_softc *, int32_t); 302void rktemp_refresh_sensors(void *); 303int32_t rktemp_get_temperature(void *, uint32_t *); 304int rktemp_set_limit(void *, uint32_t *, uint32_t); 305 306int 307rktemp_match(struct device *parent, void *match, void *aux) 308{ 309 struct fdt_attach_args *faa = aux; 310 311 return (OF_is_compatible(faa->fa_node, "rockchip,rk3288-tsadc") || 312 OF_is_compatible(faa->fa_node, "rockchip,rk3308-tsadc") || 313 OF_is_compatible(faa->fa_node, "rockchip,rk3328-tsadc") || 314 OF_is_compatible(faa->fa_node, "rockchip,rk3399-tsadc") || 315 OF_is_compatible(faa->fa_node, "rockchip,rk3568-tsadc") || 316 OF_is_compatible(faa->fa_node, "rockchip,rk3588-tsadc")); 317} 318 319void 320rktemp_attach(struct device *parent, struct device *self, void *aux) 321{ 322 struct rktemp_softc *sc = (struct rktemp_softc *)self; 323 struct fdt_attach_args *faa = aux; 324 const char *const *names; 325 uint32_t mode, polarity, temp; 326 uint32_t auto_con, inter_pd_soc; 327 int auto_period, auto_period_ht; 328 int i; 329 330 if (faa->fa_nreg < 1) { 331 printf(": no registers\n"); 332 return; 333 } 334 335 sc->sc_iot = faa->fa_iot; 336 sc->sc_node = faa->fa_node; 337 338 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 339 faa->fa_reg[0].size, 0, &sc->sc_ioh)) { 340 printf(": can't map registers\n"); 341 return; 342 } 343 344 if (OF_is_compatible(sc->sc_node, "rockchip,rk3588-tsadc")) { 345 sc->sc_ih = fdt_intr_establish(faa->fa_node, IPL_SOFTCLOCK, 346 rktemp_intr, sc, sc->sc_dev.dv_xname); 347 if (sc->sc_ih == NULL) { 348 printf(": can't establish interrupt\n"); 349 return; 350 } 351 } 352 353 printf("\n"); 354 355 if (OF_is_compatible(sc->sc_node, "rockchip,rk3288-tsadc")) { 356 sc->sc_temps = rk3288_temps; 357 sc->sc_ntemps = nitems(rk3288_temps); 358 sc->sc_nsensors = 3; 359 names = rk3288_names; 360 inter_pd_soc = 13; 361 auto_period = 250; /* 250 ms */ 362 auto_period_ht = 50; /* 50 ms */ 363 } else if (OF_is_compatible(sc->sc_node, "rockchip,rk3308-tsadc")) { 364 sc->sc_temps = rk3328_temps; 365 sc->sc_ntemps = nitems(rk3328_temps); 366 sc->sc_nsensors = 2; 367 names = rk3308_names; 368 inter_pd_soc = 13; 369 auto_period = 1875; /* 2.5 ms */ 370 auto_period_ht = 1875; /* 2.5 ms */ 371 } else if (OF_is_compatible(sc->sc_node, "rockchip,rk3328-tsadc")) { 372 sc->sc_temps = rk3328_temps; 373 sc->sc_ntemps = nitems(rk3328_temps); 374 sc->sc_nsensors = 1; 375 names = rk3328_names; 376 inter_pd_soc = 13; 377 auto_period = 1875; /* 2.5 ms */ 378 auto_period_ht = 1875; /* 2.5 ms */ 379 } else if (OF_is_compatible(sc->sc_node, "rockchip,rk3399-tsadc")) { 380 sc->sc_temps = rk3399_temps; 381 sc->sc_ntemps = nitems(rk3399_temps); 382 sc->sc_nsensors = 2; 383 names = rk3399_names; 384 inter_pd_soc = 13; 385 auto_period = 1875; /* 2.5 ms */ 386 auto_period_ht = 1875; /* 2.5 ms */ 387 } else if (OF_is_compatible(sc->sc_node, "rockchip,rk3568-tsadc")) { 388 sc->sc_temps = rk3568_temps; 389 sc->sc_ntemps = nitems(rk3568_temps); 390 sc->sc_nsensors = 2; 391 names = rk3568_names; 392 inter_pd_soc = 63; /* 97 us */ 393 auto_period = 1622; /* 2.5 ms */ 394 auto_period_ht = 1622; /* 2.5 ms */ 395 } else { 396 sc->sc_temps = rk3588_temps; 397 sc->sc_ntemps = nitems(rk3588_temps); 398 sc->sc_nsensors = 7; 399 names = rk3588_names; 400 inter_pd_soc = 0; 401 auto_period = 5000; /* 2.5 ms */ 402 auto_period_ht = 5000; /* 2.5 ms */ 403 } 404 405 pinctrl_byname(sc->sc_node, "init"); 406 407 clock_set_assigned(sc->sc_node); 408 clock_enable(sc->sc_node, "tsadc"); 409 clock_enable(sc->sc_node, "apb_pclk"); 410 411 /* Reset the TS-ADC controller block. */ 412 reset_assert_all(sc->sc_node); 413 delay(10); 414 reset_deassert_all(sc->sc_node); 415 416 mode = OF_getpropint(sc->sc_node, "rockchip,hw-tshut-mode", 1); 417 polarity = OF_getpropint(sc->sc_node, "rockchip,hw-tshut-polarity", 0); 418 temp = OF_getpropint(sc->sc_node, "rockchip,hw-tshut-temp", 95000); 419 420 if (OF_is_compatible(sc->sc_node, "rockchip,rk3588-tsadc")) { 421 uint32_t gpio_en, cru_en; 422 423 sc->sc_data0 = TSADC_V3_DATA(0); 424 425 HWRITE4(sc, TSADC_V3_AUTO_PERIOD, auto_period); 426 HWRITE4(sc, TSADC_V3_AUTO_PERIOD_HT, auto_period_ht); 427 HWRITE4(sc, TSADC_V3_HIGHT_INT_DEBOUNCE, 4); 428 HWRITE4(sc, TSADC_V3_HIGHT_TSHUT_DEBOUNCE, 4); 429 430 auto_con = TSADC_AUTO_CON_TSHUT_POLARITY << 16; 431 if (polarity) 432 auto_con = TSADC_AUTO_CON_TSHUT_POLARITY; 433 HWRITE4(sc, TSADC_AUTO_CON, auto_con); 434 435 /* Set shutdown limit. */ 436 for (i = 0; i < sc->sc_nsensors; i++) { 437 HWRITE4(sc, TSADC_V3_COMP_SHUT(i), 438 rktemp_calc_code(sc, temp)); 439 HWRITE4(sc, TSADC_V3_AUTO_SRC, 440 TSADC_V3_AUTO_SRC_CH(i) << 16 | 441 TSADC_V3_AUTO_SRC_CH(i)); 442 } 443 444 /* Clear shutdown output status. */ 445 for (i = 0; i < sc->sc_nsensors; i++) { 446 HWRITE4(sc, TSADC_V3_HLT_INT_PD, 447 TSADC_V3_HT_INT_STATUS(i)); 448 } 449 450 /* Configure mode. */ 451 gpio_en = cru_en = 0; 452 for (i = 0; i < sc->sc_nsensors; i++) { 453 gpio_en |= TSADC_V3_GPIO_EN_CH(i) << 16; 454 cru_en |= TSADC_V3_CRU_EN_CH(i) << 16; 455 if (mode) 456 gpio_en |= TSADC_V3_GPIO_EN_CH(i); 457 else 458 cru_en |= TSADC_V3_CRU_EN_CH(i); 459 } 460 HWRITE4(sc, TSADC_V3_GPIO_EN, gpio_en); 461 HWRITE4(sc, TSADC_V3_CRU_EN, cru_en); 462 } else { 463 uint32_t int_en; 464 465 sc->sc_data0 = TSADC_DATA(0); 466 467 HWRITE4(sc, TSADC_USER_CON, 468 inter_pd_soc << TSADC_USER_CON_INTER_PD_SOC_SHIFT); 469 HWRITE4(sc, TSADC_AUTO_PERIOD, auto_period); 470 HWRITE4(sc, TSADC_AUTO_PERIOD_HT, auto_period_ht); 471 HWRITE4(sc, TSADC_HIGHT_INT_DEBOUNCE, 4); 472 HWRITE4(sc, TSADC_HIGHT_TSHUT_DEBOUNCE, 4); 473 474 if (OF_is_compatible(sc->sc_node, "rockchip,rk3568-tsadc")) 475 rktemp_rk3568_init(sc); 476 477 auto_con = HREAD4(sc, TSADC_AUTO_CON); 478 auto_con |= TSADC_AUTO_CON_TSADC_Q_SEL; 479 if (polarity) 480 auto_con |= TSADC_AUTO_CON_TSHUT_POLARITY; 481 HWRITE4(sc, TSADC_AUTO_CON, auto_con); 482 483 /* Set shutdown limit. */ 484 for (i = 0; i < sc->sc_nsensors; i++) { 485 HWRITE4(sc, TSADC_COMP_SHUT(i), 486 rktemp_calc_code(sc, temp)); 487 auto_con |= (TSADC_AUTO_CON_SRC_EN(i)); 488 } 489 HWRITE4(sc, TSADC_AUTO_CON, auto_con); 490 491 /* Clear shutdown output status. */ 492 for (i = 0; i < sc->sc_nsensors; i++) 493 HWRITE4(sc, TSADC_INT_PD, TSADC_INT_PD_TSHUT_O_SRC(i)); 494 495 /* Configure mode. */ 496 int_en = HREAD4(sc, TSADC_INT_EN); 497 for (i = 0; i < sc->sc_nsensors; i++) { 498 if (mode) 499 int_en |= TSADC_INT_EN_TSHUT_2GPIO_EN_SRC(i); 500 else 501 int_en |= TSADC_INT_EN_TSHUT_2CRU_EN_SRC(i); 502 } 503 HWRITE4(sc, TSADC_INT_EN, int_en); 504 } 505 506 pinctrl_byname(sc->sc_node, "default"); 507 508 /* Finally turn on the ADC. */ 509 if (OF_is_compatible(sc->sc_node, "rockchip,rk3588-tsadc")) { 510 HWRITE4(sc, TSADC_AUTO_CON, 511 TSADC_AUTO_CON_AUTO_EN << 16 | TSADC_AUTO_CON_AUTO_EN); 512 } else { 513 auto_con |= TSADC_AUTO_CON_AUTO_EN; 514 HWRITE4(sc, TSADC_AUTO_CON, auto_con); 515 } 516 517 /* Register sensors. */ 518 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, 519 sizeof(sc->sc_sensordev.xname)); 520 for (i = 0; i < sc->sc_nsensors; i++) { 521 strlcpy(sc->sc_sensors[i].desc, names[i], 522 sizeof(sc->sc_sensors[i].desc)); 523 sc->sc_sensors[i].type = SENSOR_TEMP; 524 sc->sc_sensors[i].flags = SENSOR_FINVALID; 525 sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]); 526 } 527 sensordev_install(&sc->sc_sensordev); 528 sensor_task_register(sc, rktemp_refresh_sensors, 5); 529 530 sc->sc_ts.ts_node = sc->sc_node; 531 sc->sc_ts.ts_cookie = sc; 532 sc->sc_ts.ts_get_temperature = rktemp_get_temperature; 533 if (OF_is_compatible(sc->sc_node, "rockchip,rk3588-tsadc")) 534 sc->sc_ts.ts_set_limit = rktemp_set_limit; 535 thermal_sensor_register(&sc->sc_ts); 536} 537 538int 539rktemp_intr(void *arg) 540{ 541 struct rktemp_softc *sc = arg; 542 uint32_t stat, ch; 543 544 stat = HREAD4(sc, TSADC_V3_HLT_INT_PD); 545 stat &= HREAD4(sc, TSADC_V3_HT_INT_EN); 546 for (ch = 0; ch < sc->sc_nsensors; ch++) { 547 if (stat & TSADC_V3_HT_INT_STATUS(ch)) 548 thermal_sensor_update(&sc->sc_ts, &ch); 549 } 550 551 /* 552 * Disable and clear the active interrupts. The thermal zone 553 * code will set a new limit when necessary. 554 */ 555 HWRITE4(sc, TSADC_V3_HT_INT_EN, stat << 16); 556 HWRITE4(sc, TSADC_V3_HLT_INT_PD, stat); 557 558 return 1; 559} 560 561void 562rktemp_rk3568_init(struct rktemp_softc *sc) 563{ 564 struct regmap *rm; 565 uint32_t grf; 566 int i; 567 568 grf = OF_getpropint(sc->sc_node, "rockchip,grf", 0); 569 rm = regmap_byphandle(grf); 570 if (rm == 0) 571 return; 572 573 regmap_write_4(rm, RK3568_GRF_TSADC_CON, 574 RK3568_GRF_TSADC_EN << 16 | RK3568_GRF_TSADC_EN); 575 delay(15); 576 for (i = 0; i <= 2; i++) { 577 regmap_write_4(rm, RK3568_GRF_TSADC_CON, 578 RK3568_GRF_TSADC_ANA_REG(i) << 16 | 579 RK3568_GRF_TSADC_ANA_REG(i)); 580 } 581 delay(100); 582} 583 584int32_t 585rktemp_calc_code(struct rktemp_softc *sc, int32_t temp) 586{ 587 const int n = sc->sc_ntemps; 588 int32_t code0, delta_code; 589 int32_t temp0, delta_temp; 590 int i; 591 592 if (temp <= sc->sc_temps[0].temp) 593 return sc->sc_temps[0].code; 594 if (temp >= sc->sc_temps[n - 1].temp) 595 return sc->sc_temps[n - 1].code; 596 597 for (i = 1; i < n; i++) { 598 if (temp < sc->sc_temps[i].temp) 599 break; 600 } 601 602 code0 = sc->sc_temps[i - 1].code; 603 temp0 = sc->sc_temps[i - 1].temp; 604 delta_code = sc->sc_temps[i].code - code0; 605 delta_temp = sc->sc_temps[i].temp - temp0; 606 607 return code0 + (temp - temp0) * delta_code / delta_temp; 608} 609 610int32_t 611rktemp_calc_temp(struct rktemp_softc *sc, int32_t code) 612{ 613 const int n = sc->sc_ntemps; 614 int32_t code0, delta_code; 615 int32_t temp0, delta_temp; 616 int i; 617 618 /* Handle both negative and positive temperature coefficients. */ 619 if (sc->sc_temps[0].code > sc->sc_temps[1].code) { 620 if (code >= sc->sc_temps[0].code) 621 return sc->sc_temps[0].code; 622 if (code <= sc->sc_temps[n - 1].code) 623 return sc->sc_temps[n - 1].temp; 624 625 for (i = 1; i < n; i++) { 626 if (code > sc->sc_temps[i].code) 627 break; 628 } 629 } else { 630 if (code <= sc->sc_temps[0].code) 631 return sc->sc_temps[0].temp; 632 if (code >= sc->sc_temps[n - 1].code) 633 return sc->sc_temps[n - 1].temp; 634 635 for (i = 1; i < n; i++) { 636 if (code < sc->sc_temps[i].code) 637 break; 638 } 639 } 640 641 code0 = sc->sc_temps[i - 1].code; 642 temp0 = sc->sc_temps[i - 1].temp; 643 delta_code = sc->sc_temps[i].code - code0; 644 delta_temp = sc->sc_temps[i].temp - temp0; 645 646 return temp0 + (code - code0) * delta_temp / delta_code; 647} 648 649int 650rktemp_valid(struct rktemp_softc *sc, int32_t code) 651{ 652 const int n = sc->sc_ntemps; 653 654 if (sc->sc_temps[0].code > sc->sc_temps[1].code) { 655 if (code > sc->sc_temps[0].code) 656 return 0; 657 if (code < sc->sc_temps[n - 1].code) 658 return 0; 659 } else { 660 if (code < sc->sc_temps[0].code) 661 return 0; 662 if (code > sc->sc_temps[n - 1].code) 663 return 0; 664 } 665 return 1; 666} 667 668void 669rktemp_refresh_sensors(void *arg) 670{ 671 struct rktemp_softc *sc = arg; 672 int32_t code, temp; 673 int i; 674 675 for (i = 0; i < sc->sc_nsensors; i++) { 676 code = HREAD4(sc, sc->sc_data0 + (i * 4)); 677 temp = rktemp_calc_temp(sc, code); 678 sc->sc_sensors[i].value = 273150000 + 1000 * temp; 679 if (rktemp_valid(sc, code)) 680 sc->sc_sensors[i].flags &= ~SENSOR_FINVALID; 681 else 682 sc->sc_sensors[i].flags |= SENSOR_FINVALID; 683 } 684} 685 686int32_t 687rktemp_get_temperature(void *cookie, uint32_t *cells) 688{ 689 struct rktemp_softc *sc = cookie; 690 uint32_t ch = cells[0]; 691 int32_t code; 692 693 if (ch >= sc->sc_nsensors) 694 return THERMAL_SENSOR_MAX; 695 696 code = HREAD4(sc, sc->sc_data0 + (ch * 4)); 697 if (rktemp_valid(sc, code)) 698 return rktemp_calc_temp(sc, code); 699 else 700 return THERMAL_SENSOR_MAX; 701} 702 703int 704rktemp_set_limit(void *cookie, uint32_t *cells, uint32_t temp) 705{ 706 struct rktemp_softc *sc = cookie; 707 uint32_t ch = cells[0]; 708 709 if (ch >= sc->sc_nsensors) 710 return ENXIO; 711 712 /* Set limit for this sensor. */ 713 HWRITE4(sc, TSADC_V3_COMP_INT(ch), rktemp_calc_code(sc, temp)); 714 715 /* Clear and enable the corresponding interrupt. */ 716 HWRITE4(sc, TSADC_V3_HLT_INT_PD, TSADC_V3_HT_INT_STATUS(ch)); 717 HWRITE4(sc, TSADC_V3_HT_INT_EN, TSADC_V3_HT_INT_EN_CH(ch) << 16 | 718 TSADC_V3_HT_INT_EN_CH(ch)); 719 720 return 0; 721} 722