Message ID | 20230702175045.122041-4-dmitry.baryshkov@linaro.org |
---|---|
State | New |
Headers | show |
Series | ARM: qcom: msm8960: support CPU frequency scaling | expand |
On 2.07.2023 19:50, Dmitry Baryshkov wrote: > Early Krait CPUs required that core voltage was not below 1.15 V. > Implement this requirement by adding separate config_regulators > callback. > > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> > --- "early krait" as in msm8960, or "early krait" as in "pre-production"? Konrad > drivers/cpufreq/qcom-cpufreq-nvmem.c | 67 +++++++++++++++++++++++++++- > 1 file changed, 66 insertions(+), 1 deletion(-) > > diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c > index 113f35668048..9312c8ab62a8 100644 > --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c > +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c > @@ -30,6 +30,8 @@ > #include <linux/slab.h> > #include <linux/soc/qcom/smem.h> > > +#include <asm/cputype.h> > + > #include <dt-bindings/arm/qcom,ids.h> > > struct qcom_cpufreq_drv; > @@ -257,6 +259,66 @@ static const struct qcom_cpufreq_match_data match_data_apq8064 = { > .regulator_names = apq8064_regulator_names, > }; > > +static const int krait_needs_vmin(void) > +{ > + switch (read_cpuid_id()) { > + case 0x511F04D0: /* KR28M2A20 */ > + case 0x511F04D1: /* KR28M2A21 */ > + case 0x510F06F0: /* KR28M4A10 */ > + return 1; > + default: > + return 0; > + }; > +} > + > +#define KRAIT_VMIN 1150000 > +#define KRAIT_VMIN_MAX (KRAIT_VMIN + 25000) > +static int krait_config_regulator_vmin(struct device *dev, > + struct dev_pm_opp *old_opp, struct dev_pm_opp *new_opp, > + struct regulator **regulators, unsigned int count) > +{ > + struct regulator *reg = regulators[0]; > + struct dev_pm_opp_supply supply; > + int ret; > + > + /* This function only supports single regulator per device */ > + if (WARN_ON(count > 1)) { > + dev_err(dev, "multiple regulators are not supported\n"); > + return -EINVAL; > + } > + > + if (IS_ERR(reg)) { > + dev_dbg(dev, "%s: regulator not available: %ld\n", __func__, > + PTR_ERR(reg)); > + return 0; > + } > + > + ret = dev_pm_opp_get_supplies(new_opp, &supply); > + if (WARN_ON(ret)) > + return ret; > + > + if (supply.u_volt_min < KRAIT_VMIN) { > + supply.u_volt_min = KRAIT_VMIN; > + supply.u_volt = KRAIT_VMIN; > + supply.u_volt_max = KRAIT_VMIN_MAX; > + } > + > + dev_dbg(dev, "%s: voltages (mV): %lu %lu %lu\n", __func__, > + supply.u_volt_min, supply.u_volt, supply.u_volt_max); > + > + ret = regulator_set_voltage_triplet(reg, > + supply.u_volt_min, > + supply.u_volt, > + supply.u_volt_max); > + if (ret) > + dev_err(dev, "%s: failed to set voltage (%lu %lu %lu mV): %d\n", > + __func__, supply.u_volt_min, supply.u_volt, > + supply.u_volt_max, ret); > + > + return ret; > +} > + > + > static int qcom_cpufreq_probe(struct platform_device *pdev) > { > struct qcom_cpufreq_drv *drv; > @@ -344,8 +406,11 @@ static int qcom_cpufreq_probe(struct platform_device *pdev) > config.virt_devs = NULL; > } > > - if (drv->data->regulator_names) > + if (drv->data->regulator_names) { > config.regulator_names = drv->data->regulator_names; > + if (krait_needs_vmin()) > + config.config_regulators = krait_config_regulator_vmin; > + } > > if (config.supported_hw || > config.genpd_names ||
diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c index 113f35668048..9312c8ab62a8 100644 --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c @@ -30,6 +30,8 @@ #include <linux/slab.h> #include <linux/soc/qcom/smem.h> +#include <asm/cputype.h> + #include <dt-bindings/arm/qcom,ids.h> struct qcom_cpufreq_drv; @@ -257,6 +259,66 @@ static const struct qcom_cpufreq_match_data match_data_apq8064 = { .regulator_names = apq8064_regulator_names, }; +static const int krait_needs_vmin(void) +{ + switch (read_cpuid_id()) { + case 0x511F04D0: /* KR28M2A20 */ + case 0x511F04D1: /* KR28M2A21 */ + case 0x510F06F0: /* KR28M4A10 */ + return 1; + default: + return 0; + }; +} + +#define KRAIT_VMIN 1150000 +#define KRAIT_VMIN_MAX (KRAIT_VMIN + 25000) +static int krait_config_regulator_vmin(struct device *dev, + struct dev_pm_opp *old_opp, struct dev_pm_opp *new_opp, + struct regulator **regulators, unsigned int count) +{ + struct regulator *reg = regulators[0]; + struct dev_pm_opp_supply supply; + int ret; + + /* This function only supports single regulator per device */ + if (WARN_ON(count > 1)) { + dev_err(dev, "multiple regulators are not supported\n"); + return -EINVAL; + } + + if (IS_ERR(reg)) { + dev_dbg(dev, "%s: regulator not available: %ld\n", __func__, + PTR_ERR(reg)); + return 0; + } + + ret = dev_pm_opp_get_supplies(new_opp, &supply); + if (WARN_ON(ret)) + return ret; + + if (supply.u_volt_min < KRAIT_VMIN) { + supply.u_volt_min = KRAIT_VMIN; + supply.u_volt = KRAIT_VMIN; + supply.u_volt_max = KRAIT_VMIN_MAX; + } + + dev_dbg(dev, "%s: voltages (mV): %lu %lu %lu\n", __func__, + supply.u_volt_min, supply.u_volt, supply.u_volt_max); + + ret = regulator_set_voltage_triplet(reg, + supply.u_volt_min, + supply.u_volt, + supply.u_volt_max); + if (ret) + dev_err(dev, "%s: failed to set voltage (%lu %lu %lu mV): %d\n", + __func__, supply.u_volt_min, supply.u_volt, + supply.u_volt_max, ret); + + return ret; +} + + static int qcom_cpufreq_probe(struct platform_device *pdev) { struct qcom_cpufreq_drv *drv; @@ -344,8 +406,11 @@ static int qcom_cpufreq_probe(struct platform_device *pdev) config.virt_devs = NULL; } - if (drv->data->regulator_names) + if (drv->data->regulator_names) { config.regulator_names = drv->data->regulator_names; + if (krait_needs_vmin()) + config.config_regulators = krait_config_regulator_vmin; + } if (config.supported_hw || config.genpd_names ||
Early Krait CPUs required that core voltage was not below 1.15 V. Implement this requirement by adding separate config_regulators callback. Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> --- drivers/cpufreq/qcom-cpufreq-nvmem.c | 67 +++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-)