summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Pham <jackp@codeaurora.org>2016-03-16 11:38:40 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 21:25:49 -0700
commitee53d51499cf3b94b3d78513f3160eca68634386 (patch)
tree76b19c7b2f4961982d2d5533954dd50c76b331a0
parent0e671048def84c8bc5caec977da7fa9953d48918 (diff)
power: qpnp-smbcharger: Add extcon notifiers for USB
Allow charger to expose an extcon device which can emit notification for USB and USB-HOST cable connection states. The driver can correspondingly register interest in being notified of these cable connection statuses. This is intended to replace the power_supply_set_present() and power_supply_set_usb_otg() mechanisms currently used. Change-Id: I6c7cf971f59ac3f3075f5c8f13786306729f25a8 Signed-off-by: Jack Pham <jackp@codeaurora.org>
-rw-r--r--drivers/power/Kconfig1
-rw-r--r--drivers/power/qpnp-smbcharger.c37
2 files changed, 38 insertions, 0 deletions
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index b194a89a103a..61c19907d0cf 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -523,6 +523,7 @@ config AXP20X_POWER
config QPNP_SMBCHARGER
tristate "QPNP SMB Charger driver"
depends on SPMI
+ depends on EXTCON
help
Say Y here to enable the dual path switch mode battery charger which
supports USB detection and battery charging up to 3A.
diff --git a/drivers/power/qpnp-smbcharger.c b/drivers/power/qpnp-smbcharger.c
index 12375aeb2818..ca6bba0582e5 100644
--- a/drivers/power/qpnp-smbcharger.c
+++ b/drivers/power/qpnp-smbcharger.c
@@ -40,6 +40,7 @@
#include <linux/of_batterydata.h>
#include <linux/msm_bcl.h>
#include <linux/ktime.h>
+#include <linux/extcon.h>
#include "pmic-voter.h"
/* Mask/Bit helpers */
@@ -280,6 +281,9 @@ struct smbchg_chip {
struct votable *hw_aicl_rerun_disable_votable;
struct votable *hw_aicl_rerun_enable_indirect_votable;
struct votable *aicl_deglitch_short_votable;
+
+ /* extcon for VBUS / ID notification to USB */
+ struct extcon_dev *extcon;
};
enum qpnp_schg {
@@ -419,6 +423,13 @@ enum aicl_short_deglitch_voters {
HVDCP_SHORT_DEGLITCH_VOTER,
NUM_HW_SHORT_DEGLITCH_VOTERS,
};
+
+static const unsigned int smbchg_extcon_cable[] = {
+ EXTCON_USB,
+ EXTCON_USB_HOST,
+ EXTCON_NONE,
+};
+
static int smbchg_debug_mask;
module_param_named(
debug_mask, smbchg_debug_mask, int, S_IRUSR | S_IWUSR
@@ -4524,6 +4535,7 @@ static void handle_usb_removal(struct smbchg_chip *chip)
power_supply_set_property(chip->usb_psy,
POWER_SUPPLY_PROP_PRESENT, &pval);
}
+ extcon_set_cable_state_(chip->extcon, EXTCON_USB, chip->usb_present);
set_usb_psy_dp_dm(chip, POWER_SUPPLY_DP_DM_DPR_DMR);
schedule_work(&chip->usb_set_online_work);
@@ -4615,6 +4627,12 @@ static void handle_usb_insertion(struct smbchg_chip *chip)
POWER_SUPPLY_PROP_PRESENT, &pval);
}
+ /* Only notify USB if it's not a charger */
+ if (usb_supply_type == POWER_SUPPLY_TYPE_USB ||
+ usb_supply_type == POWER_SUPPLY_TYPE_USB_CDP)
+ extcon_set_cable_state_(chip->extcon, EXTCON_USB,
+ chip->usb_present);
+
/* Notify the USB psy if OV condition is not present */
if (!chip->usb_ov_det) {
/*
@@ -5524,6 +5542,8 @@ static void update_typec_otg_status(struct smbchg_chip *chip, int mode,
pval.intval = 1;
power_supply_set_property(chip->usb_psy,
POWER_SUPPLY_PROP_USB_OTG, &pval);
+ extcon_set_cable_state_(chip->extcon, EXTCON_USB_HOST,
+ chip->typec_dfp);
/* update FG */
set_property_on_fg(chip, POWER_SUPPLY_PROP_STATUS,
get_prop_batt_status(chip));
@@ -5532,6 +5552,8 @@ static void update_typec_otg_status(struct smbchg_chip *chip, int mode,
pval.intval = 0;
power_supply_set_property(chip->usb_psy,
POWER_SUPPLY_PROP_USB_OTG, &pval);
+ extcon_set_cable_state_(chip->extcon, EXTCON_USB_HOST,
+ chip->typec_dfp);
/* update FG */
set_property_on_fg(chip, POWER_SUPPLY_PROP_STATUS,
get_prop_batt_status(chip));
@@ -6418,6 +6440,9 @@ static irqreturn_t usbid_change_handler(int irq, void *_chip)
power_supply_set_property(chip->usb_psy,
POWER_SUPPLY_PROP_USB_OTG, &pval);
}
+
+ extcon_set_cable_state_(chip->extcon, EXTCON_USB_HOST, otg_present);
+
if (otg_present)
pr_smb(PR_STATUS, "OTG detected\n");
@@ -8018,6 +8043,18 @@ static int smbchg_probe(struct platform_device *pdev)
return rc;
}
+ chip->extcon = devm_extcon_dev_allocate(chip->dev, smbchg_extcon_cable);
+ if (IS_ERR(chip->extcon)) {
+ dev_err(chip->dev, "failed to allocate extcon device\n");
+ return PTR_ERR(chip->extcon);
+ }
+
+ rc = devm_extcon_dev_register(chip->dev, chip->extcon);
+ if (rc) {
+ dev_err(chip->dev, "failed to register extcon device\n");
+ return rc;
+ }
+
rc = smbchg_hw_init(chip);
if (rc < 0) {
dev_err(&pdev->dev,