diff options
author | Hein Tibosch <hein_tibosch@yahoo.es> | 2010-09-05 21:37:19 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2010-10-23 09:11:15 -0400 |
commit | 88ae8b866488031b0e2fc05a27440fefec5e6927 (patch) | |
tree | 07fba0c9aab5c50230fcac22e74506622fa19c68 /drivers/mmc | |
parent | 176d1ed426a2a73a87c62a8aa05f6d002353cd50 (diff) |
mmc: Make ID freq configurable
In the latest releases of the mmc driver, the freq during initialization
is set to a fixed 400 Khz. This was reportedly too fast for several
users. As there doesn't seem to be an ideal frequency
which-works-for-all, Pierre suggested to let the driver try several
frequencies.
This patch implements that idea. It will try mmc-initialization using
several frequencies from an array 400, 300, 200 and 100.
In case SDIO is broken, it'll still try to detect SDMEM, also at different
freqs.
Signed-off-by: Hein Tibosch <hein_tibosch@yahoo.es>
Cc: Pierre Ossman <pierre@ossman.eu>
Reviewed-by: Chris Ball <cjb@laptop.org>
Tested-by: Chris Ball <cjb@laptop.org>
Cc: Ben Nizette <bn@niasdigital.com>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Adrian Hunter <adrian.hunter@nokia.com>
Cc: Matt Fleming <matt@console-pimps.org>
Cc: <linux-mmc@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/core/core.c | 102 |
1 files changed, 57 insertions, 45 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index ab4446c428be..222466df66ff 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -908,12 +908,7 @@ static void mmc_power_up(struct mmc_host *host) | |||
908 | */ | 908 | */ |
909 | mmc_delay(10); | 909 | mmc_delay(10); |
910 | 910 | ||
911 | if (host->f_min > 400000) { | 911 | host->ios.clock = host->f_init; |
912 | pr_warning("%s: Minimum clock frequency too high for " | ||
913 | "identification mode\n", mmc_hostname(host)); | ||
914 | host->ios.clock = host->f_min; | ||
915 | } else | ||
916 | host->ios.clock = 400000; | ||
917 | 912 | ||
918 | host->ios.power_mode = MMC_POWER_ON; | 913 | host->ios.power_mode = MMC_POWER_ON; |
919 | mmc_set_ios(host); | 914 | mmc_set_ios(host); |
@@ -1405,6 +1400,8 @@ void mmc_rescan(struct work_struct *work) | |||
1405 | u32 ocr; | 1400 | u32 ocr; |
1406 | int err; | 1401 | int err; |
1407 | unsigned long flags; | 1402 | unsigned long flags; |
1403 | int i; | ||
1404 | const unsigned freqs[] = { 400000, 300000, 200000, 100000 }; | ||
1408 | 1405 | ||
1409 | spin_lock_irqsave(&host->lock, flags); | 1406 | spin_lock_irqsave(&host->lock, flags); |
1410 | 1407 | ||
@@ -1444,55 +1441,70 @@ void mmc_rescan(struct work_struct *work) | |||
1444 | if (host->ops->get_cd && host->ops->get_cd(host) == 0) | 1441 | if (host->ops->get_cd && host->ops->get_cd(host) == 0) |
1445 | goto out; | 1442 | goto out; |
1446 | 1443 | ||
1447 | mmc_claim_host(host); | 1444 | for (i = 0; i < ARRAY_SIZE(freqs); i++) { |
1445 | mmc_claim_host(host); | ||
1448 | 1446 | ||
1449 | mmc_power_up(host); | 1447 | if (freqs[i] >= host->f_min) |
1450 | sdio_reset(host); | 1448 | host->f_init = freqs[i]; |
1451 | mmc_go_idle(host); | 1449 | else if (!i || freqs[i-1] > host->f_min) |
1450 | host->f_init = host->f_min; | ||
1451 | else { | ||
1452 | mmc_release_host(host); | ||
1453 | goto out; | ||
1454 | } | ||
1455 | pr_info("%s: %s: trying to init card at %u Hz\n", | ||
1456 | mmc_hostname(host), __func__, host->f_init); | ||
1452 | 1457 | ||
1453 | mmc_send_if_cond(host, host->ocr_avail); | 1458 | mmc_power_up(host); |
1459 | sdio_reset(host); | ||
1460 | mmc_go_idle(host); | ||
1454 | 1461 | ||
1455 | /* | 1462 | mmc_send_if_cond(host, host->ocr_avail); |
1456 | * First we search for SDIO... | ||
1457 | */ | ||
1458 | err = mmc_send_io_op_cond(host, 0, &ocr); | ||
1459 | if (!err) { | ||
1460 | if (mmc_attach_sdio(host, ocr)) { | ||
1461 | mmc_claim_host(host); | ||
1462 | /* try SDMEM (but not MMC) even if SDIO is broken */ | ||
1463 | if (mmc_send_app_op_cond(host, 0, &ocr)) | ||
1464 | goto out_fail; | ||
1465 | 1463 | ||
1464 | /* | ||
1465 | * First we search for SDIO... | ||
1466 | */ | ||
1467 | err = mmc_send_io_op_cond(host, 0, &ocr); | ||
1468 | if (!err) { | ||
1469 | if (mmc_attach_sdio(host, ocr)) { | ||
1470 | mmc_claim_host(host); | ||
1471 | /* | ||
1472 | * Try SDMEM (but not MMC) even if SDIO | ||
1473 | * is broken. | ||
1474 | */ | ||
1475 | if (mmc_send_app_op_cond(host, 0, &ocr)) | ||
1476 | goto out_fail; | ||
1477 | |||
1478 | if (mmc_attach_sd(host, ocr)) | ||
1479 | mmc_power_off(host); | ||
1480 | } | ||
1481 | goto out; | ||
1482 | } | ||
1483 | |||
1484 | /* | ||
1485 | * ...then normal SD... | ||
1486 | */ | ||
1487 | err = mmc_send_app_op_cond(host, 0, &ocr); | ||
1488 | if (!err) { | ||
1466 | if (mmc_attach_sd(host, ocr)) | 1489 | if (mmc_attach_sd(host, ocr)) |
1467 | mmc_power_off(host); | 1490 | mmc_power_off(host); |
1491 | goto out; | ||
1468 | } | 1492 | } |
1469 | goto out; | ||
1470 | } | ||
1471 | 1493 | ||
1472 | /* | 1494 | /* |
1473 | * ...then normal SD... | 1495 | * ...and finally MMC. |
1474 | */ | 1496 | */ |
1475 | err = mmc_send_app_op_cond(host, 0, &ocr); | 1497 | err = mmc_send_op_cond(host, 0, &ocr); |
1476 | if (!err) { | 1498 | if (!err) { |
1477 | if (mmc_attach_sd(host, ocr)) | 1499 | if (mmc_attach_mmc(host, ocr)) |
1478 | mmc_power_off(host); | 1500 | mmc_power_off(host); |
1479 | goto out; | 1501 | goto out; |
1480 | } | 1502 | } |
1481 | |||
1482 | /* | ||
1483 | * ...and finally MMC. | ||
1484 | */ | ||
1485 | err = mmc_send_op_cond(host, 0, &ocr); | ||
1486 | if (!err) { | ||
1487 | if (mmc_attach_mmc(host, ocr)) | ||
1488 | mmc_power_off(host); | ||
1489 | goto out; | ||
1490 | } | ||
1491 | 1503 | ||
1492 | out_fail: | 1504 | out_fail: |
1493 | mmc_release_host(host); | 1505 | mmc_release_host(host); |
1494 | mmc_power_off(host); | 1506 | mmc_power_off(host); |
1495 | 1507 | } | |
1496 | out: | 1508 | out: |
1497 | if (host->caps & MMC_CAP_NEEDS_POLL) | 1509 | if (host->caps & MMC_CAP_NEEDS_POLL) |
1498 | mmc_schedule_delayed_work(&host->detect, HZ); | 1510 | mmc_schedule_delayed_work(&host->detect, HZ); |