power: smb5: add support for die/connector temp based mitigation
Add support to configure/enable hardware controlled mitigation
based on DIE and connector temperature. H/W controlled scheme
manipulates input current limit(ICL) of charger whenever die or
connector temperature crosses configured threshold.
Change-Id: Ib7655a8709960c79c554657a5d144c0ceccb73d3
Signed-off-by: Ashay Jaiswal <ashayj@codeaurora.org>
diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c
index 29bc0cb..f7ace93 100644
--- a/drivers/power/supply/qcom/qpnp-smb5.c
+++ b/drivers/power/supply/qcom/qpnp-smb5.c
@@ -61,7 +61,7 @@
},
.icl_stat = {
.name = "input current limit status",
- .reg = AICL_ICL_STATUS_REG,
+ .reg = ICL_STATUS_REG,
.min_u = 0,
.max_u = 3000000,
.step_u = 50000,
@@ -206,6 +206,13 @@
USBIN_VOLTAGE,
};
+enum {
+ BAT_THERM = 0,
+ MISC_THERM,
+ CONN_THERM,
+ SMB_THERM,
+};
+
#define PMI632_MAX_ICL_UA 3000000
static int smb5_chg_config_init(struct smb5 *chip)
{
@@ -266,6 +273,53 @@
return rc;
}
+#define PULL_NO_PULL 0
+#define PULL_30K 30
+#define PULL_100K 100
+#define PULL_400K 400
+static int get_valid_pullup(int pull_up)
+{
+ int pull;
+
+ /* pull up can only be 0/30K/100K/400K) */
+ switch (pull_up) {
+ case PULL_NO_PULL:
+ pull = INTERNAL_PULL_NO_PULL;
+ break;
+ case PULL_30K:
+ pull = INTERNAL_PULL_30K_PULL;
+ break;
+ case PULL_100K:
+ pull = INTERNAL_PULL_100K_PULL;
+ break;
+ case PULL_400K:
+ pull = INTERNAL_PULL_400K_PULL;
+ break;
+ default:
+ pull = INTERNAL_PULL_100K_PULL;
+ }
+
+ return pull;
+}
+
+#define INTERNAL_PULL_UP_MASK 0x3
+static int smb5_configure_internal_pull(struct smb_charger *chg, int type,
+ int pull)
+{
+ int rc;
+ int shift = type * 2;
+ u8 mask = INTERNAL_PULL_UP_MASK << shift;
+ u8 val = pull << shift;
+
+ rc = smblib_masked_write(chg, BATIF_ADC_INTERNAL_PULL_UP_REG,
+ mask, val);
+ if (rc < 0)
+ dev_err(chg->dev,
+ "Couldn't configure ADC pull-up reg rc=%d\n", rc);
+
+ return rc;
+}
+
#define MICRO_1P5A 1500000
#define MICRO_1PA 1000000
#define MICRO_P1A 100000
@@ -387,6 +441,16 @@
if (rc < 0)
chg->otg_delay_ms = OTG_DEFAULT_DEGLITCH_TIME_MS;
+ chg->hw_die_temp_mitigation = of_property_read_bool(node,
+ "qcom,hw-die-temp-mitigation");
+
+ chg->hw_connector_mitigation = of_property_read_bool(node,
+ "qcom,hw-connector-mitigation");
+
+ chg->connector_pull_up = -EINVAL;
+ of_property_read_u32(node, "qcom,connector-internal-pull-kohm",
+ &chg->connector_pull_up);
+
return 0;
}
@@ -474,6 +538,7 @@
POWER_SUPPLY_PROP_SCOPE,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED,
+ POWER_SUPPLY_PROP_QC_OPTI_DISABLE,
};
static int smb5_usb_get_prop(struct power_supply *psy,
@@ -602,6 +667,13 @@
case POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED:
val->intval = !chg->flash_active;
break;
+ case POWER_SUPPLY_PROP_QC_OPTI_DISABLE:
+ if (chg->hw_die_temp_mitigation)
+ val->intval = POWER_SUPPLY_QC_THERMAL_BALANCE_DISABLE
+ | POWER_SUPPLY_QC_INOV_THERMAL_DISABLE;
+ if (chg->hw_connector_mitigation)
+ val->intval |= POWER_SUPPLY_QC_CTM_DISABLE;
+ break;
default:
pr_err("get prop %d is not supported in usb\n", psp);
rc = -EINVAL;
@@ -1534,6 +1606,42 @@
return rc;
}
+static int smb5_configure_mitigation(struct smb_charger *chg)
+{
+ int rc;
+ u8 chan = 0;
+
+ if (!chg->hw_die_temp_mitigation && !chg->hw_connector_mitigation)
+ return 0;
+
+ if (chg->hw_die_temp_mitigation) {
+ rc = smblib_write(chg, MISC_THERMREG_SRC_CFG_REG,
+ THERMREG_CONNECTOR_ADC_SRC_EN_BIT
+ | THERMREG_DIE_ADC_SRC_EN_BIT
+ | THERMREG_DIE_CMP_SRC_EN_BIT);
+ if (rc < 0) {
+ dev_err(chg->dev,
+ "Couldn't configure THERM_SRC reg rc=%d\n", rc);
+ return rc;
+ };
+
+ chan = DIE_TEMP_CHANNEL_EN_BIT;
+ }
+
+ if (chg->hw_connector_mitigation)
+ chan |= CONN_THM_CHANNEL_EN_BIT;
+
+ rc = smblib_masked_write(chg, BATIF_ADC_CHANNEL_EN_REG,
+ CONN_THM_CHANNEL_EN_BIT | DIE_TEMP_CHANNEL_EN_BIT,
+ chan);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't enable ADC channelrc=%d\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
static int smb5_init_hw(struct smb5 *chip)
{
struct smb_charger *chg = &chip->chg;
@@ -1640,6 +1748,13 @@
return rc;
}
+ /* configure temperature mitigation */
+ rc = smb5_configure_mitigation(chg);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't configure mitigation rc=%d\n", rc);
+ return rc;
+ }
+
/* vote 0mA on usb_icl for non battery platforms */
vote(chg->usb_icl_votable,
DEFAULT_VOTER, chip->dt.no_battery, 0);
@@ -1850,6 +1965,17 @@
return rc;
}
+ if (chg->connector_pull_up != -EINVAL) {
+ rc = smb5_configure_internal_pull(chg, CONN_THERM,
+ get_valid_pullup(chg->connector_pull_up));
+ if (rc < 0) {
+ dev_err(chg->dev,
+ "Couldn't configure CONN_THERM pull-up rc=%d\n",
+ rc);
+ return rc;
+ }
+ }
+
return rc;
}