Merge changes from topic "rpix-multi-console" into integration

* changes:
  rpi: docs: Update maintainers file to new RPi directory scheme
  rpi: console: Autodetect Mini-UART vs. PL011 configuration
  rpi3: build: Include GPIO driver in all BL stages
  rpi: Allow using PL011 UART for RPi3/RPi4
  rpi3: console: Use same "clock-less" setup scheme as RPi4
  rpi3: gpio: Simplify GPIO setup
diff --git a/.gitreview b/.gitreview
new file mode 100644
index 0000000..36f2548
--- /dev/null
+++ b/.gitreview
@@ -0,0 +1,4 @@
+[gerrit]
+host=review.trustedfirmware.org
+port=29418
+project=TF-A/trusted-firmware-a
diff --git a/Makefile b/Makefile
index 3d5b395..47a544d 100644
--- a/Makefile
+++ b/Makefile
@@ -1000,6 +1000,8 @@
 
 ifeq (${NEED_BL31},yes)
 BL31_SOURCES += ${SPD_SOURCES}
+# Sort BL31 source files to remove duplicates
+BL31_SOURCES := $(sort ${BL31_SOURCES})
 ifneq (${DECRYPTION_SUPPORT},none)
 $(if ${BL31}, $(eval $(call TOOL_ADD_IMG,bl31,--soc-fw,,$(ENCRYPT_BL31))),\
 	$(eval $(call MAKE_BL,31,soc-fw,,$(ENCRYPT_BL31))))
@@ -1013,7 +1015,8 @@
 # build system will call TOOL_ADD_IMG to print a warning message and abort the
 # process. Note that the dependency on BL32 applies to the FIP only.
 ifeq (${NEED_BL32},yes)
-
+# Sort BL32 source files to remove duplicates
+BL32_SOURCES := $(sort ${BL32_SOURCES})
 BUILD_BL32 := $(if $(BL32),,$(if $(BL32_SOURCES),1))
 
 ifneq (${DECRYPTION_SUPPORT},none)
diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S
index e0138ac..5f9f9df 100644
--- a/bl31/bl31.ld.S
+++ b/bl31/bl31.ld.S
@@ -55,6 +55,11 @@
         KEEP(*(rt_svc_descs))
         __RT_SVC_DESCS_END__ = .;
 
+        . = ALIGN(8);
+         __FCONF_POPULATOR_START__ = .;
+        KEEP(*(.fconf_populator))
+         __FCONF_POPULATOR_END__ = .;
+
 #if ENABLE_PMF
         /* Ensure 8-byte alignment for descriptors and ensure inclusion */
         . = ALIGN(8);
@@ -102,6 +107,11 @@
         KEEP(*(rt_svc_descs))
         __RT_SVC_DESCS_END__ = .;
 
+        . = ALIGN(8);
+         __FCONF_POPULATOR_START__ = .;
+        KEEP(*(.fconf_populator))
+         __FCONF_POPULATOR_END__ = .;
+
 #if ENABLE_PMF
         /* Ensure 8-byte alignment for descriptors and ensure inclusion */
         . = ALIGN(8);
diff --git a/bl32/sp_min/sp_min.ld.S b/bl32/sp_min/sp_min.ld.S
index 3b1ca1b..a90a805 100644
--- a/bl32/sp_min/sp_min.ld.S
+++ b/bl32/sp_min/sp_min.ld.S
@@ -56,6 +56,11 @@
         KEEP(*(rt_svc_descs))
         __RT_SVC_DESCS_END__ = .;
 
+        . = ALIGN(8);
+         __FCONF_POPULATOR_START__ = .;
+        KEEP(*(.fconf_populator))
+         __FCONF_POPULATOR_END__ = .;
+
 #if ENABLE_PMF
         /* Ensure 4-byte alignment for descriptors and ensure inclusion */
         . = ALIGN(4);
@@ -93,6 +98,11 @@
         KEEP(*(rt_svc_descs))
         __RT_SVC_DESCS_END__ = .;
 
+        . = ALIGN(8);
+         __FCONF_POPULATOR_START__ = .;
+        KEEP(*(.fconf_populator))
+         __FCONF_POPULATOR_END__ = .;
+
         /*
          * Ensure 4-byte alignment for cpu_ops so that its fields are also
          * aligned. Also ensure cpu_ops inclusion.
diff --git a/docs/change-log-upcoming.rst b/docs/change-log-upcoming.rst
index 15f39de..f86280f 100644
--- a/docs/change-log-upcoming.rst
+++ b/docs/change-log-upcoming.rst
@@ -24,6 +24,8 @@
 
 - Build System
    - Add support for documentation build as a target in Makefile
+   - Add ``COT`` build option to select the chain of trust to use when the
+     Trusted Boot feature is enabled (default: ``tbbr``).
 
 - CPU Support
    - Example: "cortex-a55: Workaround for erratum 1221012"
@@ -40,6 +42,7 @@
 
 - Platforms
    - Example: "arm/common: Introduce wrapper functions to setup secure watchdog"
+   - plat/arm: Add support for the new `dualroot` chain of trust.
 
 - PSCI
    - Example: "Adding new optional PSCI hook ``pwr_domain_on_finish_late``"
@@ -47,6 +50,7 @@
 - Security
    - Example: "UBSAN support and handlers"
    - Add support for optional firmware encryption feature (experimental).
+   - Introduce a new `dualroot` chain of trust.
 
 - Tools
    - Example: "fiptool: Add support to build fiptool on Windows."
diff --git a/docs/components/fconf.rst b/docs/components/fconf.rst
index cec3ceb..3856600 100644
--- a/docs/components/fconf.rst
+++ b/docs/components/fconf.rst
@@ -28,29 +28,45 @@
 - (|TBBR|) Chain of Trust data: tbbr.cot.trusted_boot_fw_cert
 - (|TBBR|) dynamic configuration info: tbbr.dyn_config.disable_auth
 - Arm io policies: arm.io_policies.bl2_image
+- GICv3 properties: hw_config.gicv3_config.gicr_base
 
 Properties can be accessed with the ``FCONF_GET_PROPERTY(a,b,property)`` macro.
 
 Defining properties
 ~~~~~~~~~~~~~~~~~~~
 
-Properties composing the |FCONF| have to be stored in C structures. If another
-backing store is wanted to be used, the platform has to provide a ``populate()``
-function to fill the corresponding C structure.
+Properties composing the |FCONF| have to be stored in C structures. If
+properties originate from a different backend source such as a device tree,
+then the platform has to provide a ``populate()`` function which essentially
+captures the property and stores them into a corresponding |FCONF| based C
+structure.
 
-The ``populate()`` function must be registered to the |FCONF| framework with
-the ``FCONF_REGISTER_POPULATOR()`` macro. This ensures that the function would
-be called inside the generic ``fconf_populate()`` function during
+Such a ``populate()`` function is usually platform specific and is associated
+with a specific backend source. For example, a populator function which
+captures the hardware topology of the platform from the HW_CONFIG device tree.
+Hence each ``populate()`` function must be registered with a specific
+``config_type`` identifier. It broadly represents a logical grouping of
+configuration properties which is usually a device tree file.
+
+Example:
+ - TB_FW: properties related to trusted firmware such as IO policies,
+   base address of other DTBs, mbedtls heap info etc.
+ - HW_CONFIG: properties related to hardware configuration of the SoC
+   such as topology, GIC controller, PSCI hooks, CPU ID etc.
+
+Hence the ``populate()`` callback must be registered to the (|FCONF|) framework
+with the ``FCONF_REGISTER_POPULATOR()`` macro. This ensures that the function
+would be called inside the generic ``fconf_populate()`` function during
 initialization.
 
 ::
 
-    int fconf_populate_tbbr_dyn_config(uintptr_t config)
+    int fconf_populate_topology(uintptr_t config)
     {
-        /* read dtb and fill tbbr_dyn_config struct */
+        /* read hw config dtb and fill soc_topology struct */
     }
 
-    FCONF_REGISTER_POPULATOR(fconf_populate_tbbr_dyn_config);
+    FCONF_REGISTER_POPULATOR(HW_CONFIG, topology, fconf_populate_topology);
 
 Then, a wrapper has to be provided to match the ``FCONF_GET_PROPERTY()`` macro:
 
@@ -60,7 +76,7 @@
     #define FCONF_GET_PROPERTY(a,b,property)	a##__##b##_getter(property)
 
     /* my specific getter */
-    #define tbbr__dyn_config_getter(id)	tbbr_dyn_config.id
+    #define hw_config__topology_getter(prop) soc_topology.prop
 
 This second level wrapper can be used to remap the ``FCONF_GET_PROPERTY()`` to
 anything appropriate: structure, array, function, etc..
@@ -80,6 +96,33 @@
 Once a valid device tree is available, the ``fconf_populate(config)`` function
 can be used to fill the C data structure with the data from the config |DTB|.
 This function will call all the ``populate()`` callbacks which have been
-registered with ``FCONF_REGISTER_POPULATOR()``.
+registered with ``FCONF_REGISTER_POPULATOR()`` as described above.
 
 .. uml:: ../resources/diagrams/plantuml/fconf_bl2_populate.puml
+
+Namespace guidance
+~~~~~~~~~~~~~~~~~~
+
+As mentioned above, properties are logically grouped around namespaces and
+sub-namespaces. The following concepts should be considered when adding new
+properties/namespaces.
+The framework differentiates two types of properties:
+ - Properties used inside common code.
+ - Properties used inside platform specific code.
+
+The first category applies to properties being part of the firmware and shared
+across multiple platforms. They should be globally accessible and defined
+inside the ``lib/fconf`` directory. The namespace must be chosen to reflect the
+feature/data abstracted.
+Example:
+ - |TBBR| related properties: tbbr.cot.bl2_id
+ - Dynamic configuration information: dyn_cfg.dtb_info.hw_config_id
+
+The second category should represent the majority of the properties defined
+within the framework: Platform specific properties. They must be accessed only
+within the platform API and are defined only inside the platform scope. The
+namespace must contain the platform name under which the properties defined
+belong.
+Example:
+ - Arm io framework: arm.io_policies.bl31_id
+
diff --git a/docs/design/firmware-design.rst b/docs/design/firmware-design.rst
index 8297dc7..8e9dc38 100644
--- a/docs/design/firmware-design.rst
+++ b/docs/design/firmware-design.rst
@@ -1859,7 +1859,7 @@
                |   BL2    |  <<<<<<<<<<<<<  |                |
                |----------|  <<<<<<<<<<<<<  |----------------|
                | SCP_BL2  |  <<<<<<<<<<<<<  | BL31 PROGBITS  |
-               |----------|  <<<<<<<<<<<<<  |----------------|
+               |          |  <<<<<<<<<<<<<  |----------------|
                |          |  <<<<<<<<<<<<<  |     BL32       |
                |          |                 +----------------+
                |          |
@@ -1896,7 +1896,7 @@
                |   BL2    |  <<<<<<<<<<<<<  |                |
                |----------|  <<<<<<<<<<<<<  |----------------|
                | SCP_BL2  |  <<<<<<<<<<<<<  | BL31 PROGBITS  |
-               |----------|                 +----------------+
+               |          |                 +----------------+
     0x04001000 +----------+
                |   MHU    |
     0x04000000 +----------+
diff --git a/docs/design/trusted-board-boot-build.rst b/docs/design/trusted-board-boot-build.rst
index f5c8bc9..dd61b61 100644
--- a/docs/design/trusted-board-boot-build.rst
+++ b/docs/design/trusted-board-boot-build.rst
@@ -32,25 +32,28 @@
    -  ``TRUSTED_BOARD_BOOT=1``
    -  ``GENERATE_COT=1``
 
+   By default, this will use the Chain of Trust described in the TBBR-client
+   document. To select a different one, use the ``COT`` build option.
+
    In the case of Arm platforms, the location of the ROTPK hash must also be
    specified at build time. The following locations are currently supported (see
    ``ARM_ROTPK_LOCATION`` build option):
 
    -  ``ARM_ROTPK_LOCATION=regs``: the ROTPK hash is obtained from the Trusted
-      root-key storage registers present in the platform. On Juno, this
+      root-key storage registers present in the platform. On Juno, these
       registers are read-only. On FVP Base and Cortex models, the registers
-      are read-only, but the value can be specified using the command line
+      are also read-only, but the value can be specified using the command line
       option ``bp.trusted_key_storage.public_key`` when launching the model.
       On Juno board, the default value corresponds to an ECDSA-SECP256R1 public
       key hash, whose private part is not currently available.
 
    -  ``ARM_ROTPK_LOCATION=devel_rsa``: use the default hash located in
-      plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin. Enforce generation
-      of the new hash if ROT_KEY is specified.
+      ``plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin``. Enforce
+      generation of the new hash if ``ROT_KEY`` is specified.
 
    -  ``ARM_ROTPK_LOCATION=devel_ecdsa``: use the default hash located in
-      plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin. Enforce generation
-      of the new hash if ROT_KEY is specified.
+      ``plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin``. Enforce
+      generation of the new hash if ``ROT_KEY`` is specified.
 
    Example of command line using RSA development keys:
 
@@ -64,9 +67,8 @@
        all fip
 
    The result of this build will be the bl1.bin and the fip.bin binaries. This
-   FIP will include the certificates corresponding to the Chain of Trust
-   described in the TBBR-client document. These certificates can also be found
-   in the output build directory.
+   FIP will include the certificates corresponding to the selected Chain of
+   Trust. These certificates can also be found in the output build directory.
 
 #. The optional FWU_FIP contains any additional images to be loaded from
    Non-Volatile storage during the :ref:`Firmware Update (FWU)` process. To build the
@@ -102,8 +104,8 @@
 
    The result of this build will be bl1.bin, fip.bin and fwu_fip.bin binaries.
    Both the FIP and FWU_FIP will include the certificates corresponding to the
-   Chain of Trust described in the TBBR-client document. These certificates
-   can also be found in the output build directory.
+   selected Chain of Trust. These certificates can also be found in the output
+   build directory.
 
 --------------
 
diff --git a/docs/design/trusted-board-boot.rst b/docs/design/trusted-board-boot.rst
index 4802c97..96cf24c 100644
--- a/docs/design/trusted-board-boot.rst
+++ b/docs/design/trusted-board-boot.rst
@@ -19,7 +19,9 @@
 the Arm development platforms, these components are:
 
 -  A SHA-256 hash of the Root of Trust Public Key (ROTPK). It is stored in the
-   trusted root-key storage registers.
+   trusted root-key storage registers. Alternatively, a development ROTPK might
+   be used and its hash embedded into the BL1 and BL2 images (only for
+   development purposes).
 
 -  The BL1 image, on the assumption that it resides in ROM so cannot be
    tampered with.
@@ -32,17 +34,17 @@
 In the TBB CoT all certificates are self-signed. There is no need for a
 Certificate Authority (CA) because the CoT is not established by verifying the
 validity of a certificate's issuer but by the content of the certificate
-extensions. To sign the certificates, the PKCS#1 SHA-256 with RSA Encryption
-signature scheme is used with a RSA key length of 2048 bits. Future version of
-TF-A will support additional cryptographic algorithms.
+extensions. To sign the certificates, different signature schemes are available,
+please refer to the :ref:`Build Options` for more details.
 
 The certificates are categorised as "Key" and "Content" certificates. Key
 certificates are used to verify public keys which have been used to sign content
 certificates. Content certificates are used to store the hash of a boot loader
 image. An image can be authenticated by calculating its hash and matching it
-with the hash extracted from the content certificate. The SHA-256 function is
-used to calculate all hashes. The public keys and hashes are included as
-non-standard extension fields in the `X.509 v3`_ certificates.
+with the hash extracted from the content certificate. Various hash algorithms
+are supported to calculate all hashes, please refer to the :ref:`Build Options`
+for more details.. The public keys and hashes are included as non-standard
+extension fields in the `X.509 v3`_ certificates.
 
 The keys used to establish the CoT are:
 
@@ -63,10 +65,10 @@
    non secure world image (BL33). The public part is stored in one of the
    extension fields in the trusted world certificate.
 
--  **BL3-X keys**
+-  **BL3X keys**
 
    For each of SCP_BL2, BL31, BL32 and BL33, the private part is used to
-   sign the content certificate for the BL3-X image. The public part is stored
+   sign the content certificate for the BL3X image. The public part is stored
    in one of the extension fields in the corresponding key certificate.
 
 The following images are included in the CoT:
@@ -219,8 +221,7 @@
 generated by the tool in case they are not provided. The certificates are then
 passed as inputs to the ``fiptool`` utility for creating the FIP.
 
-The certificates are also stored individually in the in the output build
-directory.
+The certificates are also stored individually in the output build directory.
 
 The tool resides in the ``tools/cert_create`` directory. It uses the OpenSSL SSL
 library version to generate the X.509 certificates. The specific version of the
@@ -259,7 +260,7 @@
 
 --------------
 
-*Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved.*
 
 .. _X.509 v3: https://tools.ietf.org/rfc/rfc5280.txt
 .. _Trusted Board Boot Requirements (TBBR): https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a
diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst
index d634d2e7..d6572f5 100644
--- a/docs/getting_started/porting-guide.rst
+++ b/docs/getting_started/porting-guide.rst
@@ -1116,6 +1116,35 @@
 the log output. The implementation should be robust to future changes that
 increase the number of log levels.
 
+Function : plat_get_soc_version()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : void
+    Return   : int32_t
+
+This function returns soc version which mainly consist of below fields
+
+::
+
+    soc_version[30:24] = JEP-106 continuation code for the SiP
+    soc_version[23:16] = JEP-106 identification code with parity bit for the SiP
+
+Function : plat_get_soc_revision()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : void
+    Return   : int32_t
+
+This function returns soc revision in below format
+
+::
+
+    soc_revision[0:30] = SOC revision of specific SOC
+
 Modifications specific to a Boot Loader stage
 ---------------------------------------------
 
diff --git a/fdts/fvp-base-gicv2-psci-aarch32.dts b/fdts/fvp-base-gicv2-psci-aarch32.dts
index e71a395..fcef927 100644
--- a/fdts/fvp-base-gicv2-psci-aarch32.dts
+++ b/fdts/fvp-base-gicv2-psci-aarch32.dts
@@ -35,6 +35,7 @@
 		cpu_on = <0x84000003>;
 		sys_poweroff = <0x84000008>;
 		sys_reset = <0x84000009>;
+		max-pwr-lvl = <2>;
 	};
 
 	cpus {
diff --git a/fdts/fvp-base-gicv2-psci.dts b/fdts/fvp-base-gicv2-psci.dts
index c9c9d95..1e0a81c 100644
--- a/fdts/fvp-base-gicv2-psci.dts
+++ b/fdts/fvp-base-gicv2-psci.dts
@@ -35,6 +35,7 @@
 		cpu_on = <0xc4000003>;
 		sys_poweroff = <0x84000008>;
 		sys_reset = <0x84000009>;
+		max-pwr-lvl = <2>;
 	};
 
 	cpus {
diff --git a/fdts/fvp-base-gicv3-psci-aarch32-common.dtsi b/fdts/fvp-base-gicv3-psci-aarch32-common.dtsi
index f9809db..a28a4a5 100644
--- a/fdts/fvp-base-gicv3-psci-aarch32-common.dtsi
+++ b/fdts/fvp-base-gicv3-psci-aarch32-common.dtsi
@@ -33,6 +33,7 @@
 		cpu_on = <0x84000003>;
 		sys_poweroff = <0x84000008>;
 		sys_reset = <0x84000009>;
+		max-pwr-lvl = <2>;
 	};
 
 	cpus {
diff --git a/fdts/fvp-base-gicv3-psci-common.dtsi b/fdts/fvp-base-gicv3-psci-common.dtsi
index 5b0470d..fb73f60 100644
--- a/fdts/fvp-base-gicv3-psci-common.dtsi
+++ b/fdts/fvp-base-gicv3-psci-common.dtsi
@@ -33,6 +33,7 @@
 		cpu_on = <0xc4000003>;
 		sys_poweroff = <0x84000008>;
 		sys_reset = <0x84000009>;
+		max-pwr-lvl = <2>;
 	};
 
 	cpus {
diff --git a/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi b/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi
index f3f7684..4bed36f 100644
--- a/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi
+++ b/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi
@@ -11,6 +11,9 @@
 /* DynamIQ based designs have upto 8 CPUs in each cluster */
 
 &CPU_MAP {
+	/delete-node/ cluster0;
+	/delete-node/ cluster1;
+
 	cluster0 {
 		core0 {
 			cpu = <&CPU0>;
diff --git a/fdts/fvp-foundation-gicv2-psci.dts b/fdts/fvp-foundation-gicv2-psci.dts
index b6da905..3a204cb 100644
--- a/fdts/fvp-foundation-gicv2-psci.dts
+++ b/fdts/fvp-foundation-gicv2-psci.dts
@@ -35,6 +35,7 @@
 		cpu_on = <0xc4000003>;
 		sys_poweroff = <0x84000008>;
 		sys_reset = <0x84000009>;
+		max-pwr-lvl = <2>;
 	};
 
 	cpus {
diff --git a/fdts/fvp-foundation-gicv3-psci.dts b/fdts/fvp-foundation-gicv3-psci.dts
index 81071e2..d85305a 100644
--- a/fdts/fvp-foundation-gicv3-psci.dts
+++ b/fdts/fvp-foundation-gicv3-psci.dts
@@ -35,6 +35,7 @@
 		cpu_on = <0xc4000003>;
 		sys_poweroff = <0x84000008>;
 		sys_reset = <0x84000009>;
+		max-pwr-lvl = <2>;
 	};
 
 	cpus {
diff --git a/include/arch/aarch32/asm_macros.S b/include/arch/aarch32/asm_macros.S
index ea1636e..f75da0c 100644
--- a/include/arch/aarch32/asm_macros.S
+++ b/include/arch/aarch32/asm_macros.S
@@ -108,11 +108,16 @@
 #else
 	/*
 	 * Macro for mitigating against speculative execution beyond ERET.
+	 * If possible use Speculation Barrier instruction defined in ARMv8.5
 	 */
 	.macro exception_return
 	eret
+#if ARM_ARCH_AT_LEAST(8, 5)
+	sb
+#else
 	dsb	nsh
 	isb
+#endif
 	.endm
 #endif
 
diff --git a/include/arch/aarch64/asm_macros.S b/include/arch/aarch64/asm_macros.S
index a7d5a3d..cbb9f0b 100644
--- a/include/arch/aarch64/asm_macros.S
+++ b/include/arch/aarch64/asm_macros.S
@@ -220,11 +220,16 @@
 
 	/*
 	 * Macro for mitigating against speculative execution beyond ERET.
+	 * If possible use Speculation Barrier instruction defined in ARMv8.5
 	 */
 	.macro exception_return
 	eret
-	dsb nsh
+#if ARM_ARCH_AT_LEAST(8, 5)
+	sb
+#else
+	dsb	nsh
 	isb
+#endif
 	.endm
 
 #endif /* ASM_MACROS_S */
diff --git a/include/bl32/payloads/tlk.h b/include/bl32/payloads/tlk.h
index ce8e3e8..fe6f352 100644
--- a/include/bl32/payloads/tlk.h
+++ b/include/bl32/payloads/tlk.h
@@ -27,6 +27,7 @@
 #define TLK_SYSTEM_SUSPEND	TLK_TOS_YIELD_FID(0xE001)
 #define TLK_SYSTEM_RESUME	TLK_TOS_YIELD_FID(0xE002)
 #define TLK_SYSTEM_OFF		TLK_TOS_YIELD_FID(0xE003)
+#define TLK_IRQ_FIRED		TLK_TOS_YIELD_FID(0xE004)
 
 /*
  * SMC function IDs that TLK uses to signal various forms of completions
@@ -39,6 +40,7 @@
 #define TLK_SUSPEND_DONE	(0x32000005 | (ULL(1) << 31))
 #define TLK_RESUME_DONE		(0x32000006 | (ULL(1) << 31))
 #define TLK_SYSTEM_OFF_DONE	(0x32000007 | (ULL(1) << 31))
+#define TLK_IRQ_DONE		(0x32000008 | (ULL(1) << 31))
 
 /*
  * Trusted Application specific function IDs
diff --git a/include/lib/fconf/fconf.h b/include/lib/fconf/fconf.h
index 0401e5c..09d2b59 100644
--- a/include/lib/fconf/fconf.h
+++ b/include/lib/fconf/fconf.h
@@ -12,9 +12,16 @@
 /* Public API */
 #define FCONF_GET_PROPERTY(a, b, c)	a##__##b##_getter(c)
 
-#define FCONF_REGISTER_POPULATOR(name, callback)				\
+/*
+ * This macro takes three arguments:
+ *   config:	Configuration identifier
+ *   name:	property namespace
+ *   callback:	populate() function
+ */
+#define FCONF_REGISTER_POPULATOR(config, name, callback)			\
 	__attribute__((used, section(".fconf_populator")))			\
 	const struct fconf_populator (name##__populator) = {			\
+		.config_type = (#config),					\
 		.info = (#name),						\
 		.populate = (callback)						\
 	};
@@ -27,6 +34,7 @@
  */
 struct fconf_populator {
 	/* Description of the data loaded by the callback */
+	const char *config_type;
 	const char *info;
 
 	/* Callback used by fconf_populate function with a provided config dtb.
@@ -45,7 +53,7 @@
  *
  *  Panic on error.
  */
-void fconf_populate(uintptr_t config);
+void fconf_populate(const char *config_type, uintptr_t config);
 
 /* FCONF specific getter */
 #define fconf__dtb_getter(prop)	fconf_dtb_info.prop
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index babde41..a84047a 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -148,6 +148,12 @@
 #define ARM_ROTPK_DEVEL_RSA_ID		2
 #define ARM_ROTPK_DEVEL_ECDSA_ID	3
 
+/* Defines used to retrieve ARM SOC revision */
+#define ARM_SOC_CONTINUATION_CODE	U(0x4)
+#define ARM_SOC_IDENTIFICATION_CODE	U(0x3B)
+#define ARM_SOC_CONTINUATION_SHIFT	U(24)
+#define ARM_SOC_IDENTIFICATION_SHIFT	U(16)
+
 /* IO storage utility functions */
 int arm_io_setup(void);
 
@@ -222,6 +228,7 @@
 void arm_sp_min_early_platform_setup(void *from_bl2, uintptr_t tos_fw_config,
 				uintptr_t hw_config, void *plat_params_from_bl2);
 void arm_sp_min_plat_runtime_setup(void);
+void arm_sp_min_plat_arch_setup(void);
 
 /* FIP TOC validity check */
 bool arm_io_is_toc_valid(void);
@@ -322,4 +329,7 @@
 void plat_arm_secure_wdt_start(void);
 void plat_arm_secure_wdt_stop(void);
 
+/* Get SOC-ID of ARM platform */
+uint32_t plat_arm_get_soc_id(void);
+
 #endif /* PLAT_ARM_H */
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index 5b5ebb9..e4431d2 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -322,4 +322,14 @@
  */
 unsigned int platform_core_pos_helper(unsigned long mpidr);
 
+/*
+ * Optional function to get SOC version
+ */
+int32_t plat_get_soc_version(void);
+
+/*
+ * Optional function to get SOC revision
+ */
+int32_t plat_get_soc_revision(void);
+
 #endif /* PLATFORM_H */
diff --git a/include/services/arm_arch_svc.h b/include/services/arm_arch_svc.h
index 1cb2038..5bbd8bb 100644
--- a/include/services/arm_arch_svc.h
+++ b/include/services/arm_arch_svc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,7 +9,11 @@
 
 #define SMCCC_VERSION			U(0x80000000)
 #define SMCCC_ARCH_FEATURES		U(0x80000001)
+#define SMCCC_ARCH_SOC_ID		U(0x80000002)
 #define SMCCC_ARCH_WORKAROUND_1		U(0x80008000)
 #define SMCCC_ARCH_WORKAROUND_2		U(0x80007FFF)
 
+#define SMCCC_GET_SOC_VERSION		U(0)
+#define SMCCC_GET_SOC_REVISION		U(1)
+
 #endif /* ARM_ARCH_SVC_H */
diff --git a/include/services/spm_core_manifest.h b/include/services/spm_core_manifest.h
index 7874882..71e6cfb 100644
--- a/include/services/spm_core_manifest.h
+++ b/include/services/spm_core_manifest.h
@@ -43,6 +43,11 @@
 	 */
 	uint32_t binary_size;
 
+	/*
+	 * ID of the SPMD (mandatory)
+	 */
+	uint16_t spmc_id;
+
 } spmc_manifest_sect_attribute_t;
 
 #endif /* SPMC_MANIFEST_H */
diff --git a/lib/fconf/fconf.c b/lib/fconf/fconf.c
index a6da56b..9ce4635 100644
--- a/lib/fconf/fconf.c
+++ b/lib/fconf/fconf.c
@@ -53,17 +53,17 @@
 	INFO("FCONF: FW_CONFIG loaded at address = 0x%lx\n", arm_tb_fw_info.image_base);
 }
 
-void fconf_populate(uintptr_t config)
+void fconf_populate(const char *config_type, uintptr_t config)
 {
 	assert(config != 0UL);
 
 	/* Check if the pointer to DTB is correct */
 	if (fdt_check_header((void *)config) != 0) {
-		ERROR("FCONF: Invalid DTB file passed for FW_CONFIG\n");
+		ERROR("FCONF: Invalid DTB file passed for %s\n", config_type);
 		panic();
 	}
 
-	INFO("FCONF: Reading firmware configuration file from: 0x%lx\n", config);
+	INFO("FCONF: Reading %s firmware configuration file from: 0x%lx\n", config_type, config);
 
 	/* Go through all registered populate functions */
 	IMPORT_SYM(struct fconf_populator *, __FCONF_POPULATOR_START__, start);
@@ -73,10 +73,12 @@
 	for (populator = start; populator != end; populator++) {
 		assert((populator->info != NULL) && (populator->populate != NULL));
 
-		INFO("FCONF: Reading firmware configuration information for: %s\n", populator->info);
-		if (populator->populate(config) != 0) {
-			/* TODO: handle property miss */
-			panic();
+		if (strcmp(populator->config_type, config_type) == 0) {
+			INFO("FCONF: Reading firmware configuration information for: %s\n", populator->info);
+			if (populator->populate(config) != 0) {
+				/* TODO: handle property miss */
+				panic();
+			}
 		}
 	}
 
diff --git a/lib/fconf/fconf_dyn_cfg_getter.c b/lib/fconf/fconf_dyn_cfg_getter.c
index d313a56..317d3e5 100644
--- a/lib/fconf/fconf_dyn_cfg_getter.c
+++ b/lib/fconf/fconf_dyn_cfg_getter.c
@@ -92,4 +92,4 @@
 	return 0;
 }
 
-FCONF_REGISTER_POPULATOR(dyn_cfg, fconf_populate_dtb_registry);
+FCONF_REGISTER_POPULATOR(TB_FW, dyn_cfg, fconf_populate_dtb_registry);
diff --git a/lib/fconf/fconf_tbbr_getter.c b/lib/fconf/fconf_tbbr_getter.c
index c6df9c8..a4d61d8 100644
--- a/lib/fconf/fconf_tbbr_getter.c
+++ b/lib/fconf/fconf_tbbr_getter.c
@@ -72,4 +72,4 @@
 	return 0;
 }
 
-FCONF_REGISTER_POPULATOR(tbbr, fconf_populate_tbbr_dyn_config);
+FCONF_REGISTER_POPULATOR(TB_FW, tbbr, fconf_populate_tbbr_dyn_config);
diff --git a/lib/locks/bakery/bakery_lock_normal.c b/lib/locks/bakery/bakery_lock_normal.c
index caced8f..0605fce 100644
--- a/lib/locks/bakery/bakery_lock_normal.c
+++ b/lib/locks/bakery/bakery_lock_normal.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -77,6 +78,8 @@
 {
 	if (cached)
 		dccivac(addr);
+
+	dmbish();
 }
 
 /* Helper function to check if the lock is acquired */
diff --git a/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
new file mode 100644
index 0000000..2952cde
--- /dev/null
+++ b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <fconf_hw_config_getter.h>
+#include <libfdt.h>
+#include <plat/common/platform.h>
+
+struct gicv3_config_t gicv3_config;
+struct hw_topology_t soc_topology;
+
+int fconf_populate_gicv3_config(uintptr_t config)
+{
+	int err;
+	int node;
+	int addr[20];
+
+	/* Necessary to work with libfdt APIs */
+	const void *hw_config_dtb = (const void *)config;
+
+	/*
+	 * Find the offset of the node containing "arm,gic-v3" compatible property.
+	 * Populating fconf strucutures dynamically is not supported for legacy
+	 * systems which use GICv2 IP. Simply skip extracting GIC properties.
+	 */
+	node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,gic-v3");
+	if (node < 0) {
+		WARN("FCONF: Unable to locate node with arm,gic-v3 compatible property\n");
+		return 0;
+	}
+	/* Read the reg cell holding base address of GIC controller modules
+	A sample reg cell array is shown here:
+		reg = <0x0 0x2f000000 0 0x10000>,	// GICD
+		      <0x0 0x2f100000 0 0x200000>,	// GICR
+		      <0x0 0x2c000000 0 0x2000>,	// GICC
+		      <0x0 0x2c010000 0 0x2000>,	// GICH
+		      <0x0 0x2c02f000 0 0x2000>;	// GICV
+	*/
+
+	err = fdtw_read_array(hw_config_dtb, node, "reg", 20, &addr);
+	if (err < 0) {
+		ERROR("FCONF: Failed to read reg property of GIC node\n");
+	}
+	return err;
+}
+
+int fconf_populate_topology(uintptr_t config)
+{
+	int err, node, cluster_node, core_node, thread_node, max_pwr_lvl = 0;
+	uint32_t cluster_count = 0, max_cpu_per_cluster = 0, total_cpu_count = 0;
+
+	/* Necessary to work with libfdt APIs */
+	const void *hw_config_dtb = (const void *)config;
+
+	/* Find the offset of the node containing "arm,psci-1.0" compatible property */
+	node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,psci-1.0");
+	if (node < 0) {
+		ERROR("FCONF: Unable to locate node with arm,psci-1.0 compatible property\n");
+		return node;
+	}
+
+	err = fdtw_read_cells(hw_config_dtb, node, "max-pwr-lvl", 1, &max_pwr_lvl);
+	if (err < 0) {
+		/*
+		 * Some legacy FVP dts may not have this property. Assign the default
+		 * value.
+		 */
+		WARN("FCONF: Could not locate max-pwr-lvl property\n");
+		max_pwr_lvl = 2;
+	}
+
+	assert((uint32_t)max_pwr_lvl <= MPIDR_AFFLVL2);
+
+	/* Find the offset of the "cpus" node */
+	node = fdt_path_offset(hw_config_dtb, "/cpus");
+	if (node < 0) {
+		ERROR("FCONF: Node '%s' not found in hardware configuration dtb\n", "cpus");
+		return node;
+	}
+
+	/* A typical cpu-map node in a device tree is shown here for reference
+	cpu-map {
+		cluster0 {
+			core0 {
+				cpu = <&CPU0>;
+			};
+			core1 {
+				cpu = <&CPU1>;
+			};
+		};
+
+		cluster1 {
+			core0 {
+				cpu = <&CPU2>;
+			};
+			core1 {
+				cpu = <&CPU3>;
+			};
+		};
+	};
+	*/
+
+	/* Locate the cpu-map child node */
+	node = fdt_subnode_offset(hw_config_dtb, node, "cpu-map");
+	if (node < 0) {
+		ERROR("FCONF: Node '%s' not found in hardware configuration dtb\n", "cpu-map");
+		return node;
+	}
+
+	uint32_t cpus_per_cluster[PLAT_ARM_CLUSTER_COUNT] = {0};
+
+	/* Iterate through cluster nodes */
+	fdt_for_each_subnode(cluster_node, hw_config_dtb, node) {
+		assert(cluster_count < PLAT_ARM_CLUSTER_COUNT);
+
+		/* Iterate through core nodes */
+		fdt_for_each_subnode(core_node, hw_config_dtb, cluster_node) {
+			/* core nodes may have child nodes i.e., "thread" nodes */
+			if (fdt_first_subnode(hw_config_dtb, core_node) < 0) {
+				cpus_per_cluster[cluster_count]++;
+			} else {
+				/* Multi-threaded CPU description is found in dtb */
+				fdt_for_each_subnode(thread_node, hw_config_dtb, core_node) {
+					cpus_per_cluster[cluster_count]++;
+				}
+
+				/* Since in some dtbs, core nodes may not have thread node,
+				 * no need to error if even one child node is not found.
+				 */
+			}
+		}
+
+		/* Ensure every cluster node has at least 1 child node */
+		if (cpus_per_cluster[cluster_count] < 1U) {
+			ERROR("FCONF: Unable to locate the core node in cluster %d\n", cluster_count);
+			return -1;
+		}
+
+		INFO("CLUSTER ID: %d cpu-count: %d\n", cluster_count, cpus_per_cluster[cluster_count]);
+
+		/* Find the maximum number of cpus in any cluster */
+		max_cpu_per_cluster = MAX(max_cpu_per_cluster, cpus_per_cluster[cluster_count]);
+		total_cpu_count += cpus_per_cluster[cluster_count];
+		cluster_count++;
+	}
+
+
+	/* At least one cluster node is expected in hardware configuration dtb */
+	if (cluster_count < 1U) {
+		ERROR("FCONF: Unable to locate the cluster node in cpu-map node\n");
+		return -1;
+	}
+
+	soc_topology.plat_max_pwr_level = (uint32_t)max_pwr_lvl;
+	soc_topology.plat_cluster_count = cluster_count;
+	soc_topology.cluster_cpu_count = max_cpu_per_cluster;
+	soc_topology.plat_cpu_count = total_cpu_count;
+
+	return 0;
+}
+
+FCONF_REGISTER_POPULATOR(HW_CONFIG, gicv3_config, fconf_populate_gicv3_config);
+FCONF_REGISTER_POPULATOR(HW_CONFIG, topology, fconf_populate_topology);
diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
index c94a209..db3fb55 100644
--- a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
@@ -9,6 +9,7 @@
 	compatible = "spci-core-manifest-1.0";
 
 	attribute {
+		spmc_id = <0x8000>;
 		maj_ver = <0x0>;
 		min_ver = <0x9>;
 		exec_state = <0x0>;
diff --git a/plat/arm/board/fvp/fvp_bl31_setup.c b/plat/arm/board/fvp/fvp_bl31_setup.c
index 8627c5e..dc7bfa2 100644
--- a/plat/arm/board/fvp/fvp_bl31_setup.c
+++ b/plat/arm/board/fvp/fvp_bl31_setup.c
@@ -1,16 +1,21 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <assert.h>
+#include <common/debug.h>
 #include <drivers/arm/smmu_v3.h>
+#include <lib/fconf/fconf.h>
 #include <plat/arm/common/arm_config.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 
 #include "fvp_private.h"
 
+uintptr_t hw_config_dtb;
+
 void __init bl31_early_platform_setup2(u_register_t arg0,
 		u_register_t arg1, u_register_t arg2, u_register_t arg3)
 {
@@ -40,4 +45,23 @@
 	/* On FVP RevC, initialize SMMUv3 */
 	if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U)
 		smmuv3_init(PLAT_FVP_SMMUV3_BASE);
+
+	hw_config_dtb = arg2;
+}
+
+void __init bl31_plat_arch_setup(void)
+{
+	arm_bl31_plat_arch_setup();
+
+	/*
+	 * For RESET_TO_BL31 systems, BL31 is the first bootloader to run.
+	 * So there is no BL2 to load the HW_CONFIG dtb into memory before
+	 * control is passed to BL31.
+	 */
+#if !RESET_TO_BL31 && !BL2_AT_EL3
+	assert(hw_config_dtb != 0U);
+
+	INFO("BL31 FCONF: HW_CONFIG address = %p\n", (void *)hw_config_dtb);
+	fconf_populate("HW_CONFIG", hw_config_dtb);
+#endif
 }
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index 2c880fc..c5fae56 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -134,6 +134,8 @@
 #if SPM_MM
 	ARM_SPM_BUF_EL3_MMAP,
 #endif
+	/* Required by fconf APIs to read HW_CONFIG dtb loaded into DRAM */
+	ARM_DTB_DRAM_NS,
 	{0}
 };
 
@@ -160,6 +162,8 @@
 	V2M_MAP_IOFPGA,
 	MAP_DEVICE0,
 	MAP_DEVICE1,
+	/* Required by fconf APIs to read HW_CONFIG dtb loaded into DRAM */
+	ARM_DTB_DRAM_NS,
 	{0}
 };
 #endif
diff --git a/plat/arm/board/fvp/fvp_topology.c b/plat/arm/board/fvp/fvp_topology.c
index 24e79b4..80cfbd5 100644
--- a/plat/arm/board/fvp/fvp_topology.c
+++ b/plat/arm/board/fvp/fvp_topology.c
@@ -1,18 +1,21 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <platform_def.h>
+#include <assert.h>
 
 #include <arch.h>
 #include <drivers/arm/fvp/fvp_pwrc.h>
+#include <fconf_hw_config_getter.h>
 #include <lib/cassert.h>
 #include <plat/arm/common/arm_config.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 
+#include <platform_def.h>
+
 /* The FVP power domain tree descriptor */
 static unsigned char fvp_power_domain_tree_desc[FVP_CLUSTER_COUNT + 2];
 
@@ -21,24 +24,47 @@
 			assert_invalid_fvp_cluster_count);
 
 /*******************************************************************************
- * This function dynamically constructs the topology according to
- * FVP_CLUSTER_COUNT and returns it.
+ * This function dynamically constructs the topology according to cpu-map node
+ * in HW_CONFIG dtb and returns it.
  ******************************************************************************/
 const unsigned char *plat_get_power_domain_tree_desc(void)
 {
-	int i;
+	unsigned int i;
+	uint32_t cluster_count, cpus_per_cluster;
+
+	/*
+	 * fconf APIs are not supported for RESET_TO_SP_MIN, RESET_TO_BL31 and
+	 * BL2_AT_EL3 systems.
+	 */
+#if RESET_TO_SP_MIN || RESET_TO_BL31 || BL2_AT_EL3
+	cluster_count = FVP_CLUSTER_COUNT;
+	cpus_per_cluster = FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU;
+#else
+	cluster_count = FCONF_GET_PROPERTY(hw_config, topology, plat_cluster_count);
+	cpus_per_cluster = FCONF_GET_PROPERTY(hw_config, topology, cluster_cpu_count);
+	/* Several FVP Models use the same blanket dts. Ex: FVP_Base_Cortex-A65x4
+	 * and FVP_Base_Cortex-A65AEx8 both use same dts but have different number of
+	 * CPUs in the cluster, as reflected by build flags FVP_MAX_CPUS_PER_CLUSTER.
+	 * Take the minimum of two to ensure PSCI functions do not exceed the size of
+	 * the PSCI data structures allocated at build time.
+	 */
+	cpus_per_cluster = MIN(cpus_per_cluster,
+			(uint32_t)(FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU));
+
+#endif
+
+	assert(cluster_count > 0U);
+	assert(cpus_per_cluster > 0U);
 
 	/*
 	 * The highest level is the system level. The next level is constituted
 	 * by clusters and then cores in clusters.
 	 */
 	fvp_power_domain_tree_desc[0] = 1;
-	fvp_power_domain_tree_desc[1] = FVP_CLUSTER_COUNT;
-
-	for (i = 0; i < FVP_CLUSTER_COUNT; i++)
-		fvp_power_domain_tree_desc[i + 2] =
-			FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU;
+	fvp_power_domain_tree_desc[1] = (unsigned char)cluster_count;
 
+	for (i = 0; i < cluster_count; i++)
+		fvp_power_domain_tree_desc[i + 2] = (unsigned char)cpus_per_cluster;
 
 	return fvp_power_domain_tree_desc;
 }
diff --git a/plat/arm/board/fvp/include/fconf_hw_config_getter.h b/plat/arm/board/fvp/include/fconf_hw_config_getter.h
new file mode 100644
index 0000000..cab832f
--- /dev/null
+++ b/plat/arm/board/fvp/include/fconf_hw_config_getter.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FCONF_HW_CONFIG_GETTER_H
+#define FCONF_HW_CONFIG_GETTER_H
+
+#include <lib/fconf/fconf.h>
+
+/* Hardware Config related getter */
+#define hw_config__gicv3_config_getter(prop) gicv3_config.prop
+
+#define hw_config__topology_getter(prop) soc_topology.prop
+
+struct gicv3_config_t {
+	void *gicd_base;
+	void *gicr_base;
+};
+
+struct hw_topology_t {
+	uint32_t plat_cluster_count;
+	uint32_t cluster_cpu_count;
+	uint32_t plat_cpu_count;
+	uint32_t plat_max_pwr_level;
+};
+
+int fconf_populate_gicv3_config(uintptr_t config);
+int fconf_populate_topology(uintptr_t config);
+
+extern struct gicv3_config_t gicv3_config;
+extern struct hw_topology_t soc_topology;
+
+#endif /* FCONF_HW_CONFIG_GETTER_H */
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index bfe207a..1f569c2 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -52,6 +52,13 @@
 #define PLAT_ARM_DRAM2_BASE		ULL(0x880000000)
 #define PLAT_ARM_DRAM2_SIZE		UL(0x80000000)
 
+#define PLAT_HW_CONFIG_DTB_BASE		ULL(0x82000000)
+#define PLAT_HW_CONFIG_DTB_SIZE		ULL(0x8000)
+
+#define ARM_DTB_DRAM_NS			MAP_REGION_FLAT(		\
+					PLAT_HW_CONFIG_DTB_BASE,	\
+					PLAT_HW_CONFIG_DTB_SIZE,	\
+					MT_MEMORY | MT_RO | MT_NS)
 /*
  * Load address of BL33 for this platform port
  */
@@ -63,21 +70,21 @@
  */
 #if defined(IMAGE_BL31)
 # if SPM_MM
-#  define PLAT_ARM_MMAP_ENTRIES		9
+#  define PLAT_ARM_MMAP_ENTRIES		10
 #  define MAX_XLAT_TABLES		9
 #  define PLAT_SP_IMAGE_MMAP_REGIONS	30
 #  define PLAT_SP_IMAGE_MAX_XLAT_TABLES	10
 # else
-#  define PLAT_ARM_MMAP_ENTRIES		8
+#  define PLAT_ARM_MMAP_ENTRIES		9
 #  if USE_DEBUGFS
-#   define MAX_XLAT_TABLES		6
+#   define MAX_XLAT_TABLES		8
 #  else
-#   define MAX_XLAT_TABLES		5
+#   define MAX_XLAT_TABLES		7
 #  endif
 # endif
 #elif defined(IMAGE_BL32)
-# define PLAT_ARM_MMAP_ENTRIES		8
-# define MAX_XLAT_TABLES		5
+# define PLAT_ARM_MMAP_ENTRIES		9
+# define MAX_XLAT_TABLES		6
 #elif !USE_ROMLIB
 # define PLAT_ARM_MMAP_ENTRIES		11
 # define MAX_XLAT_TABLES		5
@@ -126,7 +133,7 @@
  * calculated using the current BL31 PROGBITS debug size plus the sizes of
  * BL2 and BL1-RW
  */
-#define PLAT_ARM_MAX_BL31_SIZE		UL(0x3B000)
+#define PLAT_ARM_MAX_BL31_SIZE		UL(0x3E000)
 #endif /* RESET_TO_BL31 */
 
 #ifndef __aarch64__
diff --git a/plat/arm/board/fvp/jmptbl.i b/plat/arm/board/fvp/jmptbl.i
index b1b9ed4..0c93d0a 100644
--- a/plat/arm/board/fvp/jmptbl.i
+++ b/plat/arm/board/fvp/jmptbl.i
@@ -22,6 +22,8 @@
 fdt     fdt_setprop_inplace_namelen_partial
 fdt     fdt_first_subnode
 fdt     fdt_next_subnode
+fdt     fdt_path_offset
+fdt     fdt_subnode_offset
 mbedtls mbedtls_asn1_get_alg
 mbedtls mbedtls_asn1_get_alg_null
 mbedtls mbedtls_asn1_get_bitstring_null
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index c32b302..4e20632 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -204,6 +204,14 @@
 				${FVP_INTERCONNECT_SOURCES}			\
 				${FVP_SECURITY_SOURCES}
 
+# Support for fconf in BL31
+# Added separately from the above list for better readability
+ifeq ($(filter 1,${BL2_AT_EL3} ${RESET_TO_BL31}),)
+BL31_SOURCES		+=	common/fdt_wrappers.c				\
+				lib/fconf/fconf.c				\
+				plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
+endif
+
 ifeq (${FVP_USE_SP804_TIMER},1)
 BL31_SOURCES		+=	drivers/arm/sp804/sp804_delay_timer.c
 else
diff --git a/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c b/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c
index 88c91e6..763b42a 100644
--- a/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c
+++ b/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c
@@ -1,13 +1,20 @@
 /*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <assert.h>
+
+#include <bl32/sp_min/platform_sp_min.h>
+#include <common/debug.h>
+#include <lib/fconf/fconf.h>
 #include <plat/arm/common/plat_arm.h>
 
 #include "../fvp_private.h"
 
+uintptr_t hw_config_dtb;
+
 void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1,
 			u_register_t arg2, u_register_t arg3)
 {
@@ -30,4 +37,24 @@
 	 * FVP PSCI code will enable coherency for other clusters.
 	 */
 	fvp_interconnect_enable();
+
+	hw_config_dtb = arg2;
+}
+
+void sp_min_plat_arch_setup(void)
+{
+	arm_sp_min_plat_arch_setup();
+
+	/*
+	 * For RESET_TO_SP_MIN systems, SP_MIN(BL32) is the first bootloader
+	 * to run. So there is no BL2 to load the HW_CONFIG dtb into memory
+	 * before control is passed to SP_MIN.
+	 * Also, BL2 skips loading HW_CONFIG dtb for BL2_AT_EL3 builds.
+	 */
+#if !RESET_TO_SP_MIN && !BL2_AT_EL3
+	assert(hw_config_dtb != 0U);
+
+	INFO("SP_MIN FCONF: HW_CONFIG address = %p\n", (void *)hw_config_dtb);
+	fconf_populate("HW_CONFIG", hw_config_dtb);
+#endif
 }
diff --git a/plat/arm/board/fvp/sp_min/sp_min-fvp.mk b/plat/arm/board/fvp/sp_min/sp_min-fvp.mk
index 0250a5f..36bf441 100644
--- a/plat/arm/board/fvp/sp_min/sp_min-fvp.mk
+++ b/plat/arm/board/fvp/sp_min/sp_min-fvp.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -18,4 +18,12 @@
 				${FVP_INTERCONNECT_SOURCES}			\
 				${FVP_SECURITY_SOURCES}
 
+# Support for fconf in SP_MIN(BL32)
+# Added separately from the above list for better readability
+ifeq ($(filter 1,${BL2_AT_EL3} ${RESET_TO_SP_MIN}),)
+BL32_SOURCES		+=	common/fdt_wrappers.c				\
+				lib/fconf/fconf.c				\
+				plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
+endif
+
 include plat/arm/common/sp_min/arm_sp_min.mk
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index cfac801..b446395 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -249,16 +249,12 @@
 #endif
 
 /*
- * PLAT_CSS_MAX_SCP_BL2_SIZE is calculated using the current
- * SCP_BL2 size plus a little space for growth.
- */
-#define PLAT_CSS_MAX_SCP_BL2_SIZE	UL(0x14000)
-
-/*
- * PLAT_CSS_MAX_SCP_BL2U_SIZE is calculated using the current
- * SCP_BL2U size plus a little space for growth.
+ * SCP_BL2 uses up whatever remaining space is available as it is loaded before
+ * anything else in this memory region and is handed over to the SCP before
+ * BL31 is loaded over the top.
  */
-#define PLAT_CSS_MAX_SCP_BL2U_SIZE	UL(0x14000)
+#define PLAT_CSS_MAX_SCP_BL2_SIZE	(SCP_BL2_LIMIT - ARM_TB_FW_CONFIG_LIMIT)
+#define PLAT_CSS_MAX_SCP_BL2U_SIZE	PLAT_CSS_MAX_SCP_BL2_SIZE
 
 #define PLAT_ARM_G1S_IRQ_PROPS(grp) \
 	CSS_G1S_IRQ_PROPS(grp), \
diff --git a/plat/arm/board/n1sdp/platform.mk b/plat/arm/board/n1sdp/platform.mk
index da780a3..5856c9f 100644
--- a/plat/arm/board/n1sdp/platform.mk
+++ b/plat/arm/board/n1sdp/platform.mk
@@ -65,6 +65,9 @@
 # When building for systems with hardware-assisted coherency, there's no need to
 # use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too.
 USE_COHERENT_MEM			:=	0
+
+# Enable the flag since N1SDP has a system level cache
+NEOVERSE_N1_EXTERNAL_LLC		:=	1
 include plat/arm/common/arm_common.mk
 include plat/arm/css/common/css_common.mk
 include plat/arm/board/common/board_common.mk
diff --git a/plat/arm/board/rddaniel/include/platform_def.h b/plat/arm/board/rddaniel/include/platform_def.h
index 790ed69..a118ca3 100644
--- a/plat/arm/board/rddaniel/include/platform_def.h
+++ b/plat/arm/board/rddaniel/include/platform_def.h
@@ -32,9 +32,19 @@
 					 (n * TZC400_OFFSET))
 
 #define TZC_NSAID_ALL_AP		U(0)
+#define TZC_NSAID_PCI			U(1)
+#define TZC_NSAID_HDLCD0		U(2)
+#define TZC_NSAID_CLCD			U(7)
+#define TZC_NSAID_AP			U(9)
+#define TZC_NSAID_VIRTIO		U(15)
 
 #define PLAT_ARM_TZC_NS_DEV_ACCESS	\
-		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_ALL_AP))
+		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_ALL_AP)) | \
+		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_HDLCD0)) | \
+		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_PCI))    | \
+		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_AP))     | \
+		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_CLCD))   | \
+		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_VIRTIO))
 
 /*
  * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 136e65a..d9fc84e 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -61,7 +61,7 @@
 
 	/* Fill the properties struct with the info from the config dtb */
 	if (tb_fw_config != 0U) {
-		fconf_populate(tb_fw_config);
+		fconf_populate("TB_FW", tb_fw_config);
 	}
 
 	/* Initialise the IO layer and register platform IO devices */
diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c
index d1eee08..60c777e 100644
--- a/plat/arm/common/arm_common.c
+++ b/plat/arm/common/arm_common.c
@@ -25,6 +25,9 @@
  * conflicts with the definition in plat/common. */
 #pragma weak plat_get_syscnt_freq2
 
+/* Get ARM SOC-ID */
+#pragma weak plat_arm_get_soc_id
+
 /*******************************************************************************
  * Changes the memory attributes for the region of mapped memory where the BL
  * image's translation tables are located such that the tables will have
@@ -231,3 +234,22 @@
 	return arm_validate_ns_entrypoint(pa);
 }
 #endif
+
+/*
+ * Weak function to get ARM platform SOC-ID, Always return SOC-ID=0
+ * ToDo: Get proper SOC-ID for every ARM platform and define this
+ *       function separately for every ARM platform.
+ */
+uint32_t plat_arm_get_soc_id(void)
+{
+	return 0U;
+}
+
+/* Get SOC version */
+int32_t plat_get_soc_version(void)
+{
+	return (int32_t)
+		((ARM_SOC_IDENTIFICATION_CODE << ARM_SOC_IDENTIFICATION_SHIFT)
+		 | (ARM_SOC_CONTINUATION_CODE << ARM_SOC_CONTINUATION_SHIFT)
+		 | plat_arm_get_soc_id());
+}
diff --git a/plat/arm/common/fconf/arm_fconf_io.c b/plat/arm/common/fconf/arm_fconf_io.c
index cfcddc2..017af79 100644
--- a/plat/arm/common/fconf/arm_fconf_io.c
+++ b/plat/arm/common/fconf/arm_fconf_io.c
@@ -138,6 +138,6 @@
 	return 0;
 }
 
-FCONF_REGISTER_POPULATOR(arm_io, fconf_populate_arm_io_policies);
+FCONF_REGISTER_POPULATOR(TB_FW, arm_io, fconf_populate_arm_io_policies);
 
 #endif /* IMAGE_BL2 */
diff --git a/plat/arm/common/fconf/arm_fconf_sp.c b/plat/arm/common/fconf/arm_fconf_sp.c
index bb88aff..9b6fa9b 100644
--- a/plat/arm/common/fconf/arm_fconf_sp.c
+++ b/plat/arm/common/fconf/arm_fconf_sp.c
@@ -102,6 +102,6 @@
 	return 0;
 }
 
-FCONF_REGISTER_POPULATOR(arm_sp, fconf_populate_arm_sp);
+FCONF_REGISTER_POPULATOR(TB_FW, arm_sp, fconf_populate_arm_sp);
 
 #endif /* IMAGE_BL2 */
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 cbbdfa2..2904ad9 100644
--- a/plat/arm/common/sp_min/arm_sp_min_setup.c
+++ b/plat/arm/common/sp_min/arm_sp_min_setup.c
@@ -217,7 +217,7 @@
  * Perform the very early platform specific architectural setup here. At the
  * moment this only initializes the MMU
  ******************************************************************************/
