From 33405d5aa9a712bb48ecb86ec43791545a8ce041 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Thu, 30 Mar 2017 20:35:07 +0800 Subject: [PATCH] nvmem: rockchip-efuse: add support for rk3328-efuse This adds the necessary data for handling efuse on the rk3328. Change-Id: Ica66635977163f380b7d96d73d3a2423d1e08298 Signed-off-by: Finley Xiao --- .../bindings/nvmem/rockchip-efuse.txt | 1 + drivers/nvmem/rockchip-efuse.c | 64 +++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt index 19b3dad67528..970b50ee269c 100644 --- a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt +++ b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt @@ -6,6 +6,7 @@ Required properties: - "rockchip,rk3188-efuse" - for RK3188 SoCs. - "rockchip,rk3288-efuse" - for RK3288 SoCs. - "rockchip,rk3288-secure-efuse" - for RK3288 SoCs. + - "rockchip,rk3328-efuse" - for RK3328 SoCs. - "rockchip,rk3366-efuse" - for RK3366 SoCs. - "rockchip,rk3368-efuse" - for RK3368 SoCs. - "rockchip,rk3399-efuse" - for RK3399 SoCs. diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c index 294816c2430a..8985d02b2aa2 100644 --- a/drivers/nvmem/rockchip-efuse.c +++ b/drivers/nvmem/rockchip-efuse.c @@ -33,6 +33,13 @@ #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 RK3366_A_SHIFT 6 #define RK3366_A_MASK 0x3ff #define RK3366_RDEN BIT(2) @@ -145,6 +152,59 @@ static int rockchip_rk3288_efuse_secure_read(void *context, return 0; } +static int rockchip_rk3328_efuse_read(void *context, unsigned int offset, + void *val, size_t bytes) +{ + struct rockchip_efuse_chip *efuse = context; + unsigned int addr_start, addr_end, addr_offset, addr_len; + u32 out_value, status; + u8 *buf; + int ret, i = 0; + + /* 128 Byte efuse, 96 Byte for secure, 32 Byte for non-secure */ + offset += 96; + ret = clk_prepare_enable(efuse->clk); + if (ret < 0) { + dev_err(efuse->dev, "failed to prepare/enable efuse clk\n"); + return ret; + } + + addr_start = rounddown(offset, RK3399_NBYTES) / RK3399_NBYTES; + addr_end = roundup(offset + bytes, RK3399_NBYTES) / RK3399_NBYTES; + addr_offset = offset % RK3399_NBYTES; + addr_len = addr_end - addr_start; + + buf = kzalloc(sizeof(*buf) * addr_len * RK3399_NBYTES, GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto nomem; + } + + while (addr_len--) { + writel(RK3328_AUTO_RD | RK3328_AUTO_ENB | + ((addr_start++ & RK3399_A_MASK) << RK3399_A_SHIFT), + efuse->base + RK3328_AUTO_CTRL); + udelay(2); + status = readl(efuse->base + RK3328_INT_STATUS); + if (!(status & RK3328_INT_FINISH)) { + ret = -EIO; + goto err; + } + out_value = readl(efuse->base + RK3328_DOUT); + writel(RK3328_INT_FINISH, efuse->base + RK3328_INT_STATUS); + + memcpy(&buf[i], &out_value, RK3399_NBYTES); + i += RK3399_NBYTES; + } + memcpy(val, buf + addr_offset, bytes); +err: + kfree(buf); +nomem: + clk_disable_unprepare(efuse->clk); + + return ret; +} + static int rockchip_rk3366_efuse_read(void *context, unsigned int offset, void *val, size_t bytes) { @@ -315,6 +375,10 @@ static const struct of_device_id rockchip_efuse_match[] = { .compatible = "rockchip,rk3288-secure-efuse", .data = (void *)&rockchip_rk3288_efuse_secure_read, }, + { + .compatible = "rockchip,rk3328-efuse", + .data = (void *)&rockchip_rk3328_efuse_read, + }, { .compatible = "rockchip,rk3366-efuse", .data = (void *)&rockchip_rk3366_efuse_read, -- 2.34.1