1 /* $OpenBSD: rktemp.c,v 1.12 2023/03/05 09:57:32 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_SRC3_EN (1 << 7) 40 #define TSADC_AUTO_CON_SRC2_EN (1 << 6) 41 #define TSADC_AUTO_CON_SRC1_EN (1 << 5) 42 #define TSADC_AUTO_CON_SRC0_EN (1 << 4) 43 #define TSADC_AUTO_CON_TSADC_Q_SEL (1 << 1) 44 #define TSADC_AUTO_CON_AUTO_EN (1 << 0) 45 #define TSADC_INT_EN 0x0008 46 #define TSADC_INT_EN_TSHUT_2CRU_EN_SRC3 (1 << 11) 47 #define TSADC_INT_EN_TSHUT_2CRU_EN_SRC2 (1 << 10) 48 #define TSADC_INT_EN_TSHUT_2CRU_EN_SRC1 (1 << 9) 49 #define TSADC_INT_EN_TSHUT_2CRU_EN_SRC0 (1 << 8) 50 #define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC3 (1 << 7) 51 #define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC2 (1 << 6) 52 #define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC1 (1 << 5) 53 #define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0 (1 << 4) 54 #define TSADC_INT_PD 0x000c 55 #define TSADC_INT_PD_TSHUT_O_SRC0 (1 << 4) 56 #define TSADC_INT_PD_TSHUT_O_SRC1 (1 << 5) 57 #define TSADC_INT_PD_TSHUT_O_SRC2 (1 << 6) 58 #define TSADC_INT_PD_TSHUT_O_SRC3 (1 << 7) 59 #define TSADC_DATA0 0x0020 60 #define TSADC_DATA1 0x0024 61 #define TSADC_DATA2 0x0028 62 #define TSADC_DATA3 0x002c 63 #define TSADC_COMP0_INT 0x0030 64 #define TSADC_COMP1_INT 0x0034 65 #define TSADC_COMP2_INT 0x0038 66 #define TSADC_COMP3_INT 0x003c 67 #define TSADC_COMP0_SHUT 0x0040 68 #define TSADC_COMP1_SHUT 0x0044 69 #define TSADC_COMP2_SHUT 0x0048 70 #define TSADC_COMP3_SHUT 0x004c 71 #define TSADC_HIGHT_INT_DEBOUNCE 0x0060 72 #define TSADC_HIGHT_TSHUT_DEBOUNCE 0x0064 73 #define TSADC_AUTO_PERIOD 0x0068 74 #define TSADC_AUTO_PERIOD_HT 0x006c 75 76 /* RK3568 */ 77 #define RK3568_GRF_TSADC_CON 0x0600 78 #define RK3568_GRF_TSADC_EN (1 << 8) 79 #define RK3568_GRF_TSADC_ANA_REG(idx) (1 << (idx)) 80 81 #define HREAD4(sc, reg) \ 82 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) 83 #define HWRITE4(sc, reg, val) \ 84 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 85 86 struct rktemp_entry { 87 int32_t temp; 88 int32_t code; 89 }; 90 91 /* RK3288 conversion table. */ 92 const struct rktemp_entry rk3288_temps[] = { 93 { -40000, 3800 }, 94 { -35000, 3792 }, 95 { -30000, 3783 }, 96 { -25000, 3774 }, 97 { -20000, 3765 }, 98 { -15000, 3756 }, 99 { -10000, 3747 }, 100 { -5000, 3737 }, 101 { 0, 3728 }, 102 { 5000, 3718 }, 103 { 10000, 3708 }, 104 { 15000, 3698 }, 105 { 20000, 3688 }, 106 { 25000, 3678 }, 107 { 30000, 3667 }, 108 { 35000, 3656 }, 109 { 40000, 3645 }, 110 { 45000, 3634 }, 111 { 50000, 3623 }, 112 { 55000, 3611 }, 113 { 60000, 3600 }, 114 { 65000, 3588 }, 115 { 70000, 3575 }, 116 { 75000, 3563 }, 117 { 80000, 3550 }, 118 { 85000, 3537 }, 119 { 90000, 3524 }, 120 { 95000, 3510 }, 121 { 100000, 3496 }, 122 { 105000, 3482 }, 123 { 110000, 3467 }, 124 { 115000, 3452 }, 125 { 120000, 3437 }, 126 { 125000, 3421 }, 127 }; 128 129 const char *const rk3288_names[] = { "", "CPU", "GPU" }; 130 131 /* RK3328 conversion table. */ 132 const struct rktemp_entry rk3328_temps[] = { 133 { -40000, 296 }, 134 { -35000, 304 }, 135 { -30000, 313 }, 136 { -20000, 331 }, 137 { -15000, 340 }, 138 { -10000, 349 }, 139 { -5000, 359 }, 140 { 0, 368 }, 141 { 5000, 378 }, 142 { 10000, 388 }, 143 { 15000, 398 }, 144 { 20000, 408 }, 145 { 25000, 418 }, 146 { 30000, 429 }, 147 { 35000, 440 }, 148 { 40000, 451 }, 149 { 45000, 462 }, 150 { 50000, 473 }, 151 { 55000, 485 }, 152 { 60000, 496 }, 153 { 65000, 508 }, 154 { 70000, 521 }, 155 { 75000, 533 }, 156 { 80000, 546 }, 157 { 85000, 559 }, 158 { 90000, 572 }, 159 { 95000, 586 }, 160 { 100000, 600 }, 161 { 105000, 614 }, 162 { 110000, 629 }, 163 { 115000, 644 }, 164 { 120000, 659 }, 165 { 125000, 675 }, 166 }; 167 168 const char *const rk3308_names[] = { "CPU", "GPU" }; 169 const char *const rk3328_names[] = { "CPU" }; 170 171 /* RK3399 conversion table. */ 172 const struct rktemp_entry rk3399_temps[] = { 173 { -40000, 402 }, 174 { -35000, 410 }, 175 { -30000, 419 }, 176 { -25000, 427 }, 177 { -20000, 436 }, 178 { -15000, 444 }, 179 { -10000, 453 }, 180 { -5000, 461 }, 181 { 0, 470 }, 182 { 5000, 478 }, 183 { 10000, 487 }, 184 { 15000, 496 }, 185 { 20000, 504 }, 186 { 25000, 513 }, 187 { 30000, 521 }, 188 { 35000, 530 }, 189 { 40000, 538 }, 190 { 45000, 547 }, 191 { 50000, 555 }, 192 { 55000, 564 }, 193 { 60000, 573 }, 194 { 65000, 581 }, 195 { 70000, 590 }, 196 { 75000, 599 }, 197 { 80000, 607 }, 198 { 85000, 616 }, 199 { 90000, 624 }, 200 { 95000, 633 }, 201 { 100000, 642 }, 202 { 105000, 650 }, 203 { 110000, 659 }, 204 { 115000, 668 }, 205 { 120000, 677 }, 206 { 125000, 685 }, 207 }; 208 209 const char *const rk3399_names[] = { "CPU", "GPU" }; 210 211 /* RK3568 conversion table. */ 212 const struct rktemp_entry rk3568_temps[] = { 213 { -40000, 1584 }, 214 { -35000, 1620 }, 215 { -30000, 1652 }, 216 { -25000, 1688 }, 217 { -20000, 1720 }, 218 { -15000, 1756 }, 219 { -10000, 1788 }, 220 { -5000, 1824 }, 221 { 0, 1856 }, 222 { 5000, 1892 }, 223 { 10000, 1924 }, 224 { 15000, 1956 }, 225 { 20000, 1992 }, 226 { 25000, 2024 }, 227 { 30000, 2060 }, 228 { 35000, 2092 }, 229 { 40000, 2128 }, 230 { 45000, 2160 }, 231 { 50000, 2196 }, 232 { 55000, 2228 }, 233 { 60000, 2264 }, 234 { 65000, 2300 }, 235 { 70000, 2332 }, 236 { 75000, 2368 }, 237 { 80000, 2400 }, 238 { 85000, 2436 }, 239 { 90000, 2468 }, 240 { 95000, 2500 }, 241 { 100000, 2536 }, 242 { 105000, 2572 }, 243 { 110000, 2604 }, 244 { 115000, 2636 }, 245 { 120000, 2672 }, 246 { 125000, 2704 }, 247 }; 248 249 const char *const rk3568_names[] = { "CPU", "GPU" }; 250 251 struct rktemp_softc { 252 struct device sc_dev; 253 bus_space_tag_t sc_iot; 254 bus_space_handle_t sc_ioh; 255 int sc_node; 256 257 const struct rktemp_entry *sc_temps; 258 int sc_ntemps; 259 260 struct ksensor sc_sensors[3]; 261 int sc_nsensors; 262 struct ksensordev sc_sensordev; 263 264 struct thermal_sensor sc_ts; 265 }; 266 267 int rktemp_match(struct device *, void *, void *); 268 void rktemp_attach(struct device *, struct device *, void *); 269 270 const struct cfattach rktemp_ca = { 271 sizeof (struct rktemp_softc), rktemp_match, rktemp_attach 272 }; 273 274 struct cfdriver rktemp_cd = { 275 NULL, "rktemp", DV_DULL 276 }; 277 278 void rktemp_rk3568_init(struct rktemp_softc *); 279 int32_t rktemp_calc_code(struct rktemp_softc *, int32_t); 280 int32_t rktemp_calc_temp(struct rktemp_softc *, int32_t); 281 int rktemp_valid(struct rktemp_softc *, int32_t); 282 void rktemp_refresh_sensors(void *); 283 int32_t rktemp_get_temperature(void *, uint32_t *); 284 285 int 286 rktemp_match(struct device *parent, void *match, void *aux) 287 { 288 struct fdt_attach_args *faa = aux; 289 290 return (OF_is_compatible(faa->fa_node, "rockchip,rk3288-tsadc") || 291 OF_is_compatible(faa->fa_node, "rockchip,rk3308-tsadc") || 292 OF_is_compatible(faa->fa_node, "rockchip,rk3328-tsadc") || 293 OF_is_compatible(faa->fa_node, "rockchip,rk3399-tsadc") || 294 OF_is_compatible(faa->fa_node, "rockchip,rk3568-tsadc")); 295 } 296 297 void 298 rktemp_attach(struct device *parent, struct device *self, void *aux) 299 { 300 struct rktemp_softc *sc = (struct rktemp_softc *)self; 301 struct fdt_attach_args *faa = aux; 302 const char *const *names; 303 uint32_t mode, polarity, temp; 304 uint32_t auto_con, int_en; 305 uint32_t inter_pd_soc; 306 int auto_period, auto_period_ht; 307 int i; 308 309 if (faa->fa_nreg < 1) { 310 printf(": no registers\n"); 311 return; 312 } 313 314 sc->sc_iot = faa->fa_iot; 315 sc->sc_node = faa->fa_node; 316 317 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 318 faa->fa_reg[0].size, 0, &sc->sc_ioh)) { 319 printf(": can't map registers\n"); 320 return; 321 } 322 323 printf("\n"); 324 325 if (OF_is_compatible(sc->sc_node, "rockchip,rk3288-tsadc")) { 326 sc->sc_temps = rk3288_temps; 327 sc->sc_ntemps = nitems(rk3288_temps); 328 sc->sc_nsensors = 3; 329 names = rk3288_names; 330 inter_pd_soc = 13; 331 auto_period = 250; /* 250 ms */ 332 auto_period_ht = 50; /* 50 ms */ 333 } else if (OF_is_compatible(sc->sc_node, "rockchip,rk3308-tsadc")) { 334 sc->sc_temps = rk3328_temps; 335 sc->sc_ntemps = nitems(rk3328_temps); 336 sc->sc_nsensors = 2; 337 names = rk3308_names; 338 inter_pd_soc = 13; 339 auto_period = 1875; /* 2.5 ms */ 340 auto_period_ht = 1875; /* 2.5 ms */ 341 } else if (OF_is_compatible(sc->sc_node, "rockchip,rk3328-tsadc")) { 342 sc->sc_temps = rk3328_temps; 343 sc->sc_ntemps = nitems(rk3328_temps); 344 sc->sc_nsensors = 1; 345 names = rk3328_names; 346 inter_pd_soc = 13; 347 auto_period = 1875; /* 2.5 ms */ 348 auto_period_ht = 1875; /* 2.5 ms */ 349 } else if (OF_is_compatible(sc->sc_node, "rockchip,rk3399-tsadc")) { 350 sc->sc_temps = rk3399_temps; 351 sc->sc_ntemps = nitems(rk3399_temps); 352 sc->sc_nsensors = 2; 353 names = rk3399_names; 354 inter_pd_soc = 13; 355 auto_period = 1875; /* 2.5 ms */ 356 auto_period_ht = 1875; /* 2.5 ms */ 357 } else { 358 sc->sc_temps = rk3568_temps; 359 sc->sc_ntemps = nitems(rk3568_temps); 360 sc->sc_nsensors = 2; 361 names = rk3568_names; 362 inter_pd_soc = 63; /* 97 us */ 363 auto_period = 1622; /* 2.5 ms */ 364 auto_period_ht = 1622; /* 2.5 ms */ 365 } 366 367 pinctrl_byname(sc->sc_node, "init"); 368 369 clock_set_assigned(sc->sc_node); 370 clock_enable(sc->sc_node, "tsadc"); 371 clock_enable(sc->sc_node, "apb_pclk"); 372 373 /* Reset the TS-ADC controller block. */ 374 reset_assert(sc->sc_node, "tsadc-apb"); 375 delay(10); 376 reset_deassert(sc->sc_node, "tsadc-apb"); 377 378 mode = OF_getpropint(sc->sc_node, "rockchip,hw-tshut-mode", 1); 379 polarity = OF_getpropint(sc->sc_node, "rockchip,hw-tshut-polarity", 0); 380 temp = OF_getpropint(sc->sc_node, "rockchip,hw-tshut-temp", 95000); 381 382 HWRITE4(sc, TSADC_USER_CON, 383 inter_pd_soc << TSADC_USER_CON_INTER_PD_SOC_SHIFT); 384 HWRITE4(sc, TSADC_AUTO_PERIOD, auto_period); 385 HWRITE4(sc, TSADC_AUTO_PERIOD_HT, auto_period_ht); 386 HWRITE4(sc, TSADC_HIGHT_INT_DEBOUNCE, 4); 387 HWRITE4(sc, TSADC_HIGHT_TSHUT_DEBOUNCE, 4); 388 389 if (OF_is_compatible(sc->sc_node, "rockchip,rk3568-tsadc")) 390 rktemp_rk3568_init(sc); 391 392 auto_con = HREAD4(sc, TSADC_AUTO_CON); 393 auto_con |= TSADC_AUTO_CON_TSADC_Q_SEL; 394 if (polarity) 395 auto_con |= TSADC_AUTO_CON_TSHUT_POLARITY; 396 HWRITE4(sc, TSADC_AUTO_CON, auto_con); 397 398 /* Set shutdown limit. */ 399 for (i = 0; i < sc->sc_nsensors; i++) { 400 HWRITE4(sc, TSADC_COMP0_SHUT + i * 4, 401 rktemp_calc_code(sc, temp)); 402 auto_con |= (TSADC_AUTO_CON_SRC0_EN << i); 403 } 404 HWRITE4(sc, TSADC_AUTO_CON, auto_con); 405 406 /* Clear shutdown output status. */ 407 for (i = 0; i < sc->sc_nsensors; i++) 408 HWRITE4(sc, TSADC_INT_PD, (TSADC_INT_PD_TSHUT_O_SRC0 << i)); 409 410 /* Configure mode. */ 411 int_en = HREAD4(sc, TSADC_INT_EN); 412 for (i = 0; i < sc->sc_nsensors; i++) { 413 if (mode) 414 int_en |= (TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0 << i); 415 else 416 int_en |= (TSADC_INT_EN_TSHUT_2CRU_EN_SRC0 << i); 417 } 418 HWRITE4(sc, TSADC_INT_EN, int_en); 419 420 pinctrl_byname(sc->sc_node, "default"); 421 422 /* Finally turn on the ADC. */ 423 auto_con |= TSADC_AUTO_CON_AUTO_EN; 424 HWRITE4(sc, TSADC_AUTO_CON, auto_con); 425 426 /* Register sensors. */ 427 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, 428 sizeof(sc->sc_sensordev.xname)); 429 for (i = 0; i < sc->sc_nsensors; i++) { 430 strlcpy(sc->sc_sensors[i].desc, names[i], 431 sizeof(sc->sc_sensors[i].desc)); 432 sc->sc_sensors[i].type = SENSOR_TEMP; 433 sc->sc_sensors[i].flags = SENSOR_FINVALID; 434 sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]); 435 } 436 sensordev_install(&sc->sc_sensordev); 437 sensor_task_register(sc, rktemp_refresh_sensors, 5); 438 439 sc->sc_ts.ts_node = sc->sc_node; 440 sc->sc_ts.ts_cookie = sc; 441 sc->sc_ts.ts_get_temperature = rktemp_get_temperature; 442 thermal_sensor_register(&sc->sc_ts); 443 } 444 445 void 446 rktemp_rk3568_init(struct rktemp_softc *sc) 447 { 448 struct regmap *rm; 449 uint32_t grf; 450 int i; 451 452 grf = OF_getpropint(sc->sc_node, "rockchip,grf", 0); 453 rm = regmap_byphandle(grf); 454 if (rm == 0) 455 return; 456 457 regmap_write_4(rm, RK3568_GRF_TSADC_CON, 458 RK3568_GRF_TSADC_EN << 16 | RK3568_GRF_TSADC_EN); 459 delay(15); 460 for (i = 0; i <= 2; i++) { 461 regmap_write_4(rm, RK3568_GRF_TSADC_CON, 462 RK3568_GRF_TSADC_ANA_REG(i) << 16 | 463 RK3568_GRF_TSADC_ANA_REG(i)); 464 } 465 delay(100); 466 } 467 468 int32_t 469 rktemp_calc_code(struct rktemp_softc *sc, int32_t temp) 470 { 471 const int n = sc->sc_ntemps; 472 int32_t code0, delta_code; 473 int32_t temp0, delta_temp; 474 int i; 475 476 if (temp <= sc->sc_temps[0].temp) 477 return sc->sc_temps[0].code; 478 if (temp >= sc->sc_temps[n - 1].temp) 479 return sc->sc_temps[n - 1].code; 480 481 for (i = 1; i < n; i++) { 482 if (temp < sc->sc_temps[i].temp) 483 break; 484 } 485 486 code0 = sc->sc_temps[i - 1].code; 487 temp0 = sc->sc_temps[i - 1].temp; 488 delta_code = sc->sc_temps[i].code - code0; 489 delta_temp = sc->sc_temps[i].temp - temp0; 490 491 return code0 + (temp - temp0) * delta_code / delta_temp; 492 } 493 494 int32_t 495 rktemp_calc_temp(struct rktemp_softc *sc, int32_t code) 496 { 497 const int n = sc->sc_ntemps; 498 int32_t code0, delta_code; 499 int32_t temp0, delta_temp; 500 int i; 501 502 /* Handle both negative and positive temperature coefficients. */ 503 if (sc->sc_temps[0].code > sc->sc_temps[1].code) { 504 if (code >= sc->sc_temps[0].code) 505 return sc->sc_temps[0].code; 506 if (code <= sc->sc_temps[n - 1].code) 507 return sc->sc_temps[n - 1].temp; 508 509 for (i = 1; i < n; i++) { 510 if (code > sc->sc_temps[i].code) 511 break; 512 } 513 } else { 514 if (code <= sc->sc_temps[0].code) 515 return sc->sc_temps[0].temp; 516 if (code >= sc->sc_temps[n - 1].code) 517 return sc->sc_temps[n - 1].temp; 518 519 for (i = 1; i < n; i++) { 520 if (code < sc->sc_temps[i].code) 521 break; 522 } 523 } 524 525 code0 = sc->sc_temps[i - 1].code; 526 temp0 = sc->sc_temps[i - 1].temp; 527 delta_code = sc->sc_temps[i].code - code0; 528 delta_temp = sc->sc_temps[i].temp - temp0; 529 530 return temp0 + (code - code0) * delta_temp / delta_code; 531 } 532 533 int 534 rktemp_valid(struct rktemp_softc *sc, int32_t code) 535 { 536 const int n = sc->sc_ntemps; 537 538 if (sc->sc_temps[0].code > sc->sc_temps[1].code) { 539 if (code > sc->sc_temps[0].code) 540 return 0; 541 if (code < sc->sc_temps[n - 1].code) 542 return 0; 543 } else { 544 if (code < sc->sc_temps[0].code) 545 return 0; 546 if (code > sc->sc_temps[n - 1].code) 547 return 0; 548 } 549 return 1; 550 } 551 552 void 553 rktemp_refresh_sensors(void *arg) 554 { 555 struct rktemp_softc *sc = arg; 556 int32_t code, temp; 557 int i; 558 559 for (i = 0; i < sc->sc_nsensors; i++) { 560 code = HREAD4(sc, TSADC_DATA0 + i * 4); 561 temp = rktemp_calc_temp(sc, code); 562 sc->sc_sensors[i].value = 273150000 + 1000 * temp; 563 if (rktemp_valid(sc, code)) 564 sc->sc_sensors[i].flags &= ~SENSOR_FINVALID; 565 else 566 sc->sc_sensors[i].flags |= SENSOR_FINVALID; 567 } 568 } 569 570 int32_t 571 rktemp_get_temperature(void *cookie, uint32_t *cells) 572 { 573 struct rktemp_softc *sc = cookie; 574 uint32_t idx = cells[0]; 575 int32_t code; 576 577 if (idx >= sc->sc_nsensors) 578 return THERMAL_SENSOR_MAX; 579 580 code = HREAD4(sc, TSADC_DATA0 + idx * 4); 581 if (rktemp_valid(sc, code)) 582 return rktemp_calc_temp(sc, code); 583 else 584 return THERMAL_SENSOR_MAX; 585 } 586