X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=include%2Fmmc.h;h=1f30f71d25f8cda5ac77f6a6a9ca07fe9ed38d51;hb=a1e126bf8d44f898c4dc23569245b12b9ee4c667;hp=8d6e0f8fb04563e1795c53ae6878e5aa75765178;hpb=35f6782055c99410fbeae33ab28ea68de154360c;p=oweals%2Fu-boot.git diff --git a/include/mmc.h b/include/mmc.h index 8d6e0f8fb0..1f30f71d25 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -1,10 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright 2008,2010 Freescale Semiconductor, Inc * Andy Fleming * * Based (loosely) on the Linux code - * - * SPDX-License-Identifier: GPL-2.0+ */ #ifndef _MMC_H_ @@ -15,6 +14,13 @@ #include #include +#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) @@ -47,6 +53,7 @@ #define MMC_VERSION_4_1 MAKE_MMC_VERSION(4, 1, 0) #define MMC_VERSION_4_2 MAKE_MMC_VERSION(4, 2, 0) #define MMC_VERSION_4_3 MAKE_MMC_VERSION(4, 3, 0) +#define MMC_VERSION_4_4 MAKE_MMC_VERSION(4, 4, 0) #define MMC_VERSION_4_41 MAKE_MMC_VERSION(4, 4, 1) #define MMC_VERSION_4_5 MAKE_MMC_VERSION(4, 5, 0) #define MMC_VERSION_5_0 MAKE_MMC_VERSION(5, 0, 0) @@ -56,6 +63,8 @@ #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_HS400 MMC_CAP(MMC_HS_400) #define MMC_MODE_8BIT BIT(30) #define MMC_MODE_4BIT BIT(29) @@ -86,6 +95,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 @@ -113,12 +124,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 @@ -210,6 +243,17 @@ #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_CARD_TYPE_HS400_1_8V BIT(6) +#define EXT_CSD_CARD_TYPE_HS400_1_2V BIT(7) +#define EXT_CSD_CARD_TYPE_HS400 (EXT_CSD_CARD_TYPE_HS400_1_8V | \ + EXT_CSD_CARD_TYPE_HS400_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 */ @@ -219,6 +263,9 @@ #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_TIMING_HS400 3 /* HS400 */ + #define EXT_CSD_BOOT_ACK_ENABLE (1 << 6) #define EXT_CSD_BOOT_PARTITION_ENABLE (1 << 3) #define EXT_CSD_PARTITION_ACCESS_ENABLE (1 << 0) @@ -272,13 +319,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, - MMC_SIGNAL_VOLTAGE_180, - MMC_SIGNAL_VOLTAGE_330 + 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 @@ -383,6 +437,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) @@ -393,12 +471,16 @@ 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 { @@ -435,14 +517,15 @@ enum bus_mode { SD_LEGACY, MMC_HS, SD_HS, + MMC_HS_52, + MMC_DDR_52, UHS_SDR12, UHS_SDR25, UHS_SDR50, - UHS_SDR104, UHS_DDR50, - MMC_HS_52, - MMC_DDR_52, + UHS_SDR104, MMC_HS_200, + MMC_HS_400, MMC_MODES_END }; @@ -451,12 +534,33 @@ 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) || (mode == UHS_DDR50)) + if (mode == MMC_DDR_52) + return true; +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) + else if (mode == UHS_DDR50) return true; +#endif +#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) + else if (mode == MMC_HS_400) + 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(). @@ -477,6 +581,7 @@ struct mmc { uint clock; enum mmc_voltage signal_voltage; uint card_caps; + uint host_caps; uint ocr; uint dsr; uint dsr_imp; @@ -491,17 +596,25 @@ struct mmc { 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 @@ -517,7 +630,15 @@ struct mmc { #endif #endif u8 *ext_csd; - enum bus_mode selected_mode; + 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 { @@ -567,8 +688,33 @@ 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); + +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \ + CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \ + CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) +int mmc_deinit(struct mmc *mmc); +#endif + +/** + * 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); +/** + * 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 @@ -578,6 +724,9 @@ int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size); */ int mmc_set_clock(struct mmc *mmc, uint clock, bool disable); +#define MMC_CLK_ENABLE false +#define MMC_CLK_DISABLE true + struct mmc *find_mmc_device(int dev_num); int mmc_set_dev(int dev_num); void print_mmc_devices(char separator); @@ -616,10 +765,39 @@ int mmc_rpmb_read(struct mmc *mmc, void *addr, unsigned short blk, unsigned short cnt, unsigned char *key); int mmc_rpmb_write(struct mmc *mmc, void *addr, unsigned short blk, unsigned short cnt, unsigned char *key); + +/** + * mmc_rpmb_route_frames() - route RPMB data frames + * @mmc Pointer to a MMC device struct + * @req Request data frames + * @reqlen Length of data frames in bytes + * @rsp Supplied buffer for response data frames + * @rsplen Length of supplied buffer for response data frames + * + * The RPMB data frames are routed to/from some external entity, for + * example a Trusted Exectuion Environment in an arm TrustZone protected + * secure world. It's expected that it's the external entity who is in + * control of the RPMB key. + * + * Returns 0 on success, < 0 on error. + */ +int mmc_rpmb_route_frames(struct mmc *mmc, void *req, unsigned long reqlen, + void *rsp, unsigned long rsplen); + #ifdef CONFIG_CMD_BKOPS_ENABLE int mmc_set_bkops_enable(struct mmc *mmc); #endif +/** + * Start device initialization and return immediately; it does not block on + * polling OCR (operation condition register) status. Useful for checking + * the presence of SD/eMMC when no card detect logic is available. + * + * @param mmc Pointer to a MMC device struct + * @return 0 on success, <0 on error. + */ +int mmc_get_op_cond(struct mmc *mmc); + /** * Start device initialization and return immediately; it does not block on * polling OCR (operation condition register) status. Then you should call @@ -627,7 +805,7 @@ int mmc_set_bkops_enable(struct mmc *mmc); * initializatin. * * @param mmc Pointer to a MMC device struct - * @return 0 on success, IN_PROGRESS on waiting for OCR status, <0 on error. + * @return 0 on success, <0 on error. */ int mmc_start_init(struct mmc *mmc); @@ -656,6 +834,9 @@ void board_mmc_power_init(void); int board_mmc_init(bd_t *bis); int cpu_mmc_init(bd_t *bis); int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr); +# ifdef CONFIG_SYS_MMC_ENV_PART +extern uint mmc_get_env_part(struct mmc *mmc); +# endif int mmc_get_env_dev(void); /* Set block count limit because of 16 bit register limit on some hardware*/