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

Commit 5fc29326 authored by tracychui's avatar tracychui
Browse files

Fixed USB preferences can not change in notifications area

root cause:usb hal service is not start due to without usb hal patch

How to fix:add usb hal patch

Issue:[JIRA] (ARFP3-172) NJPV<8901_USB>cant change USB preferences in notifications area

Change-Id: I5d10da573127a6c45d7097ab8f8bf93684ba5354
RiskArea:USB
parent 6cb5670a
Loading
Loading
Loading
Loading
+239 −0
Original line number Diff line number Diff line
@@ -1578,7 +1578,234 @@ static int smb5_init_batt_psy(struct smb5 *chip)

	return rc;
}
/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area start */
/******************************
 * DUAL ROLE REGISTRATION *
 ******************************/
static enum dual_role_property smb5_dr_properties[] = {
	DUAL_ROLE_PROP_SUPPORTED_MODES,
	DUAL_ROLE_PROP_MODE,
	DUAL_ROLE_PROP_PR,
	DUAL_ROLE_PROP_DR,
};

static int smb5_dr_prop_writeable(struct dual_role_phy_instance *dual_role,
					enum dual_role_property prop)
{
	int rc;

	switch (prop) {
	case DUAL_ROLE_PROP_MODE:
	case DUAL_ROLE_PROP_PR:
	case DUAL_ROLE_PROP_DR:
		rc = 1;
		break;
	default:
		rc = 0;
	}
	return rc;
}

static int smb5_dr_set_property(struct dual_role_phy_instance *dual_role,
					enum dual_role_property prop,
					const unsigned int *val)
{
	int rc = 0, current_mode;
	struct smb_charger *chg = dual_role_get_drvdata(dual_role);

	if (!chg || (chg->connector_type != POWER_SUPPLY_CONNECTOR_TYPEC))
		return -EINVAL;

	current_mode = smblib_get_typec_mode(chg);

	switch (prop) {
	case DUAL_ROLE_PROP_MODE:
		/* Force role */
		mutex_lock(&chg->dr_lock);
		if (chg->dr_swap_in_progress) {
			pr_debug("Already in mode transition skipping request\n");
			mutex_unlock(&chg->dr_lock);
			return 0;
		}
		switch (*val) {
		case DUAL_ROLE_PROP_MODE_UFP:
			if (current_mode == DUAL_ROLE_PROP_MODE_UFP)
				chg->dr_mode = DUAL_ROLE_PROP_MODE_UFP;
			else {
				rc = smblib_force_dr_mode(chg,
						DUAL_ROLE_PROP_MODE_UFP);
				if (rc)
					pr_err("Failed to force UFP mode rc=%d\n",
									rc);
				else
					chg->dr_swap_in_progress = true;
			}
			break;
		case DUAL_ROLE_PROP_MODE_DFP:
			if (current_mode == DUAL_ROLE_PROP_MODE_DFP)
				chg->dr_mode = DUAL_ROLE_PROP_MODE_DFP;
			else {
				rc = smblib_force_dr_mode(chg,
						DUAL_ROLE_PROP_MODE_DFP);
				if (rc)
					pr_err("Failed to force DFP mode rc=%d\n",
									rc);
				else
					chg->dr_swap_in_progress = true;
			}
			break;
		default:
			pr_debug("Invalid role(not DFP/UFP) %d\n", *val);
			rc = -EINVAL;
		}
		mutex_unlock(&chg->dr_lock);

		/*
		 * schedule delayed work to check if device latched to the
		 * requested mode.
		 */
		if (!rc && chg->dr_swap_in_progress) {
			cancel_delayed_work_sync(&chg->role_reversal_check);
			vote(chg->awake_votable, DR_SWAP_VOTER, true, 0);
			schedule_delayed_work(&chg->role_reversal_check,
				msecs_to_jiffies(ROLE_REVERSAL_DELAY_MS));
		}
		break;
	case DUAL_ROLE_PROP_PR:
	case DUAL_ROLE_PROP_DR:
		/* Force role */
		mutex_lock(&chg->dr_lock);
		if (chg->dr_swap_in_progress) {
			pr_debug("Already in mode transition skipping request\n");
			mutex_unlock(&chg->dr_lock);
			return 0;
		}
		switch (*val) {
		case DUAL_ROLE_PROP_PR_SNK:
			if (current_mode == DUAL_ROLE_PROP_MODE_UFP)
				chg->dr_mode = DUAL_ROLE_PROP_MODE_UFP;
			else {
				rc = smblib_force_dr_mode(chg,
						DUAL_ROLE_PROP_MODE_UFP);
				if (rc)
					pr_err("Failed to force UFP mode rc=%d\n",
									rc);
				else
					chg->dr_swap_in_progress = true;
			}
			break;
		case DUAL_ROLE_PROP_PR_SRC:
			if (current_mode == DUAL_ROLE_PROP_MODE_DFP)
				chg->dr_mode = DUAL_ROLE_PROP_MODE_DFP;
			else {
				rc = smblib_force_dr_mode(chg,
						DUAL_ROLE_PROP_MODE_DFP);
				if (rc)
					pr_err("Failed to force DFP mode rc=%d\n",
									rc);
				else
					chg->dr_swap_in_progress = true;
			}
			break;
		default:
			pr_debug("Invalid role(not DFP/UFP) %d\n", *val);
			rc = -EINVAL;
		}
		mutex_unlock(&chg->dr_lock);

		/*
		 * schedule delayed work to check if device latched to the
		 * requested mode.
		 */
		if (!rc && chg->dr_swap_in_progress) {
			cancel_delayed_work_sync(&chg->role_reversal_check);
			vote(chg->awake_votable, DR_SWAP_VOTER, true, 0);
			schedule_delayed_work(&chg->role_reversal_check,
				msecs_to_jiffies(ROLE_REVERSAL_DELAY_MS));
		}
		break;
	default:
		pr_debug("Invalid DUAL ROLE request %d\n", prop);
		rc = -EINVAL;
	}

	return rc;
}

static int smb5_dr_get_property(struct dual_role_phy_instance *dual_role,
					enum dual_role_property prop,
					unsigned int *val)
{
	struct smb_charger *chg = dual_role_get_drvdata(dual_role);
	unsigned int mode, power_role, data_role;

	if (!chg || (chg->connector_type != POWER_SUPPLY_CONNECTOR_TYPEC))
		return -EINVAL;

	mode = smblib_get_typec_mode(chg);

	switch (mode) {
	case DUAL_ROLE_PROP_MODE_UFP:
		power_role = DUAL_ROLE_PROP_PR_SNK;
		data_role = DUAL_ROLE_PROP_DR_DEVICE;
		break;
	case DUAL_ROLE_PROP_MODE_DFP:
		power_role = DUAL_ROLE_PROP_PR_SRC;
		data_role = DUAL_ROLE_PROP_DR_HOST;
		break;
	default:
		power_role = DUAL_ROLE_PROP_PR_NONE;
		data_role = DUAL_ROLE_PROP_DR_NONE;
	};

	switch (prop) {
	case DUAL_ROLE_PROP_SUPPORTED_MODES:
		*val = chg->dual_role->desc->supported_modes;
		break;
	case DUAL_ROLE_PROP_MODE:
		*val = mode;
		break;
	case DUAL_ROLE_PROP_PR:
		*val = power_role;
		break;
	case DUAL_ROLE_PROP_DR:
		*val = data_role;
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static const struct dual_role_phy_desc dr_desc = {
	.name = "otg_default",
	.supported_modes = DUAL_ROLE_SUPPORTED_MODES_DFP_AND_UFP,
	.properties = smb5_dr_properties,
	.num_properties = ARRAY_SIZE(smb5_dr_properties),
	.get_property = smb5_dr_get_property,
	.set_property = smb5_dr_set_property,
	.property_is_writeable = smb5_dr_prop_writeable,
};

static int smb5_init_dual_role_psy(struct smb5 *chip)
{
	struct smb_charger *chg = &chip->chg;
	int rc = 0;

	chg->dual_role = devm_dual_role_instance_register(chg->dev,
				&dr_desc);
	if (IS_ERR(chg->dual_role)) {
		pr_err("Couldn't register dual role\n");
		rc = PTR_ERR(chg->dual_role);
	} else {
		chg->dual_role->drv_data = chg;
		mutex_init(&chg->dr_lock);
	}

	return rc;
}
/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area end */
/******************************
 * VBUS REGULATOR REGISTRATION *
 ******************************/
@@ -2928,6 +3155,18 @@ static int smb5_probe(struct platform_device *pdev)
		goto cleanup;
	}

	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area start */
	/*
	 * Register the Android dual-role class (/sys/class/dual_role_usb/)
	 */
	if (chg->connector_type == POWER_SUPPLY_CONNECTOR_TYPEC) {
		rc = smb5_init_dual_role_psy(chip);
		if (rc < 0) {
			pr_err("Couldn't initialize batt psy rc=%d\n", rc);
			goto cleanup;
		}
	}
	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area end */
	rc = smb5_determine_initial_status(chip);
	if (rc < 0) {
		pr_err("Couldn't determine initial status rc=%d\n",
+188 −4
Original line number Diff line number Diff line
@@ -2158,6 +2158,38 @@ static int smblib_get_prop_dfp_mode(struct smb_charger *chg)
	return POWER_SUPPLY_TYPEC_NONE;
}

/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area start */
int smblib_get_typec_mode(struct smb_charger *chg)
{
	int rc;
	u8 stat = 0;

	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);
	}
	smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATE_MACHINE_STATUS_REG = 0x%02x\n",
			stat);

	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 DUAL_ROLE_PROP_MODE_NONE;
		}
		smblib_dbg(chg, PR_REGISTER, "TYPE_C_MISC_STATUS_REG = 0x%02x\n",
				stat);
		if (stat & SNK_SRC_MODE_BIT)
			return DUAL_ROLE_PROP_MODE_DFP;
		else
			return DUAL_ROLE_PROP_MODE_UFP;
	} else
		return DUAL_ROLE_PROP_MODE_NONE;
}
/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area end */

