regulator: qpnp-lcdb: Add headroom voltage for boost

Increase the boost headroom to 200mV. Also add a device tree
property to make the headroom configurable.

Change-Id: Ibc932f191e64824ba948153a7ae80f109ffcdff9
Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
This commit is contained in:
Kiran Gunda 2017-08-08 16:58:47 +05:30
parent 0d2bf7e895
commit 9d2a24f8e5
2 changed files with 58 additions and 29 deletions

View file

@ -209,6 +209,12 @@ Properties below are specific to BOOST subnode only.
Definition: Current limit (in mA) of the BOOST rail.
Possible values are 200 to 1600mA in 200mA steps.
- qcom,bst-headroom-mv
Usage: optional
Value type: <u16>
Definition: Headroom of the boost (in mV). The minimum headroom is
200mV and if not specified defaults to 200mV.
=======
Example
=======
@ -250,5 +256,6 @@ pm660l_lcdb: qpnp-lcdb@ec00 {
qcom,bst-pd-strength = <1>;
qcom,bst-ps = <1>;
qcom,bst-ps-threshold-ma = <50>;
qcom,bst-headroom-mv = <200>;
};
};

View file

@ -147,6 +147,8 @@
#define MIN_SOFT_START_US 0
#define MAX_SOFT_START_US 2000
#define BST_HEADROOM_DEFAULT_MV 200
struct ldo_regulator {
struct regulator_desc rdesc;
struct regulator_dev *rdev;
@ -187,6 +189,7 @@ struct bst_params {
int soft_start_us;
int vreg_ok_dbc_us;
int voltage_mv;
u16 headroom_mv;
};
struct qpnp_lcdb {
@ -853,28 +856,40 @@ irq_handled:
#define VOLTAGE_STEP_50_MV 50
#define VOLTAGE_STEP_50MV_OFFSET 0xA
static int qpnp_lcdb_set_bst_voltage(struct qpnp_lcdb *lcdb,
int voltage_mv)
int voltage_mv, u8 type)
{
int rc = 0;
u8 val = 0;
int bst_voltage_mv;
struct ldo_regulator *ldo = &lcdb->ldo;
struct ncp_regulator *ncp = &lcdb->ncp;
struct bst_params *bst = &lcdb->bst;
if (voltage_mv < MIN_BST_VOLTAGE_MV)
voltage_mv = MIN_BST_VOLTAGE_MV;
else if (voltage_mv > MAX_BST_VOLTAGE_MV)
voltage_mv = MAX_BST_VOLTAGE_MV;
/* Vout_Boost = headroom_mv + max( Vout_LDO, abs (Vout_NCP)) */
bst_voltage_mv = max(voltage_mv, max(ldo->voltage_mv, ncp->voltage_mv));
bst_voltage_mv += bst->headroom_mv;
val = DIV_ROUND_UP(voltage_mv - MIN_BST_VOLTAGE_MV,
VOLTAGE_STEP_50_MV);
if (bst_voltage_mv < MIN_BST_VOLTAGE_MV)
bst_voltage_mv = MIN_BST_VOLTAGE_MV;
else if (bst_voltage_mv > MAX_BST_VOLTAGE_MV)
bst_voltage_mv = MAX_BST_VOLTAGE_MV;
rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
LCDB_BST_OUTPUT_VOLTAGE_REG,
SET_OUTPUT_VOLTAGE_MASK, val);
if (rc < 0)
pr_err("Failed to set boost voltage %d mv rc=%d\n",
voltage_mv, rc);
else
pr_debug("Boost voltage set = %d mv (0x%02x = 0x%02x)\n",
voltage_mv, LCDB_BST_OUTPUT_VOLTAGE_REG, val);
if (bst_voltage_mv != bst->voltage_mv) {
val = DIV_ROUND_UP(bst_voltage_mv - MIN_BST_VOLTAGE_MV,
VOLTAGE_STEP_50_MV);
rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
LCDB_BST_OUTPUT_VOLTAGE_REG,
SET_OUTPUT_VOLTAGE_MASK, val);
if (rc < 0) {
pr_err("Failed to set boost voltage %d mv rc=%d\n",
bst_voltage_mv, rc);
} else {
pr_debug("Boost voltage set = %d mv (0x%02x = 0x%02x)\n",
bst_voltage_mv, LCDB_BST_OUTPUT_VOLTAGE_REG, val);
bst->voltage_mv = bst_voltage_mv;
}
}
return rc;
}
@ -905,25 +920,16 @@ static int qpnp_lcdb_set_voltage(struct qpnp_lcdb *lcdb,
u16 offset = LCDB_LDO_OUTPUT_VOLTAGE_REG;
u8 val = 0;
if (type == BST)
return qpnp_lcdb_set_bst_voltage(lcdb, voltage_mv);
if (type == NCP)
offset = LCDB_NCP_OUTPUT_VOLTAGE_REG;
if (!is_between(voltage_mv, MIN_VOLTAGE_MV, MAX_VOLTAGE_MV)) {
pr_err("Invalid voltage %dmv (min=%d max=%d)\n",
voltage_mv, MIN_VOLTAGE_MV, MAX_VOLTAGE_MV);
return -EINVAL;
}
/* Change the BST voltage to LDO + 100mV */
if (type == LDO) {
rc = qpnp_lcdb_set_bst_voltage(lcdb, voltage_mv + 100);
if (rc < 0) {
pr_err("Failed to set boost voltage rc=%d\n", rc);
return rc;
}
rc = qpnp_lcdb_set_bst_voltage(lcdb, voltage_mv, type);
if (rc < 0) {
pr_err("Failed to set boost voltage rc=%d\n", rc);
return rc;
}
/* Below logic is only valid for LDO and NCP type */
@ -936,6 +942,9 @@ static int qpnp_lcdb_set_voltage(struct qpnp_lcdb *lcdb,
val += VOLTAGE_STEP_50MV_OFFSET;
}
if (type == NCP)
offset = LCDB_NCP_OUTPUT_VOLTAGE_REG;
rc = qpnp_lcdb_masked_write(lcdb, lcdb->base + offset,
SET_OUTPUT_VOLTAGE_MASK, val);
if (rc < 0)
@ -1058,6 +1067,8 @@ static int qpnp_lcdb_ldo_regulator_set_voltage(struct regulator_dev *rdev,
rc = qpnp_lcdb_set_voltage(lcdb, min_uV / 1000, LDO);
if (rc < 0)
pr_err("Failed to set LDO voltage rc=%c\n", rc);
else
lcdb->ldo.voltage_mv = min_uV / 1000;
return rc;
}
@ -1129,6 +1140,8 @@ static int qpnp_lcdb_ncp_regulator_set_voltage(struct regulator_dev *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);
else
lcdb->ncp.voltage_mv = min_uV / 1000;
return rc;
}
@ -1389,6 +1402,12 @@ static int qpnp_lcdb_bst_dt_init(struct qpnp_lcdb *lcdb)
return -EINVAL;
}
/* Boost head room configuration */
of_property_read_u16(node, "qcom,bst-headroom-mv",
&lcdb->bst.headroom_mv);
if (lcdb->bst.headroom_mv < BST_HEADROOM_DEFAULT_MV)
lcdb->bst.headroom_mv = BST_HEADROOM_DEFAULT_MV;
return 0;
}
@ -1695,6 +1714,9 @@ static int qpnp_lcdb_init_bst(struct qpnp_lcdb *lcdb)
}
lcdb->bst.soft_start_us = (val & SOFT_START_MASK) * 200 + 200;
if (!lcdb->bst.headroom_mv)
lcdb->bst.headroom_mv = BST_HEADROOM_DEFAULT_MV;
return 0;
}