Commit bac80683 authored by Wenchao Chen's avatar Wenchao Chen Committed by Ulf Hansson

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: default avatarWenchao 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: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 48fe8fad
...@@ -32,7 +32,6 @@ int mmc_send_adtc_data(struct mmc_card *card, struct mmc_host *host, u32 opcode, ...@@ -32,7 +32,6 @@ int mmc_send_adtc_data(struct mmc_card *card, struct mmc_host *host, u32 opcode,
u32 args, void *buf, unsigned len); u32 args, void *buf, unsigned len);
int mmc_send_csd(struct mmc_card *card, u32 *csd); int mmc_send_csd(struct mmc_card *card, u32 *csd);
int __mmc_send_status(struct mmc_card *card, u32 *status, unsigned int retries); int __mmc_send_status(struct mmc_card *card, u32 *status, unsigned int retries);
int mmc_send_status(struct mmc_card *card, u32 *status);
int mmc_send_cid(struct mmc_host *host, u32 *cid); int mmc_send_cid(struct mmc_host *host, u32 *cid);
int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp); int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp);
int mmc_spi_set_crc(struct mmc_host *host, int use_crc); int mmc_spi_set_crc(struct mmc_host *host, int use_crc);
......
...@@ -1518,6 +1518,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, ...@@ -1518,6 +1518,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
*/ */
mmc_set_clock(host, mmc_sd_get_max_clock(card)); mmc_set_clock(host, mmc_sd_get_max_clock(card));
if (host->ios.timing == MMC_TIMING_SD_HS &&
host->ops->prepare_sd_hs_tuning) {
err = host->ops->prepare_sd_hs_tuning(host, card);
if (err)
goto free_card;
}
/* /*
* Switch to wider bus (if supported). * Switch to wider bus (if supported).
*/ */
...@@ -1529,6 +1536,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, ...@@ -1529,6 +1536,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
mmc_set_bus_width(host, MMC_BUS_WIDTH_4); mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
} }
if (host->ios.timing == MMC_TIMING_SD_HS &&
host->ops->execute_sd_hs_tuning) {
err = host->ops->execute_sd_hs_tuning(host, card);
if (err)
goto free_card;
}
} }
cont: cont:
if (!oldcard) { if (!oldcard) {
......
...@@ -323,6 +323,7 @@ int mmc_sd_switch(struct mmc_card *card, int mode, int group, ...@@ -323,6 +323,7 @@ int mmc_sd_switch(struct mmc_card *card, int mode, int group,
return mmc_send_adtc_data(card, card->host, SD_SWITCH, cmd_args, resp, return mmc_send_adtc_data(card, card->host, SD_SWITCH, cmd_args, resp,
64); 64);
} }
EXPORT_SYMBOL_GPL(mmc_sd_switch);
int mmc_app_sd_status(struct mmc_card *card, void *ssr) int mmc_app_sd_status(struct mmc_card *card, void *ssr)
{ {
......
...@@ -19,8 +19,6 @@ int mmc_send_if_cond(struct mmc_host *host, u32 ocr); ...@@ -19,8 +19,6 @@ int mmc_send_if_cond(struct mmc_host *host, u32 ocr);
int mmc_send_if_cond_pcie(struct mmc_host *host, u32 ocr); int mmc_send_if_cond_pcie(struct mmc_host *host, u32 ocr);
int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca); int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca);
int mmc_app_send_scr(struct mmc_card *card); int mmc_app_send_scr(struct mmc_card *card);
int mmc_sd_switch(struct mmc_card *card, int mode, int group,
u8 value, u8 *resp);
int mmc_app_sd_status(struct mmc_card *card, void *ssr); int mmc_app_sd_status(struct mmc_card *card, void *ssr);
int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card); int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card);
......
...@@ -184,6 +184,12 @@ struct mmc_host_ops { ...@@ -184,6 +184,12 @@ struct mmc_host_ops {
/* Execute HS400 tuning depending host driver */ /* Execute HS400 tuning depending host driver */
int (*execute_hs400_tuning)(struct mmc_host *host, struct mmc_card *card); int (*execute_hs400_tuning)(struct mmc_host *host, struct mmc_card *card);
/* Optional callback to prepare for SD high-speed tuning */
int (*prepare_sd_hs_tuning)(struct mmc_host *host, struct mmc_card *card);
/* Optional callback to execute SD high-speed tuning */
int (*execute_sd_hs_tuning)(struct mmc_host *host, struct mmc_card *card);
/* Prepare switch to DDR during the HS400 init sequence */ /* Prepare switch to DDR during the HS400 init sequence */
int (*hs400_prepare_ddr)(struct mmc_host *host); int (*hs400_prepare_ddr)(struct mmc_host *host);
...@@ -665,6 +671,8 @@ static inline void mmc_debugfs_err_stats_inc(struct mmc_host *host, ...@@ -665,6 +671,8 @@ static inline void mmc_debugfs_err_stats_inc(struct mmc_host *host,
host->err_stats[stat] += 1; host->err_stats[stat] += 1;
} }
int mmc_sd_switch(struct mmc_card *card, int mode, int group, u8 value, u8 *resp);
int mmc_send_status(struct mmc_card *card, u32 *status);
int mmc_send_tuning(struct mmc_host *host, u32 opcode, int *cmd_error); int mmc_send_tuning(struct mmc_host *host, u32 opcode, int *cmd_error);
int mmc_send_abort_tuning(struct mmc_host *host, u32 opcode); int mmc_send_abort_tuning(struct mmc_host *host, u32 opcode);
int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd); int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment