Subject: au1xmmc.c: does it work?

From: Manuel Lauss <[email-masked]>
Date: Mon, 20 Nov 2006 10:40:53 +0100

Hello folks,

I'm trying to get the au1x mmc driver working on a Au1200 board.
I insert a known working card, and the mmc cmd trace suggests
CMD9 (send CSD) times out. Before I go about to trace the
problem I'd like to know if other people see this problem too
or if it's specific to my system.
(Au1200, 2.6.19-rc6)

Thanks!

-- 
 ml.

---

From: Freddy Spierenburg <[email-masked]>
Date: Mon, 20 Nov 2006 11:49:22 +0100

Hi Manuel,

On Mon, Nov 20, 2006 at 10:40:53AM +0100, Manuel Lauss wrote:
> CMD9 (send CSD) times out.

Are you working with a real MMC card or with an SD-card?

I myself am not able to get several SD-cards working, even though
SD-cards should be able to talk the MMC-protocol (AFAIK).

What I do have is several MMC-cards working properly, but I have
to add a small side note. I am using the AU1100 processor on our
own designed board. This AU1100 processor has a different DMA
controller than the AU1200 and AU1500. Unfortunaly the mmc driver
is written to use the DMA driver for the AU1200/AU1500 controller
and not the DMA driver for the AU1100. This is why I have a
slightly altered version of the au1xmmc driver. This version is
currently using pio mode instead of DMA. In the future I want it
to correcly use the right DMA driver depending on the processor,
but time constrains keep me at this moment from doing that. Also
it is a little bit addapted for our own hardware, which is like I
mentioned before not the DBAu1100 development board.

If you have trouble with MMC-cards too I'm more than willing to
send you the patch, but it probably needs some tweaking on your
part. That's why I do not yet attach it to this mail. Just ask
me personally for it if you want to try it out.

> Before I go about to trace the problem I'd like to know if
> other people see this problem too or if it's specific to my
> system.

With the SD-cards the driver indeed got no answer on the CMD9
request. So yes, I have the same problem on the AU1100 with the
2.6.16 kernel.

-- 
$ cat ~/.signature
Freddy Spierenburg <[email-masked]>  http://freddy.snarl.nl/
GnuPG: 0x7941D1E1=C948 5851 26D2 FA5C 39F1  E588 6F17 FD5D 7941 D1E1
$ # Please read http://www.ietf.org/rfc/rfc2015.txt before complain!

---

From: Manuel Lauss <[email-masked]>
Date: Mon, 20 Nov 2006 13:01:48 +0100

Hi Freddy,

> Are you working with a real MMC card or with an SD-card?

SD cards so far. MMC seems broken in a different way.

> SD-cards should be able to talk the MMC-protocol (AFAIK).

From what I understand, SD is a superset of the MMC command set.

> controller than the AU1200 and AU1500. 

It does not get so far to actually transfer data

> me personally for it if you want to try it out.

Yes, please. I'd like to give it a spin
 
> request. So yes, I have the same problem on the AU1100 with the

I'll see what I can do ti fix this.

Thanks,

-- 
 ml.

---

From: Freddy Spierenburg <[email-masked]>
Date: Mon, 20 Nov 2006 13:37:40 +0100

Hi Manuel,

> SD cards so far. MMC seems broken in a different way.

Broke in a different way? I can positively confirm that I have a
512MB and 1GB MMC-card working with the patch I hereby send to
you.

I've also tried a DaneElec 1GB and Kingston 1GB SD-card and
SanDisk 128MB MicroSD-card. All failed.

> Yes, please. I'd like to give it a spin

Please find it attached.

-- 
$ cat ~/.signature
Freddy Spierenburg <[email-masked]>  http://freddy.snarl.nl/
GnuPG: 0x7941D1E1=C948 5851 26D2 FA5C 39F1  E588 6F17 FD5D 7941 D1E1
$ # Please read http://www.ietf.org/rfc/rfc2015.txt before complain!
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 7bddcc4..328039d 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -22,7 +22,7 @@ #
 # Select the object file format to substitute into the linker script.
 #
 ifdef CONFIG_CPU_LITTLE_ENDIAN
-32bit-tool-prefix	= mipsel-linux-
+32bit-tool-prefix	= mipsel-linux-gnu-
 64bit-tool-prefix	= mips64el-linux-
 32bit-bfd		= elf32-tradlittlemips
 64bit-bfd		= elf64-tradlittlemips
