public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] au1xmmc updates #3
@ 2008-05-19  8:03 Manuel Lauss
  2008-05-19  8:04 ` [PATCH 1/9] Alchemy: export get_au1x00_speed for modules Manuel Lauss
                   ` (9 more replies)
  0 siblings, 10 replies; 27+ messages in thread
From: Manuel Lauss @ 2008-05-19  8:03 UTC (permalink / raw)
  To: linux-mips, linux-kernel, drzeus, sshtylyov

Hello,

The following set of patches remove demoboard-specific code from the
au1xmmc.c driver and adds new features.

My main motivation was to let boards implement other carddetect schemes,
since on one of my boards the driver-implemented poll timer doesn't work
for some unknown reason.  But this board does have a dedicated carddetect
IRQ and card-present/card-readonly indicators which are incompatible with
the Db1200 implementation.

I also took the opportunity to clean up the drivers probe() and irq()
handlers to make it a "proper" platform device (patches #3 and #4)
and add a few other features.

Patch #1 is required to get the driver to build as a module.
Patch #2 is required to be able to load/unload the driver > 16 times.
Patches #5 and #6 implement new features.
Patch #7 does a little codingstyle cleanup, no functional changes.
Patch #8 adds an optimization to the request callback.
Patch #9 adds back pb1200 MMC activity LED support (patch #3 removes it).

patches #3-#9 are intended to be applied on top of each other, against
current mainline git (2.6.23-rc3).

Changes since V2:
- address almost all Sergei Shtylyov's comments:
  pb1200/db1200 mmc device registration moved back to original location,
  remove the au1xmmc.h header as part of codingstyle cleanup
  other nits.

- 2 more patches (#8, #9)

Changes since V1:
- fix a bug in patch #6: SDIO irq should be checked for independently
  from other irq events.
- more trivial cleanups

Db1200 users, please test!  I verified the poll timer works on one of
older boards, however since I don't have Db1200 and Pb1200 boards I'm
not sure whether the driver still works with both SD controllers enabled!

Thanks!
	Manuel Lauss

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

* [PATCH 1/9] Alchemy: export get_au1x00_speed for modules
  2008-05-19  8:03 [PATCH 0/9] au1xmmc updates #3 Manuel Lauss
@ 2008-05-19  8:04 ` Manuel Lauss
  2008-05-19  9:35   ` Sergei Shtylyov
  2008-05-19  8:04 ` [PATCH 2/9] Alchemy: dbdma: add API to delete custom DDMA device ids Manuel Lauss
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 27+ messages in thread
From: Manuel Lauss @ 2008-05-19  8:04 UTC (permalink / raw)
  To: linux-mips, linux-kernel, drzeus, sshtylyov

>From 8492076e98c7fd47c9dee53984dbd9568ace357d Mon Sep 17 00:00:00 2001
From: Manuel Lauss <mlau@msc-ge.com>
Date: Wed, 7 May 2008 13:42:55 +0200
Subject: [PATCH] Alchemy: export get_au1x00_speed for modules

au1xmmc.c driver depends on it, so export it for modules.

Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
---
 arch/mips/au1000/common/clocks.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/mips/au1000/common/clocks.c b/arch/mips/au1000/common/clocks.c
index 46f8ee0..043429d 100644
--- a/arch/mips/au1000/common/clocks.c
+++ b/arch/mips/au1000/common/clocks.c
@@ -45,6 +45,7 @@ unsigned int get_au1x00_speed(void)
 {
 	return au1x00_clock;
 }
+EXPORT_SYMBOL(get_au1x00_speed);
 
 /*
  * The UART baud base is not known at compile time ... if
-- 
1.5.5.1


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

* [PATCH 2/9] Alchemy: dbdma: add API to delete custom DDMA device ids.
  2008-05-19  8:03 [PATCH 0/9] au1xmmc updates #3 Manuel Lauss
  2008-05-19  8:04 ` [PATCH 1/9] Alchemy: export get_au1x00_speed for modules Manuel Lauss
@ 2008-05-19  8:04 ` Manuel Lauss
  2008-05-19  8:05 ` [PATCH 3/9] au1xmmc: remove pb1200 board-specific code from driver file Manuel Lauss
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 27+ messages in thread
From: Manuel Lauss @ 2008-05-19  8:04 UTC (permalink / raw)
  To: linux-mips, linux-kernel, drzeus, sshtylyov

>From 44aefed96c1358e52c24cc7c526b2cbe76166cfe Mon Sep 17 00:00:00 2001
From: Manuel Lauss <mlau@msc-ge.com>
Date: Wed, 7 May 2008 13:45:23 +0200
Subject: [PATCH] Alchemy: dbdma: add API to delete custom DDMA device ids.

Add API to delete custom DDMA device ids create with
au1xxx_ddma_device_add().

Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
---
 arch/mips/au1000/common/dbdma.c             |   10 ++++++++++
 include/asm-mips/mach-au1x00/au1xxx_dbdma.h |    1 +
 2 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/arch/mips/au1000/common/dbdma.c b/arch/mips/au1000/common/dbdma.c
index 42d5552..e7cb64e 100644
--- a/arch/mips/au1000/common/dbdma.c
+++ b/arch/mips/au1000/common/dbdma.c
@@ -216,6 +216,16 @@ u32 au1xxx_ddma_add_device(dbdev_tab_t *dev)
 }
 EXPORT_SYMBOL(au1xxx_ddma_add_device);
 
+void au1xxx_ddma_del_device(u32 devid)
+{
+	dbdev_tab_t *p = find_dbdev_id(devid);
+	if (p != NULL) {
+		memset(p, 0, sizeof(dbdev_tab_t));
+		p->dev_id = ~0;
+	}
+}
+EXPORT_SYMBOL(au1xxx_ddma_del_device);
+
 /* Allocate a channel and return a non-zero descriptor if successful. */
 u32 au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid,
        void (*callback)(int, void *), void *callparam)
diff --git a/include/asm-mips/mach-au1x00/au1xxx_dbdma.h b/include/asm-mips/mach-au1x00/au1xxx_dbdma.h
index ad17d7c..9077763 100644
--- a/include/asm-mips/mach-au1x00/au1xxx_dbdma.h
+++ b/include/asm-mips/mach-au1x00/au1xxx_dbdma.h
@@ -355,6 +355,7 @@ void au1xxx_dbdma_dump(u32 chanid);
 u32 au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr);
 
 u32 au1xxx_ddma_add_device(dbdev_tab_t *dev);
+void au1xxx_ddma_del_device(u32 devid);
 void *au1xxx_ddma_get_nextptr_virt(au1x_ddma_desc_t *dp);
 
 /*
-- 
1.5.5.1


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

* [PATCH 3/9] au1xmmc: remove pb1200 board-specific code from driver file
  2008-05-19  8:03 [PATCH 0/9] au1xmmc updates #3 Manuel Lauss
  2008-05-19  8:04 ` [PATCH 1/9] Alchemy: export get_au1x00_speed for modules Manuel Lauss
  2008-05-19  8:04 ` [PATCH 2/9] Alchemy: dbdma: add API to delete custom DDMA device ids Manuel Lauss
@ 2008-05-19  8:05 ` Manuel Lauss
  2008-05-19  8:17   ` Manuel Lauss
  2008-05-19  8:06 ` [PATCH 4/9] Alchemy: register mmc platform device for db1200/pb1200 boards Manuel Lauss
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 27+ messages in thread
From: Manuel Lauss @ 2008-05-19  8:05 UTC (permalink / raw)
  To: linux-mips, linux-kernel, drzeus, sshtylyov

>From 20a9a4d454e6e381f632dfadf713b515f30045b1 Mon Sep 17 00:00:00 2001
From: Manuel Lauss <mlau@msc-ge.com>
Date: Wed, 7 May 2008 14:57:01 +0200
Subject: [PATCH] au1xmmc: remove pb1200 board-specific code from driver file

Remove the DB1200 board-specific functions (card present, read-only,
activity LED methods) and instead add platform data which is passed
to the driver.  This also allows for platforms to implement other
carddetect schemes (e.g. dedicated irq) without having to pollute the
driver code.  The poll timer (used for pb1200) is kept for compatibility.

With the board-specific stuff gone, the drivers probe code can be
cleaned up considerably: this patch also rewrites the probe and
remove functions and removes a few unused variables.

Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
---
 drivers/mmc/host/au1xmmc.c                |  508 +++++++++++++++++------------
 drivers/mmc/host/au1xmmc.h                |    9 +-
 include/asm-mips/mach-au1x00/au1100_mmc.h |   15 +-
 3 files changed, 304 insertions(+), 228 deletions(-)

diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index cc5f7bc..9036677 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -54,6 +54,7 @@
 #define DRIVER_NAME "au1xxx-mmc"
 
 /* Set this to enable special debugging macros */
+/* #define DEBUG */
 
 #ifdef DEBUG
 #define DBG(fmt, idx, args...) printk("au1xx(%d): DEBUG: " fmt, idx, ##args)
@@ -61,32 +62,6 @@
 #define DBG(fmt, idx, args...)
 #endif
 
-const struct {
-	u32 iobase;
-	u32 tx_devid, rx_devid;
-	u16 bcsrpwr;
-	u16 bcsrstatus;
-	u16 wpstatus;
-} au1xmmc_card_table[] = {
-	{ SD0_BASE, DSCR_CMD0_SDMS_TX0, DSCR_CMD0_SDMS_RX0,
-	  BCSR_BOARD_SD0PWR, BCSR_INT_SD0INSERT, BCSR_STATUS_SD0WP },
-#ifndef CONFIG_MIPS_DB1200
-	{ SD1_BASE, DSCR_CMD0_SDMS_TX1, DSCR_CMD0_SDMS_RX1,
-	  BCSR_BOARD_DS1PWR, BCSR_INT_SD1INSERT, BCSR_STATUS_SD1WP }
-#endif
-};
-
-#define AU1XMMC_CONTROLLER_COUNT (ARRAY_SIZE(au1xmmc_card_table))
-
-/* This array stores pointers for the hosts (used by the IRQ handler) */
-struct au1xmmc_host *au1xmmc_hosts[AU1XMMC_CONTROLLER_COUNT];
-static int dma = 1;
-
-#ifdef MODULE
-module_param(dma, bool, 0);
-MODULE_PARM_DESC(dma, "Use DMA engine for data transfers (0 = disabled)");
-#endif
-
 static inline void IRQ_ON(struct au1xmmc_host *host, u32 mask)
 {
 	u32 val = au_readl(HOST_CONFIG(host));
@@ -135,26 +110,33 @@ static inline void SEND_STOP(struct au1xmmc_host *host)
 
 static void au1xmmc_set_power(struct au1xmmc_host *host, int state)
 {
-
-	u32 val = au1xmmc_card_table[host->id].bcsrpwr;
-
-	bcsr->board &= ~val;
-	if (state) bcsr->board |= val;
-
-	au_sync_delay(1);
+	if (host->platdata && host->platdata->set_power)
+		host->platdata->set_power(host->mmc, state);
 }
 
-static inline int au1xmmc_card_inserted(struct au1xmmc_host *host)
+static int au1xmmc_card_inserted(struct au1xmmc_host *host)
 {
-	return (bcsr->sig_status & au1xmmc_card_table[host->id].bcsrstatus)
-		? 1 : 0;
+	int ret;
+
+	if (host->platdata && host->platdata->card_inserted)
+		ret = host->platdata->card_inserted(host->mmc);
+	else
+		ret = 1;	/* assume there is a card */
+
+	return ret;
 }
 
 static int au1xmmc_card_readonly(struct mmc_host *mmc)
 {
 	struct au1xmmc_host *host = mmc_priv(mmc);
-	return (bcsr->status & au1xmmc_card_table[host->id].wpstatus)
-		? 1 : 0;
+	int ret;
+
+	if (host->platdata && host->platdata->card_readonly)
+		ret = host->platdata->card_readonly(mmc);
+	else
+		ret = 1;	/* assume card is read-only */
+
+	return ret;
 }
 
 static void au1xmmc_finish_request(struct au1xmmc_host *host)
@@ -174,8 +156,6 @@ static void au1xmmc_finish_request(struct au1xmmc_host *host)
 
 	host->status = HOST_S_IDLE;
 
-	bcsr->disk_leds |= (1 << 8);
-
 	mmc_request_done(host->mmc, mrq);
 }
 
@@ -420,18 +400,18 @@ static void au1xmmc_receive_pio(struct au1xmmc_host *host)
 			break;
 
 		if (status & SD_STATUS_RC) {
-			DBG("RX CRC Error [%d + %d].\n", host->id,
+			DBG("RX CRC Error [%d + %d].\n", host->pdev->id,
 					host->pio.len, count);
 			break;
 		}
 
 		if (status & SD_STATUS_RO) {
-			DBG("RX Overrun [%d + %d]\n", host->id,
+			DBG("RX Overrun [%d + %d]\n", host->pdev->id,
 					host->pio.len, count);
 			break;
 		}
 		else if (status & SD_STATUS_RU) {
-			DBG("RX Underrun [%d + %d]\n", host->id,
+			DBG("RX Underrun [%d + %d]\n", host->pdev->id,
 					host->pio.len,	count);
 			break;
 		}
@@ -571,12 +551,8 @@ static void au1xmmc_set_clock(struct au1xmmc_host *host, int rate)
 static int
 au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data)
 {
-
 	int datalen = data->blocks * data->blksz;
 
-	if (dma != 0)
-		host->flags |= HOST_F_DMA;
-
 	if (data->flags & MMC_DATA_READ)
 		host->flags |= HOST_F_RECV;
 	else
@@ -663,8 +639,6 @@ static void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq)
 	host->mrq = mrq;
 	host->status = HOST_S_CMD;
 
-	bcsr->disk_leds &= ~(1 << 8);
-
 	if (mrq->data) {
 		FLUSH_FIFO(host);
 		flags = mrq->data->flags;
@@ -749,245 +723,339 @@ static void au1xmmc_dma_callback(int irq, void *dev_id)
 
 static irqreturn_t au1xmmc_irq(int irq, void *dev_id)
 {
-
+	struct au1xmmc_host *host = dev_id;
 	u32 status;
-	int i, ret = 0;
 
-	disable_irq(AU1100_SD_IRQ);
+	status = au_readl(HOST_STATUS(host));
 
-	for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
-		struct au1xmmc_host * host = au1xmmc_hosts[i];
-		u32 handled = 1;
+	if (!(status & SD_STATUS_I))
+		return IRQ_NONE;	/* not ours */
 
-		status = au_readl(HOST_STATUS(host));
-
-		if (host->mrq && (status & STATUS_TIMEOUT)) {
-			if (status & SD_STATUS_RAT)
-				host->mrq->cmd->error = -ETIMEDOUT;
+	if (host->mrq && (status & STATUS_TIMEOUT)) {
+		if (status & SD_STATUS_RAT)
+			host->mrq->cmd->error = -ETIMEDOUT;
+		else if (status & SD_STATUS_DT)
+			host->mrq->data->error = -ETIMEDOUT;
 
-			else if (status & SD_STATUS_DT)
-				host->mrq->data->error = -ETIMEDOUT;
+		/* In PIO mode, interrupts might still be enabled */
+		IRQ_OFF(host, SD_CONFIG_NE | SD_CONFIG_TH);
 
-			/* In PIO mode, interrupts might still be enabled */
-			IRQ_OFF(host, SD_CONFIG_NE | SD_CONFIG_TH);
-
-			//IRQ_OFF(host, SD_CONFIG_TH|SD_CONFIG_RA|SD_CONFIG_RF);
-			tasklet_schedule(&host->finish_task);
-		}
+		/* IRQ_OFF(host, SD_CONFIG_TH|SD_CONFIG_RA|SD_CONFIG_RF); */
+		tasklet_schedule(&host->finish_task);
+	}
 #if 0
-		else if (status & SD_STATUS_DD) {
-
-			/* Sometimes we get a DD before a NE in PIO mode */
-
-			if (!(host->flags & HOST_F_DMA) &&
-					(status & SD_STATUS_NE))
-				au1xmmc_receive_pio(host);
-			else {
-				au1xmmc_data_complete(host, status);
-				//tasklet_schedule(&host->data_task);
-			}
+	else if (status & SD_STATUS_DD) {
+		/* Sometimes we get a DD before a NE in PIO mode */
+		if (!(host->flags & HOST_F_DMA) && (status & SD_STATUS_NE))
+			au1xmmc_receive_pio(host);
+		else {
+			au1xmmc_data_complete(host, status);
+			/* tasklet_schedule(&host->data_task); */
 		}
+	}
 #endif
-		else if (status & (SD_STATUS_CR)) {
-			if (host->status == HOST_S_CMD)
-				au1xmmc_cmd_complete(host,status);
-		}
-		else if (!(host->flags & HOST_F_DMA)) {
-			if ((host->flags & HOST_F_XMIT) &&
-			    (status & STATUS_DATA_OUT))
-				au1xmmc_send_pio(host);
-			else if ((host->flags & HOST_F_RECV) &&
-			    (status & STATUS_DATA_IN))
-				au1xmmc_receive_pio(host);
-		}
-		else if (status & 0x203FBC70) {
-			DBG("Unhandled status %8.8x\n", host->id, status);
-			handled = 0;
-		}
+	else if (status & SD_STATUS_CR) {
+		if (host->status == HOST_S_CMD)
+			au1xmmc_cmd_complete(host, status);
+
+	} else if (!(host->flags & HOST_F_DMA)) {
+		if ((host->flags & HOST_F_XMIT) && (status & STATUS_DATA_OUT))
+			au1xmmc_send_pio(host);
+		else if ((host->flags & HOST_F_RECV) && (status & STATUS_DATA_IN))
+			au1xmmc_receive_pio(host);
+
+	} else if (status & 0x203F3C70) {
+			DBG("Unhandled status %8.8x\n", host->pdev->id,
+				status);
+	}
 
-		au_writel(status, HOST_STATUS(host));
-		au_sync();
+	au_writel(status, HOST_STATUS(host));
+	au_sync();
 
-		ret |= handled;
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_SOC_AU1200
+/* 8bit memory DMA device */
+static dbdev_tab_t au1xmmc_mem_dbdev = {
+	.dev_id		= DSCR_CMD0_ALWAYS,
+	.dev_flags	= DEV_FLAGS_ANYUSE,
+	.dev_tsize	= 0,
+	.dev_devwidth	= 8,
+	.dev_physaddr	= 0x00000000,
+	.dev_intlevel	= 0,
+	.dev_intpolarity = 0,
+};
+static int memid;
+
+static int au1xmmc_dbdma_init(struct au1xmmc_host *host)
+{
+	struct resource *res;
+	int txid, rxid;
+
+	res = platform_get_resource(host->pdev, IORESOURCE_DMA, 0);
+	if (!res)
+		return -ENODEV;
+	txid = res->start;
+
+	res = platform_get_resource(host->pdev, IORESOURCE_DMA, 1);
+	if (!res)
+		return -ENODEV;
+	rxid = res->start;
+
+	if (!memid)
+		return -ENODEV;
+
+	host->tx_chan = au1xxx_dbdma_chan_alloc(memid, txid,
+				au1xmmc_dma_callback, (void *)host);
+	if (!host->tx_chan) {
+		dev_err(&host->pdev->dev, "cannot allocate TX DMA\n");
+		return -ENODEV;
 	}
 
-	enable_irq(AU1100_SD_IRQ);
-	return ret;
+	host->rx_chan = au1xxx_dbdma_chan_alloc(rxid, memid,
+				au1xmmc_dma_callback, (void *)host);
+	if (!host->rx_chan) {
+		dev_err(&host->pdev->dev, "cannot allocate RX DMA\n");
+		au1xxx_dbdma_chan_free(host->tx_chan);
+		return -ENODEV;
+	}
+
+	au1xxx_dbdma_set_devwidth(host->tx_chan, 8);
+	au1xxx_dbdma_set_devwidth(host->rx_chan, 8);
+
+	au1xxx_dbdma_ring_alloc(host->tx_chan, AU1XMMC_DESCRIPTOR_COUNT);
+	au1xxx_dbdma_ring_alloc(host->rx_chan, AU1XMMC_DESCRIPTOR_COUNT);
+
+	/* DBDMA is good to go */
+	host->flags |= HOST_F_DMA;
+
+	return 0;
 }
 
-static void au1xmmc_poll_event(unsigned long arg)
+static void au1xmmc_dbdma_shutdown(struct au1xmmc_host *host)
 {
-	struct au1xmmc_host *host = (struct au1xmmc_host *) arg;
+	if (host->flags & HOST_F_DMA) {
+		host->flags &= ~HOST_F_DMA;
+		au1xxx_dbdma_chan_free(host->tx_chan);
+		au1xxx_dbdma_chan_free(host->rx_chan);
+	}
+}
+#endif
 
+static const struct mmc_host_ops au1xmmc_ops = {
+	.request	= au1xmmc_request,
+	.set_ios	= au1xmmc_set_ios,
+	.get_ro		= au1xmmc_card_readonly,
+};
+
+static void au1xmmc_poll_event(unsigned long arg)
+{
+	struct au1xmmc_host *host = (struct au1xmmc_host *)arg;
 	int card = au1xmmc_card_inserted(host);
-        int controller = (host->flags & HOST_F_ACTIVE) ? 1 : 0;
+	int controller = (host->flags & HOST_F_ACTIVE) ? 1 : 0;
 
 	if (card != controller) {
 		host->flags &= ~HOST_F_ACTIVE;
-		if (card) host->flags |= HOST_F_ACTIVE;
+		if (card)
+			host->flags |= HOST_F_ACTIVE;
 		mmc_detect_change(host->mmc, 0);
 	}
 
+#ifdef DEBUG
 	if (host->mrq != NULL) {
 		u32 status = au_readl(HOST_STATUS(host));
-		DBG("PENDING - %8.8x\n", host->id, status);
+		DBG("PENDING - %8.8x\n", host->pdev->id, status);
 	}
-
+#endif
 	mod_timer(&host->timer, jiffies + AU1XMMC_DETECT_TIMEOUT);
 }
 
-static dbdev_tab_t au1xmmc_mem_dbdev =
-{
-	DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 8, 0x00000000, 0, 0
-};
-
-static void au1xmmc_init_dma(struct au1xmmc_host *host)
+static void au1xmmc_init_cd_poll_timer(struct au1xmmc_host *host)
 {
-
-	u32 rxchan, txchan;
-
-	int txid = au1xmmc_card_table[host->id].tx_devid;
-	int rxid = au1xmmc_card_table[host->id].rx_devid;
-
-	/* DSCR_CMD0_ALWAYS has a stride of 32 bits, we need a stride
-	   of 8 bits.  And since devices are shared, we need to create
-	   our own to avoid freaking out other devices
-	*/
-
-	int memid = au1xxx_ddma_add_device(&au1xmmc_mem_dbdev);
-
-	txchan = au1xxx_dbdma_chan_alloc(memid, txid,
-					 au1xmmc_dma_callback, (void *) host);
-
-	rxchan = au1xxx_dbdma_chan_alloc(rxid, memid,
-					 au1xmmc_dma_callback, (void *) host);
-
-	au1xxx_dbdma_set_devwidth(txchan, 8);
-	au1xxx_dbdma_set_devwidth(rxchan, 8);
-
-	au1xxx_dbdma_ring_alloc(txchan, AU1XMMC_DESCRIPTOR_COUNT);
-	au1xxx_dbdma_ring_alloc(rxchan, AU1XMMC_DESCRIPTOR_COUNT);
-
-	host->tx_chan = txchan;
-	host->rx_chan = rxchan;
+	init_timer(&host->timer);
+	host->timer.function = au1xmmc_poll_event;
+	host->timer.data = (unsigned long)host;
+	host->timer.expires = jiffies + AU1XMMC_DETECT_TIMEOUT;
 }
 
-static const struct mmc_host_ops au1xmmc_ops = {
-	.request	= au1xmmc_request,
-	.set_ios	= au1xmmc_set_ios,
-	.get_ro		= au1xmmc_card_readonly,
-};
-
 static int __devinit au1xmmc_probe(struct platform_device *pdev)
 {
+	struct mmc_host *mmc;
+	struct au1xmmc_host *host;
+	struct resource *r;
+	int ret;
+
+	mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), &pdev->dev);
+	if (!mmc) {
+		dev_err(&pdev->dev, "no memory for mmc host\n");
+		ret = -ENOMEM;
+		goto out0;
+	}
 
-	int i, ret = 0;
-
-	/* THe interrupt is shared among all controllers */
-	ret = request_irq(AU1100_SD_IRQ, au1xmmc_irq, IRQF_DISABLED, "MMC", 0);
+	host = mmc_priv(mmc);
+	host->mmc = mmc;
+	host->platdata = pdev->dev.platform_data;
+	host->pdev = pdev;
 
-	if (ret) {
-		printk(DRIVER_NAME "ERROR: Couldn't get int %d: %d\n",
-				AU1100_SD_IRQ, ret);
-		return -ENXIO;
+	ret = -ENODEV;
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		dev_err(&pdev->dev, "no mmio defined\n");
+		goto out1;
 	}
 
-	disable_irq(AU1100_SD_IRQ);
+	host->ioarea = request_mem_region(r->start, r->end - r->start + 1,
+					   pdev->name);
+	if (!host->ioarea) {
+		dev_err(&pdev->dev, "mmio already used\n");
+		goto out1;
+	}
 
-	for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
-		struct mmc_host *mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), &pdev->dev);
-		struct au1xmmc_host *host = 0;
+	host->iobase = (unsigned long)ioremap(r->start, r->end - r->start + 1);
+	if (!host->iobase) {
+		dev_err(&pdev->dev, "cannot remap mmio\n");
+		goto out2;
+	}
 
-		if (!mmc) {
-			printk(DRIVER_NAME "ERROR: no mem for host %d\n", i);
-			au1xmmc_hosts[i] = 0;
-			continue;
-		}
+	r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!r) {
+		dev_err(&pdev->dev, "no IRQ defined\n");
+		goto out3;
+	}
 
-		mmc->ops = &au1xmmc_ops;
+	host->irq = r->start;
+	/* IRQ is shared among both SD controllers */
+	ret = request_irq(host->irq, au1xmmc_irq, IRQF_SHARED,
+			  DRIVER_NAME, host);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot grab IRQ\n");
+		goto out3;
+	}
 
