#include <linux/err.h>
 
 #include <linux/clk.h>
+#include <linux/clk/sunxi-ng.h>
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
        /* Does DATA0 needs to be masked while the clock is updated */
        bool mask_data0;
 
+       /* hardware only supports new timing mode */
        bool needs_new_timings;
+
+       /* hardware can switch between old and new timing modes */
+       bool has_timings_switch;
 };
 
 struct sunxi_mmc_host {
 
        /* vqmmc */
        bool            vqmmc_enabled;
+
+       /* timings */
+       bool            use_new_timings;
 };
 
 static int sunxi_mmc_reset_host(struct sunxi_mmc_host *host)
 {
        int index;
 
-       if (!host->cfg->clk_delays)
+       if (host->use_new_timings)
                return 0;
 
        /* determine delays */
            ios->bus_width == MMC_BUS_WIDTH_8)
                clock <<= 1;
 
+       if (host->use_new_timings) {
+               ret = sunxi_ccu_set_mmc_timing_mode(host->clk_mmc, true);
+               if (ret) {
+                       dev_err(mmc_dev(mmc),
+                               "error setting new timing mode\n");
+                       return ret;
+               }
+       }
+
        rate = clk_round_rate(host->clk_mmc, clock);
        if (rate < 0) {
                dev_err(mmc_dev(mmc), "error rounding clk to %d: %ld\n",
        }
        mmc_writel(host, REG_CLKCR, rval);
 
-       if (host->cfg->needs_new_timings) {
+       if (host->use_new_timings) {
                /* Don't touch the delay bits */
                rval = mmc_readl(host, REG_SD_NTSR);
                rval |= SDXC_2X_TIMING_MODE;
                goto error_free_host;
        }
 
+       if (host->cfg->has_timings_switch) {
+               /*
+                * Supports both old and new timing modes.
+                * Try setting the clk to new timing mode.
+                */
+               sunxi_ccu_set_mmc_timing_mode(host->clk_mmc, true);
+
+               /* And check the result */
+               ret = sunxi_ccu_get_mmc_timing_mode(host->clk_mmc);
+               if (ret < 0) {
+                       /*
+                        * For whatever reason we were not able to get
+                        * the current active mode. Default to old mode.
+                        */
+                       dev_warn(&pdev->dev, "MMC clk timing mode unknown\n");
+                       host->use_new_timings = false;
+               } else {
+                       host->use_new_timings = !!ret;
+               }
+       } else if (host->cfg->needs_new_timings) {
+               /* Supports new timing mode only */
+               host->use_new_timings = true;
+       }
+
        mmc->ops                = &sunxi_mmc_ops;
        mmc->max_blk_count      = 8192;
        mmc->max_blk_size       = 4096;