diff --git a/drivers/arm/tzc/tzc_dmc620.c b/drivers/arm/tzc/tzc_dmc620.c
new file mode 100644
index 0000000000000000000000000000000000000000..4abd0800b1dc5b034b3f0c7ac15cf746e8a1664c
--- /dev/null
+++ b/drivers/arm/tzc/tzc_dmc620.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <mmio.h>
+#include <tzc_dmc620.h>
+
+/* Mask to extract bit 31 to 16 */
+#define MASK_31_16 UINT64_C(0x0000ffff0000)
+/* Mask to extract bit 47 to 32 */
+#define MASK_47_32 UINT64_C(0xffff00000000)
+
+/* Helper macro for getting dmc_base addr of a dmc_inst */
+#define DMC_BASE(plat_data, dmc_inst) \
+	((uintptr_t)(plat_data->dmc_base[dmc_inst]))
+
+/* Pointer to the tzc_dmc620_config_data structure populated by the platform */
+static const tzc_dmc620_config_data_t *g_plat_config_data;
+
+#if ENABLE_ASSERTIONS
+/*
+ * Helper function to check if the DMC-620 instance is present at the
+ * base address provided by the platform and also check if at least
+ * one dmc instance is present.
+ */
+static void tzc_dmc620_validate_plat_driver_data(
+			const tzc_dmc620_driver_data_t *plat_driver_data)
+{
+	uint8_t dmc_inst, dmc_count;
+	unsigned int dmc_id;
+	uintptr_t base;
+
+	assert(plat_driver_data != NULL);
+
+	dmc_count = plat_driver_data->dmc_count;
+	assert(dmc_count > 0U);
+
+	for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) {
+		base = DMC_BASE(plat_driver_data, dmc_inst);
+		dmc_id = mmio_read_32(base + DMC620_PERIPHERAL_ID_0);
+		assert(dmc_id == DMC620_PERIPHERAL_ID_0_VALUE);
+	}
+}
+#endif
+
+/*
+ * Program a region with region base and region top addresses of all
+ * DMC-620 instances.
+ */
+static void tzc_dmc620_configure_region(int region_no,
+					unsigned long long region_base,
+					unsigned long long region_top,
+					unsigned int sec_attr)
+{
+	uint32_t min_31_00, min_47_32;
+	uint32_t max_31_00, max_47_32;
+	uint8_t dmc_inst, dmc_count;
+	uintptr_t base;
+	const tzc_dmc620_driver_data_t *plat_driver_data;
+
+	plat_driver_data = g_plat_config_data->plat_drv_data;
+	assert(plat_driver_data != NULL);
+
+	/* Do range checks on regions. */
+	assert((region_no >= 0U) && (region_no <= DMC620_ACC_ADDR_COUNT));
+
+	/* region_base and (region_top + 1) must be 4KB aligned */
+	assert(((region_base | (region_top + 1U)) & (4096U - 1U)) == 0U);
+
+	dmc_count = plat_driver_data->dmc_count;
+	for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) {
+		min_31_00 = (region_base & MASK_31_16) | sec_attr;
+		min_47_32 = (region_base & MASK_47_32)
+				>> DMC620_ACC_ADDR_WIDTH;
+		max_31_00 = (region_top  & MASK_31_16);
+		max_47_32 = (region_top  & MASK_47_32)
+				>> DMC620_ACC_ADDR_WIDTH;
+
+		/* Extract the base address of the DMC-620 instance */
+		base = DMC_BASE(plat_driver_data, dmc_inst);
+		/* Configure access address region registers */
+		mmio_write_32(base + DMC620_ACC_ADDR_MIN_31_00_NEXT(region_no),
+				min_31_00);
+		mmio_write_32(base + DMC620_ACC_ADDR_MIN_47_32_NEXT(region_no),
+				min_47_32);
+		mmio_write_32(base + DMC620_ACC_ADDR_MAX_31_00_NEXT(region_no),
+				max_31_00);
+		mmio_write_32(base + DMC620_ACC_ADDR_MAX_47_32_NEXT(region_no),
+				max_47_32);
+	}
+}
+
+/*
+ * Set the action value for all the DMC-620 instances.
+ */
+static void tzc_dmc620_set_action(void)
+{
+	uint8_t dmc_inst, dmc_count;
+	uintptr_t base;
+	const tzc_dmc620_driver_data_t *plat_driver_data;
+
+	plat_driver_data = g_plat_config_data->plat_drv_data;
+	dmc_count = plat_driver_data->dmc_count;
+	for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) {
+		/* Extract the base address of the DMC-620 instance */
+		base = DMC_BASE(plat_driver_data, dmc_inst);
+		/* Switch to READY */
+		mmio_write_32(base + DMC620_MEMC_CMD, DMC620_MEMC_CMD_GO);
+		mmio_write_32(base + DMC620_MEMC_CMD, DMC620_MEMC_CMD_EXECUTE);
+	}
+}
+
+/*
+ * Verify whether the DMC-620 configuration is complete by reading back
+ * configuration registers and comparing it with the configured value. If
+ * configuration is incomplete, loop till the configured value is reflected in
+ * the register.
+ */
+static void tzc_dmc620_verify_complete(void)
+{
+	uint8_t dmc_inst, dmc_count;
+	uintptr_t base;
+	const tzc_dmc620_driver_data_t *plat_driver_data;
+
+	plat_driver_data = g_plat_config_data->plat_drv_data;
+	dmc_count = plat_driver_data->dmc_count;
+	for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) {
+		/* Extract the base address of the DMC-620 instance */
+		base = DMC_BASE(plat_driver_data, dmc_inst);
+		while ((mmio_read_32(base + DMC620_MEMC_STATUS) &
+				DMC620_MEMC_CMD_MASK) != DMC620_MEMC_CMD_GO)
+			continue;
+	}
+}
+
+/*
+ * Initialize the DMC-620 TrustZone Controller using the region configuration
+ * supplied by the platform. The DMC620 controller should be enabled elsewhere
+ * before invoking this function.
+ */
+void arm_tzc_dmc620_setup(const tzc_dmc620_config_data_t *plat_config_data)
+{
+	int i;
+
+	/* Check if valid pointer is passed */
+	assert(plat_config_data != NULL);
+
+	/*
+	 * Check if access address count passed by the platform is less than or
+	 * equal to DMC620's access address count
+	 */
+	assert(plat_config_data->acc_addr_count <= DMC620_ACC_ADDR_COUNT);
+
+#if ENABLE_ASSERTIONS
+	/* Validates the information passed by platform */
+	tzc_dmc620_validate_plat_driver_data(plat_config_data->plat_drv_data);
+#endif
+
+	g_plat_config_data = plat_config_data;
+
+	INFO("Configuring DMC-620 TZC settings\n");
+	for (i = 0U; i < g_plat_config_data->acc_addr_count; i++)
+		tzc_dmc620_configure_region(i,
+			g_plat_config_data->plat_acc_addr_data[i].region_base,
+			g_plat_config_data->plat_acc_addr_data[i].region_top,
+			g_plat_config_data->plat_acc_addr_data[i].sec_attr);
+
+	tzc_dmc620_set_action();
+	tzc_dmc620_verify_complete();
+	INFO("DMC-620 TZC setup completed\n");
+}
diff --git a/include/drivers/arm/tzc_dmc620.h b/include/drivers/arm/tzc_dmc620.h
new file mode 100644
index 0000000000000000000000000000000000000000..074bbc1224108f2170c0280c7b85999d35b30081
--- /dev/null
+++ b/include/drivers/arm/tzc_dmc620.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TZC_DMC620_H
+#define TZC_DMC620_H
+
+#include <utils_def.h>
+
+/* DMC-620 memc register offsets */
+#define DMC620_MEMC_STATUS	U(0x0000)
+#define DMC620_MEMC_CMD		U(0x0008)
+
+/* Mask value to check the status of memc_cmd register */
+#define DMC620_MEMC_CMD_MASK	U(0x00000007)
+
+/* memc_cmd register's action values */
+#define DMC620_MEMC_CMD_GO	U(0x00000003)
+#define DMC620_MEMC_CMD_EXECUTE	U(0x00000004)
+
+/* Address offsets of access address next region 0 registers */
+#define DMC620_ACC_ADDR_MIN_31_00_NEXT_BASE	U(0x0080)
+#define DMC620_ACC_ADDR_MIN_47_32_NEXT_BASE	U(0x0084)
+#define DMC620_ACC_ADDR_MAX_31_00_NEXT_BASE	U(0x0088)
+#define DMC620_ACC_ADDR_MAX_47_32_NEXT_BASE	U(0x008c)
+
+/* Length of one block of access address next register region */
+#define DMC620_ACC_ADDR_NEXT_SIZE		U(0x0010)
+
+/* Address offsets of access address next registers */
+#define DMC620_ACC_ADDR_MIN_31_00_NEXT(region_no)	\
+		(DMC620_ACC_ADDR_MIN_31_00_NEXT_BASE +	\
+			(region_no * DMC620_ACC_ADDR_NEXT_SIZE))
+#define DMC620_ACC_ADDR_MIN_47_32_NEXT(region_no)	\
+		(DMC620_ACC_ADDR_MIN_47_32_NEXT_BASE +	\
+			(region_no * DMC620_ACC_ADDR_NEXT_SIZE))
+#define DMC620_ACC_ADDR_MAX_31_00_NEXT(region_no)	\
+		(DMC620_ACC_ADDR_MAX_31_00_NEXT_BASE +	\
+			(region_no * DMC620_ACC_ADDR_NEXT_SIZE))
+#define DMC620_ACC_ADDR_MAX_47_32_NEXT(region_no)	\
+		(DMC620_ACC_ADDR_MAX_47_32_NEXT_BASE +	\
+			(region_no * DMC620_ACC_ADDR_NEXT_SIZE))
+
+/* Number of TZC address regions in DMC-620 */
+#define DMC620_ACC_ADDR_COUNT	U(8)
+/* Width of access address registers */
+#define DMC620_ACC_ADDR_WIDTH	U(32)
+
+/* Peripheral ID registers offsets */
+#define DMC620_PERIPHERAL_ID_0		U(0x1fe0)
+
+/* Default values in id registers */
+#define DMC620_PERIPHERAL_ID_0_VALUE	U(0x00000054)
+
+/* Secure access region attributes. */
+#define TZC_DMC620_REGION_NS_RD		U(0x00000001)
+#define TZC_DMC620_REGION_NS_WR		U(0x00000002)
+#define TZC_DMC620_REGION_NS_RDWR	\
+	(TZC_DMC620_REGION_NS_RD | TZC_DMC620_REGION_NS_WR)
+#define TZC_DMC620_REGION_S_RD		U(0x00000004)
+#define TZC_DMC620_REGION_S_WR		U(0x00000008)
+#define TZC_DMC620_REGION_S_RDWR	\
+	(TZC_DMC620_REGION_S_RD | TZC_DMC620_REGION_S_WR)
+#define TZC_DMC620_REGION_S_NS_RDWR	\
+	(TZC_DMC620_REGION_NS_RDWR | TZC_DMC620_REGION_S_RDWR)
+
+/*
+ * Contains pointer to the base addresses of all the DMC-620 instances.
+ * 'dmc_count' specifies the number of DMC base addresses contained in the
+ * array pointed to by dmc_base.
+ */
+typedef struct tzc_dmc620_driver_data {
+	const uintptr_t *dmc_base;
+	const unsigned int dmc_count;
+} tzc_dmc620_driver_data_t;
+
+/*
+ * Contains region base, region top addresses and corresponding attributes
+ * for configuring TZC access region registers.
+ */
+typedef struct tzc_dmc620_acc_addr_data {
+	const unsigned long long region_base;
+	const unsigned long long region_top;
+	const unsigned int sec_attr;
+} tzc_dmc620_acc_addr_data_t;
+
+/*
+ * Contains platform specific data for configuring TZC region base and
+ * region top address. 'acc_addr_count' specifies the number of
+ * valid entries in 'plat_acc_addr_data' array.
+ */
+typedef struct tzc_dmc620_config_data {
+	const tzc_dmc620_driver_data_t *plat_drv_data;
+	const tzc_dmc620_acc_addr_data_t *plat_acc_addr_data;
+	const uint8_t acc_addr_count;
+} tzc_dmc620_config_data_t;
+
+/* Function prototypes */
+void arm_tzc_dmc620_setup(const tzc_dmc620_config_data_t *plat_config_data);
+
+#endif /* TZC_DMC620_H */
+
diff --git a/plat/arm/board/sgi575/include/platform_def.h b/plat/arm/board/sgi575/include/platform_def.h
index 1870fc78aed86a1e830d8d8c7702b62fb2327006..c06a0a1fa8932dede1b340b92667aad26b851ee6 100644
--- a/plat/arm/board/sgi575/include/platform_def.h
+++ b/plat/arm/board/sgi575/include/platform_def.h
@@ -8,11 +8,16 @@
 #define PLATFORM_DEF_H
 
 #include <sgi_base_platform_def.h>
