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