On Mon, Aug 16, 2010 at 3:27 PM, Matt Fleming <matt@xxxxxxxxxxxxxxxxx> wrote: > On Mon, Aug 16, 2010 at 07:54:14PM +0100, David Vrabel wrote: >> Matt Fleming wrote: >> > >> > Sorry, I did mean to reply to this sooner but I've been travelling. Yeah >> > David, you're right. Zhangfei, have you confused the Programmable Clock >> > Mode in the 3.00 spec here with 10-bit Divided Clock Mode? >> > >> > Both 8-bit Divided Clock Mode and 10-bit Divided Clock Mode require the >> > divisor to be a power of two. >> >> The power-of-two requirement only applies to 2.00 controller. From >> section 2.2.14 of the spec. >> >> "(2) 10-bit Divided Clock Mode >> Host Controller Version 3.00 supports this mandatory mode instead of >> the 8-bit Divided Clock Mode. The length of divider is extended to >> 10bits and all divider values shall be supported." >> >> 3.00 dividers can be any multiple of two. > > Yep, you're right. I misread the spec. My bad. > David Thanks for your carefully review, my mistake. update the patch to distinguish spec 2.0 and 3.0, help review again. >From 9701da8440b847d8e061107fa6d25bd77698e577 Mon Sep 17 00:00:00 2001 From: Zhangfei Gao <zgao6@xxxxxxxxxxx> Date: Fri, 6 Aug 2010 07:10:01 +0800 Subject: [PATCH] sdhci: support 10-bit divided clock Mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Matt Fleming <matt@xxxxxxxxxxxxxxxxx> Cc: Michał Mirosław <mirqus@xxxxxxxxx> Cc: David Vrabel <david.vrabel@xxxxxxx> Signed-off-by: Zhangfei Gao <zgao6@xxxxxxxxxxx> --- drivers/mmc/host/sdhci.c | 22 +++++++++++++++++----- drivers/mmc/host/sdhci.h | 5 +++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 913555e..7ed6f1c 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1001,13 +1001,25 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) if (clock == 0) goto out; - for (div = 1;div < 256;div *= 2) { - if ((host->max_clk / div) <= clock) - break; + if (host->version >= SDHCI_SPEC_300) { + if(host->max_clk <= clock) + div = 1; + else { + for (div = 2; div < 2046; div += 2) { + if ((host->max_clk / div) <= clock) + break; + } + } + } else { + for (div = 1;div < 256;div *= 2) { + if ((host->max_clk / div) <= clock) + break; + } } div >>= 1; - clk = div << 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; sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); @@ -1707,7 +1719,7 @@ int sdhci_add_host(struct sdhci_host *host) host->version = sdhci_readw(host, SDHCI_HOST_VERSION); host->version = (host->version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT; - if (host->version > SDHCI_SPEC_200) { + if (host->version > SDHCI_SPEC_300) { printk(KERN_ERR "%s: Unknown controller version (%d). " "You may experience problems.\n", mmc_hostname(mmc), host->version); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 036cfae..50860dc 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -86,6 +86,10 @@ #define SDHCI_CLOCK_CONTROL 0x2C #define SDHCI_DIVIDER_SHIFT 8 +#define SDHCI_DIVIDER_HI_SHIFT 6 +#define SDHCI_DIV_MASK 0xFF +#define SDHCI_DIV_MASK_LEN 8 +#define SDHCI_DIV_HI_MASK 0x300 #define SDHCI_CLOCK_CARD_EN 0x0004 #define SDHCI_CLOCK_INT_STABLE 0x0002 #define SDHCI_CLOCK_INT_EN 0x0001 @@ -178,6 +182,7 @@ #define SDHCI_SPEC_VER_SHIFT 0 #define SDHCI_SPEC_100 0 #define SDHCI_SPEC_200 1 +#define SDHCI_SPEC_300 2 struct sdhci_ops; -- 1.7.0.4
From 9701da8440b847d8e061107fa6d25bd77698e577 Mon Sep 17 00:00:00 2001 From: Zhangfei Gao <zgao6@xxxxxxxxxxx> Date: Fri, 6 Aug 2010 07:10:01 +0800 Subject: [PATCH] sdhci: support 10-bit divided clock Mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Matt Fleming <matt@xxxxxxxxxxxxxxxxx> Cc: Michał Mirosław <mirqus@xxxxxxxxx> Cc: David Vrabel <david.vrabel@xxxxxxx> Signed-off-by: Zhangfei Gao <zgao6@xxxxxxxxxxx> --- drivers/mmc/host/sdhci.c | 22 +++++++++++++++++----- drivers/mmc/host/sdhci.h | 5 +++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 913555e..7ed6f1c 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1001,13 +1001,25 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) if (clock == 0) goto out; - for (div = 1;div < 256;div *= 2) { - if ((host->max_clk / div) <= clock) - break; + if (host->version >= SDHCI_SPEC_300) { + if(host->max_clk <= clock) + div = 1; + else { + for (div = 2; div < 2046; div += 2) { + if ((host->max_clk / div) <= clock) + break; + } + } + } else { + for (div = 1;div < 256;div *= 2) { + if ((host->max_clk / div) <= clock) + break; + } } div >>= 1; - clk = div << 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; sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); @@ -1707,7 +1719,7 @@ int sdhci_add_host(struct sdhci_host *host) host->version = sdhci_readw(host, SDHCI_HOST_VERSION); host->version = (host->version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT; - if (host->version > SDHCI_SPEC_200) { + if (host->version > SDHCI_SPEC_300) { printk(KERN_ERR "%s: Unknown controller version (%d). " "You may experience problems.\n", mmc_hostname(mmc), host->version); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 036cfae..50860dc 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -86,6 +86,10 @@ #define SDHCI_CLOCK_CONTROL 0x2C #define SDHCI_DIVIDER_SHIFT 8 +#define SDHCI_DIVIDER_HI_SHIFT 6 +#define SDHCI_DIV_MASK 0xFF +#define SDHCI_DIV_MASK_LEN 8 +#define SDHCI_DIV_HI_MASK 0x300 #define SDHCI_CLOCK_CARD_EN 0x0004 #define SDHCI_CLOCK_INT_STABLE 0x0002 #define SDHCI_CLOCK_INT_EN 0x0001 @@ -178,6 +182,7 @@ #define SDHCI_SPEC_VER_SHIFT 0 #define SDHCI_SPEC_100 0 #define SDHCI_SPEC_200 1 +#define SDHCI_SPEC_300 2 struct sdhci_ops; -- 1.7.0.4