All of lore.kernel.org
 help / color / mirror / Atom feed
* [patch v2 00/16] S3C24XX SD/MMC driver
@ 2008-06-16 14:34 Ben Dooks
  2008-06-16 14:34 ` [patch v2 01/16] MMC: S3C24XX MMC/SD driver Ben Dooks
                   ` (16 more replies)
  0 siblings, 17 replies; 19+ messages in thread
From: Ben Dooks @ 2008-06-16 14:34 UTC (permalink / raw)
  To: linux-kernel; +Cc: drzeus-mmc

Updated SD/MMC driver patches for the S3C24XX.

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [patch v2 01/16] MMC: S3C24XX MMC/SD driver.
  2008-06-16 14:34 [patch v2 00/16] S3C24XX SD/MMC driver Ben Dooks
@ 2008-06-16 14:34 ` Ben Dooks
  2008-06-16 14:34 ` [patch v2 02/16] MMC: S3C24XX: Fix the checkpatch.pl errors in the s3cmci driver Ben Dooks
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Ben Dooks @ 2008-06-16 14:34 UTC (permalink / raw)
  To: linux-kernel; +Cc: drzeus-mmc, Ben Dooks

[-- Attachment #1: thirdparty/openmoko-mci/s3c_mci.patch --]
[-- Type: text/plain, Size: 39953 bytes --]

From: Thomas Kleffel <tk@maintech.de>

This is the latest S3C MMC/SD driver by Thomas Kleffel

Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Index: linux-2.6.26-rc5-q/include/asm-arm/arch-s3c2410/regs-sdi.h
===================================================================
--- linux-2.6.26-rc5-q.orig/include/asm-arm/arch-s3c2410/regs-sdi.h	2008-05-13 10:13:29.000000000 +0100
+++ linux-2.6.26-rc5-q/include/asm-arm/arch-s3c2410/regs-sdi.h	2008-06-06 15:08:32.000000000 +0100
@@ -28,9 +28,15 @@
 #define S3C2410_SDIDCNT               (0x30)
 #define S3C2410_SDIDSTA               (0x34)
 #define S3C2410_SDIFSTA               (0x38)
+
 #define S3C2410_SDIDATA               (0x3C)
 #define S3C2410_SDIIMSK               (0x40)
 
+#define S3C2440_SDIDATA               (0x40)
+#define S3C2440_SDIIMSK               (0x3C)
+
+#define S3C2440_SDICON_SDRESET        (1<<8)
+#define S3C2440_SDICON_MMCCLOCK       (1<<5)
 #define S3C2410_SDICON_BYTEORDER      (1<<4)
 #define S3C2410_SDICON_SDIOIRQ        (1<<3)
 #define S3C2410_SDICON_RWAITEN        (1<<2)
@@ -42,7 +48,8 @@
 #define S3C2410_SDICMDCON_LONGRSP     (1<<10)
 #define S3C2410_SDICMDCON_WAITRSP     (1<<9)
 #define S3C2410_SDICMDCON_CMDSTART    (1<<8)
-#define S3C2410_SDICMDCON_INDEX       (0xff)
+#define S3C2410_SDICMDCON_SENDERHOST  (1<<6)
+#define S3C2410_SDICMDCON_INDEX       (0x3f)
 
 #define S3C2410_SDICMDSTAT_CRCFAIL    (1<<12)
 #define S3C2410_SDICMDSTAT_CMDSENT    (1<<11)
@@ -51,6 +58,9 @@
 #define S3C2410_SDICMDSTAT_XFERING    (1<<8)
 #define S3C2410_SDICMDSTAT_INDEX      (0xff)
 
+#define S3C2440_SDIDCON_DS_BYTE       (0<<22)
+#define S3C2440_SDIDCON_DS_HALFWORD   (1<<22)
+#define S3C2440_SDIDCON_DS_WORD       (2<<22)
 #define S3C2410_SDIDCON_IRQPERIOD     (1<<21)
 #define S3C2410_SDIDCON_TXAFTERRESP   (1<<20)
 #define S3C2410_SDIDCON_RXAFTERCMD    (1<<19)
@@ -59,6 +69,7 @@
 #define S3C2410_SDIDCON_WIDEBUS       (1<<16)
 #define S3C2410_SDIDCON_DMAEN         (1<<15)
 #define S3C2410_SDIDCON_STOP          (1<<14)
+#define S3C2440_SDIDCON_DATSTART      (1<<14)
 #define S3C2410_SDIDCON_DATMODE	      (3<<12)
 #define S3C2410_SDIDCON_BLKNUM        (0x7ff)
 
@@ -68,6 +79,7 @@
 #define S3C2410_SDIDCON_XFER_RXSTART  (2<<12)
 #define S3C2410_SDIDCON_XFER_TXSTART  (3<<12)
 
+#define S3C2410_SDIDCON_BLKNUM_MASK   (0xFFF)
 #define S3C2410_SDIDCNT_BLKNUM_SHIFT  (12)
 
 #define S3C2410_SDIDSTA_RDYWAITREQ    (1<<10)
@@ -82,10 +94,12 @@
 #define S3C2410_SDIDSTA_TXDATAON      (1<<1)
 #define S3C2410_SDIDSTA_RXDATAON      (1<<0)
 
+#define S3C2440_SDIFSTA_FIFORESET      (1<<16)
+#define S3C2440_SDIFSTA_FIFOFAIL       (3<<14)  /* 3 is correct (2 bits) */
 #define S3C2410_SDIFSTA_TFDET          (1<<13)
 #define S3C2410_SDIFSTA_RFDET          (1<<12)
-#define S3C2410_SDIFSTA_TXHALF         (1<<11)
-#define S3C2410_SDIFSTA_TXEMPTY        (1<<10)
+#define S3C2410_SDIFSTA_TFHALF         (1<<11)
+#define S3C2410_SDIFSTA_TFEMPTY        (1<<10)
 #define S3C2410_SDIFSTA_RFLAST         (1<<9)
 #define S3C2410_SDIFSTA_RFFULL         (1<<8)
 #define S3C2410_SDIFSTA_RFHALF         (1<<7)
Index: linux-2.6.26-rc5-q/drivers/mmc/host/s3cmci.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.26-rc5-q/drivers/mmc/host/s3cmci.c	2008-06-06 15:31:39.000000000 +0100
@@ -0,0 +1,1337 @@
+/*
+ *  linux/drivers/mmc/s3cmci.h - Samsung S3C MCI driver
+ *
+ *  Copyright (C) 2004-2006 maintech GmbH, Thomas Kleffel <tk@maintech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+
+#include <asm/dma.h>
+#include <asm/dma-mapping.h>
+
+#include <asm/io.h>
+#include <asm/arch/regs-sdi.h>
+#include <asm/arch/regs-gpio.h>
+
+#include "s3cmci.h"
+
+#define DRIVER_NAME "s3c-mci"
+
+enum dbg_channels {
+	dbg_err   = (1 << 0),
+	dbg_debug = (1 << 1),
+	dbg_info  = (1 << 2),
+	dbg_irq   = (1 << 3),
+	dbg_sg    = (1 << 4),
+	dbg_dma   = (1 << 5),
+	dbg_pio   = (1 << 6),
+	dbg_fail  = (1 << 7),
+	dbg_conf  = (1 << 8),
+};
+
+static const int dbgmap_err   = dbg_err | dbg_fail;
+static const int dbgmap_info  = dbg_info | dbg_conf;
+static const int dbgmap_debug = dbg_debug;
+
+#define dbg(host, channels, args...)		 \
+	if (dbgmap_err & channels) 		 \
+		dev_err(&host->pdev->dev, args); \
+	else if (dbgmap_info & channels)	 \
+		dev_info(&host->pdev->dev, args);\
+	else if (dbgmap_debug & channels)	 \
+		dev_dbg(&host->pdev->dev, args);
+
+#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
+
+static struct s3c2410_dma_client s3cmci_dma_client = {
+	.name		= "s3c-mci",
+};
+
+static void finalize_request(struct s3cmci_host *host);
+static void s3cmci_send_request(struct mmc_host *mmc);
+static void s3cmci_reset(struct s3cmci_host *host);
+
+#ifdef CONFIG_MMC_DEBUG
+
+static inline void dbg_dumpregs(struct s3cmci_host *host, char *prefix)
+{
+	u32 con, pre, cmdarg, cmdcon, cmdsta, r0, r1, r2, r3, timer, bsize;
+	u32 datcon, datcnt, datsta, fsta, imask;
+
+	con 	= readl(host->base + S3C2410_SDICON);
+	pre 	= readl(host->base + S3C2410_SDIPRE);
+	cmdarg 	= readl(host->base + S3C2410_SDICMDARG);
+	cmdcon 	= readl(host->base + S3C2410_SDICMDCON);
+	cmdsta 	= readl(host->base + S3C2410_SDICMDSTAT);
+	r0 	= readl(host->base + S3C2410_SDIRSP0);
+	r1 	= readl(host->base + S3C2410_SDIRSP1);
+	r2 	= readl(host->base + S3C2410_SDIRSP2);
+	r3 	= readl(host->base + S3C2410_SDIRSP3);
+	timer 	= readl(host->base + S3C2410_SDITIMER);
+	bsize 	= readl(host->base + S3C2410_SDIBSIZE);
+	datcon 	= readl(host->base + S3C2410_SDIDCON);
+	datcnt 	= readl(host->base + S3C2410_SDIDCNT);
+	datsta 	= readl(host->base + S3C2410_SDIDSTA);
+	fsta 	= readl(host->base + S3C2410_SDIFSTA);
+	imask   = readl(host->base + host->sdiimsk);
+
+	dbg(host, dbg_debug, "%s  CON:[%08x]  PRE:[%08x]  TMR:[%08x]\n",
+				prefix, con, pre, timer);
+
+	dbg(host, dbg_debug, "%s CCON:[%08x] CARG:[%08x] CSTA:[%08x]\n",
+				prefix, cmdcon, cmdarg, cmdsta);
+
+	dbg(host, dbg_debug, "%s DCON:[%08x] FSTA:[%08x]"
+			       " DSTA:[%08x] DCNT:[%08x]\n",
+				prefix, datcon, fsta, datsta, datcnt);
+
+	dbg(host, dbg_debug, "%s   R0:[%08x]   R1:[%08x]"
+			       "   R2:[%08x]   R3:[%08x]\n",
+				prefix, r0, r1, r2, r3);
+}
+
+static void prepare_dbgmsg(struct s3cmci_host *host, struct mmc_command *cmd,
+								int stop)
+{
+ 	snprintf(host->dbgmsg_cmd, 300,
+		"#%u%s op:%i arg:0x%08x flags:0x08%x retries:%u",
+		host->ccnt, (stop?" (STOP)":""),
+		cmd->opcode, cmd->arg, cmd->flags, cmd->retries);
+
+	if (cmd->data) {
+		snprintf(host->dbgmsg_dat, 300,
+			"#%u bsize:%u blocks:%u bytes:%u",
+			host->dcnt, cmd->data->blksz,
+			cmd->data->blocks,
+			cmd->data->blocks * cmd->data->blksz);
+	} else {
+		host->dbgmsg_dat[0] = '\0';
+	}
+}
+
+static void dbg_dumpcmd(struct s3cmci_host *host, struct mmc_command *cmd,
+								int fail)
+{
+	unsigned int dbglvl = fail?dbg_fail:dbg_debug;
+
+	if (!cmd)
+		return;
+
+	if (cmd->error == MMC_ERR_NONE) {
+		dbg(host, dbglvl, "CMD[OK] %s R0:0x%08x\n",
+			host->dbgmsg_cmd, cmd->resp[0]);
+	} else {
+		dbg(host, dbglvl, "CMD[ERR %i] %s Status:%s\n",
+			cmd->error, host->dbgmsg_cmd, host->status);
+	}
+
+	if (!cmd->data)
+		return;
+
+	if (cmd->data->error == MMC_ERR_NONE) {
+		dbg(host, dbglvl, "DAT[OK] %s\n", host->dbgmsg_dat);
+	} else {
+		dbg(host, dbglvl, "DAT[ERR %i] %s DCNT:0x%08x\n",
+			cmd->data->error, host->dbgmsg_dat,
+			readl(host->base + S3C2410_SDIDCNT));
+	}
+}
+#endif
+
+static inline u32 enable_imask(struct s3cmci_host *host, u32 imask)
+{
+	u32 newmask;
+
+	newmask = readl(host->base + host->sdiimsk);
+	newmask|= imask;
+
+	writel(newmask, host->base + host->sdiimsk);
+
+	return newmask;
+}
+
+static inline u32 disable_imask(struct s3cmci_host *host, u32 imask)
+{
+	u32 newmask;
+
+	newmask = readl(host->base + host->sdiimsk);
+	newmask&= ~imask;
+
+	writel(newmask, host->base + host->sdiimsk);
+
+	return newmask;
+}
+
+static inline void clear_imask(struct s3cmci_host *host)
+{
+	writel(0, host->base + host->sdiimsk);
+}
+
+static inline int get_data_buffer(struct s3cmci_host *host,
+			volatile u32 *words, volatile u32 **pointer)
+{
+	struct scatterlist *sg;
+
+	if (host->pio_active == XFER_NONE)
+		return -EINVAL;
+
+	if ((!host->mrq) || (!host->mrq->data))
+		return -EINVAL;
+
+	if (host->pio_sgptr >= host->mrq->data->sg_len) {
+		dbg(host, dbg_debug, "no more buffers (%i/%i)\n",
+		      host->pio_sgptr, host->mrq->data->sg_len);
+		return -EBUSY;
+	}
+	sg = &host->mrq->data->sg[host->pio_sgptr];
+
+	*words	= sg->length >> 2;
+	*pointer= page_address(sg->page) + sg->offset;
+
+	host->pio_sgptr++;
+
+	dbg(host, dbg_sg, "new buffer (%i/%i)\n",
+	      host->pio_sgptr, host->mrq->data->sg_len);
+
+	return 0;
+}
+
+#define FIFO_FILL(host) ((readl(host->base + S3C2410_SDIFSTA) & S3C2410_SDIFSTA_COUNTMASK) >> 2)
+#define FIFO_FREE(host) ((63 - (readl(host->base + S3C2410_SDIFSTA) & S3C2410_SDIFSTA_COUNTMASK)) >> 2)
+
+static inline void do_pio_read(struct s3cmci_host *host)
+{
+	int res;
+	u32 fifo;
+	void __iomem *from_ptr;
+
+	//write real prescaler to host, it might be set slow to fix
+	writel(host->prescaler, host->base + S3C2410_SDIPRE);
+
+	from_ptr = host->base + host->sdidata;
+
+	while ((fifo = FIFO_FILL(host))) {
+		if (!host->pio_words) {
+			res = get_data_buffer(host, &host->pio_words,
+							&host->pio_ptr);
+			if (res) {
+				host->pio_active = XFER_NONE;
+				host->complete_what = COMPLETION_FINALIZE;
+
+				dbg(host, dbg_pio, "pio_read(): "
+					"complete (no more data).\n");
+				return;
+			}
+
+			dbg(host, dbg_pio, "pio_read(): new target: [%i]@[%p]\n",
+			       host->pio_words, host->pio_ptr);
+		}
+
+		dbg(host, dbg_pio, "pio_read(): fifo:[%02i] "
+				   "buffer:[%03i] dcnt:[%08X]\n",
+				   fifo, host->pio_words,
+				   readl(host->base + S3C2410_SDIDCNT));
+
+		if (fifo > host->pio_words)
+			fifo = host->pio_words;
+
+		host->pio_words-= fifo;
+		host->pio_count+= fifo;
+
+		while(fifo--) {
+			*(host->pio_ptr++) = readl(from_ptr);
+		}
+	}
+
+	if (!host->pio_words) {
+		res = get_data_buffer(host, &host->pio_words, &host->pio_ptr);
+		if (res) {
+			dbg(host, dbg_pio, "pio_read(): "
+				"complete (no more buffers).\n");
+			host->pio_active = XFER_NONE;
+			host->complete_what = COMPLETION_FINALIZE;
+
+			return;
+		}
+	}
+
+	enable_imask(host, S3C2410_SDIIMSK_RXFIFOHALF | S3C2410_SDIIMSK_RXFIFOLAST);
+}
+
+static inline void do_pio_write(struct s3cmci_host *host)
+{
+	int res;
+	u32 fifo;
+
+	void __iomem *to_ptr;
+
+	to_ptr = host->base + host->sdidata;
+
+	while ((fifo = FIFO_FREE(host))) {
+		if (!host->pio_words) {
+			res = get_data_buffer(host, &host->pio_words,
+							&host->pio_ptr);
+			if (res) {
+				dbg(host, dbg_pio, "pio_write(): "
+					"complete (no more data).\n");
+				host->pio_active = XFER_NONE;
+
+				return;
+			}
+
+			dbg(host, dbg_pio, "pio_write(): "
+				"new source: [%i]@[%p]\n",
+				host->pio_words, host->pio_ptr);
+
+		}
+
+		if (fifo > host->pio_words)
+			fifo = host->pio_words;
+
+		host->pio_words-= fifo;
+		host->pio_count+= fifo;
+
+		while(fifo--) {
+			writel(*(host->pio_ptr++), to_ptr);
+		}
+	}
+
+	enable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);
+}
+
+static void pio_tasklet(unsigned long data)
+{
+	struct s3cmci_host *host = (struct s3cmci_host *) data;
+
+
+	if (host->pio_active == XFER_WRITE)
+		do_pio_write(host);
+
+	if (host->pio_active == XFER_READ)
+		do_pio_read(host);
+
+	if (host->complete_what == COMPLETION_FINALIZE) {
+		clear_imask(host);
+		if (host->pio_active != XFER_NONE) {
+			dbg(host, dbg_err, "unfinished %s "
+				"- pio_count:[%u] pio_words:[%u]\n",
+				(host->pio_active == XFER_READ)?"read":"write",
+				host->pio_count, host->pio_words);
+
+			host->mrq->data->error = MMC_ERR_DMA;
+		}
+
+		disable_irq(host->irq);
+		finalize_request(host);
+	}
+}
+
+/*
+ * ISR for SDI Interface IRQ
+ * Communication between driver and ISR works as follows:
+ *   host->mrq 			points to current request
+ *   host->complete_what	tells the ISR when the request is considered done
+ *     COMPLETION_CMDSENT	  when the command was sent
+ *     COMPLETION_RSPFIN          when a response was received
+ *     COMPLETION_XFERFINISH	  when the data transfer is finished
+ *     COMPLETION_XFERFINISH_RSPFIN both of the above.
+ *   host->complete_request	is the completion-object the driver waits for
+ *
+ * 1) Driver sets up host->mrq and host->complete_what
+ * 2) Driver prepares the transfer
+ * 3) Driver enables interrupts
+ * 4) Driver starts transfer
+ * 5) Driver waits for host->complete_rquest
+ * 6) ISR checks for request status (errors and success)
+ * 6) ISR sets host->mrq->cmd->error and host->mrq->data->error
+ * 7) ISR completes host->complete_request
+ * 8) ISR disables interrupts
+ * 9) Driver wakes up and takes care of the request
+ *
+ * Note: "->error"-fields are expected to be set to 0 before the request
+ *       was issued by mmc.c - therefore they are only set, when an error
+ *       contition comes up
+ */
+
+static irqreturn_t s3cmci_irq(int irq, void *dev_id)
+{
+	struct s3cmci_host *host;
+	struct mmc_command *cmd;
+	u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt, mci_imsk;
+	u32 mci_cclear, mci_dclear;
+	unsigned long iflags;
+
+	host = (struct s3cmci_host *)dev_id;
+
+	spin_lock_irqsave(&host->complete_lock, iflags);
+
+	mci_csta 	= readl(host->base + S3C2410_SDICMDSTAT);
+	mci_dsta 	= readl(host->base + S3C2410_SDIDSTA);
+	mci_dcnt 	= readl(host->base + S3C2410_SDIDCNT);
+	mci_fsta 	= readl(host->base + S3C2410_SDIFSTA);
+	mci_imsk	= readl(host->base + host->sdiimsk);
+	mci_cclear	= 0;
+	mci_dclear	= 0;
+
+	if ((host->complete_what == COMPLETION_NONE) ||
+			(host->complete_what == COMPLETION_FINALIZE)) {
+		host->status = "nothing to complete";
+		clear_imask(host);
+		goto irq_out;
+	}
+
+	if (!host->mrq) {
+		host->status = "no active mrq";
+		clear_imask(host);
+		goto irq_out;
+	}
+
+	cmd = host->cmd_is_stop?host->mrq->stop:host->mrq->cmd;
+
+	if (!cmd) {
+		host->status = "no active cmd";
+		clear_imask(host);
+		goto irq_out;
+	}
+
+	if (!host->dodma) {
+		if ((host->pio_active == XFER_WRITE) &&
+				(mci_fsta & S3C2410_SDIFSTA_TFDET)) {
+
+			disable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);
+			tasklet_schedule(&host->pio_tasklet);
+			host->status = "pio tx";
+		}
+
+		if ((host->pio_active == XFER_READ) &&
+				(mci_fsta & S3C2410_SDIFSTA_RFDET)) {
+
+			disable_imask(host,
+				S3C2410_SDIIMSK_RXFIFOHALF | S3C2410_SDIIMSK_RXFIFOLAST);
+
+			tasklet_schedule(&host->pio_tasklet);
+			host->status = "pio rx";
+		}
+	}
+
+	if (mci_csta & S3C2410_SDICMDSTAT_CMDTIMEOUT) {
+		cmd->error = MMC_ERR_TIMEOUT;
+		host->status = "error: command timeout";
+		goto fail_transfer;
+	}
+
+	if (mci_csta & S3C2410_SDICMDSTAT_CMDSENT) {
+		if (host->complete_what == COMPLETION_CMDSENT) {
+			host->status = "ok: command sent";
+			goto close_transfer;
+		}
+
+		mci_cclear |= S3C2410_SDICMDSTAT_CMDSENT;
+	}
+
+	if (mci_csta & S3C2410_SDICMDSTAT_CRCFAIL) {
+		if (cmd->flags & MMC_RSP_CRC) {
+			cmd->error = MMC_ERR_BADCRC;
+			host->status = "error: bad command crc";
+			goto fail_transfer;
+		}
+
+		mci_cclear |= S3C2410_SDICMDSTAT_CRCFAIL;
+	}
+
+	if (mci_csta & S3C2410_SDICMDSTAT_RSPFIN) {
+		if (host->complete_what == COMPLETION_RSPFIN) {
+			host->status = "ok: command response received";
+			goto close_transfer;
+		}
+
+		if (host->complete_what == COMPLETION_XFERFINISH_RSPFIN)
+			host->complete_what = COMPLETION_XFERFINISH;
+
+		mci_cclear |= S3C2410_SDICMDSTAT_RSPFIN;
+	}
+
+	/* errors handled after this point are only relevant
+	   when a data transfer is in progress */
+
+	if (!cmd->data)
+		goto clear_status_bits;
+
+	/* Check for FIFO failure */
+	if (host->is2440) {
+		if (mci_fsta & S3C2440_SDIFSTA_FIFOFAIL) {
+			host->mrq->data->error = MMC_ERR_FIFO;
+			host->status = "error: 2440 fifo failure";
+			goto fail_transfer;
+		}
+	} else {
+		if (mci_dsta & S3C2410_SDIDSTA_FIFOFAIL) {
+			cmd->data->error = MMC_ERR_FIFO;
+			host->status = "error:  fifo failure";
+			goto fail_transfer;
+		}
+	}
+
+	if (mci_dsta & S3C2410_SDIDSTA_RXCRCFAIL) {
+		cmd->data->error = MMC_ERR_BADCRC;
+		host->status = "error: bad data crc (outgoing)";
+		goto fail_transfer;
+	}
+
+	if (mci_dsta & S3C2410_SDIDSTA_CRCFAIL) {
+		cmd->data->error = MMC_ERR_BADCRC;
+		host->status = "error: bad data crc (incoming)";
+		goto fail_transfer;
+	}
+
+	if (mci_dsta & S3C2410_SDIDSTA_DATATIMEOUT) {
+		cmd->data->error = MMC_ERR_TIMEOUT;
+		host->status = "error: data timeout";
+		goto fail_transfer;
+	}
+
+	if (mci_dsta & S3C2410_SDIDSTA_XFERFINISH) {
+		if (host->complete_what == COMPLETION_XFERFINISH) {
+			host->status = "ok: data transfer completed";
+			goto close_transfer;
+		}
+
+		if (host->complete_what == COMPLETION_XFERFINISH_RSPFIN) {
+			host->complete_what = COMPLETION_RSPFIN;
+		}
+
+		mci_dclear |= S3C2410_SDIDSTA_XFERFINISH;
+	}
+
+clear_status_bits:
+	writel(mci_cclear, host->base + S3C2410_SDICMDSTAT);
+	writel(mci_dclear, host->base + S3C2410_SDIDSTA);
+
+	goto irq_out;
+
+fail_transfer:
+	host->pio_active = XFER_NONE;
+
+close_transfer:
+	host->complete_what = COMPLETION_FINALIZE;
+
+	clear_imask(host);
+	tasklet_schedule(&host->pio_tasklet);
+
+	goto irq_out;
+
+irq_out:
+	dbg(host, dbg_irq, "csta:0x%08x dsta:0x%08x "
+			   "fsta:0x%08x dcnt:0x%08x status:%s.\n",
+				mci_csta, mci_dsta, mci_fsta,
+				mci_dcnt, host->status);
+
+	spin_unlock_irqrestore(&host->complete_lock, iflags);
+	return IRQ_HANDLED;
+
+}
+
+/*
+ * ISR for the CardDetect Pin
+*/
+
+static irqreturn_t s3cmci_irq_cd(int irq, void *dev_id)
+{
+	struct s3cmci_host *host = (struct s3cmci_host *)dev_id;
+
+	dbg(host, dbg_irq, "card detect\n");
+
+	mmc_detect_change(host->mmc, 500);
+
+	return IRQ_HANDLED;
+}
+
+void s3cmci_dma_done_callback(struct s3c2410_dma_chan *dma_ch, void *buf_id,
+	int size, enum s3c2410_dma_buffresult result)
+{
+	unsigned long iflags;
+	u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt;
+	struct s3cmci_host *host = (struct s3cmci_host *)buf_id;
+
+	mci_csta 	= readl(host->base + S3C2410_SDICMDSTAT);
+	mci_dsta 	= readl(host->base + S3C2410_SDIDSTA);
+	mci_fsta 	= readl(host->base + S3C2410_SDIFSTA);
+	mci_dcnt 	= readl(host->base + S3C2410_SDIDCNT);
+
+	if ((!host->mrq) || (!host->mrq) || (!host->mrq->data))
+		return;
+
+	if (!host->dmatogo)
+		return;
+
+	spin_lock_irqsave(&host->complete_lock, iflags);
+
+	if (result != S3C2410_RES_OK) {
+		dbg(host, dbg_fail, "DMA FAILED: csta=0x%08x dsta=0x%08x "
+			"fsta=0x%08x dcnt:0x%08x result:0x%08x toGo:%u\n",
+			mci_csta, mci_dsta, mci_fsta,
+			mci_dcnt, result, host->dmatogo);
+
+		goto fail_request;
+	}
+
+	host->dmatogo--;
+	if (host->dmatogo) {
+		dbg(host, dbg_dma, "DMA DONE  Size:%i DSTA:[%08x] "
+			"DCNT:[%08x] toGo:%u\n",
+			size, mci_dsta, mci_dcnt, host->dmatogo);
+
+		goto out;
+	}
+
+	dbg(host, dbg_dma, "DMA FINISHED Size:%i DSTA:%08x DCNT:%08x\n",
+		size, mci_dsta, mci_dcnt);
+
+	host->complete_what = COMPLETION_FINALIZE;
+
+out:
+	tasklet_schedule(&host->pio_tasklet);
+	spin_unlock_irqrestore(&host->complete_lock, iflags);
+	return;
+
+
+fail_request:
+	host->mrq->data->error = MMC_ERR_DMA;
+	host->complete_what = COMPLETION_FINALIZE;
+	writel(0, host->base + host->sdiimsk);
+	goto out;
+
+}
+
+static void finalize_request(struct s3cmci_host *host)
+{
+	struct mmc_request *mrq = host->mrq;
+	struct mmc_command *cmd = host->cmd_is_stop?mrq->stop:mrq->cmd;
+	int debug_as_failure = 0;
+
+	if (host->complete_what != COMPLETION_FINALIZE)
+		return;
+
+	if (!mrq)
+		return;
+
+	if (cmd->data && (cmd->error == MMC_ERR_NONE) &&
+		  (cmd->data->error == MMC_ERR_NONE)) {
+
+		if (host->dodma && (!host->dma_complete)) {
+			dbg(host, dbg_dma, "DMA Missing!\n");
+			return;
+		}
+	}
+
+	// Read response
+	cmd->resp[0] = readl(host->base + S3C2410_SDIRSP0);
+	cmd->resp[1] = readl(host->base + S3C2410_SDIRSP1);
+	cmd->resp[2] = readl(host->base + S3C2410_SDIRSP2);
+	cmd->resp[3] = readl(host->base + S3C2410_SDIRSP3);
+
+	// reset clock speed, as it could still be set low for
+	writel(host->prescaler, host->base + S3C2410_SDIPRE);
+
+	if (cmd->error)
+		debug_as_failure = 1;
+
+	if (cmd->data && cmd->data->error)
+		debug_as_failure = 1;
+
+	//if(cmd->flags & MMC_RSP_MAYFAIL) debug_as_failure = 0;
+
+#ifdef CONFIG_MMC_DEBUG
+	dbg_dumpcmd(host, cmd, debug_as_failure);
+#endif
+	//Cleanup controller
+	writel(0, host->base + S3C2410_SDICMDARG);
+	writel(0, host->base + S3C2410_SDIDCON);
+	writel(0, host->base + S3C2410_SDICMDCON);
+	writel(0, host->base + host->sdiimsk);
+
+	if (cmd->data && cmd->error)
+		cmd->data->error = cmd->error;
+
+	if (cmd->data && cmd->data->stop && (!host->cmd_is_stop)) {
+		host->cmd_is_stop = 1;
+		s3cmci_send_request(host->mmc);
+		return;
+	}
+
+	// If we have no data transfer we are finished here
+	if (!mrq->data)
+		goto request_done;
+
+	// Calulate the amout of bytes transfer, but only if there was
+	// no error
+	if (mrq->data->error == MMC_ERR_NONE) {
+		mrq->data->bytes_xfered =
+			(mrq->data->blocks * mrq->data->blksz);
+	} else {
+		mrq->data->bytes_xfered = 0;
+	}
+
+	// If we had an error while transfering data we flush the
+	// DMA channel and the fifo to clear out any garbage
+	if (mrq->data->error != MMC_ERR_NONE) {
+		if (host->dodma)
+			s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
+
+		if (host->is2440) {
+			//Clear failure register and reset fifo
+			writel(S3C2440_SDIFSTA_FIFORESET |
+			       S3C2440_SDIFSTA_FIFOFAIL,
+			       host->base + S3C2410_SDIFSTA);
+		} else {
+			u32 mci_con;
+
+			//reset fifo
+			mci_con = readl(host->base + S3C2410_SDICON);
+			mci_con|= S3C2410_SDICON_FIFORESET;
+
+			writel(mci_con, host->base + S3C2410_SDICON);
+		}
+	}
+
+request_done:
+	host->complete_what = COMPLETION_NONE;
+	host->mrq = NULL;
+	mmc_request_done(host->mmc, mrq);
+}
+
+
+void s3cmci_dma_setup(struct s3cmci_host *host, enum s3c2410_dmasrc source)
+{
+	static int setup_ok = 0;
+	static enum s3c2410_dmasrc last_source = -1;
+
+	if (last_source == source)
+		return;
+
+	last_source = source;
+
+	s3c2410_dma_devconfig(host->dma, source, 3,
+		host->mem->start + host->sdidata);
+
+	if (!setup_ok) {
+		s3c2410_dma_config(host->dma, 4,
+			(S3C2410_DCON_HWTRIG | S3C2410_DCON_CH0_SDI));
+		s3c2410_dma_set_buffdone_fn(host->dma, s3cmci_dma_done_callback);
+		s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART);
+		setup_ok = 1;
+	}
+}
+
+static void s3cmci_send_command(struct s3cmci_host *host,
+					struct mmc_command *cmd)
+{
+	u32 ccon, imsk;
+
+	imsk  = S3C2410_SDIIMSK_CRCSTATUS | S3C2410_SDIIMSK_CMDTIMEOUT |
+		S3C2410_SDIIMSK_RESPONSEND | S3C2410_SDIIMSK_CMDSENT |
+		S3C2410_SDIIMSK_RESPONSECRC;
+
+	enable_imask(host, imsk);
+
+	if (cmd->data) {
+		host->complete_what = COMPLETION_XFERFINISH_RSPFIN;
+	} else if (cmd->flags & MMC_RSP_PRESENT) {
+		host->complete_what = COMPLETION_RSPFIN;
+	} else {
+		host->complete_what = COMPLETION_CMDSENT;
+	}
+
+	writel(cmd->arg, host->base + S3C2410_SDICMDARG);
+
+	ccon = cmd->opcode & S3C2410_SDICMDCON_INDEX;
+	ccon|= S3C2410_SDICMDCON_SENDERHOST | S3C2410_SDICMDCON_CMDSTART;
+
+	if (cmd->flags & MMC_RSP_PRESENT)
+		ccon |= S3C2410_SDICMDCON_WAITRSP;
+
+	if (cmd->flags & MMC_RSP_136)
+		ccon|= S3C2410_SDICMDCON_LONGRSP;
+
+	writel(ccon, host->base + S3C2410_SDICMDCON);
+}
+
+static int s3cmci_setup_data(struct s3cmci_host *host, struct mmc_data *data)
+{
+	u32 dcon, imsk, stoptries=3;
+
+	/* write DCON register */
+
+	if (!data) {
+		writel(0, host->base + S3C2410_SDIDCON);
+		return 0;
+	}
+
+	while(readl(host->base + S3C2410_SDIDSTA) &
+		(S3C2410_SDIDSTA_TXDATAON | S3C2410_SDIDSTA_RXDATAON)) {
+
+		dbg(host, dbg_err,
+			"mci_setup_data() transfer stillin progress.\n");
+
+		writel(0, host->base + S3C2410_SDIDCON);
+		s3cmci_reset(host);
+
+		if (0 == (stoptries--)) {
+#ifdef CONFIG_MMC_DEBUG
+			dbg_dumpregs(host, "DRF");
+#endif
+
+			return -EINVAL;
+		}
+	}
+
+	dcon  = data->blocks & S3C2410_SDIDCON_BLKNUM_MASK;
+
+	if (host->dodma) {
+		dcon |= S3C2410_SDIDCON_DMAEN;
+	}
+
+	if (host->bus_width == MMC_BUS_WIDTH_4) {
+		dcon |= S3C2410_SDIDCON_WIDEBUS;
+	}
+
+	if (!(data->flags & MMC_DATA_STREAM)) {
+		dcon |= S3C2410_SDIDCON_BLOCKMODE;
+	}
+
+	if (data->flags & MMC_DATA_WRITE) {
+		dcon |= S3C2410_SDIDCON_TXAFTERRESP;
+		dcon |= S3C2410_SDIDCON_XFER_TXSTART;
+	}
+
+	if (data->flags & MMC_DATA_READ) {
+		dcon |= S3C2410_SDIDCON_RXAFTERCMD;
+		dcon |= S3C2410_SDIDCON_XFER_RXSTART;
+	}
+
+	if (host->is2440) {
+		dcon |= S3C2440_SDIDCON_DS_WORD;
+		dcon |= S3C2440_SDIDCON_DATSTART;
+	}
+
+	writel(dcon, host->base + S3C2410_SDIDCON);
+
+	/* write BSIZE register */
+
+	writel(data->blksz, host->base + S3C2410_SDIBSIZE);
+
+	/* add to IMASK register */
+	imsk =	S3C2410_SDIIMSK_FIFOFAIL | S3C2410_SDIIMSK_DATACRC |
+		S3C2410_SDIIMSK_DATATIMEOUT | S3C2410_SDIIMSK_DATAFINISH;
+
+	enable_imask(host, imsk);
+
+	/* write TIMER register */
+
+	if (host->is2440) {
+		writel(0x007FFFFF, host->base + S3C2410_SDITIMER);
+	} else {
+		writel(0x0000FFFF, host->base + S3C2410_SDITIMER);
+
+		//FIX: set slow clock to prevent timeouts on read
+		if (data->flags & MMC_DATA_READ) {
+			writel(0xFF, host->base + S3C2410_SDIPRE);
+		}
+	}
+
+	//debug_dump_registers(host, "Data setup:");
+
+	return 0;
+}
+
+static int s3cmci_prepare_pio(struct s3cmci_host *host, struct mmc_data *data)
+{
+	int rw = (data->flags & MMC_DATA_WRITE)?1:0;
+
+	if (rw != ((data->flags & MMC_DATA_READ)?0:1))
+		return -EINVAL;
+
+	host->pio_sgptr = 0;
+	host->pio_words = 0;
+	host->pio_count = 0;
+	host->pio_active = rw?XFER_WRITE:XFER_READ;
+
+	if (rw) {
+		do_pio_write(host);
+		enable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);
+	} else {
+		enable_imask(host, S3C2410_SDIIMSK_RXFIFOHALF
+			| S3C2410_SDIIMSK_RXFIFOLAST);
+	}
+
+	return 0;
+}
+
+static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)
+{
+	int dma_len, i;
+
+	int rw = (data->flags & MMC_DATA_WRITE)?1:0;
+
+	if (rw != ((data->flags & MMC_DATA_READ)?0:1))
+		return -EINVAL;
+
+	s3cmci_dma_setup(host, rw?S3C2410_DMASRC_MEM:S3C2410_DMASRC_HW);
+	s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
+
+	dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+				(rw)?DMA_TO_DEVICE:DMA_FROM_DEVICE);
+
+
+	if (dma_len == 0)
+		return -ENOMEM;
+
+	host->dma_complete = 0;
+	host->dmatogo = dma_len;
+
+	for (i = 0; i < dma_len; i++) {
+		int res;
+
+		dbg(host, dbg_dma, "enqueue %i:%u@%u\n", i,
+			sg_dma_address(&data->sg[i]),
+			sg_dma_len(&data->sg[i]));
+
+		res = s3c2410_dma_enqueue(host->dma, (void *) host,
+				sg_dma_address(&data->sg[i]),
+				sg_dma_len(&data->sg[i]));
+
+		if (res) {
+			s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
+			return -EBUSY;
+		}
+ 	}
+
+	s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_START);
+
+	return 0;
+}
+
+static void s3cmci_send_request(struct mmc_host *mmc)
+{
+	struct s3cmci_host *host = mmc_priv(mmc);
+	struct mmc_request *mrq = host->mrq;
+	struct mmc_command *cmd = host->cmd_is_stop?mrq->stop:mrq->cmd;
+
+	host->ccnt++;
+#ifdef CONFIG_MMC_DEBUG
+	prepare_dbgmsg(host, cmd, host->cmd_is_stop);
+#endif
+	//Clear command, data and fifo status registers
+	//Fifo clear only necessary on 2440, but doesn't hurt on 2410
+	writel(0xFFFFFFFF, host->base + S3C2410_SDICMDSTAT);
+	writel(0xFFFFFFFF, host->base + S3C2410_SDIDSTA);
+	writel(0xFFFFFFFF, host->base + S3C2410_SDIFSTA);
+
+	if (cmd->data) {
+		int res;
+		res = s3cmci_setup_data(host, cmd->data);
+
+		host->dcnt++;
+
+		if (res) {
+			cmd->error = MMC_ERR_DMA;
+			cmd->data->error = MMC_ERR_DMA;
+
+			mmc_request_done(mmc, mrq);
+			return;
+		}
+
+
+		if (host->dodma) {
+			res = s3cmci_prepare_dma(host, cmd->data);
+		} else {
+			res = s3cmci_prepare_pio(host, cmd->data);
+		}
+
+		if (res) {
+			cmd->error = MMC_ERR_DMA;
+			cmd->data->error = MMC_ERR_DMA;
+
+			mmc_request_done(mmc, mrq);
+			return;
+		}
+
+	}
+
+	// Send command
+	s3cmci_send_command(host, cmd);
+
+	// Enable Interrupt
+	enable_irq(host->irq);
+}
+
+static void s3cmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+ 	struct s3cmci_host *host = mmc_priv(mmc);
+
+	host->cmd_is_stop = 0;
+	host->mrq = mrq;
+
+	s3cmci_send_request(mmc);
+}
+
+static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct s3cmci_host *host = mmc_priv(mmc);
+	u32 mci_psc, mci_con;
+
+	//Set power
+	mci_con = readl(host->base + S3C2410_SDICON);
+	switch(ios->power_mode) {
+		case MMC_POWER_ON:
+		case MMC_POWER_UP:
+			s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_SDCLK);
+			s3c2410_gpio_cfgpin(S3C2410_GPE6, S3C2410_GPE6_SDCMD);
+			s3c2410_gpio_cfgpin(S3C2410_GPE7, S3C2410_GPE7_SDDAT0);
+			s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);
+			s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2);
+			s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3);
+
+			if (!host->is2440)
+				mci_con|=S3C2410_SDICON_FIFORESET;
+
+			break;
+
+		case MMC_POWER_OFF:
+		default:
+			s3c2410_gpio_setpin(S3C2410_GPE5, 0);
+			s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_OUTP);
+
+			if (host->is2440)
+				mci_con|=S3C2440_SDICON_SDRESET;
+
+			break;
+	}
+
+	//Set clock
+	for (mci_psc=0; mci_psc<255; mci_psc++) {
+		host->real_rate = host->clk_rate / (host->clk_div*(mci_psc+1));
+
+		if (host->real_rate <= ios->clock)
+			break;
+	}
+
+	if(mci_psc > 255) mci_psc = 255;
+	host->prescaler = mci_psc;
+
+	writel(host->prescaler, host->base + S3C2410_SDIPRE);
+
+	//If requested clock is 0, real_rate will be 0, too
+	if (ios->clock == 0)
+		host->real_rate = 0;
+
+	//Set CLOCK_ENABLE
+	if (ios->clock)
+		mci_con |= S3C2410_SDICON_CLOCKTYPE;
+	else
+		mci_con &=~S3C2410_SDICON_CLOCKTYPE;
+
+	writel(mci_con, host->base + S3C2410_SDICON);
+
+	if ((ios->power_mode==MMC_POWER_ON)
+		|| (ios->power_mode==MMC_POWER_UP)) {
+
+		dbg(host, dbg_conf, "running at %lukHz (requested: %ukHz).\n",
+			host->real_rate/1000, ios->clock/1000);
+	} else {
+		dbg(host, dbg_conf, "powered down.\n");
+	}
+
+	host->bus_width = ios->bus_width;
+
+}
+
+static void s3cmci_reset(struct s3cmci_host *host)
+{
+	u32 con = readl(host->base + S3C2410_SDICON);
+
+	con |= S3C2440_SDICON_SDRESET;
+
+	writel(con, host->base + S3C2410_SDICON);
+}
+
+static struct mmc_host_ops s3cmci_ops = {
+	.request	= s3cmci_request,
+	.set_ios	= s3cmci_set_ios,
+};
+
+static int s3cmci_probe(struct platform_device *pdev, int is2440)
+{
+	struct mmc_host 	*mmc;
+	struct s3cmci_host 	*host;
+
+	int ret;
+
+	mmc = mmc_alloc_host(sizeof(struct s3cmci_host), &pdev->dev);
+	if (!mmc) {
+		ret = -ENOMEM;
+		goto probe_out;
+	}
+
+	host = mmc_priv(mmc);
+	host->mmc 	= mmc;
+	host->pdev	= pdev;
+
+	spin_lock_init(&host->complete_lock);
+	tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host);
+	if (is2440) {
+		host->is2440	= 1;
+		host->sdiimsk	= S3C2440_SDIIMSK;
+		host->sdidata	= S3C2440_SDIDATA;
+		host->clk_div	= 1;
+	} else {
+		host->is2440	= 0;
+		host->sdiimsk	= S3C2410_SDIIMSK;
+		host->sdidata	= S3C2410_SDIDATA;
+		host->clk_div	= 2;
+	}
+	host->dodma		= 0;
+	host->complete_what 	= COMPLETION_NONE;
+	host->pio_active 	= XFER_NONE;
+
+	host->dma		= S3CMCI_DMA;
+	host->irq_cd		= IRQ_EINT2;
+
+	host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!host->mem) {
+		dev_err(&pdev->dev,
+			"failed to get io memory region resouce.\n");
+
+		ret = -ENOENT;
+		goto probe_free_host;
+	}
+
+	host->mem = request_mem_region(host->mem->start,
+		RESSIZE(host->mem), pdev->name);
+
+	if (!host->mem) {
+		dev_err(&pdev->dev, "failed to request io memory region.\n");
+		ret = -ENOENT;
+		goto probe_free_host;
+	}
+
+	host->base = ioremap(host->mem->start, RESSIZE(host->mem));
+	if (host->base == 0) {
+		dev_err(&pdev->dev, "failed to ioremap() io memory region.\n");
+		ret = -EINVAL;
+		goto probe_free_mem_region;
+	}
+
+	host->irq = platform_get_irq(pdev, 0);
+	if (host->irq == 0) {
+		dev_err(&pdev->dev, "failed to get interrupt resouce.\n");
+		ret = -EINVAL;
+		goto probe_iounmap;
+	}
+
+	if (request_irq(host->irq, s3cmci_irq, 0, DRIVER_NAME, host)) {
+		dev_err(&pdev->dev, "failed to request mci interrupt.\n");
+		ret = -ENOENT;
+		goto probe_iounmap;
+	}
+
+	disable_irq(host->irq);
+
+	s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_EINT2);
+	set_irq_type(host->irq_cd, IRQT_BOTHEDGE);
+
+	if (request_irq(host->irq_cd, s3cmci_irq_cd, 0, DRIVER_NAME, host)) {
+		dev_err(&pdev->dev,
+			"failed to request card detect interrupt.\n");
+
+		ret = -ENOENT;
+		goto probe_free_irq;
+	}
+
+	if (s3c2410_dma_request(S3CMCI_DMA, &s3cmci_dma_client, NULL)) {
+		dev_err(&pdev->dev, "unable to get DMA channel.\n");
+		ret = -EBUSY;
+		goto probe_free_irq_cd;
+	}
+
+	host->clk = clk_get(&pdev->dev, "sdi");
+	if (IS_ERR(host->clk)) {
+		dev_err(&pdev->dev, "failed to find clock source.\n");
+		ret = PTR_ERR(host->clk);
+		host->clk = NULL;
+		goto probe_free_host;
+	}
+
+	if ((ret = clk_enable(host->clk))) {
+		dev_err(&pdev->dev, "failed to enable clock source.\n");
+		goto clk_free;
+	}
+
+	host->clk_rate = clk_get_rate(host->clk);
+
+	mmc->ops 	= &s3cmci_ops;
+	mmc->ocr_avail	= MMC_VDD_32_33;
+	mmc->caps	= MMC_CAP_4_BIT_DATA;
+	mmc->f_min 	= host->clk_rate / (host->clk_div * 256);
+	mmc->f_max 	= host->clk_rate / host->clk_div;
+
+	mmc->max_blk_count	= 4095;
+	mmc->max_blk_size	= 4095;
+	mmc->max_req_size	= 4095 * 512;
+	mmc->max_seg_size	= mmc->max_req_size;
+
+	mmc->max_phys_segs	= 128;
+	mmc->max_hw_segs	= 128;
+
+	dbg(host, dbg_debug, "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%u.\n",
+		(host->is2440?"2440":""),
+		host->base, host->irq, host->irq_cd, host->dma);
+
+	if ((ret = mmc_add_host(mmc))) {
+		dev_err(&pdev->dev, "failed to add mmc host.\n");
+		goto free_dmabuf;
+	}
+
+	platform_set_drvdata(pdev, mmc);
+
+	dev_info(&pdev->dev,"initialisation done.\n");
+	return 0;
+
+ free_dmabuf:
+	clk_disable(host->clk);
+
+ clk_free:
+	clk_put(host->clk);
+
+ probe_free_irq_cd:
+ 	free_irq(host->irq_cd, host);
+
+ probe_free_irq:
+ 	free_irq(host->irq, host);
+
+ probe_iounmap:
+	iounmap(host->base);
+
+ probe_free_mem_region:
+	release_mem_region(host->mem->start, RESSIZE(host->mem));
+
+ probe_free_host:
+	mmc_free_host(mmc);
+ probe_out:
+	return ret;
+}
+
+static int s3cmci_remove(struct platform_device *pdev)
+{
+	struct mmc_host 	*mmc  = platform_get_drvdata(pdev);
+	struct s3cmci_host 	*host = mmc_priv(mmc);
+
+	mmc_remove_host(mmc);
+	clk_disable(host->clk);
+	clk_put(host->clk);
+ 	free_irq(host->irq_cd, host);
+ 	free_irq(host->irq, host);
+	iounmap(host->base);
+	release_mem_region(host->mem->start, RESSIZE(host->mem));
+	mmc_free_host(mmc);
+
+	return 0;
+}
+
+static int s3cmci_probe_2410(struct platform_device *dev)
+{
+	return s3cmci_probe(dev, 0);
+}
+
+static int s3cmci_probe_2412(struct platform_device *dev)
+{
+	return s3cmci_probe(dev, 1);
+}
+
+static int s3cmci_probe_2440(struct platform_device *dev)
+{
+	return s3cmci_probe(dev, 1);
+}
+
+#ifdef CONFIG_PM
+
+static int s3cmci_suspend(struct platform_device *dev, pm_message_t state)
+{
+	struct mmc_host *mmc = platform_get_drvdata(dev);
+
+	return  mmc_suspend_host(mmc, state);
+}
+
+static int s3cmci_resume(struct platform_device *dev)
+{
+	struct mmc_host *mmc = platform_get_drvdata(dev);
+
+	return mmc_resume_host(mmc);
+}
+
+#else /* CONFIG_PM */
+#define s3cmci_suspend NULL
+#define s3cmci_resume NULL
+#endif /* CONFIG_PM */
+
+
+static struct platform_driver s3cmci_driver_2410 =
+{
+	.driver.name	= "s3c2410-sdi",
+	.probe		= s3cmci_probe_2410,
+	.remove		= s3cmci_remove,
+	.suspend	= s3cmci_suspend,
+	.resume		= s3cmci_resume,
+};
+
+static struct platform_driver s3cmci_driver_2412 =
+{
+	.driver.name	= "s3c2412-sdi",
+	.probe		= s3cmci_probe_2412,
+	.remove		= s3cmci_remove,
+	.suspend	= s3cmci_suspend,
+	.resume		= s3cmci_resume,
+};
+
+static struct platform_driver s3cmci_driver_2440 =
+{
+	.driver.name	= "s3c2440-sdi",
+	.probe		= s3cmci_probe_2440,
+	.remove		= s3cmci_remove,
+	.suspend	= s3cmci_suspend,
+	.resume		= s3cmci_resume,
+};
+
+
+static int __init s3cmci_init(void)
+{
+	platform_driver_register(&s3cmci_driver_2410);
+	platform_driver_register(&s3cmci_driver_2412);
+	platform_driver_register(&s3cmci_driver_2440);
+	return 0;
+}
+
+static void __exit s3cmci_exit(void)
+{
+	platform_driver_unregister(&s3cmci_driver_2410);
+	platform_driver_unregister(&s3cmci_driver_2412);
+	platform_driver_unregister(&s3cmci_driver_2440);
+}
+
+module_init(s3cmci_init);
+module_exit(s3cmci_exit);
+
+MODULE_DESCRIPTION("Samsung S3C MMC/SD Card Interface driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Thomas Kleffel <tk@maintech.de>");
+
Index: linux-2.6.26-rc5-q/drivers/mmc/host/s3cmci.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.26-rc5-q/drivers/mmc/host/s3cmci.h	2008-06-06 15:24:37.000000000 +0100
@@ -0,0 +1,71 @@
+/*
+ *  linux/drivers/mmc/s3cmci.h - Samsung S3C MCI driver
+ *
+ *  Copyright (C) 2004-2006 Thomas Kleffel, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+//FIXME: DMA Resource management ?!
+#define S3CMCI_DMA 0
+
+enum s3cmci_waitfor {
+	COMPLETION_NONE,
+	COMPLETION_FINALIZE,
+	COMPLETION_CMDSENT,
+	COMPLETION_RSPFIN,
+	COMPLETION_XFERFINISH,
+	COMPLETION_XFERFINISH_RSPFIN,
+};
+
+struct s3cmci_host {
+	struct platform_device	*pdev;
+	struct mmc_host		*mmc;
+	struct resource		*mem;
+	struct clk		*clk;
+	void __iomem		*base;
+	int			irq;
+	int			irq_cd;
+	int			dma;
+
+	unsigned long		clk_rate;
+	unsigned long		clk_div;
+	unsigned long		real_rate;
+	u8			prescaler;
+
+	int			is2440;
+	unsigned		sdiimsk;
+	unsigned		sdidata;
+	int			dodma;
+
+	volatile int		dmatogo;
+
+	struct mmc_request	*mrq;
+	int			cmd_is_stop;
+
+	spinlock_t		complete_lock;
+	volatile enum s3cmci_waitfor
+				complete_what;
+
+	volatile int		dma_complete;
+
+	volatile u32		pio_sgptr;
+	volatile u32		pio_words;
+	volatile u32		pio_count;
+	volatile u32		*pio_ptr;
+#define XFER_NONE 0
+#define XFER_READ 1
+#define XFER_WRITE 2
+	volatile u32		pio_active;
+
+	int			bus_width;
+
+	char 			dbgmsg_cmd[301];
+	char 			dbgmsg_dat[301];
+	volatile char		*status;
+
+	unsigned int		ccnt, dcnt;
+	struct tasklet_struct	pio_tasklet;
+};
Index: linux-2.6.26-rc5-q/drivers/mmc/host/Kconfig
===================================================================
--- linux-2.6.26-rc5-q.orig/drivers/mmc/host/Kconfig	2008-06-05 15:09:44.000000000 +0100
+++ linux-2.6.26-rc5-q/drivers/mmc/host/Kconfig	2008-06-06 15:08:32.000000000 +0100
@@ -130,3 +130,14 @@ config MMC_SPI
 
 	  If unsure, or if your system has no SPI master driver, say N.
 
+config MMC_S3C
+	tristate "Samsung S3C SD/MMC Card Interface support"
+	depends on ARCH_S3C2410 && MMC
+	help
+	  This selects a driver for the MCI interface found in
+          Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs.
+	  If you have a board based on one of those and a MMC/SD
+	  slot, say Y or M here.
+
+	  If unsure, say N.
+
Index: linux-2.6.26-rc5-q/drivers/mmc/host/Makefile
===================================================================
--- linux-2.6.26-rc5-q.orig/drivers/mmc/host/Makefile	2008-05-13 10:13:29.000000000 +0100
+++ linux-2.6.26-rc5-q/drivers/mmc/host/Makefile	2008-06-06 15:25:29.000000000 +0100
@@ -17,4 +17,4 @@ obj-$(CONFIG_MMC_OMAP)		+= omap.o
 obj-$(CONFIG_MMC_AT91)		+= at91_mci.o
 obj-$(CONFIG_MMC_TIFM_SD)	+= tifm_sd.o
 obj-$(CONFIG_MMC_SPI)		+= mmc_spi.o
-
+obj-$(CONFIG_MMC_S3C)   	+= s3cmci.o

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [patch v2 02/16] MMC: S3C24XX: Fix the checkpatch.pl errors in the s3cmci driver
  2008-06-16 14:34 [patch v2 00/16] S3C24XX SD/MMC driver Ben Dooks
  2008-06-16 14:34 ` [patch v2 01/16] MMC: S3C24XX MMC/SD driver Ben Dooks
@ 2008-06-16 14:34 ` Ben Dooks
  2008-06-16 15:07   ` Ben Dooks
  2008-06-16 14:34 ` [patch v2 03/16] MMC: S3C24XX MMC/SD driver write fixes Ben Dooks
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 19+ messages in thread
From: Ben Dooks @ 2008-06-16 14:34 UTC (permalink / raw)
  To: linux-kernel; +Cc: drzeus-mmc, Ben Dooks

[-- Attachment #1: simtec/simtec-fix-checkpatch-errors.patch --]
[-- Type: text/plain, Size: 31060 bytes --]

Fix the checkpatch and other problems pointed out by
akpm.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Index: linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c
===================================================================
--- linux-2.6.26-rc5-q2.orig/drivers/mmc/host/s3cmci.c	2008-06-07 12:25:20.000000000 +0100
+++ linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c	2008-06-16 15:18:13.000000000 +0100
@@ -15,11 +15,10 @@
 #include <linux/mmc/host.h>
 #include <linux/platform_device.h>
 #include <linux/irq.h>
+#include <linux/io.h>
 
 #include <asm/dma.h>
-#include <asm/dma-mapping.h>
 
-#include <asm/io.h>
 #include <asm/arch/regs-sdi.h>
 #include <asm/arch/regs-gpio.h>
 
@@ -43,13 +42,15 @@ static const int dbgmap_err   = dbg_err 
 static const int dbgmap_info  = dbg_info | dbg_conf;
 static const int dbgmap_debug = dbg_debug;
 
-#define dbg(host, channels, args...)		 \
-	if (dbgmap_err & channels) 		 \
-		dev_err(&host->pdev->dev, args); \
-	else if (dbgmap_info & channels)	 \
-		dev_info(&host->pdev->dev, args);\
-	else if (dbgmap_debug & channels)	 \
-		dev_dbg(&host->pdev->dev, args);
+#define dbg(host, channels, args...)		  \
+	do {					  \
+	if (dbgmap_err & channels) 		  \
+		dev_err(&host->pdev->dev, args);  \
+	else if (dbgmap_info & channels)	  \
+		dev_info(&host->pdev->dev, args); \
+	else if (dbgmap_debug & channels)	  \
+		dev_dbg(&host->pdev->dev, args);  \
+	} while (0)
 
 #define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
 
@@ -63,7 +64,7 @@ static void s3cmci_reset(struct s3cmci_h
 
 #ifdef CONFIG_MMC_DEBUG
 
-static inline void dbg_dumpregs(struct s3cmci_host *host, char *prefix)
+static void dbg_dumpregs(struct s3cmci_host *host, char *prefix)
 {
 	u32 con, pre, cmdarg, cmdcon, cmdsta, r0, r1, r2, r3, timer, bsize;
 	u32 datcon, datcnt, datsta, fsta, imask;
@@ -103,17 +104,17 @@ static inline void dbg_dumpregs(struct s
 static void prepare_dbgmsg(struct s3cmci_host *host, struct mmc_command *cmd,
 								int stop)
 {
- 	snprintf(host->dbgmsg_cmd, 300,
-		"#%u%s op:%i arg:0x%08x flags:0x08%x retries:%u",
-		host->ccnt, (stop?" (STOP)":""),
-		cmd->opcode, cmd->arg, cmd->flags, cmd->retries);
+	snprintf(host->dbgmsg_cmd, 300,
+		 "#%u%s op:%i arg:0x%08x flags:0x08%x retries:%u",
+		 host->ccnt, (stop ? " (STOP)" : ""),
+		 cmd->opcode, cmd->arg, cmd->flags, cmd->retries);
 
 	if (cmd->data) {
 		snprintf(host->dbgmsg_dat, 300,
-			"#%u bsize:%u blocks:%u bytes:%u",
-			host->dcnt, cmd->data->blksz,
-			cmd->data->blocks,
-			cmd->data->blocks * cmd->data->blksz);
+			 "#%u bsize:%u blocks:%u bytes:%u",
+			 host->dcnt, cmd->data->blksz,
+			 cmd->data->blocks,
+			 cmd->data->blocks * cmd->data->blksz);
 	} else {
 		host->dbgmsg_dat[0] = '\0';
 	}
@@ -153,7 +154,7 @@ static inline u32 enable_imask(struct s3
 	u32 newmask;
 
 	newmask = readl(host->base + host->sdiimsk);
-	newmask|= imask;
+	newmask |= imask;
 
 	writel(newmask, host->base + host->sdiimsk);
 
@@ -165,7 +166,7 @@ static inline u32 disable_imask(struct s
 	u32 newmask;
 
 	newmask = readl(host->base + host->sdiimsk);
-	newmask&= ~imask;
+	newmask &= ~imask;
 
 	writel(newmask, host->base + host->sdiimsk);
 
@@ -178,7 +179,7 @@ static inline void clear_imask(struct s3
 }
 
 static inline int get_data_buffer(struct s3cmci_host *host,
-			volatile u32 *words, volatile u32 **pointer)
+				  u32 *words, u32 **pointer)
 {
 	struct scatterlist *sg;
 
@@ -195,69 +196,82 @@ static inline int get_data_buffer(struct
 	}
 	sg = &host->mrq->data->sg[host->pio_sgptr];
 
-	*words	= sg->length >> 2;
-	*pointer= page_address(sg->page) + sg->offset;
+	*words = sg->length >> 2;
+	*pointer = page_address(sg->page) + sg->offset;
 
 	host->pio_sgptr++;
 
 	dbg(host, dbg_sg, "new buffer (%i/%i)\n",
-	      host->pio_sgptr, host->mrq->data->sg_len);
+	    host->pio_sgptr, host->mrq->data->sg_len);
 
 	return 0;
 }
 
-#define FIFO_FILL(host) ((readl(host->base + S3C2410_SDIFSTA) & S3C2410_SDIFSTA_COUNTMASK) >> 2)
-#define FIFO_FREE(host) ((63 - (readl(host->base + S3C2410_SDIFSTA) & S3C2410_SDIFSTA_COUNTMASK)) >> 2)
+static inline u32 fifo_count(struct s3cmci_host *host)
+{
+	u32 fifostat = readl(host->base + S3C2410_SDIFSTA);
+
+	fifostat &= S3C2410_SDIFSTA_COUNTMASK;
+	return fifostat >> 2;
+}
+
+static inline u32 fifo_free(struct s3cmci_host *host)
+{
+	u32 fifostat = readl(host->base + S3C2410_SDIFSTA);
+
+	fifostat &= S3C2410_SDIFSTA_COUNTMASK;
+	return 63 - (fifostat >> 2);
+}
 
-static inline void do_pio_read(struct s3cmci_host *host)
+static void do_pio_read(struct s3cmci_host *host)
 {
 	int res;
 	u32 fifo;
 	void __iomem *from_ptr;
 
-	//write real prescaler to host, it might be set slow to fix
+	/* write real prescaler to host, it might be set slow to fix */
 	writel(host->prescaler, host->base + S3C2410_SDIPRE);
 
 	from_ptr = host->base + host->sdidata;
 
-	while ((fifo = FIFO_FILL(host))) {
+	while ((fifo = fifo_count(host))) {
 		if (!host->pio_words) {
 			res = get_data_buffer(host, &host->pio_words,
-							&host->pio_ptr);
+					      &host->pio_ptr);
 			if (res) {
 				host->pio_active = XFER_NONE;
 				host->complete_what = COMPLETION_FINALIZE;
 
 				dbg(host, dbg_pio, "pio_read(): "
-					"complete (no more data).\n");
+				    "complete (no more data).\n");
 				return;
 			}
 
-			dbg(host, dbg_pio, "pio_read(): new target: [%i]@[%p]\n",
-			       host->pio_words, host->pio_ptr);
+			dbg(host, dbg_pio,
+			    "pio_read(): new target: [%i]@[%p]\n",
+			    host->pio_words, host->pio_ptr);
 		}
 
-		dbg(host, dbg_pio, "pio_read(): fifo:[%02i] "
-				   "buffer:[%03i] dcnt:[%08X]\n",
-				   fifo, host->pio_words,
-				   readl(host->base + S3C2410_SDIDCNT));
+		dbg(host, dbg_pio,
+		    "pio_read(): fifo:[%02i] buffer:[%03i] dcnt:[%08X]\n",
+		    fifo, host->pio_words,
+		    readl(host->base + S3C2410_SDIDCNT));
 
 		if (fifo > host->pio_words)
 			fifo = host->pio_words;
 
-		host->pio_words-= fifo;
-		host->pio_count+= fifo;
+		host->pio_words -= fifo;
+		host->pio_count += fifo;
 
-		while(fifo--) {
+		while (fifo--)
 			*(host->pio_ptr++) = readl(from_ptr);
-		}
 	}
 
 	if (!host->pio_words) {
 		res = get_data_buffer(host, &host->pio_words, &host->pio_ptr);
 		if (res) {
-			dbg(host, dbg_pio, "pio_read(): "
-				"complete (no more buffers).\n");
+			dbg(host, dbg_pio,
+			    "pio_read(): complete (no more buffers).\n");
 			host->pio_active = XFER_NONE;
 			host->complete_what = COMPLETION_FINALIZE;
 
@@ -265,10 +279,11 @@ static inline void do_pio_read(struct s3
 		}
 	}
 
-	enable_imask(host, S3C2410_SDIIMSK_RXFIFOHALF | S3C2410_SDIIMSK_RXFIFOLAST);
+	enable_imask(host,
+		     S3C2410_SDIIMSK_RXFIFOHALF | S3C2410_SDIIMSK_RXFIFOLAST);
 }
 
-static inline void do_pio_write(struct s3cmci_host *host)
+static void do_pio_write(struct s3cmci_host *host)
 {
 	int res;
 	u32 fifo;
@@ -277,33 +292,32 @@ static inline void do_pio_write(struct s
 
 	to_ptr = host->base + host->sdidata;
 
-	while ((fifo = FIFO_FREE(host))) {
+	while ((fifo = fifo_free(host))) {
 		if (!host->pio_words) {
 			res = get_data_buffer(host, &host->pio_words,
 							&host->pio_ptr);
 			if (res) {
-				dbg(host, dbg_pio, "pio_write(): "
-					"complete (no more data).\n");
+				dbg(host, dbg_pio,
+				    "pio_write(): complete (no more data).\n");
 				host->pio_active = XFER_NONE;
 
 				return;
 			}
 
-			dbg(host, dbg_pio, "pio_write(): "
-				"new source: [%i]@[%p]\n",
-				host->pio_words, host->pio_ptr);
+			dbg(host, dbg_pio,
+			    "pio_write(): new source: [%i]@[%p]\n",
+			    host->pio_words, host->pio_ptr);
 
 		}
 
 		if (fifo > host->pio_words)
 			fifo = host->pio_words;
 
-		host->pio_words-= fifo;
-		host->pio_count+= fifo;
+		host->pio_words -= fifo;
+		host->pio_count += fifo;
 
-		while(fifo--) {
+		while (fifo--)
 			writel(*(host->pio_ptr++), to_ptr);
-		}
 	}
 
 	enable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);
@@ -324,9 +338,9 @@ static void pio_tasklet(unsigned long da
 		clear_imask(host);
 		if (host->pio_active != XFER_NONE) {
 			dbg(host, dbg_err, "unfinished %s "
-				"- pio_count:[%u] pio_words:[%u]\n",
-				(host->pio_active == XFER_READ)?"read":"write",
-				host->pio_count, host->pio_words);
+			    "- pio_count:[%u] pio_words:[%u]\n",
+			    (host->pio_active == XFER_READ) ? "read" : "write",
+			    host->pio_count, host->pio_words);
 
 			host->mrq->data->error = MMC_ERR_DMA;
 		}
@@ -340,7 +354,7 @@ static void pio_tasklet(unsigned long da
  * ISR for SDI Interface IRQ
  * Communication between driver and ISR works as follows:
  *   host->mrq 			points to current request
- *   host->complete_what	tells the ISR when the request is considered done
+ *   host->complete_what	Indicates when the request is considered done
  *     COMPLETION_CMDSENT	  when the command was sent
  *     COMPLETION_RSPFIN          when a response was received
  *     COMPLETION_XFERFINISH	  when the data transfer is finished
@@ -365,14 +379,12 @@ static void pio_tasklet(unsigned long da
 
 static irqreturn_t s3cmci_irq(int irq, void *dev_id)
 {
-	struct s3cmci_host *host;
+	struct s3cmci_host *host = dev_id;
 	struct mmc_command *cmd;
 	u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt, mci_imsk;
 	u32 mci_cclear, mci_dclear;
 	unsigned long iflags;
 
-	host = (struct s3cmci_host *)dev_id;
-
 	spin_lock_irqsave(&host->complete_lock, iflags);
 
 	mci_csta 	= readl(host->base + S3C2410_SDICMDSTAT);
@@ -384,7 +396,7 @@ static irqreturn_t s3cmci_irq(int irq, v
 	mci_dclear	= 0;
 
 	if ((host->complete_what == COMPLETION_NONE) ||
-			(host->complete_what == COMPLETION_FINALIZE)) {
+	    (host->complete_what == COMPLETION_FINALIZE)) {
 		host->status = "nothing to complete";
 		clear_imask(host);
 		goto irq_out;
@@ -396,7 +408,7 @@ static irqreturn_t s3cmci_irq(int irq, v
 		goto irq_out;
 	}
 
-	cmd = host->cmd_is_stop?host->mrq->stop:host->mrq->cmd;
+	cmd = host->cmd_is_stop ? host->mrq->stop : host->mrq->cmd;
 
 	if (!cmd) {
 		host->status = "no active cmd";
@@ -406,7 +418,7 @@ static irqreturn_t s3cmci_irq(int irq, v
 
 	if (!host->dodma) {
 		if ((host->pio_active == XFER_WRITE) &&
-				(mci_fsta & S3C2410_SDIFSTA_TFDET)) {
+		    (mci_fsta & S3C2410_SDIFSTA_TFDET)) {
 
 			disable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);
 			tasklet_schedule(&host->pio_tasklet);
@@ -414,10 +426,11 @@ static irqreturn_t s3cmci_irq(int irq, v
 		}
 
 		if ((host->pio_active == XFER_READ) &&
-				(mci_fsta & S3C2410_SDIFSTA_RFDET)) {
+		    (mci_fsta & S3C2410_SDIFSTA_RFDET)) {
 
 			disable_imask(host,
-				S3C2410_SDIIMSK_RXFIFOHALF | S3C2410_SDIIMSK_RXFIFOLAST);
+				      S3C2410_SDIIMSK_RXFIFOHALF |
+				      S3C2410_SDIIMSK_RXFIFOLAST);
 
 			tasklet_schedule(&host->pio_tasklet);
 			host->status = "pio rx";
@@ -506,9 +519,8 @@ static irqreturn_t s3cmci_irq(int irq, v
 			goto close_transfer;
 		}
 
-		if (host->complete_what == COMPLETION_XFERFINISH_RSPFIN) {
+		if (host->complete_what == COMPLETION_XFERFINISH_RSPFIN)
 			host->complete_what = COMPLETION_RSPFIN;
-		}
 
 		mci_dclear |= S3C2410_SDIDSTA_XFERFINISH;
 	}
@@ -531,10 +543,9 @@ close_transfer:
 	goto irq_out;
 
 irq_out:
-	dbg(host, dbg_irq, "csta:0x%08x dsta:0x%08x "
-			   "fsta:0x%08x dcnt:0x%08x status:%s.\n",
-				mci_csta, mci_dsta, mci_fsta,
-				mci_dcnt, host->status);
+	dbg(host, dbg_irq,
+	    "csta:0x%08x dsta:0x%08x fsta:0x%08x dcnt:0x%08x status:%s.\n",
+	    mci_csta, mci_dsta, mci_fsta, mci_dcnt, host->status);
 
 	spin_unlock_irqrestore(&host->complete_lock, iflags);
 	return IRQ_HANDLED;
@@ -557,7 +568,7 @@ static irqreturn_t s3cmci_irq_cd(int irq
 }
 
 void s3cmci_dma_done_callback(struct s3c2410_dma_chan *dma_ch, void *buf_id,
-	int size, enum s3c2410_dma_buffresult result)
+			      int size, enum s3c2410_dma_buffresult result)
 {
 	unsigned long iflags;
 	u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt;
@@ -568,11 +579,9 @@ void s3cmci_dma_done_callback(struct s3c
 	mci_fsta 	= readl(host->base + S3C2410_SDIFSTA);
 	mci_dcnt 	= readl(host->base + S3C2410_SDIDCNT);
 
-	if ((!host->mrq) || (!host->mrq) || (!host->mrq->data))
-		return;
-
-	if (!host->dmatogo)
-		return;
+	BUG_ON(!host->mrq);
+	BUG_ON(!host->mrq->data);
+	BUG_ON(!host->dmatogo);
 
 	spin_lock_irqsave(&host->complete_lock, iflags);
 
@@ -616,7 +625,7 @@ fail_request:
 static void finalize_request(struct s3cmci_host *host)
 {
 	struct mmc_request *mrq = host->mrq;
-	struct mmc_command *cmd = host->cmd_is_stop?mrq->stop:mrq->cmd;
+	struct mmc_command *cmd = host->cmd_is_stop ? mrq->stop : mrq->cmd;
 	int debug_as_failure = 0;
 
 	if (host->complete_what != COMPLETION_FINALIZE)
@@ -626,21 +635,19 @@ static void finalize_request(struct s3cm
 		return;
 
 	if (cmd->data && (cmd->error == MMC_ERR_NONE) &&
-		  (cmd->data->error == MMC_ERR_NONE)) {
-
+	    (cmd->data->error == MMC_ERR_NONE)) {
 		if (host->dodma && (!host->dma_complete)) {
 			dbg(host, dbg_dma, "DMA Missing!\n");
 			return;
 		}
 	}
 
-	// Read response
+	/* Read response from controller. */
 	cmd->resp[0] = readl(host->base + S3C2410_SDIRSP0);
 	cmd->resp[1] = readl(host->base + S3C2410_SDIRSP1);
 	cmd->resp[2] = readl(host->base + S3C2410_SDIRSP2);
 	cmd->resp[3] = readl(host->base + S3C2410_SDIRSP3);
 
-	// reset clock speed, as it could still be set low for
 	writel(host->prescaler, host->base + S3C2410_SDIPRE);
 
 	if (cmd->error)
@@ -649,12 +656,10 @@ static void finalize_request(struct s3cm
 	if (cmd->data && cmd->data->error)
 		debug_as_failure = 1;
 
-	//if(cmd->flags & MMC_RSP_MAYFAIL) debug_as_failure = 0;
-
 #ifdef CONFIG_MMC_DEBUG
 	dbg_dumpcmd(host, cmd, debug_as_failure);
 #endif
-	//Cleanup controller
+	/* Cleanup controller */
 	writel(0, host->base + S3C2410_SDICMDARG);
 	writel(0, host->base + S3C2410_SDIDCON);
 	writel(0, host->base + S3C2410_SDICMDCON);
@@ -669,12 +674,11 @@ static void finalize_request(struct s3cm
 		return;
 	}
 
-	// If we have no data transfer we are finished here
+	/* If we have no data transfer we are finished here */
 	if (!mrq->data)
 		goto request_done;
 
-	// Calulate the amout of bytes transfer, but only if there was
-	// no error
+	/* Calulate the amout of bytes transfer if there was no error */
 	if (mrq->data->error == MMC_ERR_NONE) {
 		mrq->data->bytes_xfered =
 			(mrq->data->blocks * mrq->data->blksz);
@@ -682,23 +686,23 @@ static void finalize_request(struct s3cm
 		mrq->data->bytes_xfered = 0;
 	}
 
-	// If we had an error while transfering data we flush the
-	// DMA channel and the fifo to clear out any garbage
+	/* If we had an error while transfering data we flush the
+	 * DMA channel and the fifo to clear out any garbage. */
 	if (mrq->data->error != MMC_ERR_NONE) {
 		if (host->dodma)
 			s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
 
 		if (host->is2440) {
-			//Clear failure register and reset fifo
+			/* Clear failure register and reset fifo. */
 			writel(S3C2440_SDIFSTA_FIFORESET |
 			       S3C2440_SDIFSTA_FIFOFAIL,
 			       host->base + S3C2410_SDIFSTA);
 		} else {
 			u32 mci_con;
 
-			//reset fifo
+			/* reset fifo */
 			mci_con = readl(host->base + S3C2410_SDICON);
-			mci_con|= S3C2410_SDICON_FIFORESET;
+			mci_con |= S3C2410_SDICON_FIFORESET;
 
 			writel(mci_con, host->base + S3C2410_SDICON);
 		}
@@ -713,8 +717,8 @@ request_done:
 
 void s3cmci_dma_setup(struct s3cmci_host *host, enum s3c2410_dmasrc source)
 {
-	static int setup_ok = 0;
 	static enum s3c2410_dmasrc last_source = -1;
+	static int setup_ok;
 
 	if (last_source == source)
 		return;
@@ -727,7 +731,8 @@ void s3cmci_dma_setup(struct s3cmci_host
 	if (!setup_ok) {
 		s3c2410_dma_config(host->dma, 4,
 			(S3C2410_DCON_HWTRIG | S3C2410_DCON_CH0_SDI));
-		s3c2410_dma_set_buffdone_fn(host->dma, s3cmci_dma_done_callback);
+		s3c2410_dma_set_buffdone_fn(host->dma,
+					    s3cmci_dma_done_callback);
 		s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART);
 		setup_ok = 1;
 	}
@@ -744,31 +749,30 @@ static void s3cmci_send_command(struct s
 
 	enable_imask(host, imsk);
 
-	if (cmd->data) {
+	if (cmd->data)
 		host->complete_what = COMPLETION_XFERFINISH_RSPFIN;
-	} else if (cmd->flags & MMC_RSP_PRESENT) {
+	else if (cmd->flags & MMC_RSP_PRESENT)
 		host->complete_what = COMPLETION_RSPFIN;
-	} else {
+	else
 		host->complete_what = COMPLETION_CMDSENT;
-	}
 
 	writel(cmd->arg, host->base + S3C2410_SDICMDARG);
 
-	ccon = cmd->opcode & S3C2410_SDICMDCON_INDEX;
-	ccon|= S3C2410_SDICMDCON_SENDERHOST | S3C2410_SDICMDCON_CMDSTART;
+	ccon  = cmd->opcode & S3C2410_SDICMDCON_INDEX;
+	ccon |= S3C2410_SDICMDCON_SENDERHOST | S3C2410_SDICMDCON_CMDSTART;
 
 	if (cmd->flags & MMC_RSP_PRESENT)
 		ccon |= S3C2410_SDICMDCON_WAITRSP;
 
 	if (cmd->flags & MMC_RSP_136)
-		ccon|= S3C2410_SDICMDCON_LONGRSP;
+		ccon |= S3C2410_SDICMDCON_LONGRSP;
 
 	writel(ccon, host->base + S3C2410_SDICMDCON);
 }
 
 static int s3cmci_setup_data(struct s3cmci_host *host, struct mmc_data *data)
 {
-	u32 dcon, imsk, stoptries=3;
+	u32 dcon, imsk, stoptries = 3;
 
 	/* write DCON register */
 
@@ -777,16 +781,16 @@ static int s3cmci_setup_data(struct s3cm
 		return 0;
 	}
 
-	while(readl(host->base + S3C2410_SDIDSTA) &
-		(S3C2410_SDIDSTA_TXDATAON | S3C2410_SDIDSTA_RXDATAON)) {
+	while (readl(host->base + S3C2410_SDIDSTA) &
+	       (S3C2410_SDIDSTA_TXDATAON | S3C2410_SDIDSTA_RXDATAON)) {
 
 		dbg(host, dbg_err,
-			"mci_setup_data() transfer stillin progress.\n");
+		    "mci_setup_data() transfer stillin progress.\n");
 
 		writel(0, host->base + S3C2410_SDIDCON);
 		s3cmci_reset(host);
 
-		if (0 == (stoptries--)) {
+		if ((stoptries--) == 0) {
 #ifdef CONFIG_MMC_DEBUG
 			dbg_dumpregs(host, "DRF");
 #endif
@@ -797,17 +801,14 @@ static int s3cmci_setup_data(struct s3cm
 
 	dcon  = data->blocks & S3C2410_SDIDCON_BLKNUM_MASK;
 
-	if (host->dodma) {
+	if (host->dodma)
 		dcon |= S3C2410_SDIDCON_DMAEN;
-	}
 
-	if (host->bus_width == MMC_BUS_WIDTH_4) {
+	if (host->bus_width == MMC_BUS_WIDTH_4)
 		dcon |= S3C2410_SDIDCON_WIDEBUS;
-	}
 
-	if (!(data->flags & MMC_DATA_STREAM)) {
+	if (!(data->flags & MMC_DATA_STREAM))
 		dcon |= S3C2410_SDIDCON_BLOCKMODE;
-	}
 
 	if (data->flags & MMC_DATA_WRITE) {
 		dcon |= S3C2410_SDIDCON_TXAFTERRESP;
@@ -831,8 +832,8 @@ static int s3cmci_setup_data(struct s3cm
 	writel(data->blksz, host->base + S3C2410_SDIBSIZE);
 
 	/* add to IMASK register */
-	imsk =	S3C2410_SDIIMSK_FIFOFAIL | S3C2410_SDIIMSK_DATACRC |
-		S3C2410_SDIIMSK_DATATIMEOUT | S3C2410_SDIIMSK_DATAFINISH;
+	imsk = S3C2410_SDIIMSK_FIFOFAIL | S3C2410_SDIIMSK_DATACRC |
+	       S3C2410_SDIIMSK_DATATIMEOUT | S3C2410_SDIIMSK_DATAFINISH;
 
 	enable_imask(host, imsk);
 
@@ -843,35 +844,33 @@ static int s3cmci_setup_data(struct s3cm
 	} else {
 		writel(0x0000FFFF, host->base + S3C2410_SDITIMER);
 
-		//FIX: set slow clock to prevent timeouts on read
-		if (data->flags & MMC_DATA_READ) {
+		/* FIX: set slow clock to prevent timeouts on read */
+		if (data->flags & MMC_DATA_READ)
 			writel(0xFF, host->base + S3C2410_SDIPRE);
-		}
 	}
 
-	//debug_dump_registers(host, "Data setup:");
-
 	return 0;
 }
 
+#define BOTH_DIR (MMC_DATA_WRITE | MMC_DATA_READ)
+
 static int s3cmci_prepare_pio(struct s3cmci_host *host, struct mmc_data *data)
 {
-	int rw = (data->flags & MMC_DATA_WRITE)?1:0;
+	int rw = (data->flags & MMC_DATA_WRITE) ? 1 : 0;
 
-	if (rw != ((data->flags & MMC_DATA_READ)?0:1))
-		return -EINVAL;
+	BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
 
 	host->pio_sgptr = 0;
 	host->pio_words = 0;
 	host->pio_count = 0;
-	host->pio_active = rw?XFER_WRITE:XFER_READ;
+	host->pio_active = rw ? XFER_WRITE : XFER_READ;
 
 	if (rw) {
 		do_pio_write(host);
 		enable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);
 	} else {
 		enable_imask(host, S3C2410_SDIIMSK_RXFIFOHALF
-			| S3C2410_SDIIMSK_RXFIFOLAST);
+			     | S3C2410_SDIIMSK_RXFIFOLAST);
 	}
 
 	return 0;
@@ -880,18 +879,15 @@ static int s3cmci_prepare_pio(struct s3c
 static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)
 {
 	int dma_len, i;
+	int rw = (data->flags & MMC_DATA_WRITE) ? 1 : 0;
 
-	int rw = (data->flags & MMC_DATA_WRITE)?1:0;
-
-	if (rw != ((data->flags & MMC_DATA_READ)?0:1))
-		return -EINVAL;
+	BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
 
-	s3cmci_dma_setup(host, rw?S3C2410_DMASRC_MEM:S3C2410_DMASRC_HW);
+	s3cmci_dma_setup(host, rw ? S3C2410_DMASRC_MEM : S3C2410_DMASRC_HW);
 	s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
 
 	dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
-				(rw)?DMA_TO_DEVICE:DMA_FROM_DEVICE);
-
+			     (rw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 
 	if (dma_len == 0)
 		return -ENOMEM;
@@ -907,14 +903,14 @@ static int s3cmci_prepare_dma(struct s3c
 			sg_dma_len(&data->sg[i]));
 
 		res = s3c2410_dma_enqueue(host->dma, (void *) host,
-				sg_dma_address(&data->sg[i]),
-				sg_dma_len(&data->sg[i]));
+					  sg_dma_address(&data->sg[i]),
+					  sg_dma_len(&data->sg[i]));
 
 		if (res) {
 			s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
 			return -EBUSY;
 		}
- 	}
+	}
 
 	s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_START);
 
@@ -925,21 +921,21 @@ static void s3cmci_send_request(struct m
 {
 	struct s3cmci_host *host = mmc_priv(mmc);
 	struct mmc_request *mrq = host->mrq;
-	struct mmc_command *cmd = host->cmd_is_stop?mrq->stop:mrq->cmd;
+	struct mmc_command *cmd = host->cmd_is_stop ? mrq->stop : mrq->cmd;
 
 	host->ccnt++;
 #ifdef CONFIG_MMC_DEBUG
 	prepare_dbgmsg(host, cmd, host->cmd_is_stop);
 #endif
-	//Clear command, data and fifo status registers
-	//Fifo clear only necessary on 2440, but doesn't hurt on 2410
+	/* Clear command, data and fifo status registers
+	   Fifo clear only necessary on 2440, but doesn't hurt on 2410
+	*/
 	writel(0xFFFFFFFF, host->base + S3C2410_SDICMDSTAT);
 	writel(0xFFFFFFFF, host->base + S3C2410_SDIDSTA);
 	writel(0xFFFFFFFF, host->base + S3C2410_SDIFSTA);
 
 	if (cmd->data) {
-		int res;
-		res = s3cmci_setup_data(host, cmd->data);
+		int res = s3cmci_setup_data(host, cmd->data);
 
 		host->dcnt++;
 
@@ -951,12 +947,10 @@ static void s3cmci_send_request(struct m
 			return;
 		}
 
-
-		if (host->dodma) {
+		if (host->dodma)
 			res = s3cmci_prepare_dma(host, cmd->data);
-		} else {
+		else
 			res = s3cmci_prepare_pio(host, cmd->data);
-		}
 
 		if (res) {
 			cmd->error = MMC_ERR_DMA;
@@ -968,16 +962,16 @@ static void s3cmci_send_request(struct m
 
 	}
 
-	// Send command
+	/* Send command */
 	s3cmci_send_command(host, cmd);
 
-	// Enable Interrupt
+	/* Enable Interrupt */
 	enable_irq(host->irq);
 }
 
 static void s3cmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
- 	struct s3cmci_host *host = mmc_priv(mmc);
+	struct s3cmci_host *host = mmc_priv(mmc);
 
 	host->cmd_is_stop = 0;
 	host->mrq = mrq;
@@ -990,62 +984,64 @@ static void s3cmci_set_ios(struct mmc_ho
 	struct s3cmci_host *host = mmc_priv(mmc);
 	u32 mci_psc, mci_con;
 
-	//Set power
-	mci_con = readl(host->base + S3C2410_SDICON);
-	switch(ios->power_mode) {
-		case MMC_POWER_ON:
-		case MMC_POWER_UP:
-			s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_SDCLK);
-			s3c2410_gpio_cfgpin(S3C2410_GPE6, S3C2410_GPE6_SDCMD);
-			s3c2410_gpio_cfgpin(S3C2410_GPE7, S3C2410_GPE7_SDDAT0);
-			s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);
-			s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2);
-			s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3);
-
-			if (!host->is2440)
-				mci_con|=S3C2410_SDICON_FIFORESET;
+	/* Set the power state */
 
-			break;
+	mci_con = readl(host->base + S3C2410_SDICON);
 
-		case MMC_POWER_OFF:
-		default:
-			s3c2410_gpio_setpin(S3C2410_GPE5, 0);
-			s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_OUTP);
+	switch (ios->power_mode) {
+	case MMC_POWER_ON:
+	case MMC_POWER_UP:
+		s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_SDCLK);
+		s3c2410_gpio_cfgpin(S3C2410_GPE6, S3C2410_GPE6_SDCMD);
+		s3c2410_gpio_cfgpin(S3C2410_GPE7, S3C2410_GPE7_SDDAT0);
+		s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);
+		s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2);
+		s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3);
+
+		if (!host->is2440)
+			mci_con |= S3C2410_SDICON_FIFORESET;
+
+		break;
+
+	case MMC_POWER_OFF:
+	default:
+		s3c2410_gpio_setpin(S3C2410_GPE5, 0);
+		s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_OUTP);
 
-			if (host->is2440)
-				mci_con|=S3C2440_SDICON_SDRESET;
+		if (host->is2440)
+			mci_con |= S3C2440_SDICON_SDRESET;
 
-			break;
+		break;
 	}
 
-	//Set clock
-	for (mci_psc=0; mci_psc<255; mci_psc++) {
+	/* Set clock */
+	for (mci_psc = 0; mci_psc < 255; mci_psc++) {
 		host->real_rate = host->clk_rate / (host->clk_div*(mci_psc+1));
 
 		if (host->real_rate <= ios->clock)
 			break;
 	}
 
-	if(mci_psc > 255) mci_psc = 255;
-	host->prescaler = mci_psc;
+	if (mci_psc > 255)
+		mci_psc = 255;
 
+	host->prescaler = mci_psc;
 	writel(host->prescaler, host->base + S3C2410_SDIPRE);
 
-	//If requested clock is 0, real_rate will be 0, too
+	/* If requested clock is 0, real_rate will be 0, too */
 	if (ios->clock == 0)
 		host->real_rate = 0;
 
-	//Set CLOCK_ENABLE
+	/* Set CLOCK_ENABLE */
 	if (ios->clock)
 		mci_con |= S3C2410_SDICON_CLOCKTYPE;
 	else
-		mci_con &=~S3C2410_SDICON_CLOCKTYPE;
+		mci_con &= ~S3C2410_SDICON_CLOCKTYPE;
 
 	writel(mci_con, host->base + S3C2410_SDICON);
 
-	if ((ios->power_mode==MMC_POWER_ON)
-		|| (ios->power_mode==MMC_POWER_UP)) {
-
+	if ((ios->power_mode == MMC_POWER_ON) ||
+	    (ios->power_mode == MMC_POWER_UP)) {
 		dbg(host, dbg_conf, "running at %lukHz (requested: %ukHz).\n",
 			host->real_rate/1000, ios->clock/1000);
 	} else {
@@ -1053,7 +1049,6 @@ static void s3cmci_set_ios(struct mmc_ho
 	}
 
 	host->bus_width = ios->bus_width;
-
 }
 
 static void s3cmci_reset(struct s3cmci_host *host)
@@ -1061,7 +1056,6 @@ static void s3cmci_reset(struct s3cmci_h
 	u32 con = readl(host->base + S3C2410_SDICON);
 
 	con |= S3C2440_SDICON_SDRESET;
-
 	writel(con, host->base + S3C2410_SDICON);
 }
 
@@ -1086,20 +1080,21 @@ static int s3cmci_probe(struct platform_
 	host = mmc_priv(mmc);
 	host->mmc 	= mmc;
 	host->pdev	= pdev;
+	host->is2440	= is2440;
 
 	spin_lock_init(&host->complete_lock);
 	tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host);
+
 	if (is2440) {
-		host->is2440	= 1;
 		host->sdiimsk	= S3C2440_SDIIMSK;
 		host->sdidata	= S3C2440_SDIDATA;
 		host->clk_div	= 1;
 	} else {
-		host->is2440	= 0;
 		host->sdiimsk	= S3C2410_SDIIMSK;
 		host->sdidata	= S3C2410_SDIDATA;
 		host->clk_div	= 2;
 	}
+
 	host->dodma		= 0;
 	host->complete_what 	= COMPLETION_NONE;
 	host->pio_active 	= XFER_NONE;
@@ -1153,7 +1148,6 @@ static int s3cmci_probe(struct platform_
 	if (request_irq(host->irq_cd, s3cmci_irq_cd, 0, DRIVER_NAME, host)) {
 		dev_err(&pdev->dev,
 			"failed to request card detect interrupt.\n");
-
 		ret = -ENOENT;
 		goto probe_free_irq;
 	}
@@ -1172,7 +1166,8 @@ static int s3cmci_probe(struct platform_
 		goto probe_free_host;
 	}
 
-	if ((ret = clk_enable(host->clk))) {
+	ret = clk_enable(host->clk);
+	if (ret) {
 		dev_err(&pdev->dev, "failed to enable clock source.\n");
 		goto clk_free;
 	}
@@ -1193,18 +1188,20 @@ static int s3cmci_probe(struct platform_
 	mmc->max_phys_segs	= 128;
 	mmc->max_hw_segs	= 128;
 
-	dbg(host, dbg_debug, "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%u.\n",
-		(host->is2440?"2440":""),
-		host->base, host->irq, host->irq_cd, host->dma);
+	dbg(host, dbg_debug,
+	    "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%u.\n",
+	    (host->is2440?"2440":""),
+	    host->base, host->irq, host->irq_cd, host->dma);
 
-	if ((ret = mmc_add_host(mmc))) {
+	ret = mmc_add_host(mmc);
+	if (ret) {
 		dev_err(&pdev->dev, "failed to add mmc host.\n");
 		goto free_dmabuf;
 	}
 
 	platform_set_drvdata(pdev, mmc);
+	dev_info(&pdev->dev, "initialisation done.\n");
 
-	dev_info(&pdev->dev,"initialisation done.\n");
 	return 0;
 
  free_dmabuf:
@@ -1214,10 +1211,10 @@ static int s3cmci_probe(struct platform_
 	clk_put(host->clk);
 
  probe_free_irq_cd:
- 	free_irq(host->irq_cd, host);
+	free_irq(host->irq_cd, host);
 
  probe_free_irq:
- 	free_irq(host->irq, host);
+	free_irq(host->irq, host);
 
  probe_iounmap:
 	iounmap(host->base);
@@ -1237,14 +1234,19 @@ static int s3cmci_remove(struct platform
 	struct s3cmci_host 	*host = mmc_priv(mmc);
 
 	mmc_remove_host(mmc);
+
 	clk_disable(host->clk);
 	clk_put(host->clk);
- 	free_irq(host->irq_cd, host);
- 	free_irq(host->irq, host);
+
+	tasklet_disable(&host->pio_tasklet);
+
+	free_irq(host->irq_cd, host);
+	free_irq(host->irq, host);
+
 	iounmap(host->base);
 	release_mem_region(host->mem->start, RESSIZE(host->mem));
-	mmc_free_host(mmc);
 
+	mmc_free_host(mmc);
 	return 0;
 }
 
@@ -1285,27 +1287,27 @@ static int s3cmci_resume(struct platform
 #endif /* CONFIG_PM */
 
 
-static struct platform_driver s3cmci_driver_2410 =
-{
+static struct platform_driver s3cmci_driver_2410 = {
 	.driver.name	= "s3c2410-sdi",
+	.driver.owner	= THIS_MODULE,
 	.probe		= s3cmci_probe_2410,
 	.remove		= s3cmci_remove,
 	.suspend	= s3cmci_suspend,
 	.resume		= s3cmci_resume,
 };
 
-static struct platform_driver s3cmci_driver_2412 =
-{
+static struct platform_driver s3cmci_driver_2412 = {
 	.driver.name	= "s3c2412-sdi",
+	.driver.owner	= THIS_MODULE,
 	.probe		= s3cmci_probe_2412,
 	.remove		= s3cmci_remove,
 	.suspend	= s3cmci_suspend,
 	.resume		= s3cmci_resume,
 };
 
-static struct platform_driver s3cmci_driver_2440 =
-{
+static struct platform_driver s3cmci_driver_2440 = {
 	.driver.name	= "s3c2440-sdi",
+	.driver.owner	= THIS_MODULE,
 	.probe		= s3cmci_probe_2440,
 	.remove		= s3cmci_remove,
 	.suspend	= s3cmci_suspend,
@@ -1334,4 +1336,3 @@ module_exit(s3cmci_exit);
 MODULE_DESCRIPTION("Samsung S3C MMC/SD Card Interface driver");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Thomas Kleffel <tk@maintech.de>");
-
Index: linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.h
===================================================================
--- linux-2.6.26-rc5-q2.orig/drivers/mmc/host/s3cmci.h	2008-06-07 12:25:27.000000000 +0100
+++ linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.h	2008-06-16 15:13:28.000000000 +0100
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  */
 
-//FIXME: DMA Resource management ?!
+/* FIXME: DMA Resource management ?! */
 #define S3CMCI_DMA 0
 
 enum s3cmci_waitfor {
@@ -39,32 +39,30 @@ struct s3cmci_host {
 	unsigned		sdiimsk;
 	unsigned		sdidata;
 	int			dodma;
-
-	volatile int		dmatogo;
+	int			dmatogo;
 
 	struct mmc_request	*mrq;
 	int			cmd_is_stop;
 
 	spinlock_t		complete_lock;
-	volatile enum s3cmci_waitfor
-				complete_what;
+	enum s3cmci_waitfor	complete_what;
 
-	volatile int		dma_complete;
+	int			dma_complete;
 
-	volatile u32		pio_sgptr;
-	volatile u32		pio_words;
-	volatile u32		pio_count;
-	volatile u32		*pio_ptr;
+	u32			pio_sgptr;
+	u32			pio_words;
+	u32			pio_count;
+	u32			*pio_ptr;
 #define XFER_NONE 0
 #define XFER_READ 1
 #define XFER_WRITE 2
-	volatile u32		pio_active;
+	u32			pio_active;
 
 	int			bus_width;
 
 	char 			dbgmsg_cmd[301];
 	char 			dbgmsg_dat[301];
-	volatile char		*status;
+	char			*status;
 
 	unsigned int		ccnt, dcnt;
 	struct tasklet_struct	pio_tasklet;

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [patch v2 03/16] MMC: S3C24XX MMC/SD driver write fixes
  2008-06-16 14:34 [patch v2 00/16] S3C24XX SD/MMC driver Ben Dooks
  2008-06-16 14:34 ` [patch v2 01/16] MMC: S3C24XX MMC/SD driver Ben Dooks
  2008-06-16 14:34 ` [patch v2 02/16] MMC: S3C24XX: Fix the checkpatch.pl errors in the s3cmci driver Ben Dooks
@ 2008-06-16 14:34 ` Ben Dooks
  2008-06-16 14:34 ` [patch v2 04/16] MMC: DMA free fix for S3C24XX SD/MMC driver Ben Dooks
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Ben Dooks @ 2008-06-16 14:34 UTC (permalink / raw)
  To: linux-kernel; +Cc: drzeus-mmc, Ben Dooks

[-- Attachment #1: thirdparty/openmoko-mci/s3cmci_dbg.patch --]
[-- Type: text/plain, Size: 1096 bytes --]

From: Harald Welte <laforge@openmoko.org>

This patch is a workaround of some S3C2410 MMC chip bug

Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Index: linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c
===================================================================
--- linux-2.6.26-rc5-q2.orig/drivers/mmc/host/s3cmci.c	2008-06-16 14:19:18.000000000 +0100
+++ linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c	2008-06-16 14:19:44.000000000 +0100
@@ -454,11 +454,17 @@ static irqreturn_t s3cmci_irq(int irq, v
 
 	if (mci_csta & S3C2410_SDICMDSTAT_CRCFAIL) {
 		if (cmd->flags & MMC_RSP_CRC) {
-			cmd->error = MMC_ERR_BADCRC;
-			host->status = "error: bad command crc";
-			goto fail_transfer;
+			if (host->mrq->cmd->flags & MMC_RSP_136) {
+				dbg(host, dbg_irq,
+				    "fixup: ignore CRC fail with long rsp\n");
+			} else {
+#if 0
+				cmd->error = MMC_ERR_BADCRC;
+				host->status = "error: bad command crc";
+				goto fail_transfer;
+#endif
+			}
 		}
-
 		mci_cclear |= S3C2410_SDICMDSTAT_CRCFAIL;
 	}
 

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [patch v2 04/16] MMC: DMA free fix for S3C24XX SD/MMC driver
  2008-06-16 14:34 [patch v2 00/16] S3C24XX SD/MMC driver Ben Dooks
                   ` (2 preceding siblings ...)
  2008-06-16 14:34 ` [patch v2 03/16] MMC: S3C24XX MMC/SD driver write fixes Ben Dooks
@ 2008-06-16 14:34 ` Ben Dooks
  2008-06-16 14:34 ` [patch v2 05/16] MMC: S3C24XX MMC/SD stop fix Ben Dooks
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Ben Dooks @ 2008-06-16 14:34 UTC (permalink / raw)
  To: linux-kernel; +Cc: drzeus-mmc, Ben Dooks

[-- Attachment #1: thirdparty/openmoko-mci/s3cmci-dma-free.patch --]
[-- Type: text/plain, Size: 769 bytes --]

From: Harald Welte <laforge@openmoko.org>

Bugfix to ensure DMA channel allocated is freed on exit.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Index: linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c
===================================================================
--- linux-2.6.26-rc5-q2.orig/drivers/mmc/host/s3cmci.c	2008-06-16 15:24:51.000000000 +0100
+++ linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c	2008-06-16 15:24:52.000000000 +0100
@@ -1245,6 +1245,7 @@ static int s3cmci_remove(struct platform
 	clk_put(host->clk);
 
 	tasklet_disable(&host->pio_tasklet);
+	s3c2410_dma_free(S3CMCI_DMA, &s3cmci_dma_client);
 
 	free_irq(host->irq_cd, host);
 	free_irq(host->irq, host);

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [patch v2 05/16] MMC: S3C24XX MMC/SD stop fix
  2008-06-16 14:34 [patch v2 00/16] S3C24XX SD/MMC driver Ben Dooks
                   ` (3 preceding siblings ...)
  2008-06-16 14:34 ` [patch v2 04/16] MMC: DMA free fix for S3C24XX SD/MMC driver Ben Dooks
@ 2008-06-16 14:34 ` Ben Dooks
  2008-06-16 14:34 ` [patch v2 06/16] MMC: Fix S3C24XX IRQ enable during PIO transfers Ben Dooks
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Ben Dooks @ 2008-06-16 14:34 UTC (permalink / raw)
  To: linux-kernel; +Cc: drzeus-mmc, Ben Dooks, Harald Welte

[-- Attachment #1: thirdparty/openmoko-mci/s3cmci-stop-fix.patch --]
[-- Type: text/plain, Size: 1223 bytes --]

From: Thomas Kleffel <tk@maintech.de>

Fix the request finalisation by ensuring the controller
is stopped.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Harald Welte <laforge@openmoko.org>

Index: linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c
===================================================================
--- linux-2.6.26-rc5-q2.orig/drivers/mmc/host/s3cmci.c	2008-06-16 15:24:52.000000000 +0100
+++ linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c	2008-06-16 15:24:55.000000000 +0100
@@ -667,7 +667,7 @@ static void finalize_request(struct s3cm
 #endif
 	/* Cleanup controller */
 	writel(0, host->base + S3C2410_SDICMDARG);
-	writel(0, host->base + S3C2410_SDIDCON);
+	writel(S3C2410_SDIDCON_STOP, host->base + S3C2410_SDIDCON);
 	writel(0, host->base + S3C2410_SDICMDCON);
 	writel(0, host->base + host->sdiimsk);
 
@@ -793,7 +793,7 @@ static int s3cmci_setup_data(struct s3cm
 		dbg(host, dbg_err,
 		    "mci_setup_data() transfer stillin progress.\n");
 
-		writel(0, host->base + S3C2410_SDIDCON);
+		writel(S3C2410_SDIDCON_STOP, host->base + S3C2410_SDIDCON);
 		s3cmci_reset(host);
 
 		if ((stoptries--) == 0) {

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [patch v2 06/16] MMC: Fix S3C24XX IRQ enable during PIO transfers
  2008-06-16 14:34 [patch v2 00/16] S3C24XX SD/MMC driver Ben Dooks
                   ` (4 preceding siblings ...)
  2008-06-16 14:34 ` [patch v2 05/16] MMC: S3C24XX MMC/SD stop fix Ben Dooks
@ 2008-06-16 14:34 ` Ben Dooks
  2008-06-16 14:34 ` [patch v2 07/16] MMC: S3C24XX: Add platform data for MMC/SD driver Ben Dooks
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Ben Dooks @ 2008-06-16 14:34 UTC (permalink / raw)
  To: linux-kernel; +Cc: drzeus-mmc, Ben Dooks

[-- Attachment #1: thirdparty/openmoko-mci/s3cmci-unfinished-write-fix.patch --]
[-- Type: text/plain, Size: 966 bytes --]

From: Roman Moracik <roman.moravcik@gmail.com> 

Fix Bug #677 - I/O errors on heavy microSD writes for 2.6.22.x.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Index: linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c
===================================================================
--- linux-2.6.26-rc5-q2.orig/drivers/mmc/host/s3cmci.c	2008-06-08 13:57:35.000000000 +0100
+++ linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c	2008-06-08 13:57:37.000000000 +0100
@@ -327,6 +327,7 @@ static void pio_tasklet(unsigned long da
 {
 	struct s3cmci_host *host = (struct s3cmci_host *) data;
 
+	disable_irq(host->irq);
 
 	if (host->pio_active == XFER_WRITE)
 		do_pio_write(host);
@@ -345,9 +346,9 @@ static void pio_tasklet(unsigned long da
 			host->mrq->data->error = MMC_ERR_DMA;
 		}
 
-		disable_irq(host->irq);
 		finalize_request(host);
-	}
+	} else
+		enable_irq(host->irq);
 }
 
 /*

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [patch v2 07/16] MMC: S3C24XX: Add platform data for MMC/SD driver
  2008-06-16 14:34 [patch v2 00/16] S3C24XX SD/MMC driver Ben Dooks
                   ` (5 preceding siblings ...)
  2008-06-16 14:34 ` [patch v2 06/16] MMC: Fix S3C24XX IRQ enable during PIO transfers Ben Dooks
@ 2008-06-16 14:34 ` Ben Dooks
  2008-06-16 14:34 ` [patch v2 08/16] MMC: S3C24XX: Add support to invert write protect line Ben Dooks
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Ben Dooks @ 2008-06-16 14:34 UTC (permalink / raw)
  To: linux-kernel; +Cc: drzeus-mmc, Ben Dooks

[-- Attachment #1: thirdparty/openmoko-mci/s3c_mci_platform.patch --]
[-- Type: text/plain, Size: 4791 bytes --]

This patch adds platform data support to the s3mci driver.  This allows
flexible board-specific configuration of set_power, card detect and read only
pins.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Index: linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c
===================================================================
--- linux-2.6.26-rc5-q2.orig/drivers/mmc/host/s3cmci.c	2008-06-16 15:24:57.000000000 +0100
+++ linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c	2008-06-16 15:24:59.000000000 +0100
@@ -21,6 +21,7 @@
 
 #include <asm/arch/regs-sdi.h>
 #include <asm/arch/regs-gpio.h>
+#include <asm/arch/mci.h>
 
 #include "s3cmci.h"
 
@@ -1005,6 +1006,9 @@ static void s3cmci_set_ios(struct mmc_ho
 		s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2);
 		s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3);
 
+		if (host->pdata->set_power)
+			host->pdata->set_power(ios->power_mode, ios->vdd);
+
 		if (!host->is2440)
 			mci_con |= S3C2410_SDICON_FIFORESET;
 
@@ -1018,6 +1022,9 @@ static void s3cmci_set_ios(struct mmc_ho
 		if (host->is2440)
 			mci_con |= S3C2440_SDICON_SDRESET;
 
+		if (host->pdata->set_power)
+			host->pdata->set_power(ios->power_mode, ios->vdd);
+
 		break;
 	}
 
@@ -1066,9 +1073,26 @@ static void s3cmci_reset(struct s3cmci_h
 	writel(con, host->base + S3C2410_SDICON);
 }
 
+static int s3cmci_get_ro(struct mmc_host *mmc)
+{
+	struct s3cmci_host *host = mmc_priv(mmc);
+
+	if (host->pdata->gpio_wprotect == 0)
+		return 0;
+
+	return s3c2410_gpio_getpin(host->pdata->gpio_wprotect);
+}
+
 static struct mmc_host_ops s3cmci_ops = {
 	.request	= s3cmci_request,
 	.set_ios	= s3cmci_set_ios,
+	.get_ro		= s3cmci_get_ro,
+};
+
+static struct s3c24xx_mci_pdata s3cmci_def_pdata = {
+	.gpio_detect	= 0,
+	.set_power	= NULL,
+	.ocr_avail	= MMC_VDD_32_33,
 };
 
 static int s3cmci_probe(struct platform_device *pdev, int is2440)
@@ -1089,6 +1113,12 @@ static int s3cmci_probe(struct platform_
 	host->pdev	= pdev;
 	host->is2440	= is2440;
 
+	host->pdata = pdev->dev.platform_data;
+	if (!host->pdata) {
+		pdev->dev.platform_data = &s3cmci_def_pdata;
+		host->pdata = &s3cmci_def_pdata;
+	}
+
 	spin_lock_init(&host->complete_lock);
 	tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host);
 
@@ -1107,7 +1137,8 @@ static int s3cmci_probe(struct platform_
 	host->pio_active 	= XFER_NONE;
 
 	host->dma		= S3CMCI_DMA;
-	host->irq_cd		= IRQ_EINT2;
+	host->irq_cd = s3c2410_gpio_getirq(host->pdata->gpio_detect);
+	s3c2410_gpio_cfgpin(host->pdata->gpio_detect, S3C2410_GPIO_IRQ);
 
 	host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!host->mem) {
@@ -1149,7 +1180,7 @@ static int s3cmci_probe(struct platform_
 
 	disable_irq(host->irq);
 
-	s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_EINT2);
+	s3c2410_gpio_cfgpin(host->pdata->gpio_detect, S3C2410_GPIO_IRQ);
 	set_irq_type(host->irq_cd, IRQT_BOTHEDGE);
 
 	if (request_irq(host->irq_cd, s3cmci_irq_cd, 0, DRIVER_NAME, host)) {
@@ -1159,6 +1190,10 @@ static int s3cmci_probe(struct platform_
 		goto probe_free_irq;
 	}
 
+	if (host->pdata->gpio_wprotect)
+		s3c2410_gpio_cfgpin(host->pdata->gpio_wprotect,
+				    S3C2410_GPIO_INPUT);
+
 	if (s3c2410_dma_request(S3CMCI_DMA, &s3cmci_dma_client, NULL)) {
 		dev_err(&pdev->dev, "unable to get DMA channel.\n");
 		ret = -EBUSY;
@@ -1182,7 +1217,7 @@ static int s3cmci_probe(struct platform_
 	host->clk_rate = clk_get_rate(host->clk);
 
 	mmc->ops 	= &s3cmci_ops;
-	mmc->ocr_avail	= MMC_VDD_32_33;
+	mmc->ocr_avail	= host->pdata->ocr_avail;
 	mmc->caps	= MMC_CAP_4_BIT_DATA;
 	mmc->f_min 	= host->clk_rate / (host->clk_div * 256);
 	mmc->f_max 	= host->clk_rate / host->clk_div;
Index: linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.h
===================================================================
--- linux-2.6.26-rc5-q2.orig/drivers/mmc/host/s3cmci.h	2008-06-16 15:13:28.000000000 +0100
+++ linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.h	2008-06-16 15:24:59.000000000 +0100
@@ -22,6 +22,7 @@ enum s3cmci_waitfor {
 
 struct s3cmci_host {
 	struct platform_device	*pdev;
+	struct s3c24xx_mci_pdata *pdata;
 	struct mmc_host		*mmc;
 	struct resource		*mem;
 	struct clk		*clk;
Index: linux-2.6.26-rc5-q2/include/asm-arm/arch-s3c2410/mci.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.26-rc5-q2/include/asm-arm/arch-s3c2410/mci.h	2008-06-16 15:24:59.000000000 +0100
@@ -0,0 +1,12 @@
+#ifndef _ARCH_MCI_H
+#define _ARCH_MCI_H
+
+struct s3c24xx_mci_pdata {
+	unsigned int	gpio_detect;
+	unsigned int	gpio_wprotect;
+	unsigned long	ocr_avail;
+	void		(*set_power)(unsigned char power_mode,
+				     unsigned short vdd);
+};
+
+#endif /* _ARCH_NCI_H */

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [patch v2 08/16] MMC: S3C24XX: Add support to invert write protect line
  2008-06-16 14:34 [patch v2 00/16] S3C24XX SD/MMC driver Ben Dooks
                   ` (6 preceding siblings ...)
  2008-06-16 14:34 ` [patch v2 07/16] MMC: S3C24XX: Add platform data for MMC/SD driver Ben Dooks
@ 2008-06-16 14:34 ` Ben Dooks
  2008-06-16 14:34 ` [patch v2 09/16] MMC: S3C24XX: Ensure host->mrq->data is valid Ben Dooks
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Ben Dooks @ 2008-06-16 14:34 UTC (permalink / raw)
  To: linux-kernel; +Cc: drzeus-mmc, Ben Dooks

[-- Attachment #1: simtec/s3c24xx-sdmmc-roinvert.patch --]
[-- Type: text/plain, Size: 1554 bytes --]

Support for inverting the sense of the MMC driver's write
protect detection line.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Index: linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c
===================================================================
--- linux-2.6.26-rc5-q2.orig/drivers/mmc/host/s3cmci.c	2008-06-16 15:24:59.000000000 +0100
+++ linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c	2008-06-16 15:25:01.000000000 +0100
@@ -1076,11 +1076,18 @@ static void s3cmci_reset(struct s3cmci_h
 static int s3cmci_get_ro(struct mmc_host *mmc)
 {
 	struct s3cmci_host *host = mmc_priv(mmc);
+	struct s3c24xx_mci_pdata *pdata = host->pdata;
+	int ret;
 
-	if (host->pdata->gpio_wprotect == 0)
+	if (pdata->gpio_wprotect == 0)
 		return 0;
 
-	return s3c2410_gpio_getpin(host->pdata->gpio_wprotect);
+	ret = s3c2410_gpio_getpin(pdata->gpio_wprotect);
+
+	if (pdata->wprotect_invert)
+		ret = !ret;
+
+	return ret;
 }
 
 static struct mmc_host_ops s3cmci_ops = {
Index: linux-2.6.26-rc5-q2/include/asm-arm/arch-s3c2410/mci.h
===================================================================
--- linux-2.6.26-rc5-q2.orig/include/asm-arm/arch-s3c2410/mci.h	2008-06-16 15:24:59.000000000 +0100
+++ linux-2.6.26-rc5-q2/include/asm-arm/arch-s3c2410/mci.h	2008-06-16 15:25:01.000000000 +0100
@@ -2,6 +2,8 @@
 #define _ARCH_MCI_H
 
 struct s3c24xx_mci_pdata {
+	unsigned int	wprotect_invert : 1;
+
 	unsigned int	gpio_detect;
 	unsigned int	gpio_wprotect;
 	unsigned long	ocr_avail;

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [patch v2 09/16] MMC: S3C24XX: Ensure host->mrq->data is valid
  2008-06-16 14:34 [patch v2 00/16] S3C24XX SD/MMC driver Ben Dooks
                   ` (7 preceding siblings ...)
  2008-06-16 14:34 ` [patch v2 08/16] MMC: S3C24XX: Add support to invert write protect line Ben Dooks
@ 2008-06-16 14:34 ` Ben Dooks
  2008-06-16 14:34 ` [patch v2 10/16] MMC: S3C24XX: Allow card-detect on non-IRQ capable pin Ben Dooks
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Ben Dooks @ 2008-06-16 14:34 UTC (permalink / raw)
  To: linux-kernel; +Cc: drzeus-mmc, Ben Dooks

[-- Attachment #1: simtec/s3c24xx-sdmmc-piotasklet-crashfix.patch --]
[-- Type: text/plain, Size: 799 bytes --]

Fix a crash if host->mrq->data is NULL on ending a transfer.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Index: linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c
===================================================================
--- linux-2.6.26-rc5-q2.orig/drivers/mmc/host/s3cmci.c	2008-06-08 13:59:17.000000000 +0100
+++ linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c	2008-06-08 13:59:20.000000000 +0100
@@ -344,7 +344,8 @@ static void pio_tasklet(unsigned long da
 			    (host->pio_active == XFER_READ) ? "read" : "write",
 			    host->pio_count, host->pio_words);
 
-			host->mrq->data->error = MMC_ERR_DMA;
+			if (host->mrq->data)
+				host->mrq->data->error = MMC_ERR_DMA;
 		}
 
 		finalize_request(host);

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [patch v2 10/16] MMC: S3C24XX: Allow card-detect on non-IRQ capable pin
  2008-06-16 14:34 [patch v2 00/16] S3C24XX SD/MMC driver Ben Dooks
                   ` (8 preceding siblings ...)
  2008-06-16 14:34 ` [patch v2 09/16] MMC: S3C24XX: Ensure host->mrq->data is valid Ben Dooks
@ 2008-06-16 14:34 ` Ben Dooks
  2008-06-16 14:34 ` [patch v2 11/16] MMC: S3C24XX: Fix s3c2410_dma_request() return code check Ben Dooks
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Ben Dooks @ 2008-06-16 14:34 UTC (permalink / raw)
  To: linux-kernel; +Cc: drzeus-mmc, Ben Dooks

[-- Attachment #1: simtec/s3c24xx-sdmmc-nocdirq.patch --]
[-- Type: text/plain, Size: 2325 bytes --]

Add support to the S3C24XX MMC driver to have the card detect be on
a pin that is not IRQ capable.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Index: linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c
===================================================================
--- linux-2.6.26-rc5-q2.orig/drivers/mmc/host/s3cmci.c	2008-06-16 15:25:03.000000000 +0100
+++ linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c	2008-06-16 15:25:04.000000000 +0100
@@ -1145,8 +1145,6 @@ static int s3cmci_probe(struct platform_
 	host->pio_active 	= XFER_NONE;
 
 	host->dma		= S3CMCI_DMA;
-	host->irq_cd = s3c2410_gpio_getirq(host->pdata->gpio_detect);
-	s3c2410_gpio_cfgpin(host->pdata->gpio_detect, S3C2410_GPIO_IRQ);
 
 	host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!host->mem) {
@@ -1188,14 +1186,20 @@ static int s3cmci_probe(struct platform_
 
 	disable_irq(host->irq);
 
-	s3c2410_gpio_cfgpin(host->pdata->gpio_detect, S3C2410_GPIO_IRQ);
-	set_irq_type(host->irq_cd, IRQT_BOTHEDGE);
+	host->irq_cd = s3c2410_gpio_getirq(host->pdata->gpio_detect);
 
-	if (request_irq(host->irq_cd, s3cmci_irq_cd, 0, DRIVER_NAME, host)) {
-		dev_err(&pdev->dev,
-			"failed to request card detect interrupt.\n");
-		ret = -ENOENT;
-		goto probe_free_irq;
+	if (host->irq_cd >= 0) {
+		if (request_irq(host->irq_cd, s3cmci_irq_cd,
+				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+				DRIVER_NAME, host)) {
+			dev_err(&pdev->dev, "can't get card detect irq.\n");
+			ret = -ENOENT;
+			goto probe_free_irq;
+		}
+	} else {
+		dev_warn(&pdev->dev, "host detect has no irq available\n");
+		s3c2410_gpio_cfgpin(host->pdata->gpio_detect,
+				    S3C2410_GPIO_INPUT);
 	}
 
 	if (host->pdata->gpio_wprotect)
@@ -1261,7 +1265,8 @@ static int s3cmci_probe(struct platform_
 	clk_put(host->clk);
 
  probe_free_irq_cd:
-	free_irq(host->irq_cd, host);
+	if (host->irq_cd >= 0)
+		free_irq(host->irq_cd, host);
 
  probe_free_irq:
 	free_irq(host->irq, host);
@@ -1291,7 +1296,8 @@ static int s3cmci_remove(struct platform
 	tasklet_disable(&host->pio_tasklet);
 	s3c2410_dma_free(S3CMCI_DMA, &s3cmci_dma_client);
 
-	free_irq(host->irq_cd, host);
+	if (host->irq_cd >= 0)
+		free_irq(host->irq_cd, host);
 	free_irq(host->irq, host);
 
 	iounmap(host->base);

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [patch v2 11/16] MMC: S3C24XX: Fix s3c2410_dma_request() return code check.
  2008-06-16 14:34 [patch v2 00/16] S3C24XX SD/MMC driver Ben Dooks
                   ` (9 preceding siblings ...)
  2008-06-16 14:34 ` [patch v2 10/16] MMC: S3C24XX: Allow card-detect on non-IRQ capable pin Ben Dooks
@ 2008-06-16 14:34 ` Ben Dooks
  2008-06-16 14:34 ` [patch v2 12/16] MMC: S3C24XX: Fix MMC return codes Ben Dooks
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Ben Dooks @ 2008-06-16 14:34 UTC (permalink / raw)
  To: linux-kernel; +Cc: drzeus-mmc, Ben Dooks

[-- Attachment #1: simtec/s3c24xx-sdmmc-dma-retcode-fix.patch --]
[-- Type: text/plain, Size: 993 bytes --]

The driver should be checking for a negative error code from
s3c2410_dma_request(), not non-zero. Newer kernels now return
the DMA channel number that was allocated by the request.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Index: linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c
===================================================================
--- linux-2.6.26-rc5-q2.orig/drivers/mmc/host/s3cmci.c	2008-06-16 15:25:04.000000000 +0100
+++ linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c	2008-06-16 15:25:06.000000000 +0100
@@ -1206,7 +1206,7 @@ static int s3cmci_probe(struct platform_
 		s3c2410_gpio_cfgpin(host->pdata->gpio_wprotect,
 				    S3C2410_GPIO_INPUT);
 
-	if (s3c2410_dma_request(S3CMCI_DMA, &s3cmci_dma_client, NULL)) {
+	if (s3c2410_dma_request(S3CMCI_DMA, &s3cmci_dma_client, NULL) < 0) {
 		dev_err(&pdev->dev, "unable to get DMA channel.\n");
 		ret = -EBUSY;
 		goto probe_free_irq_cd;

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [patch v2 12/16] MMC: S3C24XX: Fix MMC return codes.
  2008-06-16 14:34 [patch v2 00/16] S3C24XX SD/MMC driver Ben Dooks
                   ` (10 preceding siblings ...)
  2008-06-16 14:34 ` [patch v2 11/16] MMC: S3C24XX: Fix s3c2410_dma_request() return code check Ben Dooks
@ 2008-06-16 14:34 ` Ben Dooks
  2008-06-16 14:34 ` [patch v2 13/16] MMC: S3C24XX: MMC/SD driver fix use of sg lists Ben Dooks
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Ben Dooks @ 2008-06-16 14:34 UTC (permalink / raw)
  To: linux-kernel; +Cc: drzeus-mmc, Ben Dooks

[-- Attachment #1: simtec/s3c24xx-sdmmc-retcode-fixes.patch --]
[-- Type: text/plain, Size: 945 bytes --]

Fix the error codes

Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Index: linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c
===================================================================
--- linux-2.6.26-rc5-q2.orig/drivers/mmc/host/s3cmci.c	2008-06-08 14:02:32.000000000 +0100
+++ linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c	2008-06-08 14:02:34.000000000 +0100
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <linux/clk.h>
+#include <linux/mmc/core.h>
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/host.h>
 #include <linux/platform_device.h>
@@ -27,6 +28,12 @@
 
 #define DRIVER_NAME "s3c-mci"
 
+#define MMC_ERR_NONE	(0)
+#define MMC_ERR_DMA	EINVAL
+#define MMC_ERR_TIMEOUT ETIMEDOUT
+#define MMC_ERR_BADCRC	EILSEQ
+#define MMC_ERR_FIFO	EILSEQ
+
 enum dbg_channels {
 	dbg_err   = (1 << 0),
 	dbg_debug = (1 << 1),

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [patch v2 13/16] MMC: S3C24XX: MMC/SD driver fix use of sg lists.
  2008-06-16 14:34 [patch v2 00/16] S3C24XX SD/MMC driver Ben Dooks
                   ` (11 preceding siblings ...)
  2008-06-16 14:34 ` [patch v2 12/16] MMC: S3C24XX: Fix MMC return codes Ben Dooks
@ 2008-06-16 14:34 ` Ben Dooks
  2008-06-16 14:34 ` [patch v2 14/16] MMC: S3C24XX: Add MODULE_ALIAS() entries for the platform devices Ben Dooks
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Ben Dooks @ 2008-06-16 14:34 UTC (permalink / raw)
  To: linux-kernel; +Cc: drzeus-mmc, Ben Dooks

[-- Attachment #1: simtec/s3c24xx-sdmmc-2624-fixes.patch --]
[-- Type: text/plain, Size: 707 bytes --]

Fix sg_ usage in the S3C24XX MMC driver.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Index: linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c
===================================================================
--- linux-2.6.26-rc5-q2.orig/drivers/mmc/host/s3cmci.c	2008-06-08 14:02:34.000000000 +0100
+++ linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c	2008-06-08 14:02:36.000000000 +0100
@@ -205,7 +205,7 @@ static inline int get_data_buffer(struct
 	sg = &host->mrq->data->sg[host->pio_sgptr];
 
 	*words = sg->length >> 2;
-	*pointer = page_address(sg->page) + sg->offset;
+	*pointer = sg_virt(sg);
 
 	host->pio_sgptr++;
 

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [patch v2 14/16] MMC: S3C24XX: Add MODULE_ALIAS() entries for the platform devices
  2008-06-16 14:34 [patch v2 00/16] S3C24XX SD/MMC driver Ben Dooks
                   ` (12 preceding siblings ...)
  2008-06-16 14:34 ` [patch v2 13/16] MMC: S3C24XX: MMC/SD driver fix use of sg lists Ben Dooks
@ 2008-06-16 14:34 ` Ben Dooks
  2008-06-16 14:35 ` [patch v2 15/16] MMC: S3C24XX: Fix use of msecs where jiffies are needed Ben Dooks
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Ben Dooks @ 2008-06-16 14:34 UTC (permalink / raw)
  To: linux-kernel; +Cc: drzeus-mmc, Ben Dooks

[-- Attachment #1: simtec/s3c24xx-sdmmc-modalias.patch --]
[-- Type: text/plain, Size: 821 bytes --]

Add MODULE_ALIAS() declerations for all the supported platform
devices for this driver.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Index: linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c
===================================================================
--- linux-2.6.26-rc5-q2.orig/drivers/mmc/host/s3cmci.c	2008-06-16 15:25:09.000000000 +0100
+++ linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c	2008-06-16 15:25:10.000000000 +0100
@@ -1400,3 +1400,6 @@ module_exit(s3cmci_exit);
 MODULE_DESCRIPTION("Samsung S3C MMC/SD Card Interface driver");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Thomas Kleffel <tk@maintech.de>");
+MODULE_ALIAS("platform:s3c2410-sdi");
+MODULE_ALIAS("platform:s3c2412-sdi");
+MODULE_ALIAS("platform:s3c2440-sdi");

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [patch v2 15/16] MMC: S3C24XX: Fix use of msecs where jiffies are needed
  2008-06-16 14:34 [patch v2 00/16] S3C24XX SD/MMC driver Ben Dooks
                   ` (13 preceding siblings ...)
  2008-06-16 14:34 ` [patch v2 14/16] MMC: S3C24XX: Add MODULE_ALIAS() entries for the platform devices Ben Dooks
@ 2008-06-16 14:35 ` Ben Dooks
  2008-06-16 14:35 ` [patch v2 16/16] MMC: S3C24XX: Add media presence test to request handling Ben Dooks
  2008-06-18 10:32 ` [patch v2 00/16] S3C24XX SD/MMC driver Pierre Ossman
  16 siblings, 0 replies; 19+ messages in thread
From: Ben Dooks @ 2008-06-16 14:35 UTC (permalink / raw)
  To: linux-kernel; +Cc: drzeus-mmc, Ben Dooks

[-- Attachment #1: simtec/s3c24xx-sdmmc-detectchangefix.patch --]
[-- Type: text/plain, Size: 762 bytes --]

mmc_detect_change() takes jiffies, not msecs. Convert the
previous value of msecs into jiffies before calling.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Index: linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c
===================================================================
--- linux-2.6.26-rc5-q2.orig/drivers/mmc/host/s3cmci.c	2008-06-08 14:03:03.000000000 +0100
+++ linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c	2008-06-08 14:03:08.000000000 +0100
@@ -578,7 +578,7 @@ static irqreturn_t s3cmci_irq_cd(int irq
 
 	dbg(host, dbg_irq, "card detect\n");
 
-	mmc_detect_change(host->mmc, 500);
+	mmc_detect_change(host->mmc, msecs_to_jiffies(500));
 
 	return IRQ_HANDLED;
 }

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [patch v2 16/16] MMC: S3C24XX: Add media presence test to request handling.
  2008-06-16 14:34 [patch v2 00/16] S3C24XX SD/MMC driver Ben Dooks
                   ` (14 preceding siblings ...)
  2008-06-16 14:35 ` [patch v2 15/16] MMC: S3C24XX: Fix use of msecs where jiffies are needed Ben Dooks
@ 2008-06-16 14:35 ` Ben Dooks
  2008-06-18 10:32 ` [patch v2 00/16] S3C24XX SD/MMC driver Pierre Ossman
  16 siblings, 0 replies; 19+ messages in thread
From: Ben Dooks @ 2008-06-16 14:35 UTC (permalink / raw)
  To: linux-kernel; +Cc: drzeus-mmc, Ben Dooks

[-- Attachment #1: simtec/s3c24xx-sdmmc-add-mediacheck.patch --]
[-- Type: text/plain, Size: 2123 bytes --]

Ensure that we have physical media present before attempting to
send a request to a card. This ensures that we do not get flooded
by errors from commands that can never be completed timing out.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Index: linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c
===================================================================
--- linux-2.6.26-rc5-q2.orig/drivers/mmc/host/s3cmci.c	2008-06-16 15:25:12.000000000 +0100
+++ linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c	2008-06-16 15:25:13.000000000 +0100
@@ -985,6 +985,20 @@ static void s3cmci_send_request(struct m
 	enable_irq(host->irq);
 }
 
+static int s3cmci_card_present(struct s3cmci_host *host)
+{
+	struct s3c24xx_mci_pdata *pdata = host->pdata;
+	int ret;
+
+	/* if we can't detect the presence, then always have card. */
+	if (pdata->gpio_detect == 0)
+		return 1;
+
+	ret = s3c2410_gpio_getpin(pdata->gpio_detect) ? 0 : 1;
+
+	return ret ^ pdata->detect_invert;
+}
+
 static void s3cmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
 	struct s3cmci_host *host = mmc_priv(mmc);
@@ -992,7 +1006,12 @@ static void s3cmci_request(struct mmc_ho
 	host->cmd_is_stop = 0;
 	host->mrq = mrq;
 
-	s3cmci_send_request(mmc);
+	if (!s3cmci_card_present(host)) {
+		dbg(host, dbg_err, "%s: no medium present\n", __func__);
+		host->mrq->cmd->error = -ENOMEDIUM;
+		mmc_request_done(mmc, mrq);
+	} else
+		s3cmci_send_request(mmc);
 }
 
 static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
Index: linux-2.6.26-rc5-q2/include/asm-arm/arch-s3c2410/mci.h
===================================================================
--- linux-2.6.26-rc5-q2.orig/include/asm-arm/arch-s3c2410/mci.h	2008-06-16 15:25:01.000000000 +0100
+++ linux-2.6.26-rc5-q2/include/asm-arm/arch-s3c2410/mci.h	2008-06-16 15:25:13.000000000 +0100
@@ -3,6 +3,7 @@
 
 struct s3c24xx_mci_pdata {
 	unsigned int	wprotect_invert : 1;
+	unsigned int	detect_invert : 1;   /* set => detect active high. */
 
 	unsigned int	gpio_detect;
 	unsigned int	gpio_wprotect;

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [patch v2 02/16] MMC: S3C24XX: Fix the checkpatch.pl errors in the s3cmci driver
  2008-06-16 14:34 ` [patch v2 02/16] MMC: S3C24XX: Fix the checkpatch.pl errors in the s3cmci driver Ben Dooks
@ 2008-06-16 15:07   ` Ben Dooks
  0 siblings, 0 replies; 19+ messages in thread
From: Ben Dooks @ 2008-06-16 15:07 UTC (permalink / raw)
  To: Ben Dooks; +Cc: linux-kernel, drzeus-mmc

Argh, forgot to merge the fix patch into this to make the
fifo changes correct. It should really be in this patch as
it makes the code badly incorrect.

----------------
MMC: S3C24XX: Fix the checkpatch.pl errors in the s3cmci driver

Fix the checkpatch and other problems pointed out by
akpm.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Index: linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c
===================================================================
--- linux-2.6.26-rc5-q2.orig/drivers/mmc/host/s3cmci.c	2008-06-07 12:25:20.000000000 +0100
+++ linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.c	2008-06-16 16:01:46.000000000 +0100
@@ -15,11 +15,10 @@
 #include <linux/mmc/host.h>
 #include <linux/platform_device.h>
 #include <linux/irq.h>
+#include <linux/io.h>
 
 #include <asm/dma.h>
-#include <asm/dma-mapping.h>
 
-#include <asm/io.h>
 #include <asm/arch/regs-sdi.h>
 #include <asm/arch/regs-gpio.h>
 
@@ -43,13 +42,15 @@ static const int dbgmap_err   = dbg_err 
 static const int dbgmap_info  = dbg_info | dbg_conf;
 static const int dbgmap_debug = dbg_debug;
 
-#define dbg(host, channels, args...)		 \
-	if (dbgmap_err & channels) 		 \
-		dev_err(&host->pdev->dev, args); \
-	else if (dbgmap_info & channels)	 \
-		dev_info(&host->pdev->dev, args);\
-	else if (dbgmap_debug & channels)	 \
-		dev_dbg(&host->pdev->dev, args);
+#define dbg(host, channels, args...)		  \
+	do {					  \
+	if (dbgmap_err & channels) 		  \
+		dev_err(&host->pdev->dev, args);  \
+	else if (dbgmap_info & channels)	  \
+		dev_info(&host->pdev->dev, args); \
+	else if (dbgmap_debug & channels)	  \
+		dev_dbg(&host->pdev->dev, args);  \
+	} while (0)
 
 #define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
 
@@ -63,7 +64,7 @@ static void s3cmci_reset(struct s3cmci_h
 
 #ifdef CONFIG_MMC_DEBUG
 
-static inline void dbg_dumpregs(struct s3cmci_host *host, char *prefix)
+static void dbg_dumpregs(struct s3cmci_host *host, char *prefix)
 {
 	u32 con, pre, cmdarg, cmdcon, cmdsta, r0, r1, r2, r3, timer, bsize;
 	u32 datcon, datcnt, datsta, fsta, imask;
@@ -103,17 +104,17 @@ static inline void dbg_dumpregs(struct s
 static void prepare_dbgmsg(struct s3cmci_host *host, struct mmc_command *cmd,
 								int stop)
 {
- 	snprintf(host->dbgmsg_cmd, 300,
-		"#%u%s op:%i arg:0x%08x flags:0x08%x retries:%u",
-		host->ccnt, (stop?" (STOP)":""),
-		cmd->opcode, cmd->arg, cmd->flags, cmd->retries);
+	snprintf(host->dbgmsg_cmd, 300,
+		 "#%u%s op:%i arg:0x%08x flags:0x08%x retries:%u",
+		 host->ccnt, (stop ? " (STOP)" : ""),
+		 cmd->opcode, cmd->arg, cmd->flags, cmd->retries);
 
 	if (cmd->data) {
 		snprintf(host->dbgmsg_dat, 300,
-			"#%u bsize:%u blocks:%u bytes:%u",
-			host->dcnt, cmd->data->blksz,
-			cmd->data->blocks,
-			cmd->data->blocks * cmd->data->blksz);
+			 "#%u bsize:%u blocks:%u bytes:%u",
+			 host->dcnt, cmd->data->blksz,
+			 cmd->data->blocks,
+			 cmd->data->blocks * cmd->data->blksz);
 	} else {
 		host->dbgmsg_dat[0] = '\0';
 	}
@@ -153,7 +154,7 @@ static inline u32 enable_imask(struct s3
 	u32 newmask;
 
 	newmask = readl(host->base + host->sdiimsk);
-	newmask|= imask;
+	newmask |= imask;
 
 	writel(newmask, host->base + host->sdiimsk);
 
@@ -165,7 +166,7 @@ static inline u32 disable_imask(struct s
 	u32 newmask;
 
 	newmask = readl(host->base + host->sdiimsk);
-	newmask&= ~imask;
+	newmask &= ~imask;
 
 	writel(newmask, host->base + host->sdiimsk);
 
@@ -178,7 +179,7 @@ static inline void clear_imask(struct s3
 }
 
 static inline int get_data_buffer(struct s3cmci_host *host,
-			volatile u32 *words, volatile u32 **pointer)
+				  u32 *words, u32 **pointer)
 {
 	struct scatterlist *sg;
 
@@ -195,69 +196,82 @@ static inline int get_data_buffer(struct
 	}
 	sg = &host->mrq->data->sg[host->pio_sgptr];
 
-	*words	= sg->length >> 2;
-	*pointer= page_address(sg->page) + sg->offset;
+	*words = sg->length >> 2;
+	*pointer = page_address(sg->page) + sg->offset;
 
 	host->pio_sgptr++;
 
 	dbg(host, dbg_sg, "new buffer (%i/%i)\n",
-	      host->pio_sgptr, host->mrq->data->sg_len);
+	    host->pio_sgptr, host->mrq->data->sg_len);
 
 	return 0;
 }
 
-#define FIFO_FILL(host) ((readl(host->base + S3C2410_SDIFSTA) & S3C2410_SDIFSTA_COUNTMASK) >> 2)
-#define FIFO_FREE(host) ((63 - (readl(host->base + S3C2410_SDIFSTA) & S3C2410_SDIFSTA_COUNTMASK)) >> 2)
+static inline u32 fifo_count(struct s3cmci_host *host)
+{
+	u32 fifostat = readl(host->base + S3C2410_SDIFSTA);
+
+	fifostat &= S3C2410_SDIFSTA_COUNTMASK;
+	return fifostat >> 2;
+}
+
+static inline u32 fifo_free(struct s3cmci_host *host)
+{
+	u32 fifostat = readl(host->base + S3C2410_SDIFSTA);
+
+	fifostat &= S3C2410_SDIFSTA_COUNTMASK;
+	return (63 - fifostat) >> 2;
+}
 
-static inline void do_pio_read(struct s3cmci_host *host)
+static void do_pio_read(struct s3cmci_host *host)
 {
 	int res;
 	u32 fifo;
 	void __iomem *from_ptr;
 
-	//write real prescaler to host, it might be set slow to fix
+	/* write real prescaler to host, it might be set slow to fix */
 	writel(host->prescaler, host->base + S3C2410_SDIPRE);
 
 	from_ptr = host->base + host->sdidata;
 
-	while ((fifo = FIFO_FILL(host))) {
+	while ((fifo = fifo_count(host))) {
 		if (!host->pio_words) {
 			res = get_data_buffer(host, &host->pio_words,
-							&host->pio_ptr);
+					      &host->pio_ptr);
 			if (res) {
 				host->pio_active = XFER_NONE;
 				host->complete_what = COMPLETION_FINALIZE;
 
 				dbg(host, dbg_pio, "pio_read(): "
-					"complete (no more data).\n");
+				    "complete (no more data).\n");
 				return;
 			}
 
-			dbg(host, dbg_pio, "pio_read(): new target: [%i]@[%p]\n",
-			       host->pio_words, host->pio_ptr);
+			dbg(host, dbg_pio,
+			    "pio_read(): new target: [%i]@[%p]\n",
+			    host->pio_words, host->pio_ptr);
 		}
 
-		dbg(host, dbg_pio, "pio_read(): fifo:[%02i] "
-				   "buffer:[%03i] dcnt:[%08X]\n",
-				   fifo, host->pio_words,
-				   readl(host->base + S3C2410_SDIDCNT));
+		dbg(host, dbg_pio,
+		    "pio_read(): fifo:[%02i] buffer:[%03i] dcnt:[%08X]\n",
+		    fifo, host->pio_words,
+		    readl(host->base + S3C2410_SDIDCNT));
 
 		if (fifo > host->pio_words)
 			fifo = host->pio_words;
 
-		host->pio_words-= fifo;
-		host->pio_count+= fifo;
+		host->pio_words -= fifo;
+		host->pio_count += fifo;
 
-		while(fifo--) {
+		while (fifo--)
 			*(host->pio_ptr++) = readl(from_ptr);
-		}
 	}
 
 	if (!host->pio_words) {
 		res = get_data_buffer(host, &host->pio_words, &host->pio_ptr);
 		if (res) {
-			dbg(host, dbg_pio, "pio_read(): "
-				"complete (no more buffers).\n");
+			dbg(host, dbg_pio,
+			    "pio_read(): complete (no more buffers).\n");
 			host->pio_active = XFER_NONE;
 			host->complete_what = COMPLETION_FINALIZE;
 
@@ -265,10 +279,11 @@ static inline void do_pio_read(struct s3
 		}
 	}
 
-	enable_imask(host, S3C2410_SDIIMSK_RXFIFOHALF | S3C2410_SDIIMSK_RXFIFOLAST);
+	enable_imask(host,
+		     S3C2410_SDIIMSK_RXFIFOHALF | S3C2410_SDIIMSK_RXFIFOLAST);
 }
 
-static inline void do_pio_write(struct s3cmci_host *host)
+static void do_pio_write(struct s3cmci_host *host)
 {
 	int res;
 	u32 fifo;
@@ -277,33 +292,32 @@ static inline void do_pio_write(struct s
 
 	to_ptr = host->base + host->sdidata;
 
-	while ((fifo = FIFO_FREE(host))) {
+	while ((fifo = fifo_free(host))) {
 		if (!host->pio_words) {
 			res = get_data_buffer(host, &host->pio_words,
 							&host->pio_ptr);
 			if (res) {
-				dbg(host, dbg_pio, "pio_write(): "
-					"complete (no more data).\n");
+				dbg(host, dbg_pio,
+				    "pio_write(): complete (no more data).\n");
 				host->pio_active = XFER_NONE;
 
 				return;
 			}
 
-			dbg(host, dbg_pio, "pio_write(): "
-				"new source: [%i]@[%p]\n",
-				host->pio_words, host->pio_ptr);
+			dbg(host, dbg_pio,
+			    "pio_write(): new source: [%i]@[%p]\n",
+			    host->pio_words, host->pio_ptr);
 
 		}
 
 		if (fifo > host->pio_words)
 			fifo = host->pio_words;
 
-		host->pio_words-= fifo;
-		host->pio_count+= fifo;
+		host->pio_words -= fifo;
+		host->pio_count += fifo;
 
-		while(fifo--) {
+		while (fifo--)
 			writel(*(host->pio_ptr++), to_ptr);
-		}
 	}
 
 	enable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);
@@ -324,9 +338,9 @@ static void pio_tasklet(unsigned long da
 		clear_imask(host);
 		if (host->pio_active != XFER_NONE) {
 			dbg(host, dbg_err, "unfinished %s "
-				"- pio_count:[%u] pio_words:[%u]\n",
-				(host->pio_active == XFER_READ)?"read":"write",
-				host->pio_count, host->pio_words);
+			    "- pio_count:[%u] pio_words:[%u]\n",
+			    (host->pio_active == XFER_READ) ? "read" : "write",
+			    host->pio_count, host->pio_words);
 
 			host->mrq->data->error = MMC_ERR_DMA;
 		}
@@ -340,7 +354,7 @@ static void pio_tasklet(unsigned long da
  * ISR for SDI Interface IRQ
  * Communication between driver and ISR works as follows:
  *   host->mrq 			points to current request
- *   host->complete_what	tells the ISR when the request is considered done
+ *   host->complete_what	Indicates when the request is considered done
  *     COMPLETION_CMDSENT	  when the command was sent
  *     COMPLETION_RSPFIN          when a response was received
  *     COMPLETION_XFERFINISH	  when the data transfer is finished
@@ -365,14 +379,12 @@ static void pio_tasklet(unsigned long da
 
 static irqreturn_t s3cmci_irq(int irq, void *dev_id)
 {
-	struct s3cmci_host *host;
+	struct s3cmci_host *host = dev_id;
 	struct mmc_command *cmd;
 	u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt, mci_imsk;
 	u32 mci_cclear, mci_dclear;
 	unsigned long iflags;
 
-	host = (struct s3cmci_host *)dev_id;
-
 	spin_lock_irqsave(&host->complete_lock, iflags);
 
 	mci_csta 	= readl(host->base + S3C2410_SDICMDSTAT);
@@ -384,7 +396,7 @@ static irqreturn_t s3cmci_irq(int irq, v
 	mci_dclear	= 0;
 
 	if ((host->complete_what == COMPLETION_NONE) ||
-			(host->complete_what == COMPLETION_FINALIZE)) {
+	    (host->complete_what == COMPLETION_FINALIZE)) {
 		host->status = "nothing to complete";
 		clear_imask(host);
 		goto irq_out;
@@ -396,7 +408,7 @@ static irqreturn_t s3cmci_irq(int irq, v
 		goto irq_out;
 	}
 
-	cmd = host->cmd_is_stop?host->mrq->stop:host->mrq->cmd;
+	cmd = host->cmd_is_stop ? host->mrq->stop : host->mrq->cmd;
 
 	if (!cmd) {
 		host->status = "no active cmd";
@@ -406,7 +418,7 @@ static irqreturn_t s3cmci_irq(int irq, v
 
 	if (!host->dodma) {
 		if ((host->pio_active == XFER_WRITE) &&
-				(mci_fsta & S3C2410_SDIFSTA_TFDET)) {
+		    (mci_fsta & S3C2410_SDIFSTA_TFDET)) {
 
 			disable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);
 			tasklet_schedule(&host->pio_tasklet);
@@ -414,10 +426,11 @@ static irqreturn_t s3cmci_irq(int irq, v
 		}
 
 		if ((host->pio_active == XFER_READ) &&
-				(mci_fsta & S3C2410_SDIFSTA_RFDET)) {
+		    (mci_fsta & S3C2410_SDIFSTA_RFDET)) {
 
 			disable_imask(host,
-				S3C2410_SDIIMSK_RXFIFOHALF | S3C2410_SDIIMSK_RXFIFOLAST);
+				      S3C2410_SDIIMSK_RXFIFOHALF |
+				      S3C2410_SDIIMSK_RXFIFOLAST);
 
 			tasklet_schedule(&host->pio_tasklet);
 			host->status = "pio rx";
@@ -506,9 +519,8 @@ static irqreturn_t s3cmci_irq(int irq, v
 			goto close_transfer;
 		}
 
-		if (host->complete_what == COMPLETION_XFERFINISH_RSPFIN) {
+		if (host->complete_what == COMPLETION_XFERFINISH_RSPFIN)
 			host->complete_what = COMPLETION_RSPFIN;
-		}
 
 		mci_dclear |= S3C2410_SDIDSTA_XFERFINISH;
 	}
@@ -531,10 +543,9 @@ close_transfer:
 	goto irq_out;
 
 irq_out:
-	dbg(host, dbg_irq, "csta:0x%08x dsta:0x%08x "
-			   "fsta:0x%08x dcnt:0x%08x status:%s.\n",
-				mci_csta, mci_dsta, mci_fsta,
-				mci_dcnt, host->status);
+	dbg(host, dbg_irq,
+	    "csta:0x%08x dsta:0x%08x fsta:0x%08x dcnt:0x%08x status:%s.\n",
+	    mci_csta, mci_dsta, mci_fsta, mci_dcnt, host->status);
 
 	spin_unlock_irqrestore(&host->complete_lock, iflags);
 	return IRQ_HANDLED;
@@ -557,7 +568,7 @@ static irqreturn_t s3cmci_irq_cd(int irq
 }
 
 void s3cmci_dma_done_callback(struct s3c2410_dma_chan *dma_ch, void *buf_id,
-	int size, enum s3c2410_dma_buffresult result)
+			      int size, enum s3c2410_dma_buffresult result)
 {
 	unsigned long iflags;
 	u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt;
@@ -568,11 +579,9 @@ void s3cmci_dma_done_callback(struct s3c
 	mci_fsta 	= readl(host->base + S3C2410_SDIFSTA);
 	mci_dcnt 	= readl(host->base + S3C2410_SDIDCNT);
 
-	if ((!host->mrq) || (!host->mrq) || (!host->mrq->data))
-		return;
-
-	if (!host->dmatogo)
-		return;
+	BUG_ON(!host->mrq);
+	BUG_ON(!host->mrq->data);
+	BUG_ON(!host->dmatogo);
 
 	spin_lock_irqsave(&host->complete_lock, iflags);
 
@@ -616,7 +625,7 @@ fail_request:
 static void finalize_request(struct s3cmci_host *host)
 {
 	struct mmc_request *mrq = host->mrq;
-	struct mmc_command *cmd = host->cmd_is_stop?mrq->stop:mrq->cmd;
+	struct mmc_command *cmd = host->cmd_is_stop ? mrq->stop : mrq->cmd;
 	int debug_as_failure = 0;
 
 	if (host->complete_what != COMPLETION_FINALIZE)
@@ -626,21 +635,19 @@ static void finalize_request(struct s3cm
 		return;
 
 	if (cmd->data && (cmd->error == MMC_ERR_NONE) &&
-		  (cmd->data->error == MMC_ERR_NONE)) {
-
+	    (cmd->data->error == MMC_ERR_NONE)) {
 		if (host->dodma && (!host->dma_complete)) {
 			dbg(host, dbg_dma, "DMA Missing!\n");
 			return;
 		}
 	}
 
-	// Read response
+	/* Read response from controller. */
 	cmd->resp[0] = readl(host->base + S3C2410_SDIRSP0);
 	cmd->resp[1] = readl(host->base + S3C2410_SDIRSP1);
 	cmd->resp[2] = readl(host->base + S3C2410_SDIRSP2);
 	cmd->resp[3] = readl(host->base + S3C2410_SDIRSP3);
 
-	// reset clock speed, as it could still be set low for
 	writel(host->prescaler, host->base + S3C2410_SDIPRE);
 
 	if (cmd->error)
@@ -649,12 +656,10 @@ static void finalize_request(struct s3cm
 	if (cmd->data && cmd->data->error)
 		debug_as_failure = 1;
 
-	//if(cmd->flags & MMC_RSP_MAYFAIL) debug_as_failure = 0;
-
 #ifdef CONFIG_MMC_DEBUG
 	dbg_dumpcmd(host, cmd, debug_as_failure);
 #endif
-	//Cleanup controller
+	/* Cleanup controller */
 	writel(0, host->base + S3C2410_SDICMDARG);
 	writel(0, host->base + S3C2410_SDIDCON);
 	writel(0, host->base + S3C2410_SDICMDCON);
@@ -669,12 +674,11 @@ static void finalize_request(struct s3cm
 		return;
 	}
 
-	// If we have no data transfer we are finished here
+	/* If we have no data transfer we are finished here */
 	if (!mrq->data)
 		goto request_done;
 
-	// Calulate the amout of bytes transfer, but only if there was
-	// no error
+	/* Calulate the amout of bytes transfer if there was no error */
 	if (mrq->data->error == MMC_ERR_NONE) {
 		mrq->data->bytes_xfered =
 			(mrq->data->blocks * mrq->data->blksz);
@@ -682,23 +686,23 @@ static void finalize_request(struct s3cm
 		mrq->data->bytes_xfered = 0;
 	}
 
-	// If we had an error while transfering data we flush the
-	// DMA channel and the fifo to clear out any garbage
+	/* If we had an error while transfering data we flush the
+	 * DMA channel and the fifo to clear out any garbage. */
 	if (mrq->data->error != MMC_ERR_NONE) {
 		if (host->dodma)
 			s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
 
 		if (host->is2440) {
-			//Clear failure register and reset fifo
+			/* Clear failure register and reset fifo. */
 			writel(S3C2440_SDIFSTA_FIFORESET |
 			       S3C2440_SDIFSTA_FIFOFAIL,
 			       host->base + S3C2410_SDIFSTA);
 		} else {
 			u32 mci_con;
 
-			//reset fifo
+			/* reset fifo */
 			mci_con = readl(host->base + S3C2410_SDICON);
-			mci_con|= S3C2410_SDICON_FIFORESET;
+			mci_con |= S3C2410_SDICON_FIFORESET;
 
 			writel(mci_con, host->base + S3C2410_SDICON);
 		}
@@ -713,8 +717,8 @@ request_done:
 
 void s3cmci_dma_setup(struct s3cmci_host *host, enum s3c2410_dmasrc source)
 {
-	static int setup_ok = 0;
 	static enum s3c2410_dmasrc last_source = -1;
+	static int setup_ok;
 
 	if (last_source == source)
 		return;
@@ -727,7 +731,8 @@ void s3cmci_dma_setup(struct s3cmci_host
 	if (!setup_ok) {
 		s3c2410_dma_config(host->dma, 4,
 			(S3C2410_DCON_HWTRIG | S3C2410_DCON_CH0_SDI));
-		s3c2410_dma_set_buffdone_fn(host->dma, s3cmci_dma_done_callback);
+		s3c2410_dma_set_buffdone_fn(host->dma,
+					    s3cmci_dma_done_callback);
 		s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART);
 		setup_ok = 1;
 	}
@@ -744,31 +749,30 @@ static void s3cmci_send_command(struct s
 
 	enable_imask(host, imsk);
 
-	if (cmd->data) {
+	if (cmd->data)
 		host->complete_what = COMPLETION_XFERFINISH_RSPFIN;
-	} else if (cmd->flags & MMC_RSP_PRESENT) {
+	else if (cmd->flags & MMC_RSP_PRESENT)
 		host->complete_what = COMPLETION_RSPFIN;
-	} else {
+	else
 		host->complete_what = COMPLETION_CMDSENT;
-	}
 
 	writel(cmd->arg, host->base + S3C2410_SDICMDARG);
 
-	ccon = cmd->opcode & S3C2410_SDICMDCON_INDEX;
-	ccon|= S3C2410_SDICMDCON_SENDERHOST | S3C2410_SDICMDCON_CMDSTART;
+	ccon  = cmd->opcode & S3C2410_SDICMDCON_INDEX;
+	ccon |= S3C2410_SDICMDCON_SENDERHOST | S3C2410_SDICMDCON_CMDSTART;
 
 	if (cmd->flags & MMC_RSP_PRESENT)
 		ccon |= S3C2410_SDICMDCON_WAITRSP;
 
 	if (cmd->flags & MMC_RSP_136)
-		ccon|= S3C2410_SDICMDCON_LONGRSP;
+		ccon |= S3C2410_SDICMDCON_LONGRSP;
 
 	writel(ccon, host->base + S3C2410_SDICMDCON);
 }
 
 static int s3cmci_setup_data(struct s3cmci_host *host, struct mmc_data *data)
 {
-	u32 dcon, imsk, stoptries=3;
+	u32 dcon, imsk, stoptries = 3;
 
 	/* write DCON register */
 
@@ -777,16 +781,16 @@ static int s3cmci_setup_data(struct s3cm
 		return 0;
 	}
 
-	while(readl(host->base + S3C2410_SDIDSTA) &
-		(S3C2410_SDIDSTA_TXDATAON | S3C2410_SDIDSTA_RXDATAON)) {
+	while (readl(host->base + S3C2410_SDIDSTA) &
+	       (S3C2410_SDIDSTA_TXDATAON | S3C2410_SDIDSTA_RXDATAON)) {
 
 		dbg(host, dbg_err,
-			"mci_setup_data() transfer stillin progress.\n");
+		    "mci_setup_data() transfer stillin progress.\n");
 
 		writel(0, host->base + S3C2410_SDIDCON);
 		s3cmci_reset(host);
 
-		if (0 == (stoptries--)) {
+		if ((stoptries--) == 0) {
 #ifdef CONFIG_MMC_DEBUG
 			dbg_dumpregs(host, "DRF");
 #endif
@@ -797,17 +801,14 @@ static int s3cmci_setup_data(struct s3cm
 
 	dcon  = data->blocks & S3C2410_SDIDCON_BLKNUM_MASK;
 
-	if (host->dodma) {
+	if (host->dodma)
 		dcon |= S3C2410_SDIDCON_DMAEN;
-	}
 
-	if (host->bus_width == MMC_BUS_WIDTH_4) {
+	if (host->bus_width == MMC_BUS_WIDTH_4)
 		dcon |= S3C2410_SDIDCON_WIDEBUS;
-	}
 
-	if (!(data->flags & MMC_DATA_STREAM)) {
+	if (!(data->flags & MMC_DATA_STREAM))
 		dcon |= S3C2410_SDIDCON_BLOCKMODE;
-	}
 
 	if (data->flags & MMC_DATA_WRITE) {
 		dcon |= S3C2410_SDIDCON_TXAFTERRESP;
@@ -831,8 +832,8 @@ static int s3cmci_setup_data(struct s3cm
 	writel(data->blksz, host->base + S3C2410_SDIBSIZE);
 
 	/* add to IMASK register */
-	imsk =	S3C2410_SDIIMSK_FIFOFAIL | S3C2410_SDIIMSK_DATACRC |
-		S3C2410_SDIIMSK_DATATIMEOUT | S3C2410_SDIIMSK_DATAFINISH;
+	imsk = S3C2410_SDIIMSK_FIFOFAIL | S3C2410_SDIIMSK_DATACRC |
+	       S3C2410_SDIIMSK_DATATIMEOUT | S3C2410_SDIIMSK_DATAFINISH;
 
 	enable_imask(host, imsk);
 
@@ -843,35 +844,33 @@ static int s3cmci_setup_data(struct s3cm
 	} else {
 		writel(0x0000FFFF, host->base + S3C2410_SDITIMER);
 
-		//FIX: set slow clock to prevent timeouts on read
-		if (data->flags & MMC_DATA_READ) {
+		/* FIX: set slow clock to prevent timeouts on read */
+		if (data->flags & MMC_DATA_READ)
 			writel(0xFF, host->base + S3C2410_SDIPRE);
-		}
 	}
 
-	//debug_dump_registers(host, "Data setup:");
-
 	return 0;
 }
 
+#define BOTH_DIR (MMC_DATA_WRITE | MMC_DATA_READ)
+
 static int s3cmci_prepare_pio(struct s3cmci_host *host, struct mmc_data *data)
 {
-	int rw = (data->flags & MMC_DATA_WRITE)?1:0;
+	int rw = (data->flags & MMC_DATA_WRITE) ? 1 : 0;
 
-	if (rw != ((data->flags & MMC_DATA_READ)?0:1))
-		return -EINVAL;
+	BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
 
 	host->pio_sgptr = 0;
 	host->pio_words = 0;
 	host->pio_count = 0;
-	host->pio_active = rw?XFER_WRITE:XFER_READ;
+	host->pio_active = rw ? XFER_WRITE : XFER_READ;
 
 	if (rw) {
 		do_pio_write(host);
 		enable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);
 	} else {
 		enable_imask(host, S3C2410_SDIIMSK_RXFIFOHALF
-			| S3C2410_SDIIMSK_RXFIFOLAST);
+			     | S3C2410_SDIIMSK_RXFIFOLAST);
 	}
 
 	return 0;
@@ -880,18 +879,15 @@ static int s3cmci_prepare_pio(struct s3c
 static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)
 {
 	int dma_len, i;
+	int rw = (data->flags & MMC_DATA_WRITE) ? 1 : 0;
 
-	int rw = (data->flags & MMC_DATA_WRITE)?1:0;
-
-	if (rw != ((data->flags & MMC_DATA_READ)?0:1))
-		return -EINVAL;
+	BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
 
-	s3cmci_dma_setup(host, rw?S3C2410_DMASRC_MEM:S3C2410_DMASRC_HW);
+	s3cmci_dma_setup(host, rw ? S3C2410_DMASRC_MEM : S3C2410_DMASRC_HW);
 	s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
 
 	dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
-				(rw)?DMA_TO_DEVICE:DMA_FROM_DEVICE);
-
+			     (rw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 
 	if (dma_len == 0)
 		return -ENOMEM;
@@ -907,14 +903,14 @@ static int s3cmci_prepare_dma(struct s3c
 			sg_dma_len(&data->sg[i]));
 
 		res = s3c2410_dma_enqueue(host->dma, (void *) host,
-				sg_dma_address(&data->sg[i]),
-				sg_dma_len(&data->sg[i]));
+					  sg_dma_address(&data->sg[i]),
+					  sg_dma_len(&data->sg[i]));
 
 		if (res) {
 			s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
 			return -EBUSY;
 		}
- 	}
+	}
 
 	s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_START);
 
@@ -925,21 +921,21 @@ static void s3cmci_send_request(struct m
 {
 	struct s3cmci_host *host = mmc_priv(mmc);
 	struct mmc_request *mrq = host->mrq;
-	struct mmc_command *cmd = host->cmd_is_stop?mrq->stop:mrq->cmd;
+	struct mmc_command *cmd = host->cmd_is_stop ? mrq->stop : mrq->cmd;
 
 	host->ccnt++;
 #ifdef CONFIG_MMC_DEBUG
 	prepare_dbgmsg(host, cmd, host->cmd_is_stop);
 #endif
-	//Clear command, data and fifo status registers
-	//Fifo clear only necessary on 2440, but doesn't hurt on 2410
+	/* Clear command, data and fifo status registers
+	   Fifo clear only necessary on 2440, but doesn't hurt on 2410
+	*/
 	writel(0xFFFFFFFF, host->base + S3C2410_SDICMDSTAT);
 	writel(0xFFFFFFFF, host->base + S3C2410_SDIDSTA);
 	writel(0xFFFFFFFF, host->base + S3C2410_SDIFSTA);
 
 	if (cmd->data) {
-		int res;
-		res = s3cmci_setup_data(host, cmd->data);
+		int res = s3cmci_setup_data(host, cmd->data);
 
 		host->dcnt++;
 
@@ -951,12 +947,10 @@ static void s3cmci_send_request(struct m
 			return;
 		}
 
-
-		if (host->dodma) {
+		if (host->dodma)
 			res = s3cmci_prepare_dma(host, cmd->data);
-		} else {
+		else
 			res = s3cmci_prepare_pio(host, cmd->data);
-		}
 
 		if (res) {
 			cmd->error = MMC_ERR_DMA;
@@ -968,16 +962,16 @@ static void s3cmci_send_request(struct m
 
 	}
 
-	// Send command
+	/* Send command */
 	s3cmci_send_command(host, cmd);
 
-	// Enable Interrupt
+	/* Enable Interrupt */
 	enable_irq(host->irq);
 }
 
 static void s3cmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
- 	struct s3cmci_host *host = mmc_priv(mmc);
+	struct s3cmci_host *host = mmc_priv(mmc);
 
 	host->cmd_is_stop = 0;
 	host->mrq = mrq;
@@ -990,62 +984,64 @@ static void s3cmci_set_ios(struct mmc_ho
 	struct s3cmci_host *host = mmc_priv(mmc);
 	u32 mci_psc, mci_con;
 
-	//Set power
-	mci_con = readl(host->base + S3C2410_SDICON);
-	switch(ios->power_mode) {
-		case MMC_POWER_ON:
-		case MMC_POWER_UP:
-			s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_SDCLK);
-			s3c2410_gpio_cfgpin(S3C2410_GPE6, S3C2410_GPE6_SDCMD);
-			s3c2410_gpio_cfgpin(S3C2410_GPE7, S3C2410_GPE7_SDDAT0);
-			s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);
-			s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2);
-			s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3);
-
-			if (!host->is2440)
-				mci_con|=S3C2410_SDICON_FIFORESET;
+	/* Set the power state */
 
-			break;
+	mci_con = readl(host->base + S3C2410_SDICON);
 
-		case MMC_POWER_OFF:
-		default:
-			s3c2410_gpio_setpin(S3C2410_GPE5, 0);
-			s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_OUTP);
+	switch (ios->power_mode) {
+	case MMC_POWER_ON:
+	case MMC_POWER_UP:
+		s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_SDCLK);
+		s3c2410_gpio_cfgpin(S3C2410_GPE6, S3C2410_GPE6_SDCMD);
+		s3c2410_gpio_cfgpin(S3C2410_GPE7, S3C2410_GPE7_SDDAT0);
+		s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);
+		s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2);
+		s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3);
+
+		if (!host->is2440)
+			mci_con |= S3C2410_SDICON_FIFORESET;
+
+		break;
+
+	case MMC_POWER_OFF:
+	default:
+		s3c2410_gpio_setpin(S3C2410_GPE5, 0);
+		s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_OUTP);
 
-			if (host->is2440)
-				mci_con|=S3C2440_SDICON_SDRESET;
+		if (host->is2440)
+			mci_con |= S3C2440_SDICON_SDRESET;
 
-			break;
+		break;
 	}
 
-	//Set clock
-	for (mci_psc=0; mci_psc<255; mci_psc++) {
+	/* Set clock */
+	for (mci_psc = 0; mci_psc < 255; mci_psc++) {
 		host->real_rate = host->clk_rate / (host->clk_div*(mci_psc+1));
 
 		if (host->real_rate <= ios->clock)
 			break;
 	}
 
-	if(mci_psc > 255) mci_psc = 255;
-	host->prescaler = mci_psc;
+	if (mci_psc > 255)
+		mci_psc = 255;
 
+	host->prescaler = mci_psc;
 	writel(host->prescaler, host->base + S3C2410_SDIPRE);
 
-	//If requested clock is 0, real_rate will be 0, too
+	/* If requested clock is 0, real_rate will be 0, too */
 	if (ios->clock == 0)
 		host->real_rate = 0;
 
-	//Set CLOCK_ENABLE
+	/* Set CLOCK_ENABLE */
 	if (ios->clock)
 		mci_con |= S3C2410_SDICON_CLOCKTYPE;
 	else
-		mci_con &=~S3C2410_SDICON_CLOCKTYPE;
+		mci_con &= ~S3C2410_SDICON_CLOCKTYPE;
 
 	writel(mci_con, host->base + S3C2410_SDICON);
 
-	if ((ios->power_mode==MMC_POWER_ON)
-		|| (ios->power_mode==MMC_POWER_UP)) {
-
+	if ((ios->power_mode == MMC_POWER_ON) ||
+	    (ios->power_mode == MMC_POWER_UP)) {
 		dbg(host, dbg_conf, "running at %lukHz (requested: %ukHz).\n",
 			host->real_rate/1000, ios->clock/1000);
 	} else {
@@ -1053,7 +1049,6 @@ static void s3cmci_set_ios(struct mmc_ho
 	}
 
 	host->bus_width = ios->bus_width;
-
 }
 
 static void s3cmci_reset(struct s3cmci_host *host)
@@ -1061,7 +1056,6 @@ static void s3cmci_reset(struct s3cmci_h
 	u32 con = readl(host->base + S3C2410_SDICON);
 
 	con |= S3C2440_SDICON_SDRESET;
-
 	writel(con, host->base + S3C2410_SDICON);
 }
 
@@ -1086,20 +1080,21 @@ static int s3cmci_probe(struct platform_
 	host = mmc_priv(mmc);
 	host->mmc 	= mmc;
 	host->pdev	= pdev;
+	host->is2440	= is2440;
 
 	spin_lock_init(&host->complete_lock);
 	tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host);
+
 	if (is2440) {
-		host->is2440	= 1;
 		host->sdiimsk	= S3C2440_SDIIMSK;
 		host->sdidata	= S3C2440_SDIDATA;
 		host->clk_div	= 1;
 	} else {
-		host->is2440	= 0;
 		host->sdiimsk	= S3C2410_SDIIMSK;
 		host->sdidata	= S3C2410_SDIDATA;
 		host->clk_div	= 2;
 	}
+
 	host->dodma		= 0;
 	host->complete_what 	= COMPLETION_NONE;
 	host->pio_active 	= XFER_NONE;
@@ -1153,7 +1148,6 @@ static int s3cmci_probe(struct platform_
 	if (request_irq(host->irq_cd, s3cmci_irq_cd, 0, DRIVER_NAME, host)) {
 		dev_err(&pdev->dev,
 			"failed to request card detect interrupt.\n");
-
 		ret = -ENOENT;
 		goto probe_free_irq;
 	}
@@ -1172,7 +1166,8 @@ static int s3cmci_probe(struct platform_
 		goto probe_free_host;
 	}
 
-	if ((ret = clk_enable(host->clk))) {
+	ret = clk_enable(host->clk);
+	if (ret) {
 		dev_err(&pdev->dev, "failed to enable clock source.\n");
 		goto clk_free;
 	}
@@ -1193,18 +1188,20 @@ static int s3cmci_probe(struct platform_
 	mmc->max_phys_segs	= 128;
 	mmc->max_hw_segs	= 128;
 
-	dbg(host, dbg_debug, "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%u.\n",
-		(host->is2440?"2440":""),
-		host->base, host->irq, host->irq_cd, host->dma);
+	dbg(host, dbg_debug,
+	    "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%u.\n",
+	    (host->is2440?"2440":""),
+	    host->base, host->irq, host->irq_cd, host->dma);
 
-	if ((ret = mmc_add_host(mmc))) {
+	ret = mmc_add_host(mmc);
+	if (ret) {
 		dev_err(&pdev->dev, "failed to add mmc host.\n");
 		goto free_dmabuf;
 	}
 
 	platform_set_drvdata(pdev, mmc);
+	dev_info(&pdev->dev, "initialisation done.\n");
 
-	dev_info(&pdev->dev,"initialisation done.\n");
 	return 0;
 
  free_dmabuf:
@@ -1214,10 +1211,10 @@ static int s3cmci_probe(struct platform_
 	clk_put(host->clk);
 
  probe_free_irq_cd:
- 	free_irq(host->irq_cd, host);
+	free_irq(host->irq_cd, host);
 
  probe_free_irq:
- 	free_irq(host->irq, host);
+	free_irq(host->irq, host);
 
  probe_iounmap:
 	iounmap(host->base);
@@ -1237,14 +1234,19 @@ static int s3cmci_remove(struct platform
 	struct s3cmci_host 	*host = mmc_priv(mmc);
 
 	mmc_remove_host(mmc);
+
 	clk_disable(host->clk);
 	clk_put(host->clk);
- 	free_irq(host->irq_cd, host);
- 	free_irq(host->irq, host);
+
+	tasklet_disable(&host->pio_tasklet);
+
+	free_irq(host->irq_cd, host);
+	free_irq(host->irq, host);
+
 	iounmap(host->base);
 	release_mem_region(host->mem->start, RESSIZE(host->mem));
-	mmc_free_host(mmc);
 
+	mmc_free_host(mmc);
 	return 0;
 }
 
@@ -1285,27 +1287,27 @@ static int s3cmci_resume(struct platform
 #endif /* CONFIG_PM */
 
 
-static struct platform_driver s3cmci_driver_2410 =
-{
+static struct platform_driver s3cmci_driver_2410 = {
 	.driver.name	= "s3c2410-sdi",
+	.driver.owner	= THIS_MODULE,
 	.probe		= s3cmci_probe_2410,
 	.remove		= s3cmci_remove,
 	.suspend	= s3cmci_suspend,
 	.resume		= s3cmci_resume,
 };
 
-static struct platform_driver s3cmci_driver_2412 =
-{
+static struct platform_driver s3cmci_driver_2412 = {
 	.driver.name	= "s3c2412-sdi",
+	.driver.owner	= THIS_MODULE,
 	.probe		= s3cmci_probe_2412,
 	.remove		= s3cmci_remove,
 	.suspend	= s3cmci_suspend,
 	.resume		= s3cmci_resume,
 };
 
-static struct platform_driver s3cmci_driver_2440 =
-{
+static struct platform_driver s3cmci_driver_2440 = {
 	.driver.name	= "s3c2440-sdi",
+	.driver.owner	= THIS_MODULE,
 	.probe		= s3cmci_probe_2440,
 	.remove		= s3cmci_remove,
 	.suspend	= s3cmci_suspend,
@@ -1334,4 +1336,3 @@ module_exit(s3cmci_exit);
 MODULE_DESCRIPTION("Samsung S3C MMC/SD Card Interface driver");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Thomas Kleffel <tk@maintech.de>");
-
Index: linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.h
===================================================================
--- linux-2.6.26-rc5-q2.orig/drivers/mmc/host/s3cmci.h	2008-06-07 12:25:27.000000000 +0100
+++ linux-2.6.26-rc5-q2/drivers/mmc/host/s3cmci.h	2008-06-16 16:01:32.000000000 +0100
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  */
 
-//FIXME: DMA Resource management ?!
+/* FIXME: DMA Resource management ?! */
 #define S3CMCI_DMA 0
 
 enum s3cmci_waitfor {
@@ -39,32 +39,30 @@ struct s3cmci_host {
 	unsigned		sdiimsk;
 	unsigned		sdidata;
 	int			dodma;
-
-	volatile int		dmatogo;
+	int			dmatogo;
 
 	struct mmc_request	*mrq;
 	int			cmd_is_stop;
 
 	spinlock_t		complete_lock;
-	volatile enum s3cmci_waitfor
-				complete_what;
+	enum s3cmci_waitfor	complete_what;
 
-	volatile int		dma_complete;
+	int			dma_complete;
 
-	volatile u32		pio_sgptr;
-	volatile u32		pio_words;
-	volatile u32		pio_count;
-	volatile u32		*pio_ptr;
+	u32			pio_sgptr;
+	u32			pio_words;
+	u32			pio_count;
+	u32			*pio_ptr;
 #define XFER_NONE 0
 #define XFER_READ 1
 #define XFER_WRITE 2
-	volatile u32		pio_active;
+	u32			pio_active;
 
 	int			bus_width;
 
 	char 			dbgmsg_cmd[301];
 	char 			dbgmsg_dat[301];
-	volatile char		*status;
+	char			*status;
 
 	unsigned int		ccnt, dcnt;
 	struct tasklet_struct	pio_tasklet;

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [patch v2 00/16] S3C24XX SD/MMC driver
  2008-06-16 14:34 [patch v2 00/16] S3C24XX SD/MMC driver Ben Dooks
                   ` (15 preceding siblings ...)
  2008-06-16 14:35 ` [patch v2 16/16] MMC: S3C24XX: Add media presence test to request handling Ben Dooks
@ 2008-06-18 10:32 ` Pierre Ossman
  16 siblings, 0 replies; 19+ messages in thread
From: Pierre Ossman @ 2008-06-18 10:32 UTC (permalink / raw)
  To: Ben Dooks; +Cc: linux-kernel

On Mon, 16 Jun 2008 15:34:45 +0100
Ben Dooks <ben-linux@fluff.org> wrote:

> Updated SD/MMC driver patches for the S3C24XX.
> 

Please have a look at the comments I made about the last series.

-- 
     -- Pierre Ossman

  Linux kernel, MMC maintainer        http://www.kernel.org
  rdesktop, core developer          http://www.rdesktop.org

  WARNING: This correspondence is being monitored by the
  Swedish government. Use end-to-end encryption where
  possible.

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2008-06-18 10:32 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-16 14:34 [patch v2 00/16] S3C24XX SD/MMC driver Ben Dooks
2008-06-16 14:34 ` [patch v2 01/16] MMC: S3C24XX MMC/SD driver Ben Dooks
2008-06-16 14:34 ` [patch v2 02/16] MMC: S3C24XX: Fix the checkpatch.pl errors in the s3cmci driver Ben Dooks
2008-06-16 15:07   ` Ben Dooks
2008-06-16 14:34 ` [patch v2 03/16] MMC: S3C24XX MMC/SD driver write fixes Ben Dooks
2008-06-16 14:34 ` [patch v2 04/16] MMC: DMA free fix for S3C24XX SD/MMC driver Ben Dooks
2008-06-16 14:34 ` [patch v2 05/16] MMC: S3C24XX MMC/SD stop fix Ben Dooks
2008-06-16 14:34 ` [patch v2 06/16] MMC: Fix S3C24XX IRQ enable during PIO transfers Ben Dooks
2008-06-16 14:34 ` [patch v2 07/16] MMC: S3C24XX: Add platform data for MMC/SD driver Ben Dooks
2008-06-16 14:34 ` [patch v2 08/16] MMC: S3C24XX: Add support to invert write protect line Ben Dooks
2008-06-16 14:34 ` [patch v2 09/16] MMC: S3C24XX: Ensure host->mrq->data is valid Ben Dooks
2008-06-16 14:34 ` [patch v2 10/16] MMC: S3C24XX: Allow card-detect on non-IRQ capable pin Ben Dooks
2008-06-16 14:34 ` [patch v2 11/16] MMC: S3C24XX: Fix s3c2410_dma_request() return code check Ben Dooks
2008-06-16 14:34 ` [patch v2 12/16] MMC: S3C24XX: Fix MMC return codes Ben Dooks
2008-06-16 14:34 ` [patch v2 13/16] MMC: S3C24XX: MMC/SD driver fix use of sg lists Ben Dooks
2008-06-16 14:34 ` [patch v2 14/16] MMC: S3C24XX: Add MODULE_ALIAS() entries for the platform devices Ben Dooks
2008-06-16 14:35 ` [patch v2 15/16] MMC: S3C24XX: Fix use of msecs where jiffies are needed Ben Dooks
2008-06-16 14:35 ` [patch v2 16/16] MMC: S3C24XX: Add media presence test to request handling Ben Dooks
2008-06-18 10:32 ` [patch v2 00/16] S3C24XX SD/MMC driver Pierre Ossman

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.