rtfsprorelease/rtfsdrivers/sdcard_fixed/sdmmc.c
2016-06-05 16:09:54 -04:00

1536 lines
54 KiB
C

/*
* SDMMC.c
*
* Created on: Mar 29, 2011
* Author: Peter
*/
#include "sdmmc.h"
//#include "lpc214x.h"
#include "rtpstr.h"
#include "rtpprint.h"
#define DEBUG_SDCARD_DRIVER 0
#define SD_FORCE_MAX_BLOCK_COUNT_WRITE 0
#define SD_FORCE_MAX_BLOCK_COUNT_READ 0
#define MAXSDCARDS 1
#define DWSWAP(X) X
static int RtSdcard_Driver_Initialized;
SD_CARD_INFO mmc_sd_cards[MAXSDCARDS];
int RtSdBSP_Controller_Init(void);
void RtSdBSP_Delay_micros(unsigned long delay);
void RtSdBSP_Set_Clock(int Clock_rate );
int RtSdBSP_Set_BusWidth(SD_CARD_INFO *pmmc_sd_card, int width );
void RtSdBSP_CardInit( SD_CARD_INFO * pmmc_sd_card );
int RtSdBSP_SendCmd( unsigned long CmdIndex, unsigned long Argument, int ExpectResp, int AllowTimeout );
int RtSdBSP_GetCmdResp( int ExpectCmdData, int ExpectResp, unsigned long * CmdResp );
int RtSdBSP_Read_SCR(SD_CARD_INFO * mmc_sd_card);
void RtSdBSP_CardPushPullMode( SD_CARD_INFO * pmmc_sd_card );
int RtSdBSP_Read_BlockSetup(SD_CARD_INFO * mmc_sd_card,unsigned long blockNum);
int RtSdBSP_Read_BlockTransfer(SD_CARD_INFO * mmc_sd_card);
void RtSdBSP_Read_BlockShutdown(SD_CARD_INFO * mmc_sd_card);
int RtSdBSP_Write_BlockSetup(SD_CARD_INFO * mmc_sd_card,unsigned long blockNum);
void RtSdBSP_Write_BlockShutdown(SD_CARD_INFO * mmc_sd_card);
int RtSdBSP_Write_BlockTransfer(SD_CARD_INFO * mmc_sd_card);
static int RtSdcard_Media_Init(SD_CARD_INFO *pmmc_sd_card);
static int RtSdcard_Check_CID( SD_CARD_INFO * mmc_sd_card);
static int RtSdcard_Send_CSD( SD_CARD_INFO * mmc_sd_card);
static int RtSdcard_Set_Address(SD_CARD_INFO * mmc_sd_card);
static int RtSdcard_Select_Card(SD_CARD_INFO * mmc_sd_card, int is_specific_card);
static void RtSdcard_Display_Media_Type(SD_CARD_INFO *pmmc_sd_card);
static int RtSdcard_CardInit( SD_CARD_INFO * mmc_sd_card );
static int RtSdcard_Go_Idle_State( SD_CARD_INFO *pmmc_sd_card );
static int RtSdcard_Send_OP_Cond( SD_CARD_INFO *pmmc_sd_card );
static int RtSdcard_Send_ACMD_OP_Cond( SD_CARD_INFO *pmmc_sd_card );
static int RtSdcard_Send_ACMD( SD_CARD_INFO *pmmc_sd_card );
static int RtSdcard_Send_If_Cond( SD_CARD_INFO * mmc_sd_card );
static void parse_CID(SD_CARD_INFO * mmc_sd_card, unsigned long *respValue);
static void parse_CSD(SD_CARD_INFO * mmc_sd_card, unsigned long *respValue);
static void RtSdcard_Switch_Voltage(SD_CARD_INFO *pmmc_sd_card);
static int RtSdcard_Send_ACMD_Disconnect(SD_CARD_INFO *pmmc_sd_card);
int RtSdcard_Send_ACMD_SCR(SD_CARD_INFO *pmmc_sd_card );
static int RtSdcard_Send_ACMD_Bus_Width(SD_CARD_INFO *pmmc_sd_card, int bus_width);
static int RtSdcard_Set_BusWidth(SD_CARD_INFO *pmmc_sd_card, int buswidthflag); //MA
int RtSdcard_init(int unitnumber) /* Top level interface */
{
if (unitnumber>=MAXSDCARDS)
return -1;
if (!RtSdcard_Driver_Initialized)
{
int i;
RtSdcard_Driver_Initialized = 1;
rtp_memset(&mmc_sd_cards[0], 0, sizeof(mmc_sd_cards));
for (i = 0; i < MAXSDCARDS; i++)
{
mmc_sd_cards[i].card_operating_flags= 0;
mmc_sd_cards[i].card_type = CARD_UNKNOWN_TYPE;
mmc_sd_cards[i].state = INACTIVE_STATE;
}
if (RtSdBSP_Controller_Init()!=0) /* Target specific initialization (pinconfig, clocks etc) */
return -1;
RtSdcard_Driver_Initialized = 1;
}
if (RtSdcard_Media_Init(&mmc_sd_cards[unitnumber])!=0) /* Standard device independent initialization */
return -1;
return 0;
}
int RtSdcard_device_media_parms(int unitnumber, unsigned long *nSectors, unsigned long *BytesPerSector, int *isReadOnly)
{
if (unitnumber>=MAXSDCARDS)
return -1;
*isReadOnly = 0;
*nSectors = mmc_sd_cards[unitnumber].no_blocks;
*BytesPerSector = mmc_sd_cards[unitnumber].bytes_per_block;
return 0;
}
static int RtSdcard_Media_Init(SD_CARD_INFO *pmmc_sd_card)
{
pmmc_sd_card->card_type = CARD_UNKNOWN_TYPE;
pmmc_sd_card->card_operating_flags= 0;
pmmc_sd_card->state = INACTIVE_STATE;
if (RtSdcard_CardInit( pmmc_sd_card ) != 0)
return -1;
RtSdcard_Display_Media_Type(pmmc_sd_card);
if( pmmc_sd_card->card_type == CARD_UNKNOWN_TYPE)
return -1; //for now return, no card is inserted, or we don't support that card
pmmc_sd_card->card_operating_flags |= SDFLGINSERTED;
RtSdcard_Switch_Voltage(pmmc_sd_card); /* Switch to 1.8 volts if supported by the controller */
/*We do this for each card we have, on the Olemix board we only have one SD card supported, if we have
* more (i.e. have more than one CMD line for the SD interface, then we loop throught these, and issue
* CMD2 followed by CMD3 for each card) */
/* Send CMD2 */
if (RtSdcard_Check_CID( pmmc_sd_card) != 0) /* Check Card information description, manufacturer et al. */
goto CARD_INITIALIZATION_FAILED;
if (RtSdcard_Set_Address(pmmc_sd_card) != 0) /* Set card address for this device */
goto CARD_INITIALIZATION_FAILED;
if (RtSdcard_Send_CSD(pmmc_sd_card) != 0) /* Check card specific data (operating range, capacity etc.) */
goto CARD_INITIALIZATION_FAILED;
if (RtSdcard_Select_Card(pmmc_sd_card, 1) != 0) /* Switch card to xfer state */
goto CARD_INITIALIZATION_FAILED;
RtSdBSP_CardPushPullMode(pmmc_sd_card ); /* Transfer the rest in push pull mode */
if (RtSdcard_Send_ACMD_Disconnect(pmmc_sd_card) != 0) /* Disconnect pullup resistor so it can enter hd mode */
goto CARD_INITIALIZATION_FAILED;
/* send SCR , can easily removed*/
//if (RtSdcard_Send_ACMD_SCR(pmmc_sd_card ) != 0)
// goto CARD_INITIALIZATION_FAILED;
/* Sets up
SDFLGMULTIBLOCK
SDFLGBLOCKCOUNT
SDFLGHIGHSPEED
SDFLG4BITMODE
*/
if (RtSdBSP_Read_SCR(pmmc_sd_card)!=0)
goto CARD_INITIALIZATION_FAILED;
if (( pmmc_sd_card->card_type == SD_CARD_TYPE ) || ( pmmc_sd_card->card_type == SDHC_CARD_TYPE ) || ( pmmc_sd_card->card_type == SDXC_CARD_TYPE ))
{
if (pmmc_sd_card->card_operating_flags&SDFLGHIGHSPEED)
RtSdBSP_Set_Clock(1);
else
RtSdBSP_Set_Clock(0); // TBD do we have to do this a second time ?
if (pmmc_sd_card->card_operating_flags&SDFLG4BITMODE)
{
if (RtSdcard_Set_BusWidth( pmmc_sd_card, 4 ) != 0)
goto CARD_INITIALIZATION_FAILED; /* fatal error */
}
}
return 0;
CARD_INITIALIZATION_FAILED:
rtp_printf("Card initialization failed\n");
pmmc_sd_card->card_type = CARD_UNKNOWN_TYPE;
pmmc_sd_card->card_operating_flags = 0;
pmmc_sd_card->state = INACTIVE_STATE;
return -1;
}
static void RtSdcard_Display_Media_Type(SD_CARD_INFO *pmmc_sd_card)
{
if( pmmc_sd_card->card_type == CARD_UNKNOWN_TYPE)
{
rtp_printf("Card Type is Unknown, or no card is inserted... need to check how to check for inserted card \n \r");
}
else if(pmmc_sd_card->card_type == MMC_CARD_TYPE )
{
rtp_printf("An MMC card is inserted \n \r");
}
else
{
if(pmmc_sd_card->card_type == SD_CARD_TYPE )
rtp_printf("An Standard SD card is inserted \n \r");
else
{
if(( pmmc_sd_card->card_type == SDHC_CARD_TYPE )||( pmmc_sd_card->card_type == SDXC_CARD_TYPE ))
{
rtp_printf("An Standard SDHC || SDXC card is inserted \n \r");
}
}
}
}
/******************************************************************************
** Function name: RtSdcard_Set_BusWidth
**
** Descriptions: 1-bit bus or 4-bit bus.
**
** parameters: bus width
** Returned value: TRUE or FALSE
**
******************************************************************************/
static int RtSdcard_Set_BusWidth(SD_CARD_INFO *pmmc_sd_card, int width )
{
RtSdBSP_Set_BusWidth(pmmc_sd_card,width);
if ( width == 4 )
{
return RtSdcard_Send_ACMD_Bus_Width(pmmc_sd_card, 0x2 );
}
return 0;
}
/******************************************************************************
** Function name: RtSdcard_CardInit
**
** Descriptions:
**
** parameters:
** Returned value:
**
******************************************************************************/
static int RtSdcard_CardInit( SD_CARD_INFO * pmmc_sd_card )
{
if (RtSdcard_Go_Idle_State(pmmc_sd_card) != 0)
return -1;
RtSdBSP_CardInit( pmmc_sd_card );
/* Try CMD1 first for MMC, if it's timeout, try CMD55 and CMD41 for SD, if both failed, initialization faliure, bailout. */
/*MCI_SendCmd( SEND_OP_COND, OCR_INDEX, EXPECT_SHORT_RESP, 0 ); */
if(RtSdcard_Send_If_Cond(pmmc_sd_card) == 0 )////SDXC condition
{
RtSdBSP_Delay_micros(30000);
pmmc_sd_card->card_type = SDHC_CARD_TYPE;
return RtSdcard_Send_ACMD_OP_Cond( pmmc_sd_card);
}
if (RtSdcard_Go_Idle_State(pmmc_sd_card) == -1)
return -1;
if ( RtSdcard_Send_OP_Cond(pmmc_sd_card) == 0)
{
pmmc_sd_card->card_type = MMC_CARD_TYPE;
return 0; /* Found the card, it's a MMC */
}
else
{
if ( RtSdcard_Send_ACMD_OP_Cond(pmmc_sd_card) == 0)
{
pmmc_sd_card->card_type = SD_CARD_TYPE;
return 0; /* Found the card, it's a SD */
}
}
return -1;
}
static int RtSdcard_Go_Idle_State( SD_CARD_INFO *pmmc_sd_card )
{
int retries;
unsigned long respStatus;
unsigned long respValue[4];
for (retries = 0; retries < 32; retries++)
{
/* Send CMD0 command repeatedly until the response is back correctly */
RtSdBSP_SendCmd( GO_IDLE_STATE, 0x00000000, EXPECT_NO_RESP, 0 );
respStatus = RtSdBSP_GetCmdResp(GO_IDLE_STATE, EXPECT_NO_RESP, &respValue[0] );
if (respStatus == 0 )
{
pmmc_sd_card->state = IDLE_STATE;
return 0;
}
}
return -1;
}
static int RtSdcard_Send_OP_Cond( SD_CARD_INFO *pmmc_sd_card )
{
int retries;
int respStatus;
unsigned long respValue[4];
for (retries = 0; retries < 0x200; retries++)
{
/* Send CMD1 command repeatedly until the response is back correctly */
RtSdBSP_SendCmd( SEND_OP_COND, OCR_INDEX, EXPECT_SHORT_RESP, 0 );
respStatus = RtSdBSP_GetCmdResp( SEND_OP_COND, EXPECT_SHORT_RESP, &respValue[0] );
/* bit 0 and bit 2 must be zero, or it's timeout or CRC error */
if ( (respStatus == 0) && (respValue[0] & 0x80000000) )
return 0; /* response is back and correct. */
RtSdBSP_Delay_micros(100);
}
return -1;
}
static int RtSdcard_Send_ACMD_OP_Cond( SD_CARD_INFO *pmmc_sd_card )
{
int retries;
int respStatus;
unsigned long respValue[4];
/* timeout on SEND_OP_COND command on MMC, now, try SEND_APP_OP_COND
command to SD */
for (retries = 0; retries < 512; retries++)
{
RtSdBSP_Delay_micros(3000);
if ( RtSdcard_Send_ACMD(pmmc_sd_card ) == -1)//??
{
continue;
}
/* Send ACMD41 command repeatedly until the response is back correctly */
RtSdBSP_SendCmd( SEND_APP_OP_COND, OCR_INDEX_SDHC_SDHX, EXPECT_SHORT_RESP, 0 );
respStatus = RtSdBSP_GetCmdResp( SEND_APP_OP_COND, EXPECT_SHORT_RESP, &respValue[0] );
if ( (respStatus == 0) && (respValue[0] & 0x80000000) ) /* TODO:Check the response of SD, SDHC and SHXC and compare against the return value for each, SDHC and SDXC will have the CCS bit set,
as well as the bit 31 */
{
pmmc_sd_card->state = READY_STATE;
return 0; /* response is back and correct. */
}
RtSdBSP_Delay_micros(200);
}
return -1;
}
/******************************************************************************
** Function name: RtSdcard_Send_ACMD
**
** Descriptions:
**
** parameters:
** Returned value:
**
******************************************************************************/
static int RtSdcard_Send_ACMD( SD_CARD_INFO *pmmc_sd_card )
{
int retries;
unsigned long CmdArgument;
int respStatus;
unsigned long respValue[4];
if ( (pmmc_sd_card->card_type == SD_CARD_TYPE) || (pmmc_sd_card->card_type == SDHC_CARD_TYPE) || (pmmc_sd_card->card_type == SDXC_CARD_TYPE) )
{
CmdArgument = pmmc_sd_card->RCA; /* Use the address from SET_RELATIVE_ADDR cmd */
}
else /* if MMC or unknown card type, use 0x0. */
{
CmdArgument = 0x00000000;
}
for (retries = 0; retries < 32; retries++)
{
/* Send CMD55 command followed by an ACMD */
RtSdBSP_SendCmd( APP_CMD, CmdArgument, EXPECT_SHORT_RESP, 0 );
respStatus = RtSdBSP_GetCmdResp( APP_CMD, EXPECT_SHORT_RESP, &respValue[0] );
if ( respStatus==0 && (respValue[0] & CARD_STATUS_ACMD_ENABLE) ) /* Check if APP_CMD enabled */
return 0;
RtSdBSP_Delay_micros(200);
}
return -1;
}
/******************************************************************************
** Function name: RtSdcard_Send_ACMD_Bus_Width
**
** Descriptions: ACMD6, SET_BUS_WIDTH, if it's SD card, we can
** use the 4-bit bus instead of 1-bit. This cmd
** can only be called during TRANS state.
** Since it's a ACMD, CMD55 APP_CMD needs to be
** sent out first.
**
** parameters: Bus width value, 1-bit is 0, 4-bit is 10
** Returned value: true or false, true if the card is still in the
** TRANS state after the cmd.
**
******************************************************************************/
static int RtSdcard_Send_ACMD_Bus_Width(SD_CARD_INFO *pmmc_sd_card, int buswidth )
{
int retries;
unsigned long respStatus;
unsigned long respValue[4];
for (retries = 0; retries < 32; retries++)
{
if ( RtSdcard_Send_ACMD(pmmc_sd_card) == -1 )
continue;
/* Send ACMD6 command to set the bus width */
RtSdBSP_SendCmd( SET_ACMD_BUS_WIDTH, buswidth, EXPECT_SHORT_RESP, 0 );
respStatus = RtSdBSP_GetCmdResp( SET_ACMD_BUS_WIDTH, EXPECT_SHORT_RESP, &respValue[0] );
if ( respStatus==0 && ((respValue[0] & (0x0F << 8)) == 0x0900) )
return 0; /* response is back and correct. */
RtSdBSP_Delay_micros(200);
}
return -1;
}
/*****************************************************************************
** Function name: RtSdcard_Send_Status
**
** Descriptions: CMD13, SEND_STATUS, the most important cmd to
** debug the state machine of the card.
**
** parameters: None
** Returned value: Response value(card status), true if the ready bit
** is set in the card status register, if timeout, return
** INVALID_RESPONSE 0xFFFFFFFF.
**
******************************************************************************/
/* CMD13 */
static unsigned long RtSdcard_Send_Status( SD_CARD_INFO * mmc_sd_card )
{
int retries;
int respStatus;
unsigned long respValue[4];
unsigned long CmdArgument;
if (( mmc_sd_card->card_type == SD_CARD_TYPE ) || ( mmc_sd_card->card_type == SDHC_CARD_TYPE ) || ( mmc_sd_card->card_type == SDXC_CARD_TYPE ))
CmdArgument = mmc_sd_card->RCA;
else /* if MMC or unknown card type, use default RCA addr. */
CmdArgument = 0x00010000;
/* Note that, since it's called after the block write and read, this timeout
is important based on the clock you set for the data communication. */
for (retries = 0; retries < 0x2000; retries++)
{
/* Send SELECT_CARD command before read and write */
RtSdBSP_SendCmd( SEND_STATUS, CmdArgument, EXPECT_SHORT_RESP, 0 );
respStatus = RtSdBSP_GetCmdResp( SEND_STATUS, EXPECT_SHORT_RESP, &respValue[0] );
if ( respStatus==0 && (respValue[0] & (1 << 8)) )
{ /* The ready bit should be set, it should be in either TRAN or RCV state now */
return ( respValue[0] );
}
RtSdBSP_Delay_micros(200);
}
return ( INVALID_RESPONSE );
}
/*****************************************************************************
** Function name: RtSdcard_Check_CID
**
** Descriptions:
**
** parameters:
** Returned value:
**
******************************************************************************/
static int RtSdcard_Check_CID( SD_CARD_INFO * mmc_sd_card)
{
int retries;
int respStatus;
unsigned long respValue[4];
/* This command is normally after CMD1(MMC) or ACMD41(SD) or CMD11 if board supports 1.8V signaling and SDHC/SDXC */
for (retries = 0; retries < 0x20; retries++)
{
/* Send CMD2 command repeatedly until the response is back correctly */
RtSdBSP_SendCmd( ALL_SEND_CID, 0, EXPECT_LONG_RESP, 0 );
respStatus = RtSdBSP_GetCmdResp( ALL_SEND_CID, EXPECT_LONG_RESP, &respValue[0] );
/* bit 0 and bit 2 must be zero, or it's timeout or CRC error */
if ( respStatus == 0)
{
parse_CID(mmc_sd_card, &respValue[0]);
mmc_sd_card->state = IDENTIFICATION_STATE;
return 0; /* response is back and correct. */
}
RtSdBSP_Delay_micros(200);
}
return -1;
}
/******************************************************************************
** Function name: RtSdcard_Set_Address
**
** Descriptions: Send CMD3, STE_RELATIVE_ADDR, should after CMD2
**
** parameters:
** Returned value: TRUE if response is back before timeout.
**
******************************************************************************/
static int RtSdcard_Set_Address( SD_CARD_INFO * mmc_sd_card )
{
int retries;
int respStatus;
unsigned long respValue[4];
unsigned long CmdArgument;
/* If it's a SD card, SET_RELATIVE_ADDR is to get the address
from the card and use this value in RCA, if it's a MMC, set default
RCA addr. 0x00010000. */
if (( mmc_sd_card->card_type == SD_CARD_TYPE ) || ( mmc_sd_card->card_type == SDHC_CARD_TYPE ) || ( mmc_sd_card->card_type == SDXC_CARD_TYPE ))
{
//CmdArgument = 0;
CmdArgument = mmc_sd_card->RCA;
}
else /* If it's unknown or MMC_CARD, fix the RCA address */
{
CmdArgument = 0x00010000;
}
for (retries = 0; retries < 0x20; retries++)
{
/* Send CMD3 command repeatedly until the response is back correctly */
RtSdBSP_SendCmd( SET_RELATIVE_ADDR, CmdArgument, EXPECT_SHORT_RESP, 0 );
respStatus = RtSdBSP_GetCmdResp( SET_RELATIVE_ADDR, EXPECT_SHORT_RESP, &respValue[0] );
/* bit 0 and bit 2 must be zero, or it's timeout or CRC error */
/* It should go to IDEN state and bit 8 should be 1 */
/* The second condition ((respValue[0] & (0x0F << 8)) == 0x0700) ) is added if we alreay issued CMD3 and then reissued it to the same card,
* it should be ok, the only difference the first time we issue CMD3 we were in iden state and we go to stdby, second case we are in stdby
* and stay @ stdby */
if ( respStatus ==0 && (((respValue[0] & (0x0F << 8)) == 0x0500) || ((respValue[0] & (0x0F << 8)) == 0x0700) ) )
{
mmc_sd_card->RCA = respValue[0] & 0xffff0000;
if(mmc_sd_card->state == IDENTIFICATION_STATE || (mmc_sd_card->state == STANDBY_STATE) )
mmc_sd_card->state = STANDBY_STATE;
return 0; /* response is back and correct. */
}
RtSdBSP_Delay_micros(200);
}
return -1;
}
/* CMD9 */
/******************************************************************************
** Function name: RtSdcard_Send_CSD
**
** Descriptions:
**
** parameters:
** Returned value:
**
******************************************************************************/
static int RtSdcard_Send_CSD( SD_CARD_INFO * mmc_sd_card )
{
int retries;
int respStatus;
unsigned long respValue[4];
unsigned long CmdArgument;
if (( mmc_sd_card->card_type == SD_CARD_TYPE ) || ( mmc_sd_card->card_type == SDHC_CARD_TYPE ) || ( mmc_sd_card->card_type == SDXC_CARD_TYPE ))
CmdArgument = mmc_sd_card->RCA;
else /* if MMC or unknown card type, use default RCA addr. */
CmdArgument = 0x00010000;
for (retries = 0; retries < 0x20; retries++)
{
/* Send SET_BLOCK_LEN command before read and write */
/* Send SELECT_CARD command before read and write */
RtSdBSP_SendCmd( SEND_CSD, CmdArgument, EXPECT_LONG_RESP, 0 );
respStatus = RtSdBSP_GetCmdResp( SEND_CSD, EXPECT_LONG_RESP, &respValue[0] );
if ( !respStatus )
{
parse_CSD(mmc_sd_card, &respValue[0]);
return 0;
}
RtSdBSP_Delay_micros(200);
}
return -1;
}
/* CMD7 */
/******************************************************************************
** Function name: RtSdcard_Select_Card
**
** Descriptions:
**
** parameters:
** Returned value:
**
******************************************************************************/
static int RtSdcard_Select_Card( SD_CARD_INFO * mmc_sd_card , int is_specific_card)
{
int retries;
int respStatus;
unsigned long respValue[4];
int CmdArgument;
if(is_specific_card)
{
if ( ( mmc_sd_card->card_type == SD_CARD_TYPE ) || ( mmc_sd_card->card_type == SDHC_CARD_TYPE ) || ( mmc_sd_card->card_type == SDXC_CARD_TYPE ) )
{
CmdArgument = mmc_sd_card->RCA;
}
else /* if MMC or unknown card type, use default RCA addr. */
{
CmdArgument = 0x00010000;
}
}
else
CmdArgument =0;
for (retries = 0; retries < 0x20; retries++)
{
/* Send SELECT_CARD command before read and write */
RtSdBSP_SendCmd( SELECT_CARD, CmdArgument, EXPECT_SHORT_RESP, 0 );
respStatus = RtSdBSP_GetCmdResp( SELECT_CARD, EXPECT_SHORT_RESP, &respValue[0] );
if ( (respStatus==0) && ((respValue[0] & (0x0F << 8)) == 0x0700 ))
{ /* Should be in STANDBY state now and ready */
if(is_specific_card)
{
if(mmc_sd_card->state == STANDBY_STATE)
mmc_sd_card->state = TRANSFER_STATE;
else{
if(mmc_sd_card->state == DISCONNECT_STATE)
mmc_sd_card->state = PROGRAMMING_STATE;
}
}
else //!is_specific_card
{
if(mmc_sd_card->state == PROGRAMMING_STATE)
mmc_sd_card->state = DISCONNECT_STATE;
}
return 0;
}
RtSdBSP_Delay_micros(200);
}
return -1;
}
/******************************************************************************
** Function name: RtSdcard_Send_BlockCount
**
** Descriptions: CMD23, SET_BLOCK_COUNT
**
** parameters:
** Returned value: true or false, true if, at least, the card status
** shows ready bit is set.
**
******************************************************************************/
/* CMD23 */
int RtSdcard_Send_BlockCount( SD_CARD_INFO * mmc_sd_card, unsigned long block_count )
{
int retries;
unsigned long respStatus;
unsigned long respValue[4];
for (retries = 0; retries < 0x20; retries++)
{
RtSdBSP_SendCmd( SET_BLOCK_COUNT, block_count, EXPECT_SHORT_RESP, 1 );
respStatus = RtSdBSP_GetCmdResp( SET_BLOCK_COUNT, EXPECT_SHORT_RESP, &respValue[0] );
/* ready bit, bit 8, should be set in the card status register */
if ( !respStatus && (respValue[0] & (1 << 8)) )
return 0;
RtSdBSP_Delay_micros(200);
}
return -1;
}
/******************************************************************************
** Function name: RtSdcard_Send_Stop
**
** Descriptions: CMD12, STOP_TRANSMISSION. if that happens, the card is
** maybe in a unknown state that need a warm reset.
**
** parameters:
** Returned value: true or false, true if, at least, the card status
** shows ready bit is set.
**
******************************************************************************/
/* CMD12 MCI SEND_STOP */
int RtSdcard_Send_Stop( SD_CARD_INFO * mmc_sd_card )
{
int retries;
unsigned long respStatus;
unsigned long respValue[4];
for (retries = 0; retries < 0x20; retries++)
{
RtSdBSP_SendCmd( STOP_TRANSMISSION, 0x00000000, EXPECT_SHORT_RESP, 0 );
respStatus = RtSdBSP_GetCmdResp( STOP_TRANSMISSION, EXPECT_SHORT_RESP, &respValue[0] );
/* ready bit, bit 8, should be set in the card status register */
if ( !respStatus && (respValue[0] & (1 << 8)) )
return 0;
RtSdBSP_Delay_micros(200);
}
return -1;
}
/******************************************************************************
** Function name: RtSdcard_Send_Read_Block
**
** Descriptions: CMD17, READ_SINGLE_BLOCK, send this cmd in the TRANS
** state to read a block of data from the card.
**
** parameters: ,block number
** Returned value: Response value
**
******************************************************************************/
/* CMD17 READ_SINGLE_BLOCK */
int RtSdcard_Send_Read_Block( SD_CARD_INFO * mmc_sd_card , unsigned long blockNum, unsigned long blk_len )
{
int retries;
int respStatus;
unsigned long respValue[4];
unsigned long block_arg;
/* HC and XC cards use sector orietend addressing, early versions use bytes */
if ( ( mmc_sd_card->card_type == SDHC_CARD_TYPE ) ||( mmc_sd_card->card_type == SDXC_CARD_TYPE ) )
block_arg = blockNum;
else /* if ( mmc_sd_card->card_type == SD_CARD_TYPE ) */
block_arg = blockNum * BLOCK_LENGTH;
for (retries = 0; retries < 0x20; retries++)
{
RtSdBSP_SendCmd( READ_SINGLE_BLOCK, block_arg, EXPECT_SHORT_RESP, 0 );
respStatus = RtSdBSP_GetCmdResp( READ_SINGLE_BLOCK, EXPECT_SHORT_RESP, &respValue[0] );
/* it should be in the transfer state, bit 9~12 is 0x0100 and bit 8 is 1 */
if ( respStatus==0 && ((respValue[0] & (0x0F << 8)) == 0x0900) )
{
return 0; /* ready and in TRAN state */
// PVOPVO - Do state transition
}
RtSdBSP_Delay_micros(200);
}
return -1; /* Fatal error */
}
/* CMD 24 */
int RtSdcard_Send_Write_Block( SD_CARD_INFO * mmc_sd_card, unsigned long blockNum)
{
int retries;
int respStatus;
unsigned long respValue[4];
unsigned long block_arg;
/* HC and XC cards use sector orietend addressing, early versions use bytes */
if ( ( mmc_sd_card->card_type == SDHC_CARD_TYPE ) ||( mmc_sd_card->card_type == SDXC_CARD_TYPE ) )
block_arg = blockNum;
else /* if ( mmc_sd_card->card_type == SD_CARD_TYPE ) */
block_arg = blockNum * BLOCK_LENGTH;
for (retries = 0; retries < 0x20; retries++)
{
RtSdBSP_SendCmd( WRITE_BLOCK, block_arg, EXPECT_SHORT_RESP, 0 );
respStatus = RtSdBSP_GetCmdResp( WRITE_BLOCK, EXPECT_SHORT_RESP, &respValue[0] );
/* it should be in the transfer state, bit 9~12 is 0x0100 and bit 8 is 1 */
if ( !respStatus && ((respValue[0] & (0x0F << 8)) == 0x0900) )
{
return 0; /* ready and in TRAN state */
// PVOPVO - Do state transition
}
RtSdBSP_Delay_micros(200);
}
return -1; /* Fatal error */
}
/* SEND_IF_COND */
static int RtSdcard_Send_If_Cond( SD_CARD_INFO * mmc_sd_card ) /* SEND_IF_COND does not take arguments ?? */
{
int retries;
int respStatus;
unsigned long respValue[4];
for (retries = 0; retries < 0x200; retries++)
{
/* CMD8 */
RtSdBSP_SendCmd( SEND_IF_COND, SEND_IF_COND_ARG, EXPECT_SHORT_RESP, 0 );
respStatus = RtSdBSP_GetCmdResp( SEND_IF_COND, EXPECT_SHORT_RESP, &respValue[0] );
if ( (respStatus==0) && (respValue[0] & 0x1AA) )
{
mmc_sd_card->card_type = SDHC_CARD_TYPE;
mmc_sd_card->state = IDLE_STATE;
return 0; /* response is back and correct. */
}
RtSdBSP_Delay_micros(200);
}
return -1;
}
/******************************************************************************
** Function name: RtSdcard_Send_Read_Multiple_Block
**
** Descriptions: CMD18, READ_MULTIPLE_BLOCK, continuously transfers data
** blocks from card to host until interrupted by STOP_TRA-
** NSMISSION (CMD12) command. block lenght specified the
** smae as READ_SINGLE_BLOCK command
**
** parameters: block number/address
** Returned value: Response value/R1
**
******************************************************************************/
int RtSdcard_Send_Read_Multiple_Block( SD_CARD_INFO * mmc_sd_card , unsigned long blockNum )
{
int retries;
int respStatus;
unsigned long respValue[4];
unsigned long block_arg;
/* HC and XC cards use sector orietend addressing, early versions use bytes */
if ( ( mmc_sd_card->card_type == SDHC_CARD_TYPE ) ||( mmc_sd_card->card_type == SDXC_CARD_TYPE ) )
block_arg = blockNum;
else /* if ( mmc_sd_card->card_type == SD_CARD_TYPE ) */
block_arg = blockNum * BLOCK_LENGTH;
for (retries = 0; retries < 0x20; retries++)
{
RtSdBSP_SendCmd( READ_MULTIPLE_BLOCK, block_arg, EXPECT_SHORT_RESP, 0 );
respStatus = RtSdBSP_GetCmdResp( READ_MULTIPLE_BLOCK, EXPECT_SHORT_RESP, &respValue[0] );
/* it should be in the transfer state, bit 9~12 is 0x0100 and bit 8 is 1 */
if ( !respStatus && ((respValue[0] & (0x0F << 8)) == 0x0900) )
{
return 0; /* ready and in TRAN state */
}
RtSdBSP_Delay_micros(200);
}
return -1; /* Fatal error */
}
/* CMD 25 */
int RtSdcard_Send_Write_Multiple_Block( SD_CARD_INFO * mmc_sd_card, unsigned long blockNum)
{
int retries;
int respStatus;
unsigned long respValue[4];
unsigned long block_arg;
/* HC and XC cards use sector orietend addressing, early versions use bytes */
if ( ( mmc_sd_card->card_type == SDHC_CARD_TYPE ) ||( mmc_sd_card->card_type == SDXC_CARD_TYPE ) )
block_arg = blockNum;
else /* if ( mmc_sd_card->card_type == SD_CARD_TYPE ) */
block_arg = blockNum * BLOCK_LENGTH;
for (retries = 0; retries < 0x20; retries++)
{
RtSdBSP_SendCmd( WRITE_MULTIPLE_BLOCK, block_arg, EXPECT_SHORT_RESP, 0 );
respStatus = RtSdBSP_GetCmdResp( WRITE_MULTIPLE_BLOCK, EXPECT_SHORT_RESP, &respValue[0] );
/* it should be in the transfer state, bit 9~12 is 0x0100 and bit 8 is 1 */
if ( !respStatus && ((respValue[0] & (0x0F << 8)) == 0x0900) )
{
return 0; /* ready and in TRAN state */
// PVOPVO - Do state transition
}
RtSdBSP_Delay_micros(200);
}
return -1; /* Fatal error */
}
int RtSdcard_CheckStatus( SD_CARD_INFO * mmc_sd_card ) /*check this function */
{
unsigned long respValue;
while ( 1 )
{
if ( (respValue = RtSdcard_Send_Status(mmc_sd_card)) == INVALID_RESPONSE )
{
break;
}
else
{
/* The only valid state is TRANS per MMC and SD state diagram.
RCV state may be seen, but, I have found that it happens
only when TX_ACTIVE or RX_ACTIVE occurs before the WRITE_BLOCK and
READ_BLOCK cmds are being sent, which is not a valid sequence. */
if ( (respValue & (0x0F << 8)) == 0x0900 )
{
return 0;
}
}
}
return -1;
}
/******************************************************************************
** Function name: RtSdcard_Write_Block
**
** Descriptions: Set MMCSD data control register, data length and data
** timeout, send WRITE_BLOCK cmd, finally, enable
** interrupt. On completion of WRITE_BLOCK cmd, TX_ACTIVE
** interrupt will occurs, data can be written continuously
** into the FIFO until the block data length is reached.
**
** parameters: block number
** Returned value: true or false, if cmd times out, return false and no
** need to continue.
**
******************************************************************************/
static int _RtSdcard_DoWrite_Block(SD_CARD_INFO * mmc_sd_card,unsigned long blockNum);
unsigned long RtSdcard_Write_Block(int unitnumber, unsigned long blockNum, unsigned long blockCount, unsigned char *Buffer)
{
SD_CARD_INFO * mmc_sd_card;
unsigned long xferrbuff[128] ;
unsigned long *pBuffer;
int r;
if (unitnumber>=MAXSDCARDS)
return -1;
mmc_sd_card = &mmc_sd_cards[unitnumber];
#if (SD_FORCE_MAX_BLOCK_COUNT_WRITE)
blockCount=SD_FORCE_MAX_BLOCK_COUNT_WRITE;
#endif
if ((unsigned long)Buffer & 0x3)
{
rtp_memcpy(&xferrbuff[0], Buffer, 512);
pBuffer=(unsigned long *)&xferrbuff[0];
blockCount=1;
}
else
pBuffer = (unsigned long *)Buffer;
mmc_sd_card->blk_buffer=(unsigned long *) pBuffer;
mmc_sd_card->blocks_transfered=0;
mmc_sd_card->blocks_to_transfer=blockCount;
r=_RtSdcard_DoWrite_Block(mmc_sd_card, blockNum);
if (r < 0)
{
rtp_printf("RtSdBSP_Write_Block failed\n");
return 0;
}
return mmc_sd_card->blocks_transfered;
}
static int _RtSdcard_DoWrite_Block(SD_CARD_INFO * mmc_sd_card,unsigned long blockNum)
{
/* Make sure the card is in TRANS state card. */
if (RtSdcard_CheckStatus(mmc_sd_card) != 0 )
{
RtSdcard_Send_Stop(mmc_sd_card);
return -1;
}
if (RtSdBSP_Write_BlockSetup(mmc_sd_card,blockNum)!=0)
return -1;
/* In polled mode interrupts are disabled until RtSdBSP_Read_BlockShutdown */
if (mmc_sd_card->card_operating_flags & SDFLGMULTIBLOCK)
{
if (mmc_sd_card->card_operating_flags & SDFLGBLOCKCOUNT)
{
if (RtSdcard_Send_BlockCount( mmc_sd_card, mmc_sd_card->blocks_to_transfer) != 0)
goto error_return;
}
if (RtSdcard_Send_Write_Multiple_Block(mmc_sd_card, blockNum) != 0)
goto error_return;
}
else
{
if (RtSdcard_Send_Write_Block( mmc_sd_card, blockNum) != 0)
goto error_return;
}
if (RtSdBSP_Write_BlockTransfer(mmc_sd_card)!=0)
goto error_return;
if (mmc_sd_card->card_operating_flags & SDFLGMULTIBLOCK)
{
if ((mmc_sd_card->card_operating_flags & SDFLGBLOCKCOUNT)==0)
{
/* Stop the transfer */
RtSdcard_Send_Stop(mmc_sd_card);
}
}
RtSdBSP_Write_BlockShutdown(mmc_sd_card);
/* Check Status after Transfer to be sure it completed */
if (RtSdcard_CheckStatus(mmc_sd_card) != 0 )
{
rtp_printf("RtSdBSP_Write_Block: CheckStatus failed after transfer\n");
RtSdcard_Send_Stop(mmc_sd_card);
return -1;
}
return 0;
error_return:
RtSdBSP_Write_BlockShutdown(mmc_sd_card);
return -1;
}
static int _RtSdcard_DoRead_Block(SD_CARD_INFO * mmc_sd_card,unsigned long blockNum);
unsigned long RtSdcard_Read_Block(int unit_number, unsigned long blockNum,unsigned long blockCount, unsigned char *Buffer)
{
SD_CARD_INFO * mmc_sd_card;
int use_xferrbuff=0;
unsigned long xferrbuff[128] ;
unsigned char *pBbuffer=Buffer;
#if (SD_FORCE_MAX_BLOCK_COUNT_READ)
blockCount=SD_FORCE_MAX_BLOCK_COUNT_READ;
#endif
if ((unsigned long)pBbuffer & 0x3)
{
pBbuffer = (unsigned char *)&xferrbuff[0];
use_xferrbuff=1;
blockCount=1;
}
if (unit_number>=MAXSDCARDS)
return 0;
mmc_sd_card = &mmc_sd_cards[unit_number];
mmc_sd_card->blk_buffer=(unsigned long *) pBbuffer;
mmc_sd_card->blocks_transfered=0;
mmc_sd_card->blocks_to_transfer=blockCount;
if (_RtSdcard_DoRead_Block(mmc_sd_card, blockNum)==-1)
return 0;
if (use_xferrbuff)
rtp_memcpy(Buffer, &xferrbuff[0], 512);
return mmc_sd_card->blocks_transfered;
}
static int _RtSdcard_DoRead_Block(SD_CARD_INFO * mmc_sd_card,unsigned long blockNum)
{
/* Make sure the card is in TRANS state card. */
if (RtSdcard_CheckStatus(mmc_sd_card) != 0 )
{
RtSdcard_Send_Stop(mmc_sd_card);
return -1;
}
if (RtSdBSP_Read_BlockSetup(mmc_sd_card,blockNum)!=0)
return -1;
/* In polled mode interrupts are disabled until RtSdBSP_Read_BlockShutdown */
if (mmc_sd_card->card_operating_flags & SDFLGMULTIBLOCK)
{
if ((mmc_sd_card->card_operating_flags & SDFLGBLOCKCOUNT))
{
if (RtSdcard_Send_BlockCount( mmc_sd_card, mmc_sd_card->blocks_to_transfer) != 0)
goto error_return;
}
if (RtSdcard_Send_Read_Multiple_Block(mmc_sd_card, blockNum) != 0)
goto error_return;
}
else
{
if (RtSdcard_Send_Read_Block( mmc_sd_card, blockNum, BLOCK_LENGTH ) != 0)
goto error_return;
}
if (RtSdBSP_Read_BlockTransfer(mmc_sd_card)!=0)
goto error_return;
if (mmc_sd_card->card_operating_flags & SDFLGMULTIBLOCK)
{
if ((mmc_sd_card->card_operating_flags & SDFLGBLOCKCOUNT)==0)
{
/* Stop the transfer */
RtSdcard_Send_Stop(mmc_sd_card);
}
}
RtSdBSP_Read_BlockShutdown(mmc_sd_card);
return 0;
error_return:
RtSdBSP_Read_BlockShutdown(mmc_sd_card);
return -1;
}
static void RtSdcard_Switch_Voltage(SD_CARD_INFO *pmmc_sd_card)
{
//send Command 11
//have to check on the response of ACMD41 for SR18A (Bit 24 of the R3(OCR) )
#if(SUPPORT_1_8_VOLT)
if( MCI_VoltageSwitch() == -1)
{
rtp_printf("Voltage switch to 1.8V failed?! \n \r");
}
#endif
}
#if(SUPPORT_1_8_VOLT)
static int RtSdcard_VoltageSwitch( void )
{
//using MCI_Go_Idle_State( void ) and MCI_Send_Status (void) to prototype
int retries;
int respStatus;
unsigned long respValue[4];
unsigned long cmd_index=0;
for (retries = 0; retries < 0x200; retries++)
{
/* Send CMD11 command repeatedly until the response is back correctly */
RtSdBSP_ClearStatus(mmc_sd_card,(MCI_CMD_TIMEOUT | MCI_CMD_CRC_FAIL | MCI_CMD_RESP_END);
MCI_SendCmd( VOLTAGE_SWITCH, 0x00000000, EXPECT_SHORT_RESP, 0 ); //expected resonse R1
respStatus = RtSdBSP_GetCmdResp( VOLTAGE_SWITCH, EXPECT_SHORT_RESP, (unsigned long *)&respValue[0] );
cmd_index = respValue[0];
cmd_index &= 0x3F0000000000;
cmd_index = (cmd_index >> 40);
if( cmd_index == VOLTAGE_SWITCH )
{
if ( !respStatus && (respValue[0] & (1 << 9)) )
{
/* The card should be in the ready state due to ACMD41, and the transition is again to the ready state after CMD11 */
//return ( respValue[0] );
mmc_sd_card->state = READY_STATE;
return 0;
}
}
}
return -1;
}
#endif
int RtSdcard_Send_ACMD_SCR(SD_CARD_INFO *pmmc_sd_card )
{
int retries;
unsigned long respStatus;
unsigned long respValue[4];
for (retries = 0; retries < 0x20; retries++)
{
if ( RtSdcard_Send_ACMD(pmmc_sd_card) == -1 )
continue;
/* Send ACMD51 command to get the SCR register*/
RtSdBSP_SendCmd( SEND_APP_SEND_SCR, 0x00000000, EXPECT_SHORT_RESP, 0 );
respStatus = RtSdBSP_GetCmdResp( SEND_APP_SEND_SCR, EXPECT_SHORT_RESP, &respValue[0] );
if ( respStatus==0 && ((respValue[0] & (0x0F << 8)) == 0x0900) )
return 0; /* response is back and correct. */
RtSdBSP_Delay_micros(200);
}
return -1;
}
static int RtSdcard_Send_ACMD_Disconnect(SD_CARD_INFO *pmmc_sd_card)
{
int retries;
unsigned long respStatus;
unsigned long respValue[4];
for (retries = 0; retries < 0x20; retries++)
{
if ( RtSdcard_Send_ACMD(pmmc_sd_card) == -1 )
continue;
/* Send ACMD42 command to set/clear 50 ohm pullup 0 is disconnect */
RtSdBSP_SendCmd( SEND_APP_OP_DISCONNECT, 0x00000000, EXPECT_SHORT_RESP, 0 );
respStatus = RtSdBSP_GetCmdResp( SEND_APP_OP_DISCONNECT, EXPECT_SHORT_RESP, &respValue[0] );
if ( respStatus==0 && ((respValue[0] & (0x0F << 8)) == 0x0900) )
return 0; /* response is back and correct. */
RtSdBSP_Delay_micros(200);
}
return -1;
}
static void parse_CID(SD_CARD_INFO * mmc_sd_card, unsigned long *respValue)
{
unsigned char temp_8;
unsigned long temp_32, temp_32b;
unsigned short temp_16;
unsigned long long temp_serial;
temp_32 = DWSWAP(respValue[0]) & 0xff000000;
temp_32 = (temp_32 >> 24);
temp_8 = (unsigned char) (temp_32 & 0xff);
mmc_sd_card->CID.MID = temp_8;
temp_32 = DWSWAP(respValue[0]) & 0x00ffff00;
temp_32 = (temp_32 >> 8);
temp_16 = temp_32 & 0xFFFF;
mmc_sd_card->CID.OID = temp_16;
temp_serial = DWSWAP(respValue[0]) & 0x000000ff;
temp_serial = (temp_serial << 32); //bits 40 down PVOPVO - long long not protable
temp_32 = DWSWAP(respValue[1]);
temp_serial = temp_serial | temp_32 ;
mmc_sd_card->CID.PNM.PNM = temp_serial;
temp_32 = DWSWAP(respValue[2]);
temp_32 = temp_32 & 0xff000000;
temp_32 = ( temp_32 >> 24 );
temp_8 = temp_32 & 0xFF;
mmc_sd_card->CID.PRV = temp_8;
temp_32 = DWSWAP(respValue[2]);
temp_32 = temp_32 & 0x00FFFFFF;
temp_32 = (temp_32 << 8 );
temp_32b = DWSWAP(respValue[3]);
temp_32b = temp_32b & 0xFF000000;
temp_32b = ( temp_32b >> 24 );
temp_32 = temp_32 |temp_32b;
mmc_sd_card->CID.PSN = temp_32;
temp_32 = DWSWAP(respValue[3]);
temp_32 = temp_32 & 0x000FFF00;
temp_32 = ( temp_32 >> 8 );
temp_16 = temp_32 & 0xfff;
mmc_sd_card->CID.MDT = temp_16;
mmc_sd_card->CID.MDT_month = temp_16 & 0x00f;
temp_16 = temp_16 & 0xff0;
temp_16 = (temp_16 >> 4);
mmc_sd_card->CID.MDT_year = 2000 + temp_16;
}
static void parse_CSD(SD_CARD_INFO * mmc_sd_card, unsigned long *respValue)
{
unsigned long temp_32;
unsigned long card_memory_capacity;
int csd_structure;
unsigned long block_len;
unsigned long mult;
unsigned long blocknr;
int i;
temp_32 = DWSWAP(respValue[0]);
temp_32 = temp_32 & 0xC0000000 ;
temp_32 = (temp_32 >> 30);
csd_structure = temp_32 & 0x00000003;
if(csd_structure == 0)
{
/* CSD strucure version 1 */
mmc_sd_card->CSD_Version=0;
mmc_sd_card->CSD_V1.CSD_STRUCTURE = csd_structure ;
temp_32 = DWSWAP(respValue[0]);
temp_32 = temp_32 & 0x00ff0000 ;
temp_32 = (temp_32 >> 16);
mmc_sd_card->CSD_V1.TAAC = temp_32 & 0xff;
temp_32 = DWSWAP(respValue[0]);
temp_32 = temp_32 & 0x0000ff00 ;
temp_32 = ( temp_32 >> 8 );
mmc_sd_card->CSD_V1.NSAC = temp_32 & 0xff;
temp_32 = DWSWAP(respValue[0]);
temp_32 = temp_32 & 0x000000ff ;
mmc_sd_card->CSD_V1.TRAN_SPEED = temp_32 & 0xff;
temp_32 = DWSWAP(respValue[1]);
temp_32 = temp_32 & 0xfff00000 ;
temp_32 = ( temp_32 >> 20 );
mmc_sd_card->CSD_V1.CCC = temp_32 & 0xfff; /* ?? does not match with the document default value (default value is 01x110110101 getting 100110101) */
temp_32 = DWSWAP(respValue[1]);
temp_32 = temp_32 & 0x000f0000 ;
temp_32 = ( temp_32 >> 16 );
mmc_sd_card->CSD_V1.READ_BL_LEN = temp_32 & 0x0f;
temp_32 = DWSWAP(respValue[1]);
temp_32 = temp_32 & 0x00008000 ;
temp_32 = ( temp_32 >> 15 );
mmc_sd_card->CSD_V1.READ_BL_PARTIAL= temp_32 & 0x01;
temp_32 = DWSWAP(respValue[1]);
temp_32 = temp_32 & 0x00004000 ;
temp_32 = ( temp_32 >> 14 );
mmc_sd_card->CSD_V1.WRITE_BLK_MISALIGN = temp_32 & 0x01;
temp_32 = DWSWAP(respValue[1]);
temp_32 = temp_32 & 0x00002000 ;
temp_32 = ( temp_32 >> 13 );
mmc_sd_card->CSD_V1.READ_BLK_MISALIGN = temp_32 & 0x01;
temp_32 = DWSWAP(respValue[1]);
temp_32 = temp_32 & 0x00001000 ;
temp_32 = ( temp_32 >> 12 );
mmc_sd_card->CSD_V1.DSR_IMP = temp_32 & 0x01;
temp_32 = DWSWAP(respValue[1]);
temp_32 = temp_32 & 0x000003ff ;
temp_32 = ( temp_32 << 2 );
mmc_sd_card->CSD_V1.C_SIZE = temp_32 & 0xff8;
temp_32 = DWSWAP(respValue[2]);
temp_32 = temp_32 & 0xe0000000 ;
temp_32 = ( temp_32 >> 30 );
mmc_sd_card->CSD_V1.C_SIZE = mmc_sd_card->CSD_V1.C_SIZE | (temp_32 & 0x03);
temp_32 = DWSWAP(respValue[2]);
temp_32 = temp_32 & 0x38000000 ;
temp_32 = ( temp_32 >> 27 );
mmc_sd_card->CSD_V1.VDD_R_CURR_MIN= temp_32 & 0x07;
temp_32 = DWSWAP(respValue[2]);
temp_32 = temp_32 & 0x07000000 ;
temp_32 = ( temp_32 >> 24 );
mmc_sd_card->CSD_V1.VDD_R_CURR_MAX = temp_32 & 0x07;
temp_32 = DWSWAP(respValue[2]);
temp_32 = temp_32 & 0x00e00000 ;
temp_32 = ( temp_32 >> 21 );
mmc_sd_card->CSD_V1.VDD_W_CURR_MIN = temp_32 & 0x07;
temp_32 = DWSWAP(respValue[2]);
temp_32 = temp_32 & 0x001c0000 ;
temp_32 = ( temp_32 >> 18 );
mmc_sd_card->CSD_V1.VDD_W_CURR_MAX = temp_32 & 0x07;
temp_32 = DWSWAP(respValue[2]);
temp_32 = temp_32 & 0x00038000 ;
temp_32 = ( temp_32 >> 15 );
mmc_sd_card->CSD_V1.C_SIZE_MULT = temp_32 & 0x07;
temp_32 = DWSWAP(respValue[2]);
temp_32 = temp_32 & 0x00004000 ;
temp_32 = ( temp_32 >> 14 );
mmc_sd_card->CSD_V1.ERASE_BLK_EN= temp_32 & 0x01;
temp_32 = DWSWAP(respValue[2]);
temp_32 = temp_32 & 0x00003f80 ;
temp_32 = ( temp_32 >> 7 );
mmc_sd_card->CSD_V1.SECTOR_SIZE = temp_32 & 0x7f;
temp_32 = DWSWAP(respValue[2]);
temp_32 = temp_32 & 0x0000007f ;
mmc_sd_card->CSD_V1.WP_GRP_SIZE = temp_32 & 0x7f;
temp_32 = DWSWAP(respValue[3]);
temp_32 = temp_32 & 0x80000000 ;
temp_32 = ( temp_32 >> 31 );
mmc_sd_card->CSD_V1.WP_GRP_ENABLE = temp_32 & 0x01;
temp_32 = DWSWAP(respValue[3]);
temp_32 = temp_32 & 0x1c000000 ;
temp_32 = ( temp_32 >> 26 );
mmc_sd_card->CSD_V1.R2W_FACTOR= temp_32 & 0x07;
temp_32 = DWSWAP(respValue[3]);
temp_32 = temp_32 & 0x03c00000 ;
temp_32 = ( temp_32 >> 22 );
mmc_sd_card->CSD_V1.WRITE_BL_LEN = temp_32 & 0x0f;
temp_32 = DWSWAP(respValue[3]);
temp_32 = temp_32 & 0x00200000 ;
temp_32 = ( temp_32 >> 21 );
mmc_sd_card->CSD_V1.WRITE_BL_PARTIAL = temp_32 & 0x01;
temp_32 = DWSWAP(respValue[3]);
temp_32 = temp_32 & 0x00008000 ;
temp_32 = ( temp_32 >> 15 );
mmc_sd_card->CSD_V1.FILE_FORMAT_GRP = temp_32 & 0x01;
temp_32 = DWSWAP(respValue[3]);
temp_32 = temp_32 & 0x00004000 ;
temp_32 = ( temp_32 >> 14 );
mmc_sd_card->CSD_V1.COPY = temp_32 & 0x01;
temp_32 = DWSWAP(respValue[3]);
temp_32 = temp_32 & 0x00002000 ;
temp_32 = ( temp_32 >> 13 );
mmc_sd_card->CSD_V1.PERM_WRITE_PROTECT= temp_32 & 0x01;
temp_32 = DWSWAP(respValue[3]);
temp_32 = temp_32 & 0x00001000 ;
temp_32 = ( temp_32 >> 12 );
mmc_sd_card->CSD_V1.TMP_WRITE_PROTECT= temp_32 & 0x01;
temp_32 = DWSWAP(respValue[3]);
temp_32 = temp_32 & 0x00000c00 ;
temp_32 = ( temp_32 >> 10 );
mmc_sd_card->CSD_V1.FILE_FORMAT= temp_32 & 0x03;
//to be removed later.....
temp_32 = DWSWAP(respValue[3]);
temp_32 = temp_32 & 0x000000fe ;
temp_32 = ( temp_32 >> 1 );
mmc_sd_card->CSD_V1.CRC = temp_32 & 0x7f;
if( mmc_sd_card->CSD_V1.READ_BL_LEN < 12 )
{ block_len = 1; /*pow(2,mmc_sd_card->CSD_V1.READ_BL_LEN) */
for(i=1 ; i <= mmc_sd_card->CSD_V1.READ_BL_LEN ; i++)
block_len *= 2 ; /* pow(2,mmc_sd_card->CSD_V1.READ_BL_LEN)*/
}
else
{
rtp_printf("Error?! mmc_sd_card->CSD_V1.READ_BL_LEN >= 12 \n\r");
}
if( mmc_sd_card->CSD_V1.C_SIZE_MULT < 8 )
{
mult =1;
for(i=1 ; i <= mmc_sd_card->CSD_V1.C_SIZE_MULT+2 ; i++)
mult *= 2 ; /* pow(2,(mmc_sd_card->CSD_V1.C_SIZE_MULT+2)) */
}
blocknr = ( mmc_sd_card->CSD_V1.C_SIZE +1) * mult;
mmc_sd_card->no_blocks = blocknr ; /* no of blocks in SDSC card */
mmc_sd_card->bytes_per_block = block_len;
card_memory_capacity = blocknr * block_len ;
mmc_sd_card->card_capacity_bytes = card_memory_capacity ;
}
else
{
/* CSD strucure version 2 */
if(csd_structure == 1)
{
mmc_sd_card->CSD_Version=1;
mmc_sd_card->CSD_V2.CSD_STRUCTURE = csd_structure ;
temp_32 = DWSWAP(respValue[0]);
temp_32 = temp_32 & 0x00ff0000 ;
temp_32 = (temp_32 >> 16);
mmc_sd_card->CSD_V2.TAAC = temp_32 & 0xff;
temp_32 = DWSWAP(respValue[0]);
temp_32 = temp_32 & 0x0000ff00 ;
temp_32 = (temp_32 >> 8);
mmc_sd_card->CSD_V2.NSAC = temp_32 & 0xff;
temp_32 = DWSWAP(respValue[0]);
temp_32 = temp_32 & 0x000000ff ;
mmc_sd_card->CSD_V2.TRAN_SPEED = temp_32 & 0xff;
temp_32 = DWSWAP(respValue[1]);
temp_32 = temp_32 & 0xfff00000 ;
temp_32 = (temp_32 >> 20);
mmc_sd_card->CSD_V2.CCC = temp_32 & 0xfff;
temp_32 = DWSWAP(respValue[1]);
temp_32 = temp_32 & 0x000f0000 ;
temp_32 = (temp_32 >> 16);
mmc_sd_card->CSD_V2.READ_BL_LEN = temp_32 & 0xf;
temp_32 = DWSWAP(respValue[1]);
temp_32 = temp_32 & 0x0000f000 ;
temp_32 = (temp_32 >> 15);
mmc_sd_card->CSD_V2.READ_BL_PARTIAL= temp_32 & 0x1;
temp_32 = DWSWAP(respValue[1]);
temp_32 = temp_32 & 0x0000f000 ;
temp_32 = (temp_32 >> 14);
mmc_sd_card->CSD_V2.WRITE_BLK_MISALIGN= temp_32 & 0x1;
temp_32 = DWSWAP(respValue[1]);
temp_32 = temp_32 & 0x0000f000 ;
temp_32 = (temp_32 >> 13);
mmc_sd_card->CSD_V2.READ_BLK_MISALIGN= temp_32 & 0x1;
temp_32 = DWSWAP(respValue[1]);
temp_32 = temp_32 & 0x0000f000 ;
temp_32 = (temp_32 >> 12);
mmc_sd_card->CSD_V2.DSR_IMP= temp_32 & 0x1;
temp_32 = DWSWAP(respValue[1]);
temp_32 = temp_32 & 0x0000003f ;
temp_32 = (temp_32 << 16);
mmc_sd_card->CSD_V2.C_SIZE= temp_32 & 0x3F0000;
temp_32 = DWSWAP(respValue[2]);
temp_32 = temp_32 & 0xffff0000 ;
temp_32 = (temp_32 >> 16);
mmc_sd_card->CSD_V2.C_SIZE = mmc_sd_card->CSD_V2.C_SIZE | (temp_32 & 0xffff);
temp_32 = DWSWAP(respValue[2]);
temp_32 = temp_32 & 0x00004000 ; //100000000000000
temp_32 = (temp_32 >> 14);
mmc_sd_card->CSD_V2.ERASE_BLK_EN = (temp_32 & 0x1);
temp_32 = DWSWAP(respValue[2]);
temp_32 = temp_32 & 0x00003f80 ; //011111110000000
temp_32 = (temp_32 >> 7);
mmc_sd_card->CSD_V2.SECTOR_SIZE= (temp_32 & 0x7f);
temp_32 = DWSWAP(respValue[2]);
temp_32 = temp_32 & 0x0000003f ; //011111110000000
mmc_sd_card->CSD_V2.WP_GRP_SIZE= (temp_32 & 0x3f);
temp_32 = DWSWAP(respValue[3]);
temp_32 = temp_32 & 0x80000000 ;
temp_32 = (temp_32 >> 31);
mmc_sd_card->CSD_V2.WP_GRP_ENABLE = temp_32 & 0x01;
temp_32 = DWSWAP(respValue[3]);
temp_32 = temp_32 & 0x1c000000 ;
temp_32 = (temp_32 >> 26);
mmc_sd_card->CSD_V2.R2W_FACTOR= temp_32 & 0x07;
temp_32 = DWSWAP(respValue[3]);
temp_32 = temp_32 & 0x03c00000 ;
temp_32 = (temp_32 >> 22);
mmc_sd_card->CSD_V2.WRITE_BL_LEN= temp_32 & 0x0f;
temp_32 = DWSWAP(respValue[3]);
temp_32 = temp_32 & 0x00200000 ;
temp_32 = (temp_32 >> 21);
mmc_sd_card->CSD_V2.WRITE_BL_PARTIAL= temp_32 & 0x01;
temp_32 = DWSWAP(respValue[3]);
temp_32 = temp_32 & 0x00008000 ;
temp_32 = (temp_32 >> 15);
mmc_sd_card->CSD_V2.FILE_FORMAT_GRP= temp_32 & 0x01;
temp_32 = DWSWAP(respValue[3]);
temp_32 = temp_32 & 0x00004000 ;
temp_32 = (temp_32 >> 14);
mmc_sd_card->CSD_V2.COPY= temp_32 & 0x01;
temp_32 = DWSWAP(respValue[3]);
temp_32 = temp_32 & 0x00002000 ;
temp_32 = (temp_32 >> 13);
mmc_sd_card->CSD_V2.PERM_WRITE_PROTECT= temp_32 & 0x01;
temp_32 = DWSWAP(respValue[3]);
temp_32 = temp_32 & 0x00001000 ;
temp_32 = (temp_32 >> 12);
mmc_sd_card->CSD_V2.TMP_WRITE_PROTECT= temp_32 & 0x01;
temp_32 = DWSWAP(respValue[3]);
temp_32 = temp_32 & 0x00000c00 ;
temp_32 = (temp_32 >> 10);
mmc_sd_card->CSD_V2.FILE_FORMAT= temp_32 & 0x03;
temp_32 = DWSWAP(respValue[3]);
temp_32 = temp_32 & 0x000000fe ;
temp_32 = (temp_32 >> 1);
mmc_sd_card->CSD_V2.CRC= temp_32 & 0x7f;
card_memory_capacity = (mmc_sd_card->CSD_V2.C_SIZE+1) *512 ;
mmc_sd_card->card_capacity_bytes = card_memory_capacity * 1024;
mmc_sd_card->no_blocks = (mmc_sd_card->CSD_V2.C_SIZE+1) * 1024; /* ?? no of blocks in SDSC card */
mmc_sd_card->bytes_per_block = 512;
}
}
}