power: pm8921-charger: Add api to control OVP

Some board configurations have different needs for usb overvoltage
thresholds and debounce time for usb detection.

Provide apis to program threshold voltage, debounce time and
disable/enable overvoltage protection.

CRs-Fixed: 324137
Change-Id: Ie618ca12be819739a623cf41e5e1198305467aa5
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 5bf9c76..ea50ae9 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -1334,6 +1334,69 @@
 	return pm_chg_vinmin_set(the_chip, voltage);
 }
 
+#define USB_OV_THRESHOLD_MASK  0x60
+#define USB_OV_THRESHOLD_SHIFT  5
+int pm8921_usb_ovp_set_threshold(enum pm8921_usb_ov_threshold ov)
+{
+	u8 temp;
+
+	if (!the_chip) {
+		pr_err("called before init\n");
+		return -EINVAL;
+	}
+
+	if (ov > PM_USB_OV_7V) {
+		pr_err("limiting to over voltage threshold to 7volts\n");
+		ov = PM_USB_OV_7V;
+	}
+
+	temp = USB_OV_THRESHOLD_MASK & (ov << USB_OV_THRESHOLD_SHIFT);
+
+	return pm_chg_masked_write(the_chip, USB_OVP_CONTROL,
+				USB_OV_THRESHOLD_MASK, temp);
+}
+EXPORT_SYMBOL(pm8921_usb_ovp_set_threshold);
+
+#define USB_DEBOUNCE_TIME_MASK	0x06
+#define USB_DEBOUNCE_TIME_SHIFT 1
+int pm8921_usb_ovp_set_hystersis(enum pm8921_usb_debounce_time ms)
+{
+	u8 temp;
+
+	if (!the_chip) {
+		pr_err("called before init\n");
+		return -EINVAL;
+	}
+
+	if (ms > PM_USB_DEBOUNCE_80P5MS) {
+		pr_err("limiting debounce to 80.5ms\n");
+		ms = PM_USB_DEBOUNCE_80P5MS;
+	}
+
+	temp = USB_DEBOUNCE_TIME_MASK & (ms << USB_DEBOUNCE_TIME_SHIFT);
+
+	return pm_chg_masked_write(the_chip, USB_OVP_CONTROL,
+				USB_DEBOUNCE_TIME_MASK, temp);
+}
+EXPORT_SYMBOL(pm8921_usb_ovp_set_hystersis);
+
+#define USB_OVP_DISABLE_MASK	0x80
+int pm8921_usb_ovp_disable(int disable)
+{
+	u8 temp = 0;
+
+	if (!the_chip) {
+		pr_err("called before init\n");
+		return -EINVAL;
+	}
+
+	if (disable)
+		temp = USB_OVP_DISABLE_MASK;
+
+	return pm_chg_masked_write(the_chip, USB_OVP_CONTROL,
+				USB_OVP_DISABLE_MASK, temp);
+}
+
 bool pm8921_is_battery_charging(int *source)
 {
 	int fsm_state, is_charging, dc_present, usb_present;
diff --git a/include/linux/mfd/pm8xxx/pm8921-charger.h b/include/linux/mfd/pm8xxx/pm8921-charger.h
index 31fa537..eb1005c 100644
--- a/include/linux/mfd/pm8xxx/pm8921-charger.h
+++ b/include/linux/mfd/pm8xxx/pm8921-charger.h
@@ -33,6 +33,20 @@
 	PM_SMBC_BATT_TEMP_HOT_THR__HIGH
 };
 
+enum pm8921_usb_ov_threshold {
+	PM_USB_OV_5P5V,
+	PM_USB_OV_6V,
+	PM_USB_OV_6P5V,
+	PM_USB_OV_7V,
+};
+
+enum pm8921_usb_debounce_time {
+	PM_USB_BYPASS_DEBOUNCER,
+	PM_USB_DEBOUNCE_20P5MS,
+	PM_USB_DEBOUNCE_40P5MS,
+	PM_USB_DEBOUNCE_80P5MS,
+};
+
 /**
  * struct pm8921_charger_platform_data -
  * @safety_time:	max charging time in minutes incl. fast and trkl
@@ -247,6 +261,31 @@
  */
 void unregister_external_dc_charger(struct ext_chg_pm8921 *ext);
 
+/**
+ * pm8921_usb_ovp_set_threshold -
+ * Set the usb threshold as defined in by
+ * enum usb_ov_threshold
+ */
+int pm8921_usb_ovp_set_threshold(enum pm8921_usb_ov_threshold ov);
+
+/**
+ * pm8921_usb_ovp_set_hystersis -
+ * @ms: the debounce time enum
+ *
+ * Sets the debounce time for usb insertion/removal detection
+ *
+ */
+int pm8921_usb_ovp_set_hystersis(enum pm8921_usb_debounce_time ms);
+
+/**
+ * pm8921_usb_ovp_disable -
+ *
+ * when disabled there is no over voltage protection. The usb voltage is
+ * fed to the pmic as is. This should be disabled only when there is
+ * over voltage protection circuitry present outside the pmic chip.
+ *
+ */
+int pm8921_usb_ovp_disable(int disable);
 #else
 static inline void pm8921_charger_vbus_draw(unsigned int mA)
 {
@@ -308,6 +347,18 @@
 {
 	pr_err("%s.not implemented.\n", __func__);
 }
+static inline int pm8921_usb_ovp_set_threshold(enum pm8921_usb_ov_threshold ov)
+{
+	return -ENXIO;
+}
+static inline int pm8921_usb_ovp_set_hystersis(enum pm8921_usb_debounce_time ms)
+{
+	return -ENXIO;
+}
+static inline int pm8921_usb_ovp_disable(int disable)
+{
+	return -ENXIO;
+}
 #endif
 
 #endif