static int smblib_get_prop_typec_mode(struct smb_charger *chg)
{
	int rc;
@@ -3143,6 +3175,12 @@ void smblib_usb_plugin_locked(struct smb_charger *chg)
		smblib_micro_usb_plugin(chg, vbus_rising);

	power_supply_changed(chg->usb_psy);
	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area start */
		if (chg->dual_role)
		{
		  dual_role_instance_changed(chg->dual_role);
		}
	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area end */
	smblib_dbg(chg, PR_INTERRUPT, "IRQ: usbin-plugin %s\n",
					vbus_rising ? "attached" : "detached");
}
@@ -3434,7 +3472,12 @@ irqreturn_t usb_source_change_irq_handler(int irq, void *data)
	smblib_hvdcp_adaptive_voltage_change(chg);
	
	power_supply_changed(chg->usb_psy);

    /* [20190422][TracyChui]Fixed USB preferences can not change in notifications area start */
	if (chg->dual_role)
	{
		dual_role_instance_changed(chg->dual_role);
	}
	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area end */
	rc = smblib_read(chg, APSD_STATUS_REG, &stat);
	if (rc < 0) {
		smblib_err(chg, "Couldn't read APSD_STATUS rc=%d\n", rc);
@@ -3662,7 +3705,12 @@ irqreturn_t typec_state_change_irq_handler(int irq, void *data)
				smblib_typec_mode_name[chg->typec_mode]);

	power_supply_changed(chg->usb_psy);

	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area start */
	if (chg->dual_role)
	{
		dual_role_instance_changed(chg->dual_role);
	}
	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area end */
	return IRQ_HANDLED;
}

@@ -3715,10 +3763,21 @@ irqreturn_t typec_attach_detach_irq_handler(int irq, void *data)
			chg->sink_src_mode = UNATTACHED_MODE;
			chg->early_usb_attach = false;
		}
	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area start */
		if (!chg->dr_swap_in_progress)
		{
			smblib_force_dr_mode(chg, DUAL_ROLE_PROP_MODE_NONE);
		}
	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area end */
	}

	power_supply_changed(chg->usb_psy);

	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area start */
	if (chg->dual_role)
	{
		dual_role_instance_changed(chg->dual_role);
	}	
	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area end */
	return IRQ_HANDLED;
}

@@ -4332,6 +4391,121 @@ static void jeita_update_work(struct work_struct *work)
	chg->jeita_configured = true;
}

/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area start */
/* requested mode */
static char *dual_mode_text[] = {
	"ufp", "dfp", "none"
};

