]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/meta-ti-glsdk.git/blob - recipes-kernel/linux/linux-omap-2.6.39/sakoman/0013-Enable-the-use-of-SDIO-card-interrupts.patch
linux-omap 2.6.39: add MFD patch set and refresh other patches
[glsdk/meta-ti-glsdk.git] / recipes-kernel / linux / linux-omap-2.6.39 / sakoman / 0013-Enable-the-use-of-SDIO-card-interrupts.patch
1 From 948eeb1f03da5fca0f6734c10efbc35ad63a1d08 Mon Sep 17 00:00:00 2001
2 From: David Vrabel <david.vrabel@csr.com>
3 Date: Fri, 2 Apr 2010 08:42:22 -0700
4 Subject: [PATCH 13/32] Enable the use of SDIO card interrupts.
6 FCLK must be enabled while SDIO interrupts are enabled or the MMC
7 module won't wake-up (even though ENAWAKEUP in SYSCONFIG and IWE in
8 HTCL have been set).  Enabling the MMC module to wake-up would require
9 configuring the MMC module (and the mmci_dat[1] GPIO when the CORE
10 power domain is OFF) as wake-up sources in the PRCM.
12 The writes to STAT and ISE when starting a command are unnecessary and
13 have been removed.
15 Signed-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(-)
20 diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
21 index 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);
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);
117 +       if (host->sdio_int)
118 +               int_en_mask |= CIRQ;
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 -       }
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. */
149         dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
150  
151 +       if (status & CIRQ)
152 +               card_irq = true;
154 +       if (host->mrq == NULL)
155 +               goto out;
157 +       data = host->data;
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);
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);
175 +out:
176         spin_unlock(&host->irq_lock);
177  
178 +       if (card_irq)
179 +               mmc_signal_sdio_irq(host->mmc);
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;
194 +       spin_lock_irqsave(&host->irq_lock, flags);
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);
226 +       spin_unlock_irqrestore(&host->irq_lock, flags);
227 +}
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 -- 
287 1.6.6.1