add support for target 3c24xx (more known as Openmoko GTA02 "Freerunner") and merge...
[openwrt.git] / target / linux / s3c24xx / patches / 0054-atheros_2_0_hcd.patch.patch
1 From 3a9e6d01e200d3caab806474dcf870b7fc8c113d Mon Sep 17 00:00:00 2001
2 From: mokopatches <mokopatches@openmoko.org>
3 Date: Fri, 25 Jul 2008 22:21:24 +0100
4 Subject: [PATCH] atheros_2_0_hcd.patch
5
6 ---
7  drivers/sdio/hcd/Kconfig               |   14 +
8  drivers/sdio/hcd/Makefile              |    1 +
9  drivers/sdio/hcd/s3c24xx/Makefile      |    2 +
10  drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.c | 1502 ++++++++++++++++++++++++++++++++
11  drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.h |   67 ++
12  5 files changed, 1586 insertions(+), 0 deletions(-)
13  create mode 100644 drivers/sdio/hcd/Kconfig
14  create mode 100644 drivers/sdio/hcd/Makefile
15  create mode 100644 drivers/sdio/hcd/s3c24xx/Makefile
16  create mode 100644 drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.c
17  create mode 100644 drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.h
18
19 diff --git a/drivers/sdio/hcd/Kconfig b/drivers/sdio/hcd/Kconfig
20 new file mode 100644
21 index 0000000..e4d8397
22 --- /dev/null
23 +++ b/drivers/sdio/hcd/Kconfig
24 @@ -0,0 +1,14 @@
25 +config SDIO_S3C24XX
26 +       tristate "Samsung s3c24xx host controller"
27 +       depends on PLAT_S3C24XX && SDIO
28 +       default m
29 +       help
30 +         good luck.
31 +
32 +config SDIO_S3C24XX_DMA
33 +       bool "Samsung s3c24xx host controller DMA I/O"
34 +       depends on SDIO_S3C24XX
35 +       default n
36 +       help
37 +         good luck.
38 +
39 diff --git a/drivers/sdio/hcd/Makefile b/drivers/sdio/hcd/Makefile
40 new file mode 100644
41 index 0000000..e2401e2
42 --- /dev/null
43 +++ b/drivers/sdio/hcd/Makefile
44 @@ -0,0 +1 @@
45 +obj-$(CONFIG_PLAT_S3C24XX)             += s3c24xx/
46 diff --git a/drivers/sdio/hcd/s3c24xx/Makefile b/drivers/sdio/hcd/s3c24xx/Makefile
47 new file mode 100644
48 index 0000000..d2d099c
49 --- /dev/null
50 +++ b/drivers/sdio/hcd/s3c24xx/Makefile
51 @@ -0,0 +1,2 @@
52 +obj-$(CONFIG_PLAT_S3C24XX) += sdio_s3c24xx_hcd.o
53 +sdio_s3c24xx_hcd-objs := s3c24xx_hcd.o
54 diff --git a/drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.c b/drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.c
55 new file mode 100644
56 index 0000000..3c4758b
57 --- /dev/null
58 +++ b/drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.c
59 @@ -0,0 +1,1502 @@
60 +/*
61 + * s3c24xx_hcd.c - Samsung S3C MCI driver, Atheros SDIO API compatible.
62 + *
63 + * Copyright (C) 2007 by OpenMoko, Inc.
64 + * Written by Samuel Ortiz <sameo@openedhand.com>
65 + * All Rights Reserved
66 + *
67 + * This program is free software; you can redistribute it and/or modify
68 + * it under the terms of the GNU General Public License as published by
69 + * the Free Software Foundation; either version 2 of the License, or
70 + * (at your option) any later version.
71 + *
72 + * This program is distributed in the hope that it will be useful,
73 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
74 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
75 + * GNU General Public License for more details.
76 + *
77 + * You should have received a copy of the GNU General Public License along
78 + * with this program; if not, write to the Free Software Foundation, Inc.,
79 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
80 + */
81 +
82 +#include <linux/kernel.h>
83 +#include <linux/interrupt.h>
84 +#include <linux/list.h>
85 +#include <linux/dma-mapping.h>
86 +#include <linux/errno.h>
87 +#include <linux/platform_device.h>
88 +#include <linux/device.h>
89 +#include <linux/clk.h>
90 +#include <linux/fs.h>
91 +#include <linux/ioport.h>
92 +#include <linux/workqueue.h>
93 +#include <linux/completion.h>
94 +#include <linux/delay.h>
95 +#include <linux/seq_file.h>
96 +#include <linux/debugfs.h>
97 +
98 +#include <linux/sdio/ctsystem.h>
99 +#include <linux/sdio/sdio_busdriver.h>
100 +#include <linux/sdio/sdio_lib.h>
101 +
102 +#include <asm/io.h>
103 +#include <asm/irq.h>
104 +#include <asm/uaccess.h>
105 +#include <asm/dma.h>
106 +#include <asm/dma-mapping.h>
107 +
108 +#include <asm/arch/regs-sdi.h>
109 +#include <asm/arch/regs-gpio.h>
110 +#include <asm/arch/mci.h>
111 +#include <asm/arch/gta02.h>
112 +
113 +#include "s3c24xx_hcd.h"
114 +
115 +#define DESCRIPTION "S3c24xx SDIO host controller"
116 +#define AUTHOR "Samuel Ortiz <sameo@openedhand.com>"
117 +
118 +#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
119 +
120 +static struct s3c2410_dma_client s3c24xx_hcd_dma_client = {
121 +       .name           = "s3c24xx_hcd",
122 +};
123 +
124 +extern struct platform_device s3c_device_sdi;
125 +
126 +static void dump_request(struct s3c24xx_hcd_context * context)
127 +{
128 +    if (context->hcd.pCurrentRequest != NULL) {
129 +        DBG_PRINT(SDDBG_ERROR, ("Current Request Command:%d, ARG:0x%8.8X flags: 0x%04x\n",
130 +                               context->hcd.pCurrentRequest->Command, context->hcd.pCurrentRequest->Argument,
131 +                               context->hcd.pCurrentRequest->Flags));
132 +        if (IS_SDREQ_DATA_TRANS(context->hcd.pCurrentRequest->Flags)) {
133 +            DBG_PRINT(SDDBG_ERROR, ("Data %s, Blocks: %d, BlockLen:%d Remaining: %d \n",
134 +                      IS_SDREQ_WRITE_DATA(context->hcd.pCurrentRequest->Flags) ? "WRITE":"READ",
135 +                      context->hcd.pCurrentRequest->BlockCount,
136 +                      context->hcd.pCurrentRequest->BlockLen,
137 +                      context->hcd.pCurrentRequest->DataRemaining));
138 +        }
139 +    }
140 +}
141 +
142 +static void s3c24xx_dump_regs(struct s3c24xx_hcd_context * context)
143 +{
144 +       u32 con, pre, cmdarg, cmdcon, cmdsta, r0, r1, r2, r3, timer, bsize;
145 +       u32 datcon, datcnt, datsta, fsta, imask;
146 +
147 +       con     = readl(context->base + S3C2410_SDICON);
148 +       pre     = readl(context->base + S3C2410_SDIPRE);
149 +       cmdarg  = readl(context->base + S3C2410_SDICMDARG);
150 +       cmdcon  = readl(context->base + S3C2410_SDICMDCON);
151 +       cmdsta  = readl(context->base + S3C2410_SDICMDSTAT);
152 +       r0      = readl(context->base + S3C2410_SDIRSP0);
153 +       r1      = readl(context->base + S3C2410_SDIRSP1);
154 +       r2      = readl(context->base + S3C2410_SDIRSP2);
155 +       r3      = readl(context->base + S3C2410_SDIRSP3);
156 +       timer   = readl(context->base + S3C2410_SDITIMER);
157 +       bsize   = readl(context->base + S3C2410_SDIBSIZE);
158 +       datcon  = readl(context->base + S3C2410_SDIDCON);
159 +       datcnt  = readl(context->base + S3C2410_SDIDCNT);
160 +       datsta  = readl(context->base + S3C2410_SDIDSTA);
161 +       fsta    = readl(context->base + S3C2410_SDIFSTA);
162 +       imask   = readl(context->base + S3C2440_SDIIMSK);
163 +
164 +       printk("SDICON:    0x%08x\n", con);
165 +       printk("SDIPRE:    0x%08x\n", pre);
166 +       printk("SDICmdArg: 0x%08x\n", cmdarg);
167 +       printk("SDICmdCon: 0x%08x\n", cmdcon);
168 +       printk("SDICmdSta: 0x%08x\n", cmdsta);
169 +       printk("SDIRSP0:   0x%08x\n", r0);
170 +       printk("SDIRSP1:   0x%08x\n", r1);
171 +       printk("SDIRSP2:   0x%08x\n", r2);
172 +       printk("SDIRSP3:   0x%08x\n", r3);
173 +       printk("SDIDTimer: 0x%08x\n", timer);
174 +       printk("SDIBSize:  0x%08x\n", bsize);
175 +       printk("SDIDatCon: 0x%08x\n", datcon);
176 +       printk("SDIDatCnt: 0x%08x\n", datcnt);
177 +       printk("SDIDatSta: 0x%08x\n", datsta);
178 +       printk("SDIFSta:   0x%08x\n", fsta);
179 +       printk("SDIIntMsk: 0x%08x\n", imask);
180 +}
181 +
182 +static inline void s3c24xx_hcd_clear_imask(struct s3c24xx_hcd_context * context)
183 +{
184 +       if (context->int_sdio) {
185 +               writel(S3C2410_SDIIMSK_SDIOIRQ | S3C2410_SDIIMSK_READWAIT,
186 +                      context->base + S3C2440_SDIIMSK);
187 +       }  else {
188 +               writel(0, context->base + S3C2440_SDIIMSK);
189 +       }
190 +}
191 +
192 +static inline void s3c24xx_hcd_set_imask(struct s3c24xx_hcd_context * context)
193 +{
194 +       writel(context->int_mask, context->base + S3C2440_SDIIMSK);
195 +}
196 +
197 +
198 +static inline void s3c24xx_hcd_clear_dsta(struct s3c24xx_hcd_context * context)
199 +{
200 +       u32 dsta;
201 +
202 +       dsta = readl(context->base + S3C2410_SDIDSTA);
203 +       writel(dsta, context->base + S3C2410_SDIDSTA);
204 +}
205 +
206 +static inline void s3c24xx_hcd_clear_csta(struct s3c24xx_hcd_context * context)
207 +{
208 +       u32 csta, csta_clear = 0;
209 +
210 +       csta = readl(context->base + S3C2410_SDICMDSTAT);
211 +
212 +       if (csta & S3C2410_SDICMDSTAT_CRCFAIL)
213 +               csta_clear |= S3C2410_SDICMDSTAT_CRCFAIL;
214 +       if (csta & S3C2410_SDICMDSTAT_CMDSENT)
215 +               csta_clear |= S3C2410_SDICMDSTAT_CMDSENT;
216 +       if (csta & S3C2410_SDICMDSTAT_CMDTIMEOUT)
217 +               csta_clear |= S3C2410_SDICMDSTAT_CMDTIMEOUT;
218 +       if (csta & S3C2410_SDICMDSTAT_RSPFIN)
219 +               csta_clear |= S3C2410_SDICMDSTAT_RSPFIN;
220 +
221 +       writel(csta_clear, context->base + S3C2410_SDICMDSTAT);
222 +}
223 +
224 +static inline void s3c24xx_hcd_clear_sta(struct s3c24xx_hcd_context * context)
225 +{
226 +       u32 csta, dsta, csta_clear = 0, dsta_clear = 0;
227 +
228 +       csta = readl(context->base + S3C2410_SDICMDSTAT);
229 +       dsta = readl(context->base + S3C2410_SDIDSTA);
230 +
231 +       if (csta & S3C2410_SDICMDSTAT_CRCFAIL)
232 +               csta_clear |= S3C2410_SDICMDSTAT_CRCFAIL;
233 +       if (csta & S3C2410_SDICMDSTAT_CMDSENT)
234 +               csta_clear |= S3C2410_SDICMDSTAT_CMDSENT;
235 +       if (csta & S3C2410_SDICMDSTAT_CMDTIMEOUT)
236 +               csta_clear |= S3C2410_SDICMDSTAT_CMDTIMEOUT;
237 +       if (csta & S3C2410_SDICMDSTAT_RSPFIN)
238 +               csta_clear |= S3C2410_SDICMDSTAT_RSPFIN;
239 +
240 +
241 +       if (dsta & S3C2410_SDIDSTA_RDYWAITREQ)
242 +               dsta_clear |= S3C2410_SDIDSTA_RDYWAITREQ;
243 +       if (dsta & S3C2410_SDIDSTA_SDIOIRQDETECT)
244 +               dsta_clear |= S3C2410_SDIDSTA_SDIOIRQDETECT;
245 +       if (dsta & S3C2410_SDIDSTA_FIFOFAIL)
246 +               dsta_clear |= S3C2410_SDIDSTA_FIFOFAIL;
247 +       if (dsta & S3C2410_SDIDSTA_CRCFAIL)
248 +               dsta_clear |= S3C2410_SDIDSTA_CRCFAIL;
249 +       if (dsta & S3C2410_SDIDSTA_RXCRCFAIL)
250 +               dsta_clear |= S3C2410_SDIDSTA_RXCRCFAIL;
251 +       if (dsta & S3C2410_SDIDSTA_DATATIMEOUT)
252 +               dsta_clear |= S3C2410_SDIDSTA_DATATIMEOUT;
253 +       if (dsta & S3C2410_SDIDSTA_XFERFINISH)
254 +               dsta_clear |= S3C2410_SDIDSTA_XFERFINISH;
255 +       if (dsta & S3C2410_SDIDSTA_BUSYFINISH)
256 +               dsta_clear |= S3C2410_SDIDSTA_BUSYFINISH;
257 +       if (dsta & S3C2410_SDIDSTA_SBITERR)
258 +               dsta_clear |= S3C2410_SDIDSTA_SBITERR;
259 +
260 +       writel(csta_clear, context->base + S3C2410_SDICMDSTAT);
261 +       writel(dsta_clear, context->base + S3C2410_SDIDSTA);
262 +}
263 +
264 +static inline void s3c24xx_hcd_fifo_reset(struct s3c24xx_hcd_context * context)
265 +{
266 +       u32 fsta;
267 +
268 +       fsta = readl(context->base + S3C2410_SDIFSTA);
269 +       fsta |= S3C2440_SDIFSTA_FIFORESET;
270 +       writel(fsta, context->base + S3C2410_SDIFSTA);
271 +}
272 +
273 +#if 0
274 +static void s3c24xx_hcd_reset(struct s3c24xx_hcd_context * context)
275 +{
276 +       u32 con, counter;
277 +       unsigned long flags;
278 +
279 +       spin_lock_irqsave(&context->lock, flags);
280 +
281 +       con = readl(context->base + S3C2410_SDICON);
282 +
283 +       con |= S3C2440_SDICON_SDRESET;
284 +
285 +       writel(con, context->base + S3C2410_SDICON);
286 +
287 +       counter = 1000;
288 +       while(counter) {
289 +               con = readl(context->base + S3C2410_SDICON);
290 +               if (!(con & S3C2440_SDICON_SDRESET))
291 +                       break;
292 +               counter--;
293 +               mdelay(1);
294 +       }
295 +
296 +       spin_unlock_irqrestore(&context->lock, flags);
297 +}
298 +#endif
299 +
300 +static SDIO_STATUS s3c24xx_hcd_clock_enable(struct s3c24xx_hcd_context * context,
301 +                                           unsigned int clock_rate,
302 +                                           unsigned char enable)
303 +{
304 +       SDIO_STATUS status = SDIO_STATUS_SUCCESS;
305 +       unsigned long flags;
306 +       u32 con;
307 +
308 +       spin_lock_irqsave(&context->lock, flags);
309 +
310 +       con = readl(context->base + S3C2410_SDICON);
311 +
312 +       if (enable && clock_rate) {
313 +               con |= S3C2410_SDICON_CLOCKTYPE;
314 +       } else {
315 +               con &= ~S3C2410_SDICON_CLOCKTYPE;
316 +       }
317 +
318 +       if (clock_rate) {
319 +               int prescaler;
320 +
321 +               for (prescaler = 0; prescaler < 0xff; prescaler++) {
322 +                       context->device.actual_clock_rate =
323 +                               context->device.max_clock_rate / (prescaler + 1);
324 +
325 +                       if (context->device.actual_clock_rate <= clock_rate &&
326 +                           context->device.actual_clock_rate <= context->hcd.MaxClockRate)
327 +                               break;
328 +               }
329 +
330 +               if (prescaler == 0xff)
331 +                       DBG_PRINT(SDDBG_ERROR , ("Using lowest clock rate\n"));
332 +
333 +               writel(prescaler, context->base + S3C2410_SDIPRE);
334 +       }
335 +
336 +       writel(con, context->base + S3C2410_SDICON);
337 +
338 +       spin_unlock_irqrestore(&context->lock, flags);
339 +
340 +       return SDIOErrorToOSError(status);
341 +}
342 +
343 +static void s3c24xx_hcd_set_bus_mode(struct s3c24xx_hcd_context *context,
344 +                                    PSDCONFIG_BUS_MODE_DATA pMode)
345 +{
346 +       u32 datacon;
347 +       unsigned long flags;
348 +
349 +       DBG_PRINT(SDDBG_TRACE , ("SetBusMode\n"));
350 +
351 +       spin_lock_irqsave(&context->lock, flags);
352 +       datacon = readl(context->base + S3C2410_SDIDCON);
353 +
354 +       switch (SDCONFIG_GET_BUSWIDTH(pMode->BusModeFlags)) {
355 +        case SDCONFIG_BUS_WIDTH_1_BIT:
356 +               context->bus_width = 1;
357 +               datacon &= S3C2410_SDIDCON_WIDEBUS;
358 +               break;
359 +        case SDCONFIG_BUS_WIDTH_4_BIT:
360 +               context->bus_width = 4;
361 +               datacon |= S3C2410_SDIDCON_WIDEBUS;
362 +               break;
363 +        default:
364 +               DBG_PRINT(SDDBG_TRACE , ("Unknown bus width: %d\n", SDCONFIG_GET_BUSWIDTH(pMode->BusModeFlags)));
365 +               break;
366 +       }
367 +
368 +       writel(datacon, context->base + S3C2410_SDIDCON);
369 +       spin_unlock_irqrestore(&context->lock, flags);
370 +
371 +       /* Set clock rate and enable clock */
372 +       s3c24xx_hcd_clock_enable(context, pMode->ClockRate, 1);
373 +       pMode->ActualClockRate = context->device.actual_clock_rate;
374 +
375 +       DBG_PRINT(SDDBG_TRACE , ("BUS mode: %d bits wide, actual clock rate: %d kHz (requested %d kHz)\n",
376 +                                context->bus_width, pMode->ActualClockRate / 1000, pMode->ClockRate / 1000));
377 +}
378 +
379 +
380 +static void s3c24xx_hcd_dma_complete(struct s3c24xx_hcd_context * context)
381 +{
382 +       u32 dsta, counter, i;
383 +       PSDREQUEST req;
384 +       SDIO_STATUS status = SDIO_STATUS_ERROR;
385 +
386 +       req = GET_CURRENT_REQUEST(&context->hcd);
387 +       if (req == NULL) {
388 +               DBG_PRINT(SDDBG_ERROR, ("%s(): No current request\n", __FUNCTION__));
389 +               return;
390 +       }
391 +
392 +       if (context->complete == S3C24XX_HCD_DATA_READ) {
393 +               /* DMA READ completion */
394 +               if (context->latest_xfer_size != req->DataRemaining) {
395 +                       DBG_PRINT(SDDBG_ERROR, ("Unexpected read xfer size: %d <-> %d\n",
396 +                                               context->latest_xfer_size, req->DataRemaining));
397 +                       status = SDIO_STATUS_BUS_WRITE_ERROR;
398 +               }
399 +
400 +               counter = 0;
401 +               dsta = readl(context->base + S3C2410_SDIDSTA);
402 +               while (!(dsta & S3C2410_SDIDSTA_XFERFINISH)) {
403 +                       if (counter > 500) {
404 +                               printk("read xfer timed out\n");
405 +                               s3c24xx_dump_regs(context);
406 +                               memcpy(req->pDataBuffer, context->io_buffer,
407 +                                      req->BlockCount * req->BlockLen);
408 +                               printk("Transfer: %dx%d\n", req->BlockCount, req->BlockLen);
409 +                               for (i = 0; i < req->DataRemaining; i++)
410 +                                       printk("0x%x ", *(((char *)context->io_buffer) + i));
411 +                               printk("\n");
412 +                               status = SDIO_STATUS_BUS_READ_TIMEOUT;
413 +                               goto out;
414 +                       }
415 +                       dsta = readl(context->base + S3C2410_SDIDSTA);
416 +                       counter++;
417 +                       mdelay(1);
418 +               };
419 +
420 +               dma_sync_single(NULL, context->io_buffer_dma,
421 +                               req->BlockCount * req->BlockLen, DMA_BIDIRECTIONAL);
422 +
423 +               writel(S3C2410_SDIDSTA_XFERFINISH, context->base + S3C2410_SDIDSTA);
424 +
425 +               memcpy(req->pDataBuffer, context->io_buffer,
426 +                      req->BlockCount * req->BlockLen);
427 +
428 +               req->DataRemaining = 0;
429 +               status = SDIO_STATUS_SUCCESS;
430 +
431 +       } else if (context->complete == S3C24XX_HCD_DATA_WRITE) {
432 +               /* DMA WRITE completion */
433 +               if (context->latest_xfer_size != req->DataRemaining) {
434 +                       DBG_PRINT(SDDBG_ERROR, ("Unexpected write xfer size: %d <-> %d\n",
435 +                                               context->latest_xfer_size, req->DataRemaining));
436 +                       status = SDIO_STATUS_BUS_WRITE_ERROR;
437 +               }
438 +
439 +               dsta = readl(context->base + S3C2410_SDIDSTA);
440 +               counter = 0;
441 +               while (!(dsta & S3C2410_SDIDSTA_XFERFINISH)) {
442 +                       if (counter > 500) {
443 +                               printk("write xfer timed out\n");
444 +                               status = SDIO_STATUS_BUS_WRITE_ERROR;
445 +                               goto out;
446 +                       }
447 +                       dsta = readl(context->base + S3C2410_SDIDSTA);
448 +                       counter++;
449 +                       mdelay(1);
450 +               };
451 +
452 +               writel(S3C2410_SDIDSTA_XFERFINISH, context->base + S3C2410_SDIDSTA);
453 +               req->DataRemaining = 0;
454 +               status = SDIO_STATUS_SUCCESS;
455 +       }
456 +
457 + out:
458 +       req->Status = status;
459 +}
460 +
461 +static void s3c24xx_hcd_pio_complete(struct s3c24xx_hcd_context * context)
462 +{
463 +       u32 fsta, counter;
464 +       u8 *ptr;
465 +       int fifo_count;
466 +       PSDREQUEST req;
467 +       SDIO_STATUS status = SDIO_STATUS_ERROR;
468 +
469 +       req = GET_CURRENT_REQUEST(&context->hcd);
470 +       if (req == NULL) {
471 +               DBG_PRINT(SDDBG_ERROR, ("%s(): No current request\n", __FUNCTION__));
472 +               return;
473 +       }
474 +
475 +       ptr = req->pDataBuffer;
476 +
477 +       if (context->complete == S3C24XX_HCD_DATA_READ) {
478 +               counter = 0;
479 +               DBG_PRINT(SDDBG_TRACE, ("Data read..."));
480 +               do {
481 +                       counter++;
482 +                       fsta = readl(context->base + S3C2410_SDIFSTA);
483 +                       mdelay(1);
484 +                       if (counter > 1000) {
485 +                               DBG_PRINT(SDDBG_ERROR, ("DATA read timeout\n"));
486 +                               status = SDIO_STATUS_BUS_READ_TIMEOUT;
487 +                               s3c24xx_dump_regs(context);
488 +                               goto out;
489 +                       }
490 +               } while(!(fsta & S3C2410_SDIFSTA_RFDET));
491 +               DBG_PRINT(SDDBG_TRACE, ("RX detected\n"));
492 +
493 +               while (1) {
494 +                       counter = 0;
495 +                       fifo_count = (readl(context->base + S3C2410_SDIFSTA) & S3C2410_SDIFSTA_COUNTMASK);
496 +                       while (!fifo_count) {
497 +                               counter++;
498 +                               mdelay(1);
499 +                               if (counter > 500) {
500 +                                       s3c24xx_dump_regs(context);
501 +                                       DBG_PRINT(SDDBG_ERROR, ("No more bytes in FIFO\n"));
502 +                                       goto out;
503 +                               }
504 +                               fifo_count = (readl(context->base + S3C2410_SDIFSTA) & S3C2410_SDIFSTA_COUNTMASK);
505 +                       }
506 +
507 +                       if (fifo_count > req->DataRemaining) {
508 +                               DBG_PRINT(SDDBG_ERROR, ("DATA read, fifo_count %d > expected %d\n", fifo_count, req->DataRemaining));
509 +                               fifo_count = req->DataRemaining;
510 +                       }
511 +
512 +                       req->DataRemaining -= fifo_count;
513 +                       while (fifo_count > 0) {
514 +                               if (context->data_size == 4)
515 +                                       *(ptr) = readl(context->base + S3C2440_SDIDATA);
516 +                               else if (context->data_size == 2)
517 +                                       *(ptr) = readw(context->base + S3C2440_SDIDATA);
518 +                               else
519 +                                       *(ptr) = readb(context->base + S3C2440_SDIDATA);
520 +
521 +                               ptr += context->data_size;
522 +                               fifo_count -= context->data_size;
523 +
524 +                       }
525 +
526 +                       if (!req->DataRemaining) {
527 +                               /* We poll for xfer finish */
528 +                               counter = 0;
529 +                               while (!(readl(context->base + S3C2410_SDIDSTA)
530 +                                                & S3C2410_SDIDSTA_XFERFINISH)) {
531 +                                       counter++;
532 +                                       mdelay(1);
533 +                                       if (counter > 500) {
534 +                                               DBG_PRINT(SDDBG_ERROR, ("RX XFERFINISH missing\n"));
535 +                                               s3c24xx_dump_regs(context);
536 +                                               break;
537 +                                       }
538 +                               }
539 +
540 +                               status = SDIO_STATUS_SUCCESS;
541 +                               goto out;
542 +                       }
543 +               }
544 +
545 +       } else if (context->complete == S3C24XX_HCD_DATA_WRITE) {
546 +               counter = 0;
547 +               DBG_PRINT(SDDBG_TRACE, ("Data write..."));
548 +               do {
549 +                       counter++;
550 +                       fsta = readl(context->base + S3C2410_SDIFSTA);
551 +                       mdelay(1);
552 +                       if (counter > 1000) {
553 +                               DBG_PRINT(SDDBG_ERROR, ("DATA write timeout\n"));
554 +                               status = SDIO_STATUS_BUS_WRITE_ERROR;
555 +                               goto out;
556 +                               break;
557 +                       }
558 +
559 +               } while(!(fsta & S3C2410_SDIFSTA_TFDET));
560 +               DBG_PRINT(SDDBG_TRACE, ("TX detected\n"));
561 +
562 +               while (1) {
563 +                       counter = 0;
564 +                       fifo_count = 63 - (readl(context->base + S3C2410_SDIFSTA) & S3C2410_SDIFSTA_COUNTMASK);
565 +                       while (!fifo_count) {
566 +                               counter++;
567 +                               mdelay(1);
568 +                               if (counter > 500) {
569 +                                       s3c24xx_dump_regs(context);
570 +                                       DBG_PRINT(SDDBG_ERROR, ("No more space in FIFO\n"));
571 +                                       goto out;
572 +                               }
573 +                               fifo_count = 63 - (readl(context->base + S3C2410_SDIFSTA) & S3C2410_SDIFSTA_COUNTMASK);
574 +                       }
575 +
576 +                       if (fifo_count > req->DataRemaining)
577 +                               fifo_count = req->DataRemaining;
578 +
579 +                               req->DataRemaining -= fifo_count;
580 +
581 +                               while (fifo_count > 0) {
582 +                                       if (context->data_size == 4)
583 +                                               writel(*(ptr), context->base + S3C2440_SDIDATA);
584 +                                       else if (context->data_size == 2)
585 +                                               writew(*(ptr), context->base + S3C2440_SDIDATA);
586 +                                       else
587 +                                               writeb(*(ptr), context->base + S3C2440_SDIDATA);
588 +
589 +                                       ptr += context->data_size;
590 +                                       fifo_count -= context->data_size;
591 +                               }
592 +
593 +                               if (!req->DataRemaining) {
594 +                                       /* We poll for xfer finish */
595 +                                       counter = 0;
596 +                                       while (!(readl(context->base + S3C2410_SDIDSTA)
597 +                                                & S3C2410_SDIDSTA_XFERFINISH)) {
598 +                                               counter++;
599 +                                               mdelay(1);
600 +                                               if (counter > 500) {
601 +                                                       DBG_PRINT(SDDBG_ERROR, ("RX XFERFINISH missing\n"));
602 +                                                       s3c24xx_dump_regs(context);
603 +                                                       break;
604 +                                               }
605 +                                       }
606 +
607 +                                       status = SDIO_STATUS_SUCCESS;
608 +                                       goto out;
609 +                               }
610 +               }
611 +
612 +       } else {
613 +               DBG_PRINT(SDDBG_ERROR, ("Wrong context: %d\n", context->complete));
614 +       }
615 +
616 + out:
617 +       req->Status = status;
618 +}
619 +
620 +static void s3c24xx_hcd_io_work(struct work_struct *work)
621 +{
622 +       PSDREQUEST req;
623 +       SDIO_STATUS status = SDIO_STATUS_SUCCESS;
624 +       struct s3c24xx_hcd_context * context =
625 +               container_of(work, struct s3c24xx_hcd_context, io_work);
626 +
627 +       req = GET_CURRENT_REQUEST(&context->hcd);
628 +       if (req == NULL) {
629 +               DBG_PRINT(SDDBG_ERROR, ("%s(): No current request\n", __FUNCTION__));
630 +               return;
631 +       }
632 +
633 +       if (req->Status == SDIO_STATUS_BUS_RESP_TIMEOUT) {
634 +               DBG_PRINT(SDDBG_ERROR, ("### TIMEOUT ###\n"));
635 +               s3c24xx_dump_regs(context);
636 +               goto out;
637 +       }
638 +
639 +       if (context->complete == S3C24XX_HCD_NO_RESPONSE &&
640 +           req->Status == SDIO_STATUS_SUCCESS) {
641 +               DBG_PRINT(SDDBG_TRACE, ("CMD done, Status: %d\n", req->Status));
642 +               printk("CMD done, Status: %d\n", req->Status);
643 +               goto out;
644 +       }
645 +
646 +       if ((context->complete == S3C24XX_HCD_RESPONSE_SHORT ||
647 +            context->complete == S3C24XX_HCD_RESPONSE_LONG ||
648 +            context->complete == S3C24XX_HCD_DATA_READ ||
649 +            context->complete == S3C24XX_HCD_DATA_WRITE) &&
650 +           req->Status == SDIO_STATUS_SUCCESS) {
651 +               u32 resp[4];
652 +
653 +               /* We need to copy the response data and send it over */
654 +               resp[0] = readl(context->base + S3C2410_SDIRSP0);
655 +               resp[1] = readl(context->base + S3C2410_SDIRSP1);
656 +               resp[2] = readl(context->base + S3C2410_SDIRSP2);
657 +               resp[3] = readl(context->base + S3C2410_SDIRSP3);
658 +
659 +               if (GET_SDREQ_RESP_TYPE(req->Flags) != SDREQ_FLAGS_RESP_R2) {
660 +                       DBG_PRINT(SDDBG_TRACE, ("SHORT response: 0x%08x\n", resp[0]));
661 +                       memcpy(&req->Response[1], (u8*)resp, 4);
662 +                       req->Response[5] = (readl(context->base + S3C2410_SDICMDSTAT) & 0xff);
663 +               } else {
664 +                       printk("LONG response: 0x%08x\n", resp[0]);
665 +                       DBG_PRINT(SDDBG_TRACE, ("LONG response: 0x%08x\n", resp[0]));
666 +                       memcpy(&req->Response[1], (u8*)resp, 16);
667 +                       //req->Response[17] = (readl(context->base + S3C2410_SDICMDSTAT) & 0xff);
668 +               }
669 +
670 +               /* There is a data stage */
671 +               if (context->complete == S3C24XX_HCD_DATA_READ ||
672 +                   context->complete == S3C24XX_HCD_DATA_WRITE) {
673 +                       status = SDIO_CheckResponse(&context->hcd, req,
674 +                                                   SDHCD_CHECK_DATA_TRANS_OK);
675 +
676 +                       if (!SDIO_SUCCESS(status)) {
677 +                               DBG_PRINT(SDDBG_ERROR,
678 +                                         ("Target not ready for data xfer\n"));
679 +                               return;
680 +                       }
681 +
682 +                       if (context->dma_en) {
683 +                               dma_sync_single(NULL, context->io_buffer_dma,
684 +                                               req->BlockCount * req->BlockLen, DMA_BIDIRECTIONAL);
685 +
686 +                               s3c2410_dma_ctrl(context->dma_channel, S3C2410_DMAOP_START);
687 +
688 +                               wait_for_completion(&context->dma_complete);
689 +
690 +                               s3c24xx_hcd_dma_complete(context);
691 +                       } else {
692 +                               s3c24xx_hcd_pio_complete(context);
693 +                       }
694 +               }
695 +       }
696 +
697 + out:
698 +       s3c24xx_hcd_clear_sta(context);
699 +       s3c24xx_hcd_clear_imask(context);
700 +
701 +       writel(0, context->base + S3C2410_SDICMDARG);
702 +       writel(0, context->base + S3C2410_SDICMDCON);
703 +
704 +       SDIO_HandleHcdEvent(&context->hcd, EVENT_HCD_TRANSFER_DONE);
705 +}
706 +
707 +static void s3c24xx_hcd_irq_work(struct work_struct *work)
708 +{
709 +       struct s3c24xx_hcd_context * context =
710 +               container_of(work, struct s3c24xx_hcd_context, irq_work);
711 +
712 +       disable_irq(context->io_irq);
713 +
714 +       writel(S3C2410_SDIDSTA_SDIOIRQDETECT, context->base + S3C2410_SDIDSTA);
715 +
716 +       SDIO_HandleHcdEvent(&context->hcd, EVENT_HCD_SDIO_IRQ_PENDING);
717 +
718 +       enable_irq(context->io_irq);
719 +}
720 +
721 +void s3c24xx_hcd_dma_done(struct s3c2410_dma_chan *dma_ch, void *buf_id,
722 +                         int size, enum s3c2410_dma_buffresult result)
723 +{
724 +       struct s3c24xx_hcd_context * context =
725 +               (struct s3c24xx_hcd_context *) buf_id;
726 +
727 +       if (result != S3C2410_RES_OK) {
728 +               DBG_PRINT(SDDBG_ERROR, ("%s(): DMA xfer failed: %d\n", __FUNCTION__, result));
729 +               s3c24xx_dump_regs(context);
730 +       }
731 +
732 +       context->latest_xfer_size = size;
733 +       complete(&context->dma_complete);
734 +}
735 +
736 +static int s3c24xx_hcd_prepare_dma(struct s3c24xx_hcd_context * context)
737 +{
738 +       PSDREQUEST req;
739 +       SDIO_STATUS status = SDIO_STATUS_SUCCESS;
740 +       int read = 0, hwcfg = S3C2410_DISRCC_INC | S3C2410_DISRCC_APB;
741 +       enum s3c2410_dmasrc source = S3C2410_DMASRC_MEM;
742 +
743 +       req = GET_CURRENT_REQUEST(&context->hcd);
744 +       if (req == NULL) {
745 +               DBG_PRINT(SDDBG_ERROR, ("%s(): No current request\n", __FUNCTION__));
746 +               status = SDIO_STATUS_ERROR;
747 +       }
748 +
749 +       if (!context->dma_en) {
750 +               DBG_PRINT(SDDBG_ERROR, ("%s(): DMA is disabled\n", __FUNCTION__));
751 +               status = SDIO_STATUS_ERROR;
752 +       }
753 +
754 +       if (!IS_SDREQ_DATA_TRANS(req->Flags)) {
755 +               DBG_PRINT(SDDBG_ERROR, ("%s(): No data to transfer\n", __FUNCTION__));
756 +               status = SDIO_STATUS_ERROR;
757 +       }
758 +
759 +       if(!IS_SDREQ_WRITE_DATA(req->Flags)) {
760 +               read = 1;
761 +               source = S3C2410_DMASRC_HW;
762 +               hwcfg = S3C2410_DISRCC_APB | 1;
763 +       } else {
764 +               memcpy(context->io_buffer, req->pDataBuffer, req->DataRemaining);
765 +               dma_sync_single(NULL, context->io_buffer_dma,
766 +                               req->BlockCount * req->BlockLen, DMA_BIDIRECTIONAL);
767 +
768 +       }
769 +
770 +       s3c2410_dma_devconfig(context->dma_channel, source, hwcfg,
771 +                             (unsigned long)context->mem->start + S3C2440_SDIDATA);
772 +
773 +       s3c2410_dma_config(context->dma_channel, context->data_size,
774 +                          S3C2410_DCON_CH0_SDI);
775 +                          //(S3C2410_DCON_HWTRIG | S3C2410_DCON_CH0_SDI));
776 +
777 +       s3c2410_dma_set_buffdone_fn(context->dma_channel, s3c24xx_hcd_dma_done);
778 +
779 +//     s3c2410_dma_setflags(context->dma_channel, S3C2410_DMAF_AUTOSTART);
780 +
781 +       s3c2410_dma_ctrl(context->dma_channel, S3C2410_DMAOP_FLUSH);
782 +
783 +       s3c2410_dma_enqueue(context->dma_channel, context,
784 +                           context->io_buffer_dma,
785 +                           req->DataRemaining);
786 +
787 +       return 0;
788 +}
789 +
790 +
791 +static irqreturn_t s3c24xx_hcd_irq(int irq, void *dev_id)
792 +{
793 +       u32 cmdsta, dsta, fsta;
794 +       unsigned long flags, trace = 0;
795 +       PSDREQUEST req;
796 +       struct s3c24xx_hcd_context * context =
797 +               (struct s3c24xx_hcd_context *)dev_id;
798 +
799 +       spin_lock_irqsave(&context->lock, flags);
800 +
801 +       s3c24xx_hcd_clear_imask(context);
802 +
803 +       cmdsta = readl(context->base + S3C2410_SDICMDSTAT);
804 +       dsta = readl(context->base + S3C2410_SDIDSTA);
805 +       fsta = readl(context->base + S3C2410_SDIFSTA);
806 +
807 +       context->cmdsta = cmdsta;
808 +       context->dsta = dsta;
809 +       context->fsta = fsta;
810 +
811 +       s3c24xx_hcd_clear_csta(context);
812 +
813 +       if (dsta & S3C2410_SDIDSTA_SDIOIRQDETECT) {
814 +               writel(S3C2410_SDIDSTA_SDIOIRQDETECT, context->base + S3C2410_SDIDSTA);
815 +
816 +               if (context->int_sdio) {
817 +                       u32 imask;
818 +
819 +                       context->int_sdio = 0;
820 +
821 +                       imask = readl(context->base + S3C2440_SDIIMSK);
822 +                       imask &= ~S3C2410_SDIIMSK_SDIOIRQ;
823 +                       writel(imask, context->base + S3C2440_SDIIMSK);
824 +                       schedule_work(&context->irq_work);
825 +               }
826 +       }
827 +
828 +       req = GET_CURRENT_REQUEST(&context->hcd);
829 +       if (req == NULL) {
830 +               DBG_PRINT(SDDBG_TRACE, ("%s(): No current request\n", __FUNCTION__));
831 +               goto out;
832 +       }
833 +
834 +       if (cmdsta & S3C2410_SDICMDSTAT_CMDTIMEOUT) {
835 +               DBG_PRINT(SDDBG_ERROR, ("TIMEOUT\n"));
836 +               printk("TIMEOUT\n");
837 +               req->Status = SDIO_STATUS_BUS_RESP_TIMEOUT;
838 +               writel(S3C2410_SDICMDSTAT_CMDTIMEOUT, context->base + S3C2410_SDICMDSTAT);
839 +               schedule_work(&context->io_work);
840 +       }
841 +
842 +       if (cmdsta & S3C2410_SDICMDSTAT_CRCFAIL) {
843 +               DBG_PRINT(SDDBG_ERROR, ("CRCFAIL 0x%x\n", cmdsta));
844 +               printk("CRCFAIL 0x%x\n", cmdsta);
845 +               req->Status = SDIO_STATUS_BUS_RESP_CRC_ERR;
846 +               dump_request(context);
847 +               writel(S3C2410_SDICMDSTAT_CRCFAIL, context->base + S3C2410_SDICMDSTAT);
848 +               schedule_work(&context->io_work);
849 +       }
850 +
851 +
852 +       if (cmdsta & S3C2410_SDICMDSTAT_CMDSENT) {
853 +               writel(S3C2410_SDICMDSTAT_CMDSENT, context->base + S3C2410_SDICMDSTAT);
854 +
855 +               if (context->complete == S3C24XX_HCD_NO_RESPONSE) {
856 +                       req->Status = SDIO_STATUS_SUCCESS;
857 +                       trace = 1;
858 +                       schedule_work(&context->io_work);
859 +               }
860 +       }
861 +
862 +       if (cmdsta & S3C2410_SDICMDSTAT_RSPFIN ||
863 +           (IS_SDREQ_WRITE_DATA(req->Flags) && (fsta &  S3C2410_SDIFSTA_TFDET)) ||
864 +           (!IS_SDREQ_WRITE_DATA(req->Flags) && (fsta &  S3C2410_SDIFSTA_RFDET))) {
865 +
866 +               writel(S3C2410_SDICMDSTAT_RSPFIN, context->base + S3C2410_SDICMDSTAT);
867 +
868 +               if (context->complete == S3C24XX_HCD_RESPONSE_SHORT ||
869 +                   context->complete == S3C24XX_HCD_RESPONSE_LONG ||
870 +                   context->complete == S3C24XX_HCD_DATA_READ ||
871 +                   context->complete == S3C24XX_HCD_DATA_WRITE) {
872 +                       req->Status = SDIO_STATUS_SUCCESS;
873 +                       if (trace)
874 +                               printk("IO work already scheduled, cmdsta: 0x%x\n", cmdsta);
875 +                       schedule_work(&context->io_work);
876 +               }
877 +       }
878 +
879 + out:
880 +       if (dsta & S3C2410_SDIDSTA_RDYWAITREQ) {
881 +               printk("S3C2410_SDIDSTA_RDYWAITREQ\n");
882 +               //writel(S3C2410_SDIDSTA_RDYWAITREQ, context->base + S3C2410_SDIDSTA);
883 +       }
884 +
885 +       if (dsta & S3C2410_SDIDSTA_FIFOFAIL) {
886 +               printk("S3C2410_SDIDSTA_FIFOFAIL\n");
887 +               writel(S3C2410_SDIDSTA_FIFOFAIL, context->base + S3C2410_SDIDSTA);
888 +       }
889 +
890 +       if (dsta & S3C2410_SDIDSTA_CRCFAIL) {
891 +               printk("S3C2410_SDIDSTA_CRCFAIL\n");
892 +               writel(S3C2410_SDIDSTA_CRCFAIL, context->base + S3C2410_SDIDSTA);
893 +       }
894 +
895 +       if (dsta & S3C2410_SDIDSTA_RXCRCFAIL) {
896 +               printk("S3C2410_SDIDSTA_RXCRCFAIL\n");
897 +               writel(S3C2410_SDIDSTA_RXCRCFAIL, context->base + S3C2410_SDIDSTA);
898 +       }
899 +
900 +       if (dsta & S3C2410_SDIDSTA_DATATIMEOUT) {
901 +               printk("S3C2410_SDIDSTA_DATATIMEOUT\n");
902 +               writel(S3C2410_SDIDSTA_DATATIMEOUT, context->base + S3C2410_SDIDSTA);
903 +       }
904 +
905 +       if (dsta & S3C2410_SDIDSTA_BUSYFINISH) {
906 +               printk("S3C2410_SDIDSTA_BUSYFINISH\n");
907 +               writel(S3C2410_SDIDSTA_BUSYFINISH, context->base + S3C2410_SDIDSTA);
908 +       }
909 +
910 +       if (dsta & S3C2410_SDIDSTA_SBITERR) {
911 +               printk("S3C2410_SDIDSTA_SBIERR\n");
912 +               writel(S3C2410_SDIDSTA_SBITERR, context->base + S3C2410_SDIDSTA);
913 +       }
914 +
915 +       spin_unlock_irqrestore(&context->lock, flags);
916 +       return IRQ_HANDLED;
917 +}
918 +
919 +
920 +SDIO_STATUS s3c24xx_hcd_config(PSDHCD hcd, PSDCONFIG config)
921 +{
922 +       u32 con, imsk;
923 +       SDIO_STATUS status = SDIO_STATUS_SUCCESS;
924 +       PSDCONFIG_SDIO_INT_CTRL_DATA int_data;
925 +       struct s3c24xx_hcd_context * context = (struct s3c24xx_hcd_context *)hcd->pContext;
926 +
927 +       switch (GET_SDCONFIG_CMD(config)){
928 +       case SDCONFIG_GET_WP:
929 +               DBG_PRINT(SDDBG_TRACE, ("config GET_WP\n"));
930 +               *((SDCONFIG_WP_VALUE *)config->pData) = 0;
931 +               status = SDIO_STATUS_SUCCESS;
932 +               break;
933 +       case SDCONFIG_SEND_INIT_CLOCKS:
934 +               DBG_PRINT(SDDBG_TRACE, ("config SEND_INIT_CLOCKS\n"));
935 +
936 +               /* We stop/start the clock */
937 +               con = readl(context->base + S3C2410_SDICON);
938 +
939 +               con &= ~S3C2410_SDICON_CLOCKTYPE;
940 +               writel(con, context->base + S3C2410_SDICON);
941 +
942 +               mdelay(100);
943 +
944 +               con |= S3C2410_SDICON_CLOCKTYPE;
945 +               writel(con, context->base + S3C2410_SDICON);
946 +
947 +               mdelay(100);
948 +
949 +               status = SDIO_STATUS_SUCCESS;
950 +               break;
951 +        case SDCONFIG_SDIO_INT_CTRL:
952 +               DBG_PRINT(SDDBG_TRACE, ("config SDIO_INT_CTRL\n"));
953 +               int_data =  GET_SDCONFIG_CMD_DATA(PSDCONFIG_SDIO_INT_CTRL_DATA, config);
954 +
955 +               if (int_data->SlotIRQEnable &
956 +                   (IRQ_DETECT_1_BIT | IRQ_DETECT_4_BIT | IRQ_DETECT_MULTI_BLK) ) {
957 +                       imsk = readl(context->base + S3C2440_SDIIMSK);
958 +
959 +                       if (int_data->SlotIRQEnable) {
960 +                               printk("SDIO_INT_CTRL enable IRQ\n");
961 +                               DBG_PRINT(SDDBG_TRACE, ("SDIO_INT_CTRL enable IRQ\n"));
962 +                               context->int_sdio = 1;
963 +                               imsk |= S3C2410_SDIIMSK_SDIOIRQ;
964 +                               writel(imsk, context->base + S3C2440_SDIIMSK);
965 +                       } else {
966 +                               printk("SDIO_INT_CTRL disable IRQ\n");
967 +                               DBG_PRINT(SDDBG_TRACE, ("SDIO_INT_CTRL disable IRQ\n"));
968 +                               context->int_sdio = 0;
969 +                               imsk &= ~S3C2410_SDIIMSK_SDIOIRQ;
970 +                               writel(imsk, context->base + S3C2440_SDIIMSK);
971 +                       }
972 +               }
973 +               status = SDIO_STATUS_SUCCESS;
974 +               break;
975 +        case SDCONFIG_SDIO_REARM_INT:
976 +               DBG_PRINT(SDDBG_TRACE, ("config SDIO_REARM_INT\n"));
977 +
978 +               context->int_sdio = 1;
979 +               imsk = readl(context->base + S3C2440_SDIIMSK);
980 +               imsk |= S3C2410_SDIIMSK_SDIOIRQ;
981 +               writel(imsk, context->base + S3C2440_SDIIMSK);
982 +
983 +               status = SDIO_STATUS_SUCCESS;
984 +               break;
985 +       case SDCONFIG_FUNC_CHANGE_BUS_MODE:
986 +        case SDCONFIG_BUS_MODE_CTRL:
987 +               s3c24xx_hcd_set_bus_mode(context, (PSDCONFIG_BUS_MODE_DATA)(config->pData));
988 +               DBG_PRINT(SDDBG_TRACE, ("config BUS_MODE_CTRL\n"));
989 +               status = SDIO_STATUS_SUCCESS;
990 +               break;
991 +        case SDCONFIG_POWER_CTRL:
992 +               DBG_PRINT(SDDBG_TRACE, ("config POWER_CTRL\n"));
993 +               status = SDIO_STATUS_SUCCESS;
994 +               break;
995 +        case SDCONFIG_GET_HCD_DEBUG:
996 +               DBG_PRINT(SDDBG_TRACE, ("config GET_HCD_DEBUG\n"));
997 +               status = SDIO_STATUS_SUCCESS;
998 +               break;
999 +        case SDCONFIG_SET_HCD_DEBUG:
1000 +               DBG_PRINT(SDDBG_TRACE, ("config SET_HCD_DEBUG\n"));
1001 +               status = SDIO_STATUS_SUCCESS;
1002 +               break;
1003 +       default:
1004 +               /* invalid request */
1005 +               DBG_PRINT(SDDBG_ERROR, ("%s() - unsupported command: 0x%X\n",
1006 +                                      __FUNCTION__, GET_SDCONFIG_CMD(config)));
1007 +               status = SDIO_STATUS_INVALID_PARAMETER;
1008 +       }
1009 +
1010 +       return SDIOErrorToOSError(status);
1011 +}
1012 +
1013 +
1014 +SDIO_STATUS s3c24xx_hcd_request(PSDHCD hcd)
1015 +{
1016 +       SDIO_STATUS status = SDIO_STATUS_PENDING;
1017 +       PSDREQUEST req;
1018 +       u32 cmdcon, imask;
1019 +       unsigned long flags;
1020 +       struct s3c24xx_hcd_context * context =
1021 +               (struct s3c24xx_hcd_context *)hcd->pContext;
1022 +
1023 +       req = GET_CURRENT_REQUEST(hcd);
1024 +       DBG_ASSERT(req != NULL);
1025 +
1026 +       if (req->Flags & SDREQ_FLAGS_DATA_SHORT_TRANSFER)
1027 +               printk("### SHORT TRANSFER ###\n");
1028 +
1029 +       spin_lock_irqsave(&context->lock, flags);
1030 +
1031 +       /* Clear command, data and fifo status registers */
1032 +       writel(0xFFFFFFFF, context->base + S3C2410_SDICMDSTAT);
1033 +       writel(0xFFFFFFFF, context->base + S3C2410_SDIDSTA);
1034 +       writel(0xFFFFFFFF, context->base + S3C2410_SDIFSTA);
1035 +
1036 +       /* Enabling irqs */
1037 +       imask = S3C2410_SDIIMSK_READWAIT;
1038 +
1039 +       cmdcon = readl(context->base + S3C2410_SDICMDCON);
1040 +
1041 +        switch (GET_SDREQ_RESP_TYPE(req->Flags)) {
1042 +       case SDREQ_FLAGS_NO_RESP:
1043 +               cmdcon &= ~S3C2410_SDICMDCON_WAITRSP;
1044 +               context->complete = S3C24XX_HCD_NO_RESPONSE;
1045 +               imask |= S3C2410_SDIIMSK_CMDSENT;
1046 +                break;
1047 +       case SDREQ_FLAGS_RESP_R1:
1048 +       case SDREQ_FLAGS_RESP_R1B:
1049 +       case SDREQ_FLAGS_RESP_R3:
1050 +       case SDREQ_FLAGS_RESP_SDIO_R4:
1051 +       case SDREQ_FLAGS_RESP_SDIO_R5:
1052 +       case SDREQ_FLAGS_RESP_R6:
1053 +               cmdcon &= ~S3C2410_SDICMDCON_LONGRSP;
1054 +               cmdcon |= S3C2410_SDICMDCON_WAITRSP;
1055 +               context->complete = S3C24XX_HCD_RESPONSE_SHORT;
1056 +               imask |= S3C2410_SDIIMSK_CRCSTATUS | S3C2410_SDIIMSK_RESPONSEND
1057 +                       | S3C2410_SDIIMSK_CMDTIMEOUT | S3C2410_SDIIMSK_RESPONSECRC;
1058 +                break;
1059 +       case SDREQ_FLAGS_RESP_R2:
1060 +               cmdcon |= S3C2410_SDICMDCON_LONGRSP;
1061 +               cmdcon |= S3C2410_SDICMDCON_WAITRSP;
1062 +               context->complete = S3C24XX_HCD_RESPONSE_LONG;
1063 +               imask |= S3C2410_SDIIMSK_CRCSTATUS | S3C2410_SDIIMSK_RESPONSEND
1064 +                       | S3C2410_SDIIMSK_CMDTIMEOUT | S3C2410_SDIIMSK_RESPONSECRC;
1065 +                break;
1066 +
1067 +       }
1068 +
1069 +       /* There is a data part */
1070 +       if (IS_SDREQ_DATA_TRANS(req->Flags)) {
1071 +               u32 dcon = 0;
1072 +
1073 +               if (readl(context->base + S3C2410_SDIDSTA) &
1074 +                   (S3C2410_SDIDSTA_TXDATAON | S3C2410_SDIDSTA_RXDATAON)) {
1075 +                       printk("##### DATA ON: 0x%x ######\n", readl(context->base + S3C2410_SDIDSTA));
1076 +               }
1077 +
1078 +               /* Setting timer */
1079 +               writel(0x7fffff, context->base + S3C2410_SDITIMER);
1080 +
1081 +               /* Block size */
1082 +               writel(req->BlockLen, context->base + S3C2410_SDIBSIZE);
1083 +               /* Number of blocks */
1084 +               dcon |= (0xfff & req->BlockCount);
1085 +
1086 +               if (context->bus_width == 4)
1087 +                       dcon |= S3C2410_SDIDCON_WIDEBUS;
1088 +
1089 +               req->DataRemaining = req->BlockCount * req->BlockLen;
1090 +
1091 +               /* Set data size, and start the transfer */
1092 +               dcon |= S3C2410_SDIDCON_IRQPERIOD;
1093 +               if (!(req->DataRemaining % 4)) {
1094 +                       context->data_size = 4;
1095 +                       dcon |= S3C2440_SDIDCON_DS_WORD;
1096 +               } else if (!(req->DataRemaining % 2)) {
1097 +                       context->data_size = 2;
1098 +                       dcon |= S3C2440_SDIDCON_DS_HALFWORD;
1099 +               } else {
1100 +                       context->data_size = 1;
1101 +                       dcon |= S3C2440_SDIDCON_DS_BYTE;
1102 +               }
1103 +
1104 +#ifdef CONFIG_SDIO_S3C24XX_DMA
1105 +               if (req->DataRemaining > 16) {
1106 +                       context->dma_en = 1;
1107 +               } else
1108 +#endif
1109 +               {
1110 +                       context->dma_en = 0;
1111 +                       context->data_size = 1;
1112 +                       dcon |= S3C2440_SDIDCON_DS_BYTE;
1113 +               }
1114 +
1115 +               if (context->dma_en) {
1116 +                       dcon |= S3C2410_SDIDCON_DMAEN;
1117 +                       s3c24xx_hcd_prepare_dma(context);
1118 +               }
1119 +
1120 +               if (IS_SDREQ_WRITE_DATA(req->Flags)) {
1121 +                       /* Data write */
1122 +                       DBG_PRINT(SDDBG_TRACE, ("Start data write, block count=%d, block size=%d\n",
1123 +                                               req->BlockCount, req->BlockLen));
1124 +
1125 +                       /* Data configuration: transmit after resp, block mode*/
1126 +                       dcon |= S3C2410_SDIDCON_TXAFTERRESP | S3C2410_SDIDCON_BLOCKMODE;
1127 +
1128 +                       /* This is a write */
1129 +                       dcon |= S3C2410_SDIDCON_XFER_TXSTART;
1130 +
1131 +                       imask |= S3C2410_SDIIMSK_TXFIFOHALF | S3C2410_SDIIMSK_TXFIFOEMPTY |
1132 +                               S3C2410_SDIIMSK_FIFOFAIL | S3C2410_SDIIMSK_DATACRC |
1133 +                               S3C2410_SDIIMSK_DATATIMEOUT | S3C2410_SDIIMSK_DATAFINISH;
1134 +
1135 +                       context->complete = S3C24XX_HCD_DATA_WRITE;
1136 +               } else {
1137 +                       /* Data read */
1138 +                       DBG_PRINT(SDDBG_TRACE, ("Start data read, block count=%d, block size=%d\n",
1139 +                                               req->BlockCount, req->BlockLen));
1140 +
1141 +                       /* Data configuration: receive after cmd, block mode*/
1142 +                       dcon |= S3C2410_SDIDCON_RXAFTERCMD | S3C2410_SDIDCON_BLOCKMODE;
1143 +
1144 +                       /* This is a read */
1145 +                       dcon |= S3C2410_SDIDCON_XFER_RXSTART;
1146 +
1147 +                       imask |= S3C2410_SDIIMSK_RXFIFOHALF | S3C2410_SDIIMSK_RXFIFOLAST |
1148 +                               S3C2410_SDIIMSK_FIFOFAIL | S3C2410_SDIIMSK_DATACRC |
1149 +                               S3C2410_SDIIMSK_DATATIMEOUT | S3C2410_SDIIMSK_DATAFINISH;
1150 +
1151 +                       context->complete = S3C24XX_HCD_DATA_READ;
1152 +               }
1153 +
1154 +               dcon |= S3C2440_SDIDCON_DATSTART;
1155 +
1156 +               writel(dcon, context->base + S3C2410_SDIDCON);
1157 +
1158 +               cmdcon |= S3C2410_SDICMDCON_WITHDATA;
1159 +
1160 +       } else {
1161 +               cmdcon &= ~S3C2410_SDICMDCON_WITHDATA;
1162 +       }
1163 +
1164 +       cmdcon |= req->Command & S3C2410_SDICMDCON_INDEX;
1165 +       cmdcon |= S3C2410_SDICMDCON_SENDERHOST | S3C2410_SDICMDCON_CMDSTART;
1166 +
1167 +       req->Status = SDIO_STATUS_PENDING;
1168 +
1169 +       if (context->int_sdio)
1170 +               imask |= S3C2410_SDIIMSK_SDIOIRQ;
1171 +       context->int_mask = imask;
1172 +       writel(imask, context->base + S3C2440_SDIIMSK);
1173 +       writel(req->Argument, context->base + S3C2410_SDICMDARG);
1174 +       writel(cmdcon, context->base + S3C2410_SDICMDCON);
1175 +
1176 +       spin_unlock_irqrestore(&context->lock, flags);
1177 +
1178 +       return status;
1179 +}
1180 +
1181 +static int s3c24xx_hcd_hw_init(struct s3c24xx_hcd_context * context)
1182 +{
1183 +       SDIO_STATUS status = SDIO_STATUS_SUCCESS;
1184 +       u32 con, datacon;
1185 +
1186 +       /* Clock */
1187 +       context->device.clock = clk_get(NULL, "sdi");
1188 +       if (IS_ERR(context->device.clock)) {
1189 +               DBG_PRINT(SDDBG_ERROR, ("Couldn't get clock\n"));
1190 +               status = PTR_ERR(context->device.clock);
1191 +               context->device.clock = NULL;
1192 +               return status;
1193 +       }
1194 +
1195 +       status = clk_enable(context->device.clock);
1196 +       if (SDIO_IS_ERROR(status)) {
1197 +               DBG_PRINT(SDDBG_ERROR, ("Couldn't get clock\n"));
1198 +               return SDIOErrorToOSError(status);
1199 +       }
1200 +
1201 +       context->device.max_clock_rate = clk_get_rate(context->device.clock);
1202 +       context->device.actual_clock_rate = context->device.max_clock_rate;
1203 +
1204 +       /* I/O */
1205 +       context->mem = request_mem_region(context->mem->start,
1206 +                                         RESSIZE(context->mem), context->description);
1207 +
1208 +       if (!context->mem) {
1209 +               DBG_PRINT(SDDBG_ERROR, ("Failed to request io memory region\n"));
1210 +               status = -ENOENT;
1211 +               goto out_disable_clock;
1212 +       }
1213 +
1214 +       context->base = ioremap(context->mem->start, RESSIZE(context->mem));
1215 +       if (context->base == 0) {
1216 +               DBG_PRINT(SDDBG_ERROR, ("failed to ioremap() io memory region.\n"));
1217 +               status = -EINVAL;
1218 +               goto out_free_mem_region;
1219 +       }
1220 +
1221 +       /* IRQ */
1222 +#if 0
1223 +       context->cd_irq = s3c2410_gpio_getirq(GTA02v1_GPIO_nSD_DETECT);
1224 +       s3c2410_gpio_cfgpin(GTA02v1_GPIO_nSD_DETECT, S3C2410_GPIO_IRQ);
1225 +
1226 +       if (request_irq(context->cd_irq, s3c24xx_hcd_cd_irq, 0, context->description, context)) {
1227 +               DBG_PRINT(SDDBG_ERROR, ("failed to request card detect interrupt.\n"));
1228 +               status = -ENOENT;
1229 +               goto out_unmap_mem_region;
1230 +       }
1231 +#endif
1232 +
1233 +       if (request_irq(context->io_irq, s3c24xx_hcd_irq, 0, context->description, context)) {
1234 +               DBG_PRINT(SDDBG_ERROR, ("failed to request mci interrupt.\n"));
1235 +               status = -ENOENT;
1236 +               goto out_unmap_mem_region;
1237 +       }
1238 +
1239 +
1240 +       /* DMA */
1241 +       context->io_buffer_size = 4 * 4096;
1242 +       context->io_buffer = dma_alloc_writecombine(&context->pdev->dev,
1243 +                                                   context->io_buffer_size,
1244 +                                                   &context->io_buffer_dma,
1245 +                                                   GFP_KERNEL | GFP_DMA);
1246 +
1247 +       if (context->io_buffer == NULL) {
1248 +               DBG_PRINT(SDDBG_ERROR, ("failed to allocate DMA buffer\n"));
1249 +               status = -ENOMEM;
1250 +               goto out_free_irq;
1251 +
1252 +       }
1253 +
1254 +       if (s3c2410_dma_request(context->dma_channel, &s3c24xx_hcd_dma_client, NULL)) {
1255 +               DBG_PRINT(SDDBG_ERROR, ("unable to get DMA channel.\n"));
1256 +               status = -ENOENT;
1257 +               goto out_free_dma;
1258 +       }
1259 +
1260 +
1261 +       /* Set multiplexing */
1262 +       s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_SDCLK);
1263 +       s3c2410_gpio_cfgpin(S3C2410_GPE6, S3C2410_GPE6_SDCMD);
1264 +       s3c2410_gpio_cfgpin(S3C2410_GPE7, S3C2410_GPE7_SDDAT0);
1265 +       s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);
1266 +       s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2);
1267 +       s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3);
1268 +
1269 +       con = readl(context->base + S3C2410_SDICON);
1270 +       con |= S3C2410_SDICON_SDIOIRQ;
1271 +       writel(con, context->base + S3C2410_SDICON);
1272 +
1273 +       datacon = readl(context->base + S3C2410_SDIDCON);
1274 +       datacon |= S3C2410_SDIDCON_WIDEBUS;
1275 +       writel(datacon, context->base + S3C2410_SDIDCON);
1276 +
1277 +       printk("S3c24xx SDIO: IRQ:%d Detect IRQ:%d DMA channel:%d base@0x%p PCLK@%ld kHz\n",
1278 +              context->io_irq, context->cd_irq, context->dma_channel, context->base,
1279 +              context->device.max_clock_rate/1000);
1280 +
1281 +       return SDIOErrorToOSError(status);
1282 +
1283 + out_free_dma:
1284 +       dma_free_writecombine(&context->pdev->dev,context->io_buffer_size,
1285 +                             context->io_buffer, context->io_buffer_dma);
1286 +
1287 + out_free_irq:
1288 +       free_irq(context->io_irq, context);
1289 +
1290 + out_unmap_mem_region:
1291 +       iounmap(context->base);
1292 +
1293 + out_free_mem_region:
1294 +       release_mem_region(context->mem->start, RESSIZE(context->mem));
1295 +
1296 + out_disable_clock:
1297 +       clk_disable(context->device.clock);
1298 +
1299 +       return SDIOErrorToOSError(status);
1300 +}
1301 +
1302 +static void s3c24xx_hcd_hw_cleanup(struct s3c24xx_hcd_context * context)
1303 +{
1304 +       clk_disable(context->device.clock);
1305 +       free_irq(context->io_irq, context);
1306 +       iounmap(context->base);
1307 +       release_mem_region(context->mem->start, RESSIZE(context->mem));
1308 +       dma_free_writecombine(&context->pdev->dev,context->io_buffer_size,
1309 +                             context->io_buffer, context->io_buffer_dma);
1310 +}
1311 +
1312 +static int s3c24xx_hcd_pnp_probe(struct pnp_dev *pBusDevice, const struct pnp_device_id *pId)
1313 +{
1314 +       SDIO_STATUS status = SDIO_STATUS_SUCCESS;
1315 +
1316 +       status = s3c24xx_hcd_hw_init(&hcd_context);
1317 +       if (SDIO_IS_ERROR(status)) {
1318 +               DBG_PRINT(SDDBG_ERROR, ("HW Init failed\n"));
1319 +               return SDIOErrorToOSError(status);
1320 +       }
1321 +
1322 +       status = SDIO_RegisterHostController(&hcd_context.hcd);
1323 +       if (SDIO_IS_ERROR(status)) {
1324 +               DBG_PRINT(SDDBG_ERROR, ("Host registration failed\n"));
1325 +               s3c24xx_hcd_hw_cleanup(&hcd_context);
1326 +               return SDIOErrorToOSError(status);
1327 +       }
1328 +
1329 +       /* Our card is built-in, we force the attachement event */
1330 +       SDIO_HandleHcdEvent(&hcd_context.hcd, EVENT_HCD_ATTACH);
1331 +
1332 +       return 0;
1333 +}
1334 +
1335 +static void s3c24xx_hcd_pnp_remove(struct pnp_dev *pBusDevice)
1336 +{
1337 +}
1338 +
1339 +/* the driver context data */
1340 +struct s3c24xx_hcd_context hcd_context = {
1341 +       .description  = DESCRIPTION,
1342 +       .hcd.pName = "sdio_s3c24xx",
1343 +       .hcd.Version = CT_SDIO_STACK_VERSION_CODE,
1344 +       .hcd.pModule = THIS_MODULE,
1345 +       /* builtin card, 4 bits bus */
1346 +       .hcd.Attributes = SDHCD_ATTRIB_BUS_4BIT | SDHCD_ATTRIB_BUS_1BIT | SDHCD_ATTRIB_MULTI_BLK_IRQ,
1347 +       .hcd.SlotNumber = 0,
1348 +       .hcd.MaxSlotCurrent = 500, /* 1/2 amp */
1349 +       .hcd.SlotVoltageCaps = SLOT_POWER_3_3V, /* 3.3V */
1350 +       .hcd.SlotVoltagePreferred = SLOT_POWER_3_3V, /* 3.3V */
1351 +       .hcd.MaxClockRate = 25000000,
1352 +       .hcd.MaxBytesPerBlock = 0xfff, /* 0 - 4095 */
1353 +       .hcd.MaxBlocksPerTrans = 0xfff, /* 0 - 4095 */
1354 +       .hcd.pContext = &hcd_context,
1355 +       .hcd.pRequest = s3c24xx_hcd_request,
1356 +       .hcd.pConfigure = s3c24xx_hcd_config,
1357 +       .device.pnp_device.name = "sdio_s3c24xx_hcd",
1358 +       .device.pnp_driver.name = "sdio_s3c24xx_hcd",
1359 +       .device.pnp_driver.probe  = s3c24xx_hcd_pnp_probe,
1360 +       .device.pnp_driver.remove = s3c24xx_hcd_pnp_remove,
1361 +};
1362 +
1363 +static int s3c24xx_hcd_probe(struct platform_device * pdev)
1364 +{
1365 +       SDIO_STATUS status = SDIO_STATUS_SUCCESS;
1366 +       struct resource *r = NULL;
1367 +
1368 +       printk("S3c2440 SDIO Host controller\n");
1369 +
1370 +       hcd_context.pdev = pdev;
1371 +
1372 +       hcd_context.mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1373 +       if (hcd_context.mem == NULL) {
1374 +               DBG_PRINT(SDDBG_ERROR, ("No memory region\n"));
1375 +               status = SDIO_STATUS_NO_RESOURCES;
1376 +               goto out;
1377 +       }
1378 +
1379 +       hcd_context.io_irq = platform_get_irq(pdev, 0);
1380 +       if (hcd_context.io_irq == 0) {
1381 +               DBG_PRINT(SDDBG_ERROR, ("No IRQ\n"));
1382 +               status = SDIO_STATUS_NO_RESOURCES;
1383 +               goto out;
1384 +       }
1385 +
1386 +       r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
1387 +       if (r == NULL) {
1388 +               DBG_PRINT(SDDBG_ERROR, ("No DMA channel\n"));
1389 +               status = SDIO_STATUS_NO_RESOURCES;
1390 +               goto out;
1391 +       }
1392 +       hcd_context.dma_channel = r->start;
1393 +       hcd_context.dma_en = 0;
1394 +
1395 +       hcd_context.int_sdio = 0;
1396 +
1397 +       spin_lock_init(&hcd_context.lock);
1398 +
1399 +       init_completion(&hcd_context.dma_complete);
1400 +       init_completion(&hcd_context.xfer_complete);
1401 +
1402 +       INIT_WORK(&hcd_context.io_work, s3c24xx_hcd_io_work);
1403 +       INIT_WORK(&hcd_context.irq_work, s3c24xx_hcd_irq_work);
1404 +
1405 +       mdelay(100);
1406 +
1407 +       status = SDIO_BusAddOSDevice(&hcd_context.device.dma,
1408 +                                    &hcd_context.device.pnp_driver,
1409 +                                    &hcd_context.device.pnp_device);
1410 +
1411 + out:
1412 +
1413 +       return SDIOErrorToOSError(status);
1414 +}
1415 +
1416 +/*
1417 + * module cleanup
1418 + */
1419 +static int s3c24xx_hcd_remove(struct platform_device * pdev) {
1420 +       printk("S3C2440 SDIO host controller unloaded\n");
1421 +       SDIO_BusRemoveOSDevice(&hcd_context.device.pnp_driver, &hcd_context.device.pnp_device);
1422 +
1423 +       return 0;
1424 +}
1425 +
1426 +static struct platform_driver s3c24xx_hcd_sdio =
1427 +{
1428 +       .driver.name    = "s3c24xx-sdio",
1429 +       .probe          = s3c24xx_hcd_probe,
1430 +       .remove         = s3c24xx_hcd_remove,
1431 +};
1432 +
1433 +#ifdef CONFIG_DEBUG_FS
1434 +static struct dentry *debugfs_dir;
1435 +
1436 +static int s3c24xx_hcd_debugfs_show(struct seq_file *s, void *data)
1437 +{
1438 +       PSDREQUEST req;
1439 +       u32 con, pre, cmdarg, cmdcon, cmdsta, r0, r1, r2, r3, timer, bsize;
1440 +       u32 datcon, datcnt, datsta, fsta, imask;
1441 +       struct s3c24xx_hcd_context * context = &hcd_context;
1442 +
1443 +
1444 +       con     = readl(context->base + S3C2410_SDICON);
1445 +       pre     = readl(context->base + S3C2410_SDIPRE);
1446 +       cmdarg  = readl(context->base + S3C2410_SDICMDARG);
1447 +       cmdcon  = readl(context->base + S3C2410_SDICMDCON);
1448 +       cmdsta  = readl(context->base + S3C2410_SDICMDSTAT);
1449 +       r0      = readl(context->base + S3C2410_SDIRSP0);
1450 +       r1      = readl(context->base + S3C2410_SDIRSP1);
1451 +       r2      = readl(context->base + S3C2410_SDIRSP2);
1452 +       r3      = readl(context->base + S3C2410_SDIRSP3);
1453 +       timer   = readl(context->base + S3C2410_SDITIMER);
1454 +       bsize   = readl(context->base + S3C2410_SDIBSIZE);
1455 +       datcon  = readl(context->base + S3C2410_SDIDCON);
1456 +       datcnt  = readl(context->base + S3C2410_SDIDCNT);
1457 +       datsta  = readl(context->base + S3C2410_SDIDSTA);
1458 +       fsta    = readl(context->base + S3C2410_SDIFSTA);
1459 +       imask   = readl(context->base + S3C2440_SDIIMSK);
1460 +
1461 +       seq_printf(s, "SDICON:    0x%08x\n", con);
1462 +       seq_printf(s, "SDIPRE:    0x%08x\n", pre);
1463 +       seq_printf(s, "SDICmdArg: 0x%08x\n", cmdarg);
1464 +       seq_printf(s, "SDICmdCon: 0x%08x\n", cmdcon);
1465 +       seq_printf(s, "SDICmdSta: 0x%08x\n", cmdsta);
1466 +       seq_printf(s, "SDIRSP0:   0x%08x\n", r0);
1467 +       seq_printf(s, "SDIRSP1:   0x%08x\n", r1);
1468 +       seq_printf(s, "SDIRSP2:   0x%08x\n", r2);
1469 +       seq_printf(s, "SDIRSP3:   0x%08x\n", r3);
1470 +       seq_printf(s, "SDIDTimer: 0x%08x\n", timer);
1471 +       seq_printf(s, "SDIBSize:  0x%08x\n", bsize);
1472 +       seq_printf(s, "SDIDatCon: 0x%08x\n", datcon);
1473 +       seq_printf(s, "SDIDatCnt: 0x%08x\n", datcnt);
1474 +       seq_printf(s, "SDIDatSta: 0x%08x\n", datsta);
1475 +       seq_printf(s, "SDIFSta:   0x%08x\n", fsta);
1476 +       seq_printf(s, "SDIIntMsk: 0x%08x\n", imask);
1477 +       seq_printf(s, "\n");
1478 +
1479 +       seq_printf(s, "Current REQ: \n");
1480 +       req = GET_CURRENT_REQUEST(&context->hcd);
1481 +       if (req == NULL) {
1482 +               seq_printf(s, " No current request\n");
1483 +       } else {
1484 +               seq_printf(s, " Command: %d\n", req->Command);
1485 +               seq_printf(s, " Args: 0x%x\n", req->Argument);
1486 +               seq_printf(s, " Flags: 0x%x\n", req->Flags);
1487 +               seq_printf(s, " %d blocks x %d bytes\n", req->BlockCount, req->BlockLen);
1488 +               seq_printf(s, " %d bytes remaining\n", req->DataRemaining);
1489 +       }
1490 +
1491 +       seq_printf(s, "Context: \n");
1492 +       seq_printf(s, " INT mask: 0x%x\n", context->int_mask);
1493 +       seq_printf(s, " sdio INT: %d\n", context->int_sdio);
1494 +       seq_printf(s, " cmdsta: 0x%x\n", context->cmdsta);
1495 +       seq_printf(s, " dsta: 0x%x\n", context->dsta);
1496 +       seq_printf(s, " fsta: 0x%x\n", context->fsta);
1497 +
1498 +       return 0;
1499 +}
1500 +
1501 +static int s3c24xx_hcd_debugfs_open(struct inode *inode,
1502 +                                       struct file *file)
1503 +{
1504 +       return single_open(file, s3c24xx_hcd_debugfs_show, NULL);
1505 +}
1506 +
1507 +static const struct file_operations s3c24xx_hcd_debugfs_fops = {
1508 +       .open           = s3c24xx_hcd_debugfs_open,
1509 +       .read           = seq_read,
1510 +       .llseek         = seq_lseek,
1511 +       .release        = single_release,
1512 +       .owner          = THIS_MODULE,
1513 +};
1514 +
1515 +
1516 +static int s3c24xx_debugfs_init(struct s3c24xx_hcd_context * context)
1517 +{
1518 +       debugfs_dir = debugfs_create_dir("s3c24xx_sdio", NULL);
1519 +
1520 +       debugfs_create_file("registers", 0444, debugfs_dir,
1521 +                           (void *)context,
1522 +                           &s3c24xx_hcd_debugfs_fops);
1523 +
1524 +       return 0;
1525 +}
1526 +
1527 +#else
1528 +
1529 +static int s3c24xx_debugfs_init(struct s3c24xx_hcd_context * context)
1530 +{
1531 +       return 0;
1532 +}
1533 +
1534 +#endif
1535 +
1536 +static int __init s3c24xx_hcd_init(void)
1537 +{
1538 +       int ret;
1539 +
1540 +       ret = s3c24xx_debugfs_init(&hcd_context);
1541 +       if (ret) {
1542 +               printk("%s(): debugfs init failed\n", __FUNCTION__);
1543 +       }
1544 +
1545 +       platform_driver_register(&s3c24xx_hcd_sdio);
1546 +
1547 +       return 0;
1548 +}
1549 +
1550 +static void __exit s3c24xx_hcd_exit(void)
1551 +{
1552 +       platform_driver_unregister(&s3c24xx_hcd_sdio);
1553 +}
1554 +
1555 +
1556 +MODULE_LICENSE("GPL");
1557 +MODULE_DESCRIPTION(DESCRIPTION);
1558 +MODULE_AUTHOR(AUTHOR);
1559 +
1560 +module_init(s3c24xx_hcd_init);
1561 +module_exit(s3c24xx_hcd_exit);
1562 diff --git a/drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.h b/drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.h
1563 new file mode 100644
1564 index 0000000..eb262fc
1565 --- /dev/null
1566 +++ b/drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.h
1567 @@ -0,0 +1,67 @@
1568 +#ifndef __SDIO_S3C24XX_HCD_H___
1569 +#define __SDIO_S3C24XX_HCD_H___
1570 +
1571 +#define S3C24XX_HCD_NO_RESPONSE     1
1572 +#define S3C24XX_HCD_RESPONSE_SHORT  2
1573 +#define S3C24XX_HCD_RESPONSE_LONG   3
1574 +#define S3C24XX_HCD_DATA_READ       4
1575 +#define S3C24XX_HCD_DATA_WRITE      5
1576 +
1577 +struct s3c24xx_hcd_device {
1578 +       OS_PNPDEVICE   pnp_device;     /* the OS device for this HCD */
1579 +       OS_PNPDRIVER   pnp_driver;     /* the OS driver for this HCD */
1580 +       SDDMA_DESCRIPTION dma;
1581 +       struct clk * clock;
1582 +       unsigned long max_clock_rate;
1583 +       unsigned long actual_clock_rate;
1584 +};
1585 +
1586 +
1587 +/* driver wide data, this driver only supports one device,
1588 + * so we include the per device data here also */
1589 +struct s3c24xx_hcd_context {
1590 +       PTEXT                     description;       /* human readable device decsription */
1591 +       SDHCD                     hcd;                /* HCD description for bus driver */
1592 +       struct s3c24xx_hcd_device device;             /* the single device's info */
1593 +       struct platform_device    *pdev;
1594 +       struct resource           *mem;
1595 +       void __iomem              *base;
1596 +       UINT32                    io_irq;
1597 +       UINT32                    cd_irq;
1598 +       BOOL                      card_inserted;       /* card inserted flag */
1599 +       BOOL                      cmd_processed;       /* command phase was processed */
1600 +       UINT32                    fifo_depth;          /* FIFO depth for the bus mode */
1601 +       BOOL                      irq_masked;
1602 +       UINT32                    bus_width;
1603 +       UINT32                    data_size;           /* Word, half word, or byte */
1604 +       UINT32                    latest_xfer_size;
1605 +
1606 +       void                      *io_buffer;         /* Kernel address */
1607 +       dma_addr_t                io_buffer_dma;      /* Bus address */
1608 +       UINT32                    io_buffer_size;
1609 +       UINT32                    dma_channel;
1610 +       UINT32                    dma_en;
1611 +       struct completion         dma_complete;
1612 +       struct completion         xfer_complete;
1613 +
1614 +       UINT32                    int_mask;
1615 +       UINT32                    int_sdio;            /* Do we have SDIO interrupt on ? */
1616 +
1617 +       UINT32                    complete;
1618 +
1619 +       UINT32                    cmdsta;
1620 +       UINT32                    dsta;
1621 +       UINT32                    fsta;
1622 +
1623 +       spinlock_t                lock;
1624 +
1625 +       struct work_struct        io_work;
1626 +       struct work_struct        irq_work;
1627 +};
1628 +
1629 +SDIO_STATUS s3c24xx_hcd_config(PSDHCD hcd, PSDCONFIG config);
1630 +SDIO_STATUS s3c24xx_hcd_request(PSDHCD hcd);
1631 +
1632 +struct s3c24xx_hcd_context hcd_context;
1633 +
1634 +#endif
1635 -- 
1636 1.5.6.3
1637