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

Commit 568e87ad authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "power: smb5: Add die temp to regulate ICL on RST threshold"

parents 2ab44047 3b04872b
Loading
Loading
Loading
Loading
+17 −14
Original line number Diff line number Diff line
@@ -547,7 +547,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_TYPEC_SRC_RP,
	POWER_SUPPLY_PROP_LOW_POWER,
	POWER_SUPPLY_PROP_PD_ACTIVE,
	POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
@@ -557,10 +556,8 @@ static enum power_supply_property smb5_usb_props[] = {
	POWER_SUPPLY_PROP_CTM_CURRENT_MAX,
	POWER_SUPPLY_PROP_HW_CURRENT_MAX,
	POWER_SUPPLY_PROP_REAL_TYPE,
	POWER_SUPPLY_PROP_PR_SWAP,
	POWER_SUPPLY_PROP_PD_VOLTAGE_MAX,
	POWER_SUPPLY_PROP_PD_VOLTAGE_MIN,
	POWER_SUPPLY_PROP_SDP_CURRENT_MAX,
	POWER_SUPPLY_PROP_CONNECTOR_TYPE,
	POWER_SUPPLY_PROP_CONNECTOR_HEALTH,
	POWER_SUPPLY_PROP_VOLTAGE_MAX,
@@ -1798,15 +1795,6 @@ static int smb5_init_hw(struct smb5 *chip)
		}
	}

	/* Disable SMB Temperature ADC INT */
	rc = smblib_masked_write(chg, MISC_THERMREG_SRC_CFG_REG,
					 THERMREG_SMB_ADC_SRC_EN_BIT, 0);
	if (rc < 0) {
		dev_err(chg->dev, "Couldn't configure SMB thermal regulation  rc=%d\n",
				rc);
		return rc;
	}

	/*
	 * If SW thermal regulation WA is active then all the HW temperature
	 * comparators need to be disabled to prevent HW thermal regulation,
@@ -1820,6 +1808,15 @@ static int smb5_init_hw(struct smb5 *chip)
				rc);
			return rc;
		}
	} else {
		/* Allows software thermal regulation only */
		rc = smblib_write(chg, MISC_THERMREG_SRC_CFG_REG,
					 THERMREG_SW_ICL_ADJUST_BIT);
		if (rc < 0) {
			dev_err(chg->dev, "Couldn't configure SMB thermal regulation rc=%d\n",
					rc);
			return rc;
		}
	}

	/*
@@ -1891,8 +1888,8 @@ static int smb5_init_hw(struct smb5 *chip)
		smblib_rerun_apsd_if_required(chg);
	}

	/* clear the ICL override if it is set */
	rc = smblib_icl_override(chg, false);
	/* Use ICL results from HW */
	rc = smblib_icl_override(chg, HW_AUTO_MODE);
	if (rc < 0) {
		pr_err("Couldn't disable ICL override rc=%d\n", rc);
		return rc;
@@ -2436,8 +2433,14 @@ static struct smb_irq_info smb5_irqs[] = {
	[IMP_TRIGGER_IRQ] = {
		.name		= "imp-trigger",
	},
	/*
	 * triggered when DIE or SKIN or CONNECTOR temperature across
	 * either of the _REG_L, _REG_H, _RST, or _SHDN thresholds
	 */
	[TEMP_CHANGE_IRQ] = {
		.name		= "temp-change",
		.handler	= temp_change_irq_handler,
		.wake		= true,
	},
	[TEMP_CHANGE_SMB_IRQ] = {
		.name		= "temp-change-smb",
+89 −83
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@
	|| typec_mode == POWER_SUPPLY_TYPEC_SOURCE_HIGH)	\
	&& !chg->typec_legacy)

static void update_sw_icl_max(struct smb_charger *chg, int pst);

int smblib_read(struct smb_charger *chg, u16 addr, u8 *val)
{
	unsigned int value;
@@ -156,15 +158,50 @@ 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 smblib_icl_override(struct smb_charger *chg, enum icl_override_mode  mode)
{
	int rc;
	u8 usb51_mode, icl_override, apsd_override;

	rc = smblib_masked_write(chg, USBIN_LOAD_CFG_REG,
				ICL_OVERRIDE_AFTER_APSD_BIT,
				override ? ICL_OVERRIDE_AFTER_APSD_BIT : 0);
	if (rc < 0)
	switch (mode) {
	case SW_OVERRIDE_USB51_MODE:
		usb51_mode = 0;
		icl_override = ICL_OVERRIDE_BIT;
		apsd_override = 0;
		break;
	case SW_OVERRIDE_HC_MODE:
		usb51_mode = USBIN_MODE_CHG_BIT;
		icl_override = 0;
		apsd_override = ICL_OVERRIDE_AFTER_APSD_BIT;
		break;
	case HW_AUTO_MODE:
	default:
		usb51_mode = USBIN_MODE_CHG_BIT;
		icl_override = 0;
		apsd_override = 0;
		break;
	}

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

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

	rc = smblib_masked_write(chg, USBIN_LOAD_CFG_REG,
				ICL_OVERRIDE_AFTER_APSD_BIT, apsd_override);
	if (rc < 0) {
		smblib_err(chg, "Couldn't override ICL_AFTER_APSD rc=%d\n", rc);
		return rc;
	}

	return rc;
}
@@ -1166,42 +1203,25 @@ static int set_sdp_current(struct smb_charger *chg, int icl_ua)
	}

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

	return rc;
}

static int get_sdp_current(struct smb_charger *chg, int *icl_ua)
{
	int rc;
	u8 icl_options;
	bool usb3 = false;

	rc = smblib_read(chg, USBIN_ICL_OPTIONS_REG, &icl_options);
	rc = smblib_icl_override(chg, SW_OVERRIDE_USB51_MODE);
	if (rc < 0) {
		smblib_err(chg, "Couldn't get ICL options rc=%d\n", rc);
		smblib_err(chg, "Couldn't set ICL override rc=%d\n", rc);
		return rc;
	}

	usb3 = (icl_options & CFG_USB3P0_SEL_BIT);

	if (icl_options & USB51_MODE_BIT)
		*icl_ua = usb3 ? USBIN_900MA : USBIN_500MA;
	else
		*icl_ua = usb3 ? USBIN_150MA : USBIN_100MA;

	return rc;
}

int smblib_set_icl_current(struct smb_charger *chg, int icl_ua)
{
	int rc = 0;
	bool hc_mode = false, override = false;
	enum icl_override_mode icl_override = HW_AUTO_MODE;
	/* suspend if 25mA or less is requested */
	bool suspend = (icl_ua <= USBIN_25MA);

@@ -1249,25 +1269,11 @@ int smblib_set_icl_current(struct smb_charger *chg, int icl_ua)
			smblib_err(chg, "Couldn't set HC ICL rc=%d\n", rc);
			goto out;
		}
		hc_mode = true;

		/*
		 * Micro USB mode follows ICL register independent of override
		 * bit, configure override only for typeC mode.
		 */
		if (chg->connector_type == POWER_SUPPLY_CONNECTOR_TYPEC)
			override = true;
		icl_override = SW_OVERRIDE_HC_MODE;
	}

set_mode:
	rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
		USBIN_MODE_CHG_BIT, hc_mode ? USBIN_MODE_CHG_BIT : 0);
	if (rc < 0) {
		smblib_err(chg, "Couldn't set USBIN_ICL_OPTIONS rc=%d\n", rc);
		goto out;
	}

	rc = smblib_icl_override(chg, override);
	rc = smblib_icl_override(chg, icl_override);
	if (rc < 0) {
		smblib_err(chg, "Couldn't set ICL override rc=%d\n", rc);
		goto out;
@@ -1289,38 +1295,13 @@ int smblib_set_icl_current(struct smb_charger *chg, int icl_ua)

int smblib_get_icl_current(struct smb_charger *chg, int *icl_ua)
{
	int rc = 0;
	u8 load_cfg;
	bool override;

	if ((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT
		|| chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
		&& (chg->usb_psy->desc->type == POWER_SUPPLY_TYPE_USB)) {
		rc = get_sdp_current(chg, icl_ua);
		if (rc < 0) {
			smblib_err(chg, "Couldn't get SDP ICL rc=%d\n", rc);
			return rc;
		}
	} else {
		rc = smblib_read(chg, USBIN_LOAD_CFG_REG, &load_cfg);
		if (rc < 0) {
			smblib_err(chg, "Couldn't get load cfg rc=%d\n", rc);
			return rc;
		}
		override = load_cfg & ICL_OVERRIDE_AFTER_APSD_BIT;
		if (!override)
			return INT_MAX;
	int rc;

		/* override is set */
		rc = smblib_get_charge_param(chg, &chg->param.icl_max_stat,
					icl_ua);
		if (rc < 0) {
	rc = smblib_get_charge_param(chg, &chg->param.icl_max_stat, icl_ua);
	if (rc < 0)
		smblib_err(chg, "Couldn't get HC ICL rc=%d\n", rc);
			return rc;
		}
	}

	return 0;
	return rc;
}

int smblib_toggle_smb_en(struct smb_charger *chg, int toggle)
@@ -3613,6 +3594,8 @@ int smblib_set_prop_pd_voltage_max(struct smb_charger *chg,
int smblib_set_prop_pd_active(struct smb_charger *chg,
				const union power_supply_propval *val)
{
	const struct apsd_result *apsd = smblib_get_apsd_result(chg);

	int rc = 0;
	int sec_charger;

@@ -3620,6 +3603,8 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,

	smblib_apsd_enable(chg, !chg->pd_active);

	update_sw_icl_max(chg, apsd->pst);

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

@@ -3646,7 +3631,6 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
					rc);
		}
	} else {
		vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, SDP_100_MA);
		vote(chg->usb_icl_votable, PD_VOTER, false, 0);
		vote(chg->usb_irq_enable_votable, PD_VOTER, false, 0);

@@ -4359,10 +4343,8 @@ static void smblib_handle_hvdcp_detect_done(struct smb_charger *chg,

static void update_sw_icl_max(struct smb_charger *chg, int pst)
{
	union power_supply_propval pval;
	int typec_mode;
	int rp_ua;
	int rc;

	/* while PD is active it should have complete ICL control */
	if (chg->pd_active)
@@ -4414,15 +4396,8 @@ static void update_sw_icl_max(struct smb_charger *chg, int pst)
		break;
	case POWER_SUPPLY_TYPE_UNKNOWN:
	default:
		rc = smblib_get_prop_usb_present(chg, &pval);
		if (rc < 0) {
			smblib_err(chg, "Couldn't get usb present rc = %d\n",
					rc);
			return;
		}

		vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true,
				pval.intval ? SDP_CURRENT_UA : SDP_100_MA);
					SDP_100_MA);
		break;
	}
}
@@ -5106,6 +5081,37 @@ irqreturn_t wdog_bark_irq_handler(int irq, void *data)
	return IRQ_HANDLED;
}

