2019-06-21 06:13:14

by Baolin Wang

[permalink] [raw]
Subject: [PATCH 0/3] Optimize voltage switch for the SD controller

This patch set is used to optimize voltage switch for the
Spreadtrum SD host controller.

Any comments are welcome. Thanks.

Baolin Wang (3):
mmc: sdhci-sprd: Add start_signal_voltage_switch ops
dt-bindings: mmc: sprd: Add pinctrl support
mmc: sdhci-sprd: Add pin control support for voltage switch

.../devicetree/bindings/mmc/sdhci-sprd.txt | 7 ++
drivers/mmc/host/sdhci-sprd.c | 78 ++++++++++++++++++++
2 files changed, 85 insertions(+)

--
1.7.9.5


2019-06-21 06:13:20

by Baolin Wang

[permalink] [raw]
Subject: [PATCH 1/3] mmc: sdhci-sprd: Add start_signal_voltage_switch ops

For Spreadtrum SD host controller, we can not use standard SD registers
to change and detect the I/O voltage signals, since our voltage regulator
for I/O is fixed in hardware, and no signals were connected to the SD
controller. Thus add Spreadtrum specific voltage switch ops to change
voltage instead of using standard SD host registers.

Signed-off-by: Baolin Wang <[email protected]>
---
drivers/mmc/host/sdhci-sprd.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)

diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c
index 024c3c5..8b23c88 100644
--- a/drivers/mmc/host/sdhci-sprd.c
+++ b/drivers/mmc/host/sdhci-sprd.c
@@ -403,6 +403,22 @@ static void sdhci_sprd_request(struct mmc_host *mmc, struct mmc_request *mrq)
sdhci_request(mmc, mrq);
}