-		mmc->f_min =   450000;
-		mmc->f_max = 24000000;
+	mmc->ops = &au1xmmc_ops;
 
-		mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE;
-		mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT;
+	mmc->f_min =   450000;
+	mmc->f_max = 24000000;
 
-		mmc->max_blk_size = 2048;
-		mmc->max_blk_count = 512;
+	mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE;
+	mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT;
 
-		mmc->ocr_avail = AU1XMMC_OCR;
+	mmc->max_blk_size = 2048;
+	mmc->max_blk_count = 512;
 
-		host = mmc_priv(mmc);
-		host->mmc = mmc;
+	mmc->ocr_avail = AU1XMMC_OCR;
+	mmc->caps = 0;
 
-		host->id = i;
-		host->iobase = au1xmmc_card_table[host->id].iobase;
-		host->clock = 0;
-		host->power_mode = MMC_POWER_OFF;
+	host->status = HOST_S_IDLE;
 
-		host->flags = au1xmmc_card_inserted(host) ? HOST_F_ACTIVE : 0;
-		host->status = HOST_S_IDLE;
+	/* board-specific carddetect setup, if any */
+	if (host->platdata && host->platdata->cd_setup) {
+		ret = host->platdata->cd_setup(mmc, 1);
+		if (ret) {
+			dev_err(&pdev->dev, "board CD setup failed\n");
+			goto out4;
+		}
+	} else {
+		/* poll the board-specific is-card-in-socket-? method */
+		au1xmmc_init_cd_poll_timer(host);
+	}
 
-		init_timer(&host->timer);
+	tasklet_init(&host->data_task, au1xmmc_tasklet_data,
+			(unsigned long)host);
 
-		host->timer.function = au1xmmc_poll_event;
-		host->timer.data = (unsigned long) host;
-		host->timer.expires = jiffies + AU1XMMC_DETECT_TIMEOUT;
+	tasklet_init(&host->finish_task, au1xmmc_tasklet_finish,
+			(unsigned long)host);
 
-		tasklet_init(&host->data_task, au1xmmc_tasklet_data,
-				(unsigned long) host);
+#ifdef CONFIG_SOC_Au1200
+	ret = au1xmmc_dbdma_init(host);
+	if (ret)
+		printk(KERN_INFO DRIVER_NAME ": DBDMA init failed; using PIO\n");
+#endif
 
-		tasklet_init(&host->finish_task, au1xmmc_tasklet_finish,
-				(unsigned long) host);
+	au1xmmc_reset_controller(host);
 
-		spin_lock_init(&host->lock);
+	ret = mmc_add_host(mmc);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot add mmc host\n");
+		goto out5;
+	}
 
-		if (dma != 0)
-			au1xmmc_init_dma(host);
+	platform_set_drvdata(pdev, mmc);
 
-		au1xmmc_reset_controller(host);
+	/* start the carddetect poll timer */
+	if (!(host->platdata && host->platdata->cd_setup))
+		add_timer(&host->timer);
 
-		mmc_add_host(mmc);
-		au1xmmc_hosts[i] = host;
+	printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X"
+		" (mode=%s)\n", pdev->id, host->iobase,
+		host->flags & HOST_F_DMA ? "dma" : "pio");
 
-		add_timer(&host->timer);
+	return 0;	/* all ok */
 
-		printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X (mode=%s)\n",
-		       host->id, host->iobase, dma ? "dma" : "pio");
-	}
+out5:
+	au_writel(0, HOST_ENABLE(host));
+	au_writel(0, HOST_CONFIG(host));
+	au_writel(0, HOST_CONFIG2(host));
+	au_sync();
 
-	enable_irq(AU1100_SD_IRQ);
+#ifdef CONFIG_SOC_AU1200
+	au1xmmc_dbdma_shutdown(host);
+#endif
 
-	return 0;
+	tasklet_kill(&host->data_task);
+	tasklet_kill(&host->finish_task);
+
+	if (host->platdata && host->platdata->cd_setup)
+		host->platdata->cd_setup(mmc, 0);
+out4:
+	free_irq(host->irq, host);
+out3:
+	iounmap((void *)host->iobase);
+out2:
+	release_resource(host->ioarea);
+	kfree(host->ioarea);
+out1:
+	mmc_free_host(mmc);
+out0:
+	return ret;
 }
 
 static int __devexit au1xmmc_remove(struct platform_device *pdev)
 {
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
+	struct au1xmmc_host *host;
+
+	if (mmc) {
+		host  = mmc_priv(mmc);
 
-	int i;
+		mmc_remove_host(mmc);
 
-	disable_irq(AU1100_SD_IRQ);
+		if (host->platdata && host->platdata->cd_setup)
+			host->platdata->cd_setup(mmc, 0);
+		else
+			del_timer_sync(&host->timer);
 
-	for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
-		struct au1xmmc_host *host = au1xmmc_hosts[i];
-		if (!host) continue;
+		au_writel(0, HOST_ENABLE(host));
+		au_writel(0, HOST_CONFIG(host));
+		au_writel(0, HOST_CONFIG2(host));
+		au_sync();
 
 		tasklet_kill(&host->data_task);
 		tasklet_kill(&host->finish_task);
 
-		del_timer_sync(&host->timer);
+#ifdef CONFIG_SOC_AU1200
+		au1xmmc_dbdma_shutdown(host);
+#endif
 		au1xmmc_set_power(host, 0);
 
-		mmc_remove_host(host->mmc);
-
-		au1xxx_dbdma_chan_free(host->tx_chan);
-		au1xxx_dbdma_chan_free(host->rx_chan);
+		free_irq(host->irq, host);
+		iounmap((void *)host->iobase);
+		release_resource(host->ioarea);
+		kfree(host->ioarea);
 
-		au_writel(0x0, HOST_ENABLE(host));
-		au_sync();
+		mmc_free_host(mmc);
 	}
-
-	free_irq(AU1100_SD_IRQ, 0);
 	return 0;
 }
 
@@ -1004,21 +1072,31 @@ static struct platform_driver au1xmmc_driver = {
 
 static int __init au1xmmc_init(void)
 {
+#ifdef CONFIG_SOC_AU1200
+	/* DSCR_CMD0_ALWAYS has a stride of 32 bits, we need a stride
+	 * of 8 bits.  And since devices are shared, we need to create
+	 * our own to avoid freaking out other devices.
+	 */
+	memid = au1xxx_ddma_add_device(&au1xmmc_mem_dbdev);
+	if (!memid)
+		printk(KERN_ERR "au1xmmc: cannot add memory dbdma dev\n");
+#endif
 	return platform_driver_register(&au1xmmc_driver);
 }
 
 static void __exit au1xmmc_exit(void)
 {
+#ifdef CONFIG_SOC_AU1200
+	if (memid)
+		au1xxx_ddma_del_device(memid);
+#endif
 	platform_driver_unregister(&au1xmmc_driver);
 }
 
 module_init(au1xmmc_init);
 module_exit(au1xmmc_exit);
 
-#ifdef MODULE
 MODULE_AUTHOR("Advanced Micro Devices, Inc");
 MODULE_DESCRIPTION("MMC/SD driver for the Alchemy Au1XXX");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:au1xxx-mmc");
-#endif
-
diff --git a/drivers/mmc/host/au1xmmc.h b/drivers/mmc/host/au1xmmc.h
index 341cbdf..3b40065 100644
--- a/drivers/mmc/host/au1xmmc.h
+++ b/drivers/mmc/host/au1xmmc.h
@@ -49,8 +49,6 @@ struct au1xmmc_host {
   struct mmc_host *mmc;
   struct mmc_request *mrq;
 
-  u32 id;
-
   u32 flags;
   u32 iobase;
   u32 clock;
@@ -73,11 +71,14 @@ struct au1xmmc_host {
   u32 tx_chan;
   u32 rx_chan;
 
+  int irq;
+
   struct timer_list timer;
   struct tasklet_struct finish_task;
   struct tasklet_struct data_task;
-
-  spinlock_t lock;
+  struct au1xmmc_platform_data *platdata;
+  struct platform_device *pdev;
+  struct resource *ioarea;
 };
 
 /* Status flags used by the host structure */
diff --git a/include/asm-mips/mach-au1x00/au1100_mmc.h b/include/asm-mips/mach-au1x00/au1100_mmc.h
index 9e0028f..c79dec1 100644
--- a/include/asm-mips/mach-au1x00/au1100_mmc.h
+++ b/include/asm-mips/mach-au1x00/au1100_mmc.h
@@ -38,15 +38,12 @@
 #ifndef __ASM_AU1100_MMC_H
 #define __ASM_AU1100_MMC_H
 
-
-#define NUM_AU1100_MMC_CONTROLLERS	2
-
-#if defined(CONFIG_SOC_AU1100)
-#define AU1100_SD_IRQ	AU1100_SD_INT
-#elif defined(CONFIG_SOC_AU1200)
-#define AU1100_SD_IRQ	AU1200_SD_INT
-#endif
-
+struct au1xmmc_platform_data {
+	int(*cd_setup)(void *mmc_host, int on);
+	int(*card_inserted)(void *mmc_host);
+	int(*card_readonly)(void *mmc_host);
+	void(*set_power)(void *mmc_host, int state);
+};
 
 #define SD0_BASE	0xB0600000
 #define SD1_BASE	0xB0680000
-- 
1.5.5.1


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

* [PATCH 4/9] Alchemy: register mmc platform device for db1200/pb1200 boards
  2008-05-19  8:03 [PATCH 0/9] au1xmmc updates #3 Manuel Lauss
                   ` (2 preceding siblings ...)
  2008-05-19  8:05 ` [PATCH 3/9] au1xmmc: remove pb1200 board-specific code from driver file Manuel Lauss
@ 2008-05-19  8:06 ` Manuel Lauss
  2008-05-21 12:32   ` Sergei Shtylyov
  2008-05-19  8:06 ` [PATCH 5/9] au1xmmc: enable 4 bit transfer mode Manuel Lauss
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 27+ messages in thread
From: Manuel Lauss @ 2008-05-19  8:06 UTC (permalink / raw)
  To: linux-mips, linux-kernel, drzeus, sshtylyov

>From 248ed1d1f9c8789e64a373efd37251cdcb9d522a Mon Sep 17 00:00:00 2001
From: Manuel Lauss <mlau@msc-ge.com>
Date: Sat, 17 May 2008 17:48:02 +0200
Subject: [PATCH] Alchemy: register mmc platform device for db1200/pb1200 boards

Add au1xmmc platform data for PB1200/DB1200 boards, and wire up
the 2 SD controllers for them.

Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
---
 arch/mips/au1000/common/platform.c |   88 ++++++++++++++++++++++++++----------
 arch/mips/au1000/pb1200/platform.c |   60 ++++++++++++++++++++++++
 2 files changed, 124 insertions(+), 24 deletions(-)

diff --git a/arch/mips/au1000/common/platform.c b/arch/mips/au1000/common/platform.c
index 8cae775..6225e95 100644
--- a/arch/mips/au1000/common/platform.c
+++ b/arch/mips/au1000/common/platform.c
@@ -16,6 +16,8 @@
 #include <linux/init.h>
 
 #include <asm/mach-au1x00/au1xxx.h>
+#include <asm/mach-au1x00/au1xxx_dbdma.h>
+#include <asm/mach-au1x00/au1100_mmc.h>
 
 #define PORT(_base, _irq)				\
 	{						\
@@ -162,24 +164,6 @@ static struct resource au1xxx_usb_gdt_resources[] = {
 	},
 };
 
-static struct resource au1xxx_mmc_resources[] = {
-	[0] = {
-		.start          = SD0_PHYS_ADDR,
-		.end            = SD0_PHYS_ADDR + 0x40,
-		.flags          = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start		= SD1_PHYS_ADDR,
-		.end 		= SD1_PHYS_ADDR + 0x40,
-		.flags		= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start          = AU1200_SD_INT,
-		.end            = AU1200_SD_INT,
-		.flags          = IORESOURCE_IRQ,
-	}
-};
-
 static u64 udc_dmamask = ~(u32)0;
 
 static struct platform_device au1xxx_usb_gdt_device = {
@@ -248,15 +232,70 @@ static struct platform_device au1200_lcd_device = {
 
 static u64 au1xxx_mmc_dmamask =  ~(u32)0;
 
-static struct platform_device au1xxx_mmc_device = {
+extern struct au1xmmc_platform_data au1xmmc_platdata[2];
+
+static struct resource au1200_mmc0_resources[] = {
+	[0] = {
+		.start          = SD0_PHYS_ADDR,
+		.end            = SD0_PHYS_ADDR + 0x7ffff,
+		.flags          = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= AU1200_SD_INT,
+		.flags		= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start		= DSCR_CMD0_SDMS_TX0,
+		.flags		= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start          = DSCR_CMD0_SDMS_RX0,
+		.flags          = IORESOURCE_DMA,
+	}
+};
+
+static struct resource au1200_mmc1_resources[] = {
+	[0] = {
+		.start          = SD1_PHYS_ADDR,
+		.end            = SD1_PHYS_ADDR + 0x7ffff,
+		.flags          = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= AU1200_SD_INT,
+		.flags		= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start		= DSCR_CMD0_SDMS_TX1,
+		.flags		= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start          = DSCR_CMD0_SDMS_RX1,
+		.flags          = IORESOURCE_DMA,
+	}
+};
+
+static struct platform_device au1200_mmc0_device = {
 	.name = "au1xxx-mmc",
 	.id = 0,
 	.dev = {
-		.dma_mask               = &au1xxx_mmc_dmamask,
-		.coherent_dma_mask      = 0xffffffff,
+		.dma_mask		= &au1xxx_mmc_dmamask,
+		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &au1xmmc_platdata[0],
+	},
+	.num_resources	= ARRAY_SIZE(au1200_mmc0_resources),
+	.resource	= au1200_mmc0_resources,
+};
+
+static struct platform_device au1200_mmc1_device = {
+	.name = "au1xxx-mmc",
+	.id = 1,
+	.dev = {
+		.dma_mask		= &au1xxx_mmc_dmamask,
+		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &au1xmmc_platdata[1],
 	},
-	.num_resources  = ARRAY_SIZE(au1xxx_mmc_resources),
-	.resource       = au1xxx_mmc_resources,
+	.num_resources	= ARRAY_SIZE(au1200_mmc1_resources),
+	.resource	= au1200_mmc1_resources,
 };
 #endif /* #ifdef CONFIG_SOC_AU1200 */
 
@@ -295,7 +334,8 @@ static struct platform_device *au1xxx_platform_devices[] __initdata = {
 	&au1xxx_usb_gdt_device,
 	&au1xxx_usb_otg_device,
 	&au1200_lcd_device,
-	&au1xxx_mmc_device,
+	&au1200_mmc0_device,
+	&au1200_mmc1_device,
 #endif
 #ifdef SMBUS_PSC_BASE
 	&pbdb_smbus_device,
diff --git a/arch/mips/au1000/pb1200/platform.c b/arch/mips/au1000/pb1200/platform.c
index 5930110..f329a38 100644
--- a/arch/mips/au1000/pb1200/platform.c
+++ b/arch/mips/au1000/pb1200/platform.c
@@ -22,6 +22,66 @@
 #include <linux/platform_device.h>
 
 #include <asm/mach-au1x00/au1xxx.h>
+#include <asm/mach-au1x00/au1100_mmc.h>
+
+static void pb1200mmc0_set_power(void *mmc_host, int state)
+{
+	if (state)
+		bcsr->board |= BCSR_BOARD_SD0PWR;
+	else
+		bcsr->board &= ~BCSR_BOARD_SD0PWR;
+
+	au_sync_delay(1);
+}
+
+static int pb1200mmc0_card_readonly(void *mmc_host)
+{
+	return (bcsr->status & BCSR_STATUS_SD0WP) ? 1 : 0;
+}
+
+static int pb1200mmc0_card_inserted(void *mmc_host)
+{
+	return (bcsr->sig_status & BCSR_INT_SD0INSERT) ? 1 : 0;
+}
+
+#ifndef CONFIG_MIPS_DB1200
+static void pb1200mmc1_set_power(void *mmc_host, int state)
+{
+	if (state)
+		bcsr->board |= BCSR_BOARD_SD1PWR;
+	else
+		bcsr->board &= ~BCSR_BOARD_SD1PWR;
+
+	au_sync_delay(1);
+}
+
+static int pb1200mmc1_card_readonly(void *mmc_host)
+{
+	return (bcsr->status & BCSR_STATUS_SD1WP) ? 1 : 0;
+}
+
+static int pb1200mmc1_card_inserted(void *mmc_host)
+{
+	return (bcsr->sig_status & BCSR_INT_SD1INSERT) ? 1 : 0;
+}
+#endif
+
+const struct au1xmmc_platform_data au1xmmc_platdata[2] = {
+	[0] = {
+		.set_power	= pb1200mmc0_set_power,
+		.card_inserted	= pb1200mmc0_card_inserted,
+		.card_readonly	= pb1200mmc0_card_readonly,
+		.cd_setup	= NULL,		/* use poll-timer in driver */
+	},
+#ifndef CONFIG_MIPS_DB1200
+	[1] = {
+		.set_power	= pb1200mmc1_set_power,
+		.card_inserted	= pb1200mmc1_card_inserted,
+		.card_readonly	= pb1200mmc1_card_readonly,
+		.cd_setup	= NULL,		/* use poll-timer in driver */
+	},
+#endif
+};
 
 static struct resource ide_resources[] = {
 	[0] = {
-- 
1.5.5.1


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

* [PATCH 5/9] au1xmmc: enable 4 bit transfer mode
  2008-05-19  8:03 [PATCH 0/9] au1xmmc updates #3 Manuel Lauss
                   ` (3 preceding siblings ...)
  2008-05-19  8:06 ` [PATCH 4/9] Alchemy: register mmc platform device for db1200/pb1200 boards Manuel Lauss
@ 2008-05-19  8:06 ` Manuel Lauss
  2008-05-19  8:06 ` [PATCH 6/9] au1xmmc: SDIO IRQ support Manuel Lauss
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 27+ messages in thread
From: Manuel Lauss @ 2008-05-19  8:06 UTC (permalink / raw)
  To: linux-mips, linux-kernel, drzeus, sshtylyov

>From 552bf7fadf935bfdac19b505ff4bd3ab8b280727 Mon Sep 17 00:00:00 2001
From: Manuel Lauss <mlau@msc-ge.com>
Date: Sat, 17 May 2008 17:53:57 +0200
Subject: [PATCH] au1xmmc: enable 4 bit transfer mode


Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
---
 drivers/mmc/host/au1xmmc.c |   22 +++++++++++++++++-----
 1 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index 9036677..234f324 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -94,14 +94,13 @@ static inline void IRQ_OFF(struct au1xmmc_host *host, u32 mask)
 
 static inline void SEND_STOP(struct au1xmmc_host *host)
 {
-
-	/* We know the value of CONFIG2, so avoid a read we don't need */
-	u32 mask = SD_CONFIG2_EN;
+	u32 config2;
 
 	WARN_ON(host->status != HOST_S_DATA);
 	host->status = HOST_S_STOP;
 
-	au_writel(mask | SD_CONFIG2_DF, HOST_CONFIG2(host));
+	config2 = au_readl(HOST_CONFIG2(host));
+	au_writel(config2 | SD_CONFIG2_DF, HOST_CONFIG2(host));
 	au_sync();
 
 	/* Send the stop commmand */
@@ -689,6 +688,7 @@ static void au1xmmc_reset_controller(struct au1xmmc_host *host)
 static void au1xmmc_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
 {
 	struct au1xmmc_host *host = mmc_priv(mmc);
+	u32 config2;
 
 	if (ios->power_mode == MMC_POWER_OFF)
 		au1xmmc_set_power(host, 0);
@@ -700,6 +700,18 @@ static void au1xmmc_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
 		au1xmmc_set_clock(host, ios->clock);
 		host->clock = ios->clock;
 	}
+
+	config2 = au_readl(HOST_CONFIG2(host));
+	switch (ios->bus_width) {
+	case MMC_BUS_WIDTH_4:
+		config2 |= SD_CONFIG2_WB;
+		break;
+	case MMC_BUS_WIDTH_1:
+		config2 &= ~SD_CONFIG2_WB;
+		break;
+	}
+	au_writel(config2, HOST_CONFIG2(host));
+	au_sync();
 }
 
 static void au1xmmc_dma_callback(int irq, void *dev_id)
@@ -945,7 +957,7 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev)
 	mmc->max_blk_count = 512;
 
 	mmc->ocr_avail = AU1XMMC_OCR;
-	mmc->caps = 0;
+	mmc->caps = MMC_CAP_4_BIT_DATA;
 
 	host->status = HOST_S_IDLE;
 
-- 
1.5.5.1


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

* [PATCH 6/9] au1xmmc: SDIO IRQ support
  2008-05-19  8:03 [PATCH 0/9] au1xmmc updates #3 Manuel Lauss
                   ` (4 preceding siblings ...)
  2008-05-19  8:06 ` [PATCH 5/9] au1xmmc: enable 4 bit transfer mode Manuel Lauss
@ 2008-05-19  8:06 ` Manuel Lauss
  2008-05-19  8:07 ` [PATCH 7/9] au1xmmc: codingstyle tidying Manuel Lauss
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 27+ messages in thread
From: Manuel Lauss @ 2008-05-19  8:06 UTC (permalink / raw)
  To: linux-mips, linux-kernel, drzeus, sshtylyov

>From 9621cb4d1b4160fec67fdf5eba6460cce5d37d74 Mon Sep 17 00:00:00 2001
From: Manuel Lauss <mlau@msc-ge.com>
Date: Sat, 17 May 2008 17:58:52 +0200
Subject: [PATCH] au1xmmc: SDIO IRQ support

Wire up the SD controllers' SDIO IRQ capability.

Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
---
 drivers/mmc/host/au1xmmc.c |   16 +++++++++++++++-
 1 files changed, 15 insertions(+), 1 deletions(-)

diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index 234f324..b3270b1 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -743,6 +743,9 @@ static irqreturn_t au1xmmc_irq(int irq, void *dev_id)
 	if (!(status & SD_STATUS_I))
 		return IRQ_NONE;	/* not ours */
 
+	if (status & SD_STATUS_SI)	/* SDIO */
+		mmc_signal_sdio_irq(host->mmc);
+
 	if (host->mrq && (status & STATUS_TIMEOUT)) {
 		if (status & SD_STATUS_RAT)
 			host->mrq->cmd->error = -ETIMEDOUT;
@@ -855,10 +858,21 @@ static void au1xmmc_dbdma_shutdown(struct au1xmmc_host *host)
 }
 #endif
 
+static void au1xmmc_enable_sdio_irq(struct mmc_host *mmc, int en)
+{
+	struct au1xmmc_host *host = mmc_priv(mmc);
+
+	if (en)
+		IRQ_ON(host, SD_CONFIG_SI);
+	else
+		IRQ_OFF(host, SD_CONFIG_SI);
+}
+
 static const struct mmc_host_ops au1xmmc_ops = {
 	.request	= au1xmmc_request,
 	.set_ios	= au1xmmc_set_ios,
 	.get_ro		= au1xmmc_card_readonly,
+	.enable_sdio_irq = au1xmmc_enable_sdio_irq,
 };
 
 static void au1xmmc_poll_event(unsigned long arg)
@@ -957,7 +971,7 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev)
 	mmc->max_blk_count = 512;
 
 	mmc->ocr_avail = AU1XMMC_OCR;
-	mmc->caps = MMC_CAP_4_BIT_DATA;
+	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
 
 	host->status = HOST_S_IDLE;
 
-- 
1.5.5.1


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

* [PATCH 7/9] au1xmmc: codingstyle tidying
  2008-05-19  8:03 [PATCH 0/9] au1xmmc updates #3 Manuel Lauss
                   ` (5 preceding siblings ...)
  2008-05-19  8:06 ` [PATCH 6/9] au1xmmc: SDIO IRQ support Manuel Lauss
@ 2008-05-19  8:07 ` Manuel Lauss
  2008-05-19  8:08 ` [PATCH 8/9] au1xmmc: abort requests early if no card is present Manuel Lauss
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 27+ messages in thread
From: Manuel Lauss @ 2008-05-19  8:07 UTC (permalink / raw)
  To: linux-mips, linux-kernel, drzeus, sshtylyov

>From 6a39da961304872210106e80ba07937bf88544bd Mon Sep 17 00:00:00 2001
From: Manuel Lauss <mlau@msc-ge.com>
Date: Sat, 17 May 2008 18:30:00 +0200
Subject: [PATCH] au1xmmc: codingstyle tidying

Clean up the codebase, no functional changes.
- merge the au1xmmc.h header contents into the driver file,
- indentation, spelling and style fixes.

Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
---
 drivers/mmc/host/au1xmmc.c |  254 ++++++++++++++++++++++++++------------------
 drivers/mmc/host/au1xmmc.h |   97 -----------------
 2 files changed, 151 insertions(+), 200 deletions(-)
 delete mode 100644 drivers/mmc/host/au1xmmc.h

diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index b3270b1..be09a14 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -41,15 +41,14 @@
 #include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 #include <linux/scatterlist.h>
-
 #include <linux/mmc/host.h>
+
 #include <asm/io.h>
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1xxx_dbdma.h>
 #include <asm/mach-au1x00/au1100_mmc.h>
 
 #include <au1xxx.h>
-#include "au1xmmc.h"
 
 #define DRIVER_NAME "au1xxx-mmc"
 
@@ -57,11 +56,98 @@
 /* #define DEBUG */
 
 #ifdef DEBUG
-#define DBG(fmt, idx, args...) printk("au1xx(%d): DEBUG: " fmt, idx, ##args)
+#define DBG(fmt, idx, args...)	\
+	printk(KERN_DEBUG "au1xmmc(%d): DEBUG: " fmt, idx, ##args)
 #else
-#define DBG(fmt, idx, args...)
+#define DBG(fmt, idx, args...) do {} while (0)
 #endif
 
+/* Hardware definitions */
+#define AU1XMMC_DESCRIPTOR_COUNT 1
+#define AU1XMMC_DESCRIPTOR_SIZE  2048
+
+#define AU1XMMC_OCR (MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 | \
+		     MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33 | \
+		     MMC_VDD_33_34 | MMC_VDD_34_35 | MMC_VDD_35_36)
+
+/* This gives us a hard value for the stop command that we can write directly
+ * to the command register.
+ */
+#define STOP_CMD	\
+	(SD_CMD_RT_1B | SD_CMD_CT_7 | (0xC << SD_CMD_CI_SHIFT) | SD_CMD_GO)
+
+/* This is the set of interrupts that we configure by default. */
+#define AU1XMMC_INTERRUPTS 				\
+	(SD_CONFIG_SC | SD_CONFIG_DT | SD_CONFIG_RAT |	\
+	 SD_CONFIG_CR | SD_CONFIG_I)
+
+/* The poll event (looking for insert/remove events runs twice a second. */
+#define AU1XMMC_DETECT_TIMEOUT (HZ/2)
+
+struct au1xmmc_host {
+	struct mmc_host *mmc;
+	struct mmc_request *mrq;
+
+	u32 flags;
+	u32 iobase;
+	u32 clock;
+	u32 bus_width;
+	u32 power_mode;
+
+	int status;
+
+	struct {
+		int len;
+		int dir;
+	} dma;
+
+	struct {
+		int index;
+		int offset;
+		int len;
+	} pio;
+
+	u32 tx_chan;
+	u32 rx_chan;
+
+	int irq;
+
+	struct timer_list timer;
+	struct tasklet_struct finish_task;
+	struct tasklet_struct data_task;
+	struct au1xmmc_platform_data *platdata;
+	struct platform_device *pdev;
+	struct resource *ioarea;
+};
+
+/* Status flags used by the host structure */
+#define HOST_F_XMIT	0x0001
+#define HOST_F_RECV	0x0002
+#define HOST_F_DMA	0x0010
+#define HOST_F_ACTIVE	0x0100
+#define HOST_F_STOP	0x1000
+
+#define HOST_S_IDLE	0x0001
+#define HOST_S_CMD	0x0002
+#define HOST_S_DATA	0x0003
+#define HOST_S_STOP	0x0004
+
+/* Easy access macros */
+#define HOST_STATUS(h)	((h)->iobase + SD_STATUS)
+#define HOST_CONFIG(h)	((h)->iobase + SD_CONFIG)
+#define HOST_ENABLE(h)	((h)->iobase + SD_ENABLE)
+#define HOST_TXPORT(h)	((h)->iobase + SD_TXPORT)
+#define HOST_RXPORT(h)	((h)->iobase + SD_RXPORT)
+#define HOST_CMDARG(h)	((h)->iobase + SD_CMDARG)
+#define HOST_BLKSIZE(h)	((h)->iobase + SD_BLKSIZE)
+#define HOST_CMD(h)	((h)->iobase + SD_CMD)
+#define HOST_CONFIG2(h)	((h)->iobase + SD_CONFIG2)
+#define HOST_TIMEOUT(h)	((h)->iobase + SD_TIMEOUT)
+#define HOST_DEBUG(h)	((h)->iobase + SD_DEBUG)
+
+#define DMA_CHANNEL(h)	\
+	(((h)->flags & HOST_F_XMIT) ? (h)->tx_chan : (h)->rx_chan)
+
 static inline void IRQ_ON(struct au1xmmc_host *host, u32 mask)
 {
 	u32 val = au_readl(HOST_CONFIG(host));
@@ -140,7 +226,6 @@ static int au1xmmc_card_readonly(struct mmc_host *mmc)
 
 static void au1xmmc_finish_request(struct au1xmmc_host *host)
 {
-
 	struct mmc_request *mrq = host->mrq;
 
 	host->mrq = NULL;
@@ -214,18 +299,14 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait,
 	au_sync();
 
 	/* Wait for the command to go on the line */
-
-	while(1) {
-		if (!(au_readl(HOST_CMD(host)) & SD_CMD_GO))
-			break;
-	}
+	while (au_readl(HOST_CMD(host)) & SD_CMD_GO)
+		/* nop */;
 
 	/* Wait for the command to come back */
-
 	if (wait) {
 		u32 status = au_readl(HOST_STATUS(host));
 
-		while(!(status & SD_STATUS_CR))
+		while (!(status & SD_STATUS_CR))
 			status = au_readl(HOST_STATUS(host));
 
 		/* Clear the CR status */
@@ -239,12 +320,11 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait,
 
 static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status)
 {
-
 	struct mmc_request *mrq = host->mrq;
 	struct mmc_data *data;
 	u32 crc;
 
-	WARN_ON(host->status != HOST_S_DATA && host->status != HOST_S_STOP);
+	WARN_ON((host->status != HOST_S_DATA) && (host->status != HOST_S_STOP));
 
 	if (host->mrq == NULL)
 		return;
@@ -255,15 +335,13 @@ static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status)
 		status = au_readl(HOST_STATUS(host));
 
 	/* The transaction is really over when the SD_STATUS_DB bit is clear */
-
-	while((host->flags & HOST_F_XMIT) && (status & SD_STATUS_DB))
+	while ((host->flags & HOST_F_XMIT) && (status & SD_STATUS_DB))
 		status = au_readl(HOST_STATUS(host));
 
 	data->error = 0;
 	dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma.dir);
 
         /* Process any errors */
-
 	crc = (status & (SD_STATUS_WC | SD_STATUS_RC));
 	if (host->flags & HOST_F_XMIT)
 		crc |= ((status & 0x07) == 0x02) ? 0 : 1;
@@ -280,14 +358,12 @@ static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status)
 		if (host->flags & HOST_F_DMA) {
 			u32 chan = DMA_CHANNEL(host);
 
-			chan_tab_t *c = *((chan_tab_t **) chan);
+			chan_tab_t *c = *((chan_tab_t **)chan);
 			au1x_dma_chan_t *cp = c->chan_ptr;
 			data->bytes_xfered = cp->ddma_bytecnt;
-		}
-		else
+		} else
 			data->bytes_xfered =
-				(data->blocks * data->blksz) -
-				host->pio.len;
+				(data->blocks * data->blksz) - host->pio.len;
 	}
 
 	au1xmmc_finish_request(host);
@@ -295,7 +371,7 @@ static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status)
 
 static void au1xmmc_tasklet_data(unsigned long param)
 {
-	struct au1xmmc_host *host = (struct au1xmmc_host *) param;
+	struct au1xmmc_host *host = (struct au1xmmc_host *)param;
 
 	u32 status = au_readl(HOST_STATUS(host));
 	au1xmmc_data_complete(host, status);
@@ -305,11 +381,10 @@ static void au1xmmc_tasklet_data(unsigned long param)
 
 static void au1xmmc_send_pio(struct au1xmmc_host *host)
 {
-
-	struct mmc_data *data = 0;
-	int sg_len, max, count = 0;
-	unsigned char *sg_ptr;
-	u32 status = 0;
+	struct mmc_data *data;
+	int sg_len, max, count;
+	unsigned char *sg_ptr, val;
+	u32 status;
 	struct scatterlist *sg;
 
 	data = host->mrq->data;
@@ -324,14 +399,12 @@ static void au1xmmc_send_pio(struct au1xmmc_host *host)
 	/* This is the space left inside the buffer */
 	sg_len = data->sg[host->pio.index].length - host->pio.offset;
 
-	/* Check to if we need less then the size of the sg_buffer */
-
+	/* Check if we need less than the size of the sg_buffer */
 	max = (sg_len > host->pio.len) ? host->pio.len : sg_len;
-	if (max > AU1XMMC_MAX_TRANSFER) max = AU1XMMC_MAX_TRANSFER;
-
-	for(count = 0; count < max; count++ ) {
-		unsigned char val;
+	if (max > AU1XMMC_MAX_TRANSFER)
+		max = AU1XMMC_MAX_TRANSFER;
 
+	for (count = 0; count < max; count++) {
 		status = au_readl(HOST_STATUS(host));
 
 		if (!(status & SD_STATUS_TH))
@@ -339,7 +412,7 @@ static void au1xmmc_send_pio(struct au1xmmc_host *host)
 
 		val = *sg_ptr++;
 
-		au_writel((unsigned long) val, HOST_TXPORT(host));
+		au_writel((unsigned long)val, HOST_TXPORT(host));
 		au_sync();
 	}
 
@@ -363,11 +436,10 @@ static void au1xmmc_send_pio(struct au1xmmc_host *host)
 
 static void au1xmmc_receive_pio(struct au1xmmc_host *host)
 {
-
-	struct mmc_data *data = 0;
-	int sg_len = 0, max = 0, count = 0;
-	unsigned char *sg_ptr = 0;
-	u32 status = 0;
+	struct mmc_data *data;
+	int max, count, sg_len = 0;
+	unsigned char *sg_ptr = NULL;
+	u32 status, val;
 	struct scatterlist *sg;
 
 	data = host->mrq->data;
@@ -384,15 +456,15 @@ static void au1xmmc_receive_pio(struct au1xmmc_host *host)
 		/* This is the space left inside the buffer */
 		sg_len = sg_dma_len(&data->sg[host->pio.index]) - host->pio.offset;
 
-		/* Check to if we need less then the size of the sg_buffer */
-		if (sg_len < max) max = sg_len;
+		/* Check if we need less than the size of the sg_buffer */
+		if (sg_len < max)
+			max = sg_len;
 	}
 
 	if (max > AU1XMMC_MAX_TRANSFER)
 		max = AU1XMMC_MAX_TRANSFER;
 
-	for(count = 0; count < max; count++ ) {
-		u32 val;
+	for (count = 0; count < max; count++) {
 		status = au_readl(HOST_STATUS(host));
 
 		if (!(status & SD_STATUS_NE))
@@ -418,7 +490,7 @@ static void au1xmmc_receive_pio(struct au1xmmc_host *host)
 		val = au_readl(HOST_RXPORT(host));
 
 		if (sg_ptr)
-			*sg_ptr++ = (unsigned char) (val & 0xFF);
+			*sg_ptr++ = (unsigned char)(val & 0xFF);
 	}
 
 	host->pio.len -= count;
@@ -430,7 +502,7 @@ static void au1xmmc_receive_pio(struct au1xmmc_host *host)
 	}
 
 	if (host->pio.len == 0) {
-		//IRQ_OFF(host, SD_CONFIG_RA | SD_CONFIG_RF);
+		/* IRQ_OFF(host, SD_CONFIG_RA | SD_CONFIG_RF); */
 		IRQ_OFF(host, SD_CONFIG_NE);
 
 		if (host->flags & HOST_F_STOP)
@@ -440,17 +512,15 @@ static void au1xmmc_receive_pio(struct au1xmmc_host *host)
 	}
 }
 
-/* static void au1xmmc_cmd_complete
-   This is called when a command has been completed - grab the response
-   and check for errors.  Then start the data transfer if it is indicated.
-*/
-
+/* This is called when a command has been completed - grab the response
+ * and check for errors.  Then start the data transfer if it is indicated.
+ */
 static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
 {
-
 	struct mmc_request *mrq = host->mrq;
 	struct mmc_command *cmd;
-	int trans;
+	u32 r[4], mask;
+	int i, trans;
 
 	if (!host->mrq)
 		return;
@@ -460,9 +530,6 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
 
 	if (cmd->flags & MMC_RSP_PRESENT) {
 		if (cmd->flags & MMC_RSP_136) {
-			u32 r[4];
-			int i;
-
 			r[0] = au_readl(host->iobase + SD_RESP3);
 			r[1] = au_readl(host->iobase + SD_RESP2);
 			r[2] = au_readl(host->iobase + SD_RESP1);
@@ -470,10 +537,9 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
 
 			/* The CRC is omitted from the response, so really
 			 * we only got 120 bytes, but the engine expects
-			 * 128 bits, so we have to shift things up
+			 * 128 bits, so we have to shift things up.
 			 */
-
-			for(i = 0; i < 4; i++) {
+			for (i = 0; i < 4; i++) {
 				cmd->resp[i] = (r[i] & 0x00FFFFFF) << 8;
 				if (i != 3)
 					cmd->resp[i] |= (r[i + 1] & 0xFF000000) >> 24;
@@ -484,22 +550,20 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
 			 * our response omits the CRC, our data ends up
 			 * being shifted 8 bits to the right.  In this case,
 			 * that means that the OSR data starts at bit 31,
-			 * so we can just read RESP0 and return that
+			 * so we can just read RESP0 and return that.
 			 */
 			cmd->resp[0] = au_readl(host->iobase + SD_RESP0);
 		}
 	}
 
         /* Figure out errors */
-
 	if (status & (SD_STATUS_SC | SD_STATUS_WC | SD_STATUS_RC))
 		cmd->error = -EILSEQ;
 
 	trans = host->flags & (HOST_F_XMIT | HOST_F_RECV);
 
 	if (!trans || cmd->error) {
-
-		IRQ_OFF(host, SD_CONFIG_TH | SD_CONFIG_RA|SD_CONFIG_RF);
+		IRQ_OFF(host, SD_CONFIG_TH | SD_CONFIG_RA | SD_CONFIG_RF);
 		tasklet_schedule(&host->finish_task);
 		return;
 	}
@@ -510,11 +574,10 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
 		u32 channel = DMA_CHANNEL(host);
 
 		/* Start the DMA as soon as the buffer gets something in it */
-
 		if (host->flags & HOST_F_RECV) {
-			u32 mask = SD_STATUS_DB | SD_STATUS_NE;
+			mask = SD_STATUS_DB | SD_STATUS_NE;
 
-			while((status & mask) != mask)
+			while ((status & mask) != mask)
 				status = au_readl(HOST_STATUS(host));
 		}
 
@@ -524,18 +587,15 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
 
 static void au1xmmc_set_clock(struct au1xmmc_host *host, int rate)
 {
-
 	unsigned int pbus = get_au1x00_speed();
 	unsigned int divisor;
 	u32 config;
 
 	/* From databook:
-	   divisor = ((((cpuclock / sbus_divisor) / 2) / mmcclock) / 2) - 1
-	*/
-
+	 * divisor = ((((cpuclock / sbus_divisor) / 2) / mmcclock) / 2) - 1
+	 */
 	pbus /= ((au_readl(SYS_POWERCTRL) & 0x3) + 2);
 	pbus /= 2;
-
 	divisor = ((pbus / rate) / 2) - 1;
 
 	config = au_readl(HOST_CONFIG(host));
@@ -547,8 +607,8 @@ static void au1xmmc_set_clock(struct au1xmmc_host *host, int rate)
 	au_sync();
 }
 
-static int
-au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data)
+static int au1xmmc_prepare_data(struct au1xmmc_host *host,
+				struct mmc_data *data)
 {
 	int datalen = data->blocks * data->blksz;
 
@@ -576,33 +636,29 @@ au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data)
 
 		au1xxx_dbdma_stop(channel);
 
-		for(i = 0; i < host->dma.len; i++) {
+		for (i = 0; i < host->dma.len; i++) {
 			u32 ret = 0, flags = DDMA_FLAGS_NOIE;
 			struct scatterlist *sg = &data->sg[i];
 			int sg_len = sg->length;
-
 			int len = (datalen > sg_len) ? sg_len : datalen;
 
 			if (i == host->dma.len - 1)
 				flags = DDMA_FLAGS_IE;
 
-    			if (host->flags & HOST_F_XMIT){
-      				ret = au1xxx_dbdma_put_source_flags(channel,
-					(void *) sg_virt(sg), len, flags);
-			}
-    			else {
-      				ret = au1xxx_dbdma_put_dest_flags(channel,
-					(void *) sg_virt(sg),
-					len, flags);
+			if (host->flags & HOST_F_XMIT) {
+				ret = au1xxx_dbdma_put_source_flags(channel,
+					(void *)sg_virt(sg), len, flags);
+			} else {
+				ret = au1xxx_dbdma_put_dest_flags(channel,
+					(void *)sg_virt(sg), len, flags);
 			}
 
-    			if (!ret)
+			if (!ret)
 				goto dataerr;
 
 			datalen -= len;
 		}
-	}
-	else {
+	} else {
 		host->pio.index = 0;
 		host->pio.offset = 0;
 		host->pio.len = datalen;
@@ -611,25 +667,20 @@ au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data)
 			IRQ_ON(host, SD_CONFIG_TH);
 		else
 			IRQ_ON(host, SD_CONFIG_NE);
-			//IRQ_ON(host, SD_CONFIG_RA|SD_CONFIG_RF);
+			/* IRQ_ON(host, SD_CONFIG_RA | SD_CONFIG_RF); */
 	}
 
 	return 0;
 
- dataerr:
+dataerr:
 	dma_unmap_sg(mmc_dev(host->mmc),data->sg,data->sg_len,host->dma.dir);
 	return -ETIMEDOUT;
 }
 
-/* static void au1xmmc_request
-   This actually starts a command or data transaction
-*/
-
-static void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq)
+/* This actually starts a command or data transaction */
+static void au1xmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
-
 	struct au1xmmc_host *host = mmc_priv(mmc);
-	unsigned int flags = 0;
 	int ret = 0;
 
 	WARN_ON(irqs_disabled());
@@ -640,7 +691,6 @@ static void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq)
 
 	if (mrq->data) {
 		FLUSH_FIFO(host);
-		flags = mrq->data->flags;
 		ret = au1xmmc_prepare_data(host, mrq->data);
 	}
 
@@ -655,7 +705,6 @@ static void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq)
 
 static void au1xmmc_reset_controller(struct au1xmmc_host *host)
 {
-
 	/* Apply the clock */
 	au_writel(SD_ENABLE_CE, HOST_ENABLE(host));
         au_sync_delay(1);
@@ -685,7 +734,7 @@ static void au1xmmc_reset_controller(struct au1xmmc_host *host)
 }
 
 
-static void au1xmmc_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
+static void au1xmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct au1xmmc_host *host = mmc_priv(mmc);
 	u32 config2;
@@ -716,10 +765,9 @@ static void au1xmmc_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
 
 static void au1xmmc_dma_callback(int irq, void *dev_id)
 {
-	struct au1xmmc_host *host = (struct au1xmmc_host *) dev_id;
+	struct au1xmmc_host *host = (struct au1xmmc_host *)dev_id;
 
 	/* Avoid spurious interrupts */
-
 	if (!host->mrq)
 		return;
 
@@ -729,9 +777,9 @@ static void au1xmmc_dma_callback(int irq, void *dev_id)
 	tasklet_schedule(&host->data_task);
 }
 
-#define STATUS_TIMEOUT (SD_STATUS_RAT | SD_STATUS_DT)
-#define STATUS_DATA_IN  (SD_STATUS_NE)
-#define STATUS_DATA_OUT (SD_STATUS_TH)
+#define STATUS_TIMEOUT	(SD_STATUS_RAT | SD_STATUS_DT)
+#define STATUS_DATA_IN	(SD_STATUS_NE)
+#define STATUS_DATA_OUT	(SD_STATUS_TH)
 
 static irqreturn_t au1xmmc_irq(int irq, void *dev_id)
 {
diff --git a/drivers/mmc/host/au1xmmc.h b/drivers/mmc/host/au1xmmc.h
deleted file mode 100644
index 3b40065..0000000
--- a/drivers/mmc/host/au1xmmc.h
+++ /dev/null
@@ -1,97 +0,0 @@
-#ifndef _AU1XMMC_H_
-#define _AU1XMMC_H_
-
-/* Hardware definitions */
-
-#define AU1XMMC_DESCRIPTOR_COUNT 1
-#define AU1XMMC_DESCRIPTOR_SIZE  2048
-
-#define AU1XMMC_OCR ( MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30  | \
-		      MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33  | \
-		      MMC_VDD_33_34 | MMC_VDD_34_35 | MMC_VDD_35_36)
-
-/* Easy access macros */
-
-#define HOST_STATUS(h)	((h)->iobase + SD_STATUS)
-#define HOST_CONFIG(h)	((h)->iobase + SD_CONFIG)
-#define HOST_ENABLE(h)	((h)->iobase + SD_ENABLE)
-#define HOST_TXPORT(h)	((h)->iobase + SD_TXPORT)
-#define HOST_RXPORT(h)	((h)->iobase + SD_RXPORT)
-#define HOST_CMDARG(h)	((h)->iobase + SD_CMDARG)
-#define HOST_BLKSIZE(h)	((h)->iobase + SD_BLKSIZE)
-#define HOST_CMD(h)	((h)->iobase + SD_CMD)
-#define HOST_CONFIG2(h)	((h)->iobase + SD_CONFIG2)
-#define HOST_TIMEOUT(h)	((h)->iobase + SD_TIMEOUT)
-#define HOST_DEBUG(h)	((h)->iobase + SD_DEBUG)
-
-#define DMA_CHANNEL(h) \
-	( ((h)->flags & HOST_F_XMIT) ? (h)->tx_chan : (h)->rx_chan)
-
-/* This gives us a hard value for the stop command that we can write directly
- * to the command register
- */
-
-#define STOP_CMD (SD_CMD_RT_1B|SD_CMD_CT_7|(0xC << SD_CMD_CI_SHIFT)|SD_CMD_GO)
-
-/* This is the set of interrupts that we configure by default */
-
-#if 0
-#define AU1XMMC_INTERRUPTS (SD_CONFIG_SC | SD_CONFIG_DT | SD_CONFIG_DD | \
-		SD_CONFIG_RAT | SD_CONFIG_CR | SD_CONFIG_I)
-#endif
-
-#define AU1XMMC_INTERRUPTS (SD_CONFIG_SC | SD_CONFIG_DT | \
-		SD_CONFIG_RAT | SD_CONFIG_CR | SD_CONFIG_I)
-/* The poll event (looking for insert/remove events runs twice a second */
-#define AU1XMMC_DETECT_TIMEOUT (HZ/2)
-
-struct au1xmmc_host {
-  struct mmc_host *mmc;
-  struct mmc_request *mrq;
-
-  u32 flags;
-  u32 iobase;
-  u32 clock;
-  u32 bus_width;
-  u32 power_mode;
-
-  int status;
-
-   struct {
-	   int len;
-	   int dir;
-  } dma;
-
-   struct {
-	   int index;
-	   int offset;
-	   int len;
-  } pio;
-
-  u32 tx_chan;
-  u32 rx_chan;
-
-  int irq;
-
-  struct timer_list timer;
-  struct tasklet_struct finish_task;
-  struct tasklet_struct data_task;
-  struct au1xmmc_platform_data *platdata;
-  struct platform_device *pdev;
-  struct resource *ioarea;
-};
-
-/* Status flags used by the host structure */
-
-#define HOST_F_XMIT   0x0001
-#define HOST_F_RECV   0x0002
-#define HOST_F_DMA    0x0010
-#define HOST_F_ACTIVE 0x0100
-#define HOST_F_STOP   0x1000
-
-#define HOST_S_IDLE   0x0001
-#define HOST_S_CMD    0x0002
-#define HOST_S_DATA   0x0003
-#define HOST_S_STOP   0x0004
-
-#endif
-- 
1.5.5.1


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

* [PATCH 8/9] au1xmmc: abort requests early if no card is present
  2008-05-19  8:03 [PATCH 0/9] au1xmmc updates #3 Manuel Lauss
                   ` (6 preceding siblings ...)
  2008-05-19  8:07 ` [PATCH 7/9] au1xmmc: codingstyle tidying Manuel Lauss
@ 2008-05-19  8:08 ` Manuel Lauss
  2008-06-05 21:05   ` Pierre Ossman
  2008-05-19  8:08 ` [PATCH 9/9] au1xmmc: Add back PB1200/DB1200 MMC activity LED support Manuel Lauss
  2008-06-05 21:09 ` [PATCH 0/9] au1xmmc updates #3 Pierre Ossman
  9 siblings, 1 reply; 27+ messages in thread
From: Manuel Lauss @ 2008-05-19  8:08 UTC (permalink / raw)
  To: linux-mips, linux-kernel, drzeus, sshtylyov

>From ec41439903048bf98e301dbd03426c63156ebc0e Mon Sep 17 00:00:00 2001
From: Manuel Lauss <mlau@msc-ge.com>
Date: Sun, 18 May 2008 15:52:43 +0200
Subject: [PATCH] au1xmmc: abort requests early if no card is present

Don't process a request if no card is present.

Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
---
 drivers/mmc/host/au1xmmc.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index be09a14..0b30582 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -689,6 +689,13 @@ static void au1xmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 	host->mrq = mrq;
 	host->status = HOST_S_CMD;
 
+	/* fail request immediately if no card is present */
+	if (0 == au1xmmc_card_inserted(host)) {
+		mrq->cmd->error = -ETIMEDOUT;
+		au1xmmc_finish_request(host);
+		return;
+	}
+
 	if (mrq->data) {
 		FLUSH_FIFO(host);
 		ret = au1xmmc_prepare_data(host, mrq->data);
-- 
1.5.5.1


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

* [PATCH 9/9] au1xmmc: Add back PB1200/DB1200 MMC activity LED support
  2008-05-19  8:03 [PATCH 0/9] au1xmmc updates #3 Manuel Lauss
                   ` (7 preceding siblings ...)
  2008-05-19  8:08 ` [PATCH 8/9] au1xmmc: abort requests early if no card is present Manuel Lauss
@ 2008-05-19  8:08 ` Manuel Lauss
  2008-05-19 13:27   ` Sergei Shtylyov
  2008-06-05 21:08   ` Pierre Ossman
  2008-06-05 21:09 ` [PATCH 0/9] au1xmmc updates #3 Pierre Ossman
  9 siblings, 2 replies; 27+ messages in thread
From: Manuel Lauss @ 2008-05-19  8:08 UTC (permalink / raw)
  To: linux-mips, linux-kernel, drzeus, sshtylyov

>From 5747bd6933bb212ab83044fa79adf185d248513f Mon Sep 17 00:00:00 2001
From: Manuel Lauss <mlau@msc-ge.com>
Date: Sun, 18 May 2008 16:05:56 +0200
Subject: [PATCH] au1xmmc: Add back PB1200/DB1200 MMC activity LED support.

Add back PB1200/DB1200 MMC activity LED support just the way
it was done in the original driver source.

Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
---
 arch/mips/au1000/pb1200/platform.c        |   15 +++++++++++++++
 drivers/mmc/host/au1xmmc.c                |   10 ++++++++++
 include/asm-mips/mach-au1x00/au1100_mmc.h |    1 +
 3 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/arch/mips/au1000/pb1200/platform.c b/arch/mips/au1000/pb1200/platform.c
index f329a38..f48723c 100644
--- a/arch/mips/au1000/pb1200/platform.c
+++ b/arch/mips/au1000/pb1200/platform.c
@@ -24,6 +24,8 @@
 #include <asm/mach-au1x00/au1xxx.h>
 #include <asm/mach-au1x00/au1100_mmc.h>
 
+static int mmc_activity = 0;
+
 static void pb1200mmc0_set_power(void *mmc_host, int state)
 {
 	if (state)
@@ -44,6 +46,17 @@ static int pb1200mmc0_card_inserted(void *mmc_host)
 	return (bcsr->sig_status & BCSR_INT_SD0INSERT) ? 1 : 0;
 }
 
+static void pb1200mmc_activity(int on)
+{
+	if (on) {
+		if (++mmc_activity == 1)
+			bcsr->disk_leds &= ~(1 << 8);
+	} else {
+		if (--mmc_activity == 0)
+			bcsr->disk_leds |= (1 << 8);
+	}
+}
+
 #ifndef CONFIG_MIPS_DB1200
 static void pb1200mmc1_set_power(void *mmc_host, int state)
 {
@@ -72,6 +85,7 @@ const struct au1xmmc_platform_data au1xmmc_platdata[2] = {
 		.card_inserted	= pb1200mmc0_card_inserted,
 		.card_readonly	= pb1200mmc0_card_readonly,
 		.cd_setup	= NULL,		/* use poll-timer in driver */
+		.activity	= pb1200mmc_activity,
 	},
 #ifndef CONFIG_MIPS_DB1200
 	[1] = {
@@ -79,6 +93,7 @@ const struct au1xmmc_platform_data au1xmmc_platdata[2] = {
 		.card_inserted	= pb1200mmc1_card_inserted,
 		.card_readonly	= pb1200mmc1_card_readonly,
 		.cd_setup	= NULL,		/* use poll-timer in driver */
+		.activity	= pb1200mmc_activity,
 	},
 #endif
 };
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index 0b30582..67df6fe 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -224,6 +224,12 @@ static int au1xmmc_card_readonly(struct mmc_host *mmc)
 	return ret;
 }
 
+static inline void au1xmmc_activity(struct au1xmmc_host *host, int on)
+{
+	if (host->platdata && host->platdata->activity)
+		host->platdata->activity(on);
+}
+
 static void au1xmmc_finish_request(struct au1xmmc_host *host)
 {
 	struct mmc_request *mrq = host->mrq;
@@ -240,6 +246,8 @@ static void au1xmmc_finish_request(struct au1xmmc_host *host)
 
 	host->status = HOST_S_IDLE;
 
+	au1xmmc_activity(host, 0);
+
 	mmc_request_done(host->mmc, mrq);
 }
 
@@ -696,6 +704,8 @@ static void au1xmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 		return;
 	}
 
+	au1xmmc_activity(host, 1);
+
 	if (mrq->data) {
 		FLUSH_FIFO(host);
 		ret = au1xmmc_prepare_data(host, mrq->data);
diff --git a/include/asm-mips/mach-au1x00/au1100_mmc.h b/include/asm-mips/mach-au1x00/au1100_mmc.h
index c79dec1..6433b19 100644
--- a/include/asm-mips/mach-au1x00/au1100_mmc.h
+++ b/include/asm-mips/mach-au1x00/au1100_mmc.h
@@ -43,6 +43,7 @@ struct au1xmmc_platform_data {
 	int(*card_inserted)(void *mmc_host);
 	int(*card_readonly)(void *mmc_host);
 	void(*set_power)(void *mmc_host, int state);
+	void(*activity)(int on);
 };
 
 #define SD0_BASE	0xB0600000
-- 
1.5.5.1


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

* Re: [PATCH 3/9] au1xmmc: remove pb1200 board-specific code from driver file
  2008-05-19  8:05 ` [PATCH 3/9] au1xmmc: remove pb1200 board-specific code from driver file Manuel Lauss
@ 2008-05-19  8:17   ` Manuel Lauss
  2008-05-19 10:07     ` Manuel Lauss
  0 siblings, 1 reply; 27+ messages in thread
From: Manuel Lauss @ 2008-05-19  8:17 UTC (permalink / raw)
  To: linux-mips, linux-kernel, drzeus, sshtylyov

Theres a tiny bug in the previous patch, please use this one here.

Thanks!

--- 
>From 20a9a4d454e6e381f632dfadf713b515f30045b1 Mon Sep 17 00:00:00 2001
From: Manuel Lauss <mlau@msc-ge.com>
Date: Wed, 7 May 2008 14:57:01 +0200
Subject: [PATCH] au1xmmc: remove pb1200 board-specific code from driver file

Remove the DB1200 board-specific functions (card present, read-only,
activity LED methods) and instead add platform data which is passed
to the driver.  This also allows for platforms to implement other
carddetect schemes (e.g. dedicated irq) without having to pollute the
driver code.  The poll timer (used for pb1200) is kept for compatibility.

With the board-specific stuff gone, the drivers probe code can be
cleaned up considerably: this patch also rewrites the probe and
remove functions and removes a few unused variables.

Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
---
 drivers/mmc/host/au1xmmc.c                |  508 +++++++++++++++++------------
 drivers/mmc/host/au1xmmc.h                |    9 +-
 include/asm-mips/mach-au1x00/au1100_mmc.h |   15 +-
 3 files changed, 304 insertions(+), 228 deletions(-)

diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index cc5f7bc..9036677 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -54,6 +54,7 @@
 #define DRIVER_NAME "au1xxx-mmc"
 
 /* Set this to enable special debugging macros */
+/* #define DEBUG */
 
 #ifdef DEBUG
 #define DBG(fmt, idx, args...) printk("au1xx(%d): DEBUG: " fmt, idx, ##args)
@@ -61,32 +62,6 @@
 #define DBG(fmt, idx, args...)
 #endif
 
-const struct {
-	u32 iobase;
-	u32 tx_devid, rx_devid;
-	u16 bcsrpwr;
-	u16 bcsrstatus;
-	u16 wpstatus;
-} au1xmmc_card_table[] = {
-	{ SD0_BASE, DSCR_CMD0_SDMS_TX0, DSCR_CMD0_SDMS_RX0,
-	  BCSR_BOARD_SD0PWR, BCSR_INT_SD0INSERT, BCSR_STATUS_SD0WP },
-#ifndef CONFIG_MIPS_DB1200
-	{ SD1_BASE, DSCR_CMD0_SDMS_TX1, DSCR_CMD0_SDMS_RX1,
-	  BCSR_BOARD_DS1PWR, BCSR_INT_SD1INSERT, BCSR_STATUS_SD1WP }
-#endif
-};
-
-#define AU1XMMC_CONTROLLER_COUNT (ARRAY_SIZE(au1xmmc_card_table))
-
-/* This array stores pointers for the hosts (used by the IRQ handler) */
-struct au1xmmc_host *au1xmmc_hosts[AU1XMMC_CONTROLLER_COUNT];
-static int dma = 1;
-
-#ifdef MODULE
-module_param(dma, bool, 0);
-MODULE_PARM_DESC(dma, "Use DMA engine for data transfers (0 = disabled)");
-#endif
-
 static inline void IRQ_ON(struct au1xmmc_host *host, u32 mask)
 {
 	u32 val = au_readl(HOST_CONFIG(host));
@@ -135,26 +110,33 @@ static inline void SEND_STOP(struct au1xmmc_host *host)
 
 static void au1xmmc_set_power(struct au1xmmc_host *host, int state)
 {
-
-	u32 val = au1xmmc_card_table[host->id].bcsrpwr;
-
-	bcsr->board &= ~val;
-	if (state) bcsr->board |= val;
-
-	au_sync_delay(1);
+	if (host->platdata && host->platdata->set_power)
+		host->platdata->set_power(host->mmc, state);
 }
 
-static inline int au1xmmc_card_inserted(struct au1xmmc_host *host)
+static int au1xmmc_card_inserted(struct au1xmmc_host *host)
 {
-	return (bcsr->sig_status & au1xmmc_card_table[host->id].bcsrstatus)
-		? 1 : 0;
+	int ret;
+
+	if (host->platdata && host->platdata->card_inserted)
+		ret = host->platdata->card_inserted(host->mmc);
+	else
+		ret = 1;	/* assume there is a card */
+
+	return ret;
 }
 
 static int au1xmmc_card_readonly(struct mmc_host *mmc)
 {
 	struct au1xmmc_host *host = mmc_priv(mmc);
-	return (bcsr->status & au1xmmc_card_table[host->id].wpstatus)
-		? 1 : 0;
+	int ret;
+
+	if (host->platdata && host->platdata->card_readonly)
+		ret = host->platdata->card_readonly(mmc);
+	else
+		ret = 1;	/* assume card is read-only */
+
+	return ret;
 }
 
 static void au1xmmc_finish_request(struct au1xmmc_host *host)
@@ -174,8 +156,6 @@ static void au1xmmc_finish_request(struct au1xmmc_host *host)
 
 	host->status = HOST_S_IDLE;
 
-	bcsr->disk_leds |= (1 << 8);
-
 	mmc_request_done(host->mmc, mrq);
 }
 
@@ -420,18 +400,18 @@ static void au1xmmc_receive_pio(struct au1xmmc_host *host)
 			break;
 
 		if (status & SD_STATUS_RC) {
-			DBG("RX CRC Error [%d + %d].\n", host->id,
+			DBG("RX CRC Error [%d + %d].\n", host->pdev->id,
 					host->pio.len, count);
 			break;
 		}
 
 		if (status & SD_STATUS_RO) {
-			DBG("RX Overrun [%d + %d]\n", host->id,
+			DBG("RX Overrun [%d + %d]\n", host->pdev->id,
 					host->pio.len, count);
 			break;
 		}
 		else if (status & SD_STATUS_RU) {
-			DBG("RX Underrun [%d + %d]\n", host->id,
+			DBG("RX Underrun [%d + %d]\n", host->pdev->id,
 					host->pio.len,	count);
 			break;
 		}
@@ -571,12 +551,8 @@ static void au1xmmc_set_clock(struct au1xmmc_host *host, int rate)
 static int
 au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data)
 {
-
 	int datalen = data->blocks * data->blksz;
 
-	if (dma != 0)
-		host->flags |= HOST_F_DMA;
-
 	if (data->flags & MMC_DATA_READ)
 		host->flags |= HOST_F_RECV;
 	else
@@ -663,8 +639,6 @@ static void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq)
 	host->mrq = mrq;
 	host->status = HOST_S_CMD;
 
-	bcsr->disk_leds &= ~(1 << 8);
-
 	if (mrq->data) {
 		FLUSH_FIFO(host);
 		flags = mrq->data->flags;
@@ -749,245 +723,339 @@ static void au1xmmc_dma_callback(int irq, void *dev_id)
 
 static irqreturn_t au1xmmc_irq(int irq, void *dev_id)
 {
-
+	struct au1xmmc_host *host = dev_id;
 	u32 status;
-	int i, ret = 0;
 
-	disable_irq(AU1100_SD_IRQ);
+	status = au_readl(HOST_STATUS(host));
 
-	for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
-		struct au1xmmc_host * host = au1xmmc_hosts[i];
-		u32 handled = 1;
+	if (!(status & SD_STATUS_I))
+		return IRQ_NONE;	/* not ours */
 
-		status = au_readl(HOST_STATUS(host));
-
-		if (host->mrq && (status & STATUS_TIMEOUT)) {
-			if (status & SD_STATUS_RAT)
-				host->mrq->cmd->error = -ETIMEDOUT;
+	if (host->mrq && (status & STATUS_TIMEOUT)) {
+		if (status & SD_STATUS_RAT)
+			host->mrq->cmd->error = -ETIMEDOUT;
+		else if (status & SD_STATUS_DT)
+			host->mrq->data->error = -ETIMEDOUT;
 
-			else if (status & SD_STATUS_DT)
-				host->mrq->data->error = -ETIMEDOUT;
+		/* In PIO mode, interrupts might still be enabled */
+		IRQ_OFF(host, SD_CONFIG_NE | SD_CONFIG_TH);
 
-			/* In PIO mode, interrupts might still be enabled */
-			IRQ_OFF(host, SD_CONFIG_NE | SD_CONFIG_TH);
-
-			//IRQ_OFF(host, SD_CONFIG_TH|SD_CONFIG_RA|SD_CONFIG_RF);
-			tasklet_schedule(&host->finish_task);
-		}
+		/* IRQ_OFF(host, SD_CONFIG_TH|SD_CONFIG_RA|SD_CONFIG_RF); */
+		tasklet_schedule(&host->finish_task);
+	}
 #if 0
-		else if (status & SD_STATUS_DD) {
-
-			/* Sometimes we get a DD before a NE in PIO mode */
-
-			if (!(host->flags & HOST_F_DMA) &&
-					(status & SD_STATUS_NE))
-				au1xmmc_receive_pio(host);
-			else {
-				au1xmmc_data_complete(host, status);
-				//tasklet_schedule(&host->data_task);
-			}
+	else if (status & SD_STATUS_DD) {
+		/* Sometimes we get a DD before a NE in PIO mode */
+		if (!(host->flags & HOST_F_DMA) && (status & SD_STATUS_NE))
+			au1xmmc_receive_pio(host);
+		else {
+			au1xmmc_data_complete(host, status);
+			/* tasklet_schedule(&host->data_task); */
 		}
+	}
 #endif
-		else if (status & (SD_STATUS_CR)) {
-			if (host->status == HOST_S_CMD)
-				au1xmmc_cmd_complete(host,status);
-		}
-		else if (!(host->flags & HOST_F_DMA)) {
-			if ((host->flags & HOST_F_XMIT) &&
-			    (status & STATUS_DATA_OUT))
-				au1xmmc_send_pio(host);
-			else if ((host->flags & HOST_F_RECV) &&
-			    (status & STATUS_DATA_IN))
-				au1xmmc_receive_pio(host);
-		}
-		else if (status & 0x203FBC70) {
-			DBG("Unhandled status %8.8x\n", host->id, status);
-			handled = 0;
-		}
+	else if (status & SD_STATUS_CR) {
+		if (host->status == HOST_S_CMD)
+			au1xmmc_cmd_complete(host, status);
+
+	} else if (!(host->flags & HOST_F_DMA)) {
+		if ((host->flags & HOST_F_XMIT) && (status & STATUS_DATA_OUT))
+			au1xmmc_send_pio(host);
+		else if ((host->flags & HOST_F_RECV) && (status & STATUS_DATA_IN))
+			au1xmmc_receive_pio(host);
+
+	} else if (status & 0x203F3C70) {
+			DBG("Unhandled status %8.8x\n", host->pdev->id,
+				status);
+	}
 
-		au_writel(status, HOST_STATUS(host));
-		au_sync();
+	au_writel(status, HOST_STATUS(host));
+	au_sync();
 
-		ret |= handled;
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_SOC_AU1200
+/* 8bit memory DMA device */
+static dbdev_tab_t au1xmmc_mem_dbdev = {
+	.dev_id		= DSCR_CMD0_ALWAYS,
+	.dev_flags	= DEV_FLAGS_ANYUSE,
+	.dev_tsize	= 0,
+	.dev_devwidth	= 8,
+	.dev_physaddr	= 0x00000000,
+	.dev_intlevel	= 0,
+	.dev_intpolarity = 0,
+};
+static int memid;
+
+static int au1xmmc_dbdma_init(struct au1xmmc_host *host)
+{
+	struct resource *res;
+	int txid, rxid;
+
+	res = platform_get_resource(host->pdev, IORESOURCE_DMA, 0);
+	if (!res)
+		return -ENODEV;
+	txid = res->start;
+
+	res = platform_get_resource(host->pdev, IORESOURCE_DMA, 1);
+	if (!res)
+		return -ENODEV;
+	rxid = res->start;
+
+	if (!memid)
+		return -ENODEV;
+
+	host->tx_chan = au1xxx_dbdma_chan_alloc(memid, txid,
+				au1xmmc_dma_callback, (void *)host);
+	if (!host->tx_chan) {
+		dev_err(&host->pdev->dev, "cannot allocate TX DMA\n");
+		return -ENODEV;
 	}
 
-	enable_irq(AU1100_SD_IRQ);
-	return ret;
+	host->rx_chan = au1xxx_dbdma_chan_alloc(rxid, memid,
+				au1xmmc_dma_callback, (void *)host);
+	if (!host->rx_chan) {
+		dev_err(&host->pdev->dev, "cannot allocate RX DMA\n");
+		au1xxx_dbdma_chan_free(host->tx_chan);
+		return -ENODEV;
+	}
+
+	au1xxx_dbdma_set_devwidth(host->tx_chan, 8);
+	au1xxx_dbdma_set_devwidth(host->rx_chan, 8);
+
+	au1xxx_dbdma_ring_alloc(host->tx_chan, AU1XMMC_DESCRIPTOR_COUNT);
+	au1xxx_dbdma_ring_alloc(host->rx_chan, AU1XMMC_DESCRIPTOR_COUNT);
+
+	/* DBDMA is good to go */
+	host->flags |= HOST_F_DMA;
+
+	return 0;
 }
 
-static void au1xmmc_poll_event(unsigned long arg)
+static void au1xmmc_dbdma_shutdown(struct au1xmmc_host *host)
 {
-	struct au1xmmc_host *host = (struct au1xmmc_host *) arg;
+	if (host->flags & HOST_F_DMA) {
+		host->flags &= ~HOST_F_DMA;
+		au1xxx_dbdma_chan_free(host->tx_chan);
+		au1xxx_dbdma_chan_free(host->rx_chan);
+	}
+}
+#endif
 
+static const struct mmc_host_ops au1xmmc_ops = {
+	.request	= au1xmmc_request,
+	.set_ios	= au1xmmc_set_ios,
+	.get_ro		= au1xmmc_card_readonly,
+};
+
+static void au1xmmc_poll_event(unsigned long arg)
+{
+	struct au1xmmc_host *host = (struct au1xmmc_host *)arg;
 	int card = au1xmmc_card_inserted(host);
-        int controller = (host->flags & HOST_F_ACTIVE) ? 1 : 0;
+	int controller = (host->flags & HOST_F_ACTIVE) ? 1 : 0;
 
 	if (card != controller) {
 		host->flags &= ~HOST_F_ACTIVE;
-		if (card) host->flags |= HOST_F_ACTIVE;
+		if (card)
+			host->flags |= HOST_F_ACTIVE;
 		mmc_detect_change(host->mmc, 0);
 	}
 
+#ifdef DEBUG
 	if (host->mrq != NULL) {
 		u32 status = au_readl(HOST_STATUS(host));
-		DBG("PENDING - %8.8x\n", host->id, status);
+		DBG("PENDING - %8.8x\n", host->pdev->id, status);
 	}
-
+#endif
 	mod_timer(&host->timer, jiffies + AU1XMMC_DETECT_TIMEOUT);
 }
 
-static dbdev_tab_t au1xmmc_mem_dbdev =
-{
-	DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 8, 0x00000000, 0, 0
-};
-
-static void au1xmmc_init_dma(struct au1xmmc_host *host)
+static void au1xmmc_init_cd_poll_timer(struct au1xmmc_host *host)
 {
-
-	u32 rxchan, txchan;
-
-	int txid = au1xmmc_card_table[host->id].tx_devid;
-	int rxid = au1xmmc_card_table[host->id].rx_devid;
-
-	/* DSCR_CMD0_ALWAYS has a stride of 32 bits, we need a stride
-	   of 8 bits.  And since devices are shared, we need to create
-	   our own to avoid freaking out other devices
-	*/
-
-	int memid = au1xxx_ddma_add_device(&au1xmmc_mem_dbdev);
-
-	txchan = au1xxx_dbdma_chan_alloc(memid, txid,
-					 au1xmmc_dma_callback, (void *) host);
-
-	rxchan = au1xxx_dbdma_chan_alloc(rxid, memid,
-					 au1xmmc_dma_callback, (void *) host);
-
-	au1xxx_dbdma_set_devwidth(txchan, 8);
-	au1xxx_dbdma_set_devwidth(rxchan, 8);
-
-	au1xxx_dbdma_ring_alloc(txchan, AU1XMMC_DESCRIPTOR_COUNT);
-	au1xxx_dbdma_ring_alloc(rxchan, AU1XMMC_DESCRIPTOR_COUNT);
-
-	host->tx_chan = txchan;
-	host->rx_chan = rxchan;
+	init_timer(&host->timer);
+	host->timer.function = au1xmmc_poll_event;
+	host->timer.data = (unsigned long)host;
+	host->timer.expires = jiffies + AU1XMMC_DETECT_TIMEOUT;
 }
 
-static const struct mmc_host_ops au1xmmc_ops = {
-	.request	= au1xmmc_request,
-	.set_ios	= au1xmmc_set_ios,
-	.get_ro		= au1xmmc_card_readonly,
-};
-
 static int __devinit au1xmmc_probe(struct platform_device *pdev)
 {
+	struct mmc_host *mmc;
+	struct au1xmmc_host *host;
+	struct resource *r;
+	int ret;
+
+	mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), &pdev->dev);
+	if (!mmc) {
+		dev_err(&pdev->dev, "no memory for mmc host\n");
+		ret = -ENOMEM;
+		goto out0;
+	}
 
-	int i, ret = 0;
-
-	/* THe interrupt is shared among all controllers */
-	ret = request_irq(AU1100_SD_IRQ, au1xmmc_irq, IRQF_DISABLED, "MMC", 0);
+	host = mmc_priv(mmc);
+	host->mmc = mmc;
+	host->platdata = pdev->dev.platform_data;
+	host->pdev = pdev;
 
-	if (ret) {
-		printk(DRIVER_NAME "ERROR: Couldn't get int %d: %d\n",
-				AU1100_SD_IRQ, ret);
-		return -ENXIO;
+	ret = -ENODEV;
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		dev_err(&pdev->dev, "no mmio defined\n");
+		goto out1;
 	}
 
-	disable_irq(AU1100_SD_IRQ);
+	host->ioarea = request_mem_region(r->start, r->end - r->start + 1,
+					   pdev->name);
+	if (!host->ioarea) {
+		dev_err(&pdev->dev, "mmio already used\n");
+		goto out1;
+	}
 
-	for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
-		struct mmc_host *mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), &pdev->dev);
-		struct au1xmmc_host *host = 0;
+	host->iobase = (unsigned long)ioremap(r->start, r->end - r->start + 1);
+	if (!host->iobase) {
+		dev_err(&pdev->dev, "cannot remap mmio\n");
+		goto out2;
+	}
 
-		if (!mmc) {
-			printk(DRIVER_NAME "ERROR: no mem for host %d\n", i);
-			au1xmmc_hosts[i] = 0;
-			continue;
-		}
+	r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!r) {
+		dev_err(&pdev->dev, "no IRQ defined\n");
+		goto out3;
+	}
 
-		mmc->ops = &au1xmmc_ops;
+	host->irq = r->start;
+	/* IRQ is shared among both SD controllers */
+	ret = request_irq(host->irq, au1xmmc_irq, IRQF_SHARED,
+			  DRIVER_NAME, host);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot grab IRQ\n");
+		goto out3;
+	}
 
-		mmc->f_min =   450000;
-		mmc->f_max = 24000000;
+	mmc->ops = &au1xmmc_ops;
 
-		mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE;
-		mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT;
+	mmc->f_min =   450000;
+	mmc->f_max = 24000000;
 
-		mmc->max_blk_size = 2048;
-		mmc->max_blk_count = 512;
+	mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE;
+	mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT;
 
-		mmc->ocr_avail = AU1XMMC_OCR;
+	mmc->max_blk_size = 2048;
+	mmc->max_blk_count = 512;
 
-		host = mmc_priv(mmc);
-		host->mmc = mmc;
+	mmc->ocr_avail = AU1XMMC_OCR;
+	mmc->caps = 0;
 
-		host->id = i;
-		host->iobase = au1xmmc_card_table[host->id].iobase;
-		host->clock = 0;
-		host->power_mode = MMC_POWER_OFF;
+	host->status = HOST_S_IDLE;
 
-		host->flags = au1xmmc_card_inserted(host) ? HOST_F_ACTIVE : 0;
-		host->status = HOST_S_IDLE;
+	/* board-specific carddetect setup, if any */
+	if (host->platdata && host->platdata->cd_setup) {
+		ret = host->platdata->cd_setup(mmc, 1);
+		if (ret) {
+			dev_err(&pdev->dev, "board CD setup failed\n");
+			goto out4;
+		}
+	} else {
+		/* poll the board-specific is-card-in-socket-? method */
+		au1xmmc_init_cd_poll_timer(host);
+	}
 
-		init_timer(&host->timer);
+	tasklet_init(&host->data_task, au1xmmc_tasklet_data,
+			(unsigned long)host);
 
-		host->timer.function = au1xmmc_poll_event;
-		host->timer.data = (unsigned long) host;
-		host->timer.expires = jiffies + AU1XMMC_DETECT_TIMEOUT;
+	tasklet_init(&host->finish_task, au1xmmc_tasklet_finish,
+			(unsigned long)host);
 
-		tasklet_init(&host->data_task, au1xmmc_tasklet_data,
-				(unsigned long) host);
+#ifdef CONFIG_SOC_AU1200
+	ret = au1xmmc_dbdma_init(host);
+	if (ret)
+		printk(KERN_INFO DRIVER_NAME ": DBDMA init failed; using PIO\n");
+#endif
 
-		tasklet_init(&host->finish_task, au1xmmc_tasklet_finish,
-				(unsigned long) host);
+	au1xmmc_reset_controller(host);
 
-		spin_lock_init(&host->lock);
+	ret = mmc_add_host(mmc);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot add mmc host\n");
+		goto out5;
+	}
 
-		if (dma != 0)
-			au1xmmc_init_dma(host);
+	platform_set_drvdata(pdev, mmc);
 
-		au1xmmc_reset_controller(host);
+	/* start the carddetect poll timer */
+	if (!(host->platdata && host->platdata->cd_setup))
+		add_timer(&host->timer);
 
-		mmc_add_host(mmc);
-		au1xmmc_hosts[i] = host;
+	printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X"
+		" (mode=%s)\n", pdev->id, host->iobase,
+		host->flags & HOST_F_DMA ? "dma" : "pio");
 
