static int _spm_regulator_set_voltage(struct regulator_dev *rdev) { struct spm_vreg *vreg = rdev_get_drvdata(rdev); bool pwm_required; int rc = 0; int uV; rc = spm_regulator_get_voltage(rdev); if (IS_ERR_VALUE(rc)) return rc; if (vreg->vlevel == vreg->last_set_vlevel) return 0; pwm_required = (vreg->regulator_type == QPNP_TYPE_FTS2) && !(vreg->init_mode & QPNP_SMPS_MODE_PWM) && vreg->uV > vreg->last_set_uV; if (pwm_required) { /* Switch to PWM mode so that voltage ramping is fast. */ rc = qpnp_smps_set_mode(vreg, QPNP_SMPS_MODE_PWM); if (rc) return rc; } do { uV = vreg->uV > vreg->last_set_uV ? min(vreg->uV, vreg->last_set_uV + (int)vreg->max_step_uV) : max(vreg->uV, vreg->last_set_uV - (int)vreg->max_step_uV); rc = spm_regulator_write_voltage(vreg, uV); if (rc) return rc; } while (vreg->last_set_uV != vreg->uV); if (pwm_required) { /* Wait for mode transition to complete. */ udelay(QPNP_FTS2_MODE_CHANGE_DELAY - QPNP_SPMI_WRITE_MIN_DELAY); /* Switch to AUTO mode so that power consumption is lowered. */ rc = qpnp_smps_set_mode(vreg, QPNP_SMPS_MODE_AUTO); if (rc) return rc; } rc = spm_regulator_recalibrate(vreg); return rc; }
static int spm_regulator_set_mode(struct regulator_dev *rdev, unsigned int mode) { struct spm_vreg *vreg = rdev_get_drvdata(rdev); /* * Map REGULATOR_MODE_NORMAL to PWM mode and REGULATOR_MODE_IDLE to * init_mode. This ensures that the regulator always stays in PWM mode * in the case that qcom,mode has been specified as "pwm" in device * tree. */ vreg->mode = mode == REGULATOR_MODE_NORMAL ? QPNP_SMPS_MODE_PWM : vreg->init_mode; return qpnp_smps_set_mode(vreg, vreg->mode); }
static int _spm_regulator_set_voltage(struct regulator_dev *rdev) { struct spm_vreg *vreg = rdev_get_drvdata(rdev); bool spm_failed = false; int rc = 0; u8 reg; if (vreg->vlevel == vreg->last_set_vlevel) return 0; if ((vreg->regulator_type == QPNP_TYPE_FTS2) && !(vreg->init_mode & QPNP_SMPS_MODE_PWM) && vreg->uV > vreg->last_set_uV) { /* Switch to PWM mode so that voltage ramping is fast. */ rc = qpnp_smps_set_mode(vreg, QPNP_SMPS_MODE_PWM); if (rc) return rc; } if (likely(!vreg->bypass_spm)) { /* Set voltage control register via SPM. */ rc = msm_spm_set_vdd(vreg->cpu_num, vreg->vlevel); if (rc) { pr_debug("%s: msm_spm_set_vdd failed, rc=%d; falling back on SPMI write\n", vreg->rdesc.name, rc); spm_failed = true; } } if (unlikely(vreg->bypass_spm || spm_failed)) { /* Set voltage control register via SPMI. */ reg = vreg->vlevel; rc = spmi_ext_register_writel(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid, vreg->spmi_base_addr + QPNP_SMPS_REG_VOLTAGE_SETPOINT, ®, 1); if (rc) { pr_err("%s: spmi_ext_register_writel failed, rc=%d\n", vreg->rdesc.name, rc); return rc; } } if (vreg->uV > vreg->last_set_uV) { /* Wait for voltage stepping to complete. */ udelay(DIV_ROUND_UP(vreg->uV - vreg->last_set_uV, vreg->step_rate)); } if ((vreg->regulator_type == QPNP_TYPE_FTS2) && !(vreg->init_mode & QPNP_SMPS_MODE_PWM) && vreg->uV > vreg->last_set_uV) { /* Wait for mode transition to complete. */ udelay(QPNP_FTS2_MODE_CHANGE_DELAY - QPNP_SPMI_WRITE_MIN_DELAY); /* Switch to AUTO mode so that power consumption is lowered. */ rc = qpnp_smps_set_mode(vreg, QPNP_FTS2_MODE_AUTO); if (rc) return rc; } vreg->last_set_uV = vreg->uV; vreg->last_set_vlevel = vreg->vlevel; return rc; }