Merge pull request #1461 from antonio-nino-diaz-arm/an/xlat-docs
xlat v2: Update documentation
diff --git a/Makefile b/Makefile
index f230f4a..180c558 100644
--- a/Makefile
+++ b/Makefile
@@ -151,6 +151,7 @@
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 a7e84a3..825fded 100644
--- a/docs/plat/allwinner.rst
+++ b/docs/plat/allwinner.rst
@@ -4,9 +4,11 @@
Trusted Firmware-A (TF-A) implements the EL3 firmware layer for Allwinner
SoCs with ARMv8 cores. Only BL31 is used to provide proper EL3 setup and
PSCI runtime services.
+
U-Boot's SPL acts as a loader, loading both BL31 and BL33 (typically U-Boot).
Loading is done from SD card, eMMC or SPI flash, also via an USB debug
interface (FEL).
+
BL31 lives in SRAM A2, which is documented to be accessible from secure
world only.
@@ -27,3 +29,13 @@
make CROSS_COMPILE=aarch64-linux-gnu- PLAT=sun50i_a64 DEBUG=1 bl31
.. _U-Boot documentation: http://git.denx.de/?p=u-boot.git;f=board/sunxi/README.sunxi64;hb=HEAD
+
+Trusted OS dispatcher
+=====================
+
+One can boot Trusted OS(OP-TEE OS, bl32 image) along side bl31 image on Allwinner A64.
+
+In order to include the 'opteed' dispatcher in the image, pass 'SPD=opteed' on the command line
+while compiling the bl31 image and make sure the loader (SPL) loads the Trusted OS binary to
+the beginning of DRAM (0x40000000).
+
diff --git a/drivers/io/io_fip.c b/drivers/io/io_fip.c
index 1754339..6e7103d 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 @@
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 @@
.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;
-/* 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
-};
+ 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;
+}
-/* Open a connection to the FIP device */
-static int fip_dev_open(const uintptr_t dev_spec __unused,
+/* 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;
+}
+
+/* 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 @@
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 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 240dd13..731c26f 100644
--- a/include/lib/aarch32/smccc_helpers.h
+++ b/include/lib/aarch32/smccc_helpers.h
@@ -129,13 +129,6 @@
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 1b33a0d..4d9217b 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 cb722b0..a07e510 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 94bb5d3..c01d97a 100644
--- a/maintainers.rst
+++ b/maintainers.rst
@@ -20,6 +20,8 @@
-----------------------------
:M: Andre Przywara <andre.przywara@arm.com>
:G: `Andre-ARM`_
+:M: Samuel Holland <samuel@sholland.org>
+:G: `smaeul`_
:F: docs/plat/allwinner.rst
:F: plat/allwinner/
diff --git a/plat/allwinner/common/include/platform_def.h b/plat/allwinner/common/include/platform_def.h
index ca7db2f..d039188 100644
--- a/plat/allwinner/common/include/platform_def.h
+++ b/plat/allwinner/common/include/platform_def.h
@@ -39,7 +39,13 @@
#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \
PLATFORM_MAX_CPUS_PER_CLUSTER)
#define PLATFORM_MAX_CPUS_PER_CLUSTER 4
-#define PLATFORM_MMAP_REGIONS 4
+#define PLATFORM_MMAP_REGIONS 3
#define PLATFORM_STACK_SIZE (0x1000 / PLATFORM_CORE_COUNT)
+#ifndef SPD_none
+#ifndef BL32_BASE
+#define BL32_BASE SUNXI_DRAM_BASE
+#endif
+#endif
+
#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/allwinner/common/sunxi_bl31_setup.c b/plat/allwinner/common/sunxi_bl31_setup.c
index d1f1aa1..e910ee5 100644
--- a/plat/allwinner/common/sunxi_bl31_setup.c
+++ b/plat/allwinner/common/sunxi_bl31_setup.c
@@ -18,6 +18,7 @@
#include "sunxi_private.h"
+static entry_point_info_t bl32_image_ep_info;
static entry_point_info_t bl33_image_ep_info;
static console_16550_t console;
@@ -34,6 +35,13 @@
console_16550_register(SUNXI_UART0_BASE, SUNXI_UART0_CLK_IN_HZ,
SUNXI_UART0_BAUDRATE, &console);
+#ifdef BL32_BASE
+ /* Populate entry point information for BL32 */
+ SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
+ SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+ bl32_image_ep_info.pc = BL32_BASE;
+#endif
+
/* Populate entry point information for BL33 */
SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
/*
@@ -56,6 +64,22 @@
void bl31_platform_setup(void)
{
+ const char *soc_name;
+ uint16_t soc_id = sunxi_read_soc_id();
+
+ switch (soc_id) {
+ case 0x1689:
+ soc_name = "A64/H64/R18";
+ break;
+ case 0x1718:
+ soc_name = "H5";
+ break;
+ default:
+ soc_name = "unknown";
+ break;
+ }
+ NOTICE("BL31: Detected Allwinner %s SoC (%04x)\n", soc_name, soc_id);
+
generic_delay_timer_init();
/* Configure the interrupt controller */
@@ -72,7 +96,12 @@
entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
{
assert(sec_state_is_valid(type) != 0);
- assert(type == NON_SECURE);
- return &bl33_image_ep_info;
+ if (type == NON_SECURE)
+ return &bl33_image_ep_info;
+
+ if ((type == SECURE) && bl32_image_ep_info.pc)
+ return &bl32_image_ep_info;
+
+ return NULL;
}
diff --git a/plat/allwinner/common/sunxi_common.c b/plat/allwinner/common/sunxi_common.c
index e36c8b0..fc9bf20 100644
--- a/plat/allwinner/common/sunxi_common.c
+++ b/plat/allwinner/common/sunxi_common.c
@@ -4,14 +4,15 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <mmio.h>
#include <platform.h>
#include <platform_def.h>
#include <sunxi_def.h>
#include <xlat_tables_v2.h>
+#include "sunxi_private.h"
+
static mmap_region_t sunxi_mmap[PLATFORM_MMAP_REGIONS + 1] = {
- MAP_REGION_FLAT(SUNXI_ROM_BASE, SUNXI_ROM_SIZE,
- MT_MEMORY | MT_RO | MT_SECURE),
MAP_REGION_FLAT(SUNXI_SRAM_BASE, SUNXI_SRAM_SIZE,
MT_MEMORY | MT_RW | MT_SECURE),
MAP_REGION_FLAT(SUNXI_DEV_BASE, SUNXI_DEV_SIZE,
@@ -54,3 +55,19 @@
enable_mmu_el3(0);
}
+
+#define SRAM_VER_REG (SUNXI_SYSCON_BASE + 0x24)
+uint16_t sunxi_read_soc_id(void)
+{
+ uint32_t reg = mmio_read_32(SRAM_VER_REG);
+
+ /* Set bit 15 to prepare for the SOCID read. */
+ mmio_write_32(SRAM_VER_REG, reg | BIT(15));
+
+ reg = mmio_read_32(SRAM_VER_REG);
+
+ /* deactivate the SOCID access again */
+ mmio_write_32(SRAM_VER_REG, reg & ~BIT(15));
+
+ return reg >> 16;
+}
diff --git a/plat/allwinner/common/sunxi_cpu_ops.c b/plat/allwinner/common/sunxi_cpu_ops.c
index be72dee..aaee65c 100644
--- a/plat/allwinner/common/sunxi_cpu_ops.c
+++ b/plat/allwinner/common/sunxi_cpu_ops.c
@@ -18,7 +18,7 @@
if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0xff)
return;
- INFO("PSCI: Disabling power to cluster %d core %d\n", cluster, core);
+ VERBOSE("PSCI: Disabling power to cluster %d core %d\n", cluster, core);
mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xff);
}
@@ -28,7 +28,7 @@
if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0)
return;
- INFO("PSCI: Enabling power to cluster %d core %d\n", cluster, core);
+ VERBOSE("PSCI: Enabling power to cluster %d core %d\n", cluster, core);
/* Power enable sequence from original Allwinner sources */
mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xfe);
@@ -40,7 +40,7 @@
void sunxi_cpu_off(unsigned int cluster, unsigned int core)
{
- INFO("PSCI: Powering off cluster %d core %d\n", cluster, core);
+ VERBOSE("PSCI: Powering off cluster %d core %d\n", cluster, core);
/* Deassert DBGPWRDUP */
mmio_clrbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core));
@@ -54,7 +54,7 @@
void sunxi_cpu_on(unsigned int cluster, unsigned int core)
{
- INFO("PSCI: Powering on cluster %d core %d\n", cluster, core);
+ VERBOSE("PSCI: Powering on cluster %d core %d\n", cluster, core);
/* Assert CPU core reset */
mmio_clrbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core));
diff --git a/plat/allwinner/common/sunxi_pm.c b/plat/allwinner/common/sunxi_pm.c
index fcab130..2a1f223 100644
--- a/plat/allwinner/common/sunxi_pm.c
+++ b/plat/allwinner/common/sunxi_pm.c
@@ -76,8 +76,7 @@
static int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint)
{
/* The non-secure entry point must be in DRAM */
- if (ns_entrypoint >= SUNXI_DRAM_BASE &&
- ns_entrypoint < SUNXI_DRAM_BASE + SUNXI_DRAM_SIZE)
+ if (ns_entrypoint >= SUNXI_DRAM_BASE)
return PSCI_E_SUCCESS;
return PSCI_E_INVALID_ADDRESS;
diff --git a/plat/allwinner/common/sunxi_private.h b/plat/allwinner/common/sunxi_private.h
index b9f0fb4..e45f494 100644
--- a/plat/allwinner/common/sunxi_private.h
+++ b/plat/allwinner/common/sunxi_private.h
@@ -12,6 +12,7 @@
void sunxi_cpu_on(unsigned int cluster, unsigned int core);
void sunxi_disable_secondary_cpus(unsigned int primary_cpu);
+uint16_t sunxi_read_soc_id(void);
void sunxi_security_setup(void);
#endif /* __SUNXI_PRIVATE_H__ */
diff --git a/plat/allwinner/common/sunxi_security.c b/plat/allwinner/common/sunxi_security.c
index e760072..80fed6a 100644
--- a/plat/allwinner/common/sunxi_security.c
+++ b/plat/allwinner/common/sunxi_security.c
@@ -25,9 +25,9 @@
*/
void sunxi_security_setup(void)
{
+#ifdef SUNXI_SPC_BASE
int i;
-#ifdef SUNXI_SPC_BASE
INFO("Configuring SPC Controller\n");
/* SPC setup: set all devices to non-secure */
for (i = 0; i < 6; i++)
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
index cb202a8..7d46487 100644
--- a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
+++ b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
@@ -27,7 +27,6 @@
#define SUNXI_CPU_MBIST_BASE 0x01502000
#define SUNXI_CPUCFG_BASE 0x01700000
#define SUNXI_SYSCON_BASE 0x01c00000
-#define SUNXI_SRAM_VER_REG (SUNXI_SYSCON_BASE + 0x24)
#define SUNXI_DMA_BASE 0x01c02000
#define SUNXI_KEYMEM_BASE 0x01c0b000
#define SUNXI_SMHC0_BASE 0x01c0f000