Loading Documentation/devicetree/bindings/mmc/sdhci-msm.txt +12 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,18 @@ In the following, <supply> can be vdd (flash core voltage) or vdd-io (I/O voltag - qcom,wakeup-on-idle: if configured, the mmcqd thread will call set_wake_up_idle(), thereby voting for it to be called on idle CPUs. - qcom,late-sdhci-msm: if configured, the sdhci probe will be called in late_init() call context and probe will be delayed. - qcom,tsens-id: temperature sensor id which is closest to SDC host controller. - qcom,disable_scaling_threshold_temp: temperature value at which scaling is disabled if the temperature falls below this temperature. - qcom,enable_scaling_threshold_temp: temperature value at which scaling is enabled, when the scaling is disabled, if temperature rises above this temperature. Example: aliases { Loading arch/arm/boot/dts/qcom/msm8996pro-auto-adp.dts +9 −0 Original line number Diff line number Diff line Loading @@ -73,11 +73,20 @@ }; }; &sdhc_1 { qcom,tsens-id = <0>; }; &sdhc_2 { compatible = "qcom,late-sdhci-msm"; cd-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>; pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on_sbc>; pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_on_sbc>; qcom,tsens-id = <10>; qcom,disable_scaling_threshold_temp = <(-15)>; qcom,enable_scaling_threshold_temp = <(-5)>; }; &i2c_7 { Loading drivers/mmc/core/core.c +9 −1 Original line number Diff line number Diff line Loading @@ -285,6 +285,7 @@ static int mmc_devfreq_get_dev_status(struct device *dev, { struct mmc_host *host = container_of(dev, struct mmc_host, class_dev); struct mmc_devfeq_clk_scaling *clk_scaling; bool disable = false; if (!host) { pr_err("bad host parameter\n"); Loading Loading @@ -312,6 +313,13 @@ static int mmc_devfreq_get_dev_status(struct device *dev, } } if (host->ops->check_temp && host->card->clk_scaling_highest > UHS_DDR50_MAX_DTR) disable = host->ops->check_temp(host); /* busy_time=0 for running at low freq*/ if (disable) status->busy_time = 0; else status->busy_time = clk_scaling->total_busy_time_us; status->total_time = ktime_to_us(ktime_sub(ktime_get(), clk_scaling->measure_interval_start)); Loading drivers/mmc/core/sd.c +39 −1 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ #define UHS_SDR25_MIN_DTR (25 * 1000 * 1000) #define UHS_SDR12_MIN_DTR (12.5 * 1000 * 1000) #define ENOCALLBACK 1 static const unsigned int tran_exp[] = { 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 Loading Loading @@ -498,6 +500,10 @@ static int sd_set_bus_speed_mode(struct mmc_card *card, u8 *status) err = -EBUSY; } else { mmc_set_timing(card->host, timing); if (card->host->ops->check_temp(card->host) && timing == MMC_TIMING_UHS_SDR104) mmc_set_clock(card->host, UHS_SDR50_MAX_DTR); else mmc_set_clock(card->host, card->sw_caps.uhs_max_dtr); } Loading Loading @@ -1122,6 +1128,34 @@ free_card: return err; } static int mmc_sd_init_temp_control_clk_scaling(struct mmc_host *host) { int ret; if (host->ops->reg_temp_callback) { ret = host->ops->reg_temp_callback(host); } else { pr_err("%s: %s: couldn't find init temp control clk scaling cb\n", mmc_hostname(host), __func__); ret = -ENOCALLBACK; } return ret; } static int mmc_sd_dereg_temp_control_clk_scaling(struct mmc_host *host) { int ret; if (host->ops->dereg_temp_callback) { ret = host->ops->dereg_temp_callback(host); } else { pr_err("%s: %s: couldn't find dereg temp control clk scaling cb\n", mmc_hostname(host), __func__); ret = -ENOCALLBACK; } return ret; } /* * Host is being removed. Free up the current card. */ Loading @@ -1131,6 +1165,7 @@ static void mmc_sd_remove(struct mmc_host *host) BUG_ON(!host->card); mmc_exit_clk_scaling(host); mmc_sd_dereg_temp_control_clk_scaling(host); mmc_remove_card(host->card); mmc_claim_host(host); Loading Loading @@ -1458,6 +1493,9 @@ int mmc_attach_sd(struct mmc_host *host) goto err; } if (mmc_sd_init_temp_control_clk_scaling(host)) pr_err("%s: failed to init temp control clk scaling\n", mmc_hostname(host)); /* * Detect and init the card. */ Loading include/linux/mmc/host.h +3 −0 Original line number Diff line number Diff line Loading @@ -185,6 +185,9 @@ struct mmc_host_ops { int (*notify_load)(struct mmc_host *, enum mmc_load); void (*notify_halt)(struct mmc_host *mmc, bool halt); void (*force_err_irq)(struct mmc_host *host, u64 errmask); int (*check_temp)(struct mmc_host *host); int (*reg_temp_callback)(struct mmc_host *host); int (*dereg_temp_callback)(struct mmc_host *host); }; struct mmc_card; Loading Loading
Documentation/devicetree/bindings/mmc/sdhci-msm.txt +12 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,18 @@ In the following, <supply> can be vdd (flash core voltage) or vdd-io (I/O voltag - qcom,wakeup-on-idle: if configured, the mmcqd thread will call set_wake_up_idle(), thereby voting for it to be called on idle CPUs. - qcom,late-sdhci-msm: if configured, the sdhci probe will be called in late_init() call context and probe will be delayed. - qcom,tsens-id: temperature sensor id which is closest to SDC host controller. - qcom,disable_scaling_threshold_temp: temperature value at which scaling is disabled if the temperature falls below this temperature. - qcom,enable_scaling_threshold_temp: temperature value at which scaling is enabled, when the scaling is disabled, if temperature rises above this temperature. Example: aliases { Loading
arch/arm/boot/dts/qcom/msm8996pro-auto-adp.dts +9 −0 Original line number Diff line number Diff line Loading @@ -73,11 +73,20 @@ }; }; &sdhc_1 { qcom,tsens-id = <0>; }; &sdhc_2 { compatible = "qcom,late-sdhci-msm"; cd-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>; pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on_sbc>; pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_on_sbc>; qcom,tsens-id = <10>; qcom,disable_scaling_threshold_temp = <(-15)>; qcom,enable_scaling_threshold_temp = <(-5)>; }; &i2c_7 { Loading
drivers/mmc/core/core.c +9 −1 Original line number Diff line number Diff line Loading @@ -285,6 +285,7 @@ static int mmc_devfreq_get_dev_status(struct device *dev, { struct mmc_host *host = container_of(dev, struct mmc_host, class_dev); struct mmc_devfeq_clk_scaling *clk_scaling; bool disable = false; if (!host) { pr_err("bad host parameter\n"); Loading Loading @@ -312,6 +313,13 @@ static int mmc_devfreq_get_dev_status(struct device *dev, } } if (host->ops->check_temp && host->card->clk_scaling_highest > UHS_DDR50_MAX_DTR) disable = host->ops->check_temp(host); /* busy_time=0 for running at low freq*/ if (disable) status->busy_time = 0; else status->busy_time = clk_scaling->total_busy_time_us; status->total_time = ktime_to_us(ktime_sub(ktime_get(), clk_scaling->measure_interval_start)); Loading
drivers/mmc/core/sd.c +39 −1 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ #define UHS_SDR25_MIN_DTR (25 * 1000 * 1000) #define UHS_SDR12_MIN_DTR (12.5 * 1000 * 1000) #define ENOCALLBACK 1 static const unsigned int tran_exp[] = { 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 Loading Loading @@ -498,6 +500,10 @@ static int sd_set_bus_speed_mode(struct mmc_card *card, u8 *status) err = -EBUSY; } else { mmc_set_timing(card->host, timing); if (card->host->ops->check_temp(card->host) && timing == MMC_TIMING_UHS_SDR104) mmc_set_clock(card->host, UHS_SDR50_MAX_DTR); else mmc_set_clock(card->host, card->sw_caps.uhs_max_dtr); } Loading Loading @@ -1122,6 +1128,34 @@ free_card: return err; } static int mmc_sd_init_temp_control_clk_scaling(struct mmc_host *host) { int ret; if (host->ops->reg_temp_callback) { ret = host->ops->reg_temp_callback(host); } else { pr_err("%s: %s: couldn't find init temp control clk scaling cb\n", mmc_hostname(host), __func__); ret = -ENOCALLBACK; } return ret; } static int mmc_sd_dereg_temp_control_clk_scaling(struct mmc_host *host) { int ret; if (host->ops->dereg_temp_callback) { ret = host->ops->dereg_temp_callback(host); } else { pr_err("%s: %s: couldn't find dereg temp control clk scaling cb\n", mmc_hostname(host), __func__); ret = -ENOCALLBACK; } return ret; } /* * Host is being removed. Free up the current card. */ Loading @@ -1131,6 +1165,7 @@ static void mmc_sd_remove(struct mmc_host *host) BUG_ON(!host->card); mmc_exit_clk_scaling(host); mmc_sd_dereg_temp_control_clk_scaling(host); mmc_remove_card(host->card); mmc_claim_host(host); Loading Loading @@ -1458,6 +1493,9 @@ int mmc_attach_sd(struct mmc_host *host) goto err; } if (mmc_sd_init_temp_control_clk_scaling(host)) pr_err("%s: failed to init temp control clk scaling\n", mmc_hostname(host)); /* * Detect and init the card. */ Loading
include/linux/mmc/host.h +3 −0 Original line number Diff line number Diff line Loading @@ -185,6 +185,9 @@ struct mmc_host_ops { int (*notify_load)(struct mmc_host *, enum mmc_load); void (*notify_halt)(struct mmc_host *mmc, bool halt); void (*force_err_irq)(struct mmc_host *host, u64 errmask); int (*check_temp)(struct mmc_host *host); int (*reg_temp_callback)(struct mmc_host *host); int (*dereg_temp_callback)(struct mmc_host *host); }; struct mmc_card; Loading