Merge "power: qpnp-charger: add OCP support for SMBBP/SMBCL"
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index 3150bbf..d0f4313 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -103,6 +103,7 @@
qcom,usb-chgpth:
- usbin-valid
+ - usb-ocp (only for SMBBP and SMBCL)
qcom,chgr:
- chg-done
@@ -149,6 +150,9 @@
- coarse-det-usb: Coarse detect interrupt triggers
at low voltage on USB_IN.
- chg-gone: Triggers on VCHG line.
+ - usb-ocp Triggers on over current conditions when
+ reverse boosting. (Only available on
+ SMBCL and SMBBP devices).
qcom,dc-chgpth:
- dcin-valid: Indicates a valid DC charger
diff --git a/arch/arm/boot/dts/msm-pm8110.dtsi b/arch/arm/boot/dts/msm-pm8110.dtsi
index 3c17655..187599f 100644
--- a/arch/arm/boot/dts/msm-pm8110.dtsi
+++ b/arch/arm/boot/dts/msm-pm8110.dtsi
@@ -133,11 +133,13 @@
reg = <0x1300 0x100>;
interrupts = <0 0x13 0x0>,
<0 0x13 0x1>,
- <0x0 0x13 0x2>;
+ <0x0 0x13 0x2>,
+ <0x0 0x13 0x3>;
interrupt-names = "coarse-det-usb",
"usbin-valid",
- "chg-gone";
+ "chg-gone",
+ "usb-ocp";
};
qcom,chg-misc@1600 {
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index e3daf6c..91e4321 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -149,11 +149,13 @@
reg = <0x1300 0x100>;
interrupts = <0 0x13 0x0>,
<0 0x13 0x1>,
- <0x0 0x13 0x2>;
+ <0x0 0x13 0x2>,
+ <0x0 0x13 0x3>;
interrupt-names = "coarse-det-usb",
"usbin-valid",
- "chg-gone";
+ "chg-gone",
+ "usb-ocp";
};
pm8226_chg_boost: qcom,boost@1500 {
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index c023a6d..9cdb8ca 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -100,6 +100,8 @@
#define BOOST_ENABLE_CONTROL 0x46
#define COMP_OVR1 0xEA
#define BAT_IF_BTC_CTRL 0x49
+#define USB_OCP_THR 0x52
+#define USB_OCP_CLR 0x53
#define REG_OFFSET_PERP_SUBTYPE 0x05
@@ -142,6 +144,11 @@
#define BAT_THM_EN BIT(1)
#define BAT_ID_EN BIT(0)
#define BOOST_PWR_EN BIT(7)
+#define OCP_CLR_BIT BIT(7)
+#define OCP_THR_MASK 0x03
+#define OCP_THR_900_MA 0x02
+#define OCP_THR_500_MA 0x01
+#define OCP_THR_200_MA 0x00
/* Interrupt definitions */
/* smbb_chg_interrupts */
@@ -267,6 +274,7 @@
u16 misc_base;
u16 freq_base;
struct qpnp_chg_irq usbin_valid;
+ struct qpnp_chg_irq usb_ocp;
struct qpnp_chg_irq dcin_valid;
struct qpnp_chg_irq chg_gone;
struct qpnp_chg_irq chg_fastchg;
@@ -982,6 +990,32 @@
return IRQ_HANDLED;
}
+static irqreturn_t
+qpnp_chg_usb_usb_ocp_irq_handler(int irq, void *_chip)
+{
+ struct qpnp_chg_chip *chip = _chip;
+ int rc;
+
+ pr_debug("usb-ocp triggered\n");
+
+ rc = qpnp_chg_masked_write(chip,
+ chip->usb_chgpth_base + USB_OCP_CLR,
+ OCP_CLR_BIT,
+ OCP_CLR_BIT, 1);
+ if (rc)
+ pr_err("Failed to clear OCP bit rc = %d\n", rc);
+
+ /* force usb ovp fet off */
+ rc = qpnp_chg_masked_write(chip,
+ chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
+ USB_OTG_EN_BIT,
+ USB_OTG_EN_BIT, 1);
+ if (rc)
+ pr_err("Failed to turn off usb ovp rc = %d\n", rc);
+
+ return IRQ_HANDLED;
+}
+
#define ENUM_T_STOP_BIT BIT(0)
static irqreturn_t
qpnp_chg_usb_usbin_valid_irq_handler(int irq, void *_chip)
@@ -2631,6 +2665,27 @@
return rc;
}
+ if ((subtype == SMBBP_USB_CHGPTH_SUBTYPE) ||
+ (subtype == SMBCL_USB_CHGPTH_SUBTYPE)) {
+ chip->usb_ocp.irq = spmi_get_irq_byname(spmi,
+ spmi_resource, "usb-ocp");
+ if (chip->usb_ocp.irq < 0) {
+ pr_err("Unable to get usbin irq\n");
+ return rc;
+ }
+ rc = devm_request_irq(chip->dev,
+ chip->usb_ocp.irq,
+ qpnp_chg_usb_usb_ocp_irq_handler,
+ IRQF_TRIGGER_RISING, "usb-ocp", chip);
+ if (rc < 0) {
+ pr_err("Can't request %d usb-ocp: %d\n",
+ chip->usb_ocp.irq, rc);
+ return rc;
+ }
+
+ enable_irq_wake(chip->usb_ocp.irq);
+ }
+
enable_irq_wake(chip->usbin_valid.irq);
enable_irq_wake(chip->chg_gone.irq);
break;
@@ -2882,6 +2937,16 @@
0xFF,
0x80, 1);
+ if ((subtype == SMBBP_USB_CHGPTH_SUBTYPE) ||
+ (subtype == SMBCL_USB_CHGPTH_SUBTYPE)) {
+ rc = qpnp_chg_masked_write(chip,
+ chip->usb_chgpth_base + USB_OCP_THR,
+ OCP_THR_MASK,
+ OCP_THR_900_MA, 1);
+ if (rc)
+ pr_err("Failed to configure OCP rc = %d\n", rc);
+ }
+
break;
case SMBB_DC_CHGPTH_SUBTYPE:
break;