/*
 * Copyright (C) 2010-2014 The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef __DRIVERS_STORAGE_IPQ806X_MMC_H__
#define __DRIVERS_STORAGE_IPQ806X_MMC_H__

#include "drivers/storage/mmc.h"

#ifndef MMC_SLOT
#define MMC_SLOT            0
#endif

extern int __mmc_debug;
extern int __mmc_trace;

#define MMC_BOOT_MCI_REG(base, offset)          ((base) + offset)

/*
 * Define Macros for SDCC Registers
 */
#define MMC_BOOT_MCI_POWER(base)  MMC_BOOT_MCI_REG(base, 0x000)	/* 8 bit */

#define MMC_BOOT_MCI_OPEN_DRAIN           (1 << 6)
#define MMC_BOOT_MCI_PWR_OFF              0x00
#define MMC_BOOT_MCI_PWR_UP               0x02
#define MMC_BOOT_MCI_PWR_ON               0x03

#define MMC_BOOT_MCI_CLK(base)    MMC_BOOT_MCI_REG(base, 0x004)	/* 16 bits */
/* Enable MCI bus clock - 0: clock disabled 1: enabled */
#define MMC_BOOT_MCI_CLK_ENABLE           (1 << 8)
#define MMC_BOOT_MCI_CLK_DISABLE          (0 << 8)
/* Disable clk o/p when bus idle- 0:always enabled 1:enabled when bus active */
#define MMC_BOOT_MCI_CLK_PWRSAVE          (1 << 9)
/* Enable Widebus mode - 00: 1 bit mode 10:4 bit mode 01/11: 8 bit mode */
#define MMC_BOOT_MCI_CLK_WIDEBUS_MODE     (3 << 10)
#define MMC_BOOT_MCI_CLK_WIDEBUS_1_BIT    0
#define MMC_BOOT_MCI_CLK_WIDEBUS_4_BIT    (2 << 10)
#define MMC_BOOT_MCI_CLK_WIDEBUS_8_BIT    (1 << 10)
/* Enable flow control- 0: disable 1: enable */
#define MMC_BOOT_MCI_CLK_ENA_FLOW         (1 << 12)
/* Set/clear to select rising/falling edge for data/cmd output */
#define MMC_BOOT_MCI_CLK_INVERT_OUT       (1 << 13)
/* Select to lach data/cmd coming in falling/rising/feedbk/loopbk of MCIclk */
#define MMC_BOOT_MCI_CLK_IN_FALLING       0x0
#define MMC_BOOT_MCI_CLK_IN_RISING        (1 << 14)
#define MMC_BOOT_MCI_CLK_IN_FEEDBACK      (2 << 14)
#define MMC_BOOT_MCI_CLK_IN_LOOPBACK      (3 << 14)

/* Bus Width */
#define MMC_BOOT_BUS_WIDTH_1_BIT          0
#define MMC_BOOT_BUS_WIDTH_4_BIT          2
#define MMC_BOOT_BUS_WIDTH_8_BIT          3

/* Bus width support for DDR mode */
#define MMC_DDR_BUS_WIDTH_4_BIT           6
#define MMC_DDR_BUS_WIDTH_8_BIT           7

/* DDR mode select */
#define MMC_MCI_MODE_SELECT               14
#define MMC_MCI_DDR_MODE_EN               0x3

#define MMC_DEVICE_TYPE                   196

/* 32 bits */
#define MMC_BOOT_MCI_ARGUMENT(base) MMC_BOOT_MCI_REG(base, 0x008)

/* 16 bits */
#define MMC_BOOT_MCI_CMD(base)      MMC_BOOT_MCI_REG(base, 0x00C)

/* Command Index: 0 -5 */
/* Waits for response if set */
#define MMC_BOOT_MCI_CMD_RESPONSE         (1 << 6)
/* Receives a 136-bit long response if set */
#define MMC_BOOT_MCI_CMD_LONGRSP          (1 << 7)
/* If set, CPSM disables command timer and waits for interrupt */
#define MMC_BOOT_MCI_CMD_INTERRUPT        (1 << 8)
/* If set waits for CmdPend before starting to send a command */
#define MMC_BOOT_MCI_CMD_PENDING          (1 << 9)
/* CPSM is enabled if set */
#define MMC_BOOT_MCI_CMD_ENABLE           (1 << 10)
/* If set PROG_DONE status bit asserted when busy is de-asserted */
#define MMC_BOOT_MCI_CMD_PROG_ENA         (1 << 11)
/* To indicate that this is a Command with Data (for SDIO interrupts) */
#define MMC_BOOT_MCI_CMD_DAT_CMD          (1 << 12)
/* Signals the next command to be an abort (stop) command. Always read 0 */
#define MMC_BOOT_MCI_CMD_MCIABORT         (1 << 13)
/* Waits for Command Completion Signal if set */
#define MMC_BOOT_MCI_CMD_CCS_ENABLE       (1 << 14)
/* If set sends CCS disable sequence */
#define MMC_BOOT_MCI_CMD_CCS_DISABLE      (1 << 15)

#define MMC_BOOT_MCI_RESP_CMD(base)             MMC_BOOT_MCI_REG(base, 0x010)

#define MMC_BOOT_MCI_RESP_0(base)               MMC_BOOT_MCI_REG(base, 0x014)
#define MMC_BOOT_MCI_RESP_1(base)               MMC_BOOT_MCI_REG(base, 0x018)
#define MMC_BOOT_MCI_RESP_2(base)               MMC_BOOT_MCI_REG(base, 0x01C)
#define MMC_BOOT_MCI_RESP_3(base)               MMC_BOOT_MCI_REG(base, 0x020)

#define MMC_BOOT_MCI_DATA_TIMER(base)           MMC_BOOT_MCI_REG(base, 0x024)
#define MMC_BOOT_MCI_DATA_LENGTH(base)          MMC_BOOT_MCI_REG(base, 0x028)

/* 16 bits */
#define MMC_BOOT_MCI_DATA_CTL(base)             MMC_BOOT_MCI_REG(base, 0x02C)

/* Data transfer enabled */
#define MMC_BOOT_MCI_DATA_ENABLE          (1 << 0)
/* Data transfer direction - 0: controller to card 1:card to controller */
#define MMC_BOOT_MCI_DATA_DIR             (1 << 1)
/* Data transfer mode - 0: block data transfer 1: stream data transfer */
#define MMC_BOOT_MCI_DATA_MODE            (1 << 2)
/* Enable DM interface - 0: DM disabled 1: DM enabled */
#define MMC_BOOT_MCI_DATA_DM_ENABLE       (1 << 3)
/* Data block length in bytes (1-4096) */
#define MMC_BOOT_MCI_BLKSIZE_POS          4
#define MMC_BOOT_MCI_DATA_COUNT(base)           MMC_BOOT_MCI_REG(base, 0x030)
#define MMC_BOOT_MCI_STATUS(base)               MMC_BOOT_MCI_REG(base, 0x034)
/* Command response received - CRC check failed */
#define MMC_BOOT_MCI_STAT_CMD_CRC_FAIL    (1 << 0)
/* Data block sent/received - CRC check failed */
#define MMC_BOOT_MCI_STAT_DATA_CRC_FAIL   (1 << 1)
/* Command resonse timeout */
#define MMC_BOOT_MCI_STAT_CMD_TIMEOUT     (1 << 2)
/* Data timeout */
#define MMC_BOOT_MCI_STAT_DATA_TIMEOUT    (1 << 3)
/* Transmit FIFO underrun error */
#define MMC_BOOT_MCI_STAT_TX_UNDRUN       (1 << 4)
/* Receive FIFO overrun error */
#define MMC_BOOT_MCI_STAT_RX_OVRRUN       (1 << 5)
/* Command response received - CRC check passed */
#define MMC_BOOT_MCI_STAT_CMD_RESP_END    (1 << 6)
/* Command sent - no response required */
#define MMC_BOOT_MCI_STAT_CMD_SENT        (1 << 7)
/* Data end - data counter zero */
#define MMC_BOOT_MCI_STAT_DATA_END        (1 << 8)
/* Start bit not detected on all data signals in wide bus mode */
#define MMC_BOOT_MCI_STAT_START_BIT_ERR   (1 << 9)
/* Data block sent/received - CRC check passed */
#define MMC_BOOT_MCI_STAT_DATA_BLK_END    (1 << 10)
/* Command transfer in progress */
#define MMC_BOOT_MCI_STAT_CMD_ACTIVE      (1 << 11)
/* Data transmit in progress */
#define MMC_BOOT_MCI_STAT_TX_ACTIVE       (1 << 12)
/* Data receive in progress */
#define MMC_BOOT_MCI_STAT_RX_ACTIVE       (1 << 13)
/* Transmit FIFO half full */
#define MMC_BOOT_MCI_STAT_TX_FIFO_HFULL   (1 << 14)
/* Receive FIFO half full */
#define MMC_BOOT_MCI_STAT_RX_FIFO_HFULL   (1 << 15)
/* Transmit FIFO full */
#define MMC_BOOT_MCI_STAT_TX_FIFO_FULL    (1 << 16)
/* Receive FIFO full */
#define MMC_BOOT_MCI_STAT_RX_FIFO_FULL    (1 << 17)
/* Transmit FIFO empty */
#define MMC_BOOT_MCI_STAT_TX_FIFO_EMPTY   (1 << 18)
/* Receive FIFO empty */
#define MMC_BOOT_MCI_STAT_RX_FIFO_EMPTY   (1 << 19)
/* Data available in transmit FIFO */
#define MMC_BOOT_MCI_STAT_TX_DATA_AVLBL   (1 << 20)
/* Data available in receive FIFO */
#define MMC_BOOT_MCI_STAT_RX_DATA_AVLBL   (1 << 21)
/* SDIO interrupt indicator for wake-up */
#define MMC_BOOT_MCI_STAT_SDIO_INTR       (1 << 22)
/* Programming done */
#define MMC_BOOT_MCI_STAT_PROG_DONE       (1 << 23)
/* CE-ATA command completion signal detected */
#define MMC_BOOT_MCI_STAT_ATA_CMD_CMPL    (1 << 24)
/* SDIO interrupt indicator for normal operation */
#define MMC_BOOT_MCI_STAT_SDIO_INTR_OP    (1 << 25)
/* Commpand completion signal timeout */
#define MMC_BOOT_MCI_STAT_CCS_TIMEOUT     (1 << 26)

#define MMC_BOOT_MCI_STATIC_STATUS        (MMC_BOOT_MCI_STAT_CMD_CRC_FAIL| \
		MMC_BOOT_MCI_STAT_DATA_CRC_FAIL| \
		MMC_BOOT_MCI_STAT_CMD_TIMEOUT| \
		MMC_BOOT_MCI_STAT_DATA_TIMEOUT| \
		MMC_BOOT_MCI_STAT_TX_UNDRUN| \
		MMC_BOOT_MCI_STAT_RX_OVRRUN| \
		MMC_BOOT_MCI_STAT_CMD_RESP_END| \
		MMC_BOOT_MCI_STAT_CMD_SENT| \
		MMC_BOOT_MCI_STAT_DATA_END| \
		MMC_BOOT_MCI_STAT_START_BIT_ERR| \
		MMC_BOOT_MCI_STAT_DATA_BLK_END| \
		MMC_BOOT_MCI_SDIO_INTR_CLR| \
		MMC_BOOT_MCI_STAT_PROG_DONE| \
		MMC_BOOT_MCI_STAT_ATA_CMD_CMPL |\
		MMC_BOOT_MCI_STAT_CCS_TIMEOUT)

#define MMC_BOOT_MCI_CLEAR(base)                MMC_BOOT_MCI_REG(base, 0x038)
#define MMC_BOOT_MCI_CMD_CRC_FAIL_CLR     (1 << 0)
#define MMC_BOOT_MCI_DATA_CRC_FAIL_CLR    (1 << 1)
#define MMC_BOOT_MCI_CMD_TIMEOUT_CLR      (1 << 2)
#define MMC_BOOT_MCI_DATA_TIMEOUT_CLR     (1 << 3)
#define MMC_BOOT_MCI_TX_UNDERRUN_CLR      (1 << 4)
#define MMC_BOOT_MCI_RX_OVERRUN_CLR       (1 << 5)
#define MMC_BOOT_MCI_CMD_RESP_END_CLR     (1 << 6)
#define MMC_BOOT_MCI_CMD_SENT_CLR         (1 << 7)
#define MMC_BOOT_MCI_DATA_END_CLR         (1 << 8)
#define MMC_BOOT_MCI_START_BIT_ERR_CLR    (1 << 9)
#define MMC_BOOT_MCI_DATA_BLK_END_CLR     (1 << 10)
#define MMC_BOOT_MCI_SDIO_INTR_CLR        (1 << 22)
#define MMC_BOOT_MCI_PROG_DONE_CLR        (1 << 23)
#define MMC_BOOT_MCI_ATA_CMD_COMPLR_CLR   (1 << 24)
#define MMC_BOOT_MCI_CCS_TIMEOUT_CLR      (1 << 25)

#define MMC_BOOT_MCI_INT_MASK0(base)            MMC_BOOT_MCI_REG(base, 0x03C)
#define MMC_BOOT_MCI_CMD_CRC_FAIL_MASK    (1 << 0)
#define MMC_BOOT_MCI_DATA_CRC_FAIL_MASK   (1 << 1)
#define MMC_BOOT_MCI_CMD_TIMEOUT_MASK     (1 << 2)
#define MMC_BOOT_MCI_DATA_TIMEOUT_MASK    (1 << 3)
#define MMC_BOOT_MCI_TX_OVERRUN_MASK      (1 << 4)
#define MMC_BOOT_MCI_RX_OVERRUN_MASK      (1 << 5)
#define MMC_BOOT_MCI_CMD_RESP_END_MASK    (1 << 6)
#define MMC_BOOT_MCI_CMD_SENT_MASK        (1 << 7)
#define MMC_BOOT_MCI_DATA_END_MASK        (1 << 8)
#define MMC_BOOT_MCI_START_BIT_ERR_MASK   (1 << 9)
#define MMC_BOOT_MCI_DATA_BLK_END_MASK    (1 << 10)
#define MMC_BOOT_MCI_CMD_ACTIVE_MASK      (1 << 11)
#define MMC_BOOT_MCI_TX_ACTIVE_MASK       (1 << 12)
#define MMC_BOOT_MCI_RX_ACTIVE_MASK       (1 << 13)
#define MMC_BOOT_MCI_TX_FIFO_HFULL_MASK   (1 << 14)
#define MMC_BOOT_MCI_RX_FIFO_HFULL_MASK   (1 << 15)
#define MMC_BOOT_MCI_TX_FIFO_FULL_MASK    (1 << 16)
#define MMC_BOOT_MCI_RX_FIFO_FULL_MASK    (1 << 17)
#define MMC_BOOT_MCI_TX_FIFO_EMPTY_MASK   (1 << 18)
#define MMC_BOOT_MCI_RX_FIFO_EMPTY_MASK   (1 << 19)
#define MMC_BOOT_MCI_TX_DATA_AVLBL_MASK   (1 << 20)
#define MMC_BOOT_MCI_RX_DATA_AVLBL_MASK   (1 << 21)
#define MMC_BOOT_MCI_SDIO_INT_MASK        (1 << 22)
#define MMC_BOOT_MCI_PROG_DONE_MASK       (1 << 23)
#define MMC_BOOT_MCI_ATA_CMD_COMPL_MASK   (1 << 24)
#define MMC_BOOT_MCI_SDIO_INT_OPER_MASK   (1 << 25)
#define MMC_BOOT_MCI_CCS_TIME_OUT_MASK    (1 << 26)

#define MMC_BOOT_MCI_INT_MASK1(base)            MMC_BOOT_MCI_REG(base, 0x040)

#define MMC_BOOT_MCI_FIFO_COUNT(base)           MMC_BOOT_MCI_REG(base, 0x044)

#define MMC_BOOT_MCI_VERSION(base)              MMC_BOOT_MCI_REG(base, 0x050)

#define MMC_BOOT_MCI_CCS_TIMER(base)            MMC_BOOT_MCI_REG(base, 0x0058)

#define MMC_BOOT_MCI_STATUS2(base)              MMC_BOOT_MCI_REG(base, 0x06C)
#define MMC_BOOT_MCI_MCLK_REG_WR_ACTIVE   (1 << 0)

#define MMC_BOOT_MCI_FIFO(base)                 MMC_BOOT_MCI_REG(base, 0x080)

/* OCR Register */
#define MMC_BOOT_OCR_17_19                (1 << 7)
#define MMC_BOOT_OCR_27_36                (0x1FF << 15)
#define MMC_BOOT_OCR_SEC_MODE             (2 << 29)
#define MMC_BOOT_OCR_BUSY                 (1 << 31)

