Merge pull request #1465 from Andre-ARM/allwinner/h6-support

allwinner: Add H6 SoC support
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/xlat-tables-lib-v2-design.rst b/docs/xlat-tables-lib-v2-design.rst
index d207f30..f07dfab 100644
--- a/docs/xlat-tables-lib-v2-design.rst
+++ b/docs/xlat-tables-lib-v2-design.rst
@@ -282,31 +282,49 @@
 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 @@
 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 @@
                       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 @@
 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 @@
 .. _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 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__ */