blob: 453e0b56905abf3aba32ec81515c1aeda6b21bc9 [file] [log] [blame]
Jolly Shah63436bd2019-01-08 11:31:49 -08001/*
2 * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7/*
8 * Xilinx IPI agent registers access management
9 */
10
11#include <errno.h>
12#include <string.h>
13
14#include <common/debug.h>
15#include <common/runtime_svc.h>
16#include <lib/bakery_lock.h>
17#include <lib/mmio.h>
18
19#include <ipi.h>
20#include <plat_ipi.h>
21#include <plat_private.h>
22
23/*********************************************************************
24 * Macros definitions
25 ********************************************************************/
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) (ipi_table[(I)].ipi_reg_base)
37
38/* IPI register bit mask */
39#define IPI_BIT_MASK(I) (ipi_table[(I)].ipi_bit_mask)
40
41/* IPI configuration table */
42const static struct ipi_config *ipi_table;
43
44/* Total number of IPI */
45static uint32_t ipi_total;
46
47/**
48 * ipi_config_init() - Initialize IPI configuration data
49 *
50 * @ipi_config_table - IPI configuration table
51 * @ipi_total - Total number of IPI available
52 *
53 */
54void ipi_config_table_init(const struct ipi_config *ipi_config_table,
55 uint32_t total_ipi)
56{
57 ipi_table = ipi_config_table;
58 ipi_total = total_ipi;
59}
60
61/* is_ipi_mb_within_range() - verify if IPI mailbox is within range
62 *
63 * @local - local IPI ID
64 * @remote - remote IPI ID
65 *
66 * return - 1 if within range, 0 if not
67 */
68static inline int is_ipi_mb_within_range(uint32_t local, uint32_t remote)
69{
70 int ret = 1;
71
Venkatesh Yadav Abbarapueb0d2b12022-04-29 13:52:00 +053072 if (remote >= ipi_total || local >= ipi_total) {
Jolly Shah63436bd2019-01-08 11:31:49 -080073 ret = 0;
Venkatesh Yadav Abbarapueb0d2b12022-04-29 13:52:00 +053074 }
Jolly Shah63436bd2019-01-08 11:31:49 -080075
76 return ret;
77}
78
79/**
80 * ipi_mb_validate() - validate IPI mailbox access
81 *
82 * @local - local IPI ID
83 * @remote - remote IPI ID
84 * @is_secure - indicate if the requester is from secure software
85 *
86 * return - 0 success, negative value for errors
87 */
88int ipi_mb_validate(uint32_t local, uint32_t remote, unsigned int is_secure)
89{
90 int ret = 0;
91
Venkatesh Yadav Abbarapueb0d2b12022-04-29 13:52:00 +053092 if (!is_ipi_mb_within_range(local, remote)) {
Jolly Shah63436bd2019-01-08 11:31:49 -080093 ret = -EINVAL;
Venkatesh Yadav Abbarapueb0d2b12022-04-29 13:52:00 +053094 } else if (IPI_IS_SECURE(local) && !is_secure) {
Jolly Shah63436bd2019-01-08 11:31:49 -080095 ret = -EPERM;
Venkatesh Yadav Abbarapueb0d2b12022-04-29 13:52:00 +053096 } else if (IPI_IS_SECURE(remote) && !is_secure) {
Jolly Shah63436bd2019-01-08 11:31:49 -080097 ret = -EPERM;
Venkatesh Yadav Abbarapueb0d2b12022-04-29 13:52:00 +053098 }
Jolly Shah63436bd2019-01-08 11:31:49 -080099
100 return ret;
101}
102
103/**
104 * ipi_mb_open() - Open IPI mailbox.
105 *
106 * @local - local IPI ID
107 * @remote - remote IPI ID
108 *
109 */
110void ipi_mb_open(uint32_t local, uint32_t remote)
111{
112 mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET,
113 IPI_BIT_MASK(remote));
114 mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET,
115 IPI_BIT_MASK(remote));
116}
117
118/**
119 * ipi_mb_release() - Open IPI mailbox.
120 *
121 * @local - local IPI ID
122 * @remote - remote IPI ID
123 *
124 */
125void ipi_mb_release(uint32_t local, uint32_t remote)
126{
127 mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET,
128 IPI_BIT_MASK(remote));
129}
130
131/**
132 * ipi_mb_enquire_status() - Enquire IPI mailbox status
133 *
134 * @local - local IPI ID
135 * @remote - remote IPI ID
136 *
137 * return - 0 idle, positive value for pending sending or receiving,
138 * negative value for errors
139 */
140int ipi_mb_enquire_status(uint32_t local, uint32_t remote)
141{
142 int ret = 0;
143 uint32_t status;
144
145 status = mmio_read_32(IPI_REG_BASE(local) + IPI_OBR_OFFSET);
Venkatesh Yadav Abbarapueb0d2b12022-04-29 13:52:00 +0530146 if (status & IPI_BIT_MASK(remote)) {
Jolly Shah63436bd2019-01-08 11:31:49 -0800147 ret |= IPI_MB_STATUS_SEND_PENDING;
Venkatesh Yadav Abbarapueb0d2b12022-04-29 13:52:00 +0530148 }
Jolly Shah63436bd2019-01-08 11:31:49 -0800149 status = mmio_read_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET);
Venkatesh Yadav Abbarapueb0d2b12022-04-29 13:52:00 +0530150 if (status & IPI_BIT_MASK(remote)) {
Jolly Shah63436bd2019-01-08 11:31:49 -0800151 ret |= IPI_MB_STATUS_RECV_PENDING;
Venkatesh Yadav Abbarapueb0d2b12022-04-29 13:52:00 +0530152 }
Jolly Shah63436bd2019-01-08 11:31:49 -0800153
154 return ret;
155}
156
157/* ipi_mb_notify() - Trigger IPI mailbox notification
158 *
159 * @local - local IPI ID
160 * @remote - remote IPI ID
161 * @is_blocking - if to trigger the notification in blocking mode or not.
162 *
163 * It sets the remote bit in the IPI agent trigger register.
164 *
165 */
Venkatesh Yadav Abbarapu62f91342021-08-04 21:33:15 -0600166void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking)
Jolly Shah63436bd2019-01-08 11:31:49 -0800167{
168 uint32_t status;
169
170 mmio_write_32(IPI_REG_BASE(local) + IPI_TRIG_OFFSET,
171 IPI_BIT_MASK(remote));
172 if (is_blocking) {
173 do {
174 status = mmio_read_32(IPI_REG_BASE(local) +
175 IPI_OBR_OFFSET);
176 } while (status & IPI_BIT_MASK(remote));
177 }
Jolly Shah63436bd2019-01-08 11:31:49 -0800178}
179
180/* ipi_mb_ack() - Ack IPI mailbox notification from the other end
181 *
182 * @local - local IPI ID
183 * @remote - remote IPI ID
184 *
185 * It will clear the remote bit in the isr register.
186 *
187 */
188void ipi_mb_ack(uint32_t local, uint32_t remote)
189{
190 mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET,
191 IPI_BIT_MASK(remote));
192}
193
194/* ipi_mb_disable_irq() - Disable IPI mailbox notification interrupt
195 *
196 * @local - local IPI ID
197 * @remote - remote IPI ID
198 *
199 * It will mask the remote bit in the idr register.
200 *
201 */
202void ipi_mb_disable_irq(uint32_t local, uint32_t remote)
203{
204 mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET,
205 IPI_BIT_MASK(remote));
206}
207
208/* ipi_mb_enable_irq() - Enable IPI mailbox notification interrupt
209 *
210 * @local - local IPI ID
211 * @remote - remote IPI ID
212 *
213 * It will mask the remote bit in the idr register.
214 *
215 */
216void ipi_mb_enable_irq(uint32_t local, uint32_t remote)
217{
218 mmio_write_32(IPI_REG_BASE(local) + IPI_IER_OFFSET,
219 IPI_BIT_MASK(remote));
220}