rk3368: add rockchip_get_temp function and
authorguoyi <gy@rock-chips.com>
Fri, 27 Mar 2015 03:07:02 +0000 (11:07 +0800)
committerguoyi <gy@rock-chips.com>
Fri, 27 Mar 2015 03:09:24 +0000 (11:09 +0800)
rockchip_get_leakage support for 3368

arch/arm/mach-rockchip/efuse.c
arch/arm/mach-rockchip/efuse.h

index dbb2325ebbd35eddb27495ed89ac4546f6314c27..f48b1c2e677c3db706057675c071e39a66a2791a 100644 (file)
 #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)
 
@@ -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) {
index 4caf61c5287545c3da6af0553d1a21a1de295399..3480ddbc28eadc122826b9b79b9e0cf839bf1b87 100644 (file)
@@ -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