+#include <utils_def.h>
 
 #define PLAT_ARM_CLUSTER_COUNT		2
 #define CSS_SGI_MAX_CPUS_PER_CLUSTER	4
 #define CSS_SGI_MAX_PE_PER_CPU		1
 
-#define PLAT_CSS_MHU_BASE		0x45000000
+#define PLAT_CSS_MHU_BASE		UL(0x45000000)
+
+/* Base address of DMC-620 instances */
+#define SGI575_DMC620_BASE0		UL(0x4e000000)
+#define SGI575_DMC620_BASE1		UL(0x4e100000)
 
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/sgi575/platform.mk b/plat/arm/board/sgi575/platform.mk
index 8df8b1292a1764400bfee12c1d136d20a143b2df..dd82d2975f61d37e3d666487a9b7f228b648b648 100644
--- a/plat/arm/board/sgi575/platform.mk
+++ b/plat/arm/board/sgi575/platform.mk
@@ -14,7 +14,9 @@ SGI_CPU_SOURCES		:=	lib/cpus/aarch64/cortex_a75.S
 
 BL1_SOURCES		+=	${SGI_CPU_SOURCES}
 
-BL2_SOURCES		+=	lib/utils/mem_region.c			\
+BL2_SOURCES		+=	${SGI575_BASE}/sgi575_security.c	\
+				drivers/arm/tzc/tzc_dmc620.c		\
+				lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c
 
 BL31_SOURCES		+=	${SGI_CPU_SOURCES}			\
