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

Commit 0fef7bbc authored by Jordan Crouse's avatar Jordan Crouse
Browse files

msm: kgsl: Read speed bin information for 8996v3



There are multiple speed bin levels for the 8996v3 target.  Read
the fused speed bin value and choose the appropriate set of
powerlevels.

Change-Id: Ic0dedbad51ec9716bdd623647cad4d699855a62c
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent 5dc19fc2
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
Qualcomm GPU powerlevels

Powerlevels are defined in sets by qcom,gpu-pwrlevels. Multiple sets (bins)
can be defined within qcom,gpu-pwrelvel-bins. Each powerlevel defines a
voltage, bus, and bandwitdh level.

- qcom,gpu-pwrlevel-bins:	Contains one or more qcom,gpu-pwrlevels sets

Properties:
- compatible:			Must be qcom,gpu-pwrlevel-bins
- qcom,gpu-pwrlevels:		Defines a set of powerlevels

Properties:
- qcom,speed-bin:		Speed bin identifier for the set - must match
				the value read from the hardware

- qcom,gpu-pwrlevel:		A single powerlevel

Properties:
- reg:				Index of the powerlevel (0 = highest perf)
- qcom,gpu-freq			GPU frequency for the powerlevel (in Hz)
- qcom,bus-freq			Index to a bus level (defined by the bus
				settings)
- qcom,bus-min			Minimum bus level to set for the power level
- qcom,bus-max			maximum bus level to set for the power level
+35 −30
Original line number Diff line number Diff line
@@ -78,7 +78,7 @@ IOMMU Data:
- iommu:			Phandle for the KGSL IOMMU device node

GPU Power levels:
- qcom,gpu-pwrlevels:		Container for the GPU Power Levels (see
- qcom,gpu-pwrlevel-bins:	Container for sets of GPU power levels (see
				adreno-pwrlevels.txt)

DCVS Core info
@@ -189,11 +189,15 @@ Example of A330 GPU in MSM8916:
		coresight-child-ports = <5>;

		/* Power levels */
		qcom,gpu-pwrlevels {
		qcom,gpu-pwrlevels-bins {
			#address-cells = <1>;
			#size-cells = <0>;

			compatible = "qcom,gpu-pwrlevels";
			qcom,gpu-pwrlevels-0 {
				#address-cells = <1>;
				#size-cells = <0>;

				qcom,speed-bin = <0>;

				qcom,gpu-pwrlevel@0 {
					reg = <0>;
@@ -223,6 +227,7 @@ Example of A330 GPU in MSM8916:
					qcom,io-fraction = <0>;
				};
			};
		};

	};
};
+1 −1
Original line number Diff line number Diff line
@@ -55,7 +55,7 @@
		compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d";
		status = "ok";
		reg = <0xb00000 0x3f000
		       0x070000 0x0343C>;
		       0x070000 0x04720>;
		reg-names = "kgsl_3d0_reg_memory", "qfprom_memory";
		interrupts = <0 300 0>;
		interrupt-names = "kgsl_3d0_irq";
+52 −20
Original line number Diff line number Diff line
@@ -821,19 +821,12 @@ static const struct of_device_id adreno_match_table[] = {
	{}
};

static int adreno_of_get_pwrlevels(struct device_node *parent,
static int adreno_of_parse_pwrlevels(struct device_node *node,
	struct kgsl_device_platform_data *pdata)
{
	struct device_node *node, *child;
	struct device_node *child;
	int ret = -EINVAL;

	node = of_find_node_by_name(parent, "qcom,gpu-pwrlevels");

	if (node == NULL) {
		KGSL_CORE_ERR("Unable to find 'qcom,gpu-pwrlevels'\n");
		return -EINVAL;
	}

	pdata->num_levels = 0;

	for_each_child_of_node(node, child) {
@@ -871,20 +864,49 @@ static int adreno_of_get_pwrlevels(struct device_node *parent,
			level->bus_max = level->bus_freq;
	}

	if (of_property_read_u32(parent, "qcom,initial-pwrlevel",
		&pdata->init_level))
		pdata->init_level = 1;

	if (pdata->init_level < 0 || pdata->init_level > pdata->num_levels) {
		KGSL_CORE_ERR("Initial power level out of range\n");
		pdata->init_level = 1;
	}

	ret = 0;
done:
	return ret;

}
static int adreno_of_get_legacy_pwrlevels(struct device_node *parent,
	struct kgsl_device_platform_data *pdata)
{
	struct device_node *node;

	node = of_find_node_by_name(parent, "qcom,gpu-pwrlevels");

	if (node == NULL) {
		KGSL_CORE_ERR("Unable to find 'qcom,gpu-pwrlevels'\n");
		return -EINVAL;
	}

	return adreno_of_parse_pwrlevels(node, pdata);
}

static int adreno_of_get_pwrlevels(struct device_node *parent,
		struct adreno_device *adreno_dev,
		struct kgsl_device_platform_data *pdata)
{
	struct device_node *node, *child;

	node = of_find_node_by_name(parent, "qcom,gpu-pwrlevel-bins");
	if (node == NULL)
		return adreno_of_get_legacy_pwrlevels(parent, pdata);

	for_each_child_of_node(node, child) {
		unsigned int bin;

		if (of_property_read_u32(child, "qcom,speed-bin", &bin))
			continue;

		if (bin == adreno_dev->speed_bin)
			return adreno_of_parse_pwrlevels(child, pdata);
	}

	return -ENODEV;
}

static inline struct adreno_device *adreno_get_dev(struct platform_device *pdev)
{
@@ -894,8 +916,9 @@ static inline struct adreno_device *adreno_get_dev(struct platform_device *pdev)
	return of_id ? (struct adreno_device *) of_id->data : NULL;
}

static int adreno_of_get_pdata(struct platform_device *pdev)
static int adreno_of_get_pdata(struct adreno_device *adreno_dev)
{
	struct platform_device *pdev = adreno_dev->dev.pdev;
	struct kgsl_device_platform_data *pdata = NULL;
	int ret = -EINVAL;

@@ -914,10 +937,19 @@ static int adreno_of_get_pdata(struct platform_device *pdev)
	}

	/* pwrlevel Data */
	ret = adreno_of_get_pwrlevels(pdev->dev.of_node, pdata);
	ret = adreno_of_get_pwrlevels(pdev->dev.of_node, adreno_dev, pdata);
	if (ret)
		goto err;

	if (of_property_read_u32(pdev->dev.of_node, "qcom,initial-pwrlevel",
		&pdata->init_level))
		pdata->init_level = 1;

	if (pdata->init_level < 0 || pdata->init_level > pdata->num_levels) {
		KGSL_CORE_ERR("Initial power level out of range\n");
		pdata->init_level = 1;
	}

	/* get pm-qos-active-latency, set it to default if not found */
	if (of_property_read_u32(pdev->dev.of_node,
		"qcom,pm-qos-active-latency",
@@ -1034,7 +1066,7 @@ static int adreno_probe(struct platform_device *pdev)
	adreno_identify_gpu(adreno_dev);

	/* Get the rest of the device tree */
	status = adreno_of_get_pdata(pdev);
	status = adreno_of_get_pdata(adreno_dev);
	if (status) {
		device->pdev = NULL;
		return status;
+3 −0
Original line number Diff line number Diff line
@@ -293,6 +293,7 @@ struct adreno_gpu_core {
 * @lm_limit: limiting value for LM
 * @lm_threshold_count: register value for counter for lm threshold breakin
 * @lm_threshold_cross: number of current peaks exceeding threshold
 * @speed_bin: Indicate which power level set to use
 */
struct adreno_device {
	struct kgsl_device dev;    /* Must be first field in this struct */
@@ -351,6 +352,8 @@ struct adreno_device {
	struct kgsl_memdesc capturescript;
	struct kgsl_memdesc snapshot_registers;
	bool capturescript_working;

	unsigned int speed_bin;
};

/**
Loading