-		add_timer(&host->timer);
+	return 0;	/* all ok */
 
-		printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X (mode=%s)\n",
-		       host->id, host->iobase, dma ? "dma" : "pio");
-	}
+out5:
+	au_writel(0, HOST_ENABLE(host));
+	au_writel(0, HOST_CONFIG(host));
+	au_writel(0, HOST_CONFIG2(host));
+	au_sync();
 
-	enable_irq(AU1100_SD_IRQ);
+#ifdef CONFIG_SOC_AU1200
+	au1xmmc_dbdma_shutdown(host);
+#endif
 
-	return 0;
+	tasklet_kill(&host->data_task);
+	tasklet_kill(&host->finish_task);
+
+	if (host->platdata && host->platdata->cd_setup)
+		host->platdata->cd_setup(mmc, 0);
+out4:
+	free_irq(host->irq, host);
+out3:
+	iounmap((void *)host->iobase);
+out2:
+	release_resource(host->ioarea);
+	kfree(host->ioarea);
+out1:
+	mmc_free_host(mmc);
+out0:
+	return ret;
 }
 
 static int __devexit au1xmmc_remove(struct platform_device *pdev)
 {
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
+	struct au1xmmc_host *host;
+
+	if (mmc) {
+		host  = mmc_priv(mmc);
 
-	int i;
+		mmc_remove_host(mmc);
 
-	disable_irq(AU1100_SD_IRQ);
+		if (host->platdata && host->platdata->cd_setup)
+			host->platdata->cd_setup(mmc, 0);
+		else
+			del_timer_sync(&host->timer);
 
-	for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
-		struct au1xmmc_host *host = au1xmmc_hosts[i];
-		if (!host) continue;
+		au_writel(0, HOST_ENABLE(host));
+		au_writel(0, HOST_CONFIG(host));
+		au_writel(0, HOST_CONFIG2(host));
+		au_sync();
 
 		tasklet_kill(&host->data_task);
 		tasklet_kill(&host->finish_task);
 
-		del_timer_sync(&host->timer);
+#ifdef CONFIG_SOC_AU1200
+		au1xmmc_dbdma_shutdown(host);
+#endif
 		au1xmmc_set_power(host, 0);
 
-		mmc_remove_host(host->mmc);
-
-		au1xxx_dbdma_chan_free(host->tx_chan);
-		au1xxx_dbdma_chan_free(host->rx_chan);
+		free_irq(host->irq, host);
+		iounmap((void *)host->iobase);
+		release_resource(host->ioarea);
+		kfree(host->ioarea);
 
-		au_writel(0x0, HOST_ENABLE(host));
-		au_sync();
+		mmc_free_host(mmc);
 	}
-
-	free_irq(AU1100_SD_IRQ, 0);
 	return 0;
 }
 
