mmc: core: Support UHS-II card control and access

Embed UHS-II access/control functionality into the MMC request
processing flow.

Signed-off-by: Jason Lai <jason.lai@genesyslogic.com.tw>
Signed-off-by: Victor Shih <victor.shih@genesyslogic.com.tw>
Message-ID: <20241018105333.4569-2-victorshihgli@gmail.com>
[Ulf: A couple of cleanups and fixed sd_uhs2_power_off()]
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
Victor Shih 2024-10-18 18:53:18 +08:00 committed by Ulf Hansson
parent 328bda09cc
commit 9a9f7e1395
8 changed files with 1103 additions and 37 deletions

View file

@ -354,6 +354,9 @@ int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
if (err)
return err;
if (host->uhs2_sd_tran)
mmc_uhs2_prepare_cmd(host, mrq);
led_trigger_event(host->led, LED_FULL);
__mmc_start_request(host, mrq);
@ -453,6 +456,9 @@ int mmc_cqe_start_req(struct mmc_host *host, struct mmc_request *mrq)
if (err)
goto out_err;
if (host->uhs2_sd_tran)
mmc_uhs2_prepare_cmd(host, mrq);
err = host->cqe_ops->cqe_request(host, mrq);
if (err)
goto out_err;
@ -1135,7 +1141,7 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
return 0;
}
if (host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) {
if (!mmc_card_uhs2(host) && host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) {
bit = ffs(ocr) - 1;
ocr &= 3 << bit;
mmc_power_cycle(host, ocr);

View file

@ -200,7 +200,7 @@ static int mmc_decode_csd(struct mmc_card *card, bool is_sduc)
/*
* Given a 64-bit response, decode to our card SCR structure.
*/
static int mmc_decode_scr(struct mmc_card *card)
int mmc_decode_scr(struct mmc_card *card)
{
struct sd_scr *scr = &card->scr;
unsigned int scr_struct;
@ -903,7 +903,7 @@ int mmc_sd_get_csd(struct mmc_card *card, bool is_sduc)
return 0;
}
static int mmc_sd_get_ro(struct mmc_host *host)
int mmc_sd_get_ro(struct mmc_host *host)
{
int ro;

View file

@ -11,6 +11,8 @@ struct mmc_card;
int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr);
int mmc_sd_get_csd(struct mmc_card *card, bool is_sduc);
int mmc_decode_scr(struct mmc_card *card);
int mmc_sd_get_ro(struct mmc_host *host);
void mmc_decode_cid(struct mmc_card *card);
int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
bool reinit);

View file

@ -42,6 +42,15 @@ int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card)
if (WARN_ON(card && card->host != host))
return -EINVAL;
/*
* UHS2 packet has APP bit so only set APP_CMD flag here.
* Will set the APP bit when assembling UHS2 packet.
*/
if (host->uhs2_sd_tran) {
host->uhs2_app_cmd = true;
return 0;
}
cmd.opcode = MMC_APP_CMD;
if (card) {

View file

@ -12,6 +12,7 @@
struct mmc_card;
struct mmc_host;
struct mmc_request;
int mmc_app_set_bus_width(struct mmc_card *card, int width);
int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
@ -22,6 +23,7 @@ int mmc_app_send_scr(struct mmc_card *card);
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_send_ext_addr(struct mmc_host *host, u32 addr);
void mmc_uhs2_prepare_cmd(struct mmc_host *host, struct mmc_request *mrq);
#endif

File diff suppressed because it is too large Load diff

View file

@ -11,6 +11,20 @@
struct mmc_data;
struct mmc_request;
#define UHS2_MAX_PAYLOAD_LEN 2
#define UHS2_MAX_RESP_LEN 20
struct uhs2_command {
u16 header;
u16 arg;
__be32 payload[UHS2_MAX_PAYLOAD_LEN];
u8 payload_len;
u8 packet_len;
u8 tmode_half_duplex;
u8 uhs2_resp[UHS2_MAX_RESP_LEN]; /* UHS2 native cmd resp */
u8 uhs2_resp_len; /* UHS2 native cmd resp len */
};
struct mmc_command {
u32 opcode;
u32 arg;
@ -97,6 +111,8 @@ struct mmc_command {
struct mmc_data *data; /* data segment associated with cmd */
struct mmc_request *mrq; /* associated request */
struct uhs2_command *uhs2_cmd; /* UHS2 command */
/* for SDUC */
bool has_ext_addr;
u8 ext_addr;
@ -158,6 +174,7 @@ struct mmc_request {
const struct bio_crypt_ctx *crypto_ctx;
int crypto_key_slot;
#endif
struct uhs2_command uhs2_cmd;
};
struct mmc_card;

View file

@ -127,6 +127,13 @@ struct sd_uhs2_caps {
};
enum sd_uhs2_operation {
UHS2_PHY_INIT = 0,
UHS2_SET_CONFIG,
UHS2_ENABLE_INT,
UHS2_DISABLE_INT,
UHS2_ENABLE_CLK,
UHS2_DISABLE_CLK,
UHS2_CHECK_DORMANT,
UHS2_SET_IOS,
};
@ -453,6 +460,8 @@ struct mmc_host {
#endif
#define MMC_CAP2_ALT_GPT_TEGRA (1 << 28) /* Host with eMMC that has GPT entry at a non-standard location */
bool uhs2_sd_tran; /* UHS-II flag for SD_TRAN state */
bool uhs2_app_cmd; /* UHS-II flag for APP command */
struct sd_uhs2_caps uhs2_caps; /* Host UHS-II capabilities */
int fixed_drv_type; /* fixed driver type for non-removable media */
@ -714,6 +723,12 @@ static inline void mmc_debugfs_err_stats_inc(struct mmc_host *host,
host->err_stats[stat] += 1;
}
static inline int mmc_card_uhs2_hd_mode(struct mmc_host *host)
{
return host->ios.timing == MMC_TIMING_UHS2_SPEED_A_HD ||
host->ios.timing == MMC_TIMING_UHS2_SPEED_B_HD;
}
int mmc_sd_switch(struct mmc_card *card, bool mode, int group,
u8 value, u8 *resp);
int mmc_send_status(struct mmc_card *card, u32 *status);