msm_shared: sdhci: Add support for sdhci

Implement host controller driver in compliant with SD
host contoller specifications.

Change-Id: I734ced73f30fa5e087466a166e61a67b75e903d6
diff --git a/platform/msm_shared/include/sdhci.h b/platform/msm_shared/include/sdhci.h
new file mode 100644
index 0000000..ff61868
--- /dev/null
+++ b/platform/msm_shared/include/sdhci.h
@@ -0,0 +1,340 @@
+/* Copyright (c) 2013, 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:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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 __PLATFORM_SDHCI_H_
+#define __PLATFORM_SDHCI_H_
+
+#include <reg.h>
+#include <bits.h>
+
+/*
+ * Capabilities for the host controller
+ * These values are read from the capabilities
+ * register in the controller
+ */
+struct host_caps {
+	uint32_t base_clk_rate;  /* Max clock rate supported */
+	uint32_t max_blk_len;    /* Max block len supported */
+	uint8_t bus_width_8bit;  /* 8 Bit mode supported */
+	uint8_t adma_support;    /* Adma support */
+	uint8_t voltage;         /* Supported voltage */
+	uint8_t sdr_support;     /* Single Data rate */
+	uint8_t ddr_support;     /* Dual Data rate */
+	uint8_t sdr50_support;   /* UHS mode, with 100 MHZ clock */
+};
+
+/*
+ * sdhci host structure, holding information about host
+ * controller parameters
+ */
+struct sdhci_host {
+	uint32_t base;         /* Base address for the host */
+	uint32_t cur_clk_rate; /* Running clock rate */
+	struct host_caps caps; /* Host capabilities */
+};
+
+/*
+ * Data pointer to be read/written
+ */
+struct mmc_data {
+	void *data_ptr;      /* Points to stream of data */
+	uint32_t num_blocks; /* num of blocks, each always of size SDHCI_MMC_BLK_SZ */
+};
+
+/*
+ * mmc command structure as per the spec
+ */
+struct mmc_command {
+	uint16_t cmd_index;     /* Command index */
+	uint32_t argument;      /* Command argument */
+	uint8_t data_present;   /* Command has data */
+	uint8_t cmd_type;       /* command type */
+	uint16_t resp_type;     /* Response type of the command */
+	uint32_t resp[4];       /* 128 bit response value */
+	uint32_t trans_mode;    /* Transfer mode, read/write */
+	uint32_t cmd_retry;     /* Retry the command, if card is busy */
+	struct mmc_data data;   /* Data pointer */
+};
+
+/*
+ * Descriptor table for adma
+ */
+struct desc_entry {
+	uint16_t tran_att;   /* Attribute for transfer data */
+	uint16_t len;        /* Length of data */
+	void *addr;          /* Address of the data */
+};
+
+/*
+ * Command types for sdhci
+ */
+enum {
+	SDHCI_CMD_TYPE_NORMAL = 0,
+	SDHCI_CMD_TYPE_SUSPEND,
+	SDHCI_CMD_TYPE_RESUME,
+	SDHCI_CMD_TYPE_ABORT,
+} sdhci_cmd_type;
+
+/*
+ * Response type values for sdhci
+ */
+enum {
+	SDHCI_CMD_RESP_NONE = 0,
+	SDHCI_CMD_RESP_136,
+	SDHCI_CMD_RESP_48,
+	SDHCI_CMD_RESP_48_BUSY,
+} sdhci_resp_type;
+
+
+/*
+ * Helper macros for writing byte, word & long registers
+ */
+#define REG_READ8(host, a)                        readb(host->base + a);
+#define REG_WRITE8(host, v, a)                    writeb(v, (host->base + a))
+
+#define REG_READ32(host, a)                       readl(host->base + a)
+#define REG_WRITE32(host, v, a)                   writel(v, (host->base + a))
+
+#define REG_READ16(host, a)                      readhw(host->base + a)
+#define REG_WRITE16(host, v, a)                  writehw(v, (host->base + a))
+
+/*
+ * SDHCI registers, as per the host controller spec v 3.0
+ */
+#define SDHCI_ARG2_REG                            (0x000)
+#define SDHCI_BLKSZ_REG                           (0x004)
+#define SDHCI_BLK_CNT_REG                         (0x006)
+#define SDHCI_ARGUMENT_REG                        (0x008)
+#define SDHCI_TRANS_MODE_REG                      (0x00C)
+#define SDHCI_CMD_REG                             (0x00E)
+#define SDHCI_RESP_REG                            (0x010)
+#define SDHCI_PRESENT_STATE_REG                   (0x024)
+#define SDHCI_HOST_CTRL1_REG                      (0x028)
+#define SDHCI_PWR_CTRL_REG                        (0x029)
+#define SDHCI_CLK_CTRL_REG                        (0x02C)
+#define SDHCI_TIMEOUT_REG                         (0x02E)
+#define SDHCI_RESET_REG                           (0x02F)
+#define SDHCI_NRML_INT_STS_REG                    (0x030)
+#define SDHCI_ERR_INT_STS_REG                     (0x032)
+#define SDHCI_NRML_INT_STS_EN_REG                 (0x034)
+#define SDHCI_ERR_INT_STS_EN_REG                  (0x036)
+#define SDHCI_NRML_INT_SIG_EN_REG                 (0x038)
+#define SDHCI_ERR_INT_SIG_EN_REG                  (0x03A)
+#define SDHCI_HOST_CTRL2_REG                      (0x03E)
+#define SDHCI_CAPS_REG1                           (0x040)
+#define SDHCI_CAPS_REG2                           (0x044)
+#define SDHCI_ADM_ADDR_REG                        (0x058)
+
+/*
+ * Helper macros for register writes
+ */
+#define SDHCI_SOFT_RESET                          BIT(0)
+#define SOFT_RESET_CMD                            BIT(1)
+#define SOFT_RESET_DATA                           BIT(2)
+#define SDHCI_1_8_VOL_SET                         BIT(3)
+
+/*
+ * Interrupt related
+ */
+#define SDHCI_NRML_INT_STS_EN                     0x000B
+#define SDHCI_ERR_INT_STS_EN                      0xFFFF
+#define SDHCI_NRML_INT_SIG_EN                     0x000B
+#define SDHCI_ERR_INT_SIG_EN                      0xFFFF
+
+#define SDCC_HC_INT_CARD_REMOVE                   BIT(7)
+#define SDCC_HC_INT_CARD_INSERT                   BIT(6)
+
+/*
+ * HC mode enable/disable
+ */
+#define SDHCI_HC_MODE_EN                          BIT(0)
+#define SDHCI_HC_MODE_DIS                         (0 << 1)
+
+/*
+ * Clk control related
+ */
+#define SDHCI_CLK_MAX_DIV                         2046
+#define SDHCI_SDCLK_FREQ_SEL                      8
+#define SDHCI_SDCLK_UP_BIT_SEL                    6
+#define SDHCI_SDCLK_FREQ_MASK                     0xFF
+#define SDHC_SDCLK_UP_BIT_MASK                    0x300
+#define SDHCI_INT_CLK_EN                          BIT(0)
+#define SDHCI_CLK_STABLE_MASK                     BIT(1)
+#define SDHCI_CLK_STABLE                          BIT(1)
+#define SDHCI_CLK_EN                              BIT(2)
+#define SDHCI_CLK_DIS                             (0 << 2)
+#define SDHCI_CLK_RATE_MASK                       0x0000FF00
+#define SDHCI_CLK_RATE_BIT                        8
+
+#define SDHCI_CMD_ACT                             BIT(0)
+#define SDHCI_DAT_ACT                             BIT(1)
+
+/*
+ * Bus voltage related macros
+ */
+#define SDHCI_BUS_VOL_SEL                         1
+#define SDHCI_BUS_PWR_EN                          BIT(0)
+#define SDHCI_VOL_1_8                             5
+#define SDHCI_VOL_3_0                             6
+#define SDHCI_VOL_3_3                             7
+#define SDHCI_3_3_VOL_MASK                        0x01000000
+#define SDHCI_3_0_VOL_MASK                        0x02000000
+#define SDHCI_1_8_VOL_MASK                        0x04000000
+
+/*
+ * Bus width related macros
+ */
+#define SDHCI_8BIT_WIDTH_MASK                     0x00040000
+
+#define SDHCI_BUS_WITDH_1BIT                      (0)
+#define SDHCI_BUS_WITDH_4BIT                      BIT(1)
+#define SDHCI_BUS_WITDH_8BIT                      BIT(5)
+
+/*
+ * Adma related macros
+ */
+#define SDHCI_BLK_LEN_MASK                        0x00030000
+#define SDHCI_BLK_LEN_BIT                         16
+#define SDHCI_BLK_ADMA_MASK                       0x00080000
+#define SDHCI_INT_STS_TRANS_COMPLETE              BIT(1)
+#define SDHCI_STATE_CMD_DAT_MASK                  0x0003
+#define SDHCI_INT_STS_CMD_COMPLETE                BIT(0)
+#define SDHCI_ERR_INT_STAT_MASK                   0x8000
+#define SDHCI_ADMA_DESC_LINE_SZ                   65536
+#define SDHCI_ADMA_MAX_TRANS_SZ                   (65535 * 512)
+#define SDHCI_ADMA_TRANS_VALID                    BIT(0)
+#define SDHCI_ADMA_TRANS_END                      BIT(1)
+#define SDHCI_ADMA_TRANS_DATA                     BIT(5)
+#define SDHCI_MMC_BLK_SZ                          512
+#define SDHCI_MMC_CUR_BLK_CNT_BIT                 16
+#define SDHCI_MMC_BLK_SZ_BIT                      0
+#define SDHCI_TRANS_MULTI                         BIT(5)
+#define SDHCI_TRANS_SINGLE                        (0 << 5)
+#define SDHCI_BLK_CNT_EN                          BIT(1)
+#define SDHCI_DMA_EN                              BIT(0)
+#define SDHCI_AUTO_CMD23_EN                       BIT(3)
+#define SDHCI_ADMA_32BIT                          BIT(4)
+
+/*
+ * Command related macros
+ */
+#define SDHCI_CMD_RESP_TYPE_SEL_BIT               0
+#define SDHCI_CMD_CRC_CHECK_BIT                   3
+#define SDHCI_CMD_IDX_CHECK_BIT                   4
+#define SDHCI_CMD_DATA_PRESENT_BIT                5
+#define SDHCI_CMD_CMD_TYPE_BIT                    6
+#define SDHCI_CMD_CMD_IDX_BIT                     8
+#define SDHCI_CMD_TIMEOUT_MASK                    BIT(0)
+#define SDHCI_CMD_CRC_MASK                        BIT(1)
+#define SDHCI_CMD_END_BIT_MASK                    BIT(2)
+#define SDHCI_CMD_IDX_MASK                        BIT(3)
+#define SDHCI_DAT_TIMEOUT_MASK                    BIT(4)
+#define SDHCI_DAT_CRC_MASK                        BIT(5)
+#define SDHCI_DAT_END_BIT_MASK                    BIT(6)
+#define SDHCI_CUR_LIM_MASK                        BIT(7)
+#define SDHCI_AUTO_CMD12_MASK                     BIT(8)
+#define SDHCI_ADMA_MASK                           BIT(9)
+#define SDHCI_READ_MODE                           BIT(4)
+#define SDHCI_SWITCH_CMD                          6
+#define SDHCI_CMD_TIMEOUT                         0xE
+#define SDHCI_MAX_CMD_RETRY                       10000
+#define SDHCI_MAX_TRANS_RETRY                     100000
+
+#define SDHCI_PREP_CMD(c, f)                      ((((c) & 0xff) << 8) | ((f) & 0xff))
+
+/*
+ * command response related
+ */
+#define SDHCI_RESP_LSHIFT                         8
+#define SDHCI_RESP_RSHIFT                         24
+
+/*
+ * Power control relatd macros
+ */
+#define SDHCI_SOFT_RESET_MASK                     (BIT(0) | BIT(1) | BIT(2))
+#define SDCC_HC_PWR_CTRL_INT                      0xF
+#define SDCC_HC_BUS_ON                            BIT(0)
+#define SDCC_HC_BUS_OFF                           BIT(1)
+#define SDCC_HC_BUS_ON_OFF_SUCC                   BIT(0)
+#define SDCC_HC_IO_SIG_LOW                        BIT(2)
+#define SDCC_HC_IO_SIG_HIGH                       BIT(3)
+#define SDCC_HC_IO_SIG_SUCC                       BIT(2)
+
+/*
+ * Command response
+ */
+#define SDHCI_CMD_RESP_NONE                       0
+#define SDHCI_CMD_RESP_R1                         BIT(0)
+#define SDHCI_CMD_RESP_R1B                        BIT(1)
+#define SDHCI_CMD_RESP_R2                         BIT(2)
+#define SDHCI_CMD_RESP_R3                         BIT(3)
+#define SDHCI_CMD_RESP_R6                         BIT(6)
+#define SDHCI_CMD_RESP_R7                         BIT(7)
+
+/*
+ * Clock Divider values
+ */
+#define SDHCI_CLK_400KHZ                          400000
+#define SDHCI_CLK_25MHZ                           25000000
+#define SDHCI_CLK_50MHZ                           50000000
+#define SDHCI_CLK_100MHZ                          100000000
+#define SDHCI_CLK_200MHZ                          200000000
+
+/* DDR mode related macros */
+#define SDHCI_DDR_MODE_EN                         0x0004
+#define SDHCI_DDR_MODE_MASK                       BIT(2)
+
+/* HS200/SDR50 mode related macros */
+#define SDHCI_SDR50_MODE_MASK                     BIT(0)
+#define SDHCI_SDR50_MODE_EN                       0x0002
+
+/*
+ * APIs and macros exposed for mmc/sd drivers
+ */
+#define SDHCI_MMC_WRITE                           0
+#define SDHCI_MMC_READ                            1
+
+#define DATA_BUS_WIDTH_1BIT                       0
+#define DATA_BUS_WIDTH_4BIT                       1
+#define DATA_BUS_WIDTH_8BIT                       2
+#define DATA_DDR_BUS_WIDTH_4BIT                   5
+#define DATA_DDR_BUS_WIDTH_8BIT                   6
+
+/* API: to initialize the controller */
+void     sdhci_init(struct sdhci_host *);
+/* API: Send the command & transfer data using adma */
+uint32_t sdhci_send_command(struct sdhci_host *, struct mmc_command *);
+/* API: Set the bus width for the contoller */
+uint8_t  sdhci_set_bus_width(struct sdhci_host *, uint16_t);
+/* API: Clock supply for the controller */
+uint32_t sdhci_clk_supply(struct sdhci_host *, uint32_t);
+/* API: Enable DDR mode */
+void sdhci_set_ddr_mode(struct sdhci_host *);
+/* API: To enable SDR mode */
+void sdhci_set_sdr_mode(struct sdhci_host *);
+#endif