From 4e4144f64367d6785f8d816860116e6a17ecd70a Mon Sep 17 00:00:00 2001 From: Harry Yang Date: Wed, 20 Jul 2016 14:56:41 -0700 Subject: [PATCH] qcom-charger: add support for WiPower Add support for WiPower by instantiating DC power supply and the required properties. CRs-Fixed: 1044422 Change-Id: I81d2e3b67bf55460f40406328c5ad8c40851033a Signed-off-by: Harry Yang --- drivers/power/qcom-charger/qpnp-smb2.c | 105 +++++++++++++++++++++++++ drivers/power/qcom-charger/smb-lib.c | 70 +++++++++++++++++ drivers/power/qcom-charger/smb-lib.h | 10 +++ drivers/power/qcom-charger/smb-reg.h | 3 + 4 files changed, 188 insertions(+) diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c index 541e40aeb91a..07ec0ba9149e 100644 --- a/drivers/power/qcom-charger/qpnp-smb2.c +++ b/drivers/power/qcom-charger/qpnp-smb2.c @@ -349,6 +349,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 * *************************/ @@ -904,6 +1003,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 dd3ec1eb51e3..a8441ae985d2 100644 --- a/drivers/power/qcom-charger/smb-lib.c +++ b/drivers/power/qcom-charger/smb-lib.c @@ -876,6 +876,76 @@ int smblib_set_prop_input_suspend(struct smb_charger *chg, return rc; } +/******************* + * 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 2e35e1e3b174..05025744ba5a 100644 --- a/drivers/power/qcom-charger/smb-lib.h +++ b/drivers/power/qcom-charger/smb-lib.h @@ -93,6 +93,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 */ @@ -174,6 +175,15 @@ int smblib_get_prop_batt_health(struct smb_charger *chg, int smblib_set_prop_input_suspend(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)