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

Commit 28275f6c authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: kgsl: Use the proper power level indexes"

parents cec636d8 b801ab94
Loading
Loading
Loading
Loading
+16 −145
Original line number Diff line number Diff line
@@ -1151,62 +1151,6 @@ static void a6xx_sptprac_disable(struct adreno_device *adreno_dev)
		dev_err(&gmu->pdev->dev, "power off SPTPRAC fail\n");
}

/*
 * a6xx_hm_enable() - Power on HM and turn on clock
 * @adreno_dev: Pointer to Adreno device
 */
static int a6xx_hm_enable(struct adreno_device *adreno_dev)
{
	int ret;
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
	struct gmu_device *gmu = &device->gmu;

	if (regulator_is_enabled(gmu->gx_gdsc))
		return 0;

	ret = regulator_enable(gmu->gx_gdsc);
	if (ret) {
		dev_err(&gmu->pdev->dev,
			"Failed to turn on GPU HM HS\n");
		return ret;
	}

	ret = clk_set_rate(pwr->grp_clks[0],
			pwr->pwrlevels[pwr->default_pwrlevel].
			gpu_freq);
	if (ret)
		return ret;

	return clk_prepare_enable(pwr->grp_clks[0]);
}

/*
 * a6xx_hm_disable() - Turn off HM clock and power off
 * @adreno_dev: Pointer to Adreno device
 */
static int a6xx_hm_disable(struct adreno_device *adreno_dev)
{
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
	struct gmu_device *gmu = &device->gmu;

	if (!regulator_is_enabled(gmu->gx_gdsc))
		return 0;

	/* Ensure that retention is on */
	kgsl_gmu_regrmw(device, A6XX_GPU_CC_GX_GDSCR, 0,
			A6XX_RETAIN_FF_ENABLE_ENABLE_MASK);

	clk_disable_unprepare(pwr->grp_clks[0]);

	clk_set_rate(pwr->grp_clks[0],
			pwr->pwrlevels[pwr->num_pwrlevels - 1].
			gpu_freq);

	return regulator_disable(gmu->gx_gdsc);
}

#define SPTPRAC_POWER_OFF	BIT(2)
#define SP_CLK_OFF		BIT(4)
#define GX_GDSC_POWER_OFF	BIT(6)
@@ -1257,62 +1201,6 @@ static bool a6xx_sptprac_is_on(struct adreno_device *adreno_dev)
	return !(val & (SPTPRAC_POWER_OFF | SP_CLK_OFF));
}

/*
 * a6xx_hm_sptprac_enable() - Turn on HM and SPTPRAC
 * @device: Pointer to KGSL device
 */
static int a6xx_hm_sptprac_enable(struct kgsl_device *device)
{
	int ret = 0;
	struct gmu_device *gmu = &device->gmu;

	/* If GMU does not control HM we must */
	if (gmu->idle_level < GPU_HW_IFPC) {

		ret = a6xx_hm_enable(ADRENO_DEVICE(device));
		if (ret) {
			dev_err(&gmu->pdev->dev, "Failed to power on GPU HM\n");
			return ret;
		}


	}

	/* If GMU does not control SPTPRAC we must */
	if (gmu->idle_level < GPU_HW_SPTP_PC) {
		ret = a6xx_sptprac_enable(ADRENO_DEVICE(device));
		if (ret) {
			a6xx_hm_disable(ADRENO_DEVICE(device));
			return ret;
		}
	}

	return ret;
}

/*
 * a6xx_hm_sptprac_disable() - Turn off SPTPRAC and HM
 * @device: Pointer to KGSL device
 */
static int a6xx_hm_sptprac_disable(struct kgsl_device *device)
{
	int ret = 0;
	struct gmu_device *gmu = &device->gmu;

	/* If GMU does not control SPTPRAC we must */
	if (gmu->idle_level < GPU_HW_SPTP_PC)
		a6xx_sptprac_disable(ADRENO_DEVICE(device));

	/* If GMU does not control HM we must */
	if (gmu->idle_level < GPU_HW_IFPC) {
		ret = a6xx_hm_disable(ADRENO_DEVICE(device));
		if (ret)
			dev_err(&gmu->pdev->dev, "Failed to power off GPU HM\n");
	}

	return ret;
}

