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

📄 mmc_pxa.c

📁 linux下mmc_sd卡的驱动.rar
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  linux/drivers/mmc/mmc_pxa.c  *      driver for Cotulla MMC controller  * *  Authors:    Vladimir Shebordaev, Igor Oblakov    *  Copyright:  MontaVista Software Inc. * *  $Id: mmc_pxa.c,v 0.3.1.12 2002/09/25 19:25:48 ted Exp ted $ * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License version 2 as *  published by the Free Software Foundation. *//*  The driver is modified by Ray.xian, the driver can support MMC and SD in PXA270 *  my  E-mail: mingrayxian@163.com   */#include <linux/version.h>#include <linux/config.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/module.h>#include <linux/errno.h>#include <linux/slab.h>#include <linux/sched.h>#include <linux/delay.h>#include <asm/hardware.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/dma.h>#include <asm/uaccess.h>#include <asm/semaphore.h>#include <mmc/types.h>#include <mmc/mmc.h>#include <mmc/ioctl.h>//#define CONFIG_MMC_DEBUG//#define CONFIG_MMC_DEBUG_VERBOSE 0#include "types.h"#include "mmc.h"#include "mmc_pxa.h"#include <asm-arm/arch-pxa/pxa-regs.h>static mmc_controller_t host = NULL;static inline int pxa_mmc_send_cmd55( mmc_controller_t );//init GPIOstatic void init_gpio(void){ //MMCLK PIN32 OUT-AF2  GPCR1 |= 0x1;  GPDR1 = GPDR1 | (1<<0);  GAFR1_L = (GAFR1_L&0xfffffffc)  | (2<<0); //MMDAT0 PIN92  GPSR2 |= 0x10000000;  GPDR2 |= 0x10000000;  // GPDR2 = GPDR2 & ~(1<<28) ;  GAFR2_U = (GAFR2_U & 0xfcffffff) | (1<<24) ; //MMDAT1 PIN109  GPSR3 |= (1<<13);  GPDR3 |= (1<<13);  GAFR3_L = (GAFR3_L & 0xf3ffffff) | (1<<26) ; //MMDAT2 PIN110  GPSR3 |= (1<<14);  GPDR3 |= (1<<14);  GAFR3_L = (GAFR3_L & 0xcfffffff) | (1<<28); //MMDAT3 PIN111  GPSR3 |= (1<<15);  GPDR3 |= (1<<15);    GAFR3_L = (GAFR3_L & 0x3fffffff) | (1<<30); //MMCMD PIN112  GPSR3 |= 0x00010000;  GPDR3 |= 0x00010000;  //GPDR3 = GPDR3 & ~(1<<16);  GAFR3_U = (GAFR3_U & 0xfffffffc) | (1<<0);   //  GPSR3 |= 0x0000e000;  GPDR3 |= 0x0000e000;  GAFR3_L = (GAFR3_L & 0x03ffffff) | 0x54000000;}/* service routines */static inline int pxa_mmc_check_state( mmc_controller_t ctrlr, pxa_mmc_state_t state ){    int ret = -1;    pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;        if ( hostdata->state != state ) {        //MMC_DEBUG( MMC_DEBUG_LEVEL3,  "state (%s vs %s)\n",  PXA_MMC_STATE_LABEL( hostdata->state ),  PXA_MMC_STATE_LABEL( state ) );        goto error;    }    ret = 0;error:              return ret;}static inline void pxa_mmc_set_state( mmc_controller_t ctrlr, pxa_mmc_state_t state ){	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;    	hostdata->state = state;}static inline int pxa_mmc_init_completion( mmc_controller_t ctrlr, u32 mask ){	int ret = -1;	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;    	if ( xchg( &hostdata->busy, 1 ) ) {		MMC_DEBUG( MMC_DEBUG_LEVEL3, "another interrupt "			"is already been expected\n" );		goto error;	}    #if CONFIG_MMC_DEBUG_IRQ 	hostdata->irqcnt = 1000;#endif	init_completion( &hostdata->completion );    	MMC_I_MASK = MMC_I_MASK_ALL & ~mask;	ret = 0;error:	return ret;}#if CONFIG_MMC_DEBUG_IRQ static struct timer_list timer;static void wait_timeo( unsigned long arg ) {	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)arg;	hostdata->timeo = 1;	complete( &hostdata->completion );	return;}#endifstatic inline int pxa_mmc_wait_for_completion( mmc_controller_t ctrlr, u32 mask ){	int ret = -1;	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;    	if ( !xchg( &hostdata->busy, 1 ) ) {        	MMC_DEBUG( MMC_DEBUG_LEVEL0, "there were no "				"interrupt awaited for\n" );		goto error;	}#if CONFIG_MMC_DEBUG_IRQ    	hostdata->timeo = 0;    	del_timer( &timer );	timer.function = wait_timeo;	timer.expires = jiffies + 1UL*HZ;	timer.data = (unsigned long)hostdata;	add_timer( &timer );#endif	wait_for_completion( &hostdata->completion );#if CONFIG_MMC_DEBUG_IRQ    	del_timer( &timer );	if ( hostdata->timeo ) {		MMC_DEBUG( MMC_DEBUG_LEVEL3, "irq timed out: " "mask=%x stat=%x\n", mask, MMC_STAT );		goto error;	}#endif		/*  verify interrupt */	//if ( (mask == ~0UL) || !( hostdata->mmc_i_reg & ~mask ) ) 		ret = 0;    error:	xchg( &hostdata->busy, 0 ); 	return ret;}static inline int pxa_mmc_stop_bus_clock( mmc_controller_t ctrlr ){	int ret = -1;    	if ( !pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_CLK_OFF ) )		{ goto out;}			if ( !pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_BUFFER_IN_TRANSIT ) ) {		MMC_DEBUG( MMC_DEBUG_LEVEL3, "BUFFER_IN_TRANSIT\n" );	        goto error;	}        		if ( pxa_mmc_init_completion( ctrlr, MMC_I_MASK_CLK_IS_OFF ) )		{ goto error;}    	MMC_STRPCL = MMC_STRPCL_STOP_CLK;		if ( pxa_mmc_wait_for_completion( ctrlr, MMC_I_REG_CLK_IS_OFF ) )	{goto error;}                      /* MMC_I_MASK = MMC_I_MASK_ALL ;            MMC_STRPCL |= 1;            while(!(MMC_I_REG & (1<<4)) )              {              }            printk(KERN_EMERG"%s::%s::MMC_I_REG is 0x%08x\n", __FILE__, __FUNCTION__, MMC_I_REG);           */     	//MMC_DEBUG( MMC_DEBUG_LEVEL3, "clock is off\n" );	pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_CLK_OFF ); out:	ret = 0;error:	return ret;}static inline int pxa_mmc_start_bus_clock( mmc_controller_t ctrlr ){	int ret = -1;	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;    	if ( (hostdata->state != PXA_MMC_FSM_CLK_OFF)	     && (hostdata->state != PXA_MMC_FSM_END_IO) ) {		MMC_DEBUG( MMC_DEBUG_LEVEL3, "illegal state %s\n", PXA_MMC_STATE_LABEL( hostdata->state ) );		goto error;	}    	MMC_STRPCL = MMC_STRPCL_START_CLK;	wmb();	//MMC_DEBUG( MMC_DEBUG_LEVEL3, "clock is on\n" ); 	ret = 0;error:	return ret;}/* int pxa_mmc_complete_cmd( mmc_controller_t ctrlr, mmc_response_fmt_t response )Effects: initializes completion to wait for END_CMD_RES intr,         waits for intr to occur, checks controller and card status Requiers: controller is in CLK_OFF stateModifies: moves controller to the END_CMD stateReturns: */ static mmc_error_t pxa_mmc_complete_cmd( mmc_controller_t ctrlr, mmc_response_fmt_t format, int send_abort ){	mmc_error_t ret = MMC_ERROR_GENERIC;	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;	int mask, nwords;	u32 status;    	MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD%d(0x%04x%04x)\n", MMC_CMD & 0x3f, MMC_ARGH, MMC_ARGL);/* FIXME: check arguments */    	if ( (hostdata->state != PXA_MMC_FSM_CLK_OFF)	     && (hostdata->state != PXA_MMC_FSM_END_IO) ) {		MMC_DEBUG( MMC_DEBUG_LEVEL3, "illegal state %s\n",				PXA_MMC_STATE_LABEL( hostdata->state ) );		goto error;	}    	mask = MMC_I_MASK_END_CMD_RES;	if ( pxa_mmc_init_completion( ctrlr, mask ) )		goto error;    	MMC_PRTBUF = MMC_PRTBUF_BUF_FULL; /* start the clock */	if ( pxa_mmc_start_bus_clock( ctrlr ) )		goto error;    /* wait for END_CMD_RES intr */	if ( pxa_mmc_wait_for_completion( ctrlr, MMC_I_REG_END_CMD_RES ) )		goto error;/* check status */    /*modify here*/   {  register int i;      nwords = (format == MMC_NORESPONSE) ? 0 :		(format == MMC_R1) ? 3 : 		(format == MMC_R2) ? 8 :		(format == MMC_R3) ? 3 :		(format == MMC_R6) ? 3 :		-1;	ret = nwords;       // printk("nword is 0x%d\n", nwords);        for ( i = nwords - 1; i >= 0 ; i-- ) {			u32 res = MMC_RES;			int ibase = i<<1;                       // printk(__FILE__" RESPONE is 0x%08x\n", res);			hostdata->mmc_res[ibase] = ((u8 *)&res)[0];			hostdata->mmc_res[ibase + 1] = ((u8 *)&res)[1];			--ret;	 	}      }  /*modify here*/	if ( hostdata->mmc_stat & MMC_STAT_TIME_OUT_RESPONSE ) {		// MMC_DEBUG(MMC_DEBUG_LEVEL3, "response timeout\n");		ret = MMC_ERROR_TIME_OUT_RESPONSE;		goto error;    	} else if ( hostdata->mmc_stat & MMC_STAT_READ_TIME_OUT ) {		// MMC_DEBUG(MMC_DEBUG_LEVEL3, "read timeout\n");		ret = MMC_ERROR_READ_TIME_OUT;		goto error;    	} else if ( hostdata->mmc_stat & MMC_STAT_RES_CRC_ERROR ) {		// MMC_DEBUG(MMC_DEBUG_LEVEL3, "response crc err\n");                if ( ((MMC_CMD & 2)|| (MMC_CMD & 9) || (MMC_CMD & 10) )  && (hostdata->mmc_res[ ((nwords-1)<<1)] & 0x80 ))                {                        //printk("MMC_STAT_RES_CRC_ERROR occour, the word [127]is 0x%08x\n",  hostdata->mmc_res[(nwords-1)<<1]);                }                else 		  { ret = MMC_ERROR_RES_CRC_ERROR;	 	   goto error;}    	} else if ( hostdata->mmc_stat & MMC_STAT_CRC_READ_ERROR ) {		// MMC_DEBUG(MMC_DEBUG_LEVEL3, "read crc err\n");		ret = MMC_ERROR_CRC_READ_ERROR;		goto error;        	} else if ( hostdata->mmc_stat & MMC_STAT_CRC_WRITE_ERROR ) {		// MMC_DEBUG(MMC_DEBUG_LEVEL3, "write crc err\n");		ret = MMC_ERROR_CRC_WRITE_ERROR;		goto error;	}  /*  	nwords = (format == MMC_NORESPONSE) ? 0 :		(format == MMC_R1) ? 3 : 		(format == MMC_R2) ? 8 :		(format == MMC_R3) ? 3 : 		-1;	ret = nwords;        printk(__FILE__" "__FUNCTION__"nword is 0x%d\n", nwords);*/	if ( nwords > 0 ) {//		register int i;/*		MMC_DEBUG( MMC_DEBUG_LEVEL3, "nwords=%d\n", nwords );		for ( i = nwords - 1; i >= 0 ; i-- ) {			u32 res = MMC_RES;			int ibase = i<<1;                        printk(__FILE__" "__FUNCTION__"RESPONE is 0x%08x\n", res);			hostdata->mmc_res[ibase] = ((u8 *)&res)[0];			hostdata->mmc_res[ibase + 1] = ((u8 *)&res)[1];			--ret;		}  */ #ifdef CONFIG_MMC_DEBUG		switch ( format ) {		case MMC_R1:			MMC_DUMP_R1( ctrlr );			break;		case MMC_R2:			MMC_DUMP_R2( ctrlr );			break;		case MMC_R3:			MMC_DUMP_R3( ctrlr );			break;		default:			MMC_DEBUG( MMC_DEBUG_LEVEL3, 					"unknown response format\n" );			ret = MMC_ERROR_GENERIC;			goto error;		}#endif/* check card status for R1(b) commands */		if ( format == MMC_R1 ) {			u8 cmd;						((u8 *)&status)[0] = hostdata->mmc_res[1];			((u8 *)&status)[1] = hostdata->mmc_res[2];			((u8 *)&status)[2] = hostdata->mmc_res[3];			((u8 *)&status)[3] = hostdata->mmc_res[4];			cmd = PXA_MMC_RESPONSE( ctrlr, 5 )&0x3f;			/*MMC_DEBUG( MMC_DEBUG_LEVEL3, 			//printk( KERN_INFO __FUNCTION__"():                         "cmd=%u status: 0x%08x\n",                        cmd, status );                         */                       			switch ( cmd ) {			case 11:			case 18:			case 20:			case 25:				if ( !(status & 0x00000100) ) /* FIXME */					goto mmc_error;			default:				break;			}			if ( status & MMC_CARD_STATUS_OUT_OF_RANGE ) {				ret = MMC_ERROR_OUT_OF_RANGE;				goto mmc_error;		    	} else if ( status & MMC_CARD_STATUS_ADDRESS_ERROR ) {				ret = MMC_ERROR_ADDRESS_ERROR;				goto mmc_error;			} else if ( status & MMC_CARD_STATUS_BLOCK_LEN_ERROR ) {				ret = MMC_ERROR_ADDRESS_ERROR;				goto mmc_error;			} else if ( status & MMC_CARD_STATUS_ERASE_SEQ_ERROR ) {				ret = MMC_ERROR_ERASE_SEQ_ERROR;				goto mmc_error;			} else if ( status & MMC_CARD_STATUS_ERASE_PARAM ) {				ret = MMC_ERROR_ERASE_PARAM;				goto mmc_error;			} else if ( status & MMC_CARD_STATUS_WP_VIOLATION ) {				ret = MMC_ERROR_WP_VIOLATION;				goto mmc_error;			} else if ( status & MMC_CARD_STATUS_CARD_IS_LOCKED ) {				ret = MMC_ERROR_CARD_IS_LOCKED;				goto mmc_error;			} else if ( status & MMC_CARD_STATUS_LOCK_UNLOCK_FAILED ) {				ret = MMC_ERROR_LOCK_UNLOCK_FAILED;				goto mmc_error;			} else if ( status & MMC_CARD_STATUS_COM_CRC_ERROR ) {				ret = MMC_ERROR_COM_CRC_ERROR;				goto mmc_error;			} else if ( status & MMC_CARD_STATUS_ILLEGAL_COMMAND ) {			//	ret = MMC_ERROR_ILLEGAL_COMMAND;			//	goto mmc_error;			} else if ( status & MMC_CARD_STATUS_CARD_ECC_FAILED ) {				ret = MMC_ERROR_CARD_ECC_FAILED;				goto mmc_error;			} else if ( status & MMC_CARD_STATUS_CC_ERROR ) {				ret = MMC_ERROR_CC_ERROR;				goto mmc_error;			} else if ( status & MMC_CARD_STATUS_ERROR ) {				ret = MMC_ERROR_ERROR;				goto mmc_error;			} else if ( status & MMC_CARD_STATUS_UNDERRUN ) {				ret = MMC_ERROR_UNDERRUN;				goto mmc_error;			} else if ( status & MMC_CARD_STATUS_OVERRUN ) {				ret = MMC_ERROR_OVERRUN;				goto mmc_error;			} else if ( status & MMC_CARD_STATUS_CID_CSD_OVERWRITE ) {				ret = MMC_ERROR_CID_CSD_OVERWRITE;				goto mmc_error;			} else if ( status & MMC_CARD_STATUS_ERASE_RESET ) {

⌨️ 快捷键说明

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