diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 635bcd755e09..d35cc16436ba 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -1509,8 +1509,16 @@ struct sdhci_msm_pltfm_data *sdhci_msm_populate_pdata(struct device *dev, dev_err(dev, "Invalid clock table\n"); goto out; } + if (ice_clk_table_len != 2) { + dev_err(dev, "Need max and min frequencies in the table\n"); + goto out; + } pdata->sup_ice_clk_table = ice_clk_table; pdata->sup_ice_clk_cnt = ice_clk_table_len; + pdata->ice_clk_max = pdata->sup_ice_clk_table[0]; + pdata->ice_clk_min = pdata->sup_ice_clk_table[1]; + dev_dbg(dev, "supported ICE clock rates (Hz): max: %u min: %u\n", + pdata->ice_clk_max, pdata->ice_clk_min); } pdata->vreg_data = devm_kzalloc(dev, sizeof(struct @@ -2877,6 +2885,32 @@ static void sdhci_msm_detect(struct sdhci_host *host, bool detected) mmc->pm_caps &= ~MMC_PM_KEEP_POWER; } +int sdhci_msm_notify_load(struct sdhci_host *host, enum mmc_load state) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_msm_host *msm_host = pltfm_host->priv; + int ret = 0; + u32 clk_rate = 0; + + if (!IS_ERR(msm_host->ice_clk)) { + clk_rate = (state == MMC_LOAD_LOW) ? + msm_host->pdata->ice_clk_min : + msm_host->pdata->ice_clk_max; + if (msm_host->ice_clk_rate == clk_rate) + return 0; + pr_debug("%s: changing ICE clk rate to %u\n", + mmc_hostname(host->mmc), clk_rate); + ret = clk_set_rate(msm_host->ice_clk, clk_rate); + if (ret) { + pr_err("%s: ICE_CLK rate set failed (%d) for %u\n", + mmc_hostname(host->mmc), ret, clk_rate); + return ret; + } + msm_host->ice_clk_rate = clk_rate; + } + return 0; +} + static struct sdhci_ops sdhci_msm_ops = { .crypto_engine_cfg = sdhci_msm_ice_cfg, .crypto_engine_reset = sdhci_msm_ice_reset, @@ -2897,6 +2931,7 @@ static struct sdhci_ops sdhci_msm_ops = { .clear_set_dumpregs = sdhci_msm_clear_set_dumpregs, .enhanced_strobe_mask = sdhci_msm_enhanced_strobe_mask, .detect = sdhci_msm_detect, + .notify_load = sdhci_msm_notify_load, }; static void sdhci_set_default_hw_caps(struct sdhci_msm_host *msm_host, @@ -3132,11 +3167,11 @@ static int sdhci_msm_probe(struct platform_device *pdev) if (!IS_ERR(msm_host->ice_clk)) { /* ICE core has only one clock frequency for now */ ret = clk_set_rate(msm_host->ice_clk, - msm_host->pdata->sup_ice_clk_table[0]); + msm_host->pdata->ice_clk_max); if (ret) { dev_err(&pdev->dev, "ICE_CLK rate set failed (%d) for %u\n", ret, - msm_host->pdata->sup_ice_clk_table[0]); + msm_host->pdata->ice_clk_max); goto pclk_disable; } ret = clk_prepare_enable(msm_host->ice_clk); @@ -3144,7 +3179,7 @@ static int sdhci_msm_probe(struct platform_device *pdev) goto pclk_disable; msm_host->ice_clk_rate = - msm_host->pdata->sup_clk_table[0]; + msm_host->pdata->ice_clk_max; } } diff --git a/drivers/mmc/host/sdhci-msm.h b/drivers/mmc/host/sdhci-msm.h index e3e99c6f8097..1602668c0ff4 100644 --- a/drivers/mmc/host/sdhci-msm.h +++ b/drivers/mmc/host/sdhci-msm.h @@ -106,6 +106,8 @@ struct sdhci_msm_pltfm_data { enum pm_qos_req_type cpu_affinity_type; u32 *sup_ice_clk_table; unsigned char sup_ice_clk_cnt; + u32 ice_clk_max; + u32 ice_clk_min; }; struct sdhci_msm_bus_vote {