Loading drivers/gpu/msm/adreno_a6xx.c +34 −0 Original line number Diff line number Diff line Loading @@ -698,6 +698,40 @@ void a6xx_start(struct adreno_device *adreno_dev) } } /* Offsets into the MX/CX mapped register regions */ #define RDPM_MX_OFFSET 0xf00 #define RDPM_CX_OFFSET 0xf18 void a6xx_rdpm_mx_freq_update(struct a6xx_gmu_device *gmu, u32 freq) { if (gmu->rdpm_mx_virt) { writel_relaxed(freq/1000, (gmu->rdpm_mx_virt + RDPM_MX_OFFSET)); /* * ensure previous writes post before this one, * i.e. act like normal writel() */ wmb(); } } void a6xx_rdpm_cx_freq_update(struct a6xx_gmu_device *gmu, u32 freq) { if (gmu->rdpm_cx_virt) { writel_relaxed(freq/1000, (gmu->rdpm_cx_virt + RDPM_CX_OFFSET)); /* * ensure previous writes post before this one, * i.e. act like normal writel() */ wmb(); } } void a6xx_unhalt_sqe(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); Loading drivers/gpu/msm/adreno_a6xx.h +18 −0 Original line number Diff line number Diff line Loading @@ -433,4 +433,22 @@ int a6xx_perfcounter_update(struct adreno_device *adreno_dev, extern const struct adreno_perfcounters adreno_a630_perfcounters; extern const struct adreno_perfcounters adreno_a6xx_perfcounters; extern const struct adreno_perfcounters adreno_a6xx_legacy_perfcounters; /** * a6xx_rdpm_mx_freq_update - Update the mx frequency * @gmu: An Adreno GMU handle * @freq: Frequency in KHz * * This function communicates GPU mx frequency(in Mhz) changes to rdpm. */ void a6xx_rdpm_mx_freq_update(struct a6xx_gmu_device *gmu, u32 freq); /** * a6xx_rdpm_cx_freq_update - Update the cx frequency * @gmu: An Adreno GMU handle * @freq: Frequency in KHz * * This function communicates GPU cx frequency(in Mhz) changes to rdpm. */ void a6xx_rdpm_cx_freq_update(struct a6xx_gmu_device *gmu, u32 freq); #endif drivers/gpu/msm/adreno_a6xx_gmu.c +40 −0 Original line number Diff line number Diff line Loading @@ -1092,6 +1092,9 @@ static int a6xx_gmu_gfx_rail_on(struct adreno_device *adreno_dev) gmu_core_regwrite(device, A6XX_GMU_MX_VOTE_IDX, ARC_VOTE_GET_SEC(default_opp)); a6xx_rdpm_mx_freq_update(gmu, gmu->hfi.dcvs_table.gx_votes[perf_idx].freq); return a6xx_gmu_oob_set(device, oob_boot_slumber); } Loading Loading @@ -1781,6 +1784,8 @@ void a6xx_gmu_suspend(struct adreno_device *adreno_dev) if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_CX_GDSC)) regulator_set_mode(gmu->cx_gdsc, REGULATOR_MODE_NORMAL); a6xx_rdpm_cx_freq_update(gmu, 0); dev_err(&gmu->pdev->dev, "Suspended GMU\n"); device->state = KGSL_STATE_NONE; Loading Loading @@ -1843,6 +1848,10 @@ static int a6xx_gmu_dcvs_set(struct adreno_device *adreno_dev, } } if (req.freq != INVALID_DCVS_IDX) a6xx_rdpm_mx_freq_update(gmu, gmu->hfi.dcvs_table.gx_votes[req.freq].freq); return ret; } Loading Loading @@ -2156,6 +2165,8 @@ int a6xx_gmu_enable_clks(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); int ret; a6xx_rdpm_cx_freq_update(gmu, GMU_FREQUENCY / 1000); ret = a6xx_gmu_clk_set_rate(gmu, "gmu_clk", GMU_FREQUENCY); if (ret) { dev_err(&gmu->pdev->dev, "Unable to set the GMU clock\n"); Loading Loading @@ -2278,6 +2289,8 @@ static int a6xx_gmu_first_boot(struct adreno_device *adreno_dev) if (!a6xx_cx_regulator_disable_wait(gmu->cx_gdsc, device, 5000)) dev_err(&gmu->pdev->dev, "GMU CX gdsc off timeout\n"); a6xx_rdpm_cx_freq_update(gmu, 0); return ret; } Loading Loading @@ -2357,6 +2370,8 @@ static int a6xx_gmu_boot(struct adreno_device *adreno_dev) if (!a6xx_cx_regulator_disable_wait(gmu->cx_gdsc, device, 5000)) dev_err(&gmu->pdev->dev, "GMU CX gdsc off timeout\n"); a6xx_rdpm_cx_freq_update(gmu, 0); return ret; } Loading Loading @@ -2541,6 +2556,24 @@ static int a6xx_gmu_reg_probe(struct adreno_device *adreno_dev) return 0; } static void a6xx_gmu_rdpm_probe(struct a6xx_gmu_device *gmu, struct kgsl_device *device) { struct resource *res; res = platform_get_resource_byname(device->pdev, IORESOURCE_MEM, "rdpm_cx"); if (res) gmu->rdpm_cx_virt = devm_ioremap(&device->pdev->dev, res->start, resource_size(res)); res = platform_get_resource_byname(device->pdev, IORESOURCE_MEM, "rdpm_mx"); if (res) gmu->rdpm_mx_virt = devm_ioremap(&device->pdev->dev, res->start, resource_size(res)); } static int a6xx_gmu_regulators_probe(struct a6xx_gmu_device *gmu, struct platform_device *pdev) { Loading Loading @@ -2660,6 +2693,9 @@ int a6xx_gmu_probe(struct kgsl_device *device, } } /* Setup any rdpm register ranges */ a6xx_gmu_rdpm_probe(gmu, device); /* Set up GMU regulators */ ret = a6xx_gmu_regulators_probe(gmu, pdev); if (ret) Loading Loading @@ -2790,6 +2826,8 @@ static int a6xx_gmu_power_off(struct adreno_device *adreno_dev) ret = a6xx_rscc_sleep_sequence(adreno_dev); a6xx_rdpm_mx_freq_update(gmu, 0); /* Now that we are done with GMU and GPU, Clear the GBIF */ if (!adreno_is_a630(adreno_dev)) ret = a6xx_halt_gbif(adreno_dev); Loading @@ -2804,6 +2842,8 @@ static int a6xx_gmu_power_off(struct adreno_device *adreno_dev) if (!a6xx_cx_regulator_disable_wait(gmu->cx_gdsc, device, 5000)) dev_err(&gmu->pdev->dev, "GMU CX gdsc off timeout\n"); a6xx_rdpm_cx_freq_update(gmu, 0); device->state = KGSL_STATE_NONE; return ret; Loading drivers/gpu/msm/adreno_a6xx_gmu.h +4 −0 Original line number Diff line number Diff line Loading @@ -201,6 +201,10 @@ struct a6xx_gmu_device { void __iomem *rscc_virt; /** @domain: IOMMU domain for the kernel context */ struct iommu_domain *domain; /** @rdpm_cx_virt: Pointer where the RDPM CX block is mapped */ void __iomem *rdpm_cx_virt; /** @rdpm_mx_virt: Pointer where the RDPM MX block is mapped */ void __iomem *rdpm_mx_virt; }; /* Helper function to get to a6xx gmu device from adreno device */ Loading drivers/gpu/msm/adreno_a6xx_hwsched.c +12 −0 Original line number Diff line number Diff line Loading @@ -220,6 +220,8 @@ static int a6xx_hwsched_gmu_first_boot(struct adreno_device *adreno_dev) if (!a6xx_cx_regulator_disable_wait(gmu->cx_gdsc, device, 5000)) dev_err(&gmu->pdev->dev, "GMU CX gdsc off timeout\n"); a6xx_rdpm_cx_freq_update(gmu, 0); return ret; } Loading Loading @@ -281,6 +283,8 @@ static int a6xx_hwsched_gmu_boot(struct adreno_device *adreno_dev) if (!a6xx_cx_regulator_disable_wait(gmu->cx_gdsc, device, 5000)) dev_err(&gmu->pdev->dev, "GMU CX gdsc off timeout\n"); a6xx_rdpm_cx_freq_update(gmu, 0); return ret; } Loading Loading @@ -365,6 +369,8 @@ static int a6xx_hwsched_gmu_power_off(struct adreno_device *adreno_dev) ret = a6xx_rscc_sleep_sequence(adreno_dev); a6xx_rdpm_mx_freq_update(gmu, 0); /* Now that we are done with GMU and GPU, Clear the GBIF */ ret = a6xx_halt_gbif(adreno_dev); Loading @@ -378,6 +384,8 @@ static int a6xx_hwsched_gmu_power_off(struct adreno_device *adreno_dev) if (!a6xx_cx_regulator_disable_wait(gmu->cx_gdsc, device, 5000)) dev_err(&gmu->pdev->dev, "GMU CX gdsc off timeout\n"); a6xx_rdpm_cx_freq_update(gmu, 0); return ret; error: Loading Loading @@ -776,6 +784,10 @@ static int a6xx_hwsched_dcvs_set(struct adreno_device *adreno_dev, } if (req.freq != INVALID_DCVS_IDX) a6xx_rdpm_mx_freq_update(gmu, gmu->hfi.dcvs_table.gx_votes[req.freq].freq); return ret; } Loading Loading
drivers/gpu/msm/adreno_a6xx.c +34 −0 Original line number Diff line number Diff line Loading @@ -698,6 +698,40 @@ void a6xx_start(struct adreno_device *adreno_dev) } } /* Offsets into the MX/CX mapped register regions */ #define RDPM_MX_OFFSET 0xf00 #define RDPM_CX_OFFSET 0xf18 void a6xx_rdpm_mx_freq_update(struct a6xx_gmu_device *gmu, u32 freq) { if (gmu->rdpm_mx_virt) { writel_relaxed(freq/1000, (gmu->rdpm_mx_virt + RDPM_MX_OFFSET)); /* * ensure previous writes post before this one, * i.e. act like normal writel() */ wmb(); } } void a6xx_rdpm_cx_freq_update(struct a6xx_gmu_device *gmu, u32 freq) { if (gmu->rdpm_cx_virt) { writel_relaxed(freq/1000, (gmu->rdpm_cx_virt + RDPM_CX_OFFSET)); /* * ensure previous writes post before this one, * i.e. act like normal writel() */ wmb(); } } void a6xx_unhalt_sqe(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); Loading
drivers/gpu/msm/adreno_a6xx.h +18 −0 Original line number Diff line number Diff line Loading @@ -433,4 +433,22 @@ int a6xx_perfcounter_update(struct adreno_device *adreno_dev, extern const struct adreno_perfcounters adreno_a630_perfcounters; extern const struct adreno_perfcounters adreno_a6xx_perfcounters; extern const struct adreno_perfcounters adreno_a6xx_legacy_perfcounters; /** * a6xx_rdpm_mx_freq_update - Update the mx frequency * @gmu: An Adreno GMU handle * @freq: Frequency in KHz * * This function communicates GPU mx frequency(in Mhz) changes to rdpm. */ void a6xx_rdpm_mx_freq_update(struct a6xx_gmu_device *gmu, u32 freq); /** * a6xx_rdpm_cx_freq_update - Update the cx frequency * @gmu: An Adreno GMU handle * @freq: Frequency in KHz * * This function communicates GPU cx frequency(in Mhz) changes to rdpm. */ void a6xx_rdpm_cx_freq_update(struct a6xx_gmu_device *gmu, u32 freq); #endif
drivers/gpu/msm/adreno_a6xx_gmu.c +40 −0 Original line number Diff line number Diff line Loading @@ -1092,6 +1092,9 @@ static int a6xx_gmu_gfx_rail_on(struct adreno_device *adreno_dev) gmu_core_regwrite(device, A6XX_GMU_MX_VOTE_IDX, ARC_VOTE_GET_SEC(default_opp)); a6xx_rdpm_mx_freq_update(gmu, gmu->hfi.dcvs_table.gx_votes[perf_idx].freq); return a6xx_gmu_oob_set(device, oob_boot_slumber); } Loading Loading @@ -1781,6 +1784,8 @@ void a6xx_gmu_suspend(struct adreno_device *adreno_dev) if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_CX_GDSC)) regulator_set_mode(gmu->cx_gdsc, REGULATOR_MODE_NORMAL); a6xx_rdpm_cx_freq_update(gmu, 0); dev_err(&gmu->pdev->dev, "Suspended GMU\n"); device->state = KGSL_STATE_NONE; Loading Loading @@ -1843,6 +1848,10 @@ static int a6xx_gmu_dcvs_set(struct adreno_device *adreno_dev, } } if (req.freq != INVALID_DCVS_IDX) a6xx_rdpm_mx_freq_update(gmu, gmu->hfi.dcvs_table.gx_votes[req.freq].freq); return ret; } Loading Loading @@ -2156,6 +2165,8 @@ int a6xx_gmu_enable_clks(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); int ret; a6xx_rdpm_cx_freq_update(gmu, GMU_FREQUENCY / 1000); ret = a6xx_gmu_clk_set_rate(gmu, "gmu_clk", GMU_FREQUENCY); if (ret) { dev_err(&gmu->pdev->dev, "Unable to set the GMU clock\n"); Loading Loading @@ -2278,6 +2289,8 @@ static int a6xx_gmu_first_boot(struct adreno_device *adreno_dev) if (!a6xx_cx_regulator_disable_wait(gmu->cx_gdsc, device, 5000)) dev_err(&gmu->pdev->dev, "GMU CX gdsc off timeout\n"); a6xx_rdpm_cx_freq_update(gmu, 0); return ret; } Loading Loading @@ -2357,6 +2370,8 @@ static int a6xx_gmu_boot(struct adreno_device *adreno_dev) if (!a6xx_cx_regulator_disable_wait(gmu->cx_gdsc, device, 5000)) dev_err(&gmu->pdev->dev, "GMU CX gdsc off timeout\n"); a6xx_rdpm_cx_freq_update(gmu, 0); return ret; } Loading Loading @@ -2541,6 +2556,24 @@ static int a6xx_gmu_reg_probe(struct adreno_device *adreno_dev) return 0; } static void a6xx_gmu_rdpm_probe(struct a6xx_gmu_device *gmu, struct kgsl_device *device) { struct resource *res; res = platform_get_resource_byname(device->pdev, IORESOURCE_MEM, "rdpm_cx"); if (res) gmu->rdpm_cx_virt = devm_ioremap(&device->pdev->dev, res->start, resource_size(res)); res = platform_get_resource_byname(device->pdev, IORESOURCE_MEM, "rdpm_mx"); if (res) gmu->rdpm_mx_virt = devm_ioremap(&device->pdev->dev, res->start, resource_size(res)); } static int a6xx_gmu_regulators_probe(struct a6xx_gmu_device *gmu, struct platform_device *pdev) { Loading Loading @@ -2660,6 +2693,9 @@ int a6xx_gmu_probe(struct kgsl_device *device, } } /* Setup any rdpm register ranges */ a6xx_gmu_rdpm_probe(gmu, device); /* Set up GMU regulators */ ret = a6xx_gmu_regulators_probe(gmu, pdev); if (ret) Loading Loading @@ -2790,6 +2826,8 @@ static int a6xx_gmu_power_off(struct adreno_device *adreno_dev) ret = a6xx_rscc_sleep_sequence(adreno_dev); a6xx_rdpm_mx_freq_update(gmu, 0); /* Now that we are done with GMU and GPU, Clear the GBIF */ if (!adreno_is_a630(adreno_dev)) ret = a6xx_halt_gbif(adreno_dev); Loading @@ -2804,6 +2842,8 @@ static int a6xx_gmu_power_off(struct adreno_device *adreno_dev) if (!a6xx_cx_regulator_disable_wait(gmu->cx_gdsc, device, 5000)) dev_err(&gmu->pdev->dev, "GMU CX gdsc off timeout\n"); a6xx_rdpm_cx_freq_update(gmu, 0); device->state = KGSL_STATE_NONE; return ret; Loading
drivers/gpu/msm/adreno_a6xx_gmu.h +4 −0 Original line number Diff line number Diff line Loading @@ -201,6 +201,10 @@ struct a6xx_gmu_device { void __iomem *rscc_virt; /** @domain: IOMMU domain for the kernel context */ struct iommu_domain *domain; /** @rdpm_cx_virt: Pointer where the RDPM CX block is mapped */ void __iomem *rdpm_cx_virt; /** @rdpm_mx_virt: Pointer where the RDPM MX block is mapped */ void __iomem *rdpm_mx_virt; }; /* Helper function to get to a6xx gmu device from adreno device */ Loading
drivers/gpu/msm/adreno_a6xx_hwsched.c +12 −0 Original line number Diff line number Diff line Loading @@ -220,6 +220,8 @@ static int a6xx_hwsched_gmu_first_boot(struct adreno_device *adreno_dev) if (!a6xx_cx_regulator_disable_wait(gmu->cx_gdsc, device, 5000)) dev_err(&gmu->pdev->dev, "GMU CX gdsc off timeout\n"); a6xx_rdpm_cx_freq_update(gmu, 0); return ret; } Loading Loading @@ -281,6 +283,8 @@ static int a6xx_hwsched_gmu_boot(struct adreno_device *adreno_dev) if (!a6xx_cx_regulator_disable_wait(gmu->cx_gdsc, device, 5000)) dev_err(&gmu->pdev->dev, "GMU CX gdsc off timeout\n"); a6xx_rdpm_cx_freq_update(gmu, 0); return ret; } Loading Loading @@ -365,6 +369,8 @@ static int a6xx_hwsched_gmu_power_off(struct adreno_device *adreno_dev) ret = a6xx_rscc_sleep_sequence(adreno_dev); a6xx_rdpm_mx_freq_update(gmu, 0); /* Now that we are done with GMU and GPU, Clear the GBIF */ ret = a6xx_halt_gbif(adreno_dev); Loading @@ -378,6 +384,8 @@ static int a6xx_hwsched_gmu_power_off(struct adreno_device *adreno_dev) if (!a6xx_cx_regulator_disable_wait(gmu->cx_gdsc, device, 5000)) dev_err(&gmu->pdev->dev, "GMU CX gdsc off timeout\n"); a6xx_rdpm_cx_freq_update(gmu, 0); return ret; error: Loading Loading @@ -776,6 +784,10 @@ static int a6xx_hwsched_dcvs_set(struct adreno_device *adreno_dev, } if (req.freq != INVALID_DCVS_IDX) a6xx_rdpm_mx_freq_update(gmu, gmu->hfi.dcvs_table.gx_votes[req.freq].freq); return ret; } Loading