msm: kgsl: Move voltage levels to the GPU specific powerlevels

There are only two reasons for us to define a OPP table these days, and
one of them is to define the voltage levels that we send to the GMU.
That is silly because we have a perfectly good power level definition
already handy. Move the levels to the GPU definition and use them
accordingly.

Change-Id: Ic0dedbad2d3c84a2de7cda5311ff99e96434b9e5
Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
This commit is contained in:
Jordan Crouse 2019-10-14 10:41:09 -06:00
commit 2cb2a1140c
5 changed files with 62 additions and 59 deletions

View file

@ -907,31 +907,46 @@ static int adreno_of_parse_pwrlevels(struct adreno_device *adreno_dev,
pwr->num_pwrlevels = 0;
for_each_child_of_node(node, child) {
unsigned int index, freq = 0;
u32 index, freq = 0, voltage, bus;
struct kgsl_pwrlevel *level;
if (of_property_read_u32(child, "reg", &index)) {
dev_err(device->dev,
"%pOF: powerlevel index not found\n", child);
of_node_put(child);
return -EINVAL;
ret = of_property_read_u32(child, "reg", &index);
if (ret) {
dev_err(device->dev, "%pOF: powerlevel index not found\n",
child);
goto out;
}
if (of_property_read_u32(child, "qcom,gpu-freq", &freq)) {
dev_err(device->dev,
"%pOF: Unable to read qcom,gpu-freq\n", child);
of_node_put(child);
return -EINVAL;
ret = of_property_read_u32(child, "qcom,gpu-freq", &freq);
if (ret) {
dev_err(device->dev, "%pOF: Unable to read qcom,gpu-freq\n",
child);
goto out;
}
/* Ignore "zero" powerlevels */
if (!freq)
continue;
ret = of_property_read_u32(child, "qcom,level", &voltage);
if (ret) {
dev_err(device->dev, "%pOF: Unable to read qcom,level\n",
child);
goto out;
}
ret = kgsl_of_property_read_ddrtype(child, "qcom,bus-freq",
&bus);
if (ret) {
dev_err(device->dev, "%pOF:Unable to read qcom,bus-freq\n",
child);
goto out;
}
if (index >= KGSL_MAX_PWRLEVELS) {
dev_err(device->dev,
"%pOF: Pwrlevel index %d is out of range\n",
child, index);
dev_err(device->dev, "%pOF: Pwrlevel index %d is out of range\n",
child, index);
continue;
}
@ -941,20 +956,12 @@ static int adreno_of_parse_pwrlevels(struct adreno_device *adreno_dev,
level = &pwr->pwrlevels[index];
level->gpu_freq = freq;
level->bus_freq = bus;
level->voltage_level = voltage;
of_property_read_u32(child, "qcom,acd-level",
&level->acd_level);
ret = kgsl_of_property_read_ddrtype(child,
"qcom,bus-freq", &level->bus_freq);
if (ret) {
dev_err(device->dev,
"%pOF: Couldn't read the bus frequency for power level %d\n",
child, index);
of_node_put(child);
return ret;
}
level->bus_min = level->bus_freq;
kgsl_of_property_read_ddrtype(child,
"qcom,bus-min", &level->bus_min);
@ -965,6 +972,9 @@ static int adreno_of_parse_pwrlevels(struct adreno_device *adreno_dev,
}
return 0;
out:
of_node_put(child);
return ret;
}
static void adreno_of_get_initial_pwrlevel(struct adreno_device *adreno_dev,

View file

@ -690,45 +690,22 @@ static int rpmh_arc_votes_init(struct kgsl_device *device,
{
unsigned int num_freqs;
u16 vlvl_tbl[MAX_GX_LEVELS];
unsigned int *freq_tbl;
int i;
struct dev_pm_opp *opp;
if (type == GMU_ARC_VOTE)
return rpmh_gmu_arc_votes_init(gmu, pri_rail, sec_rail);
num_freqs = gmu->num_gpupwrlevels;
freq_tbl = gmu->gpu_freqs;
if (num_freqs > pri_rail->num || num_freqs > MAX_GX_LEVELS) {
if (num_freqs > pri_rail->num) {
dev_err(&gmu->pdev->dev,
"Defined more GPU DCVS levels than RPMh can support\n");
return -EINVAL;
}
memset(vlvl_tbl, 0, sizeof(vlvl_tbl));
/* Get the values from OPP API */
for (i = 0; i < num_freqs; i++) {
/* Hardcode VLVL 0 because it is not present in OPP */
if (freq_tbl[i] == 0) {
vlvl_tbl[i] = 0;
continue;
}
opp = dev_pm_opp_find_freq_exact(&device->pdev->dev,
freq_tbl[i], true);
if (IS_ERR(opp)) {
dev_err(&gmu->pdev->dev,
"Failed to find opp freq %d for GPU\n",
freq_tbl[i]);
return PTR_ERR(opp);
}
vlvl_tbl[i] = dev_pm_opp_get_voltage(opp);
dev_pm_opp_put(opp);
}
for (i = 0; i < num_freqs; i++)
vlvl_tbl[i] = gmu->pwrlevels[i].level;
return setup_volt_dependency_tbl(gmu->rpmh_votes.gx_votes, pri_rail,
sec_rail, vlvl_tbl, num_freqs);
@ -1205,7 +1182,7 @@ static int gmu_probe(struct kgsl_device *device, struct device_node *node)
struct kgsl_hfi *hfi;
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
int i = 0, ret = -ENXIO, index = 0;
int i = 0, ret = -ENXIO, index;
gmu = kzalloc(sizeof(struct gmu_device), GFP_KERNEL);
@ -1275,12 +1252,21 @@ static int gmu_probe(struct kgsl_device *device, struct device_node *node)
tasklet_init(&hfi->tasklet, hfi_receiver, (unsigned long) gmu);
hfi->kgsldev = device;
/* Add a dummy level for "off" that the GMU expects */
gmu->gpu_freqs[index++] = 0;
if (WARN(pwr->num_pwrlevels + 1 > ARRAY_SIZE(gmu->pwrlevels),
"Too many GPU powerlevels for the GMU HFI\n")) {
ret = -EINVAL;
goto error;
}
/* Add a dummy level for "off" because the GMU expects it */
gmu->pwrlevels[0].freq = 0;
gmu->pwrlevels[0].level = 0;
/* GMU power levels are in ascending order */
for (i = pwr->num_pwrlevels - 1; i >= 0; i--)
gmu->gpu_freqs[index++] = pwr->pwrlevels[i].gpu_freq;
for (index = 1, i = pwr->num_pwrlevels - 1; i >= 0; i--, index++) {
gmu->pwrlevels[index].freq = pwr->pwrlevels[i].gpu_freq;
gmu->pwrlevels[index].level = pwr->pwrlevels[i].voltage_level;
}
gmu->num_gpupwrlevels = pwr->num_pwrlevels + 1;

View file

@ -158,7 +158,6 @@ struct icc_path;
* @dump_mem: pointer to GMU debug dump memory
* @gmu_log: gmu event log memory
* @hfi: HFI controller
* @gpu_freqs: GPU frequency table with lowest freq at index 0
* @num_gpupwrlevels: number GPU frequencies in GPU freq table
* @num_bwlevel: number of GPU BW levels
* @num_cnocbwlevel: number CNOC BW levels
@ -194,7 +193,13 @@ struct gmu_device {
struct gmu_memdesc *dump_mem;
struct gmu_memdesc *gmu_log;
struct kgsl_hfi hfi;
unsigned int gpu_freqs[MAX_GX_LEVELS];
/** @pwrlevels: Array of GMU power levels */
struct {
/** @freq: GPU frequency */
unsigned long freq;
/** @level: Voltage level */
u32 level;
} pwrlevels[MAX_GX_LEVELS];
unsigned int num_gpupwrlevels;
unsigned int num_bwlevels;
unsigned int num_cnocbwlevels;

View file

@ -437,7 +437,7 @@ static int hfi_send_dcvstbl_v1(struct gmu_device *gmu)
for (i = 0; i < gmu->num_gpupwrlevels; i++) {
cmd.gx_votes[i].vote = gmu->rpmh_votes.gx_votes[i];
/* Divide by 1000 to convert to kHz */
cmd.gx_votes[i].freq = gmu->gpu_freqs[i] / 1000;
cmd.gx_votes[i].freq = gmu->pwrlevels[i].freq / 1000;
}
cmd.cx_votes[0].vote = gmu->rpmh_votes.cx_votes[0];
@ -483,7 +483,7 @@ static int hfi_send_dcvstbl(struct gmu_device *gmu)
/* Hardcode this to the max threshold since it is not used */
cmd.gx_votes[i].acd = 0xFFFFFFFF;
/* Divide by 1000 to convert to kHz */
cmd.gx_votes[i].freq = gmu->gpu_freqs[i] / 1000;
cmd.gx_votes[i].freq = gmu->pwrlevels[i].freq / 1000;
}
cmd.cx_votes[0].vote = gmu->rpmh_votes.cx_votes[0];

View file

@ -69,6 +69,8 @@ struct kgsl_pwrlevel {
unsigned int bus_min;
unsigned int bus_max;
unsigned int acd_level;
/** @voltage_level: Voltage level used by the GMU to vote RPMh */
u32 voltage_level;
};
/**