//-------------------------------------------------------------------------------------------------------------------------
// Copyright (c) Samsung Electronics Co., Ltd.  All rights reserved.
//-------------------------------------------------------------------------------------------------------------------------
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, 
// INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
//
// Module Name :    spi_priv.H
//
// Abstract    :    SPI Interface Routines for Samsung S5PV210 CPU
//
// Environment :    Samsung S5PV210 / WinCE6.0
//
// 2010/02/10 asdf  Added Full duplex mode (Ver 1.01)
//                          Define SPI_FULL_DUPLEX in sources file to use full duplex
// 2009/07/10 asdf Modified for supporting 3-CH of SPI
//
//-------------------------------------------------------------------------------------------------------------------------

#ifndef _SPI_PRIV_H_
#define _SPI_PRIV_H_


/*****************************************************************************
 * Include files
 *****************************************************************************/ 

#include <windows.h>



/*****************************************************************************
 * Definitions
 *****************************************************************************/ 
#define SPI_MASTER_MODE     1
#define SPI_SLAVE_MODE      0

#define FIFO_EMPTY       0x0
#define RX_TRIG_LEVEL    0

#define WRITE_TIME_OUT_CONSTANT     5000
#define WRITE_TIME_OUT_MULTIPLIER   1

#define READ_TIME_OUT_CONSTANT      5000
#define READ_TIME_OUT_MULTIPLIER    1

#define SPI_WAIT_TIMEOUT        (0x10000000)
#define SPI_IS_TIMEOUT(count)   ((count & SPI_WAIT_TIMEOUT) ? TRUE : FALSE)

#define MASTER_CS_ENABLE  pSPIregs->CS_SEL=0
#define MASTER_CS_DISABLE pSPIregs->CS_SEL=1

#define TRAIL_CNT(n)     (((n)&0x3FF)<<19)

#define SPI_POWER_ON     (1<<21)
#define SPI_SCLK_ON      (1<<8)
#define SPI_USBHOST_ON   (1<<22)

#define PCLOCK           (0)
#define MPLL_CLOCK      (1)
#define EPLL_CLOCK       (2)

#define BASE_REG_SPI_OFFSET  0x100000

#define SPI_DMA_BUF_SIZE 4096


// IOCTL Commands
#define SPI_IOCTL_START                 CTL_CODE(FILE_DEVICE_SERIAL_PORT, 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define SPI_IOCTL_STOP                  CTL_CODE(FILE_DEVICE_SERIAL_PORT, 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define SPI_IOCTL_SET_CONFIG            CTL_CODE(FILE_DEVICE_SERIAL_PORT, 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define SPI_IOCTL_GET_CONFIG            CTL_CODE(FILE_DEVICE_SERIAL_PORT, 3, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define SPI_IOCTL_SET_CALLBACK          CTL_CODE(FILE_DEVICE_SERIAL_PORT, 10, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define SPI_IOCTL_CLR_CALLBACK          CTL_CODE(FILE_DEVICE_SERIAL_PORT, 11, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define SPI_IOCTL_IS_SLAVE_READY        CTL_CODE(FILE_DEVICE_SERIAL_PORT, 12, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define SPI_IOCTL_SERIAL_GET_WAIT_MASK  CTL_CODE(FILE_DEVICE_SERIAL_PORT, 20, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define SPI_IOCTL_SERIAL_SET_WAIT_MASK  CTL_CODE(FILE_DEVICE_SERIAL_PORT, 21, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define SPI_IOCTL_SERIAL_WAIT_ON_MASK   CTL_CODE(FILE_DEVICE_SERIAL_PORT, 22, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define SPI_IOCTL_FULL_DUPLEX                   CTL_CODE(FILE_DEVICE_SERIAL_PORT, 23, METHOD_BUFFERED, FILE_ANY_ACCESS)

/////////////////////////////////////////////////////////////////////////////////////////
// Required Registry Setting.
#define    PC_REG_SPI_DEVICE_INDEX        TEXT("DeviceArrayIndex")
/////////////////////////////////////////////////////////////////////////////////////////

typedef enum 
{
        SPI0=0, 
        SPI1=1, 
        SPI2=2,
        INVALID
}SPI_CH_NUM;

/*****************************************************************************
 * SPI SFR 
 *****************************************************************************/ 

//SPI_REG+0x00  CH_CFG
#define HIGH_SPEED_MASK         (1<<6)
#define HIGH_SPEED_DIS          (0<<6)
#define HIGH_SPEED_EN           (1<<6)

#define SW_RST                  (1<<5)
#define SPI_MASTER              (0<<4)
#define SPI_SLAVE               (1<<4)
#define CPOL_RISING             (0<<3)
#define CPOL_FALLING            (1<<3)
#define CPHA_FORMAT_A           (0<<2)
#define CPHA_FORMAT_B           (1<<2)
#define RX_CH_OFF               (0<<1)
#define RX_CH_ON                (1<<1)
#define TX_CH_OFF               (0<<0)
#define TX_CH_ON                (1<<0)

//SPI_REG+0x04  CLK_CFG
#define CLKSEL_PCLK             (0<<9)
#define CLKSEL_SPI_EXT_CLK      (1<<9)
#define ENCLK_DISABLE           (0<<8)
#define ENCLK_ENABLE            (1<<8)

//SPI_REG+0x08  MODE_CFG
#define CH_SIZE_BYTE            (0<<29)
#define CH_SIZE_HALF            (1<<29)
#define CH_SIZE_WORD            (2<<29)
#define BUS_SIZE_BYTE           (0<<17)
#define BUS_SIZE_HALF           (1<<17)
#define BUS_SIZE_WORD           (2<<17)
#define DMA_SINGLE              (0<<0)
#define DMA_4BURST              (1<<0)
#define RX_DMA_ON               (1<<2)
#define TX_DMA_ON               (1<<1)
#define MODE_DEFAULT            (0)

//SPI_REG+0x0C  CS_REG

//SPI_REG+0x10  SPI_INT_EN
#define INT_TRAILING            (1<<6)
#define INT_RX_OVERRUN          (1<<5)
#define INT_RX_UNDERRUN         (1<<4)
#define INT_TX_OVERRUN          (1<<3)
#define INT_TX_UNDERRUN         (1<<2)
#define INT_RX_FIFORDY          (1<<1)
#define INT_TX_FIFORDY          (1<<0)

//SPI_REG+0x14  SPI_STATUS
#define TX_DONE                 (1<<25)
#define TRAILCNT_ZERO           (1<<24)
#define RX_OVERRUN              (1<<5)
#define RX_UNDERRUN             (1<<4)
#define TX_OVERRUN              (1<<3)
#define TX_UNDERRUN             (1<<2)
#define RX_FIFORDY              (1<<1)
#define TX_FIFORDY              (1<<0)

//SPI_REG+0x18  SPI_TX_DATA

//SPI_REG+0x1C  SPI_RX_DATA

//SPI_REG+0x20  PACKET_CNT
#define PACKET_CNT_EN           (1<<16)

//SPI_REG+0x24  PENDING_CLR_REG
#define TX_UNDERRUN_CLR         (1<<4)
#define TX_OVERRUN_CLR          (1<<3)
#define RX_UNDERRUN_CLR         (1<<2)
#define RX_OVERRUN_CLR          (1<<1)
#define TRAILING_CLR            (1<<0)

//SPI_REG+0x28  SWAP_CFG_REG
#define RX_HALF_SWAP            (1<<7)
#define RX_BYTE_SWAP            (1<<6)
#define RX_BIT_SWAP             (1<<5)
#define RX_SWAP_EN              (1<<4)
#define TX_HALF_SWAP            (1<<3)
#define TX_BYTE_SWAP            (1<<2)
#define TX_BIT_SWAP             (1<<1)
#define TX_SWAP_EN              (1<<0)

//SPI_REG+0x2C  FB_CLK_SEL_REG
//NOTE:    90 degree phase lagging means 5ns delay in 50MHz operating frequency
#define DO_NOT_USE_FEEDBACK_CLOCK           (0x0)
#define FB_CLK_WITH_90_DEGREE_PHASE_LAG     (0x1)
#define FB_CLK_WITH_180_DEGREE_PHASE_LAG    (0x2)
#define FB_CLK_WITH_270_DEGREE_PHASE_LAG    (0x3)

//#define    PADDRFIX            (1<<24)

typedef enum {
        SPI_FORMAT_0,
        SPI_FORMAT_1,
        SPI_FORMAT_2,
        SPI_FORMAT_3
} SPI_FORMAT;

typedef enum {
        SPI_BYTE_BUS = 0,
        SPI_HWORD_BUS,
        SPI_WORD_BUS,
        SPI_DWORD_BUS
} SPI_BUS_WIDTH;

typedef enum {
        SPI_BYTE_CHN,
        SPI_HWORD_CHN,
        SPI_WORD_CHN,
        SPI_DWORD_CHN
} SPI_CHN_WIDTH;

typedef enum {
        SPI_SWAP_DISABLE,
        SPI_BIT_SWAP=2,
        SPI_BYTE_SWAP=4,
        SPI_WORD_SWAP=8
} SPI_SWAP_SIZE;

/*
typedef struct {
    PVOID VirtualAddress;
    UINT32 PhysicalAddress;
} SPI_DMA_BUFFER, *PSPI_DMA_BUFFER;*/

typedef enum {            
        STATE_TIMEOUT,
        STATE_READING,
        STATE_RXDMA,
        STATE_RXINTR,
        STATE_WRITING,
        STATE_TXDMA,
        STATE_TXINTR,
        STATE_CONTROLLING,
        STATE_RXBUFFERRING,
        STATE_TXBUFFERRING,
        STATE_IDLE,
        STATE_CANCELLING,
        STATE_INIT,
        STATE_FULLDUPLEX,
        STATE_ERROR
} SPI_STATUS;

typedef enum {
        SPI_NO_ERROR        = 0,
        RECOVERABLE_ERROR   = 100,
        STATE_CHECKING_ERROR,
        PARAM_CHECKING_ERROR,
        TX_TIMEOUT_ERROR,
        RX_TIMEOUT_ERROR,
        UNRECOVERABLE_ERROR = 200,
        UNDEFINED_ERROR     = 999
} SPI_ERROR;

typedef struct {
        PBYTE pStrMem;
        PBYTE pEndMem;
        PBYTE pCurMem;
        DWORD dwMemSize;
        DWORD dwDataSize;
        DWORD dwUsedSize;
        DWORD dwUnusedSize;
        BOOL  bNeedBuffering;
} SPI_BUFFER;
#ifdef SPI_EX_GPIO_CALLBACK
typedef BOOL (*SPI_CALLBACK) (PSPI_PRIVATE_CONTEXT);
#endif 
typedef struct {
    DWORD dwMode;

    BOOL               bUseRxFIFO;


    BOOL  bUseRxDMA;
    BOOL  bUseRxIntr;
    DWORD              dwRxTrigger;
    SPI_BUS_WIDTH      RxBusWidth;
    SPI_CHN_WIDTH      RxChnWidth;
    SPI_SWAP_SIZE      RxSwap;
    BOOL               bRxDMABurst;

    BOOL               bUseTxFIFO;
    BOOL  bUseTxDMA;
    BOOL  bUseTxIntr;
    DWORD              dwTxTrigger;
    SPI_BUS_WIDTH      TxBusWidth;
    SPI_CHN_WIDTH      TxChnWidth;
    SPI_SWAP_SIZE      TxSwap;
    BOOL               bTxDMABurst;

    DWORD              dwLLICount; // for DMA LLI setting
    BOOL               bLoopedLLI;

    DWORD              dwLineStrength;

    DWORD              dwFBClkSel;

    DWORD dwPrescaler;
    DWORD dwTimeOutVal;
    SPI_FORMAT         Format;
} SPI_SET_CONFIG, *PSPI_SET_CONFIG;

typedef struct {
    DWORD              dwMode;

    BOOL               bUseRxFIFO;
    BOOL               bUseRxDMA;
    BOOL               bUseRxIntr;
    DWORD              dwRxTrigger;
    SPI_BUS_WIDTH      RxBusWidth;
    SPI_CHN_WIDTH      RxChnWidth;
    SPI_SWAP_SIZE      RxSwap;
    BOOL               bRxDMABurst;

    BOOL               bUseTxFIFO;
    BOOL               bUseTxDMA;
    BOOL               bUseTxIntr;
    DWORD              dwTxTrigger;
    SPI_BUS_WIDTH      TxBusWidth;
    SPI_CHN_WIDTH      TxChnWidth;
    SPI_SWAP_SIZE      TxSwap;
    BOOL               bTxDMABurst;

    DWORD              dwLLICount; // for DMA LLI setting
    BOOL               bLoopedLLI;

    DWORD              dwPrescaler;
    DWORD              dwTimeOutVal;
    SPI_FORMAT         Format;
} SPI_GET_CONFIG, *PSPI_GET_CONFIG;

typedef struct {
    DMA_CH_CONTEXT   g_OutputDMA;
    DMA_CH_CONTEXT   g_InputDMA;

    UINT DmaDstAddress;
    UINT DmaSrcAddress;

    PHYSICAL_ADDRESS PhysDmaDstBufferAddr;
    PHYSICAL_ADDRESS PhysDmaSrcBufferAddr;

    PBYTE pVirtDmaDstBufferAddr;
    PBYTE pVirtDmaSrcBufferAddr;
}SPI_DMA_INFO;

typedef struct {
        PVOID   pSpiPrivate;

        volatile PGPIO_REG       pGPIOregs;
        volatile SPI_REG        * pSPIregs;
        volatile PCMU_CLK_REG    pSYSCONregs;
        volatile PDMAC_REG       pDMAC0regs;
        volatile PDMAC_REG       pDMAC1regs;
        volatile PDMAC_REG       pDMACregs;


        DWORD   dwRxThreadId;
        DWORD   dwRxThreadPrio;
        HANDLE  hRxEvent;
        HANDLE  hRxThread;
        HANDLE  hRxDoneEvent;
        HANDLE  hRxIntrDoneEvent;

        DWORD   dwTxThreadId;
        DWORD   dwTxThreadPrio;
        HANDLE  hTxEvent;
        HANDLE  hTxThread;
        HANDLE  hTxDoneEvent;
        HANDLE  hTxIntrDoneEvent;

        DWORD   dwSpiThreadId;
        DWORD   dwSpiThreadPrio;
        DWORD   dwSpiSysIntr;
        HANDLE  hSpiEvent;
        HANDLE  hSpiThread;

        DWORD   dwRxDmaDoneThreadId;
        DWORD   dwRxDmaDoneThreadPrio;
        DWORD   dwRxDmaDoneSysIntr;
        HANDLE  hRxDmaDoneEvent;
        HANDLE  hRxDmaDoneThread;

        DWORD   dwTxDmaDoneThreadId;
        DWORD   dwTxDmaDoneThreadPrio;
        DWORD   dwTxDmaDoneSysIntr;
        HANDLE  hTxDmaDoneEvent;
        HANDLE  hTxDmaDoneThread;

        DWORD dw_spi_dma_tx_ch;
        DWORD dw_spi_dma_rx_ch;
        SPI_DMA_INFO SPIDMAInfo;
        DWORD chnum;
        BOOL  m_bDVFSFixed;
	HANDLE m_hPowerCon;
        CRITICAL_SECTION CsTxAccess;
        CRITICAL_SECTION CsRxAccess;

} SPI_PUBLIC_CONTEXT, *PSPI_PUBLIC_CONTEXT;


typedef struct {
        PSPI_PUBLIC_CONTEXT pSpiPublic;

        DWORD           dwMode;

        //Rx
        BOOL            bUseRxDMA;
        BOOL            bUseRxIntr;
        SPI_BUFFER      RxBuffer;
        LPVOID          pRxBuffer;
        LPVOID          pRxDMABuffer;    
        DWORD           dwRxCount;
        SPI_REG RxSPIregs;

        //Tx
        BOOL            bUseTxDMA;
        BOOL            bUseTxIntr;
        SPI_BUFFER      TxBuffer;
        LPVOID          pTxBuffer;
        LPVOID          pTxDMABuffer;
        DWORD           dwTxCount;

        SPI_REG TxSPIregs;

        DWORD           dwTimeOutVal;
        DWORD           dwPrescaler;
        DWORD           dwError;
#ifdef SPI_EX_GPIO_CALLBACK
        SPI_CALLBACK    SetSlaveReady;
        SPI_CALLBACK    ClrSlaveReady;
        SPI_CALLBACK    GetSlaveReady;
#endif         
        SPI_STATUS      State;

        DWORD           dwEventMask;
        HANDLE          hCommEvent;

        UINT spi_tx_data_addr;
        UINT spi_rx_data_addr;

        SPI_ERROR       Error;

} SPI_PRIVATE_CONTEXT, *PSPI_PRIVATE_CONTEXT;

UINT   GetFifoSize(DWORD chnum);
DWORD   GetTxTriggerLevel(DWORD chnum);
#endif  // !_SPI_PRIV_H_

