blob: fd4804ddf663ca72291a014439ac897f79d09e47 [file] [log] [blame]
Wendy Liangdc1dfe82017-09-13 11:02:42 -07001/*
Jolly Shah31c38422019-01-08 11:10:47 -08002 * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
Wendy Liangdc1dfe82017-09-13 11:02:42 -07003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7/*
8 * Zynq UltraScale+ MPSoC IPI agent registers access management
9 */
10
Wendy Liangdc1dfe82017-09-13 11:02:42 -070011#include <errno.h>
Wendy Liangdc1dfe82017-09-13 11:02:42 -070012#include <string.h>
Antonio Nino Diaz09d40e02018-12-14 00:18:21 +000013
14#include <common/debug.h>
15#include <common/runtime_svc.h>
16#include <lib/bakery_lock.h>
17#include <lib/mmio.h>
Jolly Shah703a5aa2019-01-08 11:25:28 -080018
19#include <ipi.h>
Jolly Shah1611ef22019-01-08 11:21:29 -080020#include <plat_ipi.h>
Jolly Shah31c38422019-01-08 11:10:47 -080021#include <plat_private.h>
Antonio Nino Diaz09d40e02018-12-14 00:18:21 +000022
Wendy Liangdc1dfe82017-09-13 11:02:42 -070023/*********************************************************************
24 * Macros definitions
25 ********************************************************************/
26
27/* IPI registers base address */
28#define IPI_REGS_BASE 0xFF300000U
29
30/* IPI registers offsets macros */
31#define IPI_TRIG_OFFSET 0x00U
32#define IPI_OBR_OFFSET 0x04U
33#define IPI_ISR_OFFSET 0x10U
34#define IPI_IMR_OFFSET 0x14U
35#define IPI_IER_OFFSET 0x18U
36#define IPI_IDR_OFFSET 0x1CU
37
38/* IPI register start offset */
Jolly Shahb8e39f42019-01-08 11:27:36 -080039#define IPI_REG_BASE(I) (ipi_table[(I)].ipi_reg_base)
Wendy Liangdc1dfe82017-09-13 11:02:42 -070040
41/* IPI register bit mask */
Jolly Shahb8e39f42019-01-08 11:27:36 -080042#define IPI_BIT_MASK(I) (ipi_table[(I)].ipi_bit_mask)
Wendy Liangdc1dfe82017-09-13 11:02:42 -070043
44/* IPI secure check */
45#define IPI_SECURE_MASK 0x1U
Jolly Shahb8e39f42019-01-08 11:27:36 -080046#define IPI_IS_SECURE(I) ((ipi_table[(I)].secure_only & \
47 IPI_SECURE_MASK) ? 1 : 0)
48
49/* IPI configuration table */
50const static struct ipi_config *ipi_table;
51
52/* Total number of IPI */
53static uint32_t ipi_total;
Wendy Liangdc1dfe82017-09-13 11:02:42 -070054
Wendy Liangdc1dfe82017-09-13 11:02:42 -070055/* Zynqmp ipi configuration table */
Jolly Shah703a5aa2019-01-08 11:25:28 -080056const static struct ipi_config zynqmp_ipi_table[] = {
Wendy Liangdc1dfe82017-09-13 11:02:42 -070057 /* APU IPI */
58 {
59 .ipi_bit_mask = 0x1,
60 .ipi_reg_base = 0xFF300000,
61 .secure_only = 0,
62 },
63 /* RPU0 IPI */
64 {
65 .ipi_bit_mask = 0x100,
66 .ipi_reg_base = 0xFF310000,
67 .secure_only = 0,
68 },
69 /* RPU1 IPI */
70 {
71 .ipi_bit_mask = 0x200,
72 .ipi_reg_base = 0xFF320000,
73 .secure_only = 0,
74 },
75 /* PMU0 IPI */
76 {
77 .ipi_bit_mask = 0x10000,
78 .ipi_reg_base = 0xFF330000,
79 .secure_only = IPI_SECURE_MASK,
80 },
81 /* PMU1 IPI */
82 {
83 .ipi_bit_mask = 0x20000,
84 .ipi_reg_base = 0xFF331000,
Rajan Vaja85dc2d42018-01-30 03:59:23 -080085 .secure_only = 0,
Wendy Liangdc1dfe82017-09-13 11:02:42 -070086 },
87 /* PMU2 IPI */
88 {
89 .ipi_bit_mask = 0x40000,
90 .ipi_reg_base = 0xFF332000,
91 .secure_only = IPI_SECURE_MASK,
92 },
93 /* PMU3 IPI */
94 {
95 .ipi_bit_mask = 0x80000,
96 .ipi_reg_base = 0xFF333000,
97 .secure_only = IPI_SECURE_MASK,
98 },
99 /* PL0 IPI */
100 {
101 .ipi_bit_mask = 0x1000000,
102 .ipi_reg_base = 0xFF340000,
103 .secure_only = 0,
104 },
105 /* PL1 IPI */
106 {
107 .ipi_bit_mask = 0x2000000,
108 .ipi_reg_base = 0xFF350000,
109 .secure_only = 0,
110 },
111 /* PL2 IPI */
112 {
113 .ipi_bit_mask = 0x4000000,
114 .ipi_reg_base = 0xFF360000,
115 .secure_only = 0,
116 },
117 /* PL3 IPI */
118 {
119 .ipi_bit_mask = 0x8000000,
120 .ipi_reg_base = 0xFF370000,
121 .secure_only = 0,
122 },
123};
124
Jolly Shahb8e39f42019-01-08 11:27:36 -0800125/**
126 * zynqmp_ipi_config_table_init() - Initialize ZynqMP IPI configuration data
127 *
128 */
129void zynqmp_ipi_config_table_init(void)
130{
131 ipi_config_table_init(zynqmp_ipi_table, ARRAY_SIZE(zynqmp_ipi_table));
132}
133
134/**
135 * ipi_config_table_init() - Initialize IPI configuration data
136 *
137 * @ipi_config_table - IPI configuration table
138 * @ipi_total - Total number of IPI available
139 *
140 */
141void ipi_config_table_init(const struct ipi_config *ipi_config_table,
142 uint32_t total_ipi)
143{
144 ipi_table = ipi_config_table;
145 ipi_total = total_ipi;
146}
147
Wendy Liangdc1dfe82017-09-13 11:02:42 -0700148/* is_ipi_mb_within_range() - verify if IPI mailbox is within range
149 *
150 * @local - local IPI ID
151 * @remote - remote IPI ID
152 *
153 * return - 1 if within range, 0 if not
154 */
155static inline int is_ipi_mb_within_range(uint32_t local, uint32_t remote)
156{
157 int ret = 1;
Wendy Liangdc1dfe82017-09-13 11:02:42 -0700158
159 if (remote >= ipi_total || local >= ipi_total)
160 ret = 0;
161
162 return ret;
163}
164
165/**
166 * ipi_mb_validate() - validate IPI mailbox access
167 *
168 * @local - local IPI ID
169 * @remote - remote IPI ID
170 * @is_secure - indicate if the requester is from secure software
171 *
172 * return - 0 success, negative value for errors
173 */
174int ipi_mb_validate(uint32_t local, uint32_t remote, unsigned int is_secure)
175{
176 int ret = 0;
177
178 if (!is_ipi_mb_within_range(local, remote))
179 ret = -EINVAL;
180 else if (IPI_IS_SECURE(local) && !is_secure)
181 ret = -EPERM;
182 else if (IPI_IS_SECURE(remote) && !is_secure)
183 ret = -EPERM;
184
185 return ret;
186}
187
188/**
189 * ipi_mb_open() - Open IPI mailbox.
190 *
191 * @local - local IPI ID
192 * @remote - remote IPI ID
193 *
194 */
195void ipi_mb_open(uint32_t local, uint32_t remote)
196{
197 mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET,
198 IPI_BIT_MASK(remote));
199 mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET,
200 IPI_BIT_MASK(remote));
201}
202
203/**
204 * ipi_mb_release() - Open IPI mailbox.
205 *
206 * @local - local IPI ID
207 * @remote - remote IPI ID
208 *
209 */
210void ipi_mb_release(uint32_t local, uint32_t remote)
211{
212 mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET,
213 IPI_BIT_MASK(remote));
214}
215
216/**
217 * ipi_mb_enquire_status() - Enquire IPI mailbox status
218 *
219 * @local - local IPI ID
220 * @remote - remote IPI ID
221 *
222 * return - 0 idle, positive value for pending sending or receiving,
223 * negative value for errors
224 */
225int ipi_mb_enquire_status(uint32_t local, uint32_t remote)
226{
227 int ret = 0;
228 uint32_t status;
229
230 status = mmio_read_32(IPI_REG_BASE(local) + IPI_OBR_OFFSET);
231 if (status & IPI_BIT_MASK(remote))
232 ret |= IPI_MB_STATUS_SEND_PENDING;
233 status = mmio_read_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET);
234 if (status & IPI_BIT_MASK(remote))
235 ret |= IPI_MB_STATUS_RECV_PENDING;
236
237 return ret;
238}
239
240/* ipi_mb_notify() - Trigger IPI mailbox notification
241 *
242 * @local - local IPI ID
243 * @remote - remote IPI ID
244 * @is_blocking - if to trigger the notification in blocking mode or not.
245 *
246 * It sets the remote bit in the IPI agent trigger register.
247 *
248 */
249void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking)
250{
251 uint32_t status;
252
253 mmio_write_32(IPI_REG_BASE(local) + IPI_TRIG_OFFSET,
254 IPI_BIT_MASK(remote));
255 if (is_blocking) {
256 do {
257 status = mmio_read_32(IPI_REG_BASE(local) +
258 IPI_OBR_OFFSET);
259 } while (status & IPI_BIT_MASK(remote));
260 }
261}
262
263/* ipi_mb_ack() - Ack IPI mailbox notification from the other end
264 *
265 * @local - local IPI ID
266 * @remote - remote IPI ID
267 *
268 * It will clear the remote bit in the isr register.
269 *
270 */
271void ipi_mb_ack(uint32_t local, uint32_t remote)
272{
273 mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET,
274 IPI_BIT_MASK(remote));
275}
276
277/* ipi_mb_disable_irq() - Disable IPI mailbox notification interrupt
278 *
279 * @local - local IPI ID
280 * @remote - remote IPI ID
281 *
282 * It will mask the remote bit in the idr register.
283 *
284 */
285void ipi_mb_disable_irq(uint32_t local, uint32_t remote)
286{
287 mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET,
288 IPI_BIT_MASK(remote));
289}
290
291/* ipi_mb_enable_irq() - Enable IPI mailbox notification interrupt
292 *
293 * @local - local IPI ID
294 * @remote - remote IPI ID
295 *
296 * It will mask the remote bit in the idr register.
297 *
298 */
299void ipi_mb_enable_irq(uint32_t local, uint32_t remote)
300{
301 mmio_write_32(IPI_REG_BASE(local) + IPI_IER_OFFSET,
302 IPI_BIT_MASK(remote));
303}