Merge pull request #1340 from Andre-ARM/sec-irqs-fixes
Fix support for systems without secure interrupts
diff --git a/.checkpatch.conf b/.checkpatch.conf
index e92b96f..63bdf7b 100644
--- a/.checkpatch.conf
+++ b/.checkpatch.conf
@@ -36,6 +36,10 @@
# This is not Linux so don't expect a Linux tree!
--no-tree
+# The Linux kernel expects the SPDX license tag in the first line of each file.
+# We don't follow this in the Trusted Firmware.
+--ignore SPDX_LICENSE_TAG
+
# This clarifes the lines indications in the report.
#
# E.g.:
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..0e7a5c3
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,62 @@
+#
+# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# ARM Trusted Firmware Coding style spec for editors.
+
+# References:
+# [EC] http://editorconfig.org/
+# [CONT] contributing.rst
+# [LCS] Linux Coding Style
+# (https://www.kernel.org/doc/html/v4.10/process/coding-style.html)
+
+
+root = true
+
+# set default to match [LCS] .c/.h settings.
+# This will also apply to .S, .mk, .sh, Makefile, .dts, etc.
+[*]
+# Not specified, but fits current ARM-TF sources.
+charset = utf-8
+
+# Not specified, but implicit for "LINUX coding style".
+end_of_line = lf
+
+# [LCS] Chapter 1: Indentation
+# "and thus indentations are also 8 characters"
+indent_size = 8
+
+# [LCS] Chapter 1: Indentation
+# "Outside of comments,...spaces are never used for indentation"
+indent_style = tab
+
+# Not specified by [LCS], but sensible
+insert_final_newline = true
+
+# [LCS] Chapter 2: Breaking long lines and strings
+# "The limit on the length of lines is 80 columns"
+# This is a "soft" requirement for Arm-TF, and should not be the sole
+# reason for changes.
+max_line_length = 80
+
+# [LCS] Chapter 1: Indentation
+# "Tabs are 8 characters"
+tab_width = 8
+
+# [LCS] Chapter 1: Indentation
+# "Get a decent editor and don't leave whitespace at the end of lines."
+# [LCS] Chapter 3.1: Spaces
+# "Do not leave trailing whitespace at the ends of lines."
+trim_trailing_whitespace = true
+
+
+# Adjustment for existing .rst files with different format
+[*.{rst,md}]
+indent_size = 4
+indent_style = space
+max_line_length = 180
+# 180 only selected to prevent changes to existing text.
+tab_width = 4
+
diff --git a/Makefile b/Makefile
index ca91e69..b7116a7 100644
--- a/Makefile
+++ b/Makefile
@@ -90,7 +90,6 @@
LOG_LEVEL := 40
else
BUILD_TYPE := release
- $(eval $(call add_define,NDEBUG))
# Use LOG_LEVEL_NOTICE by default for release builds
LOG_LEVEL := 20
endif
@@ -373,6 +372,35 @@
endif
endif
+#For now, BL2_IN_XIP_MEM is only supported when BL2_AT_EL3 is 1.
+ifeq ($(BL2_AT_EL3)-$(BL2_IN_XIP_MEM),0-1)
+$(error "BL2_IN_XIP_MEM is only supported when BL2_AT_EL3 is enabled")
+endif
+
+# SMC Calling Convention checks
+ifneq (${SMCCC_MAJOR_VERSION},1)
+ ifneq (${SPD},none)
+ $(error "SMC Calling Convention 1.X must be used with SPDs")
+ endif
+ ifeq (${ARCH},aarch32)
+ $(error "Only SMCCC 1.X is supported in AArch32 mode.")
+ endif
+endif
+
+# For RAS_EXTENSION, require that EAs are handled in EL3 first
+ifeq ($(RAS_EXTENSION),1)
+ ifneq ($(HANDLE_EA_EL3_FIRST),1)
+ $(error For RAS_EXTENSION, HANDLE_EA_EL3_FIRST must also be 1)
+ endif
+endif
+
+# When FAULT_INJECTION_SUPPORT is used, require that RAS_EXTENSION is enabled
+ifeq ($(FAULT_INJECTION_SUPPORT),1)
+ ifneq ($(RAS_EXTENSION),1)
+ $(error For FAULT_INJECTION_SUPPORT, RAS_EXTENSION must also be 1)
+ endif
+endif
+
################################################################################
# Process platform overrideable behaviour
################################################################################
@@ -497,10 +525,13 @@
$(eval $(call assert_boolean,ENABLE_PSCI_STAT))
$(eval $(call assert_boolean,ENABLE_RUNTIME_INSTRUMENTATION))
$(eval $(call assert_boolean,ENABLE_SPE_FOR_LOWER_ELS))
+$(eval $(call assert_boolean,ENABLE_SPM))
$(eval $(call assert_boolean,ENABLE_SVE_FOR_NS))
$(eval $(call assert_boolean,ERROR_DEPRECATED))
+$(eval $(call assert_boolean,FAULT_INJECTION_SUPPORT))
$(eval $(call assert_boolean,GENERATE_COT))
$(eval $(call assert_boolean,GICV2_G0_FOR_EL3))
+$(eval $(call assert_boolean,HANDLE_EA_EL3_FIRST))
$(eval $(call assert_boolean,HW_ASSISTED_COHERENCY))
$(eval $(call assert_boolean,LOAD_IMAGE_V2))
$(eval $(call assert_boolean,MULTI_CONSOLE_API))
@@ -508,6 +539,7 @@
$(eval $(call assert_boolean,PL011_GENERIC_UART))
$(eval $(call assert_boolean,PROGRAMMABLE_RESET_ADDRESS))
$(eval $(call assert_boolean,PSCI_EXTENDED_STATE_ID))
+$(eval $(call assert_boolean,RAS_EXTENSION))
$(eval $(call assert_boolean,RESET_TO_BL31))
$(eval $(call assert_boolean,SAVE_KEYS))
$(eval $(call assert_boolean,SEPARATE_CODE_AND_RODATA))
@@ -517,9 +549,11 @@
$(eval $(call assert_boolean,USE_TBBR_DEFS))
$(eval $(call assert_boolean,WARMBOOT_ENABLE_DCACHE_EARLY))
$(eval $(call assert_boolean,BL2_AT_EL3))
+$(eval $(call assert_boolean,BL2_IN_XIP_MEM))
$(eval $(call assert_numeric,ARM_ARCH_MAJOR))
$(eval $(call assert_numeric,ARM_ARCH_MINOR))
+$(eval $(call assert_numeric,SMCCC_MAJOR_VERSION))
################################################################################
# Add definitions to the cpp preprocessor based on the current build options.
@@ -541,9 +575,12 @@
$(eval $(call add_define,ENABLE_PSCI_STAT))
$(eval $(call add_define,ENABLE_RUNTIME_INSTRUMENTATION))
$(eval $(call add_define,ENABLE_SPE_FOR_LOWER_ELS))
+$(eval $(call add_define,ENABLE_SPM))
$(eval $(call add_define,ENABLE_SVE_FOR_NS))
$(eval $(call add_define,ERROR_DEPRECATED))
+$(eval $(call add_define,FAULT_INJECTION_SUPPORT))
$(eval $(call add_define,GICV2_G0_FOR_EL3))
+$(eval $(call add_define,HANDLE_EA_EL3_FIRST))
$(eval $(call add_define,HW_ASSISTED_COHERENCY))
$(eval $(call add_define,LOAD_IMAGE_V2))
$(eval $(call add_define,LOG_LEVEL))
@@ -553,9 +590,10 @@
$(eval $(call add_define,PLAT_${PLAT}))
$(eval $(call add_define,PROGRAMMABLE_RESET_ADDRESS))
$(eval $(call add_define,PSCI_EXTENDED_STATE_ID))
+$(eval $(call add_define,RAS_EXTENSION))
$(eval $(call add_define,RESET_TO_BL31))
$(eval $(call add_define,SEPARATE_CODE_AND_RODATA))
-$(eval $(call add_define,ENABLE_SPM))
+$(eval $(call add_define,SMCCC_MAJOR_VERSION))
$(eval $(call add_define,SPD_${SPD}))
$(eval $(call add_define,SPIN_ON_BL1_EXIT))
$(eval $(call add_define,TRUSTED_BOARD_BOOT))
@@ -563,6 +601,7 @@
$(eval $(call add_define,USE_TBBR_DEFS))
$(eval $(call add_define,WARMBOOT_ENABLE_DCACHE_EARLY))
$(eval $(call add_define,BL2_AT_EL3))
+$(eval $(call add_define,BL2_IN_XIP_MEM))
# Define the EL3_PAYLOAD_BASE flag only if it is provided.
ifdef EL3_PAYLOAD_BASE
diff --git a/acknowledgements.rst b/acknowledgements.rst
index 59f569e..9b81b6c 100644
--- a/acknowledgements.rst
+++ b/acknowledgements.rst
@@ -12,5 +12,7 @@
Xilinx, Inc.
+NXP Semiconductors
+
Individuals
-----------
diff --git a/bl1/bl1_fwu.c b/bl1/bl1_fwu.c
index 49e4e8e..25be577 100644
--- a/bl1/bl1_fwu.c
+++ b/bl1/bl1_fwu.c
@@ -24,12 +24,12 @@
* Function declarations.
*/
static int bl1_fwu_image_copy(unsigned int image_id,
- uintptr_t image_addr,
+ uintptr_t image_src,
unsigned int block_size,
unsigned int image_size,
unsigned int flags);
static int bl1_fwu_image_auth(unsigned int image_id,
- uintptr_t image_addr,
+ uintptr_t image_src,
unsigned int image_size,
unsigned int flags);
static int bl1_fwu_image_execute(unsigned int image_id,
@@ -50,7 +50,7 @@
static unsigned int sec_exec_image_id = INVALID_IMAGE_ID;
/* Authentication status of each image. */
-extern unsigned int auth_img_flags[];
+extern unsigned int auth_img_flags[MAX_NUMBER_IDS];
/*******************************************************************************
* Top level handler for servicing FWU SMCs.
diff --git a/bl1/tbbr/tbbr_img_desc.c b/bl1/tbbr/tbbr_img_desc.c
index f2ed1a1..44f58d3 100644
--- a/bl1/tbbr/tbbr_img_desc.c
+++ b/bl1/tbbr/tbbr_img_desc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,6 +7,7 @@
#include <bl1.h>
#include <bl_common.h>
#include <platform_def.h>
+#include <tbbr/tbbr_img_desc.h>
image_desc_t bl1_tbbr_image_descs[] = {
{
diff --git a/bl2/bl2_el3.ld.S b/bl2/bl2_el3.ld.S
index 3728643..0f91edc 100644
--- a/bl2/bl2_el3.ld.S
+++ b/bl2/bl2_el3.ld.S
@@ -12,15 +12,26 @@
ENTRY(bl2_entrypoint)
MEMORY {
+#if BL2_IN_XIP_MEM
+ ROM (rx): ORIGIN = BL2_RO_BASE, LENGTH = BL2_RO_LIMIT - BL2_RO_BASE
+ RAM (rwx): ORIGIN = BL2_RW_BASE, LENGTH = BL2_RW_LIMIT - BL2_RW_BASE
+#else
RAM (rwx): ORIGIN = BL2_BASE, LENGTH = BL2_LIMIT - BL2_BASE
+#endif
}
SECTIONS
{
+#if BL2_IN_XIP_MEM
+ . = BL2_RO_BASE;
+ ASSERT(. == ALIGN(PAGE_SIZE),
+ "BL2_RO_BASE address is not aligned on a page boundary.")
+#else
. = BL2_BASE;
ASSERT(. == ALIGN(PAGE_SIZE),
"BL2_BASE address is not aligned on a page boundary.")
+#endif
#if SEPARATE_CODE_AND_RODATA
.text . : {
@@ -33,7 +44,11 @@
*(.vectors)
. = NEXT(PAGE_SIZE);
__TEXT_END__ = .;
+#if BL2_IN_XIP_MEM
+ } >ROM
+#else
} >RAM
+#endif
.rodata . : {
__RODATA_START__ = .;
@@ -56,7 +71,11 @@
. = NEXT(PAGE_SIZE);
__RODATA_END__ = .;
+#if BL2_IN_XIP_MEM
+ } >ROM
+#else
} >RAM
+#endif
ASSERT(__TEXT_RESIDENT_END__ - __TEXT_RESIDENT_START__ <= PAGE_SIZE,
"Resident part of BL2 has exceeded its limit.")
@@ -95,12 +114,22 @@
. = NEXT(PAGE_SIZE);
__RO_END__ = .;
+#if BL2_IN_XIP_MEM
+ } >ROM
+#else
} >RAM
#endif
+#endif
ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__,
"cpu_ops not defined for this platform.")
+#if BL2_IN_XIP_MEM
+ . = BL2_RW_BASE;
+ ASSERT(BL2_RW_BASE == ALIGN(PAGE_SIZE),
+ "BL2_RW_BASE address is not aligned on a page boundary.")
+#endif
+
/*
* Define a linker symbol to mark start of the RW memory area for this
* image.
@@ -113,10 +142,14 @@
* section can be placed independently of the main .data section.
*/
.data . : {
- __DATA_START__ = .;
+ __DATA_RAM_START__ = .;
*(.data*)
- __DATA_END__ = .;
+ __DATA_RAM_END__ = .;
+#if BL2_IN_XIP_MEM
+ } >RAM AT>ROM
+#else
} >RAM
+#endif
stacks (NOLOAD) : {
__STACKS_START__ = .;
@@ -174,12 +207,32 @@
__RW_END__ = .;
__BL2_END__ = .;
+#if BL2_IN_XIP_MEM
+ __BL2_RAM_START__ = ADDR(.data);
+ __BL2_RAM_END__ = .;
+
+ __DATA_ROM_START__ = LOADADDR(.data);
+ __DATA_SIZE__ = SIZEOF(.data);
+
+ /*
+ * The .data section is the last PROGBITS section so its end marks the end
+ * of BL2's RO content in XIP memory..
+ */
+ __BL2_ROM_END__ = __DATA_ROM_START__ + __DATA_SIZE__;
+ ASSERT(__BL2_ROM_END__ <= BL2_RO_LIMIT,
+ "BL2's RO content has exceeded its limit.")
+#endif
__BSS_SIZE__ = SIZEOF(.bss);
+
#if USE_COHERENT_MEM
__COHERENT_RAM_UNALIGNED_SIZE__ =
__COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__;
#endif
+#if BL2_IN_XIP_MEM
+ ASSERT(. <= BL2_RW_LIMIT, "BL2's RW content has exceeded its limit.")
+#else
ASSERT(. <= BL2_LIMIT, "BL2 image has exceeded its limit.")
+#endif
}
diff --git a/bl2/bl2_image_load.c b/bl2/bl2_image_load.c
index d5d28a5..d22e9ce 100644
--- a/bl2/bl2_image_load.c
+++ b/bl2/bl2_image_load.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -182,7 +182,7 @@
* This function loads SCP_BL2/BL3x images and returns the ep_info for
* the next executable image.
******************************************************************************/
-entry_point_info_t *bl2_load_images(void)
+struct entry_point_info *bl2_load_images(void)
{
bl31_params_t *bl2_to_bl31_params;
entry_point_info_t *bl31_ep_info;
diff --git a/bl2/bl2_image_load_v2.c b/bl2/bl2_image_load_v2.c
index d95c6b2..0f40785 100644
--- a/bl2/bl2_image_load_v2.c
+++ b/bl2/bl2_image_load_v2.c
@@ -21,7 +21,7 @@
* This function loads SCP_BL2/BL3x images and returns the ep_info for
* the next executable image.
******************************************************************************/
-entry_point_info_t *bl2_load_images(void)
+struct entry_point_info *bl2_load_images(void)
{
bl_params_t *bl2_to_next_bl_params;
bl_load_info_t *bl2_load_info;
diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c
index 41d1745..101eb33 100644
--- a/bl2/bl2_main.c
+++ b/bl2/bl2_main.c
@@ -46,6 +46,7 @@
/* Load the subsequent bootloader images. */
next_bl_ep_info = bl2_load_images();
+#if !BL2_AT_EL3
#ifdef AARCH32
/*
* For AArch32 state BL1 and BL2 share the MMU setup.
@@ -55,8 +56,6 @@
disable_mmu_icache_secure();
#endif /* AARCH32 */
-
-#if !BL2_AT_EL3
console_flush();
/*
diff --git a/bl2/bl2_private.h b/bl2/bl2_private.h
index 50295d6..f93a179 100644
--- a/bl2/bl2_private.h
+++ b/bl2/bl2_private.h
@@ -7,6 +7,20 @@
#ifndef __BL2_PRIVATE_H__
#define __BL2_PRIVATE_H__
+#if BL2_IN_XIP_MEM
+/*******************************************************************************
+ * Declarations of linker defined symbols which will tell us where BL2 lives
+ * in Trusted ROM and RAM
+ ******************************************************************************/
+extern uintptr_t __BL2_ROM_END__;
+#define BL2_ROM_END (uintptr_t)(&__BL2_ROM_END__)
+
+extern uintptr_t __BL2_RAM_START__;
+extern uintptr_t __BL2_RAM_END__;
+#define BL2_RAM_BASE (uintptr_t)(&__BL2_RAM_START__)
+#define BL2_RAM_LIMIT (uintptr_t)(&__BL2_RAM_END__)
+#endif
+
/******************************************
* Forward declarations
*****************************************/
diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S
index 60be932..346cd3b 100644
--- a/bl31/aarch64/runtime_exceptions.S
+++ b/bl31/aarch64/runtime_exceptions.S
@@ -8,9 +8,11 @@
#include <asm_macros.S>
#include <context.h>
#include <cpu_data.h>
+#include <ea_handle.h>
#include <interrupt_mgmt.h>
#include <platform_def.h>
#include <runtime_svc.h>
+#include <smccc.h>
.globl runtime_exceptions
@@ -34,17 +36,77 @@
.globl fiq_aarch32
.globl serror_aarch32
+ /*
+ * Macro that prepares entry to EL3 upon taking an exception.
+ *
+ * With RAS_EXTENSION, this macro synchronizes pending errors with an ESB
+ * instruction. When an error is thus synchronized, the handling is
+ * delegated to platform EA handler.
+ *
+ * Without RAS_EXTENSION, this macro just saves x30, and unmasks
+ * Asynchronous External Aborts.
+ */
+ .macro check_and_unmask_ea
+#if RAS_EXTENSION
+ /* Synchronize pending External Aborts */
+ esb
+
+ /* Unmask the SError interrupt */
+ msr daifclr, #DAIF_ABT_BIT
+
+ /*
+ * Explicitly save x30 so as to free up a register and to enable
+ * branching
+ */
+ str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+
+ /* Check for SErrors synchronized by the ESB instruction */
+ mrs x30, DISR_EL1
+ tbz x30, #DISR_A_BIT, 1f
+
+ /* Save GP registers and restore them afterwards */
+ bl save_gp_registers
+ mov x0, #ERROR_EA_ESB
+ mrs x1, DISR_EL1
+ bl delegate_ea
+ bl restore_gp_registers
+
+1:
+#else
+ /* Unmask the SError interrupt */
+ msr daifclr, #DAIF_ABT_BIT
+
+ str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+#endif
+ .endm
+
+ /*
+ * Handle External Abort by delegating to the platform's EA handler.
+ * Once the platform handler returns, the macro exits EL3 and returns to
+ * where the abort was taken from.
+ *
+ * This macro assumes that x30 is available for use.
+ *
+ * 'abort_type' is a constant passed to the platform handler, indicating
+ * the cause of the External Abort.
+ */
+ .macro handle_ea abort_type
+ /* Save GP registers */
+ bl save_gp_registers
+
+ /* Setup exception class and syndrome arguments for platform handler */
+ mov x0, \abort_type
+ mrs x1, esr_el3
+ adr x30, el3_exit
+ b delegate_ea
+ .endm
+
/* ---------------------------------------------------------------------
* This macro handles Synchronous exceptions.
* Only SMC exceptions are supported.
* ---------------------------------------------------------------------
*/
.macro handle_sync_exception
- /* Enable the SError interrupt */
- msr daifclr, #DAIF_ABT_BIT
-
- str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
-
#if ENABLE_RUNTIME_INSTRUMENTATION
/*
* Read the timestamp value and store it in per-cpu data. The value
@@ -68,6 +130,20 @@
cmp x30, #EC_AARCH64_SMC
b.eq smc_handler64
+ /* Check for I/D aborts from lower EL */
+ cmp x30, #EC_IABORT_LOWER_EL
+ b.eq 1f
+
+ cmp x30, #EC_DABORT_LOWER_EL
+ b.ne 2f
+
+1:
+ /* Test for EA bit in the instruction syndrome */
+ mrs x30, esr_el3
+ tbz x30, #ESR_ISS_EABORT_EA_BIT, 2f
+ handle_ea #ERROR_EA_SYNC
+
+2:
/* Other kinds of synchronous exceptions are not handled */
ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
b report_unhandled_exception
@@ -80,12 +156,7 @@
* ---------------------------------------------------------------------
*/
.macro handle_interrupt_exception label
- /* Enable the SError interrupt */
- msr daifclr, #DAIF_ABT_BIT
-
- str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
bl save_gp_registers
-
/* Save the EL3 system registers needed to return from this exception */
mrs x0, spsr_el3
mrs x1, elr_el3
@@ -153,25 +224,6 @@
.endm
- .macro save_x4_to_x29_sp_el0
- stp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4]
- stp x6, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X6]
- stp x8, x9, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X8]
- stp x10, x11, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X10]
- stp x12, x13, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X12]
- stp x14, x15, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X14]
- stp x16, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X16]
- stp x18, x19, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X18]
- stp x20, x21, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X20]
- stp x22, x23, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X22]
- stp x24, x25, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X24]
- stp x26, x27, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X26]
- stp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28]
- mrs x18, sp_el0
- str x18, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_SP_EL0]
- .endm
-
-
vector_base runtime_exceptions
/* ---------------------------------------------------------------------
@@ -238,23 +290,29 @@
* to a valid cpu context where the general purpose and system register
* state can be saved.
*/
+ check_and_unmask_ea
handle_sync_exception
check_vector_size sync_exception_aarch64
vector_entry irq_aarch64
+ check_and_unmask_ea
handle_interrupt_exception irq_aarch64
check_vector_size irq_aarch64
vector_entry fiq_aarch64
+ check_and_unmask_ea
handle_interrupt_exception fiq_aarch64
check_vector_size fiq_aarch64
vector_entry serror_aarch64
+ msr daifclr, #DAIF_ABT_BIT
+
/*
- * SError exceptions from lower ELs are not currently supported.
- * Report their occurrence.
+ * Explicitly save x30 so as to free up a register and to enable
+ * branching
*/
- b report_unhandled_exception
+ str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+ handle_ea #ERROR_EA_ASYNC
check_vector_size serror_aarch64
/* ---------------------------------------------------------------------
@@ -268,25 +326,62 @@
* to a valid cpu context where the general purpose and system register
* state can be saved.
*/
+ check_and_unmask_ea
handle_sync_exception
check_vector_size sync_exception_aarch32
vector_entry irq_aarch32
+ check_and_unmask_ea
handle_interrupt_exception irq_aarch32
check_vector_size irq_aarch32
vector_entry fiq_aarch32
+ check_and_unmask_ea
handle_interrupt_exception fiq_aarch32
check_vector_size fiq_aarch32
vector_entry serror_aarch32
+ msr daifclr, #DAIF_ABT_BIT
+
/*
- * SError exceptions from lower ELs are not currently supported.
- * Report their occurrence.
+ * Explicitly save x30 so as to free up a register and to enable
+ * branching
*/
- b report_unhandled_exception
+ str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+ handle_ea #ERROR_EA_ASYNC
check_vector_size serror_aarch32
+
+ /* ---------------------------------------------------------------------
+ * This macro takes an argument in x16 that is the index in the
+ * 'rt_svc_descs_indices' array, checks that the value in the array is
+ * valid, and loads in x15 the pointer to the handler of that service.
+ * ---------------------------------------------------------------------
+ */
+ .macro load_rt_svc_desc_pointer
+ /* Load descriptor index from array of indices */
+ adr x14, rt_svc_descs_indices
+ ldrb w15, [x14, x16]
+
+#if SMCCC_MAJOR_VERSION == 1
+ /* Any index greater than 127 is invalid. Check bit 7. */
+ tbnz w15, 7, smc_unknown
+#elif SMCCC_MAJOR_VERSION == 2
+ /* Verify that the top 3 bits of the loaded index are 0 (w15 <= 31) */
+ cmp w15, #31
+ b.hi smc_unknown
+#endif /* SMCCC_MAJOR_VERSION */
+
+ /*
+ * Get the descriptor using the index
+ * x11 = (base + off), w15 = index
+ *
+ * handler = (base + off) + (index << log2(size))
+ */
+ adr x11, (__RT_SVC_DESCS_START__ + RT_SVC_DESC_HANDLE)
+ lsl w10, w15, #RT_SVC_SIZE_LOG2
+ ldr x15, [x11, w10, uxtw]
+ .endm
/* ---------------------------------------------------------------------
* The following code handles secure monitor calls.
@@ -311,48 +406,77 @@
* now). x6 will point to the context structure (SP_EL3) and x7 will
* contain flags we need to pass to the handler.
*
- * Save x4-x29 and sp_el0. Refer to SMCCC v1.1.
+ * Save x4-x29 and sp_el0.
*/
- save_x4_to_x29_sp_el0
+ stp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4]
+ stp x6, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X6]
+ stp x8, x9, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X8]
+ stp x10, x11, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X10]
+ stp x12, x13, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X12]
+ stp x14, x15, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X14]
+ stp x16, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X16]
+ stp x18, x19, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X18]
+ stp x20, x21, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X20]
+ stp x22, x23, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X22]
+ stp x24, x25, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X24]
+ stp x26, x27, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X26]
+ stp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28]
+ mrs x18, sp_el0
+ str x18, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_SP_EL0]
mov x5, xzr
mov x6, sp
+#if SMCCC_MAJOR_VERSION == 1
+
/* Get the unique owning entity number */
ubfx x16, x0, #FUNCID_OEN_SHIFT, #FUNCID_OEN_WIDTH
ubfx x15, x0, #FUNCID_TYPE_SHIFT, #FUNCID_TYPE_WIDTH
orr x16, x16, x15, lsl #FUNCID_OEN_WIDTH
- adr x11, (__RT_SVC_DESCS_START__ + RT_SVC_DESC_HANDLE)
+ load_rt_svc_desc_pointer
- /* Load descriptor index from array of indices */
- adr x14, rt_svc_descs_indices
- ldrb w15, [x14, x16]
+#elif SMCCC_MAJOR_VERSION == 2
+
+ /* Bit 31 must be set */
+ tbz x0, #FUNCID_TYPE_SHIFT, smc_unknown
/*
- * Restore the saved C runtime stack value which will become the new
- * SP_EL0 i.e. EL3 runtime stack. It was saved in the 'cpu_context'
- * structure prior to the last ERET from EL3.
+ * Check MSB of namespace to decide between compatibility/vendor and
+ * SPCI/SPRT
*/
- ldr x12, [x6, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]
+ tbz x0, #(FUNCID_NAMESPACE_SHIFT + 1), compat_or_vendor
+
+ /* Namespaces SPRT and SPCI currently unimplemented */
+ b smc_unknown
+
+compat_or_vendor:
+
+ /* Namespace is b'00 (compatibility) or b'01 (vendor) */
/*
- * Any index greater than 127 is invalid. Check bit 7 for
- * a valid index
+ * Add the LSB of the namespace (bit [28]) to the OEN [27:24] to create
+ * a 5-bit index into the rt_svc_descs_indices array.
+ *
+ * The low 16 entries of the rt_svc_descs_indices array correspond to
+ * OENs of the compatibility namespace and the top 16 entries of the
+ * array are assigned to the vendor namespace descriptor.
*/
- tbnz w15, 7, smc_unknown
+ ubfx x16, x0, #FUNCID_OEN_SHIFT, #(FUNCID_OEN_WIDTH + 1)
- /* Switch to SP_EL0 */
- msr spsel, #0
+ load_rt_svc_desc_pointer
+
+#endif /* SMCCC_MAJOR_VERSION */
/*
- * Get the descriptor using the index
- * x11 = (base + off), x15 = index
- *
- * handler = (base + off) + (index << log2(size))
+ * Restore the saved C runtime stack value which will become the new
+ * SP_EL0 i.e. EL3 runtime stack. It was saved in the 'cpu_context'
+ * structure prior to the last ERET from EL3.
*/
- lsl w10, w15, #RT_SVC_SIZE_LOG2
- ldr x15, [x11, w10, uxtw]
+ ldr x12, [x6, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]
+
+ /* Switch to SP_EL0 */
+ msr spsel, #0
/*
* Save the SPSR_EL3, ELR_EL3, & SCR_EL3 in case there is a world
@@ -384,14 +508,12 @@
smc_unknown:
/*
- * Here we restore x4-x18 regardless of where we came from. AArch32
- * callers will find the registers contents unchanged, but AArch64
- * callers will find the registers modified (with stale earlier NS
- * content). Either way, we aren't leaking any secure information
- * through them.
+ * Unknown SMC call. Populate return value with SMC_UNK, restore
+ * GP registers, and return to caller.
*/
mov x0, #SMC_UNK
- b restore_gp_registers_callee_eret
+ str x0, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
+ b restore_gp_registers_eret
smc_prohibited:
ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
@@ -403,3 +525,62 @@
msr spsel, #1
no_ret report_unhandled_exception
endfunc smc_handler
+
+/*
+ * Delegate External Abort handling to platform's EA handler. This function
+ * assumes that all GP registers have been saved by the caller.
+ *
+ * x0: EA reason
+ * x1: EA syndrome
+ */
+func delegate_ea
+ /* Save EL3 state */
+ mrs x2, spsr_el3
+ mrs x3, elr_el3
+ stp x2, x3, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
+
+ /*
+ * Save ESR as handling might involve lower ELs, and returning back to
+ * EL3 from there would trample the original ESR.
+ */
+ mrs x4, scr_el3
+ mrs x5, esr_el3
+ stp x4, x5, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
+
+ /*
+ * Setup rest of arguments, and call platform External Abort handler.
+ *
+ * x0: EA reason (already in place)
+ * x1: Exception syndrome (already in place).
+ * x2: Cookie (unused for now).
+ * x3: Context pointer.
+ * x4: Flags (security state from SCR for now).
+ */
+ mov x2, xzr
+ mov x3, sp
+ ubfx x4, x4, #0, #1
+
+ /* Switch to runtime stack */
+ ldr x5, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]
+ msr spsel, #0
+ mov sp, x5
+
+ mov x29, x30
+ bl plat_ea_handler
+ mov x30, x29
+
+ /* Make SP point to context */
+ msr spsel, #1
+
+ /* Restore EL3 state */
+ ldp x1, x2, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
+ msr spsr_el3, x1
+ msr elr_el3, x2
+
+ /* Restore ESR_EL3 and SCR_EL3 */
+ ldp x3, x4, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
+ msr scr_el3, x3
+ msr esr_el3, x4
+
+ ret
+endfunc delegate_ea
diff --git a/bl32/tsp/tsp_interrupt.c b/bl32/tsp/tsp_interrupt.c
index cbfc152..f501338 100644
--- a/bl32/tsp/tsp_interrupt.c
+++ b/bl32/tsp/tsp_interrupt.c
@@ -33,7 +33,7 @@
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
spin_lock(&console_lock);
- VERBOSE("TSP: cpu 0x%lx sync s-el1 interrupt request from 0x%lx\n",
+ VERBOSE("TSP: cpu 0x%lx sync s-el1 interrupt request from 0x%llx\n",
read_mpidr(), elr_el3);
VERBOSE("TSP: cpu 0x%lx: %d sync s-el1 interrupt requests,"
" %d sync s-el1 interrupt returns\n",
diff --git a/bl32/tsp/tsp_main.c b/bl32/tsp/tsp_main.c
index 0de0ca8..e41b51e 100644
--- a/bl32/tsp/tsp_main.c
+++ b/bl32/tsp/tsp_main.c
@@ -247,7 +247,7 @@
#if LOG_LEVEL >= LOG_LEVEL_INFO
spin_lock(&console_lock);
- INFO("TSP: cpu 0x%lx resumed. maximum off power level %ld\n",
+ INFO("TSP: cpu 0x%lx resumed. maximum off power level %lld\n",
read_mpidr(), max_off_pwrlvl);
INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n",
read_mpidr(),
@@ -347,7 +347,7 @@
tsp_stats[linear_id].smc_count++;
tsp_stats[linear_id].eret_count++;
- INFO("TSP: cpu 0x%lx received %s smc 0x%lx\n", read_mpidr(),
+ INFO("TSP: cpu 0x%lx received %s smc 0x%llx\n", read_mpidr(),
((func >> 31) & 1) == 1 ? "fast" : "yielding",
func);
INFO("TSP: cpu 0x%lx: %d smcs, %d erets\n", read_mpidr(),
diff --git a/bl32/tsp/tsp_private.h b/bl32/tsp/tsp_private.h
index b11570c..dd65a5f 100644
--- a/bl32/tsp/tsp_private.h
+++ b/bl32/tsp/tsp_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -62,7 +62,7 @@
void tsp_get_magic(uint64_t args[4]);
-tsp_args_t *tsp_cpu_resume_main(uint64_t arg0,
+tsp_args_t *tsp_cpu_resume_main(uint64_t max_off_pwrlvl,
uint64_t arg1,
uint64_t arg2,
uint64_t arg3,
@@ -106,7 +106,47 @@
/* Vector table of jumps */
extern tsp_vectors_t tsp_vector_table;
+/* functions */
+int32_t tsp_common_int_handler(void);
+int32_t tsp_handle_preemption(void);
+
+tsp_args_t *tsp_abort_smc_handler(uint64_t func,
+ uint64_t arg1,
+ uint64_t arg2,
+ uint64_t arg3,
+ uint64_t arg4,
+ uint64_t arg5,
+ uint64_t arg6,
+ uint64_t arg7);
+
+tsp_args_t *tsp_smc_handler(uint64_t func,
+ uint64_t arg1,
+ uint64_t arg2,
+ uint64_t arg3,
+ uint64_t arg4,
+ uint64_t arg5,
+ uint64_t arg6,
+ uint64_t arg7);
+
+tsp_args_t *tsp_system_reset_main(uint64_t arg0,
+ uint64_t arg1,
+ uint64_t arg2,
+ uint64_t arg3,
+ uint64_t arg4,
+ uint64_t arg5,
+ uint64_t arg6,
+ uint64_t arg7);
+
+tsp_args_t *tsp_system_off_main(uint64_t arg0,
+ uint64_t arg1,
+ uint64_t arg2,
+ uint64_t arg3,
+ uint64_t arg4,
+ uint64_t arg5,
+ uint64_t arg6,
+ uint64_t arg7);
+uint64_t tsp_main(void);
#endif /* __ASSEMBLY__ */
#endif /* __TSP_PRIVATE_H__ */
diff --git a/common/runtime_svc.c b/common/runtime_svc.c
index de80f30..f997c74 100644
--- a/common/runtime_svc.c
+++ b/common/runtime_svc.c
@@ -26,8 +26,10 @@
/ sizeof(rt_svc_desc_t))
/*******************************************************************************
- * Function to invoke the registered `handle` corresponding to the smc_fid.
+ * Function to invoke the registered `handle` corresponding to the smc_fid in
+ * AArch32 mode.
******************************************************************************/
+#if SMCCC_MAJOR_VERSION == 1
uintptr_t handle_runtime_svc(uint32_t smc_fid,
void *cookie,
void *handle,
@@ -53,6 +55,7 @@
return rt_svc_descs[index].handle(smc_fid, x1, x2, x3, x4, cookie,
handle, flags);
}
+#endif /* SMCCC_MAJOR_VERSION */
/*******************************************************************************
* Simple routine to sanity check a runtime service descriptor before using it
@@ -68,12 +71,17 @@
if (desc->end_oen >= OEN_LIMIT)
return -EINVAL;
- if (desc->call_type != SMC_TYPE_FAST &&
- desc->call_type != SMC_TYPE_YIELD)
+#if SMCCC_MAJOR_VERSION == 1
+ if ((desc->call_type != SMC_TYPE_FAST) &&
+ (desc->call_type != SMC_TYPE_YIELD))
return -EINVAL;
+#elif SMCCC_MAJOR_VERSION == 2
+ if (desc->is_vendor > 1U)
+ return -EINVAL;
+#endif /* SMCCC_MAJOR_VERSION */
/* A runtime service having no init or handle function doesn't make sense */
- if (desc->init == NULL && desc->handle == NULL)
+ if ((desc->init == NULL) && (desc->handle == NULL))
return -EINVAL;
return 0;
@@ -96,7 +104,7 @@
(RT_SVC_DECS_NUM < MAX_RT_SVCS));
/* If no runtime services are implemented then simply bail out */
- if (RT_SVC_DECS_NUM == 0)
+ if (RT_SVC_DECS_NUM == 0U)
return;
/* Initialise internal variables to invalid state */
@@ -140,11 +148,18 @@
* descriptor which will handle the SMCs for this owning
* entity range.
*/
- start_idx = get_unique_oen(rt_svc_descs[index].start_oen,
- service->call_type);
- assert(start_idx < MAX_RT_SVCS);
- end_idx = get_unique_oen(rt_svc_descs[index].end_oen,
- service->call_type);
+#if SMCCC_MAJOR_VERSION == 1
+ start_idx = get_unique_oen(service->start_oen,
+ service->call_type);
+ end_idx = get_unique_oen(service->end_oen,
+ service->call_type);
+#elif SMCCC_MAJOR_VERSION == 2
+ start_idx = get_rt_desc_idx(service->start_oen,
+ service->is_vendor);
+ end_idx = get_rt_desc_idx(service->end_oen,
+ service->is_vendor);
+#endif
+ assert(start_idx <= end_idx);
assert(end_idx < MAX_RT_SVCS);
for (; start_idx <= end_idx; start_idx++)
rt_svc_descs_indices[start_idx] = index;
diff --git a/docs/cpu-specific-build-macros.rst b/docs/cpu-specific-build-macros.rst
index 9e11cdf..65f6adb 100644
--- a/docs/cpu-specific-build-macros.rst
+++ b/docs/cpu-specific-build-macros.rst
@@ -18,7 +18,11 @@
vulnerability workarounds should be applied at runtime.
- ``WORKAROUND_CVE_2017_5715``: Enables the security workaround for
- `CVE-2017-5715`_. Defaults to 1.
+ `CVE-2017-5715`_. This flag can be set to 0 by the platform if none
+ of the PEs in the system need the workaround. Setting this flag to 0 provides
+ no performance benefit for non-affected platforms, it just helps to comply
+ with the recommendation in the spec regarding workaround discovery.
+ Defaults to 1.
CPU Errata Workarounds
----------------------
diff --git a/docs/plat/ls1043a.rst b/docs/plat/ls1043a.rst
new file mode 100644
index 0000000..0d604aa
--- /dev/null
+++ b/docs/plat/ls1043a.rst
@@ -0,0 +1,91 @@
+Description
+===========
+
+The QorIQ® LS1043A processor is NXP's first quad-core, 64-bit Arm®-based
+processor for embedded networking. The LS1023A (two core version) and the
+LS1043A (four core version) deliver greater than 10 Gbps of performance
+in a flexible I/O package supporting fanless designs. This SoC is a
+purpose-built solution for small-form-factor networking and industrial
+applications with BOM optimizations for economic low layer PCB, lower cost
+power supply and single clock design. The new 0.9V versions of the LS1043A
+and LS1023A deliver addition power savings for applications such as Wireless
+LAN and to Power over Ethernet systems.
+
+LS1043ARDB Specification:
+-------------------------
+Memory subsystem:
+ * 2GByte DDR4 SDRAM (32bit bus)
+ * 128 Mbyte NOR flash single-chip memory
+ * 512 Mbyte NAND flash
+ * 16 Mbyte high-speed SPI flash
+ * SD connector to interface with the SD memory card
+
+Ethernet:
+ * XFI 10G port
+ * QSGMII with 4x 1G ports
+ * Two RGMII ports
+
+PCIe:
+ * PCIe2 (Lanes C) to mini-PCIe slot
+ * PCIe3 (Lanes D) to PCIe slot
+
+USB 3.0: two super speed USB 3.0 type A ports
+
+UART: supports two UARTs up to 115200 bps for console
+
+More information are listed in `ls1043`_.
+
+Boot Sequence
+=============
+
+
+Bootrom --> TF-A BL1 --> TF-A BL2 --> TF-A BL1 --> TF-A BL31
+--> BL32(Tee OS) --> TF-A BL31 --> BL33(u-boot) --> Linux kernel
+
+
+How to build
+============
+
+Build Procedure
+---------------
+
+- Prepare AARCH64 toolchain.
+
+- Build u-boot and OPTee firstly, and get binary images: u-boot.bin and tee.bin
+
+- Build TF-A for Nor boot
+
+ Build bl1:
+
+ .. code:: shell
+
+ CROSS_COMPILE=aarch64-linux-gnu- make PLAT=ls1043 bl1
+
+ Build fip:
+
+ .. code:: shell
+
+ CROSS_COMPILE=aarch64-linux-gnu- make PLAT=ls1043 fip \
+ BL33=u-boot.bin NEED_BL32=yes BL32=tee.bin SPD=opteed
+
+Deploy TF-A Images
+-----------------
+
+- Deploy TF-A images on Nor flash Alt Bank.
+
+ .. code:: shell
+
+ => tftp 82000000 bl1.bin
+ => pro off all;era 64100000 +$filesize;cp.b 82000000 64100000 $filesize
+
+ => tftp 82000000 fip.bin
+ => pro off all;era 64120000 +$filesize;cp.b 82000000 64120000 $filesize
+
+ Then change to Alt bank and boot up TF-A:
+
+ .. code:: shell
+
+ => cpld reset altbank
+
+
+.. _ls1043: https://www.nxp.com/products/processors-and-microcontrollers/arm-based-processors-and-mcus/qoriq-layerscape-arm-processors/qoriq-layerscape-1043a-and-1023a-multicore-communications-processors:LS1043A?lang_cd=en
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index ff5bb12..03930cf 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -217,11 +217,37 @@
- **#define : BL2\_BASE**
Defines the base address in secure RAM where BL1 loads the BL2 binary image.
- Must be aligned on a page-size boundary.
+ Must be aligned on a page-size boundary. This constant is not applicable
+ when BL2_IN_XIP_MEM is set to '1'.
- **#define : BL2\_LIMIT**
Defines the maximum address in secure RAM that the BL2 image can occupy.
+ This constant is not applicable when BL2_IN_XIP_MEM is set to '1'.
+
+- **#define : BL2\_RO\_BASE**
+
+ Defines the base address in secure XIP memory where BL2 RO section originally
+ lives. Must be aligned on a page-size boundary. This constant is only needed
+ when BL2_IN_XIP_MEM is set to '1'.
+
+- **#define : BL2\_RO\_LIMIT**
+
+ Defines the maximum address in secure XIP memory that BL2's actual content
+ (i.e. excluding any data section allocated at runtime) can occupy. This
+ constant is only needed when BL2_IN_XIP_MEM is set to '1'.
+
+- **#define : BL2\_RW\_BASE**
+
+ Defines the base address in secure RAM where BL2's read-write data will live
+ at runtime. Must be aligned on a page-size boundary. This constant is only
+ needed when BL2_IN_XIP_MEM is set to '1'.
+
+- **#define : BL2\_RW\_LIMIT**
+
+ Defines the maximum address in secure RAM that BL2's read-write data can
+ occupy at runtime. This constant is only needed when BL2_IN_XIP_MEM is set
+ to '1'.
- **#define : BL31\_BASE**
@@ -1948,12 +1974,12 @@
implementation of this function will invoke ``console_switch_state()`` to switch
console output to consoles marked for use in the ``runtime`` state.
-Function : bl31\_get\_next\_image\_info() [mandatory]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Function : bl31\_plat\_get\_next\_image\_ep\_info() [mandatory]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
- Argument : unsigned int
+ Argument : uint32_t
Return : entry_point_info *
This function may execute with the MMU and data caches enabled if the platform
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index 5794855..069ad11 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -246,6 +246,12 @@
- ``BL2_AT_EL3``: This is an optional build option that enables the use of
BL2 at EL3 execution level.
+- ``BL2_IN_XIP_MEM``: In some use-cases BL2 will be stored in eXecute In Place
+ (XIP) memory, like BL1. In these use-cases, it is necessary to initialize
+ the RW sections in RAM, while leaving the RO sections in place. This option
+ enable this use-case. For now, this option is only supported when BL2_AT_EL3
+ is set to '1'.
+
- ``BL31``: This is an optional build option which specifies the path to
BL31 image for the ``fip`` target. In this case, the BL31 in TF-A will not
be built.
@@ -384,6 +390,14 @@
handled at EL3, and a panic will result. This is supported only for AArch64
builds.
+- ``FAULT_INJECTION_SUPPORT``: ARMv8.4 externsions introduced support for fault
+ injection from lower ELs, and this build option enables lower ELs to use
+ Error Records accessed via System Registers to inject faults. This is
+ applicable only to AArch64 builds.
+
+ This feature is intended for testing purposes only, and is advisable to keep
+ disabled for production images.
+
- ``FIP_NAME``: This is an optional build option which specifies the FIP
filename for the ``fip`` target. Default is ``fip.bin``.
@@ -525,6 +539,15 @@
smc function id. When this option is enabled on Arm platforms, the
option ``ARM_RECOM_STATE_ID_ENC`` needs to be set to 1 as well.
+- ``RAS_EXTENSION``: When set to ``1``, enable Armv8.2 RAS features. RAS features
+ are an optional extension for pre-Armv8.2 CPUs, but are mandatory for Armv8.2
+ or later CPUs.
+
+ When ``RAS_EXTENSION`` is set to ``1``, ``HANDLE_EA_EL3_FIRST`` must also be
+ set to ``1``.
+
+ This option is disabled by default.
+
- ``RESET_TO_BL31``: Enable BL31 entrypoint as the CPU reset vector instead
of the BL1 entrypoint. It can take the value 0 (CPU reset to BL1
entrypoint) or 1 (CPU reset to BL31 entrypoint).
@@ -567,6 +590,11 @@
pages" section in `Firmware Design`_. This flag is disabled by default and
affects all BL images.
+- ``SMCCC_MAJOR_VERSION``: Numeric value that indicates the major version of
+ the SMC Calling Convention that the Trusted Firmware supports. The only two
+ allowed values are 1 and 2, and it defaults to 1. The minor version is
+ determined using this value.
+
- ``SPD``: Choose a Secure Payload Dispatcher component to be built into TF-A.
This build option is only valid if ``ARCH=aarch64``. The value should be
the path to the directory containing the SPD source, relative to
@@ -579,7 +607,7 @@
firmware images have been loaded in memory, and the MMU and caches are
turned off. Refer to the "Debugging options" section for more details.
-- ``SP_MIN_WITH_SECURE_FIQ``: Boolean flag to indicate the SP_MIN handles
+- ``SP_MIN_WITH_SECURE_FIQ``: Boolean flag to indicate the SP_MIN handles
secure interrupts (caught through the FIQ line). Platforms can enable
this directive if they need to handle such interruption. When enabled,
the FIQ are handled in monitor mode and non secure world is not allowed
@@ -667,6 +695,15 @@
Trusted Watchdog may be disabled at build time for testing or development
purposes.
+- ``ARM_LINUX_KERNEL_AS_BL33``: The Linux kernel expects registers x0-x3 to
+ have specific values at boot. This boolean option allows the Trusted Firmware
+ to have a Linux kernel image as BL33 by preparing the registers to these
+ values before jumping to BL33. This option defaults to 0 (disabled). For now,
+ it only supports AArch64 kernels. ``RESET_TO_BL31`` must be 1 when using it.
+ If this option is set to 1, ``ARM_PRELOADED_DTB_BASE`` must be set to the
+ location of a device tree blob (DTB) already loaded in memory. The Linux
+ Image address must be specified using the ``PRELOADED_BL33_BASE`` option.
+
- ``ARM_RECOM_STATE_ID_ENC``: The PSCI1.0 specification recommends an encoding
for the construction of composite state-ID in the power-state parameter.
The existing PSCI clients currently do not support this encoding of
@@ -783,6 +820,12 @@
HW_CONFIG blob instead of the DTS file. This option is useful to override
the default HW_CONFIG selected by the build system.
+ARM JUNO platform specific build options
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- ``JUNO_TZMP1`` : Boolean option to configure Juno to be used for TrustZone
+ Media Protection (TZ-MP1). Default value of this flag is 0.
+
Debugging options
~~~~~~~~~~~~~~~~~
@@ -1458,41 +1501,92 @@
make PRELOADED_BL33_BASE=0x80000000 PLAT=fvp all fip
-Boot of a preloaded bootwrapped kernel image on Base FVP
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Boot of a preloaded kernel image on Base FVP
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The following example uses the AArch64 boot wrapper. This simplifies normal
-world booting while also making use of TF-A features. It can be obtained from
-its repository with:
+The following example uses a simplified boot flow by directly jumping from the
+TF-A to the Linux kernel, which will use a ramdisk as filesystem. This can be
+useful if both the kernel and the device tree blob (DTB) are already present in
+memory (like in FVP).
+
+For example, if the kernel is loaded at ``0x80080000`` and the DTB is loaded at
+address ``0x82000000``, the firmware can be built like this:
::
- git clone git://git.kernel.org/pub/scm/linux/kernel/git/mark/boot-wrapper-aarch64.git
+ CROSS_COMPILE=aarch64-linux-gnu- \
+ make PLAT=fvp DEBUG=1 \
+ RESET_TO_BL31=1 \
+ ARM_LINUX_KERNEL_AS_BL33=1 \
+ PRELOADED_BL33_BASE=0x80080000 \
+ ARM_PRELOADED_DTB_BASE=0x82000000 \
+ all fip
-After compiling it, an ELF file is generated. It can be loaded with the
-following command:
+Now, it is needed to modify the DTB so that the kernel knows the address of the
+ramdisk. The following script generates a patched DTB from the provided one,
+assuming that the ramdisk is loaded at address ``0x84000000``. Note that this
+script assumes that the user is using a ramdisk image prepared for U-Boot, like
+the ones provided by Linaro. If using a ramdisk without this header,the ``0x40``
+offset in ``INITRD_START`` has to be removed.
-::
+.. code:: bash
+
+ #!/bin/bash
+
+ # Path to the input DTB
+ KERNEL_DTB=<path-to>/<fdt>
+ # Path to the output DTB
+ PATCHED_KERNEL_DTB=<path-to>/<patched-fdt>
+ # Base address of the ramdisk
+ INITRD_BASE=0x84000000
+ # Path to the ramdisk
+ INITRD=<path-to>/<ramdisk.img>
+
+ # Skip uboot header (64 bytes)
+ INITRD_START=$(printf "0x%x" $((${INITRD_BASE} + 0x40)) )
+ INITRD_SIZE=$(stat -Lc %s ${INITRD})
+ INITRD_END=$(printf "0x%x" $((${INITRD_BASE} + ${INITRD_SIZE})) )
- <path-to>/FVP_Base_AEMv8A-AEMv8A \
- -C bp.secureflashloader.fname=bl1.bin \
- -C bp.flashloader0.fname=fip.bin \
- -a cluster0.cpu0=<bootwrapped-kernel.elf> \
- --start cluster0.cpu0=0x0
+ CHOSEN_NODE=$(echo \
+ "/ { \
+ chosen { \
+ linux,initrd-start = <${INITRD_START}>; \
+ linux,initrd-end = <${INITRD_END}>; \
+ }; \
+ };")
-The ``-a cluster0.cpu0=<bootwrapped-kernel.elf>`` option loads the ELF file. It
-also sets the PC register to the ELF entry point address, which is not the
-desired behaviour, so the ``--start cluster0.cpu0=0x0`` option forces the PC back
-to 0x0 (the BL1 entry point address) on CPU #0. The ``PRELOADED_BL33_BASE`` define
-used when compiling the FIP must match the ELF entry point.
+ echo $(dtc -O dts -I dtb ${KERNEL_DTB}) ${CHOSEN_NODE} | \
+ dtc -O dtb -o ${PATCHED_KERNEL_DTB} -
-Boot of a preloaded bootwrapped kernel image on Juno
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+And the FVP binary can be run with the following command:
+
+::
+
+ <path-to>/FVP_Base_AEMv8A-AEMv8A \
+ -C pctl.startup=0.0.0.0 \
+ -C bp.secure_memory=1 \
+ -C cluster0.NUM_CORES=4 \
+ -C cluster1.NUM_CORES=4 \
+ -C cache_state_modelled=1 \
+ -C cluster0.cpu0.RVBAR=0x04020000 \
+ -C cluster0.cpu1.RVBAR=0x04020000 \
+ -C cluster0.cpu2.RVBAR=0x04020000 \
+ -C cluster0.cpu3.RVBAR=0x04020000 \
+ -C cluster1.cpu0.RVBAR=0x04020000 \
+ -C cluster1.cpu1.RVBAR=0x04020000 \
+ -C cluster1.cpu2.RVBAR=0x04020000 \
+ -C cluster1.cpu3.RVBAR=0x04020000 \
+ --data cluster0.cpu0="<path-to>/bl31.bin"@0x04020000 \
+ --data cluster0.cpu0="<path-to>/<patched-fdt>"@0x82000000 \
+ --data cluster0.cpu0="<path-to>/<kernel-binary>"@0x80080000 \
+ --data cluster0.cpu0="<path-to>/<ramdisk.img>"@0x84000000
+
+Boot of a preloaded kernel image on Juno
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The procedure to obtain and compile the boot wrapper is very similar to the case
-of the FVP. The execution must be stopped at the end of bl2\_main(), and the
-loading method explained above in the EL3 payload boot flow section may be used
-to load the ELF file over JTAG on Juno.
+The Trusted Firmware must be compiled in a similar way as for FVP explained
+above. The process to load binaries to memory is the one explained in
+`Booting an EL3 payload on Juno`_.
Running the software on FVP
---------------------------
diff --git a/drivers/arm/gic/gic_v3.c b/drivers/arm/gic/gic_v3.c
index 3e802fd..5486817 100644
--- a/drivers/arm/gic/gic_v3.c
+++ b/drivers/arm/gic/gic_v3.c
@@ -8,7 +8,7 @@
#include <debug.h>
#include <gic_v3.h>
-uintptr_t gicv3_get_rdist(uintptr_t gicr_base, uint64_t mpidr)
+uintptr_t gicv3_get_rdist(uintptr_t gicr_base, u_register_t mpidr)
{
uint32_t cpu_aff, gicr_aff;
uint64_t gicr_typer;
diff --git a/drivers/arm/tzc/tzc_dmc500.c b/drivers/arm/tzc/tzc_dmc500.c
index 7350b2c..8b618e6 100644
--- a/drivers/arm/tzc/tzc_dmc500.c
+++ b/drivers/arm/tzc/tzc_dmc500.c
@@ -25,6 +25,7 @@
/* Pointer to the tzc_dmc500_driver_data structure populated by the platform */
static const tzc_dmc500_driver_data_t *g_driver_data;
+static unsigned int g_sys_if_count;
#define verify_region_attr(region, attr) \
((g_conf_regions[(region)].sec_attr == \
@@ -88,7 +89,7 @@
for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
assert(DMC_INST_BASE_ADDR(dmc_inst));
- for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT; sys_if++)
+ for (sys_if = 0; sys_if < g_sys_if_count; sys_if++)
_tzc_dmc500_write_flush_control(
DMC_INST_SI_BASE(dmc_inst, sys_if));
}
@@ -119,7 +120,7 @@
for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count;
dmc_inst++) {
assert(DMC_INST_BASE_ADDR(dmc_inst));
- for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT;
+ for (sys_if = 0; sys_if < g_sys_if_count;
sys_if++) {
attr = _tzc_dmc500_read_region_attr_0(
DMC_INST_SI_BASE(dmc_inst, sys_if),
@@ -154,7 +155,7 @@
/* Configure region_0 in all DMC instances */
for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
assert(DMC_INST_BASE_ADDR(dmc_inst));
- for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT; sys_if++)
+ for (sys_if = 0; sys_if < g_sys_if_count; sys_if++)
_tzc_dmc500_configure_region0(
DMC_INST_SI_BASE(dmc_inst, sys_if),
sec_attr, nsaid_permissions);
@@ -195,7 +196,7 @@
for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
assert(DMC_INST_BASE_ADDR(dmc_inst));
- for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT; sys_if++)
+ for (sys_if = 0; sys_if < g_sys_if_count; sys_if++)
_tzc_dmc500_configure_region(
DMC_INST_SI_BASE(dmc_inst, sys_if),
TZC_DMC500_REGION_ATTR_F_EN_MASK,
@@ -272,4 +273,13 @@
/* Validates the information passed by platform */
validate_plat_driver_data(plat_driver_data);
g_driver_data = plat_driver_data;
+
+ /* Check valid system interface count */
+ assert(g_driver_data->sys_if_count <= MAX_SYS_IF_COUNT);
+
+ g_sys_if_count = g_driver_data->sys_if_count;
+
+ /* If interface count is not present then assume max */
+ if (g_sys_if_count == 0U)
+ g_sys_if_count = MAX_SYS_IF_COUNT;
}
diff --git a/drivers/auth/auth_mod.c b/drivers/auth/auth_mod.c
index 1cea60b..eb537b6 100644
--- a/drivers/auth/auth_mod.c
+++ b/drivers/auth/auth_mod.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -30,7 +30,7 @@
/* Pointer to CoT */
extern const auth_img_desc_t *const cot_desc_ptr;
-extern unsigned int auth_img_flags[];
+extern unsigned int auth_img_flags[MAX_NUMBER_IDS];
static int cmp_auth_param_type_desc(const auth_param_type_desc_t *a,
const auth_param_type_desc_t *b)
diff --git a/drivers/auth/crypto_mod.c b/drivers/auth/crypto_mod.c
index 3b3e3ac..4cd0550 100644
--- a/drivers/auth/crypto_mod.c
+++ b/drivers/auth/crypto_mod.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,7 +9,6 @@
#include <debug.h>
/* Variable exported by the crypto library through REGISTER_CRYPTO_LIB() */
-extern const crypto_lib_desc_t crypto_lib_desc;
/*
* The crypto module is responsible for verifying digital signatures and hashes.
diff --git a/drivers/auth/mbedtls/mbedtls_common.c b/drivers/auth/mbedtls/mbedtls_common.c
index 205c243..c048d00 100644
--- a/drivers/auth/mbedtls/mbedtls_common.c
+++ b/drivers/auth/mbedtls/mbedtls_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -10,6 +10,7 @@
#include <mbedtls/memory_buffer_alloc.h>
#include <mbedtls/platform.h>
#include <mbedtls_config.h>
+#include <mbedtls_common.h>
/*
* mbed TLS heap
diff --git a/drivers/console/aarch64/multi_console.S b/drivers/console/aarch64/multi_console.S
index 15c3ba4..a85a6a5 100644
--- a/drivers/console/aarch64/multi_console.S
+++ b/drivers/console/aarch64/multi_console.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -10,7 +10,8 @@
.globl console_register
.globl console_unregister
- .globl console_set_scope
+ .globl console_is_registered
+ .globl console_set_scope
.globl console_switch_state
.globl console_putc
.globl console_getc
@@ -38,13 +39,15 @@
* persistent memory (e.g. the data section).
* In : x0 - address of console_t structure
* Out: x0 - Always 1 (for easier tail calling)
- * Clobber list: x0, x1, x14
+ * Clobber list: x0, x1, x14, x15
* -----------------------------------------------
*/
func console_register
#if ENABLE_ASSERTIONS
+ /* Assert that x0 isn't a NULL pointer */
cmp x0, #0
ASM_ASSERT(ne)
+ /* Assert that the struct isn't in the stack */
adrp x1, __STACKS_START__
add x1, x1, :lo12:__STACKS_START__
cmp x0, x1
@@ -54,6 +57,14 @@
cmp x0, x1
ASM_ASSERT(hs)
not_on_stack:
+ /* Assert that this struct isn't in the list */
+ mov x1, x0 /* Preserve x0 and x30 */
+ mov x15, x30
+ bl console_is_registered
+ cmp x0, #0
+ ASM_ASSERT(eq)
+ mov x30, x15
+ mov x0, x1
#endif /* ENABLE_ASSERTIONS */
adrp x14, console_list
ldr x1, [x14, :lo12:console_list] /* X1 = first struct in list */
@@ -73,6 +84,11 @@
* -----------------------------------------------
*/
func console_unregister
+#if ENABLE_ASSERTIONS
+ /* Assert that x0 isn't a NULL pointer */
+ cmp x0, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
adrp x14, console_list
add x14, x14, :lo12:console_list /* X14 = ptr to first struct */
ldr x1, [x14] /* X1 = first struct */
@@ -96,6 +112,37 @@
endfunc console_unregister
/* -----------------------------------------------
+ * int console_is_registered(console_t *console)
+ * Function to detect if a specific console is
+ * registered or not.
+ * In: x0 - address of console_t struct to remove
+ * Out: x0 - 1 if it is registered, 0 if not.
+ * Clobber list: x0, x14
+ * -----------------------------------------------
+ */
+func console_is_registered
+#if ENABLE_ASSERTIONS
+ /* Assert that x0 isn't a NULL pointer */
+ cmp x0, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+ adrp x14, console_list
+ ldr x14, [x14, :lo12:console_list] /* X14 = first console struct */
+check_registered_loop:
+ cbz x14, console_not_registered /* Check if end of list */
+ cmp x0, x14 /* Check if the pointers are different */
+ b.eq console_registered
+ ldr x14, [x14, #CONSOLE_T_NEXT] /* Get pointer to next struct */
+ b check_registered_loop
+console_not_registered:
+ mov x0, #0
+ ret
+console_registered:
+ mov x0, #1
+ ret
+endfunc console_is_registered
+
+ /* -----------------------------------------------
* void console_switch_state(unsigned int new_state)
* Function to switch the current console state.
* The console state determines which of the
diff --git a/fdts/fvp-base-gicv3-psci-common.dtsi b/fdts/fvp-base-gicv3-psci-common.dtsi
index 2ef2df8..631c4e3 100644
--- a/fdts/fvp-base-gicv3-psci-common.dtsi
+++ b/fdts/fvp-base-gicv3-psci-common.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -228,7 +228,7 @@
<0 63 4>;
};
- smb {
+ smb@0,0 {
compatible = "simple-bus";
#address-cells = <2>;
@@ -244,7 +244,7 @@
};
panels {
- panel@0 {
+ panel {
compatible = "panel";
mode = "XVGA";
refresh = <60>;
diff --git a/fdts/fvp-foundation-motherboard.dtsi b/fdts/fvp-foundation-motherboard.dtsi
index ae7237b..9ee5b64 100644
--- a/fdts/fvp-foundation-motherboard.dtsi
+++ b/fdts/fvp-foundation-motherboard.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -44,14 +44,14 @@
#size-cells = <1>;
ranges = <0 3 0 0x200000>;
- v2m_sysreg: sysreg@010000 {
+ v2m_sysreg: sysreg@10000 {
compatible = "arm,vexpress-sysreg";
reg = <0x010000 0x1000>;
gpio-controller;
#gpio-cells = <2>;
};
- v2m_sysctl: sysctl@020000 {
+ v2m_sysctl: sysctl@20000 {
compatible = "arm,sp810", "arm,primecell";
reg = <0x020000 0x1000>;
clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>;
@@ -60,7 +60,7 @@
clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
};
- v2m_serial0: uart@090000 {
+ v2m_serial0: uart@90000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x090000 0x1000>;
interrupts = <0 5 4>;
@@ -68,7 +68,7 @@
clock-names = "uartclk", "apb_pclk";
};
- v2m_serial1: uart@0a0000 {
+ v2m_serial1: uart@a0000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0a0000 0x1000>;
interrupts = <0 6 4>;
@@ -76,7 +76,7 @@
clock-names = "uartclk", "apb_pclk";
};
- v2m_serial2: uart@0b0000 {
+ v2m_serial2: uart@b0000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0b0000 0x1000>;
interrupts = <0 7 4>;
@@ -84,7 +84,7 @@
clock-names = "uartclk", "apb_pclk";
};
- v2m_serial3: uart@0c0000 {
+ v2m_serial3: uart@c0000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0c0000 0x1000>;
interrupts = <0 8 4>;
@@ -92,7 +92,7 @@
clock-names = "uartclk", "apb_pclk";
};
- wdt@0f0000 {
+ wdt@f0000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0x0f0000 0x1000>;
interrupts = <0 0 4>;
@@ -124,7 +124,7 @@
clock-names = "apb_pclk";
};
- virtio_block@0130000 {
+ virtio_block@130000 {
compatible = "virtio,mmio";
reg = <0x130000 0x1000>;
interrupts = <0 0x2a 4>;
diff --git a/fdts/rtsm_ve-motherboard-aarch32.dtsi b/fdts/rtsm_ve-motherboard-aarch32.dtsi
index 5afbc1e..7a8af8e 100644
--- a/fdts/rtsm_ve-motherboard-aarch32.dtsi
+++ b/fdts/rtsm_ve-motherboard-aarch32.dtsi
@@ -57,14 +57,14 @@
#size-cells = <1>;
ranges = <0 3 0 0x200000>;
- v2m_sysreg: sysreg@010000 {
+ v2m_sysreg: sysreg@10000 {
compatible = "arm,vexpress-sysreg";
reg = <0x010000 0x1000>;
gpio-controller;
#gpio-cells = <2>;
};
- v2m_sysctl: sysctl@020000 {
+ v2m_sysctl: sysctl@20000 {
compatible = "arm,sp810", "arm,primecell";
reg = <0x020000 0x1000>;
clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>;
@@ -73,7 +73,7 @@
clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
};
- aaci@040000 {
+ aaci@40000 {
compatible = "arm,pl041", "arm,primecell";
reg = <0x040000 0x1000>;
interrupts = <11>;
@@ -81,7 +81,7 @@
clock-names = "apb_pclk";
};
- mmci@050000 {
+ mmci@50000 {
compatible = "arm,pl180", "arm,primecell";
reg = <0x050000 0x1000>;
interrupts = <9 10>;
@@ -93,7 +93,7 @@
clock-names = "mclk", "apb_pclk";
};
- kmi@060000 {
+ kmi@60000 {
compatible = "arm,pl050", "arm,primecell";
reg = <0x060000 0x1000>;
interrupts = <12>;
@@ -101,7 +101,7 @@
clock-names = "KMIREFCLK", "apb_pclk";
};
- kmi@070000 {
+ kmi@70000 {
compatible = "arm,pl050", "arm,primecell";
reg = <0x070000 0x1000>;
interrupts = <13>;
@@ -109,7 +109,7 @@
clock-names = "KMIREFCLK", "apb_pclk";
};
- v2m_serial0: uart@090000 {
+ v2m_serial0: uart@90000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x090000 0x1000>;
interrupts = <5>;
@@ -117,7 +117,7 @@
clock-names = "uartclk", "apb_pclk";
};
- v2m_serial1: uart@0a0000 {
+ v2m_serial1: uart@a0000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0a0000 0x1000>;
interrupts = <6>;
@@ -125,7 +125,7 @@
clock-names = "uartclk", "apb_pclk";
};
- v2m_serial2: uart@0b0000 {
+ v2m_serial2: uart@b0000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0b0000 0x1000>;
interrupts = <7>;
@@ -133,7 +133,7 @@
clock-names = "uartclk", "apb_pclk";
};
- v2m_serial3: uart@0c0000 {
+ v2m_serial3: uart@c0000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0c0000 0x1000>;
interrupts = <8>;
@@ -141,7 +141,7 @@
clock-names = "uartclk", "apb_pclk";
};
- wdt@0f0000 {
+ wdt@f0000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0x0f0000 0x1000>;
interrupts = <0>;
@@ -184,7 +184,7 @@
framebuffer = <0x18000000 0x00180000>;
};
- virtio_block@0130000 {
+ virtio_block@130000 {
compatible = "virtio,mmio";
reg = <0x130000 0x1000>;
interrupts = <0x2a>;
diff --git a/fdts/rtsm_ve-motherboard.dtsi b/fdts/rtsm_ve-motherboard.dtsi
index 8baa829..486f8a9 100644
--- a/fdts/rtsm_ve-motherboard.dtsi
+++ b/fdts/rtsm_ve-motherboard.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -56,14 +56,14 @@
#size-cells = <1>;
ranges = <0 3 0 0x200000>;
- v2m_sysreg: sysreg@010000 {
+ v2m_sysreg: sysreg@10000 {
compatible = "arm,vexpress-sysreg";
reg = <0x010000 0x1000>;
gpio-controller;
#gpio-cells = <2>;
};
- v2m_sysctl: sysctl@020000 {
+ v2m_sysctl: sysctl@20000 {
compatible = "arm,sp810", "arm,primecell";
reg = <0x020000 0x1000>;
clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>;
@@ -72,7 +72,7 @@
clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
};
- aaci@040000 {
+ aaci@40000 {
compatible = "arm,pl041", "arm,primecell";
reg = <0x040000 0x1000>;
interrupts = <0 11 4>;
@@ -80,7 +80,7 @@
clock-names = "apb_pclk";
};
- mmci@050000 {
+ mmci@50000 {
compatible = "arm,pl180", "arm,primecell";
reg = <0x050000 0x1000>;
interrupts = <0 9 4 0 10 4>;
@@ -92,7 +92,7 @@
clock-names = "mclk", "apb_pclk";
};
- kmi@060000 {
+ kmi@60000 {
compatible = "arm,pl050", "arm,primecell";
reg = <0x060000 0x1000>;
interrupts = <0 12 4>;
@@ -100,7 +100,7 @@
clock-names = "KMIREFCLK", "apb_pclk";
};
- kmi@070000 {
+ kmi@70000 {
compatible = "arm,pl050", "arm,primecell";
reg = <0x070000 0x1000>;
interrupts = <0 13 4>;
@@ -108,7 +108,7 @@
clock-names = "KMIREFCLK", "apb_pclk";
};
- v2m_serial0: uart@090000 {
+ v2m_serial0: uart@90000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x090000 0x1000>;
interrupts = <0 5 4>;
@@ -116,7 +116,7 @@
clock-names = "uartclk", "apb_pclk";
};
- v2m_serial1: uart@0a0000 {
+ v2m_serial1: uart@a0000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0a0000 0x1000>;
interrupts = <0 6 4>;
@@ -124,7 +124,7 @@
clock-names = "uartclk", "apb_pclk";
};
- v2m_serial2: uart@0b0000 {
+ v2m_serial2: uart@b0000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0b0000 0x1000>;
interrupts = <0 7 4>;
@@ -132,7 +132,7 @@
clock-names = "uartclk", "apb_pclk";
};
- v2m_serial3: uart@0c0000 {
+ v2m_serial3: uart@c0000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0c0000 0x1000>;
interrupts = <0 8 4>;
@@ -140,7 +140,7 @@
clock-names = "uartclk", "apb_pclk";
};
- wdt@0f0000 {
+ wdt@f0000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0x0f0000 0x1000>;
interrupts = <0 0 4>;
@@ -183,14 +183,14 @@
framebuffer = <0x18000000 0x00180000>;
};
- virtio_block@0130000 {
+ virtio_block@130000 {
compatible = "virtio,mmio";
reg = <0x130000 0x1000>;
interrupts = <0 0x2a 4>;
};
};
- v2m_fixed_3v3: fixedregulator@0 {
+ v2m_fixed_3v3: fixedregulator {
compatible = "regulator-fixed";
regulator-name = "3V3";
regulator-min-microvolt = <3300000>;
@@ -202,7 +202,7 @@
compatible = "arm,vexpress,config-bus", "simple-bus";
arm,vexpress,config-bridge = <&v2m_sysreg>;
- v2m_oscclk1: osc@1 {
+ v2m_oscclk1: osc {
/* CLCD clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 1>;
@@ -220,7 +220,7 @@
* };
*/
- muxfpga@0 {
+ muxfpga {
compatible = "arm,vexpress-muxfpga";
arm,vexpress-sysreg,func = <7 0>;
};
@@ -243,7 +243,7 @@
* };
*/
- dvimode@0 {
+ dvimode {
compatible = "arm,vexpress-dvimode";
arm,vexpress-sysreg,func = <11 0>;
};
diff --git a/include/bl2/bl2.h b/include/bl2/bl2.h
index f2bd07e..89ff06e 100644
--- a/include/bl2/bl2.h
+++ b/include/bl2/bl2.h
@@ -7,9 +7,6 @@
#ifndef BL2_H__
#define BL2_H__
-struct entry_point_info;
-
void bl2_main(void);
-struct entry_point_info *bl2_load_images(void);
#endif /* BL2_H__ */
diff --git a/include/bl31/ea_handle.h b/include/bl31/ea_handle.h
new file mode 100644
index 0000000..060c9b7
--- /dev/null
+++ b/include/bl31/ea_handle.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __EA_HANDLE_H__
+#define __EA_HANDLE_H__
+
+/* Constants indicating the reason for an External Abort */
+
+/* External Abort received at SError vector */
+#define ERROR_EA_ASYNC 0
+
+/* Synchronous External Abort received at Synchronous exception vector */
+#define ERROR_EA_SYNC 1
+
+/* External Abort synchronized by ESB instruction */
+#define ERROR_EA_ESB 2
+
+/* RAS event signalled as peripheral interrupt */
+#define ERROR_INTERRUPT 3
+
+#endif /* __EA_HANDLE_H__ */
diff --git a/include/common/aarch64/asm_macros.S b/include/common/aarch64/asm_macros.S
index 94a9df9..7c8e643 100644
--- a/include/common/aarch64/asm_macros.S
+++ b/include/common/aarch64/asm_macros.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -192,4 +192,10 @@
.space SPINLOCK_ASM_SIZE
.endm
+#if RAS_EXTENSION
+ .macro esb
+ .inst 0xd503221f
+ .endm
+#endif
+
#endif /* __ASM_MACROS_S__ */
diff --git a/include/common/aarch64/el3_common_macros.S b/include/common/aarch64/el3_common_macros.S
index 4ebf77b..d5f527a 100644
--- a/include/common/aarch64/el3_common_macros.S
+++ b/include/common/aarch64/el3_common_macros.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -278,8 +278,8 @@
* an earlier boot loader stage.
* -------------------------------------------------------------
*/
- adr x0, __RW_START__
- adr x1, __RW_END__
+ ldr x0, =__RW_START__
+ ldr x1, =__RW_END__
sub x1, x1, x0
bl inv_dcache_range
#endif
@@ -294,7 +294,7 @@
bl zeromem
#endif
-#ifdef IMAGE_BL1
+#if defined(IMAGE_BL1) || (defined(IMAGE_BL2) && BL2_IN_XIP_MEM)
ldr x0, =__DATA_RAM_START__
ldr x1, =__DATA_ROM_START__
ldr x2, =__DATA_SIZE__
diff --git a/include/common/runtime_svc.h b/include/common/runtime_svc.h
index 5d9fa39..b8cf8de 100644
--- a/include/common/runtime_svc.h
+++ b/include/common/runtime_svc.h
@@ -8,8 +8,9 @@
#define __RUNTIME_SVC_H__
#include <bl_common.h> /* to include exception types */
+#include <cassert.h>
#include <smccc_helpers.h> /* to include SMCCC definitions */
-
+#include <utils_def.h>
/*******************************************************************************
* Structure definition, typedefs & constants for the runtime service framework
@@ -32,11 +33,20 @@
/*
- * The function identifier has 6 bits for the owning entity number and
- * single bit for the type of smc call. When taken together these
- * values limit the maximum number of runtime services to 128.
+ * In SMCCC 1.X, the function identifier has 6 bits for the owning entity number
+ * and a single bit for the type of smc call. When taken together, those values
+ * limit the maximum number of runtime services to 128.
+ *
+ * In SMCCC 2.X the type bit is always 1 and there are only 4 OEN bits in the
+ * compatibility namespace, so the total number of services is 16. The LSB of
+ * namespace is also added to these 4 bits to make space for the vendor service
+ * handler and so the total number of runtime services is 32.
*/
+#if SMCCC_MAJOR_VERSION == 1
#define MAX_RT_SVCS 128
+#elif SMCCC_MAJOR_VERSION == 2
+#define MAX_RT_SVCS 32
+#endif
#ifndef __ASSEMBLY__
@@ -60,26 +70,64 @@
typedef struct rt_svc_desc {
uint8_t start_oen;
uint8_t end_oen;
+#if SMCCC_MAJOR_VERSION == 1
uint8_t call_type;
+#elif SMCCC_MAJOR_VERSION == 2
+ uint8_t is_vendor;
+#endif
const char *name;
rt_svc_init_t init;
rt_svc_handle_t handle;
} rt_svc_desc_t;
/*
- * Convenience macro to declare a service descriptor
+ * Convenience macros to declare a service descriptor
*/
-#define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch) \
- static const rt_svc_desc_t __svc_desc_ ## _name \
- __section("rt_svc_descs") __used = { \
- .start_oen = _start, \
- .end_oen = _end, \
- .call_type = _type, \
- .name = #_name, \
- .init = _setup, \
- .handle = _smch }
+#if SMCCC_MAJOR_VERSION == 1
+
+#define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch) \
+ static const rt_svc_desc_t __svc_desc_ ## _name \
+ __section("rt_svc_descs") __used = { \
+ .start_oen = _start, \
+ .end_oen = _end, \
+ .call_type = _type, \
+ .name = #_name, \
+ .init = _setup, \
+ .handle = _smch \
+ }
+
+#elif SMCCC_MAJOR_VERSION == 2
+
+#define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch) \
+ static const rt_svc_desc_t __svc_desc_ ## _name \
+ __section("rt_svc_descs") __used = { \
+ .start_oen = _start, \
+ .end_oen = _end, \
+ .is_vendor = 0, \
+ .name = #_name, \
+ .init = _setup, \
+ .handle = _smch, \
+ }; \
+ CASSERT((_type) == SMC_TYPE_FAST, rt_svc_type_check_ ## _name)
/*
+ * The higher 16 entries of the runtime services are used for the vendor
+ * specific descriptor.
+ */
+#define DECLARE_RT_SVC_VENDOR(_setup, _smch) \
+ static const rt_svc_desc_t __svc_desc_vendor \
+ __section("rt_svc_descs") __used = { \
+ .start_oen = 0, \
+ .end_oen = 15, \
+ .is_vendor = 1, \
+ .name = "vendor_rt_svc", \
+ .init = _setup, \
+ .handle = _smch, \
+ }
+
+#endif /* SMCCC_MAJOR_VERSION */
+
+/*
* Compile time assertions related to the 'rt_svc_desc' structure to:
* 1. ensure that the assembler and the compiler view of the size
* of the structure are the same.
@@ -96,25 +144,39 @@
assert_rt_svc_desc_handle_offset_mismatch);
+#if SMCCC_MAJOR_VERSION == 1
/*
* This macro combines the call type and the owning entity number corresponding
* to a runtime service to generate a unique owning entity number. This unique
* oen is used to access an entry in the 'rt_svc_descs_indices' array. The entry
* contains the index of the service descriptor in the 'rt_svc_descs' array.
*/
-#define get_unique_oen(oen, call_type) ((oen & FUNCID_OEN_MASK) | \
- ((call_type & FUNCID_TYPE_MASK) \
- << FUNCID_OEN_WIDTH))
+#define get_unique_oen(oen, call_type) \
+ (((uint32_t)(oen) & FUNCID_OEN_MASK) | \
+ (((uint32_t)(call_type) & FUNCID_TYPE_MASK) << FUNCID_OEN_WIDTH))
/*
* This macro generates the unique owning entity number from the SMC Function
- * ID. This unique oen is used to access an entry in the
- * 'rt_svc_descs_indices' array to invoke the corresponding runtime service
- * handler during SMC handling.
+ * ID. This unique oen is used to access an entry in the 'rt_svc_descs_indices'
+ * array to invoke the corresponding runtime service handler during SMC
+ * handling.
+ */
+#define get_unique_oen_from_smc_fid(fid) \
+ get_unique_oen(GET_SMC_OEN(fid), GET_SMC_TYPE(fid))
+
+#elif SMCCC_MAJOR_VERSION == 2
+
+/*
+ * This macro combines the owning entity number corresponding to a runtime
+ * service with one extra bit for the vendor namespace to generate an index into
+ * the 'rt_svc_descs_indices' array. The entry contains the index of the service
+ * descriptor in the 'rt_svc_descs' array.
*/
-#define get_unique_oen_from_smc_fid(fid) \
- get_unique_oen(((fid) >> FUNCID_OEN_SHIFT), \
- ((fid) >> FUNCID_TYPE_SHIFT))
+#define get_rt_desc_idx(oen, is_vendor) \
+ (((uint32_t)(oen) & FUNCID_OEN_MASK) | \
+ (((uint32_t)(is_vendor) & 1U) << FUNCID_OEN_WIDTH))
+
+#endif
/*******************************************************************************
* Function & variable prototypes
diff --git a/include/common/tbbr/tbbr_img_def.h b/include/common/tbbr/tbbr_img_def.h
index 060198b..273abbe 100644
--- a/include/common/tbbr/tbbr_img_def.h
+++ b/include/common/tbbr/tbbr_img_def.h
@@ -75,4 +75,7 @@
/* NT_FW_CONFIG */
#define NT_FW_CONFIG_ID 27
+/* Define size of the array */
+#define MAX_NUMBER_IDS 28
+
#endif /* __TBBR_IMG_DEF_H__ */
diff --git a/include/drivers/arm/tzc_dmc500.h b/include/drivers/arm/tzc_dmc500.h
index 2606d1b..ff58a27 100644
--- a/include/drivers/arm/tzc_dmc500.h
+++ b/include/drivers/arm/tzc_dmc500.h
@@ -130,6 +130,7 @@
typedef struct tzc_dmc500_driver_data {
uintptr_t dmc_base[MAX_DMC_COUNT];
int dmc_count;
+ unsigned int sys_if_count;
} tzc_dmc500_driver_data_t;
void tzc_dmc500_driver_init(const tzc_dmc500_driver_data_t *plat_driver_data);
diff --git a/include/drivers/auth/auth_mod.h b/include/drivers/auth/auth_mod.h
index bd65098..bb3b8f9 100644
--- a/include/drivers/auth/auth_mod.h
+++ b/include/drivers/auth/auth_mod.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,6 +12,7 @@
#include <auth_common.h>
#include <cot_def.h>
#include <img_parser_mod.h>
+#include <tbbr_img_def.h>
/*
* Image flags
@@ -41,7 +42,10 @@
#define REGISTER_COT(_cot) \
const auth_img_desc_t *const cot_desc_ptr = \
(const auth_img_desc_t *const)&_cot[0]; \
- unsigned int auth_img_flags[sizeof(_cot)/sizeof(_cot[0])]
+ unsigned int auth_img_flags[MAX_NUMBER_IDS]
+
+extern const auth_img_desc_t *const cot_desc_ptr;
+extern unsigned int auth_img_flags[MAX_NUMBER_IDS];
#endif /* TRUSTED_BOARD_BOOT */
diff --git a/include/drivers/auth/crypto_mod.h b/include/drivers/auth/crypto_mod.h
index 08884ab..f9b44d1 100644
--- a/include/drivers/auth/crypto_mod.h
+++ b/include/drivers/auth/crypto_mod.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -43,7 +43,7 @@
void crypto_mod_init(void);
int crypto_mod_verify_signature(void *data_ptr, unsigned int data_len,
void *sig_ptr, unsigned int sig_len,
- void *sig_alg, unsigned int sig_alg_len,
+ void *sig_alg_ptr, unsigned int sig_alg_len,
void *pk_ptr, unsigned int pk_len);
int crypto_mod_verify_hash(void *data_ptr, unsigned int data_len,
void *digest_info_ptr, unsigned int digest_info_len);
@@ -57,4 +57,6 @@
.verify_hash = _verify_hash \
}
+extern const crypto_lib_desc_t crypto_lib_desc;
+
#endif /* __CRYPTO_MOD_H__ */
diff --git a/include/drivers/auth/img_parser_mod.h b/include/drivers/auth/img_parser_mod.h
index 347ed62..eaf3e6e 100644
--- a/include/drivers/auth/img_parser_mod.h
+++ b/include/drivers/auth/img_parser_mod.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -44,10 +44,10 @@
/* Exported functions */
void img_parser_init(void);
int img_parser_check_integrity(img_type_t img_type,
- void *img, unsigned int img_len);
+ void *img_ptr, unsigned int img_len);
int img_parser_get_auth_param(img_type_t img_type,
const auth_param_type_desc_t *type_desc,
- void *img, unsigned int img_len,
+ void *img_ptr, unsigned int img_len,
void **param_ptr, unsigned int *param_len);
/* Macro to register an image parser library */
diff --git a/include/drivers/console.h b/include/drivers/console.h
index f8ec83d..0855170 100644
--- a/include/drivers/console.h
+++ b/include/drivers/console.h
@@ -50,7 +50,12 @@
*/
/* Remove a single console_t instance from the console list. */
int console_unregister(console_t *console);
-/* Set scope mask of a console that determines in what states it is active. */
+/* Returns 1 if this console is already registered, 0 if not */
+int console_is_registered(console_t *console);
+/*
+ * Set scope mask of a console that determines in what states it is active.
+ * By default they are registered with (CONSOLE_FLAG_BOOT|CONSOLE_FLAG_CRASH).
+ */
void console_set_scope(console_t *console, unsigned int scope);
/* Switch to a new global console state (CONSOLE_FLAG_BOOT/RUNTIME/CRASH). */
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 91aa484..92bb97d 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -215,6 +215,7 @@
/* SCR definitions */
#define SCR_RES1_BITS ((U(1) << 4) | (U(1) << 5))
+#define SCR_FIEN_BIT (U(1) << 21)
#define SCR_TWE_BIT (U(1) << 13)
#define SCR_TWI_BIT (U(1) << 12)
#define SCR_ST_BIT (U(1) << 11)
@@ -442,10 +443,10 @@
#define GET_M32(mode) (((mode) >> MODE32_SHIFT) & MODE32_MASK)
#define SPSR_64(el, sp, daif) \
- (MODE_RW_64 << MODE_RW_SHIFT | \
- ((el) & MODE_EL_MASK) << MODE_EL_SHIFT | \
- ((sp) & MODE_SP_MASK) << MODE_SP_SHIFT | \
- ((daif) & SPSR_DAIF_MASK) << SPSR_DAIF_SHIFT)
+ ((MODE_RW_64 << MODE_RW_SHIFT) | \
+ (((el) & MODE_EL_MASK) << MODE_EL_SHIFT) | \
+ (((sp) & MODE_SP_MASK) << MODE_SP_SHIFT) | \
+ (((daif) & SPSR_DAIF_MASK) << SPSR_DAIF_SHIFT))
#define SPSR_MODE32(mode, isa, endian, aif) \
((MODE_RW_32 << MODE_RW_SHIFT) | \
@@ -528,6 +529,12 @@
#define EC_AARCH64_FP U(0x2c)
#define EC_SERROR U(0x2f)
+/*
+ * External Abort bit in Instruction and Data Aborts synchronous exception
+ * syndromes.
+ */
+#define ESR_ISS_EABORT_EA_BIT U(9)
+
#define EC_BITS(x) (((x) >> ESR_EC_SHIFT) & ESR_EC_MASK)
/* Reset bit inside the Reset management register for EL3 (RMR_EL3) */
@@ -705,4 +712,23 @@
#define AMCGCR_EL0_CG1NC_LENGTH U(8)
#define AMCGCR_EL0_CG1NC_MASK U(0xff)
+/*******************************************************************************
+ * RAS system registers
+ *******************************************************************************/
+#define DISR_EL1 S3_0_C12_C1_1
+#define DISR_A_BIT 31
+
+#define ERRIDR_EL1 S3_0_C5_C3_0
+#define ERRIDR_MASK 0xffff
+
+#define ERRSELR_EL1 S3_0_C5_C3_1
+
+/* System register access to Standard Error Record registers */
+#define ERXFR_EL1 S3_0_C5_C4_0
+#define ERXCTLR_EL1 S3_0_C5_C4_1
+#define ERXSTATUS_EL1 S3_0_C5_C4_2
+#define ERXADDR_EL1 S3_0_C5_C4_3
+#define ERXMISC0_EL1 S3_0_C5_C4_4
+#define ERXMISC1_EL1 S3_0_C5_C4_5
+
#endif /* __ARCH_H__ */
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index 485ed43..58ec943 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -18,15 +18,15 @@
*********************************************************************/
#define _DEFINE_SYSREG_READ_FUNC(_name, _reg_name) \
-static inline uint64_t read_ ## _name(void) \
+static inline u_register_t read_ ## _name(void) \
{ \
- uint64_t v; \
+ u_register_t v; \
__asm__ volatile ("mrs %0, " #_reg_name : "=r" (v)); \
return v; \
}
#define _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) \
-static inline void write_ ## _name(uint64_t v) \
+static inline void write_ ## _name(u_register_t v) \
{ \
__asm__ volatile ("msr " #_reg_name ", %0" : : "r" (v)); \
}
@@ -333,6 +333,16 @@
DEFINE_RENAME_SYSREG_WRITE_FUNC(zcr_el3, ZCR_EL3)
DEFINE_RENAME_SYSREG_WRITE_FUNC(zcr_el2, ZCR_EL2)
+DEFINE_RENAME_SYSREG_READ_FUNC(erridr_el1, ERRIDR_EL1)
+DEFINE_RENAME_SYSREG_WRITE_FUNC(errselr_el1, ERRSELR_EL1)
+
+DEFINE_RENAME_SYSREG_READ_FUNC(erxfr_el1, ERXFR_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(erxctlr_el1, ERXCTLR_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(erxstatus_el1, ERXSTATUS_EL1)
+DEFINE_RENAME_SYSREG_READ_FUNC(erxaddr_el1, ERXADDR_EL1)
+DEFINE_RENAME_SYSREG_READ_FUNC(erxmisc0_el1, ERXMISC0_EL1)
+DEFINE_RENAME_SYSREG_READ_FUNC(erxmisc1_el1, ERXMISC1_EL1)
+
#define IS_IN_EL(x) \
(GET_EL(read_CurrentEl()) == MODE_EL##x)
diff --git a/include/lib/cpus/aarch64/cpu_macros.S b/include/lib/cpus/aarch64/cpu_macros.S
index 8f0a74f..bfe2449 100644
--- a/include/lib/cpus/aarch64/cpu_macros.S
+++ b/include/lib/cpus/aarch64/cpu_macros.S
@@ -230,6 +230,7 @@
/* Check whether errata applies */
mov x0, \_rev_var
+ /* Shall clobber: x0-x7 */
bl check_errata_\_id
.ifeq \_chosen
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index 5f6bdc9..cdd74a3 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -7,6 +7,8 @@
#ifndef __CONTEXT_H__
#define __CONTEXT_H__
+#include <utils_def.h>
+
/*******************************************************************************
* Constants that allow assembler code to access members of and the 'gp_regs'
* structure at their correct offsets.
@@ -53,10 +55,12 @@
******************************************************************************/
#define CTX_EL3STATE_OFFSET (CTX_GPREGS_OFFSET + CTX_GPREGS_END)
#define CTX_SCR_EL3 U(0x0)
-#define CTX_RUNTIME_SP U(0x8)
-#define CTX_SPSR_EL3 U(0x10)
-#define CTX_ELR_EL3 U(0x18)
-#define CTX_EL3STATE_END U(0x20)
+#define CTX_ESR_EL3 U(0x8)
+#define CTX_RUNTIME_SP U(0x10)
+#define CTX_SPSR_EL3 U(0x18)
+#define CTX_ELR_EL3 U(0x20)
+#define CTX_UNUSED U(0x28)
+#define CTX_EL3STATE_END U(0x30)
/*******************************************************************************
* Constants that allow assembler code to access members of and the
diff --git a/include/lib/extensions/ras.h b/include/lib/extensions/ras.h
new file mode 100644
index 0000000..f57fc3a
--- /dev/null
+++ b/include/lib/extensions/ras.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __RAS_COMMON__
+#define __RAS_COMMON__
+
+#define ERR_HANDLER_VERSION 1
+
+/* Error record access mechanism */
+#define ERR_ACCESS_SYSREG 0
+#define ERR_ACCESS_MEMMAP 1
+
+/*
+ * Register all error records on the platform.
+ *
+ * This macro must be used in the same file as the array of error record info
+ * are declared. Only then would ARRAY_SIZE() yield a meaningful value.
+ */
+#define REGISTER_ERR_RECORD_INFO(_records) \
+ const struct err_record_mapping err_record_mapping = { \
+ .err_records = _records, \
+ .num_err_records = ARRAY_SIZE(_records), \
+ }
+
+/* Error record info iterator */
+#define for_each_err_record_info(_i, _info) \
+ for (_i = 0, _info = err_record_mapping.err_records; \
+ _i < err_record_mapping.num_err_records; \
+ _i++, _info++)
+
+#define _ERR_RECORD_COMMON(_probe, _handler, _aux) \
+ .probe = _probe, \
+ .handler = _handler, \
+ .aux_data = _aux,
+
+#define ERR_RECORD_SYSREG_V1(_idx_start, _num_idx, _probe, _handler, _aux) \
+ { \
+ .version = 1, \
+ .sysreg.idx_start = _idx_start, \
+ .sysreg.num_idx = _num_idx, \
+ .access = ERR_ACCESS_SYSREG, \
+ _ERR_RECORD_COMMON(_probe, _handler, _aux) \
+ }
+
+#define ERR_RECORD_MEMMAP_V1(_base_addr, _size_num_k, _probe, _handler, _aux) \
+ { \
+ .version = 1, \
+ .memmap.base_addr = _base_addr, \
+ .memmap.size_num_k = _size_num_k, \
+ .access = ERR_ACCESS_MEMMAP, \
+ _ERR_RECORD_COMMON(_probe, _handler, _aux) \
+ }
+
+/*
+ * Macro to be used to name and declare an array of RAS interrupts along with
+ * their handlers.
+ *
+ * This macro must be used in the same file as the array of interrupts are
+ * declared. Only then would ARRAY_SIZE() yield a meaningful value. Also, the
+ * array is expected to be sorted in the increasing order of interrupt number.
+ */
+#define REGISTER_RAS_INTERRUPTS(_array) \
+ const struct ras_interrupt_mapping ras_interrupt_mapping = { \
+ .intrs = _array, \
+ .num_intrs = ARRAY_SIZE(_array), \
+ }
+
+#ifndef __ASSEMBLY__
+
+#include <assert.h>
+#include <ras_arch.h>
+
+struct err_record_info;
+
+struct ras_interrupt {
+ /* Interrupt number, and the associated error record info */
+ unsigned int intr_number;
+ struct err_record_info *err_record;
+ void *cookie;
+};
+
+/* Function to probe a error record group for error */
+typedef int (*err_record_probe_t)(const struct err_record_info *info,
+ int *probe_data);
+
+/* Data passed to error record group handler */
+struct err_handler_data {
+ /* Info passed on from top-level exception handler */
+ uint64_t flags;
+ void *cookie;
+ void *handle;
+
+ /* Data structure version */
+ unsigned int version;
+
+ /* Reason for EA: one the ERROR_* constants */
+ unsigned int ea_reason;
+
+ /*
+ * For EAs received at vector, the value read from ESR; for an EA
+ * synchronized by ESB, the value of DISR.
+ */
+ uint32_t syndrome;
+
+ /* For errors signalled via. interrupt, the raw interrupt ID; otherwise, 0. */
+ unsigned int interrupt;
+};
+
+/* Function to handle error from an error record group */
+typedef int (*err_record_handler_t)(const struct err_record_info *info,
+ int probe_data, const struct err_handler_data *const data);
+
+/* Error record information */
+struct err_record_info {
+ /* Function to probe error record group for errors */
+ err_record_probe_t probe;
+
+ /* Function to handle error record group errors */
+ err_record_handler_t handler;
+
+ /* Opaque group-specific data */
+ void *aux_data;
+
+ /* Additional information for Standard Error Records */
+ union {
+ struct {
+ /*
+ * For a group accessed via. memory-mapped register,
+ * base address of the page hosting error records, and
+ * the size of the record group.
+ */
+ uintptr_t base_addr;
+
+ /* Size of group in number of KBs */
+ unsigned int size_num_k;
+ } memmap;
+
+ struct {
+ /*
+ * For error records accessed via. system register, index of
+ * the error record.
+ */
+ unsigned int idx_start;
+ unsigned int num_idx;
+ } sysreg;
+ };
+
+ /* Data structure version */
+ unsigned int version;
+
+ /* Error record access mechanism */
+ unsigned int access:1;
+};
+
+struct err_record_mapping {
+ struct err_record_info *err_records;
+ size_t num_err_records;
+};
+
+struct ras_interrupt_mapping {
+ struct ras_interrupt *intrs;
+ size_t num_intrs;
+};
+
+extern const struct err_record_mapping err_record_mapping;
+extern const struct ras_interrupt_mapping ras_interrupt_mapping;
+
+
+/*
+ * Helper functions to probe memory-mapped and system registers implemented in
+ * Standard Error Record format
+ */
+static inline int ras_err_ser_probe_memmap(const struct err_record_info *info,
+ int *probe_data)
+{
+ assert(info->version == ERR_HANDLER_VERSION);
+
+ return ser_probe_memmap(info->memmap.base_addr, info->memmap.size_num_k,
+ probe_data);
+}
+
+static inline int ras_err_ser_probe_sysreg(const struct err_record_info *info,
+ int *probe_data)
+{
+ assert(info->version == ERR_HANDLER_VERSION);
+
+ return ser_probe_sysreg(info->sysreg.idx_start, info->sysreg.num_idx,
+ probe_data);
+}
+
+int ras_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
+ void *handle, uint64_t flags);
+void ras_init(void);
+
+#endif /* __ASSEMBLY__ */
+#endif /* __RAS_COMMON__ */
diff --git a/include/lib/extensions/ras_arch.h b/include/lib/extensions/ras_arch.h
new file mode 100644
index 0000000..7d21053
--- /dev/null
+++ b/include/lib/extensions/ras_arch.h
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __RAS_H__
+#define __RAS_H__
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <context.h>
+#include <mmio.h>
+#include <stdint.h>
+
+/*
+ * Size of nodes implementing Standard Error Records - currently only 4k is
+ * supported.
+ */
+#define STD_ERR_NODE_SIZE_NUM_K 4
+
+/*
+ * Individual register offsets within an error record in Standard Error Record
+ * format when error records are accessed through memory-mapped registers.
+ */
+#define ERR_FR(n) (0x0 + (64 * (n)))
+#define ERR_CTLR(n) (0x8 + (64 * (n)))
+#define ERR_STATUS(n) (0x10 + (64 * (n)))
+#define ERR_ADDR(n) (0x18 + (64 * (n)))
+#define ERR_MISC0(n) (0x20 + (64 * (n)))
+#define ERR_MISC1(n) (0x28 + (64 * (n)))
+
+/* Group Status Register (ERR_STATUS) offset */
+#define ERR_GSR(base, size_num_k, n) \
+ ((base) + (0x380 * (size_num_k)) + (8 * (n)))
+
+/* Management register offsets */
+#define ERR_DEVID(base, size_num_k) \
+ ((base) + ((0x400 * (size_num_k)) - 0x100) + 0xc8)
+
+#define ERR_DEVID_MASK 0xffff
+
+/* Standard Error Record status register fields */
+#define ERR_STATUS_AV_SHIFT 31
+#define ERR_STATUS_AV_MASK U(0x1)
+
+#define ERR_STATUS_V_SHIFT 30
+#define ERR_STATUS_V_MASK U(0x1)
+
+#define ERR_STATUS_UE_SHIFT 29
+#define ERR_STATUS_UE_MASK U(0x1)
+
+#define ERR_STATUS_ER_SHIFT 28
+#define ERR_STATUS_ER_MASK U(0x1)
+
+#define ERR_STATUS_OF_SHIFT 27
+#define ERR_STATUS_OF_MASK U(0x1)
+
+#define ERR_STATUS_MV_SHIFT 26
+#define ERR_STATUS_MV_MASK U(0x1)
+
+#define ERR_STATUS_CE_SHIFT 24
+#define ERR_STATUS_CE_MASK U(0x3)
+
+#define ERR_STATUS_DE_SHIFT 23
+#define ERR_STATUS_DE_MASK U(0x1)
+
+#define ERR_STATUS_PN_SHIFT 22
+#define ERR_STATUS_PN_MASK U(0x1)
+
+#define ERR_STATUS_UET_SHIFT 20
+#define ERR_STATUS_UET_MASK U(0x3)
+
+#define ERR_STATUS_IERR_SHIFT 8
+#define ERR_STATUS_IERR_MASK U(0xff)
+
+#define ERR_STATUS_SERR_SHIFT 0
+#define ERR_STATUS_SERR_MASK U(0xff)
+
+#define ERR_STATUS_GET_FIELD(_status, _field) \
+ (((_status) >> ERR_STATUS_ ##_field ##_SHIFT) & ERR_STATUS_ ##_field ##_MASK)
+
+#define ERR_STATUS_CLR_FIELD(_status, _field) \
+ (_status) &= ~(ERR_STATUS_ ##_field ##_MASK << ERR_STATUS_ ##_field ##_SHIFT)
+
+#define ERR_STATUS_SET_FIELD(_status, _field, _value) \
+ (_status) |= (((_value) & ERR_STATUS_ ##_field ##_MASK) << ERR_STATUS_ ##_field ##_SHIFT)
+
+#define ERR_STATUS_WRITE_FIELD(_status, _field, _value) do { \
+ ERR_STATUS_CLR_FIELD(_status, _field, _value); \
+ ERR_STATUS_SET_FIELD(_status, _field, _value); \
+ } while (0)
+
+
+/* Standard Error Record control register fields */
+#define ERR_CTLR_WDUI_SHIFT 11
+#define ERR_CTLR_WDUI_MASK 0x1
+
+#define ERR_CTLR_RDUI_SHIFT 10
+#define ERR_CTLR_RDUI_MASK 0x1
+#define ERR_CTLR_DUI_SHIFT ERR_CTLR_RDUI_SHIFT
+#define ERR_CTLR_DUI_MASK ERR_CTLR_RDUI_MASK
+
+#define ERR_CTLR_WCFI_SHIFT 9
+#define ERR_CTLR_WCFI_MASK 0x1
+
+#define ERR_CTLR_RCFI_SHIFT 8
+#define ERR_CTLR_RCFI_MASK 0x1
+#define ERR_CTLR_CFI_SHIFT ERR_CTLR_RCFI_SHIFT
+#define ERR_CTLR_CFI_MASK ERR_CTLR_RCFI_MASK
+
+#define ERR_CTLR_WUE_SHIFT 7
+#define ERR_CTLR_WUE_MASK 0x1
+
+#define ERR_CTLR_WFI_SHIFT 6
+#define ERR_CTLR_WFI_MASK 0x1
+
+#define ERR_CTLR_WUI_SHIFT 5
+#define ERR_CTLR_WUI_MASK 0x1
+
+#define ERR_CTLR_RUE_SHIFT 4
+#define ERR_CTLR_RUE_MASK 0x1
+#define ERR_CTLR_UE_SHIFT ERR_CTLR_RUE_SHIFT
+#define ERR_CTLR_UE_MASK ERR_CTLR_RUE_MASK
+
+#define ERR_CTLR_RFI_SHIFT 3
+#define ERR_CTLR_RFI_MASK 0x1
+#define ERR_CTLR_FI_SHIFT ERR_CTLR_RFI_SHIFT
+#define ERR_CTLR_FI_MASK ERR_CTLR_RFI_MASK
+
+#define ERR_CTLR_RUI_SHIFT 2
+#define ERR_CTLR_RUI_MASK 0x1
+#define ERR_CTLR_UI_SHIFT ERR_CTLR_RUI_SHIFT
+#define ERR_CTLR_UI_MASK ERR_CTLR_RUI_MASK
+
+#define ERR_CTLR_ED_SHIFT 0
+#define ERR_CTLR_ED_MASK 0x1
+
+#define ERR_CTLR_CLR_FIELD(_ctlr, _field) \
+ (_ctlr) &= ~(ERR_CTLR_ ##_field _MASK << ERR_CTLR_ ##_field ##_SHIFT)
+
+#define ERR_CTLR_SET_FIELD(_ctlr, _field, _value) \
+ (_ctlr) |= (((_value) & ERR_CTLR_ ##_field ##_MASK) << ERR_CTLR_ ##_field ##_SHIFT)
+
+#define ERR_CTLR_ENABLE_FIELD(_ctlr, _field) \
+ ERR_CTLR_SET_FIELD(_ctlr, _field, ERR_CTLR_ ##_field ##_MASK)
+
+/* Uncorrected error types */
+#define ERROR_STATUS_UET_UC 0x0 /* Uncontainable */
+#define ERROR_STATUS_UET_UEU 0x1 /* Unrecoverable */
+#define ERROR_STATUS_UET_UEO 0x2 /* Restable */
+#define ERROR_STATUS_UET_UER 0x3 /* Recoverable */
+
+
+/*
+ * Standard Error Record accessors for memory-mapped registers.
+ */
+
+static inline uint64_t ser_get_feature(uintptr_t base, unsigned int idx)
+{
+ return mmio_read_64(base + ERR_FR(idx));
+}
+
+static inline uint64_t ser_get_control(uintptr_t base, unsigned int idx)
+{
+ return mmio_read_64(base + ERR_CTLR(idx));
+}
+
+static inline uint64_t ser_get_status(uintptr_t base, unsigned int idx)
+{
+ return mmio_read_64(base + ERR_STATUS(idx));
+}
+
+/*
+ * Error handling agent would write to the status register to clear an
+ * identified/handled error. Most fields in the status register are
+ * conditional write-one-to-clear.
+ *
+ * Typically, to clear the status, it suffices to write back the same value
+ * previously read. However, if there were new, higher-priority errors recorded
+ * on the node since status was last read, writing read value won't clear the
+ * status. Therefore, an error handling agent must wait on and verify the status
+ * has indeed been cleared.
+ */
+static inline void ser_set_status(uintptr_t base, unsigned int idx,
+ uint64_t status)
+{
+ mmio_write_64(base + ERR_STATUS(idx), status);
+}
+
+static inline uint64_t ser_get_addr(uintptr_t base, unsigned int idx)
+{
+ return mmio_read_64(base + ERR_ADDR(idx));
+}
+
+static inline uint64_t ser_get_misc0(uintptr_t base, unsigned int idx)
+{
+ return mmio_read_64(base + ERR_MISC0(idx));
+}
+
+static inline uint64_t ser_get_misc1(uintptr_t base, unsigned int idx)
+{
+ return mmio_read_64(base + ERR_MISC1(idx));
+}
+
+
+/*
+ * Standard Error Record helpers for System registers.
+ */
+static inline void ser_sys_select_record(unsigned int idx)
+{
+ unsigned int max_idx __unused = read_erridr_el1() & ERRIDR_MASK;
+
+ assert(idx < max_idx);
+
+ write_errselr_el1(idx);
+ isb();
+}
+
+/* Library functions to probe Standard Error Record */
+int ser_probe_memmap(uintptr_t base, unsigned int size_num_k, int *probe_data);
+int ser_probe_sysreg(unsigned int idx_start, unsigned int num_idx, int *probe_data);
+
+#endif /* __RAS_H__ */
diff --git a/include/lib/smccc.h b/include/lib/smccc.h
index d683420..660c1db 100644
--- a/include/lib/smccc.h
+++ b/include/lib/smccc.h
@@ -9,83 +9,43 @@
#include <utils_def.h>
-/*******************************************************************************
- * Bit definitions inside the function id as per the SMC calling convention
- ******************************************************************************/
-#define FUNCID_TYPE_SHIFT U(31)
-#define FUNCID_CC_SHIFT U(30)
-#define FUNCID_OEN_SHIFT U(24)
-#define FUNCID_NUM_SHIFT U(0)
+#define SMCCC_VERSION_MAJOR_SHIFT U(16)
+#define SMCCC_VERSION_MAJOR_MASK U(0x7FFF)
+#define SMCCC_VERSION_MINOR_SHIFT U(0)
+#define SMCCC_VERSION_MINOR_MASK U(0xFFFF)
+#define MAKE_SMCCC_VERSION(_major, _minor) \
+ ((((uint32_t)(_major) & SMCCC_VERSION_MAJOR_MASK) << \
+ SMCCC_VERSION_MAJOR_SHIFT) \
+ | (((uint32_t)(_minor) & SMCCC_VERSION_MINOR_MASK) << \
+ SMCCC_VERSION_MINOR_SHIFT))
-#define FUNCID_TYPE_MASK U(0x1)
-#define FUNCID_CC_MASK U(0x1)
-#define FUNCID_OEN_MASK U(0x3f)
-#define FUNCID_NUM_MASK U(0xffff)
-
-#define FUNCID_TYPE_WIDTH U(1)
-#define FUNCID_CC_WIDTH U(1)
-#define FUNCID_OEN_WIDTH U(6)
-#define FUNCID_NUM_WIDTH U(16)
-
-#define GET_SMC_CC(id) ((id >> FUNCID_CC_SHIFT) & \
- FUNCID_CC_MASK)
-#define GET_SMC_TYPE(id) ((id >> FUNCID_TYPE_SHIFT) & \
- FUNCID_TYPE_MASK)
-
-#define SMC_64 U(1)
-#define SMC_32 U(0)
-#define SMC_OK U(0)
-#define SMC_UNK -1
-#define SMC_TYPE_FAST ULL(1)
-#if !ERROR_DEPRECATED
-#define SMC_TYPE_STD ULL(0)
+#if SMCCC_MAJOR_VERSION == 1
+# define SMCCC_MINOR_VERSION U(1)
+# include <smccc_v1.h>
+#elif SMCCC_MAJOR_VERSION == 2
+# define SMCCC_MINOR_VERSION U(0)
+# include <smccc_v2.h>
+#else
+# error "Unsupported version of SMCCC."
#endif
-#define SMC_TYPE_YIELD U(0)
-#define SMC_PREEMPTED -2
-/*******************************************************************************
- * Owning entity number definitions inside the function id as per the SMC
- * calling convention
- ******************************************************************************/
-#define OEN_ARM_START U(0)
-#define OEN_ARM_END U(0)
-#define OEN_CPU_START U(1)
-#define OEN_CPU_END U(1)
-#define OEN_SIP_START U(2)
-#define OEN_SIP_END U(2)
-#define OEN_OEM_START U(3)
-#define OEN_OEM_END U(3)
-#define OEN_STD_START U(4) /* Standard Service Calls */
-#define OEN_STD_END U(4)
-#define OEN_TAP_START U(48) /* Trusted Applications */
-#define OEN_TAP_END U(49)
-#define OEN_TOS_START U(50) /* Trusted OS */
-#define OEN_TOS_END U(63)
-#define OEN_LIMIT U(64)
+
+/* Various flags passed to SMC handlers */
+#define SMC_FROM_SECURE (U(0) << 0)
+#define SMC_FROM_NON_SECURE (U(1) << 0)
#ifndef __ASSEMBLY__
#include <cassert.h>
#include <stdint.h>
-#define SMCCC_MAJOR_VERSION U(1)
-#define SMCCC_MINOR_VERSION U(1)
-
-#define MAKE_SMCCC_VERSION(_major, _minor) (((_major) << 16) | (_minor))
-
-/* Various flags passed to SMC handlers */
-#define SMC_FROM_SECURE (U(0) << 0)
-#define SMC_FROM_NON_SECURE (U(1) << 0)
-
-#define is_caller_non_secure(_f) (!!(_f & SMC_FROM_NON_SECURE))
-#define is_caller_secure(_f) (!(is_caller_non_secure(_f)))
+#define is_caller_non_secure(_f) (((_f) & SMC_FROM_NON_SECURE) != U(0))
+#define is_caller_secure(_f) (!is_caller_non_secure(_f))
/* The macro below is used to identify a Standard Service SMC call */
-#define is_std_svc_call(_fid) ((((_fid) >> FUNCID_OEN_SHIFT) & \
- FUNCID_OEN_MASK) == OEN_STD_START)
+#define is_std_svc_call(_fid) (GET_SMC_OEN(_fid) == OEN_STD_START)
/* The macro below is used to identify a Arm Architectural Service SMC call */
-#define is_arm_arch_svc_call(_fid) ((((_fid) >> FUNCID_OEN_SHIFT) & \
- FUNCID_OEN_MASK) == OEN_ARM_START)
+#define is_arm_arch_svc_call(_fid) (GET_SMC_OEN(_fid) == OEN_ARM_START)
/* The macro below is used to identify a valid Fast SMC call */
#define is_valid_fast_smc(_fid) ((!(((_fid) >> 16) & U(0xff))) && \
diff --git a/include/lib/smccc_v1.h b/include/lib/smccc_v1.h
new file mode 100644
index 0000000..8718d15
--- /dev/null
+++ b/include/lib/smccc_v1.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SMCCC_V1_H
+#define SMCCC_V1_H
+
+#ifndef __SMCCC_H__
+#error "This file must only be included from smccc.h"
+#endif
+
+/*******************************************************************************
+ * Bit definitions inside the function id as per the SMC calling convention
+ ******************************************************************************/
+#define FUNCID_TYPE_SHIFT U(31)
+#define FUNCID_TYPE_MASK U(0x1)
+#define FUNCID_TYPE_WIDTH U(1)
+
+#define FUNCID_CC_SHIFT U(30)
+#define FUNCID_CC_MASK U(0x1)
+#define FUNCID_CC_WIDTH U(1)
+
+#define FUNCID_OEN_SHIFT U(24)
+#define FUNCID_OEN_MASK U(0x3f)
+#define FUNCID_OEN_WIDTH U(6)
+
+#define FUNCID_NUM_SHIFT U(0)
+#define FUNCID_NUM_MASK U(0xffff)
+#define FUNCID_NUM_WIDTH U(16)
+
+#define GET_SMC_TYPE(id) (((id) >> FUNCID_TYPE_SHIFT) & \
+ FUNCID_TYPE_MASK)
+#define GET_SMC_CC(id) (((id) >> FUNCID_CC_SHIFT) & \
+ FUNCID_CC_MASK)
+#define GET_SMC_OEN(id) (((id) >> FUNCID_OEN_SHIFT) & \
+ FUNCID_OEN_MASK)
+
+/*******************************************************************************
+ * Owning entity number definitions inside the function id as per the SMC
+ * calling convention
+ ******************************************************************************/
+#define OEN_ARM_START U(0)
+#define OEN_ARM_END U(0)
+#define OEN_CPU_START U(1)
+#define OEN_CPU_END U(1)
+#define OEN_SIP_START U(2)
+#define OEN_SIP_END U(2)
+#define OEN_OEM_START U(3)
+#define OEN_OEM_END U(3)
+#define OEN_STD_START U(4) /* Standard Service Calls */
+#define OEN_STD_END U(4)
+#define OEN_STD_HYP_START U(5) /* Standard Hypervisor Service calls */
+#define OEN_STD_HYP_END U(5)
+#define OEN_VEN_HYP_START U(6) /* Vendor Hypervisor Service calls */
+#define OEN_VEN_HYP_END U(6)
+#define OEN_TAP_START U(48) /* Trusted Applications */
+#define OEN_TAP_END U(49)
+#define OEN_TOS_START U(50) /* Trusted OS */
+#define OEN_TOS_END U(63)
+#define OEN_LIMIT U(64)
+
+/* Flags and error codes */
+#define SMC_64 U(1)
+#define SMC_32 U(0)
+
+#define SMC_TYPE_FAST ULL(1)
+#if !ERROR_DEPRECATED
+#define SMC_TYPE_STD ULL(0)
+#endif
+#define SMC_TYPE_YIELD ULL(0)
+
+#define SMC_OK ULL(0)
+#define SMC_UNK -1
+#define SMC_PREEMPTED -2 /* Not defined by the SMCCC */
+
+#endif /* SMCCC_V1_H */
diff --git a/include/lib/smccc_v2.h b/include/lib/smccc_v2.h
new file mode 100644
index 0000000..628c160
--- /dev/null
+++ b/include/lib/smccc_v2.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SMCCC_V2_H
+#define SMCCC_V2_H
+
+#ifndef __SMCCC_H__
+#error "This file must only be included from smccc.h"
+#endif
+
+/*******************************************************************************
+ * Bit definitions inside the function id as per the SMC calling convention
+ ******************************************************************************/
+#define FUNCID_TYPE_SHIFT U(31)
+#define FUNCID_TYPE_MASK U(0x1)
+#define FUNCID_TYPE_WIDTH U(1)
+
+#define FUNCID_CC_SHIFT U(30)
+#define FUNCID_CC_MASK U(0x1)
+#define FUNCID_CC_WIDTH U(1)
+
+#define FUNCID_NAMESPACE_SHIFT U(28)
+#define FUNCID_NAMESPACE_MASK U(0x3)
+#define FUNCID_NAMESPACE_WIDTH U(2)
+
+#define FUNCID_OEN_SHIFT U(24)
+#define FUNCID_OEN_MASK U(0xf)
+#define FUNCID_OEN_WIDTH U(4)
+
+#define FUNCID_NUM_SHIFT U(0)
+#define FUNCID_NUM_MASK U(0xffff)
+#define FUNCID_NUM_WIDTH U(16)
+
+#define GET_SMC_TYPE(id) (((id) >> FUNCID_TYPE_SHIFT) & \
+ FUNCID_TYPE_MASK)
+#define GET_SMC_CC(id) (((id) >> FUNCID_CC_SHIFT) & \
+ FUNCID_CC_MASK)
+#define GET_SMC_NAMESPACE(id) (((id) >> FUNCID_NAMESPACE_SHIFT) & \
+ FUNCID_NAMESPACE_MASK)
+#define GET_SMC_OEN(id) (((id) >> FUNCID_OEN_SHIFT) & \
+ FUNCID_OEN_MASK)
+
+/*******************************************************************************
+ * Owning entity number definitions inside the function id as per the SMC
+ * calling convention
+ ******************************************************************************/
+#define OEN_ARM_START U(0)
+#define OEN_ARM_END U(0)
+#define OEN_CPU_START U(1)
+#define OEN_CPU_END U(1)
+#define OEN_SIP_START U(2)
+#define OEN_SIP_END U(2)
+#define OEN_OEM_START U(3)
+#define OEN_OEM_END U(3)
+#define OEN_STD_START U(4) /* Standard Service Calls */
+#define OEN_STD_END U(4)
+#define OEN_STD_HYP_START U(5) /* Standard Hypervisor Service calls */
+#define OEN_STD_HYP_END U(5)
+#define OEN_VEN_HYP_START U(6) /* Vendor Hypervisor Service calls */
+#define OEN_VEN_HYP_END U(6)
+#define OEN_LIMIT U(16)
+
+/*******************************************************************************
+ * Service namespaces as per the SMC Calling Convention v2.X
+ ******************************************************************************/
+#define FUNCID_NAMESPACE_START U(0)
+#define FUNCID_NAMESPACE_COMPAT U(0)
+#define FUNCID_NAMESPACE_VENDOR U(1)
+#define FUNCID_NAMESPACE_SPRT U(2)
+#define FUNCID_NAMESPACE_SPCI U(3)
+#define FUNCID_NAMESPACE_LIMIT U(4)
+
+/* Flags and error codes */
+#define SMC_64 U(1)
+#define SMC_32 U(0)
+
+#define SMC_TYPE_FAST ULL(1)
+
+#define SMC_OK ULL(0)
+#define SMC_UNK -1
+
+#endif /* SMCCC_V2_H */
diff --git a/include/lib/stdlib/machine/_types.h b/include/lib/stdlib/machine/_types.h
index fb1083b..037fdf2 100644
--- a/include/lib/stdlib/machine/_types.h
+++ b/include/lib/stdlib/machine/_types.h
@@ -52,56 +52,19 @@
typedef unsigned short __uint16_t;
typedef int __int32_t;
typedef unsigned int __uint32_t;
-
-
-/*
- * Standard type definitions which are different in AArch64 and AArch32
- */
-#ifdef AARCH32
typedef long long __int64_t;
typedef unsigned long long __uint64_t;
-typedef __int32_t __critical_t;
-typedef __int32_t __intfptr_t;
-typedef __int32_t __intptr_t;
-typedef __int32_t __ptrdiff_t; /* ptr1 - ptr2 */
-typedef __int32_t __register_t;
-typedef __int32_t __segsz_t; /* segment size (in pages) */
-typedef __uint32_t __size_t; /* sizeof() */
-typedef __int32_t __ssize_t; /* byte count or error */
-typedef __uint32_t __uintfptr_t;
-typedef __uint32_t __uintptr_t;
-typedef __uint32_t __u_register_t;
-typedef __uint32_t __vm_offset_t;
-typedef __uint32_t __vm_paddr_t;
-typedef __uint32_t __vm_size_t;
-#elif defined AARCH64
-typedef long __int64_t;
-typedef unsigned long __uint64_t;
-typedef __int64_t __critical_t;
-typedef __int64_t __intfptr_t;
-typedef __int64_t __intptr_t;
-typedef __int64_t __ptrdiff_t; /* ptr1 - ptr2 */
-typedef __int64_t __register_t;
-typedef __int64_t __segsz_t; /* segment size (in pages) */
-typedef __uint64_t __size_t; /* sizeof() */
-typedef __int64_t __ssize_t; /* byte count or error */
-typedef __uint64_t __uintfptr_t;
-typedef __uint64_t __uintptr_t;
-typedef __uint64_t __u_register_t;
-typedef __uint64_t __vm_offset_t;
-typedef __uint64_t __vm_paddr_t;
-typedef __uint64_t __vm_size_t;
-#else
-#error "Only AArch32 or AArch64 supported"
-#endif /* AARCH32 */
/*
* Standard type definitions.
*/
typedef __int32_t __clock_t; /* clock()... */
+typedef long __critical_t;
typedef double __double_t;
typedef float __float_t;
+typedef long __intfptr_t;
typedef __int64_t __intmax_t;
+typedef long __intptr_t;
typedef __int32_t __int_fast8_t;
typedef __int32_t __int_fast16_t;
typedef __int32_t __int_fast32_t;
@@ -110,8 +73,22 @@
typedef __int16_t __int_least16_t;
typedef __int32_t __int_least32_t;
typedef __int64_t __int_least64_t;
+typedef long __ptrdiff_t; /* ptr1 - ptr2 */
+typedef long __register_t;
+typedef long __segsz_t; /* segment size (in pages) */
+#ifdef AARCH32
+typedef unsigned int __size_t; /* sizeof() */
+typedef int __ssize_t; /* byte count or error */
+#elif defined AARCH64
+typedef unsigned long __size_t; /* sizeof() */
+typedef long __ssize_t; /* byte count or error */
+#else
+#error "Only AArch32 or AArch64 supported"
+#endif /* AARCH32 */
typedef __int64_t __time_t; /* time()... */
+typedef unsigned long __uintfptr_t;
typedef __uint64_t __uintmax_t;
+typedef unsigned long __uintptr_t;
typedef __uint32_t __uint_fast8_t;
typedef __uint32_t __uint_fast16_t;
typedef __uint32_t __uint_fast32_t;
@@ -120,8 +97,12 @@
typedef __uint16_t __uint_least16_t;
typedef __uint32_t __uint_least32_t;
typedef __uint64_t __uint_least64_t;
+typedef unsigned long __u_register_t;
+typedef unsigned long __vm_offset_t;
typedef __int64_t __vm_ooffset_t;
+typedef unsigned long __vm_paddr_t;
typedef __uint64_t __vm_pindex_t;
+typedef unsigned long __vm_size_t;
/*
* Unusual type definitions.
diff --git a/include/lib/utils.h b/include/lib/utils.h
index 3d215c3..f367a1f 100644
--- a/include/lib/utils.h
+++ b/include/lib/utils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -29,6 +29,18 @@
*/
void clear_mem_regions(mem_region_t *tbl, size_t nregions);
+/*
+ * zero_normalmem all the regions defined in region. It dynamically
+ * maps chunks of 'chunk_size' in 'va' virtual address and clears them.
+ * For this reason memory regions must be multiple of chunk_size and
+ * must be aligned to it as well. chunk_size and va can be selected
+ * in a way that they minimize the number of entries used in the
+ * translation tables.
+ */
+void clear_map_dyn_mem_regions(mem_region_t *region,
+ size_t nregions,
+ uintptr_t va,
+ size_t chunk_size);
/*
* checks that a region (addr + nbytes-1) of memory is totally covered by
diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h
index 8abc73c..31b1294 100644
--- a/include/lib/utils_def.h
+++ b/include/lib/utils_def.h
@@ -68,6 +68,13 @@
(((ptr) > UINTPTR_MAX - (inc)) ? 1 : 0)
/*
+ * Evaluates to 1 if (u32 + inc) overflows, 0 otherwise.
+ * Both arguments must be 32-bit unsigned integers (i.e. effectively uint32_t).
+ */
+#define check_u32_overflow(u32, inc) \
+ ((u32) > (UINT32_MAX - (inc)) ? 1 : 0)
+
+/*
* For those constants to be shared between C and other sources, apply a 'u'
* or 'ull' suffix to the argument only in C, to avoid undefined or unintended
* behaviour.
diff --git a/include/lib/xlat_tables/xlat_tables_arch.h b/include/lib/xlat_tables/xlat_tables_arch.h
index 165b161d..af8c463 100644
--- a/include/lib/xlat_tables/xlat_tables_arch.h
+++ b/include/lib/xlat_tables/xlat_tables_arch.h
@@ -21,8 +21,8 @@
* limits. Not that these limits are different for AArch32 and AArch64.
*/
#define CHECK_VIRT_ADDR_SPACE_SIZE(size) \
- (((size) >= MIN_VIRT_ADDR_SPACE_SIZE) && \
- ((size) <= MAX_VIRT_ADDR_SPACE_SIZE) && \
+ (((unsigned long long)(size) >= MIN_VIRT_ADDR_SPACE_SIZE) && \
+ ((unsigned long long)(size) <= MAX_VIRT_ADDR_SPACE_SIZE) && \
IS_POWER_OF_TWO(size))
/*
diff --git a/include/lib/xlat_tables/xlat_tables_defs.h b/include/lib/xlat_tables/xlat_tables_defs.h
index 1c84fe0..5eb1d30 100644
--- a/include/lib/xlat_tables/xlat_tables_defs.h
+++ b/include/lib/xlat_tables/xlat_tables_defs.h
@@ -107,10 +107,8 @@
* Permissions bits, and does not define an AP[0] bit.
*
* AP[1] is valid only for a stage 1 translation that supports two VA ranges
- * (i.e. in the ARMv8A.0 architecture, that is the S-EL1&0 regime).
- *
- * AP[1] is RES0 for stage 1 translations that support only one VA range
- * (e.g. EL3).
+ * (i.e. in the ARMv8A.0 architecture, that is the S-EL1&0 regime). It is RES1
+ * when stage 1 translations can only support one VA range.
*/
#define AP2_SHIFT U(0x7)
#define AP2_RO U(0x1)
@@ -119,6 +117,7 @@
#define AP1_SHIFT U(0x6)
#define AP1_ACCESS_UNPRIVILEGED U(0x1)
#define AP1_NO_ACCESS_UNPRIVILEGED U(0x0)
+#define AP1_RES1 U(0x1)
/*
* The following definitions must all be passed to the LOWER_ATTRS() macro to
@@ -128,6 +127,7 @@
#define AP_RW (AP2_RW << 5)
#define AP_ACCESS_UNPRIVILEGED (AP1_ACCESS_UNPRIVILEGED << 4)
#define AP_NO_ACCESS_UNPRIVILEGED (AP1_NO_ACCESS_UNPRIVILEGED << 4)
+#define AP_ONE_VA_RANGE_RES1 (AP1_RES1 << 4)
#define NS (U(0x1) << 3)
#define ATTR_NON_CACHEABLE_INDEX U(0x2)
#define ATTR_DEVICE_INDEX U(0x1)
diff --git a/include/lib/xlat_tables/xlat_tables_v2.h b/include/lib/xlat_tables/xlat_tables_v2.h
index ba3e360..b237945 100644
--- a/include/lib/xlat_tables/xlat_tables_v2.h
+++ b/include/lib/xlat_tables/xlat_tables_v2.h
@@ -299,7 +299,7 @@
* executing.
*/
int change_mem_attributes(xlat_ctx_t *ctx, uintptr_t base_va, size_t size,
- mmap_attr_t attr);
+ uint32_t attr);
/*
* Query the memory attributes of a memory page in a set of translation tables.
@@ -317,7 +317,7 @@
* Output parameter where to store the attributes of the targeted memory page.
*/
int get_mem_attributes(const xlat_ctx_t *ctx, uintptr_t base_va,
- mmap_attr_t *attributes);
+ uint32_t *attributes);
#endif /*__ASSEMBLY__*/
#endif /* __XLAT_TABLES_V2_H__ */
diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h
index 12a21fb..845f140 100644
--- a/include/plat/arm/board/common/board_arm_def.h
+++ b/include/plat/arm/board/common/board_arm_def.h
@@ -30,7 +30,11 @@
#elif defined(IMAGE_BL2U)
# define PLATFORM_STACK_SIZE 0x200
#elif defined(IMAGE_BL31)
+#ifdef PLAT_XLAT_TABLES_DYNAMIC
+# define PLATFORM_STACK_SIZE 0x800
+#else
# define PLATFORM_STACK_SIZE 0x400
+#endif
#elif defined(IMAGE_BL32)
# define PLATFORM_STACK_SIZE 0x440
#endif
@@ -59,11 +63,11 @@
# define PLAT_SP_IMAGE_MMAP_REGIONS 7
# define PLAT_SP_IMAGE_MAX_XLAT_TABLES 10
# else
-# define PLAT_ARM_MMAP_ENTRIES 7
+# define PLAT_ARM_MMAP_ENTRIES 8
# define MAX_XLAT_TABLES 5
# endif
#elif defined(IMAGE_BL32)
-# define PLAT_ARM_MMAP_ENTRIES 7
+# define PLAT_ARM_MMAP_ENTRIES 8
# define MAX_XLAT_TABLES 5
#else
# define PLAT_ARM_MMAP_ENTRIES 11
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 95e986b..4473b53 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -245,10 +245,16 @@
* The number of regions like RO(code), coherent and data required by
* different BL stages which need to be mapped in the MMU.
*/
-#if USE_COHERENT_MEM
-#define ARM_BL_REGIONS 3
+#if ENABLE_SPM && defined(IMAGE_BL31)
+# if USE_COHERENT_MEM
+# define ARM_BL_REGIONS 5
+# else
+# define ARM_BL_REGIONS 4
+# endif
+#elif USE_COHERENT_MEM
+# define ARM_BL_REGIONS 4
#else
-#define ARM_BL_REGIONS 2
+# define ARM_BL_REGIONS 3
#endif
#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + \
@@ -483,6 +489,7 @@
#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE)
/* Priority levels for ARM platforms */
+#define PLAT_RAS_PRI 0x10
#define PLAT_SDEI_CRITICAL_PRI 0x60
#define PLAT_SDEI_NORMAL_PRI 0x70
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index b0db8f0..fc3f4ec 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -11,6 +11,7 @@
#include <cassert.h>
#include <cpu_data.h>
#include <stdint.h>
+#include <tzc_common.h>
#include <utils_def.h>
/*******************************************************************************
@@ -21,9 +22,48 @@
struct image_info;
struct bl_params;
-#define ARM_CASSERT_MMAP \
- CASSERT((ARRAY_SIZE(plat_arm_mmap) + ARM_BL_REGIONS) \
- <= MAX_MMAP_REGIONS, \
+typedef struct arm_tzc_regions_info {
+ unsigned long long base;
+ unsigned long long end;
+ tzc_region_attributes_t sec_attr;
+ unsigned int nsaid_permissions;
+} arm_tzc_regions_info_t;
+
+/*******************************************************************************
+ * Default mapping definition of the TrustZone Controller for ARM standard
+ * platforms.
+ * Configure:
+ * - Region 0 with no access;
+ * - Region 1 with secure access only;
+ * - the remaining DRAM regions access from the given Non-Secure masters.
+ ******************************************************************************/
+#if ENABLE_SPM
+#define ARM_TZC_REGIONS_DEF \
+ {ARM_AP_TZC_DRAM1_BASE, ARM_EL3_TZC_DRAM1_END, \
+ TZC_REGION_S_RDWR, 0}, \
+ {ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \
+ PLAT_ARM_TZC_NS_DEV_ACCESS}, \
+ {ARM_DRAM2_BASE, ARM_DRAM2_END, ARM_TZC_NS_DRAM_S_ACCESS, \
+ PLAT_ARM_TZC_NS_DEV_ACCESS}, \
+ {ARM_SP_IMAGE_NS_BUF_BASE, (ARM_SP_IMAGE_NS_BUF_BASE + \
+ ARM_SP_IMAGE_NS_BUF_SIZE) - 1, TZC_REGION_S_NONE, \
+ PLAT_ARM_TZC_NS_DEV_ACCESS}
+
+#else
+#define ARM_TZC_REGIONS_DEF \
+ {ARM_AP_TZC_DRAM1_BASE, ARM_EL3_TZC_DRAM1_END, \
+ TZC_REGION_S_RDWR, 0}, \
+ {ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \
+ PLAT_ARM_TZC_NS_DEV_ACCESS}, \
+ {ARM_DRAM2_BASE, ARM_DRAM2_END, ARM_TZC_NS_DRAM_S_ACCESS, \
+ PLAT_ARM_TZC_NS_DEV_ACCESS}
+#endif
+
+#define ARM_CASSERT_MMAP \
+ CASSERT((ARRAY_SIZE(plat_arm_mmap) - 1) <= PLAT_ARM_MMAP_ENTRIES, \
+ assert_plat_arm_mmap_mismatch); \
+ CASSERT((PLAT_ARM_MMAP_ENTRIES + ARM_BL_REGIONS) \
+ <= MAX_MMAP_REGIONS, \
assert_max_mmap_regions);
/*
@@ -110,9 +150,10 @@
void arm_io_setup(void);
/* Security utility functions */
-void arm_tzc400_setup(void);
+void arm_tzc400_setup(const arm_tzc_regions_info_t *tzc_regions);
struct tzc_dmc500_driver_data;
-void arm_tzc_dmc500_setup(struct tzc_dmc500_driver_data *plat_driver_data);
+void arm_tzc_dmc500_setup(struct tzc_dmc500_driver_data *plat_driver_data,
+ const arm_tzc_regions_info_t *tzc_regions);
/* Systimer utility function */
void arm_configure_sys_timer(void);
@@ -127,7 +168,8 @@
void arm_program_trusted_mailbox(uintptr_t address);
int arm_psci_read_mem_protect(int *enabled);
int arm_nor_psci_write_mem_protect(int val);
-void arm_nor_psci_do_mem_protect(void);
+void arm_nor_psci_do_static_mem_protect(void);
+void arm_nor_psci_do_dyn_mem_protect(void);
int arm_psci_mem_protect_chk(uintptr_t base, u_register_t length);
/* Topology utility function */
diff --git a/include/plat/arm/css/common/css_def.h b/include/plat/arm/css/common/css_def.h
index a2c0b4e..6d68b44 100644
--- a/include/plat/arm/css/common/css_def.h
+++ b/include/plat/arm/css/common/css_def.h
@@ -22,9 +22,6 @@
#define CSS_DEVICE_BASE 0x20000000
#define CSS_DEVICE_SIZE 0x0e000000
-#define NSRAM_BASE 0x2e000000
-#define NSRAM_SIZE 0x00008000
-
/* System Security Control Registers */
#define SSC_REG_BASE 0x2a420000
#define SSC_GPRETN (SSC_REG_BASE + 0x030)
@@ -102,7 +99,7 @@
#define CSS_MAP_NSRAM MAP_REGION_FLAT( \
NSRAM_BASE, \
NSRAM_SIZE, \
- MT_DEVICE | MT_RW | MT_SECURE)
+ MT_DEVICE | MT_RW | MT_NS)
/* Platform ID address */
#define SSC_VERSION_OFFSET 0x040
@@ -172,7 +169,7 @@
#endif /* CSS_LOAD_SCP_IMAGES */
/* Load address of Non-Secure Image for CSS platform ports */
-#define PLAT_ARM_NS_IMAGE_OFFSET 0xE0000000
+#define PLAT_ARM_NS_IMAGE_OFFSET U(0xE0000000)
/* TZC related constants */
#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT_ALL
diff --git a/include/plat/common/common_def.h b/include/plat/common/common_def.h
index 84923b9..827d416 100644
--- a/include/plat/common/common_def.h
+++ b/include/plat/common/common_def.h
@@ -78,9 +78,19 @@
#define BL1_CODE_END BL_CODE_END
#define BL1_RO_DATA_BASE BL_RO_DATA_BASE
#define BL1_RO_DATA_END round_up(BL1_ROM_END, PAGE_SIZE)
+#if BL2_IN_XIP_MEM
+#define BL2_CODE_END BL_CODE_END
+#define BL2_RO_DATA_BASE BL_RO_DATA_BASE
+#define BL2_RO_DATA_END round_up(BL2_ROM_END, PAGE_SIZE)
+#endif /* BL2_IN_XIP_MEM */
#else
#define BL_RO_DATA_BASE 0
#define BL_RO_DATA_END 0
#define BL1_CODE_END round_up(BL1_ROM_END, PAGE_SIZE)
+#if BL2_IN_XIP_MEM
+#define BL2_RO_DATA_BASE 0
+#define BL2_RO_DATA_END 0
+#define BL2_CODE_END round_up(BL2_ROM_END, PAGE_SIZE)
+#endif /* BL2_IN_XIP_MEM */
#endif /* SEPARATE_CODE_AND_RODATA */
#endif /* __COMMON_DEF_H__ */
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index aa181c8..cd17a00 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -124,6 +124,9 @@
void plat_sdei_handle_masked_trigger(uint64_t mpidr, unsigned int intr);
#endif
+void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
+ void *handle, uint64_t flags);
+
/*
* The following function is mandatory when the
* firmware update feature is used.
diff --git a/lib/cpus/aarch64/cortex_a53.S b/lib/cpus/aarch64/cortex_a53.S
index 3e480bc..3a23e02 100644
--- a/lib/cpus/aarch64/cortex_a53.S
+++ b/lib/cpus/aarch64/cortex_a53.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,6 +9,7 @@
#include <cortex_a53.h>
#include <cpu_macros.S>
#include <debug.h>
+#include <errata_report.h>
#include <plat_macros.S>
#if A53_DISABLE_NON_TEMPORAL_HINT
@@ -144,8 +145,23 @@
* This workaround is statically enabled at build time.
*/
func check_errata_835769
- mov x1, #0x04
- b cpu_rev_var_ls
+ cmp x0, #0x04
+ b.hi errata_not_applies
+ /*
+ * Fix potentially available for revisions r0p2, r0p3 and r0p4.
+ * If r0p2, r0p3 or r0p4; check for fix in REVIDR, else exit.
+ */
+ cmp x0, #0x01
+ mov x0, #ERRATA_APPLIES
+ b.ls exit_check_errata_835769
+ /* Load REVIDR. */
+ mrs x1, revidr_el1
+ /* If REVIDR[7] is set (fix exists) set ERRATA_NOT_APPLIES, else exit. */
+ tbz x1, #7, exit_check_errata_835769
+errata_not_applies:
+ mov x0, #ERRATA_NOT_APPLIES
+exit_check_errata_835769:
+ ret
endfunc check_errata_835769
/*
@@ -154,8 +170,22 @@
* This workaround is statically enabled at build time.
*/
func check_errata_843419
- mov x1, #0x04
- b cpu_rev_var_ls
+ mov x1, #ERRATA_APPLIES
+ mov x2, #ERRATA_NOT_APPLIES
+ cmp x0, #0x04
+ csel x0, x1, x2, ls
+ /*
+ * Fix potentially available for revision r0p4.
+ * If r0p4 check for fix in REVIDR, else exit.
+ */
+ b.ne exit_check_errata_843419
+ /* Load REVIDR. */
+ mrs x3, revidr_el1
+ /* If REVIDR[8] is set (fix exists) set ERRATA_NOT_APPLIES, else exit. */
+ tbz x3, #8, exit_check_errata_843419
+ mov x0, x2
+exit_check_errata_843419:
+ ret
endfunc check_errata_843419
/* -------------------------------------------------
diff --git a/lib/cpus/aarch64/cpu_helpers.S b/lib/cpus/aarch64/cpu_helpers.S
index 5a9226d..9f13ed2 100644
--- a/lib/cpus/aarch64/cpu_helpers.S
+++ b/lib/cpus/aarch64/cpu_helpers.S
@@ -198,6 +198,8 @@
* Compare the CPU's revision-variant (x0) with a given value (x1), for errata
* application purposes. If the revision-variant is less than or same as a given
* value, indicates that errata applies; otherwise not.
+ *
+ * Shall clobber: x0-x3
*/
.globl cpu_rev_var_ls
func cpu_rev_var_ls
@@ -212,6 +214,8 @@
* Compare the CPU's revision-variant (x0) with a given value (x1), for errata
* application purposes. If the revision-variant is higher than or same as a
* given value, indicates that errata applies; otherwise not.
+ *
+ * Shall clobber: x0-x3
*/
.globl cpu_rev_var_hs
func cpu_rev_var_hs
diff --git a/lib/cpus/aarch64/denver.S b/lib/cpus/aarch64/denver.S
index a6225d4..aee4fee 100644
--- a/lib/cpus/aarch64/denver.S
+++ b/lib/cpus/aarch64/denver.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,10 +7,136 @@
#include <arch.h>
#include <asm_macros.S>
#include <assert_macros.S>
+#include <context.h>
#include <denver.h>
#include <cpu_macros.S>
#include <plat_macros.S>
+ /* -------------------------------------------------
+ * CVE-2017-5715 mitigation
+ *
+ * Flush the indirect branch predictor and RSB on
+ * entry to EL3 by issuing a newly added instruction
+ * for Denver CPUs.
+ *
+ * To achieve this without performing any branch
+ * instruction, a per-cpu vbar is installed which
+ * executes the workaround and then branches off to
+ * the corresponding vector entry in the main vector
+ * table.
+ * -------------------------------------------------
+ */
+ .globl workaround_bpflush_runtime_exceptions
+
+vector_base workaround_bpflush_runtime_exceptions
+
+ .macro apply_workaround
+ stp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
+
+ /* -------------------------------------------------
+ * A new write-only system register where a write of
+ * 1 to bit 0 will cause the indirect branch predictor
+ * and RSB to be flushed.
+ *
+ * A write of 0 to bit 0 will be ignored. A write of
+ * 1 to any other bit will cause an MCA.
+ * -------------------------------------------------
+ */
+ mov x0, #1
+ msr s3_0_c15_c0_6, x0
+ isb
+
+ ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
+ .endm
+
+ /* ---------------------------------------------------------------------
+ * Current EL with SP_EL0 : 0x0 - 0x200
+ * ---------------------------------------------------------------------
+ */
+vector_entry workaround_bpflush_sync_exception_sp_el0
+ b sync_exception_sp_el0
+ check_vector_size workaround_bpflush_sync_exception_sp_el0
+
+vector_entry workaround_bpflush_irq_sp_el0
+ b irq_sp_el0
+ check_vector_size workaround_bpflush_irq_sp_el0
+
+vector_entry workaround_bpflush_fiq_sp_el0
+ b fiq_sp_el0
+ check_vector_size workaround_bpflush_fiq_sp_el0
+
+vector_entry workaround_bpflush_serror_sp_el0
+ b serror_sp_el0
+ check_vector_size workaround_bpflush_serror_sp_el0
+
+ /* ---------------------------------------------------------------------
+ * Current EL with SP_ELx: 0x200 - 0x400
+ * ---------------------------------------------------------------------
+ */
+vector_entry workaround_bpflush_sync_exception_sp_elx
+ b sync_exception_sp_elx
+ check_vector_size workaround_bpflush_sync_exception_sp_elx
+
+vector_entry workaround_bpflush_irq_sp_elx
+ b irq_sp_elx
+ check_vector_size workaround_bpflush_irq_sp_elx
+
+vector_entry workaround_bpflush_fiq_sp_elx
+ b fiq_sp_elx
+ check_vector_size workaround_bpflush_fiq_sp_elx
+
+vector_entry workaround_bpflush_serror_sp_elx
+ b serror_sp_elx
+ check_vector_size workaround_bpflush_serror_sp_elx
+
+ /* ---------------------------------------------------------------------
+ * Lower EL using AArch64 : 0x400 - 0x600
+ * ---------------------------------------------------------------------
+ */
+vector_entry workaround_bpflush_sync_exception_aarch64
+ apply_workaround
+ b sync_exception_aarch64
+ check_vector_size workaround_bpflush_sync_exception_aarch64
+
+vector_entry workaround_bpflush_irq_aarch64
+ apply_workaround
+ b irq_aarch64
+ check_vector_size workaround_bpflush_irq_aarch64
+
+vector_entry workaround_bpflush_fiq_aarch64
+ apply_workaround
+ b fiq_aarch64
+ check_vector_size workaround_bpflush_fiq_aarch64
+
+vector_entry workaround_bpflush_serror_aarch64
+ apply_workaround
+ b serror_aarch64
+ check_vector_size workaround_bpflush_serror_aarch64
+
+ /* ---------------------------------------------------------------------
+ * Lower EL using AArch32 : 0x600 - 0x800
+ * ---------------------------------------------------------------------
+ */
+vector_entry workaround_bpflush_sync_exception_aarch32
+ apply_workaround
+ b sync_exception_aarch32
+ check_vector_size workaround_bpflush_sync_exception_aarch32
+
+vector_entry workaround_bpflush_irq_aarch32
+ apply_workaround
+ b irq_aarch32
+ check_vector_size workaround_bpflush_irq_aarch32
+
+vector_entry workaround_bpflush_fiq_aarch32
+ apply_workaround
+ b fiq_aarch32
+ check_vector_size workaround_bpflush_fiq_aarch32
+
+vector_entry workaround_bpflush_serror_aarch32
+ apply_workaround
+ b serror_aarch32
+ check_vector_size workaround_bpflush_serror_aarch32
+
.global denver_disable_dco
/* ---------------------------------------------
@@ -71,6 +197,23 @@
mov x19, x30
+#if IMAGE_BL31 && WORKAROUND_CVE_2017_5715
+ /*
+ * Check if the CPU supports the special instruction
+ * required to flush the indirect branch predictor and
+ * RSB. Support for this operation can be determined by
+ * comparing bits 19:16 of ID_AFR0_EL1 with 0b0001.
+ */
+ mrs x0, id_afr0_el1
+ mov x1, #0x10000
+ and x0, x0, x1
+ cmp x0, #0
+ adr x1, workaround_bpflush_runtime_exceptions
+ mrs x2, vbar_el3
+ csel x0, x1, x2, ne
+ msr vbar_el3, x0
+#endif
+
/* ----------------------------------------------------
* Enable dynamic code optimizer (DCO)
* ----------------------------------------------------
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index 620ec16..121ca4d 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -15,8 +15,8 @@
.global fpregs_context_restore
#endif
.global save_gp_registers
+ .global restore_gp_registers
.global restore_gp_registers_eret
- .global restore_gp_registers_callee_eret
.global el3_exit
/* -----------------------------------------------------
@@ -332,30 +332,50 @@
ret
endfunc save_gp_registers
-func restore_gp_registers_eret
+/*
+ * This function restores all general purpose registers except x30 from the
+ * CPU context. x30 register must be explicitly restored by the caller.
+ */
+func restore_gp_registers
ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
- b restore_gp_registers_callee_eret
-endfunc restore_gp_registers_eret
-
-func restore_gp_registers_callee_eret
ldp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4]
ldp x6, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X6]
ldp x8, x9, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X8]
ldp x10, x11, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X10]
ldp x12, x13, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X12]
ldp x14, x15, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X14]
+ ldp x16, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X16]
ldp x18, x19, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X18]
ldp x20, x21, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X20]
ldp x22, x23, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X22]
ldp x24, x25, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X24]
ldp x26, x27, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X26]
+ ldr x28, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_SP_EL0]
+ msr sp_el0, x28
ldp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28]
- ldp x30, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
- msr sp_el0, x17
- ldp x16, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X16]
+ ret
+endfunc restore_gp_registers
+
+/*
+ * Restore general purpose registers (including x30), and exit EL3 via. ERET to
+ * a lower exception level.
+ */
+func restore_gp_registers_eret
+ bl restore_gp_registers
+ ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+
+#if IMAGE_BL31 && RAS_EXTENSION
+ /*
+ * Issue Error Synchronization Barrier to synchronize SErrors before
+ * exiting EL3. We're running with EAs unmasked, so any synchronized
+ * errors would be taken immediately; therefore no need to inspect
+ * DISR_EL1 register.
+ */
+ esb
+#endif
eret
-endfunc restore_gp_registers_callee_eret
+endfunc restore_gp_registers_eret
/* -----------------------------------------------------
* This routine assumes that the SP_EL3 is pointing to
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 2608d1f..d8267e2 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -65,7 +65,7 @@
uint32_t scr_el3, pmcr_el0;
el3_state_t *state;
gp_regs_t *gp_regs;
- unsigned long sctlr_elx;
+ unsigned long sctlr_elx, actlr_elx;
assert(ctx);
@@ -114,6 +114,11 @@
scr_el3 &= ~SCR_EA_BIT;
#endif
+#if FAULT_INJECTION_SUPPORT
+ /* Enable fault injection from lower ELs */
+ scr_el3 |= SCR_FIEN_BIT;
+#endif
+
#ifdef IMAGE_BL31
/*
* SCR_EL3.IRQ, SCR_EL3.FIQ: Enable the physical FIQ and IRQ rounting as
@@ -173,6 +178,16 @@
*/
write_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_elx);
+ /*
+ * Base the context ACTLR_EL1 on the current value, as it is
+ * implementation defined. The context restore process will write
+ * the value from the context to the actual register and can cause
+ * problems for processor cores that don't expect certain bits to
+ * be zero.
+ */
+ actlr_elx = read_actlr_el1();
+ write_ctx_reg((get_sysregs_ctx(ctx)), (CTX_ACTLR_EL1), (actlr_elx));
+
if (security_state == SECURE) {
/*
* Initialise PMCR_EL0 for secure context only, setting all
diff --git a/lib/extensions/ras/ras_common.c b/lib/extensions/ras/ras_common.c
new file mode 100644
index 0000000..0335a7b
--- /dev/null
+++ b/lib/extensions/ras/ras_common.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <debug.h>
+#include <ea_handle.h>
+#include <ehf.h>
+#include <platform.h>
+#include <ras.h>
+#include <ras_arch.h>
+
+#ifndef PLAT_RAS_PRI
+# error Platform must define RAS priority value
+#endif
+
+/* Handler that receives External Aborts on RAS-capable systems */
+int ras_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
+ void *handle, uint64_t flags)
+{
+ unsigned int i, n_handled = 0, ret;
+ int probe_data;
+ struct err_record_info *info;
+
+ const struct err_handler_data err_data = {
+ .version = ERR_HANDLER_VERSION,
+ .ea_reason = ea_reason,
+ .interrupt = 0,
+ .syndrome = syndrome,
+ .flags = flags,
+ .cookie = cookie,
+ .handle = handle
+ };
+
+ for_each_err_record_info(i, info) {
+ assert(info->probe != NULL);
+ assert(info->handler != NULL);
+
+ /* Continue probing until the record group signals no error */
+ while (1) {
+ if (info->probe(info, &probe_data) == 0)
+ break;
+
+ /* Handle error */
+ ret = info->handler(info, probe_data, &err_data);
+ if (ret != 0)
+ return ret;
+
+ n_handled++;
+ }
+ }
+
+ return (n_handled != 0);
+}
+
+#if ENABLE_ASSERTIONS
+static void assert_interrupts_sorted(void)
+{
+ unsigned int i, last;
+ struct ras_interrupt *start = ras_interrupt_mapping.intrs;
+
+ if (ras_interrupt_mapping.num_intrs == 0)
+ return;
+
+ last = start[0].intr_number;
+ for (i = 1; i < ras_interrupt_mapping.num_intrs; i++) {
+ assert(start[i].intr_number > last);
+ last = start[i].intr_number;
+ }
+}
+#endif
+
+/*
+ * Given an RAS interrupt number, locate the registered handler and call it. If
+ * no handler was found for the interrupt number, this function panics.
+ */
+static int ras_interrupt_handler(uint32_t intr_raw, uint32_t flags,
+ void *handle, void *cookie)
+{
+ struct ras_interrupt *ras_inrs = ras_interrupt_mapping.intrs;
+ struct ras_interrupt *selected = NULL;
+ int start, end, mid, probe_data, ret __unused;
+
+ const struct err_handler_data err_data = {
+ .version = ERR_HANDLER_VERSION,
+ .interrupt = intr_raw,
+ .flags = flags,
+ .cookie = cookie,
+ .handle = handle
+ };
+
+ assert(ras_interrupt_mapping.num_intrs > 0);
+
+ start = 0;
+ end = ras_interrupt_mapping.num_intrs;
+ while (start <= end) {
+ mid = ((end + start) / 2);
+ if (intr_raw == ras_inrs[mid].intr_number) {
+ selected = &ras_inrs[mid];
+ break;
+ } else if (intr_raw < ras_inrs[mid].intr_number) {
+ /* Move left */
+ end = mid - 1;
+ } else {
+ /* Move right */
+ start = mid + 1;
+ }
+ }
+
+ if (selected == NULL) {
+ ERROR("RAS interrupt %u has no handler!\n", intr_raw);
+ panic();
+ }
+
+
+ ret = selected->err_record->probe(selected->err_record, &probe_data);
+ assert(ret != 0);
+
+ /* Call error handler for the record group */
+ assert(selected->err_record->handler != NULL);
+ selected->err_record->handler(selected->err_record, probe_data,
+ &err_data);
+
+ return 0;
+}
+
+void ras_init(void)
+{
+#if ENABLE_ASSERTIONS
+ /* Check RAS interrupts are sorted */
+ assert_interrupts_sorted();
+#endif
+
+ /* Register RAS priority handler */
+ ehf_register_priority_handler(PLAT_RAS_PRI, ras_interrupt_handler);
+}
diff --git a/lib/extensions/ras/std_err_record.c b/lib/extensions/ras/std_err_record.c
new file mode 100644
index 0000000..65c007f
--- /dev/null
+++ b/lib/extensions/ras/std_err_record.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <ras_arch.h>
+#include <utils_def.h>
+
+/*
+ * Probe for error in memory-mapped registers containing error records
+ * implemented Standard Error Record format. Upon detecting an error, set probe
+ * data to the index of the record in error, and return 1; otherwise, return 0.
+ */
+int ser_probe_memmap(uintptr_t base, unsigned int size_num_k, int *probe_data)
+{
+ int num_records, num_group_regs, i;
+ uint64_t gsr;
+
+ assert(base != 0);
+
+ /* Only 4K supported for now */
+ assert(size_num_k == STD_ERR_NODE_SIZE_NUM_K);
+
+ num_records = (mmio_read_32(ERR_DEVID(base, size_num_k)) & ERR_DEVID_MASK);
+
+ /* A group register shows error status for 2^6 error records */
+ num_group_regs = (num_records >> 6) + 1;
+
+ /* Iterate through group registers to find a record in error */
+ for (i = 0; i < num_group_regs; i++) {
+ gsr = mmio_read_64(ERR_GSR(base, size_num_k, i));
+ if (gsr == 0)
+ continue;
+
+ /* Return the index of the record in error */
+ if (probe_data != NULL)
+ *probe_data = ((i << 6) + __builtin_ctz(gsr));
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Probe for error in System Registers where error records are implemented in
+ * Standard Error Record format. Upon detecting an error, set probe data to the
+ * index of the record in error, and return 1; otherwise, return 0.
+ */
+int ser_probe_sysreg(unsigned int idx_start, unsigned int num_idx, int *probe_data)
+{
+ int i;
+ uint64_t status;
+ unsigned int max_idx __unused = read_erridr_el1() & ERRIDR_MASK;
+
+ assert(idx_start < max_idx);
+ assert(check_u32_overflow(idx_start, num_idx) == 0);
+ assert((idx_start + num_idx - 1) < max_idx);
+
+ for (i = 0; i < num_idx; i++) {
+ /* Select the error record */
+ ser_sys_select_record(idx_start + i);
+
+ /* Retrieve status register from the error record */
+ status = read_erxstatus_el1();
+
+ /* Check for valid field in status */
+ if (ERR_STATUS_GET_FIELD(status, V)) {
+ if (probe_data != NULL)
+ *probe_data = i;
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/lib/utils/mem_region.c b/lib/utils/mem_region.c
index 31c6231..24c2c1d 100644
--- a/lib/utils/mem_region.c
+++ b/lib/utils/mem_region.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -40,6 +40,59 @@
}
}
+#if defined(PLAT_XLAT_TABLES_DYNAMIC)
+/*
+ * zero_normalmem all the regions defined in regions.
+ * It assumes that MMU is enabled and the memory is Normal memory.
+ * regions must be a valid pointer to a memory mem_region_t array,
+ * nregions is the size of the array. va is the virtual address
+ * where we want to map the physical pages that are going to
+ * be cleared, and chunk is the amount of memory mapped and
+ * cleared in every iteration.
+ */
+void clear_map_dyn_mem_regions(mem_region_t *regions,
+ size_t nregions,
+ uintptr_t va,
+ size_t chunk)
+{
+ uintptr_t begin;
+ int r;
+ size_t size;
+ const mmap_attr_t attr = MT_MEMORY|MT_RW|MT_NS;
+
+ assert(regions != NULL);
+ assert(nregions > 0 && chunk > 0);
+
+ for ( ; nregions--; regions++) {
+ begin = regions->base;
+ size = regions->nbytes;
+ if ((begin & (chunk-1)) != 0 || (size & (chunk-1)) != 0) {
+ INFO("PSCI: Not correctly aligned region\n");
+ panic();
+ }
+
+ while (size > 0) {
+ r = mmap_add_dynamic_region(begin, va, chunk, attr);
+ if (r != 0) {
+ INFO("PSCI: mmap_add_dynamic_region failed with %d\n", r);
+ panic();
+ }
+
+ zero_normalmem((void *) va, chunk);
+
+ r = mmap_remove_dynamic_region(va, chunk);
+ if (r != 0) {
+ INFO("PSCI: mmap_remove_dynamic_region failed with %d\n", r);
+ panic();
+ }
+
+ begin += chunk;
+ size -= chunk;
+ }
+ }
+}
+#endif
+
/*
* This function checks that a region (addr + nbytes-1) of memory is totally
* covered by one of the regions defined in tbl.
diff --git a/lib/xlat_tables/aarch64/xlat_tables.c b/lib/xlat_tables/aarch64/xlat_tables.c
index eabc3df..a72c645 100644
--- a/lib/xlat_tables/aarch64/xlat_tables.c
+++ b/lib/xlat_tables/aarch64/xlat_tables.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -57,13 +57,13 @@
}
#if ENABLE_ASSERTIONS
-/* Physical Address ranges supported in the AArch64 Memory Model */
+/*
+ * Physical Address ranges supported in the AArch64 Memory Model. Value 0b110 is
+ * supported in ARMv8.2 onwards.
+ */
static const unsigned int pa_range_bits_arr[] = {
PARANGE_0000, PARANGE_0001, PARANGE_0010, PARANGE_0011, PARANGE_0100,
- PARANGE_0101,
-#if ARM_ARCH_AT_LEAST(8, 2)
- PARANGE_0110,
-#endif
+ PARANGE_0101, PARANGE_0110
};
static unsigned long long get_max_supported_pa(void)
diff --git a/lib/xlat_tables/xlat_tables_common.c b/lib/xlat_tables/xlat_tables_common.c
index 1309936..21bf489 100644
--- a/lib/xlat_tables/xlat_tables_common.c
+++ b/lib/xlat_tables/xlat_tables_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -41,6 +41,7 @@
static uintptr_t xlat_max_va;
static uint64_t execute_never_mask;
+static uint64_t ap1_mask;
/*
* Array of all memory regions stored in order of ascending base address.
@@ -195,6 +196,7 @@
desc |= (attr & MT_NS) ? LOWER_ATTRS(NS) : 0;
desc |= (attr & MT_RW) ? LOWER_ATTRS(AP_RW) : LOWER_ATTRS(AP_RO);
desc |= LOWER_ATTRS(ACCESS_FLAG);
+ desc |= ap1_mask;
/*
* Deduce shareability domain and executability of the memory region
@@ -381,7 +383,17 @@
unsigned int level, uintptr_t *max_va,
unsigned long long *max_pa)
{
- execute_never_mask = xlat_arch_get_xn_desc(xlat_arch_current_el());
+ int el = xlat_arch_current_el();
+
+ execute_never_mask = xlat_arch_get_xn_desc(el);
+
+ if (el == 3) {
+ ap1_mask = LOWER_ATTRS(AP_ONE_VA_RANGE_RES1);
+ } else {
+ assert(el == 1);
+ ap1_mask = 0;
+ }
+
init_xlation_table_inner(mmap, base_va, table, level);
*max_va = xlat_max_va;
*max_pa = xlat_max_pa;
diff --git a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
index ffbc665..b3504e1 100644
--- a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -45,13 +45,13 @@
}
#if ENABLE_ASSERTIONS
-/* Physical Address ranges supported in the AArch64 Memory Model */
+/*
+ * Physical Address ranges supported in the AArch64 Memory Model. Value 0b110 is
+ * supported in ARMv8.2 onwards.
+ */
static const unsigned int pa_range_bits_arr[] = {
PARANGE_0000, PARANGE_0001, PARANGE_0010, PARANGE_0011, PARANGE_0100,
- PARANGE_0101,
-#if ARM_ARCH_AT_LEAST(8, 2)
- PARANGE_0110,
-#endif
+ PARANGE_0101, PARANGE_0110
};
unsigned long long xlat_arch_get_max_supported_pa(void)
diff --git a/lib/xlat_tables_v2/xlat_tables_internal.c b/lib/xlat_tables_v2/xlat_tables_internal.c
index 653260c..8be6d94 100644
--- a/lib/xlat_tables_v2/xlat_tables_internal.c
+++ b/lib/xlat_tables_v2/xlat_tables_internal.c
@@ -115,8 +115,8 @@
/*
* Returns a block/page table descriptor for the given level and attributes.
*/
-static uint64_t xlat_desc(const xlat_ctx_t *ctx, mmap_attr_t attr,
- unsigned long long addr_pa, int level)
+static uint64_t xlat_desc(const xlat_ctx_t *ctx, uint32_t attr,
+ unsigned long long addr_pa, int level)
{
uint64_t desc;
int mem_type;
@@ -155,7 +155,7 @@
}
} else {
assert(ctx->xlat_regime == EL3_REGIME);
- desc |= LOWER_ATTRS(AP_NO_ACCESS_UNPRIVILEGED);
+ desc |= LOWER_ATTRS(AP_ONE_VA_RANGE_RES1);
}
/*
@@ -561,7 +561,8 @@
if (action == ACTION_WRITE_BLOCK_ENTRY) {
table_base[table_idx] =
- xlat_desc(ctx, mm->attr, table_idx_pa, level);
+ xlat_desc(ctx, (uint32_t)mm->attr, table_idx_pa,
+ level);
} else if (action == ACTION_CREATE_NEW_TABLE) {
@@ -735,7 +736,8 @@
void mmap_add_region_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm)
{
mmap_region_t *mm_cursor = ctx->mmap;
- mmap_region_t *mm_last = mm_cursor + ctx->mmap_num;
+ const mmap_region_t *mm_end = ctx->mmap + ctx->mmap_num;
+ mmap_region_t *mm_last;
unsigned long long end_pa = mm->base_pa + mm->size - 1;
uintptr_t end_va = mm->base_va + mm->size - 1;
int ret;
@@ -786,6 +788,21 @@
&& (mm_cursor->size < mm->size))
++mm_cursor;
+ /*
+ * Find the last entry marker in the mmap
+ */
+ mm_last = ctx->mmap;
+ while ((mm_last->size != 0U) && (mm_last < mm_end)) {
+ ++mm_last;
+ }
+
+ /*
+ * Check if we have enough space in the memory mapping table.
+ * This shouldn't happen as we have checked in mmap_add_region_check
+ * that there is free space.
+ */
+ assert(mm_last->size == 0U);
+
/* Make room for new region by moving other regions up by one place */
memmove(mm_cursor + 1, mm_cursor,
(uintptr_t)mm_last - (uintptr_t)mm_cursor);
@@ -795,7 +812,7 @@
* This shouldn't happen as we have checked in mmap_add_region_check
* that there is free space.
*/
- assert(mm_last->size == 0);
+ assert(mm_end->size == 0U);
*mm_cursor = *mm;
@@ -1049,18 +1066,19 @@
if (xlat_regime == EL3_REGIME) {
/* For EL3, the AP[2] bit is all what matters */
- tf_printf((desc & LOWER_ATTRS(AP_RO)) ? ro_str : rw_str);
+ tf_printf("%s", (desc & LOWER_ATTRS(AP_RO)) ? ro_str : rw_str);
} else {
const char *ap_str = (desc & LOWER_ATTRS(AP_RO)) ? ro_str : rw_str;
- tf_printf(ap_str);
- tf_printf(priv_str);
+ tf_printf("%s", ap_str);
+ tf_printf("%s", priv_str);
/*
* EL0 can only have the same permissions as EL1 or no
* permissions at all.
*/
- tf_printf((desc & LOWER_ATTRS(AP_ACCESS_UNPRIVILEGED))
+ tf_printf("%s",
+ (desc & LOWER_ATTRS(AP_ACCESS_UNPRIVILEGED))
? ap_str : no_access_str);
- tf_printf(user_str);
+ tf_printf("%s", user_str);
}
const char *xn_str = "-XN";
@@ -1068,14 +1086,14 @@
if (xlat_regime == EL3_REGIME) {
/* For EL3, the XN bit is all what matters */
- tf_printf(LOWER_ATTRS(XN) & desc ? xn_str : exec_str);
+ tf_printf("%s", LOWER_ATTRS(XN) & desc ? xn_str : exec_str);
} else {
/* For EL0 and EL1, we need to know who has which rights */
- tf_printf(LOWER_ATTRS(PXN) & desc ? xn_str : exec_str);
- tf_printf(priv_str);
+ tf_printf("%s", LOWER_ATTRS(PXN) & desc ? xn_str : exec_str);
+ tf_printf("%s", priv_str);
- tf_printf(LOWER_ATTRS(UXN) & desc ? xn_str : exec_str);
- tf_printf(user_str);
+ tf_printf("%s", LOWER_ATTRS(UXN) & desc ? xn_str : exec_str);
+ tf_printf("%s", user_str);
}
tf_printf(LOWER_ATTRS(NS) & desc ? "-NS" : "-S");
@@ -1411,7 +1429,7 @@
static int get_mem_attributes_internal(const xlat_ctx_t *ctx, uintptr_t base_va,
- mmap_attr_t *attributes, uint64_t **table_entry,
+ uint32_t *attributes, uint64_t **table_entry,
unsigned long long *addr_pa, int *table_level)
{
uint64_t *entry;
@@ -1502,7 +1520,7 @@
int get_mem_attributes(const xlat_ctx_t *ctx, uintptr_t base_va,
- mmap_attr_t *attributes)
+ uint32_t *attributes)
{
return get_mem_attributes_internal(ctx, base_va, attributes,
NULL, NULL, NULL);
@@ -1512,7 +1530,7 @@
int change_mem_attributes(xlat_ctx_t *ctx,
uintptr_t base_va,
size_t size,
- mmap_attr_t attr)
+ uint32_t attr)
{
/* Note: This implementation isn't optimized. */
@@ -1609,7 +1627,7 @@
for (int i = 0; i < pages_count; ++i) {
- mmap_attr_t old_attr, new_attr;
+ uint32_t old_attr, new_attr;
uint64_t *entry;
int level;
unsigned long long addr_pa;
diff --git a/maintainers.rst b/maintainers.rst
index 77b851e..2217cbe 100644
--- a/maintainers.rst
+++ b/maintainers.rst
@@ -83,6 +83,15 @@
- plat/mediatek/\*
+NXP QorIQ Layerscape platform sub-maintainer
+--------------------------------------
+Jiafei Pan (jiafei.pan@nxp.com, `qoriq-open-source`_)
+
+Files:
+
+- docs/plat/ls1043a.rst
+- plat/layerscape/\*
+
Raspberry Pi 3 platform sub-maintainer
--------------------------------------
@@ -141,3 +150,4 @@
.. _sivadur: https://github.com/sivadur
.. _rockchip-linux: https://github.com/rockchip-linux
.. _etienne-lms: https://github.com/etienne-lms
+.. _qoriq-open-source: https://github.com/qoriq-open-source
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 751f834..4bbff03 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -30,6 +30,10 @@
# Execute BL2 at EL3
BL2_AT_EL3 := 0
+# BL2 image is stored in XIP memory, for now, this option is only supported
+# when BL2_AT_EL3 is 1.
+BL2_IN_XIP_MEM := 0
+
# By default, consider that the platform may release several CPUs out of reset.
# The platform Makefile is free to override this value.
COLD_BOOT_SINGLE_CPU := 0
@@ -72,6 +76,9 @@
# Build flag to treat usage of deprecated platform and framework APIs as error.
ERROR_DEPRECATED := 0
+# Fault injection support
+FAULT_INJECTION_SUPPORT := 0
+
# Byte alignment that each component in FIP is aligned to
FIP_ALIGN := 0
@@ -88,6 +95,10 @@
# default, they are for Secure EL1.
GICV2_G0_FOR_EL3 := 0
+# Route External Aborts to EL3. Disabled by default; External Aborts are handled
+# by lower ELs.
+HANDLE_EA_EL3_FIRST := 0
+
# Whether system coherency is managed in hardware, without explicit software
# operations.
HW_ASSISTED_COHERENCY := 0
@@ -116,6 +127,9 @@
# Original format.
PSCI_EXTENDED_STATE_ID := 0
+# Enable RAS support
+RAS_EXTENSION := 0
+
# By default, BL1 acts as the reset handler, not BL31
RESET_TO_BL31 := 0
@@ -129,6 +143,9 @@
# platform Makefile is free to override this value.
SEPARATE_CODE_AND_RODATA := 0
+# Default to SMCCC Version 1.X
+SMCCC_MAJOR_VERSION := 1
+
# SPD choice
SPD := none
diff --git a/plat/arm/board/common/board_css_common.c b/plat/arm/board/common/board_css_common.c
index c1c3e66..c4e83a4 100644
--- a/plat/arm/board/common/board_css_common.c
+++ b/plat/arm/board/common/board_css_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -73,6 +73,9 @@
const mmap_region_t plat_arm_mmap[] = {
#ifdef AARCH32
ARM_MAP_SHARED_RAM,
+#ifdef PLAT_ARM_MEM_PROT_ADDR
+ ARM_V2M_MAP_MEM_PROTECT,
+#endif
#endif
V2M_MAP_IOFPGA,
CSS_MAP_DEVICE,
diff --git a/plat/arm/board/fvp/aarch32/fvp_helpers.S b/plat/arm/board/fvp/aarch32/fvp_helpers.S
index 143972d..5d88546 100644
--- a/plat/arm/board/fvp/aarch32/fvp_helpers.S
+++ b/plat/arm/board/fvp/aarch32/fvp_helpers.S
@@ -104,15 +104,20 @@
bx lr
endfunc plat_is_my_cpu_primary
- /* -----------------------------------------------------
+ /* ---------------------------------------------------------------------
* unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
*
* Function to calculate the core position on FVP.
*
- * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER) +
+ * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU) +
* (CPUId * FVP_MAX_PE_PER_CPU) +
* ThreadId
- * -----------------------------------------------------
+ *
+ * which can be simplified as:
+ *
+ * ((ClusterId * FVP_MAX_CPUS_PER_CLUSTER + CPUId) * FVP_MAX_PE_PER_CPU)
+ * + ThreadId
+ * ---------------------------------------------------------------------
*/
func plat_arm_calc_core_pos
mov r3, r0
@@ -125,14 +130,15 @@
lsleq r3, r0, #MPIDR_AFFINITY_BITS
/* Extract individual affinity fields from MPIDR */
- mov r2, #FVP_MAX_PE_PER_CPU
ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
- mla r0, r1, r2, r0
-
- mov r1, #FVP_MAX_CPUS_PER_CLUSTER
ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
- mla r0, r1, r2, r0
+
+ /* Compute linear position */
+ mov r3, #FVP_MAX_CPUS_PER_CLUSTER
+ mla r1, r2, r3, r1
+ mov r3, #FVP_MAX_PE_PER_CPU
+ mla r0, r1, r3, r0
bx lr
endfunc plat_arm_calc_core_pos
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
index 0fa83a5..065ecc1 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -412,13 +412,7 @@
*/
.get_sys_suspend_power_state = fvp_get_sys_suspend_power_state,
#endif
-#if !RESET_TO_BL31 && !RESET_TO_SP_MIN
- /*
- * mem_protect is not supported in RESET_TO_BL31 and RESET_TO_SP_MIN,
- * as that would require mapping in all of NS DRAM into BL31 or BL32.
- */
.mem_protect_chk = arm_psci_mem_protect_chk,
.read_mem_protect = arm_psci_read_mem_protect,
.write_mem_protect = arm_nor_psci_write_mem_protect,
-#endif
};
diff --git a/plat/arm/board/fvp/fvp_private.h b/plat/arm/board/fvp/fvp_private.h
index c5cd07d..16f10a2 100644
--- a/plat/arm/board/fvp/fvp_private.h
+++ b/plat/arm/board/fvp/fvp_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -18,6 +18,7 @@
void fvp_interconnect_init(void);
void fvp_interconnect_enable(void);
void fvp_interconnect_disable(void);
+void tsp_early_platform_setup(void);
#endif /* __FVP_PRIVATE_H__ */
diff --git a/plat/arm/board/fvp/fvp_security.c b/plat/arm/board/fvp/fvp_security.c
index 4559865..a6c9227 100644
--- a/plat/arm/board/fvp/fvp_security.c
+++ b/plat/arm/board/fvp/fvp_security.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -22,5 +22,5 @@
*/
if (get_arm_config()->flags & ARM_CONFIG_HAS_TZC)
- arm_tzc400_setup();
+ arm_tzc400_setup(NULL);
}
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 2d01490..b1adbee 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -7,6 +7,17 @@
#ifndef __PLATFORM_DEF_H__
#define __PLATFORM_DEF_H__
+/* Enable the dynamic translation tables library. */
+#ifdef AARCH32
+# if defined(IMAGE_BL32) && RESET_TO_SP_MIN
+# define PLAT_XLAT_TABLES_DYNAMIC 1
+# endif
+#else
+# if defined(IMAGE_BL31) && RESET_TO_BL31
+# define PLAT_XLAT_TABLES_DYNAMIC 1
+# endif
+#endif /* AARCH32 */
+
#include <arm_def.h>
#include <arm_spm_def.h>
#include <board_arm_def.h>
@@ -40,6 +51,9 @@
#define PLAT_ARM_TRUSTED_DRAM_BASE 0x06000000
#define PLAT_ARM_TRUSTED_DRAM_SIZE 0x02000000 /* 32 MB */
+/* virtual address used by dynamic mem_protect for chunk_base */
+#define PLAT_ARM_MEM_PROTEC_VA_FRAME 0xc0000000
+
/* No SCP in FVP */
#define PLAT_ARM_SCP_TZC_DRAM1_SIZE ULL(0x0)
@@ -48,7 +62,7 @@
/*
* Load address of BL33 for this platform port
*/
-#define PLAT_ARM_NS_IMAGE_OFFSET (ARM_DRAM1_BASE + 0x8000000)
+#define PLAT_ARM_NS_IMAGE_OFFSET (ARM_DRAM1_BASE + U(0x8000000))
/*
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index 2e2fdd7..e616e1f 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,6 +7,18 @@
#ifndef __PLATFORM_DEF_H__
#define __PLATFORM_DEF_H__
+/* Enable the dynamic translation tables library. */
+#ifdef AARCH32
+# if defined(IMAGE_BL32) && RESET_TO_SP_MIN
+# define PLAT_XLAT_TABLES_DYNAMIC 1
+# endif
+#else
+# if defined(IMAGE_BL31) && RESET_TO_BL31
+# define PLAT_XLAT_TABLES_DYNAMIC 1
+# endif
+#endif /* AARCH32 */
+
+
#include <arm_def.h>
#include <board_arm_def.h>
#include <board_css_def.h>
@@ -44,6 +56,12 @@
/* Use the bypass address */
#define PLAT_ARM_TRUSTED_ROM_BASE V2M_FLASH0_BASE + BL1_ROM_BYPASS_OFFSET
+#define NSRAM_BASE 0x2e000000
+#define NSRAM_SIZE 0x00008000 /* 32KB */
+
+/* virtual address used by dynamic mem_protect for chunk_base */
+#define PLAT_ARM_MEM_PROTEC_VA_FRAME 0xc0000000
+
/*
* Actual ROM size on Juno is 64 KB, but TBB currently requires at least 80 KB
* in debug mode. We can test TBB on Juno bypassing the ROM and using 128 KB of
@@ -90,7 +108,7 @@
#endif
#ifdef IMAGE_BL32
-# define PLAT_ARM_MMAP_ENTRIES 5
+# define PLAT_ARM_MMAP_ENTRIES 6
# define MAX_XLAT_TABLES 4
#endif
@@ -110,12 +128,14 @@
*/
#if TRUSTED_BOARD_BOOT
#if TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA
-# define PLAT_ARM_MAX_BL2_SIZE 0x1F000
+# define PLAT_ARM_MAX_BL2_SIZE 0x20000
+#elif TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA
+# define PLAT_ARM_MAX_BL2_SIZE 0x1D000
#else
-# define PLAT_ARM_MAX_BL2_SIZE 0x1B000
+# define PLAT_ARM_MAX_BL2_SIZE 0x1C000
#endif
#else
-# define PLAT_ARM_MAX_BL2_SIZE 0xD000
+# define PLAT_ARM_MAX_BL2_SIZE 0xE000
#endif
/*
diff --git a/plat/arm/board/juno/juno_security.c b/plat/arm/board/juno/juno_security.c
index ce4239b..b6cfe78 100644
--- a/plat/arm/board/juno/juno_security.c
+++ b/plat/arm/board/juno/juno_security.c
@@ -1,17 +1,82 @@
/*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <debug.h>
#include <mmio.h>
#include <nic_400.h>
#include <plat_arm.h>
#include <soc_css.h>
+
#include "juno_def.h"
+#include "juno_tzmp1_def.h"
+
+#ifdef JUNO_TZMP1
+/*
+ * Protect buffer for VPU/GPU/DPU memory usage with hardware protection
+ * enabled. Propose 224MB video output, 96 MB video input and 32MB video
+ * private.
+ *
+ * Ind Memory Range Caption S_ATTR NS_ATTR
+ * 1 0x080000000 - 0x0E7FFFFFF ARM_NS_DRAM1 NONE RDWR | MEDIA_RW
+ * 2 0x0E8000000 - 0x0F5FFFFFF JUNO_MEDIA_TZC_PROT_DRAM1 NONE MEDIA_RW | AP_WR
+ * 3 0x0F6000000 - 0x0FBFFFFFF JUNO_VPU_TZC_PROT_DRAM1 RDWR VPU_PROT_RW
+ * 4 0x0FC000000 - 0x0FDFFFFFF JUNO_VPU_TZC_PRIV_DRAM1 RDWR VPU_PRIV_RW
+ * 5 0x0FE000000 - 0x0FEFFFFFF JUNO_AP_TZC_SHARE_DRAM1 NONE RDWR | MEDIA_RW
+ * 6 0x0FF000000 - 0x0FFFFFFFF ARM_AP_TZC_DRAM1 RDWR NONE
+ * 7 0x880000000 - 0x9FFFFFFFF ARM_DRAM2 NONE RDWR | MEDIA_RW
+ *
+ * Memory regions are neighbored to save limited TZC regions. Calculation
+ * started from ARM_TZC_SHARE_DRAM1 since it is known and fixed for both
+ * protected-enabled and protected-disabled settings.
+ *
+ * Video private buffer aheads of ARM_TZC_SHARE_DRAM1
+ */
+static const arm_tzc_regions_info_t juno_tzmp1_tzc_regions[] = {
+ {ARM_AP_TZC_DRAM1_BASE, ARM_AP_TZC_DRAM1_END, TZC_REGION_S_RDWR, 0},
+ {JUNO_NS_DRAM1_PT1_BASE, JUNO_NS_DRAM1_PT1_END,
+ TZC_REGION_S_NONE, JUNO_MEDIA_TZC_NS_DEV_ACCESS},
+ {JUNO_MEDIA_TZC_PROT_DRAM1_BASE, JUNO_MEDIA_TZC_PROT_DRAM1_END,
+ TZC_REGION_S_NONE, JUNO_MEDIA_TZC_PROT_ACCESS},
+ {JUNO_VPU_TZC_PROT_DRAM1_BASE, JUNO_VPU_TZC_PROT_DRAM1_END,
+ TZC_REGION_S_RDWR, JUNO_VPU_TZC_PROT_ACCESS},
+ {JUNO_VPU_TZC_PRIV_DRAM1_BASE, JUNO_VPU_TZC_PRIV_DRAM1_END,
+ TZC_REGION_S_RDWR, JUNO_VPU_TZC_PRIV_ACCESS},
+ {JUNO_AP_TZC_SHARE_DRAM1_BASE, JUNO_AP_TZC_SHARE_DRAM1_END,
+ TZC_REGION_S_NONE, JUNO_MEDIA_TZC_NS_DEV_ACCESS},
+ {ARM_DRAM2_BASE, ARM_DRAM2_END,
+ TZC_REGION_S_NONE, JUNO_MEDIA_TZC_NS_DEV_ACCESS},
+ {},
+};
/*******************************************************************************
+ * Program dp650 to configure NSAID value for protected mode.
+ ******************************************************************************/
+static void init_dp650(void)
+{
+ mmio_write_32(DP650_BASE + DP650_PROT_NSAID_OFFSET,
+ DP650_PROT_NSAID_CONFIG);
+}
+
+/*******************************************************************************
+ * Program v550 to configure NSAID value for protected mode.
+ ******************************************************************************/
+static void init_v550(void)
+{
+ /*
+ * bits[31:28] is for PRIVATE,
+ * bits[27:24] is for OUTBUF,
+ * bits[23:20] is for PROTECTED.
+ */
+ mmio_write_32(V550_BASE + V550_PROTCTRL_OFFSET, V550_PROTCTRL_CONFIG);
+}
+
+#endif /* JUNO_TZMP1 */
+
+/*******************************************************************************
* Set up the MMU-401 SSD tables. The power-on configuration has all stream IDs
* assigned to Non-Secure except some for the DMA-330. Assign those back to the
* Non-Secure world as well, otherwise EL1 may end up erroneously generating
@@ -59,11 +124,23 @@
/* Initialize debug configuration */
init_debug_cfg();
/* Initialize the TrustZone Controller */
- arm_tzc400_setup();
+#ifdef JUNO_TZMP1
+ arm_tzc400_setup(juno_tzmp1_tzc_regions);
+ INFO("TZC protected shared memory base address for TZMP usecase: %p\n",
+ (void *)JUNO_AP_TZC_SHARE_DRAM1_BASE);
+ INFO("TZC protected shared memory end address for TZMP usecase: %p\n",
+ (void *)JUNO_AP_TZC_SHARE_DRAM1_END);
+#else
+ arm_tzc400_setup(NULL);
+#endif
/* Do ARM CSS internal NIC setup */
css_init_nic400();
/* Do ARM CSS SoC security setup */
soc_css_security_setup();
/* Initialize the SMMU SSD tables */
init_mmu401();
+#ifdef JUNO_TZMP1
+ init_dp650();
+ init_v550();
+#endif
}
diff --git a/plat/arm/board/juno/juno_tzmp1_def.h b/plat/arm/board/juno/juno_tzmp1_def.h
new file mode 100644
index 0000000..7055f76
--- /dev/null
+++ b/plat/arm/board/juno/juno_tzmp1_def.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __JUNO_TZMP1_DEF_H__
+#define __JUNO_TZMP1_DEF_H__
+
+#include <plat_arm.h>
+
+/*
+ * Public memory regions for both protected and non-protected mode
+ *
+ * OPTEE shared memory 0xFEE00000 - 0xFEFFFFFF
+ */
+#define JUNO_AP_TZC_SHARE_DRAM1_SIZE ULL(0x02000000)
+#define JUNO_AP_TZC_SHARE_DRAM1_BASE (ARM_AP_TZC_DRAM1_BASE - \
+ JUNO_AP_TZC_SHARE_DRAM1_SIZE)
+#define JUNO_AP_TZC_SHARE_DRAM1_END (ARM_AP_TZC_DRAM1_BASE - 1)
+
+/* ARM_MEDIA_FEATURES for MEDIA GPU Protect Mode Test */
+#define JUNO_TZC400_NSAID_FPGA_MEDIA_SECURE 8 /* GPU/DPU protected, VPU outbuf */
+#define JUNO_TZC400_NSAID_FPGA_VIDEO_PROTECTED 7 /* VPU protected */
+#define JUNO_TZC400_NSAID_FPGA_VIDEO_PRIVATE 10 /* VPU private (firmware) */
+
+#define JUNO_VPU_TZC_PRIV_DRAM1_SIZE ULL(0x02000000)
+#define JUNO_VPU_TZC_PRIV_DRAM1_BASE (JUNO_AP_TZC_SHARE_DRAM1_BASE - \
+ JUNO_VPU_TZC_PRIV_DRAM1_SIZE)
+#define JUNO_VPU_TZC_PRIV_DRAM1_END (JUNO_AP_TZC_SHARE_DRAM1_BASE - 1)
+
+/* Video input protected buffer follows upper item */
+#define JUNO_VPU_TZC_PROT_DRAM1_SIZE ULL(0x06000000)
+#define JUNO_VPU_TZC_PROT_DRAM1_BASE (JUNO_VPU_TZC_PRIV_DRAM1_BASE - \
+ JUNO_VPU_TZC_PROT_DRAM1_SIZE)
+#define JUNO_VPU_TZC_PROT_DRAM1_END (JUNO_VPU_TZC_PRIV_DRAM1_BASE - 1)
+
+/* Video, graphics and display shares same NSAID and same protected buffer */
+#define JUNO_MEDIA_TZC_PROT_DRAM1_SIZE ULL(0x0e000000)
+#define JUNO_MEDIA_TZC_PROT_DRAM1_BASE (JUNO_VPU_TZC_PROT_DRAM1_BASE - \
+ JUNO_MEDIA_TZC_PROT_DRAM1_SIZE)
+#define JUNO_MEDIA_TZC_PROT_DRAM1_END (JUNO_VPU_TZC_PROT_DRAM1_BASE - 1)
+
+/* Rest of DRAM1 are Non-Secure public buffer */
+#define JUNO_NS_DRAM1_PT1_BASE ARM_DRAM1_BASE
+#define JUNO_NS_DRAM1_PT1_END (JUNO_MEDIA_TZC_PROT_DRAM1_BASE - 1)
+#define JUNO_NS_DRAM1_PT1_SIZE (JUNO_NS_DRAM1_PT1_END - \
+ JUNO_NS_DRAM1_PT1_BASE + 1)
+
+/* TZC filter flags */
+#define JUNO_MEDIA_TZC_NS_DEV_ACCESS (PLAT_ARM_TZC_NS_DEV_ACCESS | \
+ TZC_REGION_ACCESS_RD(JUNO_TZC400_NSAID_FPGA_MEDIA_SECURE))
+
+/* VPU / GPU /DPU protected access */
+#define JUNO_MEDIA_TZC_PROT_ACCESS \
+ (TZC_REGION_ACCESS_RDWR(JUNO_TZC400_NSAID_FPGA_MEDIA_SECURE) | \
+ TZC_REGION_ACCESS_WR(TZC400_NSAID_AP))
+
+#define JUNO_VPU_TZC_PROT_ACCESS \
+ (TZC_REGION_ACCESS_RDWR(JUNO_TZC400_NSAID_FPGA_VIDEO_PROTECTED))
+
+#define JUNO_VPU_TZC_PRIV_ACCESS \
+ (TZC_REGION_ACCESS_RDWR(JUNO_TZC400_NSAID_FPGA_VIDEO_PRIVATE))
+
+/*******************************************************************************
+ * Mali-DP650 related constants
+ ******************************************************************************/
+/* Base address of DP650 */
+#define DP650_BASE 0x6f200000
+/* offset to PROT_NSAID register */
+#define DP650_PROT_NSAID_OFFSET 0x10004
+/* config to PROT_NSAID register */
+#define DP650_PROT_NSAID_CONFIG 0x08008888
+
+/*******************************************************************************
+ * Mali-V550 related constants
+ ******************************************************************************/
+/* Base address of V550 */
+#define V550_BASE 0x6f030000
+/* offset to PROTCTRL register */
+#define V550_PROTCTRL_OFFSET 0x0040
+/* config to PROTCTRL register */
+#define V550_PROTCTRL_CONFIG 0xa8700000
+
+#endif /* __JUNO_TZMP1_DEF_H__ */
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index 656fc14..3ab99ef 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -31,6 +31,13 @@
$(eval $(call assert_boolean,JUNO_AARCH32_EL3_RUNTIME))
$(eval $(call add_define,JUNO_AARCH32_EL3_RUNTIME))
+# Flag to enable support for TZMP1 on JUNO
+JUNO_TZMP1 := 0
+$(eval $(call assert_boolean,JUNO_TZMP1))
+ifeq (${JUNO_TZMP1}, 1)
+$(eval $(call add_define,JUNO_TZMP1))
+endif
+
ifeq (${JUNO_AARCH32_EL3_RUNTIME}, 1)
# Include BL32 in FIP
NEED_BL32 := yes
diff --git a/plat/arm/common/aarch64/arm_ehf.c b/plat/arm/common/aarch64/arm_ehf.c
index 785b7bb..665871b 100644
--- a/plat/arm/common/aarch64/arm_ehf.c
+++ b/plat/arm/common/aarch64/arm_ehf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,6 +11,11 @@
* Enumeration of priority levels on ARM platforms.
*/
ehf_pri_desc_t arm_exceptions[] = {
+#if RAS_EXTENSION
+ /* RAS Priority */
+ EHF_PRI_DESC(ARM_PRI_BITS, PLAT_RAS_PRI),
+#endif
+
#if SDEI_SUPPORT
/* Critical priority SDEI */
EHF_PRI_DESC(ARM_PRI_BITS, PLAT_SDEI_CRITICAL_PRI),
diff --git a/plat/arm/common/aarch64/arm_ras.c b/plat/arm/common/aarch64/arm_ras.c
new file mode 100644
index 0000000..80dfaf1
--- /dev/null
+++ b/plat/arm/common/aarch64/arm_ras.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <ras.h>
+
+struct ras_interrupt arm_ras_interrupts[] = {
+};
+
+struct err_record_info arm_err_records[] = {
+};
+
+REGISTER_ERR_RECORD_INFO(arm_err_records);
+REGISTER_RAS_INTERRUPTS(arm_ras_interrupts);
diff --git a/plat/arm/common/arm_bl1_fwu.c b/plat/arm/common/arm_bl1_fwu.c
index 1305934..f2be477 100644
--- a/plat/arm/common/arm_bl1_fwu.c
+++ b/plat/arm/common/arm_bl1_fwu.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,6 +9,7 @@
#include <debug.h>
#include <errno.h>
#include <plat_arm.h>
+#include <platform.h>
#include <platform_def.h>
#include <tbbr_img_desc.h>
#include <utils.h>
@@ -19,7 +20,7 @@
unsigned int mem_size;
} bl1_mem_info_t;
-bl1_mem_info_t fwu_addr_map_secure[] = {
+static bl1_mem_info_t fwu_addr_map_secure[] = {
{
.mem_base = ARM_SHARED_RAM_BASE,
.mem_size = ARM_SHARED_RAM_SIZE
@@ -29,7 +30,7 @@
}
};
-bl1_mem_info_t fwu_addr_map_non_secure[] = {
+static bl1_mem_info_t fwu_addr_map_non_secure[] = {
{
.mem_base = ARM_NS_DRAM1_BASE,
.mem_size = ARM_NS_DRAM1_SIZE
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 8a6c768..dc7cd68 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -219,7 +219,7 @@
plat_arm_security_setup();
#if defined(PLAT_ARM_MEM_PROT_ADDR)
- arm_nor_psci_do_mem_protect();
+ arm_nor_psci_do_static_mem_protect();
#endif
}
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index 963c4d2..551e700 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -14,6 +14,7 @@
#include <mmio.h>
#include <plat_arm.h>
#include <platform.h>
+#include <ras.h>
#define BL31_END (uintptr_t)(&__BL31_END__)
@@ -80,7 +81,7 @@
assert(from_bl2 == NULL);
assert(plat_params_from_bl2 == NULL);
-#ifdef BL32_BASE
+# ifdef BL32_BASE
/* Populate entry point information for BL32 */
SET_PARAM_HEAD(&bl32_image_ep_info,
PARAM_EP,
@@ -89,7 +90,7 @@
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();
-#endif /* BL32_BASE */
+# endif /* BL32_BASE */
/* Populate entry point information for BL33 */
SET_PARAM_HEAD(&bl33_image_ep_info,
@@ -105,6 +106,19 @@
bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry();
SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+# if ARM_LINUX_KERNEL_AS_BL33
+ /*
+ * According to the file ``Documentation/arm64/booting.txt`` of the
+ * Linux kernel tree, Linux expects the physical address of the device
+ * tree blob (DTB) in x0, while x1-x3 are reserved for future use and
+ * must be 0.
+ */
+ bl33_image_ep_info.args.arg0 = (u_register_t)ARM_PRELOADED_DTB_BASE;
+ bl33_image_ep_info.args.arg1 = 0U;
+ bl33_image_ep_info.args.arg2 = 0U;
+ bl33_image_ep_info.args.arg3 = 0U;
+# endif
+
#else /* RESET_TO_BL31 */
/*
@@ -206,6 +220,10 @@
*/
plat_arm_security_setup();
+#if defined(PLAT_ARM_MEM_PROT_ADDR)
+ arm_nor_psci_do_dyn_mem_protect();
+#endif /* PLAT_ARM_MEM_PROT_ADDR */
+
#endif /* RESET_TO_BL31 */
/* Enable and initialize the System level generic timer */
@@ -217,6 +235,10 @@
/* Initialize power controller before setting up topology */
plat_arm_pwrc_setup();
+
+#if RAS_EXTENSION
+ ras_init();
+#endif
}
/*******************************************************************************
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 015e454..1218548 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -80,6 +80,27 @@
$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1))
$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1))
+# Don't have the Linux kernel as a BL33 image by default
+ARM_LINUX_KERNEL_AS_BL33 := 0
+$(eval $(call assert_boolean,ARM_LINUX_KERNEL_AS_BL33))
+$(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33))
+
+ifeq (${ARM_LINUX_KERNEL_AS_BL33},1)
+ ifneq (${ARCH},aarch64)
+ $(error "ARM_LINUX_KERNEL_AS_BL33 is only available in AArch64.")
+ endif
+ ifneq (${RESET_TO_BL31},1)
+ $(error "ARM_LINUX_KERNEL_AS_BL33 is only available if RESET_TO_BL31=1.")
+ endif
+ ifndef PRELOADED_BL33_BASE
+ $(error "PRELOADED_BL33_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is used.")
+ endif
+ ifndef ARM_PRELOADED_DTB_BASE
+ $(error "ARM_PRELOADED_DTB_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is used.")
+ endif
+ $(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
+endif
+
# Use an implementation of SHA-256 with a smaller memory footprint but reduced
# speed.
$(eval $(call add_define,MBEDTLS_SHA256_SMALLER))
@@ -203,6 +224,13 @@
BL31_SOURCES += plat/arm/common/aarch64/arm_sdei.c
endif
+# RAS sources
+ifeq (${RAS_EXTENSION},1)
+BL31_SOURCES += lib/extensions/ras/std_err_record.c \
+ lib/extensions/ras/ras_common.c \
+ plat/arm/common/aarch64/arm_ras.c
+endif
+
ifneq (${TRUSTED_BOARD_BOOT},0)
# Include common TBB sources
diff --git a/plat/arm/common/arm_dyn_cfg_helpers.c b/plat/arm/common/arm_dyn_cfg_helpers.c
index cfcbf2a..9ba51a3 100644
--- a/plat/arm/common/arm_dyn_cfg_helpers.c
+++ b/plat/arm/common/arm_dyn_cfg_helpers.c
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <arm_dyn_cfg_helpers.h>
#include <assert.h>
#include <desc_image_load.h>
#include <fdt_wrappers.h>
diff --git a/plat/arm/common/arm_nor_psci_mem_protect.c b/plat/arm/common/arm_nor_psci_mem_protect.c
index 3167a42..c01e4ed 100644
--- a/plat/arm/common/arm_nor_psci_mem_protect.c
+++ b/plat/arm/common/arm_nor_psci_mem_protect.c
@@ -12,10 +12,22 @@
#include <psci.h>
#include <utils.h>
+
+/*
+ * DRAM1 is used also to load the NS boot loader. For this reason we
+ * cannot clear the full DRAM1, because in that case we would clear
+ * the NS images (especially for RESET_TO_BL31 and RESET_TO_SPMIN cases).
+ * For this reason we reserve 64 MB for the NS images and protect the RAM
+ * until the end of DRAM1.
+ * We limit the size of DRAM2 to 1 GB to avoid big delays while booting
+ */
+#define DRAM1_NS_IMAGE_LIMIT (PLAT_ARM_NS_IMAGE_OFFSET + (32 << TWO_MB_SHIFT))
+#define DRAM1_PROTECTED_SIZE (ARM_NS_DRAM1_END+1u - DRAM1_NS_IMAGE_LIMIT)
+
static mem_region_t arm_ram_ranges[] = {
- {ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_SIZE},
+ {DRAM1_NS_IMAGE_LIMIT, DRAM1_PROTECTED_SIZE},
#ifdef AARCH64
- {ARM_DRAM2_BASE, ARM_DRAM2_SIZE},
+ {ARM_DRAM2_BASE, 1u << ONE_GB_SHIFT},
#endif
};
@@ -29,7 +41,7 @@
int tmp;
tmp = *(int *) PLAT_ARM_MEM_PROT_ADDR;
- *enabled = (tmp == 1);
+ *enabled = (tmp == 1) ? 1 : 0;
return 0;
}
@@ -46,7 +58,7 @@
return -1;
}
- if (enable) {
+ if (enable != 0) {
/*
* If we want to write a value different than 0
* then we have to erase the full block because
@@ -71,15 +83,47 @@
* Function used for required psci operations performed when
* system boots
******************************************************************************/
-void arm_nor_psci_do_mem_protect(void)
+/*
+ * PLAT_MEM_PROTECT_VA_FRAME is a address specifically
+ * selected in a way that is not needed an additional
+ * translation table for memprotect. It happens because
+ * we use a chunk of size 2MB and it means that it can
+ * be mapped in a level 2 table and the level 2 table
+ * for 0xc0000000 is already used and the entry for
+ * 0xc0000000 is not used.
+ */
+#if defined(PLAT_XLAT_TABLES_DYNAMIC)
+void arm_nor_psci_do_dyn_mem_protect(void)
{
int enable;
arm_psci_read_mem_protect(&enable);
- if (!enable)
+ if (enable == 0)
return;
- INFO("PSCI: Overwritting non secure memory\n");
- clear_mem_regions(arm_ram_ranges, ARRAY_SIZE(arm_ram_ranges));
+
+ INFO("PSCI: Overwriting non secure memory\n");
+ clear_map_dyn_mem_regions(arm_ram_ranges,
+ ARRAY_SIZE(arm_ram_ranges),
+ PLAT_ARM_MEM_PROTEC_VA_FRAME,
+ 1 << TWO_MB_SHIFT);
+}
+#endif
+
+/*******************************************************************************
+ * Function used for required psci operations performed when
+ * system boots and dynamic memory is not used.
+ ******************************************************************************/
+void arm_nor_psci_do_static_mem_protect(void)
+{
+ int enable;
+
+ arm_psci_read_mem_protect(&enable);
+ if (enable == 0)
+ return;
+
+ INFO("PSCI: Overwriting non secure memory\n");
+ clear_mem_regions(arm_ram_ranges,
+ ARRAY_SIZE(arm_ram_ranges));
arm_nor_psci_write_mem_protect(0);
}
diff --git a/plat/arm/common/arm_tzc400.c b/plat/arm/common/arm_tzc400.c
index 6b706be..a32736c 100644
--- a/plat/arm/common/arm_tzc400.c
+++ b/plat/arm/common/arm_tzc400.c
@@ -18,16 +18,20 @@
/*******************************************************************************
* Initialize the TrustZone Controller for ARM standard platforms.
- * Configure:
- * - Region 0 with no access;
- * - Region 1 with secure access only;
- * - the remaining DRAM regions access from the given Non-Secure masters.
- *
* When booting an EL3 payload, this is simplified: we configure region 0 with
* secure access only and do not enable any other region.
******************************************************************************/
-void arm_tzc400_setup(void)
+void arm_tzc400_setup(const arm_tzc_regions_info_t *tzc_regions)
{
+#ifndef EL3_PAYLOAD_BASE
+ int region_index = 1;
+ const arm_tzc_regions_info_t *p;
+ const arm_tzc_regions_info_t init_tzc_regions[] = {
+ ARM_TZC_REGIONS_DEF,
+ {0}
+ };
+#endif
+
INFO("Configuring TrustZone Controller\n");
tzc400_init(PLAT_ARM_TZC_BASE);
@@ -36,42 +40,22 @@
tzc400_disable_filters();
#ifndef EL3_PAYLOAD_BASE
+ if (tzc_regions == NULL)
+ p = init_tzc_regions;
+ else
+ p = tzc_regions;
/* Region 0 set to no access by default */
tzc400_configure_region0(TZC_REGION_S_NONE, 0);
- /* Region 1 set to cover Secure part of DRAM */
- tzc400_configure_region(PLAT_ARM_TZC_FILTERS, 1,
- ARM_AP_TZC_DRAM1_BASE, ARM_EL3_TZC_DRAM1_END,
- TZC_REGION_S_RDWR,
- 0);
-
- /* Region 2 set to cover Non-Secure access to 1st DRAM address range.
- * Apply the same configuration to given filters in the TZC. */
- tzc400_configure_region(PLAT_ARM_TZC_FILTERS, 2,
- ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_END,
- ARM_TZC_NS_DRAM_S_ACCESS,
- PLAT_ARM_TZC_NS_DEV_ACCESS);
+ /* Rest Regions set according to tzc_regions array */
+ for (; p->base != 0ULL; p++) {
+ tzc400_configure_region(PLAT_ARM_TZC_FILTERS, region_index,
+ p->base, p->end, p->sec_attr, p->nsaid_permissions);
+ region_index++;
+ }
- /* Region 3 set to cover Non-Secure access to 2nd DRAM address range */
- tzc400_configure_region(PLAT_ARM_TZC_FILTERS, 3,
- ARM_DRAM2_BASE, ARM_DRAM2_END,
- ARM_TZC_NS_DRAM_S_ACCESS,
- PLAT_ARM_TZC_NS_DEV_ACCESS);
-
-#if ENABLE_SPM
- /*
- * Region 4 set to cover Non-Secure access to the communication buffer
- * shared with the Secure world.
- */
- tzc400_configure_region(PLAT_ARM_TZC_FILTERS,
- 4,
- ARM_SP_IMAGE_NS_BUF_BASE,
- (ARM_SP_IMAGE_NS_BUF_BASE +
- ARM_SP_IMAGE_NS_BUF_SIZE) - 1,
- TZC_REGION_S_NONE,
- PLAT_ARM_TZC_NS_DEV_ACCESS);
-#endif
+ INFO("Total %d regions set.\n", region_index);
#else /* if defined(EL3_PAYLOAD_BASE) */
@@ -92,5 +76,5 @@
void plat_arm_security_setup(void)
{
- arm_tzc400_setup();
+ arm_tzc400_setup(NULL);
}
diff --git a/plat/arm/common/arm_tzc_dmc500.c b/plat/arm/common/arm_tzc_dmc500.c
index 8e41391..89c502c 100644
--- a/plat/arm/common/arm_tzc_dmc500.c
+++ b/plat/arm/common/arm_tzc_dmc500.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,15 +12,21 @@
/*******************************************************************************
* Initialize the DMC500-TrustZone Controller for ARM standard platforms.
- * Configure both the interfaces on Region 0 with no access, Region 1 with
- * secure access only, and the remaining DRAM regions access from the
- * given Non-Secure masters.
- *
* When booting an EL3 payload, this is simplified: we configure region 0 with
* secure access only and do not enable any other region.
******************************************************************************/
-void arm_tzc_dmc500_setup(tzc_dmc500_driver_data_t *plat_driver_data)
+void arm_tzc_dmc500_setup(tzc_dmc500_driver_data_t *plat_driver_data,
+ const arm_tzc_regions_info_t *tzc_regions)
{
+#ifndef EL3_PAYLOAD_BASE
+ int region_index = 1;
+ const arm_tzc_regions_info_t *p;
+ const arm_tzc_regions_info_t init_tzc_regions[] = {
+ ARM_TZC_REGIONS_DEF,
+ {0}
+ };
+#endif
+
assert(plat_driver_data);
INFO("Configuring DMC-500 TZ Settings\n");
@@ -28,28 +34,23 @@
tzc_dmc500_driver_init(plat_driver_data);
#ifndef EL3_PAYLOAD_BASE
+ if (tzc_regions == NULL)
+ p = init_tzc_regions;
+ else
+ p = tzc_regions;
+
/* Region 0 set to no access by default */
tzc_dmc500_configure_region0(TZC_REGION_S_NONE, 0);
- /* Region 1 set to cover Secure part of DRAM */
- tzc_dmc500_configure_region(1, ARM_AP_TZC_DRAM1_BASE,
- ARM_EL3_TZC_DRAM1_END,
- TZC_REGION_S_RDWR,
- 0);
+ /* Rest Regions set according to tzc_regions array */
+ for (; p->base != 0ULL; p++) {
+ tzc_dmc500_configure_region(region_index, p->base, p->end,
+ p->sec_attr, p->nsaid_permissions);
+ region_index++;
+ }
- /* Region 2 set to cover Non-Secure access to 1st DRAM address range.*/
- tzc_dmc500_configure_region(2,
- ARM_NS_DRAM1_BASE,
- ARM_NS_DRAM1_END,
- ARM_TZC_NS_DRAM_S_ACCESS,
- PLAT_ARM_TZC_NS_DEV_ACCESS);
+ INFO("Total %d regions set.\n", region_index);
- /* Region 3 set to cover Non-Secure access to 2nd DRAM address range */
- tzc_dmc500_configure_region(3,
- ARM_DRAM2_BASE,
- ARM_DRAM2_END,
- ARM_TZC_NS_DRAM_S_ACCESS,
- PLAT_ARM_TZC_NS_DEV_ACCESS);
#else
/* Allow secure access only to DRAM for EL3 payloads */
tzc_dmc500_configure_region0(TZC_REGION_S_RDWR, 0);
diff --git a/plat/arm/common/sp_min/arm_sp_min_setup.c b/plat/arm/common/sp_min/arm_sp_min_setup.c
index 7b5477e..9a6c074 100644
--- a/plat/arm/common/sp_min/arm_sp_min_setup.c
+++ b/plat/arm/common/sp_min/arm_sp_min_setup.c
@@ -162,6 +162,11 @@
*/
#if RESET_TO_SP_MIN
plat_arm_security_setup();
+
+#if defined(PLAT_ARM_MEM_PROT_ADDR)
+ arm_nor_psci_do_dyn_mem_protect();
+#endif /* PLAT_ARM_MEM_PROT_ADDR */
+
#endif
/* Enable and initialize the System level generic timer */
diff --git a/plat/arm/css/common/css_common.mk b/plat/arm/css/common/css_common.mk
index cfbb3e9..72d5527 100644
--- a/plat/arm/css/common/css_common.mk
+++ b/plat/arm/css/common/css_common.mk
@@ -28,13 +28,14 @@
ifeq (${CSS_USE_SCMI_SDS_DRIVER},0)
BL31_SOURCES += plat/arm/css/drivers/scp/css_pm_scpi.c \
- plat/arm/css/drivers/scpi/css_mhu.c \
+ plat/arm/css/drivers/mhu/css_mhu.c \
plat/arm/css/drivers/scpi/css_scpi.c
else
BL31_SOURCES += plat/arm/css/drivers/scp/css_pm_scmi.c \
plat/arm/css/drivers/scmi/scmi_common.c \
plat/arm/css/drivers/scmi/scmi_pwr_dmn_proto.c \
- plat/arm/css/drivers/scmi/scmi_sys_pwr_proto.c
+ plat/arm/css/drivers/scmi/scmi_sys_pwr_proto.c \
+ plat/arm/css/drivers/mhu/css_mhu_doorbell.c
endif
ifneq (${RESET_TO_BL31},0)
@@ -60,11 +61,11 @@
plat/arm/css/drivers/sds/sds.c
else
BL2U_SOURCES += plat/arm/css/drivers/scp/css_bom_bootloader.c \
- plat/arm/css/drivers/scpi/css_mhu.c \
+ plat/arm/css/drivers/mhu/css_mhu.c \
plat/arm/css/drivers/scpi/css_scpi.c
BL2_SOURCES += plat/arm/css/drivers/scp/css_bom_bootloader.c \
- plat/arm/css/drivers/scpi/css_mhu.c \
+ plat/arm/css/drivers/mhu/css_mhu.c \
plat/arm/css/drivers/scpi/css_scpi.c
# Enable option to detect whether the SCP ROM firmware in use predates version
# 1.7.0 and therefore, is incompatible.
diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c
index 4a615e1..3df5b78 100644
--- a/plat/arm/css/common/css_pm.c
+++ b/plat/arm/css/common/css_pm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -303,11 +303,8 @@
.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,
-/*
- * mem_protect is not supported in RESET_TO_BL31 and RESET_TO_SP_MIN,
- * as that would require mapping in all of NS DRAM into BL31 or BL32.
- */
-#if defined(PLAT_ARM_MEM_PROT_ADDR) && !RESET_TO_BL31 && !RESET_TO_SP_MIN
+
+#if defined(PLAT_ARM_MEM_PROT_ADDR)
.mem_protect_chk = arm_psci_mem_protect_chk,
.read_mem_protect = arm_psci_read_mem_protect,
.write_mem_protect = arm_nor_psci_write_mem_protect,
diff --git a/plat/arm/css/common/css_topology.c b/plat/arm/css/common/css_topology.c
index bccf2c8..42f9455 100644
--- a/plat/arm/css/common/css_topology.c
+++ b/plat/arm/css/common/css_topology.c
@@ -6,6 +6,7 @@
#include <plat_arm.h>
#include <platform.h>
+#include <assert.h>
#if ARM_PLAT_MT
#pragma weak plat_arm_get_cpu_pe_count
@@ -19,9 +20,12 @@
*****************************************************************************/
int plat_core_pos_by_mpidr(u_register_t mpidr)
{
- if (arm_check_mpidr(mpidr) == 0)
+ if (arm_check_mpidr(mpidr) == 0) {
+#if ARM_PLAT_MT
+ assert((read_mpidr_el1() & MPIDR_MT_MASK) != 0);
+#endif
return plat_arm_calc_core_pos(mpidr);
-
+ }
return -1;
}
diff --git a/plat/arm/css/common/sp_min/css_sp_min.mk b/plat/arm/css/common/sp_min/css_sp_min.mk
index 28eb2db..9fb280c 100644
--- a/plat/arm/css/common/sp_min/css_sp_min.mk
+++ b/plat/arm/css/common/sp_min/css_sp_min.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -10,11 +10,12 @@
ifeq (${CSS_USE_SCMI_SDS_DRIVER},0)
BL32_SOURCES += plat/arm/css/drivers/scp/css_pm_scpi.c \
- plat/arm/css/drivers/scpi/css_mhu.c \
+ plat/arm/css/drivers/mhu/css_mhu.c \
plat/arm/css/drivers/scpi/css_scpi.c
else
BL32_SOURCES += plat/arm/css/drivers/scp/css_pm_scmi.c \
plat/arm/css/drivers/scmi/scmi_common.c \
plat/arm/css/drivers/scmi/scmi_pwr_dmn_proto.c \
- plat/arm/css/drivers/scmi/scmi_sys_pwr_proto.c
+ plat/arm/css/drivers/scmi/scmi_sys_pwr_proto.c \
+ plat/arm/css/drivers/mhu/css_mhu_doorbell.c
endif
diff --git a/plat/arm/css/drivers/scpi/css_mhu.c b/plat/arm/css/drivers/mhu/css_mhu.c
similarity index 96%
rename from plat/arm/css/drivers/scpi/css_mhu.c
rename to plat/arm/css/drivers/mhu/css_mhu.c
index 500b8df..30492a6 100644
--- a/plat/arm/css/drivers/scpi/css_mhu.c
+++ b/plat/arm/css/drivers/mhu/css_mhu.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
diff --git a/plat/arm/css/drivers/scpi/css_mhu.h b/plat/arm/css/drivers/mhu/css_mhu.h
similarity index 85%
rename from plat/arm/css/drivers/scpi/css_mhu.h
rename to plat/arm/css/drivers/mhu/css_mhu.h
index 298eee9..0fb00c7 100644
--- a/plat/arm/css/drivers/scpi/css_mhu.h
+++ b/plat/arm/css/drivers/mhu/css_mhu.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
diff --git a/plat/arm/css/drivers/mhu/css_mhu_doorbell.c b/plat/arm/css/drivers/mhu/css_mhu_doorbell.c
new file mode 100644
index 0000000..b9faf67
--- /dev/null
+++ b/plat/arm/css/drivers/mhu/css_mhu_doorbell.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <platform_def.h>
+#include "css_mhu_doorbell.h"
+#include "../scmi/scmi.h"
+
+void mhu_ring_doorbell(scmi_channel_plat_info_t *plat_info)
+{
+ MHU_RING_DOORBELL(plat_info->db_reg_addr,
+ plat_info->db_modify_mask,
+ plat_info->db_preserve_mask);
+ return;
+}
+
+void mhuv2_ring_doorbell(scmi_channel_plat_info_t *plat_info)
+{
+ /* wake receiver */
+ MHU_V2_ACCESS_REQUEST(MHUV2_BASE_ADDR);
+
+ /* wait for receiver to acknowledge its ready */
+ while (MHU_V2_IS_ACCESS_READY(MHUV2_BASE_ADDR) == 0)
+ ;
+
+ MHU_RING_DOORBELL(plat_info->db_reg_addr,
+ plat_info->db_modify_mask,
+ plat_info->db_preserve_mask);
+
+ /* clear the access request for the recevier */
+ MHU_V2_CLEAR_REQUEST(MHUV2_BASE_ADDR);
+
+ return;
+}
diff --git a/plat/arm/css/drivers/mhu/css_mhu_doorbell.h b/plat/arm/css/drivers/mhu/css_mhu_doorbell.h
new file mode 100644
index 0000000..3c94536
--- /dev/null
+++ b/plat/arm/css/drivers/mhu/css_mhu_doorbell.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CSS_MHU_DOORBELL_H
+#define CSS_MHU_DOORBELL_H
+
+#include <mmio.h>
+#include <stdint.h>
+
+/* MHUv2 Base Address */
+#define MHUV2_BASE_ADDR PLAT_CSS_MHU_BASE
+
+/* MHUv2 Control Registers Offsets */
+#define MHU_V2_MSG_NO_CAP_OFFSET 0xF80
+#define MHU_V2_ACCESS_REQ_OFFSET 0xF88
+#define MHU_V2_ACCESS_READY_OFFSET 0xF8C
+
+#define SENDER_REG_STAT(CHANNEL) (0x20 * (CHANNEL))
+#define SENDER_REG_SET(CHANNEL) (0x20 * (CHANNEL)) + 0xC
+
+/* Helper macro to ring doorbell */
+#define MHU_RING_DOORBELL(addr, modify_mask, preserve_mask) do { \
+ uint32_t db = mmio_read_32(addr) & (preserve_mask); \
+ mmio_write_32(addr, db | (modify_mask)); \
+ } while (0)
+
+#define MHU_V2_ACCESS_REQUEST(addr) \
+ mmio_write_32((addr) + MHU_V2_ACCESS_REQ_OFFSET, 0x1)
+
+#define MHU_V2_CLEAR_REQUEST(addr) \
+ mmio_write_32((addr) + MHU_V2_ACCESS_REQ_OFFSET, 0x0)
+
+#define MHU_V2_IS_ACCESS_READY(addr) \
+ (mmio_read_32((addr) + MHU_V2_ACCESS_READY_OFFSET) & 0x1)
+
+struct scmi_channel_plat_info;
+void mhu_ring_doorbell(struct scmi_channel_plat_info *plat_info);
+void mhuv2_ring_doorbell(struct scmi_channel_plat_info *plat_info);
+
+#endif /* CSS_MHU_DOORBELL_H */
diff --git a/plat/arm/css/drivers/scmi/scmi.h b/plat/arm/css/drivers/scmi/scmi.h
index 850402a..cf9ef5e 100644
--- a/plat/arm/css/drivers/scmi/scmi.h
+++ b/plat/arm/css/drivers/scmi/scmi.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -96,6 +96,10 @@
uint32_t db_preserve_mask;
/* The bit mask that need to be set to ring doorbell */
uint32_t db_modify_mask;
+ /* The handler for ringing doorbell */
+ void (*ring_doorbell)(struct scmi_channel_plat_info *plat_info);
+ /* cookie is unused now. But added for future enhancements. */
+ void *cookie;
} scmi_channel_plat_info_t;
/*
diff --git a/plat/arm/css/drivers/scmi/scmi_common.c b/plat/arm/css/drivers/scmi/scmi_common.c
index d0051c7..8482d21 100644
--- a/plat/arm/css/drivers/scmi/scmi_common.c
+++ b/plat/arm/css/drivers/scmi/scmi_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -39,9 +39,7 @@
*/
dmbst();
- SCMI_RING_DOORBELL(ch->info->db_reg_addr, ch->info->db_modify_mask,
- ch->info->db_preserve_mask);
-
+ ch->info->ring_doorbell(ch->info);
/*
* Ensure that the write to the doorbell register is ordered prior to
* checking whether the channel is free.
@@ -150,6 +148,7 @@
assert(ch->info->db_reg_addr);
assert(ch->info->db_modify_mask);
assert(ch->info->db_preserve_mask);
+ assert(ch->info->ring_doorbell != NULL);
assert(ch->lock);
diff --git a/plat/arm/css/drivers/scmi/scmi_private.h b/plat/arm/css/drivers/scmi/scmi_private.h
index 20e1e9b..a07841e 100644
--- a/plat/arm/css/drivers/scmi/scmi_private.h
+++ b/plat/arm/css/drivers/scmi/scmi_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -113,12 +113,6 @@
(val3) = mmio_read_32((uintptr_t)&payld_arr[2]); \
} while (0)
-/* Helper macro to ring doorbell */
-#define SCMI_RING_DOORBELL(addr, modify_mask, preserve_mask) do { \
- uint32_t db = mmio_read_32(addr) & (preserve_mask); \
- mmio_write_32(addr, db | (modify_mask)); \
- } while (0)
-
/*
* Private data structure for representing the mailbox memory layout. Refer
* the SCMI specification for more details.
diff --git a/plat/arm/css/drivers/scp/css_bom_bootloader.c b/plat/arm/css/drivers/scp/css_bom_bootloader.c
index 08d6fc5..42ed30d 100644
--- a/plat/arm/css/drivers/scp/css_bom_bootloader.c
+++ b/plat/arm/css/drivers/scp/css_bom_bootloader.c
@@ -10,7 +10,7 @@
#include <debug.h>
#include <platform.h>
#include <stdint.h>
-#include "../scpi/css_mhu.h"
+#include "../mhu/css_mhu.h"
#include "../scpi/css_scpi.h"
#include "css_scp.h"
diff --git a/plat/arm/css/drivers/scp/css_pm_scmi.c b/plat/arm/css/drivers/scp/css_pm_scmi.c
index f8bc20c..c0ed487 100644
--- a/plat/arm/css/drivers/scp/css_pm_scmi.c
+++ b/plat/arm/css/drivers/scp/css_pm_scmi.c
@@ -13,6 +13,7 @@
#include <platform.h>
#include <string.h>
#include "../scmi/scmi.h"
+#include "../mhu/css_mhu_doorbell.h"
#include "css_scp.h"
/*
@@ -76,7 +77,7 @@
* Helper function to suspend a CPU power domain and its parent power domains
* if applicable.
*/
-void css_scp_suspend(const psci_power_state_t *target_state)
+void css_scp_suspend(const struct psci_power_state *target_state)
{
int lvl, ret;
uint32_t scmi_pwr_state = 0;
@@ -302,6 +303,7 @@
.db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF,
.db_preserve_mask = 0xfffffffe,
.db_modify_mask = 0x1,
+ .ring_doorbell = &mhu_ring_doorbell,
};
void plat_arm_pwrc_setup(void)
diff --git a/plat/arm/css/drivers/scp/css_pm_scpi.c b/plat/arm/css/drivers/scp/css_pm_scpi.c
index 545c3fb..23fd80e 100644
--- a/plat/arm/css/drivers/scp/css_pm_scpi.c
+++ b/plat/arm/css/drivers/scp/css_pm_scpi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -19,7 +19,7 @@
/*
* Helper function to inform power down state to SCP.
*/
-void css_scp_suspend(const psci_power_state_t *target_state)
+void css_scp_suspend(const struct psci_power_state *target_state)
{
uint32_t cluster_state = scpi_power_on;
uint32_t system_state = scpi_power_on;
diff --git a/plat/arm/css/drivers/scpi/css_scpi.c b/plat/arm/css/drivers/scpi/css_scpi.c
index 3e92c86..2ed5760 100644
--- a/plat/arm/css/drivers/scpi/css_scpi.c
+++ b/plat/arm/css/drivers/scpi/css_scpi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,7 +11,7 @@
#include <platform.h>
#include <string.h>
#include <utils.h>
-#include "css_mhu.h"
+#include "../mhu/css_mhu.h"
#include "css_scpi.h"
#define SCPI_SHARED_MEM_SCP_TO_AP PLAT_CSS_SCP_COM_SHARED_MEM_BASE
diff --git a/plat/arm/css/sgi/aarch64/sgi_helper.S b/plat/arm/css/sgi/aarch64/sgi_helper.S
index c435d8b..aaa5156 100644
--- a/plat/arm/css/sgi/aarch64/sgi_helper.S
+++ b/plat/arm/css/sgi/aarch64/sgi_helper.S
@@ -31,19 +31,37 @@
endfunc plat_is_my_cpu_primary
/* -----------------------------------------------------
- * unsigned int plat_arm_calc_core_pos(uint64_t mpidr)
- * Helper function to calculate the core position.
- * -----------------------------------------------------
- */
+ * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
+ *
+ * Helper function to calculate the core position.
+ * (ClusterId * CSS_SGI_MAX_CPUS_PER_CLUSTER * CSS_SGI_MAX_PE_PER_CPU) +
+ * (CPUId * CSS_SGI_MAX_PE_PER_CPU) +
+ * ThreadId
+ *
+ * which can be simplified as:
+ *
+ * ((ClusterId * CSS_SGI_MAX_CPUS_PER_CLUSTER + CPUId) *
+ * CSS_SGI_MAX_PE_PER_CPU) + ThreadId
+ * ------------------------------------------------------
+ */
+
func plat_arm_calc_core_pos
- mrs x2, mpidr_el1
- ands x2, x2, #MPIDR_MT_MASK
- beq 1f
- lsr x0, x0, #MPIDR_AFF1_SHIFT
-1:
- and x1, x0, #MPIDR_CPU_MASK
- and x0, x0, #MPIDR_CLUSTER_MASK
- add x0, x1, x0, LSR #6
- and x0, x0, #MPIDR_AFFLVL_MASK
+ mov x3, x0
+
+ /*
+ * The MT bit in MPIDR is always set for SGI platforms
+ * and the affinity level 0 corresponds to thread affinity level.
+ */
+
+ /* Extract individual affinity fields from MPIDR */
+ ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+
+ /* Compute linear position */
+ mov x4, #CSS_SGI_MAX_CPUS_PER_CLUSTER
+ madd x1, x2, x4, x1
+ mov x5, #CSS_SGI_MAX_PE_PER_CPU
+ madd x0, x1, x5, x0
ret
endfunc plat_arm_calc_core_pos
diff --git a/plat/arm/css/sgi/include/platform_def.h b/plat/arm/css/sgi/include/platform_def.h
index 62f4059..0f02407 100644
--- a/plat/arm/css/sgi/include/platform_def.h
+++ b/plat/arm/css/sgi/include/platform_def.h
@@ -14,12 +14,14 @@
#include <css_def.h>
#include <soc_css_def.h>
-#define CSS_SGI_MAX_CORES_PER_CLUSTER 4
+#define CSS_SGI_MAX_CPUS_PER_CLUSTER 4
/* CPU topology */
#define PLAT_ARM_CLUSTER_COUNT 2
+#define CSS_SGI_MAX_PE_PER_CPU 1
#define PLATFORM_CORE_COUNT (PLAT_ARM_CLUSTER_COUNT * \
- CSS_SGI_MAX_CORES_PER_CLUSTER)
+ CSS_SGI_MAX_CPUS_PER_CLUSTER * \
+ CSS_SGI_MAX_PE_PER_CPU)
#if ARM_BOARD_OPTIMISE_MEM
@@ -52,6 +54,9 @@
#define PLAT_ARM_TRUSTED_ROM_BASE 0x0
#define PLAT_ARM_TRUSTED_ROM_SIZE 0x00080000 /* 512KB */
+#define PLAT_ARM_NSRAM_BASE 0x06000000
+#define PLAT_ARM_NSRAM_SIZE 0x00080000 /* 512KB */
+
#define PLAT_MAX_PWR_LVL 1
#define PLAT_ARM_G1S_IRQS ARM_G1S_IRQS, \
diff --git a/plat/arm/css/sgi/sgi-common.mk b/plat/arm/css/sgi/sgi-common.mk
index 9c398b7..f6ef95a 100644
--- a/plat/arm/css/sgi/sgi-common.mk
+++ b/plat/arm/css/sgi/sgi-common.mk
@@ -19,7 +19,6 @@
drivers/arm/gic/v3/gicv3_helpers.c \
plat/common/plat_gicv3.c \
plat/arm/common/arm_gicv3.c \
- ${CSS_ENT_BASE}/sgi_gic_config.c \
drivers/arm/gic/v3/gic600.c
@@ -45,6 +44,7 @@
override CSS_LOAD_SCP_IMAGES := 0
override NEED_BL2U := no
override ARM_BL31_IN_DRAM := 1
+override ARM_PLAT_MT := 1
# System coherency is managed in hardware
HW_ASSISTED_COHERENCY := 1
diff --git a/plat/arm/css/sgi/sgi_gic_config.c b/plat/arm/css/sgi/sgi_gic_config.c
deleted file mode 100644
index dfccc1b..0000000
--- a/plat/arm/css/sgi/sgi_gic_config.c
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <sgi_plat_config.h>
-
-void plat_arm_gic_driver_init(void)
-{
- /*
- * The GICv3 driver is initialized in EL3 and does not need
- * to be initialized again in S-EL1. This is because the S-EL1
- * can use GIC system registers to manage interrupts and does
- * not need GIC interface base addresses to be configured.
- */
- gicv3_driver_init(get_plat_config()->gic_data);
-}
diff --git a/plat/arm/css/sgi/sgi_plat_config.c b/plat/arm/css/sgi/sgi_plat_config.c
index 96d31e2..29b99a3 100644
--- a/plat/arm/css/sgi/sgi_plat_config.c
+++ b/plat/arm/css/sgi/sgi_plat_config.c
@@ -18,23 +18,6 @@
/* The GICv3 driver only needs to be initialized in EL3 */
uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
-const interrupt_prop_t sgi575_interrupt_props[] = {
- CSS_G1S_IRQ_PROPS(INTR_GROUP1S),
- ARM_G0_IRQ_PROPS(INTR_GROUP0),
-};
-
-/* Special definition for SGI575 */
-/* GIC configuration for SGI575 */
-const gicv3_driver_data_t sgi575_gic_data = {
- .gicd_base = PLAT_ARM_GICD_BASE,
- .gicr_base = PLAT_ARM_GICR_BASE,
- .interrupt_props = sgi575_interrupt_props,
- .interrupt_props_num = ARRAY_SIZE(sgi575_interrupt_props),
- .rdistif_num = PLATFORM_CORE_COUNT,
- .rdistif_base_addrs = rdistif_base_addrs,
- .mpidr_to_core_pos = plat_arm_calc_core_pos
- };
-
/* Interconnect configuration for SGI575 */
const css_inteconn_config_t sgi575_inteconn = {
.ip_type = ARM_CMN,
@@ -43,7 +26,6 @@
/* Configuration structure for SGI575 */
css_plat_config_t sgi575_config = {
- .gic_data = &sgi575_gic_data,
.inteconn = &sgi575_inteconn,
};
diff --git a/plat/arm/css/sgi/sgi_topology.c b/plat/arm/css/sgi/sgi_topology.c
index 2136591..1d2e027 100644
--- a/plat/arm/css/sgi/sgi_topology.c
+++ b/plat/arm/css/sgi/sgi_topology.c
@@ -16,14 +16,14 @@
*/
const unsigned char sgi_pd_tree_desc[] = {
PLAT_ARM_CLUSTER_COUNT,
- CSS_SGI_MAX_CORES_PER_CLUSTER,
- CSS_SGI_MAX_CORES_PER_CLUSTER
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER
};
/* Topology configuration for sgi platform */
const css_topology_t sgi_topology = {
.power_tree = sgi_pd_tree_desc,
- .plat_cluster_core_count = CSS_SGI_MAX_CORES_PER_CLUSTER
+ .plat_cluster_core_count = CSS_SGI_MAX_CPUS_PER_CLUSTER
};
/*******************************************************************************
diff --git a/plat/common/aarch64/plat_common.c b/plat/common/aarch64/plat_common.c
index ddd29f2..409ae55 100644
--- a/plat/common/aarch64/plat_common.c
+++ b/plat/common/aarch64/plat_common.c
@@ -8,6 +8,9 @@
#include <assert.h>
#include <console.h>
#include <platform.h>
+#if RAS_EXTENSION
+#include <ras.h>
+#endif
#include <xlat_mmu_helpers.h>
/*
@@ -28,6 +31,8 @@
#pragma weak plat_sdei_validate_entry_point
#endif
+#pragma weak plat_ea_handler
+
void bl31_plat_enable_mmu(uint32_t flags)
{
enable_mmu_el3(flags);
@@ -93,7 +98,7 @@
*/
void plat_sdei_handle_masked_trigger(uint64_t mpidr, unsigned int intr)
{
- WARN("Spurious SDEI interrupt %u on masked PE %lx\n", intr, mpidr);
+ WARN("Spurious SDEI interrupt %u on masked PE %llx\n", intr, mpidr);
}
/*
@@ -105,3 +110,20 @@
return 0;
}
#endif
+
+/* RAS functions common to AArch64 ARM platforms */
+void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
+ void *handle, uint64_t flags)
+{
+#if RAS_EXTENSION
+ /* Call RAS EA handler */
+ int handled = ras_ea_handler(ea_reason, syndrome, cookie, handle, flags);
+ if (handled != 0)
+ return;
+#endif
+
+ ERROR("Unhandled External Abort received on 0x%lx at EL3!\n",
+ read_mpidr_el1());
+ ERROR(" exception reason=%u syndrome=0x%llx\n", ea_reason, syndrome);
+ panic();
+}
diff --git a/plat/hisilicon/hikey/hikey_bl1_setup.c b/plat/hisilicon/hikey/hikey_bl1_setup.c
index 28ad9df..da6f6a5 100644
--- a/plat/hisilicon/hikey/hikey_bl1_setup.c
+++ b/plat/hisilicon/hikey/hikey_bl1_setup.c
@@ -172,7 +172,7 @@
__asm__ volatile ("msr cpacr_el1, %0" : : "r"(data));
__asm__ volatile ("mrs %0, cpacr_el1" : "=r"(data));
} while ((data & (3 << 20)) != (3 << 20));
- INFO("cpacr_el1:0x%lx\n", data);
+ INFO("cpacr_el1:0x%llx\n", data);
ep_info->args.arg0 = 0xffff & read_mpidr();
ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
diff --git a/plat/hisilicon/hikey/hikey_bl2_setup.c b/plat/hisilicon/hikey/hikey_bl2_setup.c
index a78bb1e..a3fc607 100644
--- a/plat/hisilicon/hikey/hikey_bl2_setup.c
+++ b/plat/hisilicon/hikey/hikey_bl2_setup.c
@@ -304,15 +304,13 @@
hikey_gpio_init();
hikey_pmussi_init();
hikey_hi6553_init();
+ /* Clear SRAM since it'll be used by MCU right now. */
+ memset((void *)SRAM_BASE, 0, SRAM_SIZE);
dsb();
- hikey_ddr_init();
+ hikey_ddr_init(DDR_FREQ_800M);
hikey_security_setup();
- /* Clear SRAM since it'll be used by MCU right now. */
- memset((void *)SRAM_BASE, 0, SRAM_SIZE);
- clean_dcache_range(SRAM_BASE, SRAM_SIZE);
-
hikey_boardid_init();
init_acpu_dvfs();
hikey_rtc_init();
@@ -321,6 +319,9 @@
hikey_mmc_pll_init();
+ /* Clean SRAM before MCU used */
+ clean_dcache_range(SRAM_BASE, SRAM_SIZE);
+
reset_dwmmc_clk();
memset(¶ms, 0, sizeof(dw_mmc_params_t));
params.reg_base = DWMMC0_BASE;
diff --git a/plat/hisilicon/hikey/hikey_ddr.c b/plat/hisilicon/hikey/hikey_ddr.c
index ab572eb..43cece0 100644
--- a/plat/hisilicon/hikey/hikey_ddr.c
+++ b/plat/hisilicon/hikey/hikey_ddr.c
@@ -5,17 +5,16 @@
*/
#include <arch_helpers.h>
+#include <assert.h>
#include <debug.h>
#include <errno.h>
#include <hi6220.h>
#include <hi6553.h>
+#include <hisi_sram_map.h>
#include <mmio.h>
#include <sp804_delay_timer.h>
-enum {
- DDR_FREQ_533M = 0,
- DDR_FREQ_800M,
-};
+#include "hikey_private.h"
static void init_pll(void)
{
@@ -24,7 +23,6 @@
data = mmio_read_32((0xf7032000 + 0x000));
data |= 0x1;
mmio_write_32((0xf7032000 + 0x000), data);
- dsb();
do {
data = mmio_read_32((0xf7032000 + 0x000));
} while (!(data & (1 << 28)));
@@ -33,22 +31,45 @@
data &= ~0x007;
data |= 0x004;
mmio_write_32((0xf7800000 + 0x000), data);
- dsb();
do {
data = mmio_read_32((0xf7800000 + 0x014));
data &= 0x007;
} while (data != 0x004);
mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2101);
- data = mmio_read_32(PERI_SC_PERIPH_STAT1);
+ dsb();
+ isb();
+ udelay(10);
+ mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2001);
+ dsb();
+ isb();
+ udelay(10);
+ mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2201);
+ dsb();
+ isb();
+ udelay(10);
mmio_write_32(0xf7032000 + 0x02c, 0x5110103e);
+ dsb();
+ isb();
+ udelay(10);
data = mmio_read_32(0xf7032000 + 0x050);
data |= 1 << 28;
mmio_write_32(0xf7032000 + 0x050, data);
+ dsb();
+ isb();
+ udelay(10);
mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2101);
- mdelay(1);
- data = mmio_read_32(PERI_SC_PERIPH_STAT1);
- NOTICE("syspll frequency:%dHz\n", data);
+ dsb();
+ isb();
+ udelay(10);
+ mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2001);
+ dsb();
+ isb();
+ udelay(10);
+ mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2201);
+ dsb();
+ isb();
+ udelay(10);
}
static void init_freq(void)
@@ -215,7 +236,7 @@
data = mmio_read_32((0xf712c000 + 0x1c8));
data &= 0xfffff0f0;
- data |= 0x100f0f;
+ data |= 0x100f01;
mmio_write_32((0xf712c000 + 0x1c8), data);
for (i = 0; i < 0x20; i++) {
@@ -244,7 +265,7 @@
} while (data & 1);
data = mmio_read_32((0xf712c000 + 0x008));
- if (!(data & 0x400)) {
+ if ((data & 0x400) == 0) {
mdelay(10);
return 0;
}
@@ -489,10 +510,337 @@
INFO("wdet rbs av fail\n");
}
-static void set_ddrc_533mhz(void)
+void set_ddrc_150mhz(void)
{
unsigned int data;
+ mmio_write_32((0xf7032000 + 0x580), 0x1);
+ mmio_write_32((0xf7032000 + 0x5a8), 0x7);
+ data = mmio_read_32((0xf7032000 + 0x104));
+ data &= 0xfffffcff;
+ mmio_write_32((0xf7032000 + 0x104), data);
+
+ mmio_write_32((0xf7030000 + 0x050), 0x31);
+ mmio_write_32((0xf7030000 + 0x240), 0x5ffff);
+ mmio_write_32((0xf7030000 + 0x344), 0xf5ff);
+ mmio_write_32((0xf712c000 + 0x00c), 0x80000f0f);
+ mmio_write_32((0xf712c000 + 0x00c), 0xf0f);
+ mmio_write_32((0xf712c000 + 0x018), 0x7);
+ mmio_write_32((0xf712c000 + 0x090), 0x7200000);
+ mmio_write_32((0xf712c000 + 0x258), 0x720);
+ mmio_write_32((0xf712c000 + 0x2d8), 0x720);
+ mmio_write_32((0xf712c000 + 0x358), 0x720);
+ mmio_write_32((0xf712c000 + 0x3d8), 0x720);
+ mmio_write_32((0xf712c000 + 0x018), 0x7);
+ mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f);
+ mmio_write_32((0xf712c000 + 0x0b4), 0xf);
+ mmio_write_32((0xf712c000 + 0x088), 0x3fff801);
+ mmio_write_32((0xf712c000 + 0x070), 0x8940000);
+
+ data = mmio_read_32((0xf712c000 + 0x078));
+ data |= 4;
+ mmio_write_32((0xf712c000 + 0x078), data);
+ mmio_write_32((0xf712c000 + 0x01c), 0x8000080);
+ data = mmio_read_32((0xf712c000 + 0x020));
+ data &= 0xfffffffe;
+ mmio_write_32((0xf712c000 + 0x020), data);
+ mmio_write_32((0xf712c000 + 0x1d4), 0xc0000);
+ mmio_write_32((0xf712c000 + 0x010), 0x500000f);
+ mmio_write_32((0xf712c000 + 0x014), 0x10);
+ data = mmio_read_32((0xf712c000 + 0x1e4));
+ data &= 0xffffff00;
+ mmio_write_32((0xf712c000 + 0x1e4), data);
+ mmio_write_32((0xf712c000 + 0x030), 0x30c82355);
+ mmio_write_32((0xf712c000 + 0x034), 0x62112bb);
+ mmio_write_32((0xf712c000 + 0x038), 0x20041022);
+ mmio_write_32((0xf712c000 + 0x03c), 0x63177497);
+ mmio_write_32((0xf712c000 + 0x040), 0x3008407);
+ mmio_write_32((0xf712c000 + 0x064), 0x10483);
+ mmio_write_32((0xf712c000 + 0x068), 0xff0a0000);
+ data = mmio_read_32((0xf712c000 + 0x070));
+ data &= 0xffff0000;
+ data |= 0x184;
+ mmio_write_32((0xf712c000 + 0x070), data);
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data &= 0xbfffffff;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ data = mmio_read_32((0xf712c000 + 0x020));
+ data &= ~0x10;
+ mmio_write_32((0xf712c000 + 0x020), data);
+ data = mmio_read_32((0xf712c000 + 0x080));
+ data &= ~0x2000;
+ mmio_write_32((0xf712c000 + 0x080), data);
+ mmio_write_32((0xf712c000 + 0x270), 0x3);
+ mmio_write_32((0xf712c000 + 0x2f0), 0x3);
+ mmio_write_32((0xf712c000 + 0x370), 0x3);
+ mmio_write_32((0xf712c000 + 0x3f0), 0x3);
+ mmio_write_32((0xf712c000 + 0x048), 0x90420880);
+
+ mmio_write_32((0xf7128000 + 0x040), 0x0);
+ mmio_write_32((0xf712c000 + 0x004), 0x146d);
+ mmio_write_32((0xf7128000 + 0x050), 0x100123);
+ mmio_write_32((0xf7128000 + 0x060), 0x133);
+ mmio_write_32((0xf7128000 + 0x064), 0x133);
+ mmio_write_32((0xf7128000 + 0x200), 0xa1000);
+
+ mmio_write_32((0xf7128000 + 0x100), 0xb3290d08);
+ mmio_write_32((0xf7128000 + 0x104), 0x9621821);
+ mmio_write_32((0xf7128000 + 0x108), 0x45009023);
+ mmio_write_32((0xf7128000 + 0x10c), 0xaf44c145);
+ mmio_write_32((0xf7128000 + 0x110), 0x10b00000);
+ mmio_write_32((0xf7128000 + 0x114), 0x11080806);
+ mmio_write_32((0xf7128000 + 0x118), 0x44);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 8) {
+ NOTICE("fail to init ddr3 rank0\n");
+ return;
+ }
+
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data |= 1;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ mmio_write_32((0xf712c000 + 0x004), 0x21);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 0x8)
+ NOTICE("ddr3 rank1 init failure\n");
+ else
+ INFO("ddr3 rank1 init pass\n");
+
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data &= ~0xf;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ INFO("succeed to set ddrc 150mhz\n");
+}
+
+void set_ddrc_266mhz(void)
+{
+ unsigned int data;
+
+ mmio_write_32((0xf7032000 + 0x580), 0x3);
+ mmio_write_32((0xf7032000 + 0x5a8), 0x1003);
+ data = mmio_read_32((0xf7032000 + 0x104));
+ data &= 0xfffffcff;
+ mmio_write_32((0xf7032000 + 0x104), data);
+
+ mmio_write_32((0xf7030000 + 0x050), 0x31);
+ mmio_write_32((0xf7030000 + 0x240), 0x5ffff);
+ mmio_write_32((0xf7030000 + 0x344), 0xf5ff);
+ mmio_write_32((0xf712c000 + 0x00c), 0x80000f0f);
+ mmio_write_32((0xf712c000 + 0x00c), 0xf0f);
+ mmio_write_32((0xf712c000 + 0x018), 0x7);
+ mmio_write_32((0xf712c000 + 0x090), 0x7200000);
+ mmio_write_32((0xf712c000 + 0x258), 0x720);
+ mmio_write_32((0xf712c000 + 0x2d8), 0x720);
+ mmio_write_32((0xf712c000 + 0x358), 0x720);
+ mmio_write_32((0xf712c000 + 0x3d8), 0x720);
+ mmio_write_32((0xf712c000 + 0x018), 0x7);
+ mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f);
+ mmio_write_32((0xf712c000 + 0x0b4), 0xf);
+ mmio_write_32((0xf712c000 + 0x088), 0x3fff801);
+ mmio_write_32((0xf712c000 + 0x070), 0x8940000);
+
+ data = mmio_read_32((0xf712c000 + 0x078));
+ data |= 4;
+ mmio_write_32((0xf712c000 + 0x078), data);
+ mmio_write_32((0xf712c000 + 0x01c), 0x8000080);
+ data = mmio_read_32((0xf712c000 + 0x020));
+ data &= 0xfffffffe;
+ mmio_write_32((0xf712c000 + 0x020), data);
+ mmio_write_32((0xf712c000 + 0x1d4), 0xc0000);
+ mmio_write_32((0xf712c000 + 0x010), 0x500000f);
+ mmio_write_32((0xf712c000 + 0x014), 0x10);
+ data = mmio_read_32((0xf712c000 + 0x1e4));
+ data &= 0xffffff00;
+ mmio_write_32((0xf712c000 + 0x1e4), data);
+ mmio_write_32((0xf712c000 + 0x030), 0x510d4455);
+ mmio_write_32((0xf712c000 + 0x034), 0x8391ebb);
+ mmio_write_32((0xf712c000 + 0x038), 0x2005103c);
+ mmio_write_32((0xf712c000 + 0x03c), 0x6329950b);
+ mmio_write_32((0xf712c000 + 0x040), 0x300858c);
+ mmio_write_32((0xf712c000 + 0x064), 0x10483);
+ mmio_write_32((0xf712c000 + 0x068), 0xff0a0000);
+ data = mmio_read_32((0xf712c000 + 0x070));
+ data &= 0xffff0000;
+ data |= 0x184;
+ mmio_write_32((0xf712c000 + 0x070), data);
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data &= 0xbfffffff;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ data = mmio_read_32((0xf712c000 + 0x020));
+ data &= ~0x10;
+ mmio_write_32((0xf712c000 + 0x020), data);
+ data = mmio_read_32((0xf712c000 + 0x080));
+ data &= ~0x2000;
+ mmio_write_32((0xf712c000 + 0x080), data);
+ mmio_write_32((0xf712c000 + 0x270), 0x3);
+ mmio_write_32((0xf712c000 + 0x2f0), 0x3);
+ mmio_write_32((0xf712c000 + 0x370), 0x3);
+ mmio_write_32((0xf712c000 + 0x3f0), 0x3);
+ mmio_write_32((0xf712c000 + 0x048), 0x90420880);
+
+ mmio_write_32((0xf7128000 + 0x040), 0x0);
+ mmio_write_32((0xf712c000 + 0x004), 0x146d);
+ mmio_write_32((0xf7128000 + 0x050), 0x100123);
+ mmio_write_32((0xf7128000 + 0x060), 0x133);
+ mmio_write_32((0xf7128000 + 0x064), 0x133);
+ mmio_write_32((0xf7128000 + 0x200), 0xa1000);
+
+ mmio_write_32((0xf7128000 + 0x100), 0xb441d50d);
+ mmio_write_32((0xf7128000 + 0x104), 0xf721839);
+ mmio_write_32((0xf7128000 + 0x108), 0x5500f03f);
+ mmio_write_32((0xf7128000 + 0x10c), 0xaf486145);
+ mmio_write_32((0xf7128000 + 0x110), 0x10b00000);
+ mmio_write_32((0xf7128000 + 0x114), 0x12080d06);
+ mmio_write_32((0xf7128000 + 0x118), 0x44);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 8) {
+ NOTICE("fail to init ddr3 rank0\n");
+ return;
+ }
+
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data |= 1;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ mmio_write_32((0xf712c000 + 0x004), 0x21);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 0x8)
+ NOTICE("ddr3 rank1 init failure\n");
+ else
+ INFO("ddr3 rank1 init pass\n");
+
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data &= ~0xf;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ INFO("succeed to set ddrc 266mhz\n");
+}
+
+void set_ddrc_400mhz(void)
+{
+ unsigned int data;
+
+ mmio_write_32((0xf7032000 + 0x580), 0x2);
+ mmio_write_32((0xf7032000 + 0x5a8), 0x1003);
+ data = mmio_read_32((0xf7032000 + 0x104));
+ data &= 0xfffffcff;
+ mmio_write_32((0xf7032000 + 0x104), data);
+
+ mmio_write_32((0xf7030000 + 0x050), 0x31);
+ mmio_write_32((0xf7030000 + 0x240), 0x5ffff);
+ mmio_write_32((0xf7030000 + 0x344), 0xf5ff);
+ mmio_write_32((0xf712c000 + 0x00c), 0x80000f0f);
+ mmio_write_32((0xf712c000 + 0x00c), 0xf0f);
+ mmio_write_32((0xf712c000 + 0x018), 0x7);
+ mmio_write_32((0xf712c000 + 0x090), 0x7200000);
+ mmio_write_32((0xf712c000 + 0x258), 0x720);
+ mmio_write_32((0xf712c000 + 0x2d8), 0x720);
+ mmio_write_32((0xf712c000 + 0x358), 0x720);
+ mmio_write_32((0xf712c000 + 0x3d8), 0x720);
+ mmio_write_32((0xf712c000 + 0x018), 0x7);
+ mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f);
+ mmio_write_32((0xf712c000 + 0x0b4), 0xf);
+ mmio_write_32((0xf712c000 + 0x088), 0x3fff801);
+ mmio_write_32((0xf712c000 + 0x070), 0x8940000);
+
+ data = mmio_read_32((0xf712c000 + 0x078));
+ data |= 4;
+ mmio_write_32((0xf712c000 + 0x078), data);
+ mmio_write_32((0xf712c000 + 0x01c), 0x8000080);
+ data = mmio_read_32((0xf712c000 + 0x020));
+ data &= 0xfffffffe;
+ mmio_write_32((0xf712c000 + 0x020), data);
+ mmio_write_32((0xf712c000 + 0x1d4), 0xc0000);
+ mmio_write_32((0xf712c000 + 0x010), 0x500000f);
+ mmio_write_32((0xf712c000 + 0x014), 0x10);
+ data = mmio_read_32((0xf712c000 + 0x1e4));
+ data &= 0xffffff00;
+ mmio_write_32((0xf712c000 + 0x1e4), data);
+ mmio_write_32((0xf712c000 + 0x030), 0x75525655);
+ mmio_write_32((0xf712c000 + 0x034), 0xa552abb);
+ mmio_write_32((0xf712c000 + 0x038), 0x20071059);
+ mmio_write_32((0xf712c000 + 0x03c), 0x633e8591);
+ mmio_write_32((0xf712c000 + 0x040), 0x3008691);
+ mmio_write_32((0xf712c000 + 0x064), 0x10483);
+ mmio_write_32((0xf712c000 + 0x068), 0xff0a0000);
+ data = mmio_read_32((0xf712c000 + 0x070));
+ data &= 0xffff0000;
+ data |= 0x184;
+ mmio_write_32((0xf712c000 + 0x070), data);
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data &= 0xbfffffff;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ data = mmio_read_32((0xf712c000 + 0x020));
+ data &= ~0x10;
+ mmio_write_32((0xf712c000 + 0x020), data);
+ data = mmio_read_32((0xf712c000 + 0x080));
+ data &= ~0x2000;
+ mmio_write_32((0xf712c000 + 0x080), data);
+ mmio_write_32((0xf712c000 + 0x270), 0x3);
+ mmio_write_32((0xf712c000 + 0x2f0), 0x3);
+ mmio_write_32((0xf712c000 + 0x370), 0x3);
+ mmio_write_32((0xf712c000 + 0x3f0), 0x3);
+ mmio_write_32((0xf712c000 + 0x048), 0x90420880);
+
+ mmio_write_32((0xf7128000 + 0x040), 0x0);
+ mmio_write_32((0xf712c000 + 0x004), 0x146d);
+ mmio_write_32((0xf7128000 + 0x050), 0x100123);
+ mmio_write_32((0xf7128000 + 0x060), 0x133);
+ mmio_write_32((0xf7128000 + 0x064), 0x133);
+ mmio_write_32((0xf7128000 + 0x200), 0xa1000);
+
+ mmio_write_32((0xf7128000 + 0x100), 0xb55a9d12);
+ mmio_write_32((0xf7128000 + 0x104), 0x17721855);
+ mmio_write_32((0xf7128000 + 0x108), 0x7501505f);
+ mmio_write_32((0xf7128000 + 0x10c), 0xaf4ca245);
+ mmio_write_32((0xf7128000 + 0x110), 0x10b00000);
+ mmio_write_32((0xf7128000 + 0x114), 0x13081306);
+ mmio_write_32((0xf7128000 + 0x118), 0x44);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 8) {
+ NOTICE("fail to init ddr3 rank0\n");
+ return;
+ }
+
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data |= 1;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ mmio_write_32((0xf712c000 + 0x004), 0x21);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 0x8)
+ NOTICE("ddr3 rank1 init failure\n");
+ else
+ INFO("ddr3 rank1 init pass\n");
+
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data &= ~0xf;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ INFO("succeed to set ddrc 400mhz\n");
+}
+
+void set_ddrc_533mhz(void)
+{
+ unsigned int data;
+
mmio_write_32((0xf7032000 + 0x580), 0x3);
mmio_write_32((0xf7032000 + 0x5a8), 0x11111);
data = mmio_read_32((0xf7032000 + 0x104));
@@ -503,6 +851,7 @@
mmio_write_32((0xf7030000 + 0x240), 0x5ffff);
mmio_write_32((0xf7030000 + 0x344), 0xf5ff);
mmio_write_32((0xf712c000 + 0x00c), 0x400);
+ mmio_write_32((0xf712c000 + 0x00c), 0x400);
mmio_write_32((0xf712c000 + 0x018), 0x7);
mmio_write_32((0xf712c000 + 0x090), 0x6400000);
mmio_write_32((0xf712c000 + 0x258), 0x640);
@@ -564,10 +913,53 @@
NOTICE("failed to init lpddr3 rank0 dram phy\n");
return;
}
+ cat_533mhz_800mhz();
+
+ mmio_write_32((0xf712c000 + 0x004), 0xf1);
+ mmio_write_32((0xf7128000 + 0x050), 0x100123);
+ mmio_write_32((0xf7128000 + 0x060), 0x133);
+ mmio_write_32((0xf7128000 + 0x064), 0x133);
+ mmio_write_32((0xf7128000 + 0x200), 0xa1000);
+
+ mmio_write_32((0xf7128000 + 0x100), 0xb77b6718);
+ mmio_write_32((0xf7128000 + 0x104), 0x1e82a071);
+ mmio_write_32((0xf7128000 + 0x108), 0x9501c07e);
+ mmio_write_32((0xf7128000 + 0x10c), 0xaf50c255);
+ mmio_write_32((0xf7128000 + 0x110), 0x10b00000);
+ mmio_write_32((0xf7128000 + 0x114), 0x13181908);
+ mmio_write_32((0xf7128000 + 0x118), 0x44);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 0x7fe) {
+ NOTICE("fail to init ddr3 rank0\n");
+ return;
+ }
- NOTICE("succeed to init lpddr3 rank0 dram phy\n");
+ ddrx_rdet();
+ ddrx_wdet();
+
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data |= 1;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ mmio_write_32((0xf712c000 + 0x004), 0x21);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 0x7fe)
+ NOTICE("ddr3 rank1 init failure\n");
+ else
+ INFO("ddr3 rank1 init pass\n");
+
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data &= ~0xf;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ INFO("succeed to set ddrc 533mhz\n");
}
-static void set_ddrc_800mhz(void)
+void set_ddrc_800mhz(void)
{
unsigned int data;
@@ -581,6 +973,7 @@
mmio_write_32((0xf7030000 + 0x240), 0x5ffff);
mmio_write_32((0xf7030000 + 0x344), 0xf5ff);
mmio_write_32((0xf712c000 + 0x00c), 0x400);
+ mmio_write_32((0xf712c000 + 0x00c), 0x400);
mmio_write_32((0xf712c000 + 0x018), 0x7);
mmio_write_32((0xf712c000 + 0x090), 0x5400000);
mmio_write_32((0xf712c000 + 0x258), 0x540);
@@ -642,9 +1035,53 @@
WARN("failed to init lpddr3 rank0 dram phy\n");
return;
}
+ cat_533mhz_800mhz();
+
+ mmio_write_32((0xf712c000 + 0x004), 0xf1);
+ mmio_write_32((0xf7128000 + 0x050), 0x100023);
+ mmio_write_32((0xf7128000 + 0x060), 0x133);
+ mmio_write_32((0xf7128000 + 0x064), 0x133);
+ mmio_write_32((0xf7128000 + 0x200), 0xa1000);
+
+ mmio_write_32((0xf7128000 + 0x100), 0x755a9d12);
+ mmio_write_32((0xf7128000 + 0x104), 0x1753b055);
+ mmio_write_32((0xf7128000 + 0x108), 0x7401505f);
+ mmio_write_32((0xf7128000 + 0x10c), 0x578ca244);
+ mmio_write_32((0xf7128000 + 0x110), 0x10700000);
+ mmio_write_32((0xf7128000 + 0x114), 0x13141306);
+ mmio_write_32((0xf7128000 + 0x118), 0x44);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 0x7fe) {
+ NOTICE("fail to init ddr3 rank0\n");
+ return;
+ }
+ ddrx_rdet();
+ ddrx_wdet();
+
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data |= 1;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ mmio_write_32((0xf712c000 + 0x004), 0x21);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 0x7fe)
+ NOTICE("ddr3 rank1 init failure\n");
+ else
+ INFO("ddr3 rank1 init pass\n");
+
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data &= ~0xf;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ INFO("succeed to set ddrc 800mhz\n");
}
-static void ddrc_common_init(int ddr800)
+static void ddrc_common_init(int freq)
{
unsigned int data;
@@ -653,11 +1090,10 @@
mmio_write_32((0xf7120000 + 0x104), 0x71040004);
mmio_write_32((0xf7121400 + 0x104), 0xf);
mmio_write_32((0xf7121800 + 0x104), 0xf);
- mmio_write_32((0xf7121800 + 0x104), 0xf);
mmio_write_32((0xf7121c00 + 0x104), 0xf);
mmio_write_32((0xf7122000 + 0x104), 0xf);
mmio_write_32((0xf7128000 + 0x02c), 0x6);
- mmio_write_32((0xf7128000 + 0x020), 0x1);
+ mmio_write_32((0xf7128000 + 0x020), 0x30003);
mmio_write_32((0xf7128000 + 0x028), 0x310201);
mmio_write_32((0xf712c000 + 0x1e4), 0xfe007600);
mmio_write_32((0xf7128000 + 0x01c), 0xaf001);
@@ -668,10 +1104,10 @@
mmio_write_32((0xf7128000 + 0x280), data);
mmio_write_32((0xf7128000 + 0x244), 0x3);
- if (ddr800)
- mmio_write_32((0xf7128000 + 0x240), 167 * 400000 / 1024);
+ if (freq == DDR_FREQ_800M)
+ mmio_write_32((0xf7128000 + 0x240), 167 * (freq / 2) / 1024);
else
- mmio_write_32((0xf7128000 + 0x240), 167 * 533000 / 1024);
+ mmio_write_32((0xf7128000 + 0x240), 167 * freq / 1024);
data = mmio_read_32((0xf712c000 + 0x080));
data &= 0xffff;
@@ -702,20 +1138,24 @@
mmio_write_32((0xf7128000 + 0x064), 0x132);
mmio_write_32((0xf7120000 + 0x100), 0x1600);
mmio_write_32((0xf7120000 + 0x104), 0x71040004);
+ mmio_write_32(MEMORY_AXI_DDR_CAPACITY_ADDR, 0x40000000);
break;
case 0x1c:
mmio_write_32((0xf7128000 + 0x060), 0x142);
mmio_write_32((0xf7128000 + 0x064), 0x142);
mmio_write_32((0xf7120000 + 0x100), 0x1700);
mmio_write_32((0xf7120000 + 0x104), 0x71040004);
+ mmio_write_32(MEMORY_AXI_DDR_CAPACITY_ADDR, 0x80000000);
break;
case 0x58:
mmio_write_32((0xf7128000 + 0x060), 0x133);
mmio_write_32((0xf7128000 + 0x064), 0x133);
mmio_write_32((0xf7120000 + 0x100), 0x1700);
mmio_write_32((0xf7120000 + 0x104), 0x71040004);
+ mmio_write_32(MEMORY_AXI_DDR_CAPACITY_ADDR, 0x80000000);
break;
default:
+ mmio_write_32(MEMORY_AXI_DDR_CAPACITY_ADDR, 0x80000000);
break;
}
if (!data)
@@ -772,73 +1212,114 @@
return data;
}
-int lpddr3_freq_init(int freq)
+void ddr_phy_reset(void)
{
- unsigned int data;
+ mmio_write_32(0xf7030340, 0xa000);
+ mmio_write_32(0xf7030344, 0xa000);
+}
- if (freq == DDR_FREQ_800M) {
- set_ddrc_800mhz();
- INFO("%s, set ddrc 800mhz\n", __func__);
- } else {
- set_ddrc_533mhz();
- INFO("%s, set ddrc 533mhz\n", __func__);
+void lpddrx_save_ddl_para_bypass(uint32_t *ddr_ddl_para, unsigned int index)
+{
+ uint32_t value;
+ uint32_t cnt = index;
+ uint32_t i;
+
+ for (i = 0; i < 4; i++) {
+ value = mmio_read_32(0xf712c000 + 0x22c + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x23c + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x240 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x640 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
}
+}
- mmio_write_32((0xf712c000 + 0x004), 0xf1);
- if (freq == DDR_FREQ_800M)
- mmio_write_32((0xf7128000 + 0x050), 0x100023);
- else
- mmio_write_32((0xf7128000 + 0x050), 0x100123);
- mmio_write_32((0xf7128000 + 0x060), 0x133);
- mmio_write_32((0xf7128000 + 0x064), 0x133);
- mmio_write_32((0xf7128000 + 0x200), 0xa1000);
+void lpddrx_save_ddl_para_mission(uint32_t *ddr_ddl_para, unsigned int index)
+{
+ uint32_t value;
+ uint32_t cnt = index;
+ uint32_t i;
- if (freq == DDR_FREQ_800M) {
- mmio_write_32((0xf7128000 + 0x100), 0x755a9d12);
- mmio_write_32((0xf7128000 + 0x104), 0x1753b055);
- mmio_write_32((0xf7128000 + 0x108), 0x7401505f);
- mmio_write_32((0xf7128000 + 0x10c), 0x578ca244);
- mmio_write_32((0xf7128000 + 0x110), 0x10700000);
- mmio_write_32((0xf7128000 + 0x114), 0x13141306);
- } else {
- mmio_write_32((0xf7128000 + 0x100), 0xb77b6718);
- mmio_write_32((0xf7128000 + 0x104), 0x1e82a071);
- mmio_write_32((0xf7128000 + 0x108), 0x9501c07e);
- mmio_write_32((0xf7128000 + 0x10c), 0xaf50c255);
- mmio_write_32((0xf7128000 + 0x110), 0x10b00000);
- mmio_write_32((0xf7128000 + 0x114), 0x13181908);
+ value = mmio_read_32(0xf712c000 + 0x140);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x144);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x148);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x14c);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x150);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x1d4);
+ ddr_ddl_para[cnt++] = value;
+ for (i = 0; i < 4; i++) {
+ value = mmio_read_32(0xf712c000 + 0x210 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x214 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x218 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x21c + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x220 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x224 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x228 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x22c + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x230 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x234 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x238 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x23c + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x240 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x640 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
}
- mmio_write_32((0xf7128000 + 0x118), 0x44);
- do {
- data = mmio_read_32((0xf712c000 + 0x004));
- } while (data & 1);
+ value = mmio_read_32(0xf712c000 + 0x168);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x24c + 0 * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x24c + 2 * 0x80);
+ ddr_ddl_para[cnt++] = value;
+}
- data = mmio_read_32((0xf712c000 + 0x008));
- if (data & 0x7fe) {
- NOTICE("fail to init ddr3 rank0\n");
- return -EFAULT;
+int lpddr3_freq_init(int freq)
+{
+ set_ddrc_150mhz();
+ lpddrx_save_ddl_para_bypass((uint32_t *)MEMORY_AXI_DDR_DDL_ADDR, 0);
+ if (freq > DDR_FREQ_150M) {
+ ddr_phy_reset();
+ set_ddrc_266mhz();
+ lpddrx_save_ddl_para_bypass((uint32_t *)MEMORY_AXI_DDR_DDL_ADDR,
+ 16);
}
- INFO("init ddr3 rank0\n");
- ddrx_rdet();
- ddrx_wdet();
-
- data = mmio_read_32((0xf712c000 + 0x048));
- data |= 1;
- mmio_write_32((0xf712c000 + 0x048), data);
- mmio_write_32((0xf712c000 + 0x004), 0x21);
- do {
- data = mmio_read_32((0xf712c000 + 0x004));
- } while (data & 1);
-
- data = mmio_read_32((0xf712c000 + 0x008));
- if (data & 0x7fe)
- NOTICE("ddr3 rank1 init failure\n");
- else
- INFO("ddr3 rank1 init pass\n");
-
- data = mmio_read_32((0xf712c000 + 0x048));
- data &= ~0xf;
- mmio_write_32((0xf712c000 + 0x048), data);
+ if (freq > DDR_FREQ_266M) {
+ ddr_phy_reset();
+ set_ddrc_400mhz();
+ lpddrx_save_ddl_para_bypass((uint32_t *)MEMORY_AXI_DDR_DDL_ADDR,
+ 16 * 2);
+ }
+ if (freq > DDR_FREQ_400M) {
+ ddr_phy_reset();
+ set_ddrc_533mhz();
+ lpddrx_save_ddl_para_mission((uint32_t *)MEMORY_AXI_DDR_DDL_ADDR,
+ 16 * 3);
+ }
+ if (freq > DDR_FREQ_533M) {
+ ddr_phy_reset();
+ set_ddrc_800mhz();
+ lpddrx_save_ddl_para_mission((uint32_t *)MEMORY_AXI_DDR_DDL_ADDR,
+ 16 * 3 + 61);
+ }
return 0;
}
@@ -855,7 +1336,7 @@
data |= 1;
mmio_write_32((0xf7032000 + 0x010), data);
- udelay(100);
+ udelay(300);
do {
data = mmio_read_32((0xf7032000 + 0x030));
data &= 3 << 28;
@@ -923,38 +1404,40 @@
mmio_write_32((0xf7124000 + 0x0d0), 0x3020100);
}
-static void ddr_phy_reset(void)
-{
- mmio_write_32(0xf7030340, 0xa000);
- mmio_write_32(0xf7030344, 0xa000);
-}
-
-void hikey_ddr_init(void)
+void hikey_ddr_init(unsigned int ddr_freq)
{
uint32_t data;
+ assert((ddr_freq == DDR_FREQ_150M) || (ddr_freq == DDR_FREQ_266M) ||
+ (ddr_freq == DDR_FREQ_400M) || (ddr_freq == DDR_FREQ_533M) ||
+ (ddr_freq == DDR_FREQ_800M));
init_pll();
init_freq();
- /*
- * Init DDR with 533MHz. Otherwise, DDR initialization
- * may fail on 800MHz on some boards.
- */
- ddr_phy_reset();
- init_ddr(DDR_FREQ_533M);
- /* Init DDR with 800MHz. */
- ddr_phy_reset();
- init_ddr(DDR_FREQ_800M);
-
+ init_ddr(ddr_freq);
- ddrc_common_init(1);
+ ddrc_common_init(ddr_freq);
dienum_det_and_rowcol_cfg();
detect_ddr_chip_info();
- data = mmio_read_32(0xf7032000 + 0x010);
- data &= ~0x1;
- mmio_write_32(0xf7032000 + 0x010, data);
- data = mmio_read_32(0xf7032000 + 0x010);
+ if ((ddr_freq == DDR_FREQ_400M) || (ddr_freq == DDR_FREQ_800M)) {
+ data = mmio_read_32(0xf7032000 + 0x010);
+ data &= ~0x1;
+ mmio_write_32(0xf7032000 + 0x010, data);
+ } else if ((ddr_freq == DDR_FREQ_266M) || (ddr_freq == DDR_FREQ_533M)) {
+ data = mmio_read_32(0xf7032000 + 0x030);
+ data &= ~0x1;
+ mmio_write_32(0xf7032000 + 0x030, data);
+ } else {
+ data = mmio_read_32(0xf7032000 + 0x010);
+ data &= ~0x1;
+ mmio_write_32(0xf7032000 + 0x010, data);
+ data = mmio_read_32(0xf7032000 + 0x030);
+ data &= ~0x1;
+ mmio_write_32(0xf7032000 + 0x030, data);
+ }
+ dsb();
+ isb();
/*
* Test memory access. Do not use address 0x0 because the compiler
diff --git a/plat/hisilicon/hikey/hikey_private.h b/plat/hisilicon/hikey/hikey_private.h
index 7654921..e6d109a 100644
--- a/plat/hisilicon/hikey/hikey_private.h
+++ b/plat/hisilicon/hikey/hikey_private.h
@@ -12,6 +12,14 @@
#define RANDOM_MAX 0x7fffffffffffffff
#define RANDOM_MAGIC 0x9a4dbeaf
+enum {
+ DDR_FREQ_150M = 150 * 1000,
+ DDR_FREQ_266M = 266 * 1000,
+ DDR_FREQ_400M = 400 * 1000,
+ DDR_FREQ_533M = 533 * 1000,
+ DDR_FREQ_800M = 800 * 1000
+};
+
struct random_serial_num {
uint64_t magic;
uint64_t data;
@@ -34,7 +42,7 @@
unsigned long coh_start,
unsigned long coh_limit);
-void hikey_ddr_init(void);
+void hikey_ddr_init(unsigned int ddr_freq);
void hikey_io_setup(void);
void hikey_sp804_init(void);
diff --git a/plat/hisilicon/poplar/platform.mk b/plat/hisilicon/poplar/platform.mk
index 7c8027e..14ffa99 100644
--- a/plat/hisilicon/poplar/platform.mk
+++ b/plat/hisilicon/poplar/platform.mk
@@ -34,10 +34,10 @@
# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
# in the FIP if the platform requires.
ifneq ($(BL32_EXTRA1),)
-$(eval $(call FIP_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1))
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1))
endif
ifneq ($(BL32_EXTRA2),)
-$(eval $(call FIP_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2))
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2))
endif
NEED_BL33 := yes
diff --git a/plat/layerscape/board/ls1043/aarch64/ls1043_helpers.S b/plat/layerscape/board/ls1043/aarch64/ls1043_helpers.S
new file mode 100644
index 0000000..80524fc
--- /dev/null
+++ b/plat/layerscape/board/ls1043/aarch64/ls1043_helpers.S
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .globl plat_reset_handler
+ .globl plat_my_core_pos
+ .globl platform_mem_init
+
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ and x1, x0, #MPIDR_CPU_MASK //reserve the last 8 bits
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #4 //4 cores
+ ret
+endfunc plat_my_core_pos
+
+func platform_mem_init
+ mov x29, x30
+ bl inv_dcache_range
+
+//SDRAM_CFG
+ ldr w0, =0x1080000
+ ldr w1, =0x0c000c45
+ str w1, [x0, #0x110]
+//CS0_BNDS
+ ldr w1, =0x7f000000
+ str w1, [x0, #0x000]
+//CS0_CONFIG
+ ldr w1, =0x22030480
+ str w1, [x0, #0x080]
+//TIMING_CFG_0
+ ldr w1, =0x18005591
+ str w1, [x0, #0x104]
+//TIMING_CFG_1
+ ldr w1, =0x428cb4bb
+ str w1, [x0, #0x108]
+//TIMING_CFG_2
+ ldr w1, =0x11c14800
+ str w1, [x0, #0x10C]
+//TIMING_CFG_3
+ ldr w1, =0x00100c01
+ str w1, [x0, #0x100]
+//TIMING_CFG_4
+ ldr w1, =0x02000000
+ str w1, [x0, #0x160]
+//TIMING_CFG_5
+ ldr w1, =0x00144003
+ str w1, [x0, #0x164]
+//TIMING_CFG_7
+ ldr w1, =0x00003013
+ str w1, [x0, #0x16C]
+//TIMING_CFG_8
+ ldr w1, =0x00561102
+ str w1, [x0, #0x250]
+//SDRAM_CFG_2
+ ldr w1, =0x00114000
+ str w1, [x0, #0x114]
+//SDRAM_MODE
+ ldr w1, =0x10020103
+ str w1, [x0, #0x118]
+//SDRAM_MODE_2
+ ldr w1, =0x0
+ str w1, [x0, #0x11C]
+//SDRAM_INTERVAL
+ ldr w1, =0x18066018
+ str w1, [x0, #0x124]
+//DDR_WRLVL_CNTL
+ ldr w1, =0x07f675c6
+ str w1, [x0, #0x174]
+//DDR_WRLVL_CNTL_2
+ ldr w1, =0x00080907
+ str w1, [x0, #0x190]
+//DDR_WRLVL_CNTL_3
+ ldr w1, =0x0
+ str w1, [x0, #0x194]
+//DDR_CDR1
+ ldr w1, =0x00000480
+ str w1, [x0, #0xB28]
+//DDR_CDR2
+ ldr w1, =0x81a10000
+ str w1, [x0, #0xB2C]
+//SDRAM_CLK_CNTL
+ ldr w1, =0x00000003
+ str w1, [x0, #0x130]
+//DDR_ZQ_CNTL
+ ldr w1, =0x0507098a
+ str w1, [x0, #0x170]
+//SDRAM_MODE_9
+ ldr w1, =0x00050000
+ str w1, [x0, #0x220]
+//SDRAM_MODE_10
+ ldr w1, =0x00000004
+ str w1, [x0, #0x224]
+//CS0_CONFIG_2
+ ldr w1, =0x0
+ str w1, [x0, #0x0C0]
+//SDRAM_CFG
+ ldr w1, =0x08000cc5
+ str w1, [x0, #0x110]
+
+ mov w3,#0
+ ldr w4,=0xffffff01
+z_loop:
+delay_loop1:
+ sub w4, w4, #1
+ cmp w4, #0
+ b.gt delay_loop1
+
+ ldr w1, [x0, #0x114]
+ add w3, w3, #1
+ cmp w1, #0 //'\n'
+ b.eq 1f
+ cmp w3, #20
+ b.gt 1f
+ b z_loop
+
+1:
+ ldr w4,=0xffffff02
+delay_loop2:
+ sub w4, w4, #1
+ cmp w4, #0
+ b.gt delay_loop2
+
+ ldr w1, =0x00000000
+ str w1, [x0]
+
+ ret x29
+endfunc platform_mem_init
+
+func apply_platform_errata
+ /*TODO if needed*/
+ ret
+endfunc apply_platform_errata
+
+func plat_reset_handler
+ mov x29, x30
+ bl apply_platform_errata
+
+ mov x30, x29
+ ret
+endfunc plat_reset_handler
diff --git a/plat/layerscape/board/ls1043/include/ls_def.h b/plat/layerscape/board/ls1043/include/ls_def.h
new file mode 100644
index 0000000..1015129
--- /dev/null
+++ b/plat/layerscape/board/ls1043/include/ls_def.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __LS_DEF_H__
+#define __LS_DEF_H__
+
+#include <arch.h>
+#include <common_def.h>
+#include <platform_def.h>
+#include <tbbr_img_def.h>
+#include <utils_def.h>
+#include <xlat_tables_defs.h>
+
+
+/******************************************************************************
+ * Definitions common to all ARM standard platforms
+ *****************************************************************************/
+/* Special value used to verify platform parameters from BL2 to BL31 */
+#define LS_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
+
+#define LS_CACHE_WRITEBACK_SHIFT 6
+
+/*
+ * Macros mapping the MPIDR Affinity levels to Layerscape Platform Power levels. The
+ * power levels have a 1:1 mapping with the MPIDR affinity levels.
+ */
+#define LS_PWR_LVL0 MPIDR_AFFLVL0
+#define LS_PWR_LVL1 MPIDR_AFFLVL1
+#define LS_PWR_LVL2 MPIDR_AFFLVL2
+
+/*
+ * Macros for local power states in Layerscape platforms encoded by State-ID field
+ * within the power-state parameter.
+ */
+/* Local power state for power domains in Run state. */
+#define LS_LOCAL_STATE_RUN 0
+/* Local power state for retention. Valid only for CPU power domains */
+#define LS_LOCAL_STATE_RET 1
+/*
+ * Local power state for OFF/power-down. Valid for CPU and cluster power
+ * domains
+ */
+#define LS_LOCAL_STATE_OFF 2
+
+#define LS_MAP_NS_DRAM MAP_REGION_FLAT( \
+ (LS_NS_DRAM_BASE), \
+ LS_DRAM1_SIZE, \
+ MT_DEVICE | MT_RW | MT_NS)
+
+#define LS_MAP_TSP_SEC_MEM MAP_REGION_FLAT( \
+ TSP_SEC_MEM_BASE, \
+ TSP_SEC_MEM_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+
+#define LS_MAP_FLASH0_RW MAP_REGION_FLAT(PLAT_LS_FLASH_BASE,\
+ PLAT_LS_FLASH_SIZE, \
+ MT_DEVICE | MT_RW)
+
+#define LS_MAP_CCSR MAP_REGION_FLAT(PLAT_LS_CCSR_BASE, \
+ PLAT_LS_CCSR_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+
+#define LS_MAP_CONSOLE MAP_REGION_FLAT(PLAT_LS1043_DUART1_BASE, \
+ PLAT_LS1043_DUART_SIZE, \
+ MT_DEVICE | MT_RW | MT_NS)
+
+/*
+ * The number of regions like RO(code), coherent and data required by
+ * different BL stages which need to be mapped in the MMU.
+ */
+/******************************************************************************
+ * Required platform porting definitions common to all ARM standard platforms
+ *****************************************************************************/
+
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32)
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE LS_LOCAL_STATE_RET
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE LS_LOCAL_STATE_OFF
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_GRANULE (1 << LS_CACHE_WRITEBACK_SHIFT)
+
+/*
+ * One cache line needed for bakery locks on Layerscape platforms
+ */
+#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE)
+
+#endif /* __LS_DEF_H__ */
diff --git a/plat/layerscape/board/ls1043/include/ns_access.h b/plat/layerscape/board/ls1043/include/ns_access.h
new file mode 100644
index 0000000..6ed7bc0
--- /dev/null
+++ b/plat/layerscape/board/ls1043/include/ns_access.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __FSL_NS_ACCESS_H_
+#define __FSL_NS_ACCESS_H_
+
+#include "fsl_csu.h"
+
+enum csu_cslx_ind {
+ CSU_CSLX_PCIE2_IO = 0,
+ CSU_CSLX_PCIE1_IO,
+ CSU_CSLX_MG2TPR_IP,
+ CSU_CSLX_IFC_MEM,
+ CSU_CSLX_OCRAM,
+ CSU_CSLX_GIC,
+ CSU_CSLX_PCIE1,
+ CSU_CSLX_OCRAM2,
+ CSU_CSLX_QSPI_MEM,
+ CSU_CSLX_PCIE2,
+ CSU_CSLX_SATA,
+ CSU_CSLX_USB1,
+ CSU_CSLX_QM_BM_SWPORTAL,
+ CSU_CSLX_PCIE3 = 16,
+ CSU_CSLX_PCIE3_IO,
+ CSU_CSLX_USB3 = 20,
+ CSU_CSLX_USB2,
+ CSU_CSLX_PFE = 23,
+ CSU_CSLX_SERDES = 32,
+ CSU_CSLX_QDMA,
+ CSU_CSLX_LPUART2,
+ CSU_CSLX_LPUART1,
+ CSU_CSLX_LPUART4,
+ CSU_CSLX_LPUART3,
+ CSU_CSLX_LPUART6,
+ CSU_CSLX_LPUART5,
+ CSU_CSLX_DSPI1 = 41,
+ CSU_CSLX_QSPI,
+ CSU_CSLX_ESDHC,
+ CSU_CSLX_IFC = 45,
+ CSU_CSLX_I2C1,
+ CSU_CSLX_USB_2,
+ CSU_CSLX_I2C3 = 48,
+ CSU_CSLX_I2C2,
+ CSU_CSLX_DUART2 = 50,
+ CSU_CSLX_DUART1,
+ CSU_CSLX_WDT2,
+ CSU_CSLX_WDT1,
+ CSU_CSLX_EDMA,
+ CSU_CSLX_SYS_CNT,
+ CSU_CSLX_DMA_MUX2,
+ CSU_CSLX_DMA_MUX1,
+ CSU_CSLX_DDR,
+ CSU_CSLX_QUICC,
+ CSU_CSLX_DCFG_CCU_RCPM = 60,
+ CSU_CSLX_SECURE_BOOTROM,
+ CSU_CSLX_SFP,
+ CSU_CSLX_TMU,
+ CSU_CSLX_SECURE_MONITOR,
+ CSU_CSLX_SCFG,
+ CSU_CSLX_FM = 66,
+ CSU_CSLX_SEC5_5,
+ CSU_CSLX_BM,
+ CSU_CSLX_QM,
+ CSU_CSLX_GPIO2 = 70,
+ CSU_CSLX_GPIO1,
+ CSU_CSLX_GPIO4,
+ CSU_CSLX_GPIO3,
+ CSU_CSLX_PLATFORM_CONT,
+ CSU_CSLX_CSU,
+ CSU_CSLX_IIC4 = 77,
+ CSU_CSLX_WDT4,
+ CSU_CSLX_WDT3,
+ CSU_CSLX_ESDHC2 = 80,
+ CSU_CSLX_WDT5 = 81,
+ CSU_CSLX_SAI2,
+ CSU_CSLX_SAI1,
+ CSU_CSLX_SAI4,
+ CSU_CSLX_SAI3,
+ CSU_CSLX_FTM2 = 86,
+ CSU_CSLX_FTM1,
+ CSU_CSLX_FTM4,
+ CSU_CSLX_FTM3,
+ CSU_CSLX_FTM6 = 90,
+ CSU_CSLX_FTM5,
+ CSU_CSLX_FTM8,
+ CSU_CSLX_FTM7,
+ CSU_CSLX_DSCR = 121,
+};
+
+static struct csu_ns_dev ns_dev[] = {
+ {CSU_CSLX_PCIE2_IO, CSU_ALL_RW},
+ {CSU_CSLX_PCIE1_IO, CSU_ALL_RW},
+ {CSU_CSLX_MG2TPR_IP, CSU_ALL_RW},
+ {CSU_CSLX_IFC_MEM, CSU_ALL_RW},
+ {CSU_CSLX_OCRAM, CSU_ALL_RW},
+ {CSU_CSLX_GIC, CSU_ALL_RW},
+ {CSU_CSLX_PCIE1, CSU_ALL_RW},
+ {CSU_CSLX_OCRAM2, CSU_ALL_RW},
+ {CSU_CSLX_QSPI_MEM, CSU_ALL_RW},
+ {CSU_CSLX_PCIE2, CSU_ALL_RW},
+ {CSU_CSLX_SATA, CSU_ALL_RW},
+ {CSU_CSLX_USB1, CSU_ALL_RW},
+ {CSU_CSLX_QM_BM_SWPORTAL, CSU_ALL_RW},
+ {CSU_CSLX_PCIE3, CSU_ALL_RW},
+ {CSU_CSLX_PCIE3_IO, CSU_ALL_RW},
+ {CSU_CSLX_USB3, CSU_ALL_RW},
+ {CSU_CSLX_USB2, CSU_ALL_RW},
+ {CSU_CSLX_PFE, CSU_ALL_RW},
+ {CSU_CSLX_SERDES, CSU_ALL_RW},
+ {CSU_CSLX_QDMA, CSU_ALL_RW},
+ {CSU_CSLX_LPUART2, CSU_ALL_RW},
+ {CSU_CSLX_LPUART1, CSU_ALL_RW},
+ {CSU_CSLX_LPUART4, CSU_ALL_RW},
+ {CSU_CSLX_LPUART3, CSU_ALL_RW},
+ {CSU_CSLX_LPUART6, CSU_ALL_RW},
+ {CSU_CSLX_LPUART5, CSU_ALL_RW},
+ {CSU_CSLX_DSPI1, CSU_ALL_RW},
+ {CSU_CSLX_QSPI, CSU_ALL_RW},
+ {CSU_CSLX_ESDHC, CSU_ALL_RW},
+ {CSU_CSLX_IFC, CSU_ALL_RW},
+ {CSU_CSLX_I2C1, CSU_ALL_RW},
+ {CSU_CSLX_USB_2, CSU_ALL_RW},
+ {CSU_CSLX_I2C3, CSU_ALL_RW},
+ {CSU_CSLX_I2C2, CSU_ALL_RW},
+ {CSU_CSLX_DUART2, CSU_ALL_RW},
+ {CSU_CSLX_DUART1, CSU_ALL_RW},
+ {CSU_CSLX_WDT2, CSU_ALL_RW},
+ {CSU_CSLX_WDT1, CSU_ALL_RW},
+ {CSU_CSLX_EDMA, CSU_ALL_RW},
+ {CSU_CSLX_SYS_CNT, CSU_ALL_RW},
+ {CSU_CSLX_DMA_MUX2, CSU_ALL_RW},
+ {CSU_CSLX_DMA_MUX1, CSU_ALL_RW},
+ {CSU_CSLX_DDR, CSU_ALL_RW},
+ {CSU_CSLX_QUICC, CSU_ALL_RW},
+ {CSU_CSLX_DCFG_CCU_RCPM, CSU_ALL_RW},
+ {CSU_CSLX_SECURE_BOOTROM, CSU_ALL_RW},
+ {CSU_CSLX_SFP, CSU_ALL_RW},
+ {CSU_CSLX_TMU, CSU_ALL_RW},
+ {CSU_CSLX_SECURE_MONITOR, CSU_ALL_RW},
+ {CSU_CSLX_SCFG, CSU_ALL_RW},
+ {CSU_CSLX_FM, CSU_ALL_RW},
+ {CSU_CSLX_SEC5_5, CSU_ALL_RW},
+ {CSU_CSLX_BM, CSU_ALL_RW},
+ {CSU_CSLX_QM, CSU_ALL_RW},
+ {CSU_CSLX_GPIO2, CSU_ALL_RW},
+ {CSU_CSLX_GPIO1, CSU_ALL_RW},
+ {CSU_CSLX_GPIO4, CSU_ALL_RW},
+ {CSU_CSLX_GPIO3, CSU_ALL_RW},
+ {CSU_CSLX_PLATFORM_CONT, CSU_ALL_RW},
+ {CSU_CSLX_CSU, CSU_ALL_RW},
+ {CSU_CSLX_IIC4, CSU_ALL_RW},
+ {CSU_CSLX_WDT4, CSU_ALL_RW},
+ {CSU_CSLX_WDT3, CSU_ALL_RW},
+ {CSU_CSLX_ESDHC2, CSU_ALL_RW},
+ {CSU_CSLX_WDT5, CSU_ALL_RW},
+ {CSU_CSLX_SAI2, CSU_ALL_RW},
+ {CSU_CSLX_SAI1, CSU_ALL_RW},
+ {CSU_CSLX_SAI4, CSU_ALL_RW},
+ {CSU_CSLX_SAI3, CSU_ALL_RW},
+ {CSU_CSLX_FTM2, CSU_ALL_RW},
+ {CSU_CSLX_FTM1, CSU_ALL_RW},
+ {CSU_CSLX_FTM4, CSU_ALL_RW},
+ {CSU_CSLX_FTM3, CSU_ALL_RW},
+ {CSU_CSLX_FTM6, CSU_ALL_RW},
+ {CSU_CSLX_FTM5, CSU_ALL_RW},
+ {CSU_CSLX_FTM8, CSU_ALL_RW},
+ {CSU_CSLX_FTM7, CSU_ALL_RW},
+ {CSU_CSLX_DSCR, CSU_ALL_RW},
+};
+
+#endif
diff --git a/plat/layerscape/board/ls1043/include/plat_macros.S b/plat/layerscape/board/ls1043/include/plat_macros.S
new file mode 100644
index 0000000..8163dc1
--- /dev/null
+++ b/plat/layerscape/board/ls1043/include/plat_macros.S
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_MACROS_S__
+#define __PLAT_MACROS_S__
+
+ /* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant GIC and CCI registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ * Clobbers: x0 - x10, x16, x17, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ .endm
+
+#endif /* __PLAT_MACROS_S__ */
diff --git a/plat/layerscape/board/ls1043/include/platform_def.h b/plat/layerscape/board/ls1043/include/platform_def.h
new file mode 100644
index 0000000..0e1cae6
--- /dev/null
+++ b/plat/layerscape/board/ls1043/include/platform_def.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+#include <common_def.h>
+#include <tzc400.h>
+#include <utils.h>
+#include "ls_def.h"
+
+#define FIRMWARE_WELCOME_STR_LS1043 "Welcome to LS1043 BL1 Phase\n"
+#define FIRMWARE_WELCOME_STR_LS1043_BL2 "Welcome to LS1043 BL2 Phase\n"
+#define FIRMWARE_WELCOME_STR_LS1043_BL31 "Welcome to LS1043 BL31 Phase\n"
+#define FIRMWARE_WELCOME_STR_LS1043_BL32 "Welcome to LS1043 BL32 Phase, TSP\n"
+
+/* Required platform porting definitions */
+#define PLAT_PRIMARY_CPU 0x0
+#define PLAT_MAX_PWR_LVL LS_PWR_LVL1
+#define PLATFORM_CORE_COUNT 4
+#define COUNTER_FREQUENCY 25000000 /* 25MHz */
+
+/*
+ * Required LS standard platform porting definitions
+ */
+#define PLAT_LS_CLUSTER_COUNT 1
+#define PLAT_LS1043_CCI_CLUSTER0_SL_IFACE_IX 4
+#define LS1043_CLUSTER_COUNT 1
+#define LS1043_MAX_CPUS_PER_CLUSTER 4
+
+#define LS_DRAM1_BASE 0x80000000
+#define LS_DRAM2_BASE 0x880000000
+#define LS_DRAM2_SIZE 0x780000000 /* 30G */
+#define LS_DRAM1_SIZE 0x80000000 /* 2G */
+#define LS_NS_DRAM_BASE LS_DRAM1_BASE
+/* 64M Secure Memory, in fact there a 2M non-secure hole on top of it */
+#define LS_SECURE_DRAM_SIZE (64 * 1024 * 1024)
+#define LS_SECURE_DRAM_BASE (LS_NS_DRAM_BASE + LS_DRAM1_SIZE - \
+ LS_SECURE_DRAM_SIZE)
+#define LS_NS_DRAM_SIZE (LS_DRAM1_SIZE - LS_SECURE_DRAM_SIZE)
+
+/*
+ * By default, BL2 is in DDR memory.
+ * If LS_BL2_IN_OCRAM is defined, BL2 will in OCRAM
+ */
+/* #define LS_BL2_IN_OCRAM */
+
+#ifndef LS_BL2_IN_OCRAM
+/*
+ * on top of SECURE memory is 2M non-secure hole for OPTee,
+ * 1M secure memory below this hole will be used for BL2.
+ */
+#define LS_BL2_DDR_BASE (LS_SECURE_DRAM_BASE + \
+ LS_SECURE_DRAM_SIZE \
+ - 3 * 1024 * 1024)
+#endif
+
+#define PLAT_LS_CCSR_BASE 0x1000000
+#define PLAT_LS_CCSR_SIZE 0xF000000
+
+/* Flash base address, currently ROM is not used for TF-A images on LS platforms */
+#define PLAT_LS_TRUSTED_ROM_BASE 0x60100000
+#define PLAT_LS_TRUSTED_ROM_SIZE 0x20000000 /* Flash size */
+#define PLAT_LS_FLASH_SIZE 0x20000000
+#define PLAT_LS_FLASH_BASE 0x60000000
+
+#define LS_SRAM_BASE 0x10000000
+#define LS_SRAM_LIMIT 0x10020000 /* 128K */
+#define LS_SRAM_SHARED_SIZE 0x1000 /* 4K */
+#define LS_SRAM_SIZE (LS_SRAM_LIMIT - LS_SRAM_BASE)
+#define LS_BL_RAM_BASE (LS_SRAM_BASE + LS_SRAM_SHARED_SIZE)
+
+#define PLAT_LS_FIP_MAX_SIZE 0x4000000
+
+/* Memory Layout */
+
+#define BL1_RO_BASE PLAT_LS_TRUSTED_ROM_BASE
+#define BL1_RO_LIMIT (PLAT_LS_TRUSTED_ROM_BASE \
+ + PLAT_LS_TRUSTED_ROM_SIZE)
+#define PLAT_LS_FIP_BASE 0x60120000
+
+#ifdef LS_BL2_IN_OCRAM
+/* BL2 is in OCRAM */
+#define PLAT_LS_MAX_BL1_RW_SIZE (52 * 1024) /* 52K */
+#define PLAT_LS_MAX_BL31_SIZE (64 * 1024) /* 64K */
+#define PLAT_LS_MAX_BL2_SIZE (44 * 1024) /* 44K */
+/* Reserve memory in OCRAM for BL31 Text and ROData segment */
+#define BL31_TEXT_RODATA_SIZE (32 * 1024) /* 32K */
+#else /* LS_BL2_IN_OCRAM */
+/* BL2 in DDR */
+#define PLAT_LS_MAX_BL1_RW_SIZE (64 * 1024) /* 64K */
+#define PLAT_LS_MAX_BL31_SIZE (64 * 1024) /* 64K */
+#define PLAT_LS_MAX_BL2_SIZE (1 * 1024 * 1024) /* 1M */
+#endif /* LS_BL2_IN_OCRAM */
+/*
+ * Put BL31 at the start of OCRAM.
+ */
+#define BL31_BASE LS_SRAM_BASE
+#define BL31_LIMIT (LS_SRAM_BASE + PLAT_LS_MAX_BL31_SIZE)
+
+#ifdef LS_BL2_IN_OCRAM
+/*
+ * BL2 follow BL31 Text and ROData region.
+ */
+#define BL2_BASE (BL31_BASE + BL31_TEXT_RODATA_SIZE)
+#define BL2_LIMIT (BL2_BASE + PLAT_LS_MAX_BL2_SIZE)
+
+#else
+/*
+ * BL2 in DDR memory.
+ */
+#define BL2_BASE LS_BL2_DDR_BASE
+#define BL2_LIMIT (BL2_BASE + PLAT_LS_MAX_BL2_SIZE)
+
+#endif
+
+/*
+ * Put BL1 RW at the top of the Trusted SRAM.
+ */
+#ifdef LS_BL2_IN_OCRAM
+#define BL1_RW_BASE BL2_LIMIT
+#else
+#define BL1_RW_BASE BL31_LIMIT
+#endif
+#define BL1_RW_LIMIT LS_SRAM_LIMIT
+
+/* Put BL32 in secure memory */
+#define BL32_BASE LS_SECURE_DRAM_BASE
+#define BL32_LIMIT (LS_SECURE_DRAM_BASE + LS_SECURE_DRAM_SIZE)
+/* BL33 memory region */
+#define BL33_BASE 0x82000000
+#define BL33_LIMIT (LS_NS_DRAM_BASE + LS_NS_DRAM_SIZE)
+
+/*******************************************************************************
+ * BL32 specific defines.
+ ******************************************************************************/
+/*
+ * On ARM standard platforms, the TSP can execute from Trusted SRAM,
+ * Trusted DRAM (if available) or the DRAM region secured by the TrustZone
+ * controller.
+ */
+
+#define TSP_SEC_MEM_BASE BL32_BASE
+#define TSP_SEC_MEM_SIZE (BL32_LIMIT - BL32_BASE)
+
+/*
+ * ID of the secure physical generic timer interrupt used by the TSP.
+ */
+#define TSP_IRQ_SEC_PHY_TIMER 29
+
+
+/*
+ * GIC related constants
+ */
+#define PLAT_LS1043_CCI_BASE 0x01180000
+#define GICD_BASE 0x01401000
+#define GICC_BASE 0x01402000
+#define GICD_BASE_64K 0x01410000
+#define GICC_BASE_64K 0x01420000
+
+#define DCFG_CCSR_SVR 0x1ee00a4
+#define REV1_0 0x10
+#define REV1_1 0x11
+#define GIC_ADDR_BIT 31
+#define SCFG_GIC400_ALIGN 0x1570188
+
+/* UART related definition */
+
+#define PLAT_LS1043_DUART1_BASE 0x021c0000
+#define PLAT_LS1043_DUART2_BASE 0x021d0000
+#define PLAT_LS1043_DUART_SIZE 0x10000
+
+#define PLAT_LS1043_UART_BASE 0x21c0500
+#define PLAT_LS1043_UART2_BASE 0x21c0600
+#define PLAT_LS1043_UART_CLOCK 400000000
+#define PLAT_LS1043_UART_BAUDRATE 115200
+/* Define UART to be used by TF-A log */
+#define LS_TF_UART_BASE PLAT_LS1043_UART_BASE
+#define LS_TF_UART_CLOCK PLAT_LS1043_UART_CLOCK
+#define LS_TF_UART_BAUDRATE PLAT_LS1043_UART_BAUDRATE
+
+#define LS1043_SYS_CNTCTL_BASE 0x2B00000
+
+#define CONFIG_SYS_IMMR 0x01000000
+#define CONFIG_SYS_FSL_CSU_ADDR (CONFIG_SYS_IMMR + 0x00510000)
+
+/* Size of cacheable stacks */
+#if defined(IMAGE_BL1)
+#define PLATFORM_STACK_SIZE 0x440
+#define MAX_MMAP_REGIONS 6
+#define MAX_XLAT_TABLES 4
+#elif defined(IMAGE_BL2)
+#define PLATFORM_STACK_SIZE 0x400
+#define MAX_MMAP_REGIONS 8
+#define MAX_XLAT_TABLES 6
+#elif defined(IMAGE_BL31)
+#define PLATFORM_STACK_SIZE 0x400
+#define MAX_MMAP_REGIONS 8
+#define MAX_XLAT_TABLES 4
+#elif defined(IMAGE_BL32)
+#define PLATFORM_STACK_SIZE 0x440
+#define MAX_MMAP_REGIONS 8
+#define MAX_XLAT_TABLES 9
+#endif
+
+#define MAX_IO_DEVICES 3
+#define MAX_IO_HANDLES 4
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/layerscape/board/ls1043/include/soc_tzasc.h b/plat/layerscape/board/ls1043/include/soc_tzasc.h
new file mode 100644
index 0000000..0039f2d
--- /dev/null
+++ b/plat/layerscape/board/ls1043/include/soc_tzasc.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _SOC_TZASC_H_
+#define _SOC_TZASC_H_
+
+#include "tzc380.h"
+
+#define MAX_NUM_TZC_REGION 3
+
+/* TZASC related constants */
+#define TZASC_CONFIGURATION_REG 0x000
+#define TZASC_SECURITY_INV_REG 0x034
+#define TZASC_SECURITY_INV_EN 0x1
+#define TZASC_REGIONS_REG 0x100
+/* As region address should address atleast 32KB memory. */
+#define TZASC_REGION_LOWADDR_MASK 0xFFFF8000
+#define TZASC_REGION_LOWADDR_OFFSET 0x0
+#define TZASC_REGION_HIGHADDR_OFFSET 0x4
+#define TZASC_REGION_ATTR_OFFSET 0x8
+#define TZASC_REGION_ENABLED 1
+#define TZASC_REGION_DISABLED 0
+#define TZASC_REGION_SIZE_32KB 0xE
+#define TZASC_REGION_SIZE_64KB 0xF
+#define TZASC_REGION_SIZE_128KB 0x10
+#define TZASC_REGION_SIZE_256KB 0x11
+#define TZASC_REGION_SIZE_512KB 0x12
+#define TZASC_REGION_SIZE_1MB 0x13
+#define TZASC_REGION_SIZE_2MB 0x14
+#define TZASC_REGION_SIZE_4MB 0x15
+#define TZASC_REGION_SIZE_8MB 0x16
+#define TZASC_REGION_SIZE_16MB 0x17
+#define TZASC_REGION_SIZE_32MB 0x18
+#define TZASC_REGION_SIZE_64MB 0x19
+#define TZASC_REGION_SIZE_128MB 0x1A
+#define TZASC_REGION_SIZE_256MB 0x1B
+#define TZASC_REGION_SIZE_512MB 0x1C
+#define TZASC_REGION_SIZE_1GB 0x1D
+#define TZASC_REGION_SIZE_2GB 0x1E
+#define TZASC_REGION_SIZE_4GB 0x1F
+#define TZASC_REGION_SIZE_8GB 0x20
+#define TZASC_REGION_SIZE_16GB 0x21
+#define TZASC_REGION_SIZE_32GB 0x22
+#define TZASC_REGION_SECURITY_SR (1 << 3)
+#define TZASC_REGION_SECURITY_SW (1 << 2)
+#define TZASC_REGION_SECURITY_SRW (TZASC_REGION_SECURITY_SR| \
+ TZASC_REGION_SECURITY_SW)
+#define TZASC_REGION_SECURITY_NSR (1 << 1)
+#define TZASC_REGION_SECURITY_NSW 1
+#define TZASC_REGION_SECURITY_NSRW (TZASC_REGION_SECURITY_NSR| \
+ TZASC_REGION_SECURITY_NSW)
+
+#define CSU_SEC_ACCESS_REG_OFFSET 0x21C
+#define TZASC_BYPASS_MUX_DISABLE 0x4
+#define CCI_TERMINATE_BARRIER_TX 0x8
+#define CONFIG_SYS_FSL_TZASC_ADDR 0x1500000
+
+/* List of MAX_NUM_TZC_REGION TZC regions' boundaries and configurations. */
+
+static const struct tzc380_reg tzc380_reg_list[] = {
+ {
+ TZASC_REGION_SECURITY_NSRW, /* .secure attr */
+ 0x0, /* .enabled */
+ 0x0, /* .lowaddr */
+ 0x0, /* .highaddr */
+ 0x0, /* .size */
+ 0x0, /* .submask */
+ },
+ {
+ TZASC_REGION_SECURITY_SRW,
+ TZASC_REGION_ENABLED,
+ 0xFC000000,
+ 0x0,
+ TZASC_REGION_SIZE_64MB,
+ 0x80, /* Disable region 7 */
+ },
+ /* reserve 2M non-scure memory for OPTEE public memory */
+ {
+ TZASC_REGION_SECURITY_SRW,
+ TZASC_REGION_ENABLED,
+ 0xFF800000,
+ 0x0,
+ TZASC_REGION_SIZE_8MB,
+ 0xC0, /* Disable region 6 & 7 */
+ },
+
+ {}
+};
+
+#endif /* _SOC_TZASC_H_ */
diff --git a/plat/layerscape/board/ls1043/ls1043_bl1_setup.c b/plat/layerscape/board/ls1043/ls1043_bl1_setup.c
new file mode 100644
index 0000000..e82a1fb
--- /dev/null
+++ b/plat/layerscape/board/ls1043/ls1043_bl1_setup.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <cci.h>
+#include <debug.h>
+#include <mmio.h>
+#include "plat_ls.h"
+
+static const int cci_map[] = {
+ PLAT_LS1043_CCI_CLUSTER0_SL_IFACE_IX
+};
+
+void bl1_platform_setup(void)
+{
+ NOTICE(FIRMWARE_WELCOME_STR_LS1043);
+
+ ls_bl1_platform_setup();
+
+ /*
+ * Initialize system level generic timer for Layerscape Socs.
+ */
+ ls_delay_timer_init();
+
+ /* TODO: remove these DDR code */
+ VERBOSE("CS0_BNDS = %x\n", mmio_read_32(0x1080000 + 0x000));
+ mmio_write_32(0x1080000 + 0x000, 0x7f000000);
+ VERBOSE("CS0_BNDS = %x\n", mmio_read_32(0x1080000 + 0x000));
+}
+
+/*******************************************************************************
+ * Perform any BL1 specific platform actions.
+ ******************************************************************************/
+void bl1_early_platform_setup(void)
+{
+ ls_bl1_early_platform_setup();
+
+ /*
+ * Initialize Interconnect for this cluster during cold boot.
+ * No need for locks as no other CPU is active.
+ */
+ cci_init(PLAT_LS1043_CCI_BASE, cci_map, ARRAY_SIZE(cci_map));
+
+ /*
+ * Enable coherency in Interconnect for the primary CPU's cluster.
+ */
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
+
+}
+
+unsigned int bl1_plat_get_next_image_id(void)
+{
+ return BL2_IMAGE_ID;
+}
diff --git a/plat/layerscape/board/ls1043/ls1043_bl2_setup.c b/plat/layerscape/board/ls1043/ls1043_bl2_setup.c
new file mode 100644
index 0000000..b529aa5
--- /dev/null
+++ b/plat/layerscape/board/ls1043/ls1043_bl2_setup.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <mmio.h>
+#include <debug.h>
+#include "plat_ls.h"
+
+void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ ls_bl2_early_platform_setup((meminfo_t *)arg1);
+
+ /*
+ * Initialize system level generic timer for Layerscape Socs.
+ */
+ ls_delay_timer_init();
+}
+
+void bl2_platform_setup(void)
+{
+ NOTICE(FIRMWARE_WELCOME_STR_LS1043_BL2);
+}
diff --git a/plat/layerscape/board/ls1043/ls1043_bl31_setup.c b/plat/layerscape/board/ls1043/ls1043_bl31_setup.c
new file mode 100644
index 0000000..3473d98
--- /dev/null
+++ b/plat/layerscape/board/ls1043/ls1043_bl31_setup.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <cci.h>
+#include <debug.h>
+#include "plat_ls.h"
+#include "fsl_csu.h"
+
+/* slave interfaces according to the RM */
+static const int cci_map[] = {
+ 4,
+};
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+#ifdef LS_BL2_IN_OCRAM
+ unsigned long romem_base = (unsigned long)(&__TEXT_START__);
+ unsigned long romem_size = (unsigned long)(&__RODATA_END__)
+ - romem_base;
+
+ /* Check the Text and RO-Data region size */
+ if (romem_size > BL31_TEXT_RODATA_SIZE) {
+ ERROR("BL31 Text and RO-Data region size exceed reserved memory size\n");
+ panic();
+ }
+#endif
+
+ /*
+ * Initialize system level generic timer for Layerscape Socs.
+ */
+ ls_delay_timer_init();
+
+ ls_bl31_early_platform_setup((void *)arg0, (void *)arg3);
+
+ /*
+ * Initialize the correct interconnect for this cluster during cold
+ * boot. No need for locks as no other CPU is active.
+ */
+ cci_init(PLAT_LS1043_CCI_BASE, cci_map, ARRAY_SIZE(cci_map));
+
+ /*
+ * Enable coherency in interconnect for the primary CPU's cluster.
+ * Earlier bootloader stages might already do this (e.g. Trusted
+ * Firmware's BL1 does it) but we can't assume so. There is no harm in
+ * executing this code twice anyway.
+ */
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
+
+ /* Init CSU to enable non-secure access to peripherals */
+ enable_layerscape_ns_access();
+}
diff --git a/plat/layerscape/board/ls1043/ls1043_err.c b/plat/layerscape/board/ls1043/ls1043_err.c
new file mode 100644
index 0000000..e4a2cae
--- /dev/null
+++ b/plat/layerscape/board/ls1043/ls1043_err.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <debug.h>
+#include <errno.h>
+#include <stdint.h>
+
+/*
+ * Error handler
+ */
+void plat_error_handler(int err)
+{
+ switch (err) {
+ case -ENOENT:
+ case -EAUTH:
+ /* ToDo */
+ break;
+ default:
+ /* Unexpected error */
+ break;
+ }
+
+ /* Loop until the watchdog resets the system */
+ for (;;)
+ wfi();
+}
diff --git a/plat/layerscape/board/ls1043/ls1043_psci.c b/plat/layerscape/board/ls1043/ls1043_psci.c
new file mode 100644
index 0000000..1c83df4
--- /dev/null
+++ b/plat/layerscape/board/ls1043/ls1043_psci.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <debug.h>
+#include <errno.h>
+#include <assert.h>
+#include <platform.h>
+#include <psci.h>
+#include <mmio.h>
+#include <sys/endian.h>
+#include <gicv2.h>
+#include <delay_timer.h>
+#include "platform_def.h"
+
+#define LS_SCFG_BASE 0x01570000
+/* register to store warm boot entry, big endian, higher 32bit */
+#define LS_SCFG_SCRATCHRW0_OFFSET 0x600
+/* register to store warm boot entry, big endian, lower 32bit */
+#define LS_SCFG_SCRATCHRW1_OFFSET 0x604
+#define LS_SCFG_COREBCR_OFFSET 0x680
+
+#define LS_DCFG_BASE 0x01EE0000
+#define LS_DCFG_RSTCR_OFFSET 0x0B0
+#define LS_DCFG_RSTRQMR1_OFFSET 0x0C0
+#define LS_DCFG_BRR_OFFSET 0x0E4
+
+#define LS_SCFG_CORE0_SFT_RST_OFFSET 0x130
+#define LS_SCFG_CORE1_SFT_RST_OFFSET 0x134
+#define LS_SCFG_CORE2_SFT_RST_OFFSET 0x138
+#define LS_SCFG_CORE3_SFT_RST_OFFSET 0x13C
+
+#define LS_SCFG_CORESRENCR_OFFSET 0x204
+
+#define LS_SCFG_RVBAR0_0_OFFSET 0x220
+#define LS_SCFG_RVBAR0_1_OFFSET 0x224
+
+#define LS_SCFG_RVBAR1_0_OFFSET 0x228
+#define LS_SCFG_RVBAR1_1_OFFSET 0x22C
+
+#define LS_SCFG_RVBAR2_0_OFFSET 0x230
+#define LS_SCFG_RVBAR2_1_OFFSET 0x234
+
+#define LS_SCFG_RVBAR3_0_OFFSET 0x238
+#define LS_SCFG_RVBAR3_1_OFFSET 0x23C
+
+/* the entry for core warm boot */
+static uintptr_t warmboot_entry;
+
+/* warm reset single core */
+static void ls1043_reset_core(int core_pos)
+{
+ assert(core_pos >= 0 && core_pos < PLATFORM_CORE_COUNT);
+
+ /* set 0 in RVBAR, boot from bootrom at 0x0 */
+ mmio_write_32(LS_SCFG_BASE + LS_SCFG_RVBAR0_0_OFFSET + core_pos * 8,
+ 0);
+ mmio_write_32(LS_SCFG_BASE + LS_SCFG_RVBAR0_1_OFFSET + core_pos * 8,
+ 0);
+
+ dsb();
+ /* enable core soft reset */
+ mmio_write_32(LS_SCFG_BASE + LS_SCFG_CORESRENCR_OFFSET,
+ htobe32(1 << 31));
+ dsb();
+ isb();
+ /* reset core */
+ mmio_write_32(LS_SCFG_BASE + LS_SCFG_CORE0_SFT_RST_OFFSET +
+ core_pos * 4, htobe32(1 << 31));
+ mdelay(10);
+}
+
+static void __dead2 ls1043_system_reset(void)
+{
+ /* clear reset request mask bits */
+ mmio_write_32(LS_DCFG_BASE + LS_DCFG_RSTRQMR1_OFFSET, 0);
+
+ /* set reset request bit */
+ mmio_write_32(LS_DCFG_BASE + LS_DCFG_RSTCR_OFFSET,
+ htobe32((uint32_t)0x2));
+
+ /* system will reset; if fail, enter wfi */
+ dsb();
+ isb();
+ wfi();
+
+ panic();
+}
+
+
+static int ls1043_pwr_domain_on(u_register_t mpidr)
+{
+ int core_pos = plat_core_pos_by_mpidr(mpidr);
+ uint32_t core_mask, brr;
+
+ assert(core_pos >= 0 && core_pos < PLATFORM_CORE_COUNT);
+ core_mask = 1 << core_pos;
+
+ /* set warm boot entry */
+ mmio_write_32(LS_SCFG_BASE + LS_SCFG_SCRATCHRW0_OFFSET,
+ htobe32((uint32_t)(warmboot_entry >> 32)));
+
+ mmio_write_32(LS_SCFG_BASE + LS_SCFG_SCRATCHRW1_OFFSET,
+ htobe32((uint32_t)warmboot_entry));
+
+ dsb();
+
+ brr = be32toh(mmio_read_32(LS_DCFG_BASE + LS_DCFG_BRR_OFFSET));
+ if (brr & core_mask) {
+ /* core has been released, must reset it to restart */
+ ls1043_reset_core(core_pos);
+
+ /* set bit in core boot control register to enable boot */
+ mmio_write_32(LS_SCFG_BASE + LS_SCFG_COREBCR_OFFSET,
+ htobe32(core_mask));
+
+ } else {
+ /* set bit in core boot control register to enable boot */
+ mmio_write_32(LS_SCFG_BASE + LS_SCFG_COREBCR_OFFSET,
+ htobe32(core_mask));
+
+ /* release core */
+ mmio_write_32(LS_DCFG_BASE + LS_DCFG_BRR_OFFSET,
+ htobe32(brr | core_mask));
+ }
+
+ mdelay(20);
+
+ /* wake core in case it is in wfe */
+ dsb();
+ isb();
+ sev();
+
+ return PSCI_E_SUCCESS;
+}
+
+static void ls1043_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ /* Per cpu gic distributor setup */
+ gicv2_pcpu_distif_init();
+
+ /* Enable the gic CPU interface */
+ gicv2_cpuif_enable();
+}
+
+static void ls1043_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ /* Disable the gic CPU interface */
+ gicv2_cpuif_disable();
+}
+
+static plat_psci_ops_t ls1043_psci_pm_ops = {
+ .system_reset = ls1043_system_reset,
+ .pwr_domain_on = ls1043_pwr_domain_on,
+ .pwr_domain_on_finish = ls1043_pwr_domain_on_finish,
+ .pwr_domain_off = ls1043_pwr_domain_off,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ warmboot_entry = sec_entrypoint;
+ *psci_ops = &ls1043_psci_pm_ops;
+ return 0;
+}
diff --git a/plat/layerscape/board/ls1043/ls1043_security.c b/plat/layerscape/board/ls1043/ls1043_security.c
new file mode 100644
index 0000000..18ae56e
--- /dev/null
+++ b/plat/layerscape/board/ls1043/ls1043_security.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "plat_ls.h"
+
+/*
+ * We assume that all security programming is done by the primary core.
+ */
+void plat_ls_security_setup(void)
+{
+ tzc380_setup();
+}
diff --git a/plat/layerscape/board/ls1043/ls1043_stack_protector.c b/plat/layerscape/board/ls1043/ls1043_stack_protector.c
new file mode 100644
index 0000000..50f463b
--- /dev/null
+++ b/plat/layerscape/board/ls1043/ls1043_stack_protector.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <stdint.h>
+
+#define RANDOM_CANARY_VALUE ((u_register_t) 3288484550995823360ULL)
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+ /*
+ * Ideally, a random number should be returned instead of the
+ * combination of a timer's value and a compile-time constant. As the
+ * FVP does not have any random number generator, this is better than
+ * nothing but not necessarily really secure.
+ */
+ return RANDOM_CANARY_VALUE ^ read_cntpct_el0();
+}
diff --git a/plat/layerscape/board/ls1043/ls1043_topology.c b/plat/layerscape/board/ls1043/ls1043_topology.c
new file mode 100644
index 0000000..12d2830
--- /dev/null
+++ b/plat/layerscape/board/ls1043/ls1043_topology.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <cassert.h>
+#include "plat_ls.h"
+#include "platform_def.h"
+
+unsigned char ls1043_power_domain_tree_desc[LS1043_CLUSTER_COUNT + 1];
+
+
+CASSERT(LS1043_CLUSTER_COUNT && LS1043_CLUSTER_COUNT <= 256,
+ assert_invalid_ls1043_cluster_count);
+
+/*******************************************************************************
+ * This function dynamically constructs the topology according to
+ * LS1043_CLUSTER_COUNT and returns it.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ int i;
+
+ ls1043_power_domain_tree_desc[0] = LS1043_CLUSTER_COUNT;
+
+ for (i = 0; i < LS1043_CLUSTER_COUNT; i++)
+ ls1043_power_domain_tree_desc[i + 1] =
+ LS1043_MAX_CPUS_PER_CLUSTER;
+
+ return ls1043_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function returns the core count within the cluster corresponding to
+ * `mpidr`.
+ ******************************************************************************/
+unsigned int plat_ls_get_cluster_core_count(u_register_t mpidr)
+{
+ return LS1043_MAX_CPUS_PER_CLUSTER;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ if (ls_check_mpidr(mpidr) == -1)
+ return -1;
+
+ return plat_ls_calc_core_pos(mpidr);
+}
diff --git a/plat/layerscape/board/ls1043/ls_gic.c b/plat/layerscape/board/ls1043/ls_gic.c
new file mode 100644
index 0000000..3986153
--- /dev/null
+++ b/plat/layerscape/board/ls1043/ls_gic.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <mmio.h>
+#include <debug.h>
+#include <endian.h>
+#include "platform_def.h"
+#include "soc.h"
+
+/*
+ * Get GIC offset
+ * For LS1043a rev1.0, GIC base address align with 4k.
+ * For LS1043a rev1.1, if DCFG_GIC400_ALIGN[GIC_ADDR_BIT]
+ * is set, GIC base address align with 4K, or else align
+ * with 64k.
+ */
+void get_gic_offset(uint32_t *gicc_base, uint32_t *gicd_base)
+{
+
+ uint32_t *ccsr_svr = (uint32_t *)DCFG_CCSR_SVR;
+ uint32_t *gic_align = (uint32_t *)SCFG_GIC400_ALIGN;
+ uint32_t val;
+ uint32_t soc_dev_id;
+
+ val = be32toh(mmio_read_32((uintptr_t)ccsr_svr));
+ soc_dev_id = val & (SVR_WO_E << 8);
+
+ if ((soc_dev_id == (SVR_LS1043A << 8) ||
+ soc_dev_id == (SVR_LS1043AE << 8)) &&
+ ((val & 0xff) == REV1_1)) {
+ val = be32toh(mmio_read_32((uintptr_t)gic_align));
+ if (val & (1 << GIC_ADDR_BIT)) {
+ *gicc_base = GICC_BASE;
+ *gicd_base = GICD_BASE;
+ } else {
+ *gicc_base = GICC_BASE_64K;
+ *gicd_base = GICD_BASE_64K;
+ }
+ } else {
+ *gicc_base = GICC_BASE;
+ *gicd_base = GICD_BASE;
+ }
+}
diff --git a/plat/layerscape/board/ls1043/platform.mk b/plat/layerscape/board/ls1043/platform.mk
new file mode 100644
index 0000000..163d25e
--- /dev/null
+++ b/plat/layerscape/board/ls1043/platform.mk
@@ -0,0 +1,80 @@
+#
+# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# indicate the reset vector address can be programmed
+PROGRAMMABLE_RESET_ADDRESS := 1
+USE_COHERENT_MEM := 0
+RESET_TO_BL31 := 0
+ENABLE_STACK_PROTECTOR := 0
+LS1043_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
+ drivers/arm/gic/v2/gicv2_main.c \
+ drivers/arm/gic/v2/gicv2_helpers.c \
+ plat/common/plat_gicv2.c \
+ plat/layerscape/board/ls1043/ls_gic.c
+
+
+LS1043_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c
+
+LS1043_SECURITY_SOURCES := plat/layerscape/common/ls_tzc380.c \
+ plat/layerscape/board/ls1043/ls1043_security.c
+
+PLAT_INCLUDES := -Iplat/layerscape/board/ls1043/include \
+ -Iinclude/plat/arm/common \
+ -Iplat/layerscape/common/include \
+ -Iinclude/drivers/arm \
+ -Iinclude/lib \
+ -Iinclude/drivers/io
+
+
+PLAT_BL_COMMON_SOURCES := drivers/console/aarch64/console.S \
+ plat/layerscape/common/aarch64/ls_console.S
+
+LS1043_CPU_LIBS := lib/cpus/${ARCH}/aem_generic.S
+
+LS1043_CPU_LIBS += lib/cpus/aarch64/cortex_a53.S
+
+BL1_SOURCES += plat/layerscape/board/ls1043/ls1043_bl1_setup.c \
+ plat/layerscape/board/ls1043/ls1043_err.c \
+ drivers/delay_timer/delay_timer.c \
+
+BL1_SOURCES += plat/layerscape/board/ls1043/${ARCH}/ls1043_helpers.S \
+ ${LS1043_CPU_LIBS} \
+ ${LS1043_INTERCONNECT_SOURCES} \
+ $(LS1043_SECURITY_SOURCES)
+
+
+BL2_SOURCES += drivers/delay_timer/delay_timer.c \
+ plat/layerscape/board/ls1043/ls1043_bl2_setup.c \
+ plat/layerscape/board/ls1043/ls1043_err.c \
+ ${LS1043_SECURITY_SOURCES}
+
+
+BL31_SOURCES += plat/layerscape/board/ls1043/ls1043_bl31_setup.c \
+ plat/layerscape/board/ls1043/ls1043_topology.c \
+ plat/layerscape/board/ls1043/aarch64/ls1043_helpers.S \
+ plat/layerscape/board/ls1043/ls1043_psci.c \
+ drivers/delay_timer/delay_timer.c \
+ ${LS1043_CPU_LIBS} \
+ ${LS1043_GIC_SOURCES} \
+ ${LS1043_INTERCONNECT_SOURCES} \
+ ${LS1043_SECURITY_SOURCES}
+
+# Disable the PSCI platform compatibility layer
+ENABLE_PLAT_COMPAT := 0
+MULTI_CONSOLE_API := 1
+
+# Enable workarounds for selected Cortex-A53 erratas.
+ERRATA_A53_855873 := 1
+
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+PLAT_BL_COMMON_SOURCES += plat/layerscape/board/ls1043/ls1043_stack_protector.c
+endif
+
+ifeq (${ARCH},aarch32)
+ NEED_BL32 := yes
+endif
+
+include plat/layerscape/common/ls_common.mk
diff --git a/plat/layerscape/board/ls1043/tsp/ls1043_tsp_setup.c b/plat/layerscape/board/ls1043/tsp/ls1043_tsp_setup.c
new file mode 100644
index 0000000..4fc019c
--- /dev/null
+++ b/plat/layerscape/board/ls1043/tsp/ls1043_tsp_setup.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "plat_ls.h"
+
+void tsp_early_platform_setup(void)
+{
+ ls_tsp_early_platform_setup();
+
+ /*Todo: Initialize the platform config for future decision making */
+}
diff --git a/plat/layerscape/board/ls1043/tsp/tsp-ls1043.mk b/plat/layerscape/board/ls1043/tsp/tsp-ls1043.mk
new file mode 100644
index 0000000..3941427
--- /dev/null
+++ b/plat/layerscape/board/ls1043/tsp/tsp-ls1043.mk
@@ -0,0 +1,12 @@
+#
+# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# TSP source files specific to FVP platform
+BL32_SOURCES += plat/layerscape/board/ls1043/ls1043_topology.c \
+ plat/layerscape/board/ls1043/tsp/ls1043_tsp_setup.c \
+ ${LS1043_GIC_SOURCES}
+
+include plat/layerscape/common/tsp/ls_tsp.mk
diff --git a/plat/layerscape/common/aarch64/ls_bl2_mem_params_desc.c b/plat/layerscape/common/aarch64/ls_bl2_mem_params_desc.c
new file mode 100644
index 0000000..a96e390
--- /dev/null
+++ b/plat/layerscape/common/aarch64/ls_bl2_mem_params_desc.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl_common.h>
+#include <desc_image_load.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <debug.h>
+#include <ls_def.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+#ifdef EL3_PAYLOAD_BASE
+ /* Fill EL3 payload related information (BL31 is EL3 payload)*/
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = EL3_PAYLOAD_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_PLAT_SETUP |
+ IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+#else /* EL3_PAYLOAD_BASE */
+
+ /* Fill BL31 related information */
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = BL31_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+#if DEBUG
+ .ep_info.args.arg1 = LS_BL31_PLAT_PARAM_VAL,
+#endif
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
+ .image_info.image_base = BL31_BASE,
+ .image_info.image_max_size = (BL31_LIMIT - BL31_BASE),
+
+# ifdef BL32_BASE
+ .next_handoff_image_id = BL32_IMAGE_ID,
+# else
+ .next_handoff_image_id = BL33_IMAGE_ID,
+# endif
+ },
+# ifdef BL32_BASE
+ /* Fill BL32 related information */
+ {
+ .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),
+ .ep_info.pc = BL32_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = (BL32_LIMIT - BL32_BASE),
+
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+# endif /* BL32_BASE */
+
+ /* Fill BL33 related information */
+ {
+ .image_id = BL33_IMAGE_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE),
+# ifdef PRELOADED_BL33_BASE
+ .ep_info.pc = PRELOADED_BL33_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+# else
+ .ep_info.pc = BL33_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = BL33_BASE,
+ .image_info.image_max_size = LS_NS_DRAM_SIZE,
+# endif /* PRELOADED_BL33_BASE */
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ }
+#endif /* EL3_PAYLOAD_BASE */
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/layerscape/common/aarch64/ls_console.S b/plat/layerscape/common/aarch64/ls_console.S
new file mode 100644
index 0000000..5c87465
--- /dev/null
+++ b/plat/layerscape/common/aarch64/ls_console.S
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <console_macros.S>
+#include <assert_macros.S>
+#include "ls_16550.h"
+
+ /*
+ * "core" functions are low-level implementations that don't require
+ * writable memory and are thus safe to call in BL1 crash context.
+ */
+ .globl console_ls_16550_core_init
+ .globl console_ls_16550_core_putc
+ .globl console_ls_16550_core_getc
+
+ .globl console_ls_16550_putc
+ .globl console_ls_16550_getc
+ .globl console_ls_16550_flush
+
+ /* -----------------------------------------------
+ * int console_ls_16550_core_init(uintptr_t base_addr,
+ * unsigned int uart_clk, unsigned int baud_rate)
+ * Function to initialize the console without a
+ * C Runtime to print debug information. This
+ * function will be accessed by console_init and
+ * crash reporting.
+ * In: x0 - console base address
+ * w1 - Uart clock in Hz
+ * w2 - Baud rate
+ * Out: return 1 on success, 0 on error
+ * Clobber list : x1, x2, x3
+ * -----------------------------------------------
+ */
+func console_ls_16550_core_init
+ /* Check the input base address */
+ cbz x0, init_fail
+ /* Check baud rate and uart clock for sanity */
+ cbz w1, init_fail
+ cbz w2, init_fail
+
+ /* Program the baudrate */
+ /* Divisor = Uart clock / (16 * baudrate) */
+ lsl w2, w2, #4
+ udiv w2, w1, w2
+ and w1, w2, #0xff /* w1 = DLL */
+ lsr w2, w2, #8
+ and w2, w2, #0xff /* w2 = DLLM */
+ ldrb w3, [x0, #UARTLCR]
+ orr w3, w3, #UARTLCR_DLAB
+ strb w3, [x0, #UARTLCR] /* enable DLL, DLLM programming */
+ strb w1, [x0, #UARTDLL] /* program DLL */
+ strb w2, [x0, #UARTDLLM] /* program DLLM */
+ mov w2, #~UARTLCR_DLAB
+ and w3, w3, w2
+ strb w3, [x0, #UARTLCR] /* disable DLL, DLLM programming */
+
+ /* 8n1 */
+ mov w3, #3
+ strb w3, [x0, #UARTLCR]
+ /* no interrupt */
+ mov w3, #0
+ strb w3, [x0, #UARTIER]
+ /* enable fifo, DMA */
+ mov w3, #(UARTFCR_FIFOEN |UARTFCR_TXCLR | UARTFCR_RXCLR)
+ strb w3, [x0, #UARTFCR]
+ /* DTR + RTS */
+ mov w3, #3
+ str w3, [x0, #UARTMCR]
+ mov w0, #1
+ ret
+init_fail:
+ mov w0, #0
+ ret
+endfunc console_ls_16550_core_init
+
+#if MULTI_CONSOLE_API
+ .globl console_ls_16550_register
+
+ /* -----------------------------------------------
+ * int console_ls_16550_register(console_ls_16550_t *console,
+ * uintptr_t base, uint32_t clk, uint32_t baud)
+ * Function to initialize and register a new 16550
+ * console. Storage passed in for the console struct
+ * *must* be persistent (i.e. not from the stack).
+ * In: x0 - UART register base address
+ * w1 - UART clock in Hz
+ * w2 - Baud rate
+ * x3 - pointer to empty console_ls_16550_t struct
+ * Out: return 1 on success, 0 on error
+ * Clobber list : x0, x1, x2, x6, x7, x14
+ * -----------------------------------------------
+ */
+func console_ls_16550_register
+ mov x7, x30
+ mov x6, x3
+ cbz x6, register_fail
+ str x0, [x6, #CONSOLE_T_16550_BASE]
+
+ bl console_ls_16550_core_init
+ cbz x0, register_fail
+
+ mov x0, x6
+ mov x30, x7
+ finish_console_register ls_16550
+
+register_fail:
+ ret x7
+endfunc console_ls_16550_register
+#else
+ .globl console_core_init
+ .globl console_core_putc
+ .globl console_core_getc
+ .globl console_core_flush
+ .equ console_core_init,console_ls_16550_core_init
+ .equ console_core_putc,console_ls_16550_core_putc
+ .equ console_core_getc,console_ls_16550_core_getc
+ .equ console_core_flush,console_ls_16550_core_flush
+#endif
+
+ /* --------------------------------------------------------
+ * int console_ls_16550_core_putc(int c, uintptr_t base_addr)
+ * Function to output a character over the console. It
+ * returns the character printed on success or -1 on error.
+ * In : w0 - character to be printed
+ * x1 - console base address
+ * Out : return -1 on error else return character.
+ * Clobber list : x2
+ * --------------------------------------------------------
+ */
+func console_ls_16550_core_putc
+#if ENABLE_ASSERTIONS
+ cmp x1, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+
+ /* Prepend '\r' to '\n' */
+ cmp w0, #0xA //'\n'
+ b.ne 2f
+ /* Check if the transmit FIFO is full */
+1: ldrb w2, [x1, #UARTLSR]
+ and w2, w2, #UARTLSR_THRE /* #(UARTLSR_TEMT | UARTLSR_THRE)*/
+ cmp w2, #(UARTLSR_THRE)
+ b.ne 1b
+ mov w2, #0xD /* '\r' */
+ strb w2, [x1, #UARTTX]
+ ldrb w2, [x1, #UARTFCR]
+ orr w2, w2, #UARTFCR_TXCLR
+
+ /* Check if the transmit FIFO is full */
+2: ldrb w2, [x1, #UARTLSR]
+ and w2, w2, #(UARTLSR_THRE)
+ cmp w2, #(UARTLSR_THRE)
+ b.ne 2b
+ strb w0, [x1, #UARTTX]
+ ret
+endfunc console_ls_16550_core_putc
+
+ /* --------------------------------------------------------
+ * int console_16550_putc(int c, console_ls_16550_t *console)
+ * Function to output a character over the console. It
+ * returns the character printed on success or -1 on error.
+ * In : w0 - character to be printed
+ * x1 - pointer to console_t structure
+ * Out : return -1 on error else return character.
+ * Clobber list : x2
+ * --------------------------------------------------------
+ */
+func console_ls_16550_putc
+#if ENABLE_ASSERTIONS
+ cmp x1, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+ ldr x1, [x1, #CONSOLE_T_16550_BASE]
+ b console_ls_16550_core_putc
+endfunc console_ls_16550_putc
+
+ /* ---------------------------------------------
+ * int console_ls_16550_core_getc(uintptr_t base_addr)
+ * Function to get a character from the console.
+ * It returns the character grabbed on success
+ * or -1 on if no character is available.
+ * In : x0 - console base address
+ * Out : w0 - character if available, else -1
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func console_ls_16550_core_getc
+#if ENABLE_ASSERTIONS
+ cmp x0, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+
+ /* Check if the receive FIFO is empty */
+1: ldrb w1, [x0, #UARTLSR]
+ tbz w1, #UARTLSR_RDR, 1b
+ ldrb w0, [x0, #UARTRX]
+ ret
+no_char:
+ mov w0, #ERROR_NO_PENDING_CHAR
+ ret
+endfunc console_ls_16550_core_getc
+
+ /* ---------------------------------------------
+ * int console_ls_16550_getc(console_ls_16550_t *console)
+ * Function to get a character from the console.
+ * It returns the character grabbed on success
+ * or -1 on if no character is available.
+ * In : x0 - pointer to console_t structure
+ * Out : w0 - character if available, else -1
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func console_ls_16550_getc
+#if ENABLE_ASSERTIONS
+ cmp x1, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+ ldr x0, [x0, #CONSOLE_T_16550_BASE]
+ b console_ls_16550_core_getc
+endfunc console_ls_16550_getc
+
+ /* ---------------------------------------------
+ * int console_ls_16550_core_flush(uintptr_t base_addr)
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * In : x0 - console base address
+ * Out : return -1 on error else return 0.
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func console_ls_16550_core_flush
+#if ENABLE_ASSERTIONS
+ cmp x0, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+
+ /* Loop until the transmit FIFO is empty */
+1: ldrb w1, [x0, #UARTLSR]
+ and w1, w1, #(UARTLSR_TEMT | UARTLSR_THRE)
+ cmp w1, #(UARTLSR_TEMT | UARTLSR_THRE)
+ b.ne 1b
+
+ mov w0, #0
+ ret
+endfunc console_ls_16550_core_flush
+
+ /* ---------------------------------------------
+ * int console_ls_16550_flush(console_ls_16550_t *console)
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * In : x0 - pointer to console_t structure
+ * Out : return -1 on error else return 0.
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func console_ls_16550_flush
+#if ENABLE_ASSERTIONS
+ cmp x0, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+ ldr x0, [x0, #CONSOLE_T_16550_BASE]
+ b console_ls_16550_core_flush
+endfunc console_ls_16550_flush
diff --git a/plat/layerscape/common/aarch64/ls_helpers.S b/plat/layerscape/common/aarch64/ls_helpers.S
new file mode 100644
index 0000000..7d71f48
--- /dev/null
+++ b/plat/layerscape/common/aarch64/ls_helpers.S
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <console.h>
+#include <platform_def.h>
+
+ .weak plat_my_core_pos
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+ .weak platform_mem_init
+ .globl plat_ls_calc_core_pos
+
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * This function uses the plat_ls_calc_core_pos()
+ * definition to get the index of the calling CPU.
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b plat_ls_calc_core_pos
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int plat_ls_calc_core_pos(u_register_t mpidr)
+ * Helper function to calculate the core position.
+ * With this function: CorePos = (ClusterId * 4) +
+ * CoreId
+ * -----------------------------------------------------
+ */
+func plat_ls_calc_core_pos
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc plat_ls_calc_core_pos
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0 - x4
+ * ---------------------------------------------
+ */
+
+#if MULTI_CONSOLE_API
+ /* -----------------------------------------------------
+ * int plat_crash_console_init(void)
+ * Use normal console by default. Switch it to crash
+ * mode so serial consoles become active again.
+ * NOTE: This default implementation will only work for
+ * crashes that occur after a normal console (marked
+ * valid for the crash state) has been registered with
+ * the console framework. To debug crashes that occur
+ * earlier, the platform has to override these functions
+ * with an implementation that initializes a console
+ * driver with hardcoded parameters. See
+ * docs/porting-guide.rst for more information.
+ * -----------------------------------------------------
+ */
+func plat_crash_console_init
+#if defined(IMAGE_BL1)
+ /*
+ * BL1 code can possibly crash so early that the data segment is not yet
+ * accessible. Don't risk undefined behavior by trying to run the normal
+ * console framework. Platforms that want to debug BL1 will need to
+ * override this with custom functions that can run from registers only.
+ */
+ mov x0, #0
+ ret
+#else /* IMAGE_BL1 */
+ mov x3, x30
+ mov x0, #CONSOLE_FLAG_CRASH
+ bl console_switch_state
+ mov x0, #1
+ ret x3
+#endif
+endfunc plat_crash_console_init
+
+ /* -----------------------------------------------------
+ * void plat_crash_console_putc(int character)
+ * Output through the normal console by default.
+ * -----------------------------------------------------
+ */
+func plat_crash_console_putc
+ b console_putc
+endfunc plat_crash_console_putc
+
+ /* -----------------------------------------------------
+ * void plat_crash_console_flush(void)
+ * Flush normal console by default.
+ * -----------------------------------------------------
+ */
+func plat_crash_console_flush
+ b console_flush
+endfunc plat_crash_console_flush
+
+#else /* MULTI_CONSOLE_API */
+
+ /* -----------------------------------------------------
+ * In the old API these are all no-op stubs that need to
+ * be overridden by the platform to be useful.
+ * -----------------------------------------------------
+ */
+func plat_crash_console_init
+ mov_imm x0, PLAT_LS1043_UART_BASE
+ mov_imm x1, PLAT_LS1043_UART_CLOCK
+ mov_imm x2, PLAT_LS1043_UART_BAUDRATE
+ b console_core_init
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(int c)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ mov_imm x1, PLAT_LS1043_UART_BASE
+ b console_core_putc
+endfunc plat_crash_console_putc
+
+ /* ---------------------------------------------
+ * int plat_crash_console_flush()
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * Out : return -1 on error else return 0.
+ * Clobber list : r0 - r1
+ * ---------------------------------------------
+ */
+func plat_crash_console_flush
+ mov_imm x1, PLAT_LS1043_UART_BASE
+ b console_core_flush
+endfunc plat_crash_console_flush
+#endif
+ /* ---------------------------------------------------------------------
+ * We don't need to carry out any memory initialization on LS
+ * platforms. The Secure SRAM is accessible straight away.
+ * ---------------------------------------------------------------------
+ */
+func platform_mem_init
+ ret
+endfunc platform_mem_init
diff --git a/plat/layerscape/common/include/fsl_csu.h b/plat/layerscape/common/include/fsl_csu.h
new file mode 100644
index 0000000..680911e
--- /dev/null
+++ b/plat/layerscape/common/include/fsl_csu.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __FSL_CSU_H__
+#define __FSL_CSU_H__
+
+enum csu_cslx_access {
+ CSU_NS_SUP_R = 0x08,
+ CSU_NS_SUP_W = 0x80,
+ CSU_NS_SUP_RW = 0x88,
+ CSU_NS_USER_R = 0x04,
+ CSU_NS_USER_W = 0x40,
+ CSU_NS_USER_RW = 0x44,
+ CSU_S_SUP_R = 0x02,
+ CSU_S_SUP_W = 0x20,
+ CSU_S_SUP_RW = 0x22,
+ CSU_S_USER_R = 0x01,
+ CSU_S_USER_W = 0x10,
+ CSU_S_USER_RW = 0x11,
+ CSU_ALL_RW = 0xff,
+};
+
+struct csu_ns_dev {
+ uintptr_t ind;
+ uint32_t val;
+};
+
+void enable_layerscape_ns_access(void);
+
+#endif
diff --git a/plat/layerscape/common/include/ls_16550.h b/plat/layerscape/common/include/ls_16550.h
new file mode 100644
index 0000000..503a01d
--- /dev/null
+++ b/plat/layerscape/common/include/ls_16550.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __LS_16550_H__
+#define __LS_16550_H__
+
+#include <console.h>
+
+/* UART16550 Registers */
+#define UARTTX 0x0
+#define UARTRX 0x0
+#define UARTDLL 0x0
+#define UARTIER 0x1
+#define UARTDLLM 0x1
+#define UARTFCR 0x2
+#define UARTLCR 0x3
+#define UARTLSR 0x5
+#define UARTMCR 0x4
+
+/* FIFO Control Register bits */
+#define UARTFCR_FIFOMD_16450 (0 << 6)
+#define UARTFCR_FIFOMD_16550 (1 << 6)
+#define UARTFCR_RXTRIG_1 (0 << 6)
+#define UARTFCR_RXTRIG_4 (1 << 6)
+#define UARTFCR_RXTRIG_8 (2 << 6)
+#define UARTFCR_RXTRIG_16 (3 << 6)
+#define UARTFCR_TXTRIG_1 (0 << 4)
+#define UARTFCR_TXTRIG_4 (1 << 4)
+#define UARTFCR_TXTRIG_8 (2 << 4)
+#define UARTFCR_TXTRIG_16 (3 << 4)
+#define UARTFCR_DMAEN (1 << 3) /* Enable DMA mode */
+#define UARTFCR_TXCLR (1 << 2) /* Clear contents of Tx FIFO */
+#define UARTFCR_RXCLR (1 << 1) /* Clear contents of Rx FIFO */
+#define UARTFCR_FIFOEN (1 << 0) /* Enable the Tx/Rx FIFO */
+#define UARTFCR_64FIFO (1 << 5)
+
+/* Line Control Register bits */
+#define UARTLCR_DLAB (1 << 7) /* Divisor Latch Access */
+#define UARTLCR_SETB (1 << 6) /* Set BREAK Condition */
+#define UARTLCR_SETP (1 << 5) /* Set Parity to LCR[4] */
+#define UARTLCR_EVEN (1 << 4) /* Even Parity Format */
+#define UARTLCR_PAR (1 << 3) /* Parity */
+#define UARTLCR_STOP (1 << 2) /* Stop Bit */
+#define UARTLCR_WORDSZ_5 0 /* Word Length of 5 */
+#define UARTLCR_WORDSZ_6 1 /* Word Length of 6 */
+#define UARTLCR_WORDSZ_7 2 /* Word Length of 7 */
+#define UARTLCR_WORDSZ_8 3 /* Word Length of 8 */
+
+/* Line Status Register bits */
+#define UARTLSR_RXFIFOEMT (1 << 9) /* Rx Fifo Empty */
+#define UARTLSR_TXFIFOFULL (1 << 8) /* Tx Fifo Full */
+#define UARTLSR_RXFIFOERR (1 << 7) /* Rx Fifo Error */
+#define UARTLSR_TEMT (1 << 6) /* Tx Shift Register Empty */
+#define UARTLSR_THRE (1 << 5) /* Tx Holding Register Empty */
+#define UARTLSR_BRK (1 << 4) /* Break Condition Detected */
+#define UARTLSR_FERR (1 << 3) /* Framing Error */
+#define UARTLSR_PERR (1 << 3) /* Parity Error */
+#define UARTLSR_OVRF (1 << 2) /* Rx Overrun Error */
+#define UARTLSR_RDR (1 << 2) /* Rx Data Ready */
+
+#define CONSOLE_T_16550_BASE CONSOLE_T_DRVDATA
+
+#ifndef __ASSEMBLY__
+
+#include <types.h>
+
+typedef struct {
+ console_t console;
+ uintptr_t base;
+} console_ls_16550_t;
+
+/*
+ * Initialize a new 16550 console instance and register it with the console
+ * framework. The |console| pointer must point to storage that will be valid
+ * for the lifetime of the console, such as a global or static local variable.
+ * Its contents will be reinitialized from scratch.
+ */
+int console_ls_16550_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
+ console_ls_16550_t *console);
+
+#endif /*__ASSEMBLY__*/
+
+#endif /* __LS_16550_H__ */
diff --git a/plat/layerscape/common/include/plat_ls.h b/plat/layerscape/common/include/plat_ls.h
new file mode 100644
index 0000000..9d5ec14
--- /dev/null
+++ b/plat/layerscape/common/include/plat_ls.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_LS_H__
+#define __PLAT_LS_H__
+
+#include <sys/types.h>
+#include <cpu_data.h>
+
+/* BL1 utility functions */
+void ls_bl1_platform_setup(void);
+void ls_bl1_early_platform_setup(void);
+
+/* BL2 utility functions */
+void ls_bl2_early_platform_setup(meminfo_t *mem_layout);
+uint32_t ls_get_spsr_for_bl32_entry(void);
+uint32_t ls_get_spsr_for_bl33_entry(void);
+
+/* BL3 utility functions */
+void ls_bl31_early_platform_setup(void *from_bl2,
+ void *plat_params_from_bl2);
+
+/* IO storage utility functions */
+void plat_ls_io_setup(void);
+
+
+void ls_setup_page_tables(uintptr_t total_base,
+ size_t total_size,
+ uintptr_t code_start,
+ uintptr_t code_limit,
+ uintptr_t rodata_start,
+ uintptr_t rodata_limit
+#if USE_COHERENT_MEM
+ , uintptr_t coh_start,
+ uintptr_t coh_limit
+#endif
+);
+
+/* PSCI utility functions */
+int ls_check_mpidr(u_register_t mpidr);
+
+/* Security utility functions */
+int tzc380_setup(void);
+
+/* Timer utility functions */
+uint64_t ls_get_timer(uint64_t start);
+void ls_delay_timer_init(void);
+
+/* TSP utility functions */
+void ls_tsp_early_platform_setup(void);
+
+/* Helper functions */
+unsigned int plat_ls_calc_core_pos(u_register_t mpidr);
+
+/* others */
+unsigned int plat_ls_get_cluster_core_count(u_register_t mpidr);
+
+#endif /* __PLAT_LS_H__ */
diff --git a/plat/layerscape/common/include/soc.h b/plat/layerscape/common/include/soc.h
new file mode 100644
index 0000000..72c10cf
--- /dev/null
+++ b/plat/layerscape/common/include/soc.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __LAYERSCAPE_SOC_H__
+#define __LAYERSCAPE_SOC_H__
+
+#include <stdint.h>
+
+#define SVR_WO_E 0xFFFFFE
+#define SVR_LS1043A 0x879204
+#define SVR_LS1043AE 0x879200
+
+void get_gic_offset(uint32_t *gicc_base, uint32_t *gicd_base);
+
+#endif /* __LAYERSCAPE_SOC_H__ */
diff --git a/plat/layerscape/common/include/tzc380.h b/plat/layerscape/common/include/tzc380.h
new file mode 100644
index 0000000..788c0ed
--- /dev/null
+++ b/plat/layerscape/common/include/tzc380.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __TZC380_H__
+#define __TZC380_H__
+
+struct tzc380_reg {
+ unsigned int secure;
+ unsigned int enabled;
+ unsigned int low_addr;
+ unsigned int high_addr;
+ unsigned int size;
+ unsigned int sub_mask;
+};
+
+#endif /* __TZC380_H__ */
diff --git a/plat/layerscape/common/ls_bl1_setup.c b/plat/layerscape/common/ls_bl1_setup.c
new file mode 100644
index 0000000..43f7450
--- /dev/null
+++ b/plat/layerscape/common/ls_bl1_setup.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include "ls_16550.h"
+#include "plat_ls.h"
+#include "../../../bl1/bl1_private.h"
+
+/* Data structure which holds the extents of the trusted SRAM for BL1*/
+static meminfo_t bl1_tzram_layout;
+
+meminfo_t *bl1_plat_sec_mem_layout(void)
+{
+ return &bl1_tzram_layout;
+}
+
+/*******************************************************************************
+ * BL1 specific platform actions shared between ARM standard platforms.
+ ******************************************************************************/
+void ls_bl1_early_platform_setup(void)
+{
+ static console_ls_16550_t console;
+
+#if !LS1043_DISABLE_TRUSTED_WDOG
+ /* TODO: Enable watchdog */
+
+#endif
+
+ /* Initialize the console to provide early debug support */
+ console_ls_16550_register(LS_TF_UART_BASE, LS_TF_UART_CLOCK,
+ LS_TF_UART_BAUDRATE, &console);
+
+ /* Allow BL1 to see the whole Trusted RAM */
+ bl1_tzram_layout.total_base = LS_SRAM_BASE;
+ bl1_tzram_layout.total_size = LS_SRAM_SIZE;
+}
+
+/******************************************************************************
+ * Perform the very early platform specific architecture setup shared between
+ * ARM standard platforms. This only does basic initialization. Later
+ * architectural setup (bl1_arch_setup()) does not do anything platform
+ * specific.
+ *****************************************************************************/
+void ls_bl1_plat_arch_setup(void)
+{
+ ls_setup_page_tables(bl1_tzram_layout.total_base,
+ bl1_tzram_layout.total_size,
+ BL_CODE_BASE,
+ BL1_CODE_END,
+ BL1_RO_DATA_BASE,
+ BL1_RO_DATA_END
+#if USE_COHERENT_MEM
+ , BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END
+#endif
+ );
+ VERBOSE("After setup the page tables\n");
+#ifdef AARCH32
+ enable_mmu_secure(0);
+#else
+ enable_mmu_el3(0);
+#endif /* AARCH32 */
+ VERBOSE("After MMU enabled\n");
+}
+
+void bl1_plat_arch_setup(void)
+{
+ ls_bl1_plat_arch_setup();
+}
+
+/*
+ * Perform the platform specific architecture setup shared between
+ * ARM standard platforms.
+ */
+void ls_bl1_platform_setup(void)
+{
+ /* Initialise the IO layer and register platform IO devices */
+ plat_ls_io_setup();
+}
+
+void bl1_plat_prepare_exit(entry_point_info_t *ep_info)
+{
+#if !LS1043_DISABLE_TRUSTED_WDOG
+ /*TODO: Disable watchdog before leaving BL1 */
+#endif
+}
diff --git a/plat/layerscape/common/ls_bl2_setup.c b/plat/layerscape/common/ls_bl2_setup.c
new file mode 100644
index 0000000..6e6ad6e
--- /dev/null
+++ b/plat/layerscape/common/ls_bl2_setup.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <bl_common.h>
+#include <desc_image_load.h>
+#include "ls_16550.h"
+#include "plat_ls.h"
+#include "ls_def.h"
+
+/* Data structure which holds the extents of the trusted SRAM for BL2 */
+static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
+
+/*******************************************************************************
+ * BL1 has passed the extents of the trusted SRAM that should be visible to BL2
+ * in x0. This memory layout is sitting at the base of the free trusted SRAM.
+ * Copy it to a safe location before its reclaimed by later BL2 functionality.
+ ******************************************************************************/
+void ls_bl2_early_platform_setup(meminfo_t *mem_layout)
+{
+ static console_ls_16550_t console;
+
+ /* Initialize the console to provide early debug support */
+ console_ls_16550_register(LS_TF_UART_BASE, LS_TF_UART_CLOCK,
+ LS_TF_UART_BAUDRATE, &console);
+
+ /* Setup the BL2 memory layout */
+ bl2_tzram_layout = *mem_layout;
+
+ /* Initialise the IO layer and register platform IO devices */
+ plat_ls_io_setup();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only initializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void ls_bl2_plat_arch_setup(void)
+{
+ ls_setup_page_tables(bl2_tzram_layout.total_base,
+ bl2_tzram_layout.total_size,
+ BL_CODE_BASE,
+ BL_CODE_END,
+ BL_RO_DATA_BASE,
+ BL_RO_DATA_END
+#if USE_COHERENT_MEM
+ , BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END
+#endif
+ );
+
+#ifdef AARCH32
+ enable_mmu_secure(0);
+#else
+ enable_mmu_el1(0);
+#endif
+}
+
+void bl2_plat_arch_setup(void)
+{
+ ls_bl2_plat_arch_setup();
+}
+
+int ls_bl2_handle_post_image_load(unsigned int image_id)
+{
+ int err = 0;
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+
+ assert(bl_mem_params);
+
+ switch (image_id) {
+#ifdef AARCH64
+ case BL32_IMAGE_ID:
+ bl_mem_params->ep_info.spsr = ls_get_spsr_for_bl32_entry();
+ break;
+#endif
+
+ case BL33_IMAGE_ID:
+ /* BL33 expects to receive the primary CPU MPID (through r0) */
+ bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
+ bl_mem_params->ep_info.spsr = ls_get_spsr_for_bl33_entry();
+ break;
+ }
+
+ return err;
+}
+
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ return ls_bl2_handle_post_image_load(image_id);
+}
diff --git a/plat/layerscape/common/ls_bl31_setup.c b/plat/layerscape/common/ls_bl31_setup.c
new file mode 100644
index 0000000..3016f58
--- /dev/null
+++ b/plat/layerscape/common/ls_bl31_setup.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <console.h>
+#include <mmio.h>
+#include <gicv2.h>
+#include "ls_16550.h"
+#include "plat_ls.h"
+#include "soc.h"
+
+#define BL31_END (uintptr_t)(&__BL31_END__)
+
+/*
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL31 from BL2.
+ */
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+const unsigned int g0_interrupt_array1[] = {
+ 9
+};
+
+gicv2_driver_data_t ls_gic_data = {
+ .gicd_base = GICD_BASE,
+ .gicc_base = GICC_BASE,
+ .g0_interrupt_num = ARRAY_SIZE(g0_interrupt_array1),
+ .g0_interrupt_array = g0_interrupt_array1,
+};
+
+
+/*******************************************************************************
+ * 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)
+{
+ entry_point_info_t *next_image_info;
+
+ assert(sec_state_is_valid(type));
+ next_image_info = (type == NON_SECURE)
+ ? &bl33_image_ep_info : &bl32_image_ep_info;
+
+ if (next_image_info->pc)
+ return next_image_info;
+ else
+ return NULL;
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup common to Layerscape platforms.
+ * 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. BL2 has flushed this information to memory, so
+ * we are guaranteed to pick up good data.
+ ******************************************************************************/
+void ls_bl31_early_platform_setup(void *from_bl2,
+ void *plat_params_from_bl2)
+{
+ static console_ls_16550_t console;
+
+ /* Initialize the console to provide early debug support */
+ console_ls_16550_register(LS_TF_UART_BASE, LS_TF_UART_CLOCK,
+ LS_TF_UART_BAUDRATE, &console);
+#if RESET_TO_BL31
+ /* There are no parameters from BL2 if BL31 is a reset vector */
+ assert(from_bl2 == NULL);
+ assert(plat_params_from_bl2 == NULL);
+
+#ifdef BL32_BASE
+ /* Populate entry point information for BL32 */
+ 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 = ls_get_spsr_for_bl32_entry();
+#endif /* BL32_BASE */
+
+ /* Populate entry point information for BL33 */
+ 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 = ls_get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+#else /* RESET_TO_BL31 */
+
+ /*
+ * In debug builds, we pass a special value in 'plat_params_from_bl2'
+ * to verify platform parameters from BL2 to BL31.
+ * In release builds, it's not used.
+ */
+ assert(((unsigned long long)plat_params_from_bl2) ==
+ LS_BL31_PLAT_PARAM_VAL);
+
+ /*
+ * Check params passed from BL2 should not be NULL,
+ */
+ bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
+
+ assert(params_from_bl2 != NULL);
+ assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
+ assert(params_from_bl2->h.version >= VERSION_2);
+
+ bl_params_node_t *bl_params = params_from_bl2->head;
+
+ /*
+ * Copy BL33 and BL32 (if present), entry point information.
+ * They are stored in Secure RAM, in BL2's address space.
+ */
+ while (bl_params) {
+ if (bl_params->image_id == BL32_IMAGE_ID)
+ bl32_image_ep_info = *bl_params->ep_info;
+
+ if (bl_params->image_id == BL33_IMAGE_ID)
+ bl33_image_ep_info = *bl_params->ep_info;
+
+ bl_params = bl_params->next_params_info;
+ }
+
+ if (bl33_image_ep_info.pc == 0)
+ panic();
+
+#endif /* RESET_TO_BL31 */
+}
+
+/*******************************************************************************
+ * Perform any BL31 platform setup common to Layerscape platforms
+ ******************************************************************************/
+void ls_bl31_platform_setup(void)
+{
+ uint32_t gicc_base, gicd_base;
+
+ NOTICE(FIRMWARE_WELCOME_STR_LS1043_BL31);
+ /* Initialize the GIC driver, cpu and distributor interfaces */
+ get_gic_offset(&gicc_base, &gicd_base);
+ ls_gic_data.gicd_base = (uintptr_t)gicd_base;
+ ls_gic_data.gicc_base = (uintptr_t)gicc_base;
+ gicv2_driver_init(&ls_gic_data);
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+
+#if RESET_TO_BL31
+ /*
+ * Do initial security configuration to allow DRAM/device access
+ * (if earlier BL has not already done so).
+ */
+ plat_ls_security_setup();
+
+#endif /* RESET_TO_BL31 */
+
+ /* Enable and initialize the System level generic timer */
+ mmio_write_32(LS1043_SYS_CNTCTL_BASE + CNTCR_OFF,
+ CNTCR_FCREQ(0) | CNTCR_EN);
+
+ VERBOSE("Leave arm_bl31_platform_setup\n");
+}
+
+/*******************************************************************************
+ * Perform any BL31 platform runtime setup prior to BL31 exit common to Layerscape
+ * platforms
+ ******************************************************************************/
+void ls_bl31_plat_runtime_setup(void)
+{
+ static console_ls_16550_t console;
+
+ /* Initialize the runtime console */
+ console_ls_16550_register(PLAT_LS1043_UART_BASE, PLAT_LS1043_UART_CLOCK,
+ PLAT_LS1043_UART_BAUDRATE, &console);
+}
+
+void bl31_platform_setup(void)
+{
+ ls_bl31_platform_setup();
+}
+
+void bl31_plat_runtime_setup(void)
+{
+ ls_bl31_plat_runtime_setup();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup shared between
+ * Layerscape platforms. This only does basic initialization. Later
+ * architectural setup (bl31_arch_setup()) does not do anything platform
+ * specific.
+ ******************************************************************************/
+void ls_bl31_plat_arch_setup(void)
+{
+ ls_setup_page_tables(BL31_BASE,
+ BL31_END - BL31_BASE,
+ BL_CODE_BASE,
+ BL_CODE_END,
+ BL_RO_DATA_BASE,
+ BL_RO_DATA_END
+#if USE_COHERENT_MEM
+ , BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END
+#endif
+ );
+ enable_mmu_el3(0);
+}
+
+void bl31_plat_arch_setup(void)
+{
+ ls_bl31_plat_arch_setup();
+}
diff --git a/plat/layerscape/common/ls_common.c b/plat/layerscape/common/ls_common.c
new file mode 100644
index 0000000..abf6525
--- /dev/null
+++ b/plat/layerscape/common/ls_common.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <arch.h>
+#include <arch_helpers.h>
+#include <xlat_tables_v2.h>
+#include <assert.h>
+#include <debug.h>
+#include <mmio.h>
+#include "platform_def.h"
+
+const mmap_region_t *plat_ls_get_mmap(void);
+
+/*
+ * Table of memory regions for various BL stages to map using the MMU.
+ * This doesn't include Trusted SRAM as ls_setup_page_tables() already
+ * takes care of mapping it.
+ *
+ * The flash needs to be mapped as writable in order to erase the FIP's Table of
+ * Contents in case of unrecoverable error (see plat_error_handler()).
+ */
+#ifdef IMAGE_BL1
+const mmap_region_t plat_ls_mmap[] = {
+ LS_MAP_FLASH0_RW,
+ LS_MAP_NS_DRAM,
+ LS_MAP_CCSR,
+ {0}
+};
+#endif
+#ifdef IMAGE_BL2
+const mmap_region_t plat_ls_mmap[] = {
+ LS_MAP_FLASH0_RW,
+ LS_MAP_CCSR,
+ LS_MAP_NS_DRAM,
+ LS_MAP_TSP_SEC_MEM,
+ {0}
+};
+#endif
+#ifdef IMAGE_BL31
+const mmap_region_t plat_ls_mmap[] = {
+ LS_MAP_CCSR,
+ LS_MAP_FLASH0_RW,
+ LS_MAP_NS_DRAM,
+ LS_MAP_TSP_SEC_MEM,
+ {0}
+};
+#endif
+#ifdef IMAGE_BL32
+const mmap_region_t plat_ls_mmap[] = {
+ LS_MAP_CCSR,
+ LS_MAP_FLASH0_RW,
+ LS_MAP_TSP_SEC_MEM,
+ {0}
+};
+#endif
+/*
+ * Set up the page tables for the generic and platform-specific memory regions.
+ * The extents of the generic memory regions are specified by the function
+ * arguments and consist of:
+ * - Trusted SRAM seen by the BL image;
+ * - Code section;
+ * - Read-only data section;
+ * - Coherent memory region, if applicable.
+ */
+void ls_setup_page_tables(uintptr_t total_base,
+ size_t total_size,
+ uintptr_t code_start,
+ uintptr_t code_limit,
+ uintptr_t rodata_start,
+ uintptr_t rodata_limit
+#if USE_COHERENT_MEM
+ ,
+ uintptr_t coh_start,
+ uintptr_t coh_limit
+#endif
+ )
+{
+ /* Now (re-)map the platform-specific memory regions */
+ mmap_add(plat_ls_get_mmap());
+ /*
+ * Map the Trusted SRAM with appropriate memory attributes.
+ * Subsequent mappings will adjust the attributes for specific regions.
+ */
+ VERBOSE("Trusted SRAM seen by this BL image: %p - %p\n",
+ (void *) total_base, (void *) (total_base + total_size));
+ mmap_add_region(total_base, total_base,
+ total_size,
+ MT_MEMORY | MT_RW | MT_SECURE);
+
+ /* Re-map the code section */
+ VERBOSE("Code region: %p - %p\n",
+ (void *) code_start, (void *) code_limit);
+ mmap_add_region(code_start, code_start,
+ code_limit - code_start,
+ MT_CODE | MT_SECURE);
+
+ /* Re-map the read-only data section */
+ VERBOSE("Read-only data region: %p - %p\n",
+ (void *) rodata_start, (void *) rodata_limit);
+ mmap_add_region(rodata_start, rodata_start,
+ rodata_limit - rodata_start,
+ MT_RO_DATA | MT_SECURE);
+
+#if USE_COHERENT_MEM
+ /* Re-map the coherent memory region */
+ VERBOSE("Coherent region: %p - %p\n",
+ (void *) coh_start, (void *) coh_limit);
+ mmap_add_region(coh_start, coh_start,
+ coh_limit - coh_start,
+ MT_DEVICE | MT_RW | MT_SECURE);
+#endif
+
+ /* Create the page tables to reflect the above mappings */
+ init_xlat_tables();
+}
+
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#ifdef PRELOADED_BL33_BASE
+ return PRELOADED_BL33_BASE;
+#else
+ return LS_NS_DRAM_BASE;
+#endif
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL32 entry
+ ******************************************************************************/
+uint32_t ls_get_spsr_for_bl32_entry(void)
+{
+ /*
+ * The Secure Payload Dispatcher service is responsible for
+ * setting the SPSR prior to entry into the BL32 image.
+ */
+ return 0;
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+#ifndef AARCH32
+uint32_t ls_get_spsr_for_bl33_entry(void)
+{
+ unsigned int mode;
+ uint32_t spsr;
+
+ /* Figure out what mode we enter the non-secure world in */
+ mode = EL_IMPLEMENTED(2) ? MODE_EL2 : MODE_EL1;
+
+ /*
+ * TODO: Consider the possibility of specifying the SPSR in
+ * the FIP ToC and allowing the platform to have a say as
+ * well.
+ */
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+#else
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+uint32_t ls_get_spsr_for_bl33_entry(void)
+{
+ unsigned int hyp_status, mode, spsr;
+
+ hyp_status = GET_VIRT_EXT(read_id_pfr1());
+
+ mode = (hyp_status) ? MODE32_hyp : MODE32_svc;
+
+ /*
+ * TODO: Consider the possibility of specifying the SPSR in
+ * the FIP ToC and allowing the platform to have a say as
+ * well.
+ */
+ spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1,
+ SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+#endif /* AARCH32 */
+
+/*******************************************************************************
+ * Returns Layerscape platform specific memory map regions.
+ ******************************************************************************/
+const mmap_region_t *plat_ls_get_mmap(void)
+{
+ return plat_ls_mmap;
+}
+
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ unsigned int counter_base_frequency;
+
+ counter_base_frequency = COUNTER_FREQUENCY;
+
+ return counter_base_frequency;
+}
diff --git a/plat/layerscape/common/ls_common.mk b/plat/layerscape/common/ls_common.mk
new file mode 100644
index 0000000..1a80e9f
--- /dev/null
+++ b/plat/layerscape/common/ls_common.mk
@@ -0,0 +1,62 @@
+#
+# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+
+# Process LS1043_DISABLE_TRUSTED_WDOG flag
+# TODO:Temparally disabled it on development phase, not implemented yet
+LS1043_DISABLE_TRUSTED_WDOG := 1
+
+# On Layerscape platforms, separate the code and read-only data sections to allow
+# mapping the former as executable and the latter as execute-never.
+SEPARATE_CODE_AND_RODATA := 1
+
+# Enable new version of image loading on Layerscape platforms
+LOAD_IMAGE_V2 := 1
+
+# Use generic OID definition (tbbr_oid.h)
+USE_TBBR_DEFS := 1
+
+
+COLD_BOOT_SINGLE_CPU := 1
+
+PLAT_INCLUDES += -Iinclude/common/tbbr
+
+PLAT_BL_COMMON_SOURCES += plat/layerscape/common/${ARCH}/ls_helpers.S \
+ plat/layerscape/common/ls_common.c
+
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS}
+
+BL1_SOURCES += \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ plat/layerscape/common/ls_timer.c \
+ plat/layerscape/common/ls_bl1_setup.c \
+ plat/layerscape/common/ls_io_storage.c
+
+BL2_SOURCES += drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ plat/layerscape/common/ls_timer.c \
+ plat/layerscape/common/ls_bl2_setup.c \
+ plat/layerscape/common/ls_io_storage.c
+BL2_SOURCES += plat/layerscape/common/${ARCH}/ls_bl2_mem_params_desc.c
+BL2_SOURCES += plat/layerscape/common/ls_image_load.c \
+ common/desc_image_load.c
+
+BL31_SOURCES += plat/layerscape/common/ls_bl31_setup.c \
+ plat/layerscape/common/ls_timer.c \
+ plat/layerscape/common/ls_topology.c \
+ plat/layerscape/common/ns_access.c \
+ plat/common/plat_psci_common.c
+# Verify build config
+# -------------------
+
+ifneq (${LOAD_IMAGE_V2}, 1)
+ $(error Error: Layerscape needs LOAD_IMAGE_V2=1)
+endif
diff --git a/plat/layerscape/common/ls_image_load.c b/plat/layerscape/common/ls_image_load.c
new file mode 100644
index 0000000..909bec2
--- /dev/null
+++ b/plat/layerscape/common/ls_image_load.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <desc_image_load.h>
+#include "ls_def.h"
+
+/*******************************************************************************
+ * This function flushes the data structures so that they are visible
+ * in memory for the next BL image.
+ ******************************************************************************/
+void plat_flush_next_bl_params(void)
+{
+ flush_bl_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of loadable images.
+ ******************************************************************************/
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+ return get_bl_load_info_from_mem_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+ return get_next_bl_params_from_mem_params_desc();
+}
diff --git a/plat/layerscape/common/ls_io_storage.c b/plat/layerscape/common/ls_io_storage.c
new file mode 100644
index 0000000..7402366
--- /dev/null
+++ b/plat/layerscape/common/ls_io_storage.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <assert.h>
+#include <debug.h>
+#include <firmware_image_package.h>
+#include <io_driver.h>
+#include <io_fip.h>
+#include <io_memmap.h>
+#include <io_storage.h>
+#include "platform_def.h"
+
+/* IO devices */
+static const io_dev_connector_t *fip_dev_con;
+static uintptr_t fip_dev_handle;
+static const io_dev_connector_t *memmap_dev_con;
+static uintptr_t memmap_dev_handle;
+
+static const io_block_spec_t fip_block_spec = {
+ .offset = PLAT_LS_FIP_BASE,
+ .length = PLAT_LS_FIP_MAX_SIZE
+};
+
+static const io_uuid_spec_t bl2_uuid_spec = {
+ .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
+};
+
+static const io_uuid_spec_t bl31_uuid_spec = {
+ .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
+};
+
+static const io_uuid_spec_t bl32_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32,
+};
+
+static const io_uuid_spec_t bl33_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
+};
+
+static int open_fip(const uintptr_t spec);
+static int open_memmap(const uintptr_t spec);
+
+struct plat_io_policy {
+ uintptr_t *dev_handle;
+ uintptr_t image_spec;
+ int (*check)(const uintptr_t spec);
+};
+
+static const struct plat_io_policy policies[] = {
+ [FIP_IMAGE_ID] = {
+ &memmap_dev_handle,
+ (uintptr_t)&fip_block_spec,
+ open_memmap
+ },
+ [BL2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl2_uuid_spec,
+ open_fip
+ },
+ [BL31_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl31_uuid_spec,
+ open_fip
+ },
+ [BL32_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_uuid_spec,
+ open_fip
+ },
+ [BL33_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl33_uuid_spec,
+ open_fip
+ },
+};
+
+static int open_fip(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ /* See if a Firmware Image Package is available */
+ result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
+ if (result == 0) {
+ result = io_open(fip_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using FIP\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+
+static int open_memmap(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
+ if (result == 0) {
+ result = io_open(memmap_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using Memmap\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+
+void ls_io_setup(void)
+{
+ int io_result;
+
+ io_result = register_io_dev_fip(&fip_dev_con);
+ assert(io_result == 0);
+
+ io_result = register_io_dev_memmap(&memmap_dev_con);
+ assert(io_result == 0);
+
+ /* Open connections to devices and cache the handles */
+ io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
+ &fip_dev_handle);
+ assert(io_result == 0);
+
+ io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
+ &memmap_dev_handle);
+ assert(io_result == 0);
+
+ /* Ignore improbable errors in release builds */
+ (void)io_result;
+}
+
+void plat_ls_io_setup(void)
+{
+ ls_io_setup();
+}
+
+int plat_ls_get_alt_image_source(
+ unsigned int image_id __unused,
+ uintptr_t *dev_handle __unused,
+ uintptr_t *image_spec __unused)
+{
+ /* By default do not try an alternative */
+ return -ENOENT;
+}
+
+/*
+ * Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy.
+ */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ int result;
+ const struct plat_io_policy *policy;
+
+ assert(image_id < ARRAY_SIZE(policies));
+
+ policy = &policies[image_id];
+ result = policy->check(policy->image_spec);
+ if (result == 0) {
+ *image_spec = policy->image_spec;
+ *dev_handle = *(policy->dev_handle);
+ } else {
+ VERBOSE("Trying alternative IO\n");
+ result = plat_ls_get_alt_image_source(image_id, dev_handle,
+ image_spec);
+ }
+
+ return result;
+}
diff --git a/plat/layerscape/common/ls_timer.c b/plat/layerscape/common/ls_timer.c
new file mode 100644
index 0000000..25b5e63
--- /dev/null
+++ b/plat/layerscape/common/ls_timer.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <mmio.h>
+#include <delay_timer.h>
+#include <arch_helpers.h>
+
+#define TIMER_BASE_ADDR 0x02B00000
+
+uint64_t ls_get_timer(uint64_t start)
+{
+ return read_cntpct_el0() * 1000 / read_cntfrq_el0() - start;
+}
+
+static uint32_t ls_timeus_get_value(void)
+{
+ /*
+ * Generic delay timer implementation expects the timer to be a down
+ * counter. We apply bitwise NOT operator to the tick values returned
+ * by read_cntpct_el0() to simulate the down counter. The value is
+ * clipped from 64 to 32 bits.
+ */
+ return (uint32_t)(~read_cntpct_el0());
+}
+
+static const timer_ops_t ls_timer_ops = {
+ .get_timer_value = ls_timeus_get_value,
+ .clk_mult = 1,
+ .clk_div = 25,
+};
+
+
+/*
+ * Initialise the nxp layerscape on-chip free rolling us counter as the delay
+ * timer.
+ */
+void ls_delay_timer_init(void)
+{
+ uintptr_t cntcr = TIMER_BASE_ADDR;
+
+ mmio_write_32(cntcr, 0x1);
+
+ timer_init(&ls_timer_ops);
+}
diff --git a/plat/layerscape/common/ls_topology.c b/plat/layerscape/common/ls_topology.c
new file mode 100644
index 0000000..5b76087
--- /dev/null
+++ b/plat/layerscape/common/ls_topology.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "plat_ls.h"
+
+/*******************************************************************************
+ * This function validates an MPIDR by checking whether it falls within the
+ * acceptable bounds. An error code (-1) is returned if an incorrect mpidr
+ * is passed.
+ ******************************************************************************/
+int ls_check_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+ uint64_t valid_mask;
+
+ valid_mask = ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK);
+ cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+ if (mpidr & valid_mask)
+ return -1;
+
+ if (cluster_id >= PLAT_LS_CLUSTER_COUNT)
+ return -1;
+
+ /*
+ * Validate cpu_id by checking whether it represents a CPU in
+ * one of the two clusters present on the platform.
+ */
+ if (cpu_id >= plat_ls_get_cluster_core_count(mpidr))
+ return -1;
+
+
+ return 0;
+}
diff --git a/plat/layerscape/common/ls_tzc380.c b/plat/layerscape/common/ls_tzc380.c
new file mode 100644
index 0000000..b9f32ac
--- /dev/null
+++ b/plat/layerscape/common/ls_tzc380.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <mmio.h>
+#include <endian.h>
+#include "platform_def.h"
+#include "soc_tzasc.h"
+
+int tzc380_set_region(unsigned int tzasc_base, unsigned int region_id,
+ unsigned int enabled, unsigned int low_addr,
+ unsigned int high_addr, unsigned int size,
+ unsigned int security, unsigned int subreg_disable_mask)
+{
+ unsigned int reg;
+ unsigned int reg_base;
+ unsigned int attr_value;
+
+ reg_base = (tzasc_base + TZASC_REGIONS_REG + (region_id << 4));
+
+ if (region_id == 0) {
+ reg = (reg_base + TZASC_REGION_ATTR_OFFSET);
+ mmio_write_32((uintptr_t)reg, ((security & 0xF) << 28));
+ } else {
+ reg = reg_base + TZASC_REGION_LOWADDR_OFFSET;
+ mmio_write_32((uintptr_t)reg,
+ (low_addr & TZASC_REGION_LOWADDR_MASK));
+
+ reg = reg_base + TZASC_REGION_HIGHADDR_OFFSET;
+ mmio_write_32((uintptr_t)reg, high_addr);
+
+ reg = reg_base + TZASC_REGION_ATTR_OFFSET;
+ attr_value = ((security & 0xF) << 28) |
+ ((subreg_disable_mask & 0xFF) << 8) |
+ ((size & 0x3F) << 1) | (enabled & 0x1);
+ mmio_write_32((uintptr_t)reg, attr_value);
+
+ }
+ return 0;
+}
+
+int tzc380_setup(void)
+{
+ int reg_id = 0;
+
+ INFO("Configuring TZASC-380\n");
+
+ /*
+ * Configure CCI control override register to terminate all barrier
+ * transactions
+ */
+ mmio_write_32(PLAT_LS1043_CCI_BASE, CCI_TERMINATE_BARRIER_TX);
+
+ /* Configure CSU secure access register to disable TZASC bypass mux */
+ mmio_write_32((uintptr_t)(CONFIG_SYS_FSL_CSU_ADDR +
+ CSU_SEC_ACCESS_REG_OFFSET),
+ bswap32(TZASC_BYPASS_MUX_DISABLE));
+
+ for (reg_id = 0; reg_id < MAX_NUM_TZC_REGION; reg_id++) {
+ tzc380_set_region(CONFIG_SYS_FSL_TZASC_ADDR,
+ reg_id,
+ tzc380_reg_list[reg_id].enabled,
+ tzc380_reg_list[reg_id].low_addr,
+ tzc380_reg_list[reg_id].high_addr,
+ tzc380_reg_list[reg_id].size,
+ tzc380_reg_list[reg_id].secure,
+ tzc380_reg_list[reg_id].sub_mask);
+ }
+
+ return 0;
+}
diff --git a/plat/layerscape/common/ns_access.c b/plat/layerscape/common/ns_access.c
new file mode 100644
index 0000000..e1daaed
--- /dev/null
+++ b/plat/layerscape/common/ns_access.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <mmio.h>
+#include <endian.h>
+#include <debug.h>
+#include "ns_access.h"
+#include "platform_def.h"
+
+static void enable_devices_ns_access(struct csu_ns_dev *ns_dev, uint32_t num)
+{
+ uint32_t *base = (uint32_t *)CONFIG_SYS_FSL_CSU_ADDR;
+ uint32_t *reg;
+ uint32_t val;
+ int i;
+
+ for (i = 0; i < num; i++) {
+ reg = base + ns_dev[i].ind / 2;
+ val = be32toh(mmio_read_32((uintptr_t)reg));
+ if (ns_dev[i].ind % 2 == 0) {
+ val &= 0x0000ffff;
+ val |= ns_dev[i].val << 16;
+ } else {
+ val &= 0xffff0000;
+ val |= ns_dev[i].val;
+ }
+ mmio_write_32((uintptr_t)reg, htobe32(val));
+ }
+}
+
+void enable_layerscape_ns_access(void)
+{
+ enable_devices_ns_access(ns_dev, ARRAY_SIZE(ns_dev));
+}
diff --git a/plat/layerscape/common/tsp/ls_tsp.mk b/plat/layerscape/common/tsp/ls_tsp.mk
new file mode 100644
index 0000000..7cb9781
--- /dev/null
+++ b/plat/layerscape/common/tsp/ls_tsp.mk
@@ -0,0 +1,10 @@
+#
+# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# TSP source files common to ARM standard platforms
+BL32_SOURCES += plat/layerscape/common/ls_topology.c \
+ plat/layerscape/common/tsp/ls_tsp_setup.c \
+ plat/common/aarch64/platform_mp_stack.S
diff --git a/plat/layerscape/common/tsp/ls_tsp_setup.c b/plat/layerscape/common/tsp/ls_tsp_setup.c
new file mode 100644
index 0000000..82ac965
--- /dev/null
+++ b/plat/layerscape/common/tsp/ls_tsp_setup.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <gicv2.h>
+#include <debug.h>
+#include "ls_16550.h"
+#include "plat_ls.h"
+#include "soc.h"
+
+#define BL32_END (unsigned long)(&__BL32_END__)
+
+const unsigned int g0_interrupt_array1[] = {
+ 9
+};
+
+gicv2_driver_data_t ls_gic_data = {
+ .gicd_base = GICD_BASE,
+ .gicc_base = GICC_BASE,
+ .g0_interrupt_num = ARRAY_SIZE(g0_interrupt_array1),
+ .g0_interrupt_array = g0_interrupt_array1,
+};
+
+/*******************************************************************************
+ * Initialize the UART
+ ******************************************************************************/
+void ls_tsp_early_platform_setup(void)
+{
+ static console_ls_16550_t console;
+ /*
+ * Initialize a different console than already in use to display
+ * messages from TSP
+ */
+ console_ls_16550_register(PLAT_LS1043_UART2_BASE, PLAT_LS1043_UART_CLOCK,
+ PLAT_LS1043_UART_BAUDRATE, &console);
+ NOTICE(FIRMWARE_WELCOME_STR_LS1043_BL32);
+}
+
+/*******************************************************************************
+ * Perform platform specific setup placeholder
+ ******************************************************************************/
+void tsp_platform_setup(void)
+{
+ uint32_t gicc_base, gicd_base;
+
+ /* Initialize the GIC driver, cpu and distributor interfaces */
+ get_gic_offset(&gicc_base, &gicd_base);
+ ls_gic_data.gicd_base = (uintptr_t)gicd_base;
+ ls_gic_data.gicc_base = (uintptr_t)gicc_base;
+ gicv2_driver_init(&ls_gic_data);
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the MMU
+ ******************************************************************************/
+void tsp_plat_arch_setup(void)
+{
+ ls_setup_page_tables(BL32_BASE,
+ (BL32_END - BL32_BASE),
+ BL_CODE_BASE,
+ BL_CODE_END,
+ BL_RO_DATA_BASE,
+ BL_RO_DATA_END
+#if USE_COHERENT_MEM
+ , BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END
+#endif
+ );
+ enable_mmu_el1(0);
+}
diff --git a/plat/layerscape/common/tsp/platform_tsp.h b/plat/layerscape/common/tsp/platform_tsp.h
new file mode 100644
index 0000000..b1c96cb
--- /dev/null
+++ b/plat/layerscape/common/tsp/platform_tsp.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLATFORM_TSP_H__
+#define __PLATFORM_TSP_H__
+
+/*******************************************************************************
+ * Mandatory TSP functions (only if platform contains a TSP)
+ ******************************************************************************/
+void tsp_early_platform_setup(void);
+void tsp_plat_arch_setup(void);
+void tsp_platform_setup(void);
+
+#endif /* __PLATFORM_TSP_H__ */
diff --git a/plat/mediatek/common/custom/oem_svc.c b/plat/mediatek/common/custom/oem_svc.c
index 49e7571..c396e2d 100644
--- a/plat/mediatek/common/custom/oem_svc.c
+++ b/plat/mediatek/common/custom/oem_svc.c
@@ -32,14 +32,14 @@
/*******************************************************************************
* OEM top level handler for servicing SMCs.
******************************************************************************/
-uint64_t oem_smc_handler(uint32_t smc_fid,
- uint64_t x1,
- uint64_t x2,
- uint64_t x3,
- uint64_t x4,
+uintptr_t oem_smc_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
void *cookie,
void *handle,
- uint64_t flags)
+ u_register_t flags)
{
WARN("Unimplemented OEM Call: 0x%x\n", smc_fid);
SMC_RET1(handle, SMC_UNK);
@@ -49,14 +49,14 @@
* Top-level OEM Service SMC handler. This handler will in turn dispatch
* calls to related SMC handler
*/
-uint64_t oem_svc_smc_handler(uint32_t smc_fid,
- uint64_t x1,
- uint64_t x2,
- uint64_t x3,
- uint64_t x4,
+uintptr_t oem_svc_smc_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
void *cookie,
void *handle,
- uint64_t flags)
+ u_register_t flags)
{
/*
* Dispatch OEM calls to OEM Common handler and return its return value
diff --git a/plat/mediatek/common/mtk_plat_common.c b/plat/mediatek/common/mtk_plat_common.c
index 6a13192..a15131d 100644
--- a/plat/mediatek/common/mtk_plat_common.c
+++ b/plat/mediatek/common/mtk_plat_common.c
@@ -19,10 +19,10 @@
struct atf_arg_t gteearg;
void clean_top_32b_of_param(uint32_t smc_fid,
- uint64_t *px1,
- uint64_t *px2,
- uint64_t *px3,
- uint64_t *px4)
+ u_register_t *px1,
+ u_register_t *px2,
+ u_register_t *px3,
+ u_register_t *px4)
{
/* if parameters from SMC32. Clean top 32 bits */
if (0 == (smc_fid & SMC_AARCH64_BIT)) {
diff --git a/plat/mediatek/common/mtk_plat_common.h b/plat/mediatek/common/mtk_plat_common.h
index 7513bc7..501c339 100644
--- a/plat/mediatek/common/mtk_plat_common.h
+++ b/plat/mediatek/common/mtk_plat_common.h
@@ -48,10 +48,10 @@
/* Declarations for mtk_plat_common.c */
uint32_t plat_get_spsr_for_bl32_entry(void);
uint32_t plat_get_spsr_for_bl33_entry(void);
-void clean_top_32b_of_param(uint32_t smc_fid, uint64_t *x1,
- uint64_t *x2,
- uint64_t *x3,
- uint64_t *x4);
+void clean_top_32b_of_param(uint32_t smc_fid, u_register_t *x1,
+ u_register_t *x2,
+ u_register_t *x3,
+ u_register_t *x4);
void bl31_prepare_kernel_entry(uint64_t k32_64);
void enable_ns_access_to_cpuectlr(void);
void boot_to_kernel(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4);
diff --git a/plat/mediatek/common/mtk_sip_svc.c b/plat/mediatek/common/mtk_sip_svc.c
index 869a959..ea8cea0 100644
--- a/plat/mediatek/common/mtk_sip_svc.c
+++ b/plat/mediatek/common/mtk_sip_svc.c
@@ -19,14 +19,14 @@
0x8f, 0x95, 0x05, 0x00, 0x0f, 0x3d);
#pragma weak mediatek_plat_sip_handler
-uint64_t mediatek_plat_sip_handler(uint32_t smc_fid,
- uint64_t x1,
- uint64_t x2,
- uint64_t x3,
- uint64_t x4,
+uintptr_t mediatek_plat_sip_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
void *cookie,
void *handle,
- uint64_t flags)
+ u_register_t flags)
{
ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
SMC_RET1(handle, SMC_UNK);
@@ -34,14 +34,14 @@
/*
* This function handles Mediatek defined SiP Calls */
-uint64_t mediatek_sip_handler(uint32_t smc_fid,
- uint64_t x1,
- uint64_t x2,
- uint64_t x3,
- uint64_t x4,
+uintptr_t mediatek_sip_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
void *cookie,
void *handle,
- uint64_t flags)
+ u_register_t flags)
{
uint32_t ns;
@@ -85,14 +85,14 @@
/*
* This function is responsible for handling all SiP calls from the NS world
*/
-uint64_t sip_smc_handler(uint32_t smc_fid,
- uint64_t x1,
- uint64_t x2,
- uint64_t x3,
- uint64_t x4,
+uintptr_t sip_smc_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
void *cookie,
void *handle,
- uint64_t flags)
+ u_register_t flags)
{
switch (smc_fid) {
case SIP_SVC_CALL_COUNT:
diff --git a/plat/nvidia/tegra/common/tegra_sip_calls.c b/plat/nvidia/tegra/common/tegra_sip_calls.c
index d96ce7a..a818453 100644
--- a/plat/nvidia/tegra/common/tegra_sip_calls.c
+++ b/plat/nvidia/tegra/common/tegra_sip_calls.c
@@ -49,14 +49,14 @@
/*******************************************************************************
* This function is responsible for handling all SiP calls
******************************************************************************/
-uint64_t tegra_sip_handler(uint32_t smc_fid,
- uint64_t x1,
- uint64_t x2,
- uint64_t x3,
- uint64_t x4,
- void *cookie,
- void *handle,
- uint64_t flags)
+uintptr_t tegra_sip_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
{
uint32_t regval;
int err;
diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c b/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c
index 5435ce6..1353b6a 100644
--- a/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c
+++ b/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c
@@ -382,7 +382,7 @@
break;
default:
- ERROR("unknown MCE command (%lu)\n", cmd);
+ ERROR("unknown MCE command (%llu)\n", cmd);
ret = EINVAL;
break;
}
diff --git a/plat/rockchip/common/params_setup.c b/plat/rockchip/common/params_setup.c
index 65afe87..3dac013 100644
--- a/plat/rockchip/common/params_setup.c
+++ b/plat/rockchip/common/params_setup.c
@@ -92,7 +92,7 @@
break;
#endif
default:
- ERROR("not expected type found %ld\n",
+ ERROR("not expected type found %lld\n",
bl2_param->type);
break;
}
diff --git a/plat/rockchip/common/rockchip_sip_svc.c b/plat/rockchip/common/rockchip_sip_svc.c
index eca4f99..2480599 100644
--- a/plat/rockchip/common/rockchip_sip_svc.c
+++ b/plat/rockchip/common/rockchip_sip_svc.c
@@ -18,14 +18,14 @@
0x8f, 0x88, 0xee, 0x74, 0x7b, 0x72);
#pragma weak rockchip_plat_sip_handler
-uint64_t rockchip_plat_sip_handler(uint32_t smc_fid,
- uint64_t x1,
- uint64_t x2,
- uint64_t x3,
- uint64_t x4,
- void *cookie,
- void *handle,
- uint64_t flags)
+uintptr_t rockchip_plat_sip_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
{
ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
SMC_RET1(handle, SMC_UNK);
@@ -34,14 +34,14 @@
/*
* This function is responsible for handling all SiP calls from the NS world
*/
-uint64_t sip_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)
+uintptr_t sip_smc_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
{
uint32_t ns;
diff --git a/plat/rockchip/rk3368/plat_sip_calls.c b/plat/rockchip/rk3368/plat_sip_calls.c
index 03fee88..c0f43db 100644
--- a/plat/rockchip/rk3368/plat_sip_calls.c
+++ b/plat/rockchip/rk3368/plat_sip_calls.c
@@ -10,14 +10,14 @@
#include <rockchip_sip_svc.h>
#include <runtime_svc.h>
-uint64_t rockchip_plat_sip_handler(uint32_t smc_fid,
- uint64_t x1,
- uint64_t x2,
- uint64_t x3,
- uint64_t x4,
+uintptr_t rockchip_plat_sip_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
void *cookie,
void *handle,
- uint64_t flags)
+ u_register_t flags)
{
ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
SMC_RET1(handle, SMC_UNK);
diff --git a/plat/rockchip/rk3399/drivers/dram/dfs.c b/plat/rockchip/rk3399/drivers/dram/dfs.c
index 70d9423..e6d39a1 100644
--- a/plat/rockchip/rk3399/drivers/dram/dfs.c
+++ b/plat/rockchip/rk3399/drivers/dram/dfs.c
@@ -1964,9 +1964,6 @@
static void m0_configure_ddr(struct pll_div pll_div, uint32_t ddr_index)
{
- /* set PARAM to M0_FUNC_DRAM */
- mmio_write_32(M0_PARAM_ADDR + PARAM_M0_FUNC, M0_FUNC_DRAM);
-
mmio_write_32(M0_PARAM_ADDR + PARAM_DPLL_CON0, FBDIV(pll_div.fbdiv));
mmio_write_32(M0_PARAM_ADDR + PARAM_DPLL_CON1,
POSTDIV2(pll_div.postdiv2) | POSTDIV1(pll_div.postdiv1) |
@@ -1976,6 +1973,7 @@
mmio_write_32(M0_PARAM_ADDR + PARAM_FREQ_SELECT, ddr_index << 4);
dmbst();
+ m0_configure_execute_addr(M0_BINCODE_BASE);
}
static uint32_t prepare_ddr_timing(uint32_t mhz)
diff --git a/plat/rockchip/rk3399/drivers/dram/suspend.c b/plat/rockchip/rk3399/drivers/dram/suspend.c
index f66150a..dd97581 100644
--- a/plat/rockchip/rk3399/drivers/dram/suspend.c
+++ b/plat/rockchip/rk3399/drivers/dram/suspend.c
@@ -9,6 +9,8 @@
#include <dram.h>
#include <plat_private.h>
#include <platform_def.h>
+#include <pmu.h>
+#include <pmu_bits.h>
#include <pmu_regs.h>
#include <rk3399_def.h>
#include <secure.h>
@@ -85,10 +87,11 @@
static __pmusramfunc void sram_udelay(uint32_t usec)
{
- uint32_t start, cnt, delta, delta_us;
+ uint32_t start, cnt, delta, total_ticks;
/* counter is decreasing */
start = sram_get_timer_value();
+ total_ticks = usec * SYS_COUNTER_FREQ_IN_MHZ;
do {
cnt = sram_get_timer_value();
if (cnt > start) {
@@ -96,8 +99,7 @@
delta += start;
} else
delta = start - cnt;
- delta_us = (delta * SYS_COUNTER_FREQ_IN_MHZ);
- } while (delta_us < usec);
+ } while (delta <= total_ticks);
}
static __pmusramfunc void configure_sgrf(void)
@@ -656,6 +658,30 @@
;
}
+__pmusramfunc static void pmusram_enable_watchdog(void)
+{
+ /* Make the watchdog use the first global reset. */
+ mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, 1 << 1);
+
+ /*
+ * This gives the system ~8 seconds before reset. The pclk for the
+ * watchdog is 4MHz on reset. The value of 0x9 in WDT_TORR means that
+ * the watchdog will wait for 0x1ffffff cycles before resetting.
+ */
+ mmio_write_32(WDT0_BASE + 4, 0x9);
+
+ /* Enable the watchdog */
+ mmio_setbits_32(WDT0_BASE, 0x1);
+
+ /* Magic reset the watchdog timer value for WDT_CRR. */
+ mmio_write_32(WDT0_BASE + 0xc, 0x76);
+
+ secure_watchdog_ungate();
+
+ /* The watchdog is in PD_ALIVE, so deidle it. */
+ mmio_clrbits_32(PMU_BASE + PMU_BUS_CLR, PMU_CLR_ALIVE);
+}
+
void dmc_suspend(void)
{
struct rk3399_sdram_params *sdram_params = &sdram_config;
@@ -726,6 +752,9 @@
uint32_t channel_mask = 0;
uint32_t channel;
+ pmusram_enable_watchdog();
+ pmu_sgrf_rst_hld_release();
+ restore_pmu_rsthold();
sram_secure_timer_init();
/*
diff --git a/plat/rockchip/rk3399/drivers/m0/Makefile b/plat/rockchip/rk3399/drivers/m0/Makefile
index f6bdbf2..79e09f0 100644
--- a/plat/rockchip/rk3399/drivers/m0/Makefile
+++ b/plat/rockchip/rk3399/drivers/m0/Makefile
@@ -12,6 +12,7 @@
# Build platform
PLAT_M0 ?= rk3399m0
+PLAT_M0_PMU ?= rk3399m0pmu
ifeq (${V},0)
Q=@
@@ -26,11 +27,10 @@
-I../../include/shared/
# NOTE: Add C source files here
-C_SOURCES := src/startup.c \
- src/main.c \
- src/suspend.c \
- src/dram.c \
+C_SOURCES_COMMON := src/startup.c
+C_SOURCES := src/dram.c \
src/stopwatch.c
+C_SOURCES_PMU := src/suspend.c
# Flags definition
COMMON_FLAGS := -g -mcpu=$(ARCH) -mthumb -Wall -O3 -nostdlib -mfloat-abi=soft
@@ -54,12 +54,19 @@
$(notdir $(patsubst %.S,%.o,$(filter %.S,$(1))))
endef
+SOURCES_COMMON := $(C_SOURCES_COMMON)
SOURCES := $(C_SOURCES)
+SOURCES_PMU := $(C_SOURCES_PMU)
+OBJS_COMMON := $(addprefix $(BUILD)/,$(call SOURCES_TO_OBJS,$(SOURCES_COMMON)))
OBJS := $(addprefix $(BUILD)/,$(call SOURCES_TO_OBJS,$(SOURCES)))
+OBJS_PMU := $(addprefix $(BUILD)/,$(call SOURCES_TO_OBJS,$(SOURCES_PMU)))
LINKERFILE := $(BUILD)/$(PLAT_M0).ld
MAPFILE := $(BUILD)/$(PLAT_M0).map
+MAPFILE_PMU := $(BUILD)/$(PLAT_M0_PMU).map
ELF := $(BUILD)/$(PLAT_M0).elf
+ELF_PMU := $(BUILD)/$(PLAT_M0_PMU).elf
BIN := $(BUILD)/$(PLAT_M0).bin
+BIN_PMU := $(BUILD)/$(PLAT_M0_PMU).bin
LINKERFILE_SRC := src/$(PLAT_M0).ld.S
# Function definition related compilation
@@ -92,18 +99,27 @@
$(and $(REMAIN),$(error Unexpected source files present: $(REMAIN)))
endef
-.DEFAULT_GOAL := $(BIN)
+.PHONY: all
+all: $(BIN) $(BIN_PMU)
+
+.DEFAULT_GOAL := all
$(LINKERFILE): $(LINKERFILE_SRC)
$(CC) $(COMMON_FLAGS) $(INCLUDES) -P -E -D__LINKER__ -MMD -MF $@.d -MT $@ -o $@ $<
-include $(LINKERFILE).d
-$(ELF) : $(OBJS) $(LINKERFILE)
+$(ELF) : $(OBJS) $(OBJS_COMMON) $(LINKERFILE)
@echo " LD $@"
- $(Q)$(CC) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE) -Wl,-T$(LINKERFILE) $(OBJS)
+ $(Q)$(CC) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE) -Wl,-T$(LINKERFILE) $(OBJS) $(OBJS_COMMON)
-$(BIN) : $(ELF)
+%.bin : %.elf
@echo " BIN $@"
$(Q)$(OC) -O binary $< $@
+$(ELF_PMU) : $(OBJS_COMMON) $(OBJS_PMU) $(LINKERFILE)
+ @echo " LD $@"
+ $(Q)$(CC) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE_PMU) -Wl,-T$(LINKERFILE) $(OBJS_PMU) $(OBJS_COMMON)
+
+$(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES_COMMON),$(1)))
$(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES),$(1)))
+$(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES_PMU),$(1)))
diff --git a/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h b/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h
index 472cbc9..176af3a 100644
--- a/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h
+++ b/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h
@@ -25,8 +25,6 @@
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
-void handle_suspend(void);
-void handle_dram(void);
void stopwatch_init_usecs_expire(unsigned int usecs);
int stopwatch_expired(void);
void stopwatch_reset(void);
diff --git a/plat/rockchip/rk3399/drivers/m0/src/dram.c b/plat/rockchip/rk3399/drivers/m0/src/dram.c
index c6a9259..b939a96 100644
--- a/plat/rockchip/rk3399/drivers/m0/src/dram.c
+++ b/plat/rockchip/rk3399/drivers/m0/src/dram.c
@@ -55,7 +55,7 @@
mmio_write_32(CRU_BASE + CRU_DPLL_CON3, PLL_MODE(PLL_NORMAL_MODE));
}
-void handle_dram(void)
+__attribute__((noreturn)) void main(void)
{
mmio_setbits_32(PHY_REG(0, 927), (1 << 22));
mmio_setbits_32(PHY_REG(1, 927), (1 << 22));
@@ -76,4 +76,9 @@
deidle_port();
mmio_clrbits_32(PHY_REG(0, 927), (1 << 22));
mmio_clrbits_32(PHY_REG(1, 927), (1 << 22));
+
+ mmio_write_32(PARAM_ADDR + PARAM_M0_DONE, M0_DONE_FLAG);
+
+ for (;;)
+ __asm__ volatile ("wfi");
}
diff --git a/plat/rockchip/rk3399/drivers/m0/src/main.c b/plat/rockchip/rk3399/drivers/m0/src/main.c
deleted file mode 100644
index 0ed818d..0000000
--- a/plat/rockchip/rk3399/drivers/m0/src/main.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <m0_param.h>
-#include "rk3399_mcu.h"
-
-__attribute__((noreturn)) void main(void)
-{
- switch (mmio_read_32(PARAM_ADDR + PARAM_M0_FUNC)) {
- case M0_FUNC_SUSPEND:
- handle_suspend();
- break;
- case M0_FUNC_DRAM:
- handle_dram();
- break;
- default:
- break;
- }
-
- mmio_write_32(PARAM_ADDR + PARAM_M0_DONE, M0_DONE_FLAG);
-
- for (;;)
- __asm__ volatile ("wfi");
-}
diff --git a/plat/rockchip/rk3399/drivers/m0/src/startup.c b/plat/rockchip/rk3399/drivers/m0/src/startup.c
index 68f5b2d..dba0313 100644
--- a/plat/rockchip/rk3399/drivers/m0/src/startup.c
+++ b/plat/rockchip/rk3399/drivers/m0/src/startup.c
@@ -7,7 +7,7 @@
#include "rk3399_mcu.h"
/* Stack configuration */
-#define STACK_SIZE 0x00000100
+#define STACK_SIZE 0x00000040
__attribute__ ((section(".co_stack")))
unsigned long pstack[STACK_SIZE];
diff --git a/plat/rockchip/rk3399/drivers/m0/src/suspend.c b/plat/rockchip/rk3399/drivers/m0/src/suspend.c
index af29a11..39dfd11 100644
--- a/plat/rockchip/rk3399/drivers/m0/src/suspend.c
+++ b/plat/rockchip/rk3399/drivers/m0/src/suspend.c
@@ -11,18 +11,52 @@
#define SCR_SLEEPDEEP_SHIFT (1 << 2)
-void handle_suspend(void)
+__attribute__((noreturn)) void main(void)
{
unsigned int status_value;
+ /*
+ * PMU sometimes doesn't clear power mode bit as it's supposed to due
+ * to a hardware bug. Make the M0 clear it manually to be sure,
+ * otherwise interrupts some cases with concurrent wake interrupts
+ * we stay asleep forever.
+ */
while (1) {
status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
if (status_value) {
mmio_clrbits_32(PMU_BASE + PMU_PWRMODE_CON, 0x01);
- return;
+ break;
}
}
- /* m0 enter deep sleep mode */
- mmio_setbits_32(M0_SCR, SCR_SLEEPDEEP_SHIFT);
+ /*
+ * FSM power secquence is .. -> ST_INPUT_CLAMP(step.17) -> .. ->
+ * ST_WAKEUP_RESET -> ST_EXT_PWRUP-> ST_RELEASE_CLAMP ->
+ * ST_24M_OSC_EN -> .. -> ST_WAKEUP_RESET_CLR(step.26) -> ..,
+ * INPUT_CLAMP and WAKEUP_RESET will hold the SOC not affect by
+ * power or other single glitch, but WAKEUP_RESET need work with 24MHz,
+ * so between RELEASE_CLAMP and 24M_OSC_EN, there have a chance
+ * that glitch will affect SOC, and mess up SOC status, so we
+ * addressmap_shared software clamp between ST_INPUT_CLAMP and
+ * ST_WAKEUP_RESET_CLR to avoid this happen.
+ */
+ while (1) {
+ status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
+ if (status_value >= 17) {
+ mmio_setbits_32(PMU_BASE + PMU_SFT_CON, 0x02);
+ break;
+ }
+
+ }
+
+ while (1) {
+ status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
+ if (status_value >= 26) {
+ mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, 0x02);
+ break;
+ }
+ }
+
+ for (;;)
+ __asm__ volatile ("wfi");
}
diff --git a/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c b/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c
index 61849e5..3f258b7 100644
--- a/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c
+++ b/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c
@@ -21,14 +21,6 @@
mmio_write_32(SGRF_BASE + SGRF_PMU_CON(0), WMSK_BIT(7));
mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6), WMSK_BIT(12));
- /* set the execute address for M0 */
- mmio_write_32(SGRF_BASE + SGRF_PMU_CON(3),
- BITS_WITH_WMASK((M0_BINCODE_BASE >> 12) & 0xffff,
- 0xffff, 0));
- mmio_write_32(SGRF_BASE + SGRF_PMU_CON(7),
- BITS_WITH_WMASK((M0_BINCODE_BASE >> 28) & 0xf,
- 0xf, 0));
-
/* document is wrong, PMU_CRU_GATEDIS_CON0 do not need set MASK BIT */
mmio_setbits_32(PMUCRU_BASE + PMUCRU_GATEDIS_CON0, 0x02);
@@ -46,6 +38,17 @@
mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2, WMSK_BIT(5));
}
+void m0_configure_execute_addr(uintptr_t addr)
+{
+ /* set the execute address for M0 */
+ mmio_write_32(SGRF_BASE + SGRF_PMU_CON(3),
+ BITS_WITH_WMASK((addr >> 12) & 0xffff,
+ 0xffff, 0));
+ mmio_write_32(SGRF_BASE + SGRF_PMU_CON(7),
+ BITS_WITH_WMASK((addr >> 28) & 0xf,
+ 0xf, 0));
+}
+
void m0_start(void)
{
/* enable clocks for M0 */
diff --git a/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h b/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h
index b313ec6..cb323c4 100644
--- a/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h
+++ b/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h
@@ -11,13 +11,18 @@
#define M0_BINCODE_BASE ((uintptr_t)rk3399m0_bin)
#define M0_PARAM_ADDR (M0_BINCODE_BASE + PARAM_ADDR)
+#define M0PMU_BINCODE_BASE ((uintptr_t)rk3399m0pmu_bin)
/* pmu_fw.c */
extern char rk3399m0_bin[];
extern char rk3399m0_bin_end[];
+extern char rk3399m0pmu_bin[];
+extern char rk3399m0pmu_bin_end[];
+
extern void m0_init(void);
extern void m0_start(void);
extern void m0_stop(void);
extern void m0_wait_done(void);
+extern void m0_configure_execute_addr(uintptr_t addr);
#endif /* __M0_CTL_H__ */
diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.c b/plat/rockchip/rk3399/drivers/pmu/pmu.c
index ed1ea8b..04446d6 100644
--- a/plat/rockchip/rk3399/drivers/pmu/pmu.c
+++ b/plat/rockchip/rk3399/drivers/pmu/pmu.c
@@ -836,6 +836,7 @@
BIT_WITH_WMSK(PMU_CLR_GIC2_CORE_L_HW));
slp_mode_cfg = BIT(PMU_PWR_MODE_EN) |
+ BIT(PMU_WKUP_RST_EN) |
BIT(PMU_INPUT_CLAMP_EN) |
BIT(PMU_POWER_OFF_REQ_CFG) |
BIT(PMU_CPU0_PD_EN) |
@@ -853,7 +854,6 @@
BIT(PMU_DDRIO0_RET_DE_REQ) |
BIT(PMU_DDRIO1_RET_EN) |
BIT(PMU_DDRIO1_RET_DE_REQ) |
- BIT(PMU_DDRIO_RET_HW_DE_REQ) |
BIT(PMU_CENTER_PD_EN) |
BIT(PMU_PERILP_PD_EN) |
BIT(PMU_CLK_PERILP_SRC_GATE_EN) |
@@ -1064,12 +1064,6 @@
}
}
-static void m0_configure_suspend(void)
-{
- /* set PARAM to M0_FUNC_SUSPEND */
- mmio_write_32(M0_PARAM_ADDR + PARAM_M0_FUNC, M0_FUNC_SUSPEND);
-}
-
void sram_save(void)
{
size_t text_size = (char *)&__bl31_sram_text_real_end -
@@ -1344,7 +1338,7 @@
set_pmu_rsthold();
sys_slp_config();
- m0_configure_suspend();
+ m0_configure_execute_addr(M0PMU_BINCODE_BASE);
m0_start();
pmu_sgrf_rst_hld();
@@ -1374,7 +1368,7 @@
mmio_setbits_32(PMU_BASE + PMU_PWRDN_CON, BIT(PMU_SCU_B_PWRDWN_EN));
wdt_register_save();
- secure_watchdog_disable();
+ secure_watchdog_gate();
/*
* Disabling PLLs/PWM/DVFS is approaching WFI which is
@@ -1403,6 +1397,7 @@
plat_rockchip_restore_gpio();
cru_register_restore();
grf_register_restore();
+ wdt_register_restore();
resume_uart();
resume_apio();
resume_gpio();
@@ -1412,10 +1407,8 @@
udelay(300);
enable_dvfs_plls();
- secure_watchdog_enable();
secure_sgrf_init();
secure_sgrf_ddr_rgn_init();
- wdt_register_restore();
/* restore clk_ddrc_bpll_src_en gate */
mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(3),
@@ -1466,12 +1459,10 @@
udelay(1);
}
- pmu_sgrf_rst_hld_release();
pmu_scu_b_pwrup();
pmu_power_domains_resume();
restore_abpll();
- restore_pmu_rsthold();
clr_hw_idle(BIT(PMU_CLR_CENTER1) |
BIT(PMU_CLR_ALIVE) |
BIT(PMU_CLR_MSCH0) |
diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu_fw.c b/plat/rockchip/rk3399/drivers/pmu/pmu_fw.c
index d299116..a09ad21 100644
--- a/plat/rockchip/rk3399/drivers/pmu/pmu_fw.c
+++ b/plat/rockchip/rk3399/drivers/pmu/pmu_fw.c
@@ -5,9 +5,9 @@
*/
/* convoluted way to make sure that the define is pasted just the right way */
-#define _INCBIN(file, sym) \
+#define _INCBIN(file, sym, sec) \
__asm__( \
- ".section .sram.incbin\n" \
+ ".section " #sec "\n" \
".global " #sym "\n" \
".type " #sym ", %object\n" \
".align 4\n" \
@@ -18,6 +18,7 @@
#sym "_end:\n" \
)
-#define INCBIN(file, sym) _INCBIN(file, sym)
+#define INCBIN(file, sym, sec) _INCBIN(file, sym, sec)
-INCBIN(RK3399M0FW, rk3399m0_bin);
+INCBIN(RK3399M0FW, rk3399m0_bin, ".sram.incbin");
+INCBIN(RK3399M0PMUFW, rk3399m0pmu_bin, ".pmusram.incbin");
diff --git a/plat/rockchip/rk3399/drivers/secure/secure.c b/plat/rockchip/rk3399/drivers/secure/secure.c
index 589d833..1937b13 100644
--- a/plat/rockchip/rk3399/drivers/secure/secure.c
+++ b/plat/rockchip/rk3399/drivers/secure/secure.c
@@ -77,7 +77,7 @@
BIT_WITH_WMSK(rgn));
}
-void secure_watchdog_disable(void)
+void secure_watchdog_gate(void)
{
/**
* Disable CA53 and CM0 wdt pclk
@@ -89,7 +89,7 @@
BIT_WITH_WMSK(PCLK_WDT_CM0_GATE_SHIFT));
}
-void secure_watchdog_enable(void)
+__pmusramfunc void secure_watchdog_ungate(void)
{
/**
* Enable CA53 and CM0 wdt pclk
diff --git a/plat/rockchip/rk3399/drivers/secure/secure.h b/plat/rockchip/rk3399/drivers/secure/secure.h
index 334805d..8e80f2b 100644
--- a/plat/rockchip/rk3399/drivers/secure/secure.h
+++ b/plat/rockchip/rk3399/drivers/secure/secure.h
@@ -95,8 +95,8 @@
#define PCLK_WDT_CM0_GATE_SHIFT 10
/* export secure operating APIs */
-void secure_watchdog_disable(void);
-void secure_watchdog_enable(void);
+void secure_watchdog_gate(void);
+__pmusramfunc void secure_watchdog_ungate(void);
void secure_timer_init(void);
void secure_sgrf_init(void);
void secure_sgrf_ddr_rgn_init(void);
diff --git a/plat/rockchip/rk3399/drivers/soc/soc.c b/plat/rockchip/rk3399/drivers/soc/soc.c
index 7dd0b72..741adde 100644
--- a/plat/rockchip/rk3399/drivers/soc/soc.c
+++ b/plat/rockchip/rk3399/drivers/soc/soc.c
@@ -43,6 +43,9 @@
/* sleep data for pll suspend */
static struct deepsleep_data_s slp_data;
+/* sleep data that needs to be accessed from pmusram */
+__pmusramdata struct pmu_sleep_data pmu_slp_data;
+
static void set_pll_slow_mode(uint32_t pll_id)
{
if (pll_id == PPLL_ID)
@@ -229,9 +232,9 @@
uint32_t rstnhold_cofig0;
uint32_t rstnhold_cofig1;
- slp_data.pmucru_rstnhold_con0 = mmio_read_32(PMUCRU_BASE +
+ pmu_slp_data.pmucru_rstnhold_con0 = mmio_read_32(PMUCRU_BASE +
PMUCRU_RSTNHOLD_CON0);
- slp_data.pmucru_rstnhold_con1 = mmio_read_32(PMUCRU_BASE +
+ pmu_slp_data.pmucru_rstnhold_con1 = mmio_read_32(PMUCRU_BASE +
PMUCRU_RSTNHOLD_CON1);
rstnhold_cofig0 = BIT_WITH_WMSK(PRESETN_NOC_PMU_HOLD) |
BIT_WITH_WMSK(PRESETN_INTMEM_PMU_HOLD) |
@@ -257,12 +260,33 @@
mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON1, rstnhold_cofig1);
}
+void pmu_sgrf_rst_hld(void)
+{
+ mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1),
+ CRU_PMU_SGRF_RST_HOLD);
+}
+
-void restore_pmu_rsthold(void)
+/*
+ * When system reset in running state, we want the cpus to be reboot
+ * from maskrom (system reboot),
+ * the pmusgrf reset-hold bits needs to be released.
+ * When system wake up from system deep suspend, some soc will be reset
+ * when waked up,
+ * we want the bootcpu to be reboot from pmusram,
+ * the pmusgrf reset-hold bits needs to be held.
+ */
+__pmusramfunc void pmu_sgrf_rst_hld_release(void)
+{
+ mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1),
+ CRU_PMU_SGRF_RST_RLS);
+}
+
+__pmusramfunc void restore_pmu_rsthold(void)
{
mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON0,
- slp_data.pmucru_rstnhold_con0 | REG_SOC_WMSK);
+ pmu_slp_data.pmucru_rstnhold_con0 | REG_SOC_WMSK);
mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON1,
- slp_data.pmucru_rstnhold_con1 | REG_SOC_WMSK);
+ pmu_slp_data.pmucru_rstnhold_con1 | REG_SOC_WMSK);
}
/**
diff --git a/plat/rockchip/rk3399/drivers/soc/soc.h b/plat/rockchip/rk3399/drivers/soc/soc.h
index 6100d95..bc41933 100644
--- a/plat/rockchip/rk3399/drivers/soc/soc.h
+++ b/plat/rockchip/rk3399/drivers/soc/soc.h
@@ -134,6 +134,9 @@
uint32_t plls_con[END_PLL_ID][PLL_CON_COUNT];
uint32_t cru_gate_con[CRU_GATE_COUNT];
uint32_t pmucru_gate_con[PMUCRU_GATE_COUNT];
+};
+
+struct pmu_sleep_data {
uint32_t pmucru_rstnhold_con0;
uint32_t pmucru_rstnhold_con1;
};
@@ -263,27 +266,6 @@
#define PMUCRU_GATEDIS_CON0 0x0130
#define PMUCRU_SOFTRST_CON(n) (PMUCRU_SOFTRST_CON0 + (n) * 4)
-/*
- * When system reset in running state, we want the cpus to be reboot
- * from maskrom (system reboot),
- * the pmusgrf reset-hold bits needs to be released.
- * When system wake up from system deep suspend, some soc will be reset
- * when waked up,
- * we want the bootcpu to be reboot from pmusram,
- * the pmusgrf reset-hold bits needs to be held.
- */
-static inline void pmu_sgrf_rst_hld_release(void)
-{
- mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1),
- CRU_PMU_SGRF_RST_RLS);
-}
-
-static inline void pmu_sgrf_rst_hld(void)
-{
- mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1),
- CRU_PMU_SGRF_RST_HOLD);
-}
-
/* export related and operating SoC APIs */
void __dead2 soc_global_soft_reset(void);
void disable_dvfs_plls(void);
@@ -296,5 +278,7 @@
void clk_gate_con_disable(void);
void clk_gate_con_restore(void);
void set_pmu_rsthold(void);
-void restore_pmu_rsthold(void);
+void pmu_sgrf_rst_hld(void);
+__pmusramfunc void pmu_sgrf_rst_hld_release(void);
+__pmusramfunc void restore_pmu_rsthold(void);
#endif /* __SOC_H__ */
diff --git a/plat/rockchip/rk3399/include/plat.ld.S b/plat/rockchip/rk3399/include/plat.ld.S
index 85f4dc3..528c150 100644
--- a/plat/rockchip/rk3399/include/plat.ld.S
+++ b/plat/rockchip/rk3399/include/plat.ld.S
@@ -77,14 +77,21 @@
ASSERT(. == ALIGN(64 * 1024),
".pmusram.entry request 64K aligned.");
*(.pmusram.entry)
+
__bl31_pmusram_text_start = .;
*(.pmusram.text)
*(.pmusram.rodata)
__bl31_pmusram_text_end = .;
+
+ /* M0 start address request 4K align */
+ . = ALIGN(4096);
+ __pmusram_incbin_start = .;
+ *(.pmusram.incbin)
+ __pmusram_incbin_end = .;
+
__bl31_pmusram_data_start = .;
*(.pmusram.data)
__bl31_pmusram_data_end = .;
-
} >PMUSRAM
}
diff --git a/plat/rockchip/rk3399/include/shared/m0_param.h b/plat/rockchip/rk3399/include/shared/m0_param.h
index 3edbf89..044e797 100644
--- a/plat/rockchip/rk3399/include/shared/m0_param.h
+++ b/plat/rockchip/rk3399/include/shared/m0_param.h
@@ -7,13 +7,6 @@
#ifndef __M0_PARAM_H__
#define __M0_PARAM_H__
-#ifndef __LINKER__
-enum {
- M0_FUNC_SUSPEND = 0,
- M0_FUNC_DRAM = 1,
-};
-#endif /* __LINKER__ */
-
#define PARAM_ADDR 0xc0
#define PARAM_M0_FUNC 0x00
diff --git a/plat/rockchip/rk3399/plat_sip_calls.c b/plat/rockchip/rk3399/plat_sip_calls.c
index 2fbda67..ae74c9c 100644
--- a/plat/rockchip/rk3399/plat_sip_calls.c
+++ b/plat/rockchip/rk3399/plat_sip_calls.c
@@ -47,14 +47,14 @@
return 0;
}
-uint64_t rockchip_plat_sip_handler(uint32_t smc_fid,
- uint64_t x1,
- uint64_t x2,
- uint64_t x3,
- uint64_t x4,
- void *cookie,
- void *handle,
- uint64_t flags)
+uintptr_t rockchip_plat_sip_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
{
uint64_t x5, x6;
diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk
index 1997dfc..fc386f0 100644
--- a/plat/rockchip/rk3399/platform.mk
+++ b/plat/rockchip/rk3399/platform.mk
@@ -82,12 +82,15 @@
RK3399M0FW=${BUILD_M0}/${PLAT_M0}.bin
$(eval $(call add_define,RK3399M0FW))
+RK3399M0PMUFW=${BUILD_M0}/${PLAT_M0}pmu.bin
+$(eval $(call add_define,RK3399M0PMUFW))
+
HDCPFW=${RK_PLAT_SOC}/drivers/dp/hdcp.bin
$(eval $(call add_define,HDCPFW))
# CCACHE_EXTRAFILES is needed because ccache doesn't handle .incbin
export CCACHE_EXTRAFILES
-${BUILD_PLAT}/bl31/pmu_fw.o: CCACHE_EXTRAFILES=$(RK3399M0FW)
+${BUILD_PLAT}/bl31/pmu_fw.o: CCACHE_EXTRAFILES=$(RK3399M0FW):$(RK3399M0PMUFW)
${RK_PLAT_SOC}/drivers/pmu/pmu_fw.c: $(RK3399M0FW)
${BUILD_PLAT}/bl31/cdn_dp.o: CCACHE_EXTRAFILES=$(HDCPFW)
diff --git a/plat/xilinx/zynqmp/include/platform_def.h b/plat/xilinx/zynqmp/include/platform_def.h
index b446235..e74b9bb 100644
--- a/plat/xilinx/zynqmp/include/platform_def.h
+++ b/plat/xilinx/zynqmp/include/platform_def.h
@@ -34,9 +34,14 @@
* little space for growth.
*/
#ifndef ZYNQMP_ATF_MEM_BASE
+#if !DEBUG
# define BL31_BASE 0xfffea000
# define BL31_LIMIT 0xffffffff
#else
+# define BL31_BASE 0x1000
+# define BL31_LIMIT 0x7ffff
+#endif
+#else
# define BL31_BASE (ZYNQMP_ATF_MEM_BASE)
# define BL31_LIMIT (ZYNQMP_ATF_MEM_BASE + ZYNQMP_ATF_MEM_SIZE - 1)
# ifdef ZYNQMP_ATF_MEM_PROGBITS_SIZE
diff --git a/plat/xilinx/zynqmp/plat_startup.c b/plat/xilinx/zynqmp/plat_startup.c
index 3ec492e..18d150c 100644
--- a/plat/xilinx/zynqmp/plat_startup.c
+++ b/plat/xilinx/zynqmp/plat_startup.c
@@ -166,12 +166,12 @@
(ATFHandoffParams->magic[1] != 'L') ||
(ATFHandoffParams->magic[2] != 'N') ||
(ATFHandoffParams->magic[3] != 'X')) {
- ERROR("BL31: invalid ATF handoff structure at %lx\n",
+ ERROR("BL31: invalid ATF handoff structure at %llx\n",
atf_handoff_addr);
panic();
}
- VERBOSE("BL31: ATF handoff params at:0x%lx, entries:%u\n",
+ VERBOSE("BL31: ATF handoff params at:0x%llx, entries:%u\n",
atf_handoff_addr, ATFHandoffParams->num_entries);
if (ATFHandoffParams->num_entries > FSBL_MAX_PARTITIONS) {
ERROR("BL31: ATF handoff params: too many partitions (%u/%u)\n",
@@ -189,7 +189,7 @@
int target_estate, target_secure;
int target_cpu, target_endianness, target_el;
- VERBOSE("BL31: %zd: entry:0x%lx, flags:0x%lx\n", i,
+ VERBOSE("BL31: %zd: entry:0x%llx, flags:0x%llx\n", i,
ATFHandoffParams->partition[i].entry_point,
ATFHandoffParams->partition[i].flags);
@@ -250,7 +250,7 @@
}
}
- VERBOSE("Setting up %s entry point to:%lx, el:%x\n",
+ VERBOSE("Setting up %s entry point to:%llx, el:%x\n",
target_secure == FSBL_FLAGS_SECURE ? "BL32" : "BL33",
ATFHandoffParams->partition[i].entry_point,
target_el);
diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk
index bddf305..e49a9cd 100644
--- a/plat/xilinx/zynqmp/platform.mk
+++ b/plat/xilinx/zynqmp/platform.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
@@ -77,6 +77,9 @@
plat/xilinx/zynqmp/zynqmp_ipi.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_api_pinctrl.c \
+ plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c \
+ plat/xilinx/zynqmp/pm_service/pm_api_clock.c \
plat/xilinx/zynqmp/pm_service/pm_ipi.c \
plat/xilinx/zynqmp/pm_service/pm_client.c \
plat/xilinx/zynqmp/ipi_mailbox_service/ipi_mailbox_svc.c
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
new file mode 100644
index 0000000..a41eebb
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
@@ -0,0 +1,3212 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * ZynqMP system level PM-API functions for clock control.
+ */
+
+#include <arch_helpers.h>
+#include <mmio.h>
+#include <platform.h>
+#include <stdbool.h>
+#include <string.h>
+#include "pm_api_clock.h"
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include "pm_common.h"
+#include "pm_ipi.h"
+
+#define CLK_NODE_MAX U(6)
+
+#define CLK_PARENTS_ID_LEN U(16)
+#define CLK_TOPOLOGY_NODE_OFFSET U(16)
+#define CLK_TOPOLOGY_PAYLOAD_LEN U(12)
+#define CLK_PARENTS_PAYLOAD_LEN U(12)
+#define CLK_INIT_ENABLE_SHIFT U(1)
+#define CLK_TYPE_SHIFT U(2)
+#define CLK_CLKFLAGS_SHIFT U(8)
+#define CLK_TYPEFLAGS_SHIFT U(24)
+
+#define CLK_EXTERNAL_PARENT (PARENT_CLK_EXTERNAL << CLK_PARENTS_ID_LEN)
+
+#define NA_MULT U(0)
+#define NA_DIV U(0)
+#define NA_SHIFT U(0)
+#define NA_WIDTH U(0)
+#define NA_CLK_FLAGS U(0)
+#define NA_TYPE_FLAGS U(0)
+
+/* PLL nodes related definitions */
+#define PLL_PRESRC_MUX_SHIFT U(20)
+#define PLL_PRESRC_MUX_WIDTH U(3)
+#define PLL_POSTSRC_MUX_SHIFT U(24)
+#define PLL_POSTSRC_MUX_WIDTH U(3)
+#define PLL_DIV2_MUX_SHIFT U(16)
+#define PLL_DIV2_MUX_WIDTH U(1)
+#define PLL_BYPASS_MUX_SHIFT U(3)
+#define PLL_BYPASS_MUX_WIDTH U(1)
+
+/* Peripheral nodes related definitions */
+/* Peripheral Clocks */
+#define PERIPH_MUX_SHIFT U(0)
+#define PERIPH_MUX_WIDTH U(3)
+#define PERIPH_DIV1_SHIFT U(8)
+#define PERIPH_DIV1_WIDTH U(6)
+#define PERIPH_DIV2_SHIFT U(16)
+#define PERIPH_DIV2_WIDTH U(6)
+#define PERIPH_GATE_SHIFT U(24)
+#define PERIPH_GATE_WIDTH U(1)
+
+#define USB_GATE_SHIFT U(25)
+
+/* External clock related definitions */
+
+#define EXT_CLK_MIO_DATA(mio) \
+ [EXT_CLK_INDEX(EXT_CLK_MIO##mio)] = { \
+ .name = "mio_clk_"#mio, \
+ }
+
+#define EXT_CLK_INDEX(n) (n - CLK_MAX_OUTPUT_CLK)
+
+/* Clock control related definitions */
+#define BIT_MASK(x, y) (((1U << (y)) - 1) << (x))
+
+#define ISPLL(id) (id == CLK_APLL_INT || \
+ id == CLK_DPLL_INT || \
+ id == CLK_VPLL_INT || \
+ id == CLK_IOPLL_INT || \
+ id == CLK_RPLL_INT)
+
+
+#define PLLCTRL_BP_MASK BIT(3)
+#define PLLCTRL_RESET_MASK U(1)
+#define PLL_FRAC_OFFSET U(8)
+#define PLL_FRAC_MODE U(1)
+#define PLL_INT_MODE U(0)
+#define PLL_FRAC_MODE_MASK U(0x80000000)
+#define PLL_FRAC_MODE_SHIFT U(31)
+#define PLL_FRAC_DATA_MASK U(0xFFFF)
+#define PLL_FRAC_DATA_SHIFT U(0)
+#define PLL_FBDIV_MASK U(0x7F00)
+#define PLL_FBDIV_WIDTH U(7)
+#define PLL_FBDIV_SHIFT U(8)
+
+#define CLK_PLL_RESET_ASSERT U(1)
+#define CLK_PLL_RESET_RELEASE U(2)
+#define CLK_PLL_RESET_PULSE (CLK_PLL_RESET_ASSERT | CLK_PLL_RESET_RELEASE)
+
+/* Common topology definitions */
+#define GENERIC_MUX \
+ { \
+ .type = TYPE_MUX, \
+ .offset = PERIPH_MUX_SHIFT, \
+ .width = PERIPH_MUX_WIDTH, \
+ .clkflags = CLK_SET_RATE_NO_REPARENT | \
+ CLK_IS_BASIC, \
+ .typeflags = NA_TYPE_FLAGS, \
+ .mult = NA_MULT, \
+ .div = NA_DIV, \
+ }
+
+#define IGNORE_UNUSED_MUX \
+ { \
+ .type = TYPE_MUX, \
+ .offset = PERIPH_MUX_SHIFT, \
+ .width = PERIPH_MUX_WIDTH, \
+ .clkflags = CLK_IGNORE_UNUSED | \
+ CLK_SET_RATE_NO_REPARENT | \
+ CLK_IS_BASIC, \
+ .typeflags = NA_TYPE_FLAGS, \
+ .mult = NA_MULT, \
+ .div = NA_DIV, \
+ }
+
+#define GENERIC_DIV(id) \
+ { \
+ .type = TYPE_DIV##id, \
+ .offset = PERIPH_DIV##id##_SHIFT, \
+ .width = PERIPH_DIV##id##_WIDTH, \
+ .clkflags = CLK_SET_RATE_NO_REPARENT | \
+ CLK_IS_BASIC, \
+ .typeflags = CLK_DIVIDER_ONE_BASED | \
+ CLK_DIVIDER_ALLOW_ZERO, \
+ .mult = NA_MULT, \
+ .div = NA_DIV, \
+ }
+
+#define IGNORE_UNUSED_DIV(id) \
+ { \
+ .type = TYPE_DIV##id, \
+ .offset = PERIPH_DIV##id##_SHIFT, \
+ .width = PERIPH_DIV##id##_WIDTH, \
+ .clkflags = CLK_IGNORE_UNUSED | \
+ CLK_SET_RATE_NO_REPARENT | \
+ CLK_IS_BASIC, \
+ .typeflags = CLK_DIVIDER_ONE_BASED | \
+ CLK_DIVIDER_ALLOW_ZERO, \
+ .mult = NA_MULT, \
+ .div = NA_DIV, \
+ }
+
+#define GENERIC_GATE \
+ { \
+ .type = TYPE_GATE, \
+ .offset = PERIPH_GATE_SHIFT, \
+ .width = PERIPH_GATE_WIDTH, \
+ .clkflags = CLK_SET_RATE_PARENT | \
+ CLK_SET_RATE_GATE | \
+ CLK_IS_BASIC, \
+ .typeflags = NA_TYPE_FLAGS, \
+ .mult = NA_MULT, \
+ .div = NA_DIV, \
+ }
+
+#define IGNORE_UNUSED_GATE \
+ { \
+ .type = TYPE_GATE, \
+ .offset = PERIPH_GATE_SHIFT, \
+ .width = PERIPH_GATE_WIDTH, \
+ .clkflags = CLK_SET_RATE_PARENT | \
+ CLK_IGNORE_UNUSED | \
+ CLK_IS_BASIC, \
+ .typeflags = NA_TYPE_FLAGS, \
+ .mult = NA_MULT, \
+ .div = NA_DIV, \
+ }
+
+/**
+ * struct pm_clock_node - Clock topology node information
+ * @type: Topology type (mux/div1/div2/gate/pll/fixed factor)
+ * @offset: Offset in control register
+ * @width: Width of the specific type in control register
+ * @clkflags: Clk specific flags
+ * @typeflags: Type specific flags
+ * @mult: Multiplier for fixed factor
+ * @div: Divisor for fixed factor
+ */
+struct pm_clock_node {
+ uint16_t clkflags;
+ uint16_t typeflags;
+ uint8_t type;
+ uint8_t offset;
+ uint8_t width;
+ uint8_t mult:4;
+ uint8_t div:4;
+};
+
+/**
+ * struct pm_clock - Clock structure
+ * @name: Clock name
+ * @control_reg: Control register address
+ * @status_reg: Status register address
+ * @parents: Parents for first clock node. Lower byte indicates parent
+ * clock id and upper byte indicate flags for that id.
+ * pm_clock_node: Clock nodes
+ */
+struct pm_clock {
+ char name[CLK_NAME_LEN];
+ uint8_t num_nodes;
+ unsigned int control_reg;
+ unsigned int status_reg;
+ int32_t (*parents)[];
+ struct pm_clock_node(*nodes)[];
+};
+
+/**
+ * struct pm_clock - Clock structure
+ * @name: Clock name
+ */
+struct pm_ext_clock {
+ char name[CLK_NAME_LEN];
+};
+
+/* PLL Clocks */
+static struct pm_clock_node generic_pll_nodes[] = {
+ {
+ .type = TYPE_PLL,
+ .offset = NA_SHIFT,
+ .width = NA_WIDTH,
+ .clkflags = CLK_SET_RATE_NO_REPARENT,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node ignore_unused_pll_nodes[] = {
+ {
+ .type = TYPE_PLL,
+ .offset = NA_SHIFT,
+ .width = NA_WIDTH,
+ .clkflags = CLK_IGNORE_UNUSED | CLK_SET_RATE_NO_REPARENT,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node generic_pll_pre_src_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = PLL_PRESRC_MUX_SHIFT,
+ .width = PLL_PRESRC_MUX_WIDTH,
+ .clkflags = CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node generic_pll_half_nodes[] = {
+ {
+ .type = TYPE_FIXEDFACTOR,
+ .offset = NA_SHIFT,
+ .width = NA_WIDTH,
+ .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = 1,
+ .div = 2,
+ },
+};
+
+static struct pm_clock_node generic_pll_int_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = PLL_DIV2_MUX_SHIFT,
+ .width = PLL_DIV2_MUX_WIDTH,
+ .clkflags = CLK_SET_RATE_NO_REPARENT |
+ CLK_SET_RATE_PARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node generic_pll_post_src_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = PLL_POSTSRC_MUX_SHIFT,
+ .width = PLL_POSTSRC_MUX_WIDTH,
+ .clkflags = CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node generic_pll_system_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = PLL_BYPASS_MUX_SHIFT,
+ .width = PLL_BYPASS_MUX_WIDTH,
+ .clkflags = CLK_SET_RATE_NO_REPARENT |
+ CLK_SET_RATE_PARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node acpu_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = PERIPH_MUX_SHIFT,
+ .width = PERIPH_MUX_WIDTH,
+ .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ {
+ .type = TYPE_DIV1,
+ .offset = PERIPH_DIV1_SHIFT,
+ .width = PERIPH_DIV1_WIDTH,
+ .clkflags = CLK_IS_BASIC,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ {
+ .type = TYPE_GATE,
+ .offset = PERIPH_GATE_SHIFT,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_SET_RATE_PARENT |
+ CLK_IGNORE_UNUSED |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node generic_mux_div_nodes[] = {
+ GENERIC_MUX,
+ GENERIC_DIV(1),
+};
+
+static struct pm_clock_node generic_mux_div_gate_nodes[] = {
+ GENERIC_MUX,
+ GENERIC_DIV(1),
+ GENERIC_GATE,
+};
+
+static struct pm_clock_node generic_mux_div_unused_gate_nodes[] = {
+ GENERIC_MUX,
+ GENERIC_DIV(1),
+ IGNORE_UNUSED_GATE,
+};
+
+static struct pm_clock_node generic_mux_div_div_gate_nodes[] = {
+ GENERIC_MUX,
+ GENERIC_DIV(1),
+ GENERIC_DIV(2),
+ GENERIC_GATE,
+};
+
+static struct pm_clock_node dp_audio_video_ref_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = PERIPH_MUX_SHIFT,
+ .width = PERIPH_MUX_WIDTH,
+ .clkflags = CLK_SET_RATE_NO_REPARENT |
+ CLK_SET_RATE_PARENT |
+ CLK_FRAC | CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ {
+ .type = TYPE_DIV1,
+ .offset = PERIPH_DIV1_SHIFT,
+ .width = PERIPH_DIV1_WIDTH,
+ .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT |
+ CLK_FRAC | CLK_IS_BASIC,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ {
+ .type = TYPE_DIV2,
+ .offset = PERIPH_DIV2_SHIFT,
+ .width = PERIPH_DIV2_WIDTH,
+ .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT |
+ CLK_FRAC | CLK_IS_BASIC,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ {
+ .type = TYPE_GATE,
+ .offset = PERIPH_GATE_SHIFT,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_GATE |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node usb_nodes[] = {
+ GENERIC_MUX,
+ GENERIC_DIV(1),
+ GENERIC_DIV(2),
+ {
+ .type = TYPE_GATE,
+ .offset = USB_GATE_SHIFT,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC |
+ CLK_SET_RATE_GATE,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node generic_domain_crossing_nodes[] = {
+ {
+ .type = TYPE_DIV1,
+ .offset = 8,
+ .width = 6,
+ .clkflags = CLK_IS_BASIC,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node rpll_to_fpd_nodes[] = {
+ {
+ .type = TYPE_DIV1,
+ .offset = 8,
+ .width = 6,
+ .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node acpu_half_nodes[] = {
+ {
+ .type = TYPE_FIXEDFACTOR,
+ .offset = 0,
+ .width = 1,
+ .clkflags = 0,
+ .typeflags = 0,
+ .mult = 1,
+ .div = 2,
+ },
+ {
+ .type = TYPE_GATE,
+ .offset = 25,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_IGNORE_UNUSED |
+ CLK_SET_RATE_PARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node wdt_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 0,
+ .width = 1,
+ .clkflags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node ddr_nodes[] = {
+ GENERIC_MUX,
+ {
+ .type = TYPE_DIV1,
+ .offset = 8,
+ .width = 6,
+ .clkflags = CLK_IS_BASIC,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node pl_nodes[] = {
+ GENERIC_MUX,
+ {
+ .type = TYPE_DIV1,
+ .offset = PERIPH_DIV1_SHIFT,
+ .width = PERIPH_DIV1_WIDTH,
+ .clkflags = CLK_IS_BASIC,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ {
+ .type = TYPE_DIV2,
+ .offset = PERIPH_DIV2_SHIFT,
+ .width = PERIPH_DIV2_WIDTH,
+ .clkflags = CLK_IS_BASIC | CLK_SET_RATE_PARENT,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ {
+ .type = TYPE_GATE,
+ .offset = PERIPH_GATE_SHIFT,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node gpu_pp0_nodes[] = {
+ {
+ .type = TYPE_GATE,
+ .offset = 25,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node gpu_pp1_nodes[] = {
+ {
+ .type = TYPE_GATE,
+ .offset = 26,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node gem_nodes[] = {
+ GENERIC_MUX,
+ {
+ .type = TYPE_DIV1,
+ .offset = 8,
+ .width = 6,
+ .clkflags = CLK_IS_BASIC,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ {
+ .type = TYPE_DIV2,
+ .offset = 16,
+ .width = 6,
+ .clkflags = CLK_IS_BASIC,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ {
+ .type = TYPE_GATE,
+ .offset = 25,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node gem0_tx_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 1,
+ .width = 1,
+ .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ {
+ .type = TYPE_GATE,
+ .offset = 26,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node gem1_tx_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 6,
+ .width = 1,
+ .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ {
+ .type = TYPE_GATE,
+ .offset = 26,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node gem2_tx_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 11,
+ .width = 1,
+ .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ {
+ .type = TYPE_GATE,
+ .offset = 26,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node gem3_tx_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 16,
+ .width = 1,
+ .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ {
+ .type = TYPE_GATE,
+ .offset = 26,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node gem_tsu_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 20,
+ .width = 2,
+ .clkflags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node can0_mio_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 0,
+ .width = 7,
+ .clkflags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node can1_mio_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 15,
+ .width = 1,
+ .clkflags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node can0_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 7,
+ .width = 1,
+ .clkflags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node can1_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 22,
+ .width = 1,
+ .clkflags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node cpu_r5_core_nodes[] = {
+ {
+ .type = TYPE_GATE,
+ .offset = 25,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_IGNORE_UNUSED |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node dll_ref_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 0,
+ .width = 3,
+ .clkflags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node timestamp_ref_nodes[] = {
+ GENERIC_MUX,
+ {
+ .type = TYPE_DIV1,
+ .offset = 8,
+ .width = 6,
+ .clkflags = CLK_IS_BASIC,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ IGNORE_UNUSED_GATE,
+};
+
+static int32_t can_mio_parents[] = {
+ EXT_CLK_MIO0, EXT_CLK_MIO1, EXT_CLK_MIO2, EXT_CLK_MIO3,
+ EXT_CLK_MIO4, EXT_CLK_MIO5, EXT_CLK_MIO6, EXT_CLK_MIO7,
+ EXT_CLK_MIO8, EXT_CLK_MIO9, EXT_CLK_MIO10, EXT_CLK_MIO11,
+ EXT_CLK_MIO12, EXT_CLK_MIO13, EXT_CLK_MIO14, EXT_CLK_MIO15,
+ EXT_CLK_MIO16, EXT_CLK_MIO17, EXT_CLK_MIO18, EXT_CLK_MIO19,
+ EXT_CLK_MIO20, EXT_CLK_MIO21, EXT_CLK_MIO22, EXT_CLK_MIO23,
+ EXT_CLK_MIO24, EXT_CLK_MIO25, EXT_CLK_MIO26, EXT_CLK_MIO27,
+ EXT_CLK_MIO28, EXT_CLK_MIO29, EXT_CLK_MIO30, EXT_CLK_MIO31,
+ EXT_CLK_MIO32, EXT_CLK_MIO33, EXT_CLK_MIO34, EXT_CLK_MIO35,
+ EXT_CLK_MIO36, EXT_CLK_MIO37, EXT_CLK_MIO38, EXT_CLK_MIO39,
+ EXT_CLK_MIO40, EXT_CLK_MIO41, EXT_CLK_MIO42, EXT_CLK_MIO43,
+ EXT_CLK_MIO44, EXT_CLK_MIO45, EXT_CLK_MIO46, EXT_CLK_MIO47,
+ EXT_CLK_MIO48, EXT_CLK_MIO49, EXT_CLK_MIO50, EXT_CLK_MIO51,
+ EXT_CLK_MIO52, EXT_CLK_MIO53, EXT_CLK_MIO54, EXT_CLK_MIO55,
+ EXT_CLK_MIO56, EXT_CLK_MIO57, EXT_CLK_MIO58, EXT_CLK_MIO59,
+ EXT_CLK_MIO60, EXT_CLK_MIO61, EXT_CLK_MIO62, EXT_CLK_MIO63,
+ EXT_CLK_MIO64, EXT_CLK_MIO65, EXT_CLK_MIO66, EXT_CLK_MIO67,
+ EXT_CLK_MIO68, EXT_CLK_MIO69, EXT_CLK_MIO70, EXT_CLK_MIO71,
+ EXT_CLK_MIO72, EXT_CLK_MIO73, EXT_CLK_MIO74, EXT_CLK_MIO75,
+ EXT_CLK_MIO76, EXT_CLK_MIO77, CLK_NA_PARENT
+};
+
+/* Clock array containing clock informaton */
+static struct pm_clock clocks[] = {
+ [CLK_APLL_INT] = {
+ .name = "apll_int",
+ .control_reg = CRF_APB_APLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {CLK_APLL_PRE_SRC, CLK_NA_PARENT}),
+ .nodes = &ignore_unused_pll_nodes,
+ .num_nodes = ARRAY_SIZE(ignore_unused_pll_nodes),
+ },
+ [CLK_APLL_PRE_SRC] = {
+ .name = "apll_pre_src",
+ .control_reg = CRF_APB_APLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_pre_src_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_pre_src_nodes),
+ },
+ [CLK_APLL_HALF] = {
+ .name = "apll_half",
+ .control_reg = CRF_APB_APLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {CLK_APLL_INT, CLK_NA_PARENT}),
+ .nodes = &generic_pll_half_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_half_nodes),
+ },
+ [CLK_APLL_INT_MUX] = {
+ .name = "apll_int_mux",
+ .control_reg = CRF_APB_APLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ CLK_APLL_INT,
+ CLK_APLL_HALF,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_int_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_int_nodes),
+ },
+ [CLK_APLL_POST_SRC] = {
+ .name = "apll_post_src",
+ .control_reg = CRF_APB_APLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_post_src_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_post_src_nodes),
+ },
+ [CLK_APLL] = {
+ .name = "apll",
+ .control_reg = CRF_APB_APLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ CLK_APLL_INT_MUX,
+ CLK_APLL_POST_SRC,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_system_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_system_nodes),
+ },
+ [CLK_DPLL_INT] = {
+ .name = "dpll_int",
+ .control_reg = CRF_APB_DPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {CLK_DPLL_PRE_SRC, CLK_NA_PARENT}),
+ .nodes = &generic_pll_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_nodes),
+ },
+ [CLK_DPLL_PRE_SRC] = {
+ .name = "dpll_pre_src",
+ .control_reg = CRF_APB_DPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_pre_src_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_pre_src_nodes),
+ },
+ [CLK_DPLL_HALF] = {
+ .name = "dpll_half",
+ .control_reg = CRF_APB_DPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {CLK_DPLL_INT, CLK_NA_PARENT}),
+ .nodes = &generic_pll_half_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_half_nodes),
+ },
+ [CLK_DPLL_INT_MUX] = {
+ .name = "dpll_int_mux",
+ .control_reg = CRF_APB_DPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ CLK_DPLL_INT,
+ CLK_DPLL_HALF,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_int_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_int_nodes),
+ },
+ [CLK_DPLL_POST_SRC] = {
+ .name = "dpll_post_src",
+ .control_reg = CRF_APB_DPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_post_src_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_post_src_nodes),
+ },
+ [CLK_DPLL] = {
+ .name = "dpll",
+ .control_reg = CRF_APB_DPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ CLK_DPLL_INT_MUX,
+ CLK_DPLL_POST_SRC,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_system_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_system_nodes),
+ },
+ [CLK_VPLL_INT] = {
+ .name = "vpll_int",
+ .control_reg = CRF_APB_VPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {CLK_VPLL_PRE_SRC, CLK_NA_PARENT}),
+ .nodes = &ignore_unused_pll_nodes,
+ .num_nodes = ARRAY_SIZE(ignore_unused_pll_nodes),
+ },
+ [CLK_VPLL_PRE_SRC] = {
+ .name = "vpll_pre_src",
+ .control_reg = CRF_APB_VPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_pre_src_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_pre_src_nodes),
+ },
+ [CLK_VPLL_HALF] = {
+ .name = "vpll_half",
+ .control_reg = CRF_APB_VPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {CLK_VPLL_INT, CLK_NA_PARENT}),
+ .nodes = &generic_pll_half_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_half_nodes),
+ },
+ [CLK_VPLL_INT_MUX] = {
+ .name = "vpll_int_mux",
+ .control_reg = CRF_APB_VPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ CLK_VPLL_INT,
+ CLK_VPLL_HALF,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_int_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_int_nodes),
+ },
+ [CLK_VPLL_POST_SRC] = {
+ .name = "vpll_post_src",
+ .control_reg = CRF_APB_VPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_post_src_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_post_src_nodes),
+ },
+ [CLK_VPLL] = {
+ .name = "vpll",
+ .control_reg = CRF_APB_VPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ CLK_VPLL_INT_MUX,
+ CLK_VPLL_POST_SRC,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_system_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_system_nodes),
+ },
+ [CLK_IOPLL_INT] = {
+ .name = "iopll_int",
+ .control_reg = CRL_APB_IOPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {CLK_IOPLL_PRE_SRC, CLK_NA_PARENT}),
+ .nodes = &generic_pll_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_nodes),
+ },
+ [CLK_IOPLL_PRE_SRC] = {
+ .name = "iopll_pre_src",
+ .control_reg = CRL_APB_IOPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_pre_src_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_pre_src_nodes),
+ },
+ [CLK_IOPLL_HALF] = {
+ .name = "iopll_half",
+ .control_reg = CRL_APB_IOPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {CLK_IOPLL_INT, CLK_NA_PARENT}),
+ .nodes = &generic_pll_half_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_half_nodes),
+ },
+ [CLK_IOPLL_INT_MUX] = {
+ .name = "iopll_int_mux",
+ .control_reg = CRL_APB_IOPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ CLK_IOPLL_INT,
+ CLK_IOPLL_HALF,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_int_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_int_nodes),
+ },
+ [CLK_IOPLL_POST_SRC] = {
+ .name = "iopll_post_src",
+ .control_reg = CRL_APB_IOPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_post_src_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_post_src_nodes),
+ },
+ [CLK_IOPLL] = {
+ .name = "iopll",
+ .control_reg = CRL_APB_IOPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ CLK_IOPLL_INT_MUX,
+ CLK_IOPLL_POST_SRC,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_system_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_system_nodes),
+ },
+ [CLK_RPLL_INT] = {
+ .name = "rpll_int",
+ .control_reg = CRL_APB_RPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {CLK_RPLL_PRE_SRC, CLK_NA_PARENT}),
+ .nodes = &generic_pll_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_nodes),
+ },
+ [CLK_RPLL_PRE_SRC] = {
+ .name = "rpll_pre_src",
+ .control_reg = CRL_APB_RPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+
+ .nodes = &generic_pll_pre_src_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_pre_src_nodes),
+ },
+ [CLK_RPLL_HALF] = {
+ .name = "rpll_half",
+ .control_reg = CRL_APB_RPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {CLK_RPLL_INT, CLK_NA_PARENT}),
+ .nodes = &generic_pll_half_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_half_nodes),
+ },
+ [CLK_RPLL_INT_MUX] = {
+ .name = "rpll_int_mux",
+ .control_reg = CRL_APB_RPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ CLK_RPLL_INT,
+ CLK_RPLL_HALF,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_int_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_int_nodes),
+ },
+ [CLK_RPLL_POST_SRC] = {
+ .name = "rpll_post_src",
+ .control_reg = CRL_APB_RPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_post_src_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_post_src_nodes),
+ },
+ [CLK_RPLL] = {
+ .name = "rpll",
+ .control_reg = CRL_APB_RPLL_CTRL,
+ .status_reg = CRL_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ CLK_RPLL_INT_MUX,
+ CLK_RPLL_POST_SRC,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_system_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_system_nodes),
+ },
+ /* Peripheral Clocks */
+ [CLK_ACPU] = {
+ .name = "acpu",
+ .control_reg = CRF_APB_ACPU_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_APLL,
+ CLK_DUMMY_PARENT,
+ CLK_DPLL,
+ CLK_VPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &acpu_nodes,
+ .num_nodes = ARRAY_SIZE(acpu_nodes),
+ },
+ [CLK_DBG_TRACE] = {
+ .name = "dbg_trace",
+ .control_reg = CRF_APB_DBG_TRACE_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL_TO_FPD,
+ CLK_DUMMY_PARENT,
+ CLK_DPLL,
+ CLK_APLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_DBG_FPD] = {
+ .name = "dbg_fpd",
+ .control_reg = CRF_APB_DBG_FPD_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL_TO_FPD,
+ CLK_DUMMY_PARENT,
+ CLK_DPLL,
+ CLK_APLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_DBG_TSTMP] = {
+ .name = "dbg_tstmp",
+ .control_reg = CRF_APB_DBG_TSTMP_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL_TO_FPD,
+ CLK_DUMMY_PARENT,
+ CLK_DPLL,
+ CLK_APLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_nodes),
+ },
+ [CLK_DP_VIDEO_REF] = {
+ .name = "dp_video_ref",
+ .control_reg = CRF_APB_DP_VIDEO_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_VPLL,
+ CLK_DUMMY_PARENT,
+ CLK_DPLL,
+ CLK_RPLL_TO_FPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &dp_audio_video_ref_nodes,
+ .num_nodes = ARRAY_SIZE(dp_audio_video_ref_nodes),
+ },
+ [CLK_DP_AUDIO_REF] = {
+ .name = "dp_audio_ref",
+ .control_reg = CRF_APB_DP_AUDIO_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_VPLL,
+ CLK_DUMMY_PARENT,
+ CLK_DPLL,
+ CLK_RPLL_TO_FPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &dp_audio_video_ref_nodes,
+ .num_nodes = ARRAY_SIZE(dp_audio_video_ref_nodes),
+ },
+ [CLK_DP_STC_REF] = {
+ .name = "dp_stc_ref",
+ .control_reg = CRF_APB_DP_STC_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_VPLL,
+ CLK_DUMMY_PARENT,
+ CLK_DPLL,
+ CLK_RPLL_TO_FPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_DPDMA_REF] = {
+ .name = "dpdma_ref",
+ .control_reg = CRF_APB_DPDMA_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_APLL,
+ CLK_DUMMY_PARENT,
+ CLK_VPLL,
+ CLK_DPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_DDR_REF] = {
+ .name = "ddr_ref",
+ .control_reg = CRF_APB_DDR_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_DPLL,
+ CLK_VPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &ddr_nodes,
+ .num_nodes = ARRAY_SIZE(ddr_nodes),
+ },
+ [CLK_GPU_REF] = {
+ .name = "gpu_ref",
+ .control_reg = CRF_APB_GPU_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL_TO_FPD,
+ CLK_DUMMY_PARENT,
+ CLK_VPLL,
+ CLK_DPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_SATA_REF] = {
+ .name = "sata_ref",
+ .control_reg = CRF_APB_SATA_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL_TO_FPD,
+ CLK_DUMMY_PARENT,
+ CLK_APLL,
+ CLK_DPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_PCIE_REF] = {
+ .name = "pcie_ref",
+ .control_reg = CRF_APB_PCIE_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL_TO_FPD,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL_TO_FPD,
+ CLK_DPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_GDMA_REF] = {
+ .name = "gdma_ref",
+ .control_reg = CRF_APB_GDMA_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_APLL,
+ CLK_DUMMY_PARENT,
+ CLK_VPLL,
+ CLK_DPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_GTGREF0_REF] = {
+ .name = "gtgref0_ref",
+ .control_reg = CRF_APB_GTGREF0_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL_TO_FPD,
+ CLK_DUMMY_PARENT,
+ CLK_APLL,
+ CLK_DPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_TOPSW_MAIN] = {
+ .name = "topsw_main",
+ .control_reg = CRF_APB_TOPSW_MAIN_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_APLL,
+ CLK_DUMMY_PARENT,
+ CLK_VPLL,
+ CLK_DPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_unused_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes),
+ },
+ [CLK_TOPSW_LSBUS] = {
+ .name = "topsw_lsbus",
+ .control_reg = CRF_APB_TOPSW_LSBUS_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_APLL,
+ CLK_DUMMY_PARENT,
+ CLK_IOPLL_TO_FPD,
+ CLK_DPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_unused_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes),
+ },
+ [CLK_IOU_SWITCH] = {
+ .name = "iou_switch",
+ .control_reg = CRL_APB_IOU_SWITCH_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_RPLL,
+ CLK_DUMMY_PARENT,
+ CLK_IOPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_unused_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes),
+ },
+ [CLK_GEM0_REF] = {
+ .name = "gem0_ref",
+ .control_reg = CRL_APB_GEM0_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem_nodes,
+ .num_nodes = ARRAY_SIZE(gem_nodes),
+ },
+ [CLK_GEM1_REF] = {
+ .name = "gem1_ref",
+ .control_reg = CRL_APB_GEM1_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem_nodes,
+ .num_nodes = ARRAY_SIZE(gem_nodes),
+ },
+ [CLK_GEM2_REF] = {
+ .name = "gem2_ref",
+ .control_reg = CRL_APB_GEM2_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem_nodes,
+ .num_nodes = ARRAY_SIZE(gem_nodes),
+ },
+ [CLK_GEM3_REF] = {
+ .name = "gem3_ref",
+ .control_reg = CRL_APB_GEM3_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem_nodes,
+ .num_nodes = ARRAY_SIZE(gem_nodes),
+ },
+ [CLK_USB0_BUS_REF] = {
+ .name = "usb0_bus_ref",
+ .control_reg = CRL_APB_USB0_BUS_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &usb_nodes,
+ .num_nodes = ARRAY_SIZE(usb_nodes),
+ },
+ [CLK_USB1_BUS_REF] = {
+ .name = "usb1_bus_ref",
+ .control_reg = CRL_APB_USB1_BUS_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &usb_nodes,
+ .num_nodes = ARRAY_SIZE(usb_nodes),
+ },
+ [CLK_USB3_DUAL_REF] = {
+ .name = "usb3_dual_ref",
+ .control_reg = CRL_APB_USB3_DUAL_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &usb_nodes,
+ .num_nodes = ARRAY_SIZE(usb_nodes),
+ },
+ [CLK_QSPI_REF] = {
+ .name = "qspi_ref",
+ .control_reg = CRL_APB_QSPI_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_SDIO0_REF] = {
+ .name = "sdio0_ref",
+ .control_reg = CRL_APB_SDIO0_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_VPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_SDIO1_REF] = {
+ .name = "sdio1_ref",
+ .control_reg = CRL_APB_SDIO1_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_VPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_UART0_REF] = {
+ .name = "uart0_ref",
+ .control_reg = CRL_APB_UART0_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_UART1_REF] = {
+ .name = "uart1_ref",
+ .control_reg = CRL_APB_UART1_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_SPI0_REF] = {
+ .name = "spi0_ref",
+ .control_reg = CRL_APB_SPI0_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_SPI1_REF] = {
+ .name = "spi1_ref",
+ .control_reg = CRL_APB_SPI1_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_CAN0_REF] = {
+ .name = "can0_ref",
+ .control_reg = CRL_APB_CAN0_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_CAN1_REF] = {
+ .name = "can1_ref",
+ .control_reg = CRL_APB_CAN1_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_NAND_REF] = {
+ .name = "nand_ref",
+ .control_reg = CRL_APB_NAND_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_GEM_TSU_REF] = {
+ .name = "gem_tsu_ref",
+ .control_reg = CRL_APB_GEM_TSU_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_DLL_REF] = {
+ .name = "dll_ref",
+ .control_reg = CRL_APB_DLL_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_RPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &dll_ref_nodes,
+ .num_nodes = ARRAY_SIZE(dll_ref_nodes),
+ },
+ [CLK_ADMA_REF] = {
+ .name = "adma_ref",
+ .control_reg = CRL_APB_ADMA_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_RPLL,
+ CLK_DUMMY_PARENT,
+ CLK_IOPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_DBG_LPD] = {
+ .name = "dbg_lpd",
+ .control_reg = CRL_APB_DBG_LPD_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_RPLL,
+ CLK_DUMMY_PARENT,
+ CLK_IOPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_CPU_R5] = {
+ .name = "cpu_r5",
+ .control_reg = CRL_APB_CPU_R5_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_RPLL,
+ CLK_DUMMY_PARENT,
+ CLK_IOPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_unused_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes),
+ },
+ [CLK_CSU_PLL] = {
+ .name = "csu_pll",
+ .control_reg = CRL_APB_CSU_PLL_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_PCAP] = {
+ .name = "pcap",
+ .control_reg = CRL_APB_PCAP_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_LPD_LSBUS] = {
+ .name = "lpd_lsbus",
+ .control_reg = CRL_APB_LPD_LSBUS_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_RPLL,
+ CLK_DUMMY_PARENT,
+ CLK_IOPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_unused_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes),
+ },
+ [CLK_LPD_SWITCH] = {
+ .name = "lpd_switch",
+ .control_reg = CRL_APB_LPD_SWITCH_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_RPLL,
+ CLK_DUMMY_PARENT,
+ CLK_IOPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_unused_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes),
+ },
+ [CLK_I2C0_REF] = {
+ .name = "i2c0_ref",
+ .control_reg = CRL_APB_I2C0_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_I2C1_REF] = {
+ .name = "i2c1_ref",
+ .control_reg = CRL_APB_I2C1_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_TIMESTAMP_REF] = {
+ .name = "timestamp_ref",
+ .control_reg = CRL_APB_TIMESTAMP_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = ×tamp_ref_nodes,
+ .num_nodes = ARRAY_SIZE(timestamp_ref_nodes),
+ },
+ [CLK_PL0_REF] = {
+ .name = "pl0_ref",
+ .control_reg = CRL_APB_PL0_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &pl_nodes,
+ .num_nodes = ARRAY_SIZE(pl_nodes),
+ },
+ [CLK_PL1_REF] = {
+ .name = "pl1_ref",
+ .control_reg = CRL_APB_PL1_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &pl_nodes,
+ .num_nodes = ARRAY_SIZE(pl_nodes),
+ },
+ [CLK_PL2_REF] = {
+ .name = "pl2_ref",
+ .control_reg = CRL_APB_PL2_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &pl_nodes,
+ .num_nodes = ARRAY_SIZE(pl_nodes),
+ },
+ [CLK_PL3_REF] = {
+ .name = "pl3_ref",
+ .control_reg = CRL_APB_PL3_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &pl_nodes,
+ .num_nodes = ARRAY_SIZE(pl_nodes),
+ },
+ [CLK_AMS_REF] = {
+ .name = "ams_ref",
+ .control_reg = CRL_APB_AMS_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_RPLL,
+ CLK_DUMMY_PARENT,
+ CLK_IOPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_IOPLL_TO_FPD] = {
+ .name = "iopll_to_fpd",
+ .control_reg = CRL_APB_IOPLL_TO_FPD_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {CLK_IOPLL, CLK_NA_PARENT}),
+ .nodes = &generic_domain_crossing_nodes,
+ .num_nodes = ARRAY_SIZE(generic_domain_crossing_nodes),
+ },
+ [CLK_RPLL_TO_FPD] = {
+ .name = "rpll_to_fpd",
+ .control_reg = CRL_APB_RPLL_TO_FPD_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {CLK_RPLL, CLK_NA_PARENT}),
+ .nodes = &rpll_to_fpd_nodes,
+ .num_nodes = ARRAY_SIZE(rpll_to_fpd_nodes),
+ },
+ [CLK_APLL_TO_LPD] = {
+ .name = "apll_to_lpd",
+ .control_reg = CRF_APB_APLL_TO_LPD_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {CLK_APLL, CLK_NA_PARENT}),
+ .nodes = &generic_domain_crossing_nodes,
+ .num_nodes = ARRAY_SIZE(generic_domain_crossing_nodes),
+ },
+ [CLK_DPLL_TO_LPD] = {
+ .name = "dpll_to_lpd",
+ .control_reg = CRF_APB_DPLL_TO_LPD_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {CLK_DPLL, CLK_NA_PARENT}),
+ .nodes = &generic_domain_crossing_nodes,
+ .num_nodes = ARRAY_SIZE(generic_domain_crossing_nodes),
+ },
+ [CLK_VPLL_TO_LPD] = {
+ .name = "vpll_to_lpd",
+ .control_reg = CRF_APB_VPLL_TO_LPD_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {CLK_VPLL, CLK_NA_PARENT}),
+ .nodes = &generic_domain_crossing_nodes,
+ .num_nodes = ARRAY_SIZE(generic_domain_crossing_nodes),
+ },
+ /*
+ * This clock control requires different registers for mux and gate.
+ * Use control and status registers for the same.
+ */
+ [CLK_GEM0_TX] = {
+ .name = "gem0_tx",
+ .control_reg = IOU_SLCR_GEM_CLK_CTRL,
+ .status_reg = CRL_APB_GEM0_REF_CTRL,
+ .parents = &((int32_t []) {
+ CLK_GEM0_REF | (PARENT_CLK_NODE3 << CLK_PARENTS_ID_LEN),
+ EXT_CLK_GEM0_EMIO | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem0_tx_nodes,
+ .num_nodes = ARRAY_SIZE(gem0_tx_nodes),
+ },
+ /*
+ * This clock control requires different registers for mux and gate.
+ * Use control and status registers for the same.
+ */
+ [CLK_GEM1_TX] = {
+ .name = "gem1_tx",
+ .control_reg = IOU_SLCR_GEM_CLK_CTRL,
+ .status_reg = CRL_APB_GEM1_REF_CTRL,
+ .parents = &((int32_t []) {
+ CLK_GEM1_REF | (PARENT_CLK_NODE3 << CLK_PARENTS_ID_LEN),
+ EXT_CLK_GEM1_EMIO | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem1_tx_nodes,
+ .num_nodes = ARRAY_SIZE(gem1_tx_nodes),
+ },
+ /*
+ * This clock control requires different registers for mux and gate.
+ * Use control and status registers for the same.
+ */
+ [CLK_GEM2_TX] = {
+ .name = "gem2_tx",
+ .control_reg = IOU_SLCR_GEM_CLK_CTRL,
+ .status_reg = CRL_APB_GEM2_REF_CTRL,
+ .parents = &((int32_t []) {
+ CLK_GEM2_REF | (PARENT_CLK_NODE3 << CLK_PARENTS_ID_LEN),
+ EXT_CLK_GEM2_EMIO | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem2_tx_nodes,
+ .num_nodes = ARRAY_SIZE(gem2_tx_nodes),
+ },
+ /*
+ * This clock control requires different registers for mux and gate.
+ * Use control and status registers for the same.
+ */
+ [CLK_GEM3_TX] = {
+ .name = "gem3_tx",
+ .control_reg = IOU_SLCR_GEM_CLK_CTRL,
+ .status_reg = CRL_APB_GEM3_REF_CTRL,
+ .parents = &((int32_t []) {
+ CLK_GEM3_REF | (PARENT_CLK_NODE3 << CLK_PARENTS_ID_LEN),
+ EXT_CLK_GEM3_EMIO | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem3_tx_nodes,
+ .num_nodes = ARRAY_SIZE(gem3_tx_nodes),
+ },
+ [CLK_ACPU_HALF] = {
+ .name = "acpu_half",
+ .control_reg = CRF_APB_ACPU_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_ACPU | PARENT_CLK_NODE2 << CLK_PARENTS_ID_LEN,
+ CLK_NA_PARENT
+ }),
+ .nodes = &acpu_half_nodes,
+ .num_nodes = ARRAY_SIZE(acpu_half_nodes),
+ },
+ [CLK_WDT] = {
+ .name = "wdt",
+ .control_reg = IOU_SLCR_WDT_CLK_SEL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_TOPSW_LSBUS,
+ EXT_CLK_SWDT0 | CLK_EXTERNAL_PARENT,
+ EXT_CLK_SWDT1 | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &wdt_nodes,
+ .num_nodes = ARRAY_SIZE(wdt_nodes),
+ },
+ [CLK_GPU_PP0_REF] = {
+ .name = "gpu_pp0_ref",
+ .control_reg = CRF_APB_GPU_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_GPU_REF | PARENT_CLK_NODE2 << CLK_PARENTS_ID_LEN,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gpu_pp0_nodes,
+ .num_nodes = ARRAY_SIZE(gpu_pp0_nodes),
+ },
+ [CLK_GPU_PP1_REF] = {
+ .name = "gpu_pp1_ref",
+ .control_reg = CRF_APB_GPU_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_GPU_REF | PARENT_CLK_NODE2 << CLK_PARENTS_ID_LEN,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gpu_pp1_nodes,
+ .num_nodes = ARRAY_SIZE(gpu_pp1_nodes),
+ },
+ [CLK_GEM_TSU] = {
+ .name = "gem_tsu",
+ .control_reg = IOU_SLCR_GEM_CLK_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_GEM_TSU_REF,
+ CLK_GEM_TSU_REF,
+ EXT_CLK_MIO26 | CLK_EXTERNAL_PARENT,
+ EXT_CLK_MIO50_OR_MIO51 | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem_tsu_nodes,
+ .num_nodes = ARRAY_SIZE(gem_tsu_nodes),
+ },
+ [CLK_CPU_R5_CORE] = {
+ .name = "cpu_r5_core",
+ .control_reg = CRL_APB_CPU_R5_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_CPU_R5 | PARENT_CLK_NODE2 << CLK_PARENTS_ID_LEN,
+ CLK_DUMMY_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &cpu_r5_core_nodes,
+ .num_nodes = ARRAY_SIZE(cpu_r5_core_nodes),
+ },
+ [CLK_CAN0_MIO] = {
+ .name = "can0_mio",
+ .control_reg = IOU_SLCR_CAN_MIO_CTRL,
+ .status_reg = 0,
+ .parents = &can_mio_parents,
+ .nodes = &can0_mio_nodes,
+ .num_nodes = ARRAY_SIZE(can0_mio_nodes),
+ },
+ [CLK_CAN1_MIO] = {
+ .name = "can1_mio",
+ .control_reg = IOU_SLCR_CAN_MIO_CTRL,
+ .status_reg = 0,
+ .parents = &can_mio_parents,
+ .nodes = &can1_mio_nodes,
+ .num_nodes = ARRAY_SIZE(can1_mio_nodes),
+ },
+ [CLK_CAN0] = {
+ .name = "can0",
+ .control_reg = IOU_SLCR_CAN_MIO_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_CAN0_REF,
+ CLK_CAN0_MIO,
+ CLK_NA_PARENT
+ }),
+ .nodes = &can0_nodes,
+ .num_nodes = ARRAY_SIZE(can0_nodes),
+ },
+ [CLK_CAN1] = {
+ .name = "can1",
+ .control_reg = IOU_SLCR_CAN_MIO_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_CAN1_REF,
+ CLK_CAN1_MIO,
+ CLK_NA_PARENT
+ }),
+ .nodes = &can1_nodes,
+ .num_nodes = ARRAY_SIZE(can1_nodes),
+ },
+};
+
+static struct pm_ext_clock ext_clocks[] = {
+ [EXT_CLK_INDEX(EXT_CLK_PSS_REF)] = {
+ .name = "pss_ref_clk",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_VIDEO)] = {
+ .name = "video_clk",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_PSS_ALT_REF)] = {
+ .name = "pss_alt_ref_clk",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_AUX_REF)] = {
+ .name = "aux_ref_clk",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_GT_CRX_REF)] = {
+ .name = "video_clk",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_SWDT0)] = {
+ .name = "swdt0_ext_clk",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_SWDT1)] = {
+ .name = "swdt1_ext_clk",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_GEM0_EMIO)] = {
+ .name = "gem0_emio_clk",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_GEM1_EMIO)] = {
+ .name = "gem1_emio_clk",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_GEM2_EMIO)] = {
+ .name = "gem2_emio_clk",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_GEM3_EMIO)] = {
+ .name = "gem3_emio_clk",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_MIO50_OR_MIO51)] = {
+ .name = "mio_clk_50_51",
+ },
+ EXT_CLK_MIO_DATA(0),
+ EXT_CLK_MIO_DATA(1),
+ EXT_CLK_MIO_DATA(2),
+ EXT_CLK_MIO_DATA(3),
+ EXT_CLK_MIO_DATA(4),
+ EXT_CLK_MIO_DATA(5),
+ EXT_CLK_MIO_DATA(6),
+ EXT_CLK_MIO_DATA(7),
+ EXT_CLK_MIO_DATA(8),
+ EXT_CLK_MIO_DATA(9),
+ EXT_CLK_MIO_DATA(10),
+ EXT_CLK_MIO_DATA(11),
+ EXT_CLK_MIO_DATA(12),
+ EXT_CLK_MIO_DATA(13),
+ EXT_CLK_MIO_DATA(14),
+ EXT_CLK_MIO_DATA(15),
+ EXT_CLK_MIO_DATA(16),
+ EXT_CLK_MIO_DATA(17),
+ EXT_CLK_MIO_DATA(18),
+ EXT_CLK_MIO_DATA(19),
+ EXT_CLK_MIO_DATA(20),
+ EXT_CLK_MIO_DATA(21),
+ EXT_CLK_MIO_DATA(22),
+ EXT_CLK_MIO_DATA(23),
+ EXT_CLK_MIO_DATA(24),
+ EXT_CLK_MIO_DATA(25),
+ EXT_CLK_MIO_DATA(26),
+ EXT_CLK_MIO_DATA(27),
+ EXT_CLK_MIO_DATA(28),
+ EXT_CLK_MIO_DATA(29),
+ EXT_CLK_MIO_DATA(30),
+ EXT_CLK_MIO_DATA(31),
+ EXT_CLK_MIO_DATA(32),
+ EXT_CLK_MIO_DATA(33),
+ EXT_CLK_MIO_DATA(34),
+ EXT_CLK_MIO_DATA(35),
+ EXT_CLK_MIO_DATA(36),
+ EXT_CLK_MIO_DATA(37),
+ EXT_CLK_MIO_DATA(38),
+ EXT_CLK_MIO_DATA(39),
+ EXT_CLK_MIO_DATA(40),
+ EXT_CLK_MIO_DATA(41),
+ EXT_CLK_MIO_DATA(42),
+ EXT_CLK_MIO_DATA(43),
+ EXT_CLK_MIO_DATA(44),
+ EXT_CLK_MIO_DATA(45),
+ EXT_CLK_MIO_DATA(46),
+ EXT_CLK_MIO_DATA(47),
+ EXT_CLK_MIO_DATA(48),
+ EXT_CLK_MIO_DATA(49),
+ EXT_CLK_MIO_DATA(50),
+ EXT_CLK_MIO_DATA(51),
+ EXT_CLK_MIO_DATA(52),
+ EXT_CLK_MIO_DATA(53),
+ EXT_CLK_MIO_DATA(54),
+ EXT_CLK_MIO_DATA(55),
+ EXT_CLK_MIO_DATA(56),
+ EXT_CLK_MIO_DATA(57),
+ EXT_CLK_MIO_DATA(58),
+ EXT_CLK_MIO_DATA(59),
+ EXT_CLK_MIO_DATA(60),
+ EXT_CLK_MIO_DATA(61),
+ EXT_CLK_MIO_DATA(62),
+ EXT_CLK_MIO_DATA(63),
+ EXT_CLK_MIO_DATA(64),
+ EXT_CLK_MIO_DATA(65),
+ EXT_CLK_MIO_DATA(66),
+ EXT_CLK_MIO_DATA(67),
+ EXT_CLK_MIO_DATA(68),
+ EXT_CLK_MIO_DATA(69),
+ EXT_CLK_MIO_DATA(70),
+ EXT_CLK_MIO_DATA(71),
+ EXT_CLK_MIO_DATA(72),
+ EXT_CLK_MIO_DATA(73),
+ EXT_CLK_MIO_DATA(74),
+ EXT_CLK_MIO_DATA(75),
+ EXT_CLK_MIO_DATA(76),
+ EXT_CLK_MIO_DATA(77),
+};
+
+/* Array of clock which are invalid for this variant */
+static uint32_t pm_clk_invalid_list[] = {CLK_USB0, CLK_USB1, CLK_CSU_SPB};
+
+/* Array of clocks which needs to be enabled at init */
+static uint32_t pm_clk_init_enable_list[] = {
+ CLK_ACPU,
+ CLK_DDR_REF,
+};
+
+/**
+ * pm_clock_valid - Check if clock is valid or not
+ * @clock_id Id of the clock to be queried
+ *
+ * This function is used to check if given clock is valid
+ * or not for the chip variant.
+ *
+ * List of invalid clocks are maintained in array list for
+ * different variants.
+ *
+ * Return: Returns 1 if clock is valid else 0.
+ */
+static bool pm_clock_valid(unsigned int clock_id)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(pm_clk_invalid_list); i++)
+ if (pm_clk_invalid_list[i] == clock_id)
+ return 0;
+
+ return 1;
+}
+
+/**
+ * pm_clock_init_enable - Check if clock needs to be enabled at init
+ * @clock_id Id of the clock to be queried
+ *
+ * This function is used to check if given clock needs to be enabled
+ * at boot up or not. Some clocks needs to be enabled at init.
+ *
+ * Return: Returns 1 if clock needs to be enabled at boot up else 0.
+ */
+static unsigned int pm_clock_init_enable(unsigned int clock_id)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(pm_clk_init_enable_list); i++)
+ if (pm_clk_init_enable_list[i] == clock_id)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * pm_clock_type - Get clock's type
+ * @clock_id Id of the clock to be queried
+ *
+ * This function is used to check type of clock (OUTPUT/EXTERNAL).
+ *
+ * Return: Returns type of clock (OUTPUT/EXTERNAL).
+ */
+static unsigned int pm_clock_type(unsigned int clock_id)
+{
+ return (clock_id < CLK_MAX_OUTPUT_CLK) ?
+ CLK_TYPE_OUTPUT : CLK_TYPE_EXTERNAL;
+}
+
+/**
+ * pm_api_clock_get_name() - PM call to request a clock's name
+ * @clock_id Clock ID
+ * @name Name of clock (max 16 bytes)
+ *
+ * This function is used by master to get nmae of clock specified
+ * by given clock ID.
+ *
+ * @return Returns success. In case of error, name data is 0.
+ */
+enum pm_ret_status pm_api_clock_get_name(unsigned int clock_id, char *name)
+{
+ if (clock_id == CLK_MAX)
+ memcpy(name, END_OF_CLK, CLK_NAME_LEN);
+ else if (!pm_clock_valid(clock_id))
+ memset(name, 0, CLK_NAME_LEN);
+ else if (clock_id < CLK_MAX_OUTPUT_CLK)
+ memcpy(name, clocks[clock_id].name, CLK_NAME_LEN);
+ else
+ memcpy(name, ext_clocks[clock_id - CLK_MAX_OUTPUT_CLK].name,
+ CLK_NAME_LEN);
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_api_clock_get_topology() - PM call to request a clock's topology
+ * @clock_id Clock ID
+ * @index Topology index for next toplogy node
+ * @topology Buffer to store nodes in topology and flags
+ *
+ * This function is used by master to get topology information for the
+ * clock specified by given clock ID. Each response would return 3
+ * topology nodes. To get next nodes, caller needs to call this API with
+ * index of next node. Index starts from 0.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_clock_get_topology(unsigned int clock_id,
+ unsigned int index,
+ uint32_t *topology)
+{
+ struct pm_clock_node *clock_nodes;
+ uint8_t num_nodes;
+ unsigned int i;
+
+ if (!pm_clock_valid(clock_id))
+ return PM_RET_ERROR_ARGS;
+
+ if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+
+ memset(topology, 0, CLK_TOPOLOGY_PAYLOAD_LEN);
+ clock_nodes = *clocks[clock_id].nodes;
+ num_nodes = clocks[clock_id].num_nodes;
+
+ /* Skip parent till index */
+ if (index >= num_nodes)
+ return PM_RET_SUCCESS;
+
+ for (i = 0; i < 3U; i++) {
+ if ((index + i) == num_nodes)
+ break;
+ topology[i] = clock_nodes[index + i].type;
+ topology[i] |= clock_nodes[index + i].clkflags <<
+ CLK_CLKFLAGS_SHIFT;
+ topology[i] |= clock_nodes[index + i].typeflags <<
+ CLK_TYPEFLAGS_SHIFT;
+ }
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_api_clock_get_fixedfactor_params() - PM call to request a clock's fixed
+ * factor parameters for fixed clock
+ * @clock_id Clock ID
+ * @mul Multiplication value
+ * @div Divisor value
+ *
+ * This function is used by master to get fixed factor parameers for the
+ * fixed clock. This API is application only for the fixed clock.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_clock_get_fixedfactor_params(unsigned int clock_id,
+ uint32_t *mul,
+ uint32_t *div)
+{
+ struct pm_clock_node *clock_nodes;
+ uint8_t num_nodes;
+ unsigned int type, i;
+
+ if (!pm_clock_valid(clock_id))
+ return PM_RET_ERROR_ARGS;
+
+ if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ clock_nodes = *clocks[clock_id].nodes;
+ num_nodes = clocks[clock_id].num_nodes;
+
+ for (i = 0; i < num_nodes; i++) {
+ type = clock_nodes[i].type;
+ if (type == TYPE_FIXEDFACTOR) {
+ *mul = clock_nodes[i].mult;
+ *div = clock_nodes[i].div;
+ break;
+ }
+ }
+
+ /* Clock is not fixed clock */
+ if (i == num_nodes)
+ return PM_RET_ERROR_ARGS;
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_api_clock_get_parents() - PM call to request a clock's first 3 parents
+ * @clock_id Clock ID
+ * @index Index of next parent
+ * @parents Parents of the given clock
+ *
+ * This function is used by master to get clock's parents information.
+ * This API will return 3 parents with a single response. To get other
+ * parents, master should call same API in loop with new parent index
+ * till error is returned.
+ *
+ * E.g First call should have index 0 which will return parents 0, 1 and
+ * 2. Next call, index should be 3 which will return parent 3,4 and 5 and
+ * so on.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_clock_get_parents(unsigned int clock_id,
+ unsigned int index,
+ uint32_t *parents)
+{
+ unsigned int i;
+ int32_t *clk_parents;
+
+ if (!pm_clock_valid(clock_id))
+ return PM_RET_ERROR_ARGS;
+
+ if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ clk_parents = *clocks[clock_id].parents;
+ if (clk_parents == NULL)
+ return PM_RET_ERROR_ARGS;
+
+ memset(parents, 0, CLK_PARENTS_PAYLOAD_LEN);
+
+ /* Skip parent till index */
+ for (i = 0; i < index; i++)
+ if (clk_parents[i] == CLK_NA_PARENT)
+ return PM_RET_SUCCESS;
+
+ for (i = 0; i < 3; i++) {
+ parents[i] = clk_parents[index + i];
+ if (clk_parents[index + i] == CLK_NA_PARENT)
+ break;
+ }
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_api_clock_get_attributes() - PM call to request a clock's attributes
+ * @clock_id Clock ID
+ * @attr Clock attributes
+ *
+ * This function is used by master to get clock's attributes
+ * (e.g. valid, clock type, etc).
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_clock_get_attributes(unsigned int clock_id,
+ uint32_t *attr)
+{
+ if (clock_id >= CLK_MAX)
+ return PM_RET_ERROR_ARGS;
+
+ /* Clock valid bit */
+ *attr = pm_clock_valid(clock_id);
+
+ /* If clock needs to be enabled during init */
+ *attr |= (pm_clock_init_enable(clock_id) << CLK_INIT_ENABLE_SHIFT);
+
+ /* Clock type (Output/External) */
+ *attr |= (pm_clock_type(clock_id) << CLK_TYPE_SHIFT);
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pll_get_lockbit() - Returns lockbit index for pll id
+ * @pll_id: Id of the pll
+ *
+ * This function return the PLL_LOCKED bit index in
+ * pll status register accosiated with given pll id.
+ *
+ * Return: Returns bit index
+ */
+static int pll_get_lockbit(unsigned int pll_id)
+{
+ switch (pll_id) {
+ case CLK_APLL_INT:
+ case CLK_IOPLL_INT:
+ return 0;
+ case CLK_DPLL_INT:
+ case CLK_RPLL_INT:
+ return 1;
+ case CLK_VPLL_INT:
+ return 2;
+ default:
+ return -1;
+ }
+}
+
+/**
+ * pm_api_pll_bypass_and_reset() - Bypass and reset PLL
+ * @clock_id: Id of the PLL
+ *
+ * This function is to bypass and reset PLL.
+ */
+static inline enum pm_ret_status
+pm_api_pll_bypass_and_reset(unsigned int clock_id, unsigned int flag)
+{
+ enum pm_ret_status ret = PM_RET_SUCCESS;
+ unsigned int reg, val;
+ int lockbit;
+
+ reg = clocks[clock_id].control_reg;
+
+ if (flag & CLK_PLL_RESET_ASSERT) {
+ ret = pm_mmio_write(reg, PLLCTRL_BP_MASK, PLLCTRL_BP_MASK);
+ if (ret != PM_RET_SUCCESS)
+ return ret;
+ ret = pm_mmio_write(reg, PLLCTRL_RESET_MASK,
+ PLLCTRL_RESET_MASK);
+ if (ret != PM_RET_SUCCESS)
+ return ret;
+ }
+ if (flag & CLK_PLL_RESET_RELEASE) {
+ ret = pm_mmio_write(reg, PLLCTRL_RESET_MASK,
+ ~PLLCTRL_RESET_MASK);
+ if (ret != PM_RET_SUCCESS)
+ return ret;
+
+ lockbit = pll_get_lockbit(clock_id);
+ do {
+ ret = pm_mmio_read(clocks[clock_id].status_reg, &val);
+ if (ret != PM_RET_SUCCESS)
+ return ret;
+ } while ((lockbit >= 0) && !(val & (1 << lockbit)));
+
+ ret = pm_mmio_write(reg, PLLCTRL_BP_MASK,
+ ~(unsigned int)PLLCTRL_BP_MASK);
+ }
+ return ret;
+}
+
+/**
+ * pm_api_clk_enable_disable() - Enable/Disable the clock for given id
+ * @clock_id: Id of the clock to be enabled
+ * @enable: Enable(1)/Disable(0)
+ *
+ * This function is to enable/disable the clock which is not PLL.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_api_clk_enable_disable(unsigned int clock_id,
+ unsigned int enable)
+{
+ enum pm_ret_status ret = PM_RET_SUCCESS;
+ struct pm_clock_node *nodes = *clocks[clock_id].nodes;
+ uint8_t num_nodes = clocks[clock_id].num_nodes;
+ unsigned int reg, val;
+ uint8_t i = 0;
+ uint8_t offset = NA_SHIFT, width = NA_WIDTH;
+
+ if (clock_id == CLK_GEM0_TX || clock_id == CLK_GEM1_TX ||
+ clock_id == CLK_GEM2_TX || clock_id == CLK_GEM3_TX)
+ reg = clocks[clock_id].status_reg;
+ else
+ reg = clocks[clock_id].control_reg;
+
+ for (i = 0; i < num_nodes; i++) {
+ if (nodes->type == TYPE_GATE) {
+ offset = nodes->offset;
+ width = nodes->width;
+ break;
+ }
+ nodes++;
+ }
+ if (width == NA_WIDTH)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ ret = pm_mmio_read(reg, &val);
+ if (ret != PM_RET_SUCCESS)
+ return ret;
+ if ((val & BIT_MASK(offset, width)) == enable)
+ return PM_RET_SUCCESS;
+
+ if (enable == 0)
+ val &= ~(BIT_MASK(offset, width));
+ else
+ val |= BIT_MASK(offset, width);
+
+ ret = pm_mmio_write(reg, BIT_MASK(offset, width), val);
+
+ return ret;
+}
+
+/**
+ * pm_api_clock_enable() - Enable the clock for given id
+ * @clock_id: Id of the clock to be enabled
+ *
+ * This function is used by master to enable the clock
+ * including peripherals and PLL clocks.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_clock_enable(unsigned int clock_id)
+{
+ enum pm_ret_status ret = PM_RET_SUCCESS;
+
+ if (!pm_clock_valid(clock_id))
+ return PM_RET_ERROR_ARGS;
+
+ if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ if (ISPLL(clock_id))
+ ret = pm_api_pll_bypass_and_reset(clock_id,
+ CLK_PLL_RESET_PULSE);
+ else
+ ret = pm_api_clk_enable_disable(clock_id, 1);
+
+ return ret;
+}
+
+/**
+ * pm_api_clock_disable - Disable the clock for given id
+ * @clock_id Id of the clock to be disable
+ *
+ * This function is used by master to disable the clock
+ * including peripherals and PLL clocks.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+
+enum pm_ret_status pm_api_clock_disable(unsigned int clock_id)
+{
+ enum pm_ret_status ret = PM_RET_SUCCESS;
+
+ if (!pm_clock_valid(clock_id))
+ return PM_RET_ERROR_ARGS;
+
+ if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ if (ISPLL(clock_id))
+ ret = pm_api_pll_bypass_and_reset(clock_id,
+ CLK_PLL_RESET_ASSERT);
+ else
+ ret = pm_api_clk_enable_disable(clock_id, 0);
+
+ return ret;
+}
+
+/**
+ * pm_api_get_pll_state() - Get state of PLL
+ * @clock_id Id of the PLL
+ * @state State of PLL(1: Enable, 0: Reset)
+ *
+ * This function is to check state of PLL.
+ */
+static inline enum pm_ret_status pm_api_get_pll_state(unsigned int clock_id,
+ unsigned int *state)
+{
+ enum pm_ret_status ret = PM_RET_SUCCESS;
+ unsigned int reg, val;
+
+ reg = clocks[clock_id].control_reg;
+
+ ret = pm_mmio_read(reg, &val);
+
+ /* state:
+ * 1 - PLL is enabled
+ * 0 - PLL is in reset state
+ */
+ *state = !(val & PLLCTRL_RESET_MASK);
+ return ret;
+}
+
+/**
+ * pm_api_get_clk_state() - Get the state of clock for given id
+ * @clock_id: Id of the clock to be enabled
+ * @state: Enable(1)/Disable(0)
+ *
+ * This function is to get state of the clock which is not PLL.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_api_get_clk_state(unsigned int clock_id,
+ unsigned int *state)
+{
+ enum pm_ret_status ret = PM_RET_SUCCESS;
+ struct pm_clock_node *nodes = *clocks[clock_id].nodes;
+ uint8_t num_nodes = clocks[clock_id].num_nodes;
+ unsigned int reg, val;
+ uint8_t i = 0;
+ uint8_t offset = NA_SHIFT, width = NA_WIDTH;
+
+ reg = clocks[clock_id].control_reg;
+
+ for (i = 0; i < num_nodes; i++) {
+ if (nodes->type == TYPE_GATE) {
+ offset = nodes->offset;
+ width = nodes->width;
+ }
+ nodes++;
+ }
+ if (width == NA_WIDTH)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ ret = pm_mmio_read(reg, &val);
+ *state = (val & BIT_MASK(offset, width)) >> offset;
+
+ return ret;
+}
+
+/**
+ * pm_api_clock_getstate - Get the clock state for given id
+ * @clock_id Id of the clock to be queried
+ * @state 1/0 (Enabled/Disabled)
+ *
+ * This function is used by master to get the state of clock
+ * including peripherals and PLL clocks.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_clock_getstate(unsigned int clock_id,
+ unsigned int *state)
+{
+ enum pm_ret_status ret = PM_RET_SUCCESS;
+
+ if (!pm_clock_valid(clock_id))
+ return PM_RET_ERROR_ARGS;
+
+ if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ if (ISPLL(clock_id))
+ ret = pm_api_get_pll_state(clock_id, state);
+ else
+ ret = pm_api_get_clk_state(clock_id, state);
+
+ return ret;
+}
+
+static enum pm_ret_status pm_api_clk_set_divider(unsigned int clock_id,
+ uint32_t divider)
+{
+ enum pm_ret_status ret = PM_RET_SUCCESS;
+ struct pm_clock_node *nodes;
+ uint8_t num_nodes;
+ uint16_t div1, div2;
+ unsigned int reg, mask = 0, val = 0, i;
+ uint8_t div1_width = NA_WIDTH, div1_offset = NA_SHIFT;
+ uint8_t div2_width = NA_WIDTH, div2_offset = NA_SHIFT;
+
+ div1 = (uint16_t)(divider & 0xFFFFU);
+ div2 = (uint16_t)((divider >> 16) & 0xFFFFU);
+
+ reg = clocks[clock_id].control_reg;
+
+ nodes = *clocks[clock_id].nodes;
+ num_nodes = clocks[clock_id].num_nodes;
+ for (i = 0; i < num_nodes; i++) {
+ if (nodes->type == TYPE_DIV1) {
+ div1_offset = nodes->offset;
+ div1_width = nodes->width;
+ }
+ if (nodes->type == TYPE_DIV2) {
+ div2_offset = nodes->offset;
+ div2_width = nodes->width;
+ }
+ nodes++;
+ }
+
+ if (div1 != (uint16_t)-1) {
+ if (div1_width == NA_WIDTH)
+ return PM_RET_ERROR_NOTSUPPORTED;
+ val |= div1 << div1_offset;
+ mask |= BIT_MASK(div1_offset, div1_width);
+ }
+ if (div2 != (uint16_t)-1) {
+ if (div2_width == NA_WIDTH)
+ return PM_RET_ERROR_NOTSUPPORTED;
+ val |= div2 << div2_offset;
+ mask |= BIT_MASK(div2_offset, div2_width);
+ }
+ ret = pm_mmio_write(reg, mask, val);
+
+ return ret;
+}
+
+static enum pm_ret_status pm_api_pll_set_divider(unsigned int clock_id,
+ unsigned int divider)
+{
+ unsigned int reg = clocks[clock_id].control_reg;
+
+ return pm_mmio_write(reg, PLL_FBDIV_MASK, divider << PLL_FBDIV_SHIFT);
+}
+
+/**
+ * pm_api_clock_setdivider - Set the clock divider for given id
+ * @clock_id Id of the clock
+ * @divider Divider value
+ *
+ * This function is used by master to set divider for any clock
+ * to achieve desired rate.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_clock_setdivider(unsigned int clock_id,
+ unsigned int divider)
+{
+ enum pm_ret_status ret;
+
+ if (!pm_clock_valid(clock_id))
+ return PM_RET_ERROR_ARGS;
+
+ if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ if (ISPLL(clock_id))
+ ret = pm_api_pll_set_divider(clock_id, divider);
+ else
+ ret = pm_api_clk_set_divider(clock_id, divider);
+
+ return ret;
+}
+
+static enum pm_ret_status pm_api_clk_get_divider(unsigned int clock_id,
+ uint32_t *divider)
+{
+ enum pm_ret_status ret = PM_RET_SUCCESS;
+ struct pm_clock_node *nodes;
+ uint8_t num_nodes;
+ unsigned int reg, val, i, div1 = 0, div2 = 0;
+ uint8_t div1_width = NA_WIDTH, div1_offset = NA_SHIFT;
+ uint8_t div2_width = NA_WIDTH, div2_offset = NA_SHIFT;
+
+ reg = clocks[clock_id].control_reg;
+
+ nodes = *clocks[clock_id].nodes;
+ num_nodes = clocks[clock_id].num_nodes;
+ for (i = 0; i < num_nodes; i++) {
+ if (nodes->type == TYPE_DIV1) {
+ div1_offset = nodes->offset;
+ div1_width = nodes->width;
+ }
+ if (nodes->type == TYPE_DIV2) {
+ div2_offset = nodes->offset;
+ div2_width = nodes->width;
+ }
+ nodes++;
+ }
+
+ ret = pm_mmio_read(reg, &val);
+
+ if (div1_width == NA_WIDTH)
+ return PM_RET_ERROR_ARGS;
+
+ div1 = (val & BIT_MASK(div1_offset, div1_width)) >> div1_offset;
+
+ if (div2_width != NA_WIDTH)
+ div2 = (val & BIT_MASK(div2_offset, div2_width)) >> div2_offset;
+
+ *divider = div1 | (div2 << 16);
+
+ return ret;
+}
+
+static enum pm_ret_status pm_api_pll_get_divider(unsigned int clock_id,
+ unsigned int *divider)
+{
+ enum pm_ret_status ret = PM_RET_SUCCESS;
+ unsigned int reg, val;
+
+ reg = clocks[clock_id].control_reg;
+
+ ret = pm_mmio_read(reg, &val);
+ *divider = (val & PLL_FBDIV_MASK) >> PLL_FBDIV_SHIFT;
+
+ return ret;
+}
+
+/**
+ * pm_api_clock_getdivider - Get the clock divider for given id
+ * @clock_id Id of the clock
+ * @divider Divider value
+ *
+ * This function is used by master to get divider values
+ * for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_clock_getdivider(unsigned int clock_id,
+ unsigned int *divider)
+{
+ enum pm_ret_status ret;
+
+ if (!pm_clock_valid(clock_id))
+ return PM_RET_ERROR_ARGS;
+
+ if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ if (ISPLL(clock_id))
+ ret = pm_api_pll_get_divider(clock_id, divider);
+ else
+ ret = pm_api_clk_get_divider(clock_id, divider);
+
+ return ret;
+}
+
+/**
+ * pm_api_clock_setrate - Set the clock rate for given id
+ * @clock_id Id of the clock
+ * @rate Rate value in hz
+ *
+ * This function is used by master to set rate for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_clock_setrate(unsigned int clock_id,
+ uint64_t rate)
+{
+ return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_api_clock_getrate - Get the clock rate for given id
+ * @clock_id Id of the clock
+ * @rate rate value in hz
+ *
+ * This function is used by master to get rate
+ * for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_clock_getrate(unsigned int clock_id,
+ uint64_t *rate)
+{
+ return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_api_clock_setparent - Set the clock parent for given id
+ * @clock_id Id of the clock
+ * @parent_id parent id
+ *
+ * This function is used by master to set parent for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_clock_setparent(unsigned int clock_id,
+ unsigned int parent_idx)
+{
+ enum pm_ret_status ret = PM_RET_SUCCESS;
+ struct pm_clock_node *nodes;
+ uint8_t num_nodes;
+ unsigned int reg, val;
+ int32_t *clk_parents;
+ unsigned int i = 0;
+ uint8_t offset = NA_SHIFT, width = NA_WIDTH;
+
+ if (!pm_clock_valid(clock_id))
+ return PM_RET_ERROR_ARGS;
+
+ if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ clk_parents = *clocks[clock_id].parents;
+
+ for (i = 0; i <= parent_idx; i++)
+ if (clk_parents[i] == CLK_NA_PARENT)
+ return PM_RET_ERROR_ARGS;
+
+ nodes = *clocks[clock_id].nodes;
+ num_nodes = clocks[clock_id].num_nodes;
+ for (i = 0; i < num_nodes; i++) {
+ if (nodes->type == TYPE_MUX) {
+ offset = nodes->offset;
+ width = nodes->width;
+ }
+ nodes++;
+ }
+ if (width == NA_WIDTH)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ reg = clocks[clock_id].control_reg;
+ val = parent_idx << offset;
+ ret = pm_mmio_write(reg, BIT_MASK(offset, width), val);
+
+ return ret;
+}
+
+/**
+ * pm_api_clock_getparent - Get the clock parent for given id
+ * @clock_id Id of the clock
+ * @parent_id parent id
+ *
+ * This function is used by master to get parent index
+ * for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_clock_getparent(unsigned int clock_id,
+ unsigned int *parent_idx)
+{
+ enum pm_ret_status ret = PM_RET_SUCCESS;
+ struct pm_clock_node *nodes;
+ uint8_t num_nodes;
+ unsigned int reg, val;
+ uint8_t i = 0, offset = NA_SHIFT, width = NA_WIDTH;
+
+ if (!pm_clock_valid(clock_id))
+ return PM_RET_ERROR_ARGS;
+
+ if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ nodes = *clocks[clock_id].nodes;
+ num_nodes = clocks[clock_id].num_nodes;
+
+ for (i = 0; i < num_nodes; i++) {
+ if (nodes->type == TYPE_MUX) {
+ offset = nodes->offset;
+ width = nodes->width;
+ }
+ nodes++;
+ }
+ if (width == NA_WIDTH)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ reg = clocks[clock_id].control_reg;
+ ret = pm_mmio_read(reg, &val);
+ val >>= offset;
+ val &= ((1U << width) - 1);
+
+ *parent_idx = val;
+
+ return ret;
+}
+
+/**
+ * pm_api_clk_set_pll_mode() - Set PLL mode
+ * @pll PLL id
+ * @mode Mode fraction/integar
+ *
+ * This function sets PLL mode.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_clk_set_pll_mode(unsigned int pll,
+ unsigned int mode)
+{
+ enum pm_ret_status ret = PM_RET_SUCCESS;
+ unsigned int reg;
+
+ if (!pm_clock_valid(pll))
+ return PM_RET_ERROR_ARGS;
+
+ if (pm_clock_type(pll) != CLK_TYPE_OUTPUT)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ if (!ISPLL(pll))
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ if (mode != PLL_FRAC_MODE && mode != PLL_INT_MODE)
+ return PM_RET_ERROR_ARGS;
+
+ reg = clocks[pll].control_reg + PLL_FRAC_OFFSET;
+
+ ret = pm_mmio_write(reg, PLL_FRAC_MODE_MASK,
+ mode << PLL_FRAC_MODE_SHIFT);
+
+ return ret;
+}
+
+/**
+ * pm_ioctl_get_pll_mode() - Get PLL mode
+ * @pll PLL id
+ * @mode Mode fraction/integar
+ *
+ * This function returns current PLL mode.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_clk_get_pll_mode(unsigned int pll,
+ unsigned int *mode)
+{
+ enum pm_ret_status ret = PM_RET_SUCCESS;
+ unsigned int val, reg;
+
+ if (!pm_clock_valid(pll))
+ return PM_RET_ERROR_ARGS;
+
+ if (pm_clock_type(pll) != CLK_TYPE_OUTPUT)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ if (!ISPLL(pll))
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ reg = clocks[pll].control_reg + PLL_FRAC_OFFSET;
+
+ ret = pm_mmio_read(reg, &val);
+ val = val & PLL_FRAC_MODE_MASK;
+ if (val == 0)
+ *mode = PLL_INT_MODE;
+ else
+ *mode = PLL_FRAC_MODE;
+
+ return ret;
+}
+
+/**
+ * pm_api_clk_set_pll_frac_data() - Set PLL fraction data
+ * @pll PLL id
+ * @data fraction data
+ *
+ * This function sets fraction data. It is valid for fraction
+ * mode only.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_clk_set_pll_frac_data(unsigned int pll,
+ unsigned int data)
+{
+ enum pm_ret_status ret = PM_RET_SUCCESS;
+ unsigned int val, reg, mode = 0;
+
+ if (!pm_clock_valid(pll))
+ return PM_RET_ERROR_ARGS;
+
+ if (pm_clock_type(pll) != CLK_TYPE_OUTPUT)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ if (!ISPLL(pll))
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ ret = pm_api_clk_get_pll_mode(pll, &mode);
+ if (ret != PM_RET_SUCCESS)
+ return ret;
+ if (mode == PLL_FRAC_MODE) {
+ reg = clocks[pll].control_reg + PLL_FRAC_OFFSET;
+ val = data << PLL_FRAC_DATA_SHIFT;
+ ret = pm_mmio_write(reg, PLL_FRAC_DATA_MASK, val);
+ } else {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ return ret;
+}
+
+/**
+ * pm_api_clk_get_pll_frac_data() - Get PLL fraction data
+ * @pll PLL id
+ * @data fraction data
+ *
+ * This function returns fraction data value.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_clk_get_pll_frac_data(unsigned int pll,
+ unsigned int *data)
+{
+ enum pm_ret_status ret = PM_RET_SUCCESS;
+ unsigned int val, reg;
+
+ if (!pm_clock_valid(pll))
+ return PM_RET_ERROR_ARGS;
+
+ if (pm_clock_type(pll) != CLK_TYPE_OUTPUT)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ if (!ISPLL(pll))
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ reg = clocks[pll].control_reg + PLL_FRAC_OFFSET;
+
+ ret = pm_mmio_read(reg, &val);
+ *data = (val & PLL_FRAC_DATA_MASK);
+
+ return ret;
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.h b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h
new file mode 100644
index 0000000..56f850a
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * ZynqMP system level PM-API functions for clock control.
+ */
+
+#ifndef _PM_API_CLOCK_H_
+#define _PM_API_CLOCK_H_
+
+#include <utils_def.h>
+#include "pm_common.h"
+
+#define CLK_NAME_LEN U(15)
+#define MAX_PARENTS U(100)
+#define CLK_NA_PARENT -1
+#define CLK_DUMMY_PARENT -2
+
+/* Flags for parent id */
+#define PARENT_CLK_SELF U(0)
+#define PARENT_CLK_NODE1 U(1)
+#define PARENT_CLK_NODE2 U(2)
+#define PARENT_CLK_NODE3 U(3)
+#define PARENT_CLK_NODE4 U(4)
+#define PARENT_CLK_EXTERNAL U(5)
+#define PARENT_CLK_MIO0_MIO77 U(6)
+
+#define CLK_SET_RATE_GATE BIT(0) /* must be gated across rate change */
+#define CLK_SET_PARENT_GATE BIT(1) /* must be gated across re-parent */
+#define CLK_SET_RATE_PARENT BIT(2) /* propagate rate change up one level */
+#define CLK_IGNORE_UNUSED BIT(3) /* do not gate even if unused */
+/* unused */
+#define CLK_IS_BASIC BIT(5) /* Basic clk, can't do a to_clk_foo() */
+#define CLK_GET_RATE_NOCACHE BIT(6) /* do not use the cached clk rate */
+#define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */
+#define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */
+#define CLK_RECALC_NEW_RATES BIT(9) /* recalc rates after notifications */
+#define CLK_SET_RATE_UNGATE BIT(10) /* clock needs to run to set rate */
+#define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */
+/* parents need enable during gate/ungate, set rate and re-parent */
+#define CLK_OPS_PARENT_ENABLE BIT(12)
+#define CLK_FRAC BIT(13)
+
+#define CLK_DIVIDER_ONE_BASED BIT(0)
+#define CLK_DIVIDER_POWER_OF_TWO BIT(1)
+#define CLK_DIVIDER_ALLOW_ZERO BIT(2)
+#define CLK_DIVIDER_HIWORD_MASK BIT(3)
+#define CLK_DIVIDER_ROUND_CLOSEST BIT(4)
+#define CLK_DIVIDER_READ_ONLY BIT(5)
+#define CLK_DIVIDER_MAX_AT_ZERO BIT(6)
+
+#define END_OF_CLK "END_OF_CLK"
+
+//CLock Ids
+enum {
+ CLK_IOPLL,
+ CLK_RPLL,
+ CLK_APLL,
+ CLK_DPLL,
+ CLK_VPLL,
+ CLK_IOPLL_TO_FPD,
+ CLK_RPLL_TO_FPD,
+ CLK_APLL_TO_LPD,
+ CLK_DPLL_TO_LPD,
+ CLK_VPLL_TO_LPD,
+ CLK_ACPU,
+ CLK_ACPU_HALF,
+ CLK_DBG_FPD,
+ CLK_DBG_LPD,
+ CLK_DBG_TRACE,
+ CLK_DBG_TSTMP,
+ CLK_DP_VIDEO_REF,
+ CLK_DP_AUDIO_REF,
+ CLK_DP_STC_REF,
+ CLK_GDMA_REF,
+ CLK_DPDMA_REF,
+ CLK_DDR_REF,
+ CLK_SATA_REF,
+ CLK_PCIE_REF,
+ CLK_GPU_REF,
+ CLK_GPU_PP0_REF,
+ CLK_GPU_PP1_REF,
+ CLK_TOPSW_MAIN,
+ CLK_TOPSW_LSBUS,
+ CLK_GTGREF0_REF,
+ CLK_LPD_SWITCH,
+ CLK_LPD_LSBUS,
+ CLK_USB0_BUS_REF,
+ CLK_USB1_BUS_REF,
+ CLK_USB3_DUAL_REF,
+ CLK_USB0,
+ CLK_USB1,
+ CLK_CPU_R5,
+ CLK_CPU_R5_CORE,
+ CLK_CSU_SPB,
+ CLK_CSU_PLL,
+ CLK_PCAP,
+ CLK_IOU_SWITCH,
+ CLK_GEM_TSU_REF,
+ CLK_GEM_TSU,
+ CLK_GEM0_REF,
+ CLK_GEM1_REF,
+ CLK_GEM2_REF,
+ CLK_GEM3_REF,
+ CLK_GEM0_TX,
+ CLK_GEM1_TX,
+ CLK_GEM2_TX,
+ CLK_GEM3_TX,
+ CLK_QSPI_REF,
+ CLK_SDIO0_REF,
+ CLK_SDIO1_REF,
+ CLK_UART0_REF,
+ CLK_UART1_REF,
+ CLK_SPI0_REF,
+ CLK_SPI1_REF,
+ CLK_NAND_REF,
+ CLK_I2C0_REF,
+ CLK_I2C1_REF,
+ CLK_CAN0_REF,
+ CLK_CAN1_REF,
+ CLK_CAN0,
+ CLK_CAN1,
+ CLK_DLL_REF,
+ CLK_ADMA_REF,
+ CLK_TIMESTAMP_REF,
+ CLK_AMS_REF,
+ CLK_PL0_REF,
+ CLK_PL1_REF,
+ CLK_PL2_REF,
+ CLK_PL3_REF,
+ CLK_WDT,
+ CLK_IOPLL_INT,
+ CLK_IOPLL_PRE_SRC,
+ CLK_IOPLL_HALF,
+ CLK_IOPLL_INT_MUX,
+ CLK_IOPLL_POST_SRC,
+ CLK_RPLL_INT,
+ CLK_RPLL_PRE_SRC,
+ CLK_RPLL_HALF,
+ CLK_RPLL_INT_MUX,
+ CLK_RPLL_POST_SRC,
+ CLK_APLL_INT,
+ CLK_APLL_PRE_SRC,
+ CLK_APLL_HALF,
+ CLK_APLL_INT_MUX,
+ CLK_APLL_POST_SRC,
+ CLK_DPLL_INT,
+ CLK_DPLL_PRE_SRC,
+ CLK_DPLL_HALF,
+ CLK_DPLL_INT_MUX,
+ CLK_DPLL_POST_SRC,
+ CLK_VPLL_INT,
+ CLK_VPLL_PRE_SRC,
+ CLK_VPLL_HALF,
+ CLK_VPLL_INT_MUX,
+ CLK_VPLL_POST_SRC,
+ CLK_CAN0_MIO,
+ CLK_CAN1_MIO,
+ END_OF_OUTPUT_CLKS,
+};
+
+#define CLK_MAX_OUTPUT_CLK (unsigned int)(END_OF_OUTPUT_CLKS)
+
+//External clock ids
+enum {
+ EXT_CLK_PSS_REF = END_OF_OUTPUT_CLKS,
+ EXT_CLK_VIDEO,
+ EXT_CLK_PSS_ALT_REF,
+ EXT_CLK_AUX_REF,
+ EXT_CLK_GT_CRX_REF,
+ EXT_CLK_SWDT0,
+ EXT_CLK_SWDT1,
+ EXT_CLK_GEM0_EMIO,
+ EXT_CLK_GEM1_EMIO,
+ EXT_CLK_GEM2_EMIO,
+ EXT_CLK_GEM3_EMIO,
+ EXT_CLK_MIO50_OR_MIO51,
+ EXT_CLK_MIO0,
+ EXT_CLK_MIO1,
+ EXT_CLK_MIO2,
+ EXT_CLK_MIO3,
+ EXT_CLK_MIO4,
+ EXT_CLK_MIO5,
+ EXT_CLK_MIO6,
+ EXT_CLK_MIO7,
+ EXT_CLK_MIO8,
+ EXT_CLK_MIO9,
+ EXT_CLK_MIO10,
+ EXT_CLK_MIO11,
+ EXT_CLK_MIO12,
+ EXT_CLK_MIO13,
+ EXT_CLK_MIO14,
+ EXT_CLK_MIO15,
+ EXT_CLK_MIO16,
+ EXT_CLK_MIO17,
+ EXT_CLK_MIO18,
+ EXT_CLK_MIO19,
+ EXT_CLK_MIO20,
+ EXT_CLK_MIO21,
+ EXT_CLK_MIO22,
+ EXT_CLK_MIO23,
+ EXT_CLK_MIO24,
+ EXT_CLK_MIO25,
+ EXT_CLK_MIO26,
+ EXT_CLK_MIO27,
+ EXT_CLK_MIO28,
+ EXT_CLK_MIO29,
+ EXT_CLK_MIO30,
+ EXT_CLK_MIO31,
+ EXT_CLK_MIO32,
+ EXT_CLK_MIO33,
+ EXT_CLK_MIO34,
+ EXT_CLK_MIO35,
+ EXT_CLK_MIO36,
+ EXT_CLK_MIO37,
+ EXT_CLK_MIO38,
+ EXT_CLK_MIO39,
+ EXT_CLK_MIO40,
+ EXT_CLK_MIO41,
+ EXT_CLK_MIO42,
+ EXT_CLK_MIO43,
+ EXT_CLK_MIO44,
+ EXT_CLK_MIO45,
+ EXT_CLK_MIO46,
+ EXT_CLK_MIO47,
+ EXT_CLK_MIO48,
+ EXT_CLK_MIO49,
+ EXT_CLK_MIO50,
+ EXT_CLK_MIO51,
+ EXT_CLK_MIO52,
+ EXT_CLK_MIO53,
+ EXT_CLK_MIO54,
+ EXT_CLK_MIO55,
+ EXT_CLK_MIO56,
+ EXT_CLK_MIO57,
+ EXT_CLK_MIO58,
+ EXT_CLK_MIO59,
+ EXT_CLK_MIO60,
+ EXT_CLK_MIO61,
+ EXT_CLK_MIO62,
+ EXT_CLK_MIO63,
+ EXT_CLK_MIO64,
+ EXT_CLK_MIO65,
+ EXT_CLK_MIO66,
+ EXT_CLK_MIO67,
+ EXT_CLK_MIO68,
+ EXT_CLK_MIO69,
+ EXT_CLK_MIO70,
+ EXT_CLK_MIO71,
+ EXT_CLK_MIO72,
+ EXT_CLK_MIO73,
+ EXT_CLK_MIO74,
+ EXT_CLK_MIO75,
+ EXT_CLK_MIO76,
+ EXT_CLK_MIO77,
+ END_OF_CLKS,
+};
+
+#define CLK_MAX (unsigned int)(END_OF_CLKS)
+
+//CLock types
+#define CLK_TYPE_OUTPUT 0U
+#define CLK_TYPE_EXTERNAL 1U
+
+//Topology types
+#define TYPE_INVALID 0U
+#define TYPE_MUX 1U
+#define TYPE_PLL 2U
+#define TYPE_FIXEDFACTOR 3U
+#define TYPE_DIV1 4U
+#define TYPE_DIV2 5U
+#define TYPE_GATE 6U
+
+
+enum pm_ret_status pm_api_clock_get_name(unsigned int clock_id, char *name);
+enum pm_ret_status pm_api_clock_get_topology(unsigned int clock_id,
+ unsigned int index,
+ uint32_t *topology);
+enum pm_ret_status pm_api_clock_get_fixedfactor_params(unsigned int clock_id,
+ uint32_t *mul,
+ uint32_t *div);
+enum pm_ret_status pm_api_clock_get_parents(unsigned int clock_id,
+ unsigned int index,
+ uint32_t *parents);
+enum pm_ret_status pm_api_clock_get_attributes(unsigned int clock_id,
+ uint32_t *attr);
+enum pm_ret_status pm_api_clock_enable(unsigned int clock_id);
+enum pm_ret_status pm_api_clock_disable(unsigned int clock_id);
+enum pm_ret_status pm_api_clock_getstate(unsigned int clock_id,
+ unsigned int *state);
+enum pm_ret_status pm_api_clock_setdivider(unsigned int clock_id,
+ unsigned int divider);
+enum pm_ret_status pm_api_clock_getdivider(unsigned int clock_id,
+ unsigned int *divider);
+enum pm_ret_status pm_api_clock_setrate(unsigned int clock_id,
+ uint64_t rate);
+enum pm_ret_status pm_api_clock_getrate(unsigned int clock_id,
+ uint64_t *rate);
+enum pm_ret_status pm_api_clock_setparent(unsigned int clock_id,
+ unsigned int parent_idx);
+enum pm_ret_status pm_api_clock_getparent(unsigned int clock_id,
+ unsigned int *parent_idx);
+enum pm_ret_status pm_api_clk_set_pll_mode(unsigned int pll,
+ unsigned int mode);
+enum pm_ret_status pm_api_clk_get_pll_mode(unsigned int pll,
+ unsigned int *mode);
+enum pm_ret_status pm_api_clk_set_pll_frac_data(unsigned int pll,
+ unsigned int data);
+enum pm_ret_status pm_api_clk_get_pll_frac_data(unsigned int pll,
+ unsigned int *data);
+
+#endif /* _PM_API_CLOCK_H_ */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
new file mode 100644
index 0000000..cdbb515
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
@@ -0,0 +1,549 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * ZynqMP system level PM-API functions for ioctl.
+ */
+
+#include <arch_helpers.h>
+#include <delay_timer.h>
+#include <mmio.h>
+#include <platform.h>
+#include "pm_api_clock.h"
+#include "pm_api_ioctl.h"
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include "pm_common.h"
+#include "pm_ipi.h"
+#include "../zynqmp_def.h"
+
+/**
+ * pm_ioctl_get_rpu_oper_mode () - Get current RPU operation mode
+ * @mode Buffer to store value of oper mode(Split/Lock-step)
+ *
+ * This function provides current configured RPU operational mode.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_get_rpu_oper_mode(unsigned int *mode)
+{
+ unsigned int val;
+
+ val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
+ val &= ZYNQMP_SLSPLIT_MASK;
+ if (val == 0)
+ *mode = PM_RPU_MODE_LOCKSTEP;
+ else
+ *mode = PM_RPU_MODE_SPLIT;
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_ioctl_set_rpu_oper_mode () - Configure RPU operation mode
+ * @mode Value to set for oper mode(Split/Lock-step)
+ *
+ * This function configures RPU operational mode(Split/Lock-step).
+ * It also sets TCM combined mode in RPU lock-step and TCM non-combined
+ * mode for RPU split mode. In case of Lock step mode, RPU1's output is
+ * clamped.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_set_rpu_oper_mode(unsigned int mode)
+{
+ unsigned int val;
+
+ if (mmio_read_32(CRL_APB_RST_LPD_TOP) && CRL_APB_RPU_AMBA_RESET)
+ return PM_RET_ERROR_ACCESS;
+
+ val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
+
+ if (mode == PM_RPU_MODE_SPLIT) {
+ val |= ZYNQMP_SLSPLIT_MASK;
+ val &= ~ZYNQMP_TCM_COMB_MASK;
+ val &= ~ZYNQMP_SLCLAMP_MASK;
+ } else if (mode == PM_RPU_MODE_LOCKSTEP) {
+ val &= ~ZYNQMP_SLSPLIT_MASK;
+ val |= ZYNQMP_TCM_COMB_MASK;
+ val |= ZYNQMP_SLCLAMP_MASK;
+ } else {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val);
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_ioctl_config_boot_addr() - Configure RPU boot address
+ * @nid Node ID of RPU
+ * @value Value to set for boot address (TCM/OCM)
+ *
+ * This function configures RPU boot address(memory).
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_config_boot_addr(enum pm_node_id nid,
+ unsigned int value)
+{
+ unsigned int rpu_cfg_addr, val;
+
+ if (nid == NODE_RPU_0)
+ rpu_cfg_addr = ZYNQMP_RPU0_CFG;
+ else if (nid == NODE_RPU_1)
+ rpu_cfg_addr = ZYNQMP_RPU1_CFG;
+ else
+ return PM_RET_ERROR_ARGS;
+
+ val = mmio_read_32(rpu_cfg_addr);
+
+ if (value == PM_RPU_BOOTMEM_LOVEC)
+ val &= ~ZYNQMP_VINITHI_MASK;
+ else if (value == PM_RPU_BOOTMEM_HIVEC)
+ val |= ZYNQMP_VINITHI_MASK;
+ else
+ return PM_RET_ERROR_ARGS;
+
+ mmio_write_32(rpu_cfg_addr, val);
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_ioctl_config_tcm_comb() - Configure TCM combined mode
+ * @value Value to set (Split/Combined)
+ *
+ * This function configures TCM to be in split mode or combined
+ * mode.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_config_tcm_comb(unsigned int value)
+{
+ unsigned int val;
+
+ val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
+
+ if (value == PM_RPU_TCM_SPLIT)
+ val &= ~ZYNQMP_TCM_COMB_MASK;
+ else if (value == PM_RPU_TCM_COMB)
+ val |= ZYNQMP_TCM_COMB_MASK;
+ else
+ return PM_RET_ERROR_ARGS;
+
+ mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val);
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_ioctl_set_tapdelay_bypass() - Enable/Disable tap delay bypass
+ * @type Type of tap delay to enable/disable (e.g. QSPI)
+ * @value Enable/Disable
+ *
+ * This function enable/disable tap delay bypass.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_set_tapdelay_bypass(unsigned int type,
+ unsigned int value)
+{
+ if ((value != PM_TAPDELAY_BYPASS_ENABLE &&
+ value != PM_TAPDELAY_BYPASS_DISABLE) || type >= PM_TAPDELAY_MAX)
+ return PM_RET_ERROR_ARGS;
+
+ return pm_mmio_write(IOU_TAPDLY_BYPASS, TAP_DELAY_MASK, value << type);
+}
+
+/**
+ * pm_ioctl_set_sgmii_mode() - Set SGMII mode for the GEM device
+ * @nid Node ID of the device
+ * @value Enable/Disable
+ *
+ * This function enable/disable SGMII mode for the GEM device.
+ * While enabling SGMII mode, it also ties the GEM PCS Signal
+ * Detect to 1 and selects EMIO for RX clock generation.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_set_sgmii_mode(enum pm_node_id nid,
+ unsigned int value)
+{
+ unsigned int val, mask, shift;
+ enum pm_ret_status ret;
+
+ if (value != PM_SGMII_DISABLE && value != PM_SGMII_ENABLE)
+ return PM_RET_ERROR_ARGS;
+
+ switch (nid) {
+ case NODE_ETH_0:
+ shift = 0;
+ break;
+ case NODE_ETH_1:
+ shift = 1;
+ break;
+ case NODE_ETH_2:
+ shift = 2;
+ break;
+ case NODE_ETH_3:
+ shift = 3;
+ break;
+ default:
+ return PM_RET_ERROR_ARGS;
+ }
+
+ if (value == PM_SGMII_DISABLE) {
+ mask = GEM_SGMII_MASK << GEM_CLK_CTRL_OFFSET * shift;
+ ret = pm_mmio_write(IOU_GEM_CLK_CTRL, mask, 0U);
+ } else {
+ /* Tie the GEM PCS Signal Detect to 1 */
+ mask = SGMII_SD_MASK << SGMII_SD_OFFSET * shift;
+ val = SGMII_PCS_SD_1 << SGMII_SD_OFFSET * shift;
+ ret = pm_mmio_write(IOU_GEM_CTRL, mask, val);
+ if (ret != PM_RET_SUCCESS)
+ return ret;
+
+ /* Set the GEM to SGMII mode */
+ mask = GEM_CLK_CTRL_MASK << GEM_CLK_CTRL_OFFSET * shift;
+ val = GEM_RX_SRC_SEL_GTR | GEM_SGMII_MODE;
+ val <<= GEM_CLK_CTRL_OFFSET * shift;
+ ret = pm_mmio_write(IOU_GEM_CLK_CTRL, mask, val);
+ }
+
+ return ret;
+}
+
+/**
+ * pm_ioctl_sd_dll_reset() - Reset DLL logic
+ * @nid Node ID of the device
+ * @type Reset type
+ *
+ * This function resets DLL logic for the SD device.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_sd_dll_reset(enum pm_node_id nid,
+ unsigned int type)
+{
+ unsigned int mask, val;
+ enum pm_ret_status ret;
+
+ if (nid == NODE_SD_0) {
+ mask = ZYNQMP_SD0_DLL_RST_MASK;
+ val = ZYNQMP_SD0_DLL_RST;
+ } else if (nid == NODE_SD_1) {
+ mask = ZYNQMP_SD1_DLL_RST_MASK;
+ val = ZYNQMP_SD1_DLL_RST;
+ } else {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ switch (type) {
+ case PM_DLL_RESET_ASSERT:
+ case PM_DLL_RESET_PULSE:
+ ret = pm_mmio_write(ZYNQMP_SD_DLL_CTRL, mask, val);
+ if (ret != PM_RET_SUCCESS)
+ return ret;
+
+ if (type == PM_DLL_RESET_ASSERT)
+ break;
+ mdelay(1);
+ case PM_DLL_RESET_RELEASE:
+ ret = pm_mmio_write(ZYNQMP_SD_DLL_CTRL, mask, 0);
+ break;
+ default:
+ ret = PM_RET_ERROR_ARGS;
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * pm_ioctl_sd_set_tapdelay() - Set tap delay for the SD device
+ * @nid Node ID of the device
+ * @type Type of tap delay to set (input/output)
+ * @value Value to set fot the tap delay
+ *
+ * This function sets input/output tap delay for the SD device.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_sd_set_tapdelay(enum pm_node_id nid,
+ enum tap_delay_type type,
+ unsigned int value)
+{
+ unsigned int shift;
+ enum pm_ret_status ret;
+
+ if (nid == NODE_SD_0)
+ shift = 0;
+ else if (nid == NODE_SD_1)
+ shift = ZYNQMP_SD_TAP_OFFSET;
+ else
+ return PM_RET_ERROR_ARGS;
+
+ ret = pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_ASSERT);
+ if (ret != PM_RET_SUCCESS)
+ return ret;
+
+ if (type == PM_TAPDELAY_INPUT) {
+ ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
+ (ZYNQMP_SD_ITAPCHGWIN_MASK << shift),
+ (ZYNQMP_SD_ITAPCHGWIN << shift));
+ if (ret != PM_RET_SUCCESS)
+ goto reset_release;
+ ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
+ (ZYNQMP_SD_ITAPDLYENA_MASK << shift),
+ (ZYNQMP_SD_ITAPDLYENA << shift));
+ if (ret != PM_RET_SUCCESS)
+ goto reset_release;
+ ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
+ (ZYNQMP_SD_ITAPDLYSEL_MASK << shift),
+ (value << shift));
+ if (ret != PM_RET_SUCCESS)
+ goto reset_release;
+ ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
+ (ZYNQMP_SD_ITAPCHGWIN_MASK << shift), 0);
+ } else if (type == PM_TAPDELAY_OUTPUT) {
+ ret = pm_mmio_write(ZYNQMP_SD_OTAP_DLY,
+ (ZYNQMP_SD_OTAPDLYENA_MASK << shift),
+ (ZYNQMP_SD_OTAPDLYENA << shift));
+ if (ret != PM_RET_SUCCESS)
+ goto reset_release;
+ ret = pm_mmio_write(ZYNQMP_SD_OTAP_DLY,
+ (ZYNQMP_SD_OTAPDLYSEL_MASK << shift),
+ (value << shift));
+ } else {
+ ret = PM_RET_ERROR_ARGS;
+ }
+
+reset_release:
+ pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_RELEASE);
+ return ret;
+}
+
+/**
+ * pm_ioctl_set_pll_frac_mode() - Ioctl function for
+ * setting pll mode
+ * @pll PLL id
+ * @mode Mode fraction/integar
+ *
+ * This function sets PLL mode
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_set_pll_frac_mode
+ (unsigned int pll, unsigned int mode)
+{
+ return pm_api_clk_set_pll_mode(pll, mode);
+}
+
+/**
+ * pm_ioctl_get_pll_frac_mode() - Ioctl function for
+ * getting pll mode
+ * @pll PLL id
+ * @mode Mode fraction/integar
+ *
+ * This function return current PLL mode
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_get_pll_frac_mode
+ (unsigned int pll, unsigned int *mode)
+{
+ return pm_api_clk_get_pll_mode(pll, mode);
+}
+
+/**
+ * pm_ioctl_set_pll_frac_data() - Ioctl function for
+ * setting pll fraction data
+ * @pll PLL id
+ * @data fraction data
+ *
+ * This function sets fraction data.
+ * It is valid for fraction mode only.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_set_pll_frac_data
+ (unsigned int pll, unsigned int data)
+{
+ return pm_api_clk_set_pll_frac_data(pll, data);
+}
+
+/**
+ * pm_ioctl_get_pll_frac_data() - Ioctl function for
+ * getting pll fraction data
+ * @pll PLL id
+ * @data fraction data
+ *
+ * This function returns fraction data value.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_get_pll_frac_data
+ (unsigned int pll, unsigned int *data)
+{
+ return pm_api_clk_get_pll_frac_data(pll, data);
+}
+
+/**
+ * pm_ioctl_write_ggs() - Ioctl function for writing
+ * global general storage (ggs)
+ * @index GGS register index
+ * @value Register value to be written
+ *
+ * This function writes value to GGS register.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_write_ggs(unsigned int index,
+ unsigned int value)
+{
+ if (index >= GGS_NUM_REGS)
+ return PM_RET_ERROR_ARGS;
+
+ return pm_mmio_write(GGS_BASEADDR + (index << 2),
+ 0xFFFFFFFFU, value);
+}
+
+/**
+ * pm_ioctl_read_ggs() - Ioctl function for reading
+ * global general storage (ggs)
+ * @index GGS register index
+ * @value Register value
+ *
+ * This function returns GGS register value.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_read_ggs(unsigned int index,
+ unsigned int *value)
+{
+ if (index >= GGS_NUM_REGS)
+ return PM_RET_ERROR_ARGS;
+
+ return pm_mmio_read(GGS_BASEADDR + (index << 2), value);
+}
+
+/**
+ * pm_ioctl_write_pggs() - Ioctl function for writing persistent
+ * global general storage (pggs)
+ * @index PGGS register index
+ * @value Register value to be written
+ *
+ * This function writes value to PGGS register.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_write_pggs(unsigned int index,
+ unsigned int value)
+{
+ if (index >= PGGS_NUM_REGS)
+ return PM_RET_ERROR_ARGS;
+
+ return pm_mmio_write(PGGS_BASEADDR + (index << 2),
+ 0xFFFFFFFFU, value);
+}
+
+/**
+ * pm_ioctl_read_pggs() - Ioctl function for reading persistent
+ * global general storage (pggs)
+ * @index PGGS register index
+ * @value Register value
+ *
+ * This function returns PGGS register value.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_read_pggs(unsigned int index,
+ unsigned int *value)
+{
+ if (index >= PGGS_NUM_REGS)
+ return PM_RET_ERROR_ARGS;
+
+ return pm_mmio_read(PGGS_BASEADDR + (index << 2), value);
+}
+
+/**
+ * pm_api_ioctl() - PM IOCTL API for device control and configs
+ * @node_id Node ID of the device
+ * @ioctl_id ID of the requested IOCTL
+ * @arg1 Argument 1 to requested IOCTL call
+ * @arg2 Argument 2 to requested IOCTL call
+ * @value Returned output value
+ *
+ * This function calls IOCTL to firmware for device control and configuration.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_ioctl(enum pm_node_id nid,
+ unsigned int ioctl_id,
+ unsigned int arg1,
+ unsigned int arg2,
+ unsigned int *value)
+{
+ enum pm_ret_status ret;
+
+ switch (ioctl_id) {
+ case IOCTL_GET_RPU_OPER_MODE:
+ ret = pm_ioctl_get_rpu_oper_mode(value);
+ break;
+ case IOCTL_SET_RPU_OPER_MODE:
+ ret = pm_ioctl_set_rpu_oper_mode(arg1);
+ break;
+ case IOCTL_RPU_BOOT_ADDR_CONFIG:
+ ret = pm_ioctl_config_boot_addr(nid, arg1);
+ break;
+ case IOCTL_TCM_COMB_CONFIG:
+ ret = pm_ioctl_config_tcm_comb(arg1);
+ break;
+ case IOCTL_SET_TAPDELAY_BYPASS:
+ ret = pm_ioctl_set_tapdelay_bypass(arg1, arg2);
+ break;
+ case IOCTL_SET_SGMII_MODE:
+ ret = pm_ioctl_set_sgmii_mode(nid, arg1);
+ break;
+ case IOCTL_SD_DLL_RESET:
+ ret = pm_ioctl_sd_dll_reset(nid, arg1);
+ break;
+ case IOCTL_SET_SD_TAPDELAY:
+ ret = pm_ioctl_sd_set_tapdelay(nid, arg1, arg2);
+ break;
+ case IOCTL_SET_PLL_FRAC_MODE:
+ ret = pm_ioctl_set_pll_frac_mode(arg1, arg2);
+ break;
+ case IOCTL_GET_PLL_FRAC_MODE:
+ ret = pm_ioctl_get_pll_frac_mode(arg1, value);
+ break;
+ case IOCTL_SET_PLL_FRAC_DATA:
+ ret = pm_ioctl_set_pll_frac_data(arg1, arg2);
+ break;
+ case IOCTL_GET_PLL_FRAC_DATA:
+ ret = pm_ioctl_get_pll_frac_data(arg1, value);
+ break;
+ case IOCTL_WRITE_GGS:
+ ret = pm_ioctl_write_ggs(arg1, arg2);
+ break;
+ case IOCTL_READ_GGS:
+ ret = pm_ioctl_read_ggs(arg1, value);
+ break;
+ case IOCTL_WRITE_PGGS:
+ ret = pm_ioctl_write_pggs(arg1, arg2);
+ break;
+ case IOCTL_READ_PGGS:
+ ret = pm_ioctl_read_pggs(arg1, value);
+ break;
+ default:
+ ret = PM_RET_ERROR_NOTSUPPORTED;
+ break;
+ }
+
+ return ret;
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h
new file mode 100644
index 0000000..081259f
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * ZynqMP system level PM-API functions for pin control.
+ */
+
+#ifndef _PM_API_IOCTL_H_
+#define _PM_API_IOCTL_H_
+
+#include "pm_common.h"
+
+//ioctl id
+enum {
+ IOCTL_GET_RPU_OPER_MODE,
+ IOCTL_SET_RPU_OPER_MODE,
+ IOCTL_RPU_BOOT_ADDR_CONFIG,
+ IOCTL_TCM_COMB_CONFIG,
+ IOCTL_SET_TAPDELAY_BYPASS,
+ IOCTL_SET_SGMII_MODE,
+ IOCTL_SD_DLL_RESET,
+ IOCTL_SET_SD_TAPDELAY,
+ /* Ioctl for clock driver */
+ IOCTL_SET_PLL_FRAC_MODE,
+ IOCTL_GET_PLL_FRAC_MODE,
+ IOCTL_SET_PLL_FRAC_DATA,
+ IOCTL_GET_PLL_FRAC_DATA,
+ IOCTL_WRITE_GGS,
+ IOCTL_READ_GGS,
+ IOCTL_WRITE_PGGS,
+ IOCTL_READ_PGGS,
+};
+
+//RPU operation mode
+#define PM_RPU_MODE_LOCKSTEP 0U
+#define PM_RPU_MODE_SPLIT 1U
+
+//RPU boot mem
+#define PM_RPU_BOOTMEM_LOVEC 0U
+#define PM_RPU_BOOTMEM_HIVEC 1U
+
+//RPU tcm mpde
+#define PM_RPU_TCM_SPLIT 0U
+#define PM_RPU_TCM_COMB 1U
+
+//tap delay signal type
+#define PM_TAPDELAY_NAND_DQS_IN 0U
+#define PM_TAPDELAY_NAND_DQS_OUT 1U
+#define PM_TAPDELAY_QSPI 2U
+#define PM_TAPDELAY_MAX 3U
+
+//tap delay bypass
+#define PM_TAPDELAY_BYPASS_DISABLE 0U
+#define PM_TAPDELAY_BYPASS_ENABLE 1U
+
+//sgmii mode
+#define PM_SGMII_DISABLE 0U
+#define PM_SGMII_ENABLE 1U
+
+enum tap_delay_type {
+ PM_TAPDELAY_INPUT,
+ PM_TAPDELAY_OUTPUT,
+};
+
+//dll reset type
+#define PM_DLL_RESET_ASSERT 0U
+#define PM_DLL_RESET_RELEASE 1U
+#define PM_DLL_RESET_PULSE 2U
+
+enum pm_ret_status pm_api_ioctl(enum pm_node_id nid,
+ unsigned int ioctl_id,
+ unsigned int arg1,
+ unsigned int arg2,
+ unsigned int *value);
+#endif /* _PM_API_IOCTL_H_ */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c
new file mode 100644
index 0000000..12b9c2d
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c
@@ -0,0 +1,3039 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * ZynqMP system level PM-API functions for pin control.
+ */
+
+#include <arch_helpers.h>
+#include <platform.h>
+#include <string.h>
+#include "pm_api_pinctrl.h"
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include "pm_common.h"
+#include "pm_ipi.h"
+
+#define PINCTRL_FUNCTION_MASK U(0xFE)
+#define PINCTRL_VOLTAGE_STATUS_MASK U(0x01)
+#define NFUNCS_PER_PIN U(13)
+#define PINCTRL_NUM_MIOS U(78)
+#define MAX_PIN_PER_REG U(26)
+#define PINCTRL_BANK_ADDR_STEP U(28)
+
+#define PINCTRL_DRVSTRN0_REG_OFFSET U(0)
+#define PINCTRL_DRVSTRN1_REG_OFFSET U(4)
+#define PINCTRL_SCHCMOS_REG_OFFSET U(8)
+#define PINCTRL_PULLCTRL_REG_OFFSET U(12)
+#define PINCTRL_PULLSTAT_REG_OFFSET U(16)
+#define PINCTRL_SLEWCTRL_REG_OFFSET U(20)
+#define PINCTRL_VOLTAGE_STAT_REG_OFFSET U(24)
+
+#define IOU_SLCR_BANK1_CTRL5 U(0XFF180164)
+
+#define PINCTRL_CFG_ADDR_OFFSET(addr, reg, miopin) \
+ ((addr) + 4 * PINCTRL_NUM_MIOS + PINCTRL_BANK_ADDR_STEP * \
+ ((miopin) / MAX_PIN_PER_REG) + (reg))
+
+#define PINCTRL_PIN_OFFSET(_miopin) \
+ ((_miopin) - (MAX_PIN_PER_REG * ((_miopin) / MAX_PIN_PER_REG)))
+
+#define PINCTRL_REGVAL_TO_PIN_CONFIG(_pin, _val) \
+ (((_val) >> PINCTRL_PIN_OFFSET(_pin)) & 0x1)
+
+static uint8_t pm_pinctrl_mux[NFUNCS_PER_PIN] = {
+ 0x02, 0x04, 0x08, 0x10, 0x18,
+ 0x00, 0x20, 0x40, 0x60, 0x80,
+ 0xA0, 0xC0, 0xE0
+};
+
+struct pinctrl_function {
+ char name[FUNCTION_NAME_LEN];
+ uint16_t (*groups)[];
+ uint8_t regval;
+};
+
+/* Max groups for one pin */
+#define MAX_PIN_GROUPS U(13)
+
+struct zynqmp_pin_group {
+ uint16_t (*groups)[];
+};
+
+static struct pinctrl_function pinctrl_functions[MAX_FUNCTION] = {
+ [PINCTRL_FUNC_CAN0] = {
+ .name = "can0",
+ .regval = 0x20,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_CAN0_0,
+ PINCTRL_GRP_CAN0_1,
+ PINCTRL_GRP_CAN0_2,
+ PINCTRL_GRP_CAN0_3,
+ PINCTRL_GRP_CAN0_4,
+ PINCTRL_GRP_CAN0_5,
+ PINCTRL_GRP_CAN0_6,
+ PINCTRL_GRP_CAN0_7,
+ PINCTRL_GRP_CAN0_8,
+ PINCTRL_GRP_CAN0_9,
+ PINCTRL_GRP_CAN0_10,
+ PINCTRL_GRP_CAN0_11,
+ PINCTRL_GRP_CAN0_12,
+ PINCTRL_GRP_CAN0_13,
+ PINCTRL_GRP_CAN0_14,
+ PINCTRL_GRP_CAN0_15,
+ PINCTRL_GRP_CAN0_16,
+ PINCTRL_GRP_CAN0_17,
+ PINCTRL_GRP_CAN0_18,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_CAN1] = {
+ .name = "can1",
+ .regval = 0x20,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_CAN1_0,
+ PINCTRL_GRP_CAN1_1,
+ PINCTRL_GRP_CAN1_2,
+ PINCTRL_GRP_CAN1_3,
+ PINCTRL_GRP_CAN1_4,
+ PINCTRL_GRP_CAN1_5,
+ PINCTRL_GRP_CAN1_6,
+ PINCTRL_GRP_CAN1_7,
+ PINCTRL_GRP_CAN1_8,
+ PINCTRL_GRP_CAN1_9,
+ PINCTRL_GRP_CAN1_10,
+ PINCTRL_GRP_CAN1_11,
+ PINCTRL_GRP_CAN1_12,
+ PINCTRL_GRP_CAN1_13,
+ PINCTRL_GRP_CAN1_14,
+ PINCTRL_GRP_CAN1_15,
+ PINCTRL_GRP_CAN1_16,
+ PINCTRL_GRP_CAN1_17,
+ PINCTRL_GRP_CAN1_18,
+ PINCTRL_GRP_CAN1_19,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_ETHERNET0] = {
+ .name = "ethernet0",
+ .regval = 0x02,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_ETHERNET1] = {
+ .name = "ethernet1",
+ .regval = 0x02,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_ETHERNET2] = {
+ .name = "ethernet2",
+ .regval = 0x02,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_ETHERNET3] = {
+ .name = "ethernet3",
+ .regval = 0x02,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_GEMTSU0] = {
+ .name = "gemtsu0",
+ .regval = 0x02,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_GEMTSU0_0,
+ PINCTRL_GRP_GEMTSU0_1,
+ PINCTRL_GRP_GEMTSU0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_GPIO0] = {
+ .name = "gpio0",
+ .regval = 0x00,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_GPIO0_0,
+ PINCTRL_GRP_GPIO0_1,
+ PINCTRL_GRP_GPIO0_2,
+ PINCTRL_GRP_GPIO0_3,
+ PINCTRL_GRP_GPIO0_4,
+ PINCTRL_GRP_GPIO0_5,
+ PINCTRL_GRP_GPIO0_6,
+ PINCTRL_GRP_GPIO0_7,
+ PINCTRL_GRP_GPIO0_8,
+ PINCTRL_GRP_GPIO0_9,
+ PINCTRL_GRP_GPIO0_10,
+ PINCTRL_GRP_GPIO0_11,
+ PINCTRL_GRP_GPIO0_12,
+ PINCTRL_GRP_GPIO0_13,
+ PINCTRL_GRP_GPIO0_14,
+ PINCTRL_GRP_GPIO0_15,
+ PINCTRL_GRP_GPIO0_16,
+ PINCTRL_GRP_GPIO0_17,
+ PINCTRL_GRP_GPIO0_18,
+ PINCTRL_GRP_GPIO0_19,
+ PINCTRL_GRP_GPIO0_20,
+ PINCTRL_GRP_GPIO0_21,
+ PINCTRL_GRP_GPIO0_22,
+ PINCTRL_GRP_GPIO0_23,
+ PINCTRL_GRP_GPIO0_24,
+ PINCTRL_GRP_GPIO0_25,
+ PINCTRL_GRP_GPIO0_26,
+ PINCTRL_GRP_GPIO0_27,
+ PINCTRL_GRP_GPIO0_28,
+ PINCTRL_GRP_GPIO0_29,
+ PINCTRL_GRP_GPIO0_30,
+ PINCTRL_GRP_GPIO0_31,
+ PINCTRL_GRP_GPIO0_32,
+ PINCTRL_GRP_GPIO0_33,
+ PINCTRL_GRP_GPIO0_34,
+ PINCTRL_GRP_GPIO0_35,
+ PINCTRL_GRP_GPIO0_36,
+ PINCTRL_GRP_GPIO0_37,
+ PINCTRL_GRP_GPIO0_38,
+ PINCTRL_GRP_GPIO0_39,
+ PINCTRL_GRP_GPIO0_40,
+ PINCTRL_GRP_GPIO0_41,
+ PINCTRL_GRP_GPIO0_42,
+ PINCTRL_GRP_GPIO0_43,
+ PINCTRL_GRP_GPIO0_44,
+ PINCTRL_GRP_GPIO0_45,
+ PINCTRL_GRP_GPIO0_46,
+ PINCTRL_GRP_GPIO0_47,
+ PINCTRL_GRP_GPIO0_48,
+ PINCTRL_GRP_GPIO0_49,
+ PINCTRL_GRP_GPIO0_50,
+ PINCTRL_GRP_GPIO0_51,
+ PINCTRL_GRP_GPIO0_52,
+ PINCTRL_GRP_GPIO0_53,
+ PINCTRL_GRP_GPIO0_54,
+ PINCTRL_GRP_GPIO0_55,
+ PINCTRL_GRP_GPIO0_56,
+ PINCTRL_GRP_GPIO0_57,
+ PINCTRL_GRP_GPIO0_58,
+ PINCTRL_GRP_GPIO0_59,
+ PINCTRL_GRP_GPIO0_60,
+ PINCTRL_GRP_GPIO0_61,
+ PINCTRL_GRP_GPIO0_62,
+ PINCTRL_GRP_GPIO0_63,
+ PINCTRL_GRP_GPIO0_64,
+ PINCTRL_GRP_GPIO0_65,
+ PINCTRL_GRP_GPIO0_66,
+ PINCTRL_GRP_GPIO0_67,
+ PINCTRL_GRP_GPIO0_68,
+ PINCTRL_GRP_GPIO0_69,
+ PINCTRL_GRP_GPIO0_70,
+ PINCTRL_GRP_GPIO0_71,
+ PINCTRL_GRP_GPIO0_72,
+ PINCTRL_GRP_GPIO0_73,
+ PINCTRL_GRP_GPIO0_74,
+ PINCTRL_GRP_GPIO0_75,
+ PINCTRL_GRP_GPIO0_76,
+ PINCTRL_GRP_GPIO0_77,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_I2C0] = {
+ .name = "i2c0",
+ .regval = 0x40,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_I2C0_0,
+ PINCTRL_GRP_I2C0_1,
+ PINCTRL_GRP_I2C0_2,
+ PINCTRL_GRP_I2C0_3,
+ PINCTRL_GRP_I2C0_4,
+ PINCTRL_GRP_I2C0_5,
+ PINCTRL_GRP_I2C0_6,
+ PINCTRL_GRP_I2C0_7,
+ PINCTRL_GRP_I2C0_8,
+ PINCTRL_GRP_I2C0_9,
+ PINCTRL_GRP_I2C0_10,
+ PINCTRL_GRP_I2C0_11,
+ PINCTRL_GRP_I2C0_12,
+ PINCTRL_GRP_I2C0_13,
+ PINCTRL_GRP_I2C0_14,
+ PINCTRL_GRP_I2C0_15,
+ PINCTRL_GRP_I2C0_16,
+ PINCTRL_GRP_I2C0_17,
+ PINCTRL_GRP_I2C0_18,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_I2C1] = {
+ .name = "i2c1",
+ .regval = 0x40,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_I2C1_0,
+ PINCTRL_GRP_I2C1_1,
+ PINCTRL_GRP_I2C1_2,
+ PINCTRL_GRP_I2C1_3,
+ PINCTRL_GRP_I2C1_4,
+ PINCTRL_GRP_I2C1_5,
+ PINCTRL_GRP_I2C1_6,
+ PINCTRL_GRP_I2C1_7,
+ PINCTRL_GRP_I2C1_8,
+ PINCTRL_GRP_I2C1_9,
+ PINCTRL_GRP_I2C1_10,
+ PINCTRL_GRP_I2C1_11,
+ PINCTRL_GRP_I2C1_12,
+ PINCTRL_GRP_I2C1_13,
+ PINCTRL_GRP_I2C1_14,
+ PINCTRL_GRP_I2C1_15,
+ PINCTRL_GRP_I2C1_16,
+ PINCTRL_GRP_I2C1_17,
+ PINCTRL_GRP_I2C1_18,
+ PINCTRL_GRP_I2C1_19,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_MDIO0] = {
+ .name = "mdio0",
+ .regval = 0x60,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_MDIO0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_MDIO1] = {
+ .name = "mdio1",
+ .regval = 0x80,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_MDIO1_0,
+ PINCTRL_GRP_MDIO1_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_MDIO2] = {
+ .name = "mdio2",
+ .regval = 0xa0,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_MDIO2_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_MDIO3] = {
+ .name = "mdio3",
+ .regval = 0xc0,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_MDIO3_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_QSPI0] = {
+ .name = "qspi0",
+ .regval = 0x02,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_QSPI_FBCLK] = {
+ .name = "qspi_fbclk",
+ .regval = 0x02,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI_FBCLK,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_QSPI_SS] = {
+ .name = "qspi_ss",
+ .regval = 0x02,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI_SS,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_SPI0] = {
+ .name = "spi0",
+ .regval = 0x80,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_SPI0_0,
+ PINCTRL_GRP_SPI0_1,
+ PINCTRL_GRP_SPI0_2,
+ PINCTRL_GRP_SPI0_3,
+ PINCTRL_GRP_SPI0_4,
+ PINCTRL_GRP_SPI0_5,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_SPI1] = {
+ .name = "spi1",
+ .regval = 0x80,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_SPI1_0,
+ PINCTRL_GRP_SPI1_1,
+ PINCTRL_GRP_SPI1_2,
+ PINCTRL_GRP_SPI1_3,
+ PINCTRL_GRP_SPI1_4,
+ PINCTRL_GRP_SPI1_5,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_SPI0_SS] = {
+ .name = "spi0_ss",
+ .regval = 0x80,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_SPI0_0_SS0,
+ PINCTRL_GRP_SPI0_0_SS1,
+ PINCTRL_GRP_SPI0_0_SS2,
+ PINCTRL_GRP_SPI0_1_SS0,
+ PINCTRL_GRP_SPI0_1_SS1,
+ PINCTRL_GRP_SPI0_1_SS2,
+ PINCTRL_GRP_SPI0_2_SS0,
+ PINCTRL_GRP_SPI0_2_SS1,
+ PINCTRL_GRP_SPI0_2_SS2,
+ PINCTRL_GRP_SPI0_3_SS0,
+ PINCTRL_GRP_SPI0_3_SS1,
+ PINCTRL_GRP_SPI0_3_SS2,
+ PINCTRL_GRP_SPI0_4_SS0,
+ PINCTRL_GRP_SPI0_4_SS1,
+ PINCTRL_GRP_SPI0_4_SS2,
+ PINCTRL_GRP_SPI0_5_SS0,
+ PINCTRL_GRP_SPI0_5_SS1,
+ PINCTRL_GRP_SPI0_5_SS2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_SPI1_SS] = {
+ .name = "spi1_ss",
+ .regval = 0x80,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_SPI1_0_SS0,
+ PINCTRL_GRP_SPI1_0_SS1,
+ PINCTRL_GRP_SPI1_0_SS2,
+ PINCTRL_GRP_SPI1_1_SS0,
+ PINCTRL_GRP_SPI1_1_SS1,
+ PINCTRL_GRP_SPI1_1_SS2,
+ PINCTRL_GRP_SPI1_2_SS0,
+ PINCTRL_GRP_SPI1_2_SS1,
+ PINCTRL_GRP_SPI1_2_SS2,
+ PINCTRL_GRP_SPI1_3_SS0,
+ PINCTRL_GRP_SPI1_3_SS1,
+ PINCTRL_GRP_SPI1_3_SS2,
+ PINCTRL_GRP_SPI1_4_SS0,
+ PINCTRL_GRP_SPI1_4_SS1,
+ PINCTRL_GRP_SPI1_4_SS2,
+ PINCTRL_GRP_SPI1_5_SS0,
+ PINCTRL_GRP_SPI1_5_SS1,
+ PINCTRL_GRP_SPI1_5_SS2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_SDIO0] = {
+ .name = "sdio0",
+ .regval = 0x08,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_SDIO0_4BIT_0_0,
+ PINCTRL_GRP_SDIO0_4BIT_0_1,
+ PINCTRL_GRP_SDIO0_4BIT_1_0,
+ PINCTRL_GRP_SDIO0_4BIT_1_1,
+ PINCTRL_GRP_SDIO0_4BIT_2_0,
+ PINCTRL_GRP_SDIO0_4BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_0,
+ PINCTRL_GRP_SDIO0_1BIT_0_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_2,
+ PINCTRL_GRP_SDIO0_1BIT_0_3,
+ PINCTRL_GRP_SDIO0_1BIT_0_4,
+ PINCTRL_GRP_SDIO0_1BIT_0_5,
+ PINCTRL_GRP_SDIO0_1BIT_0_6,
+ PINCTRL_GRP_SDIO0_1BIT_0_7,
+ PINCTRL_GRP_SDIO0_1BIT_1_0,
+ PINCTRL_GRP_SDIO0_1BIT_1_1,
+ PINCTRL_GRP_SDIO0_1BIT_1_2,
+ PINCTRL_GRP_SDIO0_1BIT_1_3,
+ PINCTRL_GRP_SDIO0_1BIT_1_4,
+ PINCTRL_GRP_SDIO0_1BIT_1_5,
+ PINCTRL_GRP_SDIO0_1BIT_1_6,
+ PINCTRL_GRP_SDIO0_1BIT_1_7,
+ PINCTRL_GRP_SDIO0_1BIT_2_0,
+ PINCTRL_GRP_SDIO0_1BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_2_2,
+ PINCTRL_GRP_SDIO0_1BIT_2_3,
+ PINCTRL_GRP_SDIO0_1BIT_2_4,
+ PINCTRL_GRP_SDIO0_1BIT_2_5,
+ PINCTRL_GRP_SDIO0_1BIT_2_6,
+ PINCTRL_GRP_SDIO0_1BIT_2_7,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_SDIO0_PC] = {
+ .name = "sdio0_pc",
+ .regval = 0x08,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_SDIO0_0_PC,
+ PINCTRL_GRP_SDIO0_1_PC,
+ PINCTRL_GRP_SDIO0_2_PC,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_SDIO0_CD] = {
+ .name = "sdio0_cd",
+ .regval = 0x08,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_SDIO0_0_CD,
+ PINCTRL_GRP_SDIO0_1_CD,
+ PINCTRL_GRP_SDIO0_2_CD,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_SDIO0_WP] = {
+ .name = "sdio0_wp",
+ .regval = 0x08,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_SDIO0_0_WP,
+ PINCTRL_GRP_SDIO0_1_WP,
+ PINCTRL_GRP_SDIO0_2_WP,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_SDIO1] = {
+ .name = "sdio1",
+ .regval = 0x10,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_SDIO1_4BIT_0_0,
+ PINCTRL_GRP_SDIO1_4BIT_0_1,
+ PINCTRL_GRP_SDIO1_4BIT_1_0,
+ PINCTRL_GRP_SDIO1_1BIT_0_0,
+ PINCTRL_GRP_SDIO1_1BIT_0_1,
+ PINCTRL_GRP_SDIO1_1BIT_0_2,
+ PINCTRL_GRP_SDIO1_1BIT_0_3,
+ PINCTRL_GRP_SDIO1_1BIT_0_4,
+ PINCTRL_GRP_SDIO1_1BIT_0_5,
+ PINCTRL_GRP_SDIO1_1BIT_0_6,
+ PINCTRL_GRP_SDIO1_1BIT_0_7,
+ PINCTRL_GRP_SDIO1_1BIT_1_0,
+ PINCTRL_GRP_SDIO1_1BIT_1_1,
+ PINCTRL_GRP_SDIO1_1BIT_1_2,
+ PINCTRL_GRP_SDIO1_1BIT_1_3,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_SDIO1_PC] = {
+ .name = "sdio1_pc",
+ .regval = 0x10,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_SDIO1_0_PC,
+ PINCTRL_GRP_SDIO1_1_PC,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_SDIO1_CD] = {
+ .name = "sdio1_cd",
+ .regval = 0x10,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_SDIO1_0_CD,
+ PINCTRL_GRP_SDIO1_1_CD,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_SDIO1_WP] = {
+ .name = "sdio1_wp",
+ .regval = 0x10,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_SDIO1_0_WP,
+ PINCTRL_GRP_SDIO1_1_WP,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_NAND0] = {
+ .name = "nand0",
+ .regval = 0x04,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_NAND0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_NAND0_CE] = {
+ .name = "nand0_ce",
+ .regval = 0x04,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_NAND0_0_CE,
+ PINCTRL_GRP_NAND0_1_CE,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_NAND0_RB] = {
+ .name = "nand0_rb",
+ .regval = 0x04,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_NAND0_0_RB,
+ PINCTRL_GRP_NAND0_1_RB,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_NAND0_DQS] = {
+ .name = "nand0_dqs",
+ .regval = 0x04,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_NAND0_0_DQS,
+ PINCTRL_GRP_NAND0_1_DQS,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_TTC0_CLK] = {
+ .name = "ttc0_clk",
+ .regval = 0xa0,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_TTC0_0_CLK,
+ PINCTRL_GRP_TTC0_1_CLK,
+ PINCTRL_GRP_TTC0_2_CLK,
+ PINCTRL_GRP_TTC0_3_CLK,
+ PINCTRL_GRP_TTC0_4_CLK,
+ PINCTRL_GRP_TTC0_5_CLK,
+ PINCTRL_GRP_TTC0_6_CLK,
+ PINCTRL_GRP_TTC0_7_CLK,
+ PINCTRL_GRP_TTC0_8_CLK,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_TTC0_WAV] = {
+ .name = "ttc0_wav",
+ .regval = 0xa0,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_TTC0_0_WAV,
+ PINCTRL_GRP_TTC0_1_WAV,
+ PINCTRL_GRP_TTC0_2_WAV,
+ PINCTRL_GRP_TTC0_3_WAV,
+ PINCTRL_GRP_TTC0_4_WAV,
+ PINCTRL_GRP_TTC0_5_WAV,
+ PINCTRL_GRP_TTC0_6_WAV,
+ PINCTRL_GRP_TTC0_7_WAV,
+ PINCTRL_GRP_TTC0_8_WAV,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_TTC1_CLK] = {
+ .name = "ttc1_clk",
+ .regval = 0xa0,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_TTC1_0_CLK,
+ PINCTRL_GRP_TTC1_1_CLK,
+ PINCTRL_GRP_TTC1_2_CLK,
+ PINCTRL_GRP_TTC1_3_CLK,
+ PINCTRL_GRP_TTC1_4_CLK,
+ PINCTRL_GRP_TTC1_5_CLK,
+ PINCTRL_GRP_TTC1_6_CLK,
+ PINCTRL_GRP_TTC1_7_CLK,
+ PINCTRL_GRP_TTC1_8_CLK,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_TTC1_WAV] = {
+ .name = "ttc1_wav",
+ .regval = 0xa0,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_TTC1_0_WAV,
+ PINCTRL_GRP_TTC1_1_WAV,
+ PINCTRL_GRP_TTC1_2_WAV,
+ PINCTRL_GRP_TTC1_3_WAV,
+ PINCTRL_GRP_TTC1_4_WAV,
+ PINCTRL_GRP_TTC1_5_WAV,
+ PINCTRL_GRP_TTC1_6_WAV,
+ PINCTRL_GRP_TTC1_7_WAV,
+ PINCTRL_GRP_TTC1_8_WAV,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_TTC2_CLK] = {
+ .name = "ttc2_clk",
+ .regval = 0xa0,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_TTC2_0_CLK,
+ PINCTRL_GRP_TTC2_1_CLK,
+ PINCTRL_GRP_TTC2_2_CLK,
+ PINCTRL_GRP_TTC2_3_CLK,
+ PINCTRL_GRP_TTC2_4_CLK,
+ PINCTRL_GRP_TTC2_5_CLK,
+ PINCTRL_GRP_TTC2_6_CLK,
+ PINCTRL_GRP_TTC2_7_CLK,
+ PINCTRL_GRP_TTC2_8_CLK,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_TTC2_WAV] = {
+ .name = "ttc2_wav",
+ .regval = 0xa0,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_TTC2_0_WAV,
+ PINCTRL_GRP_TTC2_1_WAV,
+ PINCTRL_GRP_TTC2_2_WAV,
+ PINCTRL_GRP_TTC2_3_WAV,
+ PINCTRL_GRP_TTC2_4_WAV,
+ PINCTRL_GRP_TTC2_5_WAV,
+ PINCTRL_GRP_TTC2_6_WAV,
+ PINCTRL_GRP_TTC2_7_WAV,
+ PINCTRL_GRP_TTC2_8_WAV,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_TTC3_CLK] = {
+ .name = "ttc3_clk",
+ .regval = 0xa0,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_TTC3_0_CLK,
+ PINCTRL_GRP_TTC3_1_CLK,
+ PINCTRL_GRP_TTC3_2_CLK,
+ PINCTRL_GRP_TTC3_3_CLK,
+ PINCTRL_GRP_TTC3_4_CLK,
+ PINCTRL_GRP_TTC3_5_CLK,
+ PINCTRL_GRP_TTC3_6_CLK,
+ PINCTRL_GRP_TTC3_7_CLK,
+ PINCTRL_GRP_TTC3_8_CLK,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_TTC3_WAV] = {
+ .name = "ttc3_wav",
+ .regval = 0xa0,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_TTC3_0_WAV,
+ PINCTRL_GRP_TTC3_1_WAV,
+ PINCTRL_GRP_TTC3_2_WAV,
+ PINCTRL_GRP_TTC3_3_WAV,
+ PINCTRL_GRP_TTC3_4_WAV,
+ PINCTRL_GRP_TTC3_5_WAV,
+ PINCTRL_GRP_TTC3_6_WAV,
+ PINCTRL_GRP_TTC3_7_WAV,
+ PINCTRL_GRP_TTC3_8_WAV,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_UART0] = {
+ .name = "uart0",
+ .regval = 0xc0,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_UART0_0,
+ PINCTRL_GRP_UART0_1,
+ PINCTRL_GRP_UART0_2,
+ PINCTRL_GRP_UART0_3,
+ PINCTRL_GRP_UART0_4,
+ PINCTRL_GRP_UART0_5,
+ PINCTRL_GRP_UART0_6,
+ PINCTRL_GRP_UART0_7,
+ PINCTRL_GRP_UART0_8,
+ PINCTRL_GRP_UART0_9,
+ PINCTRL_GRP_UART0_10,
+ PINCTRL_GRP_UART0_11,
+ PINCTRL_GRP_UART0_12,
+ PINCTRL_GRP_UART0_13,
+ PINCTRL_GRP_UART0_14,
+ PINCTRL_GRP_UART0_15,
+ PINCTRL_GRP_UART0_16,
+ PINCTRL_GRP_UART0_17,
+ PINCTRL_GRP_UART0_18,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_UART1] = {
+ .name = "uart1",
+ .regval = 0xc0,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_UART1_0,
+ PINCTRL_GRP_UART1_1,
+ PINCTRL_GRP_UART1_2,
+ PINCTRL_GRP_UART1_3,
+ PINCTRL_GRP_UART1_4,
+ PINCTRL_GRP_UART1_5,
+ PINCTRL_GRP_UART1_6,
+ PINCTRL_GRP_UART1_7,
+ PINCTRL_GRP_UART1_8,
+ PINCTRL_GRP_UART1_9,
+ PINCTRL_GRP_UART1_10,
+ PINCTRL_GRP_UART1_11,
+ PINCTRL_GRP_UART1_12,
+ PINCTRL_GRP_UART1_13,
+ PINCTRL_GRP_UART1_14,
+ PINCTRL_GRP_UART1_15,
+ PINCTRL_GRP_UART1_16,
+ PINCTRL_GRP_UART1_17,
+ PINCTRL_GRP_UART1_18,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_USB0] = {
+ .name = "usb0",
+ .regval = 0x04,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_USB0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_USB1] = {
+ .name = "usb1",
+ .regval = 0x04,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_USB1_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_SWDT0_CLK] = {
+ .name = "swdt0_clk",
+ .regval = 0x60,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_SWDT0_0_CLK,
+ PINCTRL_GRP_SWDT0_1_CLK,
+ PINCTRL_GRP_SWDT0_2_CLK,
+ PINCTRL_GRP_SWDT0_3_CLK,
+ PINCTRL_GRP_SWDT0_4_CLK,
+ PINCTRL_GRP_SWDT0_5_CLK,
+ PINCTRL_GRP_SWDT0_6_CLK,
+ PINCTRL_GRP_SWDT0_7_CLK,
+ PINCTRL_GRP_SWDT0_8_CLK,
+ PINCTRL_GRP_SWDT0_9_CLK,
+ PINCTRL_GRP_SWDT0_10_CLK,
+ PINCTRL_GRP_SWDT0_11_CLK,
+ PINCTRL_GRP_SWDT0_12_CLK,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_SWDT0_RST] = {
+ .name = "swdt0_rst",
+ .regval = 0x60,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_SWDT0_0_RST,
+ PINCTRL_GRP_SWDT0_1_RST,
+ PINCTRL_GRP_SWDT0_2_RST,
+ PINCTRL_GRP_SWDT0_3_RST,
+ PINCTRL_GRP_SWDT0_4_RST,
+ PINCTRL_GRP_SWDT0_5_RST,
+ PINCTRL_GRP_SWDT0_6_RST,
+ PINCTRL_GRP_SWDT0_7_RST,
+ PINCTRL_GRP_SWDT0_8_RST,
+ PINCTRL_GRP_SWDT0_9_RST,
+ PINCTRL_GRP_SWDT0_10_RST,
+ PINCTRL_GRP_SWDT0_11_RST,
+ PINCTRL_GRP_SWDT0_12_RST,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_SWDT1_CLK] = {
+ .name = "swdt1_clk",
+ .regval = 0x60,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_SWDT1_0_CLK,
+ PINCTRL_GRP_SWDT1_1_CLK,
+ PINCTRL_GRP_SWDT1_2_CLK,
+ PINCTRL_GRP_SWDT1_3_CLK,
+ PINCTRL_GRP_SWDT1_4_CLK,
+ PINCTRL_GRP_SWDT1_5_CLK,
+ PINCTRL_GRP_SWDT1_6_CLK,
+ PINCTRL_GRP_SWDT1_7_CLK,
+ PINCTRL_GRP_SWDT1_8_CLK,
+ PINCTRL_GRP_SWDT1_9_CLK,
+ PINCTRL_GRP_SWDT1_10_CLK,
+ PINCTRL_GRP_SWDT1_11_CLK,
+ PINCTRL_GRP_SWDT1_12_CLK,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_SWDT1_RST] = {
+ .name = "swdt1_rst",
+ .regval = 0x60,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_SWDT1_0_RST,
+ PINCTRL_GRP_SWDT1_1_RST,
+ PINCTRL_GRP_SWDT1_2_RST,
+ PINCTRL_GRP_SWDT1_3_RST,
+ PINCTRL_GRP_SWDT1_4_RST,
+ PINCTRL_GRP_SWDT1_5_RST,
+ PINCTRL_GRP_SWDT1_6_RST,
+ PINCTRL_GRP_SWDT1_7_RST,
+ PINCTRL_GRP_SWDT1_8_RST,
+ PINCTRL_GRP_SWDT1_9_RST,
+ PINCTRL_GRP_SWDT1_10_RST,
+ PINCTRL_GRP_SWDT1_11_RST,
+ PINCTRL_GRP_SWDT1_12_RST,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_PMU0] = {
+ .name = "pmu0",
+ .regval = 0x08,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_PMU0_0,
+ PINCTRL_GRP_PMU0_1,
+ PINCTRL_GRP_PMU0_2,
+ PINCTRL_GRP_PMU0_3,
+ PINCTRL_GRP_PMU0_4,
+ PINCTRL_GRP_PMU0_5,
+ PINCTRL_GRP_PMU0_6,
+ PINCTRL_GRP_PMU0_7,
+ PINCTRL_GRP_PMU0_8,
+ PINCTRL_GRP_PMU0_9,
+ PINCTRL_GRP_PMU0_10,
+ PINCTRL_GRP_PMU0_11,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_PCIE0] = {
+ .name = "pcie0",
+ .regval = 0x04,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_PCIE0_0,
+ PINCTRL_GRP_PCIE0_1,
+ PINCTRL_GRP_PCIE0_2,
+ PINCTRL_GRP_PCIE0_3,
+ PINCTRL_GRP_PCIE0_4,
+ PINCTRL_GRP_PCIE0_5,
+ PINCTRL_GRP_PCIE0_6,
+ PINCTRL_GRP_PCIE0_7,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_CSU0] = {
+ .name = "csu0",
+ .regval = 0x18,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_CSU0_0,
+ PINCTRL_GRP_CSU0_1,
+ PINCTRL_GRP_CSU0_2,
+ PINCTRL_GRP_CSU0_3,
+ PINCTRL_GRP_CSU0_4,
+ PINCTRL_GRP_CSU0_5,
+ PINCTRL_GRP_CSU0_6,
+ PINCTRL_GRP_CSU0_7,
+ PINCTRL_GRP_CSU0_8,
+ PINCTRL_GRP_CSU0_9,
+ PINCTRL_GRP_CSU0_10,
+ PINCTRL_GRP_CSU0_11,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_DPAUX0] = {
+ .name = "dpaux0",
+ .regval = 0x18,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_DPAUX0_0,
+ PINCTRL_GRP_DPAUX0_1,
+ PINCTRL_GRP_DPAUX0_2,
+ PINCTRL_GRP_DPAUX0_3,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_PJTAG0] = {
+ .name = "pjtag0",
+ .regval = 0x60,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_PJTAG0_0,
+ PINCTRL_GRP_PJTAG0_1,
+ PINCTRL_GRP_PJTAG0_2,
+ PINCTRL_GRP_PJTAG0_3,
+ PINCTRL_GRP_PJTAG0_4,
+ PINCTRL_GRP_PJTAG0_5,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_TRACE0] = {
+ .name = "trace0",
+ .regval = 0xe0,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_TRACE0_0,
+ PINCTRL_GRP_TRACE0_1,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_TRACE0_CLK] = {
+ .name = "trace0_clk",
+ .regval = 0xe0,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_TRACE0_0_CLK,
+ PINCTRL_GRP_TRACE0_1_CLK,
+ PINCTRL_GRP_TRACE0_2_CLK,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_FUNC_TESTSCAN0] = {
+ .name = "testscan0",
+ .regval = 0x10,
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_TESTSCAN0_0,
+ END_OF_GROUPS,
+ }),
+ },
+};
+
+static struct zynqmp_pin_group zynqmp_pin_groups[MAX_PIN] = {
+ [PINCTRL_PIN_0] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_0,
+ PINCTRL_GRP_CAN1_0,
+ PINCTRL_GRP_I2C1_0,
+ PINCTRL_GRP_PJTAG0_0,
+ PINCTRL_GRP_SPI0_0,
+ PINCTRL_GRP_TTC3_0_CLK,
+ PINCTRL_GRP_UART1_0,
+ PINCTRL_GRP_TRACE0_0_CLK,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_1] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_1,
+ PINCTRL_GRP_CAN1_0,
+ PINCTRL_GRP_I2C1_0,
+ PINCTRL_GRP_PJTAG0_0,
+ PINCTRL_GRP_SPI0_0_SS2,
+ PINCTRL_GRP_TTC3_0_WAV,
+ PINCTRL_GRP_UART1_0,
+ PINCTRL_GRP_TRACE0_0_CLK,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_2] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_2,
+ PINCTRL_GRP_CAN0_0,
+ PINCTRL_GRP_I2C0_0,
+ PINCTRL_GRP_PJTAG0_0,
+ PINCTRL_GRP_SPI0_0_SS1,
+ PINCTRL_GRP_TTC2_0_CLK,
+ PINCTRL_GRP_UART0_0,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_3] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_3,
+ PINCTRL_GRP_CAN0_0,
+ PINCTRL_GRP_I2C0_0,
+ PINCTRL_GRP_PJTAG0_0,
+ PINCTRL_GRP_SPI0_0_SS0,
+ PINCTRL_GRP_TTC2_0_WAV,
+ PINCTRL_GRP_UART0_0,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_4] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_4,
+ PINCTRL_GRP_CAN1_1,
+ PINCTRL_GRP_I2C1_1,
+ PINCTRL_GRP_SWDT1_0_CLK,
+ PINCTRL_GRP_SPI0_0,
+ PINCTRL_GRP_TTC1_0_CLK,
+ PINCTRL_GRP_UART1_1,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_5] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI_SS,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_5,
+ PINCTRL_GRP_CAN1_1,
+ PINCTRL_GRP_I2C1_1,
+ PINCTRL_GRP_SWDT1_0_RST,
+ PINCTRL_GRP_SPI0_0,
+ PINCTRL_GRP_TTC1_0_WAV,
+ PINCTRL_GRP_UART1_1,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_6] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI_FBCLK,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_6,
+ PINCTRL_GRP_CAN0_1,
+ PINCTRL_GRP_I2C0_1,
+ PINCTRL_GRP_SWDT0_0_CLK,
+ PINCTRL_GRP_SPI1_0,
+ PINCTRL_GRP_TTC0_0_CLK,
+ PINCTRL_GRP_UART0_1,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_7] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI_SS,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_7,
+ PINCTRL_GRP_CAN0_1,
+ PINCTRL_GRP_I2C0_1,
+ PINCTRL_GRP_SWDT0_0_RST,
+ PINCTRL_GRP_SPI1_0_SS2,
+ PINCTRL_GRP_TTC0_0_WAV,
+ PINCTRL_GRP_UART0_1,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_8] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_8,
+ PINCTRL_GRP_CAN1_2,
+ PINCTRL_GRP_I2C1_2,
+ PINCTRL_GRP_SWDT1_1_CLK,
+ PINCTRL_GRP_SPI1_0_SS1,
+ PINCTRL_GRP_TTC3_1_CLK,
+ PINCTRL_GRP_UART1_2,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_9] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_NAND0_0_CE,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_9,
+ PINCTRL_GRP_CAN1_2,
+ PINCTRL_GRP_I2C1_2,
+ PINCTRL_GRP_SWDT1_1_RST,
+ PINCTRL_GRP_SPI1_0_SS0,
+ PINCTRL_GRP_TTC3_1_WAV,
+ PINCTRL_GRP_UART1_2,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_10] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_NAND0_0_RB,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_10,
+ PINCTRL_GRP_CAN0_2,
+ PINCTRL_GRP_I2C0_2,
+ PINCTRL_GRP_SWDT0_1_CLK,
+ PINCTRL_GRP_SPI1_0,
+ PINCTRL_GRP_TTC2_1_CLK,
+ PINCTRL_GRP_UART0_2,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_11] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_NAND0_0_RB,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_11,
+ PINCTRL_GRP_CAN0_2,
+ PINCTRL_GRP_I2C0_2,
+ PINCTRL_GRP_SWDT0_1_RST,
+ PINCTRL_GRP_SPI1_0,
+ PINCTRL_GRP_TTC2_1_WAV,
+ PINCTRL_GRP_UART0_2,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_12] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_NAND0_0_DQS,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_12,
+ PINCTRL_GRP_CAN1_3,
+ PINCTRL_GRP_I2C1_3,
+ PINCTRL_GRP_PJTAG0_1,
+ PINCTRL_GRP_SPI0_1,
+ PINCTRL_GRP_TTC1_1_CLK,
+ PINCTRL_GRP_UART1_3,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_13] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_13,
+ PINCTRL_GRP_CAN1_3,
+ PINCTRL_GRP_I2C1_3,
+ PINCTRL_GRP_PJTAG0_1,
+ PINCTRL_GRP_SPI0_1_SS2,
+ PINCTRL_GRP_TTC1_1_WAV,
+ PINCTRL_GRP_UART1_3,
+ PINCTRL_GRP_TRACE0_0,
+ PINCTRL_GRP_SDIO0_4BIT_0_0,
+ PINCTRL_GRP_SDIO0_1BIT_0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_14] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_14,
+ PINCTRL_GRP_CAN0_3,
+ PINCTRL_GRP_I2C0_3,
+ PINCTRL_GRP_PJTAG0_1,
+ PINCTRL_GRP_SPI0_1_SS1,
+ PINCTRL_GRP_TTC0_1_CLK,
+ PINCTRL_GRP_UART0_3,
+ PINCTRL_GRP_TRACE0_0,
+ PINCTRL_GRP_SDIO0_4BIT_0_0,
+ PINCTRL_GRP_SDIO0_1BIT_0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_15] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_15,
+ PINCTRL_GRP_CAN0_3,
+ PINCTRL_GRP_I2C0_3,
+ PINCTRL_GRP_PJTAG0_1,
+ PINCTRL_GRP_SPI0_1_SS0,
+ PINCTRL_GRP_TTC0_1_WAV,
+ PINCTRL_GRP_UART0_3,
+ PINCTRL_GRP_TRACE0_0,
+ PINCTRL_GRP_SDIO0_4BIT_0_0,
+ PINCTRL_GRP_SDIO0_1BIT_0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_16] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_16,
+ PINCTRL_GRP_CAN1_4,
+ PINCTRL_GRP_I2C1_4,
+ PINCTRL_GRP_SWDT1_2_CLK,
+ PINCTRL_GRP_SPI0_1,
+ PINCTRL_GRP_TTC3_2_CLK,
+ PINCTRL_GRP_UART1_4,
+ PINCTRL_GRP_TRACE0_0,
+ PINCTRL_GRP_SDIO0_4BIT_0_0,
+ PINCTRL_GRP_SDIO0_1BIT_0_3,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_17] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_17,
+ PINCTRL_GRP_CAN1_4,
+ PINCTRL_GRP_I2C1_4,
+ PINCTRL_GRP_SWDT1_2_RST,
+ PINCTRL_GRP_SPI0_1,
+ PINCTRL_GRP_TTC3_2_WAV,
+ PINCTRL_GRP_UART1_4,
+ PINCTRL_GRP_TRACE0_0,
+ PINCTRL_GRP_SDIO0_4BIT_0_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_4,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_18] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_0,
+ PINCTRL_GRP_GPIO0_18,
+ PINCTRL_GRP_CAN0_4,
+ PINCTRL_GRP_I2C0_4,
+ PINCTRL_GRP_SWDT0_2_CLK,
+ PINCTRL_GRP_SPI1_1,
+ PINCTRL_GRP_TTC2_2_CLK,
+ PINCTRL_GRP_UART0_4,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_0_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_5,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_19] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_1,
+ PINCTRL_GRP_GPIO0_19,
+ PINCTRL_GRP_CAN0_4,
+ PINCTRL_GRP_I2C0_4,
+ PINCTRL_GRP_SWDT0_2_RST,
+ PINCTRL_GRP_SPI1_1_SS2,
+ PINCTRL_GRP_TTC2_2_WAV,
+ PINCTRL_GRP_UART0_4,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_0_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_6,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_20] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_2,
+ PINCTRL_GRP_GPIO0_20,
+ PINCTRL_GRP_CAN1_5,
+ PINCTRL_GRP_I2C1_5,
+ PINCTRL_GRP_SWDT1_3_CLK,
+ PINCTRL_GRP_SPI1_1_SS1,
+ PINCTRL_GRP_TTC1_2_CLK,
+ PINCTRL_GRP_UART1_5,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_0_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_7,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_21] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_3,
+ PINCTRL_GRP_GPIO0_21,
+ PINCTRL_GRP_CAN1_5,
+ PINCTRL_GRP_I2C1_5,
+ PINCTRL_GRP_SWDT1_3_RST,
+ PINCTRL_GRP_SPI1_1_SS0,
+ PINCTRL_GRP_TTC1_2_WAV,
+ PINCTRL_GRP_UART1_5,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_0_0,
+ PINCTRL_GRP_SDIO0_4BIT_0_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_0,
+ PINCTRL_GRP_SDIO0_1BIT_0_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_2,
+ PINCTRL_GRP_SDIO0_1BIT_0_3,
+ PINCTRL_GRP_SDIO0_1BIT_0_4,
+ PINCTRL_GRP_SDIO0_1BIT_0_5,
+ PINCTRL_GRP_SDIO0_1BIT_0_6,
+ PINCTRL_GRP_SDIO0_1BIT_0_7,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_22] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_4,
+ PINCTRL_GRP_GPIO0_22,
+ PINCTRL_GRP_CAN0_5,
+ PINCTRL_GRP_I2C0_5,
+ PINCTRL_GRP_SWDT0_3_CLK,
+ PINCTRL_GRP_SPI1_1,
+ PINCTRL_GRP_TTC0_2_CLK,
+ PINCTRL_GRP_UART0_5,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_0_0,
+ PINCTRL_GRP_SDIO0_4BIT_0_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_0,
+ PINCTRL_GRP_SDIO0_1BIT_0_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_2,
+ PINCTRL_GRP_SDIO0_1BIT_0_3,
+ PINCTRL_GRP_SDIO0_1BIT_0_4,
+ PINCTRL_GRP_SDIO0_1BIT_0_5,
+ PINCTRL_GRP_SDIO0_1BIT_0_6,
+ PINCTRL_GRP_SDIO0_1BIT_0_7,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_23] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0_PC,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_5,
+ PINCTRL_GRP_GPIO0_23,
+ PINCTRL_GRP_CAN0_5,
+ PINCTRL_GRP_I2C0_5,
+ PINCTRL_GRP_SWDT0_3_RST,
+ PINCTRL_GRP_SPI1_1,
+ PINCTRL_GRP_TTC0_2_WAV,
+ PINCTRL_GRP_UART0_5,
+ PINCTRL_GRP_RESERVED,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_24] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0_CD,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_6,
+ PINCTRL_GRP_GPIO0_24,
+ PINCTRL_GRP_CAN1_6,
+ PINCTRL_GRP_I2C1_6,
+ PINCTRL_GRP_SWDT1_4_CLK,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TTC3_3_CLK,
+ PINCTRL_GRP_UART1_6,
+ PINCTRL_GRP_RESERVED,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_25] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0_WP,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_7,
+ PINCTRL_GRP_GPIO0_25,
+ PINCTRL_GRP_CAN1_6,
+ PINCTRL_GRP_I2C1_6,
+ PINCTRL_GRP_SWDT1_4_RST,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TTC3_3_WAV,
+ PINCTRL_GRP_UART1_6,
+ PINCTRL_GRP_RESERVED,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_26] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_GEMTSU0_0,
+ PINCTRL_GRP_NAND0_1_CE,
+ PINCTRL_GRP_PMU0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_8,
+ PINCTRL_GRP_GPIO0_26,
+ PINCTRL_GRP_CAN0_6,
+ PINCTRL_GRP_I2C0_6,
+ PINCTRL_GRP_PJTAG0_2,
+ PINCTRL_GRP_SPI0_2,
+ PINCTRL_GRP_TTC2_3_CLK,
+ PINCTRL_GRP_UART0_6,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_27] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_NAND0_1_RB,
+ PINCTRL_GRP_PMU0_1,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_DPAUX0_0,
+ PINCTRL_GRP_GPIO0_27,
+ PINCTRL_GRP_CAN0_6,
+ PINCTRL_GRP_I2C0_6,
+ PINCTRL_GRP_PJTAG0_2,
+ PINCTRL_GRP_SPI0_2_SS2,
+ PINCTRL_GRP_TTC2_3_WAV,
+ PINCTRL_GRP_UART0_6,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_28] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_NAND0_1_RB,
+ PINCTRL_GRP_PMU0_2,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_DPAUX0_0,
+ PINCTRL_GRP_GPIO0_28,
+ PINCTRL_GRP_CAN1_7,
+ PINCTRL_GRP_I2C1_7,
+ PINCTRL_GRP_PJTAG0_2,
+ PINCTRL_GRP_SPI0_2_SS1,
+ PINCTRL_GRP_TTC1_3_CLK,
+ PINCTRL_GRP_UART1_7,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_29] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_PCIE0_0,
+ PINCTRL_GRP_PMU0_3,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_DPAUX0_1,
+ PINCTRL_GRP_GPIO0_29,
+ PINCTRL_GRP_CAN1_7,
+ PINCTRL_GRP_I2C1_7,
+ PINCTRL_GRP_PJTAG0_2,
+ PINCTRL_GRP_SPI0_2_SS0,
+ PINCTRL_GRP_TTC1_3_WAV,
+ PINCTRL_GRP_UART1_7,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_30] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_PCIE0_1,
+ PINCTRL_GRP_PMU0_4,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_DPAUX0_1,
+ PINCTRL_GRP_GPIO0_30,
+ PINCTRL_GRP_CAN0_7,
+ PINCTRL_GRP_I2C0_7,
+ PINCTRL_GRP_SWDT0_4_CLK,
+ PINCTRL_GRP_SPI0_2,
+ PINCTRL_GRP_TTC0_3_CLK,
+ PINCTRL_GRP_UART0_7,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_31] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_PCIE0_2,
+ PINCTRL_GRP_PMU0_5,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_9,
+ PINCTRL_GRP_GPIO0_31,
+ PINCTRL_GRP_CAN0_7,
+ PINCTRL_GRP_I2C0_7,
+ PINCTRL_GRP_SWDT0_4_RST,
+ PINCTRL_GRP_SPI0_2,
+ PINCTRL_GRP_TTC0_3_WAV,
+ PINCTRL_GRP_UART0_7,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_32] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_NAND0_1_DQS,
+ PINCTRL_GRP_PMU0_6,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_10,
+ PINCTRL_GRP_GPIO0_32,
+ PINCTRL_GRP_CAN1_8,
+ PINCTRL_GRP_I2C1_8,
+ PINCTRL_GRP_SWDT1_5_CLK,
+ PINCTRL_GRP_SPI1_2,
+ PINCTRL_GRP_TTC3_4_CLK,
+ PINCTRL_GRP_UART1_8,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_33] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_PCIE0_3,
+ PINCTRL_GRP_PMU0_7,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_11,
+ PINCTRL_GRP_GPIO0_33,
+ PINCTRL_GRP_CAN1_8,
+ PINCTRL_GRP_I2C1_8,
+ PINCTRL_GRP_SWDT1_5_RST,
+ PINCTRL_GRP_SPI1_2_SS2,
+ PINCTRL_GRP_TTC3_4_WAV,
+ PINCTRL_GRP_UART1_8,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_34] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_PCIE0_4,
+ PINCTRL_GRP_PMU0_8,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_DPAUX0_2,
+ PINCTRL_GRP_GPIO0_34,
+ PINCTRL_GRP_CAN0_8,
+ PINCTRL_GRP_I2C0_8,
+ PINCTRL_GRP_SWDT0_5_CLK,
+ PINCTRL_GRP_SPI1_2_SS1,
+ PINCTRL_GRP_TTC2_4_CLK,
+ PINCTRL_GRP_UART0_8,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_35] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_PCIE0_5,
+ PINCTRL_GRP_PMU0_9,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_DPAUX0_2,
+ PINCTRL_GRP_GPIO0_35,
+ PINCTRL_GRP_CAN0_8,
+ PINCTRL_GRP_I2C0_8,
+ PINCTRL_GRP_SWDT0_5_RST,
+ PINCTRL_GRP_SPI1_2_SS0,
+ PINCTRL_GRP_TTC2_4_WAV,
+ PINCTRL_GRP_UART0_8,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_36] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_PCIE0_6,
+ PINCTRL_GRP_PMU0_10,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_DPAUX0_3,
+ PINCTRL_GRP_GPIO0_36,
+ PINCTRL_GRP_CAN1_9,
+ PINCTRL_GRP_I2C1_9,
+ PINCTRL_GRP_SWDT1_6_CLK,
+ PINCTRL_GRP_SPI1_2,
+ PINCTRL_GRP_TTC1_4_CLK,
+ PINCTRL_GRP_UART1_9,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_37] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_PCIE0_7,
+ PINCTRL_GRP_PMU0_11,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_DPAUX0_3,
+ PINCTRL_GRP_GPIO0_37,
+ PINCTRL_GRP_CAN1_9,
+ PINCTRL_GRP_I2C1_9,
+ PINCTRL_GRP_SWDT1_6_RST,
+ PINCTRL_GRP_SPI1_2,
+ PINCTRL_GRP_TTC1_4_WAV,
+ PINCTRL_GRP_UART1_9,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_38] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_38,
+ PINCTRL_GRP_CAN0_9,
+ PINCTRL_GRP_I2C0_9,
+ PINCTRL_GRP_PJTAG0_3,
+ PINCTRL_GRP_SPI0_3,
+ PINCTRL_GRP_TTC0_4_CLK,
+ PINCTRL_GRP_UART0_9,
+ PINCTRL_GRP_TRACE0_1_CLK,
+ PINCTRL_GRP_SDIO0_4BIT_1_0,
+ PINCTRL_GRP_SDIO0_4BIT_1_1,
+ PINCTRL_GRP_SDIO0_1BIT_1_0,
+ PINCTRL_GRP_SDIO0_1BIT_1_1,
+ PINCTRL_GRP_SDIO0_1BIT_1_2,
+ PINCTRL_GRP_SDIO0_1BIT_1_3,
+ PINCTRL_GRP_SDIO0_1BIT_1_4,
+ PINCTRL_GRP_SDIO0_1BIT_1_5,
+ PINCTRL_GRP_SDIO0_1BIT_1_6,
+ PINCTRL_GRP_SDIO0_1BIT_1_7,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_39] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1_CD,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_39,
+ PINCTRL_GRP_CAN0_9,
+ PINCTRL_GRP_I2C0_9,
+ PINCTRL_GRP_PJTAG0_3,
+ PINCTRL_GRP_SPI0_3_SS2,
+ PINCTRL_GRP_TTC0_4_WAV,
+ PINCTRL_GRP_UART0_9,
+ PINCTRL_GRP_TRACE0_1_CLK,
+ PINCTRL_GRP_SDIO1_4BIT_0_0,
+ PINCTRL_GRP_SDIO1_1BIT_0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_40] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_40,
+ PINCTRL_GRP_CAN1_10,
+ PINCTRL_GRP_I2C1_10,
+ PINCTRL_GRP_PJTAG0_3,
+ PINCTRL_GRP_SPI0_3_SS1,
+ PINCTRL_GRP_TTC3_5_CLK,
+ PINCTRL_GRP_UART1_10,
+ PINCTRL_GRP_TRACE0_1,
+ PINCTRL_GRP_SDIO0_4BIT_1_0,
+ PINCTRL_GRP_SDIO0_4BIT_1_1,
+ PINCTRL_GRP_SDIO0_1BIT_1_0,
+ PINCTRL_GRP_SDIO0_1BIT_1_1,
+ PINCTRL_GRP_SDIO0_1BIT_1_2,
+ PINCTRL_GRP_SDIO0_1BIT_1_3,
+ PINCTRL_GRP_SDIO0_1BIT_1_4,
+ PINCTRL_GRP_SDIO0_1BIT_1_5,
+ PINCTRL_GRP_SDIO0_1BIT_1_6,
+ PINCTRL_GRP_SDIO0_1BIT_1_7,
+ PINCTRL_GRP_SDIO1_4BIT_0_0,
+ PINCTRL_GRP_SDIO1_1BIT_0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_41] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_41,
+ PINCTRL_GRP_CAN1_10,
+ PINCTRL_GRP_I2C1_10,
+ PINCTRL_GRP_PJTAG0_3,
+ PINCTRL_GRP_SPI0_3_SS0,
+ PINCTRL_GRP_TTC3_5_WAV,
+ PINCTRL_GRP_UART1_10,
+ PINCTRL_GRP_TRACE0_1,
+ PINCTRL_GRP_SDIO0_4BIT_1_0,
+ PINCTRL_GRP_SDIO0_1BIT_1_0,
+ PINCTRL_GRP_SDIO1_4BIT_0_0,
+ PINCTRL_GRP_SDIO1_1BIT_0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_42] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_42,
+ PINCTRL_GRP_CAN0_10,
+ PINCTRL_GRP_I2C0_10,
+ PINCTRL_GRP_SWDT0_6_CLK,
+ PINCTRL_GRP_SPI0_3,
+ PINCTRL_GRP_TTC2_5_CLK,
+ PINCTRL_GRP_UART0_10,
+ PINCTRL_GRP_TRACE0_1,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO0_4BIT_1_0,
+ PINCTRL_GRP_SDIO0_1BIT_1_1,
+ PINCTRL_GRP_SDIO1_4BIT_0_0,
+ PINCTRL_GRP_SDIO1_1BIT_0_3,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_43] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO1_0_PC,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_43,
+ PINCTRL_GRP_CAN0_10,
+ PINCTRL_GRP_I2C0_10,
+ PINCTRL_GRP_SWDT0_6_RST,
+ PINCTRL_GRP_SPI0_3,
+ PINCTRL_GRP_TTC2_5_WAV,
+ PINCTRL_GRP_UART0_10,
+ PINCTRL_GRP_TRACE0_1,
+ PINCTRL_GRP_SDIO0_4BIT_1_0,
+ PINCTRL_GRP_SDIO0_1BIT_1_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_44] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO1_0_WP,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_44,
+ PINCTRL_GRP_CAN1_11,
+ PINCTRL_GRP_I2C1_11,
+ PINCTRL_GRP_SWDT1_7_CLK,
+ PINCTRL_GRP_SPI1_3,
+ PINCTRL_GRP_TTC1_5_CLK,
+ PINCTRL_GRP_UART1_11,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_1_0,
+ PINCTRL_GRP_SDIO0_1BIT_1_3,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_45] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO1_0_CD,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_45,
+ PINCTRL_GRP_CAN1_11,
+ PINCTRL_GRP_I2C1_11,
+ PINCTRL_GRP_SWDT1_7_RST,
+ PINCTRL_GRP_SPI1_3_SS2,
+ PINCTRL_GRP_TTC1_5_WAV,
+ PINCTRL_GRP_UART1_11,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_1_1,
+ PINCTRL_GRP_SDIO0_1BIT_1_4,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_46] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_46,
+ PINCTRL_GRP_CAN0_11,
+ PINCTRL_GRP_I2C0_11,
+ PINCTRL_GRP_SWDT0_7_CLK,
+ PINCTRL_GRP_SPI1_3_SS1,
+ PINCTRL_GRP_TTC0_5_CLK,
+ PINCTRL_GRP_UART0_11,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_1_1,
+ PINCTRL_GRP_SDIO0_1BIT_1_5,
+ PINCTRL_GRP_SDIO1_4BIT_0_1,
+ PINCTRL_GRP_SDIO1_1BIT_0_4,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_47] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_47,
+ PINCTRL_GRP_CAN0_11,
+ PINCTRL_GRP_I2C0_11,
+ PINCTRL_GRP_SWDT0_7_RST,
+ PINCTRL_GRP_SPI1_3_SS0,
+ PINCTRL_GRP_TTC0_5_WAV,
+ PINCTRL_GRP_UART0_11,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_1_1,
+ PINCTRL_GRP_SDIO0_1BIT_1_6,
+ PINCTRL_GRP_SDIO1_4BIT_0_1,
+ PINCTRL_GRP_SDIO1_1BIT_0_5,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_48] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_48,
+ PINCTRL_GRP_CAN1_12,
+ PINCTRL_GRP_I2C1_12,
+ PINCTRL_GRP_SWDT1_8_CLK,
+ PINCTRL_GRP_SPI1_3,
+ PINCTRL_GRP_TTC3_6_CLK,
+ PINCTRL_GRP_UART1_12,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_1_1,
+ PINCTRL_GRP_SDIO0_1BIT_1_7,
+ PINCTRL_GRP_SDIO1_4BIT_0_1,
+ PINCTRL_GRP_SDIO1_1BIT_0_6,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_49] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1_PC,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_49,
+ PINCTRL_GRP_CAN1_12,
+ PINCTRL_GRP_I2C1_12,
+ PINCTRL_GRP_SWDT1_8_RST,
+ PINCTRL_GRP_SPI1_3,
+ PINCTRL_GRP_TTC3_6_WAV,
+ PINCTRL_GRP_UART1_12,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO1_4BIT_0_1,
+ PINCTRL_GRP_SDIO1_1BIT_0_7,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_50] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_GEMTSU0_1,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1_WP,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_50,
+ PINCTRL_GRP_CAN0_12,
+ PINCTRL_GRP_I2C0_12,
+ PINCTRL_GRP_SWDT0_8_CLK,
+ PINCTRL_GRP_MDIO1_0,
+ PINCTRL_GRP_TTC2_6_CLK,
+ PINCTRL_GRP_UART0_12,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO1_4BIT_0_0,
+ PINCTRL_GRP_SDIO1_4BIT_0_1,
+ PINCTRL_GRP_SDIO1_1BIT_0_0,
+ PINCTRL_GRP_SDIO1_1BIT_0_1,
+ PINCTRL_GRP_SDIO1_1BIT_0_2,
+ PINCTRL_GRP_SDIO1_1BIT_0_3,
+ PINCTRL_GRP_SDIO1_1BIT_0_4,
+ PINCTRL_GRP_SDIO1_1BIT_0_5,
+ PINCTRL_GRP_SDIO1_1BIT_0_6,
+ PINCTRL_GRP_SDIO1_1BIT_0_7,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_51] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_GEMTSU0_2,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_51,
+ PINCTRL_GRP_CAN0_12,
+ PINCTRL_GRP_I2C0_12,
+ PINCTRL_GRP_SWDT0_8_RST,
+ PINCTRL_GRP_MDIO1_0,
+ PINCTRL_GRP_TTC2_6_WAV,
+ PINCTRL_GRP_UART0_12,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO1_4BIT_0_0,
+ PINCTRL_GRP_SDIO1_4BIT_0_1,
+ PINCTRL_GRP_SDIO1_1BIT_0_0,
+ PINCTRL_GRP_SDIO1_1BIT_0_1,
+ PINCTRL_GRP_SDIO1_1BIT_0_2,
+ PINCTRL_GRP_SDIO1_1BIT_0_3,
+ PINCTRL_GRP_SDIO1_1BIT_0_4,
+ PINCTRL_GRP_SDIO1_1BIT_0_5,
+ PINCTRL_GRP_SDIO1_1BIT_0_6,
+ PINCTRL_GRP_SDIO1_1BIT_0_7,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_52] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_52,
+ PINCTRL_GRP_CAN1_13,
+ PINCTRL_GRP_I2C1_13,
+ PINCTRL_GRP_PJTAG0_4,
+ PINCTRL_GRP_SPI0_4,
+ PINCTRL_GRP_TTC1_6_CLK,
+ PINCTRL_GRP_UART1_13,
+ PINCTRL_GRP_TRACE0_2_CLK,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_53] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_53,
+ PINCTRL_GRP_CAN1_13,
+ PINCTRL_GRP_I2C1_13,
+ PINCTRL_GRP_PJTAG0_4,
+ PINCTRL_GRP_SPI0_4_SS2,
+ PINCTRL_GRP_TTC1_6_WAV,
+ PINCTRL_GRP_UART1_13,
+ PINCTRL_GRP_TRACE0_2_CLK,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_54] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_54,
+ PINCTRL_GRP_CAN0_13,
+ PINCTRL_GRP_I2C0_13,
+ PINCTRL_GRP_PJTAG0_4,
+ PINCTRL_GRP_SPI0_4_SS1,
+ PINCTRL_GRP_TTC0_6_CLK,
+ PINCTRL_GRP_UART0_13,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_55] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_55,
+ PINCTRL_GRP_CAN0_13,
+ PINCTRL_GRP_I2C0_13,
+ PINCTRL_GRP_PJTAG0_4,
+ PINCTRL_GRP_SPI0_4_SS0,
+ PINCTRL_GRP_TTC0_6_WAV,
+ PINCTRL_GRP_UART0_13,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_56] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_56,
+ PINCTRL_GRP_CAN1_14,
+ PINCTRL_GRP_I2C1_14,
+ PINCTRL_GRP_SWDT1_9_CLK,
+ PINCTRL_GRP_SPI0_4,
+ PINCTRL_GRP_TTC3_7_CLK,
+ PINCTRL_GRP_UART1_14,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_57] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_57,
+ PINCTRL_GRP_CAN1_14,
+ PINCTRL_GRP_I2C1_14,
+ PINCTRL_GRP_SWDT1_9_RST,
+ PINCTRL_GRP_SPI0_4,
+ PINCTRL_GRP_TTC3_7_WAV,
+ PINCTRL_GRP_UART1_14,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_58] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_58,
+ PINCTRL_GRP_CAN0_14,
+ PINCTRL_GRP_I2C0_14,
+ PINCTRL_GRP_PJTAG0_5,
+ PINCTRL_GRP_SPI1_4,
+ PINCTRL_GRP_TTC2_7_CLK,
+ PINCTRL_GRP_UART0_14,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_59] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_59,
+ PINCTRL_GRP_CAN0_14,
+ PINCTRL_GRP_I2C0_14,
+ PINCTRL_GRP_PJTAG0_5,
+ PINCTRL_GRP_SPI1_4_SS2,
+ PINCTRL_GRP_TTC2_7_WAV,
+ PINCTRL_GRP_UART0_14,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_60] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_60,
+ PINCTRL_GRP_CAN1_15,
+ PINCTRL_GRP_I2C1_15,
+ PINCTRL_GRP_PJTAG0_5,
+ PINCTRL_GRP_SPI1_4_SS1,
+ PINCTRL_GRP_TTC1_7_CLK,
+ PINCTRL_GRP_UART1_15,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_61] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_61,
+ PINCTRL_GRP_CAN1_15,
+ PINCTRL_GRP_I2C1_15,
+ PINCTRL_GRP_PJTAG0_5,
+ PINCTRL_GRP_SPI1_4_SS0,
+ PINCTRL_GRP_TTC1_7_WAV,
+ PINCTRL_GRP_UART1_15,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_62] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_62,
+ PINCTRL_GRP_CAN0_15,
+ PINCTRL_GRP_I2C0_15,
+ PINCTRL_GRP_SWDT0_9_CLK,
+ PINCTRL_GRP_SPI1_4,
+ PINCTRL_GRP_TTC0_7_CLK,
+ PINCTRL_GRP_UART0_15,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_63] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_63,
+ PINCTRL_GRP_CAN0_15,
+ PINCTRL_GRP_I2C0_15,
+ PINCTRL_GRP_SWDT0_9_RST,
+ PINCTRL_GRP_SPI1_4,
+ PINCTRL_GRP_TTC0_7_WAV,
+ PINCTRL_GRP_UART0_15,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_64] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_64,
+ PINCTRL_GRP_CAN1_16,
+ PINCTRL_GRP_I2C1_16,
+ PINCTRL_GRP_SWDT1_10_CLK,
+ PINCTRL_GRP_SPI0_5,
+ PINCTRL_GRP_TTC3_8_CLK,
+ PINCTRL_GRP_UART1_16,
+ PINCTRL_GRP_TRACE0_2,
+ PINCTRL_GRP_SDIO0_4BIT_2_0,
+ PINCTRL_GRP_SDIO0_4BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_2_0,
+ PINCTRL_GRP_SDIO0_1BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_2_2,
+ PINCTRL_GRP_SDIO0_1BIT_2_3,
+ PINCTRL_GRP_SDIO0_1BIT_2_4,
+ PINCTRL_GRP_SDIO0_1BIT_2_5,
+ PINCTRL_GRP_SDIO0_1BIT_2_6,
+ PINCTRL_GRP_SDIO0_1BIT_2_7,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_65] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2_CD,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_65,
+ PINCTRL_GRP_CAN1_16,
+ PINCTRL_GRP_I2C1_16,
+ PINCTRL_GRP_SWDT1_10_RST,
+ PINCTRL_GRP_SPI0_5_SS2,
+ PINCTRL_GRP_TTC3_8_WAV,
+ PINCTRL_GRP_UART1_16,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_66] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_66,
+ PINCTRL_GRP_CAN0_16,
+ PINCTRL_GRP_I2C0_16,
+ PINCTRL_GRP_SWDT0_10_CLK,
+ PINCTRL_GRP_SPI0_5_SS1,
+ PINCTRL_GRP_TTC2_8_CLK,
+ PINCTRL_GRP_UART0_16,
+ PINCTRL_GRP_TRACE0_2,
+ PINCTRL_GRP_SDIO0_4BIT_2_0,
+ PINCTRL_GRP_SDIO0_4BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_2_0,
+ PINCTRL_GRP_SDIO0_1BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_2_2,
+ PINCTRL_GRP_SDIO0_1BIT_2_3,
+ PINCTRL_GRP_SDIO0_1BIT_2_4,
+ PINCTRL_GRP_SDIO0_1BIT_2_5,
+ PINCTRL_GRP_SDIO0_1BIT_2_6,
+ PINCTRL_GRP_SDIO0_1BIT_2_7,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_67] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_67,
+ PINCTRL_GRP_CAN0_16,
+ PINCTRL_GRP_I2C0_16,
+ PINCTRL_GRP_SWDT0_10_RST,
+ PINCTRL_GRP_SPI0_5_SS0,
+ PINCTRL_GRP_TTC2_8_WAV,
+ PINCTRL_GRP_UART0_16,
+ PINCTRL_GRP_TRACE0_2,
+ PINCTRL_GRP_SDIO0_4BIT_2_0,
+ PINCTRL_GRP_SDIO0_1BIT_2_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_68] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_68,
+ PINCTRL_GRP_CAN1_17,
+ PINCTRL_GRP_I2C1_17,
+ PINCTRL_GRP_SWDT1_11_CLK,
+ PINCTRL_GRP_SPI0_5,
+ PINCTRL_GRP_TTC1_8_CLK,
+ PINCTRL_GRP_UART1_17,
+ PINCTRL_GRP_TRACE0_2,
+ PINCTRL_GRP_SDIO0_4BIT_2_0,
+ PINCTRL_GRP_SDIO0_1BIT_2_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_69] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_SDIO1_1_WP,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_69,
+ PINCTRL_GRP_CAN1_17,
+ PINCTRL_GRP_I2C1_17,
+ PINCTRL_GRP_SWDT1_11_RST,
+ PINCTRL_GRP_SPI0_5,
+ PINCTRL_GRP_TTC1_8_WAV,
+ PINCTRL_GRP_UART1_17,
+ PINCTRL_GRP_TRACE0_2,
+ PINCTRL_GRP_SDIO0_4BIT_2_0,
+ PINCTRL_GRP_SDIO0_1BIT_2_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_70] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_SDIO1_1_PC,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_70,
+ PINCTRL_GRP_CAN0_17,
+ PINCTRL_GRP_I2C0_17,
+ PINCTRL_GRP_SWDT0_11_CLK,
+ PINCTRL_GRP_SPI1_5,
+ PINCTRL_GRP_TTC0_8_CLK,
+ PINCTRL_GRP_UART0_17,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_2_0,
+ PINCTRL_GRP_SDIO0_1BIT_2_3,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_71] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_SDIO1_4BIT_1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_71,
+ PINCTRL_GRP_CAN0_17,
+ PINCTRL_GRP_I2C0_17,
+ PINCTRL_GRP_SWDT0_11_RST,
+ PINCTRL_GRP_SPI1_5_SS2,
+ PINCTRL_GRP_TTC0_8_WAV,
+ PINCTRL_GRP_UART0_17,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_SDIO0_4BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_2_4,
+ PINCTRL_GRP_SDIO1_1BIT_1_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_72] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_SDIO1_4BIT_1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_72,
+ PINCTRL_GRP_CAN1_18,
+ PINCTRL_GRP_I2C1_18,
+ PINCTRL_GRP_SWDT1_12_CLK,
+ PINCTRL_GRP_SPI1_5_SS1,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_UART1_18,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_2_5,
+ PINCTRL_GRP_SDIO1_1BIT_1_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_73] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_SDIO1_4BIT_1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_73,
+ PINCTRL_GRP_CAN1_18,
+ PINCTRL_GRP_I2C1_18,
+ PINCTRL_GRP_SWDT1_12_RST,
+ PINCTRL_GRP_SPI1_5_SS0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_UART1_18,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_2_6,
+ PINCTRL_GRP_SDIO1_1BIT_1_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_74] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_SDIO1_4BIT_1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_74,
+ PINCTRL_GRP_CAN0_18,
+ PINCTRL_GRP_I2C0_18,
+ PINCTRL_GRP_SWDT0_12_CLK,
+ PINCTRL_GRP_SPI1_5,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_UART0_18,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_2_7,
+ PINCTRL_GRP_SDIO1_1BIT_1_3,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_75] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2_PC,
+ PINCTRL_GRP_SDIO1_4BIT_1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_75,
+ PINCTRL_GRP_CAN0_18,
+ PINCTRL_GRP_I2C0_18,
+ PINCTRL_GRP_SWDT0_12_RST,
+ PINCTRL_GRP_SPI1_5,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_UART0_18,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO1_1BIT_1_0,
+ PINCTRL_GRP_SDIO1_1BIT_1_1,
+ PINCTRL_GRP_SDIO1_1BIT_1_2,
+ PINCTRL_GRP_SDIO1_1BIT_1_3,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_76] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_2_WP,
+ PINCTRL_GRP_SDIO1_4BIT_1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_76,
+ PINCTRL_GRP_CAN1_19,
+ PINCTRL_GRP_I2C1_19,
+ PINCTRL_GRP_MDIO0_0,
+ PINCTRL_GRP_MDIO1_1,
+ PINCTRL_GRP_MDIO2_0,
+ PINCTRL_GRP_MDIO3_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO1_1BIT_1_0,
+ PINCTRL_GRP_SDIO1_1BIT_1_1,
+ PINCTRL_GRP_SDIO1_1BIT_1_2,
+ PINCTRL_GRP_SDIO1_1BIT_1_3,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_77] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO1_1_CD,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_77,
+ PINCTRL_GRP_CAN1_19,
+ PINCTRL_GRP_I2C1_19,
+ PINCTRL_GRP_MDIO0_0,
+ PINCTRL_GRP_MDIO1_1,
+ PINCTRL_GRP_MDIO2_0,
+ PINCTRL_GRP_MDIO3_0,
+ PINCTRL_GRP_RESERVED,
+ END_OF_GROUPS,
+ }),
+ },
+};
+
+/**
+ * pm_api_pinctrl_get_num_pins() - PM call to request number of pins
+ * @npins Number of pins
+ *
+ * This function is used by master to get number of pins
+ *
+ * @return Returns success.
+ */
+enum pm_ret_status pm_api_pinctrl_get_num_pins(unsigned int *npins)
+{
+ *npins = MAX_PIN;
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_api_pinctrl_get_num_functions() - PM call to request number of functions
+ * @nfuncs Number of functions
+ *
+ * This function is used by master to get number of functions
+ *
+ * @return Returns success.
+ */
+enum pm_ret_status pm_api_pinctrl_get_num_functions(unsigned int *nfuncs)
+{
+ *nfuncs = MAX_FUNCTION;
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_api_pinctrl_get_num_func_groups() - PM call to request number of
+ * function groups
+ * @fid Function Id
+ * @ngroups Number of function groups
+ *
+ * This function is used by master to get number of function groups
+ *
+ * @return Returns success.
+ */
+enum pm_ret_status pm_api_pinctrl_get_num_func_groups(unsigned int fid,
+ unsigned int *ngroups)
+{
+ int i = 0;
+ uint16_t *grps;
+
+ if (fid >= MAX_FUNCTION)
+ return PM_RET_ERROR_ARGS;
+
+ *ngroups = 0;
+
+ grps = *pinctrl_functions[fid].groups;
+ if (grps == NULL)
+ return PM_RET_SUCCESS;
+
+ while (grps[i++] != (uint16_t)END_OF_GROUPS)
+ (*ngroups)++;
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_api_pinctrl_get_function_name() - PM call to request a function name
+ * @fid Function ID
+ * @name Name of function (max 16 bytes)
+ *
+ * This function is used by master to get name of function specified
+ * by given function ID.
+ *
+ * @return Returns success. In case of error, name data is 0.
+ */
+enum pm_ret_status pm_api_pinctrl_get_function_name(unsigned int fid,
+ char *name)
+{
+ if (fid >= MAX_FUNCTION)
+ memcpy(name, END_OF_FUNCTION, FUNCTION_NAME_LEN);
+ else
+ memcpy(name, pinctrl_functions[fid].name, FUNCTION_NAME_LEN);
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_api_pinctrl_get_function_groups() - PM call to request first 6 function
+ * groups of function Id
+ * @fid Function ID
+ * @index Index of next function groups
+ * @groups Function groups
+ *
+ * This function is used by master to get function groups specified
+ * by given function Id. This API will return 6 function groups with
+ * a single response. To get other function groups, master should call
+ * same API in loop with new function groups index till error is returned.
+ *
+ * E.g First call should have index 0 which will return function groups
+ * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
+ * function groups 6, 7, 8, 9, 10 and 11 and so on.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_pinctrl_get_function_groups(unsigned int fid,
+ unsigned int index,
+ uint16_t *groups)
+{
+ unsigned int i;
+ uint16_t *grps;
+
+ if (fid >= MAX_FUNCTION)
+ return PM_RET_ERROR_ARGS;
+
+ memset(groups, END_OF_GROUPS, GROUPS_PAYLOAD_LEN);
+
+ grps = *pinctrl_functions[fid].groups;
+ if (grps == NULL)
+ return PM_RET_SUCCESS;
+
+ /* Skip groups till index */
+ for (i = 0; i < index; i++)
+ if (grps[i] == (uint16_t)END_OF_GROUPS)
+ return PM_RET_SUCCESS;
+
+ for (i = 0; i < NUM_GROUPS_PER_RESP; i++) {
+ groups[i] = grps[index + i];
+ if (groups[i] == (uint16_t)END_OF_GROUPS)
+ break;
+ }
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_api_pinctrl_get_pin_groups() - PM call to request first 6 pin
+ * groups of pin
+ * @pin Pin
+ * @index Index of next pin groups
+ * @groups pin groups
+ *
+ * This function is used by master to get pin groups specified
+ * by given pin Id. This API will return 6 pin groups with
+ * a single response. To get other pin groups, master should call
+ * same API in loop with new pin groups index till error is returned.
+ *
+ * E.g First call should have index 0 which will return pin groups
+ * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
+ * pin groups 6, 7, 8, 9, 10 and 11 and so on.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_pinctrl_get_pin_groups(unsigned int pin,
+ unsigned int index,
+ uint16_t *groups)
+{
+ unsigned int i;
+ uint16_t *grps;
+
+ if (pin >= MAX_PIN)
+ return PM_RET_ERROR_ARGS;
+
+ memset(groups, END_OF_GROUPS, GROUPS_PAYLOAD_LEN);
+
+ grps = *zynqmp_pin_groups[pin].groups;
+ if (!grps)
+ return PM_RET_SUCCESS;
+
+ /* Skip groups till index */
+ for (i = 0; i < index; i++)
+ if (grps[i] == (uint16_t)END_OF_GROUPS)
+ return PM_RET_SUCCESS;
+
+ for (i = 0; i < NUM_GROUPS_PER_RESP; i++) {
+ groups[i] = grps[index + i];
+ if (groups[i] == (uint16_t)END_OF_GROUPS)
+ break;
+ }
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_api_pinctrl_get_function() - Read function id set for the given pin
+ * @pin Pin number
+ * @nid Node ID of function currently set for given pin
+ *
+ * This function provides the function currently set for the given pin.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_pinctrl_get_function(unsigned int pin,
+ unsigned int *id)
+{
+ unsigned int i = 0, j = 0;
+ enum pm_ret_status ret = PM_RET_SUCCESS;
+ unsigned int ctrlreg, val, gid;
+ uint16_t *grps;
+
+ ctrlreg = IOU_SLCR_BASEADDR + 4U * pin;
+ ret = pm_mmio_read(ctrlreg, &val);
+ if (ret != PM_RET_SUCCESS)
+ return ret;
+
+ val &= PINCTRL_FUNCTION_MASK;
+
+ for (i = 0; i < NFUNCS_PER_PIN; i++)
+ if (val == pm_pinctrl_mux[i])
+ break;
+
+ if (i == NFUNCS_PER_PIN)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ gid = *(*zynqmp_pin_groups[pin].groups + i);
+
+ for (i = 0; i < MAX_FUNCTION; i++) {
+ grps = *pinctrl_functions[i].groups;
+ if (grps == NULL)
+ continue;
+ if (val != pinctrl_functions[i].regval)
+ continue;
+
+ for (j = 0; grps[j] != (uint16_t)END_OF_GROUPS; j++) {
+ if (gid == grps[j]) {
+ *id = i;
+ goto done;
+ }
+ }
+ }
+ if (i == MAX_FUNCTION)
+ ret = PM_RET_ERROR_ARGS;
+done:
+ return ret;
+}
+
+/**
+ * pm_api_pinctrl_set_function() - Set function id set for the given pin
+ * @pin Pin number
+ * @nid Node ID of function to set for given pin
+ *
+ * This function provides the function currently set for the given pin.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_pinctrl_set_function(unsigned int pin,
+ unsigned int fid)
+{
+ int i, j;
+ unsigned int ctrlreg, val;
+ uint16_t *pgrps, *fgrps;
+
+ ctrlreg = IOU_SLCR_BASEADDR + 4U * pin;
+ val = pinctrl_functions[fid].regval;
+
+ for (i = 0; i < NFUNCS_PER_PIN; i++)
+ if (val == pm_pinctrl_mux[i])
+ break;
+
+ if (i == NFUNCS_PER_PIN)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ pgrps = *zynqmp_pin_groups[pin].groups;
+ if (!pgrps)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ fgrps = *pinctrl_functions[fid].groups;
+ if (!fgrps)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ for (i = 0; fgrps[i] != (uint16_t)END_OF_GROUPS; i++)
+ for (j = 0; pgrps[j] != (uint16_t)END_OF_GROUPS; j++)
+ if (fgrps[i] == pgrps[j])
+ goto match;
+
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+match:
+ return pm_mmio_write(ctrlreg, PINCTRL_FUNCTION_MASK, val);
+}
+
+/**
+ * pm_api_pinctrl_set_config() - Set configuration parameter for given pin
+ * @pin: Pin for which configuration is to be set
+ * @param: Configuration parameter to be set
+ * @value: Value to be set for configuration parameter
+ *
+ * This function sets value of requested configuration parameter for given pin.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_pinctrl_set_config(unsigned int pin,
+ unsigned int param,
+ unsigned int value)
+{
+ enum pm_ret_status ret;
+ unsigned int ctrlreg, mask, val, offset;
+
+ if (param >= PINCTRL_CONFIG_MAX)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ if (pin >= PINCTRL_NUM_MIOS)
+ return PM_RET_ERROR_ARGS;
+
+ mask = 1 << PINCTRL_PIN_OFFSET(pin);
+
+ switch (param) {
+ case PINCTRL_CONFIG_SLEW_RATE:
+ if (value != PINCTRL_SLEW_RATE_FAST &&
+ value != PINCTRL_SLEW_RATE_SLOW)
+ return PM_RET_ERROR_ARGS;
+
+ ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
+ PINCTRL_SLEWCTRL_REG_OFFSET,
+ pin);
+ val = value << PINCTRL_PIN_OFFSET(pin);
+ ret = pm_mmio_write(ctrlreg, mask, val);
+ break;
+ case PINCTRL_CONFIG_BIAS_STATUS:
+ if (value != PINCTRL_BIAS_ENABLE &&
+ value != PINCTRL_BIAS_DISABLE)
+ return PM_RET_ERROR_ARGS;
+
+ ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
+ PINCTRL_PULLSTAT_REG_OFFSET,
+ pin);
+
+ offset = PINCTRL_PIN_OFFSET(pin);
+ if (ctrlreg == IOU_SLCR_BANK1_CTRL5)
+ offset = (offset < 12U) ?
+ (offset + 14U) : (offset - 12U);
+
+ val = value << offset;
+ mask = 1 << offset;
+ ret = pm_mmio_write(ctrlreg, mask, val);
+ break;
+ case PINCTRL_CONFIG_PULL_CTRL:
+
+ if (value != PINCTRL_BIAS_PULL_DOWN &&
+ value != PINCTRL_BIAS_PULL_UP)
+ return PM_RET_ERROR_ARGS;
+
+ ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
+ PINCTRL_PULLSTAT_REG_OFFSET,
+ pin);
+
+ offset = PINCTRL_PIN_OFFSET(pin);
+ if (ctrlreg == IOU_SLCR_BANK1_CTRL5)
+ offset = (offset < 12U) ?
+ (offset + 14U) : (offset - 12U);
+
+ val = PINCTRL_BIAS_ENABLE << offset;
+ ret = pm_mmio_write(ctrlreg, 1 << offset, val);
+ if (ret != PM_RET_SUCCESS)
+ return ret;
+
+ ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
+ PINCTRL_PULLCTRL_REG_OFFSET,
+ pin);
+ val = value << PINCTRL_PIN_OFFSET(pin);
+ ret = pm_mmio_write(ctrlreg, mask, val);
+ break;
+ case PINCTRL_CONFIG_SCHMITT_CMOS:
+ if (value != PINCTRL_INPUT_TYPE_CMOS &&
+ value != PINCTRL_INPUT_TYPE_SCHMITT)
+ return PM_RET_ERROR_ARGS;
+
+ ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
+ PINCTRL_SCHCMOS_REG_OFFSET,
+ pin);
+
+ val = value << PINCTRL_PIN_OFFSET(pin);
+ ret = pm_mmio_write(ctrlreg, mask, val);
+ break;
+ case PINCTRL_CONFIG_DRIVE_STRENGTH:
+ if (value > PINCTRL_DRIVE_STRENGTH_12MA)
+ return PM_RET_ERROR_ARGS;
+
+ ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
+ PINCTRL_DRVSTRN0_REG_OFFSET,
+ pin);
+ val = (value >> 1) << PINCTRL_PIN_OFFSET(pin);
+ ret = pm_mmio_write(ctrlreg, mask, val);
+ if (ret)
+ return ret;
+
+ ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
+ PINCTRL_DRVSTRN1_REG_OFFSET,
+ pin);
+ val = (value & 0x01U) << PINCTRL_PIN_OFFSET(pin);
+ ret = pm_mmio_write(ctrlreg, mask, val);
+ break;
+ default:
+ ERROR("Invalid parameter %u\n", param);
+ ret = PM_RET_ERROR_NOTSUPPORTED;
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * pm_api_pinctrl_get_config() - Get configuration parameter value for given pin
+ * @pin: Pin for which configuration is to be read
+ * @param: Configuration parameter to be read
+ * @value: buffer to store value of configuration parameter
+ *
+ * This function reads value of requested configuration parameter for given pin.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_pinctrl_get_config(unsigned int pin,
+ unsigned int param,
+ unsigned int *value)
+{
+ enum pm_ret_status ret;
+ unsigned int ctrlreg, val;
+
+ if (param >= PINCTRL_CONFIG_MAX)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ if (pin >= PINCTRL_NUM_MIOS)
+ return PM_RET_ERROR_ARGS;
+
+ switch (param) {
+ case PINCTRL_CONFIG_SLEW_RATE:
+ ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
+ PINCTRL_SLEWCTRL_REG_OFFSET,
+ pin);
+
+ ret = pm_mmio_read(ctrlreg, &val);
+ if (ret != PM_RET_SUCCESS)
+ return ret;
+
+ *value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
+ break;
+ case PINCTRL_CONFIG_BIAS_STATUS:
+ ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
+ PINCTRL_PULLSTAT_REG_OFFSET,
+ pin);
+
+ ret = pm_mmio_read(ctrlreg, &val);
+ if (ret)
+ return ret;
+
+ if (ctrlreg == IOU_SLCR_BANK1_CTRL5)
+ val = ((val & 0x3FFF) << 12) | ((val >> 14) & 0xFFF);
+
+ *value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
+ break;
+ case PINCTRL_CONFIG_PULL_CTRL:
+
+ ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
+ PINCTRL_PULLCTRL_REG_OFFSET,
+ pin);
+
+ ret = pm_mmio_read(ctrlreg, &val);
+ if (ret)
+ return ret;
+
+ *value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
+ break;
+ case PINCTRL_CONFIG_SCHMITT_CMOS:
+ ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
+ PINCTRL_SCHCMOS_REG_OFFSET,
+ pin);
+
+ ret = pm_mmio_read(ctrlreg, &val);
+ if (ret)
+ return ret;
+
+ *value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
+ break;
+ case PINCTRL_CONFIG_DRIVE_STRENGTH:
+ ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
+ PINCTRL_DRVSTRN0_REG_OFFSET,
+ pin);
+ ret = pm_mmio_read(ctrlreg, &val);
+ if (ret)
+ return ret;
+
+ *value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val) << 1;
+
+ ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
+ PINCTRL_DRVSTRN1_REG_OFFSET,
+ pin);
+ ret = pm_mmio_read(ctrlreg, &val);
+ if (ret)
+ return ret;
+
+ *value |= PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
+ break;
+ case PINCTRL_CONFIG_VOLTAGE_STATUS:
+ ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
+ PINCTRL_VOLTAGE_STAT_REG_OFFSET,
+ pin);
+
+ ret = pm_mmio_read(ctrlreg, &val);
+ if (ret)
+ return ret;
+
+ *value = val & PINCTRL_VOLTAGE_STATUS_MASK;
+ break;
+ default:
+ return PM_RET_ERROR_NOTSUPPORTED;
+ }
+
+ return PM_RET_SUCCESS;
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h
new file mode 100644
index 0000000..c70a774
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h
@@ -0,0 +1,734 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * ZynqMP system level PM-API functions for pin control.
+ */
+
+#ifndef _PM_API_PINCTRL_H_
+#define _PM_API_PINCTRL_H_
+
+#include "pm_common.h"
+
+#define FUNCTION_NAME_LEN U(16)
+#define GROUPS_PAYLOAD_LEN U(12)
+#define NUM_GROUPS_PER_RESP U(6)
+#define END_OF_FUNCTION "END_OF_FUNCTION"
+#define END_OF_GROUPS -1
+#define PINCTRL_GRP_RESERVED -2
+
+//pinctrl function ids
+enum {
+ PINCTRL_FUNC_CAN0,
+ PINCTRL_FUNC_CAN1,
+ PINCTRL_FUNC_ETHERNET0,
+ PINCTRL_FUNC_ETHERNET1,
+ PINCTRL_FUNC_ETHERNET2,
+ PINCTRL_FUNC_ETHERNET3,
+ PINCTRL_FUNC_GEMTSU0,
+ PINCTRL_FUNC_GPIO0,
+ PINCTRL_FUNC_I2C0,
+ PINCTRL_FUNC_I2C1,
+ PINCTRL_FUNC_MDIO0,
+ PINCTRL_FUNC_MDIO1,
+ PINCTRL_FUNC_MDIO2,
+ PINCTRL_FUNC_MDIO3,
+ PINCTRL_FUNC_QSPI0,
+ PINCTRL_FUNC_QSPI_FBCLK,
+ PINCTRL_FUNC_QSPI_SS,
+ PINCTRL_FUNC_SPI0,
+ PINCTRL_FUNC_SPI1,
+ PINCTRL_FUNC_SPI0_SS,
+ PINCTRL_FUNC_SPI1_SS,
+ PINCTRL_FUNC_SDIO0,
+ PINCTRL_FUNC_SDIO0_PC,
+ PINCTRL_FUNC_SDIO0_CD,
+ PINCTRL_FUNC_SDIO0_WP,
+ PINCTRL_FUNC_SDIO1,
+ PINCTRL_FUNC_SDIO1_PC,
+ PINCTRL_FUNC_SDIO1_CD,
+ PINCTRL_FUNC_SDIO1_WP,
+ PINCTRL_FUNC_NAND0,
+ PINCTRL_FUNC_NAND0_CE,
+ PINCTRL_FUNC_NAND0_RB,
+ PINCTRL_FUNC_NAND0_DQS,
+ PINCTRL_FUNC_TTC0_CLK,
+ PINCTRL_FUNC_TTC0_WAV,
+ PINCTRL_FUNC_TTC1_CLK,
+ PINCTRL_FUNC_TTC1_WAV,
+ PINCTRL_FUNC_TTC2_CLK,
+ PINCTRL_FUNC_TTC2_WAV,
+ PINCTRL_FUNC_TTC3_CLK,
+ PINCTRL_FUNC_TTC3_WAV,
+ PINCTRL_FUNC_UART0,
+ PINCTRL_FUNC_UART1,
+ PINCTRL_FUNC_USB0,
+ PINCTRL_FUNC_USB1,
+ PINCTRL_FUNC_SWDT0_CLK,
+ PINCTRL_FUNC_SWDT0_RST,
+ PINCTRL_FUNC_SWDT1_CLK,
+ PINCTRL_FUNC_SWDT1_RST,
+ PINCTRL_FUNC_PMU0,
+ PINCTRL_FUNC_PCIE0,
+ PINCTRL_FUNC_CSU0,
+ PINCTRL_FUNC_DPAUX0,
+ PINCTRL_FUNC_PJTAG0,
+ PINCTRL_FUNC_TRACE0,
+ PINCTRL_FUNC_TRACE0_CLK,
+ PINCTRL_FUNC_TESTSCAN0,
+ END_FUNCTION,
+};
+
+#define MAX_FUNCTION (unsigned int)(END_FUNCTION)
+
+// pinctrl pin numbers
+enum {
+ PINCTRL_PIN_0,
+ PINCTRL_PIN_1,
+ PINCTRL_PIN_2,
+ PINCTRL_PIN_3,
+ PINCTRL_PIN_4,
+ PINCTRL_PIN_5,
+ PINCTRL_PIN_6,
+ PINCTRL_PIN_7,
+ PINCTRL_PIN_8,
+ PINCTRL_PIN_9,
+ PINCTRL_PIN_10,
+ PINCTRL_PIN_11,
+ PINCTRL_PIN_12,
+ PINCTRL_PIN_13,
+ PINCTRL_PIN_14,
+ PINCTRL_PIN_15,
+ PINCTRL_PIN_16,
+ PINCTRL_PIN_17,
+ PINCTRL_PIN_18,
+ PINCTRL_PIN_19,
+ PINCTRL_PIN_20,
+ PINCTRL_PIN_21,
+ PINCTRL_PIN_22,
+ PINCTRL_PIN_23,
+ PINCTRL_PIN_24,
+ PINCTRL_PIN_25,
+ PINCTRL_PIN_26,
+ PINCTRL_PIN_27,
+ PINCTRL_PIN_28,
+ PINCTRL_PIN_29,
+ PINCTRL_PIN_30,
+ PINCTRL_PIN_31,
+ PINCTRL_PIN_32,
+ PINCTRL_PIN_33,
+ PINCTRL_PIN_34,
+ PINCTRL_PIN_35,
+ PINCTRL_PIN_36,
+ PINCTRL_PIN_37,
+ PINCTRL_PIN_38,
+ PINCTRL_PIN_39,
+ PINCTRL_PIN_40,
+ PINCTRL_PIN_41,
+ PINCTRL_PIN_42,
+ PINCTRL_PIN_43,
+ PINCTRL_PIN_44,
+ PINCTRL_PIN_45,
+ PINCTRL_PIN_46,
+ PINCTRL_PIN_47,
+ PINCTRL_PIN_48,
+ PINCTRL_PIN_49,
+ PINCTRL_PIN_50,
+ PINCTRL_PIN_51,
+ PINCTRL_PIN_52,
+ PINCTRL_PIN_53,
+ PINCTRL_PIN_54,
+ PINCTRL_PIN_55,
+ PINCTRL_PIN_56,
+ PINCTRL_PIN_57,
+ PINCTRL_PIN_58,
+ PINCTRL_PIN_59,
+ PINCTRL_PIN_60,
+ PINCTRL_PIN_61,
+ PINCTRL_PIN_62,
+ PINCTRL_PIN_63,
+ PINCTRL_PIN_64,
+ PINCTRL_PIN_65,
+ PINCTRL_PIN_66,
+ PINCTRL_PIN_67,
+ PINCTRL_PIN_68,
+ PINCTRL_PIN_69,
+ PINCTRL_PIN_70,
+ PINCTRL_PIN_71,
+ PINCTRL_PIN_72,
+ PINCTRL_PIN_73,
+ PINCTRL_PIN_74,
+ PINCTRL_PIN_75,
+ PINCTRL_PIN_76,
+ PINCTRL_PIN_77,
+ END_PINS,
+};
+
+#define MAX_PIN (unsigned int)(END_PINS)
+
+// pinctrl group ids
+enum {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_GEMTSU0_0,
+ PINCTRL_GRP_GEMTSU0_1,
+ PINCTRL_GRP_GEMTSU0_2,
+ PINCTRL_GRP_MDIO0_0,
+ PINCTRL_GRP_MDIO1_0,
+ PINCTRL_GRP_MDIO1_1,
+ PINCTRL_GRP_MDIO2_0,
+ PINCTRL_GRP_MDIO3_0,
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_QSPI_SS,
+ PINCTRL_GRP_QSPI_FBCLK,
+ PINCTRL_GRP_SPI0_0,
+ PINCTRL_GRP_SPI0_0_SS0,
+ PINCTRL_GRP_SPI0_0_SS1,
+ PINCTRL_GRP_SPI0_0_SS2,
+ PINCTRL_GRP_SPI0_1,
+ PINCTRL_GRP_SPI0_1_SS0,
+ PINCTRL_GRP_SPI0_1_SS1,
+ PINCTRL_GRP_SPI0_1_SS2,
+ PINCTRL_GRP_SPI0_2,
+ PINCTRL_GRP_SPI0_2_SS0,
+ PINCTRL_GRP_SPI0_2_SS1,
+ PINCTRL_GRP_SPI0_2_SS2,
+ PINCTRL_GRP_SPI0_3,
+ PINCTRL_GRP_SPI0_3_SS0,
+ PINCTRL_GRP_SPI0_3_SS1,
+ PINCTRL_GRP_SPI0_3_SS2,
+ PINCTRL_GRP_SPI0_4,
+ PINCTRL_GRP_SPI0_4_SS0,
+ PINCTRL_GRP_SPI0_4_SS1,
+ PINCTRL_GRP_SPI0_4_SS2,
+ PINCTRL_GRP_SPI0_5,
+ PINCTRL_GRP_SPI0_5_SS0,
+ PINCTRL_GRP_SPI0_5_SS1,
+ PINCTRL_GRP_SPI0_5_SS2,
+ PINCTRL_GRP_SPI1_0,
+ PINCTRL_GRP_SPI1_0_SS0,
+ PINCTRL_GRP_SPI1_0_SS1,
+ PINCTRL_GRP_SPI1_0_SS2,
+ PINCTRL_GRP_SPI1_1,
+ PINCTRL_GRP_SPI1_1_SS0,
+ PINCTRL_GRP_SPI1_1_SS1,
+ PINCTRL_GRP_SPI1_1_SS2,
+ PINCTRL_GRP_SPI1_2,
+ PINCTRL_GRP_SPI1_2_SS0,
+ PINCTRL_GRP_SPI1_2_SS1,
+ PINCTRL_GRP_SPI1_2_SS2,
+ PINCTRL_GRP_SPI1_3,
+ PINCTRL_GRP_SPI1_3_SS0,
+ PINCTRL_GRP_SPI1_3_SS1,
+ PINCTRL_GRP_SPI1_3_SS2,
+ PINCTRL_GRP_SPI1_4,
+ PINCTRL_GRP_SPI1_4_SS0,
+ PINCTRL_GRP_SPI1_4_SS1,
+ PINCTRL_GRP_SPI1_4_SS2,
+ PINCTRL_GRP_SPI1_5,
+ PINCTRL_GRP_SPI1_5_SS0,
+ PINCTRL_GRP_SPI1_5_SS1,
+ PINCTRL_GRP_SPI1_5_SS2,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_SDIO0_4BIT_0_0,
+ PINCTRL_GRP_SDIO0_4BIT_0_1,
+ PINCTRL_GRP_SDIO0_4BIT_1_0,
+ PINCTRL_GRP_SDIO0_4BIT_1_1,
+ PINCTRL_GRP_SDIO0_4BIT_2_0,
+ PINCTRL_GRP_SDIO0_4BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_0,
+ PINCTRL_GRP_SDIO0_1BIT_0_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_2,
+ PINCTRL_GRP_SDIO0_1BIT_0_3,
+ PINCTRL_GRP_SDIO0_1BIT_0_4,
+ PINCTRL_GRP_SDIO0_1BIT_0_5,
+ PINCTRL_GRP_SDIO0_1BIT_0_6,
+ PINCTRL_GRP_SDIO0_1BIT_0_7,
+ PINCTRL_GRP_SDIO0_1BIT_1_0,
+ PINCTRL_GRP_SDIO0_1BIT_1_1,
+ PINCTRL_GRP_SDIO0_1BIT_1_2,
+ PINCTRL_GRP_SDIO0_1BIT_1_3,
+ PINCTRL_GRP_SDIO0_1BIT_1_4,
+ PINCTRL_GRP_SDIO0_1BIT_1_5,
+ PINCTRL_GRP_SDIO0_1BIT_1_6,
+ PINCTRL_GRP_SDIO0_1BIT_1_7,
+ PINCTRL_GRP_SDIO0_1BIT_2_0,
+ PINCTRL_GRP_SDIO0_1BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_2_2,
+ PINCTRL_GRP_SDIO0_1BIT_2_3,
+ PINCTRL_GRP_SDIO0_1BIT_2_4,
+ PINCTRL_GRP_SDIO0_1BIT_2_5,
+ PINCTRL_GRP_SDIO0_1BIT_2_6,
+ PINCTRL_GRP_SDIO0_1BIT_2_7,
+ PINCTRL_GRP_SDIO0_0_PC,
+ PINCTRL_GRP_SDIO0_0_CD,
+ PINCTRL_GRP_SDIO0_0_WP,
+ PINCTRL_GRP_SDIO0_1_PC,
+ PINCTRL_GRP_SDIO0_1_CD,
+ PINCTRL_GRP_SDIO0_1_WP,
+ PINCTRL_GRP_SDIO0_2_PC,
+ PINCTRL_GRP_SDIO0_2_CD,
+ PINCTRL_GRP_SDIO0_2_WP,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_SDIO1_4BIT_0_0,
+ PINCTRL_GRP_SDIO1_4BIT_0_1,
+ PINCTRL_GRP_SDIO1_4BIT_1_0,
+ PINCTRL_GRP_SDIO1_1BIT_0_0,
+ PINCTRL_GRP_SDIO1_1BIT_0_1,
+ PINCTRL_GRP_SDIO1_1BIT_0_2,
+ PINCTRL_GRP_SDIO1_1BIT_0_3,
+ PINCTRL_GRP_SDIO1_1BIT_0_4,
+ PINCTRL_GRP_SDIO1_1BIT_0_5,
+ PINCTRL_GRP_SDIO1_1BIT_0_6,
+ PINCTRL_GRP_SDIO1_1BIT_0_7,
+ PINCTRL_GRP_SDIO1_1BIT_1_0,
+ PINCTRL_GRP_SDIO1_1BIT_1_1,
+ PINCTRL_GRP_SDIO1_1BIT_1_2,
+ PINCTRL_GRP_SDIO1_1BIT_1_3,
+ PINCTRL_GRP_SDIO1_0_PC,
+ PINCTRL_GRP_SDIO1_0_CD,
+ PINCTRL_GRP_SDIO1_0_WP,
+ PINCTRL_GRP_SDIO1_1_PC,
+ PINCTRL_GRP_SDIO1_1_CD,
+ PINCTRL_GRP_SDIO1_1_WP,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_NAND0_0_CE,
+ PINCTRL_GRP_NAND0_0_RB,
+ PINCTRL_GRP_NAND0_0_DQS,
+ PINCTRL_GRP_NAND0_1_CE,
+ PINCTRL_GRP_NAND0_1_RB,
+ PINCTRL_GRP_NAND0_1_DQS,
+ PINCTRL_GRP_CAN0_0,
+ PINCTRL_GRP_CAN0_1,
+ PINCTRL_GRP_CAN0_2,
+ PINCTRL_GRP_CAN0_3,
+ PINCTRL_GRP_CAN0_4,
+ PINCTRL_GRP_CAN0_5,
+ PINCTRL_GRP_CAN0_6,
+ PINCTRL_GRP_CAN0_7,
+ PINCTRL_GRP_CAN0_8,
+ PINCTRL_GRP_CAN0_9,
+ PINCTRL_GRP_CAN0_10,
+ PINCTRL_GRP_CAN0_11,
+ PINCTRL_GRP_CAN0_12,
+ PINCTRL_GRP_CAN0_13,
+ PINCTRL_GRP_CAN0_14,
+ PINCTRL_GRP_CAN0_15,
+ PINCTRL_GRP_CAN0_16,
+ PINCTRL_GRP_CAN0_17,
+ PINCTRL_GRP_CAN0_18,
+ PINCTRL_GRP_CAN1_0,
+ PINCTRL_GRP_CAN1_1,
+ PINCTRL_GRP_CAN1_2,
+ PINCTRL_GRP_CAN1_3,
+ PINCTRL_GRP_CAN1_4,
+ PINCTRL_GRP_CAN1_5,
+ PINCTRL_GRP_CAN1_6,
+ PINCTRL_GRP_CAN1_7,
+ PINCTRL_GRP_CAN1_8,
+ PINCTRL_GRP_CAN1_9,
+ PINCTRL_GRP_CAN1_10,
+ PINCTRL_GRP_CAN1_11,
+ PINCTRL_GRP_CAN1_12,
+ PINCTRL_GRP_CAN1_13,
+ PINCTRL_GRP_CAN1_14,
+ PINCTRL_GRP_CAN1_15,
+ PINCTRL_GRP_CAN1_16,
+ PINCTRL_GRP_CAN1_17,
+ PINCTRL_GRP_CAN1_18,
+ PINCTRL_GRP_CAN1_19,
+ PINCTRL_GRP_UART0_0,
+ PINCTRL_GRP_UART0_1,
+ PINCTRL_GRP_UART0_2,
+ PINCTRL_GRP_UART0_3,
+ PINCTRL_GRP_UART0_4,
+ PINCTRL_GRP_UART0_5,
+ PINCTRL_GRP_UART0_6,
+ PINCTRL_GRP_UART0_7,
+ PINCTRL_GRP_UART0_8,
+ PINCTRL_GRP_UART0_9,
+ PINCTRL_GRP_UART0_10,
+ PINCTRL_GRP_UART0_11,
+ PINCTRL_GRP_UART0_12,
+ PINCTRL_GRP_UART0_13,
+ PINCTRL_GRP_UART0_14,
+ PINCTRL_GRP_UART0_15,
+ PINCTRL_GRP_UART0_16,
+ PINCTRL_GRP_UART0_17,
+ PINCTRL_GRP_UART0_18,
+ PINCTRL_GRP_UART1_0,
+ PINCTRL_GRP_UART1_1,
+ PINCTRL_GRP_UART1_2,
+ PINCTRL_GRP_UART1_3,
+ PINCTRL_GRP_UART1_4,
+ PINCTRL_GRP_UART1_5,
+ PINCTRL_GRP_UART1_6,
+ PINCTRL_GRP_UART1_7,
+ PINCTRL_GRP_UART1_8,
+ PINCTRL_GRP_UART1_9,
+ PINCTRL_GRP_UART1_10,
+ PINCTRL_GRP_UART1_11,
+ PINCTRL_GRP_UART1_12,
+ PINCTRL_GRP_UART1_13,
+ PINCTRL_GRP_UART1_14,
+ PINCTRL_GRP_UART1_15,
+ PINCTRL_GRP_UART1_16,
+ PINCTRL_GRP_UART1_17,
+ PINCTRL_GRP_UART1_18,
+ PINCTRL_GRP_I2C0_0,
+ PINCTRL_GRP_I2C0_1,
+ PINCTRL_GRP_I2C0_2,
+ PINCTRL_GRP_I2C0_3,
+ PINCTRL_GRP_I2C0_4,
+ PINCTRL_GRP_I2C0_5,
+ PINCTRL_GRP_I2C0_6,
+ PINCTRL_GRP_I2C0_7,
+ PINCTRL_GRP_I2C0_8,
+ PINCTRL_GRP_I2C0_9,
+ PINCTRL_GRP_I2C0_10,
+ PINCTRL_GRP_I2C0_11,
+ PINCTRL_GRP_I2C0_12,
+ PINCTRL_GRP_I2C0_13,
+ PINCTRL_GRP_I2C0_14,
+ PINCTRL_GRP_I2C0_15,
+ PINCTRL_GRP_I2C0_16,
+ PINCTRL_GRP_I2C0_17,
+ PINCTRL_GRP_I2C0_18,
+ PINCTRL_GRP_I2C1_0,
+ PINCTRL_GRP_I2C1_1,
+ PINCTRL_GRP_I2C1_2,
+ PINCTRL_GRP_I2C1_3,
+ PINCTRL_GRP_I2C1_4,
+ PINCTRL_GRP_I2C1_5,
+ PINCTRL_GRP_I2C1_6,
+ PINCTRL_GRP_I2C1_7,
+ PINCTRL_GRP_I2C1_8,
+ PINCTRL_GRP_I2C1_9,
+ PINCTRL_GRP_I2C1_10,
+ PINCTRL_GRP_I2C1_11,
+ PINCTRL_GRP_I2C1_12,
+ PINCTRL_GRP_I2C1_13,
+ PINCTRL_GRP_I2C1_14,
+ PINCTRL_GRP_I2C1_15,
+ PINCTRL_GRP_I2C1_16,
+ PINCTRL_GRP_I2C1_17,
+ PINCTRL_GRP_I2C1_18,
+ PINCTRL_GRP_I2C1_19,
+ PINCTRL_GRP_TTC0_0_CLK,
+ PINCTRL_GRP_TTC0_0_WAV,
+ PINCTRL_GRP_TTC0_1_CLK,
+ PINCTRL_GRP_TTC0_1_WAV,
+ PINCTRL_GRP_TTC0_2_CLK,
+ PINCTRL_GRP_TTC0_2_WAV,
+ PINCTRL_GRP_TTC0_3_CLK,
+ PINCTRL_GRP_TTC0_3_WAV,
+ PINCTRL_GRP_TTC0_4_CLK,
+ PINCTRL_GRP_TTC0_4_WAV,
+ PINCTRL_GRP_TTC0_5_CLK,
+ PINCTRL_GRP_TTC0_5_WAV,
+ PINCTRL_GRP_TTC0_6_CLK,
+ PINCTRL_GRP_TTC0_6_WAV,
+ PINCTRL_GRP_TTC0_7_CLK,
+ PINCTRL_GRP_TTC0_7_WAV,
+ PINCTRL_GRP_TTC0_8_CLK,
+ PINCTRL_GRP_TTC0_8_WAV,
+ PINCTRL_GRP_TTC1_0_CLK,
+ PINCTRL_GRP_TTC1_0_WAV,
+ PINCTRL_GRP_TTC1_1_CLK,
+ PINCTRL_GRP_TTC1_1_WAV,
+ PINCTRL_GRP_TTC1_2_CLK,
+ PINCTRL_GRP_TTC1_2_WAV,
+ PINCTRL_GRP_TTC1_3_CLK,
+ PINCTRL_GRP_TTC1_3_WAV,
+ PINCTRL_GRP_TTC1_4_CLK,
+ PINCTRL_GRP_TTC1_4_WAV,
+ PINCTRL_GRP_TTC1_5_CLK,
+ PINCTRL_GRP_TTC1_5_WAV,
+ PINCTRL_GRP_TTC1_6_CLK,
+ PINCTRL_GRP_TTC1_6_WAV,
+ PINCTRL_GRP_TTC1_7_CLK,
+ PINCTRL_GRP_TTC1_7_WAV,
+ PINCTRL_GRP_TTC1_8_CLK,
+ PINCTRL_GRP_TTC1_8_WAV,
+ PINCTRL_GRP_TTC2_0_CLK,
+ PINCTRL_GRP_TTC2_0_WAV,
+ PINCTRL_GRP_TTC2_1_CLK,
+ PINCTRL_GRP_TTC2_1_WAV,
+ PINCTRL_GRP_TTC2_2_CLK,
+ PINCTRL_GRP_TTC2_2_WAV,
+ PINCTRL_GRP_TTC2_3_CLK,
+ PINCTRL_GRP_TTC2_3_WAV,
+ PINCTRL_GRP_TTC2_4_CLK,
+ PINCTRL_GRP_TTC2_4_WAV,
+ PINCTRL_GRP_TTC2_5_CLK,
+ PINCTRL_GRP_TTC2_5_WAV,
+ PINCTRL_GRP_TTC2_6_CLK,
+ PINCTRL_GRP_TTC2_6_WAV,
+ PINCTRL_GRP_TTC2_7_CLK,
+ PINCTRL_GRP_TTC2_7_WAV,
+ PINCTRL_GRP_TTC2_8_CLK,
+ PINCTRL_GRP_TTC2_8_WAV,
+ PINCTRL_GRP_TTC3_0_CLK,
+ PINCTRL_GRP_TTC3_0_WAV,
+ PINCTRL_GRP_TTC3_1_CLK,
+ PINCTRL_GRP_TTC3_1_WAV,
+ PINCTRL_GRP_TTC3_2_CLK,
+ PINCTRL_GRP_TTC3_2_WAV,
+ PINCTRL_GRP_TTC3_3_CLK,
+ PINCTRL_GRP_TTC3_3_WAV,
+ PINCTRL_GRP_TTC3_4_CLK,
+ PINCTRL_GRP_TTC3_4_WAV,
+ PINCTRL_GRP_TTC3_5_CLK,
+ PINCTRL_GRP_TTC3_5_WAV,
+ PINCTRL_GRP_TTC3_6_CLK,
+ PINCTRL_GRP_TTC3_6_WAV,
+ PINCTRL_GRP_TTC3_7_CLK,
+ PINCTRL_GRP_TTC3_7_WAV,
+ PINCTRL_GRP_TTC3_8_CLK,
+ PINCTRL_GRP_TTC3_8_WAV,
+ PINCTRL_GRP_SWDT0_0_CLK,
+ PINCTRL_GRP_SWDT0_0_RST,
+ PINCTRL_GRP_SWDT0_1_CLK,
+ PINCTRL_GRP_SWDT0_1_RST,
+ PINCTRL_GRP_SWDT0_2_CLK,
+ PINCTRL_GRP_SWDT0_2_RST,
+ PINCTRL_GRP_SWDT0_3_CLK,
+ PINCTRL_GRP_SWDT0_3_RST,
+ PINCTRL_GRP_SWDT0_4_CLK,
+ PINCTRL_GRP_SWDT0_4_RST,
+ PINCTRL_GRP_SWDT0_5_CLK,
+ PINCTRL_GRP_SWDT0_5_RST,
+ PINCTRL_GRP_SWDT0_6_CLK,
+ PINCTRL_GRP_SWDT0_6_RST,
+ PINCTRL_GRP_SWDT0_7_CLK,
+ PINCTRL_GRP_SWDT0_7_RST,
+ PINCTRL_GRP_SWDT0_8_CLK,
+ PINCTRL_GRP_SWDT0_8_RST,
+ PINCTRL_GRP_SWDT0_9_CLK,
+ PINCTRL_GRP_SWDT0_9_RST,
+ PINCTRL_GRP_SWDT0_10_CLK,
+ PINCTRL_GRP_SWDT0_10_RST,
+ PINCTRL_GRP_SWDT0_11_CLK,
+ PINCTRL_GRP_SWDT0_11_RST,
+ PINCTRL_GRP_SWDT0_12_CLK,
+ PINCTRL_GRP_SWDT0_12_RST,
+ PINCTRL_GRP_SWDT1_0_CLK,
+ PINCTRL_GRP_SWDT1_0_RST,
+ PINCTRL_GRP_SWDT1_1_CLK,
+ PINCTRL_GRP_SWDT1_1_RST,
+ PINCTRL_GRP_SWDT1_2_CLK,
+ PINCTRL_GRP_SWDT1_2_RST,
+ PINCTRL_GRP_SWDT1_3_CLK,
+ PINCTRL_GRP_SWDT1_3_RST,
+ PINCTRL_GRP_SWDT1_4_CLK,
+ PINCTRL_GRP_SWDT1_4_RST,
+ PINCTRL_GRP_SWDT1_5_CLK,
+ PINCTRL_GRP_SWDT1_5_RST,
+ PINCTRL_GRP_SWDT1_6_CLK,
+ PINCTRL_GRP_SWDT1_6_RST,
+ PINCTRL_GRP_SWDT1_7_CLK,
+ PINCTRL_GRP_SWDT1_7_RST,
+ PINCTRL_GRP_SWDT1_8_CLK,
+ PINCTRL_GRP_SWDT1_8_RST,
+ PINCTRL_GRP_SWDT1_9_CLK,
+ PINCTRL_GRP_SWDT1_9_RST,
+ PINCTRL_GRP_SWDT1_10_CLK,
+ PINCTRL_GRP_SWDT1_10_RST,
+ PINCTRL_GRP_SWDT1_11_CLK,
+ PINCTRL_GRP_SWDT1_11_RST,
+ PINCTRL_GRP_SWDT1_12_CLK,
+ PINCTRL_GRP_SWDT1_12_RST,
+ PINCTRL_GRP_GPIO0_0,
+ PINCTRL_GRP_GPIO0_1,
+ PINCTRL_GRP_GPIO0_2,
+ PINCTRL_GRP_GPIO0_3,
+ PINCTRL_GRP_GPIO0_4,
+ PINCTRL_GRP_GPIO0_5,
+ PINCTRL_GRP_GPIO0_6,
+ PINCTRL_GRP_GPIO0_7,
+ PINCTRL_GRP_GPIO0_8,
+ PINCTRL_GRP_GPIO0_9,
+ PINCTRL_GRP_GPIO0_10,
+ PINCTRL_GRP_GPIO0_11,
+ PINCTRL_GRP_GPIO0_12,
+ PINCTRL_GRP_GPIO0_13,
+ PINCTRL_GRP_GPIO0_14,
+ PINCTRL_GRP_GPIO0_15,
+ PINCTRL_GRP_GPIO0_16,
+ PINCTRL_GRP_GPIO0_17,
+ PINCTRL_GRP_GPIO0_18,
+ PINCTRL_GRP_GPIO0_19,
+ PINCTRL_GRP_GPIO0_20,
+ PINCTRL_GRP_GPIO0_21,
+ PINCTRL_GRP_GPIO0_22,
+ PINCTRL_GRP_GPIO0_23,
+ PINCTRL_GRP_GPIO0_24,
+ PINCTRL_GRP_GPIO0_25,
+ PINCTRL_GRP_GPIO0_26,
+ PINCTRL_GRP_GPIO0_27,
+ PINCTRL_GRP_GPIO0_28,
+ PINCTRL_GRP_GPIO0_29,
+ PINCTRL_GRP_GPIO0_30,
+ PINCTRL_GRP_GPIO0_31,
+ PINCTRL_GRP_GPIO0_32,
+ PINCTRL_GRP_GPIO0_33,
+ PINCTRL_GRP_GPIO0_34,
+ PINCTRL_GRP_GPIO0_35,
+ PINCTRL_GRP_GPIO0_36,
+ PINCTRL_GRP_GPIO0_37,
+ PINCTRL_GRP_GPIO0_38,
+ PINCTRL_GRP_GPIO0_39,
+ PINCTRL_GRP_GPIO0_40,
+ PINCTRL_GRP_GPIO0_41,
+ PINCTRL_GRP_GPIO0_42,
+ PINCTRL_GRP_GPIO0_43,
+ PINCTRL_GRP_GPIO0_44,
+ PINCTRL_GRP_GPIO0_45,
+ PINCTRL_GRP_GPIO0_46,
+ PINCTRL_GRP_GPIO0_47,
+ PINCTRL_GRP_GPIO0_48,
+ PINCTRL_GRP_GPIO0_49,
+ PINCTRL_GRP_GPIO0_50,
+ PINCTRL_GRP_GPIO0_51,
+ PINCTRL_GRP_GPIO0_52,
+ PINCTRL_GRP_GPIO0_53,
+ PINCTRL_GRP_GPIO0_54,
+ PINCTRL_GRP_GPIO0_55,
+ PINCTRL_GRP_GPIO0_56,
+ PINCTRL_GRP_GPIO0_57,
+ PINCTRL_GRP_GPIO0_58,
+ PINCTRL_GRP_GPIO0_59,
+ PINCTRL_GRP_GPIO0_60,
+ PINCTRL_GRP_GPIO0_61,
+ PINCTRL_GRP_GPIO0_62,
+ PINCTRL_GRP_GPIO0_63,
+ PINCTRL_GRP_GPIO0_64,
+ PINCTRL_GRP_GPIO0_65,
+ PINCTRL_GRP_GPIO0_66,
+ PINCTRL_GRP_GPIO0_67,
+ PINCTRL_GRP_GPIO0_68,
+ PINCTRL_GRP_GPIO0_69,
+ PINCTRL_GRP_GPIO0_70,
+ PINCTRL_GRP_GPIO0_71,
+ PINCTRL_GRP_GPIO0_72,
+ PINCTRL_GRP_GPIO0_73,
+ PINCTRL_GRP_GPIO0_74,
+ PINCTRL_GRP_GPIO0_75,
+ PINCTRL_GRP_GPIO0_76,
+ PINCTRL_GRP_GPIO0_77,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_PMU0_0,
+ PINCTRL_GRP_PMU0_1,
+ PINCTRL_GRP_PMU0_2,
+ PINCTRL_GRP_PMU0_3,
+ PINCTRL_GRP_PMU0_4,
+ PINCTRL_GRP_PMU0_5,
+ PINCTRL_GRP_PMU0_6,
+ PINCTRL_GRP_PMU0_7,
+ PINCTRL_GRP_PMU0_8,
+ PINCTRL_GRP_PMU0_9,
+ PINCTRL_GRP_PMU0_10,
+ PINCTRL_GRP_PMU0_11,
+ PINCTRL_GRP_PCIE0_0,
+ PINCTRL_GRP_PCIE0_1,
+ PINCTRL_GRP_PCIE0_2,
+ PINCTRL_GRP_PCIE0_3,
+ PINCTRL_GRP_PCIE0_4,
+ PINCTRL_GRP_PCIE0_5,
+ PINCTRL_GRP_PCIE0_6,
+ PINCTRL_GRP_PCIE0_7,
+ PINCTRL_GRP_CSU0_0,
+ PINCTRL_GRP_CSU0_1,
+ PINCTRL_GRP_CSU0_2,
+ PINCTRL_GRP_CSU0_3,
+ PINCTRL_GRP_CSU0_4,
+ PINCTRL_GRP_CSU0_5,
+ PINCTRL_GRP_CSU0_6,
+ PINCTRL_GRP_CSU0_7,
+ PINCTRL_GRP_CSU0_8,
+ PINCTRL_GRP_CSU0_9,
+ PINCTRL_GRP_CSU0_10,
+ PINCTRL_GRP_CSU0_11,
+ PINCTRL_GRP_DPAUX0_0,
+ PINCTRL_GRP_DPAUX0_1,
+ PINCTRL_GRP_DPAUX0_2,
+ PINCTRL_GRP_DPAUX0_3,
+ PINCTRL_GRP_PJTAG0_0,
+ PINCTRL_GRP_PJTAG0_1,
+ PINCTRL_GRP_PJTAG0_2,
+ PINCTRL_GRP_PJTAG0_3,
+ PINCTRL_GRP_PJTAG0_4,
+ PINCTRL_GRP_PJTAG0_5,
+ PINCTRL_GRP_TRACE0_0,
+ PINCTRL_GRP_TRACE0_0_CLK,
+ PINCTRL_GRP_TRACE0_1,
+ PINCTRL_GRP_TRACE0_1_CLK,
+ PINCTRL_GRP_TRACE0_2,
+ PINCTRL_GRP_TRACE0_2_CLK,
+ PINCTRL_GRP_TESTSCAN0_0,
+};
+
+// pinctrl config parameters
+enum {
+ PINCTRL_CONFIG_SLEW_RATE,
+ PINCTRL_CONFIG_BIAS_STATUS,
+ PINCTRL_CONFIG_PULL_CTRL,
+ PINCTRL_CONFIG_SCHMITT_CMOS,
+ PINCTRL_CONFIG_DRIVE_STRENGTH,
+ PINCTRL_CONFIG_VOLTAGE_STATUS,
+ PINCTRL_CONFIG_MAX,
+};
+
+// pinctrl slew rate
+#define PINCTRL_SLEW_RATE_FAST 0U
+#define PINCTRL_SLEW_RATE_SLOW 1U
+
+// pinctrl bias status
+#define PINCTRL_BIAS_DISABLE 0U
+#define PINCTRL_BIAS_ENABLE 1U
+
+// pinctrl pull control
+#define PINCTRL_BIAS_PULL_DOWN 0U
+#define PINCTRL_BIAS_PULL_UP 1U
+
+// pinctrl schmitt cmos type
+#define PINCTRL_INPUT_TYPE_CMOS 0U
+#define PINCTRL_INPUT_TYPE_SCHMITT 1U
+
+//pinctrl drive strength values
+#define PINCTRL_DRIVE_STRENGTH_2MA 0U
+#define PINCTRL_DRIVE_STRENGTH_4MA 1U
+#define PINCTRL_DRIVE_STRENGTH_8MA 2U
+#define PINCTRL_DRIVE_STRENGTH_12MA 3U
+
+enum pm_ret_status pm_api_pinctrl_set_function(unsigned int pin,
+ unsigned int fid);
+enum pm_ret_status pm_api_pinctrl_get_function(unsigned int pin,
+ unsigned int *id);
+enum pm_ret_status pm_api_pinctrl_set_config(unsigned int pin,
+ unsigned int param,
+ unsigned int value);
+enum pm_ret_status pm_api_pinctrl_get_config(unsigned int pin,
+ unsigned int param,
+ unsigned int *value);
+enum pm_ret_status pm_api_pinctrl_get_function_name(unsigned int fid,
+ char *name);
+enum pm_ret_status pm_api_pinctrl_get_function_groups(unsigned int fid,
+ unsigned int index,
+ uint16_t *groups);
+enum pm_ret_status pm_api_pinctrl_get_pin_groups(unsigned int pin,
+ unsigned int index,
+ uint16_t *groups);
+enum pm_ret_status pm_api_pinctrl_get_num_pins(unsigned int *npins);
+enum pm_ret_status pm_api_pinctrl_get_num_functions(unsigned int *nfuncs);
+enum pm_ret_status pm_api_pinctrl_get_num_func_groups(unsigned int fid,
+ unsigned int *ngroups);
+#endif /* _PM_API_PINCTRL_H_ */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
index 9e21067..d75f7c0 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,6 +11,9 @@
#include <arch_helpers.h>
#include <platform.h>
+#include "pm_api_clock.h"
+#include "pm_api_ioctl.h"
+#include "pm_api_pinctrl.h"
#include "pm_api_sys.h"
#include "pm_client.h"
#include "pm_common.h"
@@ -545,3 +548,529 @@
pm_ipi_buff_read_callb(data, count);
pm_ipi_irq_clear(primary_proc);
}
+
+/**
+ * pm_pinctrl_request() - Request Pin from firmware
+ * @pin Pin number to request
+ *
+ * This function requests pin from firmware.
+ *
+ * @return Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_pinctrl_request(unsigned int pin)
+{
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_pinctrl_release() - Release Pin from firmware
+ * @pin Pin number to release
+ *
+ * This function releases pin from firmware.
+ *
+ * @return Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_pinctrl_release(unsigned int pin)
+{
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_pinctrl_get_function() - Read function id set for the given pin
+ * @pin Pin number
+ * @nid Node ID of function currently set for given pin
+ *
+ * This function provides the function currently set for the given pin.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_pinctrl_get_function(unsigned int pin,
+ enum pm_node_id *nid)
+{
+ return pm_api_pinctrl_get_function(pin, nid);
+}
+
+/**
+ * pm_pinctrl_set_function() - Set function id set for the given pin
+ * @pin Pin number
+ * @nid Node ID of function to set for given pin
+ *
+ * This function provides the function currently set for the given pin.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_pinctrl_set_function(unsigned int pin,
+ enum pm_node_id nid)
+{
+ return pm_api_pinctrl_set_function(pin, (unsigned int)nid);
+}
+
+/**
+ * pm_pinctrl_get_config() - Read value of requested config param for given pin
+ * @pin Pin number
+ * @param Parameter values to be read
+ * @value Buffer for configuration Parameter value
+ *
+ * This function provides the configuration parameter value for the given pin.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_pinctrl_get_config(unsigned int pin,
+ unsigned int param,
+ unsigned int *value)
+{
+ return pm_api_pinctrl_get_config(pin, param, value);
+}
+
+/**
+ * pm_pinctrl_set_config() - Read value of requested config param for given pin
+ * @pin Pin number
+ * @param Parameter to set
+ * @value Parameter value to set
+ *
+ * This function provides the configuration parameter value for the given pin.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_pinctrl_set_config(unsigned int pin,
+ unsigned int param,
+ unsigned int value)
+{
+ return pm_api_pinctrl_set_config(pin, param, value);
+}
+
+/**
+ * pm_ioctl() - PM IOCTL API for device control and configs
+ * @node_id Node ID of the device
+ * @ioctl_id ID of the requested IOCTL
+ * @arg1 Argument 1 to requested IOCTL call
+ * @arg2 Argument 2 to requested IOCTL call
+ * @out Returned output value
+ *
+ * This function calls IOCTL to firmware for device control and configuration.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_ioctl(enum pm_node_id nid,
+ unsigned int ioctl_id,
+ unsigned int arg1,
+ unsigned int arg2,
+ unsigned int *value)
+{
+ return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value);
+}
+
+/**
+ * pm_clock_get_name() - PM call to request a clock's name
+ * @clock_id Clock ID
+ * @name Name of clock (max 16 bytes)
+ *
+ * This function is used by master to get nmae of clock specified
+ * by given clock ID.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_clock_get_name(unsigned int clock_id, char *name)
+{
+ return pm_api_clock_get_name(clock_id, name);
+}
+
+/**
+ * pm_clock_get_topology() - PM call to request a clock's topology
+ * @clock_id Clock ID
+ * @index Topology index for next toplogy node
+ * @topology Buffer to store nodes in topology and flags
+ *
+ * This function is used by master to get topology information for the
+ * clock specified by given clock ID. Each response would return 3
+ * topology nodes. To get next nodes, caller needs to call this API with
+ * index of next node. Index starts from 0.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_clock_get_topology(unsigned int clock_id,
+ unsigned int index,
+ uint32_t *topology)
+{
+ return pm_api_clock_get_topology(clock_id, index, topology);
+}
+
+/**
+ * pm_clock_get_fixedfactor_params() - PM call to request a clock's fixed factor
+ * parameters for fixed clock
+ * @clock_id Clock ID
+ * @mul Multiplication value
+ * @div Divisor value
+ *
+ * This function is used by master to get fixed factor parameers for the
+ * fixed clock. This API is application only for the fixed clock.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_clock_get_fixedfactor_params(unsigned int clock_id,
+ uint32_t *mul,
+ uint32_t *div)
+{
+ return pm_api_clock_get_fixedfactor_params(clock_id, mul, div);
+}
+
+/**
+ * pm_clock_get_parents() - PM call to request a clock's first 3 parents
+ * @clock_id Clock ID
+ * @index Index of next parent
+ * @parents Parents of the given clock
+ *
+ * This function is used by master to get clock's parents information.
+ * This API will return 3 parents with a single response. To get other
+ * parents, master should call same API in loop with new parent index
+ * till error is returned.
+ *
+ * E.g First call should have index 0 which will return parents 0, 1 and
+ * 2. Next call, index should be 3 which will return parent 3,4 and 5 and
+ * so on.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_clock_get_parents(unsigned int clock_id,
+ unsigned int index,
+ uint32_t *parents)
+{
+ return pm_api_clock_get_parents(clock_id, index, parents);
+}
+
+/**
+ * pm_clock_get_attributes() - PM call to request a clock's attributes
+ * @clock_id Clock ID
+ * @attr Clock attributes
+ *
+ * This function is used by master to get clock's attributes
+ * (e.g. valid, clock type, etc).
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_clock_get_attributes(unsigned int clock_id,
+ uint32_t *attr)
+{
+ return pm_api_clock_get_attributes(clock_id, attr);
+}
+
+/**
+ * pm_clock_enable() - Enable the clock for given id
+ * @clock_id: Id of the clock to be enabled
+ *
+ * This function is used by master to enable the clock
+ * including peripherals and PLL clocks.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+
+enum pm_ret_status pm_clock_enable(unsigned int clock_id)
+{
+ return pm_api_clock_enable(clock_id);
+}
+
+/**
+ * pm_clock_disable - Disable the clock for given id
+ * @clock_id: Id of the clock to be disable
+ *
+ * This function is used by master to disable the clock
+ * including peripherals and PLL clocks.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+
+enum pm_ret_status pm_clock_disable(unsigned int clock_id)
+{
+ return pm_api_clock_disable(clock_id);
+}
+
+/**
+ * pm_clock_getstate - Get the clock state for given id
+ * @clock_id: Id of the clock to be queried
+ * @state: 1/0 (Enabled/Disabled)
+ *
+ * This function is used by master to get the state of clock
+ * including peripherals and PLL clocks.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_getstate(unsigned int clock_id,
+ unsigned int *state)
+{
+ return pm_api_clock_getstate(clock_id, state);
+}
+
+/**
+ * pm_clock_setdivider - Set the clock divider for given id
+ * @clock_id: Id of the clock
+ * @divider: divider value
+ *
+ * This function is used by master to set divider for any clock
+ * to achieve desired rate.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_setdivider(unsigned int clock_id,
+ unsigned int divider)
+{
+ return pm_api_clock_setdivider(clock_id, divider);
+}
+
+/**
+ * pm_clock_getdivider - Get the clock divider for given id
+ * @clock_id: Id of the clock
+ * @divider: divider value
+ *
+ * This function is used by master to get divider values
+ * for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_getdivider(unsigned int clock_id,
+ unsigned int *divider)
+{
+ return pm_api_clock_getdivider(clock_id, divider);
+}
+
+/**
+ * pm_clock_setrate - Set the clock rate for given id
+ * @clock_id: Id of the clock
+ * @rate: rate value in hz
+ *
+ * This function is used by master to set rate for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_setrate(unsigned int clock_id,
+ uint64_t rate)
+{
+ return pm_api_clock_setrate(clock_id, rate);
+}
+
+/**
+ * pm_clock_getrate - Get the clock rate for given id
+ * @clock_id: Id of the clock
+ * @rate: rate value in hz
+ *
+ * This function is used by master to get rate
+ * for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_getrate(unsigned int clock_id,
+ uint64_t *rate)
+{
+ return pm_api_clock_getrate(clock_id, rate);
+}
+
+/**
+ * pm_clock_setparent - Set the clock parent for given id
+ * @clock_id: Id of the clock
+ * @parent_id: parent id
+ *
+ * This function is used by master to set parent for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_setparent(unsigned int clock_id,
+ unsigned int parent_id)
+{
+ return pm_api_clock_setparent(clock_id, parent_id);
+}
+
+/**
+ * pm_clock_getparent - Get the clock parent for given id
+ * @clock_id: Id of the clock
+ * @parent_id: parent id
+ *
+ * This function is used by master to get parent index
+ * for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_getparent(unsigned int clock_id,
+ unsigned int *parent_id)
+{
+ return pm_api_clock_getparent(clock_id, parent_id);
+}
+
+/**
+ * pm_pinctrl_get_num_pins - PM call to request number of pins
+ * @npins: Number of pins
+ *
+ * This function is used by master to get number of pins
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_pinctrl_get_num_pins(uint32_t *npins)
+{
+ return pm_api_pinctrl_get_num_pins(npins);
+}
+
+/**
+ * pm_pinctrl_get_num_functions - PM call to request number of functions
+ * @nfuncs: Number of functions
+ *
+ * This function is used by master to get number of functions
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_pinctrl_get_num_functions(uint32_t *nfuncs)
+{
+ return pm_api_pinctrl_get_num_functions(nfuncs);
+}
+
+/**
+ * pm_pinctrl_get_num_function_groups - PM call to request number of
+ * function groups
+ * @fid: Id of function
+ * @ngroups: Number of function groups
+ *
+ * This function is used by master to get number of function groups specified
+ * by given function Id
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_pinctrl_get_num_function_groups(unsigned int fid,
+ uint32_t *ngroups)
+{
+ return pm_api_pinctrl_get_num_func_groups(fid, ngroups);
+}
+
+/**
+ * pm_pinctrl_get_function_name - PM call to request function name
+ * @fid: Id of function
+ * @name: Name of function
+ *
+ * This function is used by master to get name of function specified
+ * by given function Id
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_pinctrl_get_function_name(unsigned int fid,
+ char *name)
+{
+ return pm_api_pinctrl_get_function_name(fid, name);
+}
+
+/**
+ * pm_pinctrl_get_function_groups - PM call to request function groups
+ * @fid: Id of function
+ * @index: Index of next function groups
+ * @groups: Function groups
+ *
+ * This function is used by master to get function groups specified
+ * by given function Id. This API will return 6 function groups with
+ * a single response. To get other function groups, master should call
+ * same API in loop with new function groups index till error is returned.
+ *
+ * E.g First call should have index 0 which will return function groups
+ * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
+ * function groups 6, 7, 8, 9, 10 and 11 and so on.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_pinctrl_get_function_groups(unsigned int fid,
+ unsigned int index,
+ uint16_t *groups)
+{
+ return pm_api_pinctrl_get_function_groups(fid, index, groups);
+}
+
+/**
+ * pm_pinctrl_get_pin_groups - PM call to request pin groups
+ * @pin_id: Id of pin
+ * @index: Index of next pin groups
+ * @groups: pin groups
+ *
+ * This function is used by master to get pin groups specified
+ * by given pin Id. This API will return 6 pin groups with
+ * a single response. To get other pin groups, master should call
+ * same API in loop with new pin groups index till error is returned.
+ *
+ * E.g First call should have index 0 which will return pin groups
+ * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
+ * pin groups 6, 7, 8, 9, 10 and 11 and so on.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_pinctrl_get_pin_groups(unsigned int pin_id,
+ unsigned int index,
+ uint16_t *groups)
+{
+ return pm_api_pinctrl_get_pin_groups(pin_id, index, groups);
+}
+
+/**
+ * pm_query_data() - PM API for querying firmware data
+ * @arg1 Argument 1 to requested IOCTL call
+ * @arg2 Argument 2 to requested IOCTL call
+ * @arg3 Argument 3 to requested IOCTL call
+ * @arg4 Argument 4 to requested IOCTL call
+ * @data Returned output data
+ *
+ * This function returns requested data.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_query_data(enum pm_query_id qid,
+ unsigned int arg1,
+ unsigned int arg2,
+ unsigned int arg3,
+ unsigned int *data)
+{
+ enum pm_ret_status ret;
+
+ switch (qid) {
+ case PM_QID_CLOCK_GET_NAME:
+ ret = pm_clock_get_name(arg1, (char *)data);
+ break;
+ case PM_QID_CLOCK_GET_TOPOLOGY:
+ ret = pm_clock_get_topology(arg1, arg2, &data[1]);
+ data[0] = (unsigned int)ret;
+ break;
+ case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS:
+ ret = pm_clock_get_fixedfactor_params(arg1, &data[1], &data[2]);
+ data[0] = (unsigned int)ret;
+ break;
+ case PM_QID_CLOCK_GET_PARENTS:
+ ret = pm_clock_get_parents(arg1, arg2, &data[1]);
+ data[0] = (unsigned int)ret;
+ break;
+ case PM_QID_CLOCK_GET_ATTRIBUTES:
+ ret = pm_clock_get_attributes(arg1, &data[1]);
+ data[0] = (unsigned int)ret;
+ break;
+ case PM_QID_PINCTRL_GET_NUM_PINS:
+ ret = pm_pinctrl_get_num_pins(&data[1]);
+ data[0] = (unsigned int)ret;
+ break;
+ case PM_QID_PINCTRL_GET_NUM_FUNCTIONS:
+ ret = pm_pinctrl_get_num_functions(&data[1]);
+ data[0] = (unsigned int)ret;
+ break;
+ case PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS:
+ ret = pm_pinctrl_get_num_function_groups(arg1, &data[1]);
+ data[0] = (unsigned int)ret;
+ break;
+ case PM_QID_PINCTRL_GET_FUNCTION_NAME:
+ ret = pm_pinctrl_get_function_name(arg1, (char *)data);
+ break;
+ case PM_QID_PINCTRL_GET_FUNCTION_GROUPS:
+ ret = pm_pinctrl_get_function_groups(arg1, arg2,
+ (uint16_t *)&data[1]);
+ data[0] = (unsigned int)ret;
+ break;
+ case PM_QID_PINCTRL_GET_PIN_GROUPS:
+ ret = pm_pinctrl_get_pin_groups(arg1, arg2,
+ (uint16_t *)&data[1]);
+ data[0] = (unsigned int)ret;
+ break;
+ default:
+ ret = PM_RET_ERROR_ARGS;
+ WARN("Unimplemented query service call: 0x%x\n", qid);
+ break;
+ }
+
+ return ret;
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
index af7b252..c6de560 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -10,6 +10,21 @@
#include <stdint.h>
#include "pm_defs.h"
+enum pm_query_id {
+ PM_QID_INVALID,
+ PM_QID_CLOCK_GET_NAME,
+ PM_QID_CLOCK_GET_TOPOLOGY,
+ PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS,
+ PM_QID_CLOCK_GET_PARENTS,
+ PM_QID_CLOCK_GET_ATTRIBUTES,
+ PM_QID_PINCTRL_GET_NUM_PINS,
+ PM_QID_PINCTRL_GET_NUM_FUNCTIONS,
+ PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS,
+ PM_QID_PINCTRL_GET_FUNCTION_NAME,
+ PM_QID_PINCTRL_GET_FUNCTION_GROUPS,
+ PM_QID_PINCTRL_GET_PIN_GROUPS,
+};
+
/**********************************************************
* System-level API function declarations
**********************************************************/
@@ -93,5 +108,42 @@
enum pm_ret_status pm_get_chipid(uint32_t *value);
void pm_get_callbackdata(uint32_t *data, size_t count);
-
+enum pm_ret_status pm_pinctrl_request(unsigned int pin);
+enum pm_ret_status pm_pinctrl_release(unsigned int pin);
+enum pm_ret_status pm_pinctrl_get_function(unsigned int pin,
+ enum pm_node_id *nid);
+enum pm_ret_status pm_pinctrl_set_function(unsigned int pin,
+ enum pm_node_id nid);
+enum pm_ret_status pm_pinctrl_get_config(unsigned int pin,
+ unsigned int param,
+ unsigned int *value);
+enum pm_ret_status pm_pinctrl_set_config(unsigned int pin,
+ unsigned int param,
+ unsigned int value);
+enum pm_ret_status pm_ioctl(enum pm_node_id nid,
+ unsigned int ioctl_id,
+ unsigned int arg1,
+ unsigned int arg2,
+ unsigned int *value);
+enum pm_ret_status pm_clock_enable(unsigned int clock_id);
+enum pm_ret_status pm_clock_disable(unsigned int clock_id);
+enum pm_ret_status pm_clock_getstate(unsigned int clock_id,
+ unsigned int *state);
+enum pm_ret_status pm_clock_setdivider(unsigned int clock_id,
+ unsigned int divider);
+enum pm_ret_status pm_clock_getdivider(unsigned int clock_id,
+ unsigned int *divider);
+enum pm_ret_status pm_clock_setrate(unsigned int clock_id,
+ uint64_t rate);
+enum pm_ret_status pm_clock_getrate(unsigned int clock_id,
+ uint64_t *rate);
+enum pm_ret_status pm_clock_setparent(unsigned int clock_id,
+ unsigned int parent_id);
+enum pm_ret_status pm_clock_getparent(unsigned int clock_id,
+ unsigned int *parent_id);
+enum pm_ret_status pm_query_data(enum pm_query_id qid,
+ unsigned int arg1,
+ unsigned int arg2,
+ unsigned int arg3,
+ unsigned int *data);
#endif /* _PM_API_SYS_H_ */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_common.h b/plat/xilinx/zynqmp/pm_service/pm_common.h
index 5dcbb0d..4d03bc0 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_common.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_common.h
@@ -19,6 +19,11 @@
#define PAYLOAD_ARG_CNT 6U
#define PAYLOAD_ARG_SIZE 4U /* size in bytes */
+#define ZYNQMP_TZ_VERSION_MAJOR 1
+#define ZYNQMP_TZ_VERSION_MINOR 0
+#define ZYNQMP_TZ_VERSION ((ZYNQMP_TZ_VERSION_MAJOR << 16) | \
+ ZYNQMP_TZ_VERSION_MINOR)
+
/**
* pm_ipi - struct for capturing IPI-channel specific info
* @apu_ipi_id APU IPI agent ID
diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h
index ba0c52a..0c46e73 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_defs.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -17,8 +17,8 @@
* 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_MAJOR 1
+#define PM_VERSION_MINOR 0
#define PM_VERSION ((PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR)
@@ -66,6 +66,28 @@
PM_FPGA_LOAD,
PM_FPGA_GET_STATUS,
PM_GET_CHIPID,
+ PM_SECURE_RSA_AES,
+ PM_SECURE_SHA,
+ PM_SECURE_RSA,
+ PM_PINCTRL_REQUEST,
+ PM_PINCTRL_RELEASE,
+ PM_PINCTRL_GET_FUNCTION,
+ PM_PINCTRL_SET_FUNCTION,
+ PM_PINCTRL_CONFIG_PARAM_GET,
+ PM_PINCTRL_CONFIG_PARAM_SET,
+ PM_IOCTL,
+ /* API to query information from firmware */
+ PM_QUERY_DATA,
+ /* Clock control API functions */
+ PM_CLOCK_ENABLE,
+ PM_CLOCK_DISABLE,
+ PM_CLOCK_GETSTATE,
+ PM_CLOCK_SETDIVIDER,
+ PM_CLOCK_GETDIVIDER,
+ PM_CLOCK_SETRATE,
+ PM_CLOCK_GETRATE,
+ PM_CLOCK_SETPARENT,
+ PM_CLOCK_GETPARENT,
PM_API_MAX
};
@@ -79,7 +101,7 @@
NODE_RPU,
NODE_RPU_0,
NODE_RPU_1,
- NODE_PL,
+ NODE_PLD,
NODE_FPD,
NODE_OCM_BANK_0,
NODE_OCM_BANK_1,
@@ -132,7 +154,23 @@
NODE_PCIE,
NODE_PCAP,
NODE_RTC,
- NODE_MAX
+ NODE_LPD,
+ NODE_VCU,
+ NODE_IPI_RPU_1,
+ NODE_IPI_PL_0,
+ NODE_IPI_PL_1,
+ NODE_IPI_PL_2,
+ NODE_IPI_PL_3,
+ NODE_PL,
+ NODE_GEM_TSU,
+ NODE_SWDT_0,
+ NODE_SWDT_1,
+ NODE_CSU,
+ NODE_PJTAG,
+ NODE_TRACE,
+ NODE_TESTSCAN,
+ NODE_PMU,
+ NODE_MAX,
};
enum pm_request_ack {
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
index fb64bc5..34b3ad4 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -19,6 +19,7 @@
#include "pm_ipi.h"
#define PM_GET_CALLBACK_DATA 0xa01
+#define PM_GET_TRUSTZONE_VERSION 0xa03
/* 0 - UP, !0 - DOWN */
static int32_t pm_down = !0;
@@ -248,6 +249,118 @@
(uint64_t)result[2] | ((uint64_t)result[3] << 32));
}
+ case PM_PINCTRL_REQUEST:
+ ret = pm_pinctrl_request(pm_arg[0]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_PINCTRL_RELEASE:
+ ret = pm_pinctrl_release(pm_arg[0]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_PINCTRL_GET_FUNCTION:
+ {
+ uint32_t value = 0;
+
+ ret = pm_pinctrl_get_function(pm_arg[0], &value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ case PM_PINCTRL_SET_FUNCTION:
+ ret = pm_pinctrl_set_function(pm_arg[0], pm_arg[1]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_PINCTRL_CONFIG_PARAM_GET:
+ {
+ uint32_t value;
+
+ ret = pm_pinctrl_get_config(pm_arg[0], pm_arg[1], &value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ case PM_PINCTRL_CONFIG_PARAM_SET:
+ ret = pm_pinctrl_set_config(pm_arg[0], pm_arg[1], pm_arg[2]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_IOCTL:
+ {
+ uint32_t value;
+
+ ret = pm_ioctl(pm_arg[0], pm_arg[1], pm_arg[2],
+ pm_arg[3], &value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ case PM_QUERY_DATA:
+ {
+ uint32_t data[4] = { 0 };
+
+ ret = pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2],
+ pm_arg[3], data);
+ SMC_RET2(handle, (uint64_t)data[0] | ((uint64_t)data[1] << 32),
+ (uint64_t)data[2] | ((uint64_t)data[3] << 32));
+ }
+
+ case PM_CLOCK_ENABLE:
+ ret = pm_clock_enable(pm_arg[0]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_CLOCK_DISABLE:
+ ret = pm_clock_disable(pm_arg[0]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_CLOCK_GETSTATE:
+ {
+ uint32_t value;
+
+ ret = pm_clock_getstate(pm_arg[0], &value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ case PM_CLOCK_SETDIVIDER:
+ ret = pm_clock_setdivider(pm_arg[0], pm_arg[1]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_CLOCK_GETDIVIDER:
+ {
+ uint32_t value;
+
+ ret = pm_clock_getdivider(pm_arg[0], &value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ case PM_CLOCK_SETRATE:
+ ret = pm_clock_setrate(pm_arg[0],
+ ((uint64_t)pm_arg[2]) << 32 | pm_arg[1]);
+
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_CLOCK_GETRATE:
+ {
+ uint64_t value;
+
+ ret = pm_clock_getrate(pm_arg[0], &value);
+ SMC_RET2(handle, (uint64_t)ret |
+ (((uint64_t)value & 0xFFFFFFFFU) << 32U),
+ (value >> 32U) & 0xFFFFFFFFU);
+
+ }
+
+ case PM_CLOCK_SETPARENT:
+ ret = pm_clock_setparent(pm_arg[0], pm_arg[1]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_CLOCK_GETPARENT:
+ {
+ uint32_t value;
+
+ ret = pm_clock_getparent(pm_arg[0], &value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ case PM_GET_TRUSTZONE_VERSION:
+ SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS |
+ ((uint64_t)ZYNQMP_TZ_VERSION << 32));
+
default:
WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid);
SMC_RET1(handle, SMC_UNK);
diff --git a/plat/xilinx/zynqmp/sip_svc_setup.c b/plat/xilinx/zynqmp/sip_svc_setup.c
index 8b44eaa..c7996ce 100644
--- a/plat/xilinx/zynqmp/sip_svc_setup.c
+++ b/plat/xilinx/zynqmp/sip_svc_setup.c
@@ -52,14 +52,14 @@
* 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)
+uintptr_t sip_svc_smc_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
{
/* Let PM SMC handler deal with PM-related requests */
if (is_pm_fid(smc_fid)) {
diff --git a/plat/xilinx/zynqmp/zynqmp_def.h b/plat/xilinx/zynqmp/zynqmp_def.h
index e90ad02..60df187 100644
--- a/plat/xilinx/zynqmp/zynqmp_def.h
+++ b/plat/xilinx/zynqmp/zynqmp_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -27,33 +27,36 @@
* ZYNQMP memory map related constants
******************************************************************************/
/* Aggregate of all devices in the first GB */
-#define DEVICE0_BASE 0xFF000000
-#define DEVICE0_SIZE 0x00E00000
-#define DEVICE1_BASE 0xF9000000
-#define DEVICE1_SIZE 0x00800000
+#define DEVICE0_BASE U(0xFF000000)
+#define DEVICE0_SIZE U(0x00E00000)
+#define DEVICE1_BASE U(0xF9000000)
+#define DEVICE1_SIZE U(0x00800000)
/* For cpu reset APU space here too 0xFE5F1000 CRF_APB*/
-#define CRF_APB_BASE 0xFD1A0000
-#define CRF_APB_SIZE 0x00600000
+#define CRF_APB_BASE U(0xFD1A0000)
+#define CRF_APB_SIZE U(0x00600000)
+#define CRF_APB_CLK_BASE U(0xFD1A0020)
/* 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)
+#define CRF_APB_RST_FPD_APU_ACPU_RESET (U(1) << 0)
+#define CRF_APB_RST_FPD_APU_ACPU_PWRON_RESET (U(1) << 10)
/* CRL registers and bitfields */
-#define CRL_APB_BASE 0xFF5E0000
-#define CRL_APB_RPLL_CTRL (CRL_APB_BASE + 0x30)
+#define CRL_APB_BASE U(0xFF5E0000)
#define CRL_APB_BOOT_MODE_USER (CRL_APB_BASE + 0x200)
#define CRL_APB_RESET_CTRL (CRL_APB_BASE + 0x218)
+#define CRL_APB_RST_LPD_TOP (CRL_APB_BASE + 0x23C)
+#define CRL_APB_CLK_BASE U(0xFF5E0020)
-#define CRL_APB_RPLL_CTRL_BYPASS (1 << 3)
+#define CRL_APB_RPU_AMBA_RESET (U(1) << 2)
+#define CRL_APB_RPLL_CTRL_BYPASS (U(1) << 3)
-#define CRL_APB_RESET_CTRL_SOFT_RESET (1 << 4)
+#define CRL_APB_RESET_CTRL_SOFT_RESET (U(1) << 4)
-#define CRL_APB_BOOT_MODE_MASK (0xf << 0)
-#define ZYNQMP_BOOTMODE_JTAG 0
+#define CRL_APB_BOOT_MODE_MASK (U(0xf) << 0)
+#define ZYNQMP_BOOTMODE_JTAG U(0)
/* system counter registers and bitfields */
#define IOU_SCNTRS_BASE 0xFF260000
@@ -174,4 +177,138 @@
#define ACTLR_EL3_L2ACTLR_BIT (1 << 6)
#define ACTLR_EL3_CPUACTLR_BIT (1 << 0)
+#define IOU_SLCR_BASEADDR U(0xFF180000)
+
+#define ZYNQMP_RPU_GLBL_CNTL U(0xFF9A0000)
+#define ZYNQMP_RPU0_CFG U(0xFF9A0100)
+#define ZYNQMP_RPU1_CFG U(0xFF9A0200)
+#define ZYNQMP_SLSPLIT_MASK U(0x08)
+#define ZYNQMP_TCM_COMB_MASK U(0x40)
+#define ZYNQMP_SLCLAMP_MASK U(0x10)
+#define ZYNQMP_VINITHI_MASK U(0x04)
+
+/* Tap delay bypass */
+#define IOU_TAPDLY_BYPASS U(0XFF180390)
+#define TAP_DELAY_MASK U(0x7)
+
+/* SGMII mode */
+#define IOU_GEM_CTRL U(0xFF180360)
+#define IOU_GEM_CLK_CTRL U(0xFF180308)
+#define SGMII_SD_MASK U(0x3)
+#define SGMII_SD_OFFSET U(2)
+#define SGMII_PCS_SD_0 U(0x0)
+#define SGMII_PCS_SD_1 U(0x1)
+#define SGMII_PCS_SD_PHY U(0x2)
+#define GEM_SGMII_MASK U(0x4)
+#define GEM_CLK_CTRL_MASK U(0xF)
+#define GEM_CLK_CTRL_OFFSET U(5)
+#define GEM_RX_SRC_SEL_GTR U(0x1)
+#define GEM_SGMII_MODE U(0x4)
+
+/* SD DLL reset */
+#define ZYNQMP_SD_DLL_CTRL U(0xFF180358)
+#define ZYNQMP_SD0_DLL_RST_MASK U(0x00000004)
+#define ZYNQMP_SD0_DLL_RST U(0x00000004)
+#define ZYNQMP_SD1_DLL_RST_MASK U(0x00040000)
+#define ZYNQMP_SD1_DLL_RST U(0x00040000)
+
+/* SD tap delay */
+#define ZYNQMP_SD_DLL_CTRL U(0xFF180358)
+#define ZYNQMP_SD_ITAP_DLY U(0xFF180314)
+#define ZYNQMP_SD_OTAP_DLY U(0xFF180318)
+#define ZYNQMP_SD_TAP_OFFSET U(16)
+#define ZYNQMP_SD_ITAPCHGWIN_MASK U(0x200)
+#define ZYNQMP_SD_ITAPCHGWIN U(0x200)
+#define ZYNQMP_SD_ITAPDLYENA_MASK U(0x100)
+#define ZYNQMP_SD_ITAPDLYENA U(0x100)
+#define ZYNQMP_SD_ITAPDLYSEL_MASK U(0xFF)
+#define ZYNQMP_SD_OTAPDLYSEL_MASK U(0x3F)
+#define ZYNQMP_SD_OTAPDLYENA_MASK U(0x40)
+#define ZYNQMP_SD_OTAPDLYENA U(0x40)
+
+/* Clock control registers */
+/* Full power domain clocks */
+#define CRF_APB_APLL_CTRL (CRF_APB_CLK_BASE + 0x00)
+#define CRF_APB_DPLL_CTRL (CRF_APB_CLK_BASE + 0x0c)
+#define CRF_APB_VPLL_CTRL (CRF_APB_CLK_BASE + 0x18)
+#define CRF_APB_PLL_STATUS (CRF_APB_CLK_BASE + 0x24)
+#define CRF_APB_APLL_TO_LPD_CTRL (CRF_APB_CLK_BASE + 0x28)
+#define CRF_APB_DPLL_TO_LPD_CTRL (CRF_APB_CLK_BASE + 0x2c)
+#define CRF_APB_VPLL_TO_LPD_CTRL (CRF_APB_CLK_BASE + 0x30)
+/* Peripheral clocks */
+#define CRF_APB_ACPU_CTRL (CRF_APB_CLK_BASE + 0x40)
+#define CRF_APB_DBG_TRACE_CTRL (CRF_APB_CLK_BASE + 0x44)
+#define CRF_APB_DBG_FPD_CTRL (CRF_APB_CLK_BASE + 0x48)
+#define CRF_APB_DP_VIDEO_REF_CTRL (CRF_APB_CLK_BASE + 0x50)
+#define CRF_APB_DP_AUDIO_REF_CTRL (CRF_APB_CLK_BASE + 0x54)
+#define CRF_APB_DP_STC_REF_CTRL (CRF_APB_CLK_BASE + 0x5c)
+#define CRF_APB_DDR_CTRL (CRF_APB_CLK_BASE + 0x60)
+#define CRF_APB_GPU_REF_CTRL (CRF_APB_CLK_BASE + 0x64)
+#define CRF_APB_SATA_REF_CTRL (CRF_APB_CLK_BASE + 0x80)
+#define CRF_APB_PCIE_REF_CTRL (CRF_APB_CLK_BASE + 0x94)
+#define CRF_APB_GDMA_REF_CTRL (CRF_APB_CLK_BASE + 0x98)
+#define CRF_APB_DPDMA_REF_CTRL (CRF_APB_CLK_BASE + 0x9c)
+#define CRF_APB_TOPSW_MAIN_CTRL (CRF_APB_CLK_BASE + 0xa0)
+#define CRF_APB_TOPSW_LSBUS_CTRL (CRF_APB_CLK_BASE + 0xa4)
+#define CRF_APB_GTGREF0_REF_CTRL (CRF_APB_CLK_BASE + 0xa8)
+#define CRF_APB_DBG_TSTMP_CTRL (CRF_APB_CLK_BASE + 0xd8)
+
+/* Low power domain clocks */
+#define CRL_APB_IOPLL_CTRL (CRL_APB_CLK_BASE + 0x00)
+#define CRL_APB_RPLL_CTRL (CRL_APB_CLK_BASE + 0x10)
+#define CRL_APB_PLL_STATUS (CRL_APB_CLK_BASE + 0x20)
+#define CRL_APB_IOPLL_TO_FPD_CTRL (CRL_APB_CLK_BASE + 0x24)
+#define CRL_APB_RPLL_TO_FPD_CTRL (CRL_APB_CLK_BASE + 0x28)
+/* Peripheral clocks */
+#define CRL_APB_USB3_DUAL_REF_CTRL (CRL_APB_CLK_BASE + 0x2c)
+#define CRL_APB_GEM0_REF_CTRL (CRL_APB_CLK_BASE + 0x30)
+#define CRL_APB_GEM1_REF_CTRL (CRL_APB_CLK_BASE + 0x34)
+#define CRL_APB_GEM2_REF_CTRL (CRL_APB_CLK_BASE + 0x38)
+#define CRL_APB_GEM3_REF_CTRL (CRL_APB_CLK_BASE + 0x3c)
+#define CRL_APB_USB0_BUS_REF_CTRL (CRL_APB_CLK_BASE + 0x40)
+#define CRL_APB_USB1_BUS_REF_CTRL (CRL_APB_CLK_BASE + 0x44)
+#define CRL_APB_QSPI_REF_CTRL (CRL_APB_CLK_BASE + 0x48)
+#define CRL_APB_SDIO0_REF_CTRL (CRL_APB_CLK_BASE + 0x4c)
+#define CRL_APB_SDIO1_REF_CTRL (CRL_APB_CLK_BASE + 0x50)
+#define CRL_APB_UART0_REF_CTRL (CRL_APB_CLK_BASE + 0x54)
+#define CRL_APB_UART1_REF_CTRL (CRL_APB_CLK_BASE + 0x58)
+#define CRL_APB_SPI0_REF_CTRL (CRL_APB_CLK_BASE + 0x5c)
+#define CRL_APB_SPI1_REF_CTRL (CRL_APB_CLK_BASE + 0x60)
+#define CRL_APB_CAN0_REF_CTRL (CRL_APB_CLK_BASE + 0x64)
+#define CRL_APB_CAN1_REF_CTRL (CRL_APB_CLK_BASE + 0x68)
+#define CRL_APB_CPU_R5_CTRL (CRL_APB_CLK_BASE + 0x70)
+#define CRL_APB_IOU_SWITCH_CTRL (CRL_APB_CLK_BASE + 0x7c)
+#define CRL_APB_CSU_PLL_CTRL (CRL_APB_CLK_BASE + 0x80)
+#define CRL_APB_PCAP_CTRL (CRL_APB_CLK_BASE + 0x84)
+#define CRL_APB_LPD_SWITCH_CTRL (CRL_APB_CLK_BASE + 0x88)
+#define CRL_APB_LPD_LSBUS_CTRL (CRL_APB_CLK_BASE + 0x8c)
+#define CRL_APB_DBG_LPD_CTRL (CRL_APB_CLK_BASE + 0x90)
+#define CRL_APB_NAND_REF_CTRL (CRL_APB_CLK_BASE + 0x94)
+#define CRL_APB_ADMA_REF_CTRL (CRL_APB_CLK_BASE + 0x98)
+#define CRL_APB_PL0_REF_CTRL (CRL_APB_CLK_BASE + 0xa0)
+#define CRL_APB_PL1_REF_CTRL (CRL_APB_CLK_BASE + 0xa4)
+#define CRL_APB_PL2_REF_CTRL (CRL_APB_CLK_BASE + 0xa8)
+#define CRL_APB_PL3_REF_CTRL (CRL_APB_CLK_BASE + 0xac)
+#define CRL_APB_PL0_THR_CNT (CRL_APB_CLK_BASE + 0xb4)
+#define CRL_APB_PL1_THR_CNT (CRL_APB_CLK_BASE + 0xbc)
+#define CRL_APB_PL2_THR_CNT (CRL_APB_CLK_BASE + 0xc4)
+#define CRL_APB_PL3_THR_CNT (CRL_APB_CLK_BASE + 0xdc)
+#define CRL_APB_GEM_TSU_REF_CTRL (CRL_APB_CLK_BASE + 0xe0)
+#define CRL_APB_DLL_REF_CTRL (CRL_APB_CLK_BASE + 0xe4)
+#define CRL_APB_AMS_REF_CTRL (CRL_APB_CLK_BASE + 0xe8)
+#define CRL_APB_I2C0_REF_CTRL (CRL_APB_CLK_BASE + 0x100)
+#define CRL_APB_I2C1_REF_CTRL (CRL_APB_CLK_BASE + 0x104)
+#define CRL_APB_TIMESTAMP_REF_CTRL (CRL_APB_CLK_BASE + 0x108)
+#define IOU_SLCR_GEM_CLK_CTRL (IOU_SLCR_BASEADDR + 0x308)
+#define IOU_SLCR_CAN_MIO_CTRL (IOU_SLCR_BASEADDR + 0x304)
+#define IOU_SLCR_WDT_CLK_SEL (IOU_SLCR_BASEADDR + 0x300)
+
+/* Global general storage register base address */
+#define GGS_BASEADDR (0xFFD80030U)
+#define GGS_NUM_REGS U(4)
+
+/* Persistent global general storage register base address */
+#define PGGS_BASEADDR (0xFFD80050U)
+#define PGGS_NUM_REGS U(4)
+
#endif /* __ZYNQMP_DEF_H__ */
diff --git a/services/arm_arch_svc/arm_arch_svc_setup.c b/services/arm_arch_svc/arm_arch_svc_setup.c
index 83d3625..eb736c0 100644
--- a/services/arm_arch_svc/arm_arch_svc_setup.c
+++ b/services/arm_arch_svc/arm_arch_svc_setup.c
@@ -19,19 +19,16 @@
static int32_t smccc_arch_features(u_register_t arg)
{
- int ret;
-
switch (arg) {
case SMCCC_VERSION:
case SMCCC_ARCH_FEATURES:
return SMC_OK;
+#if WORKAROUND_CVE_2017_5715
case SMCCC_ARCH_WORKAROUND_1:
- ret = check_workaround_cve_2017_5715();
- if (ret == ERRATA_APPLIES)
- return 0;
- else if (ret == ERRATA_NOT_APPLIES)
+ if (check_workaround_cve_2017_5715() == ERRATA_NOT_APPLIES)
return 1;
- return -1; /* ERRATA_MISSING */
+ return 0; /* ERRATA_APPLIES || ERRATA_MISSING */
+#endif
default:
return SMC_UNK;
}
diff --git a/services/spd/opteed/opteed_main.c b/services/spd/opteed/opteed_main.c
index 3d67980..ac58e04 100644
--- a/services/spd/opteed/opteed_main.c
+++ b/services/spd/opteed/opteed_main.c
@@ -90,7 +90,7 @@
* (aarch32/aarch64) if not already known and initialises the context for entry
* into OPTEE for its initialization.
******************************************************************************/
-int32_t opteed_setup(void)
+static int32_t opteed_setup(void)
{
entry_point_info_t *optee_ep_info;
uint32_t linear_id;
@@ -187,14 +187,14 @@
* state. Lastly it will also return any information that OPTEE needs to do
* the work assigned to it.
******************************************************************************/
-uint64_t opteed_smc_handler(uint32_t smc_fid,
- uint64_t x1,
- uint64_t x2,
- uint64_t x3,
- uint64_t x4,
+static uintptr_t opteed_smc_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
void *cookie,
void *handle,
- uint64_t flags)
+ u_register_t flags)
{
cpu_context_t *ns_cpu_context;
uint32_t linear_id = plat_my_core_pos();
diff --git a/services/spd/opteed/opteed_pm.c b/services/spd/opteed/opteed_pm.c
index 2420b1e..7efc234 100644
--- a/services/spd/opteed/opteed_pm.c
+++ b/services/spd/opteed/opteed_pm.c
@@ -16,7 +16,7 @@
* The target cpu is being turned on. Allow the OPTEED/OPTEE to perform any
* actions needed. Nothing at the moment.
******************************************************************************/
-static void opteed_cpu_on_handler(uint64_t target_cpu)
+static void opteed_cpu_on_handler(u_register_t target_cpu)
{
}
@@ -24,7 +24,7 @@
* This cpu is being turned off. Allow the OPTEED/OPTEE to perform any actions
* needed
******************************************************************************/
-static int32_t opteed_cpu_off_handler(uint64_t unused)
+static int32_t opteed_cpu_off_handler(u_register_t unused)
{
int32_t rc = 0;
uint32_t linear_id = plat_my_core_pos();
@@ -57,7 +57,7 @@
* This cpu is being suspended. S-EL1 state must have been saved in the
* resident cpu (mpidr format) if it is a UP/UP migratable OPTEE.
******************************************************************************/
-static void opteed_cpu_suspend_handler(uint64_t max_off_pwrlvl)
+static void opteed_cpu_suspend_handler(u_register_t max_off_pwrlvl)
{
int32_t rc = 0;
uint32_t linear_id = plat_my_core_pos();
@@ -87,7 +87,7 @@
* after initialising minimal architectural state that guarantees safe
* execution.
******************************************************************************/
-static void opteed_cpu_on_finish_handler(uint64_t unused)
+static void opteed_cpu_on_finish_handler(u_register_t unused)
{
int32_t rc = 0;
uint32_t linear_id = plat_my_core_pos();
@@ -123,7 +123,7 @@
* completed the preceding suspend call. Use that context to program an entry
* into OPTEE to allow it to do any remaining book keeping
******************************************************************************/
-static void opteed_cpu_suspend_finish_handler(uint64_t max_off_pwrlvl)
+static void opteed_cpu_suspend_finish_handler(u_register_t max_off_pwrlvl)
{
int32_t rc = 0;
uint32_t linear_id = plat_my_core_pos();
@@ -154,7 +154,7 @@
* Return the type of OPTEE the OPTEED is dealing with. Report the current
* resident cpu (mpidr format) if it is a UP/UP migratable OPTEE.
******************************************************************************/
-static int32_t opteed_cpu_migrate_info(uint64_t *resident_cpu)
+static int32_t opteed_cpu_migrate_info(u_register_t *resident_cpu)
{
return OPTEE_MIGRATE_INFO;
}
diff --git a/services/spd/tlkd/tlkd_main.c b/services/spd/tlkd/tlkd_main.c
index da3b732..5090f06 100644
--- a/services/spd/tlkd/tlkd_main.c
+++ b/services/spd/tlkd/tlkd_main.c
@@ -44,14 +44,14 @@
0xbd11e9c9, 0x2bba, 0x52ee, 0xb1, 0x72,
0x46, 0x1f, 0xba, 0x97, 0x7f, 0x63);
-int32_t tlkd_init(void);
+static int32_t tlkd_init(void);
/*******************************************************************************
* Secure Payload Dispatcher setup. The SPD finds out the SP entrypoint and type
* (aarch32/aarch64) if not already known and initialises the context for entry
* into the SP for its initialisation.
******************************************************************************/
-int32_t tlkd_setup(void)
+static int32_t tlkd_setup(void)
{
entry_point_info_t *tlk_ep_info;
@@ -100,7 +100,7 @@
* used. This function performs a synchronous entry into the Secure payload.
* The SP passes control back to this routine through a SMC.
******************************************************************************/
-int32_t tlkd_init(void)
+static int32_t tlkd_init(void)
{
entry_point_info_t *tlk_entry_point;
@@ -133,14 +133,14 @@
* will also return any information that the secure payload needs to do the
* work assigned to it.
******************************************************************************/
-uint64_t tlkd_smc_handler(uint32_t smc_fid,
- uint64_t x1,
- uint64_t x2,
- uint64_t x3,
- uint64_t x4,
+static uintptr_t tlkd_smc_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
void *cookie,
void *handle,
- uint64_t flags)
+ u_register_t flags)
{
cpu_context_t *ns_cpu_context;
gp_regs_t *gp_regs;
diff --git a/services/spd/tlkd/tlkd_pm.c b/services/spd/tlkd/tlkd_pm.c
index 8b4c457..2cd2fbb 100644
--- a/services/spd/tlkd/tlkd_pm.c
+++ b/services/spd/tlkd/tlkd_pm.c
@@ -22,7 +22,7 @@
* Return the type of payload TLKD is dealing with. Report the current
* resident cpu (mpidr format) if it is a UP/UP migratable payload.
******************************************************************************/
-static int32_t cpu_migrate_info(uint64_t *resident_cpu)
+static int32_t cpu_migrate_info(u_register_t *resident_cpu)
{
/* the payload runs only on CPU0 */
*resident_cpu = MPIDR_CPU0;
@@ -35,7 +35,7 @@
* This cpu is being suspended. Inform TLK of the SYSTEM_SUSPEND event, so
* that it can pass this information to its Trusted Apps.
******************************************************************************/
-static void cpu_suspend_handler(uint64_t suspend_level)
+static void cpu_suspend_handler(u_register_t suspend_level)
{
gp_regs_t *gp_regs;
int cpu = read_mpidr() & MPIDR_CPU_MASK;
@@ -67,7 +67,7 @@
* This cpu is being resumed. Inform TLK of the SYSTEM_SUSPEND exit, so
* that it can pass this information to its Trusted Apps.
******************************************************************************/
-static void cpu_resume_handler(uint64_t suspend_level)
+static void cpu_resume_handler(u_register_t suspend_level)
{
gp_regs_t *gp_regs;
int cpu = read_mpidr() & MPIDR_CPU_MASK;
diff --git a/services/spd/trusty/trusty.c b/services/spd/trusty/trusty.c
index 97f202c..cc808e2 100644
--- a/services/spd/trusty/trusty.c
+++ b/services/spd/trusty/trusty.c
@@ -53,7 +53,7 @@
uint64_t r7;
};
-struct trusty_cpu_ctx trusty_cpu_ctx[PLATFORM_CORE_COUNT];
+static struct trusty_cpu_ctx trusty_cpu_ctx[PLATFORM_CORE_COUNT];
struct args trusty_init_context_stack(void **sp, void *new_stack);
struct args trusty_context_switch_helper(void **sp, void *smc_params);
@@ -159,7 +159,7 @@
struct trusty_cpu_ctx *ctx;
if (cpu >= PLATFORM_CORE_COUNT) {
- ERROR("%s: cpu %ld >= %d\n", __func__, cpu, PLATFORM_CORE_COUNT);
+ ERROR("%s: cpu %lld >= %d\n", __func__, cpu, PLATFORM_CORE_COUNT);
return SM_ERR_INVALID_PARAMETERS;
}
@@ -191,7 +191,7 @@
ret = trusty_context_switch(NON_SECURE, SMC_FC_FIQ_EXIT, 0, 0, 0);
if (ret.r0 != 1) {
- INFO("%s(%p) SMC_FC_FIQ_EXIT returned unexpected value, %ld\n",
+ INFO("%s(%p) SMC_FC_FIQ_EXIT returned unexpected value, %lld\n",
__func__, handle, ret.r0);
}
@@ -212,14 +212,14 @@
SMC_RET0(handle);
}
-static uint64_t trusty_smc_handler(uint32_t smc_fid,
- uint64_t x1,
- uint64_t x2,
- uint64_t x3,
- uint64_t x4,
+static uintptr_t trusty_smc_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
void *cookie,
void *handle,
- uint64_t flags)
+ u_register_t flags)
{
struct args ret;
uint32_t vmid = 0;
@@ -331,7 +331,7 @@
ret = trusty_context_switch(NON_SECURE, SMC_FC_CPU_SUSPEND, off, 0, 0);
if (ret.r0 != 0) {
- INFO("%s: cpu %d, SMC_FC_CPU_SUSPEND returned unexpected value, %ld\n",
+ INFO("%s: cpu %d, SMC_FC_CPU_SUSPEND returned unexpected value, %lld\n",
__func__, plat_my_core_pos(), ret.r0);
}
}
@@ -342,19 +342,19 @@
ret = trusty_context_switch(NON_SECURE, SMC_FC_CPU_RESUME, on, 0, 0);
if (ret.r0 != 0) {
- INFO("%s: cpu %d, SMC_FC_CPU_RESUME returned unexpected value, %ld\n",
+ INFO("%s: cpu %d, SMC_FC_CPU_RESUME returned unexpected value, %lld\n",
__func__, plat_my_core_pos(), ret.r0);
}
}
-static int32_t trusty_cpu_off_handler(uint64_t unused)
+static int32_t trusty_cpu_off_handler(u_register_t unused)
{
trusty_cpu_suspend(1);
return 0;
}
-static void trusty_cpu_on_finish_handler(uint64_t unused)
+static void trusty_cpu_on_finish_handler(u_register_t unused)
{
struct trusty_cpu_ctx *ctx = get_trusty_ctx();
@@ -365,12 +365,12 @@
}
}
-static void trusty_cpu_suspend_handler(uint64_t unused)
+static void trusty_cpu_suspend_handler(u_register_t unused)
{
trusty_cpu_suspend(0);
}
-static void trusty_cpu_suspend_finish_handler(uint64_t unused)
+static void trusty_cpu_suspend_finish_handler(u_register_t unused)
{
trusty_cpu_resume(0);
}
diff --git a/services/spd/tspd/tspd_main.c b/services/spd/tspd/tspd_main.c
index 2312205..8cb23b9 100644
--- a/services/spd/tspd/tspd_main.c
+++ b/services/spd/tspd/tspd_main.c
@@ -179,7 +179,7 @@
* (aarch32/aarch64) if not already known and initialises the context for entry
* into the SP for its initialisation.
******************************************************************************/
-int32_t tspd_setup(void)
+static int32_t tspd_setup(void)
{
entry_point_info_t *tsp_ep_info;
uint32_t linear_id;
@@ -273,14 +273,14 @@
* will also return any information that the secure payload needs to do the
* work assigned to it.
******************************************************************************/
-uint64_t tspd_smc_handler(uint32_t smc_fid,
- uint64_t x1,
- uint64_t x2,
- uint64_t x3,
- uint64_t x4,
+static uintptr_t tspd_smc_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
void *cookie,
void *handle,
- uint64_t flags)
+ u_register_t flags)
{
cpu_context_t *ns_cpu_context;
uint32_t linear_id = plat_my_core_pos(), ns;
diff --git a/services/spd/tspd/tspd_pm.c b/services/spd/tspd/tspd_pm.c
index 5fdd3dc..9414c15 100644
--- a/services/spd/tspd/tspd_pm.c
+++ b/services/spd/tspd/tspd_pm.c
@@ -17,7 +17,7 @@
* The target cpu is being turned on. Allow the TSPD/TSP to perform any actions
* needed. Nothing at the moment.
******************************************************************************/
-static void tspd_cpu_on_handler(uint64_t target_cpu)
+static void tspd_cpu_on_handler(u_register_t target_cpu)
{
}
@@ -25,7 +25,7 @@
* This cpu is being turned off. Allow the TSPD/TSP to perform any actions
* needed
******************************************************************************/
-static int32_t tspd_cpu_off_handler(uint64_t unused)
+static int32_t tspd_cpu_off_handler(u_register_t unused)
{
int32_t rc = 0;
uint32_t linear_id = plat_my_core_pos();
@@ -64,7 +64,7 @@
* This cpu is being suspended. S-EL1 state must have been saved in the
* resident cpu (mpidr format) if it is a UP/UP migratable TSP.
******************************************************************************/
-static void tspd_cpu_suspend_handler(uint64_t max_off_pwrlvl)
+static void tspd_cpu_suspend_handler(u_register_t max_off_pwrlvl)
{
int32_t rc = 0;
uint32_t linear_id = plat_my_core_pos();
@@ -100,7 +100,7 @@
* after initialising minimal architectural state that guarantees safe
* execution.
******************************************************************************/
-static void tspd_cpu_on_finish_handler(uint64_t unused)
+static void tspd_cpu_on_finish_handler(u_register_t unused)
{
int32_t rc = 0;
uint32_t linear_id = plat_my_core_pos();
@@ -145,7 +145,7 @@
* completed the preceding suspend call. Use that context to program an entry
* into the TSP to allow it to do any remaining book keeping
******************************************************************************/
-static void tspd_cpu_suspend_finish_handler(uint64_t max_off_pwrlvl)
+static void tspd_cpu_suspend_finish_handler(u_register_t max_off_pwrlvl)
{
int32_t rc = 0;
uint32_t linear_id = plat_my_core_pos();
@@ -176,7 +176,7 @@
* Return the type of TSP the TSPD is dealing with. Report the current resident
* cpu (mpidr format) if it is a UP/UP migratable TSP.
******************************************************************************/
-static int32_t tspd_cpu_migrate_info(uint64_t *resident_cpu)
+static int32_t tspd_cpu_migrate_info(u_register_t *resident_cpu)
{
return TSP_MIGRATE_INFO;
}
diff --git a/services/spd/tspd/tspd_private.h b/services/spd/tspd/tspd_private.h
index 8fadb7a..692a967 100644
--- a/services/spd/tspd/tspd_private.h
+++ b/services/spd/tspd/tspd_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -206,7 +206,7 @@
/*******************************************************************************
* Forward declarations
******************************************************************************/
-struct tsp_vectors;
+typedef struct tsp_vectors tsp_vectors_t;
/*******************************************************************************
* Function & Data prototypes
@@ -215,14 +215,16 @@
void __dead2 tspd_exit_sp(uint64_t c_rt_ctx, uint64_t ret);
uint64_t tspd_synchronous_sp_entry(tsp_context_t *tsp_ctx);
void __dead2 tspd_synchronous_sp_exit(tsp_context_t *tsp_ctx, uint64_t ret);
-void tspd_init_tsp_ep_state(struct entry_point_info *tsp_ep,
+void tspd_init_tsp_ep_state(struct entry_point_info *tsp_entry_point,
uint32_t rw,
uint64_t pc,
tsp_context_t *tsp_ctx);
int tspd_abort_preempted_smc(tsp_context_t *tsp_ctx);
+uint64_t tspd_handle_sp_preemption(void *handle);
+
extern tsp_context_t tspd_sp_context[TSPD_CORE_COUNT];
-extern struct tsp_vectors *tsp_vectors;
+extern tsp_vectors_t *tsp_vectors;
#endif /*__ASSEMBLY__*/
#endif /* __TSPD_PRIVATE_H__ */
diff --git a/services/std_svc/spm/secure_partition_setup.c b/services/std_svc/spm/secure_partition_setup.c
index 6998dae..9b3f622 100644
--- a/services/std_svc/spm/secure_partition_setup.c
+++ b/services/std_svc/spm/secure_partition_setup.c
@@ -236,12 +236,14 @@
SPM_SHIM_EXCEPTIONS_PTR);
/*
- * FPEN: Forbid the Secure Partition to access FP/SIMD registers.
+ * FPEN: Allow the Secure Partition to access FP/SIMD registers.
+ * Note that SPM will not do any saving/restoring of these registers on
+ * behalf of the SP. This falls under the SP's responsibility.
* TTA: Enable access to trace registers.
* ZEN (v8.2): Trap SVE instructions and access to SVE registers.
*/
write_ctx_reg(get_sysregs_ctx(ctx), CTX_CPACR_EL1,
- CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_ALL));
+ CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE));
/*
* Prepare information in buffer shared between EL3 and S-EL0
diff --git a/services/std_svc/spm/spm_main.c b/services/std_svc/spm/spm_main.c
index 6c4e1f0..e0fe494 100644
--- a/services/std_svc/spm/spm_main.c
+++ b/services/std_svc/spm/spm_main.c
@@ -35,7 +35,7 @@
* Replace the S-EL1 re-entry information with S-EL0 re-entry
* information
******************************************************************************/
-void spm_setup_next_eret_into_sel0(cpu_context_t *secure_context)
+static void spm_setup_next_eret_into_sel0(const cpu_context_t *secure_context)
{
assert(secure_context == cm_get_context(SECURE));
@@ -83,14 +83,14 @@
* as the generic smc entry routine should have saved those.
******************************************************************************/
static void __dead2 spm_synchronous_sp_exit(
- secure_partition_context_t *sp_ctx_ptr, uint64_t ret)
+ const secure_partition_context_t *sp_ctx_ptr, uint64_t ret)
{
assert(sp_ctx_ptr != NULL);
/* Save the Secure EL1 system register context */
assert(cm_get_context(SECURE) == &sp_ctx_ptr->cpu_ctx);
cm_el1_sysregs_context_save(SECURE);
- assert(sp_ctx_ptr->c_rt_ctx != 0);
+ assert(sp_ctx_ptr->c_rt_ctx != 0U);
spm_secure_partition_exit(sp_ctx_ptr->c_rt_ctx, ret);
/* Should never reach here */
@@ -104,7 +104,7 @@
* used. This function performs a synchronous entry into the Secure partition.
* The SP passes control back to this routine through a SMC.
******************************************************************************/
-int32_t spm_init(void)
+static int32_t spm_init(void)
{
entry_point_info_t *secure_partition_ep_info;
uint64_t rc;
@@ -116,7 +116,7 @@
* absence is a critical failure.
*/
secure_partition_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
- assert(secure_partition_ep_info);
+ assert(secure_partition_ep_info != NULL);
/*
* Initialise the common context and then overlay the S-EL0 specific
@@ -155,15 +155,15 @@
{
uint32_t ep_attr;
- assert(sp_ep_info);
- assert(pc);
- assert(sp_ctx_ptr);
+ assert(sp_ep_info != NULL);
+ assert(pc != 0U);
+ assert(sp_ctx_ptr != NULL);
cm_set_context(&sp_ctx_ptr->cpu_ctx, SECURE);
/* initialise an entrypoint to set up the CPU context */
ep_attr = SECURE | EP_ST_ENABLE;
- if (read_sctlr_el3() & SCTLR_EE_BIT)
+ if ((read_sctlr_el3() & SCTLR_EE_BIT) != 0U)
ep_attr |= EP_EE_BIG;
SET_PARAM_HEAD(sp_ep_info, PARAM_EP, VERSION_1, ep_attr);
@@ -192,7 +192,7 @@
* absence is a critical failure.
*/
secure_partition_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
- if (!secure_partition_ep_info) {
+ if (secure_partition_ep_info == NULL) {
WARN("No SPM provided by BL2 boot loader, Booting device"
" without SPM initialization. SMCs destined for SPM"
" will return SMC_UNK\n");
@@ -204,7 +204,7 @@
* signalling failure initializing the service. We bail out without
* registering any handlers
*/
- if (!secure_partition_ep_info->pc) {
+ if (secure_partition_ep_info->pc == 0U) {
return 1;
}
@@ -231,9 +231,9 @@
* The other fields are left as 0 because they are ignored by the function
* change_mem_attributes().
*/
-static mmap_attr_t smc_attr_to_mmap_attr(unsigned int attributes)
+static unsigned int smc_attr_to_mmap_attr(unsigned int attributes)
{
- mmap_attr_t tf_attr = 0;
+ unsigned int tf_attr = 0U;
unsigned int access = (attributes & SP_MEMORY_ATTRIBUTES_ACCESS_MASK)
>> SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT;
@@ -262,11 +262,11 @@
* This function converts attributes from the Trusted Firmware format into the
* SMC interface format.
*/
-static int smc_mmap_to_smc_attr(mmap_attr_t attr)
+static unsigned int smc_mmap_to_smc_attr(unsigned int attr)
{
- int smc_attr = 0;
+ unsigned int smc_attr = 0U;
- int data_access;
+ unsigned int data_access;
if ((attr & MT_USER) == 0) {
/* No access from EL0. */
@@ -283,28 +283,29 @@
smc_attr |= (data_access & SP_MEMORY_ATTRIBUTES_ACCESS_MASK)
<< SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT;
- if (attr & MT_EXECUTE_NEVER) {
+ if ((attr & MT_EXECUTE_NEVER) != 0U) {
smc_attr |= SP_MEMORY_ATTRIBUTES_NON_EXEC;
}
return smc_attr;
}
-static int spm_memory_attributes_get_smc_handler(uintptr_t base_va)
+static int32_t spm_memory_attributes_get_smc_handler(uintptr_t base_va)
{
+ uint32_t attributes;
+
spin_lock(&mem_attr_smc_lock);
- mmap_attr_t attributes;
int rc = get_mem_attributes(secure_partition_xlat_ctx_handle,
base_va, &attributes);
spin_unlock(&mem_attr_smc_lock);
/* Convert error codes of get_mem_attributes() into SPM ones. */
- assert(rc == 0 || rc == -EINVAL);
+ assert((rc == 0) || (rc == -EINVAL));
if (rc == 0) {
- return smc_mmap_to_smc_attr(attributes);
+ return (int32_t) smc_mmap_to_smc_attr(attributes);
} else {
return SPM_INVALID_PARAMETER;
}
@@ -316,7 +317,7 @@
{
uintptr_t base_va = (uintptr_t) page_address;
size_t size = (size_t) (pages_count * PAGE_SIZE);
- unsigned int attributes = (unsigned int) smc_attributes;
+ uint32_t attributes = (uint32_t) smc_attributes;
INFO(" Start address : 0x%lx\n", base_va);
INFO(" Number of pages: %i (%zi bytes)\n", (int) pages_count, size);
@@ -330,7 +331,7 @@
spin_unlock(&mem_attr_smc_lock);
/* Convert error codes of change_mem_attributes() into SPM ones. */
- assert(ret == 0 || ret == -EINVAL);
+ assert((ret == 0) || (ret == -EINVAL));
return (ret == 0) ? SPM_SUCCESS : SPM_INVALID_PARAMETER;
}
@@ -389,7 +390,7 @@
/* Get a reference to the non-secure context */
ns_cpu_context = cm_get_context(NON_SECURE);
- assert(ns_cpu_context);
+ assert(ns_cpu_context != NULL);
/* Restore non-secure state */
cm_el1_sysregs_context_restore(NON_SECURE);
@@ -435,17 +436,17 @@
uint64_t comm_size_address = x3;
/* Cookie. Reserved for future use. It must be zero. */
- if (mm_cookie != 0) {
+ if (mm_cookie != 0U) {
ERROR("MM_COMMUNICATE: cookie is not zero\n");
SMC_RET1(handle, SPM_INVALID_PARAMETER);
}
- if (comm_buffer_address == 0) {
+ if (comm_buffer_address == 0U) {
ERROR("MM_COMMUNICATE: comm_buffer_address is zero\n");
SMC_RET1(handle, SPM_INVALID_PARAMETER);
}
- if (comm_size_address != 0) {
+ if (comm_size_address != 0U) {
VERBOSE("MM_COMMUNICATE: comm_size_address is not 0 as recommended.\n");
}
diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile
index b0994b8..8a1958f 100644
--- a/tools/cert_create/Makefile
+++ b/tools/cert_create/Makefile
@@ -86,5 +86,5 @@
$(call SHELL_DELETE_ALL, src/build_msg.o ${OBJECTS})
realclean: clean
- $(call SHELL_DELETE, ${BINARY})
+ $(call SHELL_DELETE,${BINARY})
diff --git a/tools/fiptool/fiptool.c b/tools/fiptool/fiptool.c
index e70ff36..e4348ee 100644
--- a/tools/fiptool/fiptool.c
+++ b/tools/fiptool/fiptool.c
@@ -169,7 +169,10 @@
free(desc->name);
free(desc->cmdline_name);
free(desc->action_arg);
- free(desc->image);
+ if (desc->image) {
+ free(desc->image->buffer);
+ free(desc->image);
+ }
free(desc);
}