diff --git a/plat/xilinx/common/include/ipi.h b/plat/xilinx/common/include/ipi.h index c9fd8d1..483902e 100644 --- a/plat/xilinx/common/include/ipi.h +++ b/plat/xilinx/common/include/ipi.h @@ -12,6 +12,26 @@ #include /********************************************************************* + * IPI mailbox status macros + ********************************************************************/ +#define IPI_MB_STATUS_IDLE 0 +#define IPI_MB_STATUS_SEND_PENDING 1 +#define IPI_MB_STATUS_RECV_PENDING 2 + +/********************************************************************* + * IPI mailbox call is secure or not macros + ********************************************************************/ +#define IPI_MB_CALL_NOTSECURE 0 +#define IPI_MB_CALL_SECURE 1 + +/********************************************************************* + * IPI secure check + ********************************************************************/ +#define IPI_SECURE_MASK 0x1U +#define IPI_IS_SECURE(I) ((ipi_table[(I)].secure_only & \ + IPI_SECURE_MASK) ? 1 : 0) + +/********************************************************************* * Struct definitions ********************************************************************/ @@ -22,4 +42,36 @@ unsigned char secure_only; }; +/********************************************************************* + * IPI APIs declarations + ********************************************************************/ + +/* Initialize IPI configuration table */ +void ipi_config_table_init(const struct ipi_config *ipi_table, + uint32_t total_ipi); + +/* Validate IPI mailbox access */ +int ipi_mb_validate(uint32_t local, uint32_t remote, unsigned int is_secure); + +/* Open the IPI mailbox */ +void ipi_mb_open(uint32_t local, uint32_t remote); + +/* Release the IPI mailbox */ +void ipi_mb_release(uint32_t local, uint32_t remote); + +/* Enquire IPI mailbox status */ +int ipi_mb_enquire_status(uint32_t local, uint32_t remote); + +/* Trigger notification on the IPI mailbox */ +void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking); + +/* Ack IPI mailbox notification */ +void ipi_mb_ack(uint32_t local, uint32_t remote); + +/* Disable IPI mailbox notification interrupt */ +void ipi_mb_disable_irq(uint32_t local, uint32_t remote); + +/* Enable IPI mailbox notification interrupt */ +void ipi_mb_enable_irq(uint32_t local, uint32_t remote); + #endif /* IPI_H */ diff --git a/plat/xilinx/common/ipi.c b/plat/xilinx/common/ipi.c new file mode 100644 index 0000000..0b8020b --- /dev/null +++ b/plat/xilinx/common/ipi.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Xilinx IPI agent registers access management + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +/********************************************************************* + * Macros definitions + ********************************************************************/ + +/* IPI registers offsets macros */ +#define IPI_TRIG_OFFSET 0x00U +#define IPI_OBR_OFFSET 0x04U +#define IPI_ISR_OFFSET 0x10U +#define IPI_IMR_OFFSET 0x14U +#define IPI_IER_OFFSET 0x18U +#define IPI_IDR_OFFSET 0x1CU + +/* IPI register start offset */ +#define IPI_REG_BASE(I) (ipi_table[(I)].ipi_reg_base) + +/* IPI register bit mask */ +#define IPI_BIT_MASK(I) (ipi_table[(I)].ipi_bit_mask) + +/* IPI configuration table */ +const static struct ipi_config *ipi_table; + +/* Total number of IPI */ +static uint32_t ipi_total; + +/** + * ipi_config_init() - Initialize IPI configuration data + * + * @ipi_config_table - IPI configuration table + * @ipi_total - Total number of IPI available + * + */ +void ipi_config_table_init(const struct ipi_config *ipi_config_table, + uint32_t total_ipi) +{ + ipi_table = ipi_config_table; + ipi_total = total_ipi; +} + +/* is_ipi_mb_within_range() - verify if IPI mailbox is within range + * + * @local - local IPI ID + * @remote - remote IPI ID + * + * return - 1 if within range, 0 if not + */ +static inline int is_ipi_mb_within_range(uint32_t local, uint32_t remote) +{ + int ret = 1; + + if (remote >= ipi_total || local >= ipi_total) + ret = 0; + + return ret; +} + +/** + * ipi_mb_validate() - validate IPI mailbox access + * + * @local - local IPI ID + * @remote - remote IPI ID + * @is_secure - indicate if the requester is from secure software + * + * return - 0 success, negative value for errors + */ +int ipi_mb_validate(uint32_t local, uint32_t remote, unsigned int is_secure) +{ + int ret = 0; + + if (!is_ipi_mb_within_range(local, remote)) + ret = -EINVAL; + else if (IPI_IS_SECURE(local) && !is_secure) + ret = -EPERM; + else if (IPI_IS_SECURE(remote) && !is_secure) + ret = -EPERM; + + return ret; +} + +/** + * ipi_mb_open() - Open IPI mailbox. + * + * @local - local IPI ID + * @remote - remote IPI ID + * + */ +void ipi_mb_open(uint32_t local, uint32_t remote) +{ + mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, + IPI_BIT_MASK(remote)); + mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET, + IPI_BIT_MASK(remote)); +} + +/** + * ipi_mb_release() - Open IPI mailbox. + * + * @local - local IPI ID + * @remote - remote IPI ID + * + */ +void ipi_mb_release(uint32_t local, uint32_t remote) +{ + mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, + IPI_BIT_MASK(remote)); +} + +/** + * ipi_mb_enquire_status() - Enquire IPI mailbox status + * + * @local - local IPI ID + * @remote - remote IPI ID + * + * return - 0 idle, positive value for pending sending or receiving, + * negative value for errors + */ +int ipi_mb_enquire_status(uint32_t local, uint32_t remote) +{ + int ret = 0; + uint32_t status; + + status = mmio_read_32(IPI_REG_BASE(local) + IPI_OBR_OFFSET); + if (status & IPI_BIT_MASK(remote)) + ret |= IPI_MB_STATUS_SEND_PENDING; + status = mmio_read_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET); + if (status & IPI_BIT_MASK(remote)) + ret |= IPI_MB_STATUS_RECV_PENDING; + + return ret; +} + +/* ipi_mb_notify() - Trigger IPI mailbox notification + * + * @local - local IPI ID + * @remote - remote IPI ID + * @is_blocking - if to trigger the notification in blocking mode or not. + * + * It sets the remote bit in the IPI agent trigger register. + * + */ +void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking) +{ + uint32_t status; + + mmio_write_32(IPI_REG_BASE(local) + IPI_TRIG_OFFSET, + IPI_BIT_MASK(remote)); + if (is_blocking) { + do { + status = mmio_read_32(IPI_REG_BASE(local) + + IPI_OBR_OFFSET); + } while (status & IPI_BIT_MASK(remote)); + } +} + +/* ipi_mb_ack() - Ack IPI mailbox notification from the other end + * + * @local - local IPI ID + * @remote - remote IPI ID + * + * It will clear the remote bit in the isr register. + * + */ +void ipi_mb_ack(uint32_t local, uint32_t remote) +{ + mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET, + IPI_BIT_MASK(remote)); +} + +/* ipi_mb_disable_irq() - Disable IPI mailbox notification interrupt + * + * @local - local IPI ID + * @remote - remote IPI ID + * + * It will mask the remote bit in the idr register. + * + */ +void ipi_mb_disable_irq(uint32_t local, uint32_t remote) +{ + mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, + IPI_BIT_MASK(remote)); +} + +/* ipi_mb_enable_irq() - Enable IPI mailbox notification interrupt + * + * @local - local IPI ID + * @remote - remote IPI ID + * + * It will mask the remote bit in the idr register. + * + */ +void ipi_mb_enable_irq(uint32_t local, uint32_t remote) +{ + mmio_write_32(IPI_REG_BASE(local) + IPI_IER_OFFSET, + IPI_BIT_MASK(remote)); +} diff --git a/plat/xilinx/zynqmp/include/plat_ipi.h b/plat/xilinx/zynqmp/include/plat_ipi.h index 15d7ab0..c6da241 100644 --- a/plat/xilinx/zynqmp/include/plat_ipi.h +++ b/plat/xilinx/zynqmp/include/plat_ipi.h @@ -28,50 +28,10 @@ #define IPI_ID_PL3 10U /********************************************************************* - * IPI mailbox status macros + * Platform specific IPI API declarations ********************************************************************/ -#define IPI_MB_STATUS_IDLE 0 -#define IPI_MB_STATUS_SEND_PENDING 1 -#define IPI_MB_STATUS_RECV_PENDING 2 -/********************************************************************* - * IPI mailbox call is secure or not macros - ********************************************************************/ -#define IPI_MB_CALL_NOTSECURE 0 -#define IPI_MB_CALL_SECURE 1 - -/********************************************************************* - * IPI APIs declarations - ********************************************************************/ /* Configure IPI table for zynqmp */ void zynqmp_ipi_config_table_init(void); -/* Initialize IPI configuration table */ -void ipi_config_table_init(const struct ipi_config *ipi_table, - uint32_t total_ipi); - -/* Validate IPI mailbox access */ -int ipi_mb_validate(uint32_t local, uint32_t remote, unsigned int is_secure); - -/* Open the IPI mailbox */ -void ipi_mb_open(uint32_t local, uint32_t remote); - -/* Release the IPI mailbox */ -void ipi_mb_release(uint32_t local, uint32_t remote); - -/* Enquire IPI mailbox status */ -int ipi_mb_enquire_status(uint32_t local, uint32_t remote); - -/* Trigger notification on the IPI mailbox */ -void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking); - -/* Ack IPI mailbox notification */ -void ipi_mb_ack(uint32_t local, uint32_t remote); - -/* Disable IPI mailbox notification interrupt */ -void ipi_mb_disable_irq(uint32_t local, uint32_t remote); - -/* Enable IPI mailbox notification interrupt */ -void ipi_mb_enable_irq(uint32_t local, uint32_t remote); - #endif /* PLAT_IPI_H */ diff --git a/plat/xilinx/zynqmp/ipi_mailbox_service/ipi_mailbox_svc.c b/plat/xilinx/zynqmp/ipi_mailbox_service/ipi_mailbox_svc.c index 932d1e7..c499d78 100644 --- a/plat/xilinx/zynqmp/ipi_mailbox_service/ipi_mailbox_svc.c +++ b/plat/xilinx/zynqmp/ipi_mailbox_service/ipi_mailbox_svc.c @@ -15,6 +15,8 @@ #include #include #include + +#include #include #include diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk index a4ffd6c..f0c7599 100644 --- a/plat/xilinx/zynqmp/platform.mk +++ b/plat/xilinx/zynqmp/platform.mk @@ -65,6 +65,7 @@ plat/arm/common/arm_common.c \ plat/arm/common/arm_gicv2.c \ plat/common/plat_gicv2.c \ + plat/xilinx/common/ipi.c \ plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S \ plat/xilinx/zynqmp/aarch64/zynqmp_common.c diff --git a/plat/xilinx/zynqmp/pm_service/pm_ipi.c b/plat/xilinx/zynqmp/pm_service/pm_ipi.c index 88e23f0..a9f0d75 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_ipi.c +++ b/plat/xilinx/zynqmp/pm_service/pm_ipi.c @@ -7,6 +7,8 @@ #include #include #include + +#include #include #include #include diff --git a/plat/xilinx/zynqmp/zynqmp_ipi.c b/plat/xilinx/zynqmp/zynqmp_ipi.c index fd4804d..f57369f 100644 --- a/plat/xilinx/zynqmp/zynqmp_ipi.c +++ b/plat/xilinx/zynqmp/zynqmp_ipi.c @@ -20,38 +20,6 @@ #include #include -/********************************************************************* - * Macros definitions - ********************************************************************/ - -/* IPI registers base address */ -#define IPI_REGS_BASE 0xFF300000U - -/* IPI registers offsets macros */ -#define IPI_TRIG_OFFSET 0x00U -#define IPI_OBR_OFFSET 0x04U -#define IPI_ISR_OFFSET 0x10U -#define IPI_IMR_OFFSET 0x14U -#define IPI_IER_OFFSET 0x18U -#define IPI_IDR_OFFSET 0x1CU - -/* IPI register start offset */ -#define IPI_REG_BASE(I) (ipi_table[(I)].ipi_reg_base) - -/* IPI register bit mask */ -#define IPI_BIT_MASK(I) (ipi_table[(I)].ipi_bit_mask) - -/* IPI secure check */ -#define IPI_SECURE_MASK 0x1U -#define IPI_IS_SECURE(I) ((ipi_table[(I)].secure_only & \ - IPI_SECURE_MASK) ? 1 : 0) - -/* IPI configuration table */ -const static struct ipi_config *ipi_table; - -/* Total number of IPI */ -static uint32_t ipi_total; - /* Zynqmp ipi configuration table */ const static struct ipi_config zynqmp_ipi_table[] = { /* APU IPI */ @@ -130,174 +98,3 @@ { ipi_config_table_init(zynqmp_ipi_table, ARRAY_SIZE(zynqmp_ipi_table)); } - -/** - * ipi_config_table_init() - Initialize IPI configuration data - * - * @ipi_config_table - IPI configuration table - * @ipi_total - Total number of IPI available - * - */ -void ipi_config_table_init(const struct ipi_config *ipi_config_table, - uint32_t total_ipi) -{ - ipi_table = ipi_config_table; - ipi_total = total_ipi; -} - -/* is_ipi_mb_within_range() - verify if IPI mailbox is within range - * - * @local - local IPI ID - * @remote - remote IPI ID - * - * return - 1 if within range, 0 if not - */ -static inline int is_ipi_mb_within_range(uint32_t local, uint32_t remote) -{ - int ret = 1; - - if (remote >= ipi_total || local >= ipi_total) - ret = 0; - - return ret; -} - -/** - * ipi_mb_validate() - validate IPI mailbox access - * - * @local - local IPI ID - * @remote - remote IPI ID - * @is_secure - indicate if the requester is from secure software - * - * return - 0 success, negative value for errors - */ -int ipi_mb_validate(uint32_t local, uint32_t remote, unsigned int is_secure) -{ - int ret = 0; - - if (!is_ipi_mb_within_range(local, remote)) - ret = -EINVAL; - else if (IPI_IS_SECURE(local) && !is_secure) - ret = -EPERM; - else if (IPI_IS_SECURE(remote) && !is_secure) - ret = -EPERM; - - return ret; -} - -/** - * ipi_mb_open() - Open IPI mailbox. - * - * @local - local IPI ID - * @remote - remote IPI ID - * - */ -void ipi_mb_open(uint32_t local, uint32_t remote) -{ - mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, - IPI_BIT_MASK(remote)); - mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET, - IPI_BIT_MASK(remote)); -} - -/** - * ipi_mb_release() - Open IPI mailbox. - * - * @local - local IPI ID - * @remote - remote IPI ID - * - */ -void ipi_mb_release(uint32_t local, uint32_t remote) -{ - mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, - IPI_BIT_MASK(remote)); -} - -/** - * ipi_mb_enquire_status() - Enquire IPI mailbox status - * - * @local - local IPI ID - * @remote - remote IPI ID - * - * return - 0 idle, positive value for pending sending or receiving, - * negative value for errors - */ -int ipi_mb_enquire_status(uint32_t local, uint32_t remote) -{ - int ret = 0; - uint32_t status; - - status = mmio_read_32(IPI_REG_BASE(local) + IPI_OBR_OFFSET); - if (status & IPI_BIT_MASK(remote)) - ret |= IPI_MB_STATUS_SEND_PENDING; - status = mmio_read_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET); - if (status & IPI_BIT_MASK(remote)) - ret |= IPI_MB_STATUS_RECV_PENDING; - - return ret; -} - -/* ipi_mb_notify() - Trigger IPI mailbox notification - * - * @local - local IPI ID - * @remote - remote IPI ID - * @is_blocking - if to trigger the notification in blocking mode or not. - * - * It sets the remote bit in the IPI agent trigger register. - * - */ -void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking) -{ - uint32_t status; - - mmio_write_32(IPI_REG_BASE(local) + IPI_TRIG_OFFSET, - IPI_BIT_MASK(remote)); - if (is_blocking) { - do { - status = mmio_read_32(IPI_REG_BASE(local) + - IPI_OBR_OFFSET); - } while (status & IPI_BIT_MASK(remote)); - } -} - -/* ipi_mb_ack() - Ack IPI mailbox notification from the other end - * - * @local - local IPI ID - * @remote - remote IPI ID - * - * It will clear the remote bit in the isr register. - * - */ -void ipi_mb_ack(uint32_t local, uint32_t remote) -{ - mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET, - IPI_BIT_MASK(remote)); -} - -/* ipi_mb_disable_irq() - Disable IPI mailbox notification interrupt - * - * @local - local IPI ID - * @remote - remote IPI ID - * - * It will mask the remote bit in the idr register. - * - */ -void ipi_mb_disable_irq(uint32_t local, uint32_t remote) -{ - mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, - IPI_BIT_MASK(remote)); -} - -/* ipi_mb_enable_irq() - Enable IPI mailbox notification interrupt - * - * @local - local IPI ID - * @remote - remote IPI ID - * - * It will mask the remote bit in the idr register. - * - */ -void ipi_mb_enable_irq(uint32_t local, uint32_t remote) -{ - mmio_write_32(IPI_REG_BASE(local) + IPI_IER_OFFSET, - IPI_BIT_MASK(remote)); -}