xref: /arm-trusted-firmware/plat/xilinx/common/ipi.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  * Copyright (c) 2020-2022, Xilinx, Inc. All rights reserved.
4*91f16700Schasinglulu  * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
5*91f16700Schasinglulu  *
6*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
7*91f16700Schasinglulu  */
8*91f16700Schasinglulu 
9*91f16700Schasinglulu /*
10*91f16700Schasinglulu  * Xilinx IPI agent registers access management
11*91f16700Schasinglulu  */
12*91f16700Schasinglulu 
13*91f16700Schasinglulu #include <errno.h>
14*91f16700Schasinglulu #include <string.h>
15*91f16700Schasinglulu 
16*91f16700Schasinglulu #include <common/debug.h>
17*91f16700Schasinglulu #include <common/runtime_svc.h>
18*91f16700Schasinglulu #include <lib/bakery_lock.h>
19*91f16700Schasinglulu #include <lib/mmio.h>
20*91f16700Schasinglulu 
21*91f16700Schasinglulu #include <ipi.h>
22*91f16700Schasinglulu #include <plat_private.h>
23*91f16700Schasinglulu 
24*91f16700Schasinglulu /*********************************************************************
25*91f16700Schasinglulu  * Macros definitions
26*91f16700Schasinglulu  ********************************************************************/
27*91f16700Schasinglulu 
28*91f16700Schasinglulu /* IPI registers offsets macros */
29*91f16700Schasinglulu #define IPI_TRIG_OFFSET 0x00U
30*91f16700Schasinglulu #define IPI_OBR_OFFSET  0x04U
31*91f16700Schasinglulu #define IPI_ISR_OFFSET  0x10U
32*91f16700Schasinglulu #define IPI_IMR_OFFSET  0x14U
33*91f16700Schasinglulu #define IPI_IER_OFFSET  0x18U
34*91f16700Schasinglulu #define IPI_IDR_OFFSET  0x1CU
35*91f16700Schasinglulu 
36*91f16700Schasinglulu /* IPI register start offset */
37*91f16700Schasinglulu #define IPI_REG_BASE(I) (ipi_table[(I)].ipi_reg_base)
38*91f16700Schasinglulu 
39*91f16700Schasinglulu /* IPI register bit mask */
40*91f16700Schasinglulu #define IPI_BIT_MASK(I) (ipi_table[(I)].ipi_bit_mask)
41*91f16700Schasinglulu 
42*91f16700Schasinglulu /* IPI configuration table */
43*91f16700Schasinglulu static const struct ipi_config *ipi_table;
44*91f16700Schasinglulu 
45*91f16700Schasinglulu /* Total number of IPI */
46*91f16700Schasinglulu static uint32_t ipi_total;
47*91f16700Schasinglulu 
48*91f16700Schasinglulu /**
49*91f16700Schasinglulu  * ipi_config_table_init() - Initialize IPI configuration data.
50*91f16700Schasinglulu  * @ipi_config_table: IPI configuration table.
51*91f16700Schasinglulu  * @total_ipi: Total number of IPI available.
52*91f16700Schasinglulu  *
53*91f16700Schasinglulu  */
54*91f16700Schasinglulu void ipi_config_table_init(const struct ipi_config *ipi_config_table,
55*91f16700Schasinglulu 			   uint32_t total_ipi)
56*91f16700Schasinglulu {
57*91f16700Schasinglulu 	ipi_table = ipi_config_table;
58*91f16700Schasinglulu 	ipi_total = total_ipi;
59*91f16700Schasinglulu }
60*91f16700Schasinglulu 
61*91f16700Schasinglulu /**
62*91f16700Schasinglulu  * is_ipi_mb_within_range() - verify if IPI mailbox is within range.
63*91f16700Schasinglulu  * @local: local IPI ID.
64*91f16700Schasinglulu  * @remote: remote IPI ID.
65*91f16700Schasinglulu  *
66*91f16700Schasinglulu  * Return: - 1 if within range, 0 if not.
67*91f16700Schasinglulu  *
68*91f16700Schasinglulu  */
69*91f16700Schasinglulu static inline int is_ipi_mb_within_range(uint32_t local, uint32_t remote)
70*91f16700Schasinglulu {
71*91f16700Schasinglulu 	int ret = 1;
72*91f16700Schasinglulu 
73*91f16700Schasinglulu 	if (remote >= ipi_total || local >= ipi_total) {
74*91f16700Schasinglulu 		ret = 0;
75*91f16700Schasinglulu 	}
76*91f16700Schasinglulu 
77*91f16700Schasinglulu 	return ret;
78*91f16700Schasinglulu }
79*91f16700Schasinglulu 
80*91f16700Schasinglulu /**
81*91f16700Schasinglulu  * ipi_mb_validate() - validate IPI mailbox access.
82*91f16700Schasinglulu  * @local: local IPI ID.
83*91f16700Schasinglulu  * @remote: remote IPI ID.
84*91f16700Schasinglulu  * @is_secure: indicate if the requester is from secure software.
85*91f16700Schasinglulu  *
86*91f16700Schasinglulu  * Return: 0 success, negative value for errors.
87*91f16700Schasinglulu  *
88*91f16700Schasinglulu  */
89*91f16700Schasinglulu int ipi_mb_validate(uint32_t local, uint32_t remote, unsigned int is_secure)
90*91f16700Schasinglulu {
91*91f16700Schasinglulu 	int ret = 0;
92*91f16700Schasinglulu 
93*91f16700Schasinglulu 	if (!is_ipi_mb_within_range(local, remote)) {
94*91f16700Schasinglulu 		ret = -EINVAL;
95*91f16700Schasinglulu 	} else if (IPI_IS_SECURE(local) && !is_secure) {
96*91f16700Schasinglulu 		ret = -EPERM;
97*91f16700Schasinglulu 	} else if (IPI_IS_SECURE(remote) && !is_secure) {
98*91f16700Schasinglulu 		ret = -EPERM;
99*91f16700Schasinglulu 	} else {
100*91f16700Schasinglulu 		/* To fix the misra 15.7 warning */
101*91f16700Schasinglulu 	}
102*91f16700Schasinglulu 
103*91f16700Schasinglulu 	return ret;
104*91f16700Schasinglulu }
105*91f16700Schasinglulu 
106*91f16700Schasinglulu /**
107*91f16700Schasinglulu  * ipi_mb_open() - Open IPI mailbox.
108*91f16700Schasinglulu  * @local: local IPI ID.
109*91f16700Schasinglulu  * @remote: remote IPI ID.
110*91f16700Schasinglulu  *
111*91f16700Schasinglulu  */
112*91f16700Schasinglulu void ipi_mb_open(uint32_t local, uint32_t remote)
113*91f16700Schasinglulu {
114*91f16700Schasinglulu 	mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET,
115*91f16700Schasinglulu 		      IPI_BIT_MASK(remote));
116*91f16700Schasinglulu 	mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET,
117*91f16700Schasinglulu 		      IPI_BIT_MASK(remote));
118*91f16700Schasinglulu }
119*91f16700Schasinglulu 
120*91f16700Schasinglulu /**
121*91f16700Schasinglulu  * ipi_mb_release() - Open IPI mailbox.
122*91f16700Schasinglulu  * @local: local IPI ID.
123*91f16700Schasinglulu  * @remote: remote IPI ID.
124*91f16700Schasinglulu  *
125*91f16700Schasinglulu  */
126*91f16700Schasinglulu void ipi_mb_release(uint32_t local, uint32_t remote)
127*91f16700Schasinglulu {
128*91f16700Schasinglulu 	mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET,
129*91f16700Schasinglulu 		      IPI_BIT_MASK(remote));
130*91f16700Schasinglulu }
131*91f16700Schasinglulu 
132*91f16700Schasinglulu /**
133*91f16700Schasinglulu  * ipi_mb_enquire_status() - Enquire IPI mailbox status.
134*91f16700Schasinglulu  * @local: local IPI ID.
135*91f16700Schasinglulu  * @remote: remote IPI ID.
136*91f16700Schasinglulu  *
137*91f16700Schasinglulu  * Return: 0 idle, positive value for pending sending or receiving,
138*91f16700Schasinglulu  *         negative value for errors.
139*91f16700Schasinglulu  *
140*91f16700Schasinglulu  */
141*91f16700Schasinglulu int ipi_mb_enquire_status(uint32_t local, uint32_t remote)
142*91f16700Schasinglulu {
143*91f16700Schasinglulu 	int ret = 0U;
144*91f16700Schasinglulu 	uint32_t status;
145*91f16700Schasinglulu 
146*91f16700Schasinglulu 	status = mmio_read_32(IPI_REG_BASE(local) + IPI_OBR_OFFSET);
147*91f16700Schasinglulu 	if (status & IPI_BIT_MASK(remote)) {
148*91f16700Schasinglulu 		ret |= IPI_MB_STATUS_SEND_PENDING;
149*91f16700Schasinglulu 	}
150*91f16700Schasinglulu 	status = mmio_read_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET);
151*91f16700Schasinglulu 	if (status & IPI_BIT_MASK(remote)) {
152*91f16700Schasinglulu 		ret |= IPI_MB_STATUS_RECV_PENDING;
153*91f16700Schasinglulu 	}
154*91f16700Schasinglulu 
155*91f16700Schasinglulu 	return ret;
156*91f16700Schasinglulu }
157*91f16700Schasinglulu 
158*91f16700Schasinglulu /**
159*91f16700Schasinglulu  * ipi_mb_notify() - Trigger IPI mailbox notification.
160*91f16700Schasinglulu  * @local: local IPI ID.
161*91f16700Schasinglulu  * @remote: remote IPI ID.
162*91f16700Schasinglulu  * @is_blocking: if to trigger the notification in blocking mode or not.
163*91f16700Schasinglulu  *
164*91f16700Schasinglulu  * It sets the remote bit in the IPI agent trigger register.
165*91f16700Schasinglulu  *
166*91f16700Schasinglulu  */
167*91f16700Schasinglulu void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking)
168*91f16700Schasinglulu {
169*91f16700Schasinglulu 	uint32_t status;
170*91f16700Schasinglulu 
171*91f16700Schasinglulu 	mmio_write_32(IPI_REG_BASE(local) + IPI_TRIG_OFFSET,
172*91f16700Schasinglulu 		      IPI_BIT_MASK(remote));
173*91f16700Schasinglulu 	if (is_blocking) {
174*91f16700Schasinglulu 		do {
175*91f16700Schasinglulu 			status = mmio_read_32(IPI_REG_BASE(local) +
176*91f16700Schasinglulu 					      IPI_OBR_OFFSET);
177*91f16700Schasinglulu 		} while (status & IPI_BIT_MASK(remote));
178*91f16700Schasinglulu 	}
179*91f16700Schasinglulu }
180*91f16700Schasinglulu 
181*91f16700Schasinglulu /**
182*91f16700Schasinglulu  * ipi_mb_ack() - Ack IPI mailbox notification from the other end.
183*91f16700Schasinglulu  * @local: local IPI ID.
184*91f16700Schasinglulu  * @remote: remote IPI ID.
185*91f16700Schasinglulu  *
186*91f16700Schasinglulu  * It will clear the remote bit in the isr register.
187*91f16700Schasinglulu  *
188*91f16700Schasinglulu  */
189*91f16700Schasinglulu void ipi_mb_ack(uint32_t local, uint32_t remote)
190*91f16700Schasinglulu {
191*91f16700Schasinglulu 	mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET,
192*91f16700Schasinglulu 		      IPI_BIT_MASK(remote));
193*91f16700Schasinglulu }
194*91f16700Schasinglulu 
195*91f16700Schasinglulu /**
196*91f16700Schasinglulu  * ipi_mb_disable_irq() - Disable IPI mailbox notification interrupt.
197*91f16700Schasinglulu  * @local: local IPI ID.
198*91f16700Schasinglulu  * @remote: remote IPI ID.
199*91f16700Schasinglulu  *
200*91f16700Schasinglulu  * It will mask the remote bit in the idr register.
201*91f16700Schasinglulu  *
202*91f16700Schasinglulu  */
203*91f16700Schasinglulu void ipi_mb_disable_irq(uint32_t local, uint32_t remote)
204*91f16700Schasinglulu {
205*91f16700Schasinglulu 	mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET,
206*91f16700Schasinglulu 		      IPI_BIT_MASK(remote));
207*91f16700Schasinglulu }
208*91f16700Schasinglulu 
209*91f16700Schasinglulu /**
210*91f16700Schasinglulu  * ipi_mb_enable_irq() - Enable IPI mailbox notification interrupt.
211*91f16700Schasinglulu  * @local: local IPI ID.
212*91f16700Schasinglulu  * @remote: remote IPI ID.
213*91f16700Schasinglulu  *
214*91f16700Schasinglulu  * It will mask the remote bit in the idr register.
215*91f16700Schasinglulu  *
216*91f16700Schasinglulu  */
217*91f16700Schasinglulu void ipi_mb_enable_irq(uint32_t local, uint32_t remote)
218*91f16700Schasinglulu {
219*91f16700Schasinglulu 	mmio_write_32(IPI_REG_BASE(local) + IPI_IER_OFFSET,
220*91f16700Schasinglulu 		      IPI_BIT_MASK(remote));
221*91f16700Schasinglulu }
222