Merge "power: smb-lib: Update the FLOAT detection logic"
This commit is contained in:
commit
88d5f45f9b
3 changed files with 132 additions and 31 deletions
|
@ -1641,6 +1641,13 @@ static int smb2_init_hw(struct smb2 *chip)
|
|||
return rc;
|
||||
}
|
||||
|
||||
rc = smblib_read(chg, USBIN_OPTIONS_2_CFG_REG, &chg->float_cfg);
|
||||
if (rc < 0) {
|
||||
dev_err(chg->dev, "Couldn't read float charger options rc=%d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
switch (chip->dt.chg_inhibit_thr_mv) {
|
||||
case 50:
|
||||
rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
|
||||
|
|
|
@ -514,10 +514,17 @@ static const struct apsd_result *smblib_update_usb_type(struct smb_charger *chg)
|
|||
const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
|
||||
|
||||
/* if PD is active, APSD is disabled so won't have a valid result */
|
||||
if (chg->pd_active)
|
||||
if (chg->pd_active) {
|
||||
chg->real_charger_type = POWER_SUPPLY_TYPE_USB_PD;
|
||||
else
|
||||
} else {
|
||||
/*
|
||||
* Update real charger type only if its not FLOAT
|
||||
* detected as as SDP
|
||||
*/
|
||||
if (!(apsd_result->pst == POWER_SUPPLY_TYPE_USB_FLOAT &&
|
||||
chg->real_charger_type == POWER_SUPPLY_TYPE_USB))
|
||||
chg->real_charger_type = apsd_result->pst;
|
||||
}
|
||||
|
||||
smblib_dbg(chg, PR_MISC, "APSD=%s PD=%d\n",
|
||||
apsd_result->name, chg->pd_active);
|
||||
|
@ -785,6 +792,7 @@ static int set_sdp_current(struct smb_charger *chg, int icl_ua)
|
|||
{
|
||||
int rc;
|
||||
u8 icl_options;
|
||||
const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
|
||||
|
||||
/* power source is SDP */
|
||||
switch (icl_ua) {
|
||||
|
@ -809,6 +817,21 @@ static int set_sdp_current(struct smb_charger *chg, int icl_ua)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB &&
|
||||
apsd_result->pst == POWER_SUPPLY_TYPE_USB_FLOAT) {
|
||||
/*
|
||||
* change the float charger configuration to SDP, if this
|
||||
* is the case of SDP being detected as FLOAT
|
||||
*/
|
||||
rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
|
||||
FORCE_FLOAT_SDP_CFG_BIT, FORCE_FLOAT_SDP_CFG_BIT);
|
||||
if (rc < 0) {
|
||||
smblib_err(chg, "Couldn't set float ICL options rc=%d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
|
||||
CFG_USB3P0_SEL_BIT | USB51_MODE_BIT, icl_options);
|
||||
if (rc < 0) {
|
||||
|
@ -2402,6 +2425,31 @@ int smblib_get_prop_die_health(struct smb_charger *chg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define SDP_CURRENT_UA 500000
|
||||
#define CDP_CURRENT_UA 1500000
|
||||
#define DCP_CURRENT_UA 1500000
|
||||
#define HVDCP_CURRENT_UA 3000000
|
||||
#define TYPEC_DEFAULT_CURRENT_UA 900000
|
||||
#define TYPEC_MEDIUM_CURRENT_UA 1500000
|
||||
#define TYPEC_HIGH_CURRENT_UA 3000000
|
||||
static int get_rp_based_dcp_current(struct smb_charger *chg, int typec_mode)
|
||||
{
|
||||
int rp_ua;
|
||||
|
||||
switch (typec_mode) {
|
||||
case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
|
||||
rp_ua = TYPEC_HIGH_CURRENT_UA;
|
||||
break;
|
||||
case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM:
|
||||
case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT:
|
||||
/* fall through */
|
||||
default:
|
||||
rp_ua = DCP_CURRENT_UA;
|
||||
}
|
||||
|
||||
return rp_ua;
|
||||
}
|
||||
|
||||
/*******************
|
||||
* USB PSY SETTERS *
|
||||
* *****************/
|
||||
|
@ -2419,14 +2467,54 @@ int smblib_set_prop_pd_current_max(struct smb_charger *chg,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int smblib_handle_usb_current(struct smb_charger *chg,
|
||||
int usb_current)
|
||||
{
|
||||
int rc = 0, rp_ua, typec_mode;
|
||||
|
||||
if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_FLOAT) {
|
||||
if (usb_current == -ETIMEDOUT) {
|
||||
/*
|
||||
* Valid FLOAT charger, report the current based
|
||||
* of Rp
|
||||
*/
|
||||
typec_mode = smblib_get_prop_typec_mode(chg);
|
||||
rp_ua = get_rp_based_dcp_current(chg, typec_mode);
|
||||
rc = vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER,
|
||||
true, rp_ua);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
} else {
|
||||
/*
|
||||
* FLOAT charger detected as SDP by USB driver,
|
||||
* charge with the requested current and update the
|
||||
* real_charger_type
|
||||
*/
|
||||
chg->real_charger_type = POWER_SUPPLY_TYPE_USB;
|
||||
rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
|
||||
true, usb_current);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
rc = vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER,
|
||||
false, 0);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
|
||||
true, usb_current);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int smblib_set_prop_usb_current_max(struct smb_charger *chg,
|
||||
const union power_supply_propval *val)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!chg->pd_active) {
|
||||
rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
|
||||
true, val->intval);
|
||||
rc = smblib_handle_usb_current(chg, val->intval);
|
||||
} else if (chg->system_suspend_supported) {
|
||||
if (val->intval <= USBIN_25MA)
|
||||
rc = vote(chg->usb_icl_votable,
|
||||
|
@ -2875,14 +2963,6 @@ int smblib_get_prop_fcc_delta(struct smb_charger *chg,
|
|||
/***********************
|
||||
* USB MAIN PSY SETTERS *
|
||||
*************************/
|
||||
|
||||
#define SDP_CURRENT_UA 500000
|
||||
#define CDP_CURRENT_UA 1500000
|
||||
#define DCP_CURRENT_UA 1500000
|
||||
#define HVDCP_CURRENT_UA 3000000
|
||||
#define TYPEC_DEFAULT_CURRENT_UA 900000
|
||||
#define TYPEC_MEDIUM_CURRENT_UA 1500000
|
||||
#define TYPEC_HIGH_CURRENT_UA 3000000
|
||||
int smblib_get_charge_current(struct smb_charger *chg,
|
||||
int *total_current_ua)
|
||||
{
|
||||
|
@ -3438,24 +3518,6 @@ static void smblib_handle_hvdcp_detect_done(struct smb_charger *chg,
|
|||
rising ? "rising" : "falling");
|
||||
}
|
||||
|
||||
static int get_rp_based_dcp_current(struct smb_charger *chg, int typec_mode)
|
||||
{
|
||||
int rp_ua;
|
||||
|
||||
switch (typec_mode) {
|
||||
case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
|
||||
rp_ua = TYPEC_HIGH_CURRENT_UA;
|
||||
break;
|
||||
case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM:
|
||||
case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT:
|
||||
/* fall through */
|
||||
default:
|
||||
rp_ua = DCP_CURRENT_UA;
|
||||
}
|
||||
|
||||
return rp_ua;
|
||||
}
|
||||
|
||||
static void smblib_force_legacy_icl(struct smb_charger *chg, int pst)
|
||||
{
|
||||
int typec_mode;
|
||||
|
@ -3481,11 +3543,17 @@ static void smblib_force_legacy_icl(struct smb_charger *chg, int pst)
|
|||
vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 1500000);
|
||||
break;
|
||||
case POWER_SUPPLY_TYPE_USB_DCP:
|
||||
case POWER_SUPPLY_TYPE_USB_FLOAT:
|
||||
typec_mode = smblib_get_prop_typec_mode(chg);
|
||||
rp_ua = get_rp_based_dcp_current(chg, typec_mode);
|
||||
vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, rp_ua);
|
||||
break;
|
||||
case POWER_SUPPLY_TYPE_USB_FLOAT:
|
||||
/*
|
||||
* limit ICL to 100mA, the USB driver will enumerate to check
|
||||
* if this is a SDP and appropriately set the current
|
||||
*/
|
||||
vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 100000);
|
||||
break;
|
||||
case POWER_SUPPLY_TYPE_USB_HVDCP:
|
||||
case POWER_SUPPLY_TYPE_USB_HVDCP_3:
|
||||
vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 3000000);
|
||||
|
@ -3680,6 +3748,13 @@ static void smblib_handle_typec_removal(struct smb_charger *chg)
|
|||
chg->pd_hard_reset = 0;
|
||||
chg->typec_legacy_valid = false;
|
||||
|
||||
/* write back the default FLOAT charger configuration */
|
||||
rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
|
||||
(u8)FLOAT_OPTIONS_MASK, chg->float_cfg);
|
||||
if (rc < 0)
|
||||
smblib_err(chg, "Couldn't write float charger options rc=%d\n",
|
||||
rc);
|
||||
|
||||
/* reset back to 120mS tCC debounce */
|
||||
rc = smblib_masked_write(chg, MISC_CFG_REG, TCC_DEBOUNCE_20MS_BIT, 0);
|
||||
if (rc < 0)
|
||||
|
@ -3774,6 +3849,24 @@ static void smblib_handle_rp_change(struct smb_charger *chg, int typec_mode)
|
|||
&& (apsd->pst != POWER_SUPPLY_TYPE_USB_FLOAT))
|
||||
return;
|
||||
|
||||
/*
|
||||
* if APSD indicates FLOAT and the USB stack had detected SDP,
|
||||
* do not respond to Rp changes as we do not confirm that its
|
||||
* a legacy cable
|
||||
*/
|
||||
if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB)
|
||||
return;
|
||||
/*
|
||||
* We want the ICL vote @ 100mA for a FLOAT charger
|
||||
* until the detection by the USB stack is complete.
|
||||
* Ignore the Rp changes unless there is a
|
||||
* pre-existing valid vote.
|
||||
*/
|
||||
if (apsd->pst == POWER_SUPPLY_TYPE_USB_FLOAT &&
|
||||
get_client_vote(chg->usb_icl_votable,
|
||||
LEGACY_UNKNOWN_VOTER) <= 100000)
|
||||
return;
|
||||
|
||||
/*
|
||||
* handle Rp change for DCP/FLOAT/OCP.
|
||||
* Update the current only if the Rp is different from
|
||||
|
|
|
@ -326,6 +326,7 @@ struct smb_charger {
|
|||
int typec_mode;
|
||||
int usb_icl_change_irq_enabled;
|
||||
u32 jeita_status;
|
||||
u8 float_cfg;
|
||||
|
||||
/* workaround flag */
|
||||
u32 wa_flags;
|
||||
|
|
Loading…
Add table
Reference in a new issue