Merge "qcom-charger: update qc charger detection for PMICv2"

This commit is contained in:
Linux Build Service Account 2016-10-09 21:17:46 -07:00 committed by Gerrit - the friendly Code Review server
commit 8e23ae41f3
4 changed files with 110 additions and 72 deletions

View file

@ -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",

View file

@ -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;

View file

@ -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;

View file

@ -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)