mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-08 12:58:12 -04:00
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:
parent
55dccd6234
commit
2cb2a1140c
5 changed files with 62 additions and 59 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue