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_amp_cfg(unsigned long func, unsigned long arg0, unsigned long arg1, 65 unsigned long arg2) 66 { 67 struct arm_smccc_res res; 68 69 arm_smccc_smc(SIP_AMP_CFG, func, arg0, arg1, arg2, 0, 0, 0, &res); 70 return res.a0; 71 } 72 73 struct arm_smccc_res sip_smc_dram(unsigned long arg0, 74 unsigned long arg1, 75 unsigned long arg2) 76 { 77 return __invoke_sip_fn_smc(SIP_DRAM_CONFIG, arg0, arg1, arg2); 78 } 79 80 struct arm_smccc_res sip_smc_request_share_mem(unsigned long page_num, 81 share_page_type_t page_type) 82 { 83 struct arm_smccc_res res; 84 unsigned long share_mem_phy; 85 86 res = __invoke_sip_fn_smc(SIP_SHARE_MEM, page_num, page_type, 0); 87 if (IS_SIP_ERROR(res.a0)) 88 goto error; 89 90 share_mem_phy = res.a1; 91 res.a1 = (unsigned long)ioremap(share_mem_phy, SIZE_PAGE(page_num)); 92 93 error: 94 return res; 95 } 96 97 struct arm_smccc_res sip_smc_secure_reg_read(unsigned long addr_phy) 98 { 99 struct arm_smccc_res res; 100 101 res = __invoke_sip_fn_smc(SIP_ACCESS_REG, 0, addr_phy, SECURE_REG_RD); 102 return res; 103 } 104 105 int sip_smc_secure_reg_write(unsigned long addr_phy, unsigned long val) 106 { 107 struct arm_smccc_res res; 108 109 res = __invoke_sip_fn_smc(SIP_ACCESS_REG, val, addr_phy, SECURE_REG_WR); 110 return res.a0; 111 } 112 113 int sip_smc_hdcp_config(unsigned long func, unsigned long arg1, unsigned long arg2) 114 { 115 struct arm_smccc_res res; 116 117 res = __invoke_sip_fn_smc(SIP_HDCP_CONFIG, func, arg1, arg2); 118 return res.a0; 119 } 120 121 struct arm_smccc_res sip_smc_get_sip_version(void) 122 { 123 return __invoke_sip_fn_smc(SIP_SIP_VERSION, 0, 0, 0); 124 } 125 126 /* 127 * OP-TEE works both for kernel 3.10 and 4.4, and these two kernels have 128 * different sip implement that 3.10 uses SIP_IMPLEMENT_V1 and 4.4 uses 129 * SIP_IMPLEMENT_V2. So we should tell OP-TEE the current rockchip sip 130 * version(default SIP_IMPLEMENT_V1) before use. 131 */ 132 int sip_smc_set_sip_version(unsigned long version) 133 { 134 struct arm_smccc_res res; 135 136 res = __invoke_sip_fn_smc(SIP_SIP_VERSION, version, SECURE_REG_WR, 0); 137 if (IS_SIP_ERROR(res.a0)) { 138 printf("%s: set rockchip sip version v%ld failed\n", 139 __func__, version); 140 return res.a0; 141 } 142 143 return 0; 144 } 145