[2/2] rockchip: efuse: Add support for rk1808 non-secure efuse
diff mbox series

Message ID 20200220023812.1998-4-finley.xiao@rock-chips.com
State Changes Requested
Delegated to: Kever Yang
Headers show
Series
  • Untitled series #159639
Related show

Commit Message

Finley Xiao Feb. 20, 2020, 2:38 a.m. UTC
This adds the necessary data for handling eFuse on the rk1808.

Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
---
 drivers/misc/rockchip-efuse.c | 114 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 114 insertions(+)

Patch
diff mbox series

diff --git a/drivers/misc/rockchip-efuse.c b/drivers/misc/rockchip-efuse.c
index 68762d3f6f..778e29f30d 100644
--- a/drivers/misc/rockchip-efuse.c
+++ b/drivers/misc/rockchip-efuse.c
@@ -16,6 +16,46 @@ 
 #include <malloc.h>
 #include <misc.h>
 
+#define T_CSB_P_S		0
+#define T_PGENB_P_S		0
+#define T_LOAD_P_S		0
+#define T_ADDR_P_S		0
+#define T_STROBE_P_S		(0 + 110) /* 1.1us */
+#define T_CSB_P_L		(0 + 110 + 1000 + 20) /* 200ns */
+#define T_PGENB_P_L		(0 + 110 + 1000 + 20)
+#define T_LOAD_P_L		(0 + 110 + 1000 + 20)
+#define T_ADDR_P_L		(0 + 110 + 1000 + 20)
+#define T_STROBE_P_L		(0 + 110 + 1000) /* 10us */
+#define T_CSB_R_S		0
+#define T_PGENB_R_S		0
+#define T_LOAD_R_S		0
+#define T_ADDR_R_S		2
+#define T_STROBE_R_S		(2 + 3)
+#define T_CSB_R_L		(2 + 3 + 3 + 3)
+#define T_PGENB_R_L		(2 + 3 + 3 + 3)
+#define T_LOAD_R_L		(2 + 3 + 3 + 3)
+#define T_ADDR_R_L		(2 + 3 + 3 + 2)
+#define T_STROBE_R_L		(2 + 3 + 3)
+
+#define T_CSB_P			0x28
+#define T_PGENB_P		0x2c
+#define T_LOAD_P		0x30
+#define T_ADDR_P		0x34
+#define T_STROBE_P		0x38
+#define T_CSB_R			0x3c
+#define T_PGENB_R		0x40
+#define T_LOAD_R		0x44
+#define T_ADDR_R		0x48
+#define T_STROBE_R		0x4c
+
+#define RK1808_USER_MODE	BIT(0)
+#define RK1808_INT_FINISH	BIT(0)
+#define RK1808_AUTO_ENB		BIT(0)
+#define RK1808_AUTO_RD		BIT(1)
+#define RK1808_A_SHIFT		16
+#define RK1808_A_MASK		0x3ff
+#define RK1808_NBYTES		4
+
 #define RK3288_A_SHIFT          6
 #define RK3288_A_MASK           0x3ff
 #define RK3288_NFUSES           32
@@ -109,6 +149,76 @@  U_BOOT_CMD(
 );
 #endif
 
+static void rk1808_efuse_timing_init(void __iomem *base)
+{
+	static bool init;
+
+	if (init)
+		return;
+
+	/* enable auto mode */
+	writel(readl(base) & (~RK1808_USER_MODE), base);
+
+	/* setup efuse timing */
+	writel((T_CSB_P_S << 16) | T_CSB_P_L, base + T_CSB_P);
+	writel((T_PGENB_P_S << 16) | T_PGENB_P_L, base + T_PGENB_P);
+	writel((T_LOAD_P_S << 16) | T_LOAD_P_L, base + T_LOAD_P);
+	writel((T_ADDR_P_S << 16) | T_ADDR_P_L, base + T_ADDR_P);
+	writel((T_STROBE_P_S << 16) | T_STROBE_P_L, base + T_STROBE_P);
+	writel((T_CSB_R_S << 16) | T_CSB_R_L, base + T_CSB_R);
+	writel((T_PGENB_R_S << 16) | T_PGENB_R_L, base + T_PGENB_R);
+	writel((T_LOAD_R_S << 16) | T_LOAD_R_L, base + T_LOAD_R);
+	writel((T_ADDR_R_S << 16) | T_ADDR_R_L, base + T_ADDR_R);
+	writel((T_STROBE_R_S << 16) | T_STROBE_R_L, base + T_STROBE_R);
+
+	init = true;
+}
+
+static int rockchip_rk1808_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;
+
+	rk1808_efuse_timing_init(plat->base);
+
+	addr_start = rounddown(offset, RK1808_NBYTES) / RK1808_NBYTES;
+	addr_end = roundup(offset + size, RK1808_NBYTES) / RK1808_NBYTES;
+	addr_offset = offset % RK1808_NBYTES;
+	addr_len = addr_end - addr_start;
+
+	buffer = calloc(1, sizeof(*buffer) * addr_len * RK1808_NBYTES);
+	if (!buffer)
+		return -ENOMEM;
+
+	while (addr_len--) {
+		writel(RK1808_AUTO_RD | RK1808_AUTO_ENB |
+		       ((addr_start++ & RK1808_A_MASK) << RK1808_A_SHIFT),
+		       &efuse->auto_ctrl);
+		udelay(2);
+		status = readl(&efuse->int_status);
+		if (!(status & RK1808_INT_FINISH)) {
+			ret = -EIO;
+			goto err;
+		}
+		out_value = readl(&efuse->dout2);
+		writel(RK1808_INT_FINISH, &efuse->int_status);
+
+		memcpy(&buffer[i], &out_value, RK1808_NBYTES);
+		i += RK1808_NBYTES;
+	}
+	memcpy(buf, buffer + addr_offset, size);
+err:
+	free(buffer);
+
+	return ret;
+}
+
 static int rockchip_rk3288_efuse_read(struct udevice *dev, int offset,
 				      void *buf, int size)
 {
@@ -273,6 +383,10 @@  static int rockchip_efuse_ofdata_to_platdata(struct udevice *dev)
 
 static const struct udevice_id rockchip_efuse_ids[] = {
 	{
+		.compatible = "rockchip,rk1808-efuse",
+		.data = (ulong)&rockchip_rk1808_efuse_read,
+	},
+	{
 		.compatible = "rockchip,rk3066a-efuse",
 		.data = (ulong)&rockchip_rk3288_efuse_read,
 	},