-void sp_min_plat_arch_setup(void)
+void arm_sp_min_plat_arch_setup(void)
 {
 	const mmap_region_t bl_regions[] = {
 		MAP_BL_SP_MIN_TOTAL,
@@ -232,3 +232,8 @@
 
 	enable_mmu_svc_mon(0);
 }
+
+void sp_min_plat_arch_setup(void)
+{
+	arm_sp_min_plat_arch_setup();
+}
diff --git a/plat/arm/css/sgm/include/sgm_base_platform_def.h b/plat/arm/css/sgm/include/sgm_base_platform_def.h
index 90511ac..0ac0c2b 100644
--- a/plat/arm/css/sgm/include/sgm_base_platform_def.h
+++ b/plat/arm/css/sgm/include/sgm_base_platform_def.h
@@ -133,16 +133,12 @@
 #endif
 
 /*
- * PLAT_CSS_MAX_SCP_BL2_SIZE is calculated using the current
- * SCP_BL2 size plus a little space for growth.
- */
-#define PLAT_CSS_MAX_SCP_BL2_SIZE	0x15000
-
-/*
- * PLAT_CSS_MAX_SCP_BL2U_SIZE is calculated using the current
- * SCP_BL2U size plus a little space for growth.
+ * SCP_BL2 uses up whatever remaining space is available as it is loaded before
+ * anything else in this memory region and is handed over to the SCP before
+ * BL31 is loaded over the top.
  */
-#define PLAT_CSS_MAX_SCP_BL2U_SIZE	0x15000
+#define PLAT_CSS_MAX_SCP_BL2_SIZE	(SCP_BL2_LIMIT - ARM_TB_FW_CONFIG_LIMIT)
+#define PLAT_CSS_MAX_SCP_BL2U_SIZE	PLAT_CSS_MAX_SCP_BL2_SIZE
 
 /*
  * Most platform porting definitions provided by included headers
diff --git a/plat/common/plat_bl_common.c b/plat/common/plat_bl_common.c
index de6c1d1..d38fc6f 100644
--- a/plat/common/plat_bl_common.c
+++ b/plat/common/plat_bl_common.c
@@ -11,6 +11,7 @@
 #include <common/debug.h>
 #include <lib/xlat_tables/xlat_tables_compat.h>
 #include <plat/common/platform.h>
+#include <smccc_helpers.h>
 #include <tools_share/firmware_encrypted.h>
 
 /*
@@ -24,6 +25,18 @@
 #pragma weak bl2_plat_handle_post_image_load
 #pragma weak plat_try_next_boot_source
 #pragma weak plat_get_enc_key_info
+#pragma weak plat_get_soc_version
+#pragma weak plat_get_soc_revision
+
+int32_t plat_get_soc_version(void)
+{
+	return SMC_ARCH_CALL_NOT_SUPPORTED;
+}
+
+int32_t plat_get_soc_revision(void)
+{
+	return SMC_ARCH_CALL_NOT_SUPPORTED;
+}
 
 void bl2_el3_plat_prepare_exit(void)
 {
diff --git a/plat/common/plat_spmd_manifest.c b/plat/common/plat_spmd_manifest.c
index 9c3dc71..f0aa27c 100644
--- a/plat/common/plat_spmd_manifest.c
+++ b/plat/common/plat_spmd_manifest.c
@@ -37,6 +37,12 @@
 		return -ENOENT;
 	}
 
+	rc = fdtw_read_cells(fdt, node, "spmc_id", 1, &attr->spmc_id);
+	if (rc) {
+		ERROR("Missing SPMC ID in manifest.\n");
+		return -ENOENT;
+	}
+
 	rc = fdtw_read_cells(fdt, node, "exec_state", 1, &attr->exec_state);
 	if (rc)
 		NOTICE("Execution state not specified in SPM core manifest.\n");
@@ -55,6 +61,7 @@
 
 	VERBOSE("SPM core manifest attribute section:\n");
 	VERBOSE("  version: %x.%x\n", attr->major_version, attr->minor_version);
+	VERBOSE("  spmc_id: %x\n", attr->spmc_id);
 	VERBOSE("  binary_size: 0x%x\n", attr->binary_size);
 	VERBOSE("  load_address: 0x%llx\n", attr->load_address);
 	VERBOSE("  entrypoint: 0x%llx\n", attr->entrypoint);
diff --git a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
index c2ef981..a53f660 100644
--- a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
+++ b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
@@ -21,6 +21,7 @@
 #include <smmu.h>
 #include <tegra_def.h>
 #include <tegra_platform.h>
+#include <tegra_private.h>
 
 /* Video Memory base and size (live values) */
 static uint64_t video_mem_base;
@@ -223,6 +224,58 @@
 	mce_update_gsc_tzram();
 }
 
+/*
+ * Save MC settings before "System Suspend" to TZDRAM
+ */
+void tegra_mc_save_context(uint64_t mc_ctx_addr)
+{
+	const tegra_mc_settings_t *plat_mc_settings = tegra_get_mc_settings();
+	uint32_t i, num_entries = 0;
+	mc_regs_t *mc_ctx_regs;
+	const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
+	uint64_t tzdram_base = params_from_bl2->tzdram_base;
+	uint64_t tzdram_end = tzdram_base + params_from_bl2->tzdram_size;
+
+	assert((mc_ctx_addr >= tzdram_base) && (mc_ctx_addr <= tzdram_end));
+
+	/* get MC context table */
+	mc_ctx_regs = plat_mc_settings->get_mc_system_suspend_ctx();
+	assert(mc_ctx_regs != NULL);
+
+	/*
+	 * mc_ctx_regs[0].val contains the size of the context table minus
+	 * the last entry. Sanity check the table size before we start with
+	 * the context save operation.
+	 */
+	while (mc_ctx_regs[num_entries].reg != 0xFFFFFFFFU) {
+		num_entries++;
+	}
+
+	/* panic if the sizes do not match */
+	if (num_entries != mc_ctx_regs[0].val) {
+		ERROR("MC context size mismatch!");
+		panic();
+	}
+
+	/* save MC register values */
+	for (i = 1U; i < num_entries; i++) {
+		mc_ctx_regs[i].val = mmio_read_32(mc_ctx_regs[i].reg);
+	}
+
+	/* increment by 1 to take care of the last entry */
+	num_entries++;
+
+	/* Save MC config settings */
+	(void)memcpy((void *)mc_ctx_addr, mc_ctx_regs,
+			sizeof(mc_regs_t) * num_entries);
+
+	/* save the MC table address */
+	mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_LO,
+		(uint32_t)mc_ctx_addr);
+	mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_HI,
+		(uint32_t)(mc_ctx_addr >> 32));
+}
+
 static void tegra_lock_videomem_nonoverlap(uint64_t phys_base,
 					   uint64_t size_in_bytes)
 {
diff --git a/plat/nvidia/tegra/common/drivers/smmu/smmu.c b/plat/nvidia/tegra/common/drivers/smmu/smmu.c
index 8c1b899..a4a4354 100644
--- a/plat/nvidia/tegra/common/drivers/smmu/smmu.c
+++ b/plat/nvidia/tegra/common/drivers/smmu/smmu.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -17,121 +18,8 @@
 
 extern void memcpy16(void *dest, const void *src, unsigned int length);
 
-/* SMMU IDs currently supported by the driver */
-enum {
-	TEGRA_SMMU0 = 0U,
-	TEGRA_SMMU1,
-	TEGRA_SMMU2
-};
-
-static uint32_t tegra_smmu_read_32(uint32_t smmu_id, uint32_t off)
-{
-	uint32_t ret = 0U;
-
-#if defined(TEGRA_SMMU0_BASE)
-	if (smmu_id == TEGRA_SMMU0) {
-		ret = mmio_read_32(TEGRA_SMMU0_BASE + (uint64_t)off);
-	}
-#endif
-
-#if defined(TEGRA_SMMU1_BASE)
-	if (smmu_id == TEGRA_SMMU1) {
-		ret = mmio_read_32(TEGRA_SMMU1_BASE + (uint64_t)off);
-	}
-#endif
-
-#if defined(TEGRA_SMMU2_BASE)
-	if (smmu_id == TEGRA_SMMU2) {
-		ret = mmio_read_32(TEGRA_SMMU2_BASE + (uint64_t)off);
-	}
-#endif
-
-	return ret;
-}
-
-static void tegra_smmu_write_32(uint32_t smmu_id,
-			uint32_t off, uint32_t val)
-{
-#if defined(TEGRA_SMMU0_BASE)
-	if (smmu_id == TEGRA_SMMU0) {
-		mmio_write_32(TEGRA_SMMU0_BASE + (uint64_t)off, val);
-	}
-#endif
-
-#if defined(TEGRA_SMMU1_BASE)
-	if (smmu_id == TEGRA_SMMU1) {
-		mmio_write_32(TEGRA_SMMU1_BASE + (uint64_t)off, val);
-	}
-#endif
-
-#if defined(TEGRA_SMMU2_BASE)
-	if (smmu_id == TEGRA_SMMU2) {
-		mmio_write_32(TEGRA_SMMU2_BASE + (uint64_t)off, val);
-	}
-#endif
-}
-
-/*
- * Save SMMU settings before "System Suspend" to TZDRAM
- */
-void tegra_smmu_save_context(uint64_t smmu_ctx_addr)
-{
-	uint32_t i, num_entries = 0;
-	smmu_regs_t *smmu_ctx_regs;
-	const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
-	uint64_t tzdram_base = params_from_bl2->tzdram_base;
-	uint64_t tzdram_end = tzdram_base + params_from_bl2->tzdram_size;
-	uint32_t reg_id1, pgshift, cb_size;
-
-	/* sanity check SMMU settings c*/
-	reg_id1 = mmio_read_32((TEGRA_SMMU0_BASE + SMMU_GNSR0_IDR1));
-	pgshift = ((reg_id1 & ID1_PAGESIZE) != 0U) ? 16U : 12U;
-	cb_size = ((uint32_t)2 << pgshift) * \
-	((uint32_t)1 << (((reg_id1 >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1U));
-
-	assert(!((pgshift != PGSHIFT) || (cb_size != CB_SIZE)));
-	assert((smmu_ctx_addr >= tzdram_base) && (smmu_ctx_addr <= tzdram_end));
-
-	/* get SMMU context table */
-	smmu_ctx_regs = plat_get_smmu_ctx();
-	assert(smmu_ctx_regs != NULL);
-
-	/*
-	 * smmu_ctx_regs[0].val contains the size of the context table minus
-	 * the last entry. Sanity check the table size before we start with
-	 * the context save operation.
-	 */
-	while ((smmu_ctx_regs[num_entries].reg != 0xFFFFFFFFU)) {
-		num_entries++;
-	}
-
-	/* panic if the sizes do not match */
-	if (num_entries != smmu_ctx_regs[0].val) {
-		ERROR("SMMU context size mismatch!");
-		panic();
-	}
-
-	/* save SMMU register values */
-	for (i = 1U; i < num_entries; i++) {
-		smmu_ctx_regs[i].val = mmio_read_32(smmu_ctx_regs[i].reg);
-	}
-
-	/* increment by 1 to take care of the last entry */
-	num_entries++;
-
-	/* Save SMMU config settings */
-	(void)memcpy16((uint8_t *)smmu_ctx_addr, (uint8_t *)smmu_ctx_regs,
-			(sizeof(smmu_regs_t) * num_entries));
-
-	/* save the SMMU table address */
-	mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SMMU_TABLE_ADDR_LO,
-		(uint32_t)smmu_ctx_addr);
-	mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SMMU_TABLE_ADDR_HI,
-		(uint32_t)(smmu_ctx_addr >> 32));
-}
-
-#define SMMU_NUM_CONTEXTS		64
-#define SMMU_CONTEXT_BANK_MAX_IDX	64
+#define SMMU_NUM_CONTEXTS		64U
+#define SMMU_CONTEXT_BANK_MAX_IDX	64U
 
 /*
  * Init SMMU during boot or "System Suspend" exit
diff --git a/plat/nvidia/tegra/include/drivers/bpmp_ipc.h b/plat/nvidia/tegra/include/drivers/bpmp_ipc.h
index a0d02c9..401a07a 100644
--- a/plat/nvidia/tegra/include/drivers/bpmp_ipc.h
+++ b/plat/nvidia/tegra/include/drivers/bpmp_ipc.h
@@ -19,11 +19,6 @@
 #define TEGRA_RESET_ID_GPCDMA		U(70)
 
 /**
- * Clock identifier for the SE device
- */
-#define TEGRA_CLK_SE        U(124)
-
-/**
  * Function to initialise the IPC with the bpmp
  */
 int32_t tegra_bpmp_ipc_init(void);
diff --git a/plat/nvidia/tegra/include/drivers/memctrl_v2.h b/plat/nvidia/tegra/include/drivers/memctrl_v2.h
index a4085e2..509fe32 100644
--- a/plat/nvidia/tegra/include/drivers/memctrl_v2.h
+++ b/plat/nvidia/tegra/include/drivers/memctrl_v2.h
@@ -84,6 +84,41 @@
 		.override_enable = OVERRIDE_ ## access \
 	}
 
+typedef struct mc_regs {
+	uint32_t reg;
+	uint32_t val;
+} mc_regs_t;
+
+#define mc_make_sid_override_cfg(name) \
+	{ \
+		.reg = TEGRA_MC_STREAMID_BASE + MC_STREAMID_OVERRIDE_CFG_ ## name, \
+		.val = 0x00000000U, \
+	}
+
+#define mc_make_sid_security_cfg(name) \
+	{ \
+		.reg = TEGRA_MC_STREAMID_BASE + MC_STREAMID_OVERRIDE_TO_SECURITY_CFG(MC_STREAMID_OVERRIDE_CFG_ ## name), \
+		.val = 0x00000000U, \
+	}
+
+#define mc_smmu_bypass_cfg \
+	{ \
+		.reg = TEGRA_MC_BASE + MC_SMMU_BYPASS_CONFIG, \
+		.val = 0x00000000U, \
+	}
+
+#define _START_OF_TABLE_ \
+	{ \
+		.reg = 0xCAFE05C7U, \
+		.val = 0x00000000U, \
+	}
+
+#define _END_OF_TABLE_ \
+	{ \
+		.reg = 0xFFFFFFFFU, \
+		.val = 0xFFFFFFFFU, \
+	}
+
 /*******************************************************************************
  * Structure to hold Memory Controller's Configuration settings
  ******************************************************************************/
@@ -96,6 +131,7 @@
 	uint32_t num_txn_override_cfgs;
 	void (*reconfig_mss_clients)(void);
 	void (*set_txn_overrides)(void);
+	mc_regs_t* (*get_mc_system_suspend_ctx)(void);
 } tegra_mc_settings_t;
 
 static inline uint32_t tegra_mc_read_32(uint32_t off)
@@ -166,6 +202,13 @@
 tegra_mc_settings_t *tegra_get_mc_settings(void);
 
 /*******************************************************************************
+ * Handler to save MC settings before "System Suspend" to TZDRAM
+ *
+ * Implemented by Tegra common memctrl_v2 driver under common/drivers/memctrl
+ ******************************************************************************/
+void tegra_mc_save_context(uint64_t mc_ctx_addr);
+
+/*******************************************************************************
  * Handler to program the scratch registers with TZDRAM settings for the
  * resume firmware.
  *
diff --git a/plat/nvidia/tegra/include/drivers/smmu.h b/plat/nvidia/tegra/include/drivers/smmu.h
index 424a91a..601864f 100644
--- a/plat/nvidia/tegra/include/drivers/smmu.h
+++ b/plat/nvidia/tegra/include/drivers/smmu.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,566 +13,7 @@
 #include <memctrl_v2.h>
 #include <tegra_def.h>
 
-/*******************************************************************************
- * SMMU Register constants
- ******************************************************************************/
-#define SMMU_CBn_SCTLR				(0x0U)
-#define SMMU_CBn_SCTLR_STAGE2			(0x0U)
 #define SMMU_CBn_ACTLR				(0x4U)