@@ -1004,21 +1072,31 @@ static struct platform_driver au1xmmc_driver = {
 
 static int __init au1xmmc_init(void)
 {
+#ifdef CONFIG_SOC_AU1200
+	/* DSCR_CMD0_ALWAYS has a stride of 32 bits, we need a stride
+	 * of 8 bits.  And since devices are shared, we need to create
+	 * our own to avoid freaking out other devices.
+	 */
+	memid = au1xxx_ddma_add_device(&au1xmmc_mem_dbdev);
+	if (!memid)
+		printk(KERN_ERR "au1xmmc: cannot add memory dbdma dev\n");
+#endif
 	return platform_driver_register(&au1xmmc_driver);
 }
 
 static void __exit au1xmmc_exit(void)
 {
+#ifdef CONFIG_SOC_AU1200
+	if (memid)
+		au1xxx_ddma_del_device(memid);
+#endif
 	platform_driver_unregister(&au1xmmc_driver);
 }
 
 module_init(au1xmmc_init);
 module_exit(au1xmmc_exit);
 
-#ifdef MODULE
 MODULE_AUTHOR("Advanced Micro Devices, Inc");
 MODULE_DESCRIPTION("MMC/SD driver for the Alchemy Au1XXX");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:au1xxx-mmc");
-#endif
-
diff --git a/drivers/mmc/host/au1xmmc.h b/drivers/mmc/host/au1xmmc.h
index 341cbdf..3b40065 100644
--- a/drivers/mmc/host/au1xmmc.h
+++ b/drivers/mmc/host/au1xmmc.h
@@ -49,8 +49,6 @@ struct au1xmmc_host {
   struct mmc_host *mmc;
   struct mmc_request *mrq;
 
-  u32 id;
-
   u32 flags;
   u32 iobase;
   u32 clock;
@@ -73,11 +71,14 @@ struct au1xmmc_host {
   u32 tx_chan;
   u32 rx_chan;
 
+  int irq;
+
   struct timer_list timer;
   struct tasklet_struct finish_task;
   struct tasklet_struct data_task;
-
-  spinlock_t lock;
+  struct au1xmmc_platform_data *platdata;
+  struct platform_device *pdev;
+  struct resource *ioarea;
 };
 
 /* Status flags used by the host structure */
diff --git a/include/asm-mips/mach-au1x00/au1100_mmc.h b/include/asm-mips/mach-au1x00/au1100_mmc.h
index 9e0028f..c79dec1 100644
--- a/include/asm-mips/mach-au1x00/au1100_mmc.h
+++ b/include/asm-mips/mach-au1x00/au1100_mmc.h
@@ -38,15 +38,12 @@
 #ifndef __ASM_AU1100_MMC_H
 #define __ASM_AU1100_MMC_H
 
-
-#define NUM_AU1100_MMC_CONTROLLERS	2
-
-#if defined(CONFIG_SOC_AU1100)
-#define AU1100_SD_IRQ	AU1100_SD_INT
-#elif defined(CONFIG_SOC_AU1200)
-#define AU1100_SD_IRQ	AU1200_SD_INT
-#endif
-
+struct au1xmmc_platform_data {
+	int(*cd_setup)(void *mmc_host, int on);
+	int(*card_inserted)(void *mmc_host);
+	int(*card_readonly)(void *mmc_host);
+	void(*set_power)(void *mmc_host, int state);
+};
 
 #define SD0_BASE	0xB0600000
 #define SD1_BASE	0xB0680000
-- 
1.5.5.1


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

* Re: [PATCH 1/9] Alchemy: export get_au1x00_speed for modules
  2008-05-19  8:04 ` [PATCH 1/9] Alchemy: export get_au1x00_speed for modules Manuel Lauss
@ 2008-05-19  9:35   ` Sergei Shtylyov
  2008-05-19  9:49     ` Manuel Lauss
  0 siblings, 1 reply; 27+ messages in thread
From: Sergei Shtylyov @ 2008-05-19  9:35 UTC (permalink / raw)
  To: Manuel Lauss; +Cc: linux-mips, linux-kernel, drzeus

Hello.

Manuel Lauss wrote:
> From 8492076e98c7fd47c9dee53984dbd9568ace357d Mon Sep 17 00:00:00 2001
> From: Manuel Lauss <mlau@msc-ge.com>
> Date: Wed, 7 May 2008 13:42:55 +0200
> Subject: [PATCH] Alchemy: export get_au1x00_speed for modules
>
> au1xmmc.c driver depends on it, so export it for modules.
>
> Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
>   

   I thought that has been merged.

WBR, Sergei



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

* Re: [PATCH 1/9] Alchemy: export get_au1x00_speed for modules
  2008-05-19  9:35   ` Sergei Shtylyov
@ 2008-05-19  9:49     ` Manuel Lauss
  2008-06-05 21:03       ` Pierre Ossman
  0 siblings, 1 reply; 27+ messages in thread
From: Manuel Lauss @ 2008-05-19  9:49 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: linux-mips, linux-kernel, drzeus

Hi Sergei,

>> From 8492076e98c7fd47c9dee53984dbd9568ace357d Mon Sep 17 00:00:00 2001
>> From: Manuel Lauss <mlau@msc-ge.com>
>> Date: Wed, 7 May 2008 13:42:55 +0200
>> Subject: [PATCH] Alchemy: export get_au1x00_speed for modules
>>
>> au1xmmc.c driver depends on it, so export it for modules.
>>
>> Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
>>   
>
>   I thought that has been merged.

Yes, Ralf merged it into linux-mips repo, but it is not yet in
mainline and the rest of the patches are against linus' git.

	Manuel Lauss

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

* Re: [PATCH 3/9] au1xmmc: remove pb1200 board-specific code from driver file
  2008-05-19  8:17   ` Manuel Lauss
@ 2008-05-19 10:07     ` Manuel Lauss
  0 siblings, 0 replies; 27+ messages in thread
From: Manuel Lauss @ 2008-05-19 10:07 UTC (permalink / raw)
  To: linux-mips, linux-kernel, drzeus, sshtylyov

On Mon, May 19, 2008 at 10:17:00AM +0200, Manuel Lauss wrote:
> Theres a tiny bug in the previous patch, please use this one here.

I found yet another bug which resulted in DMA being turned off
after the very first request finished.  Fixed version below.

Thanks,
	Manuel Lauss

--- 
>From 40d40bf91d449e14cb998de0e2f2c4c947b46206 Mon Sep 17 00:00:00 2001
From: Manuel Lauss <mlau@msc-ge.com>
Date: Wed, 7 May 2008 14:57:01 +0200
Subject: [PATCH] au1xmmc: remove pb1200 board-specific code from driver file

Remove the DB1200 board-specific functions (card present, read-only,
activity LED methods) and instead add platform data which is passed
to the driver.  This also allows for platforms to implement other
carddetect schemes (e.g. dedicated irq) without having to pollute the
driver code.  The poll timer (used for pb1200) is kept for compatibility.

With the board-specific stuff gone, the drivers probe code can be
cleaned up considerably: this patch also rewrites the probe and
remove functions and removes a few unused variables.

Update #1: fixed "CONFIG_SOC_Au1200" typo.
Update #2: fixed bug which turned off DMA after very first request finished.

Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
---
 drivers/mmc/host/au1xmmc.c                |  510 +++++++++++++++++------------
 drivers/mmc/host/au1xmmc.h                |    9 +-
 include/asm-mips/mach-au1x00/au1100_mmc.h |   15 +-
 3 files changed, 305 insertions(+), 229 deletions(-)

diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index cc5f7bc..144b1d7 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -54,6 +54,7 @@
 #define DRIVER_NAME "au1xxx-mmc"
 
 /* Set this to enable special debugging macros */
+/* #define DEBUG */
 
 #ifdef DEBUG
 #define DBG(fmt, idx, args...) printk("au1xx(%d): DEBUG: " fmt, idx, ##args)
@@ -61,32 +62,6 @@
 #define DBG(fmt, idx, args...)
 #endif
 
-const struct {
-	u32 iobase;
-	u32 tx_devid, rx_devid;
-	u16 bcsrpwr;
-	u16 bcsrstatus;
-	u16 wpstatus;
-} au1xmmc_card_table[] = {
-	{ SD0_BASE, DSCR_CMD0_SDMS_TX0, DSCR_CMD0_SDMS_RX0,
-	  BCSR_BOARD_SD0PWR, BCSR_INT_SD0INSERT, BCSR_STATUS_SD0WP },
-#ifndef CONFIG_MIPS_DB1200
-	{ SD1_BASE, DSCR_CMD0_SDMS_TX1, DSCR_CMD0_SDMS_RX1,
-	  BCSR_BOARD_DS1PWR, BCSR_INT_SD1INSERT, BCSR_STATUS_SD1WP }
-#endif
-};
-
-#define AU1XMMC_CONTROLLER_COUNT (ARRAY_SIZE(au1xmmc_card_table))
-
-/* This array stores pointers for the hosts (used by the IRQ handler) */
-struct au1xmmc_host *au1xmmc_hosts[AU1XMMC_CONTROLLER_COUNT];
-static int dma = 1;
-
-#ifdef MODULE
-module_param(dma, bool, 0);
-MODULE_PARM_DESC(dma, "Use DMA engine for data transfers (0 = disabled)");
-#endif
-
 static inline void IRQ_ON(struct au1xmmc_host *host, u32 mask)
 {
 	u32 val = au_readl(HOST_CONFIG(host));
@@ -135,26 +110,33 @@ static inline void SEND_STOP(struct au1xmmc_host *host)
 
 static void au1xmmc_set_power(struct au1xmmc_host *host, int state)
 {
-
-	u32 val = au1xmmc_card_table[host->id].bcsrpwr;
-
-	bcsr->board &= ~val;
-	if (state) bcsr->board |= val;
-
-	au_sync_delay(1);
+	if (host->platdata && host->platdata->set_power)
+		host->platdata->set_power(host->mmc, state);
 }
 
-static inline int au1xmmc_card_inserted(struct au1xmmc_host *host)
+static int au1xmmc_card_inserted(struct au1xmmc_host *host)
 {
-	return (bcsr->sig_status & au1xmmc_card_table[host->id].bcsrstatus)
-		? 1 : 0;
+	int ret;
+
+	if (host->platdata && host->platdata->card_inserted)
+		ret = host->platdata->card_inserted(host->mmc);
+	else
+		ret = 1;	/* assume there is a card */
+
+	return ret;
 }
 
 static int au1xmmc_card_readonly(struct mmc_host *mmc)
 {
 	struct au1xmmc_host *host = mmc_priv(mmc);
-	return (bcsr->status & au1xmmc_card_table[host->id].wpstatus)
-		? 1 : 0;
+	int ret;
+
+	if (host->platdata && host->platdata->card_readonly)
+		ret = host->platdata->card_readonly(mmc);
+	else
+		ret = 1;	/* assume card is read-only */
+
+	return ret;
 }
 
 static void au1xmmc_finish_request(struct au1xmmc_host *host)
@@ -163,7 +145,7 @@ static void au1xmmc_finish_request(struct au1xmmc_host *host)
 	struct mmc_request *mrq = host->mrq;
 
 	host->mrq = NULL;
-	host->flags &= HOST_F_ACTIVE;
+	host->flags &= HOST_F_ACTIVE | HOST_F_DMA;
 
 	host->dma.len = 0;
 	host->dma.dir = 0;
@@ -174,8 +156,6 @@ static void au1xmmc_finish_request(struct au1xmmc_host *host)
 
 	host->status = HOST_S_IDLE;
 
-	bcsr->disk_leds |= (1 << 8);
-
 	mmc_request_done(host->mmc, mrq);
 }
 
@@ -420,18 +400,18 @@ static void au1xmmc_receive_pio(struct au1xmmc_host *host)
 			break;
 
 		if (status & SD_STATUS_RC) {
-			DBG("RX CRC Error [%d + %d].\n", host->id,
+			DBG("RX CRC Error [%d + %d].\n", host->pdev->id,
 					host->pio.len, count);
 			break;
 		}
 
 		if (status & SD_STATUS_RO) {
-			DBG("RX Overrun [%d + %d]\n", host->id,
+			DBG("RX Overrun [%d + %d]\n", host->pdev->id,
 					host->pio.len, count);
 			break;
 		}
 		else if (status & SD_STATUS_RU) {
-			DBG("RX Underrun [%d + %d]\n", host->id,
+			DBG("RX Underrun [%d + %d]\n", host->pdev->id,
 					host->pio.len,	count);
 			break;
 		}
@@ -571,12 +551,8 @@ static void au1xmmc_set_clock(struct au1xmmc_host *host, int rate)
 static int
 au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data)
 {
-
 	int datalen = data->blocks * data->blksz;
 
-	if (dma != 0)
-		host->flags |= HOST_F_DMA;
-
 	if (data->flags & MMC_DATA_READ)
 		host->flags |= HOST_F_RECV;
 	else
@@ -663,8 +639,6 @@ static void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq)
 	host->mrq = mrq;
 	host->status = HOST_S_CMD;
 
-	bcsr->disk_leds &= ~(1 << 8);
-
 	if (mrq->data) {
 		FLUSH_FIFO(host);
 		flags = mrq->data->flags;
@@ -749,245 +723,339 @@ static void au1xmmc_dma_callback(int irq, void *dev_id)
 
 static irqreturn_t au1xmmc_irq(int irq, void *dev_id)
 {
-
+	struct au1xmmc_host *host = dev_id;
 	u32 status;
-	int i, ret = 0;
 
-	disable_irq(AU1100_SD_IRQ);
+	status = au_readl(HOST_STATUS(host));
 
-	for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
-		struct au1xmmc_host * host = au1xmmc_hosts[i];
-		u32 handled = 1;
+	if (!(status & SD_STATUS_I))
+		return IRQ_NONE;	/* not ours */
 
-		status = au_readl(HOST_STATUS(host));
-
-		if (host->mrq && (status & STATUS_TIMEOUT)) {
-			if (status & SD_STATUS_RAT)
-				host->mrq->cmd->error = -ETIMEDOUT;
+	if (host->mrq && (status & STATUS_TIMEOUT)) {
+		if (status & SD_STATUS_RAT)
+			host->mrq->cmd->error = -ETIMEDOUT;
+		else if (status & SD_STATUS_DT)
+			host->mrq->data->error = -ETIMEDOUT;
 
-			else if (status & SD_STATUS_DT)
-				host->mrq->data->error = -ETIMEDOUT;
+		/* In PIO mode, interrupts might still be enabled */
+		IRQ_OFF(host, SD_CONFIG_NE | SD_CONFIG_TH);
 
-			/* In PIO mode, interrupts might still be enabled */
-			IRQ_OFF(host, SD_CONFIG_NE | SD_CONFIG_TH);
-
-			//IRQ_OFF(host, SD_CONFIG_TH|SD_CONFIG_RA|SD_CONFIG_RF);
-			tasklet_schedule(&host->finish_task);
-		}
+		/* IRQ_OFF(host, SD_CONFIG_TH|SD_CONFIG_RA|SD_CONFIG_RF); */
+		tasklet_schedule(&host->finish_task);
+	}
 #if 0
-		else if (status & SD_STATUS_DD) {
-
-			/* Sometimes we get a DD before a NE in PIO mode */
-
-			if (!(host->flags & HOST_F_DMA) &&
-					(status & SD_STATUS_NE))
-				au1xmmc_receive_pio(host);
-			else {
-				au1xmmc_data_complete(host, status);
-				//tasklet_schedule(&host->data_task);
-			}
+	else if (status & SD_STATUS_DD) {
+		/* Sometimes we get a DD before a NE in PIO mode */
+		if (!(host->flags & HOST_F_DMA) && (status & SD_STATUS_NE))
+			au1xmmc_receive_pio(host);
+		else {
+			au1xmmc_data_complete(host, status);
+			/* tasklet_schedule(&host->data_task); */
 		}
+	}
 #endif
-		else if (status & (SD_STATUS_CR)) {
-			if (host->status == HOST_S_CMD)
-				au1xmmc_cmd_complete(host,status);
-		}
-		else if (!(host->flags & HOST_F_DMA)) {
-			if ((host->flags & HOST_F_XMIT) &&
-			    (status & STATUS_DATA_OUT))
-				au1xmmc_send_pio(host);
-			else if ((host->flags & HOST_F_RECV) &&
-			    (status & STATUS_DATA_IN))
-				au1xmmc_receive_pio(host);
-		}
-		else if (status & 0x203FBC70) {
-			DBG("Unhandled status %8.8x\n", host->id, status);
-			handled = 0;
-		}
+	else if (status & SD_STATUS_CR) {
+		if (host->status == HOST_S_CMD)
+			au1xmmc_cmd_complete(host, status);
+
+	} else if (!(host->flags & HOST_F_DMA)) {
+		if ((host->flags & HOST_F_XMIT) && (status & STATUS_DATA_OUT))
+			au1xmmc_send_pio(host);
+		else if ((host->flags & HOST_F_RECV) && (status & STATUS_DATA_IN))
+			au1xmmc_receive_pio(host);
+
+	} else if (status & 0x203F3C70) {
+			DBG("Unhandled status %8.8x\n", host->pdev->id,
+				status);
+	}
 
-		au_writel(status, HOST_STATUS(host));
-		au_sync();
+	au_writel(status, HOST_STATUS(host));
+	au_sync();
 
-		ret |= handled;
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_SOC_AU1200
+/* 8bit memory DMA device */
+static dbdev_tab_t au1xmmc_mem_dbdev = {
+	.dev_id		= DSCR_CMD0_ALWAYS,
+	.dev_flags	= DEV_FLAGS_ANYUSE,
+	.dev_tsize	= 0,
+	.dev_devwidth	= 8,
+	.dev_physaddr	= 0x00000000,
+	.dev_intlevel	= 0,
+	.dev_intpolarity = 0,
+};
+static int memid;
+
+static int au1xmmc_dbdma_init(struct au1xmmc_host *host)
+{
+	struct resource *res;
+	int txid, rxid;
+
+	res = platform_get_resource(host->pdev, IORESOURCE_DMA, 0);
+	if (!res)
+		return -ENODEV;
+	txid = res->start;
+
+	res = platform_get_resource(host->pdev, IORESOURCE_DMA, 1);
+	if (!res)
+		return -ENODEV;
+	rxid = res->start;
+
+	if (!memid)
+		return -ENODEV;
+
+	host->tx_chan = au1xxx_dbdma_chan_alloc(memid, txid,
+				au1xmmc_dma_callback, (void *)host);
+	if (!host->tx_chan) {
+		dev_err(&host->pdev->dev, "cannot allocate TX DMA\n");
+		return -ENODEV;
 	}
 
-	enable_irq(AU1100_SD_IRQ);
-	return ret;
+	host->rx_chan = au1xxx_dbdma_chan_alloc(rxid, memid,
+				au1xmmc_dma_callback, (void *)host);
+	if (!host->rx_chan) {
+		dev_err(&host->pdev->dev, "cannot allocate RX DMA\n");
+		au1xxx_dbdma_chan_free(host->tx_chan);
+		return -ENODEV;
+	}
+
+	au1xxx_dbdma_set_devwidth(host->tx_chan, 8);
+	au1xxx_dbdma_set_devwidth(host->rx_chan, 8);
+
+	au1xxx_dbdma_ring_alloc(host->tx_chan, AU1XMMC_DESCRIPTOR_COUNT);
+	au1xxx_dbdma_ring_alloc(host->rx_chan, AU1XMMC_DESCRIPTOR_COUNT);
+
+	/* DBDMA is good to go */
+	host->flags |= HOST_F_DMA;
+
+	return 0;
 }
 
-static void au1xmmc_poll_event(unsigned long arg)
+static void au1xmmc_dbdma_shutdown(struct au1xmmc_host *host)
 {
-	struct au1xmmc_host *host = (struct au1xmmc_host *) arg;
+	if (host->flags & HOST_F_DMA) {
+		host->flags &= ~HOST_F_DMA;
+		au1xxx_dbdma_chan_free(host->tx_chan);
+		au1xxx_dbdma_chan_free(host->rx_chan);
+	}
+}
+#endif
 
+static const struct mmc_host_ops au1xmmc_ops = {
+	.request	= au1xmmc_request,
+	.set_ios	= au1xmmc_set_ios,
+	.get_ro		= au1xmmc_card_readonly,
+};
+
+static void au1xmmc_poll_event(unsigned long arg)
+{
+	struct au1xmmc_host *host = (struct au1xmmc_host *)arg;
 	int card = au1xmmc_card_inserted(host);
-        int controller = (host->flags & HOST_F_ACTIVE) ? 1 : 0;
+	int controller = (host->flags & HOST_F_ACTIVE) ? 1 : 0;
 
 	if (card != controller) {
 		host->flags &= ~HOST_F_ACTIVE;
-		if (card) host->flags |= HOST_F_ACTIVE;
+		if (card)
+			host->flags |= HOST_F_ACTIVE;
 		mmc_detect_change(host->mmc, 0);
 	}
 
+#ifdef DEBUG
 	if (host->mrq != NULL) {
 		u32 status = au_readl(HOST_STATUS(host));
-		DBG("PENDING - %8.8x\n", host->id, status);
+		DBG("PENDING - %8.8x\n", host->pdev->id, status);
 	}
-
+#endif
 	mod_timer(&host->timer, jiffies + AU1XMMC_DETECT_TIMEOUT);
 }
 
-static dbdev_tab_t au1xmmc_mem_dbdev =
-{
-	DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 8, 0x00000000, 0, 0
-};
-
-static void au1xmmc_init_dma(struct au1xmmc_host *host)
+static void au1xmmc_init_cd_poll_timer(struct au1xmmc_host *host)
 {
-
-	u32 rxchan, txchan;
-
-	int txid = au1xmmc_card_table[host->id].tx_devid;
-	int rxid = au1xmmc_card_table[host->id].rx_devid;
-
-	/* DSCR_CMD0_ALWAYS has a stride of 32 bits, we need a stride
-	   of 8 bits.  And since devices are shared, we need to create
-	   our own to avoid freaking out other devices
-	*/
-
-	int memid = au1xxx_ddma_add_device(&au1xmmc_mem_dbdev);
-
-	txchan = au1xxx_dbdma_chan_alloc(memid, txid,
-					 au1xmmc_dma_callback, (void *) host);
-
-	rxchan = au1xxx_dbdma_chan_alloc(rxid, memid,
-					 au1xmmc_dma_callback, (void *) host);
-
-	au1xxx_dbdma_set_devwidth(txchan, 8);
-	au1xxx_dbdma_set_devwidth(rxchan, 8);
-
-	au1xxx_dbdma_ring_alloc(txchan, AU1XMMC_DESCRIPTOR_COUNT);
-	au1xxx_dbdma_ring_alloc(rxchan, AU1XMMC_DESCRIPTOR_COUNT);
-
-	host->tx_chan = txchan;
-	host->rx_chan = rxchan;
+	init_timer(&host->timer);
+	host->timer.function = au1xmmc_poll_event;
+	host->timer.data = (unsigned long)host;
+	host->timer.expires = jiffies + AU1XMMC_DETECT_TIMEOUT;
 }
 
-static const struct mmc_host_ops au1xmmc_ops = {
-	.request	= au1xmmc_request,
-	.set_ios	= au1xmmc_set_ios,
-	.get_ro		= au1xmmc_card_readonly,
-};
-
 static int __devinit au1xmmc_probe(struct platform_device *pdev)
 {
+	struct mmc_host *mmc;
+	struct au1xmmc_host *host;
+	struct resource *r;
+	int ret;
+
+	mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), &pdev->dev);
+	if (!mmc) {
+		dev_err(&pdev->dev, "no memory for mmc host\n");
+		ret = -ENOMEM;
+		goto out0;
+	}
 
-	int i, ret = 0;
-
-	/* THe interrupt is shared among all controllers */
-	ret = request_irq(AU1100_SD_IRQ, au1xmmc_irq, IRQF_DISABLED, "MMC", 0);
+	host = mmc_priv(mmc);
+	host->mmc = mmc;
+	host->platdata = pdev->dev.platform_data;
+	host->pdev = pdev;
 
-	if (ret) {
-		printk(DRIVER_NAME "ERROR: Couldn't get int %d: %d\n",
-				AU1100_SD_IRQ, ret);
-		return -ENXIO;
+	ret = -ENODEV;
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		dev_err(&pdev->dev, "no mmio defined\n");
+		goto out1;
 	}
 
-	disable_irq(AU1100_SD_IRQ);
+	host->ioarea = request_mem_region(r->start, r->end - r->start + 1,
+					   pdev->name);
+	if (!host->ioarea) {
+		dev_err(&pdev->dev, "mmio already used\n");
+		goto out1;
+	}
 
-	for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
-		struct mmc_host *mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), &pdev->dev);
-		struct au1xmmc_host *host = 0;
+	host->iobase = (unsigned long)ioremap(r->start, r->end - r->start + 1);
+	if (!host->iobase) {
+		dev_err(&pdev->dev, "cannot remap mmio\n");
+		goto out2;
+	}
 
-		if (!mmc) {
-			printk(DRIVER_NAME "ERROR: no mem for host %d\n", i);
-			au1xmmc_hosts[i] = 0;
-			continue;
-		}
+	r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!r) {
+		dev_err(&pdev->dev, "no IRQ defined\n");
+		goto out3;
+	}
 
-		mmc->ops = &au1xmmc_ops;
+	host->irq = r->start;
+	/* IRQ is shared among both SD controllers */
+	ret = request_irq(host->irq, au1xmmc_irq, IRQF_SHARED,
+			  DRIVER_NAME, host);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot grab IRQ\n");
+		goto out3;
+	}
 
-		mmc->f_min =   450000;
-		mmc->f_max = 24000000;
+	mmc->ops = &au1xmmc_ops;
 
-		mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE;
-		mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT;
+	mmc->f_min =   450000;
+	mmc->f_max = 24000000;
 
-		mmc->max_blk_size = 2048;
-		mmc->max_blk_count = 512;
+	mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE;
+	mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT;
 
-		mmc->ocr_avail = AU1XMMC_OCR;
+	mmc->max_blk_size = 2048;
+	mmc->max_blk_count = 512;
 
-		host = mmc_priv(mmc);
-		host->mmc = mmc;
+	mmc->ocr_avail = AU1XMMC_OCR;
+	mmc->caps = 0;
 
-		host->id = i;
-		host->iobase = au1xmmc_card_table[host->id].iobase;
-		host->clock = 0;
-		host->power_mode = MMC_POWER_OFF;
+	host->status = HOST_S_IDLE;
 
-		host->flags = au1xmmc_card_inserted(host) ? HOST_F_ACTIVE : 0;
-		host->status = HOST_S_IDLE;
+	/* board-specific carddetect setup, if any */
+	if (host->platdata && host->platdata->cd_setup) {
+		ret = host->platdata->cd_setup(mmc, 1);
+		if (ret) {
+			dev_err(&pdev->dev, "board CD setup failed\n");
+			goto out4;
+		}
+	} else {
+		/* poll the board-specific is-card-in-socket-? method */
+		au1xmmc_init_cd_poll_timer(host);
+	}
 
-		init_timer(&host->timer);
+	tasklet_init(&host->data_task, au1xmmc_tasklet_data,
+			(unsigned long)host);
 
-		host->timer.function = au1xmmc_poll_event;
-		host->timer.data = (unsigned long) host;
-		host->timer.expires = jiffies + AU1XMMC_DETECT_TIMEOUT;
+	tasklet_init(&host->finish_task, au1xmmc_tasklet_finish,
+			(unsigned long)host);
 
-		tasklet_init(&host->data_task, au1xmmc_tasklet_data,
-				(unsigned long) host);
+#ifdef CONFIG_SOC_AU1200
+	ret = au1xmmc_dbdma_init(host);
+	if (ret)
+		printk(KERN_INFO DRIVER_NAME ": DBDMA init failed; using PIO\n");
+#endif
 
-		tasklet_init(&host->finish_task, au1xmmc_tasklet_finish,
-				(unsigned long) host);
+	au1xmmc_reset_controller(host);
 
-		spin_lock_init(&host->lock);
+	ret = mmc_add_host(mmc);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot add mmc host\n");
+		goto out5;
+	}
 
-		if (dma != 0)
-			au1xmmc_init_dma(host);
+	platform_set_drvdata(pdev, mmc);
 
-		au1xmmc_reset_controller(host);
+	/* start the carddetect poll timer */
+	if (!(host->platdata && host->platdata->cd_setup))
+		add_timer(&host->timer);
 
-		mmc_add_host(mmc);
-		au1xmmc_hosts[i] = host;
+	printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X"
+		" (mode=%s)\n", pdev->id, host->iobase,
+		host->flags & HOST_F_DMA ? "dma" : "pio");
 
