unsigned char mmc_send_cmd(unsigned int base, unsigned int cmd, unsigned int arg, unsigned int *response) { unsigned int mmc_stat; unsigned int cmd_index = cmd >> 24; while ((OMAP_HSMMC_PSTATE(base) & DATI_MASK) == DATI_CMDDIS); #ifdef CONFIG_USBBOOT_ERASER /* support multi write for emmc erase */ OMAP_HSMMC_STAT(base) = 0xFFFFFFFF; OMAP_HSMMC_ARG(base) = arg; if (cmd_index == 0x19) { /* CMD25: Multi block write */ OMAP_HSMMC_CMD(base) = cmd | CMD_TYPE_NORMAL | CICE_NOCHECK | CCCE_NOCHECK | MSBS | BCE | ACEN_DISABLE | DE_DISABLE; } else if (cmd_index == 0xC) { OMAP_HSMMC_CMD(base) = cmd | 0x3 << 22 | CICE_NOCHECK | CCCE_NOCHECK | ACEN_DISABLE | BCE_DISABLE | DE_DISABLE; } else { OMAP_HSMMC_BLK(base) = BLEN_512BYTESLEN | NBLK_STPCNT; OMAP_HSMMC_CMD(base) = cmd | CMD_TYPE_NORMAL | CICE_NOCHECK | CCCE_NOCHECK | MSBS_SGLEBLK | ACEN_DISABLE | BCE_DISABLE | DE_DISABLE; } #else OMAP_HSMMC_BLK(base) = BLEN_512BYTESLEN | NBLK_STPCNT; OMAP_HSMMC_STAT(base) = 0xFFFFFFFF; OMAP_HSMMC_ARG(base) = arg; OMAP_HSMMC_CMD(base) = cmd | CMD_TYPE_NORMAL | CICE_NOCHECK | CCCE_NOCHECK | MSBS_SGLEBLK | ACEN_DISABLE | BCE_DISABLE | DE_DISABLE; #endif while (1) { do { mmc_stat = OMAP_HSMMC_STAT(base); } while (mmc_stat == 0); if ((mmc_stat & ERRI_MASK) != 0) return (unsigned char)mmc_stat; if (mmc_stat & CC_MASK) { OMAP_HSMMC_STAT(base) = CC_MASK; response[0] = OMAP_HSMMC_RSP10(base); if ((cmd & RSP_TYPE_MASK) == RSP_TYPE_LGHT136) { response[1] = OMAP_HSMMC_RSP32(base); response[2] = OMAP_HSMMC_RSP54(base); response[3] = OMAP_HSMMC_RSP76(base); } break; } } return 1; }
unsigned char omap_mmc_erase_sect(unsigned int start, mmc_controller_data *mmc_cont_cur, mmc_card_data *mmc_c, int size) { unsigned char err; unsigned int argument; unsigned int num_sec_val; unsigned int sec_inc_val; unsigned int resp[4]; unsigned int mmc_stat; unsigned int blk_cnt_current_tns; if ((start / MMCSD_SECTOR_SIZE) > mmc_c->size || ((start + size) / MMCSD_SECTOR_SIZE) > mmc_c->size) { printf("mmc erase: erase to Sector is\n" "out of card range\n"); return 1; } num_sec_val = (size + (MMCSD_SECTOR_SIZE - 1)) / MMCSD_SECTOR_SIZE; if (mmc_c->mode == SECTOR_MODE) { argument = start; sec_inc_val = 1; } else { argument = start * MMCSD_SECTOR_SIZE; sec_inc_val = MMCSD_SECTOR_SIZE; } while (num_sec_val) { if (num_sec_val > 0xFFFF) blk_cnt_current_tns = 0xFFFF; else blk_cnt_current_tns = num_sec_val; /* check for Multi Block */ if (blk_cnt_current_tns > 1) { OMAP_HSMMC_BLK(mmc_cont_cur->base) = BLEN_512BYTESLEN | (blk_cnt_current_tns << 16); err = mmc_send_cmd(mmc_cont_cur->base, MMC_CMD25, argument, resp); if (err != 1) return err; } else { err = mmc_send_cmd(mmc_cont_cur->base, MMC_CMD24, argument, resp); if (err != 1) return err; } while (1) { do { mmc_stat = OMAP_HSMMC_STAT(mmc_cont_cur->base); } while (mmc_stat == 0); if ((mmc_stat & ERRI_MASK) != 0) return (unsigned char)mmc_stat; if (mmc_stat & BWR_MASK) { unsigned int k; OMAP_HSMMC_STAT(mmc_cont_cur->base) |= BWR_MASK; for (k = 0; k < MMCSD_SECTOR_SIZE / 4; k++) { OMAP_HSMMC_DATA(mmc_cont_cur->base) = 0XFFFFFFFF; } } if (mmc_stat & BRR_MASK) OMAP_HSMMC_STAT(mmc_cont_cur->base) |= BRR_MASK; if (mmc_stat & TC_MASK) { OMAP_HSMMC_STAT(mmc_cont_cur->base) |= TC_MASK; break; } } if (blk_cnt_current_tns > 1) { err = mmc_send_cmd(mmc_cont_cur->base, MMC_CMD12, 0, resp); if (err != 1) { printf("MMC_CMD12 failed 0x%x\n", err); return err; } } argument += sec_inc_val * blk_cnt_current_tns; num_sec_val -= blk_cnt_current_tns; } return 1; }
unsigned char omap_mmc_write_sect(unsigned int *input_buf, unsigned int num_bytes, mmc_controller_data *mmc_cont_cur, mmc_card_data *mmc_c, unsigned long start_sec) { unsigned char err; unsigned int argument; unsigned int resp[4]; unsigned int num_sec_val = (num_bytes + (MMCSD_SECTOR_SIZE - 1)) / MMCSD_SECTOR_SIZE; unsigned int sec_inc_val; unsigned int blk_cnt_current_tns; int r; if (num_sec_val == 0) { printf("mmc write: Invalid size\n"); return 1; } if (mmc_c->mode == SECTOR_MODE) { argument = start_sec; sec_inc_val = 1; } else { argument = start_sec * MMCSD_SECTOR_SIZE; sec_inc_val = MMCSD_SECTOR_SIZE; } while (num_sec_val) { if (num_sec_val > 0xFFFF) /* Max number of blocks per cmd */ blk_cnt_current_tns = 0xFFFF; else blk_cnt_current_tns = num_sec_val; /* check for Multi Block */ if (blk_cnt_current_tns > 1) { #if !defined(CONFIG_4430PANDA) err = mmc_send_cmd(mmc_cont_cur->base, MMC_CMD23, blk_cnt_current_tns, resp); if (err != 1) return err; #endif OMAP_HSMMC_BLK(mmc_cont_cur->base) = BLEN_512BYTESLEN | (blk_cnt_current_tns << 16); err = mmc_send_cmd(mmc_cont_cur->base, MMC_CMD25, argument, resp); if (err != 1) return err; } else { err = mmc_send_cmd(mmc_cont_cur->base, MMC_CMD24, argument, resp); if (err != 1) return err; } r = mmc_write_data(mmc_cont_cur->base, input_buf); if (r < 0) return 1; blk_cnt_current_tns = r; #if defined(CONFIG_4430PANDA) if (blk_cnt_current_tns > 1) { err = mmc_send_cmd(mmc_cont_cur->base, MMC_CMD12, 0, resp); if (err != 1) { printf("MMC_CMD12 failed 0x%x\n", err); return err; } } #endif input_buf += (MMCSD_SECTOR_SIZE / 4) * blk_cnt_current_tns; argument += sec_inc_val * blk_cnt_current_tns; num_sec_val -= blk_cnt_current_tns; } return 1; }
unsigned char omap_mmc_read_sect(unsigned int start_sec, unsigned int num_bytes, mmc_controller_data *mmc_cont_cur, mmc_card_data *mmc_c, unsigned int *output_buf) { unsigned char err; unsigned int argument; unsigned int resp[4]; unsigned int num_sec_val = (num_bytes + (MMCSD_SECTOR_SIZE - 1)) / MMCSD_SECTOR_SIZE; unsigned int sec_inc_val; unsigned int blk_cnt_current_tns; if (num_sec_val == 0) { return 1; } if (mmc_c->mode == SECTOR_MODE) { argument = start_sec; sec_inc_val = 1; } else { argument = start_sec * MMCSD_SECTOR_SIZE; sec_inc_val = MMCSD_SECTOR_SIZE; } //++ Peter_20100914, Add MMC Multi Block Read. #if 0 /* Orig Single Block Read */ while (num_sec_val) { err = mmc_send_cmd(mmc_cont_cur->base, MMC_CMD17, argument, resp); if (err != 1) return err; err = mmc_read_data(mmc_cont_cur->base, output_buf); if (err != 1) return err; output_buf += (MMCSD_SECTOR_SIZE / 4); argument += sec_inc_val; num_sec_val--; } #else /* Mulit Block Read */ while (num_sec_val) { if (num_sec_val > 0xFFFF) /* Max number of blocks per cmd */ blk_cnt_current_tns = 0xFFFF; else blk_cnt_current_tns = num_sec_val; /* check for Multi Block */ if (blk_cnt_current_tns > 1) { err = mmc_send_cmd(mmc_cont_cur->base, MMC_CMD23, blk_cnt_current_tns, resp); if (err != 1) return err; OMAP_HSMMC_BLK(mmc_cont_cur->base) = BLEN_512BYTESLEN | (blk_cnt_current_tns << 16); err = mmc_send_cmd(mmc_cont_cur->base, MMC_CMD18, argument, resp); if (err != 1) return err; } else { err = mmc_send_cmd(mmc_cont_cur->base, MMC_CMD17, argument, resp); if (err != 1) return err; } err = mmc_read_data(mmc_cont_cur->base, output_buf); if (err != 1) return err; output_buf += ((MMCSD_SECTOR_SIZE / 4) * blk_cnt_current_tns); argument += (sec_inc_val * blk_cnt_current_tns); num_sec_val -= blk_cnt_current_tns; } #endif //-- Peter_20100914, Add MMC Multi Block Read. return 1; }
unsigned char mmc_send_cmd(unsigned int base, unsigned int cmd, unsigned int arg, unsigned int *response) { unsigned int mmc_stat; unsigned int cmd_index = cmd >> 24; while ((OMAP_HSMMC_PSTATE(base) & DATI_MASK) == DATI_CMDDIS) ; OMAP_HSMMC_STAT(base) = 0xFFFFFFFF; OMAP_HSMMC_ARG(base) = arg; //++ Peter_20100914, Add Mulit Block Read. #if 0 if (cmd_index == 0x19) { /* CMD25: Multi block write */ #else if ((cmd_index == 0x19)||(cmd_index == 0x12)) { /* CMD25: Multi block write */ /* CMD18: Multi block read */ #endif //-- Peter_20100914, Add Mulit Block Read. OMAP_HSMMC_CMD(base) = cmd | CMD_TYPE_NORMAL | CICE_NOCHECK | CCCE_NOCHECK | MSBS | BCE | ACEN_DISABLE | DE_DISABLE; } else { OMAP_HSMMC_BLK(base) = BLEN_512BYTESLEN | NBLK_STPCNT; OMAP_HSMMC_CMD(base) = cmd | CMD_TYPE_NORMAL | CICE_NOCHECK | CCCE_NOCHECK | MSBS_SGLEBLK | ACEN_DISABLE | BCE_DISABLE | DE_DISABLE; } while (1) { do { mmc_stat = OMAP_HSMMC_STAT(base); } while (mmc_stat == 0); if ((mmc_stat & ERRI_MASK) != 0) return (unsigned char)mmc_stat; if (mmc_stat & CC_MASK) { OMAP_HSMMC_STAT(base) = CC_MASK; response[0] = OMAP_HSMMC_RSP10(base); if ((cmd & RSP_TYPE_MASK) == RSP_TYPE_LGHT136) { response[1] = OMAP_HSMMC_RSP32(base); response[2] = OMAP_HSMMC_RSP54(base); response[3] = OMAP_HSMMC_RSP76(base); } break; } } return 1; } unsigned char mmc_read_data(unsigned int base, unsigned int *output_buf) { unsigned int mmc_stat; unsigned int read_count = 0; /* * Start Polled Read */ while (1) { do { mmc_stat = OMAP_HSMMC_STAT(base); } while (mmc_stat == 0); if ((mmc_stat & ERRI_MASK) != 0) return (unsigned char)mmc_stat; if (mmc_stat & BRR_MASK) { unsigned int k; OMAP_HSMMC_STAT(base) |= BRR_MASK; for (k = 0; k < MMCSD_SECTOR_SIZE / 4; k++) { *output_buf = OMAP_HSMMC_DATA(base); output_buf++; read_count += 4; } } if (mmc_stat & BWR_MASK) OMAP_HSMMC_STAT(base) |= BWR_MASK; if (mmc_stat & TC_MASK) { OMAP_HSMMC_STAT(base) |= TC_MASK; break; } } return 1; }