[U-Boot] [UBOOT PATCH v3 6/7] mmc: zynq_sdhci: Add support for SD3.0

Siva Durga Prasad Paladugu siva.durga.paladugu at xilinx.com
Thu Apr 19 07:07:09 UTC 2018


This patch adds support of SD3.0 for ZynqMP.

Signed-off-by: Siva Durga Prasad Paladugu <siva.durga.paladugu at xilinx.com>
---
Changes for v3:
- Used macro for loop counter
- Made printf to debug
- Fixed if condition to reduce a line as
  per comment
---
 board/xilinx/zynqmp/Makefile     |   2 +
 board/xilinx/zynqmp/tap_delays.c | 229 ++++++++++++++++++++++++++++++++++++++
 drivers/mmc/zynq_sdhci.c         | 231 ++++++++++++++++++++++++++++++++++++++-
 include/zynqmp_tap_delay.h       |  20 ++++
 4 files changed, 477 insertions(+), 5 deletions(-)
 create mode 100644 board/xilinx/zynqmp/tap_delays.c
 create mode 100644 include/zynqmp_tap_delay.h

diff --git a/board/xilinx/zynqmp/Makefile b/board/xilinx/zynqmp/Makefile
index 3b7a10e..1d43928 100644
--- a/board/xilinx/zynqmp/Makefile
+++ b/board/xilinx/zynqmp/Makefile
@@ -26,6 +26,8 @@ ifneq ($(call ifdef_any_of, CONFIG_ZYNQMP_PSU_INIT_ENABLED CONFIG_SPL_BUILD),)
 obj-y += $(init-objs)
 endif

+obj-$(CONFIG_MMC_SDHCI_ZYNQ) += tap_delays.o
+
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_CMD_ZYNQMP) += cmds.o
 endif
