2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
11 * Copyright (C) 2016, Fuzhou Rockchip Electronics Co., Ltd
14 #include <linux/arm-smccc.h>
16 #include <linux/rockchip/rockchip_sip.h>
17 #include <asm/cputype.h>
18 #include <asm/smp_plat.h>
19 #include <uapi/linux/psci.h>
22 #define PSCI_FN_NATIVE(version, name) PSCI_##version##_FN64_##name
24 #define PSCI_FN_NATIVE(version, name) PSCI_##version##_FN_##name
27 #define SIZE_PAGE(n) ((n) << 12)
29 static struct arm_smccc_res __invoke_sip_fn_smc(unsigned long function_id,
34 struct arm_smccc_res res;
36 arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
40 struct arm_smccc_res sip_smc_ddr_cfg(u32 arg0, u32 arg1,
43 return __invoke_sip_fn_smc(SIP_DDR_CFG32, arg0, arg1, arg2);
46 struct arm_smccc_res sip_smc_get_atf_version(void)
48 return __invoke_sip_fn_smc(SIP_ATF_VERSION32, 0, 0, 0);
51 struct arm_smccc_res sip_smc_get_sip_version(void)
53 return __invoke_sip_fn_smc(SIP_SIP_VERSION32, 0, 0, 0);
56 int sip_smc_set_suspend_mode(u32 ctrl,
60 struct arm_smccc_res res;
62 res = __invoke_sip_fn_smc(SIP_SUSPEND_MODE32, ctrl,
68 int rk_psci_virtual_poweroff(void)
70 struct arm_smccc_res res;
72 res = __invoke_sip_fn_smc(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND),
77 u32 sip_smc_secure_reg_read(u32 addr_phy)
79 struct arm_smccc_res res;
81 res = __invoke_sip_fn_smc(SIP_ACCESS_REG, 0, addr_phy, SECURE_REG_RD);
83 pr_err("%s error: %d, addr phy: 0x%x\n",
84 __func__, (int)res.a0, addr_phy);
89 int sip_smc_secure_reg_write(u32 addr_phy, u32 val)
91 struct arm_smccc_res res;
93 res = __invoke_sip_fn_smc(SIP_ACCESS_REG, val, addr_phy, SECURE_REG_WR);
95 pr_err("%s error: %d, addr phy: 0x%x\n",
96 __func__, (int)res.a0, addr_phy);
101 /************************** fiq debugger **************************************/
102 static u64 ft_fiq_mem_phy;
103 static void __iomem *ft_fiq_mem_base;
104 static void (*psci_fiq_debugger_uart_irq_tf)(void *reg_base, u64 sp_el1);
105 static u32 fig_init_flag;
107 u32 rockchip_psci_smc_get_tf_ver(void)
109 struct arm_smccc_res res;
111 arm_smccc_smc(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
115 void psci_fiq_debugger_uart_irq_tf_cb(u64 sp_el1, u64 offset)
117 psci_fiq_debugger_uart_irq_tf((char *)ft_fiq_mem_base + offset, sp_el1);
118 __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, 0, 0,
119 UARTDBG_CFG_OSHDL_TO_OS);
122 void psci_fiq_debugger_uart_irq_tf_init(u32 irq_id, void *callback)
124 struct arm_smccc_res sip_smmc;
126 psci_fiq_debugger_uart_irq_tf = callback;
127 sip_smmc = __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, irq_id,
128 (unsigned long)psci_fiq_debugger_uart_irq_tf_cb,
130 ft_fiq_mem_phy = sip_smmc.a0;
131 ft_fiq_mem_base = ioremap(ft_fiq_mem_phy, 8 * 1024);
135 void psci_enable_fiq(void)
140 if (fig_init_flag != 1)
142 irq_flag = *((char *)(ft_fiq_mem_base) + 8 * 1024 - 0x04);
144 cpu_id = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
145 if ((irq_flag == 0xAA) && (cpu_id == 0))
146 __invoke_sip_fn_smc(RK_SIP_ENABLE_FIQ, 0, 0, 0);
149 u32 psci_fiq_debugger_switch_cpu(u32 cpu)
151 struct arm_smccc_res sip_smmc;
153 sip_smmc = __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64,
154 cpu_logical_map(cpu),
155 0, UARTDBG_CFG_OSHDL_CPUSW);
159 void psci_fiq_debugger_enable_debug(bool val)
162 __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, 0,
163 0, UARTDBG_CFG_OSHDL_DEBUG_ENABLE);
165 __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, 0,
166 0, UARTDBG_CFG_OSHDL_DEBUG_DISABLE);
169 int psci_fiq_debugger_set_print_port(u32 port, u32 baudrate)
171 struct arm_smccc_res res;
173 res = __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, port, baudrate,
174 UARTDBG_CFG_PRINT_PORT);
178 struct arm_smccc_res sip_smc_get_share_mem_page(u32 page_num,
179 share_page_type_t page_type)
181 struct arm_smccc_res res;
182 unsigned long share_mem_phy;
184 res = __invoke_sip_fn_smc(SIP_SHARE_MEM32, page_num, page_type, 0);
188 share_mem_phy = res.a1;
189 res.a1 = (unsigned long)ioremap(share_mem_phy, SIZE_PAGE(page_num));
195 struct arm_smccc_res sip_smc_get_call_count(void)
197 return __invoke_sip_fn_smc(SIP_SVC_CALL_COUNT, 0, 0, 0);