Loading Documentation/devicetree/bindings/gpu/adreno-pwrlevels.txt 0 → 100644 +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 Documentation/devicetree/bindings/gpu/adreno.txt +38 −32 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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. Loading Loading @@ -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 Loading Loading @@ -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>; Loading Loading @@ -222,6 +227,7 @@ Example of A330 GPU in MSM8916: qcom,io-fraction = <0>; }; }; }; }; }; arch/arm/boot/dts/qcom/msm8996-gpu.dtsi +8 −6 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ < 5195 /* 681 MHz */ >, < 5859 /* 768 MHz */ >, < 7759 /* 1017 MHz */ >, < 9887 /* 1296 MHz */ >, < 11863 /* 1555 MHz */ >, < 13763 /* 1804 MHz */ >; }; Loading @@ -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>; Loading Loading @@ -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>, Loading @@ -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"; Loading arch/arm/boot/dts/qcom/msm8996-v3.dtsi +125 −64 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -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 { Loading Loading @@ -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>; }; }; }; }; Loading drivers/gpu/msm/adreno.c +115 −25 Original line number Diff line number Diff line Loading @@ -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 * Loading Loading @@ -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[] = { Loading @@ -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) { Loading Loading @@ -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) { Loading @@ -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; Loading @@ -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", Loading Loading @@ -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; Loading Loading @@ -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 Loading
Documentation/devicetree/bindings/gpu/adreno-pwrlevels.txt 0 → 100644 +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
Documentation/devicetree/bindings/gpu/adreno.txt +38 −32 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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. Loading Loading @@ -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 Loading Loading @@ -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>; Loading Loading @@ -222,6 +227,7 @@ Example of A330 GPU in MSM8916: qcom,io-fraction = <0>; }; }; }; }; };
arch/arm/boot/dts/qcom/msm8996-gpu.dtsi +8 −6 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ < 5195 /* 681 MHz */ >, < 5859 /* 768 MHz */ >, < 7759 /* 1017 MHz */ >, < 9887 /* 1296 MHz */ >, < 11863 /* 1555 MHz */ >, < 13763 /* 1804 MHz */ >; }; Loading @@ -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>; Loading Loading @@ -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>, Loading @@ -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"; Loading
arch/arm/boot/dts/qcom/msm8996-v3.dtsi +125 −64 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -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 { Loading Loading @@ -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>; }; }; }; }; Loading
drivers/gpu/msm/adreno.c +115 −25 Original line number Diff line number Diff line Loading @@ -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 * Loading Loading @@ -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[] = { Loading @@ -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) { Loading Loading @@ -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) { Loading @@ -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; Loading @@ -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", Loading Loading @@ -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; Loading Loading @@ -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