Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Hein Tibosch and committed by
Chris Ball
88ae8b86 176d1ed4

+58 -45
+57 -45
drivers/mmc/core/core.c
··· 908 908 */ 909 909 mmc_delay(10); 910 910 911 - if (host->f_min > 400000) { 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; 911 + host->ios.clock = host->f_init; 917 912 918 913 host->ios.power_mode = MMC_POWER_ON; 919 914 mmc_set_ios(host); ··· 1400 1405 u32 ocr; 1401 1406 int err; 1402 1407 unsigned long flags; 1408 + int i; 1409 + const unsigned freqs[] = { 400000, 300000, 200000, 100000 }; 1403 1410 1404 1411 spin_lock_irqsave(&host->lock, flags); 1405 1412 ··· 1441 1444 if (host->ops->get_cd && host->ops->get_cd(host) == 0) 1442 1445 goto out; 1443 1446 1444 - mmc_claim_host(host); 1447 + for (i = 0; i < ARRAY_SIZE(freqs); i++) { 1448 + mmc_claim_host(host); 1445 1449 1446 - mmc_power_up(host); 1447 - sdio_reset(host); 1448 - mmc_go_idle(host); 1450 + if (freqs[i] >= host->f_min) 1451 + host->f_init = freqs[i]; 1452 + else if (!i || freqs[i-1] > host->f_min) 1453 + host->f_init = host->f_min; 1454 + else { 1455 + mmc_release_host(host); 1456 + goto out; 1457 + } 1458 + pr_info("%s: %s: trying to init card at %u Hz\n", 1459 + mmc_hostname(host), __func__, host->f_init); 1449 1460 1450 - mmc_send_if_cond(host, host->ocr_avail); 1461 + mmc_power_up(host); 1462 + sdio_reset(host); 1463 + mmc_go_idle(host); 1451 1464 1452 - /* 1453 - * First we search for SDIO... 1454 - */ 1455 - err = mmc_send_io_op_cond(host, 0, &ocr); 1456 - if (!err) { 1457 - if (mmc_attach_sdio(host, ocr)) { 1458 - mmc_claim_host(host); 1459 - /* try SDMEM (but not MMC) even if SDIO is broken */ 1460 - if (mmc_send_app_op_cond(host, 0, &ocr)) 1461 - goto out_fail; 1465 + mmc_send_if_cond(host, host->ocr_avail); 1462 1466 1467 + /* 1468 + * First we search for SDIO... 1469 + */ 1470 + err = mmc_send_io_op_cond(host, 0, &ocr); 1471 + if (!err) { 1472 + if (mmc_attach_sdio(host, ocr)) { 1473 + mmc_claim_host(host); 1474 + /* 1475 + * Try SDMEM (but not MMC) even if SDIO 1476 + * is broken. 1477 + */ 1478 + if (mmc_send_app_op_cond(host, 0, &ocr)) 1479 + goto out_fail; 1480 + 1481 + if (mmc_attach_sd(host, ocr)) 1482 + mmc_power_off(host); 1483 + } 1484 + goto out; 1485 + } 1486 + 1487 + /* 1488 + * ...then normal SD... 1489 + */ 1490 + err = mmc_send_app_op_cond(host, 0, &ocr); 1491 + if (!err) { 1463 1492 if (mmc_attach_sd(host, ocr)) 1464 1493 mmc_power_off(host); 1494 + goto out; 1465 1495 } 1466 - goto out; 1467 - } 1468 1496 1469 - /* 1470 - * ...then normal SD... 1471 - */ 1472 - err = mmc_send_app_op_cond(host, 0, &ocr); 1473 - if (!err) { 1474 - if (mmc_attach_sd(host, ocr)) 1475 - mmc_power_off(host); 1476 - goto out; 1477 - } 1478 - 1479 - /* 1480 - * ...and finally MMC. 1481 - */ 1482 - err = mmc_send_op_cond(host, 0, &ocr); 1483 - if (!err) { 1484 - if (mmc_attach_mmc(host, ocr)) 1485 - mmc_power_off(host); 1486 - goto out; 1487 - } 1497 + /* 1498 + * ...and finally MMC. 1499 + */ 1500 + err = mmc_send_op_cond(host, 0, &ocr); 1501 + if (!err) { 1502 + if (mmc_attach_mmc(host, ocr)) 1503 + mmc_power_off(host); 1504 + goto out; 1505 + } 1488 1506 1489 1507 out_fail: 1490 - mmc_release_host(host); 1491 - mmc_power_off(host); 1492 - 1508 + mmc_release_host(host); 1509 + mmc_power_off(host); 1510 + } 1493 1511 out: 1494 1512 if (host->caps & MMC_CAP_NEEDS_POLL) 1495 1513 mmc_schedule_delayed_work(&host->detect, HZ);
+1
include/linux/mmc/host.h
··· 123 123 const struct mmc_host_ops *ops; 124 124 unsigned int f_min; 125 125 unsigned int f_max; 126 + unsigned int f_init; 126 127 u32 ocr_avail; 127 128 struct notifier_block pm_notify; 128 129