Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c9e2c0f9 authored by Vijay Viswanath's avatar Vijay Viswanath
Browse files

mmc: sdhci-msm: Add support to scale bus aggregate clock



Bus aggregate clock needs to be scaled according to the power mode in
which the apps clock is running. Add support to read the supported
clock rates of bus aggregate clock and scale this clock based on what
frequency the apps clock is running.

Change-Id: I28fbb1ca50a09fa7753222fe18d2b0774063fc1b
Signed-off-by: default avatarVijay Viswanath <vviswana@codeaurora.org>
parent 0bbf24ae
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -41,6 +41,11 @@ Optional Properties:
				"HS200_1p2v" - indicates that host can support HS200 at 1.2v.
				"DDR_1p8v" - indicates that host can support DDR mode at 1.8v.
				"DDR_1p2v" - indicates that host can support DDR mode at 1.2v.
	  - qcom,bus-aggr-clk-rates: this is an array that specifies the frequency for
	  			the bus-aggr-clk which should be set corresponding to the
				frequency used from clk-rate. The Frequency of this clock
				should be decided based on the power mode in which the
				apps clk would run with frequency in clk-rates.
	- qcom,devfreq,freq-table - specifies supported frequencies for clock scaling.
				    Clock scaling logic shall toggle between these frequencies based
				    on card load. In case the defined frequencies are over or below
+59 −0
Original line number Diff line number Diff line
@@ -1900,6 +1900,8 @@ struct sdhci_msm_pltfm_data *sdhci_msm_populate_pdata(struct device *dev,
	u32 *ice_clk_table = NULL;
	enum of_gpio_flags flags = OF_GPIO_ACTIVE_LOW;
	const char *lower_bus_speed = NULL;
	int bus_clk_table_len;
	u32 *bus_clk_table = NULL;

	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
	if (!pdata) {
@@ -1955,6 +1957,14 @@ struct sdhci_msm_pltfm_data *sdhci_msm_populate_pdata(struct device *dev,
	pdata->sup_clk_table = clk_table;
	pdata->sup_clk_cnt = clk_table_len;

	if (!sdhci_msm_dt_get_array(dev, "qcom,bus-aggr-clk-rates",
			&bus_clk_table, &bus_clk_table_len, 0)) {
		if (bus_clk_table && bus_clk_table_len) {
			pdata->bus_clk_table = bus_clk_table;
			pdata->bus_clk_cnt = bus_clk_table_len;
		}
	}

	if (msm_host->ice.pdev) {
		if (sdhci_msm_dt_get_array(dev, "qcom,ice-clk-rates",
				&ice_clk_table, &ice_clk_table_len, 0)) {
@@ -2962,6 +2972,34 @@ static unsigned int sdhci_msm_get_sup_clk_rate(struct sdhci_host *host,
	return sel_clk;
}

static long sdhci_msm_get_bus_aggr_clk_rate(struct sdhci_host *host,
						u32 apps_clk)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_msm_host *msm_host = pltfm_host->priv;
	long sel_clk = -1;
	unsigned char cnt;

	if (msm_host->pdata->bus_clk_cnt != msm_host->pdata->sup_clk_cnt) {
		pr_err("%s: %s: mismatch between bus_clk_cnt(%u) and apps_clk_cnt(%u)\n",
				mmc_hostname(host->mmc), __func__,
				(unsigned int)msm_host->pdata->bus_clk_cnt,
				(unsigned int)msm_host->pdata->sup_clk_cnt);
		return msm_host->pdata->bus_clk_table[0];
	}
	if (apps_clk == sdhci_msm_get_min_clock(host)) {
		sel_clk = msm_host->pdata->bus_clk_table[0];
		return sel_clk;
	}

	for (cnt = 0; cnt < msm_host->pdata->bus_clk_cnt; cnt++) {
		if (msm_host->pdata->sup_clk_table[cnt] > apps_clk)
			break;
		sel_clk = msm_host->pdata->bus_clk_table[cnt];
	}
	return sel_clk;
}

static void sdhci_msm_registers_save(struct sdhci_host *host)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -3251,6 +3289,7 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
	struct mmc_card *card = host->mmc->card;
	struct mmc_ios	curr_ios = host->mmc->ios;
	u32 sup_clock, ddr_clock, dll_lock;
	long bus_clk_rate;
	bool curr_pwrsave;

	if (!clock) {
@@ -3405,6 +3444,26 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
		msm_host->clk_rate = sup_clock;
		host->clock = clock;

		if (!IS_ERR(msm_host->bus_aggr_clk) &&
				msm_host->pdata->bus_clk_cnt) {
			bus_clk_rate = sdhci_msm_get_bus_aggr_clk_rate(host,
					sup_clock);
			if (bus_clk_rate >= 0) {
				rc = clk_set_rate(msm_host->bus_aggr_clk,
						bus_clk_rate);
				if (rc) {
					pr_err("%s: %s: Failed to set rate %ld for bus-aggr-clk : %d\n",
						mmc_hostname(host->mmc),
						__func__, bus_clk_rate, rc);
					goto out;
				}
			} else {
				pr_err("%s: %s: Unsupported apps clk rate %u for bus-aggr-clk, err: %ld\n",
					mmc_hostname(host->mmc), __func__,
					sup_clock, bus_clk_rate);
			}
		}

		/* Configure pinctrl drive type according to
		 * current clock rate
		 */
+2 −0
Original line number Diff line number Diff line
@@ -159,6 +159,8 @@ struct sdhci_msm_pltfm_data {
	u32 ice_clk_min;
	u32 ddr_config;
	bool rclk_wa;
	u32 *bus_clk_table;
	unsigned char bus_clk_cnt;
};

struct sdhci_msm_bus_vote {