diff options
37 files changed, 481 insertions, 279 deletions
diff --git a/bl1/bl1_fwu.c b/bl1/bl1_fwu.c index f7fae682..e2ede681 100644 --- a/bl1/bl1_fwu.c +++ b/bl1/bl1_fwu.c @@ -109,7 +109,7 @@ register_t bl1_fwu_smc_handler(unsigned int smc_fid, break; } - SMC_RET0(handle); + SMC_RET1(handle, SMC_UNK); } /******************************************************************************* diff --git a/drivers/ti/uart/aarch64/16550_console.S b/drivers/ti/uart/aarch64/16550_console.S index 489fcbea..1b9cab8e 100644 --- a/drivers/ti/uart/aarch64/16550_console.S +++ b/drivers/ti/uart/aarch64/16550_console.S @@ -115,9 +115,6 @@ func console_core_putc b.ne 1b mov w2, #0xD /* '\r' */ str w2, [x1, #UARTTX] - ldr w2, [x1, #UARTFCR] - orr w2, w2, #UARTFCR_TXCLR - str w2, [x1, #UARTFCR] /* Check if the transmit FIFO is full */ 2: ldr w2, [x1, #UARTLSR] @@ -125,9 +122,6 @@ func console_core_putc cmp w2, #(UARTLSR_TEMT | UARTLSR_THRE) b.ne 2b str w0, [x1, #UARTTX] - ldr w2, [x1, #UARTFCR] - orr w2, w2, #UARTFCR_TXCLR - str w2, [x1, #UARTFCR] ret putc_error: mov w0, #-1 diff --git a/include/bl32/payloads/tlk.h b/include/bl32/payloads/tlk.h index d355313e..1a83b1f7 100644 --- a/include/bl32/payloads/tlk.h +++ b/include/bl32/payloads/tlk.h @@ -31,7 +31,7 @@ #ifndef __TLK_H__ #define __TLK_H__ -#include <utils.h> +#include <utils_def.h> /* * Generate function IDs for the Trusted OS/Apps diff --git a/include/common/bl_common.h b/include/common/bl_common.h index 38be6283..2a026b8f 100644 --- a/include/common/bl_common.h +++ b/include/common/bl_common.h @@ -85,7 +85,7 @@ #include <stddef.h> #include <stdint.h> #include <types.h> -#include <utils.h> /* To retain compatibility */ +#include <utils_def.h> /* To retain compatibility */ /* * Declarations of linker defined symbols to help determine memory layout of diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h index 4b323d33..ef7241d3 100644 --- a/include/lib/aarch64/arch.h +++ b/include/lib/aarch64/arch.h @@ -31,7 +31,7 @@ #ifndef __ARCH_H__ #define __ARCH_H__ -#include <utils.h> +#include <utils_def.h> /******************************************************************************* * MIDR bit definitions diff --git a/include/lib/cpus/errata_report.h b/include/lib/cpus/errata_report.h index 6c6a844d..228ffea2 100644 --- a/include/lib/cpus/errata_report.h +++ b/include/lib/cpus/errata_report.h @@ -36,7 +36,7 @@ #include <arch.h> #include <arch_helpers.h> #include <spinlock.h> -#include <utils.h> +#include <utils_def.h> #if DEBUG void print_errata_status(void); diff --git a/include/lib/smcc.h b/include/lib/smcc.h index 708805f9..5fad7b8a 100644 --- a/include/lib/smcc.h +++ b/include/lib/smcc.h @@ -31,7 +31,7 @@ #ifndef __SMCC_H__ #define __SMCC_H__ -#include <utils.h> +#include <utils_def.h> /******************************************************************************* * Bit definitions inside the function id as per the SMC calling convention @@ -58,6 +58,7 @@ #define SMC_64 1 #define SMC_32 0 +#define SMC_OK 0 #define SMC_UNK 0xffffffff #define SMC_TYPE_FAST ULL(1) #if !ERROR_DEPRECATED diff --git a/include/lib/utils.h b/include/lib/utils.h index 279c9135..c085b7d5 100644 --- a/include/lib/utils.h +++ b/include/lib/utils.h @@ -31,67 +31,8 @@ #ifndef __UTILS_H__ #define __UTILS_H__ -/* Compute the number of elements in the given array */ -#define ARRAY_SIZE(a) \ - (sizeof(a) / sizeof((a)[0])) - -#define IS_POWER_OF_TWO(x) \ - (((x) & ((x) - 1)) == 0) - -#define SIZE_FROM_LOG2_WORDS(n) (4 << (n)) - -#define BIT(nr) (1UL << (nr)) - -#define MIN(x, y) __extension__ ({ \ - __typeof__(x) _x = (x); \ - __typeof__(y) _y = (y); \ - (void)(&_x == &_y); \ - _x < _y ? _x : _y; \ -}) - -#define MAX(x, y) __extension__ ({ \ - __typeof__(x) _x = (x); \ - __typeof__(y) _y = (y); \ - (void)(&_x == &_y); \ - _x > _y ? _x : _y; \ -}) - -/* - * The round_up() macro rounds up a value to the given boundary in a - * type-agnostic yet type-safe manner. The boundary must be a power of two. - * In other words, it computes the smallest multiple of boundary which is - * greater than or equal to value. - * - * round_down() is similar but rounds the value down instead. - */ -#define round_boundary(value, boundary) \ - ((__typeof__(value))((boundary) - 1)) - -#define round_up(value, boundary) \ - ((((value) - 1) | round_boundary(value, boundary)) + 1) - -#define round_down(value, boundary) \ - ((value) & ~round_boundary(value, boundary)) - -/* - * Evaluates to 1 if (ptr + inc) overflows, 0 otherwise. - * Both arguments must be unsigned pointer values (i.e. uintptr_t). - */ -#define check_uptr_overflow(ptr, inc) \ - (((ptr) > UINTPTR_MAX - (inc)) ? 1 : 0) - -/* - * For those constants to be shared between C and other sources, apply a 'ull' - * suffix to the argument only in C, to avoid undefined or unintended behaviour. - * - * The GNU assembler and linker do not support the 'ull' suffix (it causes the - * build process to fail) therefore the suffix is omitted when used in linker - * scripts and assembler files. -*/ -#if defined(__LINKER__) || defined(__ASSEMBLY__) -# define ULL(_x) (_x) -#else -# define ULL(_x) (_x##ull) +#if !ERROR_DEPRECATED +#include <utils_def.h> #endif /* diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h new file mode 100644 index 00000000..202f0508 --- /dev/null +++ b/include/lib/utils_def.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2016-2017, 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 __UTILS_DEF_H__ +#define __UTILS_DEF_H__ + +/* Compute the number of elements in the given array */ +#define ARRAY_SIZE(a) \ + (sizeof(a) / sizeof((a)[0])) + +#define IS_POWER_OF_TWO(x) \ + (((x) & ((x) - 1)) == 0) + +#define SIZE_FROM_LOG2_WORDS(n) (4 << (n)) + +#define BIT(nr) (1UL << (nr)) + +#define MIN(x, y) __extension__ ({ \ + __typeof__(x) _x = (x); \ + __typeof__(y) _y = (y); \ + (void)(&_x == &_y); \ + _x < _y ? _x : _y; \ +}) + +#define MAX(x, y) __extension__ ({ \ + __typeof__(x) _x = (x); \ + __typeof__(y) _y = (y); \ + (void)(&_x == &_y); \ + _x > _y ? _x : _y; \ +}) + +/* + * The round_up() macro rounds up a value to the given boundary in a + * type-agnostic yet type-safe manner. The boundary must be a power of two. + * In other words, it computes the smallest multiple of boundary which is + * greater than or equal to value. + * + * round_down() is similar but rounds the value down instead. + */ +#define round_boundary(value, boundary) \ + ((__typeof__(value))((boundary) - 1)) + +#define round_up(value, boundary) \ + ((((value) - 1) | round_boundary(value, boundary)) + 1) + +#define round_down(value, boundary) \ + ((value) & ~round_boundary(value, boundary)) + +/* + * Evaluates to 1 if (ptr + inc) overflows, 0 otherwise. + * Both arguments must be unsigned pointer values (i.e. uintptr_t). + */ +#define check_uptr_overflow(ptr, inc) \ + (((ptr) > UINTPTR_MAX - (inc)) ? 1 : 0) + +/* + * For those constants to be shared between C and other sources, apply a 'ull' + * suffix to the argument only in C, to avoid undefined or unintended behaviour. + * + * The GNU assembler and linker do not support the 'ull' suffix (it causes the + * build process to fail) therefore the suffix is omitted when used in linker + * scripts and assembler files. +*/ +#if defined(__LINKER__) || defined(__ASSEMBLY__) +# define ULL(_x) (_x) +#else +# define ULL(_x) (_x##ull) +#endif + +#endif /* __UTILS_DEF_H__ */ diff --git a/include/lib/xlat_tables/xlat_tables_defs.h b/include/lib/xlat_tables/xlat_tables_defs.h index 3105d7aa..032ce925 100644 --- a/include/lib/xlat_tables/xlat_tables_defs.h +++ b/include/lib/xlat_tables/xlat_tables_defs.h @@ -31,7 +31,7 @@ #ifndef __XLAT_TABLES_DEFS_H__ #define __XLAT_TABLES_DEFS_H__ -#include <utils.h> +#include <utils_def.h> /* Miscellaneous MMU related constants */ #define NUM_2MB_IN_GB (1 << 9) diff --git a/include/plat/arm/board/common/board_css_def.h b/include/plat/arm/board/common/board_css_def.h index 4b5e84dd..88a97d99 100644 --- a/include/plat/arm/board/common/board_css_def.h +++ b/include/plat/arm/board/common/board_css_def.h @@ -33,7 +33,7 @@ #include <common_def.h> #include <soc_css_def.h> -#include <utils.h> +#include <utils_def.h> #include <v2m_def.h> /* diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h index 43e0eb89..f5f83780 100644 --- a/include/plat/arm/common/arm_def.h +++ b/include/plat/arm/common/arm_def.h @@ -34,7 +34,7 @@ #include <common_def.h> #include <platform_def.h> #include <tbbr_img_def.h> -#include <utils.h> +#include <utils_def.h> #include <xlat_tables_defs.h> diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h index 4ba4a845..8ea32b9a 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -35,7 +35,7 @@ #include <cassert.h> #include <cpu_data.h> #include <stdint.h> -#include <utils.h> +#include <utils_def.h> /******************************************************************************* * Forward declarations diff --git a/include/plat/arm/css/common/css_pm.h b/include/plat/arm/css/common/css_pm.h index 489275e9..1e1bab79 100644 --- a/include/plat/arm/css/common/css_pm.h +++ b/include/plat/arm/css/common/css_pm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2017, 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: @@ -35,11 +35,15 @@ #include <psci.h> #include <types.h> +/* System power domain at level 2, as currently implemented by CSS platforms */ +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2 + /* Macros to read the CSS power domain state */ #define CSS_CORE_PWR_STATE(state) (state)->pwr_domain_state[ARM_PWR_LVL0] #define CSS_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[ARM_PWR_LVL1] -#define CSS_SYSTEM_PWR_STATE(state) ((PLAT_MAX_PWR_LVL > ARM_PWR_LVL1) ?\ - (state)->pwr_domain_state[ARM_PWR_LVL2] : 0) +#define CSS_SYSTEM_PWR_STATE(state) \ + ((PLAT_MAX_PWR_LVL == CSS_SYSTEM_PWR_DMN_LVL) ?\ + (state)->pwr_domain_state[CSS_SYSTEM_PWR_DMN_LVL] : 0) int css_pwr_domain_on(u_register_t mpidr); void css_pwr_domain_on_finish(const psci_power_state_t *target_state); diff --git a/include/plat/arm/soc/common/soc_css_def.h b/include/plat/arm/soc/common/soc_css_def.h index efd78f04..ecced3d9 100644 --- a/include/plat/arm/soc/common/soc_css_def.h +++ b/include/plat/arm/soc/common/soc_css_def.h @@ -32,7 +32,7 @@ #define __SOC_CSS_DEF_H__ #include <common_def.h> -#include <utils.h> +#include <utils_def.h> /* diff --git a/lib/xlat_tables/xlat_tables_common.c b/lib/xlat_tables/xlat_tables_common.c index 4426ccef..23f3daa8 100644 --- a/lib/xlat_tables/xlat_tables_common.c +++ b/lib/xlat_tables/xlat_tables_common.c @@ -273,15 +273,19 @@ static uint64_t mmap_desc(mmap_attr_t attr, unsigned long long addr_pa, } /* - * Returns attributes of area at `base_va` with size `size`. It returns the - * attributes of the innermost region that contains it. If there are partial - * overlaps, it returns -1, as a smaller size is needed. + * Look for the innermost region that contains the area at `base_va` with size + * `size`. Populate *attr with the attributes of this region. + * + * On success, this function returns 0. + * If there are partial overlaps (meaning that a smaller size is needed) or if + * the region can't be found in the given area, it returns -1. In this case the + * value pointed by attr should be ignored by the caller. */ -static mmap_attr_t mmap_region_attr(mmap_region_t *mm, uintptr_t base_va, - size_t size) +static int mmap_region_attr(mmap_region_t *mm, uintptr_t base_va, + size_t size, mmap_attr_t *attr) { /* Don't assume that the area is contained in the first region */ - mmap_attr_t attr = -1; + int ret = -1; /* * Get attributes from last (innermost) region that contains the @@ -301,23 +305,25 @@ static mmap_attr_t mmap_region_attr(mmap_region_t *mm, uintptr_t base_va, for (;; ++mm) { if (!mm->size) - return attr; /* Reached end of list */ + return ret; /* Reached end of list */ if (mm->base_va > base_va + size - 1) - return attr; /* Next region is after area so end */ + return ret; /* Next region is after area so end */ if (mm->base_va + mm->size - 1 < base_va) continue; /* Next region has already been overtaken */ - if (mm->attr == attr) + if (!ret && mm->attr == *attr) continue; /* Region doesn't override attribs so skip */ if (mm->base_va > base_va || mm->base_va + mm->size - 1 < base_va + size - 1) return -1; /* Region doesn't fully cover our area */ - attr = mm->attr; + *attr = mm->attr; + ret = 0; } + return ret; } static mmap_region_t *init_xlation_table_inner(mmap_region_t *mm, @@ -360,9 +366,10 @@ static mmap_region_t *init_xlation_table_inner(mmap_region_t *mm, * there are partially overlapping regions. On success, * it will return the innermost region's attributes. */ - mmap_attr_t attr = mmap_region_attr(mm, base_va, - level_size); - if (attr >= 0) { + mmap_attr_t attr; + int r = mmap_region_attr(mm, base_va, level_size, &attr); + + if (!r) { desc = mmap_desc(attr, base_va - mm->base_va + mm->base_pa, level); diff --git a/lib/xlat_tables/xlat_tables_private.h b/lib/xlat_tables/xlat_tables_private.h index f0f656bd..54ad909f 100644 --- a/lib/xlat_tables/xlat_tables_private.h +++ b/lib/xlat_tables/xlat_tables_private.h @@ -33,7 +33,7 @@ #include <cassert.h> #include <platform_def.h> -#include <utils.h> +#include <utils_def.h> /* * If the platform hasn't defined a physical and a virtual address space size diff --git a/lib/xlat_tables_v2/xlat_tables_private.h b/lib/xlat_tables_v2/xlat_tables_private.h index 048c4a83..e79890e5 100644 --- a/lib/xlat_tables_v2/xlat_tables_private.h +++ b/lib/xlat_tables_v2/xlat_tables_private.h @@ -33,7 +33,7 @@ #include <cassert.h> #include <platform_def.h> -#include <utils.h> +#include <utils_def.h> /* * If the platform hasn't defined a physical and a virtual address space size diff --git a/plat/arm/board/juno/juno_pm.c b/plat/arm/board/juno/juno_pm.c deleted file mode 100644 index c0fa628e..00000000 --- a/plat/arm/board/juno/juno_pm.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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 <css_pm.h> -#include <plat_arm.h> - -/* - * Custom `validate_power_state` handler for Juno. According to PSCI - * Specification, interrupts targeted to cores in PSCI CPU SUSPEND should - * be able to resume it. On Juno, when the system power domain is suspended, - * the GIC is also powered down. The SCP resumes the final core to be suspend - * when an external wake-up event is received. But the other cores cannot be - * woken up by a targeted interrupt, because GIC doesn't forward these - * interrupts to the SCP. Due to this hardware limitation, we down-grade PSCI - * CPU SUSPEND requests targeted to the system power domain level - * to cluster power domain level. - * - * The system power domain suspend on Juno is only supported only via - * PSCI SYSTEM SUSPEND API. - */ -static int juno_validate_power_state(unsigned int power_state, - psci_power_state_t *req_state) -{ - int rc; - rc = arm_validate_power_state(power_state, req_state); - - /* - * Ensure that the system power domain level is never suspended - * via PSCI CPU SUSPEND API. Currently system suspend is only - * supported via PSCI SYSTEM SUSPEND API. - */ - req_state->pwr_domain_state[ARM_PWR_LVL2] = ARM_LOCAL_STATE_RUN; - return rc; -} - -/* - * Custom `translate_power_state_by_mpidr` handler for Juno. Unlike in the - * `juno_validate_power_state`, we do not down-grade the system power - * domain level request in `power_state` as it will be used to query the - * PSCI_STAT_COUNT/RESIDENCY at the system power domain level. - */ -static int juno_translate_power_state_by_mpidr(u_register_t mpidr, - unsigned int power_state, - psci_power_state_t *output_state) -{ - return arm_validate_power_state(power_state, output_state); -} - -/******************************************************************************* - * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard - * platform will take care of registering the handlers with PSCI. - ******************************************************************************/ -plat_psci_ops_t plat_arm_psci_pm_ops = { - .pwr_domain_on = css_pwr_domain_on, - .pwr_domain_on_finish = css_pwr_domain_on_finish, - .pwr_domain_off = css_pwr_domain_off, - .cpu_standby = css_cpu_standby, - .pwr_domain_suspend = css_pwr_domain_suspend, - .pwr_domain_suspend_finish = css_pwr_domain_suspend_finish, - .system_off = css_system_off, - .system_reset = css_system_reset, - .validate_power_state = juno_validate_power_state, - .validate_ns_entrypoint = arm_validate_ns_entrypoint, - .get_sys_suspend_power_state = css_get_sys_suspend_power_state, - .translate_power_state_by_mpidr = juno_translate_power_state_by_mpidr, - .get_node_hw_state = css_node_hw_state -}; diff --git a/plat/arm/board/juno/juno_trng.c b/plat/arm/board/juno/juno_trng.c index 2fcddcdb..9bb760f9 100644 --- a/plat/arm/board/juno/juno_trng.c +++ b/plat/arm/board/juno/juno_trng.c @@ -31,7 +31,7 @@ #include <assert.h> #include <mmio.h> #include <string.h> -#include <utils.h> +#include <utils_def.h> #include "juno_def.h" #define NSAMPLE_CLOCKS 1 /* min 1 cycle, max 231 cycles */ diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk index 08554381..e29f8c86 100644 --- a/plat/arm/board/juno/platform.mk +++ b/plat/arm/board/juno/platform.mk @@ -73,7 +73,6 @@ BL2U_SOURCES += ${JUNO_SECURITY_SOURCES} BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \ lib/cpus/aarch64/cortex_a57.S \ lib/cpus/aarch64/cortex_a72.S \ - plat/arm/board/juno/juno_pm.c \ plat/arm/board/juno/juno_topology.c \ ${JUNO_GIC_SOURCES} \ ${JUNO_INTERCONNECT_SOURCES} \ diff --git a/plat/arm/css/common/css_bl2_setup.c b/plat/arm/css/common/css_bl2_setup.c index 5361d897..65a98ba4 100644 --- a/plat/arm/css/common/css_bl2_setup.c +++ b/plat/arm/css/common/css_bl2_setup.c @@ -34,6 +34,7 @@ #include <mmio.h> #include <plat_arm.h> #include <string.h> +#include <utils.h> #include "css_scp_bootloader.h" /* Weak definition may be overridden in specific CSS based platform */ diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c index d4dd0af7..21ce8655 100644 --- a/plat/arm/css/common/css_pm.c +++ b/plat/arm/css/common/css_pm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2017, 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: @@ -75,6 +75,13 @@ const unsigned int arm_pm_idle_states[] = { CASSERT(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL1, assert_max_pwr_lvl_supported_mismatch); +/* + * Ensure that the PLAT_MAX_PWR_LVL is not greater than CSS_SYSTEM_PWR_DMN_LVL + * assumed by the CSS layer. + */ +CASSERT(PLAT_MAX_PWR_LVL <= CSS_SYSTEM_PWR_DMN_LVL, + assert_max_pwr_lvl_higher_than_css_sys_lvl); + /******************************************************************************* * Handler called when a power domain is about to be turned on. The * level and mpidr determine the affinity instance. @@ -243,7 +250,7 @@ void css_get_sys_suspend_power_state(psci_power_state_t *req_state) * System Suspend is supported only if the system power domain node * is implemented. */ - assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2); + assert(PLAT_MAX_PWR_LVL == CSS_SYSTEM_PWR_DMN_LVL); for (i = ARM_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++) req_state->pwr_domain_state[i] = ARM_LOCAL_STATE_OFF; @@ -257,6 +264,39 @@ int css_node_hw_state(u_register_t mpidr, unsigned int power_level) return css_scp_get_power_state(mpidr, power_level); } +/* + * The system power domain suspend is only supported only via + * PSCI SYSTEM_SUSPEND API. PSCI CPU_SUSPEND request to system power domain + * will be downgraded to the lower level. + */ +static int css_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + int rc; + rc = arm_validate_power_state(power_state, req_state); + + /* + * Ensure that the system power domain level is never suspended + * via PSCI CPU SUSPEND API. Currently system suspend is only + * supported via PSCI SYSTEM SUSPEND API. + */ + req_state->pwr_domain_state[CSS_SYSTEM_PWR_DMN_LVL] = ARM_LOCAL_STATE_RUN; + return rc; +} + +/* + * Custom `translate_power_state_by_mpidr` handler for CSS. Unlike in the + * `css_validate_power_state`, we do not downgrade the system power + * domain level request in `power_state` as it will be used to query the + * PSCI_STAT_COUNT/RESIDENCY at the system power domain level. + */ +static int css_translate_power_state_by_mpidr(u_register_t mpidr, + unsigned int power_state, + psci_power_state_t *output_state) +{ + return arm_validate_power_state(power_state, output_state); +} + /******************************************************************************* * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard * platform will take care of registering the handlers with PSCI. @@ -270,7 +310,9 @@ plat_psci_ops_t plat_arm_psci_pm_ops = { .pwr_domain_suspend_finish = css_pwr_domain_suspend_finish, .system_off = css_system_off, .system_reset = css_system_reset, - .validate_power_state = arm_validate_power_state, + .validate_power_state = css_validate_power_state, .validate_ns_entrypoint = arm_validate_ns_entrypoint, - .get_node_hw_state = css_node_hw_state + .translate_power_state_by_mpidr = css_translate_power_state_by_mpidr, + .get_node_hw_state = css_node_hw_state, + .get_sys_suspend_power_state = css_get_sys_suspend_power_state }; diff --git a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c index 41a4ede8..87c7ed03 100644 --- a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c +++ b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c @@ -40,7 +40,8 @@ #include <string.h> #include <tegra_def.h> #include <tegra_platform.h> -#include <xlat_tables.h> +#include <utils.h> +#include <xlat_tables_v2.h> #define TEGRA_GPU_RESET_REG_OFFSET 0x30 #define GPU_RESET_BIT (1 << 0) @@ -450,7 +451,7 @@ void tegra_memctrl_restore_settings(void) tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, video_mem_size_mb); /* - * MCE propogates the VideoMem configuration values across the + * MCE propagates the VideoMem configuration values across the * CCPLEX. */ mce_update_gsc_videomem(); @@ -490,7 +491,7 @@ void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes) tegra_mc_read_32(MC_SECURITY_CFG1_0)); /* - * MCE propogates the security configuration values across the + * MCE propagates the security configuration values across the * CCPLEX. */ mce_update_gsc_tzdram(); @@ -506,25 +507,28 @@ void tegra_memctrl_tzram_setup(uint64_t phys_base, uint32_t size_in_bytes) { uint32_t index; uint32_t total_128kb_blocks = size_in_bytes >> 17; - uint32_t residual_4kb_blocks = (size_in_bytes & 0x1FFFF) >> 12; + uint32_t residual_4kb_blocks = (size_in_bytes & (uint32_t)0x1FFFF) >> 12; uint32_t val; + INFO("Configuring TrustZone SRAM Memory Carveout\n"); + /* * Reset the access configuration registers to restrict access * to the TZRAM aperture */ - for (index = MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG0; - index <= MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS5; - index += 4) + for (index = MC_TZRAM_CLIENT_ACCESS_CFG0; + index < ((uint32_t)MC_TZRAM_CARVEOUT_CFG + (uint32_t)MC_GSC_CONFIG_REGS_SIZE); + index += 4U) { tegra_mc_write_32(index, 0); + } /* * Set the TZRAM base. TZRAM base must be 4k aligned, at least. */ - assert(!(phys_base & 0xFFF)); + assert((phys_base & (uint64_t)0xFFF) == 0U); tegra_mc_write_32(MC_TZRAM_BASE_LO, (uint32_t)phys_base); tegra_mc_write_32(MC_TZRAM_BASE_HI, - (uint32_t)(phys_base >> 32) & TZRAM_BASE_HI_MASK); + (uint32_t)(phys_base >> 32) & MC_GSC_BASE_HI_MASK); /* * Set the TZRAM size @@ -533,7 +537,7 @@ void tegra_memctrl_tzram_setup(uint64_t phys_base, uint32_t size_in_bytes) * blocks) * */ - val = (residual_4kb_blocks << TZRAM_SIZE_RANGE_4KB_SHIFT) | + val = (residual_4kb_blocks << MC_GSC_SIZE_RANGE_4KB_SHIFT) | total_128kb_blocks; tegra_mc_write_32(MC_TZRAM_SIZE, val); @@ -543,17 +547,96 @@ void tegra_memctrl_tzram_setup(uint64_t phys_base, uint32_t size_in_bytes) * at all. */ val = tegra_mc_read_32(MC_TZRAM_CARVEOUT_CFG); - val &= ~TZRAM_ENABLE_TZ_LOCK_BIT; - val |= TZRAM_LOCK_CFG_SETTINGS_BIT; + val &= ~MC_GSC_ENABLE_TZ_LOCK_BIT; + val |= MC_GSC_LOCK_CFG_SETTINGS_BIT; tegra_mc_write_32(MC_TZRAM_CARVEOUT_CFG, val); /* - * MCE propogates the security configuration values across the + * MCE propagates the security configuration values across the * CCPLEX. */ mce_update_gsc_tzram(); } +static void tegra_lock_videomem_nonoverlap(uint64_t phys_base, + uint64_t size_in_bytes) +{ + uint32_t index; + uint64_t total_128kb_blocks = size_in_bytes >> 17; + uint64_t residual_4kb_blocks = (size_in_bytes & (uint32_t)0x1FFFF) >> 12; + uint64_t val; + + /* + * Reset the access configuration registers to restrict access to + * old Videomem aperture + */ + for (index = MC_VIDEO_PROTECT_CLEAR_ACCESS_CFG0; + index < ((uint32_t)MC_VIDEO_PROTECT_CLEAR_ACCESS_CFG0 + (uint32_t)MC_GSC_CONFIG_REGS_SIZE); + index += 4U) { + tegra_mc_write_32(index, 0); + } + + /* + * Set the base. It must be 4k aligned, at least. + */ + assert((phys_base & (uint64_t)0xFFF) == 0U); + tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_LO, (uint32_t)phys_base); + tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_HI, + (uint32_t)(phys_base >> 32) & (uint32_t)MC_GSC_BASE_HI_MASK); + + /* + * Set the aperture size + * + * total size = (number of 128KB blocks) + (number of remaining 4KB + * blocks) + * + */ + val = (uint32_t)((residual_4kb_blocks << MC_GSC_SIZE_RANGE_4KB_SHIFT) | + total_128kb_blocks); + tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_SIZE, (uint32_t)val); + + /* + * Lock the configuration settings by enabling TZ-only lock and + * locking the configuration against any future changes from NS + * world. + */ + tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_CFG, + (uint32_t)MC_GSC_ENABLE_TZ_LOCK_BIT); + + /* + * MCE propagates the GSC configuration values across the + * CCPLEX. + */ +} + +static void tegra_unlock_videomem_nonoverlap(void) +{ + /* Clear the base */ + tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_LO, 0); + tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_HI, 0); + + /* Clear the size */ + tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_SIZE, 0); +} + +static void tegra_clear_videomem(uintptr_t non_overlap_area_start, + unsigned long long non_overlap_area_size) +{ + /* + * Map the NS memory first, clean it and then unmap it. + */ + mmap_add_dynamic_region(non_overlap_area_start, /* PA */ + non_overlap_area_start, /* VA */ + non_overlap_area_size, /* size */ + MT_NS | MT_RW | MT_EXECUTE_NEVER); /* attrs */ + + zero_normalmem((void *)non_overlap_area_start, non_overlap_area_size); + flush_dcache_range(non_overlap_area_start, non_overlap_area_size); + + mmap_remove_dynamic_region(non_overlap_area_start, + non_overlap_area_size); +} + /* * Program the Video Memory carveout region * @@ -562,7 +645,10 @@ void tegra_memctrl_tzram_setup(uint64_t phys_base, uint32_t size_in_bytes) */ void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes) { + uintptr_t vmem_end_old = video_mem_base + (video_mem_size_mb << 20); + uintptr_t vmem_end_new = phys_base + size_in_bytes; uint32_t regval; + unsigned long long non_overlap_area_size; /* * The GPU is the user of the Video Memory region. In order to @@ -570,7 +656,7 @@ void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes) * new base/size ONLY if the GPU is in reset mode. */ regval = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_REG_OFFSET); - if ((regval & GPU_RESET_BIT) == 0) { + if ((regval & GPU_RESET_BIT) == 0U) { ERROR("GPU not in reset! Video Memory setup failed\n"); return; } @@ -581,17 +667,61 @@ void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes) */ INFO("Configuring Video Memory Carveout\n"); + /* + * Configure Memory Controller directly for the first time. + */ + if (video_mem_base == 0U) + goto done; + + /* + * Lock the non overlapping memory being cleared so that other masters + * do not accidently write to it. The memory would be unlocked once + * the non overlapping region is cleared and the new memory + * settings take effect. + */ + tegra_lock_videomem_nonoverlap(video_mem_base, + video_mem_size_mb << 20); + + /* + * Clear the old regions now being exposed. The following cases + * can occur - + * + * 1. clear whole old region (no overlap with new region) + * 2. clear old sub-region below new base + * 3. clear old sub-region above new end + */ + INFO("Cleaning previous Video Memory Carveout\n"); + + if (phys_base > vmem_end_old || video_mem_base > vmem_end_new) { + tegra_clear_videomem(video_mem_base, + (uint64_t)video_mem_size_mb << 20); + } else { + if (video_mem_base < phys_base) { + non_overlap_area_size = phys_base - video_mem_base; + tegra_clear_videomem(video_mem_base, non_overlap_area_size); + } + if (vmem_end_old > vmem_end_new) { + non_overlap_area_size = vmem_end_old - vmem_end_new; + tegra_clear_videomem(vmem_end_new, non_overlap_area_size); + } + } + +done: + /* program the Videomem aperture */ tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)phys_base); tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI, (uint32_t)(phys_base >> 32)); tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, size_in_bytes >> 20); + /* unlock the previous locked nonoverlapping aperture */ + tegra_unlock_videomem_nonoverlap(); + /* store new values */ video_mem_base = phys_base; video_mem_size_mb = size_in_bytes >> 20; /* - * MCE propogates the VideoMem configuration values across the + * MCE propagates the VideoMem configuration values across the * CCPLEX. */ mce_update_gsc_videomem(); diff --git a/plat/nvidia/tegra/common/drivers/smmu/smmu.c b/plat/nvidia/tegra/common/drivers/smmu/smmu.c index a985532c..60fd3006 100644 --- a/plat/nvidia/tegra/common/drivers/smmu/smmu.c +++ b/plat/nvidia/tegra/common/drivers/smmu/smmu.c @@ -89,7 +89,6 @@ void tegra_smmu_save_context(uint64_t smmu_ctx_addr) { uint32_t i, num_entries = 0; smmu_regs_t *smmu_ctx_regs; -#if DEBUG plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params(); uint64_t tzdram_base = params_from_bl2->tzdram_base; uint64_t tzdram_end = tzdram_base + params_from_bl2->tzdram_size; @@ -102,8 +101,6 @@ void tegra_smmu_save_context(uint64_t smmu_ctx_addr) (1 << (((reg_id1 >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1)); assert(!((pgshift != PGSHIFT) || (cb_size != CB_SIZE))); -#endif - assert((smmu_ctx_addr >= tzdram_base) && (smmu_ctx_addr <= tzdram_end)); /* get SMMU context table */ diff --git a/plat/nvidia/tegra/common/tegra_bl31_setup.c b/plat/nvidia/tegra/common/tegra_bl31_setup.c index 8307af70..1dc80663 100644 --- a/plat/nvidia/tegra/common/tegra_bl31_setup.c +++ b/plat/nvidia/tegra/common/tegra_bl31_setup.c @@ -205,6 +205,11 @@ void bl31_early_platform_setup(bl31_params_t *from_bl2, } /* + * Initialize delay timer + */ + tegra_delay_timer_init(); + + /* * Do initial security configuration to allow DRAM/device access. */ tegra_memctrl_tzdram_setup(plat_bl31_params_from_bl2.tzdram_base, @@ -264,11 +269,6 @@ void bl31_platform_setup(void) plat_gic_setup(); /* - * Initialize delay timer - */ - tegra_delay_timer_init(); - - /* * Setup secondary CPU POR infrastructure. */ plat_secondary_setup(); @@ -354,6 +354,12 @@ void bl31_plat_arch_setup(void) MT_DEVICE | MT_RW | MT_SECURE); #endif + /* map on-chip free running uS timer */ + mmap_add_region(page_align((uint64_t)TEGRA_TMRUS_BASE, 0), + page_align((uint64_t)TEGRA_TMRUS_BASE, 0), + (uint64_t)TEGRA_TMRUS_SIZE, + MT_DEVICE | MT_RO | MT_SECURE); + /* add MMIO space */ plat_mmio_map = plat_get_mmio_map(); if (plat_mmio_map) @@ -375,13 +381,12 @@ void bl31_plat_arch_setup(void) ******************************************************************************/ int bl31_check_ns_address(uint64_t base, uint64_t size_in_bytes) { - uint64_t end = base + size_in_bytes - 1; + uint64_t end = base + size_in_bytes; /* * Check if the NS DRAM address is valid */ - if ((base < TEGRA_DRAM_BASE) || (end > TEGRA_DRAM_END) || - (base >= end)) { + if ((base < TEGRA_DRAM_BASE) || (end > TEGRA_DRAM_END)) { ERROR("NS address is out-of-bounds!\n"); return -EFAULT; } diff --git a/plat/nvidia/tegra/common/tegra_common.mk b/plat/nvidia/tegra/common/tegra_common.mk index e8e25ef0..cb4d1886 100644 --- a/plat/nvidia/tegra/common/tegra_common.mk +++ b/plat/nvidia/tegra/common/tegra_common.mk @@ -28,19 +28,6 @@ # POSSIBILITY OF SUCH DAMAGE. # -CRASH_REPORTING := 1 -$(eval $(call add_define,CRASH_REPORTING)) - -ASM_ASSERTION := 1 -$(eval $(call add_define,ASM_ASSERTION)) - -USE_COHERENT_MEM := 0 - -SEPARATE_CODE_AND_RODATA := 1 - -PLAT_XLAT_TABLES_DYNAMIC := 1 -$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC)) - PLAT_INCLUDES := -Iplat/nvidia/tegra/include/drivers \ -Iplat/nvidia/tegra/include \ -Iplat/nvidia/tegra/include/${TARGET_SOC} diff --git a/plat/nvidia/tegra/include/t132/tegra_def.h b/plat/nvidia/tegra/include/t132/tegra_def.h index 4ba4f12c..e488bd87 100644 --- a/plat/nvidia/tegra/include/t132/tegra_def.h +++ b/plat/nvidia/tegra/include/t132/tegra_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2017, 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: @@ -58,6 +58,7 @@ * Tegra micro-seconds timer constants ******************************************************************************/ #define TEGRA_TMRUS_BASE 0x60005010 +#define TEGRA_TMRUS_SIZE 0x1000 /******************************************************************************* * Tegra Clock and Reset Controller constants diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h index ae11d281..8d7ab6ea 100644 --- a/plat/nvidia/tegra/include/t186/tegra_def.h +++ b/plat/nvidia/tegra/include/t186/tegra_def.h @@ -157,6 +157,16 @@ #define TEGRA_MC_STREAMID_BASE 0x02C00000 #define TEGRA_MC_BASE 0x02C10000 +/* General Security Carveout register macros */ +#define MC_GSC_CONFIG_REGS_SIZE 0x40UL +#define MC_GSC_LOCK_CFG_SETTINGS_BIT (1UL << 1) +#define MC_GSC_ENABLE_TZ_LOCK_BIT (1UL << 0) +#define MC_GSC_SIZE_RANGE_4KB_SHIFT 27UL +#define MC_GSC_BASE_LO_SHIFT 12UL +#define MC_GSC_BASE_LO_MASK 0xFFFFFUL +#define MC_GSC_BASE_HI_SHIFT 0UL +#define MC_GSC_BASE_HI_MASK 3UL + /* TZDRAM carveout configuration registers */ #define MC_SECURITY_CFG0_0 0x70 #define MC_SECURITY_CFG1_0 0x74 @@ -165,34 +175,24 @@ /* Video Memory carveout configuration registers */ #define MC_VIDEO_PROTECT_BASE_HI 0x978 #define MC_VIDEO_PROTECT_BASE_LO 0x648 -#define MC_VIDEO_PROTECT_SIZE_MB 0x64c +#define MC_VIDEO_PROTECT_SIZE_MB 0x64C + +/* + * Carveout (MC_SECURITY_CARVEOUT24) registers used to clear the + * non-overlapping Video memory region + */ +#define MC_VIDEO_PROTECT_CLEAR_CFG 0x25A0 +#define MC_VIDEO_PROTECT_CLEAR_BASE_LO 0x25A4 +#define MC_VIDEO_PROTECT_CLEAR_BASE_HI 0x25A8 +#define MC_VIDEO_PROTECT_CLEAR_SIZE 0x25AC +#define MC_VIDEO_PROTECT_CLEAR_ACCESS_CFG0 0x25B0 /* TZRAM carveout (MC_SECURITY_CARVEOUT11) configuration registers */ +#define MC_TZRAM_CARVEOUT_CFG 0x2190 #define MC_TZRAM_BASE_LO 0x2194 -#define TZRAM_BASE_LO_SHIFT 12 -#define TZRAM_BASE_LO_MASK 0xFFFFF #define MC_TZRAM_BASE_HI 0x2198 -#define TZRAM_BASE_HI_SHIFT 0 -#define TZRAM_BASE_HI_MASK 3 #define MC_TZRAM_SIZE 0x219C -#define TZRAM_SIZE_RANGE_4KB_SHIFT 27 - -#define MC_TZRAM_CARVEOUT_CFG 0x2190 -#define TZRAM_LOCK_CFG_SETTINGS_BIT (1 << 1) -#define TZRAM_ENABLE_TZ_LOCK_BIT (1 << 0) -#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG0 0x21A0 -#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG1 0x21A4 -#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG2 0x21A8 -#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG3 0x21AC -#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG4 0x21B0 -#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG5 0x21B4 - -#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS0 0x21B8 -#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS1 0x21BC -#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS2 0x21C0 -#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS3 0x21C4 -#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS4 0x21C8 -#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS5 0x21CC +#define MC_TZRAM_CLIENT_ACCESS_CFG0 0x21A0 /******************************************************************************* * Tegra UART Controller constants @@ -237,6 +237,7 @@ * Tegra micro-seconds timer constants ******************************************************************************/ #define TEGRA_TMRUS_BASE 0x0C2E0000 +#define TEGRA_TMRUS_SIZE 0x1000 /******************************************************************************* * Tegra Power Mgmt Controller constants diff --git a/plat/nvidia/tegra/include/t210/tegra_def.h b/plat/nvidia/tegra/include/t210/tegra_def.h index 09613551..d8ad10c8 100644 --- a/plat/nvidia/tegra/include/t210/tegra_def.h +++ b/plat/nvidia/tegra/include/t210/tegra_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2017, 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: @@ -83,6 +83,7 @@ * Tegra micro-seconds timer constants ******************************************************************************/ #define TEGRA_TMRUS_BASE 0x60005010 +#define TEGRA_TMRUS_SIZE 0x1000 /******************************************************************************* * Tegra Clock and Reset Controller constants diff --git a/plat/nvidia/tegra/platform.mk b/plat/nvidia/tegra/platform.mk index 2eeffca7..1f7a4dcd 100644 --- a/plat/nvidia/tegra/platform.mk +++ b/plat/nvidia/tegra/platform.mk @@ -30,12 +30,29 @@ SOC_DIR := plat/nvidia/tegra/soc/${TARGET_SOC} -# Enable PSCI v1.0 extended state ID format -PSCI_EXTENDED_STATE_ID := 1 +# dump the state on crash console +CRASH_REPORTING := 1 +$(eval $(call add_define,CRASH_REPORTING)) + +# enable assert() for release/debug builds +ENABLE_ASSERTIONS := 1 # Disable the PSCI platform compatibility layer ENABLE_PLAT_COMPAT := 0 +# enable dynamic memory mapping +PLAT_XLAT_TABLES_DYNAMIC := 1 +$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC)) + +# Enable PSCI v1.0 extended state ID format +PSCI_EXTENDED_STATE_ID := 1 + +# code and read-only data should be put on separate memory pages +SEPARATE_CODE_AND_RODATA := 1 + +# do not use coherent memory +USE_COHERENT_MEM := 0 + include plat/nvidia/tegra/common/tegra_common.mk include ${SOC_DIR}/platform_${TARGET_SOC}.mk diff --git a/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c index f05f3d0e..af21c286 100644 --- a/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c +++ b/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2017, 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: @@ -132,7 +132,7 @@ int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state) int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) { -#if DEBUG +#if ENABLE_ASSERTIONS int cpu = read_mpidr() & MPIDR_CPU_MASK; /* SYSTEM_SUSPEND only on CPU0 */ diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c b/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c index 7f711a72..87fadbe6 100644 --- a/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c +++ b/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2017, 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: @@ -30,10 +30,13 @@ #include <arch.h> #include <arch_helpers.h> +#include <assert.h> #include <debug.h> +#include <delay_timer.h> #include <denver.h> #include <mmio.h> #include <mce_private.h> +#include <platform.h> #include <sys/errno.h> #include <t18x_ari.h> @@ -49,10 +52,13 @@ #define ARI_RESPONSE_DATA_HI 0x18 /* Status values for the current request */ -#define ARI_REQ_PENDING 1 -#define ARI_REQ_ONGOING 3 -#define ARI_REQUEST_VALID_BIT (1 << 8) -#define ARI_EVT_MASK_STANDBYWFI_BIT (1 << 7) +#define ARI_REQ_PENDING 1U +#define ARI_REQ_ONGOING 3U +#define ARI_REQUEST_VALID_BIT (1U << 8) +#define ARI_EVT_MASK_STANDBYWFI_BIT (1U << 7) + +/* default timeout (ms) to wait for ARI completion */ +#define ARI_MAX_RETRY_COUNT 2000 /******************************************************************************* * ARI helper functions @@ -96,7 +102,8 @@ static inline void ari_clobber_response(uint32_t ari_base) static int ari_request_wait(uint32_t ari_base, uint32_t evt_mask, uint32_t req, uint32_t lo, uint32_t hi) { - int status; + uint32_t retries = ARI_MAX_RETRY_COUNT; + uint32_t status; /* program the request, event_mask, hi and lo registers */ ari_write_32(ari_base, lo, ARI_REQUEST_DATA_LO); @@ -112,10 +119,36 @@ static int ari_request_wait(uint32_t ari_base, uint32_t evt_mask, uint32_t req, if (evt_mask) return 0; - /* NOTE: add timeout check if needed */ - status = ari_read_32(ari_base, ARI_STATUS); - while (status & (ARI_REQ_ONGOING | ARI_REQ_PENDING)) + /* For shutdown/reboot commands, we dont have to check for timeouts */ + if ((req == (uint32_t)TEGRA_ARI_MISC_CCPLEX) && + ((lo == (uint32_t)TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF) || + (lo == (uint32_t)TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT))) { + return 0; + } + + /* + * Wait for the command response for not more than the timeout + */ + while (retries != 0U) { + + /* read the command status */ status = ari_read_32(ari_base, ARI_STATUS); + if ((status & (ARI_REQ_ONGOING | ARI_REQ_PENDING)) == 0U) + break; + + /* delay 1 ms */ + mdelay(1); + + /* decrement the retry count */ + retries--; + } + + /* assert if the command timed out */ + if (retries == 0U) { + ERROR("ARI request timed out: req %d on CPU %d\n", + req, plat_my_core_pos()); + assert(retries != 0U); + } return 0; } diff --git a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c index 9790b817..a7f41c10 100644 --- a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c +++ b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c @@ -188,8 +188,11 @@ plat_local_state_t tegra_soc_get_target_pwr_state(unsigned int lvl, int core_pos = read_mpidr() & MPIDR_CPU_MASK; mce_cstate_info_t cstate_info = { 0 }; - /* get the current core's power state */ - target = *(states + core_pos); + /* get the power state at this level */ + if (lvl == MPIDR_AFFLVL1) + target = *(states + core_pos); + if (lvl == MPIDR_AFFLVL2) + target = *(states + cpu); /* CPU suspend */ if (lvl == MPIDR_AFFLVL1 && target == PSTATE_ID_CORE_POWERDN) { @@ -242,7 +245,8 @@ plat_local_state_t tegra_soc_get_target_pwr_state(unsigned int lvl, } /* System Suspend */ - if ((lvl == MPIDR_AFFLVL2) || (target == PSTATE_ID_SOC_POWERDN)) + if (((lvl == MPIDR_AFFLVL2) || (lvl == MPIDR_AFFLVL1)) && + (target == PSTATE_ID_SOC_POWERDN)) return PSTATE_ID_SOC_POWERDN; /* default state */ diff --git a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c index 05028a1f..91a13e8c 100644 --- a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c +++ b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c @@ -100,6 +100,39 @@ int32_t tegra_soc_validate_power_state(unsigned int power_state, return PSCI_E_SUCCESS; } +/******************************************************************************* + * Platform handler to calculate the proper target power level at the + * specified affinity level + ******************************************************************************/ +plat_local_state_t tegra_soc_get_target_pwr_state(unsigned int lvl, + const plat_local_state_t *states, + unsigned int ncpu) +{ + plat_local_state_t target = *states; + int cpu = plat_my_core_pos(); + int core_pos = read_mpidr() & MPIDR_CPU_MASK; + + /* get the power state at this level */ + if (lvl == MPIDR_AFFLVL1) + target = *(states + core_pos); + if (lvl == MPIDR_AFFLVL2) + target = *(states + cpu); + + /* Cluster idle/power-down */ + if ((lvl == MPIDR_AFFLVL1) && ((target == PSTATE_ID_CLUSTER_IDLE) || + (target == PSTATE_ID_CLUSTER_POWERDN))) { + return target; + } + + /* System Suspend */ + if (((lvl == MPIDR_AFFLVL2) || (lvl == MPIDR_AFFLVL1)) && + (target == PSTATE_ID_SOC_POWERDN)) + return PSTATE_ID_SOC_POWERDN; + + /* default state */ + return PSCI_LOCAL_STATE_RUN; +} + int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) { u_register_t mpidr = read_mpidr(); @@ -121,14 +154,14 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) } else if (stateid_afflvl1 == PSTATE_ID_CLUSTER_IDLE) { - assert(stateid_afflvl0 == PLAT_MAX_OFF_STATE); + assert(stateid_afflvl0 == PSTATE_ID_CLUSTER_IDLE); /* Prepare for cluster idle */ tegra_fc_cluster_idle(mpidr); } else if (stateid_afflvl1 == PSTATE_ID_CLUSTER_POWERDN) { - assert(stateid_afflvl0 == PLAT_MAX_OFF_STATE); + assert(stateid_afflvl0 == PSTATE_ID_CLUSTER_POWERDN); /* Prepare for cluster powerdn */ tegra_fc_cluster_powerdn(mpidr); diff --git a/plat/nvidia/tegra/soc/t210/platform_t210.mk b/plat/nvidia/tegra/soc/t210/platform_t210.mk index 89468692..cd26e6e8 100644 --- a/plat/nvidia/tegra/soc/t210/platform_t210.mk +++ b/plat/nvidia/tegra/soc/t210/platform_t210.mk @@ -40,7 +40,7 @@ $(eval $(call add_define,PLATFORM_CLUSTER_COUNT)) PLATFORM_MAX_CPUS_PER_CLUSTER := 4 $(eval $(call add_define,PLATFORM_MAX_CPUS_PER_CLUSTER)) -MAX_XLAT_TABLES := 3 +MAX_XLAT_TABLES := 4 $(eval $(call add_define,MAX_XLAT_TABLES)) MAX_MMAP_REGIONS := 8 diff --git a/services/spd/tspd/tspd_main.c b/services/spd/tspd/tspd_main.c index f5384223..02e1db74 100644 --- a/services/spd/tspd/tspd_main.c +++ b/services/spd/tspd/tspd_main.c @@ -632,7 +632,7 @@ uint64_t tspd_smc_handler(uint32_t smc_fid, cm_el1_sysregs_context_restore(NON_SECURE); cm_set_next_eret_context(NON_SECURE); - SMC_RET0(handle); + SMC_RET1(handle, SMC_OK); /* * Request from non secure world to resume the preempted |