int skymedi_set_func(struct mmc *mmc, unsigned int arg) { struct mmc_cmd cmd; cmd.cmdidx = 60; cmd.resp_type = MMC_RSP_R1; cmd.cmdarg = arg; return mmc_send_cmd(mmc, &cmd, NULL); }
int mmc_startup(struct mmc *mmc) { int err; u32 mult, freq; u64 cmult, csize, capacity; struct mmc_cmd cmd; char ext_csd[512]; int timeout = 1000; /* Put the Card in Identify Mode */ cmd.cmdidx = mmc_host_is_spi(mmc) ? MMC_CMD_SEND_CID : MMC_CMD_ALL_SEND_CID; /* cmd not supported in spi */ cmd.resp_type = MMC_RSP_R2; cmd.cmdarg = 0; cmd.flags = 0; err = mmc_send_cmd(mmc, &cmd, NULL); if (err){ mmcinfo("mmc %d Put the Card in Identify Mode failed\n",mmc->control_num); return err; } memcpy(mmc->cid, cmd.response, 16); /* * For MMC cards, set the Relative Address. * For SD cards, get the Relatvie Address. * This also puts the cards into Standby State */ if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */ cmd.cmdidx = SD_CMD_SEND_RELATIVE_ADDR; cmd.cmdarg = mmc->rca << 16; cmd.resp_type = MMC_RSP_R6; cmd.flags = 0; err = mmc_send_cmd(mmc, &cmd, NULL); if (err){ mmcinfo("mmc %d send rca failed\n",mmc->control_num); return err; } if (IS_SD(mmc)) mmc->rca = (cmd.response[0] >> 16) & 0xffff; }
int mmc_read_blocks(struct mmc *mmc, void *dst, unsigned long start, unsigned blkcnt) { struct mmc_cmd cmd; struct mmc_data data; int timeout = 1000; if (blkcnt > 1) cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK; else cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK; if (mmc->high_capacity) cmd.cmdarg = start; else cmd.cmdarg = start * mmc->read_bl_len; cmd.resp_type = MMC_RSP_R1; cmd.flags = 0; data.b.dest = dst; data.blocks = blkcnt; data.blocksize = mmc->read_bl_len; data.flags = MMC_DATA_READ; if (mmc_send_cmd(mmc, &cmd, &data)){ mmcinfo("mmc %d read blcok failed\n",mmc->control_num); return 0; } if (blkcnt > 1) { cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION; cmd.cmdarg = 0; cmd.resp_type = MMC_RSP_R1b; cmd.flags = 0; if (mmc_send_cmd(mmc, &cmd, NULL)) { mmcinfo("mmc %d fail to send stop cmd\n",mmc->control_num); return 0; } /* Waiting for the ready status */ mmc_send_status(mmc, timeout); } return blkcnt; }
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; }
int card_goto_idle_state() { command.cmd = MMC_GO_IDLE_STATE; command.resp_type = NO_RESPONSE; command.args = 0x00; if (mmc_send_cmd(&command)) { // Failure return 1; } return 0; }
int mmc_set_blocklen(struct mmc *mmc, int len) { struct mmc_cmd cmd; cmd.cmdidx = MMC_CMD_SET_BLOCKLEN; cmd.resp_type = MMC_RSP_R1; cmd.cmdarg = len; cmd.flags = 0; return mmc_send_cmd(mmc, &cmd, NULL); }
int select_card(struct sd_card *card) { command.cmd = MMC_SELECT_CARD; command.resp_type = RESP_LEN_48_CHK_BUSY; command.args = MMC_ARG_RCA(card->rca); /* card rca */ if (mmc_send_cmd(&command)) { return 1; } return 0; }
int mmc_sw_part(int mmc_cont, unsigned int part) { int ret = 1; if (mmc_blk_dev[mmc_cont].dev == -1) { printf("sw_part not permitted as Card on SLOT-%d not Initialized\n",mmc_cont); } else { unsigned int resp[4]; ret = mmc_send_cmd(cur_controller_data[mmc_cont].base, MMC_CMD6, (3<<24) | (0xb3<<16) | ((part&7)<<8), resp); } return ret; }
static ulong skymedi_read_blocks(struct mmc *mmc, void *dst, lbaint_t start, lbaint_t blkcnt) { struct mmc_cmd cmd; struct mmc_data data; int timeout = 3000; if (blkcnt > 1) cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK; else cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK; if (mmc->high_capacity) cmd.cmdarg = start; else cmd.cmdarg = start * mmc->read_bl_len; cmd.resp_type = MMC_RSP_R1; data.dest = dst; data.blocks = blkcnt; data.blocksize = mmc->read_bl_len; data.flags = MMC_DATA_READ; if (mmc_send_cmd(mmc, &cmd, &data)) return 0; if (blkcnt > 1) { cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION; cmd.cmdarg = 0; cmd.resp_type = MMC_RSP_R1b; if (mmc_send_cmd(mmc, &cmd, NULL)) { return 0; } } if (mmc_send_status(mmc, timeout)) return 0; return blkcnt; }
static int mmc_set_blockcount(struct mmc *mmc, unsigned int blockcount, bool is_rel_write) { struct mmc_cmd cmd = {0}; cmd.cmdidx = MMC_CMD_SET_BLOCK_COUNT; cmd.cmdarg = blockcount & 0x0000FFFF; if (is_rel_write) cmd.cmdarg |= 1 << 31; cmd.resp_type = MMC_RSP_R1; return mmc_send_cmd(mmc, &cmd, NULL); }
static int mmc_movi_cmd(struct mmc_host *host, u32 arg) { int err; u32 resp; err = mmc_send_cmd(host, 62, arg, MMC_RSP_R1B | MMC_CMD_AC, &resp); mdelay(10); if (!err) do { err = mmc_send_cmd(host, MMC_SEND_STATUS, host->card->rca << 16, MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC, &resp); if (err) { printk(KERN_ERR "CMD13(VC) failed\n"); break; } /*wait until READY_FOR_DATA*/ } while (!(resp & 1<<8)); return err; }
MMCDriver::MMCDriver() : SPT(63), lock_("MMCDriver::lock_"), rca_(0), sector_size_(512), num_sectors_(210672) { // unsigned int check; debug(MMC_DRIVER,"MMCDriver()\n"); uint32 response; mmci->control1 = (1 << 24); while (mmci->control1 & (1 << 24)); mmci->control1 = 0xF0F27; mmci->control2 = 0x0; mmci->blksizecnt = (1 << 16) | sector_size_; mmci->irpt_mask = 0xFFFFFFFF; while (!(mmci->control1 & (1 << 1))); debug(MMC_DRIVER,"MMC controller resetted\n"); // protocol from sd card specification mmc_send_cmd(0,0,0); // go to idle state mmc_send_cmd(8,0x1AA,&response,1 << 16); // go to idle state mmc_send_acmd(41,0x50FF0000,&response); assert((response & 0x80ff8000) == 0x80ff8000); mmc_send_cmd(2,0,0); mmc_send_cmd(3,0,&response); rca_ = response >> 16; mmc_send_cmd(7,rca_ << 16,0); mmci->irpt_mask = 0xFFFFFFFF; }
static int mmc_sd_switch(struct mmc_request *request, int mode, int group, unsigned char value, unsigned char * resp) { unsigned int arg; struct mmc_response_r1 r1; mode = !!mode; value &= 0xF; arg = mode << 31 | 0x00FFFFFF; arg &= ~(0xF << (group * 4)); arg |= value << (group * 4); mmc_send_cmd(request, 6, arg, 1, 64, RESPONSE_R1, resp); return 0; }
int32 MMCDriver::writeBlock ( uint32 address, void *buffer) { debug(MMC_DRIVER,"readBlock: address: %x, buffer: %x\n",address, buffer); uint32 response; mmc_send_cmd(24, address, &response,1); uint32* buffer32 = (uint32*) buffer; // uint8* buffer8 = (uint8*) buffer; uint32 i = 0; while (i < sector_size_ / sizeof(uint32)) { while (!(mmci->interrupt & (1 << 5))); mmci->data = buffer32[i++]; } return 0; }
static int mmc_rpmb_response(struct mmc *mmc, struct s_rpmb *s, unsigned short expected) { struct mmc_cmd cmd = {0}; struct mmc_data data; int ret; ret = mmc_set_blockcount(mmc, 1, false); if (ret) { #ifdef CONFIG_MMC_RPMB_TRACE printf("%s:mmc_set_blockcount-> %d\n", __func__, ret); #endif return -1; } cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK; cmd.cmdarg = 0; cmd.resp_type = MMC_RSP_R1; data.dest = (char *)s; data.blocks = 1; data.blocksize = MMC_MAX_BLOCK_LEN; data.flags = MMC_DATA_READ; ret = mmc_send_cmd(mmc, &cmd, &data); if (ret) { #ifdef CONFIG_MMC_RPMB_TRACE printf("%s:mmc_send_cmd-> %d\n", __func__, ret); #endif return -1; } /* Check the response and the status */ if (be16_to_cpu(s->request) != expected) { #ifdef CONFIG_MMC_RPMB_TRACE printf("%s:response= %x\n", __func__, be16_to_cpu(s->request)); #endif return -1; } ret = be16_to_cpu(s->result); if (ret) { printf("%s %s\n", rpmb_err_msg[ret & RPMB_ERR_MSK], (ret & RPMB_ERR_CNT_EXPIRED) ? "Write counter has expired" : ""); } /* Return the status of the command */ return ret; }
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; }
int mmc_set_blocklen(struct mmc *mmc, int len) { struct mmc_cmd cmd; /* don't set blocklen at ddr mode */ if ((mmc->speed_mode == HSDDR52_DDR50) || (mmc->speed_mode == HS400)) { return 0; } cmd.cmdidx = MMC_CMD_SET_BLOCKLEN; cmd.resp_type = MMC_RSP_R1; cmd.cmdarg = len; cmd.flags = 0; return mmc_send_cmd(mmc, &cmd, NULL); }
int card_identification() { command.cmd = MMC_SEND_EXT_CSD; command.resp_type = RESP_LEN_48; command.args = MMCHS_SD_ARG_CMD8_VHS | MMCHS_SD_ARG_CMD8_CHECK_PATTERN; if (mmc_send_cmd(&command)) { // We currently only support 2.0, return 1; } if (!(command.resp[0] == (MMCHS_SD_ARG_CMD8_VHS | MMCHS_SD_ARG_CMD8_CHECK_PATTERN))) { printf("%s, check pattern check failed %x\n", __FUNCTION__); return 1; } return 0; }
static int mmc_send_status( mmc_card_data *mmc_card_cur, mmc_controller_data *mmc_cont_cur, unsigned int *mstatus) { unsigned char ret_val; unsigned int argument; unsigned int resp[4]; argument = mmc_card_cur->RCA << 16; ret_val = mmc_send_cmd(mmc_cont_cur->base, MMC_CMD13, argument, resp); if (ret_val != 1) { printf("error in sending cmd13\n"); if (mstatus!=NULL) *mstatus=mmc_stat_last; return ret_val; } if (mstatus) *mstatus=resp[0]; return 1; }
int32 MMCDriver::writeBlock(uint32 address, void *buffer) { debug(MMC_DRIVER, "writeBlock: address: %x, buffer: %x\n", address, buffer); uint32 response; mmc_send_cmd(24, address, &response); mmci->datalength = 512; mmci->datactrl = PL181_DATA_ENABLE | PL181_DATA_DIRECTION | PL181_DATA_MODE; for (uint32 j = 0; j < 8; j++) { uint32 i; for (i = 0; i < 16; i++) { mmci_fifo[i] = *((uint32*) buffer + j * 16 + i); } while ((mmci->status & PL181_STATUS_TXFIFOEMPTY)); } return 0; }
int read_single_block(struct sd_card_regs *card, uint32_t blknr, unsigned char *buf) { struct mmc_command command; command.cmd = MMC_READ_BLOCK_SINGLE; command.args = blknr; command.resp_type = RESP_LEN_48; command.data = buf; command.data_len = 512; if (mmc_send_cmd(&command)) { mmc_log_warn(&log, "Error sending command\n"); return 1; } return 0; }
int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp) { struct mmc_cmd cmd; struct mmc_data data; /* Switch the frequency */ cmd.cmdidx = SD_CMD_SWITCH_FUNC; cmd.resp_type = MMC_RSP_R1; cmd.cmdarg = (mode << 31) | 0xffffff; cmd.cmdarg &= ~(0xf << (group * 4)); cmd.cmdarg |= value << (group * 4); cmd.flags = 0; data.b.dest = (char *)resp; data.blocksize = 64; data.blocks = 1; data.flags = MMC_DATA_READ; return mmc_send_cmd(mmc, &cmd, &data); }
int32 MMCDriver::readBlock(uint32 address, void *buffer) { debug(MMC_DRIVER, "readBlock: address: %x, buffer: %x\n", address, buffer); uint32 response; mmc_send_cmd(17, address, &response); mmci->datalength = 512; mmci->datactrl = PL181_DATA_ENABLE | PL181_DATA_DIRECTION | PL181_DATA_MODE; for (uint32 j = 0; j < 8; j++) { while (mmci->status & PL181_STATUS_RXFIFOFULL) { uint32 i; for (i = 0; i < 16; i++) { *((uint32*) buffer + j * 16 + i) = mmci_fifo[i]; } } } return 0; }
int mmc_go_idle(struct mmc* mmc) { struct mmc_cmd cmd; int err; udelay(1000); cmd.cmdidx = MMC_CMD_GO_IDLE_STATE; cmd.cmdarg = 0; cmd.resp_type = MMC_RSP_NONE; cmd.flags = 0; err = mmc_send_cmd(mmc, &cmd, NULL); if (err) return err; udelay(2000); return 0; }
int mmc_send_ext_csd(struct mmc *mmc, char *ext_csd) { struct mmc_cmd cmd; struct mmc_data data; int err; /* Get the Card Status Register */ cmd.cmdidx = MMC_CMD_SEND_EXT_CSD; cmd.resp_type = MMC_RSP_R1; cmd.cmdarg = 0; cmd.flags = 0; data.b.dest = ext_csd; data.blocks = 1; data.blocksize = 512; data.flags = MMC_DATA_READ; err = mmc_send_cmd(mmc, &cmd, &data); return err; }
int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value) { struct mmc_cmd cmd; int timeout = 1000; int ret; cmd.cmdidx = MMC_CMD_SWITCH; cmd.resp_type = MMC_RSP_R1b; cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | (index << 16) | (value << 8); cmd.flags = 0; ret = mmc_send_cmd(mmc, &cmd, NULL); /* Waiting for the ready status */ mmc_send_status(mmc, timeout); return ret; }
int skymedi_perform_erase(struct mmc *mmc, u32 arg, u32 timeout_ms) { struct mmc_cmd cmd; int ret; cmd.cmdidx = MMC_CMD_ERASE; cmd.cmdarg = arg; cmd.resp_type = MMC_RSP_R1b; ret = mmc_send_cmd(mmc, &cmd, NULL); if (ret) { printf("erase failed\n"); return ret; } mdelay(10); ret = mmc_send_status(mmc, timeout_ms); if (ret != 0) { printf("erase timeout\n"); return ret; } return 0; }
int write_single_block(struct sd_card_regs *card, uint32_t blknr, unsigned char *buf) { struct mmc_command command; set32(base_address + MMCHS_SD_BLK, MMCHS_SD_BLK_BLEN, 512); command.cmd = MMC_WRITE_BLOCK_SINGLE; command.args = blknr; command.resp_type = RESP_LEN_48; command.data = buf; command.data_len = 512; /* write single block */ if (mmc_send_cmd(&command)) { mmc_log_warn(&log, "Write single block command failed\n"); return 1; } return 0; }
//++ 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; }