📄 ftsdc010.c
字号:
cid->ManufactureYear = ((cid_word[0] & 0x0000F000) >> 12) + SD_DEFAULT_YEAR_CODE; return TRUE;}uint sd_read_timeout_cycle(uint clock, sd_csd_t *csd){#if 1 //ivan for 100ms maximux from document "ProdManualIndGradeSDv1.0[1].pdf" chapter A-2 return clock/10; // /10;#else uint ret, total, per; per = 1000000000 / clock; total = (csd->TAAC_u + (csd->NSAC_u * 100 * per)) * 100; if (total > (100 * 1000 * 1000)) total = 100 * 1000 * 1000; ret = total / per; return ret;#endif}uint sd_block_size_convert(uint size){ uint ret = 0; while (size >= 2) { size >>= 1; ret++; } return ret;}int sd_select_card(sd_card_t *info){ uint status; /* send CMD7 with valid RCA to select */ if (!sdc_send_cmd(SD_SELECT_CARD_CMD | SDC_CMD_REG_NEED_RSP, ((uint)info->RCA) << 16, &status)) return FALSE; if (!sd_check_err(status)) return FALSE; return TRUE;}int sd_set_transfer_state(sd_card_t *info){ uint state; int count = 0; while (count++ < SD_CARD_STATE_CHANGE_RETRY_COUNT) { if (!sd_get_card_state(info, &state)) return FALSE; switch (state) { case SD_IDLE_STATE: case SD_READY_STATE: case SD_IDENT_STATE: printk("%s() error\n", __func__); return FALSE; case SD_DIS_STATE: if (!sd_operation_complete(info, SD_STBY_STATE)) return FALSE; break; case SD_TRAN_STATE: return TRUE; case SD_DATA_STATE: if (sd_operation_complete(info, SD_TRAN_STATE)) return TRUE; if (sd_err_code != ERR_NO_ERROR) return FALSE; if (!sd_stop_transmission()) return FALSE; break; case SD_RCV_STATE: if (sd_operation_complete(info, SD_TRAN_STATE)) return TRUE; if (sd_err_code != ERR_NO_ERROR) return FALSE; if (!sd_stop_transmission()) return FALSE; break; case SD_PRG_STATE: if (!sd_operation_complete(info, SD_TRAN_STATE)) return FALSE; break; case SD_STBY_STATE: if (!sd_select_card(info)) return FALSE; } } P_DEBUG("%s() error\n", __func__); return FALSE;}uint sd_write_timeout_cycle(uint clock, sd_csd_t *CSD){#if 1 //ivan for 250ms maximux from document return clock/4; //ijsung hack#else uint ret, total, pre; pre = 1000000000 / clock; total = CSD->WriteSpeedFactor * 100 * (CSD->TAAC_u + (CSD->NSAC_u * 100 * pre)); if (total > (100 * 1000 * 1000)) total = 100 * 1000 * 1000; ret = total / pre; return ret;#endif}//CMD8//CMD8 should be added in the identification state, just after reset commandstatic int SD_SendInterfaceConditionCmd(uint arg){ uint Response; if(!sdc_send_cmd(SD_SEND_IF_COND_CMD | SDC_CMD_REG_NEED_RSP, arg, &Response)){ printk("CMD8: Card does not support SPEC 2.0 or voltage is not supported!\n"); printk("If your card is not support SPEC 2.0, don't care this command error message!\n"); return FALSE; } if( Response != arg ) return FALSE; return TRUE;}int sd_card_identify(sd_card_t *info){ uint rca, status, cid[4]; /* reset all cards */ if (!sdc_send_cmd(SD_GO_IDLE_STATE_CMD, 0, NULL)) return FALSE; udelay(1000); //for SD 2.0, execute CMD8 first to determine the voltage supported by the card SD_SendInterfaceConditionCmd((0x1 << 8)|( 0xAA << 0) ); /* Do operating voltage range validation */ /* get OCR register */ if (!sd_get_ocr(info, SDC_OCR, (uint *) &info->OCR)) return FALSE; /* ckeck the operation conditions */ if ((info->OCR & SDC_OCR) == 0) { sd_err_code = ERR_OUT_OF_VOLF_RANGE; return FALSE; } /* send CMD2 to get CID register */ if (!sdc_send_cmd(SD_ALL_SEND_CID_CMD | SDC_CMD_REG_NEED_RSP | SDC_CMD_REG_LONG_RSP, 0, cid)) return FALSE; if (info->CardType == MEMORY_CARD_TYPE_SD) { /* send CMD3 to get RCA register */ if (!sdc_send_cmd(SD_SEND_RELATIVE_ADDR_CMD | SDC_CMD_REG_NEED_RSP, 0, &rca)) return FALSE; info->RCA = (ushort) (rca >> 16); } else { /* so far, we only support one interface, so we can give RCA any value */ info->RCA = 0x1; /* send CMD3 to set RCA register */ if (!sdc_send_cmd(SD_SEND_RELATIVE_ADDR_CMD | SDC_CMD_REG_NEED_RSP, (info->RCA << 16), &status)) return FALSE; if (!sd_check_err(status)) return FALSE; } return TRUE;}int sd_card_init(sd_card_t *info){ uint clock; P_DEBUG("--> %s\n", __func__); if ((SDC_R_REG(SDC_STATUS_REG) & SDC_STATUS_REG_CARD_INSERT) != SDC_CARD_INSERT) return FALSE; sd_err_code = ERR_NO_ERROR; /* At first, set card type to SD */ info->CardType = MEMORY_CARD_TYPE_SD; /* set memory card type */ sdc_set_card_type(info->CardType); /* start card idenfication process */ if (!sd_card_identify(info)) { printk("this is not SD card\n"); sd_err_code = ERR_NO_ERROR; info->CardType = MEMORY_CARD_TYPE_MMC; /* set memory card type */ sdc_set_card_type(info->CardType); if (!sd_card_identify(info)) return FALSE; } /* get CSD */ if (!sd_set_card_standby(info)) return FALSE; /* send CMD9 to get CSD register */ if (!sdc_send_cmd(SD_SEND_CSD_CMD | SDC_CMD_REG_NEED_RSP | SDC_CMD_REG_LONG_RSP, ((uint) info->RCA) << 16, info->CSDWord)) return FALSE; sd_csd_parse(&info->CSD, info->CSDWord);#if 0 if (info->CSD.ReadBlockLength != SD_SECTOR_SIZE) { printk("Sector size is mis-matched (SD CSD report=0x%X,SD_SECTOR_SIZE=0x%X)\n", info->CSD.ReadBlockLength, SD_SECTOR_SIZE); return FALSE; }#else if (info->CSD.ReadBlockLength != SD_SECTOR_SIZE) { //printk("Sector size is mis-matched (SD CSD report=0x%X,SD_SECTOR_SIZE=0x%X)\n", info->CSD.ReadBlockLength, SD_SECTOR_SIZE); printk("Sector size (SD CSD report=0x%X)\n", info->CSD.ReadBlockLength); info->CSD.ReadBlockLength = SD_SECTOR_SIZE; }#endif /* get CID */ /* send CMD10 to get CID register */ if (!sdc_send_cmd(SD_SEND_CID_CMD | SDC_CMD_REG_NEED_RSP | SDC_CMD_REG_LONG_RSP, ((uint) info->RCA) << 16, info->CIDWord)) return FALSE; sd_cid_parse(&info->CID, info->CIDWord); /* Set card bus clock. sdc_set_bus_clock() will give the real card bus clock has been set. */ clock = sdc_set_bus_clock(info, info->CSD.TransferSpeed); info->ReadAccessTimoutCycle = sd_read_timeout_cycle(clock, &(info->CSD)); info->WriteAccessTimoutCycle = sd_write_timeout_cycle(clock, &(info->CSD)); /* set bus width */ if (!sdc_set_bus_width(info)) return FALSE; /* check write protect */ info->WriteProtect = ((SDC_R_REG(SDC_STATUS_REG) & SDC_STATUS_REG_CARD_LOCK) == SDC_STATUS_REG_CARD_LOCK) ? TRUE : FALSE; if(info->WriteProtect == TRUE) printk("SD/MMC Card is Write Protected\n"); info->ActiveState = TRUE; P_DEBUG("<-- %s\n", __func__); return TRUE;}int sd_card_insert(sd_card_t *info){ P_DEBUG("--> %s\n", __func__); /* reset host interface controller */ sdc_reset(); /* turn on clock using default clock*/ SDC_W_REG(SDC_CLOCK_CTRL_REG, SDC_R_REG(SDC_CLOCK_CTRL_REG)&0xff); if (!sd_card_init(info)) { printk("root initialize failed\n"); return FALSE; } /* set interrupt mask register */ SDC_W_REG(SDC_INT_MASK_REG, SDC_STATUS_REG_CARD_CHANGE | SDC_STATUS_REG_DATA_TIMEOUT); P_DEBUG("<-- %s\n", __func__); return TRUE;}/* Free IRQ and DMA resources */void sd_free(sd_dev_t *dev){ //john release_region(FTSDC_VA_BASE, 0x48); /* return ioport */ if(SD_MODE != AUTO_DETECT) free_irq(FTSDC_IRQ, dev); /* return Hotswapping irq */#ifdef CONFIG_FTSDC010_USE_APBDMA //CONFIG_FTSDC010_USE_APBDMA fa_free_apb_dma(SD_DMA_CHANNEL); sd_card_info.DMAEnable = FALSE;#endif#ifdef CONFIG_FTSDC010_USE_AHBDMA fa_free_ahb_dma(SD_DMA_CHANNEL); sd_card_info.DMAEnable = FALSE;#endif}int sd_card_remove(sd_card_t *info){ sd_err_code = ERR_NO_ERROR; info->ActiveState = FALSE; info->WriteProtect = FALSE; info->RCA = 0; /* reset host interface controller */ sdc_reset(); /* set interrupt mask register */ SDC_W_REG(SDC_INT_MASK_REG, SDC_STATUS_REG_CARD_CHANGE | SDC_STATUS_REG_DATA_TIMEOUT); sd_err_code = ERR_CARD_NOT_EXIST; /* turn off clock */ SDC_W_REG(SDC_CLOCK_CTRL_REG, SDC_R_REG(SDC_CLOCK_CTRL_REG) | 0x100); return TRUE;}irqreturn_t sd_hotswap_interrupt_handler(int irq, void *dev_id, struct pt_regs *dummy){ uint status; sd_dev_t *dev = dev_id; P_DEBUG("--> %s, irq=%d\n", __func__, irq); /* When the card is inserted or removed, we must delay a short time to make sure */ /* the SDC_STATUS_REG_CARD_INSERT bit of status register is stable */ udelay(1000); status = SDC_R_REG(SDC_STATUS_REG); if ((status & SDC_STATUS_REG_CARD_CHANGE) == SDC_STATUS_REG_CARD_CHANGE) { SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_CARD_CHANGE | SDC_STATUS_REG_DATA_TIMEOUT); if ((status & SDC_STATUS_REG_CARD_INSERT) == SDC_CARD_INSERT) { printk("Card Insert\n"); error_flag = 0; if(SD_MODE != AUTO_DETECT) { dev->card_state = SD_CARD_INSERT; sd_card_insert(&sd_card_info); }else sys_kill(mpid,SIGUSR1); } else { printk("Card Remove\n"); if(SD_MODE != AUTO_DETECT) { dev->card_state = SD_CARD_REMOVE; sd_card_remove(&sd_card_info); }else sys_kill(mpid,SIGUSR2); /* remove all current transfers as I/O error*/#if 0 //def CONFIG_FTSDC010_USE_APBDMA //ASYNC spin_lock_irqsave(&io_request_lock, status); INIT_REQUEST; while(!QUEUE_EMPTY) end_request(0); bh_busy=0; spin_unlock_irqrestore(&io_request_lock, status);#endif } } else if ((status & SDC_STATUS_REG_DATA_TIMEOUT) == SDC_STATUS_REG_DATA_TIMEOUT) { SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_CARD_CHANGE | SDC_STATUS_REG_DATA_TIMEOUT); #if 0 //def CONFIG_FTSDC010_USE_APBDMA //ASYNC printk("Data timeout. Retry.\n"); sd_clustered_bh(2);#else printk("Data timeout. Retry.\n");#endif } //P_DEBUGG("card state=%d\n", dev->card_state); P_DEBUG("<-- %s\n", __func__); return IRQ_HANDLED;}#if 0 //def CONFIG_FTSDC010_USE_APBDMA//#define A320_SD_USE_ASYNC_DMAstatic inline int wait_completion(int doWait, int doSet){ int retry=0; if(doWait) { /* make sure SDC has completed its job */wait_again: if (!sd_wait_transfer_state(&sd_card_info)) { if(retry++ < 10) { goto wait_again; }else { printk("%s: wait transfer state failed.\n",__func__); return 0; } } retry=0; } if(doSet) {set_again: if(!sd_set_transfer_state(&sd_card_info)) { if(retry++ < 10) { goto set_again; }else { printk("%s: set transfer state failed.\n",__func__); return 0; } } } return 1;}/* erase */static int sd_erase(uint sector, uint sector_nr){ uint status; printk("%s: erase %d sectors from %d\n",__func__,sector_nr, sector); if(!sdc_send_cmd(SD_ERASE_SECTOR_START_CMD | SDC_CMD_REG_NEED_RSP, sector*SD_SECTOR_SIZE, &status)) { printk("%s: SD_ERASE_SECTOR_START_CMD error\n", __func__); return -1; } if(!sdc_send_cmd(SD_ERASE_SECTOR_END_CMD | SDC_CMD_REG_NEED_RSP, (sector+sector_nr)*SD_SECTOR_SIZE, &status)) { printk("%s: SD_ERASE_SECTOR_END_CMD error\n", __func__); return -2; } if(!sdc_send_cmd(SD_ERASE_CMD | SDC_CMD_REG_NEED_RSP, 0, &status)) { printk("%s: SD_ERASE_CMD error\n", __func__); return -3; } if(!wait_completion(1, 1)) { printk("%s: wait_completion failed\n",__func__); return -4; } printk("%s: erase complete\n",__func__); return 0;}static int sdc_config_multi_transfer(int isWrite, uint sector, uint sector_nr){ static int last_operation=READ; static sd_card_t * info = &sd_card_info; uint status, retry=0; sector+=sector_offset;again: //If last operation is write, wait for its completion if(!wait_completion(1 /*last_operation*/, 1)) printk("%s: wait_completion failed\n",__func__); last_operation=isWrite; if (!sdc_set_block_size(SD_SECTOR_SIZE)) return FALSE;#if 0 /* Check DMA cycles */ status=*(volatile unsigned *)(priv->channel_base+APBDMA_DMA_CYCLE_0x8); if(status) { printk("%s: ERROR: Unfinished DMA!!(%d left)\n",__func__, status); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -