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

📄 mmc_samsung.c

📁 The sd/mmc driver for s3c2410, it is much better than the one from samsung
💻 C
📖 第 1 页 / 共 3 页
字号:
//	mod_timer( &sd->reset_timer, jiffies + (100 * HZ) / 1000 );//	g_s3c_asic_statistics.mmc_reset++;	mmc_CMD0();	return retval;}/******* * Prototype  *  	mmc_s3c_set_command( request->cmd, request->arg ) * * Purpose: *         1. set SDICARG *         2. set the "Command with data " of SDICCON *         3. clear registers *         4. set cmd index including Start bit & transmission bit  *            and response type. * Entry * Exit * Exceptions: *            Not sure that 2 must be set here. *******************************************************************/static void mmc_s3c_set_command( u32 cmd, u32 arg, enum mmc_rsp_t rtype ){        u32 cc_reg = 0;	//	MMC_DEBUG(2,": cmd=%d arg=0x%08x", cmd, arg);	MMC_DEBUG(2,"");	/* write one clear */	rSDICSTA = ( MMC_STATUS_CRC_RESPONSE_ERROR		    |MMC_STATUS_CMD_SENT_DONE		    |MMC_STATUS_RESPONSE_TIMEOUT		    |MMC_STATUS_RESPONSE_RECV_DONE                    ); 	rSDICARG = arg;	cc_reg  = cmd |START_TRANSMISSION_PRE|NORMAL_COMMAND;	if (g_s3c_mmc_data.type == RT_READ || g_s3c_mmc_data.type==RT_WRITE){	}	#define S3C_SDIO#ifdef S3C_SDIO	if (g_s3c_mmc_data.type == RT_READ || g_s3c_mmc_data.type==RT_WRITE){		cc_reg |= CMD_WITH_DATA;		}#endif		if( rtype != RESPONSE_NONE ) {	        cc_reg |= WAIT_RESPONSE;		if ( rtype==RESPONSE_R2_CID || rtype==RESPONSE_R2_CSD ) {		        cc_reg |= LONG_136RESPONSE;   		}	} 	else {		MMC_DEBUG(2,"  RESPONSE_NONE");	}	rSDICCON = cc_reg;	MMC_DEBUG(2,": rSDICCON 0x%08X  rSDIDTIMER Ox%08X ",rSDICCON,rSDIDTIMER);}/******* * Prototype  * static void mmc_s3c_set_transfer(u16 block_len, u16 nob,u16 int cmd) * Purpose: *          1. set SDIDIMER, SDIDCON * Entry * Exit * Exceptions: *           some field of SDIDCON must be moved into initial code of mmc driver. *******************************************************************/static void mmc_s3c_set_transfer(u16 block_len,u16 nob,int cmd){	MMC_DEBUG(2,": block_len=%d nob=%d", block_len, nob);        rSDIDTIMER = SDIDTIMER_DEFAULT;	if ( block_len > 0x1000) {		MMC_DEBUG(2,"ERROR BLOCK SIZE");	}	rSDIBSIZE = block_len;	if ( nob  > 0x1000) {		MMC_DEBUG(2,"ERROR Num BLOCK ");	}//	rSDIDCON  |=  (rSDIDCON& ~DATA_MAX_BLKNUM)| nob;	rSDIDCON   =  nob;	/* ---------------------------------------------------------------*/	/* Move Me to init routine */	/* INT_PERIOD_SINGLEBLOCK , WIDE_BUS_MODE,DMA_MODE, STOP_BY_FORDE of SDIDCON */	/* Wide Bus Mode Disable */	rSDIDCON |=RECV_AF_CMD_NODIRECT|TRAS_AF_RESPONSE_NODIRECT|                   DATA_TRANS_BLOCK|BUSY_AF_CMD_NODIRECT|STANDARD_BUS_MODE;	/* ---------------------------------------------------------------*/	switch (cmd) {	case MMC_READ_SINGLE_BLOCK:	case MMC_READ_MULTIPLE_BLOCK:                rSDIDCON |= DATA_RECV_START;    				break;	case MMC_WRITE_BLOCK:	case MMC_WRITE_MULTIPLE_BLOCK:	        rSDIDCON |= DATA_TRANS_START;		break;	default:	  	break;	}}/******* * Prototype  *   static int mmc_s3c_exec_command( struct mmc_request *request ) * * Purpose: *       1. Directly Not containing Register  * Entry * Exit * Exceptions: *     what is busy check irq enable --- only for write ? *     what is CRC status errors interrupt  *     where is RT_NO_RESPONSE ? -- must be implemented in mmc_s3c_reset  *****************************************************************/static int mmc_s3c_exec_command( struct mmc_request *request ){	int retval;	int irq = 0;	MMC_DEBUG(2," request = %p request->rtype  0x%08X ",request,request->rtype);	/* Start the actual transfer */	switch (request->cmd) {	case MMC_READ_SINGLE_BLOCK:	case MMC_READ_MULTIPLE_BLOCK:  		g_s3c_mmc_data.type = RT_READ;	        mmc_s3c_set_transfer(request->block_len,request->nob,request->cmd);                irq = S3C_RX_FIFO_LAST_DATA_INT_ON| S3C_RX_FIFO_FULL_INT_ON                      |S3C_CMD_RESPONSE_TIMEOUT_INT_ON| S3C_RESPONSE_CRC_INT_ON|S3C_RESPONSE_RECV_INT_ON;		break;	case MMC_WRITE_BLOCK:	case MMC_WRITE_MULTIPLE_BLOCK:    		g_s3c_mmc_data.type = RT_WRITE;		mmc_s3c_set_transfer(request->block_len,request->nob,request->cmd);                /* The other interrupts will be enbaled in the isr after the response recv has occured */                irq = S3C_CMD_RESPONSE_TIMEOUT_INT_ON | S3C_RESPONSE_RECV_INT_ON | S3C_RESPONSE_CRC_INT_ON;		break;	default:       		g_s3c_mmc_data.type = RT_RESPONSE_ONLY;		irq = S3C_RESPONSE_RECV_INT_ON|S3C_CMD_RESPONSE_TIMEOUT_INT_ON;			/* response only interrupt */		break;	}	/* mmc_s3c_set_command must run after mmc_s3c_set_transfer closely */	mmc_s3c_set_command(request->cmd,request->arg,request->rtype);	rSDIIMSK = irq;        	MMC_DEBUG(2,"   Real Start clocking   ");	mmc_s3c_start_clock();        rSDICCON |= CMD_START;#ifdef S3C_CMD_DONE_BUSY_WAITING_DEBUG 	if ( request->cmd == MMC_READ_SINGLE_BLOCK)  {		if ( chk_CMDend(MMC_READ_SINGLE_BLOCK,1) == 0 ) {				MMC_DEBUG(2," RESPONSE & CMD done ");		}		do {} while(1); 	}#endif/*#ifdef CONFIG_MMC_DEBUG	START_MMC_DEBUG(2) { 		u16 status[3];		status[0] = SDICSTA;		status[1] = rSDIDSTA;		status[2] = rSDIFSTA;		printk(__FUNCTION__ ": status[0]=%04x status[1]=0x%04x status[2]=0x%04x ", 		       status[0],status[1],status[2]);		decode_status(status); 		printk(")\n"); 	} END_MMC_DEBUG;#endif*/	return MMC_NO_ERROR;}/******* * Prototype  *      static void mmc_s3c_send_cmd (struct mmc_request * mr)  * Purpose: * Entry * Exit * Exceptions: *         not fully convinced of mmc_s3c_reset functions  ************************************************************/static void mmc_s3c_send_command (struct mmc_request * request) {	int retval;/*	MMC_DEBUG(2," rINTMSK   0x%08X		  rINTMOD   0x%08X	  	  rEXTINT2  0x%08X		  rEINTMSK 0x%08X		  rEINTPND 0x%08X 		  rGPGCON  0x%08X ", rINTMSK,rINTMOD,rEXTINT2,rEINTMSK,rEINTPND,rGPGCON );*/	MMC_DEBUG(1,	      ": request=%p cmd=%d (%s) arg=%08x "	      "             Cmd   status=%04x"	      "             Data  status=%04x"	      "             FIFO  status=%04x", 	      request, request->cmd, get_cmd_name(request->cmd), request->arg,	      rSDICSTA,rSDIDSTA,rSDIFSTA);	/* Global Lock Needed */	g_s3c_mmc_data.request = request;	request->result = MMC_NO_RESPONSE; /* Flag to indicate don't have result yet */	if ( request->cmd == MMC_CIM_RESET  ||  request->cmd == 0 /* GO_IDLE_STATE */) {		retval = mmc_s3c_reset(&g_s3c_mmc_data);		request->result = retval;		MMC_DEBUG(2,"  Before mmc_cmd_complete  ");		mmc_cmd_complete(request);	}	else {		retval = mmc_s3c_exec_command(request);		MMC_DEBUG(2,"  retval 0x%08X   ",retval);		#if 0				if ( retval) {	  //			g_s3c_statistics.mmc_error++;			MMC_DEBUG(0," MMC not responding ! Trying to reset");			mmc_s3c_stop_clock();			retval = mmc_s3c_adjust_clock(g_s3c_mmc_data.clock);			if(retval) {			       MMC_DEBUG(0," MMC doesn't response  ! Panic Now");			}			else {			       retval = mmc_s3c_exec_command(request);			       if (retval) {				      MMC_DEBUG(0," ASIC unable to exec !");			       }			}		}#endif			}	if (retval) {		request->result = retval;		MMC_DEBUG(2,"  Before mmc_cmd_complete  ");		mmc_cmd_complete(request);	}}	static void mmc_s3c_fix_sd_detect( unsigned long nr ){	int sd_card = ! lowlevel->slot_is_empty(lowlevel);	int sd_con_slot = g_s3c_mmc_data.insert;	MMC_DEBUG(2,": card=%d con_slot=%d", sd_card, sd_con_slot);	if ( sd_card ) {		mmc_insert(0);	}	else {		mmc_eject(0);		// mmc_s3c_set_clock (MMC_CLOCK_SLOW);	}}/* the ASIC interrupted us because it detected card insertion or removal. * wait 1/4 second and see which it was. */static void mmc_s3c_sd_detect_isr(int irq, void *dev_id, struct pt_regs *regs){	struct s3c_mmc_data *sd = (struct s3c_mmc_data *) dev_id;	mod_timer( &sd->sd_detect_timer, jiffies + (250 * HZ) / 1000 );}/******* * Prototype  * static void mmc_s3c_get_response( struct mmc_request *request ) * Purpose: the MMC upper layer determines only Response type and the other response information  *          should be provided in host adapter.  * Entry * Exit * Exceptions: *          1. Command Status Register[8][command Transfer in progress] can happen *            to exist with command response received[9] ? *          2. To improve the performance of S3C SD Host, we must put the component of  *             response into upper layer.but Now we reconstruct SDIRSP0 | SDIRSP1 into one response format *          3. response buffer is 18 bytes and last two byte means crc  ***********************************************************************/static void mmc_s3c_get_response( struct mmc_request *request ){	int i,reg;	int len = rinfo[request->rtype].length;	u8 *buf = request->response;		request->result = MMC_NO_ERROR;    	/* Mark this as having a request result of some kind */	if ( len <= 0 )				/* MMC_NO_RESPONSE */		return;	switch ( len) {	case 6:					/* 6 bytes response */		reg = rSDIRSP0;		buf[0] =  rSDICSTA & MMC_STATUS_RESPONSE_INDEX_MASK ;/*  */		buf[1] =  (reg & 0xff000000) >> 24;		buf[2] =  (reg & 0x00ff0000) >> 16;		buf[3] =  (reg & 0x0000ff00) >> 8;		buf[4] =  (reg & 0x000000ff) >> 0;		buf[5] =  (u8) ((rSDIRSP1&MMC_RESPONSE_CRC_8_0)>>SDIRSP1_CRC_SHIFT ); /* CRC+ end bit */		break;	case 17:				/* R2 (CID,CSD registers)  */		reg = rSDIRSP0;		buf[0] =  MMC_RESPONSE_LONG_135_128_VAL;		buf[1] =  (reg & 0xff000000) >> 24;		buf[2] =  (reg & 0x00ff0000) >> 16;		buf[3] =  (reg & 0x0000ff00) >> 8;		buf[4] =  (reg & 0x000000ff) >> 0;		reg = rSDIRSP1;		buf[5] =  (reg & 0xff000000) >> 24;		buf[6] =  (reg & 0x00ff0000) >> 16;		buf[7] =  (reg & 0x0000ff00) >> 8;		buf[8] =  (reg & 0x000000ff) >> 0;		reg = rSDIRSP2;		buf[9] =  (reg & 0xff000000) >> 24;		buf[10] =  (reg & 0x00ff0000) >> 16;		buf[11] =  (reg & 0x0000ff00) >> 8;		buf[12] =  (reg & 0x000000ff) >> 0;		reg = rSDIRSP3;		buf[13] =  (reg & 0xff000000) >> 24;		buf[14] =  (reg & 0x00ff0000) >> 16;		buf[15] =  (reg & 0x0000ff00) >> 8;		buf[16] =  (reg & 0x000000ff) >> 0;		break;	default:		break;		}#ifdef CONFIG_MMC_DEBUG	START_MMC_DEBUG(2) {		printk("%s:  Raw byte stream: ", __FUNCTION__);		for ( i = 0 ; i < len; i++ )			printk("%02x ", buf[i]);		printk("\n");	} END_MMC_DEBUG;#endif}/******* * Prototype  *     static void mmc_s3c_transmit_data( struct mmc_request *request ) * Purpose: * Entry * Exit    *        0 : the other blocks to send remaind *        1 : transfer done * Exceptions: *     S3C FIFO SIZE of SD is 64 Bytes *     block_len * nob should be multiple of S3C_SD_FIFO_SIZE  ***********************************************************************/static int mmc_s3c_transmit_data( struct mmc_request *request ){	u32 *buf32 = (u32 *)request->buffer;	int maxdata = request->block_len * request->nob;	int i;        int fifobytes;        int fillbytes;                //MMC_DEBUG(2,": maxdata=%d size2send=%d", maxdata, g_s3c_mmc_data.size2send);	if ( (g_s3c_mmc_data.size2send == maxdata) || (maxdata == 0) ) {	        request->nob = 0;		g_s3c_mmc_data.size2send = 0;		return 1;	/* transfer done */	}                /* Fill fifo with data, make sure not to overfill if data is            still present in the fifo.  Just add enough to refill the fifo           to its maximum. */        if (rSDIFSTA & MMC_STATUS_FIFO_READY_FOR_TX) {                fifobytes = rSDIFSTA & MMC_STATUS_FIFO_COUNT_MASK;                if ((S3C_SD_FIFO_SIZE - fifobytes) > (maxdata - g_s3c_mmc_data.size2send)){                        fillbytes = maxdata - g_s3c_mmc_data.size2send;                } else {                        fillbytes = S3C_SD_FIFO_SIZE - fifobytes;                }                fillbytes = 4 * (fillbytes / 4 ); /* Makes sure it is a multiple of 4 */                                for ( i = 0;  i < fillbytes; i +=4 ) {                        rSDIDAT = *buf32++;                        udelay(1);                }                g_s3c_mmc_data.size2send += fillbytes;        }                /* Has a complete block been transfered */        if ( g_s3c_mmc_data.size2send >= request->block_len) {                /* Reduce the number of blocks to send. */                request->nob--;                g_s3c_mmc_data.size2send -= request->block_len;        }        /*#ifdef CONFIG_MMC_DEBUG	START_MMC_DEBUG(2) { 		u16 status = H3800_ASIC1_MMC_Status;		printk(__FUNCTION__ ": irq_mask=%04x status=0x%04x (", 		       H3800_ASIC1_MMC_InterruptMask, status);		decode_status(status); 		printk(")\n"); 	} END_MMC_DEBUG;  	START_MMC_DEBUG(3) {		u8 *b = request->buffer;		for ( i = 0 ; i < request->block_len ; i++ ) {			printk(" %02x", *b++);			if ( ((i + 1) % 16) == 0 )				printk("\n");		}	} END_MMC_DEBUG;#endif*/	/* Updated the request buffer to reflect the current state */	request->buffer = (u8 *) buf32;	//	g_s3c_asic_statistics.mmc_written++;	return 0;}/******* * Prototype  *     static int mmc_s3c_receive_data( struct mmc_request *request,int flag ) * Purpose: * Entry   *     flag -1 : RX_FIFO_HALF_FULL            others : the size of last FIFO data when RX_FIFO_LAST_DATA occurs. * Exit    *     -1     : Unexpected Error *     0      : last data *     1      : keep receiving data. * Exceptions: ***********************************************************************/static int mmc_s3c_receive_data( struct mmc_request *request, int flag ){	u8 *buf = (u8 *)request->buffer;	u32  data;	int i;	MMC_DEBUG(2,": nob=%d block_len=%d buf=%p", request->nob, request->block_len, buf);	if ( request->nob <= 0 ) {		MMC_DEBUG(1,": *** nob already at 0 ***");		return -1;	}	if ( flag != -1 ) { 						if (rSDIDSTA & MMC_STATUS_RX_DATA_ON_PROGRESS) {			MMC_DEBUG(2, " Not yet DATA Rx in progress ");		}		g_s3c_mmc_data.size2read +=flag;		i = flag % 4;		if( i  !=  0 ) {		           MMC_DEBUG(2," UNEXPECTED FIFO COUNT 1 ");		}		i = g_s3c_mmc_data.size2read % 512;		if ( i  !=  0 ) {		        MMC_DEBUG(2," UNEXPECTED FIFO COUNT  2");		}		for (i=0; i < flag            ; i += 4) {			data = rSDIDAT;			*buf++ = data >> 0 & 0xff;			*buf++ = data >> 8 & 0xff;			*buf++ = data >> 16 & 0xff;			*buf++ = data >> 24 & 0xff;		}		if ( request->nob > 1 ) {			MMC_DEBUG(2," Unexpected nob count error ");		} 

⌨️ 快捷键说明

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