📄 sdio_drv.c
字号:
#include "kal_release.h"
#include "reg_base.h"
#include "app_buff_alloc.h"
#include "msdc_def.h"
#include "sd_def.h"
#include "sdio_def.h"
#include "drv_comm.h"
#include "intrCtrl.h"
#include "sdio_sw.h"
#if defined(__MSDC_SD_MMC__)&&defined(__MSDC_SD_SDIO__)
__align(4) kal_uint8 sdio_cccr_reg[SDIO_CCCR_SIZE];
__align(4) kal_uint8 sdio_fbr_reg[SDIO_FBR_SIZE];
__align(4) kal_uint8 sdio_tuple[SDIO_MAX_FUCN_ID][SDIO_TUPLE_SIZE];
sdio_dcb_struct gSDIO;
kal_mutexid sdio_mutex;
/*************************************************************************
* FUNCTION
* SDIO_Initialize
*
* DESCRIPTION
* SDIO Intialization function
*
* PARAMETERS
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*
*************************************************************************/
extern kal_uint8 MSDC_GetIOCtrlParam(void);
SDC_CMD_STATUS SDIO_Initialize(void)
{
kal_uint16 rca, iocon;
SDC_CMD_STATUS status;
kal_uint32 flags;
kal_uint32 retry_count = 0;
kal_uint32 count=0;
TurnOnMSDC();
#ifdef MSDC_INT
kal_retrieve_eg_events(MSDC_Events,
(EVENT_SDCMDIRQ|EVENT_SDDATIRQ|EVENT_SDMCIRQ|EVENT_SDR1BIRQ|EVENT_DMAIRQ|EVENT_PINIRQ),
KAL_OR_CONSUME,&flags,KAL_NO_SUSPEND);
#else
/*check if the card is present*/
if(*(volatile kal_uint16*)MSDC_PS & MSDC_PS_PIN0)
{ /*card not present (1)*/
gMSDC_Handle.mIsPresent = KAL_FALSE;
}
else
{ /*card present (0)*/
gMSDC_Handle.mIsPresent = KAL_TRUE;
}
#endif
/*create mutex*/
sdio_mutex = kal_create_mutex("MutexSDIO");
/* reset msdc*/
MSDC_SET_BIT32(MSDC_CFG, MSDC_CFG_RST);
/*Driving current*/
//MSDC_WriteReg32(MSDC_IOCON,0xC3);
//MSDC_WriteReg32(MSDC_IOCON,0xdb);
/* set the output driving capability from customization interface*/
iocon = *(volatile kal_uint16*)MSDC_IOCON;
iocon &= ~(0xff);
iocon |= MSDC_GetIOCtrlParam();
MSDC_WriteReg16(MSDC_IOCON,(kal_uint16)iocon);
/*set pull up in CMD/DAT line configuration*/
BitFieldWrite32((kal_uint32*)MSDC_CFG,(kal_uint32)2,MSDC_CFG_PRCFG1);
BitFieldWrite32((kal_uint32*)MSDC_CFG,(kal_uint32)2,MSDC_CFG_PRCFG2);
/*set write timeout=(40+1)*65536*(1/serial clock)*/
BitFieldWrite32((kal_uint32*)SDC_CFG,(kal_uint32)255,SDC_CFG_DTOC);
/*set write timeout=(40+1)*65536*(1/serial clock)*/
BitFieldWrite32((kal_uint32*)SDC_CFG,(kal_uint32)15,SDC_CFG_WDOD);
/* disable 4-bit*/
MSDC_CLR_BIT32(SDC_CFG,SDC_CFG_MDLEN);
/* enable serila clock 104/8=13MHz*/
//BitFieldWrite32((kal_uint32*)MSDC_CFG,(kal_uint32)FREQ_1BY8,MSDC_CFG_SCLKF);
/* enable serila clock 104/255*4=100KHz*/
//DRV_Reg32(MSDC_CFG)|= 0x8;
MSDC_CLR_BIT32(SDC_CFG,SDC_CFG_SIEN);
BitFieldWrite32((kal_uint32*)MSDC_CFG,(kal_uint32)32,MSDC_CFG_SCLKF);
MSDC_SET_BIT32(SDC_CFG,SDC_CFG_SIEN);
/* config the sdio controller*/
/* enable SDIO mode*/
DRV_Reg32(SDC_CFG)|= SDC_CFG_SDIO;
/* enable SDIO interrupt*/
DRV_WriteReg32(SDIO_CFG, 1);
{
kal_uint32 i;
for(i=0;i<1000;i++);
}
/*SDIO initialization CMD*/
status = SDIO_Cmd5(0);
#ifdef _SDIO_DEBUG_
dbg_print("write CMD5(0) %d\r\n", status);
dbg_print("card OCR %d\r\n", gSDIO.ocr);
#endif
do
{
retry_count++;
if(gSDIO.ocr & 0x8000)
{
if((status = SDIO_Cmd5(0x8000))!=NO_ERROR)
{
#ifdef _SDIO_DEBUG_
dbg_print("card deny OCR \r\n");
#endif
}
else
{
#ifdef _SDIO_DEBUG_
dbg_print("card accept OCR \r\n");
#endif
}
gSDIO.ocr_valid = KAL_TRUE;
}
else
{
#ifdef _SDIO_DEBUG_
dbg_print("card not match OCR \r\n");
dbg_print("uses card's OCR \r\n");
#endif
if((status = SDIO_Cmd5(gSDIO.ocr))!=NO_ERROR)
{
#ifdef _SDIO_DEBUG_
dbg_print("card deny OCR \r\n");
#endif
}
else
{
#ifdef _SDIO_DEBUG_
dbg_print("card accept OCR \r\n");
#endif
}
gSDIO.ocr_valid = KAL_TRUE;
}
if(retry_count>=100)
goto err;
}while(gSDIO.io_ready!=KAL_TRUE);
MSDC_CLR_BIT32(SDC_CFG,SDC_CFG_SIEN);
#ifdef MCU_104M
BitFieldWrite32((kal_uint32*)MSDC_CFG,(kal_uint32)FREQ_1BY8,MSDC_CFG_SCLKF);
#else
BitFieldWrite32((kal_uint32*)MSDC_CFG,(kal_uint32)FREQ_1BY4,MSDC_CFG_SCLKF);
#endif /*MCU_104M*/
MSDC_SET_BIT32(SDC_CFG,SDC_CFG_SIEN);
status = SD_ValidateRCA(&rca);
#ifdef _SDIO_DEBUG_
dbg_print("CMD7 select card \r\n");
dbg_print("CMD3 request RCA \r\n");
#endif
status = SD_SelectCard(rca);
/* get parameters*/
/*read CCCR, FBR, CIS tuple*/
status=SDIO_read_CCCR();
status=SDIO_read_capacity();
status=SDIO_read_power_control();
#if 1/*support 4-bits*/
/*enable multiple block interrupt */
if(!(SDIO_support_LSC()))
{
if(SDIO_support_S4MI())
status=SDIO_enable_E4MI(KAL_TRUE);
status=SDIO_configure_bus(BIT_4W);
/* enable serila clock 104/8=13MHz*/
//BitFieldWrite32((kal_uint32*)MSDC_CFG,(kal_uint32)FREQ_1BY8,MSDC_CFG_SCLKF);
}
else/*low speed card*/
{
if(SDIO_support_4BLS())
status=SDIO_configure_bus(BIT_4W);
}
#else
/* under construction !*/
#endif
status=SDIO_read_CIS(SDIO_FUCN_0);
/*enable I/O function*/
for(count=SDIO_FUCN_1;count<SDIO_MAX_FUCN_ID;count++)
{
kal_uint32 retry=0;
kal_bool ready;
for(retry=0;retry<100;retry++)
{
status=SDIO_enable_IO(count, KAL_TRUE);
SDIO_check_IO_ready(count, &ready);
if(ready==KAL_TRUE)
break;
}
status=SDIO_read_FBR(count);
for(retry=0;retry<100;retry++)
{
status=SDIO_read_CIS(count);
if(status==NO_ERROR)
break;
}
}
if(SDIO_support_MPS())
status=SDIO_enable_MPS(KAL_TRUE);
status=SDIO_read_CCCR();
/* for Sandisk SDIO WIFI card*/
err:
if(status != NO_ERROR)
{
//dbg_print("10\r\n");
kal_mem_set(&gSD,0,sizeof(gSD));
gMSDC_Handle.mIsInitialized = KAL_FALSE;
ASSERT(0);
}
else
gMSDC_Handle.mIsInitialized = KAL_TRUE;
return status;
}
/*SDIO commnad set*/
/*************************************************************************
* FUNCTION
* SD_StopTrans
*
* DESCRIPTION
* Stop Muli-Block operation
*
* PARAMETERS
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
* Use polling to check write command completely
*************************************************************************/
SDC_CMD_STATUS SD_StopTrans_poll(void)
{
SDC_CMD_STATUS status;
if((status = SD_Send_Cmd_poll(SDC_CMD_CMD12,SDC_NO_ARG))!=NO_ERROR)
return status;
/*Read R1b*/
if((status = SD_CheckStatus())!=NO_ERROR)
return status;
#ifdef SD_STOP_SLOW
while(*(volatile kal_uint16*)(SDC_STA) & SDC_STA_R1BSY);
do{
SD_GetStatus(gSD.mRCA,(kal_uint32*)&status);
}while((status & R1_CUR_STATE) >> 9 != TRAN_STA);
#endif
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SDIO_WaitCardNotBusy
*
* DESCRIPTION
* Wait until card is not busy (R1b)
*
* PARAMETERS
*
* RETURNS
* void
*
* GLOBALS AFFECTED
*
* NOTE
* Interrupt driven and polling are both implemented
*
*************************************************************************/
/*R1b*/
void SDIO_WaitCardNotBusy(void)
{
while( *(volatile kal_uint16*)(SDC_STA) & SDC_STA_R1BSY);
}
/*************************************************************************
* FUNCTION
* SD_WaitCmdRdyOrTo_poll
*
* DESCRIPTION
* write command completely
*
* PARAMETERS
*
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
* gSD
*
*************************************************************************/
SDC_CMD_STATUS SD_WaitCmdRdyOrTo_poll(void)
{
kal_uint16 sdc_cmdsta = 0;
kal_uint32 counter = 0;
while(DRV_Reg(SDC_STA)&0x2){};
#if 1
do{
sdc_cmdsta = *(volatile kal_uint16*)SDC_CMDSTA;
if(sdc_cmdsta & SDC_CMDSTA_CMDTO)
return ERR_CMD_TIMEOUT;
else if(sdc_cmdsta & SDC_CMDSTA_RSPCRCERR)
return ERR_CMD_RSPCRCERR;
else if(sdc_cmdsta & SDC_CMDSTA_CMDRDY)
break;
}while(counter++ < 10000);
#endif
if (counter >= 10000)
{
return ERR_NORESP;
}
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SD_WaitCmdRdyOrTo_poll
*
* DESCRIPTION
* write command completely
*
* PARAMETERS
*
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
* gSD
*
*************************************************************************/
SDC_CMD_STATUS SD_Send_Cmd_poll(kal_uint32 cmd, kal_uint32 arg)
{
SDC_CMD_STATUS status;
/*check the controller is ready (stop transaction will fail)*/
//if( != SDC_CMD_CMD12)
if(!(SDC_CMD_STOP&cmd))
while(SD_IS_SDC_BUSY && gMSDC_Handle.mIsPresent);
else
while(SD_IS_CMD_BUSY && gMSDC_Handle.mIsPresent);
/* fill out the argument*/
MSDC_WriteReg32(SDC_ARG,arg);
/* launch the command*/
MSDC_WriteReg32(SDC_CMD,cmd);
if((status = SD_WaitCmdRdyOrTo_poll())!=NO_ERROR)
return status;
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SDIO_Cmd53
*
* DESCRIPTION
* IO_RW_DIRECT command
*
* PARAMETERS
* command 53 structrue
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
*************************************************************************/
kal_uint8 debug_flag = 0;
SDC_CMD_STATUS SDIO_Cmd53(cmd53_config_struct *p)
{
SDC_CMD_STATUS status;
kal_uint32 arg;
kal_uint32 cmd;
kal_uint32 *ptr = (kal_uint32 *) p->buffer;
ASSERT(p->adrs < 0x20000 && p->count < 0x200);
IRQMask(IRQ_MSDC_CODE);
arg = (p->rw << 31)|(p->func << 28)|(p->block << 27)|(p->op << 26)|(p->adrs << 9)|(p->count);
cmd = SDC_CMD_CMD53 | (p->rw << 13);
if(p->block)
{
cmd |= (2 << 11); // multi-block
BitFieldWrite32((kal_uint32*)SDC_CFG,gSDIO.block_size[1],SDC_CFG_BLKLEN);
}
else
{
cmd |= (1 << 11); // single-block
BitFieldWrite32((kal_uint32*)SDC_CFG,p->count,SDC_CFG_BLKLEN);
}
// send cmd53
//if(p->rw == SDIO_WRITE)
if(0)/*R1b*/
{
cmd &= ~0x380;
cmd |= 0x380;
}
else/*R1*/
{
cmd &= ~0x380;
cmd |= 0x80;
}
if((status = SD_Send_Cmd_poll(cmd, arg))!=NO_ERROR)
{
goto ERROR_EXIT;
}
MSDC_ReadReg32(SDC_RESP0,&status);
status = (status & 0xff00)>>8;
gSDIO.resp = status;
/* start data transfer*/
if(p->rw == SDIO_READ)
{
#ifdef MSDC_DMA
kal_uint32 total_size=0;
EnableMSDC_DMA();
if(p->block)
total_size = (p->count*gSDIO.block_size[p->func]);
else
total_size =p->count;
total_size=total_size>>2;
status = MSDC_DMATransfer((kal_uint32)ptr,total_size,KAL_FALSE);
/*check DMA*/
if(status != NO_ERROR)
goto ERROR_EXIT;
/*check Data ready*/
if((status=SDIO_WaitDatRdyOrTo())!=NO_ERROR)
goto ERROR_EXIT;
DisableMSDC_DMA();
MSDC_CLR_FIFO();
#else/*!MSDC_DMA*/
kal_uint32 i;
if(p->block)
{
kal_uint32 total;
total = (p->count*gSDIO.block_size[p->func]+3)>>2;
for(i=0;i< total;)
{
if(!MSDC_IS_FIFO_EMPTY)
{
*(ptr+i) = *(volatile kal_uint32*)MSDC_DAT;
i++;
if(i%((gSDIO.block_size[p->func]+3) >> 2)==0)
{
debug_flag = 1;
if((status=SDIO_WaitDatRdyOrTo())!=NO_ERROR)
goto ERROR_EXIT;
}
}
}
}
else
{
for(i=0;i< (p->count+3)>>2;)
{
if(!MSDC_IS_FIFO_EMPTY)
{
*(ptr+i) = *(volatile kal_uint32*)MSDC_DAT;
i++;
if((i%((p->count+3)>> 2)==0)&&(i!=0))
{
debug_flag = 1;
if((status=SDIO_WaitDatRdyOrTo())!=NO_ERROR)
goto ERROR_EXIT;
}
}
}
}
#endif/*MSDC_DMA*/
}
else
{ // SDIO_WRITE
#ifdef MSDC_DMA
kal_uint32 total_size=0;
EnableMSDC_DMA();
if(p->block)
total_size = (p->count*gSDIO.block_size[p->func]);
else
total_size =p->count;
total_size=total_size>>2;
status = MSDC_DMATransfer((kal_uint32)ptr,total_size,KAL_TRUE);
/*check DMA*/
if(status != NO_ERROR)
goto ERROR_EXIT;
/*check Data ready*/
if((status=SDIO_WaitDatRdyOrTo())!=NO_ERROR)
goto ERROR_EXIT;
DisableMSDC_DMA();
MSDC_CLR_FIFO();
#else/* MSDC_DMA*/
kal_uint32 i;
if(p->block)
{
kal_uint32 total;
total = (p->count*gSDIO.block_size[p->func]+3)>>2;
for(i=0;i< total;)
{
if(!MSDC_IS_FIFO_FULL)
{
*(volatile kal_uint32*)MSDC_DAT = *(ptr+i);
i++;
if(i%((gSDIO.block_size[p->func]+3) >> 2)==0)
{
debug_flag = 1;
if((status=SDIO_WaitDatRdyOrTo())!=NO_ERROR)
goto ERROR_EXIT;
}
}
}
}
else
{
for(i=0;i< (p->count+3)>>2;)
{
if(!MSDC_IS_FIFO_FULL)
{
*(volatile kal_uint32*)MSDC_DAT = *(ptr+i);
i++;
if(i%((p->count+3) >> 2)==0)
{
debug_flag = 1;
if((status=SDIO_WaitDatRdyOrTo())!=NO_ERROR)
goto ERROR_EXIT;
}
}
}
}
#endif/*MSDC_DMA*/
}
//SD_StopTrans_poll();
if(p->block)
SD_StopTrans_poll();
SDIO_stop();
IRQUnmask(IRQ_MSDC_CODE);
return NO_ERROR;
ERROR_EXIT:
{
kal_uint32 tmp;
#ifdef MSDC_DMA
DisableMSDC_DMA();
#endif
if(p->block)
SD_StopTrans_poll();
SDIO_stop();
MSDC_ReadReg32(SDC_CMDSTA,&tmp);
MSDC_ReadReg32(SDC_DATSTA,&tmp);
MSDC_CLR_FIFO();
IRQUnmask(IRQ_MSDC_CODE);
return status;
}
}
/*SDIO_Cmd53_poll*/
SDC_CMD_STATUS SDIO_Cmd53_isr(cmd53_config_struct *p)
{
SDC_CMD_STATUS status;
kal_uint32 arg;
kal_uint32 cmd,i;
kal_uint32 *ptr = (kal_uint32 *) p->buffer;
ASSERT(p->adrs < 0x20000 && p->count < 0x200);
arg = (p->rw << 31)|(p->func << 28)|(p->block << 27)|(p->op << 26)|(p->adrs << 9)|(p->count);
cmd = SDC_CMD_CMD53 | (p->rw << 13);
if(p->block)
{
cmd |= (2 << 11); // multi-block
BitFieldWrite32((kal_uint32*)SDC_CFG,gSDIO.block_size[1],SDC_CFG_BLKLEN);
}
else
{
cmd |= (1 << 11); // single-block
BitFieldWrite32((kal_uint32*)SDC_CFG,p->count,SDC_CFG_BLKLEN);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -