-/* $OpenBSD: rktemp.c,v 1.12 2023/03/05 09:57:32 kettenis Exp $ */
+/* $OpenBSD: rktemp.c,v 1.13 2024/06/12 09:06:15 kettenis Exp $ */
/*
* Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
*
#define TSADC_USER_CON_INTER_PD_SOC_SHIFT 6
#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_SRC_EN(ch) (1 << ((ch) + 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_EN_TSHUT_2CRU_EN_SRC(ch) (1 << ((ch) + 8))
+#define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC(ch) (1 << ((ch) + 4))
#define TSADC_INT_PD 0x000c
-#define TSADC_INT_PD_TSHUT_O_SRC0 (1 << 4)
-#define TSADC_INT_PD_TSHUT_O_SRC1 (1 << 5)
-#define TSADC_INT_PD_TSHUT_O_SRC2 (1 << 6)
-#define TSADC_INT_PD_TSHUT_O_SRC3 (1 << 7)
-#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_INT_PD_TSHUT_O_SRC(ch) (1 << ((ch) + 4))
+#define TSADC_DATA(ch) (0x0020 + (ch) * 4)
+#define TSADC_COMP_INT(ch) (0x0030 + (ch) * 4)
+#define TSADC_COMP_SHUT(ch) (0x0040 + (ch) * 4)
#define TSADC_HIGHT_INT_DEBOUNCE 0x0060
#define TSADC_HIGHT_TSHUT_DEBOUNCE 0x0064
#define TSADC_AUTO_PERIOD 0x0068
#define TSADC_AUTO_PERIOD_HT 0x006c
+/* RK3588 */
+#define TSADC_V3_AUTO_SRC 0x000c
+#define TSADC_V3_AUTO_SRC_CH(ch) (1 << (ch))
+#define TSADC_V3_GPIO_EN 0x0018
+#define TSADC_V3_GPIO_EN_CH(ch) (1 << (ch))
+#define TSADC_V3_CRU_EN 0x001c
+#define TSADC_V3_CRU_EN_CH(ch) (1 << (ch))
+#define TSADC_V3_HLT_INT_PD 0x0024
+#define TSADC_V3_HT_INT_STATUS(ch) (1 << (ch))
+#define TSADC_V3_DATA(ch) (0x002c + (ch) * 4)
+#define TSADC_V3_COMP_SHUT(ch) (0x010c + (ch) * 4)
+#define TSADC_V3_HIGHT_INT_DEBOUNCE 0x014c
+#define TSADC_V3_HIGHT_TSHUT_DEBOUNCE 0x0150
+#define TSADC_V3_AUTO_PERIOD 0x0154
+#define TSADC_V3_AUTO_PERIOD_HT 0x0158
+
/* RK3568 */
#define RK3568_GRF_TSADC_CON 0x0600
#define RK3568_GRF_TSADC_EN (1 << 8)
const char *const rk3568_names[] = { "CPU", "GPU" };
+/* RK3588 conversion table. */
+const struct rktemp_entry rk3588_temps[] = {
+ { -40000, 215 },
+ { 25000, 285 },
+ { 85000, 350 },
+ { 125000, 395 },
+};
+
+const char *const rk3588_names[] = {
+ "Top",
+ "CPU (big0)",
+ "CPU (big1)",
+ "CPU (little)",
+ "Center",
+ "GPU",
+ "NPU"
+};
+
struct rktemp_softc {
struct device sc_dev;
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
int sc_node;
+ bus_size_t sc_data0;
+
const struct rktemp_entry *sc_temps;
int sc_ntemps;
- struct ksensor sc_sensors[3];
+ struct ksensor sc_sensors[7];
int sc_nsensors;
struct ksensordev sc_sensordev;
OF_is_compatible(faa->fa_node, "rockchip,rk3308-tsadc") ||
OF_is_compatible(faa->fa_node, "rockchip,rk3328-tsadc") ||
OF_is_compatible(faa->fa_node, "rockchip,rk3399-tsadc") ||
- OF_is_compatible(faa->fa_node, "rockchip,rk3568-tsadc"));
+ OF_is_compatible(faa->fa_node, "rockchip,rk3568-tsadc") ||
+ OF_is_compatible(faa->fa_node, "rockchip,rk3588-tsadc"));
}
void
struct fdt_attach_args *faa = aux;
const char *const *names;
uint32_t mode, polarity, temp;
- uint32_t auto_con, int_en;
- uint32_t inter_pd_soc;
+ uint32_t auto_con, inter_pd_soc;
int auto_period, auto_period_ht;
int i;
inter_pd_soc = 13;
auto_period = 1875; /* 2.5 ms */
auto_period_ht = 1875; /* 2.5 ms */
- } else {
+ } else if (OF_is_compatible(sc->sc_node, "rockchip,rk3568-tsadc")) {
sc->sc_temps = rk3568_temps;
sc->sc_ntemps = nitems(rk3568_temps);
sc->sc_nsensors = 2;
inter_pd_soc = 63; /* 97 us */
auto_period = 1622; /* 2.5 ms */
auto_period_ht = 1622; /* 2.5 ms */
+ } else {
+ sc->sc_temps = rk3588_temps;
+ sc->sc_ntemps = nitems(rk3588_temps);
+ sc->sc_nsensors = 7;
+ names = rk3588_names;
+ inter_pd_soc = 0;
+ auto_period = 5000; /* 2.5 ms */
+ auto_period_ht = 5000; /* 2.5 ms */
}
pinctrl_byname(sc->sc_node, "init");
clock_enable(sc->sc_node, "apb_pclk");
/* Reset the TS-ADC controller block. */
- reset_assert(sc->sc_node, "tsadc-apb");
+ reset_assert_all(sc->sc_node);
delay(10);
- reset_deassert(sc->sc_node, "tsadc-apb");
+ reset_deassert_all(sc->sc_node);
mode = OF_getpropint(sc->sc_node, "rockchip,hw-tshut-mode", 1);
polarity = OF_getpropint(sc->sc_node, "rockchip,hw-tshut-polarity", 0);
temp = OF_getpropint(sc->sc_node, "rockchip,hw-tshut-temp", 95000);
- HWRITE4(sc, TSADC_USER_CON,
- inter_pd_soc << TSADC_USER_CON_INTER_PD_SOC_SHIFT);
- HWRITE4(sc, TSADC_AUTO_PERIOD, auto_period);
- HWRITE4(sc, TSADC_AUTO_PERIOD_HT, auto_period_ht);
- HWRITE4(sc, TSADC_HIGHT_INT_DEBOUNCE, 4);
- HWRITE4(sc, TSADC_HIGHT_TSHUT_DEBOUNCE, 4);
-
- if (OF_is_compatible(sc->sc_node, "rockchip,rk3568-tsadc"))
- rktemp_rk3568_init(sc);
-
- auto_con = HREAD4(sc, TSADC_AUTO_CON);
- auto_con |= TSADC_AUTO_CON_TSADC_Q_SEL;
- if (polarity)
- auto_con |= TSADC_AUTO_CON_TSHUT_POLARITY;
- HWRITE4(sc, TSADC_AUTO_CON, auto_con);
-
- /* Set shutdown limit. */
- 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);
+ if (OF_is_compatible(sc->sc_node, "rockchip,rk3588-tsadc")) {
+ uint32_t gpio_en, cru_en;
+
+ sc->sc_data0 = TSADC_V3_DATA(0);
+
+ HWRITE4(sc, TSADC_V3_AUTO_PERIOD, auto_period);
+ HWRITE4(sc, TSADC_V3_AUTO_PERIOD_HT, auto_period_ht);
+ HWRITE4(sc, TSADC_V3_HIGHT_INT_DEBOUNCE, 4);
+ HWRITE4(sc, TSADC_V3_HIGHT_TSHUT_DEBOUNCE, 4);
+
+ auto_con = TSADC_AUTO_CON_TSHUT_POLARITY << 16;
+ if (polarity)
+ auto_con = TSADC_AUTO_CON_TSHUT_POLARITY;
+ HWRITE4(sc, TSADC_AUTO_CON, auto_con);
+
+ /* Set shutdown limit. */
+ for (i = 0; i < sc->sc_nsensors; i++) {
+ HWRITE4(sc, TSADC_V3_COMP_SHUT(i),
+ rktemp_calc_code(sc, temp));
+ HWRITE4(sc, TSADC_V3_AUTO_SRC,
+ TSADC_V3_AUTO_SRC_CH(i) << 16 |
+ TSADC_V3_AUTO_SRC_CH(i));
+ }
- /* Clear shutdown output status. */
- for (i = 0; i < sc->sc_nsensors; i++)
- HWRITE4(sc, TSADC_INT_PD, (TSADC_INT_PD_TSHUT_O_SRC0 << i));
+ /* Clear shutdown output status. */
+ for (i = 0; i < sc->sc_nsensors; i++) {
+ HWRITE4(sc, TSADC_V3_HLT_INT_PD,
+ TSADC_V3_HT_INT_STATUS(i));
+ }
- /* Configure mode. */
- int_en = HREAD4(sc, TSADC_INT_EN);
- 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);
+ /* Configure mode. */
+ gpio_en = cru_en = 0;
+ for (i = 0; i < sc->sc_nsensors; i++) {
+ gpio_en |= TSADC_V3_GPIO_EN_CH(i) << 16;
+ cru_en |= TSADC_V3_CRU_EN_CH(i) << 16;
+ if (mode)
+ gpio_en |= TSADC_V3_GPIO_EN_CH(i);
+ else
+ cru_en |= TSADC_V3_CRU_EN_CH(i);
+ }
+ HWRITE4(sc, TSADC_V3_GPIO_EN, gpio_en);
+ HWRITE4(sc, TSADC_V3_CRU_EN, cru_en);
+ } else {
+ uint32_t int_en;
+
+ sc->sc_data0 = TSADC_DATA(0);
+
+ HWRITE4(sc, TSADC_USER_CON,
+ inter_pd_soc << TSADC_USER_CON_INTER_PD_SOC_SHIFT);
+ HWRITE4(sc, TSADC_AUTO_PERIOD, auto_period);
+ HWRITE4(sc, TSADC_AUTO_PERIOD_HT, auto_period_ht);
+ HWRITE4(sc, TSADC_HIGHT_INT_DEBOUNCE, 4);
+ HWRITE4(sc, TSADC_HIGHT_TSHUT_DEBOUNCE, 4);
+
+ if (OF_is_compatible(sc->sc_node, "rockchip,rk3568-tsadc"))
+ rktemp_rk3568_init(sc);
+
+ auto_con = HREAD4(sc, TSADC_AUTO_CON);
+ auto_con |= TSADC_AUTO_CON_TSADC_Q_SEL;
+ if (polarity)
+ auto_con |= TSADC_AUTO_CON_TSHUT_POLARITY;
+ HWRITE4(sc, TSADC_AUTO_CON, auto_con);
+
+ /* Set shutdown limit. */
+ for (i = 0; i < sc->sc_nsensors; i++) {
+ HWRITE4(sc, TSADC_COMP_SHUT(i),
+ rktemp_calc_code(sc, temp));
+ auto_con |= (TSADC_AUTO_CON_SRC_EN(i));
+ }
+ HWRITE4(sc, TSADC_AUTO_CON, auto_con);
+
+ /* Clear shutdown output status. */
+ for (i = 0; i < sc->sc_nsensors; i++)
+ HWRITE4(sc, TSADC_INT_PD, TSADC_INT_PD_TSHUT_O_SRC(i));
+
+ /* Configure mode. */
+ int_en = HREAD4(sc, TSADC_INT_EN);
+ for (i = 0; i < sc->sc_nsensors; i++) {
+ if (mode)
+ int_en |= TSADC_INT_EN_TSHUT_2GPIO_EN_SRC(i);
+ else
+ int_en |= TSADC_INT_EN_TSHUT_2CRU_EN_SRC(i);
+ }
+ HWRITE4(sc, TSADC_INT_EN, int_en);
}
- HWRITE4(sc, TSADC_INT_EN, int_en);
pinctrl_byname(sc->sc_node, "default");
/* Finally turn on the ADC. */
- auto_con |= TSADC_AUTO_CON_AUTO_EN;
- HWRITE4(sc, TSADC_AUTO_CON, auto_con);
+ if (OF_is_compatible(sc->sc_node, "rockchip,rk3588-tsadc")) {
+ HWRITE4(sc, TSADC_AUTO_CON,
+ TSADC_AUTO_CON_AUTO_EN << 16 | TSADC_AUTO_CON_AUTO_EN);
+ } else {
+ auto_con |= TSADC_AUTO_CON_AUTO_EN;
+ HWRITE4(sc, TSADC_AUTO_CON, auto_con);
+ }
/* Register sensors. */
strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
int i;
for (i = 0; i < sc->sc_nsensors; i++) {
- code = HREAD4(sc, TSADC_DATA0 + i * 4);
+ code = HREAD4(sc, sc->sc_data0 + (i * 4));
temp = rktemp_calc_temp(sc, code);
sc->sc_sensors[i].value = 273150000 + 1000 * temp;
if (rktemp_valid(sc, code))
if (idx >= sc->sc_nsensors)
return THERMAL_SENSOR_MAX;
- code = HREAD4(sc, TSADC_DATA0 + idx * 4);
+ code = HREAD4(sc, sc->sc_data0 + (idx * 4));
if (rktemp_valid(sc, code))
return rktemp_calc_temp(sc, code);
else