r3793 - developers/sameo/patches/ar6k-ng

sameo at sita.openmoko.org sameo at sita.openmoko.org
Wed Jan 9 12:48:18 CET 2008


Author: sameo
Date: 2008-01-09 12:48:17 +0100 (Wed, 09 Jan 2008)
New Revision: 3793

Added:
   developers/sameo/patches/ar6k-ng/115-s3cmci_sdio.patch
Log:
ar6k-ng: Forgot to add the mci patch.


Added: developers/sameo/patches/ar6k-ng/115-s3cmci_sdio.patch
===================================================================
--- developers/sameo/patches/ar6k-ng/115-s3cmci_sdio.patch	2008-01-09 10:43:34 UTC (rev 3792)
+++ developers/sameo/patches/ar6k-ng/115-s3cmci_sdio.patch	2008-01-09 11:48:17 UTC (rev 3793)
@@ -0,0 +1,422 @@
+---
+ drivers/mmc/host/s3cmci.c |  156 +++++++++++++++++++++++++++++++---------------
+ drivers/mmc/host/s3cmci.h |    6 +
+ 2 files changed, 112 insertions(+), 50 deletions(-)
+
+Index: linux-2.6.22-atheros-ng/drivers/mmc/host/s3cmci.c
+===================================================================
+--- linux-2.6.22-atheros-ng.orig/drivers/mmc/host/s3cmci.c	2007-12-21 16:24:25.000000000 +0100
++++ linux-2.6.22-atheros-ng/drivers/mmc/host/s3cmci.c	2007-12-21 16:25:44.000000000 +0100
+@@ -15,6 +15,7 @@
+ #include <linux/mmc/host.h>
+ #include <linux/platform_device.h>
+ #include <linux/timer.h>
++#include <linux/delay.h>
+ #include <linux/irq.h>
+ 
+ #include <asm/dma.h>
+@@ -44,7 +45,7 @@
+ 
+ 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;
++static const int dbgmap_debug = dbg_debug | dbg_pio;
+ 
+ #define dbg(host, channels, args...)		 \
+ 	if (dbgmap_err & channels) 		 \
+@@ -159,7 +160,7 @@
+ 	u32 newmask;
+ 
+ 	newmask = readl(host->base + host->sdiimsk);
+-	newmask|= imask;
++	newmask |= imask;
+ 
+ 	writel(newmask, host->base + host->sdiimsk);
+ 
+@@ -180,11 +181,14 @@
+ 
+ static inline void clear_imask(struct s3cmci_host *host)
+ {
+-	writel(0, host->base + host->sdiimsk);
++	if (host->sdio_int)
++		writel(S3C2410_SDIIMSK_SDIOIRQ, host->base + host->sdiimsk);
++	else
++		writel(0, host->base + host->sdiimsk);
+ }
+ 
+ static inline int get_data_buffer(struct s3cmci_host *host,
+-			volatile u32 *words, volatile u32 **pointer)
++				  volatile u32 *bytes, volatile u8 **pointer)
+ {
+ 	struct scatterlist *sg;
+ 
+@@ -201,7 +205,7 @@
+ 	}
+ 	sg = &host->mrq->data->sg[host->pio_sgptr];
+ 
+-	*words	= sg->length >> 2;
++	*bytes	= sg->length;
+ 	*pointer= page_address(sg->page) + sg->offset;
+ 
+ 	host->pio_sgptr++;
+@@ -212,8 +216,8 @@
+ 	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)
+ {
+@@ -227,9 +231,9 @@
+ 	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 (!host->pio_bytes) {
++			res = get_data_buffer(host, &host->pio_bytes,
++					      &host->pio_ptr);
+ 			if (res) {
+ 				host->pio_active = XFER_NONE;
+ 				host->complete_what = COMPLETION_FINALIZE;
+@@ -240,27 +244,26 @@
+ 			}
+ 
+ 			dbg(host, dbg_pio, "pio_read(): new target: [%i]@[%p]\n",
+-			       host->pio_words, host->pio_ptr);
++			       host->pio_bytes, host->pio_ptr);
+ 		}
+ 
+ 		dbg(host, dbg_pio, "pio_read(): fifo:[%02i] "
+ 				   "buffer:[%03i] dcnt:[%08X]\n",
+-				   fifo, host->pio_words,
++				   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_count+= fifo;
++		host->pio_bytes -= fifo;
++		host->pio_count += fifo;
+ 
+-		while(fifo--) {
+-			*(host->pio_ptr++) = readl(from_ptr);
+-		}
++		while(fifo--)
++			*(host->pio_ptr++) = readb(from_ptr);
+ 	}
+ 
+-	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");
+@@ -284,9 +287,9 @@
+ 	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 (!host->pio_bytes) {
++			res = get_data_buffer(host, &host->pio_bytes,
++					      &host->pio_ptr);
+ 			if (res) {
+ 				dbg(host, dbg_pio, "pio_write(): "
+ 					"complete (no more data).\n");
+@@ -297,18 +300,18 @@
+ 
+ 			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_count+= fifo;
++		host->pio_bytes -= fifo;
++		host->pio_count += fifo;
+ 
+ 		while(fifo--) {
+-			writel(*(host->pio_ptr++), to_ptr);
++			writeb(*(host->pio_ptr++), to_ptr);
+ 		}
+ 	}
+ 
+@@ -331,9 +334,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;
+ 		}
+@@ -376,6 +379,7 @@
+ 	struct mmc_command *cmd;
+ 	u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt, mci_imsk;
+ 	u32 mci_cclear, mci_dclear;
++	int cardint = 0;
+ 	unsigned long iflags;
+ 
+ 	host = (struct s3cmci_host *)dev_id;
+@@ -390,8 +394,19 @@
+ 	mci_cclear	= 0;
+ 	mci_dclear	= 0;
+ 
++	if (mci_dsta & S3C2410_SDIDSTA_SDIOIRQDETECT) {
++		if (host->sdio_int) {
++			disable_imask(host, S3C2410_SDIIMSK_SDIOIRQ);
++			cardint = 1;
++			host->sdio_pending_int = 0;
++		} else {
++			host->sdio_pending_int = 1;
++		}
++		mci_dclear |= S3C2410_SDIDSTA_SDIOIRQDETECT;
++	}
++
+ 	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;
+@@ -413,7 +428,7 @@
+ 
+ 	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);
+@@ -468,8 +483,10 @@
+ 			goto close_transfer;
+ 		}
+ 
+-		if (host->complete_what == COMPLETION_XFERFINISH_RSPFIN)
++		if (host->complete_what == COMPLETION_XFERFINISH_RSPFIN) {
+ 			host->complete_what = COMPLETION_XFERFINISH;
++			host->status = "ok: command response received, xfer to be done";
++		}
+ 
+ 		mci_cclear |= S3C2410_SDICMDSTAT_RSPFIN;
+ 	}
+@@ -550,6 +567,10 @@
+ 				mci_dcnt, host->status);
+ 
+ 	spin_unlock_irqrestore(&host->complete_lock, iflags);
++
++	/* We have to delay this as it calls back into the driver */
++	if (cardint)
++		mmc_signal_sdio_irq(host->mmc);
+ 	return IRQ_HANDLED;
+ 
+ }
+@@ -671,7 +692,7 @@
+ 	writel(0, host->base + S3C2410_SDICMDARG);
+ 	writel(S3C2410_SDIDCON_STOP, host->base + S3C2410_SDIDCON);
+ 	writel(0, host->base + S3C2410_SDICMDCON);
+-	writel(0, host->base + host->sdiimsk);
++	clear_imask(host);
+ 
+ 	if (cmd->data && cmd->error)
+ 		cmd->data->error = cmd->error;
+@@ -711,7 +732,7 @@
+ 
+ 			//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);
+ 		}
+@@ -776,6 +797,9 @@
+ 	if (cmd->flags & MMC_RSP_136)
+ 		ccon|= S3C2410_SDICMDCON_LONGRSP;
+ 
++	if (cmd->data)
++		ccon |= S3C2410_SDICMDCON_WITHDATA;
++
+ 	writel(ccon, host->base + S3C2410_SDICMDCON);
+ }
+ 
+@@ -833,7 +857,8 @@
+ 	}
+ 
+ 	if (host->is2440) {
+-		dcon |= S3C2440_SDIDCON_DS_WORD;
++		dcon |= S3C2440_SDIDCON_DS_BYTE;
++//		dcon |= S3C2440_SDIDCON_DS_WORD;
+ 		dcon |= S3C2440_SDIDCON_DATSTART;
+ 	}
+ 
+@@ -858,12 +883,11 @@
+ 
+ 		//FIX: set slow clock to prevent timeouts on read
+ 		if (data->flags & MMC_DATA_READ) {
++			printk("######## FIX ########## \n");
+ 			writel(0xFF, host->base + S3C2410_SDIPRE);
+ 		}
+ 	}
+ 
+-	//debug_dump_registers(host, "Data setup:");
+-
+ 	return 0;
+ }
+ 
+@@ -875,7 +899,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;
+ 
+@@ -1019,7 +1043,7 @@
+ 				host->pdata->set_power(ios->power_mode, ios->vdd);
+ 
+ 			if (!host->is2440)
+-				mci_con|=S3C2410_SDICON_FIFORESET;
++				mci_con |= S3C2410_SDICON_FIFORESET;
+ 
+ 			break;
+ 
+@@ -1032,7 +1056,7 @@
+ 				host->pdata->set_power(ios->power_mode, ios->vdd);
+ 
+ 			if (host->is2440)
+-				mci_con|=S3C2440_SDICON_SDRESET;
++				mci_con |= S3C2440_SDICON_SDRESET;
+ 
+ 			break;
+ 	}
+@@ -1060,9 +1084,11 @@
+ 	else
+ 		mci_con &=~S3C2410_SDICON_CLOCKTYPE;
+ 
++	mci_con |= S3C2410_SDICON_SDIOIRQ;
++
+ 	writel(mci_con, host->base + S3C2410_SDICON);
+ 
+-	if ((ios->power_mode==MMC_POWER_ON)
++	if ((ios->power_mode == MMC_POWER_ON)
+ 		|| (ios->power_mode==MMC_POWER_UP)) {
+ 
+ 		dbg(host, dbg_conf, "running at %lukHz (requested: %ukHz).\n",
+@@ -1094,10 +1120,39 @@
+ 	return s3c2410_gpio_getpin(host->pdata->gpio_wprotect);
+ }
+ 
++void s3cmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
++{
++	struct s3cmci_host *host = mmc_priv(mmc);
++	u32 con, imask;
++
++	con = readl(host->base + S3C2410_SDICON);
++	imask = readl(host->base + host->sdiimsk);
++
++	if (enable) {
++		host->sdio_int = 1;
++		con |= S3C2410_SDICON_SDIOIRQ;
++		imask |= S3C2410_SDIIMSK_SDIOIRQ;
++		if (host->sdio_pending_int) {
++			printk("We have a pending INT\n");
++			mmc_signal_sdio_irq(host->mmc);
++			host->sdio_pending_int = 0;
++		}
++	} else {
++
++		host->sdio_int = 0;
++		con &= ~S3C2410_SDICON_SDIOIRQ;
++		imask &= ~S3C2410_SDIIMSK_SDIOIRQ;
++	}
++
++	writel(imask, host->base + host->sdiimsk);
++	writel(con, host->base + S3C2410_SDICON);
++}
++
+ static struct mmc_host_ops s3cmci_ops = {
+-	.request	= s3cmci_request,
+-	.set_ios	= s3cmci_set_ios,
+-	.get_ro		= s3cmci_get_ro,
++	.request		= s3cmci_request,
++	.set_ios		= s3cmci_set_ios,
++	.get_ro			= s3cmci_get_ro,
++	.enable_sdio_irq	= s3cmci_enable_sdio_irq,
+ };
+ 
+ static struct s3c24xx_mci_pdata s3cmci_def_pdata = {
+@@ -1143,6 +1198,7 @@
+ 		host->sdidata	= S3C2410_SDIDATA;
+ 		host->clk_div	= 2;
+ 	}
++	host->sdio_int		= 0;
+ 	host->dodma		= 0;
+ 	host->complete_what 	= COMPLETION_NONE;
+ 	host->pio_active 	= XFER_NONE;
+@@ -1229,7 +1285,7 @@
+ 
+ 	mmc->ops 	= &s3cmci_ops;
+ 	mmc->ocr_avail	= host->pdata->ocr_avail;
+-	mmc->caps	= MMC_CAP_4_BIT_DATA;
++	mmc->caps	= MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
+ 	mmc->f_min 	= host->clk_rate / (host->clk_div * 256);
+ 	mmc->f_max 	= host->clk_rate / host->clk_div;
+ 
+@@ -1250,6 +1306,10 @@
+ 		goto free_dmabuf;
+ 	}
+ 
++
++//	mdelay(1000);
++	mmc_detect_change(host->mmc, 500);
++
+ 	platform_set_drvdata(pdev, mmc);
+ 
+ 	dev_info(&pdev->dev,"initialisation done.\n");
+Index: linux-2.6.22-atheros-ng/drivers/mmc/host/s3cmci.h
+===================================================================
+--- linux-2.6.22-atheros-ng.orig/drivers/mmc/host/s3cmci.h	2007-12-21 16:24:29.000000000 +0100
++++ linux-2.6.22-atheros-ng/drivers/mmc/host/s3cmci.h	2007-12-21 16:24:32.000000000 +0100
+@@ -40,6 +40,8 @@
+ 	unsigned		sdiimsk;
+ 	unsigned		sdidata;
+ 	int			dodma;
++	int			sdio_int;
++	int			sdio_pending_int;
+ 
+ 	volatile int		dmatogo;
+ 
+@@ -53,9 +55,9 @@
+ 	volatile int		dma_complete;
+ 
+ 	volatile u32		pio_sgptr;
+-	volatile u32		pio_words;
++	volatile u32		pio_bytes;
+ 	volatile u32		pio_count;
+-	volatile u32		*pio_ptr;
++	volatile u8		*pio_ptr;
+ #define XFER_NONE 0
+ #define XFER_READ 1
+ #define XFER_WRITE 2





More information about the commitlog mailing list