-/* $OpenBSD: rktemp.c,v 1.1 2017/08/25 10:29:54 kettenis Exp $ */
+/* $OpenBSD: rktemp.c,v 1.2 2017/12/29 10:39:01 kettenis Exp $ */
/*
* Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
*
#define TSADC_USER_CON 0x0000
#define TSADC_AUTO_CON 0x0004
#define TSADC_AUTO_CON_TSHUT_POLARITY (1 << 8)
+#define TSADC_AUTO_CON_SRC3_EN (1 << 7)
+#define TSADC_AUTO_CON_SRC2_EN (1 << 6)
#define TSADC_AUTO_CON_SRC1_EN (1 << 5)
#define TSADC_AUTO_CON_SRC0_EN (1 << 4)
#define TSADC_AUTO_CON_TSADC_Q_SEL (1 << 1)
#define TSADC_AUTO_CON_AUTO_EN (1 << 0)
#define TSADC_INT_EN 0x0008
+#define TSADC_INT_EN_TSHUT_2CRU_EN_SRC3 (1 << 11)
+#define TSADC_INT_EN_TSHUT_2CRU_EN_SRC2 (1 << 10)
#define TSADC_INT_EN_TSHUT_2CRU_EN_SRC1 (1 << 9)
#define TSADC_INT_EN_TSHUT_2CRU_EN_SRC0 (1 << 8)
+#define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC3 (1 << 7)
+#define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC2 (1 << 6)
#define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC1 (1 << 5)
#define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0 (1 << 4)
#define TSADC_INT_PD 0x000c
#define TSADC_DATA0 0x0020
#define TSADC_DATA1 0x0024
+#define TSADC_DATA2 0x0028
+#define TSADC_DATA3 0x002c
#define TSADC_COMP0_INT 0x0030
#define TSADC_COMP1_INT 0x0034
+#define TSADC_COMP2_INT 0x0038
+#define TSADC_COMP3_INT 0x003c
#define TSADC_COMP0_SHUT 0x0040
#define TSADC_COMP1_SHUT 0x0044
+#define TSADC_COMP2_SHUT 0x0048
+#define TSADC_COMP3_SHUT 0x004c
#define TSADC_AUTO_PERIOD 0x0068
#define TSADC_AUTO_PERIOD_HT 0x006c
#define HWRITE4(sc, reg, val) \
bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
+struct rktemp_entry {
+ int32_t temp;
+ int32_t code;
+};
+
+/* RK3288 conversion table. */
+struct rktemp_entry rk3288_temps[] = {
+ { -40000, 3800 },
+ { -35000, 3792 },
+ { -30000, 3783 },
+ { -25000, 3774 },
+ { -20000, 3765 },
+ { -15000, 3756 },
+ { -10000, 3747 },
+ { -5000, 3737 },
+ { 0, 3728 },
+ { 5000, 3718 },
+ { 10000, 3708 },
+ { 15000, 3698 },
+ { 20000, 3688 },
+ { 25000, 3678 },
+ { 30000, 3667 },
+ { 35000, 3656 },
+ { 40000, 3645 },
+ { 45000, 3634 },
+ { 50000, 3623 },
+ { 55000, 3611 },
+ { 60000, 3600 },
+ { 65000, 3588 },
+ { 70000, 3575 },
+ { 75000, 3563 },
+ { 80000, 3550 },
+ { 85000, 3537 },
+ { 90000, 3524 },
+ { 95000, 3510 },
+ { 100000, 3496 },
+ { 105000, 3482 },
+ { 110000, 3467 },
+ { 115000, 3452 },
+ { 120000, 3437 },
+ { 125000, 3421 },
+};
+
+const char *rk3288_names[] = { "", "CPU", "GPU" };
+
+/* RK3399 conversion table. */
+struct rktemp_entry rk3399_temps[] = {
+ { -40000, 402 },
+ { -35000, 410 },
+ { -30000, 419 },
+ { -25000, 427 },
+ { -20000, 436 },
+ { -15000, 444 },
+ { -10000, 453 },
+ { -5000, 461 },
+ { 0, 470 },
+ { 5000, 478 },
+ { 10000, 487 },
+ { 15000, 496 },
+ { 20000, 504 },
+ { 25000, 513 },
+ { 30000, 521 },
+ { 35000, 530 },
+ { 40000, 538 },
+ { 45000, 547 },
+ { 50000, 555 },
+ { 55000, 564 },
+ { 60000, 573 },
+ { 65000, 581 },
+ { 70000, 590 },
+ { 75000, 599 },
+ { 80000, 607 },
+ { 85000, 616 },
+ { 90000, 624 },
+ { 95000, 633 },
+ { 100000, 642 },
+ { 105000, 650 },
+ { 110000, 659 },
+ { 115000, 668 },
+ { 120000, 677 },
+ { 125000, 685 },
+};
+
+const char *rk3399_names[] = { "CPU", "GPU" };
+
struct rktemp_softc {
struct device sc_dev;
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
- struct ksensor sc_sensors[2];
+ struct rktemp_entry *sc_temps;
+ int sc_ntemps;
+
+ struct ksensor sc_sensors[3];
+ int sc_nsensors;
struct ksensordev sc_sensordev;
};
NULL, "rktemp", DV_DULL
};
-uint32_t rktemp_calc_code(int32_t);
-int32_t rktemp_calc_temp(uint32_t);
-int rktemp_valid(uint32_t);
+int32_t rktemp_calc_code(struct rktemp_softc *, int32_t);
+int32_t rktemp_calc_temp(struct rktemp_softc *, int32_t);
+int rktemp_valid(struct rktemp_softc *, int32_t);
void rktemp_refresh_sensors(void *);
int
{
struct fdt_attach_args *faa = aux;
- return (OF_is_compatible(faa->fa_node, "rockchip,rk3399-tsadc"));
+ return (OF_is_compatible(faa->fa_node, "rockchip,rk3288-tsadc") ||
+ OF_is_compatible(faa->fa_node, "rockchip,rk3399-tsadc"));
}
void
{
struct rktemp_softc *sc = (struct rktemp_softc *)self;
struct fdt_attach_args *faa = aux;
+ const char **names;
uint32_t mode, polarity, temp;
uint32_t auto_con, int_en;
int node = faa->fa_node;
+ int i;
if (faa->fa_nreg < 1) {
printf(": no registers\n");
printf("\n");
+ if (OF_is_compatible(node, "rockchip,rk3288-tsadc")) {
+ sc->sc_temps = rk3288_temps;
+ sc->sc_ntemps = nitems(rk3288_temps);
+ sc->sc_nsensors = 3;
+ names = rk3288_names;
+ } else {
+ sc->sc_temps = rk3399_temps;
+ sc->sc_ntemps = nitems(rk3399_temps);
+ sc->sc_nsensors = 2;
+ names = rk3399_names;
+ }
+
pinctrl_byname(node, "init");
clock_enable(node, "tsadc");
/* Configure mode. */
int_en = HREAD4(sc, TSADC_INT_EN);
- if (mode) {
- int_en |= TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0;
- int_en |= TSADC_INT_EN_TSHUT_2GPIO_EN_SRC1;
- } else {
- int_en |= TSADC_INT_EN_TSHUT_2CRU_EN_SRC0;
- int_en |= TSADC_INT_EN_TSHUT_2CRU_EN_SRC1;
+ for (i = 0; i < sc->sc_nsensors; i++) {
+ if (mode)
+ int_en |= (TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0 << i);
+ else
+ int_en |= (TSADC_INT_EN_TSHUT_2CRU_EN_SRC0 << i);
}
HWRITE4(sc, TSADC_INT_EN, int_en);
/* Set shutdown limit. */
- HWRITE4(sc, TSADC_COMP0_SHUT, rktemp_calc_code(temp));
- auto_con |= TSADC_AUTO_CON_SRC0_EN;
- HWRITE4(sc, TSADC_COMP1_SHUT, rktemp_calc_code(temp));
- auto_con |= TSADC_AUTO_CON_SRC1_EN;
+ for (i = 0; i < sc->sc_nsensors; i++) {
+ HWRITE4(sc, TSADC_COMP0_SHUT + i * 4,
+ rktemp_calc_code(sc, temp));
+ auto_con |= (TSADC_AUTO_CON_SRC0_EN << i);
+ }
HWRITE4(sc, TSADC_AUTO_CON, auto_con);
pinctrl_byname(faa->fa_node, "default");
/* Register sensors. */
strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
sizeof(sc->sc_sensordev.xname));
- strlcpy(sc->sc_sensors[0].desc, "CPU", sizeof(sc->sc_sensors[0].desc));
- sc->sc_sensors[0].type = SENSOR_TEMP;
- sc->sc_sensors[0].flags = SENSOR_FINVALID;
- sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[0]);
- strlcpy(sc->sc_sensors[1].desc, "GPU", sizeof(sc->sc_sensors[1].desc));
- sc->sc_sensors[1].type = SENSOR_TEMP;
- sc->sc_sensors[1].flags = SENSOR_FINVALID;
- sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[1]);
+ for (i = 0; i < sc->sc_nsensors; i++) {
+ strlcpy(sc->sc_sensors[i].desc, names[i],
+ sizeof(sc->sc_sensors[i].desc));
+ sc->sc_sensors[i].type = SENSOR_TEMP;
+ sc->sc_sensors[i].flags = SENSOR_FINVALID;
+ sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
+ }
sensordev_install(&sc->sc_sensordev);
sensor_task_register(sc, rktemp_refresh_sensors, 5);
}
-struct rktemp_table_entry {
- int32_t temp;
- uint32_t code;
-};
-
-/* RK3399 conversion table. */
-struct rktemp_table_entry rktemp_table[] = {
- { -40000, 402 },
- { -35000, 410 },
- { -30000, 419 },
- { -25000, 427 },
- { -20000, 436 },
- { -15000, 444 },
- { -10000, 453 },
- { -5000, 461 },
- { 0, 470 },
- { 5000, 478 },
- { 10000, 487 },
- { 15000, 496 },
- { 20000, 504 },
- { 25000, 513 },
- { 30000, 521 },
- { 35000, 530 },
- { 40000, 538 },
- { 45000, 547 },
- { 50000, 555 },
- { 55000, 564 },
- { 60000, 573 },
- { 65000, 581 },
- { 70000, 590 },
- { 75000, 599 },
- { 80000, 607 },
- { 85000, 616 },
- { 90000, 624 },
- { 95000, 633 },
- { 100000, 642 },
- { 105000, 650 },
- { 110000, 659 },
- { 115000, 668 },
- { 120000, 677 },
- { 125000, 685 }
-};
-
-uint32_t
-rktemp_calc_code(int32_t temp)
+int32_t
+rktemp_calc_code(struct rktemp_softc *sc, int32_t temp)
{
- const int n = nitems(rktemp_table);
- uint32_t code0, delta_code;
+ const int n = sc->sc_ntemps;
+ int32_t code0, delta_code;
int32_t temp0, delta_temp;
int i;
- if (temp <= rktemp_table[0].temp)
- return rktemp_table[0].code;
- if (temp >= rktemp_table[n - 1].temp)
- return rktemp_table[n - 1].code;
+ if (temp <= sc->sc_temps[0].temp)
+ return sc->sc_temps[0].code;
+ if (temp >= sc->sc_temps[n - 1].temp)
+ return sc->sc_temps[n - 1].code;
for (i = 1; i < n; i++) {
- if (temp < rktemp_table[i].temp)
+ if (temp < sc->sc_temps[i].temp)
break;
}
- code0 = rktemp_table[i - 1].code;
- temp0 = rktemp_table[i - 1].temp;
- delta_code = rktemp_table[i].code - code0;
- delta_temp = rktemp_table[i].temp - temp0;
+ code0 = sc->sc_temps[i - 1].code;
+ temp0 = sc->sc_temps[i - 1].temp;
+ delta_code = sc->sc_temps[i].code - code0;
+ delta_temp = sc->sc_temps[i].temp - temp0;
return code0 + (temp - temp0) * delta_code / delta_temp;
}
int32_t
-rktemp_calc_temp(uint32_t code)
+rktemp_calc_temp(struct rktemp_softc *sc, int32_t code)
{
- const int n = nitems(rktemp_table);
- uint32_t code0, delta_code;
+ const int n = sc->sc_ntemps;
+ int32_t code0, delta_code;
int32_t temp0, delta_temp;
int i;
- if (code <= rktemp_table[0].code)
- return rktemp_table[0].temp;
- if (code >= rktemp_table[n - 1].code)
- return rktemp_table[n - 1].temp;
-
- for (i = 1; i < n; i++) {
- if (code < rktemp_table[i].code)
- break;
+ /* Handle both negative and postive temperature coefficients. */
+ if (sc->sc_temps[0].code > sc->sc_temps[1].code) {
+ if (code >= sc->sc_temps[0].code)
+ return sc->sc_temps[0].code;
+ if (code <= sc->sc_temps[n - 1].code)
+ return sc->sc_temps[n - 1].temp;
+
+ for (i = 1; i < n; i++) {
+ if (code > sc->sc_temps[i].code)
+ break;
+ }
+ } else {
+ if (code <= sc->sc_temps[0].code)
+ return sc->sc_temps[0].temp;
+ if (code >= sc->sc_temps[n - 1].code)
+ return sc->sc_temps[n - 1].temp;
+
+ for (i = 1; i < n; i++) {
+ if (code < sc->sc_temps[i].code)
+ break;
+ }
}
- code0 = rktemp_table[i - 1].code;
- temp0 = rktemp_table[i - 1].temp;
- delta_code = rktemp_table[i].code - code0;
- delta_temp = rktemp_table[i].temp - temp0;
+ code0 = sc->sc_temps[i - 1].code;
+ temp0 = sc->sc_temps[i - 1].temp;
+ delta_code = sc->sc_temps[i].code - code0;
+ delta_temp = sc->sc_temps[i].temp - temp0;
return temp0 + (code - code0) * delta_temp / delta_code;
}
int
-rktemp_valid(uint32_t code)
+rktemp_valid(struct rktemp_softc *sc, int32_t code)
{
- const int n = nitems(rktemp_table);
+ const int n = sc->sc_ntemps;
- if (code < rktemp_table[0].code)
- return 0;
- if (code > rktemp_table[n - 1].code)
- return 0;
+ if (sc->sc_temps[0].code > sc->sc_temps[1].code) {
+ if (code > sc->sc_temps[0].code)
+ return 0;
+ if (code < sc->sc_temps[n - 1].code)
+ return 0;
+ } else {
+ if (code < sc->sc_temps[0].code)
+ return 0;
+ if (code > sc->sc_temps[n - 1].code)
+ return 0;
+ }
return 1;
}
rktemp_refresh_sensors(void *arg)
{
struct rktemp_softc *sc = arg;
- uint32_t code;
-
- code = HREAD4(sc, TSADC_DATA0);
- sc->sc_sensors[0].value = 1000 * rktemp_calc_temp(code) + 273150000;
- if (rktemp_valid(code))
- sc->sc_sensors[0].flags &= ~SENSOR_FINVALID;
- else
- sc->sc_sensors[0].flags |= SENSOR_FINVALID;
-
- code = HREAD4(sc, TSADC_DATA1);
- sc->sc_sensors[1].value = 1000 * rktemp_calc_temp(code) + 273150000;
- if (rktemp_valid(code))
- sc->sc_sensors[1].flags &= ~SENSOR_FINVALID;
- else
- sc->sc_sensors[1].flags |= SENSOR_FINVALID;
+ int32_t code, temp;
+ int i;
+
+ for (i = 0; i < sc->sc_nsensors; i++) {
+ code = HREAD4(sc, TSADC_DATA0 + i * 4);
+ temp = rktemp_calc_temp(sc, code);
+ sc->sc_sensors[i].value = 273150000 + 1000 * temp;
+ if (rktemp_valid(sc, code))
+ sc->sc_sensors[i].flags &= ~SENSOR_FINVALID;
+ else
+ sc->sc_sensors[i].flags |= SENSOR_FINVALID;
+ }
}