From: Finley Xiao Date: Wed, 5 Apr 2017 10:01:48 +0000 (+0800) Subject: nvmem: rockchip-efuse: add support for rk3288 secure efuse X-Git-Tag: firefly_0821_release~99 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=firefly-linux-kernel-4.4.55.git;a=commitdiff_plain;h=28ce472032d4f09f1aa7a8171f40ffea850a2652 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 --- diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt index 36ee06eb8469..ceab1d14f1ab 100644 --- a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt +++ b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt @@ -5,6 +5,7 @@ Required properties: - "rockchip,rk3066a-efuse" - for RK3066a SoCs. - "rockchip,rk3188-efuse" - for RK3188 SoCs. - "rockchip,rk3288-efuse" - for RK3288 SoCs. + - "rockchip,rk3288-secure-efuse" - for RK3288 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 986734aef252..c117d071d967 100644 --- a/drivers/nvmem/rockchip-efuse.c +++ b/drivers/nvmem/rockchip-efuse.c @@ -99,6 +99,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_rk3366_efuse_read(void *context, unsigned int offset, void *val, size_t bytes) { @@ -265,6 +311,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,rk3366-efuse", .data = (void *)&rockchip_rk3366_efuse_read,