/*++

Copyright (c) 2015 Minoca Corp. All Rights Reserved

Module Name:

    sddwc.h

Abstract:

    This header contains definitions for the DesignWare SD Controller.

Author:

    Chris Stevens 30-Jul-2015

--*/

//
// ------------------------------------------------------------------- Includes
//

//
// --------------------------------------------------------------------- Macros
//

//
// ---------------------------------------------------------------- Definitions
//

//
// Define the SD control register bits.
//

#define SD_DWC_CONTROL_USE_INTERNAL_DMAC       (1 << 25)
#define SD_DWC_CONTROL_ENABLE_OD_PULLUP        (1 << 24)
#define SD_DWC_CONTROL_CARD_VOLTAGE_B_MASK     (0xF << 20)
#define SD_DWC_CONTROL_CARD_VOLTAGE_B_SHIFT    20
#define SD_DWC_CONTROL_CARD_VOLTAGE_A_MASK     (0xF << 16)
#define SD_DWC_CONTROL_CARD_VOLTAGE_A_SHIFT    16
#define SD_DWC_CONTROL_CE_ATA_INTERRUPT_ENABLE (1 << 11)
#define SD_DWC_CONTROL_SEND_AUTO_STOP_CCSD     (1 << 10)
#define SD_DWC_CONTROL_SEND_CCSD               (1 << 9)
#define SD_DWC_CONTROL_ABORT_READ_DATA         (1 << 8)
#define SD_DWC_CONTROL_SEND_IRQ_RESPONSE       (1 << 7)
#define SD_DWC_CONTROL_READ_WAIT               (1 << 6)
#define SD_DWC_CONTROL_DMA_ENABLE              (1 << 5)
#define SD_DWC_CONTROL_INTERRUPT_ENABLE        (1 << 4)
#define SD_DWC_CONTROL_DMA_RESET               (1 << 2)
#define SD_DWC_CONTROL_FIFO_RESET              (1 << 1)
#define SD_DWC_CONTROL_CONTROLLER_RESET        (1 << 0)

//
// Define the SD power register bits.
//

#define SD_DWC_POWER_DISABLE (0 << 0)
#define SD_DWC_POWER_ENABLE  (1 << 0)

//
// Define the SD clock divider register bits.
//

#define SD_DWC_CLOCK_DIVIDER_3_MASK  (0xFF << 24)
#define SD_DWC_CLOCK_DIVIDER_3_SHIFT 24
#define SD_DWC_CLOCK_DIVIDER_2_MASK  (0xFF << 16)
#define SD_DWC_CLOCK_DIVIDER_2_SHIFT 16
#define SD_DWC_CLOCK_DIVIDER_1_MASK  (0xFF << 8)
#define SD_DWC_CLOCK_DIVIDER_1_SHIFT 8
#define SD_DWC_CLOCK_DIVIDER_0_MASK  (0xFF << 0)
#define SD_DWC_CLOCK_DIVIDER_0_SHIFT 0

#define SD_DWC_MAX_DIVISOR (0xFF * 2)

//
// Define the SD clock source register bits.
//

#define SD_DWC_CLOCK_SOURCE_DIVIDER_3     0x3
#define SD_DWC_CLOCK_SOURCE_DIVIDER_2     0x2
#define SD_DWC_CLOCK_SOURCE_DIVIDER_1     0x1
#define SD_DWC_CLOCK_SOURCE_DIVIDER_0     0x0
#define SD_DWC_CLOCK_SOURCE_DIVIDER_MASK  (0x3 << 0)
#define SD_DWC_CLOCK_SOURCE_DIVIDER_SHIFT 0

//
// Define the SD clock enable register bits.
//

#define SD_DWC_CLOCK_ENABLE_LOW_POWER (1 << 16)
#define SD_DWC_CLOCK_ENABLE_ON        (1 << 0)

//
// Define the SD clock timeout register bits.
//

#define SD_DWC_TIMEOUT_DATA_MASK      (0xFFFFFF << 8)
#define SD_DWC_TIMEOUT_DATA_SHIFT     8
#define SD_DWC_TIMEOUT_RESPONSE_MASK  (0xFF << 0)
#define SD_DWC_TIMEOUT_RESPONSE_SHIFT 0

#define SD_DWC_TIMEOUT_DEFAULT 0xFFFFFF40

//
// Define the SD card type register bits.
//

#define SD_DWC_CARD_TYPE_8_BIT_WIDTH (1 << 16)
#define SD_DWC_CARD_TYPE_4_BIT_WIDTH (1 << 0)
#define SD_DWC_CARD_TYPE_1_BIT_WIDTH (0 << 0)

//
// Define the SD block size register bits.
//

#define SD_DWC_BLOCK_SIZE_MASK  (0xFFFF << 0)
#define SD_DWC_BLOCK_SIZE_SHIFT 0

#define SD_DWC_BLOCK_SIZE_MAX 0xFFFF

//
// Define the SD interrupt mask register bits.
//

#define SD_DWC_INTERRUPT_MASK_SDIO                       (1 << 24)
#define SD_DWC_INTERRUPT_MASK_DATA_NO_BUSY               (1 << 16)
#define SD_DWC_INTERRUPT_MASK_ERROR_END_BIT              (1 << 15)
#define SD_DWC_INTERRUPT_MASK_AUTO_COMMAND_DONE          (1 << 14)
#define SD_DWC_INTERRUPT_MASK_ERROR_START_BIT            (1 << 13)
#define SD_DWC_INTERRUPT_MASK_ERROR_HARDWARE_LOCKED      (1 << 12)
#define SD_DWC_INTERRUPT_MASK_ERROR_FIFO_UNDERRUN        (1 << 11)
#define SD_DWC_INTERRUPT_MASK_ERROR_HOST_TIMEOUT         (1 << 10)
#define SD_DWC_INTERRUPT_MASK_VOLT_SWITCH                (1 << 10)
#define SD_DWC_INTERRUPT_MASK_ERROR_DATA_READ_TIMEOUT    (1 << 9)
#define SD_DWC_INTERRUPT_MASK_ERROR_RESPONSE_TIMEOUT     (1 << 8)
#define SD_DWC_INTERRUPT_MASK_ERROR_DATA_CRC             (1 << 7)
#define SD_DWC_INTERRUPT_MASK_ERROR_RESPONSE_CRC         (1 << 6)
#define SD_DWC_INTERRUPT_MASK_RECEIVE_FIFO_DATA_REQUEST  (1 << 5)
#define SD_DWC_INTERRUPT_MASK_TRANSMIT_FIFO_DATA_REQUEST (1 << 4)
#define SD_DWC_INTERRUPT_MASK_DATA_TRANSFER_OVER         (1 << 3)
#define SD_DWC_INTERRUPT_MASK_COMMAND_DONE               (1 << 2)
#define SD_DWC_INTERRUPT_MASK_ERROR_RESPONSE             (1 << 1)
#define SD_DWC_INTERRUPT_MASK_CARD_DETECT                (1 << 0)

#define SD_DWC_INTERRUPT_ERROR_MASK                     \
    (SD_DWC_INTERRUPT_MASK_ERROR_END_BIT |              \
     SD_DWC_INTERRUPT_MASK_ERROR_START_BIT |            \
     SD_DWC_INTERRUPT_MASK_ERROR_DATA_READ_TIMEOUT |    \
     SD_DWC_INTERRUPT_MASK_ERROR_RESPONSE_TIMEOUT |     \
     SD_DWC_INTERRUPT_MASK_ERROR_DATA_CRC |             \
     SD_DWC_INTERRUPT_MASK_ERROR_RESPONSE_CRC |         \
     SD_DWC_INTERRUPT_MASK_ERROR_RESPONSE)

#define SD_DWC_INTERRUPT_DEFAULT_MASK SD_DWC_INTERRUPT_MASK_CARD_DETECT

//
// Define the SD interrupt status register bits.
//

#define SD_DWC_INTERRUPT_STATUS_SDIO                       (1 << 24)
#define SD_DWC_INTERRUPT_STATUS_DATA_NO_BUSY_DISABLE       (1 << 16)
#define SD_DWC_INTERRUPT_STATUS_ERROR_END_BIT              (1 << 15)
#define SD_DWC_INTERRUPT_STATUS_AUTO_COMMAND_DONE          (1 << 14)
#define SD_DWC_INTERRUPT_STATUS_ERROR_START_BIT            (1 << 13)
#define SD_DWC_INTERRUPT_STATUS_ERROR_HARDWARE_LOCKED      (1 << 12)
#define SD_DWC_INTERRUPT_STATUS_ERROR_FIFO_UNDERRUN        (1 << 11)
#define SD_DWC_INTERRUPT_STATUS_ERROR_HOST_TIMEOUT         (1 << 10)
#define SD_DWC_INTERRUPT_STATUS_VOLT_SWITCH                (1 << 10)
#define SD_DWC_INTERRUPT_STATUS_ERROR_DATA_READ_TIMEOUT    (1 << 9)
#define SD_DWC_INTERRUPT_STATUS_ERROR_RESPONSE_TIMEOUT     (1 << 8)
#define SD_DWC_INTERRUPT_STATUS_ERROR_DATA_CRC             (1 << 7)
#define SD_DWC_INTERRUPT_STATUS_ERROR_RESPONSE_CRC         (1 << 6)
#define SD_DWC_INTERRUPT_STATUS_RECEIVE_FIFO_DATA_REQUEST  (1 << 5)
#define SD_DWC_INTERRUPT_STATUS_TRANSMIT_FIFO_DATA_REQUEST (1 << 4)
#define SD_DWC_INTERRUPT_STATUS_DATA_TRANSFER_OVER         (1 << 3)
#define SD_DWC_INTERRUPT_STATUS_COMMAND_DONE               (1 << 2)
#define SD_DWC_INTERRUPT_STATUS_ERROR_RESPONSE             (1 << 1)
#define SD_DWC_INTERRUPT_STATUS_CARD_DETECT                (1 << 0)
#define SD_DWC_INTERRUPT_STATUS_ALL_MASK                   0xFFFFFFFF

#define SD_DWC_INTERRUPT_STATUS_COMMAND_ERROR_MASK \
    (SD_DWC_INTERRUPT_STATUS_ERROR_RESPONSE |      \
     SD_DWC_INTERRUPT_STATUS_ERROR_RESPONSE_CRC)

#define SD_DWC_INTERRUPT_STATUS_DATA_ERROR_MASK        \
    (SD_DWC_INTERRUPT_STATUS_ERROR_DATA_CRC |          \
     SD_DWC_INTERRUPT_STATUS_ERROR_DATA_READ_TIMEOUT | \
     SD_DWC_INTERRUPT_STATUS_ERROR_HOST_TIMEOUT |      \
     SD_DWC_INTERRUPT_STATUS_ERROR_START_BIT |         \
     SD_DWC_INTERRUPT_STATUS_ERROR_END_BIT)

//
// Define the SD command register bits.
//

#define SD_DWC_COMMAND_START                       (1 << 31)
#define SD_DWC_COMMAND_USE_HOLD_REGISTER           (1 << 29)
#define SD_DWC_COMMAND_VOLT_SWITCH                 (1 << 28)
#define SD_DWC_COMMAND_BOOT_MODE                   (1 << 27)
#define SD_DWC_COMMAND_DISABLE_BOOT                (1 << 26)
#define SD_DWC_COMMAND_EXPECT_BOOT_ACK             (1 << 25)
#define SD_DWC_COMMAND_ENABLE_BOOT                 (1 << 24)
#define SD_DWC_COMMAND_CSS_EXPECTED                (1 << 23)
#define SD_DWC_COMMAND_READ_CE_ATA                 (1 << 22)
#define SD_DWC_COMMAND_UPDATE_CLOCK_REGISTERS      (1 << 21)
#define SD_DWC_COMMAND_CARD_NUMBER_MASK            (0x1F << 16)
#define SD_DWC_COMMAND_CARD_NUMBER_SHIFT           16
#define SD_DWC_COMMAND_SEND_INITIALIZATION         (1 << 15)
#define SD_DWC_COMMAND_STOP_ABORT                  (1 << 14)
#define SD_DWC_COMMAND_WAIT_PREVIOUS_DATA_COMPLETE (1 << 13)
#define SD_DWC_COMMAND_SEND_AUTO_STOP              (1 << 12)
#define SD_DWC_COMMAND_TRANSFER_MODE_BLOCK         (0 << 11)
#define SD_DWC_COMMAND_TRANSFER_MODE_STREAM        (1 << 11)
#define SD_DWC_COMMAND_READ                        (0 << 10)
#define SD_DWC_COMMAND_WRITE                       (1 << 10)
#define SD_DWC_COMMAND_DATA_EXPECTED               (1 << 9)
#define SD_DWC_COMMAND_CHECK_RESPONSE_CRC          (1 << 8)
#define SD_DWC_COMMAND_LONG_RESPONSE               (1 << 7)
#define SD_DWC_COMMAND_RESPONSE_EXPECTED           (1 << 6)
#define SD_DWC_COMMAND_INDEX_MASK                  (0x3F << 0)
#define SD_DWC_COMMAND_INDEX_SHIFT                 0

//
// Define the SD status register bits.
//

#define SD_DWC_STATUS_DMA_REQUEST              (1 << 31)
#define SD_DWC_STATUS_DMA_ACK                  (1 << 30)
#define SD_DWC_STATUS_FIFO_COUNT_MASK          (0x1FFF << 17)
#define SD_DWC_STATUS_FIFO_COUNT_SHIFT         17
#define SD_DWC_STATUS_RESPONSE_INDEX_MASK      (0x3F << 11)
#define SD_DWC_STATUS_RESPONSE_INDEX_SHIFT     11
#define SD_DWC_STATUS_DATA_STATE_MACHINE_BUSY  (1 << 10)
#define SD_DWC_STATUS_DATA_BUSY                (1 << 9)
#define SD_DWC_STATUS_DATA_3_STATUS            (1 << 8)
#define SD_DWC_STATUS_COMMAND_FSM_STATE_MASK   (0xF << 4)
#define SD_DWC_STATUS_COMMAND_FSM_STATE_SHIFT  4
#define SD_DWC_STATUS_FIFO_FULL                (1 << 3)
#define SD_DWC_STATUS_FIFO_EMPTY               (1 << 2)
#define SD_DWC_STATUS_FIFO_TRANSMIT_WATERMARK  (1 << 1)
#define SD_DWC_STATUS_FIFO_RECEIVE_WATERMARK   (1 << 0)

//
// Define the SD FIFO threshold register bits.
//

#define SD_DWC_FIFO_THRESHOLD_DMA_MULTIPLE_TRANSACTION_SIZE_1     0
#define SD_DWC_FIFO_THRESHOLD_DMA_MULTIPLE_TRANSACTION_SIZE_4     1
#define SD_DWC_FIFO_THRESHOLD_DMA_MULTIPLE_TRANSACTION_SIZE_8     2
#define SD_DWC_FIFO_THRESHOLD_DMA_MULTIPLE_TRANSACTION_SIZE_16    3
#define SD_DWC_FIFO_THRESHOLD_DMA_MULTIPLE_TRANSACTION_SIZE_32    4
#define SD_DWC_FIFO_THRESHOLD_DMA_MULTIPLE_TRANSACTION_SIZE_64    5
#define SD_DWC_FIFO_THRESHOLD_DMA_MULTIPLE_TRANSACTION_SIZE_128   6
#define SD_DWC_FIFO_THRESHOLD_DMA_MULTIPLE_TRANSACTION_SIZE_256   7
#define SD_DWC_FIFO_THRESHOLD_DMA_MULTIPLE_TRANSACTION_SIZE_MASK  (0x7 << 28)
#define SD_DWC_FIFO_THRESHOLD_DMA_MULTIPLE_TRANSACTION_SIZE_SHIFT 28
#define SD_DWC_FIFO_THRESHOLD_RECEIVE_WATERMARK_MASK              (0xFFF << 16)
#define SD_DWC_FIFO_THRESHOLD_RECEIVE_WATERMARK_SHIFT             16
#define SD_DWC_FIFO_THRESHOLD_TRANSMIT_WATERMARK_MASK             (0xFFF << 0)
#define SD_DWC_FIFO_THRESHOLD_TRANSMIT_WATERMARK_SHIFT            0

#define SD_DWC_FIFO_THRESHOLD_DEFAULT                              \
    ((SD_DWC_FIFO_THRESHOLD_DMA_MULTIPLE_TRANSACTION_SIZE_16 <<    \
      SD_DWC_FIFO_THRESHOLD_DMA_MULTIPLE_TRANSACTION_SIZE_SHIFT) | \
     ((((SD_DWC_FIFO_DEPTH / 2) - 1) <<                            \
       SD_DWC_FIFO_THRESHOLD_RECEIVE_WATERMARK_SHIFT) &            \
      SD_DWC_FIFO_THRESHOLD_RECEIVE_WATERMARK_MASK) |              \
     (((SD_DWC_FIFO_DEPTH / 2) <<                                  \
       SD_DWC_FIFO_THRESHOLD_TRANSMIT_WATERMARK_SHIFT) &           \
      SD_DWC_FIFO_THRESHOLD_TRANSMIT_WATERMARK_MASK))

#define SD_DWC_FIFO_DEPTH 0x100

//
// Define the SD UHS register bits.
//

#define SD_DWC_UHS_DDR_MODE     (1 << 16)
#define SD_DWC_UHS_VOLTAGE_MASK (1 << 0)
#define SD_DWC_UHS_VOLTAGE_3V3  (0 << 0)
#define SD_DWC_UHS_VOLTAGE_1V8  (1 << 0)

//
// Define the SD reset register bits.
//

#define SD_DWC_RESET_ENABLE (1 << 0)

//
// Define the SD bus mode register bits.
//

#define SD_DWC_BUS_MODE_BURST_LENGTH_1               0
#define SD_DWC_BUS_MODE_BURST_LENGTH_4               1
#define SD_DWC_BUS_MODE_BURST_LENGTH_8               2
#define SD_DWC_BUS_MODE_BURST_LENGTH_16              3
#define SD_DWC_BUS_MODE_BURST_LENGTH_32              4
#define SD_DWC_BUS_MODE_BURST_LENGTH_64              5
#define SD_DWC_BUS_MODE_BURST_LENGTH_128             6
#define SD_DWC_BUS_MODE_BURST_LENGTH_256             7
#define SD_DWC_BUS_MODE_BURST_LENGTH_MASK            (0x7 << 8)
#define SD_DWC_BUS_MODE_BURST_LENGTH_SHIFT           8
#define SD_DWC_BUS_MODE_IDMAC_ENABLE                 (1 << 7)
#define SD_DWC_BUS_MODE_DESCRIPTOR_SKIP_LENGTH_MASK  (0x1F << 2)
#define SD_DWC_BUS_MODE_DESCRIPTOR_SKIP_LENGTH_SHIFT 2
#define SD_DWC_BUS_MODE_FIXED_BURST                  (1 << 1)
#define SD_DWC_BUS_MODE_INTERNAL_DMA_RESET           (1 << 0)

//
// Define the DMA descriptor control and status bits.
//

#define SD_DWC_DMA_DESCRIPTOR_CONTROL_OWN                             (1 << 31)
#define SD_DWC_DMA_DESCRIPTOR_CONTROL_CARD_ERROR_SUMMARY              (1 << 30)
#define SD_DWC_DMA_DESCRIPTOR_CONTROL_END_OF_RING                     (1 << 5)
#define SD_DWC_DMA_DESCRIPTOR_CONTROL_SECOND_ADDRESS_CHAINED          (1 << 4)
#define SD_DWC_DMA_DESCRIPTOR_CONTROL_FIRST_DESCRIPTOR                (1 << 3)
#define SD_DWC_DMA_DESCRIPTOR_CONTROL_LAST_DESCRIPTOR                 (1 << 2)
#define SD_DWC_DMA_DESCRIPTOR_CONTROL_DISABLE_INTERRUPT_ON_COMPLETION (1 << 1)

//
// Define the maximum buffer size for a DMA descriptor. Technically it is
// 0x1FFF, but round down to the nearest page for better arithmetic.
//

#define SD_DWC_DMA_DESCRIPTOR_MAX_BUFFER_SIZE 0x1000

//
// Define card read threshold register bits.
//

#define SD_DWC_CARD_READ_THRESHOLD_ENABLE 0x00000001
#define SD_DWC_CARD_READ_THRESHOLD_SIZE_SHIFT 16

//
// ------------------------------------------------------ Data Type Definitions
//

typedef enum _SD_DWC_REGISTER {
    SdDwcControl = 0x000,
    SdDwcPower = 0x004,
    SdDwcClockDivider = 0x008,
    SdDwcClockSource = 0x00C,
    SdDwcClockEnable = 0x010,
    SdDwcTimeout = 0x014,
    SdDwcCardType = 0x018,
    SdDwcBlockSize = 0x01C,
    SdDwcByteCount = 0x020,
    SdDwcInterruptMask = 0x024,
    SdDwcCommandArgument = 0x028,
    SdDwcCommand = 0x02C,
    SdDwcResponse0 = 0x030,
    SdDwcResponse1 = 0x034,
    SdDwcResponse2 = 0x038,
    SdDwcResponse3 = 0x03C,
    SdDwcMaskedInterruptStatus = 0x040,
    SdDwcInterruptStatus = 0x044,
    SdDwcStatus = 0x048,
    SdDwcFifoThreshold = 0x04C,
    SdDwcCardDetect = 0x050,
    SdDwcWriteProtect = 0x054,
    SdDwcTransferredCiuByteCount = 0x058,
    SdDwcTransferredBiuByteCount = 0x05C,
    SdDwcUhs = 0x074,
    SdDwcResetN = 0x078,
    SdDwcBusMode = 0x080,
    SdDwcPollDemand = 0x084,
    SdDwcDescriptorBaseAddress = 0x088,
    SdDwcCardThresholdControl = 0x100,
    SdDwcFifoBase = 0x200,
} SD_DWC_REGISTER, *PSD_DWC_REGISTER;

/*++

Structure Description:

    This structure defines the DesignWare SD DMA descriptor.

Members:

    Control - Stores control and status bits for the descriptor. See
        SD_DWC_DMA_DESCRIPTOR_CONTROL_* for definitions.

    Size - Stores the size of the buffer.

    Address - Stores the physical address of the data buffer to use for the DMA.

    NextDescriptor - Stores the physical address of the next DMA descriptor.

--*/

typedef struct _SD_DWC_DMA_DESCRIPTOR {
    ULONG Control;
    ULONG Size;
    ULONG Address;
    ULONG NextDescriptor;
} PACKED SD_DWC_DMA_DESCRIPTOR, *PSD_DWC_DMA_DESCRIPTOR;

//
// -------------------------------------------------------------------- Globals
//

//
// -------------------------------------------------------- Function Prototypes
//

