/*****************************************************************************
* mci.c: SD/MMC module C file for NXP LPC177x_8x Family Microprocessors
*
* Copyright(C) 2009, NXP Semiconductor
* All rights reserved.
*
* History
* 2009.05.26 ver 1.00 Prelimnary version, first Release
*
******************************************************************************/
#include "lpc177x_8x.h"
#include "lpc_types.h"
#include "lpc177x_8x_mci.h"
#include "lpc177x_8x_gpdma.h"
#include "lpc177x_8x_clkpwr.h"
#define DMA_MCI_SIZE BLOCK_LENGTH
#define MCI_DMA_WRITE_CHANNEL (0)
#define MCI_DMA_READ_CHANNEL (1)
#define _SHIFT(x) (1 << x)
#define _XSHIFT(x, y) (x << y)
#define _SHIFT_(x) (1 >> x)
#define _XSHIFT_(x, y) (x >> y)
#define MCI_CARDSTATUS_READYFORDATA_P0S (8)
#define MCI_CARDSTATUS_CURRENTSTATE_POS (9)
#define MCI_CARDSTATUS_CURRENTSTATE_BMASK (0x0F)
#define CARDSTATEOF(x) (_XSHIFT(x, MCI_CARDSTATUS_CURRENTSTATE_POS) & MCI_CARDSTATUS_CURRENTSTATE_BMASK)
#define MCI_CMD8_VOLTAGESUPPLIED_POS (8)
#define MCI_CMD8_VOLTAGESUPPLIED_BMASK (0xFF)
#define MCI_CMD8_CHECKPATTERN_POS (0)
#define MCI_CMD8_CHECKPATTERN_BMASK (0xFF)
#define MCI_ACMD41_HCS_POS (30)
#define MCI_OUTPUT_MODE_PUSHPULL (0)
#define MCI_OUTPUT_MODE_OPENDRAIN (1)
#define MCI_PWRCTRL_OPENDRAIN_POS (6)
#define MCI_PWRCTRL_OPENDRAIN_NUMBIT (1)
#define MCI_PWRCTRL_OPENDRAIN_BMASK (0x01)
#define MCI_CID_MANUFACTURER_ID_WPOS (24) //in word 0
#define MCI_CID_MANUFACTURER_ID_WBMASK (0xFF)
#define MCI_CID_OEMAPPLICATION_ID_WPOS (8) //in word 0
#define MCI_CID_OEMAPPLICATION_ID_WBMASK (0xFFFF)
#define MCI_CID_PRODUCTNAME_ID_H_WPOS (0) //in word 0
#define MCI_CID_PRODUCTNAME_ID_H_WBMASK (0xFF)
#define MCI_CID_PRODUCTNAME_ID_L_WPOS (0) //in word 1
#define MCI_CID_PRODUCTNAME_ID_L_WBMASK (0xFFFFFFFF)
#define MCI_CID_PRODUCTREVISION_ID_WPOS (24) //in word 2
#define MCI_CID_PRODUCTREVISION_ID_WBMASK (0xFF)
#define MCI_CID_PRODUCTSERIALNUM_ID_H_WPOS (0) //in word 2
#define MCI_CID_PRODUCTSERIALNUM_ID_H_WBMASK (0x00FFFFFF)
#define MCI_CID_PRODUCTSERIALNUM_ID_L_WPOS (24) //in word 3
#define MCI_CID_PRODUCTSERIALNUM_ID_L_WBMASK (0xFF)
#define MCI_CID_PRODUCTSERIALNUM_ID_WBMASK (0xFFFFFFFF)
#define MCI_CID_RESERVED_ID_WPOS (20) //in word 3
#define MCI_CID_RESERVED_ID_WBMASK (0x1F)
#define MCI_CID_MANUFACTURINGDATE_ID_WPOS (8) //in word 3
#define MCI_CID_MANUFACTURINGDATE_ID_WBMASK (0x0FFF)
#define MCI_CID_CHECKSUM_ID_WPOS (1) //in word 3
#define MCI_CID_CHECKSUM_ID_WBMASK (0x7F)
#define MCI_CID_UNUSED_ID_WPOS (0) //in word 3
#define MCI_CID_UNUSED_ID_WBMASK (0x01)
volatile uint32_t MCI_Block_End_Flag = 0;
volatile uint32_t CardRCA;
volatile en_Mci_CardType MCI_CardType;
// Terminal Counter flag, Error Counter flag for Channel 0
uint32_t dmaWrCh_TermianalCnt, dmaWrCh_ErrorCnt;
uint32_t dmaRdCh_TermianalCnt, dmaRdCh_ErrorCnt;
uint32_t MCI_ReadFifo(uint32_t * dest);
uint32_t MCI_WriteFifo(uint32_t * src);
volatile uint8_t* dataSrcBlock;
volatile uint8_t* dataDestBlock;
volatile uint32_t txBlockCnt=0, rxBlockCnt=0;
/******************************************************************************
** Function name: MCI_ReadFifo related
**
** Descriptions:
**
**
** parameters: None
** Returned value: None
**
******************************************************************************/
uint32_t MCI_ReadFifo(uint32_t * dest)
{
//copy 8 words (32 bytes) from FIFO
memcpy(dest, LPC_MCI->FIFO, 32);
return 0;
}
/******************************************************************************
** Function name: MCI_WriteFifo related
**
** Descriptions:
**
**
** parameters: None
** Returned value: None
**
******************************************************************************/
uint32_t MCI_WriteFifo(uint32_t * src)
{
//copy 8 words (32 bytes) from FIFO
memcpy(LPC_MCI->FIFO, src, 32);
return 0;
}
/******************************************************************************
** Function name: MCI_Interrupt related
**
** Descriptions: MCI interrupt handler and related APIs
**
**
** parameters: None
** Returned value: None
**
******************************************************************************/
void MCI_TXEnable( void )
{
#if MCI_DMA_ENABLED
LPC_MCI->MASK0 |= ((DATA_END_INT_MASK)|(ERR_TX_INT_MASK)); /* Enable TX interrupts only */
#else
LPC_MCI->MASK0 |= ((FIFO_TX_INT_MASK)|(DATA_END_INT_MASK)|(ERR_TX_INT_MASK)); /* FIFO TX interrupts only */
#endif
return;
}
/*****************************************************************/
void MCI_TXDisable( void )
{
#if MCI_DMA_ENABLED
LPC_MCI->MASK0 &= ~((DATA_END_INT_MASK)|(ERR_TX_INT_MASK)); /* Enable TX interrupts only */
#else
LPC_MCI->MASK0 &= ~((FIFO_TX_INT_MASK)|(DATA_END_INT_MASK)|(ERR_TX_INT_MASK)); /* FIFO TX interrupts only */
#endif
return;
}
/*****************************************************************/
void MCI_RXEnable( void )
{
#if MCI_DMA_ENABLED
LPC_MCI->MASK0 |= ((DATA_END_INT_MASK)|(ERR_RX_INT_MASK)); /* Enable RX interrupts only */
#else
LPC_MCI->MASK0 |= ((FIFO_RX_INT_MASK)|(DATA_END_INT_MASK)|(ERR_RX_INT_MASK)); /* FIFO RX interrupts only */
#endif
return;
}
/*****************************************************************/
void MCI_RXDisable( void )
{
#if MCI_DMA_ENABLED
LPC_MCI->MASK0 &= ~((DATA_END_INT_MASK)|(ERR_RX_INT_MASK)); /* Enable TX interrupts only */
#else
LPC_MCI->MASK0 &= ~((FIFO_RX_INT_MASK)|(DATA_END_INT_MASK)|(ERR_RX_INT_MASK)); /* FIFO TX interrupts only */
#endif
return;
}
/******************************************************************************
** Function name: MCI_CheckStatus
**
** Descriptions: MCI Check status before and after the block read and
** write. Right after the block read and write, this routine
** is important that, even the FIFO is empty, complete
** block has been sent, but, data is still being written
** to the card, this routine is to ensure that the data
** has been written based on the state of the card, not
** by the length being set.
**
** parameters: None
** Returned value: TRUE or FALSE
**
******************************************************************************/
uint32_t MCI_CheckStatus(void)
{
uint32_t respValue, retval = MCI_FUNC_FAILED;
while (1)
{
if (MCI_GetCardStatus(&respValue) != MCI_FUNC_OK)
{
break;
}
else
{
/* The only valid state is TRANS per MMC and SD state diagram.
RCV state may be seen, but, 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 & _SHIFT(MCI_CARDSTATUS_READYFORDATA_P0S)))
{
retval = MCI_FUNC_NOT_READY;
}
else if(CARDSTATEOF(respValue) != MCI_CARDSTATE_TRAN)
{
/* Should be in STANDBY state now and ready */
retval = MCI_FUNC_ERR_STATE;
}
else
{
return MCI_FUNC_OK;
}
}
}
return retval;
}
/******************************************************************************
** Function name: MCI_CmdProcess
**
** Descriptions: Called by MCI interrupt handler
** To simplify the process, for card initialization, the
** CMD interrupts are disabled.
**
**
** parameters: None
** Returned value: None
**
******************************************************************************/
void MCI_CmdProcess( void )
{
uint32_t MCIStatus;
MCIStatus = LPC_MCI->STATUS;
if ( MCIStatus & MCI_CMD_CRC_FAIL )
{
LPC_MCI->CLEAR = MCI_CMD_CRC_FAIL;
}
if ( MCIStatus & MCI_CMD_TIMEOUT )
{
LPC_MCI->CLEAR = MCI_CMD_TIMEOUT;
}
/* Cmd Resp End or Cmd Sent */
if ( MCIStatus & MCI_CMD_RESP_END )
{
LPC_MCI->CLEAR = MCI