]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - drivers/mmc/fsl_esdhc.c
Unified codebase for TX28, TX48, TX51, TX53
[karo-tx-uboot.git] / drivers / mmc / fsl_esdhc.c
index 8274af561037425e9fd57c0f18c307d7c61b892c..db5278b64d13a4385a129054ecb01d1aa8996ac3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007, Freescale Semiconductor, Inc
+ * Copyright 2007, 2010-2011 Freescale Semiconductor, Inc
  * Andy Fleming
  *
  * Based vaguely on the pxa mmc code:
 #include <config.h>
 #include <common.h>
 #include <command.h>
+#include <hwconfig.h>
 #include <mmc.h>
 #include <part.h>
 #include <malloc.h>
 #include <mmc.h>
 #include <fsl_esdhc.h>
+#include <fdt_support.h>
 #include <asm/io.h>
 
-
 DECLARE_GLOBAL_DATA_PTR;
 
 struct fsl_esdhc {
@@ -57,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;
@@ -71,11 +73,16 @@ uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data)
        uint xfertyp = 0;
 
        if (data) {
-               xfertyp |= XFERTYP_DPSEL | XFERTYP_DMAEN;
-
+               xfertyp |= XFERTYP_DPSEL;
+#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
+               xfertyp |= XFERTYP_DMAEN;
+#endif
                if (data->blocks > 1) {
                        xfertyp |= XFERTYP_MSBSEL;
                        xfertyp |= XFERTYP_BCEN;
+#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
+                       xfertyp |= XFERTYP_AC12EN;
+#endif
                }
 
                if (data->flags & MMC_DATA_READ)
@@ -93,41 +100,152 @@ 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 (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
+               xfertyp |= XFERTYP_CMDTYP_ABORT;
+#endif
        return XFERTYP_CMD(cmd->cmdidx) | xfertyp;
 }
 
+#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
+/*
+ * PIO Read/Write Mode reduce the performace as DMA is not used in this mode.
+ */
+static void
+esdhc_pio_read_write(struct mmc *mmc, struct mmc_data *data)
+{
+       struct fsl_esdhc_cfg *cfg = mmc->priv;
+       struct fsl_esdhc *regs = cfg->esdhc_base;
+       uint blocks;
+       char *buffer;
+       uint databuf;
+       uint size;
+       uint timeout;
+       int wml = esdhc_read32(&regs->wml);
+
+       if (data->flags & MMC_DATA_READ) {
+               wml &= WML_RD_WML_MASK;
+               blocks = data->blocks;
+               buffer = data->dest;
+               while (blocks) {
+                       timeout = PIO_TIMEOUT;
+                       size = data->blocksize;
+                       while (size &&
+                               !(esdhc_read32(&regs->irqstat) & IRQSTAT_TC)) {
+                               int i;
+                               u32 prsstat;
+
+                               while (!((prsstat = esdhc_read32(&regs->prsstat)) &
+                                               PRSSTAT_BREN) && --timeout)
+                                       /* NOP */;
+                               if (!(prsstat & PRSSTAT_BREN)) {
+                                       printf("%s: Data Read Failed in PIO Mode\n",
+                                               __func__);
+                                       return;
+                               }
+                               for (i = 0; i < wml && size; i++) {
+                                       databuf = in_le32(&regs->datport);
+                                       memcpy(buffer, &databuf, sizeof(databuf));
+                                       buffer += 4;
+                                       size -= 4;
+                               }
+                       }
+                       blocks--;
+               }
+       } else {
+               wml = (wml & WML_WR_WML_MASK) >> 16;
+               blocks = data->blocks;
+               buffer = (char *)data->src; /* cast away 'const' */
+               while (blocks) {
+                       timeout = PIO_TIMEOUT;
+                       size = data->blocksize;
+                       while (size &&
+                               !(esdhc_read32(&regs->irqstat) & IRQSTAT_TC)) {
+                               int i;
+                               u32 prsstat;
+
+                               while (!((prsstat = esdhc_read32(&regs->prsstat)) &
+                                               PRSSTAT_BWEN) && --timeout)
+                                       /* NOP */;
+                               if (!(prsstat & PRSSTAT_BWEN)) {
+                                       printf("%s: Data Write Failed in PIO Mode\n",
+                                               __func__);
+                                       return;
+                               }
+                               for (i = 0; i < wml && size; i++) {
+                                       memcpy(&databuf, buffer, sizeof(databuf));
+                                       out_le32(&regs->datport, databuf);
+                                       buffer += 4;
+                                       size -= 4;
+                               }
+                       }
+                       blocks--;
+               }
+       }
+}
+#endif
+
 static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
 {
-       uint wml_value;
        int timeout;
-       struct fsl_esdhc *regs = mmc->priv;
+       struct fsl_esdhc_cfg *cfg = mmc->priv;
+       struct fsl_esdhc *regs = cfg->esdhc_base;
+#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
+       uint wml_value;
 
        wml_value = data->blocksize/4;
 
        if (data->flags & MMC_DATA_READ) {
-               if (wml_value > 0x10)
-                       wml_value = 0x10;
+               if (wml_value > WML_RD_WML_MAX)
+                       wml_value = WML_RD_WML_MAX_VAL;
 
-               wml_value = 0x100000 | wml_value;
-
-               out_be32(&regs->dsaddr, (u32)data->dest);
+               esdhc_clrsetbits32(&regs->wml, WML_RD_WML_MASK, wml_value);
+               esdhc_write32(&regs->dsaddr, (u32)data->dest);
        } else {
-               if (wml_value > 0x80)
-                       wml_value = 0x80;
-               if ((in_be32(&regs->prsstat) & PRSSTAT_WPSPL) == 0) {
+               if (wml_value > WML_WR_WML_MAX)
+                       wml_value = WML_WR_WML_MAX_VAL;
+               if ((esdhc_read32(&regs->prsstat) & PRSSTAT_WPSPL) == 0) {
                        printf("\nThe SD card is locked. Can not write to a locked card.\n\n");
                        return TIMEOUT;
                }
-               wml_value = wml_value << 16 | 0x10;
-               out_be32(&regs->dsaddr, (u32)data->src);
-       }
 
-       out_be32(&regs->wml, wml_value);
+               flush_dcache_range((unsigned long)data->src,
+                               (unsigned long)data->src + data->blocks * data->blocksize);
+               esdhc_clrsetbits32(&regs->wml, WML_WR_WML_MASK,
+                                       wml_value << 16);
+               esdhc_write32(&regs->dsaddr, (u32)data->src);
+       }
+#else  /* CONFIG_SYS_FSL_ESDHC_USE_PIO */
+       if (!(data->flags & MMC_DATA_READ)) {
+               if ((esdhc_read32(&regs->prsstat) & PRSSTAT_WPSPL) == 0) {
+                       printf("\nThe SD card is locked. "
+                               "Can not write to a locked card.\n\n");
+                       return TIMEOUT;
+               }
+               esdhc_write32(&regs->dsaddr, (u32)data->src);
+       } else {
+               esdhc_write32(&regs->dsaddr, (u32)data->dest);
+       }
+#endif /* CONFIG_SYS_FSL_ESDHC_USE_PIO */
 
-       out_be32(&regs->blkattr, data->blocks << 16 | data->blocksize);
+       esdhc_write32(&regs->blkattr, data->blocks << 16 | data->blocksize);
 
        /* Calculate the timeout period for data transactions */
-       timeout = __ilog2(mmc->tran_speed/10);
+       /*
+        * 1)Timeout period = (2^(timeout+13)) SD Clock cycles
+        * 2)Timeout period should be minimum 0.250sec as per SD Card spec
+        *  So, Number of SD Clock cycles for 0.25sec should be minimum
+        *              (SD Clock/sec * 0.25 sec) SD Clock cycles
+        *              = (mmc->tran_speed * 1/4) SD Clock cycles
+        * As 1) >=  2)
+        * => (2^(timeout+13)) >= mmc->tran_speed * 1/4
+        * Taking log2 both the sides
+        * => timeout + 13 >= log2(mmc->tran_speed/4)
+        * Rounding up to next power of 2
+        * => timeout + 13 = log2(mmc->tran_speed/4) + 1
+        * => timeout + 13 = fls(mmc->tran_speed/4)
+        */
+       timeout = fls(mmc->tran_speed/4);
        timeout -= 13;
 
        if (timeout > 14)
@@ -136,7 +254,12 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
        if (timeout < 0)
                timeout = 0;
 
-       clrsetbits_be32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, timeout << 16);
+#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC_A001
+       if ((timeout == 4) || (timeout == 8) || (timeout == 12))
+               timeout++;
+#endif
+
+       esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, timeout << 16);
 
        return 0;
 }
