--- 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/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,8 @@ } else { #if (CONFIG_COMMANDS & CFG_CMD_IDE) || (CONFIG_COMMANDS & CFG_CMD_SCSI) || \ - (CONFIG_COMMANDS & CFG_CMD_USB) || defined(CONFIG_SYSTEMACE) + (CONFIG_COMMANDS & CFG_CMD_USB) || defined(CONFIG_SYSTEMACE) || \ + (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;