]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - drivers/mmc/fsl_esdhc.c
mmc: Split mmc struct, rework mmc initialization (v2)
[people/ms/u-boot.git] / drivers / mmc / fsl_esdhc.c
index f87e647881cce82f2eac37a4fc5a4863072b82e2..d64962652c133a538f7cbc00c584bc6017aba244 100644 (file)
 DECLARE_GLOBAL_DATA_PTR;
 
 struct fsl_esdhc {
-       uint    dsaddr;
-       uint    blkattr;
-       uint    cmdarg;
-       uint    xfertyp;
-       uint    cmdrsp0;
-       uint    cmdrsp1;
-       uint    cmdrsp2;
-       uint    cmdrsp3;
-       uint    datport;
-       uint    prsstat;
-       uint    proctl;
-       uint    sysctl;
-       uint    irqstat;
-       uint    irqstaten;
-       uint    irqsigen;
-       uint    autoc12err;
-       uint    hostcapblt;
-       uint    wml;
-       uint    mixctrl;
-       char    reserved1[4];
-       uint    fevt;
-       char    reserved2[168];
-       uint    hostver;
-       char    reserved3[780];
-       uint    scr;
+       uint    dsaddr;         /* SDMA system address register */
+       uint    blkattr;        /* Block attributes register */
+       uint    cmdarg;         /* Command argument register */
+       uint    xfertyp;        /* Transfer type register */
+       uint    cmdrsp0;        /* Command response 0 register */
+       uint    cmdrsp1;        /* Command response 1 register */
+       uint    cmdrsp2;        /* Command response 2 register */
+       uint    cmdrsp3;        /* Command response 3 register */
+       uint    datport;        /* Buffer data port register */
+       uint    prsstat;        /* Present state register */
+       uint    proctl;         /* Protocol control register */
+       uint    sysctl;         /* System Control Register */
+       uint    irqstat;        /* Interrupt status register */
+       uint    irqstaten;      /* Interrupt status enable register */
+       uint    irqsigen;       /* Interrupt signal enable register */
+       uint    autoc12err;     /* Auto CMD error status register */
+       uint    hostcapblt;     /* Host controller capabilities register */
+       uint    wml;            /* Watermark level register */
+       uint    mixctrl;        /* For USDHC */
+       char    reserved1[4];   /* reserved */
+       uint    fevt;           /* Force event register */
+       uint    admaes;         /* ADMA error status register */
+       uint    adsaddr;        /* ADMA system address register */
+       char    reserved2[160]; /* reserved */
+       uint    hostver;        /* Host controller version register */
+       char    reserved3[4];   /* reserved */
+       uint    dmaerraddr;     /* DMA error address register */
+       char    reserved4[4];   /* reserved */
+       uint    dmaerrattr;     /* DMA error attribute register */
+       char    reserved5[4];   /* reserved */
+       uint    hostcapblt2;    /* Host controller capabilities register 2 */
+       char    reserved6[8];   /* reserved */
+       uint    tcr;            /* Tuning control register */
+       char    reserved7[28];  /* reserved */
+       uint    sddirctl;       /* SD direction control register */
+       char    reserved8[712]; /* reserved */
+       uint    scr;            /* eSDHC control register */
 };
 
 /* Return the XFERTYP flags for a given command and data packet */
@@ -160,7 +172,7 @@ esdhc_pio_read_write(struct mmc *mmc, struct mmc_data *data)
 static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
 {
        int timeout;
-       struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+       struct fsl_esdhc_cfg *cfg = mmc->priv;
        struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
 #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
        uint wml_value;
@@ -255,7 +267,7 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 {
        uint    xfertyp;
        uint    irqstat;
-       struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+       struct fsl_esdhc_cfg *cfg = mmc->priv;
        volatile struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
 
 #ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
@@ -394,13 +406,13 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 static void set_sysctl(struct mmc *mmc, uint clock)
 {
        int div, pre_div;
-       struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+       struct fsl_esdhc_cfg *cfg = mmc->priv;
        volatile struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
        int sdhc_clk = cfg->sdhc_clk;
        uint clk;
 
-       if (clock < mmc->f_min)
-               clock = mmc->f_min;
+       if (clock < mmc->cfg->f_min)
+               clock = mmc->cfg->f_min;
 
        if (sdhc_clk / 16 > clock) {
                for (pre_div = 2; pre_div < 256; pre_div *= 2)
@@ -431,7 +443,7 @@ static void set_sysctl(struct mmc *mmc, uint clock)
 
 static void esdhc_set_ios(struct mmc *mmc)
 {
-       struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+       struct fsl_esdhc_cfg *cfg = mmc->priv;
        struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
 
        /* Set the clock speed */
@@ -449,7 +461,7 @@ static void esdhc_set_ios(struct mmc *mmc)
 
 static int esdhc_init(struct mmc *mmc)
 {
-       struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+       struct fsl_esdhc_cfg *cfg = mmc->priv;
        struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
        int timeout = 1000;
 
@@ -484,10 +496,14 @@ static int esdhc_init(struct mmc *mmc)
 
 static int esdhc_getcd(struct mmc *mmc)
 {
-       struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+       struct fsl_esdhc_cfg *cfg = mmc->priv;
        struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
        int timeout = 1000;
 
+#ifdef CONFIG_ESDHC_DETECT_QUIRK
+       if (CONFIG_ESDHC_DETECT_QUIRK)
+               return 1;
+#endif
        while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_CINS) && --timeout)
                udelay(1000);
 
@@ -508,6 +524,13 @@ static void esdhc_reset(struct fsl_esdhc *regs)
                printf("MMC/SD: Reset never completed.\n");
 }
 
+static const struct mmc_ops esdhc_ops = {
+       .send_cmd       = esdhc_send_cmd,
+       .set_ios        = esdhc_set_ios,
+       .init           = esdhc_init,
+       .getcd          = esdhc_getcd,
+};
+
 int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
 {
        struct fsl_esdhc *regs;
@@ -517,9 +540,6 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
        if (!cfg)
                return -1;
 
-       mmc = malloc(sizeof(struct mmc));
-
-       sprintf(mmc->name, "FSL_SDHC");
        regs = (struct fsl_esdhc *)cfg->esdhc_base;
 
        /* First reset the eSDHC controller */
@@ -528,12 +548,7 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
        esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN
                                | SYSCTL_IPGEN | SYSCTL_CKEN);
 
-       mmc->priv = cfg;
-       mmc->send_cmd = esdhc_send_cmd;
-       mmc->set_ios = esdhc_set_ios;
-       mmc->init = esdhc_init;
-       mmc->getcd = esdhc_getcd;
-       mmc->getwp = NULL;
+       memset(&cfg->cfg, 0, sizeof(cfg->cfg));
 
        voltage_caps = 0;
        caps = regs->hostcapblt;
@@ -542,6 +557,12 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
        caps = caps & ~(ESDHC_HOSTCAPBLT_SRS |
                        ESDHC_HOSTCAPBLT_VS18 | ESDHC_HOSTCAPBLT_VS30);
 #endif
+
+/* T4240 host controller capabilities register should have VS33 bit */
+#ifdef CONFIG_SYS_FSL_MMC_HAS_CAPBLT_VS33
+       caps = caps | ESDHC_HOSTCAPBLT_VS33;
+#endif
+
        if (caps & ESDHC_HOSTCAPBLT_VS18)
                voltage_caps |= MMC_VDD_165_195;
        if (caps & ESDHC_HOSTCAPBLT_VS30)
@@ -549,33 +570,43 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
        if (caps & ESDHC_HOSTCAPBLT_VS33)
                voltage_caps |= MMC_VDD_32_33 | MMC_VDD_33_34;
 
+       cfg->cfg.name = "FSL_SDHC";
+       cfg->cfg.ops = &esdhc_ops;
 #ifdef CONFIG_SYS_SD_VOLTAGE
-       mmc->voltages = CONFIG_SYS_SD_VOLTAGE;
+       cfg->cfg.voltages = CONFIG_SYS_SD_VOLTAGE;
 #else
-       mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+       cfg->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
 #endif
-       if ((mmc->voltages & voltage_caps) == 0) {
+       if ((cfg->cfg.voltages & voltage_caps) == 0) {
                printf("voltage not supported by controller\n");
                return -1;
        }
 
-       mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HC;
+       cfg->cfg.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;
+                       cfg->cfg.host_caps &= ~MMC_MODE_8BIT;
                if (cfg->max_bus_width < 4)
-                       mmc->host_caps &= ~MMC_MODE_4BIT;
+                       cfg->cfg.host_caps &= ~MMC_MODE_4BIT;
        }
 
        if (caps & ESDHC_HOSTCAPBLT_HSS)
-               mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
+               cfg->cfg.host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
 
-       mmc->f_min = 400000;
-       mmc->f_max = MIN(gd->arch.sdhc_clk, 52000000);
+#ifdef CONFIG_ESDHC_DETECT_8_BIT_QUIRK
+       if (CONFIG_ESDHC_DETECT_8_BIT_QUIRK)
+               cfg->cfg.host_caps &= ~MMC_MODE_8BIT;
+#endif
+
+       cfg->cfg.f_min = 400000;
+       cfg->cfg.f_max = MIN(gd->arch.sdhc_clk, 52000000);
 
-       mmc->b_max = 0;
-       mmc_register(mmc);
+       cfg->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
+       mmc = mmc_create(&cfg->cfg, cfg);
+       if (mmc == NULL)
+               return -1;
 
        return 0;
 }