[PATCH v2 0/3] rockchip: rk35xx: Implement checkboard() to print SoC variant

Information about what SoC model, variant and version can be found in OTP. This series use this information in checkboard() to print out the running SoC model, variant and version.
There are some asumptions taken on how some of the OTP values are encoded, however for my boards this seem to match and something like one of the following is shown with this applied:
SoC: RK3566 v1 SoC: RK3566 v2 SoC: RK3566T v2 SoC: RK3568 v2 SoC: RK3568B2 v2 SoC: RK3568J v2
SoC: RK3582 v1 SoC: RK3588 v0 SoC: RK3588 v1 SoC: RK3588S v0 SoC: RK3588S v1 SoC: RK3588S2 v1
SoC: RK3308B SoC: RK3308B-S
Changes in v2: - Drop changes in generic-rk35xx_defconfig - Update code comments - Add patch for rk3308
This can probably be converted into an sysinfo driver in a future series, once other pending changes to sysinfo core have settled.
Jonas Karlman (3): rockchip: rk356x: Implement checkboard() to print SoC variant rockchip: rk3588: Implement checkboard() to print SoC variant rockchip: rk3308: Implement checkboard() to print SoC variant
arch/arm/dts/rk356x-u-boot.dtsi | 4 ++ arch/arm/dts/rk3588s-u-boot.dtsi | 4 ++ arch/arm/mach-rockchip/rk3308/rk3308.c | 16 ++++++ arch/arm/mach-rockchip/rk3568/rk3568.c | 67 ++++++++++++++++++++++++++ arch/arm/mach-rockchip/rk3588/rk3588.c | 58 ++++++++++++++++++++++ 5 files changed, 149 insertions(+)

Implement checkboard() to print current SoC model used by a board, e.g. one of:
SoC: RK3566 v1 SoC: RK3566 v2 SoC: RK3566T v2 SoC: RK3568 v2 SoC: RK3568B2 v2 SoC: RK3568J v2
when U-Boot proper is running.
U-Boot 2025.01-rc1 (Nov 02 2024 - 20:21:06 +0000)
Model: Generic RK3566/RK3568 SoC: RK3568J v2 DRAM: 8 GiB (effective 7.7 GiB)
Information about the SoC model, variant and version is read from OTP.
Also update rk356x-u-boot.dtsi to include OTP in U-Boot pre-reloc phase, where checkboard() is called.
Signed-off-by: Jonas Karlman jonas@kwiboo.se --- v2: - Update commit message - Update code comments - Drop generic-rk3568_defconfig change --- arch/arm/dts/rk356x-u-boot.dtsi | 4 ++ arch/arm/mach-rockchip/rk3568/rk3568.c | 67 ++++++++++++++++++++++++++ 2 files changed, 71 insertions(+)
diff --git a/arch/arm/dts/rk356x-u-boot.dtsi b/arch/arm/dts/rk356x-u-boot.dtsi index 0a0943b462a9..24a976cf7e21 100644 --- a/arch/arm/dts/rk356x-u-boot.dtsi +++ b/arch/arm/dts/rk356x-u-boot.dtsi @@ -87,6 +87,10 @@ bootph-all; };
+&otp { + bootph-some-ram; +}; + &pcfg_pull_none { bootph-all; }; diff --git a/arch/arm/mach-rockchip/rk3568/rk3568.c b/arch/arm/mach-rockchip/rk3568/rk3568.c index c9a32287e924..afa277ea5c61 100644 --- a/arch/arm/mach-rockchip/rk3568/rk3568.c +++ b/arch/arm/mach-rockchip/rk3568/rk3568.c @@ -4,6 +4,7 @@ */
#include <dm.h> +#include <misc.h> #include <asm/armv8/mmu.h> #include <asm/arch-rockchip/bootrom.h> #include <asm/arch-rockchip/grf_rk3568.h> @@ -139,3 +140,69 @@ int arch_cpu_init(void) #endif return 0; } + +#define RK3568_OTP_CPU_CODE_OFFSET 0x02 +#define RK3568_OTP_SPECIFICATION_OFFSET 0x07 +#define RK3568_OTP_CPU_VERSION_OFFSET 0x08 +#define RK3568_OTP_PERFORMANCE_OFFSET 0x22 + +int checkboard(void) +{ + u8 cpu_code[2], specification, package, cpu_version, performance; + struct udevice *dev; + char suffix[3]; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_DRIVER_GET(rockchip_otp), &dev); + if (ret) { + debug("%s: could not find otp device, ret=%d\n", __func__, ret); + return 0; + } + + /* cpu-code: SoC model, e.g. 0x35 0x66 or 0x35 0x68 */ + ret = misc_read(dev, RK3568_OTP_CPU_CODE_OFFSET, cpu_code, 2); + if (ret < 0) { + debug("%s: could not read cpu-code, ret=%d\n", __func__, ret); + return 0; + } + + /* specification: SoC variant, e.g. 0x2 for RK3568B2 and 0xA for RK3568J */ + ret = misc_read(dev, RK3568_OTP_SPECIFICATION_OFFSET, &specification, 1); + if (ret < 0) { + debug("%s: could not read specification, ret=%d\n", __func__, ret); + return 0; + } + /* package: likely SoC variant revision, 0x2 for RK3568B2 */ + package = specification >> 5; + specification &= 0x1f; + + /* cpu-version: chip version, e.g. second letter of lot number */ + ret = misc_read(dev, RK3568_OTP_CPU_VERSION_OFFSET, &cpu_version, 1); + if (ret < 0) { + debug("%s: could not read cpu-version, ret=%d\n", __func__, ret); + return 0; + } + cpu_version >>= 3; + cpu_version &= 0x7; + + /* performance: used to identify RK3566T SoC variant */ + ret = misc_read(dev, RK3568_OTP_PERFORMANCE_OFFSET, &performance, 1); + if (ret < 0) { + debug("%s: could not read performance, ret=%d\n", __func__, ret); + return 0; + } + if (performance & 0x0f) + specification = 0x14; /* T-variant */ + + /* for RK3568J i.e. '@' + 0xA = 'J' */ + suffix[0] = specification > 1 ? '@' + specification : '\0'; + /* for RK3568B2 i.e. '0' + 0x2 = '2' */ + suffix[1] = package > 1 ? '0' + package : '\0'; + suffix[2] = '\0'; + + printf("SoC: RK%02x%02x%s v%u\n", + cpu_code[0], cpu_code[1], suffix, cpu_version); + + return 0; +}

Implement checkboard() to print current SoC model used by a board, e.g. one of:
SoC: RK3582 v1 SoC: RK3588 v0 SoC: RK3588 v1 SoC: RK3588S v0 SoC: RK3588S v1 SoC: RK3588S2 v1
when U-Boot proper is running.
U-Boot 2025.01-rc1 (Nov 02 2024 - 20:19:01 +0000)
Model: Generic RK3588S/RK3588 SoC: RK3588S2 v1 DRAM: 8 GiB
Information about the SoC model, variant and version is read from OTP.
Also update rk3588s-u-boot.dtsi to include OTP in U-Boot pre-reloc phase, where checkboard() is called.
Signed-off-by: Jonas Karlman jonas@kwiboo.se --- v2: - Update commit message - Update code comments - Drop generic-rk3588_defconfig change --- arch/arm/dts/rk3588s-u-boot.dtsi | 4 ++ arch/arm/mach-rockchip/rk3588/rk3588.c | 58 ++++++++++++++++++++++++++ 2 files changed, 62 insertions(+)
diff --git a/arch/arm/dts/rk3588s-u-boot.dtsi b/arch/arm/dts/rk3588s-u-boot.dtsi index 09d8b311cec5..8880d162b11c 100644 --- a/arch/arm/dts/rk3588s-u-boot.dtsi +++ b/arch/arm/dts/rk3588s-u-boot.dtsi @@ -69,6 +69,10 @@ bootph-all; };
+&otp { + bootph-some-ram; +}; + &pcfg_pull_down { bootph-all; }; diff --git a/arch/arm/mach-rockchip/rk3588/rk3588.c b/arch/arm/mach-rockchip/rk3588/rk3588.c index e2dac2a5b806..f9da7a6f1477 100644 --- a/arch/arm/mach-rockchip/rk3588/rk3588.c +++ b/arch/arm/mach-rockchip/rk3588/rk3588.c @@ -4,6 +4,8 @@ * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd. */
+#include <dm.h> +#include <misc.h> #include <spl.h> #include <asm/armv8/mmu.h> #include <asm/arch-rockchip/bootrom.h> @@ -178,3 +180,59 @@ int arch_cpu_init(void) return 0; } #endif + +#define RK3588_OTP_CPU_CODE_OFFSET 0x02 +#define RK3588_OTP_SPECIFICATION_OFFSET 0x06 +#define RK3588_OTP_CPU_VERSION_OFFSET 0x1c + +int checkboard(void) +{ + u8 cpu_code[2], specification, package, cpu_version; + struct udevice *dev; + char suffix[3]; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_DRIVER_GET(rockchip_otp), &dev); + if (ret) { + debug("%s: could not find otp device, ret=%d\n", __func__, ret); + return 0; + } + + /* cpu-code: SoC model, e.g. 0x35 0x82 or 0x35 0x88 */ + ret = misc_read(dev, RK3588_OTP_CPU_CODE_OFFSET, cpu_code, 2); + if (ret < 0) { + debug("%s: could not read cpu-code, ret=%d\n", __func__, ret); + return 0; + } + + /* specification: SoC variant, e.g. 0xA for RK3588J and 0x13 for RK3588S */ + ret = misc_read(dev, RK3588_OTP_SPECIFICATION_OFFSET, &specification, 1); + if (ret < 0) { + debug("%s: could not read specification, ret=%d\n", __func__, ret); + return 0; + } + /* package: likely SoC variant revision, 0x2 for RK3588S2 */ + package = specification >> 5; + specification &= 0x1f; + + /* cpu-version: chip version, e.g. second letter of lot number */ + ret = misc_read(dev, RK3588_OTP_CPU_VERSION_OFFSET, &cpu_version, 1); + if (ret < 0) { + debug("%s: could not read cpu-version, ret=%d\n", __func__, ret); + return 0; + } + cpu_version >>= 3; + cpu_version &= 0x7; + + /* for RK3588J i.e. '@' + 0xA = 'J' */ + suffix[0] = specification > 1 ? '@' + specification : '\0'; + /* for RK3588S2 i.e. '0' + 0x2 = '2' */ + suffix[1] = package > 1 ? '0' + package : '\0'; + suffix[2] = '\0'; + + printf("SoC: RK%02x%02x%s v%u\n", + cpu_code[0], cpu_code[1], suffix, cpu_version); + + return 0; +}

On Sun, 3 Nov 2024 at 02:08, Jonas Karlman jonas@kwiboo.se wrote:
Implement checkboard() to print current SoC model used by a board, e.g. one of:
SoC: RK3582 v1 SoC: RK3588 v0 SoC: RK3588 v1 SoC: RK3588S v0 SoC: RK3588S v1 SoC: RK3588S2 v1
when U-Boot proper is running.
U-Boot 2025.01-rc1 (Nov 02 2024 - 20:19:01 +0000)
Model: Generic RK3588S/RK3588 SoC: RK3588S2 v1 DRAM: 8 GiB
Information about the SoC model, variant and version is read from OTP.
Also update rk3588s-u-boot.dtsi to include OTP in U-Boot pre-reloc phase, where checkboard() is called.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
v2:
- Update commit message
- Update code comments
- Drop generic-rk3588_defconfig change
arch/arm/dts/rk3588s-u-boot.dtsi | 4 ++ arch/arm/mach-rockchip/rk3588/rk3588.c | 58 ++++++++++++++++++++++++++ 2 files changed, 62 insertions(+)
diff --git a/arch/arm/dts/rk3588s-u-boot.dtsi
b/arch/arm/dts/rk3588s-u-boot.dtsi
index 09d8b311cec5..8880d162b11c 100644 --- a/arch/arm/dts/rk3588s-u-boot.dtsi +++ b/arch/arm/dts/rk3588s-u-boot.dtsi @@ -69,6 +69,10 @@ bootph-all; };
+&otp {
bootph-some-ram;
+};
&pcfg_pull_down { bootph-all; }; diff --git a/arch/arm/mach-rockchip/rk3588/rk3588.c
b/arch/arm/mach-rockchip/rk3588/rk3588.c
index e2dac2a5b806..f9da7a6f1477 100644 --- a/arch/arm/mach-rockchip/rk3588/rk3588.c +++ b/arch/arm/mach-rockchip/rk3588/rk3588.c @@ -4,6 +4,8 @@
- Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
*/
+#include <dm.h> +#include <misc.h> #include <spl.h> #include <asm/armv8/mmu.h> #include <asm/arch-rockchip/bootrom.h> @@ -178,3 +180,59 @@ int arch_cpu_init(void) return 0; } #endif
+#define RK3588_OTP_CPU_CODE_OFFSET 0x02 +#define RK3588_OTP_SPECIFICATION_OFFSET 0x06 +#define RK3588_OTP_CPU_VERSION_OFFSET 0x1c
+int checkboard(void) +{
u8 cpu_code[2], specification, package, cpu_version;
struct udevice *dev;
char suffix[3];
int ret;
ret = uclass_get_device_by_driver(UCLASS_MISC,
DM_DRIVER_GET(rockchip_otp),
&dev);
if (ret) {
debug("%s: could not find otp device, ret=%d\n",
__func__, ret);
return 0;
}
/* cpu-code: SoC model, e.g. 0x35 0x82 or 0x35 0x88 */
ret = misc_read(dev, RK3588_OTP_CPU_CODE_OFFSET, cpu_code, 2);
if (ret < 0) {
debug("%s: could not read cpu-code, ret=%d\n", __func__,
ret);
return 0;
}
/* specification: SoC variant, e.g. 0xA for RK3588J and 0x13 for
RK3588S */
ret = misc_read(dev, RK3588_OTP_SPECIFICATION_OFFSET,
&specification, 1);
Any register to find the operating temperature of the chip?
Jagan.

Hi Jagan,
On 2024-11-04 08:29, Jagan Teki wrote:
On Sun, 3 Nov 2024 at 02:08, Jonas Karlman jonas@kwiboo.se wrote:
Implement checkboard() to print current SoC model used by a board, e.g. one of:
SoC: RK3582 v1 SoC: RK3588 v0 SoC: RK3588 v1 SoC: RK3588S v0 SoC: RK3588S v1 SoC: RK3588S2 v1
when U-Boot proper is running.
U-Boot 2025.01-rc1 (Nov 02 2024 - 20:19:01 +0000)
Model: Generic RK3588S/RK3588 SoC: RK3588S2 v1 DRAM: 8 GiB
Information about the SoC model, variant and version is read from OTP.
Also update rk3588s-u-boot.dtsi to include OTP in U-Boot pre-reloc phase, where checkboard() is called.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
v2:
- Update commit message
- Update code comments
- Drop generic-rk3588_defconfig change
arch/arm/dts/rk3588s-u-boot.dtsi | 4 ++ arch/arm/mach-rockchip/rk3588/rk3588.c | 58 ++++++++++++++++++++++++++ 2 files changed, 62 insertions(+)
diff --git a/arch/arm/dts/rk3588s-u-boot.dtsi
b/arch/arm/dts/rk3588s-u-boot.dtsi
index 09d8b311cec5..8880d162b11c 100644 --- a/arch/arm/dts/rk3588s-u-boot.dtsi +++ b/arch/arm/dts/rk3588s-u-boot.dtsi @@ -69,6 +69,10 @@ bootph-all; };
+&otp {
bootph-some-ram;
+};
&pcfg_pull_down { bootph-all; }; diff --git a/arch/arm/mach-rockchip/rk3588/rk3588.c
b/arch/arm/mach-rockchip/rk3588/rk3588.c
index e2dac2a5b806..f9da7a6f1477 100644 --- a/arch/arm/mach-rockchip/rk3588/rk3588.c +++ b/arch/arm/mach-rockchip/rk3588/rk3588.c @@ -4,6 +4,8 @@
- Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
*/
+#include <dm.h> +#include <misc.h> #include <spl.h> #include <asm/armv8/mmu.h> #include <asm/arch-rockchip/bootrom.h> @@ -178,3 +180,59 @@ int arch_cpu_init(void) return 0; } #endif
+#define RK3588_OTP_CPU_CODE_OFFSET 0x02 +#define RK3588_OTP_SPECIFICATION_OFFSET 0x06 +#define RK3588_OTP_CPU_VERSION_OFFSET 0x1c
+int checkboard(void) +{
u8 cpu_code[2], specification, package, cpu_version;
struct udevice *dev;
char suffix[3];
int ret;
ret = uclass_get_device_by_driver(UCLASS_MISC,
DM_DRIVER_GET(rockchip_otp),
&dev);
if (ret) {
debug("%s: could not find otp device, ret=%d\n",
__func__, ret);
return 0;
}
/* cpu-code: SoC model, e.g. 0x35 0x82 or 0x35 0x88 */
ret = misc_read(dev, RK3588_OTP_CPU_CODE_OFFSET, cpu_code, 2);
if (ret < 0) {
debug("%s: could not read cpu-code, ret=%d\n", __func__,
ret);
return 0;
}
/* specification: SoC variant, e.g. 0xA for RK3588J and 0x13 for
RK3588S */
ret = misc_read(dev, RK3588_OTP_SPECIFICATION_OFFSET,
&specification, 1);
Any register to find the operating temperature of the chip?
Not that I know of or have looked into, downstream kernel have opp-info and leakage nvmem cells, and similar exists on rk356x, however my rk356x boards all had 0x0 in opp-info cells.
Regards, Jonas
Jagan.

Hi Jonas,
On 11/2/24 9:37 PM, Jonas Karlman wrote:
Implement checkboard() to print current SoC model used by a board, e.g. one of:
SoC: RK3582 v1 SoC: RK3588 v0 SoC: RK3588 v1 SoC: RK3588S v0 SoC: RK3588S v1 SoC: RK3588S2 v1
when U-Boot proper is running.
U-Boot 2025.01-rc1 (Nov 02 2024 - 20:19:01 +0000)
Model: Generic RK3588S/RK3588 SoC: RK3588S2 v1 DRAM: 8 GiB
Information about the SoC model, variant and version is read from OTP.
Also update rk3588s-u-boot.dtsi to include OTP in U-Boot pre-reloc phase, where checkboard() is called.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
v2:
- Update commit message
- Update code comments
- Drop generic-rk3588_defconfig change
arch/arm/dts/rk3588s-u-boot.dtsi | 4 ++ arch/arm/mach-rockchip/rk3588/rk3588.c | 58 ++++++++++++++++++++++++++ 2 files changed, 62 insertions(+)
diff --git a/arch/arm/dts/rk3588s-u-boot.dtsi b/arch/arm/dts/rk3588s-u-boot.dtsi index 09d8b311cec5..8880d162b11c 100644 --- a/arch/arm/dts/rk3588s-u-boot.dtsi +++ b/arch/arm/dts/rk3588s-u-boot.dtsi @@ -69,6 +69,10 @@ bootph-all; };
+&otp {
- bootph-some-ram;
+};
- &pcfg_pull_down { bootph-all; };
diff --git a/arch/arm/mach-rockchip/rk3588/rk3588.c b/arch/arm/mach-rockchip/rk3588/rk3588.c index e2dac2a5b806..f9da7a6f1477 100644 --- a/arch/arm/mach-rockchip/rk3588/rk3588.c +++ b/arch/arm/mach-rockchip/rk3588/rk3588.c @@ -4,6 +4,8 @@
- Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
*/
+#include <dm.h> +#include <misc.h> #include <spl.h> #include <asm/armv8/mmu.h> #include <asm/arch-rockchip/bootrom.h> @@ -178,3 +180,59 @@ int arch_cpu_init(void) return 0; } #endif
+#define RK3588_OTP_CPU_CODE_OFFSET 0x02 +#define RK3588_OTP_SPECIFICATION_OFFSET 0x06 +#define RK3588_OTP_CPU_VERSION_OFFSET 0x1c
+int checkboard(void) +{
- u8 cpu_code[2], specification, package, cpu_version;
- struct udevice *dev;
- char suffix[3];
- int ret;
- ret = uclass_get_device_by_driver(UCLASS_MISC,
DM_DRIVER_GET(rockchip_otp), &dev);
- if (ret) {
debug("%s: could not find otp device, ret=%d\n", __func__, ret);
We should probably start using log_debug instead?
I guess with #define LOG_CATEGORY LOGC_ARCH
at the top?
return 0;
- }
- /* cpu-code: SoC model, e.g. 0x35 0x82 or 0x35 0x88 */
- ret = misc_read(dev, RK3588_OTP_CPU_CODE_OFFSET, cpu_code, 2);
This will fail if CONFIG_MISC=n which is neither selected nor implied for RK3588.
I tested on multiple RK3588 Jaguar, and the commercial (RK3588) grade ones all showed RK3588 v0.
The one industrial grade (RK3588J) showed RK3588J v1.
I'm really not sure what this version number is for. If even Kever doesn't know what it means, I am not sure it makes sense to print it?
FWIW, the Linux kernel now exposes different nvmem devices for each cell and since we have a cell defined for the three OTP ranges you're using here, maybe it'd make sense to use that instead of hardcoding the offsets and size in here? Not a blocker for this though as I don't think it brings THAT much value to those fixed NVMEM layouts.
Cheers, Quentin

Hi Quentin,
On 2024-11-07 13:01, Quentin Schulz wrote:
Hi Jonas,
On 11/2/24 9:37 PM, Jonas Karlman wrote:
Implement checkboard() to print current SoC model used by a board, e.g. one of:
SoC: RK3582 v1 SoC: RK3588 v0 SoC: RK3588 v1 SoC: RK3588S v0 SoC: RK3588S v1 SoC: RK3588S2 v1
when U-Boot proper is running.
U-Boot 2025.01-rc1 (Nov 02 2024 - 20:19:01 +0000)
Model: Generic RK3588S/RK3588 SoC: RK3588S2 v1 DRAM: 8 GiB
Information about the SoC model, variant and version is read from OTP.
Also update rk3588s-u-boot.dtsi to include OTP in U-Boot pre-reloc phase, where checkboard() is called.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
v2:
- Update commit message
- Update code comments
- Drop generic-rk3588_defconfig change
arch/arm/dts/rk3588s-u-boot.dtsi | 4 ++ arch/arm/mach-rockchip/rk3588/rk3588.c | 58 ++++++++++++++++++++++++++ 2 files changed, 62 insertions(+)
diff --git a/arch/arm/dts/rk3588s-u-boot.dtsi b/arch/arm/dts/rk3588s-u-boot.dtsi index 09d8b311cec5..8880d162b11c 100644 --- a/arch/arm/dts/rk3588s-u-boot.dtsi +++ b/arch/arm/dts/rk3588s-u-boot.dtsi @@ -69,6 +69,10 @@ bootph-all; };
+&otp {
- bootph-some-ram;
+};
- &pcfg_pull_down { bootph-all; };
diff --git a/arch/arm/mach-rockchip/rk3588/rk3588.c b/arch/arm/mach-rockchip/rk3588/rk3588.c index e2dac2a5b806..f9da7a6f1477 100644 --- a/arch/arm/mach-rockchip/rk3588/rk3588.c +++ b/arch/arm/mach-rockchip/rk3588/rk3588.c @@ -4,6 +4,8 @@
- Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
*/
+#include <dm.h> +#include <misc.h> #include <spl.h> #include <asm/armv8/mmu.h> #include <asm/arch-rockchip/bootrom.h> @@ -178,3 +180,59 @@ int arch_cpu_init(void) return 0; } #endif
+#define RK3588_OTP_CPU_CODE_OFFSET 0x02 +#define RK3588_OTP_SPECIFICATION_OFFSET 0x06 +#define RK3588_OTP_CPU_VERSION_OFFSET 0x1c
+int checkboard(void) +{
- u8 cpu_code[2], specification, package, cpu_version;
- struct udevice *dev;
- char suffix[3];
- int ret;
- ret = uclass_get_device_by_driver(UCLASS_MISC,
DM_DRIVER_GET(rockchip_otp), &dev);
- if (ret) {
debug("%s: could not find otp device, ret=%d\n", __func__, ret);
We should probably start using log_debug instead?
I guess we should?, not sure why there is two different and what the difference is. Have typically only ever used debug() or printf(), so I just went with what was used in the code copied from board.c.
I guess with #define LOG_CATEGORY LOGC_ARCH
at the top?
I can give it a try, what/how is the log category used for?
My simple debug workflow is just to add a '#define LOG_DEBUG' at top of a file when I want some more debug info.
return 0;
- }
- /* cpu-code: SoC model, e.g. 0x35 0x82 or 0x35 0x88 */
- ret = misc_read(dev, RK3588_OTP_CPU_CODE_OFFSET, cpu_code, 2);
This will fail if CONFIG_MISC=n which is neither selected nor implied for RK3588.
Good catch, did not test that scenario, will fix in a v3.
I tested on multiple RK3588 Jaguar, and the commercial (RK3588) grade ones all showed RK3588 v0.
The one industrial grade (RK3588J) showed RK3588J v1.
Thanks for confirming this works on a J-variant.
I'm really not sure what this version number is for. If even Kever doesn't know what it means, I am not sure it makes sense to print it?
For rk356x there is some special handling for cpu-version <> 0 in vendor code, and DT describe a cpu-version nvmem cell, so thought it could be useful debug information. However it may just cause more confusion since there is no clear information on what the different cpu-version mean.
Will drop the cpu-version information in a v3.
FWIW, the Linux kernel now exposes different nvmem devices for each cell and since we have a cell defined for the three OTP ranges you're using here, maybe it'd make sense to use that instead of hardcoding the offsets and size in here? Not a blocker for this though as I don't think it brings THAT much value to those fixed NVMEM layouts.
Took a quick peek at nvmem cell support in U-Boot and look like 'bits' prop is not supported and nvmem-cells/nvmem-cell-names may have to be used.
Probably easier to use that in a future series that also converts this into a possible sysinfo driver using a DT node similar to:
sysinfo { compatible = "rockchip,rk3588-sysinfo"; bootph-some-ram; nvmem-cells = <&cpu_code>, <&otp_id>, ...; nvmem-cell-names = "soc", "id", ...; };
Something for the future :-)
Regards, Jonas
Cheers, Quentin

