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

📄 s3c_mmc.c

📁 mmc 方式通讯的在CPU PXA270下的WINCE 5驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
	mod_timer( &mmc_data->sd_detect_timer, jiffies + (250 * HZ) / 1000 );}/******* * Prototype  * static void s3c_mmc_split_status( struct s3c_mmc_data *sd, u16 status[], int timeout ) * Purpose: *       1. status[SDI_CMD]= command status *          status[SDI_DATA]= data    status *          status[SDI_FIFO]= FIFO    status *       2. collect the same sorts of interrupts.  * Entry * Exit *       timeout not used  * Exceptions: *       where is timeout routine ? *       rSDIIMSK = S3C_ALL_MMC_INT_MASK is right ? *         *   1.  In MMC mode, MAX clock rate is 10 Mhz *   2.  In MMC write mode(response only, ex cmd1), the CRC error is *       occured in spite of correct writing.  *   3.  In case of long response, the CRC error should be detected after receiving *       exact response data from SD device. User should check the CRC of received response *       by software. *   4.  Supposed that RESPONSE State and DATA RECEIVE don't appeare simultaneously.  ********************************************************************************************/static void s3c_mmc_split_status( struct s3c_mmc_data *sd, u16 status[], int timeout ){	int retval = MMC_NO_ERROR;	int rsp_done = 0,msk_reg =0,data_busy=0;	if ((status[SDI_CMD] & MMC_STATUS_RESPONSE_TIMEOUT )  || 	    (status[SDI_DATA]& MMC_STATUS_DATA_BUSY_TIMEOUT)	    ) {		MMC_DEBUG(0,"  MMC_ERROR_TIMEOUT ");		/*s3c_mmc_get_response(sd->request);*/		retval = MMC_ERROR_TIMEOUT;		goto terminate_int;	}		if ((status[SDI_CMD] & MMC_STATUS_CRC_RESPONSE_ERROR )  || 	    (status[SDI_DATA]& (MMC_STATUS_CRC_WRITE_ERROR|MMC_STATUS_CRC_READ_ERROR))	    ) {		if (/* Slot device is MMC && see Exception 2.*/			   g_s3c_mmc_data.type == RT_RESPONSE_ONLY) {			MMC_DEBUG(0,"  DUMMY MMC_ERROR_CRC     ");		}		else {			MMC_DEBUG(0,"  MMC_ERROR_CRC     ");			retval = MMC_ERROR_CRC;			goto terminate_int;		}	}	if ( status[SDI_CMD]& MMC_STATUS_RESPONSE_RECV_DONE 	     && sd->request->result == MMC_NO_RESPONSE /* not yet response receveied. */	    ) { 		rsp_done = 1;		MMC_DEBUG(0,"  get_response      ");		s3c_mmc_get_response( sd->request );	}	/** TODO :Fix me...	 * Read operation data error	 * Where do I handle "data error" not CRC Error--> I don't know	 */		if ((g_s3c_mmc_data.type==RT_READ) ){ 		if ( status[SDI_FIFO]&MMC_STATUS_FIFO_RX_FULL) {			         s3c_mmc_receive_data( sd->request,-1 );		}		else {			if (status[SDI_FIFO]&MMC_STATUS_FIFO_RX_LAST_DATA) {				s3c_mmc_receive_data( sd->request,					status[SDI_FIFO]&MMC_STATUS_FIFO_COUNT_MASK );			 }			 else {				if (rsp_done){				}				else {					MMC_DEBUG(0,": ERROR READ COMMAND 0x%08X,0x%08X,0x%08X"						,status[SDI_CMD],status[SDI_DATA],status[SDI_FIFO]);				}			}		}	}	if (g_s3c_mmc_data.type==RT_WRITE && status[SDI_DATA]&MMC_STATUS_DATA_BUSY_TIMEOUT) {		MMC_DEBUG(2,"  Not BUSY Finish");		data_busy =1;	}	if ((g_s3c_mmc_data.type==RT_WRITE)&& !rsp_done && !data_busy) {		MMC_DEBUG(2, "nob=%d, counter=0x%08X", sd->request->nob, rSDIDCNT);		if (!(status[SDI_DATA]&MMC_STATUS_DATA_TRANSFER_DONE)) {			if (sd->request->nob>0) {				if ((status[SDI_FIFO]&MMC_STATUS_FIFO_TX_HALF_FULL) || 				    (status[SDI_FIFO]&MMC_STATUS_FIFO_EMPTY)) {					s3c_mmc_transmit_data(sd->request); 				}			}		}	}	switch (g_s3c_mmc_data.type) {	case RT_NO_RESPONSE:		MMC_DEBUG(2,"  RT_NO_RESPONSE ");		msk_reg  = S3C_ALL_MMC_INT_MASK;		break;	case RT_RESPONSE_ONLY:		MMC_DEBUG(2,"  RT_RESPONSE_ONLY ");		if ( sd->request->result < 0 ) {			printk(KERN_INFO "%s: illegal interrupt - command hasn't finished\n", __FUNCTION__);			retval = MMC_ERROR_TIMEOUT;		}		msk_reg  = S3C_ALL_MMC_INT_MASK;		break;	case RT_READ:		if(sd->request->nob <=0 )  {			msk_reg  = S3C_ALL_MMC_INT_MASK;			break;		}		/* It is impossible to get both response and data  */		if ( sd->request->nob ) {			msk_reg = S3C_RX_FIFO_LAST_DATA_INT_ON | S3C_RX_FIFO_FULL_INT_ON;			MMC_DEBUG(2,": read SDIIMSK  mask=0x%08x",rSDIIMSK);				/*mod_timer( &sd->irq_timer, jiffies + MMC_IRQ_TIMEOUT); */				/*s3c_mmc_start_clock();*/ /* redundancy ? */			rSDIIMSK = msk_reg; 				return;		}		if(rsp_done) {			MMC_DEBUG(2,": READ RESPONSE DONE ");			MMC_DEBUG(2,": REGS sdicon 0x%08X sdiccon %08X sdidcon 0x%08X"					,rSDICON,rSDICCON,rSDIDCON);			MMC_DEBUG(2,": REGS cmd 0x%08X data 0x%08X fifo 0x%08X",rSDICSTA,rSDIDSTA,rSDIFSTA);			MMC_DEBUG(2,": REGS cmd 0x%08X data 0x%08X fifo 0x%08X",rSDICSTA,rSDIDSTA,rSDIFSTA);			msk_reg = S3C_RX_FIFO_LAST_DATA_INT_ON | S3C_RX_FIFO_FULL_INT_ON;			rSDIIMSK = msk_reg;			return;		}		MMC_DEBUG(2," Unexpected Error ");		break;	case RT_WRITE:		if( sd->request->nob <= 0) {			if (!(status[SDI_DATA]& MMC_STATUS_DATA_TRANSFER_DONE)) {				msk_reg = S3C_DATA_CNT_ZERO_INT_ON|					  S3C_BUSY_COMPLETE_INT_ON;				s3c_mmc_start_clock(); /* redundancy ? */				rSDIIMSK = msk_reg;				return;			} else {				msk_reg = S3C_ALL_MMC_INT_MASK;				break;			}		}		if( (sd->request->nob || !(status[SDI_DATA]& MMC_STATUS_DATA_TRANSFER_DONE)) 		   && !data_busy ){			msk_reg = S3C_DATA_CNT_ZERO_INT_ON|S3C_BUSY_COMPLETE_INT_ON|				  S3C_TX_FIFO_EMPTY_INT_ON;			MMC_DEBUG(2,": write SDIIMSK  mask=0x%08x",rSDIIMSK);			/*mod_timer( &sd->irq_timer, jiffies + MMC_IRQ_TIMEOUT); */			s3c_mmc_start_clock(); /* redundancy ? */			rSDIIMSK  = msk_reg;			return;		}		if(data_busy)  {			msk_reg = S3C_BUSY_COMPLETE_INT_ON;		}		else  {			msk_reg  = S3C_ALL_MMC_INT_MASK;		}		break;	}	/*MMC_DEBUG(2,": terminating status=0x%04x", S3C_ASIC1_MMC_Status );*/terminate_int:	rSDIIMSK = msk_reg; 	/*del_timer_sync( &sd->irq_timer );*/	sd->request->result = retval;	MMC_DEBUG(2,"  Before mmc_cmd_complete  ");	mmc_cmd_complete( sd->request );	sd->request = NULL;}/******* * Prototype  *  static void s3c_mmc_general_mmc_interrupt(int irq, void *dev_id, struct pt_regs *regs) * * Purpose: *       1. Analysis Command,Data and Fifo Status of SD/MMC registers * Entry * Exit * Exceptions: *****************************************************/static void s3c_mmc_general_mmc_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct s3c_mmc_data *sd = (struct s3c_mmc_data *) dev_id;		/* Disable irq */	disable_irq( irq );	u16 status[SDI_STATUS_LENGTH]= {0};	status[SDI_CMD] = rSDICSTA;	status[SDI_DATA] = rSDIDSTA;	status[SDI_FIFO] = rSDIFSTA;	sd_status_clear(2);	MMC_DEBUG(2, " PRE %x rSDIIMSK 0x%08X cmd 0x%08X data 0x%08X fifo 0x%08X",rSDIPRE,rSDIIMSK,status[0],status[1],status[2]); 	MMC_DEBUG(2, " rSDICON  0x%08X CCON  0x%08X DCONdata 0x%08X ",rSDICON,rSDICCON,rSDIDCON); 	/* this can happen if there is an old interrupt hanging around when the irq is registered */	if (sd->request == NULL) {		MMC_DEBUG(2, " rSDIIMSK 0x%08X cmd 0x%08X data 0x%08X fifo 0x%08X",rSDIIMSK,status[0],status[1],status[2]); 		MMC_DEBUG(2, " rSDICON  0x%08X CCON  0x%08X DCONdata 0x%08X ",rSDICON,rSDICCON,rSDIDCON); 		rSDIFSTA = rSDIFSTA;		printk ("ignoring mmc irq with null request\n");		enable_irq( irq );		return;	}	s3c_mmc_split_status( sd, status, 0 );	/* Clear the interrupt.  Must write a one to the src pending register	  then the interrupt pending register. */	SRCPND |= (1 << IRQ_SDI);	INTPND |= (1 << IRQ_SDI);	/* Enable the irq */	enable_irq( irq );}static int s3c_mmc_slot_is_empty( int slot ){	int is_empty  =  lowlevel->slot_is_empty(lowlevel);	return is_empty?1:0;}/************************************************************************** * *                       Hardware initialization                                              * *************************************************************************/static void s3c_mmc_slot_up( void ) {	MMC_DEBUG(1,"    before slot_up");	/* Set up timers */	g_s3c_mmc_data.sd_detect_timer.function = s3c_mmc_detect_handler;	g_s3c_mmc_data.sd_detect_timer.data     = (unsigned long) &g_s3c_mmc_data;	init_timer(&g_s3c_mmc_data.sd_detect_timer);		/* Important notice for MMC test condition */	/* Cmd & Data lines must be enabled pull up resister */	rSDICON = SDMMC_RESET;	/* Set block size to 512 bytes */	rSDIBSIZE = 0x200;	rSDIDTIMER=0x7fffff;	/* Disable SDI interrupt */	rSDIIMSK = 0x0;	/* Type B, FIFO reset, SD clock enable */	rSDICON = CLOCK_TYPE_MMC | BYTE_ORDER_TYPE_L |CLOCK_OUT_EN ;	rSDIFSTA=rSDIFSTA|(1<<16);	/* clear all */	rSDIDSTA = MMC_STATUS_DATA_ALL;		s3c_mmc_set_clock(MMC_CLOCK_SLOW);	/* Enable SMDK SD clock */	CLKCON |= lowlevel->sdi_clock;	/* Wait for power-up */	mdelay(125);}static void s3c_mmc_slot_down( void ){	del_timer_sync(&g_s3c_mmc_data.sd_detect_timer);	if (lowlevel->slot_cleanup)		lowlevel->slot_cleanup(lowlevel);		/* Disable SMDK SD clock */	CLKCON &= ~(lowlevel->sdi_clock);}static int s3c_mmc_suspend(void){    	s3c_mmc_stop_clock();    	s3c_mmc_slot_down();	return 0;}static void s3c_mmc_resume(void){	s3c_mmc_slot_up();	/*s3c_mmc_set_clock(g_s3c_mmc_data.clock);*/       	/* Set up timers */	g_s3c_mmc_data.sd_detect_timer.function = s3c_mmc_detect_handler;	g_s3c_mmc_data.sd_detect_timer.data     = (unsigned long) &g_s3c_mmc_data;	init_timer(&g_s3c_mmc_data.sd_detect_timer);	enable_irq ( lowlevel->sdi_irq );        	enable_irq ( lowlevel->detect_irq ); /* Enable card detect IRQ */}#ifdef CONFIG_PMstatic int s3c_mmc_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data){	switch(req) {  		case PM_SUSPEND:			 mmc_eject(0);			 s3c_mmc_suspend();		break;		case PM_RESUME:			s3c_mmc_resume();			s3c_mmc_fix_sd_detect(0);		 break;  	}	return 0;}#endif/*=>CEE LDM*/static int s3c_mmc_dpm_suspend(struct device *dev, u32 state, u32 level){ 	printk("s3c dpm suspend state %d, level %d",state,level);	switch(level)	{	 case SUSPEND_POWER_DOWN: 	/* Turn off power to MMC */		 s3c_mmc_suspend();		 break;	}	return 0;}static int s3c_mmc_dpm_resume(struct device *dev, u32 level){	printk("s3c dpm resume   level %d",level);	switch(level)	{		case RESUME_POWER_ON:		/* Turn on power to MMC */		s3c_mmc_resume();		mmc_eject(0);		s3c_mmc_fix_sd_detect(0);		break;	}	return 0;}/*CEE LDM=>*/static int s3c_mmc_slot_init( void ){	int retval;	MMC_DEBUG(1,"s3c_mmc_slot_init");	/* Basic service interrupt */	s3c_mmc_slot_up();	retval = request_irq( lowlevel->sdi_irq, s3c_mmc_general_mmc_interrupt,			      SA_INTERRUPT, "s3c_mmc_int", &g_s3c_mmc_data );	if ( retval ) {		printk(KERN_CRIT "%s: unable to grab MMC IRQ %d\n", __FUNCTION__, lowlevel->sdi_irq);		return retval;	}    	retval = write_gpio_bit(lowlevel->sdi_gpio_cd,0);	set_external_irq(lowlevel->detect_irq, lowlevel->detect_irq_edge, lowlevel->detect_irq_pullup);		retval = request_irq( lowlevel->detect_irq, s3c_mmc_detect_isr, 		      SA_INTERRUPT, "s3c_mmc_sd_detect", &g_s3c_mmc_data );	if ( retval ) {		printk(KERN_CRIT "%s: unable to grab SD_DETECT IRQ %d\n", __FUNCTION__, lowlevel->detect_irq);		free_irq(lowlevel->sdi_irq, &g_s3c_mmc_data);	}	return retval;}static void s3c_mmc_slot_cleanup( void ){	mmc_eject(0);	s3c_mmc_slot_down();	free_irq(lowlevel->sdi_irq, &g_s3c_mmc_data);	free_irq(lowlevel->detect_irq, &g_s3c_mmc_data);}/***********************************************************/static struct mmc_slot_driver dops = {	.owner		= THIS_MODULE,	.name		= "S3C24X0 MMC",	.ocr		= 0x00ff8000,	.flags		= MMC_SDFLAG_MMC_MODE,	.init		= s3c_mmc_slot_init,	.cleanup	= s3c_mmc_slot_cleanup,	.is_empty	= s3c_mmc_slot_is_empty,	.send_cmd	= s3c_mmc_send_command,	.set_clock	= s3c_mmc_set_clock,};static int  __init s3c_mmc_init(void){	int retval;	/*=>CEE LDM*/	s3c_mmc_ldm_register();	/*CEE LDM=>*/#ifdef CONFIG_PM	pm_register(PM_UNKNOWN_DEV, PM_SYS_UNKNOWN, s3c_mmc_pm_callback);#endif#if defined(CONFIG_ARCH_S3C24A0)	lowlevel = &s3c24a0_mmc_lowlevel;#elif defined(CONFIG_ARCH_S3C2440)	lowlevel = &s3c2440_mmc_lowlevel;#endif	retval = mmc_register_slot_driver(&dops, 1);	if ( retval < 0 )		printk(KERN_INFO "MMC: unable to register slot\n");	return retval;}static  void __exit s3c_mmc_cleanup(void){#ifdef CONFIG_PM	pm_unregister_all(s3c_mmc_pm_callback);#endif	/*=>CEE LDM*/	s3c_mmc_ldm_unregister();	/*CEE LDM=>*/	mmc_unregister_slot_driver(&dops);}module_init(s3c_mmc_init);module_exit(s3c_mmc_cleanup);MODULE_AUTHOR("Naushad");MODULE_DESCRIPTION("Samsung S3C24X0 MMC Controller");MODULE_LICENSE("GPL");EXPORT_NO_SYMBOLS;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -