firmware: rockchip: sip: add secure register read/write
[firefly-linux-kernel-4.4.55.git] / drivers / firmware / rockchip_sip.c
1 /*
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.
5  *
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.
10  *
11  * Copyright (C) 2016, Fuzhou Rockchip Electronics Co., Ltd
12  */
13
14 #include <linux/arm-smccc.h>
15 #include <linux/io.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>
20
21 #ifdef CONFIG_64BIT
22 #define PSCI_FN_NATIVE(version, name)   PSCI_##version##_FN64_##name
23 #else
24 #define PSCI_FN_NATIVE(version, name)   PSCI_##version##_FN_##name
25 #endif
26
27 #define SIZE_PAGE(n)    ((n) << 12)
28
29 static struct arm_smccc_res __invoke_sip_fn_smc(unsigned long function_id,
30                                                 unsigned long arg0,
31                                                 unsigned long arg1,
32                                                 unsigned long arg2)
33 {
34         struct arm_smccc_res res;
35
36         arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
37         return res;
38 }
39
40 struct arm_smccc_res sip_smc_ddr_cfg(u32 arg0, u32 arg1,
41                                      u32 arg2)
42 {
43         return __invoke_sip_fn_smc(SIP_DDR_CFG32, arg0, arg1, arg2);
44 }
45
46 struct arm_smccc_res sip_smc_get_atf_version(void)
47 {
48         return __invoke_sip_fn_smc(SIP_ATF_VERSION32, 0, 0, 0);
49 }
50
51 struct arm_smccc_res sip_smc_get_sip_version(void)
52 {
53         return __invoke_sip_fn_smc(SIP_SIP_VERSION32, 0, 0, 0);
54 }
55
56 int sip_smc_set_suspend_mode(u32 ctrl,
57                              u32 config1,
58                              u32 config2)
59 {
60         struct arm_smccc_res res;
61
62         res = __invoke_sip_fn_smc(SIP_SUSPEND_MODE32, ctrl,
63                                   config1, config2);
64
65         return res.a0;
66 }
67
68 int rk_psci_virtual_poweroff(void)
69 {
70         struct arm_smccc_res res;
71
72         res = __invoke_sip_fn_smc(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND),
73                                   0, 0, 0);
74         return res.a0;
75 }
76
77 u32 sip_smc_secure_reg_read(u32 addr_phy)
78 {
79         struct arm_smccc_res res;
80
81         res = __invoke_sip_fn_smc(SIP_ACCESS_REG, 0, addr_phy, SECURE_REG_RD);
82         if (res.a0)
83                 pr_err("%s error: %d, addr phy: 0x%x\n",
84                        __func__, (int)res.a0, addr_phy);
85
86         return res.a1;
87 }
88
89 int sip_smc_secure_reg_write(u32 addr_phy, u32 val)
90 {
91         struct arm_smccc_res res;
92
93         res = __invoke_sip_fn_smc(SIP_ACCESS_REG, val, addr_phy, SECURE_REG_WR);
94         if (res.a0)
95                 pr_err("%s error: %d, addr phy: 0x%x\n",
96                        __func__, (int)res.a0, addr_phy);
97
98         return res.a0;
99 }
100
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;
106
107 u32 rockchip_psci_smc_get_tf_ver(void)
108 {
109         struct arm_smccc_res res;
110
111         arm_smccc_smc(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
112         return 0x00010005;
113 }
114
115 void psci_fiq_debugger_uart_irq_tf_cb(u64 sp_el1, u64 offset)
116 {
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);
120 }
121
122 void psci_fiq_debugger_uart_irq_tf_init(u32 irq_id, void *callback)
123 {
124         struct arm_smccc_res sip_smmc;
125
126         psci_fiq_debugger_uart_irq_tf = callback;
127         sip_smmc = __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, irq_id,
128                                        (u64)psci_fiq_debugger_uart_irq_tf_cb,
129                                        UARTDBG_CFG_INIT);
130         ft_fiq_mem_phy = sip_smmc.a0;
131         ft_fiq_mem_base = ioremap(ft_fiq_mem_phy, 8 * 1024);
132         fig_init_flag = 1;
133 }
134
135 void psci_enable_fiq(void)
136 {
137         int irq_flag;
138         int cpu_id;
139
140         if (fig_init_flag != 1)
141                 return;
142         irq_flag = *((char *)(ft_fiq_mem_base) + 8 * 1024 - 0x04);
143
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);
147 }
148
149 u32 psci_fiq_debugger_switch_cpu(u32 cpu)
150 {
151         struct arm_smccc_res sip_smmc;
152
153                 sip_smmc = __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64,
154                                                cpu_logical_map(cpu),
155                                                0, UARTDBG_CFG_OSHDL_CPUSW);
156         return sip_smmc.a0;
157 }
158
159 void psci_fiq_debugger_enable_debug(bool val)
160 {
161         if (val)
162                 __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, 0,
163                                     0, UARTDBG_CFG_OSHDL_DEBUG_ENABLE);
164         else
165                 __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, 0,
166                                     0, UARTDBG_CFG_OSHDL_DEBUG_DISABLE);
167 }
168
169 int psci_fiq_debugger_set_print_port(u32 port, u32 baudrate)
170 {
171         struct arm_smccc_res res;
172
173         res = __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, port, baudrate,
174                                   UARTDBG_CFG_PRINT_PORT);
175         return res.a0;
176 }
177
178 struct arm_smccc_res sip_smc_get_share_mem_page(u32 page_num,
179                                                 share_page_type_t page_type)
180 {
181         struct arm_smccc_res res;
182         unsigned long share_mem_phy;
183
184         res = __invoke_sip_fn_smc(SIP_SHARE_MEM32, page_num, page_type, 0);
185         if (res.a0)
186                 goto error;
187
188         share_mem_phy = res.a1;
189         res.a1 = (unsigned long)ioremap(share_mem_phy, SIZE_PAGE(page_num));
190
191 error:
192         return res;
193 }
194
195 struct arm_smccc_res sip_smc_get_call_count(void)
196 {
197         return __invoke_sip_fn_smc(SIP_SVC_CALL_COUNT, 0, 0, 0);
198 }