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

Commit bac0bb62 authored by Carter Cooper's avatar Carter Cooper
Browse files

msm: kgsl: Streamline OOB set/clear calls



Abstract out all the magic of an OOB set/clear to simplify the
interface. This will remove the chance of programming error. This
also reduces the complexity to add/remove additional OOB bits.

Change-Id: I15adf614b1def93ca56d87a02c9599077eb64dc7
Signed-off-by: default avatarCarter Cooper <ccooper@codeaurora.org>
parent 258b321e
Loading
Loading
Loading
Loading
+10 −17
Original line number Diff line number Diff line
@@ -1652,9 +1652,7 @@ static int _adreno_start(struct adreno_device *adreno_dev)

	/* Send OOB request to turn on the GX */
	if (gpudev->oob_set) {
		status = gpudev->oob_set(adreno_dev, OOB_GPU_SET_MASK,
				OOB_GPU_CHECK_MASK,
				OOB_GPU_CLEAR_MASK);
		status = gpudev->oob_set(adreno_dev, oob_gpu);
		if (status)
			goto error_mmu_off;
	}
@@ -1832,19 +1830,18 @@ static int _adreno_start(struct adreno_device *adreno_dev)

	/* Send OOB request to allow IFPC */
	if (gpudev->oob_clear) {
		gpudev->oob_clear(adreno_dev, OOB_GPU_CLEAR_MASK);
		gpudev->oob_clear(adreno_dev, oob_gpu);

		/* If we made it this far, the BOOT OOB was sent to the GMU */
		if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG))
			gpudev->oob_clear(adreno_dev,
					OOB_BOOT_SLUMBER_CLEAR_MASK);
			gpudev->oob_clear(adreno_dev, oob_boot_slumber);
	}

	return 0;

error_oob_clear:
	if (gpudev->oob_clear)
		gpudev->oob_clear(adreno_dev, OOB_GPU_CLEAR_MASK);
		gpudev->oob_clear(adreno_dev, oob_gpu);

error_mmu_off:
	kgsl_mmu_stop(&device->mmu);
@@ -1897,13 +1894,11 @@ static int adreno_stop(struct kgsl_device *device)

	/* Turn the power on one last time before stopping */
	if (gpudev->oob_set) {
		error = gpudev->oob_set(adreno_dev, OOB_GPU_SET_MASK,
				OOB_GPU_CHECK_MASK,
				OOB_GPU_CLEAR_MASK);
		error = gpudev->oob_set(adreno_dev, oob_gpu);
		if (error) {
			struct gmu_device *gmu = &device->gmu;

			gpudev->oob_clear(adreno_dev, OOB_GPU_CLEAR_MASK);
			gpudev->oob_clear(adreno_dev, oob_gpu);
			if (gmu->gx_gdsc &&
				regulator_is_enabled(gmu->gx_gdsc)) {
				/* GPU is on. Try recovery */
@@ -1938,7 +1933,7 @@ static int adreno_stop(struct kgsl_device *device)
	adreno_perfcounter_save(adreno_dev);

	if (gpudev->oob_clear)
		gpudev->oob_clear(adreno_dev, OOB_GPU_CLEAR_MASK);
		gpudev->oob_clear(adreno_dev, oob_gpu);

	/*
	 * Saving perfcounters will use an OOB to put the GMU into
@@ -2596,9 +2591,7 @@ int adreno_soft_reset(struct kgsl_device *device)
	int ret;

	if (gpudev->oob_set) {
		ret = gpudev->oob_set(adreno_dev, OOB_GPU_SET_MASK,
				OOB_GPU_CHECK_MASK,
				OOB_GPU_CLEAR_MASK);
		ret = gpudev->oob_set(adreno_dev, oob_gpu);
		if (ret)
			return ret;
	}
@@ -2622,7 +2615,7 @@ int adreno_soft_reset(struct kgsl_device *device)
		ret = _soft_reset(adreno_dev);
	if (ret) {
		if (gpudev->oob_clear)
			gpudev->oob_clear(adreno_dev, OOB_GPU_CLEAR_MASK);
			gpudev->oob_clear(adreno_dev, oob_gpu);
		return ret;
	}

@@ -2676,7 +2669,7 @@ int adreno_soft_reset(struct kgsl_device *device)
	adreno_perfcounter_restore(adreno_dev);

	if (gpudev->oob_clear)
		gpudev->oob_clear(adreno_dev, OOB_GPU_CLEAR_MASK);
		gpudev->oob_clear(adreno_dev, oob_gpu);

	return ret;
}
+5 −8
Original line number Diff line number Diff line
@@ -948,11 +948,10 @@ struct adreno_gpudev {
	void (*llc_configure_gpuhtw_scid)(struct adreno_device *adreno_dev);
	void (*llc_enable_overrides)(struct adreno_device *adreno_dev);
	void (*pre_reset)(struct adreno_device *);
	int (*oob_set)(struct adreno_device *adreno_dev, unsigned int set_mask,
				unsigned int check_mask,
				unsigned int clear_mask);
	int (*oob_set)(struct adreno_device *adreno_dev,
			enum oob_request req);
	void (*oob_clear)(struct adreno_device *adreno_dev,
				unsigned int clear_mask);
			enum oob_request req);
	void (*gpu_keepalive)(struct adreno_device *adreno_dev,
			bool state);
	int (*rpmh_gpu_pwrctrl)(struct adreno_device *, unsigned int ops,
@@ -1856,9 +1855,7 @@ static inline int adreno_perfcntr_active_oob_get(
		return ret;

	if (gpudev->oob_set) {
		ret = gpudev->oob_set(adreno_dev, OOB_PERFCNTR_SET_MASK,
				OOB_PERFCNTR_CHECK_MASK,
				OOB_PERFCNTR_CLEAR_MASK);
		ret = gpudev->oob_set(adreno_dev, oob_perfcntr);
		if (ret)
			kgsl_active_count_put(KGSL_DEVICE(adreno_dev));
	}
@@ -1872,7 +1869,7 @@ static inline void adreno_perfcntr_active_oob_put(
	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);

	if (gpudev->oob_clear)
		gpudev->oob_clear(adreno_dev, OOB_PERFCNTR_CLEAR_MASK);
		gpudev->oob_clear(adreno_dev, oob_perfcntr);

	kgsl_active_count_put(KGSL_DEVICE(adreno_dev));
}
+31 −66
Original line number Diff line number Diff line
@@ -74,9 +74,6 @@ static const struct adreno_vbif_platform a6xx_vbif_platforms[] = {
	{ adreno_is_a640, a640_gbif },
};


static unsigned long a6xx_oob_state_bitmask;

struct kgsl_hwcg_reg {
	unsigned int off;
	unsigned int val;
@@ -1579,64 +1576,56 @@ static int a6xx_gmu_hfi_start(struct kgsl_device *device)
/*
 * a6xx_oob_set() - Set OOB interrupt to GMU.
 * @adreno_dev: Pointer to adreno device
 * @set_mask: set_mask is a bitmask that defines a set of OOB
 *	interrupts to trigger.
 * @check_mask: check_mask is a bitmask that provides a set of
 *	OOB ACK bits. check_mask usually matches set_mask to
 *	ensure OOBs are handled.
 * @clear_mask: After GMU handles a OOB interrupt, GMU driver
 *	clears the interrupt. clear_mask is a bitmask defines
 *	a set of OOB interrupts to clear.
 * @req: Which of the OOB bits to request
 */
static int a6xx_oob_set(struct adreno_device *adreno_dev,
		unsigned int set_mask, unsigned int check_mask,
		unsigned int clear_mask)
		enum oob_request req)
{
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	int ret = 0;
	int set, check;

	if (!kgsl_gmu_isenabled(device) || !clear_mask)
	if (!kgsl_gmu_isenabled(device))
		return 0;

	kgsl_gmu_regwrite(device, A6XX_GMU_HOST2GMU_INTR_SET, set_mask);
	set = BIT(req + 16);
	check = BIT(req + 24);

	kgsl_gmu_regwrite(device, A6XX_GMU_HOST2GMU_INTR_SET, set);

	if (timed_poll_check(device,
			A6XX_GMU_GMU2HOST_INTR_INFO,
			check_mask,
			check,
			GPU_START_TIMEOUT,
			check_mask)) {
			check)) {
		ret = -ETIMEDOUT;
		WARN(1, "OOB set timed out, mask %x\n", set_mask);
		dev_err(&device->gmu.pdev->dev,
			"OOB_set(0x%x) timed out\n", set);
	}

	kgsl_gmu_regwrite(device, A6XX_GMU_GMU2HOST_INTR_CLR, clear_mask);

	set_bit((fls(clear_mask) - 1), &a6xx_oob_state_bitmask);
	kgsl_gmu_regwrite(device, A6XX_GMU_GMU2HOST_INTR_CLR, check);

	trace_kgsl_gmu_oob_set(set_mask);
	trace_kgsl_gmu_oob_set(set);
	return ret;
}

/*
 * a6xx_oob_clear() - Clear a previously set  OOB request.
 * @adreno_dev: Pointer to the adreno device that has the GMU
 * @clear_mask: Bitmask that provides the OOB bits to clear
 * @req: Which of the OOB bits to clear
 */
static inline void a6xx_oob_clear(struct adreno_device *adreno_dev,
		unsigned int clear_mask)
		enum oob_request req)
{
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	int clear;

	if (!kgsl_gmu_isenabled(device) || !clear_mask)
	if (!kgsl_gmu_isenabled(device))
		return;

	if (test_and_clear_bit(fls(clear_mask) - 1,
				&a6xx_oob_state_bitmask))
		kgsl_gmu_regwrite(device,
			A6XX_GMU_HOST2GMU_INTR_SET,
			clear_mask);

	trace_kgsl_gmu_oob_clear(clear_mask);
	clear = BIT(req + 24);
	kgsl_gmu_regwrite(device, A6XX_GMU_HOST2GMU_INTR_SET, clear);
	trace_kgsl_gmu_oob_clear(clear);
}

/*
@@ -1767,7 +1756,6 @@ static int a6xx_gfx_rail_on(struct kgsl_device *device)
	struct gmu_device *gmu = &device->gmu;
	unsigned int perf_idx = pwr->num_pwrlevels - pwr->default_pwrlevel - 1;
	uint32_t default_opp = gmu->rpmh_votes.gx_votes[perf_idx];
	int ret;

	kgsl_gmu_regwrite(device, A6XX_GMU_BOOT_SLUMBER_OPTION,
			OOB_BOOT_OPTION);
@@ -1776,14 +1764,7 @@ static int a6xx_gfx_rail_on(struct kgsl_device *device)
	kgsl_gmu_regwrite(device, A6XX_GMU_MX_VOTE_IDX,
			ARC_VOTE_GET_SEC(default_opp));

	ret = a6xx_oob_set(adreno_dev, OOB_BOOT_SLUMBER_SET_MASK,
			OOB_BOOT_SLUMBER_CHECK_MASK,
			OOB_BOOT_SLUMBER_CLEAR_MASK);

	if (ret)
		dev_err(&gmu->pdev->dev, "Boot OOB timed out\n");

	return ret;
	return a6xx_oob_set(adreno_dev, oob_boot_slumber);
}

#define GMU_POWER_STATE_SLUMBER 15
@@ -1823,14 +1804,10 @@ static int a6xx_notify_slumber(struct kgsl_device *device)
	kgsl_gmu_regwrite(device, A6XX_GMU_GX_VOTE_IDX, perf_idx);
	kgsl_gmu_regwrite(device, A6XX_GMU_MX_VOTE_IDX, bus_level);

	ret = a6xx_oob_set(adreno_dev, OOB_BOOT_SLUMBER_SET_MASK,
			OOB_BOOT_SLUMBER_CHECK_MASK,
			OOB_BOOT_SLUMBER_CLEAR_MASK);
	a6xx_oob_clear(adreno_dev, OOB_BOOT_SLUMBER_CLEAR_MASK);
	ret = a6xx_oob_set(adreno_dev, oob_boot_slumber);
	a6xx_oob_clear(adreno_dev, oob_boot_slumber);

	if (ret)
		dev_err(&gmu->pdev->dev, "Notify slumber OOB timed out\n");
	else {
	if (!ret) {
		kgsl_gmu_regread(device,
			A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE, &state);
		if (state != GPU_HW_SLUMBER) {
@@ -2032,8 +2009,7 @@ static int a6xx_gmu_fw_start(struct kgsl_device *device,
	if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG)) {
		ret = a6xx_gfx_rail_on(device);
		if (ret) {
			a6xx_oob_clear(adreno_dev,
					OOB_BOOT_SLUMBER_CLEAR_MASK);
			a6xx_oob_clear(adreno_dev, oob_boot_slumber);
			return ret;
		}
	}
@@ -2068,7 +2044,6 @@ static int a6xx_gmu_dcvs_nohfi(struct kgsl_device *device,
		unsigned int perf_idx, unsigned int bw_idx)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct gmu_device *gmu = &device->gmu;
	int ret;

	kgsl_gmu_regwrite(device, A6XX_GMU_DCVS_ACK_OPTION, DCVS_ACK_NONBLOCK);
@@ -2078,20 +2053,11 @@ static int a6xx_gmu_dcvs_nohfi(struct kgsl_device *device,

	kgsl_gmu_regwrite(device, A6XX_GMU_DCVS_BW_SETTING, BW_VOTE(bw_idx));

	ret = a6xx_oob_set(adreno_dev, OOB_DCVS_SET_MASK, OOB_DCVS_CHECK_MASK,
		OOB_DCVS_CLEAR_MASK);

	if (ret) {
		dev_err(&gmu->pdev->dev, "DCVS OOB timed out\n");
		goto done;
	}

	ret = a6xx_oob_set(adreno_dev, oob_dcvs);
	if (ret == 0)
		kgsl_gmu_regread(device, A6XX_GMU_DCVS_RETURN, &ret);
	if (ret)
		dev_err(&gmu->pdev->dev, "OOB DCVS error %d\n", ret);

done:
	a6xx_oob_clear(adreno_dev, OOB_DCVS_CLEAR_MASK);
	a6xx_oob_clear(adreno_dev, oob_dcvs);

	return ret;
}
@@ -2459,8 +2425,7 @@ static int a6xx_rpmh_gpu_pwrctrl(struct adreno_device *adreno_dev,
		break;
	case GMU_FW_STOP:
		if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG))
			a6xx_oob_clear(adreno_dev,
					OOB_BOOT_SLUMBER_CLEAR_MASK);
			a6xx_oob_clear(adreno_dev, oob_boot_slumber);
		ret = a6xx_rpmh_power_off_gpu(device);
		break;
	case GMU_DCVS_NOHFI:
+3 −7
Original line number Diff line number Diff line
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -45,10 +45,7 @@ static void _update_wptr(struct adreno_device *adreno_dev, bool reset_timer)
		int status;

		if (gpudev->oob_set) {
			status = gpudev->oob_set(adreno_dev,
				OOB_PREEMPTION_SET_MASK,
				OOB_PREEMPTION_CHECK_MASK,
				OOB_PREEMPTION_CLEAR_MASK);
			status = gpudev->oob_set(adreno_dev, oob_preempt);
			if (status)
				return;
		}
@@ -77,8 +74,7 @@ static void _update_wptr(struct adreno_device *adreno_dev, bool reset_timer)

	if (in_interrupt() == 0) {
		if (gpudev->oob_clear)
			gpudev->oob_clear(adreno_dev,
				OOB_PREEMPTION_CLEAR_MASK);
			gpudev->oob_clear(adreno_dev, oob_preempt);
	}
}

+3 −5
Original line number Diff line number Diff line
/* Copyright (c) 2002,2007-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2002,2007-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -181,9 +181,7 @@ inline void adreno_perfcounter_save(struct adreno_device *adreno_dev)
		return;

	if (gpudev->oob_set)
		ret = gpudev->oob_set(adreno_dev, OOB_PERFCNTR_SET_MASK,
				OOB_PERFCNTR_CHECK_MASK,
				OOB_PERFCNTR_CLEAR_MASK);
		ret = gpudev->oob_set(adreno_dev, oob_perfcntr);

	/* if oob_set timeout, clear the mask and return */
	if (ret)
@@ -211,7 +209,7 @@ inline void adreno_perfcounter_save(struct adreno_device *adreno_dev)

done:
	if (gpudev->oob_clear)
		gpudev->oob_clear(adreno_dev, OOB_PERFCNTR_CLEAR_MASK);
		gpudev->oob_clear(adreno_dev, oob_perfcntr);
}

static int adreno_perfcounter_enable(struct adreno_device *adreno_dev,
Loading