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

📄 sd_disk.c

📁 linux 2.6下的sd卡驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************   File:    sd_disk.c  -   Control the instance of the card* *   The content of this file or document is CONFIDENTIAL and PROPRIETARY*   to Jade Technologies Co., Ltd.  It is subject to the terms of a*   License Agreement between Licensee and Jade Technologies Co., Ltd.*   restricting among other things, the use, reproduction, distribution*   and transfer.  Each of the embodiments, including this information *   and any derivative work shall retain this copyright notice.* *   Copyright (c) 2005 Jade Technologies Co., Ltd. *   All rights reserved.****************************************************************************/#include <asm/io.h>#include <asm/sizes.h>#include "sd.h"#define SD_DISK_DEBUG	0//------------------------------------------------------------------------------// Global Variables in SD_DISK.C//------------------------------------------------------------------------------unsigned long RCA = 0;extern unsigned char	ChannelNumber;extern unsigned long	InterruptID;extern int irqcount ;extern int irqcount1 ;//extern HANDLE		DMAIntrEvent;//------------------------------------------------------------------------------//// Initialize all the things especially the card //// Arguments://		controller - instance will be created//		errorcode - record error. //// Functions://		Create an instance.//		Create the interrupt event.//		Allocate DMA.////------------------------------------------------------------------------------irqreturn_t sd_cmd_irq(int irq, void *devid, struct pt_regs *regs){	SD_controller *c = devid;		if (c != NULL) {		c->laststatus = c->Registers->sd_STATUS ;		c->Registers->sd_CLEAR = c->laststatus;		//printk("irq: status = %x\n", c->laststatus);		irqcount++;		if(c->cmddone_data){			irqcount1++;			complete(c->cmddone_data);		}	}	return IRQ_HANDLED;}SD_controller* SDI_InitInterface(	SD_controller *controller,	unsigned long *errorcode	){	unsigned long error = 0;	if (!controller)		error = 1;	if (!error)	{		memset((void *)controller, 0, sizeof(SD_controller));				controller->Registers = (SD_REG*)ioremap(PHYS_SD0_BASE, 4096);		if (!controller->Registers)			error = 2;	}	if (!error)	{				error = request_irq(14, sd_cmd_irq, 0, "sd_cmd", (void *)controller);		printk("irq controller:%x\n", (void *)controller);		if(error<0){			printk("<1> sd register irq error:%ld\n", error);			error= 3;		}	/*		controller->InterruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);		if (!controller->InterruptEvent)		{			error = 3;		}	*/	}	if (!error)	{		SDI_ResetInterface(controller, 0);	}	controller->ifDMA = TRUE;	/*	if (!error)	{		DMAIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);		if (SDI_AllocateDMA())		{			RETAILMSG(MSG_DISK, (_T("SD: SDI_InitInterface - USE DMA\r\n")));		}		else		{			controller->ifDMA = FALSE;			RETAILMSG(MSG_DISK, (_T("SD: SDI_InitInterface - UNUSE DMA\r\n")));		}	}	*/	if (error)	{		//RETAILMSG(MSG_DISK, (_T("SD: SDI_InitInterface - error:%d\r\n"), error));		printk("SDI_InitInterface error:%ld\n", error);		if (errorcode)			*errorcode = error;		SDI_DeinitInterface(controller, 0);		return	0;	}	return controller;}//------------------------------------------------------------------------------//// Start up the card - make it into a work state//// Arguments://		controller - instance created in SDI_InitInterface//		errorcode - record error. //// Functions://		Power on. //		Inialize the interrupt event. //		Ask the card to respond. //		Get CID & CSD//		Set clock frequency. (If no DMA, the frequency should be very low)////------------------------------------------------------------------------------BOOL SDI_StartUpCard(	SD_controller *controller, 	unsigned long *errorcode	){	unsigned long error = 0;	SD_REG *regs;	printk("<1>SD: startup\n");	if (!controller)		error = 1;	if (!SDI_IsCardIn(controller, 0))		error = 7;	if (!error)	{		regs = controller->Registers;		regs->sd_CLOCK = (1<<8) | (0x40);		// Set the voltage		regs->sd_POWER = (15<<2);		// Power up		regs->sd_POWER = (1<<7) | (1<<6) | (15<<2) | MCI_POWER_UP;		msleep(1);		//{volatile int a; for(a=0; a<10000; a++); }		// Power on		regs->sd_POWER = (1<<7) | (1<<6) | (15<<2) | MCI_POWER_ON;		msleep(1);		//{volatile int a; for(a=0; a<10000; a++); }	}	/*	if (!error)	{		if (controller->InterruptEvent)		{			if (!InterruptInitialize(SYSINTR_SD0, controller->InterruptEvent, NULL, 0))				error = 7;		}	}	*/	if (!error)	{		int i;		apMCI_sResponse response;		response.ShortResponse = 0;					SDI_SendCmd(controller, &CommandParameters[GO_IDLE_STATE], 0, 0, &error);		for (i=0; i<10; i++)		{	// send command to card and wait for respond. 			SDI_SendCmd(controller, &CommandParameters[APP_CMD], 0, &response, &error);			SDI_SendCmd(controller, &CommandParameters[SEND_OP_COND], 0xFF8000, &response, &error);			if ((response.ShortResponse & 0x80000000))			{				break;			}			msleep(1);			//{volatile int a; for(a=0; a<10000; a++); }		}		if (i == 200)			error = 2;		else			error = 0;	}	if (!error)	{	// get card identification data		if (!SDI_GetCID(controller, (apMCI_sDecodedCID *)&controller->CardCID, &error))			error = 3;	}	if (!error)	{		apMCI_sResponse response;		if (!SDI_SendCmd(controller, &CommandParameters[SET_RELATIVE_ADDR], 0, &response, &error))			error = 4;		else		{			RCA = (unsigned long)(response.ShortResponse) & 0xFFFF0000;		}	}	if (!error)	{	// get card specific data		if (!SDI_GetCSD(controller, (apMCI_sDecodedCSD *)&controller->CardCSD, RCA, &error))		{			error = 5;		}	}	if (!error)	{		if (!SDI_SendCmd( controller, &CommandParameters[SELECT_CARD], RCA, 0, errorcode))		{			if (!SDI_SendCmd(controller, &CommandParameters[SELECT_CARD], RCA, 0, errorcode))				error = 8;		}	}	if (!error)	// wide bus mode	{		if (!SDI_SendCmd(controller, &CommandParameters[APP_CMD], RCA, 0, errorcode))			error = 9;		if (!SDI_SendCmd(controller, &CommandParameters[SET_BUS_WIDTH], (IF_WIDE_BUS<<1), 0, errorcode))			error = 10;	}	if (!error)	{		regs->sd_POWER &= ~(1<<6);	// don't use open drain		if (controller->ifDMA)			regs->sd_CLOCK = (1<<8) | (0x17);	// set high speed		else			return FALSE;		if (IF_WIDE_BUS)			regs->sd_CLOCK |= (1<<11);		else			regs->sd_CLOCK &= !(1<<11);	}	if (!error)	{		void *r;		u32 data;		r = ioremap(0x2002c000, SZ_4K);		if(r==NULL){			printk("sd gpio setup error3\n");			return -ENODEV;		}		data = readl(r+0x400);		writel((data & 0xef), r+0x400);		data = readl(r+0x410);		writel((data & 0xef), r+0x400);		iounmap(r);	}	if (error)	{		if (errorcode)			*errorcode = error;		return	FALSE;	}	return TRUE;}//------------------------------------------------------------------------------//// Re-start up the card - make it into a work state//// Arguments://		controller - instance created in SDI_InitInterface//		errorcode - record error. //// Functions://		Power on. //		Inialize the interrupt event. //		Ask the card to respond. //		Get CID & CSD//		Set clock frequency. (If no DMA, the frequency should be very low)////------------------------------------------------------------------------------BOOL SDI_ReStartUpCard(	SD_controller *controller, 	unsigned long *errorcode	){	unsigned long error = 0;	SD_REG *regs;	printk("<1>SD: restartup\n");	if (!controller)		error = 1;	if (!SDI_IsCardIn(controller, 0))		error = 7;	if (!error)	{		regs = controller->Registers;		regs->sd_CLOCK = (1<<8) | (0x40);		// Set the voltage		regs->sd_POWER = (15<<2);		// Power up		regs->sd_POWER = (1<<7) | (1<<6) | (15<<2) | MCI_POWER_UP;		msleep(1);		//{volatile int a; for(a=0; a<10000; a++); }		// Power on		regs->sd_POWER = (1<<7) | (1<<6) | (15<<2) | MCI_POWER_ON;		msleep(1);		//{volatile int a; for(a=0; a<10000; a++); }	}	/*	if (!error)	{		if (controller->InterruptEvent)		{			if (!InterruptInitialize(SYSINTR_SD0, controller->InterruptEvent, NULL, 0))				error = 7;		}	}	*/	if (!error)	{		int i;		apMCI_sResponse response;		response.ShortResponse = 0;					SDI_SendCmd(controller, &CommandParameters[GO_IDLE_STATE], 0, 0, &error);		for (i=0; i<10; i++)		{	// send command to card and wait for respond. 			SDI_SendCmd(controller, &CommandParameters[APP_CMD], 0, &response, &error);			SDI_SendCmd(controller, &CommandParameters[SEND_OP_COND], 0xFF8000, &response, &error);			if ((response.ShortResponse & 0x80000000))			{				break;			}			msleep(1);						/*{			volatile int a, b; 			for(a=0; a<10; a++);				for(b=0; b<10000; b++); 			}*/		}		if (i == 200)			error = 2;		else			error = 0;	}	if (!error)	{		apMCI_sResponse response;		if (!SDI_SendCmd(controller, &CommandParameters[SET_RELATIVE_ADDR], 0, &response, &error))			error = 4;		else		{			RCA = (unsigned long)(response.ShortResponse) & 0xFFFF0000;		}	}	if (!error)	{		if (!SDI_SendCmd( controller, &CommandParameters[SELECT_CARD], RCA, 0, errorcode))		{			if (!SDI_SendCmd(controller, &CommandParameters[SELECT_CARD], RCA, 0, errorcode))				error = 8;		}	}	if (!error)	// wide bus mode	{		if (!SDI_SendCmd(controller, &CommandParameters[APP_CMD], RCA, 0, errorcode))			error = 9;		if (!SDI_SendCmd(controller, &CommandParameters[SET_BUS_WIDTH], (IF_WIDE_BUS<<1), 0, errorcode))			error = 10;	}	if (!error)	{		regs->sd_POWER &= ~(1<<6);	// don't use open drain		if (controller->ifDMA)			regs->sd_CLOCK = (1<<8) | (0x03);	// set high speed		else			return FALSE;		if (IF_WIDE_BUS)			regs->sd_CLOCK |= (1<<11);	}			if (error)	{		if (errorcode)			*errorcode = error;		return	FALSE;	}	return TRUE;}//------------------------------------------------------------------------------//// Reset the card - used when the instance been closed or error occured//// Arguments://		controller - instance passed by SDI_StartUpCard//		errorcode - record error. //// Functions://		Power off. //		Clear interrupt mask////------------------------------------------------------------------------------BOOL SDI_ResetInterface(	SD_controller *controller, 	unsigned long *errorcode	){	unsigned long error = 0;	printk("<1>SD: reset\n");	if (!controller)		error = 1;	if (!error)	{		controller->Registers->sd_CLOCK = 0;		controller->Registers->sd_POWER = 0;				controller->Registers->sd_COMMAND = 0;		controller->Registers->sd_DATACTRL = 0;		controller->Registers->sd_CLEAR = MCI_STATUS_STATIC_MASK;		controller->Registers->sd_MASK0 = 0;		controller->Registers->sd_MASK1 = 0;				controller->Registers->sd_CLOCK = apMCI_CLOCK_POWERSAVE;

⌨️ 快捷键说明

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