Merge git://git.denx.de/u-boot-mmc

master
Tom Rini 6 years ago
commit 3dde8f2037
  1. 21
      cmd/mmc.c
  2. 2
      cmd/mvebu/bubt.c
  3. 2
      common/Makefile
  4. 9
      common/spl/Kconfig
  5. 4
      configs/am335x_hs_evm_defconfig
  6. 1
      configs/omapl138_lcdk_defconfig
  7. 1
      configs/openrd_base_defconfig
  8. 1
      configs/openrd_client_defconfig
  9. 1
      configs/openrd_ultimate_defconfig
  10. 76
      drivers/mmc/Kconfig
  11. 4
      drivers/mmc/Makefile
  12. 3
      drivers/mmc/exynos_dw_mmc.c
  13. 11
      drivers/mmc/fsl_esdhc.c
  14. 42
      drivers/mmc/gen_atmel_mci.c
  15. 2
      drivers/mmc/meson_gx_mmc.c
  16. 99
      drivers/mmc/mmc-uclass.c
  17. 1642
      drivers/mmc/mmc.c
  18. 4
      drivers/mmc/mmc_private.h
  19. 4
      drivers/mmc/omap_hsmmc.c
  20. 5
      drivers/mmc/sandbox_mmc.c
  21. 7
      drivers/mmc/sdhci.c
  22. 61
      drivers/power/power_core.c
  23. 212
      include/mmc.h

@ -23,7 +23,12 @@ static void print_mmcinfo(struct mmc *mmc)
(mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
(mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff);
printf("Tran Speed: %d\n", mmc->tran_speed);
printf("Bus Speed: %d\n", mmc->clock);
#if CONFIG_IS_ENABLED(MMC_VERBOSE)
printf("Mode : %s\n", mmc_mode_name(mmc->selected_mode));
mmc_dump_capabilities("card capabilities", mmc->card_caps);
mmc_dump_capabilities("host capabilities", mmc->host_caps);
#endif
printf("Rd Block Len: %d\n", mmc->read_bl_len);
printf("%s version %d.%d", IS_SD(mmc) ? "SD" : "MMC",
@ -40,15 +45,19 @@ static void print_mmcinfo(struct mmc *mmc)
printf("Bus Width: %d-bit%s\n", mmc->bus_width,
mmc->ddr_mode ? " DDR" : "");
#if CONFIG_IS_ENABLED(MMC_WRITE)
puts("Erase Group Size: ");
print_size(((u64)mmc->erase_grp_size) << 9, "\n");
#endif
if (!IS_SD(mmc) && mmc->version >= MMC_VERSION_4_41) {
bool has_enh = (mmc->part_support & ENHNCD_SUPPORT) != 0;
bool usr_enh = has_enh && (mmc->part_attr & EXT_CSD_ENH_USR);
#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
puts("HC WP Group Size: ");
print_size(((u64)mmc->hc_wp_grp_size) << 9, "\n");
#endif
puts("User Capacity: ");
print_size(mmc->capacity_user, usr_enh ? " ENH" : "");
@ -297,6 +306,8 @@ static int do_mmc_read(cmd_tbl_t *cmdtp, int flag,
return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
}
#if CONFIG_IS_ENABLED(MMC_WRITE)
static int do_mmc_write(cmd_tbl_t *cmdtp, int flag,
int argc, char * const argv[])
{
@ -355,6 +366,8 @@ static int do_mmc_erase(cmd_tbl_t *cmdtp, int flag,
return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
}
#endif
static int do_mmc_rescan(cmd_tbl_t *cmdtp, int flag,
int argc, char * const argv[])
{
@ -433,6 +446,7 @@ static int do_mmc_list(cmd_tbl_t *cmdtp, int flag,
return CMD_RET_SUCCESS;
}
#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
static int parse_hwpart_user(struct mmc_hwpart_conf *pconf,
int argc, char * const argv[])
{
@ -582,6 +596,7 @@ static int do_mmc_hwpartition(cmd_tbl_t *cmdtp, int flag,
return CMD_RET_FAILURE;
}
}
#endif
#ifdef CONFIG_SUPPORT_EMMC_BOOT
static int do_mmc_bootbus(cmd_tbl_t *cmdtp, int flag,
@ -785,13 +800,17 @@ static int do_mmc_bkops_enable(cmd_tbl_t *cmdtp, int flag,
static cmd_tbl_t cmd_mmc[] = {
U_BOOT_CMD_MKENT(info, 1, 0, do_mmcinfo, "", ""),
U_BOOT_CMD_MKENT(read, 4, 1, do_mmc_read, "", ""),
#if CONFIG_IS_ENABLED(MMC_WRITE)
U_BOOT_CMD_MKENT(write, 4, 0, do_mmc_write, "", ""),
U_BOOT_CMD_MKENT(erase, 3, 0, do_mmc_erase, "", ""),
#endif
U_BOOT_CMD_MKENT(rescan, 1, 1, do_mmc_rescan, "", ""),
U_BOOT_CMD_MKENT(part, 1, 1, do_mmc_part, "", ""),
U_BOOT_CMD_MKENT(dev, 3, 0, do_mmc_dev, "", ""),
U_BOOT_CMD_MKENT(list, 1, 1, do_mmc_list, "", ""),
#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
U_BOOT_CMD_MKENT(hwpartition, 28, 0, do_mmc_hwpartition, "", ""),
#endif
#ifdef CONFIG_SUPPORT_EMMC_BOOT
U_BOOT_CMD_MKENT(bootbus, 5, 0, do_mmc_bootbus, "", ""),
U_BOOT_CMD_MKENT(bootpart-resize, 4, 0, do_mmc_boot_resize, "", ""),

@ -110,7 +110,7 @@ static ulong get_load_addr(void)
/********************************************************************
* eMMC services
********************************************************************/
#ifdef CONFIG_DM_MMC
#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(MMC_WRITE)
static int mmc_burn_image(size_t image_size)
{
struct mmc *mmc;

@ -109,6 +109,7 @@ obj-$(CONFIG_IO_TRACE) += iotrace.o
obj-y += memsize.o
obj-y += stdio.o
ifndef CONFIG_SPL_BUILD
# This option is not just y/n - it can have a numeric value
ifdef CONFIG_FASTBOOT_FLASH
obj-y += image-sparse.o
@ -119,6 +120,7 @@ ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV
obj-y += fb_nand.o
endif
endif
endif
ifdef CONFIG_CMD_EEPROM_LAYOUT
obj-y += eeprom/eeprom_field.o eeprom/eeprom_layout.o

@ -301,6 +301,7 @@ config SPL_ENV_SUPPORT
config SPL_SAVEENV
bool "Support save environment"
depends on SPL_ENV_SUPPORT
select SPL_MMC_WRITE if ENV_IS_IN_MMC
help
Enable save environment support in SPL after setenv. By default
the saveenv option is not provided in SPL, but some boards need
@ -415,6 +416,14 @@ config SPL_MMC_SUPPORT
this option to build the drivers in drivers/mmc as part of an SPL
build.
config SPL_MMC_WRITE
bool "MMC/SD/SDIO card support for write operations in SPL"
depends on SPL_MMC_SUPPORT
default n
help
Enable write access to MMC and SD Cards in SPL
config SPL_MPC8XXX_INIT_DDR_SUPPORT
bool "Support MPC8XXX DDR init"
help

@ -13,10 +13,12 @@ CONFIG_ANDROID_BOOT_IMAGE=y
CONFIG_FIT_IMAGE_POST_PROCESS=y
CONFIG_SPL_LOAD_FIT=y
CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y
CONFIG_LOGLEVEL=3
CONFIG_SYS_CONSOLE_INFO_QUIET=y
CONFIG_VERSION_VARIABLE=y
CONFIG_ARCH_MISC_INIT=y
CONFIG_SPL=y
CONFIG_SPL_FIT_IMAGE_TINY=y
# CONFIG_SPL_ENV_SUPPORT is not set
# CONFIG_SPL_EXT_SUPPORT is not set
CONFIG_SPL_MTD_SUPPORT=y
@ -37,6 +39,7 @@ CONFIG_DFU_RAM=y
CONFIG_DM_I2C=y
CONFIG_MISC=y
CONFIG_DM_MMC=y
# CONFIG_MMC_HW_PARTITIONING is not set
CONFIG_MMC_OMAP_HS=y
CONFIG_NAND=y
CONFIG_SPI_FLASH=y
@ -60,5 +63,6 @@ CONFIG_USB_GADGET_VENDOR_NUM=0x0451
CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
CONFIG_USB_GADGET_DOWNLOAD=y
CONFIG_USB_ETHER=y
CONFIG_SPL_TINY_MEMSET=y
CONFIG_RSA=y
CONFIG_LZO=y

@ -8,6 +8,7 @@ CONFIG_SPL_MMC_SUPPORT=y
CONFIG_SPL_SERIAL_SUPPORT=y
CONFIG_SPL_NAND_SUPPORT=y
CONFIG_BOOTDELAY=3
CONFIG_LOGLEVEL=3
CONFIG_VERSION_VARIABLE=y
# CONFIG_DISPLAY_CPUINFO is not set
# CONFIG_DISPLAY_BOARDINFO is not set

@ -25,6 +25,7 @@ CONFIG_CMD_UBI=y
CONFIG_ISO_PARTITION=y
CONFIG_ENV_IS_IN_NAND=y
CONFIG_MVSATA_IDE=y
# CONFIG_MMC_HW_PARTITIONING is not set
CONFIG_SYS_NS16550=y
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y

@ -25,6 +25,7 @@ CONFIG_CMD_UBI=y
CONFIG_ISO_PARTITION=y
CONFIG_ENV_IS_IN_NAND=y
CONFIG_MVSATA_IDE=y
# CONFIG_MMC_HW_PARTITIONING is not set
CONFIG_SYS_NS16550=y
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y

@ -25,6 +25,7 @@ CONFIG_CMD_UBI=y
CONFIG_ISO_PARTITION=y
CONFIG_ENV_IS_IN_NAND=y
CONFIG_MVSATA_IDE=y
# CONFIG_MMC_HW_PARTITIONING is not set
CONFIG_SYS_NS16550=y
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y

@ -10,6 +10,13 @@ config MMC
If you want MMC/SD/SDIO support, you should say Y here and
also to your specific host controller driver.
config MMC_WRITE
bool "support for MMC/SD write operations"
depends on MMC
default y
help
Enable write access to MMC and SD Cards
config DM_MMC
bool "Enable MMC controllers using Driver Model"
depends on DM
@ -42,6 +49,75 @@ config ARM_PL180_MMCI
If you have an ARM(R) platform with a Multimedia Card slot,
say Y or M here.
config MMC_QUIRKS
bool "Enable quirks"
default y
help
Some cards and hosts may sometimes behave unexpectedly (quirks).
This option enable workarounds to handle those quirks. Some of them
are enabled by default, other may require additionnal flags or are
enabled by the host driver.
config MMC_HW_PARTITIONING
bool "Support for HW partitioning command(eMMC)"
default y
help
This adds a command and an API to do hardware partitioning on eMMC
devices.
config MMC_IO_VOLTAGE
bool "Support IO voltage configuration"
help
IO voltage configuration allows selecting the voltage level of the IO
lines (not the level of main supply). This is required for UHS
support. For eMMC this not mandatory, but not enabling this option may
prevent the driver of using the faster modes.
config SPL_MMC_IO_VOLTAGE
bool "Support IO voltage configuration in SPL"
default n
help
IO voltage configuration allows selecting the voltage level of the IO
lines (not the level of main supply). This is required for UHS
support. For eMMC this not mandatory, but not enabling this option may
prevent the driver of using the faster modes.
config MMC_UHS_SUPPORT
bool "enable UHS support"
depends on MMC_IO_VOLTAGE
help
The Ultra High Speed (UHS) bus is available on some SDHC and SDXC
cards. The IO voltage must be switchable from 3.3v to 1.8v. The bus
frequency can go up to 208MHz (SDR104)
config SPL_MMC_UHS_SUPPORT
bool "enable UHS support in SPL"
depends on SPL_MMC_IO_VOLTAGE
help
The Ultra High Speed (UHS) bus is available on some SDHC and SDXC
cards. The IO voltage must be switchable from 3.3v to 1.8v. The bus
frequency can go up to 208MHz (SDR104)
config MMC_HS200_SUPPORT
bool "enable HS200 support"
help
The HS200 mode is support by some eMMC. The bus frequency is up to
200MHz. This mode requires tuning the IO.
config SPL_MMC_HS200_SUPPORT
bool "enable HS200 support in SPL"
help
The HS200 mode is support by some eMMC. The bus frequency is up to
200MHz. This mode requires tuning the IO.
config MMC_VERBOSE
bool "Output more information about the MMC"
default y
help
Enable the output of more information about the card such as the
operating mode.
config SPL_MMC_TINY
bool "Tiny MMC framework in SPL"
help

@ -7,6 +7,7 @@
obj-y += mmc.o
obj-$(CONFIG_$(SPL_)DM_MMC) += mmc-uclass.o
obj-$(CONFIG_$(SPL_)MMC_WRITE) += mmc_write.o
ifndef CONFIG_$(SPL_)BLK
obj-y += mmc_legacy.o
@ -16,9 +17,6 @@ obj-$(CONFIG_SUPPORT_EMMC_BOOT) += mmc_boot.o
ifdef CONFIG_SPL_BUILD
obj-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o
obj-$(CONFIG_SPL_SAVEENV) += mmc_write.o
else
obj-y += mmc_write.o
endif
obj-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o

@ -168,6 +168,7 @@ static int exynos_dwmci_get_config(const void *blob, int node,
if (host->dev_index > 4) {
printf("DWMMC%d: Can't get the dev index\n", host->dev_index);
free(priv);
return -EINVAL;
}
@ -178,6 +179,7 @@ static int exynos_dwmci_get_config(const void *blob, int node,
base = fdtdec_get_addr(blob, node, "reg");
if (!base) {
printf("DWMMC%d: Can't get base address\n", host->dev_index);
free(priv);
return -EINVAL;
}
host->ioaddr = (void *)base;
@ -187,6 +189,7 @@ static int exynos_dwmci_get_config(const void *blob, int node,
if (err) {
printf("DWMMC%d: Can't get sdr-timings for devider\n",
host->dev_index);
free(priv);
return -EINVAL;
}

@ -647,7 +647,11 @@ static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
esdhc_write32(&regs->clktunectrlstatus, 0x0);
/* Put VEND_SPEC to default value */
esdhc_write32(&regs->vendorspec, VENDORSPEC_INIT);
if (priv->vs18_enable)
esdhc_write32(&regs->vendorspec, (VENDORSPEC_INIT |
ESDHC_VENDORSPEC_VSELECT));
else
esdhc_write32(&regs->vendorspec, VENDORSPEC_INIT);
/* Disable DLL_CTRL delay line */
esdhc_write32(&regs->dllctrl, 0x0);
@ -665,7 +669,7 @@ static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
#endif
/* Set the initial clock speed */
mmc_set_clock(mmc, 400000);
mmc_set_clock(mmc, 400000, false);
/* Disable the BRR and BWR bits in IRQSTAT */
esdhc_clrbits32(&regs->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR);
@ -676,9 +680,6 @@ static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
/* Set timout to the maximum value */
esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16);
if (priv->vs18_enable)
esdhc_setbits32(&regs->vendorspec, ESDHC_VENDORSPEC_VSELECT);
return 0;
}

@ -74,6 +74,20 @@ static void dump_cmd(u32 cmdr, u32 arg, u32 status, const char* msg)
cmdr, cmdr & 0x3F, arg, status, msg);
}
static inline void mci_set_blklen(atmel_mci_t *mci, int blklen)
{
unsigned int version = atmel_mci_get_version(mci);
blklen &= 0xfffc;
/* MCI IP version >= 0x200 has blkr */
if (version >= 0x200)
writel(MMCI_BFINS(BLKLEN, blklen, readl(&mci->blkr)),
&mci->blkr);
else
writel(MMCI_BFINS(BLKLEN, blklen, readl(&mci->mr)), &mci->mr);
}
/* Setup for MCI Clock and Block Size */
#ifdef CONFIG_DM_MMC
static void mci_set_mode(struct udevice *dev, u32 hz, u32 blklen)
@ -124,7 +138,6 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
priv->curr_clk = bus_hz / (clkdiv * 2 + clkodd + 2);
else
priv->curr_clk = (bus_hz / (clkdiv + 1)) / 2;
blklen &= 0xfffc;
mr = MMCI_BF(CLKDIV, clkdiv);
@ -138,14 +151,10 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
*/
if (version >= 0x500)
mr |= MMCI_BF(CLKODD, clkodd);
else
mr |= MMCI_BF(BLKLEN, blklen);
writel(mr, &mci->mr);
/* MCI IP version >= 0x200 has blkr */
if (version >= 0x200)
writel(MMCI_BF(BLKLEN, blklen), &mci->blkr);
mci_set_blklen(mci, blklen);
if (mmc->card_caps & mmc->cfg->host_caps & MMC_MODE_HS)
writel(MMCI_BIT(HSMODE), &mci->cfg);
@ -236,7 +245,6 @@ static int atmel_mci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
{
struct atmel_mci_plat *plat = dev_get_platdata(dev);
struct atmel_mci_priv *priv = dev_get_priv(dev);
struct mmc *mmc = mmc_get_mmc_dev(dev);
atmel_mci_t *mci = plat->mci;
#else
static int
@ -257,11 +265,13 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
/* Figure out the transfer arguments */
cmdr = mci_encode_cmd(cmd, data, &error_flags);
mci_set_blklen(mci, data->blocksize);
/* For multi blocks read/write, set the block register */
if ((cmd->cmdidx == MMC_CMD_READ_MULTIPLE_BLOCK)
|| (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK))
writel(data->blocks | MMCI_BF(BLKLEN, mmc->read_bl_len),
&mci->blkr);
writel(data->blocks | MMCI_BF(BLKLEN, data->blocksize),
&mci->blkr);
/* Send the command */
writel(cmd->cmdarg, &mci->argr);
@ -295,17 +305,15 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
if (data) {
u32 word_count, block_count;
u32* ioptr;
u32 sys_blocksize, dummy, i;
u32 i;
u32 (*mci_data_op)
(atmel_mci_t *mci, u32* data, u32 error_flags);
if (data->flags & MMC_DATA_READ) {
mci_data_op = mci_data_read;
sys_blocksize = mmc->read_bl_len;
ioptr = (u32*)data->dest;
} else {
mci_data_op = mci_data_write;
sys_blocksize = mmc->write_bl_len;
ioptr = (u32*)data->src;
}
@ -328,16 +336,6 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
1, cnt, 0);
}
#endif
#ifdef DEBUG
if (!status && word_count < (sys_blocksize / 4))
printf("filling rest of block...\n");
#endif
/* fill the rest of a full block */
while (!status && word_count < (sys_blocksize / 4)) {
status = mci_data_op(mci, &dummy,
error_flags);
word_count++;
}
if (status) {
dump_cmd(cmdr, cmd->cmdarg, status,
"Data Transfer Failed");

@ -250,7 +250,7 @@ static int meson_mmc_probe(struct udevice *dev)
mmc->priv = pdata;
upriv->mmc = mmc;
mmc_set_clock(mmc, cfg->f_min);
mmc_set_clock(mmc, cfg->f_min, false);
/* reset all status bits */
meson_write(mmc, STATUS_MASK, MESON_SD_EMMC_STATUS);

@ -10,7 +10,6 @@
#include <dm.h>
#include <dm/device-internal.h>
#include <dm/lists.h>
#include <dm/root.h>
#include "mmc_private.h"
DECLARE_GLOBAL_DATA_PTR;
@ -51,6 +50,35 @@ int mmc_set_ios(struct mmc *mmc)
return dm_mmc_set_ios(mmc->dev);
}
void dm_mmc_send_init_stream(struct udevice *dev)
{
struct dm_mmc_ops *ops = mmc_get_ops(dev);
if (ops->send_init_stream)
ops->send_init_stream(dev);
}
void mmc_send_init_stream(struct mmc *mmc)
{
dm_mmc_send_init_stream(mmc->dev);
}
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
int dm_mmc_wait_dat0(struct udevice *dev, int state, int timeout)
{
struct dm_mmc_ops *ops = mmc_get_ops(dev);
if (!ops->wait_dat0)
return -ENOSYS;
return ops->wait_dat0(dev, state, timeout);
}
int mmc_wait_dat0(struct mmc *mmc, int state, int timeout)
{
return dm_mmc_wait_dat0(mmc->dev, state, timeout);
}
#endif
int dm_mmc_get_wp(struct udevice *dev)
{
struct dm_mmc_ops *ops = mmc_get_ops(dev);
@ -79,6 +107,73 @@ int mmc_getcd(struct mmc *mmc)
return dm_mmc_get_cd(mmc->dev);
}
#ifdef MMC_SUPPORTS_TUNING
int dm_mmc_execute_tuning(struct udevice *dev, uint opcode)
{
struct dm_mmc_ops *ops = mmc_get_ops(dev);
if (!ops->execute_tuning)
return -ENOSYS;
return ops->execute_tuning(dev, opcode);
}
int mmc_execute_tuning(struct mmc *mmc, uint opcode)
{
return dm_mmc_execute_tuning(mmc->dev, opcode);
}
#endif
int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg)
{
int val;
val = dev_read_u32_default(dev, "bus-width", 1);
switch (val) {
case 0x8:
cfg->host_caps |= MMC_MODE_8BIT;
/* fall through */
case 0x4:
cfg->host_caps |= MMC_MODE_4BIT;
/* fall through */
case 0x1:
cfg->host_caps |= MMC_MODE_1BIT;
break;
default:
debug("warning: %s invalid bus-width property. using 1-bit\n",
dev_read_name(dev));
cfg->host_caps |= MMC_MODE_1BIT;
break;
}
cfg->f_max = dev_read_u32_default(dev, "max-frequency", 52000000);
if (dev_read_bool(dev, "cap-sd-highspeed"))
cfg->host_caps |= MMC_CAP(SD_HS);
if (dev_read_bool(dev, "cap-mmc-highspeed"))
cfg->host_caps |= MMC_CAP(MMC_HS);
if (dev_read_bool(dev, "sd-uhs-sdr12"))
cfg->host_caps |= MMC_CAP(UHS_SDR12);
if (dev_read_bool(dev, "sd-uhs-sdr25"))
cfg->host_caps |= MMC_CAP(UHS_SDR25);
if (dev_read_bool(dev, "sd-uhs-sdr50"))
cfg->host_caps |= MMC_CAP(UHS_SDR50);
if (dev_read_bool(dev, "sd-uhs-sdr104"))
cfg->host_caps |= MMC_CAP(UHS_SDR104);
if (dev_read_bool(dev, "sd-uhs-ddr50"))
cfg->host_caps |= MMC_CAP(UHS_DDR50);
if (dev_read_bool(dev, "mmc-ddr-1_8v"))
cfg->host_caps |= MMC_CAP(MMC_DDR_52);
if (dev_read_bool(dev, "mmc-ddr-1_2v"))
cfg->host_caps |= MMC_CAP(MMC_DDR_52);
if (dev_read_bool(dev, "mmc-hs200-1_8v"))
cfg->host_caps |= MMC_CAP(MMC_HS_200);
if (dev_read_bool(dev, "mmc-hs200-1_2v"))
cfg->host_caps |= MMC_CAP(MMC_HS_200);
return 0;
}
struct mmc *mmc_get_mmc_dev(struct udevice *dev)
{
struct mmc_uclass_priv *upriv;
@ -275,7 +370,7 @@ static int mmc_blk_probe(struct udevice *dev)
static const struct blk_ops mmc_blk_ops = {
.read = mmc_bread,
#ifndef CONFIG_SPL_BUILD
#if CONFIG_IS_ENABLED(MMC_WRITE)
.write = mmc_bwrite,
.erase = mmc_berase,
#endif

File diff suppressed because it is too large Load Diff

@ -28,7 +28,7 @@ ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
void *dst);
#endif
#if !(defined(CONFIG_SPL_BUILD) && !defined(CONFIG_SPL_SAVEENV))
#if CONFIG_IS_ENABLED(MMC_WRITE)
#if CONFIG_IS_ENABLED(BLK)
ulong mmc_bwrite(struct udevice *dev, lbaint_t start, lbaint_t blkcnt,
@ -40,7 +40,7 @@ ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
ulong mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt);
#endif
#else /* CONFIG_SPL_BUILD and CONFIG_SPL_SAVEENV is not defined */
#else /* CONFIG_SPL_MMC_WRITE is not defined */
/* declare dummies to reduce code size. */

@ -28,9 +28,9 @@
#include <mmc.h>
#include <part.h>
#include <i2c.h>
#include <twl4030.h>
#include <twl6030.h>
#if defined(CONFIG_OMAP54XX) || defined(CONFIG_OMAP44XX)
#include <palmas.h>
#endif
#include <asm/io.h>
#include <asm/arch/mmc_host_def.h>
#if !defined(CONFIG_SOC_KEYSTONE)

@ -48,9 +48,12 @@ static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
cmd->response[1] = 10 << 16; /* 1 << block_len */
break;
case SD_CMD_SWITCH_FUNC: {
if (!data)
break;
u32 *resp = (u32 *)data->dest;
resp[7] = cpu_to_be32(SD_HIGHSPEED_BUSY);
if ((cmd->cmdarg & 0xF) == UHS_SDR12_BUS_SPEED)
resp[4] = (cmd->cmdarg & 0xF) << 24;
break;
}
case MMC_CMD_READ_SINGLE_BLOCK:

@ -157,7 +157,6 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
/* Timeout unit - ms */
static unsigned int cmd_timeout = SDHCI_CMD_DEFAULT_TIMEOUT;
sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
mask = SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT;
/* We shouldn't wait for data inihibit for stop commands, even
@ -181,6 +180,8 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
udelay(1000);
}
sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
mask = SDHCI_INT_RESPONSE;
if (!(cmd->resp_type & MMC_RSP_PRESENT))
flags = SDHCI_CMD_RESP_NONE;
@ -201,7 +202,7 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
flags |= SDHCI_CMD_DATA;
/* Set Transfer mode regarding to data flag */
if (data != 0) {
if (data) {
sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL);
mode = SDHCI_TRNS_BLK_CNT_EN;
trans_bytes = data->blocks * data->blocksize;
@ -249,7 +250,7 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
sdhci_writel(host, cmd->cmdarg, SDHCI_ARGUMENT);
#ifdef CONFIG_MMC_SDHCI_SDMA
if (data != 0) {
if (data) {
trans_bytes = ALIGN(trans_bytes, CONFIG_SYS_CACHELINE_SIZE);
flush_cache(start_addr, trans_bytes);
}

@ -47,36 +47,6 @@ int pmic_set_output(struct pmic *p, u32 reg, int out, int on)
return 0;
}
static void pmic_show_info(struct pmic *p)
{
printf("PMIC: %s\n", p->name);
}
static int pmic_dump(struct pmic *p)
{
int i, ret;
u32 val;
if (!p) {
puts("Wrong PMIC name!\n");
return -ENODEV;
}
pmic_show_info(p);
for (i = 0; i < p->number_of_regs; i++) {
ret = pmic_reg_read(p, i, &val);
if (ret)
puts("PMIC: Registers dump failed\n");
if (!(i % 8))
printf("\n0x%02x: ", i);
printf("%08x ", val);
}
puts("\n");
return 0;
}
struct pmic *pmic_alloc(void)
{
struct pmic *p;
@ -108,7 +78,33 @@ struct pmic *pmic_get(const char *s)
return NULL;
}
const char *power_get_interface(int interface)
#ifndef CONFIG_SPL_BUILD
static int pmic_dump(struct pmic *p)
{
int i, ret;
u32 val;
if (!p) {
puts("Wrong PMIC name!\n");
return -ENODEV;
}
printf("PMIC: %s\n", p->name);
for (i = 0; i < p->number_of_regs; i++) {
ret = pmic_reg_read(p, i, &val);
if (ret)
puts("PMIC: Registers dump failed\n");
if (!(i % 8))
printf("\n0x%02x: ", i);
printf("%08x ", val);
}
puts("\n");
return 0;
}
static const char *power_get_interface(int interface)
{
const char *power_interface[] = {"I2C", "SPI", "|+|-|"};
return power_interface[interface];
@ -125,7 +121,7 @@ static void pmic_list_names(void)
}
}
int do_pmic(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
static int do_pmic(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
u32 ret, reg, val;
char *cmd, *name;
@ -221,3 +217,4 @@ U_BOOT_CMD(
"pmic name bat state - write register\n"
"pmic name bat charge - write register\n"
);
#endif

@ -15,6 +15,13 @@
#include <linux/compiler.h>
#include <part.h>
#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
#define MMC_SUPPORTS_TUNING
#endif
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
#define MMC_SUPPORTS_TUNING
#endif
/* SD/MMC version bits; 8 flags, 8 major, 8 minor, 8 change */
#define SD_VERSION_SD (1U << 31)
#define MMC_VERSION_MMC (1U << 30)
@ -52,12 +59,17 @@
#define MMC_VERSION_5_0 MAKE_MMC_VERSION(5, 0, 0)
#define MMC_VERSION_5_1 MAKE_MMC_VERSION(5, 1, 0)
#define MMC_MODE_HS (1 << 0)
#define MMC_MODE_HS_52MHz (1 << 1)
#define MMC_MODE_4BIT (1 << 2)
#define MMC_MODE_8BIT (1 << 3)
#define MMC_MODE_SPI (1 << 4)
#define MMC_MODE_DDR_52MHz (1 << 5)
#define MMC_CAP(mode) (1 << mode)
#define MMC_MODE_HS (MMC_CAP(MMC_HS) | MMC_CAP(SD_HS))
#define MMC_MODE_HS_52MHz MMC_CAP(MMC_HS_52)
#define MMC_MODE_DDR_52MHz MMC_CAP(MMC_DDR_52)
#define MMC_MODE_HS200 MMC_CAP(MMC_HS_200)
#define MMC_MODE_8BIT BIT(30)
#define MMC_MODE_4BIT BIT(29)
#define MMC_MODE_1BIT BIT(28)
#define MMC_MODE_SPI BIT(27)
#define SD_DATA_4BIT 0x00040000
@ -82,6 +94,8 @@
#define MMC_CMD_SET_BLOCKLEN 16
#define MMC_CMD_READ_SINGLE_BLOCK 17
#define MMC_CMD_READ_MULTIPLE_BLOCK 18
#define MMC_CMD_SEND_TUNING_BLOCK 19
#define MMC_CMD_SEND_TUNING_BLOCK_HS200 21
#define MMC_CMD_SET_BLOCK_COUNT 23
#define MMC_CMD_WRITE_SINGLE_BLOCK 24
#define MMC_CMD_WRITE_MULTIPLE_BLOCK 25
@ -109,12 +123,34 @@
#define SD_CMD_APP_SEND_OP_COND 41
#define SD_CMD_APP_SEND_SCR 51
static inline bool mmc_is_tuning_cmd(uint cmdidx)
{
if ((cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200) ||
(cmdidx == MMC_CMD_SEND_TUNING_BLOCK))
return true;
return false;
}
/* SCR definitions in different words */
#define SD_HIGHSPEED_BUSY 0x00020000
#define SD_HIGHSPEED_SUPPORTED 0x00020000
#define UHS_SDR12_BUS_SPEED 0
#define HIGH_SPEED_BUS_SPEED 1
#define UHS_SDR25_BUS_SPEED 1
#define UHS_SDR50_BUS_SPEED 2
#define UHS_SDR104_BUS_SPEED 3
#define UHS_DDR50_BUS_SPEED 4
#define SD_MODE_UHS_SDR12 BIT(UHS_SDR12_BUS_SPEED)
#define SD_MODE_UHS_SDR25 BIT(UHS_SDR25_BUS_SPEED)
#define SD_MODE_UHS_SDR50 BIT(UHS_SDR50_BUS_SPEED)
#define SD_MODE_UHS_SDR104 BIT(UHS_SDR104_BUS_SPEED)
#define SD_MODE_UHS_DDR50 BIT(UHS_DDR50_BUS_SPEED)
#define OCR_BUSY 0x80000000
#define OCR_HCS 0x40000000
#define OCR_S18R 0x1000000
#define OCR_VOLTAGE_MASK 0x007FFF80
#define OCR_ACCESS_MODE 0x60000000
@ -206,11 +242,23 @@
#define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \
| EXT_CSD_CARD_TYPE_DDR_1_2V)
#define EXT_CSD_CARD_TYPE_HS200_1_8V BIT(4) /* Card can run at 200MHz */
/* SDR mode @1.8V I/O */
#define EXT_CSD_CARD_TYPE_HS200_1_2V BIT(5) /* Card can run at 200MHz */
/* SDR mode @1.2V I/O */
#define EXT_CSD_CARD_TYPE_HS200 (EXT_CSD_CARD_TYPE_HS200_1_8V | \
EXT_CSD_CARD_TYPE_HS200_1_2V)
#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */
#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */
#define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */
#define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */
#define EXT_CSD_DDR_FLAG BIT(2) /* Flag for DDR mode */
#define EXT_CSD_TIMING_LEGACY 0 /* no high speed */
#define EXT_CSD_TIMING_HS 1 /* HS */
#define EXT_CSD_TIMING_HS200 2 /* HS200 */
#define EXT_CSD_BOOT_ACK_ENABLE (1 << 6)
#define EXT_CSD_BOOT_PARTITION_ENABLE (1 << 3)
@ -265,6 +313,20 @@
#define ENHNCD_SUPPORT (0x2)
#define PART_ENH_ATTRIB (0x1f)
#define MMC_QUIRK_RETRY_SEND_CID BIT(0)
#define MMC_QUIRK_RETRY_SET_BLOCKLEN BIT(1)
enum mmc_voltage {
MMC_SIGNAL_VOLTAGE_000 = 0,
MMC_SIGNAL_VOLTAGE_120 = 1,
MMC_SIGNAL_VOLTAGE_180 = 2,
MMC_SIGNAL_VOLTAGE_330 = 4,
};
#define MMC_ALL_SIGNAL_VOLTAGE (MMC_SIGNAL_VOLTAGE_120 |\
MMC_SIGNAL_VOLTAGE_180 |\
MMC_SIGNAL_VOLTAGE_330)
/* Maximum block size for MMC */
#define MMC_MAX_BLOCK_LEN 512
@ -347,6 +409,14 @@ struct dm_mmc_ops {
int (*set_ios)(struct udevice *dev);
/**
* send_init_stream() - send the initialization stream: 74 clock cycles
* This is used after power up before sending the first command
*
* @dev: Device to update
*/
void (*send_init_stream)(struct udevice *dev);
/**
* get_cd() - See whether a card is present
*
* @dev: Device to check
@ -361,6 +431,30 @@ struct dm_mmc_ops {
* @return 0 if write-enabled, 1 if write-protected, -ve on error
*/
int (*get_wp)(struct udevice *dev);
#ifdef MMC_SUPPORTS_TUNING
/**
* execute_tuning() - Start the tuning process
*
* @dev: Device to start the tuning
* @opcode: Command opcode to send
* @return 0 if OK, -ve on error
*/
int (*execute_tuning)(struct udevice *dev, uint opcode);
#endif
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
/**
* wait_dat0() - wait until dat0 is in the target state
* (CLK must be running during the wait)
*
* @dev: Device to check
* @state: target state
* @timeout: timeout in us
* @return 0 if dat0 is in the target state, -ve on error
*/
int (*wait_dat0)(struct udevice *dev, int state, int timeout);
#endif
};
#define mmc_get_ops(dev) ((struct dm_mmc_ops *)(dev)->driver->ops)
@ -368,13 +462,19 @@ struct dm_mmc_ops {
int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
struct mmc_data *data);
int dm_mmc_set_ios(struct udevice *dev);
void dm_mmc_send_init_stream(struct udevice *dev);
int dm_mmc_get_cd(struct udevice *dev);
int dm_mmc_get_wp(struct udevice *dev);
int dm_mmc_execute_tuning(struct udevice *dev, uint opcode);
int dm_mmc_wait_dat0(struct udevice *dev, int state, int timeout);
/* Transition functions for compatibility */
int mmc_set_ios(struct mmc *mmc);
void mmc_send_init_stream(struct mmc *mmc);
int mmc_getcd(struct mmc *mmc);
int mmc_getwp(struct mmc *mmc);
int mmc_execute_tuning(struct mmc *mmc, uint opcode);
int mmc_wait_dat0(struct mmc *mmc, int state, int timeout);
#else
struct mmc_ops {
@ -406,6 +506,50 @@ struct sd_ssr {
unsigned int erase_offset; /* In milliseconds */
};
enum bus_mode {
MMC_LEGACY,
SD_LEGACY,
MMC_HS,
SD_HS,
MMC_HS_52,
MMC_DDR_52,
UHS_SDR12,
UHS_SDR25,
UHS_SDR50,
UHS_DDR50,
UHS_SDR104,
MMC_HS_200,
MMC_MODES_END
};
const char *mmc_mode_name(enum bus_mode mode);
void mmc_dump_capabilities(const char *text, uint caps);
static inline bool mmc_is_mode_ddr(enum bus_mode mode)
{
if (mode == MMC_DDR_52)
return true;
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
else if (mode == UHS_DDR50)
return true;
#endif
else
return false;
}
#define UHS_CAPS (MMC_CAP(UHS_SDR12) | MMC_CAP(UHS_SDR25) | \
MMC_CAP(UHS_SDR50) | MMC_CAP(UHS_SDR104) | \
MMC_CAP(UHS_DDR50))
static inline bool supports_uhs(uint caps)
{
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
return (caps & UHS_CAPS) ? true : false;
#else
return false;
#endif
}
/*
* With CONFIG_DM_MMC enabled, struct mmc can be accessed from the MMC device
* with mmc_get_mmc_dev().
@ -421,9 +565,12 @@ struct mmc {
void *priv;
uint has_init;
int high_capacity;
bool clk_disable; /* true if the clock can be turned off */
uint bus_width;
uint clock;
enum mmc_voltage signal_voltage;
uint card_caps;
uint host_caps;
uint ocr;
uint dsr;
uint dsr_imp;
@ -436,18 +583,27 @@ struct mmc {
u8 wr_rel_set;
u8 part_config;
uint tran_speed;
uint legacy_speed; /* speed for the legacy mode provided by the card */
uint read_bl_len;
#if CONFIG_IS_ENABLED(MMC_WRITE)
uint write_bl_len;
uint erase_grp_size; /* in 512-byte sectors */
#endif
#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
uint hc_wp_grp_size; /* in 512-byte sectors */
#endif
#if CONFIG_IS_ENABLED(MMC_WRITE)
struct sd_ssr ssr; /* SD status register */
#endif
u64 capacity;
u64 capacity_user;
u64 capacity_boot;
u64 capacity_rpmb;
u64 capacity_gp[4];
#ifndef CONFIG_SPL_BUILD
u64 enh_user_start;
u64 enh_user_size;
#endif
#if !CONFIG_IS_ENABLED(BLK)
struct blk_desc block_dev;
#endif
@ -457,7 +613,21 @@ struct mmc {
int ddr_mode;
#if CONFIG_IS_ENABLED(DM_MMC)
struct udevice *dev; /* Device for this MMC controller */
#if CONFIG_IS_ENABLED(DM_REGULATOR)
struct udevice *vmmc_supply; /* Main voltage regulator (Vcc)*/
struct udevice *vqmmc_supply; /* IO voltage regulator (Vccq)*/
#endif
#endif
u8 *ext_csd;
u32 cardtype; /* cardtype read from the MMC */
enum mmc_voltage current_voltage;
enum bus_mode selected_mode; /* mode currently used */
enum bus_mode best_mode; /* best mode is the supported mode with the
* highest bandwidth. It may not always be the
* operating mode due to limitations when
* accessing the boot partitions
*/
u32 quirks;
};
struct mmc_hwpart_conf {
@ -507,8 +677,36 @@ void mmc_destroy(struct mmc *mmc);
int mmc_unbind(struct udevice *dev);
int mmc_initialize(bd_t *bis);
int mmc_init(struct mmc *mmc);
int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error);
/**
* mmc_of_parse() - Parse the device tree to get the capabilities of the host
*
* @dev: MMC device
* @cfg: MMC configuration
* @return 0 if OK, -ve on error
*/
int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg);
int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
void mmc_set_clock(struct mmc *mmc, uint clock);
/**
* mmc_voltage_to_mv() - Convert a mmc_voltage in mV
*
* @voltage: The mmc_voltage to convert
* @return the value in mV if OK, -EINVAL on error (invalid mmc_voltage value)
*/
int mmc_voltage_to_mv(enum mmc_voltage voltage);
/**
* mmc_set_clock() - change the bus clock
* @mmc: MMC struct
* @clock: bus frequency in Hz
* @disable: flag indicating if the clock must on or off
* @return 0 if OK, -ve on error
*/
int mmc_set_clock(struct mmc *mmc, uint clock, bool disable);
struct mmc *find_mmc_device(int dev_num);
int mmc_set_dev(int dev_num);
void print_mmc_devices(char separator);

Loading…
Cancel
Save