aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--docs/plat/allwinner.rst8
-rw-r--r--docs/xlat-tables-lib-v2-design.rst73
-rw-r--r--drivers/io/io_fip.c124
-rw-r--r--include/lib/aarch32/smccc_helpers.h7
-rw-r--r--include/lib/aarch64/smccc_helpers.h7
-rw-r--r--include/lib/smccc.h27
-rw-r--r--maintainers.rst1
-rw-r--r--plat/allwinner/common/sunxi_bl31_setup.c3
-rw-r--r--plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h27
-rw-r--r--plat/allwinner/sun50i_h6/include/sunxi_mmap.h61
-rw-r--r--plat/allwinner/sun50i_h6/platform.mk59
12 files changed, 342 insertions, 56 deletions
diff --git a/Makefile b/Makefile
index f230f4af3..180c55842 100644
--- a/Makefile
+++ b/Makefile
@@ -151,6 +151,7 @@ TF_CFLAGS_aarch32 = $(march32-directive)
TF_CFLAGS_aarch64 = -march=armv8-a
endif
+TF_CFLAGS_aarch32 += -mno-unaligned-access
TF_CFLAGS_aarch64 += -mgeneral-regs-only -mstrict-align
ASFLAGS_aarch32 = $(march32-directive)
diff --git a/docs/plat/allwinner.rst b/docs/plat/allwinner.rst
index 825fded48..140edf511 100644
--- a/docs/plat/allwinner.rst
+++ b/docs/plat/allwinner.rst
@@ -22,12 +22,18 @@ bl31.bin can be either copied (or sym-linked) into U-Boot's root directory,
or the environment variable BL31 must contain the binary's path.
See the respective `U-Boot documentation`_ for more details.
-To build:
+To build for machines with an A64 or H5 SoC:
::
make CROSS_COMPILE=aarch64-linux-gnu- PLAT=sun50i_a64 DEBUG=1 bl31
+To build for machines with an H6 SoC:
+
+::
+
+ make CROSS_COMPILE=aarch64-linux-gnu- PLAT=sun50i_h6 DEBUG=1 bl31
+
.. _U-Boot documentation: http://git.denx.de/?p=u-boot.git;f=board/sunxi/README.sunxi64;hb=HEAD
Trusted OS dispatcher
diff --git a/docs/xlat-tables-lib-v2-design.rst b/docs/xlat-tables-lib-v2-design.rst
index d207f301e..f07dfab68 100644
--- a/docs/xlat-tables-lib-v2-design.rst
+++ b/docs/xlat-tables-lib-v2-design.rst
@@ -282,31 +282,49 @@ Implementation details
Code structure
~~~~~~~~~~~~~~
-The library is divided into 2 modules:
+The library is divided into 4 modules:
-The core module
- Provides the main functionality of the library.
+- **Core module**
- See `xlat\_tables\_internal.c`_.
+ Provides the main functionality of the library, such as the initialization of
+ translation tables contexts and mapping/unmapping memory regions. This module
+ provides functions such as ``mmap_add_region_ctx`` that let the caller specify
+ the translation tables context affected by them.
-The architectural module
- Provides functions that are dependent on the current execution state
- (AArch32/AArch64), such as the functions used for TLB invalidation or MMU
- setup.
+ See `xlat\_tables\_core.c`_.
- See `aarch32/xlat\_tables\_arch.c`_ and `aarch64/xlat\_tables\_arch.c`_.
+- **Active context module**
-Core module
-~~~~~~~~~~~
+ Instantiates the context that is used by the current BL image and provides
+ helpers to manipulate it, abstracting it from the rest of the code.
+ This module provides functions such as ``mmap_add_region``, that directly
+ affect the BL image using them.
+
+ See `xlat\_tables\_context.c`_.
+
+- **Utilities module**
+
+ Provides additional functionality like debug print of the current state of the
+ translation tables and helpers to query memory attributes and to modify them.
+
+ See `xlat\_tables\_utils.c`_.
+
+- **Architectural module**
+
+ Provides functions that are dependent on the current execution state
+ (AArch32/AArch64), such as the functions used for TLB invalidation, setup the
+ MMU, or calculate the Physical Address Space size. They do not need a
+ translation context to work on.
+
+ See `aarch32/xlat\_tables\_arch.c`_ and `aarch64/xlat\_tables\_arch.c`_.
From mmap regions to translation tables
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-All the APIs in this module work on a translation context. The translation
-context contains the list of ``mmap_region``, which holds the information of all
-the regions that are mapped at any given time. Whenever there is a request to
-map (resp. unmap) a memory region, it is added to (resp. removed from) the
-``mmap_region`` list.
+A translation context contains a list of ``mmap_region_t``, which holds the
+information of all the regions that are mapped at any given time. Whenever there
+is a request to map (resp. unmap) a memory region, it is added to (resp. removed
+from) the ``mmap_region_t`` list.
The mmap regions list is a conceptual way to represent the memory layout. At
some point, the library has to convert this information into actual translation
@@ -326,7 +344,7 @@ be added. Changes to the translation tables (as well as the mmap regions list)
will take effect immediately.
The memory mapping algorithm
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The mapping function is implemented as a recursive algorithm. It is however
bound by the level of depth of the translation tables (the Armv8-A architecture
@@ -367,7 +385,7 @@ about the sorting algorithm in use.
granularity.
TLB maintenance operations
-^^^^^^^^^^^^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~~~~~~~~~~~~
The library takes care of performing TLB maintenance operations when required.
For example, when the user requests removing a dynamic region, the library
@@ -391,17 +409,8 @@ descriptor. Given that the TLBs are not architecturally permitted to hold any
invalid translation table entry [#tlb-no-invalid-entry]_, this means that this
mapping cannot be cached in the TLBs.
-.. [#tlb-reset-ref] See section D4.8 `Translation Lookaside Buffers (TLBs)`, subsection `TLB behavior at reset` in Armv8-A, rev B.a.
-
-.. [#tlb-no-invalid-entry] See section D4.9.1 `General TLB maintenance requirements` in Armv8-A, rev B.a.
-
-Architectural module
-~~~~~~~~~~~~~~~~~~~~
-
-This module contains functions that have different implementations for AArch32
-and AArch64. For example, it provides APIs to perform TLB maintenance operations,
-enable the MMU or calculate the Physical Address Space size. They do not need a
-translation context to work on.
+.. [#tlb-reset-ref] See section D4.9 `Translation Lookaside Buffers (TLBs)`, subsection `TLB behavior at reset` in Armv8-A, rev C.a.
+.. [#tlb-no-invalid-entry] See section D4.10.1 `General TLB maintenance requirements` in Armv8-A, rev C.a.
--------------
@@ -410,7 +419,9 @@ translation context to work on.
.. _lib/xlat\_tables\_v2: ../lib/xlat_tables_v2
.. _lib/xlat\_tables: ../lib/xlat_tables
.. _xlat\_tables\_v2.h: ../include/lib/xlat_tables/xlat_tables_v2.h
-.. _xlat\_tables\_internal.c: ../lib/xlat_tables_v2/xlat_tables_internal.c
+.. _xlat\_tables\_context.c: ../lib/xlat_tables_v2/xlat_tables_context.c
+.. _xlat\_tables\_core.c: ../lib/xlat_tables_v2/xlat_tables_core.c
+.. _xlat\_tables\_utils.c: ../lib/xlat_tables_v2/xlat_tables_utils.c
.. _aarch32/xlat\_tables\_arch.c: ../lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
.. _aarch64/xlat\_tables\_arch.c: ../lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
.. _Porting Guide: porting-guide.rst
diff --git a/drivers/io/io_fip.c b/drivers/io/io_fip.c
index 175433906..6e7103dbe 100644
--- a/drivers/io/io_fip.c
+++ b/drivers/io/io_fip.c
@@ -19,6 +19,10 @@
#include <utils.h>
#include <uuid.h>
+#ifndef MAX_FIP_DEVICES
+#define MAX_FIP_DEVICES 1
+#endif
+
/* Useful for printing UUIDs when debugging.*/
#define PRINT_UUID2(x) \
"%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx", \
@@ -32,11 +36,33 @@ typedef struct {
fip_toc_entry_t entry;
} file_state_t;
+/*
+ * Maintain dev_spec per FIP Device
+ * TODO - Add backend handles and file state
+ * per FIP device here once backends like io_memmap
+ * can support multiple open files
+ */
+typedef struct {
+ uintptr_t dev_spec;
+} fip_dev_state_t;
+
static const uuid_t uuid_null = { {0} };
+/*
+ * Only one file can be open across all FIP device
+ * as backends like io_memmap don't support
+ * multiple open files. The file state and
+ * backend handle should be maintained per FIP device
+ * if the same support is available in the backend
+ */
static file_state_t current_file = {0};
static uintptr_t backend_dev_handle;
static uintptr_t backend_image_spec;
+static fip_dev_state_t state_pool[MAX_FIP_DEVICES];
+static io_dev_info_t dev_info_pool[MAX_FIP_DEVICES];
+
+/* Track number of allocated fip devices */
+static unsigned int fip_dev_count;
/* Firmware Image Package driver functions */
static int fip_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
@@ -92,20 +118,94 @@ static const io_dev_funcs_t fip_dev_funcs = {
.dev_close = fip_dev_close,
};
+/* Locate a file state in the pool, specified by address */
+static int find_first_fip_state(const uintptr_t dev_spec,
+ unsigned int *index_out)
+{
+ int result = -ENOENT;
+ unsigned int index;
+
+ for (index = 0; index < (unsigned int)MAX_FIP_DEVICES; ++index) {
+ /* dev_spec is used as identifier since it's unique */
+ if (state_pool[index].dev_spec == dev_spec) {
+ result = 0;
+ *index_out = index;
+ break;
+ }
+ }
+ return result;
+}
+
-/* No state associated with this device so structure can be const */
-static const io_dev_info_t fip_dev_info = {
- .funcs = &fip_dev_funcs,
- .info = (uintptr_t)NULL
-};
+/* Allocate a device info from the pool and return a pointer to it */
+static int allocate_dev_info(io_dev_info_t **dev_info)
+{
+ int result = -ENOMEM;
+ assert(dev_info != NULL);
+
+ if (fip_dev_count < (unsigned int)MAX_FIP_DEVICES) {
+ unsigned int index = 0;
+
+ result = find_first_fip_state(0, &index);
+ assert(result == 0);
+ /* initialize dev_info */
+ dev_info_pool[index].funcs = &fip_dev_funcs;
+ dev_info_pool[index].info =
+ (uintptr_t)&state_pool[index];
+ *dev_info = &dev_info_pool[index];
+ ++fip_dev_count;
+ }
+
+ return result;
+}
-/* Open a connection to the FIP device */
-static int fip_dev_open(const uintptr_t dev_spec __unused,
+/* Release a device info to the pool */
+static int free_dev_info(io_dev_info_t *dev_info)
+{
+ int result;
+ unsigned int index = 0;
+ fip_dev_state_t *state;
+
+ assert(dev_info != NULL);
+
+ state = (fip_dev_state_t *)dev_info->info;
+ result = find_first_fip_state(state->dev_spec, &index);
+ if (result == 0) {
+ /* free if device info is valid */
+ zeromem(state, sizeof(fip_dev_state_t));
+ --fip_dev_count;
+ }
+
+ return result;
+}
+
+/*
+ * Multiple FIP devices can be opened depending on the value of
+ * MAX_FIP_DEVICES. Given that there is only one backend, only a
+ * single file can be open at a time by any FIP device.
+ */
+static int fip_dev_open(const uintptr_t dev_spec,
io_dev_info_t **dev_info)
{
+ int result;
+ io_dev_info_t *info;
+ fip_dev_state_t *state;
+
assert(dev_info != NULL);
- *dev_info = (io_dev_info_t *)&fip_dev_info; /* cast away const */
+#if MAX_FIP_DEVICES > 1
+ assert(dev_spec != (uintptr_t)NULL);
+#endif
+
+ result = allocate_dev_info(&info);
+ if (result != 0)
+ return -ENOMEM;
+
+ state = (fip_dev_state_t *)info->info;
+
+ state->dev_spec = dev_spec;
+
+ *dev_info = info;
return 0;
}
@@ -165,7 +265,7 @@ static int fip_dev_close(io_dev_info_t *dev_info)
backend_dev_handle = (uintptr_t)NULL;
backend_image_spec = (uintptr_t)NULL;
- return 0;
+ return free_dev_info(dev_info);
}
@@ -341,7 +441,11 @@ int register_io_dev_fip(const io_dev_connector_t **dev_con)
int result;
assert(dev_con != NULL);
- result = io_register_device(&fip_dev_info);
+ /*
+ * Since dev_info isn't really used in io_register_device, always
+ * use the same device info at here instead.
+ */
+ result = io_register_device(&dev_info_pool[0]);
if (result == 0)
*dev_con = &fip_dev_connector;
diff --git a/include/lib/aarch32/smccc_helpers.h b/include/lib/aarch32/smccc_helpers.h
index 240dd13fb..731c26fbf 100644
--- a/include/lib/aarch32/smccc_helpers.h
+++ b/include/lib/aarch32/smccc_helpers.h
@@ -129,13 +129,6 @@ CASSERT(SMC_CTX_SIZE == sizeof(smc_ctx_t), assert_smc_ctx_size_mismatch);
SMC_RET3(_h, (_r0), (_r1), (_r2)); \
}
-/* Return a UUID in the SMC return registers */
-#define SMC_UUID_RET(_h, _uuid) \
- SMC_RET4(handle, ((const uint32_t *) &(_uuid))[0], \
- ((const uint32_t *) &(_uuid))[1], \
- ((const uint32_t *) &(_uuid))[2], \
- ((const uint32_t *) &(_uuid))[3])
-
/*
* Helper macro to retrieve the SMC parameters from smc_ctx_t.
*/
diff --git a/include/lib/aarch64/smccc_helpers.h b/include/lib/aarch64/smccc_helpers.h
index 1b33a0d15..4d9217bcc 100644
--- a/include/lib/aarch64/smccc_helpers.h
+++ b/include/lib/aarch64/smccc_helpers.h
@@ -67,13 +67,6 @@
#define SMC_SET_EL3(_h, _e, _v) \
write_ctx_reg((get_el3state_ctx(_h)), (_e), (_v))
-/* Return a UUID in the SMC return registers */
-#define SMC_UUID_RET(_h, _uuid) \
- SMC_RET4(handle, ((const uint32_t *) &(_uuid))[0], \
- ((const uint32_t *) &(_uuid))[1], \
- ((const uint32_t *) &(_uuid))[2], \
- ((const uint32_t *) &(_uuid))[3])
-
/*
* Helper macro to retrieve the SMC parameters from cpu_context_t.
*/
diff --git a/include/lib/smccc.h b/include/lib/smccc.h
index cb722b0e2..a07e510b8 100644
--- a/include/lib/smccc.h
+++ b/include/lib/smccc.h
@@ -84,5 +84,32 @@
{ _n0, _n1, _n2, _n3, _n4, _n5 } \
}
+/*
+ * Return a UUID in the SMC return registers.
+ *
+ * Acccording to section 5.3 of the SMCCC, UUIDs are returned as a single
+ * 128-bit value using the SMC32 calling convention. This value is mapped to
+ * argument registers x0-x3 on AArch64 (resp. r0-r3 on AArch32). x0 for example
+ * shall hold bytes 0 to 3, with byte 0 in the low-order bits.
+ */
+static inline uint32_t smc_uuid_word(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3)
+{
+ return ((uint32_t) b0) | (((uint32_t) b1) << 8) |
+ (((uint32_t) b2) << 16) | (((uint32_t) b3) << 24);
+}
+
+#define SMC_UUID_RET(_h, _uuid) \
+ SMC_RET4(handle, \
+ smc_uuid_word((_uuid).time_low[0], (_uuid).time_low[1], \
+ (_uuid).time_low[2], (_uuid).time_low[3]), \
+ smc_uuid_word((_uuid).time_mid[0], (_uuid).time_mid[1], \
+ (_uuid).time_hi_and_version[0], \
+ (_uuid).time_hi_and_version[1]), \
+ smc_uuid_word((_uuid).clock_seq_hi_and_reserved, \
+ (_uuid).clock_seq_low, (_uuid).node[0], \
+ (_uuid).node[1]), \
+ smc_uuid_word((_uuid).node[2], (_uuid).node[3], \
+ (_uuid).node[4], (_uuid).node[5]))
+
#endif /*__ASSEMBLY__*/
#endif /* __SMCCC_H__ */
diff --git a/maintainers.rst b/maintainers.rst
index c01d97adf..638f66a7c 100644
--- a/maintainers.rst
+++ b/maintainers.rst
@@ -171,6 +171,7 @@ Xilinx platform port
.. _rockchip-linux: https://github.com/rockchip-linux
.. _shawnguo2: https://github.com/shawnguo2
.. _sivadur: https://github.com/sivadur
+.. _smaeul: https://github.com/smaeul
.. _soby-mathew: https://github.com/soby-mathew
.. _TonyXie06: https://github.com/TonyXie06
.. _vwadekar: https://github.com/vwadekar
diff --git a/plat/allwinner/common/sunxi_bl31_setup.c b/plat/allwinner/common/sunxi_bl31_setup.c
index e910ee549..8ecf49083 100644
--- a/plat/allwinner/common/sunxi_bl31_setup.c
+++ b/plat/allwinner/common/sunxi_bl31_setup.c
@@ -74,6 +74,9 @@ void bl31_platform_setup(void)
case 0x1718:
soc_name = "H5";
break;
+ case 0x1728:
+ soc_name = "H6";
+ break;
default:
soc_name = "unknown";
break;
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h
new file mode 100644
index 000000000..e061b89ca
--- /dev/null
+++ b/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SUNXI_CPUCFG_H__
+#define __SUNXI_CPUCFG_H__
+
+#include <sunxi_mmap.h>
+
+/* c = cluster, n = core */
+#define SUNXI_CPUCFG_CLS_CTRL_REG0(c) (SUNXI_CPUCFG_BASE + 0x0010 + (c) * 0x10)
+#define SUNXI_CPUCFG_CLS_CTRL_REG1(c) (SUNXI_CPUCFG_BASE + 0x0014 + (c) * 0x10)
+#define SUNXI_CPUCFG_CACHE_CFG_REG (SUNXI_CPUCFG_BASE + 0x0024)
+#define SUNXI_CPUCFG_DBG_REG0 (SUNXI_CPUCFG_BASE + 0x00c0)
+
+#define SUNXI_CPUCFG_RST_CTRL_REG(c) (SUNXI_CPUCFG_BASE + 0x0000 + (c) * 4)
+#define SUNXI_CPUCFG_RVBAR_LO_REG(n) (SUNXI_CPUCFG_BASE + 0x0040 + (n) * 8)
+#define SUNXI_CPUCFG_RVBAR_HI_REG(n) (SUNXI_CPUCFG_BASE + 0x0044 + (n) * 8)
+
+#define SUNXI_POWERON_RST_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0040 + (c) * 4)
+#define SUNXI_POWEROFF_GATING_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0044 + (c) * 4)
+#define SUNXI_CPU_POWER_CLAMP_REG(c, n) (SUNXI_R_CPUCFG_BASE + 0x0050 + \
+ (c) * 0x10 + (n) * 4)
+
+#endif /* __SUNXI_CPUCFG_H__ */
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
new file mode 100644
index 000000000..f2d5aed6b
--- /dev/null
+++ b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SUNXI_MMAP_H__
+#define __SUNXI_MMAP_H__
+
+/* Memory regions */
+#define SUNXI_ROM_BASE 0x00000000
+#define SUNXI_ROM_SIZE 0x00010000
+#define SUNXI_SRAM_BASE 0x00020000
+#define SUNXI_SRAM_SIZE 0x00098000
+#define SUNXI_SRAM_A1_BASE 0x00020000
+#define SUNXI_SRAM_A1_SIZE 0x00008000
+#define SUNXI_SRAM_A2_BASE 0x00104000
+#define SUNXI_SRAM_A2_SIZE 0x00014000
+#define SUNXI_SRAM_C_BASE 0x00028000
+#define SUNXI_SRAM_C_SIZE 0x0001e000
+#define SUNXI_DEV_BASE 0x01000000
+#define SUNXI_DEV_SIZE 0x09000000
+#define SUNXI_DRAM_BASE 0x40000000
+#define SUNXI_DRAM_SIZE 0xc0000000
+
+/* Memory-mapped devices */
+#define SUNXI_SYSCON_BASE 0x03000000
+#define SUNXI_CPUCFG_BASE 0x09010000
+#define SUNXI_SID_BASE 0x03006000
+#define SUNXI_DMA_BASE 0x03002000
+#define SUNXI_MSGBOX_BASE 0x03003000
+#define SUNXI_CCU_BASE 0x03010000
+#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0xf00)
+#define SUNXI_PIO_BASE 0x030b0000
+#define SUNXI_TIMER_BASE 0x03009000
+#define SUNXI_WDOG_BASE 0x030090a0
+#define SUNXI_THS_BASE 0x05070400
+#define SUNXI_UART0_BASE 0x05000000
+#define SUNXI_UART1_BASE 0x05000400
+#define SUNXI_UART2_BASE 0x05000800
+#define SUNXI_UART3_BASE 0x05000c00
+#define SUNXI_I2C0_BASE 0x05002000
+#define SUNXI_I2C1_BASE 0x05002400
+#define SUNXI_I2C2_BASE 0x05002800
+#define SUNXI_I2C3_BASE 0x05002c00
+#define SUNXI_SPI0_BASE 0x05010000
+#define SUNXI_SPI1_BASE 0x05011000
+#define SUNXI_SCU_BASE 0x03020000
+#define SUNXI_GICD_BASE 0x03021000
+#define SUNXI_GICC_BASE 0x03022000
+#define SUNXI_R_TIMER_BASE 0x07020000
+#define SUNXI_R_INTC_BASE 0x07021000
+#define SUNXI_R_WDOG_BASE 0x07020400
+#define SUNXI_R_PRCM_BASE 0x07010000
+#define SUNXI_R_TWD_BASE 0x07020800
+#define SUNXI_R_CPUCFG_BASE 0x07000400
+#define SUNXI_R_I2C_BASE 0x07081400
+#define SUNXI_R_UART_BASE 0x07080000
+#define SUNXI_R_PIO_BASE 0x07022000
+
+#endif /* __SUNXI_MMAP_H__ */
diff --git a/plat/allwinner/sun50i_h6/platform.mk b/plat/allwinner/sun50i_h6/platform.mk
new file mode 100644
index 000000000..c1b26fae6
--- /dev/null
+++ b/plat/allwinner/sun50i_h6/platform.mk
@@ -0,0 +1,59 @@
+#
+# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include lib/xlat_tables_v2/xlat_tables.mk
+
+AW_PLAT := plat/allwinner
+
+PLAT_INCLUDES := -Iinclude/plat/arm/common \
+ -Iinclude/plat/arm/common/aarch64 \
+ -I${AW_PLAT}/common/include \
+ -I${AW_PLAT}/${PLAT}/include
+
+PLAT_BL_COMMON_SOURCES := drivers/console/${ARCH}/console.S \
+ drivers/ti/uart/${ARCH}/16550_console.S \
+ ${XLAT_TABLES_LIB_SRCS} \
+ ${AW_PLAT}/common/plat_helpers.S \
+ ${AW_PLAT}/common/sunxi_common.c
+
+BL31_SOURCES += drivers/arm/gic/common/gic_common.c \
+ drivers/arm/gic/v2/gicv2_helpers.c \
+ drivers/arm/gic/v2/gicv2_main.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ lib/cpus/${ARCH}/cortex_a53.S \
+ plat/common/plat_gicv2.c \
+ plat/common/plat_psci_common.c \
+ ${AW_PLAT}/common/sunxi_bl31_setup.c \
+ ${AW_PLAT}/common/sunxi_cpu_ops.c \
+ ${AW_PLAT}/common/sunxi_pm.c \
+ ${AW_PLAT}/common/sunxi_security.c \
+ ${AW_PLAT}/common/sunxi_topology.c
+
+# The bootloader is guaranteed to only run on CPU 0 by the boot ROM.
+COLD_BOOT_SINGLE_CPU := 1
+
+# Enable workarounds for Cortex-A53 errata. Allwinner uses at least r0p4.
+ERRATA_A53_835769 := 1
+ERRATA_A53_843419 := 1
+ERRATA_A53_855873 := 1
+
+# Disable the PSCI platform compatibility layer.
+ENABLE_PLAT_COMPAT := 0
+
+MULTI_CONSOLE_API := 1
+
+# Prohibit using deprecated interfaces. We rely on this for this platform.
+ERROR_DEPRECATED := 1
+
+# The reset vector can be changed for each CPU.
+PROGRAMMABLE_RESET_ADDRESS := 1
+
+# Allow mapping read-only data as execute-never.
+SEPARATE_CODE_AND_RODATA := 1
+
+# BL31 gets loaded alongside BL33 (U-Boot) by U-Boot's SPL
+RESET_TO_BL31 := 1