diff --git a/drivers/clk/mxs/clk-imx23.c b/drivers/clk/mxs/clk-imx23.c
index f01876af6bb8..b7d3c44bbcbb 100644
--- a/drivers/clk/mxs/clk-imx23.c
+++ b/drivers/clk/mxs/clk-imx23.c
@@ -117,10 +117,10 @@ static void __init mx23_clocks_init(struct device_node *np)
 
 	clks[ref_xtal] = mxs_clk_fixed("ref_xtal", 24000000);
 	clks[pll] = mxs_clk_pll("pll", "ref_xtal", PLLCTRL0, 16, 480000000);
-	clks[ref_cpu] = mxs_clk_ref("ref_cpu", "pll", FRAC, 0);
-	clks[ref_emi] = mxs_clk_ref("ref_emi", "pll", FRAC, 1);
-	clks[ref_pix] = mxs_clk_ref("ref_pix", "pll", FRAC, 2);
-	clks[ref_io] = mxs_clk_ref("ref_io", "pll", FRAC, 3);
+	clks[ref_cpu] = mxs_clk_ref("ref_cpu", "pll", FRAC, 0, 18);
+	clks[ref_emi] = mxs_clk_ref("ref_emi", "pll", FRAC, 1, 18);
+	clks[ref_pix] = mxs_clk_ref("ref_pix", "pll", FRAC, 2, 18);
+	clks[ref_io] = mxs_clk_ref("ref_io", "pll", FRAC, 3, 18);
 	clks[saif_sel] = mxs_clk_mux("saif_sel", CLKSEQ, 0, 1, sel_pll, ARRAY_SIZE(sel_pll));
 	clks[lcdif_sel] = mxs_clk_mux("lcdif_sel", CLKSEQ, 1, 1, sel_pix, ARRAY_SIZE(sel_pix));
 	clks[gpmi_sel] = mxs_clk_mux("gpmi_sel", CLKSEQ, 4, 1, sel_io, ARRAY_SIZE(sel_io));
diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c
index 6b572b759f9a..09e324cbd32f 100644
--- a/drivers/clk/mxs/clk-imx28.c
+++ b/drivers/clk/mxs/clk-imx28.c
@@ -174,13 +174,13 @@ static void __init mx28_clocks_init(struct device_node *np)
 	clks[pll0] = mxs_clk_pll("pll0", "ref_xtal", PLL0CTRL0, 17, 480000000);
 	clks[pll1] = mxs_clk_pll("pll1", "ref_xtal", PLL1CTRL0, 17, 480000000);
 	clks[pll2] = mxs_clk_pll("pll2", "ref_xtal", PLL2CTRL0, 23, 50000000);
-	clks[ref_cpu] = mxs_clk_ref("ref_cpu", "pll0", FRAC0, 0);
-	clks[ref_emi] = mxs_clk_ref("ref_emi", "pll0", FRAC0, 1);
-	clks[ref_io1] = mxs_clk_ref("ref_io1", "pll0", FRAC0, 2);
-	clks[ref_io0] = mxs_clk_ref("ref_io0", "pll0", FRAC0, 3);
-	clks[ref_pix] = mxs_clk_ref("ref_pix", "pll0", FRAC1, 0);
-	clks[ref_hsadc] = mxs_clk_ref("ref_hsadc", "pll0", FRAC1, 1);
-	clks[ref_gpmi] = mxs_clk_ref("ref_gpmi", "pll0", FRAC1, 2);
+	clks[ref_cpu] = mxs_clk_ref("ref_cpu", "pll0", FRAC0, 0, 18);
+	clks[ref_emi] = mxs_clk_ref("ref_emi", "pll0", FRAC0, 1, 18);
+	clks[ref_io1] = mxs_clk_ref("ref_io1", "pll0", FRAC0, 2, 30);
+	clks[ref_io0] = mxs_clk_ref("ref_io0", "pll0", FRAC0, 3, 30);
+	clks[ref_pix] = mxs_clk_ref("ref_pix", "pll0", FRAC1, 0, 18);
+	clks[ref_hsadc] = mxs_clk_ref("ref_hsadc", "pll0", FRAC1, 1, 18);
+	clks[ref_gpmi] = mxs_clk_ref("ref_gpmi", "pll0", FRAC1, 2, 18);
 	clks[saif0_sel] = mxs_clk_mux("saif0_sel", CLKSEQ, 0, 1, sel_pll0, ARRAY_SIZE(sel_pll0));
 	clks[saif1_sel] = mxs_clk_mux("saif1_sel", CLKSEQ, 1, 1, sel_pll0, ARRAY_SIZE(sel_pll0));
 	clks[gpmi_sel] = mxs_clk_mux("gpmi_sel", CLKSEQ, 2, 1, sel_gpmi, ARRAY_SIZE(sel_gpmi));
diff --git a/drivers/clk/mxs/clk-ref.c b/drivers/clk/mxs/clk-ref.c
index 495f99b7965e..9385563b3ea8 100644
--- a/drivers/clk/mxs/clk-ref.c
+++ b/drivers/clk/mxs/clk-ref.c
@@ -23,13 +23,17 @@
  *
  * The mxs reference clock sources from pll.  Every 4 reference clocks share
  * one register space, and @idx is used to identify them.  Each reference
- * clock has a gate control and a fractional * divider.  The rate is calculated
+ * clock has a gate control and a fractional divider.  The rate is calculated
  * as pll rate  * (18 / FRAC), where FRAC = 18 ~ 35.
+ *
+ * As some clocks are not reliable at high speed (imx28 io0 and io1), the clock
+ * can be limited to not use FRAC < min_frac.
  */
 struct clk_ref {
 	struct clk_hw hw;
 	void __iomem *reg;
 	u8 idx;
+	u8 min_frac;
 };
 
 #define to_clk_ref(_hw) container_of(_hw, struct clk_ref, hw)
@@ -66,6 +70,7 @@ static unsigned long clk_ref_recalc_rate(struct clk_hw *hw,
 static long clk_ref_round_rate(struct clk_hw *hw, unsigned long rate,
 			       unsigned long *prate)
 {
+	struct clk_ref *ref = to_clk_ref(hw);
 	unsigned long parent_rate = *prate;
 	u64 tmp = parent_rate;
 	u8 frac;
@@ -74,8 +79,8 @@ static long clk_ref_round_rate(struct clk_hw *hw, unsigned long rate,
 	do_div(tmp, rate);
 	frac = tmp;
 
-	if (frac < 18)
-		frac = 18;
+	if (frac < ref->min_frac)
+		frac = ref->min_frac;
 	else if (frac > 35)
 		frac = 35;
 
@@ -99,8 +104,8 @@ static int clk_ref_set_rate(struct clk_hw *hw, unsigned long rate,
 	do_div(tmp, rate);
 	frac = tmp;
 
-	if (frac < 18)
-		frac = 18;
+	if (frac < ref->min_frac)
+		frac = ref->min_frac;
 	else if (frac > 35)
 		frac = 35;
 
@@ -125,7 +130,7 @@ static const struct clk_ops clk_ref_ops = {
 };
 
 struct clk *mxs_clk_ref(const char *name, const char *parent_name,
-			void __iomem *reg, u8 idx)
+			void __iomem *reg, u8 idx, u8 min_frac)
 {
 	struct clk_ref *ref;
 	struct clk *clk;
@@ -143,6 +148,7 @@ struct clk *mxs_clk_ref(const char *name, const char *parent_name,
 
 	ref->reg = reg;
 	ref->idx = idx;
+	ref->min_frac = min_frac;
 	ref->hw.init = &init;
 
 	clk = clk_register(NULL, &ref->hw);
diff --git a/drivers/clk/mxs/clk.h b/drivers/clk/mxs/clk.h
index 5a264a486ad9..fb63462a78cd 100644
--- a/drivers/clk/mxs/clk.h
+++ b/drivers/clk/mxs/clk.h
@@ -28,7 +28,7 @@ struct clk *mxs_clk_pll(const char *name, const char *parent_name,
 			void __iomem *base, u8 power, unsigned long rate);
 
 struct clk *mxs_clk_ref(const char *name, const char *parent_name,
-			void __iomem *reg, u8 idx);
+			void __iomem *reg, u8 idx, u8 min_frac);
 
 struct clk *mxs_clk_div(const char *name, const char *parent_name,
 			void __iomem *reg, u8 shift, u8 width, u8 busy);