int smblib_force_dr_mode(struct smb_charger *chg, int mode)
{
	int rc = 0;

	switch (mode) {
	case DUAL_ROLE_PROP_MODE_UFP:
		rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
				TYPEC_POWER_ROLE_CMD_MASK | EN_TRY_SNK_BIT,
				EN_SNK_ONLY_BIT);
		if (rc < 0) {
			dev_err(chg->dev,
				"Couldn't enable snk rc=%d\n", rc);
			return rc;
		}
		rc = smblib_masked_write(chg, DCDC_CMD_OTG_REG, OTG_EN_BIT, 0);
		if (rc < 0) {
			smblib_err(chg, "Couldn't disable OTG rc=%d\n", rc);
			return rc;
		}
		break;
	case DUAL_ROLE_PROP_MODE_DFP:
		rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
				TYPEC_POWER_ROLE_CMD_MASK | EN_TRY_SNK_BIT,
				EN_SRC_ONLY_BIT);
		if (rc < 0) {
			dev_err(chg->dev,
				"Couldn't enable src rc=%d\n", rc);
			return rc;
		}
		rc = smblib_masked_write(chg, DCDC_CMD_OTG_REG, OTG_EN_BIT,
							OTG_EN_BIT);
		if (rc < 0) {
			smblib_err(chg, "Couldn't enable OTG rc=%d\n", rc);
			return rc;
		}
		break;
	case DUAL_ROLE_PROP_MODE_NONE:
		rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
				TYPEC_POWER_ROLE_CMD_MASK | EN_TRY_SNK_BIT,
				EN_TRY_SNK_BIT);
		if (rc < 0) {
			dev_err(chg->dev,
				"Couldn't enable try.snk rc=%d\n", rc);
			return rc;
		}
		rc = smblib_masked_write(chg, DCDC_CMD_OTG_REG, OTG_EN_BIT, 0);
		if (rc < 0) {
			smblib_err(chg, "Couldn't disable OTG rc=%d\n", rc);
			return rc;
		}
		break;
	default:
		smblib_err(chg, "power role %d not supported\n", mode);
		return -EINVAL;
}

	if (chg->dr_mode != mode) {
		chg->dr_mode = mode;
		pr_debug("Forced mode: %s\n",
					dual_mode_text[chg->dr_mode]);
	}

	return rc;
}

static void smblib_dr_role_check_work(struct work_struct *work)
{
	struct smb_charger *chg = container_of(work, struct smb_charger,
						role_reversal_check.work);
	int rc, typec_mode;
	struct smb_irq_data irq_data = {chg, "determine-typec-status"};

	typec_mode = smblib_get_typec_mode(chg);
	mutex_lock(&chg->dr_lock);

	switch (chg->dr_mode) {
	case DUAL_ROLE_PROP_MODE_UFP:
		if (typec_mode != DUAL_ROLE_PROP_MODE_UFP) {
			pr_debug("Role-reversal not latched to UFP in %d msec resetting to DRP mode\n",
					ROLE_REVERSAL_DELAY_MS);
			rc = smblib_force_dr_mode(chg,
						DUAL_ROLE_PROP_MODE_NONE);
			if (rc)
				pr_err("Failed to set DRP mode rc=%d\n", rc);
		}
		chg->dr_swap_in_progress = false;
		break;
	case DUAL_ROLE_PROP_MODE_DFP:
		if (typec_mode != DUAL_ROLE_PROP_MODE_DFP) {
			pr_debug("Role-reversal not latched to DFP in %d msec resetting to DRP mode\n",
					ROLE_REVERSAL_DELAY_MS);
			rc = smblib_force_dr_mode(chg,
						DUAL_ROLE_PROP_MODE_NONE);
			if (rc)
				pr_err("Failed to set DRP mode rc=%d\n", rc);
		} else if (chg->sink_src_mode != SRC_MODE) {
			typec_attach_detach_irq_handler(0, &irq_data);
		}
		chg->dr_swap_in_progress = false;
		break;
	default:
		pr_debug("Already in DRP mode\n");
		break;
	}
	mutex_unlock(&chg->dr_lock);
	vote(chg->awake_votable, DR_SWAP_VOTER, false, 0);
}
/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area end */

