From 7344fa41a2e39a2f10ffcc5f3ea5725b56d0e285 Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Thu, 19 Sep 2024 09:00:19 -0500 Subject: [PATCH] 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 Reviewed-by: Kever Yang --- .../dts/rk3566-anbernic-rg353p-u-boot.dtsi | 34 +++ .../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 | 214 +++++++++++++----- configs/anbernic-rgxx3-rk3566_defconfig | 10 +- 6 files changed, 195 insertions(+), 147 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..fa3fbe6c81 --- /dev/null +++ b/arch/arm/dts/rk3566-anbernic-rg353p-u-boot.dtsi @@ -0,0 +1,34 @@ +// 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"; + }; +}; + +&saradc { + bootph-pre-ram; + bootph-some-ram; + vref-supply = <&vcc_1v8_dummy>; + 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..224019f9ba 100644 --- a/board/anbernic/rgxx3_rk3566/rgxx3-rk3566.c +++ b/board/anbernic/rgxx3_rk3566/rgxx3-rk3566.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,8 @@ #include #include +DECLARE_GLOBAL_DATA_PTR; + #define GPIO0_BASE 0xfdd60000 #define GPIO4_BASE 0xfe770000 #define GPIO_SWPORT_DR_L 0x0000 @@ -40,10 +43,11 @@ struct rg3xx_model { const char *board_name; const char *fdtfile; const bool detect_panel; + const bool uart_con; }; enum rgxx3_device_id { - RG353M, + RG353M = 1, RG353P, RG353V, RG503, @@ -61,45 +65,51 @@ 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, + .uart_con = 1, }, [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, + .uart_con = 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, + .uart_con = 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, + .uart_con = 1, }, [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, + .uart_con = 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, + .uart_con = 0, }, [RGARCD] = { .adc_value = 183, /* Observed average from device */ @@ -107,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, + .uart_con = 1, }, [RGB10MAX3] = { .adc_value = 765, /* Observed average from device */ @@ -114,21 +125,24 @@ static const struct rg3xx_model rg3xx_model_details[] = { .board_name = "Powkiddy RGB10MAX3", .fdtfile = DTB_DIR "rk3566-powkiddy-rgb10max3.dtb", .detect_panel = 0, + .uart_con = 0, }, /* Devices with duplicate ADC value */ [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, + .uart_con = 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, + .uart_con = 1, }, [RGARCS] = { .adc_value = 183, /* Observed average from device */ @@ -136,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, + .uart_con = 1, }, }; @@ -164,7 +179,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. */ @@ -174,16 +189,22 @@ void spl_board_init(void) /* * Buzz the buzzer so the user knows something is going on. Make it - * optional in case PWM is disabled. + * optional in case PWM is disabled or if CONFIG_DM_PWM is not + * enabled. */ void __maybe_unused startup_buzz(void) { struct udevice *dev; int err; - err = uclass_get_device(UCLASS_PWM, 0, &dev); + if (!IS_ENABLED(CONFIG_DM_PWM)) + return; + + /* Probe the PWM controller. */ + err = uclass_get_device_by_name(UCLASS_PWM, + "pwm@fe6e0010", &dev); if (err) - printf("pwm not found\n"); + return; pwm_set_enable(dev, 0, 1); mdelay(200); @@ -245,6 +266,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 +361,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 +378,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,67 +424,87 @@ 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. + * Disable the console if the board doesn't support a console. + */ +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; + if (!rg3xx_model_details[i].uart_con) + gd->flags |= GD_FLG_SILENT | + GD_FLG_DISABLE_CONSOLE; + 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)); - if (IS_ENABLED(CONFIG_DM_PWM)) - startup_buzz(); + startup_buzz(); 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 +526,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 +546,38 @@ 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 (gd->board_type == RG353M) + fdt_setprop(blob, 0, "model", + rg3xx_model_details[RG353M].board_name, + sizeof(rg3xx_model_details[RG353M].board_name)); + + 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 4dcf18e22c..8855a751dc 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 @@ -20,8 +20,10 @@ 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_DISABLE_CONSOLE=y # 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 @@ -39,13 +41,14 @@ 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_NO_NET=y 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 @@ -71,6 +74,7 @@ CONFIG_SPL_RAM=y # CONFIG_RAM_ROCKCHIP_DEBUG is not set # CONFIG_RNG_SMCCC_TRNG is not set CONFIG_BAUDRATE=1500000 +# CONFIG_REQUIRE_SERIAL_CONSOLE is not set CONFIG_DEBUG_UART_SHIFT=2 CONFIG_SYS_NS16550_MEM32=y CONFIG_SYSRESET=y -- 2.39.5