Created
September 6, 2024 20:17
-
-
Save macromorgan/745647bef36a33ad0aa294a3e4bda775 to your computer and use it in GitHub Desktop.
RGxx3 U-Boot Updates for 2024-09-06
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 21af290030161a3f8c8d6576dba1c5c3da3aca02 Mon Sep 17 00:00:00 2001 | |
From: Chris Morgan <[email protected]> | |
Date: Fri, 6 Sep 2024 15:11:57 -0500 | |
Subject: [PATCH 0/3] Anbernic RGxx3 Bootloader Fixes | |
Update the Anbernic RGxx3 "device" to use upstream device-trees, | |
add logic to detect a different vdd_cpu regulator, and implement a | |
fix to allow the panel auto-detection to run when using mainline | |
A-TF. | |
Chris Morgan (3): | |
board: rockchip: Convert Anbernic RGxx3 to OF_UPSTREAM | |
board: rockchip: Add vdd_cpu reg fixup for RGXX3 Series | |
board: rockchip: Fix panel detection logic for mainline A-TF | |
.../dts/rk3566-anbernic-rg353p-u-boot.dtsi | 75 ++++ | |
.../arm/dts/rk3566-anbernic-rgxx3-u-boot.dtsi | 52 --- | |
arch/arm/dts/rk3566-anbernic-rgxx3.dts | 28 -- | |
board/anbernic/rgxx3_rk3566/MAINTAINERS | 4 +- | |
board/anbernic/rgxx3_rk3566/rgxx3-rk3566.c | 337 +++++++++++++++--- | |
configs/anbernic-rgxx3-rk3566_defconfig | 16 +- | |
6 files changed, 367 insertions(+), 145 deletions(-) | |
create mode 100644 arch/arm/dts/rk3566-anbernic-rg353p-u-boot.dtsi | |
delete mode 100644 arch/arm/dts/rk3566-anbernic-rgxx3-u-boot.dtsi | |
delete mode 100644 arch/arm/dts/rk3566-anbernic-rgxx3.dts | |
-- | |
2.34.1 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From e682c8b9f7c1b776ab44fb8fad1d10d3c63599ca Mon Sep 17 00:00:00 2001 | |
From: Chris Morgan <[email protected]> | |
Date: Fri, 6 Sep 2024 15:03:06 -0500 | |
Subject: [PATCH 1/3] board: rockchip: Convert Anbernic RGxx3 to OF_UPSTREAM | |
Refactor the board detection logic (again) to make it compatible with | |
the upstream device-trees, and switch to OF_UPSTREAM. | |
Now the device boots with the device-tree for the 353P, and then | |
loads the correct device tree (of 10) in the later stages of SPL. | |
Signed-off-by: Chris Morgan <[email protected]> | |
--- | |
.../dts/rk3566-anbernic-rg353p-u-boot.dtsi | 75 ++++++++ | |
.../arm/dts/rk3566-anbernic-rgxx3-u-boot.dtsi | 52 ----- | |
arch/arm/dts/rk3566-anbernic-rgxx3.dts | 28 --- | |
board/anbernic/rgxx3_rk3566/MAINTAINERS | 4 +- | |
board/anbernic/rgxx3_rk3566/rgxx3-rk3566.c | 180 ++++++++++++------ | |
configs/anbernic-rgxx3-rk3566_defconfig | 13 +- | |
6 files changed, 209 insertions(+), 143 deletions(-) | |
create mode 100644 arch/arm/dts/rk3566-anbernic-rg353p-u-boot.dtsi | |
delete mode 100644 arch/arm/dts/rk3566-anbernic-rgxx3-u-boot.dtsi | |
delete mode 100644 arch/arm/dts/rk3566-anbernic-rgxx3.dts | |
diff --git a/arch/arm/dts/rk3566-anbernic-rg353p-u-boot.dtsi b/arch/arm/dts/rk3566-anbernic-rg353p-u-boot.dtsi | |
new file mode 100644 | |
index 0000000000..afb45da993 | |
--- /dev/null | |
+++ b/arch/arm/dts/rk3566-anbernic-rg353p-u-boot.dtsi | |
@@ -0,0 +1,75 @@ | |
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) | |
+ | |
+#include "rk356x-u-boot.dtsi" | |
+ | |
+/ { | |
+ chosen { | |
+ u-boot,spl-boot-order = &sdmmc0, &sdhci; | |
+ }; | |
+ | |
+ /* | |
+ * Adding fixed regulator to work around driver regulator | |
+ * requirements. Note that the correct regulator is on by | |
+ * default at boot and that saradc regulator gets corrected | |
+ * when proper device-tree is loaded. | |
+ */ | |
+ vcc_1v8_dummy: vcc-1v8-dummy { | |
+ bootph-pre-ram; | |
+ bootph-some-ram; | |
+ compatible = "regulator-fixed"; | |
+ regulator-always-on; | |
+ regulator-boot-on; | |
+ regulator-min-microvolt = <1800000>; | |
+ regulator-max-microvolt = <1800000>; | |
+ regulator-name = "vcc_1v8_dummy"; | |
+ status = "okay"; | |
+ }; | |
+}; | |
+ | |
+&i2c0 { | |
+ status = "okay"; | |
+ bootph-pre-ram; | |
+ bootph-some-ram; | |
+}; | |
+ | |
+&i2c0_xfer { | |
+ bootph-pre-ram; | |
+ bootph-some-ram; | |
+}; | |
+ | |
+&i2c2 { | |
+ pinctrl-0 = <&i2c2m1_xfer>; | |
+ pinctrl-names = "default"; | |
+ status = "okay"; | |
+ bootph-pre-ram; | |
+ bootph-some-ram; | |
+}; | |
+ | |
+&i2c2m1_xfer { | |
+ bootph-pre-ram; | |
+ bootph-some-ram; | |
+}; | |
+ | |
+&pmucru { | |
+ assigned-clocks = <&pmucru SCLK_32K_IOE>; | |
+ assigned-clock-parents = <&pmucru CLK_RTC_32K>; | |
+}; | |
+ | |
+&saradc { | |
+ bootph-pre-ram; | |
+ bootph-some-ram; | |
+ vref-supply = <&vcc_1v8_dummy>; | |
+ status = "okay"; | |
+}; | |
+ | |
+&sdhci { | |
+ pinctrl-0 = <&emmc_bus8>, <&emmc_clk>, <&emmc_cmd>, | |
+ <&emmc_datastrobe>, <&emmc_rstnout>; | |
+ pinctrl-names = "default"; | |
+ bus-width = <8>; | |
+ mmc-hs200-1_8v; | |
+ non-removable; | |
+ vmmc-supply = <&vcc_3v3>; | |
+ vqmmc-supply = <&vcc_1v8>; | |
+ status = "okay"; | |
+}; | |
diff --git a/arch/arm/dts/rk3566-anbernic-rgxx3-u-boot.dtsi b/arch/arm/dts/rk3566-anbernic-rgxx3-u-boot.dtsi | |
deleted file mode 100644 | |
index c7e849816a..0000000000 | |
--- a/arch/arm/dts/rk3566-anbernic-rgxx3-u-boot.dtsi | |
+++ /dev/null | |
@@ -1,52 +0,0 @@ | |
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT) | |
- | |
-#include "rk356x-u-boot.dtsi" | |
- | |
-/ { | |
- chosen { | |
- u-boot,spl-boot-order = &sdmmc0, &sdhci; | |
- }; | |
-}; | |
- | |
-&dsi_dphy0 { | |
- status = "okay"; | |
-}; | |
- | |
-&dsi0 { | |
- status = "okay"; | |
-}; | |
- | |
-&i2c2 { | |
- pinctrl-0 = <&i2c2m1_xfer>; | |
- pinctrl-names = "default"; | |
- status = "okay"; | |
-}; | |
- | |
-&pmucru { | |
- assigned-clocks = <&pmucru SCLK_32K_IOE>; | |
- assigned-clock-parents = <&pmucru CLK_RTC_32K>; | |
-}; | |
- | |
-/* | |
- * We don't need the clocks, but if they are present they may cause | |
- * probing to fail so we remove them for U-Boot. | |
- */ | |
-&rk817 { | |
- /delete-property/ assigned-clocks; | |
- /delete-property/ assigned-clock-parents; | |
- /delete-property/ clocks; | |
- /delete-property/ clock-names; | |
-}; | |
- | |
-&sdhci { | |
- pinctrl-0 = <&emmc_bus8>, <&emmc_clk>, <&emmc_cmd>, | |
- <&emmc_datastrobe>, <&emmc_rstnout>; | |
- pinctrl-names = "default"; | |
- bus-width = <8>; | |
- max-frequency = <200000000>; | |
- mmc-hs200-1_8v; | |
- non-removable; | |
- vmmc-supply = <&vcc_3v3>; | |
- vqmmc-supply = <&vcc_1v8>; | |
- status = "okay"; | |
-}; | |
diff --git a/arch/arm/dts/rk3566-anbernic-rgxx3.dts b/arch/arm/dts/rk3566-anbernic-rgxx3.dts | |
deleted file mode 100644 | |
index c393c8d07a..0000000000 | |
--- a/arch/arm/dts/rk3566-anbernic-rgxx3.dts | |
+++ /dev/null | |
@@ -1,28 +0,0 @@ | |
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT) | |
- | |
-/dts-v1/; | |
- | |
-#include "rk3566-anbernic-rgxx3.dtsi" | |
- | |
-/ { | |
- | |
-/* | |
- * Note this is a pseudo-model that doesn't exist in mainline Linux. | |
- * This model is used for all RGXX3 devices and the board.c file will | |
- * set the correct dtb name for loading mainline Linux automatically. | |
- */ | |
- model = "RGXX3"; | |
- compatible = "anbernic,rg-arc-d", "anbernic,rg-arc-s", | |
- "anbernic,rg353m", "anbernic,rg353p", | |
- "anbernic,rg353ps", "anbernic,rg353v", | |
- "anbernic,rg353vs", "anbernic,rg503", | |
- "powkiddy,rgb10max3", "powkiddy,rgb30", | |
- "powkiddy,rk2023", "rockchip,rk3566"; | |
-}; | |
- | |
-&cru { | |
- assigned-clocks = <&pmucru CLK_RTC_32K>, <&cru PLL_GPLL>, | |
- <&pmucru PLL_PPLL>, <&cru PLL_VPLL>; | |
- assigned-clock-rates = <32768>, <1200000000>, | |
- <200000000>, <241500000>; | |
-}; | |
diff --git a/board/anbernic/rgxx3_rk3566/MAINTAINERS b/board/anbernic/rgxx3_rk3566/MAINTAINERS | |
index 7970e5a4aa..75a1e8076c 100644 | |
--- a/board/anbernic/rgxx3_rk3566/MAINTAINERS | |
+++ b/board/anbernic/rgxx3_rk3566/MAINTAINERS | |
@@ -4,6 +4,4 @@ S: Maintained | |
F: board/anbernic/rgxx3_rk3566 | |
F: include/configs/anbernic-rgxx3-rk3566.h | |
F: configs/anbernic-rgxx3-rk3566_defconfig | |
-F: arch/arm/dts/rk3566-anbernic-rgxx3.dts | |
-F: arch/arm/dts/rk3566-anbernic-rgxx3.dtsi | |
-F: arch/arm/dts/rk3566-anbernic-rgxx3-u-boot.dtsi | |
+F: arch/arm/dts/rk3566-anbernic-rg353p-u-boot.dtsi | |
diff --git a/board/anbernic/rgxx3_rk3566/rgxx3-rk3566.c b/board/anbernic/rgxx3_rk3566/rgxx3-rk3566.c | |
index 5c57b902d1..e8ac181d81 100644 | |
--- a/board/anbernic/rgxx3_rk3566/rgxx3-rk3566.c | |
+++ b/board/anbernic/rgxx3_rk3566/rgxx3-rk3566.c | |
@@ -11,6 +11,7 @@ | |
#include <dm/lists.h> | |
#include <env.h> | |
#include <fdt_support.h> | |
+#include <i2c.h> | |
#include <linux/delay.h> | |
#include <mipi_dsi.h> | |
#include <mmc.h> | |
@@ -19,6 +20,8 @@ | |
#include <stdlib.h> | |
#include <video_bridge.h> | |
+DECLARE_GLOBAL_DATA_PTR; | |
+ | |
#define GPIO0_BASE 0xfdd60000 | |
#define GPIO4_BASE 0xfe770000 | |
#define GPIO_SWPORT_DR_L 0x0000 | |
@@ -43,7 +46,7 @@ struct rg3xx_model { | |
}; | |
enum rgxx3_device_id { | |
- RG353M, | |
+ RG353M = 1, | |
RG353P, | |
RG353V, | |
RG503, | |
@@ -61,7 +64,7 @@ static const struct rg3xx_model rg3xx_model_details[] = { | |
[RG353M] = { | |
.adc_value = 517, /* Observed average from device */ | |
.board = "rk3566-anbernic-rg353m", | |
- .board_name = "RG353M", | |
+ .board_name = "Anbernic RG353M", | |
/* Device is identical to RG353P. */ | |
.fdtfile = DTB_DIR "rk3566-anbernic-rg353p.dtb", | |
.detect_panel = 1, | |
@@ -69,35 +72,35 @@ static const struct rg3xx_model rg3xx_model_details[] = { | |
[RG353P] = { | |
.adc_value = 860, /* Documented value of 860 */ | |
.board = "rk3566-anbernic-rg353p", | |
- .board_name = "RG353P", | |
+ .board_name = "Anbernic RG353P", | |
.fdtfile = DTB_DIR "rk3566-anbernic-rg353p.dtb", | |
.detect_panel = 1, | |
}, | |
[RG353V] = { | |
.adc_value = 695, /* Observed average from device */ | |
.board = "rk3566-anbernic-rg353v", | |
- .board_name = "RG353V", | |
+ .board_name = "Anbernic RG353V", | |
.fdtfile = DTB_DIR "rk3566-anbernic-rg353v.dtb", | |
.detect_panel = 1, | |
}, | |
[RG503] = { | |
.adc_value = 1023, /* Observed average from device */ | |
.board = "rk3566-anbernic-rg503", | |
- .board_name = "RG503", | |
+ .board_name = "Anbernic RG503", | |
.fdtfile = DTB_DIR "rk3566-anbernic-rg503.dtb", | |
.detect_panel = 0, | |
}, | |
[RGB30] = { | |
.adc_value = 383, /* Gathered from second hand information */ | |
.board = "rk3566-powkiddy-rgb30", | |
- .board_name = "RGB30", | |
+ .board_name = "Powkiddy RGB30", | |
.fdtfile = DTB_DIR "rk3566-powkiddy-rgb30.dtb", | |
.detect_panel = 0, | |
}, | |
[RK2023] = { | |
.adc_value = 635, /* Observed average from device */ | |
.board = "rk3566-powkiddy-rk2023", | |
- .board_name = "RK2023", | |
+ .board_name = "Powkiddy RK2023", | |
.fdtfile = DTB_DIR "rk3566-powkiddy-rk2023.dtb", | |
.detect_panel = 0, | |
}, | |
@@ -119,14 +122,14 @@ static const struct rg3xx_model rg3xx_model_details[] = { | |
[RG353PS] = { | |
.adc_value = 860, /* Observed average from device */ | |
.board = "rk3566-anbernic-rg353ps", | |
- .board_name = "RG353PS", | |
+ .board_name = "Anbernic RG353PS", | |
.fdtfile = DTB_DIR "rk3566-anbernic-rg353ps.dtb", | |
.detect_panel = 1, | |
}, | |
[RG353VS] = { | |
.adc_value = 695, /* Gathered from second hand information */ | |
.board = "rk3566-anbernic-rg353vs", | |
- .board_name = "RG353VS", | |
+ .board_name = "Anbernic RG353VS", | |
.fdtfile = DTB_DIR "rk3566-anbernic-rg353vs.dtb", | |
.detect_panel = 1, | |
}, | |
@@ -164,7 +167,7 @@ static const struct rg353_panel rg353_panel_details[] = { | |
void spl_board_init(void) | |
{ | |
/* Set GPIO0_C5, GPIO0_C6, and GPIO0_C7 to output. */ | |
- writel(GPIO_WRITEMASK(GPIO_C7 | GPIO_C6 | GPIO_C5) | \ | |
+ writel(GPIO_WRITEMASK(GPIO_C7 | GPIO_C6 | GPIO_C5) | | |
(GPIO_C7 | GPIO_C6 | GPIO_C5), | |
(GPIO0_BASE + GPIO_SWPORT_DDR_H)); | |
/* Set GPIO0_C5 and GPIO_C6 to 0 and GPIO0_C7 to 1. */ | |
@@ -181,7 +184,9 @@ void __maybe_unused startup_buzz(void) | |
struct udevice *dev; | |
int err; | |
- err = uclass_get_device(UCLASS_PWM, 0, &dev); | |
+ /* Probe the PWM controller. */ | |
+ err = uclass_get_device_by_name(UCLASS_PWM, | |
+ "pwm@fe6e0010", &dev); | |
if (err) | |
printf("pwm not found\n"); | |
@@ -245,6 +250,13 @@ U_BOOT_DRIVER(anbernic_rg353_panel) = { | |
.plat_auto = sizeof(struct mipi_dsi_panel_plat), | |
}; | |
+/* | |
+ * The Anbernic 353 series shipped with 2 distinct displays requiring | |
+ * 2 distinct drivers, with no way for a user to know which panel is | |
+ * which. This function queries the DSI panel for the panel ID to | |
+ * determine which panel is present so the device-tree can be corrected | |
+ * automatically. | |
+ */ | |
int rgxx3_detect_display(void) | |
{ | |
struct udevice *dev; | |
@@ -333,17 +345,10 @@ int rgxx3_detect_display(void) | |
return 0; | |
} | |
-/* Detect which Anbernic RGXX3 device we are using so as to load the | |
- * correct devicetree for Linux. Set an environment variable once | |
- * found. The detection depends on the value of ADC channel 1, the | |
- * presence of an eMMC on mmc0, and querying the DSI panel. | |
- */ | |
-int rgxx3_detect_device(void) | |
+int rgxx3_read_board_id(void) | |
{ | |
u32 adc_info; | |
- int ret, i; | |
- int board_id = -ENXIO; | |
- struct mmc *mmc; | |
+ int ret; | |
ret = adc_channel_single_shot("saradc@fe720000", 1, &adc_info); | |
if (ret) { | |
@@ -357,16 +362,32 @@ int rgxx3_detect_device(void) | |
* design calls for no more than a 1% variance on the | |
* resistor, so assume a +- value of 15 should be enough. | |
*/ | |
- for (i = 0; i < ARRAY_SIZE(rg3xx_model_details); i++) { | |
+ for (int i = 0; i < ARRAY_SIZE(rg3xx_model_details); i++) { | |
u32 adc_min = rg3xx_model_details[i].adc_value - 15; | |
u32 adc_max = rg3xx_model_details[i].adc_value + 15; | |
- if (adc_min < adc_info && adc_max > adc_info) { | |
- board_id = i; | |
- break; | |
- } | |
+ if (adc_min < adc_info && adc_max > adc_info) | |
+ return i; | |
} | |
+ return -ENODEV; | |
+} | |
+ | |
+/* Detect which Anbernic RGXX3 device we are using so as to load the | |
+ * correct devicetree for Linux. Set an environment variable once | |
+ * found. The detection depends on the value of ADC channel 1 and the | |
+ * presence of an eMMC on mmc0. | |
+ */ | |
+int rgxx3_detect_device(void) | |
+{ | |
+ int ret; | |
+ int board_id; | |
+ struct mmc *mmc; | |
+ | |
+ board_id = rgxx3_read_board_id(); | |
+ if (board_id < 0) | |
+ return board_id; | |
+ | |
/* | |
* Try to access the eMMC on an RG353V, RG353P, or RG Arc D. | |
* If it's missing, it's an RG353VS, RG353PS, or RG Arc S. | |
@@ -387,36 +408,62 @@ int rgxx3_detect_device(void) | |
} | |
} | |
- if (board_id < 0) | |
- return board_id; | |
+ return board_id; | |
+} | |
- env_set("board", rg3xx_model_details[board_id].board); | |
- env_set("board_name", | |
- rg3xx_model_details[board_id].board_name); | |
- env_set("fdtfile", rg3xx_model_details[board_id].fdtfile); | |
+/* Check the loaded device tree to set the correct gd->board_type. */ | |
+int set_gd_value(void) | |
+{ | |
+ const char *model; | |
- /* Skip panel detection for when it is not needed. */ | |
- if (!rg3xx_model_details[board_id].detect_panel) | |
- return 0; | |
+ model = fdt_getprop(gd->fdt_blob, 0, "model", NULL); | |
- /* Warn but don't fail for errors in auto-detection of the panel. */ | |
- ret = rgxx3_detect_display(); | |
- if (ret) | |
- printf("Failed to detect panel type\n"); | |
+ for (int i = 0; i < ARRAY_SIZE(rg3xx_model_details); i++) { | |
+ if (strcmp(rg3xx_model_details[i].board_name, model) == 0) { | |
+ gd->board_type = i; | |
+ return 0; | |
+ } | |
+ } | |
- return 0; | |
+ return -ENODEV; | |
} | |
int rk_board_late_init(void) | |
{ | |
int ret; | |
- ret = rgxx3_detect_device(); | |
+ ret = set_gd_value(); | |
if (ret) { | |
- printf("Unable to detect device type: %d\n", ret); | |
- return ret; | |
+ printf("Unable to auto-detect device\n"); | |
+ goto end; | |
} | |
+ /* | |
+ * Change the model number on the RG353M since it uses the same | |
+ * tree as the RG353P. | |
+ */ | |
+ if (gd->board_type == RG353P) { | |
+ ret = rgxx3_read_board_id(); | |
+ if (ret > 0) | |
+ gd->board_type = ret; | |
+ } | |
+ | |
+ env_set("board", rg3xx_model_details[gd->board_type].board); | |
+ env_set("board_name", | |
+ rg3xx_model_details[gd->board_type].board_name); | |
+ env_set("fdtfile", rg3xx_model_details[gd->board_type].fdtfile); | |
+ | |
+ /* | |
+ * Skip panel detection if not needed. Warn but don't fail for | |
+ * errors in auto-detection of the panel. | |
+ */ | |
+ if (rg3xx_model_details[gd->board_type].detect_panel) { | |
+ ret = rgxx3_detect_display(); | |
+ if (ret) | |
+ printf("Failed to detect panel type\n"); | |
+ } | |
+ | |
+end: | |
/* Turn off red LED and turn on orange LED. */ | |
writel(GPIO_WRITEMASK(GPIO_C7 | GPIO_C6 | GPIO_C5) | GPIO_C6, | |
(GPIO0_BASE + GPIO_SWPORT_DR_H)); | |
@@ -427,27 +474,16 @@ int rk_board_late_init(void) | |
return 0; | |
} | |
-int ft_board_setup(void *blob, struct bd_info *bd) | |
+int rgxx3_panel_fixup(void *blob) | |
{ | |
const struct rg353_panel *panel = NULL; | |
- int node, ret, i; | |
+ int node, ret; | |
char *env; | |
- /* No fixups necessary for the RG503 */ | |
- env = env_get("board_name"); | |
- if (env && (!strcmp(env, rg3xx_model_details[RG503].board_name))) | |
- return 0; | |
- | |
- /* Change the model name of the RG353M */ | |
- if (env && (!strcmp(env, rg3xx_model_details[RG353M].board_name))) | |
- fdt_setprop(blob, 0, "model", | |
- rg3xx_model_details[RG353M].board_name, | |
- sizeof(rg3xx_model_details[RG353M].board_name)); | |
- | |
env = env_get("panel"); | |
if (!env) { | |
printf("Can't get panel env\n"); | |
- return 0; | |
+ return -EINVAL; | |
} | |
/* | |
@@ -469,7 +505,7 @@ int ft_board_setup(void *blob, struct bd_info *bd) | |
return 0; | |
/* Panels don't match, search by first compatible value. */ | |
- for (i = 0; i < ARRAY_SIZE(rg353_panel_details); i++) { | |
+ for (int i = 0; i < ARRAY_SIZE(rg353_panel_details); i++) { | |
if (!strcmp(env, rg353_panel_details[i].panel_compat[0])) { | |
panel = &rg353_panel_details[i]; | |
break; | |
@@ -489,3 +525,33 @@ int ft_board_setup(void *blob, struct bd_info *bd) | |
return 0; | |
} | |
+ | |
+int ft_board_setup(void *blob, struct bd_info *bd) | |
+{ | |
+ int ret; | |
+ | |
+ if (rg3xx_model_details[gd->board_type].detect_panel) { | |
+ ret = rgxx3_panel_fixup(blob); | |
+ if (ret) | |
+ printf("Unable to update panel compat\n"); | |
+ } | |
+ | |
+ return 0; | |
+} | |
+ | |
+int board_fit_config_name_match(const char *name) | |
+{ | |
+ int ret; | |
+ | |
+ if (gd->board_type == 0) { | |
+ ret = rgxx3_detect_device(); | |
+ if (ret < 0) | |
+ return ret; | |
+ gd->board_type = ret; | |
+ } | |
+ | |
+ if (strcmp(name, rg3xx_model_details[gd->board_type].fdtfile) == 0) | |
+ return 0; | |
+ | |
+ return -ENXIO; | |
+} | |
diff --git a/configs/anbernic-rgxx3-rk3566_defconfig b/configs/anbernic-rgxx3-rk3566_defconfig | |
index a03509bf46..81c0299894 100644 | |
--- a/configs/anbernic-rgxx3-rk3566_defconfig | |
+++ b/configs/anbernic-rgxx3-rk3566_defconfig | |
@@ -3,7 +3,7 @@ CONFIG_SKIP_LOWLEVEL_INIT=y | |
CONFIG_COUNTER_FREQUENCY=24000000 | |
CONFIG_ARCH_ROCKCHIP=y | |
CONFIG_SPL_GPIO=y | |
-CONFIG_DEFAULT_DEVICE_TREE="rk3566-anbernic-rgxx3" | |
+CONFIG_DEFAULT_DEVICE_TREE="rockchip/rk3566-anbernic-rg353p" | |
CONFIG_ROCKCHIP_RK3568=y | |
CONFIG_ROCKCHIP_RK8XX_DISABLE_BOOT_ON_POWERON=y | |
CONFIG_SPL_SERIAL=y | |
@@ -19,8 +19,9 @@ CONFIG_SPL_LOAD_FIT=y | |
CONFIG_LEGACY_IMAGE_FORMAT=y | |
CONFIG_OF_BOARD_SETUP=y | |
CONFIG_OF_STDOUT_VIA_ALIAS=y | |
-CONFIG_DEFAULT_FDT_FILE="rockchip/rk3566-anbernic-rgxx3.dtb" | |
+CONFIG_DEFAULT_FDT_FILE="rockchip/rk3566-anbernic-rg353p.dtb" | |
# CONFIG_CONSOLE_MUX is not set | |
+CONFIG_BOARD_TYPES=y | |
# CONFIG_DISPLAY_CPUINFO is not set | |
CONFIG_DISPLAY_BOARDINFO_LATE=y | |
CONFIG_BOARD_RNG_SEED=y | |
@@ -28,6 +29,7 @@ CONFIG_SPL_MAX_SIZE=0x40000 | |
CONFIG_SPL_PAD_TO=0x7f8000 | |
CONFIG_SPL_BOARD_INIT=y | |
# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set | |
+CONFIG_SPL_I2C=y | |
CONFIG_SPL_POWER=y | |
CONFIG_SPL_ATF=y | |
CONFIG_CMD_PWM=y | |
@@ -38,16 +40,19 @@ CONFIG_CMD_MMC=y | |
# CONFIG_SPL_DOS_PARTITION is not set | |
CONFIG_SPL_OF_CONTROL=y | |
CONFIG_OF_LIVE=y | |
-# CONFIG_OF_UPSTREAM is not set | |
+CONFIG_OF_LIST="rockchip/rk3566-anbernic-rg353p rockchip/rk3566-anbernic-rg353v rockchip/rk3566-anbernic-rg503 rockchip/rk3566-anbernic-rg-arc-d rockchip/rk3566-anbernic-rg353ps rockchip/rk3566-anbernic-rg353vs rockchip/rk3566-anbernic-rg-arc-s rockchip/rk3566-powkiddy-rgb30 rockchip/rk3566-powkiddy-rk2023 rockchip/rk3566-powkiddy-rgb10max3" | |
CONFIG_OF_SPL_REMOVE_PROPS="clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" | |
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y | |
# CONFIG_NET is not set | |
CONFIG_SPL_DM_SEQ_ALIAS=y | |
CONFIG_SPL_REGMAP=y | |
CONFIG_SPL_SYSCON=y | |
+CONFIG_SPL_ADC=y | |
CONFIG_SPL_CLK=y | |
CONFIG_ARM_SMCCC_FEATURES=y | |
CONFIG_SCMI_FIRMWARE=y | |
+CONFIG_CLK_CCF=y | |
+CONFIG_CLK_COMPOSITE_CCF=y | |
CONFIG_ROCKCHIP_GPIO=y | |
CONFIG_SYS_I2C_ROCKCHIP=y | |
CONFIG_MISC=y | |
@@ -61,7 +66,9 @@ CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY=y | |
CONFIG_SPL_PINCTRL=y | |
CONFIG_DM_PMIC=y | |
CONFIG_DM_PMIC_FAN53555=y | |
+CONFIG_SPL_DM_PMIC_FAN53555=y | |
CONFIG_PMIC_RK8XX=y | |
+CONFIG_SPL_PMIC_RK8XX=y | |
CONFIG_SPL_DM_REGULATOR=y | |
CONFIG_SPL_DM_REGULATOR_FIXED=y | |
CONFIG_REGULATOR_RK8XX=y | |
-- | |
2.34.1 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From ae0d308b5f686548193e9b1d977d56aedad2f093 Mon Sep 17 00:00:00 2001 | |
From: Chris Morgan <[email protected]> | |
Date: Fri, 6 Sep 2024 15:07:35 -0500 | |
Subject: [PATCH 2/3] board: rockchip: Add vdd_cpu reg fixup for RGXX3 Series | |
Some of the Powkiddy devices switched to using a different vendor for | |
the vdd_cpu regulator. Unfortunately the device does not have a new | |
revision to denote this, so users have no way of knowing in advance. | |
Add code to detect if a device is present at addresses 0x1c or 0x40 on | |
the i2c0 bus and update the devicetree if needed. | |
Signed-off-by: Chris Morgan <[email protected]> | |
--- | |
board/anbernic/rgxx3_rk3566/rgxx3-rk3566.c | 146 +++++++++++++++++++++ | |
1 file changed, 146 insertions(+) | |
diff --git a/board/anbernic/rgxx3_rk3566/rgxx3-rk3566.c b/board/anbernic/rgxx3_rk3566/rgxx3-rk3566.c | |
index e8ac181d81..c0353484f6 100644 | |
--- a/board/anbernic/rgxx3_rk3566/rgxx3-rk3566.c | |
+++ b/board/anbernic/rgxx3_rk3566/rgxx3-rk3566.c | |
@@ -43,6 +43,7 @@ struct rg3xx_model { | |
const char *board_name; | |
const char *fdtfile; | |
const bool detect_panel; | |
+ const bool detect_regulator; | |
}; | |
enum rgxx3_device_id { | |
@@ -68,6 +69,7 @@ static const struct rg3xx_model rg3xx_model_details[] = { | |
/* Device is identical to RG353P. */ | |
.fdtfile = DTB_DIR "rk3566-anbernic-rg353p.dtb", | |
.detect_panel = 1, | |
+ .detect_regulator = 0, | |
}, | |
[RG353P] = { | |
.adc_value = 860, /* Documented value of 860 */ | |
@@ -75,6 +77,7 @@ static const struct rg3xx_model rg3xx_model_details[] = { | |
.board_name = "Anbernic RG353P", | |
.fdtfile = DTB_DIR "rk3566-anbernic-rg353p.dtb", | |
.detect_panel = 1, | |
+ .detect_regulator = 0, | |
}, | |
[RG353V] = { | |
.adc_value = 695, /* Observed average from device */ | |
@@ -82,6 +85,7 @@ static const struct rg3xx_model rg3xx_model_details[] = { | |
.board_name = "Anbernic RG353V", | |
.fdtfile = DTB_DIR "rk3566-anbernic-rg353v.dtb", | |
.detect_panel = 1, | |
+ .detect_regulator = 0, | |
}, | |
[RG503] = { | |
.adc_value = 1023, /* Observed average from device */ | |
@@ -89,6 +93,7 @@ static const struct rg3xx_model rg3xx_model_details[] = { | |
.board_name = "Anbernic RG503", | |
.fdtfile = DTB_DIR "rk3566-anbernic-rg503.dtb", | |
.detect_panel = 0, | |
+ .detect_regulator = 0, | |
}, | |
[RGB30] = { | |
.adc_value = 383, /* Gathered from second hand information */ | |
@@ -96,6 +101,7 @@ static const struct rg3xx_model rg3xx_model_details[] = { | |
.board_name = "Powkiddy RGB30", | |
.fdtfile = DTB_DIR "rk3566-powkiddy-rgb30.dtb", | |
.detect_panel = 0, | |
+ .detect_regulator = 1, | |
}, | |
[RK2023] = { | |
.adc_value = 635, /* Observed average from device */ | |
@@ -103,6 +109,7 @@ static const struct rg3xx_model rg3xx_model_details[] = { | |
.board_name = "Powkiddy RK2023", | |
.fdtfile = DTB_DIR "rk3566-powkiddy-rk2023.dtb", | |
.detect_panel = 0, | |
+ .detect_regulator = 1, | |
}, | |
[RGARCD] = { | |
.adc_value = 183, /* Observed average from device */ | |
@@ -110,6 +117,7 @@ static const struct rg3xx_model rg3xx_model_details[] = { | |
.board_name = "Anbernic RG ARC-D", | |
.fdtfile = DTB_DIR "rk3566-anbernic-rg-arc-d.dtb", | |
.detect_panel = 0, | |
+ .detect_regulator = 0, | |
}, | |
[RGB10MAX3] = { | |
.adc_value = 765, /* Observed average from device */ | |
@@ -117,6 +125,7 @@ static const struct rg3xx_model rg3xx_model_details[] = { | |
.board_name = "Powkiddy RGB10MAX3", | |
.fdtfile = DTB_DIR "rk3566-powkiddy-rgb10max3.dtb", | |
.detect_panel = 0, | |
+ .detect_regulator = 1, | |
}, | |
/* Devices with duplicate ADC value */ | |
[RG353PS] = { | |
@@ -125,6 +134,7 @@ static const struct rg3xx_model rg3xx_model_details[] = { | |
.board_name = "Anbernic RG353PS", | |
.fdtfile = DTB_DIR "rk3566-anbernic-rg353ps.dtb", | |
.detect_panel = 1, | |
+ .detect_regulator = 0, | |
}, | |
[RG353VS] = { | |
.adc_value = 695, /* Gathered from second hand information */ | |
@@ -132,6 +142,7 @@ static const struct rg3xx_model rg3xx_model_details[] = { | |
.board_name = "Anbernic RG353VS", | |
.fdtfile = DTB_DIR "rk3566-anbernic-rg353vs.dtb", | |
.detect_panel = 1, | |
+ .detect_regulator = 0, | |
}, | |
[RGARCS] = { | |
.adc_value = 183, /* Observed average from device */ | |
@@ -139,6 +150,7 @@ static const struct rg3xx_model rg3xx_model_details[] = { | |
.board_name = "Anbernic RG ARC-S", | |
.fdtfile = DTB_DIR "rk3566-anbernic-rg-arc-s.dtb", | |
.detect_panel = 0, | |
+ .detect_regulator = 0, | |
}, | |
}; | |
@@ -160,6 +172,22 @@ static const struct rg353_panel rg353_panel_details[] = { | |
}, | |
}; | |
+struct powkiddy_regulators { | |
+ const u8 addr; | |
+ const char *regulator_compat; | |
+}; | |
+ | |
+static const struct powkiddy_regulators regulator_details[] = { | |
+ { | |
+ .addr = 0x1c, | |
+ .regulator_compat = "tcs,tcs4525", | |
+ }, | |
+ { | |
+ .addr = 0x40, | |
+ .regulator_compat = "fcs,fan53555", | |
+ }, | |
+}; | |
+ | |
/* | |
* Start LED very early so user knows device is on. Set color | |
* to red. | |
@@ -345,6 +373,44 @@ int rgxx3_detect_display(void) | |
return 0; | |
} | |
+/* | |
+ * Some of the Powkiddy devices switched the CPU regulator, but users | |
+ * are not able to determine this by looking at their hardware. | |
+ * Attempt to auto-detect this situation and fixup the device-tree. | |
+ */ | |
+int rgxx3_detect_regulator(void) | |
+{ | |
+ struct udevice *bus; | |
+ struct udevice *chip; | |
+ u8 val; | |
+ int ret; | |
+ | |
+ /* Get the correct i2c bus (i2c0). */ | |
+ ret = uclass_get_device_by_name(UCLASS_I2C, | |
+ "i2c@fdd40000", &bus); | |
+ if (ret) | |
+ return ret; | |
+ | |
+ /* | |
+ * Check for all vdd_cpu regulators and read an arbitrary | |
+ * register to confirm it's present. | |
+ */ | |
+ for (int i = 0; i < ARRAY_SIZE(regulator_details); i++) { | |
+ ret = i2c_get_chip(bus, regulator_details[i].addr, | |
+ 1, &chip); | |
+ if (ret) | |
+ return ret; | |
+ | |
+ ret = dm_i2c_read(chip, 0, &val, 1); | |
+ if (!ret) { | |
+ env_set("vdd_cpu", regulator_details[i].regulator_compat); | |
+ break; | |
+ } | |
+ } | |
+ | |
+ return 0; | |
+} | |
+ | |
int rgxx3_read_board_id(void) | |
{ | |
u32 adc_info; | |
@@ -463,6 +529,15 @@ int rk_board_late_init(void) | |
printf("Failed to detect panel type\n"); | |
} | |
+ /* | |
+ * Skip vdd_cpu regulator detection if not needed. Warn but | |
+ * don't fail for errors in auto-detection of regulator. | |
+ */ | |
+ if (rg3xx_model_details[gd->board_type].detect_regulator) { | |
+ ret = rgxx3_detect_regulator(); | |
+ if (ret) | |
+ printf("Unable to detect vdd_cpu regulator\n"); | |
+ } | |
end: | |
/* Turn off red LED and turn on orange LED. */ | |
writel(GPIO_WRITEMASK(GPIO_C7 | GPIO_C6 | GPIO_C5) | GPIO_C6, | |
@@ -526,6 +601,71 @@ int rgxx3_panel_fixup(void *blob) | |
return 0; | |
} | |
+int rgxx3_regulator_fixup(void *blob) | |
+{ | |
+ const struct powkiddy_regulators *vdd_cpu = NULL; | |
+ int node, ret, i; | |
+ char path[] = "/i2c@fdd40000/regulator@00"; | |
+ char name[] = "regulator@00"; | |
+ char *env; | |
+ | |
+ env = env_get("vdd_cpu"); | |
+ if (!env) { | |
+ printf("Can't get vdd_cpu env\n"); | |
+ return -EINVAL; | |
+ } | |
+ | |
+ /* | |
+ * Find the device we have in our tree, which may or may not | |
+ * be present. | |
+ */ | |
+ for (i = 0; i < ARRAY_SIZE(regulator_details); i++) { | |
+ sprintf(path, "/i2c@fdd40000/regulator@%02x", | |
+ regulator_details[i].addr); | |
+ node = fdt_path_offset(blob, path); | |
+ if (node > 0) | |
+ break; | |
+ | |
+ printf("Unable to find vdd_cpu\n"); | |
+ return -ENODEV; | |
+ } | |
+ | |
+ node = fdt_path_offset(blob, path); | |
+ if (!(node > 0)) { | |
+ printf("Can't find the vdd_cpu node\n"); | |
+ return -ENODEV; | |
+ } | |
+ | |
+ ret = fdt_node_check_compatible(blob, node, env); | |
+ if (ret < 0) | |
+ return -ENODEV; | |
+ | |
+ /* vdd_cpu regulators match, return 0. */ | |
+ if (!ret) | |
+ return 0; | |
+ | |
+ /* Regulators don't match, search by first compatible value. */ | |
+ for (i = 0; i < ARRAY_SIZE(regulator_details); i++) { | |
+ if (!strcmp(env, regulator_details[i].regulator_compat)) { | |
+ vdd_cpu = ®ulator_details[i]; | |
+ break; | |
+ } | |
+ } | |
+ | |
+ if (!vdd_cpu) { | |
+ printf("Unable to identify vdd_cpu by compat string\n"); | |
+ return -ENODEV; | |
+ } | |
+ | |
+ /* Set the compatible and reg with the auto-detected values */ | |
+ fdt_setprop_string(blob, node, "compatible", vdd_cpu->regulator_compat); | |
+ fdt_setprop_u32(blob, node, "reg", vdd_cpu->addr); | |
+ sprintf(name, "regulator@%02x", vdd_cpu->addr); | |
+ fdt_set_name(blob, node, name); | |
+ | |
+ return 0; | |
+} | |
+ | |
int ft_board_setup(void *blob, struct bd_info *bd) | |
{ | |
int ret; | |
@@ -536,6 +676,12 @@ int ft_board_setup(void *blob, struct bd_info *bd) | |
printf("Unable to update panel compat\n"); | |
} | |
+ if (rg3xx_model_details[gd->board_type].detect_regulator) { | |
+ ret = rgxx3_regulator_fixup(blob); | |
+ if (ret) | |
+ printf("Unable to update vdd_cpu compat\n"); | |
+ } | |
+ | |
return 0; | |
} | |
-- | |
2.34.1 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 21af290030161a3f8c8d6576dba1c5c3da3aca02 Mon Sep 17 00:00:00 2001 | |
From: Chris Morgan <[email protected]> | |
Date: Fri, 6 Sep 2024 15:09:44 -0500 | |
Subject: [PATCH 3/3] board: rockchip: Fix panel detection logic for mainline | |
A-TF | |
The current panel detection logic crashes when the device boots with | |
mainline A-TF, causing a reboot loop. It turns out mainline A-TF | |
doesn't enable the VO power domain like the BSP A-TF did. | |
Set the VO domain on and use a memory barrier to ensure it is powered | |
up before we attempt to do the panel detection. | |
Signed-off-by: Chris Morgan <[email protected]> | |
--- | |
board/anbernic/rgxx3_rk3566/rgxx3-rk3566.c | 13 +++++++++++++ | |
configs/anbernic-rgxx3-rk3566_defconfig | 3 --- | |
2 files changed, 13 insertions(+), 3 deletions(-) | |
diff --git a/board/anbernic/rgxx3_rk3566/rgxx3-rk3566.c b/board/anbernic/rgxx3_rk3566/rgxx3-rk3566.c | |
index c0353484f6..be45a03867 100644 | |
--- a/board/anbernic/rgxx3_rk3566/rgxx3-rk3566.c | |
+++ b/board/anbernic/rgxx3_rk3566/rgxx3-rk3566.c | |
@@ -22,6 +22,10 @@ | |
DECLARE_GLOBAL_DATA_PTR; | |
+#define PMU_BASE_ADDR 0xfdd90000 | |
+#define PMU_PWR_GATE_SFTCON 0xa0 | |
+#define PMU_PD_VO_DWN_ENA BIT(7) | |
+ | |
#define GPIO0_BASE 0xfdd60000 | |
#define GPIO4_BASE 0xfe770000 | |
#define GPIO_SWPORT_DR_L 0x0000 | |
@@ -295,6 +299,15 @@ int rgxx3_detect_display(void) | |
int i; | |
u8 panel_id[2]; | |
+ /* Disable VO power domain power-down */ | |
+ writel((PMU_PD_VO_DWN_ENA << 16), | |
+ PMU_BASE_ADDR + PMU_PWR_GATE_SFTCON); | |
+ /* | |
+ * System will crash if the power domain isn't enabled before | |
+ * we start trying to talk to the DSI panel. | |
+ */ | |
+ wmb(); | |
+ | |
/* | |
* Take panel out of reset status. | |
* Set GPIO4_A0 to output. | |
diff --git a/configs/anbernic-rgxx3-rk3566_defconfig b/configs/anbernic-rgxx3-rk3566_defconfig | |
index 81c0299894..42fc37671e 100644 | |
--- a/configs/anbernic-rgxx3-rk3566_defconfig | |
+++ b/configs/anbernic-rgxx3-rk3566_defconfig | |
@@ -49,8 +49,6 @@ CONFIG_SPL_REGMAP=y | |
CONFIG_SPL_SYSCON=y | |
CONFIG_SPL_ADC=y | |
CONFIG_SPL_CLK=y | |
-CONFIG_ARM_SMCCC_FEATURES=y | |
-CONFIG_SCMI_FIRMWARE=y | |
CONFIG_CLK_CCF=y | |
CONFIG_CLK_COMPOSITE_CCF=y | |
CONFIG_ROCKCHIP_GPIO=y | |
@@ -75,7 +73,6 @@ CONFIG_REGULATOR_RK8XX=y | |
CONFIG_PWM_ROCKCHIP=y | |
CONFIG_SPL_RAM=y | |
# CONFIG_RAM_ROCKCHIP_DEBUG is not set | |
-# CONFIG_RNG_SMCCC_TRNG is not set | |
CONFIG_BAUDRATE=1500000 | |
CONFIG_DEBUG_UART_SHIFT=2 | |
CONFIG_SYS_NS16550_MEM32=y | |
-- | |
2.34.1 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment