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

Commit 80826e04 authored by Fenglin Wu's avatar Fenglin Wu Committed by Harry Yang
Browse files

power: qcom: smb2: Add REAL_TYPE property for usb power_supply



Add POWER_SUPPLY_PROP_REAL_TYPE property for usb_psy to present its real
charger type. POWER_SUPPLY_PROP_TYPE in usb_psy is always set to
POWER_SUPPLY_TYPE_USB_PD for healthd to recognize it as an AC charger.
Also add usb_port_psy with POWER_SUPPLY_TYPE_USB type is added for healthd
to recognize it as an USB host. Their ONLINE properties will be updated
according to the VBUS status, type-c mode and real charger type.
With this type being set statically, update the usb phy and pd policy
engine code to look at real type.

Change-Id: I90aa69325cc82b09dfb513c0eeecbc61e092a57f
Signed-off-by: default avatarFenglin Wu <fenglinw@codeaurora.org>
Signed-off-by: default avatarAbhijeet Dharmapurikar <adharmap@codeaurora.org>
parent e8615ac1
Loading
Loading
Loading
Loading
+119 −5
Original line number Diff line number Diff line
@@ -427,6 +427,7 @@ static enum power_supply_property smb2_usb_props[] = {
	POWER_SUPPLY_PROP_PE_START,
	POWER_SUPPLY_PROP_CTM_CURRENT_MAX,
	POWER_SUPPLY_PROP_HW_CURRENT_MAX,
	POWER_SUPPLY_PROP_REAL_TYPE,
};

static int smb2_usb_get_prop(struct power_supply *psy,
@@ -446,6 +447,16 @@ static int smb2_usb_get_prop(struct power_supply *psy,
		break;
	case POWER_SUPPLY_PROP_ONLINE:
		rc = smblib_get_prop_usb_online(chg, val);
		if (!val->intval)
			break;

		rc = smblib_get_prop_typec_mode(chg, val);
		if ((val->intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT ||
			chg->micro_usb_mode) &&
			chg->real_charger_type == POWER_SUPPLY_TYPE_USB)
			val->intval = 0;
		else
			val->intval = 1;
		break;
	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
		val->intval = chg->voltage_min_uv;
@@ -463,10 +474,13 @@ static int smb2_usb_get_prop(struct power_supply *psy,
		rc = smblib_get_prop_usb_current_max(chg, val);
		break;
	case POWER_SUPPLY_PROP_TYPE:
		val->intval = POWER_SUPPLY_TYPE_USB_PD;
		break;
	case POWER_SUPPLY_PROP_REAL_TYPE:
		if (chip->bad_part)
			val->intval = POWER_SUPPLY_TYPE_USB;
			val->intval = POWER_SUPPLY_TYPE_USB_PD;
		else
			val->intval = chg->usb_psy_desc.type;
			val->intval = chg->real_charger_type;
		break;
	case POWER_SUPPLY_PROP_TYPEC_MODE:
		if (chg->micro_usb_mode)
@@ -608,7 +622,7 @@ static int smb2_init_usb_psy(struct smb2 *chip)
	struct smb_charger *chg = &chip->chg;

	chg->usb_psy_desc.name			= "usb";
	chg->usb_psy_desc.type			= POWER_SUPPLY_TYPE_UNKNOWN;
	chg->usb_psy_desc.type			= POWER_SUPPLY_TYPE_USB_PD;
	chg->usb_psy_desc.properties		= smb2_usb_props;
	chg->usb_psy_desc.num_properties	= ARRAY_SIZE(smb2_usb_props);
	chg->usb_psy_desc.get_property		= smb2_usb_get_prop;
@@ -628,6 +642,97 @@ static int smb2_init_usb_psy(struct smb2 *chip)
	return 0;
}

/********************************
 * USB PC_PORT PSY REGISTRATION *
 ********************************/
static enum power_supply_property smb2_usb_port_props[] = {
	POWER_SUPPLY_PROP_TYPE,
	POWER_SUPPLY_PROP_ONLINE,
};

static int smb2_usb_port_get_prop(struct power_supply *psy,
		enum power_supply_property psp,
		union power_supply_propval *val)
{
	struct smb2 *chip = power_supply_get_drvdata(psy);
	struct smb_charger *chg = &chip->chg;
	int rc = 0;

	switch (psp) {
	case POWER_SUPPLY_PROP_TYPE:
		val->intval = POWER_SUPPLY_TYPE_USB;
		break;
	case POWER_SUPPLY_PROP_ONLINE:
		rc = smblib_get_prop_usb_online(chg, val);
		if (!val->intval)
			break;

		rc = smblib_get_prop_typec_mode(chg, val);
		if ((val->intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT ||
			chg->micro_usb_mode) &&
			chg->real_charger_type == POWER_SUPPLY_TYPE_USB)
			val->intval = 1;
		else
			val->intval = 0;
		break;
	default:
		pr_err_ratelimited("Get prop %d is not supported in pc_port\n",
				psp);
		return -EINVAL;
	}

	if (rc < 0) {
		pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
		return -ENODATA;
	}

	return 0;
}

static int smb2_usb_port_set_prop(struct power_supply *psy,
		enum power_supply_property psp,
		const union power_supply_propval *val)
{
	int rc = 0;

	switch (psp) {
	default:
		pr_err_ratelimited("Set prop %d is not supported in pc_port\n",
				psp);
		rc = -EINVAL;
		break;
	}

	return rc;
}

static const struct power_supply_desc usb_port_psy_desc = {
	.name		= "pc_port",
	.type		= POWER_SUPPLY_TYPE_USB,
	.properties	= smb2_usb_port_props,
	.num_properties	= ARRAY_SIZE(smb2_usb_port_props),
	.get_property	= smb2_usb_port_get_prop,
	.set_property	= smb2_usb_port_set_prop,
};

static int smb2_init_usb_port_psy(struct smb2 *chip)
{
	struct power_supply_config usb_port_cfg = {};
	struct smb_charger *chg = &chip->chg;

	usb_port_cfg.drv_data = chip;
	usb_port_cfg.of_node = chg->dev->of_node;
	chg->usb_port_psy = power_supply_register(chg->dev,
						  &usb_port_psy_desc,
						  &usb_port_cfg);
	if (IS_ERR(chg->usb_port_psy)) {
		pr_err("Couldn't register USB pc_port power supply\n");
		return PTR_ERR(chg->usb_port_psy);
	}

	return 0;
}

/*****************************
 * USB MAIN PSY REGISTRATION *
 *****************************/
@@ -2270,7 +2375,13 @@ static int smb2_probe(struct platform_device *pdev)

	rc = smb2_init_usb_main_psy(chip);
	if (rc < 0) {
		pr_err("Couldn't initialize usb psy rc=%d\n", rc);
		pr_err("Couldn't initialize usb main psy rc=%d\n", rc);
		goto cleanup;
	}

	rc = smb2_init_usb_port_psy(chip);
	if (rc < 0) {
		pr_err("Couldn't initialize usb pc_port psy rc=%d\n", rc);
		goto cleanup;
	}

@@ -2328,7 +2439,7 @@ static int smb2_probe(struct platform_device *pdev)
	device_init_wakeup(chg->dev, true);

	pr_info("QPNP SMB2 probed successfully usb:present=%d type=%d batt:present = %d health = %d charge = %d\n",
		usb_present, chg->usb_psy_desc.type,
		usb_present, chg->real_charger_type,
		batt_present, batt_health, batt_charge_type);
	return rc;

@@ -2340,6 +2451,8 @@ static int smb2_probe(struct platform_device *pdev)
		power_supply_unregister(chg->usb_main_psy);
	if (chg->usb_psy)
		power_supply_unregister(chg->usb_psy);
	if (chg->usb_port_psy)
		power_supply_unregister(chg->usb_port_psy);
	if (chg->dc_psy)
		power_supply_unregister(chg->dc_psy);
	if (chg->vconn_vreg && chg->vconn_vreg->rdev)
@@ -2360,6 +2473,7 @@ static int smb2_remove(struct platform_device *pdev)

	power_supply_unregister(chg->batt_psy);
	power_supply_unregister(chg->usb_psy);
	power_supply_unregister(chg->usb_port_psy);
	regulator_unregister(chg->vconn_vreg->rdev);
	regulator_unregister(chg->vbus_vreg->rdev);

+7 −7
Original line number Diff line number Diff line
@@ -549,9 +549,9 @@ static const struct apsd_result *smblib_update_usb_type(struct smb_charger *chg)

	/* if PD is active, APSD is disabled so won't have a valid result */
	if (chg->pd_active)
		chg->usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_PD;
		chg->real_charger_type = POWER_SUPPLY_TYPE_USB_PD;
	else
		chg->usb_psy_desc.type = apsd_result->pst;
		chg->real_charger_type = apsd_result->pst;

	smblib_dbg(chg, PR_MISC, "APSD=%s PD=%d\n",
					apsd_result->name, chg->pd_active);
@@ -857,7 +857,7 @@ int smblib_set_icl_current(struct smb_charger *chg, int icl_ua)

	/* configure current */
	if (pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT
		&& (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_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);
@@ -878,10 +878,10 @@ int smblib_set_icl_current(struct smb_charger *chg, int icl_ua)
		/* remove override if no voters - hw defaults is desired */
		override = false;
	} else if (pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) {
		if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB)
		if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB)
			/* For std cable with type = SDP never override */
			override = false;
		else if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_CDP
		else if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_CDP
			&& icl_ua == 1500000)
			/*
			 * For std cable with type = CDP override only if
@@ -3320,7 +3320,7 @@ static void smblib_hvdcp_adaptive_voltage_change(struct smb_charger *chg)
	int pulses;

	power_supply_changed(chg->usb_main_psy);
	if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_HVDCP) {
	if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_HVDCP) {
		rc = smblib_read(chg, QC_CHANGE_STATUS_REG, &stat);
		if (rc < 0) {
			smblib_err(chg,
@@ -3348,7 +3348,7 @@ static void smblib_hvdcp_adaptive_voltage_change(struct smb_charger *chg)
		}
	}

	if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_HVDCP_3) {
	if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_HVDCP_3) {
		rc = smblib_read(chg, QC_PULSE_COUNT_STATUS_REG, &stat);
		if (rc < 0) {
			smblib_err(chg,
+2 −0
Original line number Diff line number Diff line
@@ -244,6 +244,8 @@ struct smb_charger {
	struct power_supply		*bms_psy;
	struct power_supply_desc	usb_psy_desc;
	struct power_supply		*usb_main_psy;
	struct power_supply		*usb_port_psy;
	enum power_supply_type		real_charger_type;

	/* notifiers */
	struct notifier_block	nb;
+2 −1
Original line number Diff line number Diff line
@@ -3743,7 +3743,8 @@ static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned int mA)
		}
	}

	power_supply_get_property(mdwc->usb_psy, POWER_SUPPLY_PROP_TYPE, &pval);
	power_supply_get_property(mdwc->usb_psy,
			POWER_SUPPLY_PROP_REAL_TYPE, &pval);
	if (pval.intval != POWER_SUPPLY_TYPE_USB)
		return 0;

+1 −1
Original line number Diff line number Diff line
@@ -2374,7 +2374,7 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
	pd->vbus_present = val.intval;

	ret = power_supply_get_property(pd->usb_psy,
			POWER_SUPPLY_PROP_TYPE, &val);
			POWER_SUPPLY_PROP_REAL_TYPE, &val);
	if (ret) {
		usbpd_err(&pd->dev, "Unable to read USB TYPE: %d\n", ret);
		return ret;