📄 sd_disk.c
字号:
/**************************************************************************** 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 + -