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 #define ARM_PSCI_0_2_CPU_OFF ARM_PSCI_0_2_FN_CPU_OFF 17 #else 18 #define ARM_PSCI_1_0_SYSTEM_SUSPEND ARM_PSCI_1_0_FN_SYSTEM_SUSPEND 19 #define ARM_PSCI_0_2_CPU_ON ARM_PSCI_0_2_FN_CPU_ON 20 #define ARM_PSCI_0_2_CPU_OFF ARM_PSCI_0_2_FN_CPU_OFF 21 #endif 22 23 #define SIZE_PAGE(n) ((n) << 12) 24 25 static struct arm_smccc_res __invoke_sip_fn_smc(unsigned long function_id, 26 unsigned long arg0, 27 unsigned long arg1, 28 unsigned long arg2) 29 { 30 struct arm_smccc_res res; 31 32 arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res); 33 return res; 34 } 35 36 int psci_cpu_on(unsigned long cpuid, unsigned long entry_point) 37 { 38 struct arm_smccc_res res; 39 40 res = __invoke_sip_fn_smc(ARM_PSCI_0_2_CPU_ON, cpuid, entry_point, 0); 41 42 return res.a0; 43 } 44 45 int psci_cpu_off(uint32_t state) 46 { 47 struct arm_smccc_res res; 48 49 res = __invoke_sip_fn_smc(ARM_PSCI_0_2_CPU_OFF, state, 0, 0); 50 51 return res.a0; 52 } 53 54 #ifdef CONFIG_ARM_CPU_SUSPEND 55 int psci_system_suspend(unsigned long unused) 56 { 57 struct arm_smccc_res res; 58 59 res = __invoke_sip_fn_smc(ARM_PSCI_1_0_SYSTEM_SUSPEND, 60 virt_to_phys(cpu_resume), 0, 0); 61 return res.a0; 62 } 63 #endif 64 65 int sip_smc_set_suspend_mode(unsigned long ctrl, 66 unsigned long config1, 67 unsigned long config2) 68 { 69 struct arm_smccc_res res; 70 71 res = __invoke_sip_fn_smc(SIP_SUSPEND_MODE, ctrl, config1, config2); 72 return res.a0; 73 } 74 75 int sip_smc_remotectl_config(unsigned long func, unsigned long data) 76 { 77 struct arm_smccc_res res; 78 79 res = __invoke_sip_fn_smc(SIP_REMOTECTL_CFG, func, data, 0); 80 81 return res.a0; 82 } 83 84 int sip_smc_access_mem_os_reg(unsigned long func, unsigned long id, 85 unsigned long *val) 86 { 87 struct arm_smccc_res res; 88 89 if (val == NULL) 90 return SIP_RET_INVALID_PARAMS; 91 92 res = __invoke_sip_fn_smc(SIP_ACCESS_MEM_OS_REG, func, id, *val); 93 94 if (func == RK_MEM_OS_REG_READ) 95 *val = res.a1; 96 97 return res.a0; 98 } 99 100 int sip_smc_amp_cfg(unsigned long func, unsigned long arg0, unsigned long arg1, 101 unsigned long arg2) 102 { 103 struct arm_smccc_res res; 104 105 arm_smccc_smc(SIP_AMP_CFG, func, arg0, arg1, arg2, 0, 0, 0, &res); 106 return res.a0; 107 } 108 109 struct arm_smccc_res sip_smc_dram(unsigned long arg0, 110 unsigned long arg1, 111 unsigned long arg2) 112 { 113 return __invoke_sip_fn_smc(SIP_DRAM_CONFIG, arg0, arg1, arg2); 114 } 115 116 struct arm_smccc_res sip_smc_request_share_mem(unsigned long page_num, 117 share_page_type_t page_type) 118 { 119 struct arm_smccc_res res; 120 unsigned long share_mem_phy; 121 122 res = __invoke_sip_fn_smc(SIP_SHARE_MEM, page_num, page_type, 0); 123 if (IS_SIP_ERROR(res.a0)) 124 goto error; 125 126 share_mem_phy = res.a1; 127 res.a1 = (unsigned long)ioremap(share_mem_phy, SIZE_PAGE(page_num)); 128 129 error: 130 return res; 131 } 132 133 struct arm_smccc_res sip_smc_secure_reg_read(unsigned long addr_phy) 134 { 135 struct arm_smccc_res res; 136 137 res = __invoke_sip_fn_smc(SIP_ACCESS_REG, 0, addr_phy, SECURE_REG_RD); 138 return res; 139 } 140 141 int sip_smc_secure_reg_write(unsigned long addr_phy, unsigned long val) 142 { 143 struct arm_smccc_res res; 144 145 res = __invoke_sip_fn_smc(SIP_ACCESS_REG, val, addr_phy, SECURE_REG_WR); 146 return res.a0; 147 } 148 149 int sip_smc_hdcp_config(unsigned long func, unsigned long arg1, unsigned long arg2) 150 { 151 struct arm_smccc_res res; 152 153 res = __invoke_sip_fn_smc(SIP_HDCP_CONFIG, func, arg1, arg2); 154 return res.a0; 155 } 156 157 struct arm_smccc_res sip_smc_get_sip_version(void) 158 { 159 return __invoke_sip_fn_smc(SIP_SIP_VERSION, 0, 0, 0); 160 } 161 162 /* 163 * OP-TEE works both for kernel 3.10 and 4.4, and these two kernels have 164 * different sip implement that 3.10 uses SIP_IMPLEMENT_V1 and 4.4 uses 165 * SIP_IMPLEMENT_V2. So we should tell OP-TEE the current rockchip sip 166 * version(default SIP_IMPLEMENT_V1) before use. 167 */ 168 int sip_smc_set_sip_version(unsigned long version) 169 { 170 struct arm_smccc_res res; 171 172 res = __invoke_sip_fn_smc(SIP_SIP_VERSION, version, SECURE_REG_WR, 0); 173 if (IS_SIP_ERROR(res.a0)) { 174 printf("%s: set rockchip sip version v%ld failed\n", 175 __func__, version); 176 return res.a0; 177 } 178 179 return 0; 180 } 181 182 int sip_smc_mcu_config(unsigned long mcu_id, unsigned long func, unsigned long arg2) 183 { 184 struct arm_smccc_res res; 185 186 res = __invoke_sip_fn_smc(SIP_MCU_CFG, mcu_id, func, arg2); 187 return res.a0; 188 } 189