blob: ca4146e2a4a808a59179f2b006cabd6f1d9b2cf2 [file] [log] [blame]
Jolly Shahc2583ab2019-01-08 11:31:49 -08001/*
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>
Tejas Patelc1cda9c2021-02-25 02:37:09 -080016#include <drivers/delay_timer.h>
Jolly Shahc2583ab2019-01-08 11:31:49 -080017#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
Tejas Patelc1cda9c2021-02-25 02:37:09 -080042/* IPI Timeout */
43#define TIMEOUT_COUNT_US U(0x4000)
44
Jolly Shahc2583ab2019-01-08 11:31:49 -080045/* IPI configuration table */
46const static struct ipi_config *ipi_table;
47
48/* Total number of IPI */
49static 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 */
58void 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 */
72static 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 */
91int 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 */
112void 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 */
127void 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 */
142int 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 *
Tejas Patelc1cda9c2021-02-25 02:37:09 -0800163 * return - 0 - Success or Error incase of timeout
Jolly Shahc2583ab2019-01-08 11:31:49 -0800164 * It sets the remote bit in the IPI agent trigger register.
165 *
166 */
Tejas Patelc1cda9c2021-02-25 02:37:09 -0800167int ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking)
Jolly Shahc2583ab2019-01-08 11:31:49 -0800168{
169 uint32_t status;
Tejas Patelc1cda9c2021-02-25 02:37:09 -0800170 const unsigned int timeout_count = TIMEOUT_COUNT_US;
171 uint64_t timeout;
Jolly Shahc2583ab2019-01-08 11:31:49 -0800172
173 mmio_write_32(IPI_REG_BASE(local) + IPI_TRIG_OFFSET,
174 IPI_BIT_MASK(remote));
175 if (is_blocking) {
Tejas Patelc1cda9c2021-02-25 02:37:09 -0800176 timeout = timeout_init_us(timeout_count);
Jolly Shahc2583ab2019-01-08 11:31:49 -0800177 do {
178 status = mmio_read_32(IPI_REG_BASE(local) +
179 IPI_OBR_OFFSET);
Tejas Patelc1cda9c2021-02-25 02:37:09 -0800180 if (timeout_elapsed(timeout)) {
181 return -ETIMEDOUT;
182 }
Jolly Shahc2583ab2019-01-08 11:31:49 -0800183 } while (status & IPI_BIT_MASK(remote));
184 }
Tejas Patelc1cda9c2021-02-25 02:37:09 -0800185
186 return 0;
Jolly Shahc2583ab2019-01-08 11:31:49 -0800187}
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 */
197void 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 */
211void 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 */
225void 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}