diff --git a/arch/mips/au1000/common/clocks.c b/arch/mips/au1000/common/clocks.c
index 3ce6cac..b1f5524 100644
--- a/arch/mips/au1000/common/clocks.c
+++ b/arch/mips/au1000/common/clocks.c
@@ -46,6 +46,7 @@ unsigned int get_au1x00_speed(void)
 {
 	return au1x00_clock;
 }
+EXPORT_SYMBOL(get_au1x00_speed);

diff --git a/arch/mips/au1000/common/platform.c b/arch/mips/au1000/common/platform.c
index 48d3f54..65376ef 100644
--- a/arch/mips/au1000/common/platform.c
+++ b/arch/mips/au1000/common/platform.c
@@ -72,6 +72,38 @@ static struct platform_device au1100_lcd
 	.num_resources  = ARRAY_SIZE(au1100_lcd_resources),
 	.resource       = au1100_lcd_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          = AU1100_SD_INT,
+		.end            = AU1100_SD_INT,
+		.flags          = IORESOURCE_IRQ,
+	}
+};
+
+static u64 au1xxx_mmc_dmamask =  ~(u32)0;
+
+static struct platform_device au1xxx_mmc_device = {
+	.name = "au1xxx-mmc",
+	.id = 0,
+	.dev = {
+		.dma_mask               = &au1xxx_mmc_dmamask,
+		.coherent_dma_mask      = 0xffffffff,
+	},
+	.num_resources  = ARRAY_SIZE(au1xxx_mmc_resources),
+	.resource       = au1xxx_mmc_resources,
+};
+
 #endif
 
 #ifdef CONFIG_SOC_AU1200
@@ -276,6 +308,7 @@ static struct platform_device *au1xxx_pl
 	&au1x00_pcmcia_device,
 #ifdef CONFIG_FB_AU1100
 	&au1100_lcd_device,
+	&au1xxx_mmc_device,
 #endif
 #ifdef CONFIG_SOC_AU1200
 #if 0	/* fixme */
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c
index 8d84b04..be21e7c 100644
--- a/drivers/mmc/au1xmmc.c
+++ b/drivers/mmc/au1xmmc.c
@@ -47,6 +47,7 @@ #include <linux/mmc/protocol.h>
 #include <asm/io.h>
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1xxx_dbdma.h>
+#include <asm/mach-au1x00/au1xxx_gpio.h>
 #include <asm/mach-au1x00/au1100_mmc.h>
 #include <asm/scatterlist.h>
 
@@ -55,8 +56,13 @@ #include "au1xmmc.h"
 
 #define DRIVER_NAME "au1xxx-mmc"
 
+/* Set this for Dare processor board adjustments */
+//#define MMC_DARE_PROCESSOR_BOARD
+/* DMA isn't implemented yet: */
+//#define MMC_DARE_DMA_IMPLEMENTED
+
 /* Set this to enable special debugging macros */
-/* #define MMC_DEBUG */
+#define MMC_DEBUG
 
 #ifdef MMC_DEBUG
 #define DEBUG(fmt, idx, args...) printk("au1xx(%d): DEBUG: " fmt, idx, ##args)
@@ -66,17 +72,9 @@ #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
+	{ SD0_BASE, BCSR_BOARD_SD0_WP },
 };
 
 #define AU1XMMC_CONTROLLER_COUNT \
@@ -84,7 +82,11 @@ #define AU1XMMC_CONTROLLER_COUNT \
 
 /* This array stores pointers for the hosts (used by the IRQ handler) */
 struct au1xmmc_host *au1xmmc_hosts[AU1XMMC_CONTROLLER_COUNT];
+#ifdef MMC_DARE_DMA_IMPLEMENTED
 static int dma = 1;
+#else
+static int dma = 0; /* DMA isn't implemented yet in this driver */
+#endif
 
 #ifdef MODULE
 MODULE_PARM(dma, "i");
@@ -139,25 +141,33 @@ static inline void SEND_STOP(struct au1x
 
 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);
