Loading Documentation/devicetree/bindings/regulator/qpnp-lcdb-regulator.txt +7 −0 Original line number Diff line number Diff line Loading @@ -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 ======= Loading Loading @@ -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>; }; }; drivers/regulator/qpnp-lcdb-regulator.c +53 −31 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 { Loading Loading @@ -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; 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; val = DIV_ROUND_UP(voltage_mv - MIN_BST_VOLTAGE_MV, int bst_voltage_mv; struct ldo_regulator *ldo = &lcdb->ldo; struct ncp_regulator *ncp = &lcdb->ncp; struct bst_params *bst = &lcdb->bst; /* 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; 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; 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) if (rc < 0) { pr_err("Failed to set boost voltage %d mv rc=%d\n", voltage_mv, rc); else bst_voltage_mv, rc); } else { pr_debug("Boost voltage set = %d mv (0x%02x = 0x%02x)\n", voltage_mv, LCDB_BST_OUTPUT_VOLTAGE_REG, val); bst_voltage_mv, LCDB_BST_OUTPUT_VOLTAGE_REG, val); bst->voltage_mv = bst_voltage_mv; } } return rc; } Loading Loading @@ -905,26 +920,17 @@ 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); 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 */ if (voltage_mv < VOLTAGE_MIN_STEP_50_MV) { Loading @@ -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) Loading Loading @@ -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; } Loading Loading @@ -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; } Loading Loading @@ -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; } Loading Loading @@ -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; } Loading Loading
Documentation/devicetree/bindings/regulator/qpnp-lcdb-regulator.txt +7 −0 Original line number Diff line number Diff line Loading @@ -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 ======= Loading Loading @@ -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>; }; };
drivers/regulator/qpnp-lcdb-regulator.c +53 −31 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 { Loading Loading @@ -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; 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; val = DIV_ROUND_UP(voltage_mv - MIN_BST_VOLTAGE_MV, int bst_voltage_mv; struct ldo_regulator *ldo = &lcdb->ldo; struct ncp_regulator *ncp = &lcdb->ncp; struct bst_params *bst = &lcdb->bst; /* 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; 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; 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) if (rc < 0) { pr_err("Failed to set boost voltage %d mv rc=%d\n", voltage_mv, rc); else bst_voltage_mv, rc); } else { pr_debug("Boost voltage set = %d mv (0x%02x = 0x%02x)\n", voltage_mv, LCDB_BST_OUTPUT_VOLTAGE_REG, val); bst_voltage_mv, LCDB_BST_OUTPUT_VOLTAGE_REG, val); bst->voltage_mv = bst_voltage_mv; } } return rc; } Loading Loading @@ -905,26 +920,17 @@ 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); 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 */ if (voltage_mv < VOLTAGE_MIN_STEP_50_MV) { Loading @@ -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) Loading Loading @@ -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; } Loading Loading @@ -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; } Loading Loading @@ -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; } Loading Loading @@ -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; } Loading