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

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

Merge "power: smb1351-charger: update drive to support parallel architecture"

parents fa12840e 23d22ee4
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
#define TAPER_END_VOTER			"TAPER_END_VOTER"
#define PL_TAPER_EARLY_BAD_VOTER	"PL_TAPER_EARLY_BAD_VOTER"
#define PARALLEL_PSY_VOTER		"PARALLEL_PSY_VOTER"
#define PL_HW_ABSENT_VOTER		"PL_HW_ABSENT_VOTER"

struct pl_data {
	int			pl_mode;
@@ -44,6 +45,7 @@ struct pl_data {
	struct votable		*pl_disable_votable;
	struct votable		*pl_awake_votable;
	struct work_struct	status_change_work;
	struct work_struct	pl_disable_forever_work;
	struct delayed_work	pl_taper_work;
	struct power_supply	*main_psy;
	struct power_supply	*pl_psy;
@@ -361,6 +363,15 @@ static int pl_fv_vote_callback(struct votable *votable, void *data,
	return 0;
}

static void pl_disable_forever_work(struct work_struct *work)
{
	struct pl_data *chip = container_of(work,
			struct pl_data, pl_disable_forever_work);

	/* Disable Parallel charger forever */
	vote(chip->pl_disable_votable, PL_HW_ABSENT_VOTER, true, 0);
}

static int pl_disable_vote_callback(struct votable *votable,
		void *data, int pl_disable, const char *client)
{
@@ -372,6 +383,18 @@ static int pl_disable_vote_callback(struct votable *votable,
	chip->taper_pct = 100;

	if (!pl_disable) { /* enable */
		rc = power_supply_get_property(chip->pl_psy,
				POWER_SUPPLY_PROP_CHARGE_TYPE, &pval);
		if (rc == -ENODEV) {
			/*
			 * -ENODEV is returned only if parallel chip
			 * is not present in the system.
			 * Disable parallel charger forever.
			 */
			schedule_work(&chip->pl_disable_forever_work);
			return rc;
		}

		rerun_election(chip->fv_votable);
		rerun_election(chip->fcc_votable);
		/*
@@ -697,6 +720,7 @@ static int pl_init(void)

	INIT_WORK(&chip->status_change_work, status_change_work);
	INIT_DELAYED_WORK(&chip->pl_taper_work, pl_taper_work);
	INIT_WORK(&chip->pl_disable_forever_work, pl_disable_forever_work);

	rc = pl_register_notifier(chip);
	if (rc < 0) {
+5 −9
Original line number Diff line number Diff line
@@ -385,6 +385,8 @@ static int smb2_parse_dt(struct smb2 *chip)

	chg->micro_usb_mode = of_property_read_bool(node, "qcom,micro-usb");

	chg->dcp_icl_ua = chip->dt.usb_icl_ua;

	return 0;
}

@@ -1338,7 +1340,6 @@ static int smb2_init_hw(struct smb2 *chip)
		return rc;
	}

	chg->dcp_icl_ua = chip->dt.usb_icl_ua;
	chg->boost_threshold_ua = chip->dt.boost_threshold_ua;

	rc = smblib_read(chg, APSD_RESULT_STATUS_REG, &stat);
@@ -1350,13 +1351,10 @@ static int smb2_init_hw(struct smb2 *chip)
	smblib_rerun_apsd_if_required(chg);

	/* clear the ICL override if it is set */
	if (stat & ICL_OVERRIDE_LATCH_BIT) {
		rc = smblib_write(chg, CMD_APSD_REG, ICL_OVERRIDE_BIT);
		if (rc < 0) {
	if (smblib_icl_override(chg, false) < 0) {
		pr_err("Couldn't disable ICL override rc=%d\n", rc);
		return rc;
	}
	}

	/* votes must be cast before configuring software control */
	vote(chg->usb_suspend_votable,
@@ -1367,8 +1365,6 @@ static int smb2_init_hw(struct smb2 *chip)
		DEFAULT_VOTER, true, chip->dt.fcc_ua);
	vote(chg->fv_votable,
		DEFAULT_VOTER, true, chip->dt.fv_uv);
	vote(chg->usb_icl_votable,
		DCP_VOTER, true, chip->dt.usb_icl_ua);
	vote(chg->dc_icl_votable,
		DEFAULT_VOTER, true, chip->dt.dc_icl_ua);
	vote(chg->hvdcp_disable_votable_indirect, DEFAULT_VOTER,
+106 −53
Original line number Diff line number Diff line
@@ -151,6 +151,31 @@ static int smblib_get_jeita_cc_delta(struct smb_charger *chg, int *cc_delta_ua)
	return 0;
}

int smblib_icl_override(struct smb_charger *chg, bool override)
{
	int rc;
	bool override_status;
	u8 stat;

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

	if (override != override_status) {
		rc = smblib_masked_write(chg, CMD_APSD_REG,
				ICL_OVERRIDE_BIT, ICL_OVERRIDE_BIT);
		if (rc < 0) {
			smblib_err(chg, "Couldn't override ICL rc=%d\n", rc);
			return rc;
		}
	}
	return 0;
}

/********************
 * REGISTER GETTERS *
 ********************/
@@ -591,6 +616,7 @@ static void smblib_uusb_removal(struct smb_charger *chg)
	/* reset both usbin current and voltage votes */
	vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
	vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0);
	vote(chg->pl_disable_votable, PL_DISABLE_HVDCP_VOTER, true, 0);

	cancel_delayed_work_sync(&chg->hvdcp_detect_work);

@@ -728,19 +754,33 @@ static int smblib_usb_icl_vote_callback(struct votable *votable, void *data,
{
	struct smb_charger *chg = data;
	int rc = 0;
	bool suspend = (icl_ua < USBIN_25MA);
	bool suspend, override;
	u8 icl_options = 0;

	override = true;
	/* remove override if no voters or type = SDP or CDP */
	if (client == NULL
		|| chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB
		|| chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_CDP)
		override = false;

	suspend = false;
	if (client && (icl_ua < USBIN_25MA))
		suspend = true;

	if (suspend)
		goto out;

	if (chg->usb_psy_desc.type != POWER_SUPPLY_TYPE_USB) {
		rc = smblib_set_charge_param(chg, &chg->param.usb_icl, icl_ua);
		if (client) {
			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);
				smblib_err(chg, "Couldn't set HC ICL rc=%d\n",
					rc);
				return rc;
			}

		}
		goto out;
	}

@@ -769,10 +809,14 @@ static int smblib_usb_icl_vote_callback(struct votable *votable, void *data,
	}

out:
	if (override)
		icl_options |= USBIN_MODE_CHG_BIT;

	rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
			CFG_USB3P0_SEL_BIT | USB51_MODE_BIT, icl_options);
		CFG_USB3P0_SEL_BIT | USB51_MODE_BIT | USBIN_MODE_CHG_BIT,
		icl_options);
	if (rc < 0) {
		smblib_err(chg, "Couldn't set ICL opetions rc=%d\n", rc);
		smblib_err(chg, "Couldn't set ICL options rc=%d\n", rc);
		return rc;
	}

@@ -783,6 +827,12 @@ out:
		return rc;
	}

	rc = smblib_icl_override(chg, override);
	if (rc < 0) {
		smblib_err(chg, "Couldn't set ICL override rc=%d\n", rc);
		return rc;
	}

	return rc;
}

@@ -1996,11 +2046,11 @@ int smblib_set_prop_usb_current_max(struct smb_charger *chg,
				true, val->intval);
	} else if (chg->system_suspend_supported) {
		if (val->intval <= USBIN_25MA)
			rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
					true, val->intval);
			rc = vote(chg->usb_icl_votable,
				PD_SUSPEND_SUPPORTED_VOTER, true, val->intval);
		else
			rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
					false, 0);
			rc = vote(chg->usb_icl_votable,
				PD_SUSPEND_SUPPORTED_VOTER, false, 0);
	}
	return rc;
}
@@ -2137,7 +2187,11 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
				"Couldn't enable vconn on CC line rc=%d\n", rc);
			return rc;
		}

		/*
		 * Enforce 500mA for PD until the real vote comes in later.
		 * 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",
@@ -2145,50 +2199,17 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
			return rc;
		}

		/* remove DCP_VOTER */
		rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
		if (rc < 0) {
			smblib_err(chg, "Couldn't vote for USB ICL rc=%d\n",
					rc);
			smblib_err(chg, "Couldn't unvote DCP rc=%d\n", rc);
			return rc;
		}

		rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
				USBIN_MODE_CHG_BIT, USBIN_MODE_CHG_BIT);
		if (rc < 0) {
			smblib_err(chg,
				"Couldn't change USB mode rc=%d\n", rc);
			return rc;
		}

		rc = smblib_masked_write(chg, CMD_APSD_REG,
				ICL_OVERRIDE_BIT, ICL_OVERRIDE_BIT);
		if (rc < 0) {
			smblib_err(chg,
				"Couldn't override APSD rc=%d\n", rc);
			return rc;
		}
	} else {
		rc = vote(chg->usb_icl_votable, DCP_VOTER, true,
				chg->dcp_icl_ua);
		if (rc < 0) {
			smblib_err(chg, "Couldn't vote for USB ICL rc=%d\n",
					rc);
			return rc;
		}

		rc = smblib_masked_write(chg, CMD_APSD_REG,
				ICL_OVERRIDE_BIT, 0);
		if (rc < 0) {
			smblib_err(chg,
				"Couldn't override APSD rc=%d\n", rc);
			return rc;
		}

		rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
				USBIN_MODE_CHG_BIT, 0);
		/* remove USB_PSY_VOTER */
		rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
		if (rc < 0) {
			smblib_err(chg,
				"Couldn't change USB mode rc=%d\n", rc);
			smblib_err(chg, "Couldn't unvote USB_PSY rc=%d\n", rc);
			return rc;
		}
	}