@@ -151,17 +274,25 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 {
        uint    xfertyp;
        uint    irqstat;
-       volatile struct fsl_esdhc *regs = mmc->priv;
+       struct fsl_esdhc_cfg *cfg = mmc->priv;
+       volatile struct fsl_esdhc *regs = cfg->esdhc_base;
 
-       out_be32(&regs->irqstat, -1);
+#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
+       if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
+               return 0;
+#endif
+
+       esdhc_write32(&regs->irqstat, -1);
 
        sync();
 
        /* Wait for the bus to be idle */
-       while ((in_be32(&regs->prsstat) & PRSSTAT_CICHB) ||
-                       (in_be32(&regs->prsstat) & PRSSTAT_CIDHB));
+       while ((esdhc_read32(&regs->prsstat) & PRSSTAT_CICHB) ||
+                       (esdhc_read32(&regs->prsstat) & PRSSTAT_CIDHB))
+               ;
 
-       while (in_be32(&regs->prsstat) & PRSSTAT_DLA);
+       while (esdhc_read32(&regs->prsstat) & PRSSTAT_DLA)
+               ;
 
        /* Wait at least 8 SD clock cycles before the next command */
        /*
@@ -175,7 +306,7 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
                int err;
 
                err = esdhc_setup_data(mmc, data);
-               if(err)
+               if (err)
                        return err;
        }
 
@@ -183,14 +314,20 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
        xfertyp = esdhc_xfertyp(cmd, data);
 
        /* Send the command */
-       out_be32(&regs->cmdarg, cmd->cmdarg);
-       out_be32(&regs->xfertyp, xfertyp);
-
+       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 (!(in_be32(&regs->irqstat) & IRQSTAT_CC));
+       while (!(esdhc_read32(&regs->irqstat) & IRQSTAT_CC))
+               ;
 
-       irqstat = in_be32(&regs->irqstat);
-       out_be32(&regs->irqstat, irqstat);
+       irqstat = esdhc_read32(&regs->irqstat);
+       esdhc_write32(&regs->irqstat, irqstat);
 
        if (irqstat & CMD_ERR)
                return COMM_ERR;
@@ -202,32 +339,38 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
        if (cmd->resp_type & MMC_RSP_136) {
                u32 cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0;
 
-               cmdrsp3 = in_be32(&regs->cmdrsp3);
-               cmdrsp2 = in_be32(&regs->cmdrsp2);
-               cmdrsp1 = in_be32(&regs->cmdrsp1);
-               cmdrsp0 = in_be32(&regs->cmdrsp0);
+               cmdrsp3 = esdhc_read32(&regs->cmdrsp3);
+               cmdrsp2 = esdhc_read32(&regs->cmdrsp2);
+               cmdrsp1 = esdhc_read32(&regs->cmdrsp1);
+               cmdrsp0 = esdhc_read32(&regs->cmdrsp0);
                cmd->response[0] = (cmdrsp3 << 8) | (cmdrsp2 >> 24);
                cmd->response[1] = (cmdrsp2 << 8) | (cmdrsp1 >> 24);
                cmd->response[2] = (cmdrsp1 << 8) | (cmdrsp0 >> 24);
                cmd->response[3] = (cmdrsp0 << 8);
        } else
-               cmd->response[0] = in_be32(&regs->cmdrsp0);
+               cmd->response[0] = esdhc_read32(&regs->cmdrsp0);
 
        /* Wait until all of the blocks are transferred */
        if (data) {
+#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
+               esdhc_pio_read_write(mmc, data);
+#else
                do {
-                       irqstat = in_be32(&regs->irqstat);
-
-                       if (irqstat & DATA_ERR)
-                               return COMM_ERR;
+                       irqstat = esdhc_read32(&regs->irqstat);
 
                        if (irqstat & IRQSTAT_DTOE)
                                return TIMEOUT;
+
+                       if (irqstat & DATA_ERR)
+                               return COMM_ERR;
                } while (!(irqstat & IRQSTAT_TC) &&
-                               (in_be32(&regs->prsstat) & PRSSTAT_DLA));
+                               (esdhc_read32(&regs->prsstat) & PRSSTAT_DLA));
+               invalidate_dcache_range((unsigned long)data->dest,
+                       (unsigned long)data->dest + data->blocks * data->blocksize);
+#endif
        }
 
