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>
This commit is contained in:
Jack Pham 2016-03-16 11:38:40 -07:00 committed by David Keitel
parent 0e671048de
commit ee53d51499
2 changed files with 38 additions and 0 deletions

View file

@ -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.

View file

@ -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,