1 From ff31834cfaac386f94ddd65fab8b87d090c69bcc Mon Sep 17 00:00:00 2001
2 From: Mike Westerhof <mwester@dls.net>
3 Date: Thu, 13 Nov 2008 20:38:35 +0000
4 Subject: [PATCH] fix-gta01-s3c-mci-stop-clock-when-idle.patch
6 This patch, based on the work done by Andy Green for the Glamo mci
7 driver, makes sure that the SD clock only runs during data transfers.
8 This can be overridden on the kernel command line if desired. Also
9 added is the ability for the maximum SD clock speed to be limited.
11 Signed-off-by: Mike Westerhof (mwester@dls.net)
13 drivers/mmc/host/s3cmci.c | 113 +++++++++++++++++++++++++++++++++++++++++++--
14 1 files changed, 109 insertions(+), 4 deletions(-)
16 diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
17 index edba055..8f88721 100644
18 --- a/drivers/mmc/host/s3cmci.c
19 +++ b/drivers/mmc/host/s3cmci.c
21 #include <linux/mmc/host.h>
22 #include <linux/platform_device.h>
23 #include <linux/irq.h>
24 +#include <linux/delay.h>
25 +#include <linux/spinlock.h>
28 #include <asm/dma-mapping.h>
31 #define DRIVER_NAME "s3c-mci"
33 +static spinlock_t clock_lock;
36 + * Max SD clock rate (in Hz)
38 + * you can override this on the kernel command line using
40 + * s3cmci.sd_max_clk=10000000
45 +static int sd_max_clk = 25000000;
46 +module_param(sd_max_clk, int, 0644);
49 + * SD allow SD clock to run while idle
51 + * you can override this on kernel commandline using
53 + * s3cmci.sd_idleclk=0
58 +static int sd_idleclk; /* disallow idle clock by default */
59 +module_param(sd_idleclk, int, 0644);
61 +/* used to stash real idleclk state in suspend: we force it to run in there */
62 +static int suspend_sd_idleclk;
67 @@ -368,6 +401,40 @@ static void pio_tasklet(unsigned long data)
68 enable_irq(host->irq);
71 +static void __s3cmci_enable_clock(struct s3cmci_host *host)
74 + unsigned long flags;
76 + /* enable the clock if clock rate is > 0 */
77 + if (host->real_rate) {
78 + spin_lock_irqsave(&clock_lock, flags);
80 + mci_con = readl(host->base + S3C2410_SDICON);
81 + mci_con |= S3C2410_SDICON_CLOCKTYPE;
82 + writel(mci_con, host->base + S3C2410_SDICON);
84 + spin_unlock_irqrestore(&clock_lock, flags);
88 +static void __s3cmci_disable_clock(struct s3cmci_host *host)
91 + unsigned long flags;
94 + spin_lock_irqsave(&clock_lock, flags);
96 + mci_con = readl(host->base + S3C2410_SDICON);
97 + mci_con &= ~S3C2410_SDICON_CLOCKTYPE;
98 + writel(mci_con, host->base + S3C2410_SDICON);
100 + spin_unlock_irqrestore(&clock_lock, flags);
106 * ISR for SDI Interface IRQ
107 * Communication between driver and ISR works as follows:
108 @@ -749,6 +816,7 @@ static void finalize_request(struct s3cmci_host *host)
112 + __s3cmci_disable_clock(host);
113 host->complete_what = COMPLETION_NONE;
115 mmc_request_done(host->mmc, mrq);
116 @@ -1005,6 +1073,7 @@ static void s3cmci_send_request(struct mmc_host *mmc)
120 + __s3cmci_enable_clock(host);
121 s3cmci_send_command(host, cmd);
122 enable_irq(host->irq);
124 @@ -1087,14 +1156,30 @@ static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
125 if ((ios->power_mode == MMC_POWER_ON)
126 || (ios->power_mode == MMC_POWER_UP)) {
128 - dbg(host, dbg_conf, "running at %lukHz (requested: %ukHz).\n",
129 - host->real_rate/1000, ios->clock/1000);
130 + dbg(host, dbg_conf,
131 + "powered (vdd: %d), clk: %lukHz div=%lu (req: %ukHz),"
132 + " bus width: %d\n", ios->vdd, host->real_rate / 1000,
133 + host->clk_div * (host->prescaler + 1),
134 + ios->clock / 1000, ios->bus_width);
136 + /* After power-up, we need to give the card 74 clocks to
137 + * initialize, so sleep just a moment before we disable
144 dbg(host, dbg_conf, "powered down.\n");
147 host->bus_width = ios->bus_width;
149 + /* No need to run the clock until we have data to move */
151 + __s3cmci_disable_clock(host);
152 + dbg(host, dbg_conf, "SD clock disabled when idle.\n");
156 static void s3cmci_reset(struct s3cmci_host *host)
157 @@ -1267,7 +1352,7 @@ static int s3cmci_probe(struct platform_device *pdev, int is2440)
158 mmc->ocr_avail = host->pdata->ocr_avail;
159 mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
160 mmc->f_min = host->clk_rate / (host->clk_div * 256);
161 - mmc->f_max = host->clk_rate / host->clk_div;
162 + mmc->f_max = sd_max_clk;
164 mmc->max_blk_count = 4095;
165 mmc->max_blk_size = 4095;
166 @@ -1354,14 +1439,33 @@ static int s3cmci_probe_2440(struct platform_device *dev)
167 static int s3cmci_suspend(struct platform_device *dev, pm_message_t state)
169 struct mmc_host *mmc = platform_get_drvdata(dev);
170 + struct s3cmci_host *host = mmc_priv(mmc);
173 + /* Ensure clock is running so it will be running on resume */
174 + __s3cmci_enable_clock(host);
176 - return mmc_suspend_host(mmc, state);
177 + /* We will do more commands, make sure the clock stays running,
178 + * and save our state so that we can restore it on resume.
180 + suspend_sd_idleclk = sd_idleclk;
183 + ret = mmc_suspend_host(mmc, state);
185 + /* so that when we resume, we use any modified max rate */
186 + mmc->f_max = sd_max_clk;
191 static int s3cmci_resume(struct platform_device *dev)
193 struct mmc_host *mmc = platform_get_drvdata(dev);
195 + /* Put the sd_idleclk state back to what it was */
196 + sd_idleclk = suspend_sd_idleclk;
198 return mmc_resume_host(mmc);
201 @@ -1398,6 +1502,7 @@ static struct platform_driver s3cmci_driver_2440 = {
203 static int __init s3cmci_init(void)
205 + spin_lock_init(&clock_lock);
206 platform_driver_register(&s3cmci_driver_2410);
207 platform_driver_register(&s3cmci_driver_2412);
208 platform_driver_register(&s3cmci_driver_2440);