From 774fb77ce56a1c15347eff816dcc5d5eefae68ac Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Wed, 5 Apr 2017 18:01:48 +0800 Subject: [PATCH] nvmem: rockchip-efuse: add support for rk3288 secure efuse This adds the necessary data for handling secure efuse on the rk3288. Need to use secure interface to access efuse when kernel is in no-secure mode. Change-Id: I1979f23ed8f85c9eb248de276b32adcbb165bd79 Signed-off-by: Finley Xiao --- .../bindings/nvmem/rockchip-efuse.yaml | 1 + drivers/nvmem/rockchip-efuse.c | 50 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml index 104dd508565e..4dd06326424b 100644 --- a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml +++ b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml @@ -19,6 +19,7 @@ properties: - rockchip,rk3188-efuse - rockchip,rk3228-efuse - rockchip,rk3288-efuse + - rockchip,rk3288-secure-efuse - rockchip,rk3328-efuse - rockchip,rk3368-efuse - rockchip,rk3399-efuse diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c index c29a6137a5e3..b11326553e78 100644 --- a/drivers/nvmem/rockchip-efuse.c +++ b/drivers/nvmem/rockchip-efuse.c @@ -94,6 +94,52 @@ static int rockchip_rk3288_efuse_read(void *context, unsigned int offset, return 0; } +static int rockchip_rk3288_efuse_secure_read(void *context, + unsigned int offset, + void *val, size_t bytes) +{ + struct rockchip_efuse_chip *efuse = context; + u8 *buf = val; + u32 wr_val; + int ret; + + ret = clk_prepare_enable(efuse->clk); + if (ret < 0) { + dev_err(efuse->dev, "failed to prepare/enable efuse clk\n"); + return ret; + } + + sip_smc_secure_reg_write(efuse->phys + REG_EFUSE_CTRL, + RK3288_LOAD | RK3288_PGENB); + udelay(1); + while (bytes--) { + wr_val = sip_smc_secure_reg_read(efuse->phys + REG_EFUSE_CTRL) & + (~(RK3288_A_MASK << RK3288_A_SHIFT)); + sip_smc_secure_reg_write(efuse->phys + REG_EFUSE_CTRL, wr_val); + wr_val = sip_smc_secure_reg_read(efuse->phys + REG_EFUSE_CTRL) | + ((offset++ & RK3288_A_MASK) << RK3288_A_SHIFT); + sip_smc_secure_reg_write(efuse->phys + REG_EFUSE_CTRL, wr_val); + udelay(1); + wr_val = sip_smc_secure_reg_read(efuse->phys + REG_EFUSE_CTRL) | + RK3288_STROBE; + sip_smc_secure_reg_write(efuse->phys + REG_EFUSE_CTRL, wr_val); + udelay(1); + *buf++ = sip_smc_secure_reg_read(efuse->phys + REG_EFUSE_DOUT); + wr_val = sip_smc_secure_reg_read(efuse->phys + REG_EFUSE_CTRL) & + (~RK3288_STROBE); + sip_smc_secure_reg_write(efuse->phys + REG_EFUSE_CTRL, wr_val); + udelay(1); + } + + /* Switch to standby mode */ + sip_smc_secure_reg_write(efuse->phys + REG_EFUSE_CTRL, + RK3288_PGENB | RK3288_CSB); + + clk_disable_unprepare(efuse->clk); + + return 0; +} + static int rockchip_rk3328_efuse_read(void *context, unsigned int offset, void *val, size_t bytes) { @@ -279,6 +325,10 @@ static const struct of_device_id rockchip_efuse_match[] = { .compatible = "rockchip,rk3288-efuse", .data = (void *)&rockchip_rk3288_efuse_read, }, + { + .compatible = "rockchip,rk3288-secure-efuse", + .data = (void *)&rockchip_rk3288_efuse_secure_read, + }, { .compatible = "rockchip,rk3328-efuse", .data = (void *)&rockchip_rk3328_efuse_read,