Merge pull request #1793 from marex/arm/master/fixes-v2.0.0

Arm/master/fixes v2.0.0
diff --git a/docs/coding-guidelines.rst b/docs/coding-guidelines.rst
new file mode 100644
index 0000000..5a30e91
--- /dev/null
+++ b/docs/coding-guidelines.rst
@@ -0,0 +1,553 @@
+Trusted Firmware-A Coding Guidelines
+====================================
+
+.. section-numbering::
+    :suffix: .
+
+.. contents::
+
+The following sections contain TF coding guidelines. They are continually
+evolving and should not be considered "set in stone". Feel free to question them
+and provide feedback.
+
+Some of the guidelines may also apply to other codebases.
+
+**Note:** the existing TF codebase does not necessarily comply with all the
+below guidelines but the intent is for it to do so eventually.
+
+Checkpatch overrides
+--------------------
+
+Some checkpatch warnings in the TF codebase are deliberately ignored. These
+include:
+
+- ``**WARNING: line over 80 characters**``: Although the codebase should
+  generally conform to the 80 character limit this is overly restrictive in some
+  cases.
+
+- ``**WARNING: Use of volatile is usually wrong``: see
+  `Why the “volatile” type class should not be used`_ . Although this document
+  contains some very useful information, there are several legimate uses of the
+  volatile keyword within the TF codebase.
+
+Headers and inclusion
+---------------------
+
+Header guards
+^^^^^^^^^^^^^
+
+For a header file called "some_driver.h" the style used by the Trusted Firmware
+is:
+
+.. code:: c
+
+  #ifndef SOME_DRIVER_H
+  #define SOME_DRIVER_H
+
+  <header content>
+
+  #endif /* SOME_DRIVER_H */
+
+Include statement ordering
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+All header files that are included by a source file must use the following,
+grouped ordering. This is to improve readability (by making it easier to quickly
+read through the list of headers) and maintainability.
+
+#. *System* includes: Header files from the standard *C* library, such as
+   ``stddef.h`` and ``string.h``.
+
+#. *Project* includes: Header files under the ``include/`` directory within TF
+   are *project* includes.
+
+#. *Platform* includes: Header files relating to a single, specific platform,
+   and which are located under the ``plat/<platform_name>`` directory within TF,
+   are *platform* includes.
+
+Within each group, ``#include`` statements must be in alphabetical order,
+taking both the file and directory names into account.
+
+Groups must be separated by a single blank line for clarity.
+
+The example below illustrates the ordering rules using some contrived header
+file names; this type of name reuse should be otherwise avoided.
+.. code:: c
+
+  #include <string.h>
+
+  #include <a_dir/example/a_header.h>
+  #include <a_dir/example/b_header.h>
+  #include <a_dir/test/a_header.h>
+  #include <b_dir/example/a_header.h>
+
+  #include "./a_header.h"
+
+Include statement variants
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Two variants of the ``#include`` directive are acceptable in the TF codebase.
+Correct use of the two styles improves readability by suggesting the location
+of the included header and reducing ambiguity in cases where generic and
+platform-specific headers share a name.
+
+For header files that are in the same directory as the source file that is
+including them, use the ``"..."`` variant.
+
+For header files that are **not** in the same directory as the source file that
+is including them, use the ``<...>`` variant.
+
+Example (bl1_fwu.c):
+.. code:: c
+
+  #include <assert.h>
+  #include <errno.h>
+  #include <string.h>
+
+  #include "bl1_private.h"
+
+Platform include paths
+^^^^^^^^^^^^^^^^^^^^^^
+
+Platforms are allowed to add more include paths to be passed to the compiler.
+The ``PLAT_INCLUDES`` variable is used for this purpose. This is needed in
+particular for the file ``platform_def.h``.
+
+Example:
+.. code:: c
+
+  PLAT_INCLUDES  += -Iinclude/plat/myplat/include
+
+Types and typedefs
+------------------
+
+Use of built-in *C* and *libc* data types
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The TF codebase should be kept as portable as possible, especially since both
+64-bit and 32-bit platforms are supported. To help with this, the following data
+type usage guidelines should be followed:
+
+- Where possible, use the built-in *C* data types for variable storage (for
+  example, ``char``, ``int``, ``long long``, etc) instead of the standard *C99*
+  types. Most code is typically only concerned with the minimum size of the
+  data stored, which the built-in *C* types guarantee.
+
+- Avoid using the exact-size standard *C99* types in general (for example,
+  ``uint16_t``, ``uint32_t``, ``uint64_t``, etc) since they can prevent the
+  compiler from making optimizations. There are legitimate uses for them,
+  for example to represent data of a known structure. When using them in struct
+  definitions, consider how padding in the struct will work across architectures.
+  For example, extra padding may be introduced in AArch32 systems if a struct
+  member crosses a 32-bit boundary.
+
+- Use ``int`` as the default integer type - it's likely to be the fastest on all
+  systems. Also this can be assumed to be 32-bit as a consequence of the
+  `Procedure Call Standard for the Arm Architecture`_ and the `Procedure Call
+  Standard for the Arm 64-bit Architecture`_ .
+
+- Avoid use of ``short`` as this may end up being slower than ``int`` in some
+  systems. If a variable must be exactly 16-bit, use ``int16_t`` or
+  ``uint16_t``.
+
+- Avoid use of ``long``. This is guaranteed to be at least 32-bit but, given
+  that `int` is 32-bit on Arm platforms, there is no use for it. For integers of
+  at least 64-bit, use ``long long``.
+
+- Use ``char`` for storing text. Use ``uint8_t`` for storing other 8-bit data.
+
+- Use ``unsigned`` for integers that can never be negative (counts,
+  indices, sizes, etc). TF intends to comply with MISRA "essential type" coding
+  rules (10.X), where signed and unsigned types are considered different
+  essential types. Choosing the correct type will aid this. MISRA static
+  analysers will pick up any implicit signed/unsigned conversions that may lead
+  to unexpected behaviour.
+
+- For pointer types:
+
+  - If an argument in a function declaration is pointing to a known type then
+    simply use a pointer to that type (for example: ``struct my_struct *``).
+
+  - If a variable (including an argument in a function declaration) is pointing
+    to a general, memory-mapped address, an array of pointers or another
+    structure that is likely to require pointer arithmetic then use
+    ``uintptr_t``. This will reduce the amount of casting required in the code.
+    Avoid using ``unsigned long`` or ``unsigned long long`` for this purpose; it
+    may work but is less portable.
+
+  - For other pointer arguments in a function declaration, use ``void *``. This
+    includes pointers to types that are abstracted away from the known API and
+    pointers to arbitrary data. This allows the calling function to pass a
+    pointer argument to the function without any explicit casting (the cast to
+    ``void *`` is implicit). The function implementation can then do the
+    appropriate casting to a specific type.
+
+  - Use ``ptrdiff_t`` to compare the difference between 2 pointers.
+
+- Use ``size_t`` when storing the ``sizeof()`` something.
+
+- Use ``ssize_t`` when returning the ``sizeof()`` something from a function that
+  can also return an error code; the signed type allows for a negative return
+  code in case of error. This practice should be used sparingly.
+
+- Use ``u_register_t`` when it's important to store the contents of a register
+  in its native size (32-bit in AArch32 and 64-bit in AArch64). This is not a
+  standard *C99* type but is widely available in libc implementations,
+  including the FreeBSD version included with the TF codebase. Where possible,
+  cast the variable to a more appropriate type before interpreting the data. For
+  example, the following struct in ``ep_info.h`` could use this type to minimize
+  the storage required for the set of registers:
+
+.. code:: c
+
+    typedef struct aapcs64_params {
+            u_register_t arg0;
+            u_register_t arg1;
+            u_register_t arg2;
+            u_register_t arg3;
+            u_register_t arg4;
+            u_register_t arg5;
+            u_register_t arg6;
+            u_register_t arg7;
+    } aapcs64_params_t;
+
+
+    If some code wants to operate on ``arg0`` and knows that it represents a
+    32-bit unsigned integer on all systems, cast it to ``unsigned int``.
+
+These guidelines should be updated if additional types are needed.
+
+Avoid anonymous typedefs of structs/enums in headers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+For example, the following definition:
+
+.. code:: c
+
+  typedef struct {
+          int arg1;
+          int arg2;
+  } my_struct_t;
+
+
+is better written as:
+
+.. code:: c
+
+  struct my_struct {
+          int arg1;
+          int arg2;
+  };
+
+This allows function declarations in other header files that depend on the
+struct/enum to forward declare the struct/enum instead of including the
+entire header:
+
+.. code:: c
+
+  #include <my_struct.h>
+  void my_func(my_struct_t *arg);
+
+instead of:
+
+.. code:: c
+
+  struct my_struct;
+  void my_func(struct my_struct *arg);
+
+Some TF definitions use both a struct/enum name **and** a typedef name. This
+is discouraged for new definitions as it makes it difficult for TF to comply
+with MISRA rule 8.3, which states that "All declarations of an object or
+function shall use the same names and type qualifiers".
+
+The Linux coding standards also discourage new typedefs and checkpatch emits
+a warning for this.
+
+Existing typedefs will be retained for compatibility.
+
+Error handling and robustness
+-----------------------------
+
+Using CASSERT to check for compile time data errors
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Where possible, use the ``CASSERT`` macro to check the validity of data known at
+compile time instead of checking validity at runtime, to avoid unnecessary
+runtime code.
+
+For example, this can be used to check that the assembler's and compiler's views
+of the size of an array is the same.
+
+.. code:: c
+
+  #include <cassert.h>
+
+  define MY_STRUCT_SIZE 8 /* Used by assembler source files */
+
+  struct my_struct {
+      uint32_t arg1;
+      uint32_t arg2;
+  };
+
+  CASSERT(MY_STRUCT_SIZE == sizeof(struct my_struct), assert_my_struct_size_mismatch);
+
+
+If ``MY_STRUCT_SIZE`` in the above example were wrong then the compiler would
+emit an error like this:
+
+.. code:: c
+
+  my_struct.h:10:1: error: size of array ‘assert_my_struct_size_mismatch’ is negative
+
+
+Using assert() to check for programming errors
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+In general, each secure world TF image (BL1, BL2, BL31 and BL32) should be
+treated as a tightly integrated package; the image builder should be aware of
+and responsible for all functionality within the image, even if code within that
+image is provided by multiple entities. This allows us to be more aggressive in
+interpreting invalid state or bad function arguments as programming errors using
+``assert()``, including arguments passed across platform porting interfaces.
+This is in contrast to code in a Linux environment, which is less tightly
+integrated and may attempt to be more defensive by passing the error back up the
+call stack.
+
+Where possible, badly written TF code should fail early using ``assert()``. This
+helps reduce the amount of untested conditional code. By default these
+statements are not compiled into release builds, although this can be overridden
+using the ``ENABLE_ASSERTIONS`` build flag.
+
+Examples:
+
+- Bad argument supplied to library function
+- Bad argument provided by platform porting function
+- Internal secure world image state is inconsistent
+
+
+Handling integration errors
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Each secure world image may be provided by a different entity (for example, a
+Trusted Boot vendor may provide the BL2 image, a TEE vendor may provide the BL32
+image and the OEM/SoC vendor may provide the other images).
+
+An image may contain bugs that are only visible when the images are integrated.
+The system integrator may not even have access to the debug variants of all the
+images in order to check if asserts are firing. For example, the release variant
+of BL1 may have already been burnt into the SoC. Therefore, TF code that detects
+an integration error should _not_ consider this a programming error, and should
+always take action, even in release builds.
+
+If an integration error is considered non-critical it should be treated as a
+recoverable error. If the error is considered critical it should be treated as
+an unexpected unrecoverable error.
+
+Handling recoverable errors
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The secure world **must not** crash when supplied with bad data from an external
+source. For example, data from the normal world or a hardware device. Similarly,
+the secure world **must not** crash if it detects a non-critical problem within
+itself or the system. It must make every effort to recover from the problem by
+emitting a ``WARN`` message, performing any necessary error handling and
+continuing.
+
+Examples:
+
+- Secure world receives SMC from normal world with bad arguments.
+- Secure world receives SMC from normal world at an unexpected time.
+- BL31 receives SMC from BL32 with bad arguments.
+- BL31 receives SMC from BL32 at unexpected time.
+- Secure world receives recoverable error from hardware device. Retrying the
+  operation may help here.
+- Non-critical secure world service is not functioning correctly.
+- BL31 SPD discovers minor configuration problem with corresponding SP.
+
+Handling unrecoverable errors
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+In some cases it may not be possible for the secure world to recover from an
+error. This situation should be handled in one of the following ways:
+
+1. If the unrecoverable error is unexpected then emit an ``ERROR`` message and
+   call ``panic()``. This will end up calling the platform-specific function
+   ``plat_panic_handler()``.
+2. If the unrecoverable error is expected to occur in certain circumstances,
+   then emit an ``ERROR`` message and call the platform-specific function
+   ``plat_error_handler()``.
+
+Cases 1 and 2 are subtly different. A platform may implement ``plat_panic_handler``
+and ``plat_error_handler`` in the same way (for example, by waiting for a secure
+watchdog to time-out or by invoking an interface on the platform's power
+controller to reset the platform). However, ``plat_error_handler`` may take
+additional action for some errors (for example, it may set a flag so the
+platform resets into a different mode). Also, ``plat_panic_handler()`` may
+implement additional debug functionality (for example, invoking a hardware
+breakpoint).
+
+Examples of unexpected unrecoverable errors:
+
+- BL32 receives an unexpected SMC response from BL31 that it is unable to
+  recover from.
+- BL31 Trusted OS SPD code discovers that BL2 has not loaded the corresponding
+  Trusted OS, which is critical for platform operation.
+- Secure world discovers that a critical hardware device is an unexpected and
+  unrecoverable state.
+- Secure world receives an unexpected and unrecoverable error from a critical
+  hardware device.
+- Secure world discovers that it is running on unsupported hardware.
+
+Examples of expected unrecoverable errors:
+
+- BL1/BL2 fails to load the next image due to missing/corrupt firmware on disk.
+- BL1/BL2 fails to authenticate the next image due to an invalid certificate.
+- Secure world continuously receives recoverable errors from a hardware device
+  but is unable to proceed without a valid response.
+
+Handling critical unresponsiveness
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If the secure world is waiting for a response from an external source (for
+example, the normal world or a hardware device) which is critical for continued
+operation, it must not wait indefinitely. It must have a mechanism (for example,
+a secure watchdog) for resetting itself and/or the external source to prevent
+the system from executing in this state indefinitely.
+
+Examples:
+
+- BL1 is waiting for the normal world to raise an SMC to proceed to the next
+  stage of the secure firmware update process.
+- A Trusted OS is waiting for a response from a proxy in the normal world that
+  is critical for continued operation.
+- Secure world is waiting for a hardware response that is critical for continued
+  operation.
+
+Security considerations
+-----------------------
+
+Part of the security of a platform is handling errors correctly, as described in
+the previous section. There are several other security considerations covered in
+this section.
+
+Do not leak secrets to the normal world
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The secure world **must not** leak secrets to the normal world, for example in
+response to an SMC.
+
+Handling Denial of Service attacks
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The secure world **should never** crash or become unusable due to receiving too
+many normal world requests (a *Denial of Service* or *DoS* attack). It should
+have a mechanism for throttling or ignoring normal world requests.
+
+Performance considerations
+--------------------------
+
+Avoid printf and use logging macros
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``debug.h`` provides logging macros (for example, ``WARN`` and ``ERROR``)
+which wrap ``tf_log`` and which allow the logging call to be compiled-out
+depending on the ``make`` command. Use these macros to avoid print statements
+being compiled unconditionally into the binary.
+
+Each logging macro has a numerical log level:
+
+.. code:: c
+
+  #define LOG_LEVEL_NONE    0
+  #define LOG_LEVEL_ERROR   10
+  #define LOG_LEVEL_NOTICE  20
+  #define LOG_LEVEL_WARNING 30
+  #define LOG_LEVEL_INFO    40
+  #define LOG_LEVEL_VERBOSE 50
+
+
+By default, all logging statements with a log level ``<= LOG_LEVEL_INFO`` will
+be compiled into debug builds and all statements with a log level
+``<= LOG_LEVEL_NOTICE`` will be compiled into release builds. This can be
+overridden from the command line or by the platform makefile (although it may be
+necessary to clean the build directory first). For example, to enable
+``VERBOSE`` logging on FVP:
+
+``make PLAT=fvp LOG_LEVEL=50 all``
+
+Use const data where possible
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+For example, the following code:
+
+.. code:: c
+
+  struct my_struct {
+          int arg1;
+          int arg2;
+  };
+
+  void init(struct my_struct *ptr);
+
+  void main(void)
+  {
+          struct my_struct x;
+          x.arg1 = 1;
+          x.arg2 = 2;
+          init(&x);
+  }
+
+is better written as:
+
+.. code:: c
+
+  struct my_struct {
+          int arg1;
+          int arg2;
+  };
+
+  void init(const struct my_struct *ptr);
+
+  void main(void)
+  {
+          const struct my_struct x = { 1, 2 };
+          init(&x);
+  }
+
+This allows the linker to put the data in a read-only data section instead of a
+writeable data section, which may result in a smaller and faster binary. Note
+that this may require dependent functions (``init()`` in the above example) to
+have ``const`` arguments, assuming they don't need to modify the data.
+
+Library and driver code
+-----------------------
+
+TF library code (under ``lib/`` and ``include/lib``) is any code that provides a
+reusable interface to other code, potentially even to code outside of TF.
+
+In some systems drivers must conform to a specific driver framework to provide
+services to the rest of the system. TF has no driver framework and the
+distinction between a driver and library is somewhat subjective.
+
+A driver (under ``drivers/`` and ``include/drivers/``) is defined as code that
+interfaces with hardware via a memory mapped interface.
+
+Some drivers (for example, the Arm CCI driver in ``include/drivers/arm/cci.h``)
+provide a general purpose API to that specific hardware. Other drivers (for
+example, the Arm PL011 console driver in ``drivers/arm/pl011/pl011_console.S``)
+provide a specific hardware implementation of a more abstract library API. In
+the latter case there may potentially be multiple drivers for the same hardware
+device.
+
+Neither libraries nor drivers should depend on platform-specific code. If they
+require platform-specific data (for example, a base address) to operate then
+they should provide an initialization function that takes the platform-specific
+data as arguments.
+
+TF common code (under ``common/`` and ``include/common/``) is code that is re-used
+by other generic (non-platform-specific) TF code. It is effectively internal
+library code.
+
+.. _`Why the “volatile” type class should not be used`: https://www.kernel.org/doc/html/latest/process/volatile-considered-harmful.html
+.. _`Procedure Call Standard for the Arm Architecture`: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042f/IHI0042F_aapcs.pdf
+.. _`Procedure Call Standard for the Arm 64-bit Architecture`: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index b50de37..e22733e 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -86,6 +86,46 @@
 
     git clone https://github.com/ARM-software/arm-trusted-firmware.git
 
+Checking source code style
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Trusted Firmware follows the `Linux Coding Style`_ . When making changes to the
+source, for submission to the project, the source must be in compliance with
+this style guide.
+
+Additional, project-specific guidelines are defined in the `Trusted Firmware-A
+Coding Guidelines`_ document.
+
+To assist with coding style compliance, the project Makefile contains two
+targets which both utilise the `checkpatch.pl` script that ships with the Linux
+source tree. The project also defines certain *checkpatch* options in the
+``.checkpatch.conf`` file in the top-level directory.
+
+**Note:** Checkpatch errors will gate upstream merging of pull requests.
+Checkpatch warnings will not gate merging but should be reviewed and fixed if
+possible.
+
+To check the entire source tree, you must first download copies of
+``checkpatch.pl``, ``spelling.txt`` and ``const_structs.checkpatch`` available
+in the `Linux master tree`_ *scripts* directory, then set the ``CHECKPATCH``
+environment variable to point to ``checkpatch.pl`` (with the other 2 files in
+the same directory) and build the `checkcodebase` target:
+
+::
+
+    make CHECKPATCH=<path-to-linux>/linux/scripts/checkpatch.pl checkcodebase
+
+To just check the style on the files that differ between your local branch and
+the remote master, use:
+
+::
+
+    make CHECKPATCH=<path-to-linux>/linux/scripts/checkpatch.pl checkpatch
+
+If you wish to check your patch against something other than the remote master,
+set the ``BASE_COMMIT`` variable to your desired branch. By default, ``BASE_COMMIT``
+is set to ``origin/master``.
+
 Building TF-A
 -------------
 
@@ -930,34 +970,6 @@
 
     build/<platform>/<build-type>/bl32.bin
 
-Checking source code style
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When making changes to the source for submission to the project, the source
-must be in compliance with the Linux style guide, and to assist with this check
-the project Makefile contains two targets, which both utilise the
-``checkpatch.pl`` script that ships with the Linux source tree.
-
-To check the entire source tree, you must first download copies of
-``checkpatch.pl``, ``spelling.txt`` and ``const_structs.checkpatch`` available
-in the `Linux master tree`_ scripts directory, then set the ``CHECKPATCH``
-environment variable to point to ``checkpatch.pl`` (with the other 2 files in
-the same directory) and build the target checkcodebase:
-
-::
-
-    make CHECKPATCH=<path-to-linux>/linux/scripts/checkpatch.pl checkcodebase
-
-To just check the style on the files that differ between your local branch and
-the remote master, use:
-
-::
-
-    make CHECKPATCH=<path-to-linux>/linux/scripts/checkpatch.pl checkpatch
-
-If you wish to check your patch against something other than the remote master,
-set the ``BASE_COMMIT`` variable to your desired branch. By default, ``BASE_COMMIT``
-is set to ``origin/master``.
 
 Building and using the FIP tool
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2054,6 +2066,7 @@
 .. _Instructions for using Linaro's deliverables on Juno: https://community.arm.com/dev-platforms/w/docs/303/juno
 .. _Arm Platforms Portal: https://community.arm.com/dev-platforms/
 .. _Development Studio 5 (DS-5): http://www.arm.com/products/tools/software-tools/ds-5/index.php
+.. _`Linux Coding Style`: https://www.kernel.org/doc/html/latest/process/coding-style.html
 .. _Linux master tree: https://github.com/torvalds/linux/tree/master/
 .. _Dia: https://wiki.gnome.org/Apps/Dia/Download
 .. _here: psci-lib-integration-guide.rst
@@ -2069,3 +2082,4 @@
 .. _Juno Getting Started Guide: http://infocenter.arm.com/help/topic/com.arm.doc.dui0928e/DUI0928E_juno_arm_development_platform_gsg.pdf
 .. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf
 .. _Secure Partition Manager Design guide: secure-partition-manager-design.rst
+.. _`Trusted Firmware-A Coding Guidelines`: coding-guidelines.rst
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 450bd0b..77d683c 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -300,7 +300,7 @@
 		break;
 	}
 
-	if (ret != 0) {
+	if (ret < 0) {
 		return ret;
 	}
 
diff --git a/drivers/partition/partition.c b/drivers/partition/partition.c
index 630c1d8..6fa3df0 100644
--- a/drivers/partition/partition.c
+++ b/drivers/partition/partition.c
@@ -16,7 +16,7 @@
 #include <plat/common/platform.h>
 
 static uint8_t mbr_sector[PARTITION_BLOCK_SIZE];
-partition_entry_list_t list;
+static partition_entry_list_t list;
 
 #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
 static void dump_entries(int num)
diff --git a/drivers/synopsys/ufs/dw_ufs.c b/drivers/synopsys/ufs/dw_ufs.c
index c7c8fc2..6bed981 100644
--- a/drivers/synopsys/ufs/dw_ufs.c
+++ b/drivers/synopsys/ufs/dw_ufs.c
@@ -183,7 +183,7 @@
 	return 0;
 }
 
-const ufs_ops_t dw_ufs_ops = {
+static const ufs_ops_t dw_ufs_ops = {
 	.phy_init		= dwufs_phy_init,
 	.phy_set_pwr_mode	= dwufs_phy_set_pwr_mode,
 };
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index 2351c9b..b2c1046 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -591,7 +591,7 @@
 	ufs_query(QUERY_WRITE_DESC, idn, index, 0, buf, size);
 }
 
-void ufs_read_capacity(int lun, unsigned int *num, unsigned int *size)
+static void ufs_read_capacity(int lun, unsigned int *num, unsigned int *size)
 {
 	utp_utrd_t utrd;
 	resp_upiu_t *resp;
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 9e2bffa..76c3e27 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -204,6 +204,10 @@
 
 /* ID_AA64MMFR2_EL1 definitions */
 #define ID_AA64MMFR2_EL1		S3_0_C0_C7_2
+
+#define ID_AA64MMFR2_EL1_ST_SHIFT	U(28)
+#define ID_AA64MMFR2_EL1_ST_MASK	ULL(0xf)
+
 #define ID_AA64MMFR2_EL1_CNP_SHIFT	U(0)
 #define ID_AA64MMFR2_EL1_CNP_MASK	ULL(0xf)
 
@@ -427,6 +431,7 @@
 
 #define TCR_TxSZ_MIN		ULL(16)
 #define TCR_TxSZ_MAX		ULL(39)
+#define TCR_TxSZ_MAX_TTST	ULL(48)
 
 /* (internal) physical address size bits in EL3/EL1 */
 #define TCR_PS_BITS_4GB		ULL(0x0)
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index 2b09ba0..9bf43bf 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -17,4 +17,10 @@
 		ID_AA64MMFR2_EL1_CNP_MASK) != 0U;
 }
 
+static inline bool is_armv8_4_ttst_present(void)
+{
+	return ((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_ST_SHIFT) &
+		ID_AA64MMFR2_EL1_ST_MASK) == 1U;
+}
+
 #endif /* ARCH_FEATURES_H */
diff --git a/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h b/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h
index a333d1e..30eb5e9 100644
--- a/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h
+++ b/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h
@@ -63,8 +63,7 @@
  * is 1.
  *
  * Note that this macro assumes that the given virtual address space size is
- * valid. Therefore, the caller is expected to check it is the case using the
- * CHECK_VIRT_ADDR_SPACE_SIZE() macro first.
+ * valid.
  */
 #define GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_sz)			\
 	(((_virt_addr_space_sz) > (ULL(1) << L1_XLAT_ADDRESS_SHIFT)) ?	\
diff --git a/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h b/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h
index cc5624c..3014c8f 100644
--- a/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h
+++ b/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h
@@ -43,14 +43,22 @@
  * state.
  *
  * TCR.TxSZ is calculated as 64 minus the width of said address space.
- * The value of TCR.TxSZ must be in the range 16 to 39 [1], which means that
- * the virtual address space width must be in the range 48 to 25 bits.
+ * The value of TCR.TxSZ must be in the range 16 to 39 [1] or 48 [2],
+ * depending on Small Translation Table Support which means that
+ * the virtual address space width must be in the range 48 to 25 or 16 bits.
  *
  * [1] See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more
  * information:
  * Page 1730: 'Input address size', 'For all translation stages'.
+ * [2] See section 12.2.55 in the ARMv8-A Architecture Reference Manual
+ * (DDI 0487D.a)
  */
+/* Maximum value of TCR_ELx.T(0,1)SZ is 39 */
 #define MIN_VIRT_ADDR_SPACE_SIZE	(ULL(1) << (U(64) - TCR_TxSZ_MAX))
+
+/* Maximum value of TCR_ELx.T(0,1)SZ is 48 */
+#define MIN_VIRT_ADDR_SPACE_SIZE_TTST	\
+				(ULL(1) << (U(64) - TCR_TxSZ_MAX_TTST))
 #define MAX_VIRT_ADDR_SPACE_SIZE	(ULL(1) << (U(64) - TCR_TxSZ_MIN))
 
 /*
@@ -58,9 +66,13 @@
  * virtual address space size. For a 4 KB page size,
  * - level 0 supports virtual address spaces of widths 48 to 40 bits;
  * - level 1 from 39 to 31;
- * - level 2 from 30 to 25.
+ * - level 2 from 30 to 22.
+ * - level 3 from 21 to 16.
  *
- * Wider or narrower address spaces are not supported. As a result, level 3
+ * Small Translation Table (Armv8.4-TTST) support allows the starting level
+ * of the translation table from 3 for 4KB granularity. See section 12.2.55 in
+ * the ARMv8-A Architecture Reference Manual (DDI 0487D.a). In Armv8.3 and below
+ * wider or narrower address spaces are not supported. As a result, level 3
  * cannot be used as initial lookup level with 4 KB granularity. See section
  * D4.2.5 in the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more
  * information.
@@ -71,13 +83,14 @@
  * is 1.
  *
  * Note that this macro assumes that the given virtual address space size is
- * valid. Therefore, the caller is expected to check it is the case using the
- * CHECK_VIRT_ADDR_SPACE_SIZE() macro first.
+ * valid.
  */
 #define GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_sz)		\
 	(((_virt_addr_space_sz) > (ULL(1) << L0_XLAT_ADDRESS_SHIFT))	\
 	? 0U								\
-	 : (((_virt_addr_space_sz) > (ULL(1) << L1_XLAT_ADDRESS_SHIFT))	\
-	 ? 1U : 2U))
+	: (((_virt_addr_space_sz) > (ULL(1) << L1_XLAT_ADDRESS_SHIFT))	\
+	? 1U								\
+	: (((_virt_addr_space_sz) > (ULL(1) << L2_XLAT_ADDRESS_SHIFT))	\
+	? 2U : 3U)))
 
 #endif /* XLAT_TABLES_AARCH64_H */
diff --git a/include/lib/xlat_tables/xlat_tables_arch.h b/include/lib/xlat_tables/xlat_tables_arch.h
index 251b020..7237534 100644
--- a/include/lib/xlat_tables/xlat_tables_arch.h
+++ b/include/lib/xlat_tables/xlat_tables_arch.h
@@ -14,18 +14,6 @@
 #endif
 
 /*
- * Evaluates to 1 if the given virtual address space size is valid, or 0 if it's
- * not.
- *
- * A valid size is one that is a power of 2 and is within the architectural
- * limits. Not that these limits are different for AArch32 and AArch64.
- */
-#define CHECK_VIRT_ADDR_SPACE_SIZE(size)			\
-	(((unsigned long long)(size) >= MIN_VIRT_ADDR_SPACE_SIZE) &&	\
-	((unsigned long long)(size) <= MAX_VIRT_ADDR_SPACE_SIZE) &&	\
-	IS_POWER_OF_TWO(size))
-
-/*
  * Evaluates to 1 if the given physical address space size is a power of 2,
  * or 0 if it's not.
  */
diff --git a/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
index ce5cf82..6a1be32 100644
--- a/include/lib/xlat_tables/xlat_tables_v2_helpers.h
+++ b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
@@ -125,9 +125,6 @@
 #define REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count,		\
 			_xlat_tables_count, _virt_addr_space_size,	\
 			_phy_addr_space_size, _xlat_regime, _section_name)\
-	CASSERT(CHECK_VIRT_ADDR_SPACE_SIZE(_virt_addr_space_size),	\
-		assert_invalid_virtual_addr_space_size_for_##_ctx_name);\
-									\
 	CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(_phy_addr_space_size),	\
 		assert_invalid_physical_addr_space_sizefor_##_ctx_name);\
 									\
diff --git a/lib/xlat_tables/aarch32/xlat_tables.c b/lib/xlat_tables/aarch32/xlat_tables.c
index 468a9e7..4b01b9b 100644
--- a/lib/xlat_tables/aarch32/xlat_tables.c
+++ b/lib/xlat_tables/aarch32/xlat_tables.c
@@ -55,6 +55,11 @@
 {
 	unsigned long long max_pa;
 	uintptr_t max_va;
+
+	assert(PLAT_VIRT_ADDR_SPACE_SIZE >= MIN_VIRT_ADDR_SPACE_SIZE);
+	assert(PLAT_VIRT_ADDR_SPACE_SIZE <= MAX_VIRT_ADDR_SPACE_SIZE);
+	assert(IS_POWER_OF_TWO(PLAT_VIRT_ADDR_SPACE_SIZE));
+
 	print_mmap();
 	init_xlation_table(0U, base_xlation_table, XLAT_TABLE_LEVEL_BASE,
 						&max_va, &max_pa);
diff --git a/lib/xlat_tables/aarch64/xlat_tables.c b/lib/xlat_tables/aarch64/xlat_tables.c
index 71f491a..e64fd3e 100644
--- a/lib/xlat_tables/aarch64/xlat_tables.c
+++ b/lib/xlat_tables/aarch64/xlat_tables.c
@@ -10,7 +10,7 @@
 #include <platform_def.h>
 
 #include <arch.h>
-#include <arch_helpers.h>
+#include <arch_features.h>
 #include <common/bl_common.h>
 #include <lib/utils.h>
 #include <lib/xlat_tables/xlat_tables.h>
@@ -79,6 +79,21 @@
 
 	return (1ULL << pa_range_bits_arr[pa_range]) - 1ULL;
 }
+
+/*
+ * Return minimum virtual address space size supported by the architecture
+ */
+static uintptr_t xlat_get_min_virt_addr_space_size(void)
+{
+	uintptr_t ret;
+
+	if (is_armv8_4_ttst_present())
+		ret = MIN_VIRT_ADDR_SPACE_SIZE_TTST;
+	else
+		ret = MIN_VIRT_ADDR_SPACE_SIZE;
+
+	return ret;
+}
 #endif /* ENABLE_ASSERTIONS */
 
 unsigned int xlat_arch_current_el(void)
@@ -104,6 +119,12 @@
 {
 	unsigned long long max_pa;
 	uintptr_t max_va;
+
+	assert(PLAT_VIRT_ADDR_SPACE_SIZE >=
+		(xlat_get_min_virt_addr_space_size() - 1U));
+	assert(PLAT_VIRT_ADDR_SPACE_SIZE <= MAX_VIRT_ADDR_SPACE_SIZE);
+	assert(IS_POWER_OF_TWO(PLAT_VIRT_ADDR_SPACE_SIZE));
+
 	print_mmap();
 	init_xlation_table(0U, base_xlation_table, XLAT_TABLE_LEVEL_BASE,
 			   &max_va, &max_pa);
diff --git a/lib/xlat_tables/xlat_tables_private.h b/lib/xlat_tables/xlat_tables_private.h
index 4390f34..82bc70c 100644
--- a/lib/xlat_tables/xlat_tables_private.h
+++ b/lib/xlat_tables/xlat_tables_private.h
@@ -16,9 +16,6 @@
 #error xlat tables v2 must be used with HW_ASSISTED_COHERENCY
 #endif
 
-CASSERT(CHECK_VIRT_ADDR_SPACE_SIZE(PLAT_VIRT_ADDR_SPACE_SIZE),
-	assert_valid_virt_addr_space_size);
-
 CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(PLAT_PHY_ADDR_SPACE_SIZE),
 	assert_valid_phy_addr_space_size);
 
diff --git a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
index 913c86d..b69c670 100644
--- a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
@@ -45,6 +45,14 @@
 	/* Physical address space size for long descriptor format. */
 	return (1ULL << 40) - 1ULL;
 }
+
+/*
+ * Return minimum virtual address space size supported by the architecture
+ */
+uintptr_t xlat_get_min_virt_addr_space_size(void)
+{
+	return MIN_VIRT_ADDR_SPACE_SIZE;
+}
 #endif /* ENABLE_ASSERTIONS*/
 
 bool is_mmu_enabled_ctx(const xlat_ctx_t *ctx)
@@ -193,7 +201,12 @@
 	if (max_va != UINT32_MAX) {
 		uintptr_t virtual_addr_space_size = max_va + 1U;
 
-		assert(CHECK_VIRT_ADDR_SPACE_SIZE(virtual_addr_space_size));
+		assert(virtual_addr_space_size >=
+			xlat_get_min_virt_addr_space_size());
+		assert(virtual_addr_space_size <=
+			MAX_VIRT_ADDR_SPACE_SIZE);
+		assert(IS_POWER_OF_TWO(virtual_addr_space_size));
+
 		/*
 		 * __builtin_ctzll(0) is undefined but here we are guaranteed
 		 * that virtual_addr_space_size is in the range [1, UINT32_MAX].
diff --git a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
index 228f751..e7593dd 100644
--- a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
@@ -101,6 +101,21 @@
 
 	return (1ULL << pa_range_bits_arr[pa_range]) - 1ULL;
 }
+
+/*
+ * Return minimum virtual address space size supported by the architecture
+ */
+uintptr_t xlat_get_min_virt_addr_space_size(void)
+{
+	uintptr_t ret;
+
+	if (is_armv8_4_ttst_present())
+		ret = MIN_VIRT_ADDR_SPACE_SIZE_TTST;
+	else
+		ret = MIN_VIRT_ADDR_SPACE_SIZE;
+
+	return ret;
+}
 #endif /* ENABLE_ASSERTIONS*/
 
 bool is_mmu_enabled_ctx(const xlat_ctx_t *ctx)
@@ -221,7 +236,11 @@
 	assert(max_va < ((uint64_t)UINTPTR_MAX));
 
 	virtual_addr_space_size = (uintptr_t)max_va + 1U;
-	assert(CHECK_VIRT_ADDR_SPACE_SIZE(virtual_addr_space_size));
+
+	assert(virtual_addr_space_size >=
+		xlat_get_min_virt_addr_space_size());
+	assert(virtual_addr_space_size <= MAX_VIRT_ADDR_SPACE_SIZE);
+	assert(IS_POWER_OF_TWO(virtual_addr_space_size));
 
 	/*
 	 * __builtin_ctzll(0) is undefined but here we are guaranteed that
diff --git a/lib/xlat_tables_v2/xlat_tables_core.c b/lib/xlat_tables_v2/xlat_tables_core.c
index c49554f..4820b4f 100644
--- a/lib/xlat_tables_v2/xlat_tables_core.c
+++ b/lib/xlat_tables_v2/xlat_tables_core.c
@@ -1146,6 +1146,11 @@
 
 	mmap_region_t *mm = ctx->mmap;
 
+	assert(ctx->va_max_address >=
+		(xlat_get_min_virt_addr_space_size() - 1U));
+	assert(ctx->va_max_address <= (MAX_VIRT_ADDR_SPACE_SIZE - 1U));
+	assert(IS_POWER_OF_TWO(ctx->va_max_address + 1U));
+
 	xlat_mmap_print(mm);
 
 	/* All tables must be zeroed before mapping any region. */
diff --git a/lib/xlat_tables_v2/xlat_tables_private.h b/lib/xlat_tables_v2/xlat_tables_private.h
index fc70955..70ef395 100644
--- a/lib/xlat_tables_v2/xlat_tables_private.h
+++ b/lib/xlat_tables_v2/xlat_tables_private.h
@@ -102,4 +102,9 @@
 /* Returns true if the data cache is enabled at the current EL. */
 bool is_dcache_enabled(void);
 
+/*
+ * Returns minimum virtual address space size supported by the architecture
+ */
+uintptr_t xlat_get_min_virt_addr_space_size(void);
+
 #endif /* XLAT_TABLES_PRIVATE_H */
diff --git a/plat/imx/common/imx8_psci.c b/plat/imx/common/imx8_psci.c
index 588d8b4..91d3370 100644
--- a/plat/imx/common/imx8_psci.c
+++ b/plat/imx/common/imx8_psci.c
@@ -32,8 +32,22 @@
 int imx_validate_power_state(unsigned int power_state,
 			 psci_power_state_t *req_state)
 {
-	/* TODO */
-	return PSCI_E_INVALID_PARAMS;
+	int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+	int pwr_type = psci_get_pstate_type(power_state);
+	int state_id = psci_get_pstate_id(power_state);
+
+	if (pwr_lvl > PLAT_MAX_PWR_LVL)
+		return PSCI_E_INVALID_PARAMS;
+
+	if (pwr_type == PSTATE_TYPE_POWERDOWN) {
+		req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE;
+		if (!state_id)
+			req_state->pwr_domain_state[MPIDR_AFFLVL1] = PLAT_MAX_RET_STATE;
+		else
+			req_state->pwr_domain_state[MPIDR_AFFLVL1] = PLAT_MAX_OFF_STATE;
+	}
+
+	return PSCI_E_SUCCESS;
 }
 
 void imx_get_sys_suspend_power_state(psci_power_state_t *req_state)
diff --git a/plat/imx/common/include/plat_imx8.h b/plat/imx/common/include/plat_imx8.h
index 952ad53..be99b97 100644
--- a/plat/imx/common/include/plat_imx8.h
+++ b/plat/imx/common/include/plat_imx8.h
@@ -10,6 +10,11 @@
 #include <drivers/arm/gicv3.h>
 #include <lib/psci/psci.h>
 
+struct plat_gic_ctx {
+	gicv3_redist_ctx_t rdist_ctx[PLATFORM_CORE_COUNT];
+	gicv3_dist_ctx_t dist_ctx;
+};
+
 unsigned int plat_calc_core_pos(uint64_t mpidr);
 void imx_mailbox_init(uintptr_t base_addr);
 void plat_gic_driver_init(void);
@@ -24,5 +29,7 @@
 			psci_power_state_t *req_state);
 void imx_get_sys_suspend_power_state(psci_power_state_t *req_state);
 bool imx_is_wakeup_src_irqsteer(void);
+void plat_gic_save(unsigned int proc_num, struct plat_gic_ctx *ctx);
+void plat_gic_restore(unsigned int proc_num, struct plat_gic_ctx *ctx);
 
 #endif /* PLAT_IMX8_H */
diff --git a/plat/imx/common/plat_imx8_gic.c b/plat/imx/common/plat_imx8_gic.c
index aec0b6c..27c525b 100644
--- a/plat/imx/common/plat_imx8_gic.c
+++ b/plat/imx/common/plat_imx8_gic.c
@@ -73,3 +73,19 @@
 {
 	gicv3_rdistif_init(plat_my_core_pos());
 }
+
+void plat_gic_save(unsigned int proc_num, struct plat_gic_ctx *ctx)
+{
+	/* save the gic rdist/dist context */
+	for (int i = 0; i < PLATFORM_CORE_COUNT; i++)
+		gicv3_rdistif_save(i, &ctx->rdist_ctx[i]);
+	gicv3_distif_save(&ctx->dist_ctx);
+}
+
+void plat_gic_restore(unsigned int proc_num, struct plat_gic_ctx *ctx)
+{
+	/* restore the gic rdist/dist context */
+	gicv3_distif_init_restore(&ctx->dist_ctx);
+	for (int i = 0; i < PLATFORM_CORE_COUNT; i++)
+		gicv3_rdistif_init_restore(i, &ctx->rdist_ctx[i]);
+}
diff --git a/plat/imx/common/sci/imx8_mu.c b/plat/imx/common/sci/imx8_mu.c
index 26d9bdf..66e956d 100644
--- a/plat/imx/common/sci/imx8_mu.c
+++ b/plat/imx/common/sci/imx8_mu.c
@@ -8,6 +8,21 @@
 
 #include "imx8_mu.h"
 
+void MU_Resume(uint32_t base)
+{
+	uint32_t reg, i;
+
+	reg = mmio_read_32(base + MU_ACR_OFFSET1);
+	/* Clear GIEn, RIEn, TIEn, GIRn and ABFn. */
+	reg &= ~(MU_CR_GIEn_MASK1 | MU_CR_RIEn_MASK1 | MU_CR_TIEn_MASK1
+			| MU_CR_GIRn_MASK1 | MU_CR_Fn_MASK1);
+	mmio_write_32(base + MU_ACR_OFFSET1, reg);
+
+	/* Enable all RX interrupts */
+	for (i = 0; i < MU_RR_COUNT; i++)
+		MU_EnableRxFullInt(base, i);
+}
+
 void MU_EnableRxFullInt(uint32_t base, uint32_t index)
 {
 	uint32_t reg = mmio_read_32(base + MU_ACR_OFFSET1);
diff --git a/plat/imx/common/sci/imx8_mu.h b/plat/imx/common/sci/imx8_mu.h
index 8c78877..edcac7b 100644
--- a/plat/imx/common/sci/imx8_mu.h
+++ b/plat/imx/common/sci/imx8_mu.h
@@ -33,3 +33,4 @@
 void MU_ReceiveMsg(uint32_t base, uint32_t regIndex, uint32_t *msg);
 void MU_EnableGeneralInt(uint32_t base, uint32_t index);
 void MU_EnableRxFullInt(uint32_t base, uint32_t index);
+void MU_Resume(uint32_t base);
diff --git a/plat/imx/imx8qm/imx8qm_bl31_setup.c b/plat/imx/imx8qm/imx8qm_bl31_setup.c
index a00695c..c76de64 100644
--- a/plat/imx/imx8qm/imx8qm_bl31_setup.c
+++ b/plat/imx/imx8qm/imx8qm_bl31_setup.c
@@ -49,11 +49,7 @@
 };
 
 static const mmap_region_t imx_mmap[] = {
-	MAP_REGION_FLAT(IMX_BOOT_UART_BASE, IMX_BOOT_UART_SIZE, MT_DEVICE | MT_RW),
-	MAP_REGION_FLAT(SC_IPC_BASE, SC_IPC_SIZE, MT_DEVICE | MT_RW),
-	MAP_REGION_FLAT(PLAT_GICD_BASE, PLAT_GICD_SIZE, MT_DEVICE | MT_RW),
-	MAP_REGION_FLAT(PLAT_GICR_BASE, PLAT_GICR_SIZE, MT_DEVICE | MT_RW),
-	MAP_REGION_FLAT(PLAT_CCI_BASE, PLAT_CCI_SIZE, MT_DEVICE | MT_RW),
+	MAP_REGION_FLAT(IMX_REG_BASE, IMX_REG_SIZE, MT_DEVICE | MT_RW),
 	{0}
 };
 
@@ -324,6 +320,10 @@
 
 	/* turn on MU1 for non-secure OS/Hypervisor */
 	sc_pm_set_resource_power_mode(ipc_handle, SC_R_MU_1A, SC_PM_PW_MODE_ON);
+	/* Turn on GPT_0's power & clock for non-secure OS/Hypervisor */
+	sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_ON);
+	sc_pm_clock_enable(ipc_handle, SC_R_GPT_0, SC_PM_CLK_PER, true, 0);
+	mmio_write_32(IMX_GPT_LPCG_BASE, mmio_read_32(IMX_GPT_LPCG_BASE) | (1 << 25));
 
 	/*
 	 * create new partition for non-secure OS/Hypervisor
diff --git a/plat/imx/imx8qm/imx8qm_psci.c b/plat/imx/imx8qm/imx8qm_psci.c
index 833048d..bdba37c 100644
--- a/plat/imx/imx8qm/imx8qm_psci.c
+++ b/plat/imx/imx8qm/imx8qm_psci.c
@@ -17,6 +17,8 @@
 #include <plat_imx8.h>
 #include <sci/sci.h>
 
+#include "../../common/sci/imx8_mu.h"
+
 #define CORE_PWR_STATE(state) \
 	((state)->pwr_domain_state[MPIDR_AFFLVL0])
 #define CLUSTER_PWR_STATE(state) \
@@ -29,44 +31,70 @@
 	SC_R_A53_3, SC_R_A72_0, SC_R_A72_1,
 };
 
+/* save gic dist/redist context when GIC is poewr down */
+static struct plat_gic_ctx imx_gicv3_ctx;
+static unsigned int gpt_lpcg, gpt_reg[2];
+
+static void imx_enable_irqstr_wakeup(void)
+{
+	uint32_t irq_mask;
+	gicv3_dist_ctx_t *dist_ctx = &imx_gicv3_ctx.dist_ctx;
+
+	/* put IRQSTR into ON mode */
+	sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_ON);
+
+	/* enable the irqsteer to handle wakeup irq */
+	mmio_write_32(IMX_WUP_IRQSTR_BASE, 0x1);
+	for (int i = 0; i < 15; i++) {
+		irq_mask = dist_ctx->gicd_isenabler[i];
+		mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x3c - 0x4 * i, irq_mask);
+	}
+
+	/* set IRQSTR low power mode */
+	if (imx_is_wakeup_src_irqsteer())
+		sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_STBY);
+	else
+		sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF);
+}
+
+static void imx_disable_irqstr_wakeup(void)
+{
+	/* put IRQSTR into ON from STBY mode */
+	sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_ON);
+
+	/* disable the irqsteer */
+	mmio_write_32(IMX_WUP_IRQSTR_BASE, 0x0);
+	for (int i = 0; i < 16; i++)
+		mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x4 + 0x4 * i, 0x0);
+
+	/* put IRQSTR into OFF mode */
+	sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF);
+}
+
 int imx_pwr_domain_on(u_register_t mpidr)
 {
 	int ret = PSCI_E_SUCCESS;
-	unsigned int cluster_id, cpu_id;
-
-	cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
-	cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+	unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+	unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
 
-	printf("imx_pwr_domain_on cluster_id %d, cpu_id %d\n", cluster_id, cpu_id);
+	sc_pm_set_resource_power_mode(ipc_handle, cluster_id == 0 ?
+		SC_R_A53 : SC_R_A72, SC_PM_PW_MODE_ON);
 
-	if (cluster_id == 0) {
-		sc_pm_set_resource_power_mode(ipc_handle, SC_R_A53,
-			SC_PM_PW_MODE_ON);
-		if (sc_pm_set_resource_power_mode(ipc_handle, ap_core_index[cpu_id],
-			SC_PM_PW_MODE_ON) != SC_ERR_NONE) {
-			ERROR("cluster0 core %d power on failed!\n", cpu_id);
-			ret = PSCI_E_INTERN_FAIL;
-		}
+	if (cluster_id == 1)
+		sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON);
 
-		if (sc_pm_cpu_start(ipc_handle, ap_core_index[cpu_id],
-			true, BL31_BASE) != SC_ERR_NONE) {
-			ERROR("boot cluster0 core %d failed!\n", cpu_id);
-			ret = PSCI_E_INTERN_FAIL;
-		}
-	} else {
-		sc_pm_set_resource_power_mode(ipc_handle, SC_R_A72,
-			SC_PM_PW_MODE_ON);
-		if (sc_pm_set_resource_power_mode(ipc_handle, ap_core_index[cpu_id + 4],
-			SC_PM_PW_MODE_ON) != SC_ERR_NONE) {
-			ERROR(" cluster1 core %d power on failed!\n", cpu_id);
-			ret = PSCI_E_INTERN_FAIL;
-		}
+	if (sc_pm_set_resource_power_mode(ipc_handle,
+		ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+		SC_PM_PW_MODE_ON) != SC_ERR_NONE) {
+		ERROR("core %d power on failed!\n", cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id);
+		ret = PSCI_E_INTERN_FAIL;
+	}
 
-		if (sc_pm_cpu_start(ipc_handle, ap_core_index[cpu_id + 4],
-			true, BL31_BASE) != SC_ERR_NONE) {
-			ERROR("boot cluster1 core %d failed!\n", cpu_id);
-			ret = PSCI_E_INTERN_FAIL;
-		}
+	if (sc_pm_cpu_start(ipc_handle,
+		ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+		true, BL31_BASE) != SC_ERR_NONE) {
+		ERROR("boot core %d failed!\n", cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id);
+		ret = PSCI_E_INTERN_FAIL;
 	}
 
 	return ret;
@@ -91,11 +119,14 @@
 
 	plat_gic_cpuif_disable();
 	sc_pm_req_cpu_low_power_mode(ipc_handle,
-		ap_core_index[cpu_id + cluster_id * 4],
-		SC_PM_PW_MODE_OFF,
-		SC_PM_WAKE_SRC_NONE);
-	if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
-		cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+		ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+		SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_NONE);
+
+	if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) {
+		cci_disable_snoop_dvm_reqs(cluster_id);
+		if (cluster_id == 1)
+			sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_OFF);
+	}
 	printf("turn off cluster:%d core:%d\n", cluster_id, cpu_id);
 }
 
@@ -105,24 +136,148 @@
 	unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
 	unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
 
-	plat_gic_cpuif_disable();
+	if (is_local_state_off(CORE_PWR_STATE(target_state))) {
+		plat_gic_cpuif_disable();
+		sc_pm_set_cpu_resume(ipc_handle,
+			ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+			true, BL31_BASE);
+		sc_pm_req_cpu_low_power_mode(ipc_handle,
+			ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+			SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_GIC);
+	} else {
+		dsb();
+		write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
+		isb();
+	}
 
-	cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+	if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) {
+		cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+		if (cluster_id == 1)
+			sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_OFF);
+	}
 
-	sc_pm_set_cpu_resume_addr(ipc_handle,
-		ap_core_index[cpu_id + cluster_id * 4], BL31_BASE);
-	sc_pm_req_cpu_low_power_mode(ipc_handle,
-		ap_core_index[cpu_id + cluster_id * 4],
-		SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_GIC);
+	if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) {
+		plat_gic_cpuif_disable();
+
+		/* save gic context */
+		plat_gic_save(cpu_id, &imx_gicv3_ctx);
+		/* enable the irqsteer for wakeup */
+		imx_enable_irqstr_wakeup();
+
+		cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+
+		/* Put GIC in LP mode. */
+		sc_pm_set_resource_power_mode(ipc_handle, SC_R_GIC, SC_PM_PW_MODE_OFF);
+		/* Save GPT clock and registers, then turn off its power */
+		gpt_lpcg = mmio_read_32(IMX_GPT_LPCG_BASE);
+		gpt_reg[0] = mmio_read_32(IMX_GPT_BASE);
+		gpt_reg[1] = mmio_read_32(IMX_GPT_BASE + 0x4);
+		sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_OFF);
+
+		sc_pm_req_low_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_OFF);
+		sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_OFF);
+		sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_OFF);
+
+		sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_DDR,
+			SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+		sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_DDR,
+			SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+		sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_MU,
+			SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+		sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_MU,
+			SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+		sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_INTERCONNECT,
+			SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+		sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_INTERCONNECT,
+			SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+		sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_OFF);
+
+		sc_pm_set_cpu_resume(ipc_handle,
+			ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+			true, BL31_BASE);
+		if (imx_is_wakeup_src_irqsteer())
+			sc_pm_req_cpu_low_power_mode(ipc_handle,
+				ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+				SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_IRQSTEER);
+		else
+			sc_pm_req_cpu_low_power_mode(ipc_handle,
+				ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+				SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_SCU);
+	}
 }
 
 void imx_domain_suspend_finish(const psci_power_state_t *target_state)
 {
 	u_register_t mpidr = read_mpidr_el1();
+	unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+	unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
 
-	cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+	/* check the system level status */
+	if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) {
+		MU_Resume(SC_IPC_BASE);
 
-	plat_gic_cpuif_enable();
+		sc_pm_req_cpu_low_power_mode(ipc_handle,
+			ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+			SC_PM_PW_MODE_ON, SC_PM_WAKE_SRC_GIC);
+
+		/* Put GIC/IRQSTR back to high power mode. */
+		sc_pm_set_resource_power_mode(ipc_handle, SC_R_GIC, SC_PM_PW_MODE_ON);
+
+		/* Turn GPT power and restore its clock and registers */
+		sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_ON);
+		sc_pm_clock_enable(ipc_handle, SC_R_GPT_0, SC_PM_CLK_PER, true, 0);
+		mmio_write_32(IMX_GPT_BASE, gpt_reg[0]);
+		mmio_write_32(IMX_GPT_BASE + 0x4, gpt_reg[1]);
+		mmio_write_32(IMX_GPT_LPCG_BASE, gpt_lpcg);
+
+		sc_pm_req_low_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_ON);
+		sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON);
+		sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_ON);
+
+		sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_DDR,
+			SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+		sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_DDR,
+			SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+		sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_MU,
+			SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+		sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_MU,
+			SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+		sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_INTERCONNECT,
+			SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+		sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_INTERCONNECT,
+			SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+		sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_ON);
+
+		cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+
+		/* restore gic context */
+		plat_gic_restore(cpu_id, &imx_gicv3_ctx);
+		/* disable the irqsteer wakeup */
+		imx_disable_irqstr_wakeup();
+
+		plat_gic_cpuif_enable();
+	}
+
+	/* check the cluster level power status */
+	if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) {
+		cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+		if (cluster_id == 1)
+			sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON);
+	}
+
+	/* check the core level power status */
+	if (is_local_state_off(CORE_PWR_STATE(target_state))) {
+		sc_pm_set_cpu_resume(ipc_handle,
+			ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+			false, BL31_BASE);
+		sc_pm_req_cpu_low_power_mode(ipc_handle,
+			ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+			SC_PM_PW_MODE_ON, SC_PM_WAKE_SRC_GIC);
+		plat_gic_cpuif_enable();
+	} else {
+		write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT));
+		isb();
+	}
 }
 
 int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint)
@@ -149,26 +304,23 @@
 	imx_mailbox_init(sec_entrypoint);
 	*psci_ops = &imx_plat_psci_ops;
 
-	/* Request low power mode for cluster/cci, only need to do once */
-	sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_OFF);
-	sc_pm_req_low_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_OFF);
-	sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_OFF);
+	/* make sure system sources power ON in low power mode by default */
+	sc_pm_req_low_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_ON);
+	sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON);
+	sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_ON);
 
-	/* Request RUN and LP modes for DDR, system interconnect etc. */
-	sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53,
-		SC_PM_SYS_IF_DDR, SC_PM_PW_MODE_ON, SC_PM_PW_MODE_STBY);
-	sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72,
-		SC_PM_SYS_IF_DDR, SC_PM_PW_MODE_ON, SC_PM_PW_MODE_STBY);
-	sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53,
-		SC_PM_SYS_IF_MU, SC_PM_PW_MODE_ON, SC_PM_PW_MODE_STBY);
-	sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72,
-		SC_PM_SYS_IF_MU, SC_PM_PW_MODE_ON, SC_PM_PW_MODE_STBY);
-	sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53,
-		SC_PM_SYS_IF_INTERCONNECT, SC_PM_PW_MODE_ON,
-		SC_PM_PW_MODE_STBY);
-	sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72,
-		SC_PM_SYS_IF_INTERCONNECT, SC_PM_PW_MODE_ON,
-		SC_PM_PW_MODE_STBY);
+	sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_DDR,
+		SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+	sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_DDR,
+		SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+	sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_MU,
+		SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+	sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_MU,
+		SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+	sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_INTERCONNECT,
+		SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+	sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_INTERCONNECT,
+		SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
 
 	return 0;
 }
diff --git a/plat/imx/imx8qm/include/platform_def.h b/plat/imx/imx8qm/include/platform_def.h
index 1d0bdf9..946be76 100644
--- a/plat/imx/imx8qm/include/platform_def.h
+++ b/plat/imx/imx8qm/include/platform_def.h
@@ -36,22 +36,22 @@
 #define BL31_LIMIT			0x80020000
 
 #define PLAT_GICD_BASE			0x51a00000
-#define PLAT_GICD_SIZE			0x10000
 #define PLAT_GICR_BASE			0x51b00000
-#define PLAT_GICR_SIZE			0xc0000
 #define PLAT_CCI_BASE			0x52090000
-#define PLAT_CCI_SIZE			0x10000
 #define CLUSTER0_CCI_SLVAE_IFACE	3
 #define CLUSTER1_CCI_SLVAE_IFACE	4
 #define IMX_BOOT_UART_BASE		0x5a060000
-#define IMX_BOOT_UART_SIZE		0x1000
 #define IMX_BOOT_UART_BAUDRATE		115200
 #define IMX_BOOT_UART_CLK_IN_HZ		24000000
 #define PLAT_CRASH_UART_BASE		IMX_BOOT_UART_BASE
 #define PLAT__CRASH_UART_CLK_IN_HZ	24000000
 #define IMX_CONSOLE_BAUDRATE		115200
 #define SC_IPC_BASE			0x5d1b0000
-#define SC_IPC_SIZE			0x10000
+#define IMX_GPT_LPCG_BASE		0x5d540000
+#define IMX_GPT_BASE			0x5d140000
+#define IMX_WUP_IRQSTR_BASE		0x51090000
+#define IMX_REG_BASE			0x50000000
+#define IMX_REG_SIZE			0x10000000
 
 #define COUNTER_FREQUENCY		8000000 /* 8MHz */
 
diff --git a/plat/imx/imx8qm/include/sec_rsrc.h b/plat/imx/imx8qm/include/sec_rsrc.h
index a623cd3..d16d051 100644
--- a/plat/imx/imx8qm/include/sec_rsrc.h
+++ b/plat/imx/imx8qm/include/sec_rsrc.h
@@ -19,12 +19,14 @@
 	SC_R_GIC_SMMU,
 	SC_R_CCI,
 	SC_R_SYSTEM,
-	SC_R_IRQSTR_SCU2
+	SC_R_IRQSTR_SCU2,
+	SC_R_GPT_0
 };
 
 /* resources that have register access for non-secure domain */
 sc_rsrc_t ns_access_allowed[] = {
 	SC_R_GIC,
 	SC_R_GIC_SMMU,
-	SC_R_CCI
+	SC_R_CCI,
+	SC_R_GPT_0
 };
diff --git a/plat/imx/imx8qx/imx8qx_bl31_setup.c b/plat/imx/imx8qx/imx8qx_bl31_setup.c
index c90794a..bfe4052 100644
--- a/plat/imx/imx8qx/imx8qx_bl31_setup.c
+++ b/plat/imx/imx8qx/imx8qx_bl31_setup.c
@@ -44,10 +44,7 @@
 			(SC_PAD_28FDSOI_PS_PD << PADRING_PULL_SHIFT))
 
 static const mmap_region_t imx_mmap[] = {
-	MAP_REGION_FLAT(IMX_BOOT_UART_BASE, IMX_BOOT_UART_SIZE, MT_DEVICE | MT_RW),
-	MAP_REGION_FLAT(SC_IPC_BASE, SC_IPC_SIZE, MT_DEVICE | MT_RW),
-	MAP_REGION_FLAT(PLAT_GICD_BASE, PLAT_GICD_SIZE, MT_DEVICE | MT_RW),
-	MAP_REGION_FLAT(PLAT_GICR_BASE, PLAT_GICR_SIZE, MT_DEVICE | MT_RW),
+	MAP_REGION_FLAT(IMX_REG_BASE, IMX_REG_SIZE, MT_DEVICE | MT_RW),
 	{0}
 };
 
@@ -281,6 +278,11 @@
 	/* Turn on MU1 for non-secure OS/Hypervisor */
 	sc_pm_set_resource_power_mode(ipc_handle, SC_R_MU_1A, SC_PM_PW_MODE_ON);
 
+	/* Turn on GPT_0's power & clock for non-secure OS/Hypervisor */
+	sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_ON);
+	sc_pm_clock_enable(ipc_handle, SC_R_GPT_0, SC_PM_CLK_PER, true, 0);
+	mmio_write_32(IMX_GPT0_LPCG_BASE, mmio_read_32(IMX_GPT0_LPCG_BASE) | (1 << 25));
+
 	/*
 	 * create new partition for non-secure OS/Hypervisor
 	 * uses global structs defined in sec_rsrc.h
diff --git a/plat/imx/imx8qx/imx8qx_psci.c b/plat/imx/imx8qx/imx8qx_psci.c
index 94c2e2b..aab3a2d 100644
--- a/plat/imx/imx8qx/imx8qx_psci.c
+++ b/plat/imx/imx8qx/imx8qx_psci.c
@@ -16,10 +16,52 @@
 #include <plat_imx8.h>
 #include <sci/sci.h>
 
+#include "../../common/sci/imx8_mu.h"
+
 const static int ap_core_index[PLATFORM_CORE_COUNT] = {
 	SC_R_A35_0, SC_R_A35_1, SC_R_A35_2, SC_R_A35_3
 };
 
+/* save gic dist/redist context when GIC is power down */
+static struct plat_gic_ctx imx_gicv3_ctx;
+static unsigned int gpt_lpcg, gpt_reg[2];
+
+static void imx_enable_irqstr_wakeup(void)
+{
+	uint32_t irq_mask;
+	gicv3_dist_ctx_t *dist_ctx = &imx_gicv3_ctx.dist_ctx;
+
+	/* put IRQSTR into ON mode */
+	sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_ON);
+
+	/* enable the irqsteer to handle wakeup irq */
+	mmio_write_32(IMX_WUP_IRQSTR_BASE, 0x1);
+	for (int i = 0; i < 15; i++) {
+		irq_mask = dist_ctx->gicd_isenabler[i];
+		mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x3c - 0x4 * i, irq_mask);
+	}
+
+	/* set IRQSTR low power mode */
+	if (imx_is_wakeup_src_irqsteer())
+		sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_STBY);
+	else
+		sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF);
+}
+
+static void imx_disable_irqstr_wakeup(void)
+{
+	/* Put IRQSTEER back to ON mode */
+	sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_ON);
+
+	/* disable the irqsteer */
+	mmio_write_32(IMX_WUP_IRQSTR_BASE, 0x0);
+	for (int i = 0; i < 16; i++)
+		mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x4 + 0x4 * i, 0x0);
+
+	/* Put IRQSTEER into OFF mode */
+	sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF);
+}
+
 int imx_pwr_domain_on(u_register_t mpidr)
 {
 	int ret = PSCI_E_SUCCESS;
@@ -71,11 +113,52 @@
 	u_register_t mpidr = read_mpidr_el1();
 	unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
 
-	plat_gic_cpuif_disable();
+	if (is_local_state_off(target_state->pwr_domain_state[MPIDR_AFFLVL0])) {
+		plat_gic_cpuif_disable();
+		sc_pm_set_cpu_resume(ipc_handle, ap_core_index[cpu_id], true, BL31_BASE);
+		sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
+			SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_GIC);
+	} else {
+		dsb();
+		write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
+		isb();
+	}
 
-	sc_pm_set_cpu_resume_addr(ipc_handle, ap_core_index[cpu_id], BL31_BASE);
-	sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
-		SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_GIC);
+	if (is_local_state_off(target_state->pwr_domain_state[MPIDR_AFFLVL1]))
+		sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_OFF);
+
+	if (is_local_state_retn(target_state->pwr_domain_state[PLAT_MAX_PWR_LVL])) {
+		plat_gic_cpuif_disable();
+
+		/* save gic context */
+		plat_gic_save(cpu_id, &imx_gicv3_ctx);
+		/* enable the irqsteer for wakeup */
+		imx_enable_irqstr_wakeup();
+
+		/* Save GPT clock and registers, then turn off its power */
+		gpt_lpcg = mmio_read_32(IMX_GPT0_LPCG_BASE);
+		gpt_reg[0] = mmio_read_32(IMX_GPT0_BASE);
+		gpt_reg[1] = mmio_read_32(IMX_GPT0_BASE + 0x4);
+		sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_OFF);
+
+		sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_OFF);
+		sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_DDR,
+			SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+		sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_MU,
+			SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+		sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_INTERCONNECT,
+			SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+
+		/* Put GIC in OFF mode. */
+		sc_pm_set_resource_power_mode(ipc_handle, SC_R_GIC, SC_PM_PW_MODE_OFF);
+		sc_pm_set_cpu_resume(ipc_handle, ap_core_index[cpu_id], true, BL31_BASE);
+		if (imx_is_wakeup_src_irqsteer())
+			sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
+				SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_IRQSTEER);
+		else
+			sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
+				SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_SCU);
+	}
 }
 
 void imx_domain_suspend_finish(const psci_power_state_t *target_state)
@@ -83,10 +166,51 @@
 	u_register_t mpidr = read_mpidr_el1();
 	unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
 
-	sc_pm_req_low_power_mode(ipc_handle, ap_core_index[cpu_id],
-		SC_PM_PW_MODE_ON);
+	if (is_local_state_retn(target_state->pwr_domain_state[PLAT_MAX_PWR_LVL])) {
+		MU_Resume(SC_IPC_BASE);
 
-	plat_gic_cpuif_enable();
+		sc_pm_req_low_power_mode(ipc_handle, ap_core_index[cpu_id], SC_PM_PW_MODE_ON);
+		sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
+			SC_PM_PW_MODE_ON, SC_PM_WAKE_SRC_GIC);
+
+		/* Put GIC back to high power mode. */
+		sc_pm_set_resource_power_mode(ipc_handle, SC_R_GIC, SC_PM_PW_MODE_ON);
+
+		/* restore gic context */
+		plat_gic_restore(cpu_id, &imx_gicv3_ctx);
+
+		/* Turn on GPT power and restore its clock and registers */
+		sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_ON);
+		sc_pm_clock_enable(ipc_handle, SC_R_GPT_0, SC_PM_CLK_PER, true, 0);
+		mmio_write_32(IMX_GPT0_BASE, gpt_reg[0]);
+		mmio_write_32(IMX_GPT0_BASE + 0x4, gpt_reg[1]);
+		mmio_write_32(IMX_GPT0_LPCG_BASE, gpt_lpcg);
+
+		sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_ON);
+		sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_DDR,
+			SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+		sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_MU,
+			SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+		sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_INTERCONNECT,
+			SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+
+		/* disable the irqsteer wakeup */
+		imx_disable_irqstr_wakeup();
+
+		plat_gic_cpuif_enable();
+	}
+
+	if (is_local_state_off(target_state->pwr_domain_state[MPIDR_AFFLVL1]))
+		sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_ON);
+
+	if (is_local_state_off(target_state->pwr_domain_state[MPIDR_AFFLVL0])) {
+		sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
+			SC_PM_PW_MODE_ON, SC_PM_WAKE_SRC_GIC);
+		plat_gic_cpuif_enable();
+	} else {
+		write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT));
+		isb();
+	}
 }
 
 static const plat_psci_ops_t imx_plat_psci_ops = {
@@ -108,17 +232,15 @@
 	imx_mailbox_init(sec_entrypoint);
 	*psci_ops = &imx_plat_psci_ops;
 
-	/* Request low power mode for A35 cluster, only need to do once */
-	sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_OFF);
+	/* make sure system sources power ON in low power mode by default */
+	sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_ON);
 
-	/* Request RUN and LP modes for DDR, system interconnect etc. */
-	sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35,
-		SC_PM_SYS_IF_DDR, SC_PM_PW_MODE_ON, SC_PM_PW_MODE_STBY);
-	sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35,
-		SC_PM_SYS_IF_MU, SC_PM_PW_MODE_ON, SC_PM_PW_MODE_STBY);
-	sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35,
-		SC_PM_SYS_IF_INTERCONNECT, SC_PM_PW_MODE_ON,
-		SC_PM_PW_MODE_STBY);
+	sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_DDR,
+		SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+	sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_MU,
+		SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+	sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_INTERCONNECT,
+		SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
 
 	return 0;
 }
diff --git a/plat/imx/imx8qx/include/platform_def.h b/plat/imx/imx8qx/include/platform_def.h
index 1239340..3a3fac8 100644
--- a/plat/imx/imx8qx/include/platform_def.h
+++ b/plat/imx/imx8qx/include/platform_def.h
@@ -37,18 +37,19 @@
 #define MAX_MMAP_REGIONS		8
 
 #define PLAT_GICD_BASE			0x51a00000
-#define PLAT_GICD_SIZE			0x10000
 #define PLAT_GICR_BASE			0x51b00000
-#define PLAT_GICR_SIZE			0xc0000
 #define IMX_BOOT_UART_BASE		0x5a060000
-#define IMX_BOOT_UART_SIZE		0x1000
 #define IMX_BOOT_UART_BAUDRATE		115200
 #define IMX_BOOT_UART_CLK_IN_HZ		24000000
 #define PLAT_CRASH_UART_BASE		IMX_BOOT_UART_BASE
 #define PLAT__CRASH_UART_CLK_IN_HZ	24000000
 #define IMX_CONSOLE_BAUDRATE		115200
 #define SC_IPC_BASE			0x5d1b0000
-#define SC_IPC_SIZE			0x10000
+#define IMX_GPT0_LPCG_BASE		0x5d540000
+#define IMX_GPT0_BASE			0x5d140000
+#define IMX_WUP_IRQSTR_BASE		0x51090000
+#define IMX_REG_BASE			0x50000000
+#define IMX_REG_SIZE			0x10000000
 
 #define COUNTER_FREQUENCY		8000000
 
diff --git a/plat/imx/imx8qx/include/sec_rsrc.h b/plat/imx/imx8qx/include/sec_rsrc.h
index 37c9f66..b7fe0e8 100644
--- a/plat/imx/imx8qx/include/sec_rsrc.h
+++ b/plat/imx/imx8qx/include/sec_rsrc.h
@@ -14,10 +14,12 @@
 	SC_R_A35_3,
 	SC_R_GIC,
 	SC_R_SYSTEM,
-	SC_R_IRQSTR_SCU2
+	SC_R_IRQSTR_SCU2,
+	SC_R_GPT_0
 };
 
 /* resources that have register access for non-secure domain */
 sc_rsrc_t ns_access_allowed[] = {
 	SC_R_GIC,
+	SC_R_GPT_0
 };
diff --git a/plat/rockchip/common/rockchip_gicv2.c b/plat/rockchip/common/rockchip_gicv2.c
index 222a882..8db2b30 100644
--- a/plat/rockchip/common/rockchip_gicv2.c
+++ b/plat/rockchip/common/rockchip_gicv2.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -22,11 +22,10 @@
 #pragma weak plat_rockchip_gic_pcpu_init
 
 /******************************************************************************
- * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
- * interrupts.
+ * List of interrupts.
  *****************************************************************************/
 static const interrupt_prop_t g0_interrupt_props[] = {
-	PLAT_RK_GICV2_G1S_IRQS
+	PLAT_RK_GICV2_G0_IRQS
 };
 
 /*
diff --git a/plat/rockchip/rk3328/rk3328_def.h b/plat/rockchip/rk3328/rk3328_def.h
index 4704a72..0ce13ad 100644
--- a/plat/rockchip/rk3328/rk3328_def.h
+++ b/plat/rockchip/rk3328/rk3328_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -131,15 +131,13 @@
 #define RK_IRQ_SEC_SGI_7	15
 
 /*
- * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
- * terminology. On a GICv2 system or mode, the lists will be merged and treated
- * as Group 0 interrupts.
+ * Define a list of Group 0 interrupts.
  */
-#define PLAT_RK_GICV2_G1S_IRQS						\
+#define PLAT_RK_GICV2_G0_IRQS						\
 	INTR_PROP_DESC(RK_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,	\
-		       GICV2_INTR_GROUP1, GIC_INTR_CFG_LEVEL),		\
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),		\
 	INTR_PROP_DESC(RK_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY,	\
-		       GICV2_INTR_GROUP1, GIC_INTR_CFG_LEVEL)
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL)
 
 #define SHARE_MEM_BASE          0x100000/* [1MB, 1MB+60K]*/
 #define SHARE_MEM_PAGE_NUM      15
diff --git a/plat/rockchip/rk3368/rk3368_def.h b/plat/rockchip/rk3368/rk3368_def.h
index a7be7c3..10ac77b 100644
--- a/plat/rockchip/rk3368/rk3368_def.h
+++ b/plat/rockchip/rk3368/rk3368_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -96,12 +96,10 @@
 #define RK_IRQ_SEC_SGI_7	15
 
 /*
- * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
- * terminology. On a GICv2 system or mode, the lists will be merged and treated
- * as Group 0 interrupts.
+ * Define a list of Group 0 interrupts.
  */
-#define PLAT_RK_GICV2_G1S_IRQS						\
+#define PLAT_RK_GICV2_G0_IRQS						\
 	INTR_PROP_DESC(RK_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,	\
-		       GICV2_INTR_GROUP1, GIC_INTR_CFG_LEVEL)
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL)
 
 #endif /* RK3368_DEF_H */
diff --git a/plat/rpi3/rpi3_io_storage.c b/plat/rpi3/rpi3_io_storage.c
index 7e66deb..49c6a76 100644
--- a/plat/rpi3/rpi3_io_storage.c
+++ b/plat/rpi3/rpi3_io_storage.c
@@ -133,11 +133,6 @@
 		(uintptr_t)&bl32_uuid_spec,
 		open_fip
 	},
-	[BL32_IMAGE_ID] = {
-		&fip_dev_handle,
-		(uintptr_t)&bl32_uuid_spec,
-		open_fip
-	},
 	[BL32_EXTRA1_IMAGE_ID] = {
 		&fip_dev_handle,
 		(uintptr_t)&bl32_extra1_uuid_spec,
diff --git a/plat/rpi3/rpi3_pm.c b/plat/rpi3/rpi3_pm.c
index 3a077d3..4f586b5 100644
--- a/plat/rpi3/rpi3_pm.c
+++ b/plat/rpi3/rpi3_pm.c
@@ -140,7 +140,7 @@
  * being turned off earlier. The target_state encodes the low power state that
  * each level has woken up from.
  ******************************************************************************/
-void rpi3_pwr_domain_on_finish(const psci_power_state_t *target_state)
+static void rpi3_pwr_domain_on_finish(const psci_power_state_t *target_state)
 {
 	assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
 					PLAT_LOCAL_STATE_OFF);
diff --git a/tools/fiptool/fiptool.c b/tools/fiptool/fiptool.c
index 0d4f929..80b498e 100644
--- a/tools/fiptool/fiptool.c
+++ b/tools/fiptool/fiptool.c
@@ -271,10 +271,10 @@
 	    &u->node[2], &u->node[3],
 	    &u->node[4], &u->node[5]);
 	/*
-	 * Given the format specifier above, we expect 11 items to be scanned
+	 * Given the format specifier above, we expect 16 items to be scanned
 	 * for a properly formatted UUID.
 	 */
-	if (n != 11)
+	if (n != 16)
 		log_errx("Invalid UUID: %s", s);
 }