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:
parent
5d78c03af8
commit
15a68a61bd
5 changed files with 131 additions and 14 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue