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
__invoke_sip_fn_smc(unsigned long function_id,unsigned long arg0,unsigned long arg1,unsigned long arg2)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
psci_cpu_on(unsigned long cpuid,unsigned long entry_point)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
psci_system_suspend(unsigned long unused)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
sip_smc_set_suspend_mode(unsigned long ctrl,unsigned long config1,unsigned long config2)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
sip_smc_remotectl_config(unsigned long func,unsigned long data)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
sip_smc_amp_cfg(unsigned long func,unsigned long arg0,unsigned long arg1,unsigned long arg2)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
sip_smc_dram(unsigned long arg0,unsigned long arg1,unsigned long arg2)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
sip_smc_request_share_mem(unsigned long page_num,share_page_type_t page_type)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
sip_smc_secure_reg_read(unsigned long addr_phy)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
sip_smc_secure_reg_write(unsigned long addr_phy,unsigned long val)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
sip_smc_hdcp_config(unsigned long func,unsigned long arg1,unsigned long arg2)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
sip_smc_get_sip_version(void)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 */
sip_smc_set_sip_version(unsigned long version)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
sip_smc_mcu_config(unsigned long mcu_id,unsigned long func,unsigned long arg2)155 int sip_smc_mcu_config(unsigned long mcu_id, unsigned long func, unsigned long arg2)
156 {
157 struct arm_smccc_res res;
158
159 res = __invoke_sip_fn_smc(SIP_MCU_CFG, mcu_id, func, arg2);
160 return res.a0;
161 }
162