#define SDHCI_USE_LEDS_CLASS
 #endif
 
+#define MAX_TUNING_LOOP 40
+
 static unsigned int debug_quirks = 0;
 
 static void sdhci_finish_data(struct sdhci_host *);
                flags |= SDHCI_CMD_CRC;
        if (cmd->flags & MMC_RSP_OPCODE)
                flags |= SDHCI_CMD_INDEX;
-       if (cmd->data)
+
+       /* CMD19 is special in that the Data Present Select should be set */
+       if (cmd->data || (cmd->opcode == MMC_SEND_TUNING_BLOCK))
                flags |= SDHCI_CMD_DATA;
 
        sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
                return 0;
 }
 
+static int sdhci_execute_tuning(struct mmc_host *mmc)
+{
+       struct sdhci_host *host;
+       u16 ctrl;
+       u32 ier;
+       int tuning_loop_counter = MAX_TUNING_LOOP;
+       unsigned long timeout;
+       int err = 0;
+
+       host = mmc_priv(mmc);
+
+       disable_irq(host->irq);
+       spin_lock(&host->lock);
+
+       ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+
+       /*
+        * Host Controller needs tuning only in case of SDR104 mode
+        * and for SDR50 mode when Use Tuning for SDR50 is set in
+        * Capabilities register.
+        */
+       if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) ||
+           (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) &&
+           (host->flags & SDHCI_SDR50_NEEDS_TUNING)))
+               ctrl |= SDHCI_CTRL_EXEC_TUNING;
+       else {
+               spin_unlock(&host->lock);
+               enable_irq(host->irq);
+               return 0;
+       }
+
+       sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+
+       /*
+        * As per the Host Controller spec v3.00, tuning command
+        * generates Buffer Read Ready interrupt, so enable that.
+        *
+        * Note: The spec clearly says that when tuning sequence
+        * is being performed, the controller does not generate
+        * interrupts other than Buffer Read Ready interrupt. But
+        * to make sure we don't hit a controller bug, we _only_
+        * enable Buffer Read Ready interrupt here.
+        */
+       ier = sdhci_readl(host, SDHCI_INT_ENABLE);
+       sdhci_clear_set_irqs(host, ier, SDHCI_INT_DATA_AVAIL);
+
+       /*
+        * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number
+        * of loops reaches 40 times or a timeout of 150ms occurs.
+        */
+       timeout = 150;
+       do {
+               struct mmc_command cmd = {0};
+               struct mmc_request mrq = {0};
+
+               if (!tuning_loop_counter && !timeout)
+                       break;
+
+               cmd.opcode = MMC_SEND_TUNING_BLOCK;
+               cmd.arg = 0;
+               cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+               cmd.retries = 0;
+               cmd.data = NULL;
+               cmd.error = 0;
+
+               mrq.cmd = &cmd;
+               host->mrq = &mrq;
+
+               /*
+                * In response to CMD19, the card sends 64 bytes of tuning
+                * block to the Host Controller. So we set the block size
+                * to 64 here.
+                */
+               sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), SDHCI_BLOCK_SIZE);
+
+               /*
+                * The tuning block is sent by the card to the host controller.
+                * So we set the TRNS_READ bit in the Transfer Mode register.
+                * This also takes care of setting DMA Enable and Multi Block
+                * Select in the same register to 0.
+                */
+               sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
+
+               sdhci_send_command(host, &cmd);
+
+               host->cmd = NULL;
+               host->mrq = NULL;
+
+               spin_unlock(&host->lock);
+               enable_irq(host->irq);
+
+               /* Wait for Buffer Read Ready interrupt */
+               wait_event_interruptible_timeout(host->buf_ready_int,
+                                       (host->tuning_done == 1),
+                                       msecs_to_jiffies(50));
+               disable_irq(host->irq);
+               spin_lock(&host->lock);
+
+               if (!host->tuning_done) {
+                       printk(KERN_INFO DRIVER_NAME ": Timeout waiting for "
+                               "Buffer Read Ready interrupt during tuning "
+                               "procedure, falling back to fixed sampling "
+                               "clock\n");
+                       ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+                       ctrl &= ~SDHCI_CTRL_TUNED_CLK;
+                       ctrl &= ~SDHCI_CTRL_EXEC_TUNING;
+                       sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+
+                       err = -EIO;
+                       goto out;
+               }
+
+               host->tuning_done = 0;
+
+               ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+               tuning_loop_counter--;
+               timeout--;
+               mdelay(1);
+       } while (ctrl & SDHCI_CTRL_EXEC_TUNING);
+
+       /*
+        * The Host Driver has exhausted the maximum number of loops allowed,
+        * so use fixed sampling frequency.
+        */
+       if (!tuning_loop_counter || !timeout) {
+               ctrl &= ~SDHCI_CTRL_TUNED_CLK;
+               sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+       } else {
+               if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
+                       printk(KERN_INFO DRIVER_NAME ": Tuning procedure"
+                               " failed, falling back to fixed sampling"
+                               " clock\n");
+                       err = -EIO;
+               }
+       }
+
+out:
+       sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier);
+       spin_unlock(&host->lock);
+       enable_irq(host->irq);
+
+       return err;
+}
+
 static const struct mmc_host_ops sdhci_ops = {
        .request        = sdhci_request,
        .set_ios        = sdhci_set_ios,
        .get_ro         = sdhci_get_ro,
        .enable_sdio_irq = sdhci_enable_sdio_irq,
        .start_signal_voltage_switch    = sdhci_start_signal_voltage_switch,
+       .execute_tuning                 = sdhci_execute_tuning,
 };
 
 /*****************************************************************************\
 {
        BUG_ON(intmask == 0);
 
+       /* CMD19 generates _only_ Buffer Read Ready interrupt */
+       if (intmask & SDHCI_INT_DATA_AVAIL) {
+               if (SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) ==
+                   MMC_SEND_TUNING_BLOCK) {
+                       host->tuning_done = 1;
+                       wake_up(&host->buf_ready_int);
+                       return;
+               }
+       }
+
        if (!host->data) {
                /*
                 * The "data complete" interrupt is also used to
        if (caps[1] & SDHCI_SUPPORT_DDR50)
                mmc->caps |= MMC_CAP_UHS_DDR50;
 
+       /* Does the host needs tuning for SDR50? */
+       if (caps[1] & SDHCI_USE_SDR50_TUNING)
+               host->flags |= SDHCI_SDR50_NEEDS_TUNING;
+
        /* Driver Type(s) (A, C, D) supported by the host */
        if (caps[1] & SDHCI_DRIVER_TYPE_A)
                mmc->caps |= MMC_CAP_DRIVER_TYPE_A;
 
        setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host);
 
+       if (host->version >= SDHCI_SPEC_300)
+               init_waitqueue_head(&host->buf_ready_int);
+
        ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
                mmc_hostname(mmc), host);
        if (ret)