Merge "io_fip: return -ENFILE when a file is already open" into integration
diff --git a/Makefile b/Makefile
index becbf03..65ebb93 100644
--- a/Makefile
+++ b/Makefile
@@ -659,6 +659,10 @@
 	SDEI_SUPPORT is enabled")
 endif
 
+ifeq ($(COT_DESC_IN_DTB),1)
+    $(info CoT in device tree is an experimental feature)
+endif
+
 # If pointer authentication is used in the firmware, make sure that all the
 # registers associated to it are also saved and restored.
 # Not doing it would leak the value of the keys used by EL3 to EL1 and S-EL1.
@@ -903,6 +907,7 @@
 $(eval $(call assert_boolean,ENCRYPT_BL32))
 $(eval $(call assert_boolean,ERRATA_SPECULATIVE_AT))
 $(eval $(call assert_boolean,RAS_TRAP_LOWER_EL_ERR_ACCESS))
+$(eval $(call assert_boolean,COT_DESC_IN_DTB))
 
 $(eval $(call assert_numeric,ARM_ARCH_MAJOR))
 $(eval $(call assert_numeric,ARM_ARCH_MINOR))
@@ -983,6 +988,7 @@
 $(eval $(call add_define,USE_SPINLOCK_CAS))
 $(eval $(call add_define,ERRATA_SPECULATIVE_AT))
 $(eval $(call add_define,RAS_TRAP_LOWER_EL_ERR_ACCESS))
+$(eval $(call add_define,COT_DESC_IN_DTB))
 
 ifeq (${SANITIZE_UB},trap)
         $(eval $(call add_define,MONITOR_TRAPS))
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index bf29186..0014d3b 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -21,7 +21,7 @@
 :G: `soby-mathew`_
 :M: Sandrine Bailleux <sandrine.bailleux@arm.com>
 :G: `sandrine-bailleux-arm`_
-:M: Alexei Fedorov <alexei.fedorov@arm.com>
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
 :G: `AlexeiFedorov`_
 :M: Manish Pandey <manish.pandey2@arm.com>
 :G: `manish-pandey-arm`_
@@ -60,6 +60,14 @@
 :M: Etienne Carriere <etienne.carriere@linaro.org>
 :G: `etienne-lms`_
 
+Build Definitions for CMake Build System
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:M: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
+:G: `javieralso-arm`_
+:M: Jack Bond-Preston <Jack.Bond-Preston@arm.com>
+:G: `jackbondpreston-arm`_
+:F: /
+
 Software Delegated Exception Interface (SDEI)
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 :M: Mark Dykes <mark.dykes@arm.com>
@@ -185,7 +193,7 @@
 
 Activity Monitors Unit (AMU) extensions
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Alexei Fedorov <alexei.fedorov@arm.com>
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
 :G: `AlexeiFedorov`_
 :F: lib/extensions/amu/
 
@@ -199,7 +207,7 @@
 
 Pointer Authentication (PAuth) and Branch Target Identification (BTI) extensions
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Alexei Fedorov <alexei.fedorov@arm.com>
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
 :G: `AlexeiFedorov`_
 :M: Zelalem Aweke <Zelalem.Aweke@arm.com>
 :G: `zelalem-aweke`_
@@ -221,7 +229,7 @@
 
 Standard C library
 ^^^^^^^^^^^^^^^^^^
-:M: Alexei Fedorov <alexei.fedorov@arm.com>
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
 :G: `AlexeiFedorov`_
 :M: John Powell <John.Powell@arm.com>
 :G: `john-powell-arm`_
@@ -251,7 +259,7 @@
 
 GIC driver
 ^^^^^^^^^^
-:M: Alexei Fedorov <alexei.fedorov@arm.com>
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
 :G: `AlexeiFedorov`_
 :M: Manish Pandey <manish.pandey2@arm.com>
 :G: `manish-pandey-arm`_
@@ -277,6 +285,15 @@
 :F: include/drivers/io/io_encrypted.h
 :F: include/tools_share/firmware_encrypted.h
 
+Measured Boot
+^^^^^^^^^^^^^
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
+:G: `AlexeiFedorov`_
+:M: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
+:G: `javieralso-arm`_
+:F: drivers/measured_boot
+:F: include/drivers/measured_boot
+:F: plat/arm/board/fvp/fvp_measured_boot.c
 
 Platform Ports
 ~~~~~~~~~~~~~~
@@ -320,6 +337,14 @@
 :F: docs/plat/meson-axg.rst
 :F: plat/amlogic/axg/
 
+Arm FPGA platform port
+^^^^^^^^^^^^^^^^^^^^^^
+:M: Andre Przywara <andre.przywara@arm.com>
+:G: `Andre-ARM`_
+:M: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
+:G: `javieralso-arm`_
+:F: plat/arm/board/arm_fpga
+
 Arm System Guidance for Infrastructure / Mobile FVP platforms
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 :M: Nariman Poushin <nariman.poushin@linaro.org>
@@ -613,6 +638,6 @@
 .. _madhukar-Arm: https://github.com/madhukar-Arm
 .. _john-powell-arm: https://github.com/john-powell-arm
 .. _raghuncstate: https://github.com/raghuncstate
-
+.. _jackbondpreston-arm: https://github.com/jackbondpreston-arm
 
 .. _Project Maintenance Process: https://developer.trustedfirmware.org/w/collaboration/project-maintenance-process/
diff --git a/docs/components/cot-binding.rst b/docs/components/cot-binding.rst
index cc69d79..46915db 100644
--- a/docs/components/cot-binding.rst
+++ b/docs/components/cot-binding.rst
@@ -1,23 +1,23 @@
 Chain of trust bindings
 =======================
 
-The device tree allows to describes the chain of trust with the help of
-certificates and images nodes, which in turn contains number of sub-nodes
-(i.e. certificate and image) mentioning properties for every certificate
-and image respectively.
-Also, this binding allows to describe OID of non-volatile counters, memory
-mapped address and size of non-volatile counter register.
+The device tree allows to describe the chain of trust with the help of
+'cot' node which contain 'manifests' and 'images' as sub-nodes.
+'manifests' and 'images' nodes contains number of sub-nodes (i.e. 'certificate'
+and 'image' nodes) mentioning properties of the certificate and image respectively.
 
-Convention used in this document
---------------------------------
+Also, device tree describes 'non-volatile-counters' node which contains number of
+sub-nodes mentioning properties of all non-volatile-counters used in the chain of trust.
 
-This document follows the conventions described in the Device-tree
-Specification
+cot
+------------------------------------------------------------------
+This is root node which contains 'manifests' and 'images' as sub-nodes
 
-certificates, certificate and extension node bindings definition
+
+Manifests and Certificate node bindings definition
 ----------------------------------------------------------------
 
-- Certificates node
+- Manifests node
         Description: Container of certificate nodes.
 
         PROPERTIES
@@ -27,20 +27,24 @@
 
                 Value type: <string>
 
-                Definition: must be "arm, certificate-descriptors"
+                Definition: must be "arm, cert-descs"
 
 - Certificate node
-        Description: Describes certificate properties which are used
-                     during the authentication process.
+        Description:
+
+        Describes certificate properties which are used
+        during the authentication process.
 
         PROPERTIES
 
         - root-certificate
-                Usage: Required for the certificate with no parent.
-                       In other words, Certificates which are validated
-                       using root of trust public key.
+               Usage:
 
-                Value type: <boolean>
+               Required for the certificate with no parent.
+               In other words, certificates which are validated
+               using root of trust public key.
+
+               Value type: <boolean>
 
         - image-id
                 Usage: Required for every certificate with unique id.
@@ -48,99 +52,121 @@
                 Value type: <u32>
 
         - parent
-                Usage: It refers to their parent image, which typically contains
-                       information to authenticate the certificate.
-                       This property is required for all non-root certificates.
+                Usage:
 
-                       This property is not required for root-certificates
-                       as it is validated using root of trust public key
-                       provided by platform.
+                It refers to their parent image, which typically contains
+                information to authenticate the certificate.
+                This property is required for all non-root certificates.
+
+                This property is not required for root-certificates
+                as root-certificates are validated using root of trust
+                public key provided by platform.
 
                 Value type: <phandle>
 
         - signing-key
-                Usage: This property is used to refer extension node present in
-                       parent certificate and it is required property for all non-
-                       root certificates which are authenticated using public-key
-                       present in parent certificate.
+                Usage:
 
-                       This property is not required for root-certificates
-                       as root-certificates are validated using root of trust
-                       public key provided by platform.
+                This property is used to refer public key node present in
+                parent certificate node and it is required property for all
+                non-root certificates which are authenticated using public-key
+                present in parent certificate.
+
+                This property is not required for root-certificates
+                as root-certificates are validated using root of trust
+                public key provided by platform.
 
                 Value type: <phandle>
 
         - antirollback-counter
-                Usage: This property is used by all certificates which are protected
-                       against rollback attacks using a non-volatile counter and it
-                       is optional property.
+                Usage:
 
-                       This property is used to refer trusted or non-trusted
-                       non-volatile counter node.
+                This property is used by all certificates which are
+                protected against rollback attacks using a non-volatile
+                counter and it is an optional property.
+
+                This property is used to refer one of the non-volatile
+                counter sub-node present in 'non-volatile counters' node.
 
                 Value type: <phandle>
 
+
         SUBNODES
+            - Description:
 
-        - extensions node
-                Description: This is sub-node of certificate node.
-                             Describes OIDs present in the certificate which will
-                             be used during authentication process to extract
-                             hash/public key information from this certificate.
-                             OIDs in extension node are represented using number of
-                             sub-nodes which contains 'oid' as property
+              Hash and public key information present in the certificate
+              are shown by these nodes.
 
-                PROPERTIES
+            - public key node
+                  Description: Provide public key information in the certificate.
 
-                - oid
-                        Usage: This property provides the Object ID of an extension
-                               provided in the certificate.
+                  PROPERTIES
 
-                        Value type: <string>
+                  - oid
+                     Usage:
+
+                     This property provides the Object ID of public key
+                     provided in the certificate which the help of which
+                     public key information can be extracted.
+
+                     Value type: <string>
+
+            - hash node
+                 Description: Provide the hash information in the certificate.
+
+                 PROPERTIES
+
+                 - oid
+                     Usage:
+
+                     This property provides the Object ID of hash provided in
+                     the certificate which the help of which hash information
+                     can be extracted.
+
+                     Value type: <string>
 
 Example:
 
 .. code:: c
 
-   certificates {
-         compatible = "arm, certificate-descriptors”
+   cot {
+      manifests {
+         compatible = "arm, cert-descs”
 
          trusted-key-cert: trusted-key-cert {
-                  root-certificate;
-                  image-id = <TRUSTED_KEY_CERT_ID>;
-                  antirollback-counter = <&trusted_nv_counter>;
-                  extensions {
-                        trusted-world-pk: trusted-world-pk {
-                              oid = TRUSTED_WORLD_PK_OID;
-                        };
-                        non-trusted-world-pk: non-trusted-world-pk {
-                              oid = NON_TRUSTED_WORLD_PK_OID;
-                        };
-                };
-        };
+            root-certificate;
+            image-id = <TRUSTED_KEY_CERT_ID>;
+            antirollback-counter = <&trusted_nv_counter>;
 
-        scp_fw_key_cert: scp_fw_key_cert {
-                image-id = <SCP_FW_KEY_CERT_ID>;
-                parent = <&trusted-key-cert>;
-                signing-key = <&trusted_world_pk>;
-                antirollback-counter = <&trusted_nv_counter>;
-                extensions {
-                        scp_fw_content_pk: scp_fw_content_pk {
-                              oid = SCP_FW_CONTENT_CERT_PK_OID;
-                        };
-                };
-        };
+            trusted-world-pk: trusted-world-pk {
+               oid = TRUSTED_WORLD_PK_OID;
+            };
+            non-trusted-world-pk: non-trusted-world-pk {
+               oid = NON_TRUSTED_WORLD_PK_OID;
+            };
+         };
 
-        .
-        .
-        .
+         scp_fw_key_cert: scp_fw_key_cert {
+            image-id = <SCP_FW_KEY_CERT_ID>;
+            parent = <&trusted-key-cert>;
+            signing-key = <&trusted_world_pk>;
+            antirollback-counter = <&trusted_nv_counter>;
 
-        next-cert {
+            scp_fw_content_pk: scp_fw_content_pk {
+               oid = SCP_FW_CONTENT_CERT_PK_OID;
+            };
+         };
+         .
+         .
+         .
 
-        };
+         next-certificate {
+
+         };
+      };
    };
 
-Images and image node bindings definition
+Images and Image node bindings definition
 -----------------------------------------
 
 - Images node
@@ -153,11 +179,13 @@
 
                 Value type: <string>
 
-                Definition: must be "arm, image-descriptors"
+                Definition: must be "arm, img-descs"
 
 - Image node
-        Description: Describes image properties which will be used during
-                     authentication process.
+        Description:
+
+        Describes image properties which will be used during
+        authentication process.
 
         PROPERTIES
 
@@ -167,35 +195,41 @@
                 Value type: <u32>
 
         - parent
-                Usage: Required for every image to provide a reference to
-                       it's parent image, which contains the necessary information
-                       to authenticate it.
+                Usage:
+
+                Required for every image to provide a reference to
+                its parent image, which contains the necessary information
+                to authenticate it.
 
                 Value type: <phandle>
 
         - hash
-                Usage: Required for all images which are validated using
-                       hash method. This property is used to refer extension
-                       node present in parent certificate and it is required
-                       property for all images.
+                Usage:
+
+                Required for all images which are validated using
+                hash method. This property is used to refer hash
+                node present in parent certificate node.
 
                 Value type: <phandle>
 
-                Note: Currently, all images are validated using "hash"
-                      method. In future, there may be multiple methods can
-                      be used to validate the image.
+                Note:
+
+                Currently, all images are validated using 'hash'
+                method. In future, there may be multiple methods can
+                be used to validate the image.
 
 Example:
 
 .. code:: c
 
-   images {
-         compatible = "arm, imgage-descriptors";
+   cot {
+      images {
+         compatible = "arm, img-descs";
 
          scp_bl2_image {
-               image-id = <SCP_BL2_IMAGE_ID>;
-               parent = <&scp_fw_content_cert>;
-               hash = <&scp_fw_hash>;
+            image-id = <SCP_BL2_IMAGE_ID>;
+            parent = <&scp_fw_content_cert>;
+            hash = <&scp_fw_hash>;
          };
 
          .
@@ -203,7 +237,9 @@
          .
 
          next-img {
+
          };
+      };
    };
 
 non-volatile counter node binding definition
@@ -226,8 +262,10 @@
 
                 Value type: <u32>
 
-                Definition: Must be set according to address size
-                            of non-volatile counter register
+                Definition:
+
+                Must be set according to address size
+                of non-volatile counter register
 
         - #size-cells
                 Usage: required
@@ -243,14 +281,18 @@
             PROPERTIES
 
                 - reg
-                    Usage: Register base address of non-volatile counter and it is required
-                           property.
+                    Usage:
+
+                    Register base address of non-volatile counter and it is required
+                    property.
 
                     Value type: <u32>
 
                 - oid
-                    Usage: This property provides the Object ID of non-volatile counter
-                           provided in the certificate and it is required property.
+                    Usage:
+
+                    This property provides the Object ID of non-volatile counter
+                    provided in the certificate and it is required property.
 
                     Value type: <string>
 
@@ -280,8 +322,7 @@
 Future update to chain of trust binding
 ---------------------------------------
 
-This binding document need to be revisited to generalise some terminologies
-like Object IDs, extensions etc which are currently specific to X.509
-certificates.
+This binding document needs to be revisited to generalise some terminologies
+which are currently specific to X.509 certificates for e.g. Object IDs.
 
-*Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2020, Arm Limited. All rights reserved.*
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 81903e1..bfc50df 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -648,6 +648,13 @@
    configuration device tree, instead of static structure in the code base.
    This is currently an experimental feature.
 
+-  ``COT_DESC_IN_DTB``: This flag determines whether to create COT descriptors
+   at runtime using fconf. If this flag is enabled, COT descriptors are
+   statically captured in tb_fw_config file in the form of device tree nodes
+   and properties. Currently, COT descriptors used by BL2 are moved to the
+   device tree and COT descriptors used by BL1 are retained in the code
+   base statically. This is currently an experimental feature.
+
 -  ``SDEI_IN_FCONF``: This flag determines whether to configure SDEI setup in
    runtime using firmware configuration framework. The platform specific SDEI
    shared and private events configuration is retrieved from device tree rather
diff --git a/docs/plat/imx8m.rst b/docs/plat/imx8m.rst
index ba087a2..f184b69 100644
--- a/docs/plat/imx8m.rst
+++ b/docs/plat/imx8m.rst
@@ -33,6 +33,7 @@
    Target_SoC should be "imx8mq" for i.MX8MQ SoC.
    Target_SoC should be "imx8mm" for i.MX8MM SoC.
    Target_SoC should be "imx8mn" for i.MX8MN SoC.
+   Target_SoC should be "imx8mp" for i.MX8MP SoC.
 
 Deploy TF-A Images
 ~~~~~~~~~~~~~~~~~~
diff --git a/docs/plat/marvell/armada/build.rst b/docs/plat/marvell/armada/build.rst
index bec0bcb..da4ba56 100644
--- a/docs/plat/marvell/armada/build.rst
+++ b/docs/plat/marvell/armada/build.rst
@@ -79,10 +79,12 @@
 
 - LLC_SRAM
 
-        Flag defining the LLC (L3) cache SRAM support. The feature is
-        disabled by default (``LLC_ENABLE=0``).
-        When LLC SRAM is enabled, the secure payload (BL32) is loaded into this
-        SRAM area instead of the DRAM.
+        Flag enabling the LLC (L3) cache SRAM support. The LLC SRAM is activated and used
+        by Trusted OS (OP-TEE OS, BL32). The TF-A only prepares CCU address translation windows
+        for SRAM address range at BL31 execution stage with window target set to DRAM-0.
+        When Trusted OS activates LLC SRAM, the CCU window target is changed to SRAM.
+        There is no reason to enable this feature if OP-TEE OS built with CFG_WITH_PAGER=n.
+        Only set LLC_SRAM=1 if OP-TEE OS is built with CFG_WITH_PAGER=y.
 
 - MARVELL_SECURE_BOOT
 
diff --git a/drivers/arm/gic/common/gic_common.c b/drivers/arm/gic/common/gic_common.c
index 38b2f67..bf6405f 100644
--- a/drivers/arm/gic/common/gic_common.c
+++ b/drivers/arm/gic/common/gic_common.c
@@ -1,9 +1,11 @@
 /*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#pragma message __FILE__ " is deprecated, use gicv2.mk instead"
+
 #include <assert.h>
 
 #include <drivers/arm/gic_common.h>
diff --git a/drivers/arm/gic/v2/gicdv2_helpers.c b/drivers/arm/gic/v2/gicdv2_helpers.c
new file mode 100644
index 0000000..db9ba87
--- /dev/null
+++ b/drivers/arm/gic/v2/gicdv2_helpers.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <drivers/arm/gic_common.h>
+#include <lib/mmio.h>
+
+#include "../common/gic_common_private.h"
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for reading entire registers
+ ******************************************************************************/
+/*
+ * Accessor to read the GIC Distributor IGROUPR corresponding to the interrupt
+ * `id`, 32 interrupt ids at a time.
+ */
+unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> IGROUPR_SHIFT;
+
+	return mmio_read_32(base + GICD_IGROUPR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ISENABLER corresponding to the
+ * interrupt `id`, 32 interrupt ids at a time.
+ */
+unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ISENABLER_SHIFT;
+
+	return mmio_read_32(base + GICD_ISENABLER + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ICENABLER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ICENABLER_SHIFT;
+
+	return mmio_read_32(base + GICD_ICENABLER + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ISPENDR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ISPENDR_SHIFT;
+
+	return mmio_read_32(base + GICD_ISPENDR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ICPENDR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ICPENDR_SHIFT;
+
+	return mmio_read_32(base + GICD_ICPENDR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ISACTIVER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ISACTIVER_SHIFT;
+
+	return mmio_read_32(base + GICD_ISACTIVER + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ICACTIVER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ICACTIVER_SHIFT;
+
+	return mmio_read_32(base + GICD_ICACTIVER + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor IPRIORITYR corresponding to the
+ * interrupt `id`, 4 interrupt IDs at a time.
+ */
+unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> IPRIORITYR_SHIFT;
+
+	return mmio_read_32(base + GICD_IPRIORITYR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ICGFR corresponding to the
+ * interrupt `id`, 16 interrupt IDs at a time.
+ */
+unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ICFGR_SHIFT;
+
+	return mmio_read_32(base + GICD_ICFGR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor NSACR corresponding to the
+ * interrupt `id`, 16 interrupt IDs at a time.
+ */
+unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> NSACR_SHIFT;
+
+	return mmio_read_32(base + GICD_NSACR + (n << 2));
+}
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for writing entire registers
+ ******************************************************************************/
+/*
+ * Accessor to write the GIC Distributor IGROUPR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> IGROUPR_SHIFT;
+
+	mmio_write_32(base + GICD_IGROUPR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ISENABLER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> ISENABLER_SHIFT;
+
+	mmio_write_32(base + GICD_ISENABLER + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ICENABLER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> ICENABLER_SHIFT;
+
+	mmio_write_32(base + GICD_ICENABLER + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ISPENDR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> ISPENDR_SHIFT;
+
+	mmio_write_32(base + GICD_ISPENDR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ICPENDR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> ICPENDR_SHIFT;
+
+	mmio_write_32(base + GICD_ICPENDR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ISACTIVER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> ISACTIVER_SHIFT;
+
+	mmio_write_32(base + GICD_ISACTIVER + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ICACTIVER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> ICACTIVER_SHIFT;
+
+	mmio_write_32(base + GICD_ICACTIVER + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor IPRIORITYR corresponding to the
+ * interrupt `id`, 4 interrupt IDs at a time.
+ */
+void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> IPRIORITYR_SHIFT;
+
+	mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ICFGR corresponding to the
+ * interrupt `id`, 16 interrupt IDs at a time.
+ */
+void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> ICFGR_SHIFT;
+
+	mmio_write_32(base + GICD_ICFGR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor NSACR corresponding to the
+ * interrupt `id`, 16 interrupt IDs at a time.
+ */
+void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> NSACR_SHIFT;
+
+	mmio_write_32(base + GICD_NSACR + (n << 2), val);
+}
+
+/*******************************************************************************
+ * GIC Distributor functions for accessing the GIC registers
+ * corresponding to a single interrupt ID. These functions use bitwise
+ * operations or appropriate register accesses to modify or return
+ * the bit-field corresponding the single interrupt ID.
+ ******************************************************************************/
+unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
+	unsigned int reg_val = gicd_read_igroupr(base, id);
+
+	return (reg_val >> bit_num) & 0x1U;
+}
+
+void gicd_set_igroupr(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
+	unsigned int reg_val = gicd_read_igroupr(base, id);
+
+	gicd_write_igroupr(base, id, reg_val | (1U << bit_num));
+}
+
+void gicd_clr_igroupr(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
+	unsigned int reg_val = gicd_read_igroupr(base, id);
+
+	gicd_write_igroupr(base, id, reg_val & ~(1U << bit_num));
+}
+
+void gicd_set_isenabler(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ISENABLER_SHIFT) - 1U);
+
+	gicd_write_isenabler(base, id, (1U << bit_num));
+}
+
+void gicd_set_icenabler(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ICENABLER_SHIFT) - 1U);
+
+	gicd_write_icenabler(base, id, (1U << bit_num));
+}
+
+void gicd_set_ispendr(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ISPENDR_SHIFT) - 1U);
+
+	gicd_write_ispendr(base, id, (1U << bit_num));
+}
+
+void gicd_set_icpendr(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ICPENDR_SHIFT) - 1U);
+
+	gicd_write_icpendr(base, id, (1U << bit_num));
+}
+
+unsigned int gicd_get_isactiver(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U);
+	unsigned int reg_val = gicd_read_isactiver(base, id);
+
+	return (reg_val >> bit_num) & 0x1U;
+}
+
+void gicd_set_isactiver(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U);
+
+	gicd_write_isactiver(base, id, (1U << bit_num));
+}
+
+void gicd_set_icactiver(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ICACTIVER_SHIFT) - 1U);
+
+	gicd_write_icactiver(base, id, (1U << bit_num));
+}
+
+void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
+{
+	uint8_t val = pri & GIC_PRI_MASK;
+
+	mmio_write_8(base + GICD_IPRIORITYR + id, val);
+}
+
+void gicd_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg)
+{
+	/* Interrupt configuration is a 2-bit field */
+	unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U);
+	unsigned int bit_shift = bit_num << 1;
+
+	uint32_t reg_val = gicd_read_icfgr(base, id);
+
+	/* Clear the field, and insert required configuration */
+	reg_val &= ~(GIC_CFG_MASK << bit_shift);
+	reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift);
+
+	gicd_write_icfgr(base, id, reg_val);
+}
diff --git a/drivers/arm/gic/v2/gicv2.mk b/drivers/arm/gic/v2/gicv2.mk
new file mode 100644
index 0000000..49996bb
--- /dev/null
+++ b/drivers/arm/gic/v2/gicv2.mk
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# No support for extended PPI and SPI range
+GIC_EXT_INTID	:=	0
+
+GICV2_SOURCES	+=	drivers/arm/gic/v2/gicv2_main.c		\
+			drivers/arm/gic/v2/gicv2_helpers.c	\
+			drivers/arm/gic/v2/gicdv2_helpers.c
+
+# Set GICv2 build option
+$(eval $(call add_define,GIC_EXT_INTID))
\ No newline at end of file
diff --git a/drivers/arm/gic/v3/gic-x00.c b/drivers/arm/gic/v3/gic-x00.c
index cc97174..c9e9cb9 100644
--- a/drivers/arm/gic/v3/gic-x00.c
+++ b/drivers/arm/gic/v3/gic-x00.c
@@ -24,6 +24,7 @@
 #define GICR_PWRR			0x24
 #define IIDR_MODEL_ARM_GIC_600		(0x0200043b)
 #define IIDR_MODEL_ARM_GIC_600AE	(0x0300043b)
+#define IIDR_MODEL_ARM_GIC_CLAYTON	(0x0400043b)
 
 /* GICR_PWRR fields */
 #define PWRR_RDPD_SHIFT			0
@@ -45,7 +46,7 @@
 
 #if GICV3_SUPPORT_GIC600
 
-/* GIC-600 specific accessor functions */
+/* GIC-600/Clayton specific accessor functions */
 static void gicr_write_pwrr(uintptr_t base, unsigned int val)
 {
 	mmio_write_32(base + GICR_PWRR, val);
@@ -113,12 +114,17 @@
 	return gicr_base;
 }
 
-static bool gicv3_is_gic600(uintptr_t gicr_base)
+static bool gicv3_redists_need_power_mgmt(uintptr_t gicr_base)
 {
 	uint32_t reg = mmio_read_32(gicr_base + GICR_IIDR);
 
+	/*
+	 * The Arm GIC-600 and GIC-Clayton models have their redistributors
+	 * powered down at reset.
+	 */
 	return (((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) ||
-		((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600AE));
+		((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600AE) ||
+		((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_CLAYTON));
 }
 
 #endif
@@ -143,7 +149,7 @@
 	uintptr_t gicr_base = get_gicr_base(proc_num);
 
 	/* Attempt to power redistributor off */
-	if (gicv3_is_gic600(gicr_base)) {
+	if (gicv3_redists_need_power_mgmt(gicr_base)) {
 		gic600_pwr_off(gicr_base);
 	}
 #endif
@@ -158,7 +164,7 @@
 	uintptr_t gicr_base = get_gicr_base(proc_num);
 
 	/* Power redistributor on */
-	if (gicv3_is_gic600(gicr_base)) {
+	if (gicv3_redists_need_power_mgmt(gicr_base)) {
 		gic600_pwr_on(gicr_base);
 	}
 #endif
diff --git a/drivers/brcm/rng.c b/drivers/brcm/rng.c
new file mode 100644
index 0000000..ee2e656
--- /dev/null
+++ b/drivers/brcm/rng.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#define RNG_CTRL_REG		(RNG_BASE_ADDR + 0x00)
+#define RNG_CTRL_MASK		0x00001FFF
+#define RNG_CTRL_ENABLE		0x00000001
+#define RNG_CTRL_DISABLE	0x00000000
+
+#define RNG_SOFT_RESET_REG	(RNG_BASE_ADDR + 0x04)
+#define RNG_SOFT_RESET_MASK	0x00000001
+
+#define RNG_FIFO_DATA_REG	(RNG_BASE_ADDR + 0x20)
+
+#define RNG_FIFO_COUNT_REG	(RNG_BASE_ADDR + 0x24)
+#define RNG_FIFO_COUNT_MASK	0x000000FF
+
+#define RNG_FIFO_WORDS_MAX	16
+#define MAX_WAIT_COUNT_50US	20000
+
+
+static void rng_reset(void)
+{
+	/* Disable RBG */
+	mmio_clrbits_32(RNG_CTRL_REG, RNG_CTRL_MASK);
+
+	/* Reset RNG and RBG */
+	mmio_setbits_32(RNG_SOFT_RESET_REG, RNG_SOFT_RESET_MASK);
+
+	/* Take all out of reset */
+	mmio_clrbits_32(RNG_SOFT_RESET_REG, RNG_SOFT_RESET_MASK);
+}
+
+static void rng_enable(void)
+{
+	/* Setup RNG. */
+	mmio_clrsetbits_32(RNG_CTRL_REG, RNG_CTRL_MASK, RNG_CTRL_ENABLE);
+}
+
+int rng_init(void)
+{
+	rng_reset();
+
+	rng_enable();
+
+	return 0;
+}
+
+int rng_read(uint32_t *p_out, uint32_t *words_read)
+{
+	uint32_t available_words;
+	uint32_t i;
+	uint32_t word_processed = 0;
+	uint32_t wait_count = MAX_WAIT_COUNT_50US;
+
+	if (*words_read == 0) {
+		ERROR("RNG Parameter: No word requested\n");
+		return -1;
+	}
+
+	do {
+		available_words = mmio_read_32(RNG_FIFO_COUNT_REG);
+		available_words &= RNG_FIFO_COUNT_MASK;
+
+		if (available_words != 0) {
+			available_words = MIN(available_words,
+					*words_read - word_processed);
+
+			for (i = 0; i < available_words; i++)
+				p_out[word_processed + i] =
+					mmio_read_32(RNG_FIFO_DATA_REG);
+			word_processed += available_words;
+		} else {
+			udelay(50);
+		}
+
+		if (word_processed == *words_read)
+			break;
+
+	} while (--wait_count);
+
+	if (word_processed != *words_read) {
+		ERROR("RNG Timeout: requested %d word(s) got %d\n",
+				*words_read, word_processed);
+		*words_read = word_processed;
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/drivers/io/io_fip.c b/drivers/io/io_fip.c
index 7aa717d..6e15295 100644
--- a/drivers/io/io_fip.c
+++ b/drivers/io/io_fip.c
@@ -36,7 +36,7 @@
 typedef struct {
 	unsigned int file_pos;
 	fip_toc_entry_t entry;
-} file_state_t;
+} fip_file_state_t;
 
 /*
  * Maintain dev_spec per FIP Device
@@ -49,7 +49,6 @@
 	uint16_t plat_toc_flag;
 } fip_dev_state_t;
 
-static const uuid_t uuid_null;
 /*
  * Only one file can be open across all FIP device
  * as backends like io_memmap don't support
@@ -57,7 +56,7 @@
  * backend handle should be maintained per FIP device
  * if the same support is available in the backend
  */
-static file_state_t current_file = {0};
+static fip_file_state_t current_fip_file = {0};
 static uintptr_t backend_dev_handle;
 static uintptr_t backend_image_spec;
 
@@ -288,6 +287,7 @@
 	int result;
 	uintptr_t backend_handle;
 	const io_uuid_spec_t *uuid_spec = (io_uuid_spec_t *)spec;
+	static const uuid_t uuid_null = { {0} }; /* Double braces for clang */
 	size_t bytes_read;
 	int found_file = 0;
 
@@ -300,7 +300,7 @@
 	 * When the system supports dynamic memory allocation we can allow more
 	 * than one open file at a time if needed.
 	 */
-	if (current_file.entry.offset_address != 0) {
+	if (current_fip_file.entry.offset_address != 0U) {
 		WARN("fip_file_open : Only one open file at a time.\n");
 		return -ENFILE;
 	}
@@ -326,31 +326,32 @@
 	found_file = 0;
 	do {
 		result = io_read(backend_handle,
-				 (uintptr_t)&current_file.entry,
-				 sizeof(current_file.entry),
+				 (uintptr_t)&current_fip_file.entry,
+				 sizeof(current_fip_file.entry),
 				 &bytes_read);
 		if (result == 0) {
-			if (compare_uuids(&current_file.entry.uuid,
+			if (compare_uuids(&current_fip_file.entry.uuid,
 					  &uuid_spec->uuid) == 0) {
 				found_file = 1;
-				break;
 			}
 		} else {
 			WARN("Failed to read FIP (%i)\n", result);
 			goto fip_file_open_close;
 		}
-	} while (compare_uuids(&current_file.entry.uuid, &uuid_null) != 0);
+	} while ((found_file == 0) &&
+			(compare_uuids(&current_fip_file.entry.uuid,
+				&uuid_null) != 0));
 
 	if (found_file == 1) {
 		/* All fine. Update entity info with file state and return. Set
-		 * the file position to 0. The 'current_file.entry' holds the
-		 * base and size of the file.
+		 * the file position to 0. The 'current_fip_file.entry' holds
+		 * the base and size of the file.
 		 */
-		current_file.file_pos = 0;
-		entity->info = (uintptr_t)&current_file;
+		current_fip_file.file_pos = 0;
+		entity->info = (uintptr_t)&current_fip_file;
 	} else {
 		/* Did not find the file in the FIP. */
-		current_file.entry.offset_address = 0;
+		current_fip_file.entry.offset_address = 0;
 		result = -ENOENT;
 	}
 
@@ -368,7 +369,7 @@
 	assert(entity != NULL);
 	assert(length != NULL);
 
-	*length =  ((file_state_t *)entity->info)->entry.size;
+	*length =  ((fip_file_state_t *)entity->info)->entry.size;
 
 	return 0;
 }
@@ -379,7 +380,7 @@
 			  size_t *length_read)
 {
 	int result;
-	file_state_t *fp;
+	fip_file_state_t *fp;
 	size_t file_offset;
 	size_t bytes_read;
 	uintptr_t backend_handle;
@@ -397,7 +398,7 @@
 		goto fip_file_read_exit;
 	}
 
-	fp = (file_state_t *)entity->info;
+	fp = (fip_file_state_t *)entity->info;
 
 	/* Seek to the position in the FIP where the payload lives */
 	file_offset = fp->entry.offset_address + fp->file_pos;
@@ -436,8 +437,8 @@
 	/* Clear our current file pointer.
 	 * If we had malloc() we would free() here.
 	 */
-	if (current_file.entry.offset_address != 0) {
-		zeromem(&current_file, sizeof(current_file));
+	if (current_fip_file.entry.offset_address != 0U) {
+		zeromem(&current_fip_file, sizeof(current_fip_file));
 	}
 
 	/* Clear the Entity info. */
diff --git a/drivers/io/io_memmap.c b/drivers/io/io_memmap.c
index eed50cc..eb69163 100644
--- a/drivers/io/io_memmap.c
+++ b/drivers/io/io_memmap.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -27,9 +27,9 @@
 	uintptr_t		base;
 	unsigned long long	file_pos;
 	unsigned long long	size;
-} file_state_t;
+} memmap_file_state_t;
 
-static file_state_t current_file = {0};
+static memmap_file_state_t current_memmap_file = {0};
 
 /* Identify the device type as memmap */
 static io_type_t device_type_memmap(void)
@@ -71,7 +71,7 @@
 
 
 /* No state associated with this device so structure can be const */
-static const io_dev_info_t memmap_dev_info = {
+static io_dev_info_t memmap_dev_info = {
 	.funcs = &memmap_dev_funcs,
 	.info = (uintptr_t)NULL
 };
@@ -82,8 +82,7 @@
 			   io_dev_info_t **dev_info)
 {
 	assert(dev_info != NULL);
-	*dev_info = (io_dev_info_t *)&memmap_dev_info; /* cast away const */
-
+	*dev_info = &memmap_dev_info;
 	return 0;
 }
 
@@ -109,16 +108,16 @@
 	 * spec at a time. When we have dynamic memory we can malloc and set
 	 * entity->info.
 	 */
-	if (current_file.in_use == 0) {
+	if (current_memmap_file.in_use == 0) {
 		assert(block_spec != NULL);
 		assert(entity != NULL);
 
-		current_file.in_use = 1;
-		current_file.base = block_spec->offset;
+		current_memmap_file.in_use = 1;
+		current_memmap_file.base = block_spec->offset;
 		/* File cursor offset for seek and incremental reads etc. */
-		current_file.file_pos = 0;
-		current_file.size = block_spec->length;
-		entity->info = (uintptr_t)&current_file;
+		current_memmap_file.file_pos = 0;
+		current_memmap_file.size = block_spec->length;
+		entity->info = (uintptr_t)&current_memmap_file;
 		result = 0;
 	} else {
 		WARN("A Memmap device is already active. Close first.\n");
@@ -133,13 +132,13 @@
 			     signed long long offset)
 {
 	int result = -ENOENT;
-	file_state_t *fp;
+	memmap_file_state_t *fp;
 
 	/* We only support IO_SEEK_SET for the moment. */
 	if (mode == IO_SEEK_SET) {
 		assert(entity != NULL);
 
-		fp = (file_state_t *) entity->info;
+		fp = (memmap_file_state_t *) entity->info;
 
 		/* Assert that new file position is valid */
 		assert((offset >= 0) &&
@@ -160,7 +159,7 @@
 	assert(entity != NULL);
 	assert(length != NULL);
 
-	*length = (size_t)((file_state_t *)entity->info)->size;
+	*length = (size_t)((memmap_file_state_t *)entity->info)->size;
 
 	return 0;
 }
@@ -170,13 +169,13 @@
 static int memmap_block_read(io_entity_t *entity, uintptr_t buffer,
 			     size_t length, size_t *length_read)
 {
-	file_state_t *fp;
+	memmap_file_state_t *fp;
 	unsigned long long pos_after;
 
 	assert(entity != NULL);
 	assert(length_read != NULL);
 
-	fp = (file_state_t *) entity->info;
+	fp = (memmap_file_state_t *) entity->info;
 
 	/* Assert that file position is valid for this read operation */
 	pos_after = fp->file_pos + length;
@@ -198,13 +197,13 @@
 static int memmap_block_write(io_entity_t *entity, const uintptr_t buffer,
 			      size_t length, size_t *length_written)
 {
-	file_state_t *fp;
+	memmap_file_state_t *fp;
 	unsigned long long pos_after;
 
 	assert(entity != NULL);
 	assert(length_written != NULL);
 
-	fp = (file_state_t *) entity->info;
+	fp = (memmap_file_state_t *) entity->info;
 
 	/* Assert that file position is valid for this write operation */
 	pos_after = fp->file_pos + length;
@@ -230,7 +229,7 @@
 	entity->info = 0;
 
 	/* This would be a mem free() if we had malloc.*/
-	zeromem((void *)&current_file, sizeof(current_file));
+	zeromem((void *)&current_memmap_file, sizeof(current_memmap_file));
 
 	return 0;
 }
diff --git a/drivers/io/io_semihosting.c b/drivers/io/io_semihosting.c
index 4ceddc6..1c2f84d 100644
--- a/drivers/io/io_semihosting.c
+++ b/drivers/io/io_semihosting.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -51,8 +51,7 @@
 };
 
 
-/* No state associated with this device so structure can be const */
-static const io_dev_info_t sh_dev_info = {
+static io_dev_info_t sh_dev_info = {
 	.funcs = &sh_dev_funcs,
 	.info = (uintptr_t)NULL
 };
@@ -63,7 +62,7 @@
 		io_dev_info_t **dev_info)
 {
 	assert(dev_info != NULL);
-	*dev_info = (io_dev_info_t *)&sh_dev_info; /* cast away const */
+	*dev_info = &sh_dev_info;
 	return 0;
 }
 
diff --git a/drivers/io/io_storage.c b/drivers/io/io_storage.c
index b8c1d64..0534268 100644
--- a/drivers/io/io_storage.c
+++ b/drivers/io/io_storage.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -32,36 +32,34 @@
 #if ENABLE_ASSERTIONS
 
 /* Return a boolean value indicating whether a device connector is valid */
-static int is_valid_dev_connector(const io_dev_connector_t *dev_con)
+static bool is_valid_dev_connector(const io_dev_connector_t *dev_con)
 {
-	int result = (dev_con != NULL) && (dev_con->dev_open != NULL);
-	return result;
+	return (dev_con != NULL) && (dev_con->dev_open != NULL);
 }
 
-
 /* Return a boolean value indicating whether a device handle is valid */
-static int is_valid_dev(const uintptr_t dev_handle)
+static bool is_valid_dev(const uintptr_t dev_handle)
 {
 	const io_dev_info_t *dev = (io_dev_info_t *)dev_handle;
-	int result = (dev != NULL) && (dev->funcs != NULL) &&
+
+	return (dev != NULL) && (dev->funcs != NULL) &&
 			(dev->funcs->type != NULL) &&
 			(dev->funcs->type() < IO_TYPE_MAX);
-	return result;
 }
 
 
 /* Return a boolean value indicating whether an IO entity is valid */
-static int is_valid_entity(const uintptr_t handle)
+static bool is_valid_entity(const uintptr_t handle)
 {
 	const io_entity_t *entity = (io_entity_t *)handle;
-	int result = (entity != NULL) &&
+
+	return (entity != NULL) &&
 			(is_valid_dev((uintptr_t)entity->dev_handle));
-	return result;
 }
 
 
 /* Return a boolean value indicating whether a seek mode is valid */
-static int is_valid_seek_mode(io_seek_mode_t mode)
+static bool is_valid_seek_mode(io_seek_mode_t mode)
 {
 	return ((mode != IO_SEEK_INVALID) && (mode < IO_SEEK_MAX));
 }
@@ -71,15 +69,14 @@
 
 
 /* Open a connection to a specific device */
-static int dev_open(const io_dev_connector_t *dev_con, const uintptr_t dev_spec,
+static int io_storage_dev_open(const io_dev_connector_t *dev_con,
+		const uintptr_t dev_spec,
 		io_dev_info_t **dev_info)
 {
-	int result;
 	assert(dev_info != NULL);
 	assert(is_valid_dev_connector(dev_con));
 
-	result = dev_con->dev_open(dev_spec, dev_info);
-	return result;
+	return dev_con->dev_open(dev_spec, dev_info);
 }
 
 
@@ -116,7 +113,8 @@
 		unsigned int index = 0;
 		result = find_first_entity(NULL, &index);
 		assert(result == 0);
-		*entity = entity_map[index] = &entity_pool[index];
+		*entity = &entity_pool[index];
+		entity_map[index] = &entity_pool[index];
 		++entity_count;
 	}
 
@@ -163,11 +161,8 @@
 int io_dev_open(const io_dev_connector_t *dev_con, const uintptr_t dev_spec,
 		uintptr_t *handle)
 {
-	int result;
 	assert(handle != NULL);
-
-	result = dev_open(dev_con, dev_spec, (io_dev_info_t **)handle);
-	return result;
+	return io_storage_dev_open(dev_con, dev_spec, (io_dev_info_t **)handle);
 }
 
 
diff --git a/drivers/marvell/cache_llc.c b/drivers/marvell/cache_llc.c
index 836aae7..4b06b47 100644
--- a/drivers/marvell/cache_llc.c
+++ b/drivers/marvell/cache_llc.c
@@ -111,28 +111,36 @@
 }
 
 #if LLC_SRAM
-void llc_sram_enable(int ap_index)
+int llc_sram_enable(int ap_index, int size)
 {
-	uint32_t tc, way;
+	uint32_t tc, way, ways_to_allocate;
 	uint32_t way_addr;
 
+	if ((size <= 0) || (size > LLC_SIZE) || (size % LLC_WAY_SIZE))
+		return -1;
+
+	llc_enable(ap_index, 1);
+	llc_inv_all(ap_index);
+
+	ways_to_allocate = size / LLC_WAY_SIZE;
+
 	/* Lockdown all available ways for all traffic classes */
 	for (tc = 0; tc < LLC_TC_NUM; tc++)
-		mmio_write_32(LLC_TCN_LOCK(ap_index, tc), LLC_WAY_MASK);
+		mmio_write_32(LLC_TCN_LOCK(ap_index, tc), LLC_ALL_WAYS_MASK);
 
 	/* Clear the high bits of SRAM address */
 	mmio_write_32(LLC_BANKED_MNT_AHR(ap_index), 0);
 
 	way_addr = PLAT_MARVELL_TRUSTED_RAM_BASE;
-	for (way = 0; way < LLC_WAYS; way++) {
+	for (way = 0; way < ways_to_allocate; way++) {
 		/* Trigger allocation block command */
 		mmio_write_32(LLC_BLK_ALOC(ap_index),
 			      LLC_BLK_ALOC_BASE_ADDR(way_addr) |
-			      LLC_BLK_ALOC_WAY_DATA_CLR |
+			      LLC_BLK_ALOC_WAY_DATA_SET |
 			      LLC_BLK_ALOC_WAY_ID(way));
 		way_addr += LLC_WAY_SIZE;
 	}
-	llc_enable(ap_index, 1);
+	return 0;
 }
 
 void llc_sram_disable(int ap_index)
@@ -146,4 +154,36 @@
 	/* Invalidate all ways */
 	llc_inv_all(ap_index);
 }
+
+int llc_sram_test(int ap_index, int size, char *msg)
+{
+	uintptr_t addr, end_addr;
+	uint32_t data = 0;
+
+	if ((size <= 0) || (size > LLC_SIZE))
+		return -1;
+
+	INFO("=== LLC SRAM WRITE test %s\n", msg);
+	for (addr = PLAT_MARVELL_TRUSTED_RAM_BASE,
+	     end_addr = PLAT_MARVELL_TRUSTED_RAM_BASE + size;
+	     addr < end_addr; addr += 4) {
+		mmio_write_32(addr, addr);
+	}
+	INFO("=== LLC SRAM WRITE test %s PASSED\n", msg);
+	INFO("=== LLC SRAM READ test %s\n", msg);
+	for (addr = PLAT_MARVELL_TRUSTED_RAM_BASE,
+	     end_addr = PLAT_MARVELL_TRUSTED_RAM_BASE + size;
+	     addr < end_addr; addr += 4) {
+		data = mmio_read_32(addr);
+		if (data != addr) {
+			INFO("=== LLC SRAM READ test %s FAILED @ 0x%08lx)\n",
+			     msg, addr);
+			return -1;
+		}
+	}
+	INFO("=== LLC SRAM READ test %s PASSED (last read = 0x%08x)\n",
+	     msg, data);
+	return 0;
+}
+
 #endif /* LLC_SRAM */
diff --git a/drivers/marvell/comphy/phy-comphy-cp110.c b/drivers/marvell/comphy/phy-comphy-cp110.c
index 2760f46..1d5b6f5 100644
--- a/drivers/marvell/comphy/phy-comphy-cp110.c
+++ b/drivers/marvell/comphy/phy-comphy-cp110.c
@@ -11,6 +11,7 @@
 
 #include <common/debug.h>
 #include <drivers/delay_timer.h>
+#include <mg_conf_cm3/mg_conf_cm3.h>
 #include <lib/mmio.h>
 #include <lib/spinlock.h>
 
@@ -2231,6 +2232,7 @@
 					  uint32_t comphy_mode)
 {
 	uint32_t mask, data;
+	uint8_t ap_nr, cp_nr;
 	uintptr_t comphy_addr = comphy_addr =
 				COMPHY_ADDR(comphy_base, comphy_index);
 
@@ -2247,6 +2249,10 @@
 	reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
 	debug_exit();
 
+	/* Start AP Firmware */
+	mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base);
+	mg_start_ap_fw(cp_nr, comphy_index);
+
 	return 0;
 }
 
diff --git a/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c b/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c
new file mode 100644
index 0000000..98e1896
--- /dev/null
+++ b/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2019 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <a8k_plat_def.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mss_scp_bl2_format.h>
+
+/* CONFI REGISTERS */
+#define MG_CM3_CONFI_BASE(CP)		(MVEBU_CP_REGS_BASE(CP) + 0x100000)
+#define MG_CM3_SRAM_BASE(CP)		MG_CM3_CONFI_BASE(CP)
+#define MG_CM3_CONFI_GLOB_CFG_REG(CP)	(MG_CM3_CONFI_BASE(CP) + 0x2B500)
+#define CM3_CPU_EN_BIT			BIT(28)
+#define MG_CM3_MG_INT_MFX_REG(CP)	(MG_CM3_CONFI_BASE(CP) + 0x2B054)
+#define CM3_SYS_RESET_BIT		BIT(0)
+
+#define MG_CM3_SHARED_MEM_BASE(CP)	(MG_CM3_SRAM_BASE(CP) + 0x1FC00ULL)
+
+#define MG_SRAM_SIZE	0x20000 /* 128KB */
+
+#define MG_ACK_TIMEOUT 10
+
+/**
+ * struct ap_sharedmem_ctrl - used to pass information between the HOST and CM3
+ * @init_done:	Set by CM3 when ap_proces initialzied. Host check if CM3 set
+ *		this flag to confirm that the process is running
+ * @lane_nr:	Set by Host to mark which comphy lane should be configure. E.g.:
+ *		- A8K development board uses comphy lane 2 for eth0
+ *		- CN913x development board uses comphy lane 4 for eth0
+ */
+struct ap_sharedmem_ctrl {
+	uint32_t init_done;
+	uint32_t lane_nr;
+};
+
+int mg_image_load(uintptr_t src_addr, uint32_t size, int cp_index)
+{
+	uintptr_t mg_regs = MG_CM3_SRAM_BASE(cp_index);
+
+	if (size > MG_SRAM_SIZE) {
+		ERROR("image is too big to fit into MG CM3 memory\n");
+		return 1;
+	}
+
+	NOTICE("Loading MG image from address 0x%lx Size 0x%x to MG at 0x%lx\n",
+	       src_addr, size, mg_regs);
+
+	/* Copy image to MG CM3 SRAM */
+	memcpy((void *)mg_regs, (void *)src_addr, size);
+
+	/* Don't release MG CM3 from reset - it will be done by next step
+	 * bootloader (e.g. U-Boot), when appriopriate device-tree setup (which
+	 * has enabeld 802.3. auto-neg) will be choosen.
+	 */
+
+	return 0;
+}
+
+void mg_start_ap_fw(int cp_nr, uint8_t comphy_index)
+{
+	volatile struct ap_sharedmem_ctrl *ap_shared_ctrl =
+					(void *)MG_CM3_SHARED_MEM_BASE(cp_nr);
+	int timeout = MG_ACK_TIMEOUT;
+
+	if (mmio_read_32(MG_CM3_CONFI_GLOB_CFG_REG(cp_nr)) & CM3_CPU_EN_BIT) {
+		VERBOSE("cm3 already running\n");
+		return;  /* cm3 already running */
+	}
+
+	/*
+	 * Mark which comphy lane should be used - it will be read via shared
+	 * mem by ap process
+	 */
+	ap_shared_ctrl->lane_nr = comphy_index;
+	/* Make sure it took place before enabling cm3 */
+	dmbst();
+
+	mmio_setbits_32(MG_CM3_CONFI_GLOB_CFG_REG(cp_nr), CM3_CPU_EN_BIT);
+	mmio_setbits_32(MG_CM3_MG_INT_MFX_REG(cp_nr), CM3_SYS_RESET_BIT);
+
+	/* Check for ap process initialization by fw */
+	while (ap_shared_ctrl->init_done != 1 && timeout--)
+		VERBOSE("Waiting for ap process ack, timeout %d\n", timeout);
+
+	if (timeout == 0) {
+		ERROR("AP process failed, disabling cm3\n");
+		mmio_clrbits_32(MG_CM3_MG_INT_MFX_REG(cp_nr),
+				CM3_SYS_RESET_BIT);
+		mmio_clrbits_32(MG_CM3_CONFI_GLOB_CFG_REG(cp_nr),
+				CM3_CPU_EN_BIT);
+	}
+}
diff --git a/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h b/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h
new file mode 100644
index 0000000..e2756de
--- /dev/null
+++ b/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2019 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+void mg_start_ap_fw(int cp_nr, uint8_t comphy_index);
+int mg_image_load(uintptr_t src_addr, uint32_t size, int cp_index);
diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
index 2f4dcad..d6cd8b1 100644
--- a/drivers/st/clk/stm32mp1_clk.c
+++ b/drivers/st/clk/stm32mp1_clk.c
@@ -577,6 +577,43 @@
 	1, 2, 3, 4, 4, 4, 4, 4
 };
 
+static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = {
+	[_HSI] = "HSI",
+	[_HSE] = "HSE",
+	[_CSI] = "CSI",
+	[_LSI] = "LSI",
+	[_LSE] = "LSE",
+	[_I2S_CKIN] = "I2S_CKIN",
+	[_HSI_KER] = "HSI_KER",
+	[_HSE_KER] = "HSE_KER",
+	[_HSE_KER_DIV2] = "HSE_KER_DIV2",
+	[_CSI_KER] = "CSI_KER",
+	[_PLL1_P] = "PLL1_P",
+	[_PLL1_Q] = "PLL1_Q",
+	[_PLL1_R] = "PLL1_R",
+	[_PLL2_P] = "PLL2_P",
+	[_PLL2_Q] = "PLL2_Q",
+	[_PLL2_R] = "PLL2_R",
+	[_PLL3_P] = "PLL3_P",
+	[_PLL3_Q] = "PLL3_Q",
+	[_PLL3_R] = "PLL3_R",
+	[_PLL4_P] = "PLL4_P",
+	[_PLL4_Q] = "PLL4_Q",
+	[_PLL4_R] = "PLL4_R",
+	[_ACLK] = "ACLK",
+	[_PCLK1] = "PCLK1",
+	[_PCLK2] = "PCLK2",
+	[_PCLK3] = "PCLK3",
+	[_PCLK4] = "PCLK4",
+	[_PCLK5] = "PCLK5",
+	[_HCLK6] = "KCLK6",
+	[_HCLK2] = "HCLK2",
+	[_CK_PER] = "CK_PER",
+	[_CK_MPU] = "CK_MPU",
+	[_CK_MCU] = "CK_MCU",
+	[_USB_PHY_48] = "USB_PHY_48",
+};
+
 /* RCC clock device driver private */
 static unsigned long stm32mp1_osc[NB_OSC];
 static struct spinlock reg_lock;
@@ -2007,6 +2044,165 @@
 	}
 }
 
+#ifdef STM32MP_SHARED_RESOURCES
+/*
+ * Get the parent ID of the target parent clock, for tagging as secure
+ * shared clock dependencies.
+ */
+static int get_parent_id_parent(unsigned int parent_id)
+{
+	enum stm32mp1_parent_sel s = _UNKNOWN_SEL;
+	enum stm32mp1_pll_id pll_id;
+	uint32_t p_sel;
+	uintptr_t rcc_base = stm32mp_rcc_base();
+
+	switch (parent_id) {
+	case _ACLK:
+	case _PCLK4:
+	case _PCLK5:
+		s = _AXIS_SEL;
+		break;
+	case _PLL1_P:
+	case _PLL1_Q:
+	case _PLL1_R:
+		pll_id = _PLL1;
+		break;
+	case _PLL2_P:
+	case _PLL2_Q:
+	case _PLL2_R:
+		pll_id = _PLL2;
+		break;
+	case _PLL3_P:
+	case _PLL3_Q:
+	case _PLL3_R:
+		pll_id = _PLL3;
+		break;
+	case _PLL4_P:
+	case _PLL4_Q:
+	case _PLL4_R:
+		pll_id = _PLL4;
+		break;
+	case _PCLK1:
+	case _PCLK2:
+	case _HCLK2:
+	case _HCLK6:
+	case _CK_PER:
+	case _CK_MPU:
+	case _CK_MCU:
+	case _USB_PHY_48:
+		/* We do not expect to access these */
+		panic();
+		break;
+	default:
+		/* Other parents have no parent */
+		return -1;
+	}
+
+	if (s != _UNKNOWN_SEL) {
+		const struct stm32mp1_clk_sel *sel = clk_sel_ref(s);
+
+		p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) &
+			sel->msk;
+
+		if (p_sel < sel->nb_parent) {
+			return (int)sel->parent[p_sel];
+		}
+	} else {
+		const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
+
+		p_sel = mmio_read_32(rcc_base + pll->rckxselr) &
+			RCC_SELR_REFCLK_SRC_MASK;
+
+		if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID) {
+			return (int)pll->refclk[p_sel];
+		}
+	}
+
+	VERBOSE("No parent selected for %s\n",
+		stm32mp1_clk_parent_name[parent_id]);
+
+	return -1;
+}
+
+static void secure_parent_clocks(unsigned long parent_id)
+{
+	int grandparent_id;
+
+	switch (parent_id) {
+	case _PLL3_P:
+	case _PLL3_Q:
+	case _PLL3_R:
+		stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3);
+		break;
+
+	/* These clocks are always secure when RCC is secure */
+	case _ACLK:
+	case _HCLK2:
+	case _HCLK6:
+	case _PCLK4:
+	case _PCLK5:
+	case _PLL1_P:
+	case _PLL1_Q:
+	case _PLL1_R:
+	case _PLL2_P:
+	case _PLL2_Q:
+	case _PLL2_R:
+	case _HSI:
+	case _HSI_KER:
+	case _LSI:
+	case _CSI:
+	case _CSI_KER:
+	case _HSE:
+	case _HSE_KER:
+	case _HSE_KER_DIV2:
+	case _LSE:
+		break;
+
+	default:
+		VERBOSE("Cannot secure parent clock %s\n",
+			stm32mp1_clk_parent_name[parent_id]);
+		panic();
+	}
+
+	grandparent_id = get_parent_id_parent(parent_id);
+	if (grandparent_id >= 0) {
+		secure_parent_clocks(grandparent_id);
+	}
+}
+
+void stm32mp1_register_clock_parents_secure(unsigned long clock_id)
+{
+	int parent_id;
+
+	if (!stm32mp1_rcc_is_secure()) {
+		return;
+	}
+
+	switch (clock_id) {
+	case PLL1:
+	case PLL2:
+		/* PLL1/PLL2 are always secure: nothing to do */
+		break;
+	case PLL3:
+		stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3);
+		break;
+	case PLL4:
+		ERROR("PLL4 cannot be secured\n");
+		panic();
+		break;
+	default:
+		/* Others are expected gateable clock */
+		parent_id = stm32mp1_clk_get_parent(clock_id);
+		if (parent_id < 0) {
+			INFO("No parent found for clock %lu\n", clock_id);
+		} else {
+			secure_parent_clocks(parent_id);
+		}
+		break;
+	}
+}
+#endif /* STM32MP_SHARED_RESOURCES */
+
 static void sync_earlyboot_clocks_state(void)
 {
 	unsigned int idx;
diff --git a/drivers/st/crypto/stm32_hash.c b/drivers/st/crypto/stm32_hash.c
index 3184df9..515947c 100644
--- a/drivers/st/crypto/stm32_hash.c
+++ b/drivers/st/crypto/stm32_hash.c
@@ -300,7 +300,9 @@
 			break;
 		}
 #else
+		/* BL32 uses hash if it is assigned only to secure world */
 		if (hash_info.status == DT_SECURE) {
+			stm32mp_register_secure_periph_iomem(hash_info.base);
 			break;
 		}
 #endif
diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c
index a13c341..bb77371 100644
--- a/drivers/st/gpio/stm32_gpio.c
+++ b/drivers/st/gpio/stm32_gpio.c
@@ -254,6 +254,15 @@
 		mmio_read_32(base + GPIO_AFRH_OFFSET));
 
 	stm32mp_clk_disable(clock);
+
+	if (status == DT_SECURE) {
+		stm32mp_register_secure_gpio(bank, pin);
+		set_gpio_secure_cfg(bank, pin, true);
+
+	} else {
+		stm32mp_register_non_secure_gpio(bank, pin);
+		set_gpio_secure_cfg(bank, pin, false);
+	}
 }
 
 void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure)
diff --git a/drivers/st/iwdg/stm32_iwdg.c b/drivers/st/iwdg/stm32_iwdg.c
index ea6fbb2..c052b4d 100644
--- a/drivers/st/iwdg/stm32_iwdg.c
+++ b/drivers/st/iwdg/stm32_iwdg.c
@@ -137,6 +137,12 @@
 			((dt_info.status & DT_NON_SECURE) != 0) ?
 			"non-" : "");
 
+		if ((dt_info.status & DT_NON_SECURE) != 0) {
+			stm32mp_register_non_secure_periph_iomem(iwdg->base);
+		} else {
+			stm32mp_register_secure_periph_iomem(iwdg->base);
+		}
+
 #if defined(IMAGE_BL2)
 		if (stm32_iwdg_shadow_update(idx, iwdg->flags) != BSEC_OK) {
 			return -1;
diff --git a/drivers/st/pmic/stm32mp_pmic.c b/drivers/st/pmic/stm32mp_pmic.c
index 9e9dddc..b2bb482 100644
--- a/drivers/st/pmic/stm32mp_pmic.c
+++ b/drivers/st/pmic/stm32mp_pmic.c
@@ -54,6 +54,15 @@
 	return fdt_get_status(node);
 }
 
+static bool dt_pmic_is_secure(void)
+{
+	int status = dt_pmic_status();
+
+	return (status >= 0) &&
+	       (status == DT_SECURE) &&
+	       (i2c_handle.dt_status == DT_SECURE);
+}
+
 /*
  * Get PMIC and its I2C bus configuration from the device tree.
  * Return 0 on success, negative on error, 1 if no PMIC node is found.
@@ -223,6 +232,19 @@
 	return true;
 }
 
+static void register_pmic_shared_peripherals(void)
+{
+	uintptr_t i2c_base = i2c_handle.i2c_base_addr;
+
+	if (dt_pmic_is_secure()) {
+		stm32mp_register_secure_periph_iomem(i2c_base);
+	} else {
+		if (i2c_base != 0U) {
+			stm32mp_register_non_secure_periph_iomem(i2c_base);
+		}
+	}
+}
+
 void initialize_pmic(void)
 {
 	unsigned long pmic_version;
@@ -232,6 +254,8 @@
 		return;
 	}
 
+	register_pmic_shared_peripherals();
+
 	if (stpmic1_get_version(&pmic_version) != 0) {
 		ERROR("Failed to access PMIC\n");
 		panic();
diff --git a/fdts/cot_descriptors.dtsi b/fdts/cot_descriptors.dtsi
new file mode 100644
index 0000000..753d56a
--- /dev/null
+++ b/fdts/cot_descriptors.dtsi
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <tools_share/tbbr_oid.h>
+#include <common/tbbr/tbbr_img_def.h>
+
+cot {
+	manifests {
+		compatible = "arm, cert-descs";
+
+		trusted_boot_fw_cert: trusted_boot_fw_cert {
+			root-certificate;
+			image-id =<TRUSTED_BOOT_FW_CERT_ID>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			tb_fw_hash: tb_fw_hash {
+				oid = TRUSTED_BOOT_FW_HASH_OID;
+			};
+			tb_fw_config_hash: tb_fw_config_hash {
+				oid = TRUSTED_BOOT_FW_CONFIG_HASH_OID;
+			};
+			hw_config_hash: hw_config_hash {
+				oid = HW_CONFIG_HASH_OID;
+			};
+			fw_config_hash: fw_config_hash {
+				oid = FW_CONFIG_HASH_OID;
+			};
+		};
+
+		trusted_key_cert: trusted_key_cert {
+			root-certificate;
+			image-id = <TRUSTED_KEY_CERT_ID>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			trusted_world_pk: trusted_world_pk {
+				oid = TRUSTED_WORLD_PK_OID;
+			};
+			non_trusted_world_pk: non_trusted_world_pk {
+				oid = NON_TRUSTED_WORLD_PK_OID;
+			};
+		};
+
+		scp_fw_key_cert: scp_fw_key_cert {
+			image-id = <SCP_FW_KEY_CERT_ID>;
+			parent = <&trusted_key_cert>;
+			signing-key = <&trusted_world_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			scp_fw_content_pk: scp_fw_content_pk {
+				oid = SCP_FW_CONTENT_CERT_PK_OID;
+			};
+		};
+
+		scp_fw_content_cert: scp_fw_content_cert {
+			image-id = <SCP_FW_CONTENT_CERT_ID>;
+			parent = <&scp_fw_key_cert>;
+			signing-key = <&scp_fw_content_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			scp_fw_hash: scp_fw_hash {
+				oid = SCP_FW_HASH_OID;
+			};
+		};
+
+		soc_fw_key_cert: soc_fw_key_cert {
+			image-id = <SOC_FW_KEY_CERT_ID>;
+			parent = <&trusted_key_cert>;
+			signing-key = <&trusted_world_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+			soc_fw_content_pk: soc_fw_content_pk {
+				oid = SOC_FW_CONTENT_CERT_PK_OID;
+			};
+		};
+
+		soc_fw_content_cert: soc_fw_content_cert {
+			image-id = <SOC_FW_CONTENT_CERT_ID>;
+			parent = <&soc_fw_key_cert>;
+			signing-key = <&soc_fw_content_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			soc_fw_hash: soc_fw_hash {
+				oid = SOC_AP_FW_HASH_OID;
+			};
+			soc_fw_config_hash: soc_fw_config_hash {
+				oid = SOC_FW_CONFIG_HASH_OID;
+			};
+		};
+
+		trusted_os_fw_key_cert: trusted_os_fw_key_cert {
+			image-id = <TRUSTED_OS_FW_KEY_CERT_ID>;
+			parent = <&trusted_key_cert>;
+			signing-key = <&trusted_world_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			tos_fw_content_pk: tos_fw_content_pk {
+				oid = TRUSTED_OS_FW_CONTENT_CERT_PK_OID;
+			};
+		};
+
+		trusted_os_fw_content_cert: trusted_os_fw_content_cert {
+			image-id = <TRUSTED_OS_FW_CONTENT_CERT_ID>;
+			parent = <&trusted_os_fw_key_cert>;
+			signing-key = <&tos_fw_content_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			tos_fw_hash: tos_fw_hash {
+				oid = TRUSTED_OS_FW_HASH_OID;
+			};
+			tos_fw_extra1_hash: tos_fw_extra1_hash {
+				oid = TRUSTED_OS_FW_EXTRA1_HASH_OID;
+			};
+			tos_fw_extra2_hash: tos_fw_extra2_hash {
+				oid = TRUSTED_OS_FW_EXTRA2_HASH_OID;
+			};
+			tos_fw_config_hash: tos_fw_config_hash {
+				oid = TRUSTED_OS_FW_CONFIG_HASH_OID;
+			};
+		};
+
+		non_trusted_fw_key_cert: non_trusted_fw_key_cert {
+			image-id = <NON_TRUSTED_FW_KEY_CERT_ID>;
+			parent = <&trusted_key_cert>;
+			signing-key = <&non_trusted_world_pk>;
+			antirollback-counter = <&non_trusted_nv_counter>;
+
+			nt_fw_content_pk: nt_fw_content_pk {
+				oid = NON_TRUSTED_FW_CONTENT_CERT_PK_OID;
+			};
+		};
+
+		non_trusted_fw_content_cert: non_trusted_fw_content_cert {
+			image-id = <NON_TRUSTED_FW_CONTENT_CERT_ID>;
+			parent = <&non_trusted_fw_key_cert>;
+			signing-key = <&nt_fw_content_pk>;
+			antirollback-counter = <&non_trusted_nv_counter>;
+
+			nt_world_bl_hash: nt_world_bl_hash {
+				oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID;
+			};
+			nt_fw_config_hash: nt_fw_config_hash {
+				oid = NON_TRUSTED_FW_CONFIG_HASH_OID;
+			};
+		};
+
+#if defined(SPD_spmd)
+		sp_content_cert: sp_content_cert {
+			image-id = <SP_CONTENT_CERT_ID>;
+			parent = <&trusted_key_cert>;
+			signing-key = <&trusted_world_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			sp_pkg1_hash: sp_pkg1_hash {
+				oid = SP_PKG1_HASH_OID;
+			};
+			sp_pkg2_hash: sp_pkg2_hash {
+				oid = SP_PKG2_HASH_OID;
+			};
+			sp_pkg3_hash: sp_pkg3_hash {
+				oid = SP_PKG3_HASH_OID;
+			};
+			sp_pkg4_hash: sp_pkg4_hash {
+				oid = SP_PKG4_HASH_OID;
+			};
+			sp_pkg5_hash: sp_pkg5_hash {
+				oid = SP_PKG5_HASH_OID;
+			};
+			sp_pkg6_hash: sp_pkg6_hash {
+				oid = SP_PKG6_HASH_OID;
+			};
+			sp_pkg7_hash: sp_pkg7_hash {
+				oid = SP_PKG7_HASH_OID;
+			};
+			sp_pkg8_hash: sp_pkg8_hash {
+				oid = SP_PKG8_HASH_OID;
+			};
+		};
+#endif
+	};
+
+	images {
+		compatible = "arm, img-descs";
+
+		hw_config {
+			image-id = <HW_CONFIG_ID>;
+			parent = <&trusted_boot_fw_cert>;
+			hash = <&hw_config_hash>;
+		};
+
+		tb_fw_config {
+			image-id = <TB_FW_CONFIG_ID>;
+			parent = <&trusted_boot_fw_cert>;
+			hash = <&tb_fw_config_hash>;
+		};
+
+		scp_bl2_image {
+			image-id = <SCP_BL2_IMAGE_ID>;
+			parent = <&scp_fw_content_cert>;
+			hash = <&scp_fw_hash>;
+		};
+
+		bl31_image {
+			image-id = <BL31_IMAGE_ID>;
+			parent = <&soc_fw_content_cert>;
+			hash = <&soc_fw_hash>;
+		};
+
+		soc_fw_config {
+			image-id = <SOC_FW_CONFIG_ID>;
+			parent = <&soc_fw_content_cert>;
+			hash = <&soc_fw_config_hash>;
+		};
+
+		bl32_image {
+			image-id = <BL32_IMAGE_ID>;
+			parent = <&trusted_os_fw_content_cert>;
+			hash = <&tos_fw_hash>;
+		};
+
+		bl32_extra1_image {
+			image-id = <BL32_EXTRA1_IMAGE_ID>;
+			parent = <&trusted_os_fw_content_cert>;
+			hash = <&tos_fw_extra1_hash>;
+		};
+
+		bl32_extra2_image {
+			image-id = <BL32_EXTRA2_IMAGE_ID>;
+			parent = <&trusted_os_fw_content_cert>;
+			hash = <&tos_fw_extra2_hash>;
+		};
+
+		tos_fw_config {
+			image-id = <TOS_FW_CONFIG_ID>;
+			parent = <&trusted_os_fw_content_cert>;
+			hash = <&tos_fw_config_hash>;
+		};
+
+		bl33_image {
+			image-id = <BL33_IMAGE_ID>;
+			parent = <&non_trusted_fw_content_cert>;
+			hash = <&nt_world_bl_hash>;
+		};
+
+		nt_fw_config {
+			image-id = <NT_FW_CONFIG_ID>;
+			parent = <&non_trusted_fw_content_cert>;
+			hash = <&nt_fw_config_hash>;
+		};
+
+#if defined(SPD_spmd)
+		sp_pkg1 {
+			image-id = <SP_CONTENT_CERT_ID + 1>;
+			parent = <&sp_content_cert>;
+			hash = <&sp_pkg1_hash>;
+		};
+
+		sp_pkg2 {
+			image-id = <SP_CONTENT_CERT_ID + 2>;
+			parent = <&sp_content_cert>;
+			hash = <&sp_pkg2_hash>;
+		};
+
+		sp_pkg3 {
+			image-id = <SP_CONTENT_CERT_ID + 3>;
+			parent = <&sp_content_cert>;
+			hash = <&sp_pkg3_hash>;
+		};
+
+		sp_pkg4 {
+			image-id = <SP_CONTENT_CERT_ID + 4>;
+			parent = <&sp_content_cert>;
+			hash = <&sp_pkg4_hash>;
+		};
+
+		sp_pkg5 {
+			image-id = <SP_CONTENT_CERT_ID + 5>;
+			parent = <&sp_content_cert>;
+			hash = <&sp_pkg5_hash>;
+		};
+
+		sp_pkg6 {
+			image-id = <SP_CONTENT_CERT_ID + 6>;
+			parent = <&sp_content_cert>;
+			hash = <&sp_pkg6_hash>;
+		};
+
+		sp_pkg7 {
+			image-id = <SP_CONTENT_CERT_ID + 7>;
+			parent = <&sp_content_cert>;
+			hash = <&sp_pkg7_hash>;
+		};
+
+		sp_pkg8 {
+			image-id = <SP_CONTENT_CERT_ID + 8>;
+			parent = <&sp_content_cert>;
+			hash = <&sp_pkg8_hash>;
+		};
+#endif
+	};
+};
+
+non-volatile-counters {
+	compatible = "arm, non-volatile-counter";
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	counters {
+		trusted_nv_counter: trusted_nv_counter {
+			oid = TRUSTED_FW_NVCOUNTER_OID;
+		};
+		non_trusted_nv_counter: non_trusted_nv_counter {
+			oid = NON_TRUSTED_FW_NVCOUNTER_OID;
+		};
+	};
+};
diff --git a/include/common/fdt_wrappers.h b/include/common/fdt_wrappers.h
index 1d8da18..a571092 100644
--- a/include/common/fdt_wrappers.h
+++ b/include/common/fdt_wrappers.h
@@ -9,6 +9,8 @@
 #ifndef FDT_WRAPPERS_H
 #define FDT_WRAPPERS_H
 
+#include <libfdt_env.h>
+
 /* Number of cells, given total length in bytes. Each cell is 4 bytes long */
 #define NCELLS(len) ((len) / 4U)
 
@@ -37,4 +39,11 @@
 uint64_t fdtw_translate_address(const void *dtb, int bus_node,
 				uint64_t base_address);
 
+static inline uint32_t fdt_blob_size(const void *dtb)
+{
+	const uint32_t *dtb_header = dtb;
+
+	return fdt32_to_cpu(dtb_header[1]);
+}
+
 #endif /* FDT_WRAPPERS_H */
diff --git a/include/common/tbbr/tbbr_img_def.h b/include/common/tbbr/tbbr_img_def.h
index 1f9aab1..e057891 100644
--- a/include/common/tbbr/tbbr_img_def.h
+++ b/include/common/tbbr/tbbr_img_def.h
@@ -11,6 +11,14 @@
 
 #if defined(SPD_spmd)
 #define SP_CONTENT_CERT_ID		MAX_IMAGE_IDS
+#define SP_PKG1_ID			(MAX_IMAGE_IDS + 1)
+#define SP_PKG2_ID			(MAX_IMAGE_IDS + 2)
+#define SP_PKG3_ID			(MAX_IMAGE_IDS + 3)
+#define SP_PKG4_ID			(MAX_IMAGE_IDS + 4)
+#define SP_PKG5_ID			(MAX_IMAGE_IDS + 5)
+#define SP_PKG6_ID			(MAX_IMAGE_IDS + 6)
+#define SP_PKG7_ID			(MAX_IMAGE_IDS + 7)
+#define SP_PKG8_ID			(MAX_IMAGE_IDS + 8)
 #define MAX_SP_IDS			U(8)
 #define MAX_NUMBER_IDS			(MAX_IMAGE_IDS + MAX_SP_IDS + U(1))
 #else
diff --git a/include/drivers/marvell/cache_llc.h b/include/drivers/marvell/cache_llc.h
index b326474..d6dd653 100644
--- a/include/drivers/marvell/cache_llc.h
+++ b/include/drivers/marvell/cache_llc.h
@@ -41,7 +41,7 @@
 #define LLC_BLK_ALOC_WAY_DATA_DSBL	(0x0 << 6)
 #define LLC_BLK_ALOC_WAY_DATA_CLR	(0x1 << 6)
 #define LLC_BLK_ALOC_WAY_DATA_SET	(0x3 << 6)
-#define LLC_BLK_ALOC_BASE_ADDR(addr)	((addr) & (LLC_WAY_SIZE - 1))
+#define LLC_BLK_ALOC_BASE_ADDR(addr)	((addr) & ~(LLC_WAY_SIZE - 1))
 
 #ifndef __ASSEMBLER__
 void llc_cache_sync(int ap_index);
@@ -53,8 +53,9 @@
 int llc_is_exclusive(int ap_index);
 void llc_runtime_enable(int ap_index);
 #if LLC_SRAM
-void llc_sram_enable(int ap_index);
+int llc_sram_enable(int ap_index, int size);
 void llc_sram_disable(int ap_index);
+int llc_sram_test(int ap_index, int size, char *msg);
 #endif /* LLC_SRAM */
 #endif /* __ASSEMBLY__ */
 
diff --git a/include/drivers/st/stm32mp1_clk.h b/include/drivers/st/stm32mp1_clk.h
index 1ebd39f..c46892b 100644
--- a/include/drivers/st/stm32mp1_clk.h
+++ b/include/drivers/st/stm32mp1_clk.h
@@ -59,4 +59,7 @@
 
 void stm32mp1_stgen_increment(unsigned long long offset_in_ms);
 
+#ifdef STM32MP_SHARED_RESOURCES
+void stm32mp1_register_clock_parents_secure(unsigned long id);
+#endif
 #endif /* STM32MP1_CLK_H */
diff --git a/include/lib/libc/stdbool.h b/include/lib/libc/stdbool.h
index e39aef7..b58334c 100644
--- a/include/lib/libc/stdbool.h
+++ b/include/lib/libc/stdbool.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,8 +9,8 @@
 
 #define bool	_Bool
 
-#define true	1
-#define false	0
+#define true	(0 < 1)
+#define false	(0 > 1)
 
 #define __bool_true_false_are_defined	1
 
diff --git a/include/lib/libfdt/fdt.h b/include/lib/libfdt/fdt.h
index ef7c86b..eb9edb7 100644
--- a/include/lib/libfdt/fdt.h
+++ b/include/lib/libfdt/fdt.h
@@ -1,55 +1,10 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
 #ifndef FDT_H
 #define FDT_H
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
  * Copyright 2012 Kim Phillips, Freescale Semiconductor.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef __ASSEMBLER__
@@ -90,7 +45,7 @@
 	char data[0];
 };
 
-#endif /* !__ASSEMBLER__ */
+#endif /* !__ASSEMBLER__*/
 
 #define FDT_MAGIC	0xd00dfeed	/* 4: version, 4: total size */
 #define FDT_TAGSIZE	sizeof(fdt32_t)
diff --git a/include/lib/libfdt/libfdt.h b/include/lib/libfdt/libfdt.h
index c8c00fa..48f375c 100644
--- a/include/lib/libfdt/libfdt.h
+++ b/include/lib/libfdt/libfdt.h
@@ -1,54 +1,9 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
 #ifndef LIBFDT_H
 #define LIBFDT_H
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #include <libfdt_env.h>
@@ -90,8 +45,9 @@
 
 /* Error codes: codes for bad device tree blobs */
 #define FDT_ERR_TRUNCATED	8
-	/* FDT_ERR_TRUNCATED: Structure block of the given device tree
-	 * ends without an FDT_END tag. */
+	/* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly
+	 * terminated (overflows, goes outside allowed bounds, or
+	 * isn't properly terminated).  */
 #define FDT_ERR_BADMAGIC	9
 	/* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
 	 * device tree at all - it is missing the flattened device
@@ -137,7 +93,15 @@
 	/* FDT_ERR_NOPHANDLES: The device tree doesn't have any
 	 * phandle available anymore without causing an overflow */
 
-#define FDT_ERR_MAX		17
+#define FDT_ERR_BADFLAGS	18
+	/* FDT_ERR_BADFLAGS: The function was passed a flags field that
+	 * contains invalid flags or an invalid combination of flags. */
+
+#define FDT_ERR_MAX		18
+
+/* constants */
+#define FDT_MAX_PHANDLE 0xfffffffe
+	/* Valid values for phandles range from 1 to 2^32-2. */
 
 /**********************************************************************/
 /* Low-level functions (you probably don't need these)                */
@@ -153,6 +117,61 @@
 
 uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
 
+/*
+ * Alignment helpers:
+ *     These helpers access words from a device tree blob.  They're
+ *     built to work even with unaligned pointers on platforms (ike
+ *     ARM) that don't like unaligned loads and stores
+ */
+
+static inline uint32_t fdt32_ld(const fdt32_t *p)
+{
+	const uint8_t *bp = (const uint8_t *)p;
+
+	return ((uint32_t)bp[0] << 24)
+		| ((uint32_t)bp[1] << 16)
+		| ((uint32_t)bp[2] << 8)
+		| bp[3];
+}
+
+static inline void fdt32_st(void *property, uint32_t value)
+{
+	uint8_t *bp = (uint8_t *)property;
+
+	bp[0] = value >> 24;
+	bp[1] = (value >> 16) & 0xff;
+	bp[2] = (value >> 8) & 0xff;
+	bp[3] = value & 0xff;
+}
+
+static inline uint64_t fdt64_ld(const fdt64_t *p)
+{
+	const uint8_t *bp = (const uint8_t *)p;
+
+	return ((uint64_t)bp[0] << 56)
+		| ((uint64_t)bp[1] << 48)
+		| ((uint64_t)bp[2] << 40)
+		| ((uint64_t)bp[3] << 32)
+		| ((uint64_t)bp[4] << 24)
+		| ((uint64_t)bp[5] << 16)
+		| ((uint64_t)bp[6] << 8)
+		| bp[7];
+}
+
+static inline void fdt64_st(void *property, uint64_t value)
+{
+	uint8_t *bp = (uint8_t *)property;
+
+	bp[0] = value >> 56;
+	bp[1] = (value >> 48) & 0xff;
+	bp[2] = (value >> 40) & 0xff;
+	bp[3] = (value >> 32) & 0xff;
+	bp[4] = (value >> 24) & 0xff;
+	bp[5] = (value >> 16) & 0xff;
+	bp[6] = (value >> 8) & 0xff;
+	bp[7] = value & 0xff;
+}
+
 /**********************************************************************/
 /* Traversal functions                                                */
 /**********************************************************************/
@@ -195,7 +214,7 @@
  *		...
  *	}
  *
- *	if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) {
+ *	if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) {
  *		Error handling
  *	}
  *
@@ -213,7 +232,7 @@
 /* General functions                                                  */
 /**********************************************************************/
 #define fdt_get_header(fdt, field) \
-	(fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
+	(fdt32_ld(&((const struct fdt_header *)(fdt))->field))
 #define fdt_magic(fdt)			(fdt_get_header(fdt, magic))
 #define fdt_totalsize(fdt)		(fdt_get_header(fdt, totalsize))
 #define fdt_off_dt_struct(fdt)		(fdt_get_header(fdt, off_dt_struct))
@@ -244,18 +263,32 @@
 #undef fdt_set_hdr_
 
 /**
- * fdt_check_header - sanity check a device tree or possible device tree
+ * fdt_header_size - return the size of the tree's header
+ * @fdt: pointer to a flattened device tree
+ */
+size_t fdt_header_size(const void *fdt);
+
+/**
+ * fdt_header_size_ - internal function which takes a version number
+ */
+size_t fdt_header_size_(uint32_t version);
+
+/**
+ * fdt_check_header - sanity check a device tree header
+
  * @fdt: pointer to data which might be a flattened device tree
  *
  * fdt_check_header() checks that the given buffer contains what
- * appears to be a flattened device tree with sane information in its
- * header.
+ * appears to be a flattened device tree, and that the header contains
+ * valid information (to the extent that can be determined from the
+ * header alone).
  *
  * returns:
  *     0, if the buffer appears to contain a valid device tree
  *     -FDT_ERR_BADMAGIC,
  *     -FDT_ERR_BADVERSION,
- *     -FDT_ERR_BADSTATE, standard meanings, as above
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_TRUNCATED, standard meanings, as above
  */
 int fdt_check_header(const void *fdt);
 
@@ -284,6 +317,24 @@
 /* Read-only functions                                                */
 /**********************************************************************/
 
+int fdt_check_full(const void *fdt, size_t bufsize);
+
+/**
+ * fdt_get_string - retrieve a string from the strings block of a device tree
+ * @fdt: pointer to the device tree blob
+ * @stroffset: offset of the string within the strings block (native endian)
+ * @lenp: optional pointer to return the string's length
+ *
+ * fdt_get_string() retrieves a pointer to a single string from the
+ * strings block of the device tree blob at fdt, and optionally also
+ * returns the string's length in *lenp.
+ *
+ * returns:
+ *     a pointer to the string, on success
+ *     NULL, if stroffset is out of bounds, or doesn't point to a valid string
+ */
+const char *fdt_get_string(const void *fdt, int stroffset, int *lenp);
+
 /**
  * fdt_string - retrieve a string from the strings block of a device tree
  * @fdt: pointer to the device tree blob
@@ -294,11 +345,25 @@
  *
  * returns:
  *     a pointer to the string, on success
- *     NULL, if stroffset is out of bounds
+ *     NULL, if stroffset is out of bounds, or doesn't point to a valid string
  */
 const char *fdt_string(const void *fdt, int stroffset);
 
 /**
+ * fdt_find_max_phandle - find and return the highest phandle in a tree
+ * @fdt: pointer to the device tree blob
+ * @phandle: return location for the highest phandle value found in the tree
+ *
+ * fdt_find_max_phandle() finds the highest phandle value in the given device
+ * tree. The value returned in @phandle is only valid if the function returns
+ * success.
+ *
+ * returns:
+ *     0 on success or a negative error code on failure
+ */
+int fdt_find_max_phandle(const void *fdt, uint32_t *phandle);
+
+/**
  * fdt_get_max_phandle - retrieves the highest phandle in a tree
  * @fdt: pointer to the device tree blob
  *
@@ -306,12 +371,39 @@
  * device tree. This will ignore badly formatted phandles, or phandles
  * with a value of 0 or -1.
  *
+ * This function is deprecated in favour of fdt_find_max_phandle().
+ *
  * returns:
  *      the highest phandle on success
  *      0, if no phandle was found in the device tree
  *      -1, if an error occurred
  */
-uint32_t fdt_get_max_phandle(const void *fdt);
+static inline uint32_t fdt_get_max_phandle(const void *fdt)
+{
+	uint32_t phandle;
+	int err;
+
+	err = fdt_find_max_phandle(fdt, &phandle);
+	if (err < 0)
+		return (uint32_t)-1;
+
+	return phandle;
+}
+
+/**
+ * fdt_generate_phandle - return a new, unused phandle for a device tree blob
+ * @fdt: pointer to the device tree blob
+ * @phandle: return location for the new phandle
+ *
+ * Walks the device tree blob and looks for the highest phandle value. On
+ * success, the new, unused phandle value (one higher than the previously
+ * highest phandle value in the device tree blob) will be returned in the
+ * @phandle parameter.
+ *
+ * Returns:
+ *   0 on success or a negative error-code on failure
+ */
+int fdt_generate_phandle(const void *fdt, uint32_t *phandle);
 
 /**
  * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
@@ -503,7 +595,7 @@
  *		...
  *	}
  *
- *	if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) {
+ *	if ((property < 0) && (property != -FDT_ERR_NOTFOUND)) {
  *		Error handling
  *	}
  *
@@ -606,7 +698,7 @@
 /**
  * fdt_getprop_by_offset - retrieve the value of a property at a given offset
  * @fdt: pointer to the device tree blob
- * @ffset: offset of the property to read
+ * @offset: offset of the property to read
  * @namep: pointer to a string variable (will be overwritten) or NULL
  * @lenp: pointer to an integer variable (will be overwritten) or NULL
  *
@@ -1090,7 +1182,7 @@
  *
  * returns:
  *	0 <= n < FDT_MAX_NCELLS, on success
- *      2, if the node has no #address-cells property
+ *      1, if the node has no #size-cells property
  *      -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
  *		#size-cells property
  *	-FDT_ERR_BADMAGIC,
@@ -1297,7 +1389,45 @@
 /* Sequential write functions                                         */
 /**********************************************************************/
 
+/* fdt_create_with_flags flags */
+#define FDT_CREATE_FLAG_NO_NAME_DEDUP 0x1
+	/* FDT_CREATE_FLAG_NO_NAME_DEDUP: Do not try to de-duplicate property
+	 * names in the fdt. This can result in faster creation times, but
+	 * a larger fdt. */
+
+#define FDT_CREATE_FLAGS_ALL	(FDT_CREATE_FLAG_NO_NAME_DEDUP)
+
+/**
+ * fdt_create_with_flags - begin creation of a new fdt
+ * @fdt: pointer to memory allocated where fdt will be created
+ * @bufsize: size of the memory space at fdt
+ * @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0.
+ *
+ * fdt_create_with_flags() begins the process of creating a new fdt with
+ * the sequential write interface.
+ *
+ * fdt creation process must end with fdt_finished() to produce a valid fdt.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt
+ *	-FDT_ERR_BADFLAGS, flags is not valid
+ */
+int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags);
+
+/**
+ * fdt_create - begin creation of a new fdt
+ * @fdt: pointer to memory allocated where fdt will be created
+ * @bufsize: size of the memory space at fdt
+ *
+ * fdt_create() is equivalent to fdt_create_with_flags() with flags=0.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt
+ */
 int fdt_create(void *buf, int bufsize);
+
 int fdt_resize(void *fdt, void *buf, int bufsize);
 int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
 int fdt_finish_reservemap(void *fdt);
@@ -1313,10 +1443,13 @@
 	fdt64_t tmp = cpu_to_fdt64(val);
 	return fdt_property(fdt, name, &tmp, sizeof(tmp));
 }
+
+#ifndef SWIG /* Not available in Python */
 static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
 {
 	return fdt_property_u32(fdt, name, val);
 }
+#endif
 
 /**
  * fdt_property_placeholder - add a new property and return a ptr to its value
@@ -1766,6 +1899,43 @@
 	fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
 
 /**
+ * fdt_appendprop_addrrange - append a address range property
+ * @fdt: pointer to the device tree blob
+ * @parent: offset of the parent node
+ * @nodeoffset: offset of the node to add a property at
+ * @name: name of property
+ * @addr: start address of a given range
+ * @size: size of a given range
+ *
+ * fdt_appendprop_addrrange() appends an address range value (start
+ * address and size) to the value of the named property in the given
+ * node, or creates a new property with that value if it does not
+ * already exist.
+ * If "name" is not specified, a default "reg" is used.
+ * Cell sizes are determined by parent's #address-cells and #size-cells.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
+ *		#address-cells property
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADVALUE, addr or size doesn't fit to respective cells size
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain a new property
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
+			     const char *name, uint64_t addr, uint64_t size);
+
+/**
  * fdt_delprop - delete a property
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to nop
diff --git a/include/lib/libfdt/libfdt_env.h b/include/lib/libfdt/libfdt_env.h
index bd24746..73b6d40 100644
--- a/include/lib/libfdt/libfdt_env.h
+++ b/include/lib/libfdt/libfdt_env.h
@@ -1,61 +1,18 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
 #ifndef LIBFDT_ENV_H
 #define LIBFDT_ENV_H
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
  * Copyright 2012 Kim Phillips, Freescale Semiconductor.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
 
 #ifdef __CHECKER__
 #define FDT_FORCE __attribute__((force))
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 5c11e5f..680d354 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -350,14 +350,15 @@
  * and limit. Leave enough space of BL2 meminfo.
  */
 #define ARM_FW_CONFIG_BASE		(ARM_BL_RAM_BASE + sizeof(meminfo_t))
-#define ARM_FW_CONFIG_LIMIT		(ARM_BL_RAM_BASE + PAGE_SIZE)
+#define ARM_FW_CONFIG_LIMIT		((ARM_BL_RAM_BASE + PAGE_SIZE) \
+					+ (PAGE_SIZE / 2U))
 
 /*
  * Boot parameters passed from BL2 to BL31/BL32 are stored here
  */
-#define ARM_BL2_MEM_DESC_BASE		ARM_FW_CONFIG_LIMIT
-#define ARM_BL2_MEM_DESC_LIMIT		(ARM_BL2_MEM_DESC_BASE +	\
-							(PAGE_SIZE / 2U))
+#define ARM_BL2_MEM_DESC_BASE		(ARM_FW_CONFIG_LIMIT)
+#define ARM_BL2_MEM_DESC_LIMIT		(ARM_BL2_MEM_DESC_BASE \
+					+ (PAGE_SIZE / 2U))
 
 /*
  * Define limit of firmware configuration memory:
diff --git a/lib/libfdt/fdt.c b/lib/libfdt/fdt.c
index 7855a17..c28fcc1 100644
--- a/lib/libfdt/fdt.c
+++ b/lib/libfdt/fdt.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "libfdt_env.h"
 
@@ -55,22 +10,125 @@
 
 #include "libfdt_internal.h"
 
-int fdt_check_header(const void *fdt)
+/*
+ * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks
+ * that the given buffer contains what appears to be a flattened
+ * device tree with sane information in its header.
+ */
+int32_t fdt_ro_probe_(const void *fdt)
 {
+	uint32_t totalsize = fdt_totalsize(fdt);
+
+	if (can_assume(VALID_DTB))
+		return totalsize;
+
 	if (fdt_magic(fdt) == FDT_MAGIC) {
 		/* Complete tree */
-		if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
-			return -FDT_ERR_BADVERSION;
-		if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
-			return -FDT_ERR_BADVERSION;
+		if (!can_assume(LATEST)) {
+			if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+				return -FDT_ERR_BADVERSION;
+			if (fdt_last_comp_version(fdt) >
+					FDT_LAST_SUPPORTED_VERSION)
+				return -FDT_ERR_BADVERSION;
+		}
 	} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
 		/* Unfinished sequential-write blob */
-		if (fdt_size_dt_struct(fdt) == 0)
+		if (!can_assume(VALID_INPUT) && fdt_size_dt_struct(fdt) == 0)
 			return -FDT_ERR_BADSTATE;
 	} else {
 		return -FDT_ERR_BADMAGIC;
 	}
 
+	if (totalsize < INT32_MAX)
+		return totalsize;
+	else
+		return -FDT_ERR_TRUNCATED;
+}
+
+static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off)
+{
+	return (off >= hdrsize) && (off <= totalsize);
+}
+
+static int check_block_(uint32_t hdrsize, uint32_t totalsize,
+			uint32_t base, uint32_t size)
+{
+	if (!check_off_(hdrsize, totalsize, base))
+		return 0; /* block start out of bounds */
+	if ((base + size) < base)
+		return 0; /* overflow */
+	if (!check_off_(hdrsize, totalsize, base + size))
+		return 0; /* block end out of bounds */
+	return 1;
+}
+
+size_t fdt_header_size_(uint32_t version)
+{
+	if (version <= 1)
+		return FDT_V1_SIZE;
+	else if (version <= 2)
+		return FDT_V2_SIZE;
+	else if (version <= 3)
+		return FDT_V3_SIZE;
+	else if (version <= 16)
+		return FDT_V16_SIZE;
+	else
+		return FDT_V17_SIZE;
+}
+
+size_t fdt_header_size(const void *fdt)
+{
+	return can_assume(LATEST) ? FDT_V17_SIZE :
+		fdt_header_size_(fdt_version(fdt));
+}
+
+int fdt_check_header(const void *fdt)
+{
+	size_t hdrsize;
+
+	if (fdt_magic(fdt) != FDT_MAGIC)
+		return -FDT_ERR_BADMAGIC;
+	if (!can_assume(LATEST)) {
+		if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+		    || (fdt_last_comp_version(fdt) >
+			FDT_LAST_SUPPORTED_VERSION))
+			return -FDT_ERR_BADVERSION;
+		if (fdt_version(fdt) < fdt_last_comp_version(fdt))
+			return -FDT_ERR_BADVERSION;
+	}
+	hdrsize = fdt_header_size(fdt);
+	if (!can_assume(VALID_DTB)) {
+
+		if ((fdt_totalsize(fdt) < hdrsize)
+		    || (fdt_totalsize(fdt) > INT_MAX))
+			return -FDT_ERR_TRUNCATED;
+
+		/* Bounds check memrsv block */
+		if (!check_off_(hdrsize, fdt_totalsize(fdt),
+				fdt_off_mem_rsvmap(fdt)))
+			return -FDT_ERR_TRUNCATED;
+	}
+
+	if (!can_assume(VALID_DTB)) {
+		/* Bounds check structure block */
+		if (!can_assume(LATEST) && fdt_version(fdt) < 17) {
+			if (!check_off_(hdrsize, fdt_totalsize(fdt),
+					fdt_off_dt_struct(fdt)))
+				return -FDT_ERR_TRUNCATED;
+		} else {
+			if (!check_block_(hdrsize, fdt_totalsize(fdt),
+					  fdt_off_dt_struct(fdt),
+					  fdt_size_dt_struct(fdt)))
+				return -FDT_ERR_TRUNCATED;
+		}
+
+		/* Bounds check strings block */
+		if (!check_block_(hdrsize, fdt_totalsize(fdt),
+				  fdt_off_dt_strings(fdt),
+				  fdt_size_dt_strings(fdt)))
+			return -FDT_ERR_TRUNCATED;
+	}
+
 	return 0;
 }
 
