Index: drivers/mmc/mmc_core.c =================================================================== RCS file: /cvs/linux/kernel/drivers/mmc/mmc_core.c,v retrieving revision 1.11 diff -u -U4 -r1.11 mmc_core.c --- drivers/mmc/mmc_core.c 3 Jun 2003 13:04:46 -0000 1.11 +++ drivers/mmc/mmc_core.c 20 Jun 2003 14:01:01 -0000 @@ -39,12 +39,14 @@ static struct mmc_dev g_mmc_dev; static struct proc_dir_entry *proc_mmc_dir; #ifdef CONFIG_MMC_DEBUG -int g_mmc_debug = CONFIG_MMC_DEBUG_VERBOSE; +int g_mmc_debug = 3; EXPORT_SYMBOL(g_mmc_debug); #endif +//#include "/home/luc/kernel/arch/arm/mach-sa1100/h3600_asic_mmc.c" + /************************************************************************** * Debugging functions **************************************************************************/ @@ -208,9 +224,11 @@ r1->status = PARSE_U32(buf,1); DEBUG(2,"cmd=%d status=%08x", r1->cmd, r1->status); - if (R1_STATUS(r1->status)) { + /* SD card return in upper status the cardid */ + + if (R1_STATUS(r1->status) && request->cmd!=MMC_SET_RELATIVE_ADDR) { if ( r1->status & R1_OUT_OF_RANGE ) return MMC_ERROR_OUT_OF_RANGE; if ( r1->status & R1_ADDRESS_ERROR ) return MMC_ERROR_ADDRESS; if ( r1->status & R1_BLOCK_LEN_ERROR ) return MMC_ERROR_BLOCK_LEN; if ( r1->status & R1_ERASE_SEQ_ERROR ) return MMC_ERROR_ERASE_SEQ; @@ -235,9 +253,9 @@ return 0; } -int mmc_unpack_cid( struct mmc_request *request, struct mmc_cid *cid ) +int mmc_unpack_cid_mmc( struct mmc_request *request, struct mmc_cid *cid ) { u8 *buf = request->response; int i; @@ -260,8 +278,50 @@ if ( buf[0] != 0x3f ) return MMC_ERROR_HEADER_MISMATCH; return 0; } +int mmc_unpack_cid_sd( struct mmc_request *request, struct mmc_cid *cid ) +{ + u8 *buf = request->response; + int i; + + if ( request->result ) return request->result; + + /* + * Packed CID Format + * + * Field|size| slice | byte | Description + * + * MID | 8 | [127:120] | [ 0: 0] | Manufacture ID [$02 = Toshiba ] + * OID | 16 | [119:104] | [ 1: 2] | Manufacture ID [$544D "TM" = Toshiba ] + * PNM | 40 | [103: 64] | [ 3: 7] | Product Name Manufacture [SD044 | SD128 | SD256 for toshiba sdcard ] + * PRV | 8 | [ 63: 56] | [ 8: 8] | Product Revision + * PSN | 32 | [ 55: 24] | [ 9:12] | Product Serial Number + * - | 4 | [ 23: 20] | [13:13] | All zeros + * MDT | 12 | [ 19: 8] | [13:14] | Manufacture Date [11:8] Month / [19:12] Year + 2000 + * CRC | 7 | [ 7: 1] | [15:15] | CRC + * - | 1 | [ 0: 0] | [15:15] | 1 + */ + + cid->mid = buf[1]; + cid->oid = PARSE_U16(buf,2); + for ( i = 0 ; i < 5 ; i++ ) + cid->pnm[i] = buf[4+i]; + cid->pnm[5] = 0; + cid->prv = buf[9]; + cid->psn = PARSE_U32(buf,10); + cid->mdt = (buf[14]<<4)|buf[15]; + + DEBUG(2,"mid=%d oid=%d pnm=%s prv=%d.%d psn=%08x mdt=%d/%d", + cid->mid, cid->oid, cid->pnm, + (cid->prv>>4), (cid->prv&0xf), + cid->psn, (cid->mdt>>4), (cid->mdt&0xf)+2000); + + if ( buf[0] != 0x3f ) return MMC_ERROR_HEADER_MISMATCH; + if ( !(buf[16]&1) ) return MMC_ERROR_CARD_ECC_FAILED; + return 0; +} + int mmc_unpack_r3( struct mmc_request *request, struct mmc_response_r3 *r3 ) { u8 *buf = request->response; Index: drivers/mmc/mmc_core.h =================================================================== RCS file: /cvs/linux/kernel/drivers/mmc/mmc_core.h,v retrieving revision 1.4 diff -u -U4 -r1.4 mmc_core.h --- drivers/mmc/mmc_core.h 29 Nov 2002 20:00:08 -0000 1.4 +++ drivers/mmc/mmc_core.h 20 Jun 2003 14:01:01 -0000 @@ -46,9 +46,10 @@ char * mmc_result_to_string( int ); int mmc_unpack_csd( struct mmc_request *request, struct mmc_csd *csd ); int mmc_unpack_r1( struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state ); -int mmc_unpack_cid( struct mmc_request *request, struct mmc_cid *cid ); +int mmc_unpack_cid_mmc( struct mmc_request *request, struct mmc_cid *cid ); +int mmc_unpack_cid_sd( struct mmc_request *request, struct mmc_cid *cid ); int mmc_unpack_r3( struct mmc_request *request, struct mmc_response_r3 *r3 ); void mmc_send_cmd( struct mmc_dev *dev, int cmd, u32 arg, u16 nob, u16 block_len, enum mmc_rsp_t rtype ); Index: drivers/mmc/mmc_media.h =================================================================== RCS file: /cvs/linux/kernel/drivers/mmc/mmc_media.h,v retrieving revision 1.4 diff -u -U4 -r1.4 mmc_media.h --- drivers/mmc/mmc_media.h 29 Nov 2002 20:00:08 -0000 1.4 +++ drivers/mmc/mmc_media.h 20 Jun 2003 14:01:01 -0000 @@ -35,13 +35,15 @@ #define MMC_MAX_SLOTS 2 #define MMC_SLOT_FLAG_INSERT (1<<0) #define MMC_SLOT_FLAG_EJECT (1<<1) +#define MMC_SLOT_FLAG_SDCARD (1<<2) struct mmc_media_driver; struct mmc_slot { - int id; /* Card index */ + int id; /* Card index */ + int addr; /* Sd address or id+1 for MMC (shift << 16 is already done) */ /* Card specific information */ struct mmc_cid cid; struct mmc_csd csd; Index: drivers/mmc/mmc_protocol.c =================================================================== RCS file: /cvs/linux/kernel/drivers/mmc/mmc_protocol.c,v retrieving revision 1.4 diff -u -U4 -r1.4 mmc_protocol.c --- drivers/mmc/mmc_protocol.c 2 Apr 2003 16:45:37 -0000 1.4 +++ drivers/mmc/mmc_protocol.c 20 Jun 2003 14:01:01 -0000 @@ -63,8 +63,9 @@ DEBUG(2,"slot=%d", slot); /* Fix the clock rate */ rate = mmc_tran_speed(dev->slot[slot].csd.tran_speed); + DEBUG(2,"==> mmc_configure_card (rate= %d) ",rate); if ( rate < MMC_CLOCK_SLOW ) rate = MMC_CLOCK_SLOW; if ( rate > MMC_CLOCK_FAST ) rate = MMC_CLOCK_FAST; @@ -139,9 +140,9 @@ mmc_fix_request_block_size( dev ); switch ( slot->state ) { case CARD_STATE_STBY: - mmc_simple_cmd(dev, MMC_SELECT_CARD, ID_TO_RCA(slot->id) << 16, RESPONSE_R1B ); + mmc_simple_cmd(dev, MMC_SELECT_CARD, slot->addr, RESPONSE_R1B ); break; case CARD_STATE_TRAN: mmc_simple_cmd(dev, MMC_SET_BLOCKLEN, t->block_len, RESPONSE_R1 ); break; @@ -216,9 +217,9 @@ DEBUG(2,"first=%d",first); if ( first ) { - mmc_simple_cmd(dev, MMC_SEND_STATUS, ID_TO_RCA(slot->id) << 16, RESPONSE_R1 ); + mmc_simple_cmd(dev, MMC_SEND_STATUS, slot->addr, RESPONSE_R1 ); return NULL; } switch (dev->request.cmd) { @@ -287,59 +288,124 @@ DEBUG(2,""); if ( first ) { mmc_simple_cmd(dev, MMC_GO_IDLE_STATE, 0, RESPONSE_NONE); + dev->sdrive->ocr = 0x20000; return NULL; } switch (dev->request.cmd) { case MMC_GO_IDLE_STATE: /* No response to parse */ + DEBUG(0,"==> MMC_GO_IDLE_STATE"); if ( (dev->sdrive->flags & MMC_SDFLAG_VOLTAGE )) DEBUG(0,"error - current driver doesn't do OCR"); - mmc_simple_cmd(dev, MMC_SEND_OP_COND, dev->sdrive->ocr, RESPONSE_R3); + + DEBUG(0,"==> before sending MMC_APP_CMD "); + mmc_simple_cmd(dev, MMC_APP_CMD, 0, RESPONSE_R1); + DEBUG(0,"==> after sending MMC_APP_CMD "); + DEBUG(0,"<== MMC_GO_IDLE_STATE"); + break; + + case MMC_APP_CMD: + DEBUG(0,"==> MMC_APP_CMD "); + retval = mmc_unpack_r1(&dev->request,&r1,slot->state); + if ( retval ) { + DEBUG(0,"failed MMC_APP_CMD error=%d (%s)", + retval, mmc_result_to_string(retval)); + return mmc_cim_default_state; + } + mmc_simple_cmd(dev, SD_APP_OP_COND, dev->sdrive->ocr, RESPONSE_R3); + DEBUG(0,"<== MMC_APP_CMD "); + break; + + case SD_APP_OP_COND: + DEBUG(0,"==> SD_APP_OP_COND "); + retval = mmc_unpack_r3(&dev->request, &r3); + if ( retval ) { + DEBUG(0,"failed SD_APP_OP_COND error=%d (%s) - could be MMC card", + retval, mmc_result_to_string(retval)); + DEBUG(2,"dev->sdrive->ocr = %x",dev->sdrive->ocr) + mmc_simple_cmd(dev, MMC_SEND_OP_COND, 0x00ffc000, RESPONSE_R3); + } + else { + DEBUG(0,"==> SD_APP_OP_COND 1"); + DEBUG(2,"read ocr value = 0x%08x", r3.ocr); + + if (!(r3.ocr & MMC_CARD_BUSY)) { + DEBUG(0,"==> SD_APP_OP_COND / card is busy wait until retry => resend "); + /* Need to add an time (or loop limit) */ + dev->sdrive->ocr = r3.ocr; + mmc_simple_cmd(dev, MMC_APP_CMD, 0, RESPONSE_R3); + } + else { + DEBUG(0,"==> SD_APP_OP_COND / CARD_STATE_READY "); + /* This seems to be a sd card */ + slot->flags |= MMC_SLOT_FLAG_SDCARD; + slot->state = CARD_STATE_READY; + mmc_simple_cmd(dev, MMC_ALL_SEND_CID, 0, RESPONSE_R2_CID); + DEBUG(0,"==> MMC_ALL_SEND_CID "); + } + } + DEBUG(0,"<== SD_APP_OP_COND "); break; case MMC_SEND_OP_COND: + DEBUG(0,"==> MMC_SEND_OP_COND "); retval = mmc_unpack_r3(&dev->request, &r3); if ( retval ) { - DEBUG(0,"failed SEND_OP_COND error=%d (%s) - could be SD card", + DEBUG(0,"failed MMC_SEND_OP_COND error=%d (%s) - could be SD card but sdcard init failed. Aborting!", retval, mmc_result_to_string(retval)); return mmc_cim_default_state; } DEBUG(2,"read ocr value = 0x%08x", r3.ocr); if (!(r3.ocr & MMC_CARD_BUSY)) { + DEBUG(0," MMC_SEND_OP_COND Busy retrying ..."); mmc_simple_cmd(dev, MMC_SEND_OP_COND, dev->sdrive->ocr, RESPONSE_R3); } else { slot->state = CARD_STATE_READY; mmc_simple_cmd(dev, MMC_ALL_SEND_CID, 0, RESPONSE_R2_CID); } + DEBUG(0,"<== MMC_SEND_OP_COND "); break; case MMC_ALL_SEND_CID: - retval = mmc_unpack_cid( &dev->request, &slot->cid ); + DEBUG(0,"==> MMC_ALL_SEND_CID ()"); + + if (slot->flags & MMC_SLOT_FLAG_SDCARD) + retval = mmc_unpack_cid_sd( &dev->request, &slot->cid ); + else + retval = mmc_unpack_cid_mmc( &dev->request, &slot->cid ); if ( retval ) { DEBUG(0,"unable to ALL_SEND_CID error=%d (%s)", retval, mmc_result_to_string(retval)); return mmc_cim_default_state; } slot->state = CARD_STATE_IDENT; mmc_simple_cmd(dev, MMC_SET_RELATIVE_ADDR, ID_TO_RCA(slot->id) << 16, RESPONSE_R1); + DEBUG(0,"<== MMC_ALL_SEND_CID ()"); break; case MMC_SET_RELATIVE_ADDR: + DEBUG(0,"==> MMC_SET_RELATIVE_ADDR "); retval = mmc_unpack_r1(&dev->request,&r1,slot->state); if ( retval ) { DEBUG(0, "unable to SET_RELATIVE_ADDR error=%d (%s)", retval, mmc_result_to_string(retval)); return mmc_cim_default_state; } + if (slot->flags & MMC_SLOT_FLAG_SDCARD) + slot->addr = r1.status&0xFFFF0000; /* sd addr is in the upper part */ + else + slot->addr = ID_TO_RCA(slot->id); /* for MMC, this is slot +1 */ slot->state = CARD_STATE_STBY; - mmc_simple_cmd(dev, MMC_SEND_CSD, ID_TO_RCA(slot->id) << 16, RESPONSE_R2_CSD); + mmc_simple_cmd(dev, MMC_SEND_CSD, slot->addr, RESPONSE_R2_CSD); + DEBUG(0,"<== MMC_SET_RELATIVE_ADDR "); break; case MMC_SEND_CSD: + DEBUG(0,"<== MMC_SEND_CSD () "); retval = mmc_unpack_csd(&dev->request, &slot->csd); if ( retval ) { DEBUG(0, "unable to SEND_CSD error=%d (%s)", retval, mmc_result_to_string(retval)); @@ -349,8 +415,9 @@ DEBUG(0, "driver doesn't support setting DSR"); // mmc_simple_cmd(dev, MMC_SET_DSR, 0, RESPONSE_NONE); } mmc_configure_card( dev, 0 ); + DEBUG(0,"==> MMC_SEND_CSD () "); return mmc_cim_default_state; default: DEBUG(0, "error! Illegal last cmd %d", dev->request.cmd); @@ -426,4 +493,9 @@ g_single_card = sf; sf = g_single_card(dev,1); } } + + + + + Index: drivers/mmc/mmc_protocol.h =================================================================== RCS file: /cvs/linux/kernel/drivers/mmc/mmc_protocol.h,v retrieving revision 1.2 diff -u -U4 -r1.2 mmc_protocol.h --- drivers/mmc/mmc_protocol.h 13 Jun 2002 21:06:08 -0000 1.2 +++ drivers/mmc/mmc_protocol.h 20 Jun 2003 14:01:01 -0000 @@ -85,8 +85,10 @@ /* class 8 */ #define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */ #define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1b */ +#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */ + /* Don't change the order of these; they are used in dispatch tables */ enum mmc_rsp_t { RESPONSE_NONE = 0, RESPONSE_R1 = 1, @@ -163,9 +165,9 @@ u16 oid; u8 pnm[7]; // Product name (we null-terminate) u8 prv; u32 psn; - u8 mdt; + u16 mdt; }; struct mmc_csd { u8 csd_structure; Index: include/linux/mmc/mmc_protocol.h =================================================================== RCS file: /cvs/linux/kernel/include/linux/mmc/mmc_protocol.h,v retrieving revision 1.3 diff -u -U4 -r1.3 mmc_protocol.h --- include/linux/mmc/mmc_protocol.h 2 Apr 2003 16:47:30 -0000 1.3 +++ include/linux/mmc/mmc_protocol.h 20 Jun 2003 14:01:16 -0000 @@ -85,8 +85,12 @@ /* class 8 */ #define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */ #define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1b */ + /* Advanced Command (used by sd card) */ +#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */ + + /* Don't change the order of these; they are used in dispatch tables */ enum mmc_rsp_t { RESPONSE_NONE = 0, RESPONSE_R1 = 1,