au1xmmc: suspend/resume implementation

Basic suspend/resume support: disable peripheral on suspend and
reinit on resume.

Tested on Au1200.

Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
This commit is contained in:
Manuel Lauss 2008-07-17 13:07:28 +02:00 committed by Pierre Ossman
parent d2f2761bb7
commit dd8572af68
1 changed files with 42 additions and 12 deletions

View File

@ -1043,7 +1043,7 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev)
goto out6; goto out6;
} }
platform_set_drvdata(pdev, mmc); platform_set_drvdata(pdev, host);
printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X" printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X"
" (mode=%s)\n", pdev->id, host->iobase, " (mode=%s)\n", pdev->id, host->iobase,
@ -1087,13 +1087,10 @@ out0:
static int __devexit au1xmmc_remove(struct platform_device *pdev) static int __devexit au1xmmc_remove(struct platform_device *pdev)
{ {
struct mmc_host *mmc = platform_get_drvdata(pdev); struct au1xmmc_host *host = platform_get_drvdata(pdev);
struct au1xmmc_host *host;
if (mmc) { if (host) {
host = mmc_priv(mmc); mmc_remove_host(host->mmc);
mmc_remove_host(mmc);
#ifdef CONFIG_LEDS_CLASS #ifdef CONFIG_LEDS_CLASS
if (host->platdata && host->platdata->led) if (host->platdata && host->platdata->led)
@ -1101,8 +1098,8 @@ static int __devexit au1xmmc_remove(struct platform_device *pdev)
#endif #endif
if (host->platdata && host->platdata->cd_setup && if (host->platdata && host->platdata->cd_setup &&
!(mmc->caps & MMC_CAP_NEEDS_POLL)) !(host->mmc->caps & MMC_CAP_NEEDS_POLL))
host->platdata->cd_setup(mmc, 0); host->platdata->cd_setup(host->mmc, 0);
au_writel(0, HOST_ENABLE(host)); au_writel(0, HOST_ENABLE(host));
au_writel(0, HOST_CONFIG(host)); au_writel(0, HOST_CONFIG(host));
@ -1122,16 +1119,49 @@ static int __devexit au1xmmc_remove(struct platform_device *pdev)
release_resource(host->ioarea); release_resource(host->ioarea);
kfree(host->ioarea); kfree(host->ioarea);
mmc_free_host(mmc); mmc_free_host(host->mmc);
platform_set_drvdata(pdev, NULL);
} }
return 0; return 0;
} }
#ifdef CONFIG_PM
static int au1xmmc_suspend(struct platform_device *pdev, pm_message_t state)
{
struct au1xmmc_host *host = platform_get_drvdata(pdev);
int ret;
ret = mmc_suspend_host(host->mmc, state);
if (ret)
return ret;
au_writel(0, HOST_CONFIG2(host));
au_writel(0, HOST_CONFIG(host));
au_writel(0xffffffff, HOST_STATUS(host));
au_writel(0, HOST_ENABLE(host));
au_sync();
return 0;
}
static int au1xmmc_resume(struct platform_device *pdev)
{
struct au1xmmc_host *host = platform_get_drvdata(pdev);
au1xmmc_reset_controller(host);
return mmc_resume_host(host->mmc);
}
#else
#define au1xmmc_suspend NULL
#define au1xmmc_resume NULL
#endif
static struct platform_driver au1xmmc_driver = { static struct platform_driver au1xmmc_driver = {
.probe = au1xmmc_probe, .probe = au1xmmc_probe,
.remove = au1xmmc_remove, .remove = au1xmmc_remove,
.suspend = NULL, .suspend = au1xmmc_suspend,
.resume = NULL, .resume = au1xmmc_resume,
.driver = { .driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,