@@ -78,12 +136,13 @@
 {
 	unsigned absoffset = offset + fdt_off_dt_struct(fdt);
 
-	if ((absoffset < offset)
-	    || ((absoffset + len) < absoffset)
-	    || (absoffset + len) > fdt_totalsize(fdt))
-		return NULL;
+	if (!can_assume(VALID_INPUT))
+		if ((absoffset < offset)
+		    || ((absoffset + len) < absoffset)
+		    || (absoffset + len) > fdt_totalsize(fdt))
+			return NULL;
 
-	if (fdt_version(fdt) >= 0x11)
+	if (can_assume(LATEST) || fdt_version(fdt) >= 0x11)
 		if (((offset + len) < offset)
 		    || ((offset + len) > fdt_size_dt_struct(fdt)))
 			return NULL;
@@ -100,7 +159,7 @@
 
 	*nextoffset = -FDT_ERR_TRUNCATED;
 	tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
-	if (!tagp)
+	if (!can_assume(VALID_DTB) && !tagp)
 		return FDT_END; /* premature end */
 	tag = fdt32_to_cpu(*tagp);
 	offset += FDT_TAGSIZE;
@@ -112,18 +171,19 @@
 		do {
 			p = fdt_offset_ptr(fdt, offset++, 1);
 		} while (p && (*p != '\0'));
-		if (!p)
+		if (!can_assume(VALID_DTB) && !p)
 			return FDT_END; /* premature end */
 		break;
 
 	case FDT_PROP:
 		lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
-		if (!lenp)
+		if (!can_assume(VALID_DTB) && !lenp)
 			return FDT_END; /* premature end */
 		/* skip-name offset, length and value */
 		offset += sizeof(struct fdt_property) - FDT_TAGSIZE
 			+ fdt32_to_cpu(*lenp);
-		if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
+		if (!can_assume(LATEST) &&
+		    fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
 		    ((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
 			offset += 4;
 		break;
@@ -146,6 +206,8 @@
 
 int fdt_check_node_offset_(const void *fdt, int offset)
 {
+	if (can_assume(VALID_INPUT))
+		return offset;
 	if ((offset < 0) || (offset % FDT_TAGSIZE)
 	    || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
 		return -FDT_ERR_BADOFFSET;
@@ -244,7 +306,7 @@
 
 int fdt_move(const void *fdt, void *buf, int bufsize)
 {
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	if (fdt_totalsize(fdt) > bufsize)
 		return -FDT_ERR_NOSPACE;
diff --git a/lib/libfdt/fdt_addresses.c b/lib/libfdt/fdt_addresses.c
index eff4dbc..9a82cd0 100644
--- a/lib/libfdt/fdt_addresses.c
+++ b/lib/libfdt/fdt_addresses.c
@@ -1,52 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Copyright (C) 2018 embedded brains GmbH
  */
 #include "libfdt_env.h"
 
@@ -55,42 +11,91 @@
 
 #include "libfdt_internal.h"
 
-int fdt_address_cells(const void *fdt, int nodeoffset)
+static int fdt_cells(const void *fdt, int nodeoffset, const char *name)
 {
-	const fdt32_t *ac;
-	int val;
+	const fdt32_t *c;
+	uint32_t val;
 	int len;
 
-	ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len);
-	if (!ac)
+	c = fdt_getprop(fdt, nodeoffset, name, &len);
+	if (!c)
+		return len;
+
+	if (len != sizeof(*c))
+		return -FDT_ERR_BADNCELLS;
+
+	val = fdt32_to_cpu(*c);
+	if (val > FDT_MAX_NCELLS)
+		return -FDT_ERR_BADNCELLS;
+
+	return (int)val;
+}
+
+int fdt_address_cells(const void *fdt, int nodeoffset)
+{
+	int val;
+
+	val = fdt_cells(fdt, nodeoffset, "#address-cells");
+	if (val == 0)
+		return -FDT_ERR_BADNCELLS;
+	if (val == -FDT_ERR_NOTFOUND)
 		return 2;
-
-	if (len != sizeof(*ac))
-		return -FDT_ERR_BADNCELLS;
-
-	val = fdt32_to_cpu(*ac);
-	if ((val <= 0) || (val > FDT_MAX_NCELLS))
-		return -FDT_ERR_BADNCELLS;
-
 	return val;
 }
 
 int fdt_size_cells(const void *fdt, int nodeoffset)
 {
-	const fdt32_t *sc;
 	int val;
-	int len;
 
-	sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len);
-	if (!sc)
-		return 2;
-
-	if (len != sizeof(*sc))
-		return -FDT_ERR_BADNCELLS;
-
-	val = fdt32_to_cpu(*sc);
-	if ((val < 0) || (val > FDT_MAX_NCELLS))
-		return -FDT_ERR_BADNCELLS;
-
+	val = fdt_cells(fdt, nodeoffset, "#size-cells");
+	if (val == -FDT_ERR_NOTFOUND)
+		return 1;
 	return val;
 }
+
+/* This function assumes that [address|size]_cells is 1 or 2 */
+int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
+			     const char *name, uint64_t addr, uint64_t size)
+{
+	int addr_cells, size_cells, ret;
+	uint8_t data[sizeof(fdt64_t) * 2], *prop;
+
+	ret = fdt_address_cells(fdt, parent);
+	if (ret < 0)
+		return ret;
+	addr_cells = ret;
+
+	ret = fdt_size_cells(fdt, parent);
+	if (ret < 0)
+		return ret;
+	size_cells = ret;
+
+	/* check validity of address */
+	prop = data;
+	if (addr_cells == 1) {
+		if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size))
+			return -FDT_ERR_BADVALUE;
+
+		fdt32_st(prop, (uint32_t)addr);
+	} else if (addr_cells == 2) {
+		fdt64_st(prop, addr);
+	} else {
+		return -FDT_ERR_BADNCELLS;
+	}
+
+	/* check validity of size */
+	prop += addr_cells * sizeof(fdt32_t);
+	if (size_cells == 1) {
+		if (size > UINT32_MAX)
+			return -FDT_ERR_BADVALUE;
+
+		fdt32_st(prop, (uint32_t)size);
+	} else if (size_cells == 2) {
+		fdt64_st(prop, size);
+	} else {
+		return -FDT_ERR_BADNCELLS;
+	}
+
+	return fdt_appendprop(fdt, nodeoffset, name, data,
+			      (addr_cells + size_cells) * sizeof(fdt32_t));
+}
diff --git a/lib/libfdt/fdt_empty_tree.c b/lib/libfdt/fdt_empty_tree.c
index f2ae9b7..49d54d4 100644
--- a/lib/libfdt/fdt_empty_tree.c
+++ b/lib/libfdt/fdt_empty_tree.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2012 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "libfdt_env.h"
 
diff --git a/lib/libfdt/fdt_overlay.c b/lib/libfdt/fdt_overlay.c
index bf75388..b310e49 100644
--- a/lib/libfdt/fdt_overlay.c
+++ b/lib/libfdt/fdt_overlay.c
@@ -1,53 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2016 Free Electrons
  * Copyright (C) 2016 NextThing Co.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "libfdt_env.h"
 
@@ -93,11 +48,11 @@
  * @pathp: pointer which receives the path of the target (or NULL)
  *
  * overlay_get_target() retrieves the target offset in the base
- * device tree of a fragment, no matter how the actual targetting is
+ * device tree of a fragment, no matter how the actual targeting is
  * done (through a phandle or a path)
  *
  * returns:
- *      the targetted node offset in the base device tree
+ *      the targeted node offset in the base device tree
  *      Negative error code on error
  */
 static int overlay_get_target(const void *fdt, const void *fdto,
@@ -697,7 +652,7 @@
 	int len = 0, namelen;
 	const char *name;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	for (;;) {
 		name = fdt_get_name(fdt, nodeoffset, &namelen);
@@ -778,26 +733,36 @@
 		/* keep end marker to avoid strlen() */
 		e = path + path_len;
 
-		/* format: /<fragment-name>/__overlay__/<relative-subnode-path> */
-
 		if (*path != '/')
 			return -FDT_ERR_BADVALUE;
 
 		/* get fragment name first */
 		s = strchr(path + 1, '/');
-		if (!s)
-			return -FDT_ERR_BADOVERLAY;
+		if (!s) {
+			/* Symbol refers to something that won't end
+			 * up in the target tree */
+			continue;
+		}
 
 		frag_name = path + 1;
 		frag_name_len = s - path - 1;
 
 		/* verify format; safe since "s" lies in \0 terminated prop */
 		len = sizeof("/__overlay__/") - 1;
-		if ((e - s) < len || memcmp(s, "/__overlay__/", len))
-			return -FDT_ERR_BADOVERLAY;
-
-		rel_path = s + len;
-		rel_path_len = e - rel_path;
+		if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) {
+			/* /<fragment-name>/__overlay__/<relative-subnode-path> */
+			rel_path = s + len;
+			rel_path_len = e - rel_path - 1;
+		} else if ((e - s) == len
+			   && (memcmp(s, "/__overlay__", len - 1) == 0)) {
+			/* /<fragment-name>/__overlay__ */
+			rel_path = "";
+			rel_path_len = 0;
+		} else {
+			/* Symbol refers to something that won't end
+			 * up in the target tree */
+			continue;
+		}
 
 		/* find the fragment index in which the symbol lies */
 		ret = fdt_subnode_offset_namelen(fdto, 0, frag_name,
@@ -863,11 +828,15 @@
 
 int fdt_overlay_apply(void *fdt, void *fdto)
 {
-	uint32_t delta = fdt_get_max_phandle(fdt);
+	uint32_t delta;
 	int ret;
 
-	FDT_CHECK_HEADER(fdt);
-	FDT_CHECK_HEADER(fdto);
+	FDT_RO_PROBE(fdt);
+	FDT_RO_PROBE(fdto);
+
+	ret = fdt_find_max_phandle(fdt, &delta);
+	if (ret)
+		goto err;
 
 	ret = overlay_adjust_local_phandles(fdto, delta);
 	if (ret)
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index dfb3236..e03570a 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "libfdt_env.h"
 
@@ -76,60 +31,169 @@
 		return 0;
 }
 
+const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
+{
+	int32_t totalsize;
+	uint32_t absoffset;
+	size_t len;
+	int err;
+	const char *s, *n;
+
+	if (can_assume(VALID_INPUT)) {
+		s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+
+		if (lenp)
+			*lenp = strlen(s);
+		return s;
+	}
+	totalsize = fdt_ro_probe_(fdt);
+	err = totalsize;
+	if (totalsize < 0)
+		goto fail;
+
+	err = -FDT_ERR_BADOFFSET;
+	absoffset = stroffset + fdt_off_dt_strings(fdt);
+	if (absoffset >= totalsize)
+		goto fail;
+	len = totalsize - absoffset;
+
+	if (fdt_magic(fdt) == FDT_MAGIC) {
+		if (stroffset < 0)
+			goto fail;
+		if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
+			if (stroffset >= fdt_size_dt_strings(fdt))
+				goto fail;
+			if ((fdt_size_dt_strings(fdt) - stroffset) < len)
+				len = fdt_size_dt_strings(fdt) - stroffset;
+		}
+	} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
+		if ((stroffset >= 0)
+		    || (stroffset < -fdt_size_dt_strings(fdt)))
+			goto fail;
+		if ((-stroffset) < len)
+			len = -stroffset;
+	} else {
+		err = -FDT_ERR_INTERNAL;
+		goto fail;
+	}
+
+	s = (const char *)fdt + absoffset;
+	n = memchr(s, '\0', len);
+	if (!n) {
+		/* missing terminating NULL */
+		err = -FDT_ERR_TRUNCATED;
+		goto fail;
+	}
+
+	if (lenp)
+		*lenp = n - s;
+	return s;
+
+fail:
+	if (lenp)
+		*lenp = err;
+	return NULL;
+}
+
 const char *fdt_string(const void *fdt, int stroffset)
 {
-	return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+	return fdt_get_string(fdt, stroffset, NULL);
 }
 
 static int fdt_string_eq_(const void *fdt, int stroffset,
 			  const char *s, int len)
 {
-	const char *p = fdt_string(fdt, stroffset);
+	int slen;
+	const char *p = fdt_get_string(fdt, stroffset, &slen);
 
-	return (strlen(p) == len) && (memcmp(p, s, len) == 0);
+	return p && (slen == len) && (memcmp(p, s, len) == 0);
 }
 
-uint32_t fdt_get_max_phandle(const void *fdt)
+int fdt_find_max_phandle(const void *fdt, uint32_t *phandle)
 {
-	uint32_t max_phandle = 0;
-	int offset;
+	uint32_t max = 0;
+	int offset = -1;
 
-	for (offset = fdt_next_node(fdt, -1, NULL);;
-	     offset = fdt_next_node(fdt, offset, NULL)) {
-		uint32_t phandle;
+	while (true) {
+		uint32_t value;
 
-		if (offset == -FDT_ERR_NOTFOUND)
-			return max_phandle;
+		offset = fdt_next_node(fdt, offset, NULL);
+		if (offset < 0) {
+			if (offset == -FDT_ERR_NOTFOUND)
+				break;
 
-		if (offset < 0)
-			return (uint32_t)-1;
+			return offset;
+		}
 
-		phandle = fdt_get_phandle(fdt, offset);
-		if (phandle == (uint32_t)-1)
-			continue;
+		value = fdt_get_phandle(fdt, offset);
 
-		if (phandle > max_phandle)
-			max_phandle = phandle;
+		if (value > max)
+			max = value;
 	}
 
+	if (phandle)
+		*phandle = max;
+
 	return 0;
 }
 
+int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
+{
+	uint32_t max;
+	int err;
+
+	err = fdt_find_max_phandle(fdt, &max);
+	if (err < 0)
+		return err;
+
+	if (max == FDT_MAX_PHANDLE)
+		return -FDT_ERR_NOPHANDLES;
+
+	if (phandle)
+		*phandle = max + 1;
+
+	return 0;
+}
+
+static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
+{
+	int offset = n * sizeof(struct fdt_reserve_entry);
+	int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
+
+	if (!can_assume(VALID_INPUT)) {
+		if (absoffset < fdt_off_mem_rsvmap(fdt))
+			return NULL;
+		if (absoffset > fdt_totalsize(fdt) -
+		    sizeof(struct fdt_reserve_entry))
+			return NULL;
+	}
+	return fdt_mem_rsv_(fdt, n);
+}
+
 int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
 {
-	FDT_CHECK_HEADER(fdt);
-	*address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address);
-	*size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size);
+	const struct fdt_reserve_entry *re;
+
+	FDT_RO_PROBE(fdt);
+	re = fdt_mem_rsv(fdt, n);
+	if (!can_assume(VALID_INPUT) && !re)
+		return -FDT_ERR_BADOFFSET;
+
+	*address = fdt64_ld(&re->address);
+	*size = fdt64_ld(&re->size);
 	return 0;
 }
 
 int fdt_num_mem_rsv(const void *fdt)
 {
-	int i = 0;
+	int i;
+	const struct fdt_reserve_entry *re;
 
-	while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0)
-		i++;
-	return i;
+	for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
+		if (fdt64_ld(&re->size) == 0)
+			return i;
+	}
+	return -FDT_ERR_TRUNCATED;
 }
 
 static int nextprop_(const void *fdt, int offset)
@@ -161,7 +225,7 @@
 {
 	int depth;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	for (depth = 0;
 	     (offset >= 0) && (depth >= 0);
@@ -187,7 +251,7 @@
 	const char *p = path;
 	int offset = 0;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	/* see if we have an alias */
 	if (*path != '/') {
@@ -237,13 +301,13 @@
 	const char *nameptr;
 	int err;
 
-	if (((err = fdt_check_header(fdt)) != 0)
+	if (((err = fdt_ro_probe_(fdt)) < 0)
 	    || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
 			goto fail;
 
 	nameptr = nh->name;
 
-	if (fdt_version(fdt) < 0x10) {
+	if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
 		/*
 		 * For old FDT versions, match the naming conventions of V16:
 		 * give only the leaf name (after all /). The actual tree
@@ -294,7 +358,8 @@
 	int err;
 	const struct fdt_property *prop;
 
-	if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) {
+	if (!can_assume(VALID_INPUT) &&
+	    (err = fdt_check_prop_offset_(fdt, offset)) < 0) {
 		if (lenp)
 			*lenp = err;
 		return NULL;
@@ -303,7 +368,7 @@
 	prop = fdt_offset_ptr_(fdt, offset);
 
 	if (lenp)
-		*lenp = fdt32_to_cpu(prop->len);
+		*lenp = fdt32_ld(&prop->len);
 
 	return prop;
 }
@@ -315,7 +380,7 @@
 	/* Prior to version 16, properties may need realignment
 	 * and this API does not work. fdt_getprop_*() will, however. */
 
-	if (fdt_version(fdt) < 0x10) {
+	if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
 		if (lenp)
 			*lenp = -FDT_ERR_BADVERSION;
 		return NULL;
@@ -336,11 +401,12 @@
 	     (offset = fdt_next_property_offset(fdt, offset))) {
 		const struct fdt_property *prop;
 
-		if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) {
+		prop = fdt_get_property_by_offset_(fdt, offset, lenp);
+		if (!can_assume(LIBFDT_FLAWLESS) && !prop) {
 			offset = -FDT_ERR_INTERNAL;
 			break;
 		}
-		if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
+		if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
 				   name, namelen)) {
 			if (poffset)
 				*poffset = offset;
@@ -361,7 +427,7 @@
 {
 	/* Prior to version 16, properties may need realignment
 	 * and this API does not work. fdt_getprop_*() will, however. */
-	if (fdt_version(fdt) < 0x10) {
+	if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
 		if (lenp)
 			*lenp = -FDT_ERR_BADVERSION;
 		return NULL;
@@ -392,8 +458,8 @@
 		return NULL;
 
 	/* Handle realignment */
-	if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 &&
-	    fdt32_to_cpu(prop->len) >= 8)
+	if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
+	    (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
 		return prop->data + 4;
 	return prop->data;
 }
@@ -406,12 +472,27 @@
 	prop = fdt_get_property_by_offset_(fdt, offset, lenp);
 	if (!prop)
 		return NULL;
-	if (namep)
-		*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+	if (namep) {
+		const char *name;
+		int namelen;
+
+		if (!can_assume(VALID_INPUT)) {
+			name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
+					      &namelen);
+			if (!name) {
+				if (lenp)
+					*lenp = namelen;
+				return NULL;
+			}
+			*namep = name;
+		} else {
+			*namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
+		}
+	}
 
 	/* Handle realignment */
-	if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 &&
-	    fdt32_to_cpu(prop->len) >= 8)
+	if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
+	    (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
 		return prop->data + 4;
 	return prop->data;
 }
@@ -436,7 +517,7 @@
 			return 0;
 	}
 
-	return fdt32_to_cpu(*php);
+	return fdt32_ld(php);
 }
 
 const char *fdt_get_alias_namelen(const void *fdt,
@@ -462,7 +543,7 @@
 	int offset, depth, namelen;
 	const char *name;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	if (buflen < 2)
 		return -FDT_ERR_NOSPACE;
@@ -514,7 +595,7 @@
 	int offset, depth;
 	int supernodeoffset = -FDT_ERR_INTERNAL;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	if (supernodedepth < 0)
 		return -FDT_ERR_NOTFOUND;
@@ -536,10 +617,12 @@
 		}
 	}
 
-	if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
-		return -FDT_ERR_BADOFFSET;
-	else if (offset == -FDT_ERR_BADOFFSET)
-		return -FDT_ERR_BADSTRUCTURE;
+	if (!can_assume(VALID_INPUT)) {
+		if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+			return -FDT_ERR_BADOFFSET;
+		else if (offset == -FDT_ERR_BADOFFSET)
+			return -FDT_ERR_BADSTRUCTURE;
+	}
 
 	return offset; /* error from fdt_next_node() */
 }
@@ -551,7 +634,8 @@
 
 	err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
 	if (err)
-		return (err < 0) ? err : -FDT_ERR_INTERNAL;
+		return (can_assume(LIBFDT_FLAWLESS) || err < 0) ? err :
+			-FDT_ERR_INTERNAL;
 	return nodedepth;
 }
 
@@ -573,7 +657,7 @@
 	const void *val;
 	int len;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	/* FIXME: The algorithm here is pretty horrible: we scan each
 	 * property of a node in fdt_getprop(), then if that didn't
@@ -599,7 +683,7 @@
 	if ((phandle == 0) || (phandle == -1))
 		return -FDT_ERR_BADPHANDLE;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	/* FIXME: The algorithm here is pretty horrible: we
 	 * potentially scan each property of a node in
@@ -752,7 +836,7 @@
 {
 	int offset, err;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	/* FIXME: The algorithm here is pretty horrible: we scan each
 	 * property of a node in fdt_node_check_compatible(), then if
diff --git a/lib/libfdt/fdt_rw.c b/lib/libfdt/fdt_rw.c
index 9b82905..93e4a2b 100644
--- a/lib/libfdt/fdt_rw.c
+++ b/lib/libfdt/fdt_rw.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "libfdt_env.h"
 
@@ -67,29 +22,31 @@
 		    (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
 }
 
-static int fdt_rw_check_header_(void *fdt)
+static int fdt_rw_probe_(void *fdt)
 {
-	FDT_CHECK_HEADER(fdt);
+	if (can_assume(VALID_DTB))
+		return 0;
+	FDT_RO_PROBE(fdt);
 
-	if (fdt_version(fdt) < 17)
+	if (!can_assume(LATEST) && fdt_version(fdt) < 17)
 		return -FDT_ERR_BADVERSION;
 	if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry),
 				   fdt_size_dt_struct(fdt)))
 		return -FDT_ERR_BADLAYOUT;
-	if (fdt_version(fdt) > 17)
+	if (!can_assume(LATEST) && fdt_version(fdt) > 17)
 		fdt_set_version(fdt, 17);
 
 	return 0;
 }
 
-#define FDT_RW_CHECK_HEADER(fdt) \
+#define FDT_RW_PROBE(fdt) \
 	{ \
 		int err_; \
-		if ((err_ = fdt_rw_check_header_(fdt)) != 0) \
+		if ((err_ = fdt_rw_probe_(fdt)) != 0) \
 			return err_; \
 	}
 
-static inline int fdt_data_size_(void *fdt)
+static inline unsigned int fdt_data_size_(void *fdt)
 {
 	return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
 }
@@ -97,15 +54,16 @@
 static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
 {
 	char *p = splicepoint;
-	char *end = (char *)fdt + fdt_data_size_(fdt);
+	unsigned int dsize = fdt_data_size_(fdt);
+	size_t soff = p - (char *)fdt;
 
-	if (((p + oldlen) < p) || ((p + oldlen) > end))
+	if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize))
 		return -FDT_ERR_BADOFFSET;
-	if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt))
+	if ((p < (char *)fdt) || (dsize + newlen < oldlen))
 		return -FDT_ERR_BADOFFSET;
-	if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
+	if (dsize - oldlen + newlen > fdt_totalsize(fdt))
 		return -FDT_ERR_NOSPACE;
-	memmove(p + newlen, p + oldlen, end - p - oldlen);
+	memmove(p + newlen, p + oldlen, ((char *)fdt + dsize) - (p + oldlen));
 	return 0;
 }
 
@@ -136,6 +94,14 @@
 	return 0;
 }
 
+/* Must only be used to roll back in case of error */
+static void fdt_del_last_string_(void *fdt, const char *s)
+{
+	int newlen = strlen(s) + 1;
+
+	fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) - newlen);
+}
+
 static int fdt_splice_string_(void *fdt, int newlen)
 {
 	void *p = (char *)fdt
@@ -149,7 +115,16 @@
 	return 0;
 }
 
-static int fdt_find_add_string_(void *fdt, const char *s)
+/**
+ * fdt_find_add_string_() - Find or allocate a string
+ *
+ * @fdt: pointer to the device tree to check/adjust
+ * @s: string to find/add
+ * @allocated: Set to 0 if the string was found, 1 if not found and so
+ *	allocated. Ignored if can_assume(NO_ROLLBACK)
+ * @return offset of string in the string table (whether found or added)
+ */
+static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
 {
 	char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
 	const char *p;
@@ -157,6 +132,9 @@
 	int len = strlen(s) + 1;
 	int err;
 
+	if (!can_assume(NO_ROLLBACK))
+		*allocated = 0;
+
 	p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s);
 	if (p)
 		/* found it */
@@ -167,6 +145,9 @@
 	if (err)
 		return err;
 
+	if (!can_assume(NO_ROLLBACK))
+		*allocated = 1;
+
 	memcpy(new, s, len);
 	return (new - strtab);
 }
@@ -176,7 +157,7 @@
 	struct fdt_reserve_entry *re;
 	int err;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt));
 	err = fdt_splice_mem_rsv_(fdt, re, 0, 1);
@@ -192,7 +173,7 @@
 {
 	struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n);
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	if (n >= fdt_num_mem_rsv(fdt))
 		return -FDT_ERR_NOTFOUND;
@@ -225,11 +206,12 @@
 	int nextoffset;
 	int namestroff;
 	int err;
+	int allocated;
 
 	if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
 		return nextoffset;
 
-	namestroff = fdt_find_add_string_(fdt, name);
+	namestroff = fdt_find_add_string_(fdt, name, &allocated);
 	if (namestroff < 0)
 		return namestroff;
 
@@ -237,8 +219,12 @@
 	proplen = sizeof(**prop) + FDT_TAGALIGN(len);
 
 	err = fdt_splice_struct_(fdt, *prop, 0, proplen);
-	if (err)
+	if (err) {
+		/* Delete the string if we failed to add it */
+		if (!can_assume(NO_ROLLBACK) && allocated)
+			fdt_del_last_string_(fdt, name);
 		return err;
+	}
 
 	(*prop)->tag = cpu_to_fdt32(FDT_PROP);
 	(*prop)->nameoff = cpu_to_fdt32(namestroff);
@@ -252,7 +238,7 @@
 	int oldlen, newlen;
 	int err;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
 	if (!namep)
@@ -275,7 +261,7 @@
 	struct fdt_property *prop;
 	int err;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);
 	if (err == -FDT_ERR_NOTFOUND)
@@ -308,7 +294,7 @@
 	struct fdt_property *prop;
 	int err, oldlen, newlen;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
 	if (prop) {
@@ -334,7 +320,7 @@
 	struct fdt_property *prop;
 	int len, proplen;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
 	if (!prop)
@@ -354,7 +340,7 @@
 	uint32_t tag;
 	fdt32_t *endtag;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
 	if (offset >= 0)
@@ -394,7 +380,7 @@
 {
 	int endoffset;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	endoffset = fdt_node_end_offset_(fdt, nodeoffset);
 	if (endoffset < 0)
@@ -435,12 +421,12 @@
 	const char *fdtend = fdtstart + fdt_totalsize(fdt);
 	char *tmp;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
 		* sizeof(struct fdt_reserve_entry);
 
-	if (fdt_version(fdt) >= 17) {
+	if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
 		struct_size = fdt_size_dt_struct(fdt);
 	} else {
 		struct_size = 0;
@@ -450,7 +436,8 @@
 			return struct_size;
 	}
 
-	if (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
+	if (can_assume(LIBFDT_ORDER) ||
+	    !fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
 		/* no further work necessary */
 		err = fdt_move(fdt, buf, bufsize);
 		if (err)
@@ -494,7 +481,7 @@
 {
 	int mem_rsv_size;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
 		* sizeof(struct fdt_reserve_entry);
diff --git a/lib/libfdt/fdt_strerror.c b/lib/libfdt/fdt_strerror.c
index 9677a18..768db66 100644
--- a/lib/libfdt/fdt_strerror.c
+++ b/lib/libfdt/fdt_strerror.c
@@ -1,51 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "libfdt_env.h"
@@ -82,6 +38,7 @@
 	FDT_ERRTABENT(FDT_ERR_BADVALUE),
 	FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
 	FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
+	FDT_ERRTABENT(FDT_ERR_BADFLAGS),
 };
 #define FDT_ERRTABSIZE	(sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
 
diff --git a/lib/libfdt/fdt_sw.c b/lib/libfdt/fdt_sw.c
index 6d33cc2..26759d5 100644
--- a/lib/libfdt/fdt_sw.c
+++ b/lib/libfdt/fdt_sw.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "libfdt_env.h"
 
@@ -55,21 +10,87 @@
 
 #include "libfdt_internal.h"
 
-static int fdt_sw_check_header_(void *fdt)
+static int fdt_sw_probe_(void *fdt)
 {
-	if (fdt_magic(fdt) != FDT_SW_MAGIC)
-		return -FDT_ERR_BADMAGIC;
-	/* FIXME: should check more details about the header state */
+	if (!can_assume(VALID_INPUT)) {
+		if (fdt_magic(fdt) == FDT_MAGIC)
+			return -FDT_ERR_BADSTATE;
+		else if (fdt_magic(fdt) != FDT_SW_MAGIC)
+			return -FDT_ERR_BADMAGIC;
+	}
+
 	return 0;
 }
 
-#define FDT_SW_CHECK_HEADER(fdt) \
+#define FDT_SW_PROBE(fdt) \
 	{ \
 		int err; \
-		if ((err = fdt_sw_check_header_(fdt)) != 0) \
+		if ((err = fdt_sw_probe_(fdt)) != 0) \
 			return err; \
 	}
 
+/* 'memrsv' state:	Initial state after fdt_create()
+ *
+ * Allowed functions:
+ *	fdt_add_reservmap_entry()
+ *	fdt_finish_reservemap()		[moves to 'struct' state]
+ */
+static int fdt_sw_probe_memrsv_(void *fdt)
+{
+	int err = fdt_sw_probe_(fdt);
+	if (err)
+		return err;
+
+	if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0)
+		return -FDT_ERR_BADSTATE;
+	return 0;
+}
+
+#define FDT_SW_PROBE_MEMRSV(fdt) \
+	{ \
+		int err; \
+		if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \
+			return err; \
+	}
+
+/* 'struct' state:	Enter this state after fdt_finish_reservemap()
+ *
+ * Allowed functions:
+ *	fdt_begin_node()
+ *	fdt_end_node()
+ *	fdt_property*()
+ *	fdt_finish()			[moves to 'complete' state]
+ */
+static int fdt_sw_probe_struct_(void *fdt)
+{
+	int err = fdt_sw_probe_(fdt);
+	if (err)
+		return err;
+
+	if (!can_assume(VALID_INPUT) &&
+	    fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
+		return -FDT_ERR_BADSTATE;
+	return 0;
+}
+
+#define FDT_SW_PROBE_STRUCT(fdt) \
+	{ \
+		int err; \
+		if ((err = fdt_sw_probe_struct_(fdt)) != 0) \
+			return err; \
+	}
+
+static inline uint32_t sw_flags(void *fdt)
+{
+	/* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */
+	return fdt_last_comp_version(fdt);
+}
+
+/* 'complete' state:	Enter this state after fdt_finish()
+ *
+ * Allowed functions: none
+ */
+
 static void *fdt_grab_space_(void *fdt, size_t len)
 {
 	int offset = fdt_size_dt_struct(fdt);
@@ -85,38 +106,59 @@
 	return fdt_offset_ptr_w_(fdt, offset);
 }
 
-int fdt_create(void *buf, int bufsize)
+int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags)
 {
+	const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
+					 sizeof(struct fdt_reserve_entry));
 	void *fdt = buf;
 
-	if (bufsize < sizeof(struct fdt_header))
+	if (bufsize < hdrsize)
 		return -FDT_ERR_NOSPACE;
 
+	if (flags & ~FDT_CREATE_FLAGS_ALL)
+		return -FDT_ERR_BADFLAGS;
+
 	memset(buf, 0, bufsize);
 
+	/*
+	 * magic and last_comp_version keep intermediate state during the fdt
+	 * creation process, which is replaced with the proper FDT format by
+	 * fdt_finish().
+	 *
+	 * flags should be accessed with sw_flags().
+	 */
 	fdt_set_magic(fdt, FDT_SW_MAGIC);
 	fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
-	fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
+	fdt_set_last_comp_version(fdt, flags);
+
 	fdt_set_totalsize(fdt,  bufsize);
 
-	fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
-					      sizeof(struct fdt_reserve_entry)));
+	fdt_set_off_mem_rsvmap(fdt, hdrsize);
 	fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
-	fdt_set_off_dt_strings(fdt, bufsize);
+	fdt_set_off_dt_strings(fdt, 0);
 
 	return 0;
 }
 
+int fdt_create(void *buf, int bufsize)
+{
+	return fdt_create_with_flags(buf, bufsize, 0);
+}
+
 int fdt_resize(void *fdt, void *buf, int bufsize)
 {
 	size_t headsize, tailsize;
 	char *oldtail, *newtail;
 
-	FDT_SW_CHECK_HEADER(fdt);
+	FDT_SW_PROBE(fdt);
 
-	headsize = fdt_off_dt_struct(fdt);
+	headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
 	tailsize = fdt_size_dt_strings(fdt);
 
+	if (!can_assume(VALID_DTB) &&
+	    headsize + tailsize > fdt_totalsize(fdt))
+		return -FDT_ERR_INTERNAL;
+
 	if ((headsize + tailsize) > bufsize)
 		return -FDT_ERR_NOSPACE;
 
@@ -133,8 +175,9 @@
 		memmove(buf, fdt, headsize);
 	}
 
-	fdt_set_off_dt_strings(buf, bufsize);
 	fdt_set_totalsize(buf, bufsize);
+	if (fdt_off_dt_strings(buf))
+		fdt_set_off_dt_strings(buf, bufsize);
 
 	return 0;
 }
@@ -144,10 +187,7 @@
 	struct fdt_reserve_entry *re;
 	int offset;
 
-	FDT_SW_CHECK_HEADER(fdt);
-
-	if (fdt_size_dt_struct(fdt))
-		return -FDT_ERR_BADSTATE;
+	FDT_SW_PROBE_MEMRSV(fdt);
 
 	offset = fdt_off_dt_struct(fdt);
 	if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
@@ -164,16 +204,23 @@
 
 int fdt_finish_reservemap(void *fdt)
 {
-	return fdt_add_reservemap_entry(fdt, 0, 0);
+	int err = fdt_add_reservemap_entry(fdt, 0, 0);
+
+	if (err)
+		return err;
+
+	fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt));
+	return 0;
 }
 
 int fdt_begin_node(void *fdt, const char *name)
 {
 	struct fdt_node_header *nh;
-	int namelen = strlen(name) + 1;
+	int namelen;
 
-	FDT_SW_CHECK_HEADER(fdt);
+	FDT_SW_PROBE_STRUCT(fdt);
 
+	namelen = strlen(name) + 1;
 	nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
 	if (! nh)
 		return -FDT_ERR_NOSPACE;
@@ -187,7 +234,7 @@
 {
 	fdt32_t *en;
 
-	FDT_SW_CHECK_HEADER(fdt);
+	FDT_SW_PROBE_STRUCT(fdt);
 
 	en = fdt_grab_space_(fdt, FDT_TAGSIZE);
 	if (! en)
@@ -197,19 +244,13 @@
 	return 0;
 }
 
-static int fdt_find_add_string_(void *fdt, const char *s)
+static int fdt_add_string_(void *fdt, const char *s)
 {
 	char *strtab = (char *)fdt + fdt_totalsize(fdt);
-	const char *p;
 	int strtabsize = fdt_size_dt_strings(fdt);
 	int len = strlen(s) + 1;
 	int struct_top, offset;
 
-	p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
-	if (p)
-		return p - strtab;
-
-	/* Add it */
 	offset = -strtabsize - len;
 	struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
 	if (fdt_totalsize(fdt) + offset < struct_top)
@@ -220,20 +261,56 @@
 	return offset;
 }
 
+/* Must only be used to roll back in case of error */
+static void fdt_del_last_string_(void *fdt, const char *s)
+{
+	int strtabsize = fdt_size_dt_strings(fdt);
+	int len = strlen(s) + 1;
+
+	fdt_set_size_dt_strings(fdt, strtabsize - len);
+}
+
+static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
+{
+	char *strtab = (char *)fdt + fdt_totalsize(fdt);
+	int strtabsize = fdt_size_dt_strings(fdt);
+	const char *p;
+
+	*allocated = 0;
+
+	p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
+	if (p)
+		return p - strtab;
+
+	*allocated = 1;
+
+	return fdt_add_string_(fdt, s);
+}
+
 int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
 {
 	struct fdt_property *prop;
 	int nameoff;
+	int allocated;
 
-	FDT_SW_CHECK_HEADER(fdt);
+	FDT_SW_PROBE_STRUCT(fdt);
 
-	nameoff = fdt_find_add_string_(fdt, name);
+	/* String de-duplication can be slow, _NO_NAME_DEDUP skips it */
+	if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) {
+		allocated = 1;
+		nameoff = fdt_add_string_(fdt, name);
+	} else {
+		nameoff = fdt_find_add_string_(fdt, name, &allocated);
+	}
 	if (nameoff == 0)
 		return -FDT_ERR_NOSPACE;
 
 	prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
-	if (! prop)
+	if (! prop) {
+		if (allocated)
+			fdt_del_last_string_(fdt, name);
 		return -FDT_ERR_NOSPACE;
+	}
 
 	prop->tag = cpu_to_fdt32(FDT_PROP);
 	prop->nameoff = cpu_to_fdt32(nameoff);
@@ -262,7 +339,7 @@
 	uint32_t tag;
 	int offset, nextoffset;
 
-	FDT_SW_CHECK_HEADER(fdt);
+	FDT_SW_PROBE_STRUCT(fdt);
 
 	/* Add terminator */
 	end = fdt_grab_space_(fdt, sizeof(*end));
@@ -295,6 +372,10 @@
 
 	/* Finally, adjust the header */
 	fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
+
+	/* And fix up fields that were keeping intermediate state. */
+	fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
 	fdt_set_magic(fdt, FDT_MAGIC);
+
 	return 0;
 }
diff --git a/lib/libfdt/fdt_wip.c b/lib/libfdt/fdt_wip.c
index 534c1cb..f64139e 100644
--- a/lib/libfdt/fdt_wip.c
+++ b/lib/libfdt/fdt_wip.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "libfdt_env.h"
 
diff --git a/lib/libfdt/libfdt_internal.h b/lib/libfdt/libfdt_internal.h
index 7681e19..d4e0bd4 100644
--- a/lib/libfdt/libfdt_internal.h
+++ b/lib/libfdt/libfdt_internal.h
@@ -1,65 +1,21 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
 #ifndef LIBFDT_INTERNAL_H
 #define LIBFDT_INTERNAL_H
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include <fdt.h>
 
 #define FDT_ALIGN(x, a)		(((x) + (a) - 1) & ~((a) - 1))
 #define FDT_TAGALIGN(x)		(FDT_ALIGN((x), FDT_TAGSIZE))
 
-#define FDT_CHECK_HEADER(fdt) \
-	{ \
-		int err_; \
-		if ((err_ = fdt_check_header(fdt)) != 0) \
-			return err_; \
+int32_t fdt_ro_probe_(const void *fdt);
+#define FDT_RO_PROBE(fdt)					\
+	{							\
+		int32_t totalsize_;				\
+		if ((totalsize_ = fdt_ro_probe_(fdt)) < 0)	\
+			return totalsize_;			\
 	}
 
 int fdt_check_node_offset_(const void *fdt, int offset);
@@ -92,4 +48,126 @@
 
 #define FDT_SW_MAGIC		(~FDT_MAGIC)
 
+/**********************************************************************/
+/* Checking controls                                                  */
+/**********************************************************************/
+
+#ifndef FDT_ASSUME_MASK
+#define FDT_ASSUME_MASK 0
+#endif
+
+/*
+ * Defines assumptions which can be enabled. Each of these can be enabled
+ * individually. For maximum safety, don't enable any assumptions!
+ *
+ * For minimal code size and no safety, use ASSUME_PERFECT at your own risk.
+ * You should have another method of validating the device tree, such as a
+ * signature or hash check before using libfdt.
+ *
+ * For situations where security is not a concern it may be safe to enable
+ * ASSUME_SANE.
+ */
+enum {
+	/*
+	 * This does essentially no checks. Only the latest device-tree
+	 * version is correctly handled. Inconsistencies or errors in the device
+	 * tree may cause undefined behaviour or crashes. Invalid parameters
+	 * passed to libfdt may do the same.
+	 *
+	 * If an error occurs when modifying the tree it may leave the tree in
+	 * an intermediate (but valid) state. As an example, adding a property
+	 * where there is insufficient space may result in the property name
+	 * being added to the string table even though the property itself is
+	 * not added to the struct section.
+	 *
+	 * Only use this if you have a fully validated device tree with
+	 * the latest supported version and wish to minimise code size.
+	 */
+	ASSUME_PERFECT		= 0xff,
+
+	/*
+	 * This assumes that the device tree is sane. i.e. header metadata
+	 * and basic hierarchy are correct.
+	 *
+	 * With this assumption enabled, normal device trees produced by libfdt
+	 * and the compiler should be handled safely. Malicious device trees and
+	 * complete garbage may cause libfdt to behave badly or crash. Truncated
+	 * device trees (e.g. those only partially loaded) can also cause
+	 * problems.
+	 *
+	 * Note: Only checks that relate exclusively to the device tree itself
+	 * (not the parameters passed to libfdt) are disabled by this
+	 * assumption. This includes checking headers, tags and the like.
+	 */
+	ASSUME_VALID_DTB	= 1 << 0,
+
+	/*
+	 * This builds on ASSUME_VALID_DTB and further assumes that libfdt
+	 * functions are called with valid parameters, i.e. not trigger
+	 * FDT_ERR_BADOFFSET or offsets that are out of bounds. It disables any
+	 * extensive checking of parameters and the device tree, making various
+	 * assumptions about correctness.
+	 *
+	 * It doesn't make sense to enable this assumption unless
+	 * ASSUME_VALID_DTB is also enabled.
+	 */
+	ASSUME_VALID_INPUT	= 1 << 1,
+
+	/*
+	 * This disables checks for device-tree version and removes all code
+	 * which handles older versions.
+	 *
+	 * Only enable this if you know you have a device tree with the latest
+	 * version.
+	 */
+	ASSUME_LATEST		= 1 << 2,
+
+	/*
+	 * This assumes that it is OK for a failed addition to the device tree,
+	 * due to lack of space or some other problem, to skip any rollback
+	 * steps (such as dropping the property name from the string table).
+	 * This is safe to enable in most circumstances, even though it may
+	 * leave the tree in a sub-optimal state.
+	 */
+	ASSUME_NO_ROLLBACK	= 1 << 3,
+
+	/*
+	 * This assumes that the device tree components appear in a 'convenient'
+	 * order, i.e. the memory reservation block first, then the structure
+	 * block and finally the string block.
+	 *
+	 * This order is not specified by the device-tree specification,
+	 * but is expected by libfdt. The device-tree compiler always created
+	 * device trees with this order.
+	 *
+	 * This assumption disables a check in fdt_open_into() and removes the
+	 * ability to fix the problem there. This is safe if you know that the
+	 * device tree is correctly ordered. See fdt_blocks_misordered_().
+	 */
+	ASSUME_LIBFDT_ORDER	= 1 << 4,
+
+	/*
+	 * This assumes that libfdt itself does not have any internal bugs. It
+	 * drops certain checks that should never be needed unless libfdt has an
+	 * undiscovered bug.
+	 *
+	 * This can generally be considered safe to enable.
+	 */
+	ASSUME_LIBFDT_FLAWLESS	= 1 << 5,
+};
+
+/**
+ * can_assume_() - check if a particular assumption is enabled
+ *
+ * @mask: Mask to check (ASSUME_...)
+ * @return true if that assumption is enabled, else false
+ */
+static inline bool can_assume_(int mask)
+{
+	return FDT_ASSUME_MASK & mask;
+}
+
+/** helper macros for checking assumptions */
+#define can_assume(_assume)	can_assume_(ASSUME_ ## _assume)
+
 #endif /* LIBFDT_INTERNAL_H */
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 6db228f..9a6fd58 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -305,3 +305,6 @@
 
 # Trap RAS error record access from lower EL
 RAS_TRAP_LOWER_EL_ERR_ACCESS	:= 0
+
+# Build option to create cot descriptors using fconf
+COT_DESC_IN_DTB			:= 0
diff --git a/plat/arm/board/a5ds/platform.mk b/plat/arm/board/a5ds/platform.mk
index 7693e46..5d610f4 100644
--- a/plat/arm/board/a5ds/platform.mk
+++ b/plat/arm/board/a5ds/platform.mk
@@ -14,9 +14,10 @@
 				plat/arm/common/arm_dyn_cfg_helpers.c	\
 				common/fdt_wrappers.c
 
-A5DS_GIC_SOURCES	:=	drivers/arm/gic/common/gic_common.c	\
-				drivers/arm/gic/v2/gicv2_main.c		\
-				drivers/arm/gic/v2/gicv2_helpers.c	\
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+A5DS_GIC_SOURCES	:=	${GICV2_SOURCES}			\
 				plat/common/plat_gicv2.c		\
 				plat/arm/common/arm_gicv2.c
 
diff --git a/plat/arm/board/arm_fpga/fpga_def.h b/plat/arm/board/arm_fpga/fpga_def.h
index 0378729..5f1951f 100644
--- a/plat/arm/board/arm_fpga/fpga_def.h
+++ b/plat/arm/board/arm_fpga/fpga_def.h
@@ -18,7 +18,7 @@
  * that are present will still be indexed appropriately regardless of any empty
  * entries in the array used to represent the topology.
  */
-#define FPGA_MAX_CLUSTER_COUNT			2
+#define FPGA_MAX_CLUSTER_COUNT			4
 #define FPGA_MAX_CPUS_PER_CLUSTER		8
 #define FPGA_MAX_PE_PER_CPU			4
 
diff --git a/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk
index 34e50ea..e57912c 100644
--- a/plat/arm/board/arm_fpga/platform.mk
+++ b/plat/arm/board/arm_fpga/platform.mk
@@ -24,15 +24,10 @@
 $(error "TRUSTED_BOARD_BOOT must be disabled")
 endif
 
-ifndef PRELOADED_BL33_BASE
-$(error "PRELOADED_BL33_BASE is not set")
-endif
+PRELOADED_BL33_BASE := 0x80080000
 
-ifndef FPGA_PRELOADED_DTB_BASE
-$(error "FPGA_PRELOADED_DTB_BASE is not set")
-else
+FPGA_PRELOADED_DTB_BASE := 0x80070000
 $(eval $(call add_define,FPGA_PRELOADED_DTB_BASE))
-endif
 
 # Treating this as a memory-constrained port for now
 USE_COHERENT_MEM	:=	0
@@ -64,7 +59,10 @@
 				lib/cpus/aarch64/neoverse_zeus.S	\
 				lib/cpus/aarch64/cortex_hercules_ae.S	\
 				lib/cpus/aarch64/cortex_a65.S		\
-				lib/cpus/aarch64/cortex_a65ae.S
+				lib/cpus/aarch64/cortex_a65ae.S		\
+				lib/cpus/aarch64/cortex_klein.S		\
+				lib/cpus/aarch64/cortex_matterhorn.S
+
 # AArch64/AArch32 cores
 	FPGA_CPU_LIBS	+=	lib/cpus/aarch64/cortex_a55.S	\
 				lib/cpus/aarch64/cortex_a75.S
diff --git a/plat/arm/board/corstone700/platform.mk b/plat/arm/board/corstone700/platform.mk
index 3398fba..513af3c 100644
--- a/plat/arm/board/corstone700/platform.mk
+++ b/plat/arm/board/corstone700/platform.mk
@@ -25,9 +25,10 @@
 
 NEED_BL32		:=	yes
 
-CORSTONE700_GIC_SOURCES	:=	drivers/arm/gic/common/gic_common.c	\
-				drivers/arm/gic/v2/gicv2_main.c		\
-				drivers/arm/gic/v2/gicv2_helpers.c	\
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+CORSTONE700_GIC_SOURCES	:=	${GICV2_SOURCES}			\
 				plat/common/plat_gicv2.c		\
 				plat/arm/common/arm_gicv2.c
 
diff --git a/plat/arm/board/fvp/fdts/fvp_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_fw_config.dts
index 09f2730..9fb566b 100644
--- a/plat/arm/board/fvp/fdts/fvp_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_fw_config.dts
@@ -14,7 +14,7 @@
 
 		tb_fw-config {
 			load-address = <0x0 0x4001300>;
-			max-size = <0x200>;
+			max-size = <0x1800>;
 			id = <TB_FW_CONFIG_ID>;
 		};
 
diff --git a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
index 9cffad3..8b9e41c 100644
--- a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
@@ -85,4 +85,22 @@
 			load-address = <0x7100000>;
 		};
 	};
+
+#if COT_DESC_IN_DTB
+	#include "cot_descriptors.dtsi"
+#endif
+
 };
+
+#if COT_DESC_IN_DTB
+
+#include "../fvp_def.h"
+
+&trusted_nv_counter {
+	reg = <TFW_NVCTR_BASE>;
+};
+
+&non_trusted_nv_counter {
+	reg = <NTFW_CTR_BASE>;
+};
+#endif
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 7222c55..f8fb821 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -120,7 +120,7 @@
 #if TRUSTED_BOARD_BOOT
 # define PLAT_ARM_MAX_BL2_SIZE	(UL(0x1D000) - FVP_BL2_ROMLIB_OPTIMIZATION)
 #else
-# define PLAT_ARM_MAX_BL2_SIZE	(UL(0x12000) - FVP_BL2_ROMLIB_OPTIMIZATION)
+# define PLAT_ARM_MAX_BL2_SIZE	(UL(0x13000) - FVP_BL2_ROMLIB_OPTIMIZATION)
 #endif
 
 #if RESET_TO_BL31
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index c3b49bb..9b8fccc 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -72,13 +72,10 @@
 GIC_ENABLE_V4_EXTN	:=	0
 $(eval $(call add_define,GIC_ENABLE_V4_EXTN))
 
-# No support for extended PPI and SPI range
-GIC_EXT_INTID		:=	0
-$(eval $(call add_define,GIC_EXT_INTID))
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
 
-FVP_GIC_SOURCES		:=	drivers/arm/gic/common/gic_common.c	\
-				drivers/arm/gic/v2/gicv2_main.c		\
-				drivers/arm/gic/v2/gicv2_helpers.c	\
+FVP_GIC_SOURCES		:=	${GICV2_SOURCES}			\
 				plat/common/plat_gicv2.c		\
 				plat/arm/common/arm_gicv2.c
 
diff --git a/plat/arm/board/fvp_ve/platform.mk b/plat/arm/board/fvp_ve/platform.mk
index 62981c5..f8e38ff 100644
--- a/plat/arm/board/fvp_ve/platform.mk
+++ b/plat/arm/board/fvp_ve/platform.mk
@@ -11,10 +11,11 @@
 BL2_SOURCES		+=	drivers/arm/sp804/sp804_delay_timer.c
 endif
 
-FVP_VE_GIC_SOURCES		:=	drivers/arm/gic/common/gic_common.c	\
-				drivers/arm/gic/v2/gicv2_main.c		\
-				drivers/arm/gic/v2/gicv2_helpers.c	\
-				plat/common/plat_gicv2.c		\
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+FVP_VE_GIC_SOURCES	:=	${GICV2_SOURCES}		\
+				plat/common/plat_gicv2.c	\
 				plat/arm/common/arm_gicv2.c
 
 FVP_VE_SECURITY_SOURCES	:=	plat/arm/board/fvp_ve/fvp_ve_security.c
diff --git a/plat/arm/board/juno/jmptbl.i b/plat/arm/board/juno/jmptbl.i
index 20ed2c7..393a648 100644
--- a/plat/arm/board/juno/jmptbl.i
+++ b/plat/arm/board/juno/jmptbl.i
@@ -29,6 +29,8 @@
 fdt     fdt_get_alias_namelen
 fdt     fdt_path_offset
 fdt     fdt_path_offset_namelen
+fdt     fdt_address_cells
+fdt     fdt_size_cells
 fdt     fdt_get_name
 fdt     fdt_get_alias
 fdt     fdt_node_offset_by_phandle
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index 8ca7f61..196d3c0 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -4,9 +4,10 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
-JUNO_GIC_SOURCES	:=	drivers/arm/gic/common/gic_common.c	\
-				drivers/arm/gic/v2/gicv2_main.c		\
-				drivers/arm/gic/v2/gicv2_helpers.c	\
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+JUNO_GIC_SOURCES	:=	${GICV2_SOURCES}			\
 				plat/common/plat_gicv2.c		\
 				plat/arm/common/arm_gicv2.c
 
diff --git a/plat/arm/board/rddaniel/platform.mk b/plat/arm/board/rddaniel/platform.mk
index bdf20ca..81632a5 100644
--- a/plat/arm/board/rddaniel/platform.mk
+++ b/plat/arm/board/rddaniel/platform.mk
@@ -32,6 +32,11 @@
 				lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c
 
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES		+=	${RDDANIEL_BASE}/rddaniel_trusted_boot.c
+BL2_SOURCES		+=	${RDDANIEL_BASE}/rddaniel_trusted_boot.c
+endif
+
 # Add the FDT_SOURCES and options for Dynamic Config
 FDT_SOURCES		+=	${RDDANIEL_BASE}/fdts/${PLAT}_fw_config.dts	\
 				${RDDANIEL_BASE}/fdts/${PLAT}_tb_fw_config.dts
