diff mbox series

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

Message ID 20200220025353.3158-4-finley.xiao@rock-chips.com
State New
Headers show
Series rockchip: efuse: add support for more platfroms | expand

Commit Message

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

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

Comments

Kever Yang March 2, 2020, 9:42 a.m. UTC | #1
Hi Finley,


 ??? NAK for this patch, rk1808 is not support by upstream U-Boot now.


Thanks,

- Kever

On 2020/2/20 ??10:53, Finley Xiao wrote:
> This adds the necessary data for handling eFuse on the rk1808.
>
> Signed-off-by: Finley Xiao <finley.xiao at rock-chips.com>
> ---
>   drivers/misc/rockchip-efuse.c | 114 ++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 114 insertions(+)
>
> 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,
>   	},
diff mbox series

Patch

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,
 	},