summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2017-02-09 22:09:28 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2017-02-09 22:09:28 -0800
commit3252149cd27aaaf073ae31f1da6eb3eb2fd7d729 (patch)
treebd3c76dd1b622b430edd68aafeb8d65f4eb863ea /drivers
parentfa12840e3df6183283e410b905c6828c30482bfc (diff)
parent23d22ee4bf2441c51aae648e078ef7f4ddfa6bc1 (diff)
Merge "power: smb1351-charger: update drive to support parallel architecture"
Diffstat (limited to 'drivers')
-rw-r--r--drivers/power/supply/qcom/battery.c24
-rw-r--r--drivers/power/supply/qcom/qpnp-smb2.c14
-rw-r--r--drivers/power/supply/qcom/smb-lib.c159
-rw-r--r--drivers/power/supply/qcom/smb-lib.h3
-rw-r--r--drivers/power/supply/qcom/smb1351-charger.c158
5 files changed, 231 insertions, 127 deletions
diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c
index 34add97b55d2..86e1bc040266 100644
--- a/drivers/power/supply/qcom/battery.c
+++ b/drivers/power/supply/qcom/battery.c
@@ -33,6 +33,7 @@
#define TAPER_END_VOTER "TAPER_END_VOTER"
#define PL_TAPER_EARLY_BAD_VOTER "PL_TAPER_EARLY_BAD_VOTER"
#define PARALLEL_PSY_VOTER "PARALLEL_PSY_VOTER"
+#define PL_HW_ABSENT_VOTER "PL_HW_ABSENT_VOTER"
struct pl_data {
int pl_mode;
@@ -44,6 +45,7 @@ struct pl_data {
struct votable *pl_disable_votable;
struct votable *pl_awake_votable;
struct work_struct status_change_work;
+ struct work_struct pl_disable_forever_work;
struct delayed_work pl_taper_work;
struct power_supply *main_psy;
struct power_supply *pl_psy;
@@ -361,6 +363,15 @@ static int pl_fv_vote_callback(struct votable *votable, void *data,
return 0;
}
+static void pl_disable_forever_work(struct work_struct *work)
+{
+ struct pl_data *chip = container_of(work,
+ struct pl_data, pl_disable_forever_work);
+
+ /* Disable Parallel charger forever */
+ vote(chip->pl_disable_votable, PL_HW_ABSENT_VOTER, true, 0);
+}
+
static int pl_disable_vote_callback(struct votable *votable,
void *data, int pl_disable, const char *client)
{
@@ -372,6 +383,18 @@ static int pl_disable_vote_callback(struct votable *votable,
chip->taper_pct = 100;
if (!pl_disable) { /* enable */
+ rc = power_supply_get_property(chip->pl_psy,
+ POWER_SUPPLY_PROP_CHARGE_TYPE, &pval);
+ if (rc == -ENODEV) {
+ /*
+ * -ENODEV is returned only if parallel chip
+ * is not present in the system.
+ * Disable parallel charger forever.
+ */
+ schedule_work(&chip->pl_disable_forever_work);
+ return rc;
+ }
+
rerun_election(chip->fv_votable);
rerun_election(chip->fcc_votable);
/*
@@ -697,6 +720,7 @@ static int pl_init(void)
INIT_WORK(&chip->status_change_work, status_change_work);
INIT_DELAYED_WORK(&chip->pl_taper_work, pl_taper_work);
+ INIT_WORK(&chip->pl_disable_forever_work, pl_disable_forever_work);
rc = pl_register_notifier(chip);
if (rc < 0) {
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index 4e9d2894479a..16b7dd8c2ccd 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -385,6 +385,8 @@ static int smb2_parse_dt(struct smb2 *chip)
chg->micro_usb_mode = of_property_read_bool(node, "qcom,micro-usb");
+ chg->dcp_icl_ua = chip->dt.usb_icl_ua;
+
return 0;
}
@@ -1338,7 +1340,6 @@ static int smb2_init_hw(struct smb2 *chip)
return rc;
}
- chg->dcp_icl_ua = chip->dt.usb_icl_ua;
chg->boost_threshold_ua = chip->dt.boost_threshold_ua;
rc = smblib_read(chg, APSD_RESULT_STATUS_REG, &stat);
@@ -1350,12 +1351,9 @@ static int smb2_init_hw(struct smb2 *chip)
smblib_rerun_apsd_if_required(chg);
/* clear the ICL override if it is set */
- if (stat & ICL_OVERRIDE_LATCH_BIT) {
- rc = smblib_write(chg, CMD_APSD_REG, ICL_OVERRIDE_BIT);
- if (rc < 0) {
- pr_err("Couldn't disable ICL override rc=%d\n", rc);
- return rc;
- }
+ if (smblib_icl_override(chg, false) < 0) {
+ pr_err("Couldn't disable ICL override rc=%d\n", rc);
+ return rc;
}
/* votes must be cast before configuring software control */
@@ -1367,8 +1365,6 @@ static int smb2_init_hw(struct smb2 *chip)
DEFAULT_VOTER, true, chip->dt.fcc_ua);
vote(chg->fv_votable,
DEFAULT_VOTER, true, chip->dt.fv_uv);
- vote(chg->usb_icl_votable,
- DCP_VOTER, true, chip->dt.usb_icl_ua);
vote(chg->dc_icl_votable,
DEFAULT_VOTER, true, chip->dt.dc_icl_ua);
vote(chg->hvdcp_disable_votable_indirect, DEFAULT_VOTER,
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 16edf875de96..6e01ec6174d5 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -151,6 +151,31 @@ static int smblib_get_jeita_cc_delta(struct smb_charger *chg, int *cc_delta_ua)
return 0;
}
+int smblib_icl_override(struct smb_charger *chg, bool override)
+{
+ int rc;
+ bool override_status;
+ u8 stat;
+
+ rc = smblib_read(chg, APSD_RESULT_STATUS_REG, &stat);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't read APSD_RESULT_STATUS_REG rc=%d\n",
+ rc);
+ return rc;
+ }
+ override_status = (bool)(stat & ICL_OVERRIDE_LATCH_BIT);
+
+ if (override != override_status) {
+ rc = smblib_masked_write(chg, CMD_APSD_REG,
+ ICL_OVERRIDE_BIT, ICL_OVERRIDE_BIT);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't override ICL rc=%d\n", rc);
+ return rc;
+ }
+ }
+ return 0;
+}
+
/********************
* REGISTER GETTERS *
********************/
@@ -591,6 +616,7 @@ static void smblib_uusb_removal(struct smb_charger *chg)
/* 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_DISABLE_HVDCP_VOTER, true, 0);
cancel_delayed_work_sync(&chg->hvdcp_detect_work);
@@ -728,19 +754,33 @@ static int smblib_usb_icl_vote_callback(struct votable *votable, void *data,
{
struct smb_charger *chg = data;
int rc = 0;
- bool suspend = (icl_ua < USBIN_25MA);
+ bool suspend, override;
u8 icl_options = 0;
+ override = true;
+ /* remove override if no voters or type = SDP or CDP */
+ if (client == NULL
+ || chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB
+ || chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_CDP)
+ override = false;
+
+ suspend = false;
+ if (client && (icl_ua < USBIN_25MA))
+ suspend = true;
+
if (suspend)
goto out;
if (chg->usb_psy_desc.type != POWER_SUPPLY_TYPE_USB) {
- rc = smblib_set_charge_param(chg, &chg->param.usb_icl, icl_ua);
- if (rc < 0) {
- smblib_err(chg, "Couldn't set HC ICL rc=%d\n", rc);
- return rc;
+ if (client) {
+ rc = smblib_set_charge_param(chg, &chg->param.usb_icl,
+ icl_ua);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't set HC ICL rc=%d\n",
+ rc);
+ return rc;
+ }
}
-
goto out;
}
@@ -769,10 +809,14 @@ static int smblib_usb_icl_vote_callback(struct votable *votable, void *data,
}
out:
+ if (override)
+ icl_options |= USBIN_MODE_CHG_BIT;
+
rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
- CFG_USB3P0_SEL_BIT | USB51_MODE_BIT, icl_options);
+ CFG_USB3P0_SEL_BIT | USB51_MODE_BIT | USBIN_MODE_CHG_BIT,
+ icl_options);
if (rc < 0) {
- smblib_err(chg, "Couldn't set ICL opetions rc=%d\n", rc);
+ smblib_err(chg, "Couldn't set ICL options rc=%d\n", rc);
return rc;
}
@@ -783,6 +827,12 @@ out:
return rc;
}
+ rc = smblib_icl_override(chg, override);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't set ICL override rc=%d\n", rc);
+ return rc;
+ }
+
return rc;
}
@@ -1996,11 +2046,11 @@ int smblib_set_prop_usb_current_max(struct smb_charger *chg,
true, val->intval);
} else if (chg->system_suspend_supported) {
if (val->intval <= USBIN_25MA)
- rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
- true, val->intval);
+ rc = vote(chg->usb_icl_votable,
+ PD_SUSPEND_SUPPORTED_VOTER, true, val->intval);
else
- rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
- false, 0);
+ rc = vote(chg->usb_icl_votable,
+ PD_SUSPEND_SUPPORTED_VOTER, false, 0);
}
return rc;
}
@@ -2137,7 +2187,11 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
"Couldn't enable vconn on CC line rc=%d\n", rc);
return rc;
}
-
+ /*
+ * Enforce 500mA for PD until the real vote comes in later.
+ * It is guaranteed that pd_active is set prior to
+ * pd_current_max
+ */
rc = vote(chg->usb_icl_votable, PD_VOTER, true, USBIN_500MA);
if (rc < 0) {
smblib_err(chg, "Couldn't vote for USB ICL rc=%d\n",
@@ -2145,50 +2199,17 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
return rc;
}
+ /* remove DCP_VOTER */
rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
if (rc < 0) {
- smblib_err(chg, "Couldn't vote for USB ICL rc=%d\n",
- rc);
- return rc;
- }
-
- rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
- USBIN_MODE_CHG_BIT, USBIN_MODE_CHG_BIT);
- if (rc < 0) {
- smblib_err(chg,
- "Couldn't change USB mode rc=%d\n", rc);
- return rc;
- }
-
- rc = smblib_masked_write(chg, CMD_APSD_REG,
- ICL_OVERRIDE_BIT, ICL_OVERRIDE_BIT);
- if (rc < 0) {
- smblib_err(chg,
- "Couldn't override APSD rc=%d\n", rc);
- return rc;
- }
- } else {
- rc = vote(chg->usb_icl_votable, DCP_VOTER, true,
- chg->dcp_icl_ua);
- if (rc < 0) {
- smblib_err(chg, "Couldn't vote for USB ICL rc=%d\n",
- rc);
+ smblib_err(chg, "Couldn't unvote DCP rc=%d\n", rc);
return rc;
}
- rc = smblib_masked_write(chg, CMD_APSD_REG,
- ICL_OVERRIDE_BIT, 0);
+ /* remove USB_PSY_VOTER */
+ rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
if (rc < 0) {
- smblib_err(chg,
- "Couldn't override APSD rc=%d\n", rc);
- return rc;
- }
-
- rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
- USBIN_MODE_CHG_BIT, 0);
- if (rc < 0) {
- smblib_err(chg,
- "Couldn't change USB mode rc=%d\n", rc);
+ smblib_err(chg, "Couldn't unvote USB_PSY rc=%d\n", rc);
return rc;
}
}
@@ -2782,6 +2803,9 @@ static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg,
if (chg->mode == PARALLEL_MASTER)
vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, true, 0);
+ /* QC authentication done, parallel charger can be enabled now */
+ vote(chg->pl_disable_votable, PL_DISABLE_HVDCP_VOTER, false, 0);
+
/* the APSD done handler will set the USB supply type */
apsd_result = smblib_get_apsd_result(chg);
smblib_dbg(chg, PR_INTERRUPT, "IRQ: hvdcp-3p0-auth-done rising; %s detected\n",
@@ -2791,6 +2815,8 @@ static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg,
static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg,
bool rising, bool qc_charger)
{
+ const struct apsd_result *apsd_result = smblib_update_usb_type(chg);
+
/* Hold off PD only until hvdcp 2.0 detection timeout */
if (rising) {
vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
@@ -2798,6 +2824,24 @@ static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg,
if (get_effective_result(chg->pd_disallowed_votable_indirect))
/* could be a legacy cable, try doing hvdcp */
try_rerun_apsd_for_hvdcp(chg);
+
+ /*
+ * HVDCP detection timeout done
+ * If adapter is not QC2.0/QC3.0 - it is a plain old DCP.
+ */
+ if (!qc_charger && (apsd_result->bit & DCP_CHARGER_BIT))
+ /* 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_DISABLE_HVDCP_VOTER,
+ false, 0);
}
smblib_dbg(chg, PR_INTERRUPT, "IRQ: smblib_handle_hvdcp_check_timeout %s\n",
@@ -2923,12 +2967,19 @@ static void typec_source_removal(struct smb_charger *chg)
/* clear USB ICL vote for PD_VOTER */
rc = vote(chg->usb_icl_votable, PD_VOTER, false, 0);
if (rc < 0)
- smblib_err(chg, "Couldn't un-vote for USB ICL rc=%d\n", rc);
+ smblib_err(chg, "Couldn't un-vote PD from USB ICL rc=%d\n", rc);
/* clear USB ICL vote for USB_PSY_VOTER */
rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
if (rc < 0)
- smblib_err(chg, "Couldn't un-vote for USB ICL rc=%d\n", rc);
+ smblib_err(chg,
+ "Couldn't un-vote USB_PSY from USB ICL rc=%d\n", rc);
+
+ /* clear USB ICL vote for DCP_VOTER */
+ rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
+ if (rc < 0)
+ smblib_err(chg,
+ "Couldn't un-vote DCP from USB ICL rc=%d\n", rc);
}
static void typec_source_insertion(struct smb_charger *chg)
@@ -2957,6 +3008,7 @@ static void smblib_handle_typec_removal(struct smb_charger *chg)
vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, true, 0);
vote(chg->pd_disallowed_votable_indirect, LEGACY_CABLE_VOTER, true, 0);
vote(chg->pd_disallowed_votable_indirect, VBUS_CC_SHORT_VOTER, true, 0);
+ vote(chg->pl_disable_votable, PL_DISABLE_HVDCP_VOTER, true, 0);
/* reset votes from vbus_cc_short */
vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER,
@@ -3514,6 +3566,7 @@ static int smblib_create_votables(struct smb_charger *chg)
return rc;
}
vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, true, 0);
+ vote(chg->pl_disable_votable, PL_DISABLE_HVDCP_VOTER, true, 0);
chg->usb_suspend_votable = create_votable("USB_SUSPEND", VOTE_SET_ANY,
smblib_usb_suspend_vote_callback,
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index e341484bc2ec..a0190ae44f29 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -52,6 +52,8 @@ enum print_reason {
#define HVDCP_INDIRECT_VOTER "HVDCP_INDIRECT_VOTER"
#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_DISABLE_HVDCP_VOTER "PL_DISABLE_HVDCP_VOTER"
#define VCONN_MAX_ATTEMPTS 3
#define OTG_MAX_ATTEMPTS 3
@@ -405,6 +407,7 @@ void smblib_suspend_on_debug_battery(struct smb_charger *chg);
int smblib_rerun_apsd_if_required(struct smb_charger *chg);
int smblib_get_prop_fcc_delta(struct smb_charger *chg,
union power_supply_propval *val);
+int smblib_icl_override(struct smb_charger *chg, bool override);
int smblib_init(struct smb_charger *chg);
int smblib_deinit(struct smb_charger *chg);
diff --git a/drivers/power/supply/qcom/smb1351-charger.c b/drivers/power/supply/qcom/smb1351-charger.c
index 0c2943c7f2df..d0cf37b0613a 100644
--- a/drivers/power/supply/qcom/smb1351-charger.c
+++ b/drivers/power/supply/qcom/smb1351-charger.c
@@ -461,7 +461,7 @@ struct smb1351_charger {
int parallel_pin_polarity_setting;
bool parallel_charger;
- bool parallel_charger_present;
+ bool parallel_charger_suspended;
bool bms_controlled_charging;
bool apsd_rerun;
bool usbin_ov;
@@ -873,9 +873,9 @@ static int smb1351_regulator_init(struct smb1351_charger *chip)
chip->otg_vreg.rdesc.owner = THIS_MODULE;
chip->otg_vreg.rdesc.type = REGULATOR_VOLTAGE;
chip->otg_vreg.rdesc.ops = &smb1351_chg_otg_reg_ops;
- chip->otg_vreg.rdesc.name =
+ chip->otg_vreg.rdesc.name =
chip->dev->of_node->name;
- chip->otg_vreg.rdesc.of_match =
+ chip->otg_vreg.rdesc.of_match =
chip->dev->of_node->name;
cfg.dev = chip->dev;
@@ -1409,34 +1409,27 @@ static int smb1351_battery_get_property(struct power_supply *psy,
static enum power_supply_property smb1351_parallel_properties[] = {
POWER_SUPPLY_PROP_CHARGING_ENABLED,
POWER_SUPPLY_PROP_STATUS,
- POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_CURRENT_MAX,
POWER_SUPPLY_PROP_VOLTAGE_MAX,
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+ POWER_SUPPLY_PROP_CHARGE_TYPE,
POWER_SUPPLY_PROP_PARALLEL_MODE,
};
-static int smb1351_parallel_set_chg_present(struct smb1351_charger *chip,
- int present)
+static int smb1351_parallel_set_chg_suspend(struct smb1351_charger *chip,
+ int suspend)
{
int rc;
u8 reg, mask = 0;
- if (present == chip->parallel_charger_present) {
- pr_debug("present %d -> %d, skipping\n",
- chip->parallel_charger_present, present);
+ if (chip->parallel_charger_suspended == suspend) {
+ pr_debug("Skip same state request suspended = %d suspend=%d\n",
+ chip->parallel_charger_suspended, !suspend);
return 0;
}
- if (present) {
- /* Check if SMB1351 is present */
- rc = smb1351_read_reg(chip, CHG_REVISION_REG, &reg);
- if (rc) {
- pr_debug("Failed to detect smb1351-parallel-charger, may be absent\n");
- return -ENODEV;
- }
-
+ if (!suspend) {
rc = smb_chip_get_version(chip);
if (rc) {
pr_err("Couldn't get version rc = %d\n", rc);
@@ -1476,6 +1469,26 @@ static int smb1351_parallel_set_chg_present(struct smb1351_charger *chip,
}
}
+ /* control USB suspend via command bits */
+ rc = smb1351_masked_write(chip, VARIOUS_FUNC_REG,
+ APSD_EN_BIT | SUSPEND_MODE_CTRL_BIT,
+ SUSPEND_MODE_CTRL_BY_I2C);
+ if (rc) {
+ pr_err("Couldn't set USB suspend rc=%d\n", rc);
+ return rc;
+ }
+
+ /*
+ * When present is being set force USB suspend, start charging
+ * only when POWER_SUPPLY_PROP_CURRENT_MAX is set.
+ */
+ rc = smb1351_usb_suspend(chip, CURRENT, true);
+ if (rc) {
+ pr_err("failed to suspend rc=%d\n", rc);
+ return rc;
+ }
+ chip->usb_psy_ma = SUSPEND_CURRENT_MA;
+
/* set chg en by pin active low */
reg = chip->parallel_pin_polarity_setting | USBCS_CTRL_BY_I2C;
rc = smb1351_masked_write(chip, CHG_PIN_EN_CTRL_REG,
@@ -1485,15 +1498,6 @@ static int smb1351_parallel_set_chg_present(struct smb1351_charger *chip,
return rc;
}
- /* control USB suspend via command bits */
- rc = smb1351_masked_write(chip, VARIOUS_FUNC_REG,
- SUSPEND_MODE_CTRL_BIT,
- SUSPEND_MODE_CTRL_BY_I2C);
- if (rc) {
- pr_err("Couldn't set USB suspend rc=%d\n", rc);
- return rc;
- }
-
/*
* setup USB 2.0/3.0 detection and USB 500/100
* command polarity
@@ -1508,23 +1512,21 @@ static int smb1351_parallel_set_chg_present(struct smb1351_charger *chip,
return rc;
}
- /* set fast charging current limit */
- chip->target_fastchg_current_max_ma = SMB1351_CHG_FAST_MIN_MA;
rc = smb1351_fastchg_current_set(chip,
chip->target_fastchg_current_max_ma);
if (rc) {
pr_err("Couldn't set fastchg current rc=%d\n", rc);
return rc;
}
- }
+ chip->parallel_charger_suspended = false;
+ } else {
+ rc = smb1351_usb_suspend(chip, CURRENT, true);
+ if (rc)
+ pr_debug("failed to suspend rc=%d\n", rc);
- chip->parallel_charger_present = present;
- /*
- * When present is being set force USB suspend, start charging
- * only when POWER_SUPPLY_PROP_CURRENT_MAX is set.
- */
- chip->usb_psy_ma = SUSPEND_CURRENT_MA;
- smb1351_usb_suspend(chip, CURRENT, true);
+ chip->usb_psy_ma = SUSPEND_CURRENT_MA;
+ chip->parallel_charger_suspended = true;
+ }
return 0;
}
@@ -1564,6 +1566,31 @@ static bool smb1351_is_input_current_limited(struct smb1351_charger *chip)
return !!(reg & IRQ_IC_LIMIT_STATUS_BIT);
}
+static bool smb1351_is_usb_present(struct smb1351_charger *chip)
+{
+ int rc;
+ union power_supply_propval val = {0, };
+
+ if (!chip->usb_psy)
+ chip->usb_psy = power_supply_get_by_name("usb");
+ if (!chip->usb_psy) {
+ pr_err("USB psy not found\n");
+ return false;
+ }
+
+ rc = power_supply_get_property(chip->usb_psy,
+ POWER_SUPPLY_PROP_ONLINE, &val);
+ if (rc < 0) {
+ pr_err("Failed to get present property rc=%d\n", rc);
+ return false;
+ }
+
+ if (val.intval)
+ return true;
+
+ return false;
+}
+
static int smb1351_parallel_set_property(struct power_supply *psy,
enum power_supply_property prop,
const union power_supply_propval *val)
@@ -1577,38 +1604,30 @@ static int smb1351_parallel_set_property(struct power_supply *psy,
*CHG EN is controlled by pin in the parallel charging.
*Use suspend if disable charging by command.
*/
- if (chip->parallel_charger_present)
+ if (!chip->parallel_charger_suspended)
rc = smb1351_usb_suspend(chip, USER, !val->intval);
break;
- case POWER_SUPPLY_PROP_PRESENT:
- rc = smb1351_parallel_set_chg_present(chip, val->intval);
+ case POWER_SUPPLY_PROP_INPUT_SUSPEND:
+ rc = smb1351_parallel_set_chg_suspend(chip, val->intval);
break;
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
- if (chip->parallel_charger_present) {
- chip->target_fastchg_current_max_ma =
+ chip->target_fastchg_current_max_ma =
val->intval / 1000;
+ if (!chip->parallel_charger_suspended)
rc = smb1351_fastchg_current_set(chip,
chip->target_fastchg_current_max_ma);
- }
break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
- if (chip->parallel_charger_present) {
- index = smb1351_get_closest_usb_setpoint(
- val->intval / 1000);
- chip->usb_psy_ma = usb_chg_current[index];
+ index = smb1351_get_closest_usb_setpoint(val->intval / 1000);
+ chip->usb_psy_ma = usb_chg_current[index];
+ if (!chip->parallel_charger_suspended)
rc = smb1351_set_usb_chg_current(chip,
chip->usb_psy_ma);
- }
break;
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
- if (chip->parallel_charger_present &&
- (chip->vfloat_mv != val->intval)) {
+ chip->vfloat_mv = val->intval / 1000;
+ if (!chip->parallel_charger_suspended)
rc = smb1351_float_voltage_set(chip, val->intval);
- if (!rc)
- chip->vfloat_mv = val->intval;
- } else {
- chip->vfloat_mv = val->intval;
- }
break;
default:
return -EINVAL;
@@ -1638,41 +1657,49 @@ static int smb1351_parallel_get_property(struct power_supply *psy,
val->intval = !chip->usb_suspended_status;
break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
- if (chip->parallel_charger_present)
+ if (!chip->parallel_charger_suspended)
val->intval = chip->usb_psy_ma * 1000;
else
val->intval = 0;
break;
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
- val->intval = chip->vfloat_mv;
+ if (!chip->parallel_charger_suspended)
+ val->intval = chip->vfloat_mv;
+ else
+ val->intval = 0;
break;
- case POWER_SUPPLY_PROP_PRESENT:
- val->intval = chip->parallel_charger_present;
+ case POWER_SUPPLY_PROP_CHARGE_TYPE:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
+ /* Check if SMB1351 is present */
+ if (smb1351_is_usb_present(chip)) {
+ val->intval = smb1351_get_prop_charge_type(chip);
+ if (val->intval == POWER_SUPPLY_CHARGE_TYPE_UNKNOWN) {
+ pr_debug("Failed to charge type, charger may be absent\n");
+ return -ENODEV;
+ }
+ }
break;
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
- if (chip->parallel_charger_present)
+ if (!chip->parallel_charger_suspended)
val->intval = chip->fastchg_current_max_ma * 1000;
else
val->intval = 0;
break;
case POWER_SUPPLY_PROP_STATUS:
- if (chip->parallel_charger_present)
+ if (!chip->parallel_charger_suspended)
val->intval = smb1351_get_prop_batt_status(chip);
else
val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
break;
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
- if (chip->parallel_charger_present)
+ if (!chip->parallel_charger_suspended)
val->intval =
smb1351_is_input_current_limited(chip) ? 1 : 0;
else
val->intval = 0;
break;
case POWER_SUPPLY_PROP_PARALLEL_MODE:
- if (chip->parallel_charger_present)
- val->intval = POWER_SUPPLY_PARALLEL_USBIN_USBIN;
- else
- val->intval = POWER_SUPPLY_PARALLEL_NONE;
+ val->intval = POWER_SUPPLY_PARALLEL_USBIN_USBIN;
break;
default:
return -EINVAL;
@@ -3142,6 +3169,7 @@ static int smb1351_parallel_charger_probe(struct i2c_client *client,
chip->client = client;
chip->dev = &client->dev;
chip->parallel_charger = true;
+ chip->parallel_charger_suspended = true;
chip->usb_suspended_status = of_property_read_bool(node,
"qcom,charging-disabled");