Hi,

On 7/24/21 5:10 PM, Ashok Reddy Soma wrote:
> Currently xilinx sdhci driver is using zynqmp_mmio_write() to set
> tapdelay values. Use xilinx_pm_request() using appropriate arguments
> to set input/output tapdelays for zynqmp. Where tapdelay setting is
> done by firmware. Host driver should explicitly request DLL reset
> before ITAP (assert DLL) and after OTAP (release DLL) to avoid issues
> in some cases. Also handle error return where possible.
> 
> Signed-off-by: T Karthik Reddy <t.karthik.re...@xilinx.com>
> Signed-off-by: Ashok Reddy Soma <ashok.reddy.s...@xilinx.com>
> ---
> 
>  board/xilinx/zynqmp/tap_delays.c | 89 +++-----------------------------
>  drivers/mmc/zynq_sdhci.c         | 72 +++++++++++++++++++++-----
>  include/zynqmp_tap_delay.h       | 25 ++++++---
>  3 files changed, 84 insertions(+), 102 deletions(-)

Doen it impossible to separate the board specific patch and mmc patch?

> 
> diff --git a/board/xilinx/zynqmp/tap_delays.c 
> b/board/xilinx/zynqmp/tap_delays.c
> index d16bbb8eff..4ce2244060 100644
> --- a/board/xilinx/zynqmp/tap_delays.c
> +++ b/board/xilinx/zynqmp/tap_delays.c
> @@ -10,92 +10,17 @@
>  #include <asm/arch/sys_proto.h>
>  #include <linux/delay.h>
>  #include <mmc.h>
> +#include <zynqmp_firmware.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 SD1_ITAPDLYSEL_MASK          0x00FF0000
> -#define SD0_OTAPDLYSEL_MASK          0x0000003F
> -#define SD1_OTAPDLYSEL_MASK          0x003F0000
> -
> -void zynqmp_dll_reset(u8 deviceid)
> +int arasan_zynqmp_set_in_tapdelay(u8 deviceid, u32 type, u32 itap_delay)
>  {
> -     /* 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);
> +     return xilinx_pm_request(PM_IOCTL, (u32)deviceid, IOCTL_SET_SD_TAPDELAY,
> +                       type, itap_delay, NULL);
>  }
>  
> -void arasan_zynqmp_set_in_tapdelay(u8 deviceid, u32 itap_delay)
> +int arasan_zynqmp_set_out_tapdelay(u8 deviceid, u32 type, u32 otap_delay)
>  {
> -     if (deviceid == 0) {
> -             zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, SD0_DLL_RST);
> -
> -             /* Program ITAP delay */
> -             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, itap_delay);
> -             zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, 0x0);
> -
> -             zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
> -     } else {
> -             zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, SD1_DLL_RST);
> -
> -             /* Program ITAP delay */
> -             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,
> -                               (itap_delay << 16));
> -             zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, 0x0);
> -
> -             zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
> -     }
> -}
> -
> -void arasan_zynqmp_set_out_tapdelay(u8 deviceid, u32 otap_delay)
> -{
> -     if (deviceid == 0) {
> -             zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, SD0_DLL_RST);
> -
> -             /* Program OTAP delay */
> -             zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK, otap_delay);
> -
> -             zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
> -     } else {
> -             zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, SD1_DLL_RST);
> -
> -             /* Program OTAP delay */
> -             zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
> -                               (otap_delay << 16));
> -
> -             zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
> -     }
> +     return xilinx_pm_request(PM_IOCTL, (u32)deviceid, IOCTL_SET_SD_TAPDELAY,
> +                       type, otap_delay, NULL);
>  }
> diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
> index 9fb3603c7e..4dafd47b57 100644
> --- a/drivers/mmc/zynq_sdhci.c
> +++ b/drivers/mmc/zynq_sdhci.c
> @@ -18,6 +18,7 @@
>  #include <malloc.h>
>  #include <sdhci.h>
>  #include <zynqmp_tap_delay.h>
> +#include <zynqmp_firmware.h>
>  
>  #define SDHCI_ARASAN_ITAPDLY_REGISTER        0xF0F8
>  #define SDHCI_ARASAN_ITAPDLY_SEL_MASK        GENMASK(7, 0)
> @@ -75,26 +76,39 @@ static const u8 mode2timing[] = {
>       [MMC_HS_200] = MMC_TIMING_MMC_HS200,
>  };
>  
> -static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
> +static int arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
>  {
> -     u16 clk;
> +     struct mmc *mmc = (struct mmc *)host->mmc;
> +     struct udevice *dev = mmc->dev;
>       unsigned long timeout;
> +     int ret;
> +     u16 clk;
>  
>       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);
> +     ret = zynqmp_pm_sd_dll_reset(deviceid, PM_DLL_RESET_ASSERT);
> +     if (ret) {
> +             dev_err(dev, "dll_reset assert failed with err: %d\n", ret);
> +             return ret;
> +     }
> +
> +     mdelay(1);

