📄 sd.c
字号:
/* * A EEEE SSSS OOO PPPP * A A E S O O P P * AAAAA EEEE SSSS O O PPPP * A A E S O O P * A A EEEE SSSS OOO P * * An Entertainment Solution On a Platform (AESOP) is a completely Open Source * based graphical user environment and suite of applications for PDAs and other * devices running Linux. It is included in various embedded Linux distributions * such as OpenZaurus - http://www.aesop-embedded.org * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * * Title : sd.c * Author : * Created date : 2005. 06. 26. 23:05:59 KST * Description : * * $Revision: 1.2 $ * $Log: sd.c,v $ * Revision 1.2 2005/07/07 15:46:59 linux4go * *** empty log message *** * * Revision 1.1.1.1 2005/06/27 17:03:53 linuxpark * Initial import. * * * */ #ident "@(*) $Header: /cvsroot/aesop-embedded/u-boot-aesop/board/aesop2440/sd.c,v 1.2 2005/07/07 15:46:59 linux4go Exp $"/* * Copyright (c) 2005 * Salamander, aesop-embedded.org kernelproject.org, <omega5@dreamwiz.com> * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#include <common.h>#include <s3c2440.h>#include <part.h>#if 1extern intfat_register_device(block_dev_desc_t *dev_desc, int part_no);static block_dev_desc_t mmc_dev;block_dev_desc_t * mmc_get_dev(int dev){ return ((block_dev_desc_t *)&mmc_dev);}//#if 1int isMMC; // 1:MMC, 0:SDint RCA=0; // Relative card addressunsigned int CardSize=0; // SD capacity in byte /* * CSD register, rwe == read/write/erase */typedef struct { unsigned char csd; /* CSD structure */ unsigned char spec_vers; /* Spec version, MMC only */ struct { unsigned char man; /* time mantissa */ unsigned char exp; /* time exponent */ } taac; /* Data read access-time-1 */ unsigned char nsac; /* Data read access-time-2 in CLK cycle */ struct { unsigned char man; /* rate mantissa */ unsigned char exp; /* rate exponent */ } tran_speed; /* Max. data transfer rate */ unsigned short ccc; /* Card command classes */ unsigned char read_len; /* Max. read data block length */ unsigned char read_part; /* Partial blocks for read allowed */ unsigned char write_mis; /* write block misalignment */ unsigned char read_mis; /* read block misalignment */ unsigned char dsr; /* DSR implemented */ unsigned short c_size; /* Device size */ unsigned char vcc_r_min; /* Max. read current at Vcc min */ unsigned char vcc_r_max; /* Max. read current at Vcc max */ unsigned char vcc_w_min; /* Max. write current at Vcc min */ unsigned char vcc_w_max; /* Max. write current at Vcc max */ unsigned char c_size_mult; /* Device size multiplier */ unsigned char er_size; /* Erase sector size, MMC only */ unsigned char er_grp_size; /* Erase group size, MMC only */ unsigned char wp_grp_size; /* Write protect group size */ unsigned char wp_grp_en; /* Write protect group enable */ unsigned char dflt_ecc; /* Manufacturer default ECC, MMC only */ unsigned char r2w_factor; /* Write speed factor */ unsigned char write_len; /* Max. write data block length */ unsigned char write_part; /* Partial blocks for write allowed */ unsigned char ffmt_grp; /* File format group, rw */ unsigned char copy; /* Copy flag (OTP), rw */ unsigned char perm_wp; /* Permanent write protection, rw */ unsigned char tmp_wp; /* temporary write protection, rwe */ unsigned char ffmt; /* file format, rw */ unsigned char ecc; /* ECC, rwe, MMC only */ /* SD only */ unsigned char er_blk_en; /* Erase single block enable, SD only */ unsigned char er_sec_size; /* Erase sector size, SD only */} CSD_regs;int Chk_CMDend(int cmd, int be_resp){ S3C2410_SDI * const sdi = S3C2410_GetBase_SDI(); int volatile finish0; if(!be_resp) // No response { finish0=sdi->SDICSTA; while((finish0&0x800) != 0x800) // Check cmd end { finish0=sdi->SDICSTA; } sdi->SDICSTA=finish0;// Clear cmd end state return 1; } else // With response { finish0=sdi->SDICSTA; while( !( ((finish0&0x200)==0x200) | ((finish0&0x400)==0x400) )) // Check cmd/rsp end finish0=sdi->SDICSTA; if( (cmd==1) | (cmd==41)) // CRC no check, CMD9 is a long Resp. command. { if( (finish0&0xf00) != 0xa00 ) // Check error { sdi->SDICSTA=finish0; // Clear error state if(((finish0&0x400)==0x400)) return 0; // Timeout error } sdi->SDICSTA=finish0; // Clear cmd & rsp end state } else // CRC check { if( (finish0&0x1f00) != 0xa00 ) // Check error { //printf("CMD%d:rSDICSTA=0x%x,rSDIRSP0=0x%x\n",cmd, sdi->SDICSTA, sdi->SDIRSP0); sdi->SDICSTA=finish0; // Clear error state if(((finish0&0x400)==0x400)) return 0; // Timeout error } sdi->SDICSTA=finish0; } return 1; }}int Chk_DATend(void){ S3C2410_SDI * const sdi = S3C2410_GetBase_SDI(); int finish; finish = sdi->SDIDSTA; while( !( ((finish&0x10)==0x10) | ((finish&0x20)==0x20) )) { // Chek timeout or data end finish = sdi->SDIDSTA; //printf("DATA:finish=0x%x\n", finish); } if( (finish&0xfc) != 0x10 ) { printf("DATA:finish=0x%x\n", finish); // Something wrong !! sdi->SDIDSTA = 0xec; // Clear error state return 0; } return 1;}int Chk_BUSYend(void){ S3C2410_SDI * const sdi = S3C2410_GetBase_SDI(); int finish; finish = sdi->SDIDSTA; while( !( ((finish&0x08)==0x08) | ((finish&0x20)==0x20) )) finish = sdi->SDIDSTA; if( (finish&0xfc) != 0x08 ) { printf("BUSY:finish=0x%x\n", finish); sdi->SDIDSTA = 0xf4; //clear error state return 0; } return 1;}void CMD0(void){ S3C2410_SDI * const sdi = S3C2410_GetBase_SDI(); //-- Make card idle state sdi->SDICARG=0x0; // CMD0(stuff bit) sdi->SDICCON=(1<<8)|0x40; // No_resp, start, CMD0 //-- Check end of CMD0 Chk_CMDend(0, 0); sdi->SDICSTA=0x800; // Clear cmd_end(no rsp)}int CMD55(void){ S3C2410_SDI * const sdi = S3C2410_GetBase_SDI(); //--Make ACMD sdi->SDICARG=RCA<<16; //CMD7(RCA,stuff bit) sdi->SDICCON=(0x1<<9)|(0x1<<8)|0x77; //sht_resp, wait_resp, start, CMD55 //-- Check end of CMD55 if(!Chk_CMDend(55, 1)) return 0; sdi->SDICSTA=0xa00; // Clear cmd_end(with rsp) return 1;}CSD_regs csd;int CMD9(void)//SEND_CSD{ S3C2410_SDI * const sdi = S3C2410_GetBase_SDI(); unsigned char buff[16]; // unsigned long card_size; sdi->SDICARG=RCA<<16; // CMD9(RCA,stuff bit) sdi->SDICCON=(0x1<<10)|(0x1<<9)|(0x1<<8)|0x49; // long_resp, wait_resp, start, CMD9// printf("\n****CSD register****\n"); //-- Check end of CMD9 if(!Chk_CMDend(9, 1)) return 0; buff[0]=(unsigned char)(sdi->SDIRSP0>>24); buff[1]=(unsigned char)(sdi->SDIRSP0>>16); buff[2]=(unsigned char)(sdi->SDIRSP0>>8); buff[3]=(unsigned char)(sdi->SDIRSP0); buff[4]=(unsigned char)(sdi->SDIRSP1>>24); buff[5]=(unsigned char)(sdi->SDIRSP1>>16); buff[6]=(unsigned char)(sdi->SDIRSP1>>8); buff[7]=(unsigned char)(sdi->SDIRSP1); buff[8]=(unsigned char)(sdi->SDIRSP2>>24); buff[9]=(unsigned char)(sdi->SDIRSP2>>16); buff[10]=(unsigned char)(sdi->SDIRSP2>>8); buff[11]=(unsigned char)(sdi->SDIRSP2); buff[12]=(unsigned char)(sdi->SDIRSP3>>24); buff[13]=(unsigned char)(sdi->SDIRSP3>>16); buff[14]=(unsigned char)(sdi->SDIRSP3>>8); buff[15]=(unsigned char)(sdi->SDIRSP3); { csd.csd = (buff[0] & 0xc0) >> 6; csd.spec_vers = (buff[0] & 0x3c) >> 2; (csd.taac).man = (buff[1] & 0x78) >> 3; (csd.taac).exp = (buff[1]) & 0x07; csd.nsac = buff[2]; (csd.tran_speed).man = (buff[3] & 0x78) >> 3; (csd.tran_speed).exp = (buff[3]) & 0x07; csd.ccc = (buff[4] << 4) | ((buff[5] & 0xf0) >> 4); csd.read_len = (buff[5] & 0x0f); csd.read_part = (buff[6] & 0x80) ? 1 : 0; csd.write_mis = (buff[6] & 0x40) ? 1 : 0; csd.read_mis = (buff[6] & 0x20) ? 1 : 0; csd.dsr = (buff[6] & 0x10) ? 1 : 0; csd.c_size = ((buff[6] & 0x03) << 10) | (buff[7] << 2) | ((buff[8] & 0xc0) >> 6); csd.vcc_r_min = (buff[8] & 0x38) >> 3; csd.vcc_r_max = (buff[8] & 0x07); csd.vcc_w_min = (buff[9] & 0xe0) >> 5; csd.vcc_w_max = (buff[9] & 0x1c) >> 2; csd.c_size_mult = ((buff[9] & 0x03) << 1) | ((buff[10] & 0x80) >> 7); csd.er_size = (buff[10] & 0x7c) >> 2; csd.er_grp_size = ((buff[10] & 0x03) << 3) | ((buff[11] & 0xe0) >> 5); csd.wp_grp_size = (buff[11] & 0x1f); csd.wp_grp_en = (buff[12] & 0x80) ? 1 : 0; csd.dflt_ecc = (buff[12] & 0x60) >> 5; csd.r2w_factor = (buff[12] & 0x1c) >> 2; csd.write_len = ((buff[12] & 0x03) << 2) | ((buff[13] & 0xc0) >> 6); csd.write_part = (buff[13] & 0x20) ? 1 : 0; csd.ffmt_grp = (buff[14] & 0x80) ? 1 : 0; csd.copy = (buff[14] & 0x40) ? 1 : 0; csd.perm_wp = (buff[14] & 0x20) ? 1 : 0; csd.tmp_wp = (buff[14] & 0x10) ? 1 : 0; csd.ffmt = (buff[14] & 0x0c) >> 2; csd.ecc = (buff[14] & 0x03); } /* calculate total card size in bytes */ CardSize = (1 + csd.c_size) * (0x01 << (csd.c_size_mult + 2)) * (0x01 << csd.read_len); printf("Size = %d KBytes ", CardSize/1024); return 1;}int Chk_MMC_OCR(void){ S3C2410_SDI * const sdi = S3C2410_GetBase_SDI(); int i; //-- Negotiate operating condition for MMC, it makes card ready state for(i=0;i<100;i++) //Negotiation time is dependent on CARD Vendors. { // sdi->SDICARG=0xffc000; //CMD1(MMC OCR:2.6V~3.6V) sdi->SDICARG=0xff8000; //CMD1(SD OCR:2.7V~3.6V) sdi->SDICCON=(0x1<<9)|(0x1<<8)|0x41; //sht_resp, wait_resp, start, CMD1 //-- Check end of CMD1 // if(Chk_CMDend(1, 1) & sdi->SDIRSP0==0x80ffc000) //[31]:Card Power up status bit (busy) //0xffc000 is Voltage window if(Chk_CMDend(1, 1) && (sdi->SDIRSP0>>16)==0x80ff) { sdi->SDICSTA=0xa00; // Clear cmd_end(with rsp) return 1; // Success } } sdi->SDICSTA=0xa00; // Clear cmd_end(with rsp) return 0; // Fail}int Chk_SD_OCR(void){ S3C2410_SDI * const sdi = S3C2410_GetBase_SDI(); int i; //-- Negotiate operating condition for SD, it makes card ready state for(i=0;i<50;i++) //If this time is short, init. can be fail. { CMD55(); // Make ACMD sdi->SDICARG=0xff8000; //ACMD41(SD OCR:2.7V~3.6V) sdi->SDICCON=(0x1<<9)|(0x1<<8)|0x69;//sht_resp, wait_resp, start, ACMD41 //-- Check end of ACMD41 if( Chk_CMDend(41, 1) & (sdi->SDIRSP0==0x80ff8000) ) { sdi->SDICSTA=0xa00; // Clear cmd_end(with rsp) return 1; // Success } udelay(20000); // Wait Card power up status } sdi->SDICSTA=0xa00; // Clear cmd_end(with rsp) return 0; // Fail}int CardBusWidth;void SetBus(void){ S3C2410_SDI * const sdi = S3C2410_GetBase_SDI();SET_BUS: CMD55(); // Make ACMD //-- CMD6 implement sdi->SDICARG=CardBusWidth<<1; //Width 0: 1bit, 1: 4bit sdi->SDICCON=(0x1<<9)|(0x1<<8)|0x46; //sht_resp, wait_resp, start, CMD55 if(!Chk_CMDend(6, 1)) // ACMD6 goto SET_BUS; sdi->SDICSTA=0xa00; // Clear cmd_end(with rsp)}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -