Merge "qcom: smb1351: update CHARGING_ENABLE reporting logic"
This commit is contained in:
commit
9e160e7f8b
5 changed files with 107 additions and 86 deletions
|
@ -13,6 +13,7 @@
|
|||
#define pr_fmt(fmt) "QCOM-BATT: %s: " fmt, __func__
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
@ -36,6 +37,7 @@
|
|||
#define PL_HW_ABSENT_VOTER "PL_HW_ABSENT_VOTER"
|
||||
#define PL_VOTER "PL_VOTER"
|
||||
#define RESTRICT_CHG_VOTER "RESTRICT_CHG_VOTER"
|
||||
#define ICL_CHANGE_VOTER "ICL_CHANGE_VOTER"
|
||||
|
||||
struct pl_data {
|
||||
int pl_mode;
|
||||
|
@ -56,8 +58,9 @@ struct pl_data {
|
|||
struct power_supply *main_psy;
|
||||
struct power_supply *pl_psy;
|
||||
struct power_supply *batt_psy;
|
||||
struct power_supply *usb_psy;
|
||||
int charge_type;
|
||||
int main_settled_ua;
|
||||
int total_settled_ua;
|
||||
int pl_settled_ua;
|
||||
struct class qcom_batt_class;
|
||||
struct wakeup_source *pl_ws;
|
||||
|
@ -93,15 +96,10 @@ enum {
|
|||
********/
|
||||
static void split_settled(struct pl_data *chip)
|
||||
{
|
||||
int slave_icl_pct;
|
||||
int slave_icl_pct, total_current_ua;
|
||||
int slave_ua = 0, main_settled_ua = 0;
|
||||
union power_supply_propval pval = {0, };
|
||||
int rc;
|
||||
|
||||
/* TODO some parallel chargers do not have a fine ICL resolution. For
|
||||
* them implement a psy interface which returns the closest lower ICL
|
||||
* for desired split
|
||||
*/
|
||||
int rc, total_settled_ua = 0;
|
||||
|
||||
if ((chip->pl_mode != POWER_SUPPLY_PL_USBIN_USBIN)
|
||||
&& (chip->pl_mode != POWER_SUPPLY_PL_USBIN_USBIN_EXT))
|
||||
|
@ -123,12 +121,31 @@ static void split_settled(struct pl_data *chip)
|
|||
slave_icl_pct = max(0, chip->slave_pct - 10);
|
||||
slave_ua = ((main_settled_ua + chip->pl_settled_ua)
|
||||
* slave_icl_pct) / 100;
|
||||
total_settled_ua = main_settled_ua + chip->pl_settled_ua;
|
||||
}
|
||||
|
||||
/* ICL_REDUCTION on main could be 0mA when pl is disabled */
|
||||
pval.intval = slave_ua;
|
||||
total_current_ua = get_effective_result_locked(chip->usb_icl_votable);
|
||||
if (total_current_ua < 0) {
|
||||
if (!chip->usb_psy)
|
||||
chip->usb_psy = power_supply_get_by_name("usb");
|
||||
if (!chip->usb_psy) {
|
||||
pr_err("Couldn't get usbpsy while splitting settled\n");
|
||||
return;
|
||||
}
|
||||
/* no client is voting, so get the total current from charger */
|
||||
rc = power_supply_get_property(chip->usb_psy,
|
||||
POWER_SUPPLY_PROP_HW_CURRENT_MAX, &pval);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't get max current rc=%d\n", rc);
|
||||
return;
|
||||
}
|
||||
total_current_ua = pval.intval;
|
||||
}
|
||||
|
||||
pval.intval = total_current_ua - slave_ua;
|
||||
/* Set ICL on main charger */
|
||||
rc = power_supply_set_property(chip->main_psy,
|
||||
POWER_SUPPLY_PROP_ICL_REDUCTION, &pval);
|
||||
POWER_SUPPLY_PROP_CURRENT_MAX, &pval);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't change slave suspend state rc=%d\n", rc);
|
||||
return;
|
||||
|
@ -143,10 +160,12 @@ static void split_settled(struct pl_data *chip)
|
|||
return;
|
||||
}
|
||||
|
||||
/* main_settled_ua represents the total capability of adapter */
|
||||
if (!chip->main_settled_ua)
|
||||
chip->main_settled_ua = main_settled_ua;
|
||||
chip->total_settled_ua = total_settled_ua;
|
||||
chip->pl_settled_ua = slave_ua;
|
||||
|
||||
pl_dbg(chip, PR_PARALLEL,
|
||||
"Split total_current_ua=%d main_settled_ua=%d slave_ua=%d\n",
|
||||
total_current_ua, main_settled_ua, slave_ua);
|
||||
}
|
||||
|
||||
static ssize_t version_show(struct class *c, struct class_attribute *attr,
|
||||
|
@ -214,6 +233,10 @@ static ssize_t restrict_chg_store(struct class *c, struct class_attribute *attr,
|
|||
|
||||
chip->restricted_charging_enabled = !!val;
|
||||
|
||||
/* disable parallel charger in case of restricted charging */
|
||||
vote(chip->pl_disable_votable, RESTRICT_CHG_VOTER,
|
||||
chip->restricted_charging_enabled, 0);
|
||||
|
||||
vote(chip->fcc_votable, RESTRICT_CHG_VOTER,
|
||||
chip->restricted_charging_enabled,
|
||||
chip->restricted_current);
|
||||
|
@ -488,9 +511,11 @@ static int pl_fv_vote_callback(struct votable *votable, void *data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define ICL_STEP_UV 25000
|
||||
static int usb_icl_vote_callback(struct votable *votable, void *data,
|
||||
int icl_ua, const char *client)
|
||||
{
|
||||
int rc;
|
||||
struct pl_data *chip = data;
|
||||
union power_supply_propval pval = {0, };
|
||||
|
||||
|
@ -500,9 +525,41 @@ static int usb_icl_vote_callback(struct votable *votable, void *data,
|
|||
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);
|
||||
/*
|
||||
* Disable parallel for new ICL vote - the call to split_settled will
|
||||
* ensure that all the input current limit gets assigned to the main
|
||||
* charger.
|
||||
*/
|
||||
vote(chip->pl_disable_votable, ICL_CHANGE_VOTER, true, 0);
|
||||
|
||||
/* rerun AICL */
|
||||
/* get the settled current */
|
||||
rc = power_supply_get_property(chip->main_psy,
|
||||
POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
|
||||
&pval);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't get aicl settled value rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* rerun AICL if new ICL is above settled ICL */
|
||||
if (icl_ua > pval.intval) {
|
||||
/* set a lower ICL */
|
||||
pval.intval = max(pval.intval - ICL_STEP_UV, ICL_STEP_UV);
|
||||
power_supply_set_property(chip->main_psy,
|
||||
POWER_SUPPLY_PROP_CURRENT_MAX,
|
||||
&pval);
|
||||
/* wait for ICL change */
|
||||
msleep(100);
|
||||
|
||||
pval.intval = icl_ua;
|
||||
power_supply_set_property(chip->main_psy,
|
||||
POWER_SUPPLY_PROP_CURRENT_MAX,
|
||||
&pval);
|
||||
/* wait for ICL change */
|
||||
msleep(100);
|
||||
}
|
||||
vote(chip->pl_disable_votable, ICL_CHANGE_VOTER, false, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -528,7 +585,7 @@ static int pl_disable_vote_callback(struct votable *votable,
|
|||
int rc;
|
||||
|
||||
chip->taper_pct = 100;
|
||||
chip->main_settled_ua = 0;
|
||||
chip->total_settled_ua = 0;
|
||||
chip->pl_settled_ua = 0;
|
||||
|
||||
if (!pl_disable) { /* enable */
|
||||
|
@ -733,6 +790,7 @@ static void handle_main_charge_type(struct pl_data *chip)
|
|||
static void handle_settled_icl_change(struct pl_data *chip)
|
||||
{
|
||||
union power_supply_propval pval = {0, };
|
||||
int new_total_settled_ua;
|
||||
int rc;
|
||||
|
||||
if (get_effective_result(chip->pl_disable_votable))
|
||||
|
@ -752,9 +810,15 @@ static void handle_settled_icl_change(struct pl_data *chip)
|
|||
return;
|
||||
}
|
||||
|
||||
new_total_settled_ua = pval.intval + chip->pl_settled_ua;
|
||||
pl_dbg(chip, PR_PARALLEL,
|
||||
"total_settled_ua=%d settled_ua=%d new_total_settled_ua=%d\n",
|
||||
chip->total_settled_ua, pval.intval,
|
||||
new_total_settled_ua);
|
||||
|
||||
/* If ICL change is small skip splitting */
|
||||
if (abs((chip->main_settled_ua - chip->pl_settled_ua)
|
||||
- pval.intval) > MIN_ICL_CHANGE_DELTA_UA)
|
||||
if (abs(new_total_settled_ua - chip->total_settled_ua)
|
||||
> MIN_ICL_CHANGE_DELTA_UA)
|
||||
split_settled(chip);
|
||||
} else {
|
||||
rerun_election(chip->fcc_votable);
|
||||
|
|
|
@ -414,6 +414,7 @@ static enum power_supply_property smb2_usb_props[] = {
|
|||
POWER_SUPPLY_PROP_BOOST_CURRENT,
|
||||
POWER_SUPPLY_PROP_PE_START,
|
||||
POWER_SUPPLY_PROP_CTM_CURRENT_MAX,
|
||||
POWER_SUPPLY_PROP_HW_CURRENT_MAX,
|
||||
};
|
||||
|
||||
static int smb2_usb_get_prop(struct power_supply *psy,
|
||||
|
@ -502,6 +503,9 @@ static int smb2_usb_get_prop(struct power_supply *psy,
|
|||
case POWER_SUPPLY_PROP_CTM_CURRENT_MAX:
|
||||
val->intval = get_client_vote(chg->usb_icl_votable, CTM_VOTER);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_HW_CURRENT_MAX:
|
||||
rc = smblib_get_charge_current(chg, &val->intval);
|
||||
break;
|
||||
default:
|
||||
pr_err("get prop %d is not supported in usb\n", psp);
|
||||
rc = -EINVAL;
|
||||
|
@ -610,7 +614,6 @@ static int smb2_init_usb_psy(struct smb2 *chip)
|
|||
|
||||
static enum power_supply_property smb2_usb_main_props[] = {
|
||||
POWER_SUPPLY_PROP_VOLTAGE_MAX,
|
||||
POWER_SUPPLY_PROP_ICL_REDUCTION,
|
||||
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
|
||||
POWER_SUPPLY_PROP_TYPE,
|
||||
POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
|
||||
|
@ -635,9 +638,6 @@ static int smb2_usb_main_get_prop(struct power_supply *psy,
|
|||
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
|
||||
rc = smblib_get_charge_param(chg, &chg->param.fv, &val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_ICL_REDUCTION:
|
||||
val->intval = chg->icl_reduction_ua;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
|
||||
rc = smblib_get_charge_param(chg, &chg->param.fcc,
|
||||
&val->intval);
|
||||
|
@ -681,9 +681,6 @@ static int smb2_usb_main_set_prop(struct power_supply *psy,
|
|||
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
|
||||
rc = smblib_set_charge_param(chg, &chg->param.fv, val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_ICL_REDUCTION:
|
||||
rc = smblib_set_icl_reduction(chg, val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
|
||||
rc = smblib_set_charge_param(chg, &chg->param.fcc, val->intval);
|
||||
break;
|
||||
|
|
|
@ -696,13 +696,6 @@ static void smblib_uusb_removal(struct smb_charger *chg)
|
|||
if (rc < 0)
|
||||
smblib_err(chg,
|
||||
"Couldn't un-vote DCP from USB ICL rc=%d\n", rc);
|
||||
|
||||
/* clear USB ICL vote for PL_USBIN_USBIN_VOTER */
|
||||
rc = vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0);
|
||||
if (rc < 0)
|
||||
smblib_err(chg,
|
||||
"Couldn't un-vote PL_USBIN_USBIN from USB ICL rc=%d\n",
|
||||
rc);
|
||||
}
|
||||
|
||||
void smblib_suspend_on_debug_battery(struct smb_charger *chg)
|
||||
|
@ -871,8 +864,7 @@ int smblib_set_icl_current(struct smb_charger *chg, int icl_ua)
|
|||
goto enable_icl_changed_interrupt;
|
||||
}
|
||||
} else {
|
||||
rc = smblib_set_charge_param(chg, &chg->param.usb_icl,
|
||||
icl_ua - chg->icl_reduction_ua);
|
||||
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);
|
||||
goto enable_icl_changed_interrupt;
|
||||
|
@ -890,7 +882,7 @@ override_suspend_config:
|
|||
/* For std cable with type = SDP never override */
|
||||
override = false;
|
||||
else if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_CDP
|
||||
&& icl_ua - chg->icl_reduction_ua == 1500000)
|
||||
&& icl_ua == 1500000)
|
||||
/*
|
||||
* For std cable with type = CDP override only if
|
||||
* current is not 1500mA
|
||||
|
@ -1793,6 +1785,10 @@ int smblib_set_prop_system_temp_level(struct smb_charger *chg,
|
|||
return -EINVAL;
|
||||
|
||||
chg->system_temp_level = val->intval;
|
||||
/* disable parallel charge in case of system temp level */
|
||||
vote(chg->pl_disable_votable, THERMAL_DAEMON_VOTER,
|
||||
chg->system_temp_level ? true : false, 0);
|
||||
|
||||
if (chg->system_temp_level == chg->thermal_levels)
|
||||
return vote(chg->chg_disable_votable,
|
||||
THERMAL_DAEMON_VOTER, true, 0);
|
||||
|
@ -2027,7 +2023,7 @@ int smblib_get_prop_usb_online(struct smb_charger *chg,
|
|||
int rc = 0;
|
||||
u8 stat;
|
||||
|
||||
if (get_client_vote(chg->usb_icl_votable, USER_VOTER) == 0) {
|
||||
if (get_client_vote_locked(chg->usb_icl_votable, USER_VOTER) == 0) {
|
||||
val->intval = false;
|
||||
return rc;
|
||||
}
|
||||
|
@ -2605,13 +2601,6 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
|
|||
"Couldn't un-vote DCP from USB ICL rc=%d\n",
|
||||
rc);
|
||||
|
||||
/* clear USB ICL vote for PL_USBIN_USBIN_VOTER */
|
||||
rc = vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0);
|
||||
if (rc < 0)
|
||||
smblib_err(chg,
|
||||
"Couldn't un-vote PL_USBIN_USBIN from USB ICL rc=%d\n",
|
||||
rc);
|
||||
|
||||
/* remove USB_PSY_VOTER */
|
||||
rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
|
||||
if (rc < 0) {
|
||||
|
@ -2866,15 +2855,21 @@ int smblib_get_prop_fcc_delta(struct smb_charger *chg,
|
|||
#define TYPEC_DEFAULT_CURRENT_MA 900000
|
||||
#define TYPEC_MEDIUM_CURRENT_MA 1500000
|
||||
#define TYPEC_HIGH_CURRENT_MA 3000000
|
||||
static int smblib_get_charge_current(struct smb_charger *chg,
|
||||
int smblib_get_charge_current(struct smb_charger *chg,
|
||||
int *total_current_ua)
|
||||
{
|
||||
const struct apsd_result *apsd_result = smblib_update_usb_type(chg);
|
||||
union power_supply_propval val = {0, };
|
||||
int rc, typec_source_rd, current_ua;
|
||||
int rc = 0, typec_source_rd, current_ua;
|
||||
bool non_compliant;
|
||||
u8 stat5;
|
||||
|
||||
if (chg->pd_active) {
|
||||
*total_current_ua =
|
||||
get_client_vote_locked(chg->usb_icl_votable, PD_VOTER);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat5);
|
||||
if (rc < 0) {
|
||||
smblib_err(chg, "Couldn't read TYPE_C_STATUS_5 rc=%d\n", rc);
|
||||
|
@ -2949,39 +2944,12 @@ static int smblib_get_charge_current(struct smb_charger *chg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int smblib_set_icl_reduction(struct smb_charger *chg, int reduction_ua)
|
||||
{
|
||||
int current_ua, rc;
|
||||
|
||||
if (reduction_ua == 0) {
|
||||
vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0);
|
||||
} else {
|
||||
/*
|
||||
* No usb_icl voter means we are defaulting to hw chosen
|
||||
* max limit. We need a vote from s/w to enforce the reduction.
|
||||
*/
|
||||
if (get_effective_result(chg->usb_icl_votable) == -EINVAL) {
|
||||
rc = smblib_get_charge_current(chg, ¤t_ua);
|
||||
if (rc < 0) {
|
||||
pr_err("Failed to get ICL rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, true,
|
||||
current_ua);
|
||||
}
|
||||
}
|
||||
|
||||
chg->icl_reduction_ua = reduction_ua;
|
||||
|
||||
return rerun_election(chg->usb_icl_votable);
|
||||
}
|
||||
|
||||
/************************
|
||||
* PARALLEL PSY GETTERS *
|
||||
************************/
|
||||
|
||||
int smblib_get_prop_slave_current_now(struct smb_charger *chg,
|
||||
union power_supply_propval *pval)
|
||||
union power_supply_propval *pval)
|
||||
{
|
||||
if (IS_ERR_OR_NULL(chg->iio.batt_i_chan))
|
||||
chg->iio.batt_i_chan = iio_channel_get(chg->dev, "batt_i");
|
||||
|
@ -3044,7 +3012,7 @@ irqreturn_t smblib_handle_chg_state_change(int irq, void *data)
|
|||
rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
|
||||
if (rc < 0) {
|
||||
smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
|
||||
rc);
|
||||
rc);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -3584,12 +3552,6 @@ static void typec_source_removal(struct smb_charger *chg)
|
|||
smblib_err(chg,
|
||||
"Couldn't un-vote DCP from USB ICL rc=%d\n", rc);
|
||||
|
||||
/* clear USB ICL vote for PL_USBIN_USBIN_VOTER */
|
||||
rc = vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0);
|
||||
if (rc < 0)
|
||||
smblib_err(chg,
|
||||
"Couldn't un-vote PL_USBIN_USBIN from USB ICL rc=%d\n",
|
||||
rc);
|
||||
}
|
||||
|
||||
static void typec_source_insertion(struct smb_charger *chg)
|
||||
|
|
|
@ -322,8 +322,6 @@ struct smb_charger {
|
|||
/* extcon for VBUS / ID notification to USB for uUSB */
|
||||
struct extcon_dev *extcon;
|
||||
|
||||
int icl_reduction_ua;
|
||||
|
||||
/* qnovo */
|
||||
int qnovo_fcc_ua;
|
||||
int qnovo_fv_uv;
|
||||
|
@ -489,10 +487,10 @@ 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_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_get_charge_current(struct smb_charger *chg, int *total_current_ua);
|
||||
|
||||
int smblib_init(struct smb_charger *chg);
|
||||
int smblib_deinit(struct smb_charger *chg);
|
||||
|
|
|
@ -1655,7 +1655,7 @@ static int smb1351_parallel_get_property(struct power_supply *psy,
|
|||
|
||||
switch (prop) {
|
||||
case POWER_SUPPLY_PROP_CHARGING_ENABLED:
|
||||
val->intval = !chip->usb_suspended_status;
|
||||
val->intval = !chip->parallel_charger_suspended;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CURRENT_MAX:
|
||||
if (!chip->parallel_charger_suspended)
|
||||
|
|
Loading…
Add table
Reference in a new issue