static int ocsdc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { struct ocsdc * dev = mmc->priv; int command = (cmd->cmdidx << 8); if (cmd->resp_type & MMC_RSP_PRESENT) { if (cmd->resp_type & MMC_RSP_136) command |= 2; else { command |= 1; } } if (cmd->resp_type & MMC_RSP_BUSY) command |= (1 << 2); if (cmd->resp_type & MMC_RSP_CRC) command |= (1 << 3); if (cmd->resp_type & MMC_RSP_OPCODE) command |= (1 << 4); if (data && ((data->flags & MMC_DATA_READ) || ((data->flags & MMC_DATA_WRITE))) && data->blocks) { if (data->flags & MMC_DATA_READ) command |= (1 << 5); if (data->flags & MMC_DATA_WRITE) command |= (1 << 6); ocsdc_setup_data_xfer(dev, cmd, data); } uart_print_str("ocsdc_send_smd\n"); uart_print_long(command); uart_print_str("\n"); ocsdc_write(dev, OCSDC_COMMAND, command); uart_print_str(" argument\n"); uart_print_long(cmd->cmdarg); uart_print_str("\n"); ocsdc_write(dev, OCSDC_ARGUMENT, cmd->cmdarg); if (ocsdc_finish(dev, cmd) < 0) {uart_print_str("ret -1\n"); return -1;} if (data && data->blocks) {uart_print_str("ret dat\n"); return ocsdc_data_finish(dev);} else uart_print_str("ret 0\n"); return 0; }
static void ocsdc_setup_data_xfer(struct ocsdc * dev, struct mmc_cmd *cmd, struct mmc_data *data) { //invalidate cache if (data->flags & MMC_DATA_READ) { flush_dcache_range(data->dest, data->dest+data->blocksize*data->blocks); ocsdc_write(dev, OCSDC_DST_SRC_ADDR, (uint32_t)data->dest); } else { flush_dcache_range((void *)data->src, (void *)data->src+data->blocksize*data->blocks); ocsdc_write(dev, OCSDC_DST_SRC_ADDR, (uint32_t)data->src); } uart_print_str("Blksz: "); uart_print_long(data->blocksize); uart_print_str("\n"); uart_print_str("BlkCnt: "); uart_print_long(data->blocks-1); uart_print_str("\n"); ocsdc_write(dev, OCSDC_BLOCK_SIZE, data->blocksize); ocsdc_write(dev, OCSDC_BLOCK_COUNT, data->blocks-1); }
static int ocsdc_finish(struct ocsdc * dev, struct mmc_cmd *cmd) { int retval = 0; while (1) { int r2 = ocsdc_read(dev, OCSDC_CMD_INT_STATUS); uart_print_str("finish cmd : status:"); uart_print_long(cmd->cmdidx); uart_print_long(r2); uart_print_str("\n"); //printf("ocsdc_finish: cmd %d, status %x\n", cmd->cmdidx, r2); if (r2 & OCSDC_CMD_INT_STATUS_EI) { //clear interrupts ocsdc_write(dev, OCSDC_CMD_INT_STATUS, 0); uart_print_str("OCSDC_CMD_INT_STATUS_EI\n"); //printf("ocsdc_finish: cmd %d, status %x\n\r", cmd->cmdidx, r2); retval = -1; break; } else if (r2 & OCSDC_CMD_INT_STATUS_CC) { //clear interrupts ocsdc_write(dev, OCSDC_CMD_INT_STATUS, 0); //get response cmd->response[0] = ocsdc_read(dev, OCSDC_RESPONSE_1); if (cmd->resp_type & MMC_RSP_136) { cmd->response[1] = ocsdc_read(dev, OCSDC_RESPONSE_2); cmd->response[2] = ocsdc_read(dev, OCSDC_RESPONSE_3); cmd->response[3] = ocsdc_read(dev, OCSDC_RESPONSE_4); } uart_print_str("ocsdc_finish: ok\n"); retval = 0; break; } } return retval; }
static int ocsdc_data_finish(struct ocsdc * dev) { int status; while ((status = ocsdc_read(dev, OCSDC_DAT_INT_STATUS)) == 0); ocsdc_write(dev, OCSDC_DAT_INT_STATUS, 0); if (status & SDCMSC_DAT_INT_STATUS_TRS) { uart_print_str("ocsdc_data_finish: ok\n"); return 0; } else { uart_print_str("ocsdc_data_finish: status: "); uart_print_long(status); uart_print_str("\n"); return -1; } }
sd_card sd_controller_init () { sd_card dev; unsigned int reg; unsigned int i; volatile unsigned long rtn_reg=0; volatile unsigned long rtn_reg1=0; REG32(SD_CONTROLLER_BASE+SD_COMMAND) =0x0000; REG32(SD_CONTROLLER_BASE+SD_ARG) =0x0000; sd_wait_rsp(); //while(1) {SD_REG(SD_COMMAND)=0x0000;} //while(1) {reg = SD_REG(SD_COMMAND);} REG32(SD_CONTROLLER_BASE+SD_TIMEOUT)=0x000FFFE; REG32(SD_CONTROLLER_BASE+SD_CTRL) =0x00000010; REG32(SD_CONTROLLER_BASE+SD_SOFTWARE_RST)=0x0000001; REG32(SD_CONTROLLER_BASE+SD_CLOCK_D)=0x0000000; REG32(SD_CONTROLLER_BASE+SD_SOFTWARE_RST)=0x0000000; REG32(SD_CONTROLLER_BASE+SD_COMMAND) =0x0000; REG32(SD_CONTROLLER_BASE+SD_ARG) =0x0000; sd_wait_rsp(); uart_print_str("SD_CTRL: \n"); uart_print_long(REG32(SD_CONTROLLER_BASE+SD_CTRL)); uart_print_str("\n"); SD_REG(SD_COMMAND) = CMD8 | CICE | CRCE | RSP_48; SD_REG(SD_ARG) = VHS|CHECK_PATTERN; dev.phys_spec_2_0 = sd_wait_rsp(); /* SD_REG(SD_COMMAND) = CMD8 | CICE | CRCE | RSP_48; //SD_REG(SD_COMMAND) = CMD8 | RSP_48; SD_REG(SD_ARG) = VHS|CHECK_PATTERN; //SD_REG(SD_ARG) = 0; dev.phys_spec_2_0 = sd_wait_rsp(); */ if (dev.phys_spec_2_0) uart_print_str("2_0 CARD \n"); else uart_print_str("NOT 2_0 CARD \n"); uart_print_long(REG32(SD_CONTROLLER_BASE+SD_RESP1)); while (REG32(SD_CONTROLLER_BASE+SD_STATUS)& 1) {} //uart_print_str("card staus: \n"); //uart_print_long(rtn_reg); //uart_print_str("\n"); rtn_reg=0; while ((rtn_reg & BUSY)!=BUSY) { REG32(SD_CONTROLLER_BASE+SD_COMMAND) = CMD55| CICE | CRCE | RSP_48; REG32(SD_CONTROLLER_BASE+SD_ARG) =0; sd_wait_rsp(); REG32(SD_CONTROLLER_BASE+SD_COMMAND) =ACMD41 | RSP_48; REG32(SD_CONTROLLER_BASE+SD_ARG) =0x40FF8000; sd_wait_rsp(); rtn_reg= REG32(SD_CONTROLLER_BASE+SD_RESP1); //rtn_reg= REG32(SD_CONTROLLER_BASE+SD_STATUS); //uart_print_str("response: \n"); //uart_print_long(rtn_reg); //uart_print_str("\n"); } dev.Voltage_window=rtn_reg&VOLTAGE_MASK; dev.HCS_s = rtn_reg&HCS; //GET CID uart_print_str("send command 2 ...\n"); REG32(SD_CONTROLLER_BASE+SD_COMMAND) =CMD2 | RSP_136; REG32(SD_CONTROLLER_BASE+SD_ARG)=0; sd_wait_rsp(); //Get RCA uart_print_str("send command 3 ...\n"); SD_REG(SD_COMMAND) = CMD3 | CICE | CRCE | RSP_48; SD_REG(SD_ARG)=0; sd_wait_rsp(); rtn_reg = SD_REG(SD_RESP1); dev.rca = ((rtn_reg&RCA_RCA_MASK)); dev.Active=1; return dev; }