blob: ac84e0b7364b482006eec5aad8e44f0ffec77e2b [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 */
39#define IPI_REG_BASE(I) (zynqmp_ipi_table[(I)].ipi_reg_base)
40
41/* IPI register bit mask */
42#define IPI_BIT_MASK(I) (zynqmp_ipi_table[(I)].ipi_bit_mask)
43
44/* IPI secure check */
45#define IPI_SECURE_MASK 0x1U
46#define IPI_IS_SECURE(I) ((zynqmp_ipi_table[(I)].secure_only & \
47 IPI_SECURE_MASK) ? 1 : 0)
48
Wendy Liangdc1dfe82017-09-13 11:02:42 -070049/* Zynqmp ipi configuration table */
Jolly Shah703a5aa2019-01-08 11:25:28 -080050const static struct ipi_config zynqmp_ipi_table[] = {
Wendy Liangdc1dfe82017-09-13 11:02:42 -070051 /* APU IPI */
52 {
53 .ipi_bit_mask = 0x1,
54 .ipi_reg_base = 0xFF300000,
55 .secure_only = 0,
56 },
57 /* RPU0 IPI */
58 {
59 .ipi_bit_mask = 0x100,
60 .ipi_reg_base = 0xFF310000,
61 .secure_only = 0,
62 },
63 /* RPU1 IPI */
64 {
65 .ipi_bit_mask = 0x200,
66 .ipi_reg_base = 0xFF320000,
67 .secure_only = 0,
68 },
69 /* PMU0 IPI */
70 {
71 .ipi_bit_mask = 0x10000,
72 .ipi_reg_base = 0xFF330000,
73 .secure_only = IPI_SECURE_MASK,
74 },
75 /* PMU1 IPI */
76 {
77 .ipi_bit_mask = 0x20000,
78 .ipi_reg_base = 0xFF331000,
Rajan Vaja85dc2d42018-01-30 03:59:23 -080079 .secure_only = 0,
Wendy Liangdc1dfe82017-09-13 11:02:42 -070080 },
81 /* PMU2 IPI */
82 {
83 .ipi_bit_mask = 0x40000,
84 .ipi_reg_base = 0xFF332000,
85 .secure_only = IPI_SECURE_MASK,
86 },
87 /* PMU3 IPI */
88 {
89 .ipi_bit_mask = 0x80000,
90 .ipi_reg_base = 0xFF333000,
91 .secure_only = IPI_SECURE_MASK,
92 },
93 /* PL0 IPI */
94 {
95 .ipi_bit_mask = 0x1000000,
96 .ipi_reg_base = 0xFF340000,
97 .secure_only = 0,
98 },
99 /* PL1 IPI */
100 {
101 .ipi_bit_mask = 0x2000000,
102 .ipi_reg_base = 0xFF350000,
103 .secure_only = 0,
104 },
105 /* PL2 IPI */
106 {
107 .ipi_bit_mask = 0x4000000,
108 .ipi_reg_base = 0xFF360000,
109 .secure_only = 0,
110 },
111 /* PL3 IPI */
112 {
113 .ipi_bit_mask = 0x8000000,
114 .ipi_reg_base = 0xFF370000,
115 .secure_only = 0,
116 },
117};
118
119/* is_ipi_mb_within_range() - verify if IPI mailbox is within range
120 *
121 * @local - local IPI ID
122 * @remote - remote IPI ID
123 *
124 * return - 1 if within range, 0 if not
125 */
126static inline int is_ipi_mb_within_range(uint32_t local, uint32_t remote)
127{
128 int ret = 1;
129 uint32_t ipi_total = ARRAY_SIZE(zynqmp_ipi_table);
130
131 if (remote >= ipi_total || local >= ipi_total)
132 ret = 0;
133
134 return ret;
135}
136
137/**
138 * ipi_mb_validate() - validate IPI mailbox access
139 *
140 * @local - local IPI ID
141 * @remote - remote IPI ID
142 * @is_secure - indicate if the requester is from secure software
143 *
144 * return - 0 success, negative value for errors
145 */
146int ipi_mb_validate(uint32_t local, uint32_t remote, unsigned int is_secure)
147{
148 int ret = 0;
149
150 if (!is_ipi_mb_within_range(local, remote))
151 ret = -EINVAL;
152 else if (IPI_IS_SECURE(local) && !is_secure)
153 ret = -EPERM;
154 else if (IPI_IS_SECURE(remote) && !is_secure)
155 ret = -EPERM;
156
157 return ret;
158}
159
160/**
161 * ipi_mb_open() - Open IPI mailbox.
162 *
163 * @local - local IPI ID
164 * @remote - remote IPI ID
165 *
166 */
167void ipi_mb_open(uint32_t local, uint32_t remote)
168{
169 mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET,
170 IPI_BIT_MASK(remote));
171 mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET,
172 IPI_BIT_MASK(remote));
173}
174
175/**
176 * ipi_mb_release() - Open IPI mailbox.
177 *
178 * @local - local IPI ID
179 * @remote - remote IPI ID
180 *
181 */
182void ipi_mb_release(uint32_t local, uint32_t remote)
183{
184 mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET,
185 IPI_BIT_MASK(remote));
186}
187
188/**
189 * ipi_mb_enquire_status() - Enquire IPI mailbox status
190 *
191 * @local - local IPI ID
192 * @remote - remote IPI ID
193 *
194 * return - 0 idle, positive value for pending sending or receiving,
195 * negative value for errors
196 */
197int ipi_mb_enquire_status(uint32_t local, uint32_t remote)
198{
199 int ret = 0;
200 uint32_t status;
201
202 status = mmio_read_32(IPI_REG_BASE(local) + IPI_OBR_OFFSET);
203 if (status & IPI_BIT_MASK(remote))
204 ret |= IPI_MB_STATUS_SEND_PENDING;
205 status = mmio_read_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET);
206 if (status & IPI_BIT_MASK(remote))
207 ret |= IPI_MB_STATUS_RECV_PENDING;
208
209 return ret;
210}
211
212/* ipi_mb_notify() - Trigger IPI mailbox notification
213 *
214 * @local - local IPI ID
215 * @remote - remote IPI ID
216 * @is_blocking - if to trigger the notification in blocking mode or not.
217 *
218 * It sets the remote bit in the IPI agent trigger register.
219 *
220 */
221void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking)
222{
223 uint32_t status;
224
225 mmio_write_32(IPI_REG_BASE(local) + IPI_TRIG_OFFSET,
226 IPI_BIT_MASK(remote));
227 if (is_blocking) {
228 do {
229 status = mmio_read_32(IPI_REG_BASE(local) +
230 IPI_OBR_OFFSET);
231 } while (status & IPI_BIT_MASK(remote));
232 }
233}
234
235/* ipi_mb_ack() - Ack IPI mailbox notification from the other end
236 *
237 * @local - local IPI ID
238 * @remote - remote IPI ID
239 *
240 * It will clear the remote bit in the isr register.
241 *
242 */
243void ipi_mb_ack(uint32_t local, uint32_t remote)
244{
245 mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET,
246 IPI_BIT_MASK(remote));
247}
248
249/* ipi_mb_disable_irq() - Disable IPI mailbox notification interrupt
250 *
251 * @local - local IPI ID
252 * @remote - remote IPI ID
253 *
254 * It will mask the remote bit in the idr register.
255 *
256 */
257void ipi_mb_disable_irq(uint32_t local, uint32_t remote)
258{
259 mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET,
260 IPI_BIT_MASK(remote));
261}
262
263/* ipi_mb_enable_irq() - Enable IPI mailbox notification interrupt
264 *
265 * @local - local IPI ID
266 * @remote - remote IPI ID
267 *
268 * It will mask the remote bit in the idr register.
269 *
270 */
271void ipi_mb_enable_irq(uint32_t local, uint32_t remote)
272{
273 mmio_write_32(IPI_REG_BASE(local) + IPI_IER_OFFSET,
274 IPI_BIT_MASK(remote));
275}