Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mmc: core: Add host specific tuning support for SD HS mode

To support the need for host specific tuning for SD high-speed mode, let's
add two new optional callbacks, ->prepare|execute_sd_hs_tuning() and let's
call them when switching into the SD high-speed mode.

Note that, during the tuning process it's also needed for host drivers to
send commands to the SD card to verify that the tuning process succeeds.
Therefore, let's also share the corresponding functions from the core to
allow this.

Signed-off-by: Wenchao Chen <wenchao.chen@unisoc.com>
Link: https://lore.kernel.org/r/20230825091743.15613-2-wenchao.chen@unisoc.com
[Ulf: Dropped unnecessary function declarations and updated the commit msg]
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>

authored by

Wenchao Chen and committed by
Ulf Hansson
bac80683 48fe8fad

+23 -3
-1
drivers/mmc/core/mmc_ops.h
··· 32 32 u32 args, void *buf, unsigned len); 33 33 int mmc_send_csd(struct mmc_card *card, u32 *csd); 34 34 int __mmc_send_status(struct mmc_card *card, u32 *status, unsigned int retries); 35 - int mmc_send_status(struct mmc_card *card, u32 *status); 36 35 int mmc_send_cid(struct mmc_host *host, u32 *cid); 37 36 int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp); 38 37 int mmc_spi_set_crc(struct mmc_host *host, int use_crc);
+14
drivers/mmc/core/sd.c
··· 1518 1518 */ 1519 1519 mmc_set_clock(host, mmc_sd_get_max_clock(card)); 1520 1520 1521 + if (host->ios.timing == MMC_TIMING_SD_HS && 1522 + host->ops->prepare_sd_hs_tuning) { 1523 + err = host->ops->prepare_sd_hs_tuning(host, card); 1524 + if (err) 1525 + goto free_card; 1526 + } 1527 + 1521 1528 /* 1522 1529 * Switch to wider bus (if supported). 1523 1530 */ ··· 1535 1528 goto free_card; 1536 1529 1537 1530 mmc_set_bus_width(host, MMC_BUS_WIDTH_4); 1531 + } 1532 + 1533 + if (host->ios.timing == MMC_TIMING_SD_HS && 1534 + host->ops->execute_sd_hs_tuning) { 1535 + err = host->ops->execute_sd_hs_tuning(host, card); 1536 + if (err) 1537 + goto free_card; 1538 1538 } 1539 1539 } 1540 1540 cont:
+1
drivers/mmc/core/sd_ops.c
··· 323 323 return mmc_send_adtc_data(card, card->host, SD_SWITCH, cmd_args, resp, 324 324 64); 325 325 } 326 + EXPORT_SYMBOL_GPL(mmc_sd_switch); 326 327 327 328 int mmc_app_sd_status(struct mmc_card *card, void *ssr) 328 329 {
-2
drivers/mmc/core/sd_ops.h
··· 19 19 int mmc_send_if_cond_pcie(struct mmc_host *host, u32 ocr); 20 20 int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca); 21 21 int mmc_app_send_scr(struct mmc_card *card); 22 - int mmc_sd_switch(struct mmc_card *card, int mode, int group, 23 - u8 value, u8 *resp); 24 22 int mmc_app_sd_status(struct mmc_card *card, void *ssr); 25 23 int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card); 26 24
+8
include/linux/mmc/host.h
··· 184 184 /* Execute HS400 tuning depending host driver */ 185 185 int (*execute_hs400_tuning)(struct mmc_host *host, struct mmc_card *card); 186 186 187 + /* Optional callback to prepare for SD high-speed tuning */ 188 + int (*prepare_sd_hs_tuning)(struct mmc_host *host, struct mmc_card *card); 189 + 190 + /* Optional callback to execute SD high-speed tuning */ 191 + int (*execute_sd_hs_tuning)(struct mmc_host *host, struct mmc_card *card); 192 + 187 193 /* Prepare switch to DDR during the HS400 init sequence */ 188 194 int (*hs400_prepare_ddr)(struct mmc_host *host); 189 195 ··· 671 665 host->err_stats[stat] += 1; 672 666 } 673 667 668 + int mmc_sd_switch(struct mmc_card *card, int mode, int group, u8 value, u8 *resp); 669 + int mmc_send_status(struct mmc_card *card, u32 *status); 674 670 int mmc_send_tuning(struct mmc_host *host, u32 opcode, int *cmd_error); 675 671 int mmc_send_abort_tuning(struct mmc_host *host, u32 opcode); 676 672 int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd);