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