/* ---------------------------------------------------------------------------
 * mmc.h                                                (c) 2008 Micro-key bv
 * ---------------------------------------------------------------------------
 * Micro-key bv
 * Industrieweg 28, 9804 TG Noordhorn
 * Postbus 92, 9800 AB Zuidhorn
 * The Netherlands
 * Tel: +31 594 503020
 * Fax: +31 594 505825
 * Email: support@microkey.nl   
 * Web: www.microkey.nl
 * ---------------------------------------------------------------------------
 * Description: 
 * ---------------------------------------------------------------------------
 * Version(s):  0.1, Apr 22, 2008, MMi
 *                   Creation.
 * ---------------------------------------------------------------------------
 */
#ifndef __MMC_H
#define __MMC_H 

/* ---------------------------------------------------------------------------
 * System include files.
 * ---------------------------------------------------------------------------
 */
#include "LPC23xx.h"
#include "types.h"
/* ---------------------------------------------------------------------------
 * Application include files.
 * ---------------------------------------------------------------------------
 */

/* ---------------------------------------------------------------------------
 * Constant and macro definitions.
 * ---------------------------------------------------------------------------
 */
#ifdef MMC_GLOBAL
#define MMC_EXTERN
#else
#define MMC_EXTERN  extern
#endif

extern void Dly100us(void *arg);

#define MMC_DISK_INFO
#define MMC_DISK_LUN  0

/* Hardware depends definitions                                             */
#define IdentificationModeClock     400000
#define PC_PCSPI1                   (1<<10)
#define PC_PCSPI0                   (1<<8)

#define RTC_OSC_FREQ                (32768UL)

#define RD_TIME_OUT               100LL /* SD Max. Block Read Access Time   */
#define WR_TIME_OUT               250LL /* SD Max. Block Write Access Time  */

#define OcrReg                      0x00FF8000

/* Card Status register                                                     */
#define READY_FOR_DATA      (1UL <<  8)
#define CURRENT_STATE     (0xFUL <<  9)
#define ERASE_RESET         (1UL << 13)
#define CARD_ECC_DISABLED   (1UL << 14)
#define WP_ERASE_SKIP       (1UL << 15)
#define CID_CSD_OVERWRITE   (1UL << 16)
#define ERROR               (1UL << 17)
#define ILLEGAL_COMMAND     (1UL << 22)
#define COM_CRC_ERROR       (1UL << 23)
#define WP_VIOLATION        (1UL << 26)
#define ERASE_PARAM         (1UL << 27)
#define ERASE_SEQ_ERROR     (1UL << 28)
#define BLOCK_LEN_ERROR     (1UL << 29)
#define ADDRESS_ERROR       (1UL << 30)
#define OUT_OF_RANGE        (1UL << 31)

/* Card states                                                              */
#define CARD_IDLE           (0UL << 9)
#define CARD_READY          (1UL << 9)
#define CARD_IDENT          (2UL << 9)
#define CARD_STBY           (3UL << 9)
#define CARD_TRAN           (4UL << 9)
#define CARD_DATA           (5UL << 9)
#define CARD_RCV            (6UL << 9)
#define CARD_PRG            (7UL << 9)
#define CARD_DIS            (8UL << 9)

#define MmcDly_1ms(Delay) Dly100us((void*)(10 * Delay))


/* WORKAROUND
 * As long as MCI_CP and MCI_WP are swapped, right PinMapping 
 * is done here. 
 * After Hardware Update, simply use commented PinMasks instead
 * of the corrected ones.
 */

// MMC/SD card switches
// Card present
// \MARK NEW PINSETTINGS FOR TESTER (2) and IO_CTRL (1)
#if ((PINSET_TESTER == 1) || (PINSET_TESTER == 2)) 
#define MMC_CP_MASK         (1UL << 4)
#define MMC_CP_DIR          FIO0PIN1
#define MMC_CP_FDIR         FIO0DIR
#define MMC_CP_IO           FIO0PIN1
#define MMC_CP_FIO          FIO0PIN1
#define MMC_CP_MODE         PINMODE1    /* Bit 12&13 */
#else
/* Pin 87 (P0.17) */
#define MMC_CP_MASK         (1UL << 1)
#define MMC_CP_DIR          FIO0PIN2
#define MMC_CP_FDIR         FIO0DIR
#define MMC_CP_IO           FIO0PIN2
#define MMC_CP_FIO          FIO0PIN2
#define MMC_CP_MODE         PINMODE1
#endif


// Card write protect
// \MARK NEW PINSETTINGS FOR TESTER (2) and IO_CTRL (1)
#if ((PINSET_TESTER == 1) || (PINSET_TESTER == 2)) 
#define MMC_WP_MASK         (1UL << 3)
#define MMC_WP_DIR          FIO0DIR
#define MMC_WP_FDIR         FIO0DIR
#define MMC_WP_IO           FIO0PIN1
#define MMC_WP_FIO          FIO0PIN1
#define MMC_WP_MODE         PINMODE1    /* Bit 13&14 */
#else
/* Pin 64 (P1.29) */
#define MMC_WP_MASK         (1UL << 5)
#define MMC_WP_DIR          FIO1DIR3
#define MMC_WP_FDIR         FIO1DIR
#define MMC_WP_IO           FIO1PIN3
#define MMC_WP_FIO          FIO1PIN3
#define MMC_WP_MODE         PINMODE3
#endif


#define DMA_MMCSD           4           /* MMC/SD                           */

#define MCI_PCLK_OFFSET     56

#define I_RC_OSC_FREQ   (4000000)
#define MAIN_OSC_FREQ   (12000000)
/* ---------------------------------------------------------------------------
 * Type definitions.
 * ---------------------------------------------------------------------------
 */

typedef enum _DiskStatusCode_t
{
  DiskCommandPass = 0, DiskNotReady, DiskNotPresent,
  DiskParametersError, DiskMiscompareError, DiskChanged,
  DiskUknowError,
} DiskStatusCode_t;

typedef enum _DiskIoRequest_t
{
  DiskWrite = 0, DiskRead, DiskVerify,
} DiskIoRequest_t;

typedef enum _DiskInfoType_t
{
  DiskInquiry = 0, DiskFormatCapacity,
} DiskInfoType_t;

typedef enum _DiskType_t
{
  DiskMMC, DiskSD, DiskUnknow,
} DiskType_t;

typedef struct _DiskCtrlBlk_t
{
  UINT32  BlockNumb;
  UINT32  BlockSize;
  DiskStatusCode_t DiskStatus;
  DiskType_t DiskType;
  BOOLEAN WriteProtect;
  BOOLEAN MediaChanged;
} DiskCtrlBlk_t, *pDiskCtrlBlk_t;

typedef enum _MmcState_t
    {
    MmcOk = 0,
    MmcNoPresent = 1,
    MmcNoResponse = 2 ,
    MmcCardError = 3,
    MmcMiscompare = 4,
    MmcDmaError = 5,
    MmcProtect = 6
    } MmcState_t;

typedef enum _MmcSpiCmdInd_t
    {
    CMD0 = 0,       /* Resets the MultiMediaCard                            */
    CMD1,           /* Activates card’s init process                        */
    CMD2,           /* Asks all cards to send its card identification (CID) */
    CMD3,           /* Set relative address                                 */
    CMD7,           /* Select/deselect card the card is selected by its own */
                    /* relative address and deselected by other address.    */
                    /* address 0 deselects all                              */
    CMD9,           /* Asks the card to send its card-specific data (CSD)   */
    CMD10,          /* Asks the card to send its card identification (CID)  */
    CMD12,          /* Stop transmission on multiple block read             */
    CMD13,          /* Asks the selected card to send its status register   */
    CMD16,          /* Selects a block length (in bytes) for all following  */
                    /* block commands (read and write)                      */
    CMD17,          /* Read block of size selected in SET_BLOCKLEN command  */
    CMD18,          /* Continuously transfers data blocks from card to host */
                    /* until interrupted by a Stop command or the requested */
                    /* number of data blocks transmitted                    */
    CMD24,          /* Write block of size selected in SET_BLOCKLEN command */
    CMD25,          /* Continuously writes blocks of data until ‘Stop Tran’ */
                    /* Token or the requested number of blocks received     */
    CMD27,          /* Programming of the programmable bits of the CSD      */
    CMD28,          /* If the card has write protection features, this      */
                    /* command sets the write protection bit of the         */
                    /* addressed group. The properties of write protection  */
                    /* are coded in the card specific data (WP_GRP_SIZE).   */
    CMD29,          /* If the card has write protection features, this      */
                    /* command clears protection bit of the addressed group */
    CMD30,          /* If the card has write protection features, this      */
                    /* command asks the card to send the status of the write*/
                    /* protection bits                                      */
    CMD32,          /* Sets the address of first sector of the erase group  */
    CMD33,          /* Sets the address of the last sector in a continuous  */
                    /* range within selected erase group, or the address    */
                    /* of a single sector to be selected for erase          */
    CMD34,          /* Removes one previously selected sector from the      */
                    /* erase selection                                      */
    CMD35,          /* Sets the address of the first erase group within a   */
                    /* range to be selected for erase                       */
    CMD36,          /* Sets the address of the last erase group within a    */
                    /* continuous range to be selected for erase            */
    CMD37,          /* Removes one previously selected erase group from the */
                    /* erase selection.                                     */
    CMD38,          /* Erases all previously selected sectors               */
    CMD42,          /* Used to set/reset the password or lock/unlock the    */
                    /* card. The size of the Data Block is defined by the   */
                    /* ET_BLOCK_LEN command                                 */
    CMD55,          /* Notifies the card that the next command is an        */
                    /* application specific command (Non standard command)  */
    CMD56,          /* Used either to transfer a Data Block to the card or  */
                    /* to get a Data Block from the card for general        */
                    /* purpose/application specific commands. The size      */
                    /* of Data Block is defined with SET_BLOCK_LEN command  */
    ACMD6,          /* Defines data bus width (’00’=1bit or’10’=4 bits bus) */
                    /* (Only for SD)                                        */
    ACMD41,         /* Activates card initialization process (Only for SD)  */
    CMD_END         /* End of commands index                                */
    } MmcSpiCmdInd_t;

typedef enum _MmcAgmType_t
    {
    MmcNoArg = 0,
    MmcBlockLen, 
    MmcDataAdd, 
    MmcRelAddr, 
    MmcOcr
    } MmcAgmType_t;

typedef enum _MmcRespType_t
    {
    MmcNoResp = 0,
    MmcR1,
    MmcR1b,
    MmcR2,
    MmcR3
    } MmcRespType_t;

typedef struct _MmcCommads_t
    {
        UINT8 TxData;
        MmcAgmType_t Arg;
        MmcRespType_t Resp;
    } MmcCommads_t;

typedef union _DataCtrl_t
    {
        UINT32 Data;
        struct
            {
                UINT32 ENABLE : 1;
                UINT32 DIRECTION : 1;
                UINT32 MODE : 1;
                UINT32 DMAENABLE : 1;
                UINT32 BLOCKSIZE : 4;
                UINT32 :24;
            };
    } DataCtrl_t, *pDataCtrl_t;
    
typedef struct _Mmc3FormatCapDescriptor_t
    {
      UINT8 NumberofBlocks[4];
      struct
      {
        UINT8 DescriptorType : 2;
        UINT8 FormatType     : 6;
      };
      UINT8 BlockLength[3];
    } Mmc3FormatCapDescriptor_t, *pMmc3FormatCapDescriptor_t;
    
typedef struct _Mmc3FormatCapResponse_t
    {
      UINT8 Reserved0;
      UINT8 Reserved1;
      UINT8 Reserved2;
      UINT8 CapacityListLength;
      Mmc3FormatCapDescriptor_t MaximumDescriptor;
    } Mmc3FormatCapResponse_t, * pMmc3FormatCapResponse_t;
    
typedef enum _SpcPeripheralDeviceType_t
    {
      SbcDirectAccess = 0, SscSequentialAccess,SSCPrinter,SpcProcessor,
      ScbWriteOnce,Mmc2CDROM,Scsi2Scanner,SbcOpticalMemory,
      SmcMediumChanger,Scsi2Communications,DefinedByASCIT8_1,DefinedByASCIT8_2,
      Scc2StorageArrayController,SesEnclosureServices,RbcSimplifiedDirectAccess,
      OcrwOpticalCardReader,BridgingExpanders,OsdObjectBasedStorage, UnknowType = 0x1F,
    } SpcPeripheralDeviceType_t;
    
typedef enum _FormatCapacityDescType_t
    {
      UnformattedMedia = 1, FormattedMedia, NoMediaPresent,
    } FormatCapacityDescType_t;

/* ---------------------------------------------------------------------------
 * Variable declarations.
 * ---------------------------------------------------------------------------
 */

/* ---------------------------------------------------------------------------
 * Function declarations.
 * ---------------------------------------------------------------------------
 */

extern UINT32 SYS_GetFpclk(UINT32 Periphery);

/* ---------------------------------------------------------------------------
 * Function: MmcPresent
 * 
 * checks if a Card is inserted.
 * 
 * Parameters: void
 * 
 * Return: BOOLEAN - true if Card is inserted, false if not
 * ---------------------------------------------------------------------------
 */
inline BOOLEAN MmcPresent(void);

/* ---------------------------------------------------------------------------
 * Function: MmcWriteProtect
 * 
 * checks if inserted Card is write protected.
 * 
 * Parameters: void
 * 
 * Return: BOOLEAN - true if Card is protected, false if not
 * ---------------------------------------------------------------------------
 */
inline BOOLEAN MmcWriteProtect(void);

/* ---------------------------------------------------------------------------
 * Function: MmcSetClockFreq
 * 
 * Sets SPI Clock Frequency
 * 
 * Parameters: UINT32 - Frequency
 * 
 * Return: UINT32
 * ---------------------------------------------------------------------------
 */
UINT32 MmcSetClockFreq(UINT32 Frequency);

/* ---------------------------------------------------------------------------
 * Function: MmcInit
 * 
 * Initialises the MMC Interface and sets it to SPI Mode. Sets Card Present
 * and WriteProtect Pins.
 * 
 * Parameters: void
 * 
 * Return: void
 * ---------------------------------------------------------------------------
 */
void MmcInit(void);

/* ---------------------------------------------------------------------------
 * Function: MmcPowerDown
 * 
 * Sets to PowerDown state
 * 
 * Parameters: void
 * 
 * Return: void
 * ---------------------------------------------------------------------------
 */
void MmcPowerDown(void);

/* ---------------------------------------------------------------------------
 * Function: MmcSendCmd
 * 
 * Implements and sends a Command to MMC
 * 
 * Parameters: MmcSpiCmdInd_t ComdInd - specific Command
 *             UINT32 Arg             - Command Argument
 * 
 * Return: MmcState_t - Response from Card
 * ---------------------------------------------------------------------------
 */
MmcState_t MmcSendCmd(MmcSpiCmdInd_t ComdInd, pUINT32 pArg);

/* ---------------------------------------------------------------------------
 * Function: MmcInitMedia
 * 
 * Detects and initialises a connected MMC
 * 
 * Parameters: void
 * 
 * Return: MmcState_t - Response from Card
 * ---------------------------------------------------------------------------
 */
MmcState_t MmcInitMedia(void);

/* ---------------------------------------------------------------------------
 * Function: MmcCsdImplement
 * 
 * Implement Data from CSD
 * 
 * Parameters: void
 * 
 * Return: void
 * ---------------------------------------------------------------------------
 */
void MmcCsdImplemet(void);

/* ---------------------------------------------------------------------------
 * Function: MmcVerify
 * 
 * Verifies a MMC
 * 
 * Parameters: const UINT8 * pData - Pointer to Data
 *             UINT32 Add          - Address of Data
 *             UINT32 Length       - Length of Data
 * 
 * Return: MmcState_t - Response from Card
 * ---------------------------------------------------------------------------
 */
inline MmcState_t MmcVerify(const UINT8 * pData, UINT32 Add,
        UINT32 Length);

/* ---------------------------------------------------------------------------
 * Function: MmcGetLastError
 * 
 * Returns last occured ERROR
 * 
 * Parameters: void
 * 
 * Return: UINT32 - Last occured Error
 * ---------------------------------------------------------------------------
 */
UINT32 MmcGetLastError(void);

/* ---------------------------------------------------------------------------
 * Function: MmcStatusUpdate
 * 
 * Updates the status of SD/MMC Card
 * 
 * Parameters: void
 * 
 * Return: void
 * ---------------------------------------------------------------------------
 */
void MmcStatusUpdate(void);

/* ---------------------------------------------------------------------------
 * Function: MmcDiskInit
 * 
 * Initialises MMC/SD Disk
 * 
 * Parameters: void
 * 
 * Return: void
 * ---------------------------------------------------------------------------
 */
void MmcDiskInit(void);

#ifdef MMC_DISK_INFO
/* ---------------------------------------------------------------------------
 * Function: MmcDiskInfo
 * 
 * Returns Pointer to Info Structure of inserted Disk
 * 
 * Parameters: pUINT8 pData                - Pointer to Data
 *             DiskInfoType_t DiskInfoType - Info Type
 * 
 * Return: UINT32
 * ---------------------------------------------------------------------------
 */
UINT32 MmcDiskInfo(pUINT8 pData, DiskInfoType_t DiskInfoType);
#endif // MMC_DISK_INFO
/* ---------------------------------------------------------------------------
 * Function: MmcGetDiskCtrlBkl
 * 
 * Returns Pointer to Control Block Structure
 * 
 * Parameters: void
 * 
 * Return: pDiskCtrlBlock_t - Pointer to Control Block
 * ---------------------------------------------------------------------------
 */
pDiskCtrlBlk_t MmcGetDiskCtrlBkl(void);


UINT32 SYS_GetFSclk(void);


UINT32 SYS_GetFPclk(UINT32 Periphery);

/*************************************************************************
 * Function Name: Dly100us
 * Parameters: void *arg
 * Return: void
 *
 * Description: Delay [100us]
 *      
 *************************************************************************/
void Dly100us(void *arg);



#endif // __MMC_H


