1 /*
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 */
42 const static struct ipi_config *ipi_table;
43
44 /* Total number of IPI */
45 static 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 */
ipi_config_table_init(const struct ipi_config * ipi_config_table,uint32_t total_ipi)54 void 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 */
is_ipi_mb_within_range(uint32_t local,uint32_t remote)68 static inline int is_ipi_mb_within_range(uint32_t local, uint32_t remote)
69 {
70 int ret = 1;
71
72 if (remote >= ipi_total || local >= ipi_total)
73 ret = 0;
74
75 return ret;
76 }
77
78 /**
79 * ipi_mb_validate() - validate IPI mailbox access
80 *
81 * @local - local IPI ID
82 * @remote - remote IPI ID
83 * @is_secure - indicate if the requester is from secure software
84 *
85 * return - 0 success, negative value for errors
86 */
ipi_mb_validate(uint32_t local,uint32_t remote,unsigned int is_secure)87 int ipi_mb_validate(uint32_t local, uint32_t remote, unsigned int is_secure)
88 {
89 int ret = 0;
90
91 if (!is_ipi_mb_within_range(local, remote))
92 ret = -EINVAL;
93 else if (IPI_IS_SECURE(local) && !is_secure)
94 ret = -EPERM;
95 else if (IPI_IS_SECURE(remote) && !is_secure)
96 ret = -EPERM;
97
98 return ret;
99 }
100
101 /**
102 * ipi_mb_open() - Open IPI mailbox.
103 *
104 * @local - local IPI ID
105 * @remote - remote IPI ID
106 *
107 */
ipi_mb_open(uint32_t local,uint32_t remote)108 void ipi_mb_open(uint32_t local, uint32_t remote)
109 {
110 mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET,
111 IPI_BIT_MASK(remote));
112 mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET,
113 IPI_BIT_MASK(remote));
114 }
115
116 /**
117 * ipi_mb_release() - Open IPI mailbox.
118 *
119 * @local - local IPI ID
120 * @remote - remote IPI ID
121 *
122 */
ipi_mb_release(uint32_t local,uint32_t remote)123 void ipi_mb_release(uint32_t local, uint32_t remote)
124 {
125 mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET,
126 IPI_BIT_MASK(remote));
127 }
128
129 /**
130 * ipi_mb_enquire_status() - Enquire IPI mailbox status
131 *
132 * @local - local IPI ID
133 * @remote - remote IPI ID
134 *
135 * return - 0 idle, positive value for pending sending or receiving,
136 * negative value for errors
137 */
ipi_mb_enquire_status(uint32_t local,uint32_t remote)138 int ipi_mb_enquire_status(uint32_t local, uint32_t remote)
139 {
140 int ret = 0;
141 uint32_t status;
142
143 status = mmio_read_32(IPI_REG_BASE(local) + IPI_OBR_OFFSET);
144 if (status & IPI_BIT_MASK(remote))
145 ret |= IPI_MB_STATUS_SEND_PENDING;
146 status = mmio_read_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET);
147 if (status & IPI_BIT_MASK(remote))
148 ret |= IPI_MB_STATUS_RECV_PENDING;
149
150 return ret;
151 }
152
153 /* ipi_mb_notify() - Trigger IPI mailbox notification
154 *
155 * @local - local IPI ID
156 * @remote - remote IPI ID
157 * @is_blocking - if to trigger the notification in blocking mode or not.
158 *
159 * It sets the remote bit in the IPI agent trigger register.
160 *
161 */
ipi_mb_notify(uint32_t local,uint32_t remote,uint32_t is_blocking)162 void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking)
163 {
164 uint32_t status;
165
166 mmio_write_32(IPI_REG_BASE(local) + IPI_TRIG_OFFSET,
167 IPI_BIT_MASK(remote));
168 if (is_blocking) {
169 do {
170 status = mmio_read_32(IPI_REG_BASE(local) +
171 IPI_OBR_OFFSET);
172 } while (status & IPI_BIT_MASK(remote));
173 }
174 }
175
176 /* ipi_mb_ack() - Ack IPI mailbox notification from the other end
177 *
178 * @local - local IPI ID
179 * @remote - remote IPI ID
180 *
181 * It will clear the remote bit in the isr register.
182 *
183 */
ipi_mb_ack(uint32_t local,uint32_t remote)184 void ipi_mb_ack(uint32_t local, uint32_t remote)
185 {
186 mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET,
187 IPI_BIT_MASK(remote));
188 }
189
190 /* ipi_mb_disable_irq() - Disable IPI mailbox notification interrupt
191 *
192 * @local - local IPI ID
193 * @remote - remote IPI ID
194 *
195 * It will mask the remote bit in the idr register.
196 *
197 */
ipi_mb_disable_irq(uint32_t local,uint32_t remote)198 void ipi_mb_disable_irq(uint32_t local, uint32_t remote)
199 {
200 mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET,
201 IPI_BIT_MASK(remote));
202 }
203
204 /* ipi_mb_enable_irq() - Enable IPI mailbox notification interrupt
205 *
206 * @local - local IPI ID
207 * @remote - remote IPI ID
208 *
209 * It will mask the remote bit in the idr register.
210 *
211 */
ipi_mb_enable_irq(uint32_t local,uint32_t remote)212 void ipi_mb_enable_irq(uint32_t local, uint32_t remote)
213 {
214 mmio_write_32(IPI_REG_BASE(local) + IPI_IER_OFFSET,
215 IPI_BIT_MASK(remote));
216 }
217