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

Commit 868188eb authored by Deepak Kumar's avatar Deepak Kumar Committed by Gerrit - the friendly Code Review server
Browse files

msm: kgsl: Select GPU hardware quirks based on efuse



Add qcom,gpu-hw-revisions property to define multiple
hardware revisions and select the right GPU hardware
quirks based on fused efuse value.

Earlier we used to only depend on the different device
tree configuration file for different hardware revisions.
With this approach we don’t need to depend on separate
device tree file but we can select the hardware related
quirks using this property.

Change-Id: I93abeef543213878da1be36e4b542386b51ee32b
Signed-off-by: default avatarDeepak Kumar <dkumar@codeaurora.org>
Signed-off-by: default avatarPrakash Kamliya <pkamliya@codeaurora.org>
Signed-off-by: default avatarUrvashi Agrawal <urvaagra@codeaurora.org>
parent 4620c7ed
Loading
Loading
Loading
Loading
+42 −0
Original line number Diff line number Diff line
@@ -218,6 +218,26 @@ Properties:
- qcom,mempool-allocate:	Allocate memory from the system memory when the
				reserved pool exhausted.

SOC Hardware revisions:
- qcom,soc-hw-revisions:
		Container of sets of SOC hardware revisions specified by
		qcom,soc-hw-revision.
Properties:
- compatible:
		Must be qcom,soc-hw-revisions.

- qcom,soc-hw-revision:
		Defines a SOC hardware revision.

Properties:
- reg:
		Identifier for the hardware revision - must match the value read
		from the hardware.
- qcom,chipid:
		GPU Chip ID to be used for this hardware revision.
- qcom,gpu-quirk-*:
		GPU quirks applicable for this hardware revision.

GPU LLC slice info:
- cache-slice-names:		List of LLC cache slices for GPU transactions
				and pagetable walk.
@@ -293,6 +313,28 @@ Example of A330 GPU in MSM8916:
		coresight-child-list = <&funnel_in0>;
		coresight-child-ports = <5>;

		qcom,soc-hw-revisions {
			#address-cells = <1>;
			#size-cells = <0>;

			compatible="qcom,soc-hw-revisions";

			qcom,soc-hw-revision@0 {
				reg = <0>;

				qcom,chipid = <0x06010500>;
				qcom,gpu-quirk-hfi-use-reg;
				qcom,gpu-quirk-limit-uche-gbif-rw;
			};

			qcom,soc-hw-revision@1 {
				reg = <1>;

				qcom,chipid = <0x06010501>;
				qcom,gpu-quirk-hfi-use-reg;
			};
		};

		/* GPU Mempools */
		qcom,gpu-mempools {
			#address-cells= <1>;
+108 −30
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/input.h>
#include <linux/io.h>
#include <soc/qcom/scm.h>
#include <linux/nvmem-consumer.h>

#include <linux/msm-bus-board.h>
#include <linux/msm-bus.h>
@@ -755,6 +756,107 @@ static inline const struct adreno_gpu_core *_get_gpu_core(unsigned int chipid)
	return NULL;
}

static struct {
	unsigned int quirk;
	const char *prop;
} adreno_quirks[] = {
	 { ADRENO_QUIRK_TWO_PASS_USE_WFI, "qcom,gpu-quirk-two-pass-use-wfi" },
	 { ADRENO_QUIRK_IOMMU_SYNC, "qcom,gpu-quirk-iommu-sync" },
	 { ADRENO_QUIRK_CRITICAL_PACKETS, "qcom,gpu-quirk-critical-packets" },
	 { ADRENO_QUIRK_FAULT_DETECT_MASK, "qcom,gpu-quirk-fault-detect-mask" },
	 { ADRENO_QUIRK_DISABLE_RB_DP2CLOCKGATING,
			"qcom,gpu-quirk-dp2clockgating-disable" },
	 { ADRENO_QUIRK_DISABLE_LMLOADKILL,
			"qcom,gpu-quirk-lmloadkill-disable" },
	{ ADRENO_QUIRK_HFI_USE_REG, "qcom,gpu-quirk-hfi-use-reg" },
	{ ADRENO_QUIRK_SECVID_SET_ONCE, "qcom,gpu-quirk-secvid-set-once" },
	{ ADRENO_QUIRK_LIMIT_UCHE_GBIF_RW,
			"qcom,gpu-quirk-limit-uche-gbif-rw" },
};

