Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <baolin.wang@linaro.org>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>

authored by

Baolin Wang and committed by
Ulf Hansson
29ca763f f97ee8f5

+54
+54
drivers/mmc/host/sdhci-sprd.c
··· 12 12 #include <linux/of.h> 13 13 #include <linux/of_device.h> 14 14 #include <linux/of_gpio.h> 15 + #include <linux/pinctrl/consumer.h> 15 16 #include <linux/platform_device.h> 16 17 #include <linux/pm_runtime.h> 17 18 #include <linux/regulator/consumer.h> ··· 73 72 struct clk *clk_sdio; 74 73 struct clk *clk_enable; 75 74 struct clk *clk_2x_enable; 75 + struct pinctrl *pinctrl; 76 + struct pinctrl_state *pins_uhs; 77 + struct pinctrl_state *pins_default; 76 78 u32 base_rate; 77 79 int flags; /* backup of host attribute */ 78 80 u32 phy_delay[MMC_TIMING_MMC_HS400 + 2]; ··· 409 405 410 406 static int sdhci_sprd_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios) 411 407 { 408 + struct sdhci_host *host = mmc_priv(mmc); 409 + struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host); 412 410 int ret; 413 411 414 412 if (!IS_ERR(mmc->supply.vqmmc)) { ··· 421 415 return ret; 422 416 } 423 417 } 418 + 419 + if (IS_ERR(sprd_host->pinctrl)) 420 + return 0; 421 + 422 + switch (ios->signal_voltage) { 423 + case MMC_SIGNAL_VOLTAGE_180: 424 + ret = pinctrl_select_state(sprd_host->pinctrl, 425 + sprd_host->pins_uhs); 426 + if (ret) { 427 + pr_err("%s: failed to select uhs pin state\n", 428 + mmc_hostname(mmc)); 429 + return ret; 430 + } 431 + break; 432 + 433 + default: 434 + /* fall-through */ 435 + case MMC_SIGNAL_VOLTAGE_330: 436 + ret = pinctrl_select_state(sprd_host->pinctrl, 437 + sprd_host->pins_default); 438 + if (ret) { 439 + pr_err("%s: failed to select default pin state\n", 440 + mmc_hostname(mmc)); 441 + return ret; 442 + } 443 + break; 444 + } 445 + 446 + /* Wait for 300 ~ 500 us for pin state stable */ 447 + usleep_range(300, 500); 448 + sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 424 449 425 450 return 0; 426 451 } ··· 540 503 541 504 sprd_host = TO_SPRD_HOST(host); 542 505 sdhci_sprd_phy_param_parse(sprd_host, pdev->dev.of_node); 506 + 507 + sprd_host->pinctrl = devm_pinctrl_get(&pdev->dev); 508 + if (!IS_ERR(sprd_host->pinctrl)) { 509 + sprd_host->pins_uhs = 510 + pinctrl_lookup_state(sprd_host->pinctrl, "state_uhs"); 511 + if (IS_ERR(sprd_host->pins_uhs)) { 512 + ret = PTR_ERR(sprd_host->pins_uhs); 513 + goto pltfm_free; 514 + } 515 + 516 + sprd_host->pins_default = 517 + pinctrl_lookup_state(sprd_host->pinctrl, "default"); 518 + if (IS_ERR(sprd_host->pins_default)) { 519 + ret = PTR_ERR(sprd_host->pins_default); 520 + goto pltfm_free; 521 + } 522 + } 543 523 544 524 clk = devm_clk_get(&pdev->dev, "sdio"); 545 525 if (IS_ERR(clk)) {