Merge "AArch32: Disable Secure Cycle Counter" into integration
diff --git a/common/fdt_fixup.c b/common/fdt_fixup.c
index 8843404..99d0eee 100644
--- a/common/fdt_fixup.c
+++ b/common/fdt_fixup.c
@@ -29,6 +29,33 @@
return fdt_appendprop(fdt, offs, "compatible", str, strlen(str) + 1);
}
+/*
+ * Those defines are for PSCI v0.1 legacy clients, which we expect to use
+ * the same execution state (AArch32/AArch64) as TF-A.
+ * Kernels running in AArch32 on an AArch64 TF-A should use PSCI v0.2.
+ */
+#ifdef __aarch64__
+#define PSCI_CPU_SUSPEND_FNID PSCI_CPU_SUSPEND_AARCH64
+#define PSCI_CPU_ON_FNID PSCI_CPU_ON_AARCH64
+#else
+#define PSCI_CPU_SUSPEND_FNID PSCI_CPU_SUSPEND_AARCH32
+#define PSCI_CPU_ON_FNID PSCI_CPU_ON_AARCH32
+#endif
+
+/*******************************************************************************
+ * dt_add_psci_node() - Add a PSCI node into an existing device tree
+ * @fdt: pointer to the device tree blob in memory
+ *
+ * Add a device tree node describing PSCI into the root level of an existing
+ * device tree blob in memory.
+ * This will add v0.1, v0.2 and v1.0 compatible strings and the standard
+ * function IDs for v0.1 compatibility.
+ * An existing PSCI node will not be touched, the function will return success
+ * in this case. This function will not touch the /cpus enable methods, use
+ * dt_add_psci_cpu_enable_methods() for that.
+ *
+ * Return: 0 on success, -1 otherwise.
+ ******************************************************************************/
int dt_add_psci_node(void *fdt)
{
int offs;
@@ -52,15 +79,11 @@
return -1;
if (fdt_setprop_string(fdt, offs, "method", "smc"))
return -1;
- if (fdt_setprop_u32(fdt, offs, "cpu_suspend", PSCI_CPU_SUSPEND_AARCH64))
+ if (fdt_setprop_u32(fdt, offs, "cpu_suspend", PSCI_CPU_SUSPEND_FNID))
return -1;
if (fdt_setprop_u32(fdt, offs, "cpu_off", PSCI_CPU_OFF))
return -1;
- if (fdt_setprop_u32(fdt, offs, "cpu_on", PSCI_CPU_ON_AARCH64))
- return -1;
- if (fdt_setprop_u32(fdt, offs, "sys_poweroff", PSCI_SYSTEM_OFF))
- return -1;
- if (fdt_setprop_u32(fdt, offs, "sys_reset", PSCI_SYSTEM_RESET))
+ if (fdt_setprop_u32(fdt, offs, "cpu_on", PSCI_CPU_ON_FNID))
return -1;
return 0;
}
@@ -113,6 +136,17 @@
return offs;
}
+/*******************************************************************************
+ * dt_add_psci_cpu_enable_methods() - switch CPU nodes in DT to use PSCI
+ * @fdt: pointer to the device tree blob in memory
+ *
+ * Iterate over all CPU device tree nodes (/cpus/cpu@x) in memory to change
+ * the enable-method to PSCI. This will add the enable-method properties, if
+ * required, or will change existing properties to read "psci".
+ *
+ * Return: 0 on success, or a negative error value otherwise.
+ ******************************************************************************/
+
int dt_add_psci_cpu_enable_methods(void *fdt)
{
int offs, ret;
@@ -130,6 +164,25 @@
#define HIGH_BITS(x) ((sizeof(x) > 4) ? ((x) >> 32) : (typeof(x))0)
+/*******************************************************************************
+ * fdt_add_reserved_memory() - reserve (secure) memory regions in DT
+ * @dtb: pointer to the device tree blob in memory
+ * @node_name: name of the subnode to be used
+ * @base: physical base address of the reserved region
+ * @size: size of the reserved region
+ *
+ * Add a region of memory to the /reserved-memory node in a device tree in
+ * memory, creating that node if required. Each region goes into a subnode
+ * of that node and has a @node_name, a @base address and a @size.
+ * This will prevent any device tree consumer from using that memory. It
+ * can be used to announce secure memory regions, as it adds the "no-map"
+ * property to prevent mapping and speculative operations on that region.
+ *
+ * See reserved-memory/reserved-memory.txt in the (Linux kernel) DT binding
+ * documentation for details.
+ *
+ * Return: 0 on success, a negative error value otherwise.
+ ******************************************************************************/
int fdt_add_reserved_memory(void *dtb, const char *node_name,
uintptr_t base, size_t size)
{
diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst
index 97ed1fa..9eb7c17 100644
--- a/docs/getting_started/porting-guide.rst
+++ b/docs/getting_started/porting-guide.rst
@@ -2209,6 +2209,19 @@
above the CPU might require initialization due to having previously been in
low power states. The generic code expects the handler to succeed.
+plat_psci_ops.pwr_domain_on_finish_late() [optional]
+...........................................................
+
+This optional function is called by the PSCI implementation after the calling
+CPU is fully powered on with respective data caches enabled. The calling CPU and
+the associated cluster are guaranteed to be participating in coherency. This
+function gives the flexibility to perform any platform-specific actions safely,
+such as initialization or modification of shared data structures, without the
+overhead of explicit cache maintainace operations.
+
+The ``target_state`` has a similar meaning as described in the ``pwr_domain_on_finish()``
+operation. The generic code expects the handler to succeed.
+
plat_psci_ops.pwr_domain_suspend_finish()
.........................................
diff --git a/docs/maintainers.rst b/docs/maintainers.rst
index 7731c72..d997baa 100644
--- a/docs/maintainers.rst
+++ b/docs/maintainers.rst
@@ -48,6 +48,14 @@
:F: drivers/amlogic/gxl
:F: plat/amlogic/gxl/
+Amlogic Meson S905X2 (G12A) platform port
+---------------------------------------
+:M: Carlo Caione <ccaione@baylibre.com>
+:G: `carlo.caione`_
+:F: docs/plat/meson-g12a.rst
+:F: drivers/amlogic/g12a
+:F: plat/amlogic/g12a/
+
Armv7-A architecture port
-------------------------
:M: Etienne Carriere <etienne.carriere@linaro.org>
diff --git a/docs/plat/hikey.rst b/docs/plat/hikey.rst
index 74ff2f4..372d388 100644
--- a/docs/plat/hikey.rst
+++ b/docs/plat/hikey.rst
@@ -1,15 +1,15 @@
-Description
-===========
+HiKey
+=====
HiKey is one of 96boards. Hisilicon Kirin6220 processor is installed on HiKey.
More information are listed in `link`_.
How to build
-============
+------------
Code Locations
---------------
+~~~~~~~~~~~~~~
- Trusted Firmware-A:
`link <https://github.com/ARM-software/arm-trusted-firmware>`__
@@ -33,7 +33,7 @@
`link <https://github.com/96boards-hikey/atf-fastboot/tree/master>`__
Build Procedure
----------------
+~~~~~~~~~~~~~~~
- Fetch all the above repositories into local host.
Make all the repositories in the same ${BUILD\_PATH}.
diff --git a/docs/plat/hikey960.rst b/docs/plat/hikey960.rst
index 7ddb0b1..3d42a77 100644
--- a/docs/plat/hikey960.rst
+++ b/docs/plat/hikey960.rst
@@ -1,15 +1,15 @@
-Description
-===========
+HiKey960
+========
HiKey960 is one of 96boards. Hisilicon Hi3660 processor is installed on HiKey960.
More information are listed in `link`_.
How to build
-============
+------------
Code Locations
---------------
+~~~~~~~~~~~~~~
- Trusted Firmware-A:
`link <https://github.com/ARM-software/arm-trusted-firmware>`__
@@ -30,7 +30,7 @@
`link <https://git.linaro.org/uefi/uefi-tools.git>`__
Build Procedure
----------------
+~~~~~~~~~~~~~~~
- Fetch all the above 5 repositories into local host.
Make all the repositories in the same ${BUILD\_PATH}.
diff --git a/docs/plat/index.rst b/docs/plat/index.rst
index eaeee84..2695d4e 100644
--- a/docs/plat/index.rst
+++ b/docs/plat/index.rst
@@ -7,24 +7,28 @@
:numbered:
allwinner
- fvp_ve
- imx8
- imx8m
- intel-stratix10
- ls1043a
- marvell/index
meson-gxbb
meson-gxl
+ fvp_ve
+ hikey
+ hikey960
+ intel-agilex
+ intel-stratix10
+ marvell/index
mt8183
nvidia-tegra
+ warp7
+ imx8
+ imx8m
+ ls1043a
+ poplar
qemu
+ rpi3
rcar-gen3
rockchip
- rpi3
socionext-uniphier
- stm32mp1
synquacer
+ stm32mp1
ti-k3
- warp7
xilinx-versal
xilinx-zynqmp
diff --git a/docs/plat/intel-agilex.rst b/docs/plat/intel-agilex.rst
index 015a195..ff27b6b 100644
--- a/docs/plat/intel-agilex.rst
+++ b/docs/plat/intel-agilex.rst
@@ -67,6 +67,7 @@
----------
::
+
INFO: DDR: DRAM calibration success.
INFO: ECC is disabled.
NOTICE: BL2: v2.1(debug)
diff --git a/docs/plat/intel-stratix10.rst b/docs/plat/intel-stratix10.rst
index 77a45a4..7f8d18e 100644
--- a/docs/plat/intel-stratix10.rst
+++ b/docs/plat/intel-stratix10.rst
@@ -67,6 +67,7 @@
----------
::
+
INFO: DDR: DRAM calibration success.
INFO: ECC is disabled.
INFO: Init HPS NOC's DDR Scheduler.
diff --git a/docs/plat/meson-g12a.rst b/docs/plat/meson-g12a.rst
new file mode 100644
index 0000000..1021da4
--- /dev/null
+++ b/docs/plat/meson-g12a.rst
@@ -0,0 +1,27 @@
+Amlogic Meson S905X2 (G12A)
+==========================
+
+The Amlogic Meson S905X2 is a SoC with a quad core Arm Cortex-A53 running at
+~1.8GHz. 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:
+
+.. code:: shell
+
+ CROSS_COMPILE=aarch64-linux-gnu- make DEBUG=1 PLAT=g12a
+
+This port has been tested on a SEI510 board. 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.g12a
+.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/board/amlogic/sei510/README
diff --git a/docs/plat/poplar.rst b/docs/plat/poplar.rst
index 5884ed9..215f551 100644
--- a/docs/plat/poplar.rst
+++ b/docs/plat/poplar.rst
@@ -1,5 +1,5 @@
-Description
-===========
+Poplar
+======
Poplar is the first development board compliant with the 96Boards Enterprise
Edition TV Platform specification.
@@ -35,10 +35,10 @@
l-loader --> Trusted Firmware-A --> u-boot
How to build
-============
+------------
Code Locations
---------------
+~~~~~~~~~~~~~~
- Trusted Firmware-A:
`link <https://github.com/ARM-software/arm-trusted-firmware>`__
@@ -50,7 +50,7 @@
`link <http://git.denx.de/u-boot.git>`__
Build Procedure
----------------
+~~~~~~~~~~~~~~~
- Fetch all the above 3 repositories into local host.
Make all the repositories in the same ${BUILD\_PATH}.
@@ -89,7 +89,7 @@
working firmware to eMMC.
Boot trace
-==========
+----------
::
diff --git a/docs/plat/rpi4.rst b/docs/plat/rpi4.rst
new file mode 100644
index 0000000..0f529c1
--- /dev/null
+++ b/docs/plat/rpi4.rst
@@ -0,0 +1,85 @@
+Raspberry Pi 4
+==============
+
+The `Raspberry Pi 4`_ is an inexpensive single-board computer that contains four
+Arm Cortex-A72 cores. Also in contrast to previous Raspberry Pi versions this
+model has a GICv2 interrupt controller.
+
+This port is a minimal port to support loading non-secure EL2 payloads such
+as a 64-bit Linux kernel. Other payloads such as U-Boot or EDK-II should work
+as well, but have not been tested at this point.
+
+**IMPORTANT NOTE**: This port isn't secure. All of the memory used is DRAM,
+which is available from both the Non-secure and Secure worlds. The SoC does
+not seem to feature a secure memory controller of any kind, so portions of
+DRAM can't be protected properly from the Non-secure world.
+
+Build Instructions
+------------------
+
+There are no real configuration options at this point, so there is only
+one universal binary (bl31.bin), which can be built with:
+
+.. code:: shell
+
+ CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi4 DEBUG=1
+
+Copy the generated build/rpi4/debug/bl31.bin to the SD card, either
+renaming it to ``armstub8.bin`` or adding an entry starting with ``armstub=``,
+then followed by the respective file name to ``config.txt``.
+You should have AArch64 code in the file loaded as the "kernel", as BL31
+will drop into AArch64/EL2 to the respective load address.
+arm64 Linux kernels are known to work this way.
+
+Other options that should be set in ``config.txt`` to properly boot 64-bit
+kernels are:
+
+::
+
+ enable_uart=1
+ arm_64bit=1
+ enable_gic=1
+
+The BL31 code will patch the provided device tree blob in memory to advertise
+PSCI support, also will add a reserved-memory node to the DT to tell the
+non-secure payload to not touch the resident TF-A code.
+
+If you connect a serial cable between the Mini UART and your computer, and
+connect to it (for example, with ``screen /dev/ttyUSB0 115200``) you should
+see some text from BL31, followed by the output of the EL2 payload.
+The command line provided is read from the ``cmdline.txt`` file on the SD card.
+
+TF-A port design
+----------------
+
+In contrast to the existing Raspberry Pi 3 port this one here is a BL31-only
+port, also it deviates quite a lot from the RPi3 port in many other ways.
+There is not so much difference between the two models, so eventually those
+two could be (more) unified in the future.
+
+As with the previous models, the GPU and its firmware are the first entity to
+run after the SoC gets its power. The on-chip Boot ROM loads the next stage
+(bootcode.bin) from flash (EEPROM), which is again GPU code.
+This part knows how to access the MMC controller and how to parse a FAT
+filesystem, so it will load further compononents and configuration files
+from the first FAT partition on the SD card.
+
+To accommodate this existing way of configuring and setting up the board,
+we use as much of this workflow as possible.
+If bootcode.bin finds a file called ``armstub8.bin`` on the SD card or it gets
+pointed to such code by finding a ``armstub=`` key in ``config.txt``, it will
+load this file to the beginning of DRAM (address 0) and execute it in
+AArch64 EL3.
+But before doing that, it will also load a "kernel" and the device tree into
+memory. The load addresses have a default, but can also be changed by
+setting them in ``config.txt``. If the GPU firmware finds a magic value in the
+armstub image file, it will put those two load addresses in memory locations
+near the beginning of memory, where TF-A code picks them up.
+
+To keep things simple, we will just use the kernel load address as the BL33
+entry point, also put the DTB address in the x0 register, as requested by
+the arm64 Linux kernel boot protocol. This does not necessarily mean that
+the EL2 payload needs to be a Linux kernel, a bootloader or any other kernel
+would work as well, as long as it can cope with having the DT address in
+register x0. If the payload has other means of finding the device tree, it
+could ignore this address as well.
diff --git a/drivers/amlogic/crypto/sha_dma.c b/drivers/amlogic/crypto/sha_dma.c
index d48ded9..fceb1c0 100644
--- a/drivers/amlogic/crypto/sha_dma.c
+++ b/drivers/amlogic/crypto/sha_dma.c
@@ -9,10 +9,7 @@
#include <crypto/sha_dma.h>
#include <lib/mmio.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)
+#include "aml_private.h"
#define ASD_MODE_SHA224 0x7
#define ASD_MODE_SHA256 0x6
diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c
index 94a20ba..fb49a57 100644
--- a/drivers/arm/gic/v3/gicv3_main.c
+++ b/drivers/arm/gic/v3/gicv3_main.c
@@ -16,7 +16,6 @@
#include "gicv3_private.h"
const gicv3_driver_data_t *gicv3_driver_data;
-static unsigned int gicv2_compat;
/*
* Spinlock to guard registers needing read-modify-write. APIs protected by this
@@ -60,51 +59,61 @@
void __init gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data)
{
unsigned int gic_version;
+ unsigned int gicv2_compat;
assert(plat_driver_data != NULL);
assert(plat_driver_data->gicd_base != 0U);
- assert(plat_driver_data->gicr_base != 0U);
assert(plat_driver_data->rdistif_num != 0U);
assert(plat_driver_data->rdistif_base_addrs != NULL);
assert(IS_IN_EL3());
- assert(plat_driver_data->interrupt_props_num > 0 ?
- plat_driver_data->interrupt_props != NULL : 1);
+ assert((plat_driver_data->interrupt_props_num != 0U) ?
+ (plat_driver_data->interrupt_props != NULL) : 1);
/* Check for system register support */
-#ifdef __aarch64__
+#ifndef __aarch64__
+ assert((read_id_pfr1() &
+ (ID_PFR1_GIC_MASK << ID_PFR1_GIC_SHIFT)) != 0U);
+#else
assert((read_id_aa64pfr0_el1() &
(ID_AA64PFR0_GIC_MASK << ID_AA64PFR0_GIC_SHIFT)) != 0U);
-#else
- assert((read_id_pfr1() & (ID_PFR1_GIC_MASK << ID_PFR1_GIC_SHIFT)) != 0U);
-#endif /* __aarch64__ */
+#endif /* !__aarch64__ */
/* The GIC version should be 3.0 */
gic_version = gicd_read_pidr2(plat_driver_data->gicd_base);
- gic_version >>= PIDR2_ARCH_REV_SHIFT;
+ gic_version >>= PIDR2_ARCH_REV_SHIFT;
gic_version &= PIDR2_ARCH_REV_MASK;
assert(gic_version == ARCH_REV_GICV3);
/*
- * Find out whether the GIC supports the GICv2 compatibility mode. The
- * ARE_S bit resets to 0 if supported
+ * Find out whether the GIC supports the GICv2 compatibility mode.
+ * The ARE_S bit resets to 0 if supported
*/
gicv2_compat = gicd_read_ctlr(plat_driver_data->gicd_base);
gicv2_compat >>= CTLR_ARE_S_SHIFT;
- gicv2_compat = !(gicv2_compat & CTLR_ARE_S_MASK);
+ gicv2_compat = gicv2_compat & CTLR_ARE_S_MASK;
- /*
- * Find the base address of each implemented Redistributor interface.
- * The number of interfaces should be equal to the number of CPUs in the
- * system. The memory for saving these addresses has to be allocated by
- * the platform port
- */
- gicv3_rdistif_base_addrs_probe(plat_driver_data->rdistif_base_addrs,
- plat_driver_data->rdistif_num,
- plat_driver_data->gicr_base,
- plat_driver_data->mpidr_to_core_pos);
-
+ if (plat_driver_data->gicr_base != 0U) {
+ /*
+ * Find the base address of each implemented Redistributor interface.
+ * The number of interfaces should be equal to the number of CPUs in the
+ * system. The memory for saving these addresses has to be allocated by
+ * the platform port
+ */
+ gicv3_rdistif_base_addrs_probe(plat_driver_data->rdistif_base_addrs,
+ plat_driver_data->rdistif_num,
+ plat_driver_data->gicr_base,
+ plat_driver_data->mpidr_to_core_pos);
+#if !HW_ASSISTED_COHERENCY
+ /*
+ * Flush the rdistif_base_addrs[] contents linked to the GICv3 driver.
+ */
+ flush_dcache_range((uintptr_t)(plat_driver_data->rdistif_base_addrs),
+ plat_driver_data->rdistif_num *
+ sizeof(*(plat_driver_data->rdistif_base_addrs)));
+#endif
+ }
gicv3_driver_data = plat_driver_data;
/*
@@ -112,19 +121,19 @@
* enabled. When the secondary CPU boots up, it initializes the
* GICC/GICR interface with the caches disabled. Hence flush the
* driver data to ensure coherency. This is not required if the
- * platform has HW_ASSISTED_COHERENCY or WARMBOOT_ENABLE_DCACHE_EARLY
- * enabled.
+ * platform has HW_ASSISTED_COHERENCY enabled.
*/
-#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY)
- flush_dcache_range((uintptr_t) &gicv3_driver_data,
- sizeof(gicv3_driver_data));
- flush_dcache_range((uintptr_t) gicv3_driver_data,
- sizeof(*gicv3_driver_data));
+#if !HW_ASSISTED_COHERENCY
+ flush_dcache_range((uintptr_t)&gicv3_driver_data,
+ sizeof(gicv3_driver_data));
+ flush_dcache_range((uintptr_t)gicv3_driver_data,
+ sizeof(*gicv3_driver_data));
#endif
- INFO("GICv3 %s legacy support detected."
- " ARM GICV3 driver initialized in EL3\n",
- gicv2_compat ? "with" : "without");
+ INFO("GICv3 with%s legacy support detected."
+ " ARM GICv3 driver initialized in EL3\n",
+ (gicv2_compat == 0U) ? "" : "out");
+
}
/*******************************************************************************
@@ -192,6 +201,7 @@
gicv3_rdistif_on(proc_num);
gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+ assert(gicr_base != 0U);
/* Set the default attribute of all SGIs and PPIs */
gicv3_ppi_sgi_config_defaults(gicr_base);
@@ -313,6 +323,7 @@
/* Mark the connected core as asleep */
gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+ assert(gicr_base != 0U);
gicv3_rdistif_mark_core_asleep(gicr_base);
}
@@ -629,7 +640,9 @@
num_ints &= TYPER_IT_LINES_NO_MASK;
num_ints = (num_ints + 1U) << 5;
- assert(num_ints <= (MAX_SPI_ID + 1U));
+ /* Filter out special INTIDs 1020-1023 */
+ if (num_ints > (MAX_SPI_ID + 1U))
+ num_ints = MAX_SPI_ID + 1U;
/* Wait for pending write to complete */
gicd_wait_for_pending_write(gicd_base);
@@ -637,31 +650,31 @@
/* Save the GICD_CTLR */
dist_ctx->gicd_ctlr = gicd_read_ctlr(gicd_base);
- /* Save GICD_IGROUPR for INTIDs 32 - 1020 */
+ /* Save GICD_IGROUPR for INTIDs 32 - 1019 */
SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, igroupr, IGROUPR);
- /* Save GICD_ISENABLER for INT_IDs 32 - 1020 */
+ /* Save GICD_ISENABLER for INT_IDs 32 - 1019 */
SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, isenabler, ISENABLER);
- /* Save GICD_ISPENDR for INTIDs 32 - 1020 */
+ /* Save GICD_ISPENDR for INTIDs 32 - 1019 */
SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, ispendr, ISPENDR);
- /* Save GICD_ISACTIVER for INTIDs 32 - 1020 */
+ /* Save GICD_ISACTIVER for INTIDs 32 - 1019 */
SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, isactiver, ISACTIVER);
- /* Save GICD_IPRIORITYR for INTIDs 32 - 1020 */
+ /* Save GICD_IPRIORITYR for INTIDs 32 - 1019 */
SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, ipriorityr, IPRIORITYR);
- /* Save GICD_ICFGR for INTIDs 32 - 1020 */
+ /* Save GICD_ICFGR for INTIDs 32 - 1019 */
SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, icfgr, ICFGR);
- /* Save GICD_IGRPMODR for INTIDs 32 - 1020 */
+ /* Save GICD_IGRPMODR for INTIDs 32 - 1019 */
SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, igrpmodr, IGRPMODR);
- /* Save GICD_NSACR for INTIDs 32 - 1020 */
+ /* Save GICD_NSACR for INTIDs 32 - 1019 */
SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, nsacr, NSACR);
- /* Save GICD_IROUTER for INTIDs 32 - 1024 */
+ /* Save GICD_IROUTER for INTIDs 32 - 1019 */
SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, irouter, IROUTER);
/*
@@ -707,24 +720,26 @@
num_ints &= TYPER_IT_LINES_NO_MASK;
num_ints = (num_ints + 1U) << 5;
- assert(num_ints <= (MAX_SPI_ID + 1U));
+ /* Filter out special INTIDs 1020-1023 */
+ if (num_ints > (MAX_SPI_ID + 1U))
+ num_ints = MAX_SPI_ID + 1U;
- /* Restore GICD_IGROUPR for INTIDs 32 - 1020 */
+ /* Restore GICD_IGROUPR for INTIDs 32 - 1019 */
RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, igroupr, IGROUPR);
- /* Restore GICD_IPRIORITYR for INTIDs 32 - 1020 */
+ /* Restore GICD_IPRIORITYR for INTIDs 32 - 1019 */
RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, ipriorityr, IPRIORITYR);
- /* Restore GICD_ICFGR for INTIDs 32 - 1020 */
+ /* Restore GICD_ICFGR for INTIDs 32 - 1019 */
RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, icfgr, ICFGR);
- /* Restore GICD_IGRPMODR for INTIDs 32 - 1020 */
+ /* Restore GICD_IGRPMODR for INTIDs 32 - 1019 */
RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, igrpmodr, IGRPMODR);
- /* Restore GICD_NSACR for INTIDs 32 - 1020 */
+ /* Restore GICD_NSACR for INTIDs 32 - 1019 */
RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, nsacr, NSACR);
- /* Restore GICD_IROUTER for INTIDs 32 - 1020 */
+ /* Restore GICD_IROUTER for INTIDs 32 - 1019 */
RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, irouter, IROUTER);
/*
@@ -732,13 +747,13 @@
* configured.
*/
- /* Restore GICD_ISENABLER for INT_IDs 32 - 1020 */
+ /* Restore GICD_ISENABLER for INT_IDs 32 - 1019 */
RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, isenabler, ISENABLER);
- /* Restore GICD_ISPENDR for INTIDs 32 - 1020 */
+ /* Restore GICD_ISPENDR for INTIDs 32 - 1019 */
RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, ispendr, ISPENDR);
- /* Restore GICD_ISACTIVER for INTIDs 32 - 1020 */
+ /* Restore GICD_ISACTIVER for INTIDs 32 - 1019 */
RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, isactiver, ISACTIVER);
/* Restore the GICD_CTLR */
@@ -1081,3 +1096,71 @@
return old_mask;
}
+
+/*******************************************************************************
+ * This function delegates the responsibility of discovering the corresponding
+ * Redistributor frames to each CPU itself. It is a modified version of
+ * gicv3_rdistif_base_addrs_probe() and is executed by each CPU in the platform
+ * unlike the previous way in which only the Primary CPU did the discovery of
+ * all the Redistributor frames for every CPU. It also handles the scenario in
+ * which the frames of various CPUs are not contiguous in physical memory.
+ ******************************************************************************/
+int gicv3_rdistif_probe(const uintptr_t gicr_frame)
+{
+ u_register_t mpidr;
+ unsigned int proc_num, proc_self;
+ uint64_t typer_val;
+ uintptr_t rdistif_base;
+ bool gicr_frame_found = false;
+
+ assert(gicv3_driver_data->gicr_base == 0U);
+
+ /* Ensure this function is called with Data Cache enabled */
+#ifndef __aarch64__
+ assert((read_sctlr() & SCTLR_C_BIT) != 0U);
+#else
+ assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U);
+#endif /* !__aarch64__ */
+
+ proc_self = gicv3_driver_data->mpidr_to_core_pos(read_mpidr_el1());
+ rdistif_base = gicr_frame;
+ do {
+ typer_val = gicr_read_typer(rdistif_base);
+ if (gicv3_driver_data->mpidr_to_core_pos != NULL) {
+ mpidr = mpidr_from_gicr_typer(typer_val);
+ proc_num = gicv3_driver_data->mpidr_to_core_pos(mpidr);
+ } else {
+ proc_num = (unsigned int)(typer_val >> TYPER_PROC_NUM_SHIFT) &
+ TYPER_PROC_NUM_MASK;
+ }
+ if (proc_num == proc_self) {
+ /* The base address doesn't need to be initialized on
+ * every warm boot.
+ */
+ if (gicv3_driver_data->rdistif_base_addrs[proc_num] != 0U)
+ return 0;
+ gicv3_driver_data->rdistif_base_addrs[proc_num] =
+ rdistif_base;
+ gicr_frame_found = true;
+ break;
+ }
+ rdistif_base += (uintptr_t)(ULL(1) << GICR_PCPUBASE_SHIFT);
+ } while ((typer_val & TYPER_LAST_BIT) == 0U);
+
+ if (!gicr_frame_found)
+ return -1;
+
+ /*
+ * Flush the driver data to ensure coherency. This is
+ * not required if platform has HW_ASSISTED_COHERENCY
+ * enabled.
+ */
+#if !HW_ASSISTED_COHERENCY
+ /*
+ * Flush the rdistif_base_addrs[] contents linked to the GICv3 driver.
+ */
+ flush_dcache_range((uintptr_t)&(gicv3_driver_data->rdistif_base_addrs[proc_num]),
+ sizeof(*(gicv3_driver_data->rdistif_base_addrs)));
+#endif
+ return 0; /* Found matching GICR frame */
+}
diff --git a/drivers/st/bsec/bsec.c b/drivers/st/bsec/bsec.c
index b3c15ee..01c369e 100644
--- a/drivers/st/bsec/bsec.c
+++ b/drivers/st/bsec/bsec.c
@@ -841,22 +841,6 @@
}
/*
- * bsec_mode_is_closed_device: read OTP secure sub-mode.
- * return: false if open_device and true of closed_device.
- */
-bool bsec_mode_is_closed_device(void)
-{
- uint32_t value;
-
- if ((bsec_shadow_register(DATA0_OTP) != BSEC_OK) ||
- (bsec_read_otp(&value, DATA0_OTP) != BSEC_OK)) {
- return true;
- }
-
- return (value & DATA0_OTP_SECURED) == DATA0_OTP_SECURED;
-}
-
-/*
* bsec_shadow_read_otp: Load OTP from SAFMEM and provide its value
* otp_value: read value.
* word: OTP number.
@@ -894,7 +878,7 @@
if (otp >= STM32MP1_UPPER_OTP_START) {
/* Check if BSEC is in OTP-SECURED closed_device state. */
- if (bsec_mode_is_closed_device()) {
+ if (stm32mp_is_closed_device()) {
if (!non_secure_can_access(otp)) {
return BSEC_ERROR;
}
diff --git a/drivers/st/crypto/stm32_hash.c b/drivers/st/crypto/stm32_hash.c
new file mode 100644
index 0000000..f72787d
--- /dev/null
+++ b/drivers/st/crypto/stm32_hash.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2019, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <drivers/st/stm32_hash.h>
+#include <drivers/st/stm32mp_reset.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+#define DT_HASH_COMPAT "st,stm32f756-hash"
+
+#define HASH_CR 0x00U
+#define HASH_DIN 0x04U
+#define HASH_STR 0x08U
+#define HASH_SR 0x24U
+#define HASH_HREG(x) (0x310U + ((x) * 0x04U))
+
+/* Control Register */
+#define HASH_CR_INIT BIT(2)
+#define HASH_CR_DATATYPE_SHIFT U(4)
+
+#define HASH_CR_ALGO_SHA1 0x0U
+#define HASH_CR_ALGO_MD5 BIT(7)
+#define HASH_CR_ALGO_SHA224 BIT(18)
+#define HASH_CR_ALGO_SHA256 (BIT(18) | BIT(7))
+
+/* Status Flags */
+#define HASH_SR_DCIS BIT(1)
+#define HASH_SR_BUSY BIT(3)
+
+/* STR Register */
+#define HASH_STR_NBLW_MASK GENMASK(4, 0)
+#define HASH_STR_DCAL BIT(8)
+
+#define MD5_DIGEST_SIZE 16U
+#define SHA1_DIGEST_SIZE 20U
+#define SHA224_DIGEST_SIZE 28U
+#define SHA256_DIGEST_SIZE 32U
+
+#define HASH_TIMEOUT_US 10000U
+
+enum stm32_hash_data_format {
+ HASH_DATA_32_BITS,
+ HASH_DATA_16_BITS,
+ HASH_DATA_8_BITS,
+ HASH_DATA_1_BIT
+};
+
+struct stm32_hash_instance {
+ uintptr_t base;
+ unsigned int clock;
+ size_t digest_size;
+};
+
+struct stm32_hash_remain {
+ uint32_t buffer;
+ size_t length;
+};
+
+/* Expect a single HASH peripheral */
+static struct stm32_hash_instance stm32_hash;
+static struct stm32_hash_remain stm32_remain;
+
+static uintptr_t hash_base(void)
+{
+ return stm32_hash.base;
+}
+
+static int hash_wait_busy(void)
+{
+ uint64_t timeout = timeout_init_us(HASH_TIMEOUT_US);
+
+ while ((mmio_read_32(hash_base() + HASH_SR) & HASH_SR_BUSY) != 0U) {
+ if (timeout_elapsed(timeout)) {
+ ERROR("%s: busy timeout\n", __func__);
+ return -ETIMEDOUT;
+ }
+ }
+
+ return 0;
+}
+
+static int hash_wait_computation(void)
+{
+ uint64_t timeout = timeout_init_us(HASH_TIMEOUT_US);
+
+ while ((mmio_read_32(hash_base() + HASH_SR) & HASH_SR_DCIS) == 0U) {
+ if (timeout_elapsed(timeout)) {
+ ERROR("%s: busy timeout\n", __func__);
+ return -ETIMEDOUT;
+ }
+ }
+
+ return 0;
+}
+
+static int hash_write_data(uint32_t data)
+{
+ int ret;
+
+ ret = hash_wait_busy();
+ if (ret != 0) {
+ return ret;
+ }
+
+ mmio_write_32(hash_base() + HASH_DIN, data);
+
+ return 0;
+}
+
+static void hash_hw_init(enum stm32_hash_algo_mode mode)
+{
+ uint32_t reg;
+
+ reg = HASH_CR_INIT | (HASH_DATA_8_BITS << HASH_CR_DATATYPE_SHIFT);
+
+ switch (mode) {
+ case HASH_MD5SUM:
+ reg |= HASH_CR_ALGO_MD5;
+ stm32_hash.digest_size = MD5_DIGEST_SIZE;
+ break;
+ case HASH_SHA1:
+ reg |= HASH_CR_ALGO_SHA1;
+ stm32_hash.digest_size = SHA1_DIGEST_SIZE;
+ break;
+ case HASH_SHA224:
+ reg |= HASH_CR_ALGO_SHA224;
+ stm32_hash.digest_size = SHA224_DIGEST_SIZE;
+ break;
+ /* Default selected algo is SHA256 */
+ case HASH_SHA256:
+ default:
+ reg |= HASH_CR_ALGO_SHA256;
+ stm32_hash.digest_size = SHA256_DIGEST_SIZE;
+ break;
+ }
+
+ mmio_write_32(hash_base() + HASH_CR, reg);
+}
+
+static int hash_get_digest(uint8_t *digest)
+{
+ int ret;
+ uint32_t i;
+ uint32_t dsg;
+
+ ret = hash_wait_computation();
+ if (ret != 0) {
+ return ret;
+ }
+
+ for (i = 0U; i < (stm32_hash.digest_size / sizeof(uint32_t)); i++) {
+ dsg = __builtin_bswap32(mmio_read_32(hash_base() +
+ HASH_HREG(i)));
+ memcpy(digest + (i * sizeof(uint32_t)), &dsg, sizeof(uint32_t));
+ }
+
+#if defined(IMAGE_BL2)
+ /*
+ * Clean hardware context as HASH could be used later
+ * by non-secure software
+ */
+ hash_hw_init(HASH_SHA256);
+#endif
+ return 0;
+}
+
+int stm32_hash_update(const uint8_t *buffer, size_t length)
+{
+ size_t remain_length = length;
+ int ret = 0;
+
+ if ((length == 0U) || (buffer == NULL)) {
+ return 0;
+ }
+
+ stm32mp_clk_enable(stm32_hash.clock);
+
+ if (stm32_remain.length != 0U) {
+ uint32_t copysize;
+
+ copysize = MIN((sizeof(uint32_t) - stm32_remain.length),
+ length);
+ memcpy(((uint8_t *)&stm32_remain.buffer) + stm32_remain.length,
+ buffer, copysize);
+ remain_length -= copysize;
+ buffer += copysize;
+ if (stm32_remain.length == sizeof(uint32_t)) {
+ ret = hash_write_data(stm32_remain.buffer);
+ if (ret != 0) {
+ goto exit;
+ }
+
+ zeromem(&stm32_remain, sizeof(stm32_remain));
+ }
+ }
+
+ while (remain_length / sizeof(uint32_t) != 0U) {
+ uint32_t tmp_buf;
+
+ memcpy(&tmp_buf, buffer, sizeof(uint32_t));
+ ret = hash_write_data(tmp_buf);
+ if (ret != 0) {
+ goto exit;
+ }
+
+ buffer += sizeof(uint32_t);
+ remain_length -= sizeof(uint32_t);
+ }
+
+ if (remain_length != 0U) {
+ assert(stm32_remain.length == 0U);
+
+ memcpy((uint8_t *)&stm32_remain.buffer, buffer, remain_length);
+ stm32_remain.length = remain_length;
+ }
+
+exit:
+ stm32mp_clk_disable(stm32_hash.clock);
+
+ return ret;
+}
+
+int stm32_hash_final(uint8_t *digest)
+{
+ int ret;
+
+ stm32mp_clk_enable(stm32_hash.clock);
+
+ if (stm32_remain.length != 0U) {
+ ret = hash_write_data(stm32_remain.buffer);
+ if (ret != 0) {
+ stm32mp_clk_disable(stm32_hash.clock);
+ return ret;
+ }
+
+ mmio_clrsetbits_32(hash_base() + HASH_STR, HASH_STR_NBLW_MASK,
+ 8U * stm32_remain.length);
+ zeromem(&stm32_remain, sizeof(stm32_remain));
+ }
+
+ mmio_setbits_32(hash_base() + HASH_STR, HASH_STR_DCAL);
+
+ ret = hash_get_digest(digest);
+
+ stm32mp_clk_disable(stm32_hash.clock);
+
+ return ret;
+}
+
+int stm32_hash_final_update(const uint8_t *buffer, uint32_t length,
+ uint8_t *digest)
+{
+ int ret;
+
+ ret = stm32_hash_update(buffer, length);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return stm32_hash_final(digest);
+}
+
+void stm32_hash_init(enum stm32_hash_algo_mode mode)
+{
+ stm32mp_clk_enable(stm32_hash.clock);
+
+ hash_hw_init(mode);
+
+ stm32mp_clk_disable(stm32_hash.clock);
+
+ zeromem(&stm32_remain, sizeof(stm32_remain));
+}
+
+int stm32_hash_register(void)
+{
+ struct dt_node_info hash_info;
+ int node;
+
+ for (node = dt_get_node(&hash_info, -1, DT_HASH_COMPAT);
+ node != -FDT_ERR_NOTFOUND;
+ node = dt_get_node(&hash_info, node, DT_HASH_COMPAT)) {
+#if defined(IMAGE_BL2)
+ if (hash_info.status != DT_DISABLED) {
+ break;
+ }
+#else
+ if (hash_info.status == DT_SECURE) {
+ break;
+ }
+#endif
+ }
+
+ if (node == -FDT_ERR_NOTFOUND) {
+ return -ENODEV;
+ }
+
+ if (hash_info.clock < 0) {
+ return -EINVAL;
+ }
+
+ stm32_hash.base = hash_info.base;
+ stm32_hash.clock = hash_info.clock;
+
+ stm32mp_clk_enable(stm32_hash.clock);
+
+ if (hash_info.reset >= 0) {
+ stm32mp_reset_assert((unsigned long)hash_info.reset);
+ udelay(20);
+ stm32mp_reset_deassert((unsigned long)hash_info.reset);
+ }
+
+ stm32mp_clk_disable(stm32_hash.clock);
+
+ return 0;
+}
diff --git a/drivers/st/io/io_stm32image.c b/drivers/st/io/io_stm32image.c
index 971dcce..413521b 100644
--- a/drivers/st/io/io_stm32image.c
+++ b/drivers/st/io/io_stm32image.c
@@ -246,7 +246,7 @@
static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer,
size_t length, size_t *length_read)
{
- int result = 0;
+ int result;
uint8_t *local_buffer = (uint8_t *)buffer;
boot_api_image_header_t *header =
(boot_api_image_header_t *)first_lba_buffer;
@@ -341,6 +341,12 @@
header->magic = 0;
}
+ result = stm32mp_auth_image(header, buffer);
+ if (result != 0) {
+ ERROR("Authentication Failed (%i)\n", result);
+ return result;
+ }
+
io_close(backend_handle);
}
diff --git a/fdts/a5ds.dts b/fdts/a5ds.dts
index 8bc4adf..91212e8 100644
--- a/fdts/a5ds.dts
+++ b/fdts/a5ds.dts
@@ -12,14 +12,40 @@
interrupt-parent = <&gic>;
#address-cells = <1>;
#size-cells = <1>;
+
+ psci {
+ compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci";
+ method = "smc";
+ cpu_on = <0x84000003>;
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a5";
+ enable-method = "psci";
reg = <0>;
};
+ cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a5";
+ enable-method = "psci";
+ reg = <1>;
+ };
+ cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a5";
+ enable-method = "psci";
+ reg = <2>;
+ };
+ cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a5";
+ enable-method = "psci";
+ reg = <3>;
+ };
};
memory@80000000 {
diff --git a/fdts/stm32mp157c-security.dtsi b/fdts/stm32mp157c-security.dtsi
index f7e55b3..165ffa0 100644
--- a/fdts/stm32mp157c-security.dtsi
+++ b/fdts/stm32mp157c-security.dtsi
@@ -28,6 +28,10 @@
};
};
+&hash1 {
+ secure-status = "okay";
+};
+
&sdmmc1 {
compatible = "st,stm32-sdmmc2";
};
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
index 9c72d4d..c4f42d0 100644
--- a/include/drivers/arm/gicv3.h
+++ b/include/drivers/arm/gicv3.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -366,6 +366,7 @@
* GICv3 EL3 driver API
******************************************************************************/
void gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data);
+int gicv3_rdistif_probe(const uintptr_t gicr_frame);
void gicv3_distif_init(void);
void gicv3_rdistif_init(unsigned int proc_num);
void gicv3_rdistif_on(unsigned int proc_num);
diff --git a/include/drivers/st/bsec.h b/include/drivers/st/bsec.h
index 2171550..d833e7a 100644
--- a/include/drivers/st/bsec.h
+++ b/include/drivers/st/bsec.h
@@ -199,7 +199,6 @@
bool bsec_wr_lock(uint32_t otp);
uint32_t bsec_otp_lock(uint32_t service, uint32_t value);
-bool bsec_mode_is_closed_device(void);
uint32_t bsec_shadow_read_otp(uint32_t *otp_value, uint32_t word);
uint32_t bsec_check_nsec_access_rights(uint32_t otp);
diff --git a/include/drivers/st/stm32_hash.h b/include/drivers/st/stm32_hash.h
new file mode 100644
index 0000000..969d7aa
--- /dev/null
+++ b/include/drivers/st/stm32_hash.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2019, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32_HASH_H
+#define STM32_HASH_H
+
+enum stm32_hash_algo_mode {
+ HASH_MD5SUM,
+ HASH_SHA1,
+ HASH_SHA224,
+ HASH_SHA256
+};
+
+int stm32_hash_update(const uint8_t *buffer, uint32_t length);
+int stm32_hash_final(uint8_t *digest);
+int stm32_hash_final_update(const uint8_t *buffer, uint32_t buf_length,
+ uint8_t *digest);
+void stm32_hash_init(enum stm32_hash_algo_mode mode);
+int stm32_hash_register(void);
+
+#endif /* STM32_HASH_H */
diff --git a/include/lib/psci/psci.h b/include/lib/psci/psci.h
index 04e5e3d..7f7b7e3 100644
--- a/include/lib/psci/psci.h
+++ b/include/lib/psci/psci.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -301,6 +301,8 @@
const psci_power_state_t *target_state);
void (*pwr_domain_suspend)(const psci_power_state_t *target_state);
void (*pwr_domain_on_finish)(const psci_power_state_t *target_state);
+ void (*pwr_domain_on_finish_late)(
+ const psci_power_state_t *target_state);
void (*pwr_domain_suspend_finish)(
const psci_power_state_t *target_state);
void __dead2 (*pwr_domain_pwr_down_wfi)(
diff --git a/include/plat/arm/css/common/css_pm.h b/include/plat/arm/css/common/css_pm.h
index b82ff47..93f8616 100644
--- a/include/plat/arm/css/common/css_pm.h
+++ b/include/plat/arm/css/common/css_pm.h
@@ -27,6 +27,7 @@
int css_pwr_domain_on(u_register_t mpidr);
void css_pwr_domain_on_finish(const psci_power_state_t *target_state);
+void css_pwr_domain_on_finish_late(const psci_power_state_t *target_state);
void css_pwr_domain_off(const psci_power_state_t *target_state);
void css_pwr_domain_suspend(const psci_power_state_t *target_state);
void css_pwr_domain_suspend_finish(
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index a05ee5a..d65e02d 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -142,11 +142,11 @@
* world, and only for the secure world when CTX_INCLUDE_MTE_REGS is
* set.
*/
- unsigned int mte = get_armv8_5_mte_support();
#if CTX_INCLUDE_MTE_REGS
- assert(mte == MTE_IMPLEMENTED_ELX);
+ assert(get_armv8_5_mte_support() == MTE_IMPLEMENTED_ELX);
scr_el3 |= SCR_ATA_BIT;
#else
+ unsigned int mte = get_armv8_5_mte_support();
if (mte == MTE_IMPLEMENTED_EL0) {
/*
* Can enable MTE across both worlds as no MTE registers are
diff --git a/lib/psci/psci_on.c b/lib/psci/psci_on.c
index aa6b324..470b4f3 100644
--- a/lib/psci/psci_on.c
+++ b/lib/psci/psci_on.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -182,6 +182,14 @@
#endif
/*
+ * Plat. management: Perform any platform specific actions which
+ * can only be done with the cpu and the cluster guaranteed to
+ * be coherent.
+ */
+ if (psci_plat_pm_ops->pwr_domain_on_finish_late != NULL)
+ psci_plat_pm_ops->pwr_domain_on_finish_late(state_info);
+
+ /*
* All the platform specific actions for turning this cpu
* on have completed. Perform enough arch.initialization
* to run in the non-secure address space.
diff --git a/plat/amlogic/g12a/g12a_bl31_setup.c b/plat/amlogic/g12a/g12a_bl31_setup.c
new file mode 100644
index 0000000..77057a1
--- /dev/null
+++ b/plat/amlogic/g12a/g12a_bl31_setup.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/bl_common.h>
+#include <common/interrupt_props.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include "aml_private.h"
+
+/*
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL31 from BL2.
+ */
+static entry_point_info_t bl32_image_ep_info;
+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;
+
+ next_image_info = (type == NON_SECURE) ?
+ &bl33_image_ep_info : &bl32_image_ep_info;
+
+ /* None of the images can have 0x0 as the entrypoint. */
+ if (next_image_info->pc != 0U)
+ return next_image_info;
+
+ 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 g12a_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 g12a_bl31_param *from_bl2;
+
+ /* Initialize the console to provide early debug support */
+ aml_console_init();
+
+ from_bl2 = (struct g12a_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 BL32 and BL33 entry point information. It is stored in Secure
+ * RAM, in BL2's address space.
+ */
+ bl32_image_ep_info = *from_bl2->bl32_ep_info;
+ 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)
+{
+ aml_setup_page_tables();
+
+ enable_mmu_el3(0);
+}
+
+/*******************************************************************************
+ * GICv2 driver setup information
+ ******************************************************************************/
+static const interrupt_prop_t g12a_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 g12a_gic_data = {
+ .gicd_base = AML_GICD_BASE,
+ .gicc_base = AML_GICC_BASE,
+ .interrupt_props = g12a_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(g12a_interrupt_props)
+};
+
+void bl31_platform_setup(void)
+{
+ aml_mhu_secure_init();
+
+ gicv2_driver_init(&g12a_gic_data);
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
diff --git a/plat/amlogic/g12a/g12a_common.c b/plat/amlogic/g12a/g12a_common.c
new file mode 100644
index 0000000..e74ed04
--- /dev/null
+++ b/plat/amlogic/g12a/g12a_common.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <bl31/interrupt_mgmt.h>
+#include <common/bl_common.h>
+#include <common/ep_info.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <platform_def.h>
+#include <stdint.h>
+
+/*******************************************************************************
+ * Platform memory map regions
+ ******************************************************************************/
+#define MAP_NSDRAM0 MAP_REGION_FLAT(AML_NSDRAM0_BASE, \
+ AML_NSDRAM0_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_NS_SHARE_MEM MAP_REGION_FLAT(AML_NS_SHARE_MEM_BASE, \
+ AML_NS_SHARE_MEM_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_SEC_SHARE_MEM MAP_REGION_FLAT(AML_SEC_SHARE_MEM_BASE, \
+ AML_SEC_SHARE_MEM_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE0 MAP_REGION_FLAT(AML_SEC_DEVICE0_BASE, \
+ AML_SEC_DEVICE0_SIZE, \
+ MT_DEVICE | MT_RW)
+
+#define MAP_HDCP_RX MAP_REGION_FLAT(AML_HDCP_RX_BASE, \
+ AML_HDCP_RX_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_HDCP_TX MAP_REGION_FLAT(AML_HDCP_TX_BASE, \
+ AML_HDCP_TX_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_GIC_DEVICE MAP_REGION_FLAT(AML_GIC_DEVICE_BASE, \
+ AML_GIC_DEVICE_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE1 MAP_REGION_FLAT(AML_SEC_DEVICE1_BASE, \
+ AML_SEC_DEVICE1_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE2 MAP_REGION_FLAT(AML_SEC_DEVICE2_BASE, \
+ AML_SEC_DEVICE2_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_TZRAM MAP_REGION_FLAT(AML_TZRAM_BASE, \
+ AML_TZRAM_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+static const mmap_region_t g12a_mmap[] = {
+ MAP_NSDRAM0,
+ MAP_NS_SHARE_MEM,
+ MAP_SEC_SHARE_MEM,
+ MAP_SEC_DEVICE0,
+ MAP_HDCP_RX,
+ MAP_HDCP_TX,
+ MAP_GIC_DEVICE,
+ MAP_SEC_DEVICE1,
+ MAP_SEC_DEVICE2,
+ MAP_TZRAM,
+ {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 aml_setup_page_tables(void)
+{
+#if IMAGE_BL31
+ const mmap_region_t g12a_bl_mmap[] = {
+ MAP_BL31,
+ MAP_BL_CODE,
+ MAP_BL_RO_DATA,
+#if USE_COHERENT_MEM
+ MAP_BL_COHERENT,
+#endif
+ {0}
+ };
+#endif
+
+ mmap_add(g12a_bl_mmap);
+
+ mmap_add(g12a_mmap);
+
+ init_xlat_tables();
+}
+
+/*******************************************************************************
+ * Function that returns the system counter frequency
+ ******************************************************************************/
+unsigned int plat_get_syscnt_freq2(void)
+{
+ mmio_clrbits_32(AML_SYS_CPU_CFG7, ~0xFDFFFFFF);
+ mmio_clrbits_32(AML_AO_TIMESTAMP_CNTL, ~0xFFFFFE00);
+
+ return AML_OSC24M_CLK_IN_HZ;
+}
diff --git a/plat/amlogic/g12a/g12a_def.h b/plat/amlogic/g12a/g12a_def.h
new file mode 100644
index 0000000..d032815
--- /dev/null
+++ b/plat/amlogic/g12a/g12a_def.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef G12A_DEF_H
+#define G12A_DEF_H
+
+#include <lib/utils_def.h>
+
+/*******************************************************************************
+ * System oscillator
+ ******************************************************************************/
+#define AML_OSC24M_CLK_IN_HZ ULL(24000000) /* 24 MHz */
+
+/*******************************************************************************
+ * Memory regions
+ ******************************************************************************/
+#define AML_HDCP_RX_BASE UL(0xFFE0D000)
+#define AML_HDCP_RX_SIZE UL(0x00002000)
+
+#define AML_HDCP_TX_BASE UL(0xFFE01000)
+#define AML_HDCP_TX_SIZE UL(0x00001000)
+
+#define AML_NS_SHARE_MEM_BASE UL(0x05000000)
+#define AML_NS_SHARE_MEM_SIZE UL(0x00100000)
+
+#define AML_SEC_SHARE_MEM_BASE UL(0x05200000)
+#define AML_SEC_SHARE_MEM_SIZE UL(0x00100000)
+
+#define AML_GIC_DEVICE_BASE UL(0xFFC00000)
+#define AML_GIC_DEVICE_SIZE UL(0x00008000)
+
+#define AML_NSDRAM0_BASE UL(0x01000000)
+#define AML_NSDRAM0_SIZE UL(0x0F000000)
+
+#define BL31_BASE UL(0x05100000)
+#define BL31_SIZE UL(0x00100000)
+#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
+
+/* Shared memory used for SMC services */
+#define AML_SHARE_MEM_INPUT_BASE UL(0x050FE000)
+#define AML_SHARE_MEM_OUTPUT_BASE UL(0x050FF000)
+
+#define AML_SEC_DEVICE0_BASE UL(0xFFD00000)
+#define AML_SEC_DEVICE0_SIZE UL(0x00026000)
+
+#define AML_SEC_DEVICE1_BASE UL(0xFF800000)
+#define AML_SEC_DEVICE1_SIZE UL(0x0000A000)
+
+#define AML_TZRAM_BASE UL(0xFFFA0000)
+#define AML_TZRAM_SIZE UL(0x00048000)
+
+/* Mailboxes */
+#define AML_MHU_SECURE_SCP_TO_AP_PAYLOAD UL(0xFFFE7800)
+#define AML_MHU_SECURE_AP_TO_SCP_PAYLOAD UL(0xFFFE7A00)
+#define AML_PSCI_MAILBOX_BASE UL(0xFFFE7F00)
+
+#define AML_SEC_DEVICE2_BASE UL(0xFF620000)
+#define AML_SEC_DEVICE2_SIZE UL(0x00028000)
+
+/*******************************************************************************
+ * GIC-400 and interrupt handling related constants
+ ******************************************************************************/
+#define AML_GICD_BASE UL(0xFFC01000)
+#define AML_GICC_BASE UL(0xFFC02000)
+
+#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
+#define IRQ_SEC_SGI_8 16
+
+/*******************************************************************************
+ * UART definitions
+ ******************************************************************************/
+#define AML_UART0_AO_BASE UL(0xFF803000)
+#define AML_UART0_AO_CLK_IN_HZ AML_OSC24M_CLK_IN_HZ
+#define AML_UART_BAUDRATE U(115200)
+
+/*******************************************************************************
+ * Memory-mapped I/O Registers
+ ******************************************************************************/
+#define AML_AO_TIMESTAMP_CNTL UL(0xFF8000B4)
+
+#define AML_SYS_CPU_CFG7 UL(0xFF634664)
+
+#define AML_AO_RTI_STATUS_REG3 UL(0xFF80001C)
+#define AML_AO_RTI_SCP_STAT UL(0xFF80023C)
+#define AML_AO_RTI_SCP_READY_OFF U(0x14)
+#define AML_A0_RTI_SCP_READY_MASK U(3)
+#define AML_AO_RTI_SCP_IS_READY(v) \
+ ((((v) >> AML_AO_RTI_SCP_READY_OFF) & \
+ AML_A0_RTI_SCP_READY_MASK) == AML_A0_RTI_SCP_READY_MASK)
+
+#define AML_HIU_MAILBOX_SET_0 UL(0xFF63C404)
+#define AML_HIU_MAILBOX_STAT_0 UL(0xFF63C408)
+#define AML_HIU_MAILBOX_CLR_0 UL(0xFF63C40C)
+#define AML_HIU_MAILBOX_SET_3 UL(0xFF63C428)
+#define AML_HIU_MAILBOX_STAT_3 UL(0xFF63C42C)
+#define AML_HIU_MAILBOX_CLR_3 UL(0xFF63C430)
+
+#define AML_SHA_DMA_BASE UL(0xFF63E000)
+#define AML_SHA_DMA_DESC (AML_SHA_DMA_BASE + 0x08)
+#define AML_SHA_DMA_STATUS (AML_SHA_DMA_BASE + 0x28)
+
+/*******************************************************************************
+ * System Monitor Call IDs and arguments
+ ******************************************************************************/
+#define AML_SM_GET_SHARE_MEM_INPUT_BASE U(0x82000020)
+#define AML_SM_GET_SHARE_MEM_OUTPUT_BASE U(0x82000021)
+
+#define AML_SM_EFUSE_READ U(0x82000030)
+#define AML_SM_EFUSE_USER_MAX U(0x82000033)
+
+#define AML_SM_JTAG_ON U(0x82000040)
+#define AML_SM_JTAG_OFF U(0x82000041)
+#define AML_SM_GET_CHIP_ID U(0x82000044)
+
+#define AML_JTAG_STATE_ON U(0)
+#define AML_JTAG_STATE_OFF U(1)
+
+#define AML_JTAG_M3_AO U(0)
+#define AML_JTAG_M3_EE U(1)
+#define AML_JTAG_A53_AO U(2)
+#define AML_JTAG_A53_EE U(3)
+
+#endif /* G12A_DEF_H */
diff --git a/plat/amlogic/g12a/g12a_pm.c b/plat/amlogic/g12a/g12a_pm.c
new file mode 100644
index 0000000..c9fe3e9
--- /dev/null
+++ b/plat/amlogic/g12a/g12a_pm.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <common/debug.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/console.h>
+#include <errno.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include "aml_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 g12a_sec_entrypoint;
+static volatile uint32_t g12a_cpu0_go;
+
+static void g12a_pm_set_reset_addr(u_register_t mpidr, uint64_t value)
+{
+ unsigned int core = plat_calc_core_pos(mpidr);
+ uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4);
+
+ mmio_write_64(cpu_mailbox_addr, value);
+}
+
+static void g12a_pm_reset(u_register_t mpidr)
+{
+ unsigned int core = plat_calc_core_pos(mpidr);
+ uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4) + 8;
+
+ mmio_write_32(cpu_mailbox_addr, 0);
+}
+
+static void __dead2 g12a_system_reset(void)
+{
+ INFO("BL31: PSCI_SYSTEM_RESET\n");
+
+ u_register_t mpidr = read_mpidr_el1();
+ uint32_t status = mmio_read_32(AML_AO_RTI_STATUS_REG3);
+ int ret;
+
+ NOTICE("BL31: Reboot reason: 0x%x\n", status);
+
+ status &= 0xFFFF0FF0;
+
+ console_flush();
+
+ mmio_write_32(AML_AO_RTI_STATUS_REG3, status);
+
+ ret = aml_scpi_sys_power_state(SCPI_SYSTEM_REBOOT);
+
+ if (ret != 0) {
+ ERROR("BL31: PSCI_SYSTEM_RESET: SCP error: %i\n", ret);
+ panic();
+ }
+
+ g12a_pm_reset(mpidr);
+
+ wfi();
+
+ ERROR("BL31: PSCI_SYSTEM_RESET: Operation not handled\n");
+ panic();
+}
+
+static void __dead2 g12a_system_off(void)
+{
+ INFO("BL31: PSCI_SYSTEM_OFF\n");
+
+ u_register_t mpidr = read_mpidr_el1();
+ int ret;
+
+ ret = aml_scpi_sys_power_state(SCPI_SYSTEM_SHUTDOWN);
+
+ if (ret != 0) {
+ ERROR("BL31: PSCI_SYSTEM_OFF: SCP error %i\n", ret);
+ panic();
+ }
+
+ g12a_pm_set_reset_addr(mpidr, 0);
+ g12a_pm_reset(mpidr);
+
+ wfi();
+
+ ERROR("BL31: PSCI_SYSTEM_OFF: Operation not handled\n");
+ panic();
+}
+
+static int32_t g12a_pwr_domain_on(u_register_t mpidr)
+{
+ unsigned int core = plat_calc_core_pos(mpidr);
+
+ /* CPU0 can't be turned OFF */
+ if (core == AML_PRIMARY_CPU) {
+ VERBOSE("BL31: Releasing CPU0 from wait loop...\n");
+
+ g12a_cpu0_go = 1;
+ flush_dcache_range((uintptr_t)&g12a_cpu0_go,
+ sizeof(g12a_cpu0_go));
+ dsb();
+ isb();
+
+ sev();
+
+ return PSCI_E_SUCCESS;
+ }
+
+ g12a_pm_set_reset_addr(mpidr, g12a_sec_entrypoint);
+ aml_scpi_set_css_power_state(mpidr,
+ SCPI_POWER_ON, SCPI_POWER_ON, SCPI_POWER_ON);
+ dmbsy();
+ sev();
+
+ return PSCI_E_SUCCESS;
+}
+
+static void g12a_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ unsigned int core = plat_calc_core_pos(read_mpidr_el1());
+
+ assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+ PLAT_LOCAL_STATE_OFF);
+
+ if (core == AML_PRIMARY_CPU) {
+ g12a_cpu0_go = 0;
+ flush_dcache_range((uintptr_t)&g12a_cpu0_go,
+ sizeof(g12a_cpu0_go));
+ dsb();
+ isb();
+ }
+
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
+
+static void g12a_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ unsigned int core = plat_calc_core_pos(mpidr);
+
+ gicv2_cpuif_disable();
+
+ /* CPU0 can't be turned OFF */
+ if (core == AML_PRIMARY_CPU)
+ return;
+
+ aml_scpi_set_css_power_state(mpidr,
+ SCPI_POWER_OFF, SCPI_POWER_ON,
+ SCPI_POWER_ON);
+}
+
+static void __dead2 g12a_pwr_domain_pwr_down_wfi(const psci_power_state_t
+ *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ unsigned int core = plat_calc_core_pos(mpidr);
+
+ /* CPU0 can't be turned OFF, emulate it with a WFE loop */
+ if (core == AML_PRIMARY_CPU) {
+ VERBOSE("BL31: CPU0 entering wait loop...\n");
+
+ while (g12a_cpu0_go == 0)
+ wfe();
+
+ VERBOSE("BL31: CPU0 resumed.\n");
+
+ /*
+ * Because setting CPU0's warm reset entrypoint through PSCI
+ * mailbox and/or mmio mapped RVBAR (0xda834650) does not seem
+ * to work, jump to it manually.
+ * In order to avoid an assert, MMU has to be disabled.
+ */
+ disable_mmu_el3();
+ ((void(*)(void))g12a_sec_entrypoint)();
+ }
+
+ dsbsy();
+ g12a_pm_set_reset_addr(mpidr, 0);
+ g12a_pm_reset(mpidr);
+
+ for (;;)
+ wfi();
+}
+
+/*******************************************************************************
+ * Platform handlers and setup function.
+ ******************************************************************************/
+static const plat_psci_ops_t g12a_ops = {
+ .pwr_domain_on = g12a_pwr_domain_on,
+ .pwr_domain_on_finish = g12a_pwr_domain_on_finish,
+ .pwr_domain_off = g12a_pwr_domain_off,
+ .pwr_domain_pwr_down_wfi = g12a_pwr_domain_pwr_down_wfi,
+ .system_off = g12a_system_off,
+ .system_reset = g12a_system_reset
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ g12a_sec_entrypoint = sec_entrypoint;
+ *psci_ops = &g12a_ops;
+ g12a_cpu0_go = 0;
+ return 0;
+}
diff --git a/plat/amlogic/g12a/include/platform_def.h b/plat/amlogic/g12a/include/platform_def.h
new file mode 100644
index 0000000..23d816d
--- /dev/null
+++ b/plat/amlogic/g12a/include/platform_def.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2019, 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 "../g12a_def.h"
+
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+#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 AML_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 16
+#define MAX_XLAT_TABLES 8
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/amlogic/g12a/platform.mk b/plat/amlogic/g12a/platform.mk
new file mode 100644
index 0000000..b0c91b0
--- /dev/null
+++ b/plat/amlogic/g12a/platform.mk
@@ -0,0 +1,91 @@
+#
+# Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include lib/xlat_tables_v2/xlat_tables.mk
+
+AML_PLAT := plat/amlogic
+AML_PLAT_SOC := ${AML_PLAT}/${PLAT}
+AML_PLAT_COMMON := ${AML_PLAT}/common
+
+DOIMAGEPATH ?= tools/amlogic
+DOIMAGETOOL ?= ${DOIMAGEPATH}/doimage
+
+PLAT_INCLUDES := -Iinclude/drivers/amlogic/ \
+ -I${AML_PLAT_SOC}/include \
+ -I${AML_PLAT_COMMON}/include
+
+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
+
+BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
+ plat/common/plat_psci_common.c \
+ drivers/amlogic/console/aarch64/meson_console.S \
+ ${AML_PLAT_SOC}/${PLAT}_bl31_setup.c \
+ ${AML_PLAT_SOC}/${PLAT}_pm.c \
+ ${AML_PLAT_SOC}/${PLAT}_common.c \
+ ${AML_PLAT_COMMON}/aarch64/aml_helpers.S \
+ ${AML_PLAT_COMMON}/aml_efuse.c \
+ ${AML_PLAT_COMMON}/aml_mhu.c \
+ ${AML_PLAT_COMMON}/aml_scpi.c \
+ ${AML_PLAT_COMMON}/aml_sip_svc.c \
+ ${AML_PLAT_COMMON}/aml_thermal.c \
+ ${AML_PLAT_COMMON}/aml_topology.c \
+ ${AML_PLAT_COMMON}/aml_console.c \
+ drivers/amlogic/crypto/sha_dma.c \
+ ${XLAT_TABLES_LIB_SRCS} \
+ ${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
+
+# Verify build config
+# -------------------
+
+ifneq (${RESET_TO_BL31}, 0)
+ $(error Error: ${PLAT} needs RESET_TO_BL31=0)
+endif
+
+ifeq (${ARCH},aarch32)
+ $(error Error: AArch32 not supported on ${PLAT})
+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/plat/amlogic/gxbb/gxbb_def.h b/plat/amlogic/gxbb/gxbb_def.h
index 59d9cc9..fa5e4fa 100644
--- a/plat/amlogic/gxbb/gxbb_def.h
+++ b/plat/amlogic/gxbb/gxbb_def.h
@@ -95,6 +95,10 @@
#define AML_HIU_MAILBOX_STAT_3 UL(0xDA83C42C)
#define AML_HIU_MAILBOX_CLR_3 UL(0xDA83C430)
+#define AML_SHA_DMA_BASE UL(0xC883E000)
+#define AML_SHA_DMA_DESC (AML_SHA_DMA_BASE + 0x08)
+#define AML_SHA_DMA_STATUS (AML_SHA_DMA_BASE + 0x18)
+
/*******************************************************************************
* System Monitor Call IDs and arguments
******************************************************************************/
diff --git a/plat/amlogic/gxbb/platform.mk b/plat/amlogic/gxbb/platform.mk
index 57167b0..62384d2 100644
--- a/plat/amlogic/gxbb/platform.mk
+++ b/plat/amlogic/gxbb/platform.mk
@@ -22,9 +22,9 @@
BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
plat/common/plat_psci_common.c \
drivers/amlogic/console/aarch64/meson_console.S \
- ${AML_PLAT_SOC}/gxbb_bl31_setup.c \
- ${AML_PLAT_SOC}/gxbb_pm.c \
- ${AML_PLAT_SOC}/gxbb_common.c \
+ ${AML_PLAT_SOC}/${PLAT}_bl31_setup.c \
+ ${AML_PLAT_SOC}/${PLAT}_pm.c \
+ ${AML_PLAT_SOC}/${PLAT}_common.c \
${AML_PLAT_COMMON}/aarch64/aml_helpers.S \
${AML_PLAT_COMMON}/aml_efuse.c \
${AML_PLAT_COMMON}/aml_mhu.c \
diff --git a/plat/amlogic/gxl/gxl_def.h b/plat/amlogic/gxl/gxl_def.h
index 1e1a934..f30eb28 100644
--- a/plat/amlogic/gxl/gxl_def.h
+++ b/plat/amlogic/gxl/gxl_def.h
@@ -105,6 +105,10 @@
#define AML_HIU_MAILBOX_STAT_3 UL(0xDA83C42C)
#define AML_HIU_MAILBOX_CLR_3 UL(0xDA83C430)
+#define AML_SHA_DMA_BASE UL(0xC883E000)
+#define AML_SHA_DMA_DESC (AML_SHA_DMA_BASE + 0x08)
+#define AML_SHA_DMA_STATUS (AML_SHA_DMA_BASE + 0x18)
+
/*******************************************************************************
* System Monitor Call IDs and arguments
******************************************************************************/
diff --git a/plat/amlogic/gxl/platform.mk b/plat/amlogic/gxl/platform.mk
index 2e47670..641d177 100644
--- a/plat/amlogic/gxl/platform.mk
+++ b/plat/amlogic/gxl/platform.mk
@@ -25,9 +25,9 @@
BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
plat/common/plat_psci_common.c \
drivers/amlogic/console/aarch64/meson_console.S \
- ${AML_PLAT_SOC}/gxl_bl31_setup.c \
- ${AML_PLAT_SOC}/gxl_pm.c \
- ${AML_PLAT_SOC}/gxl_common.c \
+ ${AML_PLAT_SOC}/${PLAT}_bl31_setup.c \
+ ${AML_PLAT_SOC}/${PLAT}_pm.c \
+ ${AML_PLAT_SOC}/${PLAT}_common.c \
${AML_PLAT_COMMON}/aarch64/aml_helpers.S \
${AML_PLAT_COMMON}/aml_efuse.c \
${AML_PLAT_COMMON}/aml_mhu.c \
diff --git a/plat/arm/board/a5ds/a5ds_pm.c b/plat/arm/board/a5ds/a5ds_pm.c
index 5fd443b..98de77d 100644
--- a/plat/arm/board/a5ds/a5ds_pm.c
+++ b/plat/arm/board/a5ds/a5ds_pm.c
@@ -6,6 +6,38 @@
#include <lib/psci/psci.h>
#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <drivers/arm/gicv2.h>
+
+/*******************************************************************************
+ * Platform handler called when a power domain is about to be turned on. The
+ * mpidr determines the CPU to be turned on.
+ ******************************************************************************/
+static int a5ds_pwr_domain_on(u_register_t mpidr)
+{
+ unsigned int pos = plat_core_pos_by_mpidr(mpidr);
+ uint64_t *hold_base = (uint64_t *)A5DS_HOLD_BASE;
+
+ hold_base[pos] = A5DS_HOLD_STATE_GO;
+ dsbish();
+ sev();
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Platform handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ ******************************************************************************/
+void a5ds_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ /* TODO: This setup is needed only after a cold boot*/
+ gicv2_pcpu_distif_init();
+
+ /* Enable the gic cpu interface */
+ gicv2_cpuif_enable();
+}
/*******************************************************************************
* Export the platform handlers via a5ds_psci_pm_ops. The ARM Standard
@@ -14,11 +46,16 @@
plat_psci_ops_t a5ds_psci_pm_ops = {
/* dummy struct */
.validate_ns_entrypoint = NULL,
+ .pwr_domain_on = a5ds_pwr_domain_on,
+ .pwr_domain_on_finish = a5ds_pwr_domain_on_finish
};
int __init plat_setup_psci_ops(uintptr_t sec_entrypoint,
const plat_psci_ops_t **psci_ops)
{
+ uintptr_t *mailbox = (void *)A5DS_TRUSTED_MAILBOX_BASE;
+ *mailbox = sec_entrypoint;
+
*psci_ops = &a5ds_psci_pm_ops;
return 0;
diff --git a/plat/arm/board/a5ds/aarch32/a5ds_helpers.S b/plat/arm/board/a5ds/aarch32/a5ds_helpers.S
index 23a22d9..ed7ad9c 100644
--- a/plat/arm/board/a5ds/aarch32/a5ds_helpers.S
+++ b/plat/arm/board/a5ds/aarch32/a5ds_helpers.S
@@ -12,17 +12,36 @@
.globl plat_get_my_entrypoint
.globl plat_is_my_cpu_primary
- /* --------------------------------------------------------------------
+ /* -----------------------------------------------------
* void plat_secondary_cold_boot_setup (void);
*
- * For AArch32, cold-booting secondary CPUs is not yet
- * implemented and they panic.
- * --------------------------------------------------------------------
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ * -----------------------------------------------------
*/
func plat_secondary_cold_boot_setup
-cb_panic:
- wfi
- b cb_panic
+ /* Calculate address of our hold entry */
+ bl plat_my_core_pos
+ lsl r0, r0, #A5DS_HOLD_ENTRY_SHIFT
+ mov_imm r2, A5DS_HOLD_BASE
+ /* Clear the value stored in the hold address for the specific core */
+ mov_imm r3, A5DS_HOLD_STATE_WAIT
+ str r3, [r2, r0]
+ dmb ish
+
+ /* Wait until we have a go */
+poll_mailbox:
+ ldr r1, [r2, r0]
+ cmp r1, #A5DS_HOLD_STATE_WAIT
+ beq 1f
+ mov_imm r0, A5DS_TRUSTED_MAILBOX_BASE
+ ldr r1, [r0]
+ bx r1
+1:
+ wfe
+ b poll_mailbox
endfunc plat_secondary_cold_boot_setup
/* ---------------------------------------------------------------------
@@ -56,3 +75,52 @@
movne r0, #0
bx lr
endfunc plat_is_my_cpu_primary
+
+ /* ---------------------------------------------------------------------
+ * Loads MPIDR in r0 and calls plat_arm_calc_core_pos
+ * ---------------------------------------------------------------------
+ */
+func plat_my_core_pos
+ ldcopr r0, MPIDR
+ b plat_arm_calc_core_pos
+
+endfunc plat_my_core_pos
+
+ /* ---------------------------------------------------------------------
+ * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
+ *
+ * Function to calculate the core position on A5DS.
+ *
+ * (ClusterId * A5DS_MAX_CPUS_PER_CLUSTER * A5DS_MAX_PE_PER_CPU) +
+ * (CPUId * A5DS_MAX_PE_PER_CPU) +
+ * ThreadId
+ *
+ * which can be simplified as:
+ *
+ * ((ClusterId * A5DS_MAX_CPUS_PER_CLUSTER + CPUId) * A5DS_MAX_PE_PER_CPU)
+ * + ThreadId
+ * ---------------------------------------------------------------------
+ */
+func plat_arm_calc_core_pos
+ mov r3, r0
+
+ /*
+ * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
+ * look as if in a multi-threaded implementation
+ */
+ tst r0, #MPIDR_MT_MASK
+ lsleq r3, r0, #MPIDR_AFFINITY_BITS
+
+ /* Extract individual affinity fields from MPIDR */
+ ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+
+ /* Compute linear position */
+ mov r3, #A5DS_MAX_CPUS_PER_CLUSTER
+ mla r1, r2, r3, r1
+ mov r3, #A5DS_MAX_PE_PER_CPU
+ mla r0, r1, r3, r0
+
+ bx lr
+endfunc plat_arm_calc_core_pos
diff --git a/plat/arm/board/a5ds/include/platform_def.h b/plat/arm/board/a5ds/include/platform_def.h
index db65c37..e9e4b9a 100644
--- a/plat/arm/board/a5ds/include/platform_def.h
+++ b/plat/arm/board/a5ds/include/platform_def.h
@@ -97,9 +97,9 @@
/* Default number of threads per CPU on A5DS */
#define A5DS_MAX_PE_PER_CPU 1
-#define A5DS_CORE_COUNT 1
+#define A5DS_CORE_COUNT 4
-#define A5DS_PRIMARY_CPU 0x0
+#define A5DS_PRIMARY_CPU 0x0
#define FLASH1_BASE UL(0x8000000)
#define FLASH1_SIZE UL(0x2800000)
@@ -229,11 +229,11 @@
#define BL32_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
/* Required platform porting definitions */
-#define PLATFORM_CORE_COUNT 1
-#define PLAT_NUM_PWR_DOMAINS (A5DS_CLUSTER_COUNT + \
+#define PLATFORM_CORE_COUNT A5DS_CORE_COUNT
+#define PLAT_NUM_PWR_DOMAINS (A5DS_CLUSTER_COUNT + \
PLATFORM_CORE_COUNT) + 1
-#define PLAT_MAX_PWR_LVL 2
+#define PLAT_MAX_PWR_LVL 2
/*
* Other platform porting definitions are provided by included headers
@@ -325,6 +325,14 @@
/* Mailbox base address */
#define A5DS_TRUSTED_MAILBOX_BASE A5DS_SHARED_RAM_BASE
+#define A5DS_TRUSTED_MAILBOX_SIZE (8 + A5DS_HOLD_SIZE)
+#define A5DS_HOLD_BASE (A5DS_TRUSTED_MAILBOX_BASE + 8)
+#define A5DS_HOLD_SIZE (PLATFORM_CORE_COUNT * \
+ A5DS_HOLD_ENTRY_SIZE)
+#define A5DS_HOLD_ENTRY_SHIFT 3
+#define A5DS_HOLD_ENTRY_SIZE (1 << A5DS_HOLD_ENTRY_SHIFT)
+#define A5DS_HOLD_STATE_WAIT 0
+#define A5DS_HOLD_STATE_GO 1
/*
* GIC related constants to cater for GICv2
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
index 42dec8d..0a62543 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -247,10 +247,19 @@
{
fvp_power_domain_on_finish_common(target_state);
- /* Enable the gic cpu interface */
+}
+
+/*******************************************************************************
+ * FVP handler called when a power domain has just been powered on and the cpu
+ * and its cluster are fully participating in coherent transaction on the
+ * interconnect. Data cache must be enabled for CPU at this point.
+ ******************************************************************************/
+static void fvp_pwr_domain_on_finish_late(const psci_power_state_t *target_state)
+{
+ /* Program GIC per-cpu distributor or re-distributor interface */
plat_arm_gic_pcpu_init();
- /* Program the gic per-cpu distributor or re-distributor interface */
+ /* Enable GIC CPU interface */
plat_arm_gic_cpuif_enable();
}
@@ -272,7 +281,7 @@
fvp_power_domain_on_finish_common(target_state);
- /* Enable the gic cpu interface */
+ /* Enable GIC CPU interface */
plat_arm_gic_cpuif_enable();
}
@@ -397,6 +406,7 @@
.pwr_domain_off = fvp_pwr_domain_off,
.pwr_domain_suspend = fvp_pwr_domain_suspend,
.pwr_domain_on_finish = fvp_pwr_domain_on_finish,
+ .pwr_domain_on_finish_late = fvp_pwr_domain_on_finish_late,
.pwr_domain_suspend_finish = fvp_pwr_domain_suspend_finish,
.system_off = fvp_system_off,
.system_reset = fvp_system_reset,
diff --git a/plat/arm/common/arm_gicv3.c b/plat/arm/common/arm_gicv3.c
index 7f4957f..fef5376 100644
--- a/plat/arm/common/arm_gicv3.c
+++ b/plat/arm/common/arm_gicv3.c
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <assert.h>
#include <platform_def.h>
#include <common/interrupt_props.h>
@@ -67,7 +68,7 @@
static const gicv3_driver_data_t arm_gic_data __unused = {
.gicd_base = PLAT_ARM_GICD_BASE,
- .gicr_base = PLAT_ARM_GICR_BASE,
+ .gicr_base = 0U,
.interrupt_props = arm_interrupt_props,
.interrupt_props_num = ARRAY_SIZE(arm_interrupt_props),
.rdistif_num = PLATFORM_CORE_COUNT,
@@ -86,6 +87,11 @@
#if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \
(defined(__aarch64__) && defined(IMAGE_BL31))
gicv3_driver_init(&arm_gic_data);
+
+ if (gicv3_rdistif_probe(PLAT_ARM_GICR_BASE) == -1) {
+ ERROR("No GICR base frame found for Primary CPU\n");
+ panic();
+ }
#endif
}
@@ -116,10 +122,20 @@
}
/******************************************************************************
- * ARM common helper to initialize the per-cpu redistributor interface in GICv3
+ * ARM common helper function to iterate over all GICR frames and discover the
+ * corresponding per-cpu redistributor frame as well as initialize the
+ * corresponding interface in GICv3. At the moment, Arm platforms do not have
+ * non-contiguous GICR frames.
*****************************************************************************/
void plat_arm_gic_pcpu_init(void)
{
+ int result;
+
+ result = gicv3_rdistif_probe(PLAT_ARM_GICR_BASE);
+ if (result == -1) {
+ ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr());
+ panic();
+ }
gicv3_rdistif_init(plat_my_core_pos());
}
diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c
index f6fc6aa..01c674f 100644
--- a/plat/arm/css/common/css_pm.c
+++ b/plat/arm/css/common/css_pm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -76,9 +76,6 @@
{
assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF);
- /* Enable the gic cpu interface */
- plat_arm_gic_cpuif_enable();
-
/*
* Perform the common cluster specific operations i.e enable coherency
* if this cluster was off.
@@ -100,10 +97,21 @@
/* Assert that the system power domain need not be initialized */
assert(css_system_pwr_state(target_state) == ARM_LOCAL_STATE_RUN);
+ css_pwr_domain_on_finisher_common(target_state);
+}
+
+/*******************************************************************************
+ * Handler called when a power domain has just been powered on and the cpu
+ * and its cluster are fully participating in coherent transaction on the
+ * interconnect. Data cache must be enabled for CPU at this point.
+ ******************************************************************************/
+void css_pwr_domain_on_finish_late(const psci_power_state_t *target_state)
+{
/* Program the gic per-cpu distributor or re-distributor interface */
plat_arm_gic_pcpu_init();
- css_pwr_domain_on_finisher_common(target_state);
+ /* Enable the gic cpu interface */
+ plat_arm_gic_cpuif_enable();
}
/*******************************************************************************
@@ -185,6 +193,9 @@
arm_system_pwr_domain_resume();
css_pwr_domain_on_finisher_common(target_state);
+
+ /* Enable the gic cpu interface */
+ plat_arm_gic_cpuif_enable();
}
/*******************************************************************************
@@ -306,6 +317,7 @@
plat_psci_ops_t plat_arm_psci_pm_ops = {
.pwr_domain_on = css_pwr_domain_on,
.pwr_domain_on_finish = css_pwr_domain_on_finish,
+ .pwr_domain_on_finish_late = css_pwr_domain_on_finish_late,
.pwr_domain_off = css_pwr_domain_off,
.cpu_standby = css_cpu_standby,
.pwr_domain_suspend = css_pwr_domain_suspend,
diff --git a/plat/rpi/common/include/rpi_shared.h b/plat/rpi/common/include/rpi_shared.h
index 6863438..de83571 100644
--- a/plat/rpi/common/include/rpi_shared.h
+++ b/plat/rpi/common/include/rpi_shared.h
@@ -14,7 +14,7 @@
******************************************************************************/
/* Utility functions */
-void rpi3_console_init(void);
+void rpi3_console_init(unsigned int base_clk_rate);
void rpi3_setup_page_tables(uintptr_t total_base, size_t total_size,
uintptr_t code_start, uintptr_t code_limit,
uintptr_t rodata_start, uintptr_t rodata_limit
diff --git a/plat/rpi/common/rpi3_common.c b/plat/rpi/common/rpi3_common.c
index ab63d98..ff33694 100644
--- a/plat/rpi/common/rpi3_common.c
+++ b/plat/rpi/common/rpi3_common.c
@@ -104,14 +104,14 @@
******************************************************************************/
static console_16550_t rpi3_console;
-void rpi3_console_init(void)
+void rpi3_console_init(unsigned int base_clk_rate)
{
int console_scope = CONSOLE_FLAG_BOOT;
#if RPI3_RUNTIME_UART != -1
console_scope |= CONSOLE_FLAG_RUNTIME;
#endif
int rc = console_16550_register(PLAT_RPI3_UART_BASE,
- PLAT_RPI3_UART_CLK_IN_HZ,
+ base_clk_rate,
PLAT_RPI3_UART_BAUDRATE,
&rpi3_console);
if (rc == 0) {
@@ -176,18 +176,6 @@
}
/*******************************************************************************
- * Return entrypoint of BL33.
- ******************************************************************************/
-uintptr_t plat_get_ns_image_entrypoint(void)
-{
-#ifdef PRELOADED_BL33_BASE
- return PRELOADED_BL33_BASE;
-#else
- return PLAT_RPI3_NS_IMAGE_OFFSET;
-#endif
-}
-
-/*******************************************************************************
* Gets SPSR for BL32 entry
******************************************************************************/
uint32_t rpi3_get_spsr_for_bl32_entry(void)
diff --git a/plat/rpi/rpi3/rpi3_bl1_setup.c b/plat/rpi/rpi3/rpi3_bl1_setup.c
index 3ac30e0..dcce76e 100644
--- a/plat/rpi/rpi3/rpi3_bl1_setup.c
+++ b/plat/rpi/rpi3/rpi3_bl1_setup.c
@@ -35,7 +35,7 @@
0x80000000);
/* Initialize the console to provide early debug support */
- rpi3_console_init();
+ rpi3_console_init(PLAT_RPI3_UART_CLK_IN_HZ);
/* Allow BL1 to see the whole Trusted RAM */
bl1_tzram_layout.total_base = BL_RAM_BASE;
diff --git a/plat/rpi/rpi3/rpi3_bl2_setup.c b/plat/rpi/rpi3/rpi3_bl2_setup.c
index 991c0fc..44827c6 100644
--- a/plat/rpi/rpi3/rpi3_bl2_setup.c
+++ b/plat/rpi/rpi3/rpi3_bl2_setup.c
@@ -62,7 +62,7 @@
meminfo_t *mem_layout = (meminfo_t *) arg1;
/* Initialize the console to provide early debug support */
- rpi3_console_init();
+ rpi3_console_init(PLAT_RPI3_UART_CLK_IN_HZ);
/* Enable arch timer */
generic_delay_timer_init();
diff --git a/plat/rpi/rpi3/rpi3_bl31_setup.c b/plat/rpi/rpi3/rpi3_bl31_setup.c
index a9efc52..24a5613 100644
--- a/plat/rpi/rpi3/rpi3_bl31_setup.c
+++ b/plat/rpi/rpi3/rpi3_bl31_setup.c
@@ -48,6 +48,18 @@
}
/*******************************************************************************
+ * Return entrypoint of BL33.
+ ******************************************************************************/
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#ifdef PRELOADED_BL33_BASE
+ return PRELOADED_BL33_BASE;
+#else
+ return PLAT_RPI3_NS_IMAGE_OFFSET;
+#endif
+}
+
+/*******************************************************************************
* Perform any BL31 early platform setup. Here is an opportunity to copy
* parameters passed by the calling EL (S-EL1 in BL2 & EL3 in BL1) before
* they are lost (potentially). This needs to be done before the MMU is
@@ -60,7 +72,7 @@
{
/* Initialize the console to provide early debug support */
- rpi3_console_init();
+ rpi3_console_init(PLAT_RPI3_UART_CLK_IN_HZ);
/*
* In debug builds, a special value is passed in 'arg1' to verify
diff --git a/plat/rpi/rpi4/aarch64/armstub8_header.S b/plat/rpi/rpi4/aarch64/armstub8_header.S
new file mode 100644
index 0000000..246358d
--- /dev/null
+++ b/plat/rpi/rpi4/aarch64/armstub8_header.S
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * armstub8.bin header to let the GPU firmware recognise this code.
+ * It will then write the load address of the kernel image and the DT
+ * after the header magic in RAM, so we can read those addresses at runtime.
+ */
+
+.text
+ b armstub8_end
+
+.global stub_magic
+.global dtb_ptr32
+.global kernel_entry32
+
+.org 0xf0
+armstub8:
+stub_magic:
+ .word 0x5afe570b
+stub_version:
+ .word 0
+dtb_ptr32:
+ .word 0x0
+kernel_entry32:
+ .word 0x0
+
+/*
+ * Technically an offset of 0x100 would suffice, but the follow-up code
+ * (bl31_entrypoint.S at BL31_BASE) needs to be page aligned, so pad here
+ * till the end of the first 4K page.
+ */
+.org 0x1000
+armstub8_end:
diff --git a/plat/rpi/rpi4/aarch64/plat_helpers.S b/plat/rpi/rpi4/aarch64/plat_helpers.S
new file mode 100644
index 0000000..46073b7
--- /dev/null
+++ b/plat/rpi/rpi4/aarch64/plat_helpers.S
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2015-2019, 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>
+#include <cortex_a72.h>
+
+#include "../include/rpi_hw.h"
+
+ .globl plat_crash_console_flush
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl platform_mem_init
+ .globl plat_get_my_entrypoint
+ .globl plat_is_my_cpu_primary
+ .globl plat_my_core_pos
+ .globl plat_reset_handler
+ .globl plat_rpi3_calc_core_pos
+ .globl plat_secondary_cold_boot_setup
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ *
+ * This function uses the plat_rpi3_calc_core_pos()
+ * definition to get the index of the calling CPU.
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b plat_rpi3_calc_core_pos
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr);
+ *
+ * CorePos = (ClusterId * 4) + CoreId
+ * -----------------------------------------------------
+ */
+func plat_rpi3_calc_core_pos
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc plat_rpi3_calc_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary
+ * cpu.
+ * -----------------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, #RPI4_PRIMARY_CPU
+ cset w0, eq
+ ret
+endfunc plat_is_my_cpu_primary
+
+ /* -----------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ * -----------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ /* Calculate address of our hold entry */
+ bl plat_my_core_pos
+ lsl x0, x0, #3
+ mov_imm x2, PLAT_RPI3_TM_HOLD_BASE
+ add x0, x0, x2
+
+ /*
+ * This code runs way before requesting the warmboot of this core,
+ * so it is possible to clear the mailbox before getting a request
+ * to boot.
+ */
+ mov x1, PLAT_RPI3_TM_HOLD_STATE_WAIT
+ str x1,[x0]
+
+ /* Wait until we have a go */
+poll_mailbox:
+ wfe
+ ldr x1, [x0]
+ cmp x1, PLAT_RPI3_TM_HOLD_STATE_GO
+ bne poll_mailbox
+
+ /* Jump to the provided entrypoint */
+ mov_imm x0, PLAT_RPI3_TM_ENTRYPOINT
+ ldr x1, [x0]
+ br x1
+endfunc plat_secondary_cold_boot_setup
+
+ /* ---------------------------------------------------------------------
+ * uintptr_t plat_get_my_entrypoint (void);
+ *
+ * Main job of this routine is to distinguish between a cold and a warm
+ * boot.
+ *
+ * This functions returns:
+ * - 0 for a cold boot.
+ * - Any other value for a warm boot.
+ * ---------------------------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ /* TODO: support warm boot */
+ mov x0, #0
+ ret
+endfunc plat_get_my_entrypoint
+
+ /* ---------------------------------------------
+ * void platform_mem_init (void);
+ *
+ * No need to carry out any memory initialization.
+ * ---------------------------------------------
+ */
+func platform_mem_init
+ ret
+endfunc platform_mem_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0 - x3
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+ mov_imm x0, PLAT_RPI3_UART_BASE
+ mov_imm x1, PLAT_RPI4_VPU_CLK_RATE
+ mov_imm x2, PLAT_RPI3_UART_BAUDRATE
+ b console_16550_core_init
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(int c)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ mov_imm x1, PLAT_RPI3_UART_BASE
+ b console_16550_core_putc
+endfunc plat_crash_console_putc
+
+ /* ---------------------------------------------
+ * int plat_crash_console_flush()
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * Out : return -1 on error else return 0.
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func plat_crash_console_flush
+ mov_imm x0, PLAT_RPI3_UART_BASE
+ b console_16550_core_flush
+endfunc plat_crash_console_flush
+
+ /* ---------------------------------------------
+ * void plat_reset_handler(void);
+ * ---------------------------------------------
+ */
+func plat_reset_handler
+ /* ------------------------------------------------
+ * Set L2 read/write cache latency:
+ * - L2 Data RAM latency: 3 cycles (0b010)
+ * - L2 Data RAM setup: 1 cycle (bit 5)
+ * ------------------------------------------------
+ */
+ mrs x0, CORTEX_A72_L2CTLR_EL1
+ mov x1, #0x22
+ orr x0, x0, x1
+ msr CORTEX_A72_L2CTLR_EL1, x0
+ isb
+
+ ret
+endfunc plat_reset_handler
diff --git a/plat/rpi/rpi4/include/plat.ld.S b/plat/rpi/rpi4/include/plat.ld.S
new file mode 100644
index 0000000..9262fad
--- /dev/null
+++ b/plat/rpi/rpi4/include/plat.ld.S
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Stub linker script to provide the armstub8.bin header before the actual
+ * code. If the GPU firmware finds a magic value at offset 240 in
+ * armstub8.bin, it will put the DTB and kernel load address in subsequent
+ * words. We can then read those values to find the proper NS entry point
+ * and find our DTB more flexibly.
+ */
+
+MEMORY {
+ PRERAM (rwx): ORIGIN = 0, LENGTH = 4096
+}
+
+SECTIONS
+{
+ .armstub8 . : {
+ *armstub8_header.o(.text*)
+ KEEP(*(.armstub8))
+ } >PRERAM
+}
diff --git a/plat/rpi/rpi4/include/plat_macros.S b/plat/rpi/rpi4/include/plat_macros.S
new file mode 100644
index 0000000..6007d03
--- /dev/null
+++ b/plat/rpi/rpi4/include/plat_macros.S
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+ /* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant platform registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ * Clobbers: x0 - x10, x16, x17, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/rpi/rpi4/include/platform_def.h b/plat/rpi/rpi4/include/platform_def.h
new file mode 100644
index 0000000..a9ecdba
--- /dev/null
+++ b/plat/rpi/rpi4/include/platform_def.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2015-2019, 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 <common/tbbr/tbbr_img_def.h>
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+
+#include "rpi_hw.h"
+
+/* Special value used to verify platform parameters from BL2 to BL31 */
+#define RPI3_BL31_PLAT_PARAM_VAL ULL(0x0F1E2D3C4B5A6978)
+
+#define PLATFORM_STACK_SIZE ULL(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 RPI4_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 OFF/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)
+
+/*
+ * I/O registers.
+ */
+#define DEVICE0_BASE RPI_IO_BASE
+#define DEVICE0_SIZE RPI_IO_SIZE
+
+/*
+ * Mailbox to control the secondary cores. All secondary cores are held in a
+ * wait loop in cold boot. To release them perform the following steps (plus
+ * any additional barriers that may be needed):
+ *
+ * uint64_t *entrypoint = (uint64_t *)PLAT_RPI3_TM_ENTRYPOINT;
+ * *entrypoint = ADDRESS_TO_JUMP_TO;
+ *
+ * uint64_t *mbox_entry = (uint64_t *)PLAT_RPI3_TM_HOLD_BASE;
+ * mbox_entry[cpu_id] = PLAT_RPI3_TM_HOLD_STATE_GO;
+ *
+ * sev();
+ */
+/* The secure entry point to be used on warm reset by all CPUs. */
+#define PLAT_RPI3_TM_ENTRYPOINT 0x100
+#define PLAT_RPI3_TM_ENTRYPOINT_SIZE ULL(8)
+
+/* Hold entries for each CPU. */
+#define PLAT_RPI3_TM_HOLD_BASE (PLAT_RPI3_TM_ENTRYPOINT + \
+ PLAT_RPI3_TM_ENTRYPOINT_SIZE)
+#define PLAT_RPI3_TM_HOLD_ENTRY_SIZE ULL(8)
+#define PLAT_RPI3_TM_HOLD_SIZE (PLAT_RPI3_TM_HOLD_ENTRY_SIZE * \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_RPI3_TRUSTED_MAILBOX_SIZE (PLAT_RPI3_TM_ENTRYPOINT_SIZE + \
+ PLAT_RPI3_TM_HOLD_SIZE)
+
+#define PLAT_RPI3_TM_HOLD_STATE_WAIT ULL(0)
+#define PLAT_RPI3_TM_HOLD_STATE_GO ULL(1)
+
+/*
+ * BL31 specific defines.
+ *
+ * Put BL31 at the top of the Trusted SRAM. BL31_BASE is calculated using the
+ * current BL31 debug size plus a little space for growth.
+ */
+#define PLAT_MAX_BL31_SIZE ULL(0x80000)
+
+#define BL31_BASE ULL(0x1000)
+#define BL31_LIMIT ULL(0x80000)
+#define BL31_PROGBITS_LIMIT ULL(0x80000)
+
+#define SEC_SRAM_ID 0
+#define SEC_DRAM_ID 1
+
+/*
+ * Other 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 8
+#define MAX_XLAT_TABLES 4
+
+#define MAX_IO_DEVICES U(3)
+#define MAX_IO_HANDLES U(4)
+
+#define MAX_IO_BLOCK_DEVICES U(1)
+
+/*
+ * Serial-related constants.
+ */
+#define PLAT_RPI3_UART_BASE RPI3_MINI_UART_BASE
+#define PLAT_RPI3_UART_BAUDRATE ULL(115200)
+
+/*
+ * System counter
+ */
+#define SYS_COUNTER_FREQ_IN_TICKS ULL(54000000)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/rpi/rpi4/include/rpi_hw.h b/plat/rpi/rpi4/include/rpi_hw.h
new file mode 100644
index 0000000..ed367ee
--- /dev/null
+++ b/plat/rpi/rpi4/include/rpi_hw.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RPI_HW_H
+#define RPI_HW_H
+
+#include <lib/utils_def.h>
+
+/*
+ * Peripherals
+ */
+
+#define RPI_IO_BASE ULL(0xFE000000)
+#define RPI_IO_SIZE ULL(0x02000000)
+
+/*
+ * ARM <-> VideoCore mailboxes
+ */
+#define RPI3_MBOX_OFFSET ULL(0x0000B880)
+#define RPI3_MBOX_BASE (RPI_IO_BASE + RPI3_MBOX_OFFSET)
+/* VideoCore -> ARM */
+#define RPI3_MBOX0_READ_OFFSET ULL(0x00000000)
+#define RPI3_MBOX0_PEEK_OFFSET ULL(0x00000010)
+#define RPI3_MBOX0_SENDER_OFFSET ULL(0x00000014)
+#define RPI3_MBOX0_STATUS_OFFSET ULL(0x00000018)
+#define RPI3_MBOX0_CONFIG_OFFSET ULL(0x0000001C)
+/* ARM -> VideoCore */
+#define RPI3_MBOX1_WRITE_OFFSET ULL(0x00000020)
+#define RPI3_MBOX1_PEEK_OFFSET ULL(0x00000030)
+#define RPI3_MBOX1_SENDER_OFFSET ULL(0x00000034)
+#define RPI3_MBOX1_STATUS_OFFSET ULL(0x00000038)
+#define RPI3_MBOX1_CONFIG_OFFSET ULL(0x0000003C)
+/* Mailbox status constants */
+#define RPI3_MBOX_STATUS_FULL_MASK U(0x80000000) /* Set if full */
+#define RPI3_MBOX_STATUS_EMPTY_MASK U(0x40000000) /* Set if empty */
+
+/*
+ * Power management, reset controller, watchdog.
+ */
+#define RPI3_IO_PM_OFFSET ULL(0x00100000)
+#define RPI3_PM_BASE (RPI_IO_BASE + RPI3_IO_PM_OFFSET)
+/* Registers on top of RPI3_PM_BASE. */
+#define RPI3_PM_RSTC_OFFSET ULL(0x0000001C)
+#define RPI3_PM_RSTS_OFFSET ULL(0x00000020)
+#define RPI3_PM_WDOG_OFFSET ULL(0x00000024)
+/* Watchdog constants */
+#define RPI3_PM_PASSWORD U(0x5A000000)
+#define RPI3_PM_RSTC_WRCFG_MASK U(0x00000030)
+#define RPI3_PM_RSTC_WRCFG_FULL_RESET U(0x00000020)
+/*
+ * The RSTS register is used by the VideoCore firmware when booting the
+ * Raspberry Pi to know which partition to boot from. The partition value is
+ * formed by bits 0, 2, 4, 6, 8 and 10. Partition 63 is used by said firmware
+ * to indicate halt.
+ */
+#define RPI3_PM_RSTS_WRCFG_HALT U(0x00000555)
+
+/*
+ * Clock controller
+ */
+#define RPI4_IO_CLOCK_OFFSET ULL(0x00101000)
+#define RPI4_CLOCK_BASE (RPI_IO_BASE + RPI4_IO_CLOCK_OFFSET)
+#define RPI4_VPU_CLOCK_DIVIDER ULL(0x0000000c)
+
+/*
+ * Hardware random number generator.
+ */
+#define RPI3_IO_RNG_OFFSET ULL(0x00104000)
+#define RPI3_RNG_BASE (RPI_IO_BASE + RPI3_IO_RNG_OFFSET)
+#define RPI3_RNG_CTRL_OFFSET ULL(0x00000000)
+#define RPI3_RNG_STATUS_OFFSET ULL(0x00000004)
+#define RPI3_RNG_DATA_OFFSET ULL(0x00000008)
+#define RPI3_RNG_INT_MASK_OFFSET ULL(0x00000010)
+/* Enable/disable RNG */
+#define RPI3_RNG_CTRL_ENABLE U(0x1)
+#define RPI3_RNG_CTRL_DISABLE U(0x0)
+/* Number of currently available words */
+#define RPI3_RNG_STATUS_NUM_WORDS_SHIFT U(24)
+#define RPI3_RNG_STATUS_NUM_WORDS_MASK U(0xFF)
+/* Value to mask interrupts caused by the RNG */
+#define RPI3_RNG_INT_MASK_DISABLE U(0x1)
+
+/*
+ * Serial port (called 'Mini UART' in the Broadcom documentation).
+ */
+#define RPI3_IO_MINI_UART_OFFSET ULL(0x00215040)
+#define RPI3_MINI_UART_BASE (RPI_IO_BASE + RPI3_IO_MINI_UART_OFFSET)
+#define PLAT_RPI4_VPU_CLK_RATE ULL(1000000000)
+
+/*
+ * GPIO controller
+ */
+#define RPI3_IO_GPIO_OFFSET ULL(0x00200000)
+#define RPI3_GPIO_BASE (RPI_IO_BASE + RPI3_IO_GPIO_OFFSET)
+
+/*
+ * SDHost controller
+ */
+#define RPI3_IO_SDHOST_OFFSET ULL(0x00202000)
+#define RPI3_SDHOST_BASE (RPI_IO_BASE + RPI3_IO_SDHOST_OFFSET)
+
+/*
+ * GIC interrupt controller
+ */
+#define RPI_HAVE_GIC
+#define RPI4_GIC_GICD_BASE ULL(0xff841000)
+#define RPI4_GIC_GICC_BASE ULL(0xff842000)
+
+#define RPI4_LOCAL_CONTROL_BASE_ADDRESS ULL(0xff800000)
+#define RPI4_LOCAL_CONTROL_PRESCALER ULL(0xff800008)
+
+#endif /* RPI_HW_H */
diff --git a/plat/rpi/rpi4/platform.mk b/plat/rpi/rpi4/platform.mk
new file mode 100644
index 0000000..2038021
--- /dev/null
+++ b/plat/rpi/rpi4/platform.mk
@@ -0,0 +1,103 @@
+#
+# Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include lib/libfdt/libfdt.mk
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_INCLUDES := -Iplat/rpi/common/include \
+ -Iplat/rpi/rpi4/include
+
+PLAT_BL_COMMON_SOURCES := drivers/ti/uart/aarch64/16550_console.S \
+ plat/rpi/common/rpi3_common.c \
+ ${XLAT_TABLES_LIB_SRCS}
+
+BL31_SOURCES += lib/cpus/aarch64/cortex_a72.S \
+ plat/rpi/rpi4/aarch64/plat_helpers.S \
+ plat/rpi/rpi4/aarch64/armstub8_header.S \
+ drivers/arm/gic/common/gic_common.c \
+ drivers/arm/gic/v2/gicv2_helpers.c \
+ drivers/arm/gic/v2/gicv2_main.c \
+ plat/common/plat_gicv2.c \
+ plat/rpi/rpi4/rpi4_bl31_setup.c \
+ plat/rpi/common/rpi3_pm.c \
+ plat/common/plat_psci_common.c \
+ plat/rpi/common/rpi3_topology.c \
+ common/fdt_fixup.c \
+ ${LIBFDT_SRCS}
+
+# For now we only support BL31, using the kernel loaded by the GPU firmware.
+RESET_TO_BL31 := 1
+
+# All CPUs enter armstub8.bin.
+COLD_BOOT_SINGLE_CPU := 0
+
+# Tune compiler for Cortex-A72
+ifeq ($(notdir $(CC)),armclang)
+ TF_CFLAGS_aarch64 += -mcpu=cortex-a72
+else ifneq ($(findstring clang,$(notdir $(CC))),)
+ TF_CFLAGS_aarch64 += -mcpu=cortex-a72
+else
+ TF_CFLAGS_aarch64 += -mtune=cortex-a72
+endif
+
+# Add support for platform supplied linker script for BL31 build
+$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
+
+# Enable all errata workarounds for Cortex-A72
+ERRATA_A72_859971 := 1
+
+WORKAROUND_CVE_2017_5715 := 1
+
+# Add new default target when compiling this platform
+all: bl31
+
+# Build config flags
+# ------------------
+
+# Disable stack protector by default
+ENABLE_STACK_PROTECTOR := 0
+
+# Have different sections for code and rodata
+SEPARATE_CODE_AND_RODATA := 1
+
+# Use Coherent memory
+USE_COHERENT_MEM := 1
+
+# Platform build flags
+# --------------------
+
+# There is not much else than a Linux kernel to load at the moment.
+RPI3_DIRECT_LINUX_BOOT := 1
+
+# BL33 images are in AArch64 by default
+RPI3_BL33_IN_AARCH32 := 0
+
+# UART to use at runtime. -1 means the runtime UART is disabled.
+# Any other value means the default UART will be used.
+RPI3_RUNTIME_UART := 0
+
+# Use normal memory mapping for ROM, FIP, SRAM and DRAM
+RPI3_USE_UEFI_MAP := 0
+
+# Process platform flags
+# ----------------------
+
+$(eval $(call add_define,RPI3_BL33_IN_AARCH32))
+$(eval $(call add_define,RPI3_DIRECT_LINUX_BOOT))
+ifdef RPI3_PRELOADED_DTB_BASE
+$(eval $(call add_define,RPI3_PRELOADED_DTB_BASE))
+endif
+$(eval $(call add_define,RPI3_RUNTIME_UART))
+$(eval $(call add_define,RPI3_USE_UEFI_MAP))
+
+ifeq (${ARCH},aarch32)
+ $(error Error: AArch32 not supported on rpi4)
+endif
+
+ifneq ($(ENABLE_STACK_PROTECTOR), 0)
+PLAT_BL_COMMON_SOURCES += drivers/rpi3/rng/rpi3_rng.c \
+ plat/rpi/common/rpi3_stack_protector.c
+endif
diff --git a/plat/rpi/rpi4/rpi4_bl31_setup.c b/plat/rpi/rpi4/rpi4_bl31_setup.c
new file mode 100644
index 0000000..53ab0c2
--- /dev/null
+++ b/plat/rpi/rpi4/rpi4_bl31_setup.c
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <libfdt.h>
+
+#include <platform_def.h>
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+#include <common/fdt_fixup.h>
+#include <libfdt.h>
+
+#include <drivers/arm/gicv2.h>
+
+#include <rpi_shared.h>
+
+/*
+ * Fields at the beginning of armstub8.bin.
+ * While building the BL31 image, we put the stub magic into the binary.
+ * The GPU firmware detects this at boot time, clears that field as a
+ * confirmation and puts the kernel and DT address in the following words.
+ */
+extern uint32_t stub_magic;
+extern uint32_t dtb_ptr32;
+extern uint32_t kernel_entry32;
+
+static const gicv2_driver_data_t rpi4_gic_data = {
+ .gicd_base = RPI4_GIC_GICD_BASE,
+ .gicc_base = RPI4_GIC_GICC_BASE,
+};
+
+/*
+ * To be filled by the code below. At the moment BL32 is not supported.
+ * In the future these might be passed down from BL2.
+ */
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_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(sec_state_is_valid(type) != 0);
+
+ next_image_info = (type == NON_SECURE)
+ ? &bl33_image_ep_info : &bl32_image_ep_info;
+
+ /* None of the images can have 0x0 as the entrypoint. */
+ if (next_image_info->pc) {
+ return next_image_info;
+ } else {
+ return NULL;
+ }
+}
+
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#ifdef PRELOADED_BL33_BASE
+ return PRELOADED_BL33_BASE;
+#else
+ /* Cleared by the GPU if kernel address is valid. */
+ if (stub_magic == 0)
+ return kernel_entry32;
+
+ WARN("Stub magic failure, using default kernel address 0x80000\n");
+ return 0x80000;
+#endif
+}
+
+static uintptr_t rpi4_get_dtb_address(void)
+{
+#ifdef RPI3_PRELOADED_DTB_BASE
+ return RPI3_PRELOADED_DTB_BASE;
+#else
+ /* Cleared by the GPU if DTB address is valid. */
+ if (stub_magic == 0)
+ return dtb_ptr32;
+
+ WARN("Stub magic failure, DTB address unknown\n");
+ return 0;
+#endif
+}
+
+static void ldelay(register_t delay)
+{
+ __asm__ volatile (
+ "1:\tcbz %0, 2f\n\t"
+ "sub %0, %0, #1\n\t"
+ "b 1b\n"
+ "2:"
+ : "=&r" (delay) : "0" (delay)
+ );
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & 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.
+ ******************************************************************************/
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+
+{
+ uint32_t div_reg;
+
+ /*
+ * LOCAL_CONTROL:
+ * Bit 9 clear: Increment by 1 (vs. 2).
+ * Bit 8 clear: Timer source is 19.2MHz crystal (vs. APB).
+ */
+ mmio_write_32(RPI4_LOCAL_CONTROL_BASE_ADDRESS, 0);
+
+ /* LOCAL_PRESCALER; divide-by (0x80000000 / register_val) == 1 */
+ mmio_write_32(RPI4_LOCAL_CONTROL_PRESCALER, 0x80000000);
+
+ /* Early GPU firmware revisions need a little break here. */
+ ldelay(100000);
+
+ /*
+ * Initialize the console to provide early debug support.
+ * Different GPU firmware revisions set up the VPU divider differently,
+ * so read the actual divider register to learn the UART base clock
+ * rate. The divider is encoded as a 12.12 fixed point number, but we
+ * just care about the integer part of it.
+ */
+ div_reg = mmio_read_32(RPI4_CLOCK_BASE + RPI4_VPU_CLOCK_DIVIDER);
+ div_reg = (div_reg >> 12) & 0xfff;
+ if (div_reg == 0)
+ div_reg = 1;
+ rpi3_console_init(PLAT_RPI4_VPU_CLK_RATE / div_reg);
+
+ bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+ bl33_image_ep_info.spsr = rpi3_get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+#if RPI3_DIRECT_LINUX_BOOT
+# if RPI3_BL33_IN_AARCH32
+ /*
+ * According to the file ``Documentation/arm/Booting`` of the Linux
+ * kernel tree, Linux expects:
+ * r0 = 0
+ * r1 = machine type number, optional in DT-only platforms (~0 if so)
+ * r2 = Physical address of the device tree blob
+ */
+ VERBOSE("rpi4: Preparing to boot 32-bit Linux kernel\n");
+ bl33_image_ep_info.args.arg0 = 0U;
+ bl33_image_ep_info.args.arg1 = ~0U;
+ bl33_image_ep_info.args.arg2 = rpi4_get_dtb_address();
+# else
+ /*
+ * According to the file ``Documentation/arm64/booting.txt`` of the
+ * Linux kernel tree, Linux expects the physical address of the device
+ * tree blob (DTB) in x0, while x1-x3 are reserved for future use and
+ * must be 0.
+ */
+ VERBOSE("rpi4: Preparing to boot 64-bit Linux kernel\n");
+ bl33_image_ep_info.args.arg0 = rpi4_get_dtb_address();
+ bl33_image_ep_info.args.arg1 = 0ULL;
+ bl33_image_ep_info.args.arg2 = 0ULL;
+ bl33_image_ep_info.args.arg3 = 0ULL;
+# endif /* RPI3_BL33_IN_AARCH32 */
+#endif /* RPI3_DIRECT_LINUX_BOOT */
+}
+
+void bl31_plat_arch_setup(void)
+{
+ /*
+ * Is the dtb_ptr32 pointer valid? If yes, map the DTB region.
+ * We map the 2MB region the DTB start address lives in, plus
+ * the next 2MB, to have enough room for expansion.
+ */
+ if (stub_magic == 0) {
+ unsigned long long dtb_region = dtb_ptr32;
+
+ dtb_region &= ~0x1fffff; /* Align to 2 MB. */
+ mmap_add_region(dtb_region, dtb_region, 4U << 20,
+ MT_MEMORY | MT_RW | MT_NS);
+ }
+ /*
+ * Add the first page of memory, which holds the stub magic,
+ * the kernel and the DT address.
+ * This also holds the secondary CPU's entrypoints and mailboxes.
+ */
+ mmap_add_region(0, 0, 4096, MT_NON_CACHEABLE | MT_RW | MT_SECURE);
+
+ rpi3_setup_page_tables(BL31_BASE, BL31_END - BL31_BASE,
+ BL_CODE_BASE, BL_CODE_END,
+ BL_RO_DATA_BASE, BL_RO_DATA_END
+#if USE_COHERENT_MEM
+ , BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END
+#endif
+ );
+
+ enable_mmu_el3(0);
+}
+
+static uint32_t dtb_size(const void *dtb)
+{
+ const uint32_t *dtb_header = dtb;
+
+ return fdt32_to_cpu(dtb_header[1]);
+}
+
+static void rpi4_prepare_dtb(void)
+{
+ void *dtb = (void *)rpi4_get_dtb_address();
+ uint32_t gic_int_prop[3];
+ int ret, offs;
+
+ /* Return if no device tree is detected */
+ if (fdt_check_header(dtb) != 0)
+ return;
+
+ ret = fdt_open_into(dtb, dtb, 0x100000);
+ if (ret < 0) {
+ ERROR("Invalid Device Tree at %p: error %d\n", dtb, ret);
+ return;
+ }
+
+ if (dt_add_psci_node(dtb)) {
+ ERROR("Failed to add PSCI Device Tree node\n");
+ return;
+ }
+
+ if (dt_add_psci_cpu_enable_methods(dtb)) {
+ ERROR("Failed to add PSCI cpu enable methods in Device Tree\n");
+ return;
+ }
+
+ /* Reserve memory used by Trusted Firmware. */
+ if (fdt_add_reserved_memory(dtb, "atf@0", 0, 0x80000))
+ WARN("Failed to add reserved memory nodes to DT.\n");
+
+ offs = fdt_node_offset_by_compatible(dtb, 0, "arm,gic-400");
+ gic_int_prop[0] = cpu_to_fdt32(1); // PPI
+ gic_int_prop[1] = cpu_to_fdt32(9); // PPI #9
+ gic_int_prop[2] = cpu_to_fdt32(0x0f04); // all cores, level high
+ fdt_setprop(dtb, offs, "interrupts", gic_int_prop, 12);
+
+ offs = fdt_path_offset(dtb, "/chosen");
+ fdt_setprop_string(dtb, offs, "stdout-path", "serial0");
+
+ ret = fdt_pack(dtb);
+ if (ret < 0)
+ ERROR("Failed to pack Device Tree at %p: error %d\n", dtb, ret);
+
+ clean_dcache_range((uintptr_t)dtb, dtb_size(dtb));
+ INFO("Changed device tree to advertise PSCI.\n");
+}
+
+void bl31_platform_setup(void)
+{
+ rpi4_prepare_dtb();
+
+ /* Configure the interrupt controller */
+ gicv2_driver_init(&rpi4_gic_data);
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
diff --git a/plat/st/common/include/stm32mp_auth.h b/plat/st/common/include/stm32mp_auth.h
new file mode 100644
index 0000000..3075d18
--- /dev/null
+++ b/plat/st/common/include/stm32mp_auth.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP_AUTH_H
+#define STM32MP_AUTH_H
+
+struct stm32mp_auth_ops {
+ uint32_t (*check_key)(uint8_t *pubkey_in, uint8_t *pubkey_out);
+ uint32_t (*verify_signature)(uint8_t *hash_in, uint8_t *pubkey_in,
+ uint8_t *signature, uint32_t ecc_algo);
+};
+
+void stm32mp_init_auth(struct stm32mp_auth_ops *init_ptr);
+int stm32mp_auth_image(boot_api_image_header_t *header, uintptr_t buffer);
+
+#endif /* STM32MP_AUTH_H */
diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h
index e20308e..59657fd 100644
--- a/plat/st/common/include/stm32mp_common.h
+++ b/plat/st/common/include/stm32mp_common.h
@@ -19,6 +19,7 @@
uintptr_t stm32mp_get_boot_ctx_address(void);
bool stm32mp_is_single_core(void);
+bool stm32mp_is_closed_device(void);
/* Return the base address of the DDR controller */
uintptr_t stm32mp_ddrctrl_base(void);
diff --git a/plat/st/common/stm32mp_auth.c b/plat/st/common/stm32mp_auth.c
new file mode 100644
index 0000000..0ef6d54
--- /dev/null
+++ b/plat/st/common/stm32mp_auth.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2019, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <drivers/io/io_storage.h>
+#include <drivers/st/bsec.h>
+#include <drivers/st/stm32_hash.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+static const struct stm32mp_auth_ops *auth_ops;
+
+void stm32mp_init_auth(struct stm32mp_auth_ops *init_ptr)
+{
+ if ((init_ptr == NULL) ||
+ (init_ptr->check_key == NULL) ||
+ (init_ptr->verify_signature == NULL) ||
+ (stm32_hash_register() != 0)) {
+ panic();
+ }
+
+ auth_ops = init_ptr;
+}
+
+int stm32mp_auth_image(boot_api_image_header_t *header, uintptr_t buffer)
+{
+ int ret;
+ uint8_t image_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
+ uint32_t header_skip_cksum = sizeof(header->magic) +
+ sizeof(header->image_signature) +
+ sizeof(header->payload_checksum);
+
+ /* Check Security Status */
+ if (!stm32mp_is_closed_device()) {
+ if (header->option_flags != 0U) {
+ WARN("Skip signature check (header option)\n");
+ return 0;
+ }
+ INFO("Check signature on Open device\n");
+ }
+
+ ret = mmap_add_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_BASE,
+ STM32MP_ROM_SIZE, MT_CODE | MT_SECURE);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* Check Public Key */
+ if (auth_ops->check_key(header->ecc_pubk, NULL) != BOOT_API_RETURN_OK) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* Compute end of header hash and payload hash */
+ stm32_hash_init(HASH_SHA256);
+
+ ret = stm32_hash_update((uint8_t *)&header->header_version,
+ sizeof(boot_api_image_header_t) -
+ header_skip_cksum);
+ if (ret != 0) {
+ ERROR("Hash of header failed, %i\n", ret);
+ goto err;
+ }
+
+ ret = stm32_hash_final_update((uint8_t *)buffer,
+ header->image_length, image_hash);
+ if (ret != 0) {
+ ERROR("Hash of payload failed\n");
+ goto err;
+ }
+
+ /* Verify signature */
+ if (auth_ops->verify_signature(image_hash, header->ecc_pubk,
+ header->image_signature,
+ header->ecc_algo_type) !=
+ BOOT_API_RETURN_OK) {
+ ret = -EINVAL;
+ }
+
+err:
+ mmap_remove_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_SIZE);
+ return ret;
+}
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index c6aefe3..d9e29b4 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -32,6 +32,7 @@
#include <stm32mp1_dbgmcu.h>
static struct console_stm32 console;
+static struct stm32mp_auth_ops stm32mp1_auth_ops;
static void print_reset_reason(void)
{
@@ -284,6 +285,12 @@
stm32mp_print_boardinfo();
+ if (boot_context->auth_status != BOOT_API_CTX_AUTH_NO) {
+ NOTICE("Bootrom authentication %s\n",
+ (boot_context->auth_status == BOOT_API_CTX_AUTH_FAILED) ?
+ "failed" : "succeeded");
+ }
+
skip_console_init:
if (stm32_iwdg_init() < 0) {
panic();
@@ -302,6 +309,12 @@
ERROR("Cannot save boot interface\n");
}
+ stm32mp1_auth_ops.check_key = boot_context->bootrom_ecdsa_check_key;
+ stm32mp1_auth_ops.verify_signature =
+ boot_context->bootrom_ecdsa_verify_signature;
+
+ stm32mp_init_auth(&stm32mp1_auth_ops);
+
stm32mp1_arch_security_setup();
print_reset_reason();
diff --git a/plat/st/stm32mp1/include/boot_api.h b/plat/st/stm32mp1/include/boot_api.h
index c841a74..2284970 100644
--- a/plat/st/stm32mp1/include/boot_api.h
+++ b/plat/st/stm32mp1/include/boot_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,6 +11,16 @@
#include <stdio.h>
/*
+ * Possible value of boot context field 'auth_status'
+ */
+/* No authentication done */
+#define BOOT_API_CTX_AUTH_NO 0x0U
+/* Authentication done and failed */
+#define BOOT_API_CTX_AUTH_FAILED 0x1U
+/* Authentication done and succeeded */
+#define BOOT_API_CTX_AUTH_SUCCESS 0x2U
+
+/*
* Possible value of boot context field 'boot_interface_sel'
*/
@@ -114,6 +124,8 @@
/* Closed = OTP_CFG0[6] */
#define BOOT_API_OTP_MODE_CLOSED_BIT_POS 6
+#define BOOT_API_RETURN_OK 0x66U
+
/*
* Boot Context related definitions
*/
@@ -132,7 +144,27 @@
uint16_t boot_interface_instance;
uint32_t reserved1[13];
uint32_t otp_afmux_values[3];
- uint32_t reserved[9];
+ uint32_t reserved[5];
+ uint32_t auth_status;
+
+ /*
+ * Pointers to bootROM External Secure Services
+ * - ECDSA check key
+ * - ECDSA verify signature
+ * - ECDSA verify signature and go
+ */
+ uint32_t (*bootrom_ecdsa_check_key)(uint8_t *pubkey_in,
+ uint8_t *pubkey_out);
+ uint32_t (*bootrom_ecdsa_verify_signature)(uint8_t *hash_in,
+ uint8_t *pubkey_in,
+ uint8_t *signature,
+ uint32_t ecc_algo);
+ uint32_t (*bootrom_ecdsa_verify_and_go)(uint8_t *hash_in,
+ uint8_t *pub_key_in,
+ uint8_t *signature,
+ uint32_t ecc_algo,
+ uint32_t *entry_in);
+
/*
* Information specific to an SD boot
* Updated each time an SD boot is at least attempted,
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index 83d9770..90b3e3c 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -71,7 +71,9 @@
BL2_SOURCES += drivers/io/io_block.c \
drivers/io/io_dummy.c \
drivers/io/io_storage.c \
+ drivers/st/crypto/stm32_hash.c \
drivers/st/io/io_stm32image.c \
+ plat/st/common/stm32mp_auth.c \
plat/st/common/bl2_io_storage.c \
plat/st/stm32mp1/bl2_plat_setup.c
@@ -103,6 +105,8 @@
STM32_TF_DTBFILE := ${BUILD_PLAT}/fdts/${DTB_FILE_NAME}
STM32_TF_OBJS := ${BUILD_PLAT}/stm32mp1.o
+BL2_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC=1
+
# Variables for use with stm32image
STM32IMAGEPATH ?= tools/stm32image
STM32IMAGE ?= ${STM32IMAGEPATH}/stm32image${BIN_EXT}
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index 0eba8a6..a40852b 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -19,6 +19,7 @@
#include <drivers/st/stm32mp1_clk.h>
#include <boot_api.h>
+#include <stm32mp_auth.h>
#include <stm32mp_common.h>
#include <stm32mp_dt.h>
#include <stm32mp_shres_helpers.h>
@@ -49,6 +50,8 @@
/*******************************************************************************
* STM32MP1 memory map related constants
******************************************************************************/
+#define STM32MP_ROM_BASE U(0x00000000)
+#define STM32MP_ROM_SIZE U(0x00020000)
#define STM32MP_SYSRAM_BASE U(0x2FFC0000)
#define STM32MP_SYSRAM_SIZE U(0x00040000)
diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c
index 38ebcef..e2dcd2a 100644
--- a/plat/st/stm32mp1/stm32mp1_private.c
+++ b/plat/st/stm32mp1/stm32mp1_private.c
@@ -278,6 +278,19 @@
return ret;
}
+/* Return true when device is in closed state */
+bool stm32mp_is_closed_device(void)
+{
+ uint32_t value;
+
+ if ((bsec_shadow_register(DATA0_OTP) != BSEC_OK) ||
+ (bsec_read_otp(&value, DATA0_OTP) != BSEC_OK)) {
+ return true;
+ }
+
+ return (value & DATA0_OTP_SECURED) == DATA0_OTP_SECURED;
+}
+
uint32_t stm32_iwdg_get_instance(uintptr_t base)
{
switch (base) {