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

📄 mmc_io.c

📁 给予mx21处理器的嵌入式系统的mmc卡驱动程序
💻 C
字号:
/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * Copyright (C) 2002 Motorola Semiconductors HK Ltd * *//****************************************************************************** *  * Copyright (C) 2001, Motorola All Rights Reserved *  * File Name:   mmcsd.c *  * Progammers:  Yiwei Zhao  * * Date of Creations:   30  DEC,2001 * * Synopsis: * * Modification History: * 30 DEC, 2001 * *****************************************************************************//* Functions List:       * * * *//*  * Implementation of the MMCSD Driver. */#include <linux/config.h>#include "mmc_def.h"#include "mmc_main.h"static u32 cur_perclk2;//pd25void _mmcsd_socket1_irq_set(){	_reg_GPIO_GIUS(GPIOD) |= 0x02000000;	_reg_GPIO_DDIR(GPIOD) &= ~0x02000000;	_reg_GPIO_IMR(GPIOD)  |= 0x02000000;//enable	_reg_GPIO_ICR2(GPIOD) |= 0x000c0000;//negative level trigger	_reg_GPIO_PUEN(GPIOD) &= ~0x02000000;  // pull up  enable interrupt}void _mmcsd_socket1_clear_irq(){    _reg_GPIO_ISR(GPIOD) = 0x02000000;}/****************************************************************************** * Function Name: _MMCSD_CheckHardwareRevision  * * Input:        * 	 * Value Returned:  * * Description:  *      *Modification History: *	30 DEC,2001, Initial version.                   Yiwei Zhao  ******************************************************************************/u32	 _MMCSD_ChectHardwareRevision(int port){	u32 HardwareID;#ifdef CONFIG_ARCH_MX1ADS	HardwareID = mmcsdr_rev_no;	TRACE("rev_no = %x \n",mmcsdr_rev_no);	if(HardwareID!=0x0390)	{		TRACE("HardwareID = 0x%x, return = %d", HardwareID,1);		return 1;               //Hardware Revision Error;	}#endif#ifdef CONFIG_ARCH_MX2ADS	if(port == 0)	{		HardwareID = mmcsdr_rev_no;	}	else if(port == 1)	{		HardwareID = mmcsdr_rev_no_2;	}	if(HardwareID!=0x0400)	{		TRACE("HardwareID = 0x%x, return = %d", HardwareID,1);		return 1;               //Hardware Revision Error;	}#endif	return 0;}/****************************************************************************** * Function Name: _MMCSD_SoftReset  * * Input:        * 	 * Value Returned:  * * Description:  *      *Modification History: *	30 DEC,2001, Initial version.                   Yiwei Zhao  ******************************************************************************/u32	 _MMCSD_SoftReset(int port){	#ifdef CONFIG_ARCH_MX1ADS	// System Reset	Start_Stop_Clk(0x8);	// System Reset, MMC core enable & Stop CLk	Start_Stop_Clk(0xD);	// MMC Core enable & Stop Clk	Start_Stop_Clk(0x5);	Start_Stop_Clk(0x5);	Start_Stop_Clk(0x5);	Start_Stop_Clk(0x5);	Start_Stop_Clk(0x5);	Start_Stop_Clk(0x5);	Start_Stop_Clk(0x5);	Start_Stop_Clk(0x5);#ifdef MMCSD_DMA_ENDIAN_ERR	// PLAM -- choose big endian FIFO mode	mmcsdr_str_stp_clk |= 0x00000020;	// end PLAM#else	mmcsdr_str_stp_clk &= ~0x00000020;#endif	//Set MMC Response Time-Out Register	mmcsdr_res_to=0xffff;  		//Set Block length register	mmcsdr_blk_len=MMCSD_MINIMUM_BLK_SIZE ;//2002/04/19		//Set MMC Number of Blocks Register	mmcsdr_nob=1;//2002/04/19#endif#ifdef CONFIG_ARCH_MX2ADS	// System Reset	Start_Stop_Clk(0x8,port);	// System Reset, MMC core enable & Stop CLk	Start_Stop_Clk(0xD,port);	// MMC Core enable & Stop Clk	Start_Stop_Clk(0x5,port);	Start_Stop_Clk(0x5,port);	Start_Stop_Clk(0x5,port);	Start_Stop_Clk(0x5,port);	Start_Stop_Clk(0x5,port);	Start_Stop_Clk(0x5,port);	Start_Stop_Clk(0x5,port);	Start_Stop_Clk(0x5,port);	if(port == 0)	{		mmcsdr_str_stp_clk &= ~0x00000020;	//Set MMC Response Time-Out Register		mmcsdr_res_to=0xffff;  		//Set Block length register		mmcsdr_blk_len=MMCSD_MINIMUM_BLK_SIZE ;		//Set MMC Number of Blocks Register		mmcsdr_nob=1;	}	else if(port == 1)	{		mmcsdr_str_stp_clk_2 &= ~0x00000020;	//Set MMC Response Time-Out Register		mmcsdr_res_to_2=0xffff;  		//Set Block length register		mmcsdr_blk_len_2=MMCSD_MINIMUM_BLK_SIZE ;		//Set MMC Number of Blocks Register		mmcsdr_nob_2=1;	}	#endif		return 0;	}void _MMCSD_ReadTimeOut(u32 arg,int port){	arg = 0x2db4;	if(port == 1)		mmcsdr_read_to_2=0x2db4;	else		mmcsdr_read_to=0x2db4;}/****************************************************************************** * Function Name: _MMCSD_SetCmd  * * Input:        * 	 * Value Returned:  * * Description:  *      *Modification History: *	30 DEC,2001, Initial version.                   Yiwei Zhao  ******************************************************************************/void _MMCSD_SetCmd(u8 cmd,u32 arg,u32 ctrl,int port){#ifdef MMCSD_CMD	TRACE("	----------------------------------------");	TRACE("	CMD%02d  Arg: 0x%08lX  Ctrl: 0x%04lX\n",cmd,arg,ctrl);#endif	if(port == 1)	{		mmcsdr_cmd_2=cmd;		mmcsdr_argumenth_2=arg>>16;		mmcsdr_argumentl_2=arg&0xFFFF;		mmcsdr_cmd_dat_cont_2=ctrl;	}	else	{		mmcsdr_cmd=cmd;		mmcsdr_argumenth=arg>>16;		mmcsdr_argumentl=arg&0xFFFF;		mmcsdr_cmd_dat_cont=ctrl;	}}/****************************************************************************** * Function Name: _MMCSD_IsRun  * * Input:        * 	 * Value Returned:  * * Description:  *      *Modification History: *	30 DEC,2001, Initial version.                   Yiwei Zhao  ******************************************************************************/u32 _MMCSD_IsRun(int port){	if(port == 1)	return (mmcsdr_status_2)&0x100;	else	return (mmcsdr_status)&0x100;}/****************************************************************************** * Function Name: _MMCSD_StartClk  * * Input:        * 	 * Value Returned:  * * Description:  *      *Modification History: *	30 DEC,2001, Initial version.                   Yiwei Zhao  ******************************************************************************/void _MMCSD_StartClk(int port){	unsigned short count = 0;	do	{		if (count++ == 0)		{			// do this every 256 loops			if(port == 1)			mmcsdr_str_stp_clk_2 |= 0x06;			else			mmcsdr_str_stp_clk |= 0x06;		}	}	while(!_MMCSD_IsRun(port));}/****************************************************************************** * Function Name: _MMCSD_StopClk  * * Input:        * 	 * Value Returned:  * * Description:  *      *Modification History: *	30 DEC,2001, Initial version.                   Yiwei Zhao  ******************************************************************************/void _MMCSD_StopClk(int port){	unsigned short count = 0;	do	{		if (count++ == 0)		{			// do this every 256 loops			if(port == 1)			mmcsdr_str_stp_clk_2 |= 0x05;			else			mmcsdr_str_stp_clk |= 0x05;					}	}while(_MMCSD_IsRun(port));}/****************************************************************************** * Function Name: _MMCSD_GetResponses  * * Input:        * 	 * Value Returned:  * * Description:  *      *Modification History: *	30 DEC,2001, Initial version.                   Yiwei Zhao  ******************************************************************************/void _MMCSD_GetResponses(MMCSD_Responses *pRS, u8  rsType,int port){	int i;	u16 rs;    u32 temp;	if(rsType==MMCSDB_R1)	{			pRS->status=0;		if(port == 1)			temp=(u32)mmcsdr_res_fifo_2;		else			temp=(u32)mmcsdr_res_fifo;					rs=(u16)temp;		pRS->status|=((u32)rs&0x00FF)<<24;		if(port == 1)			temp=(u32)mmcsdr_res_fifo_2;		else			temp=(u32)mmcsdr_res_fifo;		rs=(u16)temp;		pRS->status|=((u32)rs)<<8;		if(port == 1)			temp=(u32)mmcsdr_res_fifo_2;		else			temp=(u32)mmcsdr_res_fifo;		rs=(u16)temp;		pRS->status|=(rs&0xFF00)>>8;	}	else if(rsType==MMCSDB_R3)	{		pRS->OCR=0;		if(port == 1)			temp=(u32)mmcsdr_res_fifo_2;		else			temp=(u32)mmcsdr_res_fifo;		rs=(u16)temp;		temp=rs&0x00FF;		pRS->OCR|=temp<<24;		if(port == 1)			temp=(u32)mmcsdr_res_fifo_2;		else			temp=(u32)mmcsdr_res_fifo;		rs=(u16)temp;		pRS->OCR|=((u32)rs)<<8;		if(port == 1)			temp=(u32)mmcsdr_res_fifo_2;		else			temp=(u32)mmcsdr_res_fifo;		rs=(u16)temp;		pRS->OCR|=(rs&0xFF00)>>8;	}	else 	{			for(i=0;i<16;)			{				if(port == 1)				temp=(u32)mmcsdr_res_fifo_2;			else				temp=(u32)mmcsdr_res_fifo;						rs=(u16)temp;			pRS->CSD[i] = (rs&0xFF00)>>8;			i++;			pRS->CSD[i] = (rs&0x00FF);			i++;		}	}	}/****************************************************************************** * Function Name: _MMCSD_SetBlockLenReg  * * Input:        * 	 size:		size of the block. * 	 * Value Returned:  * 	 * * Description:  * 	this routine sets the size of a block  *      *Modification History: *	30 DEC,2001, Initial version.                   Yiwei Zhao  ******************************************************************************/void _MMCSD_SetBlockLenReg(u16 size,u32 port){	if(port == 1)		mmcsdr_blk_len_2=size;	else		mmcsdr_blk_len=size;}/****************************************************************************** * Function Name: _MMCSD_SetNumberOfBlockReg  * * Input:        * 	 * 	num:	Number of block	 * 	 * Value Returned:  * 	 * * Description:  * 	this routine sets number of the blocks.  *      *Modification History: *	30 DEC,2001, Initial version.                   Yiwei Zhao  ******************************************************************************/void _MMCSD_SetNumberOfBlockReg(u16 num,u32 port){	if(port == 1)		mmcsdr_nob_2=num;	else		mmcsdr_nob=num;}/****************************************************************************** * Function Name: _MMCSD_ClockSet  * * Input:        * 	 * 	speed:		if speed == oxff, set the highest speed. * 	 * Value Returned:  * 	 * * Description:  * 	this routine set clock rate.     *      *Modification History: *	30 DEC,2001, Initial version.                   Yiwei Zhao  ******************************************************************************/void _MMCSD_ClockSet(u32 prescaler,u8 clk,int port){	_MMCSD_StopClk(port);#ifdef CONFIG_ARCH_MX1ADS	prescaler = prescaler&0x07;	clk = clk&0x07;	mmcsdr_clk_rate=(prescaler<<3)|clk;#endif#ifdef CONFIG_ARCH_MX2ADS	prescaler = prescaler&0x0f;	clk = clk&0xfff;	if(port == 1)		mmcsdr_clk_rate_2=(prescaler<<4)|clk;	else		mmcsdr_clk_rate=(prescaler<<4)|clk;#endif	}void _MMCSD_SetClk(int mode,int port){#ifdef CONFIG_ARCH_MX1ADS	if(mode == MMCSD_HIGH_SPEED)	{		if(cur_perclk2<20)		{			_MMCSD_ClockSet(0,0);		}		else		{			_MMCSD_ClockSet(cur_perclk2/20-1,1);		}	}	else	{		_MMCSD_ClockSet(7,7);	}#endif#ifdef CONFIG_ARCH_MX2ADS	if(mode == MMCSD_HIGH_SPEED)	{		if(cur_perclk2<20)		{			_MMCSD_ClockSet(0,1,port);		}		else		{			_MMCSD_ClockSet(0,cur_perclk2/20+1,port);		}	}	else	{		_MMCSD_ClockSet(8,0xa,port);//if perclk2 is about 20M	}	TRACE("clkrate=0x%x ,perclk2=0x%x \n",mmcsdr_clk_rate,cur_perclk2);#endif	}/****************************************************************************** * Function Name: _MMCSD_PinConfig  * * Input:        * 	 * Value Returned:  * * Description:  * 	this routine sets GPIO registers.     *      *Modification History: *	30 DEC,2001, Initial version.                   Yiwei Zhao  ******************************************************************************/static void _MMCSD_get_cur_perclk2(void){#ifdef CONFIG_ARCH_MX1ADS	cur_perclk2 = *(u32 *)CRM_PCDR;	cur_perclk2 = (cur_perclk2&0x000000F0)>>4;	cur_perclk2 = 96/(cur_perclk2+1);#endif#ifdef CONFIG_ARCH_MX2ADS	cur_perclk2 = _reg_CRM_PCDR;	cur_perclk2 = (cur_perclk2&0x03c00000)>>22;	cur_perclk2 = 128/(cur_perclk2+1);	#endif}void _MMCSD_PinConfig(void){	_MMCSD_get_cur_perclk2();#ifdef CONFIG_ARCH_MX1ADS	*(u32 *)DBMX1_GIUS_B &= 0xFFFFC0FF;	*(u32 *)DBMX1_GPR_B &= 0xFFFFC0FF;	*(u32 *)DBMX1_PUEN_B |= 0x00003f00;#endif#ifdef CONFIG_ARCH_MX2ADS	_reg_GPIO_DDIR(GPIOE) |= 0x00fc0000;//0x3f000000;	_reg_GPIO_GIUS(GPIOE) &= 0xff03ffff;	_reg_GPIO_GPR(GPIOE)  &= 0xff03ffff;	_reg_GPIO_PUEN(GPIOE) |= 0x00fc0000;	//add for SD2 pb4~pb9 pb7-dat3,pb9-clk	_reg_GPIO_DDIR(GPIOB) |= 0x000003f0; 	_reg_GPIO_GIUS(GPIOB) &= ~0x000003f0;	_reg_GPIO_GPR(GPIOB)  &= ~0x000003f0;	_reg_GPIO_PUEN(GPIOB) |= 0x000003f0;#endif	}void _MMCSD_64M_MMC_PinConfig(void){	_MMCSD_get_cur_perclk2();#ifdef CONFIG_ARCH_MX2ADS	//pin pe18~23,18,19,20,22 up, 21-dat3,23-clk	_reg_GPIO_DDIR(GPIOE) |= 0x00fc0000; 	_reg_GPIO_GIUS(GPIOE) &= 0xff03ffff;	_reg_GPIO_GPR(GPIOE)  &= 0xff03ffff;	_reg_GPIO_PUEN(GPIOE) |= 0x005c0000;//	_reg_GPIO_PUEN(GPIOE) &= 0xff5fffff;		//add for SD2 pb4~pb9 pb7-dat3,pb9-clk	_reg_GPIO_DDIR(GPIOB) |= 0x000003f0; 	_reg_GPIO_GIUS(GPIOB) &= ~0x000003f0;	_reg_GPIO_GPR(GPIOB)  &= ~0x000003f0;	_reg_GPIO_PUEN(GPIOB) |= 0x00000170;	_reg_GPIO_PUEN(GPIOB) &= 0xfffffd7f;		#endif		//pb8~13, 11-dat3,12-clk,13-cmd#ifdef CONFIG_ARCH_MX1ADS	*(u32 *)DBMX1_DDIR_B |= 0x00003F00;		// Enable SDHC's port to Output	*(u32 *)DBMX1_GIUS_B &= 0xFFFFC0FF;	*(u32 *)DBMX1_GPR_B  &= 0xFFFFC0FF;	*(u32 *)DBMX1_PUEN_B |= 0x00003700;		*(u32 *)DBMX1_PUEN_B  &=0xfffff7ff;//Karen modify it for MMC test			#endif}/************************************************put content to STR_STP_CLK U32 Clk_en = set the clk to start or stop	0x6: start MMC clk	0x5: stop MMC clk************************************************/void Start_Stop_Clk(u32 Clk_en,int port){    	//when the clk is STARTED check whether the MMC is enable and reset is not set 	if(((Clk_en&0x2)!=0)&&((Clk_en&0x8)==0)&&((Clk_en&0x4)!=0))    {    	if(port == 1)    	{    		mmcsdr_str_stp_clk_2 &= ~MMCSD_CLOCK_MASK;			mmcsdr_str_stp_clk_2 |= Clk_en;			while ( ((mmcsdr_status_2)&0x100) == 0 );//check the status if the clock do not start    	}    	else		{			mmcsdr_str_stp_clk &= ~MMCSD_CLOCK_MASK;			mmcsdr_str_stp_clk |= Clk_en;			while ( ((mmcsdr_status)&0x100) == 0 );//check the status if the clock do not start		}	}	//when the clk is STOPPED, check whether the MMC is enable and reset is not set	else if(((Clk_en&0x1)!=0)&&((Clk_en&0x8)==0)&&((Clk_en&0x4)!=0))    {    	if(port == 1)		{			mmcsdr_str_stp_clk_2 &= ~MMCSD_CLOCK_MASK;			mmcsdr_str_stp_clk_2 |= Clk_en;			while ( ((mmcsdr_status_2) & 0x100) != 0 );//check the status if the clock is still running		}		else		{			mmcsdr_str_stp_clk &= ~MMCSD_CLOCK_MASK;			mmcsdr_str_stp_clk |= Clk_en;			while ( ((mmcsdr_status) & 0x100) != 0 );//check the status if the clock is still running		}	}	//reset or enable the syste	else 	{		if(port == 1)		{			mmcsdr_str_stp_clk_2 &= ~MMCSD_CLOCK_MASK;			mmcsdr_str_stp_clk_2 |= Clk_en;		}		else		{			mmcsdr_str_stp_clk &= ~MMCSD_CLOCK_MASK;			mmcsdr_str_stp_clk |= Clk_en;		}			}}

⌨️ 快捷键说明

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