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