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

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

Merge "power: vm-bms: Disable charging on detecting a debug battery"

parents d93332e6 b7dcff61
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -161,6 +161,7 @@ enum {
	SOC	= BIT(3),
	PARALLEL = BIT(4),
	COLLAPSE = BIT(5),
	DEBUG_BOARD = BIT(6),
};

enum bpd_type {
@@ -215,6 +216,7 @@ static enum power_supply_property msm_batt_power_props[] = {
	POWER_SUPPLY_PROP_CHARGE_COUNTER,
	POWER_SUPPLY_PROP_CYCLE_COUNT,
	POWER_SUPPLY_PROP_CHARGE_FULL,
	POWER_SUPPLY_PROP_DEBUG_BATTERY,
	POWER_SUPPLY_PROP_TEMP,
	POWER_SUPPLY_PROP_COOL_TEMP,
	POWER_SUPPLY_PROP_WARM_TEMP,
@@ -353,6 +355,7 @@ struct qpnp_lbc_chip {
	bool				cfg_use_external_charger;
	bool				cfg_chgr_led_support;
	bool				non_collapsible_chgr_detected;
	bool				debug_board;
	unsigned int			cfg_warm_bat_chg_ma;
	unsigned int			cfg_cool_bat_chg_ma;
	unsigned int			cfg_safe_voltage_mv;
@@ -1658,6 +1661,11 @@ static int qpnp_batt_power_set_property(struct power_supply *psy,
		rc = qpnp_lbc_charger_enable(chip, USER,
						!chip->cfg_charging_disabled);
		break;
	case POWER_SUPPLY_PROP_DEBUG_BATTERY:
		chip->debug_board = val->intval;
		rc = qpnp_lbc_charger_enable(chip, DEBUG_BOARD,
						!(val->intval));
		break;
	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
		qpnp_lbc_vinmin_set(chip, val->intval / 1000);
		break;
@@ -1730,6 +1738,9 @@ static int qpnp_batt_power_get_property(struct power_supply *psy,
	case POWER_SUPPLY_PROP_CHARGING_ENABLED:
		val->intval = !(chip->cfg_charging_disabled);
		break;
	case POWER_SUPPLY_PROP_DEBUG_BATTERY:
		val->intval = chip->debug_board;
		break;
	case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
		val->intval = chip->therm_lvl_sel;
		break;
+103 −7
Original line number Diff line number Diff line
@@ -123,6 +123,8 @@

#define QPNP_VM_BMS_DEV_NAME		"qcom,qpnp-vm-bms"

#define DEBUG_BATT_ID_LOW	6500
#define DEBUG_BATT_ID_HIGH	8500
/* indicates the state of BMS */
enum {
	IDLE_STATE,
@@ -275,6 +277,7 @@ struct qpnp_bms_chip {
	struct power_supply		*bms_psy;
	struct power_supply		*batt_psy;
	struct power_supply		*usb_psy;
	struct notifier_block		nb;
	bool				reported_soc_in_use;
	bool				charger_removed_since_full;
	bool				charger_reinserted;
@@ -282,6 +285,7 @@ struct qpnp_bms_chip {
	int				reported_soc;
	int				reported_soc_change_sec;
	int				reported_soc_delta;
	int				batt_id_ohm;
};

static struct qpnp_bms_chip *the_chip;
@@ -478,6 +482,45 @@ static int calculate_delta_time(unsigned long *time_stamp, int *delta_time_s)
	return 0;
}

static bool is_debug_batt_id(struct qpnp_bms_chip *chip)
{
	if (is_between(DEBUG_BATT_ID_LOW, DEBUG_BATT_ID_HIGH,
				chip->batt_id_ohm))
		return true;

	return false;
}

static int bms_notifier_cb(struct notifier_block *nb,
			unsigned long event, void *data)
{
	union power_supply_propval ret = {0,};
	struct power_supply *psy = data;
	struct qpnp_bms_chip *chip = container_of(nb, struct qpnp_bms_chip, nb);

	if (event != PSY_EVENT_PROP_CHANGED)
		return NOTIFY_OK;

	if ((strcmp(psy->desc->name, "battery") == 0)) {
		if (chip->batt_psy == NULL)
			chip->batt_psy = power_supply_get_by_name("battery");
		if (chip->batt_psy) {
			if (is_debug_batt_id(chip)) {
				power_supply_get_property(chip->batt_psy,
					POWER_SUPPLY_PROP_DEBUG_BATTERY, &ret);
				if (!ret.intval)  {
					ret.intval = 1;
					power_supply_set_property(
						chip->batt_psy,
						POWER_SUPPLY_PROP_DEBUG_BATTERY,
						 &ret);
				}
			}
		}
	}

	return NOTIFY_OK;
}
static bool is_charger_present(struct qpnp_bms_chip *chip)
{
	union power_supply_propval ret = {0,};
@@ -2162,8 +2205,16 @@ static void voltage_soc_timeout_work(struct work_struct *work)
	mutex_unlock(&chip->bms_device_mutex);
}

#define DEBUG_BOARD_SOC 67
#define BATT_MISSING_SOC 50
static int get_prop_bms_capacity(struct qpnp_bms_chip *chip)
{
	if (is_debug_batt_id(chip))
		return DEBUG_BOARD_SOC;

	if (!chip->battery_present)
		return BATT_MISSING_SOC;

	return report_state_of_charge(chip);
}

@@ -2251,6 +2302,7 @@ static enum power_supply_property bms_power_props[] = {
	POWER_SUPPLY_PROP_CYCLE_COUNT,
	POWER_SUPPLY_PROP_CHARGE_COUNTER,
	POWER_SUPPLY_PROP_CHARGE_FULL,
	POWER_SUPPLY_PROP_RESISTANCE_ID,
};

static int
@@ -2334,6 +2386,9 @@ static int qpnp_vm_bms_power_get_property(struct power_supply *psy,
	case POWER_SUPPLY_PROP_CHARGE_FULL:
		val->intval = get_charge_full(chip);
		break;
	case POWER_SUPPLY_PROP_RESISTANCE_ID:
		val->intval = chip->batt_id_ohm;
		break;
	default:
		return -EINVAL;
	}
@@ -3295,7 +3350,7 @@ static int bms_find_irqs(struct qpnp_bms_chip *chip, struct device_node *child)
}


static int64_t read_battery_id(struct qpnp_bms_chip *chip)
static int64_t read_battery_id_uv(struct qpnp_bms_chip *chip)
{
	int rc;
	struct qpnp_vadc_result result;
@@ -3478,20 +3533,55 @@ static const struct file_operations bms_data_debugfs_ops = {
	.release	= single_release,
};

#define BID_RPULL_OHM          100000
#define VREF_BAT_THERM         1800
static int get_battery_id(struct qpnp_bms_chip *chip,
			int64_t battery_id_uv)
{
	int batt_id_mv;
	int64_t denom;

	batt_id_mv = div_s64(battery_id_uv, 1000);
	if (batt_id_mv == 0) {
		pr_debug("batt_id_mv = 0 from ADC\n");
		return 0;
	}

	denom = div64_s64(VREF_BAT_THERM * 1000, batt_id_mv) - 1000;
	if (denom <= 0) {
		/* batt id connector might be open, return 0 kohms */
		return 0;
	}

	chip->batt_id_ohm = div64_u64(BID_RPULL_OHM * 1000 + denom / 2, denom);

	return 0;
}

static int set_battery_data(struct qpnp_bms_chip *chip)
{
	int64_t battery_id;
	int64_t battery_id_uv;
	int rc = 0;
	struct bms_battery_data *batt_data;
	struct device_node *node;

	battery_id = read_battery_id(chip);
	if (battery_id < 0) {
		pr_err("cannot read battery id err = %lld\n", battery_id);
		return battery_id;
	battery_id_uv = read_battery_id_uv(chip);
	if (battery_id_uv < 0) {
		pr_err("cannot read battery id_uv err = %lld\n", battery_id_uv);
		return battery_id_uv;
	}

	rc = get_battery_id(chip, battery_id_uv);
	if (rc < 0) {
		pr_err("Failed to calcualte battery-id rc=%d\n", rc);
		return rc;
	}

	node = of_parse_phandle(chip->pdev->dev.of_node,
					"qcom,battery-data", 0);
	pr_debug(" battery-id-uV=%lld batt_id=%d ohm\n",
					battery_id_uv, chip->batt_id_ohm);

	if (!node) {
		pr_err("No available batterydata\n");
		return -EINVAL;
@@ -3519,7 +3609,7 @@ static int set_battery_data(struct qpnp_bms_chip *chip)
	 * if the alloced luts are 0s, of_batterydata_read_data ignores
	 * them.
	 */
	rc = of_batterydata_read_data(node, batt_data, battery_id);
	rc = of_batterydata_read_data(node, batt_data, battery_id_uv);
	if (rc || !batt_data->pc_temp_ocv_lut
		|| !batt_data->fcc_temp_lut
		|| !batt_data->rbatt_sf_lut
@@ -3967,6 +4057,11 @@ static int qpnp_vm_bms_probe(struct platform_device *pdev)
	}
	chip->bms_psy_registered = true;

	chip->nb.notifier_call = bms_notifier_cb;
	rc = power_supply_reg_notifier(&chip->nb);
	if (rc < 0)
		pr_err("Failed register psy notifier rc = %d\n", rc);

	rc = get_battery_voltage(chip, &vbatt);
	if (rc) {
		pr_err("error reading vbat_sns adc channel=%d, rc=%d\n",
@@ -4057,6 +4152,7 @@ static int qpnp_vm_bms_remove(struct platform_device *pdev)
	mutex_destroy(&chip->last_soc_mutex);
	mutex_destroy(&chip->state_change_mutex);
	mutex_destroy(&chip->bms_device_mutex);
	power_supply_unreg_notifier(&chip->nb);
	power_supply_unregister(chip->bms_psy);
	dev_set_drvdata(&pdev->dev, NULL);
	the_chip = NULL;