@@ -2782,6 +2803,9 @@ static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg,
	if (chg->mode == PARALLEL_MASTER)
		vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, true, 0);

	/* QC authentication done, parallel charger can be enabled now */
	vote(chg->pl_disable_votable, PL_DISABLE_HVDCP_VOTER, false, 0);

	/* the APSD done handler will set the USB supply type */
	apsd_result = smblib_get_apsd_result(chg);
	smblib_dbg(chg, PR_INTERRUPT, "IRQ: hvdcp-3p0-auth-done rising; %s detected\n",
@@ -2791,6 +2815,8 @@ 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_update_usb_type(chg);

	/* Hold off PD only until hvdcp 2.0 detection timeout */
	if (rising) {
		vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
@@ -2798,6 +2824,24 @@ static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg,
		if (get_effective_result(chg->pd_disallowed_votable_indirect))
			/* could be a legacy cable, try doing hvdcp */
			try_rerun_apsd_for_hvdcp(chg);

		/*
		 * HVDCP detection timeout done
		 * If adapter is not QC2.0/QC3.0 - it is a plain old DCP.
		 */
		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 adapter is not QC2.0/QC3.0 remove vote for parallel
		 * disable.
		 * Otherwise if adapter is QC2.0/QC3.0 wait for authentication
		 * to complete.
		 */
		if (!qc_charger)
			vote(chg->pl_disable_votable, PL_DISABLE_HVDCP_VOTER,
					false, 0);
	}

	smblib_dbg(chg, PR_INTERRUPT, "IRQ: smblib_handle_hvdcp_check_timeout %s\n",
@@ -2923,12 +2967,19 @@ static void typec_source_removal(struct smb_charger *chg)
	/* clear USB ICL vote for PD_VOTER */
	rc = vote(chg->usb_icl_votable, PD_VOTER, false, 0);
	if (rc < 0)
		smblib_err(chg, "Couldn't un-vote for USB ICL rc=%d\n", rc);
		smblib_err(chg, "Couldn't un-vote PD from USB ICL rc=%d\n", rc);

	/* clear USB ICL vote for USB_PSY_VOTER */
	rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
	if (rc < 0)
		smblib_err(chg, "Couldn't un-vote for USB ICL rc=%d\n", rc);
		smblib_err(chg,
			"Couldn't un-vote USB_PSY from USB ICL rc=%d\n", rc);

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

static void typec_source_insertion(struct smb_charger *chg)
@@ -2957,6 +3008,7 @@ static void smblib_handle_typec_removal(struct smb_charger *chg)
	vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, true, 0);
	vote(chg->pd_disallowed_votable_indirect, LEGACY_CABLE_VOTER, true, 0);
	vote(chg->pd_disallowed_votable_indirect, VBUS_CC_SHORT_VOTER, true, 0);
	vote(chg->pl_disable_votable, PL_DISABLE_HVDCP_VOTER, true, 0);

	/* reset votes from vbus_cc_short */
	vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER,
@@ -3514,6 +3566,7 @@ static int smblib_create_votables(struct smb_charger *chg)
		return rc;
	}
	vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, true, 0);
	vote(chg->pl_disable_votable, PL_DISABLE_HVDCP_VOTER, true, 0);

	chg->usb_suspend_votable = create_votable("USB_SUSPEND", VOTE_SET_ANY,
					smblib_usb_suspend_vote_callback,
+3 −0
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@ enum print_reason {
#define HVDCP_INDIRECT_VOTER		"HVDCP_INDIRECT_VOTER"
#define MICRO_USB_VOTER			"MICRO_USB_VOTER"
#define DEBUG_BOARD_VOTER		"DEBUG_BOARD_VOTER"
#define PD_SUSPEND_SUPPORTED_VOTER	"PD_SUSPEND_SUPPORTED_VOTER"
#define PL_DISABLE_HVDCP_VOTER		"PL_DISABLE_HVDCP_VOTER"

#define VCONN_MAX_ATTEMPTS	3
#define OTG_MAX_ATTEMPTS	3
@@ -405,6 +407,7 @@ void smblib_suspend_on_debug_battery(struct smb_charger *chg);
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_init(struct smb_charger *chg);
int smblib_deinit(struct smb_charger *chg);
+93 −65
Original line number Diff line number Diff line
@@ -461,7 +461,7 @@ struct smb1351_charger {

	int			parallel_pin_polarity_setting;
	bool			parallel_charger;
	bool			parallel_charger_present;
	bool			parallel_charger_suspended;
	bool			bms_controlled_charging;
	bool			apsd_rerun;
	bool			usbin_ov;
@@ -1409,34 +1409,27 @@ static int smb1351_battery_get_property(struct power_supply *psy,
static enum power_supply_property smb1351_parallel_properties[] = {
	POWER_SUPPLY_PROP_CHARGING_ENABLED,
	POWER_SUPPLY_PROP_STATUS,
	POWER_SUPPLY_PROP_PRESENT,
	POWER_SUPPLY_PROP_CURRENT_MAX,
	POWER_SUPPLY_PROP_VOLTAGE_MAX,
	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
	POWER_SUPPLY_PROP_CHARGE_TYPE,
	POWER_SUPPLY_PROP_PARALLEL_MODE,
};

static int smb1351_parallel_set_chg_present(struct smb1351_charger *chip,
						int present)
static int smb1351_parallel_set_chg_suspend(struct smb1351_charger *chip,
						int suspend)
{
	int rc;
	u8 reg, mask = 0;

	if (present == chip->parallel_charger_present) {
		pr_debug("present %d -> %d, skipping\n",
				chip->parallel_charger_present, present);
	if (chip->parallel_charger_suspended == suspend) {
		pr_debug("Skip same state request suspended = %d suspend=%d\n",
				chip->parallel_charger_suspended, !suspend);
		return 0;
	}

	if (present) {
		/* Check if SMB1351 is present */
		rc = smb1351_read_reg(chip, CHG_REVISION_REG, &reg);
		if (rc) {
			pr_debug("Failed to detect smb1351-parallel-charger, may be absent\n");
			return -ENODEV;
		}

	if (!suspend) {
		rc = smb_chip_get_version(chip);
		if (rc) {
			pr_err("Couldn't get version rc = %d\n", rc);
@@ -1476,6 +1469,26 @@ static int smb1351_parallel_set_chg_present(struct smb1351_charger *chip,
			}
		}

		/* control USB suspend via command bits */
		rc = smb1351_masked_write(chip, VARIOUS_FUNC_REG,
					APSD_EN_BIT | SUSPEND_MODE_CTRL_BIT,
						SUSPEND_MODE_CTRL_BY_I2C);
		if (rc) {
			pr_err("Couldn't set USB suspend rc=%d\n", rc);
			return rc;
		}

		/*
		 * When present is being set force USB suspend, start charging
		 * only when POWER_SUPPLY_PROP_CURRENT_MAX is set.
		 */
		rc = smb1351_usb_suspend(chip, CURRENT, true);
		if (rc) {
			pr_err("failed to suspend rc=%d\n", rc);
			return rc;
		}
		chip->usb_psy_ma = SUSPEND_CURRENT_MA;

		/* set chg en by pin active low  */
		reg = chip->parallel_pin_polarity_setting | USBCS_CTRL_BY_I2C;
		rc = smb1351_masked_write(chip, CHG_PIN_EN_CTRL_REG,
@@ -1485,15 +1498,6 @@ static int smb1351_parallel_set_chg_present(struct smb1351_charger *chip,
			return rc;
		}

		/* control USB suspend via command bits */
		rc = smb1351_masked_write(chip, VARIOUS_FUNC_REG,
						SUSPEND_MODE_CTRL_BIT,
						SUSPEND_MODE_CTRL_BY_I2C);
		if (rc) {
			pr_err("Couldn't set USB suspend rc=%d\n", rc);
			return rc;
		}

		/*
		 * setup USB 2.0/3.0 detection and USB 500/100
		 * command polarity
@@ -1508,23 +1512,21 @@ static int smb1351_parallel_set_chg_present(struct smb1351_charger *chip,
			return rc;
		}

		/* set fast charging current limit */
		chip->target_fastchg_current_max_ma = SMB1351_CHG_FAST_MIN_MA;
		rc = smb1351_fastchg_current_set(chip,
					chip->target_fastchg_current_max_ma);
		if (rc) {
			pr_err("Couldn't set fastchg current rc=%d\n", rc);
			return rc;
		}
	}
		chip->parallel_charger_suspended = false;
	} else {
		rc = smb1351_usb_suspend(chip, CURRENT, true);
		if (rc)
			pr_debug("failed to suspend rc=%d\n", rc);

	chip->parallel_charger_present = present;
	/*
	 * When present is being set force USB suspend, start charging
	 * only when POWER_SUPPLY_PROP_CURRENT_MAX is set.
	 */
		chip->usb_psy_ma = SUSPEND_CURRENT_MA;
	smb1351_usb_suspend(chip, CURRENT, true);
		chip->parallel_charger_suspended = true;
	}

	return 0;
}
@@ -1564,6 +1566,31 @@ static bool smb1351_is_input_current_limited(struct smb1351_charger *chip)
	return !!(reg & IRQ_IC_LIMIT_STATUS_BIT);
}

static bool smb1351_is_usb_present(struct smb1351_charger *chip)
{
	int rc;
	union power_supply_propval val = {0, };

	if (!chip->usb_psy)
		chip->usb_psy = power_supply_get_by_name("usb");
	if (!chip->usb_psy) {
		pr_err("USB psy not found\n");
		return false;
	}

	rc = power_supply_get_property(chip->usb_psy,
				POWER_SUPPLY_PROP_ONLINE, &val);
	if (rc < 0) {
		pr_err("Failed to get present property rc=%d\n", rc);
		return false;
	}

	if (val.intval)
		return true;

	return false;
}

static int smb1351_parallel_set_property(struct power_supply *psy,
				       enum power_supply_property prop,
				       const union power_supply_propval *val)
@@ -1577,38 +1604,30 @@ static int smb1351_parallel_set_property(struct power_supply *psy,
		 *CHG EN is controlled by pin in the parallel charging.
		 *Use suspend if disable charging by command.
		 */
		if (chip->parallel_charger_present)
		if (!chip->parallel_charger_suspended)
			rc = smb1351_usb_suspend(chip, USER, !val->intval);
		break;
	case POWER_SUPPLY_PROP_PRESENT:
		rc = smb1351_parallel_set_chg_present(chip, val->intval);
	case POWER_SUPPLY_PROP_INPUT_SUSPEND:
		rc = smb1351_parallel_set_chg_suspend(chip, val->intval);
		break;
	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
		if (chip->parallel_charger_present) {
		chip->target_fastchg_current_max_ma =
						val->intval / 1000;
		if (!chip->parallel_charger_suspended)
			rc = smb1351_fastchg_current_set(chip,
					chip->target_fastchg_current_max_ma);
		}
		break;
	case POWER_SUPPLY_PROP_CURRENT_MAX:
		if (chip->parallel_charger_present) {
			index = smb1351_get_closest_usb_setpoint(
						val->intval / 1000);
		index = smb1351_get_closest_usb_setpoint(val->intval / 1000);
		chip->usb_psy_ma = usb_chg_current[index];
		if (!chip->parallel_charger_suspended)
			rc = smb1351_set_usb_chg_current(chip,
						chip->usb_psy_ma);
		}
		break;
	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
		if (chip->parallel_charger_present &&
			(chip->vfloat_mv != val->intval)) {
		chip->vfloat_mv = val->intval / 1000;
		if (!chip->parallel_charger_suspended)
			rc = smb1351_float_voltage_set(chip, val->intval);
			if (!rc)
				chip->vfloat_mv = val->intval;
		} else {
			chip->vfloat_mv = val->intval;
		}
		break;
	default:
		return -EINVAL;
@@ -1638,41 +1657,49 @@ static int smb1351_parallel_get_property(struct power_supply *psy,
		val->intval = !chip->usb_suspended_status;
		break;
	case POWER_SUPPLY_PROP_CURRENT_MAX:
		if (chip->parallel_charger_present)
		if (!chip->parallel_charger_suspended)
			val->intval = chip->usb_psy_ma * 1000;
		else
			val->intval = 0;
		break;
	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
		if (!chip->parallel_charger_suspended)
			val->intval = chip->vfloat_mv;
		else
			val->intval = 0;
		break;
	case POWER_SUPPLY_PROP_PRESENT:
		val->intval = chip->parallel_charger_present;
	case POWER_SUPPLY_PROP_CHARGE_TYPE:
		val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
		/* Check if SMB1351 is present */
		if (smb1351_is_usb_present(chip)) {
			val->intval = smb1351_get_prop_charge_type(chip);
			if (val->intval == POWER_SUPPLY_CHARGE_TYPE_UNKNOWN) {
				pr_debug("Failed to charge type, charger may be absent\n");
				return -ENODEV;
			}
		}
		break;
	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
		if (chip->parallel_charger_present)
		if (!chip->parallel_charger_suspended)
			val->intval = chip->fastchg_current_max_ma * 1000;
		else
			val->intval = 0;
		break;
	case POWER_SUPPLY_PROP_STATUS:
		if (chip->parallel_charger_present)
		if (!chip->parallel_charger_suspended)
			val->intval = smb1351_get_prop_batt_status(chip);
		else
			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
		break;
	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
		if (chip->parallel_charger_present)
		if (!chip->parallel_charger_suspended)
			val->intval =
				smb1351_is_input_current_limited(chip) ? 1 : 0;
		else
			val->intval = 0;
		break;
	case POWER_SUPPLY_PROP_PARALLEL_MODE:
		if (chip->parallel_charger_present)
		val->intval = POWER_SUPPLY_PARALLEL_USBIN_USBIN;
		else
			val->intval = POWER_SUPPLY_PARALLEL_NONE;
		break;
	default:
		return -EINVAL;
@@ -3142,6 +3169,7 @@ static int smb1351_parallel_charger_probe(struct i2c_client *client,
	chip->client = client;
	chip->dev = &client->dev;
	chip->parallel_charger = true;
	chip->parallel_charger_suspended = true;

	chip->usb_suspended_status = of_property_read_bool(node,
					"qcom,charging-disabled");