From patchwork Thu Jun 28 07:31:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: mmc: sdhci-esdhc-imx: support eMMC DDR mode when running at 3.3V From: Stefan Agner X-Patchwork-Id: 10493185 Message-Id: <20180628073136.21748-1-stefan@agner.ch> To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: fabio.estevam@nxp.com, haibo.chen@nxp.com, aisheng.dong@nxp.com, michael@amarulasolutions.com, linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, Stefan Agner Date: Thu, 28 Jun 2018 09:31:36 +0200 The uSDHC supports DDR modes for eMMC devices running at 3.3V. This allows to run eMMC with 3.3V signaling voltage at DDR52 mode: # cat /sys/kernel/debug/mmc1/ios clock: 52000000 Hz vdd: 21 (3.3 ~ 3.4 V) bus mode: 2 (push-pull) chip select: 0 (don't care) power mode: 2 (on) bus width: 3 (8 bits) timing spec: 8 (mmc DDR52) signal voltage: 0 (3.30 V) driver type: 0 (driver type B) Signed-off-by: Stefan Agner --- drivers/mmc/host/sdhci-esdhc-imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index b716b933f00a..6f444731754d 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -1324,7 +1324,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) if (esdhc_is_usdhc(imx_data)) { host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; - host->mmc->caps |= MMC_CAP_1_8V_DDR; + host->mmc->caps |= MMC_CAP_1_8V_DDR | MMC_CAP_3_3V_DDR; if (!(imx_data->socdata->flags & ESDHC_FLAG_HS200)) host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200; From patchwork Thu Jun 28 08:13:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [1/3] mmc: sdhci-esdhc-imx: get rid of support_vsel From: Stefan Agner X-Patchwork-Id: 10493269 Message-Id: <20180628081331.13051-2-stefan@agner.ch> To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: fabio.estevam@nxp.com, haibo.chen@nxp.com, aisheng.dong@nxp.com, michael@amarulasolutions.com, rmk+kernel@armlinux.org.uk, linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, Stefan Agner Date: Thu, 28 Jun 2018 10:13:29 +0200 The field support_vsel is currently only used in the device tree case. Get rid of it. No change in behavior. Signed-off-by: Stefan Agner --- drivers/mmc/host/sdhci-esdhc-imx.c | 8 ++------ include/linux/platform_data/mmc-esdhc-imx.h | 2 -- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 6f444731754d..20a420b765b3 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -1145,18 +1145,14 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, &boarddata->tuning_start_tap); if (of_find_property(np, "no-1-8-v", NULL)) - boarddata->support_vsel = false; - else - boarddata->support_vsel = true; + host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; if (of_property_read_u32(np, "fsl,delay-line", &boarddata->delay_line)) boarddata->delay_line = 0; mmc_of_parse_voltage(np, &host->ocr_mask); - /* sdr50 and sdr104 need work on 1.8v signal voltage */ - if ((boarddata->support_vsel) && esdhc_is_usdhc(imx_data) && - !IS_ERR(imx_data->pins_default)) { + if (esdhc_is_usdhc(imx_data) && !IS_ERR(imx_data->pins_default)) { imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl, ESDHC_PINCTRL_STATE_100MHZ); imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl, diff --git a/include/linux/platform_data/mmc-esdhc-imx.h b/include/linux/platform_data/mmc-esdhc-imx.h index 7daa78a2f342..640dec8b5b0c 100644 --- a/include/linux/platform_data/mmc-esdhc-imx.h +++ b/include/linux/platform_data/mmc-esdhc-imx.h @@ -34,7 +34,6 @@ enum cd_types { * @cd_gpio: gpio for card_detect interrupt * @wp_type: type of write_protect method (see wp_types enum above) * @cd_type: type of card_detect method (see cd_types enum above) - * @support_vsel: indicate it supports 1.8v switching */ struct esdhc_platform_data { @@ -43,7 +42,6 @@ struct esdhc_platform_data { enum wp_types wp_type; enum cd_types cd_type; int max_bus_width; - bool support_vsel; unsigned int delay_line; unsigned int tuning_step; /* The delay cell steps in tuning procedure */ unsigned int tuning_start_tap; /* The start delay cell point in tuning procedure */ From patchwork Thu Jun 28 08:13:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [2/3] mmc: sdhci: add quirk to prevent higher speed modes From: Stefan Agner X-Patchwork-Id: 10493273 Message-Id: <20180628081331.13051-3-stefan@agner.ch> To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: fabio.estevam@nxp.com, haibo.chen@nxp.com, aisheng.dong@nxp.com, michael@amarulasolutions.com, rmk+kernel@armlinux.org.uk, linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, Stefan Agner Date: Thu, 28 Jun 2018 10:13:30 +0200 Some hosts are capable of running higher speed modes but do not have the board support for it. Introduce a quirk which prevents the stack from using modes running at 100MHz or faster. Signed-off-by: Stefan Agner --- drivers/mmc/host/sdhci.c | 8 ++++++++ drivers/mmc/host/sdhci.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 1c828e0e9905..8ac257dfaab3 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -3749,6 +3749,14 @@ int sdhci_setup_host(struct sdhci_host *host) } } + if (host->quirks2 & SDHCI_QUIRK2_NO_UHS_HS200_HS400) { + host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | + SDHCI_SUPPORT_DDR50); + + mmc->caps2 &= ~(MMC_CAP2_HSX00_1_8V | MMC_CAP2_HSX00_1_2V | + MMC_CAP2_HS400_ES); + } + if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V) { host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 23966f887da6..cb2433d6d61f 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -450,6 +450,8 @@ struct sdhci_host { * obtainable timeout. */ #define SDHCI_QUIRK2_DISABLE_HW_TIMEOUT (1<<17) +/* Do not support any higher speeds (>50MHz) */ +#define SDHCI_QUIRK2_NO_UHS_HS200_HS400 (1<<18) int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ From patchwork Thu Jun 28 08:13:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [3/3] mmc: sdhci-esdhc-imx: prevent stack from using higher speed modes From: Stefan Agner X-Patchwork-Id: 10493271 Message-Id: <20180628081331.13051-4-stefan@agner.ch> To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: fabio.estevam@nxp.com, haibo.chen@nxp.com, aisheng.dong@nxp.com, michael@amarulasolutions.com, rmk+kernel@armlinux.org.uk, linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, Stefan Agner Date: Thu, 28 Jun 2018 10:13:31 +0200 If pinctrl configurations for higher speed modes are missing, the stack currently uses the no 1.8V quirk. This comes close to what we need but not exactly: E.g. if a eMMC chip uses 1.8V signaling (by specifying a 1.8V only vqmmc-supply) while not providing any 100MHz/200MHz pinctrl configurations then the SDHCI_QUIRK2_NO_1_8_V leads the stack to print signaling voltage switch failed errors continuously: mmc1: Switching to 3.3V signalling voltage failed Presumably because the stack tries to use 3.3V signaling: # cat /sys/kernel/debug/mmc1/ios ... timing spec: 8 (mmc DDR52) signal voltage: 0 (3.30 V) ... With using SDHCI_QUIRK2_NO_UHS_HS200_HS400 we prevent the stack from choosing any modes require speeds higher than 52MHz while still allowing to select modes using 1.8V at lower speeds (e.g. DDR52): # cat /sys/kernel/debug/mmc1/ios ... timing spec: 8 (mmc DDR52) signal voltage: 1 (1.80 V) ... Signed-off-by: Stefan Agner --- drivers/mmc/host/sdhci-esdhc-imx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 20a420b765b3..4a1c33018072 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -1165,10 +1165,10 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, * fall back to not supporting uhs by specifying no * 1.8v quirk */ - host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; + host->quirks2 |= SDHCI_QUIRK2_NO_UHS_HS200_HS400; } } else { - host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; + host->quirks2 |= SDHCI_QUIRK2_NO_UHS_HS200_HS400; } /* call to generic mmc_of_parse to support additional capabilities */