xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/rockchip_smccc.c (revision a47be44dca4e168635e6f4dd8302a2cac0aa3495)
1f270a3f8SJoseph Chen /*
2f270a3f8SJoseph Chen  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
3f270a3f8SJoseph Chen  *
4f270a3f8SJoseph Chen  * SPDX-License-Identifier:     GPL-2.0+
5f270a3f8SJoseph Chen  */
6f270a3f8SJoseph Chen 
7f270a3f8SJoseph Chen #include <asm/arch/rockchip_smccc.h>
8f270a3f8SJoseph Chen #include <asm/io.h>
9f270a3f8SJoseph Chen #include <asm/psci.h>
10f270a3f8SJoseph Chen #include <asm/suspend.h>
115f048e57SJoseph Chen #include <linux/io.h>
12f270a3f8SJoseph Chen 
13f270a3f8SJoseph Chen #ifdef CONFIG_ARM64
14f270a3f8SJoseph Chen #define ARM_PSCI_1_0_SYSTEM_SUSPEND	ARM_PSCI_1_0_FN64_SYSTEM_SUSPEND
15e2bc9ab6SLin Huang #define ARM_PSCI_0_2_CPU_ON		ARM_PSCI_0_2_FN64_CPU_ON
162003c631SJoseph Chen #define ARM_PSCI_0_2_CPU_OFF		ARM_PSCI_0_2_FN_CPU_OFF
17f270a3f8SJoseph Chen #else
18f270a3f8SJoseph Chen #define ARM_PSCI_1_0_SYSTEM_SUSPEND	ARM_PSCI_1_0_FN_SYSTEM_SUSPEND
19e2bc9ab6SLin Huang #define ARM_PSCI_0_2_CPU_ON		ARM_PSCI_0_2_FN_CPU_ON
202003c631SJoseph Chen #define ARM_PSCI_0_2_CPU_OFF		ARM_PSCI_0_2_FN_CPU_OFF
21f270a3f8SJoseph Chen #endif
22f270a3f8SJoseph Chen 
235f048e57SJoseph Chen #define SIZE_PAGE(n)	((n) << 12)
24f270a3f8SJoseph Chen 
__invoke_sip_fn_smc(unsigned long function_id,unsigned long arg0,unsigned long arg1,unsigned long arg2)25f270a3f8SJoseph Chen static struct arm_smccc_res __invoke_sip_fn_smc(unsigned long function_id,
26f270a3f8SJoseph Chen 						unsigned long arg0,
27f270a3f8SJoseph Chen 						unsigned long arg1,
28f270a3f8SJoseph Chen 						unsigned long arg2)
29f270a3f8SJoseph Chen {
30f270a3f8SJoseph Chen 	struct arm_smccc_res res;
31f270a3f8SJoseph Chen 
32f270a3f8SJoseph Chen 	arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
33f270a3f8SJoseph Chen 	return res;
34f270a3f8SJoseph Chen }
35f270a3f8SJoseph Chen 
psci_cpu_on(unsigned long cpuid,unsigned long entry_point)36e2bc9ab6SLin Huang int psci_cpu_on(unsigned long cpuid, unsigned long entry_point)
37e2bc9ab6SLin Huang {
38e2bc9ab6SLin Huang 	struct arm_smccc_res res;
39e2bc9ab6SLin Huang 
40e2bc9ab6SLin Huang 	res = __invoke_sip_fn_smc(ARM_PSCI_0_2_CPU_ON, cpuid, entry_point, 0);
41e2bc9ab6SLin Huang 
42e2bc9ab6SLin Huang 	return res.a0;
43e2bc9ab6SLin Huang }
44e2bc9ab6SLin Huang 
psci_cpu_off(uint32_t state)452003c631SJoseph Chen int psci_cpu_off(uint32_t state)
462003c631SJoseph Chen {
472003c631SJoseph Chen 	struct arm_smccc_res res;
482003c631SJoseph Chen 
492003c631SJoseph Chen 	res = __invoke_sip_fn_smc(ARM_PSCI_0_2_CPU_OFF, state, 0, 0);
502003c631SJoseph Chen 
512003c631SJoseph Chen 	return res.a0;
522003c631SJoseph Chen }
532003c631SJoseph Chen 
54164b2a33SJoseph Chen #ifdef CONFIG_ARM_CPU_SUSPEND
psci_system_suspend(unsigned long unused)55f270a3f8SJoseph Chen int psci_system_suspend(unsigned long unused)
56f270a3f8SJoseph Chen {
57f270a3f8SJoseph Chen 	struct arm_smccc_res res;
58f270a3f8SJoseph Chen 
59f270a3f8SJoseph Chen 	res = __invoke_sip_fn_smc(ARM_PSCI_1_0_SYSTEM_SUSPEND,
60f270a3f8SJoseph Chen 				  virt_to_phys(cpu_resume), 0, 0);
61f270a3f8SJoseph Chen 	return res.a0;
62f270a3f8SJoseph Chen }
63164b2a33SJoseph Chen #endif
64f270a3f8SJoseph Chen 
sip_smc_set_suspend_mode(unsigned long ctrl,unsigned long config1,unsigned long config2)65f270a3f8SJoseph Chen int sip_smc_set_suspend_mode(unsigned long ctrl,
66f270a3f8SJoseph Chen 			     unsigned long config1,
67f270a3f8SJoseph Chen 			     unsigned long config2)
68f270a3f8SJoseph Chen {
69f270a3f8SJoseph Chen 	struct arm_smccc_res res;
70f270a3f8SJoseph Chen 
71f270a3f8SJoseph Chen 	res = __invoke_sip_fn_smc(SIP_SUSPEND_MODE, ctrl, config1, config2);
72f270a3f8SJoseph Chen 	return res.a0;
73f270a3f8SJoseph Chen }
745f048e57SJoseph Chen 
sip_smc_remotectl_config(unsigned long func,unsigned long data)756ea21705SWeixin Zhou int sip_smc_remotectl_config(unsigned long func, unsigned long data)
766ea21705SWeixin Zhou {
776ea21705SWeixin Zhou 	struct arm_smccc_res res;
786ea21705SWeixin Zhou 
796ea21705SWeixin Zhou 	res = __invoke_sip_fn_smc(SIP_REMOTECTL_CFG, func, data, 0);
806ea21705SWeixin Zhou 
816ea21705SWeixin Zhou 	return res.a0;
826ea21705SWeixin Zhou }
836ea21705SWeixin Zhou 
sip_smc_access_mem_os_reg(unsigned long func,unsigned long id,unsigned long * val)84*a47be44dSXiaoDong Huang int sip_smc_access_mem_os_reg(unsigned long func, unsigned long id,
85*a47be44dSXiaoDong Huang 			      unsigned long *val)
86*a47be44dSXiaoDong Huang {
87*a47be44dSXiaoDong Huang 	struct arm_smccc_res res;
88*a47be44dSXiaoDong Huang 
89*a47be44dSXiaoDong Huang 	if (val == NULL)
90*a47be44dSXiaoDong Huang 		return SIP_RET_INVALID_PARAMS;
91*a47be44dSXiaoDong Huang 
92*a47be44dSXiaoDong Huang 	res = __invoke_sip_fn_smc(SIP_ACCESS_MEM_OS_REG, func, id, *val);
93*a47be44dSXiaoDong Huang 
94*a47be44dSXiaoDong Huang 	if (func == RK_MEM_OS_REG_READ)
95*a47be44dSXiaoDong Huang 		*val = res.a1;
96*a47be44dSXiaoDong Huang 
97*a47be44dSXiaoDong Huang 	return res.a0;
98*a47be44dSXiaoDong Huang }
99*a47be44dSXiaoDong Huang 
sip_smc_amp_cfg(unsigned long func,unsigned long arg0,unsigned long arg1,unsigned long arg2)1005a7f594fSJoseph Chen int sip_smc_amp_cfg(unsigned long func, unsigned long arg0, unsigned long arg1,
1015a7f594fSJoseph Chen 		    unsigned long arg2)
102c3e08fa0SJoseph Chen {
103c3e08fa0SJoseph Chen 	struct arm_smccc_res res;
104c3e08fa0SJoseph Chen 
1055a7f594fSJoseph Chen 	arm_smccc_smc(SIP_AMP_CFG, func, arg0, arg1, arg2, 0, 0, 0, &res);
106c3e08fa0SJoseph Chen 	return res.a0;
107c3e08fa0SJoseph Chen }
108c3e08fa0SJoseph Chen 
sip_smc_dram(unsigned long arg0,unsigned long arg1,unsigned long arg2)1095f048e57SJoseph Chen struct arm_smccc_res sip_smc_dram(unsigned long arg0,
1105f048e57SJoseph Chen 				  unsigned long arg1,
1115f048e57SJoseph Chen 				  unsigned long arg2)
1125f048e57SJoseph Chen {
1135f048e57SJoseph Chen 	return __invoke_sip_fn_smc(SIP_DRAM_CONFIG, arg0, arg1, arg2);
1145f048e57SJoseph Chen }
1155f048e57SJoseph Chen 
sip_smc_request_share_mem(unsigned long page_num,share_page_type_t page_type)1165f048e57SJoseph Chen struct arm_smccc_res sip_smc_request_share_mem(unsigned long page_num,
1175f048e57SJoseph Chen 					       share_page_type_t page_type)
1185f048e57SJoseph Chen {
1195f048e57SJoseph Chen 	struct arm_smccc_res res;
1205f048e57SJoseph Chen 	unsigned long share_mem_phy;
1215f048e57SJoseph Chen 
1225f048e57SJoseph Chen 	res = __invoke_sip_fn_smc(SIP_SHARE_MEM, page_num, page_type, 0);
1235f048e57SJoseph Chen 	if (IS_SIP_ERROR(res.a0))
1245f048e57SJoseph Chen 		goto error;
1255f048e57SJoseph Chen 
1265f048e57SJoseph Chen 	share_mem_phy = res.a1;
1275f048e57SJoseph Chen 	res.a1 = (unsigned long)ioremap(share_mem_phy, SIZE_PAGE(page_num));
1285f048e57SJoseph Chen 
1295f048e57SJoseph Chen error:
1305f048e57SJoseph Chen 	return res;
1315f048e57SJoseph Chen }
1325f048e57SJoseph Chen 
sip_smc_secure_reg_read(unsigned long addr_phy)133ac374906SJoseph Chen struct arm_smccc_res sip_smc_secure_reg_read(unsigned long addr_phy)
134ac374906SJoseph Chen {
135ac374906SJoseph Chen 	struct arm_smccc_res res;
136ac374906SJoseph Chen 
137ac374906SJoseph Chen 	res = __invoke_sip_fn_smc(SIP_ACCESS_REG, 0, addr_phy, SECURE_REG_RD);
138ac374906SJoseph Chen 	return res;
139ac374906SJoseph Chen }
140ac374906SJoseph Chen 
sip_smc_secure_reg_write(unsigned long addr_phy,unsigned long val)141ac374906SJoseph Chen int sip_smc_secure_reg_write(unsigned long addr_phy, unsigned long val)
142ac374906SJoseph Chen {
143ac374906SJoseph Chen 	struct arm_smccc_res res;
144ac374906SJoseph Chen 
145ac374906SJoseph Chen 	res = __invoke_sip_fn_smc(SIP_ACCESS_REG, val, addr_phy, SECURE_REG_WR);
146ac374906SJoseph Chen 	return res.a0;
147ac374906SJoseph Chen }
148ac374906SJoseph Chen 
sip_smc_hdcp_config(unsigned long func,unsigned long arg1,unsigned long arg2)149b4fd97a6SJoseph Chen int sip_smc_hdcp_config(unsigned long func, unsigned long arg1, unsigned long arg2)
150b4fd97a6SJoseph Chen {
151b4fd97a6SJoseph Chen 	struct arm_smccc_res res;
152b4fd97a6SJoseph Chen 
153b4fd97a6SJoseph Chen 	res = __invoke_sip_fn_smc(SIP_HDCP_CONFIG, func, arg1, arg2);
154b4fd97a6SJoseph Chen 	return res.a0;
155b4fd97a6SJoseph Chen }
156b4fd97a6SJoseph Chen 
sip_smc_get_sip_version(void)1575f048e57SJoseph Chen struct arm_smccc_res sip_smc_get_sip_version(void)
1585f048e57SJoseph Chen {
1595f048e57SJoseph Chen 	return __invoke_sip_fn_smc(SIP_SIP_VERSION, 0, 0, 0);
1605f048e57SJoseph Chen }
1615f048e57SJoseph Chen 
1625f048e57SJoseph Chen /*
1635f048e57SJoseph Chen  * OP-TEE works both for kernel 3.10 and 4.4, and these two kernels have
1645f048e57SJoseph Chen  * different sip implement that 3.10 uses SIP_IMPLEMENT_V1 and 4.4 uses
1655f048e57SJoseph Chen  * SIP_IMPLEMENT_V2. So we should tell OP-TEE the current rockchip sip
1665f048e57SJoseph Chen  * version(default SIP_IMPLEMENT_V1) before use.
1675f048e57SJoseph Chen  */
sip_smc_set_sip_version(unsigned long version)1685f048e57SJoseph Chen int sip_smc_set_sip_version(unsigned long version)
1695f048e57SJoseph Chen {
1705f048e57SJoseph Chen 	struct arm_smccc_res res;
1715f048e57SJoseph Chen 
1725f048e57SJoseph Chen 	res = __invoke_sip_fn_smc(SIP_SIP_VERSION, version, SECURE_REG_WR, 0);
1735f048e57SJoseph Chen 	if (IS_SIP_ERROR(res.a0)) {
1745f048e57SJoseph Chen 		printf("%s: set rockchip sip version v%ld failed\n",
1755f048e57SJoseph Chen 		       __func__, version);
1765f048e57SJoseph Chen 		return res.a0;
1775f048e57SJoseph Chen 	}
1785f048e57SJoseph Chen 
1795f048e57SJoseph Chen 	return 0;
1805f048e57SJoseph Chen }
181de205739Sshengfei Xu 
sip_smc_mcu_config(unsigned long mcu_id,unsigned long func,unsigned long arg2)182de205739Sshengfei Xu int sip_smc_mcu_config(unsigned long mcu_id, unsigned long func, unsigned long arg2)
183de205739Sshengfei Xu {
184de205739Sshengfei Xu 	struct arm_smccc_res res;
185de205739Sshengfei Xu 
186de205739Sshengfei Xu 	res = __invoke_sip_fn_smc(SIP_MCU_CFG, mcu_id, func, arg2);
187de205739Sshengfei Xu 	return res.a0;
188de205739Sshengfei Xu }
189