diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index a97cf76b44c1..03ad1a6c2e17 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -396,7 +396,8 @@ struct sdhci_msm_host { int pwr_irq; /* power irq */ struct clk *bus_clk; /* SDHC bus voter clock */ struct clk *xo_clk; /* TCXO clk needed for FLL feature of cm_dll*/ - struct clk_bulk_data bulk_clks[4]; /* core, iface, cal, sleep clocks */ + /* core, iface, ice, cal, sleep clocks */ + struct clk_bulk_data bulk_clks[5]; unsigned long clk_rate; struct sdhci_msm_vreg_data *vreg_data; struct mmc_host *mmc; @@ -427,6 +428,11 @@ struct sdhci_msm_host { bool use_7nm_dll; struct sdhci_msm_dll_hsr *dll_hsr; struct sdhci_msm_regs_restore regs_restore; + u32 *sup_ice_clk_table; + unsigned char sup_ice_clk_cnt; + u32 ice_clk_max; + u32 ice_clk_min; + u32 ice_clk_rate; struct workqueue_struct *workq; /* QoS work queue */ struct sdhci_msm_qos_req *sdhci_qos; struct irq_affinity_notify affinity_notify; @@ -1638,6 +1644,8 @@ static bool sdhci_msm_populate_pdata(struct device *dev, struct sdhci_msm_host *msm_host) { struct device_node *np = dev->of_node; + int ice_clk_table_len; + u32 *ice_clk_table = NULL; msm_host->vreg_data = devm_kzalloc(dev, sizeof(struct sdhci_msm_vreg_data), @@ -1668,6 +1676,22 @@ static bool sdhci_msm_populate_pdata(struct device *dev, if (sdhci_msm_dt_parse_hsr_info(dev, msm_host)) goto out; + if (!sdhci_msm_dt_get_array(dev, "qcom,ice-clk-rates", + &ice_clk_table, &ice_clk_table_len, 0)) { + if (ice_clk_table && ice_clk_table_len) { + if (ice_clk_table_len != 2) { + dev_err(dev, "Need max and min frequencies\n"); + goto out; + } + msm_host->sup_ice_clk_table = ice_clk_table; + msm_host->sup_ice_clk_cnt = ice_clk_table_len; + msm_host->ice_clk_max = msm_host->sup_ice_clk_table[0]; + msm_host->ice_clk_min = msm_host->sup_ice_clk_table[1]; + dev_dbg(dev, "ICE clock rates (Hz): max: %u min: %u\n", + msm_host->ice_clk_max, msm_host->ice_clk_min); + } + } + return false; out: return true; @@ -3535,6 +3559,33 @@ static void sdhci_msm_setup_pm(struct platform_device *pdev, } } +static int sdhci_msm_setup_ice_clk(struct sdhci_msm_host *msm_host, + struct platform_device *pdev) +{ + int ret = 0; + struct clk *clk; + + msm_host->bulk_clks[2].clk = NULL; + + /* Setup SDC ICE clock */ + clk = devm_clk_get(&pdev->dev, "ice_core"); + if (!IS_ERR(clk)) { + msm_host->bulk_clks[2].clk = clk; + + /* Set maximum clock rate for ice clk */ + ret = clk_set_rate(clk, msm_host->ice_clk_max); + if (ret) { + dev_err(&pdev->dev, "ICE_CLK rate set failed (%d) for %u\n", + ret, msm_host->ice_clk_max); + return ret; + } + + msm_host->ice_clk_rate = msm_host->ice_clk_max; + } + + return ret; +} + static int sdhci_msm_probe(struct platform_device *pdev) { struct sdhci_host *host; @@ -3635,15 +3686,19 @@ static int sdhci_msm_probe(struct platform_device *pdev) if (ret) dev_warn(&pdev->dev, "core clock boost failed\n"); + ret = sdhci_msm_setup_ice_clk(msm_host, pdev); + if (ret) + goto bus_clk_disable; + clk = devm_clk_get(&pdev->dev, "cal"); if (IS_ERR(clk)) clk = NULL; - msm_host->bulk_clks[2].clk = clk; + msm_host->bulk_clks[3].clk = clk; clk = devm_clk_get(&pdev->dev, "sleep"); if (IS_ERR(clk)) clk = NULL; - msm_host->bulk_clks[3].clk = clk; + msm_host->bulk_clks[4].clk = clk; ret = clk_bulk_prepare_enable(ARRAY_SIZE(msm_host->bulk_clks), msm_host->bulk_clks);