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>
This commit is contained in:
Michal Simek 2019-10-04 15:45:29 +02:00
parent 0f3604a2b3
commit 866225f394
7 changed files with 52 additions and 62 deletions

View File

@ -9,7 +9,6 @@
#include <asm/io.h>
#include <asm/arch/hardware.h>
#include <asm/arch/sys_proto.h>
#include <zynqmp_firmware.h>
DECLARE_GLOBAL_DATA_PTR;
@ -108,28 +107,3 @@ int reserve_mmu(void)
return 0;
}
#endif
int versal_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2,
u32 arg3, u32 *ret_payload)
{
struct pt_regs regs;
if (current_el() == 3)
return 0;
regs.regs[0] = PM_SIP_SVC | api_id;
regs.regs[1] = ((u64)arg1 << 32) | arg0;
regs.regs[2] = ((u64)arg3 << 32) | arg2;
smc_call(&regs);
if (ret_payload) {
ret_payload[0] = (u32)regs.regs[0];
ret_payload[1] = upper_32_bits(regs.regs[0]);
ret_payload[2] = (u32)regs.regs[1];
ret_payload[3] = upper_32_bits(regs.regs[1]);
ret_payload[4] = (u32)regs.regs[2];
}
return regs.regs[0];
}

View File

@ -12,6 +12,3 @@ enum {
void tcm_init(u8 mode);
void mem_map_fill(void);
int versal_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2,
u32 arg3, u32 *ret_payload);

View File

@ -154,32 +154,6 @@ unsigned int zynqmp_get_silicon_version(void)
#define ZYNQMP_MMIO_READ 0xC2000014
#define ZYNQMP_MMIO_WRITE 0xC2000013
int __maybe_unused invoke_smc(u32 pm_api_id, u32 arg0, u32 arg1, u32 arg2,
u32 arg3, u32 *ret_payload)
{
/*
* Added SIP service call Function Identifier
* Make sure to stay in x0 register
*/
struct pt_regs regs;
regs.regs[0] = pm_api_id;
regs.regs[1] = ((u64)arg1 << 32) | arg0;
regs.regs[2] = ((u64)arg3 << 32) | arg2;
smc_call(&regs);
if (ret_payload != NULL) {
ret_payload[0] = (u32)regs.regs[0];
ret_payload[1] = upper_32_bits(regs.regs[0]);
ret_payload[2] = (u32)regs.regs[1];
ret_payload[3] = upper_32_bits(regs.regs[1]);
ret_payload[4] = (u32)regs.regs[2];
}
return regs.regs[0];
}
static int zynqmp_mmio_rawwrite(const u32 address,
const u32 mask,
const u32 value)
@ -211,28 +185,34 @@ int zynqmp_mmio_write(const u32 address,
{
if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3)
return zynqmp_mmio_rawwrite(address, mask, value);
#if defined(CONFIG_ZYNQMP_FIRMWARE)
else
return invoke_smc(ZYNQMP_MMIO_WRITE, address, mask,
value, 0, NULL);
#endif
return -EINVAL;
}
int zynqmp_mmio_read(const u32 address, u32 *value)
{
u32 ret_payload[PAYLOAD_ARG_CNT];
u32 ret;
u32 ret = -EINVAL;
if (!value)
return -EINVAL;
return ret;
if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
ret = zynqmp_mmio_rawread(address, value);
} else {
}
#if defined(CONFIG_ZYNQMP_FIRMWARE)
else {
u32 ret_payload[PAYLOAD_ARG_CNT];
ret = invoke_smc(ZYNQMP_MMIO_READ, address, 0, 0,
0, ret_payload);
*value = ret_payload[1];
}
#endif
return ret;
}

View File

@ -50,8 +50,6 @@ void handoff_setup(void);
int zynqmp_mmio_write(const u32 address, const u32 mask, const u32 value);
int zynqmp_mmio_read(const u32 address, u32 *value);
int invoke_smc(u32 pm_api_id, u32 arg0, u32 arg1, u32 arg2, u32 arg3,
u32 *ret_payload);
void initialize_tcm(bool mode);
void mem_map_fill(void);

View File

@ -7,10 +7,10 @@
#include <common.h>
#include <dm.h>
#include <zynqmp_firmware.h>
#if defined(CONFIG_ZYNQMP_IPI)
#include <mailbox.h>
#include <zynqmp_firmware.h>
#include <asm/arch/sys_proto.h>
#define PMUFW_PAYLOAD_ARG_CNT 8
@ -147,6 +147,42 @@ U_BOOT_DRIVER(zynqmp_power) = {
};
#endif
int __maybe_unused invoke_smc(u32 pm_api_id, u32 arg0, u32 arg1, u32 arg2,
u32 arg3, u32 *ret_payload)
{
/*
* Added SIP service call Function Identifier
* Make sure to stay in x0 register
*/
struct pt_regs regs;
if (current_el() == 3)
return 0;
regs.regs[0] = pm_api_id;
regs.regs[1] = ((u64)arg1 << 32) | arg0;
regs.regs[2] = ((u64)arg3 << 32) | arg2;
smc_call(&regs);
if (ret_payload) {
ret_payload[0] = (u32)regs.regs[0];
ret_payload[1] = upper_32_bits(regs.regs[0]);
ret_payload[2] = (u32)regs.regs[1];
ret_payload[3] = upper_32_bits(regs.regs[1]);
ret_payload[4] = (u32)regs.regs[2];
}
return regs.regs[0];
}
int __maybe_unused versal_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2,
u32 arg3, u32 *ret_payload)
{
return invoke_smc(PM_SIP_SVC | api_id, arg0, arg1, arg2, arg3,
ret_payload);
}
static const struct udevice_id zynqmp_firmware_ids[] = {
{ .compatible = "xlnx,zynqmp-firmware" },
{ .compatible = "xlnx,versal-firmware"},

View File

@ -8,6 +8,7 @@
#include <asm/arch/sys_proto.h>
#include <memalign.h>
#include <versalpl.h>
#include <zynqmp_firmware.h>
static ulong versal_align_dma_buffer(ulong *buf, u32 len)
{

View File

@ -81,5 +81,9 @@ enum pm_api_id {
unsigned int zynqmp_firmware_version(void);
void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size);
int invoke_smc(u32 pm_api_id, u32 arg0, u32 arg1, u32 arg2, u32 arg3,
u32 *ret_payload);
int versal_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2,
u32 arg3, u32 *ret_payload);
#endif /* _ZYNQMP_FIRMWARE_H_ */