diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2017-04-05 12:17:03 -0700 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-04-05 12:17:03 -0700 |
| commit | 8f91cc1fa4ed7dcb509d0cb13a04157bcdb18449 (patch) | |
| tree | 4dac9ed9c4d83f98561e7f41ae39a5ad322dd370 | |
| parent | 6e2c59ad47bee17aee211971e082e8986ae8db2e (diff) | |
| parent | 17d9f0383d607a8c8856d6d347a1b9997e356644 (diff) | |
Merge "power_supply: add HW_CURRENT_MAX power_supply property"
| -rw-r--r-- | drivers/power/power_supply_sysfs.c | 1 | ||||
| -rw-r--r-- | drivers/power/supply/qcom/battery.c | 41 | ||||
| -rw-r--r-- | drivers/power/supply/qcom/qpnp-smb2.c | 19 | ||||
| -rw-r--r-- | drivers/power/supply/qcom/smb-lib.c | 116 | ||||
| -rw-r--r-- | drivers/power/supply/qcom/smb-lib.h | 4 | ||||
| -rw-r--r-- | drivers/power/supply/qcom/smb-reg.h | 1 | ||||
| -rw-r--r-- | include/linux/power_supply.h | 1 |
7 files changed, 114 insertions, 69 deletions
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index 438da2c51dd6..723b9eaf658a 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -293,6 +293,7 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(die_health), POWER_SUPPLY_ATTR(connector_health), POWER_SUPPLY_ATTR(ctm_current_max), + POWER_SUPPLY_ATTR(hw_current_max), /* Local extensions of type int64_t */ POWER_SUPPLY_ATTR(charge_counter_ext), /* Properties of type `const char *' */ diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c index 0c80c8be7909..99a5f48ad5db 100644 --- a/drivers/power/supply/qcom/battery.c +++ b/drivers/power/supply/qcom/battery.c @@ -49,6 +49,7 @@ struct pl_data { struct votable *pl_disable_votable; struct votable *pl_awake_votable; struct votable *hvdcp_hw_inov_dis_votable; + struct votable *usb_icl_votable; struct work_struct status_change_work; struct work_struct pl_disable_forever_work; struct delayed_work pl_taper_work; @@ -487,6 +488,25 @@ static int pl_fv_vote_callback(struct votable *votable, void *data, return 0; } +static int usb_icl_vote_callback(struct votable *votable, void *data, + int icl_ua, const char *client) +{ + struct pl_data *chip = data; + union power_supply_propval pval = {0, }; + + if (!chip->main_psy) + return 0; + + if (client == NULL) + icl_ua = INT_MAX; + + pval.intval = icl_ua; + return power_supply_set_property(chip->main_psy, + POWER_SUPPLY_PROP_INPUT_CURRENT_MAX, &pval); + + return 0; +} + static void pl_disable_forever_work(struct work_struct *work) { struct pl_data *chip = container_of(work, @@ -596,13 +616,15 @@ static int pl_awake_vote_callback(struct votable *votable, static bool is_main_available(struct pl_data *chip) { - if (!chip->main_psy) - chip->main_psy = power_supply_get_by_name("main"); + if (chip->main_psy) + return true; - if (!chip->main_psy) - return false; + chip->main_psy = power_supply_get_by_name("main"); - return true; + if (chip->main_psy) + rerun_election(chip->usb_icl_votable); + + return !!chip->main_psy; } static bool is_batt_available(struct pl_data *chip) @@ -855,6 +877,14 @@ static int pl_init(void) goto destroy_votable; } + chip->usb_icl_votable = create_votable("USB_ICL", VOTE_MIN, + usb_icl_vote_callback, + chip); + if (IS_ERR(chip->usb_icl_votable)) { + rc = PTR_ERR(chip->usb_icl_votable); + goto destroy_votable; + } + chip->pl_disable_votable = create_votable("PL_DISABLE", VOTE_SET_ANY, pl_disable_vote_callback, chip); @@ -909,6 +939,7 @@ destroy_votable: destroy_votable(chip->pl_disable_votable); destroy_votable(chip->fv_votable); destroy_votable(chip->fcc_votable); + destroy_votable(chip->usb_icl_votable); release_wakeup_source: wakeup_source_unregister(chip->pl_ws); cleanup: diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c index b4fb80a2d4f3..cb7a85068233 100644 --- a/drivers/power/supply/qcom/qpnp-smb2.c +++ b/drivers/power/supply/qcom/qpnp-smb2.c @@ -616,6 +616,7 @@ static enum power_supply_property smb2_usb_main_props[] = { POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED, POWER_SUPPLY_PROP_INPUT_VOLTAGE_SETTLED, POWER_SUPPLY_PROP_FCC_DELTA, + POWER_SUPPLY_PROP_CURRENT_MAX, /* * TODO move the TEMP and TEMP_MAX properties here, * and update the thermal balancer to look here @@ -653,6 +654,9 @@ static int smb2_usb_main_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_FCC_DELTA: rc = smblib_get_prop_fcc_delta(chg, val); break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + val->intval = get_effective_result(chg->usb_icl_votable); + break; default: pr_debug("get prop %d is not supported in usb-main\n", psp); rc = -EINVAL; @@ -683,6 +687,9 @@ static int smb2_usb_main_set_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: rc = smblib_set_charge_param(chg, &chg->param.fcc, val->intval); break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + rc = smblib_set_icl_current(chg, val->intval); + break; default: pr_err("set prop %d is not supported\n", psp); rc = -EINVAL; @@ -1572,6 +1579,16 @@ static int smb2_init_hw(struct smb2 *chip) return rc; } + /* disable h/w autonomous parallel charging control */ + rc = smblib_masked_write(chg, MISC_CFG_REG, + STAT_PARALLEL_1400MA_EN_CFG_BIT, 0); + if (rc < 0) { + dev_err(chg->dev, + "Couldn't disable h/w autonomous parallel control rc=%d\n", + rc); + return rc; + } + /* configure float charger options */ switch (chip->dt.float_option) { case 1: @@ -2230,6 +2247,8 @@ static int smb2_probe(struct platform_device *pdev) } batt_charge_type = val.intval; + 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, batt_present, batt_health, batt_charge_type); diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index d631f49db63a..379280d3eb33 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -654,10 +654,13 @@ static void smblib_uusb_removal(struct smb_charger *chg) { int rc; + cancel_delayed_work_sync(&chg->pl_enable_work); + vote(chg->pl_disable_votable, PL_DELAY_VOTER, true, 0); + vote(chg->awake_votable, PL_DELAY_VOTER, false, 0); + /* reset both usbin current and voltage votes */ vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0); vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0); - vote(chg->pl_disable_votable, PL_DELAY_HVDCP_VOTER, true, 0); cancel_delayed_work_sync(&chg->hvdcp_detect_work); @@ -795,29 +798,12 @@ static int smblib_get_pulse_cnt(struct smb_charger *chg, int *count) return 0; } -/********************* - * VOTABLE CALLBACKS * - *********************/ - -static int smblib_dc_suspend_vote_callback(struct votable *votable, void *data, - int suspend, const char *client) -{ - struct smb_charger *chg = data; - - /* resume input if suspend is invalid */ - if (suspend < 0) - suspend = 0; - - return smblib_set_dc_suspend(chg, (bool)suspend); -} - #define USBIN_25MA 25000 #define USBIN_100MA 100000 #define USBIN_150MA 150000 #define USBIN_500MA 500000 #define USBIN_900MA 900000 - static int set_sdp_current(struct smb_charger *chg, int icl_ua) { int rc; @@ -856,20 +842,18 @@ static int set_sdp_current(struct smb_charger *chg, int icl_ua) return rc; } -static int smblib_usb_icl_vote_callback(struct votable *votable, void *data, - int icl_ua, const char *client) +int smblib_set_icl_current(struct smb_charger *chg, int icl_ua) { - struct smb_charger *chg = data; int rc = 0; bool override; union power_supply_propval pval; /* suspend and return if 25mA or less is requested */ - if (client && (icl_ua < USBIN_25MA)) + if (icl_ua < USBIN_25MA) return smblib_set_usb_suspend(chg, true); disable_irq_nosync(chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq); - if (!client) + if (icl_ua == INT_MAX) goto override_suspend_config; rc = smblib_get_prop_typec_mode(chg, &pval); @@ -898,7 +882,7 @@ static int smblib_usb_icl_vote_callback(struct votable *votable, void *data, override_suspend_config: /* determine if override needs to be enforced */ override = true; - if (client == NULL) { + if (icl_ua == INT_MAX) { /* remove override if no voters - hw defaults is desired */ override = false; } else if (pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) { @@ -936,6 +920,22 @@ enable_icl_changed_interrupt: return rc; } +/********************* + * VOTABLE CALLBACKS * + *********************/ + +static int smblib_dc_suspend_vote_callback(struct votable *votable, void *data, + int suspend, const char *client) +{ + struct smb_charger *chg = data; + + /* resume input if suspend is invalid */ + if (suspend < 0) + suspend = 0; + + return smblib_set_dc_suspend(chg, (bool)suspend); +} + static int smblib_dc_icl_vote_callback(struct votable *votable, void *data, int icl_ua, const char *client) { @@ -2618,16 +2618,6 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, smblib_err(chg, "Couldn't unvote USB_PSY rc=%d\n", rc); return rc; } - - /* pd active set, parallel charger can be enabled now */ - rc = vote(chg->pl_disable_votable, PL_DELAY_HVDCP_VOTER, - false, 0); - if (rc < 0) { - smblib_err(chg, - "Couldn't unvote PL_DELAY_HVDCP_VOTER rc=%d\n", - rc); - return rc; - } } /* CC pin selection s/w override in PD session; h/w otherwise. */ @@ -3159,6 +3149,7 @@ irqreturn_t smblib_handle_usbin_uv(int irq, void *data) return IRQ_HANDLED; } +#define PL_DELAY_MS 30000 irqreturn_t smblib_handle_usb_plugin(int irq, void *data) { struct smb_irq_data *irq_data = data; @@ -3197,6 +3188,11 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data) smblib_err(chg, "Couldn't enable dpdm regulator rc=%d\n", rc); } + + /* Schedule work to enable parallel charger */ + vote(chg->awake_votable, PL_DELAY_VOTER, true, 0); + schedule_delayed_work(&chg->pl_enable_work, + msecs_to_jiffies(PL_DELAY_MS)); } else { if (chg->wa_flags & BOOST_BACK_WA) vote(chg->usb_icl_votable, BOOST_BACK_VOTER, false, 0); @@ -3374,9 +3370,6 @@ static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg, } } - /* QC authentication done, parallel charger can be enabled now */ - vote(chg->pl_disable_votable, PL_DELAY_HVDCP_VOTER, false, 0); - smblib_dbg(chg, PR_INTERRUPT, "IRQ: hvdcp-3p0-auth-done rising; %s detected\n", apsd_result->name); } @@ -3406,15 +3399,6 @@ static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg, /* enforce DCP ICL if specified */ vote(chg->usb_icl_votable, DCP_VOTER, chg->dcp_icl_ua != -EINVAL, chg->dcp_icl_ua); - /* - * If adapter is not QC2.0/QC3.0 remove vote for parallel - * disable. - * Otherwise if adapter is QC2.0/QC3.0 wait for authentication - * to complete. - */ - if (!qc_charger) - vote(chg->pl_disable_votable, PL_DELAY_HVDCP_VOTER, - false, 0); } smblib_dbg(chg, PR_INTERRUPT, "IRQ: smblib_handle_hvdcp_check_timeout %s\n", @@ -3486,13 +3470,9 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising) true); case OCP_CHARGER_BIT: case FLOAT_CHARGER_BIT: - /* - * if not DCP then no hvdcp timeout happens. Enable - * pd/parallel here. - */ + /* if not DCP then no hvdcp timeout happens, Enable pd here. */ vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, false, 0); - vote(chg->pl_disable_votable, PL_DELAY_HVDCP_VOTER, false, 0); break; case DCP_CHARGER_BIT: if (chg->wa_flags & QC_CHARGER_DETECTION_WA_BIT) @@ -3645,9 +3625,12 @@ static void smblib_handle_typec_removal(struct smb_charger *chg) { int rc; + cancel_delayed_work_sync(&chg->pl_enable_work); + vote(chg->pl_disable_votable, PL_DELAY_VOTER, true, 0); + vote(chg->awake_votable, PL_DELAY_VOTER, false, 0); + vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER, true, 0); vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, true, 0); - vote(chg->pl_disable_votable, PL_DELAY_HVDCP_VOTER, true, 0); vote(chg->usb_irq_enable_votable, PD_VOTER, false, 0); vote(chg->usb_irq_enable_votable, QC_VOTER, false, 0); @@ -3703,8 +3686,6 @@ static void smblib_handle_typec_insertion(struct smb_charger *chg, if (rp == POWER_SUPPLY_TYPEC_SOURCE_HIGH || rp == POWER_SUPPLY_TYPEC_NON_COMPLIANT) { smblib_dbg(chg, PR_MISC, "VBUS & CC could be shorted; keeping HVDCP disabled\n"); - /* HVDCP is not going to be enabled; enable parallel */ - vote(chg->pl_disable_votable, PL_DELAY_HVDCP_VOTER, false, 0); vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER, true, 0); } else { @@ -4210,6 +4191,16 @@ static void smblib_icl_change_work(struct work_struct *work) smblib_dbg(chg, PR_INTERRUPT, "icl_settled=%d\n", settled_ua); } +static void smblib_pl_enable_work(struct work_struct *work) +{ + struct smb_charger *chg = container_of(work, struct smb_charger, + pl_enable_work.work); + + smblib_dbg(chg, PR_PARALLEL, "timer expired, enabling parallel\n"); + vote(chg->pl_disable_votable, PL_DELAY_VOTER, false, 0); + vote(chg->awake_votable, PL_DELAY_VOTER, false, 0); +} + static int smblib_create_votables(struct smb_charger *chg) { int rc = 0; @@ -4226,13 +4217,19 @@ static int smblib_create_votables(struct smb_charger *chg) return rc; } + chg->usb_icl_votable = find_votable("USB_ICL"); + if (!chg->usb_icl_votable) { + rc = -EPROBE_DEFER; + return rc; + } + chg->pl_disable_votable = find_votable("PL_DISABLE"); if (!chg->pl_disable_votable) { rc = -EPROBE_DEFER; return rc; } vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, true, 0); - vote(chg->pl_disable_votable, PL_DELAY_HVDCP_VOTER, true, 0); + vote(chg->pl_disable_votable, PL_DELAY_VOTER, true, 0); chg->dc_suspend_votable = create_votable("DC_SUSPEND", VOTE_SET_ANY, smblib_dc_suspend_vote_callback, @@ -4242,14 +4239,6 @@ static int smblib_create_votables(struct smb_charger *chg) return rc; } - chg->usb_icl_votable = create_votable("USB_ICL", VOTE_MIN, - smblib_usb_icl_vote_callback, - chg); - if (IS_ERR(chg->usb_icl_votable)) { - rc = PTR_ERR(chg->usb_icl_votable); - return rc; - } - chg->dc_icl_votable = create_votable("DC_ICL", VOTE_MIN, smblib_dc_icl_vote_callback, chg); @@ -4400,6 +4389,7 @@ int smblib_init(struct smb_charger *chg) INIT_WORK(&chg->vconn_oc_work, smblib_vconn_oc_work); INIT_DELAYED_WORK(&chg->otg_ss_done_work, smblib_otg_ss_done_work); INIT_DELAYED_WORK(&chg->icl_change_work, smblib_icl_change_work); + INIT_DELAYED_WORK(&chg->pl_enable_work, smblib_pl_enable_work); chg->fake_capacity = -EINVAL; switch (chg->mode) { diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h index 048e7c2b4091..2b09a5bbd1a1 100644 --- a/drivers/power/supply/qcom/smb-lib.h +++ b/drivers/power/supply/qcom/smb-lib.h @@ -56,7 +56,7 @@ enum print_reason { #define MICRO_USB_VOTER "MICRO_USB_VOTER" #define DEBUG_BOARD_VOTER "DEBUG_BOARD_VOTER" #define PD_SUSPEND_SUPPORTED_VOTER "PD_SUSPEND_SUPPORTED_VOTER" -#define PL_DELAY_HVDCP_VOTER "PL_DELAY_HVDCP_VOTER" +#define PL_DELAY_VOTER "PL_DELAY_VOTER" #define CTM_VOTER "CTM_VOTER" #define SW_QC3_VOTER "SW_QC3_VOTER" #define AICL_RERUN_VOTER "AICL_RERUN_VOTER" @@ -288,6 +288,7 @@ struct smb_charger { struct work_struct vconn_oc_work; struct delayed_work otg_ss_done_work; struct delayed_work icl_change_work; + struct delayed_work pl_enable_work; /* cached status */ int voltage_min_uv; @@ -491,6 +492,7 @@ int smblib_icl_override(struct smb_charger *chg, bool override); int smblib_set_icl_reduction(struct smb_charger *chg, int reduction_ua); int smblib_dp_dm(struct smb_charger *chg, int val); int smblib_rerun_aicl(struct smb_charger *chg); +int smblib_set_icl_current(struct smb_charger *chg, int icl_ua); int smblib_init(struct smb_charger *chg); int smblib_deinit(struct smb_charger *chg); diff --git a/drivers/power/supply/qcom/smb-reg.h b/drivers/power/supply/qcom/smb-reg.h index b79060094cf6..167666a8c548 100644 --- a/drivers/power/supply/qcom/smb-reg.h +++ b/drivers/power/supply/qcom/smb-reg.h @@ -919,6 +919,7 @@ enum { #define MISC_CFG_REG (MISC_BASE + 0x52) #define GSM_PA_ON_ADJ_SEL_BIT BIT(0) +#define STAT_PARALLEL_1400MA_EN_CFG_BIT BIT(3) #define TCC_DEBOUNCE_20MS_BIT BIT(5) #define SNARL_BARK_BITE_WD_CFG_REG (MISC_BASE + 0x53) diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 864f7f6a0d01..7488bb993d7a 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -246,6 +246,7 @@ enum power_supply_property { POWER_SUPPLY_PROP_DIE_HEALTH, POWER_SUPPLY_PROP_CONNECTOR_HEALTH, POWER_SUPPLY_PROP_CTM_CURRENT_MAX, + POWER_SUPPLY_PROP_HW_CURRENT_MAX, /* Local extensions of type int64_t */ POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT, /* Properties of type `const char *' */ |
