--- a/cpu/pxa/mmc.c 2004-09-08 20:52:38.648768285 -0400 +++ b/cpu/pxa/mmc.c 2004-09-08 21:03:18.498151380 -0400 @@ -1,7 +1,7 @@ /* * (C) Copyright 2003 * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net - * + * patched Sept 2004 David Farrell davidjf2001@yahoo.com djf * See file CREDITS for list of people who contributed to this * project. * @@ -94,12 +92,8 @@ 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 mmc_csd_t mmc_csd; +/* static mmc_csd_t mmc_csd; */ static int mmc_ready = 0; @@ -169,9 +165,6 @@ return resp; } -#define DOS_PART_MAGIC_OFFSET 0x1fe - - int /****************************************************/ mmc_block_read(uchar *dst, ulong src, ulong len) @@ -266,10 +259,6 @@ mmc_print_stat(); debug("\n"); -// *(origdst + DOS_PART_MAGIC_OFFSET) = 0x55; -// *(origdst + DOS_PART_MAGIC_OFFSET + 1) = 0xaa; - - return 0; } @@ -497,18 +486,49 @@ return 0; } +static int current_state; /* djf */ +static u16 rca_addr; /* djf */ +#define MMC_ST_IDLE 0 +#define MMC_ST_READY 1 +#define MMC_ST_IDENT 2 +#define MMC_ST_STBY 3 +#define MMC_ST_TRAN 4 + +int mmc_block_size; + ulong /****************************************************/ mmc_bread(int dev_num, ulong blknr, ulong blkcnt, ulong *dst) /****************************************************/ { - int mmc_block_size = MMC_BLOCK_SIZE; +uchar *resp; + + debug("mmc_bread %08X, %08X, %08X\n",blknr,blkcnt,dst); + ulong src = blknr * mmc_block_size + CFG_MMC_BASE; + /* select the card */ + resp = mmc_cmd(7,rca_addr, 0, MMC_CMDAT_R1|MMC_CMDAT_BUSY); + if(resp)current_state = MMC_ST_TRAN; + mmc_read(src, (uchar *)dst, blkcnt*mmc_block_size); + + /* deselect the card */ + resp = mmc_cmd(7,0, 0, MMC_CMDAT_R1|MMC_CMDAT_BUSY); + if(resp)current_state = MMC_ST_STBY; + return blkcnt; } +/* TRAN_SPEED Multipliers mantissa is fixed point 10x book value */ +u32 t_mantissa[] = {0,10,12,13, 15,20,25,30, 35,40,45,50, 55,60,70,80}; + +/* Card transfer data rate exponents */ +u32 tran_speed_exp[] = {10000,100000,1000000,1000000,0,0,0,0}; /* in HZ */ + +/* TACC multipliers */ +u32 tacc_speed_exp[] = {1,10,100,1000,10000,100000,1000000,10000000}; /* in ns */ + int /****************************************************/ mmc_init(int verbose) @@ -516,6 +536,10 @@ { int retries, rc = -ENODEV; uchar *resp; + u32 tmp1,tmp2i,tran,Tpwns,taccess; + + mmc_cid_t *cid; + mmc_csd_t *csd; #ifdef CONFIG_LUBBOCK set_GPIO_mode( GPIO6_MMCCLK_MD ); @@ -526,76 +550,159 @@ set_GPIO_mode( GPIO8_MMCCS0_MD ); #endif - CKEN |= CKEN12_MMC; /* enable MMC unit clock */ - - mmc_csd.c_size = 0; + /* CKEN |= CKEN12_MMC; enable MMC unit clock from core. Off only for power down (enabled at reset) */ - MMC_CLKRT = MMC_CLKRT_0_3125MHZ; + MMC_CLKRT = MMC_CLKRT_0_3125MHZ; /* 312 KHZ */ MMC_RESTO = MMC_RES_TO_MAX; MMC_SPI = MMC_SPI_DISABLE; - /* reset */ - retries = 3; + /* Power On Reset Assumed for this test, the 1st command (55) prepends a 80 bit clock to reset card */ + retries = 5; + resp = NULL; /* let the loop work at least once */ + while(retries-- && !resp) { + /* djf */ + /* mmc_cmd(ushort cmd, ushort argh, ushort argl, ushort cmdat) */ + resp = mmc_cmd(0,0, 0, MMC_CMDAT_INIT|MMC_CMDAT_BUSY|MMC_CMDAT_R1); + udelay(200000); + } /* while */ - int i; - i=80; - while (i--) resp = mmc_cmd(0, 0, 0, 0); // Sends RESET command + /* djf end */ + printf("Trying MMC\n"); + retries = 5; + rca_addr = MMC_DEFAULT_RCA; - resp = mmc_cmd(1, 0x00ff, 0xc000, MMC_CMDAT_INIT|MMC_CMDAT_BUSY|MMC_CMDAT_R3); + /* 2.7 - 3.3V */ + resp = mmc_cmd(1, 0x00ff, 0x8000, MMC_CMDAT_BUSY|MMC_CMDAT_R3); while (retries-- && resp && !(resp[4] & 0x80)) { - debug(" mmc_init> resp 0x%02x 0x%02x\n", resp[0], resp[1]); - udelay(20000); - resp = mmc_cmd(1, 0x00ff, 0xff00, MMC_CMDAT_BUSY|MMC_CMDAT_R3); - } + debug(" mmc_init> resp 0x%02x 0x%02x\n", resp[0], resp[1]); /* was debug */ + udelay(200000); /* djf was 20000, now my JVC card detected 1st time */ + resp = mmc_cmd(1, 0x00ff, 0x8000, MMC_CMDAT_BUSY|MMC_CMDAT_R3); + } /* while */ + if(resp)current_state = MMC_ST_READY; - /* try to get card id */ - resp = mmc_cmd(2, 0, 0, MMC_CMDAT_R2); + if(current_state == MMC_ST_READY) + { + /* try to get card id both sd & mmc */ + resp = mmc_cmd(2, 0, 0, MMC_CMDAT_BUSY|MMC_CMDAT_R2); /* djf MMC_CMDAT_BUSY */ if (resp) { - /* TODO configure mmc driver depending on card attributes */ - mmc_cid_t *cid = (mmc_cid_t *)resp; + current_state = MMC_ST_IDENT; /* ident */ + cid = (mmc_cid_t *)resp; if (verbose) { printf("***********************************************\n"); printf("* MMC found. Card desciption is: *\n"); - printf("* Manufacturer ID = %02x%02x%02x *\n", cid->id[2], cid->id[1], cid->id[0]); - printf("* HW/FW Revision = 0x%02x 0x%02x *\n",cid->hwrev, cid->fwrev); + printf("* Manufacturer ID = %02x%02x%02x *\n", + cid->id[2], cid->id[1], cid->id[0]); + printf("* HW/FW Revision = 0x%02x 0x%02x *\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[2], cid->sn[1], cid->sn[0]); - printf("* Month = %2d Year = %d *\n",cid->month,1997 + cid->year); + printf("* Serial Number = %02x%02x%02x *\n", + cid->sn[2], cid->sn[1], cid->sn[0]); + printf("* Month = %2d Year = %d *\n", + cid->month,1997 + cid->year); printf("***********************************************\n"); - } - /* fill in device description */ - mmc_dev.if_type = IF_TYPE_MMC; - mmc_dev.dev = 1; - mmc_dev.lun = 1; - mmc_dev.type = PART_TYPE_UNKNOWN; - /* FIXME fill in the correct size (is set to 32MByte) */ - mmc_dev.blksz = 0x200; - mmc_dev.lba = 0x10000; - sprintf(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]); + } /* verbose */ + + sprintf(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(mmc_dev.product,"%s",cid->name); - sprintf(mmc_dev.revision,"0x%02x 0x%02x",cid->hwrev, cid->fwrev); - mmc_dev.removable = 0; - mmc_dev.block_read = mmc_bread; + sprintf(mmc_dev.revision,"HW%02x FW%02x",cid->hwrev, cid->fwrev); + } /* resp */ + } /* current_state == MMC_ST_READY */ - /* MMC exists, get CSD too */ - resp = mmc_cmd(MMC_CMD_SET_RCA, MMC_DEFAULT_RCA, 0, MMC_CMDAT_R1); - resp = mmc_cmd(MMC_CMD_SEND_CSD, MMC_DEFAULT_RCA, 0, MMC_CMDAT_R2); + if(current_state == MMC_ST_IDENT) { /* ident */ + /* MMC You tell the card the address to use */ + resp = mmc_cmd(MMC_CMD_SET_RCA, rca_addr, 0, MMC_CMDAT_R1); + if(resp)current_state = MMC_ST_STBY; + } /* current_state == MMC_ST_READY */ + + if(current_state == MMC_ST_STBY) { /* standby state */ + /* GET CSD */ + resp = mmc_cmd(MMC_CMD_SEND_CSD, rca_addr, 0, MMC_CMDAT_R2|MMC_CMDAT_BUSY); if (resp) { - mmc_csd_t *csd = (mmc_csd_t *)resp; - memcpy(&mmc_csd, csd, sizeof(csd)); + csd = (mmc_csd_t *)resp; /* djf */ + /* printf("sizeof csd = %d\n",sizeof(mmc_csd_t)); */ + /* memcpy(&mmc_csd, csd ,sizeof(mmc_csd_t)); */ rc = 0; mmc_ready = 1; - /* FIXME add verbose printout for csd */ + + taccess = (t_mantissa[((csd->taac>>3) & 0xf)] * tacc_speed_exp[(csd->taac & 7)])/10; + + tran = t_mantissa[((csd->tran_speed>>3) & 0xf)] * tran_speed_exp[(csd->tran_speed & 7)]; + + printf("CSD_STRUCTURE = %x, MMC_PROT=%x\n",csd->csd_structure,csd->spec_vers); + printf(" TAAC=%x (%dns), NSAC=%x\n",csd->taac,taccess,csd->nsac); + printf(" TRAN = %x (%dbps)\n",csd->tran_speed,tran); + printf(" CCC=%x, READ_BL_LEN=%x (%d)\n",csd->ccc,csd->read_bl_len,(1<read_bl_len)); + printf(" C_SIZE=%x, C_SIZE_MULT=%d (%d)\n",csd->c_size, csd->c_size_mult1, + (4<c_size_mult1)); + printf(" TOTAL MMC SIZE=%d\n",(1<read_bl_len) * csd->c_size * (4 << csd->c_size_mult1)); + + /* Correct the sizes to tell fat fs */ + mmc_block_size = (1<read_bl_len); + mmc_dev.lba = csd->c_size * (4 << csd->c_size_mult1); + } /* if resp */ + + } /* current_state == MMC_ST_STBY */ + + /* + DO NOT OVER-WRITE resp[] at this point. It will corrupt the csd-> which + points to the same place. No more cmm_cmd (or create you own buffered copy) + */ + + MMC_STRPCL = MMC_STRPCL_STOP_CLK; + + if(tran < 625000) { + MMC_CLKRT = 6; /* 312.5 KHZ Minimum speed */ + Tpwns = 3200; /* Clock period */ } + else if(tran < 1250000) { + MMC_CLKRT = 5; /* 625 KHZ */ + Tpwns = 1600; + } + else if(tran < 2500000) { + MMC_CLKRT = 4; /* 1.25MHZ */ + Tpwns = 800; + } + else if(tran < 5000000) { + MMC_CLKRT = 3; /* 2.5 MHZ */ + Tpwns = 400; + } + else if(tran < 10000000) { + MMC_CLKRT = 2; /* 5 MHZ */ + Tpwns = 200; + } + else if(tran < 20000000) { + MMC_CLKRT = 1; /* 10 MHZ */ + Tpwns = 100; + } + else { + MMC_CLKRT = 0; /* 20 MHZ */ + Tpwns = 50; } - MMC_CLKRT = 0; /* 20 MHz */ - resp = mmc_cmd(7, MMC_DEFAULT_RCA, 0, MMC_CMDAT_R1); + /* This is where I require csd-> to be intact */ + tmp1 = taccess / 50; /* Number of clocks to = ns of rd access time */ + tmp1++; /* Round up */ + tmp1 += ((Tpwns * 100 * csd->nsac) / 50); /* Additional MMC RATE clocks of access time */ + + /* The following would be (tmp1>>8), but I use a 4X safety factor */ + MMC_RDTO = (tmp1 >> 6); /* Timeout period in 20MHZ clocks (50ns) */ + printf(" MMC_RDTO = %d\n",(tmp1 >> 6)); + + /* fill in device description */ + mmc_dev.if_type = IF_TYPE_MMC; + mmc_dev.dev = 1; + mmc_dev.lun = 1; + mmc_dev.blksz = mmc_block_size; /* I dont think this is used */ + mmc_dev.part_type = PART_TYPE_DOS; + mmc_dev.type = DEV_TYPE_UNKNOWN; + mmc_dev.removable = 0; + mmc_dev.block_read = mmc_bread; fat_register_device(&mmc_dev,1); /* partitions start counting with 1 */ --- a/cpu/pxa/mmcsd.c 1969-12-31 19:00:00.000000000 -0500 +++ b/cpu/pxa/mmcsd.c 2004-09-08 18:33:42.000000000 -0400 @@ -0,0 +1,829 @@ +/* + * (C) Copyright 2003 + * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net + * patched Sept 2004 David Farrell davidjf2001@yahoo.com djf + * Reference Document: + * SanDisk Secure Digital Card Product Manual V1.9 + * 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 + */ + +#include +#include +#include +#include +#include + +#include + +// #define MMC_DEBUG +// #define debug printf + +#ifdef CONFIG_MMC + +void mmc_print_stat(void) +{ + int j,k=0; + short stat = MMC_STAT & MMC_STAT_ERRORS; + if (stat != 0) printf(""); else + for (j=1;j<256;j*=2) { + switch (stat & j) { + case (0x0001UL << 13): printf("END_CMD_RES. "); + k++; + break; + case (0x0001UL << 12): printf("PRG_DONE. "); + k++; + break; + case (0x0001UL << 11): printf("DATA_TRAN_DONE. "); + k++; + break; + case (0x0001UL << 8): printf("CLK_EN. "); + k++; + break; + case (0x0001UL << 7): printf("RECV_FIFO_FULL. "); + k++; + break; + case (0x0001UL << 6): printf("XMIT_FIFO_EMPTY. "); + k++; + break; + case (0x0001UL << 5): printf("RES_CRC_ERROR. "); + k++; + break; + case (0x0001UL << 4): printf("SPI_READ_ERROR_TOKEN. "); + k++; + break; + case (0x0001UL << 3): printf("CRC_READ_ERROR. "); + k++; + break; + case (0x0001UL << 2): printf("CRC_WRITE_ERROR. "); + k++; + break; + case (0x0001UL << 1): printf("TIME_OUT_RESPONSE. "); + k++; + break; + case (0x0001UL): printf("READ_TIME_OUT. "); + k++; + break; + default: break; + } + } +} + +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); +} + +static uchar mmc_buf[MMC_BLOCK_SIZE]; +/* static mmc_csd_t mmc_csd; */ +static int mmc_ready = 0; + + +static uchar * +/****************************************************/ +mmc_cmd(ushort cmd, ushort argh, ushort argl, ushort cmdat) +/****************************************************/ +{ + static uchar resp[20]; + ulong status; + int words, i; + + MMC_STRPCL = MMC_STRPCL_STOP_CLK; /* stop any active clock */ + MMC_I_MASK = ~MMC_I_MASK_CLK_IS_OFF; + while (!(MMC_I_REG & MMC_I_REG_CLK_IS_OFF)); + + MMC_CMD = cmd; + MMC_ARGH = argh; + MMC_ARGL = argl; + MMC_CMDAT = cmdat; + MMC_I_MASK = ~MMC_I_MASK_END_CMD_RES; + MMC_STRPCL = MMC_STRPCL_START_CLK; /* start clock, send command */ + while (!(MMC_I_REG & MMC_I_REG_END_CMD_RES)); + + status = MMC_STAT; +// printf("\n status> "); +// mmc_print_stat(); + + if (status & MMC_STAT_TIME_OUT_RESPONSE) + { + return 0; + } + + switch (cmdat & 0x3) + { + case MMC_CMDAT_R1: + case MMC_CMDAT_R3: + case MMC_CMDAT_R6: + words = 3; + break; + + case MMC_CMDAT_R2: + words = 8; + break; + + default: + return 0; + } + for (i = words-1; i >= 0; i--) + { + ulong res_fifo = MMC_RES; + int offset = i << 1; + + resp[offset] = ((uchar *)&res_fifo)[0]; + resp[offset+1] = ((uchar *)&res_fifo)[1]; + } + +#ifdef MMC_DEBUG + printf("\n results> "); + for (i=0; i dst 0x%08x src 0x%08x len %d\n", (ulong)dst, src, len); + + argh = len >> 16; + argl = len & 0xffff; + + /* set block len */ + resp = mmc_cmd(MMC_CMD_SET_BLOCKLEN, argh, argl, MMC_CMDAT_R1); + + /* send read command */ +// printf("\nBLK READ> %d:",cmd); +// debug("\n block_read> 0x%02x 0x%02x 0x%02x 0x%02x", cmd, argh, argl, cmdat); +// resp = mmc_cmd(MMC_CMD_READ_BLOCK, argh, argl, MMC_CMDAT_R1|MMC_CMDAT_READ|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN); + + MMC_STRPCL = MMC_STRPCL_STOP_CLK; + MMC_I_MASK = ~MMC_I_MASK_CLK_IS_OFF; + while (!(MMC_I_REG & MMC_I_REG_CLK_IS_OFF)); + + MMC_RDTO = 0xffff; + MMC_NOB = 1; + MMC_BLKLEN = len; + MMC_CMD = MMC_CMD_READ_BLOCK; + MMC_ARGH = src >> 16; + MMC_ARGL = src & 0xffff; + MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_READ|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN; + MMC_I_MASK = ~MMC_I_MASK_END_CMD_RES; + MMC_STRPCL = MMC_STRPCL_START_CLK; + while (!(MMC_I_REG & MMC_I_REG_END_CMD_RES)); + + status = MMC_STAT; +// printf(" "); +// printf("\n status> "); + mmc_print_stat(); + + if (status & MMC_STAT_TIME_OUT_RESPONSE) + { + return 0; + } + + MMC_I_MASK = ~MMC_I_MASK_RXFIFO_RD_REQ; + int c = 1; + + while (len) + { + c--; + + if (c==0) + { + while (c!=31) + { + if (MMC_I_REG & MMC_I_REG_RXFIFO_RD_REQ) c=31; + } + } + + { + *dst++ = MMC_RXFIFO; + len--; + } + + status = MMC_STAT; + if (status & MMC_STAT_ERRORS ) + { + printf("mmc_block_rd> MMC_STAT error 0x%08x\n", status & MMC_STAT_ERRORS ); + return -1; + } + } + + debug("\n"); + MMC_I_MASK = ~MMC_I_MASK_DATA_TRAN_DONE; + while (!(MMC_I_REG & MMC_I_REG_DATA_TRAN_DONE)); + status = MMC_STAT; + if (status & MMC_STAT_ERRORS ) + { + printf("mmc_block_rd> MMC_STAT error 0x%08x\n", status & MMC_STAT_ERRORS); + return -1; + } + debug(" End block_read: "); + mmc_print_stat(); + debug("\n"); + +// *(origdst + DOS_PART_MAGIC_OFFSET) = 0x55; +// *(origdst + DOS_PART_MAGIC_OFFSET + 1) = 0xaa; + + + return 0; +} + +int +/****************************************************/ +mmc_block_write(ulong dst, uchar *src, int len) +/****************************************************/ +{ + uchar *resp; + ushort argh, argl; + ulong status; + + if (len == 0) + { + return 0; + } + + debug("mmc_block_wr> dst 0x%08x src 0x%08x len %d\n", dst, (ulong)src, len); + + argh = len >> 16; + argl = len & 0xffff; + + /* set block len */ + resp = mmc_cmd(MMC_CMD_SET_BLOCKLEN, argh, argl, MMC_CMDAT_R1); + + /* send write command */ + argh = dst >> 16; + argl = dst & 0xffff; + MMC_STRPCL = MMC_STRPCL_STOP_CLK; + MMC_NOB = 1; + MMC_BLKLEN = len; + resp = mmc_cmd(MMC_CMD_WRITE_BLOCK, argh, argl, + MMC_CMDAT_R1|MMC_CMDAT_WRITE|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN); + + MMC_I_MASK = ~MMC_I_MASK_TXFIFO_WR_REQ; + while (len) + { + if (MMC_I_REG & MMC_I_REG_TXFIFO_WR_REQ) + { + int i, bytes = min(32,len); + + for (i=0; i MMC is ready.\n"); + + mmc_block_size = MMC_BLOCK_SIZE; + mmc_block_address = ~(mmc_block_size - 1); + + src -= CFG_MMC_BASE; + 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 */ + debug(" mmc_read> src 0x%08x dst 0x%08x end 0x%08x pstart 0x%08x pend 0x%08x astart 0x%08x aend 0x%08x\n", + src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); + if (part_start) + { + part_len = mmc_block_size - part_start; + debug(" mmc_read> ps src 0x%08x dst 0x%08x end 0x%08x pstart 0x%08x pend 0x%08x astart 0x%08x aend 0x%08x\n", + src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); + if ((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; + } + debug(" mmc_read> src 0x%08x dst 0x%08x end 0x%08x pstart 0x%08x pend 0x%08x astart 0x%08x aend 0x%08x\n", + src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); + for (; src < aligned_end; src += mmc_block_size, dst += mmc_block_size) + { + debug(" mmc_read> al src 0x%08x dst 0x%08x end 0x%08x pstart 0x%08x pend 0x%08x astart 0x%08x aend 0x%08x\n", + src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); + if ((mmc_block_read((uchar *)(dst), src, mmc_block_size)) < 0) + { + return -1; + } + } + debug(" mmc_read> src 0x%08x dst 0x%08x end 0x%08x pstart 0x%08x pend 0x%08x astart 0x%08x aend 0x%08x\n", + src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); + if (part_end && src < end) + { + debug(" mmc_read> pe src 0x%08x dst 0x%08x end 0x%08x pstart 0x%08x pend 0x%08x astart 0x%08x aend 0x%08x\n", + src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); + if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0) + { + return -1; + } + memcpy(dst, mmc_buf, part_end); + } + return 0; +} + +int +/****************************************************/ +mmc_write(uchar *src, ulong 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; + } + + debug(" mmc_write> MMC is ready.\n"); + + mmc_block_size = MMC_BLOCK_SIZE; + mmc_block_address = ~(mmc_block_size - 1); + + dst -= CFG_MMC_BASE; + end = dst + size; + part_start = ~mmc_block_address & dst; + part_end = ~mmc_block_address & end; + aligned_start = mmc_block_address & dst; + aligned_end = mmc_block_address & end; + + /* all block aligned accesses */ + debug("src 0x%08x dst 0x%08x end 0x%08x pstart 0x%08x pend 0x%08x astart 0x%08x aend 0x%08x\n", + src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); + if (part_start) + { + part_len = mmc_block_size - part_start; + debug(" mmc_write> ps: src 0x%08x dst 0x%08x end 0x%08x pstart 0x%08x pend 0x%08x astart 0x%08x aend 0x%08x\n", + (ulong)src, dst, end, part_start, part_end, aligned_start, aligned_end); + if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0) + { + return -1; + } + memcpy(mmc_buf+part_start, src, part_len); + if ((mmc_block_write(aligned_start, mmc_buf, mmc_block_size)) < 0) + { + return -1; + } + dst += part_len; + src += part_len; + } + debug(" mmc_write> src: 0x%08x dst 0x%08x end 0x%08x pstart 0x%08x pend 0x%08x astart 0x%08x aend 0x%08x\n", + src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); + for (; dst < aligned_end; src += mmc_block_size, dst += mmc_block_size) + { + debug(" mmc_write> al: src 0x%08x dst 0x%08x end 0x%08x pstart 0x%08x pend 0x%08x astart 0x%08x aend 0x%08x\n", + src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); + if ((mmc_block_write(dst, (uchar *)src, mmc_block_size)) < 0) + { + return -1; + } + } + debug(" mmc_write> src: 0x%08x dst 0x%08x end 0x%08x pstart 0x%08x pend 0x%08x astart 0x%08x aend 0x%08x\n", + src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); + if (part_end && dst < end) + { + debug(" mmc_write>pe src: 0x%08x dst 0x%08x end 0x%08x pstart 0x%08x pend 0x%08x astart 0x%08x aend 0x%08x\n", + src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); + if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0) + { + return -1; + } + memcpy(mmc_buf, src, part_end); + if ((mmc_block_write(aligned_end, mmc_buf, mmc_block_size)) < 0) + { + return -1; + } + } + return 0; +} + +static int current_state; /* djf */ +static u16 rca_addr; /* djf */ +#define SD_ST_IDLE 0 +#define SD_ST_READY 1 +#define SD_ST_IDENT 2 +#define SD_ST_STBY 3 +#define SD_ST_TRAN 4 + +int mmc_block_size; + +ulong +/****************************************************/ +mmc_bread(int dev_num, ulong blknr, ulong blkcnt, ulong *dst) +/****************************************************/ +{ +uchar *resp; + + debug("mmc_bread %08X, %08X, %08X\n",blknr,blkcnt,dst); + +/* int mmc_block_size = MMC_BLOCK_SIZE; */ + ulong src = blknr * mmc_block_size + CFG_MMC_BASE; + + /* select the card */ + resp = mmc_cmd(7,rca_addr, 0, MMC_CMDAT_R1|MMC_CMDAT_BUSY); + if(resp)current_state = SD_ST_TRAN; + + mmc_read(src, (uchar *)dst, blkcnt*mmc_block_size); + + /* deselect the card */ + resp = mmc_cmd(7,0, 0, MMC_CMDAT_R1|MMC_CMDAT_BUSY); + if(resp)current_state = SD_ST_STBY; + + return blkcnt; +} + +/* TRAN_SPEED Multipliers mantissa is fixed point 10x book value */ +u32 t_mantissa[] = {0,10,12,13, 15,20,25,30, 35,40,45,50, 55,60,70,80}; + +/* Card transfer data rate exponents */ +u32 tran_speed_exp[] = {10000,100000,1000000,1000000,0,0,0,0}; /* in HZ */ + +/* TACC multipliers */ +u32 tacc_speed_exp[] = {1,10,100,1000,10000,100000,1000000,10000000}; /* in ns */ + +static int is_sd; /* djf */ + +int +/****************************************************/ +mmc_init(int verbose) +/****************************************************/ +{ + int retries, rc = -ENODEV; + uchar *resp; + u32 tmp1,tmp2; + + sd_cid_t *sdcid; + mmc_cid_t *cid; + +#ifdef CONFIG_LUBBOCK + set_GPIO_mode( GPIO6_MMCCLK_MD ); + set_GPIO_mode( GPIO8_MMCCS0_MD ); +#endif +#ifdef CONFIG_GUMSTIK + set_GPIO_mode( GPIO6_MMCCLK_MD ); + set_GPIO_mode( GPIO8_MMCCS0_MD ); +#endif + + /* CKEN |= CKEN12_MMC; enable MMC unit clock from core. Off only for power down (enabled at reset) */ + + MMC_CLKRT = MMC_CLKRT_0_3125MHZ; /* 312 KHZ */ + MMC_RESTO = MMC_RES_TO_MAX; + MMC_SPI = MMC_SPI_DISABLE; + + /* Power On Reset Assumed for this test, the 1st command (55) prepends a 80 bit clock to reset card */ + retries = 3; + resp = -1; /* let the loop work at least once */ + while(retries-- && resp) { + /* djf */ + /* mmc_cmd(ushort cmd, ushort argh, ushort argl, ushort cmdat) */ + resp = mmc_cmd(55,SD_DEFAULT_RCA, 0, MMC_CMDAT_INIT|MMC_CMDAT_BUSY|MMC_CMDAT_R1); + if(resp) { + /* If this SD card was already initialized and moved to the STBY state, then 55 will */ + /* also cause a R1 reponse. Look at the card status word to find the current state */ + /* to see how to proceed. */ + debug("ACMD resp 0x%02x 0x%02x %02x %02x %02x %02x %02x\n", + resp[0], resp[1], resp[2], resp[3], resp[4], resp[5], resp[6]); + + is_sd = -1; + resp = mmc_cmd(41, 0x0010, 0, MMC_CMDAT_BUSY|MMC_CMDAT_R3); /* OCR, I Want 3.3V 0x0010 */ + if(resp) { + current_state = SD_ST_READY; + debug("sd_init> ocr resp 0x%02x 0x%02x %02x %02x %02x %02x %02x\n", + resp[0], resp[1], resp[2], resp[3], resp[4], resp[5], resp[6]); + + if(resp && (resp[4] & 0x80) ) { + debug("OCR = %02X%02X%02X\n",resp[3],resp[2],resp[1]); + break; + } + rca_addr = SD_DEFAULT_RCA; + } + } /* resp */ + udelay(200000); + } /* while */ + + if(resp == NULL) { + + /* Previously init'd SD (or MMC) card assumed for this test, use existing rca_addr & get_status_reg */ + retries = 3; + resp = -1; /* let the loop work at least once */ + while(retries-- && resp) { + resp = mmc_cmd(13, rca_addr, 0, MMC_CMDAT_BUSY|MMC_CMDAT_R1); + if(resp) { + /* If this SD card was already initialized and moved to the STBY state, then 55 will */ + /* also cause a R1 reponse. Look at the card status word to find the current state */ + /* to see how to proceed. */ + debug("ACMD resp 0x%02x 0x%02x %02x %02x %02x %02x %02x\n", + resp[0], resp[1], resp[2], resp[3], resp[4], resp[5], resp[6]); + current_state = (resp[2] >> 1) & 0xf; /* current state, read from card */ + break; + } /* resp */ + udelay(200000); + } /* while */ + + if(!resp)is_sd = 0; /* no SD response, try MMC */ + } /* resp */ + + /* djf end */ + if(!is_sd) { + printf("Trying MMC\n"); + retries = 3; + rca_addr = MMC_DEFAULT_RCA; + + /* 2.7 - 3.3V */ + resp = mmc_cmd(1, 0x00ff, 0x8000, MMC_CMDAT_BUSY|MMC_CMDAT_R3); + while (retries-- && resp && !(resp[4] & 0x80)) + { + debug(" mmc_init> resp 0x%02x 0x%02x\n", resp[0], resp[1]); /* was debug */ + udelay(200000); /* djf was 20000, now my JVC card detected 1st mmi */ + resp = mmc_cmd(1, 0x00ff, 0x8000, MMC_CMDAT_BUSY|MMC_CMDAT_R3); + } /* while */ + if(resp)current_state = SD_ST_READY; + + } /* !is_sd */ + + + if(current_state == SD_ST_READY) + { + /* try to get card id both sd & mmc */ + resp = mmc_cmd(2, 0, 0, MMC_CMDAT_BUSY|MMC_CMDAT_R2); /* djf MMC_CMDAT_BUSY */ + if (resp) + { + current_state = SD_ST_IDENT; /* ident */ + if(is_sd) { + + debug("sd cid %02x %02x %02x %02x %02x %02x %02x %02x\n", + resp[0], resp[1], resp[2], resp[3], resp[4], resp[5], resp[6], resp[7]); + + debug(" %02x %02x %02x %02x %02x %02x %02x %02x\n", + resp[8], resp[9], resp[10], resp[11], resp[12], resp[13], resp[14], resp[15]); + + sdcid = (sd_cid_t *)resp; /* avoid crc */ + if(verbose) { + printf("***********************************************\n"); + printf("* SD found. Card desciption is: *\n"); + printf("* MID = %02x OID=%c%c *\n", + sdcid->mid, sdcid->oid[1], sdcid->oid[0]); + printf("* Revision = %02x.%02x *\n", + sdcid->revl, sdcid->revr); + + /* sdcid->hwrev = sdcid->fwrev = 0; null terminate string */ + + printf("* Product Name = %c%c%c%c%c *\n",sdcid->name[4], + sdcid->name[3],sdcid->name[2],sdcid->name[1],sdcid->name[0]); + printf("* Serial Number = %02x%02x%02x%02x *\n", + sdcid->sn[3],sdcid->sn[2], sdcid->sn[1], sdcid->sn[0]); + printf("* Month = %2d Year = %d *\n", + (sdcid->mdt & 15),2000 + (sdcid->mdt >> 4) ); + printf("***********************************************\n"); + } /* verbose */ + + sprintf(mmc_dev.vendor,"Man %02x %c%c Snr %02x%02x%02x%02x", + sdcid->mid, sdcid->oid[1], sdcid->oid[0], + sdcid->sn[3], sdcid->sn[2], sdcid->sn[1],sdcid->sn[0]); + sprintf(mmc_dev.product,"%s",sdcid->name[4], + sdcid->name[3],sdcid->name[2],sdcid->name[1],sdcid->name[0]); + sprintf(mmc_dev.revision,"%02x.%02x",sdcid->revl, sdcid->revr); + } /* is_sd */ + else { + + cid = (mmc_cid_t *)resp; + if (verbose) + { + printf("***********************************************\n"); + printf("* MMC found. Card desciption is: *\n"); + printf("* Manufacturer ID = %02x%02x%02x *\n", + cid->id[2], cid->id[1], cid->id[0]); + printf("* HW/FW Revision = 0x%02x 0x%02x *\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[2], cid->sn[1], cid->sn[0]); + printf("* Month = %2d Year = %d *\n", + cid->month,1997 + cid->year); + printf("***********************************************\n"); + } /* verbose */ + + sprintf(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(mmc_dev.product,"%s",cid->name); + sprintf(mmc_dev.revision,"HW%02x FW%02x",cid->hwrev, cid->fwrev); + + } /* else !is_sd */ + } /* resp */ + } /* current_state == SD_ST_READY */ + + if(current_state == SD_ST_IDENT) { /* ident */ + /* SD you ask the card for an address */ + if(is_sd) { + resp = mmc_cmd(3, 0, 0, MMC_CMDAT_R1|MMC_CMDAT_BUSY); + if(resp) { + current_state = SD_ST_STBY; + /* printf("sd reladdr = %x %x %x %x %x %x %x %x\n", + resp[0],resp[1],resp[2],resp[3], resp[4], resp[5], resp[6], resp[7]); */ + rca_addr = resp[4] << 8; + rca_addr |= resp[3]; + } /* resp */ + } /* is_sd */ + else { /* MMC You tell the card the address to use */ + resp = mmc_cmd(MMC_CMD_SET_RCA, rca_addr, 0, MMC_CMDAT_R1); + if(resp)current_state = SD_ST_STBY; + debug("reladdr = %x %x\n",resp[0],resp[1]); + } + } /* current_state == SD_ST_READY */ + + if(current_state == SD_ST_STBY) { /* standby state */ + /* GET CSD */ + resp = mmc_cmd(MMC_CMD_SEND_CSD, rca_addr, 0, MMC_CMDAT_R2|MMC_CMDAT_BUSY); + if (resp) + { + if(is_sd) { + mmc_csd_t *csd = (mmc_csd_t *)resp; /* djf */ + /* printf("sizeof csd = %d\n",sizeof(mmc_csd_t)); */ + + /* memcpy(&mmc_csd, csd ,sizeof(mmc_csd_t)); */ + rc = 0; + mmc_ready = 1; + + tmp1 = (t_mantissa[((csd->taac>>3) & 0xf)] * tacc_speed_exp[(csd->taac & 7)])/10; + tmp2 = t_mantissa[((csd->tran_speed>>3) & 0xf)] * tran_speed_exp[(csd->tran_speed & 7)]; + + printf("CSD_STRUCTURE = %x, MMC_PROT=%x\n",csd->csd_structure,csd->spec_vers); + printf(" TAAC=%x (%dns), NSAC=%x\n",csd->taac,tmp1,csd->nsac); + printf(" TRAN = %x (%dbps)\n",csd->tran_speed,tmp2); + printf(" CCC=%x, READ_BL_LEN=%x (%d)\n",csd->ccc,csd->read_bl_len,(1<read_bl_len)); + printf(" C_SIZE=%x, C_SIZE_MULT=%d (%d)\n",csd->c_size, csd->c_size_mult1, + (4<c_size_mult1)); + printf(" TOTAL SD SIZE=%d\n",(1<read_bl_len) * csd->c_size * (4 << csd->c_size_mult1)); + + /* Correct the sizes to tell fat fs */ + mmc_block_size = (1<read_bl_len); + mmc_dev.lba = csd->c_size * (4 << csd->c_size_mult1); + + } /* is_sd */ + else { + mmc_csd_t *csd = (mmc_csd_t *)resp; /* djf */ + /* printf("sizeof csd = %d\n",sizeof(mmc_csd_t)); */ + + /* memcpy(&mmc_csd, csd ,sizeof(mmc_csd_t)); */ + rc = 0; + mmc_ready = 1; + + tmp1 = (t_mantissa[((csd->taac>>3) & 0xf)] * tacc_speed_exp[(csd->taac & 7)])/10; + tmp2 = t_mantissa[((csd->tran_speed>>3) & 0xf)] * tran_speed_exp[(csd->tran_speed & 7)]; + + printf("CSD_STRUCTURE = %x, MMC_PROT=%x\n",csd->csd_structure,csd->spec_vers); + printf(" TAAC=%x (%dns), NSAC=%x\n",csd->taac,tmp1,csd->nsac); + printf(" TRAN = %x (%dbps)\n",csd->tran_speed,tmp2); + printf(" CCC=%x, READ_BL_LEN=%x (%d)\n",csd->ccc,csd->read_bl_len,(1<read_bl_len)); + printf(" C_SIZE=%x, C_SIZE_MULT=%d (%d)\n",csd->c_size, csd->c_size_mult1, + (4<c_size_mult1)); + printf(" TOTAL MMC SIZE=%d\n",(1<read_bl_len) * csd->c_size * (4 << csd->c_size_mult1)); + + /* Correct the sizes to tell fat fs */ + mmc_block_size = (1<read_bl_len); + mmc_dev.lba = csd->c_size * (4 << csd->c_size_mult1); + } /* else !is_sd */ + } /* if resp */ + + } /* current_state == SD_ST_STBY */ + + +/* MMC_STRPCL = MMC_STRPCL_STOP_CLK; + MMC_CLKRT = 0; 20 MHz +*/ + MMC_STRPCL = MMC_STRPCL_STOP_CLK; + MMC_CLKRT = 0; /* 20 MHz */ + + /* fill in device description */ + mmc_dev.if_type = IF_TYPE_MMC; + mmc_dev.dev = 1; + mmc_dev.lun = 1; + mmc_dev.blksz = mmc_block_size; /* I dont think this is used */ + mmc_dev.part_type = PART_TYPE_DOS; + mmc_dev.type = DEV_TYPE_UNKNOWN; + mmc_dev.removable = 0; + mmc_dev.block_read = mmc_bread; + + fat_register_device(&mmc_dev,1); /* partitions start counting with 1 */ + + return rc; +} + +int +mmc_ident(block_dev_desc_t *dev) +{ + return 0; +} + +int +mmc2info(ulong addr) +{ + /* FIXME hard codes to 32 MB device */ + if (addr >= CFG_MMC_BASE && addr < CFG_MMC_BASE + 0x02000000) + { + return 1; + } + return 0; +} + +#endif --- a/disk/part.c 2004-04-18 13:39:39.000000000 -0400 +++ b/disk/part.c 2004-09-07 20:26:32.000000000 -0400 @@ -36,7 +36,8 @@ #if ((CONFIG_COMMANDS & CFG_CMD_IDE) || \ (CONFIG_COMMANDS & CFG_CMD_SCSI) || \ (CONFIG_COMMANDS & CFG_CMD_USB) || \ - (CONFIG_MMC) || (CONFIG_SYSTEMACE) ) + defined(CONFIG_MMC) || \ + defined(CONFIG_SYSTEMACE) ) /* ------------------------------------------------------------------------- */ /* @@ -125,6 +126,7 @@ #if ((CONFIG_COMMANDS & CFG_CMD_IDE) || \ (CONFIG_COMMANDS & CFG_CMD_SCSI) || \ (CONFIG_COMMANDS & CFG_CMD_USB) || \ + defined(CONFIG_MMC) || \ defined(CONFIG_SYSTEMACE) ) #if defined(CONFIG_MAC_PARTITION) || \ --- a/disk/part_dos.c 2004-02-23 11:11:34.000000000 -0500 +++ b/disk/part_dos.c 2004-09-07 20:28:28.000000000 -0400 @@ -38,7 +38,8 @@ #if ((CONFIG_COMMANDS & CFG_CMD_IDE) || \ (CONFIG_COMMANDS & CFG_CMD_SCSI) || \ (CONFIG_COMMANDS & CFG_CMD_USB) || \ - (CONFIG_SYSTEMACE)) && defined(CONFIG_DOS_PARTITION) + defined(CONFIG_MMC) || \ + defined(CONFIG_SYSTEMACE)) && defined(CONFIG_DOS_PARTITION) /* Convert char[4] in little endian format to the host format integer */ --- a/fs/fat/fat.c 2004-09-08 20:52:38.650767961 -0400 +++ b/fs/fat/fat.c 2004-09-07 20:29:11.000000000 -0400 @@ -90,7 +90,7 @@ } else { #if (CONFIG_COMMANDS & CFG_CMD_IDE) || (CONFIG_COMMANDS & CFG_CMD_SCSI) || \ - (CONFIG_COMMANDS & CFG_CMD_USB) + (CONFIG_COMMANDS & CFG_CMD_USB) || defined(CONFIG_MMC) disk_partition_t info; if(!get_partition_info(dev_desc, part_no, &info)) { part_offset = info.start; --- a/include/asm-arm/arch-pxa/mmc.h 2003-06-27 17:32:42.000000000 -0400 +++ b/include/asm-arm/arch-pxa/mmc.h 2004-09-08 18:36:12.000000000 -0400 @@ -184,14 +184,13 @@ dsr_imp:1, read_blk_misalign:1, write_blk_misalign:1, - read_bl_partial:1; - - ushort read_bl_len:4, + read_bl_partial:1, + read_bl_len:4, ccc:12; - uchar tran_speed; - uchar nsac; - uchar taac; - uchar rsvd1:2, + uchar tran_speed, + nsac, + taac, + rsvd1:2, spec_vers:4, csd_structure:2; } mmc_csd_t; --- a/include/asm-arm/arch-pxa/mmcsd.h 1969-12-31 19:00:00.000000000 -0500 +++ b/include/asm-arm/arch-pxa/mmcsd.h 2004-09-08 18:34:20.000000000 -0400 @@ -0,0 +1,254 @@ +/* + * linux/drivers/mmc/mmc_pxa.h + * + * Author: Vladimir Shebordaev, Igor Oblakov + * Copyright: MontaVista Software Inc. + * + * $Id: mmc_pxa.h,v 0.3.1.6 2002/09/25 19:25:48 ted Exp ted $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __MMC_PXA_P_H__ +#define __MMC_PXA_P_H__ + +/* PXA-250 MMC controller registers */ + +/* MMC_STRPCL */ +#define MMC_STRPCL_STOP_CLK (0x0001UL) +#define MMC_STRPCL_START_CLK (0x0002UL) + +/* MMC_STAT */ +#define MMC_STAT_END_CMD_RES (0x0001UL << 13) +#define MMC_STAT_PRG_DONE (0x0001UL << 12) +#define MMC_STAT_DATA_TRAN_DONE (0x0001UL << 11) +#define MMC_STAT_CLK_EN (0x0001UL << 8) +#define MMC_STAT_RECV_FIFO_FULL (0x0001UL << 7) +#define MMC_STAT_XMIT_FIFO_EMPTY (0x0001UL << 6) +#define MMC_STAT_RES_CRC_ERROR (0x0001UL << 5) +#define MMC_STAT_SPI_READ_ERROR_TOKEN (0x0001UL << 4) +#define MMC_STAT_CRC_READ_ERROR (0x0001UL << 3) +#define MMC_STAT_CRC_WRITE_ERROR (0x0001UL << 2) +#define MMC_STAT_TIME_OUT_RESPONSE (0x0001UL << 1) +#define MMC_STAT_READ_TIME_OUT (0x0001UL) + +#define MMC_STAT_ERRORS (MMC_STAT_RES_CRC_ERROR|MMC_STAT_SPI_READ_ERROR_TOKEN\ + |MMC_STAT_CRC_READ_ERROR|MMC_STAT_TIME_OUT_RESPONSE\ + |MMC_STAT_READ_TIME_OUT|MMC_STAT_CRC_WRITE_ERROR) + +/* MMC_CLKRT */ +#define MMC_CLKRT_20MHZ (0x0000UL) +#define MMC_CLKRT_10MHZ (0x0001UL) +#define MMC_CLKRT_5MHZ (0x0002UL) +#define MMC_CLKRT_2_5MHZ (0x0003UL) +#define MMC_CLKRT_1_25MHZ (0x0004UL) +#define MMC_CLKRT_0_625MHZ (0x0005UL) +#define MMC_CLKRT_0_3125MHZ (0x0006UL) + +/* MMC_SPI */ +#define MMC_SPI_DISABLE (0x00UL) +#define MMC_SPI_EN (0x01UL) +#define MMC_SPI_CS_EN (0x01UL << 2) +#define MMC_SPI_CS_ADDRESS (0x01UL << 3) +#define MMC_SPI_CRC_ON (0x01UL << 1) + +/* MMC_CMDAT */ +#define MMC_CMDAT_MMC_DMA_EN (0x0001UL << 7) +#define MMC_CMDAT_INIT (0x0001UL << 6) +#define MMC_CMDAT_BUSY (0x0001UL << 5) +#define MMC_CMDAT_STREAM (0x0001UL << 4) +#define MMC_CMDAT_BLOCK (0x0000UL << 4) +#define MMC_CMDAT_WRITE (0x0001UL << 3) +#define MMC_CMDAT_READ (0x0000UL << 3) +#define MMC_CMDAT_DATA_EN (0x0001UL << 2) +#define MMC_CMDAT_R1 (0x0001UL) +#define MMC_CMDAT_R2 (0x0002UL) +#define MMC_CMDAT_R3 (0x0003UL) + +/* djf */ +#define MMC_CMDAT_R6 (0x0004UL) + +/* MMC_RESTO */ +#define MMC_RES_TO_MAX (0x007fUL) /* [6:0] */ + +/* MMC_RDTO */ +#define MMC_READ_TO_MAX (0x0ffffUL) /* [15:0] */ + +/* MMC_BLKLEN */ +#define MMC_BLK_LEN_MAX (0x03ffUL) /* [9:0] */ + +/* MMC_PRTBUF */ +#define MMC_PRTBUF_BUF_PART_FULL (0x01UL) +#define MMC_PRTBUF_BUF_FULL (0x00UL ) + +/* MMC_I_MASK */ +#define MMC_I_MASK_TXFIFO_WR_REQ (0x01UL << 6) +#define MMC_I_MASK_RXFIFO_RD_REQ (0x01UL << 5) +#define MMC_I_MASK_CLK_IS_OFF (0x01UL << 4) +#define MMC_I_MASK_STOP_CMD (0x01UL << 3) +#define MMC_I_MASK_END_CMD_RES (0x01UL << 2) +#define MMC_I_MASK_PRG_DONE (0x01UL << 1) +#define MMC_I_MASK_DATA_TRAN_DONE (0x01UL) +#define MMC_I_MASK_ALL (0x07fUL) + + +/* MMC_I_REG */ +#define MMC_I_REG_TXFIFO_WR_REQ (0x01UL << 6) +#define MMC_I_REG_RXFIFO_RD_REQ (0x01UL << 5) +#define MMC_I_REG_CLK_IS_OFF (0x01UL << 4) +#define MMC_I_REG_STOP_CMD (0x01UL << 3) +#define MMC_I_REG_END_CMD_RES (0x01UL << 2) +#define MMC_I_REG_PRG_DONE (0x01UL << 1) +#define MMC_I_REG_DATA_TRAN_DONE (0x01UL) +#define MMC_I_REG_ALL (0x007fUL) + +/* MMC_CMD */ +#define MMC_CMD_INDEX_MAX (0x006fUL) /* [5:0] */ +#define CMD(x) (x) + +#define SD_DEFAULT_RCA 0 +#define MMC_DEFAULT_RCA 1 + +#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_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 + +#define MMC_R1_IDLE_STATE 0x01 +#define MMC_R1_ERASE_STATE 0x02 +#define MMC_R1_ILLEGAL_CMD 0x04 +#define MMC_R1_COM_CRC_ERR 0x08 +#define MMC_R1_ERASE_SEQ_ERR 0x01 +#define MMC_R1_ADDR_ERR 0x02 +#define MMC_R1_PARAM_ERR 0x04 + +#define MMC_R1B_WP_ERASE_SKIP 0x0002 +#define MMC_R1B_ERR 0x0004 +#define MMC_R1B_CC_ERR 0x0008 +#define MMC_R1B_CARD_ECC_ERR 0x0010 +#define MMC_R1B_WP_VIOLATION 0x0020 +#define MMC_R1B_ERASE_PARAM 0x0040 +#define MMC_R1B_OOR 0x0080 +#define MMC_R1B_IDLE_STATE 0x0100 +#define MMC_R1B_ERASE_RESET 0x0200 +#define MMC_R1B_ILLEGAL_CMD 0x0400 +#define MMC_R1B_COM_CRC_ERR 0x0800 +#define MMC_R1B_ERASE_SEQ_ERR 0x1000 +#define MMC_R1B_ADDR_ERR 0x2000 +#define MMC_R1B_PARAM_ERR 0x4000 + +typedef struct mmc_cid +{ +/* FIXME: BYTE_ORDER */ + uchar year:4, + month:4; + uchar sn[3]; + uchar fwrev:4, + hwrev:4; + uchar name[6]; + uchar id[3]; +} mmc_cid_t; + +typedef struct sd_cid +{ + u16 mdt:12; + uchar res:4; + uchar sn[4]; + uchar revr:4, + revl:4; + uchar name[5]; + uchar oid[2]; + uchar mid:8; +} sd_cid_t; + + +typedef struct 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, + read_bl_len:4, + ccc:12; + uchar tran_speed, + nsac, + taac, + rsvd1:2, + spec_vers:4, + csd_structure:2; +} mmc_csd_t; + +typedef struct sd_csd +{ + uchar ecc:2, + file_format:2, + tmp_write_protect:1, + perm_write_protect:1, + copy:1, + file_format_grp:1; + uint64_t rsvd3:5, + write_bl_partial:1, + write_bl_len:4, + r2w_factor:3, + default_ecc:2, + wp_grp_enable:1, + wp_grp_size:7, + sector_size:7, + erase_blk_en:1, + 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, + read_bl_len:4, + ccc:12; + uchar tran_speed, + nsac, + taac, + rsvd1:2, + spec_vers:4, + csd_structure:2; +} sd_csd_t; + + +#endif /* __MMC_PXA_P_H__ */ --- a/include/configs/gumstik.h 2004-09-08 20:52:38.652767636 -0400 +++ b/include/configs/gumstik.h 2004-09-06 17:12:37.000000000 -0400 @@ -72,6 +72,8 @@ * parameters at all! Do not get confused by them so. */ +#define CONFIG_DOS_PARTITION + #define CONFIG_BOOTARGS "console=ttyS0,115200n8 root=1f02 rootfstype=jffs2 reboot=cold,hard" #define CONFIG_BOOTCOMMAND "fsload a2000000 boot/uImage;bootm 0xa2000000" #define CONFIG_BOOTDELAY 2 /* in seconds */