diff --git a/plat/arm/board/sgi575/sgi575_security.c b/plat/arm/board/sgi575/sgi575_security.c
new file mode 100644
index 0000000000000000000000000000000000000000..7ccc59a7bc696e9601cfb4a6f0786def760dd04e
--- /dev/null
+++ b/plat/arm/board/sgi575/sgi575_security.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <platform_def.h>
+#include <tzc_dmc620.h>
+
+uintptr_t sgi575_dmc_base[] = {
+	SGI575_DMC620_BASE0,
+	SGI575_DMC620_BASE1
+};
+
+static const tzc_dmc620_driver_data_t sgi575_plat_driver_data = {
+	.dmc_base = sgi575_dmc_base,
+	.dmc_count = ARRAY_SIZE(sgi575_dmc_base)
+};
+
+static const tzc_dmc620_acc_addr_data_t sgi575_acc_addr_data[] = {
+	{
+		.region_base = ARM_AP_TZC_DRAM1_BASE,
+		.region_top = ARM_AP_TZC_DRAM1_BASE + ARM_TZC_DRAM1_SIZE - 1,
+		.sec_attr = TZC_DMC620_REGION_S_RDWR
+	}
+};
+
+static const tzc_dmc620_config_data_t sgi575_plat_config_data = {
+	.plat_drv_data = &sgi575_plat_driver_data,
+	.plat_acc_addr_data = sgi575_acc_addr_data,
+	.acc_addr_count = ARRAY_SIZE(sgi575_acc_addr_data)
+};
+
+/* Initialize the secure environment */
+void plat_arm_security_setup(void)
+{
+	arm_tzc_dmc620_setup(&sgi575_plat_config_data);
+}
diff --git a/plat/arm/board/sgiclarka/include/platform_def.h b/plat/arm/board/sgiclarka/include/platform_def.h
index abc48d84cf6da854f7164eba9ae070d07ef34a3c..ba6d0434bb7eb1f63aaa7eb160521017d107a189 100644
--- a/plat/arm/board/sgiclarka/include/platform_def.h
+++ b/plat/arm/board/sgiclarka/include/platform_def.h
@@ -8,11 +8,16 @@
 #define PLATFORM_DEF_H
 
 #include <sgi_base_platform_def.h>
+#include <utils_def.h>
 
 #define PLAT_ARM_CLUSTER_COUNT		2
 #define CSS_SGI_MAX_CPUS_PER_CLUSTER	4
 #define CSS_SGI_MAX_PE_PER_CPU		1
 
-#define PLAT_CSS_MHU_BASE		0x45400000
+#define PLAT_CSS_MHU_BASE		UL(0x45400000)
+
+/* Base address of DMC-620 instances */
+#define SGICLARKA_DMC620_BASE0		UL(0x4e000000)
+#define SGICLARKA_DMC620_BASE1		UL(0x4e100000)
 
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/sgiclarka/platform.mk b/plat/arm/board/sgiclarka/platform.mk
index fc2f766704ef3fc180414423047fc6294f541715..cf02219fb9713f0fc3f85a5bdbb09d8cd9f19e69 100644
--- a/plat/arm/board/sgiclarka/platform.mk
+++ b/plat/arm/board/sgiclarka/platform.mk
@@ -14,7 +14,9 @@ SGI_CPU_SOURCES		:=	lib/cpus/aarch64/cortex_ares.S
 
 BL1_SOURCES		+=	${SGI_CPU_SOURCES}
 
-BL2_SOURCES		+=	lib/utils/mem_region.c			\
+BL2_SOURCES		+=	${SGICLARKA_BASE}/sgiclarka_security.c	\
+				drivers/arm/tzc/tzc_dmc620.c		\
+				lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c
 
 BL31_SOURCES		+=	${SGI_CPU_SOURCES}			\
diff --git a/plat/arm/board/sgiclarka/sgiclarka_security.c b/plat/arm/board/sgiclarka/sgiclarka_security.c
new file mode 100644
index 0000000000000000000000000000000000000000..29cd75474496f49e14ecdf2c3a4f3b1f30b34b21
--- /dev/null
+++ b/plat/arm/board/sgiclarka/sgiclarka_security.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <platform_def.h>
+#include <tzc_dmc620.h>
+
+uintptr_t sgiclarka_dmc_base[] = {
+	SGICLARKA_DMC620_BASE0,
+	SGICLARKA_DMC620_BASE1
+};
+
+static const tzc_dmc620_driver_data_t sgiclarka_plat_driver_data = {
+	.dmc_base = sgiclarka_dmc_base,
+	.dmc_count = ARRAY_SIZE(sgiclarka_dmc_base)
+};
+
+static const tzc_dmc620_acc_addr_data_t sgiclarka_acc_addr_data[] = {
+	{
+		.region_base = ARM_AP_TZC_DRAM1_BASE,
+		.region_top = ARM_AP_TZC_DRAM1_BASE + ARM_TZC_DRAM1_SIZE - 1,
+		.sec_attr = TZC_DMC620_REGION_S_RDWR
+	}
+};
+
+static const tzc_dmc620_config_data_t sgiclarka_plat_config_data = {
+	.plat_drv_data = &sgiclarka_plat_driver_data,
+	.plat_acc_addr_data = sgiclarka_acc_addr_data,
+	.acc_addr_count = ARRAY_SIZE(sgiclarka_acc_addr_data)
+};
+
+/* Initialize the secure environment */
+void plat_arm_security_setup(void)
+{
+	arm_tzc_dmc620_setup(&sgiclarka_plat_config_data);
+}
diff --git a/plat/arm/css/sgi/sgi-common.mk b/plat/arm/css/sgi/sgi-common.mk
index d6e5448de1542cc22c054fbd9f41ff2284ca6f4c..46fa7c4d798a015fe07f4899a3933ddb5dcdc607 100644
--- a/plat/arm/css/sgi/sgi-common.mk
+++ b/plat/arm/css/sgi/sgi-common.mk
@@ -35,8 +35,7 @@ PLAT_BL_COMMON_SOURCES	+=	${CSS_ENT_BASE}/sgi_plat.c	\
 
 BL1_SOURCES		+=	${INTERCONNECT_SOURCES}
 
-BL2_SOURCES		+=	${CSS_ENT_BASE}/sgi_security.c		\
-				${CSS_ENT_BASE}/sgi_image_load.c
+BL2_SOURCES		+=	${CSS_ENT_BASE}/sgi_image_load.c
 
 BL31_SOURCES		+=	${INTERCONNECT_SOURCES}			\
 				${ENT_GIC_SOURCES}			\
diff --git a/plat/arm/css/sgi/sgi_security.c b/plat/arm/css/sgi/sgi_security.c
deleted file mode 100644
index 23e1a64e51fe920db4f0daffef0281f6a44ef699..0000000000000000000000000000000000000000
--- a/plat/arm/css/sgi/sgi_security.c
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <arm_config.h>
-#include <plat_arm.h>
-
-/*
- * We assume that all security programming is done by the primary core.
- */
-void plat_arm_security_setup(void)
-{
-}