ARM: rockchip: psci support arch32 and arch64 smc call
authorJianhong Chen <chenjh@rock-chips.com>
Tue, 27 Oct 2015 08:25:11 +0000 (16:25 +0800)
committerJianhong Chen <chenjh@rock-chips.com>
Wed, 28 Oct 2015 07:06:53 +0000 (15:06 +0800)
Change-Id: I736c6c15cbb41d52aa9ef1e98cb9ebdd6ac9ebfc
Signed-off-by: Jianhong Chen <chenjh@rock-chips.com>
arch/arm/mach-rockchip/Makefile
arch/arm/mach-rockchip/psci.c
include/linux/rockchip/psci.h

index c175b1da10c236725526c3c841a631e0b63a486c..d8a0484b97aa8edfb7f15f6795271f4a50fb402c 100755 (executable)
@@ -6,6 +6,7 @@ obj-y += rk3126b.o
 obj-y += rk3188.o
 obj-y += rk3288.o
 obj-y += rk3228.o
+obj-$(CONFIG_ARM_PSCI) += psci.o
 ifneq ($(CONFIG_ARM_TRUSTZONE),y)
 obj-y += ddr_freq.o
 endif
index 66d4905e093040b27f3b6380e212bf0f6be1c225..82293468e3c9041e11303d1d2b7bf47cd27f9fd5 100644 (file)
 #include <linux/rockchip/psci.h>
 #include <asm/compiler.h>
 #include <asm/smp_plat.h>
+#ifdef CONFIG_ARM
+#include <asm/opcodes-sec.h>
+#endif
 
