power: bq24257: Add SW-based approach for Power Good determination

A software-based approach for determining the charger's input voltage
"Power Good" state is introduced for devices like the bq24250 which
don't have a dedicated hardware pin for that purpose. This SW-based
approach is also used for other devices (with dedicated PG pin) as a
fall back solution if that pin is not configured to be used through
"pg-gpios".

Signed-off-by: Andreas Dannenberg <dannenberg@ti.com>
Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Signed-off-by: Sebastian Reichel <sre@kernel.org>
This commit is contained in:
Andreas Dannenberg 2015-09-28 17:33:56 -05:00 committed by Sebastian Reichel
parent eb9fbcc669
commit 7c071a0a08

View File

@ -359,7 +359,26 @@ static int bq24257_get_chip_state(struct bq24257_device *bq,
state->fault = ret;
state->power_good = !gpiod_get_value_cansleep(bq->pg);
if (bq->pg)
state->power_good = !gpiod_get_value_cansleep(bq->pg);
else
/*
* If we have a chip without a dedicated power-good GPIO or
* some other explicit bit that would provide this information
* assume the power is good if there is no supply related
* fault - and not good otherwise. There is a possibility for
* other errors to mask that power in fact is not good but this
* is probably the best we can do here.
*/
switch (state->fault) {
case FAULT_INPUT_OVP:
case FAULT_INPUT_UVLO:
case FAULT_INPUT_LDO_LOW:
state->power_good = false;
break;
default:
state->power_good = true;
}
return 0;
}
@ -651,15 +670,21 @@ static int bq24257_power_supply_init(struct bq24257_device *bq)
return PTR_ERR_OR_ZERO(bq->charger);
}
static int bq24257_pg_gpio_probe(struct bq24257_device *bq)
static void bq24257_pg_gpio_probe(struct bq24257_device *bq)
{
bq->pg = devm_gpiod_get_index(bq->dev, BQ24257_PG_GPIO, 0, GPIOD_IN);
if (IS_ERR(bq->pg)) {
dev_err(bq->dev, "could not probe PG pin\n");
return PTR_ERR(bq->pg);
bq->pg = devm_gpiod_get_optional(bq->dev, BQ24257_PG_GPIO, GPIOD_IN);
if (PTR_ERR(bq->pg) == -EPROBE_DEFER) {
dev_info(bq->dev, "probe retry requested for PG pin\n");
return;
} else if (IS_ERR(bq->pg)) {
dev_err(bq->dev, "error probing PG pin\n");
bq->pg = NULL;
return;
}
return 0;
if (bq->pg)
dev_dbg(bq->dev, "probed PG pin = %d\n", desc_to_gpio(bq->pg));
}
static int bq24257_fw_probe(struct bq24257_device *bq)
@ -789,10 +814,19 @@ static int bq24257_probe(struct i2c_client *client,
INIT_DELAYED_WORK(&bq->iilimit_setup_work,
bq24257_iilimit_setup_work);
/* we can only check Power Good status by probing the PG pin */
ret = bq24257_pg_gpio_probe(bq);
if (ret < 0)
return ret;
/*
* The BQ24250 doesn't have a dedicated Power Good (PG) pin so let's
* not probe for it and instead use a SW-based approach to determine
* the PG state. We also use a SW-based approach for all other devices
* if the PG pin is either not defined or can't be probed.
*/
if (bq->chip != BQ24250)
bq24257_pg_gpio_probe(bq);
if (PTR_ERR(bq->pg) == -EPROBE_DEFER)
return PTR_ERR(bq->pg);
else if (!bq->pg)
dev_info(bq->dev, "using SW-based power-good detection\n");
/* reset all registers to defaults */
ret = bq24257_field_write(bq, F_RESET, 1);