summaryrefslogtreecommitdiffstats
path: root/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0013-Enable-the-use-of-SDIO-card-interrupts.patch
diff options
context:
space:
mode:
Diffstat (limited to 'extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0013-Enable-the-use-of-SDIO-card-interrupts.patch')
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0013-Enable-the-use-of-SDIO-card-interrupts.patch288
1 files changed, 288 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0013-Enable-the-use-of-SDIO-card-interrupts.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0013-Enable-the-use-of-SDIO-card-interrupts.patch
new file mode 100644
index 00000000..59d5ec47
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0013-Enable-the-use-of-SDIO-card-interrupts.patch
@@ -0,0 +1,288 @@
1From 948eeb1f03da5fca0f6734c10efbc35ad63a1d08 Mon Sep 17 00:00:00 2001
2From: David Vrabel <david.vrabel@csr.com>
3Date: Fri, 2 Apr 2010 08:42:22 -0700
4Subject: [PATCH 13/32] Enable the use of SDIO card interrupts.
5
6FCLK must be enabled while SDIO interrupts are enabled or the MMC
7module won't wake-up (even though ENAWAKEUP in SYSCONFIG and IWE in
8HTCL have been set). Enabling the MMC module to wake-up would require
9configuring the MMC module (and the mmci_dat[1] GPIO when the CORE
10power domain is OFF) as wake-up sources in the PRCM.
11
12The writes to STAT and ISE when starting a command are unnecessary and
13have been removed.
14
15Signed-off-by: David Vrabel <david.vrabel@csr.com>
16---
17 drivers/mmc/host/omap_hsmmc.c | 118 +++++++++++++++++++++++++++++------------
18 1 files changed, 83 insertions(+), 35 deletions(-)
19
20diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
21index 83f93ab..d57686c 100644
22--- a/drivers/mmc/host/omap_hsmmc.c
23+++ b/drivers/mmc/host/omap_hsmmc.c
24@@ -67,6 +67,7 @@
25 #define SDVS_MASK 0x00000E00
26 #define SDVSCLR 0xFFFFF1FF
27 #define SDVSDET 0x00000400
28+#define ENAWAKEUP (1 << 2)
29 #define AUTOIDLE 0x1
30 #define SDBP (1 << 8)
31 #define DTO 0xe
32@@ -77,10 +78,13 @@
33 #define CLKD_SHIFT 6
34 #define DTO_MASK 0x000F0000
35 #define DTO_SHIFT 16
36+#define CIRQ_ENABLE (1 << 8)
37 #define INT_EN_MASK 0x307F0033
38 #define BWR_ENABLE (1 << 4)
39 #define BRR_ENABLE (1 << 5)
40 #define DTO_ENABLE (1 << 20)
41+#define CTPL (1 << 11)
42+#define CLKEXTFREE (1 << 16)
43 #define INIT_STREAM (1 << 1)
44 #define DP_SELECT (1 << 21)
45 #define DDIR (1 << 4)
46@@ -88,10 +92,12 @@
47 #define MSBS (1 << 5)
48 #define BCE (1 << 1)
49 #define FOUR_BIT (1 << 1)
50+#define IWE (1 << 24)
51 #define DW8 (1 << 5)
52 #define CC 0x1
53 #define TC 0x02
54 #define OD 0x1
55+#define CIRQ (1 << 8)
56 #define ERR (1 << 15)
57 #define CMD_TIMEOUT (1 << 16)
58 #define DATA_TIMEOUT (1 << 20)
59@@ -186,6 +192,7 @@ struct omap_hsmmc_host {
60 int protect_card;
61 int reqs_blocked;
62 int use_reg;
63+ int sdio_int;
64
65 struct omap_mmc_platform_data *pdata;
66 };
67@@ -598,7 +605,7 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
68 ;
69
70 OMAP_HSMMC_WRITE(host->base, SYSCONFIG,
71- OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE);
72+ OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE | ENAWAKEUP);
73
74 if (host->id == OMAP_MMC1_DEVID) {
75 if (host->power_mode != MMC_POWER_OFF &&
76@@ -613,7 +620,7 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
77 }
78
79 OMAP_HSMMC_WRITE(host->base, HCTL,
80- OMAP_HSMMC_READ(host->base, HCTL) | hctl);
81+ OMAP_HSMMC_READ(host->base, HCTL) | hctl | IWE);
82
83 OMAP_HSMMC_WRITE(host->base, CAPA,
84 OMAP_HSMMC_READ(host->base, CAPA) | capa);
85@@ -627,7 +634,7 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
86 ;
87
88 OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
89- OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
90+ OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK | CIRQ);
91 OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
92
93 /* Do not initialize card-specific things if the power is off */
94@@ -791,22 +798,19 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
95 struct mmc_data *data)
96 {
97 int cmdreg = 0, resptype = 0, cmdtype = 0;
98+ int int_en_mask = INT_EN_MASK;
99
100 dev_dbg(mmc_dev(host->mmc), "%s: CMD%d, argument 0x%08x\n",
101 mmc_hostname(host->mmc), cmd->opcode, cmd->arg);
102 host->cmd = cmd;
103
104- /*
105- * Clear status bits and enable interrupts
106- */
107- OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
108- OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
109-
110 if (host->use_dma)
111- OMAP_HSMMC_WRITE(host->base, IE,
112- INT_EN_MASK & ~(BRR_ENABLE | BWR_ENABLE));
113- else
114- OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
115+ int_en_mask &= ~(BRR_ENABLE | BWR_ENABLE);
116+
117+ if (host->sdio_int)
118+ int_en_mask |= CIRQ;
119+
120+ OMAP_HSMMC_WRITE(host->base, IE, int_en_mask);
121
122 host->response_busy = 0;
123 if (cmd->flags & MMC_RSP_PRESENT) {
124@@ -1019,23 +1023,26 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
125 {
126 struct omap_hsmmc_host *host = dev_id;
127 struct mmc_data *data;
128- int end_cmd = 0, end_trans = 0, status;
129+ u32 status;
130+ int end_cmd = 0, end_trans = 0;
131+ bool card_irq = false;
132
133 spin_lock(&host->irq_lock);
134
135- if (host->mrq == NULL) {
136- OMAP_HSMMC_WRITE(host->base, STAT,
137- OMAP_HSMMC_READ(host->base, STAT));
138- /* Flush posted write */
139- OMAP_HSMMC_READ(host->base, STAT);
140- spin_unlock(&host->irq_lock);
141- return IRQ_HANDLED;
142- }
143-
144- data = host->data;
145 status = OMAP_HSMMC_READ(host->base, STAT);
146+ OMAP_HSMMC_WRITE(host->base, STAT, status);
147+ OMAP_HSMMC_READ(host->base, STAT); /* Flush posted write. */
148+
149 dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
150
151+ if (status & CIRQ)
152+ card_irq = true;
153+
154+ if (host->mrq == NULL)
155+ goto out;
156+
157+ data = host->data;
158+
159 if (status & ERR) {
160 #ifdef CONFIG_MMC_DEBUG
161 omap_hsmmc_report_irq(host, status);
162@@ -1085,17 +1092,16 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
163 }
164 }
165
166- OMAP_HSMMC_WRITE(host->base, STAT, status);
167- /* Flush posted write */
168- OMAP_HSMMC_READ(host->base, STAT);
169-
170 if (end_cmd || ((status & CC) && host->cmd))
171 omap_hsmmc_cmd_done(host, host->cmd);
172 if ((end_trans || (status & TC)) && host->mrq)
173 omap_hsmmc_xfer_done(host, data);
174-
175+out:
176 spin_unlock(&host->irq_lock);
177
178+ if (card_irq)
179+ mmc_signal_sdio_irq(host->mmc);
180+
181 return IRQ_HANDLED;
182 }
183
184@@ -1643,6 +1649,47 @@ static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card)
185 mmc_slot(host).init_card(card);
186 }
187
188+static void omap_hsmmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
189+{
190+ struct omap_hsmmc_host *host = mmc_priv(mmc);
191+ u32 ie, con;
192+ unsigned long flags;
193+
194+ spin_lock_irqsave(&host->irq_lock, flags);
195+
196+ /*
197+ * When interrupts are enabled, CTPL must be set to enable
198+ * DAT1 input buffer (or the card interrupt is always
199+ * asserted) and FCLK must be enabled as wake-up does not
200+ * work. Take care to disable FCLK after all the register
201+ * accesses as they might not complete if FCLK is off.
202+ *
203+ * FIXME: if the MMC module (and the mmci_dat[1] GPIO when the
204+ * CORE power domain is OFF) are configured as a wake-up
205+ * sources in the PRCM, then FCLK could be switched off. This
206+ * might add too much latency.
207+ */
208+ con = OMAP_HSMMC_READ(host->base, CON);
209+ ie = OMAP_HSMMC_READ(host->base, IE);
210+ if (enable) {
211+ clk_enable(host->fclk);
212+ ie |= CIRQ_ENABLE;
213+ con |= CTPL | CLKEXTFREE;
214+ host->sdio_int = 1;
215+ } else {
216+ ie &= ~CIRQ_ENABLE;
217+ con &= ~(CTPL | CLKEXTFREE);
218+ host->sdio_int = 0;
219+ }
220+ OMAP_HSMMC_WRITE(host->base, CON, con);
221+ OMAP_HSMMC_WRITE(host->base, IE, ie);
222+ OMAP_HSMMC_READ(host->base, IE); /* flush posted write */
223+ if (!enable)
224+ clk_disable(host->fclk);
225+
226+ spin_unlock_irqrestore(&host->irq_lock, flags);
227+}
228+
229 static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host)
230 {
231 u32 hctl, capa, value;
232@@ -1657,14 +1704,14 @@ static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host)
233 }
234
235 value = OMAP_HSMMC_READ(host->base, HCTL) & ~SDVS_MASK;
236- OMAP_HSMMC_WRITE(host->base, HCTL, value | hctl);
237+ OMAP_HSMMC_WRITE(host->base, HCTL, value | hctl | IWE);
238
239 value = OMAP_HSMMC_READ(host->base, CAPA);
240 OMAP_HSMMC_WRITE(host->base, CAPA, value | capa);
241
242 /* Set the controller to AUTO IDLE mode */
243 value = OMAP_HSMMC_READ(host->base, SYSCONFIG);
244- OMAP_HSMMC_WRITE(host->base, SYSCONFIG, value | AUTOIDLE);
245+ OMAP_HSMMC_WRITE(host->base, SYSCONFIG, value | AUTOIDLE | ENAWAKEUP);
246
247 /* Set SD bus power bit */
248 set_sd_bus_power(host);
249@@ -1918,7 +1965,7 @@ static const struct mmc_host_ops omap_hsmmc_ops = {
250 .get_cd = omap_hsmmc_get_cd,
251 .get_ro = omap_hsmmc_get_ro,
252 .init_card = omap_hsmmc_init_card,
253- /* NYET -- enable_sdio_irq */
254+ .enable_sdio_irq = omap_hsmmc_enable_sdio_irq,
255 };
256
257 static const struct mmc_host_ops omap_hsmmc_ps_ops = {
258@@ -1929,7 +1976,7 @@ static const struct mmc_host_ops omap_hsmmc_ps_ops = {
259 .get_cd = omap_hsmmc_get_cd,
260 .get_ro = omap_hsmmc_get_ro,
261 .init_card = omap_hsmmc_init_card,
262- /* NYET -- enable_sdio_irq */
263+ .enable_sdio_irq = omap_hsmmc_enable_sdio_irq,
264 };
265
266 #ifdef CONFIG_DEBUG_FS
267@@ -2145,7 +2192,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
268 mmc->max_seg_size = mmc->max_req_size;
269
270 mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
271- MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE;
272+ MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE |
273+ MMC_CAP_SDIO_IRQ;
274
275 mmc->caps |= mmc_slot(host).caps;
276 if (mmc->caps & MMC_CAP_8_BIT_DATA)
277@@ -2224,7 +2272,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
278 pdata->resume = omap_hsmmc_resume_cdirq;
279 }
280
281- OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
282+ OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK | CIRQ);
283 OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
284
285 mmc_host_lazy_disable(host->mmc);
286--
2871.6.6.1
288