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

📄 mmci.c

📁 dm320平台的LINUX mmc和sd卡驱动代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*	it_mmcsd_clear_response_reg(&cmd); *  linux/drivers/mmc/mmci.c - ARM PrimeCell MMCI PL180/1 driver * *  Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. * * 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. */#include <linux/config.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/init.h>#include <linux/ioport.h>#include <linux/device.h>#include <linux/interrupt.h>#include <linux/delay.h>#include <linux/err.h>#include <linux/highmem.h>#include <linux/mmc/host.h>#include <linux/mmc/protocol.h>#include <linux/mmc/machmmc.h>#include <asm/div64.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/scatterlist.h>#include <asm/hardware/amba.h>#include <linux/mmc/mmc.h>#include <linux/interrupt.h>#include <asm/arch/gios.h>#include <asm/arch/gio.h>#include <asm/arch/irqs.h>#define GIO_SD_CARDDETECT 8#define GIO_SDCARD_WP 35#include "mmci.h"#include "itmmcsd.h"#include "mmc_debug.h"MODULE_LICENSE("INGENIENT");#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);static void clk_put(struct clk *clk);static int clk_enable(struct clk *clk);static int clk_use(struct clk *clk);static unsigned long clk_get_rate(struct clk *clk);static void clk_unuse(struct clk *clk);void enable_interrupt(void);void disable_interrupt(void);void it_mmcsd_get_status(struct mmc_command *);void change_clk25m(void);#endifstatic unsigned short mmc_inw(unsigned long port){	unsigned short retval = inw(port);	return retval;}static unsigned short mmc_outw(unsigned short data, unsigned long port){	outw(data,port);	return 0;}#define udelay(x)#define DRIVER_NAME "SD-MMC"static unsigned int fmax = 515633;static int bCardInitialized = 0;void it_mmcsd_get_status(struct mmc_command *cmd){        cmd->status0 = inw(IO_MMC_STATUS0);	rmb();        cmd->status1 = inw(IO_MMC_STATUS1);	rmb();        cmd->resp[0] = inw(IO_MMC_RESPONSE0);	rmb();        cmd->resp[1] = inw(IO_MMC_RESPONSE1);	rmb();        cmd->resp[2] = inw(IO_MMC_RESPONSE2);	rmb();        cmd->resp[3] = inw(IO_MMC_RESPONSE3);	rmb();        cmd->resp[4] = inw(IO_MMC_RESPONSE4);	rmb();        cmd->resp[5] = inw(IO_MMC_RESPONSE5);	rmb();        cmd->resp[6] = inw(IO_MMC_RESPONSE6);	rmb();        cmd->resp[7] = inw(IO_MMC_RESPONSE7);	rmb();        cmd->cmd_index = inw (IO_MMC_COMMAND_INDEX);	rmb();}void it_mmcsd_clear_response_reg(struct mmc_command *cmd){        outw(0,IO_MMC_RESPONSE0);	wmb();        outw(0,IO_MMC_RESPONSE1);	wmb();        outw(0,IO_MMC_RESPONSE2);	wmb();        outw(0,IO_MMC_RESPONSE3);	wmb();        outw(0,IO_MMC_RESPONSE4);	wmb();        outw(0,IO_MMC_RESPONSE5);	wmb();        outw(0,IO_MMC_RESPONSE6);	wmb();        outw(0,IO_MMC_RESPONSE7);	wmb();        outw(0,IO_MMC_COMMAND_INDEX);	wmb();		cmd->resp[0] = 0;        cmd->resp[1] = 0;        cmd->resp[2] = 0;        cmd->resp[3] = 0;        cmd->resp[4] = 0;        cmd->resp[5] = 0;        cmd->resp[6] = 0;        cmd->resp[7] = 0;}#if  0void it_mmcsd_print_status(struct mmc_command *cmd){		printk("Clk control : %x\n",inw(inw(IO_MMC_MEM_CLK_CONTROL)));	printk("Control Reg : %x\n",inw(IO_MMC_CONTROL));        printk("status0 : %x \n",cmd->status0);        printk("status1 : %x \n",cmd->status1);        printk("resp[0] : %x \n",cmd->resp[0]);        printk("resp[1] : %x \n",cmd->resp[1]);        printk("resp[2] : %x \n",cmd->resp[2]);        printk("resp[3] : %x \n",cmd->resp[3]);        printk("resp[4] : %x \n",cmd->resp[4]);        printk("resp[5] : %x \n",cmd->resp[5]);        printk("resp[6] : %x \n",cmd->resp[6]);        printk("resp[7] : %x \n",cmd->resp[7]);        printk("cmd_index : %x \n",cmd->cmd_index);}#elsevoid it_mmcsd_print_status(struct mmc_command *cmd){        printk("\n status0 : %x \t",cmd->status0);	printk("resp[6] : %x\t",cmd->resp[6]);        printk("resp[7] : %x\t",cmd->resp[7]);        printk("cmd_index : %x\t",cmd->cmd_index);}#endifvoid enable_interrupt(){		volatile u16 reg = 0;	//Enable interrupt	/* bring the sd/mmc controller to idle state */	reg = inw(IO_MMC_CONTROL);        outw(reg | 0x03,IO_MMC_CONTROL);	outw((inw(IO_INTC_EINT1) & 0xFFFC),IO_INTC_EINT1);        outw(0x0FF,IO_MMC_INT_ENABLE);        outw((inw(IO_INTC_EINT1) | 0x3),IO_INTC_EINT1);        /* release idle state */        reg = inw(IO_MMC_CONTROL);        outw(reg & 0xFFFC,IO_MMC_CONTROL);        reg = inw(IO_MMC_CONTROL);}void disable_interrupt(){	volatile u16 reg = 0;        //Disable interrupt        /* bring the sd/mmc controller to idle state */        reg = inw(IO_MMC_CONTROL);	rmb();        outw(reg | 0x03,IO_MMC_CONTROL);	wmb();        outw((inw(IO_INTC_EINT1) & 0xFFFC),IO_INTC_EINT1);	wmb();        outw(0x0000,IO_MMC_INT_ENABLE);	wmb();        outw((inw(IO_INTC_EINT1) | 0x3),IO_INTC_EINT1);	wmb();        /* release idle state */	reg = inw(IO_MMC_CONTROL);	rmb();        outw(reg & 0xFFFC,IO_MMC_CONTROL);	wmb();        reg = inw(IO_MMC_CONTROL);	rmb();}void change_clk25m(){		volatile u16 reg = 0;					//mmc_debug_msg ("%s\n",__FUNCTION__);		        /* bring the sd/mmc controller to idle state */		reg = inw (IO_MMC_CONTROL);		rmb();		//mmc_debug_msg ("reg : %x\n",reg);	        	outw(reg | 0x03,IO_MMC_CONTROL);		wmb();            	/*diable clock*/            	reg = inw(IO_MMC_MEM_CLK_CONTROL);		rmb();                outw(reg & 0xFEFF, IO_MMC_MEM_CLK_CONTROL);		wmb();                reg = inw(IO_MMC_MEM_CLK_CONTROL);                outw(inw(IO_CLK_INV) | 0x1,IO_CLK_INV);		wmb();	                /* set function clock */                outw(((inw(IO_CLK_DIV3) & 0xFF00 )| 0x01) ,IO_CLK_DIV3);		wmb();                /* set mmc clock to ~ 25 MHz */                 outw(((inw(IO_MMC_MEM_CLK_CONTROL) & 0xFF00) | 0x0),IO_MMC_MEM_CLK_CONTROL);		wmb();                		/* release idle state */                reg = inw(IO_MMC_CONTROL);		rmb();                outw(reg & 0xFFFC,IO_MMC_CONTROL);		wmb();                /* enable clock */                reg = inw(IO_MMC_MEM_CLK_CONTROL);		rmb();                outw(reg | 0x0100, IO_MMC_MEM_CLK_CONTROL);		wmb();}static void mmci_start_data(struct mmci_host *host, struct mmc_data *data){	unsigned int datactrl, timeout, irqmask;	unsigned long long clks;	host->data = data;	host->size = data->blocks << data->blksz_bits;	host->data_xfered = 0;	mmci_init_sg(host, data);			mmc_debug_msg ("%s %d\n",__FUNCTION__,__LINE__);	clks = (unsigned long long)data->timeout_ns * host->cclk;	do_div(clks, 1000000000UL);	mmc_debug_msg ("%s %d\n",__FUNCTION__,__LINE__);	timeout = data->timeout_clks + (unsigned int)clks;	mmc_debug_msg ("host->size :  %x\n",host->size);	mmc_debug_msg ("data->blocks : %x\n",data->blocks);	mmc_debug_msg ("data->blksz_bits : %x\n",data->blksz_bits);	mmc_outw(data->blksz_bits,IO_MMC_BLOCK_LENGTH);        mmc_outw(data->blocks,IO_MMC_NR_BLOCKS);	datactrl = MCI_DPSM_ENABLE | data->blksz_bits << 4;	if (data->flags & MMC_DATA_READ) {		datactrl |= MCI_DPSM_DIRECTION;		irqmask = MCI_RXFIFOHALFFULLMASK;	} else {		/*		 * We don't actually need to include "FIFO empty" here		 * since its implicit in "FIFO half empty".		 */		irqmask = MCI_TXFIFOHALFEMPTYMASK;	}}void mmc_wait_for_op_cond(struct mmc_command *cmd){u32 marg;u16 cmd1;u32 oper_volt = 0x4;do    {        marg = 0x0;        cmd1 = 55 | 0x0200 | 0x0080; //| 0x4000 | 0x0800;        mmc_outw(marg & 0xFFFF,IO_MMC_ARG_LOW);        mmc_outw((marg >> 16),IO_MMC_ARG_HI);        mmc_outw(cmd1,IO_MMC_COMMAND);        it_mmcsd_get_status(cmd);        it_mmcsd_clear_response_reg(cmd); //clear the response register in the register        //it_mmcsd_print_status(cmd);        marg = (oper_volt << 14 );        cmd1 = 41 | 0x0600 | 0x0080;//| 0x4000;        mmc_outw(marg & 0xFFFF,IO_MMC_ARG_LOW);        mmc_outw((marg >> 16),IO_MMC_ARG_HI);        mmc_outw(cmd1,IO_MMC_COMMAND);        it_mmcsd_get_status(cmd);        it_mmcsd_clear_response_reg(cmd); //clear the response register in the register        //it_mmcsd_print_status(cmd);        }while (!(cmd->resp[7] & 0x8000));}EXPORT_SYMBOL(mmc_wait_for_op_cond);static voidmmci_request_end(struct mmci_host *host, struct mmc_request *mrq){	host->mrq = NULL;	host->cmd = NULL;		if (mrq->data){		mrq->data->bytes_xfered = host->data_xfered;	}	/*	 * Need to drop the host lock here; mmc_request_done may call	 * back into the driver...	 */	spin_unlock(&host->lock);	mmc_request_done(host->mmc, mrq);	spin_lock(&host->lock);}static void mmci_stop_data(struct mmci_host *host){	host->data = NULL;}static voidmmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c){	u32 marg;	u16 cmd1;	mmc_debug_msg_command ("\nopcode : %d\targ : %x\n",(cmd->opcode & 0x3F),cmd->arg);	it_mmcsd_clear_response_reg(cmd);	host->cmd = cmd;        marg = cmd->arg;         cmd1 = cmd->opcode | cmd->flags | 0x0000;	        outw(marg & 0xFFFF,IO_MMC_ARG_LOW);        outw((marg >> 16),IO_MMC_ARG_HI);        outw(cmd1,IO_MMC_COMMAND);	wmb();	bCardInitialized = 1;}static voidmmci_data_irq(struct mmci_host *host, struct mmc_data *data,	      unsigned int status){	if (status & MMC_INT_DATA_DONE) {		host->data_xfered += 1 << data->blksz_bits;	}	if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) {		if (status & MCI_DATACRCFAIL)			data->error = MMC_ERR_BADCRC;		else if (status & MCI_DATATIMEOUT)			data->error = MMC_ERR_TIMEOUT;		else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN))			data->error = MMC_ERR_FIFO;		status |= MCI_DATAEND;	}	if (status & MCI_DATAEND) {		mmci_stop_data(host);		if (!data->stop) {			mmci_request_end(host, data->mrq);		} else {			mmci_start_command(host, data->stop, 0);		}	}}static voidmmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,	     unsigned int status){	host->cmd = NULL;		if (status & MMC_INT_RSP_TIMEOUT) {		cmd->error = MMC_ERR_TIMEOUT;		mmc_debug_msg ("Card has not responded \n");	} else if (status & MMC_INT_RSP_CRC_ERROR){		mmc_debug_msg("CRC ERROR\n");		cmd->error = MMC_ERR_BADCRC;	}	if (!cmd->data || cmd->error != MMC_ERR_NONE) {		mmci_request_end(host, cmd->mrq);	} else if ((cmd->data->flags & MMC_DATA_READ)) {		mmc_debug_msg("Data transfer\n");		mmci_start_data(host, cmd->data);		host->mrq = NULL;	        host->cmd = NULL;	}}/* * Handle completion of command and data transfers. */static volatile int in_interrupt = 1;static irqreturn_t mmci_irq(int irq, void *dev_id, struct pt_regs *regs){	struct mmci_host *host = dev_id;	int ret = 1;	struct mmc_command *cmd,data_cmd;	struct mmc_data *data;	spin_lock(&host->lock);	//local_irq_disable();        if (in_interrupt){                mmc_debug_msg(" done -\t\n");                in_interrupt = 0;                }	cmd = host->cmd;	if (cmd){	mmc_debug_msg ("Command is not NULL\n");		if((unsigned long ) cmd == 0x6b6b6b6b)	{		printk("\n Its too early to get an interrupt \n");		it_mmcsd_get_status(&data_cmd);		it_mmcsd_print_status(&data_cmd);		dump_stack();		panic("Early Interrupt\n");				spin_unlock(&host->lock);		return IRQ_HANDLED;	}	it_mmcsd_get_status(cmd);	//it_mmcsd_print_status(cmd);	}	else{	mmc_debug_msg("Command is NULL\n");	it_mmcsd_get_status(&data_cmd);//	it_mmcsd_print_status(&data_cmd);	cmd = &data_cmd;	}	data = host->data;        if ((cmd->status0 & (MMC_INT_READ_CRC_ERROR|MMC_INT_WRITE_CRC_ERROR|MMC_INT_READ_TIMEOUT|MMC_INT_DATA_DONE)) |		(cmd->status1 & (MMC_INT_DAT_RCV_RDY_S1|MMC_INT_DAT_TRX_RDY_S1))){		        mmci_data_irq(host,data,(cmd->status0|cmd->status1 << 16));		}	if ((cmd->status0 & (MMC_INT_RSP_CRC_ERROR | MMC_INT_RSP_TIMEOUT | MMC_INT_RSP_DONE))){                        mmci_cmd_irq(host, cmd, cmd->status0);	}        in_interrupt = 1;	ret = 1; 	//local_irq_enable();	spin_unlock(&host->lock);	return IRQ_RETVAL(ret);}static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq){	struct mmci_host *host = mmc_priv(mmc);		WARN_ON(host->mrq != NULL);	spin_lock_irq(&host->lock);	host->mrq = mrq;		if (mrq->data && mrq->data->flags & MMC_DATA_READ){		mmci_start_data(host, mrq->data);	}	mmci_start_command(host, mrq->cmd, 0);	spin_unlock_irq(&host->lock);}static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios){		volatile u16 reg = 0;                /* bring the sd/mmc controller to idle state */                reg = inw (IO_MMC_CONTROL);                rmb();                outw(reg | 0x03,IO_MMC_CONTROL);                wmb();				if (mmc->ios.bus_width == MMC_BUS_WIDTH_4){		/*changing to 4-data line mode*/		outw(reg | (1 << 2),IO_MMC_CONTROL); 		wmb();			}		else{		/*changing to 4-data line mode*/                outw(reg & (~(1 << 2)),IO_MMC_CONTROL);                wmb();		}		                /* release idle state */                reg = inw(IO_MMC_CONTROL);                rmb();                outw(reg & 0xFFFC,IO_MMC_CONTROL);                wmb();}int write_to_card(struct mmc_host *mmc,struct mmc_request *mrq){	u32 current_add;	u16 no_of_blks;	u32 marg;        u16 cmd1,reg;	int write_count;	volatile unsigned short reg1 = 0;#ifndef DMA_TRANSFER	short write_data;#endif	struct mmc_command cmd;	struct mmci_host *host = mmc_priv(mmc);	spin_lock(&host->lock);	disable_interrupt();	local_irq_disable();	/* disable clock */        reg = mmc_inw(IO_MMC_MEM_CLK_CONTROL);	        mmc_outw(reg & 0xFEFF, IO_MMC_MEM_CLK_CONTROL);	mrq->cmd->error = 0;        mrq->cmd->mrq = mrq;        if (mrq->data) {                mrq->cmd->data = mrq->data;

⌨️ 快捷键说明

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