⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdio_drv.c

📁 SDIO实现底层驱动文件.非常有用.经典!
💻 C
📖 第 1 页 / 共 4 页
字号:
#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 + -