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

Commit b5698bd3 authored by Tirupathi Reddy's avatar Tirupathi Reddy
Browse files

regulator: spm-regulator: Add support for FTS426 type regulators



Add support for PMIC FTSMPS 426 type regulators.  These have a
4 mV step size and a voltage control scheme consisting of two
8-bit registers defining a 16-bit voltage set point in units of
millivolts.

CRs-Fixed: 2037603
Change-Id: Ide54c8c9dd8113ab4588979ec97915403b3ecab1
Signed-off-by: default avatarTirupathi Reddy <tirupath@codeaurora.org>
parent 04d53e49
Loading
Loading
Loading
Loading
+110 −30
Original line number Diff line number Diff line
/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -47,6 +47,7 @@ enum qpnp_regulator_uniq_type {
	QPNP_TYPE_HF,
	QPNP_TYPE_FTS2,
	QPNP_TYPE_FTS2p5,
	QPNP_TYPE_FTS426,
	QPNP_TYPE_ULT_HF,
};

@@ -54,6 +55,7 @@ enum qpnp_regulator_type {
	QPNP_HF_TYPE		= 0x03,
	QPNP_FTS2_TYPE		= 0x1C,
	QPNP_FTS2p5_TYPE	= 0x1C,
	QPNP_FTS426_TYPE	= 0x1C,
	QPNP_ULT_HF_TYPE	= 0x22,
};

@@ -61,6 +63,7 @@ enum qpnp_regulator_subtype {
	QPNP_FTS2_SUBTYPE	= 0x08,
	QPNP_HF_SUBTYPE		= 0x08,
	QPNP_FTS2p5_SUBTYPE	= 0x09,
	QPNP_FTS426_SUBTYPE	= 0x0A,
	QPNP_ULT_HF_SUBTYPE	= 0x0D,
};

@@ -70,6 +73,7 @@ static const struct voltage_range fts2p5_range0
					 = { 80000, 350000, 1355000,  5000};
static const struct voltage_range fts2p5_range1
					 = {160000, 700000, 2200000, 10000};
static const struct voltage_range fts426_range = {0, 320000, 1352000, 4000};
static const struct voltage_range ult_hf_range0 = {375000, 375000, 1562500,
								12500};