+static int sdhci_sprd_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ int ret;
+
+ if (!IS_ERR(mmc->supply.vqmmc)) {
+ ret = mmc_regulator_set_vqmmc(mmc, ios);
+ if (ret) {
+ pr_err("%s: Switching signalling voltage failed\n",
+ mmc_hostname(mmc));
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
static void sdhci_sprd_hs400_enhanced_strobe(struct mmc_host *mmc,
struct mmc_ios *ios)
{
@@ -470,6 +486,14 @@ static int sdhci_sprd_probe(struct platform_device *pdev)
host->mmc_host_ops.request = sdhci_sprd_request;
host->mmc_host_ops.hs400_enhanced_strobe =
sdhci_sprd_hs400_enhanced_strobe;
+ /*
+ * We can not use the standard ops to change and detect the voltage
+ * signal for Spreadtrum SD host controller, since our voltage regulator
+ * for I/O is fixed in hardware, that means we do not need control
+ * the standard SD host controller to change the I/O voltage.
+ */
+ host->mmc_host_ops.start_signal_voltage_switch =
+ sdhci_sprd_voltage_switch;

host->mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED |
MMC_CAP_ERASE | MMC_CAP_CMD23;
--
1.7.9.5

2019-06-21 06:13:24

by Baolin Wang

[permalink] [raw]
Subject: [PATCH 2/3] dt-bindings: mmc: sprd: Add pinctrl support

When changing SD card voltage signal for Spreadtrum SD host controller,
it also need to switch related pin's state. Thus add pinctrl properties'
description in documentation.

Signed-off-by: Baolin Wang <[email protected]>
---
.../devicetree/bindings/mmc/sdhci-sprd.txt | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-sprd.txt b/Documentation/devicetree/bindings/mmc/sdhci-sprd.txt
index e675397..eb7eb1b 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-sprd.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-sprd.txt
@@ -19,6 +19,9 @@ Required properties:
Optional properties:
- assigned-clocks: the same with "sdio" clock
- assigned-clock-parents: the default parent of "sdio" clock
+- pinctrl-names: should be "default", "state_uhs"
+- pinctrl-0: should contain default/high speed pin control
+- pinctrl-1: should contain uhs mode pin control

PHY DLL delays are used to delay the data valid window, and align the window
to sampling clock. PHY DLL delays can be configured by following properties,
@@ -50,6 +53,10 @@ sdio0: sdio@20600000 {
assigned-clocks = <&ap_clk CLK_EMMC_2X>;
assigned-clock-parents = <&rpll CLK_RPLL_390M>;

+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&sd0_pins_default>;
+ pinctrl-1 = <&sd0_pins_uhs>;
+
sprd,phy-delay-sd-uhs-sdr104 = <0x3f 0x7f 0x2e 0x2e>;
bus-width = <8>;
non-removable;
--
1.7.9.5

2019-06-21 06:16:27

by Baolin Wang

[permalink] [raw]
Subject: [PATCH 3/3] mmc: sdhci-sprd: Add pin control support for voltage switch

For Spreadtrum SD card voltage switching, besides regulator setting,
it also need switch related pin's state to output corresponding voltage.

This patch adds pin control operation to support voltage switch.

Signed-off-by: Baolin Wang <[email protected]>
---
drivers/mmc/host/sdhci-sprd.c | 54 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)

diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c
index 8b23c88..6ee340a 100644
--- a/drivers/mmc/host/sdhci-sprd.c
+++ b/drivers/mmc/host/sdhci-sprd.c
@@ -12,6 +12,7 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
@@ -72,6 +73,9 @@ struct sdhci_sprd_host {
struct clk *clk_sdio;
struct clk *clk_enable;
struct clk *clk_2x_enable;
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *pins_uhs;
+ struct pinctrl_state *pins_default;
u32 base_rate;
int flags; /* backup of host attribute */
u32 phy_delay[MMC_TIMING_MMC_HS400 + 2];
@@ -405,6 +409,8 @@ static void sdhci_sprd_request(struct mmc_host *mmc, struct mmc_request *mrq)

static int sdhci_sprd_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios)
{
+ struct sdhci_host *host = mmc_priv(mmc);
+ struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host);
int ret;

if (!IS_ERR(mmc->supply.vqmmc)) {
@@ -416,6 +422,37 @@ static int sdhci_sprd_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios)
}
}

+ if (IS_ERR(sprd_host->pinctrl))
+ return 0;
+
+ switch (ios->signal_voltage) {
+ case MMC_SIGNAL_VOLTAGE_180:
+ ret = pinctrl_select_state(sprd_host->pinctrl,
+ sprd_host->pins_uhs);
+ if (ret) {
+ pr_err("%s: failed to select uhs pin state\n",
+ mmc_hostname(mmc));
+ return ret;
+ }
+ break;
+
+ default:
+ /* fall-through */
+ case MMC_SIGNAL_VOLTAGE_330:
+ ret = pinctrl_select_state(sprd_host->pinctrl,
+ sprd_host->pins_default);
+ if (ret) {
+ pr_err("%s: failed to select default pin state\n",
+ mmc_hostname(mmc));
+ return ret;
+ }
+ break;
+ }
+
+ /* Wait for 300 ~ 500 us for pin state stable */
+ usleep_range(300, 500);
+ sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+
return 0;
}

@@ -504,6 +541,23 @@ static int sdhci_sprd_probe(struct platform_device *pdev)
sprd_host = TO_SPRD_HOST(host);
sdhci_sprd_phy_param_parse(sprd_host, pdev->dev.of_node);

+ sprd_host->pinctrl = devm_pinctrl_get(&pdev->dev);
+ if (!IS_ERR(sprd_host->pinctrl)) {
+ sprd_host->pins_uhs =
+ pinctrl_lookup_state(sprd_host->pinctrl, "state_uhs");
+ if (IS_ERR(sprd_host->pins_uhs)) {
+ ret = PTR_ERR(sprd_host->pins_uhs);
+ goto pltfm_free;
+ }
+
+ sprd_host->pins_default =
+ pinctrl_lookup_state(sprd_host->pinctrl, "default");
+ if (IS_ERR(sprd_host->pins_default)) {
+ ret = PTR_ERR(sprd_host->pins_default);
+ goto pltfm_free;
+ }
+ }
+
clk = devm_clk_get(&pdev->dev, "sdio");
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
--
1.7.9.5

