diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c index 19e78afe2a48..6fc290062f99 100644 --- a/drivers/power/qcom-charger/qpnp-smb2.c +++ b/drivers/power/qcom-charger/qpnp-smb2.c @@ -368,6 +368,105 @@ static int smb2_init_usb_psy(struct smb2 *chip) return 0; } +/************************* + * DC PSY REGISTRATION * + *************************/ + +static enum power_supply_property smb2_dc_props[] = { + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_CURRENT_MAX, +}; + +static int smb2_dc_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_PRESENT: + rc = smblib_get_prop_dc_present(chg, val); + break; + case POWER_SUPPLY_PROP_ONLINE: + rc = smblib_get_prop_dc_online(chg, val); + break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + rc = smblib_get_prop_dc_current_max(chg, val); + break; + default: + return -EINVAL; + } + + return rc; +} + +static int smb2_dc_set_prop(struct power_supply *psy, + enum power_supply_property psp, + const 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_CURRENT_MAX: + rc = smblib_set_prop_dc_current_max(chg, val); + break; + default: + return -EINVAL; + } + + return rc; +} + +static int smb2_dc_prop_is_writeable(struct power_supply *psy, + enum power_supply_property psp) +{ + int rc; + + switch (psp) { + case POWER_SUPPLY_PROP_CURRENT_MAX: + rc = 1; + break; + default: + rc = 0; + break; + } + + return rc; +} + +static const struct power_supply_desc dc_psy_desc = { + .name = "dc", + .type = POWER_SUPPLY_TYPE_WIPOWER, + .properties = smb2_dc_props, + .num_properties = ARRAY_SIZE(smb2_dc_props), + .get_property = smb2_dc_get_prop, + .set_property = smb2_dc_set_prop, + .property_is_writeable = smb2_dc_prop_is_writeable, +}; + +static int smb2_init_dc_psy(struct smb2 *chip) +{ + struct power_supply_config dc_cfg = {}; + struct smb_charger *chg = &chip->chg; + + dc_cfg.drv_data = chip; + dc_cfg.of_node = chg->dev->of_node; + chg->dc_psy = devm_power_supply_register(chg->dev, + &dc_psy_desc, + &dc_cfg); + if (IS_ERR(chg->dc_psy)) { + pr_err("Couldn't register USB power supply\n"); + return PTR_ERR(chg->dc_psy); + } + + return 0; +} + /************************* * BATT PSY REGISTRATION * *************************/ @@ -930,6 +1029,12 @@ static int smb2_probe(struct platform_device *pdev) goto cleanup; } + rc = smb2_init_dc_psy(chip); + if (rc < 0) { + pr_err("Couldn't initialize dc psy rc=%d\n", rc); + goto cleanup; + } + rc = smb2_init_usb_psy(chip); if (rc < 0) { pr_err("Couldn't initialize usb psy rc=%d\n", rc); diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c index 16a39626a102..8fe882e078f0 100644 --- a/drivers/power/qcom-charger/smb-lib.c +++ b/drivers/power/qcom-charger/smb-lib.c @@ -917,6 +917,76 @@ int smblib_set_prop_system_temp_level(struct smb_charger *chg, return 0; } +/******************* + * DC PSY GETTERS * + *******************/ + +int smblib_get_prop_dc_present(struct smb_charger *chg, + union power_supply_propval *val) +{ + int rc = 0; + u8 stat; + + rc = smblib_read(chg, DC_INT_RT_STS_REG, &stat); + if (rc < 0) { + dev_err(chg->dev, "Couldn't read DC_INT_RT_STS_REG rc=%d\n", + rc); + return rc; + } + smblib_dbg(chg, PR_REGISTER, "DC_INT_RT_STS_REG = 0x%02x\n", + stat); + + val->intval = (bool)(stat & DCIN_PLUGIN_RT_STS_BIT); + + return rc; +} + +int smblib_get_prop_dc_online(struct smb_charger *chg, + union power_supply_propval *val) +{ + int rc = 0; + u8 stat; + + if (get_client_vote(chg->dc_suspend_votable, USER_VOTER)) { + val->intval = false; + return rc; + } + + rc = smblib_read(chg, POWER_PATH_STATUS_REG, &stat); + if (rc < 0) { + dev_err(chg->dev, "Couldn't read POWER_PATH_STATUS rc=%d\n", + rc); + return rc; + } + smblib_dbg(chg, PR_REGISTER, "POWER_PATH_STATUS = 0x%02x\n", + stat); + + val->intval = (stat & USE_DCIN_BIT) && + (stat & VALID_INPUT_POWER_SOURCE_BIT); + + return rc; +} + +int smblib_get_prop_dc_current_max(struct smb_charger *chg, + union power_supply_propval *val) +{ + val->intval = get_effective_result_locked(chg->dc_icl_votable); + return 0; +} + +/******************* + * USB PSY SETTERS * + * *****************/ + +int smblib_set_prop_dc_current_max(struct smb_charger *chg, + const union power_supply_propval *val) +{ + int rc; + + rc = vote(chg->dc_icl_votable, USER_VOTER, true, val->intval); + return rc; +} + /******************* * USB PSY GETTERS * *******************/ diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h index 2b6462d99341..1521fdb3fccf 100644 --- a/drivers/power/qcom-charger/smb-lib.h +++ b/drivers/power/qcom-charger/smb-lib.h @@ -95,6 +95,7 @@ struct smb_charger { /* power supplies */ struct power_supply *batt_psy; struct power_supply *usb_psy; + struct power_supply *dc_psy; struct power_supply_desc usb_psy_desc; /* parallel charging */ @@ -187,6 +188,15 @@ int smblib_set_prop_input_suspend(struct smb_charger *chg, int smblib_set_prop_system_temp_level(struct smb_charger *chg, const union power_supply_propval *val); +int smblib_get_prop_dc_present(struct smb_charger *chg, + union power_supply_propval *val); +int smblib_get_prop_dc_online(struct smb_charger *chg, + union power_supply_propval *val); +int smblib_get_prop_dc_current_max(struct smb_charger *chg, + union power_supply_propval *val); +int smblib_set_prop_dc_current_max(struct smb_charger *chg, + const union power_supply_propval *val); + int smblib_get_prop_usb_present(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_usb_online(struct smb_charger *chg, diff --git a/drivers/power/qcom-charger/smb-reg.h b/drivers/power/qcom-charger/smb-reg.h index 5af01c229f01..b03e8a7e0403 100644 --- a/drivers/power/qcom-charger/smb-reg.h +++ b/drivers/power/qcom-charger/smb-reg.h @@ -641,6 +641,9 @@ enum { #define WIPWR_RANGE_STATUS_REG (DCIN_BASE + 0x08) #define WIPWR_RANGE_STATUS_MASK GENMASK(4, 0) +#define DC_INT_RT_STS_REG (DCIN_BASE + 0x10) +#define DCIN_PLUGIN_RT_STS_BIT BIT(4) + /* DCIN Interrupt Bits */ #define WIPWR_VOLTAGE_RANGE_RT_STS_BIT BIT(7) #define DCIN_ICL_CHANGE_RT_STS_BIT BIT(6)