Merge git://git.denx.de/u-boot-mmc
This commit is contained in:
commit
3dde8f2037
21
cmd/mmc.c
21
cmd/mmc.c
@ -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(®s->clktunectrlstatus, 0x0);
|
||||
|
||||
/* Put VEND_SPEC to default value */
|
||||
esdhc_write32(®s->vendorspec, VENDORSPEC_INIT);
|
||||
if (priv->vs18_enable)
|
||||
esdhc_write32(®s->vendorspec, (VENDORSPEC_INIT |
|
||||
ESDHC_VENDORSPEC_VSELECT));
|
||||
else
|
||||
esdhc_write32(®s->vendorspec, VENDORSPEC_INIT);
|
||||
|
||||
/* Disable DLL_CTRL delay line */
|
||||
esdhc_write32(®s->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(®s->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(®s->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16);
|
||||
|
||||
if (priv->vs18_enable)
|
||||
esdhc_setbits32(®s->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
|
||||
|
1642
drivers/mmc/mmc.c
1642
drivers/mmc/mmc.c
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
|
||||
|
212
include/mmc.h
212
include/mmc.h
@ -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
|
||||
|
||||
@ -346,6 +408,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
|
||||
*
|
||||
@ -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…
Reference in New Issue
Block a user