#define GPIOCFG0 (*(volatile unsigned long *)0xbfd010c0)
#define GPIOOE0 (*(volatile unsigned long *)0xbfd010d0)
#define GPIOIN0 (*(volatile unsigned long *)0xbfd010e0)
#define GPIOOUT0 (*(volatile unsigned long *)0xbfd010f0)
#define GPIOCFG1 (*(volatile unsigned long *)0xbfd010c4)
#define GPIOOE1 (*(volatile unsigned long *)0xbfd010d4)
#define GPIOIN1 (*(volatile unsigned long *)0xbfd010e4)
#define GPIOOUT1 (*(volatile unsigned long *)0xbfd010f4)
//static char cmd0[] = {0x40,0x00,0x00,0x00,0x00,0x95};
//static char cmd1[] = {0x41,0x00,0x00,0x00,0x00,0xff};
#if 0
static unsigned char CMD0[6] = {0x40,0x0,0x0,0x0,0x0,0x95}; //reset command. ,rec 0x01
static unsigned char CMD1[6] = {0x41,0x0,0x0,0x0,0x0,0xff}; //rec 0x00
static unsigned char CMD9[6] = {0x49,0x0,0x0,0x0,0x0,0xff}; //SEND_CSD
static unsigned char CMD10[6] = {0x4A,0x0,0x0,0x0,0x0,0xff}; //SEND_CID
static unsigned char CMD17[6] = {0x51,0x0,0x0,0x0,0x0,0xff}; //Read_block
static unsigned char CMD24[6] = {0x58,0x0,0x0,0x0,0x0,0xff}; //Read_block
static unsigned char CMD55[6] = {0x77,0x0,0x0,0x0,0x0,0xff}; //?
static unsigned char ACMD41[6]= {0x69,0x0,0x0,0x0,0x0,0xff}; //?
static unsigned char CMD59[6] = {0x7B,0x0,0x0,0x0,0x1,0xff}; //?
#endif
/******************shuo ming******************************
* MISO ==> Do GPIO 25//save *
* MOSI ==> DI GPIO 26//save *
* MISO ==> DI GPIO 25//master *
* MOSI ==> DO GPIO 26//master *
* CLK GPIO 24 *
* CS2 GPIO 29 *
*******************shuo ming******************************/
inline void enable_every()
{
GPIOCFG0 &= (~(1 << 25) || ~(1 << 26) || ~(1 << 24) || ~(1 << 29) || ~(1 << 30));
GPIOCFG0 |= ((1 << 25) | (1 << 26) | (1 << 24) | (1 << 29) | (1 << 30));
GPIOOE0 &= (~(1 << 25) || ~(1 << 26) || ~(1 << 24) || ~(1 << 29) || ~(1 << 30));
GPIOOE0 |= (1 << 25);
GPIOOUT0 &= (~(1 << 26) || ~(1 << 24) || ~(1 << 29) || ~(1 << 30));
GPIOOUT0 |= ((1 << 26) | (1 << 24) | (1 << 29) | (1 << 30));
GPIOIN0 &= ~(1 << 25);
}
inline void Config_Gpio0(int state,int GPIO)
{
if(state){
GPIOOUT0 &= ~(1 << GPIO);
GPIOOUT0 |= (1 << GPIO);
udelay(100);
//printk("GPIOOUT0 = 0x%x\t,Config_DI_state = 0x%x\n",GPIOOUT0,Config_DI_state);
}else{
GPIOOUT0 &= ~(1 << GPIO);
udelay(100);
//printk("*******GPIOOUT0 = 0x%x\t,Config_DI_state = 0x%x\n",GPIOOUT0,Config_DI_state);
}
}
inline int get_di()
{
int ret;
ret = (GPIOIN0 & (1 << 25))?1:0;
//printk("I am come here");
return ret;
}
void Delay5us()
{
udelay(5);
}
void PutPortraitChar(unsigned int ScreenX,unsigned int Line,unsigned char *StringPointer,unsigned int Overwrite_Back_Ground)
{
printk("%s\n",StringPointer);
}
unsigned int BlockSize;
void SD_2Byte_Write(unsigned int IOData)
{
unsigned int BitCounter;
for(BitCounter = 0; BitCounter < 16;BitCounter++){
Config_Gpio0(0,24);//set clk,gpio 24 state low
//transmission data
if(IOData & 0x8000)//If the MSB of IODATA is 1,then Do = 1,else do=0
Config_Gpio0(1,26);//set mosi,gpio 26 state high
else Config_Gpio0(0,26);//Do low
Config_Gpio0(1,24);//set clk,gpio 24 state high
Delay5us();
IOData = IOData << 1;//Because the MSB is transmitted firstly,shift to next lower bit
}
}
void SD_Write(unsigned int IOData)
{
unsigned int BitCounter;
IOData = IOData << 8;
for(BitCounter = 0; BitCounter < 8;BitCounter++){
Config_Gpio0(0,24);//set clk,gpio 24 state low
if(IOData & 0x8000)//If the MSB of IODATA is 1,then Do = 1,else do=0
Config_Gpio0(1,26);//set do,gpio 26 state high
else Config_Gpio0(0,26);//Do low
Config_Gpio0(1,24);//set clk,gpio 24 state high
Delay5us();
IOData = IOData << 1;//Because the MSB is transmitted firstly,shift to next lower bit
}
}
#if 0
unsigned int SD_2Byte_Read()
{
unsigned int BitCounter,Buffer;
Buffer = 0;
for(BitCounter = 0; BitCounter < 16;BitCounter++){
Config_Gpio0(0,24);//set clk,gpio 24 state low
Delay5us();
Config_Gpio0(1,24);//set clk,gpio 24 state high
//Delay5us();
Buffer = Buffer << 1;//Because the MSB is transmitted firstly,shift to next lower bit
if(get_di())
Buffer++;//if spi_din=1 then the LSB_of_buffer=1
}
return Buffer;
}
#endif
unsigned int SD_2Byte_Read()
{
unsigned int BitCounter,Buffer;
Buffer = 0;
for(BitCounter = 0; BitCounter < 16;BitCounter++){
Buffer = Buffer << 1;//Because the MSB is transmitted firstly,shift to next lower bit
Config_Gpio0(0,24);//set clk,gpio 24 state low
Delay5us();
//Delay5us();
if(get_di())
Buffer++;//if spi_din=1 then the LSB_of_buffer=1
Config_Gpio0(1,24);//set clk,gpio 24 state high
}
return Buffer;
}
static int read_delay = 20;
#define DELAY_STEP 5
#if 0
unsigned short SD_Read()//simulatinf spi io
{
unsigned short BitCounter,Buffer;
Buffer = 0xffff;
//Buffer = 0x0000;
for(BitCounter = 0; BitCounter < 8;BitCounter++){
Config_Gpio0(0,24);//set clk,gpio 24 state low
Delay5us();
//transmission data
Config_Gpio0(1,24);//set clk,gpio 24 state high
Buffer = Buffer << 1;//Because the MSB is transmitted firstly,shift to next lower bit
/**************************test only***********************/
//printk("GPIOOE0 = %x\n",GPIOOE0);//test only
//printk("GPIOIN0 = %x\n",GPIOIN0);//test only
/**************************test only***********************/
if(get_di()){
printk("*************SD_Read Buffer = 0x%x\n",Buffer);
Buffer++;//if spi_din=1 then the LSB_of_buffer=1
printk("SD_Read Buffer = 0x%x\n",Buffer);
}else
buffer &= ~0x01;
}
return Buffer;
}
#endif
/*********************30 lines********************************/
unsigned short SD_Read()//simulatinf spi io
{
unsigned short BitCounter,Buffer;
Buffer = 0xffff;
//Buffer = 0x0000;
for(BitCounter = 0; BitCounter < 8;BitCounter++){
Buffer = Buffer << 1;//Because the MSB is transmitted firstly,shift to next lower bit
Config_Gpio0(0,24);//set clk,gpio 24 state low
Delay5us();
//transmission data
/**************************test only***********************/
//printk("GPIOOE0 = %x\n",GPIOOE0);//test only
//printk("GPIOIN0 = %x\n",GPIOIN0);//test only
/**************************test only***********************/
if(get_di()){
Buffer |= 0x01;//if spi_din=1 then the LSB_of_buffer=1
//printk("SD_Read Buffer = 0x%x\n",Buffer);
}else
Buffer &= ~0x01;
Config_Gpio0(1,24);//set clk,gpio 24 state high
}
return Buffer;
}
unsigned int SD_CMD_Write(unsigned int CMDIndex,unsigned long CMDArg,unsigned int ResType,unsigned int CSLowRSV)//ResType:Response Type, send 1 for R1; send 2 for R1b; send 3 for R2.
{
unsigned int temp,Response,Response2,CRC,MaximumTimes;
Response2=0;
MaximumTimes=10;
CRC=0x0095;//0x0095 is only valid for CMD0
if (CMDIndex != 0) CRC=0x00ff;
Config_Gpio0(0,29);//set cs ,gpio 29 state low
SD_2Byte_Write(((CMDIndex|0x0040)<<8)+(CMDArg>>24));//[2] Transmit Command_Index & 1st Byte of Command_Argument.
SD_2Byte_Write((CMDArg&0x00ffff00)>>8); //[2] 2nd & 3rd Byte of Command_Argument
SD_2Byte_Write(((CMDArg&0x000000ff)<<8) +CRC); //[2] 4th Byte of Command_Argument & CRC only for CMD0
//[3] Do High
Config_Gpio0(1,26);//set do,gpio 26 state high
//[3] Restore Do to High Level
for(temp = 0; temp < 8;temp++){//[4] Provide 8 extra clock after CMD
Config_Gpio0(0,24);//set clk,gpio 24 state low
Delay5us();
Config_Gpio0(1,24);//set clk,gpio 24 state high
Delay5us();
}
switch (ResType)//[5] wait response
{
case 1://R1
{
do
Response=SD_Read();
while (Response == 0xffff);
break;
}
case 2://R1b
{
do
Response=SD_Read();
while (Response==0xffff);//Read R1 firstly
do
Response2=SD_Read()-0xff00;
while (Response2!=0);//Wait until the Busy_Signal_Token is non-zero
break;
}
case 3: Response=SD_2Byte_Read();break;//R2
}
if (CSLowRSV==0)//[6] CS High (if the CMD has data block response CS should be kept low)
Config_Gpio0(1,29);//set cs ,gpio 29 state high
//printk("****** SD_CMD_Write 10 *********\n");
for(temp = 0; temp < 8;temp++){
Config_Gpio0(0,24);//set clk,gpio 24 state low
Delay5us();
Config_Gpio0(1,24);//set clk,gpio 24 state high
Delay5us();
}
//printk("****** SD_CMD_Write 11 *********\n");
return Response;
}
unsigned int SD_Reset_Card()
{
unsigned int i,Response,tries=100;
//unsigned int i,Response;
//printk("********SD_Reset_Card begin*******\n");
for(i=0;i<100;i++){//Send 74+ Clocks
Config_Gpio0(0,24);//set clk,gpio 24 state low
Delay5us();
Config_Gpio0(1,24);//set clk,gpio 24 state high
Delay5us();
}
//while(tries--){
for(i=0;i<10;i++){//The max initiation times is 10.
Response = SD_CMD_Write(0x0000,0x00000000,1,0);//Send CMD0
//Response = SD_CMD_Write(CMD0);//Send CMD0
printk("****Response=0x%x\n",Response);
if (Response == 0xff01) i=10;
//if (Response == 1) i=10;
}
// if (Response!=0xff01) read_delay +=DELAY_STEP;
// else{
// break;
// }
// printk("Response=%x read_delay=%d\n",Response,read_delay);
//}
//printk("********SD_Reset_Card over*******\n");
return Response;
}
unsigned int SD_Initiate_Card()//polling the card after reset
{
unsigned int i,Response;
unsigned int cont;
cont = 250;
do{
//test Response = SD_CMD_Write(0x0001,0x00000000,1,0);//Send CMD1 CMD1鈥斺€?x00
//test printk("**Send CMD1**Response=0x%x\n",Response);
printk("**Send CMD55**ACMD41****\n");
Response = SD_CMD_Write(0x0037,0x00000000,1,1);//Send CMD55 CMD55鈥斺€?x01锛圫D鍗″浜巌n-idle-state锛? printk("**Send ACMD41*****\n");
Response = SD_CMD_Write(0x0029,0x00000000,1,0);//Send ACMD41 ACMD41鈥斺€?x00 \
锛圫D鍗¤烦鍑篿n-idle-state锛屽畬鎴愬垵濮嬪寲鍑嗗鎺ュ彈涓嬩竴鏉℃寚浠わ級
printk("**Send ACMD41**Response=0x%x\n",Response);
}while((cont--) && (Response != 0xff00));
return Response;
}
unsigned int SD_Get_CardInfo(unsigned char *ReadBuffer)//Read CSD register
{
unsigned int temp,Response,MaximumTimes;
MaximumTimes=10;
for(temp=0;temp<MaximumTimes;temp++)
{
Response=SD_CMD_Write(9,0x00000000,3,1);//Send CMD9
//Response=SD_CMD_Write(CMD9);//Send CMD9
if (Response==0xff00)
temp=MaximumTimes;
}
//Provide 8 clock to romove the first byte of data response (0x00fe)
for(temp=0;temp<8;temp++){
Config_Gpio0(0,24);//set clk,gpio 24 state low
Delay5us();
Config_Gpio0(1,24);//set clk,gpio 24 state high
Delay5us();
}
// //sw: make sure the resp is 0xfe
// while(flash_writeb_cmd(0xff) != 0xfe);
for (temp=0;temp<8;temp++){
unsigned short data;
data=SD_2Byte_Read();
ReadBuffer[2*temp]=(data>>8)&0xff;
ReadBuffer[2*temp+1]=data&0xff;
}
//Provide 16 clock to remove the last 2 bytes of data response (CRC)
for(temp=0;temp<16;temp++){
Config_Gpio0(0,24);//set clk,gpio 24 state low
Delay5us();
Config_Gpio0(1,24);//set clk,gpio 24 state high
Delay5us();
}
//sw
Config_Gpio0(1,29);//set cs ,gpio 29 state high
//Provide 8 extra clock after data response
for(temp=0;temp<8;temp++){
Config_Gpio0(0,24);//set clk,gpio 24 state low
Delay5us();
Config_Gpio0(1,24);//set clk,gpio 24 state high
Delay5us();
}
return Response;
}
unsigned int SD_Overall_Initiation()
{
unsigned int Response,Response_2;
Response = 0x0000;
Response_2 = 0xff00;
Config_Gpio0(1,26);//set mosi,gpio 26 state high,Do must be high when there is no transmition
Response = SD_Reset_Card();
// do
// Response=SD_Reset_Card();//[2] Send CMD0
// while (Response!=0x01);
//if (Response!=0xff01) Response_2+=8;
//Response=SD_CMD_Write(8,0x00000000,1,0);//Send CMD8
#if 1
if(Response != 0xff01){
printk("*******Response=0x%x\n",Response);
PutPortraitChar(0,15,"No SD Card",1);//Print MSG
Response_2 += 8;
return Response_2;
}
#endif
Response = SD_Initiate_Card();//Send CMD55+ACMD41
if(Response == 0xff00)
PutPortraitChar(0,15,"Init Success",1);//Print MSG
else{
Response_2 += 4;
PutPortraitChar(0,15,"No SD Card",1);//Print MSG
}
// do
// Response = SD_Get_CardInfo();//[4] Read CSD
// while (Response!=0xff00);
return Response_2;
// 1111|1111||0000|0000 Response_2
// ||
// ||__CMD55+ACMD41 Fail
// |___CMD0 Fail
}
unsigned int SD_Get_CardID(unsigned char *ReadBuffer)//read CID register
{
unsigned int temp,Response,MaximumTimes;
MaximumTimes = 10;
for(temp = 0;temp < MaximumTimes;temp++){
Response = SD_CMD_Write(0x10,0x00000000,1,1);//send cmd10
//Response = SD_CMD_Write(CMD9);//send cmd9
if(Response == 0xff00)
temp = MaximumTimes;
}
for(temp = 0;temp < 8; temp++){//Provide 8 clock to remove the first byte of data response (0x00fe)
Config_Gpio0(0,24);//set clk low
Delay5us();
Config_Gpio0(1,24);//set clk high
Delay5us();
}
for(temp = 0;temp < 8;temp++){//Get the CID data
unsigned short data;
data = SD_2Byte_Read();
ReadBuffer[2*temp] = (data >> 8)&0xff;
ReadBuffer[2*temp + 1] = data&0xff;
}
for(temp = 0;temp < 16; temp++){//Provide 16 clock to remove the last 2 byte of data response (CRC)
Config_Gpio0(0,24);//set clk low
Delay5us();
Config_Gpio0(1,24);//set clk high
Delay5us();
}
Config_Gpio0(1,29);//set cs ,gpio 29 state high
for(temp = 0;temp < 8;temp++){//Provide 8 extra clock after data response
Config_Gpio0(0,24);//set clk low
Delay5us();
Config_Gpio0(1,24);//set clk high
Delay5us();
}
return Response;
}
unsigned int Read_Single_Block(unsigned long int ByteAddress,unsigned char *ReadBuffer)
{
unsigned int temp,Response,MaximumTimes;
MaximumTimes = 10;
for(temp = 0;temp < MaximumTimes;temp++){
Response = SD_CMD_Write(17,ByteAddress,1,1);//send cmd17
//Response = SD_CMD_Write(CMD17);//send cmd17
if(Response == 0xff00)
temp = MaximumTimes;
}
if(Response != 0xff00) return Response;
while(SD_Read() != 0xfffe);
for(temp = 0; temp < 256;temp++){//Get the readed data
unsigned short data;
data = SD_2Byte_Read();
ReadBuffer[2*temp] = (data >> 8)&0xff;
ReadBuffer[2*temp + 1] = data&0xff;
}
for(temp = 0;temp < 16; temp++){//Provide 16 clock to remove the last 2 byte of data response (CRC)
Config_Gpio0(0,24);//set clk low
Delay5us();
Config_Gpio0(1,24);//set clk high
Delay5us();
}
Config_Gpio0(1,29);//set cs ,gpio 29 state high
for(temp = 0;temp < 8;temp++){//Provide 8 extra clock after data response
Config_Gpio0(0,24);//set clk low
Delay5us();
Config_Gpio0(1,24);//set clk high
Delay5us();
}
return Response;
}
unsigned int Write_Single_Block(unsigned long int ByteAddress,unsigned char *WriteBuffer)
{
unsigned int temp,Response,MaximumTimes;
MaximumTimes = 10;
for(temp = 0;temp < MaximumTimes;temp++){
Response = SD_CMD_Write(24,ByteAddress,1,1);//send cmd24
//Response = SD_CMD_Write(CMD24);//send cmd24
if(Response == 0xff00)
temp = MaximumTimes;
}
for(temp = 0;temp < 8;temp++){//Provide 8 extra clock after CMD response
Config_Gpio0(0,24);//set clk low
Delay5us();
Config_Gpio0(1,24);//set clk high
Delay5us();
}
SD_Write(0x00fe);//send start block token
for(temp = 0; temp < 256;temp++)//data block
SD_2Byte_Write(((WriteBuffer[2*temp]) << 8) | (WriteBuffer[2*temp+1]));
SD_2Byte_Write(0xffff);//send 2 Byte crc
Response = SD_Read();
while(SD_Read() != 0xffff);
Config_Gpio0(1,29);//set cs ,gpio 29 state high
for(temp = 0;temp < 8;temp++){//Provide 8 extra clock after data response
Config_Gpio0(0,24);//set clk low
Delay5us();
Config_Gpio0(1,24);//set clk high
Delay5us();
}
return Response;
}
static int sdcard_init(int div)
{
unsigned char tmp;
static int inited = 0;
int i = 0,j = 0;
if(inited) return 0;
enable_every();
// Config_Gpio0(0,30);//power supply,gpio 30 state low
//
// udelay(5000000);
Config_Gpio0(1,29);//set cs ,gpio 29 state high
Config_Gpio0(1,26);//set mosi,gpio 26 state high
Config_Gpio0(0,24);//set clk,gpio 24 state low
udelay(5000000);
/******************shuo ming******************************
* MISO ==> Do GPIO 25//save *
* MOSI ==> DI GPIO 26//save *
* MISO ==> DI GPIO 25//master *
* MOSI ==> DO GPIO 26//master *
* CLK GPIO 24 *
* CS2 GPIO 29 *
*******************shuo ming******************************/
// while(1){
// for(i = 0; i < 4 ; i++){
// switch(i%4){
// case 0:{
// Config_Gpio0(1,29);//set cs ,
// udelay(200);
// Config_Gpio0(0,29);//set cs ,
// }
// case 1:{
// Config_Gpio0(1,25);//set Di ,//这里需将gpio配置成输出状态
// udelay(200);
// Config_Gpio0(0,25);//set Di ,
// }
// case 2:{
// Config_Gpio0(1,26);//set Do ,
// udelay(200);
// Config_Gpio0(0,26);//set Do,
// }
// case 3:{
// Config_Gpio0(1,24);//set CLk ,
// udelay(200);
// Config_Gpio0(0,24);//set CLK,
// }
// }
// }
// }
inited = 1;
if(SD_Overall_Initiation() == 0xff00) return 0;
}
此程序是在原loongson的基础上改来的。
内核中的路径:driver/block/sb2fsd_gpio.c
启动内核后,查看tf卡的方式为:fdisk -l /dev/sb2f_sd1,注意不是sb2f_sd。写这篇文章的原因是由于我不能在修改我上传的文章的说明了。