163436bdeSJolly Shah /* 263436bdeSJolly Shah * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. 363436bdeSJolly Shah * 463436bdeSJolly Shah * SPDX-License-Identifier: BSD-3-Clause 563436bdeSJolly Shah */ 663436bdeSJolly Shah 763436bdeSJolly Shah /* 863436bdeSJolly Shah * Xilinx IPI agent registers access management 963436bdeSJolly Shah */ 1063436bdeSJolly Shah 1163436bdeSJolly Shah #include <errno.h> 1263436bdeSJolly Shah #include <string.h> 1363436bdeSJolly Shah 1463436bdeSJolly Shah #include <common/debug.h> 1563436bdeSJolly Shah #include <common/runtime_svc.h> 1663436bdeSJolly Shah #include <lib/bakery_lock.h> 1763436bdeSJolly Shah #include <lib/mmio.h> 1863436bdeSJolly Shah 1963436bdeSJolly Shah #include <ipi.h> 2063436bdeSJolly Shah #include <plat_ipi.h> 2163436bdeSJolly Shah #include <plat_private.h> 2263436bdeSJolly Shah 2363436bdeSJolly Shah /********************************************************************* 2463436bdeSJolly Shah * Macros definitions 2563436bdeSJolly Shah ********************************************************************/ 2663436bdeSJolly Shah 2763436bdeSJolly Shah /* IPI registers offsets macros */ 2863436bdeSJolly Shah #define IPI_TRIG_OFFSET 0x00U 2963436bdeSJolly Shah #define IPI_OBR_OFFSET 0x04U 3063436bdeSJolly Shah #define IPI_ISR_OFFSET 0x10U 3163436bdeSJolly Shah #define IPI_IMR_OFFSET 0x14U 3263436bdeSJolly Shah #define IPI_IER_OFFSET 0x18U 3363436bdeSJolly Shah #define IPI_IDR_OFFSET 0x1CU 3463436bdeSJolly Shah 3563436bdeSJolly Shah /* IPI register start offset */ 3663436bdeSJolly Shah #define IPI_REG_BASE(I) (ipi_table[(I)].ipi_reg_base) 3763436bdeSJolly Shah 3863436bdeSJolly Shah /* IPI register bit mask */ 3963436bdeSJolly Shah #define IPI_BIT_MASK(I) (ipi_table[(I)].ipi_bit_mask) 4063436bdeSJolly Shah 4163436bdeSJolly Shah /* IPI configuration table */ 4263436bdeSJolly Shah const static struct ipi_config *ipi_table; 4363436bdeSJolly Shah 4463436bdeSJolly Shah /* Total number of IPI */ 4563436bdeSJolly Shah static uint32_t ipi_total; 4663436bdeSJolly Shah 4763436bdeSJolly Shah /** 4863436bdeSJolly Shah * ipi_config_init() - Initialize IPI configuration data 4963436bdeSJolly Shah * 5063436bdeSJolly Shah * @ipi_config_table - IPI configuration table 5163436bdeSJolly Shah * @ipi_total - Total number of IPI available 5263436bdeSJolly Shah * 5363436bdeSJolly Shah */ 5463436bdeSJolly Shah void ipi_config_table_init(const struct ipi_config *ipi_config_table, 5563436bdeSJolly Shah uint32_t total_ipi) 5663436bdeSJolly Shah { 5763436bdeSJolly Shah ipi_table = ipi_config_table; 5863436bdeSJolly Shah ipi_total = total_ipi; 5963436bdeSJolly Shah } 6063436bdeSJolly Shah 6163436bdeSJolly Shah /* is_ipi_mb_within_range() - verify if IPI mailbox is within range 6263436bdeSJolly Shah * 6363436bdeSJolly Shah * @local - local IPI ID 6463436bdeSJolly Shah * @remote - remote IPI ID 6563436bdeSJolly Shah * 6663436bdeSJolly Shah * return - 1 if within range, 0 if not 6763436bdeSJolly Shah */ 6863436bdeSJolly Shah static inline int is_ipi_mb_within_range(uint32_t local, uint32_t remote) 6963436bdeSJolly Shah { 7063436bdeSJolly Shah int ret = 1; 7163436bdeSJolly Shah 7263436bdeSJolly Shah if (remote >= ipi_total || local >= ipi_total) 7363436bdeSJolly Shah ret = 0; 7463436bdeSJolly Shah 7563436bdeSJolly Shah return ret; 7663436bdeSJolly Shah } 7763436bdeSJolly Shah 7863436bdeSJolly Shah /** 7963436bdeSJolly Shah * ipi_mb_validate() - validate IPI mailbox access 8063436bdeSJolly Shah * 8163436bdeSJolly Shah * @local - local IPI ID 8263436bdeSJolly Shah * @remote - remote IPI ID 8363436bdeSJolly Shah * @is_secure - indicate if the requester is from secure software 8463436bdeSJolly Shah * 8563436bdeSJolly Shah * return - 0 success, negative value for errors 8663436bdeSJolly Shah */ 8763436bdeSJolly Shah int ipi_mb_validate(uint32_t local, uint32_t remote, unsigned int is_secure) 8863436bdeSJolly Shah { 8963436bdeSJolly Shah int ret = 0; 9063436bdeSJolly Shah 9163436bdeSJolly Shah if (!is_ipi_mb_within_range(local, remote)) 9263436bdeSJolly Shah ret = -EINVAL; 9363436bdeSJolly Shah else if (IPI_IS_SECURE(local) && !is_secure) 9463436bdeSJolly Shah ret = -EPERM; 9563436bdeSJolly Shah else if (IPI_IS_SECURE(remote) && !is_secure) 9663436bdeSJolly Shah ret = -EPERM; 9763436bdeSJolly Shah 9863436bdeSJolly Shah return ret; 9963436bdeSJolly Shah } 10063436bdeSJolly Shah 10163436bdeSJolly Shah /** 10263436bdeSJolly Shah * ipi_mb_open() - Open IPI mailbox. 10363436bdeSJolly Shah * 10463436bdeSJolly Shah * @local - local IPI ID 10563436bdeSJolly Shah * @remote - remote IPI ID 10663436bdeSJolly Shah * 10763436bdeSJolly Shah */ 10863436bdeSJolly Shah void ipi_mb_open(uint32_t local, uint32_t remote) 10963436bdeSJolly Shah { 11063436bdeSJolly Shah mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, 11163436bdeSJolly Shah IPI_BIT_MASK(remote)); 11263436bdeSJolly Shah mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET, 11363436bdeSJolly Shah IPI_BIT_MASK(remote)); 11463436bdeSJolly Shah } 11563436bdeSJolly Shah 11663436bdeSJolly Shah /** 11763436bdeSJolly Shah * ipi_mb_release() - Open IPI mailbox. 11863436bdeSJolly Shah * 11963436bdeSJolly Shah * @local - local IPI ID 12063436bdeSJolly Shah * @remote - remote IPI ID 12163436bdeSJolly Shah * 12263436bdeSJolly Shah */ 12363436bdeSJolly Shah void ipi_mb_release(uint32_t local, uint32_t remote) 12463436bdeSJolly Shah { 12563436bdeSJolly Shah mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, 12663436bdeSJolly Shah IPI_BIT_MASK(remote)); 12763436bdeSJolly Shah } 12863436bdeSJolly Shah 12963436bdeSJolly Shah /** 13063436bdeSJolly Shah * ipi_mb_enquire_status() - Enquire IPI mailbox status 13163436bdeSJolly Shah * 13263436bdeSJolly Shah * @local - local IPI ID 13363436bdeSJolly Shah * @remote - remote IPI ID 13463436bdeSJolly Shah * 13563436bdeSJolly Shah * return - 0 idle, positive value for pending sending or receiving, 13663436bdeSJolly Shah * negative value for errors 13763436bdeSJolly Shah */ 13863436bdeSJolly Shah int ipi_mb_enquire_status(uint32_t local, uint32_t remote) 13963436bdeSJolly Shah { 14063436bdeSJolly Shah int ret = 0; 14163436bdeSJolly Shah uint32_t status; 14263436bdeSJolly Shah 14363436bdeSJolly Shah status = mmio_read_32(IPI_REG_BASE(local) + IPI_OBR_OFFSET); 14463436bdeSJolly Shah if (status & IPI_BIT_MASK(remote)) 14563436bdeSJolly Shah ret |= IPI_MB_STATUS_SEND_PENDING; 14663436bdeSJolly Shah status = mmio_read_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET); 14763436bdeSJolly Shah if (status & IPI_BIT_MASK(remote)) 14863436bdeSJolly Shah ret |= IPI_MB_STATUS_RECV_PENDING; 14963436bdeSJolly Shah 15063436bdeSJolly Shah return ret; 15163436bdeSJolly Shah } 15263436bdeSJolly Shah 15363436bdeSJolly Shah /* ipi_mb_notify() - Trigger IPI mailbox notification 15463436bdeSJolly Shah * 15563436bdeSJolly Shah * @local - local IPI ID 15663436bdeSJolly Shah * @remote - remote IPI ID 15763436bdeSJolly Shah * @is_blocking - if to trigger the notification in blocking mode or not. 15863436bdeSJolly Shah * 15963436bdeSJolly Shah * It sets the remote bit in the IPI agent trigger register. 16063436bdeSJolly Shah * 16163436bdeSJolly Shah */ 162*62f9134dSVenkatesh Yadav Abbarapu void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking) 16363436bdeSJolly Shah { 16463436bdeSJolly Shah uint32_t status; 16563436bdeSJolly Shah 16663436bdeSJolly Shah mmio_write_32(IPI_REG_BASE(local) + IPI_TRIG_OFFSET, 16763436bdeSJolly Shah IPI_BIT_MASK(remote)); 16863436bdeSJolly Shah if (is_blocking) { 16963436bdeSJolly Shah do { 17063436bdeSJolly Shah status = mmio_read_32(IPI_REG_BASE(local) + 17163436bdeSJolly Shah IPI_OBR_OFFSET); 17263436bdeSJolly Shah } while (status & IPI_BIT_MASK(remote)); 17363436bdeSJolly Shah } 17463436bdeSJolly Shah } 17563436bdeSJolly Shah 17663436bdeSJolly Shah /* ipi_mb_ack() - Ack IPI mailbox notification from the other end 17763436bdeSJolly Shah * 17863436bdeSJolly Shah * @local - local IPI ID 17963436bdeSJolly Shah * @remote - remote IPI ID 18063436bdeSJolly Shah * 18163436bdeSJolly Shah * It will clear the remote bit in the isr register. 18263436bdeSJolly Shah * 18363436bdeSJolly Shah */ 18463436bdeSJolly Shah void ipi_mb_ack(uint32_t local, uint32_t remote) 18563436bdeSJolly Shah { 18663436bdeSJolly Shah mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET, 18763436bdeSJolly Shah IPI_BIT_MASK(remote)); 18863436bdeSJolly Shah } 18963436bdeSJolly Shah 19063436bdeSJolly Shah /* ipi_mb_disable_irq() - Disable IPI mailbox notification interrupt 19163436bdeSJolly Shah * 19263436bdeSJolly Shah * @local - local IPI ID 19363436bdeSJolly Shah * @remote - remote IPI ID 19463436bdeSJolly Shah * 19563436bdeSJolly Shah * It will mask the remote bit in the idr register. 19663436bdeSJolly Shah * 19763436bdeSJolly Shah */ 19863436bdeSJolly Shah void ipi_mb_disable_irq(uint32_t local, uint32_t remote) 19963436bdeSJolly Shah { 20063436bdeSJolly Shah mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, 20163436bdeSJolly Shah IPI_BIT_MASK(remote)); 20263436bdeSJolly Shah } 20363436bdeSJolly Shah 20463436bdeSJolly Shah /* ipi_mb_enable_irq() - Enable IPI mailbox notification interrupt 20563436bdeSJolly Shah * 20663436bdeSJolly Shah * @local - local IPI ID 20763436bdeSJolly Shah * @remote - remote IPI ID 20863436bdeSJolly Shah * 20963436bdeSJolly Shah * It will mask the remote bit in the idr register. 21063436bdeSJolly Shah * 21163436bdeSJolly Shah */ 21263436bdeSJolly Shah void ipi_mb_enable_irq(uint32_t local, uint32_t remote) 21363436bdeSJolly Shah { 21463436bdeSJolly Shah mmio_write_32(IPI_REG_BASE(local) + IPI_IER_OFFSET, 21563436bdeSJolly Shah IPI_BIT_MASK(remote)); 21663436bdeSJolly Shah } 217