Merge "msm: kgsl: Add support for RDPM frequency register writes"

This commit is contained in:
qctecmdr 2020-11-04 06:07:47 -08:00 • committed by Gerrit - the friendly Code Review server
commit ee912b37f3
5 changed files with 108 additions and 0 deletions

View file

@ -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);

View file

@ -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

View file

@ -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);
}
@ -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;
@ -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;
}
@ -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");
@ -2278,6 +2289,8 @@ gdsc_off:
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;
}
@ -2357,6 +2370,8 @@ gdsc_off:
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;
}
@ -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)
{
@ -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)
@ -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);
@ -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;

View file

@ -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 */

View file

@ -220,6 +220,8 @@ gdsc_off:
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;
}
@ -281,6 +283,8 @@ gdsc_off:
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;
}
@ -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);
@ -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:
@ -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;
}