From 5c2f2b9bd0db84eabaf0d2cf7a9392a1581c2545 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 6 Jul 2011 11:31:36 +0200 Subject: mmc: atmel-mci: add suspend/resume support Take care of slots while going to suspend state. Signed-off-by: Nicolas Ferre Reviewed-by: Felipe Balbi Signed-off-by: Chris Ball --- drivers/mmc/host/atmel-mci.c | 63 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'drivers/mmc') diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index aa8039f473c4..fa8cae1d7005 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -203,6 +203,7 @@ struct atmel_mci_slot { #define ATMCI_CARD_PRESENT 0 #define ATMCI_CARD_NEED_INIT 1 #define ATMCI_SHUTDOWN 2 +#define ATMCI_SUSPENDED 3 int detect_pin; int wp_pin; @@ -1878,10 +1879,72 @@ static int __exit atmci_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM +static int atmci_suspend(struct device *dev) +{ + struct atmel_mci *host = dev_get_drvdata(dev); + int i; + + for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) { + struct atmel_mci_slot *slot = host->slot[i]; + int ret; + + if (!slot) + continue; + ret = mmc_suspend_host(slot->mmc); + if (ret < 0) { + while (--i >= 0) { + slot = host->slot[i]; + if (slot + && test_bit(ATMCI_SUSPENDED, &slot->flags)) { + mmc_resume_host(host->slot[i]->mmc); + clear_bit(ATMCI_SUSPENDED, &slot->flags); + } + } + return ret; + } else { + set_bit(ATMCI_SUSPENDED, &slot->flags); + } + } + + return 0; +} + +static int atmci_resume(struct device *dev) +{ + struct atmel_mci *host = dev_get_drvdata(dev); + int i; + int ret = 0; + + for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) { + struct atmel_mci_slot *slot = host->slot[i]; + int err; + + slot = host->slot[i]; + if (!slot) + continue; + if (!test_bit(ATMCI_SUSPENDED, &slot->flags)) + continue; + err = mmc_resume_host(slot->mmc); + if (err < 0) + ret = err; + else + clear_bit(ATMCI_SUSPENDED, &slot->flags); + } + + return ret; +} +static SIMPLE_DEV_PM_OPS(atmci_pm, atmci_suspend, atmci_resume); +#define ATMCI_PM_OPS (&atmci_pm) +#else +#define ATMCI_PM_OPS NULL +#endif + static struct platform_driver atmci_driver = { .remove = __exit_p(atmci_remove), .driver = { .name = "atmel_mci", + .pm = ATMCI_PM_OPS, }, }; -- cgit v1.2.3-59-g8ed1b