Skip to content

Commit

Permalink
mmc: host: sdhci-esdhc-imx.c: correct the auto-tuning setting for sdi…
Browse files Browse the repository at this point in the history
…o device

USDHC contain auto tuning circuit, this circuit will work automatically after
the tuning procedurae, it can increase/decrease the delay cell according to
the outside environment change (like temperature).

Unfortunately, this auto tuning circuit can not handle the async sdio device
interrupt correctly. When sdio device use 4 data line, async sdio interrupt
will use DAT[1], if we enable auto tuning circuit check 4 data lines, include
the DAT[1], this circuit will detect this interrupt, take this as a data on
DAT[1], and adjust the delay cell wrongly.

This is the hardware design limitation, to avoid this, when sdio device enable
async interrupt, auto tuning circuit only check DAT[0] and CMD lines.

Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
  • Loading branch information
Haibo Chen authored and Dong Aisheng committed Nov 2, 2021
1 parent 3fe0260 commit 84c529a
Showing 1 changed file with 18 additions and 0 deletions.
18 changes: 18 additions & 0 deletions drivers/mmc/host/sdhci-esdhc-imx.c
Expand Up @@ -229,6 +229,7 @@ struct esdhc_platform_data {
unsigned int tuning_step; /* The delay cell steps in tuning procedure */
unsigned int tuning_start_tap; /* The start delay cell point in tuning procedure */
unsigned int strobe_dll_delay_target; /* The delay cell for strobe pad (read clock) */
bool sdio_async_interrupt_enabled;
};

struct esdhc_soc_data {
Expand Down Expand Up @@ -435,6 +436,8 @@ static inline void esdhc_wait_for_card_clock_gate_off(struct sdhci_host *host)
/* Enable the auto tuning circuit to check the CMD line and BUS line */
static inline void usdhc_auto_tuning_mode_sel(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
u32 buswidth, auto_tune_buswidth;

buswidth = USDHC_GET_BUSWIDTH(readl(host->ioaddr + SDHCI_HOST_CONTROL));
Expand All @@ -451,6 +454,18 @@ static inline void usdhc_auto_tuning_mode_sel(struct sdhci_host *host)
break;
}

/*
* If sdio device use async interrupt, it will use DAT[1] to signal
* the device's interrupt asynchronous when use 4 data lines.
* Then hardware auto tuning circuit MUST NOT check the DAT[1] line,
* otherwise auto tuning will be impacted by this async interrupt,
* and change the delay cell incorrectly, which then cause data/cmd
* errors.
* This is the hardware auto tuning circuit limitation.
*/
if (imx_data->boarddata.sdio_async_interrupt_enabled)
auto_tune_buswidth = ESDHC_VEND_SPEC2_AUTO_TUNE_1BIT_EN;

esdhc_clrset_le(host, ESDHC_VEND_SPEC2_AUTO_TUNE_MODE_MASK,
auto_tune_buswidth | ESDHC_VEND_SPEC2_AUTO_TUNE_CMD_EN,
ESDHC_VEND_SPEC2);
Expand Down Expand Up @@ -1573,6 +1588,9 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
if (of_property_read_u32(np, "fsl,delay-line", &boarddata->delay_line))
boarddata->delay_line = 0;

if (of_property_read_bool(np, "fsl,sdio-async-interrupt-enabled"))
boarddata->sdio_async_interrupt_enabled = true;

mmc_of_parse_voltage(host->mmc, &host->ocr_mask);

if (!is_s32v234_usdhc(imx_data) && esdhc_is_usdhc(imx_data)
Expand Down

0 comments on commit 84c529a

Please sign in to comment.