-#define SMMU_CBn_RESUME				(0x8U)
-#define SMMU_CBn_TCR2				(0x10U)
-#define SMMU_CBn_TTBR0_LO			(0x20U)
-#define SMMU_CBn_TTBR0_HI			(0x24U)
-#define SMMU_CBn_TTBR1_LO			(0x28U)
-#define SMMU_CBn_TTBR1_HI			(0x2cU)
-#define SMMU_CBn_TCR_LPAE			(0x30U)
-#define SMMU_CBn_TCR				(0x30U)
-#define SMMU_CBn_TCR_EAE_1			(0x30U)
-#define SMMU_CBn_TCR				(0x30U)
-#define SMMU_CBn_CONTEXTIDR			(0x34U)
-#define SMMU_CBn_CONTEXTIDR_EAE_1		(0x34U)
-#define SMMU_CBn_PRRR_MAIR0			(0x38U)
-#define SMMU_CBn_NMRR_MAIR1			(0x3cU)
-#define SMMU_CBn_SMMU_CBn_PAR			(0x50U)
-#define SMMU_CBn_SMMU_CBn_PAR0			(0x50U)
-#define SMMU_CBn_SMMU_CBn_PAR1			(0x54U)
-/*      SMMU_CBn_SMMU_CBn_PAR0_Fault		(0x50U) */
-/*      SMMU_CBn_SMMU_CBn_PAR0_Fault		(0x54U) */
-#define SMMU_CBn_FSR				(0x58U)
-#define SMMU_CBn_FSRRESTORE			(0x5cU)
-#define SMMU_CBn_FAR_LO				(0x60U)
-#define SMMU_CBn_FAR_HI				(0x64U)
-#define SMMU_CBn_FSYNR0				(0x68U)
-#define SMMU_CBn_IPAFAR_LO			(0x70U)
-#define SMMU_CBn_IPAFAR_HI			(0x74U)
-#define SMMU_CBn_TLBIVA_LO			(0x600U)
-#define SMMU_CBn_TLBIVA_HI			(0x604U)
-#define SMMU_CBn_TLBIVA_AARCH_32		(0x600U)
-#define SMMU_CBn_TLBIVAA_LO			(0x608U)
-#define SMMU_CBn_TLBIVAA_HI			(0x60cU)
-#define SMMU_CBn_TLBIVAA_AARCH_32		(0x608U)
-#define SMMU_CBn_TLBIASID			(0x610U)
-#define SMMU_CBn_TLBIALL			(0x618U)
-#define SMMU_CBn_TLBIVAL_LO			(0x620U)
-#define SMMU_CBn_TLBIVAL_HI			(0x624U)
-#define SMMU_CBn_TLBIVAL_AARCH_32		(0x618U)
-#define SMMU_CBn_TLBIVAAL_LO			(0x628U)
-#define SMMU_CBn_TLBIVAAL_HI			(0x62cU)
-#define SMMU_CBn_TLBIVAAL_AARCH_32		(0x628U)
-#define SMMU_CBn_TLBIIPAS2_LO			(0x630U)
-#define SMMU_CBn_TLBIIPAS2_HI			(0x634U)
-#define SMMU_CBn_TLBIIPAS2L_LO			(0x638U)
-#define SMMU_CBn_TLBIIPAS2L_HI			(0x63cU)
-#define SMMU_CBn_TLBSYNC			(0x7f0U)
-#define SMMU_CBn_TLBSTATUS			(0x7f4U)
-#define SMMU_CBn_ATSR				(0x800U)
-#define SMMU_CBn_PMEVCNTR0			(0xe00U)
-#define SMMU_CBn_PMEVCNTR1			(0xe04U)
-#define SMMU_CBn_PMEVCNTR2			(0xe08U)
-#define SMMU_CBn_PMEVCNTR3			(0xe0cU)
-#define SMMU_CBn_PMEVTYPER0			(0xe80U)
-#define SMMU_CBn_PMEVTYPER1			(0xe84U)
-#define SMMU_CBn_PMEVTYPER2			(0xe88U)
-#define SMMU_CBn_PMEVTYPER3			(0xe8cU)
-#define SMMU_CBn_PMCFGR				(0xf00U)
-#define SMMU_CBn_PMCR				(0xf04U)
-#define SMMU_CBn_PMCEID				(0xf20U)
-#define SMMU_CBn_PMCNTENSE			(0xf40U)
-#define SMMU_CBn_PMCNTENCLR			(0xf44U)
-#define SMMU_CBn_PMCNTENSET			(0xf48U)
-#define SMMU_CBn_PMINTENCLR			(0xf4cU)
-#define SMMU_CBn_PMOVSCLR			(0xf50U)
-#define SMMU_CBn_PMOVSSET			(0xf58U)
-#define SMMU_CBn_PMAUTHSTATUS			(0xfb8U)
-#define SMMU_GNSR0_CR0				(0x0U)
-#define SMMU_GNSR0_CR2				(0x8U)
-#define SMMU_GNSR0_ACR				(0x10U)
-#define SMMU_GNSR0_IDR0				(0x20U)
-#define SMMU_GNSR0_IDR1				(0x24U)
-#define SMMU_GNSR0_IDR2				(0x28U)
-#define SMMU_GNSR0_IDR7				(0x3cU)
-#define SMMU_GNSR0_GFAR_LO			(0x40U)
-#define SMMU_GNSR0_GFAR_HI			(0x44U)
-#define SMMU_GNSR0_GFSR				(0x48U)
-#define SMMU_GNSR0_GFSRRESTORE			(0x4cU)
-#define SMMU_GNSR0_GFSYNR0			(0x50U)
-#define SMMU_GNSR0_GFSYNR1			(0x54U)
-#define SMMU_GNSR0_GFSYNR1_v2			(0x54U)
-#define SMMU_GNSR0_TLBIVMID			(0x64U)
-#define SMMU_GNSR0_TLBIALLNSNH			(0x68U)
-#define SMMU_GNSR0_TLBIALLH			(0x6cU)
-#define SMMU_GNSR0_TLBGSYNC			(0x70U)
-#define SMMU_GNSR0_TLBGSTATUS			(0x74U)
-#define SMMU_GNSR0_TLBIVAH_LO			(0x78U)
-#define SMMU_GNSR0_TLBIVALH64_LO		(0xb0U)
-#define SMMU_GNSR0_TLBIVALH64_HI		(0xb4U)
-#define SMMU_GNSR0_TLBIVMIDS1			(0xb8U)
-#define SMMU_GNSR0_TLBIVAH64_LO			(0xc0U)
-#define SMMU_GNSR0_TLBIVAH64_HI			(0xc4U)
-#define SMMU_GNSR0_SMR0				(0x800U)
-#define SMMU_GNSR0_SMRn				(0x800U)
-#define SMMU_GNSR0_SMR1				(0x804U)
-#define SMMU_GNSR0_SMR2				(0x808U)
-#define SMMU_GNSR0_SMR3				(0x80cU)
-#define SMMU_GNSR0_SMR4				(0x810U)
-#define SMMU_GNSR0_SMR5				(0x814U)
-#define SMMU_GNSR0_SMR6				(0x818U)
-#define SMMU_GNSR0_SMR7				(0x81cU)
-#define SMMU_GNSR0_SMR8				(0x820U)
-#define SMMU_GNSR0_SMR9				(0x824U)
-#define SMMU_GNSR0_SMR10			(0x828U)
-#define SMMU_GNSR0_SMR11			(0x82cU)
-#define SMMU_GNSR0_SMR12			(0x830U)
-#define SMMU_GNSR0_SMR13			(0x834U)
-#define SMMU_GNSR0_SMR14			(0x838U)
-#define SMMU_GNSR0_SMR15			(0x83cU)
-#define SMMU_GNSR0_SMR16			(0x840U)
-#define SMMU_GNSR0_SMR17			(0x844U)
-#define SMMU_GNSR0_SMR18			(0x848U)
-#define SMMU_GNSR0_SMR19			(0x84cU)
-#define SMMU_GNSR0_SMR20			(0x850U)
-#define SMMU_GNSR0_SMR21			(0x854U)
-#define SMMU_GNSR0_SMR22			(0x858U)
-#define SMMU_GNSR0_SMR23			(0x85cU)
-#define SMMU_GNSR0_SMR24			(0x860U)
-#define SMMU_GNSR0_SMR25			(0x864U)
-#define SMMU_GNSR0_SMR26			(0x868U)
-#define SMMU_GNSR0_SMR27			(0x86cU)
-#define SMMU_GNSR0_SMR28			(0x870U)
-#define SMMU_GNSR0_SMR29			(0x874U)
-#define SMMU_GNSR0_SMR30			(0x878U)
-#define SMMU_GNSR0_SMR31			(0x87cU)
-#define SMMU_GNSR0_SMR32			(0x880U)
-#define SMMU_GNSR0_SMR33			(0x884U)
-#define SMMU_GNSR0_SMR34			(0x888U)
-#define SMMU_GNSR0_SMR35			(0x88cU)
-#define SMMU_GNSR0_SMR36			(0x890U)
-#define SMMU_GNSR0_SMR37			(0x894U)
-#define SMMU_GNSR0_SMR38			(0x898U)
-#define SMMU_GNSR0_SMR39			(0x89cU)
-#define SMMU_GNSR0_SMR40			(0x8a0U)
-#define SMMU_GNSR0_SMR41			(0x8a4U)
-#define SMMU_GNSR0_SMR42			(0x8a8U)
-#define SMMU_GNSR0_SMR43			(0x8acU)
-#define SMMU_GNSR0_SMR44			(0x8b0U)
-#define SMMU_GNSR0_SMR45			(0x8b4U)
-#define SMMU_GNSR0_SMR46			(0x8b8U)
-#define SMMU_GNSR0_SMR47			(0x8bcU)
-#define SMMU_GNSR0_SMR48			(0x8c0U)
-#define SMMU_GNSR0_SMR49			(0x8c4U)
-#define SMMU_GNSR0_SMR50			(0x8c8U)
-#define SMMU_GNSR0_SMR51			(0x8ccU)
-#define SMMU_GNSR0_SMR52			(0x8d0U)
-#define SMMU_GNSR0_SMR53			(0x8d4U)
-#define SMMU_GNSR0_SMR54			(0x8d8U)
-#define SMMU_GNSR0_SMR55			(0x8dcU)
-#define SMMU_GNSR0_SMR56			(0x8e0U)
-#define SMMU_GNSR0_SMR57			(0x8e4U)
-#define SMMU_GNSR0_SMR58			(0x8e8U)
-#define SMMU_GNSR0_SMR59			(0x8ecU)
-#define SMMU_GNSR0_SMR60			(0x8f0U)
-#define SMMU_GNSR0_SMR61			(0x8f4U)
-#define SMMU_GNSR0_SMR62			(0x8f8U)
-#define SMMU_GNSR0_SMR63			(0x8fcU)
-#define SMMU_GNSR0_SMR64			(0x900U)
-#define SMMU_GNSR0_SMR65			(0x904U)
-#define SMMU_GNSR0_SMR66			(0x908U)
-#define SMMU_GNSR0_SMR67			(0x90cU)
-#define SMMU_GNSR0_SMR68			(0x910U)
-#define SMMU_GNSR0_SMR69			(0x914U)
-#define SMMU_GNSR0_SMR70			(0x918U)
-#define SMMU_GNSR0_SMR71			(0x91cU)
-#define SMMU_GNSR0_SMR72			(0x920U)
-#define SMMU_GNSR0_SMR73			(0x924U)
-#define SMMU_GNSR0_SMR74			(0x928U)
-#define SMMU_GNSR0_SMR75			(0x92cU)
-#define SMMU_GNSR0_SMR76			(0x930U)
-#define SMMU_GNSR0_SMR77			(0x934U)
-#define SMMU_GNSR0_SMR78			(0x938U)
-#define SMMU_GNSR0_SMR79			(0x93cU)
-#define SMMU_GNSR0_SMR80			(0x940U)
-#define SMMU_GNSR0_SMR81			(0x944U)
-#define SMMU_GNSR0_SMR82			(0x948U)
-#define SMMU_GNSR0_SMR83			(0x94cU)
-#define SMMU_GNSR0_SMR84			(0x950U)
-#define SMMU_GNSR0_SMR85			(0x954U)
-#define SMMU_GNSR0_SMR86			(0x958U)
-#define SMMU_GNSR0_SMR87			(0x95cU)
-#define SMMU_GNSR0_SMR88			(0x960U)
-#define SMMU_GNSR0_SMR89			(0x964U)
-#define SMMU_GNSR0_SMR90			(0x968U)
-#define SMMU_GNSR0_SMR91			(0x96cU)
-#define SMMU_GNSR0_SMR92			(0x970U)
-#define SMMU_GNSR0_SMR93			(0x974U)
-#define SMMU_GNSR0_SMR94			(0x978U)
-#define SMMU_GNSR0_SMR95			(0x97cU)
-#define SMMU_GNSR0_SMR96			(0x980U)
-#define SMMU_GNSR0_SMR97			(0x984U)
-#define SMMU_GNSR0_SMR98			(0x988U)
-#define SMMU_GNSR0_SMR99			(0x98cU)
-#define SMMU_GNSR0_SMR100			(0x990U)
-#define SMMU_GNSR0_SMR101			(0x994U)
-#define SMMU_GNSR0_SMR102			(0x998U)
-#define SMMU_GNSR0_SMR103			(0x99cU)
-#define SMMU_GNSR0_SMR104			(0x9a0U)
-#define SMMU_GNSR0_SMR105			(0x9a4U)
-#define SMMU_GNSR0_SMR106			(0x9a8U)
-#define SMMU_GNSR0_SMR107			(0x9acU)
-#define SMMU_GNSR0_SMR108			(0x9b0U)
-#define SMMU_GNSR0_SMR109			(0x9b4U)
-#define SMMU_GNSR0_SMR110			(0x9b8U)
-#define SMMU_GNSR0_SMR111			(0x9bcU)
-#define SMMU_GNSR0_SMR112			(0x9c0U)
-#define SMMU_GNSR0_SMR113			(0x9c4U)
-#define SMMU_GNSR0_SMR114			(0x9c8U)
-#define SMMU_GNSR0_SMR115			(0x9ccU)
-#define SMMU_GNSR0_SMR116			(0x9d0U)
-#define SMMU_GNSR0_SMR117			(0x9d4U)
-#define SMMU_GNSR0_SMR118			(0x9d8U)
-#define SMMU_GNSR0_SMR119			(0x9dcU)
-#define SMMU_GNSR0_SMR120			(0x9e0U)
-#define SMMU_GNSR0_SMR121			(0x9e4U)
-#define SMMU_GNSR0_SMR122			(0x9e8U)
-#define SMMU_GNSR0_SMR123			(0x9ecU)
-#define SMMU_GNSR0_SMR124			(0x9f0U)
-#define SMMU_GNSR0_SMR125			(0x9f4U)
-#define SMMU_GNSR0_SMR126			(0x9f8U)
-#define SMMU_GNSR0_SMR127			(0x9fcU)
-#define SMMU_GNSR0_S2CR0			(0xc00U)
-#define SMMU_GNSR0_S2CRn			(0xc00U)
-#define SMMU_GNSR0_S2CRn			(0xc00U)
-#define SMMU_GNSR0_S2CR1			(0xc04U)
-#define SMMU_GNSR0_S2CR2			(0xc08U)
-#define SMMU_GNSR0_S2CR3			(0xc0cU)
-#define SMMU_GNSR0_S2CR4			(0xc10U)
-#define SMMU_GNSR0_S2CR5			(0xc14U)
-#define SMMU_GNSR0_S2CR6			(0xc18U)
-#define SMMU_GNSR0_S2CR7			(0xc1cU)
-#define SMMU_GNSR0_S2CR8			(0xc20U)
-#define SMMU_GNSR0_S2CR9			(0xc24U)
-#define SMMU_GNSR0_S2CR10			(0xc28U)
-#define SMMU_GNSR0_S2CR11			(0xc2cU)
-#define SMMU_GNSR0_S2CR12			(0xc30U)
-#define SMMU_GNSR0_S2CR13			(0xc34U)
-#define SMMU_GNSR0_S2CR14			(0xc38U)
-#define SMMU_GNSR0_S2CR15			(0xc3cU)
-#define SMMU_GNSR0_S2CR16			(0xc40U)
-#define SMMU_GNSR0_S2CR17			(0xc44U)
-#define SMMU_GNSR0_S2CR18			(0xc48U)
-#define SMMU_GNSR0_S2CR19			(0xc4cU)
-#define SMMU_GNSR0_S2CR20			(0xc50U)
-#define SMMU_GNSR0_S2CR21			(0xc54U)
-#define SMMU_GNSR0_S2CR22			(0xc58U)
-#define SMMU_GNSR0_S2CR23			(0xc5cU)
-#define SMMU_GNSR0_S2CR24			(0xc60U)
-#define SMMU_GNSR0_S2CR25			(0xc64U)
-#define SMMU_GNSR0_S2CR26			(0xc68U)
-#define SMMU_GNSR0_S2CR27			(0xc6cU)
-#define SMMU_GNSR0_S2CR28			(0xc70U)
-#define SMMU_GNSR0_S2CR29			(0xc74U)
-#define SMMU_GNSR0_S2CR30			(0xc78U)
-#define SMMU_GNSR0_S2CR31			(0xc7cU)
-#define SMMU_GNSR0_S2CR32			(0xc80U)
-#define SMMU_GNSR0_S2CR33			(0xc84U)
-#define SMMU_GNSR0_S2CR34			(0xc88U)
-#define SMMU_GNSR0_S2CR35			(0xc8cU)
-#define SMMU_GNSR0_S2CR36			(0xc90U)
-#define SMMU_GNSR0_S2CR37			(0xc94U)
-#define SMMU_GNSR0_S2CR38			(0xc98U)
-#define SMMU_GNSR0_S2CR39			(0xc9cU)
-#define SMMU_GNSR0_S2CR40			(0xca0U)
-#define SMMU_GNSR0_S2CR41			(0xca4U)
-#define SMMU_GNSR0_S2CR42			(0xca8U)
-#define SMMU_GNSR0_S2CR43			(0xcacU)
-#define SMMU_GNSR0_S2CR44			(0xcb0U)
-#define SMMU_GNSR0_S2CR45			(0xcb4U)
-#define SMMU_GNSR0_S2CR46			(0xcb8U)
-#define SMMU_GNSR0_S2CR47			(0xcbcU)
-#define SMMU_GNSR0_S2CR48			(0xcc0U)
-#define SMMU_GNSR0_S2CR49			(0xcc4U)
-#define SMMU_GNSR0_S2CR50			(0xcc8U)
-#define SMMU_GNSR0_S2CR51			(0xcccU)
-#define SMMU_GNSR0_S2CR52			(0xcd0U)
-#define SMMU_GNSR0_S2CR53			(0xcd4U)
-#define SMMU_GNSR0_S2CR54			(0xcd8U)
-#define SMMU_GNSR0_S2CR55			(0xcdcU)
-#define SMMU_GNSR0_S2CR56			(0xce0U)
-#define SMMU_GNSR0_S2CR57			(0xce4U)
-#define SMMU_GNSR0_S2CR58			(0xce8U)
-#define SMMU_GNSR0_S2CR59			(0xcecU)
-#define SMMU_GNSR0_S2CR60			(0xcf0U)
-#define SMMU_GNSR0_S2CR61			(0xcf4U)
-#define SMMU_GNSR0_S2CR62			(0xcf8U)
-#define SMMU_GNSR0_S2CR63			(0xcfcU)
-#define SMMU_GNSR0_S2CR64			(0xd00U)
-#define SMMU_GNSR0_S2CR65			(0xd04U)
-#define SMMU_GNSR0_S2CR66			(0xd08U)
-#define SMMU_GNSR0_S2CR67			(0xd0cU)
-#define SMMU_GNSR0_S2CR68			(0xd10U)
-#define SMMU_GNSR0_S2CR69			(0xd14U)
-#define SMMU_GNSR0_S2CR70			(0xd18U)
-#define SMMU_GNSR0_S2CR71			(0xd1cU)
-#define SMMU_GNSR0_S2CR72			(0xd20U)
-#define SMMU_GNSR0_S2CR73			(0xd24U)
-#define SMMU_GNSR0_S2CR74			(0xd28U)
-#define SMMU_GNSR0_S2CR75			(0xd2cU)
-#define SMMU_GNSR0_S2CR76			(0xd30U)
-#define SMMU_GNSR0_S2CR77			(0xd34U)
-#define SMMU_GNSR0_S2CR78			(0xd38U)
-#define SMMU_GNSR0_S2CR79			(0xd3cU)
-#define SMMU_GNSR0_S2CR80			(0xd40U)
-#define SMMU_GNSR0_S2CR81			(0xd44U)
-#define SMMU_GNSR0_S2CR82			(0xd48U)
-#define SMMU_GNSR0_S2CR83			(0xd4cU)
-#define SMMU_GNSR0_S2CR84			(0xd50U)
-#define SMMU_GNSR0_S2CR85			(0xd54U)
-#define SMMU_GNSR0_S2CR86			(0xd58U)
-#define SMMU_GNSR0_S2CR87			(0xd5cU)
-#define SMMU_GNSR0_S2CR88			(0xd60U)
-#define SMMU_GNSR0_S2CR89			(0xd64U)
-#define SMMU_GNSR0_S2CR90			(0xd68U)
-#define SMMU_GNSR0_S2CR91			(0xd6cU)
-#define SMMU_GNSR0_S2CR92			(0xd70U)
-#define SMMU_GNSR0_S2CR93			(0xd74U)
-#define SMMU_GNSR0_S2CR94			(0xd78U)
-#define SMMU_GNSR0_S2CR95			(0xd7cU)
-#define SMMU_GNSR0_S2CR96			(0xd80U)
-#define SMMU_GNSR0_S2CR97			(0xd84U)
-#define SMMU_GNSR0_S2CR98			(0xd88U)
-#define SMMU_GNSR0_S2CR99			(0xd8cU)
-#define SMMU_GNSR0_S2CR100			(0xd90U)
-#define SMMU_GNSR0_S2CR101			(0xd94U)
-#define SMMU_GNSR0_S2CR102			(0xd98U)
-#define SMMU_GNSR0_S2CR103			(0xd9cU)
-#define SMMU_GNSR0_S2CR104			(0xda0U)
-#define SMMU_GNSR0_S2CR105			(0xda4U)
-#define SMMU_GNSR0_S2CR106			(0xda8U)
-#define SMMU_GNSR0_S2CR107			(0xdacU)
-#define SMMU_GNSR0_S2CR108			(0xdb0U)
-#define SMMU_GNSR0_S2CR109			(0xdb4U)
-#define SMMU_GNSR0_S2CR110			(0xdb8U)
-#define SMMU_GNSR0_S2CR111			(0xdbcU)
-#define SMMU_GNSR0_S2CR112			(0xdc0U)
-#define SMMU_GNSR0_S2CR113			(0xdc4U)
-#define SMMU_GNSR0_S2CR114			(0xdc8U)
-#define SMMU_GNSR0_S2CR115			(0xdccU)
-#define SMMU_GNSR0_S2CR116			(0xdd0U)
-#define SMMU_GNSR0_S2CR117			(0xdd4U)
-#define SMMU_GNSR0_S2CR118			(0xdd8U)
-#define SMMU_GNSR0_S2CR119			(0xddcU)
-#define SMMU_GNSR0_S2CR120			(0xde0U)
-#define SMMU_GNSR0_S2CR121			(0xde4U)
-#define SMMU_GNSR0_S2CR122			(0xde8U)
-#define SMMU_GNSR0_S2CR123			(0xdecU)
-#define SMMU_GNSR0_S2CR124			(0xdf0U)
-#define SMMU_GNSR0_S2CR125			(0xdf4U)
-#define SMMU_GNSR0_S2CR126			(0xdf8U)
-#define SMMU_GNSR0_S2CR127			(0xdfcU)
-#define SMMU_GNSR0_PIDR0			(0xfe0U)
-#define SMMU_GNSR0_PIDR1			(0xfe4U)
-#define SMMU_GNSR0_PIDR2			(0xfe8U)
-#define SMMU_GNSR0_PIDR3			(0xfecU)
-#define SMMU_GNSR0_PIDR4			(0xfd0U)
-#define SMMU_GNSR0_PIDR5			(0xfd4U)
-#define SMMU_GNSR0_PIDR6			(0xfd8U)
-#define SMMU_GNSR0_PIDR7			(0xfdcU)
-#define SMMU_GNSR0_CIDR0			(0xff0U)
-#define SMMU_GNSR0_CIDR1			(0xff4U)
-#define SMMU_GNSR0_CIDR2			(0xff8U)
-#define SMMU_GNSR0_CIDR3			(0xffcU)
-#define SMMU_GNSR1_CBAR0			(0x0U)
-#define SMMU_GNSR1_CBARn			(0x0U)
-#define SMMU_GNSR1_CBFRSYNRA0			(0x400U)
-#define SMMU_GNSR1_CBA2R0			(0x800U)
-#define SMMU_GNSR1_CBAR1			(0x4U)
-#define SMMU_GNSR1_CBFRSYNRA1			(0x404U)
-#define SMMU_GNSR1_CBA2R1			(0x804U)
-#define SMMU_GNSR1_CBAR2			(0x8U)
-#define SMMU_GNSR1_CBFRSYNRA2			(0x408U)
-#define SMMU_GNSR1_CBA2R2			(0x808U)
-#define SMMU_GNSR1_CBAR3			(0xcU)
-#define SMMU_GNSR1_CBFRSYNRA3			(0x40cU)
-#define SMMU_GNSR1_CBA2R3			(0x80cU)
-#define SMMU_GNSR1_CBAR4			(0x10U)
-#define SMMU_GNSR1_CBFRSYNRA4			(0x410U)
-#define SMMU_GNSR1_CBA2R4			(0x810U)
-#define SMMU_GNSR1_CBAR5			(0x14U)
-#define SMMU_GNSR1_CBFRSYNRA5			(0x414U)
-#define SMMU_GNSR1_CBA2R5			(0x814U)
-#define SMMU_GNSR1_CBAR6			(0x18U)
-#define SMMU_GNSR1_CBFRSYNRA6			(0x418U)
-#define SMMU_GNSR1_CBA2R6			(0x818U)
-#define SMMU_GNSR1_CBAR7			(0x1cU)
-#define SMMU_GNSR1_CBFRSYNRA7			(0x41cU)
-#define SMMU_GNSR1_CBA2R7			(0x81cU)
-#define SMMU_GNSR1_CBAR8			(0x20U)
-#define SMMU_GNSR1_CBFRSYNRA8			(0x420U)
-#define SMMU_GNSR1_CBA2R8			(0x820U)
-#define SMMU_GNSR1_CBAR9			(0x24U)
-#define SMMU_GNSR1_CBFRSYNRA9			(0x424U)
-#define SMMU_GNSR1_CBA2R9			(0x824U)
-#define SMMU_GNSR1_CBAR10			(0x28U)
-#define SMMU_GNSR1_CBFRSYNRA10			(0x428U)
-#define SMMU_GNSR1_CBA2R10			(0x828U)
-#define SMMU_GNSR1_CBAR11			(0x2cU)
-#define SMMU_GNSR1_CBFRSYNRA11			(0x42cU)
-#define SMMU_GNSR1_CBA2R11			(0x82cU)
-#define SMMU_GNSR1_CBAR12			(0x30U)
-#define SMMU_GNSR1_CBFRSYNRA12			(0x430U)
-#define SMMU_GNSR1_CBA2R12			(0x830U)
-#define SMMU_GNSR1_CBAR13			(0x34U)
-#define SMMU_GNSR1_CBFRSYNRA13			(0x434U)
-#define SMMU_GNSR1_CBA2R13			(0x834U)
-#define SMMU_GNSR1_CBAR14			(0x38U)
-#define SMMU_GNSR1_CBFRSYNRA14			(0x438U)
-#define SMMU_GNSR1_CBA2R14			(0x838U)
-#define SMMU_GNSR1_CBAR15			(0x3cU)
-#define SMMU_GNSR1_CBFRSYNRA15			(0x43cU)
-#define SMMU_GNSR1_CBA2R15			(0x83cU)
-#define SMMU_GNSR1_CBAR16			(0x40U)
-#define SMMU_GNSR1_CBFRSYNRA16			(0x440U)
-#define SMMU_GNSR1_CBA2R16			(0x840U)
-#define SMMU_GNSR1_CBAR17			(0x44U)
-#define SMMU_GNSR1_CBFRSYNRA17			(0x444U)
-#define SMMU_GNSR1_CBA2R17			(0x844U)
-#define SMMU_GNSR1_CBAR18			(0x48U)
-#define SMMU_GNSR1_CBFRSYNRA18			(0x448U)
-#define SMMU_GNSR1_CBA2R18			(0x848U)
-#define SMMU_GNSR1_CBAR19			(0x4cU)
-#define SMMU_GNSR1_CBFRSYNRA19			(0x44cU)
-#define SMMU_GNSR1_CBA2R19			(0x84cU)
-#define SMMU_GNSR1_CBAR20			(0x50U)
-#define SMMU_GNSR1_CBFRSYNRA20			(0x450U)
-#define SMMU_GNSR1_CBA2R20			(0x850U)
-#define SMMU_GNSR1_CBAR21			(0x54U)
-#define SMMU_GNSR1_CBFRSYNRA21			(0x454U)
-#define SMMU_GNSR1_CBA2R21			(0x854U)
-#define SMMU_GNSR1_CBAR22			(0x58U)
-#define SMMU_GNSR1_CBFRSYNRA22			(0x458U)
-#define SMMU_GNSR1_CBA2R22			(0x858U)
-#define SMMU_GNSR1_CBAR23			(0x5cU)
-#define SMMU_GNSR1_CBFRSYNRA23			(0x45cU)
-#define SMMU_GNSR1_CBA2R23			(0x85cU)
-#define SMMU_GNSR1_CBAR24			(0x60U)
-#define SMMU_GNSR1_CBFRSYNRA24			(0x460U)
-#define SMMU_GNSR1_CBA2R24			(0x860U)
-#define SMMU_GNSR1_CBAR25			(0x64U)
-#define SMMU_GNSR1_CBFRSYNRA25			(0x464U)
-#define SMMU_GNSR1_CBA2R25			(0x864U)
-#define SMMU_GNSR1_CBAR26			(0x68U)
-#define SMMU_GNSR1_CBFRSYNRA26			(0x468U)
-#define SMMU_GNSR1_CBA2R26			(0x868U)
-#define SMMU_GNSR1_CBAR27			(0x6cU)
-#define SMMU_GNSR1_CBFRSYNRA27			(0x46cU)
-#define SMMU_GNSR1_CBA2R27			(0x86cU)
-#define SMMU_GNSR1_CBAR28			(0x70U)
-#define SMMU_GNSR1_CBFRSYNRA28			(0x470U)
-#define SMMU_GNSR1_CBA2R28			(0x870U)
-#define SMMU_GNSR1_CBAR29			(0x74U)
-#define SMMU_GNSR1_CBFRSYNRA29			(0x474U)
-#define SMMU_GNSR1_CBA2R29			(0x874U)
-#define SMMU_GNSR1_CBAR30			(0x78U)
-#define SMMU_GNSR1_CBFRSYNRA30			(0x478U)
-#define SMMU_GNSR1_CBA2R30			(0x878U)
-#define SMMU_GNSR1_CBAR31			(0x7cU)
-#define SMMU_GNSR1_CBFRSYNRA31			(0x47cU)
-#define SMMU_GNSR1_CBA2R31			(0x87cU)
-#define SMMU_GNSR1_CBAR32			(0x80U)
-#define SMMU_GNSR1_CBFRSYNRA32			(0x480U)
-#define SMMU_GNSR1_CBA2R32			(0x880U)
-#define SMMU_GNSR1_CBAR33			(0x84U)
-#define SMMU_GNSR1_CBFRSYNRA33			(0x484U)
-#define SMMU_GNSR1_CBA2R33			(0x884U)
-#define SMMU_GNSR1_CBAR34			(0x88U)
-#define SMMU_GNSR1_CBFRSYNRA34			(0x488U)
-#define SMMU_GNSR1_CBA2R34			(0x888U)
-#define SMMU_GNSR1_CBAR35			(0x8cU)
-#define SMMU_GNSR1_CBFRSYNRA35			(0x48cU)
-#define SMMU_GNSR1_CBA2R35			(0x88cU)
-#define SMMU_GNSR1_CBAR36			(0x90U)
-#define SMMU_GNSR1_CBFRSYNRA36			(0x490U)
-#define SMMU_GNSR1_CBA2R36			(0x890U)
-#define SMMU_GNSR1_CBAR37			(0x94U)
-#define SMMU_GNSR1_CBFRSYNRA37			(0x494U)
-#define SMMU_GNSR1_CBA2R37			(0x894U)
-#define SMMU_GNSR1_CBAR38			(0x98U)
-#define SMMU_GNSR1_CBFRSYNRA38			(0x498U)
-#define SMMU_GNSR1_CBA2R38			(0x898U)
-#define SMMU_GNSR1_CBAR39			(0x9cU)
-#define SMMU_GNSR1_CBFRSYNRA39			(0x49cU)
-#define SMMU_GNSR1_CBA2R39			(0x89cU)
-#define SMMU_GNSR1_CBAR40			(0xa0U)
-#define SMMU_GNSR1_CBFRSYNRA40			(0x4a0U)
-#define SMMU_GNSR1_CBA2R40			(0x8a0U)
-#define SMMU_GNSR1_CBAR41			(0xa4U)
-#define SMMU_GNSR1_CBFRSYNRA41			(0x4a4U)
-#define SMMU_GNSR1_CBA2R41			(0x8a4U)
-#define SMMU_GNSR1_CBAR42			(0xa8U)
-#define SMMU_GNSR1_CBFRSYNRA42			(0x4a8U)
-#define SMMU_GNSR1_CBA2R42			(0x8a8U)
-#define SMMU_GNSR1_CBAR43			(0xacU)
-#define SMMU_GNSR1_CBFRSYNRA43			(0x4acU)
-#define SMMU_GNSR1_CBA2R43			(0x8acU)
-#define SMMU_GNSR1_CBAR44			(0xb0U)
-#define SMMU_GNSR1_CBFRSYNRA44			(0x4b0U)
-#define SMMU_GNSR1_CBA2R44			(0x8b0U)
-#define SMMU_GNSR1_CBAR45			(0xb4U)
-#define SMMU_GNSR1_CBFRSYNRA45			(0x4b4U)
-#define SMMU_GNSR1_CBA2R45			(0x8b4U)
-#define SMMU_GNSR1_CBAR46			(0xb8U)
-#define SMMU_GNSR1_CBFRSYNRA46			(0x4b8U)
-#define SMMU_GNSR1_CBA2R46			(0x8b8U)
-#define SMMU_GNSR1_CBAR47			(0xbcU)
-#define SMMU_GNSR1_CBFRSYNRA47			(0x4bcU)
-#define SMMU_GNSR1_CBA2R47			(0x8bcU)
-#define SMMU_GNSR1_CBAR48			(0xc0U)
-#define SMMU_GNSR1_CBFRSYNRA48			(0x4c0U)
-#define SMMU_GNSR1_CBA2R48			(0x8c0U)
-#define SMMU_GNSR1_CBAR49			(0xc4U)
-#define SMMU_GNSR1_CBFRSYNRA49			(0x4c4U)
-#define SMMU_GNSR1_CBA2R49			(0x8c4U)
-#define SMMU_GNSR1_CBAR50			(0xc8U)
-#define SMMU_GNSR1_CBFRSYNRA50			(0x4c8U)
-#define SMMU_GNSR1_CBA2R50			(0x8c8U)
-#define SMMU_GNSR1_CBAR51			(0xccU)
-#define SMMU_GNSR1_CBFRSYNRA51			(0x4ccU)
-#define SMMU_GNSR1_CBA2R51			(0x8ccU)
-#define SMMU_GNSR1_CBAR52			(0xd0U)
-#define SMMU_GNSR1_CBFRSYNRA52			(0x4d0U)
-#define SMMU_GNSR1_CBA2R52			(0x8d0U)
-#define SMMU_GNSR1_CBAR53			(0xd4U)
-#define SMMU_GNSR1_CBFRSYNRA53			(0x4d4U)
-#define SMMU_GNSR1_CBA2R53			(0x8d4U)
-#define SMMU_GNSR1_CBAR54			(0xd8U)
-#define SMMU_GNSR1_CBFRSYNRA54			(0x4d8U)
-#define SMMU_GNSR1_CBA2R54			(0x8d8U)
-#define SMMU_GNSR1_CBAR55			(0xdcU)
-#define SMMU_GNSR1_CBFRSYNRA55			(0x4dcU)
-#define SMMU_GNSR1_CBA2R55			(0x8dcU)
-#define SMMU_GNSR1_CBAR56			(0xe0U)
-#define SMMU_GNSR1_CBFRSYNRA56			(0x4e0U)
-#define SMMU_GNSR1_CBA2R56			(0x8e0U)
-#define SMMU_GNSR1_CBAR57			(0xe4U)
-#define SMMU_GNSR1_CBFRSYNRA57			(0x4e4U)
-#define SMMU_GNSR1_CBA2R57			(0x8e4U)
-#define SMMU_GNSR1_CBAR58			(0xe8U)
-#define SMMU_GNSR1_CBFRSYNRA58			(0x4e8U)
-#define SMMU_GNSR1_CBA2R58			(0x8e8U)
-#define SMMU_GNSR1_CBAR59			(0xecU)
-#define SMMU_GNSR1_CBFRSYNRA59			(0x4ecU)
-#define SMMU_GNSR1_CBA2R59			(0x8ecU)
-#define SMMU_GNSR1_CBAR60			(0xf0U)
-#define SMMU_GNSR1_CBFRSYNRA60			(0x4f0U)
-#define SMMU_GNSR1_CBA2R60			(0x8f0U)
-#define SMMU_GNSR1_CBAR61			(0xf4U)
-#define SMMU_GNSR1_CBFRSYNRA61			(0x4f4U)
-#define SMMU_GNSR1_CBA2R61			(0x8f4U)
-#define SMMU_GNSR1_CBAR62			(0xf8U)
-#define SMMU_GNSR1_CBFRSYNRA62			(0x4f8U)
-#define SMMU_GNSR1_CBA2R62			(0x8f8U)
-#define SMMU_GNSR1_CBAR63			(0xfcU)
-#define SMMU_GNSR1_CBFRSYNRA63			(0x4fcU)
-#define SMMU_GNSR1_CBA2R63			(0x8fcU)
 
 /*******************************************************************************
  * SMMU Global Secure Aux. Configuration Register
@@ -581,269 +23,69 @@
 #define SMMU_GSR0_PGSIZE_SHIFT			16U
 #define SMMU_GSR0_PGSIZE_4K			(0U << SMMU_GSR0_PGSIZE_SHIFT)
 #define SMMU_GSR0_PGSIZE_64K			(1U << SMMU_GSR0_PGSIZE_SHIFT)
-#define SMMU_ACR_CACHE_LOCK_ENABLE_BIT		(1U << 26)
+#define SMMU_ACR_CACHE_LOCK_ENABLE_BIT		(1ULL << 26U)
+#define SMMU_GSR0_PER				(0x20200U)
 
 /*******************************************************************************
  * SMMU Global Aux. Control Register
  ******************************************************************************/
 #define SMMU_CBn_ACTLR_CPRE_BIT			(1ULL << 1U)
 