+#ifdef MMC_DARE_PROCESSOR_BOARD
+	state = 1; /* Force gpio high for card detection */
+	au1xxx_gpio_write(19, state ? 1 : 0);
+#else /* db1100 board */
+	mmc_power(host->id, state);
+#endif
 }
 
 static inline int au1xmmc_card_inserted(struct au1xmmc_host *host)
 {
-	return (bcsr->sig_status & au1xmmc_card_table[host->id].bcsrstatus)
-		? 1 : 0;
+	int res = 0;
+	/* Note: card inserted checks at read-only switch,
+	 * if a card is set to read-only, it won't be recognized */
+#ifdef MMC_DARE_PROCESSOR_BOARD
+	/* Note: removing power (gpio19 low), makes it look like
+	 * the card has been removed */
+	res = au1xxx_gpio_read(19);
+#else /* db1100 board */
+	mmc_card_inserted(host->id, &res);
+#endif
+	return res;
 }
 
 static inline int au1xmmc_card_readonly(struct au1xmmc_host *host)
 {
-	return (bcsr->status & au1xmmc_card_table[host->id].wpstatus)
-		? 1 : 0;
+	/* Not implemented */
+	return 0;
 }
 
 static void au1xmmc_finish_request(struct au1xmmc_host *host)
@@ -177,8 +187,6 @@ static void au1xmmc_finish_request(struc
 
 	host->status = HOST_S_IDLE;
 
-	bcsr->disk_leds |= (1 << 8);
-
 	mmc_request_done(host->mmc, mrq);
 }
 
@@ -531,6 +539,7 @@ static void au1xmmc_cmd_complete(struct 
 
 	host->status = HOST_S_DATA;
 
+	#ifdef MMC_DARE_DMA_IMPLEMENTED
 	if (host->flags & HOST_F_DMA) {
 		u32 channel = DMA_CHANNEL(host);
 
@@ -545,6 +554,7 @@ static void au1xmmc_cmd_complete(struct 
 
 		au1xxx_dbdma_start(channel);
 	}
+	#endif
 }
 
 static void au1xmmc_set_clock(struct au1xmmc_host *host, int rate)
@@ -599,6 +609,7 @@ au1xmmc_prepare_data(struct au1xmmc_host
 
 	au_writel((1 << data->blksz_bits) - 1, HOST_BLKSIZE(host));
 
+	#ifdef MMC_DARE_DMA_IMPLEMENTED
 	if (host->flags & HOST_F_DMA) {
 		int i;
 		u32 channel = DMA_CHANNEL(host);
@@ -616,12 +627,14 @@ au1xmmc_prepare_data(struct au1xmmc_host
 				flags = DDMA_FLAGS_IE;
 
     			if (host->flags & HOST_F_XMIT){
+				ret = 0;
       				ret = au1xxx_dbdma_put_source_flags(channel,
 					(void *) (page_address(sg->page) +
 						  sg->offset),
 					len, flags);
 			}
     			else {
+				ret = 0;
       				ret = au1xxx_dbdma_put_dest_flags(channel,
 					(void *) (page_address(sg->page) +
 						  sg->offset),
@@ -634,7 +647,9 @@ au1xmmc_prepare_data(struct au1xmmc_host
 			datalen -= len;
 		}
 	}
-	else {
+	else
+	#endif
+	{
 		host->pio.index = 0;
 		host->pio.offset = 0;
 		host->pio.len = datalen;
@@ -648,9 +663,11 @@ au1xmmc_prepare_data(struct au1xmmc_host
 
 	return MMC_ERR_NONE;
 
+#ifdef MMC_DARE_DMA_IMPLEMENTED
  dataerr:
 	dma_unmap_sg(mmc_dev(host->mmc),data->sg,data->sg_len,host->dma.dir);
 	return MMC_ERR_TIMEOUT;
+#endif
 }
 
 /* static void au1xmmc_request
@@ -669,8 +686,6 @@ static void au1xmmc_request(struct mmc_h
 	host->mrq = mrq;
 	host->status = HOST_S_CMD;
 
-	bcsr->disk_leds &= ~(1 << 8);
-
 	if (mrq->data) {
 		FLUSH_FIFO(host);
 		ret = au1xmmc_prepare_data(host, mrq->data);
@@ -737,6 +752,7 @@ static void au1xmmc_set_ios(struct mmc_h
 	}
 }
 
+#ifdef MMC_DARE_DMA_IMPLEMENTED
 static void au1xmmc_dma_callback(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct au1xmmc_host *host = (struct au1xmmc_host *) dev_id;
@@ -751,6 +767,7 @@ static void au1xmmc_dma_callback(int irq
 
 	tasklet_schedule(&host->data_task);
 }
+#endif
 
 #define STATUS_TIMEOUT (SD_STATUS_RAT | SD_STATUS_DT)
 #define STATUS_DATA_IN  (SD_STATUS_NE)
@@ -845,14 +862,16 @@ static void au1xmmc_poll_event(unsigned 
 	mod_timer(&host->timer, jiffies + AU1XMMC_DETECT_TIMEOUT);
 }
 
+#ifdef MMC_DARE_DMA_IMPLEMENTED
 static dbdev_tab_t au1xmmc_mem_dbdev =
 {
 	DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 8, 0x00000000, 0, 0
 };
+#endif
 
 static void au1xmmc_init_dma(struct au1xmmc_host *host)
 {
-
+#ifdef MMC_DARE_DMA_IMPLEMENTED
 	u32 rxchan, txchan;
 
 	int txid = au1xmmc_card_table[host->id].tx_devid;
@@ -879,6 +898,7 @@ static void au1xmmc_init_dma(struct au1x
 
 	host->tx_chan = txchan;
 	host->rx_chan = rxchan;
+#endif
 }
 
 struct mmc_host_ops au1xmmc_ops = {
@@ -985,8 +1005,10 @@ static int __devexit au1xmmc_remove(stru
 
 		mmc_remove_host(host->mmc);
 
+		#ifdef MMC_DARE_DMA_IMPLEMENTED
 		au1xxx_dbdma_chan_free(host->tx_chan);
 		au1xxx_dbdma_chan_free(host->rx_chan);
+		#endif
 
 		au_writel(0x0, HOST_ENABLE(host));
 		au_sync();
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
diff --git a/include/asm-mips/mach-au1x00/au1xxx.h b/include/asm-mips/mach-au1x00/au1xxx.h
diff --git a/include/asm-mips/mach-db1x00/db1x00.h b/include/asm-mips/mach-db1x00/db1x00.h
index 7b28b23..5912361 100644
--- a/include/asm-mips/mach-db1x00/db1x00.h
+++ b/include/asm-mips/mach-db1x00/db1x00.h
@@ -177,6 +177,24 @@ #define mmc_power_on(_n_) \
 		} \
 	} while (0)
 
+/*
+ * Remove power from card slot(s).
+ */
+#define mmc_power(_n_, state) \
+	do { \
+		BCSR * const bcsr = (BCSR *)0xAE000000; \
+		unsigned long mmc_pwr, board_specific; \
+		if ((_n_)) { \
+			mmc_pwr = BCSR_BOARD_SD1_PWR; \
+		} else { \
+			mmc_pwr = BCSR_BOARD_SD0_PWR; \
+		} \
+		board_specific = au_readl((unsigned long)(&bcsr->specific)); \
+		board_specific &= ~mmc_pwr; \
+		board_specific |= (state ? mmc_pwr : 0); \
+		au_writel(board_specific, (int)(&bcsr->specific)); \
+		au_sync(); \
+	} while (0)
 
 /* NAND defines */
 /* Timing values as described in databook, * ns value stripped of
diff --git a/include/asm-mips/mach-pb1x00/pb1100.h b/include/asm-mips/mach-pb1x00/pb1100.h

---

From: Manuel Lauss <[email-masked]>
Date: Mon, 20 Nov 2006 14:22:26 +0100

> 512MB and 1GB MMC-card working with the patch I hereby send to

continuously issues CMD2 and CMD3 messages to the card, and
lots of "au1xx(0): DEBUG: PENDING - 03000090" messages.
 
> > Yes, please. I'd like to give it a spin

Thank you. You only removed parts of the Db/Pb board specific
stuff and disabled DMA, correct?

-- 
 ml.

---

From: Freddy Spierenburg <[email-masked]>
Date: Mon, 20 Nov 2006 15:16:07 +0100

Hi Manuel,

On Mon, Nov 20, 2006 at 02:22:26PM +0100, Manuel Lauss wrote:
> > Broke in a different way?
> 

I now too see those PENDING messages, which I failed to notice
more early. Actually I have tried this patch last friday for the
first time and since it worked right away did not notice all
those messages.

> You only removed parts of the Db/Pb board specific stuff and
> disabled DMA, correct?

I did not wrote the patch myself, so I can't tell you without
seriously looking into it myself. As far as I know your statement
should be correct, but only carefull looking into it will provide
the true answer. And that's where I do not have time for right
now. I should not even be writing this email I guess. :)

Good luck!