Merge pull request #1917 from marex/arm/master/v3meagle-v2.0.1

rcar_gen3: plat: Add R-Car V3M support
diff --git a/.gitignore b/.gitignore
index 341308c..6b1e057 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,6 +22,7 @@
 tools/cert_create/cert_create
 tools/cert_create/cert_create.exe
 tools/marvell/doimage/doimage
+tools/meson/doimage
 tools/stm32image/*.o
 tools/stm32image/stm32image
 tools/stm32image/stm32image.exe
diff --git a/contributing.rst b/contributing.rst
index d98d5b9..6c94d9c 100644
--- a/contributing.rst
+++ b/contributing.rst
@@ -4,22 +4,18 @@
 Getting Started
 ---------------
 
--  Make sure you have a `GitHub account`_.
+-  Make sure you have a Github account and you are logged on
+   `developer.trustedfirmware.org`_.
 -  Create an `issue`_ for your work if one does not already exist. This gives
-   everyone visibility of whether others are working on something similar. Arm
-   licensees may contact Arm directly via their partner managers instead if
-   they prefer.
+   everyone visibility of whether others are working on something similar.
 
-   -  Note that the `issue`_ tracker for this project is in a separate
-      `issue tracking repository`_. Please follow the guidelines in that
-      repository.
    -  If you intend to include Third Party IP in your contribution, please
       raise a separate `issue`_ for this and ensure that the changes that
       include Third Party IP are made on a separate topic branch.
 
--  `Fork`_ `arm-trusted-firmware`_ on GitHub.
--  Clone the fork to your own machine.
--  Create a local topic branch based on the `arm-trusted-firmware`_ ``master``
+-  Clone `arm-trusted-firmware-a`_ on your own machine as suggested on the
+   `User Guide`_.
+-  Create a local topic branch based on the `arm-trusted-firmware-a`_ ``master``
    branch.
 
 Making Changes
@@ -27,12 +23,11 @@
 
 -  Make commits of logical units. See these general `Git guidelines`_ for
    contributing to a project.
--  Follow the `Linux coding style`_; this style is enforced for the TF-A
-   project (style errors only, not warnings).
+-  Follow the `Coding Guidelines`_.
 
    -  Use the checkpatch.pl script provided with the Linux source tree. A
-      Makefile target is provided for convenience (see section 2 in the
-      `User Guide`_).
+      Makefile target is provided for convenience (see the "Checking source code
+      style" section in the `User Guide`_).
 
 -  Keep the commits on topic. If you need to fix another bug or make another
    enhancement, please create a separate `issue`_ and address it on a separate
@@ -40,14 +35,11 @@
 -  Avoid long commit series. If you do have a long series, consider whether
    some commits should be squashed together or addressed in a separate topic.
 -  Make sure your commit messages are in the proper format. If a commit fixes
-   a GitHub `issue`_, include a reference (e.g.
-   "fixes arm-software/tf-issues#45"); this ensures the `issue`_ is
-   `automatically closed`_ when merged into the `arm-trusted-firmware`_ ``master``
-   branch.
+   an `issue`_, include a reference.
 -  Where appropriate, please update the documentation.
 
-   -  Consider whether the `User Guide`_, `Porting Guide`_, `Firmware Design`_ or
-      other in-source documentation needs updating.
+   -  Consider whether the `User Guide`_, `Porting Guide`_, `Firmware Design`_
+      or other in-source documentation needs updating.
    -  Ensure that each changed file has the correct copyright and license
       information. Files that entirely consist of contributions to this
       project should have a copyright notice and BSD-3-Clause SPDX license
@@ -70,55 +62,61 @@
       changes (and nothing else) in the last commit of the series. Otherwise,
       include the documentation changes within the single commit.
 
--  Please test your changes. As a minimum, ensure UEFI boots to the shell on
-   the Foundation FVP. See `Running the software on FVP`_ for more information.
+-  Please test your changes. As a minimum, ensure that Linux boots on the
+   Foundation FVP. See `Running the software on FVP`_ for more information. For
+   more extensive testing, consider running the `TF-A Tests`_ against your
+   patches.
 
 Submitting Changes
 ------------------
 
 -  Ensure that each commit in the series has at least one ``Signed-off-by:``
    line, using your real name and email address. The names in the
-   ``Signed-off-by:`` and ``Author:`` lines must match. If anyone else contributes
-   to the commit, they must also add their own ``Signed-off-by:`` line.
-   By adding this line the contributor certifies the contribution is made under
-   the terms of the `Developer Certificate of Origin (DCO)`_.
--  Push your local changes to your fork of the repository.
--  Submit a `pull request`_ to the `arm-trusted-firmware`_ ``integration`` branch.
+   ``Signed-off-by:`` and ``Author:`` lines must match. If anyone else
+   contributes to the commit, they must also add their own ``Signed-off-by:``
+   line. By adding this line the contributor certifies the contribution is made
+   under the terms of the `Developer Certificate of Origin (DCO)`_.
 
-   -  The changes in the `pull request`_ will then undergo further review and
-      testing by the `Maintainers`_. Any review comments will be made as
-      comments on the `pull request`_. This may require you to do some rework.
+   More details may be found in the `Gerrit Signed-off-by Lines guidelines`_.
+
+-  Ensure that each commit also has a unique ``Change-Id:`` line. If you have
+   cloned the repository with the "`Clone with commit-msg hook`" clone method
+   (as advised on the `User Guide`_), this should already be the case.
+
+   More details may be found in the `Gerrit Change-Ids documentation`_.
+
+-  Submit your changes for review at https://review.trustedfirmware.org
+   targeting the ``integration`` branch.
+
+   -  The changes will then undergo further review and testing by the
+      `Maintainers`_. Any review comments will be made directly on your patch.
+      This may require you to do some rework.
+
+   Refer to the `Gerrit Uploading Changes documentation`_ for more details.
 
 -  When the changes are accepted, the `Maintainers`_ will integrate them.
 
-   -  Typically, the `Maintainers`_ will merge the `pull request`_ into the
-      ``integration`` branch within the GitHub UI, creating a merge commit.
-   -  Please avoid creating merge commits in the `pull request`_ itself.
-   -  If the `pull request`_ is not based on a recent commit, the `Maintainers`_
-      may rebase it onto the ``master`` branch first, or ask you to do this.
-   -  If the `pull request`_ cannot be automatically merged, the `Maintainers`_
-      will ask you to rebase it onto the ``master`` branch.
-   -  After final integration testing, the `Maintainers`_ will push your merge
-      commit to the ``master`` branch. If a problem is found during integration,
-      the merge commit will be removed from the ``integration`` branch and the
-      `Maintainers`_ will ask you to create a new pull request to resolve the
+   -  Typically, the `Maintainers`_ will merge the changes into the
+      ``integration`` branch.
+   -  If the changes are not based on a sufficiently-recent commit, or if they
+      cannot be automatically rebased, then the `Maintainers`_ may rebase it on
+      the ``master`` branch or ask you to do so.
+   -  After final integration testing, the changes will make their way into the
+      ``master`` branch. If a problem is found during integration, the merge
+      commit will be removed from the ``integration`` branch and the
+      `Maintainers`_ will ask you to create a new patch set to resolve the
       problem.
-   -  Please do not delete your topic branch until it is safely merged into
-      the ``master`` branch.
 
 --------------
 
-*Copyright (c) 2013-2018, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.*
 
-.. _GitHub account: https://github.com/signup/free
-.. _issue: https://github.com/ARM-software/tf-issues/issues
-.. _issue tracking repository: https://github.com/ARM-software/tf-issues
-.. _Fork: https://help.github.com/articles/fork-a-repo
-.. _arm-trusted-firmware: https://github.com/ARM-software/arm-trusted-firmware
+.. _developer.trustedfirmware.org: https://developer.trustedfirmware.org
+.. _issue: https://developer.trustedfirmware.org/project/board/1/
+.. _arm-trusted-firmware-a: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
 .. _Git guidelines: http://git-scm.com/book/ch5-2.html
-.. _Linux coding style: https://github.com/torvalds/linux/blob/master/Documentation/process/coding-style.rst
+.. _Coding Guidelines: ./docs/coding-guidelines.rst
 .. _User Guide: ./docs/user-guide.rst
-.. _automatically closed: https://help.github.com/articles/closing-issues-via-commit-messages
 .. _Porting Guide: ./docs/porting-guide.rst
 .. _Firmware Design: ./docs/firmware-design.rst
 .. _license.rst: ./license.rst
@@ -126,4 +124,7 @@
 .. _Maintainers: ./maintainers.rst
 .. _Running the software on FVP: ./docs/user-guide.rst#user-content-running-the-software-on-fvp
 .. _Developer Certificate of Origin (DCO): ./dco.txt
-.. _pull request: https://help.github.com/articles/using-pull-requests
+.. _Gerrit Uploading Changes documentation: https://review.trustedfirmware.org/Documentation/user-upload.html
+.. _Gerrit Signed-off-by Lines guidelines: https://review.trustedfirmware.org/Documentation/user-signedoffby.html
+.. _Gerrit Change-Ids documentation: https://review.trustedfirmware.org/Documentation/user-changeid.html
+.. _TF-A Tests: https://git.trustedfirmware.org/TF-A/tf-a-tests.git/about/
diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst
index 7a4ff0e..6aa04f0 100644
--- a/docs/frequently-asked-questions.rst
+++ b/docs/frequently-asked-questions.rst
@@ -1,91 +1,79 @@
 Frequently-Asked Questions (FAQ)
 ================================
 
-How do I update a Pull Request?
--------------------------------
+How do I update my changes?
+---------------------------
 
-Often it is necessary to update a Pull Request (PR) before it is merged.  When
-you push to the source topic branch of an open PR, the PR is automatically
-updated with the new commits.
+Often it is necessary to update your patch set before it is merged. Refer to the
+`Gerrit Upload Patch Set documentation`_ on how to do so.
 
-If you need to modify existing commits in the PR (for example following review
-comments), then use the ``--force`` option when pushing. Any comments that apply
-to previous versions of the PR are retained in the PR. Sometimes it may be
-confusing whether comments apply to the current or a previous version of the PR,
-especially if there are several rounds of rework. In this case, you may be asked
-to close the PR and create a new one with the latest commits. The new PR should
-have a version appended to the name (e.g. "My topic v2") and you should create a
-link to the old PR so that reviewers can easily find previous versions.
+If you need to modify an existing patch set with multiple commits, refer to the
+`Gerrit Replace Changes documentation`_.
 
-When the PR is finally merged, you will be given the option of deleting your
-topic branch. It is recommended you delete this (and any previous topic branch
-versions) to avoid polluting your fork with obsolete branches.
-
-How long will my Pull Request take to merge?
---------------------------------------------
+How long will my changes take to merge into ``integration``?
+------------------------------------------------------------
 
 This can vary a lot, depending on:
 
-* How important the Pull Request (PR) is considered by the TF maintainers. Where
-  possible, you should indicate the required timescales for merging the PR and
-  the impact of any delay.
+* How important the patch set is considered by the TF maintainers. Where
+  possible, you should indicate the required timescales for merging the patch
+  set and the impact of any delay. Feel free to add a comment to your patch set
+  to get an estimate of when it will be merged.
 
-* The quality of the PR. PRs are likely to be merged quicker if they follow the
-  coding guidelines, have already had some code review, and have been
-  appropriately tested. Note that PRs from Arm engineers go through an internal
-  review process before appearing on GitHub, therefore may appear to be merged
-  more quickly.
+* The quality of the patch set. Patches are likely to be merged more quickly if
+  they follow the coding guidelines, have already had some code review, and have
+  been appropriately tested.
 
-* The impact of the PR. For example, a PR that changes a key generic API is
-  likely to receive much greater scrutiny than a local change to a specific
-  platform port.
+* The impact of the patch set. For example, a patch that changes a key generic
+  API is likely to receive much greater scrutiny than a local change to a
+  specific platform port.
 
 * How much opportunity for external review is required. For example, the TF
   maintainers may not wait for external review comments to merge trivial
   bug-fixes but may wait up to a week to merge major changes, or ones requiring
   feedback from specific parties.
 
-* How many other topics need to be integrated and the risk of conflict between
-  the topics.
+* How many other patch sets are waiting to be integrated and the risk of
+  conflict between the topics.
 
-* Is there a code freeze in place in preparation for the release. Please refer
-  the `release information`_ for more details.
+* If there is a code freeze in place in preparation for the release. Please
+  refer the `release information`_ for more details.
 
 * The workload of the TF maintainers.
 
-Feel free to add a comment to your PR to get an estimate of when it will
-be merged.
+How long will it take for my changes to go from ``integration`` to ``master``?
+------------------------------------------------------------------------------
 
-How long will it take for my merged Pull Request to go from ``integration`` to ``master``?
-------------------------------------------------------------------------------------------
-
-This depends on how many concurrent Pull Requests (PRs) are being processed at
-the same time. In simple cases where all potential regressions have already been
-tested, the delay will be less than 1 day.  If the TF maintainers are trying to
-merge several things over the course of a few days, it might take up to a week.
+This depends on how many concurrent patches are being processed at the same
+time. In simple cases where all potential regressions have already been tested,
+the delay will be less than 1 day. If the TF maintainers are trying to merge
+several things over the course of a few days, it might take up to a week.
 Typically, it will be 1-2 days.
 
 The worst case is if the TF maintainers are trying to make a release while also
-receiving PRs that will not be merged into the release. In this case, the PRs
-will be merged onto ``integration``, which will temporarily diverge from the
-release branch. The ``integration`` branch will be rebased onto ``master`` after
-the release, and then ``master`` will be fast-forwarded to ``integration`` 1-2
-days later. This whole process could take up 4 weeks. Please refer the `release
-information`_ for code freeze dates. The TF maintainers will inform the PR owner
-if this is going to happen.
+receiving patches that will not be merged into the release. In this case, the
+patches will be merged onto ``integration``, which will temporarily diverge from
+the release branch. The ``integration`` branch will be rebased onto ``master``
+after the release, and then ``master`` will be fast-forwarded to ``integration``
+1-2 days later. This whole process could take up 4 weeks. Please refer the
+`release information`_ for code freeze dates. The TF maintainers will inform the
+patch owner if this is going to happen.
 
-It is OK to create a PR based on commits that are only available in
-``integration`` or another PR, rather than ``master``. There is a risk that the
-dependency commits will change (for example due to PR rework or integration
-problems). If this happens, the dependent PR will need reworking.
+It is OK to create a patch based on commits that are only available in
+``integration`` or another patch set, rather than ``master``. There is a risk
+that the dependency commits will change (for example due to patch set rework or
+integration problems). If this happens, the dependent patch will need reworking.
 
-What are these strange comments in my Pull Request?
----------------------------------------------------
+What are these strange comments in my changes?
+----------------------------------------------
 
-For example, comments like "Can one of the admins verify this patch?" or "test
-this please". These are associated with Arm's Continuous Integration
-infrastructure and can be safely ignored. Those who are curious can see the
-documentation for `this Jenkins plugin`_ for more details.
+All the comments from ``ci-bot-user`` are associated with Continuous Integration
+infrastructure. The links published on the comment are not currently accessible,
+but would be after the CI has been transitioned to `trustedfirmware.org`_.
+Please refer to https://github.com/ARM-software/tf-issues/issues/681 for more
+details on the timelines.
 
 .. _release information: release-information.rst
-.. _this Jenkins plugin: https://wiki.jenkins-ci.org/display/JENKINS/GitHub+pull+request+builder+plugin
+.. _Gerrit Upload Patch Set documentation: https://review.trustedfirmware.org/Documentation/intro-user.html#upload-patch-set
+.. _Gerrit Replace Changes documentation: https://review.trustedfirmware.org/Documentation/user-upload.html#push_replace
+.. _trustedfirmware.org: https://www.trustedfirmware.org/
diff --git a/docs/plat/meson-gxl.rst b/docs/plat/meson-gxl.rst
new file mode 100644
index 0000000..feac2dd
--- /dev/null
+++ b/docs/plat/meson-gxl.rst
@@ -0,0 +1,27 @@
+Trusted Firmware-A for Amlogic Meson S905x (GXL)
+================================================
+
+The Amlogic Meson S905x is a SoC with a quad core Arm Cortex-A53 running at
+1.5Ghz. It also contains a Cortex-M3 used as SCP.
+
+This port is a minimal implementation of BL31 capable of booting mainline U-Boot
+and Linux:
+
+- SCPI support.
+- Basic PSCI support (CPU_ON, CPU_OFF, SYSTEM_RESET, SYSTEM_OFF). Note that CPU0
+  can't be turned off, so there is a workaround to hide this from the caller.
+- GICv2 driver set up.
+- Basic SIP services (read efuse data, enable/disable JTAG).
+
+In order to build it:
+
+::
+
+    CROSS_COMPILE=aarch64-linux-gnu- make DEBUG=1 PLAT=gxl
+
+This port has been tested on a Lepotato. After building it, follow the
+instructions in the `gxlimg repository` or `U-Boot repository`_, replacing the
+mentioned **bl31.img** by the one built from this port.
+
+.. _gxlimg repository: https://github.com/repk/gxlimg/blob/master/README
+.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/board/amlogic/p212/README.libretech-cc
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index 0848769..769ad45 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -81,11 +81,11 @@
 Getting the TF-A source code
 ----------------------------
 
-Download the TF-A source code from Github:
-
-::
-
-    git clone https://github.com/ARM-software/arm-trusted-firmware.git
+Clone the repository from the Gerrit server. The project details may be found
+on the `arm-trusted-firmware-a project page`_. We recommend the "`Clone with
+commit-msg hook`" clone method, which will setup the git commit hook that
+automatically generates and inserts appropriate `Change-Id:` lines in your
+commit messages.
 
 Checking source code style
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2101,6 +2101,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): https://developer.arm.com/products/software-development-tools/ds-5-development-studio
+.. _arm-trusted-firmware-a project page: https://review.trustedfirmware.org/admin/projects/TF-A/trusted-firmware-a
 .. _`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
@@ -2118,4 +2119,4 @@
 .. _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
-   _`Library at ROM`: romlib-design.rst
+.. _`Library at ROM`: romlib-design.rst
diff --git a/drivers/meson/gxl/crypto/sha_dma.c b/drivers/meson/gxl/crypto/sha_dma.c
new file mode 100644
index 0000000..565099c
--- /dev/null
+++ b/drivers/meson/gxl/crypto/sha_dma.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2019, Remi Pommarel <repk@triplefau.lt>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <arch_helpers.h>
+#include <lib/mmio.h>
+#include <crypto/sha_dma.h>
+
+#define AML_SHA_DMA_BASE 0xc883e000
+
+#define AML_SHA_DMA_DESC (AML_SHA_DMA_BASE + 0x08)
+#define AML_SHA_DMA_STATUS (AML_SHA_DMA_BASE + 0x18)
+
+#define ASD_MODE_SHA224 0x7
+#define ASD_MODE_SHA256 0x6
+
+/* SHA DMA descriptor */
+struct asd_desc {
+	uint32_t cfg;
+	uint32_t src;
+	uint32_t dst;
+};
+#define ASD_DESC_GET(x, msk, off) (((x) >> (off)) & (msk))
+#define ASD_DESC_SET(x, v, msk, off)					\
+	((x) = ((x) & ~((msk) << (off))) | (((v) & (msk)) << (off)))
+
+#define ASD_DESC_LEN_OFF 0
+#define ASD_DESC_LEN_MASK 0x1ffff
+#define ASD_DESC_LEN(d)							\
+	(ASD_DESC_GET((d)->cfg, ASD_DESC_LEN_MASK, ASD_DESC_LEN_OFF))
+#define ASD_DESC_LEN_SET(d, v)						\
+	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_LEN_MASK, ASD_DESC_LEN_OFF))
+
+#define ASD_DESC_IRQ_OFF 17
+#define ASD_DESC_IRQ_MASK 0x1
+#define ASD_DESC_IRQ(d)							\
+	(ASD_DESC_GET((d)->cfg, ASD_DESC_IRQ_MASK, ASD_DESC_IRQ_OFF))
+#define ASD_DESC_IRQ_SET(d, v)						\
+	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_IRQ_MASK, ASD_DESC_IRQ_OFF))
+
+#define ASD_DESC_EOD_OFF 18
+#define ASD_DESC_EOD_MASK 0x1
+#define ASD_DESC_EOD(d)							\
+	(ASD_DESC_GET((d)->cfg, ASD_DESC_EOD_MASK, ASD_DESC_EOD_OFF))
+#define ASD_DESC_EOD_SET(d, v)						\
+	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_EOD_MASK, ASD_DESC_EOD_OFF))
+
+#define ASD_DESC_LOOP_OFF 19
+#define ASD_DESC_LOOP_MASK 0x1
+#define ASD_DESC_LOOP(d)						\
+	(ASD_DESC_GET((d)->cfg, ASD_DESC_LOOP_MASK, ASD_DESC_LOOP_OFF))
+#define ASD_DESC_LOOP_SET(d, v)						\
+	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_LOOP_MASK, ASD_DESC_LOOP_OFF))
+
+#define ASD_DESC_MODE_OFF 20
+#define ASD_DESC_MODE_MASK 0xf
+#define ASD_DESC_MODE(d)						\
+	(ASD_DESC_GET((d)->cfg, ASD_DESC_MODE_MASK, ASD_DESC_MODE_OFF))
+#define ASD_DESC_MODE_SET(d, v)						\
+	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_MODE_MASK, ASD_DESC_MODE_OFF))
+
+#define ASD_DESC_BEGIN_OFF 24
+#define ASD_DESC_BEGIN_MASK 0x1
+#define ASD_DESC_BEGIN(d)						\
+	(ASD_DESC_GET((d)->cfg, ASD_DESC_BEGIN_MASK, ASD_DESC_BEGIN_OFF))
+#define ASD_DESC_BEGIN_SET(d, v)					\
+	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_BEGIN_MASK, ASD_DESC_BEGIN_OFF))
+
+#define ASD_DESC_END_OFF 25
+#define ASD_DESC_END_MASK 0x1
+#define ASD_DESC_END(d)							\
+	(ASD_DESC_GET((d)->cfg, ASD_DESC_END_MASK, ASD_DESC_END_OFF))
+#define ASD_DESC_END_SET(d, v)						\
+	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_END_MASK, ASD_DESC_END_OFF))
+
+#define ASD_DESC_OP_OFF 26
+#define ASD_DESC_OP_MASK 0x2
+#define ASD_DESC_OP(d)							\
+	(ASD_DESC_GET((d)->cfg, ASD_DESC_OP_MASK, ASD_DESC_OP_OFF))
+#define ASD_DESC_OP_SET(d, v)						\
+	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_OP_MASK, ASD_DESC_OP_OFF))
+
+#define ASD_DESC_ENCONLY_OFF 28
+#define ASD_DESC_ENCONLY_MASK 0x1
+#define ASD_DESC_ENCONLY(d)						\
+	(ASD_DESC_GET((d)->cfg, ASD_DESC_ENCONLY_MASK, ASD_DESC_ENCONLY_OFF))
+#define ASD_DESC_ENCONLY_SET(d, v)					\
+	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_ENCONLY_MASK, ASD_DESC_ENCONLY_OFF))
+
+#define ASD_DESC_BLOCK_OFF 29
+#define ASD_DESC_BLOCK_MASK 0x1
+#define ASD_DESC_BLOCK(d)						\
+	(ASD_DESC_GET((d)->cfg, ASD_DESC_BLOCK_MASK, ASD_DESC_BLOCK_OFF))
+#define ASD_DESC_BLOCK_SET(d, v)					\
+	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_BLOCK_MASK, ASD_DESC_BLOCK_OFF))
+
+#define ASD_DESC_ERR_OFF 30
+#define ASD_DESC_ERR_MASK 0x1
+#define ASD_DESC_ERR(d)						\
+	(ASD_DESC_GET((d)->cfg, ASD_DESC_ERR_MASK, ASD_DESC_ERR_OFF))
+#define ASD_DESC_ERR_SET(d, v)					\
+	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_ERR_MASK, ASD_DESC_ERR_OFF))
+
+#define ASD_DESC_OWNER_OFF 31
+#define ASD_DESC_OWNER_MASK 0x1
+#define ASD_DESC_OWNER(d)					\
+	(ASD_DESC_GET((d)->cfg, ASD_DESC_OWNER_MASK, ASD_DESC_OWNER_OFF))
+#define ASD_DESC_OWNER_SET(d, v)				\
+	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_OWNER_MASK, ASD_DESC_OWNER_OFF))
+
+static void asd_compute_sha(struct asd_ctx *ctx, void *data, size_t len,
+		int finalize)
+{
+	/* Make it cache line size aligned ? */
+	struct asd_desc desc = {
+		.src = (uint32_t)(uintptr_t)data,
+		.dst = (uint32_t)(uintptr_t)ctx->digest,
+	};
+
+	/* Check data address is 32bit compatible */
+	assert((uintptr_t)data == (uintptr_t)desc.src);
+	assert((uintptr_t)ctx->digest == (uintptr_t)desc.dst);
+	assert((uintptr_t)&desc == (uintptr_t)&desc);
+
+	ASD_DESC_LEN_SET(&desc, len);
+	ASD_DESC_OWNER_SET(&desc, 1);
+	ASD_DESC_ENCONLY_SET(&desc, 1);
+	ASD_DESC_EOD_SET(&desc, 1);
+	if (ctx->started == 0) {
+		ASD_DESC_BEGIN_SET(&desc, 1);
+		ctx->started = 1;
+	}
+	if (finalize) {
+		ASD_DESC_END_SET(&desc, 1);
+		ctx->started = 0;
+	}
+	if (ctx->mode == ASM_SHA224)
+		ASD_DESC_MODE_SET(&desc, ASD_MODE_SHA224);
+	else
+		ASD_DESC_MODE_SET(&desc, ASD_MODE_SHA256);
+
+	flush_dcache_range((uintptr_t)&desc, sizeof(desc));
+	flush_dcache_range((uintptr_t)data, len);
+
+	mmio_write_32(AML_SHA_DMA_STATUS, 0xf);
+	mmio_write_32(AML_SHA_DMA_DESC, ((uintptr_t)&desc) | 2);
+	while (mmio_read_32(AML_SHA_DMA_STATUS) == 0)
+		continue;
+	flush_dcache_range((uintptr_t)ctx->digest, SHA256_HASHSZ);
+}
+
+void asd_sha_update(struct asd_ctx *ctx, void *data, size_t len)
+{
+	size_t nr;
+
+	if (ctx->blocksz) {
+		nr = MIN(len, SHA256_BLOCKSZ - ctx->blocksz);
+		memcpy(ctx->block + ctx->blocksz, data, nr);
+		ctx->blocksz += nr;
+		len -= nr;
+		data += nr;
+	}
+
+	if (ctx->blocksz == SHA256_BLOCKSZ) {
+		asd_compute_sha(ctx, ctx->block, SHA256_BLOCKSZ, 0);
+		ctx->blocksz = 0;
+	}
+
+	asd_compute_sha(ctx, data, len & ~(SHA256_BLOCKSZ - 1), 0);
+	data += len & ~(SHA256_BLOCKSZ - 1);
+
+	if (len & (SHA256_BLOCKSZ - 1)) {
+		nr = len & (SHA256_BLOCKSZ - 1);
+		memcpy(ctx->block + ctx->blocksz, data, nr);
+		ctx->blocksz += nr;
+	}
+}
+
+void asd_sha_finalize(struct asd_ctx *ctx)
+{
+	asd_compute_sha(ctx, ctx->block, ctx->blocksz, 1);
+}
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index d3c5bea..d15851d 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -433,6 +433,9 @@
 #define TCR_TxSZ_MAX		ULL(39)
 #define TCR_TxSZ_MAX_TTST	ULL(48)
 
+#define TCR_T0SZ_SHIFT		U(0)
+#define TCR_T1SZ_SHIFT		U(16)
+
 /* (internal) physical address size bits in EL3/EL1 */
 #define TCR_PS_BITS_4GB		ULL(0x0)
 #define TCR_PS_BITS_64GB	ULL(0x1)
@@ -462,12 +465,32 @@
 #define TCR_SH_OUTER_SHAREABLE	(ULL(0x2) << 12)
 #define TCR_SH_INNER_SHAREABLE	(ULL(0x3) << 12)
 
+#define TCR_RGN1_INNER_NC	(ULL(0x0) << 24)
+#define TCR_RGN1_INNER_WBA	(ULL(0x1) << 24)
+#define TCR_RGN1_INNER_WT	(ULL(0x2) << 24)
+#define TCR_RGN1_INNER_WBNA	(ULL(0x3) << 24)
+
+#define TCR_RGN1_OUTER_NC	(ULL(0x0) << 26)
+#define TCR_RGN1_OUTER_WBA	(ULL(0x1) << 26)
+#define TCR_RGN1_OUTER_WT	(ULL(0x2) << 26)
+#define TCR_RGN1_OUTER_WBNA	(ULL(0x3) << 26)
+
+#define TCR_SH1_NON_SHAREABLE	(ULL(0x0) << 28)
+#define TCR_SH1_OUTER_SHAREABLE	(ULL(0x2) << 28)
+#define TCR_SH1_INNER_SHAREABLE	(ULL(0x3) << 28)
+
 #define TCR_TG0_SHIFT		U(14)
 #define TCR_TG0_MASK		ULL(3)
 #define TCR_TG0_4K		(ULL(0) << TCR_TG0_SHIFT)
 #define TCR_TG0_64K		(ULL(1) << TCR_TG0_SHIFT)
 #define TCR_TG0_16K		(ULL(2) << TCR_TG0_SHIFT)
 
+#define TCR_TG1_SHIFT		U(30)
+#define TCR_TG1_MASK		ULL(3)
+#define TCR_TG1_16K		(ULL(1) << TCR_TG1_SHIFT)
+#define TCR_TG1_4K		(ULL(2) << TCR_TG1_SHIFT)
+#define TCR_TG1_64K		(ULL(3) << TCR_TG1_SHIFT)
+
 #define TCR_EPD0_BIT		(ULL(1) << 7)
 #define TCR_EPD1_BIT		(ULL(1) << 23)
 
diff --git a/include/drivers/meson/gxl/crypto/sha_dma.h b/include/drivers/meson/gxl/crypto/sha_dma.h
new file mode 100644
index 0000000..52129a6
--- /dev/null
+++ b/include/drivers/meson/gxl/crypto/sha_dma.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019, Remi Pommarel <repk@triplefau.lt>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef SHA_DMA_H
+#define SHA_DMA_H
+
+#define SHA256_HASHSZ 32
+#define SHA256_BLOCKSZ 0x40
+
+enum ASD_MODE {
+	ASM_INVAL,
+	ASM_SHA256,
+	ASM_SHA224,
+};
+
+struct asd_ctx {
+	uint8_t digest[SHA256_HASHSZ];
+	uint8_t block[SHA256_BLOCKSZ];
+	size_t blocksz;
+	enum ASD_MODE mode;
+	uint8_t started;
+};
+
+static inline void asd_sha_init(struct asd_ctx *ctx, enum ASD_MODE mode)
+{
+	ctx->started = 0;
+	ctx->mode = mode;
+	ctx->blocksz = 0;
+}
+
+void asd_sha_update(struct asd_ctx *ctx, void *data, size_t len);
+void asd_sha_finalize(struct asd_ctx *ctx);
+
+#endif
diff --git a/lib/xlat_tables/aarch64/xlat_tables.c b/lib/xlat_tables/aarch64/xlat_tables.c
index e64fd3e..c86412c 100644
--- a/lib/xlat_tables/aarch64/xlat_tables.c
+++ b/lib/xlat_tables/aarch64/xlat_tables.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -174,12 +174,12 @@
 			/* Inner & outer non-cacheable non-shareable. */\
 			tcr = TCR_SH_NON_SHAREABLE |			\
 				TCR_RGN_OUTER_NC | TCR_RGN_INNER_NC |	\
-				(uint64_t) t0sz;			\
+				((uint64_t)t0sz << TCR_T0SZ_SHIFT);	\
 		} else {						\
 			/* Inner & outer WBWA & shareable. */		\
 			tcr = TCR_SH_INNER_SHAREABLE |			\
 				TCR_RGN_OUTER_WBA | TCR_RGN_INNER_WBA |	\
-				(uint64_t) t0sz;			\
+				((uint64_t)t0sz << TCR_T0SZ_SHIFT);	\
 		}							\
 		tcr |= _tcr_extra;					\
 		write_tcr_el##_el(tcr);					\
diff --git a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
index e7593dd..8eeeea1 100644
--- a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
@@ -248,7 +248,7 @@
 	 */
 	int t0sz = 64 - __builtin_ctzll(virtual_addr_space_size);
 
-	tcr = (uint64_t) t0sz;
+	tcr = (uint64_t)t0sz << TCR_T0SZ_SHIFT;
 
 	/*
 	 * Set the cacheability and shareability attributes for memory
diff --git a/maintainers.rst b/maintainers.rst
index a1ad137..52c3dac 100644
--- a/maintainers.rst
+++ b/maintainers.rst
@@ -34,6 +34,14 @@
 :F: drivers/meson/
 :F: plat/meson/gxbb/
 
+Amlogic Meson S905x (GXL) platform port
+---------------------------------------
+:M: Remi Pommarel <repk@triplefau.lt>
+:G: `remi-triplefault`_
+:F: docs/plat/meson-gxl.rst
+:F: drivers/meson/gxl
+:F: plat/meson/gxl/
+
 Armv7-A architecture port
 -------------------------
 :M: Etienne Carriere <etienne.carriere@linaro.org>
@@ -272,6 +280,7 @@
 .. _mtk09422: https://github.com/mtk09422
 .. _npoushin: https://github.com/npoushin
 .. _qoriq-open-source: https://github.com/qoriq-open-source
+.. _remi-triplefault: https://github.com/repk
 .. _rockchip-linux: https://github.com/rockchip-linux
 .. _shawnguo2: https://github.com/shawnguo2
 .. _sivadur: https://github.com/sivadur
diff --git a/plat/meson/gxl/aarch64/gxl_helpers.S b/plat/meson/gxl/aarch64/gxl_helpers.S
new file mode 100644
index 0000000..760d6c4
--- /dev/null
+++ b/plat/meson/gxl/aarch64/gxl_helpers.S
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <platform_def.h>
+
+	.globl	plat_crash_console_flush
+	.globl	plat_crash_console_init
+	.globl	plat_crash_console_putc
+	.globl	platform_mem_init
+	.globl	plat_is_my_cpu_primary
+	.globl	plat_my_core_pos
+	.globl	plat_reset_handler
+	.globl	plat_gxbb_calc_core_pos
+
+	/* -----------------------------------------------------
+	 * unsigned int plat_my_core_pos(void);
+	 * -----------------------------------------------------
+	 */
+func plat_my_core_pos
+	mrs	x0, mpidr_el1
+	b	plat_gxbb_calc_core_pos
+endfunc plat_my_core_pos
+
+	/* -----------------------------------------------------
+	 *  unsigned int plat_gxbb_calc_core_pos(u_register_t mpidr);
+	 * -----------------------------------------------------
+	 */
+func plat_gxbb_calc_core_pos
+	and	x0, x0, #MPIDR_CPU_MASK
+	ret
+endfunc plat_gxbb_calc_core_pos
+
+	/* -----------------------------------------------------
+	 * unsigned int plat_is_my_cpu_primary(void);
+	 * -----------------------------------------------------
+	 */
+func plat_is_my_cpu_primary
+	mrs	x0, mpidr_el1
+	and	x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+	cmp	x0, #GXBB_PRIMARY_CPU
+	cset	w0, eq
+	ret
+endfunc plat_is_my_cpu_primary
+
+	/* ---------------------------------------------
+	 * void platform_mem_init(void);
+	 * ---------------------------------------------
+	 */
+func platform_mem_init
+	ret
+endfunc platform_mem_init
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_init(void)
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_init
+	mov_imm	x0, GXBB_UART0_AO_BASE
+	mov_imm	x1, GXBB_UART0_AO_CLK_IN_HZ
+	mov_imm	x2, GXBB_UART_BAUDRATE
+	b	console_meson_init
+endfunc plat_crash_console_init
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_putc(int c)
+	 * Clobber list : x1, x2
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_putc
+	mov_imm	x1, GXBB_UART0_AO_BASE
+	b	console_meson_core_putc
+endfunc plat_crash_console_putc
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_flush()
+	 * Out : return -1 on error else return 0.
+	 * Clobber list : x0, x1
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_flush
+	mov_imm	x0, GXBB_UART0_AO_BASE
+	b	console_meson_core_flush
+endfunc plat_crash_console_flush
+
+	/* ---------------------------------------------
+	 * void plat_reset_handler(void);
+	 * ---------------------------------------------
+	 */
+func plat_reset_handler
+	ret
+endfunc plat_reset_handler
diff --git a/plat/meson/gxl/gxl_bl31_setup.c b/plat/meson/gxl/gxl_bl31_setup.c
new file mode 100644
index 0000000..7fe0529
--- /dev/null
+++ b/plat/meson/gxl/gxl_bl31_setup.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/bl_common.h>
+#include <drivers/arm/gicv2.h>
+#include <common/interrupt_props.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+
+#include "gxl_private.h"
+
+/*
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL31 from BL2.
+ */
+static entry_point_info_t bl33_image_ep_info;
+static image_info_t bl30_image_info;
+static image_info_t bl301_image_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+	entry_point_info_t *next_image_info;
+
+	assert(type == NON_SECURE);
+
+	next_image_info = &bl33_image_ep_info;
+
+	/* None of the images can have 0x0 as the entrypoint. */
+	if (next_image_info->pc != 0U) {
+		return next_image_info;
+	} else {
+		return NULL;
+	}
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before
+ * they are lost (potentially). This needs to be done before the MMU is
+ * initialized so that the memory layout can be used while creating page
+ * tables. BL2 has flushed this information to memory, so we are guaranteed
+ * to pick up good data.
+ ******************************************************************************/
+struct gxl_bl31_param {
+	param_header_t h;
+	image_info_t *bl31_image_info;
+	entry_point_info_t *bl32_ep_info;
+	image_info_t *bl32_image_info;
+	entry_point_info_t *bl33_ep_info;
+	image_info_t *bl33_image_info;
+	image_info_t *scp_image_info[];
+};
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+				u_register_t arg2, u_register_t arg3)
+{
+	struct gxl_bl31_param *from_bl2;
+
+	/* Initialize the console to provide early debug support */
+	gxbb_console_init();
+
+	/*
+	 * In debug builds, we pass a special value in 'arg1' to verify platform
+	 * parameters from BL2 to BL31. In release builds it's not used.
+	 */
+	assert(arg1 == GXBB_BL31_PLAT_PARAM_VAL);
+
+	/* Check that params passed from BL2 are not NULL. */
+	from_bl2 = (struct gxl_bl31_param *) arg0;
+
+	/* Check params passed from BL2 are not NULL. */
+	assert(from_bl2 != NULL);
+	assert(from_bl2->h.type == PARAM_BL31);
+	assert(from_bl2->h.version >= VERSION_1);
+
+	/*
+	 * Copy BL33 entry point information. It is stored in Secure RAM, in
+	 * BL2's address space.
+	 */
+	bl33_image_ep_info = *from_bl2->bl33_ep_info;
+
+	if (bl33_image_ep_info.pc == 0U) {
+		ERROR("BL31: BL33 entrypoint not obtained from BL2\n");
+		panic();
+	}
+
+	bl30_image_info = *from_bl2->scp_image_info[0];
+	bl301_image_info = *from_bl2->scp_image_info[1];
+}
+
+void bl31_plat_arch_setup(void)
+{
+	gxbb_setup_page_tables();
+
+	enable_mmu_el3(0);
+}
+
+static inline void gxl_scp_boot(void)
+{
+	scpi_upload_scp_fw(bl30_image_info.image_base,
+			bl30_image_info.image_size, 0);
+	scpi_upload_scp_fw(bl301_image_info.image_base,
+			bl301_image_info.image_size, 1);
+}
+
+/*******************************************************************************
+ * GICv2 driver setup information
+ ******************************************************************************/
+static const interrupt_prop_t gxbb_interrupt_props[] = {
+	INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+};
+
+static const gicv2_driver_data_t gxbb_gic_data = {
+	.gicd_base = GXBB_GICD_BASE,
+	.gicc_base = GXBB_GICC_BASE,
+	.interrupt_props = gxbb_interrupt_props,
+	.interrupt_props_num = ARRAY_SIZE(gxbb_interrupt_props),
+};
+
+void bl31_platform_setup(void)
+{
+	mhu_secure_init();
+
+	gicv2_driver_init(&gxbb_gic_data);
+	gicv2_distif_init();
+	gicv2_pcpu_distif_init();
+	gicv2_cpuif_enable();
+
+	gxl_scp_boot();
+
+	gxbb_thermal_unknown();
+}
diff --git a/plat/meson/gxl/gxl_common.c b/plat/meson/gxl/gxl_common.c
new file mode 100644
index 0000000..e3bd604
--- /dev/null
+++ b/plat/meson/gxl/gxl_common.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/ep_info.h>
+#include <bl31/interrupt_mgmt.h>
+#include <meson_console.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+#include <stdint.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+/*******************************************************************************
+ * Platform memory map regions
+ ******************************************************************************/
+#define MAP_NSDRAM0	MAP_REGION_FLAT(GXBB_NSDRAM0_BASE,		\
+					GXBB_NSDRAM0_SIZE,		\
+					MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_NSDRAM1	MAP_REGION_FLAT(GXBB_NSDRAM1_BASE,		\
+					GXBB_NSDRAM1_SIZE,		\
+					MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_SEC_DEVICE0	MAP_REGION_FLAT(GXBB_SEC_DEVICE0_BASE,		\
+					GXBB_SEC_DEVICE0_SIZE,		\
+					MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE1	MAP_REGION_FLAT(GXBB_SEC_DEVICE1_BASE,		\
+					GXBB_SEC_DEVICE1_SIZE,		\
+					MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_TZRAM	MAP_REGION_FLAT(GXBB_TZRAM_BASE,		\
+					GXBB_TZRAM_SIZE,		\
+					MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE2	MAP_REGION_FLAT(GXBB_SEC_DEVICE2_BASE,		\
+					GXBB_SEC_DEVICE2_SIZE,		\
+					MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE3	MAP_REGION_FLAT(GXBB_SEC_DEVICE3_BASE,		\
+					GXBB_SEC_DEVICE3_SIZE,		\
+					MT_DEVICE | MT_RW | MT_SECURE)
+
+static const mmap_region_t gxbb_mmap[] = {
+	MAP_NSDRAM0,
+	MAP_NSDRAM1,
+	MAP_SEC_DEVICE0,
+	MAP_SEC_DEVICE1,
+	MAP_TZRAM,
+	MAP_SEC_DEVICE2,
+	MAP_SEC_DEVICE3,
+	{0}
+};
+
+/*******************************************************************************
+ * Per-image regions
+ ******************************************************************************/
+#define MAP_BL31	MAP_REGION_FLAT(BL31_BASE,			\
+				BL31_END - BL31_BASE,			\
+				MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MAP_BL_CODE	MAP_REGION_FLAT(BL_CODE_BASE,			\
+				BL_CODE_END - BL_CODE_BASE,		\
+				MT_CODE | MT_SECURE)
+
+#define MAP_BL_RO_DATA	MAP_REGION_FLAT(BL_RO_DATA_BASE,		\
+				BL_RO_DATA_END - BL_RO_DATA_BASE,	\
+				MT_RO_DATA | MT_SECURE)
+
+#define MAP_BL_COHERENT	MAP_REGION_FLAT(BL_COHERENT_RAM_BASE,		\
+				BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, \
+				MT_DEVICE | MT_RW | MT_SECURE)
+
+/*******************************************************************************
+ * Function that sets up the translation tables.
+ ******************************************************************************/
+void gxbb_setup_page_tables(void)
+{
+#if IMAGE_BL31
+	const mmap_region_t gxbb_bl_mmap[] = {
+		MAP_BL31,
+		MAP_BL_CODE,
+		MAP_BL_RO_DATA,
+#if USE_COHERENT_MEM
+		MAP_BL_COHERENT,
+#endif
+		{0}
+	};
+#endif
+
+	mmap_add(gxbb_bl_mmap);
+
+	mmap_add(gxbb_mmap);
+
+	init_xlat_tables();
+}
+
+/*******************************************************************************
+ * Function that sets up the console
+ ******************************************************************************/
+static console_meson_t gxbb_console;
+
+void gxbb_console_init(void)
+{
+	int rc = console_meson_register(GXBB_UART0_AO_BASE,
+					GXBB_UART0_AO_CLK_IN_HZ,
+					GXBB_UART_BAUDRATE,
+					&gxbb_console);
+	if (rc == 0) {
+		/*
+		 * The crash console doesn't use the multi console API, it uses
+		 * the core console functions directly. It is safe to call panic
+		 * and let it print debug information.
+		 */
+		panic();
+	}
+
+	console_set_scope(&gxbb_console.console,
+			  CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
+}
+
+/*******************************************************************************
+ * Function that returns the system counter frequency
+ ******************************************************************************/
+unsigned int plat_get_syscnt_freq2(void)
+{
+	uint32_t val;
+
+	val = mmio_read_32(GXBB_SYS_CPU_CFG7);
+	val &= 0xFDFFFFFF;
+	mmio_write_32(GXBB_SYS_CPU_CFG7, val);
+
+	val = mmio_read_32(GXBB_AO_TIMESTAMP_CNTL);
+	val &= 0xFFFFFE00;
+	mmio_write_32(GXBB_AO_TIMESTAMP_CNTL, val);
+
+	return GXBB_OSC24M_CLK_IN_HZ;
+}
diff --git a/plat/meson/gxl/gxl_def.h b/plat/meson/gxl/gxl_def.h
new file mode 100644
index 0000000..ada2656
--- /dev/null
+++ b/plat/meson/gxl/gxl_def.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GXBB_DEF_H
+#define GXBB_DEF_H
+
+#include <lib/utils_def.h>
+
+/*******************************************************************************
+ * System oscillator
+ ******************************************************************************/
+#define GXBB_OSC24M_CLK_IN_HZ			ULL(24000000) /* 24 MHz */
+
+/*******************************************************************************
+ * Memory regions
+ ******************************************************************************/
+#define GXBB_NSDRAM0_BASE			UL(0x01000000)
+#define GXBB_NSDRAM0_SIZE			UL(0x0F000000)
+
+#define GXBB_NSDRAM1_BASE			UL(0x10000000)
+#define GXBB_NSDRAM1_SIZE			UL(0x00100000)
+
+#define BL31_BASE				UL(0x05100000)
+#define BL31_SIZE				UL(0x000C0000)
+#define BL31_LIMIT				(BL31_BASE + BL31_SIZE)
+
+/* Shared memory used for SMC services */
+#define GXBB_SHARE_MEM_INPUT_BASE		UL(0x050FE000)
+#define GXBB_SHARE_MEM_OUTPUT_BASE		UL(0x050FF000)
+
+#define GXBB_SEC_DEVICE0_BASE			UL(0xC0000000)
+#define GXBB_SEC_DEVICE0_SIZE			UL(0x09000000)
+
+#define GXBB_SEC_DEVICE1_BASE			UL(0xD0040000)
+#define GXBB_SEC_DEVICE1_SIZE			UL(0x00008000)
+
+#define GXBB_TZRAM_BASE				UL(0xD9000000)
+#define GXBB_TZRAM_SIZE				UL(0x00014000)
+/* Top 0xC000 bytes (up to 0xD9020000) used by BL2 */
+
+/* Mailboxes */
+#define GXBB_MHU_SECURE_SCP_TO_AP_PAYLOAD	UL(0xD9013800)
+#define GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD	UL(0xD9013A00)
+#define GXBB_PSCI_MAILBOX_BASE			UL(0xD9013F00)
+
+// * [	 1K]	0xD901_3800 - 0xD901_3BFF	Secure Mailbox (3)
+// * [	 1K]	0xD901_3400 - 0xD901_37FF	High Mailbox (2) *
+// * [	 1K]	0xD901_3000 - 0xD901_33FF	High Mailbox (1) *
+
+#define GXBB_TZROM_BASE				UL(0xD9040000)
+#define GXBB_TZROM_SIZE				UL(0x00010000)
+
+#define GXBB_SEC_DEVICE2_BASE			UL(0xDA000000)
+#define GXBB_SEC_DEVICE2_SIZE			UL(0x00200000)
+
+#define GXBB_SEC_DEVICE3_BASE			UL(0xDA800000)
+#define GXBB_SEC_DEVICE3_SIZE			UL(0x00200000)
+
+/*******************************************************************************
+ * GIC-400 and interrupt handling related constants
+ ******************************************************************************/
+#define GXBB_GICD_BASE				UL(0xC4301000)
+#define GXBB_GICC_BASE				UL(0xC4302000)
+
+#define IRQ_SEC_PHY_TIMER			29
+
+#define IRQ_SEC_SGI_0				8
+#define IRQ_SEC_SGI_1				9
+#define IRQ_SEC_SGI_2				10
+#define IRQ_SEC_SGI_3				11
+#define IRQ_SEC_SGI_4				12
+#define IRQ_SEC_SGI_5				13
+#define IRQ_SEC_SGI_6				14
+#define IRQ_SEC_SGI_7				15
+
+/*******************************************************************************
+ * UART definitions
+ ******************************************************************************/
+#define GXBB_UART0_AO_BASE			UL(0xC81004C0)
+#define GXBB_UART0_AO_CLK_IN_HZ			GXBB_OSC24M_CLK_IN_HZ
+#define GXBB_UART_BAUDRATE			U(115200)
+
+/*******************************************************************************
+ * Memory-mapped I/O Registers
+ ******************************************************************************/
+#define GXBB_AO_TIMESTAMP_CNTL			UL(0xC81000B4)
+
+#define GXBB_SYS_CPU_CFG7			UL(0xC8834664)
+
+#define GXBB_AO_RTI_STATUS_REG3			UL(0xDA10001C)
+
+#define GXBB_HIU_MAILBOX_SET_0			UL(0xDA83C404)
+#define GXBB_HIU_MAILBOX_STAT_0			UL(0xDA83C408)
+#define GXBB_HIU_MAILBOX_CLR_0			UL(0xDA83C40C)
+#define GXBB_HIU_MAILBOX_SET_3			UL(0xDA83C428)
+#define GXBB_HIU_MAILBOX_STAT_3			UL(0xDA83C42C)
+#define GXBB_HIU_MAILBOX_CLR_3			UL(0xDA83C430)
+
+/*******************************************************************************
+ * System Monitor Call IDs and arguments
+ ******************************************************************************/
+#define GXBB_SM_GET_SHARE_MEM_INPUT_BASE	U(0x82000020)
+#define GXBB_SM_GET_SHARE_MEM_OUTPUT_BASE	U(0x82000021)
+
+#define GXBB_SM_EFUSE_READ			U(0x82000030)
+#define GXBB_SM_EFUSE_USER_MAX			U(0x82000033)
+
+#define GXBB_SM_JTAG_ON				U(0x82000040)
+#define GXBB_SM_JTAG_OFF			U(0x82000041)
+
+#define GXBB_JTAG_STATE_ON			U(0)
+#define GXBB_JTAG_STATE_OFF			U(1)
+
+#define GXBB_JTAG_M3_AO				U(0)
+#define GXBB_JTAG_M3_EE				U(1)
+#define GXBB_JTAG_A53_AO			U(2)
+#define GXBB_JTAG_A53_EE			U(3)
+
+#endif /* GXBB_DEF_H */
diff --git a/plat/meson/gxl/gxl_efuse.c b/plat/meson/gxl/gxl_efuse.c
new file mode 100644
index 0000000..b17d1b8
--- /dev/null
+++ b/plat/meson/gxl/gxl_efuse.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include "gxl_private.h"
+
+#define EFUSE_BASE	0x140
+#define EFUSE_SIZE	0xC0
+
+uint64_t gxbb_efuse_read(void *dst, uint32_t offset, uint32_t size)
+{
+	if ((uint64_t)(offset + size) > (uint64_t)EFUSE_SIZE)
+		return 0;
+
+	return scpi_efuse_read(dst, offset + EFUSE_BASE, size);
+}
+
+uint64_t gxbb_efuse_user_max(void)
+{
+	return EFUSE_SIZE;
+}
diff --git a/plat/meson/gxl/gxl_mhu.c b/plat/meson/gxl/gxl_mhu.c
new file mode 100644
index 0000000..4c1d5b6
--- /dev/null
+++ b/plat/meson/gxl/gxl_mhu.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+static DEFINE_BAKERY_LOCK(mhu_lock);
+
+void mhu_secure_message_start(void)
+{
+	bakery_lock_get(&mhu_lock);
+
+	while (mmio_read_32(GXBB_HIU_MAILBOX_STAT_3) != 0)
+		;
+}
+
+void mhu_secure_message_send(uint32_t msg)
+{
+	mmio_write_32(GXBB_HIU_MAILBOX_SET_3, msg);
+
+	while (mmio_read_32(GXBB_HIU_MAILBOX_STAT_3) != 0)
+		;
+}
+
+uint32_t mhu_secure_message_wait(void)
+{
+	uint32_t val;
+
+	do {
+		val = mmio_read_32(GXBB_HIU_MAILBOX_STAT_0);
+	} while (val == 0);
+
+	return val;
+}
+
+void mhu_secure_message_end(void)
+{
+	mmio_write_32(GXBB_HIU_MAILBOX_CLR_0, 0xFFFFFFFF);
+
+	bakery_lock_release(&mhu_lock);
+}
+
+void mhu_secure_init(void)
+{
+	bakery_lock_init(&mhu_lock);
+
+	mmio_write_32(GXBB_HIU_MAILBOX_CLR_3, 0xFFFFFFFF);
+}
diff --git a/plat/meson/gxl/gxl_pm.c b/plat/meson/gxl/gxl_pm.c
new file mode 100644
index 0000000..d9b69ef
--- /dev/null
+++ b/plat/meson/gxl/gxl_pm.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <drivers/console.h>
+#include <common/debug.h>
+#include <errno.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <lib/psci/psci.h>
+
+#include "gxl_private.h"
+
+#define SCPI_POWER_ON		0
+#define SCPI_POWER_RETENTION	1
+#define SCPI_POWER_OFF		3
+
+#define SCPI_SYSTEM_SHUTDOWN	0
+#define SCPI_SYSTEM_REBOOT	1
+
+static uintptr_t gxbb_sec_entrypoint;
+static volatile uint32_t gxbb_cpu0_go;
+
+static void gxbb_program_mailbox(u_register_t mpidr, uint64_t value)
+{
+	unsigned int core = plat_gxbb_calc_core_pos(mpidr);
+	uintptr_t cpu_mailbox_addr = GXBB_PSCI_MAILBOX_BASE + (core << 4);
+
+	mmio_write_64(cpu_mailbox_addr, value);
+	flush_dcache_range(cpu_mailbox_addr, sizeof(uint64_t));
+}
+
+static void __dead2 gxbb_system_reset(void)
+{
+	INFO("BL31: PSCI_SYSTEM_RESET\n");
+
+	uint32_t status = mmio_read_32(GXBB_AO_RTI_STATUS_REG3);
+
+	NOTICE("BL31: Reboot reason: 0x%x\n", status);
+
+	status &= 0xFFFF0FF0;
+
+	console_flush();
+
+	mmio_write_32(GXBB_AO_RTI_STATUS_REG3, status);
+
+	int ret = scpi_sys_power_state(SCPI_SYSTEM_REBOOT);
+
+	if (ret != 0) {
+		ERROR("BL31: PSCI_SYSTEM_RESET: SCP error: %u\n", ret);
+		panic();
+	}
+
+	wfi();
+
+	ERROR("BL31: PSCI_SYSTEM_RESET: Operation not handled\n");
+	panic();
+}
+
+static void __dead2 gxbb_system_off(void)
+{
+	INFO("BL31: PSCI_SYSTEM_OFF\n");
+
+	unsigned int ret = scpi_sys_power_state(SCPI_SYSTEM_SHUTDOWN);
+
+	if (ret != 0) {
+		ERROR("BL31: PSCI_SYSTEM_OFF: SCP error %u\n", ret);
+		panic();
+	}
+
+	gxbb_program_mailbox(read_mpidr_el1(), 0);
+
+	wfi();
+
+	ERROR("BL31: PSCI_SYSTEM_OFF: Operation not handled\n");
+	panic();
+}
+
+static int32_t gxbb_pwr_domain_on(u_register_t mpidr)
+{
+	unsigned int core = plat_gxbb_calc_core_pos(mpidr);
+
+	/* CPU0 can't be turned OFF, emulate it with a WFE loop */
+	if (core == GXBB_PRIMARY_CPU) {
+		VERBOSE("BL31: Releasing CPU0 from wait loop...\n");
+
+		gxbb_cpu0_go = 1;
+		flush_dcache_range((uintptr_t)&gxbb_cpu0_go,
+				sizeof(gxbb_cpu0_go));
+		dsb();
+		isb();
+
+		sev();
+
+		return PSCI_E_SUCCESS;
+	}
+
+	gxbb_program_mailbox(mpidr, gxbb_sec_entrypoint);
+	scpi_set_css_power_state(mpidr,
+				 SCPI_POWER_ON, SCPI_POWER_ON, SCPI_POWER_ON);
+	dmbsy();
+	sev();
+
+	return PSCI_E_SUCCESS;
+}
+
+static void gxbb_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	unsigned int core = plat_gxbb_calc_core_pos(read_mpidr_el1());
+
+	assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+					PLAT_LOCAL_STATE_OFF);
+
+	if (core == GXBB_PRIMARY_CPU) {
+		gxbb_cpu0_go = 0;
+		flush_dcache_range((uintptr_t)&gxbb_cpu0_go,
+				sizeof(gxbb_cpu0_go));
+		dsb();
+		isb();
+	}
+
+	gicv2_pcpu_distif_init();
+	gicv2_cpuif_enable();
+}
+
+static void gxbb_pwr_domain_off(const psci_power_state_t *target_state)
+{
+	u_register_t mpidr = read_mpidr_el1();
+	unsigned int core = plat_gxbb_calc_core_pos(mpidr);
+	uintptr_t addr = GXBB_PSCI_MAILBOX_BASE + 8 + (core << 4);
+
+	mmio_write_32(addr, 0xFFFFFFFF);
+	flush_dcache_range(addr, sizeof(uint32_t));
+
+	gicv2_cpuif_disable();
+
+	/* CPU0 can't be turned OFF, emulate it with a WFE loop */
+	if (core == GXBB_PRIMARY_CPU)
+		return;
+
+	scpi_set_css_power_state(mpidr,
+				 SCPI_POWER_OFF, SCPI_POWER_ON, SCPI_POWER_ON);
+}
+
+static void __dead2 gxbb_pwr_domain_pwr_down_wfi(const psci_power_state_t
+						 *target_state)
+{
+	unsigned int core = plat_gxbb_calc_core_pos(read_mpidr_el1());
+
+	/* CPU0 can't be turned OFF, emulate it with a WFE loop */
+	if (core == GXBB_PRIMARY_CPU) {
+		VERBOSE("BL31: CPU0 entering wait loop...\n");
+
+		while (gxbb_cpu0_go == 0)
+			wfe();
+
+		VERBOSE("BL31: CPU0 resumed.\n");
+
+		write_rmr_el3(RMR_EL3_RR_BIT | RMR_EL3_AA64_BIT);
+	}
+
+	dsbsy();
+
+	for (;;)
+		wfi();
+}
+
+/*******************************************************************************
+ * Platform handlers and setup function.
+ ******************************************************************************/
+static const plat_psci_ops_t gxbb_ops = {
+	.pwr_domain_on			= gxbb_pwr_domain_on,
+	.pwr_domain_on_finish		= gxbb_pwr_domain_on_finish,
+	.pwr_domain_off			= gxbb_pwr_domain_off,
+	.pwr_domain_pwr_down_wfi	= gxbb_pwr_domain_pwr_down_wfi,
+	.system_off			= gxbb_system_off,
+	.system_reset			= gxbb_system_reset,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	gxbb_sec_entrypoint = sec_entrypoint;
+	*psci_ops = &gxbb_ops;
+	gxbb_cpu0_go = 0;
+	return 0;
+}
diff --git a/plat/meson/gxl/gxl_private.h b/plat/meson/gxl/gxl_private.h
new file mode 100644
index 0000000..913cbf6
--- /dev/null
+++ b/plat/meson/gxl/gxl_private.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GXBB_PRIVATE_H
+#define GXBB_PRIVATE_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+/* Utility functions */
+unsigned int plat_gxbb_calc_core_pos(u_register_t mpidr);
+void gxbb_console_init(void);
+void gxbb_setup_page_tables(void);
+
+/* MHU functions */
+void mhu_secure_message_start(void);
+void mhu_secure_message_send(uint32_t msg);
+uint32_t mhu_secure_message_wait(void);
+void mhu_secure_message_end(void);
+void mhu_secure_init(void);
+
+/* SCPI functions */
+void scpi_set_css_power_state(u_register_t mpidr, uint32_t cpu_state,
+			      uint32_t cluster_state, uint32_t css_state);
+uint32_t scpi_sys_power_state(uint64_t system_state);
+void scpi_jtag_set_state(uint32_t state, uint8_t select);
+uint32_t scpi_efuse_read(void *dst, uint32_t base, uint32_t size);
+void scpi_unknown_thermal(uint32_t arg0, uint32_t arg1,
+			  uint32_t arg2, uint32_t arg3);
+void scpi_upload_scp_fw(uintptr_t addr, size_t size, int send);
+
+/* Peripherals */
+void gxbb_thermal_unknown(void);
+uint64_t gxbb_efuse_read(void *dst, uint32_t offset, uint32_t size);
+uint64_t gxbb_efuse_user_max(void);
+
+#endif /* GXBB_PRIVATE_H */
diff --git a/plat/meson/gxl/gxl_scpi.c b/plat/meson/gxl/gxl_scpi.c
new file mode 100644
index 0000000..13d6524
--- /dev/null
+++ b/plat/meson/gxl/gxl_scpi.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <string.h>
+#include <crypto/sha_dma.h>
+
+#include "gxl_private.h"
+
+#define SIZE_SHIFT	20
+#define SIZE_MASK	0x1FF
+#define SIZE_FWBLK	0x200UL
+
+/*
+ * Note: The Amlogic SCP firmware uses the legacy SCPI protocol.
+ */
+#define SCPI_CMD_SET_CSS_POWER_STATE	0x04
+#define SCPI_CMD_SET_SYS_POWER_STATE	0x08
+
+#define SCPI_CMD_JTAG_SET_STATE		0xC0
+#define SCPI_CMD_EFUSE_READ		0xC2
+
+#define SCPI_CMD_COPY_FW 0xd4
+#define SCPI_CMD_SET_FW_ADDR 0xd3
+#define SCPI_CMD_FW_SIZE 0xd2
+
+static inline uint32_t scpi_cmd(uint32_t command, uint32_t size)
+{
+	return command | (size << SIZE_SHIFT);
+}
+
+static void scpi_secure_message_send(uint32_t command, uint32_t size)
+{
+	mhu_secure_message_send(scpi_cmd(command, size));
+}
+
+uint32_t scpi_secure_message_receive(void **message_out, size_t *size_out)
+{
+	uint32_t response = mhu_secure_message_wait();
+
+	size_t size = (response >> SIZE_SHIFT) & SIZE_MASK;
+
+	response &= ~(SIZE_MASK << SIZE_SHIFT);
+
+	if (size_out != NULL)
+		*size_out = size;
+
+	if (message_out != NULL)
+		*message_out = (void *)GXBB_MHU_SECURE_SCP_TO_AP_PAYLOAD;
+
+	return response;
+}
+
+void scpi_set_css_power_state(u_register_t mpidr, uint32_t cpu_state,
+			      uint32_t cluster_state, uint32_t css_state)
+{
+	uint32_t state = (mpidr & 0x0F) | /* CPU ID */
+			 ((mpidr & 0xF00) >> 4) | /* Cluster ID */
+			 (cpu_state << 8) |
+			 (cluster_state << 12) |
+			 (css_state << 16);
+
+	mhu_secure_message_start();
+	mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD, state);
+	mhu_secure_message_send(scpi_cmd(SCPI_CMD_SET_CSS_POWER_STATE, 4));
+	mhu_secure_message_wait();
+	mhu_secure_message_end();
+}
+
+uint32_t scpi_sys_power_state(uint64_t system_state)
+{
+	uint32_t *response;
+	size_t size;
+
+	mhu_secure_message_start();
+	mmio_write_8(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD, system_state);
+	mhu_secure_message_send(scpi_cmd(SCPI_CMD_SET_SYS_POWER_STATE, 1));
+	scpi_secure_message_receive((void *)&response, &size);
+	mhu_secure_message_end();
+
+	return *response;
+}
+
+void scpi_jtag_set_state(uint32_t state, uint8_t select)
+{
+	assert(state <= GXBB_JTAG_STATE_OFF);
+
+	if (select > GXBB_JTAG_A53_EE) {
+		WARN("BL31: Invalid JTAG select (0x%x).\n", select);
+		return;
+	}
+
+	mhu_secure_message_start();
+	mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD,
+		      (state << 8) | (uint32_t)select);
+	mhu_secure_message_send(scpi_cmd(SCPI_CMD_JTAG_SET_STATE, 4));
+	mhu_secure_message_wait();
+	mhu_secure_message_end();
+}
+
+uint32_t scpi_efuse_read(void *dst, uint32_t base, uint32_t size)
+{
+	uint32_t *response;
+	size_t resp_size;
+
+	if (size > 0x1FC)
+		return 0;
+
+	mhu_secure_message_start();
+	mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD, base);
+	mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD + 4, size);
+	mhu_secure_message_send(scpi_cmd(SCPI_CMD_EFUSE_READ, 8));
+	scpi_secure_message_receive((void *)&response, &resp_size);
+	mhu_secure_message_end();
+
+	/*
+	 * response[0] is the size of the response message.
+	 * response[1 ... N] are the contents.
+	 */
+	if (*response != 0)
+		memcpy(dst, response + 1, *response);
+
+	return *response;
+}
+
+void scpi_unknown_thermal(uint32_t arg0, uint32_t arg1,
+			  uint32_t arg2, uint32_t arg3)
+{
+	mhu_secure_message_start();
+	mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x0, arg0);
+	mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x4, arg1);
+	mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x8, arg2);
+	mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0xC, arg3);
+	mhu_secure_message_send(scpi_cmd(0xC3, 16));
+	mhu_secure_message_wait();
+	mhu_secure_message_end();
+}
+
+static inline void scpi_copy_scp_data(uint8_t *data, size_t len)
+{
+	void *dst = (void *)GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD;
+	size_t sz;
+
+	mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD, len);
+	scpi_secure_message_send(SCPI_CMD_FW_SIZE, len);
+	mhu_secure_message_wait();
+
+	for (sz = 0; sz < len; sz += SIZE_FWBLK) {
+		memcpy(dst, data + sz, MIN(SIZE_FWBLK, len - sz));
+		mhu_secure_message_send(SCPI_CMD_COPY_FW);
+	}
+}
+
+static inline void scpi_set_scp_addr(uint64_t addr, size_t len)
+{
+	volatile uint64_t *dst = (uint64_t *)GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD;
+
+	/*
+	 * It is ok as GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD is mapped as
+	 * non cachable
+	 */
+	*dst = addr;
+	scpi_secure_message_send(SCPI_CMD_SET_FW_ADDR, sizeof(addr));
+	mhu_secure_message_wait();
+
+	mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD, len);
+	scpi_secure_message_send(SCPI_CMD_FW_SIZE, len);
+	mhu_secure_message_wait();
+}
+
+static inline void scpi_send_fw_hash(uint8_t hash[], size_t len)
+{
+	void *dst = (void *)GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD;
+
+	memcpy(dst, hash, len);
+	mhu_secure_message_send(0xd0);
+	mhu_secure_message_send(0xd1);
+	mhu_secure_message_send(0xd5);
+	mhu_secure_message_end();
+}
+
+/**
+ * Upload a FW to SCP.
+ *
+ * @param addr: firmware data address
+ * @param size: size of firmware
+ * @param send: If set, actually copy the firmware in SCP memory otherwise only
+ *  send the firmware address.
+ */
+void scpi_upload_scp_fw(uintptr_t addr, size_t size, int send)
+{
+	struct asd_ctx ctx;
+
+	asd_sha_init(&ctx, ASM_SHA256);
+	asd_sha_update(&ctx, (void *)addr, size);
+	asd_sha_finalize(&ctx);
+
+	mhu_secure_message_start();
+	if (send == 0)
+		scpi_set_scp_addr(addr, size);
+	else
+		scpi_copy_scp_data((void *)addr, size);
+
+	scpi_send_fw_hash(ctx.digest, sizeof(ctx.digest));
+}
diff --git a/plat/meson/gxl/gxl_sip_svc.c b/plat/meson/gxl/gxl_sip_svc.c
new file mode 100644
index 0000000..74fbc80
--- /dev/null
+++ b/plat/meson/gxl/gxl_sip_svc.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+#include <common/runtime_svc.h>
+#include <stdint.h>
+
+#include "gxl_private.h"
+
+/*******************************************************************************
+ * This function is responsible for handling all SiP calls
+ ******************************************************************************/
+static uintptr_t gxbb_sip_handler(uint32_t smc_fid,
+				  u_register_t x1, u_register_t x2,
+				  u_register_t x3, u_register_t x4,
+				  void *cookie, void *handle,
+				  u_register_t flags)
+{
+	switch (smc_fid) {
+
+	case GXBB_SM_GET_SHARE_MEM_INPUT_BASE:
+		SMC_RET1(handle, GXBB_SHARE_MEM_INPUT_BASE);
+
+	case GXBB_SM_GET_SHARE_MEM_OUTPUT_BASE:
+		SMC_RET1(handle, GXBB_SHARE_MEM_OUTPUT_BASE);
+
+	case GXBB_SM_EFUSE_READ:
+	{
+		void *dst = (void *)GXBB_SHARE_MEM_OUTPUT_BASE;
+		uint64_t ret = gxbb_efuse_read(dst, (uint32_t)x1, x2);
+
+		SMC_RET1(handle, ret);
+	}
+	case GXBB_SM_EFUSE_USER_MAX:
+		SMC_RET1(handle,  gxbb_efuse_user_max());
+
+	case GXBB_SM_JTAG_ON:
+		scpi_jtag_set_state(GXBB_JTAG_STATE_ON, x1);
+		SMC_RET1(handle, 0);
+
+	case GXBB_SM_JTAG_OFF:
+		scpi_jtag_set_state(GXBB_JTAG_STATE_OFF, x1);
+		SMC_RET1(handle, 0);
+
+	default:
+		ERROR("BL31: Unhandled SIP SMC: 0x%08x\n", smc_fid);
+		break;
+	}
+
+	SMC_RET1(handle, SMC_UNK);
+}
+
+DECLARE_RT_SVC(
+	gxbb_sip_handler,
+
+	OEN_SIP_START,
+	OEN_SIP_END,
+	SMC_TYPE_FAST,
+	NULL,
+	gxbb_sip_handler
+);
diff --git a/plat/meson/gxl/gxl_thermal.c b/plat/meson/gxl/gxl_thermal.c
new file mode 100644
index 0000000..3af1c6d
--- /dev/null
+++ b/plat/meson/gxl/gxl_thermal.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include "gxl_private.h"
+
+static int32_t modules_initialized = -1;
+
+/*******************************************************************************
+ * Unknown commands related to something thermal-related
+ ******************************************************************************/
+void gxbb_thermal_unknown(void)
+{
+	uint16_t ret;
+
+	if (modules_initialized == -1) {
+		scpi_efuse_read(&ret, 0, 2);
+		modules_initialized = ret;
+	}
+
+	scpi_unknown_thermal(10, 2,  /* thermal */
+			     13, 1); /* thermalver */
+}
diff --git a/plat/meson/gxl/gxl_topology.c b/plat/meson/gxl/gxl_topology.c
new file mode 100644
index 0000000..cca3ead
--- /dev/null
+++ b/plat/meson/gxl/gxl_topology.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <platform_def.h>
+#include <stdint.h>
+
+#include "gxl_private.h"
+
+/* The power domain tree descriptor */
+static unsigned char power_domain_tree_desc[] = {
+	/* Number of root nodes */
+	PLATFORM_CLUSTER_COUNT,
+	/* Number of children for the first node */
+	PLATFORM_CLUSTER0_CORE_COUNT
+};
+
+/*******************************************************************************
+ * This function returns the ARM default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+	unsigned int cluster_id, cpu_id;
+
+	mpidr &= MPIDR_AFFINITY_MASK;
+	if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
+		return -1;
+
+	cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+	cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+	if (cluster_id >= PLATFORM_CLUSTER_COUNT)
+		return -1;
+
+	if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER)
+		return -1;
+
+	return plat_gxbb_calc_core_pos(mpidr);
+}
diff --git a/plat/meson/gxl/include/plat_macros.S b/plat/meson/gxl/include/plat_macros.S
new file mode 100644
index 0000000..c721c21
--- /dev/null
+++ b/plat/meson/gxl/include/plat_macros.S
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <drivers/arm/gicv2.h>
+#include <platform_def.h>
+
+.section .rodata.gic_reg_name, "aS"
+
+gicc_regs:
+	.asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+gicd_pend_reg:
+	.asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n"
+newline:
+	.asciz "\n"
+spacer:
+	.asciz ":\t\t0x"
+
+	/* ---------------------------------------------
+	 * The below required platform porting macro
+	 * prints out relevant GIC and CCI registers
+	 * whenever an unhandled exception is taken in
+	 * BL31.
+	 * Clobbers: x0 - x10, x16, x17, sp
+	 * ---------------------------------------------
+	 */
+	.macro plat_crash_print_regs
+
+	/* GICC registers */
+
+	mov_imm	x17, GXBB_GICC_BASE
+
+	adr	x6, gicc_regs
+	ldr	w8, [x17, #GICC_HPPIR]
+	ldr	w9, [x17, #GICC_AHPPIR]
+	ldr	w10, [x17, #GICC_CTLR]
+	bl	str_in_crash_buf_print
+
+	/* GICD registers */
+
+	mov_imm	x16, GXBB_GICD_BASE
+
+	add	x7, x16, #GICD_ISPENDR
+	adr	x4, gicd_pend_reg
+	bl	asm_print_str
+
+gicd_ispendr_loop:
+	sub	x4, x7, x16
+	cmp	x4, #0x280
+	b.eq	exit_print_gic_regs
+	bl	asm_print_hex
+
+	adr	x4, spacer
+	bl	asm_print_str
+
+	ldr	x4, [x7], #8
+	bl	asm_print_hex
+
+	adr	x4, newline
+	bl	asm_print_str
+	b	gicd_ispendr_loop
+exit_print_gic_regs:
+
+	.endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/meson/gxl/include/platform_def.h b/plat/meson/gxl/include/platform_def.h
new file mode 100644
index 0000000..b32ec56
--- /dev/null
+++ b/plat/meson/gxl/include/platform_def.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <lib/utils_def.h>
+
+#include "../gxl_def.h"
+
+#define PLATFORM_LINKER_FORMAT		"elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH		aarch64
+
+/* Special value used to verify platform parameters from BL2 to BL31 */
+#define GXBB_BL31_PLAT_PARAM_VAL	ULL(0x0F1E2D3C4B5A6978)
+
+#define PLATFORM_STACK_SIZE		UL(0x1000)
+
+#define PLATFORM_MAX_CPUS_PER_CLUSTER	U(4)
+#define PLATFORM_CLUSTER_COUNT		U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT	PLATFORM_MAX_CPUS_PER_CLUSTER
+#define PLATFORM_CORE_COUNT		PLATFORM_CLUSTER0_CORE_COUNT
+
+#define GXBB_PRIMARY_CPU		U(0)
+
+#define PLAT_MAX_PWR_LVL		MPIDR_AFFLVL1
+#define PLAT_NUM_PWR_DOMAINS		(PLATFORM_CLUSTER_COUNT + \
+					 PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_RET_STATE		U(1)
+#define PLAT_MAX_OFF_STATE		U(2)
+
+/* Local power state for power domains in Run state. */
+#define PLAT_LOCAL_STATE_RUN		U(0)
+/* Local power state for retention. Valid only for CPU power domains */
+#define PLAT_LOCAL_STATE_RET		U(1)
+/* Local power state for power-down. Valid for CPU and cluster power domains. */
+#define PLAT_LOCAL_STATE_OFF		U(2)
+
+/*
+ * Macros used to parse state information from State-ID if it is using the
+ * recommended encoding for State-ID.
+ */
+#define PLAT_LOCAL_PSTATE_WIDTH		U(4)
+#define PLAT_LOCAL_PSTATE_MASK		((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1)
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_SHIFT		U(6)
+#define CACHE_WRITEBACK_GRANULE		(U(1) << CACHE_WRITEBACK_SHIFT)
+
+/* Memory-related defines */
+#define PLAT_PHY_ADDR_SPACE_SIZE	(ULL(1) << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(ULL(1) << 32)
+
+#define MAX_MMAP_REGIONS		12
+#define MAX_XLAT_TABLES			6
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/meson/gxl/platform.mk b/plat/meson/gxl/platform.mk
new file mode 100644
index 0000000..ea4aead
--- /dev/null
+++ b/plat/meson/gxl/platform.mk
@@ -0,0 +1,94 @@
+#
+# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include lib/xlat_tables_v2/xlat_tables.mk
+
+DOIMAGEPATH		?=	tools/meson
+DOIMAGETOOL		?=	${DOIMAGEPATH}/doimage
+
+PLAT_INCLUDES		:=	-Iinclude/drivers/meson/		\
+				-Iinclude/drivers/meson/gxl		\
+				-Iplat/meson/gxl/include
+
+GXBB_GIC_SOURCES	:=	drivers/arm/gic/common/gic_common.c	\
+				drivers/arm/gic/v2/gicv2_main.c		\
+				drivers/arm/gic/v2/gicv2_helpers.c	\
+				plat/common/plat_gicv2.c
+
+PLAT_BL_COMMON_SOURCES	:=	drivers/meson/console/aarch64/meson_console.S \
+				plat/meson/gxl/gxl_common.c		\
+				plat/meson/gxl/gxl_topology.c		\
+				${XLAT_TABLES_LIB_SRCS}
+
+BL31_SOURCES		+=	lib/cpus/aarch64/cortex_a53.S		\
+				plat/common/plat_psci_common.c		\
+				plat/meson/gxl/aarch64/gxl_helpers.S	\
+				plat/meson/gxl/gxl_bl31_setup.c		\
+				plat/meson/gxl/gxl_efuse.c		\
+				plat/meson/gxl/gxl_mhu.c		\
+				plat/meson/gxl/gxl_pm.c			\
+				plat/meson/gxl/gxl_scpi.c		\
+				plat/meson/gxl/gxl_sip_svc.c		\
+				plat/meson/gxl/gxl_thermal.c		\
+				drivers/meson/gxl/crypto/sha_dma.c	\
+				${GXBB_GIC_SOURCES}
+
+# Tune compiler for Cortex-A53
+ifeq ($(notdir $(CC)),armclang)
+    TF_CFLAGS_aarch64	+=	-mcpu=cortex-a53
+else ifneq ($(findstring clang,$(notdir $(CC))),)
+    TF_CFLAGS_aarch64	+=	-mcpu=cortex-a53
+else
+    TF_CFLAGS_aarch64	+=	-mtune=cortex-a53
+endif
+
+# Build config flags
+# ------------------
+
+# Enable all errata workarounds for Cortex-A53
+ERRATA_A53_855873		:= 1
+ERRATA_A53_819472		:= 1
+ERRATA_A53_824069		:= 1
+ERRATA_A53_827319		:= 1
+
+WORKAROUND_CVE_2017_5715	:= 0
+
+# Have different sections for code and rodata
+SEPARATE_CODE_AND_RODATA	:= 1
+
+# Use Coherent memory
+USE_COHERENT_MEM		:= 1
+
+# Use multi console API
+MULTI_CONSOLE_API		:= 1
+
+# Verify build config
+# -------------------
+
+ifneq (${MULTI_CONSOLE_API}, 1)
+  $(error Error: gxl needs MULTI_CONSOLE_API=1)
+endif
+
+ifneq (${RESET_TO_BL31}, 0)
+  $(error Error: gxl needs RESET_TO_BL31=0)
+endif
+
+ifeq (${ARCH},aarch32)
+  $(error Error: AArch32 not supported on gxl)
+endif
+
+all: ${BUILD_PLAT}/bl31.img
+distclean realclean clean: cleanimage
+
+cleanimage:
+	${Q}${MAKE} -C ${DOIMAGEPATH} clean
+
+${DOIMAGETOOL}:
+	${Q}${MAKE} -C ${DOIMAGEPATH}
+
+${BUILD_PLAT}/bl31.img: ${BUILD_PLAT}/bl31.bin ${DOIMAGETOOL}
+	${DOIMAGETOOL} ${BUILD_PLAT}/bl31.bin ${BUILD_PLAT}/bl31.img
+
diff --git a/readme.rst b/readme.rst
index 41ffc0f..849bbb3 100644
--- a/readme.rst
+++ b/readme.rst
@@ -211,6 +211,7 @@
 
 -  Allwinner sun50i_a64 and sun50i_h6
 -  Amlogic Meson S905 (GXBB)
+-  Amlogic Meson S905x (GXL)
 -  Arm Juno Software Development Platform
 -  Arm Neoverse N1 System Development Platform (N1SDP)
 -  Arm Neoverse Reference Design N1 Edge (RD-N1-Edge) FVP
@@ -251,15 +252,13 @@
 -  Ongoing security hardening, optimization and quality improvements.
 
 For a full list of detailed issues in the current code, please see the `Change
-Log`_ and the `GitHub issue tracker`_.
+Log`_ and the `issue tracker`_.
 
 Getting started
 ---------------
 
-Get the TF-A source code from `GitHub`_.
-
-See the `User Guide`_ for instructions on how to install, build and use TF-A
-with the Arm `FVP`_\ s.
+See the `User Guide`_ for instructions on how to download, install, build and
+use TF-A with the Arm `FVP`_\ s.
 
 See the `Firmware Design`_ for information on how TF-A works.
 
@@ -281,7 +280,7 @@
 
 Development discussion takes place on the #trusted-firmware-a channel
 on the Freenode IRC network. This is not an official support channel.
-If you have an issue to raise, please use the `GitHub issue tracker`_.
+If you have an issue to raise, please use the `issue tracker`_.
 
 Feedback and support
 ~~~~~~~~~~~~~~~~~~~~
@@ -289,7 +288,7 @@
 Arm welcomes any feedback on TF-A. If you think you have found a security
 vulnerability, please report this using the process defined in the TF-A
 `Security Center`_. For all other feedback, please use the
-`GitHub issue tracker`_.
+`issue tracker`_.
 
 Arm licensees may contact Arm directly via their partner managers.
 
@@ -326,8 +325,8 @@
 .. _OP-TEE Secure OS: https://github.com/OP-TEE/optee_os
 .. _NVIDIA Trusted Little Kernel: http://nv-tegra.nvidia.com/gitweb/?p=3rdparty/ote_partner/tlk.git;a=summary
 .. _Trusty Secure OS: https://source.android.com/security/trusty
-.. _GitHub: https://www.github.com/ARM-software/arm-trusted-firmware
-.. _GitHub issue tracker: https://github.com/ARM-software/tf-issues/issues
+.. _trustedfirmware.org: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
+.. _issue tracker: http://issues.trustedfirmware.org
 .. _Security Center: ./docs/security-center.rst
 .. _license: ./license.rst
 .. _Contributing Guidelines: ./contributing.rst
diff --git a/services/std_svc/spm/spm_main.c b/services/std_svc/spm/spm_main.c
index 6cd77e3..aa7bd04 100644
--- a/services/std_svc/spm/spm_main.c
+++ b/services/std_svc/spm/spm_main.c
@@ -300,6 +300,9 @@
 		panic();
 	}
 
+	/* Setup shim layer */
+	spm_exceptions_xlat_init_context();
+
 	/*
 	 * Setup all Secure Partitions.
 	 */
@@ -325,9 +328,6 @@
 		/* Initialize context of the SP */
 		INFO("Secure Partition %u context setup start...\n", i);
 
-		/* Assign translation tables context. */
-		ctx->xlat_ctx_handle = spm_sp_xlat_context_alloc();
-
 		/* Save location of the image in physical memory */
 		ctx->image_base = (uintptr_t)sp_base;
 		ctx->image_size = sp_size;
diff --git a/services/std_svc/spm/spm_private.h b/services/std_svc/spm/spm_private.h
index 1d5a88e..740fee5 100644
--- a/services/std_svc/spm/spm_private.h
+++ b/services/std_svc/spm/spm_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -95,8 +95,12 @@
 void spm_sp_request_decrease(sp_context_t *sp_ctx);
 int spm_sp_request_increase_if_zero(sp_context_t *sp_ctx);
 
+/* Functions related to the shim layer translation tables */
+void spm_exceptions_xlat_init_context(void);
+uint64_t *spm_exceptions_xlat_get_base_table(void);
+
 /* Functions related to the translation tables management */
-xlat_ctx_t *spm_sp_xlat_context_alloc(void);
+void spm_sp_xlat_context_alloc(sp_context_t *sp_ctx);
 void sp_map_memory_regions(sp_context_t *sp_ctx);
 
 /* Functions to handle Secure Partition contexts */
diff --git a/services/std_svc/spm/spm_setup.c b/services/std_svc/spm/spm_setup.c
index 3aabc20..2ed44d1 100644
--- a/services/std_svc/spm/spm_setup.c
+++ b/services/std_svc/spm/spm_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -60,6 +60,9 @@
 	 * ------------------------
 	 */
 
+	/* Assign translation tables context. */
+	spm_sp_xlat_context_alloc(sp_ctx);
+
 	sp_map_memory_regions(sp_ctx);
 
 	/*
@@ -77,12 +80,24 @@
 	write_ctx_reg(get_sysregs_ctx(ctx), CTX_MAIR_EL1,
 		      mmu_cfg_params[MMU_CFG_MAIR]);
 
+	/* Enable translations using TTBR1_EL1 */
+	int t1sz = 64 - __builtin_ctzll(SPM_SHIM_XLAT_VIRT_ADDR_SPACE_SIZE);
+	mmu_cfg_params[MMU_CFG_TCR] &= ~TCR_EPD1_BIT;
+	mmu_cfg_params[MMU_CFG_TCR] |=
+		((uint64_t)t1sz << TCR_T1SZ_SHIFT) |
+		TCR_SH1_INNER_SHAREABLE |
+		TCR_RGN1_OUTER_WBA | TCR_RGN1_INNER_WBA |
+		TCR_TG1_4K;
+
 	write_ctx_reg(get_sysregs_ctx(ctx), CTX_TCR_EL1,
 		      mmu_cfg_params[MMU_CFG_TCR]);
 
 	write_ctx_reg(get_sysregs_ctx(ctx), CTX_TTBR0_EL1,
 		      mmu_cfg_params[MMU_CFG_TTBR0]);
 
+	write_ctx_reg(get_sysregs_ctx(ctx), CTX_TTBR1_EL1,
+		      (uint64_t)spm_exceptions_xlat_get_base_table());
+
 	/* Setup SCTLR_EL1 */
 	u_register_t sctlr_el1 = read_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1);
 
@@ -122,9 +137,14 @@
 	 * ----------------------------
 	 */
 
-	/* Shim Exception Vector Base Address */
+	/*
+	 * Shim exception vector base address. It is mapped at the start of the
+	 * address space accessed by TTBR1_EL1, which means that the base
+	 * address of the exception vectors depends on the size of the address
+	 * space specified in TCR_EL1.T1SZ.
+	 */
 	write_ctx_reg(get_sysregs_ctx(ctx), CTX_VBAR_EL1,
-			SPM_SHIM_EXCEPTIONS_PTR);
+		      UINT64_MAX - (SPM_SHIM_XLAT_VIRT_ADDR_SPACE_SIZE - 1ULL));
 
 	/*
 	 * FPEN: Allow the Secure Partition to access FP/SIMD registers.
diff --git a/services/std_svc/spm/spm_shim_private.h b/services/std_svc/spm/spm_shim_private.h
index 7fe9692..fc510b1 100644
--- a/services/std_svc/spm/spm_shim_private.h
+++ b/services/std_svc/spm/spm_shim_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -23,4 +23,12 @@
 #define SPM_SHIM_EXCEPTIONS_SIZE	\
 	(SPM_SHIM_EXCEPTIONS_END - SPM_SHIM_EXCEPTIONS_START)
 
+/*
+ * Use the smallest virtual address space size allowed in ARMv8.0 for
+ * compatibility.
+ */
+#define SPM_SHIM_XLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 25)
+#define SPM_SHIM_MMAP_REGIONS	1
+#define SPM_SHIM_XLAT_TABLES	1
+
 #endif /* SPM_SHIM_PRIVATE_H */
diff --git a/services/std_svc/spm/spm_xlat.c b/services/std_svc/spm/spm_xlat.c
index 57ad742..5d5bc51 100644
--- a/services/std_svc/spm/spm_xlat.c
+++ b/services/std_svc/spm/spm_xlat.c
@@ -1,10 +1,11 @@
 /*
- * 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
  */
 
 #include <arch.h>
+#include <arch_features.h>
 #include <arch_helpers.h>
 #include <assert.h>
 #include <errno.h>
@@ -50,17 +51,6 @@
 	XLAT_TABLE_ENTRIES * sizeof(uint64_t),
 	(PLAT_SP_IMAGE_MAX_XLAT_TABLES + 1) * PLAT_SPM_MAX_PARTITIONS);
 
-/* Allocate base translation tables. */
-static uint64_t sp_xlat_base_tables
-	[GET_NUM_BASE_LEVEL_ENTRIES(PLAT_VIRT_ADDR_SPACE_SIZE)]
-	[PLAT_SPM_MAX_PARTITIONS]
-	__aligned(GET_NUM_BASE_LEVEL_ENTRIES(PLAT_VIRT_ADDR_SPACE_SIZE)
-		  * sizeof(uint64_t))
-	__section(PLAT_SP_IMAGE_XLAT_SECTION_NAME);
-static OBJECT_POOL(sp_xlat_base_tables_pool, sp_xlat_base_tables,
-	GET_NUM_BASE_LEVEL_ENTRIES(PLAT_VIRT_ADDR_SPACE_SIZE) * sizeof(uint64_t),
-	PLAT_SPM_MAX_PARTITIONS);
-
 /* Allocate arrays. */
 static int sp_xlat_mapped_regions[PLAT_SP_IMAGE_MAX_XLAT_TABLES]
 	[PLAT_SPM_MAX_PARTITIONS];
@@ -73,28 +63,109 @@
 	PLAT_SPM_MAX_PARTITIONS);
 
 /* Get handle of Secure Partition translation context */
-xlat_ctx_t *spm_sp_xlat_context_alloc(void)
+void spm_sp_xlat_context_alloc(sp_context_t *sp_ctx)
 {
+	/* Allocate xlat context elements */
+
 	xlat_ctx_t *ctx = pool_alloc(&sp_xlat_ctx_pool);
 
 	struct mmap_region *mmap = pool_alloc(&sp_mmap_regions_pool);
 
-	uint64_t *base_table = pool_alloc(&sp_xlat_base_tables_pool);
+	uint64_t *base_table = pool_alloc(&sp_xlat_tables_pool);
 	uint64_t **tables = pool_alloc_n(&sp_xlat_tables_pool,
 					PLAT_SP_IMAGE_MAX_XLAT_TABLES);
 
 	int *mapped_regions = pool_alloc(&sp_xlat_mapped_regions_pool);
 
-	xlat_setup_dynamic_ctx(ctx, PLAT_PHY_ADDR_SPACE_SIZE - 1,
-			       PLAT_VIRT_ADDR_SPACE_SIZE - 1, mmap,
+	/* Calculate the size of the virtual address space needed */
+
+	uintptr_t va_size = 0U;
+	struct sp_rd_sect_mem_region *rdmem;
+
+	for (rdmem = sp_ctx->rd.mem_region; rdmem != NULL; rdmem = rdmem->next) {
+		uintptr_t end_va = (uintptr_t)rdmem->base +
+				   (uintptr_t)rdmem->size;
+
+		if (end_va > va_size)
+			va_size = end_va;
+	}
+
+	if (va_size == 0U) {
+		ERROR("No regions in resource description.\n");
+		panic();
+	}
+
+	/*
+	 * Get the power of two that is greater or equal to the top VA. The
+	 * values of base and size in the resource description are 32-bit wide
+	 * so the values will never overflow when using a uintptr_t.
+	 */
+	if (!IS_POWER_OF_TWO(va_size)) {
+		va_size = 1ULL <<
+			((sizeof(va_size) * 8) - __builtin_clzll(va_size));
+	}
+
+	if (va_size > PLAT_VIRT_ADDR_SPACE_SIZE) {
+		ERROR("Resource description requested too much virtual memory.\n");
+		panic();
+	}
+
+	uintptr_t min_va_size;
+
+	/* The following sizes are only valid for 4KB pages */
+	assert(PAGE_SIZE == (4U * 1024U));
+
+	if (is_armv8_4_ttst_present()) {
+		VERBOSE("Using ARMv8.4-TTST\n");
+		min_va_size = 1ULL << (64 - TCR_TxSZ_MAX_TTST);
+	} else {
+		min_va_size = 1ULL << (64 - TCR_TxSZ_MAX);
+	}
+
+	if (va_size < min_va_size) {
+		va_size = min_va_size;
+	}
+
+	/* Initialize xlat context */
+
+	xlat_setup_dynamic_ctx(ctx, PLAT_PHY_ADDR_SPACE_SIZE - 1ULL,
+			       va_size - 1ULL, mmap,
 			       PLAT_SP_IMAGE_MMAP_REGIONS, tables,
 			       PLAT_SP_IMAGE_MAX_XLAT_TABLES, base_table,
 			       EL1_EL0_REGIME, mapped_regions);
 
-	return ctx;
+	sp_ctx->xlat_ctx_handle = ctx;
 };
 
 /*******************************************************************************
+ * Translation table context used for S-EL1 exception vectors
+ ******************************************************************************/
+
+REGISTER_XLAT_CONTEXT2(spm_sel1, SPM_SHIM_MMAP_REGIONS, SPM_SHIM_XLAT_TABLES,
+		SPM_SHIM_XLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE,
+		EL1_EL0_REGIME, PLAT_SP_IMAGE_XLAT_SECTION_NAME);
+
+void spm_exceptions_xlat_init_context(void)
+{
+	/* This region contains the exception vectors used at S-EL1. */
+	mmap_region_t sel1_exception_vectors =
+		MAP_REGION(SPM_SHIM_EXCEPTIONS_PTR,
+			   0x0UL,
+			   SPM_SHIM_EXCEPTIONS_SIZE,
+			   MT_CODE | MT_SECURE | MT_PRIVILEGED);
+
+	mmap_add_region_ctx(&spm_sel1_xlat_ctx,
+			    &sel1_exception_vectors);
+
+	init_xlat_tables_ctx(&spm_sel1_xlat_ctx);
+}
+
+uint64_t *spm_exceptions_xlat_get_base_table(void)
+{
+	return spm_sel1_xlat_ctx.base_table;
+}
+
+/*******************************************************************************
  * Functions to allocate memory for regions.
  ******************************************************************************/
 
@@ -159,6 +230,11 @@
 
 	unsigned int memtype = rdmem->attr & RD_MEM_MASK;
 
+	if (rd_size == 0U) {
+		VERBOSE("Memory region '%s' is empty. Ignored.\n", rdmem->name);
+		return;
+	}
+
 	VERBOSE("Adding memory region '%s'\n", rdmem->name);
 
 	mmap.granularity = REGION_DEFAULT_GRANULARITY;
@@ -295,15 +371,6 @@
 
 void sp_map_memory_regions(sp_context_t *sp_ctx)
 {
-	/* This region contains the exception vectors used at S-EL1. */
-	const mmap_region_t sel1_exception_vectors =
-		MAP_REGION_FLAT(SPM_SHIM_EXCEPTIONS_START,
-				SPM_SHIM_EXCEPTIONS_SIZE,
-				MT_CODE | MT_SECURE | MT_PRIVILEGED);
-
-	mmap_add_region_ctx(sp_ctx->xlat_ctx_handle,
-			    &sel1_exception_vectors);
-
 	struct sp_rd_sect_mem_region *rdmem;
 
 	for (rdmem = sp_ctx->rd.mem_region; rdmem != NULL; rdmem = rdmem->next) {
diff --git a/tools/meson/Makefile b/tools/meson/Makefile
new file mode 100644
index 0000000..1a1d1f8
--- /dev/null
+++ b/tools/meson/Makefile
@@ -0,0 +1,49 @@
+#
+# Copyright (C) 2019 Remi Pommarel <repk@triplefau.lt>
+#
+# SPDX-License-Identifier:     BSD-3-Clause
+# https://spdx.org/licenses
+#
+MAKE_HELPERS_DIRECTORY := ../../make_helpers/
+include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
+include ${MAKE_HELPERS_DIRECTORY}build_env.mk
+
+PROJECT := doimage${BIN_EXT}
+OBJECTS := doimage.o
+V := 0
+
+HOSTCCFLAGS := -Wall -Werror -pedantic -std=c99 -D_GNU_SOURCE
+
+ifeq (${DEBUG},1)
+  HOSTCCFLAGS += -g -O0 -DDEBUG
+else
+  HOSTCCFLAGS += -O2
+endif
+
+ifeq (${V},0)
+  Q := @
+else
+  Q :=
+endif
+
+HOSTCC := gcc
+
+.PHONY: all clean distclean
+
+all: ${PROJECT}
+
+${PROJECT}: ${OBJECTS} Makefile
+	@echo "  HOSTLD  $@"
+	${Q}${HOSTCC} ${OBJECTS} -o $@
+	@${ECHO_BLANK_LINE}
+	@echo "Built $@ successfully"
+	@${ECHO_BLANK_LINE}
+
+%.o: %.c Makefile
+	@echo "  HOSTCC  $<"
+	${Q}${HOSTCC} -c ${HOSTCCFLAGS} $< -o $@
+
+clean:
+	$(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS})
+
+distclean: clean
diff --git a/tools/meson/doimage.c b/tools/meson/doimage.c
new file mode 100644
index 0000000..b304038
--- /dev/null
+++ b/tools/meson/doimage.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2019, Remi Pommarel <repk@triplefau.lt>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <endian.h>
+
+#define DEFAULT_PROGNAME "doimage"
+#define PROGNAME(argc, argv) (((argc) >= 1) ? ((argv)[0]) : DEFAULT_PROGNAME)
+
+#define BL31_MAGIC 0x12348765
+#define BL31_LOADADDR 0x05100000
+#define BUFLEN 512
+
+static inline void usage(char const *prog)
+{
+	fprintf(stderr, "Usage: %s <bl31.bin> <bl31.img>\n", prog);
+}
+
+static inline int fdwrite(int fd, uint8_t *data, size_t len)
+{
+	ssize_t nr;
+	size_t l;
+	int ret = -1;
+
+	for (l = 0; l < len; l += nr) {
+		nr = write(fd, data + l, len - l);
+		if (nr < 0) {
+			perror("Cannot write to bl31.img");
+			goto out;
+		}
+	}
+
+	ret = 0;
+out:
+	return ret;
+}
+
+int main(int argc, char **argv)
+{
+	int fin, fout, ret = -1;
+	ssize_t len;
+	uint32_t data;
+	uint8_t buf[BUFLEN];
+
+	if (argc != 3) {
+		usage(PROGNAME(argc, argv));
+		goto out;
+	}
+
+	fin = open(argv[1], O_RDONLY);
+	if (fin < 0) {
+		perror("Cannot open bl31.bin");
+		goto out;
+	}
+
+	fout = open(argv[2], O_WRONLY | O_CREAT, 0660);
+	if (fout < 0) {
+		perror("Cannot open bl31.img");
+		goto closefin;
+	}
+
+	data = htole32(BL31_MAGIC);
+	if (fdwrite(fout, (uint8_t *)&data, sizeof(data)) < 0)
+		goto closefout;
+
+	lseek(fout, 8, SEEK_SET);
+	data = htole32(BL31_LOADADDR);
+	if (fdwrite(fout, (uint8_t *)&data, sizeof(data)) < 0)
+		goto closefout;
+
+	lseek(fout, 0x200, SEEK_SET);
+	while ((len = read(fin, buf, sizeof(buf))) > 0)
+		if (fdwrite(fout, buf, len) < 0)
+			goto closefout;
+	if (len < 0) {
+		perror("Cannot read bl31.bin");
+		goto closefout;
+	}
+
+	ret = 0;
+
+closefout:
+	close(fout);
+closefin:
+	close(fin);
+out:
+	return ret;
+}