Commit 866225f394a9b3174d9ea39d2d19ac0d2c07a516
1 parent
0f3604a2b3
Exists in
smarc_8mq_lf_v2020.04
and in
9 other branches
arm64: xilinx: Move firmware functions from platform to driver
versal_pm_request() and invoke_smc() are almost the same. Only one difference is that versal_pm_request is adding PM_SIP_SVC offset to api_id. The patch is moving platform implementation to firmware driver code for synchronization. Signed-off-by: Michal Simek <michal.simek@xilinx.com> Reviewed-by: Luca Ceresoli <luca@lucaceresoli.net>
Showing 7 changed files with 52 additions and 62 deletions Side-by-side Diff
arch/arm/mach-versal/cpu.c
... | ... | @@ -9,7 +9,6 @@ |
9 | 9 | #include <asm/io.h> |
10 | 10 | #include <asm/arch/hardware.h> |
11 | 11 | #include <asm/arch/sys_proto.h> |
12 | -#include <zynqmp_firmware.h> | |
13 | 12 | |
14 | 13 | DECLARE_GLOBAL_DATA_PTR; |
15 | 14 | |
... | ... | @@ -108,29 +107,4 @@ |
108 | 107 | return 0; |
109 | 108 | } |
110 | 109 | #endif |
111 | - | |
112 | -int versal_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2, | |
113 | - u32 arg3, u32 *ret_payload) | |
114 | -{ | |
115 | - struct pt_regs regs; | |
116 | - | |
117 | - if (current_el() == 3) | |
118 | - return 0; | |
119 | - | |
120 | - regs.regs[0] = PM_SIP_SVC | api_id; | |
121 | - regs.regs[1] = ((u64)arg1 << 32) | arg0; | |
122 | - regs.regs[2] = ((u64)arg3 << 32) | arg2; | |
123 | - | |
124 | - smc_call(®s); | |
125 | - | |
126 | - if (ret_payload) { | |
127 | - ret_payload[0] = (u32)regs.regs[0]; | |
128 | - ret_payload[1] = upper_32_bits(regs.regs[0]); | |
129 | - ret_payload[2] = (u32)regs.regs[1]; | |
130 | - ret_payload[3] = upper_32_bits(regs.regs[1]); | |
131 | - ret_payload[4] = (u32)regs.regs[2]; | |
132 | - } | |
133 | - | |
134 | - return regs.regs[0]; | |
135 | -} |
arch/arm/mach-versal/include/mach/sys_proto.h
arch/arm/mach-zynqmp/cpu.c
... | ... | @@ -154,32 +154,6 @@ |
154 | 154 | #define ZYNQMP_MMIO_READ 0xC2000014 |
155 | 155 | #define ZYNQMP_MMIO_WRITE 0xC2000013 |
156 | 156 | |
157 | -int __maybe_unused invoke_smc(u32 pm_api_id, u32 arg0, u32 arg1, u32 arg2, | |
158 | - u32 arg3, u32 *ret_payload) | |
159 | -{ | |
160 | - /* | |
161 | - * Added SIP service call Function Identifier | |
162 | - * Make sure to stay in x0 register | |
163 | - */ | |
164 | - struct pt_regs regs; | |
165 | - | |
166 | - regs.regs[0] = pm_api_id; | |
167 | - regs.regs[1] = ((u64)arg1 << 32) | arg0; | |
168 | - regs.regs[2] = ((u64)arg3 << 32) | arg2; | |
169 | - | |
170 | - smc_call(®s); | |
171 | - | |
172 | - if (ret_payload != NULL) { | |
173 | - ret_payload[0] = (u32)regs.regs[0]; | |
174 | - ret_payload[1] = upper_32_bits(regs.regs[0]); | |
175 | - ret_payload[2] = (u32)regs.regs[1]; | |
176 | - ret_payload[3] = upper_32_bits(regs.regs[1]); | |
177 | - ret_payload[4] = (u32)regs.regs[2]; | |
178 | - } | |
179 | - | |
180 | - return regs.regs[0]; | |
181 | -} | |
182 | - | |
183 | 157 | static int zynqmp_mmio_rawwrite(const u32 address, |
184 | 158 | const u32 mask, |
185 | 159 | const u32 value) |
186 | 160 | |
187 | 161 | |
188 | 162 | |
189 | 163 | |
190 | 164 | |
... | ... | @@ -211,28 +185,34 @@ |
211 | 185 | { |
212 | 186 | if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) |
213 | 187 | return zynqmp_mmio_rawwrite(address, mask, value); |
188 | +#if defined(CONFIG_ZYNQMP_FIRMWARE) | |
214 | 189 | else |
215 | 190 | return invoke_smc(ZYNQMP_MMIO_WRITE, address, mask, |
216 | 191 | value, 0, NULL); |
192 | +#endif | |
217 | 193 | |
218 | 194 | return -EINVAL; |
219 | 195 | } |
220 | 196 | |
221 | 197 | int zynqmp_mmio_read(const u32 address, u32 *value) |
222 | 198 | { |
223 | - u32 ret_payload[PAYLOAD_ARG_CNT]; | |
224 | - u32 ret; | |
199 | + u32 ret = -EINVAL; | |
225 | 200 | |
226 | 201 | if (!value) |
227 | - return -EINVAL; | |
202 | + return ret; | |
228 | 203 | |
229 | 204 | if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) { |
230 | 205 | ret = zynqmp_mmio_rawread(address, value); |
231 | - } else { | |
206 | + } | |
207 | +#if defined(CONFIG_ZYNQMP_FIRMWARE) | |
208 | + else { | |
209 | + u32 ret_payload[PAYLOAD_ARG_CNT]; | |
210 | + | |
232 | 211 | ret = invoke_smc(ZYNQMP_MMIO_READ, address, 0, 0, |
233 | 212 | 0, ret_payload); |
234 | 213 | *value = ret_payload[1]; |
235 | 214 | } |
215 | +#endif | |
236 | 216 | |
237 | 217 | return ret; |
238 | 218 | } |
arch/arm/mach-zynqmp/include/mach/sys_proto.h
... | ... | @@ -50,8 +50,6 @@ |
50 | 50 | |
51 | 51 | int zynqmp_mmio_write(const u32 address, const u32 mask, const u32 value); |
52 | 52 | int zynqmp_mmio_read(const u32 address, u32 *value); |
53 | -int invoke_smc(u32 pm_api_id, u32 arg0, u32 arg1, u32 arg2, u32 arg3, | |
54 | - u32 *ret_payload); | |
55 | 53 | |
56 | 54 | void initialize_tcm(bool mode); |
57 | 55 | void mem_map_fill(void); |
drivers/firmware/firmware-zynqmp.c
... | ... | @@ -7,10 +7,10 @@ |
7 | 7 | |
8 | 8 | #include <common.h> |
9 | 9 | #include <dm.h> |
10 | +#include <zynqmp_firmware.h> | |
10 | 11 | |
11 | 12 | #if defined(CONFIG_ZYNQMP_IPI) |
12 | 13 | #include <mailbox.h> |
13 | -#include <zynqmp_firmware.h> | |
14 | 14 | #include <asm/arch/sys_proto.h> |
15 | 15 | |
16 | 16 | #define PMUFW_PAYLOAD_ARG_CNT 8 |
... | ... | @@ -146,6 +146,42 @@ |
146 | 146 | .probe = zynqmp_power_probe, |
147 | 147 | }; |
148 | 148 | #endif |
149 | + | |
150 | +int __maybe_unused invoke_smc(u32 pm_api_id, u32 arg0, u32 arg1, u32 arg2, | |
151 | + u32 arg3, u32 *ret_payload) | |
152 | +{ | |
153 | + /* | |
154 | + * Added SIP service call Function Identifier | |
155 | + * Make sure to stay in x0 register | |
156 | + */ | |
157 | + struct pt_regs regs; | |
158 | + | |
159 | + if (current_el() == 3) | |
160 | + return 0; | |
161 | + | |
162 | + regs.regs[0] = pm_api_id; | |
163 | + regs.regs[1] = ((u64)arg1 << 32) | arg0; | |
164 | + regs.regs[2] = ((u64)arg3 << 32) | arg2; | |
165 | + | |
166 | + smc_call(®s); | |
167 | + | |
168 | + if (ret_payload) { | |
169 | + ret_payload[0] = (u32)regs.regs[0]; | |
170 | + ret_payload[1] = upper_32_bits(regs.regs[0]); | |
171 | + ret_payload[2] = (u32)regs.regs[1]; | |
172 | + ret_payload[3] = upper_32_bits(regs.regs[1]); | |
173 | + ret_payload[4] = (u32)regs.regs[2]; | |
174 | + } | |
175 | + | |
176 | + return regs.regs[0]; | |
177 | +} | |
178 | + | |
179 | +int __maybe_unused versal_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2, | |
180 | + u32 arg3, u32 *ret_payload) | |
181 | +{ | |
182 | + return invoke_smc(PM_SIP_SVC | api_id, arg0, arg1, arg2, arg3, | |
183 | + ret_payload); | |
184 | +} | |
149 | 185 | |
150 | 186 | static const struct udevice_id zynqmp_firmware_ids[] = { |
151 | 187 | { .compatible = "xlnx,zynqmp-firmware" }, |
drivers/fpga/versalpl.c
include/zynqmp_firmware.h
... | ... | @@ -81,6 +81,10 @@ |
81 | 81 | |
82 | 82 | unsigned int zynqmp_firmware_version(void); |
83 | 83 | void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size); |
84 | +int invoke_smc(u32 pm_api_id, u32 arg0, u32 arg1, u32 arg2, u32 arg3, | |
85 | + u32 *ret_payload); | |
86 | +int versal_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2, | |
87 | + u32 arg3, u32 *ret_payload); | |
84 | 88 | |
85 | 89 | #endif /* _ZYNQMP_FIRMWARE_H_ */ |