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

Commit 9be7e601 authored by Kyle Piefer's avatar Kyle Piefer
Browse files

msm: kgsl: Add support for the new ACD protocol



ACD on A640 uses a new HFI message to pass initialization
data and a new memory allocation.

Change-Id: I56303c882e909f83e4efde161f5dd89196ecb2ed
Signed-off-by: default avatarKyle Piefer <kpiefer@codeaurora.org>
Signed-off-by: default avatarCarter Cooper <ccooper@codeaurora.org>
parent 01697ba5
Loading
Loading
Loading
Loading
+0 −4
Original line number Original line Diff line number Diff line
@@ -966,10 +966,6 @@ static int adreno_of_parse_pwrlevels(struct adreno_device *adreno_dev,
		if (of_property_read_u32(child, "qcom,bus-max",
		if (of_property_read_u32(child, "qcom,bus-max",
			&level->bus_max))
			&level->bus_max))
			level->bus_max = level->bus_freq;
			level->bus_max = level->bus_freq;

		if (of_property_read_u32(child, "qcom,dvm-val",
				&level->acd_dvm_val))
			level->acd_dvm_val = 0xFFFFFFFF;
	}
	}


	return 0;
	return 0;
+40 −4
Original line number Original line Diff line number Diff line
@@ -818,6 +818,38 @@ static void build_bwtable_cmd_cache(struct gmu_device *gmu)
				votes->cnoc_votes.cmd_data[i][j];
				votes->cnoc_votes.cmd_data[i][j];
}
}


static int gmu_acd_probe(struct gmu_device *gmu, struct device_node *node)
{
	struct hfi_acd_table_cmd *cmd = &gmu->hfi.acd_tbl_cmd;
	struct device_node *acd_node;

	acd_node = of_find_node_by_name(node, "qcom,gpu-acd-table");
	if (!acd_node)
		return -ENODEV;

	cmd->hdr = 0xFFFFFFFF;
	cmd->version = HFI_ACD_INIT_VERSION;
	cmd->enable_by_level = 0;
	cmd->stride = 0;
	cmd->num_levels = 0;

	of_property_read_u32(acd_node, "qcom,acd-stride", &cmd->stride);
	if (!cmd->stride || cmd->stride > MAX_ACD_STRIDE)
		return -EINVAL;

	of_property_read_u32(acd_node, "qcom,acd-num-levels", &cmd->num_levels);
	if (!cmd->num_levels || cmd->num_levels > MAX_ACD_NUM_LEVELS)
		return -EINVAL;

	of_property_read_u32(acd_node, "qcom,acd-enable-by-level",
			&cmd->enable_by_level);
	if (hweight32(cmd->enable_by_level) != cmd->num_levels)
		return -EINVAL;

	return of_property_read_u32_array(acd_node, "qcom,acd-data",
			cmd->data, cmd->stride * cmd->num_levels);
}

/*
/*
 * gmu_bus_vote_init - initialized RPMh votes needed for bw scaling by GMU.
 * gmu_bus_vote_init - initialized RPMh votes needed for bw scaling by GMU.
 * @gmu: Pointer to GMU device
 * @gmu: Pointer to GMU device
@@ -1321,7 +1353,6 @@ static int gmu_probe(struct kgsl_device *device, struct device_node *node)
		int j = gmu->num_gpupwrlevels - 1 - i;
		int j = gmu->num_gpupwrlevels - 1 - i;


		gmu->gpu_freqs[i] = pwr->pwrlevels[j].gpu_freq;
		gmu->gpu_freqs[i] = pwr->pwrlevels[j].gpu_freq;
		gmu->acd_dvm_vals[i] = pwr->pwrlevels[j].acd_dvm_val;
	}
	}


	/* Initializes GPU b/w levels configuration */
	/* Initializes GPU b/w levels configuration */
@@ -1354,10 +1385,15 @@ static int gmu_probe(struct kgsl_device *device, struct device_node *node)
		gmu->idle_level = GPU_HW_ACTIVE;
		gmu->idle_level = GPU_HW_ACTIVE;


	if (ADRENO_FEATURE(adreno_dev, ADRENO_ACD) && !noacd) {
	if (ADRENO_FEATURE(adreno_dev, ADRENO_ACD) && !noacd) {
		if (!gmu_acd_probe(gmu, node)) {
			/* Init the AOP mailbox if we have a valid ACD table */
			ret = gmu_aop_mailbox_init(device, gmu);
			ret = gmu_aop_mailbox_init(device, gmu);
			if (ret)
			if (ret)
				dev_err(&gmu->pdev->dev,
				dev_err(&gmu->pdev->dev,
					"AOP mailbox init failed: %d\n", ret);
					"AOP mailbox init failed: %d\n", ret);
		} else
			dev_err(&gmu->pdev->dev,
				"ACD probe failed: missing or invalid table\n");
	}
	}


	/* disable LM if the feature is not enabled */
	/* disable LM if the feature is not enabled */
+0 −2
Original line number Original line Diff line number Diff line
@@ -157,7 +157,6 @@ struct kgsl_mailbox {
 * @ccl: CNOC BW scaling client
 * @ccl: CNOC BW scaling client
 * @idle_level: Minimal GPU idle power level
 * @idle_level: Minimal GPU idle power level
 * @fault_count: GMU fault count
 * @fault_count: GMU fault count
 * @acd_dvm_vals: Table of DVM values that correspond to frequency levels
 * @mailbox: Messages to AOP for ACD enable/disable go through this
 * @mailbox: Messages to AOP for ACD enable/disable go through this
 */
 */
struct gmu_device {
struct gmu_device {
@@ -190,7 +189,6 @@ struct gmu_device {
	unsigned int ccl;
	unsigned int ccl;
	unsigned int idle_level;
	unsigned int idle_level;
	unsigned int fault_count;
	unsigned int fault_count;
	unsigned int acd_dvm_vals[MAX_GX_LEVELS];
	struct kgsl_mailbox mailbox;
	struct kgsl_mailbox mailbox;
};
};


+28 −4
Original line number Original line Diff line number Diff line
@@ -500,7 +500,8 @@ static int hfi_send_dcvstbl(struct gmu_device *gmu)


	for (i = 0; i < gmu->num_gpupwrlevels; i++) {
	for (i = 0; i < gmu->num_gpupwrlevels; i++) {
		cmd.gx_votes[i].vote = gmu->rpmh_votes.gx_votes[i];
		cmd.gx_votes[i].vote = gmu->rpmh_votes.gx_votes[i];
		cmd.gx_votes[i].acd = gmu->acd_dvm_vals[i];
		/* Hardcode this to the max threshold since it is not used */
		cmd.gx_votes[i].acd = 0xFFFFFFFF;
		/* Divide by 1000 to convert to kHz */
		/* Divide by 1000 to convert to kHz */
		cmd.gx_votes[i].freq = gmu->gpu_freqs[i] / 1000;
		cmd.gx_votes[i].freq = gmu->gpu_freqs[i] / 1000;
	}
	}
@@ -522,6 +523,15 @@ static int hfi_send_bwtbl(struct gmu_device *gmu)
	return hfi_send_generic_req(gmu, HFI_CMD_ID, cmd);
	return hfi_send_generic_req(gmu, HFI_CMD_ID, cmd);
}
}


static int hfi_send_acd_tbl(struct gmu_device *gmu)
{
	struct hfi_acd_table_cmd *cmd = &gmu->hfi.acd_tbl_cmd;

	cmd->hdr = CMD_MSG_HDR(H2F_MSG_ACD_TBL, sizeof(*cmd));

	return hfi_send_generic_req(gmu, HFI_CMD_IDX, cmd);
}

