#include <config.h>
#include <common.h>
#include <command.h>
+#include <errno.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>
uint fevt; /* Force event register */
uint admaes; /* ADMA error status register */
uint adsaddr; /* ADMA system address register */
- char reserved2[100]; /* reserved */
- uint vendorspec; /* Vendor Specific register */
- char reserved3[56]; /* reserved */
+ char reserved2[4];
+ uint dllctrl;
+ uint dllstat;
+ uint clktunectrlstatus;
+ char reserved3[84];
+ uint vendorspec;
+ uint mmcboot;
+ uint vendorspec2;
+ char reserved4[48];
uint hostver; /* Host controller version register */
- char reserved4[4]; /* reserved */
- uint dmaerraddr; /* DMA error address register */
char reserved5[4]; /* reserved */
- uint dmaerrattr; /* DMA error attribute register */
+ uint dmaerraddr; /* DMA error address register */
char reserved6[4]; /* reserved */
+ uint dmaerrattr; /* DMA error attribute register */
+ char reserved7[4]; /* reserved */
uint hostcapblt2; /* Host controller capabilities register 2 */
- char reserved7[8]; /* reserved */
+ char reserved8[8]; /* reserved */
uint tcr; /* Tuning control register */
- char reserved8[28]; /* reserved */
+ char reserved9[28]; /* reserved */
uint sddirctl; /* SD direction control register */
- char reserved9[712]; /* reserved */
+ char reserved10[712];/* reserved */
uint scr; /* eSDHC control register */
};
* Following is used when Driver Model is enabled for MMC
* @dev: pointer for the device
* @non_removable: 0: removable; 1: non-removable
+ * @wp_enable: 1: enable checking wp; 0: no check
* @cd_gpio: gpio for card detection
+ * @wp_gpio: gpio for write protection
*/
struct fsl_esdhc_priv {
struct fsl_esdhc *esdhc_regs;
struct mmc *mmc;
struct udevice *dev;
int non_removable;
+ int wp_enable;
struct gpio_desc cd_gpio;
+ struct gpio_desc wp_gpio;
};
/* Return the XFERTYP flags for a given command and data packet */
int timeout;
struct fsl_esdhc_priv *priv = mmc->priv;
struct fsl_esdhc *regs = priv->esdhc_regs;
-#ifdef CONFIG_FSL_LAYERSCAPE
+#if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234)
dma_addr_t addr;
#endif
uint wml_value;
esdhc_clrsetbits32(®s->wml, WML_RD_WML_MASK, wml_value);
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
-#ifdef CONFIG_FSL_LAYERSCAPE
+#if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234)
addr = virt_to_phys((void *)(data->dest));
if (upper_32_bits(addr))
printf("Error found for upper 32 bits\n");
#endif
if (wml_value > WML_WR_WML_MAX)
wml_value = WML_WR_WML_MAX_VAL;
- if ((esdhc_read32(®s->prsstat) & PRSSTAT_WPSPL) == 0) {
- printf("\nThe SD card is locked. Can not write to a locked card.\n\n");
- return TIMEOUT;
+ if (priv->wp_enable) {
+ if ((esdhc_read32(®s->prsstat) &
+ PRSSTAT_WPSPL) == 0) {
+ printf("\nThe SD card is locked. Can not write to a locked card.\n\n");
+ return -ETIMEDOUT;
+ }
}
esdhc_clrsetbits32(®s->wml, WML_WR_WML_MASK,
wml_value << 16);
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
-#ifdef CONFIG_FSL_LAYERSCAPE
+#if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234)
addr = virt_to_phys((void *)(data->src));
if (upper_32_bits(addr))
printf("Error found for upper 32 bits\n");
unsigned end = 0;
unsigned size = roundup(ARCH_DMA_MINALIGN,
data->blocks*data->blocksize);
-#ifdef CONFIG_FSL_LAYERSCAPE
+#if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234)
dma_addr_t addr;
addr = virt_to_phys((void *)(data->dest));
irqstat = esdhc_read32(®s->irqstat);
if (irqstat & CMD_ERR) {
- err = COMM_ERR;
+ err = -ECOMM;
goto out;
}
if (irqstat & IRQSTAT_CTOE) {
- err = TIMEOUT;
+ err = -ETIMEDOUT;
goto out;
}
if (timeout <= 0) {
printf("Timeout waiting for DAT0 to go high!\n");
- err = TIMEOUT;
+ err = -ETIMEDOUT;
goto out;
}
}
irqstat = esdhc_read32(®s->irqstat);
if (irqstat & IRQSTAT_DTOE) {
- err = TIMEOUT;
+ err = -ETIMEDOUT;
goto out;
}
if (irqstat & DATA_ERR) {
- err = COMM_ERR;
+ err = -ECOMM;
goto out;
}
} while ((irqstat & DATA_COMPLETE) != DATA_COMPLETE);
clk = (pre_div << 8) | (div << 4);
#ifdef CONFIG_FSL_USDHC
- esdhc_setbits32(®s->sysctl, SYSCTL_RSTA);
+ esdhc_clrbits32(®s->vendorspec, VENDORSPEC_CKEN);
#else
esdhc_clrbits32(®s->sysctl, SYSCTL_CKEN);
#endif
udelay(10000);
#ifdef CONFIG_FSL_USDHC
- esdhc_clrbits32(®s->sysctl, SYSCTL_RSTA);
+ esdhc_setbits32(®s->vendorspec, VENDORSPEC_PEREN | VENDORSPEC_CKEN);
#else
esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_CKEN);
#endif
}
#endif
-static void esdhc_set_ios(struct mmc *mmc)
+static int esdhc_set_ios(struct mmc *mmc)
{
struct fsl_esdhc_priv *priv = mmc->priv;
struct fsl_esdhc *regs = priv->esdhc_regs;
else if (mmc->bus_width == 8)
esdhc_setbits32(®s->proctl, PROCTL_DTW_8);
+ return 0;
}
static int esdhc_init(struct mmc *mmc)
while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTA) && --timeout)
udelay(1000);
+#if defined(CONFIG_FSL_USDHC)
+ /* RSTA doesn't reset MMC_BOOT register, so manually reset it */
+ esdhc_write32(®s->mmcboot, 0x0);
+ /* Reset MIX_CTRL and CLK_TUNE_CTRL_STATUS regs to 0 */
+ esdhc_write32(®s->mixctrl, 0x0);
+ esdhc_write32(®s->clktunectrlstatus, 0x0);
+
+ /* Put VEND_SPEC to default value */
+ esdhc_write32(®s->vendorspec, VENDORSPEC_INIT);
+
+ /* Disable DLL_CTRL delay line */
+ esdhc_write32(®s->dllctrl, 0x0);
+#endif
+
#ifndef ARCH_MXC
/* Enable cache snooping */
esdhc_write32(®s->scr, 0x00000040);
#ifndef CONFIG_FSL_USDHC
esdhc_setbits32(®s->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN);
+#else
+ esdhc_setbits32(®s->vendorspec, VENDORSPEC_HCKEN | VENDORSPEC_IPGEN);
#endif
/* Set the initial clock speed */
priv->esdhc_regs = (struct fsl_esdhc *)(unsigned long)(cfg->esdhc_base);
priv->bus_width = cfg->max_bus_width;
priv->sdhc_clk = cfg->sdhc_clk;
+ priv->wp_enable = cfg->wp_enable;
return 0;
};
#ifndef CONFIG_FSL_USDHC
esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN
| SYSCTL_IPGEN | SYSCTL_CKEN);
+#else
+ esdhc_setbits32(®s->vendorspec, VENDORSPEC_PEREN |
+ VENDORSPEC_HCKEN | VENDORSPEC_IPGEN | VENDORSPEC_CKEN);
#endif
writel(SDHCI_IRQ_EN_BITS, ®s->irqstaten);
&priv->cd_gpio, GPIOD_IS_IN);
}
+ priv->wp_enable = 1;
+
+ ret = gpio_request_by_name_nodev(fdt, node, "wp-gpios", 0,
+ &priv->wp_gpio, GPIOD_IS_IN);
+ if (ret)
+ priv->wp_enable = 0;
+
/*
* TODO:
* Because lack of clk driver, if SDHC clk is not enabled,
}
upriv->mmc = priv->mmc;
+ priv->mmc->dev = dev;
return 0;
}