};
 #endif /* CONFIG_MMC_DW_IDMAC */
 
-/**
- * struct dw_mci_slot - MMC slot state
- * @mmc: The mmc_host representing this slot.
- * @host: The MMC controller this slot is using.
- * @quirks: Slot-level quirks (DW_MCI_SLOT_QUIRK_XXX)
- * @wp_gpio: If gpio_is_valid() we'll use this to read write protect.
- * @ctype: Card type for this slot.
- * @mrq: mmc_request currently being processed or waiting to be
- *     processed, or NULL when the slot is idle.
- * @queue_node: List node for placing this node in the @queue list of
- *     &struct dw_mci.
- * @clock: Clock rate configured by set_ios(). Protected by host->lock.
- * @__clk_old: The last updated clock with reflecting clock divider.
- *     Keeping track of this helps us to avoid spamming the console
- *     with CONFIG_MMC_CLKGATE.
- * @flags: Random state bits associated with the slot.
- * @id: Number of this slot.
- * @last_detect_state: Most recently observed card detect state.
- */
-struct dw_mci_slot {
-       struct mmc_host         *mmc;
-       struct dw_mci           *host;
-
-       int                     quirks;
-       int                     wp_gpio;
-
-       u32                     ctype;
-
-       struct mmc_request      *mrq;
-       struct list_head        queue_node;
+static const u8 tuning_blk_pattern_4bit[] = {
+       0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
+       0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
+       0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
+       0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
+       0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
+       0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
+       0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
+       0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,
+};
 
-       unsigned int            clock;
-       unsigned int            __clk_old;
-       unsigned long           flags;
-#define DW_MMC_CARD_PRESENT    0
-#define DW_MMC_CARD_NEED_INIT  1
-       int                     id;
-       int                     last_detect_state;
+static const u8 tuning_blk_pattern_8bit[] = {
+       0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
+       0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc,
+       0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff,
+       0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff,
+       0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd,
+       0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb,
+       0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff,
+       0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff,
+       0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
+       0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc,
+       0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff,
+       0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee,
+       0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd,
+       0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff,
+       0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff,
+       0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
 };
 
 #if defined(CONFIG_DEBUG_FS)
        }
 }
 
+static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+       struct dw_mci_slot *slot = mmc_priv(mmc);
+       struct dw_mci *host = slot->host;
+       const struct dw_mci_drv_data *drv_data = host->drv_data;
+       struct dw_mci_tuning_data tuning_data;
+       int err = -ENOSYS;
+
+       if (opcode == MMC_SEND_TUNING_BLOCK_HS200) {
+               if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) {
+                       tuning_data.blk_pattern = tuning_blk_pattern_8bit;
+                       tuning_data.blksz = sizeof(tuning_blk_pattern_8bit);
+               } else if (mmc->ios.bus_width == MMC_BUS_WIDTH_4) {
+                       tuning_data.blk_pattern = tuning_blk_pattern_4bit;
+                       tuning_data.blksz = sizeof(tuning_blk_pattern_4bit);
+               } else {
+                       return -EINVAL;
+               }
+       } else if (opcode == MMC_SEND_TUNING_BLOCK) {
+               tuning_data.blk_pattern = tuning_blk_pattern_4bit;
+               tuning_data.blksz = sizeof(tuning_blk_pattern_4bit);
+       } else {
+               dev_err(host->dev,
+                       "Undefined command(%d) for tuning\n", opcode);
+               return -EINVAL;
+       }
+
+       if (drv_data && drv_data->execute_tuning)
+               err = drv_data->execute_tuning(slot, opcode, &tuning_data);
+       return err;
+}
+
 static const struct mmc_host_ops dw_mci_ops = {
        .request                = dw_mci_request,
        .pre_req                = dw_mci_pre_req,
        .get_ro                 = dw_mci_get_ro,
        .get_cd                 = dw_mci_get_cd,
        .enable_sdio_irq        = dw_mci_enable_sdio_irq,
+       .execute_tuning         = dw_mci_execute_tuning,
 };
 
 static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
 
 extern int dw_mci_resume(struct dw_mci *host);
 #endif
 
+/**
+ * struct dw_mci_slot - MMC slot state
+ * @mmc: The mmc_host representing this slot.
+ * @host: The MMC controller this slot is using.
+ * @quirks: Slot-level quirks (DW_MCI_SLOT_QUIRK_XXX)
+ * @wp_gpio: If gpio_is_valid() we'll use this to read write protect.
+ * @ctype: Card type for this slot.
+ * @mrq: mmc_request currently being processed or waiting to be
+ *     processed, or NULL when the slot is idle.
+ * @queue_node: List node for placing this node in the @queue list of
+ *     &struct dw_mci.
+ * @clock: Clock rate configured by set_ios(). Protected by host->lock.
+ * @__clk_old: The last updated clock with reflecting clock divider.
+ *     Keeping track of this helps us to avoid spamming the console
+ *     with CONFIG_MMC_CLKGATE.
+ * @flags: Random state bits associated with the slot.
+ * @id: Number of this slot.
+ * @last_detect_state: Most recently observed card detect state.
+ */
+struct dw_mci_slot {
+       struct mmc_host         *mmc;
+       struct dw_mci           *host;
+
+       int                     quirks;
+       int                     wp_gpio;
+
+       u32                     ctype;
+
+       struct mmc_request      *mrq;
+       struct list_head        queue_node;
+
+       unsigned int            clock;
+       unsigned int            __clk_old;
+
+       unsigned long           flags;
+#define DW_MMC_CARD_PRESENT    0
+#define DW_MMC_CARD_NEED_INIT  1
+       int                     id;
+       int                     last_detect_state;
+};
+
+struct dw_mci_tuning_data {
+       const u8 *blk_pattern;
+       unsigned int blksz;
+};
+
 /**
  * dw_mci driver data - dw-mshc implementation specific driver data.
  * @caps: mmc subsystem specified capabilities of the controller(s).
        void            (*prepare_command)(struct dw_mci *host, u32 *cmdr);
        void            (*set_ios)(struct dw_mci *host, struct mmc_ios *ios);
        int             (*parse_dt)(struct dw_mci *host);
+       int             (*execute_tuning)(struct dw_mci_slot *slot, u32 opcode,
+                                       struct dw_mci_tuning_data *tuning_data);
 };
 #endif /* _DW_MMC_H_ */