From: Arindam Nath <arindam.nath@amd.com>
To: cjb@laptop.org
Cc: prakity@marvell.com, zhangfei.gao@gmail.com,
subhashj@codeaurora.org, linux-mmc@vger.kernel.org,
henry.su@amd.com, aaron.lu@amd.com, anath.amd@gmail.com,
Arindam Nath <arindam.nath@amd.com>
Subject: [PATCH v4 10/15] mmc: sdhci: add support for programmable clock mode
Date: Thu, 5 May 2011 12:19:06 +0530 [thread overview]
Message-ID: <1304578151-1775-11-git-send-email-arindam.nath@amd.com> (raw)
In-Reply-To: <1304578151-1775-1-git-send-email-arindam.nath@amd.com>
Host Controller v3.00 supports programmable clock mode as an optional
feature. The support for this mode is indicated by non-zero value in
bits 48-55 of the Capabilities register. If supported, the actual
value of Clock Multiplier is one more than the value provided in the
bit fields. We only set Clock Generator Select (bit 5) and SDCLK
Frequency Select (bits 8-15) of the Clock Control register in case
Preset Value Enable is not set, otherwise these fields are automatically
set by the Host Controller based on the UHS mode selected. Also, since
the maximum and minimum clock frequency in this mode can be
(Base Clock * Clock Mul) and (Base Clock * Clock Mul)/1024 respectively,
f_max and f_min have been recalculated to reflect this change.
Signed-off-by: Arindam Nath <arindam.nath@amd.com>
Reviewed-by: Philip Rakity <prakity@marvell.com>
Tested-by: Philip Rakity <prakity@marvell.com>
---
drivers/mmc/host/sdhci.c | 81 ++++++++++++++++++++++++++++++++++++--------
drivers/mmc/host/sdhci.h | 3 ++
include/linux/mmc/sdhci.h | 1 +
3 files changed, 70 insertions(+), 15 deletions(-)
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index cb767a0..8ed2e1b 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1013,8 +1013,8 @@ static void sdhci_finish_command(struct sdhci_host *host)
static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
{
- int div;
- u16 clk;
+ int div = 0; /* Initialized for compiler warning */
+ u16 clk = 0;
unsigned long timeout;
if (clock == host->clock)
@@ -1032,14 +1032,45 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
goto out;
if (host->version >= SDHCI_SPEC_300) {
- /* Version 3.00 divisors must be a multiple of 2. */
- if (host->max_clk <= clock)
- div = 1;
- else {
- for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) {
- if ((host->max_clk / div) <= clock)
- break;
+ /*
+ * Check if the Host Controller supports Programmable Clock
+ * Mode.
+ */
+ if (host->clk_mul) {
+ u16 ctrl;
+
+ /*
+ * We need to figure out whether the Host Driver needs
+ * to select Programmable Clock Mode, or the value can
+ * be set automatically by the Host Controller based on
+ * the Preset Value registers.
+ */
+ ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ if (!(ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
+ for (div = 1; div <= 1024; div++) {
+ if (((host->max_clk * host->clk_mul) /
+ div) <= clock)
+ break;
+ }
+ /*
+ * Set Programmable Clock Mode in the Clock
+ * Control register.
+ */
+ clk = SDHCI_PROG_CLOCK_MODE;
+ div--;
+ }
+ } else {
+ /* Version 3.00 divisors must be a multiple of 2. */
+ if (host->max_clk <= clock)
+ div = 1;
+ else {
+ for (div = 2; div < SDHCI_MAX_DIV_SPEC_300;
+ div += 2) {
+ if ((host->max_clk / div) <= clock)
+ break;
+ }
}
+ div >>= 1;
}
} else {
/* Version 2.00 divisors must be a power of 2. */
@@ -1047,10 +1078,10 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
if ((host->max_clk / div) <= clock)
break;
}
+ div >>= 1;
}
- div >>= 1;
- clk = (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
+ clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
<< SDHCI_DIVIDER_HI_SHIFT;
clk |= SDHCI_CLOCK_INT_EN;
@@ -2314,17 +2345,37 @@ int sdhci_add_host(struct sdhci_host *host)
host->timeout_clk *= 1000;
/*
+ * In case of Host Controller v3.00, find out whether clock
+ * multiplier is supported.
+ */
+ host->clk_mul = (caps[1] & SDHCI_CLOCK_MUL_MASK) >>
+ SDHCI_CLOCK_MUL_SHIFT;
+
+ /*
+ * In case the value in Clock Multiplier is 0, then programmable
+ * clock mode is not supported, otherwise the actual clock
+ * multiplier is one more than the value of Clock Multiplier
+ * in the Capabilities Register.
+ */
+ if (host->clk_mul)
+ host->clk_mul += 1;
+
+ /*
* Set host parameters.
*/
mmc->ops = &sdhci_ops;
+ mmc->f_max = host->max_clk;
if (host->ops->get_min_clock)
mmc->f_min = host->ops->get_min_clock(host);
- else if (host->version >= SDHCI_SPEC_300)
- mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;
- else
+ else if (host->version >= SDHCI_SPEC_300) {
+ if (host->clk_mul) {
+ mmc->f_min = (host->max_clk * host->clk_mul) / 1024;
+ mmc->f_max = host->max_clk * host->clk_mul;
+ } else
+ mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;
+ } else
mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
- mmc->f_max = host->max_clk;
mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE;
/*
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index b32fc32..0208164 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -101,6 +101,7 @@
#define SDHCI_DIV_MASK 0xFF
#define SDHCI_DIV_MASK_LEN 8
#define SDHCI_DIV_HI_MASK 0x300
+#define SDHCI_PROG_CLOCK_MODE 0x0020
#define SDHCI_CLOCK_CARD_EN 0x0004
#define SDHCI_CLOCK_INT_STABLE 0x0002
#define SDHCI_CLOCK_INT_EN 0x0001
@@ -191,6 +192,8 @@
#define SDHCI_DRIVER_TYPE_C 0x00000020
#define SDHCI_DRIVER_TYPE_D 0x00000040
#define SDHCI_USE_SDR50_TUNING 0x00002000
+#define SDHCI_CLOCK_MUL_MASK 0x00FF0000
+#define SDHCI_CLOCK_MUL_SHIFT 16
#define SDHCI_CAPABILITIES_1 0x44
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index b74c853..a88a799 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -117,6 +117,7 @@ struct sdhci_host {
unsigned int max_clk; /* Max possible freq (MHz) */
unsigned int timeout_clk; /* Timeout freq (KHz) */
+ unsigned int clk_mul; /* Clock Muliplier value */
unsigned int clock; /* Current clock (MHz) */
u8 pwr; /* Current voltage */
--
1.7.1
next prev parent reply other threads:[~2011-05-05 6:52 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-05-05 6:48 [PATCH v4 00/15] add support for host controller v3.00 Arindam Nath
2011-05-05 6:48 ` [PATCH v4 01/15] mmc: sd: add support for signal voltage switch procedure Arindam Nath
2011-05-06 10:36 ` zhangfei gao
2011-05-11 3:34 ` Chris Ball
2011-05-05 6:48 ` [PATCH v4 02/15] mmc: sd: query function modes for uhs cards Arindam Nath
2011-05-06 10:37 ` zhangfei gao
2011-05-11 3:34 ` Chris Ball
2011-05-05 6:48 ` [PATCH v4 03/15] mmc: sd: add support for driver type selection Arindam Nath
2011-05-06 10:37 ` zhangfei gao
2011-05-11 3:34 ` Chris Ball
2011-05-05 6:49 ` [PATCH v4 04/15] mmc: sdhci: reset sdclk before setting high speed enable Arindam Nath
2011-05-06 10:38 ` zhangfei gao
2011-05-11 3:36 ` Chris Ball
2011-05-05 6:49 ` [PATCH v4 05/15] mmc: sd: add support for uhs bus speed mode selection Arindam Nath
2011-05-06 10:41 ` zhangfei gao
2011-05-11 3:36 ` Chris Ball
2011-05-05 6:49 ` [PATCH v4 06/15] mmc: sd: set current limit for uhs cards Arindam Nath
2011-05-06 10:38 ` zhangfei gao
2011-05-11 3:37 ` Chris Ball
2011-05-05 6:49 ` [PATCH v4 07/15] mmc: sd: report correct speed and capacity of " Arindam Nath
2011-05-06 10:39 ` zhangfei gao
2011-05-11 3:37 ` Chris Ball
2011-05-05 6:49 ` [PATCH v4 08/15] mmc: sd: add support for tuning during uhs initialization Arindam Nath
2011-05-06 10:39 ` zhangfei gao
2011-05-11 3:38 ` Chris Ball
2011-05-05 6:49 ` [PATCH v4 09/15] mmc: sdhci: enable preset value after " Arindam Nath
2011-05-06 10:40 ` zhangfei gao
2011-05-11 3:38 ` Chris Ball
2011-05-05 6:49 ` Arindam Nath [this message]
2011-05-06 10:40 ` [PATCH v4 10/15] mmc: sdhci: add support for programmable clock mode zhangfei gao
2011-05-11 3:39 ` Chris Ball
2011-05-05 6:49 ` [PATCH v4 11/15] mmc: sdhci: add support for retuning mode 1 Arindam Nath
2011-05-06 10:40 ` zhangfei gao
2011-05-11 3:39 ` Chris Ball
2011-05-05 6:49 ` [PATCH v4 12/15] sdhci pxa add platform specific code for UHS signaling Arindam Nath
2011-05-11 1:54 ` Chris Ball
2011-05-11 8:48 ` zhangfei gao
2011-05-11 8:52 ` Philip Rakity
2011-05-11 9:28 ` zhangfei gao
2011-05-11 9:47 ` Philip Rakity
2011-05-12 1:53 ` Philip Rakity
2011-05-13 8:03 ` zhangfei gao
2011-05-15 21:42 ` Philip Rakity
2011-05-16 5:57 ` zhangfei gao
2011-05-05 6:49 ` [PATCH v4 13/15] mmc eMMC signal voltage does not use CMD11 Arindam Nath
2011-05-11 1:51 ` Chris Ball
2011-05-11 9:19 ` zhangfei gao
2011-05-11 15:01 ` Philip Rakity
2011-05-12 1:53 ` Philip Rakity
2011-05-05 6:49 ` [PATCH v4 14/15] sdhci add hooks for UHS setting by platform specific code Arindam Nath
2011-05-05 6:49 ` [PATCH v4 15/15] mmc add support for eMMC Dual Data Rate Arindam Nath
2011-05-05 8:18 ` [PATCH v4 00/15] add support for host controller v3.00 Nath, Arindam
2011-05-11 3:43 ` Chris Ball
2011-05-11 6:13 ` Nath, Arindam
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=1304578151-1775-11-git-send-email-arindam.nath@amd.com \
--to=arindam.nath@amd.com \
--cc=aaron.lu@amd.com \
--cc=anath.amd@gmail.com \
--cc=cjb@laptop.org \
--cc=henry.su@amd.com \
--cc=linux-mmc@vger.kernel.org \
--cc=prakity@marvell.com \
--cc=subhashj@codeaurora.org \
--cc=zhangfei.gao@gmail.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).