From: Quentin Schulz <quentin.sch...@cherry.de>

This implements checkboard() to print the current SoC model used by a
board, e.g. one of:

SoC:   PX30
SoC:   PX30S
SoC:   PX30K
SoC:   RK3326
SoC:   RK3326S

when U-Boot proper is running.

The information is read from the OTP and also the DDR_GRF. There's no
public information as far as I know about the layout and stored
information on OTP but this was provided by Rockchip themselves through
their support channel.

The OTP stores the information of whether the SoC is PX30K or something
else. To differentiate between PX30/RK3326 and PX30S/RK3326S, one needs
to read some undocumented bitfield in a DDR_GRF register as done in
vendor kernel,
c.f. 
https://github.com/armbian/linux-rockchip/blob/rk-6.1-rkr5.1/drivers/soc/rockchip/rockchip-cpuinfo.c#L118-L133.

I do not own a PX30S, nor RK3326/RK3326S so cannot test it works
properly.

Also add the OTP node to the pre-relocation phase of U-Boot proper so
that the SoC variant can be printed when DISPLAY_BOARDINFO is enabled.
This is not required if DISPLAY_BOARDINFO_LATE is enabled because this
happens after relocation. If both are enabled, then the SoC variant will
be printed twice in the boot log, e.g.:

U-Boot 2025.07-rc3-00014-g7cb731574ae6-dirty (May 28 2025 - 13:52:47 +0200)

Model: Theobroma Systems PX30-uQ7 SoM on Haikou devkit
SoC:   PX30  <---- due to DISPLAY_BOARDINFO
DRAM:  2 GiB
PMIC:  RK809 (on=0x40, off=0x00)
Core:  293 devices, 27 uclasses, devicetree: separate
MMC:   mmc@ff370000: 1, mmc@ff390000: 0
Loading Environment from MMC... Reading from MMC(1)... OK

In:    serial@ff030000
Out:   serial@ff030000
Err:   serial@ff030000
Model: Theobroma Systems PX30-uQ7 SoM on Haikou devkit
SoC:   PX30  <----- due to DISPLAY_BOARDINFO_LATE
Net:   eth0: ethernet@ff360000

Signed-off-by: Quentin Schulz <quentin.sch...@cherry.de>
---
Tested on a PX30 Ringneck and PX30K Ringneck. Would be nice if anyone
had a device with a PX30S, RK3326 or RK3326S so we could verify it
prints what it should :)
---
Changes in v3:
- added (theoretical, untested) support for RK3326/RK3326S based on
  feedback from Jonas,
- Link to v2: 
https://lore.kernel.org/r/20250606-px30-identify-variant-v2-1-624d34ccc...@cherry.de

Changes in v2:
- added (theoretical, untested) support for PX30S based on feedback from
  Kever,
- Link to v1: 
https://lore.kernel.org/r/20250528-px30-identify-variant-v1-1-4ea69c527...@cherry.de
---
 arch/arm/dts/px30-u-boot.dtsi      |  4 +++
 arch/arm/mach-rockchip/px30/px30.c | 61 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+)

diff --git a/arch/arm/dts/px30-u-boot.dtsi b/arch/arm/dts/px30-u-boot.dtsi
index 
157d0ea6930c55cc067560bd795249a39c3249ab..2f726b0aaba358c8fb3bf6f8ed2f9afca416aabe
 100644
--- a/arch/arm/dts/px30-u-boot.dtsi
+++ b/arch/arm/dts/px30-u-boot.dtsi
@@ -27,6 +27,10 @@
        };
 };
 