-       out_be32(&regs->irqstat, -1);
+       esdhc_write32(&regs->irqstat, -1);
 
        return 0;
 }
@@ -236,9 +379,13 @@ void set_sysctl(struct mmc *mmc, uint clock)
 {
        int sdhc_clk = gd->sdhc_clk;
        int div, pre_div;
-       volatile struct fsl_esdhc *regs = mmc->priv;
+       struct fsl_esdhc_cfg *cfg = mmc->priv;
+       volatile struct fsl_esdhc *regs = cfg->esdhc_base;
        uint clk;
 
+       if (clock < mmc->f_min)
+               clock = mmc->f_min;
+
        if (sdhc_clk / 16 > clock) {
                for (pre_div = 2; pre_div < 256; pre_div *= 2)
                        if ((sdhc_clk / pre_div) <= (clock * 16))
@@ -255,79 +402,141 @@ void set_sysctl(struct mmc *mmc, uint clock)
 
        clk = (pre_div << 8) | (div << 4);
 
-       clrsetbits_be32(&regs->sysctl, SYSCTL_CLOCK_MASK, clk);
+       esdhc_clrbits32(&regs->sysctl, SYSCTL_CKEN);
+
+       esdhc_clrsetbits32(&regs->sysctl, SYSCTL_CLOCK_MASK, clk);
 
        udelay(10000);
 
-       setbits_be32(&regs->sysctl, SYSCTL_PEREN);
+       clk = SYSCTL_PEREN | SYSCTL_CKEN;
+
+       esdhc_setbits32(&regs->sysctl, clk);
 }
 
 static void esdhc_set_ios(struct mmc *mmc)
 {
-       struct fsl_esdhc *regs = mmc->priv;
+       struct fsl_esdhc_cfg *cfg = mmc->priv;
+       struct fsl_esdhc *regs = cfg->esdhc_base;
 
        /* Set the clock speed */
        set_sysctl(mmc, mmc->clock);
 
        /* Set the bus width */
-       clrbits_be32(&regs->proctl, PROCTL_DTW_4 | PROCTL_DTW_8);
+       esdhc_clrbits32(&regs->proctl, PROCTL_DTW_4 | PROCTL_DTW_8);
 
        if (mmc->bus_width == 4)
-               setbits_be32(&regs->proctl, PROCTL_DTW_4);
+               esdhc_setbits32(&regs->proctl, PROCTL_DTW_4);
        else if (mmc->bus_width == 8)
-               setbits_be32(&regs->proctl, PROCTL_DTW_8);
+               esdhc_setbits32(&regs->proctl, PROCTL_DTW_8);
+
 }
 
 static int esdhc_init(struct mmc *mmc)
 {
-       struct fsl_esdhc *regs = mmc->priv;
+       struct fsl_esdhc_cfg *cfg = mmc->priv;
+       struct fsl_esdhc *regs = cfg->esdhc_base;
        int timeout = 1000;
 
+       /* Reset the entire host controller */
+       esdhc_write32(&regs->sysctl, SYSCTL_RSTA);
+
+       /* Wait until the controller is available */
+       while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA) && --timeout)
+               udelay(1000);
+
        /* Enable cache snooping */