-/*******************************************************************************
- * SMMU configuration constants
- ******************************************************************************/
-#define ID1_PAGESIZE				(1U << 31U)
-#define ID1_NUMPAGENDXB_SHIFT			28U
-#define ID1_NUMPAGENDXB_MASK			7U
-#define ID1_NUMS2CB_SHIFT			16U
-#define ID1_NUMS2CB_MASK			0xffU
-#define ID1_NUMCB_SHIFT				0U
-#define ID1_NUMCB_MASK				0xffU
-#define PGSHIFT					16U
-#define CB_SIZE					0x800000U
-
-typedef struct smmu_regs {
-	uint32_t reg;
-	uint32_t val;
-} smmu_regs_t;
-
-#define mc_make_sid_override_cfg(name) \
-	{ \
-		.reg = TEGRA_MC_STREAMID_BASE + MC_STREAMID_OVERRIDE_CFG_ ## name, \
-		.val = 0x00000000U, \
-	}
-
-#define mc_make_sid_security_cfg(name) \
-	{ \
-		.reg = TEGRA_MC_STREAMID_BASE + MC_STREAMID_OVERRIDE_TO_SECURITY_CFG(MC_STREAMID_OVERRIDE_CFG_ ## name), \
-		.val = 0x00000000U, \
-	}
-
-#define smmu_make_gnsr0_sec_cfg(base_addr, name) \
-	{ \
-		.reg = base_addr + SMMU_GNSR0_ ## name, \
-		.val = 0x00000000U, \
-	}
-
-/*
- * On ARM-SMMU, conditional offset to access secure aliases of non-secure registers
- * is 0x400. So, add it to register address
- */
-#define smmu_make_gnsr0_nsec_cfg(base_addr, name) \
-	{ \
-		.reg = base_addr + 0x400U + SMMU_GNSR0_ ## name, \
-		.val = 0x00000000U, \
-	}
-
-#define smmu_make_gnsr0_smr_cfg(base_addr, n) \
-	{ \
-		.reg = base_addr + SMMU_GNSR0_SMR ## n, \
-		.val = 0x00000000U, \
-	}
+/* SMMU IDs currently supported by the driver */
+enum {
+	TEGRA_SMMU0 = 0U,
+	TEGRA_SMMU1 = 1U,
+	TEGRA_SMMU2 = 2U
+};
 
-#define smmu_make_gnsr0_s2cr_cfg(base_addr, n) \
-	{ \
-		.reg = base_addr + SMMU_GNSR0_S2CR ## n, \
-		.val = 0x00000000U, \
-	}
+static inline uint32_t tegra_smmu_read_32(uint32_t smmu_id, uint32_t off)
+{
+	uint32_t ret = 0U;
 
-#define smmu_make_gnsr1_cbar_cfg(base_addr, n) \
-	{ \
-		.reg = base_addr + (1U << PGSHIFT) + SMMU_GNSR1_CBAR ## n, \
-		.val = 0x00000000U, \
+#if defined(TEGRA_SMMU0_BASE)
+	if (smmu_id == TEGRA_SMMU0) {
+		ret = mmio_read_32(TEGRA_SMMU0_BASE + (uint64_t)off);
 	}
+#endif
 
-#define smmu_make_gnsr1_cba2r_cfg(base_addr, n) \
-	{ \
-		.reg = base_addr + (1U << PGSHIFT) + SMMU_GNSR1_CBA2R ## n, \
-		.val = 0x00000000U, \
+#if defined(TEGRA_SMMU1_BASE)
+	if (smmu_id == TEGRA_SMMU1) {
+		ret = mmio_read_32(TEGRA_SMMU1_BASE + (uint64_t)off);
 	}
+#endif
 
-#define smmu_make_cb_cfg(base_addr, name, n) \
-	{ \
-		.reg = base_addr + (CB_SIZE >> 1) + (n * (1 << PGSHIFT)) \
-			+ SMMU_CBn_ ## name, \
-		.val = 0x00000000U, \
+#if defined(TEGRA_SMMU2_BASE)
+	if (smmu_id == TEGRA_SMMU2) {
+		ret = mmio_read_32(TEGRA_SMMU2_BASE + (uint64_t)off);
 	}
+#endif
 
-#define smmu_make_smrg_group(base_addr, n)	\
-	smmu_make_gnsr0_smr_cfg(base_addr, n),	\
-	smmu_make_gnsr0_s2cr_cfg(base_addr, n),	\
-	smmu_make_gnsr1_cbar_cfg(base_addr, n),	\
-	smmu_make_gnsr1_cba2r_cfg(base_addr, n)	/* don't put "," here. */
+	return ret;
+}
 
-#define smmu_make_cb_group(base_addr, n)		\
-	smmu_make_cb_cfg(base_addr, SCTLR, n),	\
-	smmu_make_cb_cfg(base_addr, TCR2, n),	\
-	smmu_make_cb_cfg(base_addr, TTBR0_LO, n),	\
-	smmu_make_cb_cfg(base_addr, TTBR0_HI, n),	\
-	smmu_make_cb_cfg(base_addr, TCR, n),	\
-	smmu_make_cb_cfg(base_addr, PRRR_MAIR0, n),\
-	smmu_make_cb_cfg(base_addr, FSR, n),	\
-	smmu_make_cb_cfg(base_addr, FAR_LO, n),	\
-	smmu_make_cb_cfg(base_addr, FAR_HI, n),	\
-	smmu_make_cb_cfg(base_addr, FSYNR0, n)	/* don't put "," here. */
-
-#define smmu_make_cfg(base_addr)			\
-	smmu_make_gnsr0_nsec_cfg(base_addr, CR0),	\
-	smmu_make_gnsr0_sec_cfg(base_addr, IDR0),	\
-	smmu_make_gnsr0_sec_cfg(base_addr, IDR1),	\
-	smmu_make_gnsr0_sec_cfg(base_addr, IDR2),	\
-	smmu_make_gnsr0_nsec_cfg(base_addr, GFSR),	\
-	smmu_make_gnsr0_nsec_cfg(base_addr, GFSYNR0),	\
-	smmu_make_gnsr0_nsec_cfg(base_addr, GFSYNR1),	\
-	smmu_make_gnsr0_nsec_cfg(base_addr, TLBGSTATUS),\
-	smmu_make_gnsr0_nsec_cfg(base_addr, PIDR2),	\
-	smmu_make_smrg_group(base_addr, 0),		\
-	smmu_make_smrg_group(base_addr, 1),		\
-	smmu_make_smrg_group(base_addr, 2),		\
-	smmu_make_smrg_group(base_addr, 3),		\
-	smmu_make_smrg_group(base_addr, 4),		\
-	smmu_make_smrg_group(base_addr, 5),		\
-	smmu_make_smrg_group(base_addr, 6),		\
-	smmu_make_smrg_group(base_addr, 7),		\
-	smmu_make_smrg_group(base_addr, 8),		\
-	smmu_make_smrg_group(base_addr, 9),		\
-	smmu_make_smrg_group(base_addr, 10),		\
-	smmu_make_smrg_group(base_addr, 11),		\
-	smmu_make_smrg_group(base_addr, 12),		\
-	smmu_make_smrg_group(base_addr, 13),		\
-	smmu_make_smrg_group(base_addr, 14),		\
-	smmu_make_smrg_group(base_addr, 15),		\
-	smmu_make_smrg_group(base_addr, 16),		\
-	smmu_make_smrg_group(base_addr, 17),		\
-	smmu_make_smrg_group(base_addr, 18),		\
-	smmu_make_smrg_group(base_addr, 19),		\
-	smmu_make_smrg_group(base_addr, 20),		\
-	smmu_make_smrg_group(base_addr, 21),		\
-	smmu_make_smrg_group(base_addr, 22),		\
-	smmu_make_smrg_group(base_addr, 23),		\
-	smmu_make_smrg_group(base_addr, 24),		\
-	smmu_make_smrg_group(base_addr, 25),		\
-	smmu_make_smrg_group(base_addr, 26),		\
-	smmu_make_smrg_group(base_addr, 27),		\
-	smmu_make_smrg_group(base_addr, 28),		\
-	smmu_make_smrg_group(base_addr, 29),		\
-	smmu_make_smrg_group(base_addr, 30),		\
-	smmu_make_smrg_group(base_addr, 31),		\
-	smmu_make_smrg_group(base_addr, 32),		\
-	smmu_make_smrg_group(base_addr, 33),		\
-	smmu_make_smrg_group(base_addr, 34),		\
-	smmu_make_smrg_group(base_addr, 35),		\
-	smmu_make_smrg_group(base_addr, 36),		\
-	smmu_make_smrg_group(base_addr, 37),		\
-	smmu_make_smrg_group(base_addr, 38),		\
-	smmu_make_smrg_group(base_addr, 39),		\
-	smmu_make_smrg_group(base_addr, 40),		\
-	smmu_make_smrg_group(base_addr, 41),		\
-	smmu_make_smrg_group(base_addr, 42),		\
-	smmu_make_smrg_group(base_addr, 43),		\
-	smmu_make_smrg_group(base_addr, 44),		\
-	smmu_make_smrg_group(base_addr, 45),		\
-	smmu_make_smrg_group(base_addr, 46),		\
-	smmu_make_smrg_group(base_addr, 47),		\
-	smmu_make_smrg_group(base_addr, 48),		\
-	smmu_make_smrg_group(base_addr, 49),		\
-	smmu_make_smrg_group(base_addr, 50),		\
-	smmu_make_smrg_group(base_addr, 51),		\
-	smmu_make_smrg_group(base_addr, 52),		\
-	smmu_make_smrg_group(base_addr, 53),		\
-	smmu_make_smrg_group(base_addr, 54),		\
-	smmu_make_smrg_group(base_addr, 55),		\
-	smmu_make_smrg_group(base_addr, 56),		\
-	smmu_make_smrg_group(base_addr, 57),		\
-	smmu_make_smrg_group(base_addr, 58),		\
-	smmu_make_smrg_group(base_addr, 59),		\
-	smmu_make_smrg_group(base_addr, 60),		\
-	smmu_make_smrg_group(base_addr, 61),		\
-	smmu_make_smrg_group(base_addr, 62),		\
-	smmu_make_smrg_group(base_addr, 63),		\
-	smmu_make_cb_group(base_addr, 0),		\
-	smmu_make_cb_group(base_addr, 1),		\
-	smmu_make_cb_group(base_addr, 2),		\
-	smmu_make_cb_group(base_addr, 3),		\
-	smmu_make_cb_group(base_addr, 4),		\
-	smmu_make_cb_group(base_addr, 5),		\
-	smmu_make_cb_group(base_addr, 6),		\
-	smmu_make_cb_group(base_addr, 7),		\
-	smmu_make_cb_group(base_addr, 8),		\
-	smmu_make_cb_group(base_addr, 9),		\
-	smmu_make_cb_group(base_addr, 10),		\
-	smmu_make_cb_group(base_addr, 11),		\
-	smmu_make_cb_group(base_addr, 12),		\
-	smmu_make_cb_group(base_addr, 13),		\
-	smmu_make_cb_group(base_addr, 14),		\
-	smmu_make_cb_group(base_addr, 15),		\
-	smmu_make_cb_group(base_addr, 16),		\
-	smmu_make_cb_group(base_addr, 17),		\
-	smmu_make_cb_group(base_addr, 18),		\
-	smmu_make_cb_group(base_addr, 19),		\
-	smmu_make_cb_group(base_addr, 20),		\
-	smmu_make_cb_group(base_addr, 21),		\
-	smmu_make_cb_group(base_addr, 22),		\
-	smmu_make_cb_group(base_addr, 23),		\
-	smmu_make_cb_group(base_addr, 24),		\
-	smmu_make_cb_group(base_addr, 25),		\
-	smmu_make_cb_group(base_addr, 26),		\
-	smmu_make_cb_group(base_addr, 27),		\
-	smmu_make_cb_group(base_addr, 28),		\
-	smmu_make_cb_group(base_addr, 29),		\
-	smmu_make_cb_group(base_addr, 30),		\
-	smmu_make_cb_group(base_addr, 31),		\
-	smmu_make_cb_group(base_addr, 32),		\
-	smmu_make_cb_group(base_addr, 33),		\
-	smmu_make_cb_group(base_addr, 34),		\
-	smmu_make_cb_group(base_addr, 35),		\
-	smmu_make_cb_group(base_addr, 36),		\
-	smmu_make_cb_group(base_addr, 37),		\
-	smmu_make_cb_group(base_addr, 38),		\
-	smmu_make_cb_group(base_addr, 39),		\
-	smmu_make_cb_group(base_addr, 40),		\
-	smmu_make_cb_group(base_addr, 41),		\
-	smmu_make_cb_group(base_addr, 42),		\
-	smmu_make_cb_group(base_addr, 43),		\
-	smmu_make_cb_group(base_addr, 44),		\
-	smmu_make_cb_group(base_addr, 45),		\
-	smmu_make_cb_group(base_addr, 46),		\
-	smmu_make_cb_group(base_addr, 47),		\
-	smmu_make_cb_group(base_addr, 48),		\
-	smmu_make_cb_group(base_addr, 49),		\
-	smmu_make_cb_group(base_addr, 50),		\
-	smmu_make_cb_group(base_addr, 51),		\
-	smmu_make_cb_group(base_addr, 52),		\
-	smmu_make_cb_group(base_addr, 53),		\
-	smmu_make_cb_group(base_addr, 54),		\
-	smmu_make_cb_group(base_addr, 55),		\
-	smmu_make_cb_group(base_addr, 56),		\
-	smmu_make_cb_group(base_addr, 57),		\
-	smmu_make_cb_group(base_addr, 58),		\
-	smmu_make_cb_group(base_addr, 59),		\
-	smmu_make_cb_group(base_addr, 60),		\
-	smmu_make_cb_group(base_addr, 61),		\
-	smmu_make_cb_group(base_addr, 62),		\
-	smmu_make_cb_group(base_addr, 63)	/* don't put "," here. */
-
-#define smmu_bypass_cfg \
-	{ \
-		.reg = TEGRA_MC_BASE + MC_SMMU_BYPASS_CONFIG, \
-		.val = 0x00000000U, \
+static inline void tegra_smmu_write_32(uint32_t smmu_id,
+			uint32_t off, uint32_t val)
+{
+#if defined(TEGRA_SMMU0_BASE)
+	if (smmu_id == TEGRA_SMMU0) {
+		mmio_write_32(TEGRA_SMMU0_BASE + (uint64_t)off, val);
 	}
+#endif
 
-#define _START_OF_TABLE_ \
-	{ \
-		.reg = 0xCAFE05C7U, \
-		.val = 0x00000000U, \
+#if defined(TEGRA_SMMU1_BASE)
+	if (smmu_id == TEGRA_SMMU1) {
+		mmio_write_32(TEGRA_SMMU1_BASE + (uint64_t)off, val);
 	}
+#endif
 
-#define _END_OF_TABLE_ \
-	{ \
-		.reg = 0xFFFFFFFFU, \
-		.val = 0xFFFFFFFFU, \
+#if defined(TEGRA_SMMU2_BASE)
+	if (smmu_id == TEGRA_SMMU2) {
+		mmio_write_32(TEGRA_SMMU2_BASE + (uint64_t)off, val);
 	}
-
+#endif
+}
 
 void tegra_smmu_init(void);
-void tegra_smmu_save_context(uint64_t smmu_ctx_addr);
-smmu_regs_t *plat_get_smmu_ctx(void);
 uint32_t plat_get_num_smmu_devices(void);
 
 #endif /* SMMU_H */
diff --git a/plat/nvidia/tegra/include/t186/tegra186_private.h b/plat/nvidia/tegra/include/t186/tegra186_private.h
index 9e2c02b..60174ab 100644
--- a/plat/nvidia/tegra/include/t186/tegra186_private.h
+++ b/plat/nvidia/tegra/include/t186/tegra186_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,7 +10,7 @@
 void tegra186_cpu_reset_handler(void);
 uint64_t tegra186_get_cpu_reset_handler_base(void);
 uint64_t tegra186_get_cpu_reset_handler_size(void);
-uint64_t tegra186_get_smmu_ctx_offset(void);
+uint64_t tegra186_get_mc_ctx_offset(void);
 void tegra186_set_system_suspend_entry(void);
 
 #endif /* TEGRA186_PRIVATE_H */
diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h
index 3d037e1..1da9b46 100644
--- a/plat/nvidia/tegra/include/t186/tegra_def.h
+++ b/plat/nvidia/tegra/include/t186/tegra_def.h
@@ -73,6 +73,12 @@
 #define TEGRA186_SEC_IRQ_TARGET_MASK	U(0xF3) /* 4 A57 - 2 Denver */
 
 /*******************************************************************************
+ * Clock identifier for the SE device
+ ******************************************************************************/
+#define TEGRA186_CLK_SE			U(103)
+#define TEGRA_CLK_SE			TEGRA186_CLK_SE
+
+/*******************************************************************************
  * Tegra Miscellanous register constants
  ******************************************************************************/
 #define TEGRA_MISC_BASE			U(0x00100000)
@@ -269,8 +275,8 @@
 #define SCRATCH_RESET_VECTOR_LO		SECURE_SCRATCH_RSV1_LO
 #define SCRATCH_RESET_VECTOR_HI		SECURE_SCRATCH_RSV1_HI
 #define SCRATCH_SECURE_BOOTP_FCFG	SECURE_SCRATCH_RSV6
-#define SCRATCH_SMMU_TABLE_ADDR_LO	SECURE_SCRATCH_RSV11_LO
-#define SCRATCH_SMMU_TABLE_ADDR_HI	SECURE_SCRATCH_RSV11_HI
+#define SCRATCH_MC_TABLE_ADDR_LO	SECURE_SCRATCH_RSV11_LO
+#define SCRATCH_MC_TABLE_ADDR_HI	SECURE_SCRATCH_RSV11_HI
 #define SCRATCH_BL31_PARAMS_ADDR	SECURE_SCRATCH_RSV53_LO
 #define SCRATCH_BL31_PLAT_PARAMS_ADDR	SECURE_SCRATCH_RSV53_HI
 #define SCRATCH_TZDRAM_ADDR_LO		SECURE_SCRATCH_RSV55_LO
diff --git a/plat/nvidia/tegra/include/t194/tegra194_private.h b/plat/nvidia/tegra/include/t194/tegra194_private.h
index 8f1deb2..c5a51e9 100644
--- a/plat/nvidia/tegra/include/t194/tegra194_private.h
+++ b/plat/nvidia/tegra/include/t194/tegra194_private.h
@@ -10,7 +10,7 @@
 void tegra194_cpu_reset_handler(void);
 uint64_t tegra194_get_cpu_reset_handler_base(void);
 uint64_t tegra194_get_cpu_reset_handler_size(void);
-uint64_t tegra194_get_smmu_ctx_offset(void);
+uint64_t tegra194_get_mc_ctx_offset(void);
 void tegra194_set_system_suspend_entry(void);
 
 #endif /* TEGRA194_PRIVATE_H */
diff --git a/plat/nvidia/tegra/include/t194/tegra_def.h b/plat/nvidia/tegra/include/t194/tegra_def.h
index a58ae9d..dc06445 100644
--- a/plat/nvidia/tegra/include/t194/tegra_def.h
+++ b/plat/nvidia/tegra/include/t194/tegra_def.h
@@ -43,6 +43,12 @@
 #define TEGRA194_SEC_IRQ_TARGET_MASK	U(0xFF) /* 8 Carmel */
 
 /*******************************************************************************
+ * Clock identifier for the SE device
+ ******************************************************************************/
+#define TEGRA194_CLK_SE			U(124)
+#define TEGRA_CLK_SE			TEGRA194_CLK_SE
+
+/*******************************************************************************
  * Tegra Miscellanous register constants
  ******************************************************************************/
 #define TEGRA_MISC_BASE			U(0x00100000)
@@ -197,6 +203,16 @@
  * Tegra scratch registers constants
  ******************************************************************************/
 #define TEGRA_SCRATCH_BASE		U(0x0C390000)
+#define  SECURE_SCRATCH_RSV68_LO	U(0x284)
+#define  SECURE_SCRATCH_RSV68_HI	U(0x288)
+#define  SECURE_SCRATCH_RSV69_LO	U(0x28C)
+#define  SECURE_SCRATCH_RSV69_HI	U(0x290)
+#define  SECURE_SCRATCH_RSV70_LO	U(0x294)
+#define  SECURE_SCRATCH_RSV70_HI	U(0x298)
+#define  SECURE_SCRATCH_RSV71_LO	U(0x29C)
+#define  SECURE_SCRATCH_RSV71_HI	U(0x2A0)
+#define  SECURE_SCRATCH_RSV72_LO	U(0x2A4)
+#define  SECURE_SCRATCH_RSV72_HI	U(0x2A8)
 #define  SECURE_SCRATCH_RSV75   	U(0x2BC)
 #define  SECURE_SCRATCH_RSV81_LO	U(0x2EC)
 #define  SECURE_SCRATCH_RSV81_HI	U(0x2F0)
@@ -215,8 +231,8 @@
 #define  SCRATCH_BL31_PLAT_PARAMS_HI_ADDR_SHIFT U(16)
 #define SCRATCH_BL31_PLAT_PARAMS_LO_ADDR SECURE_SCRATCH_RSV81_HI
 #define SCRATCH_SECURE_BOOTP_FCFG	SECURE_SCRATCH_RSV97
-#define SCRATCH_SMMU_TABLE_ADDR_LO	SECURE_SCRATCH_RSV99_LO
-#define SCRATCH_SMMU_TABLE_ADDR_HI	SECURE_SCRATCH_RSV99_HI
+#define SCRATCH_MC_TABLE_ADDR_LO	SECURE_SCRATCH_RSV99_LO
+#define SCRATCH_MC_TABLE_ADDR_HI	SECURE_SCRATCH_RSV99_HI
 #define SCRATCH_RESET_VECTOR_LO		SECURE_SCRATCH_RSV109_LO
 #define SCRATCH_RESET_VECTOR_HI		SECURE_SCRATCH_RSV109_HI
 
diff --git a/plat/nvidia/tegra/include/t210/tegra_def.h b/plat/nvidia/tegra/include/t210/tegra_def.h
index e8bce5e..f3013a8 100644
--- a/plat/nvidia/tegra/include/t210/tegra_def.h
+++ b/plat/nvidia/tegra/include/t210/tegra_def.h
@@ -44,6 +44,11 @@
 #define SC7ENTRY_FW_HEADER_SIZE_BYTES	U(0x400)
 
 /*******************************************************************************
+ * Counter-timer physical secure timer PPI
+ ******************************************************************************/
+#define TEGRA210_TIMER1_IRQ		32
+
+/*******************************************************************************
  * iRAM memory constants
  ******************************************************************************/
 #define TEGRA_IRAM_BASE			U(0x40000000)
diff --git a/plat/nvidia/tegra/soc/t186/plat_memctrl.c b/plat/nvidia/tegra/soc/t186/plat_memctrl.c
index a97496b..09377bb 100644
--- a/plat/nvidia/tegra/soc/t186/plat_memctrl.c
+++ b/plat/nvidia/tegra/soc/t186/plat_memctrl.c
@@ -516,6 +516,171 @@
 	}
 }
 
+
+/*******************************************************************************
+ * Array to hold MC context for Tegra186
+ ******************************************************************************/
+static __attribute__((aligned(16))) mc_regs_t tegra186_mc_context[] = {
+	_START_OF_TABLE_,
+	mc_make_sid_security_cfg(SCEW),
+	mc_make_sid_security_cfg(AFIR),
+	mc_make_sid_security_cfg(NVDISPLAYR1),
+	mc_make_sid_security_cfg(XUSB_DEVR),
+	mc_make_sid_security_cfg(VICSRD1),
+	mc_make_sid_security_cfg(NVENCSWR),
+	mc_make_sid_security_cfg(TSECSRDB),
+	mc_make_sid_security_cfg(AXISW),
+	mc_make_sid_security_cfg(SDMMCWAB),
+	mc_make_sid_security_cfg(AONDMAW),
+	mc_make_sid_security_cfg(GPUSWR2),
+	mc_make_sid_security_cfg(SATAW),
+	mc_make_sid_security_cfg(UFSHCW),
+	mc_make_sid_security_cfg(AFIW),
+	mc_make_sid_security_cfg(SDMMCR),
+	mc_make_sid_security_cfg(SCEDMAW),
+	mc_make_sid_security_cfg(UFSHCR),
+	mc_make_sid_security_cfg(SDMMCWAA),
+	mc_make_sid_security_cfg(APEDMAW),
+	mc_make_sid_security_cfg(SESWR),
+	mc_make_sid_security_cfg(MPCORER),
+	mc_make_sid_security_cfg(PTCR),
+	mc_make_sid_security_cfg(BPMPW),
+	mc_make_sid_security_cfg(ETRW),
+	mc_make_sid_security_cfg(GPUSRD),
+	mc_make_sid_security_cfg(VICSWR),
+	mc_make_sid_security_cfg(SCEDMAR),
+	mc_make_sid_security_cfg(HDAW),
+	mc_make_sid_security_cfg(ISPWA),
+	mc_make_sid_security_cfg(EQOSW),
+	mc_make_sid_security_cfg(XUSB_HOSTW),
+	mc_make_sid_security_cfg(TSECSWR),
+	mc_make_sid_security_cfg(SDMMCRAA),
+	mc_make_sid_security_cfg(APER),
+	mc_make_sid_security_cfg(VIW),
+	mc_make_sid_security_cfg(APEW),
+	mc_make_sid_security_cfg(AXISR),
+	mc_make_sid_security_cfg(SDMMCW),
+	mc_make_sid_security_cfg(BPMPDMAW),
+	mc_make_sid_security_cfg(ISPRA),
+	mc_make_sid_security_cfg(NVDECSWR),
+	mc_make_sid_security_cfg(XUSB_DEVW),
+	mc_make_sid_security_cfg(NVDECSRD),
+	mc_make_sid_security_cfg(MPCOREW),
+	mc_make_sid_security_cfg(NVDISPLAYR),
+	mc_make_sid_security_cfg(BPMPDMAR),
+	mc_make_sid_security_cfg(NVJPGSWR),
+	mc_make_sid_security_cfg(NVDECSRD1),
+	mc_make_sid_security_cfg(TSECSRD),
+	mc_make_sid_security_cfg(NVJPGSRD),
+	mc_make_sid_security_cfg(SDMMCWA),
+	mc_make_sid_security_cfg(SCER),
+	mc_make_sid_security_cfg(XUSB_HOSTR),
+	mc_make_sid_security_cfg(VICSRD),
+	mc_make_sid_security_cfg(AONDMAR),
+	mc_make_sid_security_cfg(AONW),
+	mc_make_sid_security_cfg(SDMMCRA),
+	mc_make_sid_security_cfg(HOST1XDMAR),
+	mc_make_sid_security_cfg(EQOSR),
+	mc_make_sid_security_cfg(SATAR),
+	mc_make_sid_security_cfg(BPMPR),
+	mc_make_sid_security_cfg(HDAR),
+	mc_make_sid_security_cfg(SDMMCRAB),
+	mc_make_sid_security_cfg(ETRR),
+	mc_make_sid_security_cfg(AONR),
+	mc_make_sid_security_cfg(APEDMAR),
+	mc_make_sid_security_cfg(SESRD),
+	mc_make_sid_security_cfg(NVENCSRD),
+	mc_make_sid_security_cfg(GPUSWR),
+	mc_make_sid_security_cfg(TSECSWRB),
+	mc_make_sid_security_cfg(ISPWB),
+	mc_make_sid_security_cfg(GPUSRD2),
+	mc_make_sid_override_cfg(APER),
+	mc_make_sid_override_cfg(VICSRD),
+	mc_make_sid_override_cfg(NVENCSRD),
+	mc_make_sid_override_cfg(NVJPGSWR),
+	mc_make_sid_override_cfg(AONW),
+	mc_make_sid_override_cfg(BPMPR),
+	mc_make_sid_override_cfg(BPMPW),
+	mc_make_sid_override_cfg(HDAW),
+	mc_make_sid_override_cfg(NVDISPLAYR1),
+	mc_make_sid_override_cfg(APEDMAR),
+	mc_make_sid_override_cfg(AFIR),
+	mc_make_sid_override_cfg(AXISR),
+	mc_make_sid_override_cfg(VICSRD1),
+	mc_make_sid_override_cfg(TSECSRD),
+	mc_make_sid_override_cfg(BPMPDMAW),
+	mc_make_sid_override_cfg(MPCOREW),
+	mc_make_sid_override_cfg(XUSB_HOSTR),
+	mc_make_sid_override_cfg(GPUSWR),
+	mc_make_sid_override_cfg(XUSB_DEVR),
+	mc_make_sid_override_cfg(UFSHCW),
+	mc_make_sid_override_cfg(XUSB_HOSTW),
+	mc_make_sid_override_cfg(SDMMCWAB),
+	mc_make_sid_override_cfg(SATAW),
+	mc_make_sid_override_cfg(SCEDMAR),
+	mc_make_sid_override_cfg(HOST1XDMAR),
+	mc_make_sid_override_cfg(SDMMCWA),
+	mc_make_sid_override_cfg(APEDMAW),
+	mc_make_sid_override_cfg(SESWR),
+	mc_make_sid_override_cfg(AXISW),
+	mc_make_sid_override_cfg(AONDMAW),
+	mc_make_sid_override_cfg(TSECSWRB),
+	mc_make_sid_override_cfg(MPCORER),
+	mc_make_sid_override_cfg(ISPWB),
+	mc_make_sid_override_cfg(AONR),
+	mc_make_sid_override_cfg(BPMPDMAR),
+	mc_make_sid_override_cfg(HDAR),
+	mc_make_sid_override_cfg(SDMMCRA),
+	mc_make_sid_override_cfg(ETRW),
+	mc_make_sid_override_cfg(GPUSWR2),
+	mc_make_sid_override_cfg(EQOSR),
+	mc_make_sid_override_cfg(TSECSWR),
+	mc_make_sid_override_cfg(ETRR),
+	mc_make_sid_override_cfg(NVDECSRD),
+	mc_make_sid_override_cfg(TSECSRDB),
+	mc_make_sid_override_cfg(SDMMCRAA),
+	mc_make_sid_override_cfg(NVDECSRD1),
+	mc_make_sid_override_cfg(SDMMCR),
+	mc_make_sid_override_cfg(NVJPGSRD),
+	mc_make_sid_override_cfg(SCEDMAW),
+	mc_make_sid_override_cfg(SDMMCWAA),
+	mc_make_sid_override_cfg(APEW),
+	mc_make_sid_override_cfg(AONDMAR),
+	mc_make_sid_override_cfg(PTCR),
+	mc_make_sid_override_cfg(SCER),
+	mc_make_sid_override_cfg(ISPRA),
+	mc_make_sid_override_cfg(ISPWA),
+	mc_make_sid_override_cfg(VICSWR),
+	mc_make_sid_override_cfg(SESRD),
+	mc_make_sid_override_cfg(SDMMCW),
+	mc_make_sid_override_cfg(SDMMCRAB),
+	mc_make_sid_override_cfg(EQOSW),
+	mc_make_sid_override_cfg(GPUSRD2),
+	mc_make_sid_override_cfg(SCEW),
+	mc_make_sid_override_cfg(GPUSRD),
+	mc_make_sid_override_cfg(NVDECSWR),
+	mc_make_sid_override_cfg(XUSB_DEVW),
+	mc_make_sid_override_cfg(SATAR),
+	mc_make_sid_override_cfg(NVDISPLAYR),
+	mc_make_sid_override_cfg(VIW),
+	mc_make_sid_override_cfg(UFSHCR),
+	mc_make_sid_override_cfg(NVENCSWR),
+	mc_make_sid_override_cfg(AFIW),
+	mc_smmu_bypass_cfg,	/* TBU settings */
+	_END_OF_TABLE_,
+};
+
+/*******************************************************************************
+ * Handler to return the pointer to the MC's context struct
+ ******************************************************************************/
+static mc_regs_t *tegra186_get_mc_system_suspend_ctx(void)
+{
+	/* index of _END_OF_TABLE_ */
+	tegra186_mc_context[0].val = (uint32_t)(ARRAY_SIZE(tegra186_mc_context)) - 1U;
+
+	return tegra186_mc_context;
+}
+
 /*******************************************************************************
  * Struct to hold the memory controller settings
  ******************************************************************************/
@@ -528,6 +693,7 @@
 	.num_txn_override_cfgs = (uint32_t)ARRAY_SIZE(tegra186_txn_override_cfgs),
 	.reconfig_mss_clients = tegra186_memctrl_reconfig_mss_clients,
 	.set_txn_overrides = tegra186_memctrl_set_overrides,
+	.get_mc_system_suspend_ctx = tegra186_get_mc_system_suspend_ctx,
 };
 
 /*******************************************************************************
diff --git a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
index a0879cc..179dd96 100644
--- a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
@@ -22,6 +22,7 @@
 
 #include <bpmp_ipc.h>
 #include <mce.h>
+#include <memctrl_v2.h>
 #include <security_engine.h>
 #include <smmu.h>
 #include <t18x_ari.h>
@@ -99,7 +100,7 @@
 	uint32_t cpu = plat_my_core_pos();
 	const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
 	mce_cstate_info_t cstate_info = { 0 };
-	uint64_t smmu_ctx_base;
+	uint64_t mc_ctx_base;
 	uint32_t val;
 
 	/* get the state ID */
@@ -132,10 +133,10 @@
 		val = mmio_read_32(TEGRA_MISC_BASE + MISCREG_PFCFG);
 		mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SECURE_BOOTP_FCFG, val);
 
-		/* save SMMU context to TZDRAM */
-		smmu_ctx_base = params_from_bl2->tzdram_base +
-				tegra186_get_smmu_ctx_offset();
-		tegra_smmu_save_context((uintptr_t)smmu_ctx_base);
+		/* save MC context to TZDRAM */
+		mc_ctx_base = params_from_bl2->tzdram_base +
+				tegra186_get_mc_ctx_offset();
+		tegra_mc_save_context((uintptr_t)mc_ctx_base);
 
 		/* Prepare for system suspend */
 		cstate_info.cluster = (uint32_t)TEGRA_ARI_CLUSTER_CC7;
@@ -294,7 +295,7 @@
 		assert(tegra_bpmp_ipc_init() == 0);
 
 		/* Enable SE clock */
-		ret = tegra_bpmp_ipc_enable_clock(TEGRA_CLK_SE);
+		ret = tegra_bpmp_ipc_enable_clock(TEGRA186_CLK_SE);
 		if (ret != 0) {
 			ERROR("Failed to enable clock\n");
 			return ret;
@@ -319,7 +320,7 @@
 		memcpy16((void *)(uintptr_t)val, (void *)(uintptr_t)BL31_BASE,
 			 (uintptr_t)BL31_END - (uintptr_t)BL31_BASE);
 
-		ret = tegra_bpmp_ipc_disable_clock(TEGRA_CLK_SE);
+		ret = tegra_bpmp_ipc_disable_clock(TEGRA186_CLK_SE);
 		if (ret != 0) {
 			ERROR("Failed to disable clock\n");
 			return ret;
diff --git a/plat/nvidia/tegra/soc/t186/plat_smmu.c b/plat/nvidia/tegra/soc/t186/plat_smmu.c
index b4a7fe5..f1bc235 100644
--- a/plat/nvidia/tegra/soc/t186/plat_smmu.c
+++ b/plat/nvidia/tegra/soc/t186/plat_smmu.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,171 +14,6 @@
 #define MAX_NUM_SMMU_DEVICES	U(1)
 
 /*******************************************************************************
- * Array to hold SMMU context for Tegra186
- ******************************************************************************/
-static __attribute__((aligned(16))) smmu_regs_t tegra186_smmu_context[] = {
-	_START_OF_TABLE_,
-	mc_make_sid_security_cfg(SCEW),
-	mc_make_sid_security_cfg(AFIR),
-	mc_make_sid_security_cfg(NVDISPLAYR1),
-	mc_make_sid_security_cfg(XUSB_DEVR),
-	mc_make_sid_security_cfg(VICSRD1),
-	mc_make_sid_security_cfg(NVENCSWR),
-	mc_make_sid_security_cfg(TSECSRDB),
-	mc_make_sid_security_cfg(AXISW),
-	mc_make_sid_security_cfg(SDMMCWAB),
-	mc_make_sid_security_cfg(AONDMAW),
-	mc_make_sid_security_cfg(GPUSWR2),
-	mc_make_sid_security_cfg(SATAW),
-	mc_make_sid_security_cfg(UFSHCW),
-	mc_make_sid_security_cfg(AFIW),
-	mc_make_sid_security_cfg(SDMMCR),
-	mc_make_sid_security_cfg(SCEDMAW),
-	mc_make_sid_security_cfg(UFSHCR),
-	mc_make_sid_security_cfg(SDMMCWAA),
-	mc_make_sid_security_cfg(APEDMAW),
-	mc_make_sid_security_cfg(SESWR),
-	mc_make_sid_security_cfg(MPCORER),
-	mc_make_sid_security_cfg(PTCR),
-	mc_make_sid_security_cfg(BPMPW),
-	mc_make_sid_security_cfg(ETRW),
-	mc_make_sid_security_cfg(GPUSRD),
-	mc_make_sid_security_cfg(VICSWR),
-	mc_make_sid_security_cfg(SCEDMAR),
-	mc_make_sid_security_cfg(HDAW),
-	mc_make_sid_security_cfg(ISPWA),
-	mc_make_sid_security_cfg(EQOSW),
-	mc_make_sid_security_cfg(XUSB_HOSTW),
-	mc_make_sid_security_cfg(TSECSWR),
-	mc_make_sid_security_cfg(SDMMCRAA),
-	mc_make_sid_security_cfg(APER),
-	mc_make_sid_security_cfg(VIW),
-	mc_make_sid_security_cfg(APEW),
-	mc_make_sid_security_cfg(AXISR),
-	mc_make_sid_security_cfg(SDMMCW),
-	mc_make_sid_security_cfg(BPMPDMAW),
-	mc_make_sid_security_cfg(ISPRA),
-	mc_make_sid_security_cfg(NVDECSWR),
-	mc_make_sid_security_cfg(XUSB_DEVW),
-	mc_make_sid_security_cfg(NVDECSRD),
-	mc_make_sid_security_cfg(MPCOREW),
-	mc_make_sid_security_cfg(NVDISPLAYR),
-	mc_make_sid_security_cfg(BPMPDMAR),
-	mc_make_sid_security_cfg(NVJPGSWR),
-	mc_make_sid_security_cfg(NVDECSRD1),
-	mc_make_sid_security_cfg(TSECSRD),
-	mc_make_sid_security_cfg(NVJPGSRD),
-	mc_make_sid_security_cfg(SDMMCWA),
-	mc_make_sid_security_cfg(SCER),
-	mc_make_sid_security_cfg(XUSB_HOSTR),
-	mc_make_sid_security_cfg(VICSRD),
-	mc_make_sid_security_cfg(AONDMAR),
-	mc_make_sid_security_cfg(AONW),
-	mc_make_sid_security_cfg(SDMMCRA),
-	mc_make_sid_security_cfg(HOST1XDMAR),
-	mc_make_sid_security_cfg(EQOSR),
-	mc_make_sid_security_cfg(SATAR),
-	mc_make_sid_security_cfg(BPMPR),
-	mc_make_sid_security_cfg(HDAR),
-	mc_make_sid_security_cfg(SDMMCRAB),
-	mc_make_sid_security_cfg(ETRR),
-	mc_make_sid_security_cfg(AONR),
-	mc_make_sid_security_cfg(APEDMAR),
-	mc_make_sid_security_cfg(SESRD),
-	mc_make_sid_security_cfg(NVENCSRD),
-	mc_make_sid_security_cfg(GPUSWR),
-	mc_make_sid_security_cfg(TSECSWRB),
-	mc_make_sid_security_cfg(ISPWB),
-	mc_make_sid_security_cfg(GPUSRD2),
-	mc_make_sid_override_cfg(APER),
-	mc_make_sid_override_cfg(VICSRD),
-	mc_make_sid_override_cfg(NVENCSRD),
-	mc_make_sid_override_cfg(NVJPGSWR),
-	mc_make_sid_override_cfg(AONW),
-	mc_make_sid_override_cfg(BPMPR),
-	mc_make_sid_override_cfg(BPMPW),
-	mc_make_sid_override_cfg(HDAW),
-	mc_make_sid_override_cfg(NVDISPLAYR1),
-	mc_make_sid_override_cfg(APEDMAR),
-	mc_make_sid_override_cfg(AFIR),
-	mc_make_sid_override_cfg(AXISR),
-	mc_make_sid_override_cfg(VICSRD1),
-	mc_make_sid_override_cfg(TSECSRD),
-	mc_make_sid_override_cfg(BPMPDMAW),
-	mc_make_sid_override_cfg(MPCOREW),
-	mc_make_sid_override_cfg(XUSB_HOSTR),
-	mc_make_sid_override_cfg(GPUSWR),
-	mc_make_sid_override_cfg(XUSB_DEVR),
-	mc_make_sid_override_cfg(UFSHCW),
-	mc_make_sid_override_cfg(XUSB_HOSTW),
-	mc_make_sid_override_cfg(SDMMCWAB),
-	mc_make_sid_override_cfg(SATAW),
-	mc_make_sid_override_cfg(SCEDMAR),
-	mc_make_sid_override_cfg(HOST1XDMAR),
-	mc_make_sid_override_cfg(SDMMCWA),
-	mc_make_sid_override_cfg(APEDMAW),
-	mc_make_sid_override_cfg(SESWR),
-	mc_make_sid_override_cfg(AXISW),
-	mc_make_sid_override_cfg(AONDMAW),
-	mc_make_sid_override_cfg(TSECSWRB),
-	mc_make_sid_override_cfg(MPCORER),
-	mc_make_sid_override_cfg(ISPWB),
-	mc_make_sid_override_cfg(AONR),
-	mc_make_sid_override_cfg(BPMPDMAR),
-	mc_make_sid_override_cfg(HDAR),
-	mc_make_sid_override_cfg(SDMMCRA),
-	mc_make_sid_override_cfg(ETRW),
-	mc_make_sid_override_cfg(GPUSWR2),
-	mc_make_sid_override_cfg(EQOSR),
-	mc_make_sid_override_cfg(TSECSWR),
-	mc_make_sid_override_cfg(ETRR),
-	mc_make_sid_override_cfg(NVDECSRD),
-	mc_make_sid_override_cfg(TSECSRDB),
-	mc_make_sid_override_cfg(SDMMCRAA),
-	mc_make_sid_override_cfg(NVDECSRD1),
-	mc_make_sid_override_cfg(SDMMCR),
-	mc_make_sid_override_cfg(NVJPGSRD),
-	mc_make_sid_override_cfg(SCEDMAW),
-	mc_make_sid_override_cfg(SDMMCWAA),
-	mc_make_sid_override_cfg(APEW),
-	mc_make_sid_override_cfg(AONDMAR),
-	mc_make_sid_override_cfg(PTCR),
-	mc_make_sid_override_cfg(SCER),
-	mc_make_sid_override_cfg(ISPRA),
-	mc_make_sid_override_cfg(ISPWA),
-	mc_make_sid_override_cfg(VICSWR),
-	mc_make_sid_override_cfg(SESRD),
-	mc_make_sid_override_cfg(SDMMCW),
-	mc_make_sid_override_cfg(SDMMCRAB),
-	mc_make_sid_override_cfg(EQOSW),
-	mc_make_sid_override_cfg(GPUSRD2),
-	mc_make_sid_override_cfg(SCEW),
-	mc_make_sid_override_cfg(GPUSRD),
-	mc_make_sid_override_cfg(NVDECSWR),
-	mc_make_sid_override_cfg(XUSB_DEVW),
-	mc_make_sid_override_cfg(SATAR),
-	mc_make_sid_override_cfg(NVDISPLAYR),
-	mc_make_sid_override_cfg(VIW),
-	mc_make_sid_override_cfg(UFSHCR),
-	mc_make_sid_override_cfg(NVENCSWR),
-	mc_make_sid_override_cfg(AFIW),
-	smmu_make_cfg(TEGRA_SMMU0_BASE),
-	smmu_bypass_cfg,	/* TBU settings */
-	_END_OF_TABLE_,
-};
-
-/*******************************************************************************
- * Handler to return the pointer to the SMMU's context struct
- ******************************************************************************/
-smmu_regs_t *plat_get_smmu_ctx(void)
-{
-	/* index of _END_OF_TABLE_ */
-	tegra186_smmu_context[0].val = (uint32_t)(ARRAY_SIZE(tegra186_smmu_context)) - 1U;
-
-	return tegra186_smmu_context;
-}
-
-/*******************************************************************************
  * Handler to return the support SMMU devices number
  ******************************************************************************/
 uint32_t plat_get_num_smmu_devices(void)
diff --git a/plat/nvidia/tegra/soc/t186/plat_trampoline.S b/plat/nvidia/tegra/soc/t186/plat_trampoline.S
index db69234..818c24b 100644
--- a/plat/nvidia/tegra/soc/t186/plat_trampoline.S
+++ b/plat/nvidia/tegra/soc/t186/plat_trampoline.S
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,7 +14,7 @@
 
 #define TEGRA186_STATE_SYSTEM_SUSPEND	0x5C7
 #define TEGRA186_STATE_SYSTEM_RESUME	0x600D
-#define TEGRA186_SMMU_CTX_SIZE		0x420
+#define TEGRA186_MC_CTX_SIZE		0x93
 
 	.globl	tegra186_cpu_reset_handler
 
@@ -69,8 +70,8 @@
 	 *
 	 * 0x000: secure world's entrypoint
 	 * 0x008: BL31 size (RO + RW)
-	 * 0x00C: SMMU context start
-	 * 0x42C: SMMU context end
+	 * 0x00C: MC context start
+	 * 0x42C: MC context end
 	 */
 
 	.align 4
@@ -85,9 +86,9 @@
 	.quad	0
 
 	.align 4
-	.globl	__tegra186_smmu_context
-__tegra186_smmu_context:
-	.rept	TEGRA186_SMMU_CTX_SIZE
+	.globl	__tegra186_mc_context
+__tegra186_mc_context:
+	.rept	TEGRA186_MC_CTX_SIZE
 	.quad	0
 	.endr
 	.size	__tegra186_cpu_reset_handler_data, \
@@ -99,7 +100,7 @@
 
 	.globl tegra186_get_cpu_reset_handler_size
 	.globl tegra186_get_cpu_reset_handler_base
-	.globl tegra186_get_smmu_ctx_offset
+	.globl tegra186_get_mc_ctx_offset
 	.globl tegra186_set_system_suspend_entry
 
 /* return size of the CPU reset handler */
@@ -116,13 +117,13 @@
 	ret
 endfunc tegra186_get_cpu_reset_handler_base
 
-/* return the size of the SMMU context */
-func tegra186_get_smmu_ctx_offset
-	adr	x0, __tegra186_smmu_context
+/* return the size of the MC context */
+func tegra186_get_mc_ctx_offset
+	adr	x0, __tegra186_mc_context
 	adr	x1, tegra186_cpu_reset_handler
 	sub	x0, x0, x1
 	ret
-endfunc tegra186_get_smmu_ctx_offset
+endfunc tegra186_get_mc_ctx_offset
 
 /* set system suspend state before SC7 entry */
 func tegra186_set_system_suspend_entry
diff --git a/plat/nvidia/tegra/soc/t194/drivers/include/se.h b/plat/nvidia/tegra/soc/t194/drivers/include/se.h
index e7cf88d..7de55a7 100644
--- a/plat/nvidia/tegra/soc/t194/drivers/include/se.h
+++ b/plat/nvidia/tegra/soc/t194/drivers/include/se.h
@@ -7,6 +7,8 @@
 #ifndef SE_H
 #define SE_H
 
+int32_t tegra_se_calculate_save_sha256(uint64_t src_addr,
+						uint32_t src_len_inbyte);
 int32_t tegra_se_suspend(void);
 void tegra_se_resume(void);
 
diff --git a/plat/nvidia/tegra/soc/t194/drivers/se/se.c b/plat/nvidia/tegra/soc/t194/drivers/se/se.c
index a3b3389..ccdc94d 100644
--- a/plat/nvidia/tegra/soc/t194/drivers/se/se.c
+++ b/plat/nvidia/tegra/soc/t194/drivers/se/se.c
@@ -28,6 +28,14 @@
 #define MAX_TIMEOUT_MS		U(100)	/* Timeout in 100ms */
 #define NUM_SE_REGS_TO_SAVE	U(4)
 
+#define SE0_MAX_BUSY_TIMEOUT_MS		U(100)	/* 100ms Timeout Expired */
+#define BYTES_IN_WORD			U(4)
+#define SHA256_MAX_HASH_RESULT		U(7)
+#define SHA256_DST_SIZE			U(32)
+#define SHA_FIRST_OP			U(1)
+#define MAX_SHA_ENGINE_CHUNK_SIZE	U(0xFFFFFF)
+#define SHA256_MSG_LENGTH_ONETIME	U(0xFFFF)
+
 /*******************************************************************************
  * Data structure and global variables
  ******************************************************************************/
@@ -175,6 +183,270 @@
 	return ret;
 }
 
+/*
+ * Check that SE operation has completed after kickoff
+ * This function is invoked after an SE operation has been started,
+ * and it checks the following conditions:
+ * 1. SE0_INT_STATUS = SE0_OP_DONE
+ * 2. SE0_STATUS = IDLE
+ * 3. SE0_ERR_STATUS is clean.
+ */
+static int32_t tegra_se_sha256_hash_operation_complete(void)
+{
+	uint32_t val = 0U;
+
+	/* Poll the SE interrupt register to ensure H/W operation complete */
+	val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET);
+	while (SE0_INT_OP_DONE(val) == SE0_INT_OP_DONE_CLEAR) {
+		val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET);
+		if (SE0_INT_OP_DONE(val) != SE0_INT_OP_DONE_CLEAR) {
+			break;
+		}
+	}
+
+	/* Poll the SE status idle to ensure H/W operation complete */
+	val = tegra_se_read_32(SE0_SHA_STATUS_0);
+	while (val != SE0_SHA_STATUS_IDLE) {
+		val = tegra_se_read_32(SE0_SHA_STATUS_0);
+		if (val == SE0_SHA_STATUS_IDLE) {
+			break;
+		}
+	}
+
+	/* Ensure that no errors are thrown during operation */
+	val = tegra_se_read_32(SE0_ERR_STATUS_REG_OFFSET);
+	if (val != 0U) {
+		ERROR("%s: error during SE operation! 0x%x", __func__,
+				val);
+		return -ENOTSUP;
+	}
+
+	return 0;
+}
+
+/*
+ * Security engine primitive normal operations
+ */
+static int32_t tegra_se_start_normal_operation(uint64_t src_addr,
+		uint32_t nbytes, uint32_t last_buf, uint32_t src_len_inbytes)
+{
+	uint32_t val = 0U;
+	uint32_t src_in_lo;
+	uint32_t src_in_msb;
+	uint32_t src_in_hi;
+	int32_t ret = 0;
+
+	if ((src_addr == 0ULL) || (nbytes == 0U))
+		return -EINVAL;
+
+	src_in_lo = (uint32_t)src_addr;
+	src_in_msb = (uint32_t)((src_addr >> 32U) & 0xFFU);
+	src_in_hi = ((src_in_msb << SE0_IN_HI_ADDR_HI_0_MSB_SHIFT) |
+				(nbytes & MAX_SHA_ENGINE_CHUNK_SIZE));
+
+	/* set SRC_IN_ADDR_LO and SRC_IN_ADDR_HI*/
+	tegra_se_write_32(SE0_IN_ADDR, src_in_lo);
+	tegra_se_write_32(SE0_IN_HI_ADDR_HI, src_in_hi);
+
+	val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET);
+	if (val > 0U) {
+		tegra_se_write_32(SE0_INT_STATUS_REG_OFFSET, 0x0U);
+	}
+
+	/* Enable SHA interrupt for SE0 Operation */
+	tegra_se_write_32(SE0_SHA_INT_ENABLE, 0x1aU);
+
+	/* flush to DRAM for SE to use the updated contents */
+	flush_dcache_range(src_addr, src_len_inbytes);
+
+	/* Start SHA256 operation */
+	if (last_buf == 1U) {
+		tegra_se_write_32(SE0_OPERATION_REG_OFFSET, SE0_OP_START |
+				SE0_UNIT_OPERATION_PKT_LASTBUF_FIELD);
+	} else {
+		tegra_se_write_32(SE0_OPERATION_REG_OFFSET, SE0_OP_START);
+	}
+
+	return ret;
+}
+
+static int32_t tegra_se_calculate_sha256_hash(uint64_t src_addr,
+						uint32_t src_len_inbyte)
+{
+	uint32_t val, last_buf, i;
+	int32_t ret = 0;
+	uint32_t operations;
+	uint64_t src_len_inbits;
+	uint32_t len_bits_msb;
+	uint32_t len_bits_lsb;
+	uint32_t number_of_operations, max_bytes, bytes_left, remaining_bytes;
+
+	if (src_len_inbyte > MAX_SHA_ENGINE_CHUNK_SIZE) {
+		ERROR("SHA input chunk size too big: 0x%x\n", src_len_inbyte);
+		return -EINVAL;
+	}
+
+	if (src_addr == 0ULL) {
+		return -EINVAL;
+	}
+
+	/* number of bytes per operation */
+	max_bytes = (SHA256_HASH_SIZE_BYTES * SHA256_MSG_LENGTH_ONETIME);
+
+	src_len_inbits = (uint32_t)(src_len_inbyte * 8U);
+	len_bits_msb = (uint32_t)(src_len_inbits >> 32U);
+	len_bits_lsb = (uint32_t)src_len_inbits;
+
+	/* program SE0_CONFIG for SHA256 operation */
+	val =  (uint32_t)(SE0_CONFIG_ENC_ALG_SHA | SE0_CONFIG_ENC_MODE_SHA256 |
+		SE0_CONFIG_DEC_ALG_NOP | SE0_CONFIG_DST_HASHREG);
+	tegra_se_write_32(SE0_SHA_CONFIG, val);
+
+	/* set SE0_SHA_MSG_LENGTH registers */
+	tegra_se_write_32(SE0_SHA_MSG_LENGTH_0, len_bits_lsb);
+	tegra_se_write_32(SE0_SHA_MSG_LEFT_0, len_bits_lsb);
+	tegra_se_write_32(SE0_SHA_MSG_LENGTH_1, len_bits_msb);
+
+	/* zero out unused SE0_SHA_MSG_LENGTH and SE0_SHA_MSG_LEFT */
+	tegra_se_write_32(SE0_SHA_MSG_LENGTH_2, 0U);
+	tegra_se_write_32(SE0_SHA_MSG_LENGTH_3, 0U);
+	tegra_se_write_32(SE0_SHA_MSG_LEFT_1, 0U);
+	tegra_se_write_32(SE0_SHA_MSG_LEFT_2, 0U);
+	tegra_se_write_32(SE0_SHA_MSG_LEFT_3, 0U);
+
+	number_of_operations = (src_len_inbyte / max_bytes);
+	remaining_bytes = (src_len_inbyte % max_bytes);
+	if (remaining_bytes > 0U) {
+		number_of_operations += 1U;
+	}
+
+	/*
+	 * 1. Operations == 1:	program SE0_SHA_TASK register to initiate SHA256
+	 *			hash generation by setting
+	 *			1(SE0_SHA_CONFIG_HW_INIT_HASH) to SE0_SHA_TASK
+	 *			and start SHA256-normal operation.
+	 * 2. 1 < Operations < number_of_operations: program SE0_SHA_TASK to
+	 *			0(SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE) to load
+	 *			intermediate SHA256 digest result from
+	 *			HASH_RESULT register to continue SHA256
+	 *			generation and start SHA256-normal operation.
+	 * 3. Operations == number_of_operations: continue with step 2 and set
+	 *			max_bytes to bytes_left to process final
+	 *			hash-result generation and start SHA256-normal
+	 *			operation.
+	 */
+	bytes_left = src_len_inbyte;
+	for (operations = 1U; operations <= number_of_operations;
+								operations++) {
+		if (operations == SHA_FIRST_OP) {
+			val = SE0_SHA_CONFIG_HW_INIT_HASH;
+		} else {
+			/* Load intermediate SHA digest result to
+			 * SHA:HASH_RESULT(0..7) to continue the SHA
+			 * calculation and tell the SHA engine to use it.
+			 */
+			for (i = 0U; (i / BYTES_IN_WORD) <=
+				SHA256_MAX_HASH_RESULT; i += BYTES_IN_WORD) {
+				val = tegra_se_read_32(SE0_SHA_HASH_RESULT_0 +
+									i);
+				tegra_se_write_32(SE0_SHA_HASH_RESULT_0 + i,
+									val);
+			}
+			val = SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE;
+			if (len_bits_lsb <= (max_bytes * 8U)) {
+				len_bits_lsb = (remaining_bytes * 8U);
+			} else {
+				len_bits_lsb -= (max_bytes * 8U);
+			}
+			tegra_se_write_32(SE0_SHA_MSG_LEFT_0, len_bits_lsb);
+		}
+		tegra_se_write_32(SE0_SHA_TASK_CONFIG, val);
+
+		max_bytes = (SHA256_HASH_SIZE_BYTES *
+						SHA256_MSG_LENGTH_ONETIME);
+		if (bytes_left < max_bytes) {
+			max_bytes = bytes_left;
+			last_buf = 1U;
+		} else {
+			bytes_left = bytes_left - max_bytes;
+			last_buf = 0U;
+		}
+		/* start operation */
+		ret = tegra_se_start_normal_operation(src_addr, max_bytes,
+					last_buf, src_len_inbyte);
+		if (ret != 0) {
+			ERROR("Error during SE operation! 0x%x", ret);
+			return -EINVAL;
+		}
+	}
+
+	return ret;
+}
+
+static int32_t tegra_se_save_sha256_pmc_scratch(void)
+{
+	uint32_t val = 0U, hash_offset = 0U, scratch_offset = 0U;
+	int32_t ret;
+
+	/* Check SE0 operation status */
+	ret = tegra_se_sha256_hash_operation_complete();
+	if (ret != 0) {
+		ERROR("SE operation complete Failed! 0x%x", ret);
+		return ret;
+	}
+
+	for (scratch_offset = SECURE_SCRATCH_TZDRAM_SHA256_HASH_START;
+			scratch_offset <= SECURE_SCRATCH_TZDRAM_SHA256_HASH_END;
+					scratch_offset += BYTES_IN_WORD) {
+		val = tegra_se_read_32(SE0_SHA_HASH_RESULT_0 + hash_offset);
+		mmio_write_32((uint32_t)(TEGRA_SCRATCH_BASE + scratch_offset),
+									val);
+		hash_offset += BYTES_IN_WORD;
+	}
+	return 0;
+}
+
+/*
+ * Handler to generate SHA256 and save HASH-result to pmc-scratch register
+ */
+int32_t tegra_se_calculate_save_sha256(uint64_t src_addr,
+						uint32_t src_len_inbyte)
+{
+	uint32_t security;
+	int32_t val = 0;
+
+	/* Set SE_SOFT_SETTINGS=SE_SECURE to prevent NS process to change SE
+	 * registers.
+	 */
+	security = tegra_se_read_32(SE0_SECURITY);
+	tegra_se_write_32(SE0_SECURITY, security | SE0_SECURITY_SE_SOFT_SETTING);
+
+	/* Bootrom enable IN_ID bit in SE0_SHA_GSCID_0 register during SC7-exit, causing
+	 * SE0 ignores SE0 operation, and therefore failure of 2nd iteration of SC7 cycle.
+	 */
+	tegra_se_write_32(SE0_SHA_GSCID_0, 0x0U);
+
+	/* Calculate SHA256 of BL31 */
+	val = tegra_se_calculate_sha256_hash(src_addr, src_len_inbyte);
+	if (val != 0) {
+		ERROR("%s: SHA256 generation failed\n", __func__);
+		return val;
+	}
+
+	/*
+	 * Reset SE_SECURE to previous value.
+	 */
+	tegra_se_write_32(SE0_SECURITY, security);
+
+	/* copy sha256_dst to PMC Scratch register */
+	val = tegra_se_save_sha256_pmc_scratch();
+	if (val != 0) {
+		ERROR("%s: SE0 status Error.\n", __func__);
+	}
+
+	return val;
+}
+
 /*
  * Handler to power down the SE hardware blocks - SE, RNG1 and PKA1. This
  * needs to be called only during System Suspend.
@@ -187,7 +459,7 @@
 	assert(tegra_bpmp_ipc_init() == 0);
 
 	/* Enable SE clock before SE context save */
-	ret = tegra_bpmp_ipc_enable_clock(TEGRA_CLK_SE);
+	ret = tegra_bpmp_ipc_enable_clock(TEGRA194_CLK_SE);
 	assert(ret == 0);
 
 	/* save SE registers */
@@ -203,7 +475,7 @@
 	}
 
 	/* Disable SE clock after SE context save */
-	ret = tegra_bpmp_ipc_disable_clock(TEGRA_CLK_SE);
+	ret = tegra_bpmp_ipc_disable_clock(TEGRA194_CLK_SE);
 	assert(ret == 0);
 
 	return ret;
@@ -220,7 +492,7 @@
 	assert(tegra_bpmp_ipc_init() == 0);
 
 	/* Enable SE clock before SE context restore */
-	ret = tegra_bpmp_ipc_enable_clock(TEGRA_CLK_SE);
+	ret = tegra_bpmp_ipc_enable_clock(TEGRA194_CLK_SE);
 	assert(ret == 0);
 
 	/*
@@ -235,6 +507,6 @@
 	mmio_write_32(TEGRA_PKA1_BASE + PKA1_MUTEX_WATCHDOG_NS_LIMIT, se_regs[3]);
 
 	/* Disable SE clock after SE context restore */
-	ret = tegra_bpmp_ipc_disable_clock(TEGRA_CLK_SE);
+	ret = tegra_bpmp_ipc_disable_clock(TEGRA194_CLK_SE);
 	assert(ret == 0);
 }
diff --git a/plat/nvidia/tegra/soc/t194/drivers/se/se_private.h b/plat/nvidia/tegra/soc/t194/drivers/se/se_private.h
index 577217b..fc118aa 100644
--- a/plat/nvidia/tegra/soc/t194/drivers/se/se_private.h
+++ b/plat/nvidia/tegra/soc/t194/drivers/se/se_private.h
@@ -9,6 +9,86 @@
 #define SE_PRIVATE_H
 
 #include <lib/utils_def.h>
+#include <tegra_def.h>
+
+/* SE0 security register */
+#define SE0_SECURITY				U(0x18)
+#define SE0_SECURITY_SE_SOFT_SETTING		(((uint32_t)1) << 16U)
+
+/* SE0 SHA GSCID register */
+#define SE0_SHA_GSCID_0				U(0x100)
+
+/* SE0 config register */
+#define SE0_SHA_CONFIG				U(0x104)
+#define SE0_SHA_TASK_CONFIG			U(0x108)
+#define SE0_SHA_CONFIG_HW_INIT_HASH		(((uint32_t)1) << 0U)
+#define SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE	U(0)
+
+#define SE0_CONFIG_ENC_ALG_SHIFT		U(12)
+#define SE0_CONFIG_ENC_ALG_SHA	\
+		(((uint32_t)3) << SE0_CONFIG_ENC_ALG_SHIFT)
+#define SE0_CONFIG_DEC_ALG_SHIFT		U(8)
+#define SE0_CONFIG_DEC_ALG_NOP	\
+		(((uint32_t)0) << SE0_CONFIG_DEC_ALG_SHIFT)
+#define SE0_CONFIG_DST_SHIFT			U(2)
+#define SE0_CONFIG_DST_HASHREG	\
+		(((uint32_t)1) << SE0_CONFIG_DST_SHIFT)
+#define SHA256_HASH_SIZE_BYTES			U(256)
+
+#define SE0_CONFIG_ENC_MODE_SHIFT		U(24)
+#define SE0_CONFIG_ENC_MODE_SHA256	\
+			(((uint32_t)5) << SE0_CONFIG_ENC_MODE_SHIFT)
+
+/* SHA input message length */
+#define SE0_IN_ADDR				U(0x10c)
+#define SE0_IN_HI_ADDR_HI			U(0x110)
+#define SE0_IN_HI_ADDR_HI_0_MSB_SHIFT		U(24)
+
+/* SHA input message length */
+#define SE0_SHA_MSG_LENGTH_0			U(0x11c)
+#define SE0_SHA_MSG_LENGTH_1			U(0x120)
+#define SE0_SHA_MSG_LENGTH_2			U(0x124)
+#define SE0_SHA_MSG_LENGTH_3			U(0x128)
+
+/* SHA input message left  */
+#define SE0_SHA_MSG_LEFT_0			U(0x12c)
+#define SE0_SHA_MSG_LEFT_1			U(0x130)
+#define SE0_SHA_MSG_LEFT_2			U(0x134)
+#define SE0_SHA_MSG_LEFT_3			U(0x138)
+
+/* SE HASH-RESULT */
+#define SE0_SHA_HASH_RESULT_0			U(0x13c)
+
+/* SE OPERATION */
+#define SE0_OPERATION_REG_OFFSET		U(0x17c)
+#define SE0_UNIT_OPERATION_PKT_LASTBUF_SHIFT	U(16)
+#define SE0_UNIT_OPERATION_PKT_LASTBUF_FIELD	\
+		((uint32_t)0x1 << SE0_UNIT_OPERATION_PKT_LASTBUF_SHIFT)
+#define SE0_OPERATION_SHIFT			U(0)
+#define SE0_OP_START	\
+		(((uint32_t)0x1) << SE0_OPERATION_SHIFT)
+
+/* SE Interrupt */
+#define SE0_SHA_INT_ENABLE			U(0x180)
+
+#define SE0_INT_STATUS_REG_OFFSET		U(0x184)
+#define SE0_INT_OP_DONE_SHIFT			U(4)
+#define SE0_INT_OP_DONE_CLEAR	\
+		(((uint32_t)0U) << SE0_INT_OP_DONE_SHIFT)
+#define SE0_INT_OP_DONE(x)	\
+		((x) & (((uint32_t)0x1U) << SE0_INT_OP_DONE_SHIFT))
+
+/* SE SHA Status */
+#define SE0_SHA_STATUS_0			U(0x188)
+#define SE0_SHA_STATUS_IDLE			U(0)
+
+/* SE error status */
+#define SE0_ERR_STATUS_REG_OFFSET		U(0x18c)
+#define SE0_ERR_STATUS_CLEAR			U(0)
+
+/* SE error status */
+#define SECURE_SCRATCH_TZDRAM_SHA256_HASH_START	SECURE_SCRATCH_RSV68_LO
+#define SECURE_SCRATCH_TZDRAM_SHA256_HASH_END	SECURE_SCRATCH_RSV71_HI
 
 /* SE0_INT_ENABLE_0 */
 #define SE0_INT_ENABLE				U(0x88)
@@ -20,7 +100,7 @@
 
 /* SE0_SHA_INT_STATUS_0 */
 #define SHA_INT_STATUS				U(0x184)
-#define  SHA_SE_OP_DONE				(U(1) << 4)
+#define SHA_SE_OP_DONE				(U(1) << 4)
 
 /* SE0_SHA_ERR_STATUS_0 */
 #define SHA_ERR_STATUS				U(0x18C)
diff --git a/plat/nvidia/tegra/soc/t194/plat_memctrl.c b/plat/nvidia/tegra/soc/t194/plat_memctrl.c
index d5f72b6..2d5f8e3 100644
--- a/plat/nvidia/tegra/soc/t194/plat_memctrl.c
+++ b/plat/nvidia/tegra/soc/t194/plat_memctrl.c
@@ -15,12 +15,15 @@
  * Array to hold stream_id override config register offsets
  ******************************************************************************/
 const static uint32_t tegra194_streamid_override_regs[] = {
+	MC_STREAMID_OVERRIDE_CFG_PTCR,
 	MC_STREAMID_OVERRIDE_CFG_HDAR,
 	MC_STREAMID_OVERRIDE_CFG_HOST1XDMAR,
 	MC_STREAMID_OVERRIDE_CFG_NVENCSRD,
 	MC_STREAMID_OVERRIDE_CFG_SATAR,
+	MC_STREAMID_OVERRIDE_CFG_MPCORER,
 	MC_STREAMID_OVERRIDE_CFG_NVENCSWR,
 	MC_STREAMID_OVERRIDE_CFG_HDAW,
+	MC_STREAMID_OVERRIDE_CFG_MPCOREW,
 	MC_STREAMID_OVERRIDE_CFG_SATAW,
 	MC_STREAMID_OVERRIDE_CFG_ISPRA,
 	MC_STREAMID_OVERRIDE_CFG_ISPFALR,
@@ -131,6 +134,9 @@
 	MC_STREAMID_OVERRIDE_CFG_NVENC1SRD1,
 	MC_STREAMID_OVERRIDE_CFG_ISPRA1,
 	MC_STREAMID_OVERRIDE_CFG_PCIE0R1,
+	MC_STREAMID_OVERRIDE_CFG_NVDEC1SRD,
+	MC_STREAMID_OVERRIDE_CFG_NVDEC1SRD1,
+	MC_STREAMID_OVERRIDE_CFG_NVDEC1SWR,
 	MC_STREAMID_OVERRIDE_CFG_MIU0R,
 	MC_STREAMID_OVERRIDE_CFG_MIU0W,
 	MC_STREAMID_OVERRIDE_CFG_MIU1R,
@@ -142,19 +148,26 @@
 	MC_STREAMID_OVERRIDE_CFG_MIU4R,
 	MC_STREAMID_OVERRIDE_CFG_MIU4W,
 	MC_STREAMID_OVERRIDE_CFG_MIU5R,
-	MC_STREAMID_OVERRIDE_CFG_MIU5W
+	MC_STREAMID_OVERRIDE_CFG_MIU5W,
+	MC_STREAMID_OVERRIDE_CFG_MIU6R,
+	MC_STREAMID_OVERRIDE_CFG_MIU6W,
+	MC_STREAMID_OVERRIDE_CFG_MIU7R,
+	MC_STREAMID_OVERRIDE_CFG_MIU7W
 };
 
 /*******************************************************************************
  * Array to hold the security configs for stream IDs
  ******************************************************************************/
 const static mc_streamid_security_cfg_t tegra194_streamid_sec_cfgs[] = {
+	mc_make_sec_cfg(PTCR, NON_SECURE, OVERRIDE, DISABLE),
 	mc_make_sec_cfg(HDAR, NON_SECURE, OVERRIDE, DISABLE),
 	mc_make_sec_cfg(HOST1XDMAR, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(NVENCSRD, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(SATAR, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MPCORER, NON_SECURE, OVERRIDE, DISABLE),
 	mc_make_sec_cfg(NVENCSWR, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(HDAW, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MPCOREW, NON_SECURE, OVERRIDE, DISABLE),
 	mc_make_sec_cfg(SATAW, NON_SECURE, OVERRIDE, DISABLE),
 	mc_make_sec_cfg(ISPRA, NON_SECURE, NO_OVERRIDE, ENABLE),
 	mc_make_sec_cfg(ISPFALR, NON_SECURE, NO_OVERRIDE, ENABLE),
@@ -265,6 +278,9 @@
 	mc_make_sec_cfg(NVENC1SRD1, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(ISPRA1, NON_SECURE, NO_OVERRIDE, ENABLE),
 	mc_make_sec_cfg(PCIE0R1, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(NVDEC1SRD, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(NVDEC1SRD1, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(NVDEC1SWR, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(MIU0R, NON_SECURE, OVERRIDE, DISABLE),
 	mc_make_sec_cfg(MIU0W, NON_SECURE, OVERRIDE, DISABLE),
 	mc_make_sec_cfg(MIU1R, NON_SECURE, OVERRIDE, DISABLE),
@@ -276,17 +292,290 @@
 	mc_make_sec_cfg(MIU4R, NON_SECURE, OVERRIDE, DISABLE),
 	mc_make_sec_cfg(MIU4W, NON_SECURE, OVERRIDE, DISABLE),
 	mc_make_sec_cfg(MIU5R, NON_SECURE, OVERRIDE, DISABLE),
-	mc_make_sec_cfg(MIU5W, NON_SECURE, OVERRIDE, DISABLE)
+	mc_make_sec_cfg(MIU5W, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MIU6R, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MIU6W, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MIU7R, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MIU7W, NON_SECURE, OVERRIDE, DISABLE)
 };
 
 /*******************************************************************************
+ * Array to hold MC context for Tegra194
+ ******************************************************************************/
+static __attribute__((aligned(16))) mc_regs_t tegra194_mc_context[] = {
+	_START_OF_TABLE_,
+	mc_make_sid_security_cfg(HDAR),
+	mc_make_sid_security_cfg(HOST1XDMAR),
+	mc_make_sid_security_cfg(NVENCSRD),
+	mc_make_sid_security_cfg(SATAR),
+	mc_make_sid_security_cfg(NVENCSWR),
+	mc_make_sid_security_cfg(HDAW),
+	mc_make_sid_security_cfg(SATAW),
+	mc_make_sid_security_cfg(ISPRA),
+	mc_make_sid_security_cfg(ISPFALR),
+	mc_make_sid_security_cfg(ISPWA),
+	mc_make_sid_security_cfg(ISPWB),
+	mc_make_sid_security_cfg(XUSB_HOSTR),
+	mc_make_sid_security_cfg(XUSB_HOSTW),
+	mc_make_sid_security_cfg(XUSB_DEVR),
+	mc_make_sid_security_cfg(XUSB_DEVW),
+	mc_make_sid_security_cfg(TSECSRD),
+	mc_make_sid_security_cfg(TSECSWR),
+	mc_make_sid_security_cfg(SDMMCRA),
+	mc_make_sid_security_cfg(SDMMCR),
+	mc_make_sid_security_cfg(SDMMCRAB),
+	mc_make_sid_security_cfg(SDMMCWA),
+	mc_make_sid_security_cfg(SDMMCW),
+	mc_make_sid_security_cfg(SDMMCWAB),
+	mc_make_sid_security_cfg(VICSRD),
+	mc_make_sid_security_cfg(VICSWR),
+	mc_make_sid_security_cfg(VIW),
+	mc_make_sid_security_cfg(NVDECSRD),
+	mc_make_sid_security_cfg(NVDECSWR),
+	mc_make_sid_security_cfg(APER),
+	mc_make_sid_security_cfg(APEW),
+	mc_make_sid_security_cfg(NVJPGSRD),
+	mc_make_sid_security_cfg(NVJPGSWR),
+	mc_make_sid_security_cfg(SESRD),
+	mc_make_sid_security_cfg(SESWR),
+	mc_make_sid_security_cfg(AXIAPR),
+	mc_make_sid_security_cfg(AXIAPW),
+	mc_make_sid_security_cfg(ETRR),
+	mc_make_sid_security_cfg(ETRW),
+	mc_make_sid_security_cfg(TSECSRDB),
+	mc_make_sid_security_cfg(TSECSWRB),
+	mc_make_sid_security_cfg(AXISR),
+	mc_make_sid_security_cfg(AXISW),
+	mc_make_sid_security_cfg(EQOSR),
+	mc_make_sid_security_cfg(EQOSW),
+	mc_make_sid_security_cfg(UFSHCR),
+	mc_make_sid_security_cfg(UFSHCW),
+	mc_make_sid_security_cfg(NVDISPLAYR),
+	mc_make_sid_security_cfg(BPMPR),
+	mc_make_sid_security_cfg(BPMPW),
+	mc_make_sid_security_cfg(BPMPDMAR),
+	mc_make_sid_security_cfg(BPMPDMAW),
+	mc_make_sid_security_cfg(AONR),
+	mc_make_sid_security_cfg(AONW),
+	mc_make_sid_security_cfg(AONDMAR),
+	mc_make_sid_security_cfg(AONDMAW),
+	mc_make_sid_security_cfg(SCER),
+	mc_make_sid_security_cfg(SCEW),
+	mc_make_sid_security_cfg(SCEDMAR),
+	mc_make_sid_security_cfg(SCEDMAW),
+	mc_make_sid_security_cfg(APEDMAR),
+	mc_make_sid_security_cfg(APEDMAW),
+	mc_make_sid_security_cfg(NVDISPLAYR1),
+	mc_make_sid_security_cfg(VICSRD1),
+	mc_make_sid_security_cfg(NVDECSRD1),
+	mc_make_sid_security_cfg(VIFALR),
+	mc_make_sid_security_cfg(VIFALW),
+	mc_make_sid_security_cfg(DLA0RDA),
+	mc_make_sid_security_cfg(DLA0FALRDB),
+	mc_make_sid_security_cfg(DLA0WRA),
+	mc_make_sid_security_cfg(DLA0FALWRB),
+	mc_make_sid_security_cfg(DLA1RDA),
+	mc_make_sid_security_cfg(DLA1FALRDB),
+	mc_make_sid_security_cfg(DLA1WRA),
+	mc_make_sid_security_cfg(DLA1FALWRB),
+	mc_make_sid_security_cfg(PVA0RDA),
+	mc_make_sid_security_cfg(PVA0RDB),
+	mc_make_sid_security_cfg(PVA0RDC),
+	mc_make_sid_security_cfg(PVA0WRA),
+	mc_make_sid_security_cfg(PVA0WRB),
+	mc_make_sid_security_cfg(PVA0WRC),
+	mc_make_sid_security_cfg(PVA1RDA),
+	mc_make_sid_security_cfg(PVA1RDB),
+	mc_make_sid_security_cfg(PVA1RDC),
+	mc_make_sid_security_cfg(PVA1WRA),
+	mc_make_sid_security_cfg(PVA1WRB),
+	mc_make_sid_security_cfg(PVA1WRC),
+	mc_make_sid_security_cfg(RCER),
+	mc_make_sid_security_cfg(RCEW),
+	mc_make_sid_security_cfg(RCEDMAR),
+	mc_make_sid_security_cfg(RCEDMAW),
+	mc_make_sid_security_cfg(NVENC1SRD),
+	mc_make_sid_security_cfg(NVENC1SWR),
+	mc_make_sid_security_cfg(PCIE0R),
+	mc_make_sid_security_cfg(PCIE0W),
+	mc_make_sid_security_cfg(PCIE1R),
+	mc_make_sid_security_cfg(PCIE1W),
+	mc_make_sid_security_cfg(PCIE2AR),
+	mc_make_sid_security_cfg(PCIE2AW),
+	mc_make_sid_security_cfg(PCIE3R),
+	mc_make_sid_security_cfg(PCIE3W),
+	mc_make_sid_security_cfg(PCIE4R),
+	mc_make_sid_security_cfg(PCIE4W),
+	mc_make_sid_security_cfg(PCIE5R),
+	mc_make_sid_security_cfg(PCIE5W),
+	mc_make_sid_security_cfg(ISPFALW),
+	mc_make_sid_security_cfg(DLA0RDA1),
+	mc_make_sid_security_cfg(DLA1RDA1),
+	mc_make_sid_security_cfg(PVA0RDA1),
+	mc_make_sid_security_cfg(PVA0RDB1),
+	mc_make_sid_security_cfg(PVA1RDA1),
+	mc_make_sid_security_cfg(PVA1RDB1),
+	mc_make_sid_security_cfg(PCIE5R1),
+	mc_make_sid_security_cfg(NVENCSRD1),
+	mc_make_sid_security_cfg(NVENC1SRD1),
+	mc_make_sid_security_cfg(ISPRA1),
+	mc_make_sid_security_cfg(PCIE0R1),
+	mc_make_sid_security_cfg(MIU0R),
+	mc_make_sid_security_cfg(MIU0W),
+	mc_make_sid_security_cfg(MIU1R),
+	mc_make_sid_security_cfg(MIU1W),
+	mc_make_sid_security_cfg(MIU2R),
+	mc_make_sid_security_cfg(MIU2W),
+	mc_make_sid_security_cfg(MIU3R),
+	mc_make_sid_security_cfg(MIU3W),
+	mc_make_sid_override_cfg(HDAR),
+	mc_make_sid_override_cfg(HOST1XDMAR),
+	mc_make_sid_override_cfg(NVENCSRD),
+	mc_make_sid_override_cfg(SATAR),
+	mc_make_sid_override_cfg(NVENCSWR),
+	mc_make_sid_override_cfg(HDAW),
+	mc_make_sid_override_cfg(SATAW),
+	mc_make_sid_override_cfg(ISPRA),
+	mc_make_sid_override_cfg(ISPFALR),
+	mc_make_sid_override_cfg(ISPWA),
+	mc_make_sid_override_cfg(ISPWB),
+	mc_make_sid_override_cfg(XUSB_HOSTR),
+	mc_make_sid_override_cfg(XUSB_HOSTW),
+	mc_make_sid_override_cfg(XUSB_DEVR),
+	mc_make_sid_override_cfg(XUSB_DEVW),
+	mc_make_sid_override_cfg(TSECSRD),
+	mc_make_sid_override_cfg(TSECSWR),
+	mc_make_sid_override_cfg(SDMMCRA),
+	mc_make_sid_override_cfg(SDMMCR),
+	mc_make_sid_override_cfg(SDMMCRAB),
+	mc_make_sid_override_cfg(SDMMCWA),
+	mc_make_sid_override_cfg(SDMMCW),
+	mc_make_sid_override_cfg(SDMMCWAB),
+	mc_make_sid_override_cfg(VICSRD),
+	mc_make_sid_override_cfg(VICSWR),
+	mc_make_sid_override_cfg(VIW),
+	mc_make_sid_override_cfg(NVDECSRD),
+	mc_make_sid_override_cfg(NVDECSWR),
+	mc_make_sid_override_cfg(APER),
+	mc_make_sid_override_cfg(APEW),
+	mc_make_sid_override_cfg(NVJPGSRD),
+	mc_make_sid_override_cfg(NVJPGSWR),
+	mc_make_sid_override_cfg(SESRD),
+	mc_make_sid_override_cfg(SESWR),
+	mc_make_sid_override_cfg(AXIAPR),
+	mc_make_sid_override_cfg(AXIAPW),
+	mc_make_sid_override_cfg(ETRR),
+	mc_make_sid_override_cfg(ETRW),
+	mc_make_sid_override_cfg(TSECSRDB),
+	mc_make_sid_override_cfg(TSECSWRB),
+	mc_make_sid_override_cfg(AXISR),
+	mc_make_sid_override_cfg(AXISW),
+	mc_make_sid_override_cfg(EQOSR),
+	mc_make_sid_override_cfg(EQOSW),
+	mc_make_sid_override_cfg(UFSHCR),
+	mc_make_sid_override_cfg(UFSHCW),
+	mc_make_sid_override_cfg(NVDISPLAYR),
+	mc_make_sid_override_cfg(BPMPR),
+	mc_make_sid_override_cfg(BPMPW),
+	mc_make_sid_override_cfg(BPMPDMAR),
+	mc_make_sid_override_cfg(BPMPDMAW),
+	mc_make_sid_override_cfg(AONR),
+	mc_make_sid_override_cfg(AONW),
+	mc_make_sid_override_cfg(AONDMAR),
+	mc_make_sid_override_cfg(AONDMAW),
+	mc_make_sid_override_cfg(SCER),
+	mc_make_sid_override_cfg(SCEW),
+	mc_make_sid_override_cfg(SCEDMAR),
+	mc_make_sid_override_cfg(SCEDMAW),
+	mc_make_sid_override_cfg(APEDMAR),
+	mc_make_sid_override_cfg(APEDMAW),
+	mc_make_sid_override_cfg(NVDISPLAYR1),
+	mc_make_sid_override_cfg(VICSRD1),
+	mc_make_sid_override_cfg(NVDECSRD1),
+	mc_make_sid_override_cfg(VIFALR),
+	mc_make_sid_override_cfg(VIFALW),
+	mc_make_sid_override_cfg(DLA0RDA),
+	mc_make_sid_override_cfg(DLA0FALRDB),
+	mc_make_sid_override_cfg(DLA0WRA),
+	mc_make_sid_override_cfg(DLA0FALWRB),
+	mc_make_sid_override_cfg(DLA1RDA),
+	mc_make_sid_override_cfg(DLA1FALRDB),
+	mc_make_sid_override_cfg(DLA1WRA),
+	mc_make_sid_override_cfg(DLA1FALWRB),
+	mc_make_sid_override_cfg(PVA0RDA),
+	mc_make_sid_override_cfg(PVA0RDB),
+	mc_make_sid_override_cfg(PVA0RDC),
+	mc_make_sid_override_cfg(PVA0WRA),
+	mc_make_sid_override_cfg(PVA0WRB),
+	mc_make_sid_override_cfg(PVA0WRC),
+	mc_make_sid_override_cfg(PVA1RDA),
+	mc_make_sid_override_cfg(PVA1RDB),
+	mc_make_sid_override_cfg(PVA1RDC),
+	mc_make_sid_override_cfg(PVA1WRA),
+	mc_make_sid_override_cfg(PVA1WRB),
+	mc_make_sid_override_cfg(PVA1WRC),
+	mc_make_sid_override_cfg(RCER),
+	mc_make_sid_override_cfg(RCEW),
+	mc_make_sid_override_cfg(RCEDMAR),
+	mc_make_sid_override_cfg(RCEDMAW),
+	mc_make_sid_override_cfg(NVENC1SRD),
+	mc_make_sid_override_cfg(NVENC1SWR),
+	mc_make_sid_override_cfg(PCIE0R),
+	mc_make_sid_override_cfg(PCIE0W),
+	mc_make_sid_override_cfg(PCIE1R),
+	mc_make_sid_override_cfg(PCIE1W),
+	mc_make_sid_override_cfg(PCIE2AR),
+	mc_make_sid_override_cfg(PCIE2AW),
+	mc_make_sid_override_cfg(PCIE3R),
+	mc_make_sid_override_cfg(PCIE3W),
+	mc_make_sid_override_cfg(PCIE4R),
+	mc_make_sid_override_cfg(PCIE4W),
+	mc_make_sid_override_cfg(PCIE5R),
+	mc_make_sid_override_cfg(PCIE5W),
+	mc_make_sid_override_cfg(ISPFALW),
+	mc_make_sid_override_cfg(DLA0RDA1),
+	mc_make_sid_override_cfg(DLA1RDA1),
+	mc_make_sid_override_cfg(PVA0RDA1),
+	mc_make_sid_override_cfg(PVA0RDB1),
+	mc_make_sid_override_cfg(PVA1RDA1),
+	mc_make_sid_override_cfg(PVA1RDB1),
+	mc_make_sid_override_cfg(PCIE5R1),
+	mc_make_sid_override_cfg(NVENCSRD1),
+	mc_make_sid_override_cfg(NVENC1SRD1),
+	mc_make_sid_override_cfg(ISPRA1),
+	mc_make_sid_override_cfg(PCIE0R1),
+	mc_make_sid_override_cfg(MIU0R),
+	mc_make_sid_override_cfg(MIU0W),
+	mc_make_sid_override_cfg(MIU1R),
+	mc_make_sid_override_cfg(MIU1W),
+	mc_make_sid_override_cfg(MIU2R),
+	mc_make_sid_override_cfg(MIU2W),
+	mc_make_sid_override_cfg(MIU3R),
+	mc_make_sid_override_cfg(MIU3W),
+	mc_smmu_bypass_cfg,	/* TBU settings */
+	_END_OF_TABLE_,
+};
+
+/*******************************************************************************
+ * Handler to return the pointer to the MC's context struct
+ ******************************************************************************/
+static mc_regs_t *tegra194_get_mc_system_suspend_ctx(void)
+{
+	/* index of _END_OF_TABLE_ */
+	tegra194_mc_context[0].val = (uint32_t)ARRAY_SIZE(tegra194_mc_context) - 1U;
+
+	return tegra194_mc_context;
+}
+
+/*******************************************************************************
  * Struct to hold the memory controller settings
  ******************************************************************************/
 static tegra_mc_settings_t tegra194_mc_settings = {
 	.streamid_override_cfg = tegra194_streamid_override_regs,
 	.num_streamid_override_cfgs = (uint32_t)ARRAY_SIZE(tegra194_streamid_override_regs),
 	.streamid_security_cfg = tegra194_streamid_sec_cfgs,
-	.num_streamid_security_cfgs = (uint32_t)ARRAY_SIZE(tegra194_streamid_sec_cfgs)
+	.num_streamid_security_cfgs = (uint32_t)ARRAY_SIZE(tegra194_streamid_sec_cfgs),
+	.get_mc_system_suspend_ctx = tegra194_get_mc_system_suspend_ctx
 };
 
 /*******************************************************************************
diff --git a/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
index 144e418..d92025b 100644
--- a/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
@@ -10,14 +10,17 @@
 #include <string.h>
 
 #include <arch_helpers.h>
+#include <bpmp_ipc.h>
 #include <common/bl_common.h>
 #include <common/debug.h>
 #include <context.h>
+#include <drivers/delay_timer.h>
 #include <denver.h>
 #include <lib/el3_runtime/context_mgmt.h>
 #include <lib/psci/psci.h>
 #include <mce.h>
 #include <mce_private.h>
+#include <memctrl_v2.h>
 #include <plat/common/platform.h>
 #include <se.h>
 #include <smmu.h>
@@ -116,7 +119,7 @@
 	const plat_local_state_t *pwr_domain_state;
 	uint8_t stateid_afflvl0, stateid_afflvl2;
 	plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
-	uint64_t smmu_ctx_base;
+	uint64_t mc_ctx_base;
 	uint32_t val;
 	mce_cstate_info_t sc7_cstate_info = {
 		.cluster = (uint32_t)TEGRA_NVG_CLUSTER_CC6,
@@ -135,7 +138,7 @@
 	stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] &
 		TEGRA194_STATE_ID_MASK;
 
-	if ((stateid_afflvl0 == PSTATE_ID_CORE_POWERDN)) {
+	if (stateid_afflvl0 == PSTATE_ID_CORE_POWERDN) {
 
 		/* Enter CPU powerdown */
 		(void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE,
@@ -149,10 +152,10 @@
 		val = mmio_read_32(TEGRA_MISC_BASE + MISCREG_PFCFG);
 		mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SECURE_BOOTP_FCFG, val);
 
-		/* save SMMU context */
-		smmu_ctx_base = params_from_bl2->tzdram_base +
-				tegra194_get_smmu_ctx_offset();
-		tegra_smmu_save_context((uintptr_t)smmu_ctx_base);
+		/* save MC context */
+		mc_ctx_base = params_from_bl2->tzdram_base +
+				tegra194_get_mc_ctx_offset();
+		tegra_mc_save_context((uintptr_t)mc_ctx_base);
 
 		/*
 		 * Suspend SE, RNG1 and PKA1 only on silcon and fpga,
@@ -289,9 +292,34 @@
 	plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
 	uint8_t stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] &
 		TEGRA194_STATE_ID_MASK;
+	uint64_t src_len_in_bytes = (uintptr_t)&__BL31_END__ - (uintptr_t)BL31_BASE;
 	uint64_t val;
+	int32_t ret = PSCI_E_SUCCESS;
 
 	if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
+		val = params_from_bl2->tzdram_base +
+		      tegra194_get_cpu_reset_handler_size();
+
+		/* initialise communication channel with BPMP */
+		ret = tegra_bpmp_ipc_init();
+		assert(ret == 0);
+
+		/* Enable SE clock before SE context save */
+		ret = tegra_bpmp_ipc_enable_clock(TEGRA194_CLK_SE);
+		assert(ret == 0);
+
+		/*
+		 * It is very unlikely that the BL31 image would be
+		 * bigger than 2^32 bytes
+		 */
+		assert(src_len_in_bytes < UINT32_MAX);
+
+		if (tegra_se_calculate_save_sha256(BL31_BASE,
+					(uint32_t)src_len_in_bytes) != 0) {
+			ERROR("Hash calculation failed. Reboot\n");
+			(void)tegra_soc_prepare_system_reset();
+		}
+
 		/*
 		 * The TZRAM loses power when we enter system suspend. To
 		 * allow graceful exit from system suspend, we need to copy
@@ -300,10 +328,14 @@
 		val = params_from_bl2->tzdram_base +
 		      tegra194_get_cpu_reset_handler_size();
 		memcpy((void *)(uintptr_t)val, (void *)(uintptr_t)BL31_BASE,
-		       (uintptr_t)&__BL31_END__ - (uintptr_t)BL31_BASE);
+		       src_len_in_bytes);
+
+		/* Disable SE clock after SE context save */
+		ret = tegra_bpmp_ipc_disable_clock(TEGRA194_CLK_SE);
+		assert(ret == 0);
 	}
 
-	return PSCI_E_SUCCESS;
+	return ret;
 }
 
 int32_t tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state)
diff --git a/plat/nvidia/tegra/soc/t194/plat_secondary.c b/plat/nvidia/tegra/soc/t194/plat_secondary.c
index c397c91..0882142 100644
--- a/plat/nvidia/tegra/soc/t194/plat_secondary.c
+++ b/plat/nvidia/tegra/soc/t194/plat_secondary.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,6 +13,8 @@
 #include <tegra_def.h>
 #include <tegra_private.h>
 
+extern uint64_t tegra_bl31_phys_base;
+
 #define MISCREG_AA64_RST_LOW		0x2004U
 #define MISCREG_AA64_RST_HIGH		0x2008U
 
@@ -25,10 +27,14 @@
 {
 	uint32_t addr_low, addr_high;
 	plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
-	uint64_t cpu_reset_handler_base, cpu_reset_handler_size;
+	uint64_t cpu_reset_handler_base, cpu_reset_handler_size, tzdram_addr;
+	uint64_t src_len_bytes = BL_END - tegra_bl31_phys_base;
 
 	INFO("Setting up secondary CPU boot\n");
 
+	tzdram_addr = params_from_bl2->tzdram_base +
+		      tegra194_get_cpu_reset_handler_size();
+
 	/*
 	 * The BL31 code resides in the TZSRAM which loses state
 	 * when we enter System Suspend. Copy the wakeup trampoline
@@ -53,4 +59,8 @@
 			addr_low);
 	mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_HI,
 			addr_high);
+	mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV72_LO,
+						(uint32_t)tzdram_addr);
+	mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV72_HI,
+						(uint32_t)src_len_bytes);
 }
diff --git a/plat/nvidia/tegra/soc/t194/plat_smmu.c b/plat/nvidia/tegra/soc/t194/plat_smmu.c
index 3b4a380..310e951 100644
--- a/plat/nvidia/tegra/soc/t194/plat_smmu.c
+++ b/plat/nvidia/tegra/soc/t194/plat_smmu.c
@@ -8,7 +8,6 @@
 #include <common/debug.h>
 #include <smmu.h>
 #include <tegra_def.h>
-#include <tegra_mc_def.h>
 
 #define BOARD_SYSTEM_FPGA_BASE		U(1)
 #define BASE_CONFIG_SMMU_DEVICES	U(2)
@@ -20,276 +19,6 @@
 }
 
 /*******************************************************************************
- * Array to hold SMMU context for Tegra194
- ******************************************************************************/
-static __attribute__((aligned(16))) smmu_regs_t tegra194_smmu_context[] = {
-	_START_OF_TABLE_,
-	mc_make_sid_security_cfg(HDAR),
-	mc_make_sid_security_cfg(HOST1XDMAR),
-	mc_make_sid_security_cfg(NVENCSRD),
-	mc_make_sid_security_cfg(SATAR),
-	mc_make_sid_security_cfg(NVENCSWR),
-	mc_make_sid_security_cfg(HDAW),
-	mc_make_sid_security_cfg(SATAW),
-	mc_make_sid_security_cfg(ISPRA),
-	mc_make_sid_security_cfg(ISPFALR),
-	mc_make_sid_security_cfg(ISPWA),
-	mc_make_sid_security_cfg(ISPWB),
-	mc_make_sid_security_cfg(XUSB_HOSTR),
-	mc_make_sid_security_cfg(XUSB_HOSTW),
-	mc_make_sid_security_cfg(XUSB_DEVR),
-	mc_make_sid_security_cfg(XUSB_DEVW),
-	mc_make_sid_security_cfg(TSECSRD),
-	mc_make_sid_security_cfg(TSECSWR),
-	mc_make_sid_security_cfg(SDMMCRA),
-	mc_make_sid_security_cfg(SDMMCR),
-	mc_make_sid_security_cfg(SDMMCRAB),
-	mc_make_sid_security_cfg(SDMMCWA),
-	mc_make_sid_security_cfg(SDMMCW),
-	mc_make_sid_security_cfg(SDMMCWAB),
-	mc_make_sid_security_cfg(VICSRD),
-	mc_make_sid_security_cfg(VICSWR),
-	mc_make_sid_security_cfg(VIW),
-	mc_make_sid_security_cfg(NVDECSRD),
-	mc_make_sid_security_cfg(NVDECSWR),
-	mc_make_sid_security_cfg(APER),
-	mc_make_sid_security_cfg(APEW),
-	mc_make_sid_security_cfg(NVJPGSRD),
-	mc_make_sid_security_cfg(NVJPGSWR),
-	mc_make_sid_security_cfg(SESRD),
-	mc_make_sid_security_cfg(SESWR),
-	mc_make_sid_security_cfg(AXIAPR),
-	mc_make_sid_security_cfg(AXIAPW),
-	mc_make_sid_security_cfg(ETRR),
-	mc_make_sid_security_cfg(ETRW),
-	mc_make_sid_security_cfg(TSECSRDB),
-	mc_make_sid_security_cfg(TSECSWRB),
-	mc_make_sid_security_cfg(AXISR),
-	mc_make_sid_security_cfg(AXISW),
-	mc_make_sid_security_cfg(EQOSR),
-	mc_make_sid_security_cfg(EQOSW),
-	mc_make_sid_security_cfg(UFSHCR),
-	mc_make_sid_security_cfg(UFSHCW),
-	mc_make_sid_security_cfg(NVDISPLAYR),
-	mc_make_sid_security_cfg(BPMPR),
-	mc_make_sid_security_cfg(BPMPW),
-	mc_make_sid_security_cfg(BPMPDMAR),
-	mc_make_sid_security_cfg(BPMPDMAW),
-	mc_make_sid_security_cfg(AONR),
-	mc_make_sid_security_cfg(AONW),
-	mc_make_sid_security_cfg(AONDMAR),
-	mc_make_sid_security_cfg(AONDMAW),
-	mc_make_sid_security_cfg(SCER),
-	mc_make_sid_security_cfg(SCEW),
-	mc_make_sid_security_cfg(SCEDMAR),
-	mc_make_sid_security_cfg(SCEDMAW),
-	mc_make_sid_security_cfg(APEDMAR),
-	mc_make_sid_security_cfg(APEDMAW),
-	mc_make_sid_security_cfg(NVDISPLAYR1),
-	mc_make_sid_security_cfg(VICSRD1),
-	mc_make_sid_security_cfg(NVDECSRD1),
-	mc_make_sid_security_cfg(VIFALR),
-	mc_make_sid_security_cfg(VIFALW),
-	mc_make_sid_security_cfg(DLA0RDA),
-	mc_make_sid_security_cfg(DLA0FALRDB),
-	mc_make_sid_security_cfg(DLA0WRA),
-	mc_make_sid_security_cfg(DLA0FALWRB),
-	mc_make_sid_security_cfg(DLA1RDA),
-	mc_make_sid_security_cfg(DLA1FALRDB),
-	mc_make_sid_security_cfg(DLA1WRA),
-	mc_make_sid_security_cfg(DLA1FALWRB),
-	mc_make_sid_security_cfg(PVA0RDA),
-	mc_make_sid_security_cfg(PVA0RDB),
-	mc_make_sid_security_cfg(PVA0RDC),
-	mc_make_sid_security_cfg(PVA0WRA),
-	mc_make_sid_security_cfg(PVA0WRB),
-	mc_make_sid_security_cfg(PVA0WRC),
-	mc_make_sid_security_cfg(PVA1RDA),
-	mc_make_sid_security_cfg(PVA1RDB),
-	mc_make_sid_security_cfg(PVA1RDC),
-	mc_make_sid_security_cfg(PVA1WRA),
-	mc_make_sid_security_cfg(PVA1WRB),
-	mc_make_sid_security_cfg(PVA1WRC),
-	mc_make_sid_security_cfg(RCER),
-	mc_make_sid_security_cfg(RCEW),
-	mc_make_sid_security_cfg(RCEDMAR),
-	mc_make_sid_security_cfg(RCEDMAW),
-	mc_make_sid_security_cfg(NVENC1SRD),
-	mc_make_sid_security_cfg(NVENC1SWR),
-	mc_make_sid_security_cfg(PCIE0R),
-	mc_make_sid_security_cfg(PCIE0W),
-	mc_make_sid_security_cfg(PCIE1R),
-	mc_make_sid_security_cfg(PCIE1W),
-	mc_make_sid_security_cfg(PCIE2AR),
-	mc_make_sid_security_cfg(PCIE2AW),
-	mc_make_sid_security_cfg(PCIE3R),
-	mc_make_sid_security_cfg(PCIE3W),
-	mc_make_sid_security_cfg(PCIE4R),
-	mc_make_sid_security_cfg(PCIE4W),
-	mc_make_sid_security_cfg(PCIE5R),
-	mc_make_sid_security_cfg(PCIE5W),
-	mc_make_sid_security_cfg(ISPFALW),
-	mc_make_sid_security_cfg(DLA0RDA1),
-	mc_make_sid_security_cfg(DLA1RDA1),
-	mc_make_sid_security_cfg(PVA0RDA1),
-	mc_make_sid_security_cfg(PVA0RDB1),
-	mc_make_sid_security_cfg(PVA1RDA1),
-	mc_make_sid_security_cfg(PVA1RDB1),
-	mc_make_sid_security_cfg(PCIE5R1),
-	mc_make_sid_security_cfg(NVENCSRD1),
-	mc_make_sid_security_cfg(NVENC1SRD1),
-	mc_make_sid_security_cfg(ISPRA1),
-	mc_make_sid_security_cfg(PCIE0R1),
-	mc_make_sid_security_cfg(MIU0R),
-	mc_make_sid_security_cfg(MIU0W),
-	mc_make_sid_security_cfg(MIU1R),
-	mc_make_sid_security_cfg(MIU1W),
-	mc_make_sid_security_cfg(MIU2R),
-	mc_make_sid_security_cfg(MIU2W),
-	mc_make_sid_security_cfg(MIU3R),
-	mc_make_sid_security_cfg(MIU3W),
-	mc_make_sid_override_cfg(HDAR),
-	mc_make_sid_override_cfg(HOST1XDMAR),
-	mc_make_sid_override_cfg(NVENCSRD),
-	mc_make_sid_override_cfg(SATAR),
-	mc_make_sid_override_cfg(NVENCSWR),
-	mc_make_sid_override_cfg(HDAW),
-	mc_make_sid_override_cfg(SATAW),
-	mc_make_sid_override_cfg(ISPRA),
-	mc_make_sid_override_cfg(ISPFALR),
-	mc_make_sid_override_cfg(ISPWA),
-	mc_make_sid_override_cfg(ISPWB),
-	mc_make_sid_override_cfg(XUSB_HOSTR),
-	mc_make_sid_override_cfg(XUSB_HOSTW),
-	mc_make_sid_override_cfg(XUSB_DEVR),
-	mc_make_sid_override_cfg(XUSB_DEVW),
-	mc_make_sid_override_cfg(TSECSRD),
-	mc_make_sid_override_cfg(TSECSWR),
-	mc_make_sid_override_cfg(SDMMCRA),
-	mc_make_sid_override_cfg(SDMMCR),
-	mc_make_sid_override_cfg(SDMMCRAB),
-	mc_make_sid_override_cfg(SDMMCWA),
-	mc_make_sid_override_cfg(SDMMCW),
-	mc_make_sid_override_cfg(SDMMCWAB),
-	mc_make_sid_override_cfg(VICSRD),
-	mc_make_sid_override_cfg(VICSWR),
-	mc_make_sid_override_cfg(VIW),
-	mc_make_sid_override_cfg(NVDECSRD),
-	mc_make_sid_override_cfg(NVDECSWR),
-	mc_make_sid_override_cfg(APER),
-	mc_make_sid_override_cfg(APEW),
-	mc_make_sid_override_cfg(NVJPGSRD),
-	mc_make_sid_override_cfg(NVJPGSWR),
-	mc_make_sid_override_cfg(SESRD),
-	mc_make_sid_override_cfg(SESWR),
-	mc_make_sid_override_cfg(AXIAPR),
-	mc_make_sid_override_cfg(AXIAPW),
-	mc_make_sid_override_cfg(ETRR),
-	mc_make_sid_override_cfg(ETRW),
-	mc_make_sid_override_cfg(TSECSRDB),
-	mc_make_sid_override_cfg(TSECSWRB),
-	mc_make_sid_override_cfg(AXISR),
-	mc_make_sid_override_cfg(AXISW),
-	mc_make_sid_override_cfg(EQOSR),
-	mc_make_sid_override_cfg(EQOSW),
-	mc_make_sid_override_cfg(UFSHCR),
-	mc_make_sid_override_cfg(UFSHCW),
-	mc_make_sid_override_cfg(NVDISPLAYR),
-	mc_make_sid_override_cfg(BPMPR),
-	mc_make_sid_override_cfg(BPMPW),
-	mc_make_sid_override_cfg(BPMPDMAR),
-	mc_make_sid_override_cfg(BPMPDMAW),
-	mc_make_sid_override_cfg(AONR),
-	mc_make_sid_override_cfg(AONW),
-	mc_make_sid_override_cfg(AONDMAR),
-	mc_make_sid_override_cfg(AONDMAW),
-	mc_make_sid_override_cfg(SCER),
-	mc_make_sid_override_cfg(SCEW),
-	mc_make_sid_override_cfg(SCEDMAR),
-	mc_make_sid_override_cfg(SCEDMAW),
-	mc_make_sid_override_cfg(APEDMAR),
-	mc_make_sid_override_cfg(APEDMAW),
-	mc_make_sid_override_cfg(NVDISPLAYR1),
-	mc_make_sid_override_cfg(VICSRD1),
-	mc_make_sid_override_cfg(NVDECSRD1),
-	mc_make_sid_override_cfg(VIFALR),
-	mc_make_sid_override_cfg(VIFALW),
-	mc_make_sid_override_cfg(DLA0RDA),
-	mc_make_sid_override_cfg(DLA0FALRDB),
-	mc_make_sid_override_cfg(DLA0WRA),
-	mc_make_sid_override_cfg(DLA0FALWRB),
-	mc_make_sid_override_cfg(DLA1RDA),
-	mc_make_sid_override_cfg(DLA1FALRDB),
-	mc_make_sid_override_cfg(DLA1WRA),
-	mc_make_sid_override_cfg(DLA1FALWRB),
-	mc_make_sid_override_cfg(PVA0RDA),
-	mc_make_sid_override_cfg(PVA0RDB),
-	mc_make_sid_override_cfg(PVA0RDC),
-	mc_make_sid_override_cfg(PVA0WRA),
-	mc_make_sid_override_cfg(PVA0WRB),
-	mc_make_sid_override_cfg(PVA0WRC),
-	mc_make_sid_override_cfg(PVA1RDA),
-	mc_make_sid_override_cfg(PVA1RDB),
-	mc_make_sid_override_cfg(PVA1RDC),
-	mc_make_sid_override_cfg(PVA1WRA),
-	mc_make_sid_override_cfg(PVA1WRB),
-	mc_make_sid_override_cfg(PVA1WRC),
-	mc_make_sid_override_cfg(RCER),
-	mc_make_sid_override_cfg(RCEW),
-	mc_make_sid_override_cfg(RCEDMAR),
-	mc_make_sid_override_cfg(RCEDMAW),
-	mc_make_sid_override_cfg(NVENC1SRD),
-	mc_make_sid_override_cfg(NVENC1SWR),
-	mc_make_sid_override_cfg(PCIE0R),
-	mc_make_sid_override_cfg(PCIE0W),
-	mc_make_sid_override_cfg(PCIE1R),
-	mc_make_sid_override_cfg(PCIE1W),
-	mc_make_sid_override_cfg(PCIE2AR),
-	mc_make_sid_override_cfg(PCIE2AW),
-	mc_make_sid_override_cfg(PCIE3R),
-	mc_make_sid_override_cfg(PCIE3W),
-	mc_make_sid_override_cfg(PCIE4R),
-	mc_make_sid_override_cfg(PCIE4W),
-	mc_make_sid_override_cfg(PCIE5R),
-	mc_make_sid_override_cfg(PCIE5W),
-	mc_make_sid_override_cfg(ISPFALW),
-	mc_make_sid_override_cfg(DLA0RDA1),
-	mc_make_sid_override_cfg(DLA1RDA1),
-	mc_make_sid_override_cfg(PVA0RDA1),
-	mc_make_sid_override_cfg(PVA0RDB1),
-	mc_make_sid_override_cfg(PVA1RDA1),
-	mc_make_sid_override_cfg(PVA1RDB1),
-	mc_make_sid_override_cfg(PCIE5R1),
-	mc_make_sid_override_cfg(NVENCSRD1),
-	mc_make_sid_override_cfg(NVENC1SRD1),
-	mc_make_sid_override_cfg(ISPRA1),
-	mc_make_sid_override_cfg(PCIE0R1),
-	mc_make_sid_override_cfg(MIU0R),
-	mc_make_sid_override_cfg(MIU0W),
-	mc_make_sid_override_cfg(MIU1R),
-	mc_make_sid_override_cfg(MIU1W),
-	mc_make_sid_override_cfg(MIU2R),
-	mc_make_sid_override_cfg(MIU2W),
-	mc_make_sid_override_cfg(MIU3R),
-	mc_make_sid_override_cfg(MIU3W),
-	smmu_make_cfg(TEGRA_SMMU0_BASE),
-	smmu_make_cfg(TEGRA_SMMU2_BASE),
-	smmu_bypass_cfg,	/* TBU settings */
-	_END_OF_TABLE_,
-};
-
-/*******************************************************************************
- * Handler to return the pointer to the SMMU's context struct
- ******************************************************************************/
-smmu_regs_t *plat_get_smmu_ctx(void)
-{
-	/* index of _END_OF_TABLE_ */
-	tegra194_smmu_context[0].val = (uint32_t)ARRAY_SIZE(tegra194_smmu_context) - 1U;
-
-	return tegra194_smmu_context;
-}
-
-/*******************************************************************************
  * Handler to return the support SMMU devices number
  ******************************************************************************/
 uint32_t plat_get_num_smmu_devices(void)
diff --git a/plat/nvidia/tegra/soc/t194/plat_trampoline.S b/plat/nvidia/tegra/soc/t194/plat_trampoline.S
index 540c201..819920f 100644
--- a/plat/nvidia/tegra/soc/t194/plat_trampoline.S
+++ b/plat/nvidia/tegra/soc/t194/plat_trampoline.S
@@ -12,7 +12,7 @@
 
 #define TEGRA194_STATE_SYSTEM_SUSPEND	0x5C7
 #define TEGRA194_STATE_SYSTEM_RESUME	0x600D
-#define TEGRA194_SMMU_CTX_SIZE		0x80D
+#define TEGRA194_MC_CTX_SIZE		0xFB
 
 	.align 4
 	.globl	tegra194_cpu_reset_handler
@@ -69,8 +69,8 @@
 	 *
 	 * 0x0000: secure world's entrypoint
 	 * 0x0008: BL31 size (RO + RW)
-	 * 0x0010: SMMU context start
-	 * 0x2490: SMMU context end
+	 * 0x0010: MC context start
+	 * 0x2490: MC context end
 	 */
 
 	.align 4
@@ -79,14 +79,13 @@
 __tegra194_cpu_reset_handler_data:
 	.quad	tegra_secure_entrypoint
 	.quad	__BL31_END__ - BL31_BASE
-
 	.globl	__tegra194_system_suspend_state
 __tegra194_system_suspend_state:
 	.quad	0
 
 	.align 4
-__tegra194_smmu_context:
-	.rept	TEGRA194_SMMU_CTX_SIZE
+__tegra194_mc_context:
+	.rept	TEGRA194_MC_CTX_SIZE
 	.quad	0
 	.endr
 	.size	__tegra194_cpu_reset_handler_data, \
@@ -98,7 +97,7 @@
 
 	.globl tegra194_get_cpu_reset_handler_size
 	.globl tegra194_get_cpu_reset_handler_base
-	.globl tegra194_get_smmu_ctx_offset
+	.globl tegra194_get_mc_ctx_offset
 	.globl tegra194_set_system_suspend_entry
 
 /* return size of the CPU reset handler */
@@ -115,13 +114,13 @@
 	ret
 endfunc tegra194_get_cpu_reset_handler_base
 
-/* return the size of the SMMU context */
-func tegra194_get_smmu_ctx_offset
-	adr	x0, __tegra194_smmu_context
+/* return the size of the MC context */
+func tegra194_get_mc_ctx_offset
+	adr	x0, __tegra194_mc_context
 	adr	x1, tegra194_cpu_reset_handler
 	sub	x0, x0, x1
 	ret
-endfunc tegra194_get_smmu_ctx_offset
+endfunc tegra194_get_mc_ctx_offset
 
 /* set system suspend state before SC7 entry */
 func tegra194_set_system_suspend_entry
diff --git a/plat/nvidia/tegra/soc/t210/plat_setup.c b/plat/nvidia/tegra/soc/t210/plat_setup.c
index 933e925..6d014bf 100644
--- a/plat/nvidia/tegra/soc/t210/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t210/plat_setup.c
@@ -179,6 +179,8 @@
 
 /* Secure IRQs for Tegra186 */
 static const interrupt_prop_t tegra210_interrupt_props[] = {
+	INTR_PROP_DESC(TEGRA210_TIMER1_IRQ, GIC_HIGHEST_SEC_PRIORITY,
+			GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
 	INTR_PROP_DESC(TEGRA210_WDT_CPU_LEGACY_FIQ, GIC_HIGHEST_SEC_PRIORITY,
 			GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
 };
diff --git a/plat/nvidia/tegra/soc/t210/plat_sip_calls.c b/plat/nvidia/tegra/soc/t210/plat_sip_calls.c
index 7d26fe7..904f8d6 100644
--- a/plat/nvidia/tegra/soc/t210/plat_sip_calls.c
+++ b/plat/nvidia/tegra/soc/t210/plat_sip_calls.c
@@ -88,7 +88,6 @@
 			return -EINVAL;
 		}
 	} else {
-		ERROR("%s: unsupported function ID\n", __func__);
 		return -ENOTSUP;
 	}
 	return 0;
diff --git a/services/arm_arch_svc/arm_arch_svc_setup.c b/services/arm_arch_svc/arm_arch_svc_setup.c
index 6dac56e..ba53930 100644
--- a/services/arm_arch_svc/arm_arch_svc_setup.c
+++ b/services/arm_arch_svc/arm_arch_svc_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,18 +12,27 @@
 #include <lib/smccc.h>
 #include <services/arm_arch_svc.h>
 #include <smccc_helpers.h>
+#include <plat/common/platform.h>
 
 static int32_t smccc_version(void)
 {
 	return MAKE_SMCCC_VERSION(SMCCC_MAJOR_VERSION, SMCCC_MINOR_VERSION);
 }
 
-static int32_t smccc_arch_features(u_register_t arg)
+static int32_t smccc_arch_features(u_register_t arg1, u_register_t arg2)
 {
-	switch (arg) {
+	switch (arg1) {
 	case SMCCC_VERSION:
 	case SMCCC_ARCH_FEATURES:
 		return SMC_OK;
+	case SMCCC_ARCH_SOC_ID:
+		if (arg2 == SMCCC_GET_SOC_REVISION) {
+			return plat_get_soc_revision();
+		}
+		if (arg2 == SMCCC_GET_SOC_VERSION) {
+			return plat_get_soc_version();
+		}
+		return SMC_ARCH_CALL_INVAL_PARAM;
 #if WORKAROUND_CVE_2017_5715
 	case SMCCC_ARCH_WORKAROUND_1:
 		if (check_wa_cve_2017_5715() == ERRATA_NOT_APPLIES)
@@ -94,7 +103,7 @@
 	case SMCCC_VERSION:
 		SMC_RET1(handle, smccc_version());
 	case SMCCC_ARCH_FEATURES:
-		SMC_RET1(handle, smccc_arch_features(x1));
+		SMC_RET1(handle, smccc_arch_features(x1, x2));
 #if WORKAROUND_CVE_2017_5715
 	case SMCCC_ARCH_WORKAROUND_1:
 		/*
diff --git a/services/spd/tlkd/tlkd_main.c b/services/spd/tlkd/tlkd_main.c
index 3cfc52d..32ae8ec 100644
--- a/services/spd/tlkd/tlkd_main.c
+++ b/services/spd/tlkd/tlkd_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,6 +14,7 @@
  * responsible for initialising and maintaining communication with the SP.
  ******************************************************************************/
 #include <assert.h>
+#include <bl31/interrupt_mgmt.h>
 #include <errno.h>
 #include <stddef.h>
 
@@ -49,6 +50,50 @@
 static int32_t tlkd_init(void);
 
 /*******************************************************************************
+ * Secure Payload Dispatcher's timer interrupt handler
+ ******************************************************************************/
+static uint64_t tlkd_interrupt_handler(uint32_t id,
+					uint32_t flags,
+					void *handle,
+					void *cookie)
+{
+	cpu_context_t *s_cpu_context;
+	int irq = plat_ic_get_pending_interrupt_id();
+
+	/* acknowledge the interrupt and mark it complete */
+	(void)plat_ic_acknowledge_interrupt();
+	plat_ic_end_of_interrupt(irq);
+
+	/*
+	 * Disable the routing of NS interrupts from secure world to
+	 * EL3 while interrupted on this core.
+	 */
+	disable_intr_rm_local(INTR_TYPE_S_EL1, SECURE);
+
+	/* Check the security state when the exception was generated */
+	assert(get_interrupt_src_ss(flags) == NON_SECURE);
+	assert(handle == cm_get_context(NON_SECURE));
+
+	/* Save non-secure state */
+	cm_el1_sysregs_context_save(NON_SECURE);
+
+	/* Get a reference to the secure context */
+	s_cpu_context = cm_get_context(SECURE);
+	assert(s_cpu_context);
+
+	/*
+	 * Restore non-secure state. There is no need to save the
+	 * secure system register context since the SP was supposed
+	 * to preserve it during S-EL1 interrupt handling.
+	 */
+	cm_el1_sysregs_context_restore(SECURE);
+	cm_set_next_eret_context(SECURE);
+
+	/* Provide the IRQ number to the SPD */
+	SMC_RET4(s_cpu_context, (uint32_t)TLK_IRQ_FIRED, 0, (uint32_t)irq, 0);
+}
+
+/*******************************************************************************
  * 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.
@@ -56,6 +101,8 @@
 static int32_t tlkd_setup(void)
 {
 	entry_point_info_t *tlk_ep_info;
+	uint32_t flags;
+	int32_t ret;
 
 	/*
 	 * Get information about the Secure Payload (BL32) image. Its
@@ -86,6 +133,18 @@
 		tlk_ep_info->pc,
 		&tlk_ctx);
 
+	/* get a list of all S-EL1 IRQs from the platform */
+
+	/* register interrupt handler */
+	flags = 0;
+	set_interrupt_rm_flag(flags, NON_SECURE);
+	ret = register_interrupt_type_handler(INTR_TYPE_S_EL1,
+					      tlkd_interrupt_handler,
+					      flags);
+	if (ret != 0) {
+		ERROR("failed to register tlkd interrupt handler (%d)\n", ret);
+	}
+
 	/*
 	 * All TLK SPD initialization done. Now register our init function
 	 * with BL31 for deferred invocation
@@ -385,6 +444,34 @@
 		break;
 
 	/*
+	 * This function ID is used by SP to indicate that it has completed
+	 * handling the secure interrupt.
+	 */
+	case TLK_IRQ_DONE:
+
+		if (ns)
+			SMC_RET1(handle, SMC_UNK);
+
+		assert(handle == cm_get_context(SECURE));
+
+		/* save secure world context */
+		cm_el1_sysregs_context_save(SECURE);
+
+		/* Get a reference to the non-secure context */
+		ns_cpu_context = cm_get_context(NON_SECURE);
+		assert(ns_cpu_context);
+
+		/*
+		 * Restore non-secure state. There is no need to save the
+		 * secure system register context since the SP was supposed
+		 * to preserve it during S-EL1 interrupt handling.
+		 */
+		cm_el1_sysregs_context_restore(NON_SECURE);
+		cm_set_next_eret_context(NON_SECURE);
+
+		SMC_RET0(ns_cpu_context);
+
+	/*
 	 * Return the number of service function IDs implemented to
 	 * provide service to non-secure
 	 */
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
index 2cdf4f5..a3e1a2d 100644
--- a/services/std_svc/spmd/spmd_main.c
+++ b/services/std_svc/spmd/spmd_main.c
@@ -162,6 +162,16 @@
 	INFO("SPM core run time EL%x.\n",
 	     SPMD_SPM_AT_SEL2 ? MODE_EL2 : MODE_EL1);
 
+	/* Validate the SPMC ID, Ensure high bit is set */
+	if (!(spmc_attrs.spmc_id >> SPMC_SECURE_ID_SHIFT) &
+			SPMC_SECURE_ID_MASK) {
+		WARN("Invalid ID (0x%x) for SPMC.\n",
+		     spmc_attrs.spmc_id);
+		return 1;
+	}
+
+	INFO("SPMC ID %x.\n", spmc_attrs.spmc_id);
+
 	/* Validate the SPM core execution state */
 	if ((spmc_attrs.exec_state != MODE_RW_64) &&
 	    (spmc_attrs.exec_state != MODE_RW_32)) {
@@ -436,6 +446,26 @@
 
 		break; /* not reached */
 
+	case SPCI_ID_GET:
+		/*
+		 * Returns the ID of the calling SPCI component.
+		*/
+		if (!secure_origin) {
+			SMC_RET8(handle, SPCI_SUCCESS_SMC32,
+				 SPCI_TARGET_INFO_MBZ, SPCI_NS_ENDPOINT_ID,
+				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
+				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
+				 SPCI_PARAM_MBZ);
+		} else {
+			SMC_RET8(handle, SPCI_SUCCESS_SMC32,
+				 SPCI_TARGET_INFO_MBZ, spmc_attrs.spmc_id,
+				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
+				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
+				 SPCI_PARAM_MBZ);
+		}
+
+		break; /* not reached */
+
 	case SPCI_RX_RELEASE:
 	case SPCI_RXTX_MAP_SMC32:
 	case SPCI_RXTX_MAP_SMC64:
diff --git a/services/std_svc/spmd/spmd_private.h b/services/std_svc/spmd/spmd_private.h
index 61b479a..0ad35c7 100644
--- a/services/std_svc/spmd/spmd_private.h
+++ b/services/std_svc/spmd/spmd_private.h
@@ -55,6 +55,15 @@
 } spmd_spm_core_context_t;
 
 /*
+ * Reserve ID for NS physical SPCI Endpoint.
+ */
+#define SPCI_NS_ENDPOINT_ID		U(0)
+
+/* Mask and shift to check valid secure SPCI Endpoint ID. */
+#define SPMC_SECURE_ID_MASK		0x1
+#define SPMC_SECURE_ID_SHIFT		15
+
+/*
  * Data structure used by the SPM dispatcher (SPMD) in EL3 to track sequence of
  * SPCI calls from lower ELs.
  *