If add some comments about this, it's more helpful.

> +     ret = zynqmp_pm_sd_dll_reset(deviceid, PM_DLL_RESET_RELEASE);
> +     if (ret) {
> +             dev_err(dev, "dll_reset release failed with err: %d\n", ret);
> +             return ret;
> +     }
>  
>       /* 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;
> +                     dev_err(dev, ": Internal clock never stabilised.\n");
> +                     return -EBUSY;
>               }
>               timeout--;
>               udelay(1000);
> @@ -102,6 +116,8 @@ static void arasan_zynqmp_dll_reset(struct sdhci_host 
> *host, u8 deviceid)
>  
>       clk |= SDHCI_CLOCK_CARD_EN;
>       sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
> +
> +     return 0;
>  }
>  
>  static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
> @@ -109,15 +125,14 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, 
> u8 opcode)
>       struct mmc_cmd cmd;
>       struct mmc_data data;
>       u32 ctrl;
> +     u8 node_id = mmc->dev->seq_ ? NODE_SD_0 : NODE_SD_1;

Does it need to get a node_id value from mmc->dev->seq_ at everytime?
And priv->deviceid doesn't use anywhere. Can't it reuse?

Best Regards,
Jaehoon Chung

>       struct sdhci_host *host;
>       struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
>       char 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_CONTROL2);
>       ctrl |= SDHCI_CTRL_EXEC_TUNING;
> @@ -125,7 +140,7 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, 
> u8 opcode)
>  
>       mdelay(1);
>  
> -     arasan_zynqmp_dll_reset(host, deviceid);
> +     arasan_zynqmp_dll_reset(host, node_id);
>  
>       sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
>       sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
> @@ -171,7 +186,7 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, 
> u8 opcode)
>       }
>  
>       udelay(1);
> -     arasan_zynqmp_dll_reset(host, deviceid);
> +     arasan_zynqmp_dll_reset(host, node_id);
>  
>       /* Enable only interrupts served by the SD controller */
>       sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK,
> @@ -194,10 +209,12 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, 
> u8 opcode)
>  static int sdhci_zynqmp_sdcardclk_set_phase(struct sdhci_host *host,
>                                           int degrees)
>  {
> -     struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
>       struct mmc *mmc = (struct mmc *)host->mmc;
> +     struct udevice *dev = mmc->dev;
> +     u8 node_id = dev->seq_ ? NODE_SD_0 : NODE_SD_1;
>       u8 tap_delay, tap_max = 0;
>       int timing = mode2timing[mmc->selected_mode];
> +     int ret;
>  
>       /*
>        * This is applicable for SDHCI_SPEC_300 and above
> @@ -233,7 +250,20 @@ static int sdhci_zynqmp_sdcardclk_set_phase(struct 
> sdhci_host *host,
>       /* Limit output tap_delay value to 6 bits */
>       tap_delay &= SDHCI_ARASAN_OTAPDLY_SEL_MASK;
>  
> -     arasan_zynqmp_set_out_tapdelay(priv->deviceid, tap_delay);
> +     /* Set the Clock Phase */
> +     ret = arasan_zynqmp_set_out_tapdelay(node_id,
> +                                          PM_TAPDELAY_OUTPUT, tap_delay);
> +     if (ret) {
> +             dev_err(dev, "Error setting output Tap Delay\n");
> +             return ret;
> +     }
> +
> +     /* Release DLL Reset */
> +     ret = zynqmp_pm_sd_dll_reset(node_id, PM_DLL_RESET_RELEASE);
> +     if (ret) {
> +             dev_err(dev, "dll_reset release failed with err: %d\n", ret);
> +             return ret;
> +     }
>  
>       return 0;
>  }
> @@ -250,10 +280,12 @@ static int sdhci_zynqmp_sdcardclk_set_phase(struct 
> sdhci_host *host,
>  static int sdhci_zynqmp_sampleclk_set_phase(struct sdhci_host *host,
>                                           int degrees)
>  {
> -     struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
>       struct mmc *mmc = (struct mmc *)host->mmc;
> +     struct udevice *dev = mmc->dev;
> +     u8 node_id = dev->seq_ ? NODE_SD_0 : NODE_SD_1;
>       u8 tap_delay, tap_max = 0;
>       int timing = mode2timing[mmc->selected_mode];
> +     int ret;
>  
>       /*
>        * This is applicable for SDHCI_SPEC_300 and above
> @@ -263,6 +295,13 @@ static int sdhci_zynqmp_sampleclk_set_phase(struct 
> sdhci_host *host,
>       if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
>               return 0;
>  
> +     /* Assert DLL Reset */
> +     ret = zynqmp_pm_sd_dll_reset(node_id, PM_DLL_RESET_ASSERT);
> +     if (ret) {
> +             dev_err(dev, "dll_reset assert failed with err: %d\n", ret);
> +             return ret;
> +     }
> +
>       switch (timing) {
>       case MMC_TIMING_MMC_HS:
>       case MMC_TIMING_SD_HS:
> @@ -289,7 +328,12 @@ static int sdhci_zynqmp_sampleclk_set_phase(struct 
> sdhci_host *host,
>       /* Limit input tap_delay value to 8 bits */
>       tap_delay &= SDHCI_ARASAN_ITAPDLY_SEL_MASK;
>  
> -     arasan_zynqmp_set_in_tapdelay(priv->deviceid, tap_delay);
> +     ret = arasan_zynqmp_set_in_tapdelay(node_id,
> +                                         PM_TAPDELAY_INPUT, tap_delay);
> +     if (ret) {
> +             dev_err(dev, "Error setting Input Tap Delay\n");
> +             return ret;
> +     }
>  
>       return 0;
>  }
> diff --git a/include/zynqmp_tap_delay.h b/include/zynqmp_tap_delay.h
> index 1c1e3e7dee..7e4d4e4a9a 100644
> --- a/include/zynqmp_tap_delay.h
> +++ b/include/zynqmp_tap_delay.h
> @@ -8,14 +8,27 @@
>  #ifndef __ZYNQMP_TAP_DELAY_H__
>  #define __ZYNQMP_TAP_DELAY_H__
>  
> +#include <zynqmp_firmware.h>
> +
>  #ifdef CONFIG_ARCH_ZYNQMP
> -void zynqmp_dll_reset(u8 deviceid);
> -void arasan_zynqmp_set_in_tapdelay(u8 device_id, u32 itap_delay);
> -void arasan_zynqmp_set_out_tapdelay(u8 device_id, u32 otap_delay);
> +int arasan_zynqmp_set_in_tapdelay(u8 device_id, u32 type, u32 itap_delay);
> +int arasan_zynqmp_set_out_tapdelay(u8 device_id, u32 type, u32 otap_delay);
>  #else
> -inline void zynqmp_dll_reset(u8 deviceid) {}
> -inline void arasan_zynqmp_set_in_tapdelay(u8 device_id, u32 itap_delay) {}
> -inline void arasan_zynqmp_set_out_tapdelay(u8 device_id, u32 otap_delay) {}
> +inline int arasan_zynqmp_set_in_tapdelay(u8 device_id, u32 type, u32 
> itap_delay)
> +{
> +     return 0;
> +}
> +
> +int arasan_zynqmp_set_out_tapdelay(u8 device_id, u32 type, u32 otap_delay)
> +{
> +     return 0;
> +}
>  #endif
>  
> +static inline int zynqmp_pm_sd_dll_reset(u8 node_id, u32 type)
> +{
> +     return xilinx_pm_request(PM_IOCTL, (u32)node_id, IOCTL_SD_DLL_RESET,
> +                              type, 0, NULL);
> +}
> +
>  #endif
> 

Reply via email to