diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c index 90c670d..9e21067 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -542,7 +542,6 @@ */ void pm_get_callbackdata(uint32_t *data, size_t count) { - pm_ipi_buff_read_callb(data, count); - pm_ipi_irq_clear(); + pm_ipi_irq_clear(primary_proc); } diff --git a/plat/xilinx/zynqmp/pm_service/pm_common.h b/plat/xilinx/zynqmp/pm_service/pm_common.h index 03351c2..5dcbb0d 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_common.h +++ b/plat/xilinx/zynqmp/pm_service/pm_common.h @@ -21,13 +21,13 @@ /** * pm_ipi - struct for capturing IPI-channel specific info - * @mask mask for enabling/disabling and triggering the IPI - * @base base address for IPI + * @apu_ipi_id APU IPI agent ID + * @pmu_ipi_id PMU Agent ID * @buffer_base base address for payload buffer */ struct pm_ipi { - const unsigned int mask; - const uintptr_t base; + const uint32_t apu_ipi_id; + const uint32_t pmu_ipi_id; const uintptr_t buffer_base; }; diff --git a/plat/xilinx/zynqmp/pm_service/pm_ipi.c b/plat/xilinx/zynqmp/pm_service/pm_ipi.c index fdffde7..58faf0e 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_ipi.c +++ b/plat/xilinx/zynqmp/pm_service/pm_ipi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -8,28 +8,17 @@ #include #include #include +#include "../zynqmp_ipi.h" #include "../zynqmp_private.h" #include "pm_ipi.h" /* IPI message buffers */ #define IPI_BUFFER_BASEADDR 0xFF990000U -#define IPI_BUFFER_RPU_0_BASE (IPI_BUFFER_BASEADDR + 0x0U) -#define IPI_BUFFER_RPU_1_BASE (IPI_BUFFER_BASEADDR + 0x200U) #define IPI_BUFFER_APU_BASE (IPI_BUFFER_BASEADDR + 0x400U) -#define IPI_BUFFER_PL_0_BASE (IPI_BUFFER_BASEADDR + 0x600U) -#define IPI_BUFFER_PL_1_BASE (IPI_BUFFER_BASEADDR + 0x800U) -#define IPI_BUFFER_PL_2_BASE (IPI_BUFFER_BASEADDR + 0xA00U) -#define IPI_BUFFER_PL_3_BASE (IPI_BUFFER_BASEADDR + 0xC00U) #define IPI_BUFFER_PMU_BASE (IPI_BUFFER_BASEADDR + 0xE00U) -#define IPI_BUFFER_TARGET_RPU_0_OFFSET 0x0U -#define IPI_BUFFER_TARGET_RPU_1_OFFSET 0x40U #define IPI_BUFFER_TARGET_APU_OFFSET 0x80U -#define IPI_BUFFER_TARGET_PL_0_OFFSET 0xC0U -#define IPI_BUFFER_TARGET_PL_1_OFFSET 0x100U -#define IPI_BUFFER_TARGET_PL_2_OFFSET 0x140U -#define IPI_BUFFER_TARGET_PL_3_OFFSET 0x180U #define IPI_BUFFER_TARGET_PMU_OFFSET 0x1C0U #define IPI_BUFFER_MAX_WORDS 8 @@ -37,76 +26,33 @@ #define IPI_BUFFER_REQ_OFFSET 0x0U #define IPI_BUFFER_RESP_OFFSET 0x20U -/* IPI Base Address */ -#define IPI_BASEADDR 0XFF300000 - -/* APU's IPI registers */ -#define IPI_APU_ISR (IPI_BASEADDR + 0X00000010) -#define IPI_APU_IER (IPI_BASEADDR + 0X00000018) -#define IPI_APU_IDR (IPI_BASEADDR + 0X0000001C) -#define IPI_APU_IXR_PMU_0_MASK (1 << 16) - -#define IPI_TRIG_OFFSET 0 -#define IPI_OBS_OFFSET 4 - -/* Power Management IPI interrupt number */ -#define PM_INT_NUM 0 -#define IPI_PMU_PM_INT_BASE (IPI_PMU_0_TRIG + (PM_INT_NUM * 0x1000)) -#define IPI_PMU_PM_INT_MASK (IPI_APU_IXR_PMU_0_MASK << PM_INT_NUM) -#if (PM_INT_NUM < 0 || PM_INT_NUM > 3) - #error PM_INT_NUM value out of range -#endif - -#define IPI_APU_MASK 1U - DEFINE_BAKERY_LOCK(pm_secure_lock); const struct pm_ipi apu_ipi = { - .mask = IPI_APU_MASK, - .base = IPI_BASEADDR, + .apu_ipi_id = IPI_ID_APU, + .pmu_ipi_id = IPI_ID_PMU0, .buffer_base = IPI_BUFFER_APU_BASE, }; /** * pm_ipi_init() - Initialize IPI peripheral for communication with PMU * + * @proc Pointer to the processor who is initiating request * @return On success, the initialization function must return 0. * Any other return value will cause the framework to ignore * the service * * Called from pm_setup initialization function */ -int pm_ipi_init(void) +int pm_ipi_init(const struct pm_proc *proc) { bakery_lock_init(&pm_secure_lock); - - /* IPI Interrupts Clear & Disable */ - mmio_write_32(IPI_APU_ISR, 0xffffffff); - mmio_write_32(IPI_APU_IDR, 0xffffffff); + ipi_mb_open(proc->ipi->apu_ipi_id, proc->ipi->pmu_ipi_id); return 0; } /** - * pm_ipi_wait() - wait for pmu to handle request - * @proc proc which is waiting for PMU to handle request - */ -static enum pm_ret_status pm_ipi_wait(const struct pm_proc *proc) -{ - int status; - - /* Wait until previous interrupt is handled by PMU */ - do { - status = mmio_read_32(proc->ipi->base + IPI_OBS_OFFSET) & - IPI_PMU_PM_INT_MASK; - /* TODO: 1) Use timer to add delay between read attempts */ - /* TODO: 2) Return PM_RET_ERR_TIMEOUT if this times out */ - } while (status); - - return PM_RET_SUCCESS; -} - -/** * pm_ipi_send_common() - Sends IPI request to the PMU * @proc Pointer to the processor who is initiating request * @payload API id and call arguments to be written in IPI buffer @@ -124,16 +70,13 @@ IPI_BUFFER_TARGET_PMU_OFFSET + IPI_BUFFER_REQ_OFFSET; - /* Wait until previous interrupt is handled by PMU */ - pm_ipi_wait(proc); - /* Write payload into IPI buffer */ for (size_t i = 0; i < PAYLOAD_ARG_CNT; i++) { mmio_write_32(buffer_base + offset, payload[i]); offset += PAYLOAD_ARG_SIZE; } /* Generate IPI to PMU */ - mmio_write_32(proc->ipi->base + IPI_TRIG_OFFSET, IPI_PMU_PM_INT_MASK); + ipi_mb_notify(proc->ipi->apu_ipi_id, proc->ipi->pmu_ipi_id, 1); return PM_RET_SUCCESS; } @@ -178,8 +121,6 @@ IPI_BUFFER_TARGET_PMU_OFFSET + IPI_BUFFER_RESP_OFFSET; - pm_ipi_wait(proc); - /* * Read response from IPI buffer * buf-0: success or error+reason @@ -250,17 +191,12 @@ return ret; } -void pm_ipi_irq_enable(void) +void pm_ipi_irq_enable(const struct pm_proc *proc) { - mmio_write_32(IPI_APU_IER, IPI_APU_IXR_PMU_0_MASK); + ipi_mb_enable_irq(proc->ipi->apu_ipi_id, proc->ipi->pmu_ipi_id); } -void pm_ipi_irq_disable(void) +void pm_ipi_irq_clear(const struct pm_proc *proc) { - mmio_write_32(IPI_APU_IDR, IPI_APU_IXR_PMU_0_MASK); -} - -void pm_ipi_irq_clear(void) -{ - mmio_write_32(IPI_APU_ISR, IPI_APU_IXR_PMU_0_MASK); + ipi_mb_ack(proc->ipi->apu_ipi_id, proc->ipi->pmu_ipi_id); } diff --git a/plat/xilinx/zynqmp/pm_service/pm_ipi.h b/plat/xilinx/zynqmp/pm_service/pm_ipi.h index a76298b..e6b36f5 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_ipi.h +++ b/plat/xilinx/zynqmp/pm_service/pm_ipi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -9,7 +9,7 @@ #include "pm_common.h" -int pm_ipi_init(void); +int pm_ipi_init(const struct pm_proc *proc); enum pm_ret_status pm_ipi_send(const struct pm_proc *proc, uint32_t payload[PAYLOAD_ARG_CNT]); @@ -17,8 +17,7 @@ uint32_t payload[PAYLOAD_ARG_CNT], unsigned int *value, size_t count); void pm_ipi_buff_read_callb(unsigned int *value, size_t count); -void pm_ipi_irq_enable(void); -void pm_ipi_irq_disable(void); -void pm_ipi_irq_clear(void); +void pm_ipi_irq_enable(const struct pm_proc *proc); +void pm_ipi_irq_clear(const struct pm_proc *proc); #endif /* _PM_IPI_H_ */ diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c index f4e679b..fb64bc5 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c +++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -49,22 +49,25 @@ */ int pm_setup(void) { - int status; + int status, ret; if (!zynqmp_is_pmu_up()) return -ENODEV; - status = pm_ipi_init(); + status = pm_ipi_init(primary_proc); - if (status == 0) + if (status >= 0) { INFO("BL31: PM Service Init Complete: API v%d.%d\n", PM_VERSION_MAJOR, PM_VERSION_MINOR); - else + ret = 0; + } else { INFO("BL31: PM Service Init Failed, Error Code %d!\n", status); + ret = status; + } pm_down = status; - return status; + return ret; } /** @@ -163,7 +166,7 @@ * Even if we were wrong, it would not enable the IRQ in * the GIC. */ - pm_ipi_irq_enable(); + pm_ipi_irq_enable(primary_proc); SMC_RET1(handle, (uint64_t)ret | ((uint64_t)pm_ctx.api_version << 32));