mbox series

[v4,00/15] Add support for AXP192 PMIC

Message ID 20220629143046.213584-1-aidanmacdonald.0x0@gmail.com
Headers show
Series Add support for AXP192 PMIC | expand

Message

Aidan MacDonald June 29, 2022, 2:30 p.m. UTC
Changes in v4:

* Drop regmap-irq patches and rebase on top of the regmap-irq
  refactoring series[1], which implements the same functionality.
* Reorder mfd_cells, putting one-line entries at the bottom.
* Fix incorrect example in axp192-gpio device tree bindings.
* Perform adc_en2 flag -> adc_en2_mask conversion in axp20x_adc
  as a separate patch.
* Simplify axp192_usb_power_set_current_max().
* Drop unneeded OF dependency in pin control driver, and document
  tables used for describing register layouts.
* Various style fixups suggested by Andy Shevchenko.

[1]: https://lore.kernel.org/lkml/20220623211420.918875-1-aidanmacdonald.0x0@gmail.com/

Changes in v3:

* Update pinctrl driver to address Andy Shevchenko's review comments
  from v1, and fix a few other issues.
* Add gpio-ranges property and example snippet to gpio DT bindings.
* Update commit message of patch 01/16 to point out that all register
  addresses are obtained using sub_irq_reg().
* Document ccc_table in axp20x_battery. Also update commit message to
  note a small fix that is part of that patch.
* Drop axp20x_adc consolidation patch in favor of using separate adc_raw
  functions. It's a minor code size optimization that may not be worth
  the effort due to implementation complexity.
* Use the FIELD_GET macro in axp20x_adc to further clarify intent.
* Fix a typo in the regulator driver where an AXP20X regulator ID was
  mistakenly used instead of an AXP192 regulator ID. Also carry over
  an Acked-by: tag from v1. Hope that's okay.
* Accumulate Acked-by: tags from v1 on DT patches.
* Accumulate Acked-by: tags from v2.

Note that regmap maintainer Mark Brown has said the first two patches to
regmap-irq aren't suitable for inclusion into the kernel in their current
state. I'm including them for v3 so the series remains testable.

Changes in v2:

* Do a little cleanup of axp20x_adc suggested by Jonathan Cameron
* Consolidate ADC read functions in axp20x_adc
* Drop the axp192's read_label callback in axp20x_adc
* Clean up the axp192-gpio dt bindings
* Rewrite a problematic bit of code in axp20x_usb_power reported
  by kernel test robot
* Support AXP192 in axp20x_battery
* Split up regmap-irq changes to two separate patches

Cover letter from v1:

Hi all,

This patch series adds support for the X-Powers AXP192 PMIC to the
AXP20x driver framework.

The first patch is a small change to regmap-irq to support the AXP192's
unusual IRQ register layout. It isn't possible to include all of the
IRQ registers in one regmap-irq chip without this.

The rest of the changes are pretty straightforward, I think the only
notable parts are the axp20x_adc driver where there seems to be some
opportunities for code reuse (the axp192 is nearly a duplicate of the
axp20x) and the addition of a new pinctrl driver for the axp192, since
the axp20x pinctrl driver was not very easy to adapt.

Aidan MacDonald (15):
  dt-bindings: mfd: add bindings for AXP192 MFD device
  dt-bindings: iio: adc: axp209: Add AXP192 compatible
  dt-bindings: power: supply: axp20x: Add AXP192 compatible
  dt-bindings: gpio: Add AXP192 GPIO bindings
  dt-bindings: power: axp20x-battery: Add AXP192 compatible
  mfd: axp20x: Add support for AXP192
  regulator: axp20x: Add support for AXP192
  iio: adc: axp20x_adc: Minor code cleanups
  iio: adc: axp20x_adc: Replace adc_en2 flag with adc_en2_mask field
  iio: adc: axp20x_adc: Add support for AXP192
  power: supply: axp20x_usb_power: Add support for AXP192
  pinctrl: Add AXP192 pin control driver
  power: axp20x_battery: Add constant charge current table
  power: axp20x_battery: Support battery status without fuel gauge
  power: axp20x_battery: Add support for AXP192

 .../bindings/gpio/x-powers,axp192-gpio.yaml   |  68 ++
 .../bindings/iio/adc/x-powers,axp209-adc.yaml |  18 +
 .../bindings/mfd/x-powers,axp152.yaml         |   1 +
 .../x-powers,axp20x-battery-power-supply.yaml |   1 +
 .../x-powers,axp20x-usb-power-supply.yaml     |   1 +
 drivers/iio/adc/axp20x_adc.c                  | 356 +++++++++--
 drivers/mfd/axp20x-i2c.c                      |   2 +
 drivers/mfd/axp20x.c                          | 152 +++++
 drivers/pinctrl/Kconfig                       |  13 +
 drivers/pinctrl/Makefile                      |   1 +
 drivers/pinctrl/pinctrl-axp192.c              | 598 ++++++++++++++++++
 drivers/power/supply/axp20x_battery.c         | 142 ++++-
 drivers/power/supply/axp20x_usb_power.c       |  84 ++-
 drivers/regulator/axp20x-regulator.c          | 100 ++-
 include/linux/mfd/axp20x.h                    |  84 +++
 15 files changed, 1547 insertions(+), 74 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/gpio/x-powers,axp192-gpio.yaml
 create mode 100644 drivers/pinctrl/pinctrl-axp192.c

Comments

Andy Shevchenko June 29, 2022, 9:13 p.m. UTC | #1
On Wed, Jun 29, 2022 at 4:30 PM Aidan MacDonald
<aidanmacdonald.0x0@gmail.com> wrote:
>
> The AXP192 PMIC's GPIO registers are much different from the GPIO
> registers of the AXP20x and AXP813 PMICs supported by the existing
> pinctrl-axp209 driver. It makes more sense to add a new driver for
> the AXP192, rather than add support in the existing axp20x driver.
>
> The pinctrl-axp192 driver is considerably more flexible in terms of
> register layout and should be able to support other X-Powers PMICs.
> Interrupts and pull down resistor configuration are supported too.

...

> +config PINCTRL_AXP192
> +       tristate "X-Powers AXP192 PMIC pinctrl and GPIO Support"
> +       depends on MFD_AXP20X
> +       select PINMUX
> +       select GENERIC_PINCONF
> +       select GPIOLIB
> +       help
> +         AXP PMICs provide multiple GPIOs that can be muxed for different
> +         functions. This driver bundles a pinctrl driver to select the function
> +         muxing and a GPIO driver to handle the GPIO when the GPIO function is
> +         selected.
> +         Say Y to enable pinctrl and GPIO support for the AXP192 PMIC.

What will be the module name if compiled as a module?

...

> +/**
> + * struct axp192_pctl_function - describes a function that GPIOs may have
> + *
> + * @name: Function name
> + * @muxvals: Mux values used for selecting this function, one per GPIO.
> + *           The i'th element corresponds to the i'th GPIO and is written
> + *           to the GPIO's control register field to select this function.
> + *           U8_MAX indicates that the pin does not support this function.
> + * @groups: Array of @ngroups groups listing pins supporting this function.
> + * @ngroups: Number of pin groups.
> + */
> +struct axp192_pctl_function {
> +       const char              *name;
> +       /* Mux value written to the control register to select the function (-1 if unsupported) */
> +       const u8                *muxvals;
> +       const char * const      *groups;
> +       unsigned int            ngroups;
> +};

Can it be replaced by struct function_desc?
https://elixir.bootlin.com/linux/latest/source/drivers/pinctrl/pinmux.h#L130

...

> +       ret = devm_gpiochip_add_data(dev, &pctl->chip, pctl);
> +       if (ret)
> +               dev_err_probe(dev, ret, "Failed to register GPIO chip\n");

Missed return.
Andy Shevchenko June 29, 2022, 9:16 p.m. UTC | #2
On Wed, Jun 29, 2022 at 11:14 PM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
> On Wed, Jun 29, 2022 at 4:29 PM Aidan MacDonald
> <aidanmacdonald.0x0@gmail.com> wrote:
> >
> > Changes in v4:
> >
> > * Drop regmap-irq patches and rebase on top of the regmap-irq
> >   refactoring series[1], which implements the same functionality.
> > * Reorder mfd_cells, putting one-line entries at the bottom.
> > * Fix incorrect example in axp192-gpio device tree bindings.
> > * Perform adc_en2 flag -> adc_en2_mask conversion in axp20x_adc
> >   as a separate patch.
> > * Simplify axp192_usb_power_set_current_max().
> > * Drop unneeded OF dependency in pin control driver, and document
> >   tables used for describing register layouts.
> > * Various style fixups suggested by Andy Shevchenko.
>
>
> For patches 6-11
> Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>

Ditto for patches 13-15.

Very good made series, thanks!

> > This patch series adds support for the X-Powers AXP192 PMIC to the
> > AXP20x driver framework.
> >
> > The first patch is a small change to regmap-irq to support the AXP192's
> > unusual IRQ register layout. It isn't possible to include all of the
> > IRQ registers in one regmap-irq chip without this.
> >
> > The rest of the changes are pretty straightforward, I think the only
> > notable parts are the axp20x_adc driver where there seems to be some
> > opportunities for code reuse (the axp192 is nearly a duplicate of the
> > axp20x) and the addition of a new pinctrl driver for the axp192, since
> > the axp20x pinctrl driver was not very easy to adapt.
Lee Jones June 30, 2022, 7:55 a.m. UTC | #3
On Wed, 29 Jun 2022, Andy Shevchenko wrote:

> On Wed, Jun 29, 2022 at 11:14 PM Andy Shevchenko
> <andy.shevchenko@gmail.com> wrote:
> > On Wed, Jun 29, 2022 at 4:29 PM Aidan MacDonald
> > <aidanmacdonald.0x0@gmail.com> wrote:
> > >
> > > Changes in v4:
> > >
> > > * Drop regmap-irq patches and rebase on top of the regmap-irq
> > >   refactoring series[1], which implements the same functionality.
> > > * Reorder mfd_cells, putting one-line entries at the bottom.
> > > * Fix incorrect example in axp192-gpio device tree bindings.
> > > * Perform adc_en2 flag -> adc_en2_mask conversion in axp20x_adc
> > >   as a separate patch.
> > > * Simplify axp192_usb_power_set_current_max().
> > > * Drop unneeded OF dependency in pin control driver, and document
> > >   tables used for describing register layouts.
> > > * Various style fixups suggested by Andy Shevchenko.
> >
> >
> > For patches 6-11
> > Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
> 
> Ditto for patches 13-15.

Not sure `b4` will pick these up!
Andy Shevchenko June 30, 2022, 8 a.m. UTC | #4
On Wed, Jun 29, 2022 at 4:30 PM Aidan MacDonald
<aidanmacdonald.0x0@gmail.com> wrote:
>
> The AXP192 has a battery charger similar to other X-Powers PMICs,
> but unlike the other supported devices, it does not have a fuel
> gauge and can't report battery capacity directly.

Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>

> Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com>
> Signed-off-by: Aidan MacDonald <aidanmacdonald.0x0@gmail.com>
> ---
>  drivers/power/supply/axp20x_battery.c | 49 +++++++++++++++++++++++++--
>  1 file changed, 46 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c
> index 574c1d001556..1e84d26ce8e3 100644
> --- a/drivers/power/supply/axp20x_battery.c
> +++ b/drivers/power/supply/axp20x_battery.c
> @@ -544,6 +544,19 @@ static int axp20x_battery_set_prop(struct power_supply *psy,
>         }
>  }
>
> +static enum power_supply_property axp192_battery_props[] = {
> +       POWER_SUPPLY_PROP_PRESENT,
> +       POWER_SUPPLY_PROP_ONLINE,
> +       POWER_SUPPLY_PROP_STATUS,
> +       POWER_SUPPLY_PROP_VOLTAGE_NOW,
> +       POWER_SUPPLY_PROP_CURRENT_NOW,
> +       POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
> +       POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
> +       POWER_SUPPLY_PROP_HEALTH,
> +       POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
> +       POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
> +};
> +
>  static enum power_supply_property axp20x_battery_props[] = {
>         POWER_SUPPLY_PROP_PRESENT,
>         POWER_SUPPLY_PROP_ONLINE,
> @@ -568,6 +581,16 @@ static int axp20x_battery_prop_writeable(struct power_supply *psy,
>                psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX;
>  }
>
> +static const struct power_supply_desc axp192_batt_ps_desc = {
> +       .name = "axp192-battery",
> +       .type = POWER_SUPPLY_TYPE_BATTERY,
> +       .properties = axp192_battery_props,
> +       .num_properties = ARRAY_SIZE(axp192_battery_props),
> +       .property_is_writeable = axp20x_battery_prop_writeable,
> +       .get_property = axp20x_battery_get_prop,
> +       .set_property = axp20x_battery_set_prop,
> +};
> +
>  static const struct power_supply_desc axp20x_batt_ps_desc = {
>         .name = "axp20x-battery",
>         .type = POWER_SUPPLY_TYPE_BATTERY,
> @@ -578,6 +601,19 @@ static const struct power_supply_desc axp20x_batt_ps_desc = {
>         .set_property = axp20x_battery_set_prop,
>  };
>
> +static const int axp192_ccc_table[AXP20X_CHRG_CTRL1_TGT_CURR+1] = {
> +       100000,  190000,  280000,  360000,
> +       450000,  550000,  630000,  700000,
> +       780000,  880000,  960000,  1000000,
> +       1080000, 1160000, 1240000, 1320000,
> +};
> +
> +static const struct axp_data axp192_data = {
> +       .ccc_table = axp192_ccc_table,
> +       .get_max_voltage = axp20x_battery_get_max_voltage,
> +       .set_max_voltage = axp20x_battery_set_max_voltage,
> +};
> +
>  static const struct axp_data axp209_data = {
>         .ccc_scale = 100000,
>         .ccc_offset = 300000,
> @@ -606,6 +642,9 @@ static const struct axp_data axp813_data = {
>
>  static const struct of_device_id axp20x_battery_ps_id[] = {
>         {
> +               .compatible = "x-powers,axp192-battery-power-supply",
> +               .data = (void *)&axp192_data,
> +       }, {
>                 .compatible = "x-powers,axp209-battery-power-supply",
>                 .data = (void *)&axp209_data,
>         }, {
> @@ -623,6 +662,7 @@ static int axp20x_power_probe(struct platform_device *pdev)
>         struct axp20x_batt_ps *axp20x_batt;
>         struct power_supply_config psy_cfg = {};
>         struct power_supply_battery_info *info;
> +       const struct power_supply_desc *ps_desc;
>         struct device *dev = &pdev->dev;
>
>         if (!of_device_is_available(pdev->dev.of_node))
> @@ -666,9 +706,12 @@ static int axp20x_power_probe(struct platform_device *pdev)
>
>         axp20x_batt->data = (struct axp_data *)of_device_get_match_data(dev);
>
> -       axp20x_batt->batt = devm_power_supply_register(&pdev->dev,
> -                                                      &axp20x_batt_ps_desc,
> -                                                      &psy_cfg);
> +       if (!axp20x_batt->data->has_fg)
> +               ps_desc = &axp192_batt_ps_desc;
> +       else
> +               ps_desc = &axp20x_batt_ps_desc;
> +
> +       axp20x_batt->batt = devm_power_supply_register(&pdev->dev, ps_desc, &psy_cfg);
>         if (IS_ERR(axp20x_batt->batt)) {
>                 dev_err(&pdev->dev, "failed to register power supply: %ld\n",
>                         PTR_ERR(axp20x_batt->batt));
> --
> 2.35.1
>
Andy Shevchenko June 30, 2022, 8:02 a.m. UTC | #5
On Thu, Jun 30, 2022 at 9:55 AM Lee Jones <lee.jones@linaro.org> wrote:
> On Wed, 29 Jun 2022, Andy Shevchenko wrote:
> > On Wed, Jun 29, 2022 at 11:14 PM Andy Shevchenko
> > <andy.shevchenko@gmail.com> wrote:
> > > On Wed, Jun 29, 2022 at 4:29 PM Aidan MacDonald
> > > <aidanmacdonald.0x0@gmail.com> wrote:
> > > >
> > > > Changes in v4:
> > > >
> > > > * Drop regmap-irq patches and rebase on top of the regmap-irq
> > > >   refactoring series[1], which implements the same functionality.
> > > > * Reorder mfd_cells, putting one-line entries at the bottom.
> > > > * Fix incorrect example in axp192-gpio device tree bindings.
> > > > * Perform adc_en2 flag -> adc_en2_mask conversion in axp20x_adc
> > > >   as a separate patch.
> > > > * Simplify axp192_usb_power_set_current_max().
> > > > * Drop unneeded OF dependency in pin control driver, and document
> > > >   tables used for describing register layouts.
> > > > * Various style fixups suggested by Andy Shevchenko.
> > >
> > > For patches 6-11
> > > Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
> >
> > Ditto for patches 13-15.
>
> Not sure `b4` will pick these up!

No it won't. But it's not an issue, one may use `git msg-filter` for
that, esp. taking into account that series most likely will be resent
due to patch 12 (`but not fully sure it will be the case).

For your convenience I have added on per patch basis.
Lee Jones June 30, 2022, 8:46 a.m. UTC | #6
On Thu, 30 Jun 2022, Andy Shevchenko wrote:

> On Thu, Jun 30, 2022 at 9:55 AM Lee Jones <lee.jones@linaro.org> wrote:
> > On Wed, 29 Jun 2022, Andy Shevchenko wrote:
> > > On Wed, Jun 29, 2022 at 11:14 PM Andy Shevchenko
> > > <andy.shevchenko@gmail.com> wrote:
> > > > On Wed, Jun 29, 2022 at 4:29 PM Aidan MacDonald
> > > > <aidanmacdonald.0x0@gmail.com> wrote:
> > > > >
> > > > > Changes in v4:
> > > > >
> > > > > * Drop regmap-irq patches and rebase on top of the regmap-irq
> > > > >   refactoring series[1], which implements the same functionality.
> > > > > * Reorder mfd_cells, putting one-line entries at the bottom.
> > > > > * Fix incorrect example in axp192-gpio device tree bindings.
> > > > > * Perform adc_en2 flag -> adc_en2_mask conversion in axp20x_adc
> > > > >   as a separate patch.
> > > > > * Simplify axp192_usb_power_set_current_max().
> > > > > * Drop unneeded OF dependency in pin control driver, and document
> > > > >   tables used for describing register layouts.
> > > > > * Various style fixups suggested by Andy Shevchenko.
> > > >
> > > > For patches 6-11
> > > > Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
> > >
> > > Ditto for patches 13-15.
> >
> > Not sure `b4` will pick these up!
> 
> No it won't. But it's not an issue, one may use `git msg-filter` for
> that, esp. taking into account that series most likely will be resent
> due to patch 12 (`but not fully sure it will be the case).
> 
> For your convenience I have added on per patch basis.

That helps, thanks Andy.
Aidan MacDonald July 1, 2022, 3:37 p.m. UTC | #7
Andy Shevchenko <andy.shevchenko@gmail.com> writes:

> On Wed, Jun 29, 2022 at 4:30 PM Aidan MacDonald
> <aidanmacdonald.0x0@gmail.com> wrote:
>>
>> The AXP192 PMIC's GPIO registers are much different from the GPIO
>> registers of the AXP20x and AXP813 PMICs supported by the existing
>> pinctrl-axp209 driver. It makes more sense to add a new driver for
>> the AXP192, rather than add support in the existing axp20x driver.
>>
>> The pinctrl-axp192 driver is considerably more flexible in terms of
>> register layout and should be able to support other X-Powers PMICs.
>> Interrupts and pull down resistor configuration are supported too.
>
> ...
>
>> +config PINCTRL_AXP192
>> +       tristate "X-Powers AXP192 PMIC pinctrl and GPIO Support"
>> +       depends on MFD_AXP20X
>> +       select PINMUX
>> +       select GENERIC_PINCONF
>> +       select GPIOLIB
>> +       help
>> +         AXP PMICs provide multiple GPIOs that can be muxed for different
>> +         functions. This driver bundles a pinctrl driver to select the function
>> +         muxing and a GPIO driver to handle the GPIO when the GPIO function is
>> +         selected.
>> +         Say Y to enable pinctrl and GPIO support for the AXP192 PMIC.
>
> What will be the module name if compiled as a module?
>
> ...
>
>> +/**
>> + * struct axp192_pctl_function - describes a function that GPIOs may have
>> + *
>> + * @name: Function name
>> + * @muxvals: Mux values used for selecting this function, one per GPIO.
>> + *           The i'th element corresponds to the i'th GPIO and is written
>> + *           to the GPIO's control register field to select this function.
>> + *           U8_MAX indicates that the pin does not support this function.
>> + * @groups: Array of @ngroups groups listing pins supporting this function.
>> + * @ngroups: Number of pin groups.
>> + */
>> +struct axp192_pctl_function {
>> +       const char              *name;
>> +       /* Mux value written to the control register to select the function (-1 if unsupported) */
>> +       const u8                *muxvals;
>> +       const char * const      *groups;
>> +       unsigned int            ngroups;
>> +};
>
> Can it be replaced by struct function_desc?
> https://elixir.bootlin.com/linux/latest/source/drivers/pinctrl/pinmux.h#L130

That'd work, but using the generic infrastructure doesn't allow me to
simplify anything -- I can eliminate three trivial functions, but the
generic code is higher overhead (extra allocations, radix trees, ...)
so I'd prefer to stick with the current approach.

>> +       ret = devm_gpiochip_add_data(dev, &pctl->chip, pctl);
>> +       if (ret)
>> +               dev_err_probe(dev, ret, "Failed to register GPIO chip\n");
>
> Missed return.

Thanks for catching this, that was pretty silly of me...
Andy Shevchenko July 1, 2022, 8:06 p.m. UTC | #8
On Fri, Jul 1, 2022 at 5:36 PM Aidan MacDonald
<aidanmacdonald.0x0@gmail.com> wrote:
> Andy Shevchenko <andy.shevchenko@gmail.com> writes:
> > On Wed, Jun 29, 2022 at 4:30 PM Aidan MacDonald
> > <aidanmacdonald.0x0@gmail.com> wrote:

...

> >> +struct axp192_pctl_function {
> >> +       const char              *name;
> >> +       /* Mux value written to the control register to select the function (-1 if unsupported) */
> >> +       const u8                *muxvals;
> >> +       const char * const      *groups;
> >> +       unsigned int            ngroups;
> >> +};
> >
> > Can it be replaced by struct function_desc?
> > https://elixir.bootlin.com/linux/latest/source/drivers/pinctrl/pinmux.h#L130
>
> That'd work, but using the generic infrastructure doesn't allow me to
> simplify anything -- I can eliminate three trivial functions, but the
> generic code is higher overhead (extra allocations, radix trees, ...)

I really don't see how it gets into extra allocations. Either way you
have a pointer to opaque data or in your current code it's called
muxvals. Other fields seem 1:1 what is in struct function_desc. The
code will be probably the same.

I.o.w. I'm talking of eliminating data type, and not about simplifying
the code by fully switching to generic infrastructure.

> so I'd prefer to stick with the current approach.