aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2012-04-19 12:02:05 -0400
committerChris Ball <cjb@laptop.org>2012-07-21 00:02:13 -0400
commitb289174ff70a591545a054d52ae081a75a73f085 (patch)
tree922e8a99e078bac2ac882ca5824924f3aa93b1e7 /drivers
parente1aae2eb3f7c446a2680a3a0ccd05aa50521b4e2 (diff)
mmc: sh_mmcif: fix clock management
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 <g.liakhovetski@gmx.de> Reviewed-by: Simon Horman <horms@verge.net.au> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/host/sh_mmcif.c46
1 files changed, 23 insertions, 23 deletions
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index d6ffb0557537..6a93b0466854 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -942,6 +942,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
942 } 942 }
943 if (host->power) { 943 if (host->power) {
944 pm_runtime_put(&host->pd->dev); 944 pm_runtime_put(&host->pd->dev);
945 clk_disable(host->hclk);
945 host->power = false; 946 host->power = false;
946 if (p->down_pwr && ios->power_mode == MMC_POWER_OFF) 947 if (p->down_pwr && ios->power_mode == MMC_POWER_OFF)
947 p->down_pwr(host->pd); 948 p->down_pwr(host->pd);
@@ -954,6 +955,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
954 if (!host->power) { 955 if (!host->power) {
955 if (p->set_pwr) 956 if (p->set_pwr)
956 p->set_pwr(host->pd, ios->power_mode); 957 p->set_pwr(host->pd, ios->power_mode);
958 clk_enable(host->hclk);
957 pm_runtime_get_sync(&host->pd->dev); 959 pm_runtime_get_sync(&host->pd->dev);
958 host->power = true; 960 host->power = true;
959 sh_mmcif_sync_reset(host); 961 sh_mmcif_sync_reset(host);
@@ -1278,22 +1280,11 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
1278 host->addr = reg; 1280 host->addr = reg;
1279 host->timeout = 1000; 1281 host->timeout = 1000;
1280 1282
1281 snprintf(clk_name, sizeof(clk_name), "mmc%d", pdev->id);
1282 host->hclk = clk_get(&pdev->dev, clk_name);
1283 if (IS_ERR(host->hclk)) {
1284 dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
1285 ret = PTR_ERR(host->hclk);
1286 goto eclkget;
1287 }
1288 clk_enable(host->hclk);
1289 host->clk = clk_get_rate(host->hclk);
1290 host->pd = pdev; 1283 host->pd = pdev;
1291 1284
1292 spin_lock_init(&host->lock); 1285 spin_lock_init(&host->lock);
1293 1286
1294 mmc->ops = &sh_mmcif_ops; 1287 mmc->ops = &sh_mmcif_ops;
1295 mmc->f_max = host->clk / 2;
1296 mmc->f_min = host->clk / 512;
1297 if (pd->ocr) 1288 if (pd->ocr)
1298 mmc->ocr_avail = pd->ocr; 1289 mmc->ocr_avail = pd->ocr;
1299 mmc->caps = MMC_CAP_MMC_HIGHSPEED; 1290 mmc->caps = MMC_CAP_MMC_HIGHSPEED;
@@ -1305,18 +1296,30 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
1305 mmc->max_blk_count = mmc->max_req_size / mmc->max_blk_size; 1296 mmc->max_blk_count = mmc->max_req_size / mmc->max_blk_size;
1306 mmc->max_seg_size = mmc->max_req_size; 1297 mmc->max_seg_size = mmc->max_req_size;
1307 1298
1308 sh_mmcif_sync_reset(host);
1309 platform_set_drvdata(pdev, host); 1299 platform_set_drvdata(pdev, host);
1310 1300
1311 pm_runtime_enable(&pdev->dev); 1301 pm_runtime_enable(&pdev->dev);
1312 host->power = false; 1302 host->power = false;
1313 1303
1304 snprintf(clk_name, sizeof(clk_name), "mmc%d", pdev->id);
1305 host->hclk = clk_get(&pdev->dev, clk_name);
1306 if (IS_ERR(host->hclk)) {
1307 ret = PTR_ERR(host->hclk);
1308 dev_err(&pdev->dev, "cannot get clock \"%s\": %d\n", clk_name, ret);
1309 goto eclkget;
1310 }
1311 clk_enable(host->hclk);
1312 host->clk = clk_get_rate(host->hclk);
1313 mmc->f_max = host->clk / 2;
1314 mmc->f_min = host->clk / 512;
1315
1314 ret = pm_runtime_resume(&pdev->dev); 1316 ret = pm_runtime_resume(&pdev->dev);
1315 if (ret < 0) 1317 if (ret < 0)
1316 goto eresume; 1318 goto eresume;
1317 1319
1318 INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work); 1320 INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work);
1319 1321
1322 sh_mmcif_sync_reset(host);
1320 sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); 1323 sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
1321 1324
1322 ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:error", host); 1325 ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:error", host);
@@ -1330,6 +1333,7 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
1330 goto ereqirq1; 1333 goto ereqirq1;
1331 } 1334 }
1332 1335
1336 clk_disable(host->hclk);
1333 ret = mmc_add_host(mmc); 1337 ret = mmc_add_host(mmc);
1334 if (ret < 0) 1338 if (ret < 0)
1335 goto emmcaddh; 1339 goto emmcaddh;
@@ -1348,9 +1352,10 @@ ereqirq1:
1348ereqirq0: 1352ereqirq0:
1349 pm_runtime_suspend(&pdev->dev); 1353 pm_runtime_suspend(&pdev->dev);
1350eresume: 1354eresume:
1351 pm_runtime_disable(&pdev->dev);
1352 clk_disable(host->hclk); 1355 clk_disable(host->hclk);
1356 clk_put(host->hclk);
1353eclkget: 1357eclkget:
1358 pm_runtime_disable(&pdev->dev);
1354 mmc_free_host(mmc); 1359 mmc_free_host(mmc);
1355ealloch: 1360ealloch:
1356 iounmap(reg); 1361 iounmap(reg);
@@ -1363,6 +1368,7 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
1363 int irq[2]; 1368 int irq[2];
1364 1369
1365 host->dying = true; 1370 host->dying = true;
1371 clk_enable(host->hclk);
1366 pm_runtime_get_sync(&pdev->dev); 1372 pm_runtime_get_sync(&pdev->dev);
1367 1373
1368 dev_pm_qos_hide_latency_limit(&pdev->dev); 1374 dev_pm_qos_hide_latency_limit(&pdev->dev);
@@ -1388,9 +1394,9 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
1388 1394
1389 platform_set_drvdata(pdev, NULL); 1395 platform_set_drvdata(pdev, NULL);
1390 1396
1391 clk_disable(host->hclk);
1392 mmc_free_host(host->mmc); 1397 mmc_free_host(host->mmc);
1393 pm_runtime_put_sync(&pdev->dev); 1398 pm_runtime_put_sync(&pdev->dev);
1399 clk_disable(host->hclk);
1394 pm_runtime_disable(&pdev->dev); 1400 pm_runtime_disable(&pdev->dev);
1395 1401
1396 return 0; 1402 return 0;
@@ -1399,24 +1405,18 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
1399#ifdef CONFIG_PM 1405#ifdef CONFIG_PM
1400static int sh_mmcif_suspend(struct device *dev) 1406static int sh_mmcif_suspend(struct device *dev)
1401{ 1407{
1402 struct platform_device *pdev = to_platform_device(dev); 1408 struct sh_mmcif_host *host = dev_get_drvdata(dev);
1403 struct sh_mmcif_host *host = platform_get_drvdata(pdev);
1404 int ret = mmc_suspend_host(host->mmc); 1409 int ret = mmc_suspend_host(host->mmc);
1405 1410
1406 if (!ret) { 1411 if (!ret)
1407 sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); 1412 sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
1408 clk_disable(host->hclk);
1409 }
1410 1413
1411 return ret; 1414 return ret;
1412} 1415}
1413 1416
1414static int sh_mmcif_resume(struct device *dev) 1417static int sh_mmcif_resume(struct device *dev)
1415{ 1418{
1416 struct platform_device *pdev = to_platform_device(dev); 1419 struct sh_mmcif_host *host = dev_get_drvdata(dev);
1417 struct sh_mmcif_host *host = platform_get_drvdata(pdev);
1418
1419 clk_enable(host->hclk);
1420 1420
1421 return mmc_resume_host(host->mmc); 1421 return mmc_resume_host(host->mmc);
1422} 1422}