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

📄 jademmc1.c.svn-base

📁 linux2.6.18下支持sd2.0的驱动程序源码,支持最大32G的SD卡
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
/* *  linux/drivers/mmc/jademmc1.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 <asm/div64.h>#include <asm/io.h>#include <asm/scatterlist.h>#include <asm/sizes.h>#include <asm/hardware/amba.h>#include <asm/hardware/clock.h>#include <asm/mach/mmc.h>#include <asm/memory.h>#include <asm/dma.h>#include <asm/mach/dma.h>#include <linux/completion.h>#include <asm/arch/platform.h>#include <linux/errno.h>#include <asm/arch/mmci.h>#include "mmci.h"#define DRIVER_NAME "MMCI-JADE"#define CONFIG_MMC_DEBUG #ifdef CONFIG_MMC_DEBUG#define DBG(host,fmt,args...)	\	pr_debug("%s: %s: " fmt, mmc_hostname(host->mmc), __func__ , args)#else#define DBG(host,fmt,args...)	do { } while (0)#endif#ifdef CONFIG_ARCH_X900  #define JADE_MMCI1_BASE X900_MMCI1_BASE  #define 	PINCFG				0x38#else  #define JADE_MMCI1_BASE Z228_MMCI1_BASE  #define 	PINCFG				 0x010c#endif int ch_sd;static struct ver_dma_param pa_sd;struct jademmci_host {	void __iomem		*base;	struct mmc_request	*mrq;	struct mmc_command	*cmd;	struct mmc_data		*data;	struct mmc_host		*mmc;	struct clk		*clk;	unsigned int		data_xfered;	spinlock_t		lock;	unsigned int		mclk;	unsigned int		cclk;	u32			pwr;	struct jademmc_platform_data *plat;	struct timer_list	timer;	unsigned int		oldstat;	unsigned int		sg_len;	/* pio stuff */	struct scatterlist	*sg_ptr;	unsigned int		sg_off;	unsigned int		size;};extern void ver_enable_dmac(void);#ifdef CONFIG_JADEMMC_PNP		        #define PMC_BASE_ADDR 0x20039000        #define PMC_EXTINTRMIS  0x48        #define PMC_EXTINTRRIS  0x4c        #define PMC_EXTINTRCLR  0x50        #define PMC_EXTINTRMASK 0x54        #define PMC_EXTINTRCFG  0x58#endifstatic int sd_request_dma(void){    	#ifdef CONFIG_ARCH_X900 		ch_sd = ver_request_dma(0, "dma_sd",24,24);	#else			ch_sd = ver_request_dma(0, "dma_sd", 0x0f, 0x0f);	#endif	if(ch_sd < 0){			printk("<1> alloc sd dma error\n");		return ch_sd;		}else{			printk("<1> sd dma chan: %d\n", ch_sd);		}	memset(&pa_sd, 0, sizeof (pa_sd));	return 0;} voidmmci_request_end(struct jademmci_host *host, struct mmc_request *mrq){	writel(0, host->base + MMCICOMMAND);	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);} void mmci_stop_data(struct jademmci_host *host){	writel(0, host->base + MMCIDATACTRL);	writel(0, host->base + MMCIMASK1);	host->data = NULL;}voidmmci_start_command(struct jademmci_host *host, struct mmc_command *cmd, u32 c){	void __iomem *base = host->base;		DBG(host, "op %02x arg %08x flags %08x\n",	    cmd->opcode, cmd->arg, cmd->flags);		if (readl(base + MMCICOMMAND) & MCI_CPSM_ENABLE) {		writel(0, base + MMCICOMMAND);		udelay(1);	}	c |= cmd->opcode | MCI_CPSM_ENABLE;	switch (cmd->flags & MMC_RSP_MASK) {	case MMC_RSP_NONE:	default:		break;	case MMC_RSP_LONG:		c |= MCI_CPSM_LONGRSP;	case MMC_RSP_SHORT:		c |= MCI_CPSM_RESPONSE;		break;	}	if (/*interrupt*/0)		c |= MCI_CPSM_INTERRUPT;	host->cmd = cmd;	writel(cmd->arg, base + MMCIARGUMENT);	writel(c, base + MMCICOMMAND);}	static void mmci_data_end(struct jademmci_host *host)	{		struct mmc_data *data;			void __iomem *base;			base=host->base;			data =host->data;			mmci_stop_data(host);		if (data )		{			if (!data->stop) {				mmci_request_end(host, data->mrq);			} else {				mmci_start_command(host, data->stop, 0);			}	}		writel(0,base + MMCIMASK1);		writel(readl(base + MMCIMASK0) | MCI_DATAENDMASK, base + MMCIMASK0);			}static void finish_dma_transfer(struct jademmci_host *host){	struct mmc_data *data;	void __iomem *base = host->base;	unsigned int tmp;		data =host->data;		host->data = NULL;	if (data )	{		if (!data->stop)			mmci_request_end(host, data->mrq);	 	else 			mmci_start_command(host, data->stop, 0);			writel(0, base + MMCIMASK1);	if  (data->flags & MMC_DATA_READ )		writel(readl(base + MMCIMASK0) | MCI_DATACRCFAIL| MCI_DATAENDMASK| MCI_RXOVERRUN , base + MMCIMASK0);	else{		 tmp=readl(base+MMCISTATUS);		writel(readl(base + MMCIMASK0) | MCI_DATACRCFAIL| MCI_DATAENDMASK| MCI_TXUNDERRUN , base + MMCIMASK0);		}	}}static void sd_dma_done(int a, int b, struct jademmci_host *host){	struct mmc_data *data;		unsigned int tmp;	unsigned int timeout=0xffffffff;	if(b)		printk("<1>sd dma error:%x, %x\n", a, b);		host->data_xfered=host->size;	data = host->data;	if (!(data->flags & MMC_DATA_READ))		{			do			{				tmp = readl(host->base +MMCISTATUS);				tmp &= 1<<20;				if (!tmp) break; 				timeout--;			}while (timeout);			udelay(3);		}			finish_dma_transfer(host);}int sd_start_dma(int read, unsigned int sg_len , u32 size,struct scatterlist *sg, struct jademmci_host *host){			pa_sd.SWidth = DMAC_TSIZE_WORD;	pa_sd.DWidth = DMAC_TSIZE_WORD;	if(read){            		 pa_sd.SBsize = 0x2;         	 pa_sd.DBsize = 0x2;		pa_sd.FlowCntrl =FLOW_PER_MEM_DMAC;         	pa_sd.SIncr = 0;         	pa_sd.DIncr = 1;	 	pa_sd.lli_src = 1;	 }else{         	pa_sd.SBsize = 0x2;         	pa_sd.DBsize = 0x2;      		pa_sd.FlowCntrl = FLOW_MEM_PER_DMAC;         	pa_sd.SIncr = 1;         	pa_sd.DIncr = 0;	 	pa_sd.lli_src = 0;	}	if (ver_set_dma(ch_sd, &pa_sd) != 0) {		printk("<1>sd read:set dma fail:\n");		return -1;	}   		pa_sd.sg_len = sg_len;	pa_sd.tsize = size;	pa_sd.hwbuf = ((unsigned int)(JADE_MMCI1_BASE+0x80)); 		pa_sd.sg = sg;	pa_sd.trans_done = sd_dma_done;	pa_sd.done_data = host;	if (ver_start_dma(ch_sd, &pa_sd) != 0) {		printk("<1>sd:start dma fail:%d\n", size);		return -1;	}				return 0;}static unsigned int fmax = 515633;static void mmci_enable_dma(struct jademmci_host *host,struct mmc_data *data ){	unsigned int sg_len,read;	void __iomem *base;		sg_len=host->sg_len;		read = (data->flags & MMC_DATA_READ) ? 1 :0; 		base = host->base;			sd_start_dma(read,sg_len,host->size,host->sg_ptr,host);}static void mmci_start_data(struct jademmci_host *host, struct mmc_data *data){	unsigned int datactrl=0, timeout;	unsigned long long clks;	void __iomem *base = host->base;		DBG(host, "blksz %04x blks %04x flags %08x\n",	    1 << data->blksz_bits, data->blocks, data->flags);	host->data = data;	host->size = data->blocks << data->blksz_bits;	host->data_xfered = 0;	mmci_init_sg(host, data);	clks = (unsigned long long)data->timeout_ns * host->cclk;	do_div(clks, 1000000000UL);	timeout = data->timeout_clks + (unsigned int)clks;	timeout=0xffffffff;	writel(timeout, base + MMCIDATATIMER);	writel(host->size, base + MMCIDATALENGTH);	datactrl = MCI_DPSM_ENABLE | data->blksz_bits << 4;	if (data->flags & MMC_DATA_READ) 		datactrl |= MCI_DPSM_DIRECTION;	if ((host->size) >32 )	{				writel((0x8000), base + MMCIDATALENGTH);		datactrl |= MCI_DPSM_DMAENABLE;			mmci_enable_dma(host,data);			}else {		datactrl &= ~MCI_DPSM_DMAENABLE;	}	writel(datactrl, base + MMCIDATACTRL);	if (datactrl & MCI_DPSM_DMAENABLE)		{			if (data->flags & MMC_DATA_READ) 				writel(readl(base + MMCIMASK0) & ~(MCI_DATACRCFAIL| MCI_DATAENDMASK| MCI_RXOVERRUN), base + MMCIMASK0);			else				writel(readl(base + MMCIMASK0) & ~(MCI_DATACRCFAIL| MCI_DATAENDMASK| MCI_TXUNDERRUN), base + MMCIMASK0);		}	else		writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0);		writel(0, base + MMCIMASK1);	} static voidmmci_data_irq(struct jademmci_host *host, struct mmc_data *data,	      unsigned int status){	if (status & MCI_DATABLOCKEND) {		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 jademmci_host *host, struct mmc_command *cmd,	     unsigned int status){	void __iomem *base = host->base;	host->cmd = NULL;	cmd->resp[0] = readl(base + MMCIRESPONSE0);	cmd->resp[1] = readl(base + MMCIRESPONSE1);	cmd->resp[2] = readl(base + MMCIRESPONSE2);	cmd->resp[3] = readl(base + MMCIRESPONSE3);	if (status & MCI_CMDTIMEOUT) {		cmd->error = MMC_ERR_TIMEOUT;	} else if (status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) {		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)) {		mmci_start_data(host, cmd->data);	}}static int mmci_pio_read(struct jademmci_host *host, char *buffer, unsigned int remain){	void __iomem *base = host->base;	char *ptr = buffer;	u32 status;	unsigned int timeout=0xffffffff;	unsigned int *ptr_trans = buffer;	unsigned int i;	unsigned int transfered;	do {		int count =  (readl(base + MMCIFIFOCNT) << 2);			transfered= remain-count;		if (transfered > remain)				transfered = remain;		for(i=0;i<transfered/4;i++ )					ptr_trans[i]=readl(base+MMCIFIFO);		ptr_trans += transfered>>2;		ptr +=transfered;					remain=count;			if (remain == 0)				break;		timeout--;	} while (timeout);	return ptr - buffer;}static int mmci_pio_write(struct jademmci_host *host, char *buffer, unsigned int remain, u32 status){	void __iomem *base = host->base;	char *ptr = buffer;	unsigned int *ptrt_rans = buffer;	unsigned int i;	do {		unsigned int count, maxcnt;		maxcnt = status & MCI_TXFIFOEMPTY ? MCI_FIFOSIZE : MCI_FIFOHALFSIZE;		count = min(remain, maxcnt);	for(i=0;i<count/4;i++ )		writel(	ptrt_rans[i],base+MMCIFIFO);		ptr += count;		remain -= count;		if (remain == 0)			break;

⌨️ 快捷键说明

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