loongson利用gpio模拟spi测试TF卡的程序

#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。写这篇文章的原因是由于我不能在修改我上传的文章的说明了。


你可能感兴趣的:(loongson利用gpio模拟spi测试TF卡的程序)