163436bdeSJolly Shah /* 20ee2dc11SRajan Vaja * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. 30ee2dc11SRajan Vaja * Copyright (c) 2020-2022, Xilinx, Inc. All rights reserved. 463436bdeSJolly Shah * 563436bdeSJolly Shah * SPDX-License-Identifier: BSD-3-Clause 663436bdeSJolly Shah */ 763436bdeSJolly Shah 863436bdeSJolly Shah /* 963436bdeSJolly Shah * Xilinx IPI agent registers access management 1063436bdeSJolly Shah */ 1163436bdeSJolly Shah 1263436bdeSJolly Shah #include <errno.h> 1363436bdeSJolly Shah #include <string.h> 1463436bdeSJolly Shah 1563436bdeSJolly Shah #include <common/debug.h> 1663436bdeSJolly Shah #include <common/runtime_svc.h> 1763436bdeSJolly Shah #include <lib/bakery_lock.h> 1863436bdeSJolly Shah #include <lib/mmio.h> 1963436bdeSJolly Shah 2063436bdeSJolly Shah #include <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 72eb0d2b17SVenkatesh Yadav Abbarapu if (remote >= ipi_total || local >= ipi_total) { 7363436bdeSJolly Shah ret = 0; 74eb0d2b17SVenkatesh Yadav Abbarapu } 7563436bdeSJolly Shah 7663436bdeSJolly Shah return ret; 7763436bdeSJolly Shah } 7863436bdeSJolly Shah 7963436bdeSJolly Shah /** 8063436bdeSJolly Shah * ipi_mb_validate() - validate IPI mailbox access 8163436bdeSJolly Shah * 8263436bdeSJolly Shah * @local - local IPI ID 8363436bdeSJolly Shah * @remote - remote IPI ID 8463436bdeSJolly Shah * @is_secure - indicate if the requester is from secure software 8563436bdeSJolly Shah * 8663436bdeSJolly Shah * return - 0 success, negative value for errors 8763436bdeSJolly Shah */ 8863436bdeSJolly Shah int ipi_mb_validate(uint32_t local, uint32_t remote, unsigned int is_secure) 8963436bdeSJolly Shah { 9063436bdeSJolly Shah int ret = 0; 9163436bdeSJolly Shah 92eb0d2b17SVenkatesh Yadav Abbarapu if (!is_ipi_mb_within_range(local, remote)) { 9363436bdeSJolly Shah ret = -EINVAL; 94eb0d2b17SVenkatesh Yadav Abbarapu } else if (IPI_IS_SECURE(local) && !is_secure) { 9563436bdeSJolly Shah ret = -EPERM; 96eb0d2b17SVenkatesh Yadav Abbarapu } else if (IPI_IS_SECURE(remote) && !is_secure) { 9763436bdeSJolly Shah ret = -EPERM; 9816de22d0SVenkatesh Yadav Abbarapu } else { 9916de22d0SVenkatesh Yadav Abbarapu /* To fix the misra 15.7 warning */ 100eb0d2b17SVenkatesh Yadav Abbarapu } 10163436bdeSJolly Shah 10263436bdeSJolly Shah return ret; 10363436bdeSJolly Shah } 10463436bdeSJolly Shah 10563436bdeSJolly Shah /** 10663436bdeSJolly Shah * ipi_mb_open() - Open IPI mailbox. 10763436bdeSJolly Shah * 10863436bdeSJolly Shah * @local - local IPI ID 10963436bdeSJolly Shah * @remote - remote IPI ID 11063436bdeSJolly Shah * 11163436bdeSJolly Shah */ 11263436bdeSJolly Shah void ipi_mb_open(uint32_t local, uint32_t remote) 11363436bdeSJolly Shah { 11463436bdeSJolly Shah mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, 11563436bdeSJolly Shah IPI_BIT_MASK(remote)); 11663436bdeSJolly Shah mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET, 11763436bdeSJolly Shah IPI_BIT_MASK(remote)); 11863436bdeSJolly Shah } 11963436bdeSJolly Shah 12063436bdeSJolly Shah /** 12163436bdeSJolly Shah * ipi_mb_release() - Open IPI mailbox. 12263436bdeSJolly Shah * 12363436bdeSJolly Shah * @local - local IPI ID 12463436bdeSJolly Shah * @remote - remote IPI ID 12563436bdeSJolly Shah * 12663436bdeSJolly Shah */ 12763436bdeSJolly Shah void ipi_mb_release(uint32_t local, uint32_t remote) 12863436bdeSJolly Shah { 12963436bdeSJolly Shah mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, 13063436bdeSJolly Shah IPI_BIT_MASK(remote)); 13163436bdeSJolly Shah } 13263436bdeSJolly Shah 13363436bdeSJolly Shah /** 13463436bdeSJolly Shah * ipi_mb_enquire_status() - Enquire IPI mailbox status 13563436bdeSJolly Shah * 13663436bdeSJolly Shah * @local - local IPI ID 13763436bdeSJolly Shah * @remote - remote IPI ID 13863436bdeSJolly Shah * 13963436bdeSJolly Shah * return - 0 idle, positive value for pending sending or receiving, 14063436bdeSJolly Shah * negative value for errors 14163436bdeSJolly Shah */ 14263436bdeSJolly Shah int ipi_mb_enquire_status(uint32_t local, uint32_t remote) 14363436bdeSJolly Shah { 144*15dc3e4fSHariBabu Gattem int ret = 0U; 14563436bdeSJolly Shah uint32_t status; 14663436bdeSJolly Shah 14763436bdeSJolly Shah status = mmio_read_32(IPI_REG_BASE(local) + IPI_OBR_OFFSET); 148eb0d2b17SVenkatesh Yadav Abbarapu if (status & IPI_BIT_MASK(remote)) { 14963436bdeSJolly Shah ret |= IPI_MB_STATUS_SEND_PENDING; 150eb0d2b17SVenkatesh Yadav Abbarapu } 15163436bdeSJolly Shah status = mmio_read_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET); 152eb0d2b17SVenkatesh Yadav Abbarapu if (status & IPI_BIT_MASK(remote)) { 15363436bdeSJolly Shah ret |= IPI_MB_STATUS_RECV_PENDING; 154eb0d2b17SVenkatesh Yadav Abbarapu } 15563436bdeSJolly Shah 15663436bdeSJolly Shah return ret; 15763436bdeSJolly Shah } 15863436bdeSJolly Shah 15963436bdeSJolly Shah /* ipi_mb_notify() - Trigger IPI mailbox notification 16063436bdeSJolly Shah * 16163436bdeSJolly Shah * @local - local IPI ID 16263436bdeSJolly Shah * @remote - remote IPI ID 16363436bdeSJolly Shah * @is_blocking - if to trigger the notification in blocking mode or not. 16463436bdeSJolly Shah * 16563436bdeSJolly Shah * It sets the remote bit in the IPI agent trigger register. 16663436bdeSJolly Shah * 16763436bdeSJolly Shah */ 16862f9134dSVenkatesh Yadav Abbarapu void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking) 16963436bdeSJolly Shah { 17063436bdeSJolly Shah uint32_t status; 17163436bdeSJolly Shah 17263436bdeSJolly Shah mmio_write_32(IPI_REG_BASE(local) + IPI_TRIG_OFFSET, 17363436bdeSJolly Shah IPI_BIT_MASK(remote)); 17463436bdeSJolly Shah if (is_blocking) { 17563436bdeSJolly Shah do { 17663436bdeSJolly Shah status = mmio_read_32(IPI_REG_BASE(local) + 17763436bdeSJolly Shah IPI_OBR_OFFSET); 17863436bdeSJolly Shah } while (status & IPI_BIT_MASK(remote)); 17963436bdeSJolly Shah } 18063436bdeSJolly Shah } 18163436bdeSJolly Shah 18263436bdeSJolly Shah /* ipi_mb_ack() - Ack IPI mailbox notification from the other end 18363436bdeSJolly Shah * 18463436bdeSJolly Shah * @local - local IPI ID 18563436bdeSJolly Shah * @remote - remote IPI ID 18663436bdeSJolly Shah * 18763436bdeSJolly Shah * It will clear the remote bit in the isr register. 18863436bdeSJolly Shah * 18963436bdeSJolly Shah */ 19063436bdeSJolly Shah void ipi_mb_ack(uint32_t local, uint32_t remote) 19163436bdeSJolly Shah { 19263436bdeSJolly Shah mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET, 19363436bdeSJolly Shah IPI_BIT_MASK(remote)); 19463436bdeSJolly Shah } 19563436bdeSJolly Shah 19663436bdeSJolly Shah /* ipi_mb_disable_irq() - Disable IPI mailbox notification interrupt 19763436bdeSJolly Shah * 19863436bdeSJolly Shah * @local - local IPI ID 19963436bdeSJolly Shah * @remote - remote IPI ID 20063436bdeSJolly Shah * 20163436bdeSJolly Shah * It will mask the remote bit in the idr register. 20263436bdeSJolly Shah * 20363436bdeSJolly Shah */ 20463436bdeSJolly Shah void ipi_mb_disable_irq(uint32_t local, uint32_t remote) 20563436bdeSJolly Shah { 20663436bdeSJolly Shah mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, 20763436bdeSJolly Shah IPI_BIT_MASK(remote)); 20863436bdeSJolly Shah } 20963436bdeSJolly Shah 21063436bdeSJolly Shah /* ipi_mb_enable_irq() - Enable IPI mailbox notification interrupt 21163436bdeSJolly Shah * 21263436bdeSJolly Shah * @local - local IPI ID 21363436bdeSJolly Shah * @remote - remote IPI ID 21463436bdeSJolly Shah * 21563436bdeSJolly Shah * It will mask the remote bit in the idr register. 21663436bdeSJolly Shah * 21763436bdeSJolly Shah */ 21863436bdeSJolly Shah void ipi_mb_enable_irq(uint32_t local, uint32_t remote) 21963436bdeSJolly Shah { 22063436bdeSJolly Shah mmio_write_32(IPI_REG_BASE(local) + IPI_IER_OFFSET, 22163436bdeSJolly Shah IPI_BIT_MASK(remote)); 22263436bdeSJolly Shah } 223