Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 88ae8b86 authored by Hein Tibosch's avatar Hein Tibosch Committed by Chris Ball
Browse files

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: default avatarHein Tibosch <hein_tibosch@yahoo.es>
Cc: Pierre Ossman <pierre@ossman.eu>
Reviewed-by: default avatarChris Ball <cjb@laptop.org>
Tested-by: default avatarChris 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: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent 176d1ed4
Loading
Loading
Loading
Loading
+57 −45
Original line number Original line Diff line number Diff line
@@ -908,12 +908,7 @@ static void mmc_power_up(struct mmc_host *host)
	 */
	 */
	mmc_delay(10);
	mmc_delay(10);


	if (host->f_min > 400000) {
	host->ios.clock = host->f_init;
		pr_warning("%s: Minimum clock frequency too high for "
				"identification mode\n", mmc_hostname(host));
		host->ios.clock = host->f_min;
	} else
		host->ios.clock = 400000;


	host->ios.power_mode = MMC_POWER_ON;
	host->ios.power_mode = MMC_POWER_ON;
	mmc_set_ios(host);
	mmc_set_ios(host);
@@ -1405,6 +1400,8 @@ void mmc_rescan(struct work_struct *work)
	u32 ocr;
	u32 ocr;
	int err;
	int err;
	unsigned long flags;
	unsigned long flags;
	int i;
	const unsigned freqs[] = { 400000, 300000, 200000, 100000 };


	spin_lock_irqsave(&host->lock, flags);
	spin_lock_irqsave(&host->lock, flags);


@@ -1444,8 +1441,20 @@ void mmc_rescan(struct work_struct *work)
	if (host->ops->get_cd && host->ops->get_cd(host) == 0)
	if (host->ops->get_cd && host->ops->get_cd(host) == 0)
		goto out;
		goto out;


	for (i = 0; i < ARRAY_SIZE(freqs); i++) {
		mmc_claim_host(host);
		mmc_claim_host(host);


		if (freqs[i] >= host->f_min)
			host->f_init = freqs[i];
		else if (!i || freqs[i-1] > host->f_min)
			host->f_init = host->f_min;
		else {
			mmc_release_host(host);
			goto out;
		}
		pr_info("%s: %s: trying to init card at %u Hz\n",
			mmc_hostname(host), __func__, host->f_init);

		mmc_power_up(host);
		mmc_power_up(host);
		sdio_reset(host);
		sdio_reset(host);
		mmc_go_idle(host);
		mmc_go_idle(host);
@@ -1459,7 +1468,10 @@ void mmc_rescan(struct work_struct *work)
		if (!err) {
		if (!err) {
			if (mmc_attach_sdio(host, ocr)) {
			if (mmc_attach_sdio(host, ocr)) {
				mmc_claim_host(host);
				mmc_claim_host(host);
			/* try SDMEM (but not MMC) even if SDIO is broken */
				/*
				 * Try SDMEM (but not MMC) even if SDIO
				 * is broken.
				 */
				if (mmc_send_app_op_cond(host, 0, &ocr))
				if (mmc_send_app_op_cond(host, 0, &ocr))
					goto out_fail;
					goto out_fail;


@@ -1492,7 +1504,7 @@ void mmc_rescan(struct work_struct *work)
out_fail:
out_fail:
		mmc_release_host(host);
		mmc_release_host(host);
		mmc_power_off(host);
		mmc_power_off(host);

	}
out:
out:
	if (host->caps & MMC_CAP_NEEDS_POLL)
	if (host->caps & MMC_CAP_NEEDS_POLL)
		mmc_schedule_delayed_work(&host->detect, HZ);
		mmc_schedule_delayed_work(&host->detect, HZ);
+1 −0
Original line number Original line Diff line number Diff line
@@ -123,6 +123,7 @@ struct mmc_host {
	const struct mmc_host_ops *ops;
	const struct mmc_host_ops *ops;
	unsigned int		f_min;
	unsigned int		f_min;
	unsigned int		f_max;
	unsigned int		f_max;
	unsigned int		f_init;
	u32			ocr_avail;
	u32			ocr_avail;
	struct notifier_block	pm_notify;
	struct notifier_block	pm_notify;