-       out_be32(&regs->scr, 0x00000040);
+       if (cfg && !cfg->no_snoop)
+               esdhc_write32(&regs->scr, 0x00000040);
 
-       out_be32(&regs->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN);
+       esdhc_write32(&regs->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN);
 
        /* Set the initial clock speed */
-       set_sysctl(mmc, 400000);
+       mmc_set_clock(mmc, 400000);
 
        /* Disable the BRR and BWR bits in IRQSTAT */
-       clrbits_be32(&regs->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR);
+       esdhc_clrbits32(&regs->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR);
 
        /* Put the PROCTL reg back to the default */
-       out_be32(&regs->proctl, PROCTL_INIT);
+       esdhc_write32(&regs->proctl, PROCTL_INIT);
 
-       while (!(in_be32(&regs->prsstat) & PRSSTAT_CINS) && --timeout)
+       /* Set timout to the maximum value */
+       esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16);
+
+       return 0;
+}
+
+static int esdhc_getcd(struct mmc *mmc)
+{
+       struct fsl_esdhc_cfg *cfg = mmc->priv;
+       struct fsl_esdhc *regs = cfg->esdhc_base;
+       int timeout = 1000;
+
+       while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_CINS) && --timeout)
                udelay(1000);
 
-       if (timeout <= 0)
-               return NO_CARD_ERR;
+       return timeout > 0;
+}
 
-       return 0;
+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);
+
+       /* hardware clears the bit when it is done */
+       while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA) && --timeout)
+               udelay(1000);
+       if (!timeout)
+               printf("MMC/SD: Reset never completed.\n");
 }
 
-static int esdhc_initialize(bd_t *bis)
+int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
 {
-       struct fsl_esdhc *regs = (struct fsl_esdhc *)CONFIG_SYS_FSL_ESDHC_ADDR;
+       struct fsl_esdhc *regs;
        struct mmc *mmc;
-       u32 caps;
+       u32 caps, voltage_caps;
+
+       if (!cfg)
+               return -1;
 
-       mmc = malloc(sizeof(struct mmc));
+       mmc = kzalloc(sizeof(struct mmc), GFP_KERNEL);
 
-       sprintf(mmc->name, "FSL_ESDHC");
-       mmc->priv = regs;
+       sprintf(mmc->name, "FSL_SDHC");
+       regs = cfg->esdhc_base;
+
+       /* First reset the eSDHC controller */
+       esdhc_reset(regs);
+
+       mmc->priv = 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;
 
+#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC135
+       caps = caps & ~(ESDHC_HOSTCAPBLT_SRS |
+                       ESDHC_HOSTCAPBLT_VS18 | ESDHC_HOSTCAPBLT_VS30);
+#endif
        if (caps & ESDHC_HOSTCAPBLT_VS18)
-               mmc->voltages |= MMC_VDD_165_195;
+               voltage_caps |= MMC_VDD_165_195;
        if (caps & ESDHC_HOSTCAPBLT_VS30)
-               mmc->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
+               voltage_caps |= MMC_VDD_29_30 | MMC_VDD_30_31;
        if (caps & ESDHC_HOSTCAPBLT_VS33)
-               mmc->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
+               voltage_caps |= MMC_VDD_32_33 | MMC_VDD_33_34;
+
+#ifdef CONFIG_SYS_SD_VOLTAGE
+       mmc->voltages = CONFIG_SYS_SD_VOLTAGE;
+#else
+       mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+#endif
+       if ((mmc->voltages & voltage_caps) == 0) {
+               printf("voltage not supported by controller\n");
+               return -1;
+       }
 
        mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
 
@@ -335,8 +544,9 @@ static int esdhc_initialize(bd_t *bis)
                mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
 
        mmc->f_min = 400000;
-       mmc->f_max = MIN(gd->sdhc_clk, 50000000);
+       mmc->f_max = MIN(gd->sdhc_clk, 52000000);
 
+       mmc->b_max = 0;
        mmc_register(mmc);
 
        return 0;
@@ -344,5 +554,31 @@ static int esdhc_initialize(bd_t *bis)
 
 int fsl_esdhc_mmc_init(bd_t *bis)
 {
-       return esdhc_initialize(bis);
+       struct fsl_esdhc_cfg *cfg;
+
+       cfg = kzalloc(sizeof(struct fsl_esdhc_cfg), GFP_KERNEL);
+
+       cfg->esdhc_base = (void __iomem *)CONFIG_SYS_FSL_ESDHC_ADDR;
+       return fsl_esdhc_initialize(bis, cfg);
+}
+
+#ifdef CONFIG_OF_LIBFDT
+void fdt_fixup_esdhc(void *blob, bd_t *bd)
+{
+       const char *compat = "fsl,esdhc";
+
+#ifdef CONFIG_FSL_ESDHC_PIN_MUX
+       if (!hwconfig("esdhc")) {
+               do_fixup_by_compat(blob, compat, "status", "disabled",
+                               8 + 1, 1);
+               return;
+       }
+#endif
+
+       do_fixup_by_compat_u32(blob, compat, "clock-frequency",
+                              gd->sdhc_clk, 1);
+
+       do_fixup_by_compat(blob, compat, "status", "okay",
+                          4 + 1, 1);
 }
+#endif