regulator: qpnp-lcdb: Add support for voltage step programming

LCDB peripheral on certain PMICs requires the voltage programming
in 500 mV steps. Add the support for the same.

Change-Id: I42f95edad0e1c6b0b87fbdceeab1c1ff9eeecb4a
Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
This commit is contained in:
Kiran Gunda 2018-09-10 18:04:43 +05:30
parent 8d29642673
commit 6e523d9f8b
2 changed files with 124 additions and 6 deletions

View File

@ -31,6 +31,14 @@ First Level Node - LCDB module
Value type: <phandle>
Definition: Phandle to the PMIC's revid node
- qcom,voltage-step-ramp
Usage: optional
Value type: <bool>
Definition: Required only if the voltage needs to be set in the
steps of 500 mV starting from the 4500 mV. This needs
to be enabled only on platforms where voltage needs to
be ramped up with multiple steps.
Touch-to-wake (TTW) properties:
TTW supports 2 modes of operation - HW and SW. In the HW mode the enable/disable

View File

@ -181,6 +181,7 @@ struct ldo_regulator {
int soft_start_us;
int vreg_ok_dbc_us;
int voltage_mv;
int prev_voltage_mv;
};
struct ncp_regulator {
@ -195,6 +196,7 @@ struct ncp_regulator {
int soft_start_us;
int vreg_ok_dbc_us;
int voltage_mv;
int prev_voltage_mv;
};
struct bst_params {
@ -228,6 +230,7 @@ struct qpnp_lcdb {
bool lcdb_enabled;
bool settings_saved;
bool lcdb_sc_disable;
bool voltage_step_ramp;
int sc_count;
ktime_t sc_module_enable_time;
@ -249,6 +252,7 @@ enum lcdb_module {
LDO,
NCP,
BST,
LDO_NCP,
};
enum pfm_hysteresis {
@ -316,6 +320,12 @@ static u32 ncp_ilim_ma[] = {
.valid = _valid \
} \
static int qpnp_lcdb_set_voltage_step(struct qpnp_lcdb *lcdb,
int voltage_start_mv, u8 type);
static int qpnp_lcdb_set_voltage(struct qpnp_lcdb *lcdb,
int voltage_mv, u8 type);
static bool is_between(int value, int min, int max)
{
if (value < min || value > max)
@ -781,9 +791,13 @@ static int qpnp_lcdb_enable_wa(struct qpnp_lcdb *lcdb)
return 0;
}
#define VOLTAGE_START_MV 4500
#define VOLTAGE_STEP_MV 500
static int qpnp_lcdb_enable(struct qpnp_lcdb *lcdb)
{
int rc = 0, timeout, delay;
int voltage_mv = VOLTAGE_START_MV;
u8 val = 0;
if (lcdb->lcdb_enabled || lcdb->lcdb_sc_disable) {
@ -806,6 +820,22 @@ static int qpnp_lcdb_enable(struct qpnp_lcdb *lcdb)
return rc;
}
if (lcdb->voltage_step_ramp) {
if (lcdb->ldo.voltage_mv < VOLTAGE_START_MV)
voltage_mv = lcdb->ldo.voltage_mv;
rc = qpnp_lcdb_set_voltage(lcdb, voltage_mv, LDO);
if (rc < 0)
return rc;
if (lcdb->ncp.voltage_mv < VOLTAGE_START_MV)
voltage_mv = lcdb->ncp.voltage_mv;
rc = qpnp_lcdb_set_voltage(lcdb, voltage_mv, NCP);
if (rc < 0)
return rc;
}
val = MODULE_EN_BIT;
rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_ENABLE_CTL1_REG,
&val, 1);
@ -842,6 +872,17 @@ static int qpnp_lcdb_enable(struct qpnp_lcdb *lcdb)
}
lcdb->lcdb_enabled = true;
if (lcdb->voltage_step_ramp) {
usleep_range(10000, 11000);
rc = qpnp_lcdb_set_voltage_step(lcdb,
voltage_mv + VOLTAGE_STEP_MV,
LDO_NCP);
if (rc < 0) {
pr_err("Failed to set LCDB voltage rc=%d\n", rc);
return rc;
}
}
pr_debug("lcdb enabled successfully!\n");
return 0;
@ -1128,6 +1169,56 @@ static int qpnp_lcdb_set_voltage(struct qpnp_lcdb *lcdb,
return rc;
}
static int qpnp_lcdb_set_voltage_step(struct qpnp_lcdb *lcdb,
int voltage_start_mv, u8 type)
{
int i, ldo_voltage, ncp_voltage, voltage, rc = 0;
for (i = voltage_start_mv; i <= (MAX_VOLTAGE_MV + VOLTAGE_STEP_MV);
i += VOLTAGE_STEP_MV) {
ldo_voltage = (lcdb->ldo.voltage_mv < i) ?
lcdb->ldo.voltage_mv : i;
ncp_voltage = (lcdb->ncp.voltage_mv < i) ?
lcdb->ncp.voltage_mv : i;
if (type == LDO_NCP) {
rc = qpnp_lcdb_set_voltage(lcdb, ldo_voltage, LDO);
if (rc < 0)
return rc;
rc = qpnp_lcdb_set_voltage(lcdb, ncp_voltage, NCP);
if (rc < 0)
return rc;
pr_debug(" LDO voltage step %d NCP voltage step %d\n",
ldo_voltage, ncp_voltage);
if ((i >= lcdb->ncp.voltage_mv) &&
(i >= lcdb->ldo.voltage_mv))
break;
} else {
voltage = (type == LDO) ? ldo_voltage : ncp_voltage;
rc = qpnp_lcdb_set_voltage(lcdb, voltage, type);
if (rc < 0)
return rc;
pr_debug("%s voltage step %d\n",
(type == LDO) ? "LDO" : "NCP", voltage);
if ((type == LDO) && (i >= lcdb->ldo.voltage_mv))
break;
if ((type == NCP) && (i >= lcdb->ncp.voltage_mv))
break;
}
usleep_range(1000, 1100);
}
return rc;
}
static int qpnp_lcdb_get_voltage(struct qpnp_lcdb *lcdb,
u32 *voltage_mv, u8 type)
{
@ -1236,11 +1327,17 @@ static int qpnp_lcdb_ldo_regulator_set_voltage(struct regulator_dev *rdev,
int rc = 0;
struct qpnp_lcdb *lcdb = rdev_get_drvdata(rdev);
rc = qpnp_lcdb_set_voltage(lcdb, min_uV / 1000, LDO);
lcdb->ldo.voltage_mv = min_uV / 1000;
if (lcdb->voltage_step_ramp)
rc = qpnp_lcdb_set_voltage_step(lcdb,
lcdb->ldo.prev_voltage_mv + VOLTAGE_STEP_MV, LDO);
else
rc = qpnp_lcdb_set_voltage(lcdb, lcdb->ldo.voltage_mv, LDO);
if (rc < 0)
pr_err("Failed to set LDO voltage rc=%c\n", rc);
else
lcdb->ldo.voltage_mv = min_uV / 1000;
lcdb->ldo.prev_voltage_mv = lcdb->ldo.voltage_mv;
return rc;
}
@ -1309,11 +1406,17 @@ static int qpnp_lcdb_ncp_regulator_set_voltage(struct regulator_dev *rdev,
int rc = 0;
struct qpnp_lcdb *lcdb = rdev_get_drvdata(rdev);
rc = qpnp_lcdb_set_voltage(lcdb, min_uV / 1000, NCP);
if (rc < 0)
pr_err("Failed to set LDO voltage rc=%c\n", rc);
lcdb->ncp.voltage_mv = min_uV / 1000;
if (lcdb->voltage_step_ramp)
rc = qpnp_lcdb_set_voltage_step(lcdb,
lcdb->ncp.prev_voltage_mv + VOLTAGE_STEP_MV, NCP);
else
lcdb->ncp.voltage_mv = min_uV / 1000;
rc = qpnp_lcdb_set_voltage(lcdb, lcdb->ncp.voltage_mv, NCP);
if (rc < 0)
pr_err("Failed to set NCP voltage rc=%c\n", rc);
else
lcdb->ncp.prev_voltage_mv = lcdb->ncp.voltage_mv;
return rc;
}
@ -1675,6 +1778,8 @@ static int qpnp_lcdb_init_ldo(struct qpnp_lcdb *lcdb)
return rc;
}
lcdb->ldo.prev_voltage_mv = lcdb->ldo.voltage_mv;
rc = qpnp_lcdb_read(lcdb, lcdb->base +
LCDB_LDO_VREG_OK_CTL_REG, &val, 1);
if (rc < 0) {
@ -1780,6 +1885,8 @@ static int qpnp_lcdb_init_ncp(struct qpnp_lcdb *lcdb)
return rc;
}
lcdb->ncp.prev_voltage_mv = lcdb->ncp.voltage_mv;
rc = qpnp_lcdb_read(lcdb, lcdb->base +
LCDB_NCP_VREG_OK_CTL_REG, &val, 1);
if (rc < 0) {
@ -2038,6 +2145,9 @@ static int qpnp_lcdb_parse_dt(struct qpnp_lcdb *lcdb)
if (lcdb->sc_irq < 0)
pr_debug("sc irq is not defined\n");
lcdb->voltage_step_ramp =
of_property_read_bool(node, "qcom,voltage-step-ramp");
return rc;
}