aboutsummaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authormerge <null@invalid>2008-11-27 08:37:56 +0000
committerAndy Green <agreen@pads.home.warmcat.com>2008-11-27 08:37:56 +0000
commita560d8579b4b009f847972667b7597c89030e26c (patch)
tree31dc5e17d93057b2e9290720a8b1f453201dead2 /drivers/mmc
parente21ce7019cc3b9495be8678ef2c41569cc03021e (diff)
MERGE-via-balaji-tracking-hist-MERGE-via-stable-tracking-hist-config-gta02-uplevel-patch
balaji-tracking-hist top was MERGE-via-stable-tracking-hist-config-gta02-uplevel-patch / eb381acecca375d0a7b88cfe640504a8a1fa4c39 ... parent commitmessage: From: merge <null@invalid> MERGE-via-stable-tracking-hist-config-gta02-uplevel-patch stable-tracking-hist top was config-gta02-uplevel-patch / 0e07e39074bbdb938cfefaea6ad7823282cc914c ... parent commitmessage: From: Andy Green <andy@openmoko.com> config-gta02-uplevel.patch Signed-off-by: Andy Green <andy@openmoko.com>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/core/core.c3
-rw-r--r--drivers/mmc/host/s3cmci.c48
-rw-r--r--drivers/mmc/host/s3cmci.h10
3 files changed, 58 insertions, 3 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index f7284b905eb..b76667e36e8 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -57,10 +57,11 @@ static int mmc_schedule_delayed_work(struct delayed_work *work,
/*
* Internal function. Flush all scheduled work from the MMC work queue.
*/
-static void mmc_flush_scheduled_work(void)
+void mmc_flush_scheduled_work(void)
{
flush_workqueue(workqueue);
}
+EXPORT_SYMBOL_GPL(mmc_flush_scheduled_work);
/**
* mmc_request_done - finish processing an MMC request
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index a2bb2129bfd..45c5192869b 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -57,6 +57,7 @@ static const int dbgmap_info = dbg_info | dbg_conf;
static const int dbgmap_debug = dbg_err | dbg_debug;
static int f_max = -1; /* override maximum frequency limit */
+static int persist; /* keep interface alive across suspend/resume */
#define dbg(host, channels, args...) \
do { \
@@ -1518,18 +1519,60 @@ static int __devinit s3cmci_2440_probe(struct platform_device *dev)
#ifdef CONFIG_PM
+static int save_regs(struct mmc_host *mmc)
+{
+ struct s3cmci_host *host = mmc_priv(mmc);
+ unsigned long flags;
+ unsigned from;
+ u32 *to = host->saved;
+
+ mmc_flush_scheduled_work();
+
+ local_irq_save(flags);
+ for (from = S3C2410_SDICON; from != S3C2410_SDIIMSK+4; from += 4)
+ if (from != host->sdidata)
+ *to++ = readl(host->base + from);
+ BUG_ON(to-host->saved != ARRAY_SIZE(host->saved));
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+static int restore_regs(struct mmc_host *mmc)
+{
+ struct s3cmci_host *host = mmc_priv(mmc);
+ unsigned long flags;
+ unsigned to;
+ u32 *from = host->saved;
+
+ /*
+ * Before we begin with the necromancy, make sure we don't
+ * inadvertently start something we'll regret microseconds later.
+ */
+ from[S3C2410_SDICMDCON - S3C2410_SDICON] = 0;
+
+ local_irq_save(flags);
+ for (to = S3C2410_SDICON; to != S3C2410_SDIIMSK+4; to += 4)
+ if (to != host->sdidata)
+ writel(*from++, host->base + to);
+ BUG_ON(from-host->saved != ARRAY_SIZE(host->saved));
+ local_irq_restore(flags);
+
+ return 0;
+}
+
static int s3cmci_suspend(struct platform_device *dev, pm_message_t state)
{
struct mmc_host *mmc = platform_get_drvdata(dev);
- return mmc_suspend_host(mmc, state);
+ return persist ? save_regs(mmc) : mmc_suspend_host(mmc, state);
}
static int s3cmci_resume(struct platform_device *dev)
{
struct mmc_host *mmc = platform_get_drvdata(dev);
- return mmc_resume_host(mmc);
+ return persist ? restore_regs(mmc) : mmc_resume_host(mmc);
}
#else /* CONFIG_PM */
@@ -1588,6 +1631,7 @@ module_init(s3cmci_init);
module_exit(s3cmci_exit);
module_param(f_max, int, 0644);
+module_param(persist, int, 0644);
MODULE_DESCRIPTION("Samsung S3C MMC/SD Card Interface driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/s3cmci.h b/drivers/mmc/host/s3cmci.h
index ca1ba3d58cf..c2b65b3488b 100644
--- a/drivers/mmc/host/s3cmci.h
+++ b/drivers/mmc/host/s3cmci.h
@@ -8,6 +8,9 @@
* published by the Free Software Foundation.
*/
+
+#include <mach/regs-sdi.h>
+
/* FIXME: DMA Resource management ?! */
#define S3CMCI_DMA 0
@@ -68,6 +71,13 @@ struct s3cmci_host {
unsigned int ccnt, dcnt;
struct tasklet_struct pio_tasklet;
+ /*
+ * Here's where we save the registers during suspend. Note that we skip
+ * SDIDATA, which is at different positions on 2410 and 2440, so
+ * there's no "+1" in the array size.
+ */
+ u32 saved[(S3C2410_SDIIMSK-S3C2410_SDICON)/4];
+
#ifdef CONFIG_CPU_FREQ
struct notifier_block freq_transition;
#endif