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

Commit 4adbbcc7 authored by San Mehat's avatar San Mehat Committed by Daniel Walker
Browse files

mmc: msm_sdcc: Clean up clock management and add a 10us delay after enabling clocks



It appears that in some cases there may be a delay on the ARM9 in enabling our clock.
As a result, we may put the controller into a bad state. Delay 10us after enabling
clocks to let the peripheral settle. Note - this is all imperical.

Also ensure set_ios() callback grabs the host lock.

Signed-off-by: default avatarSan Mehat <san@google.com>
Signed-off-by: default avatarDaniel Walker <dwalker@codeaurora.org>
parent 5b8a2fb3
Loading
Loading
Loading
Loading
+40 −40
Original line number Diff line number Diff line
@@ -735,20 +735,42 @@ msmsdcc_request(struct mmc_host *mmc, struct mmc_request *mrq)
	spin_unlock_irqrestore(&host->lock, flags);
}

static int inline
msmsdcc_enable_clocks(struct msmsdcc_host *host, int enable)
{
	int rc;
	if (enable) {
		rc = clk_enable(host->pclk);
		if (rc)
			return rc;
		rc = clk_enable(host->clk);
		if (rc) {
			clk_disable(host->pclk);
			return rc;
		}
		host->clks_on = 1;
		udelay(10);
	} else {
		clk_disable(host->clk);
		clk_disable(host->pclk);
		host->clks_on = 0;
	}
	return 0;
}

static void
msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
	struct msmsdcc_host *host = mmc_priv(mmc);
	u32 clk = 0, pwr = 0;
	int rc;
	unsigned long flags;

	spin_lock_irqsave(&host->lock, flags);
	if (ios->clock) {

		if (!host->clks_on) {
			clk_enable(host->pclk);
			clk_enable(host->clk);
			host->clks_on = 1;
		}
		if (!host->clks_on)
			msmsdcc_enable_clocks(host, 1);
		if (ios->clock != host->clk_rate) {
			rc = clk_set_rate(host->clk, ios->clock);
			if (rc < 0)
@@ -793,11 +815,9 @@ msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
		writel(pwr, host->base + MMCIPOWER);
	}

	if (!(clk & MCI_CLK_ENABLE) && host->clks_on) {
		clk_disable(host->clk);
		clk_disable(host->pclk);
		host->clks_on = 0;
	}
	if (!(clk & MCI_CLK_ENABLE) && host->clks_on)
		msmsdcc_enable_clocks(host, 0);
	spin_unlock_irqrestore(&host->lock, flags);
}

static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable)
@@ -899,7 +919,6 @@ msmsdcc_command_expired(unsigned long _data)
	pr_err("%s: Command timeout (%p %p %p %p)\n",
	       mmc_hostname(host->mmc), mrq, mrq->cmd,
	       mrq->data, host->dma.sg);

	mrq->cmd->error = -ETIMEDOUT;
	msmsdcc_stop_data(host);

@@ -1031,31 +1050,21 @@ msmsdcc_probe(struct platform_device *pdev)
	 */
	msmsdcc_init_dma(host);

	/*
	 * Setup main peripheral bus clock
	 */
	/* Get our clocks */
	host->pclk = clk_get(&pdev->dev, "sdc_pclk");
	if (IS_ERR(host->pclk)) {
		ret = PTR_ERR(host->pclk);
		goto host_free;
	}

	ret = clk_enable(host->pclk);
	if (ret)
		goto pclk_put;

	host->pclk_rate = clk_get_rate(host->pclk);

	/*
	 * Setup SDC MMC clock
	 */
	host->clk = clk_get(&pdev->dev, "sdc_clk");
	if (IS_ERR(host->clk)) {
		ret = PTR_ERR(host->clk);
		goto pclk_disable;
		goto pclk_put;
	}

	ret = clk_enable(host->clk);
	/* Enable clocks */
	ret = msmsdcc_enable_clocks(host, 1);
	if (ret)
		goto clk_put;

@@ -1065,10 +1074,9 @@ msmsdcc_probe(struct platform_device *pdev)
		goto clk_disable;
	}

	host->pclk_rate = clk_get_rate(host->pclk);
	host->clk_rate = clk_get_rate(host->clk);

	host->clks_on = 1;

	/*
	 * Setup MMC host structure
	 */
@@ -1187,11 +1195,9 @@ msmsdcc_probe(struct platform_device *pdev)
	if (host->stat_irq)
		free_irq(host->stat_irq, host);
 clk_disable:
	clk_disable(host->clk);
	msmsdcc_enable_clocks(host, 0);
 clk_put:
	clk_put(host->clk);
 pclk_disable:
	clk_disable(host->pclk);
 pclk_put:
	clk_put(host->pclk);
 host_free:
@@ -1217,11 +1223,8 @@ msmsdcc_suspend(struct platform_device *dev, pm_message_t state)
		if (!rc) {
			writel(0, host->base + MMCIMASK0);

			if (host->clks_on) {
				clk_disable(host->clk);
				clk_disable(host->pclk);
				host->clks_on = 0;
			}
			if (host->clks_on)
				msmsdcc_enable_clocks(host, 0);
		}
	}
	return rc;
@@ -1238,11 +1241,8 @@ msmsdcc_resume(struct platform_device *dev)

		spin_lock_irqsave(&host->lock, flags);

		if (!host->clks_on) {
			clk_enable(host->pclk);
			clk_enable(host->clk);
			host->clks_on = 1;
		}
		if (!host->clks_on)
			msmsdcc_enable_clocks(host, 1);

		writel(host->saved_irq0mask, host->base + MMCIMASK0);