- fsl_esdhc sdr104 and hs200 fix and error path fix
- fsl_esdhc workaround 3.3v io issue
- ca_dw_mmc cleanup
- presidio-asic emmc DT update.
This commit is contained in:
Tom Rini 2020-06-15 10:20:35 -04:00
commit bb1ff1371e
6 changed files with 74 additions and 34 deletions

View file

@ -10,11 +10,9 @@
#size-cells = <1>;
mmc0: mmc@f4400000 {
compatible = "snps,dw-cortina";
compatible = "cortina,ca-mmc";
reg = <0x0 0xf4400000 0x1000>;
bus-width = <4>;
io_ds = <0x77>;
fifo-mode;
sd_dll_ctrl = <0xf43200e8>;
io_drv_ctrl = <0xf432004c>;
};

View file

@ -727,6 +727,21 @@ config FSL_ESDHC
This selects support for the eSDHC (Enhanced Secure Digital Host
Controller) found on numerous Freescale/NXP SoCs.
config FSL_ESDHC_33V_IO_RELIABILITY_WORKAROUND
bool "enable eSDHC workaround for 3.3v IO reliability issue"
depends on FSL_ESDHC && DM_MMC
default n
help
When eSDHC operates at 3.3v, damage can accumulate in an internal
level shifter at a higher than expected rate. The faster the interface
runs, the more damage accumulates. This issue now is found on LX2160A
eSDHC1 for only SD card. The hardware workaround is recommended to use
an on-board level shifter that is 1.8v on SoC side and 3.3v on SD card
side. For boards without hardware workaround, this option could be
enabled, ensuring 1.8v IO voltage and disabling eSDHC if no card.
This option assumes no hotplug, and u-boot has to make all the way to
to linux to use 1.8v UHS-I speed mode if has card.
config FSL_ESDHC_IMX
bool "Freescale/NXP i.MX eSDHC controller support"
help

View file

@ -19,6 +19,7 @@
#define SD_CLK_SEL_200MHZ (0x2)
#define SD_CLK_SEL_100MHZ (0x1)
#define SD_CLK_SEL_50MHZ (0x0)
#define IO_DRV_SD_DS_OFFSET (16)
#define IO_DRV_SD_DS_MASK (0xff << IO_DRV_SD_DS_OFFSET)
@ -44,15 +45,11 @@ static void ca_dwmci_clksel(struct dwmci_host *host)
struct ca_dwmmc_priv_data *priv = host->priv;
u32 val = readl(priv->sd_dll_reg);
if (host->bus_hz >= 200000000) {
val &= ~SD_CLK_SEL_MASK;
if (host->bus_hz >= 200000000)
val |= SD_CLK_SEL_200MHZ;
} else if (host->bus_hz >= 100000000) {
val &= ~SD_CLK_SEL_MASK;
else if (host->bus_hz >= 100000000)
val |= SD_CLK_SEL_100MHZ;
} else {
val &= ~SD_CLK_SEL_MASK;
}
writel(val, priv->sd_dll_reg);
}
@ -77,14 +74,14 @@ unsigned int ca_dwmci_get_mmc_clock(struct dwmci_host *host, uint freq)
u8 clk_div;
switch (sd_clk_sel) {
case 2:
clk_div = 1;
case SD_CLK_SEL_50MHZ:
clk_div = 4;
break;
case 1:
case SD_CLK_SEL_100MHZ:
clk_div = 2;
break;
default:
clk_div = 4;
clk_div = 1;
}
return SD_SCLK_MAX / clk_div / (host->div + 1);
@ -100,9 +97,6 @@ static int ca_dwmmc_ofdata_to_platdata(struct udevice *dev)
host->dev_index = 0;
host->buswidth = dev_read_u32_default(dev, "bus-width", 1);
if (host->buswidth != 1 && host->buswidth != 4)
return -EINVAL;
host->bus_hz = dev_read_u32_default(dev, "max-frequency", 50000000);
priv->ds = dev_read_u32_default(dev, "io_ds", 0x33);
host->fifo_mode = dev_read_bool(dev, "fifo-mode");
@ -118,10 +112,8 @@ static int ca_dwmmc_ofdata_to_platdata(struct udevice *dev)
return -EINVAL;
host->ioaddr = dev_read_addr_ptr(dev);
if (host->ioaddr == (void *)FDT_ADDR_T_NONE) {
printf("DWMMC: base address is invalid\n");
if (!host->ioaddr)
return -EINVAL;
}
host->priv = priv;
@ -140,10 +132,8 @@ static int ca_dwmmc_probe(struct udevice *dev)
memcpy(&ca_dwmci_dm_ops, &dm_dwmci_ops, sizeof(struct dm_mmc_ops));
dwmci_setup_cfg(&plat->cfg, host, host->bus_hz, MIN_FREQ);
if (host->buswidth == 1) {
(&plat->cfg)->host_caps &= ~MMC_MODE_8BIT;
(&plat->cfg)->host_caps &= ~MMC_MODE_4BIT;
}
if (host->buswidth == 1)
(&plat->cfg)->host_caps &= ~(MMC_MODE_8BIT | MMC_MODE_4BIT);
host->mmc = &plat->mmc;
host->mmc->priv = &priv->host;
@ -164,7 +154,7 @@ static int ca_dwmmc_bind(struct udevice *dev)
}
static const struct udevice_id ca_dwmmc_ids[] = {
{ .compatible = "snps,dw-cortina" },
{ .compatible = "cortina,ca-mmc" },
{ }
};

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2007, 2010-2011 Freescale Semiconductor, Inc
* Copyright 2019 NXP Semiconductors
* Copyright 2019-2020 NXP
* Andy Fleming
*
* Based vaguely on the pxa mmc code:
@ -630,16 +630,15 @@ static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
static int esdhc_getcd_common(struct fsl_esdhc_priv *priv)
{
struct fsl_esdhc *regs = priv->esdhc_regs;
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);
if (esdhc_read32(&regs->prsstat) & PRSSTAT_CINS)
return 1;
return timeout > 0;
return 0;
}
static void fsl_esdhc_get_cfg_common(struct fsl_esdhc_priv *priv,
@ -724,13 +723,38 @@ __weak int esdhc_status_fixup(void *blob, const char *compat)
return 0;
}
#ifdef CONFIG_FSL_ESDHC_33V_IO_RELIABILITY_WORKAROUND
static int fsl_esdhc_get_cd(struct udevice *dev);
static void esdhc_disable_for_no_card(void *blob)
{
struct udevice *dev;
for (uclass_first_device(UCLASS_MMC, &dev);
dev;
uclass_next_device(&dev)) {
char esdhc_path[50];
if (fsl_esdhc_get_cd(dev))
continue;
snprintf(esdhc_path, sizeof(esdhc_path), "/soc/esdhc@%lx",
(unsigned long)dev_read_addr(dev));
do_fixup_by_path(blob, esdhc_path, "status", "disabled",
sizeof("disabled"), 1);
}
}
#endif
void fdt_fixup_esdhc(void *blob, bd_t *bd)
{
const char *compat = "fsl,esdhc";
if (esdhc_status_fixup(blob, compat))
return;
#ifdef CONFIG_FSL_ESDHC_33V_IO_RELIABILITY_WORKAROUND
esdhc_disable_for_no_card(blob);
#endif
do_fixup_by_compat_u32(blob, compat, "clock-frequency",
gd->arch.sdhc_clk, 1);
}
@ -849,6 +873,7 @@ static int fsl_esdhc_probe(struct udevice *dev)
struct fsl_esdhc_priv *priv = dev_get_priv(dev);
fdt_addr_t addr;
struct mmc *mmc;
int ret;
addr = dev_read_addr(dev);
if (addr == FDT_ADDR_T_NONE)
@ -882,7 +907,15 @@ static int fsl_esdhc_probe(struct udevice *dev)
upriv->mmc = mmc;
return esdhc_init_common(priv, mmc);
ret = esdhc_init_common(priv, mmc);
if (ret)
return ret;
#ifdef CONFIG_FSL_ESDHC_33V_IO_RELIABILITY_WORKAROUND
if (!fsl_esdhc_get_cd(dev))
esdhc_setbits32(&priv->esdhc_regs->proctl, PROCTL_VOLT_SEL);
#endif
return 0;
}
static int fsl_esdhc_get_cd(struct udevice *dev)

View file

@ -791,7 +791,7 @@ static int esdhc_set_voltage(struct mmc *mmc)
switch (mmc->signal_voltage) {
case MMC_SIGNAL_VOLTAGE_330:
if (priv->vs18_enable)
return -EIO;
return -ENOTSUPP;
#if CONFIG_IS_ENABLED(DM_REGULATOR)
if (!IS_ERR_OR_NULL(priv->vqmmc_dev)) {
ret = regulator_set_value(priv->vqmmc_dev, 3300000);
@ -972,6 +972,7 @@ static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
if (priv->signal_voltage != mmc->signal_voltage) {
ret = esdhc_set_voltage(mmc);
if (ret) {
if (ret != -ENOTSUPP)
printf("esdhc_set_voltage error %d\n", ret);
return ret;
}
@ -1455,6 +1456,7 @@ static int fsl_esdhc_probe(struct udevice *dev)
if (ret) {
dev_dbg(dev, "no vqmmc-supply\n");
} else {
priv->vqmmc_dev = vqmmc_dev;
ret = regulator_set_enable(vqmmc_dev, true);
if (ret) {
dev_err(dev, "fail to enable vqmmc-supply\n");

View file

@ -4,6 +4,7 @@
*-------------------------------------------------------------------
*
* Copyright 2007-2008,2010-2011 Freescale Semiconductor, Inc
* Copyright 2020 NXP
*/
#ifndef __FSL_ESDHC_H__
@ -98,6 +99,7 @@
#define PROCTL_DTW_4 0x00000002
#define PROCTL_DTW_8 0x00000004
#define PROCTL_D3CD 0x00000008
#define PROCTL_VOLT_SEL 0x00000400
#define CMDARG 0x0002e008