Commit a3e552b53fb85abce33a8e00bc430d014d7ee733

Authored by Michal Simek
1 parent b6039aad2d

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>

Showing 5 changed files with 25 additions and 118 deletions Side-by-side Diff

arch/arm/mach-zynqmp/Makefile
... ... @@ -8,8 +8,4 @@
8 8 obj-$(CONFIG_MP) += mp.o
9 9 obj-$(CONFIG_SPL_BUILD) += spl.o handoff.o
10 10 obj-$(CONFIG_ZYNQMP_PSU_INIT_ENABLED) += psu_spl_init.o
11   -
12   -ifneq ($(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE),"")
13   -obj-$(CONFIG_SPL_BUILD) += pmu_ipc.o
14   -endif
arch/arm/mach-zynqmp/include/mach/sys_proto.h
... ... @@ -60,7 +60,5 @@
60 60 void tcm_init(u8 mode);
61 61 #endif
62 62  
63   -void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size);
64   -
65 63 #endif /* _ASM_ARCH_SYS_PROTO_H */
arch/arm/mach-zynqmp/pmu_ipc.c
1   -// SPDX-License-Identifier: GPL-2.0+
2   -/*
3   - * Inter-Processor Communication with the Platform Management Unit (PMU)
4   - * firmware.
5   - *
6   - * (C) Copyright 2019 Luca Ceresoli
7   - * Luca Ceresoli <luca@lucaceresoli.net>
8   - */
9   -
10   -#include <common.h>
11   -#include <asm/io.h>
12   -#include <asm/arch/sys_proto.h>
13   -
14   -/* IPI bitmasks, register base and register offsets */
15   -#define IPI_BIT_MASK_APU 0x00001
16   -#define IPI_BIT_MASK_PMU0 0x10000
17   -#define IPI_REG_BASE_APU 0xFF300000
18   -#define IPI_REG_BASE_PMU0 0xFF330000
19   -#define IPI_REG_OFFSET_TRIG 0x00
20   -#define IPI_REG_OFFSET_OBR 0x04
21   -
22   -/* IPI mailbox buffer offsets */
23   -#define IPI_BUF_BASE_APU 0xFF990400
24   -#define IPI_BUF_OFFSET_TARGET_PMU 0x1C0
25   -#define IPI_BUF_OFFSET_REQ 0x00
26   -#define IPI_BUF_OFFSET_RESP 0x20
27   -
28   -#define PMUFW_PAYLOAD_ARG_CNT 8
29   -
30   -/* PMUFW commands */
31   -#define PMUFW_CMD_SET_CONFIGURATION 2
32   -
33   -static void pmu_ipc_send_request(const u32 *req, size_t req_len)
34   -{
35   - u32 *mbx = (u32 *)(IPI_BUF_BASE_APU +
36   - IPI_BUF_OFFSET_TARGET_PMU +
37   - IPI_BUF_OFFSET_REQ);
38   - size_t i;
39   -
40   - for (i = 0; i < req_len; i++)
41   - writel(req[i], &mbx[i]);
42   -}
43   -
44   -static void pmu_ipc_read_response(unsigned int *value, size_t count)
45   -{
46   - u32 *mbx = (u32 *)(IPI_BUF_BASE_APU +
47   - IPI_BUF_OFFSET_TARGET_PMU +
48   - IPI_BUF_OFFSET_RESP);
49   - size_t i;
50   -
51   - for (i = 0; i < count; i++)
52   - value[i] = readl(&mbx[i]);
53   -}
54   -
55   -/**
56   - * Send request to PMU and get the response.
57   - *
58   - * @req: Request buffer. Byte 0 is the API ID, other bytes are optional
59   - * parameters.
60   - * @req_len: Request length in number of 32-bit words.
61   - * @res: Response buffer. Byte 0 is the error code, other bytes are
62   - * optional parameters. Optional, if @res_maxlen==0 the parameters
63   - * will not be read.
64   - * @res_maxlen: Space allocated for the response in number of 32-bit words.
65   - *
66   - * @return Error code returned by the PMU (i.e. the first word of the response)
67   - */
68   -static int pmu_ipc_request(const u32 *req, size_t req_len,
69   - u32 *res, size_t res_maxlen)
70   -{
71   - u32 status;
72   -
73   - if (req_len > PMUFW_PAYLOAD_ARG_CNT ||
74   - res_maxlen > PMUFW_PAYLOAD_ARG_CNT)
75   - return -EINVAL;
76   -
77   - pmu_ipc_send_request(req, req_len);
78   -
79   - /* Raise Inter-Processor Interrupt to PMU and wait for response */
80   - writel(IPI_BIT_MASK_PMU0, IPI_REG_BASE_APU + IPI_REG_OFFSET_TRIG);
81   - do {
82   - status = readl(IPI_REG_BASE_APU + IPI_REG_OFFSET_OBR);
83   - } while (status & IPI_BIT_MASK_PMU0);
84   -
85   - pmu_ipc_read_response(res, res_maxlen);
86   -
87   - return 0;
88   -}
89   -
90   -/**
91   - * Send a configuration object to the PMU firmware.
92   - *
93   - * @cfg_obj: Pointer to the configuration object
94   - * @size: Size of @cfg_obj in bytes
95   - */
96   -void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size)
97   -{
98   - const u32 request[] = {
99   - PMUFW_CMD_SET_CONFIGURATION,
100   - (u32)((u64)cfg_obj)
101   - };
102   - u32 response;
103   - int err;
104   -
105   - printf("Loading PMUFW cfg obj (%ld bytes)\n", size);
106   -
107   - err = pmu_ipc_request(request, ARRAY_SIZE(request), &response, 1);
108   - if (err)
109   - panic("Cannot load PMUFW configuration object (%d)\n", err);
110   - if (response != 0)
111   - panic("PMUFW returned 0x%08x status!\n", response);
112   -}
drivers/firmware/firmware-zynqmp.c
... ... @@ -84,6 +84,30 @@
84 84 return pm_api_version;
85 85 };
86 86  
  87 +/**
  88 + * Send a configuration object to the PMU firmware.
  89 + *
  90 + * @cfg_obj: Pointer to the configuration object
  91 + * @size: Size of @cfg_obj in bytes
  92 + */
  93 +void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size)
  94 +{
  95 + const u32 request[] = {
  96 + PM_SET_CONFIGURATION,
  97 + (u32)((u64)cfg_obj)
  98 + };
  99 + u32 response;
  100 + int err;
  101 +
  102 + printf("Loading new PMUFW cfg obj (%ld bytes)\n", size);
  103 +
  104 + err = send_req(request, ARRAY_SIZE(request), &response, 1);
  105 + if (err)
  106 + panic("Cannot load PMUFW configuration object (%d)\n", err);
  107 + if (response != 0)
  108 + panic("PMUFW returned 0x%08x status!\n", response);
  109 +}
  110 +
87 111 static int zynqmp_power_probe(struct udevice *dev)
88 112 {
89 113 int ret = 0;
include/zynqmp_firmware.h
... ... @@ -32,6 +32,7 @@
32 32 #define PMUFW_V1_0 ((1 << ZYNQMP_PM_VERSION_MAJOR_SHIFT) | 0)
33 33  
34 34 unsigned int zynqmp_firmware_version(void);
  35 +void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size);
35 36  
36 37 #endif /* _ZYNQMP_FIRMWARE_H_ */