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

Commit 06d3e998 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ARM: dts: msm: Add new GPU power level speed bin"

parents c1fd48df a8f815c4
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
+38 −32
Original line number Diff line number Diff line
@@ -10,7 +10,9 @@ Required properties:
- reg-names:		Resource names used for the physical address of device registers
			and shader memory. "kgsl_3d0_reg_memory" gives the physical address
			and length of device registers while "kgsl_3d0_shader_memory" gives
			physical address and length of device shader memory.
			physical address and length of device shader memory.  If
			specified, "qfprom_memory" gives the range for the efuse
			registers used for various configuration options.
- interrupts:		Interrupt mapping for GPU IRQ.
- interrupt-names:	String property to describe the name of the interrupt.
- qcom,id:		An integer used as an identification number for the device.
@@ -34,7 +36,6 @@ Required properties:
				"alt_mem_iface_clk", "rbbmtimer_clk",  "alwayson_clk"
				"core_clk" and "iface_clk" are required and others are optional

- qcom,gpu-efuse-leakage:	memory region for GPU power rail leakage.
- qcom,base-leakage-coefficient: Dynamic leakage coefficient.
- qcom,lm-limit:	Current limit for GPU limit management.

@@ -77,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
@@ -188,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>;
@@ -222,6 +227,7 @@ Example of A330 GPU in MSM8916:
					qcom,io-fraction = <0>;
				};
			};
		};

	};
};
+8 −6
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@
			<  5195 /*  681 MHz */ >,
			<  5859 /*  768 MHz */ >,
			<  7759 /*  1017 MHz */ >,
			<  9887 /*  1296 MHz */ >,
			<  11863 /*  1555 MHz */ >,
			<  13763 /*  1804 MHz */ >;
	};
@@ -53,14 +54,14 @@
		label = "kgsl-3d0";
		compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d";
		status = "ok";
		reg = <0xb00000 0x3f000>;
		reg-names = "kgsl_3d0_reg_memory";
		reg = <0xb00000 0x3f000
		       0x070000 0x04720>;
		reg-names = "kgsl_3d0_reg_memory", "qfprom_memory";
		interrupts = <0 300 0>;
		interrupt-names = "kgsl_3d0_irq";
		qcom,id = <0>;

		qcom,chipid = <0x05030000>;
		qcom,gpu-efuse-leakage = <0x00070130 24>;
		qcom,base-leakage-coefficient = <34>;
		qcom,lm-limit = <6000>;

@@ -106,7 +107,7 @@
		qcom,gpubw-dev = <&gpubw>;
		qcom,bus-control;
		qcom,msm-bus,name = "grp3d";
		qcom,msm-bus,num-cases = <12>;
		qcom,msm-bus,num-cases = <13>;
		qcom,msm-bus,num-paths = <1>;
		qcom,msm-bus,vectors-KBps =
				<26 512 0 0>,
@@ -120,8 +121,9 @@
				<26 512 0 5448000>,     // 7 bus=681
				<26 512 0 6144000>,     // 8 bus=768
				<26 512 0 8136000>,     // 9 bus=1017
				<26 512 0 12440000>,    // 10 bus=1555
				<26 512 0 14432000>;    // 11 bus=1804
				<26 512 0 10368000>,    // 10 bus=1296
				<26 512 0 12440000>,    // 11 bus=1555
				<26 512 0 14432000>;    // 12 bus=1804

		/* GDSC regulator names */
		regulator-names = "vddcx", "vdd";
+125 −64
Original line number Diff line number Diff line
@@ -86,27 +86,32 @@
	qcom,initial-pwrlevel = <5>;
	qcom,bus-width = <32>;

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

		compatible = "qcom,gpu-pwrlevels";
		compatible="qcom,gpu-pwrlevel-bins";

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

			qcom,speed-bin = <0>;

			qcom,gpu-pwrlevel@0 {
				reg = <0>;
				qcom,gpu-freq = <624000000>;
			qcom,bus-freq = <11>;
			qcom,bus-min = <10>;
			qcom,bus-max = <11>;
				qcom,bus-freq = <12>;
				qcom,bus-min = <11>;
				qcom,bus-max = <12>;
			};

			qcom,gpu-pwrlevel@1 {
				reg = <1>;
				qcom,gpu-freq = <560000000>;
			qcom,bus-freq = <10>;
				qcom,bus-freq = <11>;
				qcom,bus-min = <9>;
			qcom,bus-max = <11>;
				qcom,bus-max = <12>;
			};

			qcom,gpu-pwrlevel@2 {
@@ -114,7 +119,7 @@
				qcom,gpu-freq = <510000000>;
				qcom,bus-freq = <9>;
				qcom,bus-min = <8>;
			qcom,bus-max = <10>;
				qcom,bus-max = <11>;
			};

			qcom,gpu-pwrlevel@3 {
@@ -156,6 +161,62 @@
				qcom,bus-min = <0>;
				qcom,bus-max = <0>;
			};
		};

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

			qcom,speed-bin = <1>;

			qcom,gpu-pwrlevel@0 {
				reg = <0>;
				qcom,gpu-freq = <510000000>;
				qcom,bus-freq = <9>;
				qcom,bus-min = <8>;
				qcom,bus-max = <10>;
			};

			qcom,gpu-pwrlevel@1 {
				reg = <1>;
				qcom,gpu-freq = <401800000>;
				qcom,bus-freq = <8>;
				qcom,bus-min = <7>;
				qcom,bus-max = <9>;
			};

			qcom,gpu-pwrlevel@2 {
				reg = <2>;
				qcom,gpu-freq = <315000000>;
				qcom,bus-freq = <6>;
				qcom,bus-min = <5>;
				qcom,bus-max = <7>;
			};

			qcom,gpu-pwrlevel@3 {
				reg = <3>;
				qcom,gpu-freq = <214000000>;
				qcom,bus-freq = <4>;
				qcom,bus-min = <3>;
				qcom,bus-max = <5>;
			};

			qcom,gpu-pwrlevel@4 {
				reg = <4>;
				qcom,gpu-freq = <133000000>;
				qcom,bus-freq = <3>;
				qcom,bus-min = <2>;
				qcom,bus-max = <4>;
			};

			qcom,gpu-pwrlevel@5 {
				reg = <5>;
				qcom,gpu-freq = <27000000>;
				qcom,bus-freq = <0>;
				qcom,bus-min = <0>;
				qcom,bus-max = <0>;
			};
		};

	};
};
+115 −25
Original line number Diff line number Diff line
@@ -176,6 +176,58 @@ static inline int adreno_of_read_property(struct device_node *node,
	return ret;
}

static void __iomem *efuse_base;
static size_t efuse_len;

int adreno_efuse_map(struct adreno_device *adreno_dev)
{
	struct kgsl_device *device = &adreno_dev->dev;
	struct resource *res;

	if (efuse_base != NULL)
		return 0;

	res = platform_get_resource_byname(device->pdev, IORESOURCE_MEM,
		"qfprom_memory");

	if (res == NULL)
		return -ENODEV;

	efuse_base = ioremap(res->start, resource_size(res));
	if (efuse_base == NULL)
		return -ENODEV;

	efuse_len = resource_size(res);
	return 0;
}

void adreno_efuse_unmap(struct adreno_device *adreno_dev)
{
	if (efuse_base != NULL) {
		iounmap(efuse_base);
		efuse_base = NULL;
		efuse_len = 0;
	}
}

int adreno_efuse_read_u32(struct adreno_device *adreno_dev, unsigned int offset,
		unsigned int *val)
{
	if (efuse_base == NULL)
		return -ENODEV;

	if (offset >= efuse_len)
		return -ERANGE;

	if (val != NULL) {
		*val = readl_relaxed(efuse_base + offset);
		/* Make sure memory is updated before returning */
		rmb();
	}

	return 0;
}

/*
 * adreno_iommu_cb_probe() - Adreno iommu context bank probe
 *
@@ -751,8 +803,10 @@ adreno_identify_gpu(struct adreno_device *adreno_dev)
		if (reg_offsets->offset_0 != i && !reg_offsets->offsets[i])
			reg_offsets->offsets[i] = ADRENO_REG_UNUSED;
	}
	if (gpudev->gpudev_init)
		gpudev->gpudev_init(adreno_dev);

	/* Do target specific identification */
	if (gpudev->platform_setup != NULL)
		gpudev->platform_setup(adreno_dev);
}

static const struct platform_device_id adreno_id_table[] = {
@@ -767,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) {
@@ -817,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)
{
@@ -840,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;

@@ -860,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",
@@ -976,15 +1062,16 @@ static int adreno_probe(struct platform_device *pdev)
	device->pdev = pdev;
	device->mmu.priv = &device_3d0_iommu;

	status = adreno_of_get_pdata(pdev);
	/* Get the chip ID from the DT and set up target specific parameters */
	adreno_identify_gpu(adreno_dev);

	/* Get the rest of the device tree */
	status = adreno_of_get_pdata(adreno_dev);
	if (status) {
		device->pdev = NULL;
		return status;
	}

	/* Identify the specific GPU */
	adreno_identify_gpu(adreno_dev);

	/* Bro, do you even 64 bit? */
	if (ADRENO_FEATURE(adreno_dev, ADRENO_64BIT))
		device->mmu.features |= KGSL_MMU_64BIT;
@@ -1094,6 +1181,9 @@ static int adreno_remove(struct platform_device *pdev)
	kfree(adreno_ft_regs_val);
	adreno_ft_regs_val = NULL;

	if (efuse_base != NULL)
		iounmap(efuse_base);

	adreno_perfcounter_close(adreno_dev);
	kgsl_device_platform_remove(device);

Loading