unsigned char mmc_read_cardsize(mmc_card_data *mmc_dev_data, mmc_csd_reg_t *cur_csd) { mmc_extended_csd_reg_t ext_csd; unsigned int size, count, blk_len, blk_no, card_size, argument; unsigned char err; unsigned int resp[4]; if (mmc_dev_data->mode == SECTOR_MODE) { if (mmc_dev_data->card_type == SD_CARD) { card_size = (((mmc_sd2_csd_reg_t *) cur_csd)-> c_size_lsb & MMC_SD2_CSD_C_SIZE_LSB_MASK) | ((((mmc_sd2_csd_reg_t *) cur_csd)-> c_size_msb & MMC_SD2_CSD_C_SIZE_MSB_MASK) << MMC_SD2_CSD_C_SIZE_MSB_OFFSET); mmc_dev_data->size = card_size * 1024; if (mmc_dev_data->size == 0) return 0; } else { argument = 0x00000000; err = mmc_send_cmd(MMC_CMD8, argument, resp); if (err != 1) return err; err = mmc_read_data((unsigned int *)&ext_csd); if (err != 1) return err; mmc_dev_data->size = ext_csd.sectorcount; if (mmc_dev_data->size == 0) mmc_dev_data->size = 8388608; } } else { if (cur_csd->c_size_mult >= 8) return 0; if (cur_csd->read_bl_len >= 12) return 0; /* Compute size */ count = 1 << (cur_csd->c_size_mult + 2); card_size = (cur_csd->c_size_lsb & MMC_CSD_C_SIZE_LSB_MASK) | ((cur_csd->c_size_msb & MMC_CSD_C_SIZE_MSB_MASK) << MMC_CSD_C_SIZE_MSB_OFFSET); blk_no = (card_size + 1) * count; blk_len = 1 << cur_csd->read_bl_len; size = blk_no * blk_len; mmc_dev_data->size = size / MMCSD_SECTOR_SIZE; if (mmc_dev_data->size == 0) return 0; } 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; if (num_sec_val == 0) { printf("mmc read: 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) { err = mmc_send_cmd(mmc_cont_cur->base, MMC_CMD17, argument, resp); if (err != 1) { printf("mmc read cmd sector 0x%x error 0x%x\n",argument, mmc_stat_last); printf("OMAP_HSMMC_SYSCTL(mmc_cont_cur->base)= 0x%x\n",OMAP_HSMMC_SYSCTL(mmc_cont_cur->base)); printf("OMAP_HSMMC_CAPA(mmc_cont_cur->base) = 0x%x\n", OMAP_HSMMC_CAPA(mmc_cont_cur->base)); return err; } err = mmc_read_data(mmc_cont_cur->base, output_buf); if (err != 1) { printf("mmc read data sector 0x%x error 0x%x\n",argument, mmc_stat_last); printf("OMAP_HSMMC_SYSCTL(mmc_cont_cur->base)= 0x%x\n",OMAP_HSMMC_SYSCTL(mmc_cont_cur->base)); printf("OMAP_HSMMC_CAPA(mmc_cont_cur->base) = 0x%x\n", OMAP_HSMMC_CAPA(mmc_cont_cur->base)); return err; } output_buf += (MMCSD_SECTOR_SIZE / 4); argument += sec_inc_val; num_sec_val--; } return 1; }
//++ Peter_20100914 unsigned char omap_mmc_read_sect_single_block(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; } 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--; } return 1; }
unsigned char omap_mmc_read_sect(unsigned int start_sec, unsigned int num_bytes, 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; 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; } while (num_sec_val) { err = mmc_send_cmd(MMC_CMD17, argument, resp); if (err != 1) return err; err = mmc_read_data(output_buf); if (err != 1) return err; output_buf += (MMCSD_SECTOR_SIZE / 4); argument += sec_inc_val; num_sec_val--; } return 1; }
static int omap_hsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { struct hsmmc *mmc_base; unsigned int flags, mmc_stat; ulong start; mmc_base = ((struct omap_hsmmc_data *)mmc->priv)->base_addr; start = get_timer(0); while ((readl(&mmc_base->pstate) & (DATI_MASK | CMDI_MASK)) != 0) { if (get_timer(0) - start > MAX_RETRY_MS) { printf("%s: timedout waiting on cmd inhibit to clear\n", __func__); return -ETIMEDOUT; } } writel(0xFFFFFFFF, &mmc_base->stat); start = get_timer(0); while (readl(&mmc_base->stat)) { if (get_timer(0) - start > MAX_RETRY_MS) { printf("%s: timedout waiting for STAT (%x) to clear\n", __func__, readl(&mmc_base->stat)); return -ETIMEDOUT; } } /* * CMDREG * CMDIDX[13:8] : Command index * DATAPRNT[5] : Data Present Select * ENCMDIDX[4] : Command Index Check Enable * ENCMDCRC[3] : Command CRC Check Enable * RSPTYP[1:0] * 00 = No Response * 01 = Length 136 * 10 = Length 48 * 11 = Length 48 Check busy after response */ /* Delay added before checking the status of frq change * retry not supported by mmc.c(core file) */ if (cmd->cmdidx == SD_CMD_APP_SEND_SCR) udelay(50000); /* wait 50 ms */ if (!(cmd->resp_type & MMC_RSP_PRESENT)) flags = 0; else if (cmd->resp_type & MMC_RSP_136) flags = RSP_TYPE_LGHT136 | CICE_NOCHECK; else if (cmd->resp_type & MMC_RSP_BUSY) flags = RSP_TYPE_LGHT48B; else flags = RSP_TYPE_LGHT48; /* enable default flags */ flags = flags | (CMD_TYPE_NORMAL | CICE_NOCHECK | CCCE_NOCHECK | MSBS_SGLEBLK | ACEN_DISABLE | BCE_DISABLE | DE_DISABLE); if (cmd->resp_type & MMC_RSP_CRC) flags |= CCCE_CHECK; if (cmd->resp_type & MMC_RSP_OPCODE) flags |= CICE_CHECK; if (data) { if ((cmd->cmdidx == MMC_CMD_READ_MULTIPLE_BLOCK) || (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK)) { flags |= (MSBS_MULTIBLK | BCE_ENABLE); data->blocksize = 512; writel(data->blocksize | (data->blocks << 16), &mmc_base->blk); } else writel(data->blocksize | NBLK_STPCNT, &mmc_base->blk); if (data->flags & MMC_DATA_READ) flags |= (DP_DATA | DDIR_READ); else flags |= (DP_DATA | DDIR_WRITE); } writel(cmd->cmdarg, &mmc_base->arg); udelay(20); /* To fix "No status update" error on eMMC */ writel((cmd->cmdidx << 24) | flags, &mmc_base->cmd); start = get_timer(0); do { mmc_stat = readl(&mmc_base->stat); if (get_timer(0) - start > MAX_RETRY_MS) { printf("%s : timeout: No status update\n", __func__); return -ETIMEDOUT; } } while (!mmc_stat); if ((mmc_stat & IE_CTO) != 0) { mmc_reset_controller_fsm(mmc_base, SYSCTL_SRC); return -ETIMEDOUT; } else if ((mmc_stat & ERRI_MASK) != 0) return -1; if (mmc_stat & CC_MASK) { writel(CC_MASK, &mmc_base->stat); if (cmd->resp_type & MMC_RSP_PRESENT) { if (cmd->resp_type & MMC_RSP_136) { /* response type 2 */ cmd->response[3] = readl(&mmc_base->rsp10); cmd->response[2] = readl(&mmc_base->rsp32); cmd->response[1] = readl(&mmc_base->rsp54); cmd->response[0] = readl(&mmc_base->rsp76); } else /* response types 1, 1b, 3, 4, 5, 6 */ cmd->response[0] = readl(&mmc_base->rsp10); } } if (data && (data->flags & MMC_DATA_READ)) { mmc_read_data(mmc_base, data->dest, data->blocksize * data->blocks); } else if (data && (data->flags & MMC_DATA_WRITE)) { mmc_write_data(mmc_base, data->src, data->blocksize * data->blocks); } return 0; }
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; }