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

📄 mmc_main.c.bak

📁 MMC 0.4.0驱动 龙珠 MOTO板子
💻 BAK
📖 第 1 页 / 共 5 页
字号:
/* * 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 * *//** *  * @defgroup MMC 			MMC driver **/ /**@{*/ /** * @file   mmc_main.c * @brief   mmc driver source code * * MMC operates as a block device, this file provides all the interface functions \n * for block device * * Modification History: * 30 DEC, 2001 * * @bug **/#ifndef __KERNEL__#  define __KERNEL__#endif#ifndef MODULE#  define MODULE#endif#define  TESTING_PAGE (1024*1024*40/512) #define MMCSD_TEST_PAGE_NUM 8 #include <linux/config.h>#include <asm/bitops.h>#include <linux/delay.h>#include <linux/errno.h>  /* error codes */#include <linux/fs.h>     /* everything... */#include <linux/fcntl.h>  /* O_ACCMODE */#include <linux/hdreg.h>  /* HDIO_GETGEO */#include <linux/ioctl.h>#include <linux/interrupt.h>#include <linux/init.h>#include <linux/ioport.h>#include <linux/in.h>#include <linux/kernel.h> /* printk() */#include <linux/kdev_t.h>#include <linux/module.h>#include <linux/mm.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/string.h>#include <linux/timer.h>#include <linux/tqueue.h>#include <linux/types.h>  /* size_t */#include <linux/pm.h>#include <linux/poll.h>#include <linux/ptrace.h>#include <linux/vmalloc.h>#include <linux/version.h>#include <linux/proc_fs.h>//for proc//#include <linux/malloc.h>#include <asm/io.h>#include <linux/wait.h>#include <asm/hardware.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/uaccess.h>#include <asm/system.h>   /* cli(), *_flags */#include <asm/dma.h>#include <linux/blkdev.h>#include <linux/devfs_fs_kernel.h>//#include <asm/arch/apmc.h>/*These symbols in <linux/blk.h> that must be defined in advance.*/#define DEVICE_NR(device) MINOR(device)		#define DEVICE_NAME "mmc"			/* name for messaging */#define DEVICE_NO_RANDOM			/* no entropy to contribute */#include <linux/blk.h>#ifdef CONFIG_ARCH_MX1ADS#include "dbmx1_dma.h"#endif#include "mmc_def.h"#include "mmc_main.h"        /* local definitions */#ifdef LINUX_20#  error "This module can't run with Linux-2.0"#endif#ifdef CONFIG_PM#define PM_OPT " [pm]"#else#define PM_OPT ""#endif/* * if partition is considered then HAVE_BLKPG_H should be defined. */#include <linux/blkpg.h>  /* blk_ioctl() *//* * variables will be initialized in init function. */MMCSD_Dev 		*g_mmcsd_devices = NULL;u8	 			g_mmcsd_cur_device = 0xff;u8				g_mmcsd_num = 0;u8				g_mmcsd_cmd[2] = {0,0};MMCSD_Lock		g_selected_lock[2];int 			g_mmcsd_major;int				g_mmcsd_presence = 0;volatile u32	g_mmcsd_status =0;static devfs_handle_t devfs_handle = NULL;	//devfs#define MMC_PMST_SUSPEND	0#define MMC_PMST_RESUME		1static int g_mmc_status = MMC_PMST_RESUME;struct apmc_user *g_Mmc_apmc;/* Function declarations */static int mmcsd_open(struct inode *inode, struct file *filp);static int mmcsd_release(struct inode *inode, struct file *filp);static int  mmcsd_revalidate(kdev_t dev);static MMCSD_Dev *mmcsd_locate_device(const struct request *req);void mmcsd_request_handler(request_queue_t  * q);static int mmcsd_data_transfer(MMCSD_Dev *device,struct request *req);static int mmcsd_read(	MMCSD_Dev *device, char * buffer, 			u32 sector, u32 nr_sector);static int mmcsd_write(	MMCSD_Dev *device, char * buffer, 			u32 sector, u32 nr_sector);static int mmcsd_sector_erase(MMCSD_Dev *device, MMCSD_Blks *blks);MMCSD_STATUS mmcsd_ReadBlock(MMCSD_Dev *device,u32 start_addr,u16 nsects, u8 *buff);MMCSD_STATUS mmcsd_ReadSingleBlock(MMCSD_Dev *device,u32 addr,u8 * buff);MMCSD_STATUS mmcsd_DMA_ReadSingleBlock(MMCSD_Dev *device,u32 addr,u8 * buff);int mmcsd_DmaStartTransfer(MMCSD_Dev *device,u8 * buff,u32 counter, u8 mode,u8 is_4_bit);void mmcsd_dma_handler(void);static int mmcsd_ioctl(struct inode *inode,struct file *filp,unsigned command,unsigned long argument);static int mmcsd_write_protect(MMCSD_Dev *device,u32 addr, char is_set);static int mmcsd_passwd_cmd(MMCSD_Dev * device, MMCSD_PWD *pwd);	static int mmcsd_is_writeprotection(MMCSD_Dev *device);void mmcsd_irq_handler(int irq,void * data, struct pt_regs * pt);static int mmcsd_getMBR(MMCSD_Dev * device);static int mmcsd_check_status(MMCSD_Dev *device,u32 *pstate);static void mmcsd_dma_isr(void * arg);static void mmcsd_dma_err_isr(int error_type);MMCSD_STATUS mmcsd_write_blks(MMCSD_Dev *device);MMCSD_STATUS mmcsd_dma_write_blks(MMCSD_Dev *device);void mmcsd_free_buffer(MMCSD_Dev *device);void _mmcsd_16_big_2_little(u8 *buf, u32 size);void _mmcsd_cp_16_little_2_big(u8 *src,u8 *target, int size);void mmcsd_delay(u32 delay);static int handle_pm_event(struct pm_dev *dev, pm_request_t rqst, void *data);///@brief	block device interface function structure, used in blkdev register.static struct block_device_operations mmcsd_bdops = {		open:				mmcsd_open,		release:			mmcsd_release,		ioctl:				mmcsd_ioctl,		revalidate:			mmcsd_revalidate,};///@brief	boot_sector definition used to support format functionstruct boot_sector {    __u8	ignored[3];	/*!< Boot strap short or near jump */    __u8	system_id[8];	/*!< Name - can be used to special case				   partition manager volumes */    __u8	sector_size[2];	/*!< bytes per logical sector */    __u8	cluster_size;	/*!< sectors/cluster */    __u16	reserved;	/*!< reserved sectors */    __u8	fats;		/*!< number of FATs */    __u8	dir_entries[2];	/*!< root directory entries */    __u8	sectors[2];	/*!< number of sectors */    __u8	media;		/*!< media code (unused) */    __u16	fat_length;	/*!< sectors/FAT */    __u16	secs_track;	/*!< sectors per track */    __u16	heads;		/*!< number of heads */    __u32	hidden;		/*!< hidden sectors (unused) */    __u32	total_sect;	/*!< number of sectors (if sectors == 0) */        /*!< The following fields are only used by FAT32 */    __u32	fat32_length;	/*!< sectors/FAT */    __u16	flags;		/*!< bit 8: fat mirroring, low 4: active fat */    __u8	version[2];	/*!< major, minor filesystem version */    __u32	root_cluster;	/*!< first cluster in root directory */    __u16	info_sector;	/*!< filesystem info sector */    __u16	backup_boot;	/*!< backup boot sector */    __u16	reserved2[6];	/*!< Unused */    /*!< fill up to 512 bytes */    __u8	junk[448];};static struct boot_sector gMmcSectorInfor;#define CF_LE_L(v) (((unsigned)(v)>>24) | (((unsigned)(v)>>8)&0xff00) | \               (((unsigned)(v)<<8)&0xff0000) | ((unsigned)(v)<<24))#ifndef MODULEextern int errno;#endifextern unsigned char  gSDWriteProtect;static char g_socket1_info;#define SD_SOCKET_NO_CARD		0x01#define SD_SOCKET_CARD			0x02#ifdef CONFIG_ARCH_MX2ADSstatic char gSDumounted;static devfs_handle_t devfs_handle1 = NULL;	//devfsvoid mmcsd_irq_handler_2(int irq,void * data, struct pt_regs * pt);static void mmcsd_dma_isr_1(void * arg);#endif/*static struct tasklet_struct	mmc_tasklet; #ifdef CONFIG_ARCH_MX2ADSstatic void mmc_tasklet_action(unsigned long data){	u8* tmp;	//mount the disk	printk("1 implement here \n");//	sys_module_mount("/dev/mmc","/mnt/mmcsd","msdos",MS_SYNC,0);	tmp = kmalloc(1024,GFP_KERNEL);	printk("2 implement here \n");	return;}#endif*//** *@brief irq handler for card insert/withdraw * * It is using GPIO portB16 pin to generate card detect interrupt, in the irq handler\n * will revert trigger configuration to detect card withdraw, and then clear interrupt. * * History: *       03-Feb-04       Add Card detection for MX1 silicon 2.0 (Use PB17) **/void mmcsd_socket1_irq_handler(int irq, void *dev_id, struct pt_regs * regs){	u32 status,trigger;#ifdef CONFIG_ARCH_MX1ADS	status = *(u32 *)DBMX1_ISR_B;	trigger = *(u32 *)DBMX1_ICR2_B;	if((status & 0x00020000)==0x00020000) //get PortB17 int        {		if((trigger & 0x0000000C)==0x00000008) //it is positive level		{			g_socket1_info = SD_SOCKET_NO_CARD;			*(u32 *)DBMX1_ICR2_B |= 0x0000000C; //set it to be negative level trigger detect card withdraw			printk("A card is withdrawn from socket1 \n");		}		else if((trigger & 0x0000000C)==0x0000000C) //it is negative level		{			g_socket1_info = SD_SOCKET_CARD;			*(u32 *)DBMX1_ICR2_B &= ~0x00000004;  // config as positive level trigger10			*(u32 *)DBMX1_ICR2_B |= 0x00000008; ;//set it to be positive level trigger detect card insert			printk("A card is inserted in socket1 \n");		}	}#endif#ifdef CONFIG_ARCH_MX2ADS	status = _reg_GPIO_ISR(GPIOD);	trigger = _reg_GPIO_ICR2(GPIOD);	if((status & 0x02000000)==0x02000000) //get PortB16 int	{		if((trigger & 0x000C0000)==0x00080000)//it is positive level now		{			g_socket1_info = SD_SOCKET_NO_CARD;			_reg_GPIO_ICR2(GPIOD) |= 0x000C0000; //set it to be negative level trigger detect card withdraw			_mmcsd_socket1_clear_irq();//			printk("A card is withdrawn from socket1 \n");		}		if((trigger & 0x000C0000)==0x000C0000)//it is negative level now		{			g_socket1_info = SD_SOCKET_CARD;			_reg_GPIO_ICR2(GPIOD) &= ~0x00040000;  // config as positive level trigger10 			_reg_GPIO_ICR2(GPIOD) |= 0x00080000;//set it to be positive level trigger detect card insert			_mmcsd_socket1_clear_irq();//			tasklet_schedule(&mmc_tasklet);//			printk("A card is inserted in socket1 \n");         }	}#endif//	_mmcsd_socket1_clear_irq();	return;}/** *@brief proc_output function * * It will give MMC socket status information using proc file system, it will display two status:nocard/card * **/static int mmcsd_proc_output (char *buf){	char *p;	char *devtype = "?";	char *devright = "w";	unsigned long flags;	save_flags(flags);	cli();	p = buf;//Add to proc to indicate which card in which socket	if(g_socket1_info == SD_SOCKET_CARD)	{		devtype = "mmc";		p += sprintf(p, "%s %s \n",devtype,devright);		/*	if (gSDumounted == 0)		{			sys_module_mount("/dev/mmc","/mnt/mmcsd","msdos",MS_SYNC,0);		 			}*/		}	else if(g_socket1_info == SD_SOCKET_NO_CARD)	{		devtype = "n";		p += sprintf(p, "%s %s \n",devtype,devright);		}	restore_flags(flags);				return p - buf;		}static int mmcsd_read_proc(char *page, char **start, off_t off,                         int count, int *eof, void *data){                int len = mmcsd_proc_output(page);        if (len <= (off+count))        	*eof = 1;        *start = page + off;        len -= off;        if (len>count)         	len = count;        if (len<0)         	len = 0;        return len;}/** *@brief mmc init function * * Function Name: mmcsd_init * * *@return	int   return status *			@li 0  sucess *			@li other failure * * Description: This is the initialization routine for the driver. And this function \n *		will be called while the module being installed. In this function, it will \n *		register blk device,allocate request queue,request mmc irq and mmc socket irq,\n *		register to power management.  * * Modification History: *    **/#ifdef MODULEint init_module(void)#elseint __init mmcsd_init(void)#endif{	int ret,i;	printk("MMC device driver version 0.4.0\n");	TRACE("\n Begin initialize mmcsd module ");	/***************************************************** 	* Register the block driver. 	*****************************************************/#ifdef CONFIG_ARCH_MX2ADS	gSDumounted = 0;#endif		g_mmcsd_major = MMCSD_MAJOR;	ret = devfs_register_blkdev(g_mmcsd_major, "mmc", &mmcsd_bdops);	if (ret < 0)	{        	FAILED(" can't get major %d\n",MMCSD_MAJOR);        	return ret;    }    if(g_mmcsd_major == 0) 	{		g_mmcsd_major = ret; /* dynamic */	}	devfs_handle=devfs_register(NULL,"mmc",DEVFS_FL_DEFAULT,ret,0, 					S_IFBLK | S_IRUGO | S_IWUGO,&mmcsd_bdops,NULL);#ifdef 	CONFIG_ARCH_MX2ADS	devfs_handle1 = devfs_register(NULL, "mmc1",DEVFS_FL_DEFAULT,ret,1, 					S_IFBLK | S_IRUGO | S_IWUGO,&mmcsd_bdops,NULL);#endif    read_ahead[g_mmcsd_major] = MMCSD_READ_AHEAD;/* in sectors */	/******************************************************* 	* Allocate space for each devices.  	*******************************************************/		g_mmcsd_num = MMCSD_DEVICE_NUM;	g_mmcsd_devices = kmalloc((g_mmcsd_num*sizeof(MMCSD_Dev)), GFP_KERNEL);    	if (!g_mmcsd_devices)	{        	goto fail_init;	}    memset(g_mmcsd_devices,0,(g_mmcsd_num * sizeof(MMCSD_Dev)));    for (i=0; i < g_mmcsd_num; i++)	{		spin_lock_init(&(g_mmcsd_devices[i].lock));		spin_unlock(&(g_mmcsd_devices[i].lock));		init_waitqueue_head(&(g_mmcsd_devices[i].select_wait));		sema_init(&(g_mmcsd_devices[i].sema),1);		g_mmcsd_devices[i].dma_channel = 0xFFFFFFFF;    }	g_selected_lock[0].device = NULL;	g_selected_lock[1].device = NULL;	/******************************************************* 	* Allocate request queue for each device. 	*******************************************************/	/*	for(i = 0;i < g_mmcsd_num; i++)	{		blk_init_queue(&(g_mmcsd_devices[i].queue), mmcsd_request_handler);		blk_queue_headactive(&(g_mmcsd_devices[i].queue),0);	}	*/	blk_init_queue(BLK_DEFAULT_QUEUE(g_mmcsd_major),mmcsd_request_handler);	/****************************************************** 	* Regist Interrupt Service Routine  	******************************************************/	ret = request_irq(MMCSD_IRQ, 			  mmcsd_irq_handler,			  SA_INTERRUPT,			  "mmc",			  "mmc");	if(ret)	{		TRACE("request irq error");		goto fail_init;	}#ifdef 	CONFIG_ARCH_MX2ADS	ret = request_irq(MMCSD2_IRQ, 			  mmcsd_irq_handler_2,			  SA_INTERRUPT,			  "mmc1",			  "mmc1");#endif	if(ret)	{		TRACE("request irq error");		goto fail_init;	}	/****************************************************** 	* Regist PM device.  	******************************************************/	/* We register SDHC1 & SDHC2 */	/* and the callback function will be called twice for each pm request */	pm_register(PM_SDHC1_DEV, PM_SYS_UNKNOWN, handle_pm_event);	pm_register(PM_SDHC2_DEV, PM_SYS_UNKNOWN, handle_pm_event);	g_Mmc_apmc = apmc_register(APMC_LEVEL_HIGHEST);//	pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, handle_pm_event);		/******************************************************	 * Pin Configuration	 *	 *****************************************************/	_MMCSD_64M_MMC_PinConfig();    	/******************************************************    	*  LOOP FOR THE MAXIMUM NUMBER OF CARD SLOTS 	******************************************************/    	for ( i = 0 ; i < MMCSD_DEVICE_NUM ; i++ )    	{       		g_mmcsd_devices[i].card_state= MMCSD_NOTREADY;			g_mmcsd_devices[i].card_rca = 1;			//g_mmcsd_devices[i].card_type = MMCSD_NO_CARD;    	}	/*****************************************************	*setting for auto-mount/umount	******************************************************/	g_socket1_info = SD_SOCKET_NO_CARD;	ret = request_irq(MMCSD_SOCKET1_INT,				mmcsd_socket1_irq_handler,				SA_INTERRUPT|SA_SHIRQ,				"mmc",				"mmc");/*#ifdef 	CONFIG_ARCH_MX2ADS

⌨️ 快捷键说明

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