On 16.09.2015 02:58, Andreas Dannenberg wrote:
> A new optional device property called "ti,current-limit" is introduced
> to allow disabling the D+/D- USB signal-based charger type auto-
> detection algorithm used to set the input current limit and instead to
> use a fixed input current limit.
> 
> Signed-off-by: Andreas Dannenberg <[email protected]>
> ---
>  drivers/power/bq24257_charger.c | 102 
> +++++++++++++++++++++++++++++++---------
>  1 file changed, 81 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/power/bq24257_charger.c b/drivers/power/bq24257_charger.c
> index fdfe855..55e4ee4 100644
> --- a/drivers/power/bq24257_charger.c
> +++ b/drivers/power/bq24257_charger.c
> @@ -74,6 +74,7 @@ struct bq24257_init_data {
>       u8 ichg;        /* charge current      */
>       u8 vbat;        /* regulation voltage  */
>       u8 iterm;       /* termination current */
> +     u8 in_ilimit;   /* input current limit */
>  };
>  
>  struct bq24257_state {
> @@ -100,6 +101,8 @@ struct bq24257_device {
>       struct bq24257_state state;
>  
>       struct mutex lock; /* protect state data */
> +
> +     bool in_ilimit_autoset_disable;
>  };
>  
>  static bool bq24257_is_volatile_reg(struct device *dev, unsigned int reg)
> @@ -188,6 +191,12 @@ static const u32 bq24257_iterm_map[] = {
>  
>  #define BQ24257_ITERM_MAP_SIZE               ARRAY_SIZE(bq24257_iterm_map)
>  
> +static const u32 bq24257_iilimit_map[] = {

Too many ii? bq24257_ilimit_map? Or is it a shortcut for "in_ilimit"?
New fields have pattern like "in_ilimit*".
Anyway it's a confusing so maybe use everywhere the same pattern?


> +     100000, 150000, 500000, 900000, 1500000, 2000000
> +};
> +
> +#define BQ24257_IILIMIT_MAP_SIZE     ARRAY_SIZE(bq24257_iilimit_map)

ditto: ILIMIT_MAP_SIZE?

> +
>  static int bq24257_field_read(struct bq24257_device *bq,
>                             enum bq24257_fields field_id)
>  {
> @@ -479,24 +488,35 @@ static void bq24257_handle_state_change(struct 
> bq24257_device *bq,
>       old_state = bq->state;
>       mutex_unlock(&bq->lock);
>  
> -     if (!new_state->power_good) {                        /* power removed */
> -             cancel_delayed_work_sync(&bq->iilimit_setup_work);
> -
> -             /* activate D+/D- port detection algorithm */
> -             ret = bq24257_field_write(bq, F_DPDM_EN, 1);
> -             if (ret < 0)
> -                     goto error;
> +     /*
> +      * Handle BQ2425x state changes observing whether the D+/D- based input
> +      * current limit autoset functionality is enabled.
> +      */
> +     if (!new_state->power_good) {
> +             dev_dbg(bq->dev, "Power removed\n");
> +             if (!bq->in_ilimit_autoset_disable) {
> +                     cancel_delayed_work_sync(&bq->iilimit_setup_work);
>  
> -             reset_iilimit = true;
> -     } else if (!old_state.power_good) {                 /* power inserted */
> -             config_iilimit = true;
> -     } else if (new_state->fault == FAULT_NO_BAT) {     /* battery removed */
> -             cancel_delayed_work_sync(&bq->iilimit_setup_work);
> +                     /* activate D+/D- port detection algorithm */
> +                     ret = bq24257_field_write(bq, F_DPDM_EN, 1);
> +                     if (ret < 0)
> +                             goto error;
>  
> -             reset_iilimit = true;
> -     } else if (old_state.fault == FAULT_NO_BAT) {    /* battery connected */
> -             config_iilimit = true;
> -     } else if (new_state->fault == FAULT_TIMER) { /* safety timer expired */
> +                     reset_iilimit = true;
> +             }
> +     } else if (!old_state.power_good) {
> +             dev_dbg(bq->dev, "Power inserted\n");
> +             config_iilimit = !bq->in_ilimit_autoset_disable;
> +     } else if (new_state->fault == FAULT_NO_BAT) {
> +             dev_warn(bq->dev, "Battery removed\n");

dev_warn? This wasn't here before... It's a bit too serious. Is removing
a battery an error condition? Maybe user just unplugged it?
dev_dbg or dev_info should be sufficient.

BTW, it is useful to quickly find boot regressions with "dmesg -l
warn,err". Removing a battery probably is not an error?

> +             if (!bq->in_ilimit_autoset_disable) {
> +                     cancel_delayed_work_sync(&bq->iilimit_setup_work);
> +                     reset_iilimit = true;
> +             }
> +     } else if (old_state.fault == FAULT_NO_BAT) {
> +             dev_warn(bq->dev, "Battery connected\n");

Definitely not a warn. Inserting a battery is not an error condition.

> +             config_iilimit = !bq->in_ilimit_autoset_disable;
> +     } else if (new_state->fault == FAULT_TIMER) {
>               dev_err(bq->dev, "Safety timer expired! Battery dead?\n");
>       }

Don't you have a schedule_delayed_work() call here which now will be
executed always? Even when work was not INIT and nothing will cancel it?

>  
> @@ -581,7 +601,16 @@ static int bq24257_hw_init(struct bq24257_device *bq)
>       bq->state = state;
>       mutex_unlock(&bq->lock);
>  
> -     if (!state.power_good)
> +     if (bq->in_ilimit_autoset_disable) {
> +             dev_dbg(bq->dev, "manually setting iilimit = %d\n",
> +                     bq->init_data.in_ilimit);

Nit, no actual difference but makes more sense to me because field is
u8: "%u".

> +
> +             /* program fixed input current limit */
> +             ret = bq24257_field_write(bq, F_IILIMIT,
> +                                       bq->init_data.in_ilimit);
> +             if (ret < 0)
> +                     return ret;
> +     } else if (!state.power_good)
>               /* activate D+/D- detection algorithm */
>               ret = bq24257_field_write(bq, F_DPDM_EN, 1);
>       else if (state.fault != FAULT_NO_BAT)
> @@ -659,6 +688,7 @@ static int bq24257_fw_probe(struct bq24257_device *bq)
>       int ret;
>       u32 property;
>  
> +     /* Required properties */
>       ret = device_property_read_u32(bq->dev, "ti,charge-current", &property);
>       if (ret < 0)
>               return ret;
> @@ -682,6 +712,24 @@ static int bq24257_fw_probe(struct bq24257_device *bq)
>       bq->init_data.iterm = bq24257_find_idx(property, bq24257_iterm_map,
>                                              BQ24257_ITERM_MAP_SIZE);
>  
> +     /* Optional properties. If not provided use reasonable default. */
> +     ret = device_property_read_u32(bq->dev, "ti,current-limit",
> +                                    &property);
> +     if (ret < 0)
> +             /*
> +              * Explicitly set a default value which will be needed for
> +              * devices that don't support the automatic setting of the input
> +              * current limit through the charger type detection mechanism.
> +              */
> +             bq->init_data.in_ilimit = IILIMIT_500;
> +     else {
> +             bq->in_ilimit_autoset_disable = true;
> +             bq->init_data.in_ilimit =
> +                             bq24257_find_idx(property,
> +                                              bq24257_iilimit_map,
> +                                              BQ24257_IILIMIT_MAP_SIZE);
> +     }
> +
>       return 0;
>  }
>  
> @@ -740,8 +788,6 @@ static int bq24257_probe(struct i2c_client *client,
>  
>       i2c_set_clientdata(client, bq);
>  
> -     INIT_DELAYED_WORK(&bq->iilimit_setup_work, bq24257_iilimit_setup_work);
> -
>       if (!dev->platform_data) {
>               ret = bq24257_fw_probe(bq);
>               if (ret < 0) {
> @@ -752,6 +798,18 @@ static int bq24257_probe(struct i2c_client *client,
>               return -ENODEV;
>       }
>  
> +     /*
> +      * The BQ24250 doesn't support the D+/D- based charger type detection
> +      * used for the automatic setting of the input current limit setting so
> +      * explicitly disable that feature.
> +      */
> +     if (bq->chip == BQ24250)
> +             bq->in_ilimit_autoset_disable = true;
> +
> +     if (!bq->in_ilimit_autoset_disable)

In most places you have quite obfuscated negation of
"autoset_disable"... So maybe just "bq->in_ilimit_autoset" or
"bq->in_ilimit_autoset_enable" and the negation won't be needed? It
could be more readable.

Best regards,
Krzysztof

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to