static void smblib_die_rst_icl_regulate(struct smb_charger *chg)
{
	int rc;
	u8 temp;

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

	/* Regulate ICL on die temp crossing DIE_RST threshold */
	vote(chg->usb_icl_votable, DIE_TEMP_VOTER,
				temp & DIE_TEMP_RST_BIT, 500000);
}

/*
 * triggered when DIE or SKIN or CONNECTOR temperature across
 * either of the _REG_L, _REG_H, _RST, or _SHDN thresholds
 */
irqreturn_t temp_change_irq_handler(int irq, void *data)
{
	struct smb_irq_data *irq_data = data;
	struct smb_charger *chg = irq_data->parent_data;

	smblib_die_rst_icl_regulate(chg);

	return IRQ_HANDLED;
}

/**************
 * Additional USB PSY getters/setters
 * that call interrupt functions
+12 −1
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ enum print_reason {
#define CHG_STATE_VOTER			"CHG_STATE_VOTER"
#define TAPER_END_VOTER			"TAPER_END_VOTER"
#define THERMAL_DAEMON_VOTER		"THERMAL_DAEMON_VOTER"
#define DIE_TEMP_VOTER			"DIE_TEMP_VOTER"
#define BOOST_BACK_VOTER		"BOOST_BACK_VOTER"
#define MICRO_USB_VOTER			"MICRO_USB_VOTER"
#define DEBUG_BOARD_VOTER		"DEBUG_BOARD_VOTER"
@@ -228,6 +229,15 @@ enum thermal_status_levels {
	TEMP_BELOW_RANGE,
};

enum icl_override_mode {
	/* APSD/Type-C/QC auto */
	HW_AUTO_MODE,
	/* 100/150/500/900mA */
	SW_OVERRIDE_USB51_MODE,
	/* ICL other than USB51 */
	SW_OVERRIDE_HC_MODE,
};

/* EXTCON_USB and EXTCON_USB_HOST are mutually exclusive */
static const u32 smblib_extcon_exclusive[] = {0x3, 0};

@@ -518,6 +528,7 @@ irqreturn_t switcher_power_ok_irq_handler(int irq, void *data);
irqreturn_t wdog_snarl_irq_handler(int irq, void *data);
irqreturn_t wdog_bark_irq_handler(int irq, void *data);
irqreturn_t typec_or_rid_detection_change_irq_handler(int irq, void *data);
irqreturn_t temp_change_irq_handler(int irq, void *data);

int smblib_get_prop_input_suspend(struct smb_charger *chg,
				union power_supply_propval *val);
@@ -645,7 +656,7 @@ int smblib_get_iio_channel(struct smb_charger *chg, const char *propname,
int smblib_read_iio_channel(struct smb_charger *chg, struct iio_channel *chan,
							int div, int *data);
int smblib_configure_hvdcp_apsd(struct smb_charger *chg, bool enable);
int smblib_icl_override(struct smb_charger *chg, bool override);
int smblib_icl_override(struct smb_charger *chg, enum icl_override_mode mode);
enum alarmtimer_restart smblib_lpd_recheck_timer(struct alarm *alarm,
				ktime_t time);
int smblib_toggle_smb_en(struct smb_charger *chg, int toggle);
+4 −0
Original line number Diff line number Diff line
@@ -216,6 +216,9 @@ enum {
#define CMD_APSD_REG				(USBIN_BASE + 0x41)
#define APSD_RERUN_BIT				BIT(0)

#define CMD_ICL_OVERRIDE_REG			(USBIN_BASE + 0x42)
#define ICL_OVERRIDE_BIT			BIT(0)

#define CMD_HVDCP_2_REG				(USBIN_BASE + 0x43)
#define FORCE_12V_BIT				BIT(5)
#define FORCE_9V_BIT				BIT(4)
@@ -459,6 +462,7 @@ enum {
#define AICL_RERUN_TIME_12S_VAL			0x01

#define MISC_THERMREG_SRC_CFG_REG		(MISC_BASE + 0x70)
#define THERMREG_SW_ICL_ADJUST_BIT		BIT(7)
#define THERMREG_SMB_ADC_SRC_EN_BIT		BIT(5)
#define THERMREG_DIE_CMP_SRC_EN_BIT		BIT(0)