/*  ============================================================================
 *   Copyright (c) Texas Instruments Inc 2015
 *
 *   Use of this software is controlled by the terms and conditions found in the
 *   license agreement under which this software has been supplied.
 *   ===========================================================================
 */
/** ============================================================================
 example for USIM initialization and read/write driver on KeyStone device
 only support mobile phone card for now
 * =============================================================================
 *  Revision History
 *  ===============
 *  Feb 27, 2015 Brighton Feng  file created
 * =============================================================================*/
#ifndef _KEYSTONE_USIM_H
#define _KEYSTONE_USIM_H

#include <tistdtypes.h>
#include <cslr_usimocp.h>

#define USIM_MAX_ATR_LENGTH 	40

#define USIM_RX_BUF_BYTE_SIZE 	512

//USIM command instructions
#define USIM_INS_SELECT		    0xa4
#define USIM_INS_READ_BINARY	0xb0
#define USIM_INS_READ_RECORD	0xb2
#define USIM_INS_GET_RESPONSE	0xc0

#define USIM_CLA                0xA0

#define USMI_MAX_EXPECT_BYTES 	0	/*256 bytes*/

//USIM file ID
#define USIM_MF               0x3f00
#define USIM_EF_ICCID         0x2fe2
#define USIM_DF_TELECOM       0x7f10
#define USIM_DF_GSM           0x7f20
#define USIM_EF_SMS           0x6f3c
#define USIM_EF_IMSI          0x6f07

//status return by UICC
#define USIM_SW1_SUCCESS         0x90
#define USIM_SW1_SHORT           0x9f
#define USIM_SW1_MEM_ERR         0x92
#define USIM_SW1_EF_ERR          0x94
#define USIM_SW1_SEC_ERR         0x98
#define USIM_SW1_CORRECT_COMMAND 0x9F
#define USIM_SW1_GET_RESPONSE    0x61
#define USIM_SW1_REPEAT_COMMAND  0x6C

#define USIM_IRQ_RXDMA_RDY_SHIFT 	(15)
#define USIM_IRQ_RXDMA_RDY_MASK 	(1<<15)
#define USIM_IRQ_RXDMA_RDY_MASK 	(1<<15)

/*USIM clock speed = (main core speed)/64/(programable divider)*/
typedef enum {
	USIM_CLK_DIV_2_MASK = (0<<CSL_USIMOCP_USIMCONF2_CONFSCLKMODE_SHIFT)|(0<<CSL_USIMOCP_USIMCONF2_CONFSCLKDIV_SHIFT),
	USIM_CLK_DIV_4_MASK = (0<<CSL_USIMOCP_USIMCONF2_CONFSCLKMODE_SHIFT)|(1<<CSL_USIMOCP_USIMCONF2_CONFSCLKDIV_SHIFT),
	USIM_CLK_DIV_6_LEGACY_MASK = (0<<CSL_USIMOCP_USIMCONF2_CONFSCLKMODE_SHIFT)|(2<<CSL_USIMOCP_USIMCONF2_CONFSCLKDIV_SHIFT),
	USIM_CLK_DIV_8_LEGACY_MASK = (0<<CSL_USIMOCP_USIMCONF2_CONFSCLKMODE_SHIFT)|(3<<CSL_USIMOCP_USIMCONF2_CONFSCLKDIV_SHIFT),
	USIM_CLK_DIV_6_MASK = (1<<CSL_USIMOCP_USIMCONF2_CONFSCLKMODE_SHIFT)|(0<<CSL_USIMOCP_USIMCONF2_CONFSCLKDIV_SHIFT),
	USIM_CLK_DIV_8_MASK = (1<<CSL_USIMOCP_USIMCONF2_CONFSCLKMODE_SHIFT)|(1<<CSL_USIMOCP_USIMCONF2_CONFSCLKDIV_SHIFT),
	USIM_CLK_DIV_10_MASK = (1<<CSL_USIMOCP_USIMCONF2_CONFSCLKMODE_SHIFT)|(2<<CSL_USIMOCP_USIMCONF2_CONFSCLKDIV_SHIFT),
	USIM_CLK_DIV_12_MASK = (1<<CSL_USIMOCP_USIMCONF2_CONFSCLKMODE_SHIFT)|(3<<CSL_USIMOCP_USIMCONF2_CONFSCLKDIV_SHIFT)
}USIM_CLK_DIV;

/*to generate interrupt based on a programmable number of consecutive detected 
parity errors. Default value: 0 the parity error detection is not enabled*/
typedef enum {
	USIM_PAR_ERR_DISABLED= 0,
	USIM_PAR_ERR_LEVEL_1 ,
	USIM_PAR_ERR_LEVEL_2 ,
	USIM_PAR_ERR_LEVEL_3 ,
	USIM_PAR_ERR_LEVEL_4 ,
	USIM_PAR_ERR_LEVEL_5 ,
	USIM_PAR_ERR_LEVEL_6 ,
	USIM_PAR_ERR_LEVEL_7
}USIM_PAR_ERR_LEVEL;

typedef enum {
	USIM_FI_372  = 1 ,
	USIM_FI_558  = 2 ,
	USIM_FI_744  = 3 ,
	USIM_FI_1116 = 4 ,
	USIM_FI_1488 = 5 ,
	USIM_FI_1860 = 6 ,
	USIM_FI_512  = 9 ,
	USIM_FI_768  = 10,
	USIM_FI_1024 = 11,
	USIM_FI_1536 = 12,
	USIM_FI_2048 = 13
}USIM_FI;

typedef enum {
	USIM_DI_1 = 1,
	USIM_DI_2 ,
	USIM_DI_4 ,
	USIM_DI_8 ,
	USIM_DI_16,
	USIM_DI_32,
	USIM_DI_64,
	USIM_DI_12,
	USIM_DI_20
}USIM_DI;

/*For T = 1 protocol, the error handling includes block error detection
code (EDC) and the parity checking will be used as a complement to
EDC. The EDC uses either CRC or LRC.*/
typedef enum {
	USIM_T1_EDC_NONE_MASK = (0<<CSL_USIMOCP_USIMCONF2_CONFEDC_SHIFT),
	USIM_T1_EDC_CRC_MASK = (1<<CSL_USIMOCP_USIMCONF2_CONFEDC_SHIFT),
	USIM_T1_EDC_LRC_MASK = (2<<CSL_USIMOCP_USIMCONF2_CONFEDC_SHIFT)
}USIM_T1_EDC;

typedef enum {
	USIM_STATE_IDLE  = 0x0,
	USIM_STATE_ACTING , 
	USIM_STATE_WAIT_ATR , 
	USIM_STATE_ATR_DONE , 
	USIM_STATE_WAIT_RX , 
	USIM_STATE_RX_DONE 
}USIM_Stat;


typedef struct{
	Uint32 	rx_DMA_type; 		//0~3
	Uint32  rx_FIFO_Byte_cnt;   //0~259
	Uint32 	rx_FIFO_trigger_thresh; 	//0~259
	Uint32 	tx_FIFO_trigger_thresh; 	//0~15
	Bool    bEDMA_event_en; 	//enable EDMA request event
}USIM_FIFO_Config;

typedef struct{
    USIM_CLK_DIV        sim_clk_div; /*USIM clock speed = (main core speed)/64/sim_clk_div*/
    USIM_FI             Fi;     //Tetu = (Fi/Di) x Tsclk
    USIM_DI             Di;     //Tetu = (Fi/Di) x Tsclk
    Bool                bSoftFiDi;  //software configure Fi and Di (instead of hardware decoding)
    
    Uint32              CGT; 	//in number of ETU, >=12
    Uint32              CWT; 	//in number of ETU, >=11
    Uint32              BWT; 	//in number of ETU, >=12
    Uint32              WAITI; //WWT= (WAITI+1)*960*ETU, WI*D=CONFWAITI+1.
    
    /*When T = 0, this value (0~7) indicates the number of automatic resents on parity error.*/
    Uint32              maxParityRetries;
    USIM_PAR_ERR_LEVEL  parErrLevel;
    Bool                bCheckParity;
    Bool                bPutErrInFifo; //put/discard Rx characters with parity
    Bool 				bBypassSyncATR; //Bypass ATR waiting sequence for synchronous card
    Uint32              protocol;   //T= 0 or 1
    USIM_T1_EDC         t1Edc;  
    USIM_FIFO_Config *  fifo_cfg;

    Uint32              interruptEnableMask; 	//value for IRQENABLE register

}USIM_Config;

typedef struct{
	/*USIM output clock speed*/
	Uint32    speed_Hz;

	/*ATR contents get from smart card*/
	Uint8     ATR[USIM_MAX_ATR_LENGTH];
	volatile Uint32    uiART_len;

	//RX buffer used by RX interrupt
	Uint8     Rx_Buf[USIM_RX_BUF_BYTE_SIZE];
	volatile Uint32    uiRX_len;

	volatile USIM_Stat stat;
}USIM_Data;

extern CSL_Usimocp__all__Regs * gpUSIM_regs;

extern USIM_Data usim_data;

/*configure the TX/RX FIFO of USIM*/
extern void K2_USIM_FIFO_cfg(USIM_FIFO_Config * fifo_cfg);

/*Initialize USIM controller*/
extern void K2_USIM_Init(USIM_Config * cfg);

//active USIM card
extern void K2_USIM_activate_card(USIM_FIFO_Config * fifo_cfg);

//deactive USIM card
extern void K2_USIM_deactivate();

extern Uint32 K2_USIM_read(Uint8 * Rx_Buf, Uint32 uiBufLength);
extern void K2_USIM_transmit(Uint8 * data, Uint32 uiLength);

//read ICCID from USIM
extern void K2_USIM_read_ICCID();

//return the pointer of ATR string, and parser ATR contents
extern Uint8 * K2_USIM_get_ATR();

//return IQRSTATUS and parser it
extern Uint32 K2_USIM_IRQ_handler();

#endif

