From e1cb4da465d13bb7bc641985863421d8ec36d8f7 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Wed, 22 Jun 2016 09:02:56 -0700 Subject: zynqmp: Add support for generic_delay_timer Initialize the generic_delay_timer in the zynqmp port. Signed-off-by: Soren Brinkmann --- plat/xilinx/zynqmp/aarch64/zynqmp_common.c | 3 +++ plat/xilinx/zynqmp/platform.mk | 2 ++ 2 files changed, 5 insertions(+) diff --git a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c index 1ba301de..d1b52e1a 100644 --- a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c +++ b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c @@ -29,6 +29,7 @@ */ #include +#include #include #include #include @@ -289,6 +290,8 @@ void zynqmp_config_setup(void) /* Program freq register in System counter and enable system counter. */ mmio_write_32(IOU_SCNTRS_BASEFREQ, zynqmp_get_system_timer_freq()); mmio_write_32(IOU_SCNTRS_CONTROL, IOU_SCNTRS_CONTROL_EN); + + generic_delay_timer_init(); } unsigned int plat_get_syscnt_freq2(void) diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk index 9bde5ff6..83cb1102 100644 --- a/plat/xilinx/zynqmp/platform.mk +++ b/plat/xilinx/zynqmp/platform.mk @@ -64,6 +64,8 @@ PLAT_INCLUDES := -Iinclude/plat/arm/common/ \ PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \ lib/xlat_tables/aarch64/xlat_tables.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ drivers/arm/gic/common/gic_common.c \ drivers/arm/gic/v2/gicv2_main.c \ drivers/arm/gic/v2/gicv2_helpers.c \ -- cgit From 2c239f7c2ab9979b2c3f151ed010ba3fb324f910 Mon Sep 17 00:00:00 2001 From: Mirela Simonovic Date: Fri, 17 Jun 2016 16:17:23 +0200 Subject: zynqmp: pm: Added NODE_IPI_RPU_0 node definition in pm_defs Nodes represent IPI dedicated to the RPU (not accessible by APU) Signed-off-by: Mirela Simonovic --- plat/xilinx/zynqmp/pm_service/pm_defs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h index adeec64b..a8921e7b 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_defs.h +++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h @@ -143,6 +143,7 @@ enum pm_node_id { NODE_IOPLL, NODE_DDR, NODE_IPI_APU, + NODE_IPI_RPU_0, }; enum pm_request_ack { -- cgit From 538957d85bf6d804139f329a8838275e95988a5e Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Wed, 6 Jul 2016 15:11:31 -0700 Subject: zynqmp: Set RESET_TO_BL31 through platform.mk ZynqMP only supports builds with RESET_TO_BL31=1. Set this option through the platform makefile on default. Signed-off-by: Soren Brinkmann --- plat/xilinx/zynqmp/platform.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk index 83cb1102..33c55a05 100644 --- a/plat/xilinx/zynqmp/platform.mk +++ b/plat/xilinx/zynqmp/platform.mk @@ -31,6 +31,7 @@ PROGRAMMABLE_RESET_ADDRESS := 1 PSCI_EXTENDED_STATE_ID := 1 A53_DISABLE_NON_TEMPORAL_HINT := 0 SEPARATE_CODE_AND_RODATA := 1 +RESET_TO_BL31 := 1 ifdef ZYNQMP_ATF_MEM_BASE $(eval $(call add_define,ZYNQMP_ATF_MEM_BASE)) -- cgit From 06526c9797c4f036e612602fb5a2ca20d80ad1bf Mon Sep 17 00:00:00 2001 From: Naga Sureshkumar Relli Date: Fri, 1 Jul 2016 12:46:43 +0530 Subject: zynqmp: Add RW access to L2ACTLR_EL1 and CPUACTLR_EL1 Arm provided error injection support. To enable this error injection, we need to set L2DEIEN in L2ACTLR_EL1 register and L1DEIEN in CPUACTLR_EL1 register. This is needed for our cortexa53 edac linux driver testing. These registers need write access from non secure EL1 i.e linux at the time of setting the above bits. Signed-off-by: Naga Sureshkumar Relli --- plat/xilinx/zynqmp/bl31_zynqmp_setup.c | 20 ++++++++++++++++++++ plat/xilinx/zynqmp/zynqmp_def.h | 4 ++++ 2 files changed, 24 insertions(+) diff --git a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c index d878b86b..c05b094e 100644 --- a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c +++ b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c @@ -118,11 +118,31 @@ void bl31_early_platform_setup(bl31_params_t *from_bl2, NOTICE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc); } +/* Enable the test setup */ +#ifndef ZYNQMP_TESTING +static void zynqmp_testing_setup(void) { } +#else +static void zynqmp_testing_setup(void) +{ + uint32_t actlr_el3, actlr_el2; + + /* Enable CPU ACTLR AND L2ACTLR RW access from non-secure world */ + actlr_el3 = read_actlr_el3(); + actlr_el2 = read_actlr_el2(); + + actlr_el3 |= ACTLR_EL3_L2ACTLR_BIT | ACTLR_EL3_CPUACTLR_BIT; + actlr_el2 |= ACTLR_EL3_L2ACTLR_BIT | ACTLR_EL3_CPUACTLR_BIT; + write_actlr_el3(actlr_el3); + write_actlr_el2(actlr_el2); +} +#endif + void bl31_platform_setup(void) { /* Initialize the gic cpu and distributor interfaces */ plat_arm_gic_driver_init(); plat_arm_gic_init(); + zynqmp_testing_setup(); } void bl31_plat_runtime_setup(void) diff --git a/plat/xilinx/zynqmp/zynqmp_def.h b/plat/xilinx/zynqmp/zynqmp_def.h index 4bb332e0..65bc25f8 100644 --- a/plat/xilinx/zynqmp/zynqmp_def.h +++ b/plat/xilinx/zynqmp/zynqmp_def.h @@ -201,4 +201,8 @@ #define ZYNQMP_CSU_VERSION_OFFSET 0x44 +/* Access control register defines */ +#define ACTLR_EL3_L2ACTLR_BIT (1 << 6) +#define ACTLR_EL3_CPUACTLR_BIT (1 << 0) + #endif /* __ZYNQMP_DEF_H__ */ -- cgit From 0ab6a2429b88015c809b3feff8eb645a1babdf6e Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Fri, 15 Jul 2016 06:23:37 -0700 Subject: zynqmp: Change default BL31 address space The OCM space was reorganized to use the space more efficiently. Adjust the default ATF location to be aligned with other ZynqMP software components. Signed-off-by: Soren Brinkmann --- plat/xilinx/zynqmp/include/platform_def.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plat/xilinx/zynqmp/include/platform_def.h b/plat/xilinx/zynqmp/include/platform_def.h index a35bd129..a8b3646c 100644 --- a/plat/xilinx/zynqmp/include/platform_def.h +++ b/plat/xilinx/zynqmp/include/platform_def.h @@ -56,8 +56,7 @@ * little space for growth. */ #ifndef ZYNQMP_ATF_MEM_BASE -# define BL31_BASE 0xfffe5000 -# define BL31_PROGBITS_LIMIT 0xffffa000 +# define BL31_BASE 0xfffea000 # define BL31_LIMIT 0xffffffff #else # define BL31_BASE (ZYNQMP_ATF_MEM_BASE) -- cgit From 797ab652fbd33d9ef12dc641edcb665808c4d2aa Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 25 Jul 2016 10:33:53 -0700 Subject: zynqmp: Increase MAX_XLAT_TABLES When moving the ATF into the DRAM address space an additional translation table is required. Reported-by: Michal Simek Signed-off-by: Soren Brinkmann --- plat/xilinx/zynqmp/include/platform_def.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/plat/xilinx/zynqmp/include/platform_def.h b/plat/xilinx/zynqmp/include/platform_def.h index a8b3646c..3c1a9e5c 100644 --- a/plat/xilinx/zynqmp/include/platform_def.h +++ b/plat/xilinx/zynqmp/include/platform_def.h @@ -100,11 +100,7 @@ ******************************************************************************/ #define ADDR_SPACE_SIZE (1ull << 32) #define MAX_MMAP_REGIONS 7 -#if IMAGE_BL32 -# define MAX_XLAT_TABLES 5 -#else -# define MAX_XLAT_TABLES 4 -#endif +#define MAX_XLAT_TABLES 5 #define CACHE_WRITEBACK_SHIFT 6 #define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) -- cgit From eccc7cde9f3eba2de4e533dcc7fde117adbf59cc Mon Sep 17 00:00:00 2001 From: Stefan Krsmanovic Date: Mon, 9 May 2016 18:00:47 +0200 Subject: zynqmp: Add simple implementation of zynqmp_validate_power_state() Implementation is based on arm_validate_power_state(). This function is called during CPU_SUSPEND PSCI call to validate power_state parameter. If state is valid this function populate it in req_state array as power domain level specific local state. ATF platform migration guide chapter 2.2 defines this function as mandatory for PSCIv1.0 CPU_SUSPEND support. Signed-off-by: Stefan Krsmanovic --- plat/xilinx/zynqmp/plat_psci.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/plat/xilinx/zynqmp/plat_psci.c b/plat/xilinx/zynqmp/plat_psci.c index 56eb742a..f0e260de 100644 --- a/plat/xilinx/zynqmp/plat_psci.c +++ b/plat/xilinx/zynqmp/plat_psci.c @@ -308,7 +308,20 @@ int zynqmp_validate_power_state(unsigned int power_state, { VERBOSE("%s: power_state: 0x%x\n", __func__, power_state); - /* FIXME: populate req_state */ + int pstate = psci_get_pstate_type(power_state); + + assert(req_state); + + /* Sanity check the requested state */ + if (pstate == PSTATE_TYPE_STANDBY) + req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE; + else + req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE; + + /* We expect the 'state id' to be zero */ + if (psci_get_pstate_id(power_state)) + return PSCI_E_INVALID_PARAMS; + return PSCI_E_SUCCESS; } -- cgit From 95fd990fe601af26b3d4e0aa34aa2d2aad70de30 Mon Sep 17 00:00:00 2001 From: Filip Drazic Date: Wed, 20 Jul 2016 17:17:39 +0200 Subject: zynqmp: pm: Provide state argument to the pm_self_suspend API call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The state argument of the pm_self_suspend API encodes the state to which the APU intends to suspend. The state can be: - PM_APU_STATE_CPU_IDLE - processor power down, all memories remain on - PM_APU_STATE_SUSPEND_TO_RAM - all processors powered down, L2$ powered down, all OCM banks in retention and DDR in self-refresh. The calls for setting requirements for L2$ and OCM banks are now redundant and removed. Signed-off-by: Filip Drazic [ sb - remove redundant #defines ] Signed-off-by: Sören Brinkmann --- plat/xilinx/zynqmp/plat_psci.c | 12 ++++----- plat/xilinx/zynqmp/pm_service/pm_api_sys.c | 2 +- plat/xilinx/zynqmp/pm_service/pm_client.c | 40 +----------------------------- plat/xilinx/zynqmp/pm_service/pm_defs.h | 4 +++ 4 files changed, 12 insertions(+), 46 deletions(-) diff --git a/plat/xilinx/zynqmp/plat_psci.c b/plat/xilinx/zynqmp/plat_psci.c index f0e260de..472adfb7 100644 --- a/plat/xilinx/zynqmp/plat_psci.c +++ b/plat/xilinx/zynqmp/plat_psci.c @@ -147,7 +147,7 @@ static void zynqmp_pwr_domain_off(const psci_power_state_t *target_state) * invoking CPU_on function, during which resume address will * be set. */ - pm_self_suspend(proc->node_id, MAX_LATENCY, 0, 0); + pm_self_suspend(proc->node_id, MAX_LATENCY, PM_STATE_CPU_IDLE, 0); } static void zynqmp_nopmu_pwr_domain_suspend(const psci_power_state_t *target_state) @@ -179,6 +179,7 @@ static void zynqmp_nopmu_pwr_domain_suspend(const psci_power_state_t *target_sta static void zynqmp_pwr_domain_suspend(const psci_power_state_t *target_state) { + unsigned int state; unsigned int cpu_id = plat_my_core_pos(); const struct pm_proc *proc = pm_get_proc(cpu_id); @@ -186,15 +187,14 @@ static void zynqmp_pwr_domain_suspend(const psci_power_state_t *target_state) VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", __func__, i, target_state->pwr_domain_state[i]); + state = target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE ? + PM_STATE_SUSPEND_TO_RAM : PM_STATE_CPU_IDLE; + /* Send request to PMU to suspend this core */ - pm_self_suspend(proc->node_id, MAX_LATENCY, 0, zynqmp_sec_entry); + pm_self_suspend(proc->node_id, MAX_LATENCY, state, zynqmp_sec_entry); /* APU is to be turned off */ if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) { - /* Power down L2 cache */ - pm_set_requirement(NODE_L2, 0, 0, REQ_ACK_NO); - /* Send request for OCM retention state */ - set_ocm_retention(); /* disable coherency */ plat_arm_interconnect_exit_coherency(); } diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c index eac7801b..f78a3113 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c @@ -76,7 +76,7 @@ * pm_self_suspend() - PM call for processor to suspend itself * @nid Node id of the processor or subsystem * @latency Requested maximum wakeup latency (not supported) - * @state Requested state (not supported) + * @state Requested state * @address Resume address * * This is a blocking call, it will return only once PMU has responded. diff --git a/plat/xilinx/zynqmp/pm_service/pm_client.c b/plat/xilinx/zynqmp/pm_service/pm_client.c index cf0d5f08..f0b34cbb 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_client.c +++ b/plat/xilinx/zynqmp/pm_service/pm_client.c @@ -43,16 +43,10 @@ #include "pm_ipi.h" #include "../zynqmp_def.h" -#define OCM_BANK_0 0xFFFC0000 -#define OCM_BANK_1 (OCM_BANK_0 + 0x10000) -#define OCM_BANK_2 (OCM_BANK_1 + 0x10000) -#define OCM_BANK_3 (OCM_BANK_2 + 0x10000) - #define UNDEFINED_CPUID (~0) + DEFINE_BAKERY_LOCK(pm_client_secure_lock); -/* Declaration of linker defined symbol */ -extern unsigned long __BL31_END__; extern const struct pm_ipi apu_ipi; /* Order in pm_procs_all array must match cpu ids */ @@ -79,38 +73,6 @@ static const struct pm_proc const pm_procs_all[] = { }, }; -/** - * set_ocm_retention() - Configure OCM memory banks for retention - * - * APU specific requirements for suspend action: - * OCM has to enter retention state in order to preserve saved - * context after suspend request. OCM banks are determined by - * __BL31_END__ linker symbol. - * - * Return: Returns status, either success or error+reason - */ -enum pm_ret_status set_ocm_retention(void) -{ - enum pm_ret_status ret; - - /* OCM_BANK_0 will always be occupied */ - ret = pm_set_requirement(NODE_OCM_BANK_0, PM_CAP_CONTEXT, 0, - REQ_ACK_NO); - - /* Check for other OCM banks */ - if ((unsigned long)&__BL31_END__ >= OCM_BANK_1) - ret = pm_set_requirement(NODE_OCM_BANK_1, PM_CAP_CONTEXT, 0, - REQ_ACK_NO); - if ((unsigned long)&__BL31_END__ >= OCM_BANK_2) - ret = pm_set_requirement(NODE_OCM_BANK_2, PM_CAP_CONTEXT, 0, - REQ_ACK_NO); - if ((unsigned long)&__BL31_END__ >= OCM_BANK_3) - ret = pm_set_requirement(NODE_OCM_BANK_3, PM_CAP_CONTEXT, 0, - REQ_ACK_NO); - - return ret; -} - /** * pm_get_proc() - returns pointer to the proc structure * @cpuid: id of the cpu whose proc struct pointer should be returned diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h index a8921e7b..7bbfec85 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_defs.h +++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h @@ -53,6 +53,10 @@ #define MAX_LATENCY (~0U) #define MAX_QOS 100U +/* State arguments of the self suspend */ +#define PM_STATE_CPU_IDLE 0x0U +#define PM_STATE_SUSPEND_TO_RAM 0xFU + /********************************************************************* * Enum definitions ********************************************************************/ -- cgit From 6aa4c533b815df625f960eb58c44e98d667e91ab Mon Sep 17 00:00:00 2001 From: Filip Drazic Date: Tue, 26 Jul 2016 12:07:05 +0200 Subject: zynqmp: pm: Add PM node IDs for GPU, PCIE, PCAP and RTC Signed-off-by: Filip Drazic --- plat/xilinx/zynqmp/pm_service/pm_defs.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h index 7bbfec85..90d7d3ad 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_defs.h +++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h @@ -148,6 +148,10 @@ enum pm_node_id { NODE_DDR, NODE_IPI_APU, NODE_IPI_RPU_0, + NODE_GPU, + NODE_PCIE, + NODE_PCAP, + NODE_RTC, }; enum pm_request_ack { -- cgit From b516b7dc5dfeaf14f452f608ce9014c79153ce59 Mon Sep 17 00:00:00 2001 From: Filip Drazic Date: Tue, 26 Jul 2016 12:11:33 +0200 Subject: zynqmp: pm: Call set_wakeup_source for all wake devices on sys-suspend During system suspend, identify slaves which are configured as wake sources and call pm_set_wakeup_source API for each of them. Identifying if device may wake the system is done by checking if any interrupt of that device is enabled in GICD_ISENABLER when the APU is about to enter SUSPEND_TO_RAM state. If such interrupt is found, pm_set_wakeup_source is called with corresponding PM node ID as argument. Signed-off-by: Filip Drazic --- plat/xilinx/zynqmp/pm_service/pm_api_sys.c | 2 +- plat/xilinx/zynqmp/pm_service/pm_client.c | 153 ++++++++++++++++++++++++++++- plat/xilinx/zynqmp/pm_service/pm_client.h | 2 +- plat/xilinx/zynqmp/pm_service/pm_defs.h | 1 + 4 files changed, 155 insertions(+), 3 deletions(-) diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c index f78a3113..52d91711 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c @@ -97,7 +97,7 @@ enum pm_ret_status pm_self_suspend(enum pm_node_id nid, * Do client specific suspend operations * (e.g. set powerdown request bit) */ - pm_client_suspend(proc); + pm_client_suspend(proc, state); /* Send request to the PMU */ PM_PACK_PAYLOAD6(payload, PM_SELF_SUSPEND, proc->node_id, latency, state, address, (address >> 32)); diff --git a/plat/xilinx/zynqmp/pm_service/pm_client.c b/plat/xilinx/zynqmp/pm_service/pm_client.c index f0b34cbb..b77a1cf0 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_client.c +++ b/plat/xilinx/zynqmp/pm_service/pm_client.c @@ -33,16 +33,21 @@ * for getting information about and changing state of the APU. */ +#include #include #include +#include #include #include +#include #include #include "pm_api_sys.h" #include "pm_client.h" #include "pm_ipi.h" #include "../zynqmp_def.h" +#define IRQ_MAX 84 +#define NUM_GICD_ISENABLER ((IRQ_MAX >> 5) + 1) #define UNDEFINED_CPUID (~0) DEFINE_BAKERY_LOCK(pm_client_secure_lock); @@ -73,6 +78,148 @@ static const struct pm_proc const pm_procs_all[] = { }, }; +/* Interrupt to PM node ID map */ +static enum pm_node_id irq_node_map[IRQ_MAX + 1] = { + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, /* 3 */ + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, /* 7 */ + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, /* 11 */ + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_NAND, + NODE_QSPI, /* 15 */ + NODE_GPIO, + NODE_I2C_0, + NODE_I2C_1, + NODE_SPI_0, /* 19 */ + NODE_SPI_1, + NODE_UART_0, + NODE_UART_1, + NODE_CAN_0, /* 23 */ + NODE_CAN_1, + NODE_UNKNOWN, + NODE_RTC, + NODE_RTC, /* 27 */ + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, /* 31 */ + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, /* 35, NODE_IPI_APU */ + NODE_TTC_0, + NODE_TTC_0, + NODE_TTC_0, + NODE_TTC_1, /* 39 */ + NODE_TTC_1, + NODE_TTC_1, + NODE_TTC_2, + NODE_TTC_2, /* 43 */ + NODE_TTC_2, + NODE_TTC_3, + NODE_TTC_3, + NODE_TTC_3, /* 47 */ + NODE_SD_0, + NODE_SD_1, + NODE_SD_0, + NODE_SD_1, /* 51 */ + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, /* 55 */ + NODE_UNKNOWN, + NODE_ETH_0, + NODE_ETH_0, + NODE_ETH_1, /* 59 */ + NODE_ETH_1, + NODE_ETH_2, + NODE_ETH_2, + NODE_ETH_3, /* 63 */ + NODE_ETH_3, + NODE_USB_0, + NODE_USB_0, + NODE_USB_0, /* 67 */ + NODE_USB_0, + NODE_USB_0, + NODE_USB_1, + NODE_USB_1, /* 71 */ + NODE_USB_1, + NODE_USB_1, + NODE_USB_1, + NODE_USB_0, /* 75 */ + NODE_USB_0, + NODE_ADMA, + NODE_ADMA, + NODE_ADMA, /* 79 */ + NODE_ADMA, + NODE_ADMA, + NODE_ADMA, + NODE_ADMA, /* 83 */ + NODE_ADMA, +}; + +/** + * irq_to_pm_node - Get PM node ID corresponding to the interrupt number + * @irq: Interrupt number + * + * Return: PM node ID corresponding to the specified interrupt + */ +static enum pm_node_id irq_to_pm_node(unsigned int irq) +{ + assert(irq <= IRQ_MAX); + return irq_node_map[irq]; +} + +/** + * pm_client_set_wakeup_sources - Set all slaves with enabled interrupts as wake + * sources in the PMU firmware + */ +static void pm_client_set_wakeup_sources(void) +{ + uint32_t reg_num; + uint8_t pm_wakeup_nodes_set[NODE_MAX]; + uintptr_t isenabler1 = BASE_GICD_BASE + GICD_ISENABLER + 4; + + memset(&pm_wakeup_nodes_set, 0, sizeof(pm_wakeup_nodes_set)); + + for (reg_num = 0; reg_num < NUM_GICD_ISENABLER; reg_num++) { + uint32_t base_irq = reg_num << ISENABLER_SHIFT; + uint32_t reg = mmio_read_32(isenabler1 + (reg_num << 2)); + + if (!reg) + continue; + + while (reg) { + enum pm_node_id node; + uint32_t idx, ret, irq, lowest_set = reg & (-reg); + + idx = __builtin_ctz(lowest_set); + irq = base_irq + idx; + + if (irq > IRQ_MAX) + break; + + node = irq_to_pm_node(irq); + reg &= ~lowest_set; + + if ((node != NODE_UNKNOWN) && + (!pm_wakeup_nodes_set[node])) { + ret = pm_set_wakeup_source(NODE_APU, node, 1); + pm_wakeup_nodes_set[node] = !ret; + } + } + } +} + /** * pm_get_proc() - returns pointer to the proc structure * @cpuid: id of the cpu whose proc struct pointer should be returned @@ -124,11 +271,15 @@ const struct pm_proc *primary_proc = &pm_procs_all[0]; * * This function should contain any PU-specific actions * required prior to sending suspend request to PMU + * Actions taken depend on the state system is suspending to. */ -void pm_client_suspend(const struct pm_proc *proc) +void pm_client_suspend(const struct pm_proc *proc, unsigned int state) { bakery_lock_get(&pm_client_secure_lock); + if (state == PM_STATE_SUSPEND_TO_RAM) + pm_client_set_wakeup_sources(); + /* Set powerdown request */ mmio_write_32(APU_PWRCTL, mmio_read_32(APU_PWRCTL) | proc->pwrdn_mask); diff --git a/plat/xilinx/zynqmp/pm_service/pm_client.h b/plat/xilinx/zynqmp/pm_service/pm_client.h index 9483b0d1..7f80d5b4 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_client.h +++ b/plat/xilinx/zynqmp/pm_service/pm_client.h @@ -40,7 +40,7 @@ #include "pm_common.h" /* Functions to be implemented by each PU */ -void pm_client_suspend(const struct pm_proc *proc); +void pm_client_suspend(const struct pm_proc *proc, unsigned int state); void pm_client_abort_suspend(void); void pm_client_wakeup(const struct pm_proc *proc); enum pm_ret_status set_ocm_retention(void); diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h index 90d7d3ad..db44785d 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_defs.h +++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h @@ -152,6 +152,7 @@ enum pm_node_id { NODE_PCIE, NODE_PCAP, NODE_RTC, + NODE_MAX }; enum pm_request_ack { -- cgit From 4fe0f4be7de445d2921662ac51784de84e9c7562 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Thu, 18 Feb 2016 21:16:35 -0800 Subject: zynqmp: Initialize GIC on suspend_finish Signed-off-by: Soren Brinkmann --- plat/xilinx/zynqmp/plat_psci.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plat/xilinx/zynqmp/plat_psci.c b/plat/xilinx/zynqmp/plat_psci.c index 472adfb7..55227ea9 100644 --- a/plat/xilinx/zynqmp/plat_psci.c +++ b/plat/xilinx/zynqmp/plat_psci.c @@ -242,6 +242,13 @@ static void zynqmp_pwr_domain_suspend_finish(const psci_power_state_t *target_st /* enable coherency */ plat_arm_interconnect_enter_coherency(); + /* APU was turned off */ + if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) { + plat_arm_gic_init(); + } else { + gicv2_cpuif_enable(); + gicv2_pcpu_distif_init(); + } } /******************************************************************************* -- cgit From f7d4bfc2bf4d494da7de1c5e9bf55c41d9123b4d Mon Sep 17 00:00:00 2001 From: Nava kishore Manne Date: Sat, 20 Aug 2016 23:11:11 +0530 Subject: zynqmp: pm: adds new pm ID to sync with PMUFW ID numbers This patch adds a new pm ID to sync with PMUFW ID numbers. Signed-off-by: Nava kishore Manne --- plat/xilinx/zynqmp/pm_service/pm_defs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h index db44785d..ddce1525 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_defs.h +++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h @@ -86,6 +86,7 @@ enum pm_api_id { PM_RESET_GET_STATUS, PM_MMIO_WRITE, PM_MMIO_READ, + PM_INIT, PM_API_MAX }; -- cgit From 2ddc31decebcdb03d2bcc485eca30646ac3fe3bd Mon Sep 17 00:00:00 2001 From: Nava kishore Manne Date: Sat, 20 Aug 2016 23:18:09 +0530 Subject: zynqmp: pm: Implemented pm API functions to load the bitstream into PL This patch adds pm_fpga_load() and pm_fpga_get_status() API's to provide the Access to the xilfpga library to load the bitstream into zynqmp PL region. Signed-off-by: Nava kishore Manne --- plat/xilinx/zynqmp/pm_service/pm_api_sys.c | 44 +++++++++++++++++++++++++++++ plat/xilinx/zynqmp/pm_service/pm_api_sys.h | 6 ++++ plat/xilinx/zynqmp/pm_service/pm_defs.h | 2 ++ plat/xilinx/zynqmp/pm_service/pm_svc_main.c | 13 +++++++++ 4 files changed, 65 insertions(+) diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c index 52d91711..efadbd20 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c @@ -497,3 +497,47 @@ enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value) PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address); return pm_ipi_send_sync(primary_proc, payload, value); } + +/** + * pm_fpga_load() - Load the bitstream into the PL. + * + * This function provides access to the xilfpga library to load + * the Bit-stream into PL. + * + * address_low: lower 32-bit Linear memory space address + * + * address_high: higher 32-bit Linear memory space address + * + * size: Number of 32bit words + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_fpga_load(uint32_t address_low, + uint32_t address_high, + uint32_t size, + uint32_t flags) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD5(payload, PM_FPGA_LOAD, address_high, address_low, + size, flags); + return pm_ipi_send(primary_proc, payload); +} + +/** + * pm_fpga_get_status() - Read value from fpga status register + * @value Value to read + * + * This function provides access to the xilfpga library to get + * the fpga status + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_fpga_get_status(unsigned int *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD1(payload, PM_FPGA_GET_STATUS); + return pm_ipi_send_sync(primary_proc, payload, value); +} diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h index 22bdb477..26d83e75 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h @@ -109,4 +109,10 @@ enum pm_ret_status pm_mmio_write(uintptr_t address, unsigned int mask, unsigned int value); enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value); +enum pm_ret_status pm_fpga_load(uint32_t address_high, + uint32_t address_low, + uint32_t size, + uint32_t flags); +enum pm_ret_status pm_fpga_get_status(unsigned int *value); + #endif /* _PM_API_SYS_H_ */ diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h index ddce1525..7fe5d37d 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_defs.h +++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h @@ -87,6 +87,8 @@ enum pm_api_id { PM_MMIO_WRITE, PM_MMIO_READ, PM_INIT, + PM_FPGA_LOAD, + PM_FPGA_GET_STATUS, PM_API_MAX }; diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c index e3c25c31..ccb4df8c 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c +++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c @@ -228,6 +228,19 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, ret = pm_mmio_read(pm_arg[0], &value); SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); } + + case PM_FPGA_LOAD: + ret = pm_fpga_load(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_FPGA_GET_STATUS: + { + uint32_t value; + + ret = pm_fpga_get_status(&value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + default: WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid); SMC_RET1(handle, SMC_UNK); -- cgit From 3104f2e78d99bff1a0719680b5372563701732d8 Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Wed, 24 Aug 2016 11:45:47 +0530 Subject: zynqmp: Add support to provide silicon id through SMC Add support to provide silicon id to non-secure software through SMC. Signed-off-by: Siva Durga Prasad Paladugu [ sb Move zynqmp_get_silicon_id outside of compile guards to avoid build errors. ] Signed-off-by: Soren Brinkmann Acked-by: Michal Simek --- plat/xilinx/zynqmp/aarch64/zynqmp_common.c | 24 ++++++++++++------------ plat/xilinx/zynqmp/pm_service/pm_defs.h | 1 + plat/xilinx/zynqmp/pm_service/pm_svc_main.c | 3 +++ plat/xilinx/zynqmp/zynqmp_private.h | 1 + 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c index d1b52e1a..60a16058 100644 --- a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c +++ b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c @@ -90,6 +90,18 @@ static unsigned int zynqmp_get_system_timer_freq(void) return 100000000; } +unsigned int zynqmp_get_silicon_id(void) +{ + uint32_t id; + + id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); + + id &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | ZYNQMP_CSU_IDCODE_SVD_MASK; + id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT; + + return id; +} + #if LOG_LEVEL >= LOG_LEVEL_NOTICE static const struct { unsigned int id; @@ -141,18 +153,6 @@ static const struct { }, }; -static unsigned int zynqmp_get_silicon_id(void) -{ - uint32_t id; - - id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); - - id &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | ZYNQMP_CSU_IDCODE_SVD_MASK; - id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT; - - return id; -} - static char *zynqmp_get_silicon_idcode_name(void) { unsigned int id; diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h index 7fe5d37d..aec335a5 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_defs.h +++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h @@ -89,6 +89,7 @@ enum pm_api_id { PM_INIT, PM_FPGA_LOAD, PM_FPGA_GET_STATUS, + PM_GET_CHIPID, PM_API_MAX }; diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c index ccb4df8c..9c08ffb9 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c +++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c @@ -241,6 +241,9 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); } + case PM_GET_CHIPID: + SMC_RET1(handle, zynqmp_get_silicon_id()); + default: WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid); SMC_RET1(handle, SMC_UNK); diff --git a/plat/xilinx/zynqmp/zynqmp_private.h b/plat/xilinx/zynqmp/zynqmp_private.h index ddef37b8..abcdebc3 100644 --- a/plat/xilinx/zynqmp/zynqmp_private.h +++ b/plat/xilinx/zynqmp/zynqmp_private.h @@ -39,6 +39,7 @@ void zynqmp_config_setup(void); unsigned int zynqmp_get_uart_clk(void); int zynqmp_is_pmu_up(void); unsigned int zynqmp_get_bootmode(void); +unsigned int zynqmp_get_silicon_id(void); /* For FSBL handover */ void fsbl_atf_handover(entry_point_info_t *bl32_image_ep_info, -- cgit From 8787c0e00cfde59e81f6f89c84cef89d422cfabb Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Tue, 6 Sep 2016 16:29:07 -0700 Subject: zynqmp: Make MMIO write FW call synchronous We must guarantee that writes have become effective before returning to the caller. Hence, wait for PMUFW signaling completion of the FW call before returning to the rich OS. Signed-off-by: Soren Brinkmann --- plat/xilinx/zynqmp/pm_service/pm_api_sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c index efadbd20..e859ee39 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c @@ -476,7 +476,7 @@ enum pm_ret_status pm_mmio_write(uintptr_t address, /* Send request to the PMU */ PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value); - return pm_ipi_send(primary_proc, payload); + return pm_ipi_send_sync(primary_proc, payload, NULL); } /** -- cgit