+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);
+}
+