summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-08-02 21:58:48 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-08-02 21:58:47 -0700
commitade5764cd3d141c9ce14259bb3a4356f5bdf1bd0 (patch)
tree0be9b1dd5973f338bb565161e0c538b2da222252
parentec9fd7cc51bcc302aefe26e4cbfc7f4e2590918d (diff)
parentcb5b737ccfdaa6deb023fd8865c23c9e6610e284 (diff)
Merge "smb-lib: Add support for thermal daemon throttling fcc"
-rw-r--r--Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt9
-rw-r--r--drivers/power/qcom-charger/qpnp-qnovo.c15
-rw-r--r--drivers/power/qcom-charger/qpnp-smb2.c41
-rw-r--r--drivers/power/qcom-charger/smb-lib.c51
-rw-r--r--drivers/power/qcom-charger/smb-lib.h12
5 files changed, 113 insertions, 15 deletions
diff --git a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt
index 368f0b8c9525..5a415d04fbcf 100644
--- a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt
+++ b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt
@@ -56,6 +56,15 @@ Charger specific properties:
Definition: Specifies the DC input power limit in micro-watts.
If the value is not present, 8W is used as default.
+- qcom,thermal-mitigation
+ Usage: optional
+ Value type: Array of <u32>
+ Definition: Array of fast charge current limit values for
+ different system thermal mitigation levels.
+ This should be a flat array that denotes the
+ maximum charge current in mA for each thermal
+ level.
+
=============================================
Second Level Nodes - SMB2 Charger Peripherals
=============================================
diff --git a/drivers/power/qcom-charger/qpnp-qnovo.c b/drivers/power/qcom-charger/qpnp-qnovo.c
index d50188a5efbf..2418b112d670 100644
--- a/drivers/power/qcom-charger/qpnp-qnovo.c
+++ b/drivers/power/qcom-charger/qpnp-qnovo.c
@@ -153,7 +153,7 @@ struct qnovo {
struct work_struct status_change_work;
int fv_uV_request;
int fcc_uA_request;
- struct votable *fcc_votable;
+ struct votable *fcc_max_votable;
struct votable *fv_votable;
};
@@ -243,8 +243,9 @@ static int qnovo_disable_cb(struct votable *votable, void *data, int disable,
vote(chip->fv_votable, QNOVO_VOTER, false, 0);
}
if (chip->fcc_uA_request != -EINVAL) {
- if (chip->fcc_votable)
- vote(chip->fcc_votable, QNOVO_VOTER, false, 0);
+ if (chip->fcc_max_votable)
+ vote(chip->fcc_max_votable, QNOVO_VOTER,
+ false, 0);
}
}
@@ -265,10 +266,10 @@ static int qnovo_disable_cb(struct votable *votable, void *data, int disable,
true, chip->fv_uV_request);
}
if (chip->fcc_uA_request != -EINVAL) {
- if (!chip->fcc_votable)
- chip->fcc_votable = find_votable("FCC");
- if (chip->fcc_votable)
- vote(chip->fcc_votable, QNOVO_VOTER,
+ if (!chip->fcc_max_votable)
+ chip->fcc_max_votable = find_votable("FCC_MAX");
+ if (chip->fcc_max_votable)
+ vote(chip->fcc_max_votable, QNOVO_VOTER,
true, chip->fcc_uA_request);
}
}
diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c
index a3a4591f05ed..19e78afe2a48 100644
--- a/drivers/power/qcom-charger/qpnp-smb2.c
+++ b/drivers/power/qcom-charger/qpnp-smb2.c
@@ -146,7 +146,7 @@ static int smb2_parse_dt(struct smb2 *chip)
{
struct smb_charger *chg = &chip->chg;
struct device_node *node = chg->dev->of_node;
- int rc;
+ int rc, byte_len;
if (!node) {
pr_err("device tree node missing\n");
@@ -181,6 +181,25 @@ static int smb2_parse_dt(struct smb2 *chip)
if (rc < 0)
chip->dt.wipower_max_uw = SMB2_DEFAULT_WPWR_UW;
+ if (of_find_property(node, "qcom,thermal-mitigation", &byte_len)) {
+ chg->thermal_mitigation = devm_kzalloc(chg->dev, byte_len,
+ GFP_KERNEL);
+
+ if (chg->thermal_mitigation == NULL)
+ return -ENOMEM;
+
+ chg->thermal_levels = byte_len / sizeof(u32);
+ rc = of_property_read_u32_array(node,
+ "qcom,thermal-mitigation",
+ chg->thermal_mitigation,
+ chg->thermal_levels);
+ if (rc < 0) {
+ dev_err(chg->dev,
+ "Couldn't read threm limits rc = %d\n", rc);
+ return rc;
+ }
+ }
+
return 0;
}
@@ -360,6 +379,7 @@ static enum power_supply_property smb2_batt_props[] = {
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_CHARGE_TYPE,
POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
};
static int smb2_batt_get_prop(struct power_supply *psy,
@@ -387,9 +407,11 @@ static int smb2_batt_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_CAPACITY:
smblib_get_prop_batt_capacity(chg, val);
break;
+ case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
+ smblib_get_prop_system_temp_level(chg, val);
+ break;
default:
- pr_err("batt power supply prop %d not supported\n",
- psp);
+ pr_err("batt power supply prop %d not supported\n", psp);
return -EINVAL;
}
@@ -400,17 +422,21 @@ static int smb2_batt_set_prop(struct power_supply *psy,
enum power_supply_property prop,
const union power_supply_propval *val)
{
+ int rc = 0;
struct smb_charger *chg = power_supply_get_drvdata(psy);
switch (prop) {
case POWER_SUPPLY_PROP_INPUT_SUSPEND:
- smblib_set_prop_input_suspend(chg, val);
+ rc = smblib_set_prop_input_suspend(chg, val);
+ break;
+ case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
+ rc = smblib_set_prop_system_temp_level(chg, val);
break;
default:
- return -EINVAL;
+ rc = -EINVAL;
}
- return 0;
+ return rc;
}
static int smb2_batt_prop_is_writeable(struct power_supply *psy,
@@ -418,6 +444,7 @@ static int smb2_batt_prop_is_writeable(struct power_supply *psy,
{
switch (psp) {
case POWER_SUPPLY_PROP_INPUT_SUSPEND:
+ case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
return 1;
default:
break;
@@ -608,7 +635,7 @@ static int smb2_init_hw(struct smb2 *chip)
DEFAULT_VOTER, chip->dt.suspend_input, 0);
vote(chg->dc_suspend_votable,
DEFAULT_VOTER, chip->dt.suspend_input, 0);
- vote(chg->fcc_votable,
+ vote(chg->fcc_max_votable,
DEFAULT_VOTER, true, chip->dt.fcc_ua);
vote(chg->fv_votable,
DEFAULT_VOTER, true, chip->dt.fv_uv);
diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c
index 43c360d98b69..16a39626a102 100644
--- a/drivers/power/qcom-charger/smb-lib.c
+++ b/drivers/power/qcom-charger/smb-lib.c
@@ -400,6 +400,14 @@ static int smblib_dc_suspend_vote_callback(struct votable *votable, void *data,
return smblib_set_dc_suspend(chg, suspend);
}
+static int smblib_fcc_max_vote_callback(struct votable *votable, void *data,
+ int fcc_ua, const char *client)
+{
+ struct smb_charger *chg = data;
+
+ return vote(chg->fcc_votable, FCC_MAX_RESULT, true, fcc_ua);
+}
+
static int smblib_fcc_vote_callback(struct votable *votable, void *data,
int fcc_ua, const char *client)
{
@@ -850,6 +858,13 @@ done:
return rc;
}
+int smblib_get_prop_system_temp_level(struct smb_charger *chg,
+ union power_supply_propval *val)
+{
+ val->intval = chg->system_temp_level;
+ return 0;
+}
+
/***********************
* BATTERY PSY SETTERS *
***********************/
@@ -877,6 +892,31 @@ int smblib_set_prop_input_suspend(struct smb_charger *chg,
return rc;
}
+int smblib_set_prop_system_temp_level(struct smb_charger *chg,
+ const union power_supply_propval *val)
+{
+ if (val->intval < 0)
+ return -EINVAL;
+
+ if (chg->thermal_levels <= 0)
+ return -EINVAL;
+
+ if (val->intval > chg->thermal_levels)
+ return -EINVAL;
+
+ chg->system_temp_level = val->intval;
+ if (chg->system_temp_level == chg->thermal_levels)
+ return vote(chg->chg_disable_votable, THERMAL_DAEMON, true, 0);
+
+ vote(chg->chg_disable_votable, THERMAL_DAEMON, false, 0);
+ if (chg->system_temp_level == 0)
+ return vote(chg->fcc_votable, THERMAL_DAEMON, false, 0);
+
+ vote(chg->fcc_votable, THERMAL_DAEMON, true,
+ chg->thermal_mitigation[chg->system_temp_level]);
+ return 0;
+}
+
/*******************
* USB PSY GETTERS *
*******************/
@@ -1695,7 +1735,15 @@ int smblib_create_votables(struct smb_charger *chg)
return rc;
}
- chg->fcc_votable = create_votable("FCC", VOTE_MAX,
+ chg->fcc_max_votable = create_votable("FCC_MAX", VOTE_MAX,
+ smblib_fcc_max_vote_callback,
+ chg);
+ if (IS_ERR(chg->fcc_max_votable)) {
+ rc = PTR_ERR(chg->fcc_max_votable);
+ return rc;
+ }
+
+ chg->fcc_votable = create_votable("FCC", VOTE_MIN,
smblib_fcc_vote_callback,
chg);
if (IS_ERR(chg->fcc_votable)) {
@@ -1805,6 +1853,7 @@ int smblib_deinit(struct smb_charger *chg)
{
destroy_votable(chg->usb_suspend_votable);
destroy_votable(chg->dc_suspend_votable);
+ destroy_votable(chg->fcc_max_votable);
destroy_votable(chg->fcc_votable);
destroy_votable(chg->fv_votable);
destroy_votable(chg->usb_icl_votable);
diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h
index 06a4428ffd13..2b6462d99341 100644
--- a/drivers/power/qcom-charger/smb-lib.h
+++ b/drivers/power/qcom-charger/smb-lib.h
@@ -31,6 +31,8 @@ enum print_reason {
#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"
enum smb_mode {
PARALLEL_MASTER = 0,
@@ -106,6 +108,7 @@ struct smb_charger {
/* votables */
struct votable *usb_suspend_votable;
struct votable *dc_suspend_votable;
+ struct votable *fcc_max_votable;
struct votable *fcc_votable;
struct votable *fv_votable;
struct votable *usb_icl_votable;
@@ -126,6 +129,10 @@ struct smb_charger {
int voltage_max_uv;
bool pd_active;
bool vbus_present;
+
+ int system_temp_level;
+ int thermal_levels;
+ int *thermal_mitigation;
};
int smblib_read(struct smb_charger *chg, u16 addr, u8 *val);
@@ -172,8 +179,13 @@ int smblib_get_prop_batt_charge_type(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_batt_health(struct smb_charger *chg,
union power_supply_propval *val);
+int smblib_get_prop_system_temp_level(struct smb_charger *chg,
+ union power_supply_propval *val);
+
int smblib_set_prop_input_suspend(struct smb_charger *chg,
const union power_supply_propval *val);
+int smblib_set_prop_system_temp_level(struct smb_charger *chg,
+ const union power_supply_propval *val);
int smblib_get_prop_usb_present(struct smb_charger *chg,
union power_supply_propval *val);