aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/host/sdhci.c81
-rw-r--r--drivers/mmc/host/sdhci.h3
-rw-r--r--include/linux/mmc/sdhci.h1
3 files changed, 70 insertions, 15 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index a1ab22415883..07cca557c4b5 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)
1013 1013
1014static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 1014static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
1015{ 1015{
1016 int div; 1016 int div = 0; /* Initialized for compiler warning */
1017 u16 clk; 1017 u16 clk = 0;
1018 unsigned long timeout; 1018 unsigned long timeout;
1019 1019
1020 if (clock == host->clock) 1020 if (clock == host->clock)
@@ -1032,14 +1032,45 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
1032 goto out; 1032 goto out;
1033 1033
1034 if (host->version >= SDHCI_SPEC_300) { 1034 if (host->version >= SDHCI_SPEC_300) {
1035 /* Version 3.00 divisors must be a multiple of 2. */ 1035 /*
1036 if (host->max_clk <= clock) 1036 * Check if the Host Controller supports Programmable Clock
1037 div = 1; 1037 * Mode.
1038 else { 1038 */
1039 for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) { 1039 if (host->clk_mul) {
1040 if ((host->max_clk / div) <= clock) 1040 u16 ctrl;
1041 break; 1041
1042 /*
1043 * We need to figure out whether the Host Driver needs
1044 * to select Programmable Clock Mode, or the value can
1045 * be set automatically by the Host Controller based on
1046 * the Preset Value registers.
1047 */
1048 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
1049 if (!(ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
1050 for (div = 1; div <= 1024; div++) {
1051 if (((host->max_clk * host->clk_mul) /
1052 div) <= clock)
1053 break;
1054 }
1055 /*
1056 * Set Programmable Clock Mode in the Clock
1057 * Control register.
1058 */
1059 clk = SDHCI_PROG_CLOCK_MODE;
1060 div--;
1061 }
1062 } else {
1063 /* Version 3.00 divisors must be a multiple of 2. */
1064 if (host->max_clk <= clock)
1065 div = 1;
1066 else {
1067 for (div = 2; div < SDHCI_MAX_DIV_SPEC_300;
1068 div += 2) {
1069 if ((host->max_clk / div) <= clock)
1070 break;
1071 }
1042 } 1072 }
1073 div >>= 1;
1043 } 1074 }
1044 } else { 1075 } else {
1045 /* Version 2.00 divisors must be a power of 2. */ 1076 /* 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)
1047 if ((host->max_clk / div) <= clock) 1078 if ((host->max_clk / div) <= clock)
1048 break; 1079 break;
1049 } 1080 }
1081 div >>= 1;
1050 } 1082 }
1051 div >>= 1;
1052 1083
1053 clk = (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; 1084 clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
1054 clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) 1085 clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
1055 << SDHCI_DIVIDER_HI_SHIFT; 1086 << SDHCI_DIVIDER_HI_SHIFT;
1056 clk |= SDHCI_CLOCK_INT_EN; 1087 clk |= SDHCI_CLOCK_INT_EN;
@@ -2308,17 +2339,37 @@ int sdhci_add_host(struct sdhci_host *host)
2308 host->timeout_clk *= 1000; 2339 host->timeout_clk *= 1000;
2309 2340
2310 /* 2341 /*
2342 * In case of Host Controller v3.00, find out whether clock
2343 * multiplier is supported.
2344 */
2345 host->clk_mul = (caps[1] & SDHCI_CLOCK_MUL_MASK) >>
2346 SDHCI_CLOCK_MUL_SHIFT;
2347
2348 /*
2349 * In case the value in Clock Multiplier is 0, then programmable
2350 * clock mode is not supported, otherwise the actual clock
2351 * multiplier is one more than the value of Clock Multiplier
2352 * in the Capabilities Register.
2353 */
2354 if (host->clk_mul)
2355 host->clk_mul += 1;
2356
2357 /*
2311 * Set host parameters. 2358 * Set host parameters.
2312 */ 2359 */
2313 mmc->ops = &sdhci_ops; 2360 mmc->ops = &sdhci_ops;
2361 mmc->f_max = host->max_clk;
2314 if (host->ops->get_min_clock) 2362 if (host->ops->get_min_clock)
2315 mmc->f_min = host->ops->get_min_clock(host); 2363 mmc->f_min = host->ops->get_min_clock(host);
2316 else if (host->version >= SDHCI_SPEC_300) 2364 else if (host->version >= SDHCI_SPEC_300) {
2317 mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300; 2365 if (host->clk_mul) {
2318 else 2366 mmc->f_min = (host->max_clk * host->clk_mul) / 1024;
2367 mmc->f_max = host->max_clk * host->clk_mul;
2368 } else
2369 mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;
2370 } else
2319 mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; 2371 mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
2320 2372
2321 mmc->f_max = host->max_clk;
2322 mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE; 2373 mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE;
2323 2374
2324 /* 2375 /*
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index e62367491eee..6b0a0ee9ac6e 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -101,6 +101,7 @@
101#define SDHCI_DIV_MASK 0xFF 101#define SDHCI_DIV_MASK 0xFF
102#define SDHCI_DIV_MASK_LEN 8 102#define SDHCI_DIV_MASK_LEN 8
103#define SDHCI_DIV_HI_MASK 0x300 103#define SDHCI_DIV_HI_MASK 0x300
104#define SDHCI_PROG_CLOCK_MODE 0x0020
104#define SDHCI_CLOCK_CARD_EN 0x0004 105#define SDHCI_CLOCK_CARD_EN 0x0004
105#define SDHCI_CLOCK_INT_STABLE 0x0002 106#define SDHCI_CLOCK_INT_STABLE 0x0002
106#define SDHCI_CLOCK_INT_EN 0x0001 107#define SDHCI_CLOCK_INT_EN 0x0001
@@ -191,6 +192,8 @@
191#define SDHCI_DRIVER_TYPE_C 0x00000020 192#define SDHCI_DRIVER_TYPE_C 0x00000020
192#define SDHCI_DRIVER_TYPE_D 0x00000040 193#define SDHCI_DRIVER_TYPE_D 0x00000040
193#define SDHCI_USE_SDR50_TUNING 0x00002000 194#define SDHCI_USE_SDR50_TUNING 0x00002000
195#define SDHCI_CLOCK_MUL_MASK 0x00FF0000
196#define SDHCI_CLOCK_MUL_SHIFT 16
194 197
195#define SDHCI_CAPABILITIES_1 0x44 198#define SDHCI_CAPABILITIES_1 0x44
196 199
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index b74c8530e959..a88a799ed7c3 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -117,6 +117,7 @@ struct sdhci_host {
117 117
118 unsigned int max_clk; /* Max possible freq (MHz) */ 118 unsigned int max_clk; /* Max possible freq (MHz) */
119 unsigned int timeout_clk; /* Timeout freq (KHz) */ 119 unsigned int timeout_clk; /* Timeout freq (KHz) */
120 unsigned int clk_mul; /* Clock Muliplier value */
120 121
121 unsigned int clock; /* Current clock (MHz) */ 122 unsigned int clock; /* Current clock (MHz) */
122 u8 pwr; /* Current voltage */ 123 u8 pwr; /* Current voltage */