/*
 * a6xx_gfx_rail_on() - request GMU to power GPU at given OPP.
 * @device: Pointer to KGSL device
@@ -1363,6 +1251,9 @@ static int a6xx_notify_slumber(struct kgsl_device *device)
	/* Disable the power counter so that the GMU is not busy */
	kgsl_gmu_regwrite(device, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 0);

	/* Turn off SPTPRAC before GMU turns off GX */
	a6xx_sptprac_disable(adreno_dev);

	if (!ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG)) {
		ret = hfi_notify_slumber(gmu, perf_idx, bus_level);
		return ret;
@@ -1398,7 +1289,6 @@ static int a6xx_rpmh_power_on_gpu(struct kgsl_device *device)
{
	struct gmu_device *gmu = &device->gmu;
	struct device *dev = &gmu->pdev->dev;
	int ret = 0;

	/* RSC wake sequence */
	kgsl_gmu_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, BIT(1));
@@ -1424,13 +1314,10 @@ static int a6xx_rpmh_power_on_gpu(struct kgsl_device *device)

	kgsl_gmu_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, 0);

	/* Turn on the HM and SPTP head switches */
	ret = a6xx_hm_sptprac_enable(device);

	/* Enable the power counter because it was disabled before slumber */
	kgsl_gmu_regwrite(device, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 1);

	return ret;
	return 0;
error_rsc:
	dev_err(dev, "GPU RSC sequence stuck in waking up GPU\n");
	return -EINVAL;
@@ -1440,10 +1327,7 @@ static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device)
{
	struct gmu_device *gmu = &device->gmu;
	const struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	int val, ret = 0;

	/* Turn off the SPTP and HM head switches */
	ret = a6xx_hm_sptprac_disable(device);
	int val;

	/* RSC sleep sequence */
	kgsl_gmu_regwrite(device, A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0, 1);
@@ -1472,7 +1356,7 @@ static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device)

	/* FIXME: v2 has different procedure to trigger sequence */

	return ret;
	return 0;
}

