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

📄 mmc_samsung.c.bak

📁 The sd/mmc driver for s3c2410, it is much better than the one from samsung
💻 BAK
📖 第 1 页 / 共 3 页
字号:
		else {			request->nob-- ; 		}		request->buffer = buf;		MMC_DEBUG(2," Total Read Size for single read cmd 0x%08X",g_s3c_mmc_data.size2read);		g_s3c_mmc_data.size2read = 0;		return 0 ;	}	if ( (rSDIFSTA & MMC_STATUS_FIFO_COUNT_MASK) != S3C_SD_FIFO_SIZE) {		MMC_DEBUG(2, " Unexpected FIFO Data count v.s Received Data ");	}	for (i=0; i < S3C_SD_FIFO_SIZE; i += 4) {		data = rSDIDAT;		*buf++ = data >> 0 & 0xff;		*buf++ = data >> 8 & 0xff;		*buf++ = data >> 16 & 0xff;		*buf++ = data >> 24 & 0xff;	}	g_s3c_mmc_data.size2read += S3C_SD_FIFO_SIZE;		if (0 == (g_s3c_mmc_data.size2read % request->block_len)) 		request->nob--;		if ( !request->nob ) {		while(!(rSDIDSTA&MMC_STATUS_DATA_TRANSFER_DONE)){			;		}		rSDIDSTA = MMC_STATUS_DATA_TRANSFER_DONE;		request->buffer = buf;		g_s3c_mmc_data.size2read = 0;		MMC_DEBUG(2,": Ending nob=%d block_len=%d buf=%p", request->nob, request->block_len, buf);			MMC_DEBUG(2, " accumulated g_s3c_mmc_data.size2read 0x%08X rSDIDSTA 0x%08X rSDIFSTA 0x%08X",			g_s3c_mmc_data.size2read,rSDIDSTA,rSDIFSTA);#ifdef CONFIG_MMC_DEBUG		START_MMC_DEBUG(3) {		u8 *b = request->buffer - 512 ;		for ( i = 0 ; i < request->block_len ; i++ ) {			printk(" %02x", *b++);			if ( ((i + 1) % 16) == 0 )				printk("\n");			}		} END_MMC_DEBUG;#endif		return 0;	}	MMC_DEBUG(2, " accumulated g_s3c_mmc_data.size2read 0x%08X rSDIDSTA 0x%08X rSDIFSTA 0x%08X",			g_s3c_mmc_data.size2read,rSDIDSTA,rSDIFSTA);	/* Updated the request buffer to reflect the current state */	request->buffer = buf;	//	g_s3c_asic_statistics.mmc_read++;	return 1;}/******* * Prototype  * static void mmc_s3c_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 mmc_s3c_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 ");//		mmc_s3c_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      ");		mmc_s3c_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) {			         mmc_s3c_receive_data( sd->request,-1 );		}		else {			if (status[SDI_FIFO]&MMC_STATUS_FIFO_RX_LAST_DATA) {				mmc_s3c_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)) {					mmc_s3c_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); 		//	mmc_s3c_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;				mmc_s3c_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); 			mmc_s3c_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 mmc_s3c_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 mmc_s3c_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, " 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); 	/* this can happen if there is an old interrupt hanging around when the irq is registered */	if (sd->request == NULL) {		printk ("ignoring mmc irq with null request\n");		enable_irq( irq );		return;	}/*#ifdef DEBUG	START_MMC_DEBUG(2) { 		printk(__FUNCTION__ " cmd 0x%08X data 0x%08X fifo 0x%08X",rSDICSTA,rSDIDSTA,rSDIFSTA); 		decode_status(status); 		printk(")\n"); 	} END_MMC_DEBUG;#endif*/		mmc_s3c_split_status( sd, status, 0 );	/* Clear the interrupt.  Must write a one to the src pending register	  then the interrupt pending register. */	h5400_asic_write_register (H5400_ASIC_IC_SRCPND, _H5400_ASIC_IC_INT_SD);	h5400_asic_write_register (H5400_ASIC_IC_INTPND, _H5400_ASIC_IC_INT_SD);	/* Enable the irq */	enable_irq( irq );}/******* * Prototype  *   static void mmc_s3c_irq_timeout( unsigned long nr ) * Purpose: *       1. mmc_s3c_reset_timeout  (start) *       2. mmc_s3c_exec_command   (start)         3. mmc_s3c_split_status   (stop)	 DATA Transfer (read/write), Reset timeout implementation * Entry * Exit * Exceptions: *****************************************************/static void mmc_s3c_irq_timeout( unsigned long nr ){	struct s3c_mmc_data *sd = (struct s3c_mmc_data *) nr;	u16 status[SDI_STATUS_LENGTH]= {0};	status[SDI_CMD] = rSDICSTA;	status[SDI_DATA] = rSDIDSTA;	status[SDI_FIFO] = rSDIFSTA;	sd_status_clear(2);/*#ifdef CONFIG_MMC_DEBUG	START_MMC_DEBUG(2) { 		printk(__FUNCTION__ " sd=%p status=0x%04x (", sd, status);		decode_status(status); 		printk(")\n"); 	} END_MMC_DEBUG;#endif*/	//	g_s3c_asic_statistics.mmc_timeout++;	mmc_s3c_split_status( sd, status, 1 );}static void mmc_s3c_slot_up( void ){	MMC_DEBUG(1,"    before slot_up");	/* Set up timers */	g_s3c_mmc_data.sd_detect_timer.function = mmc_s3c_fix_sd_detect;	g_s3c_mmc_data.sd_detect_timer.data     = (unsigned long) &g_s3c_mmc_data;	init_timer(&g_s3c_mmc_data.sd_detect_timer);	if (lowlevel->slot_init)		lowlevel->slot_init(lowlevel);	    /* Important notice for MMC test condition */	    /* Cmd & Data lines must be enabled pull up resister */        rSDIPRE=(2*PCLK)/(MMC_CLOCK_SLOW)-1;	// 400KHz	/* For SDIO use RECV_SDIO_INT_EN */	rSDICON=FIFO_RESET |CLOCK_OUT_EN; /* BYTE Type A */	rSDIDTIMER=0xffff;		// Set timeout count}static void mmc_s3c_slot_down(void) {	del_timer_sync(&g_s3c_mmc_data.sd_detect_timer);	if (lowlevel->slot_cleanup)		lowlevel->slot_cleanup(lowlevel);}/******* * Prototype  *  static int  mmc_s3c_slot_is_empty (int slot) * Purpose:  * Entry * Exit *        1  : slot is empty *        0  : occupied * Exceptions: *****************************************************/static int  mmc_s3c_slot_is_empty (int slot){	int retval = 1;	if (lowlevel->slot_is_empty)		retval = lowlevel->slot_is_empty(lowlevel);	return retval;}static int mmc_s3c_slot_init( void ){	int retval;	MMC_DEBUG(1,"");	/* Set up timers */	/*	g_s3c_mmc_data.sd_detect_timer.function = mmc_s3c_fix_sd_detect;	g_s3c_mmc_data.sd_detect_timer.data     = (unsigned long) &g_s3c_mmc_data;	init_timer(&g_s3c_mmc_data.sd_detect_timer);	g_s3c_mmc_data.sd_detect_timer.expires = jiffies + (250 * HZ) / 1000;	add_timer(&g_s3c_mmc_data.sd_detect_timer);	*/	/*	g_s3c_mmc_data.reset_timer.function = mmc_s3c_reset_timeout;	g_s3c_mmc_data.reset_timer.data     = (unsigned long) &g_s3c_mmc_data;	init_timer(&g_s3c_mmc_data.reset_timer);*//*	g_s3c_mmc_data.irq_timer.function = mmc_s3c_irq_timeout;	g_s3c_mmc_data.irq_timer.data     = (unsigned long) &g_s3c_mmc_data;	init_timer(&g_s3c_mmc_data.irq_timer);*/	/* Basic service interrupt */	mmc_s3c_slot_up();	retval = request_irq( lowlevel->sdi_irq, mmc_s3c_general_mmc_interrupt,			      SA_INTERRUPT, "mmc_s3c_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 = request_irq( lowlevel->detect_irq, mmc_s3c_sd_detect_isr, 		      SA_INTERRUPT, "mmc_s3c_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 mmc_s3c_slot_cleanup( void ){	MMC_DEBUG(1,"");	mmc_s3c_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:      "S3C2410 MMC",	ocr:       0x00ff8000,           /*Valid voltage ranges */	flags:     MMC_SDFLAG_MMC_MODE,  /* Slot driver flags */	init:      mmc_s3c_slot_init,	cleanup:   mmc_s3c_slot_cleanup,	is_empty:  mmc_s3c_slot_is_empty,	send_cmd:  mmc_s3c_send_command,	set_clock: mmc_s3c_set_clock,};int s3c_mmc_register_slot(struct s3c_mmc_lowlevel *s3c_mmc_lowlevel){        int retval;       	MMC_DEBUG(0," s3c_mmc_init function start"); 		lowlevel = s3c_mmc_lowlevel;	retval = mmc_register_slot_driver(&dops,1);	if ( retval < 0 )		printk(KERN_INFO "%s: unable to register slot", __FUNCTION__);	return retval;}EXPORT_SYMBOL(s3c_mmc_register_slot);int s3c_mmc_unregister_slot(void){	int retval = 0;	MMC_DEBUG(0,"");	mmc_unregister_slot_driver(&dops);	lowlevel = NULL;	return retval;}EXPORT_SYMBOL(s3c_mmc_unregister_slot);MODULE_AUTHOR("Sangwook Lee<hitchcar@sec.samsung.com>, Jamey Hicks <jamey.hicks@hp.com>");MODULE_LICENSE("GPL");MODULE_DESCRIPTION("Samsung Asic SD/MMC driver ");

⌨️ 快捷键说明

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