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] >> 24), (mmc->cid[1] >> 16) & 0xff, | ||||||
| 			(mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 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("Rd Block Len: %d\n", mmc->read_bl_len); | ||||||
| 
 | 
 | ||||||
| 	printf("%s version %d.%d", IS_SD(mmc) ? "SD" : "MMC", | 	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, | 	printf("Bus Width: %d-bit%s\n", mmc->bus_width, | ||||||
| 			mmc->ddr_mode ? " DDR" : ""); | 			mmc->ddr_mode ? " DDR" : ""); | ||||||
| 
 | 
 | ||||||
|  | #if CONFIG_IS_ENABLED(MMC_WRITE) | ||||||
| 	puts("Erase Group Size: "); | 	puts("Erase Group Size: "); | ||||||
| 	print_size(((u64)mmc->erase_grp_size) << 9, "\n"); | 	print_size(((u64)mmc->erase_grp_size) << 9, "\n"); | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| 	if (!IS_SD(mmc) && mmc->version >= MMC_VERSION_4_41) { | 	if (!IS_SD(mmc) && mmc->version >= MMC_VERSION_4_41) { | ||||||
| 		bool has_enh = (mmc->part_support & ENHNCD_SUPPORT) != 0; | 		bool has_enh = (mmc->part_support & ENHNCD_SUPPORT) != 0; | ||||||
| 		bool usr_enh = has_enh && (mmc->part_attr & EXT_CSD_ENH_USR); | 		bool usr_enh = has_enh && (mmc->part_attr & EXT_CSD_ENH_USR); | ||||||
| 
 | 
 | ||||||
|  | #if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING) | ||||||
| 		puts("HC WP Group Size: "); | 		puts("HC WP Group Size: "); | ||||||
| 		print_size(((u64)mmc->hc_wp_grp_size) << 9, "\n"); | 		print_size(((u64)mmc->hc_wp_grp_size) << 9, "\n"); | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| 		puts("User Capacity: "); | 		puts("User Capacity: "); | ||||||
| 		print_size(mmc->capacity_user, usr_enh ? " ENH" : ""); | 		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; | 	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, | static int do_mmc_write(cmd_tbl_t *cmdtp, int flag, | ||||||
| 			int argc, char * const argv[]) | 			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; | 	return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| static int do_mmc_rescan(cmd_tbl_t *cmdtp, int flag, | static int do_mmc_rescan(cmd_tbl_t *cmdtp, int flag, | ||||||
| 			 int argc, char * const argv[]) | 			 int argc, char * const argv[]) | ||||||
| { | { | ||||||
|  | @ -433,6 +446,7 @@ static int do_mmc_list(cmd_tbl_t *cmdtp, int flag, | ||||||
| 	return CMD_RET_SUCCESS; | 	return CMD_RET_SUCCESS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING) | ||||||
| static int parse_hwpart_user(struct mmc_hwpart_conf *pconf, | static int parse_hwpart_user(struct mmc_hwpart_conf *pconf, | ||||||
| 			     int argc, char * const argv[]) | 			     int argc, char * const argv[]) | ||||||
| { | { | ||||||
|  | @ -582,6 +596,7 @@ static int do_mmc_hwpartition(cmd_tbl_t *cmdtp, int flag, | ||||||
| 		return CMD_RET_FAILURE; | 		return CMD_RET_FAILURE; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_SUPPORT_EMMC_BOOT | #ifdef CONFIG_SUPPORT_EMMC_BOOT | ||||||
| static int do_mmc_bootbus(cmd_tbl_t *cmdtp, int flag, | 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[] = { | static cmd_tbl_t cmd_mmc[] = { | ||||||
| 	U_BOOT_CMD_MKENT(info, 1, 0, do_mmcinfo, "", ""), | 	U_BOOT_CMD_MKENT(info, 1, 0, do_mmcinfo, "", ""), | ||||||
| 	U_BOOT_CMD_MKENT(read, 4, 1, do_mmc_read, "", ""), | 	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(write, 4, 0, do_mmc_write, "", ""), | ||||||
| 	U_BOOT_CMD_MKENT(erase, 3, 0, do_mmc_erase, "", ""), | 	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(rescan, 1, 1, do_mmc_rescan, "", ""), | ||||||
| 	U_BOOT_CMD_MKENT(part, 1, 1, do_mmc_part, "", ""), | 	U_BOOT_CMD_MKENT(part, 1, 1, do_mmc_part, "", ""), | ||||||
| 	U_BOOT_CMD_MKENT(dev, 3, 0, do_mmc_dev, "", ""), | 	U_BOOT_CMD_MKENT(dev, 3, 0, do_mmc_dev, "", ""), | ||||||
| 	U_BOOT_CMD_MKENT(list, 1, 1, do_mmc_list, "", ""), | 	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, "", ""), | 	U_BOOT_CMD_MKENT(hwpartition, 28, 0, do_mmc_hwpartition, "", ""), | ||||||
|  | #endif | ||||||
| #ifdef CONFIG_SUPPORT_EMMC_BOOT | #ifdef CONFIG_SUPPORT_EMMC_BOOT | ||||||
| 	U_BOOT_CMD_MKENT(bootbus, 5, 0, do_mmc_bootbus, "", ""), | 	U_BOOT_CMD_MKENT(bootbus, 5, 0, do_mmc_bootbus, "", ""), | ||||||
| 	U_BOOT_CMD_MKENT(bootpart-resize, 4, 0, do_mmc_boot_resize, "", ""), | 	U_BOOT_CMD_MKENT(bootpart-resize, 4, 0, do_mmc_boot_resize, "", ""), | ||||||
|  |  | ||||||
|  | @ -110,7 +110,7 @@ static ulong get_load_addr(void) | ||||||
| /********************************************************************
 | /********************************************************************
 | ||||||
|  *     eMMC services |  *     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) | static int mmc_burn_image(size_t image_size) | ||||||
| { | { | ||||||
| 	struct mmc	*mmc; | 	struct mmc	*mmc; | ||||||
|  |  | ||||||
|  | @ -109,6 +109,7 @@ obj-$(CONFIG_IO_TRACE) += iotrace.o | ||||||
| obj-y += memsize.o | obj-y += memsize.o | ||||||
| obj-y += stdio.o | obj-y += stdio.o | ||||||
| 
 | 
 | ||||||
|  | ifndef CONFIG_SPL_BUILD | ||||||
| # This option is not just y/n - it can have a numeric value
 | # This option is not just y/n - it can have a numeric value
 | ||||||
| ifdef CONFIG_FASTBOOT_FLASH | ifdef CONFIG_FASTBOOT_FLASH | ||||||
| obj-y += image-sparse.o | obj-y += image-sparse.o | ||||||
|  | @ -119,6 +120,7 @@ ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV | ||||||
| obj-y += fb_nand.o | obj-y += fb_nand.o | ||||||
| endif | endif | ||||||
| endif | endif | ||||||
|  | endif | ||||||
| 
 | 
 | ||||||
| ifdef CONFIG_CMD_EEPROM_LAYOUT | ifdef CONFIG_CMD_EEPROM_LAYOUT | ||||||
| obj-y += eeprom/eeprom_field.o eeprom/eeprom_layout.o | obj-y += eeprom/eeprom_field.o eeprom/eeprom_layout.o | ||||||
|  |  | ||||||
|  | @ -301,6 +301,7 @@ config SPL_ENV_SUPPORT | ||||||
| config SPL_SAVEENV | config SPL_SAVEENV | ||||||
| 	bool "Support save environment" | 	bool "Support save environment" | ||||||
| 	depends on SPL_ENV_SUPPORT | 	depends on SPL_ENV_SUPPORT | ||||||
|  | 	select SPL_MMC_WRITE if ENV_IS_IN_MMC | ||||||
| 	help | 	help | ||||||
| 	  Enable save environment support in SPL after setenv. By default | 	  Enable save environment support in SPL after setenv. By default | ||||||
| 	  the saveenv option is not provided in SPL, but some boards need | 	  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 | 	  this option to build the drivers in drivers/mmc as part of an SPL | ||||||
| 	  build. | 	  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 | config SPL_MPC8XXX_INIT_DDR_SUPPORT | ||||||
| 	bool "Support MPC8XXX DDR init" | 	bool "Support MPC8XXX DDR init" | ||||||
| 	help | 	help | ||||||
|  |  | ||||||
|  | @ -13,10 +13,12 @@ CONFIG_ANDROID_BOOT_IMAGE=y | ||||||
| CONFIG_FIT_IMAGE_POST_PROCESS=y | CONFIG_FIT_IMAGE_POST_PROCESS=y | ||||||
| CONFIG_SPL_LOAD_FIT=y | CONFIG_SPL_LOAD_FIT=y | ||||||
| CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y | CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y | ||||||
|  | CONFIG_LOGLEVEL=3 | ||||||
| CONFIG_SYS_CONSOLE_INFO_QUIET=y | CONFIG_SYS_CONSOLE_INFO_QUIET=y | ||||||
| CONFIG_VERSION_VARIABLE=y | CONFIG_VERSION_VARIABLE=y | ||||||
| CONFIG_ARCH_MISC_INIT=y | CONFIG_ARCH_MISC_INIT=y | ||||||
| CONFIG_SPL=y | CONFIG_SPL=y | ||||||
|  | CONFIG_SPL_FIT_IMAGE_TINY=y | ||||||
| # CONFIG_SPL_ENV_SUPPORT is not set | # CONFIG_SPL_ENV_SUPPORT is not set | ||||||
| # CONFIG_SPL_EXT_SUPPORT is not set | # CONFIG_SPL_EXT_SUPPORT is not set | ||||||
| CONFIG_SPL_MTD_SUPPORT=y | CONFIG_SPL_MTD_SUPPORT=y | ||||||
|  | @ -37,6 +39,7 @@ CONFIG_DFU_RAM=y | ||||||
| CONFIG_DM_I2C=y | CONFIG_DM_I2C=y | ||||||
| CONFIG_MISC=y | CONFIG_MISC=y | ||||||
| CONFIG_DM_MMC=y | CONFIG_DM_MMC=y | ||||||
|  | # CONFIG_MMC_HW_PARTITIONING is not set | ||||||
| CONFIG_MMC_OMAP_HS=y | CONFIG_MMC_OMAP_HS=y | ||||||
| CONFIG_NAND=y | CONFIG_NAND=y | ||||||
| CONFIG_SPI_FLASH=y | CONFIG_SPI_FLASH=y | ||||||
|  | @ -60,5 +63,6 @@ CONFIG_USB_GADGET_VENDOR_NUM=0x0451 | ||||||
| CONFIG_USB_GADGET_PRODUCT_NUM=0xd022 | CONFIG_USB_GADGET_PRODUCT_NUM=0xd022 | ||||||
| CONFIG_USB_GADGET_DOWNLOAD=y | CONFIG_USB_GADGET_DOWNLOAD=y | ||||||
| CONFIG_USB_ETHER=y | CONFIG_USB_ETHER=y | ||||||
|  | CONFIG_SPL_TINY_MEMSET=y | ||||||
| CONFIG_RSA=y | CONFIG_RSA=y | ||||||
| CONFIG_LZO=y | CONFIG_LZO=y | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ CONFIG_SPL_MMC_SUPPORT=y | ||||||
| CONFIG_SPL_SERIAL_SUPPORT=y | CONFIG_SPL_SERIAL_SUPPORT=y | ||||||
| CONFIG_SPL_NAND_SUPPORT=y | CONFIG_SPL_NAND_SUPPORT=y | ||||||
| CONFIG_BOOTDELAY=3 | CONFIG_BOOTDELAY=3 | ||||||
|  | CONFIG_LOGLEVEL=3 | ||||||
| CONFIG_VERSION_VARIABLE=y | CONFIG_VERSION_VARIABLE=y | ||||||
| # CONFIG_DISPLAY_CPUINFO is not set | # CONFIG_DISPLAY_CPUINFO is not set | ||||||
| # CONFIG_DISPLAY_BOARDINFO is not set | # CONFIG_DISPLAY_BOARDINFO is not set | ||||||
|  |  | ||||||
|  | @ -25,6 +25,7 @@ CONFIG_CMD_UBI=y | ||||||
| CONFIG_ISO_PARTITION=y | CONFIG_ISO_PARTITION=y | ||||||
| CONFIG_ENV_IS_IN_NAND=y | CONFIG_ENV_IS_IN_NAND=y | ||||||
| CONFIG_MVSATA_IDE=y | CONFIG_MVSATA_IDE=y | ||||||
|  | # CONFIG_MMC_HW_PARTITIONING is not set | ||||||
| CONFIG_SYS_NS16550=y | CONFIG_SYS_NS16550=y | ||||||
| CONFIG_USB=y | CONFIG_USB=y | ||||||
| CONFIG_USB_EHCI_HCD=y | CONFIG_USB_EHCI_HCD=y | ||||||
|  |  | ||||||
|  | @ -25,6 +25,7 @@ CONFIG_CMD_UBI=y | ||||||
| CONFIG_ISO_PARTITION=y | CONFIG_ISO_PARTITION=y | ||||||
| CONFIG_ENV_IS_IN_NAND=y | CONFIG_ENV_IS_IN_NAND=y | ||||||
| CONFIG_MVSATA_IDE=y | CONFIG_MVSATA_IDE=y | ||||||
|  | # CONFIG_MMC_HW_PARTITIONING is not set | ||||||
| CONFIG_SYS_NS16550=y | CONFIG_SYS_NS16550=y | ||||||
| CONFIG_USB=y | CONFIG_USB=y | ||||||
| CONFIG_USB_EHCI_HCD=y | CONFIG_USB_EHCI_HCD=y | ||||||
|  |  | ||||||
|  | @ -25,6 +25,7 @@ CONFIG_CMD_UBI=y | ||||||
| CONFIG_ISO_PARTITION=y | CONFIG_ISO_PARTITION=y | ||||||
| CONFIG_ENV_IS_IN_NAND=y | CONFIG_ENV_IS_IN_NAND=y | ||||||
| CONFIG_MVSATA_IDE=y | CONFIG_MVSATA_IDE=y | ||||||
|  | # CONFIG_MMC_HW_PARTITIONING is not set | ||||||
| CONFIG_SYS_NS16550=y | CONFIG_SYS_NS16550=y | ||||||
| CONFIG_USB=y | CONFIG_USB=y | ||||||
| CONFIG_USB_EHCI_HCD=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 | 	  If you want MMC/SD/SDIO support, you should say Y here and | ||||||
| 	  also to your specific host controller driver. | 	  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 | config DM_MMC | ||||||
| 	bool "Enable MMC controllers using Driver Model" | 	bool "Enable MMC controllers using Driver Model" | ||||||
| 	depends on DM | 	depends on DM | ||||||
|  | @ -42,6 +49,75 @@ config ARM_PL180_MMCI | ||||||
| 	  If you have an ARM(R) platform with a Multimedia Card slot, | 	  If you have an ARM(R) platform with a Multimedia Card slot, | ||||||
| 	  say Y or M here. | 	  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 | config SPL_MMC_TINY | ||||||
| 	bool "Tiny MMC framework in SPL" | 	bool "Tiny MMC framework in SPL" | ||||||
| 	help | 	help | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ | ||||||
| 
 | 
 | ||||||
| obj-y += mmc.o | obj-y += mmc.o | ||||||
| obj-$(CONFIG_$(SPL_)DM_MMC) += mmc-uclass.o | obj-$(CONFIG_$(SPL_)DM_MMC) += mmc-uclass.o | ||||||
|  | obj-$(CONFIG_$(SPL_)MMC_WRITE) += mmc_write.o | ||||||
| 
 | 
 | ||||||
| ifndef CONFIG_$(SPL_)BLK | ifndef CONFIG_$(SPL_)BLK | ||||||
| obj-y += mmc_legacy.o | obj-y += mmc_legacy.o | ||||||
|  | @ -16,9 +17,6 @@ obj-$(CONFIG_SUPPORT_EMMC_BOOT) += mmc_boot.o | ||||||
| 
 | 
 | ||||||
| ifdef CONFIG_SPL_BUILD | ifdef CONFIG_SPL_BUILD | ||||||
| obj-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o | obj-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o | ||||||
| obj-$(CONFIG_SPL_SAVEENV) += mmc_write.o |  | ||||||
| else |  | ||||||
| obj-y += mmc_write.o |  | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
| obj-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o | 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) { | 	if (host->dev_index > 4) { | ||||||
| 		printf("DWMMC%d: Can't get the dev index\n", host->dev_index); | 		printf("DWMMC%d: Can't get the dev index\n", host->dev_index); | ||||||
|  | 		free(priv); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -178,6 +179,7 @@ static int exynos_dwmci_get_config(const void *blob, int node, | ||||||
| 	base = fdtdec_get_addr(blob, node, "reg"); | 	base = fdtdec_get_addr(blob, node, "reg"); | ||||||
| 	if (!base) { | 	if (!base) { | ||||||
| 		printf("DWMMC%d: Can't get base address\n", host->dev_index); | 		printf("DWMMC%d: Can't get base address\n", host->dev_index); | ||||||
|  | 		free(priv); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 	host->ioaddr = (void *)base; | 	host->ioaddr = (void *)base; | ||||||
|  | @ -187,6 +189,7 @@ static int exynos_dwmci_get_config(const void *blob, int node, | ||||||
| 	if (err) { | 	if (err) { | ||||||
| 		printf("DWMMC%d: Can't get sdr-timings for devider\n", | 		printf("DWMMC%d: Can't get sdr-timings for devider\n", | ||||||
| 				host->dev_index); | 				host->dev_index); | ||||||
|  | 		free(priv); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -647,7 +647,11 @@ static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) | ||||||
| 	esdhc_write32(®s->clktunectrlstatus, 0x0); | 	esdhc_write32(®s->clktunectrlstatus, 0x0); | ||||||
| 
 | 
 | ||||||
| 	/* Put VEND_SPEC to default value */ | 	/* 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 */ | 	/* Disable DLL_CTRL delay line */ | ||||||
| 	esdhc_write32(®s->dllctrl, 0x0); | 	esdhc_write32(®s->dllctrl, 0x0); | ||||||
|  | @ -665,7 +669,7 @@ static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 	/* Set the initial clock speed */ | 	/* Set the initial clock speed */ | ||||||
| 	mmc_set_clock(mmc, 400000); | 	mmc_set_clock(mmc, 400000, false); | ||||||
| 
 | 
 | ||||||
| 	/* Disable the BRR and BWR bits in IRQSTAT */ | 	/* Disable the BRR and BWR bits in IRQSTAT */ | ||||||
| 	esdhc_clrbits32(®s->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR); | 	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 */ | 	/* Set timout to the maximum value */ | ||||||
| 	esdhc_clrsetbits32(®s->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16); | 	esdhc_clrsetbits32(®s->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16); | ||||||
| 
 | 
 | ||||||
| 	if (priv->vs18_enable) |  | ||||||
| 		esdhc_setbits32(®s->vendorspec, ESDHC_VENDORSPEC_VSELECT); |  | ||||||
| 
 |  | ||||||
| 	return 0; | 	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); | 	      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 */ | /* Setup for MCI Clock and Block Size */ | ||||||
| #ifdef CONFIG_DM_MMC | #ifdef CONFIG_DM_MMC | ||||||
| static void mci_set_mode(struct udevice *dev, u32 hz, u32 blklen) | 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); | 		priv->curr_clk = bus_hz / (clkdiv * 2 + clkodd + 2); | ||||||
| 	else | 	else | ||||||
| 		priv->curr_clk = (bus_hz / (clkdiv + 1)) / 2; | 		priv->curr_clk = (bus_hz / (clkdiv + 1)) / 2; | ||||||
| 	blklen &= 0xfffc; |  | ||||||
| 
 | 
 | ||||||
| 	mr = MMCI_BF(CLKDIV, clkdiv); | 	mr = MMCI_BF(CLKDIV, clkdiv); | ||||||
| 
 | 
 | ||||||
|  | @ -138,14 +151,10 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen) | ||||||
| 	 */ | 	 */ | ||||||
| 	if (version >= 0x500) | 	if (version >= 0x500) | ||||||
| 		mr |= MMCI_BF(CLKODD, clkodd); | 		mr |= MMCI_BF(CLKODD, clkodd); | ||||||
| 	else |  | ||||||
| 		mr |= MMCI_BF(BLKLEN, blklen); |  | ||||||
| 
 | 
 | ||||||
| 	writel(mr, &mci->mr); | 	writel(mr, &mci->mr); | ||||||
| 
 | 
 | ||||||
| 	/* MCI IP version >= 0x200 has blkr */ | 	mci_set_blklen(mci, blklen); | ||||||
| 	if (version >= 0x200) |  | ||||||
| 		writel(MMCI_BF(BLKLEN, blklen), &mci->blkr); |  | ||||||
| 
 | 
 | ||||||
| 	if (mmc->card_caps & mmc->cfg->host_caps & MMC_MODE_HS) | 	if (mmc->card_caps & mmc->cfg->host_caps & MMC_MODE_HS) | ||||||
| 		writel(MMCI_BIT(HSMODE), &mci->cfg); | 		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_plat *plat = dev_get_platdata(dev); | ||||||
| 	struct atmel_mci_priv *priv = dev_get_priv(dev); | 	struct atmel_mci_priv *priv = dev_get_priv(dev); | ||||||
| 	struct mmc *mmc = mmc_get_mmc_dev(dev); |  | ||||||
| 	atmel_mci_t *mci = plat->mci; | 	atmel_mci_t *mci = plat->mci; | ||||||
| #else | #else | ||||||
| static int | 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 */ | 	/* Figure out the transfer arguments */ | ||||||
| 	cmdr = mci_encode_cmd(cmd, data, &error_flags); | 	cmdr = mci_encode_cmd(cmd, data, &error_flags); | ||||||
| 
 | 
 | ||||||
|  | 	mci_set_blklen(mci, data->blocksize); | ||||||
|  | 
 | ||||||
| 	/* For multi blocks read/write, set the block register */ | 	/* For multi blocks read/write, set the block register */ | ||||||
| 	if ((cmd->cmdidx == MMC_CMD_READ_MULTIPLE_BLOCK) | 	if ((cmd->cmdidx == MMC_CMD_READ_MULTIPLE_BLOCK) | ||||||
| 			|| (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK)) | 			|| (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK)) | ||||||
| 		writel(data->blocks | MMCI_BF(BLKLEN, mmc->read_bl_len), | 		writel(data->blocks | MMCI_BF(BLKLEN, data->blocksize), | ||||||
| 			&mci->blkr); | 		       &mci->blkr); | ||||||
| 
 | 
 | ||||||
| 	/* Send the command */ | 	/* Send the command */ | ||||||
| 	writel(cmd->cmdarg, &mci->argr); | 	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) { | 	if (data) { | ||||||
| 		u32 word_count, block_count; | 		u32 word_count, block_count; | ||||||
| 		u32* ioptr; | 		u32* ioptr; | ||||||
| 		u32 sys_blocksize, dummy, i; | 		u32 i; | ||||||
| 		u32 (*mci_data_op) | 		u32 (*mci_data_op) | ||||||
| 			(atmel_mci_t *mci, u32* data, u32 error_flags); | 			(atmel_mci_t *mci, u32* data, u32 error_flags); | ||||||
| 
 | 
 | ||||||
| 		if (data->flags & MMC_DATA_READ) { | 		if (data->flags & MMC_DATA_READ) { | ||||||
| 			mci_data_op = mci_data_read; | 			mci_data_op = mci_data_read; | ||||||
| 			sys_blocksize = mmc->read_bl_len; |  | ||||||
| 			ioptr = (u32*)data->dest; | 			ioptr = (u32*)data->dest; | ||||||
| 		} else { | 		} else { | ||||||
| 			mci_data_op = mci_data_write; | 			mci_data_op = mci_data_write; | ||||||
| 			sys_blocksize = mmc->write_bl_len; |  | ||||||
| 			ioptr = (u32*)data->src; | 			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); | 					     1, cnt, 0); | ||||||
| 			} | 			} | ||||||
| #endif | #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) { | 			if (status) { | ||||||
| 				dump_cmd(cmdr, cmd->cmdarg, status, | 				dump_cmd(cmdr, cmd->cmdarg, status, | ||||||
| 					"Data Transfer Failed"); | 					"Data Transfer Failed"); | ||||||
|  |  | ||||||
|  | @ -250,7 +250,7 @@ static int meson_mmc_probe(struct udevice *dev) | ||||||
| 	mmc->priv = pdata; | 	mmc->priv = pdata; | ||||||
| 	upriv->mmc = mmc; | 	upriv->mmc = mmc; | ||||||
| 
 | 
 | ||||||
| 	mmc_set_clock(mmc, cfg->f_min); | 	mmc_set_clock(mmc, cfg->f_min, false); | ||||||
| 
 | 
 | ||||||
| 	/* reset all status bits */ | 	/* reset all status bits */ | ||||||
| 	meson_write(mmc, STATUS_MASK, MESON_SD_EMMC_STATUS); | 	meson_write(mmc, STATUS_MASK, MESON_SD_EMMC_STATUS); | ||||||
|  |  | ||||||
|  | @ -10,7 +10,6 @@ | ||||||
| #include <dm.h> | #include <dm.h> | ||||||
| #include <dm/device-internal.h> | #include <dm/device-internal.h> | ||||||
| #include <dm/lists.h> | #include <dm/lists.h> | ||||||
| #include <dm/root.h> |  | ||||||
| #include "mmc_private.h" | #include "mmc_private.h" | ||||||
| 
 | 
 | ||||||
| DECLARE_GLOBAL_DATA_PTR; | DECLARE_GLOBAL_DATA_PTR; | ||||||
|  | @ -51,6 +50,35 @@ int mmc_set_ios(struct mmc *mmc) | ||||||
| 	return dm_mmc_set_ios(mmc->dev); | 	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) | int dm_mmc_get_wp(struct udevice *dev) | ||||||
| { | { | ||||||
| 	struct dm_mmc_ops *ops = mmc_get_ops(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); | 	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 *mmc_get_mmc_dev(struct udevice *dev) | ||||||
| { | { | ||||||
| 	struct mmc_uclass_priv *upriv; | 	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 = { | static const struct blk_ops mmc_blk_ops = { | ||||||
| 	.read	= mmc_bread, | 	.read	= mmc_bread, | ||||||
| #ifndef CONFIG_SPL_BUILD | #if CONFIG_IS_ENABLED(MMC_WRITE) | ||||||
| 	.write	= mmc_bwrite, | 	.write	= mmc_bwrite, | ||||||
| 	.erase	= mmc_berase, | 	.erase	= mmc_berase, | ||||||
| #endif | #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); | 		void *dst); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #if !(defined(CONFIG_SPL_BUILD) && !defined(CONFIG_SPL_SAVEENV)) | #if CONFIG_IS_ENABLED(MMC_WRITE) | ||||||
| 
 | 
 | ||||||
| #if CONFIG_IS_ENABLED(BLK) | #if CONFIG_IS_ENABLED(BLK) | ||||||
| ulong mmc_bwrite(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, | 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); | ulong mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt); | ||||||
| #endif | #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. */ | /* declare dummies to reduce code size. */ | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -28,9 +28,9 @@ | ||||||
| #include <mmc.h> | #include <mmc.h> | ||||||
| #include <part.h> | #include <part.h> | ||||||
| #include <i2c.h> | #include <i2c.h> | ||||||
| #include <twl4030.h> | #if defined(CONFIG_OMAP54XX) || defined(CONFIG_OMAP44XX) | ||||||
| #include <twl6030.h> |  | ||||||
| #include <palmas.h> | #include <palmas.h> | ||||||
|  | #endif | ||||||
| #include <asm/io.h> | #include <asm/io.h> | ||||||
| #include <asm/arch/mmc_host_def.h> | #include <asm/arch/mmc_host_def.h> | ||||||
| #if !defined(CONFIG_SOC_KEYSTONE) | #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 */ | 		cmd->response[1] = 10 << 16;	/* 1 << block_len */ | ||||||
| 		break; | 		break; | ||||||
| 	case SD_CMD_SWITCH_FUNC: { | 	case SD_CMD_SWITCH_FUNC: { | ||||||
|  | 		if (!data) | ||||||
|  | 			break; | ||||||
| 		u32 *resp = (u32 *)data->dest; | 		u32 *resp = (u32 *)data->dest; | ||||||
| 
 |  | ||||||
| 		resp[7] = cpu_to_be32(SD_HIGHSPEED_BUSY); | 		resp[7] = cpu_to_be32(SD_HIGHSPEED_BUSY); | ||||||
|  | 		if ((cmd->cmdarg & 0xF) == UHS_SDR12_BUS_SPEED) | ||||||
|  | 			resp[4] = (cmd->cmdarg & 0xF) << 24; | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 	case MMC_CMD_READ_SINGLE_BLOCK: | 	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 */ | 	/* Timeout unit - ms */ | ||||||
| 	static unsigned int cmd_timeout = SDHCI_CMD_DEFAULT_TIMEOUT; | 	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; | 	mask = SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT; | ||||||
| 
 | 
 | ||||||
| 	/* We shouldn't wait for data inihibit for stop commands, even
 | 	/* 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); | 		udelay(1000); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS); | ||||||
|  | 
 | ||||||
| 	mask = SDHCI_INT_RESPONSE; | 	mask = SDHCI_INT_RESPONSE; | ||||||
| 	if (!(cmd->resp_type & MMC_RSP_PRESENT)) | 	if (!(cmd->resp_type & MMC_RSP_PRESENT)) | ||||||
| 		flags = SDHCI_CMD_RESP_NONE; | 		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; | 		flags |= SDHCI_CMD_DATA; | ||||||
| 
 | 
 | ||||||
| 	/* Set Transfer mode regarding to data flag */ | 	/* Set Transfer mode regarding to data flag */ | ||||||
| 	if (data != 0) { | 	if (data) { | ||||||
| 		sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL); | 		sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL); | ||||||
| 		mode = SDHCI_TRNS_BLK_CNT_EN; | 		mode = SDHCI_TRNS_BLK_CNT_EN; | ||||||
| 		trans_bytes = data->blocks * data->blocksize; | 		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); | 	sdhci_writel(host, cmd->cmdarg, SDHCI_ARGUMENT); | ||||||
| #ifdef CONFIG_MMC_SDHCI_SDMA | #ifdef CONFIG_MMC_SDHCI_SDMA | ||||||
| 	if (data != 0) { | 	if (data) { | ||||||
| 		trans_bytes = ALIGN(trans_bytes, CONFIG_SYS_CACHELINE_SIZE); | 		trans_bytes = ALIGN(trans_bytes, CONFIG_SYS_CACHELINE_SIZE); | ||||||
| 		flush_cache(start_addr, trans_bytes); | 		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; | 	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 *pmic_alloc(void) | ||||||
| { | { | ||||||
| 	struct pmic *p; | 	struct pmic *p; | ||||||
|  | @ -108,7 +78,33 @@ struct pmic *pmic_get(const char *s) | ||||||
| 	return NULL; | 	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", "|+|-|"}; | 	const char *power_interface[] = {"I2C", "SPI", "|+|-|"}; | ||||||
| 	return power_interface[interface]; | 	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; | 	u32 ret, reg, val; | ||||||
| 	char *cmd, *name; | 	char *cmd, *name; | ||||||
|  | @ -221,3 +217,4 @@ U_BOOT_CMD( | ||||||
| 	"pmic name bat state - write register\n" | 	"pmic name bat state - write register\n" | ||||||
| 	"pmic name bat charge - 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 <linux/compiler.h> | ||||||
| #include <part.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 */ | /* SD/MMC version bits; 8 flags, 8 major, 8 minor, 8 change */ | ||||||
| #define SD_VERSION_SD	(1U << 31) | #define SD_VERSION_SD	(1U << 31) | ||||||
| #define MMC_VERSION_MMC	(1U << 30) | #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_0		MAKE_MMC_VERSION(5, 0, 0) | ||||||
| #define MMC_VERSION_5_1		MAKE_MMC_VERSION(5, 1, 0) | #define MMC_VERSION_5_1		MAKE_MMC_VERSION(5, 1, 0) | ||||||
| 
 | 
 | ||||||
| #define MMC_MODE_HS		(1 << 0) | #define MMC_CAP(mode)		(1 << mode) | ||||||
| #define MMC_MODE_HS_52MHz	(1 << 1) | #define MMC_MODE_HS		(MMC_CAP(MMC_HS) | MMC_CAP(SD_HS)) | ||||||
| #define MMC_MODE_4BIT		(1 << 2) | #define MMC_MODE_HS_52MHz	MMC_CAP(MMC_HS_52) | ||||||
| #define MMC_MODE_8BIT		(1 << 3) | #define MMC_MODE_DDR_52MHz	MMC_CAP(MMC_DDR_52) | ||||||
| #define MMC_MODE_SPI		(1 << 4) | #define MMC_MODE_HS200		MMC_CAP(MMC_HS_200) | ||||||
| #define MMC_MODE_DDR_52MHz	(1 << 5) | 
 | ||||||
|  | #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 | #define SD_DATA_4BIT	0x00040000 | ||||||
| 
 | 
 | ||||||
|  | @ -82,6 +94,8 @@ | ||||||
| #define MMC_CMD_SET_BLOCKLEN		16 | #define MMC_CMD_SET_BLOCKLEN		16 | ||||||
| #define MMC_CMD_READ_SINGLE_BLOCK	17 | #define MMC_CMD_READ_SINGLE_BLOCK	17 | ||||||
| #define MMC_CMD_READ_MULTIPLE_BLOCK	18 | #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_SET_BLOCK_COUNT         23 | ||||||
| #define MMC_CMD_WRITE_SINGLE_BLOCK	24 | #define MMC_CMD_WRITE_SINGLE_BLOCK	24 | ||||||
| #define MMC_CMD_WRITE_MULTIPLE_BLOCK	25 | #define MMC_CMD_WRITE_MULTIPLE_BLOCK	25 | ||||||
|  | @ -109,12 +123,34 @@ | ||||||
| #define SD_CMD_APP_SEND_OP_COND		41 | #define SD_CMD_APP_SEND_OP_COND		41 | ||||||
| #define SD_CMD_APP_SEND_SCR		51 | #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 */ | /* SCR definitions in different words */ | ||||||
| #define SD_HIGHSPEED_BUSY	0x00020000 | #define SD_HIGHSPEED_BUSY	0x00020000 | ||||||
| #define SD_HIGHSPEED_SUPPORTED	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_BUSY		0x80000000 | ||||||
| #define OCR_HCS			0x40000000 | #define OCR_HCS			0x40000000 | ||||||
|  | #define OCR_S18R		0x1000000 | ||||||
| #define OCR_VOLTAGE_MASK	0x007FFF80 | #define OCR_VOLTAGE_MASK	0x007FFF80 | ||||||
| #define OCR_ACCESS_MODE		0x60000000 | #define OCR_ACCESS_MODE		0x60000000 | ||||||
| 
 | 
 | ||||||
|  | @ -206,11 +242,23 @@ | ||||||
| #define EXT_CSD_CARD_TYPE_DDR_52	(EXT_CSD_CARD_TYPE_DDR_1_8V \ | #define EXT_CSD_CARD_TYPE_DDR_52	(EXT_CSD_CARD_TYPE_DDR_1_8V \ | ||||||
| 					| EXT_CSD_CARD_TYPE_DDR_1_2V) | 					| 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_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_4	1	/* Card is in 4 bit mode */ | ||||||
| #define EXT_CSD_BUS_WIDTH_8	2	/* Card is in 8 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_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_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_ACK_ENABLE			(1 << 6) | ||||||
| #define EXT_CSD_BOOT_PARTITION_ENABLE		(1 << 3) | #define EXT_CSD_BOOT_PARTITION_ENABLE		(1 << 3) | ||||||
|  | @ -265,6 +313,20 @@ | ||||||
| #define ENHNCD_SUPPORT		(0x2) | #define ENHNCD_SUPPORT		(0x2) | ||||||
| #define PART_ENH_ATTRIB		(0x1f) | #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 */ | /* Maximum block size for MMC */ | ||||||
| #define MMC_MAX_BLOCK_LEN	512 | #define MMC_MAX_BLOCK_LEN	512 | ||||||
| 
 | 
 | ||||||
|  | @ -346,6 +408,14 @@ struct dm_mmc_ops { | ||||||
| 	 */ | 	 */ | ||||||
| 	int (*set_ios)(struct udevice *dev); | 	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 | 	 * 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 | 	 * @return 0 if write-enabled, 1 if write-protected, -ve on error | ||||||
| 	 */ | 	 */ | ||||||
| 	int (*get_wp)(struct udevice *dev); | 	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) | #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, | int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, | ||||||
| 		    struct mmc_data *data); | 		    struct mmc_data *data); | ||||||
| int dm_mmc_set_ios(struct udevice *dev); | 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_cd(struct udevice *dev); | ||||||
| int dm_mmc_get_wp(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 */ | /* Transition functions for compatibility */ | ||||||
| int mmc_set_ios(struct mmc *mmc); | int mmc_set_ios(struct mmc *mmc); | ||||||
|  | void mmc_send_init_stream(struct mmc *mmc); | ||||||
| int mmc_getcd(struct mmc *mmc); | int mmc_getcd(struct mmc *mmc); | ||||||
| int mmc_getwp(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 | #else | ||||||
| struct mmc_ops { | struct mmc_ops { | ||||||
|  | @ -406,6 +506,50 @@ struct sd_ssr { | ||||||
| 	unsigned int erase_offset;	/* In milliseconds */ | 	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 CONFIG_DM_MMC enabled, struct mmc can be accessed from the MMC device | ||||||
|  * with mmc_get_mmc_dev(). |  * with mmc_get_mmc_dev(). | ||||||
|  | @ -421,9 +565,12 @@ struct mmc { | ||||||
| 	void *priv; | 	void *priv; | ||||||
| 	uint has_init; | 	uint has_init; | ||||||
| 	int high_capacity; | 	int high_capacity; | ||||||
|  | 	bool clk_disable; /* true if the clock can be turned off */ | ||||||
| 	uint bus_width; | 	uint bus_width; | ||||||
| 	uint clock; | 	uint clock; | ||||||
|  | 	enum mmc_voltage signal_voltage; | ||||||
| 	uint card_caps; | 	uint card_caps; | ||||||
|  | 	uint host_caps; | ||||||
| 	uint ocr; | 	uint ocr; | ||||||
| 	uint dsr; | 	uint dsr; | ||||||
| 	uint dsr_imp; | 	uint dsr_imp; | ||||||
|  | @ -436,18 +583,27 @@ struct mmc { | ||||||
| 	u8 wr_rel_set; | 	u8 wr_rel_set; | ||||||
| 	u8 part_config; | 	u8 part_config; | ||||||
| 	uint tran_speed; | 	uint tran_speed; | ||||||
|  | 	uint legacy_speed; /* speed for the legacy mode provided by the card */ | ||||||
| 	uint read_bl_len; | 	uint read_bl_len; | ||||||
|  | #if CONFIG_IS_ENABLED(MMC_WRITE) | ||||||
| 	uint write_bl_len; | 	uint write_bl_len; | ||||||
| 	uint erase_grp_size;	/* in 512-byte sectors */ | 	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 */ | 	uint hc_wp_grp_size;	/* in 512-byte sectors */ | ||||||
|  | #endif | ||||||
|  | #if CONFIG_IS_ENABLED(MMC_WRITE) | ||||||
| 	struct sd_ssr	ssr;	/* SD status register */ | 	struct sd_ssr	ssr;	/* SD status register */ | ||||||
|  | #endif | ||||||
| 	u64 capacity; | 	u64 capacity; | ||||||
| 	u64 capacity_user; | 	u64 capacity_user; | ||||||
| 	u64 capacity_boot; | 	u64 capacity_boot; | ||||||
| 	u64 capacity_rpmb; | 	u64 capacity_rpmb; | ||||||
| 	u64 capacity_gp[4]; | 	u64 capacity_gp[4]; | ||||||
|  | #ifndef CONFIG_SPL_BUILD | ||||||
| 	u64 enh_user_start; | 	u64 enh_user_start; | ||||||
| 	u64 enh_user_size; | 	u64 enh_user_size; | ||||||
|  | #endif | ||||||
| #if !CONFIG_IS_ENABLED(BLK) | #if !CONFIG_IS_ENABLED(BLK) | ||||||
| 	struct blk_desc block_dev; | 	struct blk_desc block_dev; | ||||||
| #endif | #endif | ||||||
|  | @ -457,7 +613,21 @@ struct mmc { | ||||||
| 	int ddr_mode; | 	int ddr_mode; | ||||||
| #if CONFIG_IS_ENABLED(DM_MMC) | #if CONFIG_IS_ENABLED(DM_MMC) | ||||||
| 	struct udevice *dev;	/* Device for this MMC controller */ | 	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 | ||||||
|  | #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 { | struct mmc_hwpart_conf { | ||||||
|  | @ -507,8 +677,36 @@ void mmc_destroy(struct mmc *mmc); | ||||||
| int mmc_unbind(struct udevice *dev); | int mmc_unbind(struct udevice *dev); | ||||||
| int mmc_initialize(bd_t *bis); | int mmc_initialize(bd_t *bis); | ||||||
| int mmc_init(struct mmc *mmc); | 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); | 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); | struct mmc *find_mmc_device(int dev_num); | ||||||
| int mmc_set_dev(int dev_num); | int mmc_set_dev(int dev_num); | ||||||
| void print_mmc_devices(char separator); | void print_mmc_devices(char separator); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue