nvmem: rockchip-otp: Add support for rk3568-otp

This adds the necessary data for handling efuse on the rk3568.

Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
Change-Id: Ia74d77b68a6303223eaccdc08e882851a917f50f
This commit is contained in:
Finley Xiao
2020-11-12 16:24:14 +08:00
committed by Tao Huang
parent 08ef2dd998
commit 92b14c36c7
2 changed files with 83 additions and 0 deletions

View File

@@ -4,6 +4,7 @@ Required properties:
- compatible: Should be one of the following.
- "rockchip,px30-otp" - for PX30 SoCs.
- "rockchip,rk3308-otp" - for RK3308 SoCs.
- "rockchip,rk3568-otp" - for RK3568 SoCs.
- "rockchip,rv1126-otp" - for RV1126 SoCs.
- reg: Must contain an entry with the physical base address and length
for each entry in reg-names.

View File

@@ -54,6 +54,7 @@
#define OTPC_TIMEOUT 10000
#define OTPC_TIMEOUT_PROG 100000
#define RK3568_NBYTES 2
#define RV1126_OTP_NVM_CEB 0x00
#define RV1126_OTP_NVM_RSTB 0x04
@@ -249,6 +250,72 @@ disable_clks:
return ret;
}
static int rk3568_otp_read(void *context, unsigned int offset, void *val,
size_t bytes)
{
struct rockchip_otp *otp = context;
unsigned int addr_start, addr_end, addr_offset, addr_len;
u32 out_value;
u8 *buf;
int ret = 0, i = 0;
addr_start = rounddown(offset, RK3568_NBYTES) / RK3568_NBYTES;
addr_end = roundup(offset + bytes, RK3568_NBYTES) / RK3568_NBYTES;
addr_offset = offset % RK3568_NBYTES;
addr_len = addr_end - addr_start;
buf = kzalloc(array3_size(addr_len, RK3568_NBYTES, sizeof(*buf)),
GFP_KERNEL);
if (!buf)
return -ENOMEM;
ret = clk_bulk_prepare_enable(otp->num_clks, otp->clks);
if (ret < 0) {
dev_err(otp->dev, "failed to prepare/enable clks\n");
goto out;
}
ret = rockchip_otp_reset(otp);
if (ret) {
dev_err(otp->dev, "failed to reset otp phy\n");
goto disable_clks;
}
ret = px30_otp_ecc_enable(otp, false);
if (ret < 0) {
dev_err(otp->dev, "rockchip_otp_ecc_enable err\n");
goto disable_clks;
}
writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
udelay(5);
while (addr_len--) {
writel(addr_start++ | 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 = px30_otp_wait_status(otp, OTPC_USER_DONE);
if (ret < 0) {
dev_err(otp->dev, "timeout during read setup\n");
goto read_end;
}
out_value = readl(otp->base + OTPC_USER_Q);
memcpy(&buf[i], &out_value, RK3568_NBYTES);
i += RK3568_NBYTES;
}
memcpy(val, buf + addr_offset, bytes);
read_end:
writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
disable_clks:
clk_bulk_disable_unprepare(otp->num_clks, otp->clks);
out:
kfree(buf);
return ret;
}
static int rv1126_otp_init(struct rockchip_otp *otp)
{
u32 status = 0;
@@ -429,6 +496,17 @@ static const struct rockchip_data px30_data = {
.reg_read = px30_otp_read,
};
static const char * const rk3568_otp_clocks[] = {
"usr", "sbpi", "apb", "phy",
};
static const struct rockchip_data rk3568_data = {
.size = 0x80,
.clocks = rk3568_otp_clocks,
.num_clks = ARRAY_SIZE(rk3568_otp_clocks),
.reg_read = rk3568_otp_read,
};
static const char * const rv1126_otp_clocks[] = {
"otp", "apb_pclk",
};
@@ -451,6 +529,10 @@ static const struct of_device_id rockchip_otp_match[] = {
.compatible = "rockchip,rk3308-otp",
.data = (void *)&px30_data,
},
{
.compatible = "rockchip,rk3568-otp",
.data = (void *)&rk3568_data,
},
{
.compatible = "rockchip,rv1126-otp",
.data = (void *)&rv1126_data,