#include <linux/bitfield.h>
 #include <linux/bits.h>
+#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
        struct regulator *vdd1;
        struct regulator *vdd2;
        struct regulator *vdd3;
+       struct clk *refclk;
+       unsigned long refclk_rate;
        bool interface_i2c;
 };
 
         * It seems the PLL input clock after applying P pre-divider have
         * to be lower than 20 MHz.
         */
-       fin = icn->dsi->hs_rate / 4; /* in Hz */
+       if (icn->refclk)
+               fin = icn->refclk_rate;
+       else
+               fin = icn->dsi->hs_rate / 4; /* in Hz */
 
        /* Minimum value of P predivider for PLL input in 5..20 MHz */
        p_min = clamp(DIV_ROUND_UP(fin, 20000000), 1U, 31U);
        best_p_pot = !(best_p & 1);
 
        dev_dbg(icn->dev,
-               "PLL: P[3:0]=%d P[4]=2*%d M=%d S[7:5]=2^%d delta=%d => DSI f_in=%d Hz ; DPI f_out=%d Hz\n",
+               "PLL: P[3:0]=%d P[4]=2*%d M=%d S[7:5]=2^%d delta=%d => DSI f_in(%s)=%d Hz ; DPI f_out=%d Hz\n",
                best_p >> best_p_pot, best_p_pot, best_m, best_s + 1,
-               min_delta, fin, (fin * best_m) / (best_p << (best_s + 1)));
+               min_delta, icn->refclk ? "EXT" : "DSI", fin,
+               (fin * best_m) / (best_p << (best_s + 1)));
 
        ref_div = PLL_REF_DIV_P(best_p >> best_p_pot) | PLL_REF_DIV_S(best_s);
        if (best_p_pot) /* Prefer /2 pre-divider */
                ref_div |= PLL_REF_DIV_Pe;
 
-       /* Clock source selection fixed to MIPI DSI clock lane */
-       chipone_writeb(icn, PLL_CTRL(6), PLL_CTRL_6_MIPI_CLK);
+       /* Clock source selection either external clock or MIPI DSI clock lane */
+       chipone_writeb(icn, PLL_CTRL(6),
+                      icn->refclk ? PLL_CTRL_6_EXTERNAL : PLL_CTRL_6_MIPI_CLK);
        chipone_writeb(icn, PLL_REF_DIV, ref_div);
        chipone_writeb(icn, PLL_INT(0), best_m);
 }
                                      "failed to enable VDD3 regulator: %d\n", ret);
        }
 
+       ret = clk_prepare_enable(icn->refclk);
+       if (ret)
+               DRM_DEV_ERROR(icn->dev,
+                             "failed to enable RECLK clock: %d\n", ret);
+
        gpiod_set_value(icn->enable_gpio, 1);
 
        usleep_range(10000, 11000);
 {
        struct chipone *icn = bridge_to_chipone(bridge);
 
+       clk_disable_unprepare(icn->refclk);
+
        if (icn->vdd1)
                regulator_disable(icn->vdd1);
 
        struct device *dev = icn->dev;
        int ret;
 
+       icn->refclk = devm_clk_get_optional(dev, "refclk");
+       if (IS_ERR(icn->refclk)) {
+               ret = PTR_ERR(icn->refclk);
+               DRM_DEV_ERROR(dev, "failed to get REFCLK clock: %d\n", ret);
+               return ret;
+       } else if (icn->refclk) {
+               icn->refclk_rate = clk_get_rate(icn->refclk);
+               if (icn->refclk_rate < 10000000 || icn->refclk_rate > 154000000) {
+                       DRM_DEV_ERROR(dev, "REFCLK out of range: %ld Hz\n",
+                                     icn->refclk_rate);
+                       return -EINVAL;
+               }
+       }
+
        icn->vdd1 = devm_regulator_get_optional(dev, "vdd1");
        if (IS_ERR(icn->vdd1)) {
                ret = PTR_ERR(icn->vdd1);