]> git.sur5r.net Git - u-boot/commitdiff
Merge branch 'master' of git://git.denx.de/u-boot-mpc83xx
authorWolfgang Denk <wd@denx.de>
Fri, 13 Jan 2012 19:07:40 +0000 (20:07 +0100)
committerWolfgang Denk <wd@denx.de>
Fri, 13 Jan 2012 19:07:40 +0000 (20:07 +0100)
* 'master' of git://git.denx.de/u-boot-mpc83xx:
  mpc8313erdb: fix mtdparts address
  powerpc/83xx/km: add support for 8321 based tuge1 board
  powerpc/83xx/km: merge tuxa and tuda1 boards to tuxx1
  powerpc/83xx/km: remove obsolete defines for tuda1
  powerpc/83xx/km: update SDRAM parameters for km8321 boards
  mpc8313erdb: Enable GPIO support on the MPC8313E RDB
  mpc83xx: Add a GPIO driver for the MPC83XX family
  gpio: Replace ARM gpio.h with the common API in include/asm-generic
  gpio: Modify common gpio.h to more closely match Linux

26 files changed:
board/efikamx/efikamx.c
board/emk/top9000/top9000.c
board/freescale/mx51evk/mx51evk.c
board/freescale/mx53ard/mx53ard.c
board/freescale/mx53evk/mx53evk.c
board/freescale/mx53loco/mx53loco.c
board/freescale/mx53smd/mx53smd.c
doc/README.atmel_mci
drivers/mmc/arm_pl180_mmci.c
drivers/mmc/bfin_sdh.c
drivers/mmc/davinci_mmc.c
drivers/mmc/fsl_esdhc.c
drivers/mmc/ftsdc010_esdhc.c
drivers/mmc/gen_atmel_mci.c
drivers/mmc/mmc.c
drivers/mmc/mmc_spi.c
drivers/mmc/mv_sdhci.c
drivers/mmc/mxcmmc.c
drivers/mmc/mxsmmc.c
drivers/mmc/omap_hsmmc.c
drivers/mmc/pxa_mmc_gen.c
drivers/mmc/s5p_mmc.c
drivers/mmc/sdhci.c
drivers/mmc/sh_mmcif.c
drivers/mmc/tegra2_mmc.c
include/mmc.h

index 1f6c457e9909e41d14710cb38a05831533ec11b2..e88b2edfa10865aeccb7477f13a63f6451754fee 100644 (file)
@@ -314,17 +314,18 @@ static inline uint32_t efika_mmc_cd(void)
                return MX51_PIN_EIM_CS2;
 }
 
-int board_mmc_getcd(u8 *absent, struct mmc *mmc)
+int board_mmc_getcd(struct mmc *mmc)
 {
        struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
        uint32_t cd = efika_mmc_cd();
+       int ret;
 
        if (cfg->esdhc_base == MMC_SDHC1_BASE_ADDR)
-               *absent = gpio_get_value(IOMUX_TO_GPIO(cd));
+               ret = !gpio_get_value(IOMUX_TO_GPIO(cd));
        else
-               *absent = gpio_get_value(IOMUX_TO_GPIO(MX51_PIN_GPIO1_8));
+               ret = !gpio_get_value(IOMUX_TO_GPIO(MX51_PIN_GPIO1_8));
 
-       return 0;
+       return ret;
 }
 
 int board_mmc_init(bd_t *bis)
index 6f5662a96d506f5b195f92dd17bb1ed7e380b5c3..e0b4cf2c330599484a6ea1dfa60a0a72fe6c1726 100644 (file)
@@ -108,17 +108,9 @@ int board_mmc_init(bd_t *bd)
 }
 
 /* this is a weak define that we are overriding */
-int board_mmc_getcd(u8 *cd, struct mmc *mmc)
+int board_mmc_getcd(struct mmc *mmc)
 {
-       /*
-        * the only currently existing use of this function
-        * (fsl_esdhc.c) suggests this function must return
-        * *cs = TRUE if a card is NOT detected -> in most
-        * cases the value of the pin when the detect switch
-        * closes to GND
-        */
-       *cd = at91_get_gpio_value(CONFIG_SYS_MMC_CD_PIN) ? 1 : 0;
-       return 0;
+       return !at91_get_gpio_value(CONFIG_SYS_MMC_CD_PIN);
 }
 
 #endif
index e43aaf726ec605959e257aefce05553e0e2b7d81..8d1f6a33ce55b2d6418f61fd3631881ad810ef20 100644 (file)
@@ -321,19 +321,20 @@ static void power_init(void)
 }
 
 #ifdef CONFIG_FSL_ESDHC
-int board_mmc_getcd(u8 *cd, struct mmc *mmc)
+int board_mmc_getcd(struct mmc *mmc)
 {
        struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+       int ret;
 
        mxc_request_iomux(MX51_PIN_GPIO1_0, IOMUX_CONFIG_ALT1);
        mxc_request_iomux(MX51_PIN_GPIO1_6, IOMUX_CONFIG_ALT0);
 
        if (cfg->esdhc_base == MMC_SDHC1_BASE_ADDR)
-               *cd = gpio_get_value(0);
+               ret = !gpio_get_value(0);
        else
-               *cd = gpio_get_value(6);
+               ret = !gpio_get_value(6);
 
-       return 0;
+       return ret;
 }
 
 int board_mmc_init(bd_t *bis)
index e5a11429f29540688367f92537b423448b99b91a..40b5c1967ff6b344ad0a83bb55ee90f404ff20d5 100644 (file)
@@ -83,19 +83,20 @@ struct fsl_esdhc_cfg esdhc_cfg[2] = {
        {MMC_SDHC2_BASE_ADDR, 1 },
 };
 
-int board_mmc_getcd(u8 *cd, struct mmc *mmc)
+int board_mmc_getcd(struct mmc *mmc)
 {
        struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+       int ret;
 
        mxc_request_iomux(MX53_PIN_GPIO_1, IOMUX_CONFIG_ALT1);
        mxc_request_iomux(MX53_PIN_GPIO_4, IOMUX_CONFIG_ALT1);
 
        if (cfg->esdhc_base == MMC_SDHC1_BASE_ADDR)
-               *cd = gpio_get_value(1); /*GPIO1_1*/
+               ret = !gpio_get_value(1); /* GPIO1_1 */
        else
-               *cd = gpio_get_value(4); /*GPIO1_4*/
+               ret = !gpio_get_value(4); /* GPIO1_4 */
 
-       return 0;
+       return ret;
 }
 
 int board_mmc_init(bd_t *bis)
index aa4a2c93dd0eba6a49ba4673bb54aa820dc1ff42..e976ae1c083d40dd132015a0587a98929dd752ac 100644 (file)
@@ -208,19 +208,20 @@ struct fsl_esdhc_cfg esdhc_cfg[2] = {
        {MMC_SDHC3_BASE_ADDR, 1},
 };
 
-int board_mmc_getcd(u8 *cd, struct mmc *mmc)
+int board_mmc_getcd(struct mmc *mmc)
 {
        struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+       int ret;
 
        mxc_request_iomux(MX53_PIN_EIM_DA11, IOMUX_CONFIG_ALT1);
        mxc_request_iomux(MX53_PIN_EIM_DA13, IOMUX_CONFIG_ALT1);
 
        if (cfg->esdhc_base == MMC_SDHC1_BASE_ADDR)
-               *cd = gpio_get_value(77); /*GPIO3_13*/
+               ret = !gpio_get_value(77); /* GPIO3_13 */
        else
-               *cd = gpio_get_value(75); /*GPIO3_11*/
+               ret = !gpio_get_value(75); /* GPIO3_11 */
 
-       return 0;
+       return ret;
 }
 
 int board_mmc_init(bd_t *bis)
index ea4d3543117f015e9f2b9aed914bfee92ec248da..e6345e7e5c2915500dbcc615d02287dc7169dc13 100644 (file)
@@ -147,19 +147,20 @@ struct fsl_esdhc_cfg esdhc_cfg[2] = {
        {MMC_SDHC3_BASE_ADDR, 1},
 };
 
-int board_mmc_getcd(u8 *cd, struct mmc *mmc)
+int board_mmc_getcd(struct mmc *mmc)
 {
        struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+       int ret;
 
        mxc_request_iomux(MX53_PIN_EIM_DA11, IOMUX_CONFIG_ALT1);
        mxc_request_iomux(MX53_PIN_EIM_DA13, IOMUX_CONFIG_ALT1);
 
        if (cfg->esdhc_base == MMC_SDHC1_BASE_ADDR)
-               *cd = gpio_get_value(77); /*GPIO3_13*/
+               ret = !gpio_get_value(77); /* GPIO3_13 */
        else
-               *cd = gpio_get_value(75); /*GPIO3_11*/
+               ret = !gpio_get_value(75); /* GPIO3_11 */
 
-       return 0;
+       return ret;
 }
 
 int board_mmc_init(bd_t *bis)
index 55af4e480c2e6884e95904f4b2a38cb4356b324b..e273192cac12ff5a1c4524a25cfff9558f78db06 100644 (file)
@@ -132,12 +132,10 @@ struct fsl_esdhc_cfg esdhc_cfg[1] = {
        {MMC_SDHC1_BASE_ADDR, 1},
 };
 
-int board_mmc_getcd(u8 *cd, struct mmc *mmc)
+int board_mmc_getcd(struct mmc *mmc)
 {
        mxc_request_iomux(MX53_PIN_EIM_DA13, IOMUX_CONFIG_ALT1);
-       *cd = gpio_get_value(77); /*GPIO3_13*/
-
-       return 0;
+       return !gpio_get_value(77); /* GPIO3_13 */
 }
 
 int board_mmc_init(bd_t *bis)
index dee0cf0a9b3d0230538b0b5692f9135edf676d7b..0cbd90982943714eff57f8cf74f163726f4b6fda 100644 (file)
@@ -59,17 +59,9 @@ int board_mmc_init(bd_t *bd)
 }
 
 /* this is a weak define that we are overriding */
-int board_mmc_getcd(u8 *cd, struct mmc *mmc)
+int board_mmc_getcd(struct mmc *mmc)
 {
-       /*
-        * the only currently existing use of this function
-        * (fsl_esdhc.c) suggests this function must return
-        * *cs = TRUE if a card is NOT detected -> in most
-        * cases the value of the pin when the detect switch
-        * closes to GND
-        */
-       *cd = at91_get_gpio_value (CONFIG_SYS_MMC_CD_PIN) ? 1 : 0;
-       return 0;
+       return !at91_get_gpio_value(CONFIG_SYS_MMC_CD_PIN);
 }
 
 #endif
index e6467a2d186f3a86cf3f4baec0db5dfcf7905645..09d443ee39bf90df39059a273d63f13e004c8bba 100644 (file)
@@ -385,6 +385,7 @@ static int arm_pl180_mmci_host_init(struct mmc *dev)
        dev->send_cmd = host_request;
        dev->set_ios = host_set_ios;
        dev->init = mmc_host_reset;
+       dev->getcd = NULL;
        dev->host_caps = 0;
        dev->voltages = VOLTAGE_WINDOW_MMC;
        dev->f_min = dev->clock;
index bc9057fa9a5a444c359eb93d34032ec8e19cf384..08fc5c1d3e61d66d4daac74f0b5086917f2ce4a7 100644 (file)
@@ -250,6 +250,7 @@ int bfin_mmc_init(bd_t *bis)
        mmc->send_cmd = bfin_sdh_request;
        mmc->set_ios = bfin_sdh_set_ios;
        mmc->init = bfin_sdh_init;
+       mmc->getcd = NULL;
        mmc->host_caps = MMC_MODE_4BIT;
 
        mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
index ce96736942cc1fc592ad2966b18c17a5a53d4226..ee8f2614de5d152231d30a3ee25c371a78f34ceb 100644 (file)
@@ -387,6 +387,7 @@ int davinci_mmc_init(bd_t *bis, struct davinci_mmc *host)
        mmc->send_cmd = dmmc_send_cmd;
        mmc->set_ios = dmmc_set_ios;
        mmc->init = dmmc_init;
+       mmc->getcd = NULL;
 
        mmc->f_min = 200000;
        mmc->f_max = 25000000;
index ec953f07d7156760b2ca81e5ee6418efdc91b14b..a2f35e3e99159dc0481737a0bb4d1f1e55fc0da6 100644 (file)
@@ -58,7 +58,8 @@ struct fsl_esdhc {
        uint    autoc12err;
        uint    hostcapblt;
        uint    wml;
-       char    reserved1[8];
+       uint    mixctrl;
+       char    reserved1[4];
        uint    fevt;
        char    reserved2[168];
        uint    hostver;
@@ -113,7 +114,8 @@ uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data)
 static void
 esdhc_pio_read_write(struct mmc *mmc, struct mmc_data *data)
 {
-       struct fsl_esdhc *regs = mmc->priv;
+       struct fsl_esdhc_cfg *cfg = mmc->priv;
+       struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
        uint blocks;
        char *buffer;
        uint databuf;
@@ -298,8 +300,13 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 
        /* Send the command */
        esdhc_write32(&regs->cmdarg, cmd->cmdarg);
+#if defined(CONFIG_FSL_USDHC)
+       esdhc_write32(&regs->mixctrl,
+       (esdhc_read32(&regs->mixctrl) & 0xFFFFFF80) | (xfertyp & 0x7F));
+       esdhc_write32(&regs->xfertyp, xfertyp & 0xFFFF0000);
+#else
        esdhc_write32(&regs->xfertyp, xfertyp);
-
+#endif
        /* Wait for the command to complete */
        while (!(esdhc_read32(&regs->irqstat) & IRQSTAT_CC))
                ;
@@ -412,8 +419,6 @@ static int esdhc_init(struct mmc *mmc)
        struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
        struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
        int timeout = 1000;
-       int ret = 0;
-       u8 card_absent;
 
        /* Reset the entire host controller */
        esdhc_write32(&regs->sysctl, SYSCTL_RSTA);
@@ -440,21 +445,19 @@ static int esdhc_init(struct mmc *mmc)
        /* Set timout to the maximum value */
        esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16);
 
-       /* Check if there is a callback for detecting the card */
-       if (board_mmc_getcd(&card_absent, mmc)) {
-               timeout = 1000;
-               while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_CINS) &&
-                               --timeout)
-                       udelay(1000);
+       return 0;
+}
 
-               if (timeout <= 0)
-                       ret = NO_CARD_ERR;
-       } else {
-               if (card_absent)
-                       ret = NO_CARD_ERR;
-       }
+static int esdhc_getcd(struct mmc *mmc)
+{
+       struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+       struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
+       int timeout = 1000;
+
+       while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_CINS) && --timeout)
+               udelay(1000);
 
-       return ret;
+       return timeout > 0;
 }
 
 static void esdhc_reset(struct fsl_esdhc *regs)
@@ -482,7 +485,7 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
 
        mmc = malloc(sizeof(struct mmc));
 
-       sprintf(mmc->name, "FSL_ESDHC");
+       sprintf(mmc->name, "FSL_SDHC");
        regs = (struct fsl_esdhc *)cfg->esdhc_base;
 
        /* First reset the eSDHC controller */
@@ -492,6 +495,7 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
        mmc->send_cmd = esdhc_send_cmd;
        mmc->set_ios = esdhc_set_ios;
        mmc->init = esdhc_init;
+       mmc->getcd = esdhc_getcd;
 
        voltage_caps = 0;
        caps = regs->hostcapblt;
index e38dd87f1892077bb6952dce2eec20a4d3a32d47..f1702fe33bedb560789bcb9afc4c465a531ab259 100644 (file)
@@ -90,8 +90,13 @@ static void ftsdc010_pio_read(struct mmc_host *host, char *buf, unsigned int siz
 
        while (size) {
                status = readl(&host->reg->status);
+               debug("%s: size: %08x\n", __func__, size);
 
                if (status & FTSDC010_STATUS_FIFO_ORUN) {
+
+                       debug("%s: FIFO OVERRUN: sta: %08x\n",
+                                       __func__, status);
+
                        fifo = host->fifo_len > size ?
                                size : host->fifo_len;
 
@@ -146,7 +151,7 @@ static void ftsdc010_pio_write(struct mmc_host *host, const char *buf,
        while (size) {
                status = readl(&host->reg->status);
 
-               if (status & FTSDC010_STATUS_FIFO_ORUN) {
+               if (status & FTSDC010_STATUS_FIFO_URUN) {
                        fifo = host->fifo_len > size ?
                                size : host->fifo_len;
 
@@ -158,7 +163,6 @@ static void ftsdc010_pio_write(struct mmc_host *host, const char *buf,
                                writel(*ptr, &host->reg->dwr);
                                ptr++;
                        }
-
                } else {
                        udelay(1);
                        if (++retry >= FTSDC010_PIO_RETRY) {
@@ -169,56 +173,19 @@ static void ftsdc010_pio_write(struct mmc_host *host, const char *buf,
        }
 }
 
-static int ftsdc010_pio_check_status(struct mmc *mmc, struct mmc_cmd *cmd,
+static int ftsdc010_check_rsp(struct mmc *mmc, struct mmc_cmd *cmd,
                        struct mmc_data *data)
 {
        struct mmc_host *host = mmc->priv;
-
        unsigned int sta, clear;
-       unsigned int i;
-
-       /* check response and hardware status */
-       clear = 0;
-
-       /* chech CMD_SEND */
-       for (i = 0; i < FTSDC010_CMD_RETRY; i++) {
-               sta = readl(&host->reg->status);
-               /* Command Complete */
-               if (sta & FTSDC010_STATUS_CMD_SEND) {
-                       if (!data)
-                               clear |= FTSDC010_CLR_CMD_SEND;
-                       break;
-               }
-       }
-
-       if (i > FTSDC010_CMD_RETRY) {
-               printf("%s: send command timeout\n", __func__);
-               return TIMEOUT;
-       }
-
-       /* debug: print status register and command index*/
-       debug("sta: %08x cmd %d\n", sta, cmd->cmdidx);
 
-       /* handle data FIFO */
-       if ((sta & FTSDC010_STATUS_FIFO_ORUN) ||
-               (sta & FTSDC010_STATUS_FIFO_URUN)) {
-
-               /* Wrong DATA FIFO Flag */
-               if (data == NULL)
-                       printf("%s, data fifo wrong: sta: %08x cmd %d\n",
-                               __func__, sta, cmd->cmdidx);
-
-               if (sta & FTSDC010_STATUS_FIFO_ORUN)
-                       clear |= FTSDC010_STATUS_FIFO_ORUN;
-               if (sta & FTSDC010_STATUS_FIFO_URUN)
-                       clear |= FTSDC010_STATUS_FIFO_URUN;
-       }
+       sta = readl(&host->reg->status);
+       debug("%s: sta: %08x cmd %d\n", __func__, sta, cmd->cmdidx);
 
        /* check RSP TIMEOUT or FAIL */
        if (sta & FTSDC010_STATUS_RSP_TIMEOUT) {
                /* RSP TIMEOUT */
-               debug("%s: RSP timeout: sta: %08x cmd %d\n",
-                               __func__, sta, cmd->cmdidx);
+               debug("%s: RSP timeout: sta: %08x\n", __func__, sta);
 
                clear |= FTSDC010_CLR_RSP_TIMEOUT;
                writel(clear, &host->reg->clr);
@@ -226,47 +193,62 @@ static int ftsdc010_pio_check_status(struct mmc *mmc, struct mmc_cmd *cmd,
                return TIMEOUT;
        } else if (sta & FTSDC010_STATUS_RSP_CRC_FAIL) {
                /* clear response fail bit */
-               debug("%s: RSP CRC FAIL: sta: %08x cmd %d\n",
-                               __func__, sta, cmd->cmdidx);
+               debug("%s: RSP CRC FAIL: sta: %08x\n", __func__, sta);
 
                clear |= FTSDC010_CLR_RSP_CRC_FAIL;
                writel(clear, &host->reg->clr);
 
-               return 0;
+               return COMM_ERR;
        } else if (sta & FTSDC010_STATUS_RSP_CRC_OK) {
 
                /* clear response CRC OK bit */
                clear |= FTSDC010_CLR_RSP_CRC_OK;
        }
 
+       writel(clear, &host->reg->clr);
+       return 0;
+}
+
+static int ftsdc010_check_data(struct mmc *mmc, struct mmc_cmd *cmd,
+                       struct mmc_data *data)
+{
+       struct mmc_host *host = mmc->priv;
+       unsigned int sta, clear;
+
+       sta = readl(&host->reg->status);
+       debug("%s: sta: %08x cmd %d\n", __func__, sta, cmd->cmdidx);
+
        /* check DATA TIMEOUT or FAIL */
        if (data) {
+
+               /* Transfer Complete */
+               if (sta & FTSDC010_STATUS_DATA_END)
+                       clear |= FTSDC010_STATUS_DATA_END;
+
+               /* Data CRC_OK */
+               if (sta & FTSDC010_STATUS_DATA_CRC_OK)
+                       clear |= FTSDC010_STATUS_DATA_CRC_OK;
+
+               /* DATA TIMEOUT or DATA CRC FAIL */
                if (sta & FTSDC010_STATUS_DATA_TIMEOUT) {
                        /* DATA TIMEOUT */
-                       debug("%s: DATA TIMEOUT: sta: %08x\n",
-                                       __func__, sta);
+                       debug("%s: DATA TIMEOUT: sta: %08x\n", __func__, sta);
 
                        clear |= FTSDC010_STATUS_DATA_TIMEOUT;
-                       writel(sta, &host->reg->clr);
+                       writel(clear, &host->reg->clr);
+
                        return TIMEOUT;
                } else if (sta & FTSDC010_STATUS_DATA_CRC_FAIL) {
-                       /* Error Interrupt */
-                       debug("%s: DATA CRC FAIL: sta: %08x\n",
-                                       __func__, sta);
+                       /* DATA CRC FAIL */
+                       debug("%s: DATA CRC FAIL: sta: %08x\n", __func__, sta);
 
                        clear |= FTSDC010_STATUS_DATA_CRC_FAIL;
                        writel(clear, &host->reg->clr);
 
-                       return 0;
-               } else if (sta & FTSDC010_STATUS_DATA_END) {
-                       /* Transfer Complete */
-                       clear |= FTSDC010_STATUS_DATA_END;
+                       return COMM_ERR;
                }
+               writel(clear, &host->reg->clr);
        }
-
-       /* transaction is success and clear status register */
-       writel(clear, &host->reg->clr);
-
        return 0;
 }
 
@@ -281,6 +263,9 @@ static int ftsdc010_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
        unsigned int ccon;
        unsigned int mask, tmpmask;
        unsigned int ret;
+       unsigned int sta, i;
+
+       ret = 0;
 
        if (data)
                mask = FTSDC010_INT_MASK_RSP_TIMEOUT;
@@ -290,13 +275,9 @@ static int ftsdc010_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
                mask = FTSDC010_INT_MASK_CMD_SEND;
 
        /* write argu reg */
-       debug("%s: cmd->arg: %08x\n", __func__, cmd->cmdarg);
+       debug("%s: argu: %08x\n", __func__, host->reg->argu);
        writel(cmd->cmdarg, &host->reg->argu);
 
-       /* setup cmd reg */
-       debug("cmd: %d\n", cmd->cmdidx);
-       debug("resp: %08x\n", cmd->resp_type);
-
        /* setup commnad */
        ccon = FTSDC010_CMD_IDX(cmd->cmdidx);
 
@@ -340,7 +321,51 @@ static int ftsdc010_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
        /* write cmd reg */
        debug("%s: ccon: %08x\n", __func__, ccon);
        writel(ccon, &host->reg->cmd);
-       udelay(4*FTSDC010_DELAY_UNIT);
+
+       /* check CMD_SEND */
+       for (i = 0; i < FTSDC010_CMD_RETRY; i++) {
+               /*
+                * If we read status register too fast
+                * will lead hardware error and the RSP_TIMEOUT
+                * flag will be raised incorrectly.
+                */
+               udelay(16*FTSDC010_DELAY_UNIT);
+               sta = readl(&host->reg->status);
+
+               /* Command Complete */
+               /*
+                * Note:
+                *      Do not clear FTSDC010_CLR_CMD_SEND flag.
+                *      (by writing FTSDC010_CLR_CMD_SEND bit to clear register)
+                *      It will make the driver becomes very slow.
+                *      If the operation hasn't been finished, hardware will
+                *      clear this bit automatically.
+                *      In origin, the driver will clear this flag if there is
+                *      no data need to be read.
+                */
+               if (sta & FTSDC010_STATUS_CMD_SEND)
+                       break;
+       }
+
+       if (i > FTSDC010_CMD_RETRY) {
+               printf("%s: send command timeout\n", __func__);
+               return TIMEOUT;
+       }
+
+       /* check rsp status */
+       ret = ftsdc010_check_rsp(mmc, cmd, data);
+       if (ret)
+               return ret;
+
+       /* read response if we have RSP_OK */
+       if (ccon & FTSDC010_CMD_LONG_RSP) {
+               cmd->response[0] = readl(&host->reg->rsp3);
+               cmd->response[1] = readl(&host->reg->rsp2);
+               cmd->response[2] = readl(&host->reg->rsp1);
+               cmd->response[3] = readl(&host->reg->rsp0);
+       } else {
+               cmd->response[0] = readl(&host->reg->rsp0);
+       }
 
        /* read/write data */
        if (data && (data->flags & MMC_DATA_READ)) {
@@ -351,19 +376,11 @@ static int ftsdc010_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
                                data->blocksize * data->blocks);
        }
 
-       /* pio check response status */
-       ret = ftsdc010_pio_check_status(mmc, cmd, data);
-       if (!ret) {
-               /* if it is long response */
-               if (ccon & FTSDC010_CMD_LONG_RSP) {
-                       cmd->response[0] = readl(&host->reg->rsp3);
-                       cmd->response[1] = readl(&host->reg->rsp2);
-                       cmd->response[2] = readl(&host->reg->rsp1);
-                       cmd->response[3] = readl(&host->reg->rsp0);
-
-               } else {
-                       cmd->response[0] = readl(&host->reg->rsp0);
-               }
+       /* check data status */
+       if (data) {
+               ret = ftsdc010_check_data(mmc, cmd, data);
+               if (ret)
+                       return ret;
        }
 
        udelay(FTSDC010_DELAY_UNIT);
@@ -431,8 +448,6 @@ static int ftsdc010_setup_data(struct mmc *mmc, struct mmc_data *data)
        /* always reset fifo since last transfer may fail */
        dcon |= FTSDC010_DCR_FIFO_RST;
 
-       /* handle sdio */
-       dcon = data->blocksize | data->blocks << 15;
        if (data->blocks > 1)
                dcon |= FTSDC010_SDIO_CTRL1_SDIO_BLK_MODE;
 #endif
@@ -497,7 +512,7 @@ static void ftsdc010_set_clk(struct mmc *mmc)
 {
        struct mmc_host *host = mmc->priv;
        unsigned char clk_div;
-       unsigned char real_rate;
+       unsigned int real_rate;
        unsigned int clock;
 
        debug("%s: mmc_set_clock: %x\n", __func__, mmc->clock);
@@ -518,7 +533,7 @@ static void ftsdc010_set_clk(struct mmc *mmc)
                                break;
                }
 
-               debug("%s: computed real_rete: %x, clk_div: %x\n",
+               debug("%s: computed real_rate: %x, clk_div: %x\n",
                         __func__, real_rate, clk_div);
 
                if (clk_div > 127)
@@ -579,6 +594,7 @@ static void ftsdc010_set_ios(struct mmc *mmc)
 static void ftsdc010_reset(struct mmc_host *host)
 {
        unsigned int timeout;
+       unsigned int sta;
 
        /* Do SDC_RST: Software reset for all register */
        writel(FTSDC010_CMD_SDC_RST, &host->reg->cmd);
@@ -598,6 +614,10 @@ static void ftsdc010_reset(struct mmc_host *host)
                timeout--;
                udelay(10*FTSDC010_DELAY_UNIT);
        }
+
+       sta = readl(&host->reg->status);
+       if (sta & FTSDC010_STATUS_CARD_CHANGE)
+               writel(FTSDC010_CLR_CARD_CHANGE, &host->reg->clr);
 }
 
 static int ftsdc010_core_init(struct mmc *mmc)
@@ -645,13 +665,12 @@ int ftsdc010_mmc_init(int dev_index)
        mmc->send_cmd = ftsdc010_request;
        mmc->set_ios = ftsdc010_set_ios;
        mmc->init = ftsdc010_core_init;
+       mmc->getcd = NULL;
 
        mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
 
        mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
 
-       mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
-
        mmc->f_min = CONFIG_SYS_CLK_FREQ / 2 / (2*128);
        mmc->f_max = CONFIG_SYS_CLK_FREQ / 2 / 2;
 
index f346b244be124e0502a9ec172584f4fccee78c2b..4968c5e4912aa46da6b68884e58fc9edda4375f3 100644 (file)
@@ -337,6 +337,7 @@ int atmel_mci_init(void *regs)
        mmc->send_cmd = mci_send_cmd;
        mmc->set_ios = mci_set_ios;
        mmc->init = mci_init;
+       mmc->getcd = NULL;
 
        /* need to be able to pass these in on a board by board basis */
        mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
index 21665ecc5b9288356becf9f0269494b1748374f3..6db37b1fc548a49be870d06f4737e5b799e6db76 100644 (file)
 static struct list_head mmc_devices;
 static int cur_dev_num = -1;
 
-int __board_mmc_getcd(u8 *cd, struct mmc *mmc) {
+int __board_mmc_getcd(struct mmc *mmc) {
        return -1;
 }
 
-int board_mmc_getcd(u8 *cd, struct mmc *mmc)__attribute__((weak,
+int board_mmc_getcd(struct mmc *mmc)__attribute__((weak,
        alias("__board_mmc_getcd")));
 
 int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
@@ -674,6 +674,18 @@ int mmc_switch_part(int dev_num, unsigned int part_num)
                          | (part_num & PART_ACCESS_MASK));
 }
 
+int mmc_getcd(struct mmc *mmc)
+{
+       int cd;
+
+       cd = board_mmc_getcd(mmc);
+
+       if ((cd < 0) && mmc->getcd)
+               cd = mmc->getcd(mmc);
+
+       return cd;
+}
+
 int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
 {
        struct mmc_cmd cmd;
@@ -785,6 +797,16 @@ retry_scr:
        if (!(__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED))
                return 0;
 
+       /*
+        * If the host doesn't support SD_HIGHSPEED, do not switch card to
+        * HIGHSPEED mode even if the card support SD_HIGHSPPED.
+        * This can avoid furthur problem when the card runs in different
+        * mode between the host.
+        */
+       if (!((mmc->host_caps & MMC_MODE_HS_52MHz) &&
+               (mmc->host_caps & MMC_MODE_HS)))
+               return 0;
+
        err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)switch_status);
 
        if (err)
@@ -1192,6 +1214,12 @@ int mmc_init(struct mmc *mmc)
 {
        int err;
 
+       if (mmc_getcd(mmc) == 0) {
+               mmc->has_init = 0;
+               printf("MMC: no card present\n");
+               return NO_CARD_ERR;
+       }
+
        if (mmc->has_init)
                return 0;
 
index 49fb9e02a91e039837c85729c36e0171407dcf17..de43a85355f4755a4088cbc387740240d8c08ed1 100644 (file)
@@ -272,6 +272,7 @@ struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode)
        mmc->send_cmd = mmc_spi_request;
        mmc->set_ios = mmc_spi_set_ios;
        mmc->init = mmc_spi_init_p;
+       mmc->getcd = NULL;
        mmc->host_caps = MMC_MODE_SPI;
 
        mmc->voltages = MMC_SPI_VOLTAGE;
index 1501974e2f575eb2784dec176335e4b84db2c2bc..2fe34b6993b8a8a006da4d0ae5704e1d1e0f66a7 100644 (file)
@@ -44,8 +44,7 @@ int mv_sdh_init(u32 regbase, u32 max_clk, u32 min_clk, u32 quirks)
        host->quirks = quirks;
 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
        memset(&mv_ops, 0, sizeof(struct sdhci_ops));
-       if (mv_sdhci_writeb != NULL)
-               mv_ops.write_b = mv_sdhci_writeb;
+       mv_ops.write_b = mv_sdhci_writeb;
        host->ops = &mv_ops;
 #endif
        if (quirks & SDHCI_QUIRK_REG32_RW)
index ab1fc82fbb68dd3f0d6f90f55b3be916fd8eac56..8afb22159ab518e5ea3ed9acbba769220523c943 100644 (file)
@@ -500,6 +500,7 @@ static int mxcmci_initialize(bd_t *bis)
        mmc->send_cmd = mxcmci_request;
        mmc->set_ios = mxcmci_set_ios;
        mmc->init = mxcmci_init;
+       mmc->getcd = NULL;
        mmc->host_caps = MMC_MODE_4BIT;
 
        host->base = (struct mxcmci_regs *)CONFIG_MXC_MCI_REGS_BASE;
index 2a9949eb942ef489745a69ea18df55be5a3a1006..5f87a1efd6ce2c29190cc89108c5d7ee16b2bbcb 100644 (file)
@@ -329,6 +329,7 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int))
        mmc->send_cmd = mxsmmc_send_cmd;
        mmc->set_ios = mxsmmc_set_ios;
        mmc->init = mxsmmc_init;
+       mmc->getcd = NULL;
        mmc->priv = priv;
 
        mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
index c38b9e603846d0a224ff4e7ef914c086af5df805..ef64e37411f235dfb9b21ac6c719e1a9f5b07c8c 100644 (file)
@@ -472,6 +472,7 @@ int omap_mmc_init(int dev_index)
        mmc->send_cmd = mmc_send_cmd;
        mmc->set_ios = mmc_set_ios;
        mmc->init = mmc_init_setup;
+       mmc->getcd = NULL;
 
        switch (dev_index) {
        case 0:
index 4a7c67a6bda1cb44482c93e5ad8290672baf09a8..2c5bf17bb3c5b7750e71e0ffa600125ed3218b43 100644 (file)
@@ -411,6 +411,7 @@ int pxa_mmc_register(int card_index)
        mmc->send_cmd   = pxa_mmc_request;
        mmc->set_ios    = pxa_mmc_set_ios;
        mmc->init       = pxa_mmc_init;
+       mmc->getcd      = NULL;
 
        mmc->voltages   = MMC_VDD_32_33 | MMC_VDD_33_34;
        mmc->f_max      = PXAMMC_MAX_SPEED;
index 7786ecf2be87e02ed5727082326f8b15d5632ddf..4ae3aaf7738d8ced7d51dd5500022f39759b88a0 100644 (file)
@@ -463,6 +463,7 @@ static int s5p_mmc_initialize(int dev_index, int bus_width)
        mmc->send_cmd = mmc_send_cmd;
        mmc->set_ios = mmc_set_ios;
        mmc->init = mmc_core_init;
+       mmc->getcd = NULL;
 
        mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
        if (bus_width == 8)
index fce0ef091184b39e07adf8a0acc8c29ab6a2d3dc..fc904b5308eaa855a5a758b56e0f840d9892a608 100644 (file)
@@ -390,6 +390,7 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
        mmc->send_cmd = sdhci_send_command;
        mmc->set_ios = sdhci_set_ios;
        mmc->init = sdhci_init;
+       mmc->getcd = NULL;
 
        caps = sdhci_readl(host, SDHCI_CAPABILITIES);
 #ifdef CONFIG_MMC_SDMA
index 567e2cb61d32ba8b63f574a2ee14c4dff72b989c..2835e242f8943bdaeb763f072e5b75e451d5c712 100644 (file)
@@ -598,6 +598,7 @@ int mmcif_mmc_init(void)
        mmc->send_cmd = sh_mmcif_request;
        mmc->set_ios = sh_mmcif_set_ios;
        mmc->init = sh_mmcif_init;
+       mmc->getcd = NULL;
        host->regs = (struct sh_mmcif_regs *)CONFIG_SH_MMCIF_ADDR;
        host->clk = CONFIG_SH_MMCIF_CLK;
        mmc->priv = host;
index 035a8687df724361098b780fc1d7860f314faabd..5b4c9f69a18fe34b7f0033ce8799225e60045ad4 100644 (file)
@@ -474,6 +474,18 @@ static int mmc_core_init(struct mmc *mmc)
        return 0;
 }
 
+int tegra2_mmc_getcd(struct mmc *mmc)
+{
+       struct mmc_host *host = (struct mmc_host *)mmc->priv;
+
+       debug("tegra2_mmc_getcd called\n");
+
+       if (host->cd_gpio >= 0)
+               return !gpio_get_value(host->cd_gpio);
+
+       return 1;
+}
+
 int tegra2_mmc_init(int dev_index, int bus_width, int pwr_gpio, int cd_gpio)
 {
        struct mmc_host *host;
@@ -512,6 +524,7 @@ int tegra2_mmc_init(int dev_index, int bus_width, int pwr_gpio, int cd_gpio)
        mmc->send_cmd = mmc_send_cmd;
        mmc->set_ios = mmc_set_ios;
        mmc->init = mmc_core_init;
+       mmc->getcd = tegra2_mmc_getcd;
 
        mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
        if (bus_width == 8)
@@ -535,22 +548,3 @@ int tegra2_mmc_init(int dev_index, int bus_width, int pwr_gpio, int cd_gpio)
 
        return 0;
 }
-
-/* this is a weak define that we are overriding */
-int board_mmc_getcd(u8 *cd, struct mmc *mmc)
-{
-       struct mmc_host *host = (struct mmc_host *)mmc->priv;
-
-       debug("board_mmc_getcd called\n");
-
-       *cd = 1; /* Assume card is inserted, or eMMC */
-
-       if (IS_SD(mmc)) {
-               if (host->cd_gpio >= 0) {
-                       if (gpio_get_value(host->cd_gpio))
-                               *cd = 0;
-               }
-       }
-
-       return 0;
-}
index 015a7f36ae91d04da9bcc66ab8029b0deeaf781d..8744604ead1b7db30287d744494e0957c285bbd9 100644 (file)
@@ -302,6 +302,7 @@ struct mmc {
                        struct mmc_cmd *cmd, struct mmc_data *data);
        void (*set_ios)(struct mmc *mmc);
        int (*init)(struct mmc *mmc);
+       int (*getcd)(struct mmc *mmc);
        uint b_max;
 };
 
@@ -314,8 +315,9 @@ struct mmc *find_mmc_device(int dev_num);
 int mmc_set_dev(int dev_num);
 void print_mmc_devices(char separator);
 int get_mmc_num(void);
-int board_mmc_getcd(u8 *cd, struct mmc *mmc);
+int board_mmc_getcd(struct mmc *mmc);
 int mmc_switch_part(int dev_num, unsigned int part_num);
+int mmc_getcd(struct mmc *mmc);
 
 #ifdef CONFIG_GENERIC_MMC
 int atmel_mci_init(void *regs);