r3698 - branches/src/target/kernel/2.6.24.x/patches
laforge at sita.openmoko.org
laforge at sita.openmoko.org
Thu Dec 20 11:40:09 CET 2007
Author: laforge
Date: 2007-12-20 11:40:07 +0100 (Thu, 20 Dec 2007)
New Revision: 3698
Modified:
branches/src/target/kernel/2.6.24.x/patches/s3c_mci.patch
Log:
s3c_mci:
* add support for unaligned and non-modulo-four transfers
* remove cmd2str/err2str functions, as requested by Pierre Ossmann
* remove include of linux/mmc/mmc.h, as requested by Pierre Ossmann
* cosmetic cleanup (remove {} in one-line control blocks)
* add 'do_dma' member to platform_data
* use DMACH_SDI instead of old, bogus S3CMCI_DMA
* use host->dma instead of hard-coded dma channel
Modified: branches/src/target/kernel/2.6.24.x/patches/s3c_mci.patch
===================================================================
--- branches/src/target/kernel/2.6.24.x/patches/s3c_mci.patch 2007-12-20 07:04:09 UTC (rev 3697)
+++ branches/src/target/kernel/2.6.24.x/patches/s3c_mci.patch 2007-12-20 10:40:07 UTC (rev 3698)
@@ -16,15 +16,17 @@
===================================================================
--- linux-2.6.orig/include/asm-arm/arch-s3c2410/regs-sdi.h
+++ linux-2.6/include/asm-arm/arch-s3c2410/regs-sdi.h
-@@ -28,9 +28,15 @@
+@@ -28,9 +28,17 @@
#define S3C2410_SDIDCNT (0x30)
#define S3C2410_SDIDSTA (0x34)
#define S3C2410_SDIFSTA (0x38)
+
#define S3C2410_SDIDATA (0x3C)
++#define S3C2410_SDIDATA_BYTE (0x3C)
#define S3C2410_SDIIMSK (0x40)
+#define S3C2440_SDIDATA (0x40)
++#define S3C2440_SDIDATA_BYTE (0x48)
+#define S3C2440_SDIIMSK (0x3C)
+
+#define S3C2440_SDICON_SDRESET (1<<8)
@@ -32,7 +34,7 @@
#define S3C2410_SDICON_BYTEORDER (1<<4)
#define S3C2410_SDICON_SDIOIRQ (1<<3)
#define S3C2410_SDICON_RWAITEN (1<<2)
-@@ -42,7 +48,8 @@
+@@ -42,7 +50,8 @@
#define S3C2410_SDICMDCON_LONGRSP (1<<10)
#define S3C2410_SDICMDCON_WAITRSP (1<<9)
#define S3C2410_SDICMDCON_CMDSTART (1<<8)
@@ -42,7 +44,7 @@
#define S3C2410_SDICMDSTAT_CRCFAIL (1<<12)
#define S3C2410_SDICMDSTAT_CMDSENT (1<<11)
-@@ -51,6 +58,9 @@
+@@ -51,6 +60,9 @@
#define S3C2410_SDICMDSTAT_XFERING (1<<8)
#define S3C2410_SDICMDSTAT_INDEX (0xff)
@@ -52,7 +54,7 @@
#define S3C2410_SDIDCON_IRQPERIOD (1<<21)
#define S3C2410_SDIDCON_TXAFTERRESP (1<<20)
#define S3C2410_SDIDCON_RXAFTERCMD (1<<19)
-@@ -59,6 +69,7 @@
+@@ -59,6 +71,7 @@
#define S3C2410_SDIDCON_WIDEBUS (1<<16)
#define S3C2410_SDIDCON_DMAEN (1<<15)
#define S3C2410_SDIDCON_STOP (1<<14)
@@ -60,7 +62,7 @@
#define S3C2410_SDIDCON_DATMODE (3<<12)
#define S3C2410_SDIDCON_BLKNUM (0x7ff)
-@@ -68,6 +79,7 @@
+@@ -68,6 +81,7 @@
#define S3C2410_SDIDCON_XFER_RXSTART (2<<12)
#define S3C2410_SDIDCON_XFER_TXSTART (3<<12)
@@ -68,7 +70,7 @@
#define S3C2410_SDIDCNT_BLKNUM_SHIFT (12)
#define S3C2410_SDIDSTA_RDYWAITREQ (1<<10)
-@@ -82,10 +94,12 @@
+@@ -82,10 +96,12 @@
#define S3C2410_SDIDSTA_TXDATAON (1<<1)
#define S3C2410_SDIDSTA_RXDATAON (1<<0)
@@ -87,7 +89,7 @@
===================================================================
--- /dev/null
+++ linux-2.6/drivers/mmc/host/s3cmci.c
-@@ -0,0 +1,1409 @@
+@@ -0,0 +1,1389 @@
+/*
+ * linux/drivers/mmc/s3cmci.h - Samsung S3C MCI driver
+ *
@@ -102,7 +104,6 @@
+#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>
@@ -114,6 +115,7 @@
+#include <asm/arch/regs-sdi.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/mci.h>
++#include <asm/arch/dma.h>
+
+#include "s3cmci.h"
+
@@ -156,45 +158,6 @@
+static void s3cmci_reset(struct s3cmci_host *host);
+
+#ifdef CONFIG_MMC_DEBUG
-+
-+static char *mmc_cmd2str(int cmd)
-+{
-+ switch (cmd) {
-+ case 0: return "GO_IDLE_STATE";
-+ case 1: return "ALL_SEND_OCR";
-+ case 2: return "ALL_SEND_CID";
-+ case 3: return "ALL_SEND_RELATIVE_ADD";
-+ case 6: return "ACMD: SD_SET_BUSWIDTH";
-+ case 7: return "SEL_DESEL_CARD";
-+ case 9: return "SEND_CSD";
-+ case 10: return "SEND_CID";
-+ case 11: return "READ_UNTIL_STOP";
-+ case 12: return "STOP_TRANSMISSION";
-+ case 13: return "SEND_STATUS";
-+ case 15: return "GO_INACTIVE_STATE";
-+ case 16: return "SET_BLOCKLEN";
-+ case 17: return "READ_SINGLE_BLOCK";
-+ case 18: return "READ_MULTIPLE_BLOCK";
-+ case 24: return "WRITE_SINGLE_BLOCK";
-+ case 25: return "WRITE_MULTIPLE_BLOCK";
-+ case 41: return "ACMD: SD_APP_OP_COND";
-+ case 55: return "APP_CMD";
-+ default: return "UNKNOWN";
-+ }
-+}
-+
-+static char *mmc_err2str(int err)
-+{
-+ switch (err) {
-+ case 0: return "OK";
-+ case -ETIMEDOUT: return "TIMEOUT";
-+ case -EILSEQ: return "BADCRC";
-+ case -EINVAL: return "EINVAL";
-+ case -ENOMEDIUM: return "NOMEDIUM";
-+ default: return "UNKNOWN";
-+ }
-+}
-+
+static inline void dbg_dumpregs(struct s3cmci_host *host, char *prefix)
+{
+ u32 con, pre, cmdarg, cmdcon, cmdsta, r0, r1, r2, r3, timer, bsize;
@@ -236,9 +199,9 @@
+ int stop)
+{
+ snprintf(host->dbgmsg_cmd, 300,
-+ "#%u%s op:%s(%i) arg:0x%08x flags:0x08%x retries:%u",
-+ host->ccnt, (stop?" (STOP)":""), mmc_cmd2str(cmd->opcode),
-+ cmd->opcode, cmd->arg, cmd->flags, cmd->retries);
++ "#%u%s op:CMD%d 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,
@@ -259,29 +222,24 @@
+ if (!cmd)
+ return;
+
-+ if (cmd->error == 0) {
-+
++ if (cmd->error == 0)
+ dbg(host, dbglvl, "CMD[OK] %s R0:0x%08x\n",
+ host->dbgmsg_cmd, cmd->resp[0]);
-+ } else {
-+ dbg(host, dbglvl, "CMD[%s] %s Status:%s\n",
-+ mmc_err2str(cmd->error), host->dbgmsg_cmd,
-+ host->status);
-+ }
++ else
++ dbg(host, dbglvl, "CMD[FAIL(%d)] %s Status:%s\n",
++ cmd->error, host->dbgmsg_cmd, host->status);
+
+ if (!cmd->data)
+ return;
+
-+ if (cmd->data->error == 0) {
-+ dbg(host, dbglvl, "DAT[%s] %s\n",
-+ mmc_err2str(cmd->data->error), host->dbgmsg_dat);
-+ } else {
-+ dbg(host, dbglvl, "DAT[%s] %s DCNT:0x%08x\n",
-+ mmc_err2str(cmd->data->error), host->dbgmsg_dat,
++ if (cmd->data->error == 0)
++ dbg(host, dbglvl, "DAT[OK] %s\n", host->dbgmsg_dat);
++ else
++ dbg(host, dbglvl, "DAT[FAIL(%d)] %s DCNT:0x%08x\n",
++ cmd->data->error, host->dbgmsg_dat,
+ readl(host->base + S3C2410_SDIDCNT));
-+ }
+}
-+#endif
++#endif /* CONFIG_MMC_DEBUG */
+
+static inline u32 enable_imask(struct s3cmci_host *host, u32 imask)
+{
@@ -313,7 +271,7 @@
+}
+
+static inline int get_data_buffer(struct s3cmci_host *host,
-+ u32 *words, u32 **pointer)
++ u32 *bytes, u8 **pointer)
+{
+ struct scatterlist *sg;
+
@@ -330,7 +288,7 @@
+ }
+ sg = &host->mrq->data->sg[host->pio_sgptr];
+
-+ *words = sg->length >> 2;
++ *bytes = sg->length;
+ *pointer = page_address(sg_page(sg)) + sg->offset;
+
+ host->pio_sgptr++;
@@ -341,15 +299,15 @@
+ 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)
++#define FIFO_FILL(host) (readl(host->base + S3C2410_SDIFSTA) & \
++ S3C2410_SDIFSTA_COUNTMASK)
++#define FIFO_FREE(host) (63 - (readl(host->base + S3C2410_SDIFSTA) \
++ & S3C2410_SDIFSTA_COUNTMASK))
+
+static inline void do_pio_read(struct s3cmci_host *host)
+{
+ int res;
-+ u32 fifo;
++ int fifo;
+ void __iomem *from_ptr;
+
+ /* write real prescaler to host, it might be set slow to fix */
@@ -358,8 +316,8 @@
+ from_ptr = host->base + host->sdidata;
+
+ while ((fifo = FIFO_FILL(host))) {
-+ if (!host->pio_words) {
-+ res = get_data_buffer(host, &host->pio_words,
++ if (!host->pio_bytes) {
++ res = get_data_buffer(host, &host->pio_bytes,
+ &host->pio_ptr);
+ if (res) {
+ host->pio_active = XFER_NONE;
@@ -371,25 +329,36 @@
+ }
+
+ dbg(host, dbg_pio, "pio_read(): new target: "
-+ "[%i]@[%p]\n", host->pio_words, host->pio_ptr);
++ "[%i]@[%p]\n", host->pio_bytes, host->pio_ptr);
+ }
+
+ dbg(host, dbg_pio, "pio_read(): fifo:[%02i] "
-+ "buffer:[%03i] dcnt:[%08X]\n", fifo, host->pio_words,
++ "buffer:[%03i] dcnt:[%08X]\n", fifo, host->pio_bytes,
+ readl(host->base + S3C2410_SDIDCNT));
+
-+ if (fifo > host->pio_words)
-+ fifo = host->pio_words;
++ if (fifo > host->pio_bytes)
++ fifo = host->pio_bytes;
+
-+ host->pio_words -= fifo;
++ host->pio_bytes -= fifo;
+ host->pio_count += fifo;
+
-+ while (fifo--)
-+ *(host->pio_ptr++) = readl(from_ptr);
++ /* we might have an unaligned start of data */
++ while ((unsigned long)host->pio_ptr & 0x03)
++ *(host->pio_ptr++) = readb(host->base + host->sdidata_b);
++
++ /* and a major chunk of data in the middle */
++ for (; fifo >= 4; fifo -=4) {
++ *(host->pio_ptr) = readl(from_ptr);
++ host->pio_ptr+= 4;
++ }
++
++ /* as well as some non-modulo-four trailer */
++ while (fifo)
++ *(host->pio_ptr++) = readb(host->base + host->sdidata_b);
+ }
+
-+ if (!host->pio_words) {
-+ res = get_data_buffer(host, &host->pio_words, &host->pio_ptr);
++ if (!host->pio_bytes) {
++ res = get_data_buffer(host, &host->pio_bytes, &host->pio_ptr);
+ if (res) {
+ dbg(host, dbg_pio, "pio_read(): "
+ "complete (no more buffers).\n");
@@ -407,15 +376,15 @@
+static inline void do_pio_write(struct s3cmci_host *host)
+{
+ int res;
-+ u32 fifo;
++ int 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,
++ if (!host->pio_bytes) {
++ res = get_data_buffer(host, &host->pio_bytes,
+ &host->pio_ptr);
+ if (res) {
+ dbg(host, dbg_pio, "pio_write(): "
@@ -427,18 +396,29 @@
+
+ dbg(host, dbg_pio, "pio_write(): "
+ "new source: [%i]@[%p]\n",
-+ host->pio_words, host->pio_ptr);
++ host->pio_bytes, host->pio_ptr);
+
+ }
+
-+ if (fifo > host->pio_words)
-+ fifo = host->pio_words;
++ if (fifo > host->pio_bytes)
++ fifo = host->pio_bytes;
+
-+ host->pio_words -= fifo;
++ host->pio_bytes -= fifo;
+ host->pio_count += fifo;
+
++ /* we might have an unaligned start of data */
++ while ((unsigned long)host->pio_ptr & 0x03)
++ writeb(*(host->pio_ptr++), host->base + host->sdidata_b);
++
++ /* and a major chunk of data in the middle */
++ for (; fifo >= 4; fifo -=4) {
++ writel(*(host->pio_ptr), to_ptr);
++ host->pio_ptr += 4;
++ }
++
++ /* as well as some non-modulo-four trailer */
+ while (fifo--)
-+ writel(*(host->pio_ptr++), to_ptr);
++ writeb(*(host->pio_ptr++), host->base + host->sdidata_b);
+ }
+
+ enable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);
@@ -460,9 +440,9 @@
+ clear_imask(host);
+ if (host->pio_active != XFER_NONE) {
+ dbg(host, dbg_err, "unfinished %s "
-+ "- pio_count:[%u] pio_words:[%u]\n",
++ "- pio_count:[%u] pio_bytes:[%u]\n",
+ (host->pio_active == XFER_READ)?"read":"write",
-+ host->pio_count, host->pio_words);
++ host->pio_count, host->pio_bytes);
+
+ host->mrq->data->error = -EIO;
+ }
@@ -993,7 +973,7 @@
+ return -EINVAL;
+
+ host->pio_sgptr = 0;
-+ host->pio_words = 0;
++ host->pio_bytes = 0;
+ host->pio_count = 0;
+ host->pio_active = rw?XFER_WRITE:XFER_READ;
+
@@ -1216,6 +1196,7 @@
+};
+
+static struct s3c24xx_mci_pdata s3cmci_def_pdata = {
++ .do_dma = 0,
+ .gpio_detect = 0,
+ .set_power = NULL,
+ .ocr_avail = MMC_VDD_32_33,
@@ -1250,18 +1231,20 @@
+ host->is2440 = 1;
+ host->sdiimsk = S3C2440_SDIIMSK;
+ host->sdidata = S3C2440_SDIDATA;
++ host->sdidata_b = S3C2440_SDIDATA_BYTE;
+ host->clk_div = 1;
+ } else {
+ host->is2440 = 0;
+ host->sdiimsk = S3C2410_SDIIMSK;
+ host->sdidata = S3C2410_SDIDATA;
++ host->sdidata_b = S3C2410_SDIDATA_BYTE;
+ host->clk_div = 2;
+ }
-+ host->dodma = 0;
++ host->dodma = host->pdata->do_dma;
+ host->complete_what = COMPLETION_NONE;
+ host->pio_active = XFER_NONE;
+
-+ host->dma = S3CMCI_DMA;
++ host->dma = DMACH_SDI;
+ host->irq_cd = s3c2410_gpio_getirq(host->pdata->gpio_detect);
+ s3c2410_gpio_cfgpin(host->pdata->gpio_detect, S3C2410_GPIO_IRQ);
+
@@ -1320,7 +1303,7 @@
+ s3c2410_gpio_cfgpin(host->pdata->gpio_wprotect,
+ S3C2410_GPIO_INPUT);
+
-+ if (s3c2410_dma_request(S3CMCI_DMA, &s3cmci_dma_client, NULL)) {
++ if (s3c2410_dma_request(host->dma, &s3cmci_dma_client, NULL)) {
+ dev_err(&pdev->dev, "unable to get DMA channel.\n");
+ ret = -EBUSY;
+ goto probe_free_irq_cd;
@@ -1403,7 +1386,7 @@
+ mmc_remove_host(mmc);
+ clk_disable(host->clk);
+ clk_put(host->clk);
-+ s3c2410_dma_free(S3CMCI_DMA, &s3cmci_dma_client);
++ s3c2410_dma_free(host->dma, &s3cmci_dma_client);
+ free_irq(host->irq_cd, host);
+ free_irq(host->irq, host);
+ iounmap(host->base);
@@ -1496,12 +1479,11 @@
+MODULE_DESCRIPTION("Samsung S3C MMC/SD Card Interface driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Thomas Kleffel <tk at maintech.de>");
-+
Index: linux-2.6/drivers/mmc/host/s3cmci.h
===================================================================
--- /dev/null
+++ linux-2.6/drivers/mmc/host/s3cmci.h
-@@ -0,0 +1,71 @@
+@@ -0,0 +1,69 @@
+/*
+ * linux/drivers/mmc/s3cmci.h - Samsung S3C MCI driver
+ *
@@ -1512,9 +1494,6 @@
+ * published by the Free Software Foundation.
+ */
+
-+/* FIXME: DMA Resource management ?! */
-+#define S3CMCI_DMA 0
-+
+enum s3cmci_waitfor {
+ COMPLETION_NONE,
+ COMPLETION_FINALIZE,
@@ -1543,6 +1522,7 @@
+ int is2440;
+ unsigned sdiimsk;
+ unsigned sdidata;
++ unsigned sdidata_b;
+ int dodma;
+
+ int dmatogo;
@@ -1556,9 +1536,9 @@
+ int dma_complete;
+
+ u32 pio_sgptr;
-+ u32 pio_words;
++ u32 pio_bytes;
+ u32 pio_count;
-+ u32 *pio_ptr;
++ u8 *pio_ptr;
+#define XFER_NONE 0
+#define XFER_READ 1
+#define XFER_WRITE 2
More information about the commitlog
mailing list