-static u32 reg_rd_fn_smc(u64 function_id, u64 arg0, u64 arg1, u64 arg2,
-                        u64 *val)
+/*
+ * SMC32 id call made from arch32 or arch64
+ */
+static u32 reg_rd_fn_smc(u32 function_id, u32 arg0, u32 arg1,
+                        u32 arg2, u32 *val)
+{
+       asm volatile(
+#ifdef CONFIG_ARM
+                       __asmeq("%0", "r0")
+                       __asmeq("%1", "r1")
+                       __asmeq("%2", "r2")
+                       __asmeq("%3", "r3")
+                       __SMC(0)
+#else
+                       __asmeq("%w0", "w0")
+                       __asmeq("%w1", "w1")
+                       __asmeq("%w2", "w2")
+                       __asmeq("%w3", "w3")
+                       "smc    #0\n"
+#endif
+               : "+r" (function_id), "+r" (arg0)
+               : "r" (arg1), "r" (arg2));
+
+
+               if (val)
+                       *val = arg0;
+
+       return function_id;
+}
+
+/*
+ * SMC32 id call made from arch32 or arch64
+ */
+static u32 reg_wr_fn_smc(u32 function_id, u32 arg0,
+                        u32 arg1, u32 arg2)
+{
+       asm volatile(
+#ifdef CONFIG_ARM
+                       __asmeq("%0", "r0")
+                       __asmeq("%1", "r1")
+                       __asmeq("%2", "r2")
+                       __asmeq("%3", "r3")
+                       __SMC(0)
+#else
+                       __asmeq("%w0", "w0")
+                       __asmeq("%w1", "w1")
+                       __asmeq("%w2", "w2")
+                       __asmeq("%w3", "w3")
+                       "smc    #0\n"
+#endif
+               : "+r" (function_id), "+r" (arg0)
+               : "r" (arg1), "r" (arg2));
+
+       return function_id;
+}
+
+static u32 (*reg_wr_fn)(u32, u32, u32, u32) = reg_wr_fn_smc;
+static u32 (*reg_rd_fn)(u32, u32, u32, u32, u32 *) = reg_rd_fn_smc;
+
+
+#ifdef CONFIG_ARM64
+
+/*
+ * SMC64 id call only made from arch64
+ */
+static u32 reg_rd_fn_smc64(u64 function_id, u64 arg0, u64 arg1, u64 arg2,
+                          u64 *val)
 {
        asm volatile(
                        __asmeq("%0", "x0")
@@ -39,7 +107,10 @@ static u32 reg_rd_fn_smc(u64 function_id, u64 arg0, u64 arg1, u64 arg2,
        return function_id;
 }
 
-static u32 reg_wr_fn_smc(u64 function_id, u64 arg0, u64 arg1, u64 arg2)
+/*
+ * SMC64 id call only made from Arch64
+ */
+static u32 reg_wr_fn_smc64(u64 function_id, u64 arg0, u64 arg1, u64 arg2)
 {
        asm volatile(
                        __asmeq("%0", "x0")
@@ -53,37 +124,59 @@ static u32 reg_wr_fn_smc(u64 function_id, u64 arg0, u64 arg1, u64 arg2)
        return function_id;
 }
 
-static u32 (*reg_wr_fn)(u64, u64, u64, u64) = reg_wr_fn_smc;
-static u32 (*reg_rd_fn)(u64, u64, u64, u64, u64 *) = reg_rd_fn_smc;
+static u32 (*reg_wr_fn64)(u64, u64, u64, u64) = reg_wr_fn_smc64;
+static u32 (*reg_rd_fn64)(u64, u64, u64, u64, u64 *) = reg_rd_fn_smc64;
 
-/*
- * u64 *val: another return value
- */
-u32 rockchip_psci_smc_read(u64 function_id, u64 arg0, u64 arg1, u64 arg2,
-                          u64 *val)
+u32 rockchip_psci_smc_read64(u64 function_id, u64 arg0, u64 arg1, u64 arg2,
+                            u64 *val)
+{
+       return reg_rd_fn64(function_id, arg0, arg1, arg2, val);
+}
+
+u32 rockchip_psci_smc_write64(u64 function_id, u64 arg0, u64 arg1, u64 arg2)
+{
+       return reg_wr_fn64(function_id, arg0, arg1, arg2);
+}
+
+u64 rockchip_secure_reg_read64(u64 addr_phy)
+{
+       u64 val;
+
+       reg_rd_fn64(PSCI_SIP_ACCESS_REG64, 0, addr_phy, SEC_REG_RD, &val);
+
+       return val;
+}
+
+u32 rockchip_secure_reg_write64(u64 addr_phy, u64 val)
+{
+       return reg_wr_fn64(PSCI_SIP_ACCESS_REG64, val, addr_phy, SEC_REG_WR);
+}
+
+#endif /*CONFIG_ARM64*/
+
+u32 rockchip_psci_smc_read(u32 function_id, u32 arg0, u32 arg1, u32 arg2,
+                          u32 *val)
 {
        return reg_rd_fn(function_id, arg0, arg1, arg2, val);
 }
 
-u32 rockchip_psci_smc_write(u64 function_id, u64 arg0, u64 arg1, u64 arg2)
+u32 rockchip_psci_smc_write(u32 function_id, u32 arg0, u32 arg1, u32 arg2)
 {
        return reg_wr_fn(function_id, arg0, arg1, arg2);
 }
 
-u32 rockchip_secure_reg_read32(u64 addr_phy)
+u32 rockchip_secure_reg_read(u32 addr_phy)
 {
-       u64 val = 0;
+       u32 val = 0;
 
-       reg_rd_fn(PSCI_SIP_ACCESS_REG, 0, addr_phy, SEC_REG_RD_32, &val);
+       reg_rd_fn(PSCI_SIP_ACCESS_REG, 0, addr_phy, SEC_REG_RD, &val);
 
        return val;
 }
 
-u32 rockchip_secure_reg_write32(u64 addr_phy, u32 val)
+u32 rockchip_secure_reg_write(u32 addr_phy, u32 val)
 {
-       u64 val_64 = val;
-
-       return reg_wr_fn(PSCI_SIP_ACCESS_REG, val_64, addr_phy, SEC_REG_WR_32);
+       return reg_wr_fn(PSCI_SIP_ACCESS_REG, val, addr_phy, SEC_REG_WR);
 }
 
 /*
@@ -95,6 +188,7 @@ u32 rockchip_psci_smc_get_tf_ver(void)
 }
 
 /*************************** fiq debug *****************************/
+#ifdef CONFIG_ARM64
 static u64 ft_fiq_mem_phy;
 static void __iomem *ft_fiq_mem_base;
 static void (*psci_fiq_debugger_uart_irq_tf)(void *reg_base, u64 sp_el1);
@@ -102,32 +196,31 @@ static void (*psci_fiq_debugger_uart_irq_tf)(void *reg_base, u64 sp_el1);
 void psci_fiq_debugger_uart_irq_tf_cb(u64 sp_el1, u64 offset)
 {
        psci_fiq_debugger_uart_irq_tf((char *)ft_fiq_mem_base + offset, sp_el1);
-
-       reg_wr_fn(PSCI_SIP_UARTDBG_CFG, 0, 0, UARTDBG_CFG_OSHDL_TO_OS);
+       reg_wr_fn64(PSCI_SIP_UARTDBG_CFG64, 0, 0, UARTDBG_CFG_OSHDL_TO_OS);
 }
 
 void psci_fiq_debugger_uart_irq_tf_init(u32 irq_id, void *callback)
 {
        psci_fiq_debugger_uart_irq_tf = callback;
-
-       ft_fiq_mem_phy = reg_wr_fn(PSCI_SIP_UARTDBG_CFG, irq_id,
-                                  (u64)psci_fiq_debugger_uart_irq_tf_cb,
-                                  UARTDBG_CFG_INIT);
+       ft_fiq_mem_phy = reg_wr_fn64(PSCI_SIP_UARTDBG_CFG64, irq_id,
+                                    (u64)psci_fiq_debugger_uart_irq_tf_cb,
+                                    UARTDBG_CFG_INIT);
        ft_fiq_mem_base = ioremap(ft_fiq_mem_phy, 8 * 1024);
 }
 
 u32 psci_fiq_debugger_switch_cpu(u32 cpu)
 {
-       return reg_wr_fn(PSCI_SIP_UARTDBG_CFG, cpu_logical_map(cpu),
-                        0, UARTDBG_CFG_OSHDL_CPUSW);
+       return reg_wr_fn64(PSCI_SIP_UARTDBG_CFG64, cpu_logical_map(cpu),
+                          0, UARTDBG_CFG_OSHDL_CPUSW);
 }
 
 void psci_fiq_debugger_enable_debug(bool val)
 {
        if (val)
-               reg_wr_fn(PSCI_SIP_UARTDBG_CFG, 0,
-                         0, UARTDBG_CFG_OSHDL_DEBUG_ENABLE);
+               reg_wr_fn64(PSCI_SIP_UARTDBG_CFG64, 0,
+                           0, UARTDBG_CFG_OSHDL_DEBUG_ENABLE);
        else
-               reg_wr_fn(PSCI_SIP_UARTDBG_CFG, 0,
-                         0, UARTDBG_CFG_OSHDL_DEBUG_DISABLE);
+               reg_wr_fn64(PSCI_SIP_UARTDBG_CFG64, 0,
+                           0, UARTDBG_CFG_OSHDL_DEBUG_DISABLE);
 }
+#endif
index 93c7c827a69f229d284962f0c0402a44c4aa3f32..5a2111031e52f7ce0a4748138299d04839793e7a 100644 (file)
@@ -1,19 +1,9 @@
 #ifndef __ROCKCHIP_PSCI_H
 #define __ROCKCHIP_PSCI_H
 
-#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)
-
 /*
  * trust firmware verison
  */
  */
 #define PSCI_SIP_RKTF_VER              (0x82000001)
 #define PSCI_SIP_ACCESS_REG            (0x82000002)
+#define PSCI_SIP_ACCESS_REG64          (0xc2000002)
 #define PSCI_SIP_SUSPEND_WR_CTRBITS    (0x82000003)
 #define PSCI_SIP_PENDING_CPUS          (0x82000004)
 #define PSCI_SIP_UARTDBG_CFG           (0x82000005)
+#define PSCI_SIP_UARTDBG_CFG64         (0xc2000005)
 #define PSCI_SIP_EL3FIQ_CFG            (0x82000006)
 
 /*
 /*
  * rockchip psci function call interface
  */
-u32 rockchip_psci_smc_read(u64 function_id, u64 arg0, u64 arg1, u64 arg2,
-                          u64 *val);
-u32 rockchip_psci_smc_write(u64 function_id, u64 arg0, u64 arg1, u64 arg2);
+
+u32 rockchip_psci_smc_read(u32 function_id, u32 arg0, u32 arg1, u32 arg2,
+                          u32 *val);
+u32 rockchip_psci_smc_write(u32 function_id, u32 arg0, u32 arg1, u32 arg2);
 
 u32 rockchip_psci_smc_get_tf_ver(void);
-u32 rockchip_secure_reg_read32(u64 addr_phy);
-u32 rockchip_secure_reg_write32(u64 addr_phy, u32 val);
+u32 rockchip_secure_reg_read(u32 addr_phy);
+u32 rockchip_secure_reg_write(u32 addr_phy, u32 val);
+
+#ifdef CONFIG_ARM64
+u32 rockchip_psci_smc_write64(u64 function_id, u64 arg0, u64 arg1, u64 arg2);
+u32 rockchip_psci_smc_read64(u64 function_id, u64 arg0, u64 arg1, u64 arg2,
+                            u64 *val);
+u64 rockchip_secure_reg_read64(u64 addr_phy);
+u32 rockchip_secure_reg_write64(u64 addr_phy, u64 val);
 
-u32 psci_fiq_debugger_switch_cpu(u32 cpu);
 void psci_fiq_debugger_uart_irq_tf_cb(u64 sp_el1, u64 offset);
+#endif
+
+u32 psci_fiq_debugger_switch_cpu(u32 cpu);
 void psci_fiq_debugger_uart_irq_tf_init(u32 irq_id, void *callback);
 void psci_fiq_debugger_enable_debug(bool val);