Loading drivers/mmc/core/mmc.c +49 −7 Original line number Original line Diff line number Diff line Loading @@ -652,6 +652,11 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) } } if (card->ext_csd.rev >= 7) { if (card->ext_csd.rev >= 7) { /* Enhance Strobe is supported since v5.1 which rev should be * 8 but some eMMC devices can support it with rev 7. So handle * Enhance Strobe here. */ card->ext_csd.strobe_support = ext_csd[EXT_CSD_STROBE_SUPPORT]; card->ext_csd.cmdq_support = ext_csd[EXT_CSD_CMDQ_SUPPORT]; card->ext_csd.cmdq_support = ext_csd[EXT_CSD_CMDQ_SUPPORT]; if (card->ext_csd.cmdq_support) { if (card->ext_csd.cmdq_support) { /* /* Loading Loading @@ -1100,13 +1105,33 @@ static int mmc_select_hs400(struct mmc_card *card) { { struct mmc_host *host = card->host; struct mmc_host *host = card->host; int err = 0; int err = 0; u8 val; /* /* * HS400 mode requires 8-bit bus width * HS400 mode requires 8-bit bus width */ */ if (card->ext_csd.strobe_support) { if (!(card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400 && host->caps & MMC_CAP_8_BIT_DATA)) return 0; /* For Enhance Strobe flow. For non Enhance Strobe, signal * voltage will not be set. */ if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V) err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V) err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); if (err) return err; } else { if (!(card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400 && if (!(card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400 && host->ios.bus_width == MMC_BUS_WIDTH_8)) host->ios.bus_width == MMC_BUS_WIDTH_8)) return 0; return 0; } /* /* * Before switching to dual data rate operation for HS400, * Before switching to dual data rate operation for HS400, Loading @@ -1125,9 +1150,16 @@ static int mmc_select_hs400(struct mmc_card *card) return err; return err; } } val = EXT_CSD_DDR_BUS_WIDTH_8; if (card->ext_csd.strobe_support) { err = mmc_select_bus_width(card); if (IS_ERR_VALUE(err)) return err; val |= EXT_CSD_BUS_WIDTH_STROBE; } err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH, EXT_CSD_DDR_BUS_WIDTH_8, val, card->ext_csd.generic_cmd6_time); card->ext_csd.generic_cmd6_time); if (err) { if (err) { pr_warn("%s: switch to bus width for hs400 failed, err:%d\n", pr_warn("%s: switch to bus width for hs400 failed, err:%d\n", Loading @@ -1148,7 +1180,12 @@ static int mmc_select_hs400(struct mmc_card *card) mmc_set_timing(host, MMC_TIMING_MMC_HS400); mmc_set_timing(host, MMC_TIMING_MMC_HS400); mmc_set_bus_speed(card); mmc_set_bus_speed(card); if ((host->caps2 & MMC_CAP2_HS400_POST_TUNING) && host->ops->execute_tuning) { if (host->ops->enhanced_strobe) { mmc_host_clk_hold(host); err = host->ops->enhanced_strobe(host); mmc_host_clk_release(host); } else if ((host->caps2 & MMC_CAP2_HS400_POST_TUNING) && host->ops->execute_tuning) { mmc_host_clk_hold(host); mmc_host_clk_hold(host); err = host->ops->execute_tuning(host, err = host->ops->execute_tuning(host, MMC_SEND_TUNING_BLOCK_HS200); MMC_SEND_TUNING_BLOCK_HS200); Loading @@ -1159,7 +1196,7 @@ static int mmc_select_hs400(struct mmc_card *card) mmc_hostname(host)); mmc_hostname(host)); } } return 0; return err; } } /* /* Loading Loading @@ -1225,7 +1262,12 @@ static int mmc_select_timing(struct mmc_card *card) if (!mmc_can_ext_csd(card)) if (!mmc_can_ext_csd(card)) goto bus_speed; goto bus_speed; if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200) /* For Enhance Strobe HS400 flow */ if (card->ext_csd.strobe_support && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400 && card->host->caps & MMC_CAP_8_BIT_DATA) err = mmc_select_hs400(card); else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200) err = mmc_select_hs200(card); err = mmc_select_hs200(card); else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS) else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS) err = mmc_select_hs(card); err = mmc_select_hs(card); Loading drivers/mmc/host/sdhci-msm.c +50 −2 Original line number Original line Diff line number Diff line Loading @@ -151,7 +151,9 @@ #define CORE_DDR_200_CFG 0x184 #define CORE_DDR_200_CFG 0x184 #define CORE_CDC_T4_DLY_SEL (1 << 0) #define CORE_CDC_T4_DLY_SEL (1 << 0) #define CORE_CMDIN_RCLK_EN (1 << 1) #define CORE_START_CDC_TRAFFIC (1 << 6) #define CORE_START_CDC_TRAFFIC (1 << 6) #define CORE_VENDOR_SPEC3 0x1B0 #define CORE_VENDOR_SPEC3 0x1B0 #define CORE_PWRSAVE_DLL (1 << 3) #define CORE_PWRSAVE_DLL (1 << 3) Loading Loading @@ -771,6 +773,11 @@ static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host) */ */ writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr + CORE_DDR_CONFIG); writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr + CORE_DDR_CONFIG); if (msm_host->enhanced_strobe) 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 */ /* Write 1 to DDR_CAL_EN field in CORE_DLL_CONFIG_2 */ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2) writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2) | CORE_DDR_CAL_EN), | CORE_DDR_CAL_EN), Loading Loading @@ -805,6 +812,42 @@ out: return ret; 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) { pr_debug("%s: host 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) static int sdhci_msm_hs400_dll_calibration(struct sdhci_host *host) { { int ret = 0; int ret = 0; Loading Loading @@ -2543,7 +2586,8 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) * Select HS400 mode using the HC_SELECT_IN from VENDOR SPEC * Select HS400 mode using the HC_SELECT_IN from VENDOR SPEC * register * register */ */ if (msm_host->tuning_done && !msm_host->calibration_done) { if ((msm_host->tuning_done || msm_host->enhanced_strobe) && !msm_host->calibration_done) { /* /* * Write 0x6 to HC_SELECT_IN and 1 to HC_SELECT_IN_EN * Write 0x6 to HC_SELECT_IN and 1 to HC_SELECT_IN_EN * field in VENDOR_SPEC_FUNC * field in VENDOR_SPEC_FUNC Loading Loading @@ -2772,6 +2816,7 @@ static struct sdhci_ops sdhci_msm_ops = { .set_uhs_signaling = sdhci_msm_set_uhs_signaling, .set_uhs_signaling = sdhci_msm_set_uhs_signaling, .check_power_status = sdhci_msm_check_power_status, .check_power_status = sdhci_msm_check_power_status, .platform_execute_tuning = sdhci_msm_execute_tuning, .platform_execute_tuning = sdhci_msm_execute_tuning, .enhanced_strobe = sdhci_msm_enhanced_strobe, .toggle_cdr = sdhci_msm_toggle_cdr, .toggle_cdr = sdhci_msm_toggle_cdr, .get_max_segments = sdhci_msm_max_segs, .get_max_segments = sdhci_msm_max_segs, .set_clock = sdhci_msm_set_clock, .set_clock = sdhci_msm_set_clock, Loading Loading @@ -2829,9 +2874,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 * SDCC 5 controller with major version 1, minor version 0x42 and later * will require additional steps when resetting DLL. * 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->use_updated_dll_reset = true; msm_host->enhanced_strobe = true; } /* /* * SDCC 5 controller with major version 1 and minor version 0x42, * SDCC 5 controller with major version 1 and minor version 0x42, Loading drivers/mmc/host/sdhci-msm.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -154,6 +154,7 @@ struct sdhci_msm_host { bool use_cdclp533; bool use_cdclp533; bool use_updated_dll_reset; bool use_updated_dll_reset; bool use_14lpp_dll; bool use_14lpp_dll; bool enhanced_strobe; u32 caps_0; u32 caps_0; struct sdhci_msm_ice_data ice; struct sdhci_msm_ice_data ice; u32 ice_clk_rate; u32 ice_clk_rate; Loading drivers/mmc/host/sdhci.c +15 −0 Original line number Original line Diff line number Diff line Loading @@ -60,6 +60,7 @@ static void sdhci_finish_data(struct sdhci_host *); static void sdhci_finish_command(struct sdhci_host *); static void sdhci_finish_command(struct sdhci_host *); static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode); 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_tuning_timer(unsigned long data); static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); static void sdhci_show_adma_error(struct sdhci_host *host); static void sdhci_show_adma_error(struct sdhci_host *host); Loading Loading @@ -2274,6 +2275,19 @@ static int sdhci_card_busy(struct mmc_host *mmc) return !(present_state & SDHCI_DATA_LVL_MASK); 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 = 0; 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) static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) { { struct sdhci_host *host = mmc_priv(mmc); struct sdhci_host *host = mmc_priv(mmc); Loading Loading @@ -2539,6 +2553,7 @@ static const struct mmc_host_ops sdhci_ops = { .enable_sdio_irq = sdhci_enable_sdio_irq, .enable_sdio_irq = sdhci_enable_sdio_irq, .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, .execute_tuning = sdhci_execute_tuning, .execute_tuning = sdhci_execute_tuning, .enhanced_strobe = sdhci_enhanced_strobe, .card_event = sdhci_card_event, .card_event = sdhci_card_event, .card_busy = sdhci_card_busy, .card_busy = sdhci_card_busy, .enable = sdhci_enable, .enable = sdhci_enable, Loading drivers/mmc/host/sdhci.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -320,6 +320,7 @@ struct sdhci_ops { #define REQ_IO_LOW (1 << 2) #define REQ_IO_LOW (1 << 2) #define REQ_IO_HIGH (1 << 3) #define REQ_IO_HIGH (1 << 3) void (*card_event)(struct sdhci_host *host); void (*card_event)(struct sdhci_host *host); int (*enhanced_strobe)(struct sdhci_host *host); void (*platform_bus_voting)(struct sdhci_host *host, u32 enable); void (*platform_bus_voting)(struct sdhci_host *host, u32 enable); void (*dump_vendor_regs)(struct sdhci_host *host); void (*dump_vendor_regs)(struct sdhci_host *host); int (*config_auto_tuning_cmd)(struct sdhci_host *host, int (*config_auto_tuning_cmd)(struct sdhci_host *host, Loading Loading
drivers/mmc/core/mmc.c +49 −7 Original line number Original line Diff line number Diff line Loading @@ -652,6 +652,11 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) } } if (card->ext_csd.rev >= 7) { if (card->ext_csd.rev >= 7) { /* Enhance Strobe is supported since v5.1 which rev should be * 8 but some eMMC devices can support it with rev 7. So handle * Enhance Strobe here. */ card->ext_csd.strobe_support = ext_csd[EXT_CSD_STROBE_SUPPORT]; card->ext_csd.cmdq_support = ext_csd[EXT_CSD_CMDQ_SUPPORT]; card->ext_csd.cmdq_support = ext_csd[EXT_CSD_CMDQ_SUPPORT]; if (card->ext_csd.cmdq_support) { if (card->ext_csd.cmdq_support) { /* /* Loading Loading @@ -1100,13 +1105,33 @@ static int mmc_select_hs400(struct mmc_card *card) { { struct mmc_host *host = card->host; struct mmc_host *host = card->host; int err = 0; int err = 0; u8 val; /* /* * HS400 mode requires 8-bit bus width * HS400 mode requires 8-bit bus width */ */ if (card->ext_csd.strobe_support) { if (!(card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400 && host->caps & MMC_CAP_8_BIT_DATA)) return 0; /* For Enhance Strobe flow. For non Enhance Strobe, signal * voltage will not be set. */ if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V) err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V) err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); if (err) return err; } else { if (!(card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400 && if (!(card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400 && host->ios.bus_width == MMC_BUS_WIDTH_8)) host->ios.bus_width == MMC_BUS_WIDTH_8)) return 0; return 0; } /* /* * Before switching to dual data rate operation for HS400, * Before switching to dual data rate operation for HS400, Loading @@ -1125,9 +1150,16 @@ static int mmc_select_hs400(struct mmc_card *card) return err; return err; } } val = EXT_CSD_DDR_BUS_WIDTH_8; if (card->ext_csd.strobe_support) { err = mmc_select_bus_width(card); if (IS_ERR_VALUE(err)) return err; val |= EXT_CSD_BUS_WIDTH_STROBE; } err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH, EXT_CSD_DDR_BUS_WIDTH_8, val, card->ext_csd.generic_cmd6_time); card->ext_csd.generic_cmd6_time); if (err) { if (err) { pr_warn("%s: switch to bus width for hs400 failed, err:%d\n", pr_warn("%s: switch to bus width for hs400 failed, err:%d\n", Loading @@ -1148,7 +1180,12 @@ static int mmc_select_hs400(struct mmc_card *card) mmc_set_timing(host, MMC_TIMING_MMC_HS400); mmc_set_timing(host, MMC_TIMING_MMC_HS400); mmc_set_bus_speed(card); mmc_set_bus_speed(card); if ((host->caps2 & MMC_CAP2_HS400_POST_TUNING) && host->ops->execute_tuning) { if (host->ops->enhanced_strobe) { mmc_host_clk_hold(host); err = host->ops->enhanced_strobe(host); mmc_host_clk_release(host); } else if ((host->caps2 & MMC_CAP2_HS400_POST_TUNING) && host->ops->execute_tuning) { mmc_host_clk_hold(host); mmc_host_clk_hold(host); err = host->ops->execute_tuning(host, err = host->ops->execute_tuning(host, MMC_SEND_TUNING_BLOCK_HS200); MMC_SEND_TUNING_BLOCK_HS200); Loading @@ -1159,7 +1196,7 @@ static int mmc_select_hs400(struct mmc_card *card) mmc_hostname(host)); mmc_hostname(host)); } } return 0; return err; } } /* /* Loading Loading @@ -1225,7 +1262,12 @@ static int mmc_select_timing(struct mmc_card *card) if (!mmc_can_ext_csd(card)) if (!mmc_can_ext_csd(card)) goto bus_speed; goto bus_speed; if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200) /* For Enhance Strobe HS400 flow */ if (card->ext_csd.strobe_support && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400 && card->host->caps & MMC_CAP_8_BIT_DATA) err = mmc_select_hs400(card); else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200) err = mmc_select_hs200(card); err = mmc_select_hs200(card); else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS) else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS) err = mmc_select_hs(card); err = mmc_select_hs(card); Loading
drivers/mmc/host/sdhci-msm.c +50 −2 Original line number Original line Diff line number Diff line Loading @@ -151,7 +151,9 @@ #define CORE_DDR_200_CFG 0x184 #define CORE_DDR_200_CFG 0x184 #define CORE_CDC_T4_DLY_SEL (1 << 0) #define CORE_CDC_T4_DLY_SEL (1 << 0) #define CORE_CMDIN_RCLK_EN (1 << 1) #define CORE_START_CDC_TRAFFIC (1 << 6) #define CORE_START_CDC_TRAFFIC (1 << 6) #define CORE_VENDOR_SPEC3 0x1B0 #define CORE_VENDOR_SPEC3 0x1B0 #define CORE_PWRSAVE_DLL (1 << 3) #define CORE_PWRSAVE_DLL (1 << 3) Loading Loading @@ -771,6 +773,11 @@ static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host) */ */ writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr + CORE_DDR_CONFIG); writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr + CORE_DDR_CONFIG); if (msm_host->enhanced_strobe) 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 */ /* Write 1 to DDR_CAL_EN field in CORE_DLL_CONFIG_2 */ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2) writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2) | CORE_DDR_CAL_EN), | CORE_DDR_CAL_EN), Loading Loading @@ -805,6 +812,42 @@ out: return ret; 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) { pr_debug("%s: host 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) static int sdhci_msm_hs400_dll_calibration(struct sdhci_host *host) { { int ret = 0; int ret = 0; Loading Loading @@ -2543,7 +2586,8 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) * Select HS400 mode using the HC_SELECT_IN from VENDOR SPEC * Select HS400 mode using the HC_SELECT_IN from VENDOR SPEC * register * register */ */ if (msm_host->tuning_done && !msm_host->calibration_done) { if ((msm_host->tuning_done || msm_host->enhanced_strobe) && !msm_host->calibration_done) { /* /* * Write 0x6 to HC_SELECT_IN and 1 to HC_SELECT_IN_EN * Write 0x6 to HC_SELECT_IN and 1 to HC_SELECT_IN_EN * field in VENDOR_SPEC_FUNC * field in VENDOR_SPEC_FUNC Loading Loading @@ -2772,6 +2816,7 @@ static struct sdhci_ops sdhci_msm_ops = { .set_uhs_signaling = sdhci_msm_set_uhs_signaling, .set_uhs_signaling = sdhci_msm_set_uhs_signaling, .check_power_status = sdhci_msm_check_power_status, .check_power_status = sdhci_msm_check_power_status, .platform_execute_tuning = sdhci_msm_execute_tuning, .platform_execute_tuning = sdhci_msm_execute_tuning, .enhanced_strobe = sdhci_msm_enhanced_strobe, .toggle_cdr = sdhci_msm_toggle_cdr, .toggle_cdr = sdhci_msm_toggle_cdr, .get_max_segments = sdhci_msm_max_segs, .get_max_segments = sdhci_msm_max_segs, .set_clock = sdhci_msm_set_clock, .set_clock = sdhci_msm_set_clock, Loading Loading @@ -2829,9 +2874,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 * SDCC 5 controller with major version 1, minor version 0x42 and later * will require additional steps when resetting DLL. * 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->use_updated_dll_reset = true; msm_host->enhanced_strobe = true; } /* /* * SDCC 5 controller with major version 1 and minor version 0x42, * SDCC 5 controller with major version 1 and minor version 0x42, Loading
drivers/mmc/host/sdhci-msm.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -154,6 +154,7 @@ struct sdhci_msm_host { bool use_cdclp533; bool use_cdclp533; bool use_updated_dll_reset; bool use_updated_dll_reset; bool use_14lpp_dll; bool use_14lpp_dll; bool enhanced_strobe; u32 caps_0; u32 caps_0; struct sdhci_msm_ice_data ice; struct sdhci_msm_ice_data ice; u32 ice_clk_rate; u32 ice_clk_rate; Loading
drivers/mmc/host/sdhci.c +15 −0 Original line number Original line Diff line number Diff line Loading @@ -60,6 +60,7 @@ static void sdhci_finish_data(struct sdhci_host *); static void sdhci_finish_command(struct sdhci_host *); static void sdhci_finish_command(struct sdhci_host *); static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode); 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_tuning_timer(unsigned long data); static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); static void sdhci_show_adma_error(struct sdhci_host *host); static void sdhci_show_adma_error(struct sdhci_host *host); Loading Loading @@ -2274,6 +2275,19 @@ static int sdhci_card_busy(struct mmc_host *mmc) return !(present_state & SDHCI_DATA_LVL_MASK); 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 = 0; 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) static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) { { struct sdhci_host *host = mmc_priv(mmc); struct sdhci_host *host = mmc_priv(mmc); Loading Loading @@ -2539,6 +2553,7 @@ static const struct mmc_host_ops sdhci_ops = { .enable_sdio_irq = sdhci_enable_sdio_irq, .enable_sdio_irq = sdhci_enable_sdio_irq, .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, .execute_tuning = sdhci_execute_tuning, .execute_tuning = sdhci_execute_tuning, .enhanced_strobe = sdhci_enhanced_strobe, .card_event = sdhci_card_event, .card_event = sdhci_card_event, .card_busy = sdhci_card_busy, .card_busy = sdhci_card_busy, .enable = sdhci_enable, .enable = sdhci_enable, Loading
drivers/mmc/host/sdhci.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -320,6 +320,7 @@ struct sdhci_ops { #define REQ_IO_LOW (1 << 2) #define REQ_IO_LOW (1 << 2) #define REQ_IO_HIGH (1 << 3) #define REQ_IO_HIGH (1 << 3) void (*card_event)(struct sdhci_host *host); void (*card_event)(struct sdhci_host *host); int (*enhanced_strobe)(struct sdhci_host *host); void (*platform_bus_voting)(struct sdhci_host *host, u32 enable); void (*platform_bus_voting)(struct sdhci_host *host, u32 enable); void (*dump_vendor_regs)(struct sdhci_host *host); void (*dump_vendor_regs)(struct sdhci_host *host); int (*config_auto_tuning_cmd)(struct sdhci_host *host, int (*config_auto_tuning_cmd)(struct sdhci_host *host, Loading