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  *
  ********************************/