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

Commit 75f6d92a authored by Lucille Sylvester's avatar Lucille Sylvester Committed by Matt Wagantall
Browse files

msm: kgsl: Add Limits Management for targets with GPMU



The LM feature is supported by the GPMU to automatically limit
the GPU clocks as needed to stay within the power envelope.

Change-Id: Idcd90ef59f3bb5c1470173891552c6394d44ea47
Signed-off-by: default avatarLucille Sylvester <lsylvest@codeaurora.org>
parent b6ea56e9
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -843,5 +843,32 @@
#define A5XX_GPMU_POWER_COUNTER_SELECT_0	0xA87C
#define A5XX_GPMU_POWER_COUNTER_SELECT_1	0xA87D

#define A5XX_GPMU_CLOCK_THROTTLE_CTRL		0xA8A3
#define A5XX_GPMU_THROTTLE_UNMASK_FORCE_CTRL	0xA8A8

#define A5XX_GPMU_TEMP_SENSOR_ID		0xAC00
#define A5XX_GPMU_TEMP_SENSOR_CONFIG		0xAC01
#define A5XX_GPMU_TEMP_VAL			0xAC02
#define A5XX_GPMU_DELTA_TEMP_THRESHOLD		0xAC03
#define A5XX_GPMU_TEMP_THRESHOLD_INTR_STATUS	0xAC05
#define A5XX_GPMU_TEMP_THRESHOLD_INTR_EN_MASK	0xAC06

#define A5XX_GPMU_LEAKAGE_TEMP_COEFF_0_1	0xAC40
#define A5XX_GPMU_LEAKAGE_TEMP_COEFF_2_3	0xAC41
#define A5XX_GPMU_LEAKAGE_VTG_COEFF_0_1		0xAC42
#define A5XX_GPMU_LEAKAGE_VTG_COEFF_2_3		0xAC43
#define A5XX_GPMU_BASE_LEAKAGE			0xAC46

#define A5XX_GPMU_GPMU_VOLTAGE			0xAC60
#define A5XX_GPMU_GPMU_VOLTAGE_INTR_STATUS	0xAC61
#define A5XX_GPMU_GPMU_VOLTAGE_INTR_EN_MASK	0xAC62
#define A5XX_GPMU_GPMU_PWR_THRESHOLD		0xAC80

#define A5XX_GDPM_CONFIG1			0xB80C
#define A5XX_GDPM_CONFIG2			0xB80D
#define A5XX_GDPM_INT_EN			0xB80F
#define A5XX_GDPM_INT_MASK			0xB811
#define A5XX_GPMU_BEC_ENABLE			0xB9A0

#endif /* _A5XX_REG_H */
+6 −1
Original line number Diff line number Diff line
@@ -140,7 +140,7 @@ static const struct adreno_gpu_core adreno_gpulist[] = {
		.major = 3,
		.minor = 0,
		.patchid = ANY_ID,
		.features = ADRENO_GPMU | ADRENO_SPTP_PC,
		.features = ADRENO_GPMU | ADRENO_SPTP_PC | ADRENO_LM,
		.pm4fw_name = "a530_pm4.fw",
		.pfpfw_name = "a530_pfp.fw",
		.zap_name = "a530_zap",
@@ -151,6 +151,11 @@ static const struct adreno_gpu_core adreno_gpulist[] = {
		.gpmu_major = 1,
		.gpmu_minor = 0,
		.busy_mask = 0xFFFFFFFE,
		.lm_major = 3,
		.lm_minor = 0,
		.gpmu_tsens = 0x00060007,
		.max_power = 5448,
		.regfw_name = "a530v2_seq.fw2",
	},
	{
		.gpurev = ADRENO_REV_A510,
+11 −2
Original line number Diff line number Diff line
@@ -1483,6 +1483,10 @@ static int _adreno_start(struct adreno_device *adreno_dev)
	if (status)
		goto error_mmu_off;

	/* Set up LM before initializing the GPMU */
	if (gpudev->lm_init)
		gpudev->lm_init(adreno_dev);

	/* Enable h/w power collapse feature */
	if (gpudev->enable_pc)
		gpudev->enable_pc(adreno_dev);
@@ -1495,6 +1499,10 @@ static int _adreno_start(struct adreno_device *adreno_dev)
	if (gpudev->enable_ppd)
		gpudev->enable_ppd(adreno_dev);

	/* Enable limits management */
	if (gpudev->lm_enable)
		gpudev->lm_enable(adreno_dev);

	/* Start the dispatcher */
	adreno_dispatcher_start(device);

@@ -2565,13 +2573,14 @@ static void adreno_regulator_disable(struct kgsl_device *device)
}

static void adreno_pwrlevel_change_settings(struct kgsl_device *device,
						bool mask_throttle)
		unsigned int prelevel, unsigned int postlevel, bool post)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct adreno_gpudev *gpudev  = ADRENO_GPU_DEVICE(adreno_dev);

	if (gpudev->pwrlevel_change_settings)
		gpudev->pwrlevel_change_settings(adreno_dev, mask_throttle);
		gpudev->pwrlevel_change_settings(adreno_dev, prelevel,
					postlevel, post);
}

static const struct kgsl_functable adreno_functable = {
+22 −1
Original line number Diff line number Diff line
@@ -100,6 +100,8 @@
#define ADRENO_PREEMPTION BIT(7)
/* The core uses GPMU for power and limit management */
#define ADRENO_GPMU BIT(8)
/* The GPMU supports Limits Management */
#define ADRENO_LM BIT(9)

/* Flags to control command packet settings */
#define KGSL_CMD_FLAGS_NONE             0
@@ -165,6 +167,7 @@ enum adreno_start_type {

#define ADRENO_SPTP_PC_CTRL 0
#define ADRENO_PPD_CTRL     1
#define ADRENO_LM_CTRL      2

struct adreno_gpudev;

@@ -202,6 +205,11 @@ struct adreno_busy_data {
 * @gpmu_minor: Match for the GPMU & firmware, minor revision
 * @gpmu_features: Supported features for any given GPMU version
 * @busy_mask: mask to check if GPU is busy in RBBM_STATUS
 * @lm_major: Limits Management register sequence, major revision
 * @lm_minor: LM register sequence, minor revision
 * @regfw_name: Filename for the register sequence firmware
 * @gpmu_tsens: ID for the temporature sensor used by the GPMU
 * @max_power: Max possible power draw of a core, units elephant tail hairs
 */
struct adreno_gpu_core {
	enum adreno_gpurev gpurev;
@@ -227,6 +235,10 @@ struct adreno_gpu_core {
	unsigned int gpmu_minor;
	unsigned int gpmu_features;
	unsigned int busy_mask;
	unsigned int lm_major, lm_minor;
	const char *regfw_name;
	unsigned int gpmu_tsens;
	unsigned int max_power;
};

/**
@@ -271,6 +283,9 @@ struct adreno_gpu_core {
 * buffer
 * @sp_local_gpuaddr: Base GPU virtual address for SP local memory
 * @sp_pvt_gpuaddr: Base GPU virtual address for SP private memory
 * @lm_fw: The LM firmware handle
 * @lm_sequence: Pointer to the start of the register write sequence for LM
 * @lm_size: The dword size of the LM sequence
 */
struct adreno_device {
	struct kgsl_device dev;    /* Must be first field in this struct */
@@ -314,6 +329,9 @@ struct adreno_device {
	unsigned int cmdbatch_profile_index;
	uint64_t sp_local_gpuaddr;
	uint64_t sp_pvt_gpuaddr;
	const struct firmware *lm_fw;
	uint32_t *lm_sequence;
	uint32_t lm_size;
};

/**
@@ -630,8 +648,11 @@ struct adreno_gpudev {
	int (*regulator_enable)(struct adreno_device *);
	void (*regulator_disable)(struct adreno_device *);
	void (*gpmu_start)(struct adreno_device *);
	void (*lm_init)(struct adreno_device *);
	void (*lm_enable)(struct adreno_device *);
	void (*pwrlevel_change_settings)(struct adreno_device *,
					bool mask_throttle);
				unsigned int prelevel, unsigned int postlevel,
				bool post);
	int (*preemption_pre_ibsubmit)(struct adreno_device *,
				struct adreno_ringbuffer *, unsigned int *,
				struct kgsl_context *, uint64_t cond_addr,
+17 −4
Original line number Diff line number Diff line
@@ -392,12 +392,16 @@ static void a4xx_enable_ppd(struct adreno_device *adreno_dev)
 * a4xx_pwrlevel_change_settings() - Program the hardware during power level
 * transitions
 * @adreno_dev: The adreno device pointer
 * @mask_throttle: flag to check if PPD throttle should be masked
 * @prelevel: The previous power level
 * @postlevel: The new power level
 * @post: True if called after the clock change has taken effect
 */
static void a4xx_pwrlevel_change_settings(struct adreno_device *adreno_dev,
						bool mask_throttle)
				unsigned int prelevel, unsigned int postlevel,
				bool post)
{
	struct kgsl_device *device = &adreno_dev->dev;
	static int pre;

	/* PPD programming only for A430v2 */
	if (!ADRENO_FEATURE(adreno_dev, ADRENO_PPD) ||
@@ -405,15 +409,24 @@ static void a4xx_pwrlevel_change_settings(struct adreno_device *adreno_dev,
		!adreno_is_a430v2(adreno_dev))
		return;

	if (mask_throttle) {
	/* if this is a real pre, or a post without a previous pre, set pre */
	if ((post == 0) || (pre == 0 && post == 1))
		pre = 1;
	else if (post == 1)
		pre = 0;

	if ((prelevel == 0) && pre) {
		/* Going to Non-Turbo mode - mask the throttle and reset */
		kgsl_regwrite(device, A4XX_RBBM_PPD_CTRL, 0x1002E40E);
		kgsl_regwrite(device, A4XX_RBBM_PPD_CTRL, 0x1002E40C);
	} else {
	} else if ((postlevel == 0) && post) {
		/* Going to Turbo mode - unmask the throttle and reset */
		kgsl_regwrite(device, A4XX_RBBM_PPD_CTRL, 0x1002E40A);
		kgsl_regwrite(device, A4XX_RBBM_PPD_CTRL, 0x1002E408);
	}

	if (post)
		pre = 0;
}

/*
Loading