Browse Source
The Xilinx Zynq UltraScale+ MPSOC containes a quad A53 cluster. This patch adds the platform port for that SoC. Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>pull/569/head
Soren Brinkmann
9 years ago
25 changed files with 3532 additions and 0 deletions
@ -0,0 +1,49 @@ |
|||
ARM Trusted Firmware for Xilinx Zynq UltraScale+ MPSoC |
|||
================================ |
|||
|
|||
ARM Trusted Firmware implements the EL3 firmware layer for Xilinx Zynq |
|||
UltraScale + MPSoC. |
|||
The platform only uses the runtime part of ATF as ZynqMP already has a |
|||
BootROM (BL1) and FSBL (BL2). |
|||
|
|||
BL31 is ATF. |
|||
BL32 is an optional Secure Payload. |
|||
BL33 is the non-secure world software (U-Boot, Linux etc). |
|||
|
|||
To build: |
|||
```bash |
|||
make ERROR_DEPRECATED=1 RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=zynqmp bl31 |
|||
``` |
|||
|
|||
To build bl32 TSP you have to rebuild bl31 too: |
|||
```bash |
|||
make ERROR_DEPRECATED=1 RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=zynqmp SPD=tspd bl31 bl32 |
|||
``` |
|||
|
|||
# ZynqMP platform specific build options |
|||
* `ZYNQMP_ATF_LOCATION`: Specifies the location of the bl31 binary. Options: |
|||
- `tsram` : bl31 will be located in OCM (default) |
|||
- `tdram` : bl31 will be located in DRAM (address: 0x30000000) |
|||
|
|||
* `ZYNQMP_TSP_RAM_LOCATION`: Specifies the location of the bl32 binary and |
|||
secure payload dispatcher. Options: |
|||
- `tsram` : bl32/spd will be located in OCM (default) |
|||
- `tdram` : bl32/spd will be located in DRAM (address: 0x30000000) |
|||
|
|||
# Power Domain Tree |
|||
The following power domain tree represents the power domain model used by the |
|||
ATF for ZynqMP: |
|||
``` |
|||
+-+ |
|||
|0| |
|||
+-+ |
|||
+-------+---+---+-------+ |
|||
| | | | |
|||
| | | | |
|||
v v v v |
|||
+-+ +-+ +-+ +-+ |
|||
|0| |1| |2| |3| |
|||
+-+ +-+ +-+ +-+ |
|||
``` |
|||
The 4 leaf power domains represent the individual A53 cores, while resources |
|||
common to the cluster are grouped in the power domain on the top. |
@ -0,0 +1,308 @@ |
|||
/*
|
|||
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#include <arch_helpers.h> |
|||
#include <cci.h> |
|||
#include <debug.h> |
|||
#include <gicv2.h> |
|||
#include <mmio.h> |
|||
#include <plat_arm.h> |
|||
#include <platform.h> |
|||
#include <xlat_tables.h> |
|||
#include "../zynqmp_private.h" |
|||
|
|||
/*
|
|||
* Table of regions to map using the MMU. |
|||
* This doesn't include TZRAM as the 'mem_layout' argument passed to |
|||
* configure_mmu_elx() will give the available subset of that, |
|||
*/ |
|||
const mmap_region_t plat_arm_mmap[] = { |
|||
{ DEVICE0_BASE, DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, |
|||
{ DEVICE1_BASE, DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, |
|||
{ CRF_APB_BASE, CRF_APB_BASE, CRF_APB_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, |
|||
{0} |
|||
}; |
|||
|
|||
static unsigned int zynqmp_get_silicon_ver(void) |
|||
{ |
|||
unsigned int ver; |
|||
|
|||
ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET); |
|||
ver &= ZYNQMP_SILICON_VER_MASK; |
|||
ver >>= ZYNQMP_SILICON_VER_SHIFT; |
|||
|
|||
return ver; |
|||
} |
|||
|
|||
unsigned int zynqmp_get_uart_clk(void) |
|||
{ |
|||
unsigned int ver = zynqmp_get_silicon_ver(); |
|||
|
|||
switch (ver) { |
|||
case ZYNQMP_CSU_VERSION_VELOCE: |
|||
return 48000; |
|||
case ZYNQMP_CSU_VERSION_EP108: |
|||
return 25000000; |
|||
case ZYNQMP_CSU_VERSION_QEMU: |
|||
return 133000000; |
|||
} |
|||
|
|||
return 100000000; |
|||
} |
|||
|
|||
static unsigned int zynqmp_get_system_timer_freq(void) |
|||
{ |
|||
unsigned int ver = zynqmp_get_silicon_ver(); |
|||
|
|||
switch (ver) { |
|||
case ZYNQMP_CSU_VERSION_VELOCE: |
|||
return 10000; |
|||
case ZYNQMP_CSU_VERSION_EP108: |
|||
return 4000000; |
|||
case ZYNQMP_CSU_VERSION_QEMU: |
|||
return 50000000; |
|||
} |
|||
|
|||
return 100000000; |
|||
} |
|||
|
|||
#if LOG_LEVEL >= LOG_LEVEL_NOTICE |
|||
static const struct { |
|||
unsigned int id; |
|||
char *name; |
|||
} zynqmp_devices[] = { |
|||
{ |
|||
.id = 0x10, |
|||
.name = "3EG", |
|||
}, |
|||
{ |
|||
.id = 0x11, |
|||
.name = "2EG", |
|||
}, |
|||
{ |
|||
.id = 0x20, |
|||
.name = "5EV", |
|||
}, |
|||
{ |
|||
.id = 0x21, |
|||
.name = "4EV", |
|||
}, |
|||
{ |
|||
.id = 0x30, |
|||
.name = "7EV", |
|||
}, |
|||
{ |
|||
.id = 0x38, |
|||
.name = "9EG", |
|||
}, |
|||
{ |
|||
.id = 0x39, |
|||
.name = "6EG", |
|||
}, |
|||
{ |
|||
.id = 0x40, |
|||
.name = "11EG", |
|||
}, |
|||
{ |
|||
.id = 0x50, |
|||
.name = "15EG", |
|||
}, |
|||
{ |
|||
.id = 0x58, |
|||
.name = "19EG", |
|||
}, |
|||
{ |
|||
.id = 0x59, |
|||
.name = "17EG", |
|||
}, |
|||
}; |
|||
|
|||
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; |
|||
|
|||
id = zynqmp_get_silicon_id(); |
|||
for (size_t i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) { |
|||
if (zynqmp_devices[i].id == id) |
|||
return zynqmp_devices[i].name; |
|||
} |
|||
return "UNKN"; |
|||
} |
|||
|
|||
static unsigned int zynqmp_get_rtl_ver(void) |
|||
{ |
|||
uint32_t ver; |
|||
|
|||
ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET); |
|||
ver &= ZYNQMP_RTL_VER_MASK; |
|||
ver >>= ZYNQMP_RTL_VER_SHIFT; |
|||
|
|||
return ver; |
|||
} |
|||
|
|||
static char *zynqmp_print_silicon_idcode(void) |
|||
{ |
|||
uint32_t id, maskid, tmp; |
|||
|
|||
id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); |
|||
|
|||
tmp = id; |
|||
tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK | |
|||
ZYNQMP_CSU_IDCODE_FAMILY_MASK | |
|||
ZYNQMP_CSU_IDCODE_REVISION_MASK; |
|||
maskid = ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT | |
|||
ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT | |
|||
ZYNQMP_CSU_IDCODE_REVISION << ZYNQMP_CSU_IDCODE_REVISION_SHIFT; |
|||
if (tmp != maskid) { |
|||
ERROR("Incorrect XILINX IDCODE 0x%x, maskid 0x%x\n", id, maskid); |
|||
return "UNKN"; |
|||
} |
|||
VERBOSE("Xilinx IDCODE 0x%x\n", id); |
|||
return zynqmp_get_silicon_idcode_name(); |
|||
} |
|||
|
|||
static unsigned int zynqmp_get_ps_ver(void) |
|||
{ |
|||
uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET); |
|||
|
|||
ver &= ZYNQMP_PS_VER_MASK; |
|||
ver >>= ZYNQMP_PS_VER_SHIFT; |
|||
|
|||
return ver + 1; |
|||
} |
|||
|
|||
static void zynqmp_print_platform_name(void) |
|||
{ |
|||
unsigned int ver = zynqmp_get_silicon_ver(); |
|||
unsigned int rtl = zynqmp_get_rtl_ver(); |
|||
char *label = "Unknown"; |
|||
|
|||
switch (ver) { |
|||
case ZYNQMP_CSU_VERSION_VELOCE: |
|||
label = "VELOCE"; |
|||
break; |
|||
case ZYNQMP_CSU_VERSION_EP108: |
|||
label = "EP108"; |
|||
break; |
|||
case ZYNQMP_CSU_VERSION_QEMU: |
|||
label = "QEMU"; |
|||
break; |
|||
case ZYNQMP_CSU_VERSION_SILICON: |
|||
label = "silicon"; |
|||
break; |
|||
} |
|||
|
|||
NOTICE("ATF running on XCZU%s/%s v%d/RTL%d.%d at 0x%x%s\n", |
|||
zynqmp_print_silicon_idcode(), label, zynqmp_get_ps_ver(), |
|||
(rtl & 0xf0) >> 4, rtl & 0xf, BL31_BASE, |
|||
zynqmp_is_pmu_up() ? ", with PMU firmware" : ""); |
|||
} |
|||
#else |
|||
static inline void zynqmp_print_platform_name(void) { } |
|||
#endif |
|||
|
|||
/*
|
|||
* Indicator for PMUFW discovery: |
|||
* 0 = No FW found |
|||
* non-zero = FW is present |
|||
*/ |
|||
static int zynqmp_pmufw_present; |
|||
|
|||
/*
|
|||
* zynqmp_discover_pmufw - Discover presence of PMUFW |
|||
* |
|||
* Discover the presence of PMUFW and store it for later run-time queries |
|||
* through zynqmp_is_pmu_up. |
|||
* NOTE: This discovery method is fragile and will break if: |
|||
* - setting FW_PRESENT is done by PMUFW itself and could be left out in PMUFW |
|||
* (be it by error or intentionally) |
|||
* - XPPU/XMPU may restrict ATF's access to the PMU address space |
|||
*/ |
|||
static int zynqmp_discover_pmufw(void) |
|||
{ |
|||
zynqmp_pmufw_present = mmio_read_32(PMU_GLOBAL_CNTRL); |
|||
zynqmp_pmufw_present &= PMU_GLOBAL_CNTRL_FW_IS_PRESENT; |
|||
|
|||
return !!zynqmp_pmufw_present; |
|||
} |
|||
|
|||
/*
|
|||
* zynqmp_is_pmu_up - Find if PMU firmware is up and running |
|||
* |
|||
* Return 0 if firmware is not available, non 0 otherwise |
|||
*/ |
|||
int zynqmp_is_pmu_up(void) |
|||
{ |
|||
return zynqmp_pmufw_present; |
|||
} |
|||
|
|||
/*
|
|||
* A single boot loader stack is expected to work on both the Foundation ZYNQMP |
|||
* models and the two flavours of the Base ZYNQMP models (AEMv8 & Cortex). The |
|||
* SYS_ID register provides a mechanism for detecting the differences between |
|||
* these platforms. This information is stored in a per-BL array to allow the |
|||
* code to take the correct path.Per BL platform configuration. |
|||
*/ |
|||
void zynqmp_config_setup(void) |
|||
{ |
|||
zynqmp_discover_pmufw(); |
|||
zynqmp_print_platform_name(); |
|||
|
|||
/* Global timer init - Program time stamp reference clk */ |
|||
uint32_t val = mmio_read_32(CRL_APB_TIMESTAMP_REF_CTRL); |
|||
val |= CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT; |
|||
mmio_write_32(CRL_APB_TIMESTAMP_REF_CTRL, val); |
|||
|
|||
/* 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); |
|||
} |
|||
|
|||
uint64_t plat_get_syscnt_freq(void) |
|||
{ |
|||
uint64_t counter_base_frequency; |
|||
|
|||
/* FIXME: Read the frequency from Frequency modes table */ |
|||
counter_base_frequency = zynqmp_get_system_timer_freq(); |
|||
|
|||
return counter_base_frequency; |
|||
} |
@ -0,0 +1,73 @@ |
|||
/* |
|||
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#include <asm_macros.S> |
|||
#include <gicv2.h> |
|||
#include <platform_def.h> |
|||
|
|||
.globl plat_secondary_cold_boot_setup |
|||
.globl plat_is_my_cpu_primary |
|||
|
|||
/* ----------------------------------------------------- |
|||
* void plat_secondary_cold_boot_setup (void); |
|||
* |
|||
* This function performs any platform specific actions |
|||
* needed for a secondary cpu after a cold reset e.g |
|||
* mark the cpu's presence, mechanism to place it in a |
|||
* holding pen etc. |
|||
* TODO: Should we read the PSYS register to make sure |
|||
* that the request has gone through. |
|||
* ----------------------------------------------------- |
|||
*/ |
|||
func plat_secondary_cold_boot_setup |
|||
mrs x0, mpidr_el1 |
|||
|
|||
/* Deactivate the gic cpu interface */ |
|||
ldr x1, =BASE_GICC_BASE |
|||
mov w0, #(IRQ_BYP_DIS_GRP1 | FIQ_BYP_DIS_GRP1) |
|||
orr w0, w0, #(IRQ_BYP_DIS_GRP0 | FIQ_BYP_DIS_GRP0) |
|||
str w0, [x1, #GICC_CTLR] |
|||
|
|||
/* |
|||
* There is no sane reason to come out of this wfi. This |
|||
* cpu will be powered on and reset by the cpu_on pm api |
|||
*/ |
|||
dsb sy |
|||
1: |
|||
bl plat_panic_handler |
|||
endfunc plat_secondary_cold_boot_setup |
|||
|
|||
func plat_is_my_cpu_primary |
|||
mov x9, x30 |
|||
bl plat_my_core_pos |
|||
cmp x0, #ZYNQMP_PRIMARY_CPU |
|||
cset x0, eq |
|||
ret x9 |
|||
endfunc plat_is_my_cpu_primary |
@ -0,0 +1,164 @@ |
|||
/*
|
|||
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#include <assert.h> |
|||
#include <bl_common.h> |
|||
#include <bl31.h> |
|||
#include <console.h> |
|||
#include <debug.h> |
|||
#include <errno.h> |
|||
#include <plat_arm.h> |
|||
#include <platform.h> |
|||
#include "zynqmp_private.h" |
|||
|
|||
/*
|
|||
* Declarations of linker defined symbols which will help us find the layout |
|||
* of trusted SRAM |
|||
*/ |
|||
extern unsigned long __RO_START__; |
|||
extern unsigned long __RO_END__; |
|||
|
|||
extern unsigned long __COHERENT_RAM_START__; |
|||
extern unsigned long __COHERENT_RAM_END__; |
|||
|
|||
/*
|
|||
* The next 2 constants identify the extents of the code & RO data region. |
|||
* These addresses are used by the MMU setup code and therefore they must be |
|||
* page-aligned. It is the responsibility of the linker script to ensure that |
|||
* __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses. |
|||
*/ |
|||
#define BL31_RO_BASE (unsigned long)(&__RO_START__) |
|||
#define BL31_RO_LIMIT (unsigned long)(&__RO_END__) |
|||
|
|||
/*
|
|||
* The next 2 constants identify the extents of the coherent memory region. |
|||
* These addresses are used by the MMU setup code and therefore they must be |
|||
* page-aligned. It is the responsibility of the linker script to ensure that |
|||
* __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols |
|||
* refer to page-aligned addresses. |
|||
*/ |
|||
#define BL31_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) |
|||
#define BL31_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) |
|||
|
|||
static entry_point_info_t bl32_image_ep_info; |
|||
static entry_point_info_t bl33_image_ep_info; |
|||
|
|||
/*
|
|||
* Return a pointer to the 'entry_point_info' structure of the next image for |
|||
* the security state specified. BL33 corresponds to the non-secure image type |
|||
* while BL32 corresponds to the secure image type. A NULL pointer is returned |
|||
* if the image does not exist. |
|||
*/ |
|||
entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) |
|||
{ |
|||
assert(sec_state_is_valid(type)); |
|||
|
|||
if (type == NON_SECURE) |
|||
return &bl33_image_ep_info; |
|||
|
|||
return &bl32_image_ep_info; |
|||
} |
|||
|
|||
/*
|
|||
* Perform any BL31 specific platform actions. Here is an opportunity to copy |
|||
* parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they |
|||
* are lost (potentially). This needs to be done before the MMU is initialized |
|||
* so that the memory layout can be used while creating page tables. |
|||
*/ |
|||
void bl31_early_platform_setup(bl31_params_t *from_bl2, |
|||
void *plat_params_from_bl2) |
|||
{ |
|||
/* Initialize the console to provide early debug support */ |
|||
console_init(ZYNQMP_UART0_BASE, zynqmp_get_uart_clk(), |
|||
ZYNQMP_UART_BAUDRATE); |
|||
|
|||
/* Initialize the platform config for future decision making */ |
|||
zynqmp_config_setup(); |
|||
|
|||
/* There are no parameters from BL2 if BL31 is a reset vector */ |
|||
assert(from_bl2 == NULL); |
|||
assert(plat_params_from_bl2 == NULL); |
|||
|
|||
/*
|
|||
* Do initial security configuration to allow DRAM/device access. On |
|||
* Base ZYNQMP only DRAM security is programmable (via TrustZone), but |
|||
* other platforms might have more programmable security devices |
|||
* present. |
|||
*/ |
|||
|
|||
/* Populate entry point information for BL32 and BL33 */ |
|||
SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0); |
|||
SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); |
|||
bl32_image_ep_info.pc = BL32_BASE; |
|||
bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry(); |
|||
|
|||
NOTICE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc); |
|||
|
|||
SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0); |
|||
|
|||
/*
|
|||
* Tell BL31 where the non-trusted software image |
|||
* is located and the entry state information |
|||
*/ |
|||
bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); |
|||
bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, |
|||
DISABLE_ALL_EXCEPTIONS); |
|||
SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); |
|||
|
|||
NOTICE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc); |
|||
} |
|||
|
|||
void bl31_platform_setup(void) |
|||
{ |
|||
/* Initialize the gic cpu and distributor interfaces */ |
|||
plat_arm_gic_driver_init(); |
|||
plat_arm_gic_init(); |
|||
} |
|||
|
|||
void bl31_plat_runtime_setup(void) |
|||
{ |
|||
} |
|||
|
|||
/*
|
|||
* Perform the very early platform specific architectural setup here. At the |
|||
* moment this is only intializes the MMU in a quick and dirty way. |
|||
*/ |
|||
void bl31_plat_arch_setup(void) |
|||
{ |
|||
plat_arm_interconnect_init(); |
|||
plat_arm_interconnect_enter_coherency(); |
|||
|
|||
arm_configure_mmu_el3(BL31_RO_BASE, |
|||
BL31_COHERENT_RAM_LIMIT - BL31_RO_BASE, |
|||
BL31_RO_BASE, |
|||
BL31_RO_LIMIT, |
|||
BL31_COHERENT_RAM_BASE, |
|||
BL31_COHERENT_RAM_LIMIT); |
|||
} |
@ -0,0 +1,51 @@ |
|||
/* |
|||
* Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
#ifndef __PLAT_MACROS_S__ |
|||
#define __PLAT_MACROS_S__ |
|||
|
|||
#include <arm_macros.S> |
|||
#include <cci_macros.S> |
|||
#include "../zynqmp_def.h" |
|||
|
|||
/* --------------------------------------------- |
|||
* The below required platform porting macro |
|||
* prints out relevant GIC registers whenever an |
|||
* unhandled exception is taken in BL31. |
|||
* Clobbers: x0 - x10, x16, sp |
|||
* --------------------------------------------- |
|||
*/ |
|||
.macro plat_print_gic_regs |
|||
mov_imm x17, BASE_GICC_BASE |
|||
mov_imm x16, BASE_GICD_BASE |
|||
arm_print_gic_regs |
|||
mov x0, x1 |
|||
.endm |
|||
|
|||
#endif /* __PLAT_MACROS_S__ */ |
@ -0,0 +1,135 @@ |
|||
/*
|
|||
* Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#ifndef __PLATFORM_DEF_H__ |
|||
#define __PLATFORM_DEF_H__ |
|||
|
|||
#include <arch.h> |
|||
#include "../zynqmp_def.h" |
|||
|
|||
/*******************************************************************************
|
|||
* Generic platform constants |
|||
******************************************************************************/ |
|||
|
|||
/* Size of cacheable stacks */ |
|||
#define PLATFORM_STACK_SIZE 0x440 |
|||
|
|||
#define PLATFORM_CORE_COUNT 4 |
|||
#define PLAT_NUM_POWER_DOMAINS 5 |
|||
#define PLAT_MAX_PWR_LVL 1 |
|||
#define PLAT_MAX_RET_STATE 1 |
|||
#define PLAT_MAX_OFF_STATE 2 |
|||
|
|||
/*******************************************************************************
|
|||
* BL31 specific defines. |
|||
******************************************************************************/ |
|||
|
|||
#define ZYNQMP_BL31_SIZE 0x1b000 |
|||
/*
|
|||
* Put BL31 at the top of the Trusted SRAM (just below the shared memory, if |
|||
* present). BL31_BASE is calculated using the current BL31 debug size plus a |
|||
* little space for growth. |
|||
*/ |
|||
#if ZYNQMP_ATF_LOCATION_ID == ZYNQMP_IN_TRUSTED_SRAM |
|||
# define BL31_BASE (ZYNQMP_TRUSTED_SRAM_LIMIT - \ |
|||
ZYNQMP_BL31_SIZE) |
|||
# define BL31_PROGBITS_LIMIT (ZYNQMP_TRUSTED_SRAM_LIMIT - 0x6000) |
|||
# define BL31_LIMIT ZYNQMP_TRUSTED_SRAM_LIMIT |
|||
#elif ZYNQMP_ATF_LOCATION_ID == ZYNQMP_IN_TRUSTED_DRAM |
|||
# define BL31_BASE (ZYNQMP_TRUSTED_DRAM_LIMIT - \ |
|||
ZYNQMP_BL31_SIZE) |
|||
# define BL31_PROGBITS_LIMIT (ZYNQMP_TRUSTED_DRAM_LIMIT - 0x6000) |
|||
# define BL31_LIMIT (ZYNQMP_TRUSTED_DRAM_BASE + \ |
|||
ZYNQMP_TRUSTED_DRAM_SIZE) |
|||
#else |
|||
# error "Unsupported ZYNQMP_ATF_LOCATION_ID value" |
|||
#endif |
|||
|
|||
/*******************************************************************************
|
|||
* BL32 specific defines. |
|||
******************************************************************************/ |
|||
/*
|
|||
* On ZYNQMP, the TSP can execute either from Trusted SRAM or Trusted DRAM. |
|||
*/ |
|||
#if ZYNQMP_TSP_RAM_LOCATION_ID == ZYNQMP_IN_TRUSTED_SRAM |
|||
# define TSP_SEC_MEM_BASE ZYNQMP_TRUSTED_SRAM_BASE |
|||
# define TSP_SEC_MEM_SIZE ZYNQMP_TRUSTED_SRAM_SIZE |
|||
# define TSP_PROGBITS_LIMIT (ZYNQMP_TRUSTED_SRAM_LIMIT - \ |
|||
ZYNQMP_BL31_SIZE) |
|||
# define BL32_BASE ZYNQMP_TRUSTED_SRAM_BASE |
|||
# define BL32_LIMIT (ZYNQMP_TRUSTED_SRAM_LIMIT - \ |
|||
ZYNQMP_BL31_SIZE) |
|||
#elif ZYNQMP_TSP_RAM_LOCATION_ID == ZYNQMP_IN_TRUSTED_DRAM |
|||
# define TSP_SEC_MEM_BASE ZYNQMP_TRUSTED_DRAM_BASE |
|||
# define TSP_SEC_MEM_SIZE (ZYNQMP_TRUSTED_DRAM_LIMIT - \ |
|||
ZYNQMP_BL31_SIZE) |
|||
# define BL32_BASE ZYNQMP_TRUSTED_DRAM_BASE |
|||
# define BL32_LIMIT (ZYNQMP_TRUSTED_DRAM_LIMIT - \ |
|||
ZYNQMP_BL31_SIZE) |
|||
#else |
|||
# error "Unsupported ZYNQMP_TSP_RAM_LOCATION_ID value" |
|||
#endif |
|||
|
|||
/*
|
|||
* ID of the secure physical generic timer interrupt used by the TSP. |
|||
*/ |
|||
#define TSP_IRQ_SEC_PHY_TIMER ARM_IRQ_SEC_PHY_TIMER |
|||
|
|||
/*******************************************************************************
|
|||
* Platform specific page table and MMU setup constants |
|||
******************************************************************************/ |
|||
#define ADDR_SPACE_SIZE (1ull << 32) |
|||
#define MAX_XLAT_TABLES 5 |
|||
#define MAX_MMAP_REGIONS 7 |
|||
|
|||
#define CACHE_WRITEBACK_SHIFT 6 |
|||
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) |
|||
|
|||
#define PLAT_ARM_GICD_BASE BASE_GICD_BASE |
|||
#define PLAT_ARM_GICC_BASE BASE_GICC_BASE |
|||
/*
|
|||
* Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 |
|||
* terminology. On a GICv2 system or mode, the lists will be merged and treated |
|||
* as Group 0 interrupts. |
|||
*/ |
|||
#define PLAT_ARM_G1S_IRQS ARM_IRQ_SEC_PHY_TIMER, \ |
|||
IRQ_SEC_IPI_APU, \ |
|||
ARM_IRQ_SEC_SGI_0, \ |
|||
ARM_IRQ_SEC_SGI_1, \ |
|||
ARM_IRQ_SEC_SGI_2, \ |
|||
ARM_IRQ_SEC_SGI_3, \ |
|||
ARM_IRQ_SEC_SGI_4, \ |
|||
ARM_IRQ_SEC_SGI_5, \ |
|||
ARM_IRQ_SEC_SGI_6, \ |
|||
ARM_IRQ_SEC_SGI_7 |
|||
|
|||
#define PLAT_ARM_G0_IRQS |
|||
|
|||
#endif /* __PLATFORM_DEF_H__ */ |
@ -0,0 +1,374 @@ |
|||
/*
|
|||
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#include <arch_helpers.h> |
|||
#include <errno.h> |
|||
#include <assert.h> |
|||
#include <debug.h> |
|||
#include <gicv2.h> |
|||
#include <mmio.h> |
|||
#include <plat_arm.h> |
|||
#include <platform.h> |
|||
#include <psci.h> |
|||
#include "pm_api_sys.h" |
|||
#include "pm_client.h" |
|||
#include "zynqmp_private.h" |
|||
|
|||
uintptr_t zynqmp_sec_entry; |
|||
|
|||
void zynqmp_cpu_standby(plat_local_state_t cpu_state) |
|||
{ |
|||
VERBOSE("%s: cpu_state: 0x%x\n", __func__, cpu_state); |
|||
|
|||
dsb(); |
|||
wfi(); |
|||
} |
|||
|
|||
static int zynqmp_nopmu_pwr_domain_on(u_register_t mpidr) |
|||
{ |
|||
uint32_t r; |
|||
unsigned int cpu_id = plat_core_pos_by_mpidr(mpidr); |
|||
|
|||
VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr); |
|||
|
|||
if (cpu_id == -1) |
|||
return PSCI_E_INTERN_FAIL; |
|||
|
|||
/* program RVBAR */ |
|||
mmio_write_32(APU_RVBAR_L_0 + (cpu_id << 3), zynqmp_sec_entry); |
|||
mmio_write_32(APU_RVBAR_H_0 + (cpu_id << 3), zynqmp_sec_entry >> 32); |
|||
|
|||
/* clear VINITHI */ |
|||
r = mmio_read_32(APU_CONFIG_0); |
|||
r &= ~(1 << APU_CONFIG_0_VINITHI_SHIFT << cpu_id); |
|||
mmio_write_32(APU_CONFIG_0, r); |
|||
|
|||
/* clear power down request */ |
|||
r = mmio_read_32(APU_PWRCTL); |
|||
r &= ~(1 << cpu_id); |
|||
mmio_write_32(APU_PWRCTL, r); |
|||
|
|||
/* power up island */ |
|||
mmio_write_32(PMU_GLOBAL_REQ_PWRUP_EN, 1 << cpu_id); |
|||
mmio_write_32(PMU_GLOBAL_REQ_PWRUP_TRIG, 1 << cpu_id); |
|||
/* FIXME: we should have a way to break out */ |
|||
while (mmio_read_32(PMU_GLOBAL_REQ_PWRUP_STATUS) & (1 << cpu_id)) |
|||
; |
|||
|
|||
/* release core reset */ |
|||
r = mmio_read_32(CRF_APB_RST_FPD_APU); |
|||
r &= ~((CRF_APB_RST_FPD_APU_ACPU_PWRON_RESET | |
|||
CRF_APB_RST_FPD_APU_ACPU_RESET) << cpu_id); |
|||
mmio_write_32(CRF_APB_RST_FPD_APU, r); |
|||
|
|||
return PSCI_E_SUCCESS; |
|||
} |
|||
|
|||
static int zynqmp_pwr_domain_on(u_register_t mpidr) |
|||
{ |
|||
unsigned int cpu_id = plat_core_pos_by_mpidr(mpidr); |
|||
const struct pm_proc *proc; |
|||
|
|||
VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr); |
|||
|
|||
if (cpu_id == -1) |
|||
return PSCI_E_INTERN_FAIL; |
|||
|
|||
proc = pm_get_proc(cpu_id); |
|||
|
|||
/* Send request to PMU to wake up selected APU CPU core */ |
|||
pm_req_wakeup(proc->node_id, 1, zynqmp_sec_entry, REQ_ACK_NO); |
|||
|
|||
return PSCI_E_SUCCESS; |
|||
} |
|||
|
|||
static void zynqmp_nopmu_pwr_domain_off(const psci_power_state_t *target_state) |
|||
{ |
|||
uint32_t r; |
|||
unsigned int cpu_id = plat_my_core_pos(); |
|||
|
|||
for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) |
|||
VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", |
|||
__func__, i, target_state->pwr_domain_state[i]); |
|||
|
|||
/* Prevent interrupts from spuriously waking up this cpu */ |
|||
gicv2_cpuif_disable(); |
|||
|
|||
/* set power down request */ |
|||
r = mmio_read_32(APU_PWRCTL); |
|||
r |= (1 << cpu_id); |
|||
mmio_write_32(APU_PWRCTL, r); |
|||
} |
|||
|
|||
static void zynqmp_pwr_domain_off(const psci_power_state_t *target_state) |
|||
{ |
|||
unsigned int cpu_id = plat_my_core_pos(); |
|||
const struct pm_proc *proc = pm_get_proc(cpu_id); |
|||
|
|||
for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) |
|||
VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", |
|||
__func__, i, target_state->pwr_domain_state[i]); |
|||
|
|||
/* Prevent interrupts from spuriously waking up this cpu */ |
|||
gicv2_cpuif_disable(); |
|||
|
|||
/*
|
|||
* Send request to PMU to power down the appropriate APU CPU |
|||
* core. |
|||
* According to PSCI specification, CPU_off function does not |
|||
* have resume address and CPU core can only be woken up |
|||
* invoking CPU_on function, during which resume address will |
|||
* be set. |
|||
*/ |
|||
pm_self_suspend(proc->node_id, MAX_LATENCY, 0, 0); |
|||
} |
|||
|
|||
static void zynqmp_nopmu_pwr_domain_suspend(const psci_power_state_t *target_state) |
|||
{ |
|||
uint32_t r; |
|||
unsigned int cpu_id = plat_my_core_pos(); |
|||
|
|||
for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) |
|||
VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", |
|||
__func__, i, target_state->pwr_domain_state[i]); |
|||
|
|||
/* set power down request */ |
|||
r = mmio_read_32(APU_PWRCTL); |
|||
r |= (1 << cpu_id); |
|||
mmio_write_32(APU_PWRCTL, r); |
|||
|
|||
/* program RVBAR */ |
|||
mmio_write_32(APU_RVBAR_L_0 + (cpu_id << 3), zynqmp_sec_entry); |
|||
mmio_write_32(APU_RVBAR_H_0 + (cpu_id << 3), zynqmp_sec_entry >> 32); |
|||
|
|||
/* clear VINITHI */ |
|||
r = mmio_read_32(APU_CONFIG_0); |
|||
r &= ~(1 << APU_CONFIG_0_VINITHI_SHIFT << cpu_id); |
|||
mmio_write_32(APU_CONFIG_0, r); |
|||
|
|||
/* enable power up on IRQ */ |
|||
mmio_write_32(PMU_GLOBAL_REQ_PWRUP_EN, 1 << cpu_id); |
|||
} |
|||
|
|||
static void zynqmp_pwr_domain_suspend(const psci_power_state_t *target_state) |
|||
{ |
|||
unsigned int cpu_id = plat_my_core_pos(); |
|||
const struct pm_proc *proc = pm_get_proc(cpu_id); |
|||
|
|||
for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) |
|||
VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", |
|||
__func__, i, target_state->pwr_domain_state[i]); |
|||
|
|||
/* Send request to PMU to suspend this core */ |
|||
pm_self_suspend(proc->node_id, MAX_LATENCY, 0, 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(); |
|||
} |
|||
} |
|||
|
|||
static void zynqmp_pwr_domain_on_finish(const psci_power_state_t *target_state) |
|||
{ |
|||
for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) |
|||
VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", |
|||
__func__, i, target_state->pwr_domain_state[i]); |
|||
|
|||
gicv2_cpuif_enable(); |
|||
gicv2_pcpu_distif_init(); |
|||
} |
|||
|
|||
static void zynqmp_nopmu_pwr_domain_suspend_finish(const psci_power_state_t *target_state) |
|||
{ |
|||
uint32_t r; |
|||
unsigned int cpu_id = plat_my_core_pos(); |
|||
|
|||
for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) |
|||
VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", |
|||
__func__, i, target_state->pwr_domain_state[i]); |
|||
|
|||
/* disable power up on IRQ */ |
|||
mmio_write_32(PMU_GLOBAL_REQ_PWRUP_DIS, 1 << cpu_id); |
|||
|
|||
/* clear powerdown bit */ |
|||
r = mmio_read_32(APU_PWRCTL); |
|||
r &= ~(1 << cpu_id); |
|||
mmio_write_32(APU_PWRCTL, r); |
|||
} |
|||
|
|||
static void zynqmp_pwr_domain_suspend_finish(const psci_power_state_t *target_state) |
|||
{ |
|||
unsigned int cpu_id = plat_my_core_pos(); |
|||
const struct pm_proc *proc = pm_get_proc(cpu_id); |
|||
|
|||
for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) |
|||
VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", |
|||
__func__, i, target_state->pwr_domain_state[i]); |
|||
|
|||
/* Clear the APU power control register for this cpu */ |
|||
pm_client_wakeup(proc); |
|||
|
|||
/* enable coherency */ |
|||
plat_arm_interconnect_enter_coherency(); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* ZynqMP handlers to shutdown/reboot the system |
|||
******************************************************************************/ |
|||
static void __dead2 zynqmp_nopmu_system_off(void) |
|||
{ |
|||
ERROR("ZynqMP System Off: operation not handled.\n"); |
|||
|
|||
/* disable coherency */ |
|||
plat_arm_interconnect_exit_coherency(); |
|||
|
|||
panic(); |
|||
} |
|||
|
|||
static void __dead2 zynqmp_system_off(void) |
|||
{ |
|||
/* disable coherency */ |
|||
plat_arm_interconnect_exit_coherency(); |
|||
|
|||
/* Send the power down request to the PMU */ |
|||
pm_system_shutdown(0); |
|||
|
|||
while (1) |
|||
wfi(); |
|||
} |
|||
|
|||
static void __dead2 zynqmp_nopmu_system_reset(void) |
|||
{ |
|||
/*
|
|||
* This currently triggers a system reset. I.e. the whole |
|||
* system will be reset! Including RPUs, PMU, PL, etc. |
|||
*/ |
|||
|
|||
/* disable coherency */ |
|||
plat_arm_interconnect_exit_coherency(); |
|||
|
|||
/* bypass RPLL (needed on 1.0 silicon) */ |
|||
uint32_t reg = mmio_read_32(CRL_APB_RPLL_CTRL); |
|||
reg |= CRL_APB_RPLL_CTRL_BYPASS; |
|||
mmio_write_32(CRL_APB_RPLL_CTRL, reg); |
|||
|
|||
/* trigger system reset */ |
|||
mmio_write_32(CRL_APB_RESET_CTRL, CRL_APB_RESET_CTRL_SOFT_RESET); |
|||
|
|||
while (1) |
|||
wfi(); |
|||
} |
|||
|
|||
static void __dead2 zynqmp_system_reset(void) |
|||
{ |
|||
/* disable coherency */ |
|||
plat_arm_interconnect_exit_coherency(); |
|||
|
|||
/* Send the system reset request to the PMU */ |
|||
pm_system_shutdown(1); |
|||
|
|||
while (1) |
|||
wfi(); |
|||
} |
|||
|
|||
int zynqmp_validate_power_state(unsigned int power_state, |
|||
psci_power_state_t *req_state) |
|||
{ |
|||
VERBOSE("%s: power_state: 0x%x\n", __func__, power_state); |
|||
|
|||
/* FIXME: populate req_state */ |
|||
return PSCI_E_SUCCESS; |
|||
} |
|||
|
|||
int zynqmp_validate_ns_entrypoint(unsigned long ns_entrypoint) |
|||
{ |
|||
VERBOSE("%s: ns_entrypoint: 0x%lx\n", __func__, ns_entrypoint); |
|||
|
|||
/* FIXME: Actually validate */ |
|||
return PSCI_E_SUCCESS; |
|||
} |
|||
|
|||
void zynqmp_get_sys_suspend_power_state(psci_power_state_t *req_state) |
|||
{ |
|||
req_state->pwr_domain_state[PSCI_CPU_PWR_LVL] = PLAT_MAX_OFF_STATE; |
|||
req_state->pwr_domain_state[1] = PLAT_MAX_OFF_STATE; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Export the platform handlers to enable psci to invoke them |
|||
******************************************************************************/ |
|||
static const struct plat_psci_ops zynqmp_psci_ops = { |
|||
.cpu_standby = zynqmp_cpu_standby, |
|||
.pwr_domain_on = zynqmp_pwr_domain_on, |
|||
.pwr_domain_off = zynqmp_pwr_domain_off, |
|||
.pwr_domain_suspend = zynqmp_pwr_domain_suspend, |
|||
.pwr_domain_on_finish = zynqmp_pwr_domain_on_finish, |
|||
.pwr_domain_suspend_finish = zynqmp_pwr_domain_suspend_finish, |
|||
.system_off = zynqmp_system_off, |
|||
.system_reset = zynqmp_system_reset, |
|||
.validate_power_state = zynqmp_validate_power_state, |
|||
.validate_ns_entrypoint = zynqmp_validate_ns_entrypoint, |
|||
.get_sys_suspend_power_state = zynqmp_get_sys_suspend_power_state, |
|||
}; |
|||
|
|||
static const struct plat_psci_ops zynqmp_nopmu_psci_ops = { |
|||
.cpu_standby = zynqmp_cpu_standby, |
|||
.pwr_domain_on = zynqmp_nopmu_pwr_domain_on, |
|||
.pwr_domain_off = zynqmp_nopmu_pwr_domain_off, |
|||
.pwr_domain_suspend = zynqmp_nopmu_pwr_domain_suspend, |
|||
.pwr_domain_on_finish = zynqmp_pwr_domain_on_finish, |
|||
.pwr_domain_suspend_finish = zynqmp_nopmu_pwr_domain_suspend_finish, |
|||
.system_off = zynqmp_nopmu_system_off, |
|||
.system_reset = zynqmp_nopmu_system_reset, |
|||
.validate_power_state = zynqmp_validate_power_state, |
|||
.validate_ns_entrypoint = zynqmp_validate_ns_entrypoint, |
|||
.get_sys_suspend_power_state = zynqmp_get_sys_suspend_power_state, |
|||
}; |
|||
|
|||
/*******************************************************************************
|
|||
* Export the platform specific power ops. |
|||
******************************************************************************/ |
|||
int plat_setup_psci_ops(uintptr_t sec_entrypoint, |
|||
const struct plat_psci_ops **psci_ops) |
|||
{ |
|||
zynqmp_sec_entry = sec_entrypoint; |
|||
|
|||
if (zynqmp_is_pmu_up()) |
|||
*psci_ops = &zynqmp_psci_ops; |
|||
else |
|||
*psci_ops = &zynqmp_nopmu_psci_ops; |
|||
|
|||
return 0; |
|||
} |
@ -0,0 +1,39 @@ |
|||
/*
|
|||
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#include <platform_def.h> |
|||
#include <psci.h> |
|||
|
|||
static const unsigned char plat_power_domain_tree_desc[] = {1, 4}; |
|||
|
|||
const unsigned char *plat_get_power_domain_tree_desc(void) |
|||
{ |
|||
return plat_power_domain_tree_desc; |
|||
} |
@ -0,0 +1,42 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#include <plat_arm.h> |
|||
|
|||
int plat_core_pos_by_mpidr(u_register_t mpidr) |
|||
{ |
|||
if (mpidr & MPIDR_CLUSTER_MASK) |
|||
return -1; |
|||
|
|||
if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT) |
|||
return -1; |
|||
|
|||
return plat_arm_calc_core_pos(mpidr); |
|||
} |
@ -0,0 +1,95 @@ |
|||
# Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
|
|||
#
|
|||
# Redistribution and use in source and binary forms, with or without
|
|||
# modification, are permitted provided that the following conditions are met:
|
|||
#
|
|||
# Redistributions of source code must retain the above copyright notice, this
|
|||
# list of conditions and the following disclaimer.
|
|||
#
|
|||
# Redistributions in binary form must reproduce the above copyright notice,
|
|||
# this list of conditions and the following disclaimer in the documentation
|
|||
# and/or other materials provided with the distribution.
|
|||
#
|
|||
# Neither the name of ARM nor the names of its contributors may be used
|
|||
# to endorse or promote products derived from this software without specific
|
|||
# prior written permission.
|
|||
#
|
|||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|||
# POSSIBILITY OF SUCH DAMAGE.
|
|||
|
|||
ENABLE_PLAT_COMPAT := 0 |
|||
PROGRAMMABLE_RESET_ADDRESS := 1 |
|||
PSCI_EXTENDED_STATE_ID := 1 |
|||
A53_DISABLE_NON_TEMPORAL_HINT := 0 |
|||
|
|||
ZYNQMP_ATF_LOCATION ?= tsram |
|||
ifeq (${ZYNQMP_ATF_LOCATION}, tsram) |
|||
ZYNQMP_ATF_LOCATION_ID := ZYNQMP_IN_TRUSTED_SRAM |
|||
else ifeq (${ZYNQMP_ATF_LOCATION}, tdram) |
|||
ZYNQMP_ATF_LOCATION_ID := ZYNQMP_IN_TRUSTED_DRAM |
|||
else |
|||
$(error "Unsupported ZYNQMP_ATF_LOCATION value") |
|||
endif |
|||
|
|||
# On ZYNQMP, the TSP can execute either from Trusted SRAM or Trusted DRAM.
|
|||
# Trusted SRAM is the default.
|
|||
ZYNQMP_TSP_RAM_LOCATION ?= tsram |
|||
ifeq (${ZYNQMP_TSP_RAM_LOCATION}, tsram) |
|||
ZYNQMP_TSP_RAM_LOCATION_ID := ZYNQMP_IN_TRUSTED_SRAM |
|||
else ifeq (${ZYNQMP_TSP_RAM_LOCATION}, tdram) |
|||
ZYNQMP_TSP_RAM_LOCATION_ID := ZYNQMP_IN_TRUSTED_DRAM |
|||
else |
|||
$(error "Unsupported ZYNQMP_TSP_RAM_LOCATION value") |
|||
endif |
|||
|
|||
# Process flags
|
|||
$(eval $(call add_define,ZYNQMP_ATF_LOCATION_ID)) |
|||
$(eval $(call add_define,ZYNQMP_TSP_RAM_LOCATION_ID)) |
|||
|
|||
PLAT_INCLUDES := -Iinclude/plat/arm/common/ \
|
|||
-Iinclude/plat/arm/common/aarch64/ \
|
|||
-Iplat/xilinx/zynqmp/include/ \
|
|||
-Iplat/xilinx/zynqmp/pm_service/ |
|||
|
|||
PLAT_BL_COMMON_SOURCES := lib/aarch64/xlat_tables.c \
|
|||
drivers/arm/gic/common/gic_common.c \
|
|||
drivers/arm/gic/v2/gicv2_main.c \
|
|||
drivers/arm/gic/v2/gicv2_helpers.c \
|
|||
drivers/cadence/uart/cdns_console.S \
|
|||
drivers/console/console.S \
|
|||
plat/arm/common/aarch64/arm_common.c \
|
|||
plat/arm/common/aarch64/arm_helpers.S \
|
|||
plat/arm/common/arm_cci.c \
|
|||
plat/arm/common/arm_gicv2.c \
|
|||
plat/common/plat_gicv2.c \
|
|||
plat/common/aarch64/plat_common.c \
|
|||
plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S \
|
|||
plat/xilinx/zynqmp/aarch64/zynqmp_common.c |
|||
|
|||
BL31_SOURCES += drivers/arm/cci/cci.c \
|
|||
lib/cpus/aarch64/aem_generic.S \
|
|||
lib/cpus/aarch64/cortex_a53.S \
|
|||
plat/common/aarch64/plat_psci_common.c \
|
|||
plat/common/aarch64/platform_mp_stack.S \
|
|||
plat/xilinx/zynqmp/bl31_zynqmp_setup.c \
|
|||
plat/xilinx/zynqmp/plat_psci.c \
|
|||
plat/xilinx/zynqmp/plat_zynqmp.c \
|
|||
plat/xilinx/zynqmp/plat_topology.c \
|
|||
plat/xilinx/zynqmp/sip_svc_setup.c \
|
|||
plat/xilinx/zynqmp/pm_service/pm_svc_main.c \
|
|||
plat/xilinx/zynqmp/pm_service/pm_api_sys.c \
|
|||
plat/xilinx/zynqmp/pm_service/pm_ipi.c \
|
|||
plat/xilinx/zynqmp/pm_service/pm_client.c |
|||
|
|||
ifneq (${RESET_TO_BL31},1) |
|||
$(error "Using BL31 as the reset vector is only one option supported on ZynqMP. Please set RESET_TO_BL31 to 1.") |
|||
endif |
@ -0,0 +1,485 @@ |
|||
/*
|
|||
* Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
/*
|
|||
* ZynqMP system level PM-API functions and communication with PMU via |
|||
* IPI interrupts |
|||
*/ |
|||
|
|||
#include <arch_helpers.h> |
|||
#include <platform.h> |
|||
#include "pm_client.h" |
|||
#include "pm_common.h" |
|||
#include "pm_api_sys.h" |
|||
|
|||
/**
|
|||
* Assigning of argument values into array elements. |
|||
*/ |
|||
#define PM_PACK_PAYLOAD1(pl, arg0) { \ |
|||
pl[0] = (uint32_t)(arg0); \ |
|||
} |
|||
|
|||
#define PM_PACK_PAYLOAD2(pl, arg0, arg1) { \ |
|||
pl[1] = (uint32_t)(arg1); \ |
|||
PM_PACK_PAYLOAD1(pl, arg0); \ |
|||
} |
|||
|
|||
#define PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2) { \ |
|||
pl[2] = (uint32_t)(arg2); \ |
|||
PM_PACK_PAYLOAD2(pl, arg0, arg1); \ |
|||
} |
|||
|
|||
#define PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3) { \ |
|||
pl[3] = (uint32_t)(arg3); \ |
|||
PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2); \ |
|||
} |
|||
|
|||
#define PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4) { \ |
|||
pl[4] = (uint32_t)(arg4); \ |
|||
PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3); \ |
|||
} |
|||
|
|||
#define PM_PACK_PAYLOAD6(pl, arg0, arg1, arg2, arg3, arg4, arg5) { \ |
|||
pl[5] = (uint32_t)(arg5); \ |
|||
PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4); \ |
|||
} |
|||
|
|||
/**
|
|||
* 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) |
|||
* @address Resume address |
|||
* |
|||
* This is a blocking call, it will return only once PMU has responded. |
|||
* On a wakeup, resume address will be automatically set by PMU. |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
enum pm_ret_status pm_self_suspend(enum pm_node_id nid, |
|||
unsigned int latency, |
|||
unsigned int state, |
|||
uintptr_t address) |
|||
{ |
|||
uint32_t payload[PAYLOAD_ARG_CNT]; |
|||
unsigned int cpuid = plat_my_core_pos(); |
|||
const struct pm_proc *proc = pm_get_proc(cpuid); |
|||
|
|||
/*
|
|||
* Do client specific suspend operations |
|||
* (e.g. set powerdown request bit) |
|||
*/ |
|||
pm_client_suspend(proc); |
|||
/* Send request to the PMU */ |
|||
PM_PACK_PAYLOAD6(payload, PM_SELF_SUSPEND, proc->node_id, latency, |
|||
state, address, (address >> 32)); |
|||
return pm_ipi_send_sync(proc, payload, NULL); |
|||
} |
|||
|
|||
/**
|
|||
* pm_req_suspend() - PM call to request for another PU or subsystem to |
|||
* be suspended gracefully. |
|||
* @target Node id of the targeted PU or subsystem |
|||
* @ack Flag to specify whether acknowledge is requested |
|||
* @latency Requested wakeup latency (not supported) |
|||
* @state Requested state (not supported) |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
enum pm_ret_status pm_req_suspend(enum pm_node_id target, |
|||
enum pm_request_ack ack, |
|||
unsigned int latency, unsigned int state) |
|||
{ |
|||
uint32_t payload[PAYLOAD_ARG_CNT]; |
|||
|
|||
/* Send request to the PMU */ |
|||
PM_PACK_PAYLOAD5(payload, PM_REQ_SUSPEND, target, ack, latency, state); |
|||
if (ack == REQ_ACK_BLOCKING) |
|||
return pm_ipi_send_sync(primary_proc, payload, NULL); |
|||
else |
|||
return pm_ipi_send(primary_proc, payload); |
|||
} |
|||
|
|||
/**
|
|||
* pm_req_wakeup() - PM call for processor to wake up selected processor |
|||
* or subsystem |
|||
* @target Node id of the processor or subsystem to wake up |
|||
* @ack Flag to specify whether acknowledge requested |
|||
* @set_address Resume address presence indicator |
|||
* 1 resume address specified, 0 otherwise |
|||
* @address Resume address |
|||
* |
|||
* This API function is either used to power up another APU core for SMP |
|||
* (by PSCI) or to power up an entirely different PU or subsystem, such |
|||
* as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be |
|||
* automatically set by PMU. |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
enum pm_ret_status pm_req_wakeup(enum pm_node_id target, |
|||
unsigned int set_address, |
|||
uintptr_t address, |
|||
enum pm_request_ack ack) |
|||
{ |
|||
uint32_t payload[PAYLOAD_ARG_CNT]; |
|||
uint64_t encoded_address; |
|||
const struct pm_proc *proc = pm_get_proc_by_node(target); |
|||
|
|||
/* invoke APU-specific code for waking up another APU core */ |
|||
pm_client_wakeup(proc); |
|||
|
|||
/* encode set Address into 1st bit of address */ |
|||
encoded_address = address; |
|||
encoded_address |= !!set_address; |
|||
|
|||
/* Send request to the PMU to perform the wake of the PU */ |
|||
PM_PACK_PAYLOAD5(payload, PM_REQ_WAKEUP, target, encoded_address, |
|||
encoded_address >> 32, ack); |
|||
|
|||
if (ack == REQ_ACK_BLOCKING) |
|||
return pm_ipi_send_sync(primary_proc, payload, NULL); |
|||
else |
|||
return pm_ipi_send(primary_proc, payload); |
|||
} |
|||
|
|||
/**
|
|||
* pm_force_powerdown() - PM call to request for another PU or subsystem to |
|||
* be powered down forcefully |
|||
* @target Node id of the targeted PU or subsystem |
|||
* @ack Flag to specify whether acknowledge is requested |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
enum pm_ret_status pm_force_powerdown(enum pm_node_id target, |
|||
enum pm_request_ack ack) |
|||
{ |
|||
uint32_t payload[PAYLOAD_ARG_CNT]; |
|||
|
|||
/* Send request to the PMU */ |
|||
PM_PACK_PAYLOAD3(payload, PM_FORCE_POWERDOWN, target, ack); |
|||
|
|||
if (ack == REQ_ACK_BLOCKING) |
|||
return pm_ipi_send_sync(primary_proc, payload, NULL); |
|||
else |
|||
return pm_ipi_send(primary_proc, payload); |
|||
} |
|||
|
|||
/**
|
|||
* pm_abort_suspend() - PM call to announce that a prior suspend request |
|||
* is to be aborted. |
|||
* @reason Reason for the abort |
|||
* |
|||
* Calling PU expects the PMU to abort the initiated suspend procedure. |
|||
* This is a non-blocking call without any acknowledge. |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason) |
|||
{ |
|||
uint32_t payload[PAYLOAD_ARG_CNT]; |
|||
|
|||
/*
|
|||
* Do client specific abort suspend operations |
|||
* (e.g. enable interrupts and clear powerdown request bit) |
|||
*/ |
|||
pm_client_abort_suspend(); |
|||
/* Send request to the PMU */ |
|||
/* TODO: allow passing the node ID of the affected CPU */ |
|||
PM_PACK_PAYLOAD3(payload, PM_ABORT_SUSPEND, reason, |
|||
primary_proc->node_id); |
|||
return pm_ipi_send(primary_proc, payload); |
|||
} |
|||
|
|||
/**
|
|||
* pm_set_wakeup_source() - PM call to specify the wakeup source while suspended |
|||
* @target Node id of the targeted PU or subsystem |
|||
* @wkup_node Node id of the wakeup peripheral |
|||
* @enable Enable or disable the specified peripheral as wake source |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target, |
|||
enum pm_node_id wkup_node, |
|||
unsigned int enable) |
|||
{ |
|||
uint32_t payload[PAYLOAD_ARG_CNT]; |
|||
|
|||
PM_PACK_PAYLOAD4(payload, PM_SET_WAKEUP_SOURCE, target, wkup_node, |
|||
enable); |
|||
return pm_ipi_send(primary_proc, payload); |
|||
} |
|||
|
|||
/**
|
|||
* pm_system_shutdown() - PM call to request a system shutdown or restart |
|||
* @restart Shutdown or restart? 0 for shutdown, 1 for restart |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
enum pm_ret_status pm_system_shutdown(unsigned int restart) |
|||
{ |
|||
uint32_t payload[PAYLOAD_ARG_CNT]; |
|||
|
|||
PM_PACK_PAYLOAD2(payload, PM_SYSTEM_SHUTDOWN, restart); |
|||
return pm_ipi_send(primary_proc, payload); |
|||
} |
|||
|
|||
/* APIs for managing PM slaves: */ |
|||
|
|||
/**
|
|||
* pm_req_node() - PM call to request a node with specific capabilities |
|||
* @nid Node id of the slave |
|||
* @capabilities Requested capabilities of the slave |
|||
* @qos Quality of service (not supported) |
|||
* @ack Flag to specify whether acknowledge is requested |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
enum pm_ret_status pm_req_node(enum pm_node_id nid, |
|||
unsigned int capabilities, |
|||
unsigned int qos, |
|||
enum pm_request_ack ack) |
|||
{ |
|||
uint32_t payload[PAYLOAD_ARG_CNT]; |
|||
|
|||
PM_PACK_PAYLOAD5(payload, PM_REQ_NODE, nid, capabilities, qos, ack); |
|||
|
|||
if (ack == REQ_ACK_BLOCKING) |
|||
return pm_ipi_send_sync(primary_proc, payload, NULL); |
|||
else |
|||
return pm_ipi_send(primary_proc, payload); |
|||
} |
|||
|
|||
/**
|
|||
* pm_set_requirement() - PM call to set requirement for PM slaves |
|||
* @nid Node id of the slave |
|||
* @capabilities Requested capabilities of the slave |
|||
* @qos Quality of service (not supported) |
|||
* @ack Flag to specify whether acknowledge is requested |
|||
* |
|||
* This API function is to be used for slaves a PU already has requested |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
enum pm_ret_status pm_set_requirement(enum pm_node_id nid, |
|||
unsigned int capabilities, |
|||
unsigned int qos, |
|||
enum pm_request_ack ack) |
|||
{ |
|||
uint32_t payload[PAYLOAD_ARG_CNT]; |
|||
|
|||
PM_PACK_PAYLOAD5(payload, PM_SET_REQUIREMENT, nid, capabilities, qos, |
|||
ack); |
|||
|
|||
if (ack == REQ_ACK_BLOCKING) |
|||
return pm_ipi_send_sync(primary_proc, payload, NULL); |
|||
else |
|||
return pm_ipi_send(primary_proc, payload); |
|||
} |
|||
|
|||
/**
|
|||
* pm_release_node() - PM call to release a node |
|||
* @nid Node id of the slave |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
enum pm_ret_status pm_release_node(enum pm_node_id nid) |
|||
{ |
|||
uint32_t payload[PAYLOAD_ARG_CNT]; |
|||
|
|||
PM_PACK_PAYLOAD2(payload, PM_RELEASE_NODE, nid); |
|||
return pm_ipi_send(primary_proc, payload); |
|||
} |
|||
|
|||
/**
|
|||
* pm_set_max_latency() - PM call to set wakeup latency requirements |
|||
* @nid Node id of the slave |
|||
* @latency Requested maximum wakeup latency |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
enum pm_ret_status pm_set_max_latency(enum pm_node_id nid, |
|||
unsigned int latency) |
|||
{ |
|||
uint32_t payload[PAYLOAD_ARG_CNT]; |
|||
|
|||
PM_PACK_PAYLOAD3(payload, PM_SET_MAX_LATENCY, nid, latency); |
|||
return pm_ipi_send(primary_proc, payload); |
|||
} |
|||
|
|||
/* Miscellaneous API functions */ |
|||
|
|||
/**
|
|||
* pm_get_api_version() - Get version number of PMU PM firmware |
|||
* @version Returns 32-bit version number of PMU Power Management Firmware |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
enum pm_ret_status pm_get_api_version(unsigned int *version) |
|||
{ |
|||
uint32_t payload[PAYLOAD_ARG_CNT]; |
|||
|
|||
/* Send request to the PMU */ |
|||
PM_PACK_PAYLOAD1(payload, PM_GET_API_VERSION); |
|||
return pm_ipi_send_sync(primary_proc, payload, version); |
|||
} |
|||
|
|||
/**
|
|||
* pm_set_configuration() - PM call to set system configuration |
|||
* @phys_addr Physical 32-bit address of data structure in memory |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
enum pm_ret_status pm_set_configuration(unsigned int phys_addr) |
|||
{ |
|||
return PM_RET_ERROR_NOTSUPPORTED; |
|||
} |
|||
|
|||
/**
|
|||
* pm_get_node_status() - PM call to request a node's current power state |
|||
* @nid Node id of the slave |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
enum pm_ret_status pm_get_node_status(enum pm_node_id nid) |
|||
{ |
|||
/* TODO: Add power state argument!! */ |
|||
uint32_t payload[PAYLOAD_ARG_CNT]; |
|||
|
|||
PM_PACK_PAYLOAD2(payload, PM_GET_NODE_STATUS, nid); |
|||
return pm_ipi_send(primary_proc, payload); |
|||
} |
|||
|
|||
/**
|
|||
* pm_register_notifier() - Register the PU to be notified of PM events |
|||
* @nid Node id of the slave |
|||
* @event The event to be notified about |
|||
* @wake Wake up on event |
|||
* @enable Enable or disable the notifier |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
enum pm_ret_status pm_register_notifier(enum pm_node_id nid, |
|||
unsigned int event, |
|||
unsigned int wake, |
|||
unsigned int enable) |
|||
{ |
|||
return PM_RET_ERROR_NOTSUPPORTED; |
|||
} |
|||
|
|||
/**
|
|||
* pm_get_op_characteristic() - PM call to get a particular operating |
|||
* characteristic of a node |
|||
* @nid Node ID |
|||
* @type Operating characterstic type to be returned |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
enum pm_ret_status pm_get_op_characteristic(enum pm_node_id nid, |
|||
enum pm_opchar_type type) |
|||
{ |
|||
return PM_RET_ERROR_NOTSUPPORTED; |
|||
} |
|||
|
|||
/* Direct-Control API functions */ |
|||
|
|||
/**
|
|||
* pm_reset_assert() - Assert reset |
|||
* @reset Reset ID |
|||
* @assert Assert (1) or de-assert (0) |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
enum pm_ret_status pm_reset_assert(unsigned int reset, |
|||
unsigned int assert) |
|||
{ |
|||
uint32_t payload[PAYLOAD_ARG_CNT]; |
|||
|
|||
/* Send request to the PMU */ |
|||
PM_PACK_PAYLOAD3(payload, PM_RESET_ASSERT, reset, assert); |
|||
return pm_ipi_send(primary_proc, payload); |
|||
} |
|||
|
|||
/**
|
|||
* pm_reset_get_status() - Get current status of a reset line |
|||
* @reset Reset ID |
|||
* @reset_status Returns current status of selected reset line |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
enum pm_ret_status pm_reset_get_status(unsigned int reset, |
|||
unsigned int *reset_status) |
|||
{ |
|||
uint32_t payload[PAYLOAD_ARG_CNT]; |
|||
|
|||
/* Send request to the PMU */ |
|||
PM_PACK_PAYLOAD2(payload, PM_RESET_GET_STATUS, reset); |
|||
return pm_ipi_send_sync(primary_proc, payload, reset_status); |
|||
} |
|||
|
|||
/**
|
|||
* pm_mmio_write() - Perform write to protected mmio |
|||
* @address Address to write to |
|||
* @mask Mask to apply |
|||
* @value Value to write |
|||
* |
|||
* This function provides access to PM-related control registers |
|||
* that may not be directly accessible by a particular PU. |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
enum pm_ret_status pm_mmio_write(uintptr_t address, |
|||
unsigned int mask, |
|||
unsigned int value) |
|||
{ |
|||
uint32_t payload[PAYLOAD_ARG_CNT]; |
|||
|
|||
/* Send request to the PMU */ |
|||
PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value); |
|||
return pm_ipi_send(primary_proc, payload); |
|||
} |
|||
|
|||
/**
|
|||
* pm_mmio_read() - Read value from protected mmio |
|||
* @address Address to write to |
|||
* @value Value to write |
|||
* |
|||
* This function provides access to PM-related control registers |
|||
* that may not be directly accessible by a particular PU. |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value) |
|||
{ |
|||
uint32_t payload[PAYLOAD_ARG_CNT]; |
|||
|
|||
/* Send request to the PMU */ |
|||
PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address); |
|||
return pm_ipi_send_sync(primary_proc, payload, value); |
|||
} |
@ -0,0 +1,111 @@ |
|||
/*
|
|||
* Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#ifndef _PM_API_SYS_H_ |
|||
#define _PM_API_SYS_H_ |
|||
|
|||
#include <stdint.h> |
|||
#include "pm_defs.h" |
|||
|
|||
/**********************************************************
|
|||
* System-level API function declarations |
|||
**********************************************************/ |
|||
enum pm_ret_status pm_req_suspend(enum pm_node_id nid, |
|||
enum pm_request_ack ack, |
|||
unsigned int latency, |
|||
unsigned int state); |
|||
|
|||
enum pm_ret_status pm_self_suspend(enum pm_node_id nid, |
|||
unsigned int latency, |
|||
unsigned int state, |
|||
uintptr_t address); |
|||
|
|||
enum pm_ret_status pm_force_powerdown(enum pm_node_id nid, |
|||
enum pm_request_ack ack); |
|||
|
|||
enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason); |
|||
|
|||
enum pm_ret_status pm_req_wakeup(enum pm_node_id nid, |
|||
unsigned int set_address, |
|||
uintptr_t address, |
|||
enum pm_request_ack ack); |
|||
|
|||
enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target, |
|||
enum pm_node_id wkup_node, |
|||
unsigned int enable); |
|||
|
|||
enum pm_ret_status pm_system_shutdown(unsigned int restart); |
|||
|
|||
enum pm_ret_status pm_init_suspend_cb(enum pm_suspend_reason reason, |
|||
unsigned int latency, |
|||
unsigned int state, |
|||
unsigned int timeout); |
|||
|
|||
/* API functions for managing PM Slaves */ |
|||
enum pm_ret_status pm_req_node(enum pm_node_id nid, |
|||
unsigned int capabilities, |
|||
unsigned int qos, |
|||
enum pm_request_ack ack); |
|||
enum pm_ret_status pm_release_node(enum pm_node_id nid); |
|||
|
|||
enum pm_ret_status pm_set_requirement(enum pm_node_id nid, |
|||
unsigned int capabilities, |
|||
unsigned int qos, |
|||
enum pm_request_ack ack); |
|||
enum pm_ret_status pm_set_max_latency(enum pm_node_id nid, |
|||
unsigned int latency); |
|||
|
|||
/* Miscellaneous API functions */ |
|||
enum pm_ret_status pm_get_api_version(unsigned int *version); |
|||
enum pm_ret_status pm_set_configuration(unsigned int phys_addr); |
|||
enum pm_ret_status pm_get_node_status(enum pm_node_id node); |
|||
enum pm_ret_status pm_register_notifier(enum pm_node_id nid, |
|||
unsigned int event, |
|||
unsigned int wake, |
|||
unsigned int enable); |
|||
enum pm_ret_status pm_get_op_characteristic(enum pm_node_id nid, |
|||
enum pm_opchar_type type); |
|||
enum pm_ret_status pm_acknowledge_cb(enum pm_node_id nid, |
|||
enum pm_ret_status status, |
|||
unsigned int oppoint); |
|||
enum pm_ret_status pm_notify_cb(enum pm_node_id nid, |
|||
unsigned int event, |
|||
unsigned int oppoint); |
|||
|
|||
/* Direct-Control API functions */ |
|||
enum pm_ret_status pm_reset_assert(unsigned int reset_id, |
|||
unsigned int assert); |
|||
enum pm_ret_status pm_reset_get_status(unsigned int reset_id, |
|||
unsigned int *reset_status); |
|||
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); |
|||
#endif /* _PM_API_SYS_H_ */ |
@ -0,0 +1,202 @@ |
|||
/*
|
|||
* Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
/*
|
|||
* APU specific definition of processors in the subsystem as well as functions |
|||
* for getting information about and changing state of the APU. |
|||
*/ |
|||
|
|||
#include <gicv2.h> |
|||
#include <bl_common.h> |
|||
#include <mmio.h> |
|||
#include "pm_api_sys.h" |
|||
#include "pm_client.h" |
|||
#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) |
|||
|
|||
/* 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 */ |
|||
static const struct pm_proc const pm_procs_all[] = { |
|||
{ |
|||
.node_id = NODE_APU_0, |
|||
.pwrdn_mask = APU_0_PWRCTL_CPUPWRDWNREQ_MASK, |
|||
.ipi = &apu_ipi, |
|||
}, |
|||
{ |
|||
.node_id = NODE_APU_1, |
|||
.pwrdn_mask = APU_1_PWRCTL_CPUPWRDWNREQ_MASK, |
|||
.ipi = &apu_ipi, |
|||
}, |
|||
{ |
|||
.node_id = NODE_APU_2, |
|||
.pwrdn_mask = APU_2_PWRCTL_CPUPWRDWNREQ_MASK, |
|||
.ipi = &apu_ipi, |
|||
}, |
|||
{ |
|||
.node_id = NODE_APU_3, |
|||
.pwrdn_mask = APU_3_PWRCTL_CPUPWRDWNREQ_MASK, |
|||
.ipi = &apu_ipi, |
|||
}, |
|||
}; |
|||
|
|||
/**
|
|||
* 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 |
|||
* |
|||
* Return: pointer to a proc structure if proc is found, otherwise NULL |
|||
*/ |
|||
const struct pm_proc *pm_get_proc(unsigned int cpuid) |
|||
{ |
|||
if (cpuid < ARRAY_SIZE(pm_procs_all)) |
|||
return &pm_procs_all[cpuid]; |
|||
|
|||
return NULL; |
|||
} |
|||
|
|||
/**
|
|||
* pm_get_proc_by_node() - returns pointer to the proc structure |
|||
* @nid: node id of the processor |
|||
* |
|||
* Return: pointer to a proc structure if proc is found, otherwise NULL |
|||
*/ |
|||
const struct pm_proc *pm_get_proc_by_node(enum pm_node_id nid) |
|||
{ |
|||
for (size_t i = 0; i < ARRAY_SIZE(pm_procs_all); i++) { |
|||
if (nid == pm_procs_all[i].node_id) |
|||
return &pm_procs_all[i]; |
|||
} |
|||
return NULL; |
|||
} |
|||
|
|||
/**
|
|||
* pm_get_cpuid() - get the local cpu ID for a global node ID |
|||
* @nid: node id of the processor |
|||
* |
|||
* Return: the cpu ID (starting from 0) for the subsystem |
|||
*/ |
|||
static unsigned int pm_get_cpuid(enum pm_node_id nid) |
|||
{ |
|||
for (size_t i = 0; i < ARRAY_SIZE(pm_procs_all); i++) { |
|||
if (pm_procs_all[i].node_id == nid) |
|||
return i; |
|||
} |
|||
return UNDEFINED_CPUID; |
|||
} |
|||
|
|||
const struct pm_proc *primary_proc = &pm_procs_all[0]; |
|||
|
|||
/**
|
|||
* pm_client_suspend() - Client-specific suspend actions |
|||
* |
|||
* This function should contain any PU-specific actions |
|||
* required prior to sending suspend request to PMU |
|||
*/ |
|||
void pm_client_suspend(const struct pm_proc *proc) |
|||
{ |
|||
/* Set powerdown request */ |
|||
mmio_write_32(APU_PWRCTL, mmio_read_32(APU_PWRCTL) | proc->pwrdn_mask); |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* pm_client_abort_suspend() - Client-specific abort-suspend actions |
|||
* |
|||
* This function should contain any PU-specific actions |
|||
* required for aborting a prior suspend request |
|||
*/ |
|||
void pm_client_abort_suspend(void) |
|||
{ |
|||
/* Enable interrupts at processor level (for current cpu) */ |
|||
gicv2_cpuif_enable(); |
|||
/* Clear powerdown request */ |
|||
mmio_write_32(APU_PWRCTL, |
|||
mmio_read_32(APU_PWRCTL) & ~primary_proc->pwrdn_mask); |
|||
} |
|||
|
|||
/**
|
|||
* pm_client_wakeup() - Client-specific wakeup actions |
|||
* |
|||
* This function should contain any PU-specific actions |
|||
* required for waking up another APU core |
|||
*/ |
|||
void pm_client_wakeup(const struct pm_proc *proc) |
|||
{ |
|||
unsigned int cpuid = pm_get_cpuid(proc->node_id); |
|||
|
|||
if (cpuid == UNDEFINED_CPUID) |
|||
return; |
|||
|
|||
/* clear powerdown bit for affected cpu */ |
|||
uint32_t val = mmio_read_32(APU_PWRCTL); |
|||
val &= ~(proc->pwrdn_mask); |
|||
mmio_write_32(APU_PWRCTL, val); |
|||
} |
@ -0,0 +1,56 @@ |
|||
/*
|
|||
* Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
/*
|
|||
* Contains APU specific macros and macros to be defined depending on |
|||
* the execution environment. |
|||
*/ |
|||
|
|||
#ifndef _PM_CLIENT_H_ |
|||
#define _PM_CLIENT_H_ |
|||
|
|||
#include "pm_defs.h" |
|||
#include "pm_common.h" |
|||
|
|||
/* Functions to be implemented by each PU */ |
|||
enum pm_ret_status pm_ipi_send(const struct pm_proc *proc, |
|||
uint32_t payload[PAYLOAD_ARG_CNT]); |
|||
enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc, |
|||
uint32_t payload[PAYLOAD_ARG_CNT], |
|||
uint32_t *val); |
|||
void pm_client_suspend(const struct pm_proc *proc); |
|||
void pm_client_abort_suspend(void); |
|||
void pm_client_wakeup(const struct pm_proc *proc); |
|||
enum pm_ret_status set_ocm_retention(void); |
|||
|
|||
/* Global variables to be set in pm_client.c */ |
|||
extern const struct pm_proc *primary_proc; |
|||
|
|||
#endif /* _PM_CLIENT_H_ */ |
@ -0,0 +1,74 @@ |
|||
/*
|
|||
* Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
/*
|
|||
* Contains definitions of commonly used macros and data types needed |
|||
* for PU Power Management. This file should be common for all PU's. |
|||
*/ |
|||
|
|||
#ifndef _PM_COMMON_H_ |
|||
#define _PM_COMMON_H_ |
|||
|
|||
#include <debug.h> |
|||
#include <stdint.h> |
|||
#include "pm_defs.h" |
|||
|
|||
#define PAYLOAD_ARG_CNT 6U |
|||
#define PAYLOAD_ARG_SIZE 4U /* size in bytes */ |
|||
|
|||
/**
|
|||
* pm_ipi - struct for capturing IPI-channel specific info |
|||
* @mask mask for enabling/disabling and triggering the IPI |
|||
* @base base address for IPI |
|||
* @buffer_base base address for payload buffer |
|||
*/ |
|||
struct pm_ipi { |
|||
const unsigned int mask; |
|||
const uintptr_t base; |
|||
const uintptr_t buffer_base; |
|||
}; |
|||
|
|||
/**
|
|||
* pm_proc - struct for capturing processor related info |
|||
* @node_id node-ID of the processor |
|||
* @pwrdn_mask cpu-specific mask to be used for power control register |
|||
* @ipi pointer to IPI channel structure |
|||
* (in APU all processors share one IPI channel) |
|||
*/ |
|||
struct pm_proc { |
|||
const enum pm_node_id node_id; |
|||
const unsigned int pwrdn_mask; |
|||
const struct pm_ipi *ipi; |
|||
}; |
|||
|
|||
const struct pm_proc *pm_get_proc(unsigned int cpuid); |
|||
const struct pm_proc *pm_get_proc_by_node(enum pm_node_id nid); |
|||
|
|||
#endif /* _PM_COMMON_H_ */ |
@ -0,0 +1,213 @@ |
|||
/*
|
|||
* Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
/* ZynqMP power management enums and defines */ |
|||
|
|||
#ifndef _PM_DEFS_H_ |
|||
#define _PM_DEFS_H_ |
|||
|
|||
/*********************************************************************
|
|||
* Macro definitions |
|||
********************************************************************/ |
|||
|
|||
/*
|
|||
* Version number is a 32bit value, like: |
|||
* (PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR |
|||
*/ |
|||
#define PM_VERSION_MAJOR 0 |
|||
#define PM_VERSION_MINOR 2 |
|||
|
|||
#define PM_VERSION ((PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR) |
|||
|
|||
/* Capabilities for RAM */ |
|||
#define PM_CAP_ACCESS 0x1U |
|||
#define PM_CAP_CONTEXT 0x2U |
|||
|
|||
#define MAX_LATENCY (~0U) |
|||
#define MAX_QOS 100U |
|||
|
|||
/*********************************************************************
|
|||
* Enum definitions |
|||
********************************************************************/ |
|||
|
|||
enum pm_api_id { |
|||
/* Miscellaneous API functions: */ |
|||
PM_GET_API_VERSION = 1, /* Do not change or move */ |
|||
PM_SET_CONFIGURATION, |
|||
PM_GET_NODE_STATUS, |
|||
PM_GET_OP_CHARACTERISTIC, |
|||
PM_REGISTER_NOTIFIER, |
|||
/* API for suspending of PUs: */ |
|||
PM_REQ_SUSPEND, |
|||
PM_SELF_SUSPEND, |
|||
PM_FORCE_POWERDOWN, |
|||
PM_ABORT_SUSPEND, |
|||
PM_REQ_WAKEUP, |
|||
PM_SET_WAKEUP_SOURCE, |
|||
PM_SYSTEM_SHUTDOWN, |
|||
/* API for managing PM slaves: */ |
|||
PM_REQ_NODE, |
|||
PM_RELEASE_NODE, |
|||
PM_SET_REQUIREMENT, |
|||
PM_SET_MAX_LATENCY, |
|||
/* Direct control API functions: */ |
|||
PM_RESET_ASSERT, |
|||
PM_RESET_GET_STATUS, |
|||
PM_MMIO_WRITE, |
|||
PM_MMIO_READ, |
|||
PM_API_MAX |
|||
}; |
|||
|
|||
enum pm_node_id { |
|||
NODE_UNKNOWN = 0, |
|||
NODE_APU, |
|||
NODE_APU_0, |
|||
NODE_APU_1, |
|||
NODE_APU_2, |
|||
NODE_APU_3, |
|||
NODE_RPU, |
|||
NODE_RPU_0, |
|||
NODE_RPU_1, |
|||
NODE_PL, |
|||
NODE_FPD, |
|||
NODE_OCM_BANK_0, |
|||
NODE_OCM_BANK_1, |
|||
NODE_OCM_BANK_2, |
|||
NODE_OCM_BANK_3, |
|||
NODE_TCM_0_A, |
|||
NODE_TCM_0_B, |
|||
NODE_TCM_1_A, |
|||
NODE_TCM_1_B, |
|||
NODE_L2, |
|||
NODE_GPU_PP_0, |
|||
NODE_GPU_PP_1, |
|||
NODE_USB_0, |
|||
NODE_USB_1, |
|||
NODE_TTC_0, |
|||
NODE_TTC_1, |
|||
NODE_TTC_2, |
|||
NODE_TTC_3, |
|||
NODE_SATA, |
|||
NODE_ETH_0, |
|||
NODE_ETH_1, |
|||
NODE_ETH_2, |
|||
NODE_ETH_3, |
|||
NODE_UART_0, |
|||
NODE_UART_1, |
|||
NODE_SPI_0, |
|||
NODE_SPI_1, |
|||
NODE_I2C_0, |
|||
NODE_I2C_1, |
|||
NODE_SD_0, |
|||
NODE_SD_1, |
|||
NODE_DP, |
|||
NODE_GDMA, |
|||
NODE_ADMA, |
|||
NODE_NAND, |
|||
NODE_QSPI, |
|||
NODE_GPIO, |
|||
NODE_CAN_0, |
|||
NODE_CAN_1, |
|||
NODE_AFI, |
|||
NODE_APLL, |
|||
NODE_VPLL, |
|||
NODE_DPLL, |
|||
NODE_RPLL, |
|||
NODE_IOPLL, |
|||
NODE_DDR, |
|||
}; |
|||
|
|||
enum pm_request_ack { |
|||
REQ_ACK_NO = 1, |
|||
REQ_ACK_BLOCKING, |
|||
REQ_ACK_NON_BLOCKING, |
|||
}; |
|||
|
|||
enum pm_abort_reason { |
|||
ABORT_REASON_WKUP_EVENT = 100, |
|||
ABORT_REASON_PU_BUSY, |
|||
ABORT_REASON_NO_PWRDN, |
|||
ABORT_REASON_UNKNOWN, |
|||
}; |
|||
|
|||
enum pm_suspend_reason { |
|||
SUSPEND_REASON_PU_REQ = 201, |
|||
SUSPEND_REASON_ALERT, |
|||
SUSPEND_REASON_SYS_SHUTDOWN, |
|||
}; |
|||
|
|||
enum pm_ram_state { |
|||
PM_RAM_STATE_OFF = 1, |
|||
PM_RAM_STATE_RETENTION, |
|||
PM_RAM_STATE_ON, |
|||
}; |
|||
|
|||
enum pm_opchar_type { |
|||
PM_OPCHAR_TYPE_POWER = 1, |
|||
PM_OPCHAR_TYPE_ENERGY, |
|||
PM_OPCHAR_TYPE_TEMP, |
|||
}; |
|||
|
|||
/**
|
|||
* @PM_RET_SUCCESS: success |
|||
* @PM_RET_ERROR_ARGS: illegal arguments provided |
|||
* @PM_RET_ERROR_ACCESS: access rights violation |
|||
* @PM_RET_ERROR_TIMEOUT: timeout in communication with PMU |
|||
* @PM_RET_ERROR_NOTSUPPORTED: feature not supported |
|||
* @PM_RET_ERROR_PROC: node is not a processor node |
|||
* @PM_RET_ERROR_API_ID: illegal API ID |
|||
* @PM_RET_ERROR_OTHER: other error |
|||
*/ |
|||
enum pm_ret_status { |
|||
PM_RET_SUCCESS, |
|||
PM_RET_ERROR_ARGS, |
|||
PM_RET_ERROR_ACCESS, |
|||
PM_RET_ERROR_TIMEOUT, |
|||
PM_RET_ERROR_NOTSUPPORTED, |
|||
PM_RET_ERROR_PROC, |
|||
PM_RET_ERROR_API_ID, |
|||
PM_RET_ERROR_FAILURE, |
|||
PM_RET_ERROR_COMMUNIC, |
|||
PM_RET_ERROR_DOUBLEREQ, |
|||
PM_RET_ERROR_OTHER, |
|||
}; |
|||
|
|||
/**
|
|||
* @PM_INITIAL_BOOT: boot is a fresh system startup |
|||
* @PM_RESUME: boot is a resume |
|||
* @PM_BOOT_ERROR: error, boot cause cannot be identified |
|||
*/ |
|||
enum pm_boot_status { |
|||
PM_INITIAL_BOOT, |
|||
PM_RESUME, |
|||
PM_BOOT_ERROR, |
|||
}; |
|||
|
|||
#endif /* _PM_DEFS_H_ */ |
@ -0,0 +1,247 @@ |
|||
/*
|
|||
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#include <bakery_lock.h> |
|||
#include <mmio.h> |
|||
#include <platform.h> |
|||
#include <arch_helpers.h> |
|||
#include "pm_ipi.h" |
|||
#include "../zynqmp_private.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_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_ISR_PMU_0_MASK 0X00010000 |
|||
#define IPI_APU_IER_PMU_0_MASK 0X00010000 |
|||
|
|||
#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_ISR_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 |
|||
|
|||
static bakery_lock_t pm_secure_lock; |
|||
|
|||
const struct pm_ipi apu_ipi = { |
|||
.mask = IPI_APU_MASK, |
|||
.base = IPI_BASEADDR, |
|||
.buffer_base = IPI_BUFFER_APU_BASE, |
|||
}; |
|||
|
|||
/**
|
|||
* pm_ipi_init() - Initialize IPI peripheral for communication with PMU |
|||
* |
|||
* @return On success, the initialization function must return 0. |
|||
* Any other return value will cause the framework to ignore |
|||
* the service |
|||
* |
|||
* Enable interrupts at registered entrance in IPI peripheral |
|||
* Called from pm_setup initialization function |
|||
*/ |
|||
int pm_ipi_init(void) |
|||
{ |
|||
bakery_lock_init(&pm_secure_lock); |
|||
|
|||
/* IPI Interrupts Clear & Disable */ |
|||
mmio_write_32(IPI_APU_ISR, 0xffffffff); |
|||
mmio_write_32(IPI_APU_IDR, 0xffffffff); |
|||
|
|||
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 |
|||
* |
|||
* Send an IPI request to the power controller. Caller needs to hold |
|||
* the 'pm_secure_lock' lock. |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
static enum pm_ret_status pm_ipi_send_common(const struct pm_proc *proc, |
|||
uint32_t payload[PAYLOAD_ARG_CNT]) |
|||
{ |
|||
unsigned int offset = 0; |
|||
uintptr_t buffer_base = proc->ipi->buffer_base + |
|||
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); |
|||
|
|||
return PM_RET_SUCCESS; |
|||
} |
|||
|
|||
/**
|
|||
* pm_ipi_send() - 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 |
|||
* |
|||
* Send an IPI request to the power controller. |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
enum pm_ret_status pm_ipi_send(const struct pm_proc *proc, |
|||
uint32_t payload[PAYLOAD_ARG_CNT]) |
|||
{ |
|||
enum pm_ret_status ret; |
|||
|
|||
bakery_lock_get(&pm_secure_lock); |
|||
|
|||
ret = pm_ipi_send_common(proc, payload); |
|||
|
|||
bakery_lock_release(&pm_secure_lock); |
|||
|
|||
return ret; |
|||
} |
|||
|
|||
|
|||
/**
|
|||
* pm_ipi_buff_read() - Reads IPI response after PMU has handled interrupt |
|||
* @proc Pointer to the processor who is waiting and reading response |
|||
* @value Used to return value from 2nd IPI buffer element (optional) |
|||
* |
|||
* @return Returns status, either success or error+reason |
|||
*/ |
|||
static enum pm_ret_status pm_ipi_buff_read(const struct pm_proc *proc, |
|||
unsigned int *value) |
|||
{ |
|||
uintptr_t buffer_base = proc->ipi->buffer_base + |
|||
IPI_BUFFER_TARGET_PMU_OFFSET + |
|||
IPI_BUFFER_RESP_OFFSET; |
|||
|
|||
pm_ipi_wait(proc); |
|||
|
|||
/*
|
|||
* Read response from IPI buffer |
|||
* buf-0: success or error+reason |
|||
* buf-1: value |
|||
* buf-2: unused |
|||
* buf-3: unused |
|||
*/ |
|||
if (value != NULL) |
|||
*value = mmio_read_32(buffer_base + PAYLOAD_ARG_SIZE); |
|||
|
|||
return mmio_read_32(buffer_base); |
|||
} |
|||
|
|||
/**
|
|||
* pm_ipi_send_sync() - 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 |
|||
* @value Used to return value from 2nd IPI buffer element (optional) |
|||
* |
|||
* Send an IPI request to the power controller and wait for it to be handled. |
|||
* |
|||
* @return Returns status, either success or error+reason and, optionally, |
|||
* @value |
|||
*/ |
|||
enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc, |
|||
uint32_t payload[PAYLOAD_ARG_CNT], |
|||
unsigned int *value) |
|||
{ |
|||
enum pm_ret_status ret; |
|||
|
|||
bakery_lock_get(&pm_secure_lock); |
|||
|
|||
ret = pm_ipi_send_common(proc, payload); |
|||
if (ret != PM_RET_SUCCESS) |
|||
goto unlock; |
|||
|
|||
ret = pm_ipi_buff_read(proc, value); |
|||
|
|||
unlock: |
|||
bakery_lock_release(&pm_secure_lock); |
|||
|
|||
return ret; |
|||
} |
@ -0,0 +1,44 @@ |
|||
/*
|
|||
* Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#ifndef _PM_IPI_H_ |
|||
#define _PM_IPI_H_ |
|||
|
|||
#include "pm_common.h" |
|||
|
|||
int pm_ipi_init(void); |
|||
|
|||
enum pm_ret_status pm_ipi_send(const struct pm_proc *proc, |
|||
uint32_t payload[PAYLOAD_ARG_CNT]); |
|||
enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc, |
|||
uint32_t payload[PAYLOAD_ARG_CNT], |
|||
unsigned int *value); |
|||
|
|||
#endif /* _PM_IPI_H_ */ |
@ -0,0 +1,231 @@ |
|||
/*
|
|||
* Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
/*
|
|||
* Top-level SMC handler for ZynqMP power management calls and |
|||
* IPI setup functions for communication with PMU. |
|||
*/ |
|||
|
|||
#include <errno.h> |
|||
#include <gic_common.h> |
|||
#include <runtime_svc.h> |
|||
#include <string.h> |
|||
#include "pm_api_sys.h" |
|||
#include "pm_client.h" |
|||
#include "pm_ipi.h" |
|||
#include "../zynqmp_private.h" |
|||
|
|||
/* 0 - UP, !0 - DOWN */ |
|||
static int32_t pm_down = !0; |
|||
|
|||
/**
|
|||
* pm_context - Structure which contains data for power management |
|||
* @api_version version of PM API, must match with one on PMU side |
|||
* @payload payload array used to store received |
|||
* data from ipi buffer registers |
|||
*/ |
|||
static struct { |
|||
uint32_t api_version; |
|||
uint32_t payload[PAYLOAD_ARG_CNT]; |
|||
} pm_ctx; |
|||
|
|||
/**
|
|||
* pm_setup() - PM service setup |
|||
* |
|||
* @return On success, the initialization function must return 0. |
|||
* Any other return value will cause the framework to ignore |
|||
* the service |
|||
* |
|||
* Initialization functions for ZynqMP power management for |
|||
* communicaton with PMU. |
|||
* |
|||
* Called from sip_svc_setup initialization function with the |
|||
* rt_svc_init signature. |
|||
* |
|||
*/ |
|||
int pm_setup(void) |
|||
{ |
|||
int status; |
|||
|
|||
if (!zynqmp_is_pmu_up()) |
|||
return -ENODEV; |
|||
|
|||
status = pm_ipi_init(); |
|||
|
|||
if (status == 0) |
|||
INFO("BL31: PM Service Init Complete: API v%d.%d\n", |
|||
PM_VERSION_MAJOR, PM_VERSION_MINOR); |
|||
else |
|||
INFO("BL31: PM Service Init Failed, Error Code %d!\n", status); |
|||
|
|||
pm_down = status; |
|||
|
|||
return status; |
|||
} |
|||
|
|||
/**
|
|||
* pm_smc_handler() - SMC handler for PM-API calls coming from EL1/EL2. |
|||
* @smc_fid - Function Identifier |
|||
* @x1 - x4 - Arguments |
|||
* @cookie - Unused |
|||
* @handler - Pointer to caller's context structure |
|||
* |
|||
* @return - Unused |
|||
* |
|||
* Determines that smc_fid is valid and supported PM SMC Function ID from the |
|||
* list of pm_api_ids, otherwise completes the request with |
|||
* the unknown SMC Function ID |
|||
* |
|||
* The SMC calls for PM service are forwarded from SIP Service SMC handler |
|||
* function with rt_svc_handle signature |
|||
*/ |
|||
uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, |
|||
uint64_t x4, void *cookie, void *handle, uint64_t flags) |
|||
{ |
|||
enum pm_ret_status ret; |
|||
|
|||
uint32_t pm_arg[4]; |
|||
|
|||
/* Handle case where PM wasn't initialized properly */ |
|||
if (pm_down) |
|||
SMC_RET1(handle, SMC_UNK); |
|||
|
|||
pm_arg[0] = (uint32_t)x1; |
|||
pm_arg[1] = (uint32_t)(x1 >> 32); |
|||
pm_arg[2] = (uint32_t)x2; |
|||
pm_arg[3] = (uint32_t)(x2 >> 32); |
|||
|
|||
switch (smc_fid & FUNCID_NUM_MASK) { |
|||
/* PM API Functions */ |
|||
case PM_SELF_SUSPEND: |
|||
ret = pm_self_suspend(pm_arg[0], pm_arg[1], pm_arg[2], |
|||
pm_arg[3]); |
|||
SMC_RET1(handle, (uint64_t)ret); |
|||
|
|||
case PM_REQ_SUSPEND: |
|||
ret = pm_req_suspend(pm_arg[0], pm_arg[1], pm_arg[2], |
|||
pm_arg[3]); |
|||
SMC_RET1(handle, (uint64_t)ret); |
|||
|
|||
case PM_REQ_WAKEUP: |
|||
ret = pm_req_wakeup(pm_arg[0], pm_arg[1], pm_arg[2], |
|||
pm_arg[3]); |
|||
SMC_RET1(handle, (uint64_t)ret); |
|||
|
|||
case PM_FORCE_POWERDOWN: |
|||
ret = pm_force_powerdown(pm_arg[0], pm_arg[1]); |
|||
SMC_RET1(handle, (uint64_t)ret); |
|||
|
|||
case PM_ABORT_SUSPEND: |
|||
ret = pm_abort_suspend(pm_arg[0]); |
|||
SMC_RET1(handle, (uint64_t)ret); |
|||
|
|||
case PM_SET_WAKEUP_SOURCE: |
|||
ret = pm_set_wakeup_source(pm_arg[0], pm_arg[1], pm_arg[2]); |
|||
SMC_RET1(handle, (uint64_t)ret); |
|||
|
|||
case PM_SYSTEM_SHUTDOWN: |
|||
ret = pm_system_shutdown(pm_arg[0]); |
|||
SMC_RET1(handle, (uint64_t)ret); |
|||
|
|||
case PM_REQ_NODE: |
|||
ret = pm_req_node(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]); |
|||
SMC_RET1(handle, (uint64_t)ret); |
|||
|
|||
case PM_RELEASE_NODE: |
|||
ret = pm_release_node(pm_arg[0]); |
|||
SMC_RET1(handle, (uint64_t)ret); |
|||
|
|||
case PM_SET_REQUIREMENT: |
|||
ret = pm_set_requirement(pm_arg[0], pm_arg[1], pm_arg[2], |
|||
pm_arg[3]); |
|||
SMC_RET1(handle, (uint64_t)ret); |
|||
|
|||
case PM_SET_MAX_LATENCY: |
|||
ret = pm_set_max_latency(pm_arg[0], pm_arg[1]); |
|||
SMC_RET1(handle, (uint64_t)ret); |
|||
|
|||
case PM_GET_API_VERSION: |
|||
/* Check is PM API version already verified */ |
|||
if (pm_ctx.api_version == PM_VERSION) |
|||
SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS | |
|||
((uint64_t)PM_VERSION << 32)); |
|||
|
|||
ret = pm_get_api_version(&pm_ctx.api_version); |
|||
SMC_RET1(handle, (uint64_t)ret | |
|||
((uint64_t)pm_ctx.api_version << 32)); |
|||
|
|||
case PM_SET_CONFIGURATION: |
|||
ret = pm_set_configuration(pm_arg[0]); |
|||
SMC_RET1(handle, (uint64_t)ret); |
|||
|
|||
case PM_GET_NODE_STATUS: |
|||
ret = pm_get_node_status(pm_arg[0]); |
|||
SMC_RET1(handle, (uint64_t)ret); |
|||
|
|||
case PM_GET_OP_CHARACTERISTIC: |
|||
ret = pm_get_op_characteristic(pm_arg[0], pm_arg[1]); |
|||
SMC_RET1(handle, (uint64_t)ret); |
|||
|
|||
case PM_REGISTER_NOTIFIER: |
|||
ret = pm_register_notifier(pm_arg[0], pm_arg[1], pm_arg[2], |
|||
pm_arg[3]); |
|||
SMC_RET1(handle, (uint64_t)ret); |
|||
|
|||
case PM_RESET_ASSERT: |
|||
ret = pm_reset_assert(pm_arg[0], pm_arg[1]); |
|||
SMC_RET1(handle, (uint64_t)ret); |
|||
|
|||
case PM_RESET_GET_STATUS: |
|||
{ |
|||
uint32_t reset_status; |
|||
|
|||
ret = pm_reset_get_status(pm_arg[0], &reset_status); |
|||
SMC_RET1(handle, (uint64_t)ret | |
|||
((uint64_t)reset_status << 32)); |
|||
} |
|||
|
|||
/* PM memory access functions */ |
|||
case PM_MMIO_WRITE: |
|||
ret = pm_mmio_write(pm_arg[0], pm_arg[1], pm_arg[2]); |
|||
SMC_RET1(handle, (uint64_t)ret); |
|||
|
|||
case PM_MMIO_READ: |
|||
{ |
|||
uint32_t value; |
|||
|
|||
ret = pm_mmio_read(pm_arg[0], &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); |
|||
} |
|||
} |
@ -0,0 +1,41 @@ |
|||
/*
|
|||
* Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#ifndef _PM_SVC_MAIN_H_ |
|||
#define _PM_SVC_MAIN_H_ |
|||
|
|||
#include "pm_common.h" |
|||
|
|||
int pm_setup(void); |
|||
uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, |
|||
uint64_t x4, void *cookie, void *handle, |
|||
uint64_t flags); |
|||
|
|||
#endif /* _PM_SVC_MAIN_H_ */ |
@ -0,0 +1,114 @@ |
|||
/*
|
|||
* Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
/* Top level SMC handler for SiP calls. Dispatch PM calls to PM SMC handler. */ |
|||
|
|||
#include <runtime_svc.h> |
|||
#include <uuid.h> |
|||
#include "pm_svc_main.h" |
|||
|
|||
/* SMC function IDs for SiP Service queries */ |
|||
#define ZYNQMP_SIP_SVC_CALL_COUNT 0x8200ff00 |
|||
#define ZYNQMP_SIP_SVC_UID 0x8200ff01 |
|||
#define ZYNQMP_SIP_SVC_VERSION 0x8200ff03 |
|||
|
|||
/* SiP Service Calls version numbers */ |
|||
#define SIP_SVC_VERSION_MAJOR 0 |
|||
#define SIP_SVC_VERSION_MINOR 1 |
|||
|
|||
/* These macros are used to identify PM calls from the SMC function ID */ |
|||
#define PM_FID_MASK 0xf000u |
|||
#define PM_FID_VALUE 0u |
|||
#define is_pm_fid(_fid) (((_fid) & PM_FID_MASK) == PM_FID_VALUE) |
|||
|
|||
/* SiP Service UUID */ |
|||
DEFINE_SVC_UUID(zynqmp_sip_uuid, |
|||
0x2a1d9b5c, 0x8605, 0x4023, 0xa6, 0x1b, |
|||
0xb9, 0x25, 0x82, 0x2d, 0xe3, 0xa5); |
|||
|
|||
/**
|
|||
* sip_svc_setup() - Setup SiP Service |
|||
* |
|||
* Invokes PM setup |
|||
*/ |
|||
static int32_t sip_svc_setup(void) |
|||
{ |
|||
/* PM implementation as SiP Service */ |
|||
pm_setup(); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
/**
|
|||
* sip_svc_smc_handler() - Top-level SiP Service SMC handler |
|||
* |
|||
* Handler for all SiP SMC calls. Handles standard SIP requests |
|||
* and calls PM SMC handler if the call is for a PM-API function. |
|||
*/ |
|||
uint64_t sip_svc_smc_handler(uint32_t smc_fid, |
|||
uint64_t x1, |
|||
uint64_t x2, |
|||
uint64_t x3, |
|||
uint64_t x4, |
|||
void *cookie, |
|||
void *handle, |
|||
uint64_t flags) |
|||
{ |
|||
/* Let PM SMC handler deal with PM-related requests */ |
|||
if (is_pm_fid(smc_fid)) { |
|||
return pm_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, |
|||
flags); |
|||
} |
|||
|
|||
switch (smc_fid) { |
|||
case ZYNQMP_SIP_SVC_CALL_COUNT: |
|||
/* PM functions + default functions */ |
|||
SMC_RET1(handle, PM_API_MAX + 2); |
|||
|
|||
case ZYNQMP_SIP_SVC_UID: |
|||
SMC_UUID_RET(handle, zynqmp_sip_uuid); |
|||
|
|||
case ZYNQMP_SIP_SVC_VERSION: |
|||
SMC_RET2(handle, SIP_SVC_VERSION_MAJOR, SIP_SVC_VERSION_MINOR); |
|||
|
|||
default: |
|||
WARN("Unimplemented SiP Service Call: 0x%x\n", smc_fid); |
|||
SMC_RET1(handle, SMC_UNK); |
|||
} |
|||
} |
|||
|
|||
/* Register PM Service Calls as runtime service */ |
|||
DECLARE_RT_SVC( |
|||
sip_svc, |
|||
OEN_SIP_START, |
|||
OEN_SIP_END, |
|||
SMC_TYPE_FAST, |
|||
sip_svc_setup, |
|||
sip_svc_smc_handler); |
@ -0,0 +1,31 @@ |
|||
# Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
|
|||
#
|
|||
# Redistribution and use in source and binary forms, with or without
|
|||
# modification, are permitted provided that the following conditions are met:
|
|||
#
|
|||
# Redistributions of source code must retain the above copyright notice, this
|
|||
# list of conditions and the following disclaimer.
|
|||
#
|
|||
# Redistributions in binary form must reproduce the above copyright notice,
|
|||
# this list of conditions and the following disclaimer in the documentation
|
|||
# and/or other materials provided with the distribution.
|
|||
#
|
|||
# Neither the name of ARM nor the names of its contributors may be used
|
|||
# to endorse or promote products derived from this software without specific
|
|||
# prior written permission.
|
|||
#
|
|||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|||
# POSSIBILITY OF SUCH DAMAGE.
|
|||
|
|||
# TSP source files specific to ZynqMP platform
|
|||
BL32_SOURCES += plat/common/aarch64/platform_mp_stack.S \
|
|||
plat/xilinx/zynqmp/tsp/tsp_plat_setup.c |
@ -0,0 +1,104 @@ |
|||
/*
|
|||
* Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#include <bl_common.h> |
|||
#include <console.h> |
|||
#include <debug.h> |
|||
#include <platform_tsp.h> |
|||
#include <xlat_tables.h> |
|||
#include <plat_arm.h> |
|||
#include "../zynqmp_def.h" |
|||
#include "../zynqmp_private.h" |
|||
|
|||
/*
|
|||
* The next 3 constants identify the extents of the code & RO data region and |
|||
* the limit of the BL32 image. These addresses are used by the MMU setup code |
|||
* and therefore they must be page-aligned. It is the responsibility of the |
|||
* linker script to ensure that __RO_START__, __RO_END__ & & __BL32_END__ |
|||
* linker symbols refer to page-aligned addresses. |
|||
*/ |
|||
#define BL32_RO_BASE (unsigned long)(&__RO_START__) |
|||
#define BL32_RO_LIMIT (unsigned long)(&__RO_END__) |
|||
#define BL32_END (unsigned long)(&__BL32_END__) |
|||
|
|||
|
|||
#if USE_COHERENT_MEM |
|||
/*
|
|||
* The next 2 constants identify the extents of the coherent memory region. |
|||
* These addresses are used by the MMU setup code and therefore they must be |
|||
* page-aligned. It is the responsibility of the linker script to ensure that |
|||
* __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to |
|||
* page-aligned addresses. |
|||
*/ |
|||
#define BL32_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) |
|||
#define BL32_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) |
|||
#endif |
|||
|
|||
/*******************************************************************************
|
|||
* Initialize the UART |
|||
******************************************************************************/ |
|||
void tsp_early_platform_setup(void) |
|||
{ |
|||
/*
|
|||
* Initialize a different console than already in use to display |
|||
* messages from TSP |
|||
*/ |
|||
console_init(ZYNQMP_UART0_BASE, zynqmp_get_uart_clk(), |
|||
ZYNQMP_UART_BAUDRATE); |
|||
|
|||
/* Initialize the platform config for future decision making */ |
|||
zynqmp_config_setup(); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Perform platform specific setup placeholder |
|||
******************************************************************************/ |
|||
void tsp_platform_setup(void) |
|||
{ |
|||
plat_arm_gic_driver_init(); |
|||
plat_arm_gic_init(); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Perform the very early platform specific architectural setup here. At the |
|||
* moment this is only intializes the MMU |
|||
******************************************************************************/ |
|||
void tsp_plat_arch_setup(void) |
|||
{ |
|||
arm_configure_mmu_el1(BL32_RO_BASE, |
|||
(BL32_END - BL32_RO_BASE), |
|||
BL32_RO_BASE, |
|||
BL32_RO_LIMIT |
|||
#if USE_COHERENT_MEM |
|||
, BL32_COHERENT_RAM_BASE, |
|||
BL32_COHERENT_RAM_LIMIT |
|||
#endif |
|||
); |
|||
} |
@ -0,0 +1,207 @@ |
|||
/*
|
|||
* Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#ifndef __ZYNQMP_DEF_H__ |
|||
#define __ZYNQMP_DEF_H__ |
|||
|
|||
#include <common_def.h> |
|||
|
|||
/* Firmware Image Package */ |
|||
#define ZYNQMP_PRIMARY_CPU 0 |
|||
|
|||
/* Memory location options for Shared data and TSP in ZYNQMP */ |
|||
#define ZYNQMP_IN_TRUSTED_SRAM 0 |
|||
#define ZYNQMP_IN_TRUSTED_DRAM 1 |
|||
|
|||
/*******************************************************************************
|
|||
* ZYNQMP memory map related constants |
|||
******************************************************************************/ |
|||
|
|||
#define ZYNQMP_TRUSTED_SRAM_BASE 0xFFFC0000 |
|||
#define ZYNQMP_TRUSTED_SRAM_SIZE 0x00040000 |
|||
#define ZYNQMP_TRUSTED_SRAM_LIMIT (ZYNQMP_TRUSTED_SRAM_BASE + \ |
|||
ZYNQMP_TRUSTED_SRAM_SIZE) |
|||
|
|||
|
|||
/* Location of trusted dram on the base zynqmp */ |
|||
#define ZYNQMP_TRUSTED_DRAM_BASE 0x30000000 /* Can't overlap TZROM area */ |
|||
#define ZYNQMP_TRUSTED_DRAM_SIZE 0x10000000 |
|||
#define ZYNQMP_TRUSTED_DRAM_LIMIT (ZYNQMP_TRUSTED_DRAM_BASE + \ |
|||
ZYNQMP_TRUSTED_DRAM_SIZE) |
|||
|
|||
/* Aggregate of all devices in the first GB */ |
|||
#define DEVICE0_BASE 0xFF000000 |
|||
#define DEVICE0_SIZE 0x00E00000 |
|||
#define DEVICE1_BASE 0xF9000000 |
|||
#define DEVICE1_SIZE 0x01000000 |
|||
|
|||
/* For cpu reset APU space here too 0xFE5F1000 CRF_APB*/ |
|||
#define CRF_APB_BASE 0xFD1A0000 |
|||
#define CRF_APB_SIZE 0x00600000 |
|||
|
|||
/* CRF registers and bitfields */ |
|||
#define CRF_APB_RST_FPD_APU (CRF_APB_BASE + 0X00000104) |
|||
|
|||
#define CRF_APB_RST_FPD_APU_ACPU_RESET (1 << 0) |
|||
#define CRF_APB_RST_FPD_APU_ACPU_PWRON_RESET (1 << 10) |
|||
|
|||
/* CRL registers and bitfields */ |
|||
#define CRL_APB_BASE 0xFF5E0000 |
|||
#define CRL_APB_RPLL_CTRL (CRL_APB_BASE + 0x30) |
|||
#define CRL_APB_TIMESTAMP_REF_CTRL (CRL_APB_BASE + 0x128) |
|||
#define CRL_APB_RESET_CTRL (CRL_APB_BASE + 0x218) |
|||
|
|||
#define CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT (1 << 24) |
|||
|
|||
#define CRL_APB_RPLL_CTRL_BYPASS (1 << 3) |
|||
|
|||
#define CRL_APB_RESET_CTRL_SOFT_RESET (1 << 4) |
|||
|
|||
/* system counter registers and bitfields */ |
|||
#define IOU_SCNTRS_BASE 0xFF260000 |
|||
#define IOU_SCNTRS_CONTROL (IOU_SCNTRS_BASE + 0) |
|||
#define IOU_SCNTRS_BASEFREQ (IOU_SCNTRS_BASE + 0x20) |
|||
|
|||
#define IOU_SCNTRS_CONTROL_EN (1 << 0) |
|||
|
|||
/* APU registers and bitfields */ |
|||
#define APU_BASE 0xFD5C0000 |
|||
#define APU_CONFIG_0 (APU_BASE + 0x20) |
|||
#define APU_RVBAR_L_0 (APU_BASE + 0x40) |
|||
#define APU_RVBAR_H_0 (APU_BASE + 0x44) |
|||
#define APU_PWRCTL (APU_BASE + 0x90) |
|||
|
|||
#define APU_CONFIG_0_VINITHI_SHIFT 8 |
|||
#define APU_0_PWRCTL_CPUPWRDWNREQ_MASK 1 |
|||
#define APU_1_PWRCTL_CPUPWRDWNREQ_MASK 2 |
|||
#define APU_2_PWRCTL_CPUPWRDWNREQ_MASK 4 |
|||
#define APU_3_PWRCTL_CPUPWRDWNREQ_MASK 8 |
|||
|
|||
/* PMU registers and bitfields */ |
|||
#define PMU_GLOBAL_BASE 0xFFD80000 |
|||
#define PMU_GLOBAL_CNTRL (PMU_GLOBAL_BASE + 0) |
|||
#define PMU_GLOBAL_REQ_PWRUP_STATUS (PMU_GLOBAL_BASE + 0x110) |
|||
#define PMU_GLOBAL_REQ_PWRUP_EN (PMU_GLOBAL_BASE + 0x118) |
|||
#define PMU_GLOBAL_REQ_PWRUP_DIS (PMU_GLOBAL_BASE + 0x11c) |
|||
#define PMU_GLOBAL_REQ_PWRUP_TRIG (PMU_GLOBAL_BASE + 0x120) |
|||
|
|||
#define PMU_GLOBAL_CNTRL_FW_IS_PRESENT (1 << 4) |
|||
|
|||
#define DRAM1_BASE 0x00000000ull |
|||
#define DRAM1_SIZE 0x10000000ull |
|||
#define DRAM1_END (DRAM1_BASE + DRAM1_SIZE - 1) |
|||
|
|||
#define DRAM_BASE DRAM1_BASE |
|||
#define DRAM_SIZE DRAM1_SIZE |
|||
|
|||
/* Load address of BL33 in the ZYNQMP port */ |
|||
#define PLAT_ARM_NS_IMAGE_OFFSET (DRAM1_BASE + 0x8000000) /* DRAM + 128MB */ |
|||
|
|||
/*******************************************************************************
|
|||
* CCI-400 related constants |
|||
******************************************************************************/ |
|||
#define PLAT_ARM_CCI_BASE 0xFD6E0000 |
|||
#define PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX 3 |
|||
#define PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX 4 |
|||
|
|||
/*******************************************************************************
|
|||
* GIC-400 & interrupt handling related constants |
|||
******************************************************************************/ |
|||
#define BASE_GICD_BASE 0xF9010000 |
|||
#define BASE_GICC_BASE 0xF9020000 |
|||
#define BASE_GICH_BASE 0xF9040000 |
|||
#define BASE_GICV_BASE 0xF9060000 |
|||
|
|||
#define IRQ_SEC_IPI_APU 67 |
|||
#define ARM_IRQ_SEC_PHY_TIMER 29 |
|||
|
|||
#define ARM_IRQ_SEC_SGI_0 8 |
|||
#define ARM_IRQ_SEC_SGI_1 9 |
|||
#define ARM_IRQ_SEC_SGI_2 10 |
|||
#define ARM_IRQ_SEC_SGI_3 11 |
|||
#define ARM_IRQ_SEC_SGI_4 12 |
|||
#define ARM_IRQ_SEC_SGI_5 13 |
|||
#define ARM_IRQ_SEC_SGI_6 14 |
|||
#define ARM_IRQ_SEC_SGI_7 15 |
|||
|
|||
#define MAX_INTR_EL3 128 |
|||
|
|||
/*******************************************************************************
|
|||
* UART related constants |
|||
******************************************************************************/ |
|||
#define ZYNQMP_UART0_BASE 0xFF000000 |
|||
#define ZYNQMP_UART1_BASE 0xFF001000 |
|||
|
|||
#define PLAT_ARM_CRASH_UART_BASE ZYNQMP_UART0_BASE |
|||
/* impossible to call C routine how it is done now - hardcode any value */ |
|||
#define PLAT_ARM_CRASH_UART_CLK_IN_HZ 100000000 /* FIXME */ |
|||
|
|||
/* Must be non zero */ |
|||
#define ZYNQMP_UART_BAUDRATE 115200 |
|||
#define ARM_CONSOLE_BAUDRATE ZYNQMP_UART_BAUDRATE |
|||
|
|||
/* Silicon version detection */ |
|||
#define ZYNQMP_SILICON_VER_MASK 0xF000 |
|||
#define ZYNQMP_SILICON_VER_SHIFT 12 |
|||
#define ZYNQMP_CSU_VERSION_SILICON 0 |
|||
#define ZYNQMP_CSU_VERSION_EP108 1 |
|||
#define ZYNQMP_CSU_VERSION_VELOCE 2 |
|||
#define ZYNQMP_CSU_VERSION_QEMU 3 |
|||
|
|||
#define ZYNQMP_RTL_VER_MASK 0xFF0 |
|||
#define ZYNQMP_RTL_VER_SHIFT 4 |
|||
|
|||
#define ZYNQMP_PS_VER_MASK 0xF |
|||
#define ZYNQMP_PS_VER_SHIFT 0 |
|||
|
|||
#define ZYNQMP_CSU_BASEADDR 0xFFCA0000 |
|||
#define ZYNQMP_CSU_IDCODE_OFFSET 0x40 |
|||
|
|||
#define ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT 0 |
|||
#define ZYNQMP_CSU_IDCODE_XILINX_ID_MASK (0xFFF << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT) |
|||
#define ZYNQMP_CSU_IDCODE_XILINX_ID 0x093 |
|||
|
|||
#define ZYNQMP_CSU_IDCODE_SVD_SHIFT 12 |
|||
#define ZYNQMP_CSU_IDCODE_SVD_MASK (0xE << ZYNQMP_CSU_IDCODE_SVD_SHIFT) |
|||
#define ZYNQMP_CSU_IDCODE_DEVICE_CODE_SHIFT 15 |
|||
#define ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK (0xF << ZYNQMP_CSU_IDCODE_DEVICE_CODE_SHIFT) |
|||
#define ZYNQMP_CSU_IDCODE_SUB_FAMILY_SHIFT 19 |
|||
#define ZYNQMP_CSU_IDCODE_SUB_FAMILY_MASK (0x3 << ZYNQMP_CSU_IDCODE_SUB_FAMILY_SHIFT) |
|||
#define ZYNQMP_CSU_IDCODE_FAMILY_SHIFT 21 |
|||
#define ZYNQMP_CSU_IDCODE_FAMILY_MASK (0x7F << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT) |
|||
#define ZYNQMP_CSU_IDCODE_FAMILY 0x23 |
|||
|
|||
#define ZYNQMP_CSU_IDCODE_REVISION_SHIFT 28 |
|||
#define ZYNQMP_CSU_IDCODE_REVISION_MASK (0xF << ZYNQMP_CSU_IDCODE_REVISION_SHIFT) |
|||
#define ZYNQMP_CSU_IDCODE_REVISION 0 |
|||
|
|||
#define ZYNQMP_CSU_VERSION_OFFSET 0x44 |
|||
|
|||
#endif /* __ZYNQMP_DEF_H__ */ |
@ -0,0 +1,42 @@ |
|||
/*
|
|||
* Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#ifndef __ZYNQMP_PRIVATE_H__ |
|||
#define __ZYNQMP_PRIVATE_H__ |
|||
|
|||
#include <interrupt_mgmt.h> |
|||
|
|||
void zynqmp_config_setup(void); |
|||
|
|||
/* ZynqMP specific functions */ |
|||
unsigned int zynqmp_get_uart_clk(void); |
|||
int zynqmp_is_pmu_up(void); |
|||
|
|||
#endif /* __ZYNQMP_PRIVATE_H__ */ |
Loading…
Reference in new issue