From 873777cb8b8b4e5dfb61fbf57477814adfd72cf1 Mon Sep 17 00:00:00 2001 From: guoyi Date: Fri, 27 Mar 2015 11:07:02 +0800 Subject: [PATCH] rk3368: add rockchip_get_temp function and rockchip_get_leakage support for 3368 --- arch/arm/mach-rockchip/efuse.c | 180 ++++++++++++++++++++++++++++++++- arch/arm/mach-rockchip/efuse.h | 1 + 2 files changed, 178 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-rockchip/efuse.c b/arch/arm/mach-rockchip/efuse.c index dbb2325ebbd3..f48b1c2e677c 100644 --- a/arch/arm/mach-rockchip/efuse.c +++ b/arch/arm/mach-rockchip/efuse.c @@ -10,11 +10,32 @@ #include #include #include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + #ifdef CONFIG_ARM #include #endif #include "efuse.h" + #define efuse_readl(offset) readl_relaxed(RK_EFUSE_VIRT + offset) #define efuse_writel(val, offset) writel_relaxed(val, RK_EFUSE_VIRT + offset) @@ -22,12 +43,144 @@ static u8 efuse_buf[32] = {}; struct rockchip_efuse { int (*get_leakage)(int ch); + int (*get_temp)(int ch); int efuse_version; int process_version; }; static struct rockchip_efuse efuse; + + +/****************************secure reg access****************************/ + +#define SEC_REG_RW_SHT (0x0) +#define SEC_REG_RD (0x0) +#define SEC_REG_WR (0x1) + +#define SEC_REG_BITS_SHT (0x1) +#define SEC_REG_32 (0x0) +#define SEC_REG_64 (0x2) + +#define SEC_REG_RD_32 (SEC_REG_RD | SEC_REG_32) +#define SEC_REG_RD_64 (SEC_REG_RD | SEC_REG_64) +#define SEC_REG_WR_32 (SEC_REG_WR | SEC_REG_32) +#define SEC_REG_WR_64 (SEC_REG_WR | SEC_REG_64) + +#define PSCI_OS_ACCESS_REG (0xba00ffb0) +#define EFUSE_BASE 0xffb00000 +/* + * arg2: rd/wr control, bit[0] 0-rd 1-rt, bit[1] 0-32bit, 1-64bit + * arg1: base addr + * arg0: read or write val + * function_id: return fail/succes + */ +noinline int __invoke_reg_access_fn_hvc(u64 function_id, u64 arg0, u64 arg1, u64 arg2, u64 *val) +{ + asm volatile( + __asmeq("%0", "x0") + __asmeq("%1", "x1") + __asmeq("%2", "x2") + __asmeq("%3", "x3") + "hvc #0\n" + : "+r" (function_id), "+r" (arg0) + : "r" (arg1), "r" (arg2)); + + if(!(arg2 & SEC_REG_WR)) + *val = arg0; + + return function_id; +} + +noinline int __invoke_reg_wr_fn_smc(u64 function_id, u64 arg0, u64 arg1, u64 arg2) +{ + asm volatile( + __asmeq("%0", "x0") + __asmeq("%1", "x1") + __asmeq("%2", "x2") + __asmeq("%3", "x3") + "smc #0\n" + : "+r" (function_id) ,"+r" (arg0) + : "r" (arg1), "r" (arg2)); + + return function_id; +} + +noinline int __invoke_reg_rd_fn_smc(u64 function_id, u64 arg0, u64 arg1, + u64 arg2, u64 *val) +{ + asm volatile( + __asmeq("%0", "x0") + __asmeq("%1", "x1") + __asmeq("%2", "x2") + __asmeq("%3", "x3") + "smc #0\n" + : "+r" (function_id) ,"+r" (arg0) + : "r" (arg1), "r" (arg2)); + + *val = arg0; + + return function_id; +} + +int (*invoke_regs_wr_fn)(u64, u64 , u64, u64) = __invoke_reg_wr_fn_smc; + +int (*invoke_regs_rd_fn)(u64, u64 , u64, u64, u64 *) = __invoke_reg_rd_fn_smc; + + +int secure_regs_rd(u64 addr_phy) +{ + u64 val_64; + u32 val; + int ret; + ret = invoke_regs_rd_fn(PSCI_OS_ACCESS_REG, 0, addr_phy, SEC_REG_RD_32, &val_64); + val = val_64; + return val; +} + +int secure_regs_wr_32(u64 addr_phy, u32 val) +{ + u64 val_64 = val; + return invoke_regs_wr_fn(PSCI_OS_ACCESS_REG, val_64, addr_phy, SEC_REG_WR_32); +} + +static int __init rk3368_efuse_readregs(u32 addr, u32 length, u8 *buf) +{ + int ret = length; + if (!length) + return 0; + if (!buf) + return 0; + + secure_regs_wr_32(EFUSE_BASE+REG_EFUSE_CTRL , EFUSE_CSB); + secure_regs_wr_32(EFUSE_BASE+REG_EFUSE_CTRL , EFUSE_LOAD | EFUSE_PGENB); + udelay(2); + do { + secure_regs_wr_32(EFUSE_BASE+REG_EFUSE_CTRL , + secure_regs_rd(EFUSE_BASE+REG_EFUSE_CTRL) & + (~(EFUSE_A_MASK << EFUSE_A_SHIFT))); + secure_regs_wr_32(EFUSE_BASE+REG_EFUSE_CTRL, + secure_regs_rd(EFUSE_BASE+REG_EFUSE_CTRL) | + ((addr & EFUSE_A_MASK) << EFUSE_A_SHIFT)); + udelay(2); + secure_regs_wr_32(EFUSE_BASE+REG_EFUSE_CTRL , + secure_regs_rd(EFUSE_BASE+REG_EFUSE_CTRL) | EFUSE_STROBE); + udelay(2); + *buf = secure_regs_rd(EFUSE_BASE+REG_EFUSE_DOUT); + secure_regs_wr_32(EFUSE_BASE+REG_EFUSE_CTRL , + secure_regs_rd(EFUSE_BASE+REG_EFUSE_CTRL) & (~EFUSE_STROBE)); + udelay(2); + buf++; + addr++; + } while (--length); + udelay(2); + secure_regs_wr_32(EFUSE_BASE+REG_EFUSE_CTRL , + secure_regs_rd(EFUSE_BASE+REG_EFUSE_CTRL) | EFUSE_CSB); + udelay(1); + + return ret; +} + static int __init rk3288_efuse_readregs(u32 addr, u32 length, u8 *buf) { int ret = length; @@ -150,15 +303,36 @@ int rockchip_process_version(void) int rockchip_get_leakage(int ch) { - if (efuse.get_leakage) - return efuse.get_leakage(ch); + int ret = 0; + if (efuse.get_leakage){ + return efuse.get_leakage(ch); + }else{ + ret = rk3368_efuse_readregs(0,32,efuse_buf); + if (ret == 32){ + return efuse_buf[23+ch]; + } + } + return 0; +} +int rockchip_get_temp(int ch) +{ + int ret = 0; + int temp = 0; + ret = rk3368_efuse_readregs(0,32,efuse_buf); + if (ret == 32){ + temp = efuse_buf[31+ch]; + if(efuse_buf[31+ch] & 0x80) + { + temp = -(efuse_buf[31+ch] & 0x7f); + } + return temp; + } return 0; } void __init rockchip_efuse_init(void) { int ret; - if (cpu_is_rk3288()) { ret = rk3288_efuse_readregs(0, 32, efuse_buf); if (ret == 32) { diff --git a/arch/arm/mach-rockchip/efuse.h b/arch/arm/mach-rockchip/efuse.h index 4caf61c52875..3480ddbc28ea 100644 --- a/arch/arm/mach-rockchip/efuse.h +++ b/arch/arm/mach-rockchip/efuse.h @@ -28,4 +28,5 @@ int rockchip_efuse_version(void); int rockchip_process_version(void); int rockchip_get_leakage(int ch); +int rockchip_get_temp(int ch); #endif -- 2.34.1