mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-04-02 04:21:32 +00:00
arm64: zynqmp: Use mailbox driver for PMUFW config loading
With new mailbox driver PMUFW configuration object can be loaded via the same interface and there is no need to have pmu_ipc.c completely. Signed-off-by: Michal Simek <michal.simek@xilinx.com> Reviewed-by: Luca Ceresoli <luca@lucaceresoli.net>
This commit is contained in:
parent
b6039aad2d
commit
a3e552b53f
5 changed files with 25 additions and 118 deletions
|
@ -8,7 +8,3 @@ obj-y += cpu.o
|
||||||
obj-$(CONFIG_MP) += mp.o
|
obj-$(CONFIG_MP) += mp.o
|
||||||
obj-$(CONFIG_SPL_BUILD) += spl.o handoff.o
|
obj-$(CONFIG_SPL_BUILD) += spl.o handoff.o
|
||||||
obj-$(CONFIG_ZYNQMP_PSU_INIT_ENABLED) += psu_spl_init.o
|
obj-$(CONFIG_ZYNQMP_PSU_INIT_ENABLED) += psu_spl_init.o
|
||||||
|
|
||||||
ifneq ($(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE),"")
|
|
||||||
obj-$(CONFIG_SPL_BUILD) += pmu_ipc.o
|
|
||||||
endif
|
|
||||||
|
|
|
@ -60,6 +60,4 @@ int chip_id(unsigned char id);
|
||||||
void tcm_init(u8 mode);
|
void tcm_init(u8 mode);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size);
|
|
||||||
|
|
||||||
#endif /* _ASM_ARCH_SYS_PROTO_H */
|
#endif /* _ASM_ARCH_SYS_PROTO_H */
|
||||||
|
|
|
@ -1,112 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0+
|
|
||||||
/*
|
|
||||||
* Inter-Processor Communication with the Platform Management Unit (PMU)
|
|
||||||
* firmware.
|
|
||||||
*
|
|
||||||
* (C) Copyright 2019 Luca Ceresoli
|
|
||||||
* Luca Ceresoli <luca@lucaceresoli.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <common.h>
|
|
||||||
#include <asm/io.h>
|
|
||||||
#include <asm/arch/sys_proto.h>
|
|
||||||
|
|
||||||
/* IPI bitmasks, register base and register offsets */
|
|
||||||
#define IPI_BIT_MASK_APU 0x00001
|
|
||||||
#define IPI_BIT_MASK_PMU0 0x10000
|
|
||||||
#define IPI_REG_BASE_APU 0xFF300000
|
|
||||||
#define IPI_REG_BASE_PMU0 0xFF330000
|
|
||||||
#define IPI_REG_OFFSET_TRIG 0x00
|
|
||||||
#define IPI_REG_OFFSET_OBR 0x04
|
|
||||||
|
|
||||||
/* IPI mailbox buffer offsets */
|
|
||||||
#define IPI_BUF_BASE_APU 0xFF990400
|
|
||||||
#define IPI_BUF_OFFSET_TARGET_PMU 0x1C0
|
|
||||||
#define IPI_BUF_OFFSET_REQ 0x00
|
|
||||||
#define IPI_BUF_OFFSET_RESP 0x20
|
|
||||||
|
|
||||||
#define PMUFW_PAYLOAD_ARG_CNT 8
|
|
||||||
|
|
||||||
/* PMUFW commands */
|
|
||||||
#define PMUFW_CMD_SET_CONFIGURATION 2
|
|
||||||
|
|
||||||
static void pmu_ipc_send_request(const u32 *req, size_t req_len)
|
|
||||||
{
|
|
||||||
u32 *mbx = (u32 *)(IPI_BUF_BASE_APU +
|
|
||||||
IPI_BUF_OFFSET_TARGET_PMU +
|
|
||||||
IPI_BUF_OFFSET_REQ);
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < req_len; i++)
|
|
||||||
writel(req[i], &mbx[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pmu_ipc_read_response(unsigned int *value, size_t count)
|
|
||||||
{
|
|
||||||
u32 *mbx = (u32 *)(IPI_BUF_BASE_APU +
|
|
||||||
IPI_BUF_OFFSET_TARGET_PMU +
|
|
||||||
IPI_BUF_OFFSET_RESP);
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
value[i] = readl(&mbx[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send request to PMU and get the response.
|
|
||||||
*
|
|
||||||
* @req: Request buffer. Byte 0 is the API ID, other bytes are optional
|
|
||||||
* parameters.
|
|
||||||
* @req_len: Request length in number of 32-bit words.
|
|
||||||
* @res: Response buffer. Byte 0 is the error code, other bytes are
|
|
||||||
* optional parameters. Optional, if @res_maxlen==0 the parameters
|
|
||||||
* will not be read.
|
|
||||||
* @res_maxlen: Space allocated for the response in number of 32-bit words.
|
|
||||||
*
|
|
||||||
* @return Error code returned by the PMU (i.e. the first word of the response)
|
|
||||||
*/
|
|
||||||
static int pmu_ipc_request(const u32 *req, size_t req_len,
|
|
||||||
u32 *res, size_t res_maxlen)
|
|
||||||
{
|
|
||||||
u32 status;
|
|
||||||
|
|
||||||
if (req_len > PMUFW_PAYLOAD_ARG_CNT ||
|
|
||||||
res_maxlen > PMUFW_PAYLOAD_ARG_CNT)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
pmu_ipc_send_request(req, req_len);
|
|
||||||
|
|
||||||
/* Raise Inter-Processor Interrupt to PMU and wait for response */
|
|
||||||
writel(IPI_BIT_MASK_PMU0, IPI_REG_BASE_APU + IPI_REG_OFFSET_TRIG);
|
|
||||||
do {
|
|
||||||
status = readl(IPI_REG_BASE_APU + IPI_REG_OFFSET_OBR);
|
|
||||||
} while (status & IPI_BIT_MASK_PMU0);
|
|
||||||
|
|
||||||
pmu_ipc_read_response(res, res_maxlen);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a configuration object to the PMU firmware.
|
|
||||||
*
|
|
||||||
* @cfg_obj: Pointer to the configuration object
|
|
||||||
* @size: Size of @cfg_obj in bytes
|
|
||||||
*/
|
|
||||||
void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size)
|
|
||||||
{
|
|
||||||
const u32 request[] = {
|
|
||||||
PMUFW_CMD_SET_CONFIGURATION,
|
|
||||||
(u32)((u64)cfg_obj)
|
|
||||||
};
|
|
||||||
u32 response;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
printf("Loading PMUFW cfg obj (%ld bytes)\n", size);
|
|
||||||
|
|
||||||
err = pmu_ipc_request(request, ARRAY_SIZE(request), &response, 1);
|
|
||||||
if (err)
|
|
||||||
panic("Cannot load PMUFW configuration object (%d)\n", err);
|
|
||||||
if (response != 0)
|
|
||||||
panic("PMUFW returned 0x%08x status!\n", response);
|
|
||||||
}
|
|
|
@ -84,6 +84,30 @@ unsigned int zynqmp_firmware_version(void)
|
||||||
return pm_api_version;
|
return pm_api_version;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a configuration object to the PMU firmware.
|
||||||
|
*
|
||||||
|
* @cfg_obj: Pointer to the configuration object
|
||||||
|
* @size: Size of @cfg_obj in bytes
|
||||||
|
*/
|
||||||
|
void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size)
|
||||||
|
{
|
||||||
|
const u32 request[] = {
|
||||||
|
PM_SET_CONFIGURATION,
|
||||||
|
(u32)((u64)cfg_obj)
|
||||||
|
};
|
||||||
|
u32 response;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
printf("Loading new PMUFW cfg obj (%ld bytes)\n", size);
|
||||||
|
|
||||||
|
err = send_req(request, ARRAY_SIZE(request), &response, 1);
|
||||||
|
if (err)
|
||||||
|
panic("Cannot load PMUFW configuration object (%d)\n", err);
|
||||||
|
if (response != 0)
|
||||||
|
panic("PMUFW returned 0x%08x status!\n", response);
|
||||||
|
}
|
||||||
|
|
||||||
static int zynqmp_power_probe(struct udevice *dev)
|
static int zynqmp_power_probe(struct udevice *dev)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
|
@ -32,5 +32,6 @@ enum pm_api_id {
|
||||||
#define PMUFW_V1_0 ((1 << ZYNQMP_PM_VERSION_MAJOR_SHIFT) | 0)
|
#define PMUFW_V1_0 ((1 << ZYNQMP_PM_VERSION_MAJOR_SHIFT) | 0)
|
||||||
|
|
||||||
unsigned int zynqmp_firmware_version(void);
|
unsigned int zynqmp_firmware_version(void);
|
||||||
|
void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size);
|
||||||
|
|
||||||
#endif /* _ZYNQMP_FIRMWARE_H_ */
|
#endif /* _ZYNQMP_FIRMWARE_H_ */
|
||||||
|
|
Loading…
Add table
Reference in a new issue