#endif
 
+void mmc_retune_enable(struct mmc_host *host)
+{
+       host->can_retune = 1;
+       if (host->retune_period)
+               mod_timer(&host->retune_timer,
+                         jiffies + host->retune_period * HZ);
+}
+
+void mmc_retune_disable(struct mmc_host *host)
+{
+       host->can_retune = 0;
+       del_timer_sync(&host->retune_timer);
+       host->retune_now = 0;
+       host->need_retune = 0;
+}
+
+void mmc_retune_timer_stop(struct mmc_host *host)
+{
+       del_timer_sync(&host->retune_timer);
+}
+EXPORT_SYMBOL(mmc_retune_timer_stop);
+
+void mmc_retune_hold(struct mmc_host *host)
+{
+       if (!host->hold_retune)
+               host->retune_now = 1;
+       host->hold_retune += 1;
+}
+
+void mmc_retune_release(struct mmc_host *host)
+{
+       if (host->hold_retune)
+               host->hold_retune -= 1;
+       else
+               WARN_ON(1);
+}
+
+int mmc_retune(struct mmc_host *host)
+{
+       int err;
+
+       if (host->retune_now)
+               host->retune_now = 0;
+       else
+               return 0;
+
+       if (!host->need_retune || host->doing_retune || !host->card)
+               return 0;
+
+       host->need_retune = 0;
+
+       host->doing_retune = 1;
+
+       err = mmc_execute_tuning(host->card);
+
+       host->doing_retune = 0;
+
+       return err;
+}
+
+static void mmc_retune_timer(unsigned long data)
+{
+       struct mmc_host *host = (struct mmc_host *)data;
+
+       mmc_retune_needed(host);
+}
+
 /**
  *     mmc_of_parse() - parse host's device-tree node
  *     @host: host whose node should be parsed.
 #ifdef CONFIG_PM
        host->pm_notify.notifier_call = mmc_pm_notify;
 #endif
+       setup_timer(&host->retune_timer, mmc_retune_timer, (unsigned long)host);
 
        /*
         * By default, hosts do not support SGIO or large requests.
 
 int mmc_register_host_class(void);
 void mmc_unregister_host_class(void);
 
+void mmc_retune_enable(struct mmc_host *host);
+void mmc_retune_disable(struct mmc_host *host);
+void mmc_retune_hold(struct mmc_host *host);
+void mmc_retune_release(struct mmc_host *host);
+int mmc_retune(struct mmc_host *host);
+
 #endif
 
 
 
 #include <linux/leds.h>
 #include <linux/mutex.h>
+#include <linux/timer.h>
 #include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/fault-inject.h>
 #ifdef CONFIG_MMC_DEBUG
        unsigned int            removed:1;      /* host is being removed */
 #endif
+       unsigned int            can_retune:1;   /* re-tuning can be used */
+       unsigned int            doing_retune:1; /* re-tuning in progress */
+       unsigned int            retune_now:1;   /* do re-tuning at next req */
 
        int                     rescan_disable; /* disable card detection */
        int                     rescan_entered; /* used with nonremovable devices */
 
+       int                     need_retune;    /* re-tuning is needed */
+       int                     hold_retune;    /* hold off re-tuning */
+       unsigned int            retune_period;  /* re-tuning period in secs */
+       struct timer_list       retune_timer;   /* for periodic re-tuning */
+
        bool                    trigger_card_event; /* card_event necessary */
 
        struct mmc_card         *card;          /* device attached to this host */
        return card->host->ios.timing == MMC_TIMING_MMC_HS400;
 }
 
+void mmc_retune_timer_stop(struct mmc_host *host);
+
+static inline void mmc_retune_needed(struct mmc_host *host)
+{
+       if (host->can_retune)
+               host->need_retune = 1;
+}
+
+static inline void mmc_retune_recheck(struct mmc_host *host)
+{
+       if (host->hold_retune <= 1)
+               host->retune_now = 1;
+}
+
 #endif /* LINUX_MMC_HOST_H */