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

📄 mmci.c

📁 dm320平台的LINUX mmc和sd卡驱动代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* enable clock */        reg = mmc_inw(IO_MMC_MEM_CLK_CONTROL);        outw(reg | 0x0100, IO_MMC_MEM_CLK_CONTROL);	local_irq_enable();	enable_interrupt();        spin_unlock(&host->lock);	host->data = NULL;	return 0;}int src_read(struct mmc_host *mmc,struct mmc_request *mrq,unsigned int *relative,char* scr_reg){	u32 marg;        u16 cmd1,reg;	int read_count;	struct mmc_command cmd;	struct mmci_host *host = mmc_priv(mmc);	short temp_data;	spin_lock(&host->lock);	disable_interrupt();	local_irq_disable();	memset(scr_reg,0,8*sizeof(char));		/* disable clock */        reg = inw(IO_MMC_MEM_CLK_CONTROL);		rmb();        outw(reg & 0xFEFF, IO_MMC_MEM_CLK_CONTROL);	wmb();       #if 0		printk ("%s %d\n",__FUNCTION__,__LINE__);	mrq->cmd->error = 0;        mrq->cmd->mrq = mrq;        if (mrq->data) {                mrq->cmd->data = mrq->data;                mrq->data->error = 0;                mrq->data->mrq = mrq;                if (mrq->stop) {                        mrq->data->stop = mrq->stop;                        mrq->stop->error = 0;                        mrq->stop->mrq = mrq;                }        }	it_mmcsd_get_status(&cmd);	it_mmcsd_clear_response_reg(&cmd);	current_add = mrq->cmd->arg;        no_of_blks = mrq->data->blocks;// * host->sg_len; //To read more than segment#endif	do{        char *buffer = NULL;	short *buffer_short = NULL;	int count = 0;	buffer = scr_reg;	it_mmcsd_clear_response_reg(&cmd);	it_mmcsd_get_status(&cmd);	//it_mmcsd_print_status(&cmd);	        outw(1,IO_MMC_NR_BLOCKS);	outw(0x200,IO_MMC_BLOCK_LENGTH);	buffer_short = (short*)buffer;        marg = 0x200;        cmd1 = 51 | 0x0200 | 0x2000 | 0x0080 | 0x0000 | 0x0000;        outw(marg & 0xFFFF,IO_MMC_ARG_LOW);        outw((marg >> 16),IO_MMC_ARG_HI);        outw(cmd1,IO_MMC_COMMAND);#if 1 	do        {                it_mmcsd_get_status(&cmd);		//mdelay(10);	}while( !((cmd.status0 & 0x4)==4));//checking for busy state and response of the command#endif	//it_mmcsd_print_status(&cmd);		        read_count = 0;        do{		it_mmcsd_get_status(&cmd);		//it_mmcsd_print_status(&cmd);	                reg = cmd.status0;                if (reg & 0x0040)                {                        mmc_debug_msg ("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<Read CRC error\n");			mmc_debug_msg ("STATUS0 :%x\tSTATUS1 :%x\n",cmd.status0,cmd.status1);                        break;                }                if ((cmd.status0 & 0x400))                {			temp_data = 0;			temp_data = inw (IO_MMC_RX_DATA);			mmc_debug_msg_rw ("%x\t",temp_data);			if (read_count < 4){						*buffer = (temp_data >> 8) & 0xFF;				buffer = buffer + 1;				*buffer = temp_data & 0xFF;					buffer = buffer + 1;			}			read_count++;			if (read_count > 0x200)				break;                }		else	                        if (cmd.status0 & 0x10){                        	printk("Command Time OUT");                                break;		}	} while (!(reg &0x0001));        do{		if (count ++ > 100)			break;		it_mmcsd_get_status(&cmd);	}while((cmd.status1 & 0x1));	buffer_short = NULL ;	break;	}while(1);	/* enable clock */	        reg = mmc_inw(IO_MMC_MEM_CLK_CONTROL);        outw(reg | 0x0100, IO_MMC_MEM_CLK_CONTROL);	local_irq_enable();	enable_interrupt();        spin_unlock(&host->lock);	return 0;}static volatile int plug_count = 0;static int dat3stat_new = 0;static int dat3stat_old = 0;static int dat3stat_count = 0;static void host_configuration(void){		short reg = 0;		/*Erase past settings*/	outw(0x0,IO_MMC_CONTROL);	outw(0x0,IO_MMC_MEM_CLK_CONTROL);//	outw(0x0,IO_MEM_STICK_MODE);//MS mode		/*HOST CONFIGURATION STARTS */	/* bring the controller to reset state */        reg = inw(IO_MMC_CONTROL);        outw(reg | 0x03,IO_MMC_CONTROL);	wmb();        reg = inw(IO_MMC_CONTROL);	rmb();	/* configure mmc controller */        reg = inw(IO_MMC_CONTROL);        outw(reg | 0x0200 | 0x0400 | 0x0000,IO_MMC_CONTROL);	wmb();        reg = inw(IO_MMC_CONTROL);	rmb();	/*Response timeout register */	outw(255,IO_MMC_RESPONSE_TIMEOUT);	wmb();	/*Data timeout register*/	reg = inw (IO_MMC_RESPONSE_TIMEOUT);	rmb();	outw(reg | 0x1F00,IO_MMC_RESPONSE_TIMEOUT);        wmb();	outw(0xFFFF,IO_MMC_READ_TIMEOUT);	wmb();	/* disable clock */        reg = inw(IO_MMC_MEM_CLK_CONTROL);        outw(reg & 0xFEFF, IO_MMC_MEM_CLK_CONTROL);		wmb();        reg = inw(IO_MMC_MEM_CLK_CONTROL);	rmb();	/* set clock */        outw(inw(IO_CLK_INV) | 0x1,IO_CLK_INV);	wmb();        /* set function clock */        outw(( (mmc_inw(IO_CLK_DIV3) & 0xFF00) | (0x01)) ,IO_CLK_DIV3);	wmb();        /* set mmc clock to ~ 400 kHz */ /* 338 KHZ */        outw((0),IO_MMC_MEM_CLK_CONTROL);	wmb();        outw(((mmc_inw(IO_MMC_MEM_CLK_CONTROL) & 0xFF00) | (0x40)),IO_MMC_MEM_CLK_CONTROL);	wmb();        outw((0x40),IO_MMC_MEM_CLK_CONTROL);	wmb();	/* release controller reset state */        reg = inw(IO_MMC_CONTROL);	rmb();        outw(reg & 0xFFFC,IO_MMC_CONTROL);	wmb();        reg = inw(IO_MMC_CONTROL);	rmb();		/* enable clock */        reg = inw(IO_MMC_MEM_CLK_CONTROL);	rmb();        outw(reg | 0x0100, IO_MMC_MEM_CLK_CONTROL);	wmb();        reg = inw(IO_MMC_MEM_CLK_CONTROL);	rmb();	/*HOST CONFIGURATION ENDS*/}static void mmci_check_status(unsigned long data){	struct mmci_host *host = (struct mmci_host *)data;	u16 status;		status = gio_get_bitset(GIO_SD_CARDDETECT) & !(inw(IO_GIO_CARD_ST));	rmb();	if (status ^ host->oldstat){		host_configuration();		mmc_detect_change(host->mmc, 0);		printk("card state changed\n");		goto detect_called;	}	if (inw (IO_MMC_STATUS1) & 0x10)		dat3stat_new = 1;		else 		dat3stat_new = 0;	if ((dat3stat_old == 1) && (dat3stat_new == 1)){		if ((dat3stat_count == 0) && (plug_count == 0)){			host_configuration();			mmc_detect_change(host->mmc, 0);			dat3stat_count = 1;		}			}detect_called:	host->oldstat = status;	dat3stat_old = dat3stat_new;	mod_timer(&host->timer, jiffies + HZ);	outw (0x0000,IO_GIO_CARD_SET);	wmb();	plug_count = 0;		}static int get_write_protect_status(struct mmc_host *mmc){	mmc_debug_msg("Write protect status : %x\n",gio_get_bitset(GIO_SDCARD_WP));	return gio_get_bitset(GIO_SDCARD_WP);}	static struct mmc_host_ops mmci_ops = {        .request        = mmci_request,        .set_ios        = mmci_set_ios,	.get_ro		= get_write_protect_status,};static int mmci_probe(struct device *dev){	struct mmc_platform_data *plat = dev->platform_data;	struct mmci_host *host = NULL;	struct mmc_host *mmc = NULL;	int ret;	volatile u16 reg;	#ifdef DMA_TRANSFER	mmc_debug_msg("DMA TRANSFER ENABLED\n");#endif		mmc = mmc_alloc_host(sizeof(struct mmci_host), dev);	bCardInitialized = 0;		if (!mmc) {		ret = -ENOMEM;		mmc_debug_msg(" mmc_alloc_host failed \n");		goto rel_regions;	}	host = mmc_priv(mmc);	host->cmd = NULL;	host->clk = clk_get(dev, "MCLK");	mmc->readdata = read_from_card;//used in calling the read system call	mmc->writedata = write_to_card;//used in calling the write system call	mmc->src_data = src_read;//used in calling src read function	mmc->enable_interrupt = enable_interrupt;	mmc->disable_interrupt = disable_interrupt;	mmc->change_clk25m = change_clk25m;	host_configuration();//Host controller configuration			ret = clk_use(host->clk);	if (ret)		goto clk_free;	ret = clk_enable(host->clk);	if (ret)		goto clk_unuse;	host->plat = plat;	host->mclk = clk_get_rate(host->clk);	host->mmc = mmc;	mmc->ops = &mmci_ops;	mmc->ocr_avail = 1 << 16;//Has to be done by platform data	/*	 * We can do SGIO	 */	mmc->max_hw_segs = 16;	mmc->max_phys_segs = NR_SG;	/*	 * Since we only have a 16-bit data length register, we must	 * ensure that we don't exceed 2^16-1 bytes in a single request.	 * Choose 64 (512-byte) sectors as the limit.	 */	mmc->max_sectors = 64;	/*	 * Set the maximum segment size.  Since we aren't doing DMA	 * (yet) we are only limited by the data length register.	 */	mmc->max_seg_size = mmc->max_sectors << 9;				spin_lock_init(&host->lock);	reg = inw(IO_INTC_EINT1);	rmb();        reg &= ~(3 << 0);        outw(reg,IO_INTC_EINT1);	wmb();	//ret = request_irq(IRQ_SD_MMC, mmci_irq, SA_SHIRQ, DRIVER_NAME " (cmd)", host);	//ret = request_irq(IRQ_SD_MMC, mmci_irq, SA_INTERRUPT, DRIVER_NAME " (cmd)", host);	//ret = request_irq(IRQ_SD_MMC, mmci_irq,SA_PROBE, DRIVER_NAME " (cmd)", host);	ret = request_irq(IRQ_SD_MMC, mmci_irq,0, DRIVER_NAME " (cmd)", host);	if (ret){			printk ("Interrupt %d may be busy\n",IRQ_SD_MMC);		free_irq(IRQ_SD_MMC,host);	}	outw((mmc_inw(IO_INTC_EINT1) & 0xFFFC),IO_INTC_EINT1);	wmb();	outw(0x114,IO_MMC_INT_ENABLE);	wmb();		outw((mmc_inw(IO_INTC_EINT1) | 0x3),IO_INTC_EINT1);	wmb();		dev_set_drvdata(dev,mmc);	mmc_add_host(mmc);	init_timer(&host->timer);	host->timer.data = (unsigned long)host;	host->timer.function = mmci_check_status;	host->timer.expires = jiffies + HZ;	add_timer(&host->timer);	mmc_debug_msg ("Leaving mmci probe\n");	return 0; clk_unuse:	clk_unuse(host->clk); clk_free:	clk_put(host->clk); rel_regions:	return ret;}static int mmci_remove(struct device *dev){	struct mmc_host *mmc = dev_get_drvdata(dev);	mmc_debug_msg ("entering %s\n",__FUNCTION__);	plug_count = 0;	dat3stat_new = 0;	dev_set_drvdata(dev, NULL);	if (mmc) {		struct mmci_host *host = mmc_priv(mmc);		del_timer_sync(&host->timer);		mmc_remove_host(mmc);		mmc_free_host(mmc);				free_irq(IRQ_SD_MMC,mmc_priv(mmc));	}		mmc_debug_msg ("leaving %s\n",__FUNCTION__);		return 0;}#define mmci_suspend	NULL#define mmci_resume	NULLstatic struct device_driver mmci_driver = { 	.name		= DRIVER_NAME,	.bus            = &platform_bus_type,	.probe		= mmci_probe,	.remove		= mmci_remove,	.suspend	= mmci_suspend,	.resume		= mmci_resume,};static irqreturn_t it_mmcsd_detect_interrupt(int flags, void * data, struct pt_regs * regs){        int inserted = 0;	if (!plug_count)	{        	inserted = gio_get_bitset(GIO_SD_CARDDETECT);        	outw (0x0003,IO_GIO_CARD_SET);  //inversion & card detect enable		wmb();        	if (inserted & !inw(IO_GIO_CARD_ST)){                	mmc_debug_msg("Card pluged out\t\n");		}        	else{               	 	mmc_debug_msg("Card pluged in\t\n");		}		plug_count += 1;        	return IRQ_HANDLED;	}	else{			if (plug_count < 5){ //5 is debounce count			plug_count += 1;			return IRQ_HANDLED;		}		else{	   		plug_count = 0;	   		return IRQ_HANDLED;		}	}}static void init_sd_mmc(void){	int status;	status = request_gio(GIO_SD_CARDDETECT);        if (status){                mmc_debug_msg("\tUnable to register gio1 %d\n",GIO_SD_CARDDETECT);                }        gio_enable_irq(GIO_SD_CARDDETECT,GIO_ANY_EDGE);		mmc_debug_msg ("IRQ_GIO8 : %d\t\n",IRQ_GIO8);	status = request_irq(IRQ_GIO8 /* GIO_SD_CARDDETECT */,it_mmcsd_detect_interrupt,0,"mmc/sd DMA controller",NULL);        if (status){                mmc_debug_msg("\tUnable to register irq \t\n");        }	status = request_gio(GIO_SDCARD_WP);	if (status){                mmc_debug_msg("\tUnable to register gio2 %d\n",GIO_SDCARD_WP);                }	gio_set_dir(GIO_SDCARD_WP,bit_hi);}static int __init mmci_init(void){	int val = 0;	val = driver_register(&mmci_driver);	init_sd_mmc();	return val;}static void __exit mmci_exit(void){	unsigned short reg;	plug_count = 0;	dat3stat_new = 0;	disable_interrupt();        reg = inw(IO_MMC_MEM_CLK_CONTROL);        rmb();        outw(reg & 0xFEFF, IO_MMC_MEM_CLK_CONTROL);        wmb();	unrequest_gio(GIO_SD_CARDDETECT);	free_irq(IRQ_GIO8,NULL);	unrequest_gio(GIO_SDCARD_WP);	driver_unregister(&mmci_driver);}module_init(mmci_init);module_exit(mmci_exit);module_param(fmax, uint, 0444);#if defined(CONFIG_ARCH_NTDEV_DM320) || defined(CONFIG_ARCH_NTR3_DM320) || defined(CONFIG_ARCH_ITDM320_20)static struct clk *clk_get(struct device *dev, const char *id){	//mmc_debug_msg(" %s called \n",__FUNCTION__);}static void clk_put(struct clk *clk){	//mmc_debug_msg(" %s called \n",__FUNCTION__);}static int clk_enable(struct clk *clk){	//mmc_debug_msg(" %s called \n",__FUNCTION__);	return 0;}static int clk_use(struct clk *clk){	//mmc_debug_msg(" %s called \n",__FUNCTION__);	return 0;}static unsigned long clk_get_rate(struct clk *clk){	//mmc_debug_msg(" %s called \n",__FUNCTION__);        //return clk->rate;	return 0;}static void clk_unuse(struct clk *clk){	mmc_debug_msg(" %s called \n",__FUNCTION__);}#endifMODULE_DESCRIPTION("ARM PrimeCell PL180/181 Multimedia Card Interface driver");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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