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

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

Merge "power: qcom: smb-lib: handle dynamic Rp change"

parents 2ca7082e dd08c620
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -46,7 +46,7 @@ static ssize_t power_supply_show_property(struct device *dev,
	static char *type_text[] = {
		"Unknown", "Battery", "UPS", "Mains", "USB", "USB_DCP",
		"USB_CDP", "USB_ACA", "USB_HVDCP", "USB_HVDCP_3", "USB_PD",
		"Wireless", "BMS", "Parallel", "Main", "Wipower",
		"Wireless", "USB_FLOAT", "BMS", "Parallel", "Main", "Wipower",
		"TYPEC", "TYPEC_UFP", "TYPEC_DFP"
	};
	static char *status_text[] = {
+6 −1
Original line number Diff line number Diff line
@@ -51,9 +51,12 @@
#define PROFILE_LOAD		"fg_profile_load"
#define DELTA_SOC		"fg_delta_soc"

/* Delta BSOC votable reasons */
/* Delta BSOC irq votable reasons */
#define DELTA_BSOC_IRQ_VOTER	"fg_delta_bsoc_irq"

/* Battery missing irq votable reasons */
#define BATT_MISS_IRQ_VOTER	"fg_batt_miss_irq"

#define DEBUG_PRINT_BUFFER_SIZE		64
/* 3 byte address + 1 space character */
#define ADDR_LEN			4
@@ -361,6 +364,7 @@ struct fg_chip {
	struct fg_irq_info	*irqs;
	struct votable		*awake_votable;
	struct votable		*delta_bsoc_irq_en_votable;
	struct votable		*batt_miss_irq_en_votable;
	struct fg_sram_param	*sp;
	struct fg_alg_flag	*alg_flags;
	int			*debug_mask;
@@ -467,6 +471,7 @@ extern void dump_sram(u8 *buf, int addr, int len);
extern int64_t twos_compliment_extend(int64_t val, int s_bit_pos);
extern s64 fg_float_decode(u16 val);
extern bool is_input_present(struct fg_chip *chip);
extern bool is_qnovo_en(struct fg_chip *chip);
extern void fg_circ_buf_add(struct fg_circ_buf *buf, int val);
extern void fg_circ_buf_clr(struct fg_circ_buf *buf);
extern int fg_circ_buf_avg(struct fg_circ_buf *buf, int *avg);
+33 −8
Original line number Diff line number Diff line
@@ -106,14 +106,17 @@ static struct fg_dbgfs dbgfs_data = {
static bool is_usb_present(struct fg_chip *chip)
{
	union power_supply_propval pval = {0, };
	int rc;

	if (!chip->usb_psy)
		chip->usb_psy = power_supply_get_by_name("usb");

	if (chip->usb_psy)
		power_supply_get_property(chip->usb_psy,
	if (!chip->usb_psy)
		return false;

	rc = power_supply_get_property(chip->usb_psy,
			POWER_SUPPLY_PROP_PRESENT, &pval);
	else
	if (rc < 0)
		return false;

	return pval.intval != 0;
@@ -122,14 +125,17 @@ static bool is_usb_present(struct fg_chip *chip)
static bool is_dc_present(struct fg_chip *chip)
{
	union power_supply_propval pval = {0, };
	int rc;

	if (!chip->dc_psy)
		chip->dc_psy = power_supply_get_by_name("dc");

	if (chip->dc_psy)
		power_supply_get_property(chip->dc_psy,
	if (!chip->dc_psy)
		return false;

	rc = power_supply_get_property(chip->dc_psy,
			POWER_SUPPLY_PROP_PRESENT, &pval);
	else
	if (rc < 0)
		return false;

	return pval.intval != 0;
@@ -140,6 +146,25 @@ bool is_input_present(struct fg_chip *chip)
	return is_usb_present(chip) || is_dc_present(chip);
}

bool is_qnovo_en(struct fg_chip *chip)
{
	union power_supply_propval pval = {0, };
	int rc;

	if (!chip->batt_psy)
		chip->batt_psy = power_supply_get_by_name("battery");

	if (!chip->batt_psy)
		return false;

	rc = power_supply_get_property(chip->batt_psy,
			POWER_SUPPLY_PROP_CHARGE_QNOVO_ENABLE, &pval);
	if (rc < 0)
		return false;

	return pval.intval != 0;
}

#define EXPONENT_SHIFT		11
#define EXPONENT_OFFSET		-9
#define MANTISSA_SIGN_BIT	10
+84 −42
Original line number Diff line number Diff line
@@ -904,6 +904,7 @@ static int fg_get_batt_id(struct fg_chip *chip)
		return ret;
	}

	vote(chip->batt_miss_irq_en_votable, BATT_MISS_IRQ_VOTER, true, 0);
	return rc;
}

@@ -1103,6 +1104,25 @@ static void fg_notify_charger(struct fg_chip *chip)
	fg_dbg(chip, FG_STATUS, "Notified charger on float voltage and FCC\n");
}

static int fg_batt_miss_irq_en_cb(struct votable *votable, void *data,
					int enable, const char *client)
{
	struct fg_chip *chip = data;

	if (!chip->irqs[BATT_MISSING_IRQ].irq)
		return 0;

	if (enable) {
		enable_irq(chip->irqs[BATT_MISSING_IRQ].irq);
		enable_irq_wake(chip->irqs[BATT_MISSING_IRQ].irq);
	} else {
		disable_irq_wake(chip->irqs[BATT_MISSING_IRQ].irq);
		disable_irq(chip->irqs[BATT_MISSING_IRQ].irq);
	}

	return 0;
}

static int fg_delta_bsoc_irq_en_cb(struct votable *votable, void *data,
					int enable, const char *client)
{
@@ -1402,6 +1422,7 @@ static int fg_cap_learning_done(struct fg_chip *chip)
static void fg_cap_learning_update(struct fg_chip *chip)
{
	int rc, batt_soc, batt_soc_msb;
	bool input_present = is_input_present(chip);

	mutex_lock(&chip->cl.lock);

@@ -1442,13 +1463,31 @@ static void fg_cap_learning_update(struct fg_chip *chip)
			chip->cl.init_cc_uah = 0;
		}

		if (chip->charge_status == POWER_SUPPLY_STATUS_DISCHARGING) {
			if (!input_present) {
				fg_dbg(chip, FG_CAP_LEARN, "Capacity learning aborted @ battery SOC %d\n",
					 batt_soc_msb);
				chip->cl.active = false;
				chip->cl.init_cc_uah = 0;
			}
		}

		if (chip->charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING) {
			if (is_qnovo_en(chip) && input_present) {
				/*
				 * Don't abort the capacity learning when qnovo
				 * is enabled and input is present where the
				 * charging status can go to "not charging"
				 * intermittently.
				 */
			} else {
				fg_dbg(chip, FG_CAP_LEARN, "Capacity learning aborted @ battery SOC %d\n",
					batt_soc_msb);
				chip->cl.active = false;
				chip->cl.init_cc_uah = 0;
			}
		}
	}

out:
	mutex_unlock(&chip->cl.lock);
@@ -1981,7 +2020,7 @@ static int fg_esr_fcc_config(struct fg_chip *chip)
{
	union power_supply_propval prop = {0, };
	int rc;
	bool parallel_en = false, qnovo_en = false;
	bool parallel_en = false, qnovo_en;

	if (is_parallel_charger_available(chip)) {
		rc = power_supply_get_property(chip->parallel_psy,
@@ -1994,10 +2033,7 @@ static int fg_esr_fcc_config(struct fg_chip *chip)
		parallel_en = prop.intval;
	}

	rc = power_supply_get_property(chip->batt_psy,
			POWER_SUPPLY_PROP_CHARGE_QNOVO_ENABLE, &prop);
	if (!rc)
		qnovo_en = prop.intval;
	qnovo_en = is_qnovo_en(chip);

	fg_dbg(chip, FG_POWER_SUPPLY, "chg_sts: %d par_en: %d qnov_en: %d esr_fcc_ctrl_en: %d\n",
		chip->charge_status, parallel_en, qnovo_en,
@@ -2498,6 +2534,23 @@ static void profile_load_work(struct work_struct *work)
	int rc;

	vote(chip->awake_votable, PROFILE_LOAD, true, 0);

	rc = fg_get_batt_id(chip);
	if (rc < 0) {
		pr_err("Error in getting battery id, rc:%d\n", rc);
		goto out;
	}

	rc = fg_get_batt_profile(chip);
	if (rc < 0) {
		pr_warn("profile for batt_id=%dKOhms not found..using OTP, rc:%d\n",
			chip->batt_id_ohms / 1000, rc);
		goto out;
	}

	if (!chip->profile_available)
		goto out;

	if (!is_profile_load_required(chip))
		goto done;

@@ -2562,9 +2615,9 @@ static void profile_load_work(struct work_struct *work)
	batt_psy_initialized(chip);
	fg_notify_charger(chip);
	chip->profile_loaded = true;
	chip->soc_reporting_ready = true;
	fg_dbg(chip, FG_STATUS, "profile loaded successfully");
out:
	chip->soc_reporting_ready = true;
	vote(chip->awake_votable, PROFILE_LOAD, false, 0);
}

@@ -3550,20 +3603,6 @@ static irqreturn_t fg_batt_missing_irq_handler(int irq, void *data)
		return IRQ_HANDLED;
	}

	rc = fg_get_batt_id(chip);
	if (rc < 0) {
		chip->soc_reporting_ready = true;
		pr_err("Error in getting battery id, rc:%d\n", rc);
		return IRQ_HANDLED;
	}

	rc = fg_get_batt_profile(chip);
	if (rc < 0) {
		chip->soc_reporting_ready = true;
		pr_err("Error in getting battery profile, rc:%d\n", rc);
		return IRQ_HANDLED;
	}

	clear_battery_profile(chip);
	schedule_delayed_work(&chip->profile_load_work, 0);

@@ -4330,6 +4369,9 @@ static void fg_cleanup(struct fg_chip *chip)
	if (chip->delta_bsoc_irq_en_votable)
		destroy_votable(chip->delta_bsoc_irq_en_votable);

	if (chip->batt_miss_irq_en_votable)
		destroy_votable(chip->batt_miss_irq_en_votable);

	if (chip->batt_id_chan)
		iio_channel_release(chip->batt_id_chan);

@@ -4387,6 +4429,7 @@ static int fg_gen3_probe(struct platform_device *pdev)
					chip);
	if (IS_ERR(chip->awake_votable)) {
		rc = PTR_ERR(chip->awake_votable);
		chip->awake_votable = NULL;
		goto exit;
	}

@@ -4395,6 +4438,16 @@ static int fg_gen3_probe(struct platform_device *pdev)
						fg_delta_bsoc_irq_en_cb, chip);
	if (IS_ERR(chip->delta_bsoc_irq_en_votable)) {
		rc = PTR_ERR(chip->delta_bsoc_irq_en_votable);
		chip->delta_bsoc_irq_en_votable = NULL;
		goto exit;
	}

	chip->batt_miss_irq_en_votable = create_votable("FG_BATT_MISS_IRQ",
						VOTE_SET_ANY,
						fg_batt_miss_irq_en_cb, chip);
	if (IS_ERR(chip->batt_miss_irq_en_votable)) {
		rc = PTR_ERR(chip->batt_miss_irq_en_votable);
		chip->batt_miss_irq_en_votable = NULL;
		goto exit;
	}

@@ -4419,19 +4472,6 @@ static int fg_gen3_probe(struct platform_device *pdev)
	INIT_DELAYED_WORK(&chip->batt_avg_work, batt_avg_work);
	INIT_DELAYED_WORK(&chip->sram_dump_work, sram_dump_work);

	rc = fg_get_batt_id(chip);
	if (rc < 0) {
		pr_err("Error in getting battery id, rc:%d\n", rc);
		goto exit;
	}

	rc = fg_get_batt_profile(chip);
	if (rc < 0) {
		chip->soc_reporting_ready = true;
		pr_warn("profile for batt_id=%dKOhms not found..using OTP, rc:%d\n",
			chip->batt_id_ohms / 1000, rc);
	}

	rc = fg_memif_init(chip);
	if (rc < 0) {
		dev_err(chip->dev, "Error in initializing FG_MEMIF, rc:%d\n",
@@ -4475,12 +4515,15 @@ static int fg_gen3_probe(struct platform_device *pdev)
		goto exit;
	}

	/* Keep SOC_UPDATE irq disabled until we require it */
	/* Keep SOC_UPDATE_IRQ disabled until we require it */
	if (fg_irqs[SOC_UPDATE_IRQ].irq)
		disable_irq_nosync(fg_irqs[SOC_UPDATE_IRQ].irq);

	/* Keep BSOC_DELTA_IRQ irq disabled until we require it */
	rerun_election(chip->delta_bsoc_irq_en_votable);
	/* Keep BSOC_DELTA_IRQ disabled until we require it */
	vote(chip->delta_bsoc_irq_en_votable, DELTA_BSOC_IRQ_VOTER, false, 0);

	/* Keep BATT_MISSING_IRQ disabled until we require it */
	vote(chip->batt_miss_irq_en_votable, BATT_MISS_IRQ_VOTER, false, 0);

	rc = fg_debugfs_create(chip);
	if (rc < 0) {
@@ -4505,7 +4548,6 @@ static int fg_gen3_probe(struct platform_device *pdev)
	}

	device_init_wakeup(chip->dev, true);
	if (chip->profile_available)
	schedule_delayed_work(&chip->profile_load_work, 0);

	pr_debug("FG GEN3 driver probed successfully\n");
+23 −11
Original line number Diff line number Diff line
@@ -266,6 +266,10 @@ module_param_named(
	debug_mask, __debug_mask, int, 0600
);

static int __weak_chg_icl_ua = 500000;
module_param_named(
	weak_chg_icl_ua, __weak_chg_icl_ua, int, 0600);

#define MICRO_1P5A		1500000
#define MICRO_P1A		100000
#define OTG_DEFAULT_DEGLITCH_TIME_MS	50
@@ -461,6 +465,8 @@ static int smb2_usb_get_prop(struct power_supply *psy,
			val->intval = 0;
		else
			val->intval = 1;
		if (chg->real_charger_type == POWER_SUPPLY_TYPE_UNKNOWN)
			val->intval = 0;
		break;
	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
		val->intval = chg->voltage_min_uv;
@@ -1466,15 +1472,6 @@ static int smb2_configure_typec(struct smb_charger *chg)
		return rc;
	}

	/* configure power role for dual-role */
	rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
				 TYPEC_POWER_ROLE_CMD_MASK, 0);
	if (rc < 0) {
		dev_err(chg->dev,
			"Couldn't configure power role for DRP rc=%d\n", rc);
		return rc;
	}

	/*
	 * disable Type-C factory mode and stay in Attached.SRC state when VCONN
	 * over-current happens
@@ -1852,6 +1849,16 @@ static int smb2_init_hw(struct smb2 *chip)
static int smb2_post_init(struct smb2 *chip)
{
	struct smb_charger *chg = &chip->chg;
	int rc;

	/* configure power role for dual-role */
	rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
				 TYPEC_POWER_ROLE_CMD_MASK, 0);
	if (rc < 0) {
		dev_err(chg->dev,
			"Couldn't configure power role for DRP rc=%d\n", rc);
		return rc;
	}

	rerun_election(chg->usb_irq_enable_votable);

@@ -2113,7 +2120,7 @@ static struct smb_irq_info smb2_irqs[] = {
	[SWITCH_POWER_OK_IRQ] = {
		.name		= "switcher-power-ok",
		.handler	= smblib_handle_switcher_power_ok,
		.storm_data	= {true, 1000, 3},
		.storm_data	= {true, 1000, 8},
	},
};

@@ -2307,6 +2314,7 @@ static int smb2_probe(struct platform_device *pdev)
	chg->dev = &pdev->dev;
	chg->param = v1_params;
	chg->debug_mask = &__debug_mask;
	chg->weak_chg_icl_ua = &__weak_chg_icl_ua;
	chg->mode = PARALLEL_MASTER;
	chg->irq_info = smb2_irqs;
	chg->name = "PMI";
@@ -2418,7 +2426,11 @@ static int smb2_probe(struct platform_device *pdev)
		goto cleanup;
	}

	smb2_post_init(chip);
	rc = smb2_post_init(chip);
	if (rc < 0) {
		pr_err("Failed in post init rc=%d\n", rc);
		goto cleanup;
	}

	smb2_create_debugfs(chip);

Loading