diff --git a/plat/arm/board/rddaniel/rddaniel_trusted_boot.c b/plat/arm/board/rddaniel/rddaniel_trusted_boot.c
new file mode 100644
index 0000000..4592b8f
--- /dev/null
+++ b/plat/arm/board/rddaniel/rddaniel_trusted_boot.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier  ::=  SEQUENCE  {
+ *     algorithm         OBJECT IDENTIFIER,
+ *     parameters        ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ *     digestAlgorithm   AlgorithmIdentifier,
+ *     digest            OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+	return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/rddanielxlr/platform.mk b/plat/arm/board/rddanielxlr/platform.mk
index 1482c81..93967ad 100644
--- a/plat/arm/board/rddanielxlr/platform.mk
+++ b/plat/arm/board/rddanielxlr/platform.mk
@@ -32,6 +32,11 @@
 				lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c
 
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES		+=	${RDDANIELXLR_BASE}/rddanielxlr_trusted_boot.c
+BL2_SOURCES		+=	${RDDANIELXLR_BASE}/rddanielxlr_trusted_boot.c
+endif
+
 # Enable dynamic addition of MMAP regions in BL31
 BL31_CFLAGS		+=	-DPLAT_XLAT_TABLES_DYNAMIC
 
diff --git a/plat/arm/board/rddanielxlr/rddanielxlr_trusted_boot.c b/plat/arm/board/rddanielxlr/rddanielxlr_trusted_boot.c
new file mode 100644
index 0000000..4592b8f
--- /dev/null
+++ b/plat/arm/board/rddanielxlr/rddanielxlr_trusted_boot.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier  ::=  SEQUENCE  {
+ *     algorithm         OBJECT IDENTIFIER,
+ *     parameters        ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ *     digestAlgorithm   AlgorithmIdentifier,
+ *     digest            OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+	return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
diff --git a/plat/brcm/board/common/board_common.mk b/plat/brcm/board/common/board_common.mk
index 808a107..3069f91 100644
--- a/plat/brcm/board/common/board_common.mk
+++ b/plat/brcm/board/common/board_common.mk
@@ -133,6 +133,12 @@
 				plat/brcm/board/common/sbl_util.c \
 				drivers/arm/sp805/sp805.c
 
+# Add RNG driver
+DRIVER_RNG_ENABLE := 1
+ifeq (${DRIVER_RNG_ENABLE},1)
+PLAT_BL_COMMON_SOURCES	+=	drivers/brcm/rng.c
+endif
+
 # Add eMMC driver
 ifeq (${DRIVER_EMMC_ENABLE},1)
 $(eval $(call add_define,DRIVER_EMMC_ENABLE))
diff --git a/plat/brcm/board/stingray/include/sr_def.h b/plat/brcm/board/stingray/include/sr_def.h
index ac3ee78..be0dee1 100644
--- a/plat/brcm/board/stingray/include/sr_def.h
+++ b/plat/brcm/board/stingray/include/sr_def.h
@@ -292,6 +292,11 @@
 #define ICFG_PKA_MEM_PWR_CTRL__ISO		BIT(8)
 
 /*******************************************************************************
+ * RNG constants
+ ******************************************************************************/
+#define RNG_BASE_ADDR			0x68b20000
+
+/*******************************************************************************
  * Trusted Watchdog constants
  ******************************************************************************/
 #define ARM_SP805_TWDG_BASE		0x68b30000
diff --git a/plat/common/plat_spmd_manifest.c b/plat/common/plat_spmd_manifest.c
index 455b980..e65980b 100644
--- a/plat/common/plat_spmd_manifest.c
+++ b/plat/common/plat_spmd_manifest.c
@@ -128,7 +128,13 @@
 	 */
 	pm_base = (uintptr_t)pm_addr;
 	pm_base_align = page_align(pm_base, UP);
-	mapped_size = pm_base_align - pm_base;
+
+	if (pm_base == pm_base_align) {
+		/* Page aligned */
+		mapped_size = PAGE_SIZE;
+	} else {
+		mapped_size = pm_base_align - pm_base;
+	}
 
 	/* Check space within the page at least maps the FDT header */
 	if (mapped_size < sizeof(struct fdt_header)) {
diff --git a/plat/imx/imx8m/imx8mm/include/gpc_reg.h b/plat/imx/imx8m/imx8mm/include/gpc_reg.h
new file mode 100644
index 0000000..c697af2
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/include/gpc_reg.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPC_REG_H
+#define GPC_REG_H
+
+#define LPCR_A53_BSC			0x0
+#define LPCR_A53_BSC2			0x108
+#define LPCR_A53_AD			0x4
+#define LPCR_M4				0x8
+#define SLPCR				0x14
+#define MST_CPU_MAPPING			0x18
+#define MLPCR				0x20
+#define PGC_ACK_SEL_A53			0x24
+#define IMR1_CORE0_A53			0x30
+#define IMR1_CORE1_A53			0x40
+#define IMR1_CORE2_A53			0x1C0
+#define IMR1_CORE3_A53			0x1D0
+#define IMR1_CORE0_M4			0x50
+#define SLT0_CFG			0xB0
+#define GPC_PU_PWRHSK			0x1FC
+#define PGC_CPU_0_1_MAPPING		0xEC
+#define CPU_PGC_UP_TRG			0xF0
+#define PU_PGC_UP_TRG			0xF8
+#define CPU_PGC_DN_TRG			0xFC
+#define PU_PGC_DN_TRG			0x104
+#define LPS_CPU1			0x114
+#define A53_CORE0_PGC			0x800
+#define A53_PLAT_PGC			0x900
+#define PLAT_PGC_PCR			0x900
+#define NOC_PGC_PCR			0xa40
+#define PGC_SCU_TIMING			0x910
+
+#define MASK_DSM_TRIGGER_A53		BIT(31)
+#define IRQ_SRC_A53_WUP			BIT(30)
+#define IRQ_SRC_A53_WUP_SHIFT		30
+#define IRQ_SRC_C1			BIT(29)
+#define IRQ_SRC_C0			BIT(28)
+#define IRQ_SRC_C3			BIT(23)
+#define IRQ_SRC_C2			BIT(22)
+#define CPU_CLOCK_ON_LPM		BIT(14)
+#define A53_CLK_ON_LPM			BIT(14)
+#define MASTER0_LPM_HSK			BIT(6)
+#define MASTER1_LPM_HSK			BIT(7)
+#define MASTER2_LPM_HSK			BIT(8)
+
+#define L2PGE				BIT(31)
+#define EN_L2_WFI_PDN			BIT(5)
+#define EN_PLAT_PDN			BIT(4)
+
+#define SLPCR_EN_DSM			BIT(31)
+#define SLPCR_RBC_EN			BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE	BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE	BIT(16)
+#define SLPCR_VSTBY			BIT(2)
+#define SLPCR_SBYOS			BIT(1)
+#define SLPCR_BYPASS_PMIC_READY		BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT		24
+#define SLPCR_STBY_COUNT_SHFT		3
+
+#define A53_DUMMY_PDN_ACK		BIT(15)
+#define A53_DUMMY_PUP_ACK		BIT(31)
+#define A53_PLAT_PDN_ACK		BIT(2)
+#define A53_PLAT_PUP_ACK		BIT(18)
+#define NOC_PDN_SLT_CTRL		BIT(10)
+#define NOC_PUP_SLT_CTRL		BIT(11)
+#define NOC_PGC_PDN_ACK			BIT(3)
+#define NOC_PGC_PUP_ACK			BIT(19)
+
+#define PLAT_PUP_SLT_CTRL		BIT(9)
+#define PLAT_PDN_SLT_CTRL		BIT(8)
+
+#define SLT_PLAT_PDN			BIT(8)
+#define SLT_PLAT_PUP			BIT(9)
+
+#define MASTER1_MAPPING			BIT(1)
+#define MASTER2_MAPPING			BIT(2)
+
+#define MIPI_PWR_REQ			BIT(0)
+#define PCIE_PWR_REQ			BIT(1)
+#define OTG1_PWR_REQ			BIT(2)
+#define OTG2_PWR_REQ			BIT(3)
+#define HSIOMIX_PWR_REQ			BIT(4)
+#define DDRMIX_PWR_REQ			BIT(5)
+#define GPU2D_PWR_REQ			BIT(6)
+#define GPUMIX_PWR_REQ			BIT(7)
+#define VPUMIX_PWR_REQ			BIT(8)
+#define GPU3D_PWR_REQ			BIT(9)
+#define DISPMIX_PWR_REQ			BIT(10)
+#define VPU_G1_PWR_REQ			BIT(11)
+#define VPU_G2_PWR_REQ			BIT(12)
+#define VPU_H1_PWR_REQ			BIT(13)
+
+#define DDRMIX_ADB400_SYNC		BIT(2)
+#define HSIOMIX_ADB400_SYNC		(0x3 << 5)
+#define DISPMIX_ADB400_SYNC		BIT(7)
+#define VPUMIX_ADB400_SYNC		BIT(8)
+#define GPU3D_ADB400_SYNC		BIT(9)
+#define GPU2D_ADB400_SYNC		BIT(10)
+#define GPUMIX_ADB400_SYNC		BIT(11)
+#define DDRMIX_ADB400_ACK		BIT(20)
+#define HSIOMIX_ADB400_ACK		(0x3 << 23)
+#define DISPMIX_ADB400_ACK		BIT(25)
+#define VPUMIX_ADB400_ACK		BIT(26)
+#define GPU3D_ADB400_ACK		BIT(27)
+#define GPU2D_ADB400_ACK		BIT(28)
+#define GPUMIX_ADB400_ACK		BIT(29)
+
+#define MIPI_PGC			0xc00
+#define PCIE_PGC			0xc40
+#define OTG1_PGC			0xc80
+#define OTG2_PGC			0xcc0
+#define HSIOMIX_PGC			0xd00
+#define DDRMIX_PGC			0xd40
+#define GPU2D_PGC			0xd80
+#define GPUMIX_PGC			0xdc0
+#define VPUMIX_PGC			0xe00
+#define GPU3D_PGC			0xe40
+#define DISPMIX_PGC			0xe80
+#define VPU_G1_PGC			0xec0
+#define VPU_G2_PGC			0xf00
+#define VPU_H1_PGC			0xf40
+
+#endif /* GPC_REG_H */
diff --git a/plat/imx/imx8m/imx8mn/include/gpc_reg.h b/plat/imx/imx8m/imx8mn/include/gpc_reg.h
new file mode 100644
index 0000000..fd10438
--- /dev/null
+++ b/plat/imx/imx8m/imx8mn/include/gpc_reg.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPC_REG_H
+#define GPC_REG_H
+
+#define LPCR_A53_BSC			0x0
+#define LPCR_A53_BSC2			0x108
+#define LPCR_A53_AD			0x4
+#define LPCR_M4				0x8
+#define SLPCR				0x14
+#define MST_CPU_MAPPING			0x18
+#define MLPCR				0x20
+#define PGC_ACK_SEL_A53			0x24
+#define IMR1_CORE0_A53			0x30
+#define IMR1_CORE1_A53			0x40
+#define IMR1_CORE2_A53			0x1C0
+#define IMR1_CORE3_A53			0x1D0
+#define IMR1_CORE0_M4			0x50
+#define SLT0_CFG			0xB0
+#define GPC_PU_PWRHSK			0x1FC
+#define PGC_CPU_0_1_MAPPING		0xEC
+#define CPU_PGC_UP_TRG			0xF0
+#define PU_PGC_UP_TRG			0xF8
+#define CPU_PGC_DN_TRG			0xFC
+#define PU_PGC_DN_TRG			0x104
+#define LPS_CPU1			0x114
+#define A53_CORE0_PGC			0x800
+#define A53_PLAT_PGC			0x900
+#define PLAT_PGC_PCR			0x900
+#define NOC_PGC_PCR			0xa40
+#define PGC_SCU_TIMING			0x910
+
+#define MASK_DSM_TRIGGER_A53		BIT(31)
+#define IRQ_SRC_A53_WUP			BIT(30)
+#define IRQ_SRC_A53_WUP_SHIFT		30
+#define IRQ_SRC_C1			BIT(29)
+#define IRQ_SRC_C0			BIT(28)
+#define IRQ_SRC_C3			BIT(23)
+#define IRQ_SRC_C2			BIT(22)
+#define CPU_CLOCK_ON_LPM		BIT(14)
+#define A53_CLK_ON_LPM			BIT(14)
+#define MASTER0_LPM_HSK			BIT(6)
+#define MASTER1_LPM_HSK			BIT(7)
+#define MASTER2_LPM_HSK			BIT(8)
+
+#define L2PGE				BIT(31)
+#define EN_L2_WFI_PDN			BIT(5)
+#define EN_PLAT_PDN			BIT(4)
+
+#define SLPCR_EN_DSM			BIT(31)
+#define SLPCR_RBC_EN			BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE	BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE	BIT(16)
+#define SLPCR_VSTBY			BIT(2)
+#define SLPCR_SBYOS			BIT(1)
+#define SLPCR_BYPASS_PMIC_READY		BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT		24
+#define SLPCR_STBY_COUNT_SHFT		3
+
+#define A53_DUMMY_PDN_ACK		BIT(15)
+#define A53_DUMMY_PUP_ACK		BIT(31)
+#define A53_PLAT_PDN_ACK		BIT(2)
+#define A53_PLAT_PUP_ACK		BIT(18)
+#define NOC_PDN_SLT_CTRL		BIT(10)
+#define NOC_PUP_SLT_CTRL		BIT(11)
+#define NOC_PGC_PDN_ACK			BIT(3)
+#define NOC_PGC_PUP_ACK			BIT(19)
+
+#define PLAT_PUP_SLT_CTRL		BIT(9)
+#define PLAT_PDN_SLT_CTRL		BIT(8)
+
+#define SLT_PLAT_PDN			BIT(8)
+#define SLT_PLAT_PUP			BIT(9)
+
+#define MASTER1_MAPPING			BIT(1)
+#define MASTER2_MAPPING			BIT(2)
+
+#define TMR_TCD2_SHIFT			0
+#define TMC_TMR_SHIFT			10
+#define TRC1_TMC_SHIFT			20
+
+#define MIPI_PWR_REQ			BIT(0)
+#define OTG1_PWR_REQ			BIT(2)
+#define HSIOMIX_PWR_REQ			BIT(4)
+#define DDRMIX_PWR_REQ			BIT(5)
+#define GPUMIX_PWR_REQ			BIT(7)
+#define DISPMIX_PWR_REQ			BIT(10)
+
+#define DDRMIX_ADB400_SYNC		BIT(2)
+#define HSIOMIX_ADB400_SYNC		BIT(5)
+#define DISPMIX_ADB400_SYNC		BIT(7)
+#define GPUMIX_ADB400_SYNC		(0x5 << 9)
+#define DDRMIX_ADB400_ACK		BIT(20)
+#define HSIOMIX_ADB400_ACK		BIT(23)
+#define DISPMIX_ADB400_ACK		BIT(25)
+#define GPUMIX_ADB400_ACK		(0x5 << 27)
+
+#define MIPI_PGC			0xc00
+#define OTG1_PGC			0xc80
+#define HSIOMIX_PGC			0xd00
+#define DDRMIX_PGC			0xd40
+#define GPUMIX_PGC			0xdc0
+#define DISPMIX_PGC			0xe80
+
+#endif /* GPC_REG_H */
diff --git a/plat/imx/imx8m/imx8mp/gpc.c b/plat/imx/imx8m/imx8mp/gpc.c
new file mode 100644
index 0000000..d660e3d
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/gpc.c
@@ -0,0 +1,379 @@
+/*
+ * Copyright 2019-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <lib/smccc.h>
+#include <services/std_svc.h>
+
+#include <gpc.h>
+#include <imx_aipstz.h>
+#include <imx_sip_svc.h>
+#include <platform_def.h>
+
+#define CCGR(x)		(0x4000 + (x) * 0x10)
+#define IMR_NUM		U(5)
+
+struct imx_noc_setting {
+	uint32_t domain_id;
+	uint32_t start;
+	uint32_t end;
+	uint32_t prioriy;
+	uint32_t mode;
+	uint32_t socket_qos_en;
+};
+
+enum clk_type {
+	CCM_ROOT_SLICE,
+	CCM_CCGR,
+};
+
+struct clk_setting {
+	uint32_t offset;
+	uint32_t val;
+	enum clk_type type;
+};
+
+enum pu_domain_id {
+	/* hsio ss */
+	HSIOMIX,
+	PCIE_PHY,
+	USB1_PHY,
+	USB2_PHY,
+	MLMIX,
+	AUDIOMIX,
+	/* gpu ss */
+	GPUMIX,
+	GPU2D,
+	GPU3D,
+	/* vpu ss */
+	VPUMIX,
+	VPU_G1,
+	VPU_G2,
+	VPU_H1,
+	/* media ss */
+	MEDIAMIX,
+	MEDIAMIX_ISPDWP,
+	MIPI_PHY1,
+	MIPI_PHY2,
+	/* HDMI ss */
+	HDMIMIX,
+	HDMI_PHY,
+	DDRMIX,
+};
+
+/* PU domain, add some hole to minimize the uboot change */
+static struct imx_pwr_domain pu_domains[20] = {
+	[MIPI_PHY1] = IMX_PD_DOMAIN(MIPI_PHY1, false),
+	[PCIE_PHY] = IMX_PD_DOMAIN(PCIE_PHY, false),
+	[USB1_PHY] = IMX_PD_DOMAIN(USB1_PHY, true),
+	[USB2_PHY] = IMX_PD_DOMAIN(USB2_PHY, true),
+	[MLMIX] = IMX_MIX_DOMAIN(MLMIX, false),
+	[AUDIOMIX] = IMX_MIX_DOMAIN(AUDIOMIX, false),
+	[GPU2D] = IMX_PD_DOMAIN(GPU2D, false),
+	[GPUMIX] = IMX_MIX_DOMAIN(GPUMIX, false),
+	[VPUMIX] = IMX_MIX_DOMAIN(VPUMIX, false),
+	[GPU3D] = IMX_PD_DOMAIN(GPU3D, false),
+	[MEDIAMIX] = IMX_MIX_DOMAIN(MEDIAMIX, false),
+	[VPU_G1] = IMX_PD_DOMAIN(VPU_G1, false),
+	[VPU_G2] = IMX_PD_DOMAIN(VPU_G2, false),
+	[VPU_H1] = IMX_PD_DOMAIN(VPU_H1, false),
+	[HDMIMIX] = IMX_MIX_DOMAIN(HDMIMIX, false),
+	[HDMI_PHY] = IMX_PD_DOMAIN(HDMI_PHY, false),
+	[MIPI_PHY2] = IMX_PD_DOMAIN(MIPI_PHY2, false),
+	[HSIOMIX] = IMX_MIX_DOMAIN(HSIOMIX, false),
+	[MEDIAMIX_ISPDWP] = IMX_PD_DOMAIN(MEDIAMIX_ISPDWP, false),
+};
+
+static struct imx_noc_setting noc_setting[] = {
+	{MLMIX, 0x180, 0x180, 0x80000303, 0x0, 0x0},
+	{AUDIOMIX, 0x200, 0x200, 0x80000303, 0x0, 0x0},
+	{AUDIOMIX, 0x280, 0x480, 0x80000404, 0x0, 0x0},
+	{GPUMIX, 0x500, 0x580, 0x80000303, 0x0, 0x0},
+	{HDMIMIX, 0x600, 0x680, 0x80000202, 0x0, 0x1},
+	{HDMIMIX, 0x700, 0x700, 0x80000505, 0x0, 0x0},
+	{HSIOMIX, 0x780, 0x900, 0x80000303, 0x0, 0x0},
+	{MEDIAMIX, 0x980, 0xb80, 0x80000202, 0x0, 0x1},
+	{MEDIAMIX_ISPDWP, 0xc00, 0xd00, 0x80000505, 0x0, 0x0},
+	{VPU_G1, 0xd80, 0xd80, 0x80000303, 0x0, 0x0},
+	{VPU_G2, 0xe00, 0xe00, 0x80000303, 0x0, 0x0},
+	{VPU_H1, 0xe80, 0xe80, 0x80000303, 0x0, 0x0}
+};
+
+static struct clk_setting hsiomix_clk[] = {
+	{ 0x8380, 0x0, CCM_ROOT_SLICE },
+	{ 0x44d0, 0x0, CCM_CCGR },
+	{ 0x45c0, 0x0, CCM_CCGR },
+};
+
+static struct aipstz_cfg aipstz5[] = {
+	{IMX_AIPSTZ5, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{0},
+};
+
+static unsigned int pu_domain_status;
+
+static void imx_noc_qos(unsigned int domain_id)
+{
+	unsigned int i;
+	uint32_t hurry;
+
+	if (domain_id == HDMIMIX) {
+		mmio_write_32(IMX_HDMI_CTL_BASE + TX_CONTROL1, 0x22018);
+		mmio_write_32(IMX_HDMI_CTL_BASE + TX_CONTROL1, 0x22010);
+
+		/* set GPR to make lcdif read hurry level 0x7 */
+		hurry = mmio_read_32(IMX_HDMI_CTL_BASE + TX_CONTROL0);
+		hurry |= 0x00077000;
+		mmio_write_32(IMX_HDMI_CTL_BASE + TX_CONTROL0, hurry);
+	}
+
+	if (domain_id == MEDIAMIX) {
+		/* handle mediamix special */
+		mmio_write_32(IMX_MEDIAMIX_CTL_BASE + RSTn_CSR, 0x1FFFFFF);
+		mmio_write_32(IMX_MEDIAMIX_CTL_BASE + CLK_EN_CSR, 0x1FFFFFF);
+		mmio_write_32(IMX_MEDIAMIX_CTL_BASE + RST_DIV, 0x40030000);
+
+		/* set GPR to make lcdif read hurry level 0x7 */
+		hurry = mmio_read_32(IMX_MEDIAMIX_CTL_BASE + LCDIF_ARCACHE_CTRL);
+		hurry |= 0xfc00;
+		mmio_write_32(IMX_MEDIAMIX_CTL_BASE + LCDIF_ARCACHE_CTRL, hurry);
+		/* set GPR to make isi write hurry level 0x7 */
+		hurry = mmio_read_32(IMX_MEDIAMIX_CTL_BASE + ISI_CACHE_CTRL);
+		hurry |= 0x1ff00000;
+		mmio_write_32(IMX_MEDIAMIX_CTL_BASE + ISI_CACHE_CTRL, hurry);
+	}
+
+	/* set MIX NoC */
+	for (i = 0; i < ARRAY_SIZE(noc_setting); i++) {
+		if (noc_setting[i].domain_id == domain_id) {
+			udelay(50);
+			uint32_t offset = noc_setting[i].start;
+
+			while (offset <= noc_setting[i].end) {
+				mmio_write_32(IMX_NOC_BASE + offset + 0x8, noc_setting[i].prioriy);
+				mmio_write_32(IMX_NOC_BASE + offset + 0xc, noc_setting[i].mode);
+				mmio_write_32(IMX_NOC_BASE + offset + 0x18, noc_setting[i].socket_qos_en);
+				offset += 0x80;
+			}
+		}
+	}
+}
+
+static void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on)
+{
+	struct imx_pwr_domain *pwr_domain = &pu_domains[domain_id];
+	unsigned int i;
+
+	if (domain_id == HSIOMIX) {
+		for (i = 0; i < ARRAY_SIZE(hsiomix_clk); i++) {
+			hsiomix_clk[i].val = mmio_read_32(IMX_CCM_BASE + hsiomix_clk[i].offset);
+			mmio_setbits_32(IMX_CCM_BASE + hsiomix_clk[i].offset,
+					hsiomix_clk[i].type == CCM_ROOT_SLICE ? BIT(28) : 0x3);
+		}
+	}
+
+	if (on) {
+		if (pwr_domain->need_sync) {
+			pu_domain_status |= (1 << domain_id);
+		}
+
+		if (domain_id == HDMIMIX) {
+			/* assert the reset */
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_RESET_CTL0, 0x0);
+			/* enable all th function clock */
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL0, 0xFFFFFFFF);
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL1, 0x7ffff87e);
+		}
+
+		/* clear the PGC bit */
+		mmio_clrbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+		/* power up the domain */
+		mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, pwr_domain->pwr_req);
+
+		/* wait for power request done */
+		while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & pwr_domain->pwr_req)
+			;
+
+		if (domain_id == HDMIMIX) {
+			/* wait for memory repair done for HDMIMIX */
+			while (!(mmio_read_32(IMX_SRC_BASE + 0x94) & BIT(8)))
+				;
+			/* disable all the function clock */
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL0, 0x0);
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL1, 0x0);
+			/* deassert the reset */
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_RESET_CTL0, 0xffffffff);
+			/* enable all the clock again */
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL0, 0xFFFFFFFF);
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL1, 0x7ffff87e);
+		}
+
+		if (domain_id == HSIOMIX) {
+			/* enable HSIOMIX clock */
+			mmio_write_32(IMX_HSIOMIX_CTL_BASE, 0x2);
+		}
+
+		/* handle the ADB400 sync */
+		if (pwr_domain->need_sync) {
+			/* clear adb power down request */
+			mmio_setbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+			/* wait for adb power request ack */
+			while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack))
+				;
+		}
+
+		imx_noc_qos(domain_id);
+
+		/* AIPS5 config is lost when audiomix is off, so need to re-init it */
+		if (domain_id == AUDIOMIX) {
+			imx_aipstz_init(aipstz5);
+		}
+	} else {
+		if (pwr_domain->always_on) {
+			return;
+		}
+
+		if (pwr_domain->need_sync) {
+			pu_domain_status &= ~(1 << domain_id);
+		}
+
+		/* handle the ADB400 sync */
+		if (pwr_domain->need_sync) {
+			/* set adb power down request */
+			mmio_clrbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+			/* wait for adb power request ack */
+			while ((mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack))
+				;
+		}
+
+		/* set the PGC bit */
+		mmio_setbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+		/*
+		 * leave the G1, G2, H1 power domain on until VPUMIX power off,
+		 * otherwise system will hang due to VPUMIX ACK
+		 */
+		if (domain_id == VPU_H1 || domain_id == VPU_G1 || domain_id == VPU_G2) {
+			return;
+		}
+
+		if (domain_id == VPUMIX) {
+			mmio_write_32(IMX_GPC_BASE + PU_PGC_DN_TRG, VPU_G1_PWR_REQ |
+				 VPU_G2_PWR_REQ | VPU_H1_PWR_REQ);
+
+			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & (VPU_G1_PWR_REQ |
+					VPU_G2_PWR_REQ | VPU_H1_PWR_REQ))
+				;
+		}
+
+		/* power down the domain */
+		mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, pwr_domain->pwr_req);
+
+		/* wait for power request done */
+		while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & pwr_domain->pwr_req)
+			;
+
+		if (domain_id == HDMIMIX) {
+			/* disable all the clocks of HDMIMIX */
+			mmio_write_32(IMX_HDMI_CTL_BASE + 0x40, 0x0);
+			mmio_write_32(IMX_HDMI_CTL_BASE + 0x50, 0x0);
+		}
+	}
+
+	if (domain_id == HSIOMIX) {
+		for (i = 0; i < ARRAY_SIZE(hsiomix_clk); i++) {
+			mmio_write_32(IMX_CCM_BASE + hsiomix_clk[i].offset, hsiomix_clk[i].val);
+		}
+	}
+}
+
+void imx_gpc_init(void)
+{
+	uint32_t val;
+	unsigned int i;
+
+	/* mask all the wakeup irq by default */
+	for (i = 0; i < IMR_NUM; i++) {
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0);
+	}
+
+	val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
+	/* use GIC wake_request to wakeup C0~C3 from LPM */
+	val |= CORE_WKUP_FROM_GIC;
+	/* clear the MASTER0 LPM handshake */
+	val &= ~MASTER0_LPM_HSK;
+	mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
+
+	/* clear MASTER1 & MASTER2 mapping in CPU0(A53) */
+	mmio_clrbits_32(IMX_GPC_BASE + MST_CPU_MAPPING, (MASTER1_MAPPING |
+		MASTER2_MAPPING));
+
+	/* set all mix/PU in A53 domain */
+	mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0x3fffff);
+
+	/*
+	 * Set the CORE & SCU power up timing:
+	 * SW = 0x1, SW2ISO = 0x1;
+	 * the CPU CORE and SCU power up timming counter
+	 * is drived  by 32K OSC, each domain's power up
+	 * latency is (SW + SW2ISO) / 32768
+	 */
+	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(0) + 0x4, 0x401);
+	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(1) + 0x4, 0x401);
+	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(2) + 0x4, 0x401);
+	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(3) + 0x4, 0x401);
+	mmio_write_32(IMX_GPC_BASE + PLAT_PGC_PCR + 0x4, 0x401);
+	mmio_write_32(IMX_GPC_BASE + PGC_SCU_TIMING,
+		      (0x59 << TMC_TMR_SHIFT) | 0x5B | (0x2 << TRC1_TMC_SHIFT));
+
+	/* set DUMMY PDN/PUP ACK by default for A53 domain */
+	mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53,
+		      A53_DUMMY_PUP_ACK | A53_DUMMY_PDN_ACK);
+
+	/* clear DSM by default */
+	val = mmio_read_32(IMX_GPC_BASE + SLPCR);
+	val &= ~SLPCR_EN_DSM;
+	/* enable the fast wakeup wait/stop mode */
+	val |= SLPCR_A53_FASTWUP_WAIT_MODE;
+	val |= SLPCR_A53_FASTWUP_STOP_MODE;
+	/* clear the RBC */
+	val &= ~(0x3f << SLPCR_RBC_COUNT_SHIFT);
+	/* set the STBY_COUNT to 0x5, (128 * 30)us */
+	val &= ~(0x7 << SLPCR_STBY_COUNT_SHFT);
+	val |= (0x5 << SLPCR_STBY_COUNT_SHFT);
+	mmio_write_32(IMX_GPC_BASE + SLPCR, val);
+
+	/*
+	 * USB PHY power up needs to make sure RESET bit in SRC is clear,
+	 * otherwise, the PU power up bit in GPC will NOT self-cleared.
+	 * only need to do it once.
+	 */
+	mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1);
+	mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG2PHY_SCR, 0x1);
+
+	/* enable all the power domain by default */
+	for (i = 0; i < 101; i++) {
+		mmio_write_32(IMX_CCM_BASE + CCGR(i), 0x3);
+	}
+
+	for (i = 0; i < 20; i++) {
+		imx_gpc_pm_domain_enable(i, true);
+	}
+}
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c b/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c
new file mode 100644
index 0000000..22fbd5e
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <context.h>
+#include <drivers/arm/tzc380.h>
+#include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <gpc.h>
+#include <imx_aipstz.h>
+#include <imx_uart.h>
+#include <imx_rdc.h>
+#include <imx8m_caam.h>
+#include <platform_def.h>
+#include <plat_imx8.h>
+
+static const mmap_region_t imx_mmap[] = {
+	GIC_MAP, AIPS_MAP, OCRAM_S_MAP, DDRC_MAP,
+	NOC_MAP, {0},
+};
+
+static const struct aipstz_cfg aipstz[] = {
+	{IMX_AIPSTZ1, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{IMX_AIPSTZ2, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{IMX_AIPSTZ3, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{IMX_AIPSTZ4, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{0},
+};
+
+static const struct imx_rdc_cfg rdc[] = {
+	/* Master domain assignment */
+	RDC_MDAn(0x1, DID1),
+
+	/* peripherals domain permission */
+
+	/* memory region */
+
+	/* Sentinel */
+	{0},
+};
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/* get SPSR for BL33 entry */
+static uint32_t get_spsr_for_bl33_entry(void)
+{
+	unsigned long el_status;
+	unsigned long mode;
+	uint32_t spsr;
+
+	/* figure out what mode we enter the non-secure world */
+	el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+	el_status &= ID_AA64PFR0_ELX_MASK;
+
+	mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+	spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+	return spsr;
+}
+
+static void bl31_tzc380_setup(void)
+{
+	unsigned int val;
+
+	val = mmio_read_32(IMX_IOMUX_GPR_BASE + 0x28);
+	if ((val & GPR_TZASC_EN) != GPR_TZASC_EN)
+		return;
+
+	tzc380_init(IMX_TZASC_BASE);
+
+	/*
+	 * Need to substact offset 0x40000000 from CPU address when
+	 * programming tzasc region for i.mx8mp.
+	 */
+
+	/* Enable 1G-5G S/NS RW */
+	tzc380_configure_region(0, 0x00000000, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_4G) |
+		TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_ALL);
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+		u_register_t arg2, u_register_t arg3)
+{
+	static console_t console;
+	unsigned int i;
+
+	/* Enable CSU NS access permission */
+	for (i = 0; i < 64; i++) {
+		mmio_write_32(IMX_CSU_BASE + i * 4, 0x00ff00ff);
+	}
+
+	imx_aipstz_init(aipstz);
+
+	imx_rdc_init(rdc);
+
+	imx8m_caam_init();
+
+	console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
+		IMX_CONSOLE_BAUDRATE, &console);
+	/* This console is only used for boot stage */
+	console_set_scope(&console, CONSOLE_FLAG_BOOT);
+
+	/*
+	 * tell BL3-1 where the non-secure software image is located
+	 * and the entry state information.
+	 */
+	bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET;
+	bl33_image_ep_info.spsr = get_spsr_for_bl33_entry();
+	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+#ifdef SPD_opteed
+	/* Populate entry point information for BL32 */
+	SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
+	SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+	bl32_image_ep_info.pc = BL32_BASE;
+	bl32_image_ep_info.spsr = 0;
+
+	/* Pass TEE base and size to bl33 */
+	bl33_image_ep_info.args.arg1 = BL32_BASE;
+	bl33_image_ep_info.args.arg2 = BL32_SIZE;
+#endif
+
+	bl31_tzc380_setup();
+}
+
+void bl31_plat_arch_setup(void)
+{
+	mmap_add_region(BL31_BASE, BL31_BASE, (BL31_LIMIT - BL31_BASE),
+		MT_MEMORY | MT_RW | MT_SECURE);
+	mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, (BL_CODE_END - BL_CODE_BASE),
+		MT_MEMORY | MT_RO | MT_SECURE);
+#if USE_COHERENT_MEM
+	mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE,
+		(BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE),
+		MT_DEVICE | MT_RW | MT_SECURE);
+#endif
+	mmap_add(imx_mmap);
+
+	init_xlat_tables();
+
+	enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+	generic_delay_timer_init();
+
+	/* select the CKIL source to 32K OSC */
+	mmio_write_32(IMX_ANAMIX_BASE + ANAMIX_MISC_CTL, 0x1);
+
+	plat_gic_driver_init();
+	plat_gic_init();
+
+	imx_gpc_init();
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type)
+{
+	if (type == NON_SECURE) {
+		return &bl33_image_ep_info;
+	}
+
+	if (type == SECURE) {
+		return &bl32_image_ep_info;
+	}
+
+	return NULL;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return COUNTER_FREQUENCY;
+}
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_psci.c b/plat/imx/imx8m/imx8mp/imx8mp_psci.c
new file mode 100644
index 0000000..bc7b246
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/imx8mp_psci.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <gpc.h>
+#include <imx8m_psci.h>
+#include <plat_imx8.h>
+
+static const plat_psci_ops_t imx_plat_psci_ops = {
+	.pwr_domain_on = imx_pwr_domain_on,
+	.pwr_domain_on_finish = imx_pwr_domain_on_finish,
+	.pwr_domain_off = imx_pwr_domain_off,
+	.validate_ns_entrypoint = imx_validate_ns_entrypoint,
+	.validate_power_state = imx_validate_power_state,
+	.cpu_standby = imx_cpu_standby,
+	.pwr_domain_suspend = imx_domain_suspend,
+	.pwr_domain_suspend_finish = imx_domain_suspend_finish,
+	.pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi,
+	.get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
+	.system_reset = imx_system_reset,
+	.system_off = imx_system_off,
+};
+
+/* export the platform specific psci ops */
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	/* sec_entrypoint is used for warm reset */
+	imx_mailbox_init(sec_entrypoint);
+
+	*psci_ops = &imx_plat_psci_ops;
+
+	return 0;
+}
diff --git a/plat/imx/imx8m/imx8mp/include/gpc_reg.h b/plat/imx/imx8m/imx8mp/include/gpc_reg.h
new file mode 100644
index 0000000..12da6ac
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/include/gpc_reg.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPC_REG_H
+#define GPC_REG_H
+
+#define LPCR_A53_BSC			0x0
+#define LPCR_A53_BSC2			0x180
+#define LPCR_A53_AD			0x4
+#define LPCR_M4				0x8
+#define SLPCR				0x14
+#define MST_CPU_MAPPING			0x18
+#define MLPCR				0x20
+#define PGC_ACK_SEL_A53			0x24
+#define IMR1_CORE0_A53			0x30
+#define IMR1_CORE1_A53			0x44
+#define IMR1_CORE2_A53			0x194
+#define IMR1_CORE3_A53			0x1A8
+#define IMR1_CORE0_M4			0x58
+
+#define SLT0_CFG			0x200
+#define GPC_PU_PWRHSK			0x190
+#define PGC_CPU_0_1_MAPPING		0x1CC
+#define CPU_PGC_UP_TRG			0xD0
+#define PU_PGC_UP_TRG			0xD8
+#define CPU_PGC_DN_TRG			0xDC
+#define PU_PGC_DN_TRG			0xE4
+#define LPS_CPU1			0xEC
+
+#define A53_CORE0_PGC			0x800
+#define A53_PLAT_PGC			0x900
+#define PLAT_PGC_PCR			0x900
+#define NOC_PGC_PCR			0xa40
+#define PGC_SCU_TIMING			0x910
+
+#define MASK_DSM_TRIGGER_A53		BIT(31)
+#define IRQ_SRC_A53_WUP			BIT(30)
+#define IRQ_SRC_A53_WUP_SHIFT		30
+#define IRQ_SRC_C1			BIT(29)
+#define IRQ_SRC_C0			BIT(28)
+#define IRQ_SRC_C3			BIT(23)
+#define IRQ_SRC_C2			BIT(22)
+#define CPU_CLOCK_ON_LPM		BIT(14)
+#define A53_CLK_ON_LPM			BIT(14)
+#define MASTER0_LPM_HSK			BIT(6)
+#define MASTER1_LPM_HSK			BIT(7)
+#define MASTER2_LPM_HSK			BIT(8)
+
+#define L2PGE				BIT(31)
+#define EN_L2_WFI_PDN			BIT(5)
+#define EN_PLAT_PDN			BIT(4)
+
+#define SLPCR_EN_DSM			BIT(31)
+#define SLPCR_RBC_EN			BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE	BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE	BIT(16)
+#define SLPCR_VSTBY			BIT(2)
+#define SLPCR_SBYOS			BIT(1)
+#define SLPCR_BYPASS_PMIC_READY		BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT		24
+#define SLPCR_STBY_COUNT_SHFT		3
+
+#define A53_DUMMY_PDN_ACK		BIT(30)
+#define A53_DUMMY_PUP_ACK		BIT(31)
+#define A53_PLAT_PDN_ACK		BIT(8)
+#define A53_PLAT_PUP_ACK		BIT(9)
+
+#define NOC_PDN_SLT_CTRL		BIT(12)
+#define NOC_PUP_SLT_CTRL		BIT(13)
+#define NOC_PGC_PDN_ACK			BIT(12)
+#define NOC_PGC_PUP_ACK			BIT(13)
+
+#define PLAT_PUP_SLT_CTRL		BIT(9)
+#define PLAT_PDN_SLT_CTRL		BIT(8)
+
+#define SLT_PLAT_PDN			BIT(8)
+#define SLT_PLAT_PUP			BIT(9)
+
+#define MASTER1_MAPPING			BIT(1)
+#define MASTER2_MAPPING			BIT(2)
+
+#define TMR_TCD2_SHIFT			0
+#define TMC_TMR_SHIFT			10
+#define TRC1_TMC_SHIFT			20
+
+#define MIPI_PHY1_PWR_REQ		BIT(0)
+#define PCIE_PHY_PWR_REQ		BIT(1)
+#define USB1_PHY_PWR_REQ		BIT(2)
+#define USB2_PHY_PWR_REQ		BIT(3)
+#define MLMIX_PWR_REQ			BIT(4)
+#define AUDIOMIX_PWR_REQ		BIT(5)
+#define GPU2D_PWR_REQ			BIT(6)
+#define GPUMIX_PWR_REQ			BIT(7)
+#define VPUMIX_PWR_REQ			BIT(8)
+#define GPU3D_PWR_REQ			BIT(9)
+#define MEDIAMIX_PWR_REQ		BIT(10)
+#define VPU_G1_PWR_REQ			BIT(11)
+#define VPU_G2_PWR_REQ			BIT(12)
+#define VPU_H1_PWR_REQ			BIT(13)
+#define HDMIMIX_PWR_REQ			BIT(14)
+#define HDMI_PHY_PWR_REQ		BIT(15)
+#define MIPI_PHY2_PWR_REQ		BIT(16)
+#define HSIOMIX_PWR_REQ			BIT(17)
+#define MEDIAMIX_ISPDWP_PWR_REQ		BIT(18)
+#define DDRMIX_PWR_REQ			BIT(19)
+
+#define AUDIOMIX_ADB400_SYNC		(BIT(4) | BIT(15))
+#define MLMIX_ADB400_SYNC		(BIT(7) | BIT(8))
+#define GPUMIX_ADB400_SYNC		BIT(9)
+#define VPUMIX_ADB400_SYNC		BIT(10)
+#define DDRMIX_ADB400_SYNC		BIT(11)
+#define HSIOMIX_ADB400_SYNC		BIT(12)
+#define HDMIMIX_ADB400_SYNC		BIT(13)
+#define MEDIAMIX_ADB400_SYNC		BIT(14)
+
+#define AUDIOMIX_ADB400_ACK		(BIT(20) | BIT(31))
+#define MLMIX_ADB400_ACK		(BIT(23) | BIT(24))
+#define GPUMIX_ADB400_ACK		BIT(25)
+#define VPUMIX_ADB400_ACK		BIT(26)
+#define DDRMIX_ADB400_ACK		BIT(27)
+#define HSIOMIX_ADB400_ACK		BIT(28)
+#define HDMIMIX_ADB400_ACK		BIT(29)
+#define MEDIAMIX_ADB400_ACK		BIT(30)
+
+#define MIPI_PHY1_PGC			0xb00
+#define PCIE_PHY_PGC			0xb40
+#define USB1_PHY_PGC			0xb80
+#define USB2_PHY_PGC			0xbc0
+#define MLMIX_PGC			0xc00
+#define AUDIOMIX_PGC			0xc40
+#define GPU2D_PGC			0xc80
+#define GPUMIX_PGC			0xcc0
+#define VPUMIX_PGC			0xd00
+#define GPU3D_PGC			0xd40
+#define MEDIAMIX_PGC			0xd80
+#define VPU_G1_PGC			0xdc0
+#define VPU_G2_PGC			0xe00
+#define VPU_H1_PGC			0xe40
+#define HDMIMIX_PGC			0xe80
+#define HDMI_PHY_PGC			0xec0
+#define MIPI_PHY2_PGC			0xf00
+#define HSIOMIX_PGC			0xf40
+#define MEDIAMIX_ISPDWP_PGC		0xf80
+#define DDRMIX_PGC			0xfc0
+
+#endif /* GPC_REG_H */
diff --git a/plat/imx/imx8m/imx8mp/include/platform_def.h b/plat/imx/imx8m/imx8mp/include/platform_def.h
new file mode 100644
index 0000000..644adc7
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/include/platform_def.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#define PLATFORM_LINKER_FORMAT		"elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH		aarch64
+
+#define PLATFORM_STACK_SIZE		0xB00
+#define CACHE_WRITEBACK_GRANULE		64
+
+#define PLAT_PRIMARY_CPU		U(0x0)
+#define PLATFORM_MAX_CPU_PER_CLUSTER	U(4)
+#define PLATFORM_CLUSTER_COUNT		U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT	U(4)
+#define PLATFORM_CLUSTER1_CORE_COUNT	U(0)
+#define PLATFORM_CORE_COUNT		(PLATFORM_CLUSTER0_CORE_COUNT)
+
+#define IMX_PWR_LVL0			MPIDR_AFFLVL0
+#define IMX_PWR_LVL1			MPIDR_AFFLVL1
+#define IMX_PWR_LVL2			MPIDR_AFFLVL2
+
+#define PWR_DOMAIN_AT_MAX_LVL		U(1)
+#define PLAT_MAX_PWR_LVL		U(2)
+#define PLAT_MAX_OFF_STATE		U(4)
+#define PLAT_MAX_RET_STATE		U(2)
+
+#define PLAT_WAIT_RET_STATE		U(1)
+#define PLAT_STOP_OFF_STATE		U(3)
+
+#define BL31_BASE			U(0x960000)
+#define BL31_LIMIT			U(0x980000)
+
+/* non-secure uboot base */
+#define PLAT_NS_IMAGE_OFFSET		U(0x40200000)
+
+/* GICv3 base address */
+#define PLAT_GICD_BASE			U(0x38800000)
+#define PLAT_GICR_BASE			U(0x38880000)
+
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(ULL(1) << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE	(ULL(1) << 32)
+
+#define MAX_XLAT_TABLES			8
+#define MAX_MMAP_REGIONS		16
+
+#define HAB_RVT_BASE			U(0x00000900) /* HAB_RVT for i.MX8MM */
+
+#define IMX_BOOT_UART_CLK_IN_HZ		24000000 /* Select 24MHz oscillator */
+#define PLAT_CRASH_UART_BASE		IMX_BOOT_UART_BASE
+#define PLAT_CRASH_UART_CLK_IN_HZ	24000000
+#define IMX_CONSOLE_BAUDRATE		115200
+
+#define IMX_AIPSTZ1			U(0x301f0000)
+#define IMX_AIPSTZ2			U(0x305f0000)
+#define IMX_AIPSTZ3			U(0x309f0000)
+#define IMX_AIPSTZ4			U(0x32df0000)
+#define IMX_AIPSTZ5			U(0x30df0000)
+
+#define IMX_AIPS_BASE			U(0x30000000)
+#define IMX_AIPS_SIZE			U(0x3000000)
+#define IMX_GPV_BASE			U(0x32000000)
+#define IMX_GPV_SIZE			U(0x800000)
+#define IMX_AIPS1_BASE			U(0x30200000)
+#define IMX_AIPS4_BASE			U(0x32c00000)
+#define IMX_ANAMIX_BASE			U(0x30360000)
+#define IMX_CCM_BASE			U(0x30380000)
+#define IMX_SRC_BASE			U(0x30390000)
+#define IMX_GPC_BASE			U(0x303a0000)
+#define IMX_RDC_BASE			U(0x303d0000)
+#define IMX_CSU_BASE			U(0x303e0000)
+#define IMX_WDOG_BASE			U(0x30280000)
+#define IMX_SNVS_BASE			U(0x30370000)
+#define IMX_NOC_BASE			U(0x32700000)
+#define IMX_NOC_SIZE			U(0x100000)
+#define IMX_TZASC_BASE			U(0x32F80000)
+#define IMX_IOMUX_GPR_BASE		U(0x30340000)
+#define IMX_CAAM_BASE			U(0x30900000)
+#define IMX_DDRC_BASE			U(0x3d400000)
+#define IMX_DDRPHY_BASE			U(0x3c000000)
+#define IMX_DDR_IPS_BASE		U(0x3d000000)
+#define IMX_DDR_IPS_SIZE		U(0x1800000)
+#define IMX_ROM_BASE			U(0x0)
+
+#define IMX_GIC_BASE			PLAT_GICD_BASE
+#define IMX_GIC_SIZE			U(0x200000)
+
+#define IMX_HSIOMIX_CTL_BASE		U(0x32f10000)
+#define IMX_HDMI_CTL_BASE		U(0x32fc0000)
+#define RTX_RESET_CTL0			U(0x20)
+#define RTX_CLK_CTL0			U(0x40)
+#define RTX_CLK_CTL1			U(0x50)
+#define TX_CONTROL0			U(0x200)
+#define TX_CONTROL1			U(0x220)
+
+#define IMX_MEDIAMIX_CTL_BASE		U(0x32ec0000)
+#define RSTn_CSR			U(0x0)
+#define CLK_EN_CSR			U(0x4)
+#define RST_DIV				U(0x8)
+#define LCDIF_ARCACHE_CTRL		U(0x4c)
+#define ISI_CACHE_CTRL			U(0x50)
+
+#define WDOG_WSR			U(0x2)
+#define WDOG_WCR_WDZST			BIT(0)
+#define WDOG_WCR_WDBG			BIT(1)
+#define WDOG_WCR_WDE			BIT(2)
+#define WDOG_WCR_WDT			BIT(3)
+#define WDOG_WCR_SRS			BIT(4)
+#define WDOG_WCR_WDA			BIT(5)
+#define WDOG_WCR_SRE			BIT(6)
+#define WDOG_WCR_WDW			BIT(7)
+
+#define SRC_A53RCR0			U(0x4)
+#define SRC_A53RCR1			U(0x8)
+#define SRC_OTG1PHY_SCR			U(0x20)
+#define SRC_OTG2PHY_SCR			U(0x24)
+#define SRC_GPR1_OFFSET			U(0x74)
+
+#define SNVS_LPCR			U(0x38)
+#define SNVS_LPCR_SRTC_ENV		BIT(0)
+#define SNVS_LPCR_DP_EN			BIT(5)
+#define SNVS_LPCR_TOP			BIT(6)
+
+#define IOMUXC_GPR10			U(0x28)
+#define GPR_TZASC_EN			BIT(0)
+#define GPR_TZASC_EN_LOCK		BIT(16)
+
+#define ANAMIX_MISC_CTL			U(0x124)
+#define DRAM_PLL_CTRL			(IMX_ANAMIX_BASE + 0x50)
+
+#define MAX_CSU_NUM			U(64)
+
+#define OCRAM_S_BASE			U(0x00180000)
+#define OCRAM_S_SIZE			U(0x8000)
+#define OCRAM_S_LIMIT			(OCRAM_S_BASE + OCRAM_S_SIZE)
+#define SAVED_DRAM_TIMING_BASE		OCRAM_S_BASE
+
+#define COUNTER_FREQUENCY		8000000 /* 8MHz */
+
+#define IMX_WDOG_B_RESET
+
+#define GIC_MAP		MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW)
+#define AIPS_MAP	MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW) /* AIPS map */
+#define OCRAM_S_MAP	MAP_REGION_FLAT(OCRAM_S_BASE, OCRAM_S_SIZE, MT_MEMORY | MT_RW) /* OCRAM_S */
+#define DDRC_MAP	MAP_REGION_FLAT(IMX_DDRPHY_BASE, IMX_DDR_IPS_SIZE, MT_DEVICE | MT_RW) /* DDRMIX */
+#define NOC_MAP		MAP_REGION_FLAT(IMX_NOC_BASE, IMX_NOC_SIZE, MT_DEVICE | MT_RW) /* NOC QoS */
+
+#endif /* platform_def.h */
diff --git a/plat/imx/imx8m/imx8mp/platform.mk b/plat/imx/imx8m/imx8mp/platform.mk
new file mode 100644
index 0000000..1d11e3d
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/platform.mk
@@ -0,0 +1,56 @@
+#
+# Copyright 2019-2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES		:=	-Iplat/imx/common/include		\
+				-Iplat/imx/imx8m/include		\
+				-Iplat/imx/imx8m/imx8mp/include
+# Translation tables library
+include lib/xlat_tables_v2/xlat_tables.mk
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+IMX_GIC_SOURCES		:=	${GICV3_SOURCES}			\
+				plat/common/plat_gicv3.c		\
+				plat/common/plat_psci_common.c		\
+				plat/imx/common/plat_imx8_gic.c
+
+BL31_SOURCES		+=	plat/imx/common/imx8_helpers.S			\
+				plat/imx/imx8m/gpc_common.c			\
+				plat/imx/imx8m/imx_aipstz.c			\
+				plat/imx/imx8m/imx_rdc.c			\
+				plat/imx/imx8m/imx8m_caam.c			\
+				plat/imx/imx8m/imx8m_psci_common.c		\
+				plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c	\
+				plat/imx/imx8m/imx8mp/imx8mp_psci.c		\
+				plat/imx/imx8m/imx8mp/gpc.c			\
+				plat/imx/common/imx8_topology.c			\
+				plat/imx/common/imx_sip_handler.c		\
+				plat/imx/common/imx_sip_svc.c			\
+				plat/imx/common/imx_uart_console.S		\
+				lib/cpus/aarch64/cortex_a53.S			\
+				drivers/arm/tzc/tzc380.c			\
+				drivers/delay_timer/delay_timer.c		\
+				drivers/delay_timer/generic_delay_timer.c	\
+				${IMX_GIC_SOURCES}				\
+				${XLAT_TABLES_LIB_SRCS}
+
+USE_COHERENT_MEM	:=	1
+RESET_TO_BL31		:=	1
+A53_DISABLE_NON_TEMPORAL_HINT := 0
+
+ERRATA_A53_835769	:=	1
+ERRATA_A53_843419	:=	1
+ERRATA_A53_855873	:=	1
+
+BL32_BASE		?=	0x56000000
+$(eval $(call add_define,BL32_BASE))
+
+BL32_SIZE		?=	0x2000000
+$(eval $(call add_define,BL32_SIZE))
+
+IMX_BOOT_UART_BASE	?=	0x30890000
+$(eval $(call add_define,IMX_BOOT_UART_BASE))
diff --git a/plat/imx/imx8m/imx8mq/include/gpc_reg.h b/plat/imx/imx8m/imx8mq/include/gpc_reg.h
new file mode 100644
index 0000000..9f472d6
--- /dev/null
+++ b/plat/imx/imx8m/imx8mq/include/gpc_reg.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPC_REG_H
+#define GPC_REG_H
+
+#define LPCR_A53_BSC			0x0
+#define LPCR_A53_BSC2			0x108
+#define LPCR_A53_AD			0x4
+#define LPCR_M4				0x8
+#define SLPCR				0x14
+#define MST_CPU_MAPPING			0x18
+#define MLPCR				0x20
+#define PGC_ACK_SEL_A53			0x24
+#define IMR1_CORE0_A53			0x30
+#define IMR1_CORE1_A53			0x40
+#define IMR1_CORE2_A53			0x1C0
+#define IMR1_CORE3_A53			0x1D0
+#define IMR1_CORE0_M4			0x50
+#define SLT0_CFG			0xB0
+#define GPC_PU_PWRHSK			0x1FC
+#define PGC_CPU_0_1_MAPPING		0xEC
+#define CPU_PGC_UP_TRG			0xF0
+#define PU_PGC_UP_TRG			0xF8
+#define CPU_PGC_DN_TRG			0xFC
+#define PU_PGC_DN_TRG			0x104
+#define LPS_CPU1			0x114
+#define A53_CORE0_PGC			0x800
+#define A53_PLAT_PGC			0x900
+#define PLAT_PGC_PCR			0x900
+#define NOC_PGC_PCR			0xa40
+#define PGC_SCU_TIMING			0x910
+
+#define MASK_DSM_TRIGGER_A53		BIT(31)
+#define IRQ_SRC_A53_WUP			BIT(30)
+#define IRQ_SRC_A53_WUP_SHIFT		30
+#define IRQ_SRC_C1			BIT(29)
+#define IRQ_SRC_C0			BIT(28)
+#define IRQ_SRC_C3			BIT(23)
+#define IRQ_SRC_C2			BIT(22)
+#define CPU_CLOCK_ON_LPM		BIT(14)
+#define A53_CLK_ON_LPM			BIT(14)
+#define MASTER0_LPM_HSK			BIT(6)
+#define MASTER1_LPM_HSK			BIT(7)
+#define MASTER2_LPM_HSK			BIT(8)
+
+#define L2PGE				BIT(31)
+#define EN_L2_WFI_PDN			BIT(5)
+#define EN_PLAT_PDN			BIT(4)
+
+#define SLPCR_EN_DSM			BIT(31)
+#define SLPCR_RBC_EN			BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE	BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE	BIT(16)
+#define SLPCR_VSTBY			BIT(2)
+#define SLPCR_SBYOS			BIT(1)
+#define SLPCR_BYPASS_PMIC_READY		BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT		24
+#define SLPCR_STBY_COUNT_SHFT		3
+
+#define A53_DUMMY_PDN_ACK		BIT(15)
+#define A53_DUMMY_PUP_ACK		BIT(31)
+#define A53_PLAT_PDN_ACK		BIT(2)
+#define A53_PLAT_PUP_ACK		BIT(18)
+#define NOC_PDN_SLT_CTRL		BIT(10)
+#define NOC_PUP_SLT_CTRL		BIT(11)
+#define NOC_PGC_PDN_ACK			BIT(3)
+#define NOC_PGC_PUP_ACK			BIT(19)
+
+#define DDRMIX_PWR_REQ			BIT(5)
+#define DDRMIX_ADB400_SYNC		BIT(1)
+#define DDRMIX_ADB400_ACK		BIT(18)
+#define DDRMIX_PGC			0xd40
+
+#define PLAT_PUP_SLT_CTRL		BIT(9)
+#define PLAT_PDN_SLT_CTRL		BIT(8)
+
+#define SLT_PLAT_PDN			BIT(8)
+#define SLT_PLAT_PUP			BIT(9)
+
+#define MASTER1_MAPPING			BIT(1)
+#define MASTER2_MAPPING			BIT(2)
+
+#endif /* GPC_REG_H */
diff --git a/plat/imx/imx8m/include/gpc.h b/plat/imx/imx8m/include/gpc.h
index 6033b0d..89a0b9d 100644
--- a/plat/imx/imx8m/include/gpc.h
+++ b/plat/imx/imx8m/include/gpc.h
@@ -7,74 +7,7 @@
 #ifndef IMX8M_GPC_H
 #define IMX8M_GPC_H
 
-#define LPCR_A53_BSC			0x0
-#define LPCR_A53_BSC2			0x108
-#define LPCR_A53_AD			0x4
-#define LPCR_M4				0x8
-#define SLPCR				0x14
-#define MST_CPU_MAPPING			0x18
-#define MLPCR				0x20
-#define PGC_ACK_SEL_A53			0x24
-#define IMR1_CORE0_A53			0x30
-#define IMR1_CORE1_A53			0x40
-#define IMR1_CORE2_A53			0x1C0
-#define IMR1_CORE3_A53			0x1D0
-#define IMR1_CORE0_M4			0x50
-#define SLT0_CFG			0xB0
-#define GPC_PU_PWRHSK			0x1FC
-#define PGC_CPU_0_1_MAPPING		0xEC
-#define CPU_PGC_UP_TRG			0xF0
-#define PU_PGC_UP_TRG			0xF8
-#define CPU_PGC_DN_TRG			0xFC
-#define PU_PGC_DN_TRG			0x104
-#define A53_CORE0_PGC			0x800
-#define A53_PLAT_PGC			0x900
-#define PLAT_PGC_PCR			0x900
-#define PGC_SCU_TIMING			0x910
-
-#define MASK_DSM_TRIGGER_A53		BIT(31)
-#define IRQ_SRC_A53_WUP			BIT(30)
-#define IRQ_SRC_A53_WUP_SHIFT		30
-#define IRQ_SRC_C1			BIT(29)
-#define IRQ_SRC_C0			BIT(28)
-#define IRQ_SRC_C3			BIT(23)
-#define IRQ_SRC_C2			BIT(22)
-#define CORE_WKUP_FROM_GIC		(IRQ_SRC_C0 | IRQ_SRC_C1 | IRQ_SRC_C2 | IRQ_SRC_C3)
-#define CPU_CLOCK_ON_LPM		BIT(14)
-#define A53_CLK_ON_LPM			BIT(14)
-#define MASTER0_LPM_HSK			BIT(6)
-
-#define L2PGE				BIT(31)
-#define EN_L2_WFI_PDN			BIT(5)
-#define EN_PLAT_PDN			BIT(4)
-
-#define SLPCR_EN_DSM			BIT(31)
-#define SLPCR_RBC_EN			BIT(30)
-#define SLPCR_A53_FASTWUP_STOP_MODE	BIT(17)
-#define SLPCR_A53_FASTWUP_WAIT_MODE	BIT(16)
-#define SLPCR_VSTBY			BIT(2)
-#define SLPCR_SBYOS			BIT(1)
-#define SLPCR_BYPASS_PMIC_READY		BIT(0)
-#define SLPCR_RBC_COUNT_SHIFT		24
-#define SLPCR_STBY_COUNT_SHFT		3
-
-#define A53_DUMMY_PDN_ACK		BIT(15)
-#define A53_DUMMY_PUP_ACK		BIT(31)
-#define A53_PLAT_PDN_ACK		BIT(2)
-#define A53_PLAT_PUP_ACK		BIT(18)
-
-#define PLAT_PUP_SLT_CTRL		BIT(9)
-#define PLAT_PDN_SLT_CTRL		BIT(8)
-
-#define SLT_PLAT_PDN			BIT(8)
-#define SLT_PLAT_PUP			BIT(9)
-
-#define MASTER1_MAPPING			BIT(1)
-#define MASTER2_MAPPING			BIT(2)
-
-#define TMR_TCD2_SHIFT			0
-#define TMC_TMR_SHIFT			10
-#define TRC1_TMC_SHIFT			20
+#include <gpc_reg.h>
 
 /* helper macro */
 #define A53_LPM_MASK	U(0xF)
@@ -83,7 +16,7 @@
 #define LPM_MODE(local_state)		((local_state) == PLAT_WAIT_RET_STATE ? A53_LPM_WAIT : A53_LPM_STOP)
 
 #define DSM_MODE_MASK	BIT(31)
-
+#define CORE_WKUP_FROM_GIC		(IRQ_SRC_C0 | IRQ_SRC_C1 | IRQ_SRC_C2 | IRQ_SRC_C3)
 #define A53_CORE_WUP_SRC(core_id)	(1 << ((core_id) < 2 ? 28 + (core_id) : 22 + (core_id) - 2))
 #define COREx_PGC_PCR(core_id)		(0x800 + (core_id) * 0x40)
 #define COREx_WFI_PDN(core_id)		(1 << ((core_id) < 2 ? (core_id) * 2 : ((core_id) - 2) * 2 + 16))
@@ -95,6 +28,33 @@
 #define IRQ_IMR_NUM	4
 #define IMR_MASK_ALL	0xffffffff
 
+#define IMX_PD_DOMAIN(name, on)				\
+	{						\
+		.pwr_req = name##_PWR_REQ,		\
+		.pgc_offset = name##_PGC,		\
+		.need_sync = false,			\
+		.always_on = true,			\
+	}
+
+#define IMX_MIX_DOMAIN(name, on)			\
+	{						\
+		.pwr_req = name##_PWR_REQ,		\
+		.pgc_offset = name##_PGC,		\
+		.adb400_sync = name##_ADB400_SYNC,	\
+		.adb400_ack = name##_ADB400_ACK,	\
+		.need_sync = true,			\
+		.always_on = true,			\
+	}
+
+struct imx_pwr_domain {
+	uint32_t pwr_req;
+	uint32_t adb400_sync;
+	uint32_t adb400_ack;
+	uint32_t pgc_offset;
+	bool need_sync;
+	bool always_on;
+};
+
 /* function declare */
 void imx_gpc_init(void);
 void imx_set_cpu_secure_entry(unsigned int core_index, uintptr_t sec_entrypoint);
diff --git a/plat/marvell/armada/a3k/common/include/platform_def.h b/plat/marvell/armada/a3k/common/include/platform_def.h
index 7f8f79a..61c7dfe 100644
--- a/plat/marvell/armada/a3k/common/include/platform_def.h
+++ b/plat/marvell/armada/a3k/common/include/platform_def.h
@@ -83,9 +83,11 @@
 #define PLAT_MARVELL_TRUSTED_ROM_BASE		PLAT_MARVELL_ATF_LOAD_ADDR
 /* 4 MB for FIP image */
 #define PLAT_MARVELL_TRUSTED_ROM_SIZE		0x00400000
-/* Reserve 16M for SCP (Secure PayLoad) Trusted DRAM */
+/* Reserve 12M for SCP (Secure PayLoad) Trusted RAM
+ * OP-TEE SHMEM follows this region
+ */
 #define PLAT_MARVELL_TRUSTED_RAM_BASE		0x04400000
-#define PLAT_MARVELL_TRUSTED_RAM_SIZE		0x01000000	/* 16 MB */
+#define PLAT_MARVELL_TRUSTED_RAM_SIZE		0x00C00000	/* 12 MB DRAM */
 
 /*
  * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
diff --git a/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c
index 7d30ebe..a409261 100644
--- a/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c
+++ b/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c
@@ -103,7 +103,10 @@
 	{0x00000000f2000000,	0x4000000,	IO_0_TID}, /* IO window */
 #else
 #if LLC_SRAM
-	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, SRAM_TID},
+	/* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+	 * and changes the window target to SRAM_TID.
+	 */
+	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
 #endif
 	{0x00000000f2000000,	0xe000000,	IO_0_TID},
 	{0x00000000c0000000,	0x30000000,	IO_0_TID}, /* IO window */
diff --git a/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c
index 7fc33f1..3b68e91 100644
--- a/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c
+++ b/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c
@@ -94,7 +94,10 @@
 	{0x00000000f2000000,	0x4000000,	IO_0_TID}, /* IO window */
 #else
 #if LLC_SRAM
-	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, SRAM_TID},
+	/* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+	 * and changes the window target to SRAM_TID.
+	 */
+	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
 #endif
 	{0x00000000f2000000,	0xe000000,	IO_0_TID},
 	{0x00000000c0000000,    0x30000000,	IO_0_TID}, /* IO window */
diff --git a/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c
index 856c07a..4ccda14 100644
--- a/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c
+++ b/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c
@@ -132,7 +132,10 @@
 	{0x00000000f2000000,	0x4000000,  IO_0_TID}, /* IO window */
 #else
 #if LLC_SRAM
-	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, SRAM_TID},
+	/* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+	 * and changes the window target to SRAM_TID.
+	 */
+	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
 #endif
 	{0x00000000f2000000,	0xe000000,  IO_0_TID}, /* IO window */
 	{0x00000000c0000000,	0x30000000,  IO_0_TID}, /* IO window */
diff --git a/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c
index 0edc977..75a1b0c 100644
--- a/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c
+++ b/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c
@@ -78,12 +78,8 @@
 	/* CP1 (MCI0) internal regs */
 	{0x00000000f4000000,		0x2000000,  MCI_0_TID},
 #ifndef IMAGE_BLE
-	/* PCIe0 and SPI1_CS0 (RUNIT) on CP1*/
-	{0x00000000f9000000,		0x2000000,  MCI_0_TID},
-	/* PCIe1 on CP1*/
-	{0x00000000fb000000,		0x1000000,  MCI_0_TID},
-	/* PCIe2 on CP1*/
-	{0x00000000fc000000,		0x1000000,  MCI_0_TID},
+	/* PCIe0-2 and SPI1_CS0 (RUNIT) on CP1*/
+	{0x00000000f9000000,		0x4000000,  MCI_0_TID},
 	/* MCI 0 indirect window */
 	{MVEBU_MCI_REG_BASE_REMAP(0),	0x100000,   MCI_0_TID},
 	/* MCI 1 indirect window */
@@ -166,7 +162,10 @@
 	{0x00000000f2000000,	0x4000000,  IO_0_TID}, /* IO window */
 #else
 #if LLC_SRAM
-	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, SRAM_TID},
+	/* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+	 * and changes the window target to SRAM_TID.
+	 */
+	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
 #endif
 	{0x00000000f2000000,	0xe000000,  IO_0_TID}, /* IO window */
 	{0x00000000c0000000,	0x30000000,  IO_0_TID}, /* IO window */
diff --git a/plat/marvell/armada/a8k/common/a8k_common.mk b/plat/marvell/armada/a8k/common/a8k_common.mk
index dcbf9a6..0446b8d 100644
--- a/plat/marvell/armada/a8k/common/a8k_common.mk
+++ b/plat/marvell/armada/a8k/common/a8k_common.mk
@@ -85,7 +85,8 @@
 				$(MARVELL_DRV_BASE)/ccu.c	\
 				$(MARVELL_DRV_BASE)/cache_llc.c	\
 				$(MARVELL_DRV_BASE)/comphy/phy-comphy-cp110.c \
-				$(MARVELL_DRV_BASE)/mc_trustzone/mc_trustzone.c
+				$(MARVELL_DRV_BASE)/mc_trustzone/mc_trustzone.c \
+				$(MARVELL_DRV_BASE)/mg_conf_cm3/mg_conf_cm3.c
 
 BL31_PORTING_SOURCES	:=	$(BOARD_DIR)/board/marvell_plat_config.c
 
diff --git a/plat/marvell/armada/a8k/common/include/platform_def.h b/plat/marvell/armada/a8k/common/include/platform_def.h
index b26e3ea..944a151 100644
--- a/plat/marvell/armada/a8k/common/include/platform_def.h
+++ b/plat/marvell/armada/a8k/common/include/platform_def.h
@@ -96,11 +96,13 @@
 #define PLAT_MARVELL_TRUSTED_ROM_BASE		PLAT_MARVELL_ATF_LOAD_ADDR
 /* 4 MB for FIP image */
 #define PLAT_MARVELL_TRUSTED_ROM_SIZE		0x00400000
-/* Reserve 16M for SCP (Secure PayLoad) Trusted RAM */
+/* Reserve 12MB for SCP (Secure PayLoad) Trusted RAM
+ * OP-TEE 4MB SHMEM follows this region
+ */
 #define PLAT_MARVELL_TRUSTED_RAM_BASE		0x04400000
-#define PLAT_MARVELL_TRUSTED_RAM_SIZE		0x01000000	/* 16 MB DRAM */
+#define PLAT_MARVELL_TRUSTED_RAM_SIZE		0x00C00000	/* 12 MB DRAM */
 
-#define PLAT_MARVELL_LLC_SRAM_BASE		PLAT_MARVELL_TRUSTED_RAM_BASE
+#define PLAT_MARVELL_LLC_SRAM_BASE		0x05400000
 #define PLAT_MARVELL_LLC_SRAM_SIZE		0x00100000	/* 1 MB SRAM */
 
 /*
diff --git a/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c b/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c
index 6a8e11c..8d909dc 100644
--- a/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c
+++ b/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c
@@ -100,6 +100,45 @@
 
 	    .next_handoff_image_id = BL33_IMAGE_ID,
     },
+
+	/*
+	 * Fill BL32 external 1 related information.
+	 * A typical use for extra1 image is with OP-TEE
+	 * where it is the pager image.
+	 */
+	{
+	    .image_id = BL32_EXTRA1_IMAGE_ID,
+
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+	    VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+	    .image_info.image_base = BL32_BASE,
+	    .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+	    .next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+
+	/*
+	 * Fill BL32 external 2 related information.
+	 * A typical use for extra2 image is with OP-TEE,
+	 * where it is the paged image.
+	 */
+	{
+	    .image_id = BL32_EXTRA2_IMAGE_ID,
+
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+		    VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+#ifdef SPD_opteed
+	    .image_info.image_base = MARVELL_OPTEE_PAGEABLE_LOAD_BASE,
+	    .image_info.image_max_size = MARVELL_OPTEE_PAGEABLE_LOAD_SIZE,
+#endif
+	    .next_handoff_image_id = INVALID_IMAGE_ID,
+	},
 # endif /* BL32_BASE */
 
 	/* Fill BL33 related information */
diff --git a/plat/marvell/armada/common/marvell_bl2_setup.c b/plat/marvell/armada/common/marvell_bl2_setup.c
index 3c1c391..3dfa82e 100644
--- a/plat/marvell/armada/common/marvell_bl2_setup.c
+++ b/plat/marvell/armada/common/marvell_bl2_setup.c
@@ -17,6 +17,9 @@
 #include <drivers/console.h>
 #include <lib/utils.h>
 
+#ifdef SPD_opteed
+#include <optee_utils.h>
+#endif
 #include <marvell_def.h>
 #include <plat_marvell.h>
 
@@ -97,9 +100,29 @@
 	int err = 0;
 	bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
 
+#ifdef SPD_opteed
+	bl_mem_params_node_t *pager_mem_params = NULL;
+	bl_mem_params_node_t *paged_mem_params = NULL;
+#endif /* SPD_opteed */
 	assert(bl_mem_params);
 
 	switch (image_id) {
+	case BL32_IMAGE_ID:
+#ifdef SPD_opteed
+		pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+		assert(pager_mem_params);
+
+		paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+		assert(paged_mem_params);
+
+		err = parse_optee_header(&bl_mem_params->ep_info,
+					 &pager_mem_params->image_info,
+					 &paged_mem_params->image_info);
+		if (err != 0)
+			WARN("OPTEE header parse error.\n");
+#endif /* SPD_opteed */
+		bl_mem_params->ep_info.spsr = marvell_get_spsr_for_bl32_entry();
+		break;
 
 	case BL33_IMAGE_ID:
 		/* BL33 expects to receive the primary CPU MPID (through r0) */
diff --git a/plat/marvell/armada/common/marvell_common.mk b/plat/marvell/armada/common/marvell_common.mk
index fcc97ac..2e96e2f 100644
--- a/plat/marvell/armada/common/marvell_common.mk
+++ b/plat/marvell/armada/common/marvell_common.mk
@@ -22,15 +22,7 @@
 $(eval $(call add_define,LLC_SRAM))
 
 # Enable/Disable LLC
-ifeq (${LLC_SRAM}, 0)
 LLC_ENABLE			:= 1
-else
-# When LLC_SRAM=1, the entire LLC converted to SRAM and enabled at BL1.
-# All existing cases activating LLC at BL31 stage should be disabled.
-# The below assignment does not allow changing the LLC_ENABLE
-# value in the command line.
-LLC_ENABLE			= 0
-endif
 $(eval $(call add_define,LLC_ENABLE))
 
 include lib/xlat_tables_v2/xlat_tables.mk
@@ -66,6 +58,10 @@
 				$(MARVELL_PLAT_BASE)/common/aarch64/marvell_bl2_mem_params_desc.c	\
 				$(MARVELL_PLAT_BASE)/common/marvell_image_load.c
 
+ifeq (${SPD},opteed)
+PLAT_INCLUDES		+=	-Iinclude/lib
+BL2_SOURCES		+=	lib/optee/optee_utils.c
+endif
 
 BL31_SOURCES		+=	$(MARVELL_PLAT_BASE)/common/marvell_bl31_setup.c	\
 				$(MARVELL_PLAT_BASE)/common/marvell_pm.c		\
@@ -77,6 +73,15 @@
 # PSCI functionality
 $(eval $(call add_define,CONFIG_ARM64))
 
+# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
+# in the FIP if the platform requires.
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2))
+endif
+
 # MSS (SCP) build
 ifeq (${MSS_SUPPORT}, 1)
 include $(MARVELL_PLAT_BASE)/common/mss/mss_common.mk
diff --git a/plat/marvell/armada/common/marvell_io_storage.c b/plat/marvell/armada/common/marvell_io_storage.c
index 065f956..2627ba4 100644
--- a/plat/marvell/armada/common/marvell_io_storage.c
+++ b/plat/marvell/armada/common/marvell_io_storage.c
@@ -43,6 +43,15 @@
 static const io_uuid_spec_t bl32_uuid_spec = {
 	.uuid = UUID_SECURE_PAYLOAD_BL32,
 };
+
+static const io_uuid_spec_t bl32_extra1_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
+};
+
+static const io_uuid_spec_t bl32_extra2_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
+};
+
 static const io_uuid_spec_t bl33_uuid_spec = {
 	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
 };
@@ -83,6 +92,16 @@
 		(uintptr_t)&bl32_uuid_spec,
 		open_fip
 	},
+	[BL32_EXTRA1_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_extra1_uuid_spec,
+		open_fip
+	},
+	[BL32_EXTRA2_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_extra2_uuid_spec,
+		open_fip
+	},
 	[BL33_IMAGE_ID] = {
 		&fip_dev_handle,
 		(uintptr_t)&bl33_uuid_spec,
diff --git a/plat/marvell/armada/common/mss/mss_scp_bl2_format.h b/plat/marvell/armada/common/mss/mss_scp_bl2_format.h
index 7150f0a..74dddc6 100644
--- a/plat/marvell/armada/common/mss/mss_scp_bl2_format.h
+++ b/plat/marvell/armada/common/mss/mss_scp_bl2_format.h
@@ -13,7 +13,6 @@
 #define HEADER_VERSION	0x1
 
 #define MSS_IDRAM_SIZE	0x10000 /* 64KB */
-#define MG_SRAM_SIZE	0x20000 /* 128KB */
 
 /* Types definitions */
 typedef struct file_header {
diff --git a/plat/marvell/armada/common/mss/mss_scp_bootloader.c b/plat/marvell/armada/common/mss/mss_scp_bootloader.c
index 4473d81..adf570e 100644
--- a/plat/marvell/armada/common/mss/mss_scp_bootloader.c
+++ b/plat/marvell/armada/common/mss/mss_scp_bootloader.c
@@ -12,6 +12,7 @@
 #include <arch_helpers.h>
 #include <common/debug.h>
 #include <drivers/delay_timer.h>
+#include <mg_conf_cm3/mg_conf_cm3.h>
 #include <lib/mmio.h>
 
 #include <plat_pm_trace.h>
@@ -42,8 +43,6 @@
 
 #define MSS_HANDSHAKE_TIMEOUT		50
 
-#define MG_CM3_SRAM_BASE(CP)		(MVEBU_CP_REGS_BASE(CP) + 0x100000)
-
 static int mss_check_image_ready(volatile struct mss_pm_ctrl_block *mss_pm_crtl)
 {
 	int timeout = MSS_HANDSHAKE_TIMEOUT;
@@ -61,28 +60,6 @@
 	return 0;
 }
 
-static int mg_image_load(uintptr_t src_addr, uint32_t size, uintptr_t mg_regs)
-{
-	if (size > MG_SRAM_SIZE) {
-		ERROR("image is too big to fit into MG CM3 memory\n");
-		return 1;
-	}
-
-	NOTICE("Loading MG image from address 0x%lx Size 0x%x to MG at 0x%lx\n",
-	       src_addr, size, mg_regs);
-
-	/* Copy image to MG CM3 SRAM */
-	memcpy((void *)mg_regs, (void *)src_addr, size);
-
-	/*
-	 * Don't release MG CM3 from reset - it will be done by next step
-	 * bootloader (e.g. U-Boot), when appriopriate device-tree setup (which
-	 * has enabeld 802.3. auto-neg) will be choosen.
-	 */
-
-	return 0;
-}
-
 static int mss_image_load(uint32_t src_addr, uint32_t size, uintptr_t mss_regs)
 {
 	uint32_t i, loop_num, timeout;
@@ -258,8 +235,7 @@
 			break;
 		}
 		NOTICE("Load image to CP%d MG\n", cp_index);
-		ret = mg_image_load(single_img, image_size,
-				    MG_CM3_SRAM_BASE(cp_index));
+		ret = mg_image_load(single_img, image_size, cp_index);
 		if (ret != 0) {
 			ERROR("SCP Image load failed\n");
 			return -1;
diff --git a/plat/nvidia/tegra/common/tegra_common.mk b/plat/nvidia/tegra/common/tegra_common.mk
index 82dd606..f412a80 100644
--- a/plat/nvidia/tegra/common/tegra_common.mk
+++ b/plat/nvidia/tegra/common/tegra_common.mk
@@ -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.
 # Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
@@ -20,9 +20,10 @@
 				plat/common/plat_gicv3.c			\
 				${COMMON_DIR}/tegra_gicv3.c
 
-TEGRA_GICv2_SOURCES	:=	drivers/arm/gic/common/gic_common.c		\
-				drivers/arm/gic/v2/gicv2_main.c			\
-				drivers/arm/gic/v2/gicv2_helpers.c		\
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+TEGRA_GICv2_SOURCES	:=	${GICV2_SOURCES}				\
 				plat/common/plat_gicv2.c			\
 				${COMMON_DIR}/tegra_gicv2.c
 
diff --git a/plat/rpi/rpi4/rpi4_bl31_setup.c b/plat/rpi/rpi4/rpi4_bl31_setup.c
index 0a49d81..cfacd1f 100644
--- a/plat/rpi/rpi4/rpi4_bl31_setup.c
+++ b/plat/rpi/rpi4/rpi4_bl31_setup.c
@@ -17,6 +17,7 @@
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #include <plat/common/platform.h>
 #include <common/fdt_fixup.h>
+#include <common/fdt_wrappers.h>
 #include <libfdt.h>
 
 #include <drivers/arm/gicv2.h>
@@ -200,13 +201,6 @@
 	enable_mmu_el3(0);
 }
 
-static uint32_t dtb_size(const void *dtb)
-{
-	const uint32_t *dtb_header = dtb;
-
-	return fdt32_to_cpu(dtb_header[1]);
-}
-
 static void rpi4_prepare_dtb(void)
 {
 	void *dtb = (void *)rpi4_get_dtb_address();
@@ -250,7 +244,7 @@
 	if (ret < 0)
 		ERROR("Failed to pack Device Tree at %p: error %d\n", dtb, ret);
 
-	clean_dcache_range((uintptr_t)dtb, dtb_size(dtb));
+	clean_dcache_range((uintptr_t)dtb, fdt_blob_size(dtb));
 	INFO("Changed device tree to advertise PSCI.\n");
 }
 
diff --git a/plat/socionext/uniphier/uniphier_bl2_setup.c b/plat/socionext/uniphier/uniphier_bl2_setup.c
index 679f14d..4524610 100644
--- a/plat/socionext/uniphier/uniphier_bl2_setup.c
+++ b/plat/socionext/uniphier/uniphier_bl2_setup.c
@@ -21,8 +21,8 @@
 
 #include "uniphier.h"
 
-#define UNIPHIER_IMAGE_BUF_OFFSET	0x04300000UL
-#define UNIPHIER_IMAGE_BUF_SIZE		0x00100000UL
+#define UNIPHIER_IMAGE_BUF_OFFSET	0x03800000UL
+#define UNIPHIER_IMAGE_BUF_SIZE		0x00800000UL
 
 static uintptr_t uniphier_mem_base = UNIPHIER_MEM_BASE;
 static unsigned int uniphier_soc = UNIPHIER_SOC_UNKNOWN;
diff --git a/plat/socionext/uniphier/uniphier_image_desc.c b/plat/socionext/uniphier/uniphier_image_desc.c
index 8c232ba..dd62d1e 100644
--- a/plat/socionext/uniphier/uniphier_image_desc.c
+++ b/plat/socionext/uniphier/uniphier_image_desc.c
@@ -14,9 +14,9 @@
 #include "uniphier.h"
 
 #define UNIPHIER_BL33_OFFSET		0x04000000UL
-#define UNIPHIER_BL33_MAX_SIZE		0x00100000UL
+#define UNIPHIER_BL33_MAX_SIZE		0x00800000UL
 
-#define UNIPHIER_SCP_OFFSET		0x04100000UL
+#define UNIPHIER_SCP_OFFSET		0x04800000UL
 #define UNIPHIER_SCP_MAX_SIZE		0x00020000UL
 
 static struct bl_mem_params_node uniphier_image_descs[] = {
diff --git a/plat/socionext/uniphier/uniphier_io_storage.c b/plat/socionext/uniphier/uniphier_io_storage.c
index 77d1eaf..92e15b0 100644
--- a/plat/socionext/uniphier/uniphier_io_storage.c
+++ b/plat/socionext/uniphier/uniphier_io_storage.c
@@ -25,8 +25,8 @@
 
 #define UNIPHIER_OCM_REGION_SIZE	0x00040000ULL
 
-#define UNIPHIER_BLOCK_BUF_OFFSET	0x04200000UL
-#define UNIPHIER_BLOCK_BUF_SIZE		0x00100000UL
+#define UNIPHIER_BLOCK_BUF_OFFSET	0x03000000UL
+#define UNIPHIER_BLOCK_BUF_SIZE		0x00800000UL
 
 static const io_dev_connector_t *uniphier_fip_dev_con;
 static uintptr_t uniphier_fip_dev_handle;
diff --git a/plat/st/common/include/stm32mp_shared_resources.h b/plat/st/common/include/stm32mp_shared_resources.h
index b148666..13f4b13 100644
--- a/plat/st/common/include/stm32mp_shared_resources.h
+++ b/plat/st/common/include/stm32mp_shared_resources.h
@@ -8,6 +8,10 @@
 #define STM32MP_SHARED_RESOURCES_H
 
 #include <stdbool.h>
+#include <stdint.h>
+
+#ifdef STM32MP_SHARED_RESOURCES
+enum stm32mp_shres;
 
 /* Return true if @clock_id is shared by secure and non-secure worlds */
 bool stm32mp_nsec_can_access_clock(unsigned long clock_id);
@@ -15,7 +19,40 @@
 /* Return true if and only if @reset_id relates to a non-secure peripheral */
 bool stm32mp_nsec_can_access_reset(unsigned int reset_id);
 
+/* Register a shared resource assigned to the secure world */
+void stm32mp_register_secure_periph(enum stm32mp_shres id);
+
+/* Register a shared resource assigned to the non-secure world */
+void stm32mp_register_non_secure_periph(enum stm32mp_shres id);
+
+/* Register a peripheral as secure or non-secure based on IO base address */
+void stm32mp_register_secure_periph_iomem(uintptr_t base);
+void stm32mp_register_non_secure_periph_iomem(uintptr_t base);
+
+/* Register a GPIO as secure or non-secure based on its bank and pin numbers */
+void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin);
+void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin);
+
 /* Consolidate peripheral states and lock against new peripheral registering */
 void stm32mp_lock_periph_registering(void);
+#else
+static inline void stm32mp_register_secure_periph_iomem(uintptr_t base __unused)
+{
+}
 
+static inline
+void stm32mp_register_non_secure_periph_iomem(uintptr_t base __unused)
+{
+}
+
+static inline void stm32mp_register_secure_gpio(unsigned int bank __unused,
+						unsigned int pin __unused)
+{
+}
+
+static inline void stm32mp_register_non_secure_gpio(unsigned int bank __unused,
+						    unsigned int pin __unused)
+{
+}
+#endif /* STM32MP_SHARED_RESOURCES */
 #endif /* STM32MP_SHARED_RESOURCES_H */
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index ef82d5e..bce5994 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -494,14 +494,16 @@
 #define IWDG2_BASE			U(0x5A002000)
 
 /*******************************************************************************
- * STM32MP1 I2C4
+ * Miscellaneous STM32MP1 peripherals base address
  ******************************************************************************/
-#define I2C4_BASE			U(0x5C002000)
-
-/*******************************************************************************
- * STM32MP1 DBGMCU
- ******************************************************************************/
+#define CRYP1_BASE			U(0x54001000)
 #define DBGMCU_BASE			U(0x50081000)
+#define HASH1_BASE			U(0x54002000)
+#define I2C4_BASE			U(0x5C002000)
+#define I2C6_BASE			U(0x5c009000)
+#define RNG1_BASE			U(0x54003000)
+#define RTC_BASE			U(0x5c004000)
+#define SPI6_BASE			U(0x5c001000)
 
 /*******************************************************************************
  * Device Tree defines
diff --git a/plat/st/stm32mp1/stm32mp1_shared_resources.c b/plat/st/stm32mp1/stm32mp1_shared_resources.c
index 268aa52..208e34a 100644
--- a/plat/st/stm32mp1/stm32mp1_shared_resources.c
+++ b/plat/st/stm32mp1/stm32mp1_shared_resources.c
@@ -44,6 +44,49 @@
 /* Force uint8_t array for array of enum shres_state for size considerations */
 static uint8_t shres_state[STM32MP1_SHRES_COUNT];
 
+static const char *shres2str_id_tbl[STM32MP1_SHRES_COUNT] __unused = {
+	[STM32MP1_SHRES_GPIOZ(0)] = "GPIOZ0",
+	[STM32MP1_SHRES_GPIOZ(1)] = "GPIOZ1",
+	[STM32MP1_SHRES_GPIOZ(2)] = "GPIOZ2",
+	[STM32MP1_SHRES_GPIOZ(3)] = "GPIOZ3",
+	[STM32MP1_SHRES_GPIOZ(4)] = "GPIOZ4",
+	[STM32MP1_SHRES_GPIOZ(5)] = "GPIOZ5",
+	[STM32MP1_SHRES_GPIOZ(6)] = "GPIOZ6",
+	[STM32MP1_SHRES_GPIOZ(7)] = "GPIOZ7",
+	[STM32MP1_SHRES_IWDG1] = "IWDG1",
+	[STM32MP1_SHRES_USART1] = "USART1",
+	[STM32MP1_SHRES_SPI6] = "SPI6",
+	[STM32MP1_SHRES_I2C4] = "I2C4",
+	[STM32MP1_SHRES_RNG1] = "RNG1",
+	[STM32MP1_SHRES_HASH1] = "HASH1",
+	[STM32MP1_SHRES_CRYP1] = "CRYP1",
+	[STM32MP1_SHRES_I2C6] = "I2C6",
+	[STM32MP1_SHRES_RTC] = "RTC",
+	[STM32MP1_SHRES_MCU] = "MCU",
+	[STM32MP1_SHRES_MDMA] = "MDMA",
+	[STM32MP1_SHRES_PLL3] = "PLL3",
+};
+
+static const char __unused *shres2str_id(enum stm32mp_shres id)
+{
+	assert(id < ARRAY_SIZE(shres2str_id_tbl));
+
+	return shres2str_id_tbl[id];
+}
+
+static const char __unused *shres2str_state_tbl[] = {
+	[SHRES_UNREGISTERED] = "unregistered",
+	[SHRES_NON_SECURE] = "non-secure",
+	[SHRES_SECURE] = "secure",
+};
+
+static const char __unused *shres2str_state(unsigned int state)
+{
+	assert(state < ARRAY_SIZE(shres2str_state_tbl));
+
+	return shres2str_state_tbl[state];
+}
+
 /* Get resource state: these accesses lock the registering support */
 static void lock_registering(void)
 {
@@ -92,16 +135,344 @@
 	return get_gpio_nbpin(GPIO_BANK_Z);
 }
 
-/* Currently allow full access by non-secure to platform clock services */
-bool stm32mp_nsec_can_access_clock(unsigned long clock_id)
+static void register_periph(enum stm32mp_shres id, unsigned int state)
 {
-	return true;
+	assert((id < STM32MP1_SHRES_COUNT) &&
+	       ((state == SHRES_SECURE) || (state == SHRES_NON_SECURE)));
+
+	if (registering_locked) {
+		if (shres_state[id] == state) {
+			return;
+		}
+		panic();
+	}
+
+	if ((shres_state[id] != SHRES_UNREGISTERED) &&
+	    (shres_state[id] != state)) {
+		VERBOSE("Cannot change %s from %s to %s\n",
+			shres2str_id(id),
+			shres2str_state(shres_state[id]),
+			shres2str_state(state));
+		panic();
+	}
+
+	if (shres_state[id] == SHRES_UNREGISTERED) {
+		VERBOSE("Register %s as %s\n",
+			shres2str_id(id), shres2str_state(state));
+	}
+
+	if ((id >= STM32MP1_SHRES_GPIOZ(0)) &&
+	    (id <= STM32MP1_SHRES_GPIOZ(7)) &&
+	    ((id - STM32MP1_SHRES_GPIOZ(0)) >= get_gpioz_nbpin())) {
+		ERROR("Invalid GPIO pin %u, %u pin(s) available\n",
+		      id - STM32MP1_SHRES_GPIOZ(0), get_gpioz_nbpin());
+		panic();
+	}
+
+	shres_state[id] = (uint8_t)state;
+
+	/* Explore clock tree to lock dependencies */
+	if (state == SHRES_SECURE) {
+		enum stm32mp_shres clock_res_id;
+
+		switch (id) {
+		case STM32MP1_SHRES_GPIOZ(0):
+		case STM32MP1_SHRES_GPIOZ(1):
+		case STM32MP1_SHRES_GPIOZ(2):
+		case STM32MP1_SHRES_GPIOZ(3):
+		case STM32MP1_SHRES_GPIOZ(4):
+		case STM32MP1_SHRES_GPIOZ(5):
+		case STM32MP1_SHRES_GPIOZ(6):
+		case STM32MP1_SHRES_GPIOZ(7):
+			clock_res_id = GPIOZ;
+			break;
+		case STM32MP1_SHRES_IWDG1:
+			clock_res_id = IWDG1;
+			break;
+		case STM32MP1_SHRES_USART1:
+			clock_res_id = USART1_K;
+			break;
+		case STM32MP1_SHRES_SPI6:
+			clock_res_id = SPI6_K;
+			break;
+		case STM32MP1_SHRES_I2C4:
+			clock_res_id = I2C4_K;
+			break;
+		case STM32MP1_SHRES_RNG1:
+			clock_res_id = RNG1_K;
+			break;
+		case STM32MP1_SHRES_HASH1:
+			clock_res_id = HASH1;
+			break;
+		case STM32MP1_SHRES_CRYP1:
+			clock_res_id = CRYP1;
+			break;
+		case STM32MP1_SHRES_I2C6:
+			clock_res_id = I2C6_K;
+			break;
+		case STM32MP1_SHRES_RTC:
+			clock_res_id = RTC;
+			break;
+		default:
+			/* No clock resource dependency */
+			return;
+		}
+
+		stm32mp1_register_clock_parents_secure(clock_res_id);
+	}
 }
 
-/* Currently allow full access by non-secure to platform reset services */
+/* Register resource by ID */
+void stm32mp_register_secure_periph(enum stm32mp_shres id)
+{
+	register_periph(id, SHRES_SECURE);
+}
+
+void stm32mp_register_non_secure_periph(enum stm32mp_shres id)
+{
+	register_periph(id, SHRES_NON_SECURE);
+}
+
+static void register_periph_iomem(uintptr_t base, unsigned int state)
+{
+	enum stm32mp_shres id;
+
+	switch (base) {
+	case CRYP1_BASE:
+		id = STM32MP1_SHRES_CRYP1;
+		break;
+	case HASH1_BASE:
+		id = STM32MP1_SHRES_HASH1;
+		break;
+	case I2C4_BASE:
+		id = STM32MP1_SHRES_I2C4;
+		break;
+	case I2C6_BASE:
+		id = STM32MP1_SHRES_I2C6;
+		break;
+	case IWDG1_BASE:
+		id = STM32MP1_SHRES_IWDG1;
+		break;
+	case RNG1_BASE:
+		id = STM32MP1_SHRES_RNG1;
+		break;
+	case RTC_BASE:
+		id = STM32MP1_SHRES_RTC;
+		break;
+	case SPI6_BASE:
+		id = STM32MP1_SHRES_SPI6;
+		break;
+	case USART1_BASE:
+		id = STM32MP1_SHRES_USART1;
+		break;
+
+	case GPIOA_BASE:
+	case GPIOB_BASE:
+	case GPIOC_BASE:
+	case GPIOD_BASE:
+	case GPIOE_BASE:
+	case GPIOF_BASE:
+	case GPIOG_BASE:
+	case GPIOH_BASE:
+	case GPIOI_BASE:
+	case GPIOJ_BASE:
+	case GPIOK_BASE:
+	case USART2_BASE:
+	case USART3_BASE:
+	case UART4_BASE:
+	case UART5_BASE:
+	case USART6_BASE:
+	case UART7_BASE:
+	case UART8_BASE:
+	case IWDG2_BASE:
+		/* Allow drivers to register some non-secure resources */
+		VERBOSE("IO for non-secure resource 0x%x\n",
+			(unsigned int)base);
+		if (state != SHRES_NON_SECURE) {
+			panic();
+		}
+
+		return;
+
+	default:
+		panic();
+	}
+
+	register_periph(id, state);
+}
+
+void stm32mp_register_secure_periph_iomem(uintptr_t base)
+{
+	register_periph_iomem(base, SHRES_SECURE);
+}
+
+void stm32mp_register_non_secure_periph_iomem(uintptr_t base)
+{
+	register_periph_iomem(base, SHRES_NON_SECURE);
+}
+
+void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin)
+{
+	switch (bank) {
+	case GPIO_BANK_Z:
+		register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_SECURE);
+		break;
+	default:
+		ERROR("GPIO bank %u cannot be secured\n", bank);
+		panic();
+	}
+}
+
+void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin)
+{
+	switch (bank) {
+	case GPIO_BANK_Z:
+		register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_NON_SECURE);
+		break;
+	default:
+		break;
+	}
+}
+
+static bool stm32mp_gpio_bank_is_non_secure(unsigned int bank)
+{
+	unsigned int non_secure = 0U;
+	unsigned int i;
+
+	lock_registering();
+
+	if (bank != GPIO_BANK_Z) {
+		return true;
+	}
+
+	for (i = 0U; i < get_gpioz_nbpin(); i++) {
+		if (periph_is_non_secure(STM32MP1_SHRES_GPIOZ(i))) {
+			non_secure++;
+		}
+	}
+
+	return non_secure == get_gpioz_nbpin();
+}
+
+static bool stm32mp_gpio_bank_is_secure(unsigned int bank)
+{
+	unsigned int secure = 0U;
+	unsigned int i;
+
+	lock_registering();
+
+	if (bank != GPIO_BANK_Z) {
+		return false;
+	}
+
+	for (i = 0U; i < get_gpioz_nbpin(); i++) {
+		if (periph_is_secure(STM32MP1_SHRES_GPIOZ(i))) {
+			secure++;
+		}
+	}
+
+	return secure == get_gpioz_nbpin();
+}
+
+bool stm32mp_nsec_can_access_clock(unsigned long clock_id)
+{
+	enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT;
+
+	switch (clock_id) {
+	case CK_CSI:
+	case CK_HSE:
+	case CK_HSE_DIV2:
+	case CK_HSI:
+	case CK_LSE:
+	case CK_LSI:
+	case PLL1_P:
+	case PLL1_Q:
+	case PLL1_R:
+	case PLL2_P:
+	case PLL2_Q:
+	case PLL2_R:
+	case PLL3_P:
+	case PLL3_Q:
+	case PLL3_R:
+	case RTCAPB:
+		return true;
+	case GPIOZ:
+		/* Allow clock access if at least one pin is non-secure */
+		return !stm32mp_gpio_bank_is_secure(GPIO_BANK_Z);
+	case CRYP1:
+		shres_id = STM32MP1_SHRES_CRYP1;
+		break;
+	case HASH1:
+		shres_id = STM32MP1_SHRES_HASH1;
+		break;
+	case I2C4_K:
+		shres_id = STM32MP1_SHRES_I2C4;
+		break;
+	case I2C6_K:
+		shres_id = STM32MP1_SHRES_I2C6;
+		break;
+	case IWDG1:
+		shres_id = STM32MP1_SHRES_IWDG1;
+		break;
+	case RNG1_K:
+		shres_id = STM32MP1_SHRES_RNG1;
+		break;
+	case RTC:
+		shres_id = STM32MP1_SHRES_RTC;
+		break;
+	case SPI6_K:
+		shres_id = STM32MP1_SHRES_SPI6;
+		break;
+	case USART1_K:
+		shres_id = STM32MP1_SHRES_USART1;
+		break;
+	default:
+		return false;
+	}
+
+	return periph_is_non_secure(shres_id);
+}
+
 bool stm32mp_nsec_can_access_reset(unsigned int reset_id)
 {
-	return true;
+	enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT;
+
+	switch (reset_id) {
+	case CRYP1_R:
+		shres_id = STM32MP1_SHRES_CRYP1;
+		break;
+	case GPIOZ_R:
+		/* GPIOZ reset mandates all pins are non-secure */
+		return stm32mp_gpio_bank_is_non_secure(GPIO_BANK_Z);
+	case HASH1_R:
+		shres_id = STM32MP1_SHRES_HASH1;
+		break;
+	case I2C4_R:
+		shres_id = STM32MP1_SHRES_I2C4;
+		break;
+	case I2C6_R:
+		shres_id = STM32MP1_SHRES_I2C6;
+		break;
+	case MCU_R:
+		shres_id = STM32MP1_SHRES_MCU;
+		break;
+	case MDMA_R:
+		shres_id = STM32MP1_SHRES_MDMA;
+		break;
+	case RNG1_R:
+		shres_id = STM32MP1_SHRES_RNG1;
+		break;
+	case SPI6_R:
+		shres_id = STM32MP1_SHRES_SPI6;
+		break;
+	case USART1_R:
+		shres_id = STM32MP1_SHRES_USART1;
+		break;
+	default:
+		return false;
+	}
+
+	return periph_is_non_secure(shres_id);
 }
 
 static bool mckprot_protects_periph(enum stm32mp_shres id)
@@ -170,10 +541,10 @@
 		}
 
 		if (!secure || (mckprot_protects_periph(n) && (!mckprot))) {
-			ERROR("RCC %s MCKPROT %s and %u secure\n",
+			ERROR("RCC %s MCKPROT %s and %s secure\n",
 			      secure ? "secure" : "non-secure",
 			      mckprot ? "set" : "not set",
-			      n);
+			      shres2str_id(n));
 			error++;
 		}
 	}
@@ -201,14 +572,14 @@
 	for (id = 0U; id < STM32MP1_SHRES_COUNT; id++) {
 		switch (shres_state[id]) {
 		case SHRES_SECURE:
-			INFO("stm32mp1 %u is secure\n", id);
+			INFO("stm32mp1 %s is secure\n", shres2str_id(id));
 			break;
 		case SHRES_NON_SECURE:
 		case SHRES_UNREGISTERED:
-			VERBOSE("stm32mp %u is non-secure\n", id);
+			VERBOSE("stm32mp %s is non-secure\n", shres2str_id(id));
 			break;
 		default:
-			VERBOSE("stm32mp %u is invalid\n", id);
+			VERBOSE("stm32mp %s is invalid\n", shres2str_id(id));
 			panic();
 		}
 	}
diff --git a/tools/fiptool/fiptool.c b/tools/fiptool/fiptool.c
index 80b498e..8c5b04a 100644
--- a/tools/fiptool/fiptool.c
+++ b/tools/fiptool/fiptool.c
@@ -24,17 +24,17 @@
 #define OPT_ALIGN 2
 
 static int info_cmd(int argc, char *argv[]);
-static void info_usage(void);
+static void info_usage(int);
 static int create_cmd(int argc, char *argv[]);
-static void create_usage(void);
+static void create_usage(int);
 static int update_cmd(int argc, char *argv[]);
-static void update_usage(void);
+static void update_usage(int);
 static int unpack_cmd(int argc, char *argv[]);
-static void unpack_usage(void);
+static void unpack_usage(int);
 static int remove_cmd(int argc, char *argv[]);
-static void remove_usage(void);
+static void remove_usage(int);
 static int version_cmd(int argc, char *argv[]);
-static void version_usage(void);
+static void version_usage(int);
 static int help_cmd(int argc, char *argv[]);
 static void usage(void);
 
@@ -448,7 +448,7 @@
 	fip_toc_header_t toc_header;
 
 	if (argc != 2)
-		info_usage();
+		info_usage(EXIT_FAILURE);
 	argc--, argv++;
 
 	parse_fip(argv[0], &toc_header);
@@ -487,10 +487,10 @@
 	return 0;
 }
 
-static void info_usage(void)
+static void info_usage(int exit_status)
 {
 	printf("fiptool info FIP_FILENAME\n");
-	exit(1);
+	exit(exit_status);
 }
 
 static int pack_images(const char *filename, uint64_t toc_flags, unsigned long align)
@@ -669,7 +669,7 @@
 	unsigned long align = 1;
 
 	if (argc < 2)
-		create_usage();
+		create_usage(EXIT_FAILURE);
 
 	opts = fill_common_opts(opts, &nr_opts, required_argument);
 	opts = add_opt(opts, &nr_opts, "plat-toc-flags", required_argument,
@@ -710,7 +710,7 @@
 
 			if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0 ||
 			    filename[0] == '\0')
-				create_usage();
+				create_usage(EXIT_FAILURE);
 
 			desc = lookup_image_desc_from_uuid(&uuid);
 			if (desc == NULL) {
@@ -722,7 +722,7 @@
 			break;
 		}
 		default:
-			create_usage();
+			create_usage(EXIT_FAILURE);
 		}
 	}
 	argc -= optind;
@@ -730,7 +730,7 @@
 	free(opts);
 
 	if (argc == 0)
-		create_usage();
+		create_usage(EXIT_SUCCESS);
 
 	update_fip();
 
@@ -738,7 +738,7 @@
 	return 0;
 }
 
-static void create_usage(void)
+static void create_usage(int exit_status)
 {
 	toc_entry_t *toc_entry = toc_entries;
 
@@ -753,7 +753,7 @@
 	for (; toc_entry->cmdline_name != NULL; toc_entry++)
 		printf("  --%-16s FILENAME\t%s\n", toc_entry->cmdline_name,
 		    toc_entry->name);
-	exit(1);
+	exit(exit_status);
 }
 
 static int update_cmd(int argc, char *argv[])
@@ -767,7 +767,7 @@
 	int pflag = 0;
 
 	if (argc < 2)
-		update_usage();
+		update_usage(EXIT_FAILURE);
 
 	opts = fill_common_opts(opts, &nr_opts, required_argument);
 	opts = add_opt(opts, &nr_opts, "align", required_argument, OPT_ALIGN);
@@ -807,7 +807,7 @@
 
 			if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0 ||
 			    filename[0] == '\0')
-				update_usage();
+				update_usage(EXIT_FAILURE);
 
 			desc = lookup_image_desc_from_uuid(&uuid);
 			if (desc == NULL) {
@@ -825,7 +825,7 @@
 			snprintf(outfile, sizeof(outfile), "%s", optarg);
 			break;
 		default:
-			update_usage();
+			update_usage(EXIT_FAILURE);
 		}
 	}
 	argc -= optind;
@@ -833,7 +833,7 @@
 	free(opts);
 
 	if (argc == 0)
-		update_usage();
+		update_usage(EXIT_SUCCESS);
 
 	if (outfile[0] == '\0')
 		snprintf(outfile, sizeof(outfile), "%s", argv[0]);
@@ -851,7 +851,7 @@
 	return 0;
 }
 
-static void update_usage(void)
+static void update_usage(int exit_status)
 {
 	toc_entry_t *toc_entry = toc_entries;
 
@@ -867,7 +867,7 @@
 	for (; toc_entry->cmdline_name != NULL; toc_entry++)
 		printf("  --%-16s FILENAME\t%s\n", toc_entry->cmdline_name,
 		    toc_entry->name);
-	exit(1);
+	exit(exit_status);
 }
 
 static int unpack_cmd(int argc, char *argv[])
@@ -880,7 +880,7 @@
 	int unpack_all = 1;
 
 	if (argc < 2)
-		unpack_usage();
+		unpack_usage(EXIT_FAILURE);
 
 	opts = fill_common_opts(opts, &nr_opts, required_argument);
 	opts = add_opt(opts, &nr_opts, "blob", required_argument, 'b');
@@ -915,7 +915,7 @@
 
 			if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0 ||
 			    filename[0] == '\0')
-				unpack_usage();
+				unpack_usage(EXIT_FAILURE);
 
 			desc = lookup_image_desc_from_uuid(&uuid);
 			if (desc == NULL) {
@@ -934,7 +934,7 @@
 			snprintf(outdir, sizeof(outdir), "%s", optarg);
 			break;
 		default:
-			unpack_usage();
+			unpack_usage(EXIT_FAILURE);
 		}
 	}
 	argc -= optind;
@@ -942,7 +942,7 @@
 	free(opts);
 
 	if (argc == 0)
-		unpack_usage();
+		unpack_usage(EXIT_SUCCESS);
 
 	parse_fip(argv[0], NULL);
 
@@ -986,7 +986,7 @@
 	return 0;
 }
 
-static void unpack_usage(void)
+static void unpack_usage(int exit_status)
 {
 	toc_entry_t *toc_entry = toc_entries;
 
@@ -1003,7 +1003,7 @@
 		    toc_entry->name);
 	printf("\n");
 	printf("If no options are provided, all images will be unpacked.\n");
-	exit(1);
+	exit(exit_status);
 }
 
 static int remove_cmd(int argc, char *argv[])
@@ -1017,7 +1017,7 @@
 	int fflag = 0;
 
 	if (argc < 2)
-		remove_usage();
+		remove_usage(EXIT_FAILURE);
 
 	opts = fill_common_opts(opts, &nr_opts, no_argument);
 	opts = add_opt(opts, &nr_opts, "align", required_argument, OPT_ALIGN);
@@ -1053,7 +1053,7 @@
 			    filename, sizeof(filename));
 
 			if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0)
-				remove_usage();
+				remove_usage(EXIT_FAILURE);
 
 			desc = lookup_image_desc_from_uuid(&uuid);
 			if (desc == NULL) {
@@ -1071,7 +1071,7 @@
 			snprintf(outfile, sizeof(outfile), "%s", optarg);
 			break;
 		default:
-			remove_usage();
+			remove_usage(EXIT_FAILURE);
 		}
 	}
 	argc -= optind;
@@ -1079,7 +1079,7 @@
 	free(opts);
 
 	if (argc == 0)
-		remove_usage();
+		remove_usage(EXIT_SUCCESS);
 
 	if (outfile[0] != '\0' && access(outfile, F_OK) == 0 && !fflag)
 		log_errx("File %s already exists, use --force to overwrite it",
@@ -1110,7 +1110,7 @@
 	return 0;
 }
 
-static void remove_usage(void)
+static void remove_usage(int exit_status)
 {
 	toc_entry_t *toc_entry = toc_entries;
 
@@ -1126,7 +1126,7 @@
 	for (; toc_entry->cmdline_name != NULL; toc_entry++)
 		printf("  --%-16s\t%s\n", toc_entry->cmdline_name,
 		    toc_entry->name);
-	exit(1);
+	exit(exit_status);
 }
 
 static int version_cmd(int argc, char *argv[])
@@ -1140,10 +1140,10 @@
 	return 0;
 }
 
-static void version_usage(void)
+static void version_usage(int exit_status)
 {
 	printf("fiptool version\n");
-	exit(1);
+	exit(exit_status);
 }
 
 static int help_cmd(int argc, char *argv[])
@@ -1157,7 +1157,7 @@
 	for (i = 0; i < NELEM(cmds); i++) {
 		if (strcmp(cmds[i].name, argv[0]) == 0 &&
 		    cmds[i].usage != NULL)
-			cmds[i].usage();
+			cmds[i].usage(EXIT_SUCCESS);
 	}
 	if (i == NELEM(cmds))
 		printf("No help for subcommand '%s'\n", argv[0]);
@@ -1178,7 +1178,7 @@
 	printf("  remove\tRemove images from FIP.\n");
 	printf("  version\tShow fiptool version.\n");
 	printf("  help\t\tShow help for given command.\n");
-	exit(1);
+	exit(EXIT_SUCCESS);
 }
 
 int main(int argc, char *argv[])
diff --git a/tools/fiptool/fiptool.h b/tools/fiptool/fiptool.h
index af3fcbd..88c4a7e 100644
--- a/tools/fiptool/fiptool.h
+++ b/tools/fiptool/fiptool.h
@@ -48,7 +48,7 @@
 typedef struct cmd {
 	char              *name;
 	int              (*handler)(int, char **);
-	void             (*usage)(void);
+	void             (*usage)(int);
 } cmd_t;
 
 #endif /* FIPTOOL_H */
diff --git a/tools/marvell/doimage/doimage.c b/tools/marvell/doimage/doimage.c
index 82fd375..e08b820 100644
--- a/tools/marvell/doimage/doimage.c
+++ b/tools/marvell/doimage/doimage.c
@@ -51,7 +51,7 @@
 /* Number of address pairs in control array */
 #define CP_CTRL_EL_ARRAY_SZ	32
 
-#define VERSION_STRING		"Marvell(C) doimage utility version 3.2"
+#define VERSION_STRING		"Marvell(C) doimage utility version 3.3"
 
 /* A8K definitions */
 
@@ -303,7 +303,7 @@
 				MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
 
 	/* First compute the SHA256 hash for the input blob */
-	mbedtls_sha256(input, ilen, hash, 0);
+	mbedtls_sha256_ret(input, ilen, hash, 0);
 
 	/* Then calculate the hash signature */
 	rval = mbedtls_rsa_rsassa_pss_sign(mbedtls_pk_rsa(*pk_ctx),
@@ -354,6 +354,7 @@
 	mbedtls_pk_context		pk_ctx;
 	unsigned char			hash[32];
 	int				rval;
+	unsigned char			*pkey = (unsigned char *)pub_key;
 
 	/* Not sure this is required,
 	 * but it's safer to start with empty buffer
@@ -373,8 +374,7 @@
 	}
 
 	/* Check ability to read the public key */
-	rval = mbedtls_pk_parse_public_key(&pk_ctx, pub_key,
-					   MAX_RSA_DER_BYTE_LEN);
+	rval = mbedtls_pk_parse_subpubkey(&pkey, pub_key + klen, &pk_ctx);
 	if (rval != 0) {
 		fprintf(stderr, " Failed in pk_parse_public_key (%#x)!\n",
 			rval);
@@ -387,7 +387,7 @@
 				MBEDTLS_MD_SHA256);
 
 	/* Compute the SHA256 hash for the input buffer */
-	mbedtls_sha256(input, ilen, hash, 0);
+	mbedtls_sha256_ret(input, ilen, hash, 0);
 
 	rval = mbedtls_rsa_rsassa_pss_verify(mbedtls_pk_rsa(pk_ctx),
 					     mbedtls_ctr_drbg_random,
@@ -458,7 +458,7 @@
 	/* compute SHA-256 digest of the results
 	 * and use it as the init vector (IV)
 	 */
-	mbedtls_sha256(IV, AES_BLOCK_SZ, digest, 0);
+	mbedtls_sha256_ret(IV, AES_BLOCK_SZ, digest, 0);
 	memcpy(IV, digest, AES_BLOCK_SZ);
 	mbedtls_aes_setkey_enc(&aes_ctx, opts.sec_opts->aes_key,
 			       AES_KEY_BIT_LEN);
@@ -880,11 +880,13 @@
 				fname);
 			return 1;
 		}
+
 		/* Data in the output buffer is aligned to the buffer end */
 		der_buf_start = output_buf + sizeof(output_buf) - output_len;
 		/* In the header DER data is aligned
 		 * to the start of appropriate field
 		 */
+		bzero(out_der_key, MAX_RSA_DER_BYTE_LEN);
 		memcpy(out_der_key, der_buf_start, output_len);
 
 	} /* for every private key file */
@@ -899,8 +901,10 @@
 		fprintf(stderr, "Failed to sign CSK keys block!\n");
 		return 1;
 	}
+
 	/* Check that everything is correct */
-	if (verify_rsa_signature(sec_ext.kak_key, MAX_RSA_DER_BYTE_LEN,
+	if (verify_rsa_signature(sec_ext.kak_key,
+				 MAX_RSA_DER_BYTE_LEN,
 				 &sec_ext.csk_keys[0][0],
 				 sizeof(sec_ext.csk_keys),
 				 opts.sec_opts->kak_key_file,
@@ -1333,7 +1337,7 @@
 					goto error;
 				}
 
-				mbedtls_sha256(sec_entry->kak_key,
+				mbedtls_sha256_ret(sec_entry->kak_key,
 					       MAX_RSA_DER_BYTE_LEN, hash, 0);
 				fprintf(stdout,
 					">>>>>>>>>> KAK KEY HASH >>>>>>>>>>\n");
@@ -1559,13 +1563,9 @@
 
 int write_boot_image(uint8_t *buf, uint32_t image_size, FILE *out_fd)
 {
-	int aligned_size;
 	int written;
 
-	/* Image size must be aligned to 4 bytes */
-	aligned_size = (image_size + 3) & (~0x3);
-
-	written = fwrite(buf, aligned_size, 1, out_fd);
+	written = fwrite(buf, image_size, 1, out_fd);
 	if (written != 1) {
 		fprintf(stderr, "Error: Failed to write boot image\n");
 		goto error;
@@ -1587,7 +1587,7 @@
 	int ext_cnt = 0;
 	int opt;
 	int ret = 0;
-	int image_size;
+	int image_size, file_size;
 	uint8_t *image_buf = NULL;
 	int read;
 	size_t len;
@@ -1683,16 +1683,18 @@
 		goto main_exit;
 	}
 
-	/* Read the input file to buffer */
-	image_size = get_file_size(in_file);
-	image_buf = calloc((image_size + AES_BLOCK_SZ - 1) &
-			   ~(AES_BLOCK_SZ - 1), 1);
+	/* Read the input file to buffer
+	 * Always align the image to 16 byte boundary
+	 */
+	file_size  = get_file_size(in_file);
+	image_size = (file_size + AES_BLOCK_SZ - 1) & ~(AES_BLOCK_SZ - 1);
+	image_buf  = calloc(image_size, 1);
 	if (image_buf == NULL) {
 		fprintf(stderr, "Error: failed allocating input buffer\n");
 		return 1;
 	}
 
-	read = fread(image_buf, image_size, 1, in_fd);
+	read = fread(image_buf, file_size, 1, in_fd);
 	if (read != 1) {
 		fprintf(stderr, "Error: failed to read input file\n");
 		goto main_exit;