mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
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:
parent
328bda09cc
commit
9a9f7e1395
8 changed files with 1103 additions and 37 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue