Merge "power: qpnp-charger: add input current limit options"
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index 03b01ee..a868b75 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -34,6 +34,8 @@
system thermal mitigation level.
Parent node optional properties:
+- qcom,chg-maxinput-usb-ma: Maximum input current USB.
+- qcom,chg-maxinput-dc-ma: Maximum input current DC.
- qcom,chg-charging-disabled: Set this property to disable charging
by default. This can then be overriden
writing the the module parameter
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 3eaf262..e2ba042 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -70,7 +70,7 @@
#define CHGR_CHG_WDOG_PET 0x64
#define CHGR_CHG_WDOG_EN 0x65
#define CHGR_IR_DROP_COMPEN 0x67
-#define CHGR_USB_IUSB_MAX 0x44
+#define CHGR_I_MAX_REG 0x44
#define CHGR_USB_USB_SUSP 0x47
#define CHGR_USB_USB_OTG_CTL 0x48
#define CHGR_USB_ENUM_T_STOP 0x4E
@@ -172,6 +172,8 @@
* @resume_voltage_mv: voltage at which the battery resumes charging
* @term_current: the charging based term current
* @safe_current: battery safety current setting
+ * @maxinput_usb_ma: Maximum Input current USB
+ * @maxinput_dc_ma: Maximum Input current DC
* @revision: PMIC revision
* @thermal_levels amount of thermal mitigation levels
* @thermal_mitigation thermal mitigation level values
@@ -210,6 +212,8 @@
unsigned int min_voltage_mv;
unsigned int resume_voltage_mv;
unsigned int term_current;
+ unsigned int maxinput_usb_ma;
+ unsigned int maxinput_dc_ma;
unsigned int safe_current;
unsigned int revision;
unsigned int thermal_levels;
@@ -348,36 +352,73 @@
return (dcin_valid_rt_sts & DCIN_VALID_IRQ) ? 1 : 0;
}
-#define QPNP_CHG_IUSB_MAX_MIN_100 100
-#define QPNP_CHG_IUSB_MAX_MIN_150 150
-#define QPNP_CHG_IUSB_MAX_MIN_MA 200
-#define QPNP_CHG_IUSB_MAX_MAX_MA 2500
-#define QPNP_CHG_IUSB_MAX_STEP_MA 100
+#define QPNP_CHG_I_MAX_MIN_100 100
+#define QPNP_CHG_I_MAX_MIN_150 150
+#define QPNP_CHG_I_MAX_MIN_MA 200
+#define QPNP_CHG_I_MAX_MAX_MA 2500
+#define QPNP_CHG_I_MAXSTEP_MA 100
+static int
+qpnp_chg_idcmax_set(struct qpnp_chg_chip *chip, int mA)
+{
+ int rc = 0;
+ u8 dc = 0;
+
+ if (mA < QPNP_CHG_I_MAX_MIN_100
+ || mA > QPNP_CHG_I_MAX_MAX_MA) {
+ pr_err("bad mA=%d asked to set\n", mA);
+ return -EINVAL;
+ }
+
+ if (mA == QPNP_CHG_I_MAX_MIN_100) {
+ dc = 0x00;
+ pr_debug("current=%d setting %02x\n", mA, dc);
+ return qpnp_chg_write(chip, &dc,
+ chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
+ } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
+ dc = 0x01;
+ pr_debug("current=%d setting %02x\n", mA, dc);
+ return qpnp_chg_write(chip, &dc,
+ chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
+ }
+
+ dc = mA / QPNP_CHG_I_MAXSTEP_MA;
+
+ pr_debug("current=%d setting 0x%x\n", mA, dc);
+ rc = qpnp_chg_write(chip, &dc,
+ chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
+
+ return rc;
+}
+
static int
qpnp_chg_iusbmax_set(struct qpnp_chg_chip *chip, int mA)
{
int rc = 0;
u8 usb_reg = 0, temp = 8;
- if (mA == QPNP_CHG_IUSB_MAX_MIN_100) {
- usb_reg = 0x00;
- pr_debug("current=%d setting %02x\n", mA, usb_reg);
- return qpnp_chg_write(chip, &usb_reg,
- chip->usb_chgpth_base + CHGR_USB_IUSB_MAX, 1);
- } else if (mA == QPNP_CHG_IUSB_MAX_MIN_150) {
- usb_reg = 0x01;
- pr_debug("current=%d setting %02x\n", mA, usb_reg);
- return qpnp_chg_write(chip, &usb_reg,
- chip->usb_chgpth_base + CHGR_USB_IUSB_MAX, 1);
- }
-
- if (mA < QPNP_CHG_IUSB_MAX_MIN_MA
- || mA > QPNP_CHG_IUSB_MAX_MAX_MA) {
+ if (mA < QPNP_CHG_I_MAX_MIN_100
+ || mA > QPNP_CHG_I_MAX_MAX_MA) {
pr_err("bad mA=%d asked to set\n", mA);
return -EINVAL;
}
- usb_reg = mA / QPNP_CHG_IUSB_MAX_STEP_MA;
+ if (mA == QPNP_CHG_I_MAX_MIN_100) {
+ usb_reg = 0x00;
+ pr_debug("current=%d setting %02x\n", mA, usb_reg);
+ return qpnp_chg_write(chip, &usb_reg,
+ chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
+ } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
+ usb_reg = 0x01;
+ pr_debug("current=%d setting %02x\n", mA, usb_reg);
+ return qpnp_chg_write(chip, &usb_reg,
+ chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
+ }
+
+ /* Impose input current limit */
+ if (chip->maxinput_usb_ma)
+ mA = (chip->maxinput_usb_ma) <= mA ? chip->maxinput_usb_ma : mA;
+
+ usb_reg = mA / QPNP_CHG_I_MAXSTEP_MA;
if (chip->flags & CHG_FLAGS_VCP_WA) {
temp = 0xA5;
@@ -390,7 +431,7 @@
pr_debug("current=%d setting 0x%x\n", mA, usb_reg);
rc = qpnp_chg_write(chip, &usb_reg,
- chip->usb_chgpth_base + CHGR_USB_IUSB_MAX, 1);
+ chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
if (chip->flags & CHG_FLAGS_VCP_WA) {
temp = 0xA5;
@@ -875,12 +916,12 @@
chip->usb_psy->get_property(chip->usb_psy,
POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
- if ((ret.intval / 1000) <= QPNP_CHG_IUSB_MAX_MIN_MA)
+ if ((ret.intval / 1000) <= QPNP_CHG_I_MAX_MIN_MA)
qpnp_chg_usb_suspend_enable(chip, 1);
else
qpnp_chg_usb_suspend_enable(chip, 0);
} else {
- qpnp_chg_iusbmax_set(chip, QPNP_CHG_IUSB_MAX_MIN_100);
+ qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
qpnp_chg_usb_suspend_enable(chip, 0);
}
@@ -1429,6 +1470,33 @@
goto fail_chg_enable;
}
+ /* Get the ibatsafe property */
+ rc = of_property_read_u32(spmi->dev.of_node,
+ "qcom,chg-vbatdet-mv",
+ &chip->resume_voltage_mv);
+ if (rc) {
+ pr_err("Error reading vbatdet property %d\n", rc);
+ goto fail_chg_enable;
+ }
+
+ /* Get the maxinput-dc-ma property */
+ rc = of_property_read_u32(spmi->dev.of_node,
+ "qcom,chg-maxinput-dc-ma",
+ &chip->maxinput_dc_ma);
+ if (rc && rc != -EINVAL) {
+ pr_err("Error reading maxinput-dc-ma property %d\n", rc);
+ goto fail_chg_enable;
+ }
+
+ /* Get the maxinput-usb-ma property */
+ rc = of_property_read_u32(spmi->dev.of_node,
+ "qcom,chg-maxinput-usb-ma",
+ &chip->maxinput_usb_ma);
+ if (rc && rc != -EINVAL) {
+ pr_err("Error reading maxinput-usb-ma property %d\n", rc);
+ goto fail_chg_enable;
+ }
+
/* Get the charging-disabled property */
chip->charging_disabled = of_property_read_bool(spmi->dev.of_node,
"qcom,chg-charging-disabled");
@@ -1596,6 +1664,14 @@
power_supply_set_present(chip->usb_psy,
qpnp_chg_is_usb_chg_plugged_in(chip));
+ if (chip->maxinput_dc_ma) {
+ rc = qpnp_chg_idcmax_set(chip, chip->maxinput_dc_ma);
+ if (rc) {
+ pr_err("Error setting idcmax property %d\n", rc);
+ goto fail_chg_enable;
+ }
+ }
+
qpnp_chg_charge_en(chip, !chip->charging_disabled);
qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);