aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/core/sd.c65
-rw-r--r--drivers/mmc/host/sdhci.c40
-rw-r--r--drivers/mmc/host/sdhci.h6
-rw-r--r--include/linux/mmc/card.h19
-rw-r--r--include/linux/mmc/host.h5
5 files changed, 132 insertions, 3 deletions
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 5b7c99855635..6970b82171f7 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -452,6 +452,66 @@ static int sd_select_driver_type(struct mmc_card *card, u8 *status)
452 return 0; 452 return 0;
453} 453}
454 454
455static int sd_set_bus_speed_mode(struct mmc_card *card, u8 *status)
456{
457 unsigned int bus_speed = 0, timing = 0;
458 int err;
459
460 /*
461 * If the host doesn't support any of the UHS-I modes, fallback on
462 * default speed.
463 */
464 if (!(card->host->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
465 MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50)))
466 return 0;
467
468 if ((card->host->caps & MMC_CAP_UHS_SDR104) &&
469 (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104)) {
470 bus_speed = UHS_SDR104_BUS_SPEED;
471 timing = MMC_TIMING_UHS_SDR104;
472 card->sw_caps.uhs_max_dtr = UHS_SDR104_MAX_DTR;
473 } else if ((card->host->caps & MMC_CAP_UHS_DDR50) &&
474 (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50)) {
475 bus_speed = UHS_DDR50_BUS_SPEED;
476 timing = MMC_TIMING_UHS_DDR50;
477 card->sw_caps.uhs_max_dtr = UHS_DDR50_MAX_DTR;
478 } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
479 MMC_CAP_UHS_SDR50)) && (card->sw_caps.sd3_bus_mode &
480 SD_MODE_UHS_SDR50)) {
481 bus_speed = UHS_SDR50_BUS_SPEED;
482 timing = MMC_TIMING_UHS_SDR50;
483 card->sw_caps.uhs_max_dtr = UHS_SDR50_MAX_DTR;
484 } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
485 MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25)) &&
486 (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR25)) {
487 bus_speed = UHS_SDR25_BUS_SPEED;
488 timing = MMC_TIMING_UHS_SDR25;
489 card->sw_caps.uhs_max_dtr = UHS_SDR25_MAX_DTR;
490 } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
491 MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 |
492 MMC_CAP_UHS_SDR12)) && (card->sw_caps.sd3_bus_mode &
493 SD_MODE_UHS_SDR12)) {
494 bus_speed = UHS_SDR12_BUS_SPEED;
495 timing = MMC_TIMING_UHS_SDR12;
496 card->sw_caps.uhs_max_dtr = UHS_SDR12_MAX_DTR;
497 }
498
499 card->sd_bus_speed = bus_speed;
500 err = mmc_sd_switch(card, 1, 0, bus_speed, status);
501 if (err)
502 return err;
503
504 if ((status[16] & 0xF) != bus_speed)
505 printk(KERN_WARNING "%s: Problem setting bus speed mode!\n",
506 mmc_hostname(card->host));
507 else {
508 mmc_set_timing(card->host, timing);
509 mmc_set_clock(card->host, card->sw_caps.uhs_max_dtr);
510 }
511
512 return 0;
513}
514
455/* 515/*
456 * UHS-I specific initialization procedure 516 * UHS-I specific initialization procedure
457 */ 517 */
@@ -485,6 +545,11 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card)
485 545
486 /* Set the driver strength for the card */ 546 /* Set the driver strength for the card */
487 err = sd_select_driver_type(card, status); 547 err = sd_select_driver_type(card, status);
548 if (err)
549 goto out;
550
551 /* Set bus speed mode of the card */
552 err = sd_set_bus_speed_mode(card, status);
488 553
489out: 554out:
490 kfree(status); 555 kfree(status);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 409cde5970ae..8994493dd940 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1244,7 +1244,16 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1244 ctrl &= ~SDHCI_CTRL_HISPD; 1244 ctrl &= ~SDHCI_CTRL_HISPD;
1245 1245
1246 if (host->version >= SDHCI_SPEC_300) { 1246 if (host->version >= SDHCI_SPEC_300) {
1247 u16 ctrl_2; 1247 u16 clk, ctrl_2;
1248 unsigned int clock;
1249
1250 /* In case of UHS-I modes, set High Speed Enable */
1251 if ((ios->timing == MMC_TIMING_UHS_SDR50) ||
1252 (ios->timing == MMC_TIMING_UHS_SDR104) ||
1253 (ios->timing == MMC_TIMING_UHS_DDR50) ||
1254 (ios->timing == MMC_TIMING_UHS_SDR25) ||
1255 (ios->timing == MMC_TIMING_UHS_SDR12))
1256 ctrl |= SDHCI_CTRL_HISPD;
1248 1257
1249 ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 1258 ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
1250 if (!(ctrl_2 & SDHCI_CTRL_PRESET_VAL_ENABLE)) { 1259 if (!(ctrl_2 & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
@@ -1267,8 +1276,6 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1267 * need to reset SD Clock Enable before changing High 1276 * need to reset SD Clock Enable before changing High
1268 * Speed Enable to avoid generating clock gliches. 1277 * Speed Enable to avoid generating clock gliches.
1269 */ 1278 */
1270 u16 clk;
1271 unsigned int clock;
1272 1279
1273 /* Reset SD Clock Enable */ 1280 /* Reset SD Clock Enable */
1274 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 1281 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
@@ -1282,6 +1289,33 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1282 host->clock = 0; 1289 host->clock = 0;
1283 sdhci_set_clock(host, clock); 1290 sdhci_set_clock(host, clock);
1284 } 1291 }
1292
1293 ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
1294
1295 /* Select Bus Speed Mode for host */
1296 ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
1297 if (ios->timing == MMC_TIMING_UHS_SDR12)
1298 ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
1299 else if (ios->timing == MMC_TIMING_UHS_SDR25)
1300 ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
1301 else if (ios->timing == MMC_TIMING_UHS_SDR50)
1302 ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
1303 else if (ios->timing == MMC_TIMING_UHS_SDR104)
1304 ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
1305 else if (ios->timing == MMC_TIMING_UHS_DDR50)
1306 ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
1307
1308 /* Reset SD Clock Enable */
1309 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
1310 clk &= ~SDHCI_CLOCK_CARD_EN;
1311 sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
1312
1313 sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
1314
1315 /* Re-enable SD Clock */
1316 clock = host->clock;
1317 host->clock = 0;
1318 sdhci_set_clock(host, clock);
1285 } else 1319 } else
1286 sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 1320 sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
1287 1321
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 667bf8874be7..d96f6afcca1f 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -149,6 +149,12 @@
149#define SDHCI_ACMD12_ERR 0x3C 149#define SDHCI_ACMD12_ERR 0x3C
150 150
151#define SDHCI_HOST_CONTROL2 0x3E 151#define SDHCI_HOST_CONTROL2 0x3E
152#define SDHCI_CTRL_UHS_MASK 0x0007
153#define SDHCI_CTRL_UHS_SDR12 0x0000
154#define SDHCI_CTRL_UHS_SDR25 0x0001
155#define SDHCI_CTRL_UHS_SDR50 0x0002
156#define SDHCI_CTRL_UHS_SDR104 0x0003
157#define SDHCI_CTRL_UHS_DDR50 0x0004
152#define SDHCI_CTRL_VDD_180 0x0008 158#define SDHCI_CTRL_VDD_180 0x0008
153#define SDHCI_CTRL_DRV_TYPE_MASK 0x0030 159#define SDHCI_CTRL_DRV_TYPE_MASK 0x0030
154#define SDHCI_CTRL_DRV_TYPE_B 0x0000 160#define SDHCI_CTRL_DRV_TYPE_B 0x0000
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 539327260dc1..4ef6ded6347d 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -81,7 +81,24 @@ struct sd_ssr {
81 81
82struct sd_switch_caps { 82struct sd_switch_caps {
83 unsigned int hs_max_dtr; 83 unsigned int hs_max_dtr;
84 unsigned int uhs_max_dtr;
85#define UHS_SDR104_MAX_DTR 208000000
86#define UHS_SDR50_MAX_DTR 100000000
87#define UHS_DDR50_MAX_DTR 50000000
88#define UHS_SDR25_MAX_DTR UHS_DDR50_MAX_DTR
89#define UHS_SDR12_MAX_DTR 25000000
84 unsigned int sd3_bus_mode; 90 unsigned int sd3_bus_mode;
91#define UHS_SDR12_BUS_SPEED 0
92#define UHS_SDR25_BUS_SPEED 1
93#define UHS_SDR50_BUS_SPEED 2
94#define UHS_SDR104_BUS_SPEED 3
95#define UHS_DDR50_BUS_SPEED 4
96
97#define SD_MODE_UHS_SDR12 (1 << UHS_SDR12_BUS_SPEED)
98#define SD_MODE_UHS_SDR25 (1 << UHS_SDR25_BUS_SPEED)
99#define SD_MODE_UHS_SDR50 (1 << UHS_SDR50_BUS_SPEED)
100#define SD_MODE_UHS_SDR104 (1 << UHS_SDR104_BUS_SPEED)
101#define SD_MODE_UHS_DDR50 (1 << UHS_DDR50_BUS_SPEED)
85 unsigned int sd3_drv_type; 102 unsigned int sd3_drv_type;
86#define SD_DRIVER_TYPE_B 0x01 103#define SD_DRIVER_TYPE_B 0x01
87#define SD_DRIVER_TYPE_A 0x02 104#define SD_DRIVER_TYPE_A 0x02
@@ -166,6 +183,8 @@ struct mmc_card {
166 const char **info; /* info strings */ 183 const char **info; /* info strings */
167 struct sdio_func_tuple *tuples; /* unknown common tuples */ 184 struct sdio_func_tuple *tuples; /* unknown common tuples */
168 185
186 unsigned int sd_bus_speed; /* Bus Speed Mode set for the card */
187
169 struct dentry *debugfs_root; 188 struct dentry *debugfs_root;
170}; 189};
171 190
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 949e4d525989..62375992bdd6 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -50,6 +50,11 @@ struct mmc_ios {
50#define MMC_TIMING_LEGACY 0 50#define MMC_TIMING_LEGACY 0
51#define MMC_TIMING_MMC_HS 1 51#define MMC_TIMING_MMC_HS 1
52#define MMC_TIMING_SD_HS 2 52#define MMC_TIMING_SD_HS 2
53#define MMC_TIMING_UHS_SDR12 MMC_TIMING_LEGACY
54#define MMC_TIMING_UHS_SDR25 MMC_TIMING_SD_HS
55#define MMC_TIMING_UHS_SDR50 3
56#define MMC_TIMING_UHS_SDR104 4
57#define MMC_TIMING_UHS_DDR50 5
53 58
54 unsigned char ddr; /* dual data rate used */ 59 unsigned char ddr; /* dual data rate used */
55 60