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