From: philipspatches@gmail.com
To: cjb@laptop.org, linux-mmc@vger.kernel.org, aaron.lu@amd.com,
mark.brown314@gmail.com
Cc: Philip Rakity <prakity@marvell.com>
Subject: [PATCH 1/2] mmc: Add support for Signal (vccq) Voltage Switching using Regulators
Date: Fri, 8 Jun 2012 12:26:25 -0700 [thread overview]
Message-ID: <1339183585-21723-1-git-send-email-prakity@marvell.com> (raw)
In-Reply-To: <prakity@marvell.com>
From: Philip Rakity <prakity@marvell.com>
The SD Host Controller may require a regulator to support signal
and voltage switching. Curently we support voltage (vmmc) but not
signal changing via a regulator. Add this support.
If a regulator is supported and voltage switching to 1.8V is
supported then use the vmmc regulator to disable the voltage to
the core if 1.8 signal voltage switching fails.
Signed-off-by: Philip Rakity <prakity@marvell.com>
---
drivers/mmc/host/sdhci.c | 88 ++++++++++++++++++++++++++++++++++-----------
include/linux/mmc/sdhci.h | 3 +-
2 files changed, 69 insertions(+), 22 deletions(-)
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 417851f..248f68b 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1584,6 +1584,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
u8 pwr;
u16 clk, ctrl;
u32 present_state;
+ int ret;
/*
* Signal Voltage Switching is only applicable for Host Controllers
@@ -1604,6 +1605,15 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
/* Wait for 5ms */
usleep_range(5000, 5500);
+ if (host->vmmcvccq) {
+ ret = regulator_set_voltage(host->vmmcvccq,
+ 3300000, 3300000);
+ if (ret) {
+ pr_info(DRIVER_NAME ": Switching to 3.3V "
+ "signalling voltage failed\n");
+ return -EIO;
+ }
+ }
/* 3.3V regulator output should be stable within 5 ms */
ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
@@ -1629,29 +1639,43 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
* Enable 1.8V Signal Enable in the Host Control2
* register
*/
- ctrl |= SDHCI_CTRL_VDD_180;
- sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
-
- /* Wait for 5ms */
- usleep_range(5000, 5500);
-
- ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- if (ctrl & SDHCI_CTRL_VDD_180) {
- /* Provide SDCLK again and wait for 1ms*/
- clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
- clk |= SDHCI_CLOCK_CARD_EN;
- sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
- usleep_range(1000, 1500);
+ ret = 0;
+ if (host->vmmcvccq) {
+ ret = regulator_set_voltage(host->vmmcvccq,
+ 1800000, 1800000);
+ }
- /*
- * If DAT[3:0] level is 1111b, then the card
- * was successfully switched to 1.8V signaling.
- */
- present_state = sdhci_readl(host,
+ if (!ret) {
+ ctrl |= SDHCI_CTRL_VDD_180;
+ sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+
+ /* Wait for 5ms */
+ usleep_range(5000, 5500);
+
+ ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ if (ctrl & SDHCI_CTRL_VDD_180) {
+ /* Provide SDCLK again */
+ /* and wait for 1ms*/
+ clk = sdhci_readw(host,
+ SDHCI_CLOCK_CONTROL);
+ clk |= SDHCI_CLOCK_CARD_EN;
+ sdhci_writew(host, clk,
+ SDHCI_CLOCK_CONTROL);
+ usleep_range(1000, 1500);
+
+ /*
+ * If DAT[3:0] level is 1111b,
+ * then the card
+ * was successfully switched
+ * to 1.8V signaling.
+ */
+ present_state = sdhci_readl(host,
SDHCI_PRESENT_STATE);
- if ((present_state & SDHCI_DATA_LVL_MASK) ==
- SDHCI_DATA_LVL_MASK)
- return 0;
+ if ((present_state &
+ SDHCI_DATA_LVL_MASK) ==
+ SDHCI_DATA_LVL_MASK)
+ return 0;
+ }
}
}
@@ -1663,11 +1687,15 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
pwr = sdhci_readb(host, SDHCI_POWER_CONTROL);
pwr &= ~SDHCI_POWER_ON;
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+ if (host->vmmc)
+ regulator_disable(host->vmmc);
/* Wait for 1ms as per the spec */
usleep_range(1000, 1500);
pwr |= SDHCI_POWER_ON;
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+ if (host->vmmc)
+ regulator_enable(host->vmmc);
pr_info(DRIVER_NAME ": Switching to 1.8V signalling "
"voltage failed, retrying with S18R set to 0\n");
@@ -2784,6 +2812,19 @@ int sdhci_add_host(struct sdhci_host *host)
mmc_card_is_removable(mmc))
mmc->caps |= MMC_CAP_NEEDS_POLL;
+ /* if vccq regulator and no 1.8V signaling no UHS */
+ host->vmmcvccq = regulator_get(mmc_dev(mmc), "vmmcvccq");
+ if (IS_ERR(host->vmmcvccq)) {
+ printk(KERN_INFO "%s: no vmmcvccq regulator found\n",
+ mmc_hostname(mmc));
+ host->vmmcvccq = NULL;
+ } else if (regulator_is_supported_voltage(host->vmmcvccq,
+ 1800000, 1800000)) {
+ regulator_enable(host->vmmcvccq);
+ } else
+ caps[1] &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
+ SDHCI_SUPPORT_DDR50);
+
/* Any UHS-I mode in caps implies SDR12 and SDR25 support. */
if (caps[1] & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
SDHCI_SUPPORT_DDR50))
@@ -3108,6 +3149,11 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
if (host->vmmc)
regulator_put(host->vmmc);
+ if (host->vmmcvccq) {
+ regulator_disable(host->vmmcvccq);
+ regulator_put(host->vmmcvccq);
+ }
+
kfree(host->adma_desc);
kfree(host->align_buffer);
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index 560fe22..67906bd 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -98,7 +98,8 @@ struct sdhci_host {
const struct sdhci_ops *ops; /* Low level hw interface */
- struct regulator *vmmc; /* Power regulator */
+ struct regulator *vmmc; /* Power regulator (vcc or vdd) */
+ struct regulator *vmmcvccq; /* Signal regulator (vccq) */
/* Internal data */
struct mmc_host *mmc; /* MMC structure */
--
1.7.0.4
reply other threads:[~2012-06-08 19:26 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=1339183585-21723-1-git-send-email-prakity@marvell.com \
--to=philipspatches@gmail.com \
--cc=aaron.lu@amd.com \
--cc=cjb@laptop.org \
--cc=linux-mmc@vger.kernel.org \
--cc=mark.brown314@gmail.com \
--cc=prakity@marvell.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: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).