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