Merge "power: smb-lib: Add support to detect weak charger"
This commit is contained in:
commit
1cbfeeaf0d
5 changed files with 102 additions and 19 deletions
|
@ -266,6 +266,10 @@ module_param_named(
|
|||
debug_mask, __debug_mask, int, S_IRUSR | S_IWUSR
|
||||
);
|
||||
|
||||
static int __weak_chg_icl_ua = 500000;
|
||||
module_param_named(
|
||||
weak_chg_icl_ua, __weak_chg_icl_ua, int, S_IRUSR | S_IWUSR);
|
||||
|
||||
#define MICRO_1P5A 1500000
|
||||
#define MICRO_P1A 100000
|
||||
#define OTG_DEFAULT_DEGLITCH_TIME_MS 50
|
||||
|
@ -2109,7 +2113,7 @@ static struct smb_irq_info smb2_irqs[] = {
|
|||
[SWITCH_POWER_OK_IRQ] = {
|
||||
.name = "switcher-power-ok",
|
||||
.handler = smblib_handle_switcher_power_ok,
|
||||
.storm_data = {true, 1000, 3},
|
||||
.storm_data = {true, 1000, 8},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -2303,6 +2307,7 @@ static int smb2_probe(struct platform_device *pdev)
|
|||
chg->dev = &pdev->dev;
|
||||
chg->param = v1_params;
|
||||
chg->debug_mask = &__debug_mask;
|
||||
chg->weak_chg_icl_ua = &__weak_chg_icl_ua;
|
||||
chg->mode = PARALLEL_MASTER;
|
||||
chg->irq_info = smb2_irqs;
|
||||
chg->name = "PMI";
|
||||
|
|
|
@ -630,6 +630,8 @@ int smblib_mapping_cc_delta_from_field_value(struct smb_chg_param *param,
|
|||
static void smblib_uusb_removal(struct smb_charger *chg)
|
||||
{
|
||||
int rc;
|
||||
struct smb_irq_data *data;
|
||||
struct storm_watch *wdata;
|
||||
|
||||
cancel_delayed_work_sync(&chg->pl_enable_work);
|
||||
|
||||
|
@ -641,8 +643,16 @@ static void smblib_uusb_removal(struct smb_charger *chg)
|
|||
rc);
|
||||
}
|
||||
|
||||
if (chg->wa_flags & BOOST_BACK_WA)
|
||||
vote(chg->usb_icl_votable, BOOST_BACK_VOTER, false, 0);
|
||||
if (chg->wa_flags & BOOST_BACK_WA) {
|
||||
data = chg->irq_info[SWITCH_POWER_OK_IRQ].irq_data;
|
||||
if (data) {
|
||||
wdata = &data->storm_data;
|
||||
update_storm_count(wdata, WEAK_CHG_STORM_COUNT);
|
||||
vote(chg->usb_icl_votable, BOOST_BACK_VOTER, false, 0);
|
||||
vote(chg->usb_icl_votable, WEAK_CHARGER_VOTER,
|
||||
false, 0);
|
||||
}
|
||||
}
|
||||
vote(chg->pl_disable_votable, PL_DELAY_VOTER, true, 0);
|
||||
vote(chg->awake_votable, PL_DELAY_VOTER, false, 0);
|
||||
|
||||
|
@ -3138,6 +3148,8 @@ void smblib_usb_plugin_hard_reset_locked(struct smb_charger *chg)
|
|||
int rc;
|
||||
u8 stat;
|
||||
bool vbus_rising;
|
||||
struct smb_irq_data *data;
|
||||
struct storm_watch *wdata;
|
||||
|
||||
rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat);
|
||||
if (rc < 0) {
|
||||
|
@ -3151,8 +3163,18 @@ void smblib_usb_plugin_hard_reset_locked(struct smb_charger *chg)
|
|||
smblib_cc2_sink_removal_exit(chg);
|
||||
} else {
|
||||
smblib_cc2_sink_removal_enter(chg);
|
||||
if (chg->wa_flags & BOOST_BACK_WA)
|
||||
vote(chg->usb_icl_votable, BOOST_BACK_VOTER, false, 0);
|
||||
if (chg->wa_flags & BOOST_BACK_WA) {
|
||||
data = chg->irq_info[SWITCH_POWER_OK_IRQ].irq_data;
|
||||
if (data) {
|
||||
wdata = &data->storm_data;
|
||||
update_storm_count(wdata,
|
||||
WEAK_CHG_STORM_COUNT);
|
||||
vote(chg->usb_icl_votable, BOOST_BACK_VOTER,
|
||||
false, 0);
|
||||
vote(chg->usb_icl_votable, WEAK_CHARGER_VOTER,
|
||||
false, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
power_supply_changed(chg->usb_psy);
|
||||
|
@ -3166,6 +3188,8 @@ void smblib_usb_plugin_locked(struct smb_charger *chg)
|
|||
int rc;
|
||||
u8 stat;
|
||||
bool vbus_rising;
|
||||
struct smb_irq_data *data;
|
||||
struct storm_watch *wdata;
|
||||
|
||||
rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat);
|
||||
if (rc < 0) {
|
||||
|
@ -3202,8 +3226,18 @@ void smblib_usb_plugin_locked(struct smb_charger *chg)
|
|||
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);
|
||||
if (chg->wa_flags & BOOST_BACK_WA) {
|
||||
data = chg->irq_info[SWITCH_POWER_OK_IRQ].irq_data;
|
||||
if (data) {
|
||||
wdata = &data->storm_data;
|
||||
update_storm_count(wdata,
|
||||
WEAK_CHG_STORM_COUNT);
|
||||
vote(chg->usb_icl_votable, BOOST_BACK_VOTER,
|
||||
false, 0);
|
||||
vote(chg->usb_icl_votable, WEAK_CHARGER_VOTER,
|
||||
false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (chg->dpdm_reg && regulator_is_enabled(chg->dpdm_reg)) {
|
||||
smblib_dbg(chg, PR_MISC, "disabling DPDM regulator\n");
|
||||
|
@ -3582,6 +3616,8 @@ static void typec_sink_removal(struct smb_charger *chg)
|
|||
static void smblib_handle_typec_removal(struct smb_charger *chg)
|
||||
{
|
||||
int rc;
|
||||
struct smb_irq_data *data;
|
||||
struct storm_watch *wdata;
|
||||
|
||||
chg->cc2_detach_wa_active = false;
|
||||
|
||||
|
@ -3593,8 +3629,16 @@ static void smblib_handle_typec_removal(struct smb_charger *chg)
|
|||
rc);
|
||||
}
|
||||
|
||||
if (chg->wa_flags & BOOST_BACK_WA)
|
||||
vote(chg->usb_icl_votable, BOOST_BACK_VOTER, false, 0);
|
||||
if (chg->wa_flags & BOOST_BACK_WA) {
|
||||
data = chg->irq_info[SWITCH_POWER_OK_IRQ].irq_data;
|
||||
if (data) {
|
||||
wdata = &data->storm_data;
|
||||
update_storm_count(wdata, WEAK_CHG_STORM_COUNT);
|
||||
vote(chg->usb_icl_votable, BOOST_BACK_VOTER, false, 0);
|
||||
vote(chg->usb_icl_votable, WEAK_CHARGER_VOTER,
|
||||
false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* reset APSD voters */
|
||||
vote(chg->apsd_disable_votable, PD_HARD_RESET_VOTER, false, 0);
|
||||
|
@ -3826,10 +3870,13 @@ static void smblib_bb_removal_work(struct work_struct *work)
|
|||
}
|
||||
|
||||
#define BOOST_BACK_UNVOTE_DELAY_MS 750
|
||||
#define BOOST_BACK_STORM_COUNT 3
|
||||
#define WEAK_CHG_STORM_COUNT 8
|
||||
irqreturn_t smblib_handle_switcher_power_ok(int irq, void *data)
|
||||
{
|
||||
struct smb_irq_data *irq_data = data;
|
||||
struct smb_charger *chg = irq_data->parent_data;
|
||||
struct storm_watch *wdata = &irq_data->storm_data;
|
||||
int rc, usb_icl;
|
||||
u8 stat;
|
||||
|
||||
|
@ -3851,16 +3898,32 @@ irqreturn_t smblib_handle_switcher_power_ok(int irq, void *data)
|
|||
return IRQ_HANDLED;
|
||||
|
||||
if (is_storming(&irq_data->storm_data)) {
|
||||
smblib_err(chg, "Reverse boost detected: voting 0mA to suspend input\n");
|
||||
vote(chg->usb_icl_votable, BOOST_BACK_VOTER, true, 0);
|
||||
vote(chg->awake_votable, BOOST_BACK_VOTER, true, 0);
|
||||
/*
|
||||
* Remove the boost-back vote after a delay, to avoid
|
||||
* permanently suspending the input if the boost-back condition
|
||||
* is unintentionally hit.
|
||||
*/
|
||||
schedule_delayed_work(&chg->bb_removal_work,
|
||||
msecs_to_jiffies(BOOST_BACK_UNVOTE_DELAY_MS));
|
||||
/* This could be a weak charger reduce ICL */
|
||||
if (!is_client_vote_enabled(chg->usb_icl_votable,
|
||||
WEAK_CHARGER_VOTER)) {
|
||||
smblib_err(chg,
|
||||
"Weak charger detected: voting %dmA ICL\n",
|
||||
*chg->weak_chg_icl_ua / 1000);
|
||||
vote(chg->usb_icl_votable, WEAK_CHARGER_VOTER,
|
||||
true, *chg->weak_chg_icl_ua);
|
||||
/*
|
||||
* reset storm data and set the storm threshold
|
||||
* to 3 for reverse boost detection.
|
||||
*/
|
||||
update_storm_count(wdata, BOOST_BACK_STORM_COUNT);
|
||||
} else {
|
||||
smblib_err(chg,
|
||||
"Reverse boost detected: voting 0mA to suspend input\n");
|
||||
vote(chg->usb_icl_votable, BOOST_BACK_VOTER, true, 0);
|
||||
vote(chg->awake_votable, BOOST_BACK_VOTER, true, 0);
|
||||
/*
|
||||
* Remove the boost-back vote after a delay, to avoid
|
||||
* permanently suspending the input if the boost-back
|
||||
* condition is unintentionally hit.
|
||||
*/
|
||||
schedule_delayed_work(&chg->bb_removal_work,
|
||||
msecs_to_jiffies(BOOST_BACK_UNVOTE_DELAY_MS));
|
||||
}
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
|
|
@ -64,9 +64,12 @@ enum print_reason {
|
|||
#define BATT_PROFILE_VOTER "BATT_PROFILE_VOTER"
|
||||
#define OTG_DELAY_VOTER "OTG_DELAY_VOTER"
|
||||
#define USBIN_I_VOTER "USBIN_I_VOTER"
|
||||
#define WEAK_CHARGER_VOTER "WEAK_CHARGER_VOTER"
|
||||
|
||||
#define VCONN_MAX_ATTEMPTS 3
|
||||
#define OTG_MAX_ATTEMPTS 3
|
||||
#define BOOST_BACK_STORM_COUNT 3
|
||||
#define WEAK_CHG_STORM_COUNT 8
|
||||
|
||||
enum smb_mode {
|
||||
PARALLEL_MASTER = 0,
|
||||
|
@ -230,6 +233,7 @@ struct smb_charger {
|
|||
struct smb_chg_freq chg_freq;
|
||||
int smb_version;
|
||||
int otg_delay_ms;
|
||||
int *weak_chg_icl_ua;
|
||||
|
||||
/* locks */
|
||||
struct mutex lock;
|
||||
|
|
|
@ -64,3 +64,13 @@ void reset_storm_count(struct storm_watch *data)
|
|||
data->storm_count = 0;
|
||||
mutex_unlock(&data->storm_lock);
|
||||
}
|
||||
|
||||
void update_storm_count(struct storm_watch *data, int max_count)
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
mutex_lock(&data->storm_lock);
|
||||
data->max_storm_count = max_count;
|
||||
mutex_unlock(&data->storm_lock);
|
||||
}
|
||||
|
|
|
@ -37,4 +37,5 @@ struct storm_watch {
|
|||
|
||||
bool is_storming(struct storm_watch *data);
|
||||
void reset_storm_count(struct storm_watch *data);
|
||||
void update_storm_count(struct storm_watch *data, int max_count);
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue