#include <linux/delay.h>
#include <linux/rockchip/cpu.h>
#include <linux/rockchip/iomap.h>
+
+#include <linux/cpuidle.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/smp.h>
+#include <linux/slab.h>
+#include <linux/reboot.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <uapi/linux/psci.h>
+
+#include <asm/compiler.h>
+#include <asm/cpu_ops.h>
+#include <asm/errno.h>
+#include <asm/psci.h>
+#include <asm/smp_plat.h>
+#include <asm/suspend.h>
+#include <asm/system_misc.h>
+
#ifdef CONFIG_ARM
#include <asm/system_info.h>
#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)
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;
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) {