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>
This commit is contained in:
Fenglin Wu 2017-04-25 21:45:08 +08:00 committed by Abhijeet Dharmapurikar
parent 5d78c03af8
commit 15a68a61bd
5 changed files with 131 additions and 14 deletions

View file

@ -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);

View file

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

View file

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

View file

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

View file

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