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