summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2017-04-05 12:17:03 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-04-05 12:17:03 -0700
commit8f91cc1fa4ed7dcb509d0cb13a04157bcdb18449 (patch)
tree4dac9ed9c4d83f98561e7f41ae39a5ad322dd370
parent6e2c59ad47bee17aee211971e082e8986ae8db2e (diff)
parent17d9f0383d607a8c8856d6d347a1b9997e356644 (diff)
Merge "power_supply: add HW_CURRENT_MAX power_supply property"
-rw-r--r--drivers/power/power_supply_sysfs.c1
-rw-r--r--drivers/power/supply/qcom/battery.c41
-rw-r--r--drivers/power/supply/qcom/qpnp-smb2.c19
-rw-r--r--drivers/power/supply/qcom/smb-lib.c116
-rw-r--r--drivers/power/supply/qcom/smb-lib.h4
-rw-r--r--drivers/power/supply/qcom/smb-reg.h1
-rw-r--r--include/linux/power_supply.h1
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 *' */