@@ -13,6 +13,7 @@
#include <dm.h>
#include <linux/bitops.h>
#include <linux/delay.h>
+#include <malloc.h>
#include <misc.h>
#define RK3288_A_SHIFT 6
@@ -24,6 +25,15 @@
#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)
+#define RK3328_NO_SECURE_BYTES 32
+#define RK3328_SECURE_BYTES 96
+
#define RK3399_A_SHIFT 16
#define RK3399_A_MASK 0x3ff
#define RK3399_NFUSES 32
@@ -47,6 +57,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_platdata {
@@ -138,6 +152,57 @@ 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_platdata *plat = dev_get_platdata(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 > RK3328_NO_SECURE_BYTES)
+ size = RK3328_NO_SECURE_BYTES;
+
+ /* 128 Byte efuse, 96 Byte for secure, 32 Byte for non-secure */
+ offset += RK3328_SECURE_BYTES;
+ 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_rk3399_efuse_read(struct udevice *dev, int offset,
void *buf, int size)
{
@@ -224,6 +289,10 @@ static const struct udevice_id rockchip_efuse_ids[] = {
.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,
},
This adds the necessary data for handling eFuse on the rk3328. Signed-off-by: Finley Xiao <finley.xiao at rock-chips.com> --- drivers/misc/rockchip-efuse.c | 69 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+)