Merge "feat(plat/st): improve FIP image loading from MMC" into integration
diff --git a/Makefile b/Makefile
index b4bebf1..8411355 100644
--- a/Makefile
+++ b/Makefile
@@ -525,6 +525,10 @@
ifeq ($(TS_SP_FW_CONFIG),1)
DTC_CPPFLAGS += -DTS_SP_FW_CONFIG
endif
+
+ ifneq ($(ARM_BL2_SP_LIST_DTS),)
+ DTC_CPPFLAGS += -DARM_BL2_SP_LIST_DTS=$(ARM_BL2_SP_LIST_DTS)
+ endif
else
# All other SPDs in spd directory
SPD_DIR := spd
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 901a72a..bac8847 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -790,6 +790,11 @@
GIC-600, so is safe to select even for a GIC500 implementation.
This option defaults to 0.
+- ``GICV3_SUPPORT_GIC600AE_FMU``: Add support for the Fault Management Unit
+ for GIC-600 AE. Enabling this option will introduce support to initialize
+ the FMU. Platforms should call the init function during boot to enable the
+ FMU and its safety mechanisms. This option defaults to 0.
+
- ``GICV3_IMPL_GIC600_MULTICHIP``: Selects GIC-600 variant with multichip
functionality. This option defaults to 0
diff --git a/docs/plat/arm/arm-build-options.rst b/docs/plat/arm/arm-build-options.rst
index d4fa98d..74251bd 100644
--- a/docs/plat/arm/arm-build-options.rst
+++ b/docs/plat/arm/arm-build-options.rst
@@ -100,6 +100,9 @@
- ``ARM_SPMC_MANIFEST_DTS`` : path to an alternate manifest file used as the
SPMC Core manifest. Valid when ``SPD=spmd`` is selected.
+- ``ARM_BL2_SP_LIST_DTS``: Path to DTS file snippet to override the hardcoded
+ SP nodes in tb_fw_config.
+
- ``OPTEE_SP_FW_CONFIG``: DTC build flag to include OP-TEE as SP in tb_fw_config
device tree. This flag is defined only when ``ARM_SPMC_MANIFEST_DTS`` manifest
file name contains pattern optee_sp.
diff --git a/docs/plat/index.rst b/docs/plat/index.rst
index 4dc9ecd..5848005 100644
--- a/docs/plat/index.rst
+++ b/docs/plat/index.rst
@@ -27,6 +27,7 @@
imx8
imx8m
ls1043a
+ nxp/index
poplar
qemu
qemu-sbsa
diff --git a/docs/plat/marvell/armada/build.rst b/docs/plat/marvell/armada/build.rst
index 8af27b1..b125144 100644
--- a/docs/plat/marvell/armada/build.rst
+++ b/docs/plat/marvell/armada/build.rst
@@ -153,6 +153,29 @@
Armada37x0 specific build options:
+- HANDLE_EA_EL3_FIRST
+
+ When ``HANDLE_EA_EL3_FIRST=1``, External Aborts and SError Interrupts will be always trapped
+ in TF-A. TF-A in this case enables dirty hack / workaround for a bug found in U-Boot and
+ Linux kernel PCIe controller driver pci-aardvark.c, traps and then masks SError interrupt
+ caused by AXI SLVERR on external access (syndrome 0xbf000002).
+
+ Otherwise when ``HANDLE_EA_EL3_FIRST=0``, these exceptions will be trapped in the current
+ exception level (or in EL1 if the current exception level is EL0). So exceptions caused by
+ U-Boot will be trapped in U-Boot, exceptions caused by Linux kernel (or user applications)
+ will be trapped in Linux kernel.
+
+ Mentioned bug in pci-aardvark.c driver is fixed in U-Boot version v2021.07 and Linux kernel
+ version v5.13 (workarounded since Linux kernel version 5.9) and also backported in Linux
+ kernel stable releases since versions v5.12.13, v5.10.46, v5.4.128, v4.19.198, v4.14.240.
+
+ If target system has already patched version of U-Boot and Linux kernel then it is strongly
+ recommended to not enable this workaround as it disallows propagating of all External Aborts
+ to running Linux kernel and makes correctable errors as fatal aborts.
+
+ This option is now disabled by default. In past this option was enabled by default in
+ TF-A versions v2.2, v2.3, v2.4 and v2.5.
+
- CM3_SYSTEM_RESET
When ``CM3_SYSTEM_RESET=1``, the Cortex-M3 secure coprocessor will be used for system reset.
diff --git a/docs/plat/nxp/index.rst b/docs/plat/nxp/index.rst
new file mode 100644
index 0000000..8546887
--- /dev/null
+++ b/docs/plat/nxp/index.rst
@@ -0,0 +1,17 @@
+NXP Reference Development Platforms
+===================================
+
+.. toctree::
+ :maxdepth: 1
+ :caption: Contents
+
+ nxp-layerscape
+ nxp-ls-fuse-prov
+ nxp-ls-tbbr
+
+This chapter holds documentation related to NXP reference development platforms.
+It includes details on image flashing, fuse provisioning and trusted board boot-up.
+
+--------------
+
+*Copyright (c) 2021, NXP Limited. All rights reserved.*
diff --git a/docs/plat/nxp/nxp-layerscape.rst b/docs/plat/nxp/nxp-layerscape.rst
new file mode 100644
index 0000000..3d98354
--- /dev/null
+++ b/docs/plat/nxp/nxp-layerscape.rst
@@ -0,0 +1,232 @@
+NXP SoCs - Overview
+=====================
+.. section-numbering::
+ :suffix: .
+
+The QorIQ family of ARM based SoCs that are supported on TF-A are:
+
+1. LX2160ARDB:
+ Platform Name:
+
+ a. lx2160ardb (Board details can be fetched from the link: `lx2160ardb`_)
+
+
+Table of supported boot-modes by each platform & platform that needs FIP-DDR:
+-----------------------------------------------------------------------------
+
++---+-----------------+-------+--------+-------+-------+-------+-------------+--------------+-----------------+
+| | BOOT_MODE-->| sd | qspi | nor | nand | emmc | flexspi_nor | flexspi_nand | fip_ddr needed |
+| | | | | | | | | | |
+| | PLAT | | | | | | | | |
++===+=================+=======+========+=======+=======+=======+=============+==============+=================+
+| 1.| lx2160ardb | yes | | | | yes | yes | | yes |
++---+-----------------+-------+--------+-------+-------+-------+-------------+--------------+-----------------+
+
+Boot Sequence
+-------------
+::
+
++ Secure World | Normal World
++ EL0 |
++ |
++ EL1 BL32(Tee OS) | kernel
++ ^ | | ^
++ | | | |
++ EL2 | | | BL33(u-boot)
++ | | | ^
++ | v | /
++ EL3 BootROM --> BL2 --> BL31 ---------------/
++
+
+Boot Sequence with FIP-DDR
+--------------------------
+::
+
++ Secure World | Normal World
++ EL0 |
++ |
++ EL1 fip-ddr BL32(Tee OS) | kernel
++ ^ | ^ | | ^
++ | | | | | |
++ EL2 | | | | | BL33(u-boot)
++ | | | | | ^
++ | v | v | /
++ EL3 BootROM --> BL2 -----> BL31 ---------------/
++
+
+
+How to build
+=============
+
+Code Locations
+--------------
+
+- OP-TEE:
+ `link <https://source.codeaurora.org/external/qoriq/qoriq-components/optee_os>`__
+
+- U-Boot:
+ `link <https://source.codeaurora.org/external/qoriq/qoriq-components/u-boot>`__
+
+- RCW:
+ `link <https://source.codeaurora.org/external/qoriq/qoriq-components/rcw>`__
+
+- ddr-phy-binary: Required by platforms that need fip-ddr.
+ `link <https:://github.com/NXP/ddr-phy-binary>`__
+
+- cst: Required for TBBR.
+ `link <https:://source.codeaurora.org/external/qoriq/qoriq-components/cst>`__
+
+Build Procedure
+---------------
+
+- Fetch all the above repositories into local host.
+
+- Prepare AARCH64 toolchain and set the environment variable "CROSS_COMPILE".
+
+ .. code:: shell
+
+ export CROSS_COMPILE=.../bin/aarch64-linux-gnu-
+
+- Build RCW. Refer README from the respective cloned folder for more details.
+
+- Build u-boot and OPTee firstly, and get binary images: u-boot.bin and tee.bin.
+ For u-boot you can use the <platform>_tfa_defconfig for build.
+
+- Copy/clone the repo "ddr-phy-binary" to the tfa directory for platform needing ddr-fip.
+
+- Below are the steps to build TF-A images for the supported platforms.
+
+Compilation steps without BL32
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+BUILD BL2:
+
+-To compile
+ .. code:: shell
+
+ make PLAT=$PLAT \
+ BOOT_MODE=<platform_supported_boot_mode> \
+ RCW=$RCW_BIN \
+ pbl
+
+BUILD FIP:
+
+ .. code:: shell
+
+ make PLAT=$PLAT \
+ BOOT_MODE=<platform_supported_boot_mode> \
+ RCW=$RCW_BIN \
+ BL33=$UBOOT_SECURE_BIN \
+ pbl \
+ fip
+
+Compilation steps with BL32
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+BUILD BL2:
+
+-To compile
+ .. code:: shell
+
+ make PLAT=$PLAT \
+ BOOT_MODE=<platform_supported_boot_mode> \
+ RCW=$RCW_BIN \
+ BL32=$TEE_BIN SPD=opteed\
+ pbl
+
+BUILD FIP:
+
+ .. code:: shell
+
+ make PLAT=$PLAT \
+ BOOT_MODE=<platform_supported_boot_mode> \
+ RCW=$RCW_BIN \
+ BL32=$TEE_BIN SPD=opteed\
+ BL33=$UBOOT_SECURE_BIN \
+ pbl \
+ fip
+
+
+BUILD fip-ddr (Mandatory for certain platforms, refer table above):
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+-To compile additional fip-ddr for selected platforms(Refer above table if the platform needs fip-ddr).
+ .. code:: shell
+
+ make PLAT=<platform_name> fip-ddr
+
+
+Deploy ATF Images
+=================
+
+Note: The size in the standard uboot commands for copy to nor, qspi, nand or sd
+should be modified based on the binary size of the image to be copied.
+
+- Deploy ATF images on flexspi-Nor flash Alt Bank from U-Boot prompt.
+ -- Commands to flash images for bl2_xxx.pbl and fip.bin.
+
+ .. code:: shell
+
+ tftp 82000000 $path/bl2_flexspi_nor.pbl;
+ i2c mw 66 50 20;sf probe 0:0; sf erase 0 +$filesize; sf write 0x82000000 0x0 $filesize;
+
+ tftp 82000000 $path/fip.bin;
+ i2c mw 66 50 20;sf probe 0:0; sf erase 0x100000 +$filesize; sf write 0x82000000 0x100000 $filesize;
+
+ -- Next step is valid for platform where FIP-DDR is needed.
+
+ .. code:: shell
+
+ tftp 82000000 $path/ddr_fip.bin;
+ i2c mw 66 50 20;sf probe 0:0; sf erase 0x800000 +$filesize; sf write 0x82000000 0x800000 $filesize;
+
+ -- Then reset to alternate bank to boot up ATF.
+
+ .. code:: shell
+
+ qixisreset altbank;
+
+- Deploy ATF images on SD/eMMC from U-Boot prompt.
+ -- file_size_in_block_sizeof_512 = (Size_of_bytes_tftp / 512)
+
+ .. code:: shell
+
+ mmc dev <idx>; (idx = 1 for eMMC; idx = 0 for SD)
+
+ tftp 82000000 $path/bl2_<sd>_or_<emmc>.pbl;
+ mmc write 82000000 8 <file_size_in_block_sizeof_512>;
+
+ tftp 82000000 $path/fip.bin;
+ mmc write 82000000 0x800 <file_size_in_block_sizeof_512>;
+
+ -- Next step is valid for platform that needs FIP-DDR.
+
+ .. code:: shell
+
+ tftp 82000000 $path/ddr_fip.bin;
+ mmc write 82000000 0x4000 <file_size_in_block_sizeof_512>;
+
+ -- Then reset to sd/emmc to boot up ATF from sd/emmc as boot-source.
+
+ .. code:: shell
+
+ qixisreset <sd or emmc>;
+
+Trusted Board Boot:
+===================
+
+For TBBR, the binary name changes:
+
++-------------+--------------------------+---------+-------------------+
+| Boot Type | BL2 | FIP | FIP-DDR |
++=============+==========================+=========+===================+
+| Normal Boot | bl2_<boot_mode>.pbl | fip.bin | ddr_fip.bin |
++-------------+--------------------------+---------+-------------------+
+| TBBR Boot | bl2_<boot_mode>_sec.pbl | fip.bin | ddr_fip_sec.bin |
++-------------+--------------------------+---------+-------------------+
+
+Refer `nxp-ls-tbbr.rst`_ for detailed user steps.
+
+
+.. _lx2160ardb: https://www.nxp.com/products/processors-and-microcontrollers/arm-processors/layerscape-communication-process/layerscape-lx2160a-multicore-communications-processor:LX2160A
+.. _nxp-ls-tbbr.rst: ./nxp-ls-tbbr.rst
diff --git a/docs/plat/nxp/nxp-ls-fuse-prov.rst b/docs/plat/nxp/nxp-ls-fuse-prov.rst
new file mode 100644
index 0000000..64e1c6f
--- /dev/null
+++ b/docs/plat/nxp/nxp-ls-fuse-prov.rst
@@ -0,0 +1,271 @@
+
+Steps to blow fuses on NXP LS SoC:
+==================================
+
+
+- Enable POVDD
+ -- Refer board GSG(Getting Started Guide) for the steps to enable POVDD.
+ -- Once the POVDD is enabled, make sure to set variable POVDD_ENABLE := yes, in the platform.mk.
+
++---+-----------------+-----------+------------+-----------------+-----------------------------+
+| | Platform | Jumper | Switch | LED to Verify | Through GPIO Pin (=number) |
++===+=================+===========+============+=================+=============================+
+| 1.| lx2160ardb | J9 | | | no |
++---+-----------------+-----------+------------+-----------------+-----------------------------+
+| 2.| lx2160aqds | J35 | | | no |
++---+-----------------+-----------+------------+-----------------+-----------------------------+
+| 3.| lx2162aqds | J35 | SW9[4] = 1 | D15 | no |
++---+-----------------+-----------+------------+-----------------+-----------------------------+
+
+- SFP registers to be written to:
+
++---+----------------------------------+----------------------+----------------------+
+| | Platform | OTPMKR0..OTPMKR7 | SRKHR0..SRKHR7 |
++===+==================================+======================+======================+
+| 1.| lx2160ardb/lx2160aqds/lx2162aqds | 0x1e80234..0x1e80250 | 0x1e80254..0x1e80270 |
++---+----------------------------------+----------------------+----------------------+
+
+- At U-Boot prompt, verify that SNVS register - HPSR, whether OTPMK was written, already:
+
++---+----------------------------------+-------------------------------------------+---------------+
+| | Platform | OTPMK_ZERO_BIT(=value) | SNVS_HPSR_REG |
++===+==================================+===========================================+===============+
+| 1.| lx2160ardb/lx2160aqds/lx2162aqds | 27 (= 1 means not blown, =0 means blown) | 0x01E90014 |
++---+----------------------------------+-------------------------------------------+---------------+
+
+From u-boot prompt:
+
+ -- Check for the OTPMK.
+ .. code:: shell
+
+ md $SNVS_HPSR_REG
+
+ Command Output:
+ 01e90014: 88000900
+
+ In case it is read as 00000000, then read this register using jtag (in development mode only through CW tap).
+ +0 +4 +8 +C
+ [0x01E90014] 88000900
+
+ Note: OTPMK_ZERO_BIT is 1, indicating that the OTPMK is not blown.
+
+ -- Check for the SRK Hash.
+ .. code:: shell
+
+ md $SRKHR0 0x10
+
+ Command Output:
+ 01e80254: 00000000 00000000 00000000 00000000 ................
+ 01e80264: 00000000 00000000 00000000 00000000 ................
+
+ Note: Zero means that SRK hash is not blown.
+
+- If not blown, then from the U-Boot prompt, using following commands:
+ -- Provision the OTPMK.
+
+ .. code:: shell
+
+ mw.l $OTPMKR0 <OTMPKR_0_32Bit_val>
+ mw.l $OTPMKR1 <OTMPKR_1_32Bit_val>
+ mw.l $OTPMKR2 <OTMPKR_2_32Bit_val>
+ mw.l $OTPMKR3 <OTMPKR_3_32Bit_val>
+ mw.l $OTPMKR4 <OTMPKR_4_32Bit_val>
+ mw.l $OTPMKR5 <OTMPKR_5_32Bit_val>
+ mw.l $OTPMKR6 <OTMPKR_6_32Bit_val>
+ mw.l $OTPMKR7 <OTMPKR_7_32Bit_val>
+
+ -- Provision the SRK Hash.
+
+ .. code:: shell
+
+ mw.l $SRKHR0 <SRKHR_0_32Bit_val>
+ mw.l $SRKHR1 <SRKHR_1_32Bit_val>
+ mw.l $SRKHR2 <SRKHR_2_32Bit_val>
+ mw.l $SRKHR3 <SRKHR_3_32Bit_val>
+ mw.l $SRKHR4 <SRKHR_4_32Bit_val>
+ mw.l $SRKHR5 <SRKHR_5_32Bit_val>
+ mw.l $SRKHR6 <SRKHR_6_32Bit_val>
+ mw.l $SRKHR7 <SRKHR_7_32Bit_val>
+
+ Note: SRK Hash should be carefully written keeping in mind the SFP Block Endianness.
+
+- At U-Boot prompt, verify that SNVS registers for OTPMK are correctly written:
+
+ -- Check for the OTPMK.
+ .. code:: shell
+
+ md $SNVS_HPSR_REG
+
+ Command Output:
+ 01e90014: 80000900
+
+ OTPMK_ZERO_BIT is zero, indicating that the OTPMK is blown.
+
+ Note: In case it is read as 00000000, then read this register using jtag (in development mode only through CW tap).
+
+ .. code:: shell
+
+ md $OTPMKR0 0x10
+
+ Command Output:
+ 01e80234: ffffffff ffffffff ffffffff ffffffff ................
+ 01e80244: ffffffff ffffffff ffffffff ffffffff ................
+
+ Note: OTPMK will never be visible in plain.
+
+ -- Check for the SRK Hash. For example, if following SRK hash is written:
+
+ SFP SRKHR0 = fdc2fed4
+ SFP SRKHR1 = 317f569e
+ SFP SRKHR2 = 1828425c
+ SFP SRKHR3 = e87b5cfd
+ SFP SRKHR4 = 34beab8f
+ SFP SRKHR5 = df792a70
+ SFP SRKHR6 = 2dff85e1
+ SFP SRKHR7 = 32a29687,
+
+ then following would be the value on dumping SRK hash.
+
+ .. code:: shell
+
+ md $SRKHR0 0x10
+
+ Command Output:
+ 01e80254: d4fec2fd 9e567f31 5c422818 fd5c7be8 ....1.V..(B\.{\.
+ 01e80264: 8fabbe34 702a79df e185ff2d 8796a232 4....y*p-...2...
+
+ Note: SRK Hash is visible in plain based on the SFP Block Endianness.
+
+- Caution: Donot proceed to the next step, until you are sure that OTPMK and SRKH are correctly blown from above steps.
+ -- After the next step, there is no turning back.
+ -- Fuses will be burnt, which cannot be undo.
+
+- Write SFP_INGR[INST] with the PROGFB(0x2) instruction to blow the fuses.
+ -- User need to save the SRK key pair and OTPMK Key forever, to continue using this board.
+
++---+----------------------------------+-------------------------------------------+-----------+
+| | Platform | SFP_INGR_REG | SFP_WRITE_DATE_FRM_MIRROR_REG_TO_FUSE |
++===+==================================+=======================================================+
+| 1.| lx2160ardb/lx2160aqds/lx2162aqds | 0x01E80020 | 0x2 |
++---+----------------------------------+--------------+----------------------------------------+
+
+ .. code:: shell
+
+ md $SFP_INGR_REG $SFP_WRITE_DATE_FRM_MIRROR_REG_TO_FUSE
+
+- On reset, if the SFP register were read from u-boot, it will show the following:
+ -- Check for the OTPMK.
+
+ .. code:: shell
+
+ md $SNVS_HPSR_REG
+
+ Command Output:
+ 01e90014: 80000900
+
+ In case it is read as 00000000, then read this register using jtag (in development mode only through CW tap).
+ +0 +4 +8 +C
+ [0x01E90014] 80000900
+
+ Note: OTPMK_ZERO_BIT is zero, indicating that the OTPMK is blown.
+
+ .. code:: shell
+
+ md $OTPMKR0 0x10
+
+ Command Output:
+ 01e80234: ffffffff ffffffff ffffffff ffffffff ................
+ 01e80244: ffffffff ffffffff ffffffff ffffffff ................
+
+ Note: OTPMK will never be visible in plain.
+
+ -- SRK Hash
+
+ .. code:: shell
+
+ md $SRKHR0 0x10
+
+ Command Output:
+ 01e80254: d4fec2fd 9e567f31 5c422818 fd5c7be8 ....1.V..(B\.{\.
+ 01e80264: 8fabbe34 702a79df e185ff2d 8796a232 4....y*p-...2...
+
+ Note: SRK Hash is visible in plain based on the SFP Block Endianness.
+
+Second method to do the fuse provsioning:
+=========================================
+
+This method is used for quick way to provision fuses.
+Typically used by those who needs to provision number of boards.
+
+- Enable POVDD:
+ -- Refer the table above to enable POVDD.
+
+ Note: If GPIO Pin supports enabling POVDD, it can be done through the below input_fuse_file.
+
+ -- Once the POVDD is enabled, make sure to set variable POVDD_ENABLE := yes, in the platform.mk.
+
+- User need to populate the "input_fuse_file", corresponding to the platform for:
+
+ -- OTPMK
+ -- SRKH
+
+ Table of fuse provisioning input file for every supported platform:
+
++---+----------------------------------+-----------------------------------------------------------------+
+| | Platform | FUSE_PROV_FILE |
++===+==================================+=================================================================+
+| 1.| lx2160ardb/lx2160aqds/lx2162aqds | ${CST_DIR}/input_files/gen_fusescr/ls2088_1088/input_fuse_file |
++---+----------------------------------+--------------+--------------------------------------------------+
+
+- Create the TF-A binary with FUSE_PROG=1.
+
+ .. code:: shell
+
+ make PLAT=$PLAT FUSE_PROG=1\
+ BOOT_MODE=<platform_supported_boot_mode> \
+ RCW=$RCW_BIN \
+ BL32=$TEE_BIN SPD=opteed\
+ BL33=$UBOOT_SECURE_BIN \
+ pbl \
+ fip \
+ fip_fuse \
+ FUSE_PROV_FILE=../../apps/security/cst/input_files/gen_fusescr/ls2088_1088/input_fuse_file
+
+- Deployment:
+ -- Refer the nxp-layerscape.rst for deploying TF-A images.
+ -- Deploying fip_fuse.bin:
+
+ For Flexspi-Nor:
+
+ .. code:: shell
+
+ tftp 82000000 $path/fuse_fip.bin;
+ i2c mw 66 50 20;sf probe 0:0; sf erase 0x880000 +$filesize; sf write 0x82000000 0x880000 $filesize;
+
+ For SD or eMMC [file_size_in_block_sizeof_512 = (Size_of_bytes_tftp / 512)]:
+
+ .. code:: shell
+
+ tftp 82000000 $path/fuse_fip.bin;
+ mmc write 82000000 0x4408 <file_size_in_block_sizeof_512>;
+
+- Valiation:
+
++---+----------------------------------+---------------------------------------------------+
+| | Platform | Error_Register | Error_Register_Address |
++===+==================================+===================================================+
+| 1.| lx2160ardb/lx2160aqds/lx2162aqds | DCFG scratch 4 register | 0x01EE020C |
++---+----------------------------------+---------------------------------------------------+
+
+ At the U-Boot prompt, check DCFG scratch 4 register for any error.
+
+ .. code:: shell
+
+ md $Error_Register_Address 1
+
+ Command Ouput:
+ 01ee020c: 00000000
+
+ Note:
+ - 0x00000000 shows no error, then fuse provisioning is successful.
+ - For non-zero value, refer the code header file ".../drivers/nxp/sfp/sfp_error_codes.h"
diff --git a/docs/plat/nxp/nxp-ls-tbbr.rst b/docs/plat/nxp/nxp-ls-tbbr.rst
new file mode 100644
index 0000000..43e15f7
--- /dev/null
+++ b/docs/plat/nxp/nxp-ls-tbbr.rst
@@ -0,0 +1,210 @@
+
+--------------
+NXP Platforms:
+--------------
+TRUSTED_BOARD_BOOT option can be enabled by specifying TRUSTED_BOARD_BOOT=1 on command line during make.
+
+
+
+Bare-Minimum Preparation to run TBBR on NXP Platforms:
+=======================================================
+- OTPMK(One Time Programable Key) needs to be burnt in fuses.
+ -- It is the 256 bit key that stores a secret value used by the NXP SEC 4.0 IP in Trusted or Secure mode.
+
+ Note: It is primarily for the purpose of decrypting additional secrets stored in system non-volatile memory.
+
+ -- NXP CST tool gives an option to generate it.
+
+ Use the below command from directory 'cst', with correct options.
+
+ .. code:: shell
+
+ ./gen_otpmk_drbg
+
+- SRKH (Super Root Key Hash) needs to be burnt in fuses.
+ -- It is the 256 bit hash of the list of the public keys of the SRK key pair.
+ -- NXP CST tool gives an option to generate the RSA key pair and its hash.
+
+ Use the below command from directory 'cst', with correct options.
+
+ .. code:: shell
+
+ ./gen_keys
+
+Refer fuse frovisioning readme 'nxp-ls-fuse-prov.rst' for steps to blow these keys.
+
+
+
+Two options are provided for TRUSTED_BOARD_BOOT:
+================================================
+
+-------------------------------------------------------------------------
+Option 1: CoT using X 509 certificates
+-------------------------------------------------------------------------
+
+- This CoT is as provided by ARM.
+
+- To use this option user needs to specify mbedtld dir path in MBEDTLS_DIR.
+
+- To generate CSF header, path of CST repository needs to be specified as CST_DIR
+
+- CSF header is embedded to each of the BL2 image.
+
+- GENERATE_COT=1 adds the tool 'cert_create' to the build environment to generate:
+ -- X509 Certificates as (.crt) files.
+ -- X509 Pem key file as (.pem) files.
+
+- SAVE_KEYS=1 saves the keys and certificates, if GENERATE_COT=1.
+ -- For this to work, file name for cert and keys are provided as part of compilation or build command.
+
+ --- default file names will be used, incase not provided as part compilation or build command.
+ --- default folder 'BUILD_PLAT' will be used to store them.
+
+- ROTPK for x.509 certificates is generated and embedded in bl2.bin and
+ verified as part of CoT by Boot ROM during secure boot.
+
+- Compilation steps:
+
+All Images
+ .. code:: shell
+
+ make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 MBEDTLS_DIR=$MBEDTLS_PATH CST_DIR=$CST_DIR_PATH \
+ BOOT_MODE=<platform_supported_boot_mode> \
+ RCW=$RCW_BIN \
+ BL32=$TEE_BIN SPD=opteed\
+ BL33=$UBOOT_SECURE_BIN \
+ pbl \
+ fip
+
+Additional FIP_DDR Image (For NXP platforms like lx2160a)
+ .. code:: shell
+
+ make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 MBEDTLS_DIR=$MBEDTLS_PATH fip_ddr
+
+ Note: make target 'fip_ddr' should never be combine with other make target 'fip', 'pbl' & 'bl2'.
+
+-------------------------------------------------------------------------
+Option 2: CoT using NXP CSF headers.
+-------------------------------------------------------------------------
+
+- This option is automatically selected when TRUSTED_BOARD_BOOT is set but MBEDTLS_DIR path is not specified.
+
+- CSF header is embedded to each of the BL31, BL32 and BL33 image.
+
+- To generate CSF header, path of CST repository needs to be specified as CST_DIR
+
+- Default input files for CSF header generation is added in this repo.
+
+- Default input file requires user to generate RSA key pair named
+ -- srk.pri, and
+ -- srk.pub, and add them in ATF repo.
+ -- These keys can be generated using gen_keys tool of CST.
+
+- To change the input file , user can use the options BL33_INPUT_FILE, BL32_INPUT_FILE, BL31_INPUT_FILE
+
+- There are 2 paths in secure boot flow :
+ -- Development Mode (sb_en in RCW = 1, SFP->OSPR, ITS = 0)
+
+ --- In this flow , even on ROTPK comparison failure, flow would continue.
+ --- However SNVS is transitioned to non-secure state
+
+ -- Production mode (SFP->OSPR, ITS = 1)
+
+ --- Any failure is fatal failure
+
+- Compilation steps:
+
+All Images
+ .. code:: shell
+
+ make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 CST_DIR=$CST_DIR_PATH \
+ BOOT_MODE=<platform_supported_boot_mode> \
+ RCW=$RCW_BIN \
+ BL32=$TEE_BIN SPD=opteed\
+ BL33=$UBOOT_SECURE_BIN \
+ pbl \
+ fip
+
+Additional FIP_DDR Image (For NXP platforms like lx2160a)
+ .. code:: shell
+
+ make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 CST_DIR=$CST_DIR_PATH fip_ddr
+
+- Compilation Steps with build option for generic image processing filters to prepend CSF header:
+ -- Generic image processing filters to prepend CSF header
+
+ BL32_INPUT_FILE = < file name>
+ BL33_INPUT_FILE = <file name>
+
+ .. code:: shell
+
+ make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 CST_DIR=$CST_DIR_PATH \
+ BOOT_MODE=<platform_supported_boot_mode> \
+ RCW=$RCW_BIN \
+ BL32=$TEE_BIN SPD=opteed\
+ BL33=$UBOOT_SECURE_BIN \
+ BL33_INPUT_FILE = <ip file> \
+ BL32_INPUT_FILE = <ip_file> \
+ BL31_INPUT_FILE = <ip file> \
+ pbl \
+ fip
+
+
+Deploy ATF Images
+=================
+Same steps as mentioned in the readme "nxp-layerscape.rst".
+
+
+
+Verification to check if Secure state is achieved:
+==================================================
+
++---+----------------+-----------------+------------------------+----------------------------------+-------------------------------+
+| | Platform | SNVS_HPSR_REG | SYS_SECURE_BIT(=value) | SYSTEM_SECURE_CONFIG_BIT(=value) | SSM_STATE |
++===+================+=================+========================+==================================+===============================+
+| 1.| lx2160ardb or | 0x01E90014 | 15 | 14-12 | 11-8 |
+| | lx2160aqds or | | ( = 1, BootROM Booted) | ( = 010 means Intent to Secure, | (=1111 means secure boot) |
+| | lx2162aqds | | | ( = 000 Unsecure) | (=1011 means Non-secure Boot) |
++---+----------------+-----------------+------------------------+----------------------------------+-------------------------------+
+
+- Production mode (SFP->OSPR, ITS = 1)
+ -- Linux prompt will successfully come. if the TBBR is successful.
+
+ --- Else, Linux boot will be successful.
+
+ -- For secure-boot status, read SNVS Register $SNVS_HPSR_REG from u-boot prompt:
+
+ .. code:: shell
+
+ md $SNVS_HPSR_REG
+
+ Command Output:
+ 1e90014: 8000AF00
+
+ In case it is read as 00000000, then read this register using jtag (in development mode only through CW tap).
+ +0 +4 +8 +C
+ [0x01E90014] 8000AF00
+
+
+- Development Mode (sb_en in RCW = 1, SFP->OSPR, ITS = 0)
+ -- Refer the SoC specific table to read the register to interpret whether the secure boot is achieved or not.
+ -- Using JTAG (in development environment only, using CW tap):
+
+ --- For secure-boot status, read SNVS Register $SNVS_HPSR_REG
+
+ .. code:: shell
+
+ ccs::display_regs 86 0x01E90014 4 0 1
+
+ Command Output:
+ Using the SAP chain position number 86, following is the output.
+
+ +0 +4 +8 +C
+ [0x01E90014] 8000AF00
+
+ Note: Chain position number will vary from one SoC to other SoC.
+
+- Interpretation of the value:
+
+ -- 0xA indicates BootROM booted, with intent to secure.
+ -- 0xF = secure boot, as SSM_STATE.
diff --git a/docs/process/contributing.rst b/docs/process/contributing.rst
index c91903a..a0d0683 100644
--- a/docs/process/contributing.rst
+++ b/docs/process/contributing.rst
@@ -209,6 +209,65 @@
revert your patches and ask you to resubmit a reworked version of them or
they may ask you to provide a fix-up patch.
+Add Build Configurations
+------------------------
+
+- TF-A uses Jenkins tool for Continuous Integration and testing activities.
+ Various CI Jobs are deployed which run tests on every patch before being
+ merged. So each of your patches go through a series of checks before they
+ get merged on to the master branch.
+
+- ``Coverity Scan analysis`` is one of the tests we perform on our source code
+ at regular intervals. We maintain a build script ``tf-cov-make`` which contains the
+ build configurations of various platforms in order to cover the entire source
+ code being analysed by Coverity.
+
+- When you submit your patches for review containing new source files, please
+ ensure to include them for the ``Coverity Scan analysis`` by adding the
+ respective build configurations in the ``tf-cov-make`` build script.
+
+- In this section you find the details on how to append your new build
+ configurations for Coverity Scan analysis:
+
+#. We maintain a separate repository named `tf-a-ci-scripts repository`_
+ for placing all the test scripts which will be executed by the CI Jobs.
+
+#. In this repository, ``tf-cov-make`` script is located at
+ ``tf-a-ci-scripts/script/tf-coverity/tf-cov-make``
+
+#. Edit `tf-cov-make`_ script by appending all the possible build configurations with
+ the specific ``build-flags`` relevant to your platform, so that newly added
+ source files get built and analysed by Coverity.
+
+#. For better understanding follow the below specified examples listed in the
+ ``tf-cov-make`` script.
+
+.. code:: c
+
+ Example 1:
+ #Intel
+ make PLAT=stratix10 $(common_flags) all
+ make PLAT=agilex $(common_flags) all
+
+- In the above example there are two different SoCs ``stratix`` and ``agilex``
+ under the Intel platform and the build configurations has been added suitably
+ to include most of their source files.
+
+.. code:: c
+
+ Example 2:
+ #Hikey
+ make PLAT=hikey $(common_flags) ${TBB_OPTIONS} ENABLE_PMF=1 all
+ make PLAT=hikey960 $(common_flags) ${TBB_OPTIONS} all
+ make PLAT=poplar $(common_flags) all
+
+- In this case for ``Hikey`` boards additional ``build-flags`` has been included
+ along with the ``commom_flags`` to cover most of the files relevant to it.
+
+- Similar to this you can still find many other different build configurations
+ of various other platforms listed in the ``tf-cov-make`` script. Kindly refer
+ them and append your build configurations respectively.
+
Binary Components
-----------------
@@ -228,7 +287,7 @@
--------------
-*Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.*
.. _Conventional Commits: https://www.conventionalcommits.org/en/v1.0.0
.. _developer.trustedfirmware.org: https://developer.trustedfirmware.org
@@ -243,3 +302,5 @@
.. _Trusted Firmware binary repository: https://review.trustedfirmware.org/admin/repos/tf-binaries
.. _tf-binaries-readme: https://git.trustedfirmware.org/tf-binaries.git/tree/readme.rst
.. _TF-A mailing list: https://lists.trustedfirmware.org/mailman/listinfo/tf-a
+.. _tf-a-ci-scripts repository: https://git.trustedfirmware.org/ci/tf-a-ci-scripts.git/
+.. _tf-cov-make: https://git.trustedfirmware.org/ci/tf-a-ci-scripts.git/tree/script/tf-coverity/tf-cov-make
diff --git a/drivers/arm/gic/v3/gic600ae_fmu.c b/drivers/arm/gic/v3/gic600ae_fmu.c
new file mode 100644
index 0000000..13979fa
--- /dev/null
+++ b/drivers/arm/gic/v3/gic600ae_fmu.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Driver for GIC-600AE Fault Management Unit
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/gic600ae_fmu.h>
+#include <drivers/arm/gicv3.h>
+
+/* GIC-600 AE FMU specific register offsets */
+
+/* GIC-600 AE FMU specific macros */
+#define FMU_ERRIDR_NUM U(44)
+#define FMU_ERRIDR_NUM_MASK U(0xFFFF)
+
+/* Safety mechanisms for GICD block */
+static char *gicd_sm_info[] = {
+ "Reserved",
+ "GICD dual lockstep error",
+ "GICD AXI4 slave interface error",
+ "GICD-PPI AXI4-Stream interface error",
+ "GICD-ITS AXI4-Stream interface error",
+ "GICD-SPI-Collator AXI4-Stream interface error",
+ "GICD AXI4 master interface error",
+ "SPI RAM DED error",
+ "SGI RAM DED error",
+ "Reserved",
+ "LPI RAM DED error",
+ "GICD-remote-GICD AXI4-Stream interface error",
+ "GICD Q-Channel interface error",
+ "GICD P-Channel interface error",
+ "SPI RAM address decode error",
+ "SGI RAM address decode error",
+ "Reserved",
+ "LPI RAM address decode error",
+ "FMU dual lockstep error",
+ "FMU ping ACK error",
+ "FMU APB parity error",
+ "GICD-Wake AXI4-Stream interface error",
+ "GICD PageOffset or Chip ID error",
+ "MBIST REQ error",
+ "SPI RAM SEC error",
+ "SGI RAM SEC error",
+ "Reserved",
+ "LPI RAM SEC error",
+ "User custom SM0 error",
+ "User custom SM1 error",
+ "GICD-ITS Monolithic switch error",
+ "GICD-ITS Q-Channel interface error",
+ "GICD-ITS Monolithic interface error",
+ "GICD FMU ClkGate override"
+};
+
+/* Safety mechanisms for PPI block */
+static char *ppi_sm_info[] = {
+ "Reserved",
+ "PPI dual lockstep error",
+ "PPI-GICD AXI4-Stream interface error",
+ "PPI-CPU-IF AXI4-Stream interface error",
+ "PPI Q-Channel interface error",
+ "PPI RAM DED error",
+ "PPI RAM address decode error",
+ "PPI RAM SEC error",
+ "PPI User0 SM",
+ "PPI User1 SM",
+ "MBIST REQ error",
+ "PPI interrupt parity protection error",
+ "PPI FMU ClkGate override"
+};
+
+/* Safety mechanisms for ITS block */
+static char *its_sm_info[] = {
+ "Reserved",
+ "ITS dual lockstep error",
+ "ITS-GICD AXI4-Stream interface error",
+ "ITS AXI4 slave interface error",
+ "ITS AXI4 master interface error",
+ "ITS Q-Channel interface error",
+ "ITS RAM DED error",
+ "ITS RAM address decode error",
+ "Bypass ACE switch error",
+ "ITS RAM SEC error",
+ "ITS User0 SM",
+ "ITS User1 SM",
+ "ITS-GICD Monolithic interface error",
+ "MBIST REQ error",
+ "ITS FMU ClkGate override"
+};
+
+/* Safety mechanisms for SPI Collator block */
+static char *spicol_sm_info[] = {
+ "Reserved",
+ "SPI Collator dual lockstep error",
+ "SPI-Collator-GICD AXI4-Stream interface error",
+ "SPI Collator Q-Channel interface error",
+ "SPI Collator Q-Channel clock error",
+ "SPI interrupt parity error"
+};
+
+/* Safety mechanisms for Wake Request block */
+static char *wkrqst_sm_info[] = {
+ "Reserved",
+ "Wake dual lockstep error",
+ "Wake-GICD AXI4-Stream interface error"
+};
+
+/*
+ * Initialization sequence for the FMU
+ *
+ * 1. enable error detection for error records that are passed in the blk_present_mask
+ * 2. enable MBIST REQ and FMU Clk Gate override safety mechanisms for error records
+ * that are present on the platform
+ *
+ * The platforms are expected to pass `errctlr_ce_en` and `errctlr_ue_en`.
+ */
+void gic600_fmu_init(uint64_t base, uint64_t blk_present_mask,
+ bool errctlr_ce_en, bool errctlr_ue_en)
+{
+ unsigned int num_blk = gic_fmu_read_erridr(base) & FMU_ERRIDR_NUM_MASK;
+ uint64_t errctlr;
+ uint32_t smen;
+
+ INFO("GIC600-AE FMU supports %d error records\n", num_blk);
+
+ assert(num_blk == FMU_ERRIDR_NUM);
+
+ /* sanitize block present mask */
+ blk_present_mask &= FMU_BLK_PRESENT_MASK;
+
+ /* Enable error detection for all error records */
+ for (unsigned int i = 0U; i < num_blk; i++) {
+
+ /* Skip next steps if the block is not present */
+ if ((blk_present_mask & BIT(i)) == 0U) {
+ continue;
+ }
+
+ /* Read the error record control register */
+ errctlr = gic_fmu_read_errctlr(base, i);
+
+ /* Enable error reporting and logging, if it is disabled */
+ if ((errctlr & FMU_ERRCTLR_ED_BIT) == 0U) {
+ errctlr |= FMU_ERRCTLR_ED_BIT;
+ }
+
+ /* Enable client provided ERRCTLR settings */
+ errctlr |= (errctlr_ce_en ? (FMU_ERRCTLR_CI_BIT | FMU_ERRCTLR_CE_EN_BIT) : 0);
+ errctlr |= (errctlr_ue_en ? FMU_ERRCTLR_UI_BIT : 0U);
+
+ gic_fmu_write_errctlr(base, i, errctlr);
+ }
+
+ /*
+ * Enable MBIST REQ error and FMU CLK gate override safety mechanisms for
+ * all blocks
+ *
+ * GICD, SMID 23 and SMID 33
+ * PPI, SMID 10 and SMID 12
+ * ITS, SMID 13 and SMID 14
+ */
+ if ((blk_present_mask & BIT(FMU_BLK_GICD)) != 0U) {
+ smen = (GICD_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) |
+ (FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT);
+ gic_fmu_write_smen(base, smen);
+
+ smen = (GICD_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
+ (FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT);
+ gic_fmu_write_smen(base, smen);
+ }
+
+ for (unsigned int i = FMU_BLK_PPI0; i < FMU_BLK_PPI31; i++) {
+ if ((blk_present_mask & BIT(i)) != 0U) {
+ smen = (PPI_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) |
+ (i << FMU_SMEN_BLK_SHIFT);
+ gic_fmu_write_smen(base, smen);
+
+ smen = (PPI_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
+ (i << FMU_SMEN_BLK_SHIFT);
+ gic_fmu_write_smen(base, smen);
+ }
+ }
+
+ for (unsigned int i = FMU_BLK_ITS0; i < FMU_BLK_ITS7; i++) {
+ if ((blk_present_mask & BIT(i)) != 0U) {
+ smen = (ITS_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) |
+ (i << FMU_SMEN_BLK_SHIFT);
+ gic_fmu_write_smen(base, smen);
+
+ smen = (ITS_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
+ (i << FMU_SMEN_BLK_SHIFT);
+ gic_fmu_write_smen(base, smen);
+ }
+ }
+}
+
+/*
+ * This function enable the GICD background ping engine. The GICD sends ping
+ * messages to each remote GIC block, and expects a PING_ACK back within the
+ * specified timeout. Pings need to be enabled after programming the timeout
+ * value.
+ */
+void gic600_fmu_enable_ping(uint64_t base, uint64_t blk_present_mask,
+ unsigned int timeout_val, unsigned int interval_diff)
+{
+ /*
+ * Populate the PING Mask to skip a specific block while generating
+ * background ping messages and enable the ping mechanism.
+ */
+ gic_fmu_write_pingmask(base, ~blk_present_mask);
+ gic_fmu_write_pingctlr(base, (interval_diff << FMU_PINGCTLR_INTDIFF_SHIFT) |
+ (timeout_val << FMU_PINGCTLR_TIMEOUTVAL_SHIFT) | FMU_PINGCTLR_EN_BIT);
+}
+
+/* Print the safety mechanism description for a given block */
+void gic600_fmu_print_sm_info(uint64_t base, unsigned int blk, unsigned int smid)
+{
+ if (blk == FMU_BLK_GICD && smid <= FMU_SMID_GICD_MAX) {
+ INFO("GICD, SMID %d: %s\n", smid, gicd_sm_info[smid]);
+ }
+
+ if (blk == FMU_BLK_SPICOL && smid <= FMU_SMID_SPICOL_MAX) {
+ INFO("SPI Collator, SMID %d: %s\n", smid, spicol_sm_info[smid]);
+ }
+
+ if (blk == FMU_BLK_WAKERQ && (smid <= FMU_SMID_WAKERQ_MAX)) {
+ INFO("Wake Request, SMID %d: %s\n", smid, wkrqst_sm_info[smid]);
+ }
+
+ if (((blk >= FMU_BLK_ITS0) && (blk <= FMU_BLK_ITS7)) && (smid <= FMU_SMID_ITS_MAX)) {
+ INFO("ITS, SMID %d: %s\n", smid, its_sm_info[smid]);
+ }
+
+ if (((blk >= FMU_BLK_PPI0) && (blk <= FMU_BLK_PPI31)) && (smid <= FMU_SMID_PPI_MAX)) {
+ INFO("PPI, SMID %d: %s\n", smid, ppi_sm_info[smid]);
+ }
+}
diff --git a/drivers/arm/gic/v3/gic600ae_fmu_helpers.c b/drivers/arm/gic/v3/gic600ae_fmu_helpers.c
new file mode 100644
index 0000000..84f7292
--- /dev/null
+++ b/drivers/arm/gic/v3/gic600ae_fmu_helpers.c
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <drivers/arm/gic600ae_fmu.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#define GICFMU_IDLE_TIMEOUT_US U(2000000)
+
+/* Macro to write 32-bit FMU registers */
+#define GIC_FMU_WRITE_32(base, reg, val) \
+ do { \
+ /* \
+ * This register receives the unlock key that is required for \
+ * writes to FMU registers to be successful. \
+ */ \
+ mmio_write_32(base + GICFMU_KEY, 0xBE); \
+ /* Perform the actual write */ \
+ mmio_write_32((base) + (reg), (val)); \
+ } while (false)
+
+/* Macro to write 64-bit FMU registers */
+#define GIC_FMU_WRITE_64(base, reg, n, val) \
+ do { \
+ /* \
+ * This register receives the unlock key that is required for \
+ * writes to FMU registers to be successful. \
+ */ \
+ mmio_write_32(base + GICFMU_KEY, 0xBE); \
+ /* \
+ * APB bus is 32-bit wide; so split the 64-bit write into \
+ * two 32-bit writes \
+ */ \
+ mmio_write_32((base) + reg##_LO + (n * 64), (val)); \
+ mmio_write_32((base) + reg##_HI + (n * 64), (val)); \
+ } while (false)
+
+/* Helper function to wait until FMU is ready to accept the next command */
+static void wait_until_fmu_is_idle(uintptr_t base)
+{
+ uint64_t timeout_ref = timeout_init_us(GICFMU_IDLE_TIMEOUT_US);
+ uint64_t status;
+
+ /* wait until status is 'busy' */
+ do {
+ status = (gic_fmu_read_status(base) & BIT(0));
+
+ if (timeout_elapsed(timeout_ref)) {
+ ERROR("GIC600 AE FMU is not responding\n");
+ panic();
+ }
+ } while (status == U(0));
+}
+
+#define GIC_FMU_WRITE_ON_IDLE_32(base, reg, val) \
+ do { \
+ /* Wait until FMU is ready */ \
+ wait_until_fmu_is_idle(base); \
+ /* Actual register write */ \
+ GIC_FMU_WRITE_32(base, reg, val); \
+ /* Wait until FMU is ready */ \
+ wait_until_fmu_is_idle(base); \
+ } while (false)
+
+#define GIC_FMU_WRITE_ON_IDLE_64(base, reg, n, val) \
+ do { \
+ /* Wait until FMU is ready */ \
+ wait_until_fmu_is_idle(base); \
+ /* Actual register write */ \
+ GIC_FMU_WRITE_64(base, reg, n, val); \
+ /* Wait until FMU is ready */ \
+ wait_until_fmu_is_idle(base); \
+ } while (false)
+
+/*******************************************************************************
+ * GIC FMU functions for accessing the Fault Management Unit registers
+ ******************************************************************************/
+
+/*
+ * Accessors to read the Error Record Feature Register bits corresponding
+ * to an error record 'n'
+ */
+uint64_t gic_fmu_read_errfr(uintptr_t base, unsigned int n)
+{
+ /*
+ * APB bus is 32-bit wide; so split the 64-bit read into
+ * two 32-bit reads
+ */
+ uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRFR_LO + n * 64U);
+
+ reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRFR_HI + n * 64U) << 32);
+ return reg_val;
+}
+
+/*
+ * Accessors to read the Error Record Control Register bits corresponding
+ * to an error record 'n'
+ */
+uint64_t gic_fmu_read_errctlr(uintptr_t base, unsigned int n)
+{
+ /*
+ * APB bus is 32-bit wide; so split the 64-bit read into
+ * two 32-bit reads
+ */
+ uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRCTLR_LO + n * 64U);
+
+ reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRCTLR_HI + n * 64U) << 32);
+ return reg_val;
+}
+
+/*
+ * Accessors to read the Error Record Primary Status Register bits
+ * corresponding to an error record 'n'
+ */
+uint64_t gic_fmu_read_errstatus(uintptr_t base, unsigned int n)
+{
+ /*
+ * APB bus is 32-bit wide; so split the 64-bit read into
+ * two 32-bit reads
+ */
+ uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRSTATUS_LO + n * 64U);
+
+ reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRSTATUS_HI + n * 64U) << 32);
+ return reg_val;
+}
+
+/*
+ * Accessors to read the Error Group Status Register
+ */
+uint64_t gic_fmu_read_errgsr(uintptr_t base)
+{
+ /*
+ * APB bus is 32-bit wide; so split the 64-bit read into
+ * two 32-bit reads
+ */
+ uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRGSR_LO);
+
+ reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRGSR_HI) << 32);
+ return reg_val;
+}
+
+/*
+ * Accessors to read the Ping Control Register
+ */
+uint32_t gic_fmu_read_pingctlr(uintptr_t base)
+{
+ return mmio_read_32(base + GICFMU_PINGCTLR);
+}
+
+/*
+ * Accessors to read the Ping Now Register
+ */
+uint32_t gic_fmu_read_pingnow(uintptr_t base)
+{
+ return mmio_read_32(base + GICFMU_PINGNOW);
+}
+
+/*
+ * Accessors to read the Ping Mask Register
+ */
+uint64_t gic_fmu_read_pingmask(uintptr_t base)
+{
+ /*
+ * APB bus is 32-bit wide; so split the 64-bit read into
+ * two 32-bit reads
+ */
+ uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_PINGMASK_LO);
+
+ reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_PINGMASK_HI) << 32);
+ return reg_val;
+}
+
+/*
+ * Accessors to read the FMU Status Register
+ */
+uint32_t gic_fmu_read_status(uintptr_t base)
+{
+ return mmio_read_32(base + GICFMU_STATUS);
+}
+
+/*
+ * Accessors to read the Error Record ID Register
+ */
+uint32_t gic_fmu_read_erridr(uintptr_t base)
+{
+ return mmio_read_32(base + GICFMU_ERRIDR);
+}
+
+/*
+ * Accessors to write a 64 bit value to the Error Record Control Register
+ */
+void gic_fmu_write_errctlr(uintptr_t base, unsigned int n, uint64_t val)
+{
+ GIC_FMU_WRITE_64(base, GICFMU_ERRCTLR, n, val);
+}
+
+/*
+ * Accessors to write a 64 bit value to the Error Record Primary Status
+ * Register
+ */
+void gic_fmu_write_errstatus(uintptr_t base, unsigned int n, uint64_t val)
+{
+ /* Wait until FMU is ready before writing */
+ GIC_FMU_WRITE_ON_IDLE_64(base, GICFMU_ERRSTATUS, n, val);
+}
+
+/*
+ * Accessors to write a 32 bit value to the Ping Control Register
+ */
+void gic_fmu_write_pingctlr(uintptr_t base, uint32_t val)
+{
+ GIC_FMU_WRITE_32(base, GICFMU_PINGCTLR, val);
+}
+
+/*
+ * Accessors to write a 32 bit value to the Ping Now Register
+ */
+void gic_fmu_write_pingnow(uintptr_t base, uint32_t val)
+{
+ /* Wait until FMU is ready before writing */
+ GIC_FMU_WRITE_ON_IDLE_32(base, GICFMU_PINGNOW, val);
+}
+
+/*
+ * Accessors to write a 32 bit value to the Safety Mechanism Enable Register
+ */
+void gic_fmu_write_smen(uintptr_t base, uint32_t val)
+{
+ /* Wait until FMU is ready before writing */
+ GIC_FMU_WRITE_ON_IDLE_32(base, GICFMU_SMEN, val);
+}
+
+/*
+ * Accessors to write a 32 bit value to the Safety Mechanism Inject Error
+ * Register
+ */
+void gic_fmu_write_sminjerr(uintptr_t base, uint32_t val)
+{
+ /* Wait until FMU is ready before writing */
+ GIC_FMU_WRITE_ON_IDLE_32(base, GICFMU_SMINJERR, val);
+}
+
+/*
+ * Accessors to write a 64 bit value to the Ping Mask Register
+ */
+void gic_fmu_write_pingmask(uintptr_t base, uint64_t val)
+{
+ GIC_FMU_WRITE_64(base, GICFMU_PINGMASK, 0, val);
+}
diff --git a/drivers/arm/gic/v3/gicv3.mk b/drivers/arm/gic/v3/gicv3.mk
index a2fc16f..d7e3536 100644
--- a/drivers/arm/gic/v3/gicv3.mk
+++ b/drivers/arm/gic/v3/gicv3.mk
@@ -1,11 +1,13 @@
#
# Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
# Default configuration values
GICV3_SUPPORT_GIC600 ?= 0
+GICV3_SUPPORT_GIC600AE_FMU ?= 0
GICV3_IMPL_GIC600_MULTICHIP ?= 0
GICV3_OVERRIDE_DISTIF_PWR_OPS ?= 0
GIC_ENABLE_V4_EXTN ?= 0
@@ -16,6 +18,11 @@
drivers/arm/gic/v3/gicdv3_helpers.c \
drivers/arm/gic/v3/gicrv3_helpers.c
+ifeq (${GICV3_SUPPORT_GIC600AE_FMU}, 1)
+GICV3_SOURCES += drivers/arm/gic/v3/gic600ae_fmu.c \
+ drivers/arm/gic/v3/gic600ae_fmu_helpers.c
+endif
+
ifeq (${GICV3_OVERRIDE_DISTIF_PWR_OPS}, 0)
GICV3_SOURCES += drivers/arm/gic/v3/arm_gicv3_common.c
endif
@@ -29,6 +36,10 @@
$(eval $(call assert_boolean,GICV3_SUPPORT_GIC600))
$(eval $(call add_define,GICV3_SUPPORT_GIC600))
+# Set GIC-600AE FMU support
+$(eval $(call assert_boolean,GICV3_SUPPORT_GIC600AE_FMU))
+$(eval $(call add_define,GICV3_SUPPORT_GIC600AE_FMU))
+
# Set GICv4 extension
$(eval $(call assert_boolean,GIC_ENABLE_V4_EXTN))
$(eval $(call add_define,GIC_ENABLE_V4_EXTN))
diff --git a/drivers/marvell/comphy/comphy-cp110.h b/drivers/marvell/comphy/comphy-cp110.h
index 9b10619..af5c715 100644
--- a/drivers/marvell/comphy/comphy-cp110.h
+++ b/drivers/marvell/comphy/comphy-cp110.h
@@ -54,7 +54,7 @@
#define COMMON_SELECTOR_PIPE_COMPHY_USBH 0x1
#define COMMON_SELECTOR_PIPE_COMPHY_USBD 0x2
-/* SGMII/HS-SGMII/SFI/RXAUI */
+/* SGMII/Base-X/SFI/RXAUI */
#define COMMON_SELECTOR_COMPHY0_1_2_NETWORK 0x1
#define COMMON_SELECTOR_COMPHY3_RXAUI 0x1
#define COMMON_SELECTOR_COMPHY3_SGMII 0x2
diff --git a/drivers/marvell/comphy/phy-comphy-3700.c b/drivers/marvell/comphy/phy-comphy-3700.c
index 7377e5e..027d07d 100644
--- a/drivers/marvell/comphy/phy-comphy-3700.c
+++ b/drivers/marvell/comphy/phy-comphy-3700.c
@@ -135,7 +135,7 @@
break;
case (COMPHY_SGMII_MODE):
- case (COMPHY_HS_SGMII_MODE):
+ case (COMPHY_2500BASEX_MODE):
if (comphy_index == COMPHY_LANE0)
reg &= ~COMPHY_SELECTOR_USB3_GBE1_SEL_BIT;
else if (comphy_index == COMPHY_LANE1)
@@ -183,7 +183,7 @@
* with COMPHY_USB3D_MODE or COMPHY_USB3H_MODE. (The usb3 phy initialization
* code does not differentiate between these modes.)
* Also it returns COMPHY_SGMII_MODE even if the phy was configures with
- * COMPHY_HS_SGMII_MODE. (The sgmii phy initialization code does differentiate
+ * COMPHY_2500BASEX_MODE. (The sgmii phy initialization code does differentiate
* between these modes, but it is irrelevant when powering the phy off.)
*/
static int mvebu_a3700_comphy_get_mode(uint8_t comphy_index)
@@ -401,8 +401,8 @@
/* SGMII 1G, SerDes speed 1.25G */
data |= SD_SPEED_1_25_G << GEN_RX_SEL_OFFSET;
data |= SD_SPEED_1_25_G << GEN_TX_SEL_OFFSET;
- } else if (mode == COMPHY_HS_SGMII_MODE) {
- /* HS SGMII (2.5G), SerDes speed 3.125G */
+ } else if (mode == COMPHY_2500BASEX_MODE) {
+ /* 2500Base-X, SerDes speed 3.125G */
data |= SD_SPEED_2_5_G << GEN_RX_SEL_OFFSET;
data |= SD_SPEED_2_5_G << GEN_TX_SEL_OFFSET;
} else {
@@ -479,7 +479,7 @@
* 25 MHz the default values stored in PHY registers are OK.
*/
debug("Running C-DPI phy init %s mode\n",
- mode == COMPHY_HS_SGMII_MODE ? "2G5" : "1G");
+ mode == COMPHY_2500BASEX_MODE ? "2G5" : "1G");
if (get_ref_clk() == 40)
comphy_sgmii_phy_init(comphy_index, mode, sd_ip_addr);
@@ -883,7 +883,7 @@
comphy_mode);
break;
case(COMPHY_SGMII_MODE):
- case(COMPHY_HS_SGMII_MODE):
+ case(COMPHY_2500BASEX_MODE):
ret = mvebu_a3700_comphy_sgmii_power_on(comphy_index,
comphy_mode);
break;
@@ -960,7 +960,7 @@
switch (mode) {
case(COMPHY_SGMII_MODE):
- case(COMPHY_HS_SGMII_MODE):
+ case(COMPHY_2500BASEX_MODE):
err = mvebu_a3700_comphy_sgmii_power_off(comphy_index);
break;
case (COMPHY_USB3_MODE):
diff --git a/drivers/marvell/comphy/phy-comphy-common.h b/drivers/marvell/comphy/phy-comphy-common.h
index e3b430a..c599437 100644
--- a/drivers/marvell/comphy/phy-comphy-common.h
+++ b/drivers/marvell/comphy/phy-comphy-common.h
@@ -87,7 +87,7 @@
#define COMPHY_SATA_MODE 0x1
#define COMPHY_SGMII_MODE 0x2 /* SGMII 1G */
-#define COMPHY_HS_SGMII_MODE 0x3 /* SGMII 2.5G */
+#define COMPHY_2500BASEX_MODE 0x3 /* 2500Base-X */
#define COMPHY_USB3H_MODE 0x4
#define COMPHY_USB3D_MODE 0x5
#define COMPHY_PCIE_MODE 0x6
diff --git a/drivers/marvell/comphy/phy-comphy-cp110.c b/drivers/marvell/comphy/phy-comphy-cp110.c
index 86f4c77..d10425b 100644
--- a/drivers/marvell/comphy/phy-comphy-cp110.c
+++ b/drivers/marvell/comphy/phy-comphy-cp110.c
@@ -30,7 +30,7 @@
/* COMPHY speed macro */
#define COMPHY_SPEED_1_25G 0 /* SGMII 1G */
#define COMPHY_SPEED_2_5G 1
-#define COMPHY_SPEED_3_125G 2 /* SGMII 2.5G */
+#define COMPHY_SPEED_3_125G 2 /* 2500Base-X */
#define COMPHY_SPEED_5G 3
#define COMPHY_SPEED_5_15625G 4 /* XFI 5G */
#define COMPHY_SPEED_6G 5
@@ -191,7 +191,7 @@
case(3):
/* For comphy 3:
* 0x1 = RXAUI_Lane1
- * 0x2 = SGMII/HS-SGMII Port1
+ * 0x2 = SGMII/Base-X Port1
*/
if (mode == COMPHY_RXAUI_MODE)
reg |= COMMON_SELECTOR_COMPHY3_RXAUI <<
@@ -202,20 +202,20 @@
break;
case(4):
/* For comphy 4:
- * 0x1 = SGMII/HS-SGMII Port1, XFI1/SFI1
- * 0x2 = SGMII/HS-SGMII Port0: XFI0/SFI0, RXAUI_Lane0
+ * 0x1 = SGMII/Base-X Port1, XFI1/SFI1
+ * 0x2 = SGMII/Base-X Port0: XFI0/SFI0, RXAUI_Lane0
*
- * We want to check if SGMII1/HS_SGMII1 is the
+ * We want to check if SGMII1 is the
* requested mode in order to determine which value
* should be set (all other modes use the same value)
* so we need to strip the mode, and check the ID
- * because we might handle SGMII0/HS_SGMII0 too.
+ * because we might handle SGMII0 too.
*/
/* TODO: need to distinguish between CP110 and CP115
* as SFI1/XFI1 available only for CP115.
*/
if ((mode == COMPHY_SGMII_MODE ||
- mode == COMPHY_HS_SGMII_MODE ||
+ mode == COMPHY_2500BASEX_MODE ||
mode == COMPHY_SFI_MODE ||
mode == COMPHY_XFI_MODE ||
mode == COMPHY_AP_MODE)
@@ -228,7 +228,7 @@
break;
case(5):
/* For comphy 5:
- * 0x1 = SGMII/HS-SGMII Port2
+ * 0x1 = SGMII/Base-X Port2
* 0x2 = RXAUI Lane1
*/
if (mode == COMPHY_RXAUI_MODE)
@@ -713,7 +713,7 @@
data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET;
data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET;
} else if (sgmii_speed == COMPHY_SPEED_3_125G) {
- /* HS SGMII (2.5G), SerDes speed 3.125G */
+ /* 2500Base-X, SerDes speed 3.125G */
data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET;
data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET;
} else {
@@ -2343,7 +2343,7 @@
switch (mode) {
case (COMPHY_SGMII_MODE):
- case (COMPHY_HS_SGMII_MODE):
+ case (COMPHY_2500BASEX_MODE):
case (COMPHY_XFI_MODE):
case (COMPHY_SFI_MODE):
case (COMPHY_RXAUI_MODE):
@@ -2378,7 +2378,7 @@
comphy_mode);
break;
case(COMPHY_SGMII_MODE):
- case(COMPHY_HS_SGMII_MODE):
+ case(COMPHY_2500BASEX_MODE):
err = mvebu_cp110_comphy_sgmii_power_on(comphy_base,
comphy_index,
comphy_mode);
diff --git a/include/drivers/arm/gic600ae_fmu.h b/include/drivers/arm/gic600ae_fmu.h
new file mode 100644
index 0000000..691ffc7
--- /dev/null
+++ b/include/drivers/arm/gic600ae_fmu.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GIC600AE_FMU_H
+#define GIC600AE_FMU_H
+
+/*******************************************************************************
+ * GIC600-AE FMU register offsets and constants
+ ******************************************************************************/
+#define GICFMU_ERRFR_LO U(0x000)
+#define GICFMU_ERRFR_HI U(0x004)
+#define GICFMU_ERRCTLR_LO U(0x008)
+#define GICFMU_ERRCTLR_HI U(0x00C)
+#define GICFMU_ERRSTATUS_LO U(0x010)
+#define GICFMU_ERRSTATUS_HI U(0x014)
+#define GICFMU_ERRGSR_LO U(0xE00)
+#define GICFMU_ERRGSR_HI U(0xE04)
+#define GICFMU_KEY U(0xEA0)
+#define GICFMU_PINGCTLR U(0xEA4)
+#define GICFMU_PINGNOW U(0xEA8)
+#define GICFMU_SMEN U(0xEB0)
+#define GICFMU_SMINJERR U(0xEB4)
+#define GICFMU_PINGMASK_LO U(0xEC0)
+#define GICFMU_PINGMASK_HI U(0xEC4)
+#define GICFMU_STATUS U(0xF00)
+#define GICFMU_ERRIDR U(0xFC8)
+
+/* ERRCTLR bits */
+#define FMU_ERRCTLR_ED_BIT BIT(0)
+#define FMU_ERRCTLR_CE_EN_BIT BIT(1)
+#define FMU_ERRCTLR_UI_BIT BIT(2)
+#define FMU_ERRCTLR_CI_BIT BIT(3)
+
+/* SMEN constants */
+#define FMU_SMEN_BLK_SHIFT U(8)
+#define FMU_SMEN_SMID_SHIFT U(24)
+
+/* Error record IDs */
+#define FMU_BLK_GICD U(0)
+#define FMU_BLK_SPICOL U(1)
+#define FMU_BLK_WAKERQ U(2)
+#define FMU_BLK_ITS0 U(4)
+#define FMU_BLK_ITS1 U(5)
+#define FMU_BLK_ITS2 U(6)
+#define FMU_BLK_ITS3 U(7)
+#define FMU_BLK_ITS4 U(8)
+#define FMU_BLK_ITS5 U(9)
+#define FMU_BLK_ITS6 U(10)
+#define FMU_BLK_ITS7 U(11)
+#define FMU_BLK_PPI0 U(12)
+#define FMU_BLK_PPI1 U(13)
+#define FMU_BLK_PPI2 U(14)
+#define FMU_BLK_PPI3 U(15)
+#define FMU_BLK_PPI4 U(16)
+#define FMU_BLK_PPI5 U(17)
+#define FMU_BLK_PPI6 U(18)
+#define FMU_BLK_PPI7 U(19)
+#define FMU_BLK_PPI8 U(20)
+#define FMU_BLK_PPI9 U(21)
+#define FMU_BLK_PPI10 U(22)
+#define FMU_BLK_PPI11 U(23)
+#define FMU_BLK_PPI12 U(24)
+#define FMU_BLK_PPI13 U(25)
+#define FMU_BLK_PPI14 U(26)
+#define FMU_BLK_PPI15 U(27)
+#define FMU_BLK_PPI16 U(28)
+#define FMU_BLK_PPI17 U(29)
+#define FMU_BLK_PPI18 U(30)
+#define FMU_BLK_PPI19 U(31)
+#define FMU_BLK_PPI20 U(32)
+#define FMU_BLK_PPI21 U(33)
+#define FMU_BLK_PPI22 U(34)
+#define FMU_BLK_PPI23 U(35)
+#define FMU_BLK_PPI24 U(36)
+#define FMU_BLK_PPI25 U(37)
+#define FMU_BLK_PPI26 U(38)
+#define FMU_BLK_PPI27 U(39)
+#define FMU_BLK_PPI28 U(40)
+#define FMU_BLK_PPI29 U(41)
+#define FMU_BLK_PPI30 U(42)
+#define FMU_BLK_PPI31 U(43)
+#define FMU_BLK_PRESENT_MASK U(0xFFFFFFFFFFF)
+
+/* Safety Mechamism limit */
+#define FMU_SMID_GICD_MAX U(33)
+#define FMU_SMID_SPICOL_MAX U(5)
+#define FMU_SMID_WAKERQ_MAX U(2)
+#define FMU_SMID_ITS_MAX U(14)
+#define FMU_SMID_PPI_MAX U(12)
+
+/* MBIST Safety Mechanism ID */
+#define GICD_MBIST_REQ_ERROR U(23)
+#define GICD_FMU_CLKGATE_ERROR U(33)
+#define PPI_MBIST_REQ_ERROR U(10)
+#define PPI_FMU_CLKGATE_ERROR U(12)
+#define ITS_MBIST_REQ_ERROR U(13)
+#define ITS_FMU_CLKGATE_ERROR U(14)
+
+/* ERRSTATUS bits */
+#define FMU_ERRSTATUS_V_BIT BIT(30)
+#define FMU_ERRSTATUS_UE_BIT BIT(29)
+#define FMU_ERRSTATUS_OV_BIT BIT(27)
+#define FMU_ERRSTATUS_CE_BITS (BIT(25) | BIT(24))
+#define FMU_ERRSTATUS_CLEAR (FMU_ERRSTATUS_V_BIT | FMU_ERRSTATUS_UE_BIT | \
+ FMU_ERRSTATUS_OV_BIT | FMU_ERRSTATUS_CE_BITS)
+
+/* PINGCTLR constants */
+#define FMU_PINGCTLR_INTDIFF_SHIFT U(16)
+#define FMU_PINGCTLR_TIMEOUTVAL_SHIFT U(4)
+#define FMU_PINGCTLR_EN_BIT BIT(0)
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+
+/*******************************************************************************
+ * GIC600 FMU EL3 driver API
+ ******************************************************************************/
+uint64_t gic_fmu_read_errfr(uintptr_t base, unsigned int n);
+uint64_t gic_fmu_read_errctlr(uintptr_t base, unsigned int n);
+uint64_t gic_fmu_read_errstatus(uintptr_t base, unsigned int n);
+uint64_t gic_fmu_read_errgsr(uintptr_t base);
+uint32_t gic_fmu_read_pingctlr(uintptr_t base);
+uint32_t gic_fmu_read_pingnow(uintptr_t base);
+uint64_t gic_fmu_read_pingmask(uintptr_t base);
+uint32_t gic_fmu_read_status(uintptr_t base);
+uint32_t gic_fmu_read_erridr(uintptr_t base);
+void gic_fmu_write_errctlr(uintptr_t base, unsigned int n, uint64_t val);
+void gic_fmu_write_errstatus(uintptr_t base, unsigned int n, uint64_t val);
+void gic_fmu_write_pingctlr(uintptr_t base, uint32_t val);
+void gic_fmu_write_pingnow(uintptr_t base, uint32_t val);
+void gic_fmu_write_smen(uintptr_t base, uint32_t val);
+void gic_fmu_write_sminjerr(uintptr_t base, uint32_t val);
+void gic_fmu_write_pingmask(uintptr_t base, uint64_t val);
+
+void gic600_fmu_init(uint64_t base, uint64_t blk_present_mask, bool errctlr_ce_en, bool errctlr_ue_en);
+void gic600_fmu_enable_ping(uint64_t base, uint64_t blk_present_mask,
+ unsigned int timeout_val, unsigned int interval_diff);
+void gic600_fmu_print_sm_info(uint64_t base, unsigned int blk, unsigned int smid);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* GIC600AE_FMU_H */
diff --git a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
index 62ab27c..08d3c32 100644
--- a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
@@ -4,6 +4,8 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <lib/libc/cdefs.h>
+
/dts-v1/;
/ {
@@ -74,6 +76,10 @@
secure-partitions {
compatible = "arm,sp";
+
+#ifdef ARM_BL2_SP_LIST_DTS
+ #include __XSTRING(ARM_BL2_SP_LIST_DTS)
+#else
#ifdef OPTEE_SP_FW_CONFIG
op-tee {
uuid = "486178e0-e7f8-11e3-bc5e-0002a5d5c51b";
@@ -104,6 +110,7 @@
owner = "Plat";
};
#endif
+#endif /* ARM_BL2_SP_LIST_DTS */
};
#if COT_DESC_IN_DTB
diff --git a/plat/arm/board/tc/fdts/tc_fw_config.dts b/plat/arm/board/tc/fdts/tc_fw_config.dts
index 4b6abd4..a84c7f8 100644
--- a/plat/arm/board/tc/fdts/tc_fw_config.dts
+++ b/plat/arm/board/tc/fdts/tc_fw_config.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -26,7 +26,7 @@
hw-config {
load-address = <0x0 0x83000000>;
- max-size = <0x01000000>;
+ max-size = <0x8000>;
id = <HW_CONFIG_ID>;
};
};
diff --git a/plat/arm/board/tc/include/platform_def.h b/plat/arm/board/tc/include/platform_def.h
index c8edd2f..ccabced 100644
--- a/plat/arm/board/tc/include/platform_def.h
+++ b/plat/arm/board/tc/include/platform_def.h
@@ -55,6 +55,14 @@
TC_TZC_DRAM1_BASE, \
TC_TZC_DRAM1_SIZE, \
MT_MEMORY | MT_RW | MT_SECURE)
+
+#define PLAT_HW_CONFIG_DTB_BASE ULL(0x83000000)
+#define PLAT_HW_CONFIG_DTB_SIZE ULL(0x8000)
+
+#define PLAT_DTB_DRAM_NS MAP_REGION_FLAT( \
+ PLAT_HW_CONFIG_DTB_BASE, \
+ PLAT_HW_CONFIG_DTB_SIZE, \
+ MT_MEMORY | MT_RO | MT_NS)
/*
* Max size of SPMC is 2MB for tc. With SPMD enabled this value corresponds to
* max size of BL32 image.
@@ -122,7 +130,7 @@
* calculated using the current BL31 PROGBITS debug size plus the sizes of
* BL2 and BL1-RW
*/
-#define PLAT_ARM_MAX_BL31_SIZE 0x3B000
+#define PLAT_ARM_MAX_BL31_SIZE 0x3F000
/*
* Size of cacheable stacks
diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk
index 8db764c..7ebf639 100644
--- a/plat/arm/board/tc/platform.mk
+++ b/plat/arm/board/tc/platform.mk
@@ -31,6 +31,9 @@
# GIC-600 configuration
GICV3_SUPPORT_GIC600 := 1
+# Enable SVE
+ENABLE_SVE_FOR_NS := 1
+ENABLE_SVE_FOR_SWD := 1
# Include GICv3 driver files
include drivers/arm/gic/v3/gicv3.mk
@@ -77,6 +80,7 @@
BL2_SOURCES += ${TC_BASE}/tc_security.c \
${TC_BASE}/tc_err.c \
${TC_BASE}/tc_trusted_boot.c \
+ ${TC_BASE}/tc_bl2_setup.c \
lib/utils/mem_region.c \
drivers/arm/tzc/tzc400.c \
plat/arm/common/arm_tzc400.c \
@@ -87,6 +91,9 @@
${ENT_GIC_SOURCES} \
${TC_BASE}/tc_bl31_setup.c \
${TC_BASE}/tc_topology.c \
+ common/fdt_wrappers.c \
+ lib/fconf/fconf.c \
+ lib/fconf/fconf_dyn_cfg_getter.c \
drivers/cfi/v2m/v2m_flash.c \
lib/utils/mem_region.c \
plat/arm/common/arm_nor_psci_mem_protect.c
diff --git a/plat/arm/board/tc/tc_bl2_setup.c b/plat/arm/board/tc/tc_bl2_setup.c
new file mode 100644
index 0000000..74ef569
--- /dev/null
+++ b/plat/arm/board/tc/tc_bl2_setup.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+
+#include <plat/arm/common/plat_arm.h>
+
+/*******************************************************************************
+ * This function returns the list of executable images
+ ******************************************************************************/
+struct bl_params *plat_get_next_bl_params(void)
+{
+ struct bl_params *arm_bl_params = arm_get_next_bl_params();
+
+ const struct dyn_cfg_dtb_info_t *fw_config_info;
+ bl_mem_params_node_t *param_node;
+ uintptr_t fw_config_base = 0U;
+ entry_point_info_t *ep_info;
+
+ /* Get BL31 image node */
+ param_node = get_bl_mem_params_node(BL31_IMAGE_ID);
+ assert(param_node != NULL);
+
+ /* Get fw_config load address */
+ fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID);
+ assert(fw_config_info != NULL);
+
+ fw_config_base = fw_config_info->config_addr;
+ assert(fw_config_base != 0U);
+
+ /*
+ * Get the entry point info of BL31 image and override
+ * arg1 of entry point info with fw_config base address
+ */
+ ep_info = ¶m_node->ep_info;
+ ep_info->args.arg1 = (uint32_t)fw_config_base;
+
+ return arm_bl_params;
+}
diff --git a/plat/arm/board/tc/tc_bl31_setup.c b/plat/arm/board/tc/tc_bl31_setup.c
index ecec26c..0523ef8 100644
--- a/plat/arm/board/tc/tc_bl31_setup.c
+++ b/plat/arm/board/tc/tc_bl31_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,6 +13,8 @@
#include <common/debug.h>
#include <drivers/arm/css/css_mhu_doorbell.h>
#include <drivers/arm/css/scmi.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
#include <plat/arm/common/plat_arm.h>
#include <plat/common/platform.h>
@@ -42,6 +44,9 @@
u_register_t arg2, u_register_t arg3)
{
arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
+
+ /* Fill the properties struct with the info from the config dtb */
+ fconf_populate("FW_CONFIG", arg1);
}
void tc_bl31_common_platform_setup(void)
@@ -53,3 +58,16 @@
{
return css_scmi_override_pm_ops(ops);
}
+
+void __init bl31_plat_arch_setup(void)
+{
+ arm_bl31_plat_arch_setup();
+
+ /* HW_CONFIG was also loaded by BL2 */
+ const struct dyn_cfg_dtb_info_t *hw_config_info;
+
+ hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID);
+ assert(hw_config_info != NULL);
+
+ fconf_populate("HW_CONFIG", hw_config_info->config_addr);
+}
diff --git a/plat/arm/board/tc/tc_plat.c b/plat/arm/board/tc/tc_plat.c
index 3863a0a..a9668e1 100644
--- a/plat/arm/board/tc/tc_plat.c
+++ b/plat/arm/board/tc/tc_plat.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -63,6 +63,7 @@
ARM_MAP_SHARED_RAM,
V2M_MAP_IOFPGA,
TC_MAP_DEVICE,
+ PLAT_DTB_DRAM_NS,
#if SPM_MM
ARM_SPM_BUF_EL3_MMAP,
#endif
diff --git a/plat/marvell/armada/a3k/common/a3700_common.mk b/plat/marvell/armada/a3k/common/a3700_common.mk
index 0a89742..238587d 100644
--- a/plat/marvell/armada/a3k/common/a3700_common.mk
+++ b/plat/marvell/armada/a3k/common/a3700_common.mk
@@ -13,7 +13,6 @@
PLAT_COMMON_BASE := $(PLAT_FAMILY_BASE)/common
MARVELL_DRV_BASE := drivers/marvell
MARVELL_COMMON_BASE := $(MARVELL_PLAT_BASE)/common
-HANDLE_EA_EL3_FIRST := 1
include plat/marvell/marvell.mk
@@ -53,7 +52,6 @@
$(PLAT_COMMON_BASE)/dram_win.c \
$(PLAT_COMMON_BASE)/io_addr_dec.c \
$(PLAT_COMMON_BASE)/marvell_plat_config.c \
- $(PLAT_COMMON_BASE)/a3700_ea.c \
$(PLAT_FAMILY_BASE)/$(PLAT)/plat_bl31_setup.c \
$(MARVELL_COMMON_BASE)/marvell_cci.c \
$(MARVELL_COMMON_BASE)/marvell_ddr_info.c \
@@ -63,6 +61,10 @@
$(PLAT_COMMON_BASE)/a3700_sip_svc.c \
$(MARVELL_DRV)
+ifeq ($(HANDLE_EA_EL3_FIRST),1)
+BL31_SOURCES += $(PLAT_COMMON_BASE)/a3700_ea.c
+endif
+
ifeq ($(CM3_SYSTEM_RESET),1)
BL31_SOURCES += $(PLAT_COMMON_BASE)/cm3_system_reset.c
endif
diff --git a/plat/marvell/armada/a3k/common/a3700_ea.c b/plat/marvell/armada/a3k/common/a3700_ea.c
index 3a4f720..4a58fc6 100644
--- a/plat/marvell/armada/a3k/common/a3700_ea.c
+++ b/plat/marvell/armada/a3k/common/a3700_ea.c
@@ -8,14 +8,79 @@
#include <common/debug.h>
#include <arch_helpers.h>
#include <plat/common/platform.h>
+#include <bl31/ea_handle.h>
-#define ADVK_SERROR_SYNDROME 0xbf000002
+#define A53_SERR_INT_AXI_SLVERR_ON_EXTERNAL_ACCESS 0xbf000002
+#if !ENABLE_BACKTRACE
+static const char *get_el_str(unsigned int el)
+{
+ if (el == MODE_EL3) {
+ return "EL3";
+ } else if (el == MODE_EL2) {
+ return "EL2";
+ }
+ return "S-EL1";
+}
+#endif /* !ENABLE_BACKTRACE */
+
+/*
+ * This source file with custom plat_ea_handler function is compiled only when
+ * building TF-A with compile option HANDLE_EA_EL3_FIRST=1
+ */
void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
void *handle, uint64_t flags)
{
- if (syndrome == ADVK_SERROR_SYNDROME)
+ unsigned int level = (unsigned int)GET_EL(read_spsr_el3());
+
+ /*
+ * Asynchronous External Abort with syndrome 0xbf000002 on Cortex A53
+ * core means SError interrupt caused by AXI SLVERR on external access.
+ *
+ * In most cases this indicates a bug in U-Boot or Linux kernel driver
+ * pci-aardvark.c which implements access to A3700 PCIe config space.
+ * Driver does not wait for PCIe PIO transfer completion and try to
+ * start a new PCIe PIO transfer while previous has not finished yet.
+ * A3700 PCIe controller in this case sends SLVERR via AXI which results
+ * in a fatal Asynchronous SError interrupt on Cortex A53 CPU.
+ *
+ * Following patches fix that bug in U-Boot and Linux kernel drivers:
+ * https://source.denx.de/u-boot/u-boot/-/commit/eccbd4ad8e4e182638eafbfb87ac139c04f24a01
+ * https://git.kernel.org/stable/c/f18139966d072dab8e4398c95ce955a9742e04f7
+ *
+ * As a hacky workaround for unpatched U-Boot and Linux kernel drivers
+ * ignore all asynchronous aborts with that syndrome value received on
+ * CPU from level lower than EL3.
+ *
+ * Because these aborts are delivered on CPU asynchronously, they are
+ * imprecise and we cannot check the real reason of abort and neither
+ * who and why sent this abort. We expect that on A3700 it is always
+ * PCIe controller.
+ *
+ * Hence ignoring all aborts with this syndrome value is just a giant
+ * hack that we need only because of bugs in old U-Boot and Linux kernel
+ * versions and because it was decided that TF-A would implement this
+ * hack for U-Boot and Linux kernel it in this way. New patched U-Boot
+ * and kernel versions do not need it anymore.
+ *
+ * Links to discussion about this workaround:
+ * https://lore.kernel.org/linux-pci/20190316161243.29517-1-repk@triplefau.lt/
+ * https://lore.kernel.org/linux-pci/971be151d24312cc533989a64bd454b4@www.loen.fr/
+ * https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/1541
+ */
+ if (level < MODE_EL3 && ea_reason == ERROR_EA_ASYNC &&
+ syndrome == A53_SERR_INT_AXI_SLVERR_ON_EXTERNAL_ACCESS) {
+ ERROR_NL();
+ ERROR("Ignoring Asynchronous External Abort with"
+ " syndrome 0x%llx received on 0x%lx from %s\n",
+ syndrome, read_mpidr_el1(), get_el_str(level));
+ ERROR("SError interrupt: AXI SLVERR on external access\n");
+ ERROR("This indicates a bug in pci-aardvark.c driver\n");
+ ERROR("Please update U-Boot/Linux to the latest version\n");
+ ERROR_NL();
+ console_flush();
return;
+ }
plat_default_ea_handler(ea_reason, syndrome, cookie, handle, flags);
}