Skip to content

Instantly share code, notes, and snippets.

@macromorgan
Created September 6, 2024 20:17
Show Gist options
  • Save macromorgan/745647bef36a33ad0aa294a3e4bda775 to your computer and use it in GitHub Desktop.
Save macromorgan/745647bef36a33ad0aa294a3e4bda775 to your computer and use it in GitHub Desktop.
RGxx3 U-Boot Updates for 2024-09-06
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
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
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 = &regulator_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
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