From: Yangbo Lu <yangbo.lu@nxp.com> To: linux-mmc@vger.kernel.org, ulf.hansson@linaro.org, Adrian Hunter <adrian.hunter@intel.com>, Rob Herring <robh+dt@kernel.org>, Mark Rutland <mark.rutland@arm.com>, Catalin Marinas <catalin.marinas@arm.com>, Will Deacon <will.deacon@arm.com> Cc: devicetree@vger.kernel.org, Xiaobo Xie <xiaobo.xie@nxp.com>, linux-arm-kernel@lists.infradead.org, Yangbo Lu <yangbo.lu@nxp.com> Subject: [v2, 2/7] mmc: sdhci-of-esdhc: add support for signal voltage switch Date: Fri, 3 Mar 2017 16:18:44 +0800 [thread overview] Message-ID: <1488529129-23560-3-git-send-email-yangbo.lu@nxp.com> (raw) In-Reply-To: <1488529129-23560-1-git-send-email-yangbo.lu@nxp.com> eSDHC supports signal voltage switch from 3.3v to 1.8v by eSDHC_PROCTL[VOLT_SEL] bit. This bit changes the value of output signal SDHC_VS, and there must be a control circuit out of eSDHC to change the signal voltage according to SDHC_VS output signal. Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- Changes for v2: - Used Adrain's method to support voltage switching: host->mmc_host_ops.start_signal_voltage_switch = esdhc_signal_voltage_switch; --- drivers/mmc/host/sdhci-esdhc.h | 1 + drivers/mmc/host/sdhci-of-esdhc.c | 74 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h index 5343fc0..6869567 100644 --- a/drivers/mmc/host/sdhci-esdhc.h +++ b/drivers/mmc/host/sdhci-esdhc.h @@ -37,6 +37,7 @@ /* Protocol Control Register */ #define ESDHC_PROCTL 0x28 +#define ESDHC_VOLT_SEL 0x00000400 #define ESDHC_CTRL_4BITBUS (0x1 << 1) #define ESDHC_CTRL_8BITBUS (0x2 << 1) #define ESDHC_CTRL_BUSWIDTH_MASK (0x3 << 1) diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 84865b0..9ab6943 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -16,6 +16,7 @@ #include <linux/err.h> #include <linux/io.h> #include <linux/of.h> +#include <linux/of_address.h> #include <linux/delay.h> #include <linux/module.h> #include <linux/sys_soc.h> @@ -559,6 +560,76 @@ static void esdhc_reset(struct sdhci_host *host, u8 mask) sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); } +/* The SCFG, Supplemental Configuration Unit, provides SoC specific + * configuration and status registers for the device. There is a + * SDHC IO VSEL control register on SCFG for some platforms. It's + * used to support SDHC IO voltage switching. + */ +static const struct of_device_id scfg_device_ids[] = { + { .compatible = "fsl,t1040-scfg", }, + { .compatible = "fsl,ls1012a-scfg", }, + { .compatible = "fsl,ls1046a-scfg", }, + {} +}; + +/* SDHC IO VSEL control register definition */ +#define SCFG_SDHCIOVSELCR 0x408 +#define SDHCIOVSELCR_TGLEN 0x80000000 +#define SDHCIOVSELCR_VSELVAL 0x60000000 +#define SDHCIOVSELCR_SDHC_VS 0x00000001 + +static int esdhc_signal_voltage_switch(struct mmc_host *mmc, + struct mmc_ios *ios) +{ + struct sdhci_host *host = mmc_priv(mmc); + struct device_node *scfg_node; + void __iomem *scfg_base = NULL; + u32 sdhciovselcr; + u32 val; + + /* + * Signal Voltage Switching is only applicable for Host Controllers + * v3.00 and above. + */ + if (host->version < SDHCI_SPEC_300) + return 0; + + val = sdhci_readl(host, ESDHC_PROCTL); + + switch (ios->signal_voltage) { + case MMC_SIGNAL_VOLTAGE_330: + val &= ~ESDHC_VOLT_SEL; + sdhci_writel(host, val, ESDHC_PROCTL); + return 0; + case MMC_SIGNAL_VOLTAGE_180: + scfg_node = of_find_matching_node(NULL, scfg_device_ids); + if (scfg_node) + scfg_base = of_iomap(scfg_node, 0); + if (scfg_base) { + sdhciovselcr = SDHCIOVSELCR_TGLEN | + SDHCIOVSELCR_VSELVAL; + iowrite32be(sdhciovselcr, + scfg_base + SCFG_SDHCIOVSELCR); + + val |= ESDHC_VOLT_SEL; + sdhci_writel(host, val, ESDHC_PROCTL); + mdelay(5); + + sdhciovselcr = SDHCIOVSELCR_TGLEN | + SDHCIOVSELCR_SDHC_VS; + iowrite32be(sdhciovselcr, + scfg_base + SCFG_SDHCIOVSELCR); + iounmap(scfg_base); + } else { + val |= ESDHC_VOLT_SEL; + sdhci_writel(host, val, ESDHC_PROCTL); + } + return 0; + default: + return 0; + } +} + #ifdef CONFIG_PM_SLEEP static u32 esdhc_proctl; static int esdhc_of_suspend(struct device *dev) @@ -708,6 +779,9 @@ static int sdhci_esdhc_probe(struct platform_device *pdev) host = sdhci_pltfm_init(pdev, &sdhci_esdhc_be_pdata, sizeof(struct sdhci_esdhc)); + host->mmc_host_ops.start_signal_voltage_switch = + esdhc_signal_voltage_switch; + if (IS_ERR(host)) return PTR_ERR(host); -- 2.1.0.27.g96db324
WARNING: multiple messages have this Message-ID (diff)
From: yangbo.lu@nxp.com (Yangbo Lu) To: linux-arm-kernel@lists.infradead.org Subject: [v2, 2/7] mmc: sdhci-of-esdhc: add support for signal voltage switch Date: Fri, 3 Mar 2017 16:18:44 +0800 [thread overview] Message-ID: <1488529129-23560-3-git-send-email-yangbo.lu@nxp.com> (raw) In-Reply-To: <1488529129-23560-1-git-send-email-yangbo.lu@nxp.com> eSDHC supports signal voltage switch from 3.3v to 1.8v by eSDHC_PROCTL[VOLT_SEL] bit. This bit changes the value of output signal SDHC_VS, and there must be a control circuit out of eSDHC to change the signal voltage according to SDHC_VS output signal. Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- Changes for v2: - Used Adrain's method to support voltage switching: host->mmc_host_ops.start_signal_voltage_switch = esdhc_signal_voltage_switch; --- drivers/mmc/host/sdhci-esdhc.h | 1 + drivers/mmc/host/sdhci-of-esdhc.c | 74 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h index 5343fc0..6869567 100644 --- a/drivers/mmc/host/sdhci-esdhc.h +++ b/drivers/mmc/host/sdhci-esdhc.h @@ -37,6 +37,7 @@ /* Protocol Control Register */ #define ESDHC_PROCTL 0x28 +#define ESDHC_VOLT_SEL 0x00000400 #define ESDHC_CTRL_4BITBUS (0x1 << 1) #define ESDHC_CTRL_8BITBUS (0x2 << 1) #define ESDHC_CTRL_BUSWIDTH_MASK (0x3 << 1) diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 84865b0..9ab6943 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -16,6 +16,7 @@ #include <linux/err.h> #include <linux/io.h> #include <linux/of.h> +#include <linux/of_address.h> #include <linux/delay.h> #include <linux/module.h> #include <linux/sys_soc.h> @@ -559,6 +560,76 @@ static void esdhc_reset(struct sdhci_host *host, u8 mask) sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); } +/* The SCFG, Supplemental Configuration Unit, provides SoC specific + * configuration and status registers for the device. There is a + * SDHC IO VSEL control register on SCFG for some platforms. It's + * used to support SDHC IO voltage switching. + */ +static const struct of_device_id scfg_device_ids[] = { + { .compatible = "fsl,t1040-scfg", }, + { .compatible = "fsl,ls1012a-scfg", }, + { .compatible = "fsl,ls1046a-scfg", }, + {} +}; + +/* SDHC IO VSEL control register definition */ +#define SCFG_SDHCIOVSELCR 0x408 +#define SDHCIOVSELCR_TGLEN 0x80000000 +#define SDHCIOVSELCR_VSELVAL 0x60000000 +#define SDHCIOVSELCR_SDHC_VS 0x00000001 + +static int esdhc_signal_voltage_switch(struct mmc_host *mmc, + struct mmc_ios *ios) +{ + struct sdhci_host *host = mmc_priv(mmc); + struct device_node *scfg_node; + void __iomem *scfg_base = NULL; + u32 sdhciovselcr; + u32 val; + + /* + * Signal Voltage Switching is only applicable for Host Controllers + * v3.00 and above. + */ + if (host->version < SDHCI_SPEC_300) + return 0; + + val = sdhci_readl(host, ESDHC_PROCTL); + + switch (ios->signal_voltage) { + case MMC_SIGNAL_VOLTAGE_330: + val &= ~ESDHC_VOLT_SEL; + sdhci_writel(host, val, ESDHC_PROCTL); + return 0; + case MMC_SIGNAL_VOLTAGE_180: + scfg_node = of_find_matching_node(NULL, scfg_device_ids); + if (scfg_node) + scfg_base = of_iomap(scfg_node, 0); + if (scfg_base) { + sdhciovselcr = SDHCIOVSELCR_TGLEN | + SDHCIOVSELCR_VSELVAL; + iowrite32be(sdhciovselcr, + scfg_base + SCFG_SDHCIOVSELCR); + + val |= ESDHC_VOLT_SEL; + sdhci_writel(host, val, ESDHC_PROCTL); + mdelay(5); + + sdhciovselcr = SDHCIOVSELCR_TGLEN | + SDHCIOVSELCR_SDHC_VS; + iowrite32be(sdhciovselcr, + scfg_base + SCFG_SDHCIOVSELCR); + iounmap(scfg_base); + } else { + val |= ESDHC_VOLT_SEL; + sdhci_writel(host, val, ESDHC_PROCTL); + } + return 0; + default: + return 0; + } +} + #ifdef CONFIG_PM_SLEEP static u32 esdhc_proctl; static int esdhc_of_suspend(struct device *dev) @@ -708,6 +779,9 @@ static int sdhci_esdhc_probe(struct platform_device *pdev) host = sdhci_pltfm_init(pdev, &sdhci_esdhc_be_pdata, sizeof(struct sdhci_esdhc)); + host->mmc_host_ops.start_signal_voltage_switch = + esdhc_signal_voltage_switch; + if (IS_ERR(host)) return PTR_ERR(host); -- 2.1.0.27.g96db324
next prev parent reply other threads:[~2017-03-03 8:18 UTC|newest] Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top 2017-03-03 8:18 [v2, 0/7] Add SD UHS-I and eMMC HS200 support for eSDHC Yangbo Lu 2017-03-03 8:18 ` Yangbo Lu 2017-03-03 8:18 ` [v2, 1/7] mmc: sdhci-of-esdhc: add peripheral clock support Yangbo Lu 2017-03-03 8:18 ` Yangbo Lu 2017-03-03 8:18 ` Yangbo Lu [this message] 2017-03-03 8:18 ` [v2, 2/7] mmc: sdhci-of-esdhc: add support for signal voltage switch Yangbo Lu [not found] ` <1488529129-23560-1-git-send-email-yangbo.lu-3arQi8VN3Tc@public.gmane.org> 2017-03-03 8:18 ` [v2, 3/7] mmc: sdhci-of-esdhc: add tuning support Yangbo Lu 2017-03-03 8:18 ` Yangbo Lu 2017-03-03 8:18 ` [v2, 4/7] mmc: sdhci: add a quirk to restore delay in tuning Yangbo Lu 2017-03-03 8:18 ` Yangbo Lu 2017-03-23 7:03 ` Adrian Hunter 2017-03-23 7:03 ` Adrian Hunter 2017-03-27 8:05 ` Y.B. Lu 2017-03-27 8:05 ` Y.B. Lu 2017-03-03 8:18 ` [v2, 7/7] arm64: dts: ls1046ardb: add MMC HS200/UHS-1 modes support Yangbo Lu 2017-03-03 8:18 ` Yangbo Lu 2017-03-03 8:18 ` [v2, 5/7] mmc: sdhci-of-esdhc: add delay between tuning cycles Yangbo Lu 2017-03-03 8:18 ` Yangbo Lu 2017-03-03 8:18 ` [v2, 6/7] arm64: dts: ls1046a: add clocks property and compatible for eSDHC node Yangbo Lu 2017-03-03 8:18 ` Yangbo Lu 2017-03-09 2:22 ` [v2, 0/7] Add SD UHS-I and eMMC HS200 support for eSDHC Y.B. Lu 2017-03-09 2:22 ` Y.B. Lu 2017-03-17 3:01 ` Y.B. Lu 2017-03-17 3:01 ` Y.B. Lu
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1488529129-23560-3-git-send-email-yangbo.lu@nxp.com \ --to=yangbo.lu@nxp.com \ --cc=adrian.hunter@intel.com \ --cc=catalin.marinas@arm.com \ --cc=devicetree@vger.kernel.org \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-mmc@vger.kernel.org \ --cc=mark.rutland@arm.com \ --cc=robh+dt@kernel.org \ --cc=ulf.hansson@linaro.org \ --cc=will.deacon@arm.com \ --cc=xiaobo.xie@nxp.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.