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