Loading Documentation/devicetree/bindings/gpu/adreno.txt +42 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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>; Loading drivers/gpu/msm/adreno.c +108 −30 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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) { Loading @@ -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) Loading Loading @@ -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)) { Loading @@ -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); Loading Loading @@ -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); Loading Loading
Documentation/devicetree/bindings/gpu/adreno.txt +42 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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>; Loading
drivers/gpu/msm/adreno.c +108 −30 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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) { Loading @@ -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) Loading Loading @@ -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)) { Loading @@ -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); Loading Loading @@ -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); Loading