summaryrefslogtreecommitdiff
path: root/drivers/power/qcom-charger/smb-lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power/qcom-charger/smb-lib.c')
-rw-r--r--drivers/power/qcom-charger/smb-lib.c70
1 files changed, 51 insertions, 19 deletions
diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c
index bcdfdd459b3d..5785e42e0140 100644
--- a/drivers/power/qcom-charger/smb-lib.c
+++ b/drivers/power/qcom-charger/smb-lib.c
@@ -38,8 +38,8 @@
static bool is_secure(struct smb_charger *chg, int addr)
{
- /* assume everything above 0xC0 is secure */
- return (bool)((addr & 0xFF) >= 0xC0);
+ /* assume everything above 0xA0 is secure */
+ return (bool)((addr & 0xFF) >= 0xA0);
}
int smblib_read(struct smb_charger *chg, u16 addr, u8 *val)
@@ -152,7 +152,7 @@ static void smblib_split_fcc(struct smb_charger *chg, int total_ua,
int *master_ua, int *slave_ua)
{
int rc, jeita_cc_delta_ua, step_cc_delta_ua, effective_total_ua,
- hw_cc_delta_ua = 0;
+ slave_limited_ua, hw_cc_delta_ua = 0;
rc = smblib_get_step_cc_delta(chg, &step_cc_delta_ua);
if (rc < 0) {
@@ -172,7 +172,8 @@ static void smblib_split_fcc(struct smb_charger *chg, int total_ua,
}
effective_total_ua = max(0, total_ua + hw_cc_delta_ua);
- *slave_ua = (effective_total_ua * chg->pl.slave_pct) / 100;
+ slave_limited_ua = min(effective_total_ua, chg->input_limited_fcc_ua);
+ *slave_ua = (slave_limited_ua * chg->pl.slave_pct) / 100;
*slave_ua = (*slave_ua * chg->pl.taper_pct) / 100;
*master_ua = max(0, total_ua - *slave_ua);
}
@@ -470,9 +471,8 @@ static int try_rerun_apsd_for_hvdcp(struct smb_charger *chg)
return 0;
}
-static int smblib_update_usb_type(struct smb_charger *chg)
+static const struct apsd_result *smblib_update_usb_type(struct smb_charger *chg)
{
- int rc = 0;
const struct apsd_result *apsd_result;
/* if PD is active, APSD is disabled so won't have a valid result */
@@ -483,7 +483,7 @@ static int smblib_update_usb_type(struct smb_charger *chg)
apsd_result = smblib_get_apsd_result(chg);
chg->usb_psy_desc.type = apsd_result->pst;
- return rc;
+ return apsd_result;
}
static int smblib_notifier_call(struct notifier_block *nb,
@@ -592,7 +592,7 @@ static int smblib_fcc_vote_callback(struct votable *votable, void *data,
{
struct smb_charger *chg = data;
union power_supply_propval pval = {0, };
- int rc, master_fcc_ua = total_fcc_ua, slave_fcc_ua;
+ int rc, master_fcc_ua = total_fcc_ua, slave_fcc_ua = 0;
if (total_fcc_ua < 0)
return 0;
@@ -624,6 +624,11 @@ static int smblib_fcc_vote_callback(struct votable *votable, void *data,
return rc;
}
+ smblib_dbg(chg, PR_PARALLEL, "master_fcc=%d slave_fcc=%d distribution=(%d/%d)\n",
+ master_fcc_ua, slave_fcc_ua,
+ (master_fcc_ua * 100) / total_fcc_ua,
+ (slave_fcc_ua * 100) / total_fcc_ua);
+
return 0;
}
@@ -833,6 +838,9 @@ static int smblib_pl_disable_vote_callback(struct votable *votable, void *data,
return rc;
}
+ smblib_dbg(chg, PR_PARALLEL, "parallel charging %s\n",
+ pl_disable ? "disabled" : "enabled");
+
return 0;
}
@@ -1758,7 +1766,7 @@ int smblib_get_prop_typec_power_role(struct smb_charger *chg,
int smblib_get_prop_pd_allowed(struct smb_charger *chg,
union power_supply_propval *val)
{
- val->intval = get_effective_result_locked(chg->pd_allowed_votable);
+ val->intval = get_effective_result(chg->pd_allowed_votable);
return 0;
}
@@ -1784,6 +1792,19 @@ int smblib_get_prop_pd_in_hard_reset(struct smb_charger *chg,
return 0;
}
+int smblib_get_pe_start(struct smb_charger *chg,
+ union power_supply_propval *val)
+{
+ /*
+ * hvdcp timeout voter is the last one to allow pd. Use its vote
+ * to indicate start of pe engine
+ */
+ val->intval
+ = !get_client_vote_locked(chg->pd_disallowed_votable_indirect,
+ HVDCP_TIMEOUT_VOTER);
+ return 0;
+}
+
/*******************
* USB PSY SETTERS *
* *****************/
@@ -1954,6 +1975,13 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
smblib_update_usb_type(chg);
power_supply_changed(chg->usb_psy);
+ rc = smblib_masked_write(chg, TYPE_C_CFG_3_REG, EN_TRYSINK_MODE_BIT,
+ chg->pd_active ? 0 : EN_TRYSINK_MODE_BIT);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't set TRYSINK_MODE rc=%d\n", rc);
+ return rc;
+ }
+
return rc;
}
@@ -2187,12 +2215,14 @@ skip_dpdm_float:
}
#define USB_WEAK_INPUT_UA 1400000
+#define EFFICIENCY_PCT 80
irqreturn_t smblib_handle_icl_change(int irq, void *data)
{
struct smb_irq_data *irq_data = data;
struct smb_charger *chg = irq_data->parent_data;
int rc, icl_ua;
+ smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
rc = smblib_get_charge_param(chg, &chg->param.icl_stat, &icl_ua);
if (rc < 0) {
@@ -2200,11 +2230,18 @@ irqreturn_t smblib_handle_icl_change(int irq, void *data)
return IRQ_HANDLED;
}
- if (chg->mode == PARALLEL_MASTER)
- vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER,
- icl_ua >= USB_WEAK_INPUT_UA, 0);
+ if (chg->mode != PARALLEL_MASTER)
+ return IRQ_HANDLED;
- smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
+ chg->input_limited_fcc_ua = div64_s64(
+ (s64)icl_ua * MICRO_5V * EFFICIENCY_PCT,
+ (s64)get_effective_result(chg->fv_votable) * 100);
+
+ if (!get_effective_result(chg->pl_disable_votable))
+ rerun_election(chg->fcc_votable);
+
+ vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER,
+ icl_ua >= USB_WEAK_INPUT_UA, 0);
return IRQ_HANDLED;
}
@@ -2280,13 +2317,12 @@ static void smblib_handle_hvdcp_detect_done(struct smb_charger *chg,
#define HVDCP_DET_MS 2500
static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
{
- int rc;
const struct apsd_result *apsd_result;
if (!rising)
return;
- apsd_result = smblib_get_apsd_result(chg);
+ apsd_result = smblib_update_usb_type(chg);
switch (apsd_result->bit) {
case SDP_CHARGER_BIT:
case CDP_CHARGER_BIT:
@@ -2305,10 +2341,6 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
break;
}
- rc = smblib_update_usb_type(chg);
- if (rc < 0)
- smblib_err(chg, "Couldn't update usb type rc=%d\n", rc);
-
smblib_dbg(chg, PR_INTERRUPT, "IRQ: apsd-done rising; %s detected\n",
apsd_result->name);
}