163436bdeSJolly Shah /* 2619bc13eSMichal Simek * Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved. 30ee2dc11SRajan Vaja * Copyright (c) 2020-2022, Xilinx, Inc. All rights reserved. 472eb16b7SDevanshi Chauhan Alpeshbhai * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved. 563436bdeSJolly Shah * 663436bdeSJolly Shah * SPDX-License-Identifier: BSD-3-Clause 763436bdeSJolly Shah */ 863436bdeSJolly Shah 963436bdeSJolly Shah /* 1063436bdeSJolly Shah * Xilinx IPI agent registers access management 1163436bdeSJolly Shah */ 1263436bdeSJolly Shah 1363436bdeSJolly Shah #include <errno.h> 1463436bdeSJolly Shah #include <string.h> 1563436bdeSJolly Shah 1663436bdeSJolly Shah #include <common/debug.h> 1763436bdeSJolly Shah #include <common/runtime_svc.h> 1863436bdeSJolly Shah #include <lib/bakery_lock.h> 1963436bdeSJolly Shah #include <lib/mmio.h> 2063436bdeSJolly Shah 2163436bdeSJolly Shah #include <ipi.h> 2263436bdeSJolly Shah #include <plat_private.h> 2372eb16b7SDevanshi Chauhan Alpeshbhai #include "pm_defs.h" 2463436bdeSJolly Shah 2563436bdeSJolly Shah /********************************************************************* 2663436bdeSJolly Shah * Macros definitions 2763436bdeSJolly Shah ********************************************************************/ 2863436bdeSJolly Shah 2963436bdeSJolly Shah /* IPI registers offsets macros */ 3063436bdeSJolly Shah #define IPI_TRIG_OFFSET 0x00U 3163436bdeSJolly Shah #define IPI_OBR_OFFSET 0x04U 3263436bdeSJolly Shah #define IPI_ISR_OFFSET 0x10U 3363436bdeSJolly Shah #define IPI_IMR_OFFSET 0x14U 3463436bdeSJolly Shah #define IPI_IER_OFFSET 0x18U 3563436bdeSJolly Shah #define IPI_IDR_OFFSET 0x1CU 3663436bdeSJolly Shah 3763436bdeSJolly Shah /* IPI register start offset */ 3863436bdeSJolly Shah #define IPI_REG_BASE(I) (ipi_table[(I)].ipi_reg_base) 3963436bdeSJolly Shah 4063436bdeSJolly Shah /* IPI register bit mask */ 4163436bdeSJolly Shah #define IPI_BIT_MASK(I) (ipi_table[(I)].ipi_bit_mask) 4263436bdeSJolly Shah 4363436bdeSJolly Shah /* IPI configuration table */ 44f4b8470fSBoyan Karatotev static const struct ipi_config *ipi_table; 4563436bdeSJolly Shah 4663436bdeSJolly Shah /* Total number of IPI */ 4763436bdeSJolly Shah static uint32_t ipi_total; 4863436bdeSJolly Shah 4963436bdeSJolly Shah /** 50de7ed953SPrasad Kummari * ipi_config_table_init() - Initialize IPI configuration data. 51de7ed953SPrasad Kummari * @ipi_config_table: IPI configuration table. 52de7ed953SPrasad Kummari * @total_ipi: Total number of IPI available. 5363436bdeSJolly Shah * 5463436bdeSJolly Shah */ 5563436bdeSJolly Shah void ipi_config_table_init(const struct ipi_config *ipi_config_table, 5663436bdeSJolly Shah uint32_t total_ipi) 5763436bdeSJolly Shah { 5863436bdeSJolly Shah ipi_table = ipi_config_table; 5963436bdeSJolly Shah ipi_total = total_ipi; 6063436bdeSJolly Shah } 6163436bdeSJolly Shah 62de7ed953SPrasad Kummari /** 63de7ed953SPrasad Kummari * is_ipi_mb_within_range() - verify if IPI mailbox is within range. 64de7ed953SPrasad Kummari * @local: local IPI ID. 65de7ed953SPrasad Kummari * @remote: remote IPI ID. 6663436bdeSJolly Shah * 67de7ed953SPrasad Kummari * Return: - 1 if within range, 0 if not. 6863436bdeSJolly Shah * 6963436bdeSJolly Shah */ 70*6df7184eSDevanshi Chauhan Alpeshbhai static inline uint32_t is_ipi_mb_within_range(uint32_t local, uint32_t remote) 7163436bdeSJolly Shah { 72*6df7184eSDevanshi Chauhan Alpeshbhai uint32_t ret = 1U; 7363436bdeSJolly Shah 748e9a5a51SNithin G if ((remote >= ipi_total) || (local >= ipi_total)) { 75*6df7184eSDevanshi Chauhan Alpeshbhai ret = 0U; 76eb0d2b17SVenkatesh Yadav Abbarapu } 7763436bdeSJolly Shah 7863436bdeSJolly Shah return ret; 7963436bdeSJolly Shah } 8063436bdeSJolly Shah 8163436bdeSJolly Shah /** 82de7ed953SPrasad Kummari * ipi_mb_validate() - validate IPI mailbox access. 83de7ed953SPrasad Kummari * @local: local IPI ID. 84de7ed953SPrasad Kummari * @remote: remote IPI ID. 85de7ed953SPrasad Kummari * @is_secure: indicate if the requester is from secure software. 8663436bdeSJolly Shah * 87de7ed953SPrasad Kummari * Return: 0 success, negative value for errors. 8863436bdeSJolly Shah * 8963436bdeSJolly Shah */ 90*6df7184eSDevanshi Chauhan Alpeshbhai int32_t ipi_mb_validate(uint32_t local, uint32_t remote, uint32_t is_secure) 9163436bdeSJolly Shah { 92*6df7184eSDevanshi Chauhan Alpeshbhai int32_t ret = 0; 9363436bdeSJolly Shah 94*6df7184eSDevanshi Chauhan Alpeshbhai if (is_ipi_mb_within_range(local, remote) == 0U) { 9563436bdeSJolly Shah ret = -EINVAL; 967d15b94bSMaheedhar Bollapalli } else if (IPI_IS_SECURE(local) && (is_secure == 0U)) { 9763436bdeSJolly Shah ret = -EPERM; 987d15b94bSMaheedhar Bollapalli } else if (IPI_IS_SECURE(remote) && (is_secure == 0U)) { 9963436bdeSJolly Shah ret = -EPERM; 10016de22d0SVenkatesh Yadav Abbarapu } else { 10116de22d0SVenkatesh Yadav Abbarapu /* To fix the misra 15.7 warning */ 102eb0d2b17SVenkatesh Yadav Abbarapu } 10363436bdeSJolly Shah 10463436bdeSJolly Shah return ret; 10563436bdeSJolly Shah } 10663436bdeSJolly Shah 10763436bdeSJolly Shah /** 10863436bdeSJolly Shah * ipi_mb_open() - Open IPI mailbox. 109de7ed953SPrasad Kummari * @local: local IPI ID. 110de7ed953SPrasad Kummari * @remote: remote IPI ID. 11163436bdeSJolly Shah * 11263436bdeSJolly Shah */ 11363436bdeSJolly Shah void ipi_mb_open(uint32_t local, uint32_t remote) 11463436bdeSJolly Shah { 11550ab1357SMaheedhar Bollapalli uint64_t idr_offset = (uint64_t)(IPI_REG_BASE(local) + IPI_IDR_OFFSET); 11650ab1357SMaheedhar Bollapalli uint64_t isr_offset = (uint64_t)(IPI_REG_BASE(local) + IPI_ISR_OFFSET); 11750ab1357SMaheedhar Bollapalli 11850ab1357SMaheedhar Bollapalli mmio_write_32(idr_offset, 11963436bdeSJolly Shah IPI_BIT_MASK(remote)); 12050ab1357SMaheedhar Bollapalli mmio_write_32(isr_offset, 12163436bdeSJolly Shah IPI_BIT_MASK(remote)); 12263436bdeSJolly Shah } 12363436bdeSJolly Shah 12463436bdeSJolly Shah /** 12563436bdeSJolly Shah * ipi_mb_release() - Open IPI mailbox. 126de7ed953SPrasad Kummari * @local: local IPI ID. 127de7ed953SPrasad Kummari * @remote: remote IPI ID. 12863436bdeSJolly Shah * 12963436bdeSJolly Shah */ 13063436bdeSJolly Shah void ipi_mb_release(uint32_t local, uint32_t remote) 13163436bdeSJolly Shah { 13250ab1357SMaheedhar Bollapalli uint64_t idr_offset = (uint64_t)(IPI_REG_BASE(local) + IPI_IDR_OFFSET); 13350ab1357SMaheedhar Bollapalli 13450ab1357SMaheedhar Bollapalli mmio_write_32(idr_offset, 13563436bdeSJolly Shah IPI_BIT_MASK(remote)); 13663436bdeSJolly Shah } 13763436bdeSJolly Shah 13863436bdeSJolly Shah /** 139de7ed953SPrasad Kummari * ipi_mb_enquire_status() - Enquire IPI mailbox status. 140de7ed953SPrasad Kummari * @local: local IPI ID. 141de7ed953SPrasad Kummari * @remote: remote IPI ID. 14263436bdeSJolly Shah * 143bdba3c84SDevanshi Chauhan Alpeshbhai * Return: 0 idle and positive value for pending sending or receiving. 14463436bdeSJolly Shah * 14563436bdeSJolly Shah */ 146bdba3c84SDevanshi Chauhan Alpeshbhai uint32_t ipi_mb_enquire_status(uint32_t local, uint32_t remote) 14763436bdeSJolly Shah { 148bdba3c84SDevanshi Chauhan Alpeshbhai uint32_t ret = (uint32_t)PM_RET_SUCCESS; 14963436bdeSJolly Shah uint32_t status; 15050ab1357SMaheedhar Bollapalli uint64_t obr_offset = (uint64_t)(IPI_REG_BASE(local) + IPI_OBR_OFFSET); 15150ab1357SMaheedhar Bollapalli uint64_t isr_offset = (uint64_t)(IPI_REG_BASE(local) + IPI_ISR_OFFSET); 15263436bdeSJolly Shah 15350ab1357SMaheedhar Bollapalli status = mmio_read_32(obr_offset); 154e2230375SMaheedhar Bollapalli if ((status & IPI_BIT_MASK(remote)) != 0U) { 15563436bdeSJolly Shah ret |= IPI_MB_STATUS_SEND_PENDING; 156eb0d2b17SVenkatesh Yadav Abbarapu } 15750ab1357SMaheedhar Bollapalli status = mmio_read_32(isr_offset); 158e2230375SMaheedhar Bollapalli if ((status & IPI_BIT_MASK(remote)) != 0U) { 15963436bdeSJolly Shah ret |= IPI_MB_STATUS_RECV_PENDING; 160eb0d2b17SVenkatesh Yadav Abbarapu } 16163436bdeSJolly Shah 16263436bdeSJolly Shah return ret; 16363436bdeSJolly Shah } 16463436bdeSJolly Shah 165de7ed953SPrasad Kummari /** 166de7ed953SPrasad Kummari * ipi_mb_notify() - Trigger IPI mailbox notification. 167de7ed953SPrasad Kummari * @local: local IPI ID. 168de7ed953SPrasad Kummari * @remote: remote IPI ID. 169de7ed953SPrasad Kummari * @is_blocking: if to trigger the notification in blocking mode or not. 17063436bdeSJolly Shah * 17163436bdeSJolly Shah * It sets the remote bit in the IPI agent trigger register. 17263436bdeSJolly Shah * 17363436bdeSJolly Shah */ 17462f9134dSVenkatesh Yadav Abbarapu void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking) 17563436bdeSJolly Shah { 17663436bdeSJolly Shah uint32_t status; 17750ab1357SMaheedhar Bollapalli uint64_t trig_offset = (uint64_t)(IPI_REG_BASE(local) + IPI_TRIG_OFFSET); 17850ab1357SMaheedhar Bollapalli uint64_t obr_offset = (uint64_t)(IPI_REG_BASE(local) + IPI_OBR_OFFSET); 17963436bdeSJolly Shah 18050ab1357SMaheedhar Bollapalli mmio_write_32(trig_offset, 18163436bdeSJolly Shah IPI_BIT_MASK(remote)); 182e2230375SMaheedhar Bollapalli if (is_blocking != 0U) { 18363436bdeSJolly Shah do { 18450ab1357SMaheedhar Bollapalli status = mmio_read_32(obr_offset); 185e2230375SMaheedhar Bollapalli } while ((status & IPI_BIT_MASK(remote)) != 0U); 18663436bdeSJolly Shah } 18763436bdeSJolly Shah } 18863436bdeSJolly Shah 189de7ed953SPrasad Kummari /** 190de7ed953SPrasad Kummari * ipi_mb_ack() - Ack IPI mailbox notification from the other end. 191de7ed953SPrasad Kummari * @local: local IPI ID. 192de7ed953SPrasad Kummari * @remote: remote IPI ID. 19363436bdeSJolly Shah * 19463436bdeSJolly Shah * It will clear the remote bit in the isr register. 19563436bdeSJolly Shah * 19663436bdeSJolly Shah */ 19763436bdeSJolly Shah void ipi_mb_ack(uint32_t local, uint32_t remote) 19863436bdeSJolly Shah { 19950ab1357SMaheedhar Bollapalli uint64_t isr_offset = (uint64_t)(IPI_REG_BASE(local) + IPI_ISR_OFFSET); 20050ab1357SMaheedhar Bollapalli 20150ab1357SMaheedhar Bollapalli mmio_write_32(isr_offset, 20263436bdeSJolly Shah IPI_BIT_MASK(remote)); 20363436bdeSJolly Shah } 20463436bdeSJolly Shah 205de7ed953SPrasad Kummari /** 206de7ed953SPrasad Kummari * ipi_mb_disable_irq() - Disable IPI mailbox notification interrupt. 207de7ed953SPrasad Kummari * @local: local IPI ID. 208de7ed953SPrasad Kummari * @remote: remote IPI ID. 20963436bdeSJolly Shah * 21063436bdeSJolly Shah * It will mask the remote bit in the idr register. 21163436bdeSJolly Shah * 21263436bdeSJolly Shah */ 21363436bdeSJolly Shah void ipi_mb_disable_irq(uint32_t local, uint32_t remote) 21463436bdeSJolly Shah { 21550ab1357SMaheedhar Bollapalli uint64_t idr_offset = (uint64_t)(IPI_REG_BASE(local) + IPI_IDR_OFFSET); 21650ab1357SMaheedhar Bollapalli 21750ab1357SMaheedhar Bollapalli mmio_write_32(idr_offset, 21863436bdeSJolly Shah IPI_BIT_MASK(remote)); 21963436bdeSJolly Shah } 22063436bdeSJolly Shah 221de7ed953SPrasad Kummari /** 222de7ed953SPrasad Kummari * ipi_mb_enable_irq() - Enable IPI mailbox notification interrupt. 223de7ed953SPrasad Kummari * @local: local IPI ID. 224de7ed953SPrasad Kummari * @remote: remote IPI ID. 22563436bdeSJolly Shah * 22663436bdeSJolly Shah * It will mask the remote bit in the idr register. 22763436bdeSJolly Shah * 22863436bdeSJolly Shah */ 22963436bdeSJolly Shah void ipi_mb_enable_irq(uint32_t local, uint32_t remote) 23063436bdeSJolly Shah { 23150ab1357SMaheedhar Bollapalli uint64_t ier_offset = (uint64_t)(IPI_REG_BASE(local) + IPI_IER_OFFSET); 23250ab1357SMaheedhar Bollapalli 23350ab1357SMaheedhar Bollapalli mmio_write_32(ier_offset, 23463436bdeSJolly Shah IPI_BIT_MASK(remote)); 23563436bdeSJolly Shah } 236