[U-Boot] [PATCH 4/5] Add support for mmc read and writes

mohamed.haneef at lntinfotech.com mohamed.haneef at lntinfotech.com
Thu Feb 16 03:59:22 CET 2012


From: Mohamed Haneef <mohamed.haneef at lntinfotech.com>

        *Support for msm7x30 mmc read and writes

Signed-off-by: Mohamed Haneef <mohamed.haneef at lntinfotech.com>
---
 arch/arm/include/asm/arch-msm7630/mmc.h |  399 +++++++++++++++++++++
 drivers/mmc/Makefile                    |    1 +
 drivers/mmc/qc_mmc.c                    |  584 +++++++++++++++++++++++++++++++
 3 files changed, 984 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-msm7630/mmc.h
 create mode 100644 drivers/mmc/qc_mmc.c

diff --git a/arch/arm/include/asm/arch-msm7630/mmc.h b/arch/arm/include/asm/arch-msm7630/mmc.h
new file mode 100644
index 0000000..949e43c
--- /dev/null
+++ b/arch/arm/include/asm/arch-msm7630/mmc.h
@@ -0,0 +1,399 @@
+/*
+ * (C) Copyright 2012
+ * LARSEN & TOUBRO INFOTECH LTD <www.lntinfotech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __MMC_H__
+#define __MMC_H__
+
+#ifndef MMC_SLOT
+#define MMC_SLOT            0
+#endif
+
+#include <common.h>
+#include <part.h>
+#include <mmc.h>
+
+/*
+ * Define Macros for SDCC Registers
+ */
+/* 8 bit */
+#define MMC_BOOT_MCI_POWER                 0x000
+
+/* MCICMD output control - 6th bit */
+#ifdef PLATFORM_MSM7X30
+#define MMC_BOOT_MCI_OPEN_DRAIN            (1 << 6)
+#define MMC_BOOT_MCI_PWR_OFF               0x00
+#define MMC_BOOT_MCI_PWR_UP                0x01
+#define MMC_BOOT_MCI_PWR_ON                0x01
+#else
+#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
+#endif
+
+/* 16 bits */
+#define MMC_BOOT_MCI_CLK                  0x004
+/* Enable MCI bus clock - 0: clock disabled 1: enabled */
+#define MMC_BOOT_MCI_CLK_ENABLE           (1 << 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
+
+/* 32 bits */
+#define MMC_BOOT_MCI_ARGUMENT              0x008
+
+/* 16 bits */
+#define MMC_BOOT_MCI_CMD                   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               0x010
+
+#define MMC_BOOT_MCI_RESP_0                 0x014
+#define MMC_BOOT_MCI_RESP_1                 0x018
+#define MMC_BOOT_MCI_RESP_2                 0x01C
+#define MMC_BOOT_MCI_RESP_3                 0x020
+
+#define MMC_BOOT_MCI_DATA_TIMER             0x024
+#define MMC_BOOT_MCI_DATA_LENGTH            0x028
+/* 16 bits */
+#define MMC_BOOT_MCI_DATA_CTL               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            0x030
+#define MMC_BOOT_MCI_STATUS                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                  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             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              0x040
+
+#define MMC_BOOT_MCI_FIFO_COUNT            0x044
+
+#define MMC_BOOT_MCI_CCS_TIMER              0x0058
+
+#define MMC_BOOT_MCI_FIFO                   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)
+
+/* Commands type */
+#define MMC_BOOT_CMD_BCAST                (1 << 0)
+#define MMC_BOOT_CMD_BCAST_W_RESP         (1 << 1)
+#define MMC_BOOT_CMD_ADDRESS              (1 << 2)
+#define MMC_BOOT_CMD_ADDR_DATA_XFER       (1 << 3)
+
+/* 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)
+
+/* Macros for Common Errors */
+#define MMC_BOOT_E_SUCCESS                0
+#define MMC_BOOT_E_FAILURE                1
+/* Not used..use instead TIMEOUT in include/mmc.h */
+#define MMC_BOOT_E_TIMEOUT                2
+#define MMC_BOOT_E_INVAL                  3
+#define MMC_BOOT_E_CRC_FAIL               4
+#define MMC_BOOT_E_INIT_FAIL              5
+#define MMC_BOOT_E_CMD_INDX_MISMATCH      6
+#define MMC_BOOT_E_RESP_VERIFY_FAIL       7
+#define MMC_BOOT_E_NOT_SUPPORTED          8
+#define MMC_BOOT_E_CARD_BUSY              9
+#define MMC_BOOT_E_MEM_ALLOC_FAIL         10
+#define MMC_BOOT_E_CLK_ENABLE_FAIL        11
+#define MMC_BOOT_E_CMMC_DECODE_FAIL       12
+#define MMC_BOOT_E_CID_DECODE_FAIL        13
+#define MMC_BOOT_E_BLOCKLEN_ERR           14
+#define MMC_BOOT_E_ADDRESS_ERR            15
+#define MMC_BOOT_E_DATA_CRC_FAIL          16
+#define MMC_BOOT_E_DATA_TIMEOUT           17
+#define MMC_BOOT_E_RX_OVRRUN              18
+#define MMC_BOOT_E_VREG_SET_FAILED        19
+#define MMC_BOOT_E_GPIO_CFG_FAIL          20
+#define MMC_BOOT_E_DATA_ADM_ERR           21
+
+/* EXT_CSD */
+#define MMC_BOOT_ACCESS_WRITE             0x3
+#define MMC_BOOT_EXT_CMMC_HS_TIMING       185
+#define MMC_BOOT_EXT_CMMC_BUS_WIDTH       183
+
+#define MMC_BOOT_EXT_USER_WP              171
+#define MMC_BOOT_EXT_ERASE_GROUP_DEF      175
+#define MMC_BOOT_EXT_HC_WP_GRP_SIZE       221
+#define MMC_BOOT_EXT_HC_ERASE_GRP_SIZE    224
+
+#define MMC_BOOT_US_PERM_WP_EN            2
+#define MMC_BOOT_US_PWR_WP_DIS            3
+
+#define MMC_BOOT_US_PERM_WP_DIS           (1<<4)
+#define MMC_BOOT_US_PWR_WP_EN             1
+
+/* For SD */
+#define MMC_BOOT_SD_HC_VOLT_SUPPLIED      0x000001AA
+#define MMC_BOOT_SD_NEG_OCR               0x00FF8000
+#define MMC_BOOT_SD_HC_HCS                0x40000000
+#define MMC_BOOT_SD_DEV_READY             0x80000000
+#define MMC_BOOT_SD_SWITCH_HS             0x80FFFFF1
+
+/* Data structure definitions */
+
+#define MMC_BOOT_XFER_MODE_BLOCK          0
+#define MMC_BOOT_XFER_MODE_STREAM         1
+#define MMC_BOOT_PROGRAM_ENABLED          2
+
+
+#define MMC_RCA 2
+
+#define MMC_BOOT_MAX_COMMAND_RETRY    1000
+#define MMC_BOOT_RD_BLOCK_LEN         512
+#define MMC_BOOT_WR_BLOCK_LEN         512
+
+/* 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)
+
+#define MAX_PARTITIONS 64
+
+#define MMC_BOOT_CHECK_PATTERN        0xAA /* 10101010b */
+
+#define MMC_CLK_400KHZ                400000
+#define MMC_CLK_144KHZ                144000
+#define MMC_CLK_20MHZ                 20000000
+#define MMC_CLK_24MHZ                 24000000
+#define MMC_CLK_25MHZ                 25000000
+#define MMC_CLK_26MHZ                 26000000
+#define MMC_CLK_48MHZ                 48000000
+#define MMC_CLK_50MHZ                 49152000
+#define MMC_CLK_52MHZ                 52000000
+
+#define MMC_CLK_ENABLE      1
+#define MMC_CLK_DISABLE     0
+
+#if 0
+#define MSM_SDC1_BASE       0x12400000
+#define MSM_SDC2_BASE       0x12140000
+#define MSM_SDC3_BASE       0x12180000
+#define MSM_SDC4_BASE       0x121C0000
+#endif
+struct mmc_priv {
+       unsigned int instance;
+       unsigned int base;
+       unsigned int rd_timeout_ns;     /* for read timeout */
+};
+
+void mmc_boot_set_ios(struct mmc *mmc);
+int mmc_boot_send_command_map(struct mmc *mmc,
+                                       struct mmc_cmd *cmd,
+                                       struct mmc_data *data);
+unsigned long int mmc_boot_mci_reg(unsigned long base, unsigned long offset);
+unsigned int mmc_boot_main(struct mmc *mmc);
+
+extern void clock_config_mmc(uint32_t interface, uint32_t freq);
+extern void clock_init_mmc(uint32_t interface);
+#endif
+
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 506f1d6..2d926ec 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -44,6 +44,7 @@ COBJS-$(CONFIG_S5P_MMC) += s5p_mmc.o
 COBJS-$(CONFIG_SDHCI) += sdhci.o
 COBJS-$(CONFIG_SH_MMCIF) += sh_mmcif.o
 COBJS-$(CONFIG_TEGRA2_MMC) += tegra2_mmc.o
+COBJS-$(CONFIG_QC_MMC) += qc_mmc.o

 COBJS  := $(COBJS-y)
 SRCS   := $(COBJS:.o=.c)
diff --git a/drivers/mmc/qc_mmc.c b/drivers/mmc/qc_mmc.c
new file mode 100644
index 0000000..7b7a1ed
--- /dev/null
+++ b/drivers/mmc/qc_mmc.c
@@ -0,0 +1,584 @@
+/*
+ * (C) Copyright 2012
+ * LARSEN & TOUBRO INFOTECH LTD <www.lntinfotech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/iomap.h>
+#include <common.h>
+
+#if MMC_BOOT_ADM
+#include "adm.h"
+#endif
+
+#ifndef NULL
+#define NULL        0
+#endif
+
+#define MMC_BOOT_DATA_READ     0
+#define MMC_BOOT_DATA_WRITE    1
+/*
+ * Calculates the address of registers according to the base address
+ */
+unsigned long int mmc_boot_mci_reg(unsigned long base, unsigned long offset)
+{
+       return base + offset;
+}
+
+
+/*
+ * Sets a timeout for read operation.
+ */
+static unsigned int mmc_boot_set_read_timeout(struct mmc *mmc)
+{
+       if (mmc == NULL)
+               return MMC_BOOT_E_INVAL;
+
+       /* todo: Add a check for HC, only if HC do this.
+        * If not, taac and nsac must be taken into account
+        */
+       ((struct mmc_priv *)(mmc->priv))->rd_timeout_ns = 100000000;
+       debug(" Read timeout set: %d ns\n",
+       ((struct mmc_priv *)(mmc->priv))->rd_timeout_ns);
+
+       return MMC_BOOT_E_SUCCESS;
+}
+
+/*
+ * Check to ensure that there is no alignment or data length errors
+ */
+static unsigned int mmc_boot_check_read_data(struct mmc_cmd *cmd)
+{
+
+       if (cmd->response[0] & MMC_BOOT_R1_BLOCK_LEN_ERR)
+               return MMC_BOOT_E_BLOCKLEN_ERR;
+
+       /* Misaligned address not matching block length */
+       if (cmd->response[0] & MMC_BOOT_R1_ADDR_ERR)
+               return MMC_BOOT_E_ADDRESS_ERR;
+
+       return MMC_BOOT_E_SUCCESS;
+}
+
+/*
+ * Decode type of error caused during read and write
+ */
+static unsigned int mmc_boot_status_error(unsigned mmc_status)
+{
+       unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
+
+               /* If DATA_CRC_FAIL bit is set to 1 then CRC error
+                * was detected by card/device during the data transfer
+                */
+       if (mmc_status & MMC_BOOT_MCI_STAT_DATA_CRC_FAIL)
+               mmc_ret = MMC_BOOT_E_DATA_CRC_FAIL;
+               /* If DATA_TIMEOUT bit is set to 1 then the data transfer time
+                * exceeded the data timeout period without completing the
+                * transfer
+                */
+       else if (mmc_status & MMC_BOOT_MCI_STAT_DATA_TIMEOUT)
+               mmc_ret = MMC_BOOT_E_DATA_TIMEOUT;
+               /* If RX_OVERRUN bit is set to 1 then SDCC2 tried to
+                * receive data from the card before empty storage for new
+                * received data was available.
+                * Verify that bit FLOW_ENA in MCI_CLK is set to 1 during
+                * the data xfer.
+                */
+       else if (mmc_status & MMC_BOOT_MCI_STAT_RX_OVRRUN)
+               /* Note: We've set FLOW_ENA bit in MCI_CLK to 1.
+                * so no need to verify for now
+                */
+               mmc_ret = MMC_BOOT_E_RX_OVRRUN;
+               /* If TX_UNDERRUN bit is set to 1 then SDCC2 tried to send
+                * data to the card before new data for sending was available.
+                * Verify that bit FLOW_ENA in MCI_CLK
+                * is set to 1 during the data xfer.
+                */
+       else if (mmc_status & MMC_BOOT_MCI_STAT_TX_UNDRUN)
+               /* Note: We've set FLOW_ENA bit in MCI_CLK to 1.
+                * so skipping it now
+                */
+               mmc_ret = MMC_BOOT_E_RX_OVRRUN;
+
+       return mmc_ret;
+}
+
+/*
+ * Read data to SDC FIFO.
+ */
+static unsigned int mmc_boot_fifo_read(unsigned int *mmc_ptr,
+                                               unsigned int  data_len,
+                                               struct mmc *mmc)
+{
+       unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
+       unsigned int mmc_status = 0;
+       unsigned int mmc_count = 0;
+       unsigned int read_error = MMC_BOOT_MCI_STAT_DATA_CRC_FAIL | \
+                                       MMC_BOOT_MCI_STAT_DATA_TIMEOUT  | \
+                                       MMC_BOOT_MCI_STAT_RX_OVRRUN;
+       unsigned int i;
+       struct mmc_priv *priv = (struct mmc_priv  *)mmc->priv;
+       unsigned long reg_status, reg_fifo;
+
+       reg_status = mmc_boot_mci_reg(priv->base, MMC_BOOT_MCI_STATUS);
+       reg_fifo = mmc_boot_mci_reg(priv->base, MMC_BOOT_MCI_FIFO);
+
+       /* Read the data from the MCI_FIFO register as long as
+        * RXDATA_AVLBL bit of MCI_STATUS register is set to 1 and bits
+        * DATA_CRC_FAIL, DATA_TIMEOUT, RX_OVERRUN of MCI_STATUS
+        * register are cleared to 0.
+        * Continue the reads until the whole transfer data is received
+        */
+
+       do {
+               mmc_ret = MMC_BOOT_E_SUCCESS;
+               mmc_status = readl(reg_status);
+
+               if (mmc_status & read_error) {
+                       mmc_ret = mmc_boot_status_error(mmc_status);
+                       break;
+               }
+
+               if (mmc_status & MMC_BOOT_MCI_STAT_RX_DATA_AVLBL) {
+                       unsigned read_count = 1;
+                       if (mmc_status & MMC_BOOT_MCI_STAT_RX_FIFO_HFULL)
+                               read_count = MMC_BOOT_MCI_HFIFO_COUNT;
+
+                       for (i = 0; i < read_count; i++) {
+                               /* FIFO contains 16 32-bit data buffer
+                                 * on 16 sequential addresses
+                                 */
+                               *mmc_ptr = readl(reg_fifo +
+                                       (mmc_count % MMC_BOOT_MCI_FIFO_SIZE));
+                               mmc_ptr++;
+                               /* increase mmc_count by word size */
+                               mmc_count += sizeof(unsigned int);
+                       }
+                       /* quit if we have read enough of data */
+                       if (mmc_count == data_len)
+                               break;
+               } else if (mmc_status & MMC_BOOT_MCI_STAT_DATA_END)
+                       break;
+       }  while (1);
+       return mmc_ret;
+}
+
+static unsigned int mmc_boot_fifo_data_transfer(unsigned int *data_ptr,
+                                                       unsigned int  data_len,
+                                                       unsigned char direction,
+                                                       struct mmc *mmc)
+{
+       unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
+
+       if (direction == MMC_BOOT_DATA_READ)
+               mmc_ret = mmc_boot_fifo_read(data_ptr, data_len, mmc);
+
+       return mmc_ret;
+}
+
+/*
+ * Sends specified command to a card and waits for a response.
+ */
+static unsigned int mmc_boot_send_command(struct mmc_cmd *cmd,
+                                               struct mmc *mmc)
+{
+       unsigned int mmc_cmd = 0;
+       unsigned int mmc_status = 0;
+       unsigned int mmc_resp = 0;
+       unsigned int mmc_return = MMC_BOOT_E_SUCCESS;
+       unsigned int cmd_index = 0;
+       int i = 0;
+       unsigned long reg, reg_status, reg_resp_cmd, reg_resp_0;
+       struct mmc_priv *priv = (struct mmc_priv  *)mmc->priv;
+
+       /* basic check */
+       if (cmd == NULL)
+               return MMC_BOOT_E_INVAL;
+
+       /* 1. Write command argument to MMC_BOOT_MCI_ARGUMENT register */
+       reg = mmc_boot_mci_reg(priv->base, MMC_BOOT_MCI_ARGUMENT);
+       writel(cmd->cmdarg, reg);
+
+       /* Writes to MCI port are not effective for 3 ticks of PCLK.
+        * ticks calculated using 400KHz clock speed
+        */
+       udelay(8);
+
+       /* 2. Set appropriate fields and write MMC_BOOT_MCI_CMD */
+       /* 2a. Write command index in CMD_INDEX field */
+       cmd_index = cmd->cmdidx;
+       mmc_cmd |= cmd->cmdidx;
+       /* 2b. Set RESPONSE bit to 1 for all cmds except CMD0 */
+       if (cmd_index != MMC_CMD_GO_IDLE_STATE)
+               mmc_cmd |= MMC_BOOT_MCI_CMD_RESPONSE;
+
+       /* 2c. Set LONGRESP bit to 1 for CMD2, CMD9 and CMD10 */
+       if (cmd->resp_type & MMC_RSP_136)
+               mmc_cmd |= MMC_BOOT_MCI_CMD_LONGRSP;
+
+       /* 2d. Set INTERRUPT bit to 1 to disable command timeout */
+
+       /* 2e. Set PENDING bit to 1 for CMD12 in the beginning of stream
+        * mode data transfer
+        */
+       if (cmd->flags & MMC_BOOT_XFER_MODE_STREAM)
+               mmc_cmd |= MMC_BOOT_MCI_CMD_PENDING;
+
+       /* 2f. Set ENABLE bit to 1 */
+       mmc_cmd |= MMC_BOOT_MCI_CMD_ENABLE;
+
+       /* 2g. Set PROG_ENA bit to 1 for CMD12, CMD13 issued at the end of
+        * write data transfer
+        */
+       if ((cmd_index == MMC_CMD_STOP_TRANSMISSION ||
+                       cmd_index == MMC_CMD_SEND_STATUS) &&
+                       (cmd->flags & MMC_BOOT_PROGRAM_ENABLED))
+                       mmc_cmd |= MMC_BOOT_MCI_CMD_PROG_ENA;
+
+
+       /* 2h. Set MCIABORT bit to 1 for CMD12 when working with SDIO card */
+       /* 2i. Set CCS_ENABLE bit to 1 for CMD61 when Command Completion Signal
+        * of CE-ATA device is enabled
+        */
+
+       /* 2j. clear all static status bits */
+       reg = mmc_boot_mci_reg(priv->base, MMC_BOOT_MCI_CLEAR);
+       writel(MMC_BOOT_MCI_STATIC_STATUS, reg);
+
+       /* 2k. Write to MMC_BOOT_MCI_CMD register */
+       reg = mmc_boot_mci_reg(priv->base, MMC_BOOT_MCI_CMD);
+       writel(mmc_cmd, reg);
+
+       /* Writes to MCI port are not effective for 3 ticks of PCLK.
+        * ticks calculated using 400KHz clock speed
+        */
+       udelay(8);
+
+       reg_status = mmc_boot_mci_reg(priv->base, MMC_BOOT_MCI_STATUS);
+       reg_resp_cmd = mmc_boot_mci_reg(priv->base, MMC_BOOT_MCI_RESP_CMD);
+       reg_resp_0 = mmc_boot_mci_reg(priv->base, MMC_BOOT_MCI_RESP_0);
+
+       /* 3. Wait for interrupt or poll on the following bits of MCI_STATUS
+        * register
+        */
+       do {
+               /* 3a. Read MCI_STATUS register */
+               mmc_status = readl(reg_status);
+               while (mmc_status & MMC_BOOT_MCI_STAT_CMD_ACTIVE)
+                       mmc_status = readl(reg_status);
+
+               /* 3b. CMD_SENT bit supposed to be set to 1 only
+                 * after CMD0 is sent -no response required.
+                 */
+               if ((cmd->resp_type == MMC_RSP_NONE) &&
+                               (mmc_status & MMC_BOOT_MCI_STAT_CMD_SENT))
+                       break;
+
+               /* 3c. If CMD_TIMEOUT bit is set then no response
+                 * was received */
+               else if (mmc_status & MMC_BOOT_MCI_STAT_CMD_TIMEOUT) {
+                       mmc_return = TIMEOUT;
+                       break;
+               }
+               /* 3d. If CMD_RESPONSE_END bit is set to 1 then command's
+                 * response was received and CRC check passed
+                 * Spcial case for ACMD41: it seems to always fail CRC even if
+                 * the response is valid
+                 */
+               else if ((mmc_status & MMC_BOOT_MCI_STAT_CMD_RESP_END) ||
+                               (cmd_index == MMC_CMD_SEND_OP_COND)
+                               || (cmd_index == SD_CMD_SEND_IF_COND)) {
+                       /* 3i. Read MCI_RESP_CMD register to verify that
+                         *  response index is equal to command index
+                         */
+                       mmc_resp = readl(reg_resp_cmd) & 0x3F;
+
+                       /* However, long response does not contain the
+                        * command index field.
+                        * In that case, response index field must be set to
+                        * 111111b (0x3F)
+                        */
+                       if ((mmc_resp == cmd_index) ||
+                               (cmd->resp_type == MMC_RSP_R2 ||
+                               cmd->resp_type == MMC_RSP_R3 ||
+                               cmd->resp_type == MMC_RSP_R6 ||
+                               cmd->resp_type == MMC_RSP_R7)){
+                               /* 3j. If resp index is equal to cmd index,
+                                 * read command resp from MCI_RESPn registers
+                                 * - MCI_RESP0/1/2/3 for CMD2/9/10
+                                 * - MCI_RESP0 for all other registers
+                                 */
+                               if (cmd->resp_type & MMC_RSP_136) {
+                                       for (i = 0; i < 4; i++)
+                                               cmd->response[3-i] =
+                                                       readl(reg_resp_0 + \
+                                                       (i * 4));
+                               } else
+                                       cmd->response[0] = readl(reg_resp_0);
+                       } else
+                               /* command index mis-match */
+                               mmc_return = MMC_BOOT_E_CMD_INDX_MISMATCH;
+
+                       break;
+               }
+
+               /* 3e. If CMD_CRC_FAIL bit is set to 1 then cmd's response
+                * was recvd, but CRC check failed.
+                */
+               else if ((mmc_status & MMC_BOOT_MCI_STAT_CMD_CRC_FAIL)) {
+                       if (cmd_index == SD_CMD_APP_SEND_OP_COND)
+                               cmd->response[0] = readl(reg_resp_0);
+                       else
+                               mmc_return = MMC_BOOT_E_CRC_FAIL;
+                       break;
+               }
+
+       }  while (1);
+
+       return mmc_return;
+}
+
+static void mmc_boot_init_data(struct mmc *mmc, struct mmc_cmd *cmd,
+                       struct mmc_data *data)
+{
+       uint32_t data_ctrl, mmc_reg, data_len;
+       struct mmc_priv *priv = (struct mmc_priv  *)mmc->priv;
+       unsigned long reg;
+
+       /* Write data timeout period to MCI_DATA_TIMER register. */
+       /* Data timeout period should be in card bus clock periods */
+       mmc_reg = (unsigned long)(((struct mmc_priv *)
+                                               (mmc->priv))->rd_timeout_ns /
+                                               1000000) * (mmc->clock / 1000);
+       /* add some extra clock cycles to be safe */
+       mmc_reg += 1000;
+       mmc_reg = mmc_reg/2;
+
+       reg = mmc_boot_mci_reg(priv->base, MMC_BOOT_MCI_DATA_TIMER);
+       writel(mmc_reg, reg);
+
+       /* Write the total size of the transfer data to MCI_DATA_LENGTH
+        * register. For block xfer it must be multiple of the block
+        * size.
+        */
+
+       data_len = data->blocks*data->blocksize;
+       reg = mmc_boot_mci_reg(priv->base, MMC_BOOT_MCI_DATA_LENGTH);
+       writel(data_len, reg);
+
+       /* Writes to MCI port are not effective for 3 ticks of PCLK.
+        * ticks calculated using 400KHz clock speed
+        */
+       udelay(8);
+
+       data_ctrl = MMC_BOOT_MCI_DATA_ENABLE |
+               (data->blocksize << MMC_BOOT_MCI_BLKSIZE_POS);
+
+
+       if (data->flags == MMC_DATA_READ)
+               data_ctrl |= MMC_BOOT_MCI_DATA_DIR;
+
+       reg = mmc_boot_mci_reg(priv->base, MMC_BOOT_MCI_DATA_CTL);
+       writel(data_ctrl, reg);
+
+       /* Writes to MCI port are not effective for 3 ticks of PCLK.
+        * ticks calculated using 400KHz clock speed
+        */
+       udelay(8);
+
+}
+
+/*
+ * Function to map mmc send command to board send command
+ */
+int mmc_boot_send_command_map(struct mmc *mmc,
+                               struct mmc_cmd *cmd,
+                               struct mmc_data *data)
+{
+       unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
+
+       /*  todo: do we need to fill in command type ?? */
+
+       if (cmd->cmdidx == MMC_CMD_SEND_STATUS) {
+               /* u-boot doesn't fill in the correct argument value */
+               cmd->cmdarg =  mmc->rca << 16;
+               /* this is to explicitly disable the prg enabled flag */
+               cmd->flags &= ~MMC_BOOT_PROGRAM_ENABLED;
+
+       } else if (cmd->cmdidx == MMC_CMD_READ_SINGLE_BLOCK) {
+               if (mmc->read_bl_len != MMC_BOOT_RD_BLOCK_LEN &&
+                               mmc->version & SD_VERSION_SD) {
+                       mmc->read_bl_len = MMC_BOOT_RD_BLOCK_LEN;
+                       data->blocksize = MMC_BOOT_RD_BLOCK_LEN;
+               }
+       } else if (cmd->cmdidx == MMC_CMD_READ_MULTIPLE_BLOCK) {
+                       if (mmc->read_bl_len != MMC_BOOT_RD_BLOCK_LEN &&
+                                       mmc->version & SD_VERSION_SD) {
+                               mmc->read_bl_len = MMC_BOOT_RD_BLOCK_LEN;
+                               data->blocksize = MMC_BOOT_RD_BLOCK_LEN;
+                       }
+       } else if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) {
+                       /* explicitly disable the prg enabled flag */
+                       cmd->flags &= ~MMC_BOOT_PROGRAM_ENABLED;
+                       /* set the XFER mode */
+                       cmd->flags |= MMC_BOOT_XFER_MODE_BLOCK;
+       }
+
+
+       /* For Data cmd's */
+       if (data != NULL)
+               mmc_boot_init_data(mmc, cmd, data);
+
+       /* send command */
+       mmc_ret = mmc_boot_send_command(cmd, mmc);
+
+       if (mmc_ret != MMC_BOOT_E_SUCCESS) {
+               debug("Return Error = %d\n", mmc_ret);
+               return mmc_ret;
+       }
+
+       if (data != NULL) {
+               mmc_ret = mmc_boot_check_read_data(cmd);
+               if (mmc_ret)
+                       return mmc_ret;
+               mmc_boot_fifo_data_transfer((unsigned int *) data->dest,
+                                       data->blocks * data->blocksize,
+                                       MMC_BOOT_DATA_READ,
+                                       mmc);
+       }
+
+       if (cmd->cmdidx == MMC_CMD_SEND_CSD) {
+               /* Set read timeout once csd is received */
+               mmc_ret = mmc_boot_set_read_timeout(mmc);
+               if (mmc_ret != MMC_BOOT_E_SUCCESS) {
+                       printf("Error No.%d: Failure setting \
+                                       write Timeout value!\n",
+                                       mmc_ret);
+                       return mmc_ret;
+               }
+       } else if ((cmd->cmdidx == SD_CMD_SWITCH_FUNC) && (data != NULL)) {
+               /* cmd6 needs at least 8 clocks after the
+                * End Data of Status.
+                * ticks calculated using 400KHz clock speed
+                */
+               udelay(20);
+       }
+
+       return mmc_ret;
+}
+
+/*
+ * Initialize host structure, set and enable clock-rate and power mode.
+ */
+unsigned int mmc_boot_init(struct mmc *mmc)
+{
+       unsigned int mmc_pwr = 0;
+       struct mmc_priv *priv = (struct mmc_priv *) mmc->priv;
+       int mmc_slot = priv->instance;
+       unsigned long reg;
+
+       /* Initialize any clocks needed for SDC controller */
+       clock_init_mmc(mmc_slot);
+
+       /* Setup initial freq to 400KHz */
+       clock_config_mmc(mmc_slot, MMC_CLK_400KHZ);
+
+       /* set power mode*/
+       mmc_pwr &= ~MMC_BOOT_MCI_PWR_UP;
+       mmc_pwr |= MMC_BOOT_MCI_PWR_ON;
+       mmc_pwr |= MMC_BOOT_MCI_PWR_UP;
+       reg = mmc_boot_mci_reg(priv->base, MMC_BOOT_MCI_POWER);
+       writel(mmc_pwr, reg);
+
+       /* Writes to MCI port are not effective for 3 ticks of PCLK.
+        * ticks calculated using 400KHz clock speed
+        */
+       udelay(8);
+
+       return MMC_BOOT_E_SUCCESS;
+}
+
+static unsigned int mmc_boot_set_bus_width(unsigned int width,
+                                               struct mmc *mmc)
+{
+       unsigned int mmc_reg;
+       struct mmc_priv *priv = (struct mmc_priv  *)mmc->priv;
+       unsigned long reg;
+
+       /* set MCI_CLK accordingly */
+       reg = mmc_boot_mci_reg(priv->base, MMC_BOOT_MCI_CLK);
+       mmc_reg = readl(reg);
+       mmc_reg &= ~MMC_BOOT_MCI_CLK_WIDEBUS_MODE;
+       if (width == 1)
+               mmc_reg |=  MMC_BOOT_MCI_CLK_WIDEBUS_1_BIT;
+       else if (width == 4)
+               mmc_reg |=  MMC_BOOT_MCI_CLK_WIDEBUS_4_BIT;
+       else if (width == 8)
+               mmc_reg |=  MMC_BOOT_MCI_CLK_WIDEBUS_8_BIT;
+       else
+               return MMC_BOOT_E_INVAL;
+
+       writel(mmc_reg, reg);
+
+       /* Writes to MCI port are not effective for 3 ticks of PCLK.
+        * ticks calculated using 400KHz clock speed
+        */
+       udelay(8);
+
+       debug("Setting bus width to %d\n", width);
+       return MMC_BOOT_E_SUCCESS;
+}
+
+void mmc_boot_set_ios(struct mmc *mmc)
+{
+       unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
+       struct mmc_priv *priv = (struct mmc_priv  *)mmc->priv;
+       int mmc_slot = priv->instance;
+
+       /* clock frequency should be less than 400KHz in identification mode */
+       clock_config_mmc(mmc_slot, mmc->clock);
+       /*
+        * give atleast 2 MCLK cycles delay for clocks
+        * and SDCC core to stabilize.
+        * ticks calculated using 400KHz clock speed
+        */
+       udelay(5);
+       mmc_ret = mmc_boot_set_bus_width(mmc->bus_width, mmc);
+       if (mmc_ret != MMC_BOOT_E_SUCCESS)
+               printf("Set bus width error %d\n", mmc_ret);
+}
+
+/*
+ * Board specific initializations
+ */
+unsigned int mmc_boot_main(struct mmc *mmc)
+{
+       unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
+
+       /* Initialize necessary data structure and enable/set clock and power */
+       debug(" Initializing MMC host data structure and clock!\n");
+       mmc_ret = mmc_boot_init(mmc);
+       if (mmc_ret != MMC_BOOT_E_SUCCESS) {
+               printf("MMC Boot: Error Initializing MMC Card!!!\n");
+               return MMC_BOOT_E_FAILURE;
+       }
+
+       return MMC_BOOT_E_SUCCESS;
+}
--
1.7.1


The contents of this e-mail and any attachment(s) may contain confidential or privileged information for the intended recipient(s). Unintended recipients are prohibited from taking action on the basis of information in this e-mail and  using or disseminating the information,  and must notify the sender and delete it from their system. L&T Infotech will not accept responsibility or liability for the accuracy or completeness of, or the presence of any virus or disabling code in this e-mail"


More information about the U-Boot mailing list