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