Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 019955f7 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "regulator: spm: check min/max voltages against HW configuration"

parents 2bf7a89b 26efcc23
Loading
Loading
Loading
Loading
+106 −0
Original line number Original line Diff line number Diff line
@@ -95,6 +95,7 @@ static const struct voltage_range hf_range1 = {1550000, 1550000, 3125000,
#define QPNP_SMPS_REG_VOLTAGE_SETPOINT	0x41
#define QPNP_SMPS_REG_VOLTAGE_SETPOINT	0x41
#define QPNP_SMPS_REG_MODE		0x45
#define QPNP_SMPS_REG_MODE		0x45
#define QPNP_SMPS_REG_STEP_CTRL		0x61
#define QPNP_SMPS_REG_STEP_CTRL		0x61
#define QPNP_SMPS_REG_UL_LL_CTRL	0x68


/* FTS426 voltage control registers */
/* FTS426 voltage control registers */
#define QPNP_FTS426_REG_VOLTAGE_LB		0x40
#define QPNP_FTS426_REG_VOLTAGE_LB		0x40
@@ -102,6 +103,22 @@ static const struct voltage_range hf_range1 = {1550000, 1550000, 3125000,
#define QPNP_FTS426_REG_VOLTAGE_VALID_LB	0x42
#define QPNP_FTS426_REG_VOLTAGE_VALID_LB	0x42
#define QPNP_FTS426_REG_VOLTAGE_VALID_UB	0x43
#define QPNP_FTS426_REG_VOLTAGE_VALID_UB	0x43


/* HF voltage limit registers */
#define QPNP_HF_REG_VOLTAGE_ULS		0x69
#define QPNP_HF_REG_VOLTAGE_LLS		0x6B

/* FTS voltage limit registers */
#define QPNP_FTS_REG_VOLTAGE_ULS_VALID	0x6A
#define QPNP_FTS_REG_VOLTAGE_LLS_VALID	0x6C

/* FTS426 voltage limit registers */
#define QPNP_FTS426_REG_VOLTAGE_ULS_LB	0x68
#define QPNP_FTS426_REG_VOLTAGE_ULS_UB	0x69

/* Common regulator UL & LL limits control register layout */
#define QPNP_COMMON_UL_EN_MASK		0x80
#define QPNP_COMMON_LL_EN_MASK		0x40

#define QPNP_SMPS_MODE_PWM		0x80
#define QPNP_SMPS_MODE_PWM		0x80
#define QPNP_SMPS_MODE_AUTO		0x40
#define QPNP_SMPS_MODE_AUTO		0x40
#define QPNP_FTS426_MODE_PWM		0x07
#define QPNP_FTS426_MODE_PWM		0x07
@@ -924,6 +941,88 @@ static int qpnp_smps_init_step_rate(struct spm_vreg *vreg)
	return rc;
	return rc;
}
}


static int qpnp_smps_check_constraints(struct spm_vreg *vreg,
					struct regulator_init_data *init_data)
{
	int rc = 0, limit_min_uV, limit_max_uV;
	u16 ul_reg, ll_reg;
	u8 reg[2];

	limit_min_uV = 0;
	limit_max_uV = INT_MAX;

	ul_reg = QPNP_FTS_REG_VOLTAGE_ULS_VALID;
	ll_reg = QPNP_FTS_REG_VOLTAGE_LLS_VALID;

	switch (vreg->regulator_type) {
	case QPNP_TYPE_HF:
		ul_reg = QPNP_HF_REG_VOLTAGE_ULS;
		ll_reg = QPNP_HF_REG_VOLTAGE_LLS;
	case QPNP_TYPE_FTS2:
	case QPNP_TYPE_FTS2p5:
		rc = regmap_bulk_read(vreg->regmap, vreg->spmi_base_addr
					+ QPNP_SMPS_REG_UL_LL_CTRL, reg, 1);
		if (rc) {
			dev_err(&vreg->pdev->dev, "%s: UL_LL register read failed, rc=%d\n",
				__func__, rc);
			return rc;
		}

		if (reg[0] & QPNP_COMMON_UL_EN_MASK) {
			rc = regmap_bulk_read(vreg->regmap, vreg->spmi_base_addr
						+ ul_reg, &reg[1], 1);
			if (rc) {
				dev_err(&vreg->pdev->dev, "%s: ULS register read failed, rc=%d\n",
					__func__, rc);
				return rc;
			}

			limit_max_uV = spm_regulator_vlevel_to_uv(vreg, reg[1]);
		}

		if (reg[0] & QPNP_COMMON_LL_EN_MASK) {
			rc = regmap_bulk_read(vreg->regmap, vreg->spmi_base_addr
						+ ll_reg, &reg[1], 1);
			if (rc) {
				dev_err(&vreg->pdev->dev, "%s: LLS register read failed, rc=%d\n",
					__func__, rc);
				return rc;
			}

			limit_min_uV = spm_regulator_vlevel_to_uv(vreg, reg[1]);
		}

		break;
	case QPNP_TYPE_FTS426:
		rc = regmap_bulk_read(vreg->regmap, vreg->spmi_base_addr
					+ QPNP_FTS426_REG_VOLTAGE_ULS_LB,
					reg, 2);
		if (rc) {
			dev_err(&vreg->pdev->dev, "%s: could not read voltage limit registers, rc=%d\n",
				__func__, rc);
			return rc;
		}

		limit_max_uV = spm_regulator_vlevel_to_uv(vreg,
					((unsigned)reg[1] << 8) | reg[0]);
		break;
	case QPNP_TYPE_ULT_HF:
		/* no HW voltage limit configuration */
		break;
	}

	if (init_data->constraints.min_uV < limit_min_uV
	    || init_data->constraints.max_uV >  limit_max_uV) {
		dev_err(&vreg->pdev->dev, "regulator min/max(%d/%d) constraints do not fit within HW configured min/max(%d/%d) constraints\n",
			init_data->constraints.min_uV,
			init_data->constraints.max_uV, limit_min_uV,
			limit_max_uV);
		return -EINVAL;
	}

	return rc;
}

static bool spm_regulator_using_range0(struct spm_vreg *vreg)
static bool spm_regulator_using_range0(struct spm_vreg *vreg)
{
{
	return vreg->range == &fts2_range0 || vreg->range == &fts2p5_range0
	return vreg->range == &fts2_range0 || vreg->range == &fts2p5_range0
@@ -1105,6 +1204,13 @@ static int spm_regulator_probe(struct platform_device *pdev)
		return -EINVAL;
		return -EINVAL;
	}
	}


	rc = qpnp_smps_check_constraints(vreg, init_data);
	if (rc) {
		dev_err(&pdev->dev, "%s: regulator constraints check failed, rc=%d\n",
			__func__, rc);
		return rc;
	}

	vreg->rdesc.name	= init_data->constraints.name;
	vreg->rdesc.name	= init_data->constraints.name;
	vreg->rdesc.type	= REGULATOR_VOLTAGE;
	vreg->rdesc.type	= REGULATOR_VOLTAGE;
	vreg->rdesc.owner	= THIS_MODULE;
	vreg->rdesc.owner	= THIS_MODULE;