+&otp {
+       bootph-some-ram;
+};
+
 &uart2 {
        clock-frequency = <24000000>;
        bootph-all;
diff --git a/arch/arm/mach-rockchip/px30/px30.c 
b/arch/arm/mach-rockchip/px30/px30.c
index 
8ce9ac561f0213fd4db933fdb9e1edde61ac39ca..5a5c119328fb3912af4276b1e1b12640349a7c47
 100644
--- a/arch/arm/mach-rockchip/px30/px30.c
+++ b/arch/arm/mach-rockchip/px30/px30.c
@@ -2,10 +2,14 @@
 /*
  * Copyright (c) 2017 Rockchip Electronics Co., Ltd
  */
+
+#define LOG_CATEGORY LOGC_ARCH
+
 #include <clk.h>
 #include <dm.h>
 #include <fdt_support.h>
 #include <init.h>
+#include <misc.h>
 #include <spl.h>
 #include <asm/armv8/mmu.h>
 #include <asm/arch-rockchip/bootrom.h>
@@ -15,6 +19,7 @@
 #include <asm/arch-rockchip/clock.h>
 #include <asm/arch-rockchip/cru_px30.h>
 #include <dt-bindings/clock/px30-cru.h>
+#include <linux/bitfield.h>
 
 const char * const boot_devices[BROM_LAST_BOOTSOURCE + 1] = {
        [BROM_BOOTSOURCE_EMMC] = "/mmc@ff390000",
@@ -442,3 +447,59 @@ void board_debug_uart_init(void)
 #endif /* CONFIG_DEBUG_UART_BASE && CONFIG_DEBUG_UART_BASE == ... */
 }
 #endif /* CONFIG_DEBUG_UART_BOARD_INIT */
+
+#define PX30_OTP_SPECIFICATION_OFFSET          0x06
+
+#define DDR_GRF_BASE_ADDR               0xff630000
+#define DDR_GRF_CON(n)                  (0 + (n) * 4)
+
+int checkboard(void)
+{
+       struct udevice *dev;
+       u8 specification;
+       u32 base_soc;
+       int ret;
+
+       if (!IS_ENABLED(CONFIG_ROCKCHIP_OTP) || !CONFIG_IS_ENABLED(MISC))
+               return 0;
+
+       ret = uclass_get_device_by_driver(UCLASS_MISC,
+                                         DM_DRIVER_GET(rockchip_otp), &dev);
+       if (ret) {
+               log_debug("Could not find otp device, ret=%d\n", ret);
+               return 0;
+       }
+
+       /* base SoC: 0x26334b52 for RK3326; 0x30335850 for PX30 */
+       ret = misc_read(dev, 0, &base_soc, 4);
+       if (ret < 0) {
+               log_debug("Could not read specification, ret=%d\n", ret);
+               return 0;
+       }
+
+       if (base_soc != 0x26334b52 && base_soc != 0x30335850) {
+               log_debug("Could not identify SoC, got 0x%04x in OTP\n", 
base_soc);
+               return 0;
+       }
+
+       /* SoC variant: 0x21 for PX30/PX30S/RK3326/RK3326S; 0x2b for PX30K */
+       ret = misc_read(dev, PX30_OTP_SPECIFICATION_OFFSET, &specification, 1);
+       if (ret < 0) {
+               log_debug("Could not read specification, ret=%d\n", ret);
+               return 0;
+       }
+
+       if (specification == 0x2b) {
+               printf("SoC:   PX30K\n");
+               return 0;
+       }
+
+       /* From vendor kernel: drivers/soc/rockchip/rockchip-cpuinfo.c */
+       specification = FIELD_GET(GENMASK(15, 14),
+                                 readl(DDR_GRF_BASE_ADDR + DDR_GRF_CON(1)));
+       log_debug("DDR specification is %d\n", specification);
+       printf("SoC:   %s%s\n", base_soc == 0x26334b52 ? "RK3326" : "PX30",
+              specification == 0x3 ? "S" : "");
+
+       return 0;
+}

---
base-commit: 11b8bcd7005ff24b2114dcc4d1061e083e4c9e6c
change-id: 20250528-px30-identify-variant-ae39c772155b

Best regards,
-- 
Quentin Schulz <quentin.sch...@cherry.de>

Reply via email to