#ifndef __SWM320_SDIO_H__
#define __SWM320_SDIO_H__


#define SD_CMD_GO_IDLE_STATE                       ((uint8_t)0)
#define SD_CMD_SEND_OP_COND                        ((uint8_t)1)
#define SD_CMD_ALL_SEND_CID                        ((uint8_t)2)
#define SD_CMD_SET_REL_ADDR                        ((uint8_t)3)
#define SD_CMD_SET_DSR                             ((uint8_t)4)
#define SD_CMD_HS_SWITCH                           ((uint8_t)6)
#define SD_CMD_SEL_DESEL_CARD                      ((uint8_t)7)
#define SD_CMD_SEND_IF_COND                        ((uint8_t)8)
#define SD_CMD_SEND_CSD                            ((uint8_t)9)
#define SD_CMD_SEND_CID                            ((uint8_t)10)
#define SD_CMD_STOP_TRANSMISSION                   ((uint8_t)12)
#define SD_CMD_SEND_STATUS                         ((uint8_t)13)
#define SD_CMD_SET_BLOCKLEN                        ((uint8_t)16)
#define SD_CMD_READ_SINGLE_BLOCK                   ((uint8_t)17)
#define SD_CMD_READ_MULT_BLOCK                     ((uint8_t)18)
#define SD_CMD_WRITE_SINGLE_BLOCK                  ((uint8_t)24)
#define SD_CMD_WRITE_MULT_BLOCK                    ((uint8_t)25)
#define SD_CMD_PROG_CID                            ((uint8_t)26)
#define SD_CMD_PROG_CSD                            ((uint8_t)27)
#define SD_CMD_APP_CMD                             ((uint8_t)55)

/*Following commands are SD Card Specific commands.
  SDIO_APP_CMD should be sent before sending these commands. */
#define SD_CMD_APP_SD_SET_BUSWIDTH                 ((uint8_t)6)
#define SD_CMD_SD_APP_STAUS                        ((uint8_t)13)
#define SD_CMD_SD_APP_SEND_NUM_WRITE_BLOCKS        ((uint8_t)22)
#define SD_CMD_SD_APP_OP_COND                      ((uint8_t)41)
#define SD_CMD_SD_APP_SET_CLR_CARD_DETECT          ((uint8_t)42)
#define SD_CMD_SD_APP_SEND_SCR                     ((uint8_t)51)
#define SD_CMD_SDIO_RW_DIRECT                      ((uint8_t)52)
#define SD_CMD_SDIO_RW_EXTENDED                    ((uint8_t)53)


#define SD_RESP_NO          0   //0 无响应
#define SD_RESP_32b         2   //2 32位响应
#define SD_RESP_128b        1   //1 128位响应
#define SD_RESP_32b_busy    3   //3 32位响应,check Busy after response

#define SD_BUSWIDTH_1b      0
#define SD_BUSWIDTH_4b      2

#define SD_RES_OK           0
#define SD_RES_ERR          1
#define SD_RES_TIMEOUT      2


typedef struct
{
  __IO uint8_t  CSDStruct;            // CSD structure
  __IO uint8_t  SysSpecVersion;       // System specification version
  __IO uint8_t  Reserved1;            // Reserved
  __IO uint8_t  TAAC;                 // Data read access-time 1
  __IO uint8_t  NSAC;                 // Data read access-time 2 in CLK cycles
  __IO uint8_t  MaxBusClkFrec;        // Max. bus clock frequency
  __IO uint16_t CardComdClasses;      //< Card command classes
  __IO uint8_t  RdBlockLen;           // Max. read data block length
  __IO uint8_t  PartBlockRead;        // Partial blocks for read allowed
  __IO uint8_t  WrBlockMisalign;      // Write block misalignment
  __IO uint8_t  RdBlockMisalign;      // Read block misalignment
  __IO uint8_t  DSRImpl;              // DSR implemented
  __IO uint8_t  Reserved2;            // Reserved
  __IO uint32_t DeviceSize;           // Device Size
  __IO uint8_t  MaxRdCurrentVDDMin;   // Max. read current @ VDD min
  __IO uint8_t  MaxRdCurrentVDDMax;   // Max. read current @ VDD max
  __IO uint8_t  MaxWrCurrentVDDMin;   // Max. write current @ VDD min
  __IO uint8_t  MaxWrCurrentVDDMax;   // Max. write current @ VDD max
  __IO uint8_t  DeviceSizeMul;        // Device size multiplier
  __IO uint8_t  EraseGrSize;          // Erase group size
  __IO uint8_t  EraseGrMul;           // Erase group size multiplier
  __IO uint8_t  WrProtectGrSize;      // Write protect group size
  __IO uint8_t  WrProtectGrEnable;    // Write protect group enable
  __IO uint8_t  ManDeflECC;           // Manufacturer default ECC
  __IO uint8_t  WrSpeedFact;          // Write speed factor
  __IO uint8_t  MaxWrBlockLen;        // Max. write data block length
  __IO uint8_t  WriteBlockPaPartial;  // Partial blocks for write allowed
  __IO uint8_t  Reserved3;            // Reserded
  __IO uint8_t  ContentProtectAppli;  // Content protection application
  __IO uint8_t  FileFormatGrouop;     // File format group
  __IO uint8_t  CopyFlag;             // Copy flag (OTP)
  __IO uint8_t  PermWrProtect;        // Permanent write protection
  __IO uint8_t  TempWrProtect;        // Temporary write protection
  __IO uint8_t  FileFormat;           // File Format
  __IO uint8_t  ECC;                  // ECC code
} SD_CSD;

typedef struct
{
  __IO uint8_t  ManufacturerID;       // ManufacturerID
  __IO uint16_t OEM_AppliID;          // OEM/Application ID
  __IO uint32_t ProdName1;            // Product Name part1
  __IO uint8_t  ProdName2;            // Product Name part2
  __IO uint8_t  ProdRev;              // Product Revision
  __IO uint32_t ProdSN;               // Product Serial Number
  __IO uint8_t  Reserved1;            // Reserved1
  __IO uint16_t ManufactDate;         // Manufacturing Date
} SD_CID;


#define SDIO_STD_CAPACITY_SD_CARD_V1_1             ((uint32_t)0x00000000)
#define SDIO_STD_CAPACITY_SD_CARD_V2_0             ((uint32_t)0x00000001)
#define SDIO_HIGH_CAPACITY_SD_CARD                 ((uint32_t)0x00000002)
#define SDIO_MULTIMEDIA_CARD                       ((uint32_t)0x00000003)
#define SDIO_SECURE_DIGITAL_IO_CARD                ((uint32_t)0x00000004)
#define SDIO_HIGH_SPEED_MULTIMEDIA_CARD            ((uint32_t)0x00000005)
#define SDIO_SECURE_DIGITAL_IO_COMBO_CARD          ((uint32_t)0x00000006)
#define SDIO_HIGH_CAPACITY_MMC_CARD                ((uint32_t)0x00000007)


typedef struct
{
  SD_CSD SD_csd;
  SD_CID SD_cid;
  uint64_t CardCapacity;  // Card Capacity
  uint32_t CardBlockSize; // Card Block Size
  uint16_t RCA;
  uint8_t CardType;
} SD_CardInfo;


extern SD_CardInfo SD_cardInfo;

uint32_t SDIO_Init(uint32_t freq);
uint32_t SDIO_BlockWrite(uint32_t block_addr, uint32_t buff[]);
uint32_t SDIO_BlockRead(uint32_t block_addr, uint32_t buff[]);

uint32_t SDIO_MultiBlockWrite(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]);
uint32_t SDIO_MultiBlockRead(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]);

uint32_t SDIO_DMABlockWrite(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]);
uint32_t SDIO_DMABlockRead(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]);

uint32_t _SDIO_SendCmd(uint32_t cmd, uint32_t arg, uint32_t resp_type, uint32_t *resp_data, uint32_t have_data, uint32_t data_read, uint16_t block_cnt, uint32_t use_dma);

#define SDIO_SendCmd(cmd, arg, resp_type, resp_data)                                      _SDIO_SendCmd(cmd, arg, resp_type, resp_data, 0, 0, 0, 0)
#define SDIO_SendCmdWithData(cmd, arg, resp_type, resp_data, data_read, block_cnt)        _SDIO_SendCmd(cmd, arg, resp_type, resp_data, 1, data_read, block_cnt, 0)
#define SDIO_SendCmdWithDataByDMA(cmd, arg, resp_type, resp_data, data_read, block_cnt)   _SDIO_SendCmd(cmd, arg, resp_type, resp_data, 1, data_read, block_cnt, 1)

void parseCID(uint32_t CID_Tab[4]);
void parseCSD(uint32_t CID_Tab[4]);

uint32_t calcSDCLKDiv(uint32_t freq_sel);

#endif //__SWM320_SDIO_H__