Merge "power_supply: add DIE_HEALTH and CONNECTOR_HEALTH properties"

This commit is contained in:
Linux Build Service Account 2017-02-10 06:46:01 -08:00 committed by Gerrit - the friendly Code Review server
commit 1a78d46209
5 changed files with 218 additions and 46 deletions

View file

@ -60,7 +60,7 @@ static ssize_t power_supply_show_property(struct device *dev,
"Unknown", "Good", "Overheat", "Dead", "Over voltage", "Unknown", "Good", "Overheat", "Dead", "Over voltage",
"Unspecified failure", "Cold", "Watchdog timer expire", "Unspecified failure", "Cold", "Watchdog timer expire",
"Safety timer expire", "Safety timer expire",
"Warm", "Cool" "Warm", "Cool", "Hot"
}; };
static char *technology_text[] = { static char *technology_text[] = {
"Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd", "Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd",
@ -122,6 +122,10 @@ static ssize_t power_supply_show_property(struct device *dev,
return sprintf(buf, "%s\n", typec_text[value.intval]); return sprintf(buf, "%s\n", typec_text[value.intval]);
else if (off == POWER_SUPPLY_PROP_TYPEC_POWER_ROLE) else if (off == POWER_SUPPLY_PROP_TYPEC_POWER_ROLE)
return sprintf(buf, "%s\n", typec_pr_text[value.intval]); return sprintf(buf, "%s\n", typec_pr_text[value.intval]);
else if (off == POWER_SUPPLY_PROP_DIE_HEALTH)
return sprintf(buf, "%s\n", health_text[value.intval]);
else if (off == POWER_SUPPLY_PROP_CONNECTOR_HEALTH)
return sprintf(buf, "%s\n", health_text[value.intval]);
else if (off >= POWER_SUPPLY_PROP_MODEL_NAME) else if (off >= POWER_SUPPLY_PROP_MODEL_NAME)
return sprintf(buf, "%s\n", value.strval); return sprintf(buf, "%s\n", value.strval);
@ -283,6 +287,8 @@ static struct device_attribute power_supply_attrs[] = {
POWER_SUPPLY_ATTR(icl_reduction), POWER_SUPPLY_ATTR(icl_reduction),
POWER_SUPPLY_ATTR(parallel_mode), POWER_SUPPLY_ATTR(parallel_mode),
POWER_SUPPLY_ATTR(connector_therm_zone), POWER_SUPPLY_ATTR(connector_therm_zone),
POWER_SUPPLY_ATTR(die_health),
POWER_SUPPLY_ATTR(connector_health),
/* Local extensions of type int64_t */ /* Local extensions of type int64_t */
POWER_SUPPLY_ATTR(charge_counter_ext), POWER_SUPPLY_ATTR(charge_counter_ext),
/* Properties of type `const char *' */ /* Properties of type `const char *' */

View file

@ -664,8 +664,7 @@ static int smb2_usb_main_set_prop(struct power_supply *psy,
rc = smblib_set_charge_param(chg, &chg->param.fv, val->intval); rc = smblib_set_charge_param(chg, &chg->param.fv, val->intval);
break; break;
case POWER_SUPPLY_PROP_ICL_REDUCTION: case POWER_SUPPLY_PROP_ICL_REDUCTION:
chg->icl_reduction_ua = val->intval; rc = smblib_set_icl_reduction(chg, val->intval);
rc = rerun_election(chg->usb_icl_votable);
break; break;
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
rc = smblib_set_charge_param(chg, &chg->param.fcc, val->intval); rc = smblib_set_charge_param(chg, &chg->param.fcc, val->intval);
@ -1317,9 +1316,10 @@ static int smb2_init_hw(struct smb2 *chip)
if (chip->dt.fv_uv < 0) if (chip->dt.fv_uv < 0)
smblib_get_charge_param(chg, &chg->param.fv, &chip->dt.fv_uv); smblib_get_charge_param(chg, &chg->param.fv, &chip->dt.fv_uv);
smblib_get_charge_param(chg, &chg->param.usb_icl,
&chg->default_icl_ua);
if (chip->dt.usb_icl_ua < 0) if (chip->dt.usb_icl_ua < 0)
smblib_get_charge_param(chg, &chg->param.usb_icl, chip->dt.usb_icl_ua = chg->default_icl_ua;
&chip->dt.usb_icl_ua);
if (chip->dt.dc_icl_ua < 0) if (chip->dt.dc_icl_ua < 0)
smblib_get_charge_param(chg, &chg->param.dc_icl, smblib_get_charge_param(chg, &chg->param.dc_icl,
@ -1581,6 +1581,7 @@ static int smb2_chg_config_init(struct smb2 *chip)
switch (pmic_rev_id->pmic_subtype) { switch (pmic_rev_id->pmic_subtype) {
case PMI8998_SUBTYPE: case PMI8998_SUBTYPE:
chip->chg.smb_version = PMI8998_SUBTYPE;
chip->chg.wa_flags |= BOOST_BACK_WA; chip->chg.wa_flags |= BOOST_BACK_WA;
if (pmic_rev_id->rev4 == PMI8998_V1P1_REV4) /* PMI rev 1.1 */ if (pmic_rev_id->rev4 == PMI8998_V1P1_REV4) /* PMI rev 1.1 */
chg->wa_flags |= QC_CHARGER_DETECTION_WA_BIT; chg->wa_flags |= QC_CHARGER_DETECTION_WA_BIT;
@ -1595,6 +1596,7 @@ static int smb2_chg_config_init(struct smb2 *chip)
chg->chg_freq.freq_above_otg_threshold = 800; chg->chg_freq.freq_above_otg_threshold = 800;
break; break;
case PM660_SUBTYPE: case PM660_SUBTYPE:
chip->chg.smb_version = PM660_SUBTYPE;
chip->chg.wa_flags |= BOOST_BACK_WA; chip->chg.wa_flags |= BOOST_BACK_WA;
chg->param.freq_buck = pm660_params.freq_buck; chg->param.freq_buck = pm660_params.freq_buck;
chg->param.freq_boost = pm660_params.freq_boost; chg->param.freq_boost = pm660_params.freq_boost;

View file

@ -16,6 +16,7 @@
#include <linux/iio/consumer.h> #include <linux/iio/consumer.h>
#include <linux/power_supply.h> #include <linux/power_supply.h>
#include <linux/regulator/driver.h> #include <linux/regulator/driver.h>
#include <linux/qpnp/qpnp-revid.h>
#include <linux/input/qpnp-power-on.h> #include <linux/input/qpnp-power-on.h>
#include <linux/irq.h> #include <linux/irq.h>
#include "smb-lib.h" #include "smb-lib.h"
@ -156,11 +157,24 @@ int smblib_icl_override(struct smb_charger *chg, bool override)
int rc; int rc;
bool override_status; bool override_status;
u8 stat; u8 stat;
u16 reg;
rc = smblib_read(chg, APSD_RESULT_STATUS_REG, &stat); switch (chg->smb_version) {
case PMI8998_SUBTYPE:
reg = APSD_RESULT_STATUS_REG;
break;
case PM660_SUBTYPE:
reg = AICL_STATUS_REG;
break;
default:
smblib_dbg(chg, PR_MISC, "Unknown chip version=%x\n",
chg->smb_version);
return -EINVAL;
}
rc = smblib_read(chg, reg, &stat);
if (rc < 0) { if (rc < 0) {
smblib_err(chg, "Couldn't read APSD_RESULT_STATUS_REG rc=%d\n", smblib_err(chg, "Couldn't read reg=%x rc=%d\n", reg, rc);
rc);
return rc; return rc;
} }
override_status = (bool)(stat & ICL_OVERRIDE_LATCH_BIT); override_status = (bool)(stat & ICL_OVERRIDE_LATCH_BIT);
@ -640,6 +654,19 @@ static void smblib_uusb_removal(struct smb_charger *chg)
rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
if (rc < 0) if (rc < 0)
smblib_err(chg, "Couldn't un-vote for USB ICL rc=%d\n", rc); smblib_err(chg, "Couldn't un-vote for USB ICL rc=%d\n", rc);
/* clear USB ICL vote for DCP_VOTER */
rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
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);
} }
static bool smblib_sysok_reason_usbin(struct smb_charger *chg) static bool smblib_sysok_reason_usbin(struct smb_charger *chg)
@ -2203,12 +2230,19 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
return rc; return rc;
} }
/* remove DCP_VOTER */ /* clear USB ICL vote for DCP_VOTER */
rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0); rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
if (rc < 0) { if (rc < 0)
smblib_err(chg, "Couldn't unvote DCP rc=%d\n", rc); smblib_err(chg,
return rc; "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 */ /* remove USB_PSY_VOTER */
rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
@ -2255,39 +2289,6 @@ int smblib_set_prop_ship_mode(struct smb_charger *chg,
return rc; return rc;
} }
/***********************
* USB MAIN PSY GETTERS *
*************************/
int smblib_get_prop_fcc_delta(struct smb_charger *chg,
union power_supply_propval *val)
{
int rc, jeita_cc_delta_ua, step_cc_delta_ua, hw_cc_delta_ua = 0;
rc = smblib_get_step_cc_delta(chg, &step_cc_delta_ua);
if (rc < 0) {
smblib_err(chg, "Couldn't get step cc delta rc=%d\n", rc);
step_cc_delta_ua = 0;
} else {
hw_cc_delta_ua = step_cc_delta_ua;
}
rc = smblib_get_jeita_cc_delta(chg, &jeita_cc_delta_ua);
if (rc < 0) {
smblib_err(chg, "Couldn't get jeita cc delta rc=%d\n", rc);
jeita_cc_delta_ua = 0;
} else if (jeita_cc_delta_ua < 0) {
/* HW will take the min between JEITA and step charge */
hw_cc_delta_ua = min(hw_cc_delta_ua, jeita_cc_delta_ua);
}
val->intval = hw_cc_delta_ua;
return 0;
}
/***********************
* USB MAIN PSY SETTERS *
*************************/
int smblib_reg_block_update(struct smb_charger *chg, int smblib_reg_block_update(struct smb_charger *chg,
struct reg_info *entry) struct reg_info *entry)
{ {
@ -2463,6 +2464,155 @@ int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg,
return rc; return rc;
} }
/***********************
* USB MAIN PSY GETTERS *
*************************/
int smblib_get_prop_fcc_delta(struct smb_charger *chg,
union power_supply_propval *val)
{
int rc, jeita_cc_delta_ua, step_cc_delta_ua, hw_cc_delta_ua = 0;
rc = smblib_get_step_cc_delta(chg, &step_cc_delta_ua);
if (rc < 0) {
smblib_err(chg, "Couldn't get step cc delta rc=%d\n", rc);
step_cc_delta_ua = 0;
} else {
hw_cc_delta_ua = step_cc_delta_ua;
}
rc = smblib_get_jeita_cc_delta(chg, &jeita_cc_delta_ua);
if (rc < 0) {
smblib_err(chg, "Couldn't get jeita cc delta rc=%d\n", rc);
jeita_cc_delta_ua = 0;
} else if (jeita_cc_delta_ua < 0) {
/* HW will take the min between JEITA and step charge */
hw_cc_delta_ua = min(hw_cc_delta_ua, jeita_cc_delta_ua);
}
val->intval = hw_cc_delta_ua;
return 0;
}
/***********************
* USB MAIN PSY SETTERS *
*************************/
#define SDP_CURRENT_MA 500000
#define CDP_CURRENT_MA 1500000
#define DCP_CURRENT_MA 1500000
#define HVDCP_CURRENT_MA 3000000
#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 *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;
bool non_compliant;
u8 stat5;
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);
return rc;
}
non_compliant = stat5 & TYPEC_NONCOMP_LEGACY_CABLE_STATUS_BIT;
/* get settled ICL */
rc = smblib_get_prop_input_current_settled(chg, &val);
if (rc < 0) {
smblib_err(chg, "Couldn't get settled ICL rc=%d\n", rc);
return rc;
}
typec_source_rd = smblib_get_prop_ufp_mode(chg);
/* QC 2.0/3.0 adapter */
if (apsd_result->bit & (QC_3P0_BIT | QC_2P0_BIT)) {
*total_current_ua = HVDCP_CURRENT_MA;
return 0;
}
if (non_compliant) {
switch (apsd_result->bit) {
case CDP_CHARGER_BIT:
current_ua = CDP_CURRENT_MA;
break;
case DCP_CHARGER_BIT:
case OCP_CHARGER_BIT:
case FLOAT_CHARGER_BIT:
current_ua = DCP_CURRENT_MA;
break;
default:
current_ua = 0;
break;
}
*total_current_ua = max(current_ua, val.intval);
return 0;
}
switch (typec_source_rd) {
case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT:
switch (apsd_result->bit) {
case CDP_CHARGER_BIT:
current_ua = CDP_CURRENT_MA;
break;
case DCP_CHARGER_BIT:
case OCP_CHARGER_BIT:
case FLOAT_CHARGER_BIT:
current_ua = chg->default_icl_ua;
break;
default:
current_ua = 0;
break;
}
break;
case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM:
current_ua = TYPEC_MEDIUM_CURRENT_MA;
break;
case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
current_ua = TYPEC_HIGH_CURRENT_MA;
break;
case POWER_SUPPLY_TYPEC_NON_COMPLIANT:
case POWER_SUPPLY_TYPEC_NONE:
default:
current_ua = 0;
break;
}
*total_current_ua = max(current_ua, val.intval);
return 0;
}
int smblib_set_icl_reduction(struct smb_charger *chg, int reduction_ua)
{
int current_ua, rc;
if (reduction_ua == 0) {
chg->icl_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, &current_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);
}
}
return rerun_election(chg->usb_icl_votable);
}
/************************ /************************
* PARALLEL PSY GETTERS * * PARALLEL PSY GETTERS *
************************/ ************************/
@ -2984,6 +3134,13 @@ static void typec_source_removal(struct smb_charger *chg)
if (rc < 0) if (rc < 0)
smblib_err(chg, smblib_err(chg,
"Couldn't un-vote DCP from USB ICL rc=%d\n", rc); "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) static void typec_source_insertion(struct smb_charger *chg)

View file

@ -31,6 +31,7 @@ enum print_reason {
#define USER_VOTER "USER_VOTER" #define USER_VOTER "USER_VOTER"
#define PD_VOTER "PD_VOTER" #define PD_VOTER "PD_VOTER"
#define DCP_VOTER "DCP_VOTER" #define DCP_VOTER "DCP_VOTER"
#define PL_USBIN_USBIN_VOTER "PL_USBIN_USBIN_VOTER"
#define USB_PSY_VOTER "USB_PSY_VOTER" #define USB_PSY_VOTER "USB_PSY_VOTER"
#define PL_TAPER_WORK_RUNNING_VOTER "PL_TAPER_WORK_RUNNING_VOTER" #define PL_TAPER_WORK_RUNNING_VOTER "PL_TAPER_WORK_RUNNING_VOTER"
#define PL_INDIRECT_VOTER "PL_INDIRECT_VOTER" #define PL_INDIRECT_VOTER "PL_INDIRECT_VOTER"
@ -171,6 +172,7 @@ struct smb_charger {
enum smb_mode mode; enum smb_mode mode;
bool external_vconn; bool external_vconn;
struct smb_chg_freq chg_freq; struct smb_chg_freq chg_freq;
int smb_version;
/* locks */ /* locks */
struct mutex write_lock; struct mutex write_lock;
@ -244,6 +246,7 @@ struct smb_charger {
bool vconn_en; bool vconn_en;
int otg_attempts; int otg_attempts;
int vconn_attempts; int vconn_attempts;
int default_icl_ua;
/* workaround flag */ /* workaround flag */
u32 wa_flags; u32 wa_flags;
@ -408,6 +411,7 @@ int smblib_rerun_apsd_if_required(struct smb_charger *chg);
int smblib_get_prop_fcc_delta(struct smb_charger *chg, int smblib_get_prop_fcc_delta(struct smb_charger *chg,
union power_supply_propval *val); union power_supply_propval *val);
int smblib_icl_override(struct smb_charger *chg, bool override); int smblib_icl_override(struct smb_charger *chg, bool override);
int smblib_set_icl_reduction(struct smb_charger *chg, int reduction_ua);
int smblib_init(struct smb_charger *chg); int smblib_init(struct smb_charger *chg);
int smblib_deinit(struct smb_charger *chg); int smblib_deinit(struct smb_charger *chg);

View file

@ -61,6 +61,7 @@ enum {
POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE, POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE,
POWER_SUPPLY_HEALTH_WARM, POWER_SUPPLY_HEALTH_WARM,
POWER_SUPPLY_HEALTH_COOL, POWER_SUPPLY_HEALTH_COOL,
POWER_SUPPLY_HEALTH_HOT,
}; };
enum { enum {
@ -238,6 +239,8 @@ enum power_supply_property {
POWER_SUPPLY_PROP_ICL_REDUCTION, POWER_SUPPLY_PROP_ICL_REDUCTION,
POWER_SUPPLY_PROP_PARALLEL_MODE, POWER_SUPPLY_PROP_PARALLEL_MODE,
POWER_SUPPLY_PROP_CONNECTOR_THERM_ZONE, POWER_SUPPLY_PROP_CONNECTOR_THERM_ZONE,
POWER_SUPPLY_PROP_DIE_HEALTH,
POWER_SUPPLY_PROP_CONNECTOR_HEALTH,
/* Local extensions of type int64_t */ /* Local extensions of type int64_t */
POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT, POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT,
/* Properties of type `const char *' */ /* Properties of type `const char *' */