static const struct voltage_range ult_hf_range1 = {750000, 750000, 1525000,
@@ -85,6 +89,12 @@ static const struct voltage_range hf_range1 = {1550000, 1550000, 3125000,
#define QPNP_SMPS_REG_MODE		0x45
#define QPNP_SMPS_REG_STEP_CTRL		0x61

/* FTS426 voltage control registers */
#define QPNP_FTS426_REG_VOLTAGE_LB		0x40
#define QPNP_FTS426_REG_VOLTAGE_UB		0x41
#define QPNP_FTS426_REG_VOLTAGE_VALID_LB	0x42
#define QPNP_FTS426_REG_VOLTAGE_VALID_UB	0x43

#define QPNP_SMPS_MODE_PWM		0x80
#define QPNP_SMPS_MODE_AUTO		0x40

@@ -92,9 +102,12 @@ static const struct voltage_range hf_range1 = {1550000, 1550000, 3125000,
#define QPNP_SMPS_STEP_CTRL_STEP_SHIFT	3
#define QPNP_SMPS_STEP_CTRL_DELAY_MASK	0x07
#define QPNP_SMPS_STEP_CTRL_DELAY_SHIFT	0
#define QPNP_FTS426_STEP_CTRL_DELAY_MASK	0x03
#define QPNP_FTS426_STEP_CTRL_DELAY_SHIFT	0

/* Clock rate in kHz of the FTS2 regulator reference clock. */
#define QPNP_SMPS_CLOCK_RATE		19200
#define QPNP_FTS426_CLOCK_RATE		4800

/* Time to delay in us to ensure that a mode change has completed. */
#define QPNP_FTS2_MODE_CHANGE_DELAY	50
@@ -105,6 +118,7 @@ static const struct voltage_range hf_range1 = {1550000, 1550000, 3125000,
/* Minimum voltage stepper delay for each step. */
#define QPNP_FTS2_STEP_DELAY		8
#define QPNP_HF_STEP_DELAY		20
#define QPNP_FTS426_STEP_DELAY		2

/* Arbitrarily large max step size used to avoid possible numerical overflow */
#define SPM_REGULATOR_MAX_STEP_UV	10000000
@@ -115,6 +129,8 @@ static const struct voltage_range hf_range1 = {1550000, 1550000, 3125000,
 */
#define QPNP_FTS2_STEP_MARGIN_NUM	4
#define QPNP_FTS2_STEP_MARGIN_DEN	5
#define QPNP_FTS426_STEP_MARGIN_NUM	10
#define QPNP_FTS426_STEP_MARGIN_DEN	11

/*
 * Settling delay for FTS2.5
@@ -160,6 +176,9 @@ static int spm_regulator_uv_to_vlevel(struct spm_vreg *vreg, int uV)
{
	int vlevel;

	if (vreg->regulator_type == QPNP_TYPE_FTS426)
		return roundup(uV, vreg->range->step_uV) / 1000;

	vlevel = DIV_ROUND_UP(uV - vreg->range->min_uV, vreg->range->step_uV);

	/* Fix VSET for ULT HF Buck */
@@ -174,6 +193,8 @@ static int spm_regulator_uv_to_vlevel(struct spm_vreg *vreg, int uV)

static int spm_regulator_vlevel_to_uv(struct spm_vreg *vreg, int vlevel)
{
	if (vreg->regulator_type == QPNP_TYPE_FTS426)
		return vlevel * 1000;
	/*
	 * Calculate ULT HF buck VSET based on range:
	 * In case of range 0: VSET is a 7 bit value.
@@ -201,19 +222,63 @@ static unsigned spm_regulator_vlevel_to_selector(struct spm_vreg *vreg,
static int qpnp_smps_read_voltage(struct spm_vreg *vreg)
{
	int rc;
	u8 reg = 0;
	u8 reg[2] = {0,};

	rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
		vreg->spmi_base_addr + QPNP_SMPS_REG_VOLTAGE_SETPOINT, &reg, 1);
	if (vreg->regulator_type == QPNP_TYPE_FTS426) {
		rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl,
					vreg->spmi_dev->sid,
			vreg->spmi_base_addr + QPNP_FTS426_REG_VOLTAGE_VALID_LB,
					reg, 2);
		if (rc) {
		dev_err(&vreg->spmi_dev->dev, "%s: could not read voltage setpoint register, rc=%d\n",
			dev_err(&vreg->spmi_dev->dev,
				"%s: could not read voltage setpoint registers, rc=%d\n",
				__func__, rc);
			return rc;
		}

	vreg->last_set_vlevel = reg;
	vreg->last_set_uV = spm_regulator_vlevel_to_uv(vreg, reg);
		vreg->last_set_vlevel = (reg[1] << 8) | reg[0];
	} else {
		rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl,
					vreg->spmi_dev->sid,
			vreg->spmi_base_addr + QPNP_SMPS_REG_VOLTAGE_SETPOINT,
					reg, 1);
		if (rc) {
			dev_err(&vreg->spmi_dev->dev,
				"%s: could not read voltage setpoint register, rc=%d\n",
				__func__, rc);
			return rc;
		}
		vreg->last_set_vlevel = reg[0];
	}

	vreg->last_set_uV = spm_regulator_vlevel_to_uv(vreg,
						vreg->last_set_vlevel);
	return rc;
}

static int qpnp_smps_write_voltage(struct spm_vreg *vreg, unsigned vlevel)
{
	int rc = 0;
	u8 reg[2];

	/* Set voltage control registers via SPMI. */
	reg[0] = vlevel & 0xFF;
	reg[1] = (vlevel >> 8) & 0xFF;

	if (vreg->regulator_type == QPNP_TYPE_FTS426) {
		rc = spmi_ext_register_writel(vreg->spmi_dev->ctrl,
					vreg->spmi_dev->sid,
			vreg->spmi_base_addr + QPNP_FTS426_REG_VOLTAGE_LB,
					reg, 2);
	} else {
		rc = spmi_ext_register_writel(vreg->spmi_dev->ctrl,
					vreg->spmi_dev->sid,
			vreg->spmi_base_addr + QPNP_SMPS_REG_VOLTAGE_SETPOINT,
					reg, 1);
	}
	if (rc)
		pr_err("%s: spmi_ext_register_writel failed, rc=%d\n",
			vreg->rdesc.name, rc);
	return rc;
}

@@ -267,7 +332,6 @@ static int spm_regulator_write_voltage(struct spm_vreg *vreg, int uV)
	bool spm_failed = false;
	int rc = 0;
	u32 slew_delay;
	u8 reg;

	if (likely(!vreg->bypass_spm)) {
		/* Set voltage control register via SPM. */
@@ -280,14 +344,9 @@ static int spm_regulator_write_voltage(struct spm_vreg *vreg, int uV)
	}

	if (unlikely(vreg->bypass_spm || spm_failed)) {
		/* Set voltage control register via SPMI. */
		reg = vlevel;
		rc = spmi_ext_register_writel(vreg->spmi_dev->ctrl,
			vreg->spmi_dev->sid,
			vreg->spmi_base_addr + QPNP_SMPS_REG_VOLTAGE_SETPOINT,
			&reg, 1);
		rc = qpnp_smps_write_voltage(vreg, vlevel);
		if (rc) {
			pr_err("%s: spmi_ext_register_writel failed, rc=%d\n",
			pr_err("%s: voltage write failed, rc=%d\n",
			       vreg->rdesc.name, rc);
			return rc;
		}
@@ -531,7 +590,7 @@ static int spm_regulator_avs_set_voltage(struct regulator_dev *rdev, int min_uV,
		return -EINVAL;
	}

	vlevel_max = (uV - range->min_uV) / range->step_uV;
	vlevel_max = spm_regulator_uv_to_vlevel(vreg, uV);
	avs_max_uV = spm_regulator_vlevel_to_uv(vreg, vlevel_max);

	if (avs_max_uV < min_uV) {
@@ -636,6 +695,9 @@ static int qpnp_smps_check_type(struct spm_vreg *vreg)
	} else if (type[0] == QPNP_FTS2p5_TYPE
					&& type[1] == QPNP_FTS2p5_SUBTYPE) {
		vreg->regulator_type = QPNP_TYPE_FTS2p5;
	} else if (type[0] == QPNP_FTS426_TYPE
					&& type[1] == QPNP_FTS426_SUBTYPE) {
		vreg->regulator_type = QPNP_TYPE_FTS426;
	} else if (type[0] == QPNP_ULT_HF_TYPE
					&& type[1] == QPNP_ULT_HF_SUBTYPE) {
		vreg->regulator_type = QPNP_TYPE_ULT_HF;
@@ -776,24 +838,39 @@ static int qpnp_smps_init_step_rate(struct spm_vreg *vreg)
		return rc;
	}

	/* ULT buck does not support steps */
	if (vreg->regulator_type != QPNP_TYPE_ULT_HF)
	/* ULT and FTS426 bucks do not support steps */
	if (vreg->regulator_type != QPNP_TYPE_ULT_HF
		&& vreg->regulator_type != QPNP_TYPE_FTS426)
		step = (reg & QPNP_SMPS_STEP_CTRL_STEP_MASK)
			>> QPNP_SMPS_STEP_CTRL_STEP_SHIFT;

	if (vreg->regulator_type == QPNP_TYPE_FTS426) {
		delay = (reg & QPNP_FTS426_STEP_CTRL_DELAY_MASK)
			>> QPNP_FTS426_STEP_CTRL_DELAY_SHIFT;

		/* step_rate has units of uV/us. */
		vreg->step_rate = QPNP_FTS426_CLOCK_RATE * vreg->range->step_uV;
	} else {
		delay = (reg & QPNP_SMPS_STEP_CTRL_DELAY_MASK)
			>> QPNP_SMPS_STEP_CTRL_DELAY_SHIFT;

		/* step_rate has units of uV/us. */
		vreg->step_rate = QPNP_SMPS_CLOCK_RATE * vreg->range->step_uV
					* (1 << step);
	}

	if ((vreg->regulator_type == QPNP_TYPE_ULT_HF)
			|| (vreg->regulator_type == QPNP_TYPE_HF))
		vreg->step_rate /= 1000 * (QPNP_HF_STEP_DELAY << delay);
	else if (vreg->regulator_type == QPNP_TYPE_FTS426)
		vreg->step_rate /= 1000 * (QPNP_FTS426_STEP_DELAY << delay);
	else
		vreg->step_rate /= 1000 * (QPNP_FTS2_STEP_DELAY << delay);

	if (vreg->regulator_type == QPNP_TYPE_FTS426)
		vreg->step_rate = vreg->step_rate * QPNP_FTS426_STEP_MARGIN_NUM
					/ QPNP_FTS426_STEP_MARGIN_DEN;
	else
		vreg->step_rate = vreg->step_rate * QPNP_FTS2_STEP_MARGIN_NUM
					/ QPNP_FTS2_STEP_MARGIN_DEN;

@@ -806,7 +883,8 @@ static int qpnp_smps_init_step_rate(struct spm_vreg *vreg)
static bool spm_regulator_using_range0(struct spm_vreg *vreg)
{
	return vreg->range == &fts2_range0 || vreg->range == &fts2p5_range0
		|| vreg->range == &ult_hf_range0 || vreg->range == &hf_range0;
		|| vreg->range == &ult_hf_range0 || vreg->range == &hf_range0
		|| vreg->range == &fts426_range;
}

/* Register a regulator to enable/disable AVS and set AVS min/max limits. */
@@ -937,6 +1015,8 @@ static int spm_regulator_probe(struct spmi_device *spmi)
		rc = qpnp_smps_init_range(vreg, &fts2_range0, &fts2_range1);
	else if (vreg->regulator_type == QPNP_TYPE_FTS2p5)
		rc = qpnp_smps_init_range(vreg, &fts2p5_range0, &fts2p5_range1);
	else if (vreg->regulator_type == QPNP_TYPE_FTS426)
		vreg->range = &fts426_range;
	else if (vreg->regulator_type == QPNP_TYPE_HF)
		rc = qpnp_smps_init_range(vreg, &hf_range0, &hf_range1);
	else if (vreg->regulator_type == QPNP_TYPE_ULT_HF)