Skip to content

Commit

Permalink
mmc: sh_mmcif: fix clock management
Browse files Browse the repository at this point in the history
Regardless of whether the MMC bus clock is the same as the PM clock on
this specific interface, it has to be managed separately. Its proper
management should also include enabling and disabling of the clock,
whenever the interface is becoming active or going idle respectively.

Signed-off-by: Guennadi Liakhovetski <[email protected]>
Reviewed-by: Simon Horman <[email protected]>
Signed-off-by: Chris Ball <[email protected]>
  • Loading branch information
lyakh authored and cjb committed Jul 21, 2012
1 parent e1aae2e commit b289174
Showing 1 changed file with 23 additions and 23 deletions.
46 changes: 23 additions & 23 deletions drivers/mmc/host/sh_mmcif.c
Original file line number Diff line number Diff line change
Expand Up @@ -942,6 +942,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
}
if (host->power) {
pm_runtime_put(&host->pd->dev);
clk_disable(host->hclk);
host->power = false;
if (p->down_pwr && ios->power_mode == MMC_POWER_OFF)
p->down_pwr(host->pd);
Expand All @@ -954,6 +955,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
if (!host->power) {
if (p->set_pwr)
p->set_pwr(host->pd, ios->power_mode);
clk_enable(host->hclk);
pm_runtime_get_sync(&host->pd->dev);
host->power = true;
sh_mmcif_sync_reset(host);
Expand Down Expand Up @@ -1278,22 +1280,11 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
host->addr = reg;
host->timeout = 1000;

snprintf(clk_name, sizeof(clk_name), "mmc%d", pdev->id);
host->hclk = clk_get(&pdev->dev, clk_name);
if (IS_ERR(host->hclk)) {
dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
ret = PTR_ERR(host->hclk);
goto eclkget;
}
clk_enable(host->hclk);
host->clk = clk_get_rate(host->hclk);
host->pd = pdev;

spin_lock_init(&host->lock);

mmc->ops = &sh_mmcif_ops;
mmc->f_max = host->clk / 2;
mmc->f_min = host->clk / 512;
if (pd->ocr)
mmc->ocr_avail = pd->ocr;
mmc->caps = MMC_CAP_MMC_HIGHSPEED;
Expand All @@ -1305,18 +1296,30 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
mmc->max_blk_count = mmc->max_req_size / mmc->max_blk_size;
mmc->max_seg_size = mmc->max_req_size;

sh_mmcif_sync_reset(host);
platform_set_drvdata(pdev, host);

pm_runtime_enable(&pdev->dev);
host->power = false;

snprintf(clk_name, sizeof(clk_name), "mmc%d", pdev->id);
host->hclk = clk_get(&pdev->dev, clk_name);
if (IS_ERR(host->hclk)) {
ret = PTR_ERR(host->hclk);
dev_err(&pdev->dev, "cannot get clock \"%s\": %d\n", clk_name, ret);
goto eclkget;
}
clk_enable(host->hclk);
host->clk = clk_get_rate(host->hclk);
mmc->f_max = host->clk / 2;
mmc->f_min = host->clk / 512;

ret = pm_runtime_resume(&pdev->dev);
if (ret < 0)
goto eresume;

INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work);

sh_mmcif_sync_reset(host);
sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);

ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:error", host);
Expand All @@ -1330,6 +1333,7 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
goto ereqirq1;
}

clk_disable(host->hclk);
ret = mmc_add_host(mmc);
if (ret < 0)
goto emmcaddh;
Expand All @@ -1348,9 +1352,10 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
ereqirq0:
pm_runtime_suspend(&pdev->dev);
eresume:
pm_runtime_disable(&pdev->dev);
clk_disable(host->hclk);
clk_put(host->hclk);
eclkget:
pm_runtime_disable(&pdev->dev);
mmc_free_host(mmc);
ealloch:
iounmap(reg);
Expand All @@ -1363,6 +1368,7 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
int irq[2];

host->dying = true;
clk_enable(host->hclk);
pm_runtime_get_sync(&pdev->dev);

dev_pm_qos_hide_latency_limit(&pdev->dev);
Expand All @@ -1388,9 +1394,9 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)

platform_set_drvdata(pdev, NULL);

clk_disable(host->hclk);
mmc_free_host(host->mmc);
pm_runtime_put_sync(&pdev->dev);
clk_disable(host->hclk);
pm_runtime_disable(&pdev->dev);

return 0;
Expand All @@ -1399,24 +1405,18 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
#ifdef CONFIG_PM
static int sh_mmcif_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct sh_mmcif_host *host = platform_get_drvdata(pdev);
struct sh_mmcif_host *host = dev_get_drvdata(dev);
int ret = mmc_suspend_host(host->mmc);

if (!ret) {
if (!ret)
sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
clk_disable(host->hclk);
}

return ret;
}

static int sh_mmcif_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct sh_mmcif_host *host = platform_get_drvdata(pdev);

clk_enable(host->hclk);
struct sh_mmcif_host *host = dev_get_drvdata(dev);

return mmc_resume_host(host->mmc);
}
Expand Down

0 comments on commit b289174

Please sign in to comment.