]> git.karo-electronics.de Git - karo-tx-uboot.git/blobdiff - drivers/mmc/fsl_esdhc.c
powerpc/esdhc: Map register for eSDHC Host Controller V3.0
[karo-tx-uboot.git] / drivers / mmc / fsl_esdhc.c
index 54b5363169b5d10f9ac747ab75eef724422a28a0..bd8c539a571c7201af880c4e7bc14267b1f0a6c5 100644 (file)
@@ -6,23 +6,7 @@
  * (C) Copyright 2003
  * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
  *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * 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
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <config.h>
@@ -61,9 +45,21 @@ struct fsl_esdhc {
        uint    mixctrl;
        char    reserved1[4];
        uint    fevt;
-       char    reserved2[168];
+       uint    admaes;
+       uint    adsaddr;
+       char    reserved2[160];
        uint    hostver;
-       char    reserved3[780];
+       char    reserved3[4];
+       uint    dmaerraddr;
+       char    reserved4[4];
+       uint    dmaerrattr;
+       char    reserved5[4];
+       uint    hostcapblt2;
+       char    reserved6[8];
+       uint    tcr;
+       char    reserved7[28];
+       uint    sddirctl;
+       char    reserved8[712];
        uint    scr;
 };
 
@@ -100,7 +96,7 @@ static uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data)
        else if (cmd->resp_type & MMC_RSP_PRESENT)
                xfertyp |= XFERTYP_RSPTYP_48;
 
-#ifdef CONFIG_MX53
+#if defined(CONFIG_MX53) || defined(CONFIG_T4240QDS)
        if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
                xfertyp |= XFERTYP_CMDTYP_ABORT;
 #endif
@@ -310,6 +306,9 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
        /* Figure out the transfer arguments */
        xfertyp = esdhc_xfertyp(cmd, data);
 
+       /* Mask all irqs */
+       esdhc_write32(&regs->irqsigen, 0);
+
        /* Send the command */
        esdhc_write32(&regs->cmdarg, cmd->cmdarg);
 #if defined(CONFIG_FSL_USDHC)
@@ -320,18 +319,11 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
        esdhc_write32(&regs->xfertyp, xfertyp);
 #endif
 
-       /* Mask all irqs */
-       esdhc_write32(&regs->irqsigen, 0);
-
        /* Wait for the command to complete */
        while (!(esdhc_read32(&regs->irqstat) & (IRQSTAT_CC | IRQSTAT_CTOE)))
                ;
 
-       if (data && (data->flags & MMC_DATA_READ))
-               check_and_invalidate_dcache_range(cmd, data);
-
        irqstat = esdhc_read32(&regs->irqstat);
-       esdhc_write32(&regs->irqstat, irqstat);
 
        /* Reset CMD and DATA portions on error */
        if (irqstat & (CMD_ERR | IRQSTAT_CTOE)) {
@@ -400,9 +392,10 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 
                        if (irqstat & DATA_ERR)
                                return COMM_ERR;
-               } while (!(irqstat & IRQSTAT_TC) &&
-                               (esdhc_read32(&regs->prsstat) & PRSSTAT_DLA));
+               } while ((irqstat & DATA_COMPLETE) != DATA_COMPLETE);
 #endif
+               if (data->flags & MMC_DATA_READ)
+                       check_and_invalidate_dcache_range(cmd, data);
        }
 
        esdhc_write32(&regs->irqstat, -1);
@@ -473,7 +466,7 @@ static int esdhc_init(struct mmc *mmc)
        int timeout = 1000;
 
        /* Reset the entire host controller */
-       esdhc_write32(&regs->sysctl, SYSCTL_RSTA);
+       esdhc_setbits32(&regs->sysctl, SYSCTL_RSTA);
 
        /* Wait until the controller is available */
        while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA) && --timeout)
@@ -484,7 +477,7 @@ static int esdhc_init(struct mmc *mmc)
        esdhc_write32(&regs->scr, 0x00000040);
 #endif
 
-       esdhc_write32(&regs->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN);
+       esdhc_setbits32(&regs->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN);
 
        /* Set the initial clock speed */
        mmc_set_clock(mmc, 400000);
@@ -518,7 +511,7 @@ static void esdhc_reset(struct fsl_esdhc *regs)
        unsigned long timeout = 100; /* wait max 100 ms */
 
        /* reset the controller */
-       esdhc_write32(&regs->sysctl, SYSCTL_RSTA);
+       esdhc_setbits32(&regs->sysctl, SYSCTL_RSTA);
 
        /* hardware clears the bit when it is done */
        while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA) && --timeout)
@@ -537,6 +530,8 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
                return -1;
 
        mmc = malloc(sizeof(struct mmc));
+       if (!mmc)
+               return -ENOMEM;
 
        sprintf(mmc->name, "FSL_SDHC");
        regs = (struct fsl_esdhc *)cfg->esdhc_base;
@@ -580,6 +575,13 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
 
        mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HC;
 
+       if (cfg->max_bus_width > 0) {
+               if (cfg->max_bus_width < 8)
+                       mmc->host_caps &= ~MMC_MODE_8BIT;
+               if (cfg->max_bus_width < 4)
+                       mmc->host_caps &= ~MMC_MODE_4BIT;
+       }
+
        if (caps & ESDHC_HOSTCAPBLT_HSS)
                mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
 
@@ -596,8 +598,7 @@ int fsl_esdhc_mmc_init(bd_t *bis)
 {
        struct fsl_esdhc_cfg *cfg;
 
-       cfg = malloc(sizeof(struct fsl_esdhc_cfg));
-       memset(cfg, 0, sizeof(struct fsl_esdhc_cfg));
+       cfg = calloc(sizeof(struct fsl_esdhc_cfg), 1);
        cfg->esdhc_base = CONFIG_SYS_FSL_ESDHC_ADDR;
        cfg->sdhc_clk = gd->arch.sdhc_clk;
        return fsl_esdhc_initialize(bis, cfg);