
On 2024/9/19 22:00, Chris Morgan wrote:
From: Chris Morgan macromorgan@hotmail.com
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 macromorgan@hotmail.com
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Thanks, - Kever
board/anbernic/rgxx3_rk3566/rgxx3-rk3566.c | 147 +++++++++++++++++++++ 1 file changed, 147 insertions(+)
diff --git a/board/anbernic/rgxx3_rk3566/rgxx3-rk3566.c b/board/anbernic/rgxx3_rk3566/rgxx3-rk3566.c index 224019f9ba3..c1d1826fd14 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; const bool uart_con; };
@@ -69,6 +70,7 @@ static const struct rg3xx_model rg3xx_model_details[] = { /* Device is identical to RG353P. */ .fdtfile = DTB_DIR "rk3566-anbernic-rg353p.dtb", .detect_panel = 1,
.uart_con = 1, }, [RG353P] = {.detect_regulator = 0,
@@ -77,6 +79,7 @@ static const struct rg3xx_model rg3xx_model_details[] = { .board_name = "Anbernic RG353P", .fdtfile = DTB_DIR "rk3566-anbernic-rg353p.dtb", .detect_panel = 1,
.uart_con = 1, }, [RG353V] = {.detect_regulator = 0,
@@ -85,6 +88,7 @@ static const struct rg3xx_model rg3xx_model_details[] = { .board_name = "Anbernic RG353V", .fdtfile = DTB_DIR "rk3566-anbernic-rg353v.dtb", .detect_panel = 1,
.uart_con = 1, }, [RG503] = {.detect_regulator = 0,
@@ -93,6 +97,7 @@ static const struct rg3xx_model rg3xx_model_details[] = { .board_name = "Anbernic RG503", .fdtfile = DTB_DIR "rk3566-anbernic-rg503.dtb", .detect_panel = 0,
.uart_con = 1, }, [RGB30] = {.detect_regulator = 0,
@@ -101,6 +106,7 @@ static const struct rg3xx_model rg3xx_model_details[] = { .board_name = "Powkiddy RGB30", .fdtfile = DTB_DIR "rk3566-powkiddy-rgb30.dtb", .detect_panel = 0,
.uart_con = 0, }, [RK2023] = {.detect_regulator = 1,
@@ -109,6 +115,7 @@ static const struct rg3xx_model rg3xx_model_details[] = { .board_name = "Powkiddy RK2023", .fdtfile = DTB_DIR "rk3566-powkiddy-rk2023.dtb", .detect_panel = 0,
.uart_con = 0, }, [RGARCD] = {.detect_regulator = 1,
@@ -117,6 +124,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] = {.detect_regulator = 0,
@@ -125,6 +133,7 @@ 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 */.detect_regulator = 1,
@@ -134,6 +143,7 @@ static const struct rg3xx_model rg3xx_model_details[] = { .board_name = "Anbernic RG353PS", .fdtfile = DTB_DIR "rk3566-anbernic-rg353ps.dtb", .detect_panel = 1,
.uart_con = 1, }, [RG353VS] = {.detect_regulator = 0,
@@ -142,6 +152,7 @@ static const struct rg3xx_model rg3xx_model_details[] = { .board_name = "Anbernic RG353VS", .fdtfile = DTB_DIR "rk3566-anbernic-rg353vs.dtb", .detect_panel = 1,
.uart_con = 1, }, [RGARCS] = {.detect_regulator = 0,
@@ -150,6 +161,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, }, };.detect_regulator = 0,
@@ -172,6 +184,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.
@@ -361,6 +389,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;
@@ -485,6 +551,16 @@ 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,
@@ -547,6 +623,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;
@@ -562,6 +703,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; }