Merge "power: qcom: smb5: Add support for PMI632 charger"
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt
index 8e17f80..65c3cb8 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt
@@ -114,12 +114,6 @@
SOC. If this property is not specified, then auto recharge will
be based off battery voltage.
-- qcom,micro-usb
- Usage: optional
- Value type: <empty>
- Definition: Boolean flag which indicates that the platform only support
- micro usb port.
-
- qcom,suspend-input-on-debug-batt
Usage: optional
Value type: <empty>
diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c
index d1031ba..3903a4b 100644
--- a/drivers/power/supply/qcom/qpnp-smb5.c
+++ b/drivers/power/supply/qcom/qpnp-smb5.c
@@ -28,7 +28,67 @@
#include "smb5-reg.h"
#include "smb5-lib.h"
-static struct smb_params smb5_params = {
+static struct smb_params smb5_pmi632_params = {
+ .fcc = {
+ .name = "fast charge current",
+ .reg = CHGR_FAST_CHARGE_CURRENT_CFG_REG,
+ .min_u = 0,
+ .max_u = 3000000,
+ .step_u = 50000,
+ },
+ .fv = {
+ .name = "float voltage",
+ .reg = CHGR_FLOAT_VOLTAGE_CFG_REG,
+ .min_u = 3600000,
+ .max_u = 4800000,
+ .step_u = 10000,
+ },
+ .usb_icl = {
+ .name = "usb input current limit",
+ .reg = USBIN_CURRENT_LIMIT_CFG_REG,
+ .min_u = 0,
+ .max_u = 3000000,
+ .step_u = 50000,
+ },
+ .icl_stat = {
+ .name = "input current limit status",
+ .reg = AICL_ICL_STATUS_REG,
+ .min_u = 0,
+ .max_u = 3000000,
+ .step_u = 50000,
+ },
+ .otg_cl = {
+ .name = "usb otg current limit",
+ .reg = DCDC_OTG_CURRENT_LIMIT_CFG_REG,
+ .min_u = 500000,
+ .max_u = 1000000,
+ .step_u = 250000,
+ },
+ .jeita_cc_comp_hot = {
+ .name = "jeita fcc reduction",
+ .reg = JEITA_CCCOMP_CFG_HOT_REG,
+ .min_u = 0,
+ .max_u = 1575000,
+ .step_u = 25000,
+ },
+ .jeita_cc_comp_cold = {
+ .name = "jeita fcc reduction",
+ .reg = JEITA_CCCOMP_CFG_COLD_REG,
+ .min_u = 0,
+ .max_u = 1575000,
+ .step_u = 25000,
+ },
+ .freq_switcher = {
+ .name = "switching frequency",
+ .reg = DCDC_FSW_SEL_REG,
+ .min_u = 600,
+ .max_u = 1200,
+ .step_u = 400,
+ .set_proc = smblib_set_chg_freq,
+ },
+};
+
+static struct smb_params smb5_pmi855_params = {
.fcc = {
.name = "fast charge current",
.reg = CHGR_FAST_CHARGE_CURRENT_CFG_REG,
@@ -119,6 +179,64 @@
weak_chg_icl_ua, __weak_chg_icl_ua, int, 0600
);
+#define PMI632_MAX_ICL_UA 3000000
+static int smb5_chg_config_init(struct smb5 *chip)
+{
+ struct smb_charger *chg = &chip->chg;
+ struct pmic_revid_data *pmic_rev_id;
+ struct device_node *revid_dev_node;
+ int rc = 0;
+
+ revid_dev_node = of_parse_phandle(chip->chg.dev->of_node,
+ "qcom,pmic-revid", 0);
+ if (!revid_dev_node) {
+ pr_err("Missing qcom,pmic-revid property\n");
+ return -EINVAL;
+ }
+
+ pmic_rev_id = get_revid_data(revid_dev_node);
+ if (IS_ERR_OR_NULL(pmic_rev_id)) {
+ /*
+ * the revid peripheral must be registered, any failure
+ * here only indicates that the rev-id module has not
+ * probed yet.
+ */
+ rc = -EPROBE_DEFER;
+ goto out;
+ }
+
+ switch (pmic_rev_id->pmic_subtype) {
+ case PM855B_SUBTYPE:
+ chip->chg.smb_version = PM855B_SUBTYPE;
+ chg->param = smb5_pmi855_params;
+ chg->name = "pm855b_charger";
+ break;
+ case PMI632_SUBTYPE:
+ chip->chg.smb_version = PMI632_SUBTYPE;
+ chg->param = smb5_pmi632_params;
+ chg->use_extcon = true;
+ chg->name = "pmi632_charger";
+ chg->hw_max_icl_ua =
+ (chip->dt.usb_icl_ua > 0) ? chip->dt.usb_icl_ua
+ : PMI632_MAX_ICL_UA;
+ chg->chg_freq.freq_5V = 600;
+ chg->chg_freq.freq_6V_8V = 800;
+ chg->chg_freq.freq_9V = 1050;
+ chg->chg_freq.freq_removal = 1050;
+ chg->chg_freq.freq_below_otg_threshold = 800;
+ chg->chg_freq.freq_above_otg_threshold = 800;
+ break;
+ default:
+ pr_err("PMIC subtype %d not supported\n",
+ pmic_rev_id->pmic_subtype);
+ rc = -EINVAL;
+ }
+
+out:
+ of_node_put(revid_dev_node);
+ return rc;
+}
+
#define MICRO_1P5A 1500000
#define MICRO_P1A 100000
#define OTG_DEFAULT_DEGLITCH_TIME_MS 50
@@ -213,8 +331,6 @@
chip->dt.auto_recharge_soc = of_property_read_bool(node,
"qcom,auto-recharge-soc");
- chg->micro_usb_mode = of_property_read_bool(node, "qcom,micro-usb");
-
chg->dcp_icl_ua = chip->dt.usb_icl_ua;
chg->suspend_input_on_debug_batt = of_property_read_bool(node,
@@ -253,6 +369,7 @@
POWER_SUPPLY_PROP_PD_VOLTAGE_MAX,
POWER_SUPPLY_PROP_PD_VOLTAGE_MIN,
POWER_SUPPLY_PROP_SDP_CURRENT_MAX,
+ POWER_SUPPLY_PROP_CONNECTOR_TYPE,
};
static int smb5_usb_get_prop(struct power_supply *psy,
@@ -272,12 +389,13 @@
if (!val->intval)
break;
- if ((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT ||
- chg->micro_usb_mode) &&
- chg->real_charger_type == POWER_SUPPLY_TYPE_USB)
+ if (((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) ||
+ (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB))
+ && (chg->real_charger_type == POWER_SUPPLY_TYPE_USB))
val->intval = 0;
else
val->intval = 1;
+
if (chg->real_charger_type == POWER_SUPPLY_TYPE_UNKNOWN)
val->intval = 0;
break;
@@ -297,19 +415,19 @@
val->intval = chg->real_charger_type;
break;
case POWER_SUPPLY_PROP_TYPEC_MODE:
- if (chg->micro_usb_mode)
+ if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
val->intval = POWER_SUPPLY_TYPEC_NONE;
else
val->intval = chg->typec_mode;
break;
case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
- if (chg->micro_usb_mode)
+ if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
val->intval = POWER_SUPPLY_TYPEC_PR_NONE;
else
rc = smblib_get_prop_typec_power_role(chg, val);
break;
case POWER_SUPPLY_PROP_TYPEC_CC_ORIENTATION:
- if (chg->micro_usb_mode)
+ if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
val->intval = 0;
else
rc = smblib_get_prop_typec_cc_orientation(chg, val);
@@ -354,6 +472,9 @@
val->intval = get_client_vote(chg->usb_icl_votable,
USB_PSY_VOTER);
break;
+ case POWER_SUPPLY_PROP_CONNECTOR_TYPE:
+ val->intval = chg->connector_type;
+ break;
default:
pr_err("get prop %d is not supported in usb\n", psp);
rc = -EINVAL;
@@ -496,9 +617,9 @@
if (!val->intval)
break;
- if ((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT ||
- chg->micro_usb_mode) &&
- chg->real_charger_type == POWER_SUPPLY_TYPE_USB)
+ if (((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) ||
+ (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB))
+ && (chg->real_charger_type == POWER_SUPPLY_TYPE_USB))
val->intval = 1;
else
val->intval = 0;
@@ -1093,7 +1214,7 @@
struct regulator_config cfg = {};
int rc = 0;
- if (chg->micro_usb_mode)
+ if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
return 0;
chg->vconn_vreg = devm_kzalloc(chg->dev, sizeof(*chg->vconn_vreg),
@@ -1139,7 +1260,6 @@
}
rc = smblib_write(chg, TYPE_C_INTERRUPT_EN_CFG_2_REG,
- MICRO_USB_STATE_CHANGE_INT_EN_BIT |
TYPEC_WATER_DETECTION_INT_EN_BIT);
if (rc < 0) {
dev_err(chg->dev,
@@ -1172,14 +1292,23 @@
return rc;
}
+ rc = smblib_masked_write(chg, TYPE_C_INTERRUPT_EN_CFG_2_REG,
+ MICRO_USB_STATE_CHANGE_INT_EN_BIT,
+ MICRO_USB_STATE_CHANGE_INT_EN_BIT);
+ if (rc < 0) {
+ dev_err(chg->dev,
+ "Couldn't configure Type-C interrupts rc=%d\n", rc);
+ return rc;
+ }
+
return rc;
}
static int smb5_init_hw(struct smb5 *chip)
{
struct smb_charger *chg = &chip->chg;
- int rc;
- u8 val;
+ int rc, type = 0;
+ u8 val = 0;
if (chip->dt.no_battery)
chg->fake_capacity = 50;
@@ -1194,8 +1323,50 @@
smblib_get_charge_param(chg, &chg->param.usb_icl,
&chg->default_icl_ua);
- if (chip->dt.usb_icl_ua < 0)
- chip->dt.usb_icl_ua = chg->default_icl_ua;
+
+ /* Use SW based VBUS control, disable HW autonomous mode */
+ /* TODO: auth can be enabled through vote based on APSD flow */
+ rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
+ HVDCP_AUTH_ALG_EN_CFG_BIT | HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT,
+ HVDCP_AUTH_ALG_EN_CFG_BIT);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't configure HVDCP rc=%d\n", rc);
+ return rc;
+ }
+
+ /*
+ * PMI632 can have the connector type defined by a dedicated register
+ * TYPEC_MICRO_USB_MODE_REG or by a common TYPEC_U_USB_CFG_REG.
+ */
+ if (chg->smb_version == PMI632_SUBTYPE) {
+ rc = smblib_read(chg, TYPEC_MICRO_USB_MODE_REG, &val);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't read USB mode rc=%d\n", rc);
+ return rc;
+ }
+ type = !!(val & MICRO_USB_MODE_ONLY_BIT);
+ }
+
+ /*
+ * If TYPEC_MICRO_USB_MODE_REG is not set and for all non-PMI632
+ * check the connector type using TYPEC_U_USB_CFG_REG.
+ */
+ if (!type) {
+ rc = smblib_read(chg, TYPEC_U_USB_CFG_REG, &val);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't read U_USB config rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ type = !!(val & EN_MICRO_USB_MODE_BIT);
+ }
+
+ chg->connector_type = type ? POWER_SUPPLY_CONNECTOR_MICRO_USB
+ : POWER_SUPPLY_CONNECTOR_TYPEC;
+ pr_debug("Connector type=%s\n", type ? "Micro USB" : "TypeC");
+
+ smblib_rerun_apsd_if_required(chg);
/* vote 0mA on usb_icl for non battery platforms */
vote(chg->usb_icl_votable,
@@ -1207,15 +1378,21 @@
vote(chg->fv_votable, HW_LIMIT_VOTER,
chip->dt.batt_profile_fv_uv > 0, chip->dt.batt_profile_fv_uv);
vote(chg->fcc_votable,
- BATT_PROFILE_VOTER, true, chg->batt_profile_fcc_ua);
+ BATT_PROFILE_VOTER, chg->batt_profile_fcc_ua > 0,
+ chg->batt_profile_fcc_ua);
vote(chg->fv_votable,
- BATT_PROFILE_VOTER, true, chg->batt_profile_fv_uv);
+ BATT_PROFILE_VOTER, chg->batt_profile_fv_uv > 0,
+ chg->batt_profile_fv_uv);
vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER,
true, 0);
vote(chg->pd_disallowed_votable_indirect, APSD_VOTER,
true, 0);
vote(chg->pd_disallowed_votable_indirect, MICRO_USB_VOTER,
- chg->micro_usb_mode, 0);
+ chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB, 0);
+
+ /* Some h/w limit maximum supported ICL */
+ vote(chg->usb_icl_votable, HW_LIMIT_VOTER,
+ chg->hw_max_icl_ua > 0, chg->hw_max_icl_ua);
/*
* AICL configuration:
@@ -1235,7 +1412,7 @@
return rc;
}
- if (chg->micro_usb_mode)
+ if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
rc = smb5_configure_micro_usb(chg);
else
rc = smb5_configure_typec(chg);
@@ -1384,8 +1561,8 @@
pval.intval = POWER_SUPPLY_TYPEC_PR_DUAL;
rc = smblib_set_prop_typec_power_role(chg, &pval);
if (rc < 0) {
- dev_err(chg->dev,
- "Couldn't configure power role for DRP rc=%d\n", rc);
+ dev_err(chg->dev, "Couldn't configure DRP role rc=%d\n",
+ rc);
return rc;
}
@@ -1405,6 +1582,7 @@
if (chg->bms_psy)
smblib_suspend_on_debug_battery(chg);
+
usb_plugin_irq_handler(0, &irq_data);
typec_state_change_irq_handler(0, &irq_data);
usb_source_change_irq_handler(0, &irq_data);
@@ -1412,6 +1590,7 @@
icl_change_irq_handler(0, &irq_data);
batt_temp_changed_irq_handler(0, &irq_data);
wdog_bark_irq_handler(0, &irq_data);
+ typec_or_rid_detection_change_irq_handler(0, &irq_data);
return 0;
}
@@ -1586,7 +1765,7 @@
/* TYPEC IRQs */
[TYPEC_OR_RID_DETECTION_CHANGE_IRQ] = {
.name = "typec-or-rid-detect-change",
- .handler = default_irq_handler,
+ .handler = typec_or_rid_detection_change_irq_handler,
},
[TYPEC_VPD_DETECT_IRQ] = {
.name = "typec-vpd-detect",
@@ -1880,13 +2059,12 @@
chg = &chip->chg;
chg->dev = &pdev->dev;
- chg->param = smb5_params;
chg->debug_mask = &__debug_mask;
chg->weak_chg_icl_ua = &__weak_chg_icl_ua;
chg->mode = PARALLEL_MASTER;
chg->irq_info = smb5_irqs;
chg->die_health = -EINVAL;
- chg->name = "pm855b_charger";
+ chg->otg_present = false;
chg->regmap = dev_get_regmap(chg->dev->parent, NULL);
if (!chg->regmap) {
@@ -1897,13 +2075,20 @@
rc = smb5_parse_dt(chip);
if (rc < 0) {
pr_err("Couldn't parse device tree rc=%d\n", rc);
- goto cleanup;
+ return rc;
+ }
+
+ rc = smb5_chg_config_init(chip);
+ if (rc < 0) {
+ if (rc != -EPROBE_DEFER)
+ pr_err("Couldn't setup chg_config rc=%d\n", rc);
+ return rc;
}
rc = smblib_init(chg);
if (rc < 0) {
pr_err("Smblib_init failed rc=%d\n", rc);
- goto cleanup;
+ return rc;
}
/* set driver data before resources request it */
@@ -1945,10 +2130,12 @@
goto cleanup;
}
- rc = smb5_init_dc_psy(chip);
- if (rc < 0) {
- pr_err("Couldn't initialize dc psy rc=%d\n", rc);
- goto cleanup;
+ if (chg->smb_version == PM855B_SUBTYPE) {
+ rc = smb5_init_dc_psy(chip);
+ if (rc < 0) {
+ pr_err("Couldn't initialize dc psy rc=%d\n", rc);
+ goto cleanup;
+ }
}
rc = smb5_init_usb_psy(chip);
@@ -1991,7 +2178,7 @@
rc = smb5_post_init(chip);
if (rc < 0) {
pr_err("Failed in post init rc=%d\n", rc);
- goto cleanup;
+ goto free_irq;
}
smb5_create_debugfs(chip);
@@ -1999,7 +2186,7 @@
rc = smb5_show_charger_status(chip);
if (rc < 0) {
pr_err("Failed in getting charger status rc=%d\n", rc);
- goto cleanup;
+ goto free_irq;
}
device_init_wakeup(chg->dev, true);
@@ -2008,8 +2195,9 @@
return rc;
-cleanup:
+free_irq:
smb5_free_interrupts(chg);
+cleanup:
smblib_deinit(chg);
platform_set_drvdata(pdev, NULL);
@@ -2036,7 +2224,7 @@
smb5_disable_interrupts(chg);
/* configure power role for UFP */
- if (!chg->micro_usb_mode)
+ if (chg->connector_type == POWER_SUPPLY_CONNECTOR_TYPEC)
smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
TYPEC_POWER_ROLE_CMD_MASK, EN_SNK_ONLY_BIT);
diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c
index ff7da6c..4fc60a1 100644
--- a/drivers/power/supply/qcom/smb5-lib.c
+++ b/drivers/power/supply/qcom/smb5-lib.c
@@ -107,19 +107,6 @@
return 0;
}
-int smblib_icl_override(struct smb_charger *chg, bool override)
-{
- int rc;
-
- rc = smblib_masked_write(chg, USBIN_LOAD_CFG_REG,
- ICL_OVERRIDE_AFTER_APSD_BIT,
- override ? ICL_OVERRIDE_AFTER_APSD_BIT : 0);
- if (rc < 0)
- smblib_err(chg, "Couldn't override ICL rc=%d\n", rc);
-
- return rc;
-}
-
int smblib_stat_sw_override_cfg(struct smb_charger *chg, bool override)
{
int rc = 0;
@@ -137,6 +124,39 @@
return rc;
}
+static void smblib_notify_extcon_props(struct smb_charger *chg, int id)
+{
+ union extcon_property_value val;
+ union power_supply_propval prop_val;
+
+ if (chg->connector_type == POWER_SUPPLY_CONNECTOR_TYPEC) {
+ smblib_get_prop_typec_cc_orientation(chg, &prop_val);
+ val.intval = ((prop_val.intval == 2) ? 1 : 0);
+ extcon_set_property(chg->extcon, id,
+ EXTCON_PROP_USB_TYPEC_POLARITY, val);
+ }
+
+ val.intval = true;
+ extcon_set_property(chg->extcon, id,
+ EXTCON_PROP_USB_SS, val);
+}
+
+static void smblib_notify_device_mode(struct smb_charger *chg, bool enable)
+{
+ if (enable)
+ smblib_notify_extcon_props(chg, EXTCON_USB);
+
+ extcon_set_state_sync(chg->extcon, EXTCON_USB, enable);
+}
+
+static void smblib_notify_usb_host(struct smb_charger *chg, bool enable)
+{
+ if (enable)
+ smblib_notify_extcon_props(chg, EXTCON_USB_HOST);
+
+ extcon_set_state_sync(chg->extcon, EXTCON_USB_HOST, enable);
+}
+
/********************
* REGISTER GETTERS *
********************/
@@ -281,6 +301,48 @@
/********************
* REGISTER SETTERS *
********************/
+static const struct buck_boost_freq chg_freq_list[] = {
+ [0] = {
+ .freq_khz = 2400,
+ .val = 7,
+ },
+ [1] = {
+ .freq_khz = 2100,
+ .val = 8,
+ },
+ [2] = {
+ .freq_khz = 1600,
+ .val = 11,
+ },
+ [3] = {
+ .freq_khz = 1200,
+ .val = 15,
+ },
+};
+
+int smblib_set_chg_freq(struct smb_chg_param *param,
+ int val_u, u8 *val_raw)
+{
+ u8 i;
+
+ if (val_u > param->max_u || val_u < param->min_u)
+ return -EINVAL;
+
+ /* Charger FSW is the configured freqency / 2 */
+ val_u *= 2;
+ for (i = 0; i < ARRAY_SIZE(chg_freq_list); i++) {
+ if (chg_freq_list[i].freq_khz == val_u)
+ break;
+ }
+ if (i == ARRAY_SIZE(chg_freq_list)) {
+ pr_err("Invalid frequency %d Hz\n", val_u / 2);
+ return -EINVAL;
+ }
+
+ *val_raw = chg_freq_list[i].val;
+
+ return 0;
+}
int smblib_set_opt_switcher_freq(struct smb_charger *chg, int fsw_khz)
{
@@ -316,11 +378,15 @@
if (rc < 0)
return -EINVAL;
} else {
- if (val_u > param->max_u || val_u < param->min_u) {
- smblib_err(chg, "%s: %d is out of range [%d, %d]\n",
+ if (val_u > param->max_u || val_u < param->min_u)
+ smblib_dbg(chg, PR_MISC,
+ "%s: %d is out of range [%d, %d]\n",
param->name, val_u, param->min_u, param->max_u);
- return -EINVAL;
- }
+
+ if (val_u > param->max_u)
+ val_u = param->max_u;
+ if (val_u < param->min_u)
+ val_u = param->min_u;
val_raw = (val_u - param->min_u) / param->step_u;
}
@@ -771,69 +837,46 @@
int smblib_set_icl_current(struct smb_charger *chg, int icl_ua)
{
int rc = 0;
- bool override;
+ bool hc_mode = false;
/* suspend and return if 25mA or less is requested */
if (icl_ua <= USBIN_25MA)
return smblib_set_usb_suspend(chg, true);
if (icl_ua == INT_MAX)
- goto override_suspend_config;
+ goto set_mode;
/* configure current */
- if (chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT
+ if (((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT)
+ || (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB))
&& (chg->real_charger_type == POWER_SUPPLY_TYPE_USB)) {
rc = set_sdp_current(chg, icl_ua);
if (rc < 0) {
smblib_err(chg, "Couldn't set SDP ICL rc=%d\n", rc);
- goto enable_icl_changed_interrupt;
+ goto out;
}
} else {
set_sdp_current(chg, 100000);
rc = smblib_set_charge_param(chg, &chg->param.usb_icl, icl_ua);
if (rc < 0) {
smblib_err(chg, "Couldn't set HC ICL rc=%d\n", rc);
- goto enable_icl_changed_interrupt;
+ goto out;
}
+ hc_mode = true;
}
-override_suspend_config:
- /* determine if override needs to be enforced */
- override = true;
- if (icl_ua == INT_MAX) {
- /* remove override if no voters - hw defaults is desired */
- override = false;
- } else if (chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) {
- if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB)
- /* For std cable with type = SDP never override */
- override = false;
- else if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_CDP
- && icl_ua == 1500000)
- /*
- * For std cable with type = CDP override only if
- * current is not 1500mA
- */
- override = false;
- }
-
- /* enforce override */
+set_mode:
rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
- USBIN_MODE_CHG_BIT, override ? USBIN_MODE_CHG_BIT : 0);
-
- rc = smblib_icl_override(chg, override);
- if (rc < 0) {
- smblib_err(chg, "Couldn't set ICL override rc=%d\n", rc);
- goto enable_icl_changed_interrupt;
- }
+ USBIN_MODE_CHG_BIT, hc_mode ? USBIN_MODE_CHG_BIT : 0);
/* unsuspend after configuring current and override */
rc = smblib_set_usb_suspend(chg, false);
if (rc < 0) {
smblib_err(chg, "Couldn't resume input rc=%d\n", rc);
- goto enable_icl_changed_interrupt;
+ goto out;
}
-enable_icl_changed_interrupt:
+out:
return rc;
}
@@ -844,7 +887,7 @@
bool override;
if ((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT
- || chg->micro_usb_mode)
+ || chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
&& (chg->usb_psy->desc->type == POWER_SUPPLY_TYPE_USB)) {
rc = get_sdp_current(chg, icl_ua);
if (rc < 0) {
@@ -881,6 +924,9 @@
{
struct smb_charger *chg = data;
+ if (chg->smb_version == PMI632_SUBTYPE)
+ return 0;
+
/* resume input if suspend is invalid */
if (suspend < 0)
suspend = 0;
@@ -2053,7 +2099,7 @@
}
int smblib_set_prop_boost_current(struct smb_charger *chg,
- const union power_supply_propval *val)
+ const union power_supply_propval *val)
{
int rc = 0;
@@ -2076,6 +2122,9 @@
int rc = 0;
u8 power_role;
+ if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
+ return 0;
+
switch (val->intval) {
case POWER_SUPPLY_TYPEC_PR_NONE:
power_role = TYPEC_DISABLE_CMD_BIT;
@@ -2513,7 +2562,7 @@
} else {
chg->typec_present = 0;
smblib_update_usb_type(chg);
- extcon_set_state_sync(chg->extcon, EXTCON_USB, false);
+ smblib_notify_device_mode(chg, false);
smblib_uusb_removal(chg);
}
}
@@ -2601,7 +2650,7 @@
smblib_err(chg, "Couldn't disable DPDM rc=%d\n", rc);
}
- if (chg->micro_usb_mode)
+ if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
smblib_micro_usb_plugin(chg, vbus_rising);
power_supply_changed(chg->usb_psy);
@@ -2763,37 +2812,6 @@
rising ? "rising" : "falling");
}
-static void smblib_notify_extcon_props(struct smb_charger *chg, int id)
-{
- union extcon_property_value val;
- union power_supply_propval prop_val;
-
- smblib_get_prop_typec_cc_orientation(chg, &prop_val);
- val.intval = ((prop_val.intval == 2) ? 1 : 0);
- extcon_set_property(chg->extcon, id,
- EXTCON_PROP_USB_TYPEC_POLARITY, val);
-
- val.intval = true;
- extcon_set_property(chg->extcon, id,
- EXTCON_PROP_USB_SS, val);
-}
-
-static void smblib_notify_device_mode(struct smb_charger *chg, bool enable)
-{
- if (enable)
- smblib_notify_extcon_props(chg, EXTCON_USB);
-
- extcon_set_state_sync(chg->extcon, EXTCON_USB, enable);
-}
-
-static void smblib_notify_usb_host(struct smb_charger *chg, bool enable)
-{
- if (enable)
- smblib_notify_extcon_props(chg, EXTCON_USB_HOST);
-
- extcon_set_state_sync(chg->extcon, EXTCON_USB_HOST, enable);
-}
-
static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
{
const struct apsd_result *apsd_result;
@@ -2806,13 +2824,11 @@
switch (apsd_result->bit) {
case SDP_CHARGER_BIT:
case CDP_CHARGER_BIT:
- if (chg->micro_usb_mode)
- extcon_set_state_sync(chg->extcon, EXTCON_USB,
- true);
/* if not DCP then no hvdcp timeout happens. Enable pd here */
vote(chg->pd_disallowed_votable_indirect, APSD_VOTER,
false, 0);
- if (chg->use_extcon)
+ if ((chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
+ || chg->use_extcon)
smblib_notify_device_mode(chg, true);
break;
case OCP_CHARGER_BIT:
@@ -2845,8 +2861,9 @@
}
smblib_dbg(chg, PR_REGISTER, "APSD_STATUS = 0x%02x\n", stat);
- if (chg->micro_usb_mode && (stat & APSD_DTC_STATUS_DONE_BIT)
- && !chg->uusb_apsd_rerun_done) {
+ if ((chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
+ && (stat & APSD_DTC_STATUS_DONE_BIT)
+ && !chg->uusb_apsd_rerun_done) {
/*
* Force re-run APSD to handle slow insertion related
* charger-mis-detection.
@@ -3146,12 +3163,12 @@
power_supply_changed(chg->usb_psy);
}
-irqreturn_t typec_state_change_irq_handler(int irq, void *data)
+irqreturn_t typec_or_rid_detection_change_irq_handler(int irq, void *data)
{
struct smb_irq_data *irq_data = data;
struct smb_charger *chg = irq_data->parent_data;
- if (chg->micro_usb_mode) {
+ if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB) {
cancel_delayed_work_sync(&chg->uusb_otg_work);
vote(chg->awake_votable, OTG_DELAY_VOTER, true, 0);
smblib_dbg(chg, PR_INTERRUPT, "Scheduling OTG work\n");
@@ -3160,7 +3177,16 @@
return IRQ_HANDLED;
}
- if (chg->pr_swap_in_progress) {
+ return IRQ_HANDLED;
+}
+
+irqreturn_t typec_state_change_irq_handler(int irq, void *data)
+{
+ struct smb_irq_data *irq_data = data;
+ struct smb_charger *chg = irq_data->parent_data;
+
+ if ((chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
+ || chg->pr_swap_in_progress) {
smblib_dbg(chg, PR_INTERRUPT,
"Ignoring since pr_swap_in_progress\n");
return IRQ_HANDLED;
@@ -3335,10 +3361,20 @@
smblib_err(chg, "Couldn't read TYPE_C_STATUS_3 rc=%d\n", rc);
goto out;
}
+ otg = !!(stat & U_USB_GROUND_NOVBUS_BIT);
+ if (chg->otg_present != otg)
+ smblib_notify_usb_host(chg, otg);
+ chg->otg_present = otg;
+ if (!otg)
+ chg->boost_current_ua = 0;
- otg = !!(stat & (U_USB_GROUND_NOVBUS_BIT | U_USB_GROUND_BIT));
- extcon_set_state_sync(chg->extcon, EXTCON_USB_HOST, otg);
- smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_3 = 0x%02x OTG=%d\n",
+ rc = smblib_set_charge_param(chg, &chg->param.freq_switcher,
+ otg ? chg->chg_freq.freq_below_otg_threshold
+ : chg->chg_freq.freq_removal);
+ if (rc < 0)
+ dev_err(chg->dev, "Error in setting freq_boost rc=%d\n", rc);
+
+ smblib_dbg(chg, PR_REGISTER, "TYPE_C_U_USB_STATUS = 0x%02x OTG=%d\n",
stat, otg);
power_supply_changed(chg->usb_psy);
@@ -3559,13 +3595,6 @@
return rc;
}
- rc = smblib_register_notifier(chg);
- if (rc < 0) {
- smblib_err(chg,
- "Couldn't register notifier rc=%d\n", rc);
- return rc;
- }
-
chg->bms_psy = power_supply_get_by_name("bms");
chg->pl.psy = power_supply_get_by_name("parallel");
if (chg->pl.psy) {
@@ -3576,6 +3605,12 @@
return rc;
}
}
+ rc = smblib_register_notifier(chg);
+ if (rc < 0) {
+ smblib_err(chg,
+ "Couldn't register notifier rc=%d\n", rc);
+ return rc;
+ }
break;
case PARALLEL_SLAVE:
break;
diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h
index 8633ba0..fa7381c 100644
--- a/drivers/power/supply/qcom/smb5-lib.h
+++ b/drivers/power/supply/qcom/smb5-lib.h
@@ -196,6 +196,11 @@
u8 *val_raw);
};
+struct buck_boost_freq {
+ int freq_khz;
+ u8 val;
+};
+
struct smb_chg_freq {
unsigned int freq_5V;
unsigned int freq_6V_8V;
@@ -311,7 +316,7 @@
bool sw_jeita_enabled;
bool is_hdc;
bool chg_done;
- bool micro_usb_mode;
+ int connector_type;
bool otg_en;
bool suspend_input_on_debug_batt;
int otg_attempts;
@@ -329,6 +334,7 @@
u8 float_cfg;
bool use_extcon;
bool otg_present;
+ int hw_max_icl_ua;
/* workaround flag */
u32 wa_flags;
@@ -369,6 +375,8 @@
int val_u, u8 *val_raw);
int smblib_set_chg_freq(struct smb_chg_param *param,
int val_u, u8 *val_raw);
+int smblib_set_prop_boost_current(struct smb_charger *chg,
+ const union power_supply_propval *val);
int smblib_vbus_regulator_enable(struct regulator_dev *rdev);
int smblib_vbus_regulator_disable(struct regulator_dev *rdev);
int smblib_vbus_regulator_is_enabled(struct regulator_dev *rdev);
@@ -390,6 +398,7 @@
irqreturn_t high_duty_cycle_irq_handler(int irq, void *data);
irqreturn_t switcher_power_ok_irq_handler(int irq, void *data);
irqreturn_t wdog_bark_irq_handler(int irq, void *data);
+irqreturn_t typec_or_rid_detection_change_irq_handler(int irq, void *data);
int smblib_get_prop_input_suspend(struct smb_charger *chg,
union power_supply_propval *val);
@@ -470,8 +479,6 @@
const union power_supply_propval *val);
int smblib_set_prop_pd_voltage_min(struct smb_charger *chg,
const union power_supply_propval *val);
-int smblib_set_prop_boost_current(struct smb_charger *chg,
- const union power_supply_propval *val);
int smblib_set_prop_typec_power_role(struct smb_charger *chg,
const union power_supply_propval *val);
int smblib_set_prop_pd_active(struct smb_charger *chg,
@@ -484,7 +491,6 @@
int smblib_rerun_apsd_if_required(struct smb_charger *chg);
int smblib_get_prop_fcc_delta(struct smb_charger *chg,
union power_supply_propval *val);
-int smblib_icl_override(struct smb_charger *chg, bool override);
int smblib_dp_dm(struct smb_charger *chg, int val);
int smblib_disable_hw_jeita(struct smb_charger *chg, bool disable);
int smblib_rerun_aicl(struct smb_charger *chg);
diff --git a/drivers/power/supply/qcom/smb5-reg.h b/drivers/power/supply/qcom/smb5-reg.h
index 1534f7c..dfc303e 100644
--- a/drivers/power/supply/qcom/smb5-reg.h
+++ b/drivers/power/supply/qcom/smb5-reg.h
@@ -196,6 +196,7 @@
};
#define USBIN_OPTIONS_1_CFG_REG (USBIN_BASE + 0x62)
+#define HVDCP_AUTH_ALG_EN_CFG_BIT BIT(6)
#define HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT BIT(5)
#define BC1P2_SRC_DETECT_BIT BIT(3)
@@ -299,6 +300,8 @@
#define TYPEC_U_USB_CFG_REG (TYPEC_BASE + 0x70)
#define EN_MICRO_USB_MODE_BIT BIT(0)
+#define TYPEC_MICRO_USB_MODE_REG (TYPEC_BASE + 0x70)
+#define MICRO_USB_MODE_ONLY_BIT BIT(0)
/********************************
* MISC Peripheral Registers *
********************************/