changed Makefile and profiles, added patches for kernel 2.6.24
[openwrt.git] / target / linux / s3c24xx / patches-2.6.26 / 0019-s3c_mci.patch.patch
1 From ed9a479d4e02e6415e4242211266845013ecad77 Mon Sep 17 00:00:00 2001
2 From: mokopatches <mokopatches@openmoko.org>
3 Date: Wed, 16 Jul 2008 14:44:50 +0100
4 Subject: [PATCH] s3c_mci.patch
5  This is a MMC/SD driver for the Samsung S3C24xx SD/MMC controller, originally
6  developed years ago by Thomas Kleffel <tk@maintech.de>.
7
8 Due to time restraints, he had no time to further maintain the driver and
9 follow the mainline Linux changes in the SD/MMC stack.
10
11 With his authorization, I have taken over the task of making it compliant to
12 the current mainline SD/MMC API and take care of the mainline kernel merge.
13
14 After a potential kernel inclusion, we would co-maintain the driver.
15
16 Acked-by: Thomas Kleffel <tk@maintech.de>
17 Signed-off-by: Harald Welte <laforge@gnumonks.org>
18 ---
19  arch/arm/mach-s3c2412/s3c2412.c         |    3 +
20  arch/arm/mach-s3c2440/s3c2440.c         |    3 +
21  arch/arm/mach-s3c2442/s3c2442.c         |    4 +
22  drivers/mmc/host/Kconfig                |   11 +
23  drivers/mmc/host/Makefile               |    2 +-
24  drivers/mmc/host/s3cmci.c               | 1419 +++++++++++++++++++++++++++++++
25  drivers/mmc/host/s3cmci.h               |   69 ++
26  include/asm-arm/arch-s3c2410/mci.h      |   13 +
27  include/asm-arm/arch-s3c2410/regs-sdi.h |   22 +-
28  9 files changed, 1542 insertions(+), 4 deletions(-)
29  create mode 100644 drivers/mmc/host/s3cmci.c
30  create mode 100644 drivers/mmc/host/s3cmci.h
31  create mode 100644 include/asm-arm/arch-s3c2410/mci.h
32
33 diff --git a/arch/arm/mach-s3c2412/s3c2412.c b/arch/arm/mach-s3c2412/s3c2412.c
34 index 98a0de9..ee4436d 100644
35 --- a/arch/arm/mach-s3c2412/s3c2412.c
36 +++ b/arch/arm/mach-s3c2412/s3c2412.c
37 @@ -216,5 +216,8 @@ int __init s3c2412_init(void)
38  {
39         printk("S3C2412: Initialising architecture\n");
40  
41 +       /* make sure SD/MMC driver can distinguish 2412 from 2410 */
42 +       s3c_device_sdi.name = "s3c2412-sdi";
43 +
44         return sysdev_register(&s3c2412_sysdev);
45  }
46 diff --git a/arch/arm/mach-s3c2440/s3c2440.c b/arch/arm/mach-s3c2440/s3c2440.c
47 index 90e1da6..6c18cbd 100644
48 --- a/arch/arm/mach-s3c2440/s3c2440.c
49 +++ b/arch/arm/mach-s3c2440/s3c2440.c
50 @@ -46,6 +46,9 @@ int __init s3c2440_init(void)
51         s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT;
52         s3c_device_wdt.resource[1].end   = IRQ_S3C2440_WDT;
53  
54 +       /* make sure SD/MMC driver can distinguish 2440 from 2410 */
55 +       s3c_device_sdi.name = "s3c2440-sdi";
56 +
57         /* register our system device for everything else */
58  
59         return sysdev_register(&s3c2440_sysdev);
60 diff --git a/arch/arm/mach-s3c2442/s3c2442.c b/arch/arm/mach-s3c2442/s3c2442.c
61 index fbf8264..fbfb330 100644
62 --- a/arch/arm/mach-s3c2442/s3c2442.c
63 +++ b/arch/arm/mach-s3c2442/s3c2442.c
64 @@ -21,6 +21,7 @@
65  
66  #include <asm/plat-s3c24xx/s3c2442.h>
67  #include <asm/plat-s3c24xx/cpu.h>
68 +#include <asm/plat-s3c24xx/devs.h>
69  
70  static struct sys_device s3c2442_sysdev = {
71         .cls            = &s3c2442_sysclass,
72 @@ -30,5 +31,8 @@ int __init s3c2442_init(void)
73  {
74         printk("S3C2442: Initialising architecture\n");
75  
76 +       /* make sure SD/MMC driver can distinguish 2440 from 2410 */
77 +       s3c_device_sdi.name = "s3c2440-sdi";
78 +
79         return sysdev_register(&s3c2442_sysdev);
80  }
81 diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
82 index dead617..fd59856 100644
83 --- a/drivers/mmc/host/Kconfig
84 +++ b/drivers/mmc/host/Kconfig
85 @@ -130,3 +130,14 @@ config MMC_SPI
86  
87           If unsure, or if your system has no SPI master driver, say N.
88  
89 +config MMC_S3C
90 +       tristate "Samsung S3C24xx SD/MMC Card Interface support"
91 +       depends on ARCH_S3C2410 && MMC
92 +       help
93 +         This selects a driver for the MCI interface found in
94 +         Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs.
95 +         If you have a board based on one of those and a MMC/SD
96 +         slot, say Y or M here.
97 +
98 +         If unsure, say N.
99 +
100 diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
101 index 3877c87..071d256 100644
102 --- a/drivers/mmc/host/Makefile
103 +++ b/drivers/mmc/host/Makefile
104 @@ -17,4 +17,4 @@ obj-$(CONFIG_MMC_OMAP)                += omap.o
105  obj-$(CONFIG_MMC_AT91)         += at91_mci.o
106  obj-$(CONFIG_MMC_TIFM_SD)      += tifm_sd.o
107  obj-$(CONFIG_MMC_SPI)          += mmc_spi.o
108 -
109 +obj-$(CONFIG_MMC_S3C)          += s3cmci.o
110 diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
111 new file mode 100644
112 index 0000000..edba055
113 --- /dev/null
114 +++ b/drivers/mmc/host/s3cmci.c
115 @@ -0,0 +1,1419 @@
116 +/*
117 + *  linux/drivers/mmc/s3cmci.h - Samsung S3C MCI driver
118 + *
119 + *  Copyright (C) 2004-2006 maintech GmbH, Thomas Kleffel <tk@maintech.de>
120 + *  Copyright (C) 2007 Harald Welte <laforge@gnumonks.org>
121 + *
122 + * This program is free software; you can redistribute it and/or modify
123 + * it under the terms of the GNU General Public License version 2 as
124 + * published by the Free Software Foundation.
125 + */
126 +
127 +#include <linux/module.h>
128 +#include <linux/dma-mapping.h>
129 +#include <linux/clk.h>
130 +#include <linux/mmc/host.h>
131 +#include <linux/platform_device.h>
132 +#include <linux/irq.h>
133 +
134 +#include <asm/dma.h>
135 +#include <asm/dma-mapping.h>
136 +
137 +#include <asm/io.h>
138 +#include <asm/arch/regs-sdi.h>
139 +#include <asm/arch/regs-gpio.h>
140 +#include <asm/arch/mci.h>
141 +#include <asm/arch/dma.h>
142 +
143 +#include "s3cmci.h"
144 +
145 +#define DRIVER_NAME "s3c-mci"
146 +
147 +enum dbg_channels {
148 +       dbg_err   = (1 << 0),
149 +       dbg_debug = (1 << 1),
150 +       dbg_info  = (1 << 2),
151 +       dbg_irq   = (1 << 3),
152 +       dbg_sg    = (1 << 4),
153 +       dbg_dma   = (1 << 5),
154 +       dbg_pio   = (1 << 6),
155 +       dbg_fail  = (1 << 7),
156 +       dbg_conf  = (1 << 8),
157 +};
158 +
159 +static const int dbgmap_err   = dbg_err | dbg_fail;
160 +static const int dbgmap_info  = dbg_info | dbg_conf;
161 +static const int dbgmap_debug = dbg_debug;
162 +
163 +#define dbg(host, channels, args...)            \
164 +       do {                                     \
165 +       if (dbgmap_err & channels)               \
166 +               dev_err(&host->pdev->dev, args); \
167 +       else if (dbgmap_info & channels)         \
168 +               dev_info(&host->pdev->dev, args);\
169 +       else if (dbgmap_debug & channels)        \
170 +               dev_dbg(&host->pdev->dev, args); \
171 +       } while (0)
172 +
173 +#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
174 +
175 +static struct s3c2410_dma_client s3cmci_dma_client = {
176 +       .name           = "s3c-mci",
177 +};
178 +
179 +static void finalize_request(struct s3cmci_host *host);
180 +static void s3cmci_send_request(struct mmc_host *mmc);
181 +static void s3cmci_reset(struct s3cmci_host *host);
182 +
183 +#ifdef CONFIG_MMC_DEBUG
184 +static inline void dbg_dumpregs(struct s3cmci_host *host, char *prefix)
185 +{
186 +       u32 con, pre, cmdarg, cmdcon, cmdsta, r0, r1, r2, r3, timer, bsize;
187 +       u32 datcon, datcnt, datsta, fsta, imask;
188 +
189 +       con     = readl(host->base + S3C2410_SDICON);
190 +       pre     = readl(host->base + S3C2410_SDIPRE);
191 +       cmdarg  = readl(host->base + S3C2410_SDICMDARG);
192 +       cmdcon  = readl(host->base + S3C2410_SDICMDCON);
193 +       cmdsta  = readl(host->base + S3C2410_SDICMDSTAT);
194 +       r0      = readl(host->base + S3C2410_SDIRSP0);
195 +       r1      = readl(host->base + S3C2410_SDIRSP1);
196 +       r2      = readl(host->base + S3C2410_SDIRSP2);
197 +       r3      = readl(host->base + S3C2410_SDIRSP3);
198 +       timer   = readl(host->base + S3C2410_SDITIMER);
199 +       bsize   = readl(host->base + S3C2410_SDIBSIZE);
200 +       datcon  = readl(host->base + S3C2410_SDIDCON);
201 +       datcnt  = readl(host->base + S3C2410_SDIDCNT);
202 +       datsta  = readl(host->base + S3C2410_SDIDSTA);
203 +       fsta    = readl(host->base + S3C2410_SDIFSTA);
204 +       imask   = readl(host->base + host->sdiimsk);
205 +
206 +       dbg(host, dbg_debug, "%s  CON:[%08x]  PRE:[%08x]  TMR:[%08x]\n",
207 +                               prefix, con, pre, timer);
208 +
209 +       dbg(host, dbg_debug, "%s CCON:[%08x] CARG:[%08x] CSTA:[%08x]\n",
210 +                               prefix, cmdcon, cmdarg, cmdsta);
211 +
212 +       dbg(host, dbg_debug, "%s DCON:[%08x] FSTA:[%08x]"
213 +                              " DSTA:[%08x] DCNT:[%08x]\n",
214 +                               prefix, datcon, fsta, datsta, datcnt);
215 +
216 +       dbg(host, dbg_debug, "%s   R0:[%08x]   R1:[%08x]"
217 +                              "   R2:[%08x]   R3:[%08x]\n",
218 +                               prefix, r0, r1, r2, r3);
219 +}
220 +
221 +static void prepare_dbgmsg(struct s3cmci_host *host, struct mmc_command *cmd,
222 +                                                               int stop)
223 +{
224 +       snprintf(host->dbgmsg_cmd, 300,
225 +               "#%u%s op:CMD%d arg:0x%08x flags:0x08%x retries:%u",
226 +               host->ccnt, (stop?" (STOP)":""), cmd->opcode,
227 +               cmd->arg, cmd->flags, cmd->retries);
228 +
229 +       if (cmd->data) {
230 +               snprintf(host->dbgmsg_dat, 300,
231 +                       "#%u bsize:%u blocks:%u bytes:%u",
232 +                       host->dcnt, cmd->data->blksz,
233 +                       cmd->data->blocks,
234 +                       cmd->data->blocks * cmd->data->blksz);
235 +       } else {
236 +               host->dbgmsg_dat[0] = '\0';
237 +       }
238 +}
239 +
240 +static void dbg_dumpcmd(struct s3cmci_host *host, struct mmc_command *cmd,
241 +                                                               int fail)
242 +{
243 +       unsigned int dbglvl = fail?dbg_fail:dbg_debug;
244 +
245 +       if (!cmd)
246 +               return;
247 +
248 +       if (cmd->error == 0)
249 +               dbg(host, dbglvl, "CMD[OK] %s R0:0x%08x\n",
250 +                       host->dbgmsg_cmd, cmd->resp[0]);
251 +       else
252 +               dbg(host, dbglvl, "CMD[FAIL(%d)] %s Status:%s\n",
253 +                       cmd->error, host->dbgmsg_cmd, host->status);
254 +
255 +       if (!cmd->data)
256 +               return;
257 +
258 +       if (cmd->data->error == 0)
259 +               dbg(host, dbglvl, "DAT[OK] %s\n", host->dbgmsg_dat);
260 +       else
261 +               dbg(host, dbglvl, "DAT[FAIL(%d)] %s DCNT:0x%08x\n",
262 +                       cmd->data->error, host->dbgmsg_dat,
263 +                       readl(host->base + S3C2410_SDIDCNT));
264 +}
265 +#endif /* CONFIG_MMC_DEBUG */
266 +
267 +static inline u32 enable_imask(struct s3cmci_host *host, u32 imask)
268 +{
269 +       u32 newmask;
270 +
271 +       newmask = readl(host->base + host->sdiimsk);
272 +       newmask |= imask;
273 +
274 +       writel(newmask, host->base + host->sdiimsk);
275 +
276 +       return newmask;
277 +}
278 +
279 +static inline u32 disable_imask(struct s3cmci_host *host, u32 imask)
280 +{
281 +       u32 newmask;
282 +
283 +       newmask = readl(host->base + host->sdiimsk);
284 +       newmask &= ~imask;
285 +
286 +       writel(newmask, host->base + host->sdiimsk);
287 +
288 +       return newmask;
289 +}
290 +
291 +static inline void clear_imask(struct s3cmci_host *host)
292 +{
293 +       writel(0, host->base + host->sdiimsk);
294 +}
295 +
296 +static inline int get_data_buffer(struct s3cmci_host *host,
297 +                                 u32 *bytes, u8 **pointer)
298 +{
299 +       struct scatterlist *sg;
300 +
301 +       if (host->pio_active == XFER_NONE)
302 +               return -EINVAL;
303 +
304 +       if ((!host->mrq) || (!host->mrq->data))
305 +               return -EINVAL;
306 +
307 +       if (host->pio_sgptr >= host->mrq->data->sg_len) {
308 +               dbg(host, dbg_debug, "no more buffers (%i/%i)\n",
309 +                     host->pio_sgptr, host->mrq->data->sg_len);
310 +               return -EBUSY;
311 +       }
312 +       sg = &host->mrq->data->sg[host->pio_sgptr];
313 +
314 +       *bytes = sg->length;
315 +       *pointer = page_address(sg_page(sg)) + sg->offset;
316 +
317 +       host->pio_sgptr++;
318 +
319 +       dbg(host, dbg_sg, "new buffer (%i/%i)\n",
320 +             host->pio_sgptr, host->mrq->data->sg_len);
321 +
322 +       return 0;
323 +}
324 +
325 +#define FIFO_FILL(host) (readl(host->base + S3C2410_SDIFSTA) &         \
326 +                               S3C2410_SDIFSTA_COUNTMASK)
327 +#define FIFO_FREE(host) (63 - (readl(host->base + S3C2410_SDIFSTA)     \
328 +                               & S3C2410_SDIFSTA_COUNTMASK))
329 +
330 +static inline void do_pio_read(struct s3cmci_host *host)
331 +{
332 +       int res;
333 +       int fifo;
334 +       void __iomem *from_ptr;
335 +
336 +       /* write real prescaler to host, it might be set slow to fix */
337 +       writel(host->prescaler, host->base + S3C2410_SDIPRE);
338 +
339 +       from_ptr = host->base + host->sdidata;
340 +
341 +       while ((fifo = FIFO_FILL(host))) {
342 +               if (!host->pio_bytes) {
343 +                       res = get_data_buffer(host, &host->pio_bytes,
344 +                                                       &host->pio_ptr);
345 +                       if (res) {
346 +                               host->pio_active = XFER_NONE;
347 +                               host->complete_what = COMPLETION_FINALIZE;
348 +
349 +                               dbg(host, dbg_pio, "pio_read(): "
350 +                                   "complete (no more data).\n");
351 +                               return;
352 +                       }
353 +
354 +                       dbg(host, dbg_pio, "pio_read(): new target: "
355 +                           "[%i]@[%p]\n", host->pio_bytes, host->pio_ptr);
356 +               }
357 +
358 +               dbg(host, dbg_pio, "pio_read(): fifo:[%02i] "
359 +                   "buffer:[%03i] dcnt:[%08X]\n", fifo, host->pio_bytes,
360 +                   readl(host->base + S3C2410_SDIDCNT));
361 +
362 +               if (fifo > host->pio_bytes)
363 +                       fifo = host->pio_bytes;
364 +
365 +               host->pio_bytes -= fifo;
366 +               host->pio_count += fifo;
367 +
368 +               /* we might have an unaligned start of data */
369 +               while (((unsigned long)host->pio_ptr & 0x03) && fifo) {
370 +                       *(host->pio_ptr++) = readb(host->base + host->sdidata_b);
371 +                       fifo--;
372 +               }
373 +
374 +               /* and a major chunk of data in the middle */
375 +               for (; fifo >= 4; fifo -=4) {
376 +                       *(u32 *) host->pio_ptr = readl(from_ptr);
377 +                       host->pio_ptr+= 4;
378 +               }
379 +
380 +               /* as well as some non-modulo-four trailer */
381 +               while (fifo) {
382 +                       *(host->pio_ptr++) = readb(host->base + host->sdidata_b);
383 +                       fifo--;
384 +               }
385 +       }
386 +
387 +       if (!host->pio_bytes) {
388 +               res = get_data_buffer(host, &host->pio_bytes, &host->pio_ptr);
389 +               if (res) {
390 +                       dbg(host, dbg_pio, "pio_read(): "
391 +                           "complete (no more buffers).\n");
392 +                       host->pio_active = XFER_NONE;
393 +                       host->complete_what = COMPLETION_FINALIZE;
394 +
395 +                       return;
396 +               }
397 +       }
398 +
399 +       enable_imask(host, S3C2410_SDIIMSK_RXFIFOHALF
400 +                                               | S3C2410_SDIIMSK_RXFIFOLAST);
401 +}
402 +
403 +static inline void do_pio_write(struct s3cmci_host *host)
404 +{
405 +       int res;
406 +       int fifo;
407 +
408 +       void __iomem *to_ptr;
409 +
410 +       to_ptr = host->base + host->sdidata;
411 +
412 +       while ((fifo = FIFO_FREE(host))) {
413 +               if (!host->pio_bytes) {
414 +                       res = get_data_buffer(host, &host->pio_bytes,
415 +                                                       &host->pio_ptr);
416 +                       if (res) {
417 +                               dbg(host, dbg_pio, "pio_write(): "
418 +                                       "complete (no more data).\n");
419 +                               host->pio_active = XFER_NONE;
420 +
421 +                               return;
422 +                       }
423 +
424 +                       dbg(host, dbg_pio, "pio_write(): "
425 +                               "new source: [%i]@[%p]\n",
426 +                               host->pio_bytes, host->pio_ptr);
427 +
428 +               }
429 +
430 +               if (fifo > host->pio_bytes)
431 +                       fifo = host->pio_bytes;
432 +
433 +               host->pio_bytes -= fifo;
434 +               host->pio_count += fifo;
435 +
436 +               /* we might have an unaligned start of data */
437 +               while (((unsigned long)host->pio_ptr & 0x03) && fifo) {
438 +                       writeb(*(host->pio_ptr++), host->base + host->sdidata_b);
439 +                       fifo--;
440 +               }
441 +
442 +               /* and a major chunk of data in the middle */
443 +               for (; fifo >= 4; fifo -=4) {
444 +                       writel(*(u32 *) host->pio_ptr, to_ptr);
445 +                       host->pio_ptr += 4;
446 +               }
447 +
448 +               /* as well as some non-modulo-four trailer */
449 +               while (fifo) {
450 +                       writeb(*(host->pio_ptr++), host->base + host->sdidata_b);
451 +                       fifo--;
452 +               }
453 +       }
454 +
455 +       enable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);
456 +}
457 +
458 +static void pio_tasklet(unsigned long data)
459 +{
460 +       struct s3cmci_host *host = (struct s3cmci_host *) data;
461 +
462 +       disable_irq(host->irq);
463 +
464 +       if (host->pio_active == XFER_WRITE)
465 +               do_pio_write(host);
466 +
467 +       if (host->pio_active == XFER_READ)
468 +               do_pio_read(host);
469 +
470 +       if (host->complete_what == COMPLETION_FINALIZE) {
471 +               clear_imask(host);
472 +               if (host->pio_active != XFER_NONE) {
473 +                       dbg(host, dbg_err, "unfinished %s "
474 +                               "- pio_count:[%u] pio_bytes:[%u]\n",
475 +                               (host->pio_active == XFER_READ)?"read":"write",
476 +                               host->pio_count, host->pio_bytes);
477 +
478 +                       host->mrq->data->error = -EIO;
479 +               }
480 +
481 +               finalize_request(host);
482 +       } else
483 +               enable_irq(host->irq);
484 +}
485 +
486 +/*
487 + * ISR for SDI Interface IRQ
488 + * Communication between driver and ISR works as follows:
489 + *   host->mrq                         points to current request
490 + *   host->complete_what       tells ISR when the request is considered done
491 + *     COMPLETION_CMDSENT        when the command was sent
492 + *     COMPLETION_RSPFIN          when a response was received
493 + *     COMPLETION_XFERFINISH     when the data transfer is finished
494 + *     COMPLETION_XFERFINISH_RSPFIN both of the above.
495 + *   host->complete_request    is the completion-object the driver waits for
496 + *
497 + * 1) Driver sets up host->mrq and host->complete_what
498 + * 2) Driver prepares the transfer
499 + * 3) Driver enables interrupts
500 + * 4) Driver starts transfer
501 + * 5) Driver waits for host->complete_rquest
502 + * 6) ISR checks for request status (errors and success)
503 + * 6) ISR sets host->mrq->cmd->error and host->mrq->data->error
504 + * 7) ISR completes host->complete_request
505 + * 8) ISR disables interrupts
506 + * 9) Driver wakes up and takes care of the request
507 + *
508 + * Note: "->error"-fields are expected to be set to 0 before the request
509 + *       was issued by mmc.c - therefore they are only set, when an error
510 + *       contition comes up
511 + */
512 +
513 +static irqreturn_t s3cmci_irq(int irq, void *dev_id)
514 +{
515 +       struct s3cmci_host *host;
516 +       struct mmc_command *cmd;
517 +       u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt, mci_imsk;
518 +       u32 mci_cclear, mci_dclear;
519 +       unsigned long iflags;
520 +       int cardint = 0;
521 +
522 +       host = (struct s3cmci_host *)dev_id;
523 +
524 +       spin_lock_irqsave(&host->complete_lock, iflags);
525 +
526 +       mci_csta        = readl(host->base + S3C2410_SDICMDSTAT);
527 +       mci_dsta        = readl(host->base + S3C2410_SDIDSTA);
528 +       mci_dcnt        = readl(host->base + S3C2410_SDIDCNT);
529 +       mci_fsta        = readl(host->base + S3C2410_SDIFSTA);
530 +       mci_imsk        = readl(host->base + host->sdiimsk);
531 +       mci_cclear      = 0;
532 +       mci_dclear      = 0;
533 +
534 +       if ((host->complete_what == COMPLETION_NONE) ||
535 +                       (host->complete_what == COMPLETION_FINALIZE)) {
536 +               host->status = "nothing to complete";
537 +               clear_imask(host);
538 +               goto irq_out;
539 +       }
540 +
541 +       if (!host->mrq) {
542 +               host->status = "no active mrq";
543 +               clear_imask(host);
544 +               goto irq_out;
545 +       }
546 +
547 +       cmd = host->cmd_is_stop?host->mrq->stop:host->mrq->cmd;
548 +
549 +       if (!cmd) {
550 +               host->status = "no active cmd";
551 +               clear_imask(host);
552 +               goto irq_out;
553 +       }
554 +
555 +       if (!host->dodma) {
556 +               if ((host->pio_active == XFER_WRITE) &&
557 +                               (mci_fsta & S3C2410_SDIFSTA_TFDET)) {
558 +
559 +                       disable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);
560 +                       tasklet_schedule(&host->pio_tasklet);
561 +                       host->status = "pio tx";
562 +               }
563 +
564 +               if ((host->pio_active == XFER_READ) &&
565 +                               (mci_fsta & S3C2410_SDIFSTA_RFDET)) {
566 +
567 +                       disable_imask(host, S3C2410_SDIIMSK_RXFIFOHALF |
568 +                                               S3C2410_SDIIMSK_RXFIFOLAST);
569 +
570 +                       tasklet_schedule(&host->pio_tasklet);
571 +                       host->status = "pio rx";
572 +               }
573 +       }
574 +
575 +       if (mci_csta & S3C2410_SDICMDSTAT_CMDTIMEOUT) {
576 +               cmd->error = -ETIMEDOUT;
577 +               host->status = "error: command timeout";
578 +               goto fail_transfer;
579 +       }
580 +
581 +       if (mci_csta & S3C2410_SDICMDSTAT_CMDSENT) {
582 +               if (host->complete_what == COMPLETION_CMDSENT) {
583 +                       host->status = "ok: command sent";
584 +                       goto close_transfer;
585 +               }
586 +
587 +               mci_cclear |= S3C2410_SDICMDSTAT_CMDSENT;
588 +       }
589 +
590 +       if (mci_csta & S3C2410_SDICMDSTAT_CRCFAIL) {
591 +               if (cmd->flags & MMC_RSP_CRC) {
592 +                       if (host->mrq->cmd->flags & MMC_RSP_136) {
593 +                               dbg(host, dbg_irq, "fixup for chip bug: "
594 +                                   "ignore CRC fail with long rsp\n");
595 +                       } else {
596 +                               cmd->error = -EILSEQ;
597 +                               host->status = "error: bad command crc";
598 +                               goto fail_transfer;
599 +                       }
600 +               }
601 +
602 +               mci_cclear |= S3C2410_SDICMDSTAT_CRCFAIL;
603 +       }
604 +
605 +       if (mci_csta & S3C2410_SDICMDSTAT_RSPFIN) {
606 +               if (host->complete_what == COMPLETION_RSPFIN) {
607 +                       host->status = "ok: command response received";
608 +                       goto close_transfer;
609 +               }
610 +
611 +               if (host->complete_what == COMPLETION_XFERFINISH_RSPFIN)
612 +                       host->complete_what = COMPLETION_XFERFINISH;
613 +
614 +               mci_cclear |= S3C2410_SDICMDSTAT_RSPFIN;
615 +       }
616 +
617 +       /* errors handled after this point are only relevant
618 +          when a data transfer is in progress */
619 +
620 +       if (!cmd->data)
621 +               goto clear_status_bits;
622 +
623 +       /* Check for FIFO failure */
624 +       if (host->is2440) {
625 +               if (mci_fsta & S3C2440_SDIFSTA_FIFOFAIL) {
626 +                       host->mrq->data->error = -EIO;
627 +                       host->status = "error: 2440 fifo failure";
628 +                       goto fail_transfer;
629 +               }
630 +       } else {
631 +               if (mci_dsta & S3C2410_SDIDSTA_FIFOFAIL) {
632 +                       cmd->data->error = -EIO;
633 +                       host->status = "error:  fifo failure";
634 +                       goto fail_transfer;
635 +               }
636 +       }
637 +
638 +       if (mci_dsta & S3C2410_SDIDSTA_RXCRCFAIL) {
639 +               cmd->data->error = -EILSEQ;
640 +               host->status = "error: bad data crc (outgoing)";
641 +               goto fail_transfer;
642 +       }
643 +
644 +       if (mci_dsta & S3C2410_SDIDSTA_CRCFAIL) {
645 +               cmd->data->error = -EIO;
646 +               host->status = "error: bad data crc (incoming)";
647 +               goto fail_transfer;
648 +       }
649 +
650 +       if (mci_dsta & S3C2410_SDIDSTA_DATATIMEOUT) {
651 +               cmd->data->error = -ETIMEDOUT;
652 +               host->status = "error: data timeout";
653 +               goto fail_transfer;
654 +       }
655 +
656 +       if (mci_dsta & S3C2410_SDIDSTA_XFERFINISH) {
657 +               if (host->complete_what == COMPLETION_XFERFINISH) {
658 +                       host->status = "ok: data transfer completed";
659 +                       goto close_transfer;
660 +               }
661 +
662 +               if (host->complete_what == COMPLETION_XFERFINISH_RSPFIN)
663 +                       host->complete_what = COMPLETION_RSPFIN;
664 +
665 +               mci_dclear |= S3C2410_SDIDSTA_XFERFINISH;
666 +       }
667 +
668 +       if (mci_dsta & S3C2410_SDIDSTA_SDIOIRQDETECT) {
669 +               cardint = 1;
670 +               mci_dclear |= S3C2410_SDIDSTA_SDIOIRQDETECT;
671 +       }
672 +
673 +clear_status_bits:
674 +       writel(mci_cclear, host->base + S3C2410_SDICMDSTAT);
675 +       writel(mci_dclear, host->base + S3C2410_SDIDSTA);
676 +
677 +       goto irq_out;
678 +
679 +fail_transfer:
680 +       host->pio_active = XFER_NONE;
681 +
682 +close_transfer:
683 +       host->complete_what = COMPLETION_FINALIZE;
684 +
685 +       clear_imask(host);
686 +       tasklet_schedule(&host->pio_tasklet);
687 +
688 +       goto irq_out;
689 +
690 +irq_out:
691 +       dbg(host, dbg_irq, "csta:0x%08x dsta:0x%08x "
692 +                          "fsta:0x%08x dcnt:0x%08x status:%s.\n",
693 +                               mci_csta, mci_dsta, mci_fsta,
694 +                               mci_dcnt, host->status);
695 +
696 +       spin_unlock_irqrestore(&host->complete_lock, iflags);
697 +
698 +       /* We have to delay this as it calls back into the driver */
699 +       if (cardint)
700 +               mmc_signal_sdio_irq(host->mmc);
701 +
702 +       return IRQ_HANDLED;
703 +
704 +}
705 +
706 +/*
707 + * ISR for the CardDetect Pin
708 +*/
709 +
710 +static irqreturn_t s3cmci_irq_cd(int irq, void *dev_id)
711 +{
712 +       struct s3cmci_host *host = (struct s3cmci_host *)dev_id;
713 +
714 +       dbg(host, dbg_irq, "card detect\n");
715 +
716 +       mmc_detect_change(host->mmc, 500);
717 +
718 +       return IRQ_HANDLED;
719 +}
720 +
721 +void s3cmci_dma_done_callback(struct s3c2410_dma_chan *dma_ch, void *buf_id,
722 +       int size, enum s3c2410_dma_buffresult result)
723 +{
724 +       unsigned long iflags;
725 +       u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt;
726 +       struct s3cmci_host *host = (struct s3cmci_host *)buf_id;
727 +
728 +       mci_csta        = readl(host->base + S3C2410_SDICMDSTAT);
729 +       mci_dsta        = readl(host->base + S3C2410_SDIDSTA);
730 +       mci_fsta        = readl(host->base + S3C2410_SDIFSTA);
731 +       mci_dcnt        = readl(host->base + S3C2410_SDIDCNT);
732 +
733 +       if ((!host->mrq) || (!host->mrq) || (!host->mrq->data))
734 +               return;
735 +
736 +       if (!host->dmatogo)
737 +               return;
738 +
739 +       spin_lock_irqsave(&host->complete_lock, iflags);
740 +
741 +       if (result != S3C2410_RES_OK) {
742 +               dbg(host, dbg_fail, "DMA FAILED: csta=0x%08x dsta=0x%08x "
743 +                       "fsta=0x%08x dcnt:0x%08x result:0x%08x toGo:%u\n",
744 +                       mci_csta, mci_dsta, mci_fsta,
745 +                       mci_dcnt, result, host->dmatogo);
746 +
747 +               goto fail_request;
748 +       }
749 +
750 +       host->dmatogo--;
751 +       if (host->dmatogo) {
752 +               dbg(host, dbg_dma, "DMA DONE  Size:%i DSTA:[%08x] "
753 +                       "DCNT:[%08x] toGo:%u\n",
754 +                       size, mci_dsta, mci_dcnt, host->dmatogo);
755 +
756 +               goto out;
757 +       }
758 +
759 +       dbg(host, dbg_dma, "DMA FINISHED Size:%i DSTA:%08x DCNT:%08x\n",
760 +               size, mci_dsta, mci_dcnt);
761 +
762 +       host->complete_what = COMPLETION_FINALIZE;
763 +
764 +out:
765 +       tasklet_schedule(&host->pio_tasklet);
766 +       spin_unlock_irqrestore(&host->complete_lock, iflags);
767 +       return;
768 +
769 +
770 +fail_request:
771 +       host->mrq->data->error = -EIO;
772 +       host->complete_what = COMPLETION_FINALIZE;
773 +       writel(0, host->base + host->sdiimsk);
774 +       goto out;
775 +
776 +}
777 +
778 +static void finalize_request(struct s3cmci_host *host)
779 +{
780 +       struct mmc_request *mrq = host->mrq;
781 +       struct mmc_command *cmd = host->cmd_is_stop?mrq->stop:mrq->cmd;
782 +       int debug_as_failure = 0;
783 +
784 +       if (host->complete_what != COMPLETION_FINALIZE)
785 +               return;
786 +
787 +       if (!mrq)
788 +               return;
789 +
790 +       if (cmd->data && (cmd->error == 0) &&
791 +                 (cmd->data->error == 0)) {
792 +
793 +               if (host->dodma && (!host->dma_complete)) {
794 +                       dbg(host, dbg_dma, "DMA Missing!\n");
795 +                       return;
796 +               }
797 +       }
798 +
799 +       /* Read response */
800 +       cmd->resp[0] = readl(host->base + S3C2410_SDIRSP0);
801 +       cmd->resp[1] = readl(host->base + S3C2410_SDIRSP1);
802 +       cmd->resp[2] = readl(host->base + S3C2410_SDIRSP2);
803 +       cmd->resp[3] = readl(host->base + S3C2410_SDIRSP3);
804 +
805 +       /* reset clock speed, as it could still be set low for */
806 +       writel(host->prescaler, host->base + S3C2410_SDIPRE);
807 +
808 +       if (cmd->error)
809 +               debug_as_failure = 1;
810 +
811 +       if (cmd->data && cmd->data->error)
812 +               debug_as_failure = 1;
813 +
814 +#ifdef CONFIG_MMC_DEBUG
815 +       dbg_dumpcmd(host, cmd, debug_as_failure);
816 +#endif
817 +       /* Cleanup controller */
818 +       writel(0, host->base + S3C2410_SDICMDARG);
819 +       writel(S3C2410_SDIDCON_STOP, host->base + S3C2410_SDIDCON);
820 +       writel(0, host->base + S3C2410_SDICMDCON);
821 +       writel(0, host->base + host->sdiimsk);
822 +
823 +       if (cmd->data && cmd->error)
824 +               cmd->data->error = cmd->error;
825 +
826 +       if (cmd->data && cmd->data->stop && (!host->cmd_is_stop)) {
827 +               host->cmd_is_stop = 1;
828 +               s3cmci_send_request(host->mmc);
829 +               return;
830 +       }
831 +
832 +       /* If we have no data transfer we are finished here */
833 +       if (!mrq->data)
834 +               goto request_done;
835 +
836 +       /* Calulate the amout of bytes transfer, but only if there was
837 +        * no error */
838 +       if (mrq->data->error == 0)
839 +               mrq->data->bytes_xfered =
840 +                       (mrq->data->blocks * mrq->data->blksz);
841 +       else
842 +               mrq->data->bytes_xfered = 0;
843 +
844 +       /* If we had an error while transfering data we flush the
845 +        * DMA channel and the fifo to clear out any garbage */
846 +       if (mrq->data->error) {
847 +               if (host->dodma)
848 +                       s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
849 +
850 +               if (host->is2440) {
851 +                       /* Clear failure register and reset fifo */
852 +                       writel(S3C2440_SDIFSTA_FIFORESET |
853 +                              S3C2440_SDIFSTA_FIFOFAIL,
854 +                              host->base + S3C2410_SDIFSTA);
855 +               } else {
856 +                       u32 mci_con;
857 +
858 +                       /* reset fifo */
859 +                       mci_con = readl(host->base + S3C2410_SDICON);
860 +                       mci_con |= S3C2410_SDICON_FIFORESET;
861 +
862 +                       writel(mci_con, host->base + S3C2410_SDICON);
863 +               }
864 +       }
865 +
866 +request_done:
867 +       host->complete_what = COMPLETION_NONE;
868 +       host->mrq = NULL;
869 +       mmc_request_done(host->mmc, mrq);
870 +}
871 +
872 +
873 +void s3cmci_dma_setup(struct s3cmci_host *host, enum s3c2410_dmasrc source)
874 +{
875 +       static int setup_ok;
876 +       static enum s3c2410_dmasrc last_source = -1;
877 +
878 +       if (last_source == source)
879 +               return;
880 +
881 +       last_source = source;
882 +
883 +       s3c2410_dma_devconfig(host->dma, source, 3,
884 +               host->mem->start + host->sdidata);
885 +
886 +       if (!setup_ok) {
887 +               s3c2410_dma_config(host->dma, 4,
888 +                       (S3C2410_DCON_HWTRIG | S3C2410_DCON_CH0_SDI));
889 +               s3c2410_dma_set_buffdone_fn(host->dma,
890 +                                           s3cmci_dma_done_callback);
891 +               s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART);
892 +               setup_ok = 1;
893 +       }
894 +}
895 +
896 +static void s3cmci_send_command(struct s3cmci_host *host,
897 +                                       struct mmc_command *cmd)
898 +{
899 +       u32 ccon, imsk;
900 +
901 +       imsk  = S3C2410_SDIIMSK_CRCSTATUS | S3C2410_SDIIMSK_CMDTIMEOUT |
902 +               S3C2410_SDIIMSK_RESPONSEND | S3C2410_SDIIMSK_CMDSENT |
903 +               S3C2410_SDIIMSK_RESPONSECRC;
904 +
905 +       enable_imask(host, imsk);
906 +
907 +       if (cmd->data)
908 +               host->complete_what = COMPLETION_XFERFINISH_RSPFIN;
909 +       else if (cmd->flags & MMC_RSP_PRESENT)
910 +               host->complete_what = COMPLETION_RSPFIN;
911 +       else
912 +               host->complete_what = COMPLETION_CMDSENT;
913 +
914 +       writel(cmd->arg, host->base + S3C2410_SDICMDARG);
915 +
916 +       ccon = cmd->opcode & S3C2410_SDICMDCON_INDEX;
917 +       ccon |= S3C2410_SDICMDCON_SENDERHOST | S3C2410_SDICMDCON_CMDSTART;
918 +
919 +       if (cmd->flags & MMC_RSP_PRESENT)
920 +               ccon |= S3C2410_SDICMDCON_WAITRSP;
921 +
922 +       if (cmd->flags & MMC_RSP_136)
923 +               ccon |= S3C2410_SDICMDCON_LONGRSP;
924 +
925 +       writel(ccon, host->base + S3C2410_SDICMDCON);
926 +}
927 +
928 +static int s3cmci_setup_data(struct s3cmci_host *host, struct mmc_data *data)
929 +{
930 +       u32 dcon, imsk, stoptries = 3;
931 +
932 +       /* write DCON register */
933 +
934 +       if (!data) {
935 +               writel(0, host->base + S3C2410_SDIDCON);
936 +               return 0;
937 +       }
938 +
939 +       while (readl(host->base + S3C2410_SDIDSTA) &
940 +               (S3C2410_SDIDSTA_TXDATAON | S3C2410_SDIDSTA_RXDATAON)) {
941 +
942 +               dbg(host, dbg_err,
943 +                   "mci_setup_data() transfer stillin progress.\n");
944 +
945 +               writel(S3C2410_SDIDCON_STOP, host->base + S3C2410_SDIDCON);
946 +               s3cmci_reset(host);
947 +
948 +               if (0 == (stoptries--)) {
949 +#ifdef CONFIG_MMC_DEBUG
950 +                       dbg_dumpregs(host, "DRF");
951 +#endif
952 +
953 +                       return -EINVAL;
954 +               }
955 +       }
956 +
957 +       dcon  = data->blocks & S3C2410_SDIDCON_BLKNUM_MASK;
958 +
959 +       if (host->dodma)
960 +               dcon |= S3C2410_SDIDCON_DMAEN;
961 +
962 +       if (host->bus_width == MMC_BUS_WIDTH_4)
963 +               dcon |= S3C2410_SDIDCON_WIDEBUS;
964 +
965 +       if (!(data->flags & MMC_DATA_STREAM))
966 +               dcon |= S3C2410_SDIDCON_BLOCKMODE;
967 +
968 +       if (data->flags & MMC_DATA_WRITE) {
969 +               dcon |= S3C2410_SDIDCON_TXAFTERRESP;
970 +               dcon |= S3C2410_SDIDCON_XFER_TXSTART;
971 +       }
972 +
973 +       if (data->flags & MMC_DATA_READ) {
974 +               dcon |= S3C2410_SDIDCON_RXAFTERCMD;
975 +               dcon |= S3C2410_SDIDCON_XFER_RXSTART;
976 +       }
977 +
978 +       if (host->is2440) {
979 +               dcon |= S3C2440_SDIDCON_DS_WORD;
980 +               dcon |= S3C2440_SDIDCON_DATSTART;
981 +       }
982 +
983 +       writel(dcon, host->base + S3C2410_SDIDCON);
984 +
985 +       /* write BSIZE register */
986 +
987 +       writel(data->blksz, host->base + S3C2410_SDIBSIZE);
988 +
989 +       /* add to IMASK register */
990 +       imsk =  S3C2410_SDIIMSK_FIFOFAIL | S3C2410_SDIIMSK_DATACRC |
991 +               S3C2410_SDIIMSK_DATATIMEOUT | S3C2410_SDIIMSK_DATAFINISH;
992 +
993 +       enable_imask(host, imsk);
994 +
995 +       /* write TIMER register */
996 +
997 +       if (host->is2440) {
998 +               writel(0x007FFFFF, host->base + S3C2410_SDITIMER);
999 +       } else {
1000 +               writel(0x0000FFFF, host->base + S3C2410_SDITIMER);
1001 +
1002 +               /* FIX: set slow clock to prevent timeouts on read */
1003 +               if (data->flags & MMC_DATA_READ)
1004 +                       writel(0xFF, host->base + S3C2410_SDIPRE);
1005 +       }
1006 +
1007 +       return 0;
1008 +}
1009 +
1010 +static int s3cmci_prepare_pio(struct s3cmci_host *host, struct mmc_data *data)
1011 +{
1012 +       int rw = (data->flags & MMC_DATA_WRITE)?1:0;
1013 +
1014 +       if (rw != ((data->flags & MMC_DATA_READ)?0:1))
1015 +               return -EINVAL;
1016 +
1017 +       host->pio_sgptr = 0;
1018 +       host->pio_bytes = 0;
1019 +       host->pio_count = 0;
1020 +       host->pio_active = rw?XFER_WRITE:XFER_READ;
1021 +
1022 +       if (rw) {
1023 +               do_pio_write(host);
1024 +               enable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);
1025 +       } else {
1026 +               enable_imask(host, S3C2410_SDIIMSK_RXFIFOHALF
1027 +                       | S3C2410_SDIIMSK_RXFIFOLAST);
1028 +       }
1029 +
1030 +       return 0;
1031 +}
1032 +
1033 +static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)
1034 +{
1035 +       int dma_len, i;
1036 +
1037 +       int rw = (data->flags & MMC_DATA_WRITE)?1:0;
1038 +
1039 +       if (rw != ((data->flags & MMC_DATA_READ)?0:1))
1040 +               return -EINVAL;
1041 +
1042 +       s3cmci_dma_setup(host, rw?S3C2410_DMASRC_MEM:S3C2410_DMASRC_HW);
1043 +       s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
1044 +
1045 +       dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
1046 +                               (rw)?DMA_TO_DEVICE:DMA_FROM_DEVICE);
1047 +
1048 +
1049 +       if (dma_len == 0)
1050 +               return -ENOMEM;
1051 +
1052 +       host->dma_complete = 0;
1053 +       host->dmatogo = dma_len;
1054 +
1055 +       for (i = 0; i < dma_len; i++) {
1056 +               int res;
1057 +
1058 +               dbg(host, dbg_dma, "enqueue %i:%u@%u\n", i,
1059 +                       sg_dma_address(&data->sg[i]),
1060 +                       sg_dma_len(&data->sg[i]));
1061 +
1062 +               res = s3c2410_dma_enqueue(host->dma, (void *) host,
1063 +                               sg_dma_address(&data->sg[i]),
1064 +                               sg_dma_len(&data->sg[i]));
1065 +
1066 +               if (res) {
1067 +                       s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
1068 +                       return -EBUSY;
1069 +               }
1070 +       }
1071 +
1072 +       s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_START);
1073 +
1074 +       return 0;
1075 +}
1076 +
1077 +static void s3cmci_send_request(struct mmc_host *mmc)
1078 +{
1079 +       struct s3cmci_host *host = mmc_priv(mmc);
1080 +       struct mmc_request *mrq = host->mrq;
1081 +       struct mmc_command *cmd = host->cmd_is_stop?mrq->stop:mrq->cmd;
1082 +
1083 +       host->ccnt++;
1084 +#ifdef CONFIG_MMC_DEBUG
1085 +       prepare_dbgmsg(host, cmd, host->cmd_is_stop);
1086 +#endif
1087 +       /* clear command, data and fifo status registers;
1088 +        * Fifo clear only necessary on 2440, but doesn't hurt on 2410 */
1089 +       writel(0xFFFFFFFF, host->base + S3C2410_SDICMDSTAT);
1090 +       writel(0xFFFFFFFF, host->base + S3C2410_SDIDSTA);
1091 +       writel(0xFFFFFFFF, host->base + S3C2410_SDIFSTA);
1092 +
1093 +       if (cmd->data) {
1094 +               int res;
1095 +               res = s3cmci_setup_data(host, cmd->data);
1096 +
1097 +               host->dcnt++;
1098 +
1099 +               if (res) {
1100 +                       cmd->error = -EIO;
1101 +                       cmd->data->error = -EIO;
1102 +
1103 +                       mmc_request_done(mmc, mrq);
1104 +                       return;
1105 +               }
1106 +
1107 +
1108 +               if (host->dodma)
1109 +                       res = s3cmci_prepare_dma(host, cmd->data);
1110 +               else
1111 +                       res = s3cmci_prepare_pio(host, cmd->data);
1112 +
1113 +               if (res) {
1114 +                       cmd->error = -EIO;
1115 +                       cmd->data->error = -EIO;
1116 +
1117 +                       mmc_request_done(mmc, mrq);
1118 +                       return;
1119 +               }
1120 +
1121 +       }
1122 +
1123 +       s3cmci_send_command(host, cmd);
1124 +       enable_irq(host->irq);
1125 +}
1126 +
1127 +static void s3cmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
1128 +{
1129 +       struct s3cmci_host *host = mmc_priv(mmc);
1130 +
1131 +       host->cmd_is_stop = 0;
1132 +       host->mrq = mrq;
1133 +
1134 +       s3cmci_send_request(mmc);
1135 +}
1136 +
1137 +static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1138 +{
1139 +       struct s3cmci_host *host = mmc_priv(mmc);
1140 +       u32 mci_psc, mci_con;
1141 +
1142 +       /* Set power */
1143 +       mci_con = readl(host->base + S3C2410_SDICON);
1144 +       switch (ios->power_mode) {
1145 +       case MMC_POWER_ON:
1146 +       case MMC_POWER_UP:
1147 +               s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_SDCLK);
1148 +               s3c2410_gpio_cfgpin(S3C2410_GPE6, S3C2410_GPE6_SDCMD);
1149 +               s3c2410_gpio_cfgpin(S3C2410_GPE7, S3C2410_GPE7_SDDAT0);
1150 +               s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);
1151 +               s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2);
1152 +               s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3);
1153 +
1154 +               if (host->pdata->set_power)
1155 +                       host->pdata->set_power(ios->power_mode, ios->vdd);
1156 +
1157 +               if (!host->is2440)
1158 +                       mci_con |= S3C2410_SDICON_FIFORESET;
1159 +
1160 +               break;
1161 +
1162 +       case MMC_POWER_OFF:
1163 +       default:
1164 +               s3c2410_gpio_setpin(S3C2410_GPE5, 0);
1165 +               s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_OUTP);
1166 +
1167 +               if (host->pdata->set_power)
1168 +                       host->pdata->set_power(ios->power_mode, ios->vdd);
1169 +
1170 +               if (host->is2440)
1171 +                       mci_con |= S3C2440_SDICON_SDRESET;
1172 +
1173 +               break;
1174 +       }
1175 +
1176 +       /* Set clock */
1177 +       for (mci_psc = 0; mci_psc < 255; mci_psc++) {
1178 +               host->real_rate = host->clk_rate / (host->clk_div*(mci_psc+1));
1179 +
1180 +               if (host->real_rate <= ios->clock)
1181 +                       break;
1182 +       }
1183 +
1184 +       if (mci_psc > 255)
1185 +               mci_psc = 255;
1186 +       host->prescaler = mci_psc;
1187 +
1188 +       writel(host->prescaler, host->base + S3C2410_SDIPRE);
1189 +
1190 +       /* If requested clock is 0, real_rate will be 0, too */
1191 +       if (ios->clock == 0)
1192 +               host->real_rate = 0;
1193 +
1194 +       /* Set CLOCK_ENABLE */
1195 +       if (ios->clock)
1196 +               mci_con |= S3C2410_SDICON_CLOCKTYPE;
1197 +       else
1198 +               mci_con &= ~S3C2410_SDICON_CLOCKTYPE;
1199 +
1200 +       writel(mci_con, host->base + S3C2410_SDICON);
1201 +
1202 +       if ((ios->power_mode == MMC_POWER_ON)
1203 +               || (ios->power_mode == MMC_POWER_UP)) {
1204 +
1205 +               dbg(host, dbg_conf, "running at %lukHz (requested: %ukHz).\n",
1206 +                   host->real_rate/1000, ios->clock/1000);
1207 +       } else {
1208 +               dbg(host, dbg_conf, "powered down.\n");
1209 +       }
1210 +
1211 +       host->bus_width = ios->bus_width;
1212 +
1213 +}
1214 +
1215 +static void s3cmci_reset(struct s3cmci_host *host)
1216 +{
1217 +       u32 con = readl(host->base + S3C2410_SDICON);
1218 +
1219 +       con |= S3C2440_SDICON_SDRESET;
1220 +
1221 +       writel(con, host->base + S3C2410_SDICON);
1222 +}
1223 +
1224 +static int s3cmci_get_ro(struct mmc_host *mmc)
1225 +{
1226 +       struct s3cmci_host *host = mmc_priv(mmc);
1227 +
1228 +       if (host->pdata->gpio_wprotect == 0)
1229 +               return 0;
1230 +
1231 +       return s3c2410_gpio_getpin(host->pdata->gpio_wprotect);
1232 +}
1233 +
1234 +static void s3cmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
1235 +{
1236 +       struct s3cmci_host *host = mmc_priv(mmc);
1237 +
1238 +       if (enable)
1239 +               enable_imask(host, S3C2410_SDIIMSK_SDIOIRQ);
1240 +       else
1241 +               disable_imask(host, S3C2410_SDIIMSK_SDIOIRQ);
1242 +}
1243 +
1244 +static struct mmc_host_ops s3cmci_ops = {
1245 +       .request        = s3cmci_request,
1246 +       .set_ios        = s3cmci_set_ios,
1247 +       .get_ro         = s3cmci_get_ro,
1248 +       .enable_sdio_irq = s3cmci_enable_sdio_irq,
1249 +};
1250 +
1251 +static struct s3c24xx_mci_pdata s3cmci_def_pdata = {
1252 +       .do_dma         = 0,
1253 +       .gpio_detect    = 0,
1254 +       .set_power      = NULL,
1255 +       .ocr_avail      = MMC_VDD_32_33,
1256 +};
1257 +
1258 +static int s3cmci_probe(struct platform_device *pdev, int is2440)
1259 +{
1260 +       struct mmc_host         *mmc;
1261 +       struct s3cmci_host      *host;
1262 +
1263 +       int ret;
1264 +
1265 +       mmc = mmc_alloc_host(sizeof(struct s3cmci_host), &pdev->dev);
1266 +       if (!mmc) {
1267 +               ret = -ENOMEM;
1268 +               goto probe_out;
1269 +       }
1270 +
1271 +       host = mmc_priv(mmc);
1272 +       host->mmc       = mmc;
1273 +       host->pdev      = pdev;
1274 +
1275 +       host->pdata = pdev->dev.platform_data;
1276 +       if (!host->pdata) {
1277 +               pdev->dev.platform_data = &s3cmci_def_pdata;
1278 +               host->pdata = &s3cmci_def_pdata;
1279 +       }
1280 +
1281 +       spin_lock_init(&host->complete_lock);
1282 +       tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host);
1283 +       if (is2440) {
1284 +               host->is2440    = 1;
1285 +               host->sdiimsk   = S3C2440_SDIIMSK;
1286 +               host->sdidata   = S3C2440_SDIDATA;
1287 +               host->sdidata_b = S3C2440_SDIDATA_BYTE;
1288 +               host->clk_div   = 1;
1289 +       } else {
1290 +               host->is2440    = 0;
1291 +               host->sdiimsk   = S3C2410_SDIIMSK;
1292 +               host->sdidata   = S3C2410_SDIDATA;
1293 +               host->sdidata_b = S3C2410_SDIDATA_BYTE;
1294 +               host->clk_div   = 2;
1295 +       }
1296 +       host->dodma             = host->pdata->do_dma;
1297 +       host->complete_what     = COMPLETION_NONE;
1298 +       host->pio_active        = XFER_NONE;
1299 +
1300 +       host->dma               = DMACH_SDI;
1301 +       host->irq_cd = s3c2410_gpio_getirq(host->pdata->gpio_detect);
1302 +       s3c2410_gpio_cfgpin(host->pdata->gpio_detect, S3C2410_GPIO_IRQ);
1303 +
1304 +       host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1305 +       if (!host->mem) {
1306 +               dev_err(&pdev->dev,
1307 +                       "failed to get io memory region resouce.\n");
1308 +
1309 +               ret = -ENOENT;
1310 +               goto probe_free_host;
1311 +       }
1312 +
1313 +       host->mem = request_mem_region(host->mem->start,
1314 +               RESSIZE(host->mem), pdev->name);
1315 +
1316 +       if (!host->mem) {
1317 +               dev_err(&pdev->dev, "failed to request io memory region.\n");
1318 +               ret = -ENOENT;
1319 +               goto probe_free_host;
1320 +       }
1321 +
1322 +       host->base = ioremap(host->mem->start, RESSIZE(host->mem));
1323 +       if (host->base == 0) {
1324 +               dev_err(&pdev->dev, "failed to ioremap() io memory region.\n");
1325 +               ret = -EINVAL;
1326 +               goto probe_free_mem_region;
1327 +       }
1328 +
1329 +       host->irq = platform_get_irq(pdev, 0);
1330 +       if (host->irq == 0) {
1331 +               dev_err(&pdev->dev, "failed to get interrupt resouce.\n");
1332 +               ret = -EINVAL;
1333 +               goto probe_iounmap;
1334 +       }
1335 +
1336 +       if (request_irq(host->irq, s3cmci_irq, 0, DRIVER_NAME, host)) {
1337 +               dev_err(&pdev->dev, "failed to request mci interrupt.\n");
1338 +               ret = -ENOENT;
1339 +               goto probe_iounmap;
1340 +       }
1341 +
1342 +       disable_irq(host->irq);
1343 +
1344 +       s3c2410_gpio_cfgpin(host->pdata->gpio_detect, S3C2410_GPIO_IRQ);
1345 +       set_irq_type(host->irq_cd, IRQT_BOTHEDGE);
1346 +
1347 +       if (request_irq(host->irq_cd, s3cmci_irq_cd, 0, DRIVER_NAME, host)) {
1348 +               dev_err(&pdev->dev,
1349 +                       "failed to request card detect interrupt.\n");
1350 +
1351 +               ret = -ENOENT;
1352 +               goto probe_free_irq;
1353 +       }
1354 +
1355 +       if (host->pdata->gpio_wprotect)
1356 +               s3c2410_gpio_cfgpin(host->pdata->gpio_wprotect,
1357 +                                   S3C2410_GPIO_INPUT);
1358 +
1359 +       if (s3c2410_dma_request(host->dma, &s3cmci_dma_client, NULL)) {
1360 +               dev_err(&pdev->dev, "unable to get DMA channel.\n");
1361 +               ret = -EBUSY;
1362 +               goto probe_free_irq_cd;
1363 +       }
1364 +
1365 +       host->clk = clk_get(&pdev->dev, "sdi");
1366 +       if (IS_ERR(host->clk)) {
1367 +               dev_err(&pdev->dev, "failed to find clock source.\n");
1368 +               ret = PTR_ERR(host->clk);
1369 +               host->clk = NULL;
1370 +               goto probe_free_host;
1371 +       }
1372 +
1373 +       ret = clk_enable(host->clk);
1374 +       if (ret) {
1375 +               dev_err(&pdev->dev, "failed to enable clock source.\n");
1376 +               goto clk_free;
1377 +       }
1378 +
1379 +       host->clk_rate = clk_get_rate(host->clk);
1380 +
1381 +       mmc->ops        = &s3cmci_ops;
1382 +       mmc->ocr_avail  = host->pdata->ocr_avail;
1383 +       mmc->caps       = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
1384 +       mmc->f_min      = host->clk_rate / (host->clk_div * 256);
1385 +       mmc->f_max      = host->clk_rate / host->clk_div;
1386 +
1387 +       mmc->max_blk_count      = 4095;
1388 +       mmc->max_blk_size       = 4095;
1389 +       mmc->max_req_size       = 4095 * 512;
1390 +       mmc->max_seg_size       = mmc->max_req_size;
1391 +
1392 +       mmc->max_phys_segs      = 128;
1393 +       mmc->max_hw_segs        = 128;
1394 +
1395 +       dbg(host, dbg_debug, "probe: mode:%s mapped mci_base:%p irq:%u "
1396 +           "irq_cd:%u dma:%u.\n", (host->is2440?"2440":""),
1397 +           host->base, host->irq, host->irq_cd, host->dma);
1398 +
1399 +       ret = mmc_add_host(mmc);
1400 +       if (ret) {
1401 +               dev_err(&pdev->dev, "failed to add mmc host.\n");
1402 +               goto free_dmabuf;
1403 +       }
1404 +
1405 +       platform_set_drvdata(pdev, mmc);
1406 +
1407 +       dev_info(&pdev->dev, "initialisation done.\n");
1408 +       return 0;
1409 +
1410 + free_dmabuf:
1411 +       clk_disable(host->clk);
1412 +
1413 + clk_free:
1414 +       clk_put(host->clk);
1415 +
1416 + probe_free_irq_cd:
1417 +       free_irq(host->irq_cd, host);
1418 +
1419 + probe_free_irq:
1420 +       free_irq(host->irq, host);
1421 +
1422 + probe_iounmap:
1423 +       iounmap(host->base);
1424 +
1425 + probe_free_mem_region:
1426 +       release_mem_region(host->mem->start, RESSIZE(host->mem));
1427 +
1428 + probe_free_host:
1429 +       mmc_free_host(mmc);
1430 + probe_out:
1431 +       return ret;
1432 +}
1433 +
1434 +static int s3cmci_remove(struct platform_device *pdev)
1435 +{
1436 +       struct mmc_host         *mmc  = platform_get_drvdata(pdev);
1437 +       struct s3cmci_host      *host = mmc_priv(mmc);
1438 +
1439 +       mmc_remove_host(mmc);
1440 +       clk_disable(host->clk);
1441 +       clk_put(host->clk);
1442 +       s3c2410_dma_free(host->dma, &s3cmci_dma_client);
1443 +       free_irq(host->irq_cd, host);
1444 +       free_irq(host->irq, host);
1445 +       iounmap(host->base);
1446 +       release_mem_region(host->mem->start, RESSIZE(host->mem));
1447 +       mmc_free_host(mmc);
1448 +
1449 +       return 0;
1450 +}
1451 +
1452 +static int s3cmci_probe_2410(struct platform_device *dev)
1453 +{
1454 +       return s3cmci_probe(dev, 0);
1455 +}
1456 +
1457 +static int s3cmci_probe_2412(struct platform_device *dev)
1458 +{
1459 +       return s3cmci_probe(dev, 1);
1460 +}
1461 +
1462 +static int s3cmci_probe_2440(struct platform_device *dev)
1463 +{
1464 +       return s3cmci_probe(dev, 1);
1465 +}
1466 +
1467 +#ifdef CONFIG_PM
1468 +
1469 +static int s3cmci_suspend(struct platform_device *dev, pm_message_t state)
1470 +{
1471 +       struct mmc_host *mmc = platform_get_drvdata(dev);
1472 +
1473 +       return  mmc_suspend_host(mmc, state);
1474 +}
1475 +
1476 +static int s3cmci_resume(struct platform_device *dev)
1477 +{
1478 +       struct mmc_host *mmc = platform_get_drvdata(dev);
1479 +
1480 +       return mmc_resume_host(mmc);
1481 +}
1482 +
1483 +#else /* CONFIG_PM */
1484 +#define s3cmci_suspend NULL
1485 +#define s3cmci_resume NULL
1486 +#endif /* CONFIG_PM */
1487 +
1488 +
1489 +static struct platform_driver s3cmci_driver_2410 = {
1490 +       .driver.name    = "s3c2410-sdi",
1491 +       .probe          = s3cmci_probe_2410,
1492 +       .remove         = s3cmci_remove,
1493 +       .suspend        = s3cmci_suspend,
1494 +       .resume         = s3cmci_resume,
1495 +};
1496 +
1497 +static struct platform_driver s3cmci_driver_2412 = {
1498 +       .driver.name    = "s3c2412-sdi",
1499 +       .probe          = s3cmci_probe_2412,
1500 +       .remove         = s3cmci_remove,
1501 +       .suspend        = s3cmci_suspend,
1502 +       .resume         = s3cmci_resume,
1503 +};
1504 +
1505 +static struct platform_driver s3cmci_driver_2440 = {
1506 +       .driver.name    = "s3c2440-sdi",
1507 +       .probe          = s3cmci_probe_2440,
1508 +       .remove         = s3cmci_remove,
1509 +       .suspend        = s3cmci_suspend,
1510 +       .resume         = s3cmci_resume,
1511 +};
1512 +
1513 +
1514 +static int __init s3cmci_init(void)
1515 +{
1516 +       platform_driver_register(&s3cmci_driver_2410);
1517 +       platform_driver_register(&s3cmci_driver_2412);
1518 +       platform_driver_register(&s3cmci_driver_2440);
1519 +       return 0;
1520 +}
1521 +
1522 +static void __exit s3cmci_exit(void)
1523 +{
1524 +       platform_driver_unregister(&s3cmci_driver_2410);
1525 +       platform_driver_unregister(&s3cmci_driver_2412);
1526 +       platform_driver_unregister(&s3cmci_driver_2440);
1527 +}
1528 +
1529 +module_init(s3cmci_init);
1530 +module_exit(s3cmci_exit);
1531 +
1532 +MODULE_DESCRIPTION("Samsung S3C MMC/SD Card Interface driver");
1533 +MODULE_LICENSE("GPL");
1534 +MODULE_AUTHOR("Thomas Kleffel <tk@maintech.de>");
1535 diff --git a/drivers/mmc/host/s3cmci.h b/drivers/mmc/host/s3cmci.h
1536 new file mode 100644
1537 index 0000000..9644b45
1538 --- /dev/null
1539 +++ b/drivers/mmc/host/s3cmci.h
1540 @@ -0,0 +1,69 @@
1541 +/*
1542 + *  linux/drivers/mmc/s3cmci.h - Samsung S3C MCI driver
1543 + *
1544 + *  Copyright (C) 2004-2006 Thomas Kleffel, All Rights Reserved.
1545 + *
1546 + * This program is free software; you can redistribute it and/or modify
1547 + * it under the terms of the GNU General Public License version 2 as
1548 + * published by the Free Software Foundation.
1549 + */
1550 +
1551 +enum s3cmci_waitfor {
1552 +       COMPLETION_NONE,
1553 +       COMPLETION_FINALIZE,
1554 +       COMPLETION_CMDSENT,
1555 +       COMPLETION_RSPFIN,
1556 +       COMPLETION_XFERFINISH,
1557 +       COMPLETION_XFERFINISH_RSPFIN,
1558 +};
1559 +
1560 +struct s3cmci_host {
1561 +       struct platform_device  *pdev;
1562 +       struct s3c24xx_mci_pdata *pdata;
1563 +       struct mmc_host         *mmc;
1564 +       struct resource         *mem;
1565 +       struct clk              *clk;
1566 +       void __iomem            *base;
1567 +       int                     irq;
1568 +       int                     irq_cd;
1569 +       int                     dma;
1570 +
1571 +       unsigned long           clk_rate;
1572 +       unsigned long           clk_div;
1573 +       unsigned long           real_rate;
1574 +       u8                      prescaler;
1575 +
1576 +       int                     is2440;
1577 +       unsigned                sdiimsk;
1578 +       unsigned                sdidata;
1579 +       unsigned                sdidata_b;
1580 +       int                     dodma;
1581 +
1582 +       int                     dmatogo;
1583 +
1584 +       struct mmc_request      *mrq;
1585 +       int                     cmd_is_stop;
1586 +
1587 +       spinlock_t              complete_lock;
1588 +       enum s3cmci_waitfor     complete_what;
1589 +
1590 +       int                     dma_complete;
1591 +
1592 +       u32                     pio_sgptr;
1593 +       u32                     pio_bytes;
1594 +       u32                     pio_count;
1595 +       u8                      *pio_ptr;
1596 +#define XFER_NONE 0
1597 +#define XFER_READ 1
1598 +#define XFER_WRITE 2
1599 +       u32                     pio_active;
1600 +
1601 +       int                     bus_width;
1602 +
1603 +       char                    dbgmsg_cmd[301];
1604 +       char                    dbgmsg_dat[301];
1605 +       char                    *status;
1606 +
1607 +       unsigned int            ccnt, dcnt;
1608 +       struct tasklet_struct   pio_tasklet;
1609 +};
1610 diff --git a/include/asm-arm/arch-s3c2410/mci.h b/include/asm-arm/arch-s3c2410/mci.h
1611 new file mode 100644
1612 index 0000000..24e6cd1
1613 --- /dev/null
1614 +++ b/include/asm-arm/arch-s3c2410/mci.h
1615 @@ -0,0 +1,13 @@
1616 +#ifndef _ARCH_MCI_H
1617 +#define _ARCH_MCI_H
1618 +
1619 +struct s3c24xx_mci_pdata {
1620 +       unsigned int    gpio_detect;
1621 +       unsigned int    gpio_wprotect;
1622 +       unsigned long   ocr_avail;
1623 +       unsigned int    do_dma;
1624 +       void            (*set_power)(unsigned char power_mode,
1625 +                                    unsigned short vdd);
1626 +};
1627 +
1628 +#endif /* _ARCH_NCI_H */
1629 diff --git a/include/asm-arm/arch-s3c2410/regs-sdi.h b/include/asm-arm/arch-s3c2410/regs-sdi.h
1630 index bb9d30b..4bb1ec5 100644
1631 --- a/include/asm-arm/arch-s3c2410/regs-sdi.h
1632 +++ b/include/asm-arm/arch-s3c2410/regs-sdi.h
1633 @@ -28,9 +28,17 @@
1634  #define S3C2410_SDIDCNT               (0x30)
1635  #define S3C2410_SDIDSTA               (0x34)
1636  #define S3C2410_SDIFSTA               (0x38)
1637 +
1638  #define S3C2410_SDIDATA               (0x3C)
1639 +#define S3C2410_SDIDATA_BYTE          (0x3C)
1640  #define S3C2410_SDIIMSK               (0x40)
1641  
1642 +#define S3C2440_SDIDATA               (0x40)
1643 +#define S3C2440_SDIDATA_BYTE          (0x48)
1644 +#define S3C2440_SDIIMSK               (0x3C)
1645 +
1646 +#define S3C2440_SDICON_SDRESET        (1<<8)
1647 +#define S3C2440_SDICON_MMCCLOCK       (1<<5)
1648  #define S3C2410_SDICON_BYTEORDER      (1<<4)
1649  #define S3C2410_SDICON_SDIOIRQ        (1<<3)
1650  #define S3C2410_SDICON_RWAITEN        (1<<2)
1651 @@ -42,7 +50,8 @@
1652  #define S3C2410_SDICMDCON_LONGRSP     (1<<10)
1653  #define S3C2410_SDICMDCON_WAITRSP     (1<<9)
1654  #define S3C2410_SDICMDCON_CMDSTART    (1<<8)
1655 -#define S3C2410_SDICMDCON_INDEX       (0xff)
1656 +#define S3C2410_SDICMDCON_SENDERHOST  (1<<6)
1657 +#define S3C2410_SDICMDCON_INDEX       (0x3f)
1658  
1659  #define S3C2410_SDICMDSTAT_CRCFAIL    (1<<12)
1660  #define S3C2410_SDICMDSTAT_CMDSENT    (1<<11)
1661 @@ -51,6 +60,9 @@
1662  #define S3C2410_SDICMDSTAT_XFERING    (1<<8)
1663  #define S3C2410_SDICMDSTAT_INDEX      (0xff)
1664  
1665 +#define S3C2440_SDIDCON_DS_BYTE       (0<<22)
1666 +#define S3C2440_SDIDCON_DS_HALFWORD   (1<<22)
1667 +#define S3C2440_SDIDCON_DS_WORD       (2<<22)
1668  #define S3C2410_SDIDCON_IRQPERIOD     (1<<21)
1669  #define S3C2410_SDIDCON_TXAFTERRESP   (1<<20)
1670  #define S3C2410_SDIDCON_RXAFTERCMD    (1<<19)
1671 @@ -59,6 +71,7 @@
1672  #define S3C2410_SDIDCON_WIDEBUS       (1<<16)
1673  #define S3C2410_SDIDCON_DMAEN         (1<<15)
1674  #define S3C2410_SDIDCON_STOP          (1<<14)
1675 +#define S3C2440_SDIDCON_DATSTART      (1<<14)
1676  #define S3C2410_SDIDCON_DATMODE              (3<<12)
1677  #define S3C2410_SDIDCON_BLKNUM        (0x7ff)
1678  
1679 @@ -68,6 +81,7 @@
1680  #define S3C2410_SDIDCON_XFER_RXSTART  (2<<12)
1681  #define S3C2410_SDIDCON_XFER_TXSTART  (3<<12)
1682  
1683 +#define S3C2410_SDIDCON_BLKNUM_MASK   (0xFFF)
1684  #define S3C2410_SDIDCNT_BLKNUM_SHIFT  (12)
1685  
1686  #define S3C2410_SDIDSTA_RDYWAITREQ    (1<<10)
1687 @@ -82,10 +96,12 @@
1688  #define S3C2410_SDIDSTA_TXDATAON      (1<<1)
1689  #define S3C2410_SDIDSTA_RXDATAON      (1<<0)
1690  
1691 +#define S3C2440_SDIFSTA_FIFORESET      (1<<16)
1692 +#define S3C2440_SDIFSTA_FIFOFAIL       (3<<14)  /* 3 is correct (2 bits) */
1693  #define S3C2410_SDIFSTA_TFDET          (1<<13)
1694  #define S3C2410_SDIFSTA_RFDET          (1<<12)
1695 -#define S3C2410_SDIFSTA_TXHALF         (1<<11)
1696 -#define S3C2410_SDIFSTA_TXEMPTY        (1<<10)
1697 +#define S3C2410_SDIFSTA_TFHALF         (1<<11)
1698 +#define S3C2410_SDIFSTA_TFEMPTY        (1<<10)
1699  #define S3C2410_SDIFSTA_RFLAST         (1<<9)
1700  #define S3C2410_SDIFSTA_RFFULL         (1<<8)
1701  #define S3C2410_SDIFSTA_RFHALF         (1<<7)
1702 -- 
1703 1.5.6.3
1704