[PATCH 00/11] rockchip: Add efuse and otp support to more SoCs

This series refactors and add support for more SoCs to the rockchip efuse and otp driver.
Support is added for the following SoCs: - efuse: RK3036, RK3066, RK3128, RK3188, RK3228, RK3288 and RK3328 - otp: RK3568 and RK3588
This also changes so that eth1addr is also set when there is a ethernet1 alias in the fdt. And a small change so that ethernet addresses is set based on CONFIG_HASH and CONFIG_SHA256 instead of CONFIG_CMD_NET.
I have only been able to test the efuse driver on RK3288, RK3328, RK3399 and the otp driver on RK3568 and RK3588. Information on the remaining SoCs is based on information at [1], [2] and in TRM.
The final patch enables use of the otp driver for RK3568. To handle this SoCs unique cpuid offset a new const CFG_CPUID_OFFSET was added.
Ideally, we should get this cpuid offset from the id node in the fdt. Maybe adding a custom ioctl that these drivers support and misc.c can call to get the cpuid. Something that can be improved in a future series.
This series can also be found at [3].
[1] https://github.com/rockchip-linux/kernel/blob/release-3.10/arch/arm/mach-roc... [2] https://github.com/rockchip-linux/kernel/blob/develop-5.10/drivers/nvmem/roc... [2] https://github.com/Kwiboo/u-boot-rockchip/commits/rk3568-efuse-otp
Jonas Karlman (11): rockchip: otp: Refactor to use driver data and ops rockchip: otp: Add support for RK3568 rockchip: otp: Add support for RK3588 rockchip: otp: Add dump_otp debug command rockchip: efuse: Refactor to use driver data and ops rockchip: efuse: Add support for RK3288 and more rockchip: efuse: Add support for RK3328 rockchip: efuse: Add support for RK3128 rockchip: efuse: Add support for RK3036 rockchip: misc: Set eth1addr mac address rockchip: rk3568: Read cpuid from otp
arch/arm/dts/rk356x-u-boot.dtsi | 12 ++ arch/arm/mach-rockchip/Kconfig | 2 + arch/arm/mach-rockchip/board.c | 2 +- arch/arm/mach-rockchip/misc.c | 10 +- drivers/misc/Kconfig | 4 - drivers/misc/rockchip-efuse.c | 333 +++++++++++++++++++++++------- drivers/misc/rockchip-otp.c | 230 +++++++++++++++++---- include/configs/rk3568_common.h | 3 + include/configs/rockchip-common.h | 2 + 9 files changed, 480 insertions(+), 118 deletions(-)

Refactor the driver to use driver data and ops to simplify handling of SoCs that require a unique read op.
Use readl_poll_sleep_timeout instead of a custom poll loop, and add validation of input parameter to main read op.
Signed-off-by: Jonas Karlman jonas@kwiboo.se --- drivers/misc/rockchip-otp.c | 83 +++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 40 deletions(-)
diff --git a/drivers/misc/rockchip-otp.c b/drivers/misc/rockchip-otp.c index cc9a5450e0ce..a6df0834ebbc 100644 --- a/drivers/misc/rockchip-otp.c +++ b/drivers/misc/rockchip-otp.c @@ -5,10 +5,10 @@
#include <common.h> #include <asm/io.h> -#include <command.h> #include <dm.h> #include <linux/bitops.h> #include <linux/delay.h> +#include <linux/iopoll.h> #include <misc.h>
/* OTP Register Offsets */ @@ -49,35 +49,31 @@
struct rockchip_otp_plat { void __iomem *base; - unsigned long secure_conf_base; - unsigned long otp_mask_base; };
-static int rockchip_otp_wait_status(struct rockchip_otp_plat *otp, - u32 flag) +struct rockchip_otp_data { + int (*read)(struct udevice *dev, int offset, void *buf, int size); + int size; +}; + +static int rockchip_otp_poll_timeout(struct rockchip_otp_plat *otp, u32 flag) { - int delay = OTPC_TIMEOUT; - - while (!(readl(otp->base + OTPC_INT_STATUS) & flag)) { - udelay(1); - delay--; - if (delay <= 0) { - printf("%s: wait init status timeout\n", __func__); - return -ETIMEDOUT; - } - } + u32 status; + int ret; + + ret = readl_poll_sleep_timeout(otp->base + OTPC_INT_STATUS, status, + (status & flag), 1, OTPC_TIMEOUT); + if (ret) + return ret;
- /* clean int status */ + /* Clear int flag */ writel(flag, otp->base + OTPC_INT_STATUS);
return 0; }
-static int rockchip_otp_ecc_enable(struct rockchip_otp_plat *otp, - bool enable) +static int rockchip_otp_ecc_enable(struct rockchip_otp_plat *otp, bool enable) { - int ret = 0; - writel(SBPI_DAP_ADDR_MASK | (SBPI_DAP_ADDR << SBPI_DAP_ADDR_SHIFT), otp->base + OTPC_SBPI_CTRL);
@@ -92,11 +88,7 @@ static int rockchip_otp_ecc_enable(struct rockchip_otp_plat *otp,
writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL);
- ret = rockchip_otp_wait_status(otp, OTPC_SBPI_DONE); - if (ret < 0) - printf("%s timeout during ecc_enable\n", __func__); - - return ret; + return rockchip_otp_poll_timeout(otp, OTPC_SBPI_DONE); }
static int rockchip_px30_otp_read(struct udevice *dev, int offset, @@ -104,27 +96,24 @@ static int rockchip_px30_otp_read(struct udevice *dev, int offset, { struct rockchip_otp_plat *otp = dev_get_plat(dev); u8 *buffer = buf; - int ret = 0; + int ret;
ret = rockchip_otp_ecc_enable(otp, false); - if (ret < 0) { - printf("%s rockchip_otp_ecc_enable err\n", __func__); + if (ret) return ret; - }
writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); udelay(5); + while (size--) { writel(offset++ | OTPC_USER_ADDR_MASK, otp->base + OTPC_USER_ADDR); writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK, otp->base + OTPC_USER_ENABLE);
- ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE); - if (ret < 0) { - printf("%s timeout during read setup\n", __func__); + ret = rockchip_otp_poll_timeout(otp, OTPC_USER_DONE); + if (ret) goto read_end; - }
*buffer++ = readb(otp->base + OTPC_USER_Q); } @@ -138,7 +127,16 @@ read_end: static int rockchip_otp_read(struct udevice *dev, int offset, void *buf, int size) { - return rockchip_px30_otp_read(dev, offset, buf, size); + const struct rockchip_otp_data *data = + (void *)dev_get_driver_data(dev); + + if (offset < 0 || !buf || size <= 0 || offset + size > data->size) + return -EINVAL; + + if (!data->read) + return -ENOSYS; + + return data->read(dev, offset, buf, size); }
static const struct misc_ops rockchip_otp_ops = { @@ -147,21 +145,26 @@ static const struct misc_ops rockchip_otp_ops = {
static int rockchip_otp_of_to_plat(struct udevice *dev) { - struct rockchip_otp_plat *otp = dev_get_plat(dev); + struct rockchip_otp_plat *plat = dev_get_plat(dev);
- otp->base = dev_read_addr_ptr(dev); + plat->base = dev_read_addr_ptr(dev);
return 0; }
+static const struct rockchip_otp_data px30_data = { + .read = rockchip_px30_otp_read, + .size = 0x40, +}; + static const struct udevice_id rockchip_otp_ids[] = { { .compatible = "rockchip,px30-otp", - .data = (ulong)&rockchip_px30_otp_read, + .data = (ulong)&px30_data, }, { .compatible = "rockchip,rk3308-otp", - .data = (ulong)&rockchip_px30_otp_read, + .data = (ulong)&px30_data, }, {} }; @@ -170,7 +173,7 @@ U_BOOT_DRIVER(rockchip_otp) = { .name = "rockchip_otp", .id = UCLASS_MISC, .of_match = rockchip_otp_ids, - .ops = &rockchip_otp_ops, .of_to_plat = rockchip_otp_of_to_plat, - .plat_auto = sizeof(struct rockchip_otp_plat), + .plat_auto = sizeof(struct rockchip_otp_plat), + .ops = &rockchip_otp_ops, };

Hi Jonas,
Thanks for your patches.
On 2023/2/16 07:48, Jonas Karlman wrote:
Refactor the driver to use driver data and ops to simplify handling of SoCs that require a unique read op.
Use readl_poll_sleep_timeout instead of a custom poll loop, and add validation of input parameter to main read op.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Thanks, - Kever
drivers/misc/rockchip-otp.c | 83 +++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 40 deletions(-)
diff --git a/drivers/misc/rockchip-otp.c b/drivers/misc/rockchip-otp.c index cc9a5450e0ce..a6df0834ebbc 100644 --- a/drivers/misc/rockchip-otp.c +++ b/drivers/misc/rockchip-otp.c @@ -5,10 +5,10 @@
#include <common.h> #include <asm/io.h> -#include <command.h> #include <dm.h> #include <linux/bitops.h> #include <linux/delay.h> +#include <linux/iopoll.h> #include <misc.h>
/* OTP Register Offsets */ @@ -49,35 +49,31 @@
struct rockchip_otp_plat { void __iomem *base;
- unsigned long secure_conf_base;
- unsigned long otp_mask_base; };
-static int rockchip_otp_wait_status(struct rockchip_otp_plat *otp,
u32 flag)
+struct rockchip_otp_data {
- int (*read)(struct udevice *dev, int offset, void *buf, int size);
- int size;
+};
+static int rockchip_otp_poll_timeout(struct rockchip_otp_plat *otp, u32 flag) {
- int delay = OTPC_TIMEOUT;
- while (!(readl(otp->base + OTPC_INT_STATUS) & flag)) {
udelay(1);
delay--;
if (delay <= 0) {
printf("%s: wait init status timeout\n", __func__);
return -ETIMEDOUT;
}
- }
- u32 status;
- int ret;
- ret = readl_poll_sleep_timeout(otp->base + OTPC_INT_STATUS, status,
(status & flag), 1, OTPC_TIMEOUT);
- if (ret)
return ret;
- /* clean int status */
/* Clear int flag */ writel(flag, otp->base + OTPC_INT_STATUS);
return 0; }
-static int rockchip_otp_ecc_enable(struct rockchip_otp_plat *otp,
bool enable)
+static int rockchip_otp_ecc_enable(struct rockchip_otp_plat *otp, bool enable) {
- int ret = 0;
- writel(SBPI_DAP_ADDR_MASK | (SBPI_DAP_ADDR << SBPI_DAP_ADDR_SHIFT), otp->base + OTPC_SBPI_CTRL);
@@ -92,11 +88,7 @@ static int rockchip_otp_ecc_enable(struct rockchip_otp_plat *otp,
writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL);
- ret = rockchip_otp_wait_status(otp, OTPC_SBPI_DONE);
- if (ret < 0)
printf("%s timeout during ecc_enable\n", __func__);
- return ret;
return rockchip_otp_poll_timeout(otp, OTPC_SBPI_DONE); }
static int rockchip_px30_otp_read(struct udevice *dev, int offset,
@@ -104,27 +96,24 @@ static int rockchip_px30_otp_read(struct udevice *dev, int offset, { struct rockchip_otp_plat *otp = dev_get_plat(dev); u8 *buffer = buf;
- int ret = 0;
int ret;
ret = rockchip_otp_ecc_enable(otp, false);
- if (ret < 0) {
printf("%s rockchip_otp_ecc_enable err\n", __func__);
- if (ret) return ret;
}
writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); udelay(5);
- while (size--) { writel(offset++ | OTPC_USER_ADDR_MASK, otp->base + OTPC_USER_ADDR); writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK, otp->base + OTPC_USER_ENABLE);
ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE);
if (ret < 0) {
printf("%s timeout during read setup\n", __func__);
ret = rockchip_otp_poll_timeout(otp, OTPC_USER_DONE);
if (ret) goto read_end;
}
*buffer++ = readb(otp->base + OTPC_USER_Q); }
@@ -138,7 +127,16 @@ read_end: static int rockchip_otp_read(struct udevice *dev, int offset, void *buf, int size) {
- return rockchip_px30_otp_read(dev, offset, buf, size);
const struct rockchip_otp_data *data =
(void *)dev_get_driver_data(dev);
if (offset < 0 || !buf || size <= 0 || offset + size > data->size)
return -EINVAL;
if (!data->read)
return -ENOSYS;
return data->read(dev, offset, buf, size); }
static const struct misc_ops rockchip_otp_ops = {
@@ -147,21 +145,26 @@ static const struct misc_ops rockchip_otp_ops = {
static int rockchip_otp_of_to_plat(struct udevice *dev) {
- struct rockchip_otp_plat *otp = dev_get_plat(dev);
- struct rockchip_otp_plat *plat = dev_get_plat(dev);
- otp->base = dev_read_addr_ptr(dev);
plat->base = dev_read_addr_ptr(dev);
return 0; }
+static const struct rockchip_otp_data px30_data = {
- .read = rockchip_px30_otp_read,
- .size = 0x40,
+};
- static const struct udevice_id rockchip_otp_ids[] = { { .compatible = "rockchip,px30-otp",
.data = (ulong)&rockchip_px30_otp_read,
}, { .compatible = "rockchip,rk3308-otp",.data = (ulong)&px30_data,
.data = (ulong)&rockchip_px30_otp_read,
}, {} };.data = (ulong)&px30_data,
@@ -170,7 +173,7 @@ U_BOOT_DRIVER(rockchip_otp) = { .name = "rockchip_otp", .id = UCLASS_MISC, .of_match = rockchip_otp_ids,
- .ops = &rockchip_otp_ops, .of_to_plat = rockchip_otp_of_to_plat,
- .plat_auto = sizeof(struct rockchip_otp_plat),
- .plat_auto = sizeof(struct rockchip_otp_plat),
- .ops = &rockchip_otp_ops, };

Add support for rk3568 compatible.
Handle allocation of an aligned bounce buffer in main read op in order to keep the SoC unique read op simple.
Signed-off-by: Jonas Karlman jonas@kwiboo.se --- drivers/misc/rockchip-otp.c | 67 ++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-)
diff --git a/drivers/misc/rockchip-otp.c b/drivers/misc/rockchip-otp.c index a6df0834ebbc..243c173cdb18 100644 --- a/drivers/misc/rockchip-otp.c +++ b/drivers/misc/rockchip-otp.c @@ -9,6 +9,7 @@ #include <linux/bitops.h> #include <linux/delay.h> #include <linux/iopoll.h> +#include <malloc.h> #include <misc.h>
/* OTP Register Offsets */ @@ -54,6 +55,7 @@ struct rockchip_otp_plat { struct rockchip_otp_data { int (*read)(struct udevice *dev, int offset, void *buf, int size); int size; + int block_size; };
static int rockchip_otp_poll_timeout(struct rockchip_otp_plat *otp, u32 flag) @@ -124,11 +126,47 @@ read_end: return ret; }
+static int rockchip_rk3568_otp_read(struct udevice *dev, int offset, + void *buf, int size) +{ + struct rockchip_otp_plat *otp = dev_get_plat(dev); + u16 *buffer = buf; + int ret; + + ret = rockchip_otp_ecc_enable(otp, false); + if (ret) + return ret; + + writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); + udelay(5); + + while (size--) { + writel(offset++ | OTPC_USER_ADDR_MASK, + otp->base + OTPC_USER_ADDR); + writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK, + otp->base + OTPC_USER_ENABLE); + + ret = rockchip_otp_poll_timeout(otp, OTPC_USER_DONE); + if (ret) + goto read_end; + + *buffer++ = readw(otp->base + OTPC_USER_Q); + } + +read_end: + writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); + + return ret; +} + static int rockchip_otp_read(struct udevice *dev, int offset, void *buf, int size) { const struct rockchip_otp_data *data = (void *)dev_get_driver_data(dev); + u32 block_start, block_end, block_offset, blocks; + u8 *buffer; + int ret;
if (offset < 0 || !buf || size <= 0 || offset + size > data->size) return -EINVAL; @@ -136,7 +174,24 @@ static int rockchip_otp_read(struct udevice *dev, int offset, if (!data->read) return -ENOSYS;
- return data->read(dev, offset, buf, size); + if (data->block_size <= 1) + return data->read(dev, offset, buf, size); + + block_start = offset / data->block_size; + block_offset = offset % data->block_size; + block_end = DIV_ROUND_UP(offset + size, data->block_size); + blocks = block_end - block_start; + + buffer = calloc(blocks, data->block_size); + if (!buffer) + return -ENOMEM; + + ret = data->read(dev, block_start, buffer, blocks); + if (!ret) + memcpy(buf, buffer + block_offset, size); + + free(buffer); + return ret; }
static const struct misc_ops rockchip_otp_ops = { @@ -157,6 +212,12 @@ static const struct rockchip_otp_data px30_data = { .size = 0x40, };
+static const struct rockchip_otp_data rk3568_data = { + .read = rockchip_rk3568_otp_read, + .size = 0x80, + .block_size = 2, +}; + static const struct udevice_id rockchip_otp_ids[] = { { .compatible = "rockchip,px30-otp", @@ -166,6 +227,10 @@ static const struct udevice_id rockchip_otp_ids[] = { .compatible = "rockchip,rk3308-otp", .data = (ulong)&px30_data, }, + { + .compatible = "rockchip,rk3568-otp", + .data = (ulong)&rk3568_data, + }, {} };

On 2023/2/16 07:48, Jonas Karlman wrote:
Add support for rk3568 compatible.
Handle allocation of an aligned bounce buffer in main read op in order to keep the SoC unique read op simple.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Thanks, - Kever
drivers/misc/rockchip-otp.c | 67 ++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-)
diff --git a/drivers/misc/rockchip-otp.c b/drivers/misc/rockchip-otp.c index a6df0834ebbc..243c173cdb18 100644 --- a/drivers/misc/rockchip-otp.c +++ b/drivers/misc/rockchip-otp.c @@ -9,6 +9,7 @@ #include <linux/bitops.h> #include <linux/delay.h> #include <linux/iopoll.h> +#include <malloc.h> #include <misc.h>
/* OTP Register Offsets */ @@ -54,6 +55,7 @@ struct rockchip_otp_plat { struct rockchip_otp_data { int (*read)(struct udevice *dev, int offset, void *buf, int size); int size;
int block_size; };
static int rockchip_otp_poll_timeout(struct rockchip_otp_plat *otp, u32 flag)
@@ -124,11 +126,47 @@ read_end: return ret; }
+static int rockchip_rk3568_otp_read(struct udevice *dev, int offset,
void *buf, int size)
+{
- struct rockchip_otp_plat *otp = dev_get_plat(dev);
- u16 *buffer = buf;
- int ret;
- ret = rockchip_otp_ecc_enable(otp, false);
- if (ret)
return ret;
- writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
- udelay(5);
- while (size--) {
writel(offset++ | OTPC_USER_ADDR_MASK,
otp->base + OTPC_USER_ADDR);
writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK,
otp->base + OTPC_USER_ENABLE);
ret = rockchip_otp_poll_timeout(otp, OTPC_USER_DONE);
if (ret)
goto read_end;
*buffer++ = readw(otp->base + OTPC_USER_Q);
- }
+read_end:
- writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
- return ret;
+}
static int rockchip_otp_read(struct udevice *dev, int offset, void *buf, int size) { const struct rockchip_otp_data *data = (void *)dev_get_driver_data(dev);
u32 block_start, block_end, block_offset, blocks;
u8 *buffer;
int ret;
if (offset < 0 || !buf || size <= 0 || offset + size > data->size) return -EINVAL;
@@ -136,7 +174,24 @@ static int rockchip_otp_read(struct udevice *dev, int offset, if (!data->read) return -ENOSYS;
- return data->read(dev, offset, buf, size);
if (data->block_size <= 1)
return data->read(dev, offset, buf, size);
block_start = offset / data->block_size;
block_offset = offset % data->block_size;
block_end = DIV_ROUND_UP(offset + size, data->block_size);
blocks = block_end - block_start;
buffer = calloc(blocks, data->block_size);
if (!buffer)
return -ENOMEM;
ret = data->read(dev, block_start, buffer, blocks);
if (!ret)
memcpy(buf, buffer + block_offset, size);
free(buffer);
return ret; }
static const struct misc_ops rockchip_otp_ops = {
@@ -157,6 +212,12 @@ static const struct rockchip_otp_data px30_data = { .size = 0x40, };
+static const struct rockchip_otp_data rk3568_data = {
- .read = rockchip_rk3568_otp_read,
- .size = 0x80,
- .block_size = 2,
+};
- static const struct udevice_id rockchip_otp_ids[] = { { .compatible = "rockchip,px30-otp",
@@ -166,6 +227,10 @@ static const struct udevice_id rockchip_otp_ids[] = { .compatible = "rockchip,rk3308-otp", .data = (ulong)&px30_data, },
- {
.compatible = "rockchip,rk3568-otp",
.data = (ulong)&rk3568_data,
- }, {} };

Add a simple debug command to dump the content of the otp.
Signed-off-by: Jonas Karlman jonas@kwiboo.se --- drivers/misc/rockchip-otp.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)
diff --git a/drivers/misc/rockchip-otp.c b/drivers/misc/rockchip-otp.c index babb6ce2f241..c41f0a606258 100644 --- a/drivers/misc/rockchip-otp.c +++ b/drivers/misc/rockchip-otp.c @@ -5,6 +5,8 @@
#include <common.h> #include <asm/io.h> +#include <command.h> +#include <display_options.h> #include <dm.h> #include <linux/bitops.h> #include <linux/delay.h> @@ -70,6 +72,39 @@ struct rockchip_otp_data { int block_size; };
+#if defined(DEBUG) +static int dump_otp(struct cmd_tbl *cmdtp, int flag, + int argc, char *const argv[]) +{ + struct udevice *dev; + u8 data[4]; + int ret, i; + + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_DRIVER_GET(rockchip_otp), &dev); + if (ret) { + printf("%s: no misc-device found\n", __func__); + return 0; + } + + for (i = 0; true; i += sizeof(data)) { + ret = misc_read(dev, i, &data, sizeof(data)); + if (ret < 0) + return 0; + + print_buffer(i, data, sizeof(data), 1, 1); + } + + return 0; +} + +U_BOOT_CMD( + dump_otp, 1, 1, dump_otp, + "Dump the content of the otp", + "" +); +#endif + static int rockchip_otp_poll_timeout(struct rockchip_otp_plat *otp, u32 flag, u32 reg) {

On 2023/2/16 07:48, Jonas Karlman wrote:
Add a simple debug command to dump the content of the otp.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Thanks, - Kever
drivers/misc/rockchip-otp.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)
diff --git a/drivers/misc/rockchip-otp.c b/drivers/misc/rockchip-otp.c index babb6ce2f241..c41f0a606258 100644 --- a/drivers/misc/rockchip-otp.c +++ b/drivers/misc/rockchip-otp.c @@ -5,6 +5,8 @@
#include <common.h> #include <asm/io.h> +#include <command.h> +#include <display_options.h> #include <dm.h> #include <linux/bitops.h> #include <linux/delay.h> @@ -70,6 +72,39 @@ struct rockchip_otp_data { int block_size; };
+#if defined(DEBUG) +static int dump_otp(struct cmd_tbl *cmdtp, int flag,
int argc, char *const argv[])
+{
- struct udevice *dev;
- u8 data[4];
- int ret, i;
- ret = uclass_get_device_by_driver(UCLASS_MISC,
DM_DRIVER_GET(rockchip_otp), &dev);
- if (ret) {
printf("%s: no misc-device found\n", __func__);
return 0;
- }
- for (i = 0; true; i += sizeof(data)) {
ret = misc_read(dev, i, &data, sizeof(data));
if (ret < 0)
return 0;
print_buffer(i, data, sizeof(data), 1, 1);
- }
- return 0;
+}
+U_BOOT_CMD(
- dump_otp, 1, 1, dump_otp,
- "Dump the content of the otp",
- ""
+); +#endif
- static int rockchip_otp_poll_timeout(struct rockchip_otp_plat *otp, u32 flag, u32 reg) {

Add support for rk3588 compatible.
Adjust offset using driver data in main read op.
Signed-off-by: Jonas Karlman jonas@kwiboo.se --- drivers/misc/rockchip-otp.c | 63 +++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 6 deletions(-)
diff --git a/drivers/misc/rockchip-otp.c b/drivers/misc/rockchip-otp.c index 243c173cdb18..babb6ce2f241 100644 --- a/drivers/misc/rockchip-otp.c +++ b/drivers/misc/rockchip-otp.c @@ -48,28 +48,41 @@
#define OTPC_TIMEOUT 10000
+#define RK3588_OTPC_AUTO_CTRL 0x0004 +#define RK3588_ADDR_SHIFT 16 +#define RK3588_ADDR(n) ((n) << RK3588_ADDR_SHIFT) +#define RK3588_BURST_SHIFT 8 +#define RK3588_BURST(n) ((n) << RK3588_BURST_SHIFT) +#define RK3588_OTPC_AUTO_EN 0x0008 +#define RK3588_AUTO_EN BIT(0) +#define RK3588_OTPC_DOUT0 0x0020 +#define RK3588_OTPC_INT_ST 0x0084 +#define RK3588_RD_DONE BIT(1) + struct rockchip_otp_plat { void __iomem *base; };
struct rockchip_otp_data { int (*read)(struct udevice *dev, int offset, void *buf, int size); + int offset; int size; int block_size; };
-static int rockchip_otp_poll_timeout(struct rockchip_otp_plat *otp, u32 flag) +static int rockchip_otp_poll_timeout(struct rockchip_otp_plat *otp, + u32 flag, u32 reg) { u32 status; int ret;
- ret = readl_poll_sleep_timeout(otp->base + OTPC_INT_STATUS, status, + ret = readl_poll_sleep_timeout(otp->base + reg, status, (status & flag), 1, OTPC_TIMEOUT); if (ret) return ret;
/* Clear int flag */ - writel(flag, otp->base + OTPC_INT_STATUS); + writel(flag, otp->base + reg);
return 0; } @@ -90,7 +103,7 @@ static int rockchip_otp_ecc_enable(struct rockchip_otp_plat *otp, bool enable)
writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL);
- return rockchip_otp_poll_timeout(otp, OTPC_SBPI_DONE); + return rockchip_otp_poll_timeout(otp, OTPC_SBPI_DONE, OTPC_INT_STATUS); }
static int rockchip_px30_otp_read(struct udevice *dev, int offset, @@ -113,7 +126,8 @@ static int rockchip_px30_otp_read(struct udevice *dev, int offset, writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK, otp->base + OTPC_USER_ENABLE);
- ret = rockchip_otp_poll_timeout(otp, OTPC_USER_DONE); + ret = rockchip_otp_poll_timeout(otp, OTPC_USER_DONE, + OTPC_INT_STATUS); if (ret) goto read_end;
@@ -146,7 +160,8 @@ static int rockchip_rk3568_otp_read(struct udevice *dev, int offset, writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK, otp->base + OTPC_USER_ENABLE);
- ret = rockchip_otp_poll_timeout(otp, OTPC_USER_DONE); + ret = rockchip_otp_poll_timeout(otp, OTPC_USER_DONE, + OTPC_INT_STATUS); if (ret) goto read_end;
@@ -159,6 +174,29 @@ read_end: return ret; }
+static int rockchip_rk3588_otp_read(struct udevice *dev, int offset, + void *buf, int size) +{ + struct rockchip_otp_plat *otp = dev_get_plat(dev); + u32 *buffer = buf; + int ret; + + while (size--) { + writel(RK3588_ADDR(offset++) | RK3588_BURST(1), + otp->base + RK3588_OTPC_AUTO_CTRL); + writel(RK3588_AUTO_EN, otp->base + RK3588_OTPC_AUTO_EN); + + ret = rockchip_otp_poll_timeout(otp, RK3588_RD_DONE, + RK3588_OTPC_INT_ST); + if (ret) + return ret; + + *buffer++ = readl(otp->base + RK3588_OTPC_DOUT0); + } + + return 0; +} + static int rockchip_otp_read(struct udevice *dev, int offset, void *buf, int size) { @@ -174,6 +212,8 @@ static int rockchip_otp_read(struct udevice *dev, int offset, if (!data->read) return -ENOSYS;
+ offset += data->offset; + if (data->block_size <= 1) return data->read(dev, offset, buf, size);
@@ -218,6 +258,13 @@ static const struct rockchip_otp_data rk3568_data = { .block_size = 2, };
+static const struct rockchip_otp_data rk3588_data = { + .read = rockchip_rk3588_otp_read, + .offset = 0xC00, + .size = 0x400, + .block_size = 4, +}; + static const struct udevice_id rockchip_otp_ids[] = { { .compatible = "rockchip,px30-otp", @@ -231,6 +278,10 @@ static const struct udevice_id rockchip_otp_ids[] = { .compatible = "rockchip,rk3568-otp", .data = (ulong)&rk3568_data, }, + { + .compatible = "rockchip,rk3588-otp", + .data = (ulong)&rk3588_data, + }, {} };

On 2023/2/16 07:48, Jonas Karlman wrote:
Add support for rk3588 compatible.
Adjust offset using driver data in main read op.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Thanks, - Kever
drivers/misc/rockchip-otp.c | 63 +++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 6 deletions(-)
diff --git a/drivers/misc/rockchip-otp.c b/drivers/misc/rockchip-otp.c index 243c173cdb18..babb6ce2f241 100644 --- a/drivers/misc/rockchip-otp.c +++ b/drivers/misc/rockchip-otp.c @@ -48,28 +48,41 @@
#define OTPC_TIMEOUT 10000
+#define RK3588_OTPC_AUTO_CTRL 0x0004 +#define RK3588_ADDR_SHIFT 16 +#define RK3588_ADDR(n) ((n) << RK3588_ADDR_SHIFT) +#define RK3588_BURST_SHIFT 8 +#define RK3588_BURST(n) ((n) << RK3588_BURST_SHIFT) +#define RK3588_OTPC_AUTO_EN 0x0008 +#define RK3588_AUTO_EN BIT(0) +#define RK3588_OTPC_DOUT0 0x0020 +#define RK3588_OTPC_INT_ST 0x0084 +#define RK3588_RD_DONE BIT(1)
struct rockchip_otp_plat { void __iomem *base; };
struct rockchip_otp_data { int (*read)(struct udevice *dev, int offset, void *buf, int size);
int offset; int size; int block_size; };
-static int rockchip_otp_poll_timeout(struct rockchip_otp_plat *otp, u32 flag) +static int rockchip_otp_poll_timeout(struct rockchip_otp_plat *otp,
{ u32 status; int ret;u32 flag, u32 reg)
- ret = readl_poll_sleep_timeout(otp->base + OTPC_INT_STATUS, status,
ret = readl_poll_sleep_timeout(otp->base + reg, status, (status & flag), 1, OTPC_TIMEOUT); if (ret) return ret;
/* Clear int flag */
- writel(flag, otp->base + OTPC_INT_STATUS);
writel(flag, otp->base + reg);
return 0; }
@@ -90,7 +103,7 @@ static int rockchip_otp_ecc_enable(struct rockchip_otp_plat *otp, bool enable)
writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL);
- return rockchip_otp_poll_timeout(otp, OTPC_SBPI_DONE);
return rockchip_otp_poll_timeout(otp, OTPC_SBPI_DONE, OTPC_INT_STATUS); }
static int rockchip_px30_otp_read(struct udevice *dev, int offset,
@@ -113,7 +126,8 @@ static int rockchip_px30_otp_read(struct udevice *dev, int offset, writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK, otp->base + OTPC_USER_ENABLE);
ret = rockchip_otp_poll_timeout(otp, OTPC_USER_DONE);
ret = rockchip_otp_poll_timeout(otp, OTPC_USER_DONE,
if (ret) goto read_end;OTPC_INT_STATUS);
@@ -146,7 +160,8 @@ static int rockchip_rk3568_otp_read(struct udevice *dev, int offset, writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK, otp->base + OTPC_USER_ENABLE);
ret = rockchip_otp_poll_timeout(otp, OTPC_USER_DONE);
ret = rockchip_otp_poll_timeout(otp, OTPC_USER_DONE,
if (ret) goto read_end;OTPC_INT_STATUS);
@@ -159,6 +174,29 @@ read_end: return ret; }
+static int rockchip_rk3588_otp_read(struct udevice *dev, int offset,
void *buf, int size)
+{
- struct rockchip_otp_plat *otp = dev_get_plat(dev);
- u32 *buffer = buf;
- int ret;
- while (size--) {
writel(RK3588_ADDR(offset++) | RK3588_BURST(1),
otp->base + RK3588_OTPC_AUTO_CTRL);
writel(RK3588_AUTO_EN, otp->base + RK3588_OTPC_AUTO_EN);
ret = rockchip_otp_poll_timeout(otp, RK3588_RD_DONE,
RK3588_OTPC_INT_ST);
if (ret)
return ret;
*buffer++ = readl(otp->base + RK3588_OTPC_DOUT0);
- }
- return 0;
+}
- static int rockchip_otp_read(struct udevice *dev, int offset, void *buf, int size) {
@@ -174,6 +212,8 @@ static int rockchip_otp_read(struct udevice *dev, int offset, if (!data->read) return -ENOSYS;
- offset += data->offset;
- if (data->block_size <= 1) return data->read(dev, offset, buf, size);
@@ -218,6 +258,13 @@ static const struct rockchip_otp_data rk3568_data = { .block_size = 2, };
+static const struct rockchip_otp_data rk3588_data = {
- .read = rockchip_rk3588_otp_read,
- .offset = 0xC00,
- .size = 0x400,
- .block_size = 4,
+};
- static const struct udevice_id rockchip_otp_ids[] = { { .compatible = "rockchip,px30-otp",
@@ -231,6 +278,10 @@ static const struct udevice_id rockchip_otp_ids[] = { .compatible = "rockchip,rk3568-otp", .data = (ulong)&rk3568_data, },
- {
.compatible = "rockchip,rk3588-otp",
.data = (ulong)&rk3588_data,
- }, {} };

Refactor the driver to use driver data and ops to simplify handling of SoCs that require a unique read op.
Move handling of the aligned bounce buffer to main read op in order to keep the SoC unique read op simple.
Signed-off-by: Jonas Karlman jonas@kwiboo.se --- drivers/misc/rockchip-efuse.c | 160 ++++++++++++++++++---------------- 1 file changed, 85 insertions(+), 75 deletions(-)
diff --git a/drivers/misc/rockchip-efuse.c b/drivers/misc/rockchip-efuse.c index 083ee65e0ad7..864c9c15bbe5 100644 --- a/drivers/misc/rockchip-efuse.c +++ b/drivers/misc/rockchip-efuse.c @@ -13,50 +13,40 @@ #include <dm.h> #include <linux/bitops.h> #include <linux/delay.h> +#include <malloc.h> #include <misc.h>
-#define RK3399_A_SHIFT 16 -#define RK3399_A_MASK 0x3ff -#define RK3399_NFUSES 32 -#define RK3399_BYTES_PER_FUSE 4 -#define RK3399_STROBSFTSEL BIT(9) -#define RK3399_RSB BIT(7) -#define RK3399_PD BIT(5) -#define RK3399_PGENB BIT(3) -#define RK3399_LOAD BIT(2) -#define RK3399_STROBE BIT(1) -#define RK3399_CSB BIT(0) - -struct rockchip_efuse_regs { - u32 ctrl; /* 0x00 efuse control register */ - u32 dout; /* 0x04 efuse data out register */ - u32 rf; /* 0x08 efuse redundancy bit used register */ - u32 _rsvd0; - u32 jtag_pass; /* 0x10 JTAG password */ - u32 strobe_finish_ctrl; - /* 0x14 efuse strobe finish control register */ -}; +#define EFUSE_CTRL 0x0000 +#define RK3399_A_SHIFT 16 +#define RK3399_A_MASK GENMASK(25, 16) +#define RK3399_ADDR(n) ((n) << RK3399_A_SHIFT) +#define RK3399_STROBSFTSEL BIT(9) +#define RK3399_RSB BIT(7) +#define RK3399_PD BIT(5) +#define RK3399_PGENB BIT(3) +#define RK3399_LOAD BIT(2) +#define RK3399_STROBE BIT(1) +#define RK3399_CSB BIT(0) +#define EFUSE_DOUT 0x0004
struct rockchip_efuse_plat { void __iomem *base; - struct clk *clk; +}; + +struct rockchip_efuse_data { + int (*read)(struct udevice *dev, int offset, void *buf, int size); + int size; + int block_size; };
#if defined(DEBUG) -static int dump_efuses(struct cmd_tbl *cmdtp, int flag, - int argc, char *const argv[]) +static int dump_efuse(struct cmd_tbl *cmdtp, int flag, + int argc, char *const argv[]) { - /* - * N.B.: This function is tailored towards the RK3399 and assumes that - * there's always 32 fuses x 32 bits (i.e. 128 bytes of data) to - * be read. - */ - struct udevice *dev; - u8 fuses[128]; - int ret; + u8 data[4]; + int ret, i;
- /* retrieve the device */ ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(rockchip_efuse), &dev); if (ret) { @@ -64,21 +54,20 @@ static int dump_efuses(struct cmd_tbl *cmdtp, int flag, return 0; }
- ret = misc_read(dev, 0, &fuses, sizeof(fuses)); - if (ret < 0) { - printf("%s: misc_read failed\n", __func__); - return 0; - } + for (i = 0; true; i += sizeof(data)) { + ret = misc_read(dev, i, &data, sizeof(data)); + if (ret < 0) + return 0;
- printf("efuse-contents:\n"); - print_buffer(0, fuses, 1, 128, 16); + print_buffer(i, data, sizeof(data), 1, 1); + }
return 0; }
U_BOOT_CMD( - rk3399_dump_efuses, 1, 1, dump_efuses, - "Dump the content of the efuses", + dump_efuse, 1, 1, dump_efuse, + "Dump the content of the efuse", "" ); #endif @@ -86,43 +75,25 @@ U_BOOT_CMD( static int rockchip_rk3399_efuse_read(struct udevice *dev, int offset, void *buf, int size) { - struct rockchip_efuse_plat *plat = dev_get_plat(dev); - struct rockchip_efuse_regs *efuse = - (struct rockchip_efuse_regs *)plat->base; - - unsigned int addr_start, addr_end, addr_offset; - u32 out_value; - u8 bytes[RK3399_NFUSES * RK3399_BYTES_PER_FUSE]; - int i = 0; - u32 addr; - - addr_start = offset / RK3399_BYTES_PER_FUSE; - addr_offset = offset % RK3399_BYTES_PER_FUSE; - addr_end = DIV_ROUND_UP(offset + size, RK3399_BYTES_PER_FUSE); - - /* cap to the size of the efuse block */ - if (addr_end > RK3399_NFUSES) - addr_end = RK3399_NFUSES; + struct rockchip_efuse_plat *efuse = dev_get_plat(dev); + u32 *buffer = buf;
+ /* Switch to array read mode */ writel(RK3399_LOAD | RK3399_PGENB | RK3399_STROBSFTSEL | RK3399_RSB, - &efuse->ctrl); + efuse->base + EFUSE_CTRL); udelay(1); - for (addr = addr_start; addr < addr_end; addr++) { - setbits_le32(&efuse->ctrl, - RK3399_STROBE | (addr << RK3399_A_SHIFT)); + + while (size--) { + setbits_le32(efuse->base + EFUSE_CTRL, + RK3399_STROBE | RK3399_ADDR(offset++)); udelay(1); - out_value = readl(&efuse->dout); - clrbits_le32(&efuse->ctrl, RK3399_STROBE); + *buffer++ = readl(efuse->base + EFUSE_DOUT); + clrbits_le32(efuse->base + EFUSE_CTRL, RK3399_STROBE); udelay(1); - - memcpy(&bytes[i], &out_value, RK3399_BYTES_PER_FUSE); - i += RK3399_BYTES_PER_FUSE; }
- /* Switch to standby mode */ - writel(RK3399_PD | RK3399_CSB, &efuse->ctrl); - - memcpy(buf, bytes + addr_offset, size); + /* Switch to power-down mode */ + writel(RK3399_PD | RK3399_CSB, efuse->base + EFUSE_CTRL);
return 0; } @@ -130,7 +101,36 @@ static int rockchip_rk3399_efuse_read(struct udevice *dev, int offset, static int rockchip_efuse_read(struct udevice *dev, int offset, void *buf, int size) { - return rockchip_rk3399_efuse_read(dev, offset, buf, size); + const struct rockchip_efuse_data *data = + (void *)dev_get_driver_data(dev); + u32 block_start, block_end, block_offset, blocks; + u8 *buffer; + int ret; + + if (offset < 0 || !buf || size <= 0 || offset + size > data->size) + return -EINVAL; + + if (!data->read) + return -ENOSYS; + + if (data->block_size <= 1) + return data->read(dev, offset, buf, size); + + block_start = offset / data->block_size; + block_offset = offset % data->block_size; + block_end = DIV_ROUND_UP(offset + size, data->block_size); + blocks = block_end - block_start; + + buffer = calloc(blocks, data->block_size); + if (!buffer) + return -ENOMEM; + + ret = data->read(dev, block_start, buffer, blocks); + if (!ret) + memcpy(buf, buffer + block_offset, size); + + free(buffer); + return ret; }
static const struct misc_ops rockchip_efuse_ops = { @@ -142,11 +142,21 @@ static int rockchip_efuse_of_to_plat(struct udevice *dev) struct rockchip_efuse_plat *plat = dev_get_plat(dev);
plat->base = dev_read_addr_ptr(dev); + return 0; }
+static const struct rockchip_efuse_data rk3399_data = { + .read = rockchip_rk3399_efuse_read, + .size = 0x80, + .block_size = 4, +}; + static const struct udevice_id rockchip_efuse_ids[] = { - { .compatible = "rockchip,rk3399-efuse" }, + { + .compatible = "rockchip,rk3399-efuse", + .data = (ulong)&rk3399_data, + }, {} };
@@ -155,6 +165,6 @@ U_BOOT_DRIVER(rockchip_efuse) = { .id = UCLASS_MISC, .of_match = rockchip_efuse_ids, .of_to_plat = rockchip_efuse_of_to_plat, - .plat_auto = sizeof(struct rockchip_efuse_plat), + .plat_auto = sizeof(struct rockchip_efuse_plat), .ops = &rockchip_efuse_ops, };

On 2023/2/16 07:48, Jonas Karlman wrote:
Refactor the driver to use driver data and ops to simplify handling of SoCs that require a unique read op.
Move handling of the aligned bounce buffer to main read op in order to keep the SoC unique read op simple.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Thanks, - Kever
drivers/misc/rockchip-efuse.c | 160 ++++++++++++++++++---------------- 1 file changed, 85 insertions(+), 75 deletions(-)
diff --git a/drivers/misc/rockchip-efuse.c b/drivers/misc/rockchip-efuse.c index 083ee65e0ad7..864c9c15bbe5 100644 --- a/drivers/misc/rockchip-efuse.c +++ b/drivers/misc/rockchip-efuse.c @@ -13,50 +13,40 @@ #include <dm.h> #include <linux/bitops.h> #include <linux/delay.h> +#include <malloc.h> #include <misc.h>
-#define RK3399_A_SHIFT 16 -#define RK3399_A_MASK 0x3ff -#define RK3399_NFUSES 32 -#define RK3399_BYTES_PER_FUSE 4 -#define RK3399_STROBSFTSEL BIT(9) -#define RK3399_RSB BIT(7) -#define RK3399_PD BIT(5) -#define RK3399_PGENB BIT(3) -#define RK3399_LOAD BIT(2) -#define RK3399_STROBE BIT(1) -#define RK3399_CSB BIT(0)
-struct rockchip_efuse_regs {
- u32 ctrl; /* 0x00 efuse control register */
- u32 dout; /* 0x04 efuse data out register */
- u32 rf; /* 0x08 efuse redundancy bit used register */
- u32 _rsvd0;
- u32 jtag_pass; /* 0x10 JTAG password */
- u32 strobe_finish_ctrl;
/* 0x14 efuse strobe finish control register */
-}; +#define EFUSE_CTRL 0x0000 +#define RK3399_A_SHIFT 16 +#define RK3399_A_MASK GENMASK(25, 16) +#define RK3399_ADDR(n) ((n) << RK3399_A_SHIFT) +#define RK3399_STROBSFTSEL BIT(9) +#define RK3399_RSB BIT(7) +#define RK3399_PD BIT(5) +#define RK3399_PGENB BIT(3) +#define RK3399_LOAD BIT(2) +#define RK3399_STROBE BIT(1) +#define RK3399_CSB BIT(0) +#define EFUSE_DOUT 0x0004
struct rockchip_efuse_plat { void __iomem *base;
- struct clk *clk;
+};
+struct rockchip_efuse_data {
int (*read)(struct udevice *dev, int offset, void *buf, int size);
int size;
int block_size; };
#if defined(DEBUG)
-static int dump_efuses(struct cmd_tbl *cmdtp, int flag,
int argc, char *const argv[])
+static int dump_efuse(struct cmd_tbl *cmdtp, int flag,
{int argc, char *const argv[])
- /*
* N.B.: This function is tailored towards the RK3399 and assumes that
* there's always 32 fuses x 32 bits (i.e. 128 bytes of data) to
* be read.
*/
- struct udevice *dev;
- u8 fuses[128];
- int ret;
- u8 data[4];
- int ret, i;
- /* retrieve the device */ ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(rockchip_efuse), &dev); if (ret) {
@@ -64,21 +54,20 @@ static int dump_efuses(struct cmd_tbl *cmdtp, int flag, return 0; }
- ret = misc_read(dev, 0, &fuses, sizeof(fuses));
- if (ret < 0) {
printf("%s: misc_read failed\n", __func__);
return 0;
- }
- for (i = 0; true; i += sizeof(data)) {
ret = misc_read(dev, i, &data, sizeof(data));
if (ret < 0)
return 0;
- printf("efuse-contents:\n");
- print_buffer(0, fuses, 1, 128, 16);
print_buffer(i, data, sizeof(data), 1, 1);
}
return 0; }
U_BOOT_CMD(
- rk3399_dump_efuses, 1, 1, dump_efuses,
- "Dump the content of the efuses",
- dump_efuse, 1, 1, dump_efuse,
- "Dump the content of the efuse", "" ); #endif
@@ -86,43 +75,25 @@ U_BOOT_CMD( static int rockchip_rk3399_efuse_read(struct udevice *dev, int offset, void *buf, int size) {
- struct rockchip_efuse_plat *plat = dev_get_plat(dev);
- struct rockchip_efuse_regs *efuse =
(struct rockchip_efuse_regs *)plat->base;
- unsigned int addr_start, addr_end, addr_offset;
- u32 out_value;
- u8 bytes[RK3399_NFUSES * RK3399_BYTES_PER_FUSE];
- int i = 0;
- u32 addr;
- addr_start = offset / RK3399_BYTES_PER_FUSE;
- addr_offset = offset % RK3399_BYTES_PER_FUSE;
- addr_end = DIV_ROUND_UP(offset + size, RK3399_BYTES_PER_FUSE);
- /* cap to the size of the efuse block */
- if (addr_end > RK3399_NFUSES)
addr_end = RK3399_NFUSES;
struct rockchip_efuse_plat *efuse = dev_get_plat(dev);
u32 *buffer = buf;
/* Switch to array read mode */ writel(RK3399_LOAD | RK3399_PGENB | RK3399_STROBSFTSEL | RK3399_RSB,
&efuse->ctrl);
udelay(1);efuse->base + EFUSE_CTRL);
- for (addr = addr_start; addr < addr_end; addr++) {
setbits_le32(&efuse->ctrl,
RK3399_STROBE | (addr << RK3399_A_SHIFT));
- while (size--) {
setbits_le32(efuse->base + EFUSE_CTRL,
udelay(1);RK3399_STROBE | RK3399_ADDR(offset++));
out_value = readl(&efuse->dout);
clrbits_le32(&efuse->ctrl, RK3399_STROBE);
*buffer++ = readl(efuse->base + EFUSE_DOUT);
udelay(1);clrbits_le32(efuse->base + EFUSE_CTRL, RK3399_STROBE);
memcpy(&bytes[i], &out_value, RK3399_BYTES_PER_FUSE);
i += RK3399_BYTES_PER_FUSE;
}
/* Switch to standby mode */
writel(RK3399_PD | RK3399_CSB, &efuse->ctrl);
memcpy(buf, bytes + addr_offset, size);
/* Switch to power-down mode */
writel(RK3399_PD | RK3399_CSB, efuse->base + EFUSE_CTRL);
return 0; }
@@ -130,7 +101,36 @@ static int rockchip_rk3399_efuse_read(struct udevice *dev, int offset, static int rockchip_efuse_read(struct udevice *dev, int offset, void *buf, int size) {
- return rockchip_rk3399_efuse_read(dev, offset, buf, size);
const struct rockchip_efuse_data *data =
(void *)dev_get_driver_data(dev);
u32 block_start, block_end, block_offset, blocks;
u8 *buffer;
int ret;
if (offset < 0 || !buf || size <= 0 || offset + size > data->size)
return -EINVAL;
if (!data->read)
return -ENOSYS;
if (data->block_size <= 1)
return data->read(dev, offset, buf, size);
block_start = offset / data->block_size;
block_offset = offset % data->block_size;
block_end = DIV_ROUND_UP(offset + size, data->block_size);
blocks = block_end - block_start;
buffer = calloc(blocks, data->block_size);
if (!buffer)
return -ENOMEM;
ret = data->read(dev, block_start, buffer, blocks);
if (!ret)
memcpy(buf, buffer + block_offset, size);
free(buffer);
return ret; }
static const struct misc_ops rockchip_efuse_ops = {
@@ -142,11 +142,21 @@ static int rockchip_efuse_of_to_plat(struct udevice *dev) struct rockchip_efuse_plat *plat = dev_get_plat(dev);
plat->base = dev_read_addr_ptr(dev);
- return 0; }
+static const struct rockchip_efuse_data rk3399_data = {
- .read = rockchip_rk3399_efuse_read,
- .size = 0x80,
- .block_size = 4,
+};
- static const struct udevice_id rockchip_efuse_ids[] = {
- { .compatible = "rockchip,rk3399-efuse" },
- {
.compatible = "rockchip,rk3399-efuse",
.data = (ulong)&rk3399_data,
- }, {} };
@@ -155,6 +165,6 @@ U_BOOT_DRIVER(rockchip_efuse) = { .id = UCLASS_MISC, .of_match = rockchip_efuse_ids, .of_to_plat = rockchip_efuse_of_to_plat,
- .plat_auto = sizeof(struct rockchip_efuse_plat),
- .plat_auto = sizeof(struct rockchip_efuse_plat), .ops = &rockchip_efuse_ops, };

Add support for rk3328 compatible.
Signed-off-by: Jonas Karlman jonas@kwiboo.se --- drivers/misc/rockchip-efuse.c | 45 +++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)
diff --git a/drivers/misc/rockchip-efuse.c b/drivers/misc/rockchip-efuse.c index 808246e92230..7aa3dc1b3868 100644 --- a/drivers/misc/rockchip-efuse.c +++ b/drivers/misc/rockchip-efuse.c @@ -13,6 +13,7 @@ #include <dm.h> #include <linux/bitops.h> #include <linux/delay.h> +#include <linux/iopoll.h> #include <malloc.h> #include <misc.h>
@@ -31,6 +32,12 @@ #define EFUSE_STROBE BIT(1) #define EFUSE_CSB BIT(0) #define EFUSE_DOUT 0x0004 +#define RK3328_INT_STATUS 0x0018 +#define RK3328_INT_FINISH BIT(0) +#define RK3328_DOUT 0x0020 +#define RK3328_AUTO_CTRL 0x0024 +#define RK3328_AUTO_RD BIT(1) +#define RK3328_AUTO_ENB BIT(0)
struct rockchip_efuse_plat { void __iomem *base; @@ -38,6 +45,7 @@ struct rockchip_efuse_plat {
struct rockchip_efuse_data { int (*read)(struct udevice *dev, int offset, void *buf, int size); + int offset; int size; int block_size; }; @@ -103,6 +111,30 @@ static int rockchip_rk3288_efuse_read(struct udevice *dev, int offset, return 0; }
+static int rockchip_rk3328_efuse_read(struct udevice *dev, int offset, + void *buf, int size) +{ + struct rockchip_efuse_plat *efuse = dev_get_plat(dev); + u32 status, *buffer = buf; + int ret; + + while (size--) { + writel(RK3328_AUTO_RD | RK3328_AUTO_ENB | RK3399_ADDR(offset++), + efuse->base + RK3328_AUTO_CTRL); + udelay(1); + + ret = readl_poll_sleep_timeout(efuse->base + RK3328_INT_STATUS, + status, (status & RK3328_INT_FINISH), 1, 50); + if (ret) + return ret; + + *buffer++ = readl(efuse->base + RK3328_DOUT); + writel(RK3328_INT_FINISH, efuse->base + RK3328_INT_STATUS); + } + + return 0; +} + static int rockchip_rk3399_efuse_read(struct udevice *dev, int offset, void *buf, int size) { @@ -144,6 +176,8 @@ static int rockchip_efuse_read(struct udevice *dev, int offset, if (!data->read) return -ENOSYS;
+ offset += data->offset; + if (data->block_size <= 1) return data->read(dev, offset, buf, size);
@@ -182,6 +216,13 @@ static const struct rockchip_efuse_data rk3288_data = { .size = 0x20, };
+static const struct rockchip_efuse_data rk3328_data = { + .read = rockchip_rk3328_efuse_read, + .offset = 0x60, + .size = 0x20, + .block_size = 4, +}; + static const struct rockchip_efuse_data rk3399_data = { .read = rockchip_rk3399_efuse_read, .size = 0x80, @@ -205,6 +246,10 @@ static const struct udevice_id rockchip_efuse_ids[] = { .compatible = "rockchip,rk3288-efuse", .data = (ulong)&rk3288_data, }, + { + .compatible = "rockchip,rk3328-efuse", + .data = (ulong)&rk3328_data, + }, { .compatible = "rockchip,rk3399-efuse", .data = (ulong)&rk3399_data,

On 2023/2/16 07:48, Jonas Karlman wrote:
Add support for rk3328 compatible.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
drivers/misc/rockchip-efuse.c | 45 +++++++++++++++++++++++++++++++++++
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Thanks, - Kever
1 file changed, 45 insertions(+)
diff --git a/drivers/misc/rockchip-efuse.c b/drivers/misc/rockchip-efuse.c index 808246e92230..7aa3dc1b3868 100644 --- a/drivers/misc/rockchip-efuse.c +++ b/drivers/misc/rockchip-efuse.c @@ -13,6 +13,7 @@ #include <dm.h> #include <linux/bitops.h> #include <linux/delay.h> +#include <linux/iopoll.h> #include <malloc.h> #include <misc.h>
@@ -31,6 +32,12 @@ #define EFUSE_STROBE BIT(1) #define EFUSE_CSB BIT(0) #define EFUSE_DOUT 0x0004 +#define RK3328_INT_STATUS 0x0018 +#define RK3328_INT_FINISH BIT(0) +#define RK3328_DOUT 0x0020 +#define RK3328_AUTO_CTRL 0x0024 +#define RK3328_AUTO_RD BIT(1) +#define RK3328_AUTO_ENB BIT(0)
struct rockchip_efuse_plat { void __iomem *base; @@ -38,6 +45,7 @@ struct rockchip_efuse_plat {
struct rockchip_efuse_data { int (*read)(struct udevice *dev, int offset, void *buf, int size);
- int offset; int size; int block_size; };
@@ -103,6 +111,30 @@ static int rockchip_rk3288_efuse_read(struct udevice *dev, int offset, return 0; }
+static int rockchip_rk3328_efuse_read(struct udevice *dev, int offset,
void *buf, int size)
+{
- struct rockchip_efuse_plat *efuse = dev_get_plat(dev);
- u32 status, *buffer = buf;
- int ret;
- while (size--) {
writel(RK3328_AUTO_RD | RK3328_AUTO_ENB | RK3399_ADDR(offset++),
efuse->base + RK3328_AUTO_CTRL);
udelay(1);
ret = readl_poll_sleep_timeout(efuse->base + RK3328_INT_STATUS,
status, (status & RK3328_INT_FINISH), 1, 50);
if (ret)
return ret;
*buffer++ = readl(efuse->base + RK3328_DOUT);
writel(RK3328_INT_FINISH, efuse->base + RK3328_INT_STATUS);
- }
- return 0;
+}
- static int rockchip_rk3399_efuse_read(struct udevice *dev, int offset, void *buf, int size) {
@@ -144,6 +176,8 @@ static int rockchip_efuse_read(struct udevice *dev, int offset, if (!data->read) return -ENOSYS;
- offset += data->offset;
- if (data->block_size <= 1) return data->read(dev, offset, buf, size);
@@ -182,6 +216,13 @@ static const struct rockchip_efuse_data rk3288_data = { .size = 0x20, };
+static const struct rockchip_efuse_data rk3328_data = {
- .read = rockchip_rk3328_efuse_read,
- .offset = 0x60,
- .size = 0x20,
- .block_size = 4,
+};
- static const struct rockchip_efuse_data rk3399_data = { .read = rockchip_rk3399_efuse_read, .size = 0x80,
@@ -205,6 +246,10 @@ static const struct udevice_id rockchip_efuse_ids[] = { .compatible = "rockchip,rk3288-efuse", .data = (ulong)&rk3288_data, },
- {
.compatible = "rockchip,rk3328-efuse",
.data = (ulong)&rk3328_data,
- }, { .compatible = "rockchip,rk3399-efuse", .data = (ulong)&rk3399_data,

Add support for rk3066a, rk3188, rk322x and rk3288 compatible.
Signed-off-by: Jonas Karlman jonas@kwiboo.se --- drivers/misc/Kconfig | 4 --- drivers/misc/rockchip-efuse.c | 68 ++++++++++++++++++++++++++++++----- 2 files changed, 60 insertions(+), 12 deletions(-)
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index b07261d3db5a..b5707a15c504 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -92,10 +92,6 @@ config ROCKCHIP_EFUSE or through child-nodes that are generated based on the e-fuse map retrieved from the DTS.
- This driver currently supports the RK3399 only, but can easily be - extended (by porting the read function from the Linux kernel sources) - to support other recent Rockchip devices. - config ROCKCHIP_OTP bool "Rockchip OTP Support" depends on MISC diff --git a/drivers/misc/rockchip-efuse.c b/drivers/misc/rockchip-efuse.c index 864c9c15bbe5..808246e92230 100644 --- a/drivers/misc/rockchip-efuse.c +++ b/drivers/misc/rockchip-efuse.c @@ -17,16 +17,19 @@ #include <misc.h>
#define EFUSE_CTRL 0x0000 +#define RK3288_A_SHIFT 6 +#define RK3288_A_MASK GENMASK(15, 6) +#define RK3288_ADDR(n) ((n) << RK3288_A_SHIFT) #define RK3399_A_SHIFT 16 #define RK3399_A_MASK GENMASK(25, 16) #define RK3399_ADDR(n) ((n) << RK3399_A_SHIFT) #define RK3399_STROBSFTSEL BIT(9) #define RK3399_RSB BIT(7) #define RK3399_PD BIT(5) -#define RK3399_PGENB BIT(3) -#define RK3399_LOAD BIT(2) -#define RK3399_STROBE BIT(1) -#define RK3399_CSB BIT(0) +#define EFUSE_PGENB BIT(3) +#define EFUSE_LOAD BIT(2) +#define EFUSE_STROBE BIT(1) +#define EFUSE_CSB BIT(0) #define EFUSE_DOUT 0x0004
struct rockchip_efuse_plat { @@ -72,6 +75,34 @@ U_BOOT_CMD( ); #endif
+static int rockchip_rk3288_efuse_read(struct udevice *dev, int offset, + void *buf, int size) +{ + struct rockchip_efuse_plat *efuse = dev_get_plat(dev); + u8 *buffer = buf; + + /* Switch to read mode */ + writel(EFUSE_CSB, efuse->base + EFUSE_CTRL); + writel(EFUSE_LOAD | EFUSE_PGENB, efuse->base + EFUSE_CTRL); + udelay(2); + + while (size--) { + clrsetbits_le32(efuse->base + EFUSE_CTRL, RK3288_A_MASK, + RK3288_ADDR(offset++)); + udelay(2); + setbits_le32(efuse->base + EFUSE_CTRL, EFUSE_STROBE); + udelay(2); + *buffer++ = readb(efuse->base + EFUSE_DOUT); + clrbits_le32(efuse->base + EFUSE_CTRL, EFUSE_STROBE); + udelay(2); + } + + /* Switch to standby mode */ + writel(EFUSE_CSB | EFUSE_PGENB, efuse->base + EFUSE_CTRL); + + return 0; +} + static int rockchip_rk3399_efuse_read(struct udevice *dev, int offset, void *buf, int size) { @@ -79,21 +110,21 @@ static int rockchip_rk3399_efuse_read(struct udevice *dev, int offset, u32 *buffer = buf;
/* Switch to array read mode */ - writel(RK3399_LOAD | RK3399_PGENB | RK3399_STROBSFTSEL | RK3399_RSB, + writel(EFUSE_LOAD | EFUSE_PGENB | RK3399_STROBSFTSEL | RK3399_RSB, efuse->base + EFUSE_CTRL); udelay(1);
while (size--) { setbits_le32(efuse->base + EFUSE_CTRL, - RK3399_STROBE | RK3399_ADDR(offset++)); + EFUSE_STROBE | RK3399_ADDR(offset++)); udelay(1); *buffer++ = readl(efuse->base + EFUSE_DOUT); - clrbits_le32(efuse->base + EFUSE_CTRL, RK3399_STROBE); + clrbits_le32(efuse->base + EFUSE_CTRL, EFUSE_STROBE); udelay(1); }
/* Switch to power-down mode */ - writel(RK3399_PD | RK3399_CSB, efuse->base + EFUSE_CTRL); + writel(RK3399_PD | EFUSE_CSB, efuse->base + EFUSE_CTRL);
return 0; } @@ -146,6 +177,11 @@ static int rockchip_efuse_of_to_plat(struct udevice *dev) return 0; }
+static const struct rockchip_efuse_data rk3288_data = { + .read = rockchip_rk3288_efuse_read, + .size = 0x20, +}; + static const struct rockchip_efuse_data rk3399_data = { .read = rockchip_rk3399_efuse_read, .size = 0x80, @@ -153,6 +189,22 @@ static const struct rockchip_efuse_data rk3399_data = { };
static const struct udevice_id rockchip_efuse_ids[] = { + { + .compatible = "rockchip,rk3066a-efuse", + .data = (ulong)&rk3288_data, + }, + { + .compatible = "rockchip,rk3188-efuse", + .data = (ulong)&rk3288_data, + }, + { + .compatible = "rockchip,rk3228-efuse", + .data = (ulong)&rk3288_data, + }, + { + .compatible = "rockchip,rk3288-efuse", + .data = (ulong)&rk3288_data, + }, { .compatible = "rockchip,rk3399-efuse", .data = (ulong)&rk3399_data,

On 2023/2/16 07:48, Jonas Karlman wrote:
Add support for rk3066a, rk3188, rk322x and rk3288 compatible.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Thanks, - Kever
drivers/misc/Kconfig | 4 --- drivers/misc/rockchip-efuse.c | 68 ++++++++++++++++++++++++++++++----- 2 files changed, 60 insertions(+), 12 deletions(-)
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index b07261d3db5a..b5707a15c504 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -92,10 +92,6 @@ config ROCKCHIP_EFUSE or through child-nodes that are generated based on the e-fuse map retrieved from the DTS.
This driver currently supports the RK3399 only, but can easily be
extended (by porting the read function from the Linux kernel sources)
to support other recent Rockchip devices.
- config ROCKCHIP_OTP bool "Rockchip OTP Support" depends on MISC
diff --git a/drivers/misc/rockchip-efuse.c b/drivers/misc/rockchip-efuse.c index 864c9c15bbe5..808246e92230 100644 --- a/drivers/misc/rockchip-efuse.c +++ b/drivers/misc/rockchip-efuse.c @@ -17,16 +17,19 @@ #include <misc.h>
#define EFUSE_CTRL 0x0000 +#define RK3288_A_SHIFT 6 +#define RK3288_A_MASK GENMASK(15, 6) +#define RK3288_ADDR(n) ((n) << RK3288_A_SHIFT) #define RK3399_A_SHIFT 16 #define RK3399_A_MASK GENMASK(25, 16) #define RK3399_ADDR(n) ((n) << RK3399_A_SHIFT) #define RK3399_STROBSFTSEL BIT(9) #define RK3399_RSB BIT(7) #define RK3399_PD BIT(5) -#define RK3399_PGENB BIT(3) -#define RK3399_LOAD BIT(2) -#define RK3399_STROBE BIT(1) -#define RK3399_CSB BIT(0) +#define EFUSE_PGENB BIT(3) +#define EFUSE_LOAD BIT(2) +#define EFUSE_STROBE BIT(1) +#define EFUSE_CSB BIT(0) #define EFUSE_DOUT 0x0004
struct rockchip_efuse_plat { @@ -72,6 +75,34 @@ U_BOOT_CMD( ); #endif
+static int rockchip_rk3288_efuse_read(struct udevice *dev, int offset,
void *buf, int size)
+{
- struct rockchip_efuse_plat *efuse = dev_get_plat(dev);
- u8 *buffer = buf;
- /* Switch to read mode */
- writel(EFUSE_CSB, efuse->base + EFUSE_CTRL);
- writel(EFUSE_LOAD | EFUSE_PGENB, efuse->base + EFUSE_CTRL);
- udelay(2);
- while (size--) {
clrsetbits_le32(efuse->base + EFUSE_CTRL, RK3288_A_MASK,
RK3288_ADDR(offset++));
udelay(2);
setbits_le32(efuse->base + EFUSE_CTRL, EFUSE_STROBE);
udelay(2);
*buffer++ = readb(efuse->base + EFUSE_DOUT);
clrbits_le32(efuse->base + EFUSE_CTRL, EFUSE_STROBE);
udelay(2);
- }
- /* Switch to standby mode */
- writel(EFUSE_CSB | EFUSE_PGENB, efuse->base + EFUSE_CTRL);
- return 0;
+}
- static int rockchip_rk3399_efuse_read(struct udevice *dev, int offset, void *buf, int size) {
@@ -79,21 +110,21 @@ static int rockchip_rk3399_efuse_read(struct udevice *dev, int offset, u32 *buffer = buf;
/* Switch to array read mode */
- writel(RK3399_LOAD | RK3399_PGENB | RK3399_STROBSFTSEL | RK3399_RSB,
writel(EFUSE_LOAD | EFUSE_PGENB | RK3399_STROBSFTSEL | RK3399_RSB, efuse->base + EFUSE_CTRL); udelay(1);
while (size--) { setbits_le32(efuse->base + EFUSE_CTRL,
RK3399_STROBE | RK3399_ADDR(offset++));
udelay(1); *buffer++ = readl(efuse->base + EFUSE_DOUT);EFUSE_STROBE | RK3399_ADDR(offset++));
clrbits_le32(efuse->base + EFUSE_CTRL, RK3399_STROBE);
clrbits_le32(efuse->base + EFUSE_CTRL, EFUSE_STROBE);
udelay(1); }
/* Switch to power-down mode */
- writel(RK3399_PD | RK3399_CSB, efuse->base + EFUSE_CTRL);
writel(RK3399_PD | EFUSE_CSB, efuse->base + EFUSE_CTRL);
return 0; }
@@ -146,6 +177,11 @@ static int rockchip_efuse_of_to_plat(struct udevice *dev) return 0; }
+static const struct rockchip_efuse_data rk3288_data = {
- .read = rockchip_rk3288_efuse_read,
- .size = 0x20,
+};
- static const struct rockchip_efuse_data rk3399_data = { .read = rockchip_rk3399_efuse_read, .size = 0x80,
@@ -153,6 +189,22 @@ static const struct rockchip_efuse_data rk3399_data = { };
static const struct udevice_id rockchip_efuse_ids[] = {
- {
.compatible = "rockchip,rk3066a-efuse",
.data = (ulong)&rk3288_data,
- },
- {
.compatible = "rockchip,rk3188-efuse",
.data = (ulong)&rk3288_data,
- },
- {
.compatible = "rockchip,rk3228-efuse",
.data = (ulong)&rk3288_data,
- },
- {
.compatible = "rockchip,rk3288-efuse",
.data = (ulong)&rk3288_data,
- }, { .compatible = "rockchip,rk3399-efuse", .data = (ulong)&rk3399_data,

Hi Kever,
On 2023-02-22 09:55, Kever Yang wrote:
On 2023/2/16 07:48, Jonas Karlman wrote:
Add support for rk3066a, rk3188, rk322x and rk3288 compatible.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Alex reported that there is an issue / hang reading efuse on rk3188, will send a v2 that use readl and not readb/readw to fix that issue.
Regards, Jonas
Thanks,
- Kever
drivers/misc/Kconfig | 4 --- drivers/misc/rockchip-efuse.c | 68 ++++++++++++++++++++++++++++++----- 2 files changed, 60 insertions(+), 12 deletions(-)
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index b07261d3db5a..b5707a15c504 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -92,10 +92,6 @@ config ROCKCHIP_EFUSE or through child-nodes that are generated based on the e-fuse map retrieved from the DTS.
This driver currently supports the RK3399 only, but can easily be
extended (by porting the read function from the Linux kernel sources)
to support other recent Rockchip devices.
- config ROCKCHIP_OTP bool "Rockchip OTP Support" depends on MISC
diff --git a/drivers/misc/rockchip-efuse.c b/drivers/misc/rockchip-efuse.c index 864c9c15bbe5..808246e92230 100644 --- a/drivers/misc/rockchip-efuse.c +++ b/drivers/misc/rockchip-efuse.c @@ -17,16 +17,19 @@ #include <misc.h>
#define EFUSE_CTRL 0x0000 +#define RK3288_A_SHIFT 6 +#define RK3288_A_MASK GENMASK(15, 6) +#define RK3288_ADDR(n) ((n) << RK3288_A_SHIFT) #define RK3399_A_SHIFT 16 #define RK3399_A_MASK GENMASK(25, 16) #define RK3399_ADDR(n) ((n) << RK3399_A_SHIFT) #define RK3399_STROBSFTSEL BIT(9) #define RK3399_RSB BIT(7) #define RK3399_PD BIT(5) -#define RK3399_PGENB BIT(3) -#define RK3399_LOAD BIT(2) -#define RK3399_STROBE BIT(1) -#define RK3399_CSB BIT(0) +#define EFUSE_PGENB BIT(3) +#define EFUSE_LOAD BIT(2) +#define EFUSE_STROBE BIT(1) +#define EFUSE_CSB BIT(0) #define EFUSE_DOUT 0x0004
struct rockchip_efuse_plat { @@ -72,6 +75,34 @@ U_BOOT_CMD( ); #endif
+static int rockchip_rk3288_efuse_read(struct udevice *dev, int offset,
void *buf, int size)
+{
- struct rockchip_efuse_plat *efuse = dev_get_plat(dev);
- u8 *buffer = buf;
- /* Switch to read mode */
- writel(EFUSE_CSB, efuse->base + EFUSE_CTRL);
- writel(EFUSE_LOAD | EFUSE_PGENB, efuse->base + EFUSE_CTRL);
- udelay(2);
- while (size--) {
clrsetbits_le32(efuse->base + EFUSE_CTRL, RK3288_A_MASK,
RK3288_ADDR(offset++));
udelay(2);
setbits_le32(efuse->base + EFUSE_CTRL, EFUSE_STROBE);
udelay(2);
*buffer++ = readb(efuse->base + EFUSE_DOUT);
clrbits_le32(efuse->base + EFUSE_CTRL, EFUSE_STROBE);
udelay(2);
- }
- /* Switch to standby mode */
- writel(EFUSE_CSB | EFUSE_PGENB, efuse->base + EFUSE_CTRL);
- return 0;
+}
- static int rockchip_rk3399_efuse_read(struct udevice *dev, int offset, void *buf, int size) {
@@ -79,21 +110,21 @@ static int rockchip_rk3399_efuse_read(struct udevice *dev, int offset, u32 *buffer = buf;
/* Switch to array read mode */
- writel(RK3399_LOAD | RK3399_PGENB | RK3399_STROBSFTSEL | RK3399_RSB,
writel(EFUSE_LOAD | EFUSE_PGENB | RK3399_STROBSFTSEL | RK3399_RSB, efuse->base + EFUSE_CTRL); udelay(1);
while (size--) { setbits_le32(efuse->base + EFUSE_CTRL,
RK3399_STROBE | RK3399_ADDR(offset++));
udelay(1); *buffer++ = readl(efuse->base + EFUSE_DOUT);EFUSE_STROBE | RK3399_ADDR(offset++));
clrbits_le32(efuse->base + EFUSE_CTRL, RK3399_STROBE);
clrbits_le32(efuse->base + EFUSE_CTRL, EFUSE_STROBE);
udelay(1); }
/* Switch to power-down mode */
- writel(RK3399_PD | RK3399_CSB, efuse->base + EFUSE_CTRL);
writel(RK3399_PD | EFUSE_CSB, efuse->base + EFUSE_CTRL);
return 0; }
@@ -146,6 +177,11 @@ static int rockchip_efuse_of_to_plat(struct udevice *dev) return 0; }
+static const struct rockchip_efuse_data rk3288_data = {
- .read = rockchip_rk3288_efuse_read,
- .size = 0x20,
+};
- static const struct rockchip_efuse_data rk3399_data = { .read = rockchip_rk3399_efuse_read, .size = 0x80,
@@ -153,6 +189,22 @@ static const struct rockchip_efuse_data rk3399_data = { };
static const struct udevice_id rockchip_efuse_ids[] = {
- {
.compatible = "rockchip,rk3066a-efuse",
.data = (ulong)&rk3288_data,
- },
- {
.compatible = "rockchip,rk3188-efuse",
.data = (ulong)&rk3288_data,
- },
- {
.compatible = "rockchip,rk3228-efuse",
.data = (ulong)&rk3288_data,
- },
- {
.compatible = "rockchip,rk3288-efuse",
.data = (ulong)&rk3288_data,
- }, { .compatible = "rockchip,rk3399-efuse", .data = (ulong)&rk3399_data,

Set eth1addr when there is an ethernet1 alias in the fdt.
Also allow fdt fixup of ethernet mac addresses when CMD_NET is disabled. Set ethaddr and eth1addr based on HASH and SHA256 options.
Signed-off-by: Jonas Karlman jonas@kwiboo.se --- arch/arm/mach-rockchip/misc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-rockchip/misc.c b/arch/arm/mach-rockchip/misc.c index b350f18f1140..aceaea6b29b7 100644 --- a/arch/arm/mach-rockchip/misc.c +++ b/arch/arm/mach-rockchip/misc.c @@ -21,9 +21,11 @@
#include <asm/arch-rockchip/misc.h>
+DECLARE_GLOBAL_DATA_PTR; + int rockchip_setup_macaddr(void) { -#if IS_ENABLED(CONFIG_CMD_NET) +#if CONFIG_IS_ENABLED(HASH) && CONFIG_IS_ENABLED(SHA256) int ret; const char *cpuid = env_get("cpuid#"); u8 hash[SHA256_SUM_LEN]; @@ -52,6 +54,12 @@ int rockchip_setup_macaddr(void) mac_addr[0] &= 0xfe; /* clear multicast bit */ mac_addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ eth_env_set_enetaddr("ethaddr", mac_addr); + + if (gd->fdt_blob && fdt_get_alias(gd->fdt_blob, "ethernet1")) { + /* Make a valid MAC address for eth1 */ + mac_addr[5] += 0x20; + eth_env_set_enetaddr("eth1addr", mac_addr); + } #endif return 0; }

On Thu, Feb 16, 2023 at 7:57 AM Jonas Karlman jonas@kwiboo.se wrote:
Set eth1addr when there is an ethernet1 alias in the fdt.
Maybe it makes sense to set it regardless whether an alias is present or not?
The user might be loading a custom FDT for the kernel, or have DT overlays stacked on, either could have the "ethernet1" alias while the U-boot DT doesn't.
ChenYu
Also allow fdt fixup of ethernet mac addresses when CMD_NET is disabled. Set ethaddr and eth1addr based on HASH and SHA256 options.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
arch/arm/mach-rockchip/misc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-rockchip/misc.c b/arch/arm/mach-rockchip/misc.c index b350f18f1140..aceaea6b29b7 100644 --- a/arch/arm/mach-rockchip/misc.c +++ b/arch/arm/mach-rockchip/misc.c @@ -21,9 +21,11 @@
#include <asm/arch-rockchip/misc.h>
+DECLARE_GLOBAL_DATA_PTR;
int rockchip_setup_macaddr(void) { -#if IS_ENABLED(CONFIG_CMD_NET) +#if CONFIG_IS_ENABLED(HASH) && CONFIG_IS_ENABLED(SHA256) int ret; const char *cpuid = env_get("cpuid#"); u8 hash[SHA256_SUM_LEN]; @@ -52,6 +54,12 @@ int rockchip_setup_macaddr(void) mac_addr[0] &= 0xfe; /* clear multicast bit */ mac_addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ eth_env_set_enetaddr("ethaddr", mac_addr);
if (gd->fdt_blob && fdt_get_alias(gd->fdt_blob, "ethernet1")) {
/* Make a valid MAC address for eth1 */
mac_addr[5] += 0x20;
eth_env_set_enetaddr("eth1addr", mac_addr);
}
#endif return 0; } -- 2.39.1

Hi Chen-Yu,
On 2023-02-16 03:42, Chen-Yu Tsai wrote:
On Thu, Feb 16, 2023 at 7:57 AM Jonas Karlman jonas@kwiboo.se wrote:
Set eth1addr when there is an ethernet1 alias in the fdt.
Maybe it makes sense to set it regardless whether an alias is present or not?
Makes sense, changed to always set eth1addr in v2, thanks!
Regards, Jonas
The user might be loading a custom FDT for the kernel, or have DT overlays stacked on, either could have the "ethernet1" alias while the U-boot DT doesn't.
ChenYu
Also allow fdt fixup of ethernet mac addresses when CMD_NET is disabled. Set ethaddr and eth1addr based on HASH and SHA256 options.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
arch/arm/mach-rockchip/misc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-rockchip/misc.c b/arch/arm/mach-rockchip/misc.c index b350f18f1140..aceaea6b29b7 100644 --- a/arch/arm/mach-rockchip/misc.c +++ b/arch/arm/mach-rockchip/misc.c @@ -21,9 +21,11 @@
#include <asm/arch-rockchip/misc.h>
+DECLARE_GLOBAL_DATA_PTR;
int rockchip_setup_macaddr(void) { -#if IS_ENABLED(CONFIG_CMD_NET) +#if CONFIG_IS_ENABLED(HASH) && CONFIG_IS_ENABLED(SHA256) int ret; const char *cpuid = env_get("cpuid#"); u8 hash[SHA256_SUM_LEN]; @@ -52,6 +54,12 @@ int rockchip_setup_macaddr(void) mac_addr[0] &= 0xfe; /* clear multicast bit */ mac_addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ eth_env_set_enetaddr("ethaddr", mac_addr);
if (gd->fdt_blob && fdt_get_alias(gd->fdt_blob, "ethernet1")) {
/* Make a valid MAC address for eth1 */
mac_addr[5] += 0x20;
eth_env_set_enetaddr("eth1addr", mac_addr);
}
#endif return 0; } -- 2.39.1

On 2023/2/16 07:49, Jonas Karlman wrote:
Set eth1addr when there is an ethernet1 alias in the fdt.
Also allow fdt fixup of ethernet mac addresses when CMD_NET is disabled. Set ethaddr and eth1addr based on HASH and SHA256 options.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Thanks, - Kever
arch/arm/mach-rockchip/misc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-rockchip/misc.c b/arch/arm/mach-rockchip/misc.c index b350f18f1140..aceaea6b29b7 100644 --- a/arch/arm/mach-rockchip/misc.c +++ b/arch/arm/mach-rockchip/misc.c @@ -21,9 +21,11 @@
#include <asm/arch-rockchip/misc.h>
+DECLARE_GLOBAL_DATA_PTR;
- int rockchip_setup_macaddr(void) {
-#if IS_ENABLED(CONFIG_CMD_NET) +#if CONFIG_IS_ENABLED(HASH) && CONFIG_IS_ENABLED(SHA256) int ret; const char *cpuid = env_get("cpuid#"); u8 hash[SHA256_SUM_LEN]; @@ -52,6 +54,12 @@ int rockchip_setup_macaddr(void) mac_addr[0] &= 0xfe; /* clear multicast bit */ mac_addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ eth_env_set_enetaddr("ethaddr", mac_addr);
- if (gd->fdt_blob && fdt_get_alias(gd->fdt_blob, "ethernet1")) {
/* Make a valid MAC address for eth1 */
mac_addr[5] += 0x20;
eth_env_set_enetaddr("eth1addr", mac_addr);
- } #endif return 0; }

Add support for rk3036 compatible.
Signed-off-by: Jonas Karlman jonas@kwiboo.se --- drivers/misc/rockchip-efuse.c | 39 +++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/drivers/misc/rockchip-efuse.c b/drivers/misc/rockchip-efuse.c index 897e79bcc60f..177c96983ed8 100644 --- a/drivers/misc/rockchip-efuse.c +++ b/drivers/misc/rockchip-efuse.c @@ -18,6 +18,9 @@ #include <misc.h>
#define EFUSE_CTRL 0x0000 +#define RK3036_A_SHIFT 8 +#define RK3036_A_MASK GENMASK(15, 8) +#define RK3036_ADDR(n) ((n) << RK3036_A_SHIFT) #define RK3128_A_SHIFT 7 #define RK3128_A_MASK GENMASK(15, 7) #define RK3128_ADDR(n) ((n) << RK3128_A_SHIFT) @@ -86,6 +89,33 @@ U_BOOT_CMD( ); #endif
+static int rockchip_rk3036_efuse_read(struct udevice *dev, int offset, + void *buf, int size) +{ + struct rockchip_efuse_plat *efuse = dev_get_plat(dev); + u8 *buffer = buf; + + /* Switch to read mode */ + writel(EFUSE_LOAD, efuse->base + EFUSE_CTRL); + udelay(2); + + while (size--) { + clrsetbits_le32(efuse->base + EFUSE_CTRL, RK3036_A_MASK, + RK3036_ADDR(offset++)); + udelay(2); + setbits_le32(efuse->base + EFUSE_CTRL, EFUSE_STROBE); + udelay(2); + *buffer++ = readb(efuse->base + EFUSE_DOUT); + clrbits_le32(efuse->base + EFUSE_CTRL, EFUSE_STROBE); + udelay(2); + } + + /* Switch to inactive mode */ + writel(0x0, efuse->base + EFUSE_CTRL); + + return 0; +} + static int rockchip_rk3128_efuse_read(struct udevice *dev, int offset, void *buf, int size) { @@ -241,6 +271,11 @@ static int rockchip_efuse_of_to_plat(struct udevice *dev) return 0; }
+static const struct rockchip_efuse_data rk3036_data = { + .read = rockchip_rk3036_efuse_read, + .size = 0x20, +}; + static const struct rockchip_efuse_data rk3128_data = { .read = rockchip_rk3128_efuse_read, .size = 0x40, @@ -265,6 +300,10 @@ static const struct rockchip_efuse_data rk3399_data = { };
static const struct udevice_id rockchip_efuse_ids[] = { + { + .compatible = "rockchip,rk3036-efuse", + .data = (ulong)&rk3036_data, + }, { .compatible = "rockchip,rk3066a-efuse", .data = (ulong)&rk3288_data,

On 2023/2/16 07:49, Jonas Karlman wrote:
Add support for rk3036 compatible.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Thanks, - Kever
drivers/misc/rockchip-efuse.c | 39 +++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/drivers/misc/rockchip-efuse.c b/drivers/misc/rockchip-efuse.c index 897e79bcc60f..177c96983ed8 100644 --- a/drivers/misc/rockchip-efuse.c +++ b/drivers/misc/rockchip-efuse.c @@ -18,6 +18,9 @@ #include <misc.h>
#define EFUSE_CTRL 0x0000 +#define RK3036_A_SHIFT 8 +#define RK3036_A_MASK GENMASK(15, 8) +#define RK3036_ADDR(n) ((n) << RK3036_A_SHIFT) #define RK3128_A_SHIFT 7 #define RK3128_A_MASK GENMASK(15, 7) #define RK3128_ADDR(n) ((n) << RK3128_A_SHIFT) @@ -86,6 +89,33 @@ U_BOOT_CMD( ); #endif
+static int rockchip_rk3036_efuse_read(struct udevice *dev, int offset,
void *buf, int size)
+{
- struct rockchip_efuse_plat *efuse = dev_get_plat(dev);
- u8 *buffer = buf;
- /* Switch to read mode */
- writel(EFUSE_LOAD, efuse->base + EFUSE_CTRL);
- udelay(2);
- while (size--) {
clrsetbits_le32(efuse->base + EFUSE_CTRL, RK3036_A_MASK,
RK3036_ADDR(offset++));
udelay(2);
setbits_le32(efuse->base + EFUSE_CTRL, EFUSE_STROBE);
udelay(2);
*buffer++ = readb(efuse->base + EFUSE_DOUT);
clrbits_le32(efuse->base + EFUSE_CTRL, EFUSE_STROBE);
udelay(2);
- }
- /* Switch to inactive mode */
- writel(0x0, efuse->base + EFUSE_CTRL);
- return 0;
+}
- static int rockchip_rk3128_efuse_read(struct udevice *dev, int offset, void *buf, int size) {
@@ -241,6 +271,11 @@ static int rockchip_efuse_of_to_plat(struct udevice *dev) return 0; }
+static const struct rockchip_efuse_data rk3036_data = {
- .read = rockchip_rk3036_efuse_read,
- .size = 0x20,
+};
- static const struct rockchip_efuse_data rk3128_data = { .read = rockchip_rk3128_efuse_read, .size = 0x40,
@@ -265,6 +300,10 @@ static const struct rockchip_efuse_data rk3399_data = { };
static const struct udevice_id rockchip_efuse_ids[] = {
- {
.compatible = "rockchip,rk3036-efuse",
.data = (ulong)&rk3036_data,
- }, { .compatible = "rockchip,rk3066a-efuse", .data = (ulong)&rk3288_data,

Add support for rk3128 compatible.
Signed-off-by: Jonas Karlman jonas@kwiboo.se --- drivers/misc/rockchip-efuse.c | 39 +++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/drivers/misc/rockchip-efuse.c b/drivers/misc/rockchip-efuse.c index 7aa3dc1b3868..897e79bcc60f 100644 --- a/drivers/misc/rockchip-efuse.c +++ b/drivers/misc/rockchip-efuse.c @@ -18,6 +18,9 @@ #include <misc.h>
#define EFUSE_CTRL 0x0000 +#define RK3128_A_SHIFT 7 +#define RK3128_A_MASK GENMASK(15, 7) +#define RK3128_ADDR(n) ((n) << RK3128_A_SHIFT) #define RK3288_A_SHIFT 6 #define RK3288_A_MASK GENMASK(15, 6) #define RK3288_ADDR(n) ((n) << RK3288_A_SHIFT) @@ -83,6 +86,33 @@ U_BOOT_CMD( ); #endif
+static int rockchip_rk3128_efuse_read(struct udevice *dev, int offset, + void *buf, int size) +{ + struct rockchip_efuse_plat *efuse = dev_get_plat(dev); + u8 *buffer = buf; + + /* Switch to read mode */ + writel(EFUSE_LOAD, efuse->base + EFUSE_CTRL); + udelay(2); + + while (size--) { + clrsetbits_le32(efuse->base + EFUSE_CTRL, RK3128_A_MASK, + RK3128_ADDR(offset++)); + udelay(2); + setbits_le32(efuse->base + EFUSE_CTRL, EFUSE_STROBE); + udelay(2); + *buffer++ = readb(efuse->base + EFUSE_DOUT); + clrbits_le32(efuse->base + EFUSE_CTRL, EFUSE_STROBE); + udelay(2); + } + + /* Switch to inactive mode */ + writel(0x0, efuse->base + EFUSE_CTRL); + + return 0; +} + static int rockchip_rk3288_efuse_read(struct udevice *dev, int offset, void *buf, int size) { @@ -211,6 +241,11 @@ static int rockchip_efuse_of_to_plat(struct udevice *dev) return 0; }
+static const struct rockchip_efuse_data rk3128_data = { + .read = rockchip_rk3128_efuse_read, + .size = 0x40, +}; + static const struct rockchip_efuse_data rk3288_data = { .read = rockchip_rk3288_efuse_read, .size = 0x20, @@ -234,6 +269,10 @@ static const struct udevice_id rockchip_efuse_ids[] = { .compatible = "rockchip,rk3066a-efuse", .data = (ulong)&rk3288_data, }, + { + .compatible = "rockchip,rk3128-efuse", + .data = (ulong)&rk3128_data, + }, { .compatible = "rockchip,rk3188-efuse", .data = (ulong)&rk3288_data,

On 2023/2/16 07:48, Jonas Karlman wrote:
Add support for rk3128 compatible.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Thanks, - Kever
drivers/misc/rockchip-efuse.c | 39 +++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/drivers/misc/rockchip-efuse.c b/drivers/misc/rockchip-efuse.c index 7aa3dc1b3868..897e79bcc60f 100644 --- a/drivers/misc/rockchip-efuse.c +++ b/drivers/misc/rockchip-efuse.c @@ -18,6 +18,9 @@ #include <misc.h>
#define EFUSE_CTRL 0x0000 +#define RK3128_A_SHIFT 7 +#define RK3128_A_MASK GENMASK(15, 7) +#define RK3128_ADDR(n) ((n) << RK3128_A_SHIFT) #define RK3288_A_SHIFT 6 #define RK3288_A_MASK GENMASK(15, 6) #define RK3288_ADDR(n) ((n) << RK3288_A_SHIFT) @@ -83,6 +86,33 @@ U_BOOT_CMD( ); #endif
+static int rockchip_rk3128_efuse_read(struct udevice *dev, int offset,
void *buf, int size)
+{
- struct rockchip_efuse_plat *efuse = dev_get_plat(dev);
- u8 *buffer = buf;
- /* Switch to read mode */
- writel(EFUSE_LOAD, efuse->base + EFUSE_CTRL);
- udelay(2);
- while (size--) {
clrsetbits_le32(efuse->base + EFUSE_CTRL, RK3128_A_MASK,
RK3128_ADDR(offset++));
udelay(2);
setbits_le32(efuse->base + EFUSE_CTRL, EFUSE_STROBE);
udelay(2);
*buffer++ = readb(efuse->base + EFUSE_DOUT);
clrbits_le32(efuse->base + EFUSE_CTRL, EFUSE_STROBE);
udelay(2);
- }
- /* Switch to inactive mode */
- writel(0x0, efuse->base + EFUSE_CTRL);
- return 0;
+}
- static int rockchip_rk3288_efuse_read(struct udevice *dev, int offset, void *buf, int size) {
@@ -211,6 +241,11 @@ static int rockchip_efuse_of_to_plat(struct udevice *dev) return 0; }
+static const struct rockchip_efuse_data rk3128_data = {
- .read = rockchip_rk3128_efuse_read,
- .size = 0x40,
+};
- static const struct rockchip_efuse_data rk3288_data = { .read = rockchip_rk3288_efuse_read, .size = 0x20,
@@ -234,6 +269,10 @@ static const struct udevice_id rockchip_efuse_ids[] = { .compatible = "rockchip,rk3066a-efuse", .data = (ulong)&rk3288_data, },
- {
.compatible = "rockchip,rk3128-efuse",
.data = (ulong)&rk3128_data,
- }, { .compatible = "rockchip,rk3188-efuse", .data = (ulong)&rk3288_data,

The cpuid on RK3568 is located at 0xa instead of 0x7 as all other SoCs. Add and use a CFG_CPUID_OFFSET to define this offset.
Signed-off-by: Jonas Karlman jonas@kwiboo.se --- arch/arm/dts/rk356x-u-boot.dtsi | 12 ++++++++++++ arch/arm/mach-rockchip/Kconfig | 2 ++ arch/arm/mach-rockchip/board.c | 2 +- include/configs/rk3568_common.h | 3 +++ include/configs/rockchip-common.h | 2 ++ 5 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/arch/arm/dts/rk356x-u-boot.dtsi b/arch/arm/dts/rk356x-u-boot.dtsi index ccb8db0001a4..4262afce768d 100644 --- a/arch/arm/dts/rk356x-u-boot.dtsi +++ b/arch/arm/dts/rk356x-u-boot.dtsi @@ -20,6 +20,18 @@ u-boot,dm-pre-reloc; status = "okay"; }; + + otp: nvmem@fe38c000 { + compatible = "rockchip,rk3568-otp"; + reg = <0x0 0xfe38c000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <1>; + status = "okay"; + + otp_id: id@a { + reg = <0x0a 0x10>; + }; + }; };
&cru { diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index b678ec41318e..998c6e88e4aa 100644 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -287,6 +287,8 @@ config ROCKCHIP_RK3568 select SYSCON select BOARD_LATE_INIT imply ROCKCHIP_COMMON_BOARD + imply ROCKCHIP_OTP + imply MISC_INIT_R help The Rockchip RK3568 is a ARM-based SoC with quad-core Cortex-A55, including NEON and GPU, 512K L3 cache, Mali-G52 based graphics, diff --git a/arch/arm/mach-rockchip/board.c b/arch/arm/mach-rockchip/board.c index ebffb6c3ff0c..f1f70c81d0ca 100644 --- a/arch/arm/mach-rockchip/board.c +++ b/arch/arm/mach-rockchip/board.c @@ -323,7 +323,7 @@ int fastboot_set_reboot_flag(enum fastboot_reboot_reason reason) #ifdef CONFIG_MISC_INIT_R __weak int misc_init_r(void) { - const u32 cpuid_offset = 0x7; + const u32 cpuid_offset = CFG_CPUID_OFFSET; const u32 cpuid_length = 0x10; u8 cpuid[cpuid_length]; int ret; diff --git a/include/configs/rk3568_common.h b/include/configs/rk3568_common.h index ae360105d508..e4004d19ee37 100644 --- a/include/configs/rk3568_common.h +++ b/include/configs/rk3568_common.h @@ -8,6 +8,9 @@
#include "rockchip-common.h"
+#undef CFG_CPUID_OFFSET +#define CFG_CPUID_OFFSET 0xa + #define CFG_IRAM_BASE 0xfdcc0000
#define CFG_SYS_SDRAM_BASE 0 diff --git a/include/configs/rockchip-common.h b/include/configs/rockchip-common.h index ff8123dabd69..b62c32f02bdb 100644 --- a/include/configs/rockchip-common.h +++ b/include/configs/rockchip-common.h @@ -7,6 +7,8 @@ #define _ROCKCHIP_COMMON_H_ #include <linux/sizes.h>
+#define CFG_CPUID_OFFSET 0x7 + /* ((CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR - 64) * 512) */
#ifndef CONFIG_SPL_BUILD

On 2023/2/16 07:49, Jonas Karlman wrote:
The cpuid on RK3568 is located at 0xa instead of 0x7 as all other SoCs. Add and use a CFG_CPUID_OFFSET to define this offset.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Thanks, - Kever
arch/arm/dts/rk356x-u-boot.dtsi | 12 ++++++++++++ arch/arm/mach-rockchip/Kconfig | 2 ++ arch/arm/mach-rockchip/board.c | 2 +- include/configs/rk3568_common.h | 3 +++ include/configs/rockchip-common.h | 2 ++ 5 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/arch/arm/dts/rk356x-u-boot.dtsi b/arch/arm/dts/rk356x-u-boot.dtsi index ccb8db0001a4..4262afce768d 100644 --- a/arch/arm/dts/rk356x-u-boot.dtsi +++ b/arch/arm/dts/rk356x-u-boot.dtsi @@ -20,6 +20,18 @@ u-boot,dm-pre-reloc; status = "okay"; };
otp: nvmem@fe38c000 {
compatible = "rockchip,rk3568-otp";
reg = <0x0 0xfe38c000 0x0 0x4000>;
#address-cells = <1>;
#size-cells = <1>;
status = "okay";
otp_id: id@a {
reg = <0x0a 0x10>;
};
}; };
&cru {
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index b678ec41318e..998c6e88e4aa 100644 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -287,6 +287,8 @@ config ROCKCHIP_RK3568 select SYSCON select BOARD_LATE_INIT imply ROCKCHIP_COMMON_BOARD
- imply ROCKCHIP_OTP
- imply MISC_INIT_R help The Rockchip RK3568 is a ARM-based SoC with quad-core Cortex-A55, including NEON and GPU, 512K L3 cache, Mali-G52 based graphics,
diff --git a/arch/arm/mach-rockchip/board.c b/arch/arm/mach-rockchip/board.c index ebffb6c3ff0c..f1f70c81d0ca 100644 --- a/arch/arm/mach-rockchip/board.c +++ b/arch/arm/mach-rockchip/board.c @@ -323,7 +323,7 @@ int fastboot_set_reboot_flag(enum fastboot_reboot_reason reason) #ifdef CONFIG_MISC_INIT_R __weak int misc_init_r(void) {
- const u32 cpuid_offset = 0x7;
- const u32 cpuid_offset = CFG_CPUID_OFFSET; const u32 cpuid_length = 0x10; u8 cpuid[cpuid_length]; int ret;
diff --git a/include/configs/rk3568_common.h b/include/configs/rk3568_common.h index ae360105d508..e4004d19ee37 100644 --- a/include/configs/rk3568_common.h +++ b/include/configs/rk3568_common.h @@ -8,6 +8,9 @@
#include "rockchip-common.h"
+#undef CFG_CPUID_OFFSET +#define CFG_CPUID_OFFSET 0xa
#define CFG_IRAM_BASE 0xfdcc0000
#define CFG_SYS_SDRAM_BASE 0
diff --git a/include/configs/rockchip-common.h b/include/configs/rockchip-common.h index ff8123dabd69..b62c32f02bdb 100644 --- a/include/configs/rockchip-common.h +++ b/include/configs/rockchip-common.h @@ -7,6 +7,8 @@ #define _ROCKCHIP_COMMON_H_ #include <linux/sizes.h>
+#define CFG_CPUID_OFFSET 0x7
/* ((CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR - 64) * 512) */
#ifndef CONFIG_SPL_BUILD
participants (3)
-
Chen-Yu Tsai
-
Jonas Karlman
-
Kever Yang