/* Card Status bits (R1 register) */
#define MMC_BOOT_R1_AKE_SEQ_ERROR         (1 << 3)
#define MMC_BOOT_R1_APP_CMD               (1 << 5)
#define MMC_BOOT_R1_RDY_FOR_DATA          (1 << 6)
#define MMC_BOOT_R1_CURR_STATE_IDLE       (0 << 9)
#define MMC_BOOT_R1_CURR_STATE_RDY        (1 << 9)
#define MMC_BOOT_R1_CURR_STATE_IDENT      (2 << 9)
#define MMC_BOOT_R1_CURR_STATE_STBY       (3 << 9)
#define MMC_BOOT_R1_CURR_STATE_TRAN       (4 << 9)
#define MMC_BOOT_R1_CURR_STATE_DATA       (5 << 9)
#define MMC_BOOT_R1_CURR_STATE_RCV        (6 << 9)
#define MMC_BOOT_R1_CURR_STATE_PRG        (7 << 9)
#define MMC_BOOT_R1_CURR_STATE_DIS        (8 << 9)
#define MMC_BOOT_R1_ERASE_RESET           (1 << 13)
#define MMC_BOOT_R1_CARD_ECC_DISABLED     (1 << 14)
#define MMC_BOOT_R1_WP_ERASE_SKIP         (1 << 15)
#define MMC_BOOT_R1_ERROR                 (1 << 19)
#define MMC_BOOT_R1_CC_ERROR              (1 << 20)
#define MMC_BOOT_R1_CARD_ECC_FAILED       (1 << 21)
#define MMC_BOOT_R1_ILLEGAL_CMD           (1 << 22)
#define MMC_BOOT_R1_COM_CRC_ERR           (1 << 23)
#define MMC_BOOT_R1_LOCK_UNLOCK_FAIL      (1 << 24)
#define MMC_BOOT_R1_CARD_IS_LOCKED        (1 << 25)
#define MMC_BOOT_R1_WP_VIOLATION          (1 << 26)
#define MMC_BOOT_R1_ERASE_PARAM           (1 << 27)
#define MMC_BOOT_R1_ERASE_SEQ_ERR         (1 << 28)
#define MMC_BOOT_R1_BLOCK_LEN_ERR         (1 << 29)
#define MMC_BOOT_R1_ADDR_ERR              (1 << 30)
#define MMC_BOOT_R1_OUT_OF_RANGE          (1 << 31)

/* Macro for Success*/
#define MMC_BOOT_E_SUCCESS                0

typedef struct {
	MmcCtrlr mmc;
	unsigned instance;
	uint8_t *mci_base;
	uint32_t mmc_cont_version;
} QcomMmcHost;

/* We have 16 32-bits FIFO registers */
#define MMC_BOOT_MCI_FIFO_DEPTH       16
#define MMC_BOOT_MCI_HFIFO_COUNT      (MMC_BOOT_MCI_FIFO_DEPTH / 2)
#define MMC_BOOT_MCI_FIFO_SIZE        (MMC_BOOT_MCI_FIFO_DEPTH * 4)

/* MMC clock speeds. */
#define MMC_CLK_400KHZ                400000
#define MMC_CLK_144KHZ                144000
#define MMC_CLK_20MHZ                 20000000
#define MMC_CLK_25MHZ                 25000000
#define MMC_CLK_48MHZ                 48000000
#define MMC_CLK_50MHZ                 49152000
#define MMC_CLK_96MHZ                 96000000
#define MMC_CLK_200MHZ                200000000

#define MMC_CLK_ENABLE      1
#define MMC_CLK_DISABLE     0

#define MMC_READ_ERROR		(MMC_BOOT_MCI_STAT_DATA_CRC_FAIL|\
				MMC_BOOT_MCI_STAT_DATA_TIMEOUT|\
				MMC_BOOT_MCI_STAT_RX_OVRRUN)

#define MMC_WRITE_ERROR		(MMC_BOOT_MCI_STAT_DATA_CRC_FAIL|\
				MMC_BOOT_MCI_STAT_DATA_TIMEOUT|\
				MMC_BOOT_MCI_STAT_TX_UNDRUN)

void mmc_boot_mci_clk_enable(MmcCtrlr *ctrlr);
void clock_init_mmc(unsigned instance);
void clock_config_mmc(MmcCtrlr *ctrlr, unsigned freq);
void board_mmc_gpio_config(void);
QcomMmcHost *new_qcom_mmc_host(unsigned slot, uint32_t base, int bus_width);

#endif /* __DRIVERS_STORAGE_IPQ806X_MMC_H__ */