diff --git a/board/xilinx/zynqmp/tap_delays.c b/board/xilinx/zynqmp/tap_delays.c
new file mode 100644
index 0000000..c3ae357
--- /dev/null
+++ b/board/xilinx/zynqmp/tap_delays.c
@@ -0,0 +1,229 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx ZynqMP SoC Tap Delay Programming
+ *
+ * Copyright (C) 2018 Xilinx, Inc.
+ */
+
+#include <common.h>
+#include <asm/arch/sys_proto.h>
+
+#define SD_DLL_CTRL                    0xFF180358
+#define SD_ITAP_DLY                    0xFF180314
+#define SD_OTAP_DLY                    0xFF180318
+#define SD0_DLL_RST_MASK               0x00000004
+#define SD0_DLL_RST                    0x00000004
+#define SD1_DLL_RST_MASK               0x00040000
+#define SD1_DLL_RST                    0x00040000
+#define SD0_ITAPCHGWIN_MASK            0x00000200
+#define SD0_ITAPCHGWIN                 0x00000200
+#define SD1_ITAPCHGWIN_MASK            0x02000000
+#define SD1_ITAPCHGWIN                 0x02000000
+#define SD0_ITAPDLYENA_MASK            0x00000100
+#define SD0_ITAPDLYENA                 0x00000100
+#define SD1_ITAPDLYENA_MASK            0x01000000
+#define SD1_ITAPDLYENA                 0x01000000
+#define SD0_ITAPDLYSEL_MASK            0x000000FF
+#define SD0_ITAPDLYSEL_HSD             0x00000015
+#define SD0_ITAPDLYSEL_SD_DDR50                0x0000003D
+#define SD0_ITAPDLYSEL_MMC_DDR50       0x00000012
+
+#define SD1_ITAPDLYSEL_MASK            0x00FF0000
+#define SD1_ITAPDLYSEL_HSD             0x00150000
+#define SD1_ITAPDLYSEL_SD_DDR50                0x003D0000
+#define SD1_ITAPDLYSEL_MMC_DDR50       0x00120000
+
+#define SD0_OTAPDLYSEL_MASK            0x0000003F
+#define SD0_OTAPDLYSEL_MMC_HSD         0x00000006
+#define SD0_OTAPDLYSEL_SD_HSD          0x00000005
+#define SD0_OTAPDLYSEL_SDR50           0x00000003
+#define SD0_OTAPDLYSEL_SDR104_B0       0x00000003
+#define SD0_OTAPDLYSEL_SDR104_B2       0x00000002
+#define SD0_OTAPDLYSEL_SD_DDR50                0x00000004
+#define SD0_OTAPDLYSEL_MMC_DDR50       0x00000006
+
+#define SD1_OTAPDLYSEL_MASK            0x003F0000
+#define SD1_OTAPDLYSEL_MMC_HSD         0x00060000
+#define SD1_OTAPDLYSEL_SD_HSD          0x00050000
+#define SD1_OTAPDLYSEL_SDR50           0x00030000
+#define SD1_OTAPDLYSEL_SDR104_B0       0x00030000
+#define SD1_OTAPDLYSEL_SDR104_B2       0x00020000
+#define SD1_OTAPDLYSEL_SD_DDR50                0x00040000
+#define SD1_OTAPDLYSEL_MMC_DDR50       0x00060000
+
+#define MMC_BANK2              0x2
+
+#define MMC_TIMING_UHS_SDR25           1
+#define MMC_TIMING_UHS_SDR50           2
+#define MMC_TIMING_UHS_SDR104          3
+#define MMC_TIMING_UHS_DDR50           4
+#define MMC_TIMING_MMC_HS200           5
+#define MMC_TIMING_SD_HS               6
+#define MMC_TIMING_MMC_DDR52           7
+#define MMC_TIMING_MMC_HS              8
+
+void zynqmp_dll_reset(u8 deviceid)
+{
+       /* Issue DLL Reset */
+       if (deviceid == 0)
+               zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK,
+                                 SD0_DLL_RST);
+       else
+               zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK,
+                                 SD1_DLL_RST);
+
+       mdelay(1);
+
+       /* Release DLL Reset */
+       if (deviceid == 0)
+               zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
+       else
+               zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
+}
+
+static void arasan_zynqmp_tap_sdr104(u8 deviceid, u8 timing, u8 bank)
+{
+       if (deviceid == 0) {
+               /* Program OTAP */
+               if (bank == MMC_BANK2)
+                       zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
+                                         SD0_OTAPDLYSEL_SDR104_B2);
+               else
+                       zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
+                                         SD0_OTAPDLYSEL_SDR104_B0);
+       } else {
+               /* Program OTAP */
+               if (bank == MMC_BANK2)
+                       zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+                                         SD1_OTAPDLYSEL_SDR104_B2);
+               else
+                       zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+                                         SD1_OTAPDLYSEL_SDR104_B0);
+       }
+}
+
+static void arasan_zynqmp_tap_hs(u8 deviceid, u8 timing, u8 bank)
+{
+       if (deviceid == 0) {
+               /* Program ITAP */
+               zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
+                                 SD0_ITAPCHGWIN);
+               zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK,
+                                 SD0_ITAPDLYENA);
+               zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
+                                 SD0_ITAPDLYSEL_HSD);
+               zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, 0x0);
+               /* Program OTAP */
+               if (timing == MMC_TIMING_MMC_HS)
+                       zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
+                                         SD0_OTAPDLYSEL_MMC_HSD);
+               else
+                       zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
+                                         SD0_OTAPDLYSEL_SD_HSD);
+       } else {
+               /* Program ITAP */
+               zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
+                                 SD1_ITAPCHGWIN);
+               zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK,
+                                 SD1_ITAPDLYENA);
+               zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
+                                 SD1_ITAPDLYSEL_HSD);
+               zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, 0x0);
+               /* Program OTAP */
+               if (timing == MMC_TIMING_MMC_HS)
+                       zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+                                         SD1_OTAPDLYSEL_MMC_HSD);
+               else
+                       zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+                                         SD1_OTAPDLYSEL_SD_HSD);
+       }
+}
+
+static void arasan_zynqmp_tap_ddr50(u8 deviceid, u8 timing, u8 bank)
+{
+       if (deviceid == 0) {
+               /* Program ITAP */
+               zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
+                                 SD0_ITAPCHGWIN);
+               zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK,
+                                 SD0_ITAPDLYENA);
+               if (timing == MMC_TIMING_UHS_DDR50)
+                       zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
+                                         SD0_ITAPDLYSEL_SD_DDR50);
+               else
+                       zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
+                                         SD0_ITAPDLYSEL_MMC_DDR50);
+               zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, 0x0);
+               /* Program OTAP */
+               if (timing == MMC_TIMING_UHS_DDR50)
+                       zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
+                                         SD0_OTAPDLYSEL_SD_DDR50);
+               else
+                       zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
+                                         SD0_OTAPDLYSEL_MMC_DDR50);
+       } else {
+               /* Program ITAP */
+               zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
+                                 SD1_ITAPCHGWIN);
+               zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK,
+                                 SD1_ITAPDLYENA);
+               if (timing == MMC_TIMING_UHS_DDR50)
+                       zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
+                                         SD1_ITAPDLYSEL_SD_DDR50);
+               else
+                       zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
+                                         SD1_ITAPDLYSEL_MMC_DDR50);
+               zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, 0x0);
+               /* Program OTAP */
+               if (timing == MMC_TIMING_UHS_DDR50)
+                       zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+                                         SD1_OTAPDLYSEL_SD_DDR50);
+               else
+                       zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+                                         SD1_OTAPDLYSEL_MMC_DDR50);
+       }
+}
+
+static void arasan_zynqmp_tap_sdr50(u8 deviceid, u8 timing, u8 bank)
+{
+       if (deviceid == 0) {
+               /* Program OTAP */
+               zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
+                                 SD0_OTAPDLYSEL_SDR50);
+       } else {
+               /* Program OTAP */
+               zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+                                 SD1_OTAPDLYSEL_SDR50);
+       }
+}
+
+void arasan_zynqmp_set_tapdelay(u8 deviceid, u8 timing, u8 bank)
+{
+       if (deviceid == 0)
+               zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK,
+                                 SD0_DLL_RST);
+       else
+               zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK,
+                                 SD1_DLL_RST);
+
+       switch (timing) {
+       case MMC_TIMING_UHS_SDR25:
+               arasan_zynqmp_tap_hs(deviceid, timing, bank);
+               break;
+       case MMC_TIMING_UHS_SDR50:
+               arasan_zynqmp_tap_sdr50(deviceid, timing, bank);
+               break;
+       case MMC_TIMING_UHS_SDR104:
+       case MMC_TIMING_MMC_HS200:
+               arasan_zynqmp_tap_sdr104(deviceid, timing, bank);
+               break;
+       case MMC_TIMING_UHS_DDR50:
+               arasan_zynqmp_tap_ddr50(deviceid, timing, bank);
+               break;
+       }
+
+       if (deviceid == 0)
+               zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
+       else
+               zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
+}
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 9463a06..d61ccaa 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -10,9 +10,11 @@
 #include <common.h>
 #include <dm.h>
 #include <fdtdec.h>
+#include "mmc_private.h"
 #include <linux/libfdt.h>
 #include <malloc.h>
 #include <sdhci.h>
+#include <zynqmp_tap_delay.h>

 DECLARE_GLOBAL_DATA_PTR;

@@ -22,15 +24,212 @@ struct arasan_sdhci_plat {
        unsigned int f_max;
 };

+struct arasan_sdhci_priv {
+       struct sdhci_host *host;
+       u8 deviceid;
+       u8 bank;
+       u8 no_1p8;
+       bool pwrseq;
+};
+
+#if defined(CONFIG_ARCH_ZYNQMP)
+static const u8 mode2timing[] = {
+            [UHS_SDR12] = UHS_SDR12_BUS_SPEED,
+            [UHS_SDR25] = UHS_SDR25_BUS_SPEED,
+            [UHS_SDR50] = UHS_SDR50_BUS_SPEED,
+            [UHS_SDR104] = UHS_SDR104_BUS_SPEED,
+            [UHS_DDR50] = UHS_DDR50_BUS_SPEED,
+};
+
+#define SDHCI_HOST_CTRL2       0x3E
+#define SDHCI_CTRL2_MODE_MASK  0x7
+#define SDHCI_18V_SIGNAL       0x8
+#define SDHCI_CTRL_EXEC_TUNING 0x0040
+#define SDHCI_CTRL_TUNED_CLK   0x80
+#define SDHCI_TUNING_LOOP_COUNT        40
+
+static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
+{
+       u16 clk;
+       unsigned long timeout;
+
+       clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+       clk &= ~(SDHCI_CLOCK_CARD_EN);
+       sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+       /* Issue DLL Reset */
+       zynqmp_dll_reset(deviceid);
+
+       /* Wait max 20 ms */
+       timeout = 100;
+       while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
+                               & SDHCI_CLOCK_INT_STABLE)) {
+               if (timeout == 0) {
+                       dev_err(mmc_dev(host->mmc),
+                               ": Internal clock never stabilised.\n");
+                       return;
+               }
+               timeout--;
+               udelay(1000);
+       }
+
+       clk |= SDHCI_CLOCK_CARD_EN;
+       sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+}
+
+static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
+{
+       struct mmc_cmd cmd;
+       struct mmc_data data;
+       u32 ctrl;
+       struct sdhci_host *host;
+       struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
+       u8 tuning_loop_counter = SDHCI_TUNING_LOOP_COUNT;
+       u8 deviceid;
+
+       debug("%s\n", __func__);
+
+       host = priv->host;
+       deviceid = priv->deviceid;
+
+       ctrl = sdhci_readw(host, SDHCI_HOST_CTRL2);
+       ctrl |= SDHCI_CTRL_EXEC_TUNING;
+       sdhci_writew(host, ctrl, SDHCI_HOST_CTRL2);
+
+       mdelay(1);
+
+       arasan_zynqmp_dll_reset(host, deviceid);
+
+       sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
+       sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
+
+       do {
+               cmd.cmdidx = opcode;
+               cmd.resp_type = MMC_RSP_R1;
+               cmd.cmdarg = 0;
+
+               data.blocksize = 64;
+               data.blocks = 1;
+               data.flags = MMC_DATA_READ;
+
+               if (tuning_loop_counter-- == 0)
+                       break;
+
+               if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200 &&
+                   mmc->bus_width == 8)
+                       data.blocksize = 128;
+
+               sdhci_writew(host, SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG,
+                                                   data.blocksize),
+                            SDHCI_BLOCK_SIZE);
+               sdhci_writew(host, data.blocks, SDHCI_BLOCK_COUNT);
+               sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
+
+               mmc_send_cmd(mmc, &cmd, NULL);
+               ctrl = sdhci_readw(host, SDHCI_HOST_CTRL2);
+
+               if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK)
+                       udelay(1);
+
+       } while (ctrl & SDHCI_CTRL_EXEC_TUNING);
+
+       if (tuning_loop_counter < 0) {
+               ctrl &= ~SDHCI_CTRL_TUNED_CLK;
+               sdhci_writel(host, ctrl, SDHCI_HOST_CTRL2);
+       }
+
+       if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
+               printf("%s:Tuning failed\n", __func__);
+               return -1;
+       }
+
+       udelay(1);
+       arasan_zynqmp_dll_reset(host, deviceid);
+
+       /* Enable only interrupts served by the SD controller */
+       sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK,
+                    SDHCI_INT_ENABLE);
+       /* Mask all sdhci interrupt sources */
+       sdhci_writel(host, 0x0, SDHCI_SIGNAL_ENABLE);
+
+       return 0;
+}
+
+static void arasan_sdhci_set_tapdelay(struct sdhci_host *host)
+{
+       struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
+       struct mmc *mmc = (struct mmc *)host->mmc;
+       u8 uhsmode;
+
+       if (!IS_SD(mmc))
+               return;
+
+       uhsmode = mode2timing[mmc->selected_mode];
+
+       if (uhsmode >= UHS_SDR25_BUS_SPEED)
+               arasan_zynqmp_set_tapdelay(priv->deviceid, uhsmode,
+                                          priv->bank);
+}
+
+static void arasan_sdhci_set_control_reg(struct sdhci_host *host)
+{
+       struct mmc *mmc = (struct mmc *)host->mmc;
+       u32 reg;
+
+       if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
+               reg = sdhci_readw(host, SDHCI_HOST_CTRL2);
+               reg |= SDHCI_18V_SIGNAL;
+               sdhci_writew(host, reg, SDHCI_HOST_CTRL2);
+       }
+
+       if (mmc->selected_mode > SD_HS &&
+           mmc->selected_mode <= UHS_DDR50) {
+               reg = sdhci_readw(host, SDHCI_HOST_CTRL2);
+               reg &= ~SDHCI_CTRL2_MODE_MASK;
+               switch (mmc->selected_mode) {
+               case UHS_SDR12:
+                       reg |= UHS_SDR12_BUS_SPEED;
+                       break;
+               case UHS_SDR25:
+                       reg |= UHS_SDR25_BUS_SPEED;
+                       break;
+               case UHS_SDR50:
+                       reg |= UHS_SDR50_BUS_SPEED;
+                       break;
+               case UHS_SDR104:
+                       reg |= UHS_SDR104_BUS_SPEED;
+                       break;
+               case UHS_DDR50:
+                       reg |= UHS_DDR50_BUS_SPEED;
+                       break;
+               default:
+                       break;
+               }
+               sdhci_writew(host, reg, SDHCI_HOST_CTRL2);
+       }
+}
+#endif
+
+#if defined(CONFIG_DM_MMC) && defined(CONFIG_ARCH_ZYNQMP)
+const struct sdhci_ops arasan_ops = {
+       .platform_execute_tuning        = &arasan_sdhci_execute_tuning,
+       .set_delay = &arasan_sdhci_set_tapdelay,
+       .set_control_reg = &arasan_sdhci_set_control_reg,
+};
+#endif
+
 static int arasan_sdhci_probe(struct udevice *dev)
 {
        struct arasan_sdhci_plat *plat = dev_get_platdata(dev);
        struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
-       struct sdhci_host *host = dev_get_priv(dev);
+       struct arasan_sdhci_priv *priv = dev_get_priv(dev);
+       struct sdhci_host *host;
        struct clk clk;
        unsigned long clock;
        int ret;

+       host = priv->host;
+
        ret = clk_get_by_index(dev, 0, &clk);
        if (ret < 0) {
                dev_err(dev, "failed to get clock\n");
@@ -42,6 +241,7 @@ static int arasan_sdhci_probe(struct udevice *dev)
                dev_err(dev, "failed to get rate\n");
                return clock;
        }
+
        debug("%s: CLK %ld\n", __func__, clock);

        ret = clk_enable(&clk);
@@ -57,6 +257,9 @@ static int arasan_sdhci_probe(struct udevice *dev)
        host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
 #endif

+       if (priv->no_1p8)
+               host->quirks |= SDHCI_QUIRK_NO_1_8_V;
+
        host->max_clk = clock;

        ret = sdhci_setup_cfg(&plat->cfg, host, plat->f_max,
@@ -74,10 +277,28 @@ static int arasan_sdhci_probe(struct udevice *dev)
 static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
 {
        struct arasan_sdhci_plat *plat = dev_get_platdata(dev);
-       struct sdhci_host *host = dev_get_priv(dev);
+       struct arasan_sdhci_priv *priv = dev_get_priv(dev);
+
+       priv->host = calloc(1, sizeof(struct sdhci_host));
+       if (!priv->host)
+               return -1;

-       host->name = dev->name;
-       host->ioaddr = (void *)devfdt_get_addr(dev);
+       priv->host->name = dev->name;
+       priv->host->ioaddr = (void *)devfdt_get_addr(dev);
+
+       priv->deviceid = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+                                       "xlnx,device_id", -1);
+       priv->bank = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+                                   "xlnx,mio_bank", -1);
+       if (fdt_get_property(gd->fdt_blob, dev_of_offset(dev),
+                            "no-1-8-v", NULL))
+               priv->no_1p8 = 1;
+       else
+               priv->no_1p8 = 0;
+
+#if defined(CONFIG_DM_MMC) && defined(CONFIG_ARCH_ZYNQMP)
+       priv->host->ops = &arasan_ops;
+#endif

        plat->f_max = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
                                "max-frequency", CONFIG_ZYNQ_SDHCI_MAX_FREQ);
@@ -105,6 +326,6 @@ U_BOOT_DRIVER(arasan_sdhci_drv) = {
        .ops            = &sdhci_ops,
        .bind           = arasan_sdhci_bind,
        .probe          = arasan_sdhci_probe,
-       .priv_auto_alloc_size = sizeof(struct sdhci_host),
+       .priv_auto_alloc_size = sizeof(struct arasan_sdhci_priv),
        .platdata_auto_alloc_size = sizeof(struct arasan_sdhci_plat),
 };
diff --git a/include/zynqmp_tap_delay.h b/include/zynqmp_tap_delay.h
new file mode 100644
index 0000000..63be099
--- /dev/null
+++ b/include/zynqmp_tap_delay.h
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx ZynqMP SoC Tap Delay Programming
+ *
+ * Copyright (C) 2018 Xilinx, Inc.
+ *
+ */
+
+#ifndef __ZYNQMP_TAP_DELAY_H__
+#define __ZYNQMP_TAP_DELAY_H__
+
+#ifdef CONFIG_ARCH_ZYNQMP
+void zynqmp_dll_reset(u8 deviceid);
+void arasan_zynqmp_set_tapdelay(u8 device_id, u8 uhsmode, u8 bank);
+#else
+inline void zynqmp_dll_reset(u8 deviceid) {}
+inline void arasan_zynqmp_set_tapdelay(u8 device_id, u8 uhsmode, u8 bank) {}
+#endif
+
+#endif
--
2.7.4

This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.


More information about the U-Boot mailing list