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

Commit df8425d2 authored by Hareesh Gundu's avatar Hareesh Gundu
Browse files

msm: kgsl: Move some helper functions out of gmu



Some of the gmu functions have common functionality
across A6xx GPUs. Move out these helper function from
gmu so that it can be reusable.

Change-Id: Idf623544854329a27ecbe52f28bbd2e90941fcba
Signed-off-by: default avatarHareesh Gundu <hareeshg@codeaurora.org>
parent b8900bc7
Loading
Loading
Loading
Loading
+42 −1
Original line number Diff line number Diff line
@@ -3111,9 +3111,50 @@ static void adreno_regwrite(struct kgsl_device *device,
	__raw_writel(value, reg);
}

/**
 * adreno_gmu_clear_and_unmask_irqs() - Clear pending IRQs and Unmask IRQs
 * @adreno_dev: Pointer to the Adreno device that owns the GMU
 */
void adreno_gmu_clear_and_unmask_irqs(struct adreno_device *adreno_dev)
{
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	struct gmu_dev_ops *gmu_dev_ops = GMU_DEVICE_OPS(device);

	/* Clear any pending IRQs before unmasking on GMU */
	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_CLR,
			0xFFFFFFFF);
	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR,
			0xFFFFFFFF);

	/* Unmask needed IRQs on GMU */
	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_MASK,
			(unsigned int) ~(gmu_dev_ops->gmu2host_intr_mask));
	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK,
			(unsigned int) ~(gmu_dev_ops->gmu_ao_intr_mask));
}

/**
 * adreno_gmu_mask_and_clear_irqs() - Mask all IRQs and clear pending IRQs
 * @adreno_dev: Pointer to the Adreno device that owns the GMU
 */
void adreno_gmu_mask_and_clear_irqs(struct adreno_device *adreno_dev)
{
	/* Mask all IRQs on GMU */
	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK,
			0xFFFFFFFF);
	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_MASK,
			0xFFFFFFFF);

	/* Clear any pending IRQs before disabling */
	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR,
			0xFFFFFFFF);
	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_CLR,
			0xFFFFFFFF);
}

/*
 * adreno_gmu_fenced_write() - Check if there is a GMU and it is enabled
 * @adreno_dev: Pointer to the Adreno device device that owns the GMU
 * @adreno_dev: Pointer to the Adreno device that owns the GMU
 * @offset: 32bit register enum that is to be written
 * @val: The value to be written to the register
 * @fence_mask: The value to poll the fence status register
+2 −1
Original line number Diff line number Diff line
@@ -1935,7 +1935,8 @@ static inline void adreno_deassert_gbif_halt(struct adreno_device *adreno_dev)
	if (adreno_has_gbif(adreno_dev))
		adreno_writereg(adreno_dev, ADRENO_REG_GBIF_HALT, 0x0);
}

void adreno_gmu_clear_and_unmask_irqs(struct adreno_device *adreno_dev);
void adreno_gmu_mask_and_clear_irqs(struct adreno_device *adreno_dev);
int adreno_gmu_fenced_write(struct adreno_device *adreno_dev,
	enum adreno_regs offset, unsigned int val,
	unsigned int fence_mask);
+41 −3
Original line number Diff line number Diff line
@@ -1123,6 +1123,44 @@ static int a6xx_rb_start(struct adreno_device *adreno_dev,
	return a6xx_post_start(adreno_dev);
}

/*
 * a6xx_sptprac_enable() - Power on SPTPRAC
 * @adreno_dev: Pointer to Adreno device
 */
static int a6xx_sptprac_enable(struct adreno_device *adreno_dev)
{
	if (!adreno_has_sptprac_gdsc(adreno_dev))
		return 0;

	return a6xx_gmu_sptprac_enable(adreno_dev);
}

/*
 * a6xx_sptprac_disable() - Power off SPTPRAC
 * @adreno_dev: Pointer to Adreno device
 */
static void a6xx_sptprac_disable(struct adreno_device *adreno_dev)
{
	if (!adreno_has_sptprac_gdsc(adreno_dev))
		return;

	a6xx_gmu_sptprac_disable(adreno_dev);
}

/*
 * a6xx_sptprac_is_on() - Check if SPTP is on using pwr status register
 * @adreno_dev - Pointer to adreno_device
 * This check should only be performed if the keepalive bit is set or it
 * can be guaranteed that the power state of the GPU will remain unchanged
 */
bool a6xx_sptprac_is_on(struct adreno_device *adreno_dev)
{
	if (!adreno_has_sptprac_gdsc(adreno_dev))
		return true;

	return a6xx_gmu_sptprac_is_on(adreno_dev);
}

unsigned int a6xx_set_marker(
		unsigned int *cmds, enum adreno_cp_marker_type type)
{
@@ -2813,8 +2851,8 @@ struct adreno_gpudev adreno_a6xx_gpudev = {
	.platform_setup = a6xx_platform_setup,
	.init = a6xx_init,
	.rb_start = a6xx_rb_start,
	.regulator_enable = a6xx_gmu_sptprac_enable,
	.regulator_disable = a6xx_gmu_sptprac_disable,
	.regulator_enable = a6xx_sptprac_enable,
	.regulator_disable = a6xx_sptprac_disable,
	.perfcounters = &a6xx_perfcounters,
	.enable_pwr_counters = a6xx_enable_pwr_counters,
	.count_throttles = a6xx_count_throttles,
@@ -2836,7 +2874,7 @@ struct adreno_gpudev adreno_a6xx_gpudev = {
	.preemption_context_init = a6xx_preemption_context_init,
	.preemption_context_destroy = a6xx_preemption_context_destroy,
	.gx_is_on = a6xx_gmu_gx_is_on,
	.sptprac_is_on = a6xx_gmu_sptprac_is_on,
	.sptprac_is_on = a6xx_sptprac_is_on,
	.ccu_invalidate = a6xx_ccu_invalidate,
	.perfcounter_update = a6xx_perfcounter_update,
	.coresight = {&a6xx_coresight, &a6xx_coresight_cx},
+62 −2
Original line number Diff line number Diff line
@@ -106,6 +106,68 @@ struct cpu_gpu_lock {
#define A6XX_CP_RB_CNTL_DEFAULT (((ilog2(4) << 8) & 0x1F00) | \
		(ilog2(KGSL_RB_DWORDS >> 1) & 0x3F))

/*
 * timed_poll_check() - polling *gmu* register at given offset until
 * its value changed to match expected value. The function times
 * out and returns after given duration if register is not updated
 * as expected.
 *
 * @device: Pointer to KGSL device
 * @offset: Register offset
 * @expected_ret: expected register value that stops polling
 * @timout: number of jiffies to abort the polling
 * @mask: bitmask to filter register value to match expected_ret
 */
static inline int timed_poll_check(struct kgsl_device *device,
		unsigned int offset, unsigned int expected_ret,
		unsigned int timeout, unsigned int mask)
{
	unsigned long t;
	unsigned int value;

	t = jiffies + msecs_to_jiffies(timeout);

	do {
		gmu_core_regread(device, offset, &value);
		if ((value & mask) == expected_ret)
			return 0;
		/* Wait 100us to reduce unnecessary AHB bus traffic */
		usleep_range(10, 100);
	} while (!time_after(jiffies, t));

	/* Double check one last time */
	gmu_core_regread(device, offset, &value);
	if ((value & mask) == expected_ret)
		return 0;

	return -ETIMEDOUT;
}

/*
 * read_AO_counter() - Returns the 64bit always on counter value
 *
 * @device: Pointer to KGSL device
 */
static inline uint64_t read_AO_counter(struct kgsl_device *device)
{
	unsigned int l, h, h1;

	gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h);
	gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l);
	gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h1);

	/*
	 * If there's no change in COUNTER_H we have no overflow so return,
	 * otherwise read COUNTER_L again
	 */

	if (h == h1)
		return (uint64_t) l | ((uint64_t) h << 32);

	gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l);
	return (uint64_t) l | ((uint64_t) h1 << 32);
}

/* Preemption functions */
void a6xx_preemption_trigger(struct adreno_device *adreno_dev);
void a6xx_preemption_schedule(struct adreno_device *adreno_dev);
@@ -131,8 +193,6 @@ void a6xx_snapshot(struct adreno_device *adreno_dev,
		struct kgsl_snapshot *snapshot);
void a6xx_snapshot_debugbus(struct adreno_device *adreno_dev,
		struct kgsl_snapshot *snapshot);
void a6xx_gmu_snapshot(struct adreno_device *adreno_dev,
		struct kgsl_snapshot *snapshot);
void a6xx_crashdump_init(struct adreno_device *adreno_dev);
int a6xx_gmu_sptprac_enable(struct adreno_device *adreno_dev);
void a6xx_gmu_sptprac_disable(struct adreno_device *adreno_dev);
+39 −70
Original line number Diff line number Diff line
@@ -11,9 +11,8 @@
 *
 */
#include <linux/firmware.h>
#include <soc/qcom/subsystem_restart.h>
#include <linux/pm_opp.h>
#include <linux/jiffies.h>
#include <linux/interrupt.h>

#include "kgsl_gmu_core.h"
#include "kgsl_gmu.h"
@@ -171,48 +170,13 @@ static void _load_gmu_rpmh_ucode(struct kgsl_device *device)
	wmb();
}

/* GMU timeouts */
#define GMU_IDLE_TIMEOUT	100	/* ms */
#define GMU_START_TIMEOUT	100	/* ms */
#define GPU_START_TIMEOUT	100	/* ms */
#define GPU_RESET_TIMEOUT	1	/* ms */
#define GPU_RESET_TIMEOUT_US	10	/* us */

/*
 * timed_poll_check() - polling *gmu* register at given offset until
 * its value changed to match expected value. The function times
 * out and returns after given duration if register is not updated
 * as expected.
 *
 * @device: Pointer to KGSL device
 * @offset: Register offset
 * @expected_ret: expected register value that stops polling
 * @timout: number of jiffies to abort the polling
 * @mask: bitmask to filter register value to match expected_ret
 */
static int timed_poll_check(struct kgsl_device *device,
		unsigned int offset, unsigned int expected_ret,
		unsigned int timeout, unsigned int mask)
{
	unsigned long t;
	unsigned int value;

	t = jiffies + msecs_to_jiffies(timeout);

	do {
		gmu_core_regread(device, offset, &value);
		if ((value & mask) == expected_ret)
			return 0;
		/* Wait 100us to reduce unnecessary AHB bus traffic */
		usleep_range(10, 100);
	} while (!time_after(jiffies, t));

	/* Double check one last time */
	gmu_core_regread(device, offset, &value);
	if ((value & mask) == expected_ret)
		return 0;

	return -EINVAL;
}

/*
 * The lowest 16 bits of this value are the number of XO clock cycles
 * for main hysteresis. This is the first hysteresis. Here we set it
@@ -334,26 +298,6 @@ static int a6xx_gmu_hfi_start(struct kgsl_device *device)
	return 0;
}

static uint64_t read_AO_counter(struct kgsl_device *device)
{
	unsigned int l, h, h1;

	gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h);
	gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l);
	gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h1);

	/*
	 * If there's no change in COUNTER_H we have no overflow so return,
	 * otherwise read COUNTER_L again
	 */

	if (h == h1)
		return (uint64_t) l | ((uint64_t) h << 32);

	gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l);
	return (uint64_t) l | ((uint64_t) h1 << 32);
}

static int a6xx_rpmh_power_on_gpu(struct kgsl_device *device)
{
	struct gmu_device *gmu = KGSL_GMU_DEVICE(device);
@@ -621,6 +565,32 @@ static inline void a6xx_gmu_oob_clear(struct adreno_device *adreno_dev,
	trace_kgsl_gmu_oob_clear(clear);
}

static void a6xx_gmu_irq_enable(struct kgsl_device *device)
{
	struct gmu_device *gmu = KGSL_GMU_DEVICE(device);
	struct kgsl_hfi *hfi = &gmu->hfi;

	/* Clear pending IRQs and Unmask needed IRQs */
	adreno_gmu_clear_and_unmask_irqs(ADRENO_DEVICE(device));

	/* Enable all IRQs on host */
	enable_irq(hfi->hfi_interrupt_num);
	enable_irq(gmu->gmu_interrupt_num);
}

static void a6xx_gmu_irq_disable(struct kgsl_device *device)
{
	struct gmu_device *gmu = KGSL_GMU_DEVICE(device);
	struct kgsl_hfi *hfi = &gmu->hfi;

	/* Disable all IRQs on host */
	disable_irq(gmu->gmu_interrupt_num);
	disable_irq(hfi->hfi_interrupt_num);

	/* Mask all IRQs and clear pending IRQs */
	adreno_gmu_mask_and_clear_irqs(ADRENO_DEVICE(device));
}

static int a6xx_gmu_hfi_start_msg(struct adreno_device *adreno_dev)
{
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
@@ -704,9 +674,6 @@ int a6xx_gmu_sptprac_enable(struct adreno_device *adreno_dev)
	if (!gmu_core_gpmu_isenabled(device))
		return -EINVAL;

	if (!adreno_has_sptprac_gdsc(adreno_dev))
		return 0;

	gmu_core_regwrite(device, A6XX_GMU_GX_SPTPRAC_POWER_CONTROL,
			SPTPRAC_POWERON_CTRL_MASK);

@@ -731,9 +698,6 @@ void a6xx_gmu_sptprac_disable(struct adreno_device *adreno_dev)
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	struct gmu_device *gmu = KGSL_GMU_DEVICE(device);

	if (!adreno_has_sptprac_gdsc(adreno_dev))
		return;

	if (!gmu_core_gpmu_isenabled(device))
		return;

@@ -786,7 +750,7 @@ bool a6xx_gmu_sptprac_is_on(struct adreno_device *adreno_dev)
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	unsigned int val;

	if (!gmu_core_isenabled(device) || !adreno_has_sptprac_gdsc(adreno_dev))
	if (!gmu_core_isenabled(device))
		return true;

	gmu_core_regread(device, A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, &val);
@@ -901,6 +865,9 @@ static int a6xx_gmu_wait_for_idle(struct adreno_device *adreno_dev)
	return 0;
}

/* A6xx GMU FENCE RANGE MASK */
#define GMU_FENCE_RANGE_MASK	((0x1 << 31) | ((0xA << 2) << 18) | (0x8A0))

/*
 * a6xx_gmu_fw_start() - set up GMU and start FW
 * @device: Pointer to KGSL device
@@ -958,7 +925,7 @@ static int a6xx_gmu_fw_start(struct kgsl_device *device,
	gmu_core_regwrite(device, A6XX_GMU_HFI_QTBL_INFO, 1);

	gmu_core_regwrite(device, A6XX_GMU_AHB_FENCE_RANGE_0,
			FENCE_RANGE_MASK);
			GMU_FENCE_RANGE_MASK);

	/* Pass chipid to GMU FW, must happen before starting GMU */

@@ -1389,7 +1356,7 @@ static size_t a6xx_snapshot_gmu_mem(struct kgsl_device *device,
 * This is where all of the A6XX GMU specific bits and pieces are grabbed
 * into the snapshot memory
 */
void a6xx_gmu_snapshot(struct adreno_device *adreno_dev,
static void a6xx_gmu_snapshot(struct adreno_device *adreno_dev,
		struct kgsl_snapshot *snapshot)
{
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
@@ -1432,14 +1399,16 @@ struct gmu_dev_ops adreno_a6xx_gmudev = {
	.load_firmware = a6xx_gmu_load_firmware,
	.oob_set = a6xx_gmu_oob_set,
	.oob_clear = a6xx_gmu_oob_clear,
	.irq_enable = a6xx_gmu_irq_enable,
	.irq_disable = a6xx_gmu_irq_disable,
	.hfi_start_msg = a6xx_gmu_hfi_start_msg,
	.enable_lm = a6xx_gmu_enable_lm,
	.rpmh_gpu_pwrctrl = a6xx_gmu_rpmh_gpu_pwrctrl,
	.wait_for_lowest_idle = a6xx_gmu_wait_for_lowest_idle,
	.wait_for_gmu_idle = a6xx_gmu_wait_for_idle,
	.sptprac_enable  = a6xx_gmu_sptprac_enable,
	.sptprac_disable = a6xx_gmu_sptprac_disable,
	.ifpc_store = a6xx_gmu_ifpc_store,
	.ifpc_show = a6xx_gmu_ifpc_show,
	.snapshot = a6xx_gmu_snapshot,
	.gmu2host_intr_mask = HFI_IRQ_MASK,
	.gmu_ao_intr_mask = GMU_AO_INT_MASK,
};
Loading