[U-Boot-Users] drivers MMCplus for at91sam9x
Pierre Savary
pierre.savary at kerlink.fr
Wed Apr 30 16:20:05 CEST 2008
Hi Ken,
Thanks a lot for your patch. I will test it next week. Have you ever tested
your U-Boot with 4GB or 8GB moviNAND?
Thanks in advance
Pierre
-----Message d'origine-----
De : u-boot-users-bounces at lists.sourceforge.net
[mailto:u-boot-users-bounces at lists.sourceforge.net] De la part de
Ken.Fuchs at bench.com
Envoyé : mardi 29 avril 2008 21:46
À : pierre.savary at kerlink.fr
Cc : u-boot-users at lists.sourceforge.net; afleming at freescale.com;
abo at kerlink.fr; drzeus-mmc at drzeus.cx
Objet : Re: [U-Boot-Users] drivers MMCplus for at91sam9x
I posted the following patch under a different subject line:
Re: [U-Boot-Users] [PATCH] Add eSDHC driver
> > --- u-boot_at91sam9260_mmc.patch (AT91 MCI driver) ---
Pierre Savary wrote:
> Thanks for that... but it's my own patch ;)
>
> Pierre
===========================================================
Pierre, I hope you like this patch better. :)
The following MMC v4 patch is for u-boot-1.1.5_atmel_1.2.
To the AT91SAM9261 MCI device driver it adds support for
MMC v4.x chips (MoviNAND in particular).
The u-boot_at91sam9260_mmc.patch, previously send to this
thread 23 April 2008 must be applied to
u-boot-1.1.5_atmel_1.2, prior to applying the patch below.
The patch includes lines "/* Ignore */". These are
simply place holders for code that was not relevant
to the MCI driver or MMC code.
The patch is actually of four individual source files.
Please let me know of any serious problems applying the
patch. It should apply cleanly, but I didn't verify this.
The MCI MMC v4 features contained in this patch work perfectly
on our AT91SAM9261 board, except that I never got MMC 4 bit
bus working (that code is omitted from this patch). Anyone
know why the AT91SAM9261-EK doesn't appear to support 4 bit MMC?
This patch may not work on AT91SAM9261-EK, since we modified
the AT91SAM9261-EK board definitions rather than creating a
new configuration and files for our board.
Sincerely,
Ken Fuchs
u-boot-at91sam9261-mmc-v4.patch
===============================
svn diff -r21 cpu/arm926ejs/at91sam926x/atmel_mci.c
Index: cpu/arm926ejs/at91sam926x/atmel_mci.c
===================================================================
--- cpu/arm926ejs/at91sam926x/atmel_mci.c (revision 21)
+++ cpu/arm926ejs/at91sam926x/atmel_mci.c (working copy)
@@ -1,4 +1,8 @@
/*
+ * (C) Copyright 2007-2008
+ * Benchmark Electronics, Inc.
+ * Added MMC v4.x (MoviNAND) support
+ *
* Copyright (C) 2004-2006 Atmel Corporation
*
* See file CREDITS for list of people who contributed to this
@@ -34,21 +38,43 @@
#include <asm/arch/hardware.h> //klk
#include "atmel_mci.h"
-#undef DEBUG
+
+/* Ignore */
+/* Ignore */
+/* Ignore */
+
+#if 0
+#define DEBUG
+#else /* 0 */
+#undef DEBUG /* kf - was #undef */
+#endif /* 0 */
+
#ifdef DEBUG
#define pr_debug(fmt, args...) printf(fmt, ##args)
#else
#define pr_debug(...) do { } while(0)
#endif
+#undef CFG_MMC_CLK_OD
+#define CFG_MMC_CLK_OD 375000
+
#ifndef CFG_MMC_CLK_OD
#define CFG_MMC_CLK_OD 375000
#endif
+#undef CFG_MMC_CLK_PP
+#define CFG_MMC_CLK_PP 20000000
+
#ifndef CFG_MMC_CLK_PP
#define CFG_MMC_CLK_PP 20000000
#endif
+#undef CFG_MMC_OP_COND
+#define CFG_MMC_OP_COND 0x80ff8000
+/* 0x80ff8080 works with 30+ sec. power
off req */
+/* 0x00800000 works better, but write
forever? */
+/* 0x00100000 works with 30+ sec. power
off req */
+
#ifndef CFG_MMC_OP_COND
#define CFG_MMC_OP_COND 0x00100000
#endif
@@ -74,8 +100,13 @@
bus_hz = AT91C_MASTER_CLOCK;
clkdiv = (bus_hz / hz) / 2 - 1;
+#if 1
+ printf("mmc: setting clock %lu Hz, block size %lu\n",
+ hz, blklen);
+#else /* 1 */
pr_debug("mmc: setting clock %lu Hz, block size %lu\n",
hz, blklen);
+#endif /* 1 */
if (clkdiv & ~255UL) {
clkdiv = 255;
@@ -84,10 +115,17 @@
}
blklen &= 0xfffc;
+
+#if 1 /* AT91SAM9261 does not have RDPROOF and WRPROOF fields. */
mmci_writel(MR, (MMCI_BF(CLKDIV, clkdiv)
+ | MMCI_BF(BLKLEN, blklen)));
+#else /* 1 */
+ mmci_writel(MR, (MMCI_BF(CLKDIV, clkdiv)
| MMCI_BF(BLKLEN, blklen)
| MMCI_BIT(RDPROOF)
| MMCI_BIT(WRPROOF)));
+#endif /* 1 */
+
}
#define RESP_NO_CRC 1
@@ -99,6 +137,7 @@
#define NCR MMCI_BF(MAXLAT, 1)
#define TRCMD_START MMCI_BF(TRCMD, 1)
#define TRDIR_READ MMCI_BF(TRDIR, 1)
+#define TRDIR_WRITE MMCI_BF(TRDIR, 0)
#define TRTYP_BLOCK MMCI_BF(TRTYP, 0)
#define INIT_CMD MMCI_BF(SPCMD, 1)
#define OPEN_DRAIN MMCI_BF(OPDCMD, 1)
@@ -109,6 +148,20 @@
| MMCI_BIT(RINDE) \
| MMCI_BIT(RTOE))
+#if 0
+#define DEBUG
+#else /* 0 */
+#undef DEBUG /* kf - was #undef */
+#endif /* 0 */
+
+#undef pr_debug
+
+#ifdef DEBUG
+#define pr_debug(fmt, args...) printf(fmt, ##args)
+#else
+#define pr_debug(...) do { } while(0)
+#endif
+
static int
mmc_cmd(unsigned long cmd, unsigned long arg,
void *resp, unsigned long flags)
@@ -117,7 +170,9 @@
int i, response_words = 0;
unsigned long error_flags;
u32 status;
-
+#if 1
+ pr_debug("mmc_cmd: entry\n");
+#endif /* 1 */
AT91F_MMC_Hardware_Init();
pr_debug("mmc: CMD%lu 0x%lx (flags 0x%lx)\n",
@@ -161,12 +216,28 @@
return 0;
}
+#if 0
+#define DEBUG
+#else /* 0 */
+#undef DEBUG /* kf - was #undef */
+#endif /* 0 */
+
+#undef pr_debug
+
+#ifdef DEBUG
+#define pr_debug(fmt, args...) printf(fmt, ##args)
+#else
+#define pr_debug(...) do { } while(0)
+#endif
+
static int mmc_acmd(unsigned long cmd, unsigned long arg,
void *resp, unsigned long flags)
{
unsigned long aresp[4];
int ret;
+ pr_debug("mmc_acmd: entry\n");
+
/*
* Seems like the APP_CMD part of an ACMD has 64 cycles max
* latency even though the ACMD part doesn't. This isn't
@@ -184,7 +255,16 @@
return ret;
}
-static unsigned long
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+
+unsigned long
mmc_bread(int dev, unsigned long start, lbaint_t blkcnt,
unsigned long *buffer)
{
@@ -193,7 +273,14 @@
unsigned long card_status, data;
unsigned long wordcount;
u32 status;
+ unsigned long *bufaddr;
+ pr_debug("mmc_bread: entry\n");
+ mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 |
NCR);
+ pr_debug("mmc: bread ret = %d, card status = %08x\n", ret,
card_status);
+
+ bufaddr = buffer;
+
if (blkcnt == 0)
return 0;
@@ -202,10 +289,16 @@
/* Put the device into Transfer state */
ret = mmc_cmd(MMC_CMD_SELECT_CARD, mmc_rca << 16, resp, R1 |
NCR);
+ mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 |
NCR);
+ pr_debug("mmc: bread ret = %d, card status = %08x\n",
+ ret, card_status);
if (ret) goto fail;
/* Set block length */
ret = mmc_cmd(MMC_CMD_SET_BLOCKLEN, mmc_blkdev.blksz, resp, R1 |
NCR);
+ mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 |
NCR);
+ pr_debug("mmc: bread ret = %d, card status = %08x\n",
+ ret, card_status);
if (ret) goto fail;
pr_debug("MCI_DTOR = %08lx\n", mmci_readl(DTOR));
@@ -228,7 +321,6 @@
if (status & MMCI_BIT(RXRDY)) {
data = mmci_readl(RDR);
- /* pr_debug("%x\n", data); */
*buffer++ = data;
wordcount++;
}
@@ -240,12 +332,68 @@
status = mmci_readl(SR);
} while (!(status & MMCI_BIT(BLKE)));
- putc('.');
+ mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16,
+ &card_status, R1 | NCR);
+ pr_debug("mmc: bread ret = %d, card status = %08x\n",
+ ret, card_status);
+
+ if (i % 0x800 == 0x7ff) {
+ putc('.'); /* Display '.', after each MB
xfer'ed */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+ }
+
+#if 0
+ buffer = bufaddr;
+ wordcount = 0;
+ do {
+ if (wordcount % 8 == 0) {
+ pr_debug("\n%06lx:", 4 * wordcount);
+ }
+ pr_debug(" %08lx", *buffer++);
+ wordcount++;
+ } while (4 * wordcount < mmc_blkdev.blksz);
+ pr_debug("\n");
+#endif /* 0 */
+
}
out:
/* Put the device back into Standby state */
mmc_cmd(MMC_CMD_SELECT_CARD, 0, resp, NCR);
+ mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 |
NCR);
+ pr_debug("mmc: bread ret = %d, card status = %08x\n", ret,
card_status);
+ if (i >= 0x7ff) {
+ putc('\n');
+ }
return i;
fail:
@@ -254,8 +402,329 @@
goto out;
}
+unsigned long
+mmc_bwrite(int dev, unsigned long start, lbaint_t blkcnt,
+ unsigned long *buffer)
+{
+ int ret, i = 0;
+ unsigned long resp[4];
+ unsigned long card_status, data;
+ unsigned long wordcount;
+ u32 status;
+ unsigned long *bufaddr;
+
+ pr_debug("mmc_bwrite: entry\n");
+ mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 |
NCR);
+ pr_debug("en mmc: bwrite ret = %d, card status = %08x\n",
+ ret, card_status);
+
+ bufaddr = buffer;
+
+ if (blkcnt == 0)
+ return 0;
+
+ pr_debug("mmc_bwrite: dev %d, start %lx, blkcnt %lx\n",
+ dev, start, blkcnt);
+
+ /* Put the device into Transfer state */
+ ret = mmc_cmd(MMC_CMD_SELECT_CARD, mmc_rca << 16, resp, R1 |
NCR);
+ mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 |
NCR);
+ pr_debug("sc mmc: bwrite ret = %d, card status = %08x\n",
+ ret, card_status);
+ if (ret) goto fail;
+
+ /* Set block length */
+ ret = mmc_cmd(MMC_CMD_SET_BLOCKLEN, mmc_blkdev.blksz, resp, R1 |
NCR);
+ mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 |
NCR);
+ pr_debug("bl mmc: bwrite ret = %d, card status = %08x\n",
+ ret, card_status);
+ if (ret) goto fail;
+
+ pr_debug("MCI_DTOR = %08lx\n", mmci_readl(DTOR));
+
+ for (i = 0; i < blkcnt; i++, start++) {
+ ret = mmc_cmd(MMC_CMD_WRITE_BLOCK,
+ start * mmc_blkdev.blksz, resp,
+ (R1 | NCR | TRCMD_START | TRDIR_WRITE
+ | TRTYP_BLOCK));
+ if (ret) goto fail;
+
+ ret = -EIO;
+ wordcount = 0;
+ do {
+ do {
+ status = mmci_readl(SR);
+ if (status & (ERROR_FLAGS |
MMCI_BIT(UNRE)))
+ goto fail;
+ } while (!(status & MMCI_BIT(TXRDY)));
+
+ if (status & MMCI_BIT(TXRDY)) {
+ data = *buffer++;
+ mmci_writel(TDR, data);
+ wordcount++;
+ }
+ } while(wordcount < (mmc_blkdev.blksz / 4));
+
+ pr_debug("mmc: write %u words, waiting for BLKE\n",
wordcount);
+
+ do {
+ status = mmci_readl(SR);
+ } while (!(status & MMCI_BIT(BLKE)));
+
+ do {
+ mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16,
+ &card_status, R1 | NCR);
+ if ((card_status & 0x00000100) != 0x00000100) {
+#if 0
+ printf("lp mmc: bwrite ret = %d, ",
ret);
+ printf("card status = %08x\n",
card_status);
+#endif /* 0 */
+ } else {
+ pr_debug("lp mmc: bwrite ret = %d, ",
ret);
+ pr_debug("card status = %08x\n",
card_status);
+ }
+ } while ((card_status & 0x00000100) != 0x00000100);
+
+ if (i % 0x800 == 0x7ff) {
+ putc('.'); /* Display '.', after each MB
xfer'ed */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+ }
+
+#if 0
+ ret = mmc_cmd(MMC_CMD_STOP_TRANSMISSION,
+ 0, resp,
+ R1 | NCR);
+ mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16,
+ &card_status, R1 | NCR);
+ pr_debug("st mmc: bwrite ret = %d, card status =
%08x\n",
+ ret, card_status);
+ if (ret) goto fail;
+#endif /* 0 */
+
+ }
+
+out:
+#if 0
+ ret = mmc_cmd(MMC_CMD_STOP_TRANSMISSION,
+ 0, resp,
+ R1 | NCR);
+ mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 |
NCR);
+ pr_debug("st mmc: bwrite ret = %d, card status = %08x\n",
+ ret, card_status);
+ if (ret) goto fail;
+#endif /* 0 */
+
+ /* Put the device back into Standby state */
+ mmc_cmd(MMC_CMD_SELECT_CARD, 0, resp, NCR);
+ mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 |
NCR);
+ pr_debug("dc mmc: bwrite ret = %d, card status = %08x\n",
+ ret, card_status);
+ if (i >= 0x7ff) {
+ putc('\n');
+ }
+ return i;
+
+fail:
+ mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 |
NCR);
+ pr_debug("fa mmc: bwrite ret = %d, card status = %08x\n",
+ ret, card_status);
+ goto out;
+}
+
+ /* Hangs - did not attempt to debug */
+/* MMC Multiple Block Write - mmc_mbwrite() */
+unsigned long
+mmc_mbwrite(int dev, unsigned long start, lbaint_t blkcnt,
+ unsigned long *buffer)
+{
+ int ret, i = 0;
+ unsigned long resp[4];
+ unsigned long card_status, data;
+ unsigned long wordcount;
+ u32 status;
+ unsigned long *bufaddr;
+
+ pr_debug("mmc_bwrite: entry\n");
+ mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 |
NCR);
+ pr_debug("en mmc: mbwrite ret = %d, card status = %08x\n",
+ ret, card_status);
+
+ bufaddr = buffer;
+
+ if (blkcnt == 0)
+ return 0;
+
+ if (blkcnt > 0xffff) { /* Exceeds length supported by MoviNAND.
*/
+ return -1;
+ }
+
+ pr_debug("mmc_mbwrite: dev %d, start %lx, blkcnt %lx\n",
+ dev, start, blkcnt);
+
+ /* Put the device into Transfer state */
+ ret = mmc_cmd(MMC_CMD_SELECT_CARD, mmc_rca << 16, resp, R1 |
NCR);
+ mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 |
NCR);
+ pr_debug("sc mmc: mbwrite ret = %d, card status = %08x\n",
+ ret, card_status);
+ if (ret) goto fail;
+
+ /* Set block length */
+ ret = mmc_cmd(MMC_CMD_SET_BLOCKLEN, mmc_blkdev.blksz, resp, R1 |
NCR);
+ mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 |
NCR);
+ pr_debug("bl mmc: mbwrite ret = %d, card status = %08x\n",
+ ret, card_status);
+ if (ret) goto fail;
+
+ pr_debug("MCI_DTOR = %08lx\n", mmci_readl(DTOR));
+
+ ret = mmc_cmd(MMC_CMD_SET_BLOCK_COUNT,
+ blkcnt, resp,
+ R1 | NCR);
+ mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 |
NCR);
+ pr_debug("bc mmc: mbwrite ret = %d, card status = %08x\n",
+ ret, card_status);
+ if (ret) goto fail;
+
+ ret = mmc_cmd(MMC_CMD_WRITE_MULTIPLE_BLOCK,
+ start * mmc_blkdev.blksz, resp,
+ (R1 | NCR | TRCMD_START | TRDIR_WRITE |
TRTYP_BLOCK));
+ if (ret) goto fail;
+
+ for (i = 0; i < blkcnt; i++, start++) {
+
+ ret = -EIO;
+ wordcount = 0;
+ do {
+ do {
+ status = mmci_readl(SR);
+ if (status & (ERROR_FLAGS |
MMCI_BIT(UNRE)))
+ goto fail;
+ } while (!(status & MMCI_BIT(TXRDY)));
+
+ if (status & MMCI_BIT(TXRDY)) {
+ data = *buffer++;
+ mmci_writel(TDR, data);
+ wordcount++;
+ }
+ } while(wordcount < (mmc_blkdev.blksz / 4));
+
+#if 1
+ pr_debug("mmc: write %u words, waiting for BLKE\n",
wordcount);
+
+ do {
+ status = mmci_readl(SR);
+ } while (!(status & MMCI_BIT(BLKE)));
+#endif /* 0 */
+
+ do {
+ mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16,
+ &card_status, R1 | NCR);
+ if ((card_status & 0x00000100) != 0x00000100) {
+#if 0
+ printf("lp mmc: mbwrite ret = %d, ",
ret);
+ printf("card status = %08x\n",
card_status);
+#endif /* 0 */
+ } else {
+ pr_debug("lp mmc: mbwrite ret = %d, ",
ret);
+ pr_debug("card status = %08x\n",
card_status);
+ }
+ } while ((card_status & 0x00000100) != 0x00000100);
+
+ if (i % 0x800 == 0x7ff) {
+ putc('.'); /* Display '.', after each MB
xfer'ed */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+ }
+ }
+
+out:
+#if 0
+ ret = mmc_cmd(MMC_CMD_STOP_TRANSMISSION,
+ 0, resp,
+ R1 | NCR);
+ mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 |
NCR);
+ pr_debug("st mmc: mbwrite ret = %d, card status = %08x\n",
+ ret, card_status);
+ if (ret) goto fail;
+#endif /* 0 */
+
+ /* Put the device back into Standby state */
+ mmc_cmd(MMC_CMD_SELECT_CARD, 0, resp, NCR);
+ mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 |
NCR);
+ pr_debug("dc mmc: mbwrite ret = %d, card status = %08x\n",
+ ret, card_status);
+ if (i >= 0x7ff) {
+ putc('\n');
+ }
+ return i;
+
+fail:
+ mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 |
NCR);
+ pr_debug("fa mmc: mbwrite failed, card status = %08x\n",
card_status);
+ goto out;
+}
+
static void mmc_parse_cid(struct mmc_cid *cid, unsigned long *resp)
{
+ pr_debug("mmc_parse_cid: entry\n");
+
cid->mid = resp[0] >> 24;
cid->oid = (resp[0] >> 8) & 0xffff;
cid->pnm[0] = resp[0];
@@ -272,6 +741,8 @@
static void sd_parse_cid(struct mmc_cid *cid, unsigned long *resp)
{
+ pr_debug("sd_parse_cid: entry\n");
+
cid->mid = resp[0] >> 24;
cid->oid = (resp[0] >> 8) & 0xffff;
cid->pnm[0] = resp[0];
@@ -288,6 +759,8 @@
static void mmc_dump_cid(const struct mmc_cid *cid)
{
+ pr_debug("mmc_dump_cid: entry\n");
+
printf("Manufacturer ID: %02lX\n", cid->mid);
printf("OEM/Application ID: %04lX\n", cid->oid);
printf("Product name: %s\n", cid->pnm);
@@ -301,6 +774,9 @@
static void mmc_dump_csd(const struct mmc_csd *csd)
{
unsigned long *csd_raw = (unsigned long *)csd;
+
+ pr_debug("mmc_dump_csd: entry\n");
+
pr_debug("CSD data: %08lx %08lx %08lx %08lx\n",
csd_raw[0], csd_raw[1], csd_raw[2], csd_raw[3]);
pr_debug("CSD structure version: 1.%u\n", csd->csd_structure);
@@ -337,6 +813,8 @@
{
int ret;
+ pr_debug("mmc_idle_cards: entry\n");
+
/* Reset and initialize all cards */
ret = mmc_cmd(MMC_CMD_GO_IDLE_STATE, 0, NULL, 0);
@@ -352,6 +830,8 @@
unsigned long resp[4];
int i, ret = 0;
+ pr_debug("sd_init_card: entry\n");
+
mmc_idle_cards();
for (i = 0; i < 1000; i++) {
ret = mmc_acmd(MMC_ACMD_SD_SEND_OP_COND,
CFG_MMC_OP_COND,
@@ -387,10 +867,40 @@
{
unsigned long resp[4];
int i, ret = 0;
+ u32 status;
+ pr_debug("mmc_init_card: entry\n");
+
mmc_idle_cards();
+ /* MoviNAND initialization */
for (i = 0; i < 1000; i++) {
+ mmci_writel(ARGR, 0xFFFFFFFF);
+ mmci_writel(CMDR, 0x0018113F);
+ do {
+ status = mmci_readl(SR);
+ } while (!(status & MMCI_BIT(CMDRDY)));
+ }
+ /* Getting the OCR value seems to prevent marginal chips from
*/
+ /* working at all, whereas they would work fine after waiting
*/
+ /* a full minute or more with the power off prior to booting.
*/
+ /* Our marginal chips have date codes 0716 and 0728.
*/
+#if 0
+ for (i = 0; i < 1000; i++) {
+ /* Request OCR value to determine chip's supported volt. */
+ ret = mmc_cmd(MMC_CMD_SEND_OP_COND, 0, resp,
+ R3 | NID | OPEN_DRAIN);
+ if (ret || (resp[0] & 0x80000000))
+ {
+ break;
+ }
+ ret = -ETIMEDOUT;
+ }
+ if (ret) {
+ return ret;
+ }
+#endif /* 0 */
+ for (i = 0; i < 1000; i++) {
ret = mmc_cmd(MMC_CMD_SEND_OP_COND, CFG_MMC_OP_COND,
resp,
R3 | NID | OPEN_DRAIN);
if (ret || (resp[0] & 0x80000000))
@@ -399,13 +909,35 @@
}
ret = -ETIMEDOUT;
}
+ pr_debug("Step 4: ret = 0x%lx\n", ret);
+ pr_debug("MMC_CMD_SEND_OP_COND = 0x%lx\n",
MMC_CMD_SEND_OP_COND);
+ pr_debug("CFG_MMC_OP_COND = 0x%lx\n", CFG_MMC_OP_COND);
+ pr_debug("resp[0] = 0x%lx\n", resp[0]);
+ pr_debug("resp[1] = 0x%lx\n", resp[1]);
+ pr_debug("resp[2] = 0x%lx\n", resp[2]);
+ pr_debug("resp[3] = 0x%lx\n", resp[3]);
+ pr_debug("R3 = 0x%lx\n", R3);
+ pr_debug("NID = 0x%lx\n", NID);
+ pr_debug("OPEN_DRAIN = 0x%lx\n", OPEN_DRAIN);
+
pr_debug("4\n");
pr_debug("ret : %i\n",ret);
+
+ pr_debug("MCI_MR = 0x%08lx\n", mmci_readl(MR));
+ pr_debug("MCI_DTOR = 0x%08lx\n", mmci_readl(DTOR));
+ pr_debug("MCI_SDCR = 0x%08lx\n", mmci_readl(SDCR));
+ pr_debug("MCI_ARGR = 0x%08lx\n", mmci_readl(ARGR));
+ /* RSPR */
+ /* RDR */
+ pr_debug("MCI_SR = 0x%08lx\n", mmci_readl(SR));
+ pr_debug("MCI_IMR = 0x%08lx\n", mmci_readl(IMR));
+
if (ret)
return ret;
pr_debug("5\n");
/* Get CID of all cards. FIXME: Support more than one card */
ret = mmc_cmd(MMC_CMD_ALL_SEND_CID, 0, resp, R2 | NID |
OPEN_DRAIN);
+ pr_debug("ALL_SEND_CID ret: 0x%08lx\n", ret);
if (ret)
return ret;
mmc_parse_cid(cid, resp);
@@ -415,6 +947,7 @@
/* Set Relative Address of the card that responded */
ret = mmc_cmd(MMC_CMD_SET_RELATIVE_ADDR, mmc_rca << 16, resp,
R1 | NCR | OPEN_DRAIN);
+ pr_debug("SET_RELATIVE_ADDR ret: 0x%08lx\n", ret);
return ret;
}
@@ -471,23 +1004,42 @@
dtocyc << shift, dtor);
}
+#define DEFAULT_SECTOR_SIZE 512
+
int mmc_init(int verbose)
{
struct mmc_cid cid;
struct mmc_csd csd;
unsigned int max_blksz;
int ret,aux;
+ unsigned char buffer[DEFAULT_SECTOR_SIZE];
+ pr_debug("mmc_init: entry\n");
+ pr_debug("mmc_init: verbose = 0x%08lx\n", verbose);
+
AT91F_MMC_Hardware_Init();
pr_debug("0\n");
/* Initialize controller */
mmci_writel(CR, MMCI_BIT(SWRST));
mmci_writel(CR, MMCI_BIT(MCIEN));
+
+ pr_debug("MCI_MR = 0x%08lx\n", mmci_readl(MR));
+ pr_debug("MCI_DTOR = 0x%08lx\n", mmci_readl(DTOR));
+ pr_debug("MCI_SDCR = 0x%08lx\n", mmci_readl(SDCR));
+ pr_debug("MCI_ARGR = 0x%08lx\n", mmci_readl(ARGR));
+ /* RSPR */
+ /* RDR */
+ pr_debug("MCI_SR = 0x%08lx\n", mmci_readl(SR));
+ pr_debug("MCI_IMR = 0x%08lx\n", mmci_readl(IMR));
+
mmci_writel(DTOR, 0x5f);
mmci_writel(IDR, ~0UL);
mmci_writel(SDCR, 0x1);
mci_set_mode(CFG_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
+#if 0
+ mmci_writel(MR, 0x02009B4A);
+#endif /* 0 */
/* //mmci_writel(CR, MMCI_BIT(SWRST));
mmci_writel(CR, 0x00000001);
mmci_writel(DTOR, 0x0000007F);
@@ -502,6 +1054,7 @@
ret = sd_init_card(&cid, verbose);
if (ret) {
+ pr_debug("Not SDCard, try MMC\n");
mmc_rca = MMC_DEFAULT_RCA;
ret = mmc_init_card(&cid, verbose);
}
@@ -545,6 +1098,20 @@
mci_set_mode(CFG_MMC_CLK_PP, mmc_blkdev.blksz);
#if 0
+ mmc_bread(mmc_blkdev.dev, 1024, 1, (ulong *)buffer);
+ buffer[0] = 0x00; buffer[1] = 0x11;
+ buffer[2] = 0x22; buffer[3] = 0x33;
+ buffer[4] = 0x44; buffer[5] = 0x55;
+ buffer[6] = 0x66; buffer[7] = 0x77;
+ buffer[504] = 0x88; buffer[505] = 0x99;
+ buffer[506] = 0xaa; buffer[507] = 0xbb;
+ buffer[508] = 0xcc; buffer[509] = 0xdd;
+ buffer[510] = 0xee; buffer[511] = 0xff;
+ mmc_bwrite(mmc_blkdev.dev, 1024, 1, (ulong *)buffer);
+ mmc_bread(mmc_blkdev.dev, 1024, 1, (ulong *)buffer);
+#endif /* 0 */
+
+#if 0
if (fat_register_device(&mmc_blkdev, 1))
pr_debug("Could not register MMC fat device\n");
#else
@@ -556,16 +1123,22 @@
int mmc_read(ulong src, uchar *dst, int size)
{
+ pr_debug("mmc_read: entry\n");
+
return -ENOSYS;
}
int mmc_write(uchar *src, ulong dst, int size)
{
+ pr_debug("mmc_write: entry\n");
+
return -ENOSYS;
}
int mmc2info(ulong addr)
{
+ pr_debug("mmc2info: entry\n");
+
return 0;
}
svn diff -r21 include/asm-arm/arch-at91sam926x/mmc.h
Index: include/asm-arm/arch-at91sam926x/mmc.h
===================================================================
--- include/asm-arm/arch-at91sam926x/mmc.h (revision 0)
+++ include/asm-arm/arch-at91sam926x/mmc.h (revision 50)
@@ -0,0 +1,103 @@
+/*
+ * (C) Copyright 2007
+ * Benchmark Electronics, Inc.
+ * Added MMC v4.x (MoviNAND) support
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef __ASM_AT91SAM926X_MMC_H
+#define __ASM_AT91SAM926X_MMC_H
+
+struct mmc_cid {
+ unsigned long psn;
+ unsigned short oid;
+ unsigned char mid;
+ unsigned char prv;
+ unsigned char mdt;
+ char pnm[7];
+};
+
+struct mmc_csd
+{
+ u8 csd_structure:2,
+ spec_vers:4,
+ rsvd1:2;
+ u8 taac;
+ u8 nsac;
+ u8 tran_speed;
+ u16 ccc:12,
+ read_bl_len:4;
+ u64 read_bl_partial:1,
+ write_blk_misalign:1,
+ read_blk_misalign:1,
+ dsr_imp:1,
+ rsvd2:2,
+ c_size:12,
+ vdd_r_curr_min:3,
+ vdd_r_curr_max:3,
+ vdd_w_curr_min:3,
+ vdd_w_curr_max:3,
+ c_size_mult:3,
+ sector_size:5,
+ erase_grp_size:5,
+ wp_grp_size:5,
+ wp_grp_enable:1,
+ default_ecc:2,
+ r2w_factor:3,
+ write_bl_len:4,
+ write_bl_partial:1,
+ rsvd3:5;
+ u8 file_format_grp:1,
+ copy:1,
+ perm_write_protect:1,
+ tmp_write_protect:1,
+ file_format:2,
+ ecc:2;
+ u8 crc:7;
+ u8 one:1;
+};
+
+/* MMC Command numbers */
+#define MMC_CMD_GO_IDLE_STATE 0
+#define MMC_CMD_SEND_OP_COND 1
+#define MMC_CMD_ALL_SEND_CID 2
+#define MMC_CMD_SET_RELATIVE_ADDR 3
+#define MMC_CMD_SD_SEND_RELATIVE_ADDR 3
+#define MMC_CMD_SET_DSR 4
+#define MMC_CMD_SELECT_CARD 7
+#define MMC_CMD_SEND_CSD 9
+#define MMC_CMD_SEND_CID 10
+#define MMC_CMD_STOP_TRANSMISSION 12
+#define MMC_CMD_SEND_STATUS 13
+#define MMC_CMD_SET_BLOCKLEN 16
+#define MMC_CMD_READ_SINGLE_BLOCK 17
+#define MMC_CMD_READ_MULTIPLE_BLOCK 18
+#define MMC_CMD_SET_BLOCK_COUNT 23
+#define MMC_CMD_WRITE_BLOCK 24
+#define MMC_CMD_WRITE_MULTIPLE_BLOCK 25
+#define MMC_CMD_APP_CMD 55
+
+#define MMC_ACMD_SD_SEND_OP_COND 41
+
+#define R1_ILLEGAL_COMMAND (1 << 22)
+#define R1_APP_CMD (1 << 5)
+
+#endif /* __ASM_AT91SAM926X_MMC_H */
svn diff -r21 include/configs/at91sam9261ek.h
Index: include/configs/at91sam9261ek.h
===================================================================
--- include/configs/at91sam9261ek.h (revision 21)
+++ include/configs/at91sam9261ek.h (working copy)
@@ -1,4 +1,8 @@
/*
+ * (C) Copyright 2007-2008
+ * Benchmark Electronics, Inc.
+ * Added MMC v4.x (MoviNAND) support
+ *
* (C) Copyright 2005
* M. Amine SAYA ATMEL Rousset, France.
*
@@ -95,18 +99,24 @@
/* SPI */
#define CONFIG_SPI
+/* kf - define hush (from busy box) command line interface & options */
+#define CFG_HUSH_PARSER
+#define CFG_PROMPT_HUSH_PS2 "> "
+#define CFG_AUTO_COMPLETE
+#define CONFIG_CMDLINE_EDITING
+
#define CONFIG_COMMANDS \
((CONFIG_CMD_DFL | \
CFG_CMD_NET | \
CFG_CMD_ENV | \
CFG_CMD_USB | \
CFG_CMD_FLASH | \
- CFG_CMD_NAND | \
+ CFG_CMD_MMC | \
+ CFG_CMD_EXT2 | \
+ CFG_CMD_FAT | \
CFG_CMD_AUTOSCRIPT | \
- CFG_CMD_FAT | \
CFG_CMD_NFS | \
CFG_CMD_SPI | \
- CFG_CMD_U | \
CFG_CMD_IMI | \
CFG_CMD_PING ) & \
~(CFG_CMD_BDI | \
@@ -296,8 +306,12 @@
#define CFG_FLASH_ERASE_TOUT (2*CFG_HZ) /* Timeout for Flash
Erase */
#define CFG_FLASH_WRITE_TOUT (2*CFG_HZ) /* Timeout for Flash
Write */
+#undef CFG_ENV_IS_IN_FLASH
#define CFG_ENV_IS_IN_DATAFLASH 1
-#undef CFG_ENV_IS_IN_FLASH
+#if 0
+#undef CFG_ENV_IS_IN_NAND
+#endif /* 0 - kf */
+#undef CFG_ENV_IS_NOWHERE
#ifdef CFG_ENV_IS_IN_DATAFLASH
#define CFG_ENV_OFFSET 0x4000
@@ -305,6 +319,10 @@
#define CFG_ENV_SIZE 0x4000 /* 0x8000 */
#endif
+#ifdef CFG_ENV_IS_NOWHERE
+#define CFG_ENV_SIZE 0x4000
+#endif
+
#ifdef CFG_ENV_IS_IN_FLASH
#ifdef CONFIG_BOOTBINFUNC
#define CFG_ENV_ADDR (PHYS_FLASH_1 + 0x60000) /*
after u-boot.bin */
@@ -316,6 +334,9 @@
#endif
/* Add LCD stuff */
+/* Ignore */
+/* Ignore */
+
#if 0 /* No LCD */
#define CONFIG_LCD
/* #undef CONFIG_LCD_LOGO */
@@ -333,8 +354,21 @@
#define CONFIG_DOS_PARTITION 1
#define LITTLEENDIAN 1
-#define CFG_LOAD_ADDR 0x23f00000 /* default load address */
+/* Add FAT filesystem configuration, other than CFG_CMD_FAT */
+#define CONFIG_SUPPORT_VFAT
+/* MMC */
+#define CONFIG_MMC 1
+#define MMCI_BASE 0xFFFA8000 /* (void *)AT91C_BASE_MCI */
+/* MMC - kf - slow down speed for debug from 20000000 Hz down to ...
*/
+/* However, tweaking this value here causes all code to be compiled,
*/
+/* so we shall change the value only where needed - in atmel_mci.c.
*/
+#define CFG_MMC_CLK_PP 20000000
+
+#define CFG_LOAD_ADDR 0x23f00000 /* default load address */
+
+#define CFG_BOOTM_LEN 0x02100000 /* 33MB uncompressed max.
*/
+
#ifdef CONFIG_BOOTBINFUNC
#define CFG_BOOT_SIZE 0x00 /* 0 KBytes */
#define CFG_U_BOOT_BASE PHYS_FLASH_1
svn diff -r21 board/at91sam9261ek/at91sam9261ek.c
Index: board/at91sam9261ek/at91sam9261ek.c
===================================================================
--- board/at91sam9261ek/at91sam9261ek.c (revision 21)
+++ board/at91sam9261ek/at91sam9261ek.c (working copy)
@@ -1,4 +1,8 @@
/*
+ * (C) Copyright 2007-2008
+ * Benchmark Electronics, Inc.
+ * Added specific AT91SAM9261 board support
+ *
* (C) Copyright 2005
* M. Amine SAYA ATMEL Rousset, France.
* Added AT91SAM9261EK support.
@@ -28,12 +32,19 @@
#include <common.h>
#include <asm/arch/hardware.h>
+#include <asm/arch-at91sam926x/at91sam9261.h>
#include <net.h>
extern void AT91F_Spi1Init (void);
extern void gpio_init(void);
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+
/*
------------------------------------------------------------------------
- */
/*
* Miscelaneous platform dependent initialisations
@@ -107,7 +118,8 @@
*AT91C_PMC_PCER |= 1 << AT91C_ID_US0; /* enable clock */
#endif
-#ifdef CONFIG_USART1
+#if 1
+ /* #ifdef CONFIG_USART1 */
*AT91C_PIOB_PDR = AT91C_PC12_TXD1 | AT91C_PC13_RXD1;
*AT91C_PMC_PCER |= 1 << AT91C_ID_US1; /* enable clock */
#endif
@@ -118,6 +130,41 @@
#endif
}
+#ifdef CONFIG_MMC
+#if (CONFIG_COMMANDS & CFG_CMD_MMC)
+int AT91F_MMC_Hardware_Init(void)
+{
+#if 0
+ printf("AT91F_MMC_Hardware_Init: entry\n");
+#endif /* 0 */
+
+ AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA,
+ 0, /* <- Peripheral A */
+ (AT91C_PA0_MCDA0 | /* MMC NAND MCDA0 */
+ AT91C_PA1_MCCDA | /* MMC NAND MCCDA */
+ AT91C_PA2_MCCK | /* MMC NAND MCCK */
+ AT91C_PA4_MCDA1 | /* MMC NAND MCDA1 */
+ AT91C_PA5_MCDA2 | /* MMC NAND MCDA2 */
+ AT91C_PA6_MCDA3 | /* MMC NAND MCDA3 */
+ 0)); /* <- Peripheral B */
+
+#if 1
+ /* Pull up disable register */
+ AT91C_BASE_PIOA->PIO_PPUDR |=
+ AT91C_PA0_MCDA0 | /* MMC NAND MCDA0 */
+ AT91C_PA1_MCCDA | /* MMC NAND MCCDA */
+ AT91C_PA2_MCCK | /* MMC NAND MCCK */
+ AT91C_PA4_MCDA1 | /* MMC NAND MCDA1 */
+ AT91C_PA5_MCDA2 | /* MMC NAND MCDA2 */
+ AT91C_PA6_MCDA3; /* MMC NAND MCDA3 */
+#endif /* 0 */
+
+ AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_MCI);
+}
+#endif /* CONFIG_COMMANDS & CFG_CMD_MMC */
+#endif /* CONFIG_MMC */
+
+
int dram_init (void)
{
DECLARE_GLOBAL_DATA_PTR;
@@ -148,5 +195,35 @@
gpio_init();
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+/* Ignore */
+
return 0;
}
-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javao
ne
_______________________________________________
U-Boot-Users mailing list
U-Boot-Users at lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/u-boot-users
More information about the U-Boot
mailing list