Re: [PATCH v1 1/1] mmc: sdhci-esdhc-imx: Set maximum watermark levels for PIO access

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 17 April 2018 at 15:15, Harish Jenny K N <harish_kandiga@xxxxxxxxxx> wrote:
> From: Andrew Gabbasov <andrew_gabbasov@xxxxxxxxxx>
>
> While performing R/W access in PIO mode, the common SDHCI driver checks
> the buffer ready status once per whole block processing. That is, after
> getting an appropriate interrupt, or checking an appropriate status bit,
> the driver makes buffer accesses for the whole block size (e.g. 128 reads
> for 512 bytes block). This is done in accordance with SD Host Controller
> Specification.
>
> At the same time, the Ultra Secured Digital Host Controller (uSDHC), used
> in i.MX6 (and, probably, earlier i.MX series too), uses a separate
> Watermark Levels register, controlling the amount of data or space
> available when raising status bit or interrupt. For default watermark
> setting of 16 words, the controller expects (and guarantees) no more
> than 16 buffer accesses after raising buffer ready status bit and
> generating an appropriate interrupt. If the driver tries to access the
> whole block size, it will get incorrect data at the end, and a new
> interrupt will appear later, when the driver already doesn't expect it.
> This happens sometimes, more likely on low frequencies, e.g. when
> reading EXT_CSD at MMC card initialization phase
> (which makes that initialization fail).
>
> Such behavior of i.MX uSDHC seems to be non-compliant
> to SDHCI Specification, but this is the way it works now.
>
> In order not to rewrite the SDHCI driver PIO mode access logic,
> the IMX specific driver can just set the watermark level to default
> block size (128 words or 512 bytes), so that the controller behavior
> will be consistent to generic specification. This patch does this
> for PIO mode accesses only, restoring default values for DMA accesses
> to avoid any possible side effects from performance point of view.
>
> Signed-off-by: Andrew Gabbasov <andrew_gabbasov@xxxxxxxxxx>
> Signed-off-by: Harish Jenny K N <harish_kandiga@xxxxxxxxxx>

Thanks, applied for next!

Kind regards
Uffe

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
>
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index cd2b5f6..d6aef70 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -41,6 +41,12 @@
>  #define  ESDHC_VENDOR_SPEC_FRC_SDCLK_ON        (1 << 8)
>  #define ESDHC_WTMK_LVL                 0x44
>  #define  ESDHC_WTMK_DEFAULT_VAL                0x10401040
> +#define  ESDHC_WTMK_LVL_RD_WML_MASK    0x000000FF
> +#define  ESDHC_WTMK_LVL_RD_WML_SHIFT   0
> +#define  ESDHC_WTMK_LVL_WR_WML_MASK    0x00FF0000
> +#define  ESDHC_WTMK_LVL_WR_WML_SHIFT   16
> +#define  ESDHC_WTMK_LVL_WML_VAL_DEF    64
> +#define  ESDHC_WTMK_LVL_WML_VAL_MAX    128
>  #define ESDHC_MIX_CTRL                 0x48
>  #define  ESDHC_MIX_CTRL_DDREN          (1 << 3)
>  #define  ESDHC_MIX_CTRL_AC23EN         (1 << 7)
> @@ -516,6 +522,7 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
>                 }
>
>                 if (esdhc_is_usdhc(imx_data)) {
> +                       u32 wml;
>                         u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL);
>                         /* Swap AC23 bit */
>                         if (val & SDHCI_TRNS_AUTO_CMD23) {
> @@ -524,6 +531,21 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
>                         }
>                         m = val | (m & ~ESDHC_MIX_CTRL_SDHCI_MASK);
>                         writel(m, host->ioaddr + ESDHC_MIX_CTRL);
> +
> +                       /* Set watermark levels for PIO access to maximum value
> +                        * (128 words) to accommodate full 512 bytes buffer.
> +                        * For DMA access restore the levels to default value.
> +                        */
> +                       m = readl(host->ioaddr + ESDHC_WTMK_LVL);
> +                       if (val & SDHCI_TRNS_DMA)
> +                               wml = ESDHC_WTMK_LVL_WML_VAL_DEF;
> +                       else
> +                               wml = ESDHC_WTMK_LVL_WML_VAL_MAX;
> +                       m &= ~(ESDHC_WTMK_LVL_RD_WML_MASK |
> +                              ESDHC_WTMK_LVL_WR_WML_MASK);
> +                       m |= (wml << ESDHC_WTMK_LVL_RD_WML_SHIFT) |
> +                            (wml << ESDHC_WTMK_LVL_WR_WML_SHIFT);
> +                       writel(m, host->ioaddr + ESDHC_WTMK_LVL);
>                 } else {
>                         /*
>                          * Postpone this write, we must do it together with a
> --
> 1.9.1
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux