提交 e64ebde1 编写于 作者: T Tom Rini

Merge tag 'mmc-2019-11-5' of https://gitlab.denx.de/u-boot/custodians/u-boot-mmc

- fsl_esdhc driver cleanup
- fsl_esdhc_imx driver improvement and compatible string update
......@@ -25,13 +25,6 @@
DECLARE_GLOBAL_DATA_PTR;
#define SDHCI_IRQ_EN_BITS (IRQSTATEN_CC | IRQSTATEN_TC | \
IRQSTATEN_CINT | \
IRQSTATEN_CTOE | IRQSTATEN_CCE | IRQSTATEN_CEBE | \
IRQSTATEN_CIE | IRQSTATEN_DTOE | IRQSTATEN_DCE | \
IRQSTATEN_DEBE | IRQSTATEN_BRR | IRQSTATEN_BWR | \
IRQSTATEN_DINT)
struct fsl_esdhc {
uint dsaddr; /* SDMA system address register */
uint blkattr; /* Block attributes register */
......@@ -82,8 +75,6 @@ struct fsl_esdhc_plat {
* @mmc: mmc
* 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
*/
......@@ -92,13 +83,10 @@ struct fsl_esdhc_priv {
unsigned int sdhc_clk;
struct clk per_clk;
unsigned int clock;
unsigned int bus_width;
#if !CONFIG_IS_ENABLED(DM_MMC)
struct mmc *mmc;
#endif
struct udevice *dev;
int non_removable;
int wp_enable;
};
/* Return the XFERTYP flags for a given command and data packet */
......@@ -241,12 +229,10 @@ static int esdhc_setup_data(struct fsl_esdhc_priv *priv, struct mmc *mmc,
#endif
if (wml_value > WML_WR_WML_MAX)
wml_value = WML_WR_WML_MAX_VAL;
if (priv->wp_enable) {
if ((esdhc_read32(&regs->prsstat) &
PRSSTAT_WPSPL) == 0) {
printf("\nThe SD card is locked. Can not write to a locked card.\n\n");
return -ETIMEDOUT;
}
if (!(esdhc_read32(&regs->prsstat) & PRSSTAT_WPSPL)) {
printf("Can not write to locked SD card.\n");
return -EINVAL;
}
esdhc_clrsetbits32(&regs->wml, WML_WR_WML_MASK,
......@@ -636,236 +622,42 @@ static int esdhc_getcd_common(struct fsl_esdhc_priv *priv)
if (CONFIG_ESDHC_DETECT_QUIRK)
return 1;
#endif
#if CONFIG_IS_ENABLED(DM_MMC)
if (priv->non_removable)
return 1;
#endif
while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_CINS) && --timeout)
udelay(1000);
return timeout > 0;
}
static int esdhc_reset(struct fsl_esdhc *regs)
{
ulong start;
/* reset the controller */
esdhc_setbits32(&regs->sysctl, SYSCTL_RSTA);
/* hardware clears the bit when it is done */
start = get_timer(0);
while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA)) {
if (get_timer(start) > 100) {
printf("MMC/SD: Reset never completed.\n");
return -ETIMEDOUT;
}
}
return 0;
}
#if !CONFIG_IS_ENABLED(DM_MMC)
static int esdhc_getcd(struct mmc *mmc)
{
struct fsl_esdhc_priv *priv = mmc->priv;
return esdhc_getcd_common(priv);
}
static int esdhc_init(struct mmc *mmc)
{
struct fsl_esdhc_priv *priv = mmc->priv;
return esdhc_init_common(priv, mmc);
}
static int esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data)
{
struct fsl_esdhc_priv *priv = mmc->priv;
return esdhc_send_cmd_common(priv, mmc, cmd, data);
}
static int esdhc_set_ios(struct mmc *mmc)
{
struct fsl_esdhc_priv *priv = mmc->priv;
return esdhc_set_ios_common(priv, mmc);
}
static const struct mmc_ops esdhc_ops = {
.getcd = esdhc_getcd,
.init = esdhc_init,
.send_cmd = esdhc_send_cmd,
.set_ios = esdhc_set_ios,
};
#endif
static int fsl_esdhc_init(struct fsl_esdhc_priv *priv,
struct fsl_esdhc_plat *plat)
static void fsl_esdhc_get_cfg_common(struct fsl_esdhc_priv *priv,
struct mmc_config *cfg)
{
struct mmc_config *cfg;
struct fsl_esdhc *regs;
u32 caps, voltage_caps;
int ret;
if (!priv)
return -EINVAL;
regs = priv->esdhc_regs;
/* First reset the eSDHC controller */
ret = esdhc_reset(regs);
if (ret)
return ret;
esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN |
SYSCTL_IPGEN | SYSCTL_CKEN);
writel(SDHCI_IRQ_EN_BITS, &regs->irqstaten);
cfg = &plat->cfg;
#ifndef CONFIG_DM_MMC
memset(cfg, '\0', sizeof(*cfg));
#endif
struct fsl_esdhc *regs = priv->esdhc_regs;
u32 caps;
voltage_caps = 0;
caps = esdhc_read32(&regs->hostcapblt);
#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC135
caps = caps & ~(ESDHC_HOSTCAPBLT_SRS |
ESDHC_HOSTCAPBLT_VS18 | ESDHC_HOSTCAPBLT_VS30);
caps &= ~(HOSTCAPBLT_SRS | HOSTCAPBLT_VS18 | 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;
caps |= HOSTCAPBLT_VS33;
#endif
if (caps & ESDHC_HOSTCAPBLT_VS18)
voltage_caps |= MMC_VDD_165_195;
if (caps & ESDHC_HOSTCAPBLT_VS30)
voltage_caps |= MMC_VDD_29_30 | MMC_VDD_30_31;
if (caps & ESDHC_HOSTCAPBLT_VS33)
voltage_caps |= MMC_VDD_32_33 | MMC_VDD_33_34;
if (caps & HOSTCAPBLT_VS18)
cfg->voltages |= MMC_VDD_165_195;
if (caps & HOSTCAPBLT_VS30)
cfg->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
if (caps & HOSTCAPBLT_VS33)
cfg->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
cfg->name = "FSL_SDHC";
#if !CONFIG_IS_ENABLED(DM_MMC)
cfg->ops = &esdhc_ops;
#endif
#ifdef CONFIG_SYS_SD_VOLTAGE
cfg->voltages = CONFIG_SYS_SD_VOLTAGE;
#else
cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
#endif
if ((cfg->voltages & voltage_caps) == 0) {
printf("voltage not supported by controller\n");
return -1;
}
if (priv->bus_width == 8)
cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
else if (priv->bus_width == 4)
cfg->host_caps = MMC_MODE_4BIT;
cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
if (priv->bus_width > 0) {
if (priv->bus_width < 8)
cfg->host_caps &= ~MMC_MODE_8BIT;
if (priv->bus_width < 4)
cfg->host_caps &= ~MMC_MODE_4BIT;
}
if (caps & ESDHC_HOSTCAPBLT_HSS)
if (caps & HOSTCAPBLT_HSS)
cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
#ifdef CONFIG_ESDHC_DETECT_8_BIT_QUIRK
if (CONFIG_ESDHC_DETECT_8_BIT_QUIRK)
cfg->host_caps &= ~MMC_MODE_8BIT;
#endif
cfg->f_min = 400000;
cfg->f_max = min(priv->sdhc_clk, (u32)200000000);
cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
return 0;
}
#if !CONFIG_IS_ENABLED(DM_MMC)
static int fsl_esdhc_cfg_to_priv(struct fsl_esdhc_cfg *cfg,
struct fsl_esdhc_priv *priv)
{
if (!cfg || !priv)
return -EINVAL;
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;
};
int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
{
struct fsl_esdhc_plat *plat;
struct fsl_esdhc_priv *priv;
struct mmc *mmc;
int ret;
if (!cfg)
return -EINVAL;
priv = calloc(sizeof(struct fsl_esdhc_priv), 1);
if (!priv)
return -ENOMEM;
plat = calloc(sizeof(struct fsl_esdhc_plat), 1);
if (!plat) {
free(priv);
return -ENOMEM;
}
ret = fsl_esdhc_cfg_to_priv(cfg, priv);
if (ret) {
debug("%s xlate failure\n", __func__);
free(plat);
free(priv);
return ret;
}
ret = fsl_esdhc_init(priv, plat);
if (ret) {
debug("%s init failure\n", __func__);
free(plat);
free(priv);
return ret;
}
mmc = mmc_create(&plat->cfg, priv);
if (!mmc)
return -EIO;
priv->mmc = mmc;
return 0;
}
int fsl_esdhc_mmc_init(bd_t *bis)
{
struct fsl_esdhc_cfg *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);
}
#endif
#ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
void mmc_adapter_card_type_ident(void)
{
......@@ -939,7 +731,106 @@ void fdt_fixup_esdhc(void *blob, bd_t *bd)
}
#endif
#if CONFIG_IS_ENABLED(DM_MMC)
#if !CONFIG_IS_ENABLED(DM_MMC)
static int esdhc_getcd(struct mmc *mmc)
{
struct fsl_esdhc_priv *priv = mmc->priv;
return esdhc_getcd_common(priv);
}
static int esdhc_init(struct mmc *mmc)
{
struct fsl_esdhc_priv *priv = mmc->priv;
return esdhc_init_common(priv, mmc);
}
static int esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data)
{
struct fsl_esdhc_priv *priv = mmc->priv;
return esdhc_send_cmd_common(priv, mmc, cmd, data);
}
static int esdhc_set_ios(struct mmc *mmc)
{
struct fsl_esdhc_priv *priv = mmc->priv;
return esdhc_set_ios_common(priv, mmc);
}
static const struct mmc_ops esdhc_ops = {
.getcd = esdhc_getcd,
.init = esdhc_init,
.send_cmd = esdhc_send_cmd,
.set_ios = esdhc_set_ios,
};
int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
{
struct fsl_esdhc_plat *plat;
struct fsl_esdhc_priv *priv;
struct mmc_config *mmc_cfg;
struct mmc *mmc;
if (!cfg)
return -EINVAL;
priv = calloc(sizeof(struct fsl_esdhc_priv), 1);
if (!priv)
return -ENOMEM;
plat = calloc(sizeof(struct fsl_esdhc_plat), 1);
if (!plat) {
free(priv);
return -ENOMEM;
}
priv->esdhc_regs = (struct fsl_esdhc *)(unsigned long)(cfg->esdhc_base);
priv->sdhc_clk = cfg->sdhc_clk;
mmc_cfg = &plat->cfg;
if (cfg->max_bus_width == 8) {
mmc_cfg->host_caps |= MMC_MODE_1BIT | MMC_MODE_4BIT |
MMC_MODE_8BIT;
} else if (cfg->max_bus_width == 4) {
mmc_cfg->host_caps |= MMC_MODE_1BIT | MMC_MODE_4BIT;
} else if (cfg->max_bus_width == 1) {
mmc_cfg->host_caps |= MMC_MODE_1BIT;
} else {
mmc_cfg->host_caps |= MMC_MODE_1BIT | MMC_MODE_4BIT |
MMC_MODE_8BIT;
printf("No max bus width provided. Assume 8-bit supported.\n");
}
#ifdef CONFIG_ESDHC_DETECT_8_BIT_QUIRK
if (CONFIG_ESDHC_DETECT_8_BIT_QUIRK)
mmc_cfg->host_caps &= ~MMC_MODE_8BIT;
#endif
mmc_cfg->ops = &esdhc_ops;
fsl_esdhc_get_cfg_common(priv, mmc_cfg);
mmc = mmc_create(mmc_cfg, priv);
if (!mmc)
return -EIO;
priv->mmc = mmc;
return 0;
}
int fsl_esdhc_mmc_init(bd_t *bis)
{
struct fsl_esdhc_cfg *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);
}
#else /* DM_MMC */
#ifndef CONFIG_PPC
#include <asm/arch/clock.h>
#endif
......@@ -949,7 +840,6 @@ static int fsl_esdhc_probe(struct udevice *dev)
struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
struct fsl_esdhc_priv *priv = dev_get_priv(dev);
fdt_addr_t addr;
unsigned int val;
struct mmc *mmc;
int ret;
......@@ -963,22 +853,6 @@ static int fsl_esdhc_probe(struct udevice *dev)
#endif
priv->dev = dev;
val = dev_read_u32_default(dev, "bus-width", -1);
if (val == 8)
priv->bus_width = 8;
else if (val == 4)
priv->bus_width = 4;
else
priv->bus_width = 1;
if (dev_read_bool(dev, "non-removable")) {
priv->non_removable = 1;
} else {
priv->non_removable = 0;
}
priv->wp_enable = 1;
if (IS_ENABLED(CONFIG_CLK)) {
/* Assigned clock already set clock */
ret = clk_get_by_name(dev, "per", &priv->per_clk);
......@@ -1005,11 +879,7 @@ static int fsl_esdhc_probe(struct udevice *dev)
}
}
ret = fsl_esdhc_init(priv, plat);
if (ret) {
dev_err(dev, "fsl_esdhc_init failure\n");
return ret;
}
fsl_esdhc_get_cfg_common(priv, &plat->cfg);
mmc_of_parse(dev, &plat->cfg);
......@@ -1024,8 +894,12 @@ static int fsl_esdhc_probe(struct udevice *dev)
static int fsl_esdhc_get_cd(struct udevice *dev)
{
struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
struct fsl_esdhc_priv *priv = dev_get_priv(dev);
if (plat->cfg.host_caps & MMC_CAP_NONREMOVABLE)
return 1;
return esdhc_getcd_common(priv);
}
......
......@@ -627,9 +627,6 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock)
int sdhc_clk = priv->sdhc_clk;
uint clk;
if (clock < mmc->cfg->f_min)
clock = mmc->cfg->f_min;
while (sdhc_clk / (16 * pre_div * ddr_pre_div) > clock && pre_div < 256)
pre_div *= 2;
......@@ -958,6 +955,7 @@ static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
{
struct fsl_esdhc *regs = priv->esdhc_regs;
int ret __maybe_unused;
u32 clock;
#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
/* Select to use peripheral clock */
......@@ -966,8 +964,12 @@ static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
esdhc_clock_control(priv, true);
#endif
/* Set the clock speed */
if (priv->clock != mmc->clock)
set_sysctl(priv, mmc, mmc->clock);
clock = mmc->clock;
if (clock < mmc->cfg->f_min)
clock = mmc->cfg->f_min;
if (priv->clock != clock)
set_sysctl(priv, mmc, clock);
#ifdef MMC_SUPPORTS_TUNING
if (mmc->clk_disable) {
......@@ -1645,6 +1647,9 @@ static const struct udevice_id fsl_esdhc_ids[] = {
{ .compatible = "fsl,imx7d-usdhc", .data = (ulong)&usdhc_imx7d_data,},
{ .compatible = "fsl,imx7ulp-usdhc", },
{ .compatible = "fsl,imx8qm-usdhc", .data = (ulong)&usdhc_imx8qm_data,},
{ .compatible = "fsl,imx8mm-usdhc", .data = (ulong)&usdhc_imx8qm_data,},
{ .compatible = "fsl,imx8mn-usdhc", .data = (ulong)&usdhc_imx8qm_data,},
{ .compatible = "fsl,imx8mq-usdhc", .data = (ulong)&usdhc_imx8qm_data,},
{ .compatible = "fsl,esdhc", },
{ /* sentinel */ }
};
......
......@@ -156,18 +156,18 @@
#define BLKATTR_SIZE(x) (x & 0x1fff)
#define MAX_BLK_CNT 0x7fff /* so malloc will have enough room with 32M */
#define ESDHC_HOSTCAPBLT_VS18 0x04000000
#define ESDHC_HOSTCAPBLT_VS30 0x02000000
#define ESDHC_HOSTCAPBLT_VS33 0x01000000
#define ESDHC_HOSTCAPBLT_SRS 0x00800000
#define ESDHC_HOSTCAPBLT_DMAS 0x00400000
#define ESDHC_HOSTCAPBLT_HSS 0x00200000
/* Host controller capabilities register */
#define HOSTCAPBLT_VS18 0x04000000
#define HOSTCAPBLT_VS30 0x02000000
#define HOSTCAPBLT_VS33 0x01000000
#define HOSTCAPBLT_SRS 0x00800000
#define HOSTCAPBLT_DMAS 0x00400000
#define HOSTCAPBLT_HSS 0x00200000
struct fsl_esdhc_cfg {
phys_addr_t esdhc_base;
u32 sdhc_clk;
u8 max_bus_width;
int wp_enable;
int vs18_enable; /* Use 1.8V if set to 1 */
struct mmc_config cfg;
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册