Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8e8b850c authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge changes I9ef65b37,I2816a88c into msm-4.14

* changes:
  usb: pd: Adapt to new charger detection flow
  power: smb5: update USB source detection sequence
parents 64d2e2e3 1fdc55bc
Loading
Loading
Loading
Loading
+44 −42
Original line number Diff line number Diff line
@@ -176,6 +176,11 @@ module_param_named(
	debug_mask, __debug_mask, int, 0600
);

static int __pd_disabled;
module_param_named(
	pd_disabled, __pd_disabled, int, 0600
);

static int __weak_chg_icl_ua = 500000;
module_param_named(
	weak_chg_icl_ua, __weak_chg_icl_ua, int, 0600
@@ -373,7 +378,6 @@ static enum power_supply_property smb5_usb_props[] = {
	POWER_SUPPLY_PROP_TYPEC_MODE,
	POWER_SUPPLY_PROP_TYPEC_POWER_ROLE,
	POWER_SUPPLY_PROP_TYPEC_CC_ORIENTATION,
	POWER_SUPPLY_PROP_PD_ALLOWED,
	POWER_SUPPLY_PROP_PD_ACTIVE,
	POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
	POWER_SUPPLY_PROP_INPUT_CURRENT_NOW,
@@ -452,9 +456,6 @@ static int smb5_usb_get_prop(struct power_supply *psy,
		else
			rc = smblib_get_prop_typec_cc_orientation(chg, val);
		break;
	case POWER_SUPPLY_PROP_PD_ALLOWED:
		rc = smblib_get_prop_pd_allowed(chg, val);
		break;
	case POWER_SUPPLY_PROP_PD_ACTIVE:
		val->intval = chg->pd_active;
		break;
@@ -526,12 +527,6 @@ static int smb5_usb_set_prop(struct power_supply *psy,
	struct smb_charger *chg = &chip->chg;
	int rc = 0;

	mutex_lock(&chg->lock);
	if (!chg->typec_present) {
		rc = -EINVAL;
		goto unlock;
	}

	switch (psp) {
	case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
		rc = smblib_set_prop_pd_current_max(chg, val);
@@ -573,8 +568,6 @@ static int smb5_usb_set_prop(struct power_supply *psy,
		break;
	}

unlock:
	mutex_unlock(&chg->lock);
	return rc;
}

@@ -1294,6 +1287,15 @@ static int smb5_configure_typec(struct smb_charger *chg)
{
	int rc;

	/* disable apsd */
	rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
				HVDCP_EN_BIT | BC1P2_SRC_DETECT_BIT,
				0);
	if (rc < 0) {
		dev_err(chg->dev, "Couldn't disable APSD rc=%d\n", rc);
		return rc;
	}

	rc = smblib_write(chg, TYPE_C_INTERRUPT_EN_CFG_1_REG,
				TYPEC_CCOUT_DETACH_INT_EN_BIT |
				TYPEC_CCOUT_ATTACH_INT_EN_BIT);
@@ -1328,14 +1330,6 @@ static int smb5_configure_micro_usb(struct smb_charger *chg)
{
	int rc;

	/* configure micro USB mode */
	rc = smblib_masked_write(chg, TYPEC_U_USB_CFG_REG,
			EN_MICRO_USB_MODE_BIT, EN_MICRO_USB_MODE_BIT);
	if (rc < 0) {
		dev_err(chg->dev, "Couldn't enable micro USB mode rc=%d\n", rc);
		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);
@@ -1369,7 +1363,6 @@ static int smb5_init_hw(struct smb5 *chip)
				&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);
@@ -1406,10 +1399,22 @@ static int smb5_init_hw(struct smb5 *chip)
		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");

	if (type) {
		chg->connector_type = POWER_SUPPLY_CONNECTOR_MICRO_USB;
		smblib_rerun_apsd_if_required(chg);
		rc = smb5_configure_micro_usb(chg);
	} else {
		chg->connector_type = POWER_SUPPLY_CONNECTOR_TYPEC;
		rc = smb5_configure_typec(chg);
	}
	if (rc < 0) {
		dev_err(chg->dev,
			"Couldn't configure TypeC/micro-USB mode rc=%d\n", rc);
		return rc;
	}

	/*
	 * PMI632 based hw init:
	 * - Initialize flash module for PMI632
@@ -1417,8 +1422,6 @@ static int smb5_init_hw(struct smb5 *chip)
	if (chg->smb_version == PMI632_SUBTYPE)
		schgm_flash_init(chg);

	smblib_rerun_apsd_if_required(chg);

	/* vote 0mA on usb_icl for non battery platforms */
	vote(chg->usb_icl_votable,
		DEFAULT_VOTER, chip->dt.no_battery, 0);
@@ -1434,12 +1437,6 @@ static int smb5_init_hw(struct smb5 *chip)
	vote(chg->fv_votable,
		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->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB, 0);

	/* Some h/w limit maximum supported ICL */
	vote(chg->usb_icl_votable, HW_LIMIT_VOTER,
@@ -1472,16 +1469,6 @@ static int smb5_init_hw(struct smb5 *chip)
		return rc;
	}

	if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
		rc = smb5_configure_micro_usb(chg);
	else
		rc = smb5_configure_typec(chg);
	if (rc < 0) {
		dev_err(chg->dev,
			"Couldn't configure TypeC/micro-USB mode rc=%d\n", rc);
		return rc;
	}

	/* configure VBUS for software control */
	rc = smblib_masked_write(chg, DCDC_OTG_CFG_REG, OTG_EN_SRC_CFG_BIT, 0);
	if (rc < 0) {
@@ -1690,11 +1677,21 @@ static int smb5_determine_initial_status(struct smb5 *chip)
{
	struct smb_irq_data irq_data = {chip, "determine-initial-status"};
	struct smb_charger *chg = &chip->chg;
	union power_supply_propval val;
	int rc;

	rc = smblib_get_prop_usb_present(chg, &val);
	if (rc < 0) {
		pr_err("Couldn't get usb present rc=%d\n", rc);
		return rc;
	}
	chg->early_usb_attach = val.intval;

	if (chg->bms_psy)
		smblib_suspend_on_debug_battery(chg);

	usb_plugin_irq_handler(0, &irq_data);
	typec_attach_detach_irq_handler(0, &irq_data);
	typec_state_change_irq_handler(0, &irq_data);
	usb_source_change_irq_handler(0, &irq_data);
	chg_state_change_irq_handler(0, &irq_data);
@@ -1896,7 +1893,7 @@ static struct smb_irq_info smb5_irqs[] = {
	},
	[TYPEC_ATTACH_DETACH_IRQ] = {
		.name		= "typec-attach-detach",
		.handler	= default_irq_handler,
		.handler	= typec_attach_detach_irq_handler,
	},
	[TYPEC_LEGACY_CABLE_DETECT_IRQ] = {
		.name		= "typec-legacy-cable-detect",
@@ -2204,6 +2201,7 @@ static int smb5_probe(struct platform_device *pdev)
	chg = &chip->chg;
	chg->dev = &pdev->dev;
	chg->debug_mask = &__debug_mask;
	chg->pd_disabled = &__pd_disabled;
	chg->weak_chg_icl_ua = &__weak_chg_icl_ua;
	chg->mode = PARALLEL_MASTER;
	chg->irq_info = smb5_irqs;
@@ -2353,6 +2351,10 @@ static int smb5_remove(struct platform_device *pdev)
	struct smb5 *chip = platform_get_drvdata(pdev);
	struct smb_charger *chg = &chip->chg;

	/* force enable APSD */
	smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
				BC1P2_SRC_DETECT_BIT, BC1P2_SRC_DETECT_BIT);

	smb5_free_interrupts(chg);
	smblib_deinit(chg);
	platform_set_drvdata(pdev, NULL);
+0 −1
Original line number Diff line number Diff line
@@ -334,7 +334,6 @@ struct smb_charger {
	int			otg_cl_ua;
	bool			uusb_apsd_rerun_done;
	bool			pd_hard_reset;
	bool			typec_present;
	u8			typec_status[5];
	bool			typec_legacy_valid;
	int			fake_input_current_limited;
+149 −232
Original line number Diff line number Diff line
@@ -659,10 +659,6 @@ static void smblib_uusb_removal(struct smb_charger *chg)

	cancel_delayed_work_sync(&chg->pl_enable_work);

	rc = smblib_request_dpdm(chg, false);
	if (rc < 0)
		smblib_err(chg, "Couldn't to disable DPDM rc=%d\n", rc);

	if (chg->wa_flags & BOOST_BACK_WA) {
		data = chg->irq_info[SWITCHER_POWER_OK_IRQ].irq_data;
		if (data) {
@@ -938,18 +934,6 @@ static int smblib_dc_suspend_vote_callback(struct votable *votable, void *data,
	return smblib_set_dc_suspend(chg, (bool)suspend);
}

static int smblib_pd_disallowed_votable_indirect_callback(
	struct votable *votable, void *data, int disallowed, const char *client)
{
	struct smb_charger *chg = data;
	int rc;

	rc = vote(chg->pd_allowed_votable, PD_DISALLOWED_INDIRECT_VOTER,
		!disallowed, 0);

	return rc;
}

static int smblib_awake_vote_callback(struct votable *votable, void *data,
			int awake, const char *client)
{
@@ -1952,13 +1936,6 @@ int smblib_get_prop_typec_power_role(struct smb_charger *chg,
	return rc;
}

int smblib_get_prop_pd_allowed(struct smb_charger *chg,
			       union power_supply_propval *val)
{
	val->intval = get_effective_result(chg->pd_allowed_votable);
	return 0;
}

int smblib_get_prop_input_current_settled(struct smb_charger *chg,
					  union power_supply_propval *val)
{
@@ -2002,13 +1979,7 @@ int smblib_get_prop_pd_in_hard_reset(struct smb_charger *chg,
int smblib_get_pe_start(struct smb_charger *chg,
			       union power_supply_propval *val)
{
	/*
	 * hvdcp timeout voter is the last one to allow pd. Use its vote
	 * to indicate start of pe engine
	 */
	val->intval
		= !get_client_vote_locked(chg->pd_disallowed_votable_indirect,
			APSD_VOTER);
	val->intval = chg->ok_to_pd;
	return 0;
}

@@ -2243,14 +2214,14 @@ int smblib_set_prop_pd_voltage_max(struct smb_charger *chg,
	return rc;
}

static int __smblib_set_prop_pd_active(struct smb_charger *chg, bool pd_active)
int smblib_set_prop_pd_active(struct smb_charger *chg,
				const union power_supply_propval *val)
{
	int rc = 0;

	chg->pd_active = pd_active;
	chg->pd_active = val->intval;

	if (chg->pd_active) {
		vote(chg->pd_allowed_votable, PD_VOTER, true, 0);
		vote(chg->usb_irq_enable_votable, PD_VOTER, true, 0);

		/*
@@ -2258,27 +2229,24 @@ static int __smblib_set_prop_pd_active(struct smb_charger *chg, bool pd_active)
		 * It is guaranteed that pd_active is set prior to
		 * pd_current_max
		 */
		rc = vote(chg->usb_icl_votable, PD_VOTER, true, USBIN_500MA);
		if (rc < 0)
			smblib_err(chg, "Couldn't vote for USB ICL rc=%d\n",
									rc);

		/* since PD was found the cable must be non-legacy */
		vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, false, 0);

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

		/* remove USB_PSY_VOTER */
		rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
		if (rc < 0)
			smblib_err(chg, "Couldn't unvote USB_PSY rc=%d\n", rc);
		vote(chg->usb_icl_votable, PD_VOTER, true, USBIN_500MA);
	} else {
		vote(chg->pd_allowed_votable, PD_VOTER, true, 0);
		vote(chg->usb_icl_votable, PD_VOTER, false, 0);
		vote(chg->usb_irq_enable_votable, PD_VOTER, false, 0);

		/* PD hard resets failed, rerun apsd */
		if (chg->ok_to_pd) {
			chg->ok_to_pd = false;
			rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
					HVDCP_EN_BIT | BC1P2_SRC_DETECT_BIT,
					HVDCP_EN_BIT | BC1P2_SRC_DETECT_BIT);
			if (rc < 0) {
				dev_err(chg->dev,
					"Couldn't disable APSD rc=%d\n", rc);
				return rc;
			}
			smblib_rerun_apsd(chg);
		}
	}

	smblib_update_usb_type(chg);
@@ -2286,15 +2254,6 @@ static int __smblib_set_prop_pd_active(struct smb_charger *chg, bool pd_active)
	return rc;
}

int smblib_set_prop_pd_active(struct smb_charger *chg,
			      const union power_supply_propval *val)
{
	if (!get_effective_result(chg->pd_allowed_votable))
		return -EINVAL;

	return __smblib_set_prop_pd_active(chg, val->intval);
}

int smblib_set_prop_ship_mode(struct smb_charger *chg,
				const union power_supply_propval *val)
{
@@ -2605,11 +2564,7 @@ irqreturn_t icl_change_irq_handler(int irq, void *data)

static void smblib_micro_usb_plugin(struct smb_charger *chg, bool vbus_rising)
{
	if (vbus_rising) {
		/* use the typec flag even though its not typec */
		chg->typec_present = 1;
	} else {
		chg->typec_present = 0;
	if (!vbus_rising) {
		smblib_update_usb_type(chg);
		smblib_notify_device_mode(chg, false);
		smblib_uusb_removal(chg);
@@ -2712,12 +2667,10 @@ irqreturn_t usb_plugin_irq_handler(int irq, void *data)
	struct smb_irq_data *irq_data = data;
	struct smb_charger *chg = irq_data->parent_data;

	mutex_lock(&chg->lock);
	if (chg->pd_hard_reset)
		smblib_usb_plugin_hard_reset_locked(chg);
	else
		smblib_usb_plugin_locked(chg);
	mutex_unlock(&chg->lock);

	return IRQ_HANDLED;
}
@@ -2806,8 +2759,6 @@ static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg,
	if (!rising)
		return;

	vote(chg->pd_disallowed_votable_indirect, APSD_VOTER, false, 0);

	if (chg->mode == PARALLEL_MASTER)
		vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, true, 0);

@@ -2820,33 +2771,19 @@ static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg,
static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg,
					      bool rising, bool qc_charger)
{
	const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);

	/* Hold off PD only until hvdcp 2.0 detection timeout */
	if (rising) {

		/* enable HDC and ICL irq for QC2/3 charger */
		if (qc_charger)
			vote(chg->usb_irq_enable_votable, QC_VOTER, true, 0);
		else
			vote(chg->pd_disallowed_votable_indirect, APSD_VOTER,
							false, 0);

		/*
		 * HVDCP detection timeout done
		 * If adapter is not QC2.0/QC3.0 - it is a plain old DCP.
		 * enforce DCP ICL if specified
		 */
		if (!qc_charger && (apsd_result->bit & DCP_CHARGER_BIT))
			/* enforce DCP ICL if specified */
			vote(chg->usb_icl_votable, DCP_VOTER,
				chg->dcp_icl_ua != -EINVAL, chg->dcp_icl_ua);

		/*
		 * if pd is not allowed, then set pd_active = false right here,
		 * so that it starts the hvdcp engine
		 */
		if (!get_effective_result(chg->pd_allowed_votable))
			__smblib_set_prop_pd_active(chg, 0);
	}

	smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s %s\n", __func__,
@@ -2873,19 +2810,12 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
	switch (apsd_result->bit) {
	case SDP_CHARGER_BIT:
	case CDP_CHARGER_BIT:
		/* if not DCP then no hvdcp timeout happens. Enable pd here */
		vote(chg->pd_disallowed_votable_indirect, APSD_VOTER,
				false, 0);
		if ((chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
				|| chg->use_extcon)
			smblib_notify_device_mode(chg, true);
		break;
	case OCP_CHARGER_BIT:
	case FLOAT_CHARGER_BIT:
		/* if not DCP then no hvdcp timeout happens, Enable pd here. */
		vote(chg->pd_disallowed_votable_indirect, APSD_VOTER,
				false, 0);
		break;
	case DCP_CHARGER_BIT:
		break;
	default:
@@ -2903,6 +2833,14 @@ irqreturn_t usb_source_change_irq_handler(int irq, void *data)
	int rc = 0;
	u8 stat;

	/*
	 * Prepared to run PD or PD is active. At this moment, APSD is disabled,
	 * but there still can be irq on apsd_done from previously unfinished
	 * APSD run, skip it.
	 */
	if (chg->ok_to_pd)
		return IRQ_HANDLED;

	rc = smblib_read(chg, APSD_STATUS_REG, &stat);
	if (rc < 0) {
		smblib_err(chg, "Couldn't read APSD_STATUS rc=%d\n", rc);
@@ -2957,32 +2895,68 @@ irqreturn_t usb_source_change_irq_handler(int irq, void *data)

static void typec_sink_insertion(struct smb_charger *chg)
{
	/* when a sink is inserted we should not wait on hvdcp timeout to
	 * enable pd
	 */
	vote(chg->pd_disallowed_votable_indirect, APSD_VOTER, false, 0);
	vote(chg->usb_icl_votable, OTG_VOTER, true, 0);

	if (chg->use_extcon) {
		smblib_notify_usb_host(chg, true);
		chg->otg_present = true;
	}

	if (!chg->pr_swap_in_progress)
		chg->ok_to_pd = !(*chg->pd_disabled) || chg->early_usb_attach;
}

static void typec_src_insertion(struct smb_charger *chg)
{
	int rc = 0;
	u8 stat;

	if (chg->pr_swap_in_progress)
		return;

	rc = smblib_read(chg, LEGACY_CABLE_STATUS_REG, &stat);
	if (rc < 0) {
		smblib_err(chg, "Couldn't read TYPE_C_STATE_MACHINE_STATUS_REG rc=%d\n",
			rc);
		return;
	}

	chg->typec_legacy = stat & TYPEC_LEGACY_CABLE_STATUS_BIT;
	chg->ok_to_pd = !(chg->typec_legacy || *chg->pd_disabled)
						|| chg->early_usb_attach;
	if (!chg->ok_to_pd) {
		rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
				HVDCP_EN_BIT | BC1P2_SRC_DETECT_BIT,
				HVDCP_EN_BIT | BC1P2_SRC_DETECT_BIT);
		if (rc < 0) {
			dev_err(chg->dev,
				"Couldn't disable APSD rc=%d\n", rc);
			return;
		}
		smblib_rerun_apsd(chg);
	}
}

static void typec_sink_removal(struct smb_charger *chg)
{
	smblib_set_charge_param(chg, &chg->param.freq_switcher,
			chg->chg_freq.freq_above_otg_threshold);
	chg->boost_current_ua = 0;
	vote(chg->usb_icl_votable, OTG_VOTER, false, 0);
}

static void smblib_handle_typec_removal(struct smb_charger *chg)
static void typec_src_removal(struct smb_charger *chg)
{
	int rc;
	struct smb_irq_data *data;
	struct storm_watch *wdata;

	rc = smblib_request_dpdm(chg, false);
	/* disable apsd */
	rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
				HVDCP_EN_BIT | BC1P2_SRC_DETECT_BIT,
				0);
	if (rc < 0)
		smblib_err(chg, "Couldn't disable DPDM rc=%d\n", rc);
		smblib_err(chg,
			"Couldn't disable APSD rc=%d\n", rc);

	smblib_update_usb_type(chg);

	if (chg->wa_flags & BOOST_BACK_WA) {
		data = chg->irq_info[SWITCHER_POWER_OK_IRQ].irq_data;
@@ -3007,11 +2981,6 @@ static void smblib_handle_typec_removal(struct smb_charger *chg)
	vote(chg->usb_icl_votable, OTG_VOTER, false, 0);
	vote(chg->usb_icl_votable, CTM_VOTER, false, 0);

	/* reset power delivery voters */
	vote(chg->pd_allowed_votable, PD_VOTER, false, 0);
	vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER, true, 0);
	vote(chg->pd_disallowed_votable_indirect, APSD_VOTER, true, 0);

	/* reset usb irq voters */
	vote(chg->usb_irq_enable_votable, PD_VOTER, false, 0);
	vote(chg->usb_irq_enable_votable, QC_VOTER, false, 0);
@@ -3023,14 +2992,10 @@ static void smblib_handle_typec_removal(struct smb_charger *chg)
	vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0);
	vote(chg->awake_votable, PL_DELAY_VOTER, false, 0);

	chg->vconn_attempts = 0;
	chg->otg_attempts = 0;
	chg->pulse_cnt = 0;
	chg->usb_icl_delta_ua = 0;
	chg->voltage_min_uv = MICRO_5V;
	chg->voltage_max_uv = MICRO_5V;
	chg->pd_active = 0;
	chg->pd_hard_reset = 0;

	/* write back the default FLOAT charger configuration */
	rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
@@ -3046,16 +3011,6 @@ static void smblib_handle_typec_removal(struct smb_charger *chg)
		smblib_err(chg, "Couldn't set USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V rc=%d\n",
			rc);

	/* clear exit sink based on cc */
	rc = smblib_masked_write(chg, TYPE_C_EXIT_STATE_CFG_REG,
						EXIT_SNK_BASED_ON_CC_BIT, 0);
	if (rc < 0)
		smblib_err(chg, "Couldn't clear exit_sink_based_on_cc rc=%d\n",
				rc);

	typec_sink_removal(chg);
	smblib_update_usb_type(chg);

	if (chg->use_extcon) {
		if (chg->otg_present)
			smblib_notify_usb_host(chg, false);
@@ -3063,29 +3018,7 @@ static void smblib_handle_typec_removal(struct smb_charger *chg)
			smblib_notify_device_mode(chg, false);
	}
	chg->otg_present = false;
}

static void smblib_handle_typec_insertion(struct smb_charger *chg)
{
	int rc;
	u8 stat;

	vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER, false, 0);

	rc = smblib_read(chg, TYPE_C_MISC_STATUS_REG, &stat);
	if (rc < 0) {
		smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
		return;
	}

	if (stat & SNK_SRC_MODE_BIT) {
		typec_sink_insertion(chg);
	} else {
		rc = smblib_request_dpdm(chg, true);
		if (rc < 0)
			smblib_err(chg, "Couldn't to enable DPDM rc=%d\n", rc);
		typec_sink_removal(chg);
	}
	chg->typec_legacy = false;
}

static void smblib_handle_rp_change(struct smb_charger *chg, int typec_mode)
@@ -3127,98 +3060,103 @@ static void smblib_handle_rp_change(struct smb_charger *chg, int typec_mode)
	vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, rp_ua);
}

static void smblib_handle_typec_cc_state_change(struct smb_charger *chg)
irqreturn_t typec_or_rid_detection_change_irq_handler(int irq, void *data)
{
	u8 stat;
	int typec_mode, rc;
	struct smb_irq_data *irq_data = data;
	struct smb_charger *chg = irq_data->parent_data;

	if (chg->pr_swap_in_progress)
		return;
	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");
		schedule_delayed_work(&chg->uusb_otg_work,
				msecs_to_jiffies(chg->otg_delay_ms));
		return IRQ_HANDLED;
	}

	typec_mode = smblib_get_prop_typec_mode(chg);
	if (chg->typec_present && (typec_mode != chg->typec_mode))
		smblib_handle_rp_change(chg, typec_mode);
	return IRQ_HANDLED;
}

	chg->typec_mode = typec_mode;
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;
	int typec_mode;

	if (!chg->typec_present && chg->typec_mode != POWER_SUPPLY_TYPEC_NONE) {
		chg->typec_present = true;
		smblib_dbg(chg, PR_MISC, "TypeC %s insertion\n",
			smblib_typec_mode_name[chg->typec_mode]);
		smblib_handle_typec_insertion(chg);
	} else if (chg->typec_present &&
				chg->typec_mode == POWER_SUPPLY_TYPEC_NONE) {
		chg->typec_present = false;
		smblib_dbg(chg, PR_MISC, "TypeC removal\n");
		smblib_handle_typec_removal(chg);
	if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB) {
		smblib_dbg(chg, PR_INTERRUPT,
				"Ignoring for micro USB\n");
		return IRQ_HANDLED;
	}

	rc = smblib_read(chg, TYPE_C_MISC_STATUS_REG, &stat);
	if (rc < 0) {
		smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
		return;
	}
	/* suspend usb if sink */
	if ((stat & SNK_SRC_MODE_BIT) && chg->typec_present)
		vote(chg->usb_icl_votable, OTG_VOTER, true, 0);
	else
		vote(chg->usb_icl_votable, OTG_VOTER, false, 0);
	typec_mode = smblib_get_prop_typec_mode(chg);
	if (chg->sink_src_mode != UNATTACHED_MODE
			&& (typec_mode != chg->typec_mode))
		smblib_handle_rp_change(chg, typec_mode);
	chg->typec_mode = typec_mode;

	smblib_dbg(chg, PR_INTERRUPT, "IRQ: cc-state-change; Type-C %s detected\n",
				smblib_typec_mode_name[chg->typec_mode]);
}

static void smblib_usb_typec_change(struct smb_charger *chg)
{
	int rc;
	u8 stat;

	smblib_handle_typec_cc_state_change(chg);
	power_supply_changed(chg->usb_psy);

	rc = smblib_read(chg, TYPE_C_MISC_STATUS_REG, &stat);
	if (rc < 0) {
		smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
		return;
	return IRQ_HANDLED;
}

	if (stat & TYPEC_VBUS_ERROR_STATUS_BIT)
		smblib_dbg(chg, PR_INTERRUPT, "IRQ: vbus-error\n");

	power_supply_changed(chg->usb_psy);
}

irqreturn_t typec_or_rid_detection_change_irq_handler(int irq, void *data)
irqreturn_t typec_attach_detach_irq_handler(int irq, void *data)
{
	struct smb_irq_data *irq_data = data;
	struct smb_charger *chg = irq_data->parent_data;
	u8 stat;
	int rc;

	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");
		schedule_delayed_work(&chg->uusb_otg_work,
				msecs_to_jiffies(chg->otg_delay_ms));
	smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);

	rc = smblib_read(chg, TYPE_C_STATE_MACHINE_STATUS_REG, &stat);
	if (rc < 0) {
		smblib_err(chg, "Couldn't read TYPE_C_STATE_MACHINE_STATUS_REG rc=%d\n",
			rc);
		return IRQ_HANDLED;
	}

	if (stat & TYPEC_ATTACH_DETACH_STATE_BIT) {
		rc = smblib_read(chg, TYPE_C_MISC_STATUS_REG, &stat);
		if (rc < 0) {
			smblib_err(chg, "Couldn't read TYPE_C_MISC_STATUS_REG rc=%d\n",
				rc);
			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 (stat & SNK_SRC_MODE_BIT) {
			chg->sink_src_mode = SRC_MODE;
			typec_sink_insertion(chg);
		} else {
			chg->sink_src_mode = SINK_MODE;
			typec_src_insertion(chg);
		}

	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;
	} else {
		switch (chg->sink_src_mode) {
		case SRC_MODE:
			typec_sink_removal(chg);
			break;
		case SINK_MODE:
			typec_src_removal(chg);
			break;
		default:
			break;
		}

		if (!chg->pr_swap_in_progress) {
			chg->ok_to_pd = false;
			chg->sink_src_mode = UNATTACHED_MODE;
			chg->early_usb_attach = false;
		}
	}

	power_supply_changed(chg->usb_psy);

	mutex_lock(&chg->lock);
	smblib_usb_typec_change(chg);
	mutex_unlock(&chg->lock);
	return IRQ_HANDLED;
}

@@ -3550,23 +3488,6 @@ static int smblib_create_votables(struct smb_charger *chg)
		return rc;
	}

	chg->pd_disallowed_votable_indirect
		= create_votable("PD_DISALLOWED_INDIRECT", VOTE_SET_ANY,
			smblib_pd_disallowed_votable_indirect_callback, chg);
	if (IS_ERR(chg->pd_disallowed_votable_indirect)) {
		rc = PTR_ERR(chg->pd_disallowed_votable_indirect);
		chg->pd_disallowed_votable_indirect = NULL;
		return rc;
	}

	chg->pd_allowed_votable = create_votable("PD_ALLOWED",
					VOTE_SET_ANY, NULL, NULL);
	if (IS_ERR(chg->pd_allowed_votable)) {
		rc = PTR_ERR(chg->pd_allowed_votable);
		chg->pd_allowed_votable = NULL;
		return rc;
	}

	chg->awake_votable = create_votable("AWAKE", VOTE_SET_ANY,
					smblib_awake_vote_callback,
					chg);
@@ -3604,10 +3525,6 @@ static void smblib_destroy_votables(struct smb_charger *chg)
		destroy_votable(chg->dc_suspend_votable);
	if (chg->usb_icl_votable)
		destroy_votable(chg->usb_icl_votable);
	if (chg->pd_disallowed_votable_indirect)
		destroy_votable(chg->pd_disallowed_votable_indirect);
	if (chg->pd_allowed_votable)
		destroy_votable(chg->pd_allowed_votable);
	if (chg->awake_votable)
		destroy_votable(chg->awake_votable);
	if (chg->chg_disable_votable)
@@ -3619,7 +3536,6 @@ int smblib_init(struct smb_charger *chg)
	int rc = 0;

	mutex_init(&chg->lock);
	mutex_init(&chg->otg_oc_lock);
	INIT_WORK(&chg->bms_update_work, bms_update_work);
	INIT_WORK(&chg->pl_update_work, pl_update_work);
	INIT_DELAYED_WORK(&chg->clear_hdc_work, clear_hdc_work);
@@ -3630,6 +3546,7 @@ int smblib_init(struct smb_charger *chg)
	chg->fake_capacity = -EINVAL;
	chg->fake_input_current_limited = -EINVAL;
	chg->fake_batt_status = -EINVAL;
	chg->sink_src_mode = UNATTACHED_MODE;

	switch (chg->mode) {
	case PARALLEL_MASTER:
+17 −10
Original line number Diff line number Diff line
@@ -78,6 +78,12 @@ enum smb_mode {
	NUM_MODES,
};

enum sink_src_mode {
	SINK_MODE,
	SRC_MODE,
	UNATTACHED_MODE,
};

enum {
	BOOST_BACK_WA			= BIT(0),
};
@@ -257,6 +263,7 @@ struct smb_charger {
	struct smb_params	param;
	struct smb_iio		iio;
	int			*debug_mask;
	int			*pd_disabled;
	enum smb_mode		mode;
	struct smb_chg_freq	chg_freq;
	int			smb_version;
@@ -266,7 +273,6 @@ struct smb_charger {
	/* locks */
	struct mutex		lock;
	struct mutex		ps_change_lock;
	struct mutex		otg_oc_lock;

	/* power supplies */
	struct power_supply		*batt_psy;
@@ -293,8 +299,6 @@ struct smb_charger {
	struct votable		*fcc_votable;
	struct votable		*fv_votable;
	struct votable		*usb_icl_votable;
	struct votable		*pd_disallowed_votable_indirect;
	struct votable		*pd_allowed_votable;
	struct votable		*awake_votable;
	struct votable		*pl_disable_votable;
	struct votable		*chg_disable_votable;
@@ -311,10 +315,17 @@ struct smb_charger {
	struct delayed_work	uusb_otg_work;
	struct delayed_work	bb_removal_work;

	/* cached status */
	/* pd */
	int			voltage_min_uv;
	int			voltage_max_uv;
	int			pd_active;
	bool			pd_hard_reset;
	bool			pr_swap_in_progress;
	bool			early_usb_attach;
	bool			ok_to_pd;
	bool			typec_legacy;

	/* cached status */
	bool			system_suspend_supported;
	int			boost_threshold_ua;
	int			system_temp_level;
@@ -330,15 +341,11 @@ struct smb_charger {
	int			connector_type;
	bool			otg_en;
	bool			suspend_input_on_debug_batt;
	int			otg_attempts;
	int			vconn_attempts;
	int			default_icl_ua;
	int			otg_cl_ua;
	bool			uusb_apsd_rerun_done;
	bool			pd_hard_reset;
	bool			typec_present;
	int			fake_input_current_limited;
	bool			pr_swap_in_progress;
	int			typec_mode;
	int			usb_icl_change_irq_enabled;
	u32			jeita_status;
@@ -347,6 +354,7 @@ struct smb_charger {
	bool			otg_present;
	int			hw_max_icl_ua;
	int			auto_recharge_soc;
	enum sink_src_mode	sink_src_mode;

	/* workaround flag */
	u32			wa_flags;
@@ -415,6 +423,7 @@ irqreturn_t usb_plugin_irq_handler(int irq, void *data);
irqreturn_t usb_source_change_irq_handler(int irq, void *data);
irqreturn_t icl_change_irq_handler(int irq, void *data);
irqreturn_t typec_state_change_irq_handler(int irq, void *data);
irqreturn_t typec_attach_detach_irq_handler(int irq, void *data);
irqreturn_t dc_plugin_irq_handler(int irq, void *data);
irqreturn_t high_duty_cycle_irq_handler(int irq, void *data);
irqreturn_t switcher_power_ok_irq_handler(int irq, void *data);
@@ -480,8 +489,6 @@ int smblib_get_prop_typec_cc_orientation(struct smb_charger *chg,
				union power_supply_propval *val);
int smblib_get_prop_typec_power_role(struct smb_charger *chg,
				union power_supply_propval *val);
int smblib_get_prop_pd_allowed(struct smb_charger *chg,
				union power_supply_propval *val);
int smblib_get_prop_input_current_settled(struct smb_charger *chg,
				union power_supply_propval *val);
int smblib_get_prop_input_voltage_settled(struct smb_charger *chg,
+5 −0

File changed.

Preview size limit exceeded, changes collapsed.

Loading