diff options
| -rw-r--r-- | drivers/mmc/core/bus.c | 9 | ||||
| -rw-r--r-- | drivers/mmc/core/core.c | 12 | ||||
| -rw-r--r-- | drivers/mmc/core/sdio.c | 135 | ||||
| -rw-r--r-- | include/linux/mmc/card.h | 1 |
4 files changed, 134 insertions, 23 deletions
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 49d9dcaeca4..7cd9749dc21 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c | |||
| @@ -37,6 +37,8 @@ static ssize_t mmc_type_show(struct device *dev, | |||
| 37 | return sprintf(buf, "SD\n"); | 37 | return sprintf(buf, "SD\n"); |
| 38 | case MMC_TYPE_SDIO: | 38 | case MMC_TYPE_SDIO: |
| 39 | return sprintf(buf, "SDIO\n"); | 39 | return sprintf(buf, "SDIO\n"); |
| 40 | case MMC_TYPE_SD_COMBO: | ||
| 41 | return sprintf(buf, "SDcombo\n"); | ||
| 40 | default: | 42 | default: |
| 41 | return -EFAULT; | 43 | return -EFAULT; |
| 42 | } | 44 | } |
| @@ -74,6 +76,9 @@ mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
| 74 | case MMC_TYPE_SDIO: | 76 | case MMC_TYPE_SDIO: |
| 75 | type = "SDIO"; | 77 | type = "SDIO"; |
| 76 | break; | 78 | break; |
| 79 | case MMC_TYPE_SD_COMBO: | ||
| 80 | type = "SDcombo"; | ||
| 81 | break; | ||
| 77 | default: | 82 | default: |
| 78 | type = NULL; | 83 | type = NULL; |
| 79 | } | 84 | } |
| @@ -239,6 +244,10 @@ int mmc_add_card(struct mmc_card *card) | |||
| 239 | case MMC_TYPE_SDIO: | 244 | case MMC_TYPE_SDIO: |
| 240 | type = "SDIO"; | 245 | type = "SDIO"; |
| 241 | break; | 246 | break; |
| 247 | case MMC_TYPE_SD_COMBO: | ||
| 248 | type = "SD-combo"; | ||
| 249 | if (mmc_card_blockaddr(card)) | ||
| 250 | type = "SDHC-combo"; | ||
| 242 | default: | 251 | default: |
| 243 | type = "?"; | 252 | type = "?"; |
| 244 | break; | 253 | break; |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 569e94da844..b69ce91b11e 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
| @@ -1099,8 +1099,15 @@ void mmc_rescan(struct work_struct *work) | |||
| 1099 | */ | 1099 | */ |
| 1100 | err = mmc_send_io_op_cond(host, 0, &ocr); | 1100 | err = mmc_send_io_op_cond(host, 0, &ocr); |
| 1101 | if (!err) { | 1101 | if (!err) { |
| 1102 | if (mmc_attach_sdio(host, ocr)) | 1102 | if (mmc_attach_sdio(host, ocr)) { |
| 1103 | mmc_power_off(host); | 1103 | mmc_claim_host(host); |
| 1104 | /* try SDMEM (but not MMC) even if SDIO is broken */ | ||
| 1105 | if (mmc_send_app_op_cond(host, 0, &ocr)) | ||
| 1106 | goto out_fail; | ||
| 1107 | |||
| 1108 | if (mmc_attach_sd(host, ocr)) | ||
| 1109 | mmc_power_off(host); | ||
| 1110 | } | ||
| 1104 | goto out; | 1111 | goto out; |
| 1105 | } | 1112 | } |
| 1106 | 1113 | ||
| @@ -1124,6 +1131,7 @@ void mmc_rescan(struct work_struct *work) | |||
| 1124 | goto out; | 1131 | goto out; |
| 1125 | } | 1132 | } |
| 1126 | 1133 | ||
| 1134 | out_fail: | ||
| 1127 | mmc_release_host(host); | 1135 | mmc_release_host(host); |
| 1128 | mmc_power_off(host); | 1136 | mmc_power_off(host); |
| 1129 | 1137 | ||
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 47d1708810b..b0b6ce93e51 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c | |||
| @@ -160,9 +160,7 @@ static int sdio_enable_wide(struct mmc_card *card) | |||
| 160 | if (ret) | 160 | if (ret) |
| 161 | return ret; | 161 | return ret; |
| 162 | 162 | ||
| 163 | mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); | 163 | return 1; |
| 164 | |||
| 165 | return 0; | ||
| 166 | } | 164 | } |
| 167 | 165 | ||
| 168 | /* | 166 | /* |
| @@ -222,10 +220,34 @@ static int sdio_disable_wide(struct mmc_card *card) | |||
| 222 | return 0; | 220 | return 0; |
| 223 | } | 221 | } |
| 224 | 222 | ||
| 223 | |||
| 224 | static int sdio_enable_4bit_bus(struct mmc_card *card) | ||
| 225 | { | ||
| 226 | int err; | ||
| 227 | |||
| 228 | if (card->type == MMC_TYPE_SDIO) | ||
| 229 | return sdio_enable_wide(card); | ||
| 230 | |||
| 231 | if ((card->host->caps & MMC_CAP_4_BIT_DATA) && | ||
| 232 | (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) { | ||
| 233 | err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4); | ||
| 234 | if (err) | ||
| 235 | return err; | ||
| 236 | } else | ||
| 237 | return 0; | ||
| 238 | |||
| 239 | err = sdio_enable_wide(card); | ||
| 240 | if (err <= 0) | ||
| 241 | mmc_app_set_bus_width(card, MMC_BUS_WIDTH_1); | ||
| 242 | |||
| 243 | return err; | ||
| 244 | } | ||
| 245 | |||
| 246 | |||
| 225 | /* | 247 | /* |
| 226 | * Test if the card supports high-speed mode and, if so, switch to it. | 248 | * Test if the card supports high-speed mode and, if so, switch to it. |
| 227 | */ | 249 | */ |
| 228 | static int sdio_enable_hs(struct mmc_card *card) | 250 | static int mmc_sdio_switch_hs(struct mmc_card *card, int enable) |
| 229 | { | 251 | { |
| 230 | int ret; | 252 | int ret; |
| 231 | u8 speed; | 253 | u8 speed; |
| @@ -240,7 +262,10 @@ static int sdio_enable_hs(struct mmc_card *card) | |||
| 240 | if (ret) | 262 | if (ret) |
| 241 | return ret; | 263 | return ret; |
| 242 | 264 | ||
| 243 | speed |= SDIO_SPEED_EHS; | 265 | if (enable) |
| 266 | speed |= SDIO_SPEED_EHS; | ||
| 267 | else | ||
| 268 | speed &= ~SDIO_SPEED_EHS; | ||
| 244 | 269 | ||
| 245 | ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL); | 270 | ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL); |
| 246 | if (ret) | 271 | if (ret) |
| @@ -249,6 +274,24 @@ static int sdio_enable_hs(struct mmc_card *card) | |||
| 249 | return 1; | 274 | return 1; |
| 250 | } | 275 | } |
| 251 | 276 | ||
| 277 | /* | ||
| 278 | * Enable SDIO/combo card's high-speed mode. Return 0/1 if [not]supported. | ||
| 279 | */ | ||
| 280 | static int sdio_enable_hs(struct mmc_card *card) | ||
| 281 | { | ||
| 282 | int ret; | ||
| 283 | |||
| 284 | ret = mmc_sdio_switch_hs(card, true); | ||
| 285 | if (ret <= 0 || card->type == MMC_TYPE_SDIO) | ||
| 286 | return ret; | ||
| 287 | |||
| 288 | ret = mmc_sd_switch_hs(card); | ||
| 289 | if (ret <= 0) | ||
| 290 | mmc_sdio_switch_hs(card, false); | ||
| 291 | |||
| 292 | return ret; | ||
| 293 | } | ||
| 294 | |||
| 252 | static unsigned mmc_sdio_get_max_clock(struct mmc_card *card) | 295 | static unsigned mmc_sdio_get_max_clock(struct mmc_card *card) |
| 253 | { | 296 | { |
| 254 | unsigned max_dtr; | 297 | unsigned max_dtr; |
| @@ -265,6 +308,9 @@ static unsigned mmc_sdio_get_max_clock(struct mmc_card *card) | |||
| 265 | max_dtr = card->cis.max_dtr; | 308 | max_dtr = card->cis.max_dtr; |
| 266 | } | 309 | } |
| 267 | 310 | ||
| 311 | if (card->type == MMC_TYPE_SD_COMBO) | ||
| 312 | max_dtr = min(max_dtr, mmc_sd_get_max_clock(card)); | ||
| 313 | |||
| 268 | return max_dtr; | 314 | return max_dtr; |
| 269 | } | 315 | } |
| 270 | 316 | ||
| @@ -310,7 +356,24 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, | |||
| 310 | goto err; | 356 | goto err; |
| 311 | } | 357 | } |
| 312 | 358 | ||
| 313 | card->type = MMC_TYPE_SDIO; | 359 | err = mmc_sd_get_cid(host, host->ocr & ocr, card->raw_cid); |
| 360 | |||
| 361 | if (!err) { | ||
| 362 | card->type = MMC_TYPE_SD_COMBO; | ||
| 363 | |||
| 364 | if (oldcard && (oldcard->type != MMC_TYPE_SD_COMBO || | ||
| 365 | memcmp(card->raw_cid, oldcard->raw_cid, sizeof(card->raw_cid)) != 0)) { | ||
| 366 | mmc_remove_card(card); | ||
| 367 | return -ENOENT; | ||
| 368 | } | ||
| 369 | } else { | ||
| 370 | card->type = MMC_TYPE_SDIO; | ||
| 371 | |||
| 372 | if (oldcard && oldcard->type != MMC_TYPE_SDIO) { | ||
| 373 | mmc_remove_card(card); | ||
| 374 | return -ENOENT; | ||
| 375 | } | ||
| 376 | } | ||
| 314 | 377 | ||
| 315 | /* | 378 | /* |
| 316 | * Call the optional HC's init_card function to handle quirks. | 379 | * Call the optional HC's init_card function to handle quirks. |
| @@ -330,6 +393,17 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, | |||
| 330 | } | 393 | } |
| 331 | 394 | ||
| 332 | /* | 395 | /* |
| 396 | * Read CSD, before selecting the card | ||
| 397 | */ | ||
| 398 | if (!oldcard && card->type == MMC_TYPE_SD_COMBO) { | ||
| 399 | err = mmc_sd_get_csd(host, card); | ||
| 400 | if (err) | ||
| 401 | return err; | ||
| 402 | |||
| 403 | mmc_decode_cid(card); | ||
| 404 | } | ||
| 405 | |||
| 406 | /* | ||
| 333 | * Select card, as all following commands rely on that. | 407 | * Select card, as all following commands rely on that. |
| 334 | */ | 408 | */ |
| 335 | if (!powered_resume && !mmc_host_is_spi(host)) { | 409 | if (!powered_resume && !mmc_host_is_spi(host)) { |
| @@ -356,14 +430,33 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, | |||
| 356 | int same = (card->cis.vendor == oldcard->cis.vendor && | 430 | int same = (card->cis.vendor == oldcard->cis.vendor && |
| 357 | card->cis.device == oldcard->cis.device); | 431 | card->cis.device == oldcard->cis.device); |
| 358 | mmc_remove_card(card); | 432 | mmc_remove_card(card); |
| 359 | if (!same) { | 433 | if (!same) |
| 360 | err = -ENOENT; | 434 | return -ENOENT; |
| 361 | goto err; | 435 | |
| 362 | } | ||
| 363 | card = oldcard; | 436 | card = oldcard; |
| 364 | return 0; | 437 | return 0; |
| 365 | } | 438 | } |
| 366 | 439 | ||
| 440 | if (card->type == MMC_TYPE_SD_COMBO) { | ||
| 441 | err = mmc_sd_setup_card(host, card, oldcard != NULL); | ||
| 442 | /* handle as SDIO-only card if memory init failed */ | ||
| 443 | if (err) { | ||
| 444 | mmc_go_idle(host); | ||
| 445 | if (mmc_host_is_spi(host)) | ||
| 446 | /* should not fail, as it worked previously */ | ||
| 447 | mmc_spi_set_crc(host, use_spi_crc); | ||
| 448 | card->type = MMC_TYPE_SDIO; | ||
| 449 | } else | ||
| 450 | card->dev.type = &sd_type; | ||
| 451 | } | ||
| 452 | |||
| 453 | /* | ||
| 454 | * If needed, disconnect card detection pull-up resistor. | ||
| 455 | */ | ||
| 456 | err = sdio_disable_cd(card); | ||
| 457 | if (err) | ||
| 458 | goto remove; | ||
| 459 | |||
| 367 | /* | 460 | /* |
| 368 | * Switch to high-speed (if supported). | 461 | * Switch to high-speed (if supported). |
| 369 | */ | 462 | */ |
| @@ -381,8 +474,10 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, | |||
| 381 | /* | 474 | /* |
| 382 | * Switch to wider bus (if supported). | 475 | * Switch to wider bus (if supported). |
| 383 | */ | 476 | */ |
| 384 | err = sdio_enable_wide(card); | 477 | err = sdio_enable_4bit_bus(card); |
| 385 | if (err) | 478 | if (err > 0) |
| 479 | mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); | ||
| 480 | else if (err) | ||
| 386 | goto remove; | 481 | goto remove; |
| 387 | 482 | ||
| 388 | if (!oldcard) | 483 | if (!oldcard) |
| @@ -496,9 +591,14 @@ static int mmc_sdio_resume(struct mmc_host *host) | |||
| 496 | mmc_claim_host(host); | 591 | mmc_claim_host(host); |
| 497 | err = mmc_sdio_init_card(host, host->ocr, host->card, | 592 | err = mmc_sdio_init_card(host, host->ocr, host->card, |
| 498 | (host->pm_flags & MMC_PM_KEEP_POWER)); | 593 | (host->pm_flags & MMC_PM_KEEP_POWER)); |
| 499 | if (!err) | 594 | if (!err) { |
| 500 | /* We may have switched to 1-bit mode during suspend. */ | 595 | /* We may have switched to 1-bit mode during suspend. */ |
| 501 | err = sdio_enable_wide(host->card); | 596 | err = sdio_enable_4bit_bus(host->card); |
| 597 | if (err > 0) { | ||
| 598 | mmc_set_bus_width(host, MMC_BUS_WIDTH_4); | ||
| 599 | err = 0; | ||
| 600 | } | ||
| 601 | } | ||
| 502 | if (!err && host->sdio_irqs) | 602 | if (!err && host->sdio_irqs) |
| 503 | mmc_signal_sdio_irq(host); | 603 | mmc_signal_sdio_irq(host); |
| 504 | mmc_release_host(host); | 604 | mmc_release_host(host); |
| @@ -583,13 +683,6 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) | |||
| 583 | card->sdio_funcs = 0; | 683 | card->sdio_funcs = 0; |
| 584 | 684 | ||
| 585 | /* | 685 | /* |
| 586 | * If needed, disconnect card detection pull-up resistor. | ||
| 587 | */ | ||
| 588 | err = sdio_disable_cd(card); | ||
| 589 | if (err) | ||
| 590 | goto remove; | ||
| 591 | |||
| 592 | /* | ||
| 593 | * Initialize (but don't add) all present functions. | 686 | * Initialize (but don't add) all present functions. |
| 594 | */ | 687 | */ |
| 595 | for (i = 0; i < funcs; i++, card->sdio_funcs++) { | 688 | for (i = 0; i < funcs; i++, card->sdio_funcs++) { |
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index c83c7a7303f..340d391aecb 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h | |||
| @@ -93,6 +93,7 @@ struct mmc_card { | |||
| 93 | #define MMC_TYPE_MMC 0 /* MMC card */ | 93 | #define MMC_TYPE_MMC 0 /* MMC card */ |
| 94 | #define MMC_TYPE_SD 1 /* SD card */ | 94 | #define MMC_TYPE_SD 1 /* SD card */ |
| 95 | #define MMC_TYPE_SDIO 2 /* SDIO card */ | 95 | #define MMC_TYPE_SDIO 2 /* SDIO card */ |
| 96 | #define MMC_TYPE_SD_COMBO 3 /* SD combo (IO+mem) card */ | ||
| 96 | unsigned int state; /* (our) card state */ | 97 | unsigned int state; /* (our) card state */ |
| 97 | #define MMC_STATE_PRESENT (1<<0) /* present in sysfs */ | 98 | #define MMC_STATE_PRESENT (1<<0) /* present in sysfs */ |
| 98 | #define MMC_STATE_READONLY (1<<1) /* card is read-only */ | 99 | #define MMC_STATE_READONLY (1<<1) /* card is read-only */ |
