diff --git a/arch/arm/cpu/armv7/omap5/dra7xx_iodelay.c b/arch/arm/cpu/armv7/omap5/dra7xx_iodelay.c
index 4b8ba26fd66c95067748765f49dad8f1541dd9c5..9fa6e6991f0ef7d168ed53f3903e9a16e8448568 100644
--- a/arch/arm/cpu/armv7/omap5/dra7xx_iodelay.c
+++ b/arch/arm/cpu/armv7/omap5/dra7xx_iodelay.c
@@ -13,6 +13,7 @@
 #include <asm/arch/omap.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/arch/clock.h>
+#include <asm/arch/mux_dra7xx.h>
 #include <asm/omap_common.h>
 
 static int isolate_io(u32 isolate)
@@ -80,7 +81,94 @@ static int update_delay_mechanism(u32 base)
 	return 0;
 }
 
-void __recalibrate_iodelay(struct pad_conf_entry const *pad, int npads)
+static u32 calculate_delay(u32 base, u16 offset, u16 den)
+{
+	u16 refclk_period, dly_cnt, ref_cnt;
+	u32 reg, q, r;
+
+	refclk_period = readl(base + CFG_REG_2_OFFSET) &
+			      CFG_REG_REFCLK_PERIOD_MASK;
+
+	reg = readl(base + offset);
+	dly_cnt = (reg & CFG_REG_DLY_CNT_MASK) >> CFG_REG_DLY_CNT_SHIFT;
+	ref_cnt = (reg & CFG_REG_REF_CNT_MASK) >> CFG_REG_REF_CNT_SHIFT;
+
+	if (!dly_cnt || !den)
+		return 0;
+
+	/*
+	 * To avoid overflow and integer truncation, delay value
+	 * is calculated as quotient + remainder.
+	 */
+	q = 5 * ((ref_cnt * refclk_period) / (dly_cnt * den));
+	r = (10 * ((ref_cnt * refclk_period) % (dly_cnt * den))) /
+		(2 * dly_cnt * den);
+
+	return q + r;
+}
+
+static u32 get_cfg_reg(u16 a_delay, u16 g_delay, u32 cpde, u32 fpde)
+{
+	u32 g_delay_coarse, g_delay_fine;
+	u32 a_delay_coarse, a_delay_fine;
+	u32 c_elements, f_elements;
+	u32 total_delay, reg = 0;
+
+	g_delay_coarse = g_delay / 920;
+	g_delay_fine = ((g_delay % 920) * 10) / 60;
+
+	a_delay_coarse = a_delay / cpde;
+	a_delay_fine = ((a_delay % cpde) * 10) / fpde;
+
+	c_elements = g_delay_coarse + a_delay_coarse;
+	f_elements = (g_delay_fine + a_delay_fine) / 10;
+
+	if (f_elements > 22) {
+		total_delay = c_elements * cpde + f_elements * fpde;
+
+		c_elements = total_delay / cpde;
+		f_elements = (total_delay % cpde) / fpde;
+	}
+
+	reg = (c_elements << CFG_X_COARSE_DLY_SHIFT) & CFG_X_COARSE_DLY_MASK;
+	reg |= (f_elements << CFG_X_FINE_DLY_SHIFT) & CFG_X_FINE_DLY_MASK;
+	reg |= CFG_X_SIGNATURE << CFG_X_SIGNATURE_SHIFT;
+	reg |= CFG_X_LOCK << CFG_X_LOCK_SHIFT;
+
+	return reg;
+}
+
+static int do_set_iodelay(u32 base, struct iodelay_cfg_entry const *array,
+			   int niodelays)
+{
+	struct iodelay_cfg_entry *iodelay = (struct iodelay_cfg_entry *)array;
+	u32 reg, cpde, fpde, i;
+
+	if (!niodelays)
+		return 0;
+
+	cpde = calculate_delay((*ctrl)->iodelay_config_base, CFG_REG_3_OFFSET,
+			       88);
+	if (!cpde)
+		return ERR_CPDE;
+
+	fpde = calculate_delay((*ctrl)->iodelay_config_base, CFG_REG_4_OFFSET,
+			       264);
+	if (!fpde)
+		return ERR_FPDE;
+
+	for (i = 0; i < niodelays; i++, iodelay++) {
+		reg = get_cfg_reg(iodelay->a_delay, iodelay->g_delay, cpde,
+				  fpde);
+		writel(reg, base + iodelay->offset);
+	}
+
+	return 0;
+}
+
+void __recalibrate_iodelay(struct pad_conf_entry const *pad, int npads,
+			   struct iodelay_cfg_entry const *iodelay,
+			   int niodelays)
 {
 	int ret = 0;
 
@@ -109,6 +197,11 @@ void __recalibrate_iodelay(struct pad_conf_entry const *pad, int npads)
 	/* Configure Mux settings */
 	do_set_mux32((*ctrl)->control_padconf_core_base, pad, npads);
 
+	/* Configure Manual IO timing modes */
+	ret = do_set_iodelay((*ctrl)->iodelay_config_base, iodelay, niodelays);
+	if (ret)
+		goto err;
+
 	ret = isolate_io(DEISOLATE_IO);
 
 err:
@@ -133,6 +226,12 @@ err:
 	case ERR_DEISOLATE_IO:
 		puts("IODELAY: De-isolation of Device IOs failed\n");
 		break;
+	case ERR_CPDE:
+		puts("IODELAY: CPDE calculation failed\n");
+		break;
+	case ERR_FPDE:
+		puts("IODELAY: FPDE calculation failed\n");
+		break;
 	default:
 		debug("IODELAY: IO delay recalibration successfully completed\n");
 	}
diff --git a/arch/arm/include/asm/arch-omap5/dra7xx_iodelay.h b/arch/arm/include/asm/arch-omap5/dra7xx_iodelay.h
index a924629a35df1b1c04c07b534eab0fea8119a854..2f53d85283b8d2138ac350ac28fde71042ffe5f1 100644
--- a/arch/arm/include/asm/arch-omap5/dra7xx_iodelay.h
+++ b/arch/arm/include/asm/arch-omap5/dra7xx_iodelay.h
@@ -35,6 +35,14 @@
 #define CFG_IODELAY_UNLOCK_KEY		0x0000AAAA
 #define CFG_IODELAY_LOCK_KEY		0x0000AAAB
 
+/* CONFIG_REG_3/4 */
+#define CFG_REG_3_OFFSET	0x18
+#define CFG_REG_4_OFFSET	0x1C
+#define CFG_REG_DLY_CNT_SHIFT	16
+#define CFG_REG_DLY_CNT_MASK	(0xFFFF << 16)
+#define CFG_REG_REF_CNT_SHIFT	0
+#define CFG_REG_REF_CNT_MASK	(0xFFFF << 0)
+
 /* CTRL_CORE_SMA_SW_0 */
 #define CTRL_ISOLATE_SHIFT		2
 #define CTRL_ISOLATE_MASK		(1 << 2)
@@ -53,6 +61,23 @@
 #define ERR_DEISOLATE_IO		0x2
 #define ERR_ISOLATE_IO			0x4
 #define ERR_UPDATE_DELAY		0x8
+#define ERR_CPDE			0x3
+#define ERR_FPDE			0x5
+
+/* CFG_XXX */
+#define CFG_X_SIGNATURE_SHIFT		12
+#define CFG_X_SIGNATURE_MASK		(0x3F << 12)
+#define CFG_X_LOCK_SHIFT		10
+#define CFG_X_LOCK_MASK			(0x1 << 10)
+#define CFG_X_COARSE_DLY_SHIFT		5
+#define CFG_X_COARSE_DLY_MASK		(0x1F << 5)
+#define CFG_X_FINE_DLY_SHIFT		0
+#define CFG_X_FINE_DLY_MASK		(0x1F << 0)
+#define CFG_X_SIGNATURE			0x29
+#define CFG_X_LOCK			1
+
+void __recalibrate_iodelay(struct pad_conf_entry const *pad, int npads,
+			   struct iodelay_cfg_entry const *iodelay,
+			   int niodelays);
 
-void __recalibrate_iodelay(struct pad_conf_entry const *array, int npads);
 #endif
diff --git a/arch/arm/include/asm/arch-omap5/mux_dra7xx.h b/arch/arm/include/asm/arch-omap5/mux_dra7xx.h
index 13c288b5d31296b472e4f34922b9f7397c6772f7..2115abb5553e59f2c2475cd8de4fbbebfa4633b0 100644
--- a/arch/arm/include/asm/arch-omap5/mux_dra7xx.h
+++ b/arch/arm/include/asm/arch-omap5/mux_dra7xx.h
@@ -61,6 +61,8 @@
 #define MODE_SELECT		(1 << 8)
 #define DELAYMODE_SHIFT		4
 
+#define MANUAL_MODE	MODE_SELECT
+
 #define VIRTUAL_MODE0	(MODE_SELECT | (0x0 << DELAYMODE_SHIFT))
 #define VIRTUAL_MODE1	(MODE_SELECT | (0x1 << DELAYMODE_SHIFT))
 #define VIRTUAL_MODE2	(MODE_SELECT | (0x2 << DELAYMODE_SHIFT))
diff --git a/arch/arm/include/asm/arch-omap5/sys_proto.h b/arch/arm/include/asm/arch-omap5/sys_proto.h
index b41bf15a08cf61e172fcbdb4defd5c916097b14a..6da8297c7292ec5329196fab082d45f93d9b12a5 100644
--- a/arch/arm/include/asm/arch-omap5/sys_proto.h
+++ b/arch/arm/include/asm/arch-omap5/sys_proto.h
@@ -18,6 +18,18 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/*
+ * Structure for Iodelay configuration registers.
+ * Theoretical max for g_delay is 21560 ps.
+ * Theoretical max for a_delay is 1/3rd of g_delay max.
+ * So using u16 for both a/g_delay.
+ */
+struct iodelay_cfg_entry {
+	u16 offset;
+	u16 a_delay;
+	u16 g_delay;
+};
+
 struct pad_conf_entry {
 	u32 offset;
 	u32 val;