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