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

Commit 74ee3277 authored by Xiaozhe Shi's avatar Xiaozhe Shi Committed by Gerrit - the friendly Code Review server
Browse files

power: qpnp-smbcharger: account for battery OCP for flash prediction



In the flash current prediction algorithm, the battery pack OCP
threshold was not accounted for. Use the instantaneous vbat value and
max value from the fg_adc peripheral in order to make sure the maximum
flash current reported to the flash driver is below the amount necessary
to trip OCP.

CRs-Fixed: 793302
Change-Id: I60ad0371ff530148d2d2fb9e4966767736de85e7
Signed-off-by: default avatarXiaozhe Shi <xiaozhes@codeaurora.org>
parent 2411250d
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -209,6 +209,9 @@ Optional Properties:
				the line from the battery connectors through
				vph_power. This is used to calculate maximum
				available current of the battery.
- qcom,vled-max-uv:		The maximum input voltage of the flash leds.
				This is used to calculate maximum available
				current of the battery.
- qcom,autoadjust-vfloat	A boolean property that when set, makes the
				driver automatically readjust vfloat using the
				fuel gauge ADC readings to make charging more
@@ -223,6 +226,9 @@ Optional Properties:
				AICL deglitch configuration dynamically. This needs
				to be set if the DCIN supply is going to be less
				than or equal to 5V.
- qcom,ibat-ocp-threshold-ua	Maximum current before the battery will trigger
				overcurrent protection. Use the recommended
				battery pack value minus some margin.
- qcom,soft-vfloat-comp-disabled	Set this property when the battery is
					powered via external source and could
					go above the float voltage.
+67 −20
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@
#include <linux/rtc.h>
#include <linux/qpnp/qpnp-adc.h>
#include <linux/batterydata-lib.h>
#include <linux/msm_bcl.h>

/* Mask/Bit helpers */
#define _SMB_MASK(BITS, POS) \
@@ -134,6 +135,7 @@ struct smbchg_chip {
	/* flash current prediction */
	int				rpara_uohm;
	int				rslow_uohm;
	int				vled_max_uv;

	/* vfloat adjustment */
	int				max_vbat_sample;
@@ -2244,14 +2246,20 @@ out:
	return rc;
}

static int smbchg_ibat_ocp_threshold_ua = 4500000;
module_param(smbchg_ibat_ocp_threshold_ua, int, 0644);

#define UCONV			1000000LL
#define VIN_FLASH_UV		5500000LL
#define FLASH_V_THRESHOLD	3000000LL
#define MCONV			1000LL
#define FLASH_V_THRESHOLD	3000000
#define FLASH_VDIP_MARGIN	100000
#define VPH_FLASH_VDIP		(FLASH_V_THRESHOLD + FLASH_VDIP_MARGIN)
#define BUCK_EFFICIENCY		800LL
static int smbchg_calc_max_flash_current(struct smbchg_chip *chip)
{
	int ocv_uv, ibat_ua, esr_uohm, rbatt_uohm, rc;
	int64_t ibat_flash_ua, total_flash_ua, total_flash_power_fw;
	int ocv_uv, esr_uohm, rbatt_uohm, ibat_now, rc;
	int64_t ibat_flash_ua, avail_flash_ua, avail_flash_power_fw;
	int64_t ibat_safe_ua, vin_flash_uv, vph_flash_uv;

	rc = get_property_from_fg(chip, POWER_SUPPLY_PROP_VOLTAGE_OCV, &ocv_uv);
	if (rc) {
@@ -2259,30 +2267,59 @@ static int smbchg_calc_max_flash_current(struct smbchg_chip *chip)
		return 0;
	}

	rc = get_property_from_fg(chip,
			POWER_SUPPLY_PROP_CURRENT_NOW, &ibat_ua);
	rc = get_property_from_fg(chip, POWER_SUPPLY_PROP_RESISTANCE,
			&esr_uohm);
	if (rc) {
		pr_smb(PR_STATUS, "bms psy does not support current_now\n");
		pr_smb(PR_STATUS, "bms psy does not support resistance\n");
		return 0;
	}

	rc = get_property_from_fg(chip, POWER_SUPPLY_PROP_RESISTANCE,
			&esr_uohm);
	rc = msm_bcl_read(BCL_PARAM_CURRENT, &ibat_now);
	if (rc) {
		pr_smb(PR_STATUS, "bms psy does not support resistance\n");
		pr_smb(PR_STATUS, "BCL current read failed: %d\n", rc);
		return 0;
	}

	rbatt_uohm = esr_uohm + chip->rpara_uohm + chip->rslow_uohm;
	ibat_flash_ua = (div_s64((ocv_uv - FLASH_V_THRESHOLD) * UCONV,
			rbatt_uohm)) - ibat_ua;
	total_flash_power_fw = FLASH_V_THRESHOLD * ibat_flash_ua
			* BUCK_EFFICIENCY;
	total_flash_ua = div64_s64(total_flash_power_fw, VIN_FLASH_UV * 1000LL);
	/*
	 * Calculate the maximum current that can pulled out of the battery
	 * before the battery voltage dips below a safe threshold.
	 */
	ibat_safe_ua = div_s64((ocv_uv - VPH_FLASH_VDIP) * UCONV,
				rbatt_uohm);

	if (ibat_safe_ua <= smbchg_ibat_ocp_threshold_ua) {
		/*
		 * If the calculated current is below the OCP threshold, then
		 * use it as the possible flash current.
		 */
		ibat_flash_ua = ibat_safe_ua - ibat_now;
		vph_flash_uv = VPH_FLASH_VDIP;
	} else {
		/*
		 * If the calculated current is above the OCP threshold, then
		 * use the ocp threshold instead.
		 *
		 * Any higher current will be tripping the battery OCP.
		 */
		ibat_flash_ua = smbchg_ibat_ocp_threshold_ua - ibat_now;
		vph_flash_uv = ocv_uv - div64_s64((int64_t)rbatt_uohm
				* smbchg_ibat_ocp_threshold_ua, UCONV);
	}
	/* Calculate the input voltage of the flash module. */
	vin_flash_uv = max((chip->vled_max_uv + 500000LL),
				(vph_flash_uv * 1200 / 1000));
	/* Calculate the available power for the flash module. */
	avail_flash_power_fw = BUCK_EFFICIENCY * vph_flash_uv * ibat_flash_ua;
	/*
	 * Calculate the available amount of current the flash module can draw
	 * before collapsing the battery. (available power/ flash input voltage)
	 */
	avail_flash_ua = div64_s64(avail_flash_power_fw, vin_flash_uv * MCONV);
	pr_smb(PR_MISC,
		"ibat_flash=%lld\n, ocv=%d, ibat=%d, rbatt=%d t_flash=%lld\n",
		ibat_flash_ua, ocv_uv, ibat_ua, rbatt_uohm, total_flash_ua);
	return (int)total_flash_ua;
		"avail_iflash=%lld, ocv=%d, ibat=%d, rbatt=%d\n",
		avail_flash_ua, ocv_uv, ibat_now, rbatt_uohm);
	return (int)avail_flash_ua;
}

#define FCC_CMP_CFG	0xF3
@@ -4705,9 +4742,10 @@ err:
	return rc;
}

#define DEFAULT_VLED_MAX_UV		3500000
static int smb_parse_dt(struct smbchg_chip *chip)
{
	int rc = 0;
	int rc = 0, ocp_thresh = -EINVAL;
	struct device_node *node = chip->dev->of_node;
	const char *dc_psy_type, *bpd;

@@ -4717,12 +4755,21 @@ static int smb_parse_dt(struct smbchg_chip *chip)
	}

	/* read optional u32 properties */
	OF_PROP_READ(chip, ocp_thresh,
			"ibat-ocp-threshold-ua", rc, 1);
	if (ocp_thresh >= 0)
		smbchg_ibat_ocp_threshold_ua = ocp_thresh;
	OF_PROP_READ(chip, chip->iterm_ma, "iterm-ma", rc, 1);
	OF_PROP_READ(chip, chip->target_fastchg_current_ma,
			"fastchg-current-ma", rc, 1);
	OF_PROP_READ(chip, chip->vfloat_mv, "float-voltage-mv", rc, 1);
	OF_PROP_READ(chip, chip->safety_time, "charging-timeout-mins", rc, 1);
	OF_PROP_READ(chip, chip->vled_max_uv, "vled-max-uv", rc, 1);
	if (chip->vled_max_uv < 0)
		chip->vled_max_uv = DEFAULT_VLED_MAX_UV;
	OF_PROP_READ(chip, chip->rpara_uohm, "rparasitic-uohm", rc, 1);
	if (chip->rpara_uohm < 0)
		chip->rpara_uohm = 0;
	OF_PROP_READ(chip, chip->prechg_safety_time, "precharging-timeout-mins",
			rc, 1);
	OF_PROP_READ(chip, chip->fastchg_current_comp, "fastchg-current-comp",
@@ -4829,7 +4876,7 @@ static int smb_parse_dt(struct smbchg_chip *chip)
	if (rc)
		chip->bms_psy_name = NULL;

	/* read the bms power supply name */
	/* read the battery power supply name */
	rc = of_property_read_string(node, "qcom,battery-psy-name",
						&chip->battery_psy_name);
	if (rc)