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

📄 s3c_mmc.c

📁 mmc 方式通讯的在CPU PXA270下的WINCE 5驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
				else {					MMC_DEBUG(2," RESPONSE OK ");				}    	   		}			rSDICSTA=status;	/* Clear cmd & rsp end state */		}		else	/* CRC check */		{			if( (status&0x1f00) != 0xa00 )	/* Check error */	    		{				MMC_DEBUG(2," ERROR CMD%d:rSDICSTA=0x%x, rSDIRSP0=0x%x",cmd, rSDICSTA, rSDIRSP0);				rSDICSTA=status;   /* Clear error state */				if(((status&0x400)==0x400))		    		return -EIO;	/* Timeout error */    	    		}	   		rSDICSTA=status;		}		return 0;    	}}static void  mmc_CMD0(void) {	rSDICARG = 0x0;          rSDICCON = START_TRANSMISSION_PRE;        s3c_mmc_start_clock ();        rSDICCON |= CMD_START;        mdelay(1);	chk_CMDend(0,0);}/******* * Prototype *      static int s3c_mmc_reset( struct s3c_mmc_data *sd ) * * Purpose: *      1. mmc_cim_init_stack(struct mmc_dev *dev,int first ) issue "MMC_CIM_RESET" *      2. implement "CMD0" * Entry * Exit * Exceptions: *     It is nessecary to get clock slow that obtains the sufficient response time. *****************************************************************************/static int s3c_mmc_reset( struct s3c_mmc_data *sd ){        int retval = 0 ;        g_s3c_mmc_data.type = RT_NO_RESPONSE;        mmc_CMD0();        return retval;}                                                                                                                             /******* * Prototype *      s3c_mmc_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 s3c_mmc_set_command( u32 cmd, u32 arg, enum mmc_rsp_t rtype ){        u32 cc_reg = 0;        /* 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){        }#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);}                                                                                                                                                static int s3c_mmc_exec_command( struct mmc_request *request ){	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;	        s3c_mmc_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;		s3c_mmc_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;	}	/* s3c_mmc_set_command must run after s3c_mmc_set_transfer closely */	s3c_mmc_set_command(request->cmd,request->arg,request->rtype);	rSDIIMSK = irq;        	MMC_DEBUG(2,"   Real Start clocking   ");	s3c_mmc_start_clock();        rSDICCON |= CMD_START;#if 0  /*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	return MMC_NO_ERROR;}static void s3c_mmc_send_command( struct mmc_request *request ){	int retval;	MMC_DEBUG(1, ": request=%p cmd=%d (%s) arg=%08x "		      "             Cmd   status=%04x"		      "             Data  status=%04x"		      "             FIFO  status=%04x\r\n", 		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 ) {		retval = s3c_mmc_reset(&g_s3c_mmc_data);		request->result = retval;		MMC_DEBUG(2,"  Before mmc_cmd_complete  ");		mmc_cmd_complete(request);	}	else {		retval = s3c_mmc_exec_command(request);		MMC_DEBUG(2,"  retval 0x%08X   ",retval);	}	if (retval) {		request->result = retval;		MMC_DEBUG(2,"  Before mmc_cmd_complete  ");		mmc_cmd_complete(request);	}	MMC_DEBUG(2, " rSDIIMSK 0x%08X cmd 0x%08X data 0x%08X fifo 0x%08X",rSDIIMSK,rSDICSTA,rSDIDSTA,rSDIFSTA); 	MMC_DEBUG(2, " rSDICON  0x%08X CCON  0x%08X DCONdata 0x%08X ",rSDICON,rSDICCON,rSDIDCON); }static void s3c_mmc_get_response( struct mmc_request *request ){	int 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	{		int i;		printk("%s:  Raw byte stream: ", __FUNCTION__);		for ( i = 0 ; i < len; i++ )			printk("%02x ", buf[i]);		printk("\n");	}#endif}/******* * Prototype  *     static void s3c_mmc_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 s3c_mmc_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;        }        	if(rSDIDSTA & MMC_STATUS_DATA_TRANSFER_DONE)		rSDIDSTA = MMC_STATUS_DATA_TRANSFER_DONE;        /* 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;        }        	/* Updated the request buffer to reflect the current state */	request->buffer = (u8 *) buf32;	/* g_s3c_asic_statistics.mmc_written++; */	return 0;}/******* * Prototype  *     static int s3c_mmc_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 s3c_mmc_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 ");		} 		else {			request->nob-- ; 		}		if(rSDIFSTA & MMC_STATUS_FIFO_RX_LAST_DATA)			rSDIFSTA |=  MMC_STATUS_FIFO_RX_LAST_DATA;		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;		if(rSDIFSTA & MMC_STATUS_FIFO_RX_LAST_DATA)			rSDIFSTA |=  MMC_STATUS_FIFO_RX_LAST_DATA;		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		 {		u8 *b = request->buffer - 512 ;		for ( i = 0 ; i < request->block_len ; i++ ) {			printk(" %02x", *b++);			if ( ((i + 1) % 16) == 0 )				printk("\n");			}		} #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;}static void s3c_mmc_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);                s3c_mmc_set_clock (MMC_CLOCK_SLOW);        }}static void s3c_mmc_detect_handler( unsigned long nr ){	int card_in =  !lowlevel->slot_is_empty(lowlevel);	/*int sd_con_slot = g_s3c_mmc_data.insert;*/	if (card_in ) {		mmc_insert(0);		MMC_DEBUG(1,"Card In");	}	else {		mmc_eject(0);		MMC_DEBUG(1,"Card Eject");		s3c_mmc_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 s3c_mmc_detect_isr(int irq, void *dev_id, struct pt_regs *regs){	struct s3c_mmc_data *mmc_data = (struct s3c_mmc_data *) dev_id;		set_gpio_ctrl( (lowlevel->sdi_gpio_cd) | GPIO_PULLUP_EN | GPIO_MODE_IN );

⌨️ 快捷键说明

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