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 %lx src %lx 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<bytes; i++) { MMC_TXFIFO = *src++; } if (bytes < 32) { MMC_PRTBUF = MMC_PRTBUF_BUF_PART_FULL; } len -= bytes; } status = MMC_STAT; if (status & MMC_STAT_ERRORS) { printf("MMC_STAT error %lx\n", status); return -1; } } MMC_I_MASK = ~MMC_I_MASK_DATA_TRAN_DONE; while (!(MMC_I_REG & MMC_I_REG_DATA_TRAN_DONE)); MMC_I_MASK = ~MMC_I_MASK_PRG_DONE; while (!(MMC_I_REG & MMC_I_REG_PRG_DONE)); status = MMC_STAT; if (status & MMC_STAT_ERRORS) { printf("MMC_STAT error %lx\n", status); return -1; } return 0; }
int emmc_boot(void) { int ret; current_boot = EMMC_BOOT; ctl_num = 0; sd_init(); REG_MSC_CLKRT(ctl_num) = 1; REG_MSC_LPM(ctl_num) = 1; /* cmd12 reset when we reading or writing from the card, send this cmd */ mmc_cmd(12, 0, 0x1, MSC_CMDAT_RESPONSE_R1); mmc_cmd(0, 0xf0f0f0f0, 0x80, MSC_CMDAT_RESPONSE_NONE); REG_MSC_BLKLEN(ctl_num) = 0x200; REG_MSC_NOB(ctl_num) = (SPL_SIZE + redundancy_size) / 512; mmc_cmd(0, 0xfffffffa, ((MSC_CMDAT_INIT) | (MSC_CMDAT_EXP_BOOT_ACK) | (MSC_CMDAT_BOOT_MODE_A) | (MSC_CMDAT_DATA_EN)), MSC_CMDAT_RESPONSE_NONE); ret = mmc_block_readp(SPL_SIZE + redundancy_size, (u32 *)start_addr); if(!ret){ mmc_cmd(0, 0, 0x0, MSC_CMDAT_RESPONSE_NONE); if (!(REG32(start_addr) == 0x4d53504c)){ return sd_boot(1); } return xfer_d2i(start_addr + jump_offset, SPL_SIZE); }else{ return error_handler(current_boot); } }
/* init mmc/sd card we assume that the card is in the slot */ static int mmc_init(unsigned int msc_clkrt_val) { int retries, ret; u8 *resp; //unsigned int msc_clk_div = (__cpm_get_pllout())/24000000; __msc_reset(); mmc_init_gpio(); REG_MSC_IMASK = 0xffff; REG_MSC_IREG = 0xffff; REG_MSC_CLKRT = 6; //200k /* just for reading and writing, suddenly it was reset, and the power of sd card was not broken off */ resp = mmc_cmd(12, 0, 0x41, MSC_CMDAT_RESPONSE_R1); /* reset */ resp = mmc_cmd(0, 0, 0x80, 0); resp = mmc_cmd(8, 0x1aa, 0x1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(55, 0, 0x1, MSC_CMDAT_RESPONSE_R1); if(resp[5] == 0x37) { resp = mmc_cmd(41, 0x40ff8000, 0x3, MSC_CMDAT_RESPONSE_R3); if(resp[5] == 0x3f) ret = sd_init(msc_clkrt_val); return ret; } ret = mmc_found(msc_clkrt_val); return ret; }
int /****************************************************/ mmc_block_read(uchar *dst, ulong src, ulong len) /****************************************************/ { uchar *resp; ushort argh, argl; ulong status; if (len == 0) { return 0; } debug("mmc_block_rd dst %lx src %lx 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 */ argh = src >> 16; argl = src & 0xffff; MMC_STRPCL = MMC_STRPCL_STOP_CLK; MMC_RDTO = 0xffff; MMC_NOB = 1; MMC_BLKLEN = len; resp = mmc_cmd(MMC_CMD_READ_BLOCK, argh, argl, MMC_CMDAT_R1|MMC_CMDAT_READ|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN); MMC_I_MASK = ~MMC_I_MASK_RXFIFO_RD_REQ; while (len) { if (MMC_I_REG & MMC_I_REG_RXFIFO_RD_REQ) { *dst++ = MMC_RXFIFO; len--; } status = MMC_STAT; if (status & MMC_STAT_ERRORS) { printf("MMC_STAT error %lx\n", status); return -1; } } 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_STAT error %lx\n", status); return -1; } return 0; }
int sd_found(void) { u8 *resp; u32 cardaddr, timeout = 1000; DBG("sd_found\n"); resp = mmc_cmd(55, 0, 0x1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(41, 0x40ff8000, 0x3, MSC_CMDAT_RESPONSE_R3); while (timeout-- && !(resp[4] & 0x80)) { xmdelay(10); resp = mmc_cmd(55, 0, 0x1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(41, 0x40ff8000, 0x3, MSC_CMDAT_RESPONSE_R3); } if (!(resp[4] & 0x80)) return 1; resp = mmc_cmd(2, 0, 0x2, MSC_CMDAT_RESPONSE_R2); resp = mmc_cmd(3, 0, 0x6, MSC_CMDAT_RESPONSE_R6); cardaddr = (resp[4] << 8) | resp[3]; rca = cardaddr << 16; REG_MSC_CLKRT(ctl_num) = 1; resp = mmc_cmd(7, rca, 0x1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(55, rca, 0x1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(6, 0, 0x1, MSC_CMDAT_RESPONSE_R1); return 0; }
static void sd_init(void) { int retries; u8 *resp; unsigned int cardaddr; resp = mmc_cmd(41, 0x40ff8000, 0x3, MSC_CMDAT_RESPONSE_R3); retries = 500; while (retries-- && resp && !(resp[4] & 0x80)) { resp = mmc_cmd(55, 0, 0x1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(41, 0x40ff8000, 0x3, MSC_CMDAT_RESPONSE_R3); udelay(1000); udelay(1000); } if (resp[4] & 0x80) serial_puts("SD init ok\n"); else serial_puts("SD init fail\n"); /* try to get card id */ resp = mmc_cmd(2, 0, 0x2, MSC_CMDAT_RESPONSE_R2); resp = mmc_cmd(3, 0, 0x6, MSC_CMDAT_RESPONSE_R1); cardaddr = (resp[4] << 8) | resp[3]; rca = cardaddr << 16; resp = mmc_cmd(9, rca, 0x2, MSC_CMDAT_RESPONSE_R2); sd2_0 = (resp[14] & 0xc0) >> 6; REG_MSC_CLKRT = 2; //2 is ok ,dont't grater resp = mmc_cmd(7, rca, 0x41, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(55, rca, 0x1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(6, 0x2, 0x401, MSC_CMDAT_RESPONSE_R1); }
static void sd_init(void) { int retries, wait; u8 *resp; unsigned int cardaddr; serial_puts("SD card found!\n"); resp = mmc_cmd(41, 0x40ff8000, 0x3, MSC_CMDAT_RESPONSE_R3); retries = 100; while (retries-- && resp && !(resp[4] & 0x80)) { resp = mmc_cmd(55, 0, 0x1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(41, 0x40ff8000, 0x3, MSC_CMDAT_RESPONSE_R3); sd_mdelay(10); } if (resp[4] & 0x80) serial_puts("MMC/SD init ok\n"); else serial_puts("SD init fail\n"); /* try to get card id */ resp = mmc_cmd(2, 0, 0x2, MSC_CMDAT_RESPONSE_R2); resp = mmc_cmd(3, 0, 0x6, MSC_CMDAT_RESPONSE_R1); cardaddr = (resp[4] << 8) | resp[3]; rca = cardaddr << 16; resp = mmc_cmd(9, rca, 0x2, MSC_CMDAT_RESPONSE_R2); highcap = (resp[14] & 0xc0) >> 6; REG_MSC_CLKRT = 0; resp = mmc_cmd(7, rca, 0x41, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(55, rca, 0x1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(6, 0x2, 0x401, MSC_CMDAT_RESPONSE_R1); }
/* init mmc/sd card we assume that the card is in the slot */ static int mmc_init(void) { int retries; u8 *resp; __gpio_as_msc(); __msc_reset(); MMC_IRQ_MASK(); REG_CPM_MSCCDR = __cpm_get_pllout2()%24000000 ? __cpm_get_pllout2()/24000000 : __cpm_get_pllout2()/24000000 - 1; REG_CPM_CPCCR |= CPM_CPCCR_CE; REG_MSC_CLKRT = 7; //250k REG_MSC_RDTO = 0xffffffff; resp = mmc_cmd(12, 0, 0x41, MSC_CMDAT_RESPONSE_R1); /* reset */ resp = mmc_cmd(0, 0, 0x80, 0); resp = mmc_cmd(8, 0x1aa, 0x1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(55, 0, 0x1, MSC_CMDAT_RESPONSE_R1); if(!(resp[0] & 0x20) && (resp[5] != 0x37)) { resp = mmc_cmd(1, 0x40ff8000, 0x3, MSC_CMDAT_RESPONSE_R3); retries = 500; while (retries-- && resp && !(resp[4] & 0x80)) { resp = mmc_cmd(1, 0x40300000, 0x3, MSC_CMDAT_RESPONSE_R3); udelay(1000); udelay(1000); } if ((resp[4] & 0x80 ) == 0x80) serial_puts("MMC init ok\n"); else serial_puts("MMC init fail\n"); if((resp[4] & 0x60) == 0x40) highcap = 1; else highcap = 0; /* try to get card id */ resp = mmc_cmd(2, 0, 0x2, MSC_CMDAT_RESPONSE_R2); resp = mmc_cmd(3, 0x10, 0x1, MSC_CMDAT_RESPONSE_R1); REG_MSC_CLKRT = 2; /* 16/1 MHz */ resp = mmc_cmd(7, 0x10, 0x1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(6, 0x3b70101, 0x441, MSC_CMDAT_RESPONSE_R1); while(!(REG_MSC_STAT & MSC_STAT_PRG_DONE)) ; REG_MSC_IREG |= MSC_IREG_PRG_DONE; } else sd_init(); return 0; }
int init_MMC(int max_tries) { int i,tries,c; tries=0; output_low(ChipSel); /// reset chip hardware !!! required delay_ms(100); for(tries=0; tries < max_tries; tries++) { output_high(ChipSel); /// reset chip hardware !!! required delay_ms(20); for(i=0;i<20;i++) SPI_READ(0xFF); // min 80 clocks to get MMC ready output_low(ChipSel); /// !!! required delay_ms(20); c=mmc_cmd(0x40,0x00000000,128,0x01,0x99); if (c==0x01) break; } if(tries >= max_tries) { output_high(ChipSel); return MMC_INIT_RESET_ERR; } /// now try to switch to idle mode /// Note: cmd1(idle) is the only command allowed after a cmd0(reset) for(tries=0; tries < max_tries; tries++) { c=mmc_cmd(0x41,0x00000000,128,0x00,0x99); if (c==0x00) break; } output_high(ChipSel); if(tries >= max_tries) return MMC_INIT_IDLE_ERR; return MMC_NO_ERR; }
static int mmc_acmd(unsigned long cmd, unsigned long arg, void *resp, unsigned long flags) { unsigned long aresp[4]; int ret = 0; ret = mmc_cmd(MMC_CMD_APP_CMD, 0, aresp, MMC_RSP_PRESENT); if (ret) return ret; if ((aresp[0] & (ILLEGAL_COMMAND | APP_CMD)) != APP_CMD) return -ENODEV; ret = mmc_cmd(cmd, arg, resp, flags); return ret; }
/* init mmc/sd card we assume that the card is in the slot */ static int mmc_init(void) { int retries; u8 *resp; __gpio_as_msc(); __msc_reset(); MMC_IRQ_MASK(); __cpm_select_msc_clk(0,1); REG_MSC_CLKRT = 7; //250k resp = mmc_cmd(12, 0, 0x41, MSC_CMDAT_RESPONSE_R1); /* reset */ resp = mmc_cmd(0, 0, 0x80, 0); resp = mmc_cmd(8, 0x1aa, 0x1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(55, 0, 0x1, MSC_CMDAT_RESPONSE_R1); if(!(resp[0] & 0x20) && (resp[5] != 0x37)) { resp = mmc_cmd(1, 0xff8000, 0x3, MSC_CMDAT_RESPONSE_R3); retries = 500; while (retries-- && resp && !(resp[4] & 0x80)) { resp = mmc_cmd(1, 0x40300000, 0x3, MSC_CMDAT_RESPONSE_R3); udelay(1000); udelay(1000); } if (resp[4]== 0x80) serial_puts("MMC init ok\n"); else serial_puts("MMC init fail\n"); /* try to get card id */ resp = mmc_cmd(2, 0, 0x2, MSC_CMDAT_RESPONSE_R2); resp = mmc_cmd(3, 0x10, 0x1, MSC_CMDAT_RESPONSE_R1); REG_MSC_CLKRT = 2; /* 16/1 MHz */ resp = mmc_cmd(7, 0x10, 0x1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(6, 0x3b70101, 0x401, MSC_CMDAT_RESPONSE_R1); } else sd_init(); return 0; }
/* init mmc/sd card we assume that the card is in the slot */ int mmc_init(void) { int retries, wait; u8 *resp; __gpio_as_msc(); __msc_reset(); MMC_IRQ_MASK(); REG_MSC_CLKRT = 7; //250k REG_MSC_RDTO = 0xffffffff; serial_puts("\n\nMMC/SD INIT\n"); /* reset */ resp = mmc_cmd(0, 0, 0x80, 0); resp = mmc_cmd(8, 0x1aa, 0x1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(55, 0, 0x1, MSC_CMDAT_RESPONSE_R1); if(!(resp[0] & 0x20) && (resp[5] != 0x37)) { serial_puts("MMC card found!\n"); resp = mmc_cmd(1, 0x40ff8000, 0x3, MSC_CMDAT_RESPONSE_R3); retries = 100; while (retries-- && resp && !(resp[4] & 0x80)) { resp = mmc_cmd(1, 0x40300000, 0x3, MSC_CMDAT_RESPONSE_R3); sd_mdelay(10); } if ((resp[4] & 0x80) == 0x80) serial_puts("MMC init ok\n"); else serial_puts("MMC init fail\n"); if((resp[4] & 0x60) == 0x40) highcap = 1; else highcap = 0; /* try to get card id */ resp = mmc_cmd(2, 0, 0x2, MSC_CMDAT_RESPONSE_R2); resp = mmc_cmd(3, 0x10, 0x1, MSC_CMDAT_RESPONSE_R1); REG_MSC_CLKRT = 0; /* 16/1 MHz */ resp = mmc_cmd(7, 0x10, 0x1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(6, 0x3b70101, 0x441, MSC_CMDAT_RESPONSE_R1); } else sd_init(); return 0; }
int mmc_found(void) { u8 *resp; u32 timeout = 100; DBG("mmc_found\n"); if (ctl_num == 1) return 1; resp = mmc_cmd(1, 0x40ff8000, 0x3, MSC_CMDAT_RESPONSE_R3); while (timeout-- && !(resp[4] & 0x80)) { xmdelay(10); resp = mmc_cmd(1, 0x40ff8000, 0x3, MSC_CMDAT_RESPONSE_R3); } if (!(resp[4] & 0x80)) return 1; resp = mmc_cmd(2, 0, 0x2, MSC_CMDAT_RESPONSE_R2); resp = mmc_cmd(3, 0x10, 0x1, MSC_CMDAT_RESPONSE_R1); REG_MSC_CLKRT(ctl_num) = 1; resp = mmc_cmd(7, 0x10, 0x1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(6, 0x3b70001, 0x41, MSC_CMDAT_RESPONSE_R1); wait_prog_done(); return 0; }
static int sd_init(unsigned int msc_clkrt_val) { int retries, wait; // int rca; u8 *resp; unsigned int cardaddr; serial_puts("SD card found!\n"); resp = mmc_cmd(55, 0, 0x1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(41, 0x40ff8000, 0x3, MSC_CMDAT_RESPONSE_R3); retries = 500; while (retries-- && resp && !(resp[4] & 0x80)) { resp = mmc_cmd(55, 0, 0x1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(41, 0x40ff8000, 0x3, MSC_CMDAT_RESPONSE_R3); sd_mdelay(10); } if ((resp[4] & 0x80) == 0x80) serial_puts("SD init ok\n"); else { serial_puts("SD init fail\n"); return -1; } /* try to get card id */ resp = mmc_cmd(2, 0, 0x2, MSC_CMDAT_RESPONSE_R2); serial_puts("CID="); serial_dump_data(resp, 15); resp = mmc_cmd(3, 0, 0x6, MSC_CMDAT_RESPONSE_R1); cardaddr = (resp[4] << 8) | resp[3]; rca = cardaddr << 16; resp = mmc_cmd(9, rca, 0x2, MSC_CMDAT_RESPONSE_R2); highcap = (resp[14] & 0xc0) >> 6; REG_MSC_CLKRT = msc_clkrt_val; resp = mmc_cmd(7, rca, 0x41, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(55, rca, 0x1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(6, BUS_WIDTH, 0x1 | (BUS_WIDTH << 9), MSC_CMDAT_RESPONSE_R1); return 0; }
static int mmc_acmd(unsigned long cmd, unsigned long arg, void *resp, unsigned long flags) { unsigned long aresp[4]; int ret; /* * Seems like the APP_CMD part of an ACMD has 64 cycles max * latency even though the ACMD part doesn't. This isn't * entirely clear in the SD Card spec, but some cards refuse * to work if we attempt to use 5 cycles max latency here... */ ret = mmc_cmd(MMC_CMD_APP_CMD, 0, aresp, R1 | NCR | (flags & OPEN_DRAIN)); if (ret) return ret; if ((aresp[0] & (R1_ILLEGAL_COMMAND | R1_APP_CMD)) != R1_APP_CMD) return -ENODEV; ret = mmc_cmd(cmd, arg, resp, flags); return ret; }
int mmc_block_read(u32 size, u32 *dst) { u8 *resp; u32 nob, cnt, stat; resp = mmc_cmd(16, 0x200, 0x1, MSC_CMDAT_RESPONSE_R1); REG_MSC_BLKLEN(ctl_num) = 0x200; REG_MSC_NOB(ctl_num) = size / 512; resp = mmc_cmd(18, 0x0, 0x9, MSC_CMDAT_RESPONSE_R1); //more than 16 nob = size / 64; for (; nob > 0; nob--) { while(1){ stat = REG_MSC_STAT(ctl_num); if (stat & (MSC_STAT_TIME_OUT_READ | MSC_STAT_CRC_READ_ERROR)) { goto err; } if(!(stat & MSC_STAT_DATA_FIFO_EMPTY)) break; } cnt = 16; //16 words while (cnt--) { while (!(REG_MSC_IREG(ctl_num) & MSC_IREG_RXFIFO_RD_REQ)) ; *dst = REG_MSC_RXFIFO(ctl_num); if (size - (nob * 64) >= redundancy_size) dst++; } } resp = mmc_cmd(12, 0, 0x1, MSC_CMDAT_RESPONSE_R1); return 0; err: return 1; }
static int mmc_found(unsigned int msc_clkrt_val) { int retries; u8 *resp; int ocr; serial_puts("MMC card found!\n"); resp = mmc_cmd(1, 0x40ff8000, 0x3, MSC_CMDAT_RESPONSE_R3); retries = 1000; while (retries-- && resp && !(resp[4] & 0x80)) { resp = mmc_cmd(1, 0x40300000, 0x3, MSC_CMDAT_RESPONSE_R3); ocr = (resp[4] << 24) | (resp[3] << 16) | (resp[2] << 8) | resp[1]; serial_puts(" ocr = "); serial_put_hex(ocr); sd_mdelay(10); } sd_mdelay(10); if ((resp[4] & 0x80 )== 0x80) serial_puts("MMC init ok\n"); else { serial_puts("MMC init fail\n"); return -1; } if((resp[4] & 0x60 ) == 0x40) highcap = 1; else highcap =0; /* try to get card id */ resp = mmc_cmd(2, 0, 0x2, MSC_CMDAT_RESPONSE_R2); serial_puts("CID="); serial_dump_data(resp, 15); resp = mmc_cmd(3, 0x10, 0x1, MSC_CMDAT_RESPONSE_R1); REG_MSC_CLKRT = msc_clkrt_val; /* 16/1 MHz */ resp = mmc_cmd(7, 0x10, 0x1, MSC_CMDAT_RESPONSE_R1); if(BUS_WIDTH == 2) { resp = mmc_cmd(6, 0x3b70101, 0x441, MSC_CMDAT_RESPONSE_R1); } else if(BUS_WIDTH == 0) { resp = mmc_cmd(6, 0x3b30001, 0x41, MSC_CMDAT_RESPONSE_R1); } return 0; }
int ReadSector( int32 sector, char *buff) { int r1; long i,iw; /// allows large gt 255 buff size addressing output_low(ChipSel); delay_ms(1); TRACE1("\r\nRead sector# %lu.", sector); r1=mmc_cmd(0x51,sector<<9,16,0x00,0x40); if(r1 == 0x40) { output_high(ChipSel); return MMC_READ_INVALID_ERR; } else if(r1 != 0x00) { output_high(ChipSel); return MMC_READ_GEN_ERR; } //Get token for(iw=0;iw<1024;iw++) { r1=SPI_READ(0xFF); if (r1==0xFE) break; } //Get token error. It may be caused by improper MMC reset if(r1 != 0xFE) { output_high(ChipSel); return MMC_READ_TOKEN_ERR; } #ifdef SPEED_BOOST FSR0 = buff; // Set start address in index register for (i=0;i<512;i++) { // POSTINC0 = SPI_READ(0xFF); // Write data to Buffer and increase address WRITE_SSP(0xFF); WAIT_FOR_SSP(); POSTINC0 = READ_SSP(); } #else //Read the whole sector (512 bytes) for (i=0;i<512;i++) buff[i]=SPI_READ(0xFF); #endif SPI_READ(0xFF); // read crc SPI_READ(0xFF); #ifdef TRACE_READ_SECTOR fprintf(debug, "\r\nRead sector #%lu:", sector); for(i = 0; i<512; i++) { if(i%16 == 0) fprintf(debug, "\r\n%04LX - ", i); r1 = *buff; if(r1 < ' ' || r1 > 'z') r1 = '.'; fprintf(debug, "%02X%c ", *buff++, r1); } #endif output_high(ChipSel); return MMC_NO_ERR; }
static int mmc_block_writem(u32 src, u32 num, u8 *dst) { u8 *resp; u32 stat, timeout, data, cnt, wait, nob, i, j; u32 *wbuf = (u32 *)dst; resp = mmc_cmd(16, 0x200, 0x1, MSC_CMDAT_RESPONSE_R1); REG_MSC_BLKLEN = 0x200; REG_MSC_NOB = num / 512; if (highcap) resp = mmc_cmd(25, src, 0x19 | (BUS_WIDTH << 9), MSC_CMDAT_RESPONSE_R1); // for sdhc card else resp = mmc_cmd(25, src * 512, 0x19 | (BUS_WIDTH << 9), MSC_CMDAT_RESPONSE_R1); nob = num / 512; timeout = 0x3ffffff; //serial_puts("nob ==w===");serial_put_hex(nob); //serial_dump_data(dst, 16); for (i = 0; i < nob; i++) { timeout = 0x3FFFFFF; while (timeout) { timeout--; stat = REG_MSC_STAT; if (stat & (MSC_STAT_CRC_WRITE_ERROR | MSC_STAT_CRC_WRITE_ERROR_NOSTS)) return -1; else if (!(stat & MSC_STAT_DATA_FIFO_FULL)) { /* Ready to write data */ break; } wait = 336; while (wait--) ; } if (!timeout) return -1; /* Write data to TXFIFO */ cnt = 128; while (cnt) { //stat = REG_MSC_STAT; //serial_puts("stat ==write===");serial_put_hex(stat); while(!(REG_MSC_IREG & MSC_IREG_TXFIFO_WR_REQ)) ; for (j=0; j<16; j++) { //serial_put_hex(*wbuf); REG_MSC_TXFIFO = *wbuf++; cnt--; } } } #if 0 while (!(REG_MSC_IREG & MSC_IREG_DATA_TRAN_DONE)) ; REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE; /* clear status */ resp = mmc_cmd(12, 0, 0x441, MSC_CMDAT_RESPONSE_R1); while (!(REG_MSC_IREG & MSC_IREG_PRG_DONE)) ; REG_MSC_IREG = MSC_IREG_PRG_DONE; /* clear status */ #else while (!(REG_MSC_IREG & MSC_IREG_DATA_TRAN_DONE)) ; REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE; /* clear status */ while (!(REG_MSC_STAT & MSC_STAT_PRG_DONE)) ; REG_MSC_IREG = MSC_IREG_PRG_DONE; /* clear status */ resp = mmc_cmd(12, 0, 0x441, MSC_CMDAT_RESPONSE_R1); do { resp = mmc_cmd(13, rca, 0x1, MSC_CMDAT_RESPONSE_R1); // for sdhc card } while(!(resp[2] & 0x1)); //wait the card is ready for data #endif jz_mmc_stop_clock(); //return src+nob; return 0; }
static int mmc_block_readm(u32 src, u32 num, u8 *dst) { u8 *resp; u32 stat, timeout, data, cnt, wait, nob; resp = mmc_cmd(16, 0x200, 0x401, MSC_CMDAT_RESPONSE_R1); REG_MSC_BLKLEN = 0x200; REG_MSC_NOB = num / 512; if (highcap) resp = mmc_cmd(18, src, 0x10409, MSC_CMDAT_RESPONSE_R1); // for sdhc card else resp = mmc_cmd(18, src * 512, 0x10409, MSC_CMDAT_RESPONSE_R1); nob = num / 512; //serial_puts("nob ==r===");serial_put_hex(nob); //serial_puts("src ==r===");serial_put_hex(src); for (nob; nob >= 1; nob--) { timeout = 0x7ffffff; while (timeout) { timeout--; stat = REG_MSC_STAT; if (stat & MSC_STAT_TIME_OUT_READ) { serial_puts("\n MSC_STAT_TIME_OUT_READ\n\n"); return -1; } else if (stat & MSC_STAT_CRC_READ_ERROR) { serial_puts("\n MSC_STAT_CRC_READ_ERROR\n\n"); return -1; } else if (!(stat & MSC_STAT_DATA_FIFO_EMPTY)) { /* Ready to read data */ break; } wait = 336; while (wait--) ; } if (!timeout) { serial_puts("\n mmc/sd read timeout\n"); return -1; } /* Read data from RXFIFO. It could be FULL or PARTIAL FULL */ cnt = 128; while (cnt) { while (cnt && (REG_MSC_STAT & MSC_STAT_DATA_FIFO_EMPTY)) ; cnt --; data = REG_MSC_RXFIFO; { *dst++ = (u8)(data >> 0); *dst++ = (u8)(data >> 8); *dst++ = (u8)(data >> 16); *dst++ = (u8)(data >> 24); } } } #if defined(MSC_STAT_AUTO_CMD_DONE) while(!(REG_MSC_STAT & MSC_STAT_AUTO_CMD_DONE)); #else resp = mmc_cmd(12, 0, 0x41, MSC_CMDAT_RESPONSE_R1); while (!(REG_MSC_STAT & MSC_STAT_DATA_TRAN_DONE)); #endif jz_mmc_stop_clock(); return 0; }
static unsigned long mmc_bread(int dev, unsigned long start, lbaint_t blkcnt, unsigned long *buffer) { int ret, i = 0; unsigned long resp[4]; unsigned long card_status, data; unsigned long wordcount; u32 status; if (blkcnt == 0) return 0; pr_debug("mmc_bread: dev %d, start %lx, blkcnt %lx\n", dev, start, blkcnt); /* Put the device into Transfer state */ ret = mmc_cmd(MMC_CMD_SELECT_CARD, mmc_rca << 16, resp, R1 | NCR); if (ret) goto fail; /* Set block length */ ret = mmc_cmd(MMC_CMD_SET_BLOCKLEN, mmc_blkdev.blksz, resp, R1 | NCR); if (ret) goto fail; pr_debug("MCI_DTOR = %08lx\n", mmci_readl(DTOR)); for (i = 0; i < blkcnt; i++, start++) { ret = mmc_cmd(MMC_CMD_READ_SINGLE_BLOCK, start * mmc_blkdev.blksz, resp, (R1 | NCR | TRCMD_START | TRDIR_READ | TRTYP_BLOCK)); if (ret) goto fail; ret = -EIO; wordcount = 0; do { do { status = mmci_readl(SR); if (status & (ERROR_FLAGS | MMCI_BIT(OVRE))) goto fail; } while (!(status & MMCI_BIT(RXRDY))); if (status & MMCI_BIT(RXRDY)) { data = mmci_readl(RDR); /* pr_debug("%x\n", data); */ *buffer++ = data; wordcount++; } } while(wordcount < (mmc_blkdev.blksz / 4)); pr_debug("mmc: read %u words, waiting for BLKE\n", wordcount); do { status = mmci_readl(SR); } while (!(status & MMCI_BIT(BLKE))); putc('.'); } out: /* Put the device back into Standby state */ mmc_cmd(MMC_CMD_SELECT_CARD, 0, resp, NCR); return i; fail: mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 | NCR); printf("mmc: bread failed, card status = %08x\n", card_status); goto out; }
static int mmc_block_writem(u32 src, u32 num, u8 *dst) { u8 *resp; u32 stat, timeout, cnt, nob, sorm; u32 *wbuf = (u32 *)dst; resp = mmc_cmd(16, 0x200, 0x401, MSC_CMDAT_RESPONSE_R1); REG_MSC_BLKLEN = 0x200; REG_MSC_NOB = num / 512; nob = num / 512; if (nob == 1) { if (highcap) resp = mmc_cmd(24, src, 0x419, MSC_CMDAT_RESPONSE_R1); else resp = mmc_cmd(24, src * 512, 0x419, MSC_CMDAT_RESPONSE_R1); sorm = 0; } else { if (highcap) resp = mmc_cmd(25, src, 0x419, MSC_CMDAT_RESPONSE_R1); // for sdhc card else resp = mmc_cmd(25, src * 512, 0x419, MSC_CMDAT_RESPONSE_R1); sorm = 1; } for (nob; nob >= 1; nob--) { timeout = 0x3FFFFFF; while (timeout) { timeout--; stat = REG_MSC_STAT; if (stat & (MSC_STAT_CRC_WRITE_ERROR | MSC_STAT_CRC_WRITE_ERROR_NOSTS)) { serial_puts("\n MSC_STAT_CRC_WRITE_ERROR\n\n"); return -1; } else if (!(stat & MSC_STAT_DATA_FIFO_FULL)) { /* Ready to write data */ break; } udelay(1); } if (!timeout) return -1; /* Write data to TXFIFO */ cnt = 128; while (cnt) { while (REG_MSC_STAT & MSC_STAT_DATA_FIFO_FULL) ; REG_MSC_TXFIFO = *wbuf++; cnt--; } } if (sorm) resp = mmc_cmd(12, 0, 0x41, MSC_CMDAT_RESPONSE_R1); while (!(REG_MSC_STAT & MSC_STAT_DATA_TRAN_DONE)) ; REG_MSC_IREG |= MSC_IREG_DATA_TRAN_DONE; while (!(REG_MSC_STAT & MSC_STAT_PRG_DONE)) ; REG_MSC_IREG |= MSC_IREG_PRG_DONE; jz_mmc_stop_clock(); return 0; }
static int mmc_block_readm(u32 src, u32 num, u8 *dst) { u8 *resp; u32 stat, timeout, data, cnt, nob, sorm; resp = mmc_cmd(16, 0x200, 0x401, MSC_CMDAT_RESPONSE_R1); REG_MSC_BLKLEN = 0x200; REG_MSC_NOB = num / 512; nob = num / 512; if (nob == 1) { if (highcap) resp = mmc_cmd(17, src, 0x409, MSC_CMDAT_RESPONSE_R1); else resp = mmc_cmd(17, src * 512, 0x409, MSC_CMDAT_RESPONSE_R1); sorm = 0; } else { if (highcap) resp = mmc_cmd(18, src, 0x409, MSC_CMDAT_RESPONSE_R1); else resp = mmc_cmd(18, src * 512, 0x409, MSC_CMDAT_RESPONSE_R1); sorm = 1; } for (nob; nob >= 1; nob--) { timeout = 0x3ffffff; while (timeout) { timeout--; stat = REG_MSC_STAT; if (stat & MSC_STAT_TIME_OUT_READ) { serial_puts("\n MSC_STAT_TIME_OUT_READ\n\n"); return -1; } else if (stat & MSC_STAT_CRC_READ_ERROR) { serial_puts("\n MSC_STAT_CRC_READ_ERROR\n\n"); return -1; } else if (!(stat & MSC_STAT_DATA_FIFO_EMPTY)) { /* Ready to read data */ break; } udelay(1); } if (!timeout) { serial_puts("\n mmc/sd read timeout\n"); return -1; } /* Read data from RXFIFO. It could be FULL or PARTIAL FULL */ cnt = 128; while (cnt) { while (cnt && (REG_MSC_STAT & MSC_STAT_DATA_FIFO_EMPTY)) ; cnt --; data = REG_MSC_RXFIFO; { *dst++ = (u8)(data >> 0); *dst++ = (u8)(data >> 8); *dst++ = (u8)(data >> 16); *dst++ = (u8)(data >> 24); } } } if (sorm) resp = mmc_cmd(12, 0, 0x41, MSC_CMDAT_RESPONSE_R1); while (!(REG_MSC_STAT & MSC_STAT_DATA_TRAN_DONE)) ; REG_MSC_IREG |= MSC_IREG_DATA_TRAN_DONE; jz_mmc_stop_clock(); return 0; }
static unsigned long mmc_bwrite(int dev, unsigned long start, lbaint_t blkcnt, const void *buffer) { int ret, i = 0; unsigned long resp[4]; unsigned long card_status; const __u8 *buf = buffer; __u32 status; __u16 data_ctl = 0; __u16 dma_cfg = 0; if (blkcnt == 0) return 0; debug("mmc_bwrite: dev %d, start %lx, blkcnt %lx\n", dev, start, blkcnt); /* Force to use 512-byte block,because a lot of code depends on this */ data_ctl |= 9 << 4; data_ctl &= ~DTX_DIR; bfin_write_SDH_DATA_CTL(data_ctl); dma_cfg |= WDSIZE_32 | RESTART | DMAEN; /* FIXME later */ bfin_write_SDH_DATA_TIMER(0xFFFFFFFF); for (i = 0; i < blkcnt; ++i, ++start) { bfin_write_DMA_START_ADDR(buf + i * mmc_blkdev.blksz); bfin_write_DMA_X_COUNT(mmc_blkdev.blksz / 4); bfin_write_DMA_X_MODIFY(4); bfin_write_DMA_CONFIG(dma_cfg); bfin_write_SDH_DATA_LGTH(mmc_blkdev.blksz); /* Put the device into Transfer state */ ret = mmc_cmd(MMC_CMD_SELECT_CARD, mmc_rca << 16, resp, MMC_RSP_R1); if (ret) { printf("MMC_CMD_SELECT_CARD failed\n"); goto out; } /* Set block length */ ret = mmc_cmd(MMC_CMD_SET_BLOCKLEN, mmc_blkdev.blksz, resp, MMC_RSP_R1); if (ret) { printf("MMC_CMD_SET_BLOCKLEN failed\n"); goto out; } ret = mmc_cmd(MMC_CMD_WRITE_SINGLE_BLOCK, start * mmc_blkdev.blksz, resp, MMC_RSP_R1); if (ret) { printf("MMC_CMD_WRITE_SINGLE_BLOCK failed\n"); goto out; } bfin_write_SDH_DATA_CTL(bfin_read_SDH_DATA_CTL() | DTX_DMA_E | DTX_E); do { udelay(1); status = bfin_read_SDH_STATUS(); } while (!(status & (DAT_BLK_END | DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | TX_UNDERRUN))); if (status & (DAT_TIME_OUT | DAT_CRC_FAIL | TX_UNDERRUN)) { bfin_write_SDH_STATUS_CLR(DAT_TIMEOUT_STAT | DAT_CRC_FAIL_STAT | TX_UNDERRUN_STAT); goto write_error; } else { bfin_write_SDH_STATUS_CLR(DAT_BLK_END_STAT | DAT_END_STAT); mmc_cmd(MMC_CMD_SELECT_CARD, 0, resp, 0); } } out: return i; write_error: mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, MMC_RSP_R1); printf("mmc: bwrite failed, status = %08x, card status = %08lx\n", status, card_status); goto out; }
int /****************************************************/ mmc_init(int verbose) /****************************************************/ { int retries, rc = -ENODEV; uchar *resp; #ifdef CONFIG_LUBBOCK set_GPIO_mode( GPIO6_MMCCLK_MD ); set_GPIO_mode( GPIO8_MMCCS0_MD ); #endif CKEN |= CKEN12_MMC; /* enable MMC unit clock */ mmc_csd.c_size = 0; MMC_CLKRT = MMC_CLKRT_0_3125MHZ; MMC_RESTO = MMC_RES_TO_MAX; MMC_SPI = MMC_SPI_DISABLE; /* reset */ retries = 10; resp = mmc_cmd(0, 0, 0, 0); resp = mmc_cmd(1, 0x00ff, 0xc000, MMC_CMDAT_INIT|MMC_CMDAT_BUSY|MMC_CMDAT_R3); while (retries-- && resp && !(resp[4] & 0x80)) { debug("resp %x %x\n", resp[0], resp[1]); udelay(50); resp = mmc_cmd(1, 0x00ff, 0xff00, MMC_CMDAT_BUSY|MMC_CMDAT_R3); } /* try to get card id */ resp = mmc_cmd(2, 0, 0, MMC_CMDAT_R2); if (resp) { /* TODO configure mmc driver depending on card attributes */ mmc_cid_t *cid = (mmc_cid_t *)resp; if (verbose) { 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); } /* fill in device description */ mmc_dev.if_type = IF_TYPE_MMC; mmc_dev.dev = 0; mmc_dev.lun = 0; mmc_dev.type = 0; /* FIXME fill in the correct size (is set to 32MByte) */ mmc_dev.blksz = 512; 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]); sprintf(mmc_dev.product,"%s",cid->name); sprintf(mmc_dev.revision,"%x %x",cid->hwrev, cid->fwrev); mmc_dev.removable = 0; mmc_dev.block_read = mmc_bread; /* 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 (resp) { mmc_csd_t *csd = (mmc_csd_t *)resp; memcpy(&mmc_csd, csd, sizeof(csd)); rc = 0; mmc_ready = 1; /* FIXME add verbose printout for csd */ } } MMC_CLKRT = 0; /* 20 MHz */ resp = mmc_cmd(7, MMC_DEFAULT_RCA, 0, MMC_CMDAT_R1); fat_register_device(&mmc_dev,1); /* partitions start counting with 1 */ return rc; }
int WriteSector(int32 sector, char *buff) { int r1; int16 i; TRACE1("\r\nWriteSector(%lu).", sector); if(sector == 0) //never write sector 0 return MMC_WRITE_SEC0_ERR; output_low(ChipSel); delay_ms(1); r1=mmc_cmd(0x58,sector<<9,16,0x00,0x40); if(r1 == 0x40) { output_high(ChipSel); return MMC_WRITE_INVALID_ERR; } else if(r1 != 0x00) { output_high(ChipSel); return MMC_WRITE_GEN_ERR; } SPI_READ(0xFE); #ifdef SPEED_BOOST FSR0 = buff; // Set start address in index register for (i=0;i<512;i++) { // SPI_READ(POSTINC0); /// send payload WRITE_SSP(POSTINC0); WAIT_FOR_SSP(); } #else for (i=0;i < 512;i++) { SPI_READ(buff[i]); /// send payload } #endif SPI_READ(0xFF); // send dummy chcksum SPI_READ(0xFF); r1=SPI_READ(0xFF); for( i=0;i<0x0fff;i++) { r1=SPI_READ(0xFF);// digest prior operation if (r1!=0x00) break; } #ifdef TRACE_WRITE_SECTOR fprintf(debug, "\r\nWrite sector #%lu:", sector); for(i = 0; i<512; i++) { if(i%16 == 0) fprintf(debug, "\r\n%04LX - ", i); r1 = *buff; if(r1 < ' ' || r1 > 'z') r1 = '.'; fprintf(debug, "%02X%c ", *buff++, r1); } #endif output_high(ChipSel); return MMC_NO_ERR; }
int sd_boot(num) { u8 *resp; u32 ret = 0; u32 clk_set = 0, clkrt = 0; DBG("sd_boot\n"); current_boot = SD_BOOT; ctl_num = num; if (ctl_num == 1) REG_CPM_CLKGR &= ~(1 << 11); sd_init(); clk_set = jz_extal / 2; while (200000 < clk_set) { clkrt++; clk_set >>= 1; } if (clkrt > 7) { clkrt = 7; } REG_MSC_CLKRT(ctl_num) = clkrt; REG_MSC_LPM(ctl_num) = 1; /* cmd12 reset when we reading or writing from the card, send this cmd */ resp = mmc_cmd(12, 0, 0x41, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(0, 0, 0x80, MSC_CMDAT_RESPONSE_NONE); resp = mmc_cmd(8, 0x1aa, 0x1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(55, 0, 0x1, MSC_CMDAT_RESPONSE_R1); if (resp[0] & 0x20){ if (resp[5] == 0x37){ resp = mmc_cmd(41, 0x40ff8000, 0x3, MSC_CMDAT_RESPONSE_R3); if (resp[5] == 0x3f) ret = sd_found(); else ret = mmc_found(); } else { ret = mmc_found(); } } else { ret = mmc_found(); } if (ret) return error_handler(current_boot); ret = mmc_block_read(SPL_SIZE + redundancy_size, (u32 *)start_addr); //SDRAM ADDR if(!ret) { if (!(REG32(start_addr) == 0x4d53504c)) { if (ctl_num == 0) return sd_boot(1); if (ctl_num == 1) return usb_boot(); } else { return xfer_d2i(start_addr + jump_offset, SPL_SIZE); } } else { return error_handler(current_boot); } }