mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-09-21 11:53:01 +00:00
Merge "mmc: sdhci-msm: Enable enhanced strobe support for host"
This commit is contained in:
commit
e960032081
|
@ -398,11 +398,12 @@ int mmc_add_card(struct mmc_card *card)
|
|||
mmc_card_ddr_mode(card) ? "DDR " : "",
|
||||
type);
|
||||
} else {
|
||||
pr_info("%s: new %s%s%s%s%s%s card at address %04x\n",
|
||||
pr_info("%s: new %s%s%s%s%s%s%s card at address %04x\n",
|
||||
mmc_hostname(card->host),
|
||||
mmc_card_uhs(card) ? "ultra high speed " :
|
||||
(mmc_card_highspeed(card) ? "high speed " : ""),
|
||||
(mmc_card_hs400(card) ? "HS400 " : ""),
|
||||
(mmc_card_hs400_strobe(card) ? "enhanced strobe " : ""),
|
||||
(mmc_card_hs200(card) ? "HS200 " : ""),
|
||||
mmc_card_ddr_mode(card) ? "DDR " : "",
|
||||
uhs_bus_speed_mode, type, card->rca);
|
||||
|
|
|
@ -313,6 +313,7 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
|
|||
}
|
||||
}
|
||||
|
||||
card->ext_csd.raw_strobe_support = ext_csd[EXT_CSD_STROBE_SUPPORT];
|
||||
/*
|
||||
* The EXT_CSD format is meant to be forward compatible. As long
|
||||
* as CSD_STRUCTURE does not change, all values for EXT_CSD_REV
|
||||
|
@ -1117,6 +1118,98 @@ out:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int mmc_select_hs400_strobe(struct mmc_card *card, u8 *ext_csd)
|
||||
{
|
||||
int err = 0, ret = 0;
|
||||
struct mmc_host *host = card->host;
|
||||
|
||||
if (!(host->caps2 & MMC_CAP2_HS400) || !host->ops->enhanced_strobe ||
|
||||
!(card->ext_csd.card_type & EXT_CSD_CARD_TYPE_HS400) ||
|
||||
!mmc_card_strobe(card)) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_HS400_1_2V)
|
||||
&& (host->caps2 & MMC_CAP2_HS400_1_2V))
|
||||
if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120))
|
||||
err = __mmc_set_signal_voltage(host,
|
||||
MMC_SIGNAL_VOLTAGE_180);
|
||||
/* If fails try again during next card power cycle */
|
||||
if (err) {
|
||||
pr_err("%s: err in __mmc_set_signal_voltage failed\n",
|
||||
mmc_hostname(host));
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* For HS400 enhanced strobe mode following sequence is being followed:
|
||||
* - switch to HS mode.
|
||||
* - select DDR bus width along with enhanced strobe mode enabled.
|
||||
* - switch to HS400 mode and set clock to max.
|
||||
* - call for host specific ops to enable enhanced strobe at host side.
|
||||
*/
|
||||
err = mmc_select_hs(card, ext_csd);
|
||||
if (err) {
|
||||
pr_warn("%s: switch to high-speed failed, err:%d\n",
|
||||
mmc_hostname(host), err);
|
||||
goto err;
|
||||
}
|
||||
mmc_card_clr_highspeed(card);
|
||||
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_BUS_WIDTH,
|
||||
0x86,
|
||||
card->ext_csd.generic_cmd6_time);
|
||||
if (err) {
|
||||
pr_warn("%s: switch to DDR bus width with enhanced strobe for hs400 failed, err:%d\n",
|
||||
mmc_hostname(host), err);
|
||||
goto err;
|
||||
}
|
||||
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_HS_TIMING,
|
||||
0x3,
|
||||
card->ext_csd.generic_cmd6_time);
|
||||
if (err) {
|
||||
pr_warn("%s: switch to hs400 failed, err:%d\n",
|
||||
mmc_hostname(host), err);
|
||||
goto err;
|
||||
}
|
||||
|
||||
mmc_set_timing(host, MMC_TIMING_MMC_HS400);
|
||||
mmc_set_clock(host, MMC_HS400_MAX_DTR);
|
||||
mmc_card_set_hs400(card);
|
||||
|
||||
mmc_host_clk_hold(host);
|
||||
err = host->ops->enhanced_strobe(host);
|
||||
mmc_host_clk_release(host);
|
||||
|
||||
/*
|
||||
* Fall back to HS mode if hs400 enhanced
|
||||
* strobe is unsuccessful.
|
||||
* Lower the clock and adjust the timing
|
||||
* to be able to switch to HighSpeed mode
|
||||
*/
|
||||
if (err) {
|
||||
pr_debug("%s: strobe execution failed %d\n",
|
||||
mmc_hostname(host), err);
|
||||
mmc_card_clr_hs400(card);
|
||||
|
||||
mmc_set_timing(host, MMC_TIMING_LEGACY);
|
||||
mmc_set_clock(host, MMC_HIGH_26_MAX_DTR);
|
||||
|
||||
ret = mmc_select_hs(card, ext_csd);
|
||||
if (ret)
|
||||
pr_warn("%s: select highspeed mode failed %d\n",
|
||||
__func__, ret);
|
||||
goto err;
|
||||
}
|
||||
mmc_card_set_hs400_strobe(card);
|
||||
err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mmc_select_hs400(struct mmc_card *card, u8 *ext_csd)
|
||||
{
|
||||
int err = 0;
|
||||
|
@ -1236,7 +1329,11 @@ int mmc_set_clock_bus_speed(struct mmc_card *card, unsigned long freq)
|
|||
mmc_set_timing(card->host, MMC_TIMING_LEGACY);
|
||||
mmc_set_clock(card->host, MMC_HIGH_26_MAX_DTR);
|
||||
}
|
||||
err = mmc_select_hs400(card, card->cached_ext_csd);
|
||||
if (mmc_card_hs400_strobe(card))
|
||||
err = mmc_select_hs400_strobe(card,
|
||||
card->cached_ext_csd);
|
||||
else
|
||||
err = mmc_select_hs400(card, card->cached_ext_csd);
|
||||
}
|
||||
|
||||
return err;
|
||||
|
@ -1335,7 +1432,8 @@ static int mmc_select_bus_speed(struct mmc_card *card, u8 *ext_csd)
|
|||
int err = 0;
|
||||
|
||||
BUG_ON(!card);
|
||||
|
||||
if (!mmc_select_hs400_strobe(card, ext_csd))
|
||||
goto out;
|
||||
if (!mmc_select_hs400(card, ext_csd))
|
||||
goto out;
|
||||
if (!mmc_select_hs200(card, ext_csd))
|
||||
|
|
|
@ -374,6 +374,8 @@ static int cmdq_enable(struct mmc_host *mmc)
|
|||
if (cq_host->ops->clear_set_dumpregs)
|
||||
cq_host->ops->clear_set_dumpregs(mmc, 1);
|
||||
|
||||
if (cq_host->ops->enhanced_strobe_mask)
|
||||
cq_host->ops->enhanced_strobe_mask(mmc, true);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
@ -389,6 +391,9 @@ static void cmdq_disable(struct mmc_host *mmc, bool soft)
|
|||
}
|
||||
|
||||
mmc_host_set_cq_disable(mmc);
|
||||
if (cq_host->ops->enhanced_strobe_mask)
|
||||
cq_host->ops->enhanced_strobe_mask(mmc, false);
|
||||
|
||||
cq_host->enabled = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -202,6 +202,7 @@ struct cmdq_host_ops {
|
|||
void (*write_l)(struct cmdq_host *host, u32 val, int reg);
|
||||
u32 (*read_l)(struct cmdq_host *host, int reg);
|
||||
void (*clear_set_dumpregs)(struct mmc_host *mmc, bool set);
|
||||
void (*enhanced_strobe_mask)(struct mmc_host *mmc, bool set);
|
||||
int (*reset)(struct mmc_host *mmc);
|
||||
int (*crypto_cfg)(struct mmc_host *mmc, struct mmc_request *mrq,
|
||||
u32 slot);
|
||||
|
|
|
@ -146,10 +146,12 @@ enum sdc_mpm_pin_state {
|
|||
|
||||
#define CORE_DDR_200_CFG 0x184
|
||||
#define CORE_CDC_T4_DLY_SEL (1 << 0)
|
||||
#define CORE_CMDIN_RCLK_EN (1 << 1)
|
||||
#define CORE_START_CDC_TRAFFIC (1 << 6)
|
||||
|
||||
#define CORE_VENDOR_SPEC3 0x1B0
|
||||
#define CORE_PWRSAVE_DLL (1 << 3)
|
||||
#define CORE_CMDEN_HS400_INPUT_MASK_CNT (1 << 13)
|
||||
|
||||
#define CORE_DLL_CONFIG_2 0x1B4
|
||||
#define CORE_DDR_CAL_EN (1 << 0)
|
||||
|
@ -797,6 +799,8 @@ static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)
|
|||
{
|
||||
u32 dll_status, ddr_config;
|
||||
int ret = 0;
|
||||
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
struct sdhci_msm_host *msm_host = pltfm_host->priv;
|
||||
|
||||
pr_debug("%s: Enter %s\n", mmc_hostname(host->mmc), __func__);
|
||||
|
||||
|
@ -808,6 +812,11 @@ static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)
|
|||
ddr_config |= DDR_CONFIG_PRG_RCLK_DLY;
|
||||
writel_relaxed(ddr_config, host->ioaddr + CORE_DDR_CONFIG);
|
||||
|
||||
if (msm_host->enhanced_strobe && mmc_card_strobe(msm_host->mmc->card))
|
||||
writel_relaxed((readl_relaxed(host->ioaddr + CORE_DDR_200_CFG)
|
||||
| CORE_CMDIN_RCLK_EN),
|
||||
host->ioaddr + CORE_DDR_200_CFG);
|
||||
|
||||
/* Write 1 to DDR_CAL_EN field in CORE_DLL_CONFIG_2 */
|
||||
writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2)
|
||||
| CORE_DDR_CAL_EN),
|
||||
|
@ -834,6 +843,42 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int sdhci_msm_enhanced_strobe(struct sdhci_host *host)
|
||||
{
|
||||
int ret = 0;
|
||||
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
struct sdhci_msm_host *msm_host = pltfm_host->priv;
|
||||
struct mmc_host *mmc = host->mmc;
|
||||
|
||||
pr_debug("%s: Enter %s\n", mmc_hostname(host->mmc), __func__);
|
||||
|
||||
if (!msm_host->enhanced_strobe || !mmc_card_strobe(mmc->card)) {
|
||||
pr_debug("%s: host/card does not support hs400 enhanced strobe\n",
|
||||
mmc_hostname(mmc));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (msm_host->calibration_done ||
|
||||
!(mmc->ios.timing == MMC_TIMING_MMC_HS400)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the tuning block.
|
||||
*/
|
||||
ret = msm_init_cm_dll(host);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = sdhci_msm_cm_dll_sdc4_calibration(host);
|
||||
out:
|
||||
if (!ret)
|
||||
msm_host->calibration_done = true;
|
||||
pr_debug("%s: Exit %s, ret:%d\n", mmc_hostname(host->mmc),
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sdhci_msm_hs400_dll_calibration(struct sdhci_host *host)
|
||||
{
|
||||
int ret = 0;
|
||||
|
@ -2849,7 +2894,10 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
|
|||
* Select HS400 mode using the HC_SELECT_IN from VENDOR SPEC
|
||||
* register
|
||||
*/
|
||||
if (msm_host->tuning_done && !msm_host->calibration_done) {
|
||||
if ((msm_host->tuning_done ||
|
||||
(mmc_card_strobe(msm_host->mmc->card) &&
|
||||
msm_host->enhanced_strobe)) &&
|
||||
!msm_host->calibration_done) {
|
||||
/*
|
||||
* Write 0x6 to HC_SELECT_IN and 1 to HC_SELECT_IN_EN
|
||||
* field in VENDOR_SPEC_FUNC
|
||||
|
@ -3189,6 +3237,36 @@ static void sdhci_msm_notify_pm_status(struct sdhci_host *host,
|
|||
msm_host->mmc_dev_state = state;
|
||||
}
|
||||
|
||||
/*
|
||||
* sdhci_msm_enhanced_strobe_mask :-
|
||||
* Before running CMDQ transfers in HS400 Enhanced Strobe mode,
|
||||
* SW should write 3 to
|
||||
* HC_VENDOR_SPECIFIC_FUNC3.CMDEN_HS400_INPUT_MASK_CNT register.
|
||||
* The default reset value of this register is 2.
|
||||
*/
|
||||
static void sdhci_msm_enhanced_strobe_mask(struct sdhci_host *host, bool set)
|
||||
{
|
||||
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
struct sdhci_msm_host *msm_host = pltfm_host->priv;
|
||||
|
||||
if (!msm_host->enhanced_strobe ||
|
||||
!mmc_card_strobe(msm_host->mmc->card)) {
|
||||
pr_debug("%s: host/card does not support hs400 enhanced strobe\n",
|
||||
mmc_hostname(host->mmc));
|
||||
return;
|
||||
}
|
||||
|
||||
if (set) {
|
||||
writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC3)
|
||||
| CORE_CMDEN_HS400_INPUT_MASK_CNT),
|
||||
host->ioaddr + CORE_VENDOR_SPEC3);
|
||||
} else {
|
||||
writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC3)
|
||||
& ~CORE_CMDEN_HS400_INPUT_MASK_CNT),
|
||||
host->ioaddr + CORE_VENDOR_SPEC3);
|
||||
}
|
||||
}
|
||||
|
||||
static void sdhci_msm_clear_set_dumpregs(struct sdhci_host *host, bool set)
|
||||
{
|
||||
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
|
@ -3239,6 +3317,7 @@ static struct sdhci_ops sdhci_msm_ops = {
|
|||
.set_uhs_signaling = sdhci_msm_set_uhs_signaling,
|
||||
.check_power_status = sdhci_msm_check_power_status,
|
||||
.execute_tuning = sdhci_msm_execute_tuning,
|
||||
.enhanced_strobe = sdhci_msm_enhanced_strobe,
|
||||
.toggle_cdr = sdhci_msm_toggle_cdr,
|
||||
.get_max_segments = sdhci_msm_max_segs,
|
||||
.set_clock = sdhci_msm_set_clock,
|
||||
|
@ -3252,6 +3331,7 @@ static struct sdhci_ops sdhci_msm_ops = {
|
|||
.clear_set_dumpregs = sdhci_msm_clear_set_dumpregs,
|
||||
.notify_load = sdhci_msm_notify_load,
|
||||
.notify_pm_status = sdhci_msm_notify_pm_status,
|
||||
.enhanced_strobe_mask = sdhci_msm_enhanced_strobe_mask,
|
||||
};
|
||||
|
||||
static int sdhci_msm_cfg_mpm_pin_wakeup(struct sdhci_host *host, unsigned mode)
|
||||
|
@ -3343,9 +3423,12 @@ static void sdhci_set_default_hw_caps(struct sdhci_msm_host *msm_host,
|
|||
/*
|
||||
* SDCC 5 controller with major version 1, minor version 0x42 and later
|
||||
* will require additional steps when resetting DLL.
|
||||
* It also supports HS400 enhanced strobe mode.
|
||||
*/
|
||||
if ((major == 1) && (minor >= 0x42))
|
||||
if ((major == 1) && (minor >= 0x42)) {
|
||||
msm_host->use_updated_dll_reset = true;
|
||||
msm_host->enhanced_strobe = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mask 64-bit support for controller with 32-bit address bus so that
|
||||
|
|
|
@ -165,5 +165,6 @@ struct sdhci_msm_host {
|
|||
enum dev_state mmc_dev_state;
|
||||
struct sdhci_msm_ice_data ice;
|
||||
u32 ice_clk_rate;
|
||||
bool enhanced_strobe;
|
||||
};
|
||||
#endif /* __SDHCI_MSM_H__ */
|
||||
|
|
|
@ -62,6 +62,7 @@ static void sdhci_finish_data(struct sdhci_host *);
|
|||
static void sdhci_send_command(struct sdhci_host *, struct mmc_command *);
|
||||
static void sdhci_finish_command(struct sdhci_host *);
|
||||
static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
|
||||
static int sdhci_enhanced_strobe(struct mmc_host *mmc);
|
||||
static void sdhci_tuning_timer(unsigned long data);
|
||||
static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
|
||||
static bool sdhci_check_state(struct sdhci_host *);
|
||||
|
@ -2551,6 +2552,19 @@ static int sdhci_card_busy(struct mmc_host *mmc)
|
|||
return !(present_state & SDHCI_DATA_LVL_MASK);
|
||||
}
|
||||
|
||||
static int sdhci_enhanced_strobe(struct mmc_host *mmc)
|
||||
{
|
||||
struct sdhci_host *host = mmc_priv(mmc);
|
||||
int err = -EINVAL;
|
||||
|
||||
sdhci_runtime_pm_get(host);
|
||||
if (host->ops->enhanced_strobe)
|
||||
err = host->ops->enhanced_strobe(host);
|
||||
sdhci_runtime_pm_put(host);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
|
||||
{
|
||||
struct sdhci_host *host;
|
||||
|
@ -2872,6 +2886,7 @@ static const struct mmc_host_ops sdhci_ops = {
|
|||
.enable_sdio_irq = sdhci_enable_sdio_irq,
|
||||
.start_signal_voltage_switch = sdhci_start_signal_voltage_switch,
|
||||
.execute_tuning = sdhci_execute_tuning,
|
||||
.enhanced_strobe = sdhci_enhanced_strobe,
|
||||
.card_event = sdhci_card_event,
|
||||
.card_busy = sdhci_card_busy,
|
||||
.enable = sdhci_enable,
|
||||
|
@ -3779,6 +3794,14 @@ static void sdhci_cmdq_set_block_size(struct mmc_host *mmc)
|
|||
sdhci_set_blk_size_reg(host, 512, 0);
|
||||
}
|
||||
|
||||
static void sdhci_enhanced_strobe_mask(struct mmc_host *mmc, bool set)
|
||||
{
|
||||
struct sdhci_host *host = mmc_priv(mmc);
|
||||
|
||||
if (host->ops->enhanced_strobe_mask)
|
||||
host->ops->enhanced_strobe_mask(host, set);
|
||||
}
|
||||
|
||||
static void sdhci_cmdq_clear_set_dumpregs(struct mmc_host *mmc, bool set)
|
||||
{
|
||||
struct sdhci_host *host = mmc_priv(mmc);
|
||||
|
@ -3851,6 +3874,11 @@ static void sdhci_cmdq_set_block_size(struct mmc_host *mmc)
|
|||
|
||||
}
|
||||
|
||||
static void sdhci_enhanced_strobe_mask(struct mmc_host *mmc, bool set)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void sdhci_cmdq_clear_set_dumpregs(struct mmc_host *mmc, bool set)
|
||||
{
|
||||
|
||||
|
@ -3880,6 +3908,7 @@ static const struct cmdq_host_ops sdhci_cmdq_ops = {
|
|||
.dump_vendor_regs = sdhci_cmdq_dump_vendor_regs,
|
||||
.set_block_size = sdhci_cmdq_set_block_size,
|
||||
.clear_set_dumpregs = sdhci_cmdq_clear_set_dumpregs,
|
||||
.enhanced_strobe_mask = sdhci_enhanced_strobe_mask,
|
||||
.crypto_cfg = sdhci_cmdq_crypto_cfg,
|
||||
.crypto_cfg_reset = sdhci_cmdq_crypto_cfg_reset,
|
||||
.post_cqe_halt = sdhci_cmdq_post_cqe_halt,
|
||||
|
|
|
@ -320,6 +320,7 @@ struct sdhci_ops {
|
|||
int (*execute_tuning)(struct sdhci_host *host, u32 opcode);
|
||||
void (*toggle_cdr)(struct sdhci_host *host, bool enable);
|
||||
unsigned int (*get_max_segments)(void);
|
||||
int (*enhanced_strobe)(struct sdhci_host *host);
|
||||
void (*platform_bus_voting)(struct sdhci_host *host, u32 enable);
|
||||
void (*disable_data_xfer)(struct sdhci_host *host);
|
||||
void (*dump_vendor_regs)(struct sdhci_host *host);
|
||||
|
@ -332,6 +333,7 @@ struct sdhci_ops {
|
|||
int (*notify_load)(struct sdhci_host *host, enum mmc_load state);
|
||||
void (*notify_pm_status)(struct sdhci_host *host,
|
||||
enum dev_state state);
|
||||
void (*enhanced_strobe_mask)(struct sdhci_host *host, bool set);
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
|
||||
|
|
|
@ -95,6 +95,8 @@ struct mmc_ext_csd {
|
|||
u8 raw_partition_support; /* 160 */
|
||||
u8 raw_rpmb_size_mult; /* 168 */
|
||||
u8 raw_erased_mem_count; /* 181 */
|
||||
u8 raw_strobe_support; /* 184 */
|
||||
#define MMC_STROBE_SUPPORT (1 << 0)
|
||||
u8 raw_ext_csd_structure; /* 194 */
|
||||
u8 raw_card_type; /* 196 */
|
||||
u8 raw_drive_strength; /* 197 */
|
||||
|
@ -351,6 +353,7 @@ struct mmc_card {
|
|||
#define MMC_STATE_NEED_BKOPS (1<<11) /* card needs to do BKOPS */
|
||||
#define MMC_STATE_CMDQ (1<<12) /* card is in cmd queue mode */
|
||||
#define MMC_STATE_SUSPENDED (1<<13) /* card is suspended */
|
||||
#define MMC_STATE_HS400_STROBE (1<<14) /* card is in strobe mode */
|
||||
unsigned int quirks; /* card quirks */
|
||||
#define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */
|
||||
#define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */
|
||||
|
@ -546,6 +549,9 @@ struct mmc_fixup {
|
|||
card->cid.year, \
|
||||
card->cid.month)
|
||||
|
||||
#define mmc_card_strobe(c) (((c)->ext_csd).raw_strobe_support & \
|
||||
MMC_STROBE_SUPPORT)
|
||||
|
||||
/*
|
||||
* Unconditionally quirk add/remove.
|
||||
*/
|
||||
|
@ -569,6 +575,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
|
|||
#define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED)
|
||||
#define mmc_card_hs200(c) ((c)->state & MMC_STATE_HIGHSPEED_200)
|
||||
#define mmc_card_hs400(c) ((c)->state & MMC_STATE_HIGHSPEED_400)
|
||||
#define mmc_card_hs400_strobe(c) ((c)->state & MMC_STATE_HS400_STROBE)
|
||||
#define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR)
|
||||
#define mmc_card_ddr_mode(c) ((c)->state & MMC_STATE_HIGHSPEED_DDR)
|
||||
#define mmc_card_uhs(c) ((c)->state & MMC_STATE_ULTRAHIGHSPEED)
|
||||
|
@ -588,6 +595,8 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
|
|||
#define mmc_card_clr_hs200(c) ((c)->state &= ~MMC_STATE_HIGHSPEED_200)
|
||||
#define mmc_card_set_hs400(c) ((c)->state |= MMC_STATE_HIGHSPEED_400)
|
||||
#define mmc_card_clr_hs400(c) ((c)->state &= ~MMC_STATE_HIGHSPEED_400)
|
||||
#define mmc_card_set_hs400_strobe(c) ((c)->state |= MMC_STATE_HS400_STROBE)
|
||||
#define mmc_card_clr_hs400_strobe(c) ((c)->state &= ~MMC_STATE_HS400_STROBE)
|
||||
#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
|
||||
#define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)
|
||||
#define mmc_card_clr_ddr_mode(c) ((c)->state &= ~MMC_STATE_HIGHSPEED_DDR)
|
||||
|
|
|
@ -165,6 +165,7 @@ struct mmc_host_ops {
|
|||
|
||||
/* The tuning command opcode value is different for SD and eMMC cards */
|
||||
int (*execute_tuning)(struct mmc_host *host, u32 opcode);
|
||||
int (*enhanced_strobe)(struct mmc_host *host);
|
||||
int (*select_drive_strength)(unsigned int max_dtr, int host_drv, int card_drv);
|
||||
void (*hw_reset)(struct mmc_host *host);
|
||||
void (*card_event)(struct mmc_host *host);
|
||||
|
|
|
@ -244,6 +244,7 @@ struct _mmc_csd {
|
|||
#define EXT_CSD_PART_CONFIG 179 /* R/W */
|
||||
#define EXT_CSD_ERASED_MEM_CONT 181 /* RO */
|
||||
#define EXT_CSD_BUS_WIDTH 183 /* R/W */
|
||||
#define EXT_CSD_STROBE_SUPPORT 184 /* RO */
|
||||
#define EXT_CSD_HS_TIMING 185 /* R/W */
|
||||
#define EXT_CSD_POWER_CLASS 187 /* R/W */
|
||||
#define EXT_CSD_REV 192 /* RO */
|
||||
|
@ -334,6 +335,7 @@ struct _mmc_csd {
|
|||
#define EXT_CSD_CARD_TYPE_HS400 (EXT_CSD_CARD_TYPE_HS400_1_8V \
|
||||
| EXT_CSD_CARD_TYPE_HS400_1_2V)
|
||||
|
||||
#define EXT_CSD_ENHANCED_STROBE (1 << 0)
|
||||
#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 */
|
||||
|
|
Loading…
Reference in a new issue