mbox series

[0/8] add support for AXP813 ADC and battery power supply

Message ID cover.4052f8c517c42db26a3cabe078cad333243d371c.1512396054.git-series.quentin.schulz@free-electrons.com
Headers show
Series add support for AXP813 ADC and battery power supply | expand

Message

Quentin Schulz Dec. 4, 2017, 2:12 p.m. UTC
The AXP813 PMIC is relatively close to the already supported AXP20X and
AXP22X. It provides three different power outputs: battery, AC and USB, and
measures a few different things: temperature, power supply status, current
current and voltage supplied, maximum current limit, battery capacity, min
and max voltage limits.

One of its two GPIOs can be used as an ADC.

There are a few differences with AXP20X/AXP22X PMICs though:
  - a different constant charge current formula,
  - battery temperature, GPIO0 and battery voltages are the only voltages
  measurable,
  - all data are stored on 12 bits (AXP20X/AXP22X had one type of data that
  was stored on 13 bits),
  - different scales and offsets,
  - a different ADC rate formula and register,

This patch series adds support for the PMIC's ADC and battery power supply
in the existing drivers.

Make the axp20x MFD automatically probe the ADC driver, add the battery
power supply node in axp81x node and enable it for the TBS A711 since it
has a soldered battery.

Q: The BananaPi M3 has two solder balls for battery, should the battery
power supply node be enabled for this board as well?

Thanks,
Quentin

Quentin Schulz (8):
  iio: adc: axp20x_adc: put ADC rate setting in a per-variant function
  iio: adc: axp20x_adc: add support for AXP813 ADC
  mfd: axp20x: probe axp20x_adc driver for AXP813
  dt-bindings: power: supply: axp20x: add AXP813 battery DT binding
  power: supply: axp20x_battery: add support for AXP813
  mfd: axp20x: add battery power supply cell for AXP813
  ARM: dtsi: axp81x: add battery power supply subnode
  ARM: dtsi: sun8i: a711: enable battery power supply subnode

 Documentation/devicetree/bindings/power/supply/axp20x_battery.txt |   8 ++--
 arch/arm/boot/dts/axp81x.dtsi                                     |   5 +++-
 arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts                         |   4 ++-
 drivers/iio/adc/axp20x_adc.c                                      | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 drivers/mfd/axp20x.c                                              |   7 +++-
 drivers/power/supply/axp20x_battery.c                             |  44 ++++++++++++++++++++++-
 include/linux/mfd/axp20x.h                                        |   2 +-
 7 files changed, 196 insertions(+), 13 deletions(-)

base-commit: 7cc61a0a562c7005d2a34f97e94cf26689a2f57c
-- 
git-series 0.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Maxime Ripard Dec. 5, 2017, 8:08 a.m. UTC | #1
On Mon, Dec 04, 2017 at 03:12:49PM +0100, Quentin Schulz wrote:
> This makes the axp20x_adc driver probe with platform device id

> "axp813-adc".

> 

> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>

> ---

>  drivers/mfd/axp20x.c | 4 +++-

>  1 file changed, 3 insertions(+), 1 deletion(-)

> 

> diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c

> index 2468b43..42e54d1 100644

> --- a/drivers/mfd/axp20x.c

> +++ b/drivers/mfd/axp20x.c

> @@ -878,7 +878,9 @@ static struct mfd_cell axp813_cells[] = {

>  		.resources		= axp803_pek_resources,

>  	}, {

>  		.name			= "axp20x-regulator",

> -	}

> +	}, {

> +		.name			= "axp813-adc",

> +	},


Any particular reason you're not adding it to the DT?

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
Lee Jones Dec. 5, 2017, 8:24 a.m. UTC | #2
On Mon, 04 Dec 2017, Quentin Schulz wrote:

> As axp20x-battery-power-supply now supports AXP813, add a cell for it.

> 

> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>

> ---

>  drivers/mfd/axp20x.c | 3 +++

>  1 file changed, 3 insertions(+)


For my own reference:
  Acked-for-MFD-by: Lee Jones <lee.jones@linaro.org>

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rob Herring (Arm) Dec. 6, 2017, 9:16 p.m. UTC | #3
On Mon, Dec 04, 2017 at 03:12:50PM +0100, Quentin Schulz wrote:
> The AXP813 can have a battery as power supply, so let's add it to the

> list of compatibles.

> 

> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>

> ---

>  Documentation/devicetree/bindings/power/supply/axp20x_battery.txt | 8 +++----

>  1 file changed, 4 insertions(+), 4 deletions(-)


Reviewed-by: Rob Herring <robh@kernel.org>

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Chen-Yu Tsai Dec. 7, 2017, 8:54 a.m. UTC | #4
On Thu, Dec 7, 2017 at 4:51 PM, Quentin Schulz
<quentin.schulz@free-electrons.com> wrote:
> Hi Maxime,

>

> On 05/12/2017 09:08, Maxime Ripard wrote:

>> On Mon, Dec 04, 2017 at 03:12:49PM +0100, Quentin Schulz wrote:

>>> This makes the axp20x_adc driver probe with platform device id

>>> "axp813-adc".

>>>

>>> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>

>>> ---

>>>  drivers/mfd/axp20x.c | 4 +++-

>>>  1 file changed, 3 insertions(+), 1 deletion(-)

>>>

>>> diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c

>>> index 2468b43..42e54d1 100644

>>> --- a/drivers/mfd/axp20x.c

>>> +++ b/drivers/mfd/axp20x.c

>>> @@ -878,7 +878,9 @@ static struct mfd_cell axp813_cells[] = {

>>>              .resources              = axp803_pek_resources,

>>>      }, {

>>>              .name                   = "axp20x-regulator",

>>> -    }

>>> +    }, {

>>> +            .name                   = "axp813-adc",

>>> +    },

>>

>> Any particular reason you're not adding it to the DT?

>>

>

> No, no particular reason. It's just the way it is currently for AXP209

> and AXP22x so did the same for AXP813.

>

> I'll add DT "support" in next version for all AXPs supported by this

> driver. Or is it worthy of a small separate patch series?


IIRC there's no DT support because there's no need to reference
it in the device tree.

ChenYu
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Quentin Schulz Dec. 11, 2017, 8:35 a.m. UTC | #5
Hi Jonathan,

On 10/12/2017 17:49, Jonathan Cameron wrote:
> On Mon,  4 Dec 2017 15:12:51 +0100

> Quentin Schulz <quentin.schulz@free-electrons.com> wrote:

> 

>> The X-Powers AXP813 PMIC has got some slight differences from

>> AXP20X/AXP22X PMICs:

>>  - the maximum voltage supplied by the PMIC is 4.35 instead of 4.36/4.24

>>  for AXP20X/AXP22X,

>>  - the constant charge current formula is different,

>>

>> It also has a bit to tell whether the battery percentage returned by the

>> PMIC is valid.

>>

>> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>

> 

> I'd use switch statements when matching the IDs as that'll be more elegant

> as you perhaps add further devices going forward...

> 

> Other than that, looks good to me.

> 


Well, I was wondering if it shouldn't be better to define a structure
for each device containing their quirks, functions, etc... like it is
done for the ADC or the ACIN power supply driver part.

struct axp20x_data {
	bool	has_valid_fg_reg;
	void 	constant_charge_current_to_raw(struct axp20x_batt_ps *axp, int *val);
	void 	raw_to_constant_charge_current(struct axp20x_batt_ps *axp, int *val);
	int 	get_max_voltage(struct axp20x_batt_ps *axp, int *val);
	[...]
};

static const struct of_device_id axp20x_battery_ps_id[] = {
	{ .compatible = "x-powers,axp209-battery-power-supply", .data = (void
*)&axp209_data, }, {}
};

void probe()
{
	[...]
	axp20x_batt->info = of_device_get_match_data(&pdev->dev);
	[...]
}

Sebastian, any objection on doing this?

Thanks,
Quentin

> Jonathan

> 

>> ---

>>  drivers/power/supply/axp20x_battery.c | 44 +++++++++++++++++++++++++++-

>>  1 file changed, 43 insertions(+), 1 deletion(-)

>>

>> diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c

>> index 7494f0f..cb30302 100644

>> --- a/drivers/power/supply/axp20x_battery.c

>> +++ b/drivers/power/supply/axp20x_battery.c

>> @@ -46,6 +46,8 @@

>>  #define AXP20X_CHRG_CTRL1_TGT_4_2V	(2 << 5)

>>  #define AXP20X_CHRG_CTRL1_TGT_4_36V	(3 << 5)

>>  

>> +#define AXP813_CHRG_CTRL1_TGT_4_35V	(3 << 5)

>> +

>>  #define AXP22X_CHRG_CTRL1_TGT_4_22V	(1 << 5)

>>  #define AXP22X_CHRG_CTRL1_TGT_4_24V	(3 << 5)

>>  

>> @@ -123,10 +125,41 @@ static int axp22x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,

>>  	return 0;

>>  }

>>  

>> +static int axp813_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,

>> +					  int *val)

>> +{

>> +	int ret, reg;

>> +

>> +	ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, &reg);

>> +	if (ret)

>> +		return ret;

>> +

>> +	switch (reg & AXP20X_CHRG_CTRL1_TGT_VOLT) {

> 

> You could do a lookup based from a table instead which might

> be ever so slightly more elegant..

> 

>> +	case AXP20X_CHRG_CTRL1_TGT_4_1V:

>> +		*val = 4100000;

>> +		break;

>> +	case AXP20X_CHRG_CTRL1_TGT_4_15V:

>> +		*val = 4150000;

>> +		break;

>> +	case AXP20X_CHRG_CTRL1_TGT_4_2V:

>> +		*val = 4200000;

>> +		break;

>> +	case AXP813_CHRG_CTRL1_TGT_4_35V:

>> +		*val = 4350000;

>> +		break;

>> +	default:

>> +		return -EINVAL;

>> +	}

>> +

>> +	return 0;

>> +}

>> +

>>  static void raw_to_constant_charge_current(struct axp20x_batt_ps *axp, int *val)

>>  {

>>  	if (axp->axp_id == AXP209_ID)

>>  		*val = *val * 100000 + 300000;

>> +	else if (axp->axp_id == AXP813_ID)

>> +		*val = *val * 200000 + 200000;

>>  	else

>>  		*val = *val * 150000 + 300000;

> 

> Switch?

> 

>>  }

>> @@ -135,6 +168,8 @@ static void constant_charge_current_to_raw(struct axp20x_batt_ps *axp, int *val)

>>  {

>>  	if (axp->axp_id == AXP209_ID)

>>  		*val = (*val - 300000) / 100000;

>> +	else if (axp->axp_id == AXP813_ID)

>> +		*val = (*val - 200000) / 200000;

>>  	else

>>  		*val = (*val - 300000) / 150000;

>>  }

>> @@ -269,7 +304,8 @@ static int axp20x_battery_get_prop(struct power_supply *psy,

>>  		if (ret)

>>  			return ret;

>>  

>> -		if (axp20x_batt->axp_id == AXP221_ID &&

>> +		if ((axp20x_batt->axp_id == AXP221_ID ||

>> +		     axp20x_batt->axp_id == AXP813_ID) &&

>>  		    !(reg & AXP22X_FG_VALID))

>>  			return -EINVAL;

>>  

>> @@ -284,6 +320,9 @@ static int axp20x_battery_get_prop(struct power_supply *psy,

>>  		if (axp20x_batt->axp_id == AXP209_ID)

>>  			return axp20x_battery_get_max_voltage(axp20x_batt,

>>  							      &val->intval);

>> +		else if (axp20x_batt->axp_id == AXP813_ID)

>> +			return axp813_battery_get_max_voltage(axp20x_batt,

>> +							      &val->intval);

>>  		return axp22x_battery_get_max_voltage(axp20x_batt,

>>  						      &val->intval);

> 

> Worth converting to a switch statement to make it more elegant for future

> devices?

> 

>>  

>> @@ -467,6 +506,9 @@ static const struct of_device_id axp20x_battery_ps_id[] = {

>>  	}, {

>>  		.compatible = "x-powers,axp221-battery-power-supply",

>>  		.data = (void *)AXP221_ID,

>> +	}, {

>> +		.compatible = "x-powers,axp813-battery-power-supply",

>> +		.data = (void *)AXP813_ID,

>>  	}, { /* sentinel */ },

>>  };

>>  MODULE_DEVICE_TABLE(of, axp20x_battery_ps_id);

> 


-- 
Quentin Schulz, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jonathan Cameron Dec. 12, 2017, 7:55 p.m. UTC | #6
On Mon, 11 Dec 2017 09:35:43 +0100
Quentin Schulz <quentin.schulz@free-electrons.com> wrote:

> Hi Jonathan,

> 

> On 10/12/2017 17:49, Jonathan Cameron wrote:

> > On Mon,  4 Dec 2017 15:12:51 +0100

> > Quentin Schulz <quentin.schulz@free-electrons.com> wrote:

> >   

> >> The X-Powers AXP813 PMIC has got some slight differences from

> >> AXP20X/AXP22X PMICs:

> >>  - the maximum voltage supplied by the PMIC is 4.35 instead of 4.36/4.24

> >>  for AXP20X/AXP22X,

> >>  - the constant charge current formula is different,

> >>

> >> It also has a bit to tell whether the battery percentage returned by the

> >> PMIC is valid.

> >>

> >> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>  

> > 

> > I'd use switch statements when matching the IDs as that'll be more elegant

> > as you perhaps add further devices going forward...

> > 

> > Other than that, looks good to me.

> >   

> 

> Well, I was wondering if it shouldn't be better to define a structure

> for each device containing their quirks, functions, etc... like it is

> done for the ADC or the ACIN power supply driver part.

> 


Even better.

> struct axp20x_data {

> 	bool	has_valid_fg_reg;

> 	void 	constant_charge_current_to_raw(struct axp20x_batt_ps *axp, int *val);

> 	void 	raw_to_constant_charge_current(struct axp20x_batt_ps *axp, int *val);

> 	int 	get_max_voltage(struct axp20x_batt_ps *axp, int *val);

> 	[...]

> };

> 

> static const struct of_device_id axp20x_battery_ps_id[] = {

> 	{ .compatible = "x-powers,axp209-battery-power-supply", .data = (void

> *)&axp209_data, }, {}

> };

> 

> void probe()

> {

> 	[...]

> 	axp20x_batt->info = of_device_get_match_data(&pdev->dev);

> 	[...]

> }

> 

> Sebastian, any objection on doing this?

> 

> Thanks,

> Quentin

> 

> > Jonathan

> >   

> >> ---

> >>  drivers/power/supply/axp20x_battery.c | 44 +++++++++++++++++++++++++++-

> >>  1 file changed, 43 insertions(+), 1 deletion(-)

> >>

> >> diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c

> >> index 7494f0f..cb30302 100644

> >> --- a/drivers/power/supply/axp20x_battery.c

> >> +++ b/drivers/power/supply/axp20x_battery.c

> >> @@ -46,6 +46,8 @@

> >>  #define AXP20X_CHRG_CTRL1_TGT_4_2V	(2 << 5)

> >>  #define AXP20X_CHRG_CTRL1_TGT_4_36V	(3 << 5)

> >>  

> >> +#define AXP813_CHRG_CTRL1_TGT_4_35V	(3 << 5)

> >> +

> >>  #define AXP22X_CHRG_CTRL1_TGT_4_22V	(1 << 5)

> >>  #define AXP22X_CHRG_CTRL1_TGT_4_24V	(3 << 5)

> >>  

> >> @@ -123,10 +125,41 @@ static int axp22x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,

> >>  	return 0;

> >>  }

> >>  

> >> +static int axp813_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,

> >> +					  int *val)

> >> +{

> >> +	int ret, reg;

> >> +

> >> +	ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, &reg);

> >> +	if (ret)

> >> +		return ret;

> >> +

> >> +	switch (reg & AXP20X_CHRG_CTRL1_TGT_VOLT) {  

> > 

> > You could do a lookup based from a table instead which might

> > be ever so slightly more elegant..

> >   

> >> +	case AXP20X_CHRG_CTRL1_TGT_4_1V:

> >> +		*val = 4100000;

> >> +		break;

> >> +	case AXP20X_CHRG_CTRL1_TGT_4_15V:

> >> +		*val = 4150000;

> >> +		break;

> >> +	case AXP20X_CHRG_CTRL1_TGT_4_2V:

> >> +		*val = 4200000;

> >> +		break;

> >> +	case AXP813_CHRG_CTRL1_TGT_4_35V:

> >> +		*val = 4350000;

> >> +		break;

> >> +	default:

> >> +		return -EINVAL;

> >> +	}

> >> +

> >> +	return 0;

> >> +}

> >> +

> >>  static void raw_to_constant_charge_current(struct axp20x_batt_ps *axp, int *val)

> >>  {

> >>  	if (axp->axp_id == AXP209_ID)

> >>  		*val = *val * 100000 + 300000;

> >> +	else if (axp->axp_id == AXP813_ID)

> >> +		*val = *val * 200000 + 200000;

> >>  	else

> >>  		*val = *val * 150000 + 300000;  

> > 

> > Switch?

> >   

> >>  }

> >> @@ -135,6 +168,8 @@ static void constant_charge_current_to_raw(struct axp20x_batt_ps *axp, int *val)

> >>  {

> >>  	if (axp->axp_id == AXP209_ID)

> >>  		*val = (*val - 300000) / 100000;

> >> +	else if (axp->axp_id == AXP813_ID)

> >> +		*val = (*val - 200000) / 200000;

> >>  	else

> >>  		*val = (*val - 300000) / 150000;

> >>  }

> >> @@ -269,7 +304,8 @@ static int axp20x_battery_get_prop(struct power_supply *psy,

> >>  		if (ret)

> >>  			return ret;

> >>  

> >> -		if (axp20x_batt->axp_id == AXP221_ID &&

> >> +		if ((axp20x_batt->axp_id == AXP221_ID ||

> >> +		     axp20x_batt->axp_id == AXP813_ID) &&

> >>  		    !(reg & AXP22X_FG_VALID))

> >>  			return -EINVAL;

> >>  

> >> @@ -284,6 +320,9 @@ static int axp20x_battery_get_prop(struct power_supply *psy,

> >>  		if (axp20x_batt->axp_id == AXP209_ID)

> >>  			return axp20x_battery_get_max_voltage(axp20x_batt,

> >>  							      &val->intval);

> >> +		else if (axp20x_batt->axp_id == AXP813_ID)

> >> +			return axp813_battery_get_max_voltage(axp20x_batt,

> >> +							      &val->intval);

> >>  		return axp22x_battery_get_max_voltage(axp20x_batt,

> >>  						      &val->intval);  

> > 

> > Worth converting to a switch statement to make it more elegant for future

> > devices?

> >   

> >>  

> >> @@ -467,6 +506,9 @@ static const struct of_device_id axp20x_battery_ps_id[] = {

> >>  	}, {

> >>  		.compatible = "x-powers,axp221-battery-power-supply",

> >>  		.data = (void *)AXP221_ID,

> >> +	}, {

> >> +		.compatible = "x-powers,axp813-battery-power-supply",

> >> +		.data = (void *)AXP813_ID,

> >>  	}, { /* sentinel */ },

> >>  };

> >>  MODULE_DEVICE_TABLE(of, axp20x_battery_ps_id);  

> >   

> 


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