mirror of
https://github.com/peteratebs/rtfsprorelease.git
synced 2025-06-19 01:05:39 -04:00
1255 lines
42 KiB
C
1255 lines
42 KiB
C
/*
|
|
* SDMMC.c
|
|
*
|
|
* Created on: Mar 29, 2011
|
|
* Author: Peter
|
|
*/
|
|
|
|
/*
|
|
|
|
RtSdBSP_Card_IsInstalled -
|
|
Return 1 if the card is installed otherwise return 0
|
|
RtSdBSP_Controller_Attach -
|
|
Called once at start-up.
|
|
Make sure the controller is initialized
|
|
Make sure card detect interrupts are hooked
|
|
card detect interrupts should call one of these events when card insert status cahnges.
|
|
rtsdcardReportRemovalEvent - A card has been removed.
|
|
rtsdcardReportInsertionEvent - A card has been inserted.
|
|
Make sure card IO event interrupts are hooked
|
|
The card IO event handlers coordinate with other routines that are private to the sdbsp file
|
|
see: RtSdBSP_Read_BlockSetup, RtSdBSP_Read_BlockTransfer, RtSdBSP_Read_BlockShutdown
|
|
see: RtSdBSP_Write_BlockSetup, RtSdBSP_Write_BlockTransfer, RtSdBSP_Write_BlockShutdown
|
|
RtSdBSP_CardInit -
|
|
Called when a card is installed
|
|
Must set Open Drain output control for MMC
|
|
RtSdBSP_CardPushPullMode
|
|
Called when a card exits initialization mode
|
|
Must set Open Drain output control for MMC
|
|
RtSdBSP_Set_Clock -
|
|
If passed zero set the SD bus clock to its low value (must be less than 400 KHZ;
|
|
If passed one set the SD bus clock to its high value (18 to 25 mhz)
|
|
RtSdBSP_Set_BusWidth
|
|
Set the SD bus width to the width requested (1 or 4)
|
|
SendCmd -
|
|
Send an SD card command
|
|
GetCmdResp
|
|
Receive an SD card response
|
|
RtSdBSP_Read_BlockSetup
|
|
Prepare for a read transfer.
|
|
If using DMA initialize the DMA controller.
|
|
If using interrupts clear the interrupt signal.
|
|
If using interrupts mask on proper interrupts.
|
|
If using PIO transfer with polling disable interrupts.
|
|
RtSdBSP_Read_BlockTransfer
|
|
If using interrupts wait for signal from interrupt complete.
|
|
If using PIO transfer without interrupts perform polled transfer.
|
|
return 0 if successful
|
|
return -1 if an error is detected.
|
|
RtSdBSP_Read_BlockShutdown
|
|
If using interrupts mask off proper interrupts.
|
|
If using PIO transfer with polling re-enable interrupts.
|
|
RtSdBSP_Write_BlockSetup
|
|
Prepare for a read transfer.
|
|
If using DMA initialize the DMA controller.
|
|
If using interrupts clear the interrupt signal.
|
|
If using interrupts mask on proper interrupts.
|
|
If using PIO transfer with polling disable interrupts.
|
|
RtSdBSP_Write_BlockTransfer
|
|
If using interrupts wait for signal from interrupt complete.
|
|
If using PIO transfer without interrupts perform polled transfer.
|
|
return 0 if successful
|
|
return -1 if an error is detected.
|
|
RtSdBSP_Write_BlockShutdown
|
|
If using interrupts mask off proper interrupts.
|
|
If using PIO transfer with polling re-enable interrupts.
|
|
RtSdBSP_Delay_micros -
|
|
Perform a polling loop to delay the number of microseconds requested
|
|
|
|
int RtSdBSP_Read_SCR(SD_CARD_INFO * mmc_sd_card);
|
|
|
|
*/
|
|
|
|
#include "sdmmc.h"
|
|
|
|
extern SD_CARD_INFO mmc_sd_cards[];
|
|
|
|
/* Relatively device independent example BSP routenes */
|
|
|
|
/* Delay loop assuming 10 loops per microsecond */
|
|
void RtSdBSP_Delay_micros(unsigned long delay)
|
|
{
|
|
int i;
|
|
#define MICROSPERLOOP 10
|
|
for (i = 0; i < delay * MICROSPERLOOP; i++)
|
|
;
|
|
}
|
|
|
|
/* Simple minded signalling mechanism for interrupts */
|
|
static int sig;
|
|
static void sd_sig_clear(SD_CARD_INFO * mmc_sd_card)
|
|
{
|
|
sig=0;
|
|
}
|
|
static void sd_sig_set(SD_CARD_INFO * mmc_sd_card)
|
|
{
|
|
sig=1;
|
|
}
|
|
#define TIMEOUTVAL 100000000
|
|
static int sd_sig_wait(SD_CARD_INFO * mmc_sd_card,unsigned long timeout)
|
|
{
|
|
while (sig==0)
|
|
{
|
|
if (timeout-- == 0)
|
|
return -1;
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
#include "lpc214x.h"
|
|
#include "rtpstr.h"
|
|
#include "rtpprint.h"
|
|
|
|
#define SD_CARD_UNIT_NUM 0
|
|
|
|
#define DATA_TIMER_VALUE 0x10000 /* Check if I need to scale this down, or if it can be determined programatically from the CSD */
|
|
#define MA_DATA_TIMER_VALUE 0x80000000 //Check if I need to scale this down, or if it can be determined programatically from the CSD
|
|
|
|
|
|
|
|
|
|
extern unsigned long PVOPVO_T_splx(unsigned long level);
|
|
extern unsigned long PVOPVO_T_splhigh();
|
|
extern int RtSdcard_CheckStatus( SD_CARD_INFO * mmc_sd_card );
|
|
extern int RtSdcard_Send_Stop( SD_CARD_INFO * mmc_sd_card );
|
|
extern int RtSdcard_Send_BlockCount( SD_CARD_INFO * mmc_sd_card, unsigned long block_count );
|
|
extern int RtSdcard_Send_Write_Block( SD_CARD_INFO * mmc_sd_card, unsigned long blockNum);
|
|
extern int RtSdcard_Send_Read_Block( SD_CARD_INFO * mmc_sd_card , unsigned long blockNum, unsigned long blk_len);
|
|
extern int RtSdcard_Send_ACMD_SCR(SD_CARD_INFO *pmmc_sd_card);
|
|
extern int RtSdcard_Send_Write_Multiple_Block( SD_CARD_INFO * mmc_sd_card, unsigned long blockNum); //MA
|
|
extern void rtsdcardReportRemovalEvent(int unit);
|
|
extern void rtsdcardReportInsertionEvent(int unit);
|
|
#if (ENABLE_DMA)
|
|
static void RtSdBSP_Dma_Setup(SD_CARD_INFO * mmc_sd_card,unsigned char *pBbuffer, int Reading);
|
|
static int RtSdBSP_Dma_Complete(SD_CARD_INFO * mmc_sd_card, int Reading);
|
|
#endif
|
|
|
|
static int RtSdBSP_PolledReadXfer(unsigned char *pBbuffer,unsigned long count_of_data);
|
|
static int RtSdBSP_PolledWriteXfer(unsigned long *pcBbuffer,unsigned long remain);
|
|
|
|
static void RtSdBSP_Enable_Card_Isr(void);
|
|
void RtSdBSP_Set_Clock(int Clock_rate );
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
*/
|
|
|
|
extern unsigned long install_irq(unsigned long IntNumber, void *HandlerAddr, unsigned long Priority);
|
|
|
|
int RtSdBSP_Card_IsInstalled(int unit)
|
|
{
|
|
unsigned long l;
|
|
l=FIO2PIN;
|
|
/* If the pin reads zero the card is inserted.
|
|
The signal should be de-bounced because several edges may occur per removal */
|
|
if (l & (1<<11))
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
static void RtSdBSP_PowerOff(void);
|
|
static void Card_Check_Insert(void)
|
|
{
|
|
/* If the pin reads zero the card is inserted.
|
|
The signal should be de-bounced because several edges may occur per removal */
|
|
if (!RtSdBSP_Card_IsInstalled(0))
|
|
{
|
|
/* Set all lines to pulldown so the card doesn't draw power from them */
|
|
PINMODE2 = 0x3C0FCF0; /* 00 00 00 11 11 00 00 00 11 11 11 00 11 11 00 00 */
|
|
MCIPower =0x00; /* Shut down bus power */
|
|
MCIMask0 = 0x00 ; /* Disable all interrupts for now */
|
|
rtsdcardReportRemovalEvent(0);
|
|
}
|
|
else
|
|
{
|
|
rtsdcardReportInsertionEvent(0);
|
|
}
|
|
}
|
|
static void Card_Detect_Isr (void)
|
|
{
|
|
IO2INTCLR |= (1 << 11);
|
|
VICSoftIntClr = 0xffffffff;
|
|
VICAddress=0; // Ack the interrupt
|
|
Card_Check_Insert();
|
|
}
|
|
static void RtSdBSP_Enable_Card_Detect_Isr(void)
|
|
{
|
|
rtp_printf("Card detects ISR collides with touch. Disable if using touch Must fix \n");
|
|
return;
|
|
|
|
IO2INTCLR |= (1 << 11);
|
|
IO2INTENR |= (1 << 11);
|
|
IO2INTENF |= (1 << 11);
|
|
|
|
install_irq(VIC_EINT3, (void *)Card_Detect_Isr, EINT3_PRIORITY);
|
|
|
|
IO2INTCLR |= (1 << 11);
|
|
VICIntEnable |= (1 << VIC_EINT3);
|
|
}
|
|
|
|
static void RtSdBSP_PowerOff(void)
|
|
{
|
|
SCS |= 0x08; /* SCS register bit 3 corresponds to MCIPWR 0 the MCIPWR pin is low. 1 The MCIPWR pin is high */
|
|
MCIPower =0x00; /* Shut down bus power */
|
|
MCIMask0 = 0x00 ; /* Disable all interrupts for now */
|
|
RtSdBSP_Delay_micros(1);
|
|
|
|
// SD_CMD_MODE = 2;
|
|
MCICommand = 0;
|
|
RtSdBSP_Delay_micros(1);
|
|
MCIDataCtrl = 0;
|
|
RtSdBSP_Delay_micros(1);
|
|
MCIClear = 0x7FF; /* clear all interrupts */
|
|
RtSdBSP_Set_Clock(0);
|
|
// MCIClock &= ~(1 << 11)|(0x16); /* disabled, 1 bit bus, clock to slow mode < 400 khz */
|
|
RtSdBSP_Delay_micros(1);
|
|
}
|
|
#define TEST_NEW_CLOCK 1
|
|
int RtSdBSP_Controller_Attach(void)
|
|
{
|
|
/* Power the PCONP register */
|
|
/* On Reset, the SD/MMC is disabled PCMCI=0 in PCONP */
|
|
|
|
/* P2.11 - EINT1 */
|
|
PINSEL4 &= ~(0x3<<22);
|
|
PINSEL4 |= (0x0<<22); /* GPIO */
|
|
|
|
PINMODE4 &= ~(0x3<<22);
|
|
PINMODE4 |= (0x0<<22);
|
|
|
|
|
|
PCONP |= 0x10000000; /* (1<<28) */
|
|
|
|
#if(ENABLE_DMA)
|
|
PCONP |= (1<<29);
|
|
|
|
// enable DMA , little endian
|
|
DMACConfiguration = 1;
|
|
DMACSync = 0; // DMA sync enable
|
|
DMACIntErrClr = 3;
|
|
DMACIntTCClear = 3;
|
|
DMACC0Configuration = 0;
|
|
DMACC1Configuration = 0;
|
|
|
|
#endif
|
|
// FC== CLK/4 FD == CLK, FE == CLK/2 FF=CLK/8
|
|
#if (TEST_NEW_CLOCK)
|
|
unsigned long l=PCLKSEL1;
|
|
l &= 0xfaffffff;
|
|
l |= 0x01000000; // 0=CLK/4, 1 = CLK, 2 == CLK/2 3== CLK/8
|
|
PCLKSEL1=l;
|
|
#else
|
|
PCLKSEL1 &= 0xFCFFFFFF; // PCCLK_MCICLK_DIV;
|
|
#endif
|
|
|
|
PINSEL2 |= 0x20 ; /* Set GPIO Port 1.2 to MCICLK */
|
|
PINSEL2 |= 0x80 ; /* Set GPIO Port 1.3 to MCICMD */
|
|
PINSEL2 |= 0x800; /* Set GPIO Port 1.5 to MCIPWR */
|
|
PINSEL2 |= 0x2000; /* Set GPIO Port 1.6 to MCIDAT0 */
|
|
PINSEL2 |= 0x8000; /* Set GPIO Port 1.7 to MCIDAT1 */
|
|
PINSEL2 |= 0x800000; /* Set GPIO Port 1.11 to MCIDAT2 */
|
|
PINSEL2 |= 0x2000000; /* Set GPIO Port 1.12 to MCIDAT3 */
|
|
PINMODE2 |= 0x280A8A0; /* MCI/SD Pins have neither pull-up nor pull down 00 00 00 10 10 00 00 00 10 10 10 00 10 10 00 00 */
|
|
SCS |= 0x08; /* SCS register bit 3 corresponds to MCIPWR 0 the MCIPWR pin is low. 1 The MCIPWR pin is high */
|
|
RtSdBSP_PowerOff();
|
|
|
|
RtSdBSP_Enable_Card_Detect_Isr();
|
|
#if(CONFIGURE_SDMMC_INTERRUPTS)
|
|
RtSdBSP_Enable_Card_Isr();
|
|
#endif //CONFIGURE_SDMMC_INTERRUPTS
|
|
return 0;
|
|
}
|
|
|
|
/* Experimentation yields these working sets
|
|
MCLKDIV_SLOW 23 = 391,304Hz -> @18Mhz/(2*60) works on commands to get started but reads bad data if we run this way.
|
|
CLKDIV_NORMAL (0x6-1) 1.5Mhz -> @18Mhz/(2*6) Works on data
|
|
CLKDIV_NORMAL (0x3-1) 3Mhz -> @18Mhz/(2*3) Works on data with interrupts
|
|
USE_BYPASS Set this to one to use 18 MHZ clock undivided, some luck with DMA
|
|
*/
|
|
#if (TEST_NEW_CLOCK)
|
|
#define MCLKDIV_SLOW ((0x17-1)*4) /* 23 = 391,304Hz -> @18Mhz/(2*60) */
|
|
#else
|
|
#define MCLKDIV_SLOW 0x17-1 /* 23 = 391,304Hz -> @18Mhz/(2*60) */
|
|
#endif
|
|
#if(CONFIGURE_SDMMC_INTERRUPTS)
|
|
#if (TEST_NEW_CLOCK)
|
|
#define MCLKDIV_NORMAL ((0x5-1)*4) /* 9 = 3Mhz -> @18Mhz/(2*4) */
|
|
#else
|
|
#define MCLKDIV_NORMAL (0x5-1) /* 9 = 3Mhz -> @18Mhz/(2*4) */
|
|
#endif
|
|
#else
|
|
#define MCLKDIV_NORMAL (0x6-1) /* 5 = 15Mhz -> @18Mhz/(2*4) */
|
|
//#define MCLKDIV_NORMAL (0x3-1) /* 5 = 15Mhz -> @18Mhz/(2*4) */
|
|
//#define MCLKDIV_NORMAL (0x2-1) /* 5 = 15Mhz -> @18Mhz/(2*4) */
|
|
//#define MCLKDIV_NORMAL (0x1-1) /* 5 = 15Mhz -> @18Mhz/(2*4) */
|
|
#endif
|
|
#define USE_BYPASS 0 /* Set this to one to use 18 MHZ clock undivided. */
|
|
|
|
|
|
unsigned long SYS_GetFpclk(unsigned long clock_offset);
|
|
|
|
void RtSdBSP_Set_Clock(int rate )
|
|
{
|
|
unsigned long ClkValue = 0;
|
|
#define MCI_PCLK_OFFSET 56 // See board.h
|
|
if(rate == 0)
|
|
{
|
|
ClkValue = MCLKDIV_SLOW; /* Slow Clock */
|
|
}
|
|
else
|
|
{
|
|
ClkValue = MCLKDIV_NORMAL; /* 0x06-1 */
|
|
#if (USE_BYPASS)
|
|
// This will work with DMA, getting errors when using fifo
|
|
rtp_printf("MCI Bypass Bus clock freq == 18MHZ \n");
|
|
MCIClock &=~(0xFF); /* Clear the clock divider */
|
|
MCIClock |= (1<<10); // turn on bypass
|
|
RtSdBSP_Delay_micros(1000); /* Delay 3MCLK + 2PCLK before next write */
|
|
return;
|
|
#endif
|
|
}
|
|
rtp_printf("MCI Periph clock freq == %d \n",SYS_GetFpclk(MCI_PCLK_OFFSET));
|
|
rtp_printf("MCI Bus clock freq == %d \n" ,SYS_GetFpclk(MCI_PCLK_OFFSET)/(2*(ClkValue+1)));
|
|
MCIClock &=~(0xFF); /* Clear the clock divider */
|
|
MCIClock |= (1<<8) |ClkValue;
|
|
RtSdBSP_Delay_micros(1000); /* Delay 3MCLK + 2PCLK before next write */
|
|
}
|
|
|
|
|
|
int RtSdBSP_Set_BusWidth(SD_CARD_INFO *pmmc_sd_card, int width )
|
|
{
|
|
RtSdBSP_Delay_micros(100);
|
|
if ( width == 1 )
|
|
{
|
|
MCIClock &= ~(1 << 11); /* 1 bit bus */
|
|
}
|
|
else if ( width == 4 )
|
|
{
|
|
MCIClock |= (1 << 11); /* 4 bit bus */
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void RtSdBSP_CardInit( SD_CARD_INFO * pmmc_sd_card )
|
|
{
|
|
RtSdBSP_PowerOff();
|
|
|
|
if(MCIClock & 0x100)
|
|
MCIClock &= ~(1 << 8);
|
|
|
|
if(MCIPower & 0x2)
|
|
MCIPower =0x00;
|
|
|
|
MCIPower |= 0x02;
|
|
while ( !(MCIPower & 0x02) ); /* PVOPVO - Endless */
|
|
RtSdBSP_Delay_micros(10000); /* When the external power supply is switched on, the software first enters the power-up phase,
|
|
* and wait until the supply output is stable before moving to the power-on phase. */
|
|
|
|
MCIPower |= 0x01; /* bit 1 is set already, from power up to power on */
|
|
|
|
RtSdBSP_Delay_micros(100000); /* When the external power supply is switched on, the software first enters the power-up phase,
|
|
* and wait until the supply output is stable before moving to the power-on phase. */
|
|
|
|
MCIMask0 = 0x00 ; /* Mask the interrupts Disable all interrupts for now */
|
|
MCIClear = 0x7FF; /* Write 0B11111111111 to the MCI Clear register to clear the status flags */
|
|
|
|
PINMODE2 = 0;
|
|
MCIPower |= (1 << 6 ); /* Enable open Drain output control for MMC */
|
|
RtSdBSP_Delay_micros(1);
|
|
|
|
RtSdBSP_Set_Clock(0);
|
|
|
|
RtSdBSP_Delay_micros(3000);
|
|
}
|
|
|
|
void RtSdBSP_CardPushPullMode( SD_CARD_INFO * pmmc_sd_card )
|
|
{
|
|
MCIPower &= ~(1 << 6 ); /* Clear Open Drain output control for MMC */
|
|
PINMODE2 |= 0x280A8A0; /* MCI/SD Pins have neither pull-up nor pull down 00 00 00 10 10 00 00 00 10 10 10 00 10 10 00 00 */
|
|
|
|
// rtp_printf("Pnmode in push pull mode %X\n", 0 /*PINMODE2*/);
|
|
RtSdBSP_Delay_micros(3000);
|
|
}
|
|
|
|
int RtSdBSP_SendCmd( unsigned long CmdIndex, unsigned long Argument, int ExpectResp, int AllowTimeout )
|
|
{
|
|
unsigned long CmdData = 0;
|
|
unsigned long CmdStatus;
|
|
|
|
/* Clear appropriate status bits before sending the command */
|
|
switch(CmdIndex)
|
|
{
|
|
case SEND_STATUS:
|
|
case SEND_CSD:
|
|
// case VOLTAGE_SWITCH:
|
|
case SELECT_CARD:
|
|
MCIClear |= (MCI_CMD_TIMEOUT | MCI_CMD_CRC_FAIL | MCI_CMD_RESP_END);
|
|
break;
|
|
case SET_BLOCK_COUNT:
|
|
case STOP_TRANSMISSION:
|
|
case READ_SINGLE_BLOCK:
|
|
case WRITE_BLOCK:
|
|
case READ_MULTIPLE_BLOCK:
|
|
case WRITE_MULTIPLE_BLOCK:
|
|
MCIClear |= MCI_CLEAR_ALL;
|
|
break;
|
|
// HEREHERE - We don't clear for any of these ? why
|
|
case GO_IDLE_STATE:
|
|
case SEND_OP_COND:
|
|
case SEND_APP_OP_COND:
|
|
case APP_CMD:
|
|
case SET_ACMD_BUS_WIDTH:
|
|
case ALL_SEND_CID:
|
|
case SET_RELATIVE_ADDR:
|
|
case SEND_IF_COND:
|
|
case SEND_APP_SEND_SCR:
|
|
case SEND_APP_OP_DISCONNECT:
|
|
// HEREHERE try this
|
|
MCIClear |= (MCI_CMD_TIMEOUT | MCI_CMD_CRC_FAIL | MCI_CMD_RESP_END);
|
|
break;
|
|
}
|
|
|
|
/* the command engine must be disabled when we modify the argument or the peripheral resends */
|
|
while ( (CmdStatus = MCIStatus) & MCI_CMD_ACTIVE ) /* Command in progress. */
|
|
{
|
|
MCICommand = 0; /* PVOPVO endless */
|
|
RtSdBSP_Delay_micros(10);
|
|
MCIClear = CmdStatus | MCI_CMD_ACTIVE;
|
|
}
|
|
RtSdBSP_Delay_micros(100);
|
|
|
|
/*set the command details, the CmdIndex should 0 through 0x3F only */
|
|
CmdData |= (CmdIndex & 0x3F);
|
|
if ( ExpectResp == SD_RESP_R0) /* no response */
|
|
{
|
|
CmdData &= ~((1 << 6) | (1 << 7)); /* Clear long response bit as well */
|
|
}
|
|
else if ( ExpectResp == EXPECT_SHORT_RESP ) /* expect short response */
|
|
{
|
|
CmdData |= (1 << 6);
|
|
}
|
|
else if ( ExpectResp == SD_RESP_R2) /* expect long response */
|
|
{
|
|
CmdData |= (1 << 6) | (1 << 7);
|
|
}
|
|
|
|
if ( AllowTimeout ) /* allow timeout or not */
|
|
{
|
|
CmdData |= (1 << 8);
|
|
}
|
|
else
|
|
{
|
|
CmdData &= ~(1 << 8);
|
|
}
|
|
/*send the command*/
|
|
CmdData |= (1 << 10);
|
|
MCIArgument = Argument; /* Set the argument first, finally command */
|
|
MCICommand = CmdData;
|
|
return 0;
|
|
}
|
|
|
|
int RtSdBSP_GetCmdResp( int ExpectCmdData, int ExpectResp, unsigned long * CmdResp )
|
|
{
|
|
int CmdRespStatus = 0;
|
|
int LastCmdIndex;
|
|
unsigned long MCIRespCmdValue;
|
|
if ( ExpectResp == SD_RESP_R0 )
|
|
return ( 0 );
|
|
while ( 1 )
|
|
{ // PVOPVO endless
|
|
CmdRespStatus = MCIStatus;
|
|
if ( CmdRespStatus & MCI_CMD_TIMEOUT)
|
|
{
|
|
MCIClear = CmdRespStatus | MCI_CMD_TIMEOUT;
|
|
MCICommand = 0;
|
|
MCIArgument = 0xFFFFFFFF;
|
|
return -1;
|
|
}
|
|
if (CmdRespStatus & MCI_CMD_CRC_FAIL )
|
|
{
|
|
MCIClear = CmdRespStatus | MCI_CMD_CRC_FAIL;
|
|
LastCmdIndex = MCICommand & 0x003F;
|
|
if ( (LastCmdIndex == SET_BLOCK_COUNT)||(LastCmdIndex == SEND_OP_COND) || (LastCmdIndex == SEND_APP_OP_COND) || (LastCmdIndex == STOP_TRANSMISSION) )
|
|
{
|
|
MCICommand = 0;
|
|
MCIArgument = 0xFFFFFFFF;
|
|
break; /* ignore CRC error if it's a resp for SEND_OP_COND or STOP_TRANSMISSION. */
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
else if ( CmdRespStatus & MCI_CMD_RESP_END )
|
|
{
|
|
MCIClear = CmdRespStatus | MCI_CMD_RESP_END;
|
|
break; /* cmd response is received, expecting response */
|
|
}
|
|
}
|
|
MCIRespCmdValue=MCIRespCmd;
|
|
if ( (MCIRespCmdValue & 0x3F) != ExpectCmdData )
|
|
{
|
|
/* If the response is not R1, in the response field, the Expected Cmd data
|
|
won't be the same as the CMD data in SendCmd(). Below four cmds have
|
|
R2 or R3 response. We don't need to check if MCI_RESP_CMD is the same
|
|
as the Expected or not. */
|
|
if ( (ExpectCmdData != SEND_OP_COND) && (ExpectCmdData != SEND_APP_OP_COND) && (ExpectCmdData != ALL_SEND_CID) && (ExpectCmdData != SEND_CSD) )
|
|
{
|
|
/* PVOPVO - Analyze */
|
|
return -1;
|
|
}
|
|
}
|
|
if ( ExpectResp == EXPECT_SHORT_RESP )
|
|
{
|
|
*CmdResp = MCIResponse0;
|
|
}
|
|
else if ( ExpectResp == SD_RESP_R2 )
|
|
{
|
|
*CmdResp = MCIResponse0;
|
|
*(CmdResp+1) = MCIResponse1;
|
|
*(CmdResp+2) = MCIResponse2;
|
|
*(CmdResp+3) = MCIResponse3;
|
|
}
|
|
return ( 0 ); /* Read MCI_RESP0 register assuming it's not long response. */
|
|
}
|
|
|
|
|
|
int RtSdBSP_Read_BlockSetup(SD_CARD_INFO * mmc_sd_card,unsigned long blockNum)
|
|
{
|
|
MCIClear |= MCI_CLEAR_ALL;
|
|
RtSdBSP_Delay_micros(100);
|
|
|
|
if (mmc_sd_card->card_operating_flags & SDFLGMULTIBLOCK)
|
|
mmc_sd_card->bytes_left_to_transfer = BLOCK_LENGTH*mmc_sd_card->blocks_to_transfer;
|
|
else
|
|
mmc_sd_card->bytes_left_to_transfer = BLOCK_LENGTH;
|
|
mmc_sd_card->byte_buffer =(unsigned char *)mmc_sd_card->blk_buffer;
|
|
|
|
#if (ENABLE_DMA==0)
|
|
#if(CONFIGURE_SDMMC_INTERRUPTS)
|
|
sd_sig_clear(mmc_sd_card);
|
|
MCIClear |= ((FIFO_RX_INT_MASK)|(DATA_END_INT_MASK)|(ERR_RX_INT_MASK)); /* FIFO RX interrupts only */
|
|
MCIMask0 |= ((FIFO_RX_INT_MASK)|(DATA_END_INT_MASK)|(ERR_RX_INT_MASK)); /* FIFO RX interrupts only */
|
|
#else
|
|
mmc_sd_card->cpu_level=PVOPVO_T_splhigh();
|
|
#endif
|
|
#else
|
|
RtSdBSP_Dma_Setup(mmc_sd_card,(unsigned char *)mmc_sd_card->blk_buffer,1/* Reading*/);
|
|
#endif
|
|
MCIDataTimer = MA_DATA_TIMER_VALUE; //MA: Increased the time out, huge now, optimize later
|
|
MCIDataLength = mmc_sd_card->bytes_left_to_transfer;
|
|
return 0;
|
|
}
|
|
|
|
void RtSdBSP_Read_BlockShutdown(SD_CARD_INFO * mmc_sd_card)
|
|
{
|
|
#if (ENABLE_DMA==0)
|
|
#if(CONFIGURE_SDMMC_INTERRUPTS)
|
|
|
|
sd_sig_clear(mmc_sd_card);
|
|
MCIMask0 &= ~((FIFO_RX_INT_MASK)|(DATA_END_INT_MASK)|(ERR_RX_INT_MASK)); /* FIFO RX interrupts only */
|
|
#else
|
|
PVOPVO_T_splx(mmc_sd_card->cpu_level);
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
int RtSdBSP_Read_BlockTransfer(SD_CARD_INFO * mmc_sd_card)
|
|
{
|
|
unsigned long DataCtrl;
|
|
int ret_val=0;
|
|
#if (ENABLE_DMA)
|
|
DataCtrl = ((1 << 0) | (1 << 1) | (1 << 3) | ((LOG_BLOCK_LENGTH) << 4));
|
|
#else
|
|
/* Read, enable, block transfer, and data length */
|
|
DataCtrl = ((1 << 0) | (1 << 1) | (LOG_BLOCK_LENGTH << 4));
|
|
#endif
|
|
|
|
/* No break points after this or we'll get a fifo overrun */
|
|
MCIDataCtrl = DataCtrl;
|
|
// RtSdBSP_Delay_micros(1); //MA
|
|
#if (ENABLE_DMA==0)
|
|
#if(CONFIGURE_SDMMC_INTERRUPTS)
|
|
ret_val = sd_sig_wait(mmc_sd_card,TIMEOUTVAL);
|
|
if (ret_val==-1)
|
|
{
|
|
; /* Check ISR status */
|
|
}
|
|
else
|
|
{
|
|
if ( mmc_sd_card->bytes_left_to_transfer==0)
|
|
mmc_sd_card->blocks_transfered = mmc_sd_card->blocks_to_transfer;
|
|
}
|
|
#else
|
|
if (mmc_sd_card->card_operating_flags & SDFLGMULTIBLOCK)
|
|
{
|
|
while (mmc_sd_card->blocks_transfered < mmc_sd_card->blocks_to_transfer&&ret_val==0)
|
|
{
|
|
ret_val = RtSdBSP_PolledReadXfer((unsigned char *)mmc_sd_card->blk_buffer,mmc_sd_card->blocks_to_transfer*512);
|
|
mmc_sd_card->blocks_transfered+=mmc_sd_card->blocks_to_transfer;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ret_val = RtSdBSP_PolledReadXfer((unsigned char *)mmc_sd_card->blk_buffer,512);
|
|
mmc_sd_card->blocks_transfered+=1;
|
|
}
|
|
#endif
|
|
#else
|
|
ret_val=RtSdBSP_Dma_Complete(mmc_sd_card,1/* Reading*/);
|
|
if (ret_val==0)
|
|
mmc_sd_card->blocks_transfered = mmc_sd_card->blocks_to_transfer;
|
|
#endif
|
|
// mmc_sd_card->blocks_to_transfer=blockCount;
|
|
return ret_val;
|
|
}
|
|
|
|
|
|
|
|
|
|
int RtSdBSP_Write_BlockSetup(SD_CARD_INFO * mmc_sd_card,unsigned long blockNum)
|
|
{
|
|
MCIClear |= MCI_CLEAR_ALL;
|
|
MCIDataCtrl = 0;
|
|
RtSdBSP_Delay_micros(100);
|
|
|
|
if (mmc_sd_card->card_operating_flags & SDFLGMULTIBLOCK)
|
|
mmc_sd_card->bytes_left_to_transfer = BLOCK_LENGTH*mmc_sd_card->blocks_to_transfer;
|
|
else
|
|
mmc_sd_card->bytes_left_to_transfer = BLOCK_LENGTH;
|
|
mmc_sd_card->byte_buffer =(unsigned char *)mmc_sd_card->blk_buffer;
|
|
|
|
#if (ENABLE_DMA==0)
|
|
/* pre-load the fifo with the first 64 bytes of data */
|
|
if(0)
|
|
{
|
|
unsigned long i,*fifo_ptr,*plBbuffer;
|
|
fifo_ptr = (unsigned long *) 0xE008C080;
|
|
plBbuffer = (unsigned long *)mmc_sd_card->byte_buffer;
|
|
for (i =0;i < 16; i++)
|
|
{
|
|
*fifo_ptr = *plBbuffer++;
|
|
}
|
|
mmc_sd_card->bytes_left_to_transfer -= 64;
|
|
mmc_sd_card->byte_buffer += 64;
|
|
}
|
|
#if(CONFIGURE_SDMMC_INTERRUPTS)
|
|
sd_sig_clear(mmc_sd_card);
|
|
MCIClear |= ((FIFO_TX_INT_MASK)|(DATA_END_INT_MASK)|(ERR_TX_INT_MASK));
|
|
MCIMask0 |= ((FIFO_TX_INT_MASK)|(DATA_END_INT_MASK)|(ERR_TX_INT_MASK));
|
|
#else
|
|
mmc_sd_card->cpu_level=PVOPVO_T_splhigh();
|
|
#endif
|
|
#else
|
|
RtSdBSP_Dma_Setup(mmc_sd_card,(unsigned char *)mmc_sd_card->blk_buffer,0/* writing */);
|
|
#endif
|
|
MCIDataTimer = MA_DATA_TIMER_VALUE; //MA: Increased the time out, huge now, optimize later
|
|
MCIDataLength = mmc_sd_card->bytes_left_to_transfer;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void RtSdBSP_Write_BlockShutdown(SD_CARD_INFO * mmc_sd_card)
|
|
{
|
|
#if (ENABLE_DMA==0)
|
|
#if(CONFIGURE_SDMMC_INTERRUPTS)
|
|
MCIMask0 &= ~((FIFO_TX_INT_MASK)|(DATA_END_INT_MASK)|(ERR_TX_INT_MASK));
|
|
#else
|
|
PVOPVO_T_splx(mmc_sd_card->cpu_level);
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
int RtSdBSP_Write_BlockTransfer(SD_CARD_INFO * mmc_sd_card)
|
|
{
|
|
unsigned long DataCtrl;
|
|
int ret_val=0;
|
|
#if (ENABLE_DMA)
|
|
DataCtrl = ((1 << 0) | (1 << 3) | (LOG_BLOCK_LENGTH<< 4));
|
|
#else
|
|
/* Write, block transfer, and data length */
|
|
DataCtrl = ((1 << 0) | (LOG_BLOCK_LENGTH << 4));
|
|
#endif
|
|
|
|
/* No break points after this or we'll get a fifo overrun */
|
|
MCIDataCtrl = DataCtrl;
|
|
|
|
RtSdBSP_Delay_micros(1); //MA
|
|
|
|
ret_val = 0;
|
|
|
|
|
|
#if(ENABLE_DMA==0)
|
|
#if(CONFIGURE_SDMMC_INTERRUPTS)
|
|
ret_val = sd_sig_wait(mmc_sd_card,TIMEOUTVAL);
|
|
if (ret_val==-1)
|
|
{
|
|
; /* Check ISR status */
|
|
}
|
|
else
|
|
{
|
|
if ( mmc_sd_card->bytes_left_to_transfer==0)
|
|
mmc_sd_card->blocks_transfered = mmc_sd_card->blocks_to_transfer;
|
|
}
|
|
|
|
#else
|
|
{
|
|
if (mmc_sd_card->card_operating_flags & SDFLGMULTIBLOCK)
|
|
{
|
|
while (mmc_sd_card->blocks_transfered < mmc_sd_card->blocks_to_transfer&&ret_val==0)
|
|
{
|
|
ret_val = RtSdBSP_PolledWriteXfer(mmc_sd_card->blk_buffer,mmc_sd_card->blocks_to_transfer*512);
|
|
mmc_sd_card->blocks_transfered+=mmc_sd_card->blocks_to_transfer;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ret_val = RtSdBSP_PolledWriteXfer(mmc_sd_card->blk_buffer,512);
|
|
mmc_sd_card->blocks_transfered+=1;
|
|
}
|
|
}
|
|
#endif
|
|
#else
|
|
{
|
|
ret_val=RtSdBSP_Dma_Complete(mmc_sd_card,0);
|
|
if (ret_val==0)
|
|
mmc_sd_card->blocks_transfered = mmc_sd_card->blocks_to_transfer;
|
|
|
|
}
|
|
#endif
|
|
if (mmc_sd_card->card_operating_flags & SDFLGMULTIBLOCK)
|
|
{
|
|
/* Stop the transfer */
|
|
if ((mmc_sd_card->card_operating_flags & SDFLGBLOCKCOUNT)==0)
|
|
RtSdcard_Send_Stop(mmc_sd_card);
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
|
|
extern unsigned long long rtp_GetMicroseconds(void);
|
|
static int RtSdBSP_PolledReadXfer(unsigned char *pBbuffer,unsigned long count_of_data)
|
|
{
|
|
unsigned long ShadowStatus;
|
|
unsigned long maxloops = 10000000;
|
|
unsigned long *plBbuffer = (unsigned long *)pBbuffer;
|
|
unsigned long *fifo_ptr;
|
|
|
|
fifo_ptr = (unsigned long *) 0xE008C080;
|
|
ShadowStatus=MCIStatus ;
|
|
while((ShadowStatus & SD_RX_DATA_AVAILABLE)==0)
|
|
{
|
|
if (ShadowStatus & SD_RCV_ERRORS)
|
|
{
|
|
rtp_printf("\nStatus error on Polled read %X\n",ShadowStatus);
|
|
return -1;
|
|
}
|
|
|
|
ShadowStatus=MCIStatus ;
|
|
if (--maxloops==0)
|
|
{
|
|
rtp_printf("\npolledXFER timeout 1\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
while(count_of_data >= 32 && maxloops)
|
|
{
|
|
if(ShadowStatus & SD_FIFO_DATA_OVERRUN)
|
|
{
|
|
rtp_printf("DATA TIMEDOUT status == %X \n",ShadowStatus);
|
|
return -1;
|
|
}
|
|
while (maxloops && (ShadowStatus & SD_FIFO_HALF_FULL)==0)
|
|
{
|
|
if(ShadowStatus & SD_FIFO_DATA_OVERRUN)
|
|
{
|
|
rtp_printf("DATA TIMEDOUT status == %X \n",ShadowStatus);
|
|
return -1;
|
|
}
|
|
ShadowStatus=MCIStatus; //MA
|
|
maxloops++;
|
|
}
|
|
*plBbuffer++ = *fifo_ptr;
|
|
*plBbuffer++ = *fifo_ptr;
|
|
*plBbuffer++ = *fifo_ptr;
|
|
*plBbuffer++ = *fifo_ptr;
|
|
*plBbuffer++ = *fifo_ptr;
|
|
*plBbuffer++ = *fifo_ptr;
|
|
*plBbuffer++ = *fifo_ptr;
|
|
*plBbuffer++ = *fifo_ptr;
|
|
count_of_data -= 32;
|
|
ShadowStatus=MCIStatus; //MA
|
|
}
|
|
while(count_of_data && maxloops)
|
|
{
|
|
maxloops--;
|
|
//READ FIFO LOOP
|
|
if (count_of_data >= 4 && (ShadowStatus & SD_RX_DATA_AVAILABLE))
|
|
{
|
|
*plBbuffer++ = *fifo_ptr;
|
|
count_of_data -= 4;
|
|
ShadowStatus=MCIStatus; //MA
|
|
if(ShadowStatus & SD_FIFO_DATA_OVERRUN)
|
|
break;
|
|
}
|
|
else if (count_of_data && count_of_data < 4)
|
|
{
|
|
//#if (DEBUG_SDCARD_DRIVER)
|
|
unsigned long length_of_data = MCIDataLength;
|
|
rtp_printf("Too much Length =%d and the count of data to be read =%d, read so far = %d \n",length_of_data, count_of_data, (length_of_data-count_of_data) );
|
|
//#endif //DEBUG_SDCARD_DRIVER
|
|
return -1;
|
|
}
|
|
ShadowStatus=MCIStatus ; //MA
|
|
if(ShadowStatus & SD_FIFO_DATA_OVERRUN)
|
|
{
|
|
//#if (DEBUG_SDCARD_DRIVER)
|
|
rtp_printf("DATA TIMEDOUT status == %X \n",ShadowStatus);
|
|
//#endif //DEBUG_SDCARD_DRIVER
|
|
return -1;
|
|
}
|
|
}
|
|
if (maxloops==0)
|
|
{
|
|
//#if (DEBUG_SDCARD_DRIVER)
|
|
rtp_printf("Loopmax exceeded\n");
|
|
//#endif //DEBUG_SDCARD_DRIVER
|
|
return -1;
|
|
}
|
|
else
|
|
return 0;
|
|
|
|
}
|
|
/* Note: remain is in bytes not in longs transfered */
|
|
static int RtSdBSP_PolledWriteXfer(unsigned long *pcBbuffer,unsigned long remain)
|
|
{
|
|
unsigned long *fifo_ptr;
|
|
unsigned long maxloops = 100000000;
|
|
fifo_ptr = (unsigned long *) 0xE008C080;
|
|
|
|
unsigned long status;
|
|
unsigned long *plBbuffer = (unsigned long *)pcBbuffer;
|
|
do {
|
|
int count;
|
|
|
|
if(remain > 32)
|
|
count = 32;
|
|
else
|
|
count = (int)remain;
|
|
|
|
status = MCIStatus;
|
|
|
|
if (status & TXFIFOHALFEMPTY)
|
|
{
|
|
*fifo_ptr = *plBbuffer ;
|
|
*(fifo_ptr+1 ) = *(plBbuffer+1 ) ;
|
|
*(fifo_ptr+2 ) = *(plBbuffer+2 ) ;
|
|
*(fifo_ptr+3 ) = *(plBbuffer+3 ) ;
|
|
*(fifo_ptr+4 ) = *(plBbuffer+4 ) ;
|
|
*(fifo_ptr+5 ) = *(plBbuffer+5 ) ;
|
|
*(fifo_ptr+6 ) = *(plBbuffer+6 ) ;
|
|
*(fifo_ptr+7 ) = *(plBbuffer+7 ) ;
|
|
|
|
plBbuffer+=8;
|
|
remain -= count;
|
|
}
|
|
|
|
if (remain == 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
RtSdBSP_Delay_micros(10);
|
|
maxloops--;
|
|
status = MCIStatus;
|
|
}
|
|
while (status & MCI_TXACTIVE && maxloops>0);
|
|
|
|
if(status & (1<<5) )
|
|
{
|
|
#if (DEBUG_SDCARD_DRIVER)
|
|
rtp_printf("DATA TIMEDOUT \n");
|
|
#endif //DEBUG_SDCARD_DRIVER
|
|
return -1; //TIMEOUT ERROR
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int RtSdBSP_Read_SCRSetup(SD_CARD_INFO * mmc_sd_card)
|
|
{
|
|
unsigned long DataCtrl;
|
|
MCIDataTimer = MA_DATA_TIMER_VALUE; //MA: Increased the time out, huge now, optimize later
|
|
MCIDataLength = SCR_LENGTH;
|
|
DataCtrl = ((1 << 0) | (1 << 1) | (LOG_SCR_LENGTH << 4));
|
|
MCIDataCtrl = DataCtrl;
|
|
return 0;
|
|
}
|
|
|
|
int RtSdBSP_Read_SCRTransfer(SD_CARD_INFO * mmc_sd_card,unsigned char *buf)
|
|
{
|
|
|
|
int ret_val=0;
|
|
unsigned long i,tmp,scr[2];
|
|
|
|
|
|
ret_val = RtSdBSP_PolledReadXfer(buf,SCR_LENGTH);
|
|
return ret_val;
|
|
}
|
|
|
|
void RtSdBSP_Read_SCRShutdown(SD_CARD_INFO * mmc_sd_card)
|
|
{
|
|
}
|
|
|
|
/*****************************************************************************************************
|
|
*
|
|
* Configuring the Interrupts for SDMMC
|
|
*
|
|
******************************************************************************************************/
|
|
#if (CONFIGURE_SDMMC_INTERRUPTS)
|
|
|
|
void RtSdBSP_FifoInterruptService(SD_CARD_INFO *pmmc_sd_card) @ "FASTMEM"
|
|
{
|
|
unsigned long *fifo_ptr;
|
|
unsigned long *plBbuffer;
|
|
unsigned long ShadowStatus = MCIStatus ;
|
|
MCIClear |= FIFO_INT_MASK;
|
|
fifo_ptr = (unsigned long *) 0xE008C080;
|
|
plBbuffer = (unsigned long *)pmmc_sd_card->byte_buffer;
|
|
if ( (ShadowStatus & (FIFO_TX_INT_MASK) ) && ( ShadowStatus & MMCSD_TX_ACTIVE ) )
|
|
{
|
|
int flush_output=0;
|
|
if (ShadowStatus & MMCSD_TX_FIFO_EMPTY)
|
|
{
|
|
if (pmmc_sd_card->bytes_left_to_transfer>=64)
|
|
{
|
|
*fifo_ptr = *plBbuffer ;
|
|
*(fifo_ptr+1 ) = *(plBbuffer+1 ) ;
|
|
*(fifo_ptr+2 ) = *(plBbuffer+2 ) ;
|
|
*(fifo_ptr+3 ) = *(plBbuffer+3 ) ;
|
|
*(fifo_ptr+4 ) = *(plBbuffer+4 ) ;
|
|
*(fifo_ptr+5 ) = *(plBbuffer+5 ) ;
|
|
*(fifo_ptr+6 ) = *(plBbuffer+6 ) ;
|
|
*(fifo_ptr+7 ) = *(plBbuffer+7 ) ;
|
|
*(fifo_ptr+8 ) = *(plBbuffer+8 ) ;
|
|
*(fifo_ptr+9 ) = *(plBbuffer+9 ) ;
|
|
*(fifo_ptr+10 ) = *(plBbuffer+10 ) ;
|
|
*(fifo_ptr+11 ) = *(plBbuffer+11 ) ;
|
|
*(fifo_ptr+12 ) = *(plBbuffer+12 ) ;
|
|
*(fifo_ptr+13 ) = *(plBbuffer+13 ) ;
|
|
*(fifo_ptr+14 ) = *(plBbuffer+14 ) ;
|
|
*(fifo_ptr+15 ) = *(plBbuffer+15 ) ;
|
|
plBbuffer+=16;
|
|
pmmc_sd_card->bytes_left_to_transfer-=64;
|
|
pmmc_sd_card->byte_buffer+=64;
|
|
}
|
|
else
|
|
flush_output = 1;
|
|
}//else if data fifo empty
|
|
else if(ShadowStatus & TXFIFOHALFEMPTY)
|
|
{
|
|
if (pmmc_sd_card->bytes_left_to_transfer>=64)
|
|
{
|
|
*fifo_ptr = *plBbuffer ;
|
|
*(fifo_ptr+1 ) = *(plBbuffer+1 ) ;
|
|
*(fifo_ptr+2 ) = *(plBbuffer+2 ) ;
|
|
*(fifo_ptr+3 ) = *(plBbuffer+3 ) ;
|
|
*(fifo_ptr+4 ) = *(plBbuffer+4 ) ;
|
|
*(fifo_ptr+5 ) = *(plBbuffer+5 ) ;
|
|
*(fifo_ptr+6 ) = *(plBbuffer+6 ) ;
|
|
*(fifo_ptr+7 ) = *(plBbuffer+7 ) ;
|
|
pmmc_sd_card->bytes_left_to_transfer-=32;
|
|
pmmc_sd_card->byte_buffer+=32;
|
|
plBbuffer+=8;
|
|
}
|
|
else
|
|
flush_output = 1;
|
|
}//if data fifo half empty
|
|
if (flush_output)
|
|
{
|
|
int i = pmmc_sd_card->bytes_left_to_transfer;
|
|
pmmc_sd_card->byte_buffer += i;
|
|
pmmc_sd_card->bytes_left_to_transfer = 0;
|
|
while (i > 0)
|
|
{
|
|
*fifo_ptr = *plBbuffer++;
|
|
i-=4;
|
|
}
|
|
}
|
|
}
|
|
else if ( (ShadowStatus & (FIFO_RX_INT_MASK) ) && ( ShadowStatus & MMCSD_RX_ACTIVE ) )
|
|
{
|
|
int flush_fifo=0;
|
|
if (ShadowStatus & SD_FIFO_FULL)
|
|
{
|
|
if (pmmc_sd_card->bytes_left_to_transfer>=64)
|
|
{
|
|
*plBbuffer = *fifo_ptr;
|
|
*(plBbuffer+1 ) = *(fifo_ptr+1 );
|
|
*(plBbuffer+2 ) = *(fifo_ptr+2 );
|
|
*(plBbuffer+3 ) = *(fifo_ptr+3 );
|
|
*(plBbuffer+4 ) = *(fifo_ptr+4 );
|
|
*(plBbuffer+5 ) = *(fifo_ptr+5 );
|
|
*(plBbuffer+6 ) = *(fifo_ptr+6 );
|
|
*(plBbuffer+7 ) = *(fifo_ptr+7 );
|
|
*(plBbuffer+8 ) = *(fifo_ptr+8 );
|
|
*(plBbuffer+9 ) = *(fifo_ptr+9 );
|
|
*(plBbuffer+10 ) = *(fifo_ptr+10 );
|
|
*(plBbuffer+11 ) = *(fifo_ptr+11 );
|
|
*(plBbuffer+12) = *(fifo_ptr+12);
|
|
*(plBbuffer+13) = *(fifo_ptr+13);
|
|
*(plBbuffer+14) = *(fifo_ptr+14);
|
|
*(plBbuffer+15) = *(fifo_ptr+15);
|
|
plBbuffer+=16;
|
|
pmmc_sd_card->bytes_left_to_transfer-=64;
|
|
pmmc_sd_card->byte_buffer+=64;
|
|
}
|
|
else
|
|
flush_fifo = 1;
|
|
}
|
|
else if (ShadowStatus & SD_FIFO_HALF_FULL)
|
|
{
|
|
if (pmmc_sd_card->bytes_left_to_transfer>=32)
|
|
{
|
|
*plBbuffer = *fifo_ptr;
|
|
*(plBbuffer+1 ) = *(fifo_ptr+1 );
|
|
*(plBbuffer+2 ) = *(fifo_ptr+2 );
|
|
*(plBbuffer+3 ) = *(fifo_ptr+3 );
|
|
*(plBbuffer+4 ) = *(fifo_ptr+4 );
|
|
*(plBbuffer+5 ) = *(fifo_ptr+5 );
|
|
*(plBbuffer+6 ) = *(fifo_ptr+6 );
|
|
*(plBbuffer+7 ) = *(fifo_ptr+7 );
|
|
plBbuffer+=8;
|
|
pmmc_sd_card->bytes_left_to_transfer-=32;
|
|
pmmc_sd_card->byte_buffer+=32;
|
|
}
|
|
else
|
|
flush_fifo = 1;
|
|
}
|
|
if (flush_fifo)
|
|
{
|
|
int i = pmmc_sd_card->bytes_left_to_transfer;
|
|
pmmc_sd_card->byte_buffer += i;
|
|
pmmc_sd_card->bytes_left_to_transfer = 0;
|
|
while (i>0)
|
|
{
|
|
*plBbuffer++= *fifo_ptr;
|
|
i-=4;
|
|
}
|
|
}
|
|
}
|
|
// if (!pmmc_sd_card->bytes_left_to_transfer)
|
|
// SIGNAL;
|
|
|
|
return;
|
|
}
|
|
|
|
void Card_Event_Isr(void) @ "FASTMEM"
|
|
{
|
|
unsigned long intr_mask,ShadowStatus;
|
|
SD_CARD_INFO * pmmc_sd_card = &mmc_sd_cards[SD_CARD_UNIT_NUM];
|
|
unsigned long *fifo_ptr = (unsigned long *) 0xE008C080;
|
|
unsigned long *plBbuffer = (unsigned long *)pmmc_sd_card->byte_buffer;
|
|
|
|
intr_mask = PVOPVO_T_splhigh();
|
|
ShadowStatus = MCIStatus;
|
|
/* handle MCI_STATUS interrupt */
|
|
if ( ShadowStatus & (MMCSD_DATA_CRC_FAIL | MMCSD_DATA_TIMEOUT | MMCSD_TX_UNDERRUN | MMCSD_RX_OVERRUN | MMCSD_START_BIT_ERR))
|
|
{
|
|
MCIClear |= MCI_CLEAR_ALL;
|
|
//MCI_DataErrorProcess_count++;
|
|
pmmc_sd_card->BspErrorStatus = ShadowStatus;
|
|
sd_sig_set(pmmc_sd_card);
|
|
VICAddress=0; /* Ack */
|
|
PVOPVO_T_splx(intr_mask);
|
|
return;
|
|
}
|
|
if (ShadowStatus & FIFO_INT_MASK)
|
|
{
|
|
// MCIClear |= FIFO_INT_MASK; // Done inside
|
|
RtSdBSP_FifoInterruptService(pmmc_sd_card);
|
|
pmmc_sd_card->BspFifoInterrupts += 1;
|
|
VICAddress=0; /* Ack the interrupt , we do it this way for USB??*/
|
|
PVOPVO_T_splx(intr_mask);
|
|
return;
|
|
}
|
|
if ( ShadowStatus & MMCSD_DATA_END) // |MMCSD_DATA_BLOCK_END))
|
|
{
|
|
MCIClear |= MMCSD_DATA_END;
|
|
sd_sig_set(pmmc_sd_card);
|
|
pmmc_sd_card->BspEndInterrupts += 1;
|
|
VICAddress=0; /* Ack the interrupt , we do it this way for USB??*/
|
|
PVOPVO_T_splx(intr_mask);
|
|
return;
|
|
}
|
|
{
|
|
MCIClear |= 0x3ff;
|
|
VICAddress=0; /* Ack the interrupt , we do it this way for USB??*/
|
|
PVOPVO_T_splx(intr_mask);
|
|
return;
|
|
}
|
|
#if (0)
|
|
else if ( ShadowStatus & CMD_INT_MASK )
|
|
{
|
|
/* Not Implemented Yet*/
|
|
//MCI_CmdProcess();
|
|
/* Ack the interrupt */
|
|
VICVectAddr0 = 0;
|
|
// PVOPVO_T_splx(intr_mask);
|
|
return;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//#define MCI_IRQENABLE \
|
|
// (MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK| \
|
|
// MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \
|
|
// MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK)
|
|
|
|
#define MCI_IRQENABLE \
|
|
(MCI_DATACRCFAILMASK|MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK||MCI_DATABLOCKENDMASK)
|
|
|
|
|
|
static void RtSdBSP_Enable_Card_Isr(void)
|
|
{
|
|
install_irq(VIC_MMC, (void *)Card_Event_Isr, SDMMC_PRIORITY);
|
|
VICIntEnable |= (1 << VIC_MMC);
|
|
}
|
|
|
|
|
|
|
|
#endif /* #if (CONFIGURE_SDMMC_INTERRUPTS) */
|
|
|
|
|
|
#if (ENABLE_DMA)
|
|
|
|
#define TCI 0
|
|
#define MEMWIDTH_READ 2
|
|
#define MEMWIDTH_WRITE 2
|
|
#define FIFOWIDTH 2
|
|
|
|
#define DBSIZEREAD 2 // Burst size 8
|
|
#define SBSIZEREAD 2 //??
|
|
#define DBSIZEWRITE 2 //??
|
|
#define SBSIZEWRITE 2 //??
|
|
|
|
#define DIREAD 1
|
|
#define DIWRITE 0
|
|
#define SIREAD 0
|
|
#define SIWRITE 1
|
|
#define TSIZE 0
|
|
|
|
#define MMCPERIPHERAL 0x04
|
|
#define DMAPERIPHERALTOMEMORY 0x06
|
|
#define DMAMEMORYTOPERIPHERAL 0x05
|
|
#define DMAMEMORYTOMEMORY 0x0
|
|
|
|
static void RtSdBSP_Dma_Setup(SD_CARD_INFO * mmc_sd_card,unsigned char *pBbuffer, int Reading)
|
|
{
|
|
unsigned long l;
|
|
|
|
/* Enable DMA */
|
|
l=DMACConfiguration;
|
|
if (!(l&1))
|
|
DMACConfiguration=1;
|
|
|
|
DMACIntTCClear=0x01;
|
|
DMACIntErrClr=0x01;
|
|
/* Disable the channel */
|
|
DMACC0Configuration = 0; // DMACC0Configuration&0xfffffffe;
|
|
|
|
if (Reading)
|
|
{
|
|
DMACC0SrcAddr = 0xE008C080; // MCI fifo
|
|
DMACC0DestAddr = (unsigned long) pBbuffer;
|
|
DMACC0LLI = 0; // No link just a single transaction.
|
|
l = (TCI<<31)|(DIREAD<<27)|(SIREAD<<26)|(MEMWIDTH_READ<<21)|(FIFOWIDTH<<18)|(DBSIZEREAD<<15)|(SBSIZEREAD<<12)|(TSIZE);
|
|
l |= (1<<31); // Enable TC
|
|
l |= mmc_sd_card->bytes_left_to_transfer>>2;
|
|
DMACC0Control = l;
|
|
l = 1|(MMCPERIPHERAL<<1)|(DMAPERIPHERALTOMEMORY<<11);
|
|
l |=0x10001; // HEREHERE - add lock
|
|
|
|
DMACC0Configuration = l;
|
|
}
|
|
else
|
|
{
|
|
DMACC0SrcAddr = (unsigned long) pBbuffer;
|
|
DMACC0DestAddr = 0xE008C080; // MCI fifo
|
|
DMACC0LLI = 0; // No link just a single transaction.
|
|
l = (TCI<<31)|(DIWRITE<<27)|(SIWRITE<<26)|(FIFOWIDTH<<21)|(MEMWIDTH_WRITE<<18)|(DBSIZEWRITE<<15)|(SBSIZEWRITE<<12)|(TSIZE);
|
|
l |= (1<<31); // Enable TC
|
|
l |= mmc_sd_card->bytes_left_to_transfer>>2;
|
|
DMACC0Control = l;
|
|
l = 1|(MMCPERIPHERAL<<6)|(DMAMEMORYTOPERIPHERAL<<11);
|
|
l |=0x10001; // HEREHERE - add lock
|
|
DMACC0Configuration = l;
|
|
}
|
|
|
|
}
|
|
|
|
static int RtSdBSP_Dma_Complete(SD_CARD_INFO * mmc_sd_card, int Reading)
|
|
{
|
|
unsigned long mcistatus, dmatcstatus, dmaerrorststatus;
|
|
unsigned long loops = 0;
|
|
int ret_val=-1;
|
|
while (loops++ < 1000000)
|
|
{
|
|
#if(1)
|
|
dmatcstatus = DMACRawIntTCStatus;
|
|
if (dmatcstatus)
|
|
{
|
|
// rtp_printf("DMA TC loops == %d\n", loops);
|
|
ret_val = 0;
|
|
break;
|
|
}
|
|
#endif
|
|
dmaerrorststatus=DMACRawIntErrorStatus;
|
|
if (dmaerrorststatus)
|
|
{
|
|
DMACIntErrClr=dmaerrorststatus;
|
|
rtp_printf("DMA status error\n");
|
|
ret_val = -1;
|
|
break;
|
|
}
|
|
|
|
mcistatus = MCIStatus;
|
|
if (mcistatus&(MCI_DATACRCFAILMASK|MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK))
|
|
{
|
|
MCIClear = mcistatus&(MCI_DATACRCFAILMASK|MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK|MCI_DATABLOCKENDMASK);
|
|
rtp_printf("Mci status error %d\n", mcistatus);
|
|
ret_val = -1;
|
|
}
|
|
#if (0)
|
|
if (mcistatus&(MCI_DATABLOCKENDMASK))
|
|
{
|
|
unsigned long l;
|
|
MCIClear = mcistatus&(MCI_DATACRCFAILMASK|MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK|MCI_DATABLOCKENDMASK);
|
|
ret_val = 0;
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return ret_val;
|
|
}
|
|
#endif /* (INCLUDE_DMA) */
|