From a3e552b53fb85abce33a8e00bc430d014d7ee733 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 27 Sep 2019 14:20:00 +0200 Subject: [PATCH] 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 Reviewed-by: Luca Ceresoli --- arch/arm/mach-zynqmp/Makefile | 4 - arch/arm/mach-zynqmp/include/mach/sys_proto.h | 2 - arch/arm/mach-zynqmp/pmu_ipc.c | 112 -------------------------- drivers/firmware/firmware-zynqmp.c | 24 ++++++ include/zynqmp_firmware.h | 1 + 5 files changed, 25 insertions(+), 118 deletions(-) delete mode 100644 arch/arm/mach-zynqmp/pmu_ipc.c diff --git a/arch/arm/mach-zynqmp/Makefile b/arch/arm/mach-zynqmp/Makefile index f3765e4..8a3b074 100644 --- a/arch/arm/mach-zynqmp/Makefile +++ b/arch/arm/mach-zynqmp/Makefile @@ -8,7 +8,3 @@ obj-y += cpu.o obj-$(CONFIG_MP) += mp.o obj-$(CONFIG_SPL_BUILD) += spl.o handoff.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 diff --git a/arch/arm/mach-zynqmp/include/mach/sys_proto.h b/arch/arm/mach-zynqmp/include/mach/sys_proto.h index 27603a6..69e729f 100644 --- a/arch/arm/mach-zynqmp/include/mach/sys_proto.h +++ b/arch/arm/mach-zynqmp/include/mach/sys_proto.h @@ -60,6 +60,4 @@ int chip_id(unsigned char id); void tcm_init(u8 mode); #endif -void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size); - #endif /* _ASM_ARCH_SYS_PROTO_H */ diff --git a/arch/arm/mach-zynqmp/pmu_ipc.c b/arch/arm/mach-zynqmp/pmu_ipc.c deleted file mode 100644 index d8858ea..0000000 --- a/arch/arm/mach-zynqmp/pmu_ipc.c +++ /dev/null @@ -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 - */ - -#include -#include -#include - -/* 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); -} diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index 304398f..15e82ac 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -84,6 +84,30 @@ unsigned int zynqmp_firmware_version(void) 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) { int ret = 0; diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h index cebac74..a20cbcd 100644 --- a/include/zynqmp_firmware.h +++ b/include/zynqmp_firmware.h @@ -32,5 +32,6 @@ enum pm_api_id { #define PMUFW_V1_0 ((1 << ZYNQMP_PM_VERSION_MAJOR_SHIFT) | 0) unsigned int zynqmp_firmware_version(void); +void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size); #endif /* _ZYNQMP_FIRMWARE_H_ */ -- 2.7.4