Hi Jonas,
On 11/7/24 3:29 PM, Jonas Karlman wrote:
Hi Quentin,
On 2024-11-07 13:01, Quentin Schulz wrote:
Hi Jonas,
On 11/2/24 9:37 PM, Jonas Karlman wrote:
Implement checkboard() to print current SoC model used by a board, e.g. one of:
SoC: RK3582 v1 SoC: RK3588 v0 SoC: RK3588 v1 SoC: RK3588S v0 SoC: RK3588S v1 SoC: RK3588S2 v1
when U-Boot proper is running.
U-Boot 2025.01-rc1 (Nov 02 2024 - 20:19:01 +0000) Model: Generic RK3588S/RK3588 SoC: RK3588S2 v1 DRAM: 8 GiB
Information about the SoC model, variant and version is read from OTP.
Also update rk3588s-u-boot.dtsi to include OTP in U-Boot pre-reloc phase, where checkboard() is called.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
v2:
- Update commit message
- Update code comments
- Drop generic-rk3588_defconfig change
arch/arm/dts/rk3588s-u-boot.dtsi | 4 ++ arch/arm/mach-rockchip/rk3588/rk3588.c | 58 ++++++++++++++++++++++++++ 2 files changed, 62 insertions(+)
diff --git a/arch/arm/dts/rk3588s-u-boot.dtsi b/arch/arm/dts/rk3588s-u-boot.dtsi index 09d8b311cec5..8880d162b11c 100644 --- a/arch/arm/dts/rk3588s-u-boot.dtsi +++ b/arch/arm/dts/rk3588s-u-boot.dtsi @@ -69,6 +69,10 @@ bootph-all; };
+&otp {
- bootph-some-ram;
+};
- &pcfg_pull_down { bootph-all; };
diff --git a/arch/arm/mach-rockchip/rk3588/rk3588.c b/arch/arm/mach-rockchip/rk3588/rk3588.c index e2dac2a5b806..f9da7a6f1477 100644 --- a/arch/arm/mach-rockchip/rk3588/rk3588.c +++ b/arch/arm/mach-rockchip/rk3588/rk3588.c @@ -4,6 +4,8 @@ * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd. */
+#include <dm.h> +#include <misc.h> #include <spl.h> #include <asm/armv8/mmu.h> #include <asm/arch-rockchip/bootrom.h> @@ -178,3 +180,59 @@ int arch_cpu_init(void) return 0; } #endif
+#define RK3588_OTP_CPU_CODE_OFFSET 0x02 +#define RK3588_OTP_SPECIFICATION_OFFSET 0x06 +#define RK3588_OTP_CPU_VERSION_OFFSET 0x1c
+int checkboard(void) +{
- u8 cpu_code[2], specification, package, cpu_version;
- struct udevice *dev;
- char suffix[3];
- int ret;
- ret = uclass_get_device_by_driver(UCLASS_MISC,
DM_DRIVER_GET(rockchip_otp), &dev);
- if (ret) {
debug("%s: could not find otp device, ret=%d\n", __func__, ret);
We should probably start using log_debug instead?
I guess we should?, not sure why there is two different and what the difference is. Have typically only ever used debug() or printf(), so I just went with what was used in the code copied from board.c.
But I think that doing this also build the assert() in?
I guess with #define LOG_CATEGORY LOGC_ARCH
at the top?
I can give it a try, what/how is the log category used for?
My simple debug workflow is just to add a '#define LOG_DEBUG' at top of a file when I want some more debug info.
This defines DEBUG which then defines _DEBUG to 1 which enables assert().
Not sure how to selectively increase the log level for a specific drivers/class though but the docs[1] say #define LOG_DEBUG. And if I trust my ability to read C, it'll end up also enabling assert()s...
I think those should not be enabled with the same constant but that's where we stand today.
[1] https://docs.u-boot.org/en/latest/develop/logging.html#temporary-logging-wit...
Cheers, Quentin

Hi Jonas,
On 2024/11/7 22:29, Jonas Karlman wrote:
Hi Quentin,
On 2024-11-07 13:01, Quentin Schulz wrote:
Hi Jonas,
On 11/2/24 9:37 PM, Jonas Karlman wrote:
Implement checkboard() to print current SoC model used by a board, e.g. one of:
SoC: RK3582 v1 SoC: RK3588 v0 SoC: RK3588 v1 SoC: RK3588S v0 SoC: RK3588S v1 SoC: RK3588S2 v1
when U-Boot proper is running.
U-Boot 2025.01-rc1 (Nov 02 2024 - 20:19:01 +0000) Model: Generic RK3588S/RK3588 SoC: RK3588S2 v1 DRAM: 8 GiB
Information about the SoC model, variant and version is read from OTP.
Also update rk3588s-u-boot.dtsi to include OTP in U-Boot pre-reloc phase, where checkboard() is called.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
v2:
- Update commit message
- Update code comments
- Drop generic-rk3588_defconfig change
arch/arm/dts/rk3588s-u-boot.dtsi | 4 ++ arch/arm/mach-rockchip/rk3588/rk3588.c | 58 ++++++++++++++++++++++++++ 2 files changed, 62 insertions(+)
diff --git a/arch/arm/dts/rk3588s-u-boot.dtsi b/arch/arm/dts/rk3588s-u-boot.dtsi index 09d8b311cec5..8880d162b11c 100644 --- a/arch/arm/dts/rk3588s-u-boot.dtsi +++ b/arch/arm/dts/rk3588s-u-boot.dtsi @@ -69,6 +69,10 @@ bootph-all; };
+&otp {
- bootph-some-ram;
+};
- &pcfg_pull_down { bootph-all; };
diff --git a/arch/arm/mach-rockchip/rk3588/rk3588.c b/arch/arm/mach-rockchip/rk3588/rk3588.c index e2dac2a5b806..f9da7a6f1477 100644 --- a/arch/arm/mach-rockchip/rk3588/rk3588.c +++ b/arch/arm/mach-rockchip/rk3588/rk3588.c @@ -4,6 +4,8 @@ * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd. */
+#include <dm.h> +#include <misc.h> #include <spl.h> #include <asm/armv8/mmu.h> #include <asm/arch-rockchip/bootrom.h> @@ -178,3 +180,59 @@ int arch_cpu_init(void) return 0; } #endif
+#define RK3588_OTP_CPU_CODE_OFFSET 0x02 +#define RK3588_OTP_SPECIFICATION_OFFSET 0x06 +#define RK3588_OTP_CPU_VERSION_OFFSET 0x1c
+int checkboard(void) +{
- u8 cpu_code[2], specification, package, cpu_version;
- struct udevice *dev;
- char suffix[3];
- int ret;
- ret = uclass_get_device_by_driver(UCLASS_MISC,
DM_DRIVER_GET(rockchip_otp), &dev);
- if (ret) {
debug("%s: could not find otp device, ret=%d\n", __func__, ret);
We should probably start using log_debug instead?
I guess we should?, not sure why there is two different and what the difference is. Have typically only ever used debug() or printf(), so I just went with what was used in the code copied from board.c.
I guess with #define LOG_CATEGORY LOGC_ARCH
at the top?
I can give it a try, what/how is the log category used for?
My simple debug workflow is just to add a '#define LOG_DEBUG' at top of a file when I want some more debug info.
return 0;
- }
- /* cpu-code: SoC model, e.g. 0x35 0x82 or 0x35 0x88 */
- ret = misc_read(dev, RK3588_OTP_CPU_CODE_OFFSET, cpu_code, 2);
This will fail if CONFIG_MISC=n which is neither selected nor implied for RK3588.
Good catch, did not test that scenario, will fix in a v3.
I tested on multiple RK3588 Jaguar, and the commercial (RK3588) grade ones all showed RK3588 v0.
The one industrial grade (RK3588J) showed RK3588J v1.
Thanks for confirming this works on a J-variant.
I'm really not sure what this version number is for. If even Kever doesn't know what it means, I am not sure it makes sense to print it?
For rk356x there is some special handling for cpu-version <> 0 in vendor code, and DT describe a cpu-version nvmem cell, so thought it could be useful debug information. However it may just cause more confusion since there is no clear information on what the different cpu-version mean.
Will drop the cpu-version information in a v3.
Yes, this cpu-version does not help users, I think it may be one of the silicon version(
The process may change in foundry), package version(change in package factory),
and we don't know the detail about there difference.
We can print the useful info which sync with the mark on the chip.
For RV series chip set, it may integrate with difference size DRAM in package, and with
different mark name, not sure if we have info for that.
Thanks, - Kever
FWIW, the Linux kernel now exposes different nvmem devices for each cell and since we have a cell defined for the three OTP ranges you're using here, maybe it'd make sense to use that instead of hardcoding the offsets and size in here? Not a blocker for this though as I don't think it brings THAT much value to those fixed NVMEM layouts.
Took a quick peek at nvmem cell support in U-Boot and look like 'bits' prop is not supported and nvmem-cells/nvmem-cell-names may have to be used.
Probably easier to use that in a future series that also converts this into a possible sysinfo driver using a DT node similar to:
sysinfo { compatible = "rockchip,rk3588-sysinfo"; bootph-some-ram; nvmem-cells = <&cpu_code>, <&otp_id>, ...; nvmem-cell-names = "soc", "id", ...; };
Something for the future :-)
Regards, Jonas
Cheers, Quentin

On Fri, 8 Nov 2024 at 09:10, Kever Yang kever.yang@rock-chips.com wrote:
Hi Jonas,
On 2024/11/7 22:29, Jonas Karlman wrote:
Hi Quentin,
On 2024-11-07 13:01, Quentin Schulz wrote:
Hi Jonas,
On 11/2/24 9:37 PM, Jonas Karlman wrote:
Implement checkboard() to print current SoC model used by a board, e.g. one of:
SoC: RK3582 v1 SoC: RK3588 v0 SoC: RK3588 v1 SoC: RK3588S v0 SoC: RK3588S v1 SoC: RK3588S2 v1
when U-Boot proper is running.
U-Boot 2025.01-rc1 (Nov 02 2024 - 20:19:01 +0000) Model: Generic RK3588S/RK3588 SoC: RK3588S2 v1 DRAM: 8 GiB
Information about the SoC model, variant and version is read from OTP.
Also update rk3588s-u-boot.dtsi to include OTP in U-Boot pre-reloc phase, where checkboard() is called.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
v2:
- Update commit message
- Update code comments
- Drop generic-rk3588_defconfig change
arch/arm/dts/rk3588s-u-boot.dtsi | 4 ++ arch/arm/mach-rockchip/rk3588/rk3588.c | 58 ++++++++++++++++++++++++++ 2 files changed, 62 insertions(+)
diff --git a/arch/arm/dts/rk3588s-u-boot.dtsi b/arch/arm/dts/rk3588s-u-boot.dtsi index 09d8b311cec5..8880d162b11c 100644 --- a/arch/arm/dts/rk3588s-u-boot.dtsi +++ b/arch/arm/dts/rk3588s-u-boot.dtsi @@ -69,6 +69,10 @@ bootph-all; };
+&otp {
- bootph-some-ram;
+};
- &pcfg_pull_down { bootph-all; };
diff --git a/arch/arm/mach-rockchip/rk3588/rk3588.c b/arch/arm/mach-rockchip/rk3588/rk3588.c index e2dac2a5b806..f9da7a6f1477 100644 --- a/arch/arm/mach-rockchip/rk3588/rk3588.c +++ b/arch/arm/mach-rockchip/rk3588/rk3588.c @@ -4,6 +4,8 @@ * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd. */
+#include <dm.h> +#include <misc.h> #include <spl.h> #include <asm/armv8/mmu.h> #include <asm/arch-rockchip/bootrom.h> @@ -178,3 +180,59 @@ int arch_cpu_init(void) return 0; } #endif
+#define RK3588_OTP_CPU_CODE_OFFSET 0x02 +#define RK3588_OTP_SPECIFICATION_OFFSET 0x06 +#define RK3588_OTP_CPU_VERSION_OFFSET 0x1c
+int checkboard(void) +{
- u8 cpu_code[2], specification, package, cpu_version;
- struct udevice *dev;
- char suffix[3];
- int ret;
- ret = uclass_get_device_by_driver(UCLASS_MISC,
DM_DRIVER_GET(rockchip_otp), &dev);
- if (ret) {
debug("%s: could not find otp device, ret=%d\n", __func__, ret);
We should probably start using log_debug instead?
I guess we should?, not sure why there is two different and what the difference is. Have typically only ever used debug() or printf(), so I just went with what was used in the code copied from board.c.
I guess with #define LOG_CATEGORY LOGC_ARCH
at the top?
I can give it a try, what/how is the log category used for?
My simple debug workflow is just to add a '#define LOG_DEBUG' at top of a file when I want some more debug info.
return 0;
- }
- /* cpu-code: SoC model, e.g. 0x35 0x82 or 0x35 0x88 */
- ret = misc_read(dev, RK3588_OTP_CPU_CODE_OFFSET, cpu_code, 2);
This will fail if CONFIG_MISC=n which is neither selected nor implied for RK3588.
Good catch, did not test that scenario, will fix in a v3.
I tested on multiple RK3588 Jaguar, and the commercial (RK3588) grade ones all showed RK3588 v0.
The one industrial grade (RK3588J) showed RK3588J v1.
Thanks for confirming this works on a J-variant.
I'm really not sure what this version number is for. If even Kever doesn't know what it means, I am not sure it makes sense to print it?
For rk356x there is some special handling for cpu-version <> 0 in vendor code, and DT describe a cpu-version nvmem cell, so thought it could be useful debug information. However it may just cause more confusion since there is no clear information on what the different cpu-version mean.
Will drop the cpu-version information in a v3.
Yes, this cpu-version does not help users, I think it may be one of the silicon version(
The process may change in foundry), package version(change in package factory),
Apart from package number chip versions like RK3588, RK3588J and RK3588M would be much beneficial when we boot multi-dtb from SPL and load the respective silicon dtb in u-boot proper. So, chip numbers, temperature (if possible) are useful like imx chips supported so far.
Thanks, Jagan.

Hi Jagan,
On 11/8/24 9:55 AM, Jagan Teki wrote:
On Fri, 8 Nov 2024 at 09:10, Kever Yang kever.yang@rock-chips.com wrote:
Hi Jonas,
On 2024/11/7 22:29, Jonas Karlman wrote:
Hi Quentin,
On 2024-11-07 13:01, Quentin Schulz wrote:
Hi Jonas,
On 11/2/24 9:37 PM, Jonas Karlman wrote:
Implement checkboard() to print current SoC model used by a board, e.g. one of:
SoC: RK3582 v1 SoC: RK3588 v0 SoC: RK3588 v1 SoC: RK3588S v0 SoC: RK3588S v1 SoC: RK3588S2 v1
when U-Boot proper is running.
U-Boot 2025.01-rc1 (Nov 02 2024 - 20:19:01 +0000) Model: Generic RK3588S/RK3588 SoC: RK3588S2 v1 DRAM: 8 GiB
Information about the SoC model, variant and version is read from OTP.
Also update rk3588s-u-boot.dtsi to include OTP in U-Boot pre-reloc phase, where checkboard() is called.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
v2:
- Update commit message
- Update code comments
- Drop generic-rk3588_defconfig change
arch/arm/dts/rk3588s-u-boot.dtsi | 4 ++ arch/arm/mach-rockchip/rk3588/rk3588.c | 58 ++++++++++++++++++++++++++ 2 files changed, 62 insertions(+)
diff --git a/arch/arm/dts/rk3588s-u-boot.dtsi b/arch/arm/dts/rk3588s-u-boot.dtsi index 09d8b311cec5..8880d162b11c 100644 --- a/arch/arm/dts/rk3588s-u-boot.dtsi +++ b/arch/arm/dts/rk3588s-u-boot.dtsi @@ -69,6 +69,10 @@ bootph-all; };
+&otp {
- bootph-some-ram;
+};
- &pcfg_pull_down { bootph-all; };
diff --git a/arch/arm/mach-rockchip/rk3588/rk3588.c b/arch/arm/mach-rockchip/rk3588/rk3588.c index e2dac2a5b806..f9da7a6f1477 100644 --- a/arch/arm/mach-rockchip/rk3588/rk3588.c +++ b/arch/arm/mach-rockchip/rk3588/rk3588.c @@ -4,6 +4,8 @@ * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd. */
+#include <dm.h> +#include <misc.h> #include <spl.h> #include <asm/armv8/mmu.h> #include <asm/arch-rockchip/bootrom.h> @@ -178,3 +180,59 @@ int arch_cpu_init(void) return 0; } #endif
+#define RK3588_OTP_CPU_CODE_OFFSET 0x02 +#define RK3588_OTP_SPECIFICATION_OFFSET 0x06 +#define RK3588_OTP_CPU_VERSION_OFFSET 0x1c
+int checkboard(void) +{
- u8 cpu_code[2], specification, package, cpu_version;
- struct udevice *dev;
- char suffix[3];
- int ret;
- ret = uclass_get_device_by_driver(UCLASS_MISC,
DM_DRIVER_GET(rockchip_otp), &dev);
- if (ret) {
debug("%s: could not find otp device, ret=%d\n", __func__, ret);
We should probably start using log_debug instead?
I guess we should?, not sure why there is two different and what the difference is. Have typically only ever used debug() or printf(), so I just went with what was used in the code copied from board.c.
I guess with #define LOG_CATEGORY LOGC_ARCH
at the top?
I can give it a try, what/how is the log category used for?
My simple debug workflow is just to add a '#define LOG_DEBUG' at top of a file when I want some more debug info.
return 0;
- }
- /* cpu-code: SoC model, e.g. 0x35 0x82 or 0x35 0x88 */
- ret = misc_read(dev, RK3588_OTP_CPU_CODE_OFFSET, cpu_code, 2);
This will fail if CONFIG_MISC=n which is neither selected nor implied for RK3588.
Good catch, did not test that scenario, will fix in a v3.
I tested on multiple RK3588 Jaguar, and the commercial (RK3588) grade ones all showed RK3588 v0.
The one industrial grade (RK3588J) showed RK3588J v1.
Thanks for confirming this works on a J-variant.
I'm really not sure what this version number is for. If even Kever doesn't know what it means, I am not sure it makes sense to print it?
For rk356x there is some special handling for cpu-version <> 0 in vendor code, and DT describe a cpu-version nvmem cell, so thought it could be useful debug information. However it may just cause more confusion since there is no clear information on what the different cpu-version mean.
Will drop the cpu-version information in a v3.
Yes, this cpu-version does not help users, I think it may be one of the silicon version(
The process may change in foundry), package version(change in package factory),
Apart from package number chip versions like RK3588, RK3588J and RK3588M would be much beneficial when we boot multi-dtb from SPL and load the respective silicon dtb in u-boot proper. So, chip numbers, temperature (if possible) are useful like imx chips supported so far.
I mean... can't we just derive the operating temperature from the variant? It's pretty public what the operating range is for each SoC and its variants, so not sure what exactly you're after?
I think we agreed on keeping the printing of the variant in there, so that should be enough to derive the operating range?
We would probably need another mechanism to expose the variant to the rest of the code so it can be used by the SPL to load a multi-dtb proper (or at the very least have proper select the appropriate DTB from a multi-dtb kernel fitimage).
Cheers, Quentin

Implement checkboard() to print current SoC variant used by a board, e.g. one of:
SoC: RK3308 SoC: RK3308B SoC: RK3308B-S
when U-Boot proper is running.
U-Boot 2025.01-rc1 (Nov 02 2024 - 20:26:25 +0000)
Model: Radxa ROCK Pi S SoC: RK3308B DRAM: 512 MiB (effective 510 MiB)
Information about the SoC variant is read from GRF.
Signed-off-by: Jonas Karlman jonas@kwiboo.se --- v2: New patch --- arch/arm/mach-rockchip/rk3308/rk3308.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/arch/arm/mach-rockchip/rk3308/rk3308.c b/arch/arm/mach-rockchip/rk3308/rk3308.c index c6b1a35f47e6..03d97e1d7460 100644 --- a/arch/arm/mach-rockchip/rk3308/rk3308.c +++ b/arch/arm/mach-rockchip/rk3308/rk3308.c @@ -216,3 +216,19 @@ int arch_cpu_init(void) return 0; } #endif + +#define RK3308_GRF_CHIP_ID 0xFF000800 + +int checkboard(void) +{ + u32 chip_id = readl(RK3308_GRF_CHIP_ID); + + if (chip_id == 0x3308) + printf("SoC: RK3308B\n"); + else if (chip_id == 0x3308c) + printf("SoC: RK3308B-S\n"); + else + printf("SoC: RK3308\n"); + + return 0; +}
participants (4)
-
Jagan Teki
-
Jonas Karlman
-
Kever Yang
-
Quentin Schulz