From 768ff9ab40cc54e03895a46a4818d36dec150cac Mon Sep 17 00:00:00 2001 From: Paolo Sabatino Date: Sun, 4 Apr 2021 10:29:29 +0000 Subject: [PATCH] Enable rockchip efuse for rk322x, rk3288 and rk3328 --- arch/arm/dts/rk322x.dtsi | 14 +++ arch/arm/dts/rk3288.dtsi | 3 +- configs/evb-rk3229_defconfig | 3 + configs/evb-rk3328_defconfig | 3 + configs/miqi-rk3288_defconfig | 2 + configs/rock64-rk3328_defconfig | 2 + configs/tinker-rk3288_defconfig | 1 + configs/tinker-s-rk3288_defconfig | 1 + drivers/misc/rockchip-efuse.c | 142 ++++++++++++++++++++++++- include/dt-bindings/clock/rk3228-cru.h | 4 + 10 files changed, 169 insertions(+), 6 deletions(-) diff --git a/arch/arm/dts/rk322x.dtsi b/arch/arm/dts/rk322x.dtsi index 4a8be5dabb..255e3a7a28 100644 --- a/arch/arm/dts/rk322x.dtsi +++ b/arch/arm/dts/rk322x.dtsi @@ -212,6 +212,20 @@ status = "disabled"; }; + efuse: efuse@11040000 { + compatible = "rockchip,rk3228-efuse", "rockchip,rk3288-efuse"; + reg = <0x11040000 0x20>; + clocks = <&cru PCLK_EFUSE_256>; + clock-names = "pclk_efuse"; + #address-cells = <1>; + #size-cells = <1>; + + /* Data cells */ + cpu_id: cpu_id@7 { + reg = <0x7 0x10>; + }; + }; + i2c0: i2c@11050000 { compatible = "rockchip,rk3228-i2c"; reg = <0x11050000 0x1000>; diff --git a/arch/arm/dts/rk3288.dtsi b/arch/arm/dts/rk3288.dtsi index 22bb06cec5..381391360c 100644 --- a/arch/arm/dts/rk3288.dtsi +++ b/arch/arm/dts/rk3288.dtsi @@ -919,8 +919,7 @@ efuse: efuse@ffb40000 { compatible = "rockchip,rk3288-efuse"; - reg = <0xffb40000 0x10000>; - status = "disabled"; + reg = <0xffb40000 0x20>; }; gic: interrupt-controller@ffc01000 { diff --git a/configs/evb-rk3229_defconfig b/configs/evb-rk3229_defconfig index e708ed4909..e3ba0651fd 100644 --- a/configs/evb-rk3229_defconfig +++ b/configs/evb-rk3229_defconfig @@ -49,6 +49,8 @@ CONFIG_FASTBOOT_BUF_SIZE=0x04000000 CONFIG_FASTBOOT_CMD_OEM_FORMAT=y CONFIG_ROCKCHIP_GPIO=y CONFIG_SYS_I2C_ROCKCHIP=y +CONFIG_MISC=y +CONFIG_ROCKCHIP_EFUSE=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y CONFIG_MTD=y @@ -68,3 +70,4 @@ CONFIG_USB_GADGET=y CONFIG_USB_GADGET_DWC2_OTG=y CONFIG_TPL_TINY_MEMSET=y CONFIG_ERRNO_STR=y +CONFIG_MISC_INIT_R=y diff --git a/configs/evb-rk3328_defconfig b/configs/evb-rk3328_defconfig index 9cbfeb0279..f0acfd8abd 100644 --- a/configs/evb-rk3328_defconfig +++ b/configs/evb-rk3328_defconfig @@ -20,6 +20,7 @@ CONFIG_FIT=y CONFIG_FIT_VERBOSE=y CONFIG_SPL_LOAD_FIT=y CONFIG_DEFAULT_FDT_FILE="rockchip/rk3328-evb.dtb" +CONFIG_MISC_INIT_R=y # CONFIG_DISPLAY_CPUINFO is not set CONFIG_DISPLAY_BOARDINFO_LATE=y # CONFIG_SPL_RAW_IMAGE_SUPPORT is not set @@ -56,6 +57,8 @@ CONFIG_FASTBOOT_BUF_ADDR=0x800800 CONFIG_FASTBOOT_CMD_OEM_FORMAT=y CONFIG_ROCKCHIP_GPIO=y CONFIG_SYS_I2C_ROCKCHIP=y +CONFIG_MISC=y +CONFIG_ROCKCHIP_EFUSE=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y CONFIG_SF_DEFAULT_SPEED=20000000 diff --git a/configs/miqi-rk3288_defconfig b/configs/miqi-rk3288_defconfig index 234ced5ab0..3d42e93866 100644 --- a/configs/miqi-rk3288_defconfig +++ b/configs/miqi-rk3288_defconfig @@ -49,6 +49,8 @@ CONFIG_SPL_CLK=y CONFIG_FASTBOOT_CMD_OEM_FORMAT=y CONFIG_ROCKCHIP_GPIO=y CONFIG_SYS_I2C_ROCKCHIP=y +CONFIG_MISC=y +CONFIG_ROCKCHIP_EFUSE=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y CONFIG_MTD=y diff --git a/configs/rock64-rk3328_defconfig b/configs/rock64-rk3328_defconfig index cb79cea821..dacb57165e 100644 --- a/configs/rock64-rk3328_defconfig +++ b/configs/rock64-rk3328_defconfig @@ -57,6 +57,8 @@ CONFIG_FASTBOOT_BUF_ADDR=0x800800 CONFIG_FASTBOOT_CMD_OEM_FORMAT=y CONFIG_ROCKCHIP_GPIO=y CONFIG_SYS_I2C_ROCKCHIP=y +CONFIG_MISC=y +CONFIG_ROCKCHIP_EFUSE=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y CONFIG_SF_DEFAULT_SPEED=20000000 diff --git a/configs/tinker-rk3288_defconfig b/configs/tinker-rk3288_defconfig index 8686a66d13..b7dc845451 100644 --- a/configs/tinker-rk3288_defconfig +++ b/configs/tinker-rk3288_defconfig @@ -52,6 +52,7 @@ CONFIG_FASTBOOT_CMD_OEM_FORMAT=y CONFIG_ROCKCHIP_GPIO=y CONFIG_SYS_I2C_ROCKCHIP=y CONFIG_MISC=y +CONFIG_ROCKCHIP_EFUSE=y CONFIG_I2C_EEPROM=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y diff --git a/configs/tinker-s-rk3288_defconfig b/configs/tinker-s-rk3288_defconfig index 22714833cc..19aa314164 100644 --- a/configs/tinker-s-rk3288_defconfig +++ b/configs/tinker-s-rk3288_defconfig @@ -53,6 +53,7 @@ CONFIG_FASTBOOT_CMD_OEM_FORMAT=y CONFIG_ROCKCHIP_GPIO=y CONFIG_SYS_I2C_ROCKCHIP=y CONFIG_MISC=y +CONFIG_ROCKCHIP_EFUSE=y CONFIG_I2C_EEPROM=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y diff --git a/drivers/misc/rockchip-efuse.c b/drivers/misc/rockchip-efuse.c index 083ee65e0a..0fcbcfc69a 100644 --- a/drivers/misc/rockchip-efuse.c +++ b/drivers/misc/rockchip-efuse.c @@ -14,6 +14,7 @@ #include #include #include +#include #define RK3399_A_SHIFT 16 #define RK3399_A_MASK 0x3ff @@ -27,6 +28,24 @@ #define RK3399_STROBE BIT(1) #define RK3399_CSB BIT(0) +#define RK3288_A_SHIFT 6 +#define RK3288_A_MASK 0x3ff +#define RK3288_NFUSES 32 +#define RK3288_BYTES_PER_FUSE 1 +#define RK3288_PGENB BIT(3) +#define RK3288_LOAD BIT(2) +#define RK3288_STROBE BIT(1) +#define RK3288_CSB BIT(0) + +#define RK3328_INT_STATUS 0x0018 +#define RK3328_DOUT 0x0020 +#define RK3328_AUTO_CTRL 0x0024 +#define RK3328_INT_FINISH BIT(0) +#define RK3328_AUTO_ENB BIT(0) +#define RK3328_AUTO_RD BIT(1) + +typedef int (*EFUSE_READ)(struct udevice *dev, int offset, void *buf, int size); + struct rockchip_efuse_regs { u32 ctrl; /* 0x00 efuse control register */ u32 dout; /* 0x04 efuse data out register */ @@ -35,6 +54,10 @@ struct rockchip_efuse_regs { u32 jtag_pass; /* 0x10 JTAG password */ u32 strobe_finish_ctrl; /* 0x14 efuse strobe finish control register */ + u32 int_status;/* 0x18 */ + u32 reserved; /* 0x1c */ + u32 dout2; /* 0x20 */ + u32 auto_ctrl; /* 0x24 */ }; struct rockchip_efuse_plat { @@ -53,7 +76,7 @@ static int dump_efuses(struct cmd_tbl *cmdtp, int flag, */ struct udevice *dev; - u8 fuses[128]; + u8 fuses[128] = {0}; int ret; /* retrieve the device */ @@ -77,7 +100,7 @@ static int dump_efuses(struct cmd_tbl *cmdtp, int flag, } U_BOOT_CMD( - rk3399_dump_efuses, 1, 1, dump_efuses, + rockchip_dump_efuses, 1, 1, dump_efuses, "Dump the content of the efuses", "" ); @@ -127,10 +150,110 @@ static int rockchip_rk3399_efuse_read(struct udevice *dev, int offset, return 0; } +static int rockchip_rk3288_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; + u8 *buffer = buf; + int max_size = RK3288_NFUSES * RK3288_BYTES_PER_FUSE; + + if (size > (max_size - offset)) + size = max_size - offset; + + /* Switch to read mode */ + writel(RK3288_LOAD | RK3288_PGENB, &efuse->ctrl); + udelay(1); + + while (size--) { + writel(readl(&efuse->ctrl) & + (~(RK3288_A_MASK << RK3288_A_SHIFT)), + &efuse->ctrl); + /* set addr */ + writel(readl(&efuse->ctrl) | + ((offset++ & RK3288_A_MASK) << RK3288_A_SHIFT), + &efuse->ctrl); + udelay(1); + /* strobe low to high */ + writel(readl(&efuse->ctrl) | + RK3288_STROBE, &efuse->ctrl); + ndelay(60); + /* read data */ + *buffer++ = readl(&efuse->dout); + /* reset strobe to low */ + writel(readl(&efuse->ctrl) & + (~RK3288_STROBE), &efuse->ctrl); + udelay(1); + } + + /* Switch to standby mode */ + writel(RK3288_PGENB | RK3288_CSB, &efuse->ctrl); + + return 0; +} + +static int rockchip_rk3328_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, addr_len; + u32 out_value, status; + u8 *buffer; + int ret = 0, i = 0, j = 0; + + /* Max non-secure Byte */ + if (size > 32) + size = 32; + + /* 128 Byte efuse, 96 Byte for secure, 32 Byte for non-secure */ + offset += 96; + addr_start = rounddown(offset, RK3399_BYTES_PER_FUSE) / + RK3399_BYTES_PER_FUSE; + addr_end = roundup(offset + size, RK3399_BYTES_PER_FUSE) / + RK3399_BYTES_PER_FUSE; + addr_offset = offset % RK3399_BYTES_PER_FUSE; + addr_len = addr_end - addr_start; + + buffer = calloc(1, sizeof(*buffer) * addr_len * RK3399_BYTES_PER_FUSE); + if (!buffer) + return -ENOMEM; + + for (j = 0; j < addr_len; j++) { + writel(RK3328_AUTO_RD | RK3328_AUTO_ENB | + ((addr_start++ & RK3399_A_MASK) << RK3399_A_SHIFT), + &efuse->auto_ctrl); + udelay(5); + status = readl(&efuse->int_status); + if (!(status & RK3328_INT_FINISH)) { + ret = -EIO; + goto err; + } + out_value = readl(&efuse->dout2); + writel(RK3328_INT_FINISH, &efuse->int_status); + + memcpy(&buffer[i], &out_value, RK3399_BYTES_PER_FUSE); + i += RK3399_BYTES_PER_FUSE; + } + memcpy(buf, buffer + addr_offset, size); +err: + free(buffer); + + return ret; +} + static int rockchip_efuse_read(struct udevice *dev, int offset, void *buf, int size) { - return rockchip_rk3399_efuse_read(dev, offset, buf, size); + EFUSE_READ efuse_read = NULL; + + efuse_read = (EFUSE_READ)dev_get_driver_data(dev); + if (!efuse_read) + return -ENOSYS; + + return (*efuse_read)(dev, offset, buf, size); } static const struct misc_ops rockchip_efuse_ops = { @@ -146,7 +269,18 @@ static int rockchip_efuse_of_to_plat(struct udevice *dev) } static const struct udevice_id rockchip_efuse_ids[] = { - { .compatible = "rockchip,rk3399-efuse" }, + { + .compatible = "rockchip,rk3288-efuse", + .data = (ulong)&rockchip_rk3288_efuse_read, + }, + { + .compatible = "rockchip,rk3328-efuse", + .data = (ulong)&rockchip_rk3328_efuse_read, + }, + { + .compatible = "rockchip,rk3399-efuse", + .data = (ulong)&rockchip_rk3399_efuse_read, + }, {} }; diff --git a/include/dt-bindings/clock/rk3228-cru.h b/include/dt-bindings/clock/rk3228-cru.h index 1217d5239f..13b2f4e4a4 100644 --- a/include/dt-bindings/clock/rk3228-cru.h +++ b/include/dt-bindings/clock/rk3228-cru.h @@ -67,6 +67,10 @@ #define PCLK_GPIO1 321 #define PCLK_GPIO2 322 #define PCLK_GPIO3 323 +#define PCLK_VIO_H2P 324 +#define PCLK_HDCP 325 +#define PCLK_EFUSE_1024 326 +#define PCLK_EFUSE_256 327 #define PCLK_GRF 329 #define PCLK_I2C0 332 #define PCLK_I2C1 333 -- 2.25.1