From 0353c08d3869b1507e6eba4423c10dd58cfc6d1c Mon Sep 17 00:00:00 2001 From: Lluis Batlle Date: Sun, 27 Jan 2013 15:27:54 +0100 Subject: [PATCH] uboot: updating the default uboot to 2012.07 This is what I use in the sheevplug, with the provided patches. The old sheevaplug uboot doesn't understand ubifs. --- pkgs/misc/uboot/default.nix | 15 +- pkgs/misc/uboot/sheevaplug-config.patch | 57 ++ pkgs/misc/uboot/sheevaplug-sdio.patch | 1091 +++++++++++++++++++++++ 3 files changed, 1160 insertions(+), 3 deletions(-) create mode 100644 pkgs/misc/uboot/sheevaplug-config.patch create mode 100644 pkgs/misc/uboot/sheevaplug-sdio.patch diff --git a/pkgs/misc/uboot/default.nix b/pkgs/misc/uboot/default.nix index 7525c28e740e..629537212bd4 100644 --- a/pkgs/misc/uboot/default.nix +++ b/pkgs/misc/uboot/default.nix @@ -20,11 +20,11 @@ let in stdenv.mkDerivation { - name = "uboot-2009.11"; + name = "uboot-2012.07"; src = fetchurl { - url = "ftp://ftp.denx.de/pub/u-boot/u-boot-2009.11.tar.bz2"; - sha256 = "1rld7q3ww89si84g80hqskd1z995lni5r5xc4d4322n99wqiarh6"; + url = "ftp://ftp.denx.de/pub/u-boot/u-boot-2012.07.tar.bz2"; + sha256 = "15nli6h9a127ldizsck3g4ysy5j4m910wawspgpadz4vjyk213p0"; }; buildNativeInputs = [ unzip ]; @@ -40,6 +40,15 @@ stdenv.mkDerivation { cp tools/{envcrc,mkimage} $out/bin ''; + # They have 'errno.h' included by a "-idirafter". As the gcc + # wrappers add the glibc include as "-idirafter", the only way + # we can make the glibc take priority is to -include errno.h. + postPatch = if stdenv ? glibc && stdenv.glibc != null then '' + sed -i 's,$(HOSTCPPFLAGS),-include ${stdenv.glibc}/include/errno.h $(HOSTCPPFLAGS),' config.mk + '' else ""; + + patches = [ ./sheevaplug-sdio.patch ./sheevaplug-config.patch ]; + configurePhase = assert platform ? uboot && platform.uboot != null; assert (platform ? ubootConfig); diff --git a/pkgs/misc/uboot/sheevaplug-config.patch b/pkgs/misc/uboot/sheevaplug-config.patch new file mode 100644 index 000000000000..487756217bfb --- /dev/null +++ b/pkgs/misc/uboot/sheevaplug-config.patch @@ -0,0 +1,57 @@ +diff --git a/include/configs/sheevaplug.h b/include/configs/sheevaplug.h +index 7c8497c..b0da1e5 100644 +--- a/include/configs/sheevaplug.h ++++ b/include/configs/sheevaplug.h +@@ -50,7 +50,6 @@ + #define CONFIG_CMD_MII + #define CONFIG_CMD_MMC + #define CONFIG_CMD_NAND +-#define CONFIG_JFFS2_NAND + #define CONFIG_CMD_PING + #define CONFIG_CMD_USB + /* +@@ -73,25 +72,36 @@ + * it has to be rounded to sector size + */ + #define CONFIG_ENV_SIZE 0x20000 /* 128k */ +-#define CONFIG_ENV_ADDR 0xa0000 +-#define CONFIG_ENV_OFFSET 0xa0000 /* env starts here */ ++#define CONFIG_ENV_ADDR 0x60000 ++#define CONFIG_ENV_OFFSET 0x60000 /* env starts here */ + + /* + * Default environment variables + */ +-#define CONFIG_BOOTCOMMAND "${x_bootcmd_kernel}; " \ ++#define CONFIG_BOOTCOMMAND "${x_bootcmd_ubi0}; " \ ++ "${x_bootcmd_ubi1}; " \ ++ "${x_bootcmd_ubi2}; " \ ++ "${x_bootcmd_ubi3}; " \ + "setenv bootargs ${x_bootargs} ${x_bootargs_root}; " \ +- "${x_bootcmd_usb}; bootm 0x6400000;" ++ "${x_bootcmd_usb}; bootm 0x200000 0x1100000;" + + #define CONFIG_MTDPARTS "orion_nand:512k(uboot)," \ +- "0x1ff00000@512k(rootfs) rw\0" ++ "0x1ff00000@512k(rootfs)\0" ++#define CONFIG_MTDPARTSK "orion_nand:512k(uboot)," \ ++ "0x1ff00000@512k(rootfs)rw\0" + + #define CONFIG_EXTRA_ENV_SETTINGS "x_bootargs=console" \ +- "=ttyS0,115200 mtdparts="CONFIG_MTDPARTS \ ++ "=ttyS0,115200 mtdparts="CONFIG_MTDPARTSK \ ++ "mtdparts=mtdparts="CONFIG_MTDPARTS \ + "mtdids=nand0=orion_nand\0" \ +- "x_bootcmd_kernel=nand read 0x6400000 0x100000 0x300000\0" \ ++ "ipaddr=192.168.1.4\0" \ ++ "x_bootcmd_ubi0=ubi part nand0,1\0" \ ++ "x_bootcmd_ubi1=ubifsmount rootfs\0" \ ++ "x_bootcmd_ubi2=ubifsload 0x200000 /nixos-kernel\0" \ ++ "x_bootcmd_ubi3=ubifsload 0x1100000 /nixos-initrd\0" \ + "x_bootcmd_usb=usb start\0" \ +- "x_bootargs_root=root=/dev/mtdblock3 rw rootfstype=jffs2\0" ++ "x_bootargs_root=ubi.mtd=rootfs root=ubi0:rootfs rw rootfstype=ubifs " \ ++ "init=/boot/nixos-init systemConfig=/boot/default/system\0" + + /* + * Ethernet Driver configuration diff --git a/pkgs/misc/uboot/sheevaplug-sdio.patch b/pkgs/misc/uboot/sheevaplug-sdio.patch new file mode 100644 index 000000000000..3a4ea2933a34 --- /dev/null +++ b/pkgs/misc/uboot/sheevaplug-sdio.patch @@ -0,0 +1,1091 @@ +diff --git a/arch/arm/include/asm/arch-kirkwood/config.h b/arch/arm/include/asm/arch-kirkwood/config.h +index a9499b7..1294d7f 100644 +--- a/arch/arm/include/asm/arch-kirkwood/config.h ++++ b/arch/arm/include/asm/arch-kirkwood/config.h +@@ -66,6 +66,7 @@ + #define MV_SATA_BASE KW_SATA_BASE + #define MV_SATA_PORT0_OFFSET KW_SATA_PORT0_OFFSET + #define MV_SATA_PORT1_OFFSET KW_SATA_PORT1_OFFSET ++#define MV_SDIO_BASE KW_SDIO_BASE + + /* + * NAND configuration +@@ -107,6 +108,14 @@ + #endif /* CONFIG_CMD_NET */ + + /* ++ * SDIO/MMC Card Configuration ++ */ ++#ifdef CONFIG_CMD_MMC ++#define CONFIG_MMC ++#define CONFIG_MV_SDIO ++#endif /* CONFIG_CMD_MMC */ ++ ++/* + * USB/EHCI + */ + #ifdef CONFIG_CMD_USB +diff --git a/arch/arm/include/asm/arch-kirkwood/kirkwood.h b/arch/arm/include/asm/arch-kirkwood/kirkwood.h +index 47771d5..343214b 100644 +--- a/arch/arm/include/asm/arch-kirkwood/kirkwood.h ++++ b/arch/arm/include/asm/arch-kirkwood/kirkwood.h +@@ -55,6 +55,7 @@ + #define KW_EGIGA0_BASE (KW_REGISTER(0x72000)) + #define KW_EGIGA1_BASE (KW_REGISTER(0x76000)) + #define KW_SATA_BASE (KW_REGISTER(0x80000)) ++#define KW_SDIO_BASE (KW_REGISTER(0x90000)) + + /* Kirkwood Sata controller has two ports */ + #define KW_SATA_PORT0_OFFSET 0x2000 +diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile +index c567737..081d5f4 100644 +--- a/drivers/mmc/Makefile ++++ b/drivers/mmc/Makefile +@@ -34,6 +34,7 @@ COBJS-$(CONFIG_GENERIC_ATMEL_MCI) += gen_atmel_mci.o + COBJS-$(CONFIG_MMC_SPI) += mmc_spi.o + COBJS-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o + COBJS-$(CONFIG_MV_SDHCI) += mv_sdhci.o ++COBJS-$(CONFIG_MV_SDIO) += mv_sdio.o + COBJS-$(CONFIG_MXC_MMC) += mxcmmc.o + COBJS-$(CONFIG_MXS_MMC) += mxsmmc.o + COBJS-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o +diff --git a/drivers/mmc/mv_sdio.c b/drivers/mmc/mv_sdio.c +new file mode 100644 +index 0000000..35969d3 +--- /dev/null ++++ b/drivers/mmc/mv_sdio.c +@@ -0,0 +1,675 @@ ++/* ++ * (C) Copyright 2009 ++ * Marvell Semiconductor ++ * Written-by: Gérald Kerma ++ * ++ * (C) Copyright 2003 ++ * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net ++ * ++ * 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., 51 Franklin Street, Fifth Floor, Boston, ++ * MA 02110-1301 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef CONFIG_KIRKWOOD ++#include ++#endif ++#include "mv_sdio.h" ++ ++#ifdef CONFIG_MMC ++ ++#define DRIVER_NAME "mv-sdio" ++ ++#ifdef DEBUG ++#define pr_debug(fmt, args...) printf(fmt, ##args) ++#else ++#define pr_debug(...) do { } while(0) ++#endif ++ ++//static mv_sdio_t *mvsd = (mv_sdio_t *)mmc->priv; ++static mv_sdio_t *mvsd = (mv_sdio_t *)MV_SDIO_BASE; ++ ++static int is_sdhc; ++extern int fat_register_device(block_dev_desc_t *dev_desc, int part_no); ++static block_dev_desc_t mmc_dev; ++block_dev_desc_t * mmc_get_dev(int dev) ++{ ++ return ((block_dev_desc_t *)&mmc_dev); ++} ++ ++/* ++ * FIXME needs to read cid and csd info to determine block size ++ * and other parameters ++ */ ++static uchar mmc_buf[MMC_BLOCK_SIZE]; ++static mv_mmc_csd_t mv_mmc_csd; ++static int mmc_ready = 0; ++ ++/* MMC_DEFAULT_RCA should probably be just 1, but this may break other code ++ that expects it to be shifted. */ ++static u_int16_t rca = 0; ++ ++/* used for debug */ ++static u_int32_t mv_mmc_size(const struct mv_mmc_csd *csd) ++{ ++ u_int32_t block_len, mult, blocknr; ++ ++ block_len = csd->read_bl_len << 12; ++ mult = csd->c_size_mult1 << 8; ++ blocknr = (csd->c_size+1) * mult; ++ ++ return blocknr * block_len; ++} ++ ++static int isprint (unsigned char ch) ++{ ++ if (ch >= 32 && ch < 127) ++ return (1); ++ ++ return (0); ++} ++ ++static int toprint(char *dst, char c) ++{ ++ if (isprint(c)) { ++ *dst = c; ++ return 1; ++ } ++ ++ return sprintf(dst,"\\x%02x", c); ++ ++} ++ ++static void print_mmc_cid(mv_mmc_cid_t *cid) ++{ ++ printf("MMC found. Card desciption is:\n"); ++ printf("Manufacturer ID = %02x%02x%02x\n", ++ cid->id[0], cid->id[1], cid->id[2]); ++ printf("HW/FW Revision = %x %x\n",cid->hwrev, cid->fwrev); ++ cid->hwrev = cid->fwrev = 0; /* null terminate string */ ++ printf("Product Name = %s\n",cid->name); ++ printf("Serial Number = %02x%02x%02x\n", ++ cid->sn[0], cid->sn[1], cid->sn[2]); ++ printf("Month = %d\n",cid->month); ++ printf("Year = %d\n",1997 + cid->year); ++} ++ ++static void print_sd_cid(mv_sd_cid_t *cid) ++{ ++ int len; ++ char tbuf[64]; ++ ++ printf("SD%s found. Card desciption is:\n", is_sdhc?"HC":""); ++ ++ len = 0; ++ len += toprint(&tbuf[len], cid->oid_0); ++ len += toprint(&tbuf[len], cid->oid_1); ++ tbuf[len] = 0; ++ ++ printf("Manufacturer: 0x%02x, OEM \"%s\"\n", ++ cid->mid, tbuf); ++ ++ len = 0; ++ len += toprint(&tbuf[len], cid->pnm_0); ++ len += toprint(&tbuf[len], cid->pnm_1); ++ len += toprint(&tbuf[len], cid->pnm_2); ++ len += toprint(&tbuf[len], cid->pnm_3); ++ len += toprint(&tbuf[len], cid->pnm_4); ++ tbuf[len] = 0; ++ ++ printf("Product name: \"%s\", revision %d.%d\n", ++ tbuf, ++ cid->prv >> 4, cid->prv & 15); ++ ++ printf("Serial number: %u\n", ++ cid->psn_0 << 24 | cid->psn_1 << 16 | cid->psn_2 << 8 | ++ cid->psn_3); ++ printf("Manufacturing date: %d/%d\n", ++ cid->mdt_1 & 15, ++ 2000+((cid->mdt_0 & 15) << 4)+((cid->mdt_1 & 0xf0) >> 4)); ++ ++ printf("CRC: 0x%02x, b0 = %d\n", ++ cid->crc >> 1, cid->crc & 1); ++} ++ ++static void mvsdio_set_clock(unsigned int clock) ++{ ++ unsigned int m; ++ ++ m = MVSDMMC_BASE_FAST_CLOCK/(2*clock) - 1; ++ ++ pr_debug("mvsdio_set_clock: dividor = 0x%x clock=%d\n", ++ m, clock); ++ ++ ++ writew(m & 0x7ff, &mvsd->CLK_DIV); ++ ++ if (isprint(1)) ++ udelay(10*1000); ++} ++ ++/****************************************************/ ++static ulong * mv_mmc_cmd(ulong cmd, ulong arg, ushort xfermode, ushort resptype, ushort waittype) ++/****************************************************/ ++{ ++ static ulong resp[4]; ++ ushort done ; ++ int err = 0 ; ++ ulong curr, start, diff, hz; ++ ushort response[8]; ++ ++ pr_debug("mv_mmc_cmd %x, arg: %x,xfer: %x,resp: %x, wait : %x\n" ++ , (unsigned int)cmd, (unsigned int)arg, xfermode, resptype, waittype); ++ ++ ++ /* clear status */ ++ writew(0xffff, &mvsd->NOR_INTR_STATUS); ++ writew(0xffff, &mvsd->ERR_INTR_STATUS); ++ ++ start = get_timer(0); ++ hz = CONFIG_SYS_HZ; ++ ++ while((readw(&mvsd->PRESENT_STATE0) & CARD_BUSY)) { ++ curr = get_timer(0); ++ diff = (long) curr - (long) start; ++ if (diff > (3*hz)) ++ { ++ /* 3 seconds timeout, card busy, can't sent cmd */ ++ printf("card too busy \n"); ++ return 0; ++ } ++ } ++ ++ writew((ushort)(arg&0xffff), &mvsd->ARG_LOW); ++ writew((ushort)(arg>>16), &mvsd->ARG_HI); ++ writew(xfermode, &mvsd->XFER_MODE); ++ if( (cmd == MMC_CMD_READ_BLOCK) || (cmd == 25) ) ++ { ++ writew(((cmd << 8) | resptype | 0x3c ) , &mvsd->CMD); ++ pr_debug("cmd reg : %x\n", readw(&mvsd->CMD)) ; ++ ++ } ++ else ++ { ++ writew(((cmd << 8) | resptype ), &mvsd->CMD); ++ } ++ ++ done = readw(&mvsd->NOR_INTR_STATUS) & waittype; ++ start = get_timer(0); ++ ++ while( done!=waittype) ++ { ++ done = readw(&mvsd->NOR_INTR_STATUS) & waittype; ++ ++ if( readw(&mvsd->NOR_INTR_STATUS) & 0x8000 ) ++ { ++ pr_debug("Error! cmd : %d, err : %04x\n", (unsigned int)cmd, readw(&mvsd->ERR_INTR_STATUS)) ; ++ ++ return 0 ; /* error happen */ ++ } ++ ++ curr = get_timer(0); ++ diff = (long) curr - (long) start; ++ if (diff > (3*hz)) ++ { ++ pr_debug("cmd timeout, status : %04x\n", readw(&mvsd->NOR_INTR_STATUS)); ++ pr_debug("xfer mode : %04x\n", readw(&mvsd->XFER_MODE)); ++ ++ err = 1 ; ++ break; ++ } ++ } ++ ++ response[0] = readw(&mvsd->RSP0); ++ response[1] = readw(&mvsd->RSP1); ++ response[2] = readw(&mvsd->RSP2); ++ response[3] = readw(&mvsd->RSP3); ++ response[4] = readw(&mvsd->RSP4); ++ response[5] = readw(&mvsd->RSP5); ++ response[6] = readw(&mvsd->RSP6); ++ response[7] = readw(&mvsd->RSP7); ++ ++ memset(resp, 0, sizeof(resp)); ++ ++ switch (resptype & 0x3) { ++ case SDIO_CMD_RSP_48: ++ case SDIO_CMD_RSP_48BUSY: ++ resp[0] = ((response[2] & 0x3f) << (8 - 8)) | ++ ((response[1] & 0xffff) << (14 - 8)) | ++ ((response[0] & 0x3ff) << (30 - 8)); ++ resp[1] = ((response[0] & 0xfc00) >> 10); ++ break; ++ ++ case SDIO_CMD_RSP_136: ++ resp[3] = ((response[7] & 0x3fff) << 8) | ++ ((response[6] & 0x3ff) << 22); ++ resp[2] = ((response[6] & 0xfc00) >> 10) | ++ ((response[5] & 0xffff) << 6) | ++ ((response[4] & 0x3ff) << 22); ++ resp[1] = ((response[4] & 0xfc00) >> 10) | ++ ((response[3] & 0xffff) << 6) | ++ ((response[2] & 0x3ff) << 22); ++ resp[0] = ((response[2] & 0xfc00) >> 10) | ++ ((response[1] & 0xffff) << 6) | ++ ((response[0] & 0x3ff) << 22); ++ break; ++ default: ++ return 0; ++ } ++ int i; ++ pr_debug("MMC resp :"); ++ for (i=0; i<4; ++i ) { ++ pr_debug(" %08x", (unsigned int)resp[i]); ++ } ++ pr_debug("\n"); ++ if( err ) ++ return NULL ; ++ else ++ return resp; ++} ++ ++/****************************************************/ ++static int mv_mmc_block_read(uchar *dst, ulong src, ulong len) ++/****************************************************/ ++{ ++ ulong *resp; ++ ++ if (len == 0) { ++ return 0; ++ } ++ ++ if (is_sdhc) { ++ /* SDHC: use block address */ ++ src >>= 9; ++ } ++ ++ pr_debug("mmc_block_rd dst %lx src %lx len %d\n", (ulong)dst, src, (int)len); ++ ++ /* prepare for dma transfer */ ++ writew(((ulong)(dst))&0xffff,&mvsd->SYS_ADDR_LOW); ++ writew(((ulong)(dst)>>16)&0xffff,&mvsd->SYS_ADDR_HI); ++ writew(len,&mvsd->BLK_SIZE); ++ writew(1,&mvsd->BLK_COUNT); ++ ++ /* send read command */ ++ resp = mv_mmc_cmd(MMC_CMD_READ_BLOCK, src, 0x10 , ++ SDIO_CMD_RSP_48, SDIO_NOR_XFER_DONE); ++ if (!resp) { ++ pr_debug("mv_mmc_block_read: mmc read block cmd fails\n"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++/****************************************************/ ++int mv_mmc_read(ulong src, uchar *dst, int size) ++/****************************************************/ ++{ ++ ulong end, part_start, part_end, part_len, aligned_start, aligned_end; ++ ulong mmc_block_size, mmc_block_address; ++ ++ if (size == 0) { ++ return 0; ++ } ++ ++ if (!mmc_ready) { ++ printf("Please initial the MMC first\n"); ++ return -1; ++ } ++ ++ mmc_block_size = MMC_BLOCK_SIZE; ++ mmc_block_address = ~(mmc_block_size - 1); ++ ++ end = src + size; ++ part_start = ~mmc_block_address & src; ++ part_end = ~mmc_block_address & end; ++ aligned_start = mmc_block_address & src; ++ aligned_end = mmc_block_address & end; ++ ++ /* all block aligned accesses */ ++ pr_debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", ++ (long unsigned int)src,(ulong)dst, end, part_start, part_end, aligned_start, aligned_end); ++ ++ if (part_start) { ++ part_len = mmc_block_size - part_start; ++ pr_debug("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", ++ (long unsigned int)src,(ulong)dst, end, part_start, part_end, aligned_start, aligned_end); ++ ++ if ((mv_mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0) { ++ return -1; ++ } ++ memcpy(dst, mmc_buf+part_start, part_len); ++ dst += part_len; ++ src += part_len; ++ } ++ pr_debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", ++ (long unsigned int)src,(ulong)dst, end, part_start, part_end, aligned_start, aligned_end); ++ ++ for (; src < aligned_end; aligned_start +=mmc_block_size, src += mmc_block_size, dst += mmc_block_size) { ++ pr_debug("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", ++ (long unsigned int)src,(ulong)dst, end, part_start, part_end, aligned_start, aligned_end); ++ ++ if ((mv_mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0) { ++ printf("mmc block read error\n"); ++ return -1; ++ } ++ memcpy(dst, mmc_buf, mmc_block_size); ++ } ++ pr_debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", ++ (long unsigned int)src,(ulong)dst, end, part_start, part_end, aligned_start, aligned_end); ++ ++ if (part_end && src < end) { ++ pr_debug("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", ++ (long unsigned int)src,(ulong)dst, end, part_start, part_end, aligned_start, aligned_end); ++ ++ if ((mv_mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0) { ++ return -1; ++ } ++ memcpy(dst, mmc_buf, part_end); ++ } ++ return 0; ++} ++ ++/****************************************************/ ++static ulong mv_mmc_bread(int dev_num, ulong blknr, ulong blkcnt, ulong *dst) ++/****************************************************/ ++{ ++ int mmc_block_size = MMC_BLOCK_SIZE; ++ ulong src = blknr * mmc_block_size; ++ ++ mv_mmc_read(src, (uchar *)dst, blkcnt*mmc_block_size); ++ return blkcnt; ++} ++ ++/****************************************************/ ++int mmc_legacy_init(int verbose) ++/****************************************************/ ++{ ++ int retries, rc = -ENODEV; ++ ulong *resp; ++ int sd_ver20; ++ int is_sd; ++ ushort reg; ++ uchar cidbuf[64]; ++ ++ sd_ver20 = 0; ++ is_sdhc = 0; ++ is_sd = 0; ++ ++ /* Initial Host Ctrl : Timeout : max , Normal Speed mode, 4-bit data mode */ ++ /* Big Endian, SD memory Card, Push_pull CMD Line */ ++ writew( SDIO_HOST_CTRL_TMOUT(0xf) | ++ SDIO_HOST_CTRL_DATA_WIDTH_4_BITS | ++ SDIO_HOST_CTRL_BIG_ENDIAN | ++ SDIO_HOST_CTRL_PUSH_PULL_EN | ++ SDIO_HOST_CTRL_CARD_TYPE_MEM_ONLY , ++ &mvsd->HOST_CTRL); ++ ++ writew( 0, &mvsd->CLK_CTRL); ++ ++ /* enable status */ ++ writew( 0xffff, &mvsd->NOR_STATUS_EN); ++ writew( 0xffff, &mvsd->ERR_STATUS_EN); ++ ++ /* disable interrupts */ ++ writew( 0, &mvsd->NOR_INTR_EN); ++ writew( 0, &mvsd->ERR_INTR_EN); ++ ++ writew( 0x100, &mvsd->SW_RESET); ++ udelay(10000); ++ ++ mv_mmc_csd.c_size = 0; ++ ++ /* reset */ ++ retries = 10; ++ resp = mv_mmc_cmd(0, 0, 0, SDIO_CMD_RSP_NONE, SDIO_NOR_CMD_DONE ); ++ pr_debug("cmd 0 resp : %08x %08x %08x %08x\n", ++ (unsigned int)resp[0], (unsigned int)resp[1], (unsigned int)resp[2], (unsigned int)resp[3] ); ++ ++ ++ pr_debug ("trying to detect SD card version\n"); ++ ++ resp = mv_mmc_cmd(8, 0x000001aa, 0, SDIO_CMD_RSP_48, SDIO_NOR_CMD_DONE ); ++ pr_debug("cmd 8 resp : %08x %08x %08x %08x\n", ++ (unsigned int)resp[0], (unsigned int)resp[1], (unsigned int)resp[2], (unsigned int)resp[3] ); ++ ++ if (resp && (resp[0] & 0x1ff)==0x1aa) { ++ pr_debug ("SD version 2.0 card detected\n"); ++ ++ sd_ver20 = 1; ++ } ++ ++ if (sd_ver20) ++ retries = 50; ++ else ++ retries = 10; ++ ++ while (retries--) { ++ resp = mv_mmc_cmd(55, 0, 0, SDIO_CMD_RSP_48, SDIO_NOR_CMD_DONE ); ++ pr_debug("cmd 55 resp : %08x %08x %08x %08x\n", ++ (unsigned int)resp[0], (unsigned int)resp[1], (unsigned int)resp[2], (unsigned int)resp[3] ); ++ ++ ++ if (sd_ver20) ++ resp = mv_mmc_cmd(41, 0x40300000, 0, SDIO_CMD_RSP_48, SDIO_NOR_CMD_DONE ); ++ else ++ resp = mv_mmc_cmd(41, 0x00300000, 0, SDIO_CMD_RSP_48, SDIO_NOR_CMD_DONE ); ++ ++ pr_debug("cmd 41 resp : %08x %08x %08x %08x\n", ++ (unsigned int)resp[0], (unsigned int)resp[1], (unsigned int)resp[2], (unsigned int)resp[3] ); ++ ++ ++ if (resp && (resp[0] & 0x80000000)) { ++ pr_debug ("detected SD card\n"); ++ ++ is_sd = 1; ++ break; ++ } ++ ++ udelay(100*1000); ++ } ++ ++ if (retries <= 0 && !is_sd) { ++ pr_debug ("failed to detect SD card, trying MMC\n"); ++ ++ retries = 10; ++ while (retries--) { ++ resp = mv_mmc_cmd(1, 0, 0, SDIO_CMD_RSP_48, SDIO_NOR_CMD_DONE ); ++ pr_debug("cmd 01 resp : %08x %08x %08x %08x\n", ++ (unsigned int)resp[0], (unsigned int)resp[1], (unsigned int)resp[2], (unsigned int)resp[3] ); ++ ++ ++ if (resp && (resp[0] & 0x80000000)) { ++ printf ("detected MMC card\n"); ++ reg = readw(&mvsd->HOST_CTRL); ++ reg &= ~(0x3<<1); ++ reg |= SDIO_HOST_CTRL_CARD_TYPE_IO_MMC; ++ writew( reg, &mvsd->HOST_CTRL); ++ break; ++ } ++ ++ udelay(100*1000); ++ } ++ } ++ ++ if (retries <= 0) { ++ pr_debug ("detect fails\n"); ++ ++ return -ENODEV; ++ } ++ ++ /* try to get card id */ ++ resp = mv_mmc_cmd(2, 0, 0, SDIO_CMD_RSP_136, SDIO_NOR_CMD_DONE ); ++ pr_debug("cmd 2 resp : %08x %08x %08x %08x\n", ++ (unsigned int)resp[0], (unsigned int)resp[1], (unsigned int)resp[2], (unsigned int)resp[3] ); ++ ++ ++ if (resp == NULL) { ++ pr_debug ("read cid fails\n"); ++ ++ return -ENODEV; ++ } ++ ++ if (is_sd) { ++ mv_sd_cid_t *cid = (mv_sd_cid_t *) resp; ++ ++ memcpy(cidbuf, resp, sizeof(mv_sd_cid_t)); ++ ++ sprintf((char *) mmc_dev.vendor, ++ "Man %02x OEM %c%c \"%c%c%c%c%c\"", ++ cid->mid, cid->oid_0, cid->oid_1, ++ cid->pnm_0, cid->pnm_1, cid->pnm_2, cid->pnm_3, cid->pnm_4); ++ ++ sprintf((char *) mmc_dev.product, "%d", ++ (cid->psn_0 << 24) | (cid->psn_1 <<16) | (cid->psn_2 << 8) | (cid->psn_3 << 8)); ++ ++ sprintf((char *) mmc_dev.revision, "%d.%d", cid->prv>>4, cid->prv & 0xff); ++ ++ } else { ++ /* TODO configure mmc driver depending on card attributes */ ++ mv_mmc_cid_t *cid = (mv_mmc_cid_t *) resp; ++ ++ memcpy(cidbuf, resp, sizeof(mv_sd_cid_t)); ++ ++ ++ sprintf((char *) mmc_dev.vendor, ++ "Man %02x%02x%02x Snr %02x%02x%02x", ++ cid->id[0], cid->id[1], cid->id[2], ++ cid->sn[0], cid->sn[1], cid->sn[2]); ++ sprintf((char *) mmc_dev.product, "%s", cid->name); ++ sprintf((char *) mmc_dev.revision, "%x %x", cid->hwrev, cid->fwrev); ++ } ++ ++ /* fill in device description */ ++ mmc_dev.if_type = IF_TYPE_MMC; ++ mmc_dev.part_type = PART_TYPE_DOS; ++ mmc_dev.dev = 0; ++ mmc_dev.lun = 0; ++ mmc_dev.type = 0; ++ ++ /* FIXME fill in the correct size (is set to 128MByte) */ ++ mmc_dev.blksz = MMC_BLOCK_SIZE; ++ mmc_dev.lba = 0x10000; ++ ++ mmc_dev.removable = 0; ++ mmc_dev.block_read = (unsigned long) mv_mmc_bread; ++ ++ /* MMC exists, get CSD too */ ++ resp = mv_mmc_cmd(MMC_CMD_SET_RCA, 0, 0, SDIO_CMD_RSP_48, SDIO_NOR_CMD_DONE ); ++ if (resp == NULL) { ++ pr_debug ("set rca fails\n"); ++ ++ return -ENODEV; ++ } ++ pr_debug("cmd3 resp : 0x%08x 0x%08x 0x%08x 0x%08x\n", ++ (unsigned int)resp[0], (unsigned int)resp[1], (unsigned int)resp[2], (unsigned int)resp[3]); ++ ++ ++ if (is_sd) ++ rca = resp[0] >> 16; ++ else ++ rca = 0; ++ ++ resp = mv_mmc_cmd(MMC_CMD_SEND_CSD, rca<<16, 0, SDIO_CMD_RSP_136,SDIO_NOR_CMD_DONE ); ++ pr_debug("cmd 9 resp : %08x %08x %08x %08x\n", ++ (unsigned int)resp[0], (unsigned int)resp[1], (unsigned int)resp[2], (unsigned int)resp[3] ); ++ ++ if (resp == NULL) { ++ pr_debug ("read csd fails\n"); ++ ++ return -ENODEV; ++ } ++ ++ memcpy(&mv_mmc_csd, (mv_mmc_csd_t *) resp, sizeof(mv_mmc_csd_t)); ++ rc = 0; ++ mmc_ready = 1; ++ ++ /* FIXME add verbose printout for csd */ ++ pr_debug ("size = %u\n", mv_mmc_size(&mv_mmc_csd)); ++ ++ ++ resp = mv_mmc_cmd(7, rca<<16, 0, SDIO_CMD_RSP_48BUSY, SDIO_NOR_CMD_DONE); ++ if (resp == NULL) { ++ pr_debug ("select card fails\n"); ++ ++ return -ENODEV; ++ } ++ pr_debug("cmd 7 resp : %08x %08x %08x %08x\n", ++ (unsigned int)resp[0], (unsigned int)resp[1], (unsigned int)resp[2], (unsigned int)resp[3] ); ++ ++ ++ if (is_sd) { ++ resp = mv_mmc_cmd(55, rca<<16, 0, SDIO_CMD_RSP_48, SDIO_NOR_CMD_DONE ); ++ if (resp == NULL) { ++ pr_debug ("cmd55 fails\n"); ++ ++ return -ENODEV; ++ } ++ pr_debug("cmd55 resp : 0x%08x 0x%08x 0x%08x 0x%08x\n", ++ (unsigned int)resp[0], (unsigned int)resp[1], (unsigned int)resp[2], (unsigned int)resp[3]); ++ ++ ++ resp = mv_mmc_cmd(6, (rca<<16) | 0x2 , 0, SDIO_CMD_RSP_48, SDIO_NOR_CMD_DONE ); ++ if (resp == NULL) { ++ pr_debug ("cmd55 fails\n"); ++ ++ return -ENODEV; ++ } ++ pr_debug("cmd6 resp : 0x%08x 0x%08x 0x%08x 0x%08x\n", ++ (unsigned int)resp[0], (unsigned int)resp[1], (unsigned int)resp[2], (unsigned int)resp[3]); ++ ++ } ++ ++ resp = (ulong *) &mv_mmc_csd; ++ pr_debug("csd: 0x%08x 0x%08x 0x%08x 0x%08x\n", ++ (unsigned int)resp[0], (unsigned int)resp[1], (unsigned int)resp[2], (unsigned int)resp[3]); ++ ++ ++ /* check SDHC */ ++ if ((resp[0]&0xf0000000)==0x40000000) ++ is_sdhc = 1; ++ ++ /* set block len */ ++ resp = mv_mmc_cmd(MMC_CMD_SET_BLOCKLEN, MMC_BLOCK_SIZE, 0, SDIO_CMD_RSP_48, SDIO_NOR_CMD_DONE ); ++ if (!resp) { ++ pr_debug("mv_mmc_block_read: set blk len fails\n"); ++ return -ENODEV; ++ } ++ ++ if (verbose) { ++ if (is_sd) ++ print_sd_cid((mv_sd_cid_t *) cidbuf); ++ else ++ print_mmc_cid((mv_mmc_cid_t *) cidbuf); ++ } ++ ++ mvsdio_set_clock(CONFIG_SYS_MMC_CLK_PP); ++ ++ fat_register_device(&mmc_dev,1); /* partitions start counting with 1 */ ++ ++ return 0; ++} ++ ++#endif /* CONFIG_MMC */ +diff --git a/drivers/mmc/mv_sdio.h b/drivers/mmc/mv_sdio.h +new file mode 100644 +index 0000000..9707000 +--- /dev/null ++++ b/drivers/mmc/mv_sdio.h +@@ -0,0 +1,310 @@ ++/* ++ * (C) Copyright 2009 ++ * Marvell Semiconductor ++ * Written-by: Gérald Kerma ++ * ++ * 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., 51 Franklin Street, Fifth Floor, Boston, ++ * MA 02110-1301 USA ++ */ ++ ++#ifndef _MVSDIO_INCLUDE ++#define _MVSDIO_INCLUDE ++ ++//#define SDIO_REG(x) (MV_SDIO_BASE + (x)) ++ ++#define MVSDMMC_DMA_SIZE 65536 ++#define MVSDMMC_CMD_TIMEOUT 2 /* 100 usec*/ ++ ++/* ++ * Clock rates ++ */ ++ ++#define MVSD_CLOCKRATE_MAX 50000000 ++#define MVSD_BASE_DIV_MAX 0x7ff ++ ++#define CONFIG_SYS_MMC_CLK_PP 25000000 ++ ++/* ++ * The base MMC clock rate ++ */ ++ ++#define MVSDMMC_CLOCKRATE_MIN 100000 ++#define MVSDMMC_CLOCKRATE_MAX MVSD_CLOCKRATE_MAX ++#define MVSDMMC_BASE_FAST_CLOCK CONFIG_SYS_TCLK ++ ++ ++/* ++ * SDIO register ++ */ ++#ifndef __ASSEMBLY__ ++ ++/* ++ * Structure for struct SoC access. ++ * Names starting with '_' are fillers. ++ */ ++typedef struct mv_sdio { ++ /* reg Offset */ ++ u32 SYS_ADDR_LOW; /* 0x00 */ ++ u32 SYS_ADDR_HI; /* 0x04 */ ++ u32 BLK_SIZE; /* 0x08 */ ++ u32 BLK_COUNT; /* 0x0c */ ++ u32 ARG_LOW; /* 0x10 */ ++ u32 ARG_HI; /* 0x14 */ ++ u32 XFER_MODE; /* 0x18 */ ++ u32 CMD; /* 0x1c */ ++ u32 RSP0; /* 0x20 */ ++ u32 RSP1; /* 0x24 */ ++ u32 RSP2; /* 0x28 */ ++ u32 RSP3; /* 0x2c */ ++ u32 RSP4; /* 0x30 */ ++ u32 RSP5; /* 0x34 */ ++ u32 RSP6; /* 0x38 */ ++ u32 RSP7; /* 0x3c */ ++ u32 BUF_DATA_PORT; /* 0x40 */ ++ u32 RSVED; /* 0x44 */ ++ u32 PRESENT_STATE0; /* 0x48 */ ++ u32 PRESENT_STATE1; /* 0x4c */ ++ u32 HOST_CTRL; /* 0x50 */ ++ u32 BLK_GAP_CTRL; /* 0x54 */ ++ u32 CLK_CTRL; /* 0x58 */ ++ u32 SW_RESET; /* 0x5c */ ++ u32 NOR_INTR_STATUS; /* 0x60 */ ++ u32 ERR_INTR_STATUS; /* 0x64 */ ++ u32 NOR_STATUS_EN; /* 0x68 */ ++ u32 ERR_STATUS_EN; /* 0x6c */ ++ u32 NOR_INTR_EN; /* 0x70 */ ++ u32 ERR_INTR_EN; /* 0x74 */ ++ u32 AUTOCMD12_ERR_STATUS; /* 0x78 */ ++ u32 CURR_BYTE_LEFT; /* 0x7c */ ++ u32 CURR_BLK_LEFT; /* 0x80 */ ++ u32 AUTOCMD12_ARG_LOW; /* 0x84 */ ++ u32 AUTOCMD12_ARG_HI; /* 0x88 */ ++ u32 AUTOCMD12_INDEX; /* 0x8c */ ++ u32 AUTO_RSP0; /* 0x90 */ ++ u32 AUTO_RSP1; /* 0x94 */ ++ u32 AUTO_RSP2; /* 0x98 */ ++ u32 _9c; /* 0x9c */ ++ u32 _a0[0x78]; /* 0xa0 */ ++ u32 CLK_DIV; /* 0x128 */ ++ ++} mv_sdio_t; ++ ++#endif /* __ASSEMBLY__ */ ++ ++/* ++ * SDIO_PRESENT_STATE ++ */ ++ ++#define CARD_BUSY (1 << 1) ++#define CMD_INHIBIT (1 << 0) ++#define CMD_TXACTIVE (1 << 8) ++#define CMD_RXACTIVE (1 << 9) ++#define CMD_AUTOCMD12ACTIVE (1 << 14) ++ ++#define CMD_BUS_BUSY (CMD_AUTOCMD12ACTIVE| \ ++ CMD_RXACTIVE| \ ++ CMD_TXACTIVE| \ ++ CMD_INHIBIT| \ ++ CARD_BUSY) ++ ++/* ++ * SDIO_CMD ++ */ ++ ++#define SDIO_CMD_RSP_NONE (0 << 0) ++#define SDIO_CMD_RSP_136 (1 << 0) ++#define SDIO_CMD_RSP_48 (2 << 0) ++#define SDIO_CMD_RSP_48BUSY (3 << 0) ++ ++#define SDIO_CMD_CHECK_DATACRC16 (1 << 2) ++#define SDIO_CMD_CHECK_CMDCRC (1 << 3) ++#define SDIO_CMD_INDX_CHECK (1 << 4) ++#define SDIO_CMD_DATA_PRESENT (1 << 5) ++#define SDIO_UNEXPECTED_RESP (1 << 7) ++ ++ ++/* ++ * SDIO_XFER_MODE ++ */ ++ ++#define SDIO_XFER_MODE_STOP_CLK (1 << 5) ++#define SDIO_XFER_MODE_HW_WR_DATA_EN (1 << 1) ++#define SDIO_XFER_MODE_AUTO_CMD12 (1 << 2) ++#define SDIO_XFER_MODE_INT_CHK_EN (1 << 3) ++#define SDIO_XFER_MODE_TO_HOST (1 << 4) ++ ++ ++/* ++ * SDIO_HOST_CTRL ++ */ ++ ++#define SDIO_HOST_CTRL_PUSH_PULL_EN (1 << 0) ++ ++#define SDIO_HOST_CTRL_CARD_TYPE_MEM_ONLY (0 << 1) ++#define SDIO_HOST_CTRL_CARD_TYPE_IO_ONLY (1 << 1) ++#define SDIO_HOST_CTRL_CARD_TYPE_IO_MEM_COMBO (2 << 1) ++#define SDIO_HOST_CTRL_CARD_TYPE_IO_MMC (3 << 1) ++#define SDIO_HOST_CTRL_CARD_TYPE_MASK (3 << 1) ++ ++#define SDIO_HOST_CTRL_BIG_ENDIAN (1 << 3) ++#define SDIO_HOST_CTRL_LSB_FIRST (1 << 4) ++#define SDIO_HOST_CTRL_ID_MODE_LOW_FREQ (1 << 5) ++#define SDIO_HOST_CTRL_HALF_SPEED (1 << 6) ++#define SDIO_HOST_CTRL_DATA_WIDTH_4_BITS (1 << 9) ++#define SDIO_HOST_CTRL_HI_SPEED_EN (1 << 10) ++ ++ ++#define SDIO_HOST_CTRL_TMOUT_MASK (0xf << 11) ++#define SDIO_HOST_CTRL_TMOUT_MAX (0xf << 11) ++#define SDIO_HOST_CTRL_TMOUT(x) ((x) << 11) ++#define SDIO_HOST_CTRL_TMOUT_EN (1 << 15) ++ ++#define SDIO_HOST_CTRL_DFAULT_OPEN_DRAIN \ ++ (SDIO_HOST_CTRL_TMOUT(x)(0xf)) ++#define SDIO_HOST_CTRL_DFAULT_PUSH_PULL \ ++ (SDIO_HOST_CTRL_TMOUT(x)(0xf) | SDIO_HOST_CTRL_PUSH_PULL_EN) ++ ++ ++/* ++ * NOR status bits ++ */ ++ ++#define SDIO_NOR_ERROR (1 << 15) ++#define SDIO_NOR_UNEXP_RSP (1 << 14) ++#define SDIO_NOR_AUTOCMD12_DONE (1 << 13) ++#define SDIO_NOR_SUSPEND_ON (1 << 12) ++#define SDIO_NOR_LMB_FF_8W_AVAIL (1 << 11) ++#define SDIO_NOR_LMB_FF_8W_FILLED (1 << 10) ++#define SDIO_NOR_READ_WAIT_ON (1 << 9) ++#define SDIO_NOR_CARD_INT (1 << 8) ++#define SDIO_NOR_READ_READY (1 << 5) ++#define SDIO_NOR_WRITE_READY (1 << 4) ++#define SDIO_NOR_DMA_INI (1 << 3) ++#define SDIO_NOR_BLK_GAP_EVT (1 << 2) ++#define SDIO_NOR_XFER_DONE (1 << 1) ++#define SDIO_NOR_CMD_DONE (1 << 0) ++ ++ ++/* ++ * ERR status bits ++ */ ++ ++#define SDIO_ERR_CRC_STATUS (1 << 14) ++#define SDIO_ERR_CRC_STARTBIT (1 << 13) ++#define SDIO_ERR_CRC_ENDBIT (1 << 12) ++#define SDIO_ERR_RESP_TBIT (1 << 11) ++#define SDIO_ERR_SIZE (1 << 10) ++#define SDIO_ERR_CMD_STARTBIT (1 << 9) ++#define SDIO_ERR_AUTOCMD12 (1 << 8) ++#define SDIO_ERR_DATA_ENDBIT (1 << 6) ++#define SDIO_ERR_DATA_CRC (1 << 5) ++#define SDIO_ERR_DATA_TIMEOUT (1 << 4) ++#define SDIO_ERR_CMD_INDEX (1 << 3) ++#define SDIO_ERR_CMD_ENDBIT (1 << 2) ++#define SDIO_ERR_CMD_CRC (1 << 1) ++#define SDIO_ERR_CMD_TIMEOUT (1 << 0) ++ ++#define SDIO_ERR_INTR_MASK 0xFFFF ++ ++ ++#define MMC_BLOCK_SIZE 512 ++#define MMC_CMD_RESET 0 ++#define MMC_CMD_SEND_OP_COND 1 ++#define MMC_CMD_ALL_SEND_CID 2 ++#define MMC_CMD_SET_RCA 3 ++#define MMC_CMD_SELECT_CARD 7 ++#define MMC_CMD_SEND_CSD 9 ++#define MMC_CMD_SEND_CID 10 ++#define MMC_CMD_SEND_STATUS 13 ++#define MMC_CMD_SET_BLOCKLEN 16 ++#define MMC_CMD_READ_BLOCK 17 ++#define MMC_CMD_RD_BLK_MULTI 18 ++#define MMC_CMD_WRITE_BLOCK 24 ++#define MMC_MAX_BLOCK_SIZE 512 ++ ++typedef struct mv_mmc_cid ++{ ++ /* FIXME: BYTE_ORDER */ ++ uchar year:4, ++ month:4; ++ uchar sn[3]; ++ uchar fwrev:4, ++ hwrev:4; ++ uchar name[6]; ++ uchar id[3]; ++} mv_mmc_cid_t; ++ ++typedef struct mv_mmc_csd ++{ ++ uchar ecc:2, ++ file_format:2, ++ tmp_write_protect:1, ++ perm_write_protect:1, ++ copy:1, ++ file_format_grp:1; ++ uint64_t content_prot_app:1, ++ rsvd3:4, ++ write_bl_partial:1, ++ write_bl_len:4, ++ r2w_factor:3, ++ default_ecc:2, ++ wp_grp_enable:1, ++ wp_grp_size:5, ++ erase_grp_mult:5, ++ erase_grp_size:5, ++ c_size_mult1:3, ++ vdd_w_curr_max:3, ++ vdd_w_curr_min:3, ++ vdd_r_curr_max:3, ++ vdd_r_curr_min:3, ++ c_size:12, ++ rsvd2:2, ++ dsr_imp:1, ++ read_blk_misalign:1, ++ write_blk_misalign:1, ++ read_bl_partial:1; ++ ushort read_bl_len:4, ++ ccc:12; ++ uchar tran_speed; ++ uchar nsac; ++ uchar taac; ++ uchar rsvd1:2, ++ spec_vers:4, ++ csd_structure:2; ++} mv_mmc_csd_t; ++ ++typedef struct { ++ char pnm_0; /* product name */ ++ char oid_1; /* OEM/application ID */ ++ char oid_0; ++ uint8_t mid; /* manufacturer ID */ ++ char pnm_4; ++ char pnm_3; ++ char pnm_2; ++ char pnm_1; ++ uint8_t psn_2; /* product serial number */ ++ uint8_t psn_1; ++ uint8_t psn_0; /* MSB */ ++ uint8_t prv; /* product revision */ ++ uint8_t crc; /* CRC7 checksum, b0 is unused and set to 1 */ ++ uint8_t mdt_1; /* manufacturing date, LSB, RRRRyyyy yyyymmmm */ ++ uint8_t mdt_0; /* MSB */ ++ uint8_t psn_3; /* LSB */ ++} mv_sd_cid_t; ++ ++#endif /* _MVSDIO_INCLUDE */ +diff --git a/include/configs/sheevaplug.h b/include/configs/sheevaplug.h +index 83dd8ff..7c8497c 100644 +--- a/include/configs/sheevaplug.h ++++ b/include/configs/sheevaplug.h +@@ -1,3 +1,4 @@ ++ + /* + * (C) Copyright 2009 + * Marvell Semiconductor +@@ -47,7 +48,9 @@ + #define CONFIG_CMD_DHCP + #define CONFIG_CMD_ENV + #define CONFIG_CMD_MII ++#define CONFIG_CMD_MMC + #define CONFIG_CMD_NAND ++#define CONFIG_JFFS2_NAND + #define CONFIG_CMD_PING + #define CONFIG_CMD_USB + /* +@@ -70,8 +73,8 @@ + * it has to be rounded to sector size + */ + #define CONFIG_ENV_SIZE 0x20000 /* 128k */ +-#define CONFIG_ENV_ADDR 0x60000 +-#define CONFIG_ENV_OFFSET 0x60000 /* env starts here */ ++#define CONFIG_ENV_ADDR 0xa0000 ++#define CONFIG_ENV_OFFSET 0xa0000 /* env starts here */ + + /* + * Default environment variables +@@ -81,10 +84,11 @@ + "${x_bootcmd_usb}; bootm 0x6400000;" + + #define CONFIG_MTDPARTS "orion_nand:512k(uboot)," \ +- "3m@1m(kernel),1m@4m(psm),13m@5m(rootfs) rw\0" ++ "0x1ff00000@512k(rootfs) rw\0" + + #define CONFIG_EXTRA_ENV_SETTINGS "x_bootargs=console" \ + "=ttyS0,115200 mtdparts="CONFIG_MTDPARTS \ ++ "mtdids=nand0=orion_nand\0" \ + "x_bootcmd_kernel=nand read 0x6400000 0x100000 0x300000\0" \ + "x_bootcmd_usb=usb start\0" \ + "x_bootargs_root=root=/dev/mtdblock3 rw rootfstype=jffs2\0"