static int smblib_create_votables(struct smb_charger *chg)
{
	int rc = 0;
@@ -4441,6 +4615,9 @@ int smblib_init(struct smb_charger *chg)
	INIT_DELAYED_WORK(&chg->uusb_otg_work, smblib_uusb_otg_work);
	INIT_DELAYED_WORK(&chg->bb_removal_work, smblib_bb_removal_work);
	INIT_DELAYED_WORK(&chg->usbov_dbc_work, smblib_usbov_dbc_work);
	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area start */
	INIT_DELAYED_WORK(&chg->role_reversal_check, smblib_dr_role_check_work);
	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area end */

	if (chg->wa_flags & CHG_TERMINATION_WA) {
		INIT_WORK(&chg->chg_termination_work,
@@ -4474,6 +4651,10 @@ int smblib_init(struct smb_charger *chg)
	chg->fake_batt_status = -EINVAL;
	chg->jeita_configured = false;
	chg->sink_src_mode = UNATTACHED_MODE;
	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area start */
	chg->dr_mode = DUAL_ROLE_PROP_MODE_NONE;
	chg->dr_swap_in_progress = false;
 	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area end */

	switch (chg->mode) {
	case PARALLEL_MASTER:
@@ -4548,6 +4729,9 @@ int smblib_deinit(struct smb_charger *chg)
		cancel_delayed_work_sync(&chg->uusb_otg_work);
		cancel_delayed_work_sync(&chg->bb_removal_work);
		cancel_delayed_work_sync(&chg->usbov_dbc_work);
		/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area start */
		cancel_delayed_work_sync(&chg->role_reversal_check);
		/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area end */
		power_supply_unreg_notifier(&chg->nb);
		smblib_destroy_votables(chg);
		qcom_step_chg_deinit();
+28 −2
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@
#include <linux/regulator/consumer.h>
#include <linux/extcon.h>
#include <linux/alarmtimer.h>
/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area start */
#include <linux/usb/class-dual-role.h>
/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area end */
#include "storm-watch.h"

enum print_reason {
@@ -73,6 +76,9 @@ enum print_reason {
#define USBOV_DBC_VOTER			"USBOV_DBC_VOTER"
#define FCC_STEPPER_VOTER		"FCC_STEPPER_VOTER"
#define CHG_TERMINATION_VOTER		"CHG_TERMINATION_VOTER"
/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area start */
#define DR_SWAP_VOTER			"DR_SWAP_VOTER"
/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area end */

#define BOOST_BACK_STORM_COUNT	3
#define WEAK_CHG_STORM_COUNT	8
@@ -87,6 +93,9 @@ enum print_reason {
#define TYPEC_DEFAULT_CURRENT_UA	900000
#define TYPEC_MEDIUM_CURRENT_UA		1500000
#define TYPEC_HIGH_CURRENT_UA		3000000
/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area start */
#define ROLE_REVERSAL_DELAY_MS	2000
/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area end */

enum smb_mode {
	PARALLEL_MASTER = 0,
@@ -310,6 +319,9 @@ struct smb_charger {
	struct mutex		lock;
	struct mutex		ps_change_lock;
	struct mutex		vadc_lock;
	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area start */
    struct mutex		dr_lock;
	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area end */
	
	/* power supplies */
	struct power_supply		*batt_psy;
@@ -318,6 +330,9 @@ struct smb_charger {
	struct power_supply		*bms_psy;
	struct power_supply		*usb_main_psy;
	struct power_supply		*usb_port_psy;
	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area start */
	struct dual_role_phy_instance	*dual_role;
	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area end */
	enum power_supply_type		real_charger_type;

	/* notifiers */
@@ -355,6 +370,9 @@ struct smb_charger {
	struct delayed_work	uusb_otg_work;
	struct delayed_work	bb_removal_work;
	struct delayed_work	usbov_dbc_work;
	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area start */
    struct delayed_work role_reversal_check;
	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area end */
	
	/* alarm */
	struct alarm		moisture_protection_alarm;
@@ -393,6 +411,10 @@ struct smb_charger {
	int			typec_mode;
	int			usb_icl_change_irq_enabled;
	u32			jeita_status;
	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area start */
	u32			dr_mode;
	bool		dr_swap_in_progress;
	/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area end */
	u8			float_cfg;
	bool			use_extcon;
	bool			otg_present;
@@ -596,4 +618,8 @@ int smblib_icl_override(struct smb_charger *chg, bool override);

int smblib_init(struct smb_charger *chg);
int smblib_deinit(struct smb_charger *chg);
/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area start */
int smblib_get_typec_mode(struct smb_charger *chg);
int smblib_force_dr_mode(struct smb_charger *chg, int mode);
/* [20190422][TracyChui]Fixed USB preferences can not change in notifications area end */
#endif /* __SMB5_CHARGER_H */