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

Commit 124233f1 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "power: smb1390-psy: Support PPS constant current(CC) mode"

parents 6ece5e09 5e657181
Loading
Loading
Loading
Loading
+72 −0
Original line number Diff line number Diff line
@@ -292,6 +292,11 @@ enum {
	SMB_THERM,
};

static const struct clamp_config clamp_levels[] = {
	{ {0x11C6, 0x11F9, 0x13F1}, {0x60, 0x2E, 0x90} },
	{ {0x11C6, 0x11F9, 0x13F1}, {0x60, 0x2B, 0x9C} },
};

#define PMI632_MAX_ICL_UA	3000000
#define PM6150_MAX_FCC_UA	3000000
static int smb5_chg_config_init(struct smb5 *chip)
@@ -701,6 +706,33 @@ static int smb5_parse_dt(struct smb5 *chip)
	return 0;
}

static int smb5_set_prop_comp_clamp_level(struct smb_charger *chg,
			     const union power_supply_propval *val)
{
	int rc = 0, i;
	struct clamp_config clamp_config;
	enum comp_clamp_levels level;

	level = val->intval;
	if (level >= MAX_CLAMP_LEVEL) {
		pr_err("Invalid comp clamp level=%d\n", val->intval);
		return -EINVAL;
	}

	for (i = 0; i < ARRAY_SIZE(clamp_config.reg); i++) {
		rc = smblib_write(chg, clamp_levels[level].reg[i],
			     clamp_levels[level].val[i]);
		if (rc < 0)
			dev_err(chg->dev,
				"Failed to configure comp clamp settings for reg=0x%04x rc=%d\n",
				   clamp_levels[level].reg[i], rc);
	}

	chg->comp_clamp_level = val->intval;

	return rc;
}

/************************
 * USB PSY REGISTRATION *
 ************************/
@@ -732,6 +764,7 @@ static enum power_supply_property smb5_usb_props[] = {
	POWER_SUPPLY_PROP_VOLTAGE_MAX_LIMIT,
	POWER_SUPPLY_PROP_SMB_EN_MODE,
	POWER_SUPPLY_PROP_SMB_EN_REASON,
	POWER_SUPPLY_PROP_ADAPTER_CC_MODE,
	POWER_SUPPLY_PROP_SCOPE,
	POWER_SUPPLY_PROP_MOISTURE_DETECTED,
	POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED,
@@ -875,6 +908,9 @@ static int smb5_usb_get_prop(struct power_supply *psy,
		val->intval = get_client_vote(chg->usb_icl_votable,
					THERMAL_THROTTLE_VOTER);
		break;
	case POWER_SUPPLY_PROP_ADAPTER_CC_MODE:
		val->intval = chg->adapter_cc_mode;
		break;
	default:
		pr_err("get prop %d is not supported in usb\n", psp);
		rc = -EINVAL;
@@ -961,6 +997,9 @@ static int smb5_usb_set_prop(struct power_supply *psy,
	case POWER_SUPPLY_PROP_VOLTAGE_MAX_LIMIT:
		smblib_set_prop_usb_voltage_max_limit(chg, val);
		break;
	case POWER_SUPPLY_PROP_ADAPTER_CC_MODE:
		chg->adapter_cc_mode = val->intval;
		break;
	default:
		pr_err("set prop %d is not supported\n", psp);
		rc = -EINVAL;
@@ -978,6 +1017,7 @@ static int smb5_usb_prop_is_writeable(struct power_supply *psy,
	case POWER_SUPPLY_PROP_CONNECTOR_HEALTH:
	case POWER_SUPPLY_PROP_THERM_ICL_LIMIT:
	case POWER_SUPPLY_PROP_VOLTAGE_MAX_LIMIT:
	case POWER_SUPPLY_PROP_ADAPTER_CC_MODE:
		return 1;
	default:
		break;
@@ -1129,6 +1169,9 @@ static enum power_supply_property smb5_usb_main_props[] = {
	POWER_SUPPLY_PROP_TOGGLE_STAT,
	POWER_SUPPLY_PROP_MAIN_FCC_MAX,
	POWER_SUPPLY_PROP_IRQ_STATUS,
	POWER_SUPPLY_PROP_FORCE_MAIN_FCC,
	POWER_SUPPLY_PROP_FORCE_MAIN_ICL,
	POWER_SUPPLY_PROP_COMP_CLAMP_LEVEL,
};

static int smb5_usb_main_get_prop(struct power_supply *psy,
@@ -1177,6 +1220,17 @@ static int smb5_usb_main_get_prop(struct power_supply *psy,
	case POWER_SUPPLY_PROP_IRQ_STATUS:
		rc = smblib_get_irq_status(chg, val);
		break;
	case POWER_SUPPLY_PROP_FORCE_MAIN_FCC:
		rc = smblib_get_charge_param(chg, &chg->param.fcc,
							&val->intval);
		break;
	case POWER_SUPPLY_PROP_FORCE_MAIN_ICL:
		rc = smblib_get_charge_param(chg, &chg->param.usb_icl,
							&val->intval);
		break;
	case POWER_SUPPLY_PROP_COMP_CLAMP_LEVEL:
		val->intval = chg->comp_clamp_level;
		break;
	default:
		pr_debug("get prop %d is not supported in usb-main\n", psp);
		rc = -EINVAL;
@@ -1247,6 +1301,17 @@ static int smb5_usb_main_set_prop(struct power_supply *psy,
		chg->main_fcc_max = val->intval;
		rerun_election(chg->fcc_votable);
		break;
	case POWER_SUPPLY_PROP_FORCE_MAIN_FCC:
		vote_override(chg->fcc_main_votable, CC_MODE_VOTER,
				(val->intval < 0) ? false : true, val->intval);
		break;
	case POWER_SUPPLY_PROP_FORCE_MAIN_ICL:
		vote_override(chg->usb_icl_votable, CC_MODE_VOTER,
				(val->intval < 0) ? false : true, val->intval);
		break;
	case POWER_SUPPLY_PROP_COMP_CLAMP_LEVEL:
		rc = smb5_set_prop_comp_clamp_level(chg, val);
		break;
	default:
		pr_err("set prop %d is not supported\n", psp);
		rc = -EINVAL;
@@ -1264,6 +1329,9 @@ static int smb5_usb_main_prop_is_writeable(struct power_supply *psy,
	switch (psp) {
	case POWER_SUPPLY_PROP_TOGGLE_STAT:
	case POWER_SUPPLY_PROP_MAIN_FCC_MAX:
	case POWER_SUPPLY_PROP_FORCE_MAIN_FCC:
	case POWER_SUPPLY_PROP_FORCE_MAIN_ICL:
	case POWER_SUPPLY_PROP_COMP_CLAMP_LEVEL:
		rc = 1;
		break;
	default:
@@ -1452,6 +1520,7 @@ static enum power_supply_property smb5_batt_props[] = {
	POWER_SUPPLY_PROP_CURRENT_NOW,
	POWER_SUPPLY_PROP_CURRENT_QNOVO,
	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
	POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
	POWER_SUPPLY_PROP_TEMP,
	POWER_SUPPLY_PROP_TECHNOLOGY,
@@ -1543,6 +1612,9 @@ static int smb5_batt_get_prop(struct power_supply *psy,
		val->intval = get_client_vote(chg->fcc_votable,
					      BATT_PROFILE_VOTER);
		break;
	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
		val->intval = get_effective_result(chg->fcc_votable);
		break;
	case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
		rc = smblib_get_prop_batt_iterm(chg, val);
		break;
+117 −9
Original line number Diff line number Diff line
@@ -96,11 +96,15 @@
#define SWITCHER_TOGGLE_VOTER	"SWITCHER_TOGGLE_VOTER"
#define SOC_LEVEL_VOTER		"SOC_LEVEL_VOTER"
#define HW_DISABLE_VOTER	"HW_DISABLE_VOTER"
#define CC_MODE_VOTER		"CC_MODE_VOTER"

#define CP_MASTER		0
#define CP_SLAVE		1
#define THERMAL_SUSPEND_DECIDEGC	1400
#define MAX_ILIM_UA			3200000
#define MAX_ILIM_DUAL_CP_UA		6400000
#define CC_MODE_TAPER_DELTA_UA		200000
#define DEFAULT_TAPER_DELTA_UA		100000

#define smb1390_dbg(chip, reason, fmt, ...)				\
	do {								\
@@ -195,6 +199,8 @@ struct smb1390 {
	u32			pl_output_mode;
	u32			cp_role;
	enum isns_mode		current_capability;
	bool			batt_soc_validated;
	int			cp_slave_thr_taper_ua;
};

struct smb_cfg {
@@ -349,6 +355,28 @@ static int smb1390_isns_mode_control(struct smb1390 *chip, enum isns_mode mode)
	return rc;
}

static bool smb1390_is_adapter_cc_mode(struct smb1390 *chip)
{
	int rc;
	union power_supply_propval pval = {0, };

	if (!chip->usb_psy) {
		chip->usb_psy = power_supply_get_by_name("usb");
		if (!chip->usb_psy)
			return false;
	}

	rc = power_supply_get_property(chip->usb_psy,
				POWER_SUPPLY_PROP_ADAPTER_CC_MODE,
				&pval);
	if (rc < 0) {
		pr_err("Couldn't get PPS CC mode status rc=%d\n", rc);
		return false;
	}

	return pval.intval;
}

static bool is_cps_available(struct smb1390 *chip)
{
	if (!chip->cps_psy)
@@ -690,6 +718,30 @@ static int smb1390_get_isns_slave(struct smb1390 *chip,
	return rc;
}

static int smb1390_get_cp_ilim(struct smb1390 *chip,
			       union power_supply_propval *val)
{
	int rc = 0, status;

	if (is_cps_available(chip)) {
		if (!chip->ilim_votable) {
			chip->ilim_votable = find_votable("CP_ILIM");
			if (!chip->ilim_votable)
				return -EINVAL;
		}

		val->intval = get_effective_result(chip->ilim_votable);
	} else {
		rc = smb1390_read(chip, CORE_FTRIM_ILIM_REG, &status);
		if (!rc)
			val->intval =
				((status & CFG_ILIM_MASK) * 100000)
					+ 500000;
	}

	return rc;
}

static int smb1390_is_batt_soc_valid(struct smb1390 *chip)
{
	int rc;
@@ -818,7 +870,8 @@ static int smb1390_ilim_vote_cb(struct votable *votable, void *data,
		return -EINVAL;
	}

	ilim_uA = min(ilim_uA, MAX_ILIM_UA);
	ilim_uA = min(ilim_uA, (is_cps_available(chip) ?
				MAX_ILIM_DUAL_CP_UA : MAX_ILIM_UA));
	/* ILIM less than min_ilim_ua, disable charging */
	if (ilim_uA < chip->min_ilim_ua) {
		smb1390_dbg(chip, PR_INFO, "ILIM %duA is too low to allow charging\n",
@@ -919,6 +972,7 @@ static void smb1390_status_change_work(struct work_struct *work)
	if (!is_psy_voter_available(chip))
		goto out;

	if (!smb1390_is_adapter_cc_mode(chip))
		vote(chip->disable_votable, SOC_LEVEL_VOTER,
		     smb1390_is_batt_soc_valid(chip) ? false : true, 0);

@@ -937,7 +991,14 @@ static void smb1390_status_change_work(struct work_struct *work)
			goto out;
		}

		/* Check for SOC threshold only once before enabling CP */
		vote(chip->disable_votable, SRC_VOTER, false, 0);
		if (!chip->batt_soc_validated) {
			vote(chip->disable_votable, SOC_LEVEL_VOTER,
				smb1390_is_batt_soc_valid(chip) ?
				false : true, 0);
			chip->batt_soc_validated = true;
		}

		if (pval.intval == POWER_SUPPLY_CP_WIRELESS) {
			vote(chip->ilim_votable, ICL_VOTER, false, 0);
@@ -1007,10 +1068,12 @@ static void smb1390_status_change_work(struct work_struct *work)
			}
		}
	} else {
		chip->batt_soc_validated = false;
		vote(chip->disable_votable, SRC_VOTER, true, 0);
		vote(chip->disable_votable, TAPER_END_VOTER, false, 0);
		vote(chip->fcc_votable, CP_VOTER, false, 0);
		vote(chip->disable_votable, SOC_LEVEL_VOTER, true, 0);
		vote_override(chip->ilim_votable, CC_MODE_VOTER, false, 0);
	}

out:
@@ -1018,11 +1081,39 @@ static void smb1390_status_change_work(struct work_struct *work)
	chip->status_change_running = false;
}

static int smb1390_validate_slave_chg_taper(struct smb1390 *chip, int fcc_uA)
{
	int rc = 0;
	u8 mask;

	/*
	 * In Collapse mode, while in Taper, Disable the slave SMB1390
	 * when FCC drops below a specified threshold.
	 */
	if (fcc_uA < (chip->cp_slave_thr_taper_ua) && is_cps_available(chip)) {
		mask = CMD_EN_SWITCHER_BIT | CMD_EN_SL_BIT;
		rc = smb1390_masked_write(chip, CORE_CONTROL1_REG,
						  mask, CMD_EN_SWITCHER_BIT);
		if (rc < 0)
			return rc;
		/*
		 * Set ILIM of master CP to Max value = 3.2A once slave is
		 * disabled to prevent ILIM irq storm.
		 */
		smb1390_dbg(chip, PR_INFO, "Set Master ILIM to MAX, post Slave disable in taper, fcc=%d\n",
									fcc_uA);
		vote_override(chip->ilim_votable, CC_MODE_VOTER,
						true, MAX_ILIM_DUAL_CP_UA);
	}

	return rc;
}

static void smb1390_taper_work(struct work_struct *work)
{
	struct smb1390 *chip = container_of(work, struct smb1390, taper_work);
	union power_supply_propval pval = {0, };
	int rc, fcc_uA;
	int rc, fcc_uA, delta_fcc_uA;

	if (!is_psy_voter_available(chip))
		goto out;
@@ -1046,11 +1137,21 @@ static void smb1390_taper_work(struct work_struct *work)
		}

		if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER) {
			delta_fcc_uA =
				(smb1390_is_adapter_cc_mode(chip) ?
							CC_MODE_TAPER_DELTA_UA :
							DEFAULT_TAPER_DELTA_UA);
			fcc_uA = get_effective_result(chip->fcc_votable)
								- 100000;
								- delta_fcc_uA;
			smb1390_dbg(chip, PR_INFO, "taper work reducing FCC to %duA\n",
				fcc_uA);
			vote(chip->fcc_votable, CP_VOTER, true, fcc_uA);
			rc = smb1390_validate_slave_chg_taper(chip, fcc_uA);
			if (rc < 0) {
				pr_err("Couldn't Disable slave in Taper, rc=%d\n",
				       rc);
				goto out;
			}

			if (fcc_uA < (chip->min_ilim_ua * 2)) {
				vote(chip->disable_votable, TAPER_END_VOTER,
@@ -1167,10 +1268,7 @@ static int smb1390_get_prop(struct power_supply *psy,
			val->intval |= status;
		break;
	case POWER_SUPPLY_PROP_CP_ILIM:
		rc = smb1390_read(chip, CORE_FTRIM_ILIM_REG, &status);
		if (!rc)
			val->intval = ((status & CFG_ILIM_MASK) * 100000)
					+ 500000;
		rc = smb1390_get_cp_ilim(chip, val);
		break;
	case POWER_SUPPLY_PROP_CHIP_VERSION:
		val->intval = chip->pmic_rev_id->rev4;
@@ -1208,6 +1306,11 @@ static int smb1390_set_prop(struct power_supply *psy,
	case POWER_SUPPLY_PROP_CP_IRQ_STATUS:
		chip->irq_status = val->intval;
		break;
	case POWER_SUPPLY_PROP_CP_ILIM:
		if (chip->ilim_votable)
			vote_override(chip->ilim_votable, CC_MODE_VOTER,
							true, val->intval);
		break;
	default:
		smb1390_dbg(chip, PR_MISC, "charge pump power supply set prop %d not supported\n",
			prop);
@@ -1226,6 +1329,7 @@ static int smb1390_prop_is_writeable(struct power_supply *psy,
	case POWER_SUPPLY_PROP_CP_IRQ_STATUS:
	case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
	case POWER_SUPPLY_PROP_CURRENT_CAPABILITY:
	case POWER_SUPPLY_PROP_CP_ILIM:
		return 1;
	default:
		break;
@@ -1300,6 +1404,10 @@ static int smb1390_parse_dt(struct smb1390 *chip)
	chip->pl_output_mode = POWER_SUPPLY_PL_OUTPUT_VPH;
	of_property_read_u32(chip->dev->of_node, "qcom,parallel-output-mode",
			&chip->pl_output_mode);

	chip->cp_slave_thr_taper_ua = chip->min_ilim_ua * 3;
	of_property_read_u32(chip->dev->of_node, "qcom,cp-slave-thr-taper-ua",
			      &chip->cp_slave_thr_taper_ua);
	return 0;
}

+4 −1
Original line number Diff line number Diff line
@@ -5584,8 +5584,11 @@ static void typec_src_removal(struct smb_charger *chg)
	chg->voltage_max_uv = MICRO_5V;
	chg->usbin_forced_max_uv = 0;

	/* Reset CC mode Votes */
	/* Reset all CC mode votes */
	vote(chg->fcc_main_votable, MAIN_FCC_VOTER, false, 0);
	chg->adapter_cc_mode = 0;
	vote_override(chg->fcc_votable, CC_MODE_VOTER, false, 0);
	vote_override(chg->usb_icl_votable, CC_MODE_VOTER, false, 0);

	/* write back the default FLOAT charger configuration */
	rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
+16 −0
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ enum print_reason {
#define CHARGER_TYPE_VOTER		"CHARGER_TYPE_VOTER"
#define HDC_IRQ_VOTER			"HDC_IRQ_VOTER"
#define DETACH_DETECT_VOTER		"DETACH_DETECT_VOTER"
#define CC_MODE_VOTER			"CC_MODE_VOTER"
#define MAIN_FCC_VOTER			"MAIN_FCC_VOTER"

#define BOOST_BACK_STORM_COUNT	3
@@ -219,6 +220,17 @@ enum chg_term_config_src {
	ITERM_SRC_ANALOG
};

enum comp_clamp_levels {
	CLAMP_LEVEL_DEFAULT = 0,
	CLAMP_LEVEL_1,
	MAX_CLAMP_LEVEL,
};

struct clamp_config {
	u16 reg[3];
	u16 val[3];
};

struct smb_irq_info {
	const char			*name;
	const irq_handler_t		handler;
@@ -384,6 +396,9 @@ struct smb_charger {
	/* parallel charging */
	struct parallel_params	pl;

	/* CC Mode */
	int	adapter_cc_mode;

	/* regulators */
	struct smb_regulator	*vbus_vreg;
	struct smb_regulator	*vconn_vreg;
@@ -512,6 +527,7 @@ struct smb_charger {
	int			last_cc_soc;
	int			usbin_forced_max_uv;
	int			init_thermal_ua;
	u32			comp_clamp_level;

	/* workaround flag */
	u32			wa_flags;