summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorFenglin Wu <fenglinw@codeaurora.org>2017-04-25 21:45:08 +0800
committerAbhijeet Dharmapurikar <adharmap@codeaurora.org>2017-05-03 13:48:19 -0700
commit15a68a61bd49f0a7306aa89eba9800a1d2ef031e (patch)
treee0bc305e6e90153d827c289b14cd1194f9e1e4b5 /drivers
parent5d78c03af8ffb440d418cbc45ad0d68928354e48 (diff)
power: qcom: smb2: Add REAL_TYPE property for usb power_supply
Add POWER_SUPPLY_PROP_REAL_TYPE property for usb_psy to present its real charger type. POWER_SUPPLY_PROP_TYPE in usb_psy is always set to POWER_SUPPLY_TYPE_USB_PD for healthd to recognize it as an AC charger. Also add usb_port_psy with POWER_SUPPLY_TYPE_USB type is added for healthd to recognize it as an USB host. Their ONLINE properties will be updated according to the VBUS status, type-c mode and real charger type. With this type being set statically, update the usb phy and pd policy engine code to look at real type. Change-Id: I90aa69325cc82b09dfb513c0eeecbc61e092a57f Signed-off-by: Fenglin Wu <fenglinw@codeaurora.org> Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/power/supply/qcom/qpnp-smb2.c124
-rw-r--r--drivers/power/supply/qcom/smb-lib.c14
-rw-r--r--drivers/power/supply/qcom/smb-lib.h2
-rw-r--r--drivers/usb/dwc3/dwc3-msm.c3
-rw-r--r--drivers/usb/pd/policy_engine.c2
5 files changed, 131 insertions, 14 deletions
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index 024c968e484a..2a4617a7359d 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -427,6 +427,7 @@ static enum power_supply_property smb2_usb_props[] = {
POWER_SUPPLY_PROP_PE_START,
POWER_SUPPLY_PROP_CTM_CURRENT_MAX,
POWER_SUPPLY_PROP_HW_CURRENT_MAX,
+ POWER_SUPPLY_PROP_REAL_TYPE,
};
static int smb2_usb_get_prop(struct power_supply *psy,
@@ -446,6 +447,16 @@ static int smb2_usb_get_prop(struct power_supply *psy,
break;
case POWER_SUPPLY_PROP_ONLINE:
rc = smblib_get_prop_usb_online(chg, val);
+ if (!val->intval)
+ break;
+
+ rc = smblib_get_prop_typec_mode(chg, val);
+ if ((val->intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT ||
+ chg->micro_usb_mode) &&
+ chg->real_charger_type == POWER_SUPPLY_TYPE_USB)
+ val->intval = 0;
+ else
+ val->intval = 1;
break;
case POWER_SUPPLY_PROP_VOLTAGE_MIN:
val->intval = chg->voltage_min_uv;
@@ -463,10 +474,13 @@ static int smb2_usb_get_prop(struct power_supply *psy,
rc = smblib_get_prop_usb_current_max(chg, val);
break;
case POWER_SUPPLY_PROP_TYPE:
+ val->intval = POWER_SUPPLY_TYPE_USB_PD;
+ break;
+ case POWER_SUPPLY_PROP_REAL_TYPE:
if (chip->bad_part)
- val->intval = POWER_SUPPLY_TYPE_USB;
+ val->intval = POWER_SUPPLY_TYPE_USB_PD;
else
- val->intval = chg->usb_psy_desc.type;
+ val->intval = chg->real_charger_type;
break;
case POWER_SUPPLY_PROP_TYPEC_MODE:
if (chg->micro_usb_mode)
@@ -608,7 +622,7 @@ static int smb2_init_usb_psy(struct smb2 *chip)
struct smb_charger *chg = &chip->chg;
chg->usb_psy_desc.name = "usb";
- chg->usb_psy_desc.type = POWER_SUPPLY_TYPE_UNKNOWN;
+ chg->usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_PD;
chg->usb_psy_desc.properties = smb2_usb_props;
chg->usb_psy_desc.num_properties = ARRAY_SIZE(smb2_usb_props);
chg->usb_psy_desc.get_property = smb2_usb_get_prop;
@@ -628,6 +642,97 @@ static int smb2_init_usb_psy(struct smb2 *chip)
return 0;
}
+/********************************
+ * USB PC_PORT PSY REGISTRATION *
+ ********************************/
+static enum power_supply_property smb2_usb_port_props[] = {
+ POWER_SUPPLY_PROP_TYPE,
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static int smb2_usb_port_get_prop(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct smb2 *chip = power_supply_get_drvdata(psy);
+ struct smb_charger *chg = &chip->chg;
+ int rc = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_TYPE:
+ val->intval = POWER_SUPPLY_TYPE_USB;
+ break;
+ case POWER_SUPPLY_PROP_ONLINE:
+ rc = smblib_get_prop_usb_online(chg, val);
+ if (!val->intval)
+ break;
+
+ rc = smblib_get_prop_typec_mode(chg, val);
+ if ((val->intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT ||
+ chg->micro_usb_mode) &&
+ chg->real_charger_type == POWER_SUPPLY_TYPE_USB)
+ val->intval = 1;
+ else
+ val->intval = 0;
+ break;
+ default:
+ pr_err_ratelimited("Get prop %d is not supported in pc_port\n",
+ psp);
+ return -EINVAL;
+ }
+
+ if (rc < 0) {
+ pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
+ return -ENODATA;
+ }
+
+ return 0;
+}
+
+static int smb2_usb_port_set_prop(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ int rc = 0;
+
+ switch (psp) {
+ default:
+ pr_err_ratelimited("Set prop %d is not supported in pc_port\n",
+ psp);
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+static const struct power_supply_desc usb_port_psy_desc = {
+ .name = "pc_port",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .properties = smb2_usb_port_props,
+ .num_properties = ARRAY_SIZE(smb2_usb_port_props),
+ .get_property = smb2_usb_port_get_prop,
+ .set_property = smb2_usb_port_set_prop,
+};
+
+static int smb2_init_usb_port_psy(struct smb2 *chip)
+{
+ struct power_supply_config usb_port_cfg = {};
+ struct smb_charger *chg = &chip->chg;
+
+ usb_port_cfg.drv_data = chip;
+ usb_port_cfg.of_node = chg->dev->of_node;
+ chg->usb_port_psy = power_supply_register(chg->dev,
+ &usb_port_psy_desc,
+ &usb_port_cfg);
+ if (IS_ERR(chg->usb_port_psy)) {
+ pr_err("Couldn't register USB pc_port power supply\n");
+ return PTR_ERR(chg->usb_port_psy);
+ }
+
+ return 0;
+}
+
/*****************************
* USB MAIN PSY REGISTRATION *
*****************************/
@@ -2266,7 +2371,13 @@ static int smb2_probe(struct platform_device *pdev)
rc = smb2_init_usb_main_psy(chip);
if (rc < 0) {
- pr_err("Couldn't initialize usb psy rc=%d\n", rc);
+ pr_err("Couldn't initialize usb main psy rc=%d\n", rc);
+ goto cleanup;
+ }
+
+ rc = smb2_init_usb_port_psy(chip);
+ if (rc < 0) {
+ pr_err("Couldn't initialize usb pc_port psy rc=%d\n", rc);
goto cleanup;
}
@@ -2324,7 +2435,7 @@ static int smb2_probe(struct platform_device *pdev)
device_init_wakeup(chg->dev, true);
pr_info("QPNP SMB2 probed successfully usb:present=%d type=%d batt:present = %d health = %d charge = %d\n",
- usb_present, chg->usb_psy_desc.type,
+ usb_present, chg->real_charger_type,
batt_present, batt_health, batt_charge_type);
return rc;
@@ -2336,6 +2447,8 @@ cleanup:
power_supply_unregister(chg->usb_main_psy);
if (chg->usb_psy)
power_supply_unregister(chg->usb_psy);
+ if (chg->usb_port_psy)
+ power_supply_unregister(chg->usb_port_psy);
if (chg->dc_psy)
power_supply_unregister(chg->dc_psy);
if (chg->vconn_vreg && chg->vconn_vreg->rdev)
@@ -2356,6 +2469,7 @@ static int smb2_remove(struct platform_device *pdev)
power_supply_unregister(chg->batt_psy);
power_supply_unregister(chg->usb_psy);
+ power_supply_unregister(chg->usb_port_psy);
regulator_unregister(chg->vconn_vreg->rdev);
regulator_unregister(chg->vbus_vreg->rdev);
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index ecfb532e5b3c..64e3edeec3d5 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -550,9 +550,9 @@ static const struct apsd_result *smblib_update_usb_type(struct smb_charger *chg)
/* if PD is active, APSD is disabled so won't have a valid result */
if (chg->pd_active)
- chg->usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_PD;
+ chg->real_charger_type = POWER_SUPPLY_TYPE_USB_PD;
else
- chg->usb_psy_desc.type = apsd_result->pst;
+ chg->real_charger_type = apsd_result->pst;
smblib_dbg(chg, PR_MISC, "APSD=%s PD=%d\n",
apsd_result->name, chg->pd_active);
@@ -858,7 +858,7 @@ int smblib_set_icl_current(struct smb_charger *chg, int icl_ua)
/* configure current */
if (pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT
- && (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB)) {
+ && (chg->real_charger_type == POWER_SUPPLY_TYPE_USB)) {
rc = set_sdp_current(chg, icl_ua);
if (rc < 0) {
smblib_err(chg, "Couldn't set SDP ICL rc=%d\n", rc);
@@ -879,10 +879,10 @@ override_suspend_config:
/* remove override if no voters - hw defaults is desired */
override = false;
} else if (pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) {
- if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB)
+ if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB)
/* For std cable with type = SDP never override */
override = false;
- else if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_CDP
+ else if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_CDP
&& icl_ua == 1500000)
/*
* For std cable with type = CDP override only if
@@ -3314,7 +3314,7 @@ static void smblib_hvdcp_adaptive_voltage_change(struct smb_charger *chg)
int pulses;
power_supply_changed(chg->usb_main_psy);
- if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_HVDCP) {
+ if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_HVDCP) {
rc = smblib_read(chg, QC_CHANGE_STATUS_REG, &stat);
if (rc < 0) {
smblib_err(chg,
@@ -3342,7 +3342,7 @@ static void smblib_hvdcp_adaptive_voltage_change(struct smb_charger *chg)
}
}
- if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_HVDCP_3) {
+ if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_HVDCP_3) {
rc = smblib_read(chg, QC_PULSE_COUNT_STATUS_REG, &stat);
if (rc < 0) {
smblib_err(chg,
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index d14ea86bf0c6..76de955c303b 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -244,6 +244,8 @@ struct smb_charger {
struct power_supply *bms_psy;
struct power_supply_desc usb_psy_desc;
struct power_supply *usb_main_psy;
+ struct power_supply *usb_port_psy;
+ enum power_supply_type real_charger_type;
/* notifiers */
struct notifier_block nb;
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index e394f123f918..ad9d6cc4e23f 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -3597,7 +3597,8 @@ static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned mA)
}
}
- power_supply_get_property(mdwc->usb_psy, POWER_SUPPLY_PROP_TYPE, &pval);
+ power_supply_get_property(mdwc->usb_psy,
+ POWER_SUPPLY_PROP_REAL_TYPE, &pval);
if (pval.intval != POWER_SUPPLY_TYPE_USB)
return 0;
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index c76ca5a94557..055c6203577a 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -2365,7 +2365,7 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
pd->vbus_present = val.intval;
ret = power_supply_get_property(pd->usb_psy,
- POWER_SUPPLY_PROP_TYPE, &val);
+ POWER_SUPPLY_PROP_REAL_TYPE, &val);
if (ret) {
usbpd_err(&pd->dev, "Unable to read USB TYPE: %d\n", ret);
return ret;