Refactor the ARM CoreLink TZC-400 driver

TrustZone protection can be programmed by both memory and TrustZone
address space controllers like DMC-500 and TZC-400. These peripherals
share a similar programmer's view.

Furthermore, it is possible to have multiple instances of each type of
peripheral in a system resulting in multiple programmer's views.
For example, on the TZC-400 each of the 4 filter units can be enabled
or disabled for each region. There is a single set of registers to
program the region attributes. On the DMC-500, each filter unit has its
own programmer's view resulting in multiple sets of registers to program
the region attributes. The layout of the registers is almost the same
across all these variations.

Hence the existing driver in `tzc400\tzc400.c` is refactored into the
new driver in `tzc\tzc400.c`. The previous driver file is still maintained
for compatibility and it is now deprecated.

Change-Id: Ieabd0528e244582875bc7e65029a00517671216d
diff --git a/drivers/arm/tzc400/tzc400.c b/drivers/arm/tzc400/tzc400.c
index 7194443..97adf81 100644
--- a/drivers/arm/tzc400/tzc400.c
+++ b/drivers/arm/tzc400/tzc400.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -28,313 +28,8 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <assert.h>
-#include <debug.h>
-#include <mmio.h>
-#include <stddef.h>
-#include <tzc400.h>
-
-/*
- * Implementation defined values used to validate inputs later.
- * Filters : max of 4 ; 0 to 3
- * Regions : max of 9 ; 0 to 8
- * Address width : Values between 32 to 64
- */
-typedef struct tzc_instance {
-	uintptr_t base;
-	uint8_t addr_width;
-	uint8_t num_filters;
-	uint8_t num_regions;
-} tzc_instance_t;
-
-tzc_instance_t tzc;
-
-
-static inline uint32_t tzc_read_build_config(uintptr_t base)
-{
-	return mmio_read_32(base + BUILD_CONFIG_OFF);
-}
-
-static inline uint32_t tzc_read_gate_keeper(uintptr_t base)
-{
-	return mmio_read_32(base + GATE_KEEPER_OFF);
-}
-
-static inline void tzc_write_gate_keeper(uintptr_t base, uint32_t val)
-{
-	mmio_write_32(base + GATE_KEEPER_OFF, val);
-}
-
-static inline void tzc_write_action(uintptr_t base, tzc_action_t action)
-{
-	mmio_write_32(base + ACTION_OFF, action);
-}
-
-static inline void tzc_write_region_base_low(uintptr_t base,
-					uint32_t region,
-					uint32_t val)
-{
-	mmio_write_32(base + REGION_BASE_LOW_OFF +
-		REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_base_high(uintptr_t base,
-					uint32_t region,
-					uint32_t val)
-{
-	mmio_write_32(base + REGION_BASE_HIGH_OFF +
-		REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_top_low(uintptr_t base,
-					uint32_t region,
-					uint32_t val)
-{
-	mmio_write_32(base + REGION_TOP_LOW_OFF +
-		REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_top_high(uintptr_t base,
-					uint32_t region,
-					uint32_t val)
-{
-	mmio_write_32(base + REGION_TOP_HIGH_OFF +
-		REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_attributes(uintptr_t base,
-					uint32_t region,
-					uint32_t val)
-{
-	mmio_write_32(base + REGION_ATTRIBUTES_OFF +
-		REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_id_access(uintptr_t base,
-					uint32_t region,
-					uint32_t val)
-{
-	mmio_write_32(base + REGION_ID_ACCESS_OFF +
-		REGION_NUM_OFF(region), val);
-}
-
-static unsigned int tzc_read_peripheral_id(uintptr_t base)
-{
-	unsigned int id;
-
-	id = mmio_read_8(base + PID0_OFF);
-	/* Masks jep106_id_3_0 part in PID1 */
-	id |= ((mmio_read_8(base + PID1_OFF) & 0xF) << 8);
-
-	return id;
-}
-
-static uint32_t tzc_get_gate_keeper(uintptr_t base, uint8_t filter)
-{
-	uint32_t tmp;
-
-	tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
-		GATE_KEEPER_OS_MASK;
-
-	return (tmp >> filter) & GATE_KEEPER_FILTER_MASK;
-}
-
-/* This function is not MP safe. */
-static void tzc_set_gate_keeper(uintptr_t base, uint8_t filter, uint32_t val)
-{
-	uint32_t tmp;
-
-	/* Upper half is current state. Lower half is requested state. */
-	tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
-		GATE_KEEPER_OS_MASK;
-
-	if (val)
-		tmp |=  (1 << filter);
-	else
-		tmp &= ~(1 << filter);
-
-	tzc_write_gate_keeper(base, (tmp & GATE_KEEPER_OR_MASK) <<
-			      GATE_KEEPER_OR_SHIFT);
-
-	/* Wait here until we see the change reflected in the TZC status. */
-	while (((tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
-		GATE_KEEPER_OS_MASK) != tmp)
-	  ;
-}
-
-
-void tzc_init(uintptr_t base)
-{
-	unsigned int tzc_id;
-	unsigned int tzc_build;
-
-	assert(base);
-
-	tzc.base = base;
-
-	/*
-	 * We expect to see a tzc400. Check peripheral ID.
-	 */
-	tzc_id = tzc_read_peripheral_id(tzc.base);
-	if (tzc_id != TZC400_PERIPHERAL_ID) {
-		ERROR("TZC : Wrong device ID (0x%x).\n", tzc_id);
-		panic();
-	}
-
-	/* Save values we will use later. */
-	tzc_build = tzc_read_build_config(tzc.base);
-	tzc.num_filters = ((tzc_build >> BUILD_CONFIG_NF_SHIFT) &
-			   BUILD_CONFIG_NF_MASK) + 1;
-	tzc.addr_width  = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) &
-			   BUILD_CONFIG_AW_MASK) + 1;
-	tzc.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) &
-			   BUILD_CONFIG_NR_MASK) + 1;
-}
-
-/*
- * `tzc_configure_region0` is used to program region 0 into the TrustZone
- * controller. Region 0 covers the whole address space that is not mapped
- * to any other region, and is enabled on all filters; this cannot be
- * changed. This function only changes the access permissions.
- */
-void tzc_configure_region0(tzc_region_attributes_t sec_attr,
-			   uint32_t ns_device_access)
-{
-	assert(tzc.base);
-
-	VERBOSE("TZC : Configuring region 0 (sec_attr=0x%x, ns_devs=0x%x)\n",
-		sec_attr, ns_device_access);
-
-	assert(sec_attr <= TZC_REGION_S_RDWR);
-
-	/* Set secure attributes on region 0 */
-	tzc_write_region_attributes(tzc.base, 0,
-		sec_attr << REG_ATTR_SEC_SHIFT);
-
-	/*
-	 * Specify which non-secure devices have permission to access
-	 * region 0.
-	 */
-	tzc_write_region_id_access(tzc.base, 0, ns_device_access);
-}
-
-
-/*
- * `tzc_configure_region` is used to program regions into the TrustZone
- * controller. A region can be associated with more than one filter. The
- * associated filters are passed in as a bitmap (bit0 = filter0).
- * NOTE:
- * Region 0 is special; it is preferable to use tzc_configure_region0
- * for this region (see comment for that function).
- */
-void tzc_configure_region(uint32_t filters,
-			  uint8_t  region,
-			  uint64_t region_base,
-			  uint64_t region_top,
-			  tzc_region_attributes_t sec_attr,
-			  uint32_t ns_device_access)
-{
-	assert(tzc.base);
-
-	VERBOSE("TZC : Configuring region (filters=0x%x, region=%d, ...\n",
-		filters, region);
-	VERBOSE("TZC : ... base=0x%lx, top=0x%lx, ...\n",
-		region_base, region_top);
-	VERBOSE("TZC : ... sec_attr=0x%x, ns_devs=0x%x)\n",
-		sec_attr, ns_device_access);
-
-	/* Do range checks on filters and regions. */
-	assert(((filters >> tzc.num_filters) == 0) &&
-	       (region < tzc.num_regions));
-
-	/*
-	 * Do address range check based on TZC configuration. A 64bit address is
-	 * the max and expected case.
-	 */
-	assert(((region_top <= (UINT64_MAX >> (64 - tzc.addr_width))) &&
-		(region_base < region_top)));
-
-	/* region_base and (region_top + 1) must be 4KB aligned */
-	assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
-
-	assert(sec_attr <= TZC_REGION_S_RDWR);
-
-	/*
-	 * Inputs look ok, start programming registers.
-	 * All the address registers are 32 bits wide and have a LOW and HIGH
-	 * component used to construct a up to a 64bit address.
-	 */
-	tzc_write_region_base_low(tzc.base, region,
-				(uint32_t)(region_base));
-	tzc_write_region_base_high(tzc.base, region,
-				(uint32_t)(region_base >> 32));
-
-	tzc_write_region_top_low(tzc.base, region,
-				(uint32_t)(region_top));
-	tzc_write_region_top_high(tzc.base, region,
-				(uint32_t)(region_top >> 32));
-
-	/* Assign the region to a filter and set secure attributes */
-	tzc_write_region_attributes(tzc.base, region,
-		(sec_attr << REG_ATTR_SEC_SHIFT) | filters);
-
-	/*
-	 * Specify which non-secure devices have permission to access this
-	 * region.
-	 */
-	tzc_write_region_id_access(tzc.base, region, ns_device_access);
-}
-
-
-void tzc_set_action(tzc_action_t action)
-{
-	assert(tzc.base);
-
-	/*
-	 * - Currently no handler is provided to trap an error via interrupt
-	 *   or exception.
-	 * - The interrupt action has not been tested.
-	 */
-	tzc_write_action(tzc.base, action);
-}
-
-
-void tzc_enable_filters(void)
-{
-	uint32_t state;
-	uint32_t filter;
-
-	assert(tzc.base);
-
-	for (filter = 0; filter < tzc.num_filters; filter++) {
-		state = tzc_get_gate_keeper(tzc.base, filter);
-		if (state) {
-			/* The TZC filter is already configured. Changing the
-			 * programmer's view in an active system can cause
-			 * unpredictable behavior therefore panic for now rather
-			 * than try to determine whether this is safe in this
-			 * instance. See:
-			 * http://infocenter.arm.com/help/index.jsp?\
-			 * topic=/com.arm.doc.ddi0504c/CJHHECBF.html */
-			ERROR("TZC : Filter %d Gatekeeper already enabled.\n",
-				filter);
-			panic();
-		}
-		tzc_set_gate_keeper(tzc.base, filter, 1);
-	}
-}
-
-
-void tzc_disable_filters(void)
-{
-	uint32_t filter;
-
-	assert(tzc.base);
-
-	/*
-	 * We don't do the same state check as above as the Gatekeepers are
-	 * disabled after reset.
-	 */
-	for (filter = 0; filter < tzc.num_filters; filter++)
-		tzc_set_gate_keeper(tzc.base, filter, 0);
-}
+#if ERROR_DEPRECATED
+#error "Using deprecated TZC-400 source file"
+#else
+#include "../tzc/tzc400.c"
+#endif /* ERROR_DEPRECATED */