xref: /rk3399_ARM-atf/plat/xilinx/common/ipi.c (revision eb0d2b17722c01a22bf3ec1123f7bed2bf891b09)
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  */
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  */
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 
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  */
88 int ipi_mb_validate(uint32_t local, uint32_t remote, unsigned int is_secure)
89 {
90 	int ret = 0;
91 
92 	if (!is_ipi_mb_within_range(local, remote)) {
93 		ret = -EINVAL;
94 	} else if (IPI_IS_SECURE(local) && !is_secure) {
95 		ret = -EPERM;
96 	} else if (IPI_IS_SECURE(remote) && !is_secure) {
97 		ret = -EPERM;
98 	}
99 
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  */
110 void 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  */
125 void 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  */
140 int 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);
146 	if (status & IPI_BIT_MASK(remote)) {
147 		ret |= IPI_MB_STATUS_SEND_PENDING;
148 	}
149 	status = mmio_read_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET);
150 	if (status & IPI_BIT_MASK(remote)) {
151 		ret |= IPI_MB_STATUS_RECV_PENDING;
152 	}
153 
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  */
166 void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking)
167 {
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 	}
178 }
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  */
188 void 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  */
202 void 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  */
216 void 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 }
221