Merge "qcom-charger: update qc charger detection for PMICv2"
This commit is contained in:
commit
8e23ae41f3
4 changed files with 110 additions and 72 deletions
|
@ -983,9 +983,11 @@ static int smb2_init_hw(struct smb2 *chip)
|
|||
|
||||
/* votes must be cast before configuring software control */
|
||||
vote(chg->pl_disable_votable,
|
||||
USBIN_ICL_VOTER, true, 0);
|
||||
PL_INDIRECT_VOTER, true, 0);
|
||||
vote(chg->pl_disable_votable,
|
||||
CHG_STATE_VOTER, true, 0);
|
||||
vote(chg->pl_disable_votable,
|
||||
PARALLEL_PSY_VOTER, true, 0);
|
||||
vote(chg->usb_suspend_votable,
|
||||
DEFAULT_VOTER, chip->dt.no_battery, 0);
|
||||
vote(chg->dc_suspend_votable,
|
||||
|
@ -1100,6 +1102,7 @@ static int smb2_init_hw(struct smb2 *chip)
|
|||
|
||||
static int smb2_setup_wa_flags(struct smb2 *chip)
|
||||
{
|
||||
struct smb_charger *chg = &chip->chg;
|
||||
struct pmic_revid_data *pmic_rev_id;
|
||||
struct device_node *revid_dev_node;
|
||||
|
||||
|
@ -1122,6 +1125,8 @@ static int smb2_setup_wa_flags(struct smb2 *chip)
|
|||
|
||||
switch (pmic_rev_id->pmic_subtype) {
|
||||
case PMICOBALT_SUBTYPE:
|
||||
if (pmic_rev_id->rev4 == PMICOBALT_V1P1_REV4) /* PMI rev 1.1 */
|
||||
chg->wa_flags |= QC_CHARGER_DETECTION_WA_BIT;
|
||||
break;
|
||||
default:
|
||||
pr_err("PMIC subtype %d not supported\n",
|
||||
|
|
|
@ -521,7 +521,7 @@ static int smblib_fcc_max_vote_callback(struct votable *votable, void *data,
|
|||
{
|
||||
struct smb_charger *chg = data;
|
||||
|
||||
return vote(chg->fcc_votable, FCC_MAX_RESULT, true, fcc_ua);
|
||||
return vote(chg->fcc_votable, FCC_MAX_RESULT_VOTER, true, fcc_ua);
|
||||
}
|
||||
|
||||
static int smblib_fcc_vote_callback(struct votable *votable, void *data,
|
||||
|
@ -731,6 +731,17 @@ static int smblib_chg_disable_vote_callback(struct votable *votable, void *data,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smblib_pl_enable_indirect_vote_callback(struct votable *votable,
|
||||
void *data, int chg_enable, const char *client)
|
||||
{
|
||||
struct smb_charger *chg = data;
|
||||
|
||||
vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, !chg_enable, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************
|
||||
* OTG REGULATOR *
|
||||
*****************/
|
||||
|
@ -1144,13 +1155,14 @@ int smblib_set_prop_system_temp_level(struct smb_charger *chg,
|
|||
|
||||
chg->system_temp_level = val->intval;
|
||||
if (chg->system_temp_level == chg->thermal_levels)
|
||||
return vote(chg->chg_disable_votable, THERMAL_DAEMON, true, 0);
|
||||
return vote(chg->chg_disable_votable,
|
||||
THERMAL_DAEMON_VOTER, true, 0);
|
||||
|
||||
vote(chg->chg_disable_votable, THERMAL_DAEMON, false, 0);
|
||||
vote(chg->chg_disable_votable, THERMAL_DAEMON_VOTER, false, 0);
|
||||
if (chg->system_temp_level == 0)
|
||||
return vote(chg->fcc_votable, THERMAL_DAEMON, false, 0);
|
||||
return vote(chg->fcc_votable, THERMAL_DAEMON_VOTER, false, 0);
|
||||
|
||||
vote(chg->fcc_votable, THERMAL_DAEMON, true,
|
||||
vote(chg->fcc_votable, THERMAL_DAEMON_VOTER, true,
|
||||
chg->thermal_mitigation[chg->system_temp_level]);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1589,7 +1601,11 @@ int smblib_set_prop_usb_voltage_min(struct smb_charger *chg,
|
|||
return rc;
|
||||
}
|
||||
|
||||
chg->voltage_min_uv = val->intval;
|
||||
if (chg->mode == PARALLEL_MASTER)
|
||||
vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER,
|
||||
min_uv > MICRO_5V, 0);
|
||||
|
||||
chg->voltage_min_uv = min_uv;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1607,7 +1623,7 @@ int smblib_set_prop_usb_voltage_max(struct smb_charger *chg,
|
|||
return rc;
|
||||
}
|
||||
|
||||
chg->voltage_max_uv = val->intval;
|
||||
chg->voltage_max_uv = max_uv;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1875,49 +1891,23 @@ skip_dpdm_float:
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
#define MICRO_5P5V 5500000
|
||||
#define USB_WEAK_INPUT_MA 1500000
|
||||
static bool is_icl_pl_ready(struct smb_charger *chg)
|
||||
{
|
||||
union power_supply_propval pval = {0, };
|
||||
int icl_ma;
|
||||
int rc;
|
||||
|
||||
rc = smblib_get_prop_usb_voltage_now(chg, &pval);
|
||||
if (rc < 0) {
|
||||
dev_err(chg->dev, "Couldn't get prop usb voltage rc=%d\n", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pval.intval <= MICRO_5P5V) {
|
||||
rc = smblib_get_charge_param(chg,
|
||||
&chg->param.icl_stat, &icl_ma);
|
||||
if (rc < 0) {
|
||||
dev_err(chg->dev, "Couldn't get ICL status rc=%d\n",
|
||||
rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (icl_ma < USB_WEAK_INPUT_MA)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Always enable parallel charging when USB INPUT is higher than 5V
|
||||
* regardless of the AICL results. Assume chargers above 5V are strong
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define USB_WEAK_INPUT_MA 1400000
|
||||
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 icl_ma;
|
||||
int rc;
|
||||
|
||||
rc = smblib_get_charge_param(chg, &chg->param.icl_stat, &icl_ma);
|
||||
if (rc < 0) {
|
||||
dev_err(chg->dev, "Couldn't get ICL status rc=%d\n", rc);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if (chg->mode == PARALLEL_MASTER)
|
||||
vote(chg->pl_disable_votable, USBIN_ICL_VOTER,
|
||||
!is_icl_pl_ready(chg), 0);
|
||||
vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER,
|
||||
icl_ma >= USB_WEAK_INPUT_MA, 0);
|
||||
|
||||
smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
|
||||
|
||||
|
@ -1954,12 +1944,27 @@ static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg,
|
|||
if (!rising)
|
||||
return;
|
||||
|
||||
if (chg->mode == PARALLEL_MASTER)
|
||||
vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, true, 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",
|
||||
apsd_result->name);
|
||||
}
|
||||
|
||||
static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg,
|
||||
bool rising, bool qc_charger)
|
||||
{
|
||||
if (rising && !qc_charger) {
|
||||
vote(chg->pd_allowed_votable, DEFAULT_VOTER, true, 0);
|
||||
power_supply_changed(chg->usb_psy);
|
||||
}
|
||||
|
||||
smblib_dbg(chg, PR_INTERRUPT, "IRQ: smblib_handle_hvdcp_check_timeout %s\n",
|
||||
rising ? "rising" : "falling");
|
||||
}
|
||||
|
||||
/* triggers when HVDCP is detected */
|
||||
static void smblib_handle_hvdcp_detect_done(struct smb_charger *chg,
|
||||
bool rising)
|
||||
|
@ -1991,8 +1996,9 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
|
|||
vote(chg->pd_allowed_votable, DEFAULT_VOTER, true, 0);
|
||||
break;
|
||||
case DCP_CHARGER_BIT:
|
||||
schedule_delayed_work(&chg->hvdcp_detect_work,
|
||||
msecs_to_jiffies(HVDCP_DET_MS));
|
||||
if (chg->wa_flags & QC_CHARGER_DETECTION_WA_BIT)
|
||||
schedule_delayed_work(&chg->hvdcp_detect_work,
|
||||
msecs_to_jiffies(HVDCP_DET_MS));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -2026,6 +2032,10 @@ irqreturn_t smblib_handle_usb_source_change(int irq, void *data)
|
|||
smblib_handle_hvdcp_detect_done(chg,
|
||||
(bool)(stat & QC_CHARGER_BIT));
|
||||
|
||||
smblib_handle_hvdcp_check_timeout(chg,
|
||||
(bool)(stat & HVDCP_CHECK_TIMEOUT_BIT),
|
||||
(bool)(stat & QC_CHARGER_BIT));
|
||||
|
||||
smblib_handle_hvdcp_3p0_auth_done(chg,
|
||||
(bool)(stat & QC_AUTH_DONE_STATUS_BIT));
|
||||
|
||||
|
@ -2079,8 +2089,9 @@ static void smblib_handle_typec_debounce_done(struct smb_charger *chg,
|
|||
!rising || sink_attached, 0);
|
||||
|
||||
if (!rising || sink_attached) {
|
||||
/* icl votes to disable parallel charging */
|
||||
vote(chg->pl_disable_votable, USBIN_ICL_VOTER, true, 0);
|
||||
/* 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);
|
||||
/* reset taper_end voter here */
|
||||
vote(chg->pl_disable_votable, TAPER_END_VOTER, false, 0);
|
||||
}
|
||||
|
@ -2105,11 +2116,6 @@ irqreturn_t smblib_handle_usb_typec_change(int irq, void *data)
|
|||
}
|
||||
smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n", stat);
|
||||
|
||||
if (stat & TYPEC_VBUS_ERROR_STATUS_BIT) {
|
||||
dev_err(chg->dev, "IRQ: vbus-error rising\n");
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
smblib_handle_typec_cc(chg,
|
||||
(bool)(stat & CC_ATTACHED_BIT));
|
||||
smblib_handle_typec_debounce_done(chg,
|
||||
|
@ -2118,6 +2124,10 @@ irqreturn_t smblib_handle_usb_typec_change(int irq, void *data)
|
|||
|
||||
power_supply_changed(chg->usb_psy);
|
||||
|
||||
if (stat & TYPEC_VBUS_ERROR_STATUS_BIT)
|
||||
smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s vbus-error\n",
|
||||
irq_data->name);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -2178,8 +2188,7 @@ static void smblib_pl_detect_work(struct work_struct *work)
|
|||
struct smb_charger *chg = container_of(work, struct smb_charger,
|
||||
pl_detect_work);
|
||||
|
||||
if (!get_effective_result_locked(chg->pl_disable_votable))
|
||||
rerun_election(chg->pl_disable_votable);
|
||||
vote(chg->pl_disable_votable, PARALLEL_PSY_VOTER, false, 0);
|
||||
}
|
||||
|
||||
#define MINIMUM_PARALLEL_FCC_UA 500000
|
||||
|
@ -2204,7 +2213,7 @@ static void smblib_pl_taper_work(struct work_struct *work)
|
|||
}
|
||||
|
||||
if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER) {
|
||||
vote(chg->awake_votable, PL_VOTER, true, 0);
|
||||
vote(chg->awake_votable, PL_TAPER_WORK_RUNNING_VOTER, true, 0);
|
||||
/* Reduce the taper percent by 25 percent */
|
||||
chg->pl.taper_percent = chg->pl.taper_percent
|
||||
* TAPER_RESIDUAL_PERCENT / 100;
|
||||
|
@ -2218,7 +2227,7 @@ static void smblib_pl_taper_work(struct work_struct *work)
|
|||
* Master back to Fast Charge, get out of this round of taper reduction
|
||||
*/
|
||||
done:
|
||||
vote(chg->awake_votable, PL_VOTER, false, 0);
|
||||
vote(chg->awake_votable, PL_TAPER_WORK_RUNNING_VOTER, false, 0);
|
||||
}
|
||||
|
||||
static void clear_hdc_work(struct work_struct *work)
|
||||
|
@ -2320,6 +2329,15 @@ static int smblib_create_votables(struct smb_charger *chg)
|
|||
return rc;
|
||||
}
|
||||
|
||||
chg->pl_enable_votable_indirect = create_votable("PL_ENABLE_INDIRECT",
|
||||
VOTE_SET_ANY,
|
||||
smblib_pl_enable_indirect_vote_callback,
|
||||
chg);
|
||||
if (IS_ERR(chg->pl_enable_votable_indirect)) {
|
||||
rc = PTR_ERR(chg->pl_enable_votable_indirect);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -2345,6 +2363,10 @@ static void smblib_destroy_votables(struct smb_charger *chg)
|
|||
destroy_votable(chg->awake_votable);
|
||||
if (chg->pl_disable_votable)
|
||||
destroy_votable(chg->pl_disable_votable);
|
||||
if (chg->chg_disable_votable)
|
||||
destroy_votable(chg->chg_disable_votable);
|
||||
if (chg->pl_enable_votable_indirect)
|
||||
destroy_votable(chg->pl_enable_votable_indirect);
|
||||
}
|
||||
|
||||
static void smblib_iio_deinit(struct smb_charger *chg)
|
||||
|
@ -2381,9 +2403,6 @@ int smblib_init(struct smb_charger *chg)
|
|||
return rc;
|
||||
}
|
||||
|
||||
chg->bms_psy = power_supply_get_by_name("bms");
|
||||
chg->pl.psy = power_supply_get_by_name("parallel");
|
||||
|
||||
rc = smblib_register_notifier(chg);
|
||||
if (rc < 0) {
|
||||
dev_err(chg->dev,
|
||||
|
@ -2391,6 +2410,12 @@ int smblib_init(struct smb_charger *chg)
|
|||
return rc;
|
||||
}
|
||||
|
||||
chg->bms_psy = power_supply_get_by_name("bms");
|
||||
chg->pl.psy = power_supply_get_by_name("parallel");
|
||||
if (chg->pl.psy)
|
||||
vote(chg->pl_disable_votable, PARALLEL_PSY_VOTER,
|
||||
false, 0);
|
||||
|
||||
break;
|
||||
case PARALLEL_SLAVE:
|
||||
break;
|
||||
|
|
|
@ -24,16 +24,19 @@ enum print_reason {
|
|||
PR_MISC = BIT(2),
|
||||
};
|
||||
|
||||
#define DEFAULT_VOTER "DEFAULT_VOTER"
|
||||
#define USER_VOTER "USER_VOTER"
|
||||
#define PD_VOTER "PD_VOTER"
|
||||
#define PL_VOTER "PL_VOTER"
|
||||
#define USBIN_ICL_VOTER "USBIN_ICL_VOTER"
|
||||
#define CHG_STATE_VOTER "CHG_STATE_VOTER"
|
||||
#define TYPEC_SRC_VOTER "TYPEC_SRC_VOTER"
|
||||
#define TAPER_END_VOTER "TAPER_END_VOTER"
|
||||
#define FCC_MAX_RESULT "FCC_MAX_RESULT"
|
||||
#define THERMAL_DAEMON "THERMAL_DAEMON"
|
||||
#define DEFAULT_VOTER "DEFAULT_VOTER"
|
||||
#define USER_VOTER "USER_VOTER"
|
||||
#define PD_VOTER "PD_VOTER"
|
||||
#define PL_TAPER_WORK_RUNNING_VOTER "PL_TAPER_WORK_RUNNING_VOTER"
|
||||
#define PARALLEL_PSY_VOTER "PARALLEL_PSY_VOTER"
|
||||
#define PL_INDIRECT_VOTER "PL_INDIRECT_VOTER"
|
||||
#define USBIN_I_VOTER "USBIN_I_VOTER"
|
||||
#define USBIN_V_VOTER "USBIN_V_VOTER"
|
||||
#define CHG_STATE_VOTER "CHG_STATE_VOTER"
|
||||
#define TYPEC_SRC_VOTER "TYPEC_SRC_VOTER"
|
||||
#define TAPER_END_VOTER "TAPER_END_VOTER"
|
||||
#define FCC_MAX_RESULT_VOTER "FCC_MAX_RESULT_VOTER"
|
||||
#define THERMAL_DAEMON_VOTER "THERMAL_DAEMON_VOTER"
|
||||
|
||||
enum smb_mode {
|
||||
PARALLEL_MASTER = 0,
|
||||
|
@ -41,6 +44,10 @@ enum smb_mode {
|
|||
NUM_MODES,
|
||||
};
|
||||
|
||||
enum {
|
||||
QC_CHARGER_DETECTION_WA_BIT = BIT(0),
|
||||
};
|
||||
|
||||
struct smb_regulator {
|
||||
struct regulator_dev *rdev;
|
||||
struct regulator_desc rdesc;
|
||||
|
@ -139,6 +146,7 @@ struct smb_charger {
|
|||
struct votable *awake_votable;
|
||||
struct votable *pl_disable_votable;
|
||||
struct votable *chg_disable_votable;
|
||||
struct votable *pl_enable_votable_indirect;
|
||||
|
||||
/* work */
|
||||
struct work_struct bms_update_work;
|
||||
|
|
|
@ -427,7 +427,7 @@ enum {
|
|||
|
||||
#define APSD_STATUS_REG (USBIN_BASE + 0x07)
|
||||
#define APSD_STATUS_7_BIT BIT(7)
|
||||
#define APSD_STATUS_6_BIT BIT(6)
|
||||
#define HVDCP_CHECK_TIMEOUT_BIT BIT(6)
|
||||
#define SLOW_PLUGIN_TIMEOUT_BIT BIT(5)
|
||||
#define ENUMERATION_DONE_BIT BIT(4)
|
||||
#define VADP_CHANGE_DONE_AFTER_AUTH_BIT BIT(3)
|
||||
|
|
Loading…
Add table
Reference in a new issue