static int hfi_send_test(struct gmu_device *gmu)
static int hfi_send_test(struct gmu_device *gmu)
{
{
	struct hfi_test_cmd cmd = {
	struct hfi_test_cmd cmd = {
@@ -662,6 +672,20 @@ static int hfi_verify_fw_version(struct kgsl_device *device,
	return 0;
	return 0;
}
}


static int hfi_send_acd_feature_ctrl(struct gmu_device *gmu,
		struct adreno_device *adreno_dev)
{
	int ret = 0;

	if (test_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag)) {
		ret = hfi_send_acd_tbl(gmu);
		if (!ret)
			ret = hfi_send_feature_ctrl(gmu, HFI_FEATURE_ACD, 1, 0);
	}

	return ret;
}

int hfi_start(struct kgsl_device *device,
int hfi_start(struct kgsl_device *device,
		struct gmu_device *gmu, uint32_t boot_state)
		struct gmu_device *gmu, uint32_t boot_state)
{
{
@@ -716,10 +740,10 @@ int hfi_start(struct kgsl_device *device,
	 */
	 */
	if (HFI_VER_MAJOR(&gmu->hfi) >= 2) {
	if (HFI_VER_MAJOR(&gmu->hfi) >= 2) {
		result = hfi_send_feature_ctrl(gmu, HFI_FEATURE_ECP, 0, 0);
		result = hfi_send_feature_ctrl(gmu, HFI_FEATURE_ECP, 0, 0);
		if (test_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag))
		if (result)
			result |= hfi_send_feature_ctrl(gmu,
			return result;
					HFI_FEATURE_ACD, 1, 0);


		result = hfi_send_acd_feature_ctrl(gmu, adreno_dev);
		if (result)
		if (result)
			return result;
			return result;


+17 −0
Original line number Original line Diff line number Diff line
@@ -176,6 +176,7 @@ enum hfi_msg_type {
#define H2F_MSG_BW_VOTE_TBL	3
#define H2F_MSG_BW_VOTE_TBL	3
#define H2F_MSG_PERF_TBL	4
#define H2F_MSG_PERF_TBL	4
#define H2F_MSG_TEST		5
#define H2F_MSG_TEST		5
#define H2F_MSG_ACD_TBL		7
#define H2F_MSG_START		10
#define H2F_MSG_START		10
#define H2F_MSG_FEATURE_CTRL	11
#define H2F_MSG_FEATURE_CTRL	11
#define H2F_MSG_GET_VALUE	12
#define H2F_MSG_GET_VALUE	12
@@ -274,6 +275,20 @@ struct hfi_dcvstable_cmd {
	struct opp_desc cx_votes[MAX_CX_LEVELS];
	struct opp_desc cx_votes[MAX_CX_LEVELS];
};
};


#define HFI_ACD_INIT_VERSION 1
#define MAX_ACD_STRIDE 2
#define MAX_ACD_NUM_LEVELS 6

/* H2F */
struct hfi_acd_table_cmd {
	uint32_t hdr;
	uint32_t version;
	uint32_t enable_by_level;
	uint32_t stride;
	uint32_t num_levels;
	uint32_t data[MAX_ACD_NUM_LEVELS * MAX_ACD_STRIDE];
};

/* H2F */
/* H2F */
struct hfi_test_cmd {
struct hfi_test_cmd {
	uint32_t hdr;
	uint32_t hdr;
@@ -604,6 +619,7 @@ struct pending_cmd {
 * @seqnum: atomic counter that is incremented for each message sent. The
 * @seqnum: atomic counter that is incremented for each message sent. The
 *	value of the counter is used as sequence number for HFI message
 *	value of the counter is used as sequence number for HFI message
 * @bwtbl_cmd: HFI BW table buffer
 * @bwtbl_cmd: HFI BW table buffer
 * @acd_tbl_cmd: HFI table for ACD data
 */
 */
struct kgsl_hfi {
struct kgsl_hfi {
	struct kgsl_device *kgsldev;
	struct kgsl_device *kgsldev;
@@ -613,6 +629,7 @@ struct kgsl_hfi {
	uint32_t version;
	uint32_t version;
	atomic_t seqnum;
	atomic_t seqnum;
	struct hfi_bwtable_cmd bwtbl_cmd;
	struct hfi_bwtable_cmd bwtbl_cmd;
	struct hfi_acd_table_cmd acd_tbl_cmd;
};
};


struct gmu_device;
struct gmu_device;
Loading