2019-07-01 15:17:22

by Adrian Hunter

[permalink] [raw]
Subject: Re: [PATCH 3/3] mmc: sdhci-sprd: Add pin control support for voltage switch

On 21/06/19 9:12 AM, Baolin Wang wrote:
> For Spreadtrum SD card voltage switching, besides regulator setting,
> it also need switch related pin's state to output corresponding voltage.
>
> This patch adds pin control operation to support voltage switch.
>
> Signed-off-by: Baolin Wang <[email protected]>

Acked-by: Adrian Hunter <[email protected]>

> ---
> drivers/mmc/host/sdhci-sprd.c | 54 +++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 54 insertions(+)
>
> diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c
> index 8b23c88..6ee340a 100644
> --- a/drivers/mmc/host/sdhci-sprd.c
> +++ b/drivers/mmc/host/sdhci-sprd.c
> @@ -12,6 +12,7 @@
> #include <linux/of.h>
> #include <linux/of_device.h>
> #include <linux/of_gpio.h>
> +#include <linux/pinctrl/consumer.h>
> #include <linux/platform_device.h>
> #include <linux/pm_runtime.h>
> #include <linux/regulator/consumer.h>
> @@ -72,6 +73,9 @@ struct sdhci_sprd_host {
> struct clk *clk_sdio;
> struct clk *clk_enable;
> struct clk *clk_2x_enable;
> + struct pinctrl *pinctrl;
> + struct pinctrl_state *pins_uhs;
> + struct pinctrl_state *pins_default;
> u32 base_rate;
> int flags; /* backup of host attribute */
> u32 phy_delay[MMC_TIMING_MMC_HS400 + 2];
> @@ -405,6 +409,8 @@ static void sdhci_sprd_request(struct mmc_host *mmc, struct mmc_request *mrq)
>
> static int sdhci_sprd_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios)
> {
> + struct sdhci_host *host = mmc_priv(mmc);
> + struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host);
> int ret;
>
> if (!IS_ERR(mmc->supply.vqmmc)) {
> @@ -416,6 +422,37 @@ static int sdhci_sprd_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios)
> }
> }
>
> + if (IS_ERR(sprd_host->pinctrl))
> + return 0;
> +
> + switch (ios->signal_voltage) {
> + case MMC_SIGNAL_VOLTAGE_180:
> + ret = pinctrl_select_state(sprd_host->pinctrl,
> + sprd_host->pins_uhs);
> + if (ret) {
> + pr_err("%s: failed to select uhs pin state\n",
> + mmc_hostname(mmc));
> + return ret;
> + }
> + break;
> +
> + default:
> + /* fall-through */
> + case MMC_SIGNAL_VOLTAGE_330:
> + ret = pinctrl_select_state(sprd_host->pinctrl,
> + sprd_host->pins_default);
> + if (ret) {
> + pr_err("%s: failed to select default pin state\n",
> + mmc_hostname(mmc));
> + return ret;
> + }
> + break;
> + }
> +
> + /* Wait for 300 ~ 500 us for pin state stable */
> + usleep_range(300, 500);
> + sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
> +
> return 0;
> }
>
> @@ -504,6 +541,23 @@ static int sdhci_sprd_probe(struct platform_device *pdev)
> sprd_host = TO_SPRD_HOST(host);
> sdhci_sprd_phy_param_parse(sprd_host, pdev->dev.of_node);
>
> + sprd_host->pinctrl = devm_pinctrl_get(&pdev->dev);
> + if (!IS_ERR(sprd_host->pinctrl)) {
> + sprd_host->pins_uhs =
> + pinctrl_lookup_state(sprd_host->pinctrl, "state_uhs");
> + if (IS_ERR(sprd_host->pins_uhs)) {
> + ret = PTR_ERR(sprd_host->pins_uhs);
> + goto pltfm_free;
> + }
> +
> + sprd_host->pins_default =
> + pinctrl_lookup_state(sprd_host->pinctrl, "default");
> + if (IS_ERR(sprd_host->pins_default)) {
> + ret = PTR_ERR(sprd_host->pins_default);
> + goto pltfm_free;
> + }
> + }
> +
> clk = devm_clk_get(&pdev->dev, "sdio");
> if (IS_ERR(clk)) {
> ret = PTR_ERR(clk);
>

2019-07-01 15:17:38

by Adrian Hunter

[permalink] [raw]
Subject: Re: [PATCH 1/3] mmc: sdhci-sprd: Add start_signal_voltage_switch ops

On 21/06/19 9:12 AM, Baolin Wang wrote:
> For Spreadtrum SD host controller, we can not use standard SD registers
> to change and detect the I/O voltage signals, since our voltage regulator
> for I/O is fixed in hardware, and no signals were connected to the SD
> controller. Thus add Spreadtrum specific voltage switch ops to change
> voltage instead of using standard SD host registers.
>
> Signed-off-by: Baolin Wang <[email protected]>

Acked-by: Adrian Hunter <[email protected]>

> ---
> drivers/mmc/host/sdhci-sprd.c | 24 ++++++++++++++++++++++++
> 1 file changed, 24 insertions(+)
>
> diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c
> index 024c3c5..8b23c88 100644
> --- a/drivers/mmc/host/sdhci-sprd.c
> +++ b/drivers/mmc/host/sdhci-sprd.c
> @@ -403,6 +403,22 @@ static void sdhci_sprd_request(struct mmc_host *mmc, struct mmc_request *mrq)
> sdhci_request(mmc, mrq);
> }
>
> +static int sdhci_sprd_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios)
> +{
> + int ret;
> +
> + if (!IS_ERR(mmc->supply.vqmmc)) {
> + ret = mmc_regulator_set_vqmmc(mmc, ios);
> + if (ret) {
> + pr_err("%s: Switching signalling voltage failed\n",
> + mmc_hostname(mmc));
> + return ret;
> + }
> + }
> +
> + return 0;
> +}
> +
> static void sdhci_sprd_hs400_enhanced_strobe(struct mmc_host *mmc,
> struct mmc_ios *ios)
> {
> @@ -470,6 +486,14 @@ static int sdhci_sprd_probe(struct platform_device *pdev)
> host->mmc_host_ops.request = sdhci_sprd_request;
> host->mmc_host_ops.hs400_enhanced_strobe =
> sdhci_sprd_hs400_enhanced_strobe;
> + /*
> + * We can not use the standard ops to change and detect the voltage
> + * signal for Spreadtrum SD host controller, since our voltage regulator
> + * for I/O is fixed in hardware, that means we do not need control
> + * the standard SD host controller to change the I/O voltage.
> + */
> + host->mmc_host_ops.start_signal_voltage_switch =
> + sdhci_sprd_voltage_switch;
>
> host->mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED |
> MMC_CAP_ERASE | MMC_CAP_CMD23;
>

2019-07-08 16:34:50

by Ulf Hansson

[permalink] [raw]
Subject: Re: [PATCH 0/3] Optimize voltage switch for the SD controller

On Fri, 21 Jun 2019 at 08:12, Baolin Wang <[email protected]> wrote:
>
> This patch set is used to optimize voltage switch for the
> Spreadtrum SD host controller.
>
> Any comments are welcome. Thanks.
>
> Baolin Wang (3):
> mmc: sdhci-sprd: Add start_signal_voltage_switch ops
> dt-bindings: mmc: sprd: Add pinctrl support
> mmc: sdhci-sprd: Add pin control support for voltage switch
>
> .../devicetree/bindings/mmc/sdhci-sprd.txt | 7 ++
> drivers/mmc/host/sdhci-sprd.c | 78 ++++++++++++++++++++
> 2 files changed, 85 insertions(+)
>
> --
> 1.7.9.5
>

Applied for next, thanks!

Kind regards
Uffe