#define KMASK(start, n) (GENMASK((start + n), (start)))
@@ -1564,25 +1448,12 @@ static int a6xx_gmu_fw_start(struct kgsl_device *device,
	case GMU_RESET:
		/* fall through */
	case GMU_COLD_BOOT:
		/* Turn on the HM and SPTP head switches */
		ret = a6xx_hm_sptprac_enable(device);
		if (ret)
			return ret;

		/* Turn on TCM retention */
		kgsl_gmu_regwrite(device, A6XX_GMU_GENERAL_7, 1);

		if (!test_and_set_bit(GMU_BOOT_INIT_DONE, &gmu->flags)) {
		if (!test_and_set_bit(GMU_BOOT_INIT_DONE, &gmu->flags))
			_load_gmu_rpmh_ucode(device);
			/* Turn on the HM and SPTP head switches */
			ret = a6xx_hm_sptprac_enable(device);
			if (ret)
				return ret;
		} else if (boot_state == GMU_RESET) {
			ret = a6xx_hm_sptprac_enable(device);
			if (ret)
				return ret;
		} else {
		else if (boot_state != GMU_RESET) {
			ret = a6xx_rpmh_power_on_gpu(device);
			if (ret)
				return ret;
@@ -1646,6 +1517,12 @@ static int a6xx_gmu_fw_start(struct kgsl_device *device,
		}
	}

	if (gmu->idle_level < GPU_HW_SPTP_PC) {
		ret = a6xx_sptprac_enable(adreno_dev);
		if (ret)
			return ret;
	}

	ret = a6xx_gmu_hfi_start(device);
	if (ret)
		return ret;
@@ -1953,13 +1830,7 @@ static int a6xx_gmu_suspend(struct kgsl_device *device)
	/* Check no outstanding RPMh voting */
	a6xx_complete_rpmh_votes(device);

	if (gmu->idle_level < GPU_HW_IFPC) {
		/* HM GDSC is controlled by KGSL */
		ret = a6xx_hm_disable(ADRENO_DEVICE(device));
		if (ret)
			dev_err(&gmu->pdev->dev,
				"suspend: fail: power off GPU HM\n");
	} else if (gmu->gx_gdsc) {
	if (gmu->gx_gdsc) {
		if (regulator_is_enabled(gmu->gx_gdsc)) {
			/* Switch gx gdsc control from GMU to CPU
			 * force non-zero reference count in clk driver
+65 −63
Original line number Diff line number Diff line
@@ -505,7 +505,11 @@ static int rpmh_arc_cmds(struct gmu_device *gmu,
	}

	cmd_db_get_aux_data(res_id, (uint8_t *)arc->val, len);
	arc->num = len >> 1;
	for (arc->num = 1; arc->num <= MAX_GX_LEVELS; arc->num++) {
		if (arc->num == MAX_GX_LEVELS ||
				arc->val[arc->num - 1] >= arc->val[arc->num])
			break;
	}

	return 0;
}
@@ -528,35 +532,42 @@ static int setup_volt_dependency_tbl(struct arc_vote_desc *votes,
{
	int i, j, k;
	uint16_t cur_vlvl;
	bool found_match;

	/* i tracks current KGSL GPU frequency table entry
	 * j tracks second rail voltage table entry
	 * k tracks primary rail voltage table entry
	 */
	for (i = 0, k = 0; i < num_entries; k++) {
		if (pri_rail->val[k] != vlvl[i]) {
			if (k >= pri_rail->num)
				return -EINVAL;
			continue;
		}
	for (i = 0; i < num_entries; i++) {
		found_match = false;

		/* Look for a primary rail voltage that matches a VLVL level */
		for (k = 0; k < pri_rail->num; k++) {
			if (pri_rail->val[k] == vlvl[i]) {
				votes[i].pri_idx = k;
				votes[i].vlvl = vlvl[i];
				cur_vlvl = vlvl[i];
				found_match = true;
				break;
			}
		}

		/* If we did not find a matching VLVL level then abort */
		if (!found_match)
			return -EINVAL;

		/* find index of second rail vlvl array element that
		 * its vlvl >= current vlvl of primary rail
		/*
		 * Look for a secondary rail index whose VLVL value
		 * is greater than or equal to the VLVL value of the
		 * corresponding index of the primary rail
		 */
		for (j = 0; j < sec_rail->num; j++) {
			if (sec_rail->val[j] >= cur_vlvl) {
			if (sec_rail->val[j] >= cur_vlvl ||
					j + 1 == sec_rail->num) {
				votes[i].sec_idx = j;
				break;
			}
		}

		if (j == sec_rail->num)
			votes[i].sec_idx = j;

		i++;
	}
	return 0;
}
@@ -575,26 +586,25 @@ static int rpmh_arc_votes_init(struct gmu_device *gmu,
		struct rpmh_arc_vals *sec_rail,
		unsigned int type)
{
	struct device *dev;
	struct kgsl_device *device = container_of(gmu, struct kgsl_device, gmu);
	unsigned int num_freqs;
	struct arc_vote_desc *votes;
	unsigned int vlvl_tbl[MAX_GX_LEVELS];
	unsigned int *freq_tbl;
	int i, ret;
	/*
	 * FIXME: remove below two arrays after OPP VLVL query API ready
	 * struct dev_pm_opp *opp;
	 */
	uint16_t gpu_vlvl[] = {0, 128, 256, 384};
	uint16_t cx_vlvl[] = {0, 48, 256};
	struct dev_pm_opp *opp;

	if (type == GPU_ARC_VOTE) {
		num_freqs = gmu->num_gpupwrlevels;
		votes = gmu->rpmh_votes.gx_votes;
		freq_tbl = gmu->gmu_freqs;
		freq_tbl = gmu->gpu_freqs;
		dev = &device->pdev->dev;
	} else if (type == GMU_ARC_VOTE) {
		num_freqs = gmu->num_gmupwrlevels;
		votes = gmu->rpmh_votes.cx_votes;
		freq_tbl = gmu->gpu_freqs;
		freq_tbl = gmu->gmu_freqs;
		dev = &gmu->pdev->dev;
	} else {
		return -EINVAL;
	}
@@ -606,26 +616,25 @@ static int rpmh_arc_votes_init(struct gmu_device *gmu,
		return -EINVAL;
	}

	/*
	 * FIXME: Find a core's voltage VLVL value based on its frequency
	 *	using OPP framework, waiting for David Colin, ETA Jan.
	 */
	memset(vlvl_tbl, 0, sizeof(vlvl_tbl));
	for (i = 0; i < num_freqs; i++) {
		/*
		 * opp = dev_pm_opp_find_freq_exact(&gmu->pdev->dev,
		 *		freq_tbl[i], true);
		 * if (IS_ERR(opp)) {
		 *	dev_err(&gmu->pdev->dev,
		 *			"Failed to find opp freq %d of %s\n",
		 *			freq_tbl[i], debug_strs[type]);
		 *	return PTR_ERR(opp);
		 * }
		 * vlvl_tbl[i] = dev_pm_opp_get_voltage(opp);
		 */
		if (type == GPU_ARC_VOTE)
			vlvl_tbl[i] = gpu_vlvl[i];
		else
			vlvl_tbl[i] = cx_vlvl[i];
		/* Hardcode VLVL for 0 because it is not registered in OPP */
		if (freq_tbl[i] == 0) {
			vlvl_tbl[i] = 0;
			continue;
		}

		/* Otherwise get the value from the OPP API */
		opp = dev_pm_opp_find_freq_exact(dev, freq_tbl[i], true);
		if (IS_ERR(opp)) {
			dev_err(&gmu->pdev->dev,
				"Failed to find opp freq %d of %s\n",
				freq_tbl[i], debug_strs[type]);
			return PTR_ERR(opp);
		}

		/* Values from OPP framework are offset by 1 */
		vlvl_tbl[i] = dev_pm_opp_get_voltage(opp) - 1;
	}

	ret = setup_volt_dependency_tbl(votes,
@@ -1130,6 +1139,7 @@ int gmu_probe(struct kgsl_device *device)
		goto error;

	gmu->num_gpupwrlevels = pwr->num_pwrlevels;
	gmu->wakeup_pwrlevel = pwr->default_pwrlevel;

	for (i = 0; i < gmu->num_gpupwrlevels; i++) {
		int j = gmu->num_gpupwrlevels - 1 - i;
@@ -1337,12 +1347,11 @@ static int gmu_suspend(struct kgsl_device *device)
/* To be called to power on both GPU and GMU */
int gmu_start(struct kgsl_device *device)
{
	int ret = 0, perf_idx;
	int ret = 0;
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
	struct gmu_device *gmu = &device->gmu;
	int bus_level = pwr->pwrlevels[pwr->default_pwrlevel].bus_freq;

	switch (device->state) {
	case KGSL_STATE_INIT:
@@ -1351,13 +1360,9 @@ int gmu_start(struct kgsl_device *device)
		gmu_enable_gdsc(gmu);
		gmu_enable_clks(gmu);

		/* Convert to RPMh frequency index */
		perf_idx = gmu->num_gpupwrlevels -
				pwr->default_pwrlevel - 1;

		/* Vote for 300MHz DDR for GMU to init */
		ret = msm_bus_scale_client_update_request(gmu->pcl,
				bus_level);
				pwr->pwrlevels[pwr->default_pwrlevel].bus_freq);
		if (ret) {
			dev_err(&gmu->pdev->dev,
					"Failed to allocate gmu b/w\n");
@@ -1376,7 +1381,8 @@ int gmu_start(struct kgsl_device *device)
			goto error_gpu;

		/* Send default DCVS level */
		ret = gmu_dcvs_set(gmu, perf_idx, bus_level);
		ret = gmu_dcvs_set(gmu, pwr->default_pwrlevel,
				pwr->pwrlevels[pwr->default_pwrlevel].bus_freq);
		if (ret)
			goto error_gpu;

@@ -1388,8 +1394,6 @@ int gmu_start(struct kgsl_device *device)
		gmu_enable_gdsc(gmu);
		gmu_enable_clks(gmu);

		perf_idx = gmu->num_gpupwrlevels - gmu->wakeup_pwrlevel - 1;

		ret = gpudev->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_START,
				GMU_WARM_BOOT, 0);
		if (ret)
@@ -1402,7 +1406,9 @@ int gmu_start(struct kgsl_device *device)
			goto error_gpu;

		if (gmu->wakeup_pwrlevel != pwr->default_pwrlevel) {
			ret = gmu_dcvs_set(gmu, perf_idx, bus_level);
			ret = gmu_dcvs_set(gmu, gmu->wakeup_pwrlevel,
					pwr->pwrlevels[gmu->wakeup_pwrlevel]
					.bus_freq);
			if (ret)
				goto error_gpu;
			gmu->wakeup_pwrlevel = pwr->default_pwrlevel;
@@ -1415,11 +1421,6 @@ int gmu_start(struct kgsl_device *device)
			gmu_enable_gdsc(gmu);
			gmu_enable_clks(gmu);

			perf_idx = gmu->num_gpupwrlevels -
				pwr->active_pwrlevel - 1;

			bus_level =
				pwr->pwrlevels[pwr->active_pwrlevel].bus_freq;
			ret = gpudev->rpmh_gpu_pwrctrl(
				adreno_dev, GMU_FW_START, GMU_RESET, 0);
			if (ret)
@@ -1432,7 +1433,9 @@ int gmu_start(struct kgsl_device *device)
				goto error_gpu;

			/* Send DCVS level prior to reset*/
			ret = gmu_dcvs_set(gmu, perf_idx, bus_level);
			ret = gmu_dcvs_set(gmu, pwr->active_pwrlevel,
					pwr->pwrlevels[pwr->active_pwrlevel]
					.bus_freq);
			if (ret)
				goto error_gpu;

@@ -1441,9 +1444,8 @@ int gmu_start(struct kgsl_device *device)
				OOB_CPINIT_CHECK_MASK,
				OOB_CPINIT_CLEAR_MASK);

		} else {
		} else
			gmu_fast_boot(device);
		}
		break;
	default:
		break;
+12 −5
Original line number Diff line number Diff line
@@ -253,23 +253,30 @@ static int kgsl_clk_set_rate(struct kgsl_device *device,
{
	struct gmu_device *gmu = &device->gmu;
	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
	struct kgsl_pwrlevel *pl = &pwr->pwrlevels[pwrlevel];
	int ret = 0;

	/* GMU scales GPU freq */
	if (kgsl_gmu_isenabled(device)) {
		/* If GMU has not been started, save it */
		if (!(gmu->flags & GMU_HFI_ON)) {
			/* In slumber the clock is off so we are done */
			if (pwrlevel == (gmu->num_gpupwrlevels - 1))
				return 0;

			gmu->wakeup_pwrlevel = pwrlevel;
			return 0;
		}

		/* If the GMU is on we cannot vote for the lowest level */
		if (pwrlevel == (gmu->num_gpupwrlevels - 1)) {
			WARN(1, "Cannot set 0 GPU frequency with GMU\n");
			return -EINVAL;
		}
		ret = gmu_dcvs_set(gmu, pwrlevel, INVALID_DCVS_IDX);
	} else {
	} else
		/* Linux clock driver scales GPU freq */
		struct kgsl_pwrlevel *Pl = &pwr->pwrlevels[pwrlevel];

		ret = clk_set_rate(pwr->grp_clks[0], Pl->gpu_freq);
	}
		ret = clk_set_rate(pwr->grp_clks[0], pl->gpu_freq);

	if (ret)
		KGSL_PWR_ERR(device, "GPU clk freq set failure\n");