1 /* 2 * (C) Copyright 2017 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <asm/arch/rockchip_smccc.h> 8 #include <asm/io.h> 9 #include <asm/psci.h> 10 #include <asm/suspend.h> 11 #include <linux/io.h> 12 13 #ifdef CONFIG_ARM64 14 #define ARM_PSCI_1_0_SYSTEM_SUSPEND ARM_PSCI_1_0_FN64_SYSTEM_SUSPEND 15 #define ARM_PSCI_0_2_CPU_ON ARM_PSCI_0_2_FN64_CPU_ON 16 #else 17 #define ARM_PSCI_1_0_SYSTEM_SUSPEND ARM_PSCI_1_0_FN_SYSTEM_SUSPEND 18 #define ARM_PSCI_0_2_CPU_ON ARM_PSCI_0_2_FN_CPU_ON 19 #endif 20 21 #define SIZE_PAGE(n) ((n) << 12) 22 23 static struct arm_smccc_res __invoke_sip_fn_smc(unsigned long function_id, 24 unsigned long arg0, 25 unsigned long arg1, 26 unsigned long arg2) 27 { 28 struct arm_smccc_res res; 29 30 arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res); 31 return res; 32 } 33 34 int psci_cpu_on(unsigned long cpuid, unsigned long entry_point) 35 { 36 struct arm_smccc_res res; 37 38 res = __invoke_sip_fn_smc(ARM_PSCI_0_2_CPU_ON, cpuid, entry_point, 0); 39 40 return res.a0; 41 } 42 43 #ifdef CONFIG_ARM_CPU_SUSPEND 44 int psci_system_suspend(unsigned long unused) 45 { 46 struct arm_smccc_res res; 47 48 res = __invoke_sip_fn_smc(ARM_PSCI_1_0_SYSTEM_SUSPEND, 49 virt_to_phys(cpu_resume), 0, 0); 50 return res.a0; 51 } 52 #endif 53 54 int sip_smc_set_suspend_mode(unsigned long ctrl, 55 unsigned long config1, 56 unsigned long config2) 57 { 58 struct arm_smccc_res res; 59 60 res = __invoke_sip_fn_smc(SIP_SUSPEND_MODE, ctrl, config1, config2); 61 return res.a0; 62 } 63 64 int sip_smc_remotectl_config(unsigned long func, unsigned long data) 65 { 66 struct arm_smccc_res res; 67 68 res = __invoke_sip_fn_smc(SIP_REMOTECTL_CFG, func, data, 0); 69 70 return res.a0; 71 } 72 73 int sip_smc_amp_cfg(unsigned long func, unsigned long arg0, unsigned long arg1, 74 unsigned long arg2) 75 { 76 struct arm_smccc_res res; 77 78 arm_smccc_smc(SIP_AMP_CFG, func, arg0, arg1, arg2, 0, 0, 0, &res); 79 return res.a0; 80 } 81 82 struct arm_smccc_res sip_smc_dram(unsigned long arg0, 83 unsigned long arg1, 84 unsigned long arg2) 85 { 86 return __invoke_sip_fn_smc(SIP_DRAM_CONFIG, arg0, arg1, arg2); 87 } 88 89 struct arm_smccc_res sip_smc_request_share_mem(unsigned long page_num, 90 share_page_type_t page_type) 91 { 92 struct arm_smccc_res res; 93 unsigned long share_mem_phy; 94 95 res = __invoke_sip_fn_smc(SIP_SHARE_MEM, page_num, page_type, 0); 96 if (IS_SIP_ERROR(res.a0)) 97 goto error; 98 99 share_mem_phy = res.a1; 100 res.a1 = (unsigned long)ioremap(share_mem_phy, SIZE_PAGE(page_num)); 101 102 error: 103 return res; 104 } 105 106 struct arm_smccc_res sip_smc_secure_reg_read(unsigned long addr_phy) 107 { 108 struct arm_smccc_res res; 109 110 res = __invoke_sip_fn_smc(SIP_ACCESS_REG, 0, addr_phy, SECURE_REG_RD); 111 return res; 112 } 113 114 int sip_smc_secure_reg_write(unsigned long addr_phy, unsigned long val) 115 { 116 struct arm_smccc_res res; 117 118 res = __invoke_sip_fn_smc(SIP_ACCESS_REG, val, addr_phy, SECURE_REG_WR); 119 return res.a0; 120 } 121 122 int sip_smc_hdcp_config(unsigned long func, unsigned long arg1, unsigned long arg2) 123 { 124 struct arm_smccc_res res; 125 126 res = __invoke_sip_fn_smc(SIP_HDCP_CONFIG, func, arg1, arg2); 127 return res.a0; 128 } 129 130 struct arm_smccc_res sip_smc_get_sip_version(void) 131 { 132 return __invoke_sip_fn_smc(SIP_SIP_VERSION, 0, 0, 0); 133 } 134 135 /* 136 * OP-TEE works both for kernel 3.10 and 4.4, and these two kernels have 137 * different sip implement that 3.10 uses SIP_IMPLEMENT_V1 and 4.4 uses 138 * SIP_IMPLEMENT_V2. So we should tell OP-TEE the current rockchip sip 139 * version(default SIP_IMPLEMENT_V1) before use. 140 */ 141 int sip_smc_set_sip_version(unsigned long version) 142 { 143 struct arm_smccc_res res; 144 145 res = __invoke_sip_fn_smc(SIP_SIP_VERSION, version, SECURE_REG_WR, 0); 146 if (IS_SIP_ERROR(res.a0)) { 147 printf("%s: set rockchip sip version v%ld failed\n", 148 __func__, version); 149 return res.a0; 150 } 151 152 return 0; 153 } 154