Index | Thread | Search

From:
Mark Kettenis <mark.kettenis@xs4all.nl>
Subject:
rktemp(4): Add RK3588 support
To:
patrick@openbsd.org, dlg@openbsd.org, jmatthew@openbsd.org, mlarkin@openbsd.org, kurt@openbsd.org
Cc:
tech@openbsd.org
Date:
Tue, 11 Jun 2024 11:38:28 +0200

Download raw body.

Thread
The TSADC block of the RK3588 SoC has some significant differences
from earlier SoCs.  While implementing support for this new SoC, I
adjusted the existing code for the older SoCs a bit, so this needs
testing on older Rockchip SoCs as well.

This makes the sensors available, but isn't enough to make the thermal
zones function as those depend on functioning interrupts for trip
points.  That is probably true for some of the older SoCs as well.
I'd like to address that in a follow-up diff.

ok?

Index: dev/fdt/rktemp.c
===================================================================
RCS file: /cvs/src/sys/dev/fdt/rktemp.c,v
retrieving revision 1.12
diff -u -p -r1.12 rktemp.c
--- dev/fdt/rktemp.c	5 Mar 2023 09:57:32 -0000	1.12
+++ dev/fdt/rktemp.c	11 Jun 2024 09:30:43 -0000
@@ -36,43 +36,38 @@
 #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)
@@ -248,16 +243,36 @@ const struct rktemp_entry rk3568_temps[]
 
 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;
 
@@ -291,7 +306,8 @@ rktemp_match(struct device *parent, void
 	    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
@@ -301,8 +317,7 @@ rktemp_attach(struct device *parent, str
 	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;
 
@@ -354,7 +369,7 @@ rktemp_attach(struct device *parent, str
 		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;
@@ -362,6 +377,14 @@ rktemp_attach(struct device *parent, str
 		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");
@@ -371,57 +394,110 @@ rktemp_attach(struct device *parent, str
 	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);
+	if (OF_is_compatible(sc->sc_node, "rockchip,rk3588-tsadc")) {
+		uint32_t gpio_en, cru_en;
 
-	/* 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);
-
-	/* Clear shutdown output status. */
-	for (i = 0; i < sc->sc_nsensors; i++)
-		HWRITE4(sc, TSADC_INT_PD, (TSADC_INT_PD_TSHUT_O_SRC0 << i));
+		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));
+		}
 
-	/* 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);
+		/* 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. */
+		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,
@@ -557,7 +633,7 @@ rktemp_refresh_sensors(void *arg)
 	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))
@@ -577,7 +653,7 @@ rktemp_get_temperature(void *cookie, uin
 	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