#if defined(CONFIG_NVMEM) && defined(CONFIG_QCOM_QFPROM)
static struct device_node *
adreno_get_soc_hw_revision_node(struct platform_device *pdev)
{
	struct device_node *node, *child;
	struct nvmem_cell *cell;
	ssize_t len;
	u32 *buf, hw_rev, rev;

	node = of_find_node_by_name(pdev->dev.of_node, "qcom,soc-hw-revisions");
	if (node == NULL)
		goto err;

	/* read the soc hw revision and select revision node */
	cell = nvmem_cell_get(&pdev->dev, "minor_rev");
	if (IS_ERR_OR_NULL(cell)) {
		if (PTR_ERR(cell) == -EPROBE_DEFER)
			return (void *)cell;

		KGSL_CORE_ERR("Unable to get nvmem cell: ret=%ld\n",
				PTR_ERR(cell));
		goto err;
	}

	buf = nvmem_cell_read(cell, &len);
	nvmem_cell_put(cell);

	if (IS_ERR_OR_NULL(buf)) {
		KGSL_CORE_ERR("Unable to read nvmem cell: ret=%ld\n",
				PTR_ERR(buf));
		goto err;
	}

	hw_rev = *buf;
	kfree(buf);

	for_each_child_of_node(node, child) {
		if (of_property_read_u32(child, "reg", &rev))
			continue;

		if (rev == hw_rev)
			return child;
	}

err:
	/* fall back to parent node */
	return pdev->dev.of_node;
}
#else
static struct device_node *
adreno_get_soc_hw_revision_node(struct platform_device *pdev)
{
	return pdev->dev.of_node;
}
#endif


static int adreno_update_soc_hw_revision_quirks(
		struct adreno_device *adreno_dev, struct platform_device *pdev)
{
	struct device_node *node;
	int i;

	node = adreno_get_soc_hw_revision_node(pdev);
	if (IS_ERR(node))
		return PTR_ERR(node);

	/* get chip id, fall back to parent if revision node does not have it */
	if (of_property_read_u32(node, "qcom,chipid", &adreno_dev->chipid))
		if (of_property_read_u32(pdev->dev.of_node,
				"qcom,chipid", &adreno_dev->chipid))
			KGSL_DRV_FATAL(KGSL_DEVICE(adreno_dev),
			"No GPU chip ID was specified\n");

	/* update quirk */
	for (i = 0; i < ARRAY_SIZE(adreno_quirks); i++) {
		if (of_property_read_bool(node, adreno_quirks[i].prop))
			adreno_dev->quirks |= adreno_quirks[i].quirk;
	}

	return 0;
}

static void
adreno_identify_gpu(struct adreno_device *adreno_dev)
{
@@ -762,11 +864,6 @@ adreno_identify_gpu(struct adreno_device *adreno_dev)
	struct adreno_gpudev *gpudev;
	int i;

	if (kgsl_property_read_u32(KGSL_DEVICE(adreno_dev), "qcom,chipid",
		&adreno_dev->chipid))
		KGSL_DRV_FATAL(KGSL_DEVICE(adreno_dev),
			"No GPU chip ID was specified\n");

	adreno_dev->gpucore = _get_gpu_core(adreno_dev->chipid);

	if (adreno_dev->gpucore == NULL)
@@ -932,31 +1029,12 @@ static inline struct adreno_device *adreno_get_dev(struct platform_device *pdev)
	return of_id ? (struct adreno_device *) of_id->data : NULL;
}

static struct {
	unsigned int quirk;
	const char *prop;
} adreno_quirks[] = {
	 { ADRENO_QUIRK_TWO_PASS_USE_WFI, "qcom,gpu-quirk-two-pass-use-wfi" },
	 { ADRENO_QUIRK_IOMMU_SYNC, "qcom,gpu-quirk-iommu-sync" },
	 { ADRENO_QUIRK_CRITICAL_PACKETS, "qcom,gpu-quirk-critical-packets" },
	 { ADRENO_QUIRK_FAULT_DETECT_MASK, "qcom,gpu-quirk-fault-detect-mask" },
	 { ADRENO_QUIRK_DISABLE_RB_DP2CLOCKGATING,
			"qcom,gpu-quirk-dp2clockgating-disable" },
	 { ADRENO_QUIRK_DISABLE_LMLOADKILL,
			"qcom,gpu-quirk-lmloadkill-disable" },
	{ ADRENO_QUIRK_HFI_USE_REG, "qcom,gpu-quirk-hfi-use-reg" },
	{ ADRENO_QUIRK_SECVID_SET_ONCE, "qcom,gpu-quirk-secvid-set-once" },
	{ ADRENO_QUIRK_LIMIT_UCHE_GBIF_RW,
			"qcom,gpu-quirk-limit-uche-gbif-rw" },
};

static int adreno_of_get_power(struct adreno_device *adreno_dev,
		struct platform_device *pdev)
{
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	struct device_node *node = pdev->dev.of_node;
	struct resource *res;
	int i;
	unsigned int timeout;

	if (of_property_read_string(node, "label", &pdev->name)) {
@@ -967,12 +1045,6 @@ static int adreno_of_get_power(struct adreno_device *adreno_dev,
	if (adreno_of_read_property(node, "qcom,id", &pdev->id))
		return -EINVAL;

	/* Set up quirks and other boolean options */
	for (i = 0; i < ARRAY_SIZE(adreno_quirks); i++) {
		if (of_property_read_bool(node, adreno_quirks[i].prop))
			adreno_dev->quirks |= adreno_quirks[i].quirk;
	}

	/* Get starting physical address of device registers */
	res = platform_get_resource_byname(device->pdev, IORESOURCE_MEM,
					   device->iomemname);
@@ -1134,6 +1206,12 @@ static int adreno_probe(struct platform_device *pdev)
		return -ENODEV;
	}

	status = adreno_update_soc_hw_revision_quirks(adreno_dev, pdev);
	if (status) {
		device->pdev = NULL;
		return status;
	}

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