-		add_timer(&host->timer);
+	return 0;	/* all ok */
 
-		printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X (mode=%s)\n",
-		       host->id, host->iobase, dma ? "dma" : "pio");
-	}
+out5:
+	au_writel(0, HOST_ENABLE(host));
+	au_writel(0, HOST_CONFIG(host));
+	au_writel(0, HOST_CONFIG2(host));
+	au_sync();
 
-	enable_irq(AU1100_SD_IRQ);
+#ifdef CONFIG_SOC_AU1200
+	au1xmmc_dbdma_shutdown(host);
+#endif
 
-	return 0;
+	tasklet_kill(&host->data_task);
+	tasklet_kill(&host->finish_task);
+
+	if (host->platdata && host->platdata->cd_setup)
+		host->platdata->cd_setup(mmc, 0);
+out4:
+	free_irq(host->irq, host);
+out3:
+	iounmap((void *)host->iobase);
+out2:
+	release_resource(host->ioarea);
+	kfree(host->ioarea);
+out1:
+	mmc_free_host(mmc);
+out0:
+	return ret;
 }
 
 static int __devexit au1xmmc_remove(struct platform_device *pdev)
 {
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
+	struct au1xmmc_host *host;
+
+	if (mmc) {
+		host  = mmc_priv(mmc);
 
-	int i;
+		mmc_remove_host(mmc);
 
-	disable_irq(AU1100_SD_IRQ);
+		if (host->platdata && host->platdata->cd_setup)
+			host->platdata->cd_setup(mmc, 0);
+		else
+			del_timer_sync(&host->timer);
 
-	for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
-		struct au1xmmc_host *host = au1xmmc_hosts[i];
-		if (!host) continue;
+		au_writel(0, HOST_ENABLE(host));
+		au_writel(0, HOST_CONFIG(host));
+		au_writel(0, HOST_CONFIG2(host));
+		au_sync();
 
 		tasklet_kill(&host->data_task);
 		tasklet_kill(&host->finish_task);
 
-		del_timer_sync(&host->timer);
+#ifdef CONFIG_SOC_AU1200
+		au1xmmc_dbdma_shutdown(host);
+#endif
 		au1xmmc_set_power(host, 0);
 
-		mmc_remove_host(host->mmc);
-
-		au1xxx_dbdma_chan_free(host->tx_chan);
-		au1xxx_dbdma_chan_free(host->rx_chan);
+		free_irq(host->irq, host);
+		iounmap((void *)host->iobase);
+		release_resource(host->ioarea);
+		kfree(host->ioarea);
 
-		au_writel(0x0, HOST_ENABLE(host));
-		au_sync();
+		mmc_free_host(mmc);
 	}
-
-	free_irq(AU1100_SD_IRQ, 0);
 	return 0;
 }
 
@@ -1004,21 +1072,31 @@ static struct platform_driver au1xmmc_driver = {
 
 static int __init au1xmmc_init(void)
 {
+#ifdef CONFIG_SOC_AU1200
+	/* DSCR_CMD0_ALWAYS has a stride of 32 bits, we need a stride
+	 * of 8 bits.  And since devices are shared, we need to create
+	 * our own to avoid freaking out other devices.
+	 */
+	memid = au1xxx_ddma_add_device(&au1xmmc_mem_dbdev);
+	if (!memid)
+		printk(KERN_ERR "au1xmmc: cannot add memory dbdma dev\n");
+#endif
 	return platform_driver_register(&au1xmmc_driver);
 }
 
 static void __exit au1xmmc_exit(void)
 {
+#ifdef CONFIG_SOC_AU1200
+	if (memid)
+		au1xxx_ddma_del_device(memid);
+#endif
 	platform_driver_unregister(&au1xmmc_driver);
 }
 
 module_init(au1xmmc_init);
 module_exit(au1xmmc_exit);
 
-#ifdef MODULE
 MODULE_AUTHOR("Advanced Micro Devices, Inc");
 MODULE_DESCRIPTION("MMC/SD driver for the Alchemy Au1XXX");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:au1xxx-mmc");
-#endif
-
diff --git a/drivers/mmc/host/au1xmmc.h b/drivers/mmc/host/au1xmmc.h
index 341cbdf..3b40065 100644
--- a/drivers/mmc/host/au1xmmc.h
+++ b/drivers/mmc/host/au1xmmc.h
@@ -49,8 +49,6 @@ struct au1xmmc_host {
   struct mmc_host *mmc;
   struct mmc_request *mrq;
 
-  u32 id;
-
   u32 flags;
   u32 iobase;
   u32 clock;
@@ -73,11 +71,14 @@ struct au1xmmc_host {
   u32 tx_chan;
   u32 rx_chan;
 
+  int irq;
+
   struct timer_list timer;
   struct tasklet_struct finish_task;
   struct tasklet_struct data_task;
-
-  spinlock_t lock;
+  struct au1xmmc_platform_data *platdata;
+  struct platform_device *pdev;
+  struct resource *ioarea;
 };
 
 /* Status flags used by the host structure */
diff --git a/include/asm-mips/mach-au1x00/au1100_mmc.h b/include/asm-mips/mach-au1x00/au1100_mmc.h
index 9e0028f..c79dec1 100644
--- a/include/asm-mips/mach-au1x00/au1100_mmc.h
+++ b/include/asm-mips/mach-au1x00/au1100_mmc.h
@@ -38,15 +38,12 @@
 #ifndef __ASM_AU1100_MMC_H
 #define __ASM_AU1100_MMC_H
 
-
-#define NUM_AU1100_MMC_CONTROLLERS	2
-
-#if defined(CONFIG_SOC_AU1100)
-#define AU1100_SD_IRQ	AU1100_SD_INT
-#elif defined(CONFIG_SOC_AU1200)
-#define AU1100_SD_IRQ	AU1200_SD_INT
-#endif
-
+struct au1xmmc_platform_data {
+	int(*cd_setup)(void *mmc_host, int on);
+	int(*card_inserted)(void *mmc_host);
+	int(*card_readonly)(void *mmc_host);
+	void(*set_power)(void *mmc_host, int state);
+};
 
 #define SD0_BASE	0xB0600000
 #define SD1_BASE	0xB0680000
-- 
1.5.5.1


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

* Re: [PATCH 9/9] au1xmmc: Add back PB1200/DB1200 MMC activity LED support
  2008-05-19  8:08 ` [PATCH 9/9] au1xmmc: Add back PB1200/DB1200 MMC activity LED support Manuel Lauss
@ 2008-05-19 13:27   ` Sergei Shtylyov
  2008-06-05 21:08   ` Pierre Ossman
  1 sibling, 0 replies; 27+ messages in thread
From: Sergei Shtylyov @ 2008-05-19 13:27 UTC (permalink / raw)
  To: Manuel Lauss; +Cc: linux-mips, linux-kernel, drzeus

Hello.

Manuel Lauss wrote:

> Add back PB1200/DB1200 MMC activity LED support just the way
> it was done in the original driver source.

> Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>

   For the reason of "bisectability" you'd better merge this with patch 3.

WBR, Sergei

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

* Re: [PATCH 4/9] Alchemy: register mmc platform device for db1200/pb1200 boards
  2008-05-19  8:06 ` [PATCH 4/9] Alchemy: register mmc platform device for db1200/pb1200 boards Manuel Lauss
@ 2008-05-21 12:32   ` Sergei Shtylyov
  2008-05-21 13:10     ` Manuel Lauss
  0 siblings, 1 reply; 27+ messages in thread
From: Sergei Shtylyov @ 2008-05-21 12:32 UTC (permalink / raw)
  To: Manuel Lauss; +Cc: linux-mips, linux-kernel, drzeus

Hello.

Manuel Lauss wrote:

> Add au1xmmc platform data for PB1200/DB1200 boards, and wire up
> the 2 SD controllers for them.

> Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>

    OK, this definitely looks better (and shorter :-).

> diff --git a/arch/mips/au1000/common/platform.c b/arch/mips/au1000/common/platform.c
> index 8cae775..6225e95 100644
> --- a/arch/mips/au1000/common/platform.c
> +++ b/arch/mips/au1000/common/platform.c

[...]

> @@ -248,15 +232,70 @@ static struct platform_device au1200_lcd_device = {
>  
>  static u64 au1xxx_mmc_dmamask =  ~(u32)0;
>  
> -static struct platform_device au1xxx_mmc_device = {
> +extern struct au1xmmc_platform_data au1xmmc_platdata[2];
> +
> +static struct resource au1200_mmc0_resources[] = {
> +	[0] = {
> +		.start          = SD0_PHYS_ADDR,
> +		.end            = SD0_PHYS_ADDR + 0x7ffff,
> +		.flags          = IORESOURCE_MEM,
> +	},
> +	[1] = {
> +		.start		= AU1200_SD_INT,
> +		.flags		= IORESOURCE_IRQ,
> +	},
> +	[2] = {
> +		.start		= DSCR_CMD0_SDMS_TX0,
> +		.flags		= IORESOURCE_DMA,
> +	},
> +	[3] = {
> +		.start          = DSCR_CMD0_SDMS_RX0,
> +		.flags          = IORESOURCE_DMA,
> +	}
> +};
> +
> +static struct resource au1200_mmc1_resources[] = {
> +	[0] = {
> +		.start          = SD1_PHYS_ADDR,
> +		.end            = SD1_PHYS_ADDR + 0x7ffff,
> +		.flags          = IORESOURCE_MEM,
> +	},
> +	[1] = {
> +		.start		= AU1200_SD_INT,
> +		.flags		= IORESOURCE_IRQ,
> +	},
> +	[2] = {
> +		.start		= DSCR_CMD0_SDMS_TX1,
> +		.flags		= IORESOURCE_DMA,
> +	},
> +	[3] = {
> +		.start          = DSCR_CMD0_SDMS_RX1,
> +		.flags          = IORESOURCE_DMA,
> +	}
> +};
> +

    Shouldn't the IRQ/DMA resources also have their 'end' field set?

[...]

> diff --git a/arch/mips/au1000/pb1200/platform.c b/arch/mips/au1000/pb1200/platform.c
> index 5930110..f329a38 100644
> --- a/arch/mips/au1000/pb1200/platform.c
> +++ b/arch/mips/au1000/pb1200/platform.c
> @@ -22,6 +22,66 @@
>  #include <linux/platform_device.h>
>  
>  #include <asm/mach-au1x00/au1xxx.h>
> +#include <asm/mach-au1x00/au1100_mmc.h>
> +
> +static void pb1200mmc0_set_power(void *mmc_host, int state)
> +{
> +	if (state)
> +		bcsr->board |= BCSR_BOARD_SD0PWR;
> +	else
> +		bcsr->board &= ~BCSR_BOARD_SD0PWR;
> +
> +	au_sync_delay(1);
> +}
> +
> +static int pb1200mmc0_card_readonly(void *mmc_host)
> +{
> +	return (bcsr->status & BCSR_STATUS_SD0WP) ? 1 : 0;
> +}
> +
> +static int pb1200mmc0_card_inserted(void *mmc_host)
> +{
> +	return (bcsr->sig_status & BCSR_INT_SD0INSERT) ? 1 : 0;
> +}
> +
> +#ifndef CONFIG_MIPS_DB1200
> +static void pb1200mmc1_set_power(void *mmc_host, int state)
> +{
> +	if (state)
> +		bcsr->board |= BCSR_BOARD_SD1PWR;
> +	else
> +		bcsr->board &= ~BCSR_BOARD_SD1PWR;
> +
> +	au_sync_delay(1);
> +}
> +
> +static int pb1200mmc1_card_readonly(void *mmc_host)
> +{
> +	return (bcsr->status & BCSR_STATUS_SD1WP) ? 1 : 0;
> +}
> +
> +static int pb1200mmc1_card_inserted(void *mmc_host)
> +{
> +	return (bcsr->sig_status & BCSR_INT_SD1INSERT) ? 1 : 0;
> +}
> +#endif

    These 2 separate versions could be converted into single one by using the 
data arrays holding info BCSR bits -- something like the MMC driver has currently.

> +
> +const struct au1xmmc_platform_data au1xmmc_platdata[2] = {
> +	[0] = {
> +		.set_power	= pb1200mmc0_set_power,
> +		.card_inserted	= pb1200mmc0_card_inserted,
> +		.card_readonly	= pb1200mmc0_card_readonly,
> +		.cd_setup	= NULL,		/* use poll-timer in driver */
> +	},
> +#ifndef CONFIG_MIPS_DB1200
> +	[1] = {
> +		.set_power	= pb1200mmc1_set_power,
> +		.card_inserted	= pb1200mmc1_card_inserted,
> +		.card_readonly	= pb1200mmc1_card_readonly,
> +		.cd_setup	= NULL,		/* use poll-timer in driver */
> +	},
> +#endif
> +};

    You don't have to explicitly set 'cd_setup' to NULL...

PS: BTW, I've noticed that include/asm-mips/mach-db1x00/db1x00.h defines 
macros mmc_card_insterted() and mmc_power_on() which no code seems to be using 
(might have been intended for use by the MMC driver but why no such macros in 
other board headers?). Care to remove those while you're working on MMC?

WBR, Sergei

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

* Re: [PATCH 4/9] Alchemy: register mmc platform device for db1200/pb1200 boards
  2008-05-21 12:32   ` Sergei Shtylyov
@ 2008-05-21 13:10     ` Manuel Lauss
  0 siblings, 0 replies; 27+ messages in thread
From: Manuel Lauss @ 2008-05-21 13:10 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: linux-mips, linux-kernel, drzeus

Hi Sergei,

> Manuel Lauss wrote:
>
>> Add au1xmmc platform data for PB1200/DB1200 boards, and wire up
>> the 2 SD controllers for them.
>
>> Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
>
>    OK, this definitely looks better (and shorter :-).

Thanks ;-)


>> +static struct resource au1200_mmc0_resources[] = {
>> +	[0] = {
>> +		.start          = SD0_PHYS_ADDR,
>> +		.end            = SD0_PHYS_ADDR + 0x7ffff,
>> +		.flags          = IORESOURCE_MEM,
>> +	},
>> +	[1] = {
>> +		.start		= AU1200_SD_INT,
>> +		.flags		= IORESOURCE_IRQ,
>> +	},
>> +	[2] = {
>> +		.start		= DSCR_CMD0_SDMS_TX0,
>> +		.flags		= IORESOURCE_DMA,
>> +	},
>> +	[3] = {
>> +		.start          = DSCR_CMD0_SDMS_RX0,
>> +		.flags          = IORESOURCE_DMA,
>> +	}
>> +};
>> +
>> +static struct resource au1200_mmc1_resources[] = {
>> +	[0] = {
>> +		.start          = SD1_PHYS_ADDR,
>> +		.end            = SD1_PHYS_ADDR + 0x7ffff,
>> +		.flags          = IORESOURCE_MEM,
>> +	},
>> +	[1] = {
>> +		.start		= AU1200_SD_INT,
>> +		.flags		= IORESOURCE_IRQ,
>> +	},
>> +	[2] = {
>> +		.start		= DSCR_CMD0_SDMS_TX1,
>> +		.flags		= IORESOURCE_DMA,
>> +	},
>> +	[3] = {
>> +		.start          = DSCR_CMD0_SDMS_RX1,
>> +		.flags          = IORESOURCE_DMA,
>> +	}
>> +};
>> +
>
>    Shouldn't the IRQ/DMA resources also have their 'end' field set?

Not sure, but I'll add them too.


>> +static void pb1200mmc0_set_power(void *mmc_host, int state)
>> +{
>> +	if (state)
>> +		bcsr->board |= BCSR_BOARD_SD0PWR;
>> +	else
>> +		bcsr->board &= ~BCSR_BOARD_SD0PWR;
>> +
>> +	au_sync_delay(1);
>> +}
>> +
>> +static int pb1200mmc0_card_readonly(void *mmc_host)
>> +{
>> +	return (bcsr->status & BCSR_STATUS_SD0WP) ? 1 : 0;
>> +}
>> +
>> +static int pb1200mmc0_card_inserted(void *mmc_host)
>> +{
>> +	return (bcsr->sig_status & BCSR_INT_SD0INSERT) ? 1 : 0;
>> +}
>> +
>> +#ifndef CONFIG_MIPS_DB1200
>> +static void pb1200mmc1_set_power(void *mmc_host, int state)
>> +{
>> +	if (state)
>> +		bcsr->board |= BCSR_BOARD_SD1PWR;
>> +	else
>> +		bcsr->board &= ~BCSR_BOARD_SD1PWR;
>> +
>> +	au_sync_delay(1);
>> +}
>> +
>> +static int pb1200mmc1_card_readonly(void *mmc_host)
>> +{
>> +	return (bcsr->status & BCSR_STATUS_SD1WP) ? 1 : 0;
>> +}
>> +
>> +static int pb1200mmc1_card_inserted(void *mmc_host)
>> +{
>> +	return (bcsr->sig_status & BCSR_INT_SD1INSERT) ? 1 : 0;
>> +}
>> +#endif
>
>    These 2 separate versions could be converted into single one by using 
> the data arrays holding info BCSR bits -- something like the MMC driver has 
> currently.

Well, that's what my initial submission did, but it required access to the
mmc drivers host structure (moved from au1xmmc.h to au1100_mmc.h) to determine
which controller wants the attention, and you weren't fond of that.


>> +
>> +const struct au1xmmc_platform_data au1xmmc_platdata[2] = {
>> +	[0] = {
>> +		.set_power	= pb1200mmc0_set_power,
>> +		.card_inserted	= pb1200mmc0_card_inserted,
>> +		.card_readonly	= pb1200mmc0_card_readonly,
>> +		.cd_setup	= NULL,		/* use poll-timer in driver */
>> +	},
>> +#ifndef CONFIG_MIPS_DB1200
>> +	[1] = {
>> +		.set_power	= pb1200mmc1_set_power,
>> +		.card_inserted	= pb1200mmc1_card_inserted,
>> +		.card_readonly	= pb1200mmc1_card_readonly,
>> +		.cd_setup	= NULL,		/* use poll-timer in driver */
>> +	},
>> +#endif
>> +};
>
>    You don't have to explicitly set 'cd_setup' to NULL...

The comment explains what setting to NULL does, so I'd like to
keep it (for people implementing this for other boards and wondering what
to do with thse members...)


> PS: BTW, I've noticed that include/asm-mips/mach-db1x00/db1x00.h defines 
> macros mmc_card_insterted() and mmc_power_on() which no code seems to be 
> using (might have been intended for use by the MMC driver but why no such 
> macros in other board headers?). Care to remove those while you're working 
> on MMC?

Sure, I'll add another patch to the pile.


Thank you!
	Manuel Lauss

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

* Re: [PATCH 1/9] Alchemy: export get_au1x00_speed for modules
  2008-05-19  9:49     ` Manuel Lauss
@ 2008-06-05 21:03       ` Pierre Ossman
  2008-06-06  7:16         ` Manuel Lauss
  0 siblings, 1 reply; 27+ messages in thread
From: Pierre Ossman @ 2008-06-05 21:03 UTC (permalink / raw)
  To: Manuel Lauss, ralf; +Cc: Sergei Shtylyov, linux-mips, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 820 bytes --]

On Mon, 19 May 2008 11:49:53 +0200
Manuel Lauss <mano@roarinelk.homelinux.net> wrote:

> Hi Sergei,
> 
> >> From 8492076e98c7fd47c9dee53984dbd9568ace357d Mon Sep 17 00:00:00 2001
> >> From: Manuel Lauss <mlau@msc-ge.com>
> >> Date: Wed, 7 May 2008 13:42:55 +0200
> >> Subject: [PATCH] Alchemy: export get_au1x00_speed for modules
> >>
> >> au1xmmc.c driver depends on it, so export it for modules.
> >>
> >> Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
> >>   
> >
> >   I thought that has been merged.
> 
> Yes, Ralf merged it into linux-mips repo, but it is not yet in
> mainline and the rest of the patches are against linus' git.
> 

So who should push this to Linus? If this set is the only patches
depending on it, it would be easiest if I carry it in my tree.

Rgds
Pierre

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 8/9] au1xmmc: abort requests early if no card is present
  2008-05-19  8:08 ` [PATCH 8/9] au1xmmc: abort requests early if no card is present Manuel Lauss
@ 2008-06-05 21:05   ` Pierre Ossman
  2008-06-06  7:17     ` Manuel Lauss
  0 siblings, 1 reply; 27+ messages in thread
From: Pierre Ossman @ 2008-06-05 21:05 UTC (permalink / raw)
  To: Manuel Lauss; +Cc: linux-mips, linux-kernel, sshtylyov

[-- Attachment #1: Type: text/plain, Size: 1240 bytes --]

On Mon, 19 May 2008 10:08:04 +0200
Manuel Lauss <mano@roarinelk.homelinux.net> wrote:

> From ec41439903048bf98e301dbd03426c63156ebc0e Mon Sep 17 00:00:00 2001
> From: Manuel Lauss <mlau@msc-ge.com>
> Date: Sun, 18 May 2008 15:52:43 +0200
> Subject: [PATCH] au1xmmc: abort requests early if no card is present
> 
> Don't process a request if no card is present.
> 
> Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
> ---
>  drivers/mmc/host/au1xmmc.c |    7 +++++++
>  1 files changed, 7 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
> index be09a14..0b30582 100644
> --- a/drivers/mmc/host/au1xmmc.c
> +++ b/drivers/mmc/host/au1xmmc.c
> @@ -689,6 +689,13 @@ static void au1xmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
>  	host->mrq = mrq;
>  	host->status = HOST_S_CMD;
>  
> +	/* fail request immediately if no card is present */
> +	if (0 == au1xmmc_card_inserted(host)) {
> +		mrq->cmd->error = -ETIMEDOUT;
> +		au1xmmc_finish_request(host);
> +		return;
> +	}
> +
>  	if (mrq->data) {
>  		FLUSH_FIFO(host);
>  		ret = au1xmmc_prepare_data(host, mrq->data);

You should use -ENOMEDIUM for this case.

Rgds
Pierre

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 9/9] au1xmmc: Add back PB1200/DB1200 MMC activity LED support
  2008-05-19  8:08 ` [PATCH 9/9] au1xmmc: Add back PB1200/DB1200 MMC activity LED support Manuel Lauss
  2008-05-19 13:27   ` Sergei Shtylyov
@ 2008-06-05 21:08   ` Pierre Ossman
  2008-06-06  7:45     ` Manuel Lauss
  1 sibling, 1 reply; 27+ messages in thread
From: Pierre Ossman @ 2008-06-05 21:08 UTC (permalink / raw)
  To: Manuel Lauss; +Cc: linux-mips, linux-kernel, sshtylyov

[-- Attachment #1: Type: text/plain, Size: 659 bytes --]

On Mon, 19 May 2008 10:08:37 +0200
Manuel Lauss <mano@roarinelk.homelinux.net> wrote:

> From 5747bd6933bb212ab83044fa79adf185d248513f Mon Sep 17 00:00:00 2001
> From: Manuel Lauss <mlau@msc-ge.com>
> Date: Sun, 18 May 2008 16:05:56 +0200
> Subject: [PATCH] au1xmmc: Add back PB1200/DB1200 MMC activity LED support.
> 
> Add back PB1200/DB1200 MMC activity LED support just the way
> it was done in the original driver source.
> 
> Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>

You might want to consider using the LED subsystem now that the MMC
core exports a trigger. Look at my next tree for how sdhci uses it.

Rgds
Pierre

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 0/9] au1xmmc updates #3
  2008-05-19  8:03 [PATCH 0/9] au1xmmc updates #3 Manuel Lauss
                   ` (8 preceding siblings ...)
  2008-05-19  8:08 ` [PATCH 9/9] au1xmmc: Add back PB1200/DB1200 MMC activity LED support Manuel Lauss
@ 2008-06-05 21:09 ` Pierre Ossman
  2008-06-06  7:18   ` Manuel Lauss
  9 siblings, 1 reply; 27+ messages in thread
From: Pierre Ossman @ 2008-06-05 21:09 UTC (permalink / raw)
  To: Manuel Lauss; +Cc: linux-mips, linux-kernel, sshtylyov

[-- Attachment #1: Type: text/plain, Size: 286 bytes --]

On Mon, 19 May 2008 10:03:39 +0200
Manuel Lauss <mano@roarinelk.homelinux.net> wrote:

> Hello,
> 
> The following set of patches remove demoboard-specific code from the
> au1xmmc.c driver and adds new features.
> 

The role of maintainer is vacant if you want it. *nudge* ;)

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 1/9] Alchemy: export get_au1x00_speed for modules
  2008-06-05 21:03       ` Pierre Ossman
@ 2008-06-06  7:16         ` Manuel Lauss
  2008-06-06 11:45           ` Sergei Shtylyov
  0 siblings, 1 reply; 27+ messages in thread
From: Manuel Lauss @ 2008-06-06  7:16 UTC (permalink / raw)
  To: Pierre Ossman; +Cc: ralf, Sergei Shtylyov, linux-mips, linux-kernel

Hi Folks,

On Thu, Jun 05, 2008 at 11:03:11PM +0200, Pierre Ossman wrote:
> On Mon, 19 May 2008 11:49:53 +0200
> Manuel Lauss <mano@roarinelk.homelinux.net> wrote:
> 
> > Hi Sergei,
> > 
> > >> From 8492076e98c7fd47c9dee53984dbd9568ace357d Mon Sep 17 00:00:00 2001
> > >> From: Manuel Lauss <mlau@msc-ge.com>
> > >> Date: Wed, 7 May 2008 13:42:55 +0200
> > >> Subject: [PATCH] Alchemy: export get_au1x00_speed for modules
> > >>
> > >> au1xmmc.c driver depends on it, so export it for modules.
> > >>
> > >> Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
> > >>   
> > >
> > >   I thought that has been merged.
> > 
> > Yes, Ralf merged it into linux-mips repo, but it is not yet in
> > mainline and the rest of the patches are against linus' git.
> > 
> 
> So who should push this to Linus? If this set is the only patches
> depending on it, it would be easiest if I carry it in my tree.

I'd prefer if you (Pierre) carried them all since they all depend on
each other (kind of, anyway).  And it seems Ralf has gone silent anyway :)

Thank you!
	Manuel Lauss


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

* Re: [PATCH 8/9] au1xmmc: abort requests early if no card is present
  2008-06-05 21:05   ` Pierre Ossman
@ 2008-06-06  7:17     ` Manuel Lauss
  0 siblings, 0 replies; 27+ messages in thread
From: Manuel Lauss @ 2008-06-06  7:17 UTC (permalink / raw)
  To: Pierre Ossman; +Cc: linux-mips, linux-kernel, sshtylyov

Hi Pierre,

On Thu, Jun 05, 2008 at 11:05:52PM +0200, Pierre Ossman wrote:
> On Mon, 19 May 2008 10:08:04 +0200
> Manuel Lauss <mano@roarinelk.homelinux.net> wrote:
> 
> > From ec41439903048bf98e301dbd03426c63156ebc0e Mon Sep 17 00:00:00 2001
> > From: Manuel Lauss <mlau@msc-ge.com>
> > Date: Sun, 18 May 2008 15:52:43 +0200
> > Subject: [PATCH] au1xmmc: abort requests early if no card is present
> > 
> > Don't process a request if no card is present.
> > 
> > Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
> > ---
> >  drivers/mmc/host/au1xmmc.c |    7 +++++++
> >  1 files changed, 7 insertions(+), 0 deletions(-)
> > 
> > diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
> > index be09a14..0b30582 100644
> > --- a/drivers/mmc/host/au1xmmc.c
> > +++ b/drivers/mmc/host/au1xmmc.c
> > @@ -689,6 +689,13 @@ static void au1xmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
> >  	host->mrq = mrq;
> >  	host->status = HOST_S_CMD;
> >  
> > +	/* fail request immediately if no card is present */
> > +	if (0 == au1xmmc_card_inserted(host)) {
> > +		mrq->cmd->error = -ETIMEDOUT;
> > +		au1xmmc_finish_request(host);
> > +		return;
> > +	}
> > +
> >  	if (mrq->data) {
> >  		FLUSH_FIFO(host);
> >  		ret = au1xmmc_prepare_data(host, mrq->data);
> 
> You should use -ENOMEDIUM for this case.

Didn't know it existed, consider it changed.

Thanks!
	Manuel Lauss


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

* Re: [PATCH 0/9] au1xmmc updates #3
  2008-06-05 21:09 ` [PATCH 0/9] au1xmmc updates #3 Pierre Ossman
@ 2008-06-06  7:18   ` Manuel Lauss
  2008-06-06 10:11     ` Pierre Ossman
  0 siblings, 1 reply; 27+ messages in thread
From: Manuel Lauss @ 2008-06-06  7:18 UTC (permalink / raw)
  To: Pierre Ossman; +Cc: linux-mips, linux-kernel, sshtylyov

Hi Pierre,

On Thu, Jun 05, 2008 at 11:09:23PM +0200, Pierre Ossman wrote:
> On Mon, 19 May 2008 10:03:39 +0200
> Manuel Lauss <mano@roarinelk.homelinux.net> wrote:
> 
> > Hello,
> > 
> > The following set of patches remove demoboard-specific code from the
> > au1xmmc.c driver and adds new features.
> > 
> 
> The role of maintainer is vacant if you want it. *nudge* ;)


I'll do it as long as I have hardware or you find someone better.

Thanks!
	Manuel Lauss

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

* Re: [PATCH 9/9] au1xmmc: Add back PB1200/DB1200 MMC activity LED support
  2008-06-05 21:08   ` Pierre Ossman
@ 2008-06-06  7:45     ` Manuel Lauss
  0 siblings, 0 replies; 27+ messages in thread
From: Manuel Lauss @ 2008-06-06  7:45 UTC (permalink / raw)
  To: Pierre Ossman; +Cc: linux-mips, linux-kernel, sshtylyov

Hi Pierre,

On Thu, Jun 05, 2008 at 11:08:03PM +0200, Pierre Ossman wrote:
> On Mon, 19 May 2008 10:08:37 +0200
> Manuel Lauss <mano@roarinelk.homelinux.net> wrote:
> 
> > From 5747bd6933bb212ab83044fa79adf185d248513f Mon Sep 17 00:00:00 2001
> > From: Manuel Lauss <mlau@msc-ge.com>
> > Date: Sun, 18 May 2008 16:05:56 +0200
> > Subject: [PATCH] au1xmmc: Add back PB1200/DB1200 MMC activity LED support.
> > 
> > Add back PB1200/DB1200 MMC activity LED support just the way
> > it was done in the original driver source.
> > 
> > Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
> 
> You might want to consider using the LED subsystem now that the MMC
> core exports a trigger. Look at my next tree for how sdhci uses it.

I tried that originally. The LED subsystem seems quite complex for something
as simple as turning on a bit in a register. I don't have a DB1200 to test
so I went the safe route and added a simple callback to toggle the LED bit in
the DB1200 FPGA.

I'll try to come up with something over the weekend and then resend the
whole series.

Thanks!
	Manuel Lauss



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

* Re: [PATCH 0/9] au1xmmc updates #3
  2008-06-06  7:18   ` Manuel Lauss
@ 2008-06-06 10:11     ` Pierre Ossman
  0 siblings, 0 replies; 27+ messages in thread
From: Pierre Ossman @ 2008-06-06 10:11 UTC (permalink / raw)
  To: Manuel Lauss; +Cc: linux-mips, linux-kernel, sshtylyov

[-- Attachment #1: Type: text/plain, Size: 339 bytes --]

On Fri, 6 Jun 2008 09:18:31 +0200
Manuel Lauss <mano@roarinelk.homelinux.net> wrote:

> > 
> > The role of maintainer is vacant if you want it. *nudge* ;)
> 
> 
> I'll do it as long as I have hardware or you find someone better.
> 

Great. Please include a patch for the MAINTAINERS file in your next set
then.

Rgds
Pierre

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 1/9] Alchemy: export get_au1x00_speed for modules
  2008-06-06  7:16         ` Manuel Lauss
@ 2008-06-06 11:45           ` Sergei Shtylyov
  0 siblings, 0 replies; 27+ messages in thread
From: Sergei Shtylyov @ 2008-06-06 11:45 UTC (permalink / raw)
  To: Manuel Lauss; +Cc: Pierre Ossman, ralf, linux-mips, linux-kernel

Hello.

Manuel Lauss wrote:
>>>>> From 8492076e98c7fd47c9dee53984dbd9568ace357d Mon Sep 17 00:00:00 2001
>>>>> From: Manuel Lauss <mlau@msc-ge.com>
>>>>> Date: Wed, 7 May 2008 13:42:55 +0200
>>>>> Subject: [PATCH] Alchemy: export get_au1x00_speed for modules
>>>>>
>>>>> au1xmmc.c driver depends on it, so export it for modules.
>>>>>
>>>>> Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
>>>>>
>>>>>           
>>>>   I thought that has been merged.
>>>>         
>>> Yes, Ralf merged it into linux-mips repo, but it is not yet in
>>> mainline and the rest of the patches are against linus' git.
>>>
>>>       
>> So who should push this to Linus? If this set is the only patches
>> depending on it, it would be easiest if I carry it in my tree.
>>     
>
> I'd prefer if you (Pierre) carried them all since they all depend on
> each other (kind of, anyway).  And it seems Ralf has gone silent anyway :)
>   

   Ralf has pushed this patch to Linus, and it has gone into the Linus' 
tree today.

> Thank you!
> 	Manuel Lauss
>   

WBR, Sergei



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

end of thread, other threads:[~2008-06-06 11:46 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-05-19  8:03 [PATCH 0/9] au1xmmc updates #3 Manuel Lauss
2008-05-19  8:04 ` [PATCH 1/9] Alchemy: export get_au1x00_speed for modules Manuel Lauss
2008-05-19  9:35   ` Sergei Shtylyov
2008-05-19  9:49     ` Manuel Lauss
2008-06-05 21:03       ` Pierre Ossman
2008-06-06  7:16         ` Manuel Lauss
2008-06-06 11:45           ` Sergei Shtylyov
2008-05-19  8:04 ` [PATCH 2/9] Alchemy: dbdma: add API to delete custom DDMA device ids Manuel Lauss
2008-05-19  8:05 ` [PATCH 3/9] au1xmmc: remove pb1200 board-specific code from driver file Manuel Lauss
2008-05-19  8:17   ` Manuel Lauss
2008-05-19 10:07     ` Manuel Lauss
2008-05-19  8:06 ` [PATCH 4/9] Alchemy: register mmc platform device for db1200/pb1200 boards Manuel Lauss
2008-05-21 12:32   ` Sergei Shtylyov
2008-05-21 13:10     ` Manuel Lauss
2008-05-19  8:06 ` [PATCH 5/9] au1xmmc: enable 4 bit transfer mode Manuel Lauss
2008-05-19  8:06 ` [PATCH 6/9] au1xmmc: SDIO IRQ support Manuel Lauss
2008-05-19  8:07 ` [PATCH 7/9] au1xmmc: codingstyle tidying Manuel Lauss
2008-05-19  8:08 ` [PATCH 8/9] au1xmmc: abort requests early if no card is present Manuel Lauss
2008-06-05 21:05   ` Pierre Ossman
2008-06-06  7:17     ` Manuel Lauss
2008-05-19  8:08 ` [PATCH 9/9] au1xmmc: Add back PB1200/DB1200 MMC activity LED support Manuel Lauss
2008-05-19 13:27   ` Sergei Shtylyov
2008-06-05 21:08   ` Pierre Ossman
2008-06-06  7:45     ` Manuel Lauss
2008-06-05 21:09 ` [PATCH 0/9] au1xmmc updates #3 Pierre Ossman
2008-06-06  7:18   ` Manuel Lauss
2008-06-06 10:11     ` Pierre Ossman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox