/* Initializes the MCI card controller */
void IP_SDMMC_Init(IP_SDMMC_001_T *pSDMMC)
{
	/* Software reset */
	pSDMMC->BMOD = MCI_BMOD_SWR;

	/* reset all blocks */
	pSDMMC->CTRL = MCI_CTRL_RESET | MCI_CTRL_FIFO_RESET | MCI_CTRL_DMA_RESET;
	while (pSDMMC->CTRL & (MCI_CTRL_RESET | MCI_CTRL_FIFO_RESET | MCI_CTRL_DMA_RESET)) {}

	/* Internal DMA setup for control register */
	pSDMMC->CTRL = MCI_CTRL_USE_INT_DMAC | MCI_CTRL_INT_ENABLE;
	pSDMMC->INTMASK = 0;

	/* Clear the interrupts for the host controller */
	pSDMMC->RINTSTS = 0xFFFFFFFF;

	/* Put in max timeout */
	pSDMMC->TMOUT = 0xFFFFFFFF;

	/* FIFO threshold settings for DMA, DMA burst of 4,   FIFO watermark at 16 */
	pSDMMC->FIFOTH = MCI_FIFOTH_DMA_MTS_4 | MCI_FIFOTH_RX_WM((SD_FIFO_SZ / 2) - 1) | MCI_FIFOTH_TX_WM(SD_FIFO_SZ / 2);

	/* Enable internal DMA, burst size of 4, fixed burst */
	pSDMMC->BMOD = MCI_BMOD_DE | MCI_BMOD_PBL4 | MCI_BMOD_DSL(4);

	/* disable clock to CIU (needs latch) */
	pSDMMC->CLKENA = 0;
	pSDMMC->CLKSRC = 0;
}
/* Initialize the SDIO card */
int SDIO_Card_Init(LPC_SDMMC_T *pSDMMC, uint32_t freq)
{
	int ret;
	uint32_t val;

	/* Set Clock to 400KHz */
	Chip_SDIF_SetClock(pSDMMC, Chip_Clock_GetBaseClocktHz(CLK_BASE_SDIO), freq);
	Chip_SDIF_SetCardType(pSDMMC, 0);

	sdioif->wait_evt(pSDMMC, SDIO_WAIT_DELAY, (void *) 100); /* Wait for card to wake up */

	if (sdioif->flag & SDIO_POWER_INIT) {
		/* Write to the Reset Bit */
		ret = SDIO_Write_Direct(pSDMMC, SDIO_AREA_CIA, 0x06, 0x08);
		if (ret) return ret;
	}

	/* Set Voltage level to 3v3 */
	ret = SDIO_Card_SetVoltage(pSDMMC);
	if (ret) return ret;

	/* Set the RCA */
	ret = SDIO_CARD_SetRCA(pSDMMC);
	if (ret) return ret;

	/* ==== check card capability ==== */
	val = 0x02;
	ret = SDIO_WriteRead_Direct(pSDMMC, SDIO_AREA_CIA, 0x13, &val);
	if (ret) return ret;

	/* FIXME: Verify */
	/* FIFO threshold settings for DMA, DMA burst of 4,   FIFO watermark at 16 */
	pSDMMC->FIFOTH = MCI_FIFOTH_DMA_MTS_1 | MCI_FIFOTH_RX_WM(0) | MCI_FIFOTH_TX_WM(1);

	/* Enable internal DMA, burst size of 4, fixed burst */
	pSDMMC->BMOD = MCI_BMOD_DE | MCI_BMOD_PBL1 | MCI_BMOD_DSL(0);

	/* High Speed Support? */
	if ((val & 0x03) == 3) {
		return SDIO_Card_SetMode(pSDMMC, SDIO_CLK_HISPEED, 1);
	}

	ret = SDIO_Read_Direct(pSDMMC, SDIO_AREA_CIA, 0x08, &val);
	if (ret) return ret;

	/* Full Speed Support? */
	if (val & SDIO_CCCR_LSC) {
		return SDIO_Card_SetMode(pSDMMC, SDIO_CLK_FULLSPEED, 1);
	}

	/* Low Speed Card */
	return SDIO_Card_SetMode(pSDMMC, SDIO_CLK_LOWSPEED, val & SDIO_CCCR_4BLS);
}
/*********************************************************************//**
* @brief 		Initializes the MCI card controller
* @param[in]	waitfunc Pointer to wait function to be used during for poll command status
* @param[in]	irq_callback Pointer to IRQ callback function
* @return 		None
**********************************************************************/
void sdif_init(uint32_t sdio_clock, MCI_IRQ_CB_FUNC_T irq_callback)
{
    volatile uint32_t i;

    sdif_dev.sdio_clk_rate = sdio_clock;
    sdif_dev.irq_cb = irq_callback;

    /* enable SD/MMC clock */
    sdif_enable_clock();

    /* Software reset */
    LPC_SDMMC->BMOD = MCI_BMOD_SWR;

    /* reset all blocks */
    LPC_SDMMC->CTRL = MCI_CTRL_RESET | MCI_CTRL_FIFO_RESET |
        MCI_CTRL_DMA_RESET;
    while (LPC_SDMMC->CTRL &
        (MCI_CTRL_RESET | MCI_CTRL_FIFO_RESET | MCI_CTRL_DMA_RESET));

    /* Internal DMA setup for control register */
    LPC_SDMMC->CTRL = MCI_CTRL_USE_INT_DMAC | MCI_CTRL_INT_ENABLE;
    LPC_SDMMC->INTMASK = 0;

    /* Clear the interrupts for the host controller */
    LPC_SDMMC->RINTSTS = 0xFFFFFFFF;

    /* Put in max timeout */
    LPC_SDMMC->TMOUT = 0xFFFFFFFF;

    /* FIFO threshold settings for DMA, DMA burst of 4,
       FIFO watermark at 16 */
    LPC_SDMMC->FIFOTH = MCI_FIFOTH_DMA_MTS_4 |
        MCI_FIFOTH_RX_WM((SD_FIFO_SZ / 2) - 1) |
        MCI_FIFOTH_TX_WM(SD_FIFO_SZ / 2);

    /* Enable internal DMA, burst size of 4, fixed burst */
    LPC_SDMMC->BMOD = MCI_BMOD_DE | MCI_BMOD_PBL4 | MCI_BMOD_DSL(4);

    /* disable clock to CIU (needs latch) */
    LPC_SDMMC->CLKENA = 0;
    LPC_SDMMC->CLKSRC = 0;
}