diff --git a/arch/arm/cpu/armv7/omap-common/hwinit-common.c b/arch/arm/cpu/armv7/omap-common/hwinit-common.c
index 2aec2ea..00e246b 100644
--- a/arch/arm/cpu/armv7/omap-common/hwinit-common.c
+++ b/arch/arm/cpu/armv7/omap-common/hwinit-common.c
@@ -35,6 +35,7 @@
 #include <asm/cache.h>
 #include <asm/system.h>
 #include <asm/omap_common.h>
+#include <linux/compiler.h>
 
 #define ARMV7_DCACHE_WRITEBACK  0xe
 #define	ARMV7_DOMAIN_CLIENT	1
@@ -106,6 +107,10 @@ void spl_display_print(void)
 }
 #endif
 
+void __weak srcomp_enable(void)
+{
+}
+
 /*
  * Routine: s_init
  * Description: Does early system init of watchdog, muxing,  andclocks
@@ -132,6 +137,7 @@ void s_init(void)
 	watchdog_init();
 	set_mux_conf_regs();
 #ifdef CONFIG_SPL_BUILD
+	srcomp_enable();
 	setup_clocks_for_console();
 
 	gd = &gdata;
diff --git a/arch/arm/cpu/armv7/omap5/hwinit.c b/arch/arm/cpu/armv7/omap5/hwinit.c
index 0d8c95d..620b99a 100644
--- a/arch/arm/cpu/armv7/omap5/hwinit.c
+++ b/arch/arm/cpu/armv7/omap5/hwinit.c
@@ -32,6 +32,7 @@
 #include <asm/armv7.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/sys_proto.h>
+#include <asm/arch/clocks.h>
 #include <asm/sizes.h>
 #include <asm/utils.h>
 #include <asm/arch/gpio.h>
@@ -182,6 +183,121 @@ void do_io_settings(void)
 	writel(EFUSE_3, (*ctrl)->control_efuse_3);
 	writel(EFUSE_4, (*ctrl)->control_efuse_4);
 }
+
+static const struct srcomp_params srcomp_parameters[NUM_SYS_CLKS] = {
+	{0x45, 0x1},	/* 12 MHz   */
+	{-1, -1},	/* 13 MHz   */
+	{0x63, 0x2},	/* 16.8 MHz */
+	{0x57, 0x2},	/* 19.2 MHz */
+	{0x20, 0x1},	/* 26 MHz   */
+	{-1, -1},	/* 27 MHz   */
+	{0x41, 0x3}	/* 38.4 MHz */
+};
+
+void srcomp_enable(void)
+{
+	u32 srcomp_value, mul_factor, div_factor, clk_val, i;
+	u32 sysclk_ind	= get_sys_clk_index();
+	u32 omap_rev	= omap_revision();
+
+	mul_factor = srcomp_parameters[sysclk_ind].multiply_factor;
+	div_factor = srcomp_parameters[sysclk_ind].divide_factor;
+
+	for (i = 0; i < 4; i++) {
+		srcomp_value = readl((*ctrl)->control_srcomp_north_side + i*4);
+		srcomp_value &=
+			~(MULTIPLY_FACTOR_XS_MASK | DIVIDE_FACTOR_XS_MASK);
+		srcomp_value |= (mul_factor << MULTIPLY_FACTOR_XS_SHIFT) |
+			(div_factor << DIVIDE_FACTOR_XS_SHIFT);
+		writel(srcomp_value, (*ctrl)->control_srcomp_north_side + i*4);
+	}
+
+	if ((omap_rev == OMAP5430_ES1_0) || (omap_rev == OMAP5432_ES1_0)) {
+		clk_val = readl((*prcm)->cm_coreaon_io_srcomp_clkctrl);
+		clk_val |= OPTFCLKEN_SRCOMP_FCLK_MASK;
+		writel(clk_val, (*prcm)->cm_coreaon_io_srcomp_clkctrl);
+
+		for (i = 0; i < 4; i++) {
+			srcomp_value =
+				readl((*ctrl)->control_srcomp_north_side + i*4);
+			srcomp_value &= ~PWRDWN_XS_MASK;
+			writel(srcomp_value,
+			       (*ctrl)->control_srcomp_north_side + i*4);
+
+			while (((readl((*ctrl)->control_srcomp_north_side + i*4)
+				& SRCODE_READ_XS_MASK) >>
+				SRCODE_READ_XS_SHIFT) == 0)
+				;
+
+			srcomp_value =
+				readl((*ctrl)->control_srcomp_north_side + i*4);
+			srcomp_value &= ~OVERRIDE_XS_MASK;
+			writel(srcomp_value,
+			       (*ctrl)->control_srcomp_north_side + i*4);
+		}
+	} else {
+		srcomp_value = readl((*ctrl)->control_srcomp_east_side_wkup);
+		srcomp_value &= ~(MULTIPLY_FACTOR_XS_MASK |
+				  DIVIDE_FACTOR_XS_MASK);
+		srcomp_value |= (mul_factor << MULTIPLY_FACTOR_XS_SHIFT) |
+				(div_factor << DIVIDE_FACTOR_XS_SHIFT);
+		writel(srcomp_value, (*ctrl)->control_srcomp_east_side_wkup);
+
+		for (i = 0; i < 4; i++) {
+			srcomp_value =
+				readl((*ctrl)->control_srcomp_north_side + i*4);
+			srcomp_value |= SRCODE_OVERRIDE_SEL_XS_MASK;
+			writel(srcomp_value,
+			       (*ctrl)->control_srcomp_north_side + i*4);
+
+			srcomp_value =
+				readl((*ctrl)->control_srcomp_north_side + i*4);
+			srcomp_value &= ~OVERRIDE_XS_MASK;
+			writel(srcomp_value,
+			       (*ctrl)->control_srcomp_north_side + i*4);
+		}
+
+		srcomp_value =
+			readl((*ctrl)->control_srcomp_east_side_wkup);
+		srcomp_value |= SRCODE_OVERRIDE_SEL_XS_MASK;
+		writel(srcomp_value, (*ctrl)->control_srcomp_east_side_wkup);
+
+		srcomp_value =
+			readl((*ctrl)->control_srcomp_east_side_wkup);
+		srcomp_value &= ~OVERRIDE_XS_MASK;
+		writel(srcomp_value, (*ctrl)->control_srcomp_east_side_wkup);
+
+		clk_val = readl((*prcm)->cm_coreaon_io_srcomp_clkctrl);
+		clk_val |= OPTFCLKEN_SRCOMP_FCLK_MASK;
+		writel(clk_val, (*prcm)->cm_coreaon_io_srcomp_clkctrl);
+
+		clk_val = readl((*prcm)->cm_wkupaon_io_srcomp_clkctrl);
+		clk_val |= OPTFCLKEN_SRCOMP_FCLK_MASK;
+		writel(clk_val, (*prcm)->cm_wkupaon_io_srcomp_clkctrl);
+
+		for (i = 0; i < 4; i++) {
+			while (((readl((*ctrl)->control_srcomp_north_side + i*4)
+				& SRCODE_READ_XS_MASK) >>
+				SRCODE_READ_XS_SHIFT) == 0)
+				;
+
+			srcomp_value =
+				readl((*ctrl)->control_srcomp_north_side + i*4);
+			srcomp_value &= ~SRCODE_OVERRIDE_SEL_XS_MASK;
+			writel(srcomp_value,
+			       (*ctrl)->control_srcomp_north_side + i*4);
+		}
+
+		while (((readl((*ctrl)->control_srcomp_east_side_wkup) &
+			SRCODE_READ_XS_MASK) >> SRCODE_READ_XS_SHIFT) == 0)
+			;
+
+		srcomp_value =
+			readl((*ctrl)->control_srcomp_east_side_wkup);
+		srcomp_value &= ~SRCODE_OVERRIDE_SEL_XS_MASK;
+		writel(srcomp_value, (*ctrl)->control_srcomp_east_side_wkup);
+	}
+}
 #endif
 
 void config_data_eye_leveling_samples(u32 emif_base)
diff --git a/arch/arm/cpu/armv7/omap5/prcm-regs.c b/arch/arm/cpu/armv7/omap5/prcm-regs.c
index 58c9d50..5e5abcc 100644
--- a/arch/arm/cpu/armv7/omap5/prcm-regs.c
+++ b/arch/arm/cpu/armv7/omap5/prcm-regs.c
@@ -149,6 +149,7 @@ struct prcm_regs const omap5_es1_prcm = {
 
 	/* cm2.core */
 	.cm_coreaon_bandgap_clkctrl = 0x4a008648,
+	.cm_coreaon_io_srcomp_clkctrl = 0x4a008650,
 	.cm_l3_1_clkstctrl = 0x4a008700,
 	.cm_l3_1_dynamicdep = 0x4a008708,
 	.cm_l3_1_l3_1_clkctrl = 0x4a008720,
@@ -294,6 +295,7 @@ struct prcm_regs const omap5_es1_prcm = {
 	.cm_wkup_rtc_clkctrl = 0x4ae07880,
 	.cm_wkup_bandgap_clkctrl = 0x4ae07888,
 	.cm_wkupaon_scrm_clkctrl = 0x4ae07890,
+	.cm_wkupaon_io_srcomp_clkctrl = 0x4ae07898,
 	.prm_vc_val_bypass = 0x4ae07ba0,
 	.prm_vc_cfg_i2c_mode = 0x4ae07bb4,
 	.prm_vc_cfg_i2c_clk = 0x4ae07bb8,
@@ -502,7 +504,7 @@ struct prcm_regs const omap5_es2_prcm = {
 	.cm_ssc_deltamstep_dpll_unipro = 0x4a0081e8,
 	.cm_ssc_modfreqdiv_dpll_unipro = 0x4a0081ec,
 	.cm_coreaon_bandgap_clkctrl = 0x4a008648,
-
+	.cm_coreaon_io_srcomp_clkctrl = 0x4a008650,
 
 	/* cm2.core */
 	.cm_l3_1_clkstctrl = 0x4a008700,
@@ -650,6 +652,7 @@ struct prcm_regs const omap5_es2_prcm = {
 	.cm_wkup_rtc_clkctrl = 0x4ae07980,
 	.cm_wkup_bandgap_clkctrl = 0x4ae07988,
 	.cm_wkupaon_scrm_clkctrl = 0x4ae07990,
+	.cm_wkupaon_io_srcomp_clkctrl = 0x4ae07998,
 	.prm_vc_val_bypass = 0x4ae07ca0,
 	.prm_vc_cfg_i2c_mode = 0x4ae07cb4,
 	.prm_vc_cfg_i2c_clk = 0x4ae07cb8,
diff --git a/arch/arm/include/asm/arch-omap5/clocks.h b/arch/arm/include/asm/arch-omap5/clocks.h
index 685aad5..6f64186 100644
--- a/arch/arm/include/asm/arch-omap5/clocks.h
+++ b/arch/arm/include/asm/arch-omap5/clocks.h
@@ -186,6 +186,10 @@
 #define OPTFCLKEN_SCRM_CORE_SHIFT		8
 #define OPTFCLKEN_SCRM_CORE_MASK		(1 << 8)
 
+/* CM_COREAON_IO_SRCOMP_CLKCTRL */
+#define OPTFCLKEN_SRCOMP_FCLK_SHIFT		8
+#define OPTFCLKEN_SRCOMP_FCLK_MASK		(1 << 8)
+
 /* Clock frequencies */
 #define OMAP_SYS_CLK_FREQ_38_4_MHZ	38400000
 #define OMAP_SYS_CLK_IND_38_4_MHZ	6
diff --git a/arch/arm/include/asm/arch-omap5/omap.h b/arch/arm/include/asm/arch-omap5/omap.h
index ba2775b..d29be93 100644
--- a/arch/arm/include/asm/arch-omap5/omap.h
+++ b/arch/arm/include/asm/arch-omap5/omap.h
@@ -229,7 +229,26 @@ struct s32ktimer {
 #define CH_FLAGS_CHFLASH	(0x1 << 2)
 #define CH_FLAGS_CHMMCSD	(0x1 << 3)
 
+/* CONTROL_SRCOMP_XXX_SIDE */
+#define OVERRIDE_XS_SHIFT		30
+#define OVERRIDE_XS_MASK		(1 << 30)
+#define SRCODE_READ_XS_SHIFT		12
+#define SRCODE_READ_XS_MASK		(0xff << 12)
+#define PWRDWN_XS_SHIFT			11
+#define PWRDWN_XS_MASK			(1 << 11)
+#define DIVIDE_FACTOR_XS_SHIFT		4
+#define DIVIDE_FACTOR_XS_MASK		(0x7f << 4)
+#define MULTIPLY_FACTOR_XS_SHIFT	1
+#define MULTIPLY_FACTOR_XS_MASK		(0x7 << 1)
+#define SRCODE_OVERRIDE_SEL_XS_SHIFT	0
+#define SRCODE_OVERRIDE_SEL_XS_MASK	(1 << 0)
+
 #ifndef __ASSEMBLY__
+struct srcomp_params {
+	s8 divide_factor;
+	s8 multiply_factor;
+};
+
 struct omap_boot_parameters {
 	char *boot_message;
 	unsigned int mem_boot_descriptor;
diff --git a/arch/arm/include/asm/arch-omap5/sys_proto.h b/arch/arm/include/asm/arch-omap5/sys_proto.h
index 201ed6f..b8d841d 100644
--- a/arch/arm/include/asm/arch-omap5/sys_proto.h
+++ b/arch/arm/include/asm/arch-omap5/sys_proto.h
@@ -59,6 +59,7 @@ int omap_vc_bypass_send_value(u8 sa, u8 reg_addr, u8 reg_data);
 u32 warm_reset(void);
 void force_emif_self_refresh(void);
 void get_ioregs(const struct ctrl_ioregs **regs);
+void srcomp_enable(void);
 
 /*
  * This is used to verify if the configuration header
diff --git a/arch/arm/include/asm/omap_common.h b/arch/arm/include/asm/omap_common.h
index 8a886ec..0af0c33 100644
--- a/arch/arm/include/asm/omap_common.h
+++ b/arch/arm/include/asm/omap_common.h
@@ -153,6 +153,7 @@ struct prcm_regs {
 
 	/* cm2.core */
 	u32 cm_coreaon_bandgap_clkctrl;
+	u32 cm_coreaon_io_srcomp_clkctrl;
 	u32 cm_l3_1_clkstctrl;
 	u32 cm_l3_1_dynamicdep;
 	u32 cm_l3_1_l3_1_clkctrl;
@@ -300,6 +301,7 @@ struct prcm_regs {
 	u32 cm_wkup_rtc_clkctrl;
 	u32 cm_wkup_bandgap_clkctrl;
 	u32 cm_wkupaon_scrm_clkctrl;
+	u32 cm_wkupaon_io_srcomp_clkctrl;
 	u32 prm_vc_val_bypass;
 	u32 prm_vc_cfg_i2c_mode;
 	u32 prm_vc_cfg_i2c_clk;
