diff --git a/arch/arm/cpu/armv7/socfpga/Makefile b/arch/arm/cpu/armv7/socfpga/Makefile
index 0859e44..10d20f2 100644
--- a/arch/arm/cpu/armv7/socfpga/Makefile
+++ b/arch/arm/cpu/armv7/socfpga/Makefile
@@ -14,7 +14,7 @@ LIB	=  $(obj)lib$(SOC).o
 
 SOBJS	:= lowlevel_init.o
 COBJS-y	:= misc.o timer.o reset_manager.o system_manager.o
-COBJS-$(CONFIG_SPL_BUILD) += spl.o
+COBJS-$(CONFIG_SPL_BUILD) += spl.o freeze_controller.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
diff --git a/arch/arm/cpu/armv7/socfpga/freeze_controller.c b/arch/arm/cpu/armv7/socfpga/freeze_controller.c
new file mode 100644
index 0000000..330b4aa
--- /dev/null
+++ b/arch/arm/cpu/armv7/socfpga/freeze_controller.c
@@ -0,0 +1,216 @@
+/*
+ *  Copyright (C) 2013 Altera Corporation <www.altera.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/freeze_controller.h>
+#include <asm/arch/timer.h>
+#include <asm/errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct socfpga_freeze_controller *freeze_controller_base =
+		(void *)(SOCFPGA_SYSMGR_ADDRESS + SYSMGR_FRZCTRL_ADDRESS);
+
+/*
+ * Default state from cold reset is FREEZE_ALL; the global
+ * flag is set to TRUE to indicate the IO banks are frozen
+ */
+static uint32_t frzctrl_channel_freeze[FREEZE_CHANNEL_NUM]
+	= { FREEZE_CTRL_FROZEN, FREEZE_CTRL_FROZEN,
+	FREEZE_CTRL_FROZEN, FREEZE_CTRL_FROZEN};
+
+/* Freeze HPS IOs */
+void sys_mgr_frzctrl_freeze_req(void)
+{
+	u32 ioctrl_reg_offset;
+	u32 reg_value;
+	u32 reg_cfg_mask;
+	u32 channel_id;
+
+	/* select software FSM */
+	writel(SYSMGR_FRZCTRL_SRC_VIO1_ENUM_SW,	&freeze_controller_base->src);
+
+	/* Freeze channel 0 to 2 */
+	for (channel_id = 0; channel_id <= 2; channel_id++) {
+		ioctrl_reg_offset = (u32)(
+			&freeze_controller_base->vioctrl +
+			(channel_id << SYSMGR_FRZCTRL_VIOCTRL_SHIFT));
+
+		/*
+		 * Assert active low enrnsl, plniotri
+		 * and niotri signals
+		 */
+		reg_cfg_mask =
+			SYSMGR_FRZCTRL_VIOCTRL_SLEW_MASK
+			| SYSMGR_FRZCTRL_VIOCTRL_WKPULLUP_MASK
+			| SYSMGR_FRZCTRL_VIOCTRL_TRISTATE_MASK;
+		clrbits_le32(ioctrl_reg_offset,	reg_cfg_mask);
+
+		/*
+		 * Note: Delay for 20ns at min
+		 * Assert active low bhniotri signal and de-assert
+		 * active high csrdone
+		 */
+		reg_cfg_mask
+			= SYSMGR_FRZCTRL_VIOCTRL_BUSHOLD_MASK
+			| SYSMGR_FRZCTRL_VIOCTRL_CFG_MASK;
+		clrbits_le32(ioctrl_reg_offset,	reg_cfg_mask);
+
+		/* Set global flag to indicate channel is frozen */
+		frzctrl_channel_freeze[channel_id] = FREEZE_CTRL_FROZEN;
+	}
+
+	/* Freeze channel 3 */
+	/*
+	 * Assert active low enrnsl, plniotri and
+	 * niotri signals
+	 */
+	reg_cfg_mask
+		= SYSMGR_FRZCTRL_HIOCTRL_SLEW_MASK
+		| SYSMGR_FRZCTRL_HIOCTRL_WKPULLUP_MASK
+		| SYSMGR_FRZCTRL_HIOCTRL_TRISTATE_MASK;
+	clrbits_le32(&freeze_controller_base->hioctrl, reg_cfg_mask);
+
+	/*
+	 * assert active low bhniotri & nfrzdrv signals,
+	 * de-assert active high csrdone and assert
+	 * active high frzreg and nfrzdrv signals
+	 */
+	reg_value = readl(&freeze_controller_base->hioctrl);
+	reg_cfg_mask
+		= SYSMGR_FRZCTRL_HIOCTRL_BUSHOLD_MASK
+		| SYSMGR_FRZCTRL_HIOCTRL_CFG_MASK;
+	reg_value
+		= (reg_value & ~reg_cfg_mask)
+		| SYSMGR_FRZCTRL_HIOCTRL_REGRST_MASK
+		| SYSMGR_FRZCTRL_HIOCTRL_OCTRST_MASK;
+	writel(reg_value, &freeze_controller_base->hioctrl);
+
+	/*
+	 * assert active high reinit signal and de-assert
+	 * active high pllbiasen signals
+	 */
+	reg_value = readl(&freeze_controller_base->hioctrl);
+	reg_value
+		= (reg_value &
+		~SYSMGR_FRZCTRL_HIOCTRL_OCT_CFGEN_CALSTART_MASK)
+		| SYSMGR_FRZCTRL_HIOCTRL_DLLRST_MASK;
+	writel(reg_value, &freeze_controller_base->hioctrl);
+
+	/* Set global flag to indicate channel is frozen */
+	frzctrl_channel_freeze[channel_id] = FREEZE_CTRL_FROZEN;
+}
+
+/* Unfreeze/Thaw HPS IOs */
+void sys_mgr_frzctrl_thaw_req(void)
+{
+	u32 ioctrl_reg_offset;
+	u32 reg_cfg_mask;
+	u32 reg_value;
+	u32 channel_id;
+
+	/* select software FSM */
+	writel(SYSMGR_FRZCTRL_SRC_VIO1_ENUM_SW,	&freeze_controller_base->src);
+
+	/* Thaw channel 0 to 2 */
+	for (channel_id = 0; channel_id <= 2; channel_id++) {
+		ioctrl_reg_offset
+			= (u32)(&freeze_controller_base->vioctrl
+				+ (channel_id << SYSMGR_FRZCTRL_VIOCTRL_SHIFT));
+
+		/*
+		 * Assert active low bhniotri signal and
+		 * de-assert active high csrdone
+		 */
+		reg_cfg_mask
+			= SYSMGR_FRZCTRL_VIOCTRL_BUSHOLD_MASK
+			| SYSMGR_FRZCTRL_VIOCTRL_CFG_MASK;
+		setbits_le32(ioctrl_reg_offset,	reg_cfg_mask);
+
+		/*
+		 * Note: Delay for 20ns at min
+		 * de-assert active low plniotri and niotri signals
+		 */
+		reg_cfg_mask
+			= SYSMGR_FRZCTRL_VIOCTRL_WKPULLUP_MASK
+			| SYSMGR_FRZCTRL_VIOCTRL_TRISTATE_MASK;
+		setbits_le32(ioctrl_reg_offset,	reg_cfg_mask);
+
+		/*
+		 * Note: Delay for 20ns at min
+		 * de-assert active low enrnsl signal
+		 */
+		setbits_le32(ioctrl_reg_offset,
+			SYSMGR_FRZCTRL_VIOCTRL_SLEW_MASK);
+
+		/* Set global flag to indicate channel is thawed */
+		frzctrl_channel_freeze[channel_id] = FREEZE_CTRL_THAWED;
+	}
+
+	/* Thaw channel 3 */
+	/* de-assert active high reinit signal */
+	clrbits_le32(&freeze_controller_base->hioctrl,
+		SYSMGR_FRZCTRL_HIOCTRL_DLLRST_MASK);
+
+	/*
+	 * Note: Delay for 40ns at min
+	 * assert active high pllbiasen signals
+	 */
+	setbits_le32(&freeze_controller_base->hioctrl,
+		SYSMGR_FRZCTRL_HIOCTRL_OCT_CFGEN_CALSTART_MASK);
+
+	/*
+	 * Delay 1000 intosc. intosc is based on eosc1
+	 * Use worst case which is fatest eosc1=50MHz, delay required
+	 * is 1/50MHz * 1000 = 20us
+	 */
+	udelay(20);
+
+	/*
+	 * de-assert active low bhniotri signals,
+	 * assert active high csrdone and nfrzdrv signal
+	 */
+	reg_value = readl(&freeze_controller_base->hioctrl);
+	reg_value = (reg_value
+		| SYSMGR_FRZCTRL_HIOCTRL_BUSHOLD_MASK
+		| SYSMGR_FRZCTRL_HIOCTRL_CFG_MASK)
+		& ~SYSMGR_FRZCTRL_HIOCTRL_OCTRST_MASK;
+	writel(reg_value, &freeze_controller_base->hioctrl);
+
+	/*
+	 * Delay 33 intosc
+	 * Use worst case which is fatest eosc1=50MHz, delay required
+	 * is 1/50MHz * 33 = 660ns ~= 1us
+	 */
+	udelay(1);
+
+	/* de-assert active low plniotri and niotri signals */
+	reg_cfg_mask
+		= SYSMGR_FRZCTRL_HIOCTRL_WKPULLUP_MASK
+		| SYSMGR_FRZCTRL_HIOCTRL_TRISTATE_MASK;
+
+	setbits_le32(&freeze_controller_base->hioctrl, reg_cfg_mask);
+
+	/*
+	 * Note: Delay for 40ns at min
+	 * de-assert active high frzreg signal
+	 */
+	clrbits_le32(&freeze_controller_base->hioctrl,
+		SYSMGR_FRZCTRL_HIOCTRL_REGRST_MASK);
+
+	/*
+	 * Note: Delay for 40ns at min
+	 * de-assert active low enrnsl signal
+	 */
+	setbits_le32(&freeze_controller_base->hioctrl,
+		SYSMGR_FRZCTRL_HIOCTRL_SLEW_MASK);
+
+	/* Set global flag to indicate channel is thawed */
+	frzctrl_channel_freeze[channel_id] = FREEZE_CTRL_THAWED;
+}
+
diff --git a/arch/arm/cpu/armv7/socfpga/spl.c b/arch/arm/cpu/armv7/socfpga/spl.c
index 74bceab..36a00c3 100644
--- a/arch/arm/cpu/armv7/socfpga/spl.c
+++ b/arch/arm/cpu/armv7/socfpga/spl.c
@@ -13,6 +13,7 @@
 #include <asm/arch/reset_manager.h>
 #include <spl.h>
 #include <asm/arch/system_manager.h>
+#include <asm/arch/freeze_controller.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -27,6 +28,10 @@ u32 spl_boot_device(void)
 void spl_board_init(void)
 {
 #ifndef CONFIG_SOCFPGA_VIRTUAL_TARGET
+	debug("Freezing all I/O banks\n");
+	/* freeze all IO banks */
+	sys_mgr_frzctrl_freeze_req();
+
 	/* configure the pin muxing through system manager */
 	sysmgr_pinmux_init();
 #endif /* CONFIG_SOCFPGA_VIRTUAL_TARGET */
@@ -34,6 +39,10 @@ void spl_board_init(void)
 	/* de-assert reset for peripherals and bridges based on handoff */
 	reset_deassert_peripherals_handoff();
 
+	debug("Unfreezing/Thaw all I/O banks\n");
+	/* unfreeze / thaw all IO banks */
+	sys_mgr_frzctrl_thaw_req();
+
 	/* enable console uart printing */
 	preloader_console_init();
 }
diff --git a/arch/arm/include/asm/arch-socfpga/freeze_controller.h b/arch/arm/include/asm/arch-socfpga/freeze_controller.h
new file mode 100644
index 0000000..120f20e
--- /dev/null
+++ b/arch/arm/include/asm/arch-socfpga/freeze_controller.h
@@ -0,0 +1,50 @@
+/*
+ *  Copyright (C) 2013 Altera Corporation <www.altera.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef	_FREEZE_CONTROLLER_H_
+#define	_FREEZE_CONTROLLER_H_
+
+struct socfpga_freeze_controller {
+	u32	vioctrl;
+	u32	padding[3];
+	u32	hioctrl;
+	u32	src;
+	u32	hwctrl;
+};
+
+#define FREEZE_CHANNEL_NUM		(4)
+
+typedef enum {
+	FREEZE_CTRL_FROZEN = 0,
+	FREEZE_CTRL_THAWED = 1
+} FREEZE_CTRL_CHAN_STATE;
+
+#define SYSMGR_FRZCTRL_ADDRESS 0x40
+#define SYSMGR_FRZCTRL_SRC_VIO1_ENUM_SW 0x0
+#define SYSMGR_FRZCTRL_SRC_VIO1_ENUM_HW 0x1
+#define SYSMGR_FRZCTRL_VIOCTRL_SLEW_MASK 0x00000010
+#define SYSMGR_FRZCTRL_VIOCTRL_WKPULLUP_MASK 0x00000008
+#define SYSMGR_FRZCTRL_VIOCTRL_TRISTATE_MASK 0x00000004
+#define SYSMGR_FRZCTRL_VIOCTRL_BUSHOLD_MASK 0x00000002
+#define SYSMGR_FRZCTRL_VIOCTRL_CFG_MASK 0x00000001
+#define SYSMGR_FRZCTRL_HIOCTRL_SLEW_MASK 0x00000010
+#define SYSMGR_FRZCTRL_HIOCTRL_WKPULLUP_MASK 0x00000008
+#define SYSMGR_FRZCTRL_HIOCTRL_TRISTATE_MASK 0x00000004
+#define SYSMGR_FRZCTRL_HIOCTRL_BUSHOLD_MASK 0x00000002
+#define SYSMGR_FRZCTRL_HIOCTRL_CFG_MASK 0x00000001
+#define SYSMGR_FRZCTRL_HIOCTRL_REGRST_MASK 0x00000080
+#define SYSMGR_FRZCTRL_HIOCTRL_OCTRST_MASK 0x00000040
+#define SYSMGR_FRZCTRL_HIOCTRL_OCT_CFGEN_CALSTART_MASK 0x00000100
+#define SYSMGR_FRZCTRL_HIOCTRL_DLLRST_MASK 0x00000020
+#define SYSMGR_FRZCTRL_HWCTRL_VIO1REQ_MASK 0x00000001
+#define SYSMGR_FRZCTRL_HWCTRL_VIO1STATE_ENUM_FROZEN 0x2
+#define SYSMGR_FRZCTRL_HWCTRL_VIO1STATE_ENUM_THAWED 0x1
+#define SYSMGR_FRZCTRL_VIOCTRL_SHIFT 0x2
+
+void sys_mgr_frzctrl_freeze_req(void);
+void sys_mgr_frzctrl_thaw_req(void);
+
+#endif /* _FREEZE_CONTROLLER_H_ */
