Skip to content

Commit 29ca763

Browse files
wangbaolin719storulf
authored andcommitted
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]> Acked-by: Adrian Hunter <[email protected]> Signed-off-by: Ulf Hansson <[email protected]>
1 parent f97ee8f commit 29ca763

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed

drivers/mmc/host/sdhci-sprd.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/of.h>
1313
#include <linux/of_device.h>
1414
#include <linux/of_gpio.h>
15+
#include <linux/pinctrl/consumer.h>
1516
#include <linux/platform_device.h>
1617
#include <linux/pm_runtime.h>
1718
#include <linux/regulator/consumer.h>
@@ -72,6 +73,9 @@ struct sdhci_sprd_host {
7273
struct clk *clk_sdio;
7374
struct clk *clk_enable;
7475
struct clk *clk_2x_enable;
76+
struct pinctrl *pinctrl;
77+
struct pinctrl_state *pins_uhs;
78+
struct pinctrl_state *pins_default;
7579
u32 base_rate;
7680
int flags; /* backup of host attribute */
7781
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)
405409

406410
static int sdhci_sprd_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios)
407411
{
412+
struct sdhci_host *host = mmc_priv(mmc);
413+
struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host);
408414
int ret;
409415

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

425+
if (IS_ERR(sprd_host->pinctrl))
426+
return 0;
427+
428+
switch (ios->signal_voltage) {
429+
case MMC_SIGNAL_VOLTAGE_180:
430+
ret = pinctrl_select_state(sprd_host->pinctrl,
431+
sprd_host->pins_uhs);
432+
if (ret) {
433+
pr_err("%s: failed to select uhs pin state\n",
434+
mmc_hostname(mmc));
435+
return ret;
436+
}
437+
break;
438+
439+
default:
440+
/* fall-through */
441+
case MMC_SIGNAL_VOLTAGE_330:
442+
ret = pinctrl_select_state(sprd_host->pinctrl,
443+
sprd_host->pins_default);
444+
if (ret) {
445+
pr_err("%s: failed to select default pin state\n",
446+
mmc_hostname(mmc));
447+
return ret;
448+
}
449+
break;
450+
}
451+
452+
/* Wait for 300 ~ 500 us for pin state stable */
453+
usleep_range(300, 500);
454+
sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
455+
419456
return 0;
420457
}
421458

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

544+
sprd_host->pinctrl = devm_pinctrl_get(&pdev->dev);
545+
if (!IS_ERR(sprd_host->pinctrl)) {
546+
sprd_host->pins_uhs =
547+
pinctrl_lookup_state(sprd_host->pinctrl, "state_uhs");
548+
if (IS_ERR(sprd_host->pins_uhs)) {
549+
ret = PTR_ERR(sprd_host->pins_uhs);
550+
goto pltfm_free;
551+
}
552+
553+
sprd_host->pins_default =
554+
pinctrl_lookup_state(sprd_host->pinctrl, "default");
555+
if (IS_ERR(sprd_host->pins_default)) {
556+
ret = PTR_ERR(sprd_host->pins_default);
557+
goto pltfm_free;
558+
}
559+
}
560+
507561
clk = devm_clk_get(&pdev->dev, "sdio");
508562
if (IS_ERR(clk)) {
509563
ret = PTR_ERR(clk);

0 commit comments

Comments
 (0)