📄 mmc_main.c
字号:
} if(counter == 0) { ret = MMCSD_ERROR; FAILED("TIME OUT.."); goto dma_write_end; } /******************************************************* * Write Done *******************************************************/ if(ret==MMCSD_OK) { counter = 0xFFFF; while(counter--) { if(device->port == 1) g_mmcsd_status = mmcsdr_status_2; else g_mmcsd_status = mmcsdr_status; TRACE("g_mmcsd_status is 0x%0lX (for Write-DONE)",(unsigned long)g_mmcsd_status); if(g_mmcsd_status&0x0004) { TRACE("8)ERROR!"); ret = MMCSD_ERROR; break; } else if((g_mmcsd_status&0x1000)!=0) { ret = MMCSD_OK; break; } mmcsd_delay(0xFFFF); } if(counter==0) { ret = MMCSD_ERROR; FAILED("Time Out for Write-DONE."); goto dma_write_end; } }dma_write_end: g_mmcsd_cmd[device->port] = 0; if((ret == MMCSD_OK)&&(device->cur_num>1)) { MMCSD_Responses rp;// TRACE("CMD12 -- Last Block."); ret2=_MMCSD_NoDataCommand(MMCSD_CMD12,0,MMCSDB_R1,device->port); _MMCSD_GetResponses(&rp,MMCSDB_R1,device->port); }// INFO("Check Status.....(after cmd12)"); state =MMCSD_TRANSFER; mmcsd_check_status(device,&state); if(int_mask != 0xFFFFFFFF) {// TRACE("Enable Interrupt."); _MMCSD_Restore_Mask(int_mask,device->port); } mmcsd_free_buffer(device);// TRACE("15)return with ret = %lx,ret2 = %lx",ret,ret2); return(ret|ret2);}void mmcsd_free_buffer(MMCSD_Dev *device){ device->cur_num = 0; device->addr = 0;}/****************************************************************************** * Function Name: mmcsd_sector_erase * * Input: * device: the related device * blks: the blocks that will be erased. * * Value Returned: * 0: success. * 1: failure. * * Description: * this routine will erase indicated group. * * Modification History: * 30 DEC,2001, Initial version. Yiwei Zhao *****************************************************************************/static int mmcsd_sector_erase(MMCSD_Dev *device, MMCSD_Blks *blks) { int ret; u32 state; TRACE("Erase the sector %ld ", (long int)(blks->start)); /******************************************************************** * Lock the device. *******************************************************************/#ifndef MMCSD_TEST down_interruptible(&(device->sema)); g_selected_lock[device->port].device = device;#endif /******************************************************************** * Identify the Card State ( Process only for Stand By State) *******************************************************************/ state =MMCSD_TRANSFER; ret = mmcsd_check_status(device,&state); if(ret) { FAILED(" Check Status failed."); goto sector_erase_ret; } /******************************************************************** * Erase *******************************************************************/ ret = _MMCSD_TagSectorStart(blks->start); if(ret) { TRACE("TagSectorStart error"); goto sector_erase_ret; } //ret = _MMCSD_TagSectorEnd(blks->start); ret = _MMCSD_TagSectorEnd(blks->start+device->phy_sectorsize-1); if(ret) { TRACE("TagSectorEnd error"); goto sector_erase_ret; } ret = _MMCSD_Erase(); if(ret) { TRACE("Erase error"); goto sector_erase_ret; }sector_erase_ret: /******************************************************************** * Unlock the selected device structure. *******************************************************************/ state =MMCSD_TRANSFER; mmcsd_check_status(device,&state);#ifndef MMCSD_TEST up(&(device->sema));#endif return ret;}/****************************************************************************** * Function Name: mmcsd_ReadBlock * * Input: None. * * Value Returned: * * MMCSD_STATUS * * Description: * * * Modification History: * 30 DEC,2001, Initial version. Yiwei Zhao *****************************************************************************/MMCSD_STATUS mmcsd_ReadBlock(MMCSD_Dev *device,u32 start_addr,u16 nsects, u8 *buff ){ u16 i; u32 read_addr; MMCSD_STATUS ret; u8 *cur_buf; /************************************************************************ * Initialize local variables *************************************************************************/ ret = read_addr = 0; /* SEND/RECEIVE ERROR */ for ( i = 0 ; i < nsects ; i++ ) { /************************************************************ * Set the first address of read sector **************************************************************/ read_addr = ( start_addr + (MMCSD_MINIMUM_BLK_SIZE*i) ); /************************************************************ * Create cmd **************************************************************/ cur_buf = buff+(MMCSD_MINIMUM_BLK_SIZE*i);#ifdef MMCSD_READ_DMA ret=mmcsd_DMA_ReadSingleBlock(device,read_addr, cur_buf); if(ret==MMCSD_OK) // Only for DMA { // Endian processing#ifdef MMCSD_DMA_ENDIAN_ERR _mmcsd_16_big_2_little(cur_buf,MMCSD_MINIMUM_BLK_SIZE);#endif }#else ret=mmcsd_ReadSingleBlock(device,read_addr, cur_buf); #endif if (ret) { break; } } return( ret );}/****************************************************************************** * Function Name: mmcsd_ReadSingleBlock * * Input: None. * * Value Returned: * * MMCSD_STATUS * * Description: * * Modification History: * 30 DEC,2001, Initial version. Yiwei Zhao *****************************************************************************/MMCSD_STATUS mmcsd_DMA_ReadSingleBlock(MMCSD_Dev *device,u32 addr,u8 * buff){ MMCSD_STATUS ret; u32 channel,status,int_mask,state; int timeleft; device->result = MMCSD_OK; channel = device->dma_channel; ret = mmcsd_DmaStartTransfer( device, buff, MMCSD_MINIMUM_BLK_SIZE, MMCSD_READ, device->bit_width); if(ret != MMCSD_OK) { FAILED("mmcsd_DmaStartTransfer failed !"); return ret; } state = MMCSD_TRANSFER; ret = mmcsd_check_status(device,&state); _MMCSD_Mask_interrupt(0x7F,&int_mask,device->port); _MMCSD_StopClk(device->port); if(device->bit_width) { _MMCSD_SetCmd(MMCSD_CMD17,addr,MMCSD_BUS_4BIT|MMCSDB_DATEN|MMCSDB_R1,device->port); // Read Single BLK } else { _MMCSD_SetCmd(MMCSD_CMD17,addr,MMCSDB_DATEN|MMCSDB_R1,device->port); // Read Single BLK } g_mmcsd_cmd[device->port] = MMCSD_CMD17; _MMCSD_StartClk(device->port); if((ret=_MMCSD_WaitUntil(MMCSD_CMD_DONE,device->port))!=0) { FAILED("WaitCMDDone ret 0x%lx",(unsigned long)ret); goto dma_read_end; } TRACE("Enable DMA..");#ifdef CONFIG_ARCH_MX1ADS enable_dma(channel);#endif#ifdef CONFIG_ARCH_MX2ADS mx_dma_start(channel);#endif timeleft = interruptible_sleep_on_timeout(&(device->select_wait),100); if(!timeleft) { TRACE("read failed, Timeout!"); ret = MMCSD_ERROR; goto dma_read_end; } status = device->result; TRACE("waked up! status = %x", status); if(status&0x800) { ret = MMCSD_OK; goto dma_read_end; } else if(status&0x3) { TRACE("g_mmcsd_status 0x%lx",(unsigned long)status); ret = MMCSD_ERROR; goto dma_read_end; } // in fact, although status&0x800 ==0, read succeed.dma_read_end:#ifdef CONFIG_ARCH_MX1ADS disable_dma(channel);#endif #ifdef CONFIG_ARCH_MX2ADS //disable dma _reg_DMA_CCR(channel) &= 0xFFFFFFFE;#endif _MMCSD_Restore_Mask(int_mask,device->port); g_mmcsd_cmd[device->port] = 0; return ret;}MMCSD_STATUS mmcsd_ReadSingleBlock(MMCSD_Dev *device,u32 addr,u8 * buff){ MMCSD_STATUS ret; u32 temp32,j,int_mask,total; u16 temp16; u8 *pbuff; int i; pbuff=buff; _MMCSD_Mask_interrupt(0x7F,&int_mask,device->port); total = 0; _MMCSD_StopClk(device->port); //Ricky if(device->bit_width) { _MMCSD_SetCmd(MMCSD_CMD17,addr,MMCSD_BUS_4BIT|MMCSDB_DATEN|MMCSDB_R1,device->port); // Read Single BLK } else { _MMCSD_SetCmd(MMCSD_CMD17,addr,MMCSDB_DATEN|MMCSDB_R1,device->port); // Read Single BLK } g_mmcsd_cmd[device->port] = MMCSD_CMD17; _MMCSD_StartClk(device->port); while(1) { if(device->port == 1) g_mmcsd_status = (mmcsdr_status_2); else g_mmcsd_status = (mmcsdr_status); if((g_mmcsd_status&0x088B) == 0) { continue; } j = 0xFF; while(j--); if(g_mmcsd_status&0x000B) { FAILED("Read Error (status = 0x%lx",(unsigned long)g_mmcsd_status); ret = MMCSD_ERROR; goto signle_read_end; }/* if(g_mmcsd_status&0x0008) { goto single_read_try_again; }*/ if((g_mmcsd_status&0x0080)!=0) // Buffer is FULL { //TRACE("FIFO is full"); if(device->bit_width == 0) { for(i = 0;i < 8; i++) { if(device->port == 1) temp32 = mmcsdr_buffer_access_2; else temp32 = mmcsdr_buffer_access; temp16 = (u16)temp32;#ifdef MMCSD_DMA_ENDIAN_ERR *pbuff = (temp16&0xFF00)>>8; pbuff++; *pbuff = (temp16&0x00FF); pbuff++;#else *pbuff = (temp16&0x00FF); pbuff++; *pbuff = (temp16&0xFF00)>>8; pbuff++; #endif } total += 16; } else { for(i = 0;i < 32; i++) { if(device->port == 1) temp32 = mmcsdr_buffer_access_2; else temp32 = mmcsdr_buffer_access; temp16 = (u16)temp32;#ifdef MMCSD_DMA_ENDIAN_ERR *pbuff = (temp16&0xFF00)>>8; pbuff++; *pbuff = (temp16&0x00FF); pbuff++;#else *pbuff = (temp16&0x00FF); pbuff++; *pbuff = (temp16&0xFF00)>>8; pbuff++;#endif } total += 64; } } if((g_mmcsd_status&0x0800) != 0) // TRANS Done { //TRACE("Transfer done! g_mmcsd_status = 0x%x",g_mmcsd_status); ret = MMCSD_OK; goto signle_read_end; }// TRACE("Sleep on.. status=%x",g_mmcsd_status);// interruptible_sleep_on(&(device->select_wait));// TRACE("Waked up ! status = 0x%x",g_mmcsd_status);// }signle_read_end: _MMCSD_StopClk(device->port); //Karen need more consideration how to implement this!!!!!!!!!!!!!!!! _MMCSD_Restore_Mask(int_mask,device->port);//Karen need more consideration how to implement this!!!!!!!!!!!!!!!! g_mmcsd_cmd[device->port] = 0; return ret;}/****************************************************************************** * Function Name: mmcsd_DmaStartTransfer * * Input: * * Value Returned: * * Description: * * * Modification History: * 30 DEC,2001, Initial version. Yiwei Zhao *****************************************************************************/int mmcsd_DmaStartTransfer(MMCSD_Dev *device,u8 * buff,u32 counter, u8 mode,u8 is_4_bit){ int channel; channel = device->dma_channel; if(mode == MMCSD_READ) {#ifdef CONFIG_ARCH_MX1ADS _reg_DMA_DAR(channel) = (u32)__virt_to_phys(buff); _reg_DMA_SAR(channel) = (MMCSDR_BUFFER_ACCESS&0x0FFFFFFF); _reg_DMA_CNTR(channel) = counter; _reg_DMA_CCR(channel) = 0x00000828; // Source Size = 16,Des Len = 32 _reg_DMA_RSSR(channel) = 0xD; if(is_4_bit) { _reg_DMA_BLR(channel) = 0x0; // Burst Len 64; //_reg_DMA_BLR(channel) = 0x20; // Burst Len 32; } else { _reg_DMA_BLR(channel) = 0x10; // Burst Len 16; }#endif#ifdef CONFIG_ARCH_MX2ADS (device->dma).sourceType = DMA_TYPE_FIFO; (device->dma).sourcePort = DMA_MEM_SIZE_16; (device->dma).destType = DMA_TYPE_LINEAR; (device->dma).destAddr = (u32)__virt_to_phys(buff); (device->dma).destPort = DMA_MEM_SIZE_32; (device->dma).count = counter; if(device->port == 0) { (device->dma).sourceAddr = 0x10013038;//sdhc1, (device->dma).request = 0x7;//sdhc1 } else { (device->dma).sourceAddr = 0x10014038;// for sdhc2 is 0x10014038 (device->dma).request = 0x6;// sdhc2 is 0x6; } if(is_4_bit) { (device->dma).burstLength = 0x0; //burst length 64 } else { (device->dma).burstLength = 0x10; //burst len 16 } mx_dma_set_config(device->dma_channel,&(device->dma));// mx_dump_dma_register(device->dma_channel);#endif } else {#ifdef CONFIG_ARCH_MX1ADS // _reg_DMA_SAR(channel) = (u32)_MMCSD_get_phy_addr(buff); _reg_DMA_SAR(channel) = (u32)__virt_to_phys(buff); _reg_DMA_DAR(channel) = (MMCSDR_BUFFER_ACCESS&0x0FFFFFFF); _reg_DMA_CNTR(channel) = counter; //_reg_DMA_CCR(channel) = 0x00002088; // Source Size = 32,Des Len = 16 _reg_DMA_CCR(channel) = 0x2088; // Source Size = 32,Des Len = 16 _reg_DMA_RSSR(channel) = 0xD; if(is_4_bit) { _reg_DMA_BLR(channel) = 0x0; // Burst Len 64; //_reg_DMA_BLR(channel) = 0x20; // Burst Len 32; } else { _reg_DMA_BLR(channel) = 0x10; // Burst Len 16; // _reg_DMA_BLR(channel) = 0x8; // Burst Len 8; }#endif#ifdef CONFIG_ARCH_MX2ADS (device->dma).sourceType = DMA_TYPE_LINEAR; (device->dma).sourceAddr = (u32)__virt_to_phys(buff); (device->dma).sourcePort = DMA_MEM_SIZE_32; (device->dma).destType = DMA_TYPE_FIFO; (device->dma).destPort = DMA_MEM_SIZE_16; (device->dma).count = counter;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -