diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/Kconfig | 19 | ||||
-rw-r--r-- | drivers/mmc/Makefile | 1 | ||||
-rw-r--r-- | drivers/mmc/aspeed_sdhci.c | 45 | ||||
-rw-r--r-- | drivers/mmc/fsl_esdhc.c | 3 | ||||
-rw-r--r-- | drivers/mmc/pxa_mmc_gen.c | 531 |
5 files changed, 55 insertions, 544 deletions
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 5a87db6be0..6ff00a7cbd 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -123,6 +123,7 @@ config MMC_IO_VOLTAGE config SPL_MMC_IO_VOLTAGE bool "Support IO voltage configuration in SPL" + depends on SPL_MMC help IO voltage configuration allows selecting the voltage level of the IO lines (not the level of main supply). This is required for UHS @@ -153,6 +154,7 @@ config MMC_HS400_ES_SUPPORT config SPL_MMC_HS400_ES_SUPPORT bool "enable HS400 Enhanced Strobe support in SPL" + depends on SPL_MMC help The HS400 Enhanced Strobe mode is support by some eMMC. The bus frequency is up to 200MHz. This mode does not tune the IO. @@ -166,6 +168,7 @@ config MMC_HS400_SUPPORT config SPL_MMC_HS400_SUPPORT bool "enable HS400 support in SPL" + depends on SPL_MMC select SPL_MMC_HS200_SUPPORT help The HS400 mode is support by some eMMC. The bus frequency is up to @@ -179,6 +182,7 @@ config MMC_HS200_SUPPORT config SPL_MMC_HS200_SUPPORT bool "enable HS200 support in SPL" + depends on SPL_MMC help The HS200 mode is support by some eMMC. The bus frequency is up to 200MHz. This mode requires tuning the IO. @@ -342,14 +346,6 @@ config MVEBU_MMC If unsure, say N. -config PXA_MMC_GENERIC - bool "Support for MMC controllers on PXA" - help - This selects MMC controllers on PXA. - If you are on a PXA architecture, say Y here. - - If unsure, say N. - config MMC_OMAP_HS bool "TI OMAP High Speed Multimedia Card Interface support" select DM_REGULATOR_PBIAS if DM_MMC && DM_REGULATOR @@ -478,7 +474,7 @@ config MMC_SDHCI_ADMA config SPL_MMC_SDHCI_ADMA bool "Support SDHCI ADMA2 in SPL" - depends on MMC_SDHCI + depends on SPL_MMC && MMC_SDHCI select MMC_SDHCI_ADMA_HELPERS help This enables support for the ADMA (Advanced DMA) defined @@ -502,6 +498,7 @@ config MMC_SDHCI_ASPEED depends on ARCH_ASPEED depends on DM_MMC depends on MMC_SDHCI + select MISC help Enables support for the Aspeed SDHCI 2.0 controller present on Aspeed SoCs. This device is compatible with SD 3.0 and/or MMC 4.3 @@ -844,6 +841,10 @@ config SYS_FSL_ESDHC_DEFAULT_BUS_WIDTH depends on FSL_ESDHC default 1 +config ESDHC_DETECT_QUIRK + bool "QIXIS-based eSDHC quirk detection" + depends on FSL_ESDHC && FSL_QIXIS + config FSL_ESDHC_IMX bool "Freescale/NXP i.MX eSDHC controller support" help diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 9627509302..7c4243289c 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -46,7 +46,6 @@ obj-$(CONFIG_MMC_MXS) += mxsmmc.o obj-$(CONFIG_MMC_OCTEONTX) += octeontx_hsmmc.o obj-$(CONFIG_MMC_OWL) += owl_mmc.o obj-$(CONFIG_MMC_PCI) += pci_mmc.o -obj-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o obj-$(CONFIG_$(SPL_TPL_)SUPPORT_EMMC_RPMB) += rpmb.o obj-$(CONFIG_MMC_SANDBOX) += sandbox_mmc.o obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o diff --git a/drivers/mmc/aspeed_sdhci.c b/drivers/mmc/aspeed_sdhci.c index 4537315719..9d79bf58cc 100644 --- a/drivers/mmc/aspeed_sdhci.c +++ b/drivers/mmc/aspeed_sdhci.c @@ -10,6 +10,7 @@ #include <malloc.h> #include <sdhci.h> #include <linux/err.h> +#include <dm/lists.h> struct aspeed_sdhci_plat { struct mmc_config cfg; @@ -26,12 +27,16 @@ static int aspeed_sdhci_probe(struct udevice *dev) int ret; ret = clk_get_by_index(dev, 0, &clk); - if (ret) + if (ret) { + debug("%s: clock get failed %d\n", __func__, ret); return ret; + } ret = clk_enable(&clk); - if (ret) + if (ret) { + debug("%s: clock enable failed %d\n", __func__, ret); goto free; + } host->name = dev->name; host->ioaddr = dev_read_addr_ptr(dev); @@ -39,6 +44,7 @@ static int aspeed_sdhci_probe(struct udevice *dev) max_clk = clk_get_rate(&clk); if (IS_ERR_VALUE(max_clk)) { ret = max_clk; + debug("%s: clock rate get failed %d\n", __func__, ret); goto err; } @@ -89,3 +95,38 @@ U_BOOT_DRIVER(aspeed_sdhci_drv) = { .priv_auto = sizeof(struct sdhci_host), .plat_auto = sizeof(struct aspeed_sdhci_plat), }; + + +static int aspeed_sdc_probe(struct udevice *parent) +{ + struct clk clk; + int ret; + + ret = clk_get_by_index(parent, 0, &clk); + if (ret) { + debug("%s: clock get failed %d\n", __func__, ret); + return ret; + } + + ret = clk_enable(&clk); + if (ret) { + debug("%s: clock enable failed %d\n", __func__, ret); + return ret; + } + + return 0; +} + +static const struct udevice_id aspeed_sdc_ids[] = { + { .compatible = "aspeed,ast2400-sd-controller" }, + { .compatible = "aspeed,ast2500-sd-controller" }, + { .compatible = "aspeed,ast2600-sd-controller" }, + { } +}; + +U_BOOT_DRIVER(aspeed_sdc_drv) = { + .name = "aspeed_sdc", + .id = UCLASS_MISC, + .of_match = aspeed_sdc_ids, + .probe = aspeed_sdc_probe, +}; diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 4e7bfdfaa7..b49a7b425b 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -30,6 +30,7 @@ #include <linux/iopoll.h> #include <linux/dma-mapping.h> #include <sdhci.h> +#include "../../board/freescale/common/qixis.h" DECLARE_GLOBAL_DATA_PTR; @@ -773,7 +774,7 @@ static int esdhc_getcd_common(struct fsl_esdhc_priv *priv) struct fsl_esdhc *regs = priv->esdhc_regs; #ifdef CONFIG_ESDHC_DETECT_QUIRK - if (CONFIG_ESDHC_DETECT_QUIRK) + if (qixis_esdhc_detect_quirk()) return 1; #endif if (esdhc_read32(®s->prsstat) & PRSSTAT_CINS) diff --git a/drivers/mmc/pxa_mmc_gen.c b/drivers/mmc/pxa_mmc_gen.c deleted file mode 100644 index a0e1a76d57..0000000000 --- a/drivers/mmc/pxa_mmc_gen.c +++ /dev/null @@ -1,531 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.com> - * - * Modified to add driver model (DM) support - * Copyright (C) 2019 Marcel Ziswiler <marcel@ziswiler.com> - * - * Loosely based on the old code and Linux's PXA MMC driver - */ - -#include <common.h> -#include <asm/arch/hardware.h> -#include <asm/arch/regs-mmc.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <asm/io.h> -#include <dm.h> -#include <dm/platform_data/pxa_mmc_gen.h> -#include <malloc.h> -#include <mmc.h> - -/* PXAMMC Generic default config for various CPUs */ -#if defined(CONFIG_CPU_PXA27X) -#define PXAMMC_CRC_SKIP -#define PXAMMC_FIFO_SIZE 32 -#define PXAMMC_MIN_SPEED 304000 -#define PXAMMC_MAX_SPEED 19500000 -#define PXAMMC_HOST_CAPS (MMC_MODE_4BIT) -#elif defined(CONFIG_CPU_MONAHANS) -#define PXAMMC_FIFO_SIZE 32 -#define PXAMMC_MIN_SPEED 304000 -#define PXAMMC_MAX_SPEED 26000000 -#define PXAMMC_HOST_CAPS (MMC_MODE_4BIT | MMC_MODE_HS) -#else -#error "This CPU isn't supported by PXA MMC!" -#endif - -#define MMC_STAT_ERRORS \ - (MMC_STAT_RES_CRC_ERROR | MMC_STAT_SPI_READ_ERROR_TOKEN | \ - MMC_STAT_CRC_READ_ERROR | MMC_STAT_TIME_OUT_RESPONSE | \ - MMC_STAT_READ_TIME_OUT | MMC_STAT_CRC_WRITE_ERROR) - -/* 1 millisecond (in wait cycles below it's 100 x 10uS waits) */ -#define PXA_MMC_TIMEOUT 100 - -struct pxa_mmc_priv { - struct pxa_mmc_regs *regs; -}; - -/* Wait for bit to be set */ -static int pxa_mmc_wait(struct mmc *mmc, uint32_t mask) -{ - struct pxa_mmc_priv *priv = mmc->priv; - struct pxa_mmc_regs *regs = priv->regs; - unsigned int timeout = PXA_MMC_TIMEOUT; - - /* Wait for bit to be set */ - while (--timeout) { - if (readl(®s->stat) & mask) - break; - udelay(10); - } - - if (!timeout) - return -ETIMEDOUT; - - return 0; -} - -static int pxa_mmc_stop_clock(struct mmc *mmc) -{ - struct pxa_mmc_priv *priv = mmc->priv; - struct pxa_mmc_regs *regs = priv->regs; - unsigned int timeout = PXA_MMC_TIMEOUT; - - /* If the clock aren't running, exit */ - if (!(readl(®s->stat) & MMC_STAT_CLK_EN)) - return 0; - - /* Tell the controller to turn off the clock */ - writel(MMC_STRPCL_STOP_CLK, ®s->strpcl); - - /* Wait until the clock are off */ - while (--timeout) { - if (!(readl(®s->stat) & MMC_STAT_CLK_EN)) - break; - udelay(10); - } - - /* The clock refused to stop, scream and die a painful death */ - if (!timeout) - return -ETIMEDOUT; - - /* The clock stopped correctly */ - return 0; -} - -static int pxa_mmc_start_cmd(struct mmc *mmc, struct mmc_cmd *cmd, - uint32_t cmdat) -{ - struct pxa_mmc_priv *priv = mmc->priv; - struct pxa_mmc_regs *regs = priv->regs; - int ret; - - /* The card can send a "busy" response */ - if (cmd->resp_type & MMC_RSP_BUSY) - cmdat |= MMC_CMDAT_BUSY; - - /* Inform the controller about response type */ - switch (cmd->resp_type) { - case MMC_RSP_R1: - case MMC_RSP_R1b: - cmdat |= MMC_CMDAT_R1; - break; - case MMC_RSP_R2: - cmdat |= MMC_CMDAT_R2; - break; - case MMC_RSP_R3: - cmdat |= MMC_CMDAT_R3; - break; - default: - break; - } - - /* Load command and it's arguments into the controller */ - writel(cmd->cmdidx, ®s->cmd); - writel(cmd->cmdarg >> 16, ®s->argh); - writel(cmd->cmdarg & 0xffff, ®s->argl); - writel(cmdat, ®s->cmdat); - - /* Start the controller clock and wait until they are started */ - writel(MMC_STRPCL_START_CLK, ®s->strpcl); - - ret = pxa_mmc_wait(mmc, MMC_STAT_CLK_EN); - if (ret) - return ret; - - /* Correct and happy end */ - return 0; -} - -static int pxa_mmc_cmd_done(struct mmc *mmc, struct mmc_cmd *cmd) -{ - struct pxa_mmc_priv *priv = mmc->priv; - struct pxa_mmc_regs *regs = priv->regs; - u32 a, b, c; - int i; - int stat; - - /* Read the controller status */ - stat = readl(®s->stat); - - /* - * Linux says: - * Did I mention this is Sick. We always need to - * discard the upper 8 bits of the first 16-bit word. - */ - a = readl(®s->res) & 0xffff; - for (i = 0; i < 4; i++) { - b = readl(®s->res) & 0xffff; - c = readl(®s->res) & 0xffff; - cmd->response[i] = (a << 24) | (b << 8) | (c >> 8); - a = c; - } - - /* The command response didn't arrive */ - if (stat & MMC_STAT_TIME_OUT_RESPONSE) { - return -ETIMEDOUT; - } else if (stat & MMC_STAT_RES_CRC_ERROR && - cmd->resp_type & MMC_RSP_CRC) { -#ifdef PXAMMC_CRC_SKIP - if (cmd->resp_type & MMC_RSP_136 && - cmd->response[0] & (1 << 31)) - printf("Ignoring CRC, this may be dangerous!\n"); - else -#endif - return -EILSEQ; - } - - /* The command response was successfully read */ - return 0; -} - -static int pxa_mmc_do_read_xfer(struct mmc *mmc, struct mmc_data *data) -{ - struct pxa_mmc_priv *priv = mmc->priv; - struct pxa_mmc_regs *regs = priv->regs; - u32 len; - u32 *buf = (uint32_t *)data->dest; - int size; - int ret; - - len = data->blocks * data->blocksize; - - while (len) { - /* The controller has data ready */ - if (readl(®s->i_reg) & MMC_I_REG_RXFIFO_RD_REQ) { - size = min(len, (uint32_t)PXAMMC_FIFO_SIZE); - len -= size; - size /= 4; - - /* Read data into the buffer */ - while (size--) - *buf++ = readl(®s->rxfifo); - } - - if (readl(®s->stat) & MMC_STAT_ERRORS) - return -EIO; - } - - /* Wait for the transmission-done interrupt */ - ret = pxa_mmc_wait(mmc, MMC_STAT_DATA_TRAN_DONE); - if (ret) - return ret; - - return 0; -} - -static int pxa_mmc_do_write_xfer(struct mmc *mmc, struct mmc_data *data) -{ - struct pxa_mmc_priv *priv = mmc->priv; - struct pxa_mmc_regs *regs = priv->regs; - u32 len; - u32 *buf = (uint32_t *)data->src; - int size; - int ret; - - len = data->blocks * data->blocksize; - - while (len) { - /* The controller is ready to receive data */ - if (readl(®s->i_reg) & MMC_I_REG_TXFIFO_WR_REQ) { - size = min(len, (uint32_t)PXAMMC_FIFO_SIZE); - len -= size; - size /= 4; - - while (size--) - writel(*buf++, ®s->txfifo); - - if (min(len, (uint32_t)PXAMMC_FIFO_SIZE) < 32) - writel(MMC_PRTBUF_BUF_PART_FULL, ®s->prtbuf); - } - - if (readl(®s->stat) & MMC_STAT_ERRORS) - return -EIO; - } - - /* Wait for the transmission-done interrupt */ - ret = pxa_mmc_wait(mmc, MMC_STAT_DATA_TRAN_DONE); - if (ret) - return ret; - - /* Wait until the data are really written to the card */ - ret = pxa_mmc_wait(mmc, MMC_STAT_PRG_DONE); - if (ret) - return ret; - - return 0; -} - -static int pxa_mmc_send_cmd_common(struct pxa_mmc_priv *priv, struct mmc *mmc, - struct mmc_cmd *cmd, struct mmc_data *data) -{ - struct pxa_mmc_regs *regs = priv->regs; - u32 cmdat = 0; - int ret; - - /* Stop the controller */ - ret = pxa_mmc_stop_clock(mmc); - if (ret) - return ret; - - /* If we're doing data transfer, configure the controller accordingly */ - if (data) { - writel(data->blocks, ®s->nob); - writel(data->blocksize, ®s->blklen); - /* This delay can be optimized, but stick with max value */ - writel(0xffff, ®s->rdto); - cmdat |= MMC_CMDAT_DATA_EN; - if (data->flags & MMC_DATA_WRITE) - cmdat |= MMC_CMDAT_WRITE; - } - - /* Run in 4bit mode if the card can do it */ - if (mmc->bus_width == 4) - cmdat |= MMC_CMDAT_SD_4DAT; - - /* Execute the command */ - ret = pxa_mmc_start_cmd(mmc, cmd, cmdat); - if (ret) - return ret; - - /* Wait until the command completes */ - ret = pxa_mmc_wait(mmc, MMC_STAT_END_CMD_RES); - if (ret) - return ret; - - /* Read back the result */ - ret = pxa_mmc_cmd_done(mmc, cmd); - if (ret) - return ret; - - /* In case there was a data transfer scheduled, do it */ - if (data) { - if (data->flags & MMC_DATA_WRITE) - pxa_mmc_do_write_xfer(mmc, data); - else - pxa_mmc_do_read_xfer(mmc, data); - } - - return 0; -} - -static int pxa_mmc_set_ios_common(struct pxa_mmc_priv *priv, struct mmc *mmc) -{ - struct pxa_mmc_regs *regs = priv->regs; - u32 tmp; - u32 pxa_mmc_clock; - - if (!mmc->clock) { - pxa_mmc_stop_clock(mmc); - return 0; - } - - /* PXA3xx can do 26MHz with special settings. */ - if (mmc->clock == 26000000) { - writel(0x7, ®s->clkrt); - return 0; - } - - /* Set clock to the card the usual way. */ - pxa_mmc_clock = 0; - tmp = mmc->cfg->f_max / mmc->clock; - tmp += tmp % 2; - - while (tmp > 1) { - pxa_mmc_clock++; - tmp >>= 1; - } - - writel(pxa_mmc_clock, ®s->clkrt); - - return 0; -} - -static int pxa_mmc_init_common(struct pxa_mmc_priv *priv, struct mmc *mmc) -{ - struct pxa_mmc_regs *regs = priv->regs; - - /* Make sure the clock are stopped */ - pxa_mmc_stop_clock(mmc); - - /* Turn off SPI mode */ - writel(0, ®s->spi); - - /* Set up maximum timeout to wait for command response */ - writel(MMC_RES_TO_MAX_MASK, ®s->resto); - - /* Mask all interrupts */ - writel(~(MMC_I_MASK_TXFIFO_WR_REQ | MMC_I_MASK_RXFIFO_RD_REQ), - ®s->i_mask); - - return 0; -} - -#if !CONFIG_IS_ENABLED(DM_MMC) -static int pxa_mmc_init(struct mmc *mmc) -{ - struct pxa_mmc_priv *priv = mmc->priv; - - return pxa_mmc_init_common(priv, mmc); -} - -static int pxa_mmc_request(struct mmc *mmc, struct mmc_cmd *cmd, - struct mmc_data *data) -{ - struct pxa_mmc_priv *priv = mmc->priv; - - return pxa_mmc_send_cmd_common(priv, mmc, cmd, data); -} - -static int pxa_mmc_set_ios(struct mmc *mmc) -{ - struct pxa_mmc_priv *priv = mmc->priv; - - return pxa_mmc_set_ios_common(priv, mmc); -} - -static const struct mmc_ops pxa_mmc_ops = { - .send_cmd = pxa_mmc_request, - .set_ios = pxa_mmc_set_ios, - .init = pxa_mmc_init, -}; - -static struct mmc_config pxa_mmc_cfg = { - .name = "PXA MMC", - .ops = &pxa_mmc_ops, - .voltages = MMC_VDD_32_33 | MMC_VDD_33_34, - .f_max = PXAMMC_MAX_SPEED, - .f_min = PXAMMC_MIN_SPEED, - .host_caps = PXAMMC_HOST_CAPS, - .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT, -}; - -int pxa_mmc_register(int card_index) -{ - struct mmc *mmc; - struct pxa_mmc_priv *priv; - u32 reg; - int ret = -ENOMEM; - - priv = malloc(sizeof(struct pxa_mmc_priv)); - if (!priv) - goto err0; - - memset(priv, 0, sizeof(*priv)); - - switch (card_index) { - case 0: - priv->regs = (struct pxa_mmc_regs *)MMC0_BASE; - break; - case 1: - priv->regs = (struct pxa_mmc_regs *)MMC1_BASE; - break; - default: - ret = -EINVAL; - printf("PXA MMC: Invalid MMC controller ID (card_index = %d)\n", - card_index); - goto err1; - } - -#ifndef CONFIG_CPU_MONAHANS /* PXA2xx */ - reg = readl(CKEN); - reg |= CKEN12_MMC; - writel(reg, CKEN); -#else /* PXA3xx */ - reg = readl(CKENA); - reg |= CKENA_12_MMC0 | CKENA_13_MMC1; - writel(reg, CKENA); -#endif - - mmc = mmc_create(&pxa_mmc_cfg, priv); - if (!mmc) - goto err1; - - return 0; - -err1: - free(priv); -err0: - return ret; -} -#else /* !CONFIG_IS_ENABLED(DM_MMC) */ -static int pxa_mmc_probe(struct udevice *dev) -{ - struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); - struct pxa_mmc_plat *plat = dev_get_plat(dev); - struct mmc_config *cfg = &plat->cfg; - struct mmc *mmc = &plat->mmc; - struct pxa_mmc_priv *priv = dev_get_priv(dev); - u32 reg; - - upriv->mmc = mmc; - - cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; - cfg->f_max = PXAMMC_MAX_SPEED; - cfg->f_min = PXAMMC_MIN_SPEED; - cfg->host_caps = PXAMMC_HOST_CAPS; - cfg->name = dev->name; - cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; - - mmc->priv = priv; - - priv->regs = plat->base; - -#ifndef CONFIG_CPU_MONAHANS /* PXA2xx */ - reg = readl(CKEN); - reg |= CKEN12_MMC; - writel(reg, CKEN); -#else /* PXA3xx */ - reg = readl(CKENA); - reg |= CKENA_12_MMC0 | CKENA_13_MMC1; - writel(reg, CKENA); -#endif - - return pxa_mmc_init_common(priv, mmc); -} - -static int pxa_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, - struct mmc_data *data) -{ - struct pxa_mmc_plat *plat = dev_get_plat(dev); - struct pxa_mmc_priv *priv = dev_get_priv(dev); - - return pxa_mmc_send_cmd_common(priv, &plat->mmc, cmd, data); -} - -static int pxa_mmc_set_ios(struct udevice *dev) -{ - struct pxa_mmc_plat *plat = dev_get_plat(dev); - struct pxa_mmc_priv *priv = dev_get_priv(dev); - - return pxa_mmc_set_ios_common(priv, &plat->mmc); -} - -static const struct dm_mmc_ops pxa_mmc_ops = { - .get_cd = NULL, - .send_cmd = pxa_mmc_send_cmd, - .set_ios = pxa_mmc_set_ios, -}; - -#if CONFIG_IS_ENABLED(BLK) -static int pxa_mmc_bind(struct udevice *dev) -{ - struct pxa_mmc_plat *plat = dev_get_plat(dev); - - return mmc_bind(dev, &plat->mmc, &plat->cfg); -} -#endif - -U_BOOT_DRIVER(pxa_mmc) = { -#if CONFIG_IS_ENABLED(BLK) - .bind = pxa_mmc_bind, -#endif - .id = UCLASS_MMC, - .name = "pxa_mmc", - .ops = &pxa_mmc_ops, - .priv_auto = sizeof(struct pxa_mmc_priv), - .probe = pxa_mmc_probe, -}; -#endif /* !CONFIG_IS_ENABLED(DM_MMC) */ |