aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/davinci_mmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/davinci_mmc.c')
-rw-r--r--drivers/mmc/host/davinci_mmc.c51
1 files changed, 43 insertions, 8 deletions
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index 56afe0a00f56..aae39125b8d7 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -171,6 +171,7 @@ struct mmc_davinci_host {
171#define DAVINCI_MMC_DATADIR_READ 1 171#define DAVINCI_MMC_DATADIR_READ 1
172#define DAVINCI_MMC_DATADIR_WRITE 2 172#define DAVINCI_MMC_DATADIR_WRITE 2
173 unsigned char data_dir; 173 unsigned char data_dir;
174 unsigned char suspended;
174 175
175 /* buffer is used during PIO of one scatterlist segment, and 176 /* buffer is used during PIO of one scatterlist segment, and
176 * is updated along with buffer_bytes_left. bytes_left applies 177 * is updated along with buffer_bytes_left. bytes_left applies
@@ -1332,32 +1333,66 @@ static int __exit davinci_mmcsd_remove(struct platform_device *pdev)
1332} 1333}
1333 1334
1334#ifdef CONFIG_PM 1335#ifdef CONFIG_PM
1335static int davinci_mmcsd_suspend(struct platform_device *pdev, pm_message_t msg) 1336static int davinci_mmcsd_suspend(struct device *dev)
1336{ 1337{
1338 struct platform_device *pdev = to_platform_device(dev);
1337 struct mmc_davinci_host *host = platform_get_drvdata(pdev); 1339 struct mmc_davinci_host *host = platform_get_drvdata(pdev);
1340 struct pm_message msg = { PM_EVENT_SUSPEND };
1341 int ret;
1338 1342
1339 return mmc_suspend_host(host->mmc, msg); 1343 mmc_host_enable(host->mmc);
1344 ret = mmc_suspend_host(host->mmc, msg);
1345 if (!ret) {
1346 writel(0, host->base + DAVINCI_MMCIM);
1347 mmc_davinci_reset_ctrl(host, 1);
1348 mmc_host_disable(host->mmc);
1349 clk_disable(host->clk);
1350 host->suspended = 1;
1351 } else {
1352 host->suspended = 0;
1353 mmc_host_disable(host->mmc);
1354 }
1355
1356 return ret;
1340} 1357}
1341 1358
1342static int davinci_mmcsd_resume(struct platform_device *pdev) 1359static int davinci_mmcsd_resume(struct device *dev)
1343{ 1360{
1361 struct platform_device *pdev = to_platform_device(dev);
1344 struct mmc_davinci_host *host = platform_get_drvdata(pdev); 1362 struct mmc_davinci_host *host = platform_get_drvdata(pdev);
1363 int ret;
1345 1364
1346 return mmc_resume_host(host->mmc); 1365 if (!host->suspended)
1366 return 0;
1367
1368 clk_enable(host->clk);
1369 mmc_host_enable(host->mmc);
1370
1371 mmc_davinci_reset_ctrl(host, 0);
1372 ret = mmc_resume_host(host->mmc);
1373 if (!ret)
1374 host->suspended = 0;
1375
1376 return ret;
1347} 1377}
1378
1379static const struct dev_pm_ops davinci_mmcsd_pm = {
1380 .suspend = davinci_mmcsd_suspend,
1381 .resume = davinci_mmcsd_resume,
1382};
1383
1384#define davinci_mmcsd_pm_ops (&davinci_mmcsd_pm)
1348#else 1385#else
1349#define davinci_mmcsd_suspend NULL 1386#define davinci_mmcsd_pm_ops NULL
1350#define davinci_mmcsd_resume NULL
1351#endif 1387#endif
1352 1388
1353static struct platform_driver davinci_mmcsd_driver = { 1389static struct platform_driver davinci_mmcsd_driver = {
1354 .driver = { 1390 .driver = {
1355 .name = "davinci_mmc", 1391 .name = "davinci_mmc",
1356 .owner = THIS_MODULE, 1392 .owner = THIS_MODULE,
1393 .pm = davinci_mmcsd_pm_ops,
1357 }, 1394 },
1358 .remove = __exit_p(davinci_mmcsd_remove), 1395 .remove = __exit_p(davinci_mmcsd_remove),
1359 .suspend = davinci_mmcsd_suspend,
1360 .resume = davinci_mmcsd_resume,
1361}; 1396};
1362 1397
1363static int __init davinci_mmcsd_init(void) 1398static int __init davinci_mmcsd_init(void)