struct omap2_mcspi_dma  *dma_channels;
        struct device           *dev;
        struct omap2_mcspi_regs ctx;
+       struct clk              *ref_clk;
        int                     fifo_depth;
        bool                    target_aborted;
        unsigned int            pin_dir:1;
        size_t                  max_xfer_len;
+       u32                     ref_clk_hz;
 };
 
 struct omap2_mcspi_cs {
        return count - c;
 }
 
-static u32 omap2_mcspi_calc_divisor(u32 speed_hz)
+static u32 omap2_mcspi_calc_divisor(u32 speed_hz, u32 ref_clk_hz)
 {
        u32 div;
 
        for (div = 0; div < 15; div++)
-               if (speed_hz >= (OMAP2_MCSPI_MAX_FREQ >> div))
+               if (speed_hz >= (ref_clk_hz >> div))
                        return div;
 
        return 15;
 {
        struct omap2_mcspi_cs *cs = spi->controller_state;
        struct omap2_mcspi *mcspi;
-       u32 l = 0, clkd = 0, div, extclk = 0, clkg = 0;
+       u32 ref_clk_hz, l = 0, clkd = 0, div, extclk = 0, clkg = 0;
        u8 word_len = spi->bits_per_word;
        u32 speed_hz = spi->max_speed_hz;
 
        if (t && t->speed_hz)
                speed_hz = t->speed_hz;
 
-       speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ);
-       if (speed_hz < (OMAP2_MCSPI_MAX_FREQ / OMAP2_MCSPI_MAX_DIVIDER)) {
-               clkd = omap2_mcspi_calc_divisor(speed_hz);
-               speed_hz = OMAP2_MCSPI_MAX_FREQ >> clkd;
+       ref_clk_hz = mcspi->ref_clk_hz;
+       speed_hz = min_t(u32, speed_hz, ref_clk_hz);
+       if (speed_hz < (ref_clk_hz / OMAP2_MCSPI_MAX_DIVIDER)) {
+               clkd = omap2_mcspi_calc_divisor(speed_hz, ref_clk_hz);
+               speed_hz = ref_clk_hz >> clkd;
                clkg = 0;
        } else {
-               div = (OMAP2_MCSPI_MAX_FREQ + speed_hz - 1) / speed_hz;
-               speed_hz = OMAP2_MCSPI_MAX_FREQ / div;
+               div = (ref_clk_hz + speed_hz - 1) / speed_hz;
+               speed_hz = ref_clk_hz / div;
                clkd = (div - 1) & 0xf;
                extclk = (div - 1) >> 4;
                clkg = OMAP2_MCSPI_CHCONF_CLKG;
        ctlr->cleanup = omap2_mcspi_cleanup;
        ctlr->target_abort = omap2_mcspi_target_abort;
        ctlr->dev.of_node = node;
-       ctlr->max_speed_hz = OMAP2_MCSPI_MAX_FREQ;
-       ctlr->min_speed_hz = OMAP2_MCSPI_MAX_FREQ >> 15;
        ctlr->use_gpio_descriptors = true;
 
        platform_set_drvdata(pdev, ctlr);
                goto free_ctlr;
        }
 
+       mcspi->ref_clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);
+       if (mcspi->ref_clk)
+               mcspi->ref_clk_hz = clk_get_rate(mcspi->ref_clk);
+       else
+               mcspi->ref_clk_hz = OMAP2_MCSPI_MAX_FREQ;
+       ctlr->max_speed_hz = mcspi->ref_clk_hz;
+       ctlr->min_speed_hz = mcspi->ref_clk_hz >> 15;
+
        pm_runtime_use_autosuspend(&pdev->dev);
        pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
        pm_runtime_enable(&pdev->dev);