📄 mmc_asic3.c
字号:
buf[13] = data & 0xff; data = H3900_ASIC3_SD_CTRL_Response0; buf[14] = data >> 8; buf[15] = data & 0xff; buf[16] = 1; // ecc flag } else { // R1, R1B, R3 handle if (request->rtype == RESPONSE_R3) buf[0] = 0x3f; else buf[0] = request->cmd; data = H3900_ASIC3_SD_CTRL_Response1; buf[1] = data >> 8; buf[2] = data & 0xff; data = H3900_ASIC3_SD_CTRL_Response0; buf[3] = data >> 8; buf[4] = data & 0xff; } START_MMC_DEBUG(3) { printk(__FILE__ ":%s - Response byte stream: ", __FUNCTION__); for (i = 0; i < len; i++) printk("%02x ", buf[i]); printk("\n"); } END_MMC_DEBUG;}static void mmc_asic3_send_command(struct mmc_request *request){ u16 card_status, buffer_status; int retval = MMC_NO_ERROR, timeout, res_end = 0, rw_end = 0; int read_enable = 0, write_enable = 0, transfer = 0, cdc = 0; MMC_DEBUG(2, "request=%p cmd=%d (%s) arg=%08x", request, request->cmd, get_cmd_name(request->cmd), request->arg); g_data.request = request; request->result = MMC_NO_RESPONSE; // Flag to indicate don't have a result yet if (request->cmd == MMC_CIM_RESET) { retval = mmc_asic3_reset_asic(); goto end_command; } if (request->cmd == MMC_STOP_TRANSMISSION) { H3900_ASIC3_SD_CTRL_StopInternal = SD_CTRL_STOP_INTERNAL_ISSSUE_CMD12; request->response[0] = request->cmd; request->response[1] = 0; request->response[2] = 0; request->response[3] = 0; request->response[4] = 0; retval = MMC_NO_ERROR; goto end_command; } // reset card status card_status = H3900_ASIC3_SD_CTRL_CardStatus; // detect if state of card is changed first card_status &= (SD_CTRL_CARDSTATUS_CARD_REMOVED_0 | SD_CTRL_CARDSTATUS_CARD_INSERTED_0 | SD_CTRL_CARDSTATUS_SIGNAL_STATE_PRESENT_0 | SD_CTRL_CARDSTATUS_WRITE_PROTECT); H3900_ASIC3_SD_CTRL_CardStatus = card_status; // reset buffer status H3900_ASIC3_SD_CTRL_BufferCtrl = 0; H3900_ASIC3_SD_CTRL_ErrorStatus0 = 0; H3900_ASIC3_SD_CTRL_ErrorStatus1 = 0; timeout = 0; do { // check and wait if SD/MMC controller is ready for receive commands buffer_status = H3900_ASIC3_SD_CTRL_BufferCtrl; if ((buffer_status & (SD_CTRL_BUFFERSTATUS_ILLEGAL_ACCESS | SD_CTRL_BUFFERSTATUS_CMD_INDEX_ERROR | SD_CTRL_BUFFERSTATUS_CRC_ERROR | SD_CTRL_BUFFERSTATUS_DATA_TIMEOUT | SD_CTRL_BUFFERSTATUS_STOP_BIT_END_ERROR | SD_CTRL_BUFFERSTATUS_BUFFER_OVERFLOW | SD_CTRL_BUFFERSTATUS_BUFFER_UNDERFLOW | SD_CTRL_BUFFERSTATUS_CMD_TIMEOUT)) != 0) { MMC_DEBUG(0, "Buffer status ERROR 0x%04x - inside check buffer\n", buffer_status); MMC_DEBUG(0, "detail0 error status 0x%04x\n", H3900_ASIC3_SD_CTRL_ErrorStatus0); MMC_DEBUG(0, "detail1 error status 0x%04x\n", H3900_ASIC3_SD_CTRL_ErrorStatus1); retval = MMC_ERROR_GENERAL; goto end_command; } if (timeout > 3000000) { MMC_DEBUG(0, "TIMEOUT - inside check buffer\n"); retval = MMC_ERROR_TIMEOUT; goto end_command; } timeout++; udelay(1); } while ((buffer_status & SD_CTRL_BUFFERSTATUS_CMD_BUSY) != 0); MMC_DEBUG(3, "Buffer status 0x%04x - after check buffer\n", buffer_status); switch (request->cmd) { case MMC_READ_MULTIPLE_BLOCK: H3900_ASIC3_SD_CTRL_StopInternal = SD_CTRL_STOP_INTERNAL_AUTO_ISSUE_CMD12; cdc = SD_CTRL_COMMAND_TRANSFER_READ | SD_CTRL_COMMAND_DATA_PRESENT | SD_CTRL_COMMAND_MULTI_BLOCK; cdc |= rinfo[request->rtype].cdc_flags; mmc_asic3_set_transfer(request->block_len, request->nob); mmc_asic3_set_command(request->cmd | cdc, request->arg); transfer = 1; break; case MMC_WRITE_MULTIPLE_BLOCK: H3900_ASIC3_SD_CTRL_StopInternal = SD_CTRL_STOP_INTERNAL_AUTO_ISSUE_CMD12; cdc = SD_CTRL_COMMAND_TRANSFER_WRITE | SD_CTRL_COMMAND_DATA_PRESENT | SD_CTRL_COMMAND_MULTI_BLOCK; cdc |= rinfo[request->rtype].cdc_flags; mmc_asic3_set_transfer(request->block_len, request->nob); mmc_asic3_set_command(request->cmd | cdc, request->arg); transfer = 1; break; case MMC_READ_SINGLE_BLOCK: cdc = SD_CTRL_COMMAND_TRANSFER_READ | SD_CTRL_COMMAND_DATA_PRESENT; cdc |= rinfo[request->rtype].cdc_flags; mmc_asic3_set_transfer(request->block_len, request->nob); mmc_asic3_set_command(request->cmd | cdc, request->arg); transfer = 1; break; case MMC_WRITE_BLOCK: cdc = SD_CTRL_COMMAND_TRANSFER_WRITE | SD_CTRL_COMMAND_DATA_PRESENT; cdc |= rinfo[request->rtype].cdc_flags; mmc_asic3_set_transfer(request->block_len, request->nob); mmc_asic3_set_command(request->cmd | cdc, request->arg); transfer = 1; break; default: if (request->cmd == MMC_GO_IDLE_STATE) cdc |= SD_CTRL_COMMAND_TYPE_IDLE; if (request->cmd == MMC_APP_CMD) cdc |= SD_CTRL_COMMAND_TYPE_ACMD; cdc |= rinfo[request->rtype].cdc_flags; mmc_asic3_set_command(request->cmd | cdc, request->arg); rw_end = 1; break; } timeout = 0; do { buffer_status = H3900_ASIC3_SD_CTRL_BufferCtrl; if ((buffer_status & SD_CTRL_BUFFERSTATUS_CMD_TIMEOUT) != 0) { MMC_DEBUG(0, "got status buffer COMMAND TIMEOUT - inside loop after send cmd\n"); MMC_DEBUG(0, "detail0 error status 0x%04x\n", H3900_ASIC3_SD_CTRL_ErrorStatus0); MMC_DEBUG(0, "detail1 error status 0x%04x\n", H3900_ASIC3_SD_CTRL_ErrorStatus1); retval = MMC_ERROR_TIMEOUT; goto end_command; } if ((buffer_status & SD_CTRL_BUFFERSTATUS_DATA_TIMEOUT) != 0) { MMC_DEBUG(0, "got status buffer DATA TIMEOUT - inside loop after send cmd\n"); MMC_DEBUG(0, "detail0 error status 0x%04x\n", H3900_ASIC3_SD_CTRL_ErrorStatus0); MMC_DEBUG(0, "detail1 error status 0x%04x\n", H3900_ASIC3_SD_CTRL_ErrorStatus1); retval = MMC_ERROR_TIMEOUT; goto end_command; } if ((buffer_status & (SD_CTRL_BUFFERSTATUS_ILLEGAL_ACCESS | SD_CTRL_BUFFERSTATUS_CMD_INDEX_ERROR | SD_CTRL_BUFFERSTATUS_CRC_ERROR | SD_CTRL_BUFFERSTATUS_STOP_BIT_END_ERROR | SD_CTRL_BUFFERSTATUS_BUFFER_OVERFLOW | SD_CTRL_BUFFERSTATUS_BUFFER_UNDERFLOW)) != 0) { retval = MMC_ERROR_GENERAL; MMC_DEBUG(0, "Buffer status ERROR 0x%04x - inside loop after send cmd\n", buffer_status); MMC_DEBUG(0, "detail0 error status 0x%04x\n", H3900_ASIC3_SD_CTRL_ErrorStatus0); MMC_DEBUG(0, "detail1 error status 0x%04x\n", H3900_ASIC3_SD_CTRL_ErrorStatus1); goto end_command; } if ((buffer_status & SD_CTRL_BUFFERSTATUS_BUFFER_READ_ENABLE) != 0) { MMC_DEBUG(3, "got status buffer READ ENABLE\n"); read_enable = 1; H3900_ASIC3_SD_CTRL_BufferCtrl &= ~SD_CTRL_BUFFERSTATUS_BUFFER_READ_ENABLE; } if ((buffer_status & SD_CTRL_BUFFERSTATUS_BUFFER_WRITE_ENABLE) != 0) { MMC_DEBUG(3, "got status buffer WRITE ENABLE\n"); write_enable = 1; H3900_ASIC3_SD_CTRL_BufferCtrl &= ~SD_CTRL_BUFFERSTATUS_BUFFER_WRITE_ENABLE; } if ((read_enable == 1) && (transfer == 1) && (request->nob > 0)) { MMC_DEBUG(3, "starting receive data\n"); mmc_asic3_receive_data(request); timeout = 0; } if ((write_enable == 1) && (transfer == 1) && (request->nob > 0)) { MMC_DEBUG(3, "starting transit data\n"); mmc_asic3_transmit_data(request); timeout = 0; } if ((H3900_ASIC3_SD_CTRL_CardStatus & SD_CTRL_CARDSTATUS_RW_END) != 0) { MMC_DEBUG(3, "got END of RW buffer operation - inside loop after send cmd\n"); rw_end = 1; H3900_ASIC3_SD_CTRL_CardStatus &= ~SD_CTRL_CARDSTATUS_RW_END; H3900_ASIC3_SD_CTRL_StopInternal = 0; } if ((H3900_ASIC3_SD_CTRL_CardStatus & SD_CTRL_CARDSTATUS_RESPONSE_END) != 0) { MMC_DEBUG(2, "got RESPONSE - inside loop after send cmd\n"); res_end = 1; H3900_ASIC3_SD_CTRL_CardStatus &= ~SD_CTRL_CARDSTATUS_RESPONSE_END; mmc_asic3_get_response(request); } if (timeout > 3000000) { MMC_DEBUG(0, "TIMEOUT - inside loop after send cmd\n"); retval = MMC_ERROR_TIMEOUT; goto end_command; } timeout++; udelay(1); } while ((res_end == 0) || (rw_end == 0)); MMC_DEBUG(3, "Card status 0x%04x - after cmd, before response parse\n", H3900_ASIC3_SD_CTRL_CardStatus); MMC_DEBUG(3, "Buffer status 0x%04x - after cmd, before response parse\n", H3900_ASIC3_SD_CTRL_BufferCtrl); if ((request->cmd == SD_APP_OP_COND) && (retval == MMC_NO_ERROR)) { g_data.flag = 1; } if ((request->cmd == SD_APP_SET_BUS_WIDTH) && (retval == MMC_NO_ERROR)) { H3900_ASIC3_SD_CTRL_MemCardOptionSetup = MEM_CARD_OPTION_REQUIRED | MEM_CARD_OPTION_DATA_RESPONSE_TIMEOUT(14) | MEM_CARD_OPTION_C2_MODULE_NOT_PRESENT | MEM_CARD_OPTION_DATA_XFR_WIDTH_4; }end_command: request->result = retval; mmc_cmd_complete(request);}static void mmc_asic3_enable_hardware(void){}static void mmc_asic3_disable_hardware(void){}static int mmc_asic3_slot_is_empty(int slot){ return 0;}static void mmc_asic3_slot_up(void){}static void mmc_asic3_slot_down(void){}static int mmc_asic3_slot_init(void){ MMC_DEBUG(2, "");// mmc_asic3_slot_up(); return 0;}static void mmc_asic3_slot_cleanup(void){ MMC_DEBUG(2, "");// mmc_asic3_slot_down();}int mmc_asic3_suspend(void){// mmc_asic3_slot_down(); return 0;}void mmc_asic3_resume(void){// mmc_asic3_slot_up();}static struct mmc_slot_driver dops = { owner: THIS_MODULE, name: "ASIC3 MMC/SD", ocr: 0x00ffc000, flags: MMC_SDFLAG_MMC_MODE | MMC_SDFLAG_SD_MODE | MMC_SDFLAG_4BIT_BUS, init: mmc_asic3_slot_init, cleanup: mmc_asic3_slot_cleanup, is_empty: mmc_asic3_slot_is_empty, send_cmd: mmc_asic3_send_command, set_clock: mmc_asic3_set_clock,};int __init mmc_asic3_init(void){ int retval = 0; MMC_DEBUG(2, ""); if (!machine_is_h3900 ()) { /* seems to put h3900 into some bad state */ if (machine_is_h1900 ()) { H3900_ASIC3_SDHWCTRL_SDConf = ASIC3_SDHWCTRL_CLKSEL | ASIC3_SDHWCTRL_SUSPEND; mdelay(10); } else /* No one else uses asic3, so return an error code so we can unload the module */ return -ENODEV; } g_data.flag = 0; retval = mmc_register_slot_driver(&dops, 1); if (retval < 0) PALERT("unable to register slot"); return retval;}void __exit mmc_asic3_cleanup(void){ MMC_DEBUG(2, ""); H3900_ASIC3_SD_CONFIG_SDHC_Power1 = SD_CONFIG_POWER1_PC_OFF; mdelay(1); H3900_ASIC3_SDHWCTRL_SDConf &= ~ASIC3_SDHWCTRL_SDPWR; mdelay(1); H3900_ASIC3_CLOCK_CDEX &= ~CLOCK_CDEX_EX1; mdelay(1); H3900_ASIC3_SDHWCTRL_SDConf |= ASIC3_SDHWCTRL_SUSPEND; mdelay(10); mmc_unregister_slot_driver(&dops);}module_init(mmc_asic3_init);module_exit(mmc_asic3_cleanup);MODULE_AUTHOR("Pawel Kolodziejski");MODULE_DESCRIPTION("ASIC3 MMC/SD controller driver");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -