mirror of
https://github.com/u-boot/u-boot.git
synced 2024-12-11 21:53:29 +08:00
This commit is contained in:
commit
db97266579
@ -20,11 +20,19 @@ config MMC_WRITE
|
||||
|
||||
config MMC_PWRSEQ
|
||||
bool "HW reset support for eMMC"
|
||||
depends on PWRSEQ
|
||||
depends on PWRSEQ && DM_GPIO
|
||||
help
|
||||
Ths select Hardware reset support aka pwrseq-emmc for eMMC
|
||||
This select Hardware reset support aka pwrseq-emmc for eMMC
|
||||
devices.
|
||||
|
||||
config SPL_MMC_PWRSEQ
|
||||
bool "HW reset support for eMMC in SPL"
|
||||
depends on SPL_PWRSEQ && SPL_DM_GPIO
|
||||
default y if MMC_PWRSEQ
|
||||
help
|
||||
This select Hardware reset support aka pwrseq-emmc for eMMC
|
||||
devices in SPL.
|
||||
|
||||
config MMC_BROKEN_CD
|
||||
bool "Poll for broken card detection case"
|
||||
help
|
||||
@ -79,11 +87,12 @@ config MMC_SPI_CRC_ON
|
||||
|
||||
config ARM_PL180_MMCI
|
||||
bool "ARM AMBA Multimedia Card Interface and compatible support"
|
||||
depends on DM_MMC
|
||||
help
|
||||
This selects the ARM(R) AMBA(R) PrimeCell Multimedia Card
|
||||
Interface (PL180, PL181 and compatible) support.
|
||||
If you have an ARM(R) platform with a Multimedia Card slot,
|
||||
say Y or M here.
|
||||
say Y here.
|
||||
|
||||
config MMC_QUIRKS
|
||||
bool "Enable quirks"
|
||||
@ -599,7 +608,7 @@ config MMC_SDHCI_IPROC
|
||||
This selects the iProc SD/MMC controller.
|
||||
|
||||
If you have a Broadcom IPROC platform with SD or MMC devices,
|
||||
say Y or M here.
|
||||
say Y here.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
@ -610,7 +619,7 @@ config MMC_SDHCI_F_SDH30
|
||||
help
|
||||
This selects the Secure Digital Host Controller Interface (SDHCI)
|
||||
Needed by some Fujitsu/Socionext SoC for MMC / SD / SDIO support.
|
||||
If you have a controller with this interface, say Y or M here.
|
||||
If you have a controller with this interface, say Y here.
|
||||
If unsure, say N.
|
||||
|
||||
config MMC_SDHCI_KONA
|
||||
@ -804,7 +813,7 @@ config STM32_SDMMC2
|
||||
help
|
||||
This selects support for the SD/MMC controller on STM32H7 SoCs.
|
||||
If you have a board based on such a SoC and with a SD/MMC slot,
|
||||
say Y or M here.
|
||||
say Y here.
|
||||
|
||||
config FTSDC010
|
||||
bool "Ftsdc010 SD/MMC controller Support"
|
||||
@ -824,7 +833,7 @@ config MMC_MTK
|
||||
depends on OF_CONTROL
|
||||
help
|
||||
This selects the MediaTek(R) Secure digital and Multimedia card Interface.
|
||||
If you have a machine with a integrated SD/MMC card reader, say Y or M here.
|
||||
If you have a machine with a integrated SD/MMC card reader, say Y here.
|
||||
This is needed if support for any SD/SDIO/MMC devices is required.
|
||||
If unsure, say N.
|
||||
|
||||
|
@ -11,7 +11,7 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += mmc_bootdev.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_$(SPL_TPL_)MMC_WRITE) += mmc_write.o
|
||||
obj-$(CONFIG_MMC_PWRSEQ) += mmc-pwrseq.o
|
||||
obj-$(CONFIG_$(SPL_)MMC_PWRSEQ) += mmc-pwrseq.o
|
||||
obj-$(CONFIG_MMC_SDHCI_ADMA_HELPERS) += sdhci-adma.o
|
||||
|
||||
ifndef CONFIG_$(SPL_)BLK
|
||||
|
@ -390,7 +390,7 @@ static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
|
||||
for (itap = 0; itap < ITAP_MAX; itap++) {
|
||||
am654_sdhci_write_itapdly(plat, itap);
|
||||
|
||||
cur_val = !mmc_send_tuning(mmc, opcode, NULL);
|
||||
cur_val = !mmc_send_tuning(mmc, opcode);
|
||||
if (cur_val && !prev_val)
|
||||
pass_window = itap;
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <malloc.h>
|
||||
#include <mmc.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <dm.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm-generic/gpio.h>
|
||||
@ -25,8 +26,6 @@
|
||||
#include "arm_pl180_mmci.h"
|
||||
#include <linux/delay.h>
|
||||
|
||||
#ifdef CONFIG_DM_MMC
|
||||
#include <dm.h>
|
||||
#define MMC_CLOCK_MAX 48000000
|
||||
#define MMC_CLOCK_MIN 400000
|
||||
|
||||
@ -34,7 +33,6 @@ struct arm_pl180_mmc_plat {
|
||||
struct mmc_config cfg;
|
||||
struct mmc mmc;
|
||||
};
|
||||
#endif
|
||||
|
||||
static int wait_for_command_end(struct mmc *dev, struct mmc_cmd *cmd)
|
||||
{
|
||||
@ -358,65 +356,6 @@ static int host_set_ios(struct mmc *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DM_MMC
|
||||
/* MMC uses open drain drivers in the enumeration phase */
|
||||
static int mmc_host_reset(struct mmc *dev)
|
||||
{
|
||||
struct pl180_mmc_host *host = dev->priv;
|
||||
|
||||
writel(host->pwr_init, &host->base->power);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct mmc_ops arm_pl180_mmci_ops = {
|
||||
.send_cmd = host_request,
|
||||
.set_ios = host_set_ios,
|
||||
.init = mmc_host_reset,
|
||||
};
|
||||
|
||||
/*
|
||||
* mmc_host_init - initialize the mmc controller.
|
||||
* Set initial clock and power for mmc slot.
|
||||
* Initialize mmc struct and register with mmc framework.
|
||||
*/
|
||||
|
||||
int arm_pl180_mmci_init(struct pl180_mmc_host *host, struct mmc **mmc)
|
||||
{
|
||||
u32 sdi_u32;
|
||||
|
||||
writel(host->pwr_init, &host->base->power);
|
||||
writel(host->clkdiv_init, &host->base->clock);
|
||||
udelay(CLK_CHANGE_DELAY);
|
||||
|
||||
/* Disable mmc interrupts */
|
||||
sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK;
|
||||
writel(sdi_u32, &host->base->mask0);
|
||||
|
||||
host->cfg.name = host->name;
|
||||
host->cfg.ops = &arm_pl180_mmci_ops;
|
||||
|
||||
/* TODO remove the duplicates */
|
||||
host->cfg.host_caps = host->caps;
|
||||
host->cfg.voltages = host->voltages;
|
||||
host->cfg.f_min = host->clock_min;
|
||||
host->cfg.f_max = host->clock_max;
|
||||
if (host->b_max != 0)
|
||||
host->cfg.b_max = host->b_max;
|
||||
else
|
||||
host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
|
||||
|
||||
*mmc = mmc_create(&host->cfg, host);
|
||||
if (!*mmc)
|
||||
return -1;
|
||||
debug("registered mmc interface number is:%d\n",
|
||||
(*mmc)->block_dev.devnum);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DM_MMC
|
||||
static void arm_pl180_mmc_init(struct pl180_mmc_host *host)
|
||||
{
|
||||
u32 sdi_u32;
|
||||
@ -477,7 +416,7 @@ static int arm_pl180_mmc_probe(struct udevice *dev)
|
||||
host->version2 = true;
|
||||
break;
|
||||
default:
|
||||
host->version2 = true;
|
||||
host->version2 = false; /* ARM variant */
|
||||
}
|
||||
|
||||
gpio_request_by_name(dev, "cd-gpios", 0, &host->cd_gpio, GPIOD_IS_IN);
|
||||
@ -561,4 +500,3 @@ U_BOOT_DRIVER(arm_pl180_mmc) = {
|
||||
.priv_auto = sizeof(struct pl180_mmc_host),
|
||||
.plat_auto = sizeof(struct arm_pl180_mmc_plat),
|
||||
};
|
||||
#endif
|
||||
|
@ -42,7 +42,7 @@ static int cv1800b_execute_tuning(struct mmc *mmc, u8 opcode)
|
||||
for (tap = 0; tap < TUNE_MAX_PHCODE; tap++) {
|
||||
cv1800b_set_tap_delay(host, tap);
|
||||
|
||||
if (mmc_send_tuning(host->mmc, opcode, NULL)) {
|
||||
if (mmc_send_tuning(host->mmc, opcode)) {
|
||||
current_size = 0;
|
||||
} else {
|
||||
current_size++;
|
||||
|
@ -262,8 +262,8 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
|
||||
|
||||
while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) {
|
||||
if (get_timer(start) > timeout) {
|
||||
debug("%s: Timeout on data busy\n", __func__);
|
||||
return -ETIMEDOUT;
|
||||
debug("%s: Timeout on data busy, continue anyway\n", __func__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1123,7 +1123,7 @@ static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode)
|
||||
esdhc_write32(®s->irqstaten, IRQSTATEN_BRR);
|
||||
|
||||
for (i = 0; i < MAX_TUNING_LOOP; i++) {
|
||||
mmc_send_tuning(mmc, opcode, NULL);
|
||||
mmc_send_tuning(mmc, opcode);
|
||||
mdelay(1);
|
||||
|
||||
val = esdhc_read32(®s->autoc12err);
|
||||
|
@ -882,7 +882,7 @@ static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode)
|
||||
esdhc_write32(®s->mixctrl, val);
|
||||
|
||||
/* We are using STD tuning, no need to check return value */
|
||||
mmc_send_tuning(mmc, opcode, NULL);
|
||||
mmc_send_tuning(mmc, opcode);
|
||||
|
||||
ctrl = esdhc_read32(®s->autoc12err);
|
||||
if ((!(ctrl & MIX_CTRL_EXE_TUNE)) &&
|
||||
|
@ -5,15 +5,24 @@
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <dwmmc.h>
|
||||
#include <errno.h>
|
||||
#include <fdtdec.h>
|
||||
#include <malloc.h>
|
||||
#include <reset.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <dm/device_compat.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
enum hi6220_dwmmc_clk_type {
|
||||
HI6220_DWMMC_CLK_BIU,
|
||||
HI6220_DWMMC_CLK_CIU,
|
||||
HI6220_DWMMC_CLK_CNT,
|
||||
};
|
||||
|
||||
struct hi6220_dwmmc_plat {
|
||||
struct mmc_config cfg;
|
||||
struct mmc mmc;
|
||||
@ -21,18 +30,43 @@ struct hi6220_dwmmc_plat {
|
||||
|
||||
struct hi6220_dwmmc_priv_data {
|
||||
struct dwmci_host host;
|
||||
struct clk *clks[HI6220_DWMMC_CLK_CNT];
|
||||
struct reset_ctl_bulk rsts;
|
||||
};
|
||||
|
||||
struct hisi_mmc_data {
|
||||
unsigned int clock;
|
||||
bool use_fifo;
|
||||
u32 fifoth_val;
|
||||
};
|
||||
|
||||
static int hi6220_dwmmc_of_to_plat(struct udevice *dev)
|
||||
{
|
||||
struct hi6220_dwmmc_priv_data *priv = dev_get_priv(dev);
|
||||
struct dwmci_host *host = &priv->host;
|
||||
int ret;
|
||||
|
||||
if (CONFIG_IS_ENABLED(CLK) && CONFIG_IS_ENABLED(DM_RESET)) {
|
||||
priv->clks[HI6220_DWMMC_CLK_BIU] = devm_clk_get(dev, "biu");
|
||||
if (IS_ERR(priv->clks[HI6220_DWMMC_CLK_BIU])) {
|
||||
ret = PTR_ERR(priv->clks[HI6220_DWMMC_CLK_BIU]);
|
||||
dev_err(dev, "Failed to get BIU clock(ret = %d).\n", ret);
|
||||
return log_msg_ret("clk", ret);
|
||||
}
|
||||
|
||||
priv->clks[HI6220_DWMMC_CLK_CIU] = devm_clk_get(dev, "ciu");
|
||||
if (IS_ERR(priv->clks[HI6220_DWMMC_CLK_CIU])) {
|
||||
ret = PTR_ERR(priv->clks[HI6220_DWMMC_CLK_CIU]);
|
||||
dev_err(dev, "Failed to get CIU clock(ret = %d).\n", ret);
|
||||
return log_msg_ret("clk", ret);
|
||||
}
|
||||
|
||||
ret = reset_get_bulk(dev, &priv->rsts);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get resets(ret = %d)", ret);
|
||||
return log_msg_ret("rst", ret);
|
||||
}
|
||||
}
|
||||
host->name = dev->name;
|
||||
host->ioaddr = dev_read_addr_ptr(dev);
|
||||
host->buswidth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
|
||||
@ -56,16 +90,43 @@ static int hi6220_dwmmc_probe(struct udevice *dev)
|
||||
struct hi6220_dwmmc_priv_data *priv = dev_get_priv(dev);
|
||||
struct dwmci_host *host = &priv->host;
|
||||
struct hisi_mmc_data *mmc_data;
|
||||
int ret;
|
||||
|
||||
mmc_data = (struct hisi_mmc_data *)dev_get_driver_data(dev);
|
||||
|
||||
/* Use default bus speed due to absence of clk driver */
|
||||
host->bus_hz = mmc_data->clock;
|
||||
if (CONFIG_IS_ENABLED(CLK) && CONFIG_IS_ENABLED(DM_RESET)) {
|
||||
ret = clk_prepare_enable(priv->clks[HI6220_DWMMC_CLK_BIU]);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable biu clock(ret = %d).\n", ret);
|
||||
return log_msg_ret("clk", ret);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(priv->clks[HI6220_DWMMC_CLK_CIU]);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable ciu clock(ret = %d).\n", ret);
|
||||
return log_msg_ret("clk", ret);
|
||||
}
|
||||
|
||||
ret = reset_deassert_bulk(&priv->rsts);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to deassert resets(ret = %d).\n", ret);
|
||||
return log_msg_ret("rst", ret);
|
||||
}
|
||||
|
||||
host->bus_hz = clk_get_rate(priv->clks[HI6220_DWMMC_CLK_CIU]);
|
||||
if (host->bus_hz <= 0) {
|
||||
dev_err(dev, "Failed to get ciu clock rate(ret = %d).\n", ret);
|
||||
return log_msg_ret("clk", ret);
|
||||
}
|
||||
}
|
||||
dev_dbg(dev, "bus clock rate: %d.\n", host->bus_hz);
|
||||
|
||||
dwmci_setup_cfg(&plat->cfg, host, host->bus_hz, 400000);
|
||||
host->mmc = &plat->mmc;
|
||||
|
||||
host->fifo_mode = mmc_data->use_fifo;
|
||||
host->fifoth_val = mmc_data->fifoth_val;
|
||||
host->mmc->priv = &priv->host;
|
||||
upriv->mmc = host->mmc;
|
||||
host->mmc->dev = dev;
|
||||
@ -95,13 +156,20 @@ static const struct hisi_mmc_data hi6220_mmc_data = {
|
||||
.use_fifo = false,
|
||||
};
|
||||
|
||||
static const struct hisi_mmc_data hi3798mv2x_mmc_data = {
|
||||
.clock = 50000000,
|
||||
.use_fifo = false,
|
||||
// FIFO depth is 256
|
||||
.fifoth_val = MSIZE(4) | RX_WMARK(0x7f) | TX_WMARK(0x80),
|
||||
};
|
||||
|
||||
static const struct udevice_id hi6220_dwmmc_ids[] = {
|
||||
{ .compatible = "hisilicon,hi6220-dw-mshc",
|
||||
.data = (ulong)&hi6220_mmc_data },
|
||||
{ .compatible = "hisilicon,hi3798cv200-dw-mshc",
|
||||
.data = (ulong)&hi6220_mmc_data },
|
||||
{ .compatible = "hisilicon,hi3798mv200-dw-mshc",
|
||||
.data = (ulong)&hi6220_mmc_data },
|
||||
.data = (ulong)&hi3798mv2x_mmc_data },
|
||||
{ .compatible = "hisilicon,hi3660-dw-mshc",
|
||||
.data = (ulong)&hi3660_mmc_data },
|
||||
{ }
|
||||
|
@ -288,7 +288,7 @@ static int meson_mmc_probe(struct udevice *dev)
|
||||
|
||||
mmc_set_clock(mmc, cfg->f_min, MMC_CLK_ENABLE);
|
||||
|
||||
#ifdef CONFIG_MMC_PWRSEQ
|
||||
#if CONFIG_IS_ENABLED(MMC_PWRSEQ)
|
||||
/* Enable power if needed */
|
||||
ret = mmc_pwrseq_get_power(dev, cfg);
|
||||
if (!ret) {
|
||||
|
@ -124,7 +124,13 @@ static int dm_mmc_execute_tuning(struct udevice *dev, uint opcode)
|
||||
|
||||
int mmc_execute_tuning(struct mmc *mmc, uint opcode)
|
||||
{
|
||||
return dm_mmc_execute_tuning(mmc->dev, opcode);
|
||||
int ret;
|
||||
|
||||
mmc->tuning = true;
|
||||
ret = dm_mmc_execute_tuning(mmc->dev, opcode);
|
||||
mmc->tuning = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -494,10 +500,7 @@ static int mmc_blk_probe(struct udevice *dev)
|
||||
if (ret) {
|
||||
debug("Probing %s failed (err=%d)\n", dev->name, ret);
|
||||
|
||||
if (CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) ||
|
||||
CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) ||
|
||||
CONFIG_IS_ENABLED(MMC_HS400_SUPPORT))
|
||||
mmc_deinit(mmc);
|
||||
mmc_deinit(mmc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -505,9 +508,6 @@ static int mmc_blk_probe(struct udevice *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
|
||||
static int mmc_blk_remove(struct udevice *dev)
|
||||
{
|
||||
struct udevice *mmc_dev = dev_get_parent(dev);
|
||||
@ -516,7 +516,6 @@ static int mmc_blk_remove(struct udevice *dev)
|
||||
|
||||
return mmc_deinit(mmc);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct blk_ops mmc_blk_ops = {
|
||||
.read = mmc_bread,
|
||||
@ -532,12 +531,8 @@ U_BOOT_DRIVER(mmc_blk) = {
|
||||
.id = UCLASS_BLK,
|
||||
.ops = &mmc_blk_ops,
|
||||
.probe = mmc_blk_probe,
|
||||
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
|
||||
.remove = mmc_blk_remove,
|
||||
.flags = DM_FLAG_OS_PREPARE,
|
||||
#endif
|
||||
};
|
||||
#endif /* CONFIG_BLK */
|
||||
|
||||
|
@ -360,7 +360,7 @@ static const u8 tuning_blk_pattern_8bit[] = {
|
||||
0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
|
||||
};
|
||||
|
||||
int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error)
|
||||
int mmc_send_tuning(struct mmc *mmc, u32 opcode)
|
||||
{
|
||||
struct mmc_cmd cmd;
|
||||
struct mmc_data data;
|
||||
@ -1570,13 +1570,20 @@ static int sd_read_ssr(struct mmc *mmc)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
/* frequency bases */
|
||||
/* divided by 10 to be nice to platforms without floating point */
|
||||
/*
|
||||
* TRAN_SPEED bits 0:2 encode the frequency unit:
|
||||
* 0 = 100KHz, 1 = 1MHz, 2 = 10MHz, 3 = 100MHz, values 4 - 7 are reserved.
|
||||
* The values in fbase[] are divided by 10 to avoid floats in multiplier[].
|
||||
*/
|
||||
static const int fbase[] = {
|
||||
10000,
|
||||
100000,
|
||||
1000000,
|
||||
10000000,
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
};
|
||||
|
||||
/* Multiplier values for TRAN_SPEED. Multiplied by 10 to be nice
|
||||
@ -2027,9 +2034,9 @@ static int mmc_select_hs400(struct mmc *mmc)
|
||||
mmc_set_clock(mmc, mmc->tran_speed, false);
|
||||
|
||||
/* execute tuning if needed */
|
||||
mmc->hs400_tuning = 1;
|
||||
mmc->hs400_tuning = true;
|
||||
err = mmc_execute_tuning(mmc, MMC_CMD_SEND_TUNING_BLOCK_HS200);
|
||||
mmc->hs400_tuning = 0;
|
||||
mmc->hs400_tuning = false;
|
||||
if (err) {
|
||||
debug("tuning failed\n");
|
||||
return err;
|
||||
@ -2250,6 +2257,16 @@ error:
|
||||
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
#else
|
||||
static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps)
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
|
||||
static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if CONFIG_IS_ENABLED(MMC_TINY)
|
||||
@ -2560,6 +2577,8 @@ static int mmc_startup(struct mmc *mmc)
|
||||
mult = multipliers[((cmd.response[0] >> 3) & 0xf)];
|
||||
|
||||
mmc->legacy_speed = freq * mult;
|
||||
if (!mmc->legacy_speed)
|
||||
log_debug("TRAN_SPEED: reserved value");
|
||||
mmc_select_mode(mmc, MMC_LEGACY);
|
||||
|
||||
mmc->dsr_imp = ((cmd.response[1] >> 12) & 0x1);
|
||||
@ -3010,13 +3029,15 @@ int mmc_init(struct mmc *mmc)
|
||||
return err;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
|
||||
int mmc_deinit(struct mmc *mmc)
|
||||
{
|
||||
u32 caps_filtered;
|
||||
|
||||
if (!CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) &&
|
||||
!CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) &&
|
||||
!CONFIG_IS_ENABLED(MMC_HS400_SUPPORT))
|
||||
return 0;
|
||||
|
||||
if (!mmc->has_init)
|
||||
return 0;
|
||||
|
||||
@ -3034,7 +3055,6 @@ int mmc_deinit(struct mmc *mmc)
|
||||
return mmc_select_mode_and_width(mmc, caps_filtered);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int mmc_set_dsr(struct mmc *mmc, u16 val)
|
||||
{
|
||||
|
@ -1131,7 +1131,7 @@ static int hs400_tune_response(struct udevice *dev, u32 opcode)
|
||||
i << PAD_CMD_TUNE_RX_DLY3_S);
|
||||
|
||||
for (j = 0; j < 3; j++) {
|
||||
mmc_send_tuning(mmc, opcode, &cmd_err);
|
||||
cmd_err = mmc_send_tuning(mmc, opcode);
|
||||
if (!cmd_err) {
|
||||
cmd_delay |= (1 << i);
|
||||
} else {
|
||||
@ -1181,7 +1181,7 @@ static int msdc_tune_response(struct udevice *dev, u32 opcode)
|
||||
i << MSDC_PAD_TUNE_CMDRDLY_S);
|
||||
|
||||
for (j = 0; j < 3; j++) {
|
||||
mmc_send_tuning(mmc, opcode, &cmd_err);
|
||||
cmd_err = mmc_send_tuning(mmc, opcode);
|
||||
if (!cmd_err) {
|
||||
rise_delay |= (1 << i);
|
||||
} else {
|
||||
@ -1203,7 +1203,7 @@ static int msdc_tune_response(struct udevice *dev, u32 opcode)
|
||||
i << MSDC_PAD_TUNE_CMDRDLY_S);
|
||||
|
||||
for (j = 0; j < 3; j++) {
|
||||
mmc_send_tuning(mmc, opcode, &cmd_err);
|
||||
cmd_err = mmc_send_tuning(mmc, opcode);
|
||||
if (!cmd_err) {
|
||||
fall_delay |= (1 << i);
|
||||
} else {
|
||||
@ -1238,7 +1238,7 @@ skip_fall:
|
||||
clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRRDLY_M,
|
||||
i << MSDC_PAD_TUNE_CMDRRDLY_S);
|
||||
|
||||
mmc_send_tuning(mmc, opcode, &cmd_err);
|
||||
cmd_err = mmc_send_tuning(mmc, opcode);
|
||||
if (!cmd_err)
|
||||
internal_delay |= (1 << i);
|
||||
}
|
||||
@ -1264,7 +1264,6 @@ static int msdc_tune_data(struct udevice *dev, u32 opcode)
|
||||
struct msdc_delay_phase final_rise_delay, final_fall_delay = { 0, };
|
||||
u8 final_delay, final_maxlen;
|
||||
void __iomem *tune_reg = &host->base->pad_tune;
|
||||
int cmd_err;
|
||||
int i, ret;
|
||||
|
||||
if (host->dev_comp->pad_tune0)
|
||||
@ -1277,10 +1276,10 @@ static int msdc_tune_data(struct udevice *dev, u32 opcode)
|
||||
clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_DATRRDLY_M,
|
||||
i << MSDC_PAD_TUNE_DATRRDLY_S);
|
||||
|
||||
ret = mmc_send_tuning(mmc, opcode, &cmd_err);
|
||||
ret = mmc_send_tuning(mmc, opcode);
|
||||
if (!ret) {
|
||||
rise_delay |= (1 << i);
|
||||
} else if (cmd_err) {
|
||||
} else {
|
||||
/* in this case, retune response is needed */
|
||||
ret = msdc_tune_response(dev, opcode);
|
||||
if (ret)
|
||||
@ -1300,10 +1299,10 @@ static int msdc_tune_data(struct udevice *dev, u32 opcode)
|
||||
clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_DATRRDLY_M,
|
||||
i << MSDC_PAD_TUNE_DATRRDLY_S);
|
||||
|
||||
ret = mmc_send_tuning(mmc, opcode, &cmd_err);
|
||||
ret = mmc_send_tuning(mmc, opcode);
|
||||
if (!ret) {
|
||||
fall_delay |= (1 << i);
|
||||
} else if (cmd_err) {
|
||||
} else {
|
||||
/* in this case, retune response is needed */
|
||||
ret = msdc_tune_response(dev, opcode);
|
||||
if (ret)
|
||||
@ -1362,7 +1361,7 @@ static int msdc_tune_together(struct udevice *dev, u32 opcode)
|
||||
for (i = 0; i < PAD_DELAY_MAX; i++) {
|
||||
msdc_set_cmd_delay(host, i);
|
||||
msdc_set_data_delay(host, i);
|
||||
ret = mmc_send_tuning(mmc, opcode, NULL);
|
||||
ret = mmc_send_tuning(mmc, opcode);
|
||||
if (!ret)
|
||||
rise_delay |= (1 << i);
|
||||
}
|
||||
@ -1378,7 +1377,7 @@ static int msdc_tune_together(struct udevice *dev, u32 opcode)
|
||||
for (i = 0; i < PAD_DELAY_MAX; i++) {
|
||||
msdc_set_cmd_delay(host, i);
|
||||
msdc_set_data_delay(host, i);
|
||||
ret = mmc_send_tuning(mmc, opcode, NULL);
|
||||
ret = mmc_send_tuning(mmc, opcode);
|
||||
if (!ret)
|
||||
fall_delay |= (1 << i);
|
||||
}
|
||||
|
@ -1653,6 +1653,12 @@ static int octeontx_mmc_test_cmd(struct mmc *mmc, u32 opcode, int *statp)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int octeontx_mmc_send_tuning(struct mmc *mmc, u32 opcode, int *error)
|
||||
{
|
||||
*error = 0;
|
||||
return mmc_send_tuning(mmc, opcode);
|
||||
}
|
||||
|
||||
static int octeontx_mmc_test_get_ext_csd(struct mmc *mmc, u32 opcode,
|
||||
int *statp)
|
||||
{
|
||||
@ -2006,7 +2012,7 @@ struct adj adj[] = {
|
||||
{ "CMD_IN", 48, octeontx_mmc_test_cmd, MMC_CMD_SEND_STATUS,
|
||||
false, false, false, 2, },
|
||||
/* { "CMD_OUT", 32, octeontx_mmc_test_cmd, MMC_CMD_SEND_STATUS, },*/
|
||||
{ "DATA_IN(HS200)", 16, mmc_send_tuning,
|
||||
{ "DATA_IN(HS200)", 16, octeontx_mmc_send_tuning,
|
||||
MMC_CMD_SEND_TUNING_BLOCK_HS200, false, true, false, 2, },
|
||||
{ "DATA_IN", 16, octeontx_mmc_test_get_ext_csd, 0, false, false,
|
||||
true, 2, },
|
||||
|
@ -666,7 +666,7 @@ static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode)
|
||||
while (phase_delay <= MAX_PHASE_DELAY) {
|
||||
omap_hsmmc_set_dll(mmc, phase_delay);
|
||||
|
||||
cur_match = !mmc_send_tuning(mmc, opcode, NULL);
|
||||
cur_match = !mmc_send_tuning(mmc, opcode);
|
||||
|
||||
if (cur_match) {
|
||||
if (prev_match) {
|
||||
@ -731,7 +731,7 @@ static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode)
|
||||
*/
|
||||
for (i = 3; i <= 10; i++) {
|
||||
omap_hsmmc_set_dll(mmc, phase_delay + i);
|
||||
if (mmc_send_tuning(mmc, opcode, NULL)) {
|
||||
if (mmc_send_tuning(mmc, opcode)) {
|
||||
if (temperature < 10000)
|
||||
phase_delay += i + 6;
|
||||
else if (temperature < 20000)
|
||||
@ -749,7 +749,7 @@ static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode)
|
||||
|
||||
for (i = 2; i >= -10; i--) {
|
||||
omap_hsmmc_set_dll(mmc, phase_delay + i);
|
||||
if (mmc_send_tuning(mmc, opcode, NULL)) {
|
||||
if (mmc_send_tuning(mmc, opcode)) {
|
||||
if (temperature < 10000)
|
||||
phase_delay += i + 12;
|
||||
else if (temperature < 20000)
|
||||
|
@ -568,8 +568,8 @@ int renesas_sdhi_execute_tuning(struct udevice *dev, uint opcode)
|
||||
struct mmc *mmc = upriv->mmc;
|
||||
unsigned int tap_num;
|
||||
unsigned int taps = 0;
|
||||
int i, ret = 0;
|
||||
u32 caps;
|
||||
int i, ret = 0, sret;
|
||||
u32 caps, reg;
|
||||
|
||||
/* Only supported on Renesas RCar */
|
||||
if (!(priv->caps & TMIO_SD_CAP_RCAR_UHS))
|
||||
@ -605,15 +605,15 @@ int renesas_sdhi_execute_tuning(struct udevice *dev, uint opcode)
|
||||
caps = priv->caps;
|
||||
priv->caps &= ~TMIO_SD_CAP_DMA_INTERNAL;
|
||||
|
||||
ret = mmc_send_tuning(mmc, opcode, NULL);
|
||||
ret = mmc_send_tuning(mmc, opcode);
|
||||
|
||||
priv->caps = caps;
|
||||
|
||||
if (ret == 0)
|
||||
taps |= BIT(i);
|
||||
|
||||
ret = renesas_sdhi_compare_scc_data(priv);
|
||||
if (ret == 0)
|
||||
reg = renesas_sdhi_compare_scc_data(priv);
|
||||
if (reg == 0)
|
||||
priv->smpcmp |= BIT(i);
|
||||
|
||||
mdelay(1);
|
||||
@ -624,9 +624,9 @@ int renesas_sdhi_execute_tuning(struct udevice *dev, uint opcode)
|
||||
* eMMC.
|
||||
*/
|
||||
if (ret && (opcode == MMC_CMD_SEND_TUNING_BLOCK_HS200)) {
|
||||
ret = mmc_send_stop_transmission(mmc, false);
|
||||
if (ret < 0)
|
||||
dev_dbg(dev, "Tuning abort fail (%d)\n", ret);
|
||||
sret = mmc_send_stop_transmission(mmc, false);
|
||||
if (sret < 0)
|
||||
dev_dbg(dev, "Tuning abort fail (%d)\n", sret);
|
||||
}
|
||||
}
|
||||
|
||||
@ -798,9 +798,12 @@ static int renesas_sdhi_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
|
||||
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
|
||||
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
|
||||
struct tmio_sd_priv *priv = dev_get_priv(dev);
|
||||
struct mmc *mmc = upriv->mmc;
|
||||
|
||||
renesas_sdhi_check_scc_error(dev);
|
||||
if (!mmc->tuning)
|
||||
renesas_sdhi_check_scc_error(dev);
|
||||
|
||||
if (cmd->cmdidx == MMC_CMD_SEND_STATUS)
|
||||
renesas_sdhi_adjust_hs400_mode_enable(priv);
|
||||
|
@ -145,7 +145,7 @@ static int rockchip_dwmmc_probe(struct udevice *dev)
|
||||
|
||||
host->fifo_mode = priv->fifo_mode;
|
||||
|
||||
#ifdef CONFIG_MMC_PWRSEQ
|
||||
#if CONFIG_IS_ENABLED(MMC_PWRSEQ)
|
||||
/* Enable power if needed */
|
||||
ret = mmc_pwrseq_get_power(dev, &plat->cfg);
|
||||
if (!ret) {
|
||||
|
@ -224,7 +224,7 @@ static int __maybe_unused sdhci_cdns_execute_tuning(struct udevice *dev,
|
||||
|
||||
for (i = 0; i < SDHCI_CDNS_MAX_TUNING_LOOP; i++) {
|
||||
if (sdhci_cdns_set_tune_val(plat, i) ||
|
||||
mmc_send_tuning(mmc, opcode, NULL)) { /* bad */
|
||||
mmc_send_tuning(mmc, opcode)) { /* bad */
|
||||
cur_streak = 0;
|
||||
} else { /* good */
|
||||
cur_streak++;
|
||||
|
@ -299,7 +299,13 @@ static int tmio_sd_dma_wait_for_irq(struct udevice *dev, u32 flag,
|
||||
struct tmio_sd_priv *priv = dev_get_priv(dev);
|
||||
long wait = 1000000 + 10 * blocks;
|
||||
|
||||
while (!(tmio_sd_readl(priv, TMIO_SD_DMA_INFO1) & flag)) {
|
||||
for (;;) {
|
||||
if (tmio_sd_readl(priv, TMIO_SD_DMA_INFO1) & flag)
|
||||
break;
|
||||
|
||||
if (tmio_sd_readl(priv, TMIO_SD_INFO1) & TMIO_SD_INFO1_CMP)
|
||||
break;
|
||||
|
||||
if (wait-- < 0) {
|
||||
dev_err(dev, "timeout during DMA\n");
|
||||
return -ETIMEDOUT;
|
||||
|
@ -590,7 +590,7 @@ struct mmc_config {
|
||||
uint f_max;
|
||||
uint b_max;
|
||||
unsigned char part_type;
|
||||
#ifdef CONFIG_MMC_PWRSEQ
|
||||
#if CONFIG_IS_ENABLED(MMC_PWRSEQ)
|
||||
struct udevice *pwr_dev;
|
||||
#endif
|
||||
};
|
||||
@ -736,7 +736,8 @@ struct mmc {
|
||||
* accessing the boot partitions
|
||||
*/
|
||||
u32 quirks;
|
||||
u8 hs400_tuning;
|
||||
bool tuning:1;
|
||||
bool hs400_tuning:1;
|
||||
|
||||
enum bus_mode user_speed_mode; /* input speed mode from user */
|
||||
};
|
||||
@ -795,7 +796,7 @@ int mmc_unbind(struct udevice *dev);
|
||||
int mmc_initialize(struct bd_info *bis);
|
||||
int mmc_init_device(int num);
|
||||
int mmc_init(struct mmc *mmc);
|
||||
int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error);
|
||||
int mmc_send_tuning(struct mmc *mmc, u32 opcode);
|
||||
int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data);
|
||||
int mmc_deinit(struct mmc *mmc);
|
||||
|
||||
@ -808,7 +809,7 @@ int mmc_deinit(struct mmc *mmc);
|
||||
*/
|
||||
int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg);
|
||||
|
||||
#ifdef CONFIG_MMC_PWRSEQ
|
||||
#if CONFIG_IS_ENABLED(MMC_PWRSEQ)
|
||||
/**
|
||||
* mmc_pwrseq_get_power() - get a power device from device tree
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user