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