summaryrefslogtreecommitdiffstats
path: root/recipes/linux/linux-openmoko-2.6.32/0005-save_regs.patch.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/linux/linux-openmoko-2.6.32/0005-save_regs.patch.patch')
-rw-r--r--recipes/linux/linux-openmoko-2.6.32/0005-save_regs.patch.patch140
1 files changed, 140 insertions, 0 deletions
diff --git a/recipes/linux/linux-openmoko-2.6.32/0005-save_regs.patch.patch b/recipes/linux/linux-openmoko-2.6.32/0005-save_regs.patch.patch
new file mode 100644
index 0000000000..7873f850e4
--- /dev/null
+++ b/recipes/linux/linux-openmoko-2.6.32/0005-save_regs.patch.patch
@@ -0,0 +1,140 @@
+From f143dfe95e9b48aebc8fad111086a25c915bf479 Mon Sep 17 00:00:00 2001
+From: Radek Polak <psonek2@seznam.cz>
+Date: Fri, 9 Apr 2010 09:22:23 +0200
+Subject: [PATCH 05/14] save_regs.patch
+
+With this patch wifi can survive suspend.
+---
+ drivers/mmc/core/core.c | 3 +-
+ drivers/mmc/host/s3cmci.c | 46 +++++++++++++++++++++++++++++++++++++++++++-
+ drivers/mmc/host/s3cmci.h | 8 +++++++
+ include/linux/mmc/core.h | 2 +
+ 4 files changed, 56 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
+index 7dab2e5..7df08dd 100644
+--- a/drivers/mmc/core/core.c
++++ b/drivers/mmc/core/core.c
+@@ -59,10 +59,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 fba147c..06423cb 100644
+--- a/drivers/mmc/host/s3cmci.c
++++ b/drivers/mmc/host/s3cmci.c
+@@ -1879,19 +1879,61 @@ MODULE_DEVICE_TABLE(platform, s3cmci_driver_ids);
+
+ #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 device *dev)
+ {
+ struct mmc_host *mmc = platform_get_drvdata(to_platform_device(dev));
+ struct pm_message event = { PM_EVENT_SUSPEND };
+
+- return mmc_suspend_host(mmc, event);
++ return save_regs(mmc);
+ }
+
+ static int s3cmci_resume(struct device *dev)
+ {
+ struct mmc_host *mmc = platform_get_drvdata(to_platform_device(dev));
+
+- return mmc_resume_host(mmc);
++ return restore_regs(mmc);
+ }
+
+ static struct dev_pm_ops s3cmci_pm = {
+diff --git a/drivers/mmc/host/s3cmci.h b/drivers/mmc/host/s3cmci.h
+index c76b53d..551e715 100644
+--- a/drivers/mmc/host/s3cmci.h
++++ b/drivers/mmc/host/s3cmci.h
+@@ -8,6 +8,8 @@
+ * published by the Free Software Foundation.
+ */
+
++#include <mach/regs-sdi.h>
++
+ enum s3cmci_waitfor {
+ COMPLETION_NONE,
+ COMPLETION_FINALIZE,
+@@ -27,6 +29,12 @@ struct s3cmci_host {
+ int irq;
+ int irq_cd;
+ int dma;
++ /*
++ * 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];
+
+ unsigned long clk_rate;
+ unsigned long clk_div;
+diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
+index e4898e9..b49d674 100644
+--- a/include/linux/mmc/core.h
++++ b/include/linux/mmc/core.h
+@@ -129,6 +129,8 @@ struct mmc_request {
+ struct mmc_host;
+ struct mmc_card;
+
++extern void mmc_flush_scheduled_work(void);
++
+ extern void mmc_wait_for_req(struct mmc_host *, struct mmc_request *);
+ extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
+ extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *,
+--
+1.7.1
+