ARM Sunxi Platform Development
 help / color / mirror / Atom feed
* [PATCH] mfd: axp20x: Change volatile ranges on axp803
@ 2026-03-15 12:49 Ondřej Jirman
  2026-03-21  6:25 ` Jernej Škrabec
  0 siblings, 1 reply; 7+ messages in thread
From: Ondřej Jirman @ 2026-03-15 12:49 UTC (permalink / raw)
  To: linux-sunxi; +Cc: linux-kernel, Ondrej Jirman, Lee Jones, Chen-Yu Tsai

From: Ondrej Jirman <megi@xff.cz>

Regulator control registers can be cached. They don't update by
themselves. Enable cache on them, to speed up voltage changes,
particularly DCDC2 which needs to be handled quickly due to being used
for CPUX cores and is changed very frequently by some cpufreq schedulers.

This shrinks register access over RSB bus to one write per voltage
change (down from 4 or so).

Signed-off-by: Ondrej Jirman <megi@xff.cz>
---
 drivers/mfd/axp20x.c | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index 0d0d40972eb8..2ea409029d2f 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -172,6 +172,18 @@ static const struct regmap_range axp288_volatile_ranges[] = {
 	regmap_reg_range(AXP20X_FG_RES, AXP288_FG_CC_CAP_REG),
 };
 
+static const struct regmap_range axp803_volatile_ranges[] = {
+	regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP288_POWER_REASON),
+	regmap_reg_range(AXP288_BC_GLOBAL, AXP288_BC_GLOBAL),
+	regmap_reg_range(AXP288_BC_DET_STAT, AXP20X_VBUS_IPSOUT_MGMT),
+	regmap_reg_range(AXP20X_CHRG_BAK_CTRL, AXP20X_CHRG_BAK_CTRL),
+	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L),
+	regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL),
+	regmap_reg_range(AXP20X_GPIO1_CTRL, AXP22X_GPIO_STATE),
+	regmap_reg_range(AXP288_RT_BATT_V_H, AXP288_RT_BATT_V_L),
+	regmap_reg_range(AXP20X_FG_RES, AXP288_FG_CC_CAP_REG),
+};
+
 static const struct regmap_access_table axp288_writeable_table = {
 	.yes_ranges	= axp288_writeable_ranges,
 	.n_yes_ranges	= ARRAY_SIZE(axp288_writeable_ranges),
@@ -182,6 +194,11 @@ static const struct regmap_access_table axp288_volatile_table = {
 	.n_yes_ranges	= ARRAY_SIZE(axp288_volatile_ranges),
 };
 
+static const struct regmap_access_table axp803_volatile_table = {
+	.yes_ranges	= axp803_volatile_ranges,
+	.n_yes_ranges	= ARRAY_SIZE(axp803_volatile_ranges),
+};
+
 static const struct regmap_range axp806_writeable_ranges[] = {
 	regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_DATACACHE(3)),
 	regmap_reg_range(AXP806_PWR_OUT_CTRL1, AXP806_CLDO3_V_CTRL),
@@ -456,6 +473,15 @@ static const struct regmap_config axp22x_regmap_config = {
 	.cache_type	= REGCACHE_MAPLE,
 };
 
+static const struct regmap_config axp803_regmap_config = {
+	.reg_bits	= 8,
+	.val_bits	= 8,
+	.wr_table	= &axp288_writeable_table,
+	.volatile_table	= &axp803_volatile_table,
+	.max_register	= AXP288_FG_TUNE5,
+	.cache_type	= REGCACHE_MAPLE,
+};
+
 static const struct regmap_config axp288_regmap_config = {
 	.reg_bits	= 8,
 	.val_bits	= 8,
@@ -1368,7 +1394,7 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
 	case AXP803_ID:
 		axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
 		axp20x->cells = axp803_cells;
-		axp20x->regmap_cfg = &axp288_regmap_config;
+		axp20x->regmap_cfg = &axp803_regmap_config;
 		axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;
 		break;
 	case AXP806_ID:
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] mfd: axp20x: Change volatile ranges on axp803
  2026-03-15 12:49 [PATCH] mfd: axp20x: Change volatile ranges on axp803 Ondřej Jirman
@ 2026-03-21  6:25 ` Jernej Škrabec
  2026-03-21 18:26   ` Ondřej Jirman
  2026-04-21  5:06   ` Icenowy Zheng
  0 siblings, 2 replies; 7+ messages in thread
From: Jernej Škrabec @ 2026-03-21  6:25 UTC (permalink / raw)
  To: linux-sunxi, Ondřej Jirman
  Cc: linux-kernel, Ondrej Jirman, Lee Jones, Chen-Yu Tsai

Dne nedelja, 15. marec 2026 ob 13:49:31 Srednjeevropski standardni čas je Ondřej Jirman napisal(a):
> From: Ondrej Jirman <megi@xff.cz>
> 
> Regulator control registers can be cached. They don't update by
> themselves. Enable cache on them, to speed up voltage changes,
> particularly DCDC2 which needs to be handled quickly due to being used
> for CPUX cores and is changed very frequently by some cpufreq schedulers.

That's not really the case, DCDC2-DCDC6 registers have DVM finished status
bit, which is volatile and it is right to have them in volatile range.
However, it is true that other registers are non-volatile, so that range can
be considerably shrinked. It seems that AXP288 have same register layout
but I can't say for sure (I only found datasheet for AXP288C), so it's best
to leave it alone and apply changes only to AXP803. 

Best regards,
Jernej

> 
> This shrinks register access over RSB bus to one write per voltage
> change (down from 4 or so).
> 
> Signed-off-by: Ondrej Jirman <megi@xff.cz>
> ---
>  drivers/mfd/axp20x.c | 28 +++++++++++++++++++++++++++-
>  1 file changed, 27 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
> index 0d0d40972eb8..2ea409029d2f 100644
> --- a/drivers/mfd/axp20x.c
> +++ b/drivers/mfd/axp20x.c
> @@ -172,6 +172,18 @@ static const struct regmap_range axp288_volatile_ranges[] = {
>  	regmap_reg_range(AXP20X_FG_RES, AXP288_FG_CC_CAP_REG),
>  };
>  
> +static const struct regmap_range axp803_volatile_ranges[] = {
> +	regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP288_POWER_REASON),
> +	regmap_reg_range(AXP288_BC_GLOBAL, AXP288_BC_GLOBAL),
> +	regmap_reg_range(AXP288_BC_DET_STAT, AXP20X_VBUS_IPSOUT_MGMT),
> +	regmap_reg_range(AXP20X_CHRG_BAK_CTRL, AXP20X_CHRG_BAK_CTRL),
> +	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L),
> +	regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL),
> +	regmap_reg_range(AXP20X_GPIO1_CTRL, AXP22X_GPIO_STATE),
> +	regmap_reg_range(AXP288_RT_BATT_V_H, AXP288_RT_BATT_V_L),
> +	regmap_reg_range(AXP20X_FG_RES, AXP288_FG_CC_CAP_REG),
> +};
> +
>  static const struct regmap_access_table axp288_writeable_table = {
>  	.yes_ranges	= axp288_writeable_ranges,
>  	.n_yes_ranges	= ARRAY_SIZE(axp288_writeable_ranges),
> @@ -182,6 +194,11 @@ static const struct regmap_access_table axp288_volatile_table = {
>  	.n_yes_ranges	= ARRAY_SIZE(axp288_volatile_ranges),
>  };
>  
> +static const struct regmap_access_table axp803_volatile_table = {
> +	.yes_ranges	= axp803_volatile_ranges,
> +	.n_yes_ranges	= ARRAY_SIZE(axp803_volatile_ranges),
> +};
> +
>  static const struct regmap_range axp806_writeable_ranges[] = {
>  	regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_DATACACHE(3)),
>  	regmap_reg_range(AXP806_PWR_OUT_CTRL1, AXP806_CLDO3_V_CTRL),
> @@ -456,6 +473,15 @@ static const struct regmap_config axp22x_regmap_config = {
>  	.cache_type	= REGCACHE_MAPLE,
>  };
>  
> +static const struct regmap_config axp803_regmap_config = {
> +	.reg_bits	= 8,
> +	.val_bits	= 8,
> +	.wr_table	= &axp288_writeable_table,
> +	.volatile_table	= &axp803_volatile_table,
> +	.max_register	= AXP288_FG_TUNE5,
> +	.cache_type	= REGCACHE_MAPLE,
> +};
> +
>  static const struct regmap_config axp288_regmap_config = {
>  	.reg_bits	= 8,
>  	.val_bits	= 8,
> @@ -1368,7 +1394,7 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
>  	case AXP803_ID:
>  		axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
>  		axp20x->cells = axp803_cells;
> -		axp20x->regmap_cfg = &axp288_regmap_config;
> +		axp20x->regmap_cfg = &axp803_regmap_config;
>  		axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;
>  		break;
>  	case AXP806_ID:
> 





^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] mfd: axp20x: Change volatile ranges on axp803
  2026-03-21  6:25 ` Jernej Škrabec
@ 2026-03-21 18:26   ` Ondřej Jirman
  2026-05-09 13:00     ` Jernej Škrabec
  2026-04-21  5:06   ` Icenowy Zheng
  1 sibling, 1 reply; 7+ messages in thread
From: Ondřej Jirman @ 2026-03-21 18:26 UTC (permalink / raw)
  To: Jernej Škrabec; +Cc: linux-sunxi, linux-kernel, Lee Jones, Chen-Yu Tsai

On Sat, Mar 21, 2026 at 07:25:49AM +0100, Jernej Škrabec wrote:
> Dne nedelja, 15. marec 2026 ob 13:49:31 Srednjeevropski standardni čas je Ondřej Jirman napisal(a):
> > From: Ondrej Jirman <megi@xff.cz>
> > 
> > Regulator control registers can be cached. They don't update by
> > themselves. Enable cache on them, to speed up voltage changes,
> > particularly DCDC2 which needs to be handled quickly due to being used
> > for CPUX cores and is changed very frequently by some cpufreq schedulers.
> 
> That's not really the case, DCDC2-DCDC6 registers have DVM finished status
> bit, which is volatile and it is right to have them in volatile range.
> However, it is true that other registers are non-volatile, so that range can
> be considerably shrinked. It seems that AXP288 have same register layout
> but I can't say for sure (I only found datasheet for AXP288C), so it's best
> to leave it alone and apply changes only to AXP803. 

While true, it's not used by any kernel drivers, and having the whole register
marked volatile for a single unused bit is contributing 10s of % of permanent
CPU load just from cpufreq DVFS operations alone when using schedutil governor,
which is doing DVFS hundred or more times per second.

If someone will want to use this bit in the regulator driver, they can use eg.
regmap_read_bypassed() to access the bit, while keepig the other parts of
regulator implementation performant.

But I guess it may deserve a comment in the code.

Kind regards,
	o.

> Best regards,
> Jernej
> 
> > 
> > This shrinks register access over RSB bus to one write per voltage
> > change (down from 4 or so).
> > 
> > Signed-off-by: Ondrej Jirman <megi@xff.cz>
> > ---
> >  drivers/mfd/axp20x.c | 28 +++++++++++++++++++++++++++-
> >  1 file changed, 27 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
> > index 0d0d40972eb8..2ea409029d2f 100644
> > --- a/drivers/mfd/axp20x.c
> > +++ b/drivers/mfd/axp20x.c
> > @@ -172,6 +172,18 @@ static const struct regmap_range axp288_volatile_ranges[] = {
> >  	regmap_reg_range(AXP20X_FG_RES, AXP288_FG_CC_CAP_REG),
> >  };
> >  
> > +static const struct regmap_range axp803_volatile_ranges[] = {
> > +	regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP288_POWER_REASON),
> > +	regmap_reg_range(AXP288_BC_GLOBAL, AXP288_BC_GLOBAL),
> > +	regmap_reg_range(AXP288_BC_DET_STAT, AXP20X_VBUS_IPSOUT_MGMT),
> > +	regmap_reg_range(AXP20X_CHRG_BAK_CTRL, AXP20X_CHRG_BAK_CTRL),
> > +	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L),
> > +	regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL),
> > +	regmap_reg_range(AXP20X_GPIO1_CTRL, AXP22X_GPIO_STATE),
> > +	regmap_reg_range(AXP288_RT_BATT_V_H, AXP288_RT_BATT_V_L),
> > +	regmap_reg_range(AXP20X_FG_RES, AXP288_FG_CC_CAP_REG),
> > +};
> > +
> >  static const struct regmap_access_table axp288_writeable_table = {
> >  	.yes_ranges	= axp288_writeable_ranges,
> >  	.n_yes_ranges	= ARRAY_SIZE(axp288_writeable_ranges),
> > @@ -182,6 +194,11 @@ static const struct regmap_access_table axp288_volatile_table = {
> >  	.n_yes_ranges	= ARRAY_SIZE(axp288_volatile_ranges),
> >  };
> >  
> > +static const struct regmap_access_table axp803_volatile_table = {
> > +	.yes_ranges	= axp803_volatile_ranges,
> > +	.n_yes_ranges	= ARRAY_SIZE(axp803_volatile_ranges),
> > +};
> > +
> >  static const struct regmap_range axp806_writeable_ranges[] = {
> >  	regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_DATACACHE(3)),
> >  	regmap_reg_range(AXP806_PWR_OUT_CTRL1, AXP806_CLDO3_V_CTRL),
> > @@ -456,6 +473,15 @@ static const struct regmap_config axp22x_regmap_config = {
> >  	.cache_type	= REGCACHE_MAPLE,
> >  };
> >  
> > +static const struct regmap_config axp803_regmap_config = {
> > +	.reg_bits	= 8,
> > +	.val_bits	= 8,
> > +	.wr_table	= &axp288_writeable_table,
> > +	.volatile_table	= &axp803_volatile_table,
> > +	.max_register	= AXP288_FG_TUNE5,
> > +	.cache_type	= REGCACHE_MAPLE,
> > +};
> > +
> >  static const struct regmap_config axp288_regmap_config = {
> >  	.reg_bits	= 8,
> >  	.val_bits	= 8,
> > @@ -1368,7 +1394,7 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
> >  	case AXP803_ID:
> >  		axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
> >  		axp20x->cells = axp803_cells;
> > -		axp20x->regmap_cfg = &axp288_regmap_config;
> > +		axp20x->regmap_cfg = &axp803_regmap_config;
> >  		axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;
> >  		break;
> >  	case AXP806_ID:
> > 
> 
> 
> 
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] mfd: axp20x: Change volatile ranges on axp803
  2026-03-21  6:25 ` Jernej Škrabec
  2026-03-21 18:26   ` Ondřej Jirman
@ 2026-04-21  5:06   ` Icenowy Zheng
  2026-04-21  5:10     ` Icenowy Zheng
  2026-04-21  5:19     ` Icenowy Zheng
  1 sibling, 2 replies; 7+ messages in thread
From: Icenowy Zheng @ 2026-04-21  5:06 UTC (permalink / raw)
  To: Jernej �0�7krabec, linux-sunxi,
	Ond�0�0ej Jirman
  Cc: linux-kernel, Lee Jones, Chen-Yu Tsai

在 2026-03-21六的 07:25 +0100,Jernej Škrabec写道:
> Dne nedelja, 15. marec 2026 ob 13:49:31 Srednjeevropski standardni
> čas je Ondřej Jirman napisal(a):
> > From: Ondrej Jirman <megi@xff.cz>
> > 
> > Regulator control registers can be cached. They don't update by
> > themselves. Enable cache on them, to speed up voltage changes,
> > particularly DCDC2 which needs to be handled quickly due to being
> > used
> > for CPUX cores and is changed very frequently by some cpufreq
> > schedulers.
> 
> That's not really the case, DCDC2-DCDC6 registers have DVM finished
> status
> bit, which is volatile and it is right to have them in volatile
> range.
> However, it is true that other registers are non-volatile, so that
> range can
> be considerably shrinked. It seems that AXP288 have same register
> layout
> but I can't say for sure (I only found datasheet for AXP288C), so
> it's best
> to leave it alone and apply changes only to AXP803. 

I have AXP288 datasheet, and register map looks the same with AXP288C.

BTW I think AXP288/288C/803/813(PMIC part) is the same die -- they have
the same "IC type no" value of 0b010001, and their difference could be
explained as package difference -- AXP803 doesn't wire AXP813's DCDC7
and wire SWIN to DCDC1 out, and AXP288 doesn't wire AXP813's DCDC3. (As
of RSB, all AXP PMICs boot at I2C mode by default, and the main SoC
switches it to RSB when it's needed; AXP288 is paired with non-
Allwinner SoCs (Intel ones) so it just doesn't advertise RSB.)

Thanks,
Icenowy

> 
> Best regards,
> Jernej
> 
> > 
> > This shrinks register access over RSB bus to one write per voltage
> > change (down from 4 or so).
> > 
> > Signed-off-by: Ondrej Jirman <megi@xff.cz>
> > ---
> >  drivers/mfd/axp20x.c | 28 +++++++++++++++++++++++++++-
> >  1 file changed, 27 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
> > index 0d0d40972eb8..2ea409029d2f 100644
> > --- a/drivers/mfd/axp20x.c
> > +++ b/drivers/mfd/axp20x.c
> > @@ -172,6 +172,18 @@ static const struct regmap_range
> > axp288_volatile_ranges[] = {
> >  	regmap_reg_range(AXP20X_FG_RES, AXP288_FG_CC_CAP_REG),
> >  };
> >  
> > +static const struct regmap_range axp803_volatile_ranges[] = {
> > +	regmap_reg_range(AXP20X_PWR_INPUT_STATUS,
> > AXP288_POWER_REASON),
> > +	regmap_reg_range(AXP288_BC_GLOBAL, AXP288_BC_GLOBAL),
> > +	regmap_reg_range(AXP288_BC_DET_STAT,
> > AXP20X_VBUS_IPSOUT_MGMT),
> > +	regmap_reg_range(AXP20X_CHRG_BAK_CTRL,
> > AXP20X_CHRG_BAK_CTRL),
> > +	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L),
> > +	regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL),
> > +	regmap_reg_range(AXP20X_GPIO1_CTRL, AXP22X_GPIO_STATE),
> > +	regmap_reg_range(AXP288_RT_BATT_V_H, AXP288_RT_BATT_V_L),
> > +	regmap_reg_range(AXP20X_FG_RES, AXP288_FG_CC_CAP_REG),
> > +};
> > +
> >  static const struct regmap_access_table axp288_writeable_table = {
> >  	.yes_ranges	= axp288_writeable_ranges,
> >  	.n_yes_ranges	= ARRAY_SIZE(axp288_writeable_ranges),
> > @@ -182,6 +194,11 @@ static const struct regmap_access_table
> > axp288_volatile_table = {
> >  	.n_yes_ranges	= ARRAY_SIZE(axp288_volatile_ranges),
> >  };
> >  
> > +static const struct regmap_access_table axp803_volatile_table = {
> > +	.yes_ranges	= axp803_volatile_ranges,
> > +	.n_yes_ranges	= ARRAY_SIZE(axp803_volatile_ranges),
> > +};
> > +
> >  static const struct regmap_range axp806_writeable_ranges[] = {
> >  	regmap_reg_range(AXP20X_DATACACHE(0),
> > AXP20X_DATACACHE(3)),
> >  	regmap_reg_range(AXP806_PWR_OUT_CTRL1,
> > AXP806_CLDO3_V_CTRL),
> > @@ -456,6 +473,15 @@ static const struct regmap_config
> > axp22x_regmap_config = {
> >  	.cache_type	= REGCACHE_MAPLE,
> >  };
> >  
> > +static const struct regmap_config axp803_regmap_config = {
> > +	.reg_bits	= 8,
> > +	.val_bits	= 8,
> > +	.wr_table	= &axp288_writeable_table,
> > +	.volatile_table	= &axp803_volatile_table,
> > +	.max_register	= AXP288_FG_TUNE5,
> > +	.cache_type	= REGCACHE_MAPLE,
> > +};
> > +
> >  static const struct regmap_config axp288_regmap_config = {
> >  	.reg_bits	= 8,
> >  	.val_bits	= 8,
> > @@ -1368,7 +1394,7 @@ int axp20x_match_device(struct axp20x_dev
> > *axp20x)
> >  	case AXP803_ID:
> >  		axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
> >  		axp20x->cells = axp803_cells;
> > -		axp20x->regmap_cfg = &axp288_regmap_config;
> > +		axp20x->regmap_cfg = &axp803_regmap_config;
> >  		axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;
> >  		break;
> >  	case AXP806_ID:
> > 
> 
> 
> 
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] mfd: axp20x: Change volatile ranges on axp803
  2026-04-21  5:06   ` Icenowy Zheng
@ 2026-04-21  5:10     ` Icenowy Zheng
  2026-04-21  5:19     ` Icenowy Zheng
  1 sibling, 0 replies; 7+ messages in thread
From: Icenowy Zheng @ 2026-04-21  5:10 UTC (permalink / raw)
  To: Jernej �0�7krabec, linux-sunxi,
	Ond�0�0ej Jirman
  Cc: linux-kernel, Lee Jones, Chen-Yu Tsai

在 2026-04-21二的 13:06 +0800,Icenowy Zheng写道:
> 在 2026-03-21六的 07:25 +0100,Jernej Škrabec写道:
> > Dne nedelja, 15. marec 2026 ob 13:49:31 Srednjeevropski standardni
> > čas je Ondřej Jirman napisal(a):
> > > From: Ondrej Jirman <megi@xff.cz>
> > > 
> > > Regulator control registers can be cached. They don't update by
> > > themselves. Enable cache on them, to speed up voltage changes,
> > > particularly DCDC2 which needs to be handled quickly due to being
> > > used
> > > for CPUX cores and is changed very frequently by some cpufreq
> > > schedulers.
> > 
> > That's not really the case, DCDC2-DCDC6 registers have DVM finished
> > status
> > bit, which is volatile and it is right to have them in volatile
> > range.
> > However, it is true that other registers are non-volatile, so that
> > range can
> > be considerably shrinked. It seems that AXP288 have same register
> > layout
> > but I can't say for sure (I only found datasheet for AXP288C), so
> > it's best
> > to leave it alone and apply changes only to AXP803. 
> 
> I have AXP288 datasheet, and register map looks the same with
> AXP288C.
> 
> BTW I think AXP288/288C/803/813(PMIC part) is the same die -- they
> have
> the same "IC type no" value of 0b010001, and their difference could
> be
> explained as package difference -- AXP803 doesn't wire AXP813's DCDC7
> and wire SWIN to DCDC1 out, and AXP288 doesn't wire AXP813's DCDC3.
> (As
> of RSB, all AXP PMICs boot at I2C mode by default, and the main SoC
> switches it to RSB when it's needed; AXP288 is paired with non-
> Allwinner SoCs (Intel ones) so it just doesn't advertise RSB.)

P.S. my "AXP813 datasheet v1.0-20140901.pdf" file has a PDF title of
"AXP288".

And I think AXP813 has the most functionality because it's a BGA chip.
(Weirdly the switch bit is "reserved" on the datasheet despite SWIN and
SWOUT pins are there -- but the kernel driver has the switch defined
and it matches AXP803 DC1SW).

Thanks,
Icenowy

> 
> Thanks,
> Icenowy
> 
> > 
> > Best regards,
> > Jernej
> > 
> > > 
> > > This shrinks register access over RSB bus to one write per
> > > voltage
> > > change (down from 4 or so).
> > > 
> > > Signed-off-by: Ondrej Jirman <megi@xff.cz>
> > > ---
> > >  drivers/mfd/axp20x.c | 28 +++++++++++++++++++++++++++-
> > >  1 file changed, 27 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
> > > index 0d0d40972eb8..2ea409029d2f 100644
> > > --- a/drivers/mfd/axp20x.c
> > > +++ b/drivers/mfd/axp20x.c
> > > @@ -172,6 +172,18 @@ static const struct regmap_range
> > > axp288_volatile_ranges[] = {
> > >  	regmap_reg_range(AXP20X_FG_RES, AXP288_FG_CC_CAP_REG),
> > >  };
> > >  
> > > +static const struct regmap_range axp803_volatile_ranges[] = {
> > > +	regmap_reg_range(AXP20X_PWR_INPUT_STATUS,
> > > AXP288_POWER_REASON),
> > > +	regmap_reg_range(AXP288_BC_GLOBAL, AXP288_BC_GLOBAL),
> > > +	regmap_reg_range(AXP288_BC_DET_STAT,
> > > AXP20X_VBUS_IPSOUT_MGMT),
> > > +	regmap_reg_range(AXP20X_CHRG_BAK_CTRL,
> > > AXP20X_CHRG_BAK_CTRL),
> > > +	regmap_reg_range(AXP20X_IRQ1_EN,
> > > AXP20X_IPSOUT_V_HIGH_L),
> > > +	regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL),
> > > +	regmap_reg_range(AXP20X_GPIO1_CTRL, AXP22X_GPIO_STATE),
> > > +	regmap_reg_range(AXP288_RT_BATT_V_H,
> > > AXP288_RT_BATT_V_L),
> > > +	regmap_reg_range(AXP20X_FG_RES, AXP288_FG_CC_CAP_REG),
> > > +};
> > > +
> > >  static const struct regmap_access_table axp288_writeable_table =
> > > {
> > >  	.yes_ranges	= axp288_writeable_ranges,
> > >  	.n_yes_ranges	= ARRAY_SIZE(axp288_writeable_ranges),
> > > @@ -182,6 +194,11 @@ static const struct regmap_access_table
> > > axp288_volatile_table = {
> > >  	.n_yes_ranges	= ARRAY_SIZE(axp288_volatile_ranges),
> > >  };
> > >  
> > > +static const struct regmap_access_table axp803_volatile_table =
> > > {
> > > +	.yes_ranges	= axp803_volatile_ranges,
> > > +	.n_yes_ranges	= ARRAY_SIZE(axp803_volatile_ranges),
> > > +};
> > > +
> > >  static const struct regmap_range axp806_writeable_ranges[] = {
> > >  	regmap_reg_range(AXP20X_DATACACHE(0),
> > > AXP20X_DATACACHE(3)),
> > >  	regmap_reg_range(AXP806_PWR_OUT_CTRL1,
> > > AXP806_CLDO3_V_CTRL),
> > > @@ -456,6 +473,15 @@ static const struct regmap_config
> > > axp22x_regmap_config = {
> > >  	.cache_type	= REGCACHE_MAPLE,
> > >  };
> > >  
> > > +static const struct regmap_config axp803_regmap_config = {
> > > +	.reg_bits	= 8,
> > > +	.val_bits	= 8,
> > > +	.wr_table	= &axp288_writeable_table,
> > > +	.volatile_table	= &axp803_volatile_table,
> > > +	.max_register	= AXP288_FG_TUNE5,
> > > +	.cache_type	= REGCACHE_MAPLE,
> > > +};
> > > +
> > >  static const struct regmap_config axp288_regmap_config = {
> > >  	.reg_bits	= 8,
> > >  	.val_bits	= 8,
> > > @@ -1368,7 +1394,7 @@ int axp20x_match_device(struct axp20x_dev
> > > *axp20x)
> > >  	case AXP803_ID:
> > >  		axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
> > >  		axp20x->cells = axp803_cells;
> > > -		axp20x->regmap_cfg = &axp288_regmap_config;
> > > +		axp20x->regmap_cfg = &axp803_regmap_config;
> > >  		axp20x->regmap_irq_chip =
> > > &axp803_regmap_irq_chip;
> > >  		break;
> > >  	case AXP806_ID:
> > > 
> > 
> > 
> > 
> > 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] mfd: axp20x: Change volatile ranges on axp803
  2026-04-21  5:06   ` Icenowy Zheng
  2026-04-21  5:10     ` Icenowy Zheng
@ 2026-04-21  5:19     ` Icenowy Zheng
  1 sibling, 0 replies; 7+ messages in thread
From: Icenowy Zheng @ 2026-04-21  5:19 UTC (permalink / raw)
  To: Jernej �0�7krabec, linux-sunxi,
	Ond�0�0ej Jirman
  Cc: linux-kernel, Lee Jones, Chen-Yu Tsai

在 2026-04-21二的 13:06 +0800,Icenowy Zheng写道:
> 在 2026-03-21六的 07:25 +0100,Jernej Škrabec写道:
> > Dne nedelja, 15. marec 2026 ob 13:49:31 Srednjeevropski standardni
> > čas je Ondřej Jirman napisal(a):
> > > From: Ondrej Jirman <megi@xff.cz>
> > > 
> > > Regulator control registers can be cached. They don't update by
> > > themselves. Enable cache on them, to speed up voltage changes,
> > > particularly DCDC2 which needs to be handled quickly due to being
> > > used
> > > for CPUX cores and is changed very frequently by some cpufreq
> > > schedulers.
> > 
> > That's not really the case, DCDC2-DCDC6 registers have DVM finished
> > status
> > bit, which is volatile and it is right to have them in volatile
> > range.
> > However, it is true that other registers are non-volatile, so that
> > range can
> > be considerably shrinked. It seems that AXP288 have same register
> > layout
> > but I can't say for sure (I only found datasheet for AXP288C), so
> > it's best
> > to leave it alone and apply changes only to AXP803. 
> 
> I have AXP288 datasheet, and register map looks the same with
> AXP288C.
> 
> BTW I think AXP288/288C/803/813(PMIC part) is the same die -- they
> have
> the same "IC type no" value of 0b010001, and their difference could
> be
> explained as package difference -- AXP803 doesn't wire AXP813's DCDC7
> and wire SWIN to DCDC1 out, and AXP288 doesn't wire AXP813's DCDC3.
> (As
> of RSB, all AXP PMICs boot at I2C mode by default, and the main SoC
> switches it to RSB when it's needed; AXP288 is paired with non-
> Allwinner SoCs (Intel ones) so it just doesn't advertise RSB.)

Forgot to mention that AXP8x3 also have dedicated VBUS and ACIN inputs
while AXP288 has only VBUS -- but in the AXP803 datasheet, VBUS and
ACIN shorted together is a valid use case and can be detected by the
PMIC, and when they're shorted the VBUS current limit is active (the
ACIN current limit is ignored); so for AXP288 it could be explained
that the ACIN is shorted with VBUS in the package.

Thanks,
Icenowy

> 
> Thanks,
> Icenowy
> 
> > 
> > Best regards,
> > Jernej
> > 
> > > 
> > > This shrinks register access over RSB bus to one write per
> > > voltage
> > > change (down from 4 or so).
> > > 
> > > Signed-off-by: Ondrej Jirman <megi@xff.cz>
> > > ---
> > >  drivers/mfd/axp20x.c | 28 +++++++++++++++++++++++++++-
> > >  1 file changed, 27 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
> > > index 0d0d40972eb8..2ea409029d2f 100644
> > > --- a/drivers/mfd/axp20x.c
> > > +++ b/drivers/mfd/axp20x.c
> > > @@ -172,6 +172,18 @@ static const struct regmap_range
> > > axp288_volatile_ranges[] = {
> > >  	regmap_reg_range(AXP20X_FG_RES, AXP288_FG_CC_CAP_REG),
> > >  };
> > >  
> > > +static const struct regmap_range axp803_volatile_ranges[] = {
> > > +	regmap_reg_range(AXP20X_PWR_INPUT_STATUS,
> > > AXP288_POWER_REASON),
> > > +	regmap_reg_range(AXP288_BC_GLOBAL, AXP288_BC_GLOBAL),
> > > +	regmap_reg_range(AXP288_BC_DET_STAT,
> > > AXP20X_VBUS_IPSOUT_MGMT),
> > > +	regmap_reg_range(AXP20X_CHRG_BAK_CTRL,
> > > AXP20X_CHRG_BAK_CTRL),
> > > +	regmap_reg_range(AXP20X_IRQ1_EN,
> > > AXP20X_IPSOUT_V_HIGH_L),
> > > +	regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL),
> > > +	regmap_reg_range(AXP20X_GPIO1_CTRL, AXP22X_GPIO_STATE),
> > > +	regmap_reg_range(AXP288_RT_BATT_V_H,
> > > AXP288_RT_BATT_V_L),
> > > +	regmap_reg_range(AXP20X_FG_RES, AXP288_FG_CC_CAP_REG),
> > > +};
> > > +
> > >  static const struct regmap_access_table axp288_writeable_table =
> > > {
> > >  	.yes_ranges	= axp288_writeable_ranges,
> > >  	.n_yes_ranges	= ARRAY_SIZE(axp288_writeable_ranges),
> > > @@ -182,6 +194,11 @@ static const struct regmap_access_table
> > > axp288_volatile_table = {
> > >  	.n_yes_ranges	= ARRAY_SIZE(axp288_volatile_ranges),
> > >  };
> > >  
> > > +static const struct regmap_access_table axp803_volatile_table =
> > > {
> > > +	.yes_ranges	= axp803_volatile_ranges,
> > > +	.n_yes_ranges	= ARRAY_SIZE(axp803_volatile_ranges),
> > > +};
> > > +
> > >  static const struct regmap_range axp806_writeable_ranges[] = {
> > >  	regmap_reg_range(AXP20X_DATACACHE(0),
> > > AXP20X_DATACACHE(3)),
> > >  	regmap_reg_range(AXP806_PWR_OUT_CTRL1,
> > > AXP806_CLDO3_V_CTRL),
> > > @@ -456,6 +473,15 @@ static const struct regmap_config
> > > axp22x_regmap_config = {
> > >  	.cache_type	= REGCACHE_MAPLE,
> > >  };
> > >  
> > > +static const struct regmap_config axp803_regmap_config = {
> > > +	.reg_bits	= 8,
> > > +	.val_bits	= 8,
> > > +	.wr_table	= &axp288_writeable_table,
> > > +	.volatile_table	= &axp803_volatile_table,
> > > +	.max_register	= AXP288_FG_TUNE5,
> > > +	.cache_type	= REGCACHE_MAPLE,
> > > +};
> > > +
> > >  static const struct regmap_config axp288_regmap_config = {
> > >  	.reg_bits	= 8,
> > >  	.val_bits	= 8,
> > > @@ -1368,7 +1394,7 @@ int axp20x_match_device(struct axp20x_dev
> > > *axp20x)
> > >  	case AXP803_ID:
> > >  		axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
> > >  		axp20x->cells = axp803_cells;
> > > -		axp20x->regmap_cfg = &axp288_regmap_config;
> > > +		axp20x->regmap_cfg = &axp803_regmap_config;
> > >  		axp20x->regmap_irq_chip =
> > > &axp803_regmap_irq_chip;
> > >  		break;
> > >  	case AXP806_ID:
> > > 
> > 
> > 
> > 
> > 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] mfd: axp20x: Change volatile ranges on axp803
  2026-03-21 18:26   ` Ondřej Jirman
@ 2026-05-09 13:00     ` Jernej Škrabec
  0 siblings, 0 replies; 7+ messages in thread
From: Jernej Škrabec @ 2026-05-09 13:00 UTC (permalink / raw)
  To: Ondřej Jirman <megi@xff.cz>, Jernej Škrabec,
	linux-sunxi, linux-kernel, Lee Jones, Chen-Yu Tsai

Dne sobota, 21. marec 2026 ob 19:26:43 Srednjeevropski poletni čas je Ondřej Jirman napisal(a):
> On Sat, Mar 21, 2026 at 07:25:49AM +0100, Jernej Škrabec wrote:
> > Dne nedelja, 15. marec 2026 ob 13:49:31 Srednjeevropski standardni čas je Ondřej Jirman napisal(a):
> > > From: Ondrej Jirman <megi@xff.cz>
> > > 
> > > Regulator control registers can be cached. They don't update by
> > > themselves. Enable cache on them, to speed up voltage changes,
> > > particularly DCDC2 which needs to be handled quickly due to being used
> > > for CPUX cores and is changed very frequently by some cpufreq schedulers.
> > 
> > That's not really the case, DCDC2-DCDC6 registers have DVM finished status
> > bit, which is volatile and it is right to have them in volatile range.
> > However, it is true that other registers are non-volatile, so that range can
> > be considerably shrinked. It seems that AXP288 have same register layout
> > but I can't say for sure (I only found datasheet for AXP288C), so it's best
> > to leave it alone and apply changes only to AXP803. 
> 
> While true, it's not used by any kernel drivers, and having the whole register
> marked volatile for a single unused bit is contributing 10s of % of permanent
> CPU load just from cpufreq DVFS operations alone when using schedutil governor,
> which is doing DVFS hundred or more times per second.
> 
> If someone will want to use this bit in the regulator driver, they can use eg.
> regmap_read_bypassed() to access the bit, while keepig the other parts of
> regulator implementation performant.

This sounds like a good compromise.

> 
> But I guess it may deserve a comment in the code.

For sure.

BR Jernej

> 
> Kind regards,
> 	o.
> 
> > Best regards,
> > Jernej
> > 
> > > 
> > > This shrinks register access over RSB bus to one write per voltage
> > > change (down from 4 or so).
> > > 
> > > Signed-off-by: Ondrej Jirman <megi@xff.cz>
> > > ---
> > >  drivers/mfd/axp20x.c | 28 +++++++++++++++++++++++++++-
> > >  1 file changed, 27 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
> > > index 0d0d40972eb8..2ea409029d2f 100644
> > > --- a/drivers/mfd/axp20x.c
> > > +++ b/drivers/mfd/axp20x.c
> > > @@ -172,6 +172,18 @@ static const struct regmap_range axp288_volatile_ranges[] = {
> > >  	regmap_reg_range(AXP20X_FG_RES, AXP288_FG_CC_CAP_REG),
> > >  };
> > >  
> > > +static const struct regmap_range axp803_volatile_ranges[] = {
> > > +	regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP288_POWER_REASON),
> > > +	regmap_reg_range(AXP288_BC_GLOBAL, AXP288_BC_GLOBAL),
> > > +	regmap_reg_range(AXP288_BC_DET_STAT, AXP20X_VBUS_IPSOUT_MGMT),
> > > +	regmap_reg_range(AXP20X_CHRG_BAK_CTRL, AXP20X_CHRG_BAK_CTRL),
> > > +	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L),
> > > +	regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL),
> > > +	regmap_reg_range(AXP20X_GPIO1_CTRL, AXP22X_GPIO_STATE),
> > > +	regmap_reg_range(AXP288_RT_BATT_V_H, AXP288_RT_BATT_V_L),
> > > +	regmap_reg_range(AXP20X_FG_RES, AXP288_FG_CC_CAP_REG),
> > > +};
> > > +
> > >  static const struct regmap_access_table axp288_writeable_table = {
> > >  	.yes_ranges	= axp288_writeable_ranges,
> > >  	.n_yes_ranges	= ARRAY_SIZE(axp288_writeable_ranges),
> > > @@ -182,6 +194,11 @@ static const struct regmap_access_table axp288_volatile_table = {
> > >  	.n_yes_ranges	= ARRAY_SIZE(axp288_volatile_ranges),
> > >  };
> > >  
> > > +static const struct regmap_access_table axp803_volatile_table = {
> > > +	.yes_ranges	= axp803_volatile_ranges,
> > > +	.n_yes_ranges	= ARRAY_SIZE(axp803_volatile_ranges),
> > > +};
> > > +
> > >  static const struct regmap_range axp806_writeable_ranges[] = {
> > >  	regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_DATACACHE(3)),
> > >  	regmap_reg_range(AXP806_PWR_OUT_CTRL1, AXP806_CLDO3_V_CTRL),
> > > @@ -456,6 +473,15 @@ static const struct regmap_config axp22x_regmap_config = {
> > >  	.cache_type	= REGCACHE_MAPLE,
> > >  };
> > >  
> > > +static const struct regmap_config axp803_regmap_config = {
> > > +	.reg_bits	= 8,
> > > +	.val_bits	= 8,
> > > +	.wr_table	= &axp288_writeable_table,
> > > +	.volatile_table	= &axp803_volatile_table,
> > > +	.max_register	= AXP288_FG_TUNE5,
> > > +	.cache_type	= REGCACHE_MAPLE,
> > > +};
> > > +
> > >  static const struct regmap_config axp288_regmap_config = {
> > >  	.reg_bits	= 8,
> > >  	.val_bits	= 8,
> > > @@ -1368,7 +1394,7 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
> > >  	case AXP803_ID:
> > >  		axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
> > >  		axp20x->cells = axp803_cells;
> > > -		axp20x->regmap_cfg = &axp288_regmap_config;
> > > +		axp20x->regmap_cfg = &axp803_regmap_config;
> > >  		axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;
> > >  		break;
> > >  	case AXP806_ID:
> > > 
> > 
> > 
> > 
> > 
> 





^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-05-09 13:00 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-15 12:49 [PATCH] mfd: axp20x: Change volatile ranges on axp803 Ondřej Jirman
2026-03-21  6:25 ` Jernej Škrabec
2026-03-21 18:26   ` Ondřej Jirman
2026-05-09 13:00     ` Jernej Škrabec
2026-04-21  5:06   ` Icenowy Zheng
2026-04-21  5:10     ` Icenowy Zheng
2026-04-21  5:19     ` Icenowy Zheng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox