diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c
index b12abf9..7af6cec 100644
--- a/drivers/mmc/host/sdhci-of-arasan.c
+++ b/drivers/mmc/host/sdhci-of-arasan.c
@@ -22,6 +22,7 @@
 #include <linux/phy/phy.h>
 #include <linux/regmap.h>
 #include <linux/of.h>
+#include <linux/firmware/xlnx-zynqmp.h>
 
 #include "cqhci.h"
 #include "sdhci-pltfm.h"
@@ -32,6 +33,10 @@
 
 #define PHY_CLK_TOO_SLOW_HZ		400000
 
+/* Default settings for ZynqMP Tap Delays */
+#define ZYNQMP_ITAP_DELAYS {0, 0x15, 0x15, 0, 0x15, 0, 0, 0x3D, 0x12, 0, 0}
+#define ZYNQMP_OTAP_DELAYS {0, 0x5, 0x6, 0, 0x5, 0x3, 0x3, 0x4, 0x6, 0x3, 0}
+
 /*
  * On some SoCs the syscon area has a feature where the upper 16-bits of
  * each 32-bit register act as a write mask for the lower 16-bits.  This allows
@@ -81,6 +86,7 @@ struct sdhci_arasan_soc_ctl_map {
  * @sdcardclk:		Pointer to normal 'struct clock' for sdcardclk_hw.
  * @soc_ctl_base:	Pointer to regmap for syscon for soc_ctl registers.
  * @soc_ctl_map:	Map to get offsets into soc_ctl registers.
+ * @of_data:		Platform specific runtime data storage pointer
  */
 struct sdhci_arasan_data {
 	struct sdhci_host *host;
@@ -101,6 +107,15 @@ struct sdhci_arasan_data {
 /* Controller immediately reports SDHCI_CLOCK_INT_STABLE after enabling the
  * internal clock even when the clock isn't stable */
 #define SDHCI_ARASAN_QUIRK_CLOCK_UNSTABLE BIT(1)
+
+	void *of_data;
+};
+
+struct sdhci_arasan_zynqmp_data {
+	void (*set_tap_delay)(struct sdhci_host *host);
+	const struct zynqmp_eemi_ops *eemi_ops;
+	u8 tapdly[MMC_TIMING_MMC_HS400 + 1][2]; /* [0] for input delay, */
+						/* [1] for output delay */
 };
 
 struct sdhci_arasan_of_data {
@@ -209,6 +224,16 @@ static void sdhci_arasan_set_clock(struct sdhci_host *host, unsigned int clock)
 		sdhci_arasan->is_phy_on = false;
 	}
 
+	/* Set the Input and Output Tap Delays */
+	if (host->version >= SDHCI_SPEC_300 &&
+	    host->timing != MMC_TIMING_LEGACY &&
+	    host->timing != MMC_TIMING_UHS_SDR12) {
+		struct sdhci_arasan_zynqmp_data *zynqmp_data =
+			sdhci_arasan->of_data;
+		if (zynqmp_data && zynqmp_data->set_tap_delay)
+			zynqmp_data->set_tap_delay(host);
+	}
+
 	sdhci_set_clock(host, clock);
 
 	if (sdhci_arasan->quirks & SDHCI_ARASAN_QUIRK_CLOCK_UNSTABLE)
@@ -487,6 +512,10 @@ static const struct of_device_id sdhci_arasan_of_match[] = {
 		.compatible = "arasan,sdhci-4.9a",
 		.data = &sdhci_arasan_data,
 	},
+	{
+		.compatible = "xlnx,zynqmp-8.9a",
+		.data = &sdhci_arasan_data,
+	},
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sdhci_arasan_of_match);
@@ -517,6 +546,37 @@ static const struct clk_ops arasan_sdcardclk_ops = {
 };
 
 /**
+ * sdhci_zynqmp_sdcardclk_set_phase - Set the SD Clock Tap Delays
+ *
+ * Set the SD Clock Tap Delays for Input and Output paths
+ *
+ * @hw:			Pointer to the hardware clock structure.
+ * @degrees		The clock phase shift between 0 - 359.
+ * Return: 0 on success and error value on error
+ */
+static int sdhci_zynqmp_sdcardclk_set_phase(struct clk_hw *hw, int degrees)
+
+{
+	struct sdhci_arasan_data *sdhci_arasan =
+		container_of(hw, struct sdhci_arasan_data, sdcardclk_hw);
+	struct sdhci_arasan_zynqmp_data *zynqmp_data = sdhci_arasan->of_data;
+	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_data->eemi_ops;
+	const char *clk_name = clk_hw_get_name(hw);
+	u32 device_id = !strcmp(clk_name, "clk_sd0") ? 0 : 1;
+
+	if (!eemi_ops->sdio_setphase)
+		return -ENODEV;
+
+	/* Set the Clock Phase */
+	return eemi_ops->sdio_setphase(device_id, degrees);
+}
+
+static const struct clk_ops zynqmp_sdcardclk_ops = {
+	.recalc_rate = sdhci_arasan_sdcardclk_recalc_rate,
+	.set_phase = sdhci_zynqmp_sdcardclk_set_phase,
+};
+
+/**
  * sdhci_arasan_update_clockmultiplier - Set corecfg_clockmultiplier
  *
  * The corecfg_clockmultiplier is supposed to contain clock multiplier
@@ -638,7 +698,10 @@ static int sdhci_arasan_register_sdclk(struct sdhci_arasan_data *sdhci_arasan,
 	sdcardclk_init.parent_names = &parent_clk_name;
 	sdcardclk_init.num_parents = 1;
 	sdcardclk_init.flags = CLK_GET_RATE_NOCACHE;
-	sdcardclk_init.ops = &arasan_sdcardclk_ops;
+	if (of_device_is_compatible(np, "xlnx,zynqmp-8.9a"))
+		sdcardclk_init.ops = &zynqmp_sdcardclk_ops;
+	else
+		sdcardclk_init.ops = &arasan_sdcardclk_ops;
 
 	sdhci_arasan->sdcardclk_hw.init = &sdcardclk_init;
 	sdhci_arasan->sdcardclk =
@@ -714,6 +777,108 @@ static int sdhci_arasan_add_host(struct sdhci_arasan_data *sdhci_arasan)
 	return ret;
 }
 
+static void sdhci_arasan_zynqmp_set_tap_delay(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
+	struct sdhci_arasan_zynqmp_data *zynqmp_data = sdhci_arasan->of_data;
+
+	clk_set_phase(sdhci_arasan->sdcardclk,
+		      (int)zynqmp_data->tapdly[host->timing][0]);
+	clk_set_phase(sdhci_arasan->sdcardclk,
+		      (int)zynqmp_data->tapdly[host->timing][1] +
+		      INPUT_TAP_BOUNDARY);
+}
+
+static void arasan_dt_read_tap_delay(struct device *dev, u8 *tapdly,
+				     const char *prop, u8 itap_def, u8 otap_def)
+{
+	struct device_node *np = dev->of_node;
+
+	tapdly[0] = itap_def;
+	tapdly[1] = otap_def;
+
+	/*
+	 * Read Tap Delay values from DT, if the DT does not contain the
+	 * Tap Values then use the pre-defined values.
+	 */
+	if (of_property_read_variable_u8_array(np, prop, &tapdly[0], 2, 0)) {
+		dev_dbg(dev, "Using predefined tapdly for %s = %d %d\n",
+			prop, tapdly[0], tapdly[1]);
+	}
+}
+
+/**
+ * arasan_dt_parse_tap_delays - Read Tap Delay values from DT
+ *
+ * Called at initialization to parse the values of Tap Delays.
+ *
+ * @dev:		Pointer to our struct device.
+ */
+static int arasan_dt_parse_tap_delays(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct sdhci_host *host = platform_get_drvdata(pdev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
+	struct sdhci_arasan_zynqmp_data zynqmp_data;
+	const struct zynqmp_eemi_ops *eemi_ops;
+	u8 *itapdly, *otapdly;
+	u32 mio_bank = 0;
+
+	eemi_ops = zynqmp_pm_get_eemi_ops();
+	if (IS_ERR(eemi_ops))
+		return PTR_ERR(eemi_ops);
+
+	itapdly = (u8 [MMC_TIMING_MMC_HS400 + 1]) ZYNQMP_ITAP_DELAYS;
+	otapdly = (u8 [MMC_TIMING_MMC_HS400 + 1]) ZYNQMP_OTAP_DELAYS;
+
+	of_property_read_u32(pdev->dev.of_node, "xlnx,mio-bank", &mio_bank);
+	if (mio_bank == 2) {
+		otapdly[MMC_TIMING_UHS_SDR104] = 0x2;
+		otapdly[MMC_TIMING_MMC_HS200] = 0x2;
+	}
+
+	arasan_dt_read_tap_delay(dev, zynqmp_data.tapdly[MMC_TIMING_MMC_HS],
+				 "xlnx,tap-delay-mmc-hsd",
+				 itapdly[MMC_TIMING_MMC_HS],
+				 otapdly[MMC_TIMING_MMC_HS]);
+	arasan_dt_read_tap_delay(dev, zynqmp_data.tapdly[MMC_TIMING_SD_HS],
+				 "xlnx,tap-delay-sd-hsd",
+				 itapdly[MMC_TIMING_SD_HS],
+				 otapdly[MMC_TIMING_SD_HS]);
+	arasan_dt_read_tap_delay(dev, zynqmp_data.tapdly[MMC_TIMING_UHS_SDR25],
+				 "xlnx,tap-delay-sdr25",
+				 itapdly[MMC_TIMING_UHS_SDR25],
+				 otapdly[MMC_TIMING_UHS_SDR25]);
+	arasan_dt_read_tap_delay(dev, zynqmp_data.tapdly[MMC_TIMING_UHS_SDR50],
+				 "xlnx,tap-delay-sdr50",
+				 itapdly[MMC_TIMING_UHS_SDR50],
+				 otapdly[MMC_TIMING_UHS_SDR50]);
+	arasan_dt_read_tap_delay(dev, zynqmp_data.tapdly[MMC_TIMING_UHS_SDR104],
+				 "xlnx,tap-delay-sdr104",
+				 itapdly[MMC_TIMING_UHS_SDR104],
+				 otapdly[MMC_TIMING_UHS_SDR104]);
+	arasan_dt_read_tap_delay(dev, zynqmp_data.tapdly[MMC_TIMING_UHS_DDR50],
+				 "xlnx,tap-delay-sd-ddr50",
+				 itapdly[MMC_TIMING_UHS_DDR50],
+				 otapdly[MMC_TIMING_UHS_DDR50]);
+	arasan_dt_read_tap_delay(dev, zynqmp_data.tapdly[MMC_TIMING_MMC_DDR52],
+				 "xlnx,tap-delay-mmc-ddr52",
+				 itapdly[MMC_TIMING_MMC_DDR52],
+				 otapdly[MMC_TIMING_MMC_DDR52]);
+	arasan_dt_read_tap_delay(dev, zynqmp_data.tapdly[MMC_TIMING_MMC_HS200],
+				 "xlnx,tap-delay-mmc-hs200",
+				 itapdly[MMC_TIMING_MMC_HS200],
+				 otapdly[MMC_TIMING_MMC_HS200]);
+
+	zynqmp_data.set_tap_delay = sdhci_arasan_zynqmp_set_tap_delay;
+	zynqmp_data.eemi_ops = eemi_ops;
+	sdhci_arasan->of_data = &zynqmp_data;
+
+	return 0;
+}
+
 static int sdhci_arasan_probe(struct platform_device *pdev)
 {
 	int ret;
@@ -806,6 +971,12 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
 		goto unreg_clk;
 	}
 
+	if (of_device_is_compatible(pdev->dev.of_node, "xlnx,zynqmp-8.9a")) {
+		ret = arasan_dt_parse_tap_delays(&pdev->dev);
+		if (ret)
+			goto unreg_clk;
+	}
+
 	sdhci_arasan->phy = ERR_PTR(-ENODEV);
 	if (of_device_is_compatible(pdev->dev.of_node,
 				    "arasan,sdhci-5.1")) {
