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

Commit 0cfbfde6 authored by Andreas Dannenberg's avatar Andreas Dannenberg Committed by Sebastian Reichel
Browse files

power: bq24257: Allow input current limit sysfs access



This patch allows reading and writing of the input current limit through
the power supply's input_current_limit sysfs property. This allows
userspace to see what charger was detected (if the D+/D- USB signal-
based charger type detection is enabled) and to re-configure the maximum
current drawn from the external supply at runtime based on system-level
knowledge or user input. Note that upon charger disconnection and
re-connection the limit configured through firmware becomes active again
(or the D+/D- USB signal-based charger detection will be run again).

Signed-off-by: default avatarAndreas Dannenberg <dannenberg@ti.com>
Reviewed-by: default avatarKrzysztof Kozlowski <k.kozlowski@samsung.com>
Signed-off-by: default avatarSebastian Reichel <sre@kernel.org>
parent 138606ff
Loading
Loading
Loading
Loading
+79 −6
Original line number Diff line number Diff line
@@ -267,6 +267,47 @@ enum bq24257_fault {
	FAULT_INPUT_LDO_LOW,
};

static int bq24257_get_input_current_limit(struct bq24257_device *bq,
					   union power_supply_propval *val)
{
	int ret;

	ret = bq24257_field_read(bq, F_IILIMIT);
	if (ret < 0)
		return ret;

	/*
	 * The "External ILIM" and "Production & Test" modes are not exposed
	 * through this driver and not being covered by the lookup table.
	 * Should such a mode have become active let's return an error rather
	 * than exceeding the bounds of the lookup table and returning
	 * garbage.
	 */
	if (ret >= BQ24257_IILIMIT_MAP_SIZE)
		return -ENODATA;

	val->intval = bq24257_iilimit_map[ret];

	return 0;
}

static int bq24257_set_input_current_limit(struct bq24257_device *bq,
					const union power_supply_propval *val)
{
	/*
	 * Address the case where the user manually sets an input current limit
	 * while the charger auto-detection mechanism is is active. In this
	 * case we want to abort and go straight to the user-specified value.
	 */
	if (bq->iilimit_autoset_enable)
		cancel_delayed_work_sync(&bq->iilimit_setup_work);

	return bq24257_field_write(bq, F_IILIMIT,
				   bq24257_find_idx(val->intval,
						    bq24257_iilimit_map,
						    BQ24257_IILIMIT_MAP_SIZE));
}

static int bq24257_power_supply_get_property(struct power_supply *psy,
					     enum power_supply_property psp,
					     union power_supply_propval *val)
@@ -351,6 +392,9 @@ static int bq24257_power_supply_get_property(struct power_supply *psy,
		val->intval = bq24257_iterm_map[bq->init_data.iterm];
		break;

	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
		return bq24257_get_input_current_limit(bq, val);

	default:
		return -EINVAL;
	}
@@ -358,6 +402,31 @@ static int bq24257_power_supply_get_property(struct power_supply *psy,
	return 0;
}

static int bq24257_power_supply_set_property(struct power_supply *psy,
					enum power_supply_property prop,
					const union power_supply_propval *val)
{
	struct bq24257_device *bq = power_supply_get_drvdata(psy);

	switch (prop) {
	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
		return bq24257_set_input_current_limit(bq, val);
	default:
		return -EINVAL;
	}
}

static int bq24257_power_supply_property_is_writeable(struct power_supply *psy,
					enum power_supply_property psp)
{
	switch (psp) {
	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
		return true;
	default:
		return false;
	}
}

static int bq24257_get_chip_state(struct bq24257_device *bq,
				  struct bq24257_state *state)
{
@@ -559,13 +628,14 @@ static void bq24257_handle_state_change(struct bq24257_device *bq,
			ret = bq24257_field_write(bq, F_DPDM_EN, 1);
			if (ret < 0)
				goto error;

			/* reset input current limit */
			ret = bq24257_field_write(bq, F_IILIMIT,
						  bq->init_data.iilimit);
		}
		/*
		 * When power is removed always return to the default input
		 * current limit as configured during probe.
		 */
		ret = bq24257_field_write(bq, F_IILIMIT, bq->init_data.iilimit);
		if (ret < 0)
			goto error;
		}
	} else if (!old_state.power_good) {
		dev_dbg(bq->dev, "Power inserted\n");

@@ -682,6 +752,7 @@ static enum power_supply_property bq24257_power_supply_props[] = {
	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
	POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
};

static char *bq24257_charger_supplied_to[] = {
@@ -694,6 +765,8 @@ static const struct power_supply_desc bq24257_power_supply_desc = {
	.properties = bq24257_power_supply_props,
	.num_properties = ARRAY_SIZE(bq24257_power_supply_props),
	.get_property = bq24257_power_supply_get_property,
	.set_property = bq24257_power_supply_set_property,
	.property_is_writeable = bq24257_power_supply_property_is_writeable,
};

static ssize_t bq24257_show_ovp_voltage(struct device *dev,