diff mbox series

[3/6] pinctrl: sunxi: Support the 2.5V I/O bias mode

Message ID 20220626021148.56740-4-samuel@sholland.org (mailing list archive)
State New, archived
Headers show
Series pinctrl: sunxi: Allwinner D1/D1s support | expand

Commit Message

Samuel Holland June 26, 2022, 2:11 a.m. UTC
H616 and newer SoCs feature a 2.5V I/O bias mode in addition to the
1.8V and 3.3V modes. This mode is entered by selecting the 3.3V level
and disabling the "withstand function".

H616 supports this capability on its main PIO only. A100 supports this
capability on both its PIO and R-PIO.

Signed-off-by: Samuel Holland <samuel@sholland.org>
---

 drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c |  1 +
 drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c   |  2 +-
 drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c   |  2 +-
 drivers/pinctrl/sunxi/pinctrl-sunxi.c         | 10 ++++++++++
 drivers/pinctrl/sunxi/pinctrl-sunxi.h         |  7 +++++++
 5 files changed, 20 insertions(+), 2 deletions(-)

Comments

Jernej Škrabec June 27, 2022, 8:43 p.m. UTC | #1
Dne nedelja, 26. junij 2022 ob 04:11:44 CEST je Samuel Holland napisal(a):
> H616 and newer SoCs feature a 2.5V I/O bias mode in addition to the
> 1.8V and 3.3V modes. This mode is entered by selecting the 3.3V level
> and disabling the "withstand function".
> 
> H616 supports this capability on its main PIO only. A100 supports this
> capability on both its PIO and R-PIO.
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>
> ---
> 
>  drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c |  1 +
>  drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c   |  2 +-
>  drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c   |  2 +-
>  drivers/pinctrl/sunxi/pinctrl-sunxi.c         | 10 ++++++++++
>  drivers/pinctrl/sunxi/pinctrl-sunxi.h         |  7 +++++++
>  5 files changed, 20 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
> b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c index
> 21054fcacd34..afc1f5df7545 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
> @@ -82,6 +82,7 @@ static const struct sunxi_pinctrl_desc a100_r_pinctrl_data
> = { .npins = ARRAY_SIZE(a100_r_pins),
>  	.pin_base = PL_BASE,
>  	.irq_banks = 1,
> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
>  };
> 
>  static int a100_r_pinctrl_probe(struct platform_device *pdev)
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
> b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c index
> e69f6da40dc0..f682e0e4244d 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
> @@ -684,7 +684,7 @@ static const struct sunxi_pinctrl_desc a100_pinctrl_data
> = { .npins = ARRAY_SIZE(a100_pins),
>  	.irq_banks = 7,
>  	.irq_bank_map = a100_irq_bank_map,
> -	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
>  };
> 
>  static int a100_pinctrl_probe(struct platform_device *pdev)
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
> b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c index
> 152b71226a80..d6ca720ee8d8 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
> @@ -525,7 +525,7 @@ static const struct sunxi_pinctrl_desc h616_pinctrl_data
> = { .irq_banks = ARRAY_SIZE(h616_irq_bank_map),
>  	.irq_bank_map = h616_irq_bank_map,
>  	.irq_read_needs_mux = true,
> -	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
>  };
> 
>  static int h616_pinctrl_probe(struct platform_device *pdev)
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 3c5e71359ca8..eb3d595f816a
> 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> @@ -662,6 +662,16 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct
> sunxi_pinctrl *pctl, reg &= ~IO_BIAS_MASK;
>  		writel(reg | val, pctl->membase + 
sunxi_grp_config_reg(pin));
>  		return 0;
> +	case BIAS_VOLTAGE_PIO_POW_MODE_CTL:
> +		val = uV > 1800000 && uV <= 2500000 ? BIT(bank) : 0;
> +
> +		raw_spin_lock_irqsave(&pctl->lock, flags);
> +		reg = readl(pctl->membase + PIO_POW_MOD_CTL_REG);
> +		reg &= ~BIT(bank);
> +		writel(reg | val, pctl->membase + PIO_POW_MOD_CTL_REG);
> +		raw_spin_unlock_irqrestore(&pctl->lock, flags);
> +
> +		fallthrough;

Would this set bit 12 as needed? According to documentation, it's a bit 
special case, since it covers VCC-IO, port F and port H, at least according to 
documentation. I guess BIAS_VOLTAGE_PIO_POW_MODE_SEL has same issue.

Best regards,
Jernej

>  	case BIAS_VOLTAGE_PIO_POW_MODE_SEL:
>  		val = uV <= 1800000 ? 1 : 0;
> 
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> b/drivers/pinctrl/sunxi/pinctrl-sunxi.h index a32bb5bcb754..0f1aab58650c
> 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> @@ -98,6 +98,7 @@
>  #define PINCTRL_SUN8I_V3S	BIT(10)
> 
>  #define PIO_POW_MOD_SEL_REG	0x340
> +#define PIO_POW_MOD_CTL_REG	0x344
> 
>  enum sunxi_desc_bias_voltage {
>  	BIAS_VOLTAGE_NONE,
> @@ -111,6 +112,12 @@ enum sunxi_desc_bias_voltage {
>  	 * register, as seen on H6 SoC, for example.
>  	 */
>  	BIAS_VOLTAGE_PIO_POW_MODE_SEL,
> +	/*
> +	 * Bias voltage is set through PIO_POW_MOD_SEL_REG
> +	 * and PIO_POW_MOD_CTL_REG register, as seen on
> +	 * A100 and D1 SoC, for example.
> +	 */
> +	BIAS_VOLTAGE_PIO_POW_MODE_CTL,
>  };
> 
>  struct sunxi_desc_function {
Samuel Holland June 28, 2022, 3:29 a.m. UTC | #2
On 6/27/22 3:43 PM, Jernej Škrabec wrote:
> Dne nedelja, 26. junij 2022 ob 04:11:44 CEST je Samuel Holland napisal(a):
>> H616 and newer SoCs feature a 2.5V I/O bias mode in addition to the
>> 1.8V and 3.3V modes. This mode is entered by selecting the 3.3V level
>> and disabling the "withstand function".
>>
>> H616 supports this capability on its main PIO only. A100 supports this
>> capability on both its PIO and R-PIO.
>>
>> Signed-off-by: Samuel Holland <samuel@sholland.org>
>> ---
>>
>>  drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c |  1 +
>>  drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c   |  2 +-
>>  drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c   |  2 +-
>>  drivers/pinctrl/sunxi/pinctrl-sunxi.c         | 10 ++++++++++
>>  drivers/pinctrl/sunxi/pinctrl-sunxi.h         |  7 +++++++
>>  5 files changed, 20 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
>> b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c index
>> 21054fcacd34..afc1f5df7545 100644
>> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
>> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
>> @@ -82,6 +82,7 @@ static const struct sunxi_pinctrl_desc a100_r_pinctrl_data
>> = { .npins = ARRAY_SIZE(a100_r_pins),
>>  	.pin_base = PL_BASE,
>>  	.irq_banks = 1,
>> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
>>  };
>>
>>  static int a100_r_pinctrl_probe(struct platform_device *pdev)
>> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
>> b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c index
>> e69f6da40dc0..f682e0e4244d 100644
>> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
>> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
>> @@ -684,7 +684,7 @@ static const struct sunxi_pinctrl_desc a100_pinctrl_data
>> = { .npins = ARRAY_SIZE(a100_pins),
>>  	.irq_banks = 7,
>>  	.irq_bank_map = a100_irq_bank_map,
>> -	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
>> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
>>  };
>>
>>  static int a100_pinctrl_probe(struct platform_device *pdev)
>> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
>> b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c index
>> 152b71226a80..d6ca720ee8d8 100644
>> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
>> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
>> @@ -525,7 +525,7 @@ static const struct sunxi_pinctrl_desc h616_pinctrl_data
>> = { .irq_banks = ARRAY_SIZE(h616_irq_bank_map),
>>  	.irq_bank_map = h616_irq_bank_map,
>>  	.irq_read_needs_mux = true,
>> -	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
>> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
>>  };
>>
>>  static int h616_pinctrl_probe(struct platform_device *pdev)
>> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
>> b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 3c5e71359ca8..eb3d595f816a
>> 100644
>> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
>> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
>> @@ -662,6 +662,16 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct
>> sunxi_pinctrl *pctl, reg &= ~IO_BIAS_MASK;
>>  		writel(reg | val, pctl->membase + 
> sunxi_grp_config_reg(pin));
>>  		return 0;
>> +	case BIAS_VOLTAGE_PIO_POW_MODE_CTL:
>> +		val = uV > 1800000 && uV <= 2500000 ? BIT(bank) : 0;
>> +
>> +		raw_spin_lock_irqsave(&pctl->lock, flags);
>> +		reg = readl(pctl->membase + PIO_POW_MOD_CTL_REG);
>> +		reg &= ~BIT(bank);
>> +		writel(reg | val, pctl->membase + PIO_POW_MOD_CTL_REG);
>> +		raw_spin_unlock_irqrestore(&pctl->lock, flags);
>> +
>> +		fallthrough;
> 
> Would this set bit 12 as needed? According to documentation, it's a bit 
> special case, since it covers VCC-IO, port F and port H, at least according to 
> documentation. I guess BIAS_VOLTAGE_PIO_POW_MODE_SEL has same issue.

Right, it seems we would need some mask to tell us which ports are affected by
bit 12, and which have their own setting. The current code is unlikely to cause
any issue, though, because in practice VCC-IO is always 3.3 V.

Regards,
Samuel
Heiko Stübner July 1, 2022, 1:04 p.m. UTC | #3
Am Sonntag, 26. Juni 2022, 04:11:44 CEST schrieb Samuel Holland:
> H616 and newer SoCs feature a 2.5V I/O bias mode in addition to the
> 1.8V and 3.3V modes. This mode is entered by selecting the 3.3V level
> and disabling the "withstand function".
> 
> H616 supports this capability on its main PIO only. A100 supports this
> capability on both its PIO and R-PIO.
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>

On a D1-Nezha
Tested-by: Heiko Stuebner <heiko@sntech.de>
Jernej Škrabec July 2, 2022, 7:48 p.m. UTC | #4
Dne torek, 28. junij 2022 ob 05:29:51 CEST je Samuel Holland napisal(a):
> On 6/27/22 3:43 PM, Jernej Škrabec wrote:
> > Dne nedelja, 26. junij 2022 ob 04:11:44 CEST je Samuel Holland napisal(a):
> >> H616 and newer SoCs feature a 2.5V I/O bias mode in addition to the
> >> 1.8V and 3.3V modes. This mode is entered by selecting the 3.3V level
> >> and disabling the "withstand function".
> >> 
> >> H616 supports this capability on its main PIO only. A100 supports this
> >> capability on both its PIO and R-PIO.
> >> 
> >> Signed-off-by: Samuel Holland <samuel@sholland.org>
> >> ---
> >> 
> >>  drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c |  1 +
> >>  drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c   |  2 +-
> >>  drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c   |  2 +-
> >>  drivers/pinctrl/sunxi/pinctrl-sunxi.c         | 10 ++++++++++
> >>  drivers/pinctrl/sunxi/pinctrl-sunxi.h         |  7 +++++++
> >>  5 files changed, 20 insertions(+), 2 deletions(-)
> >> 
> >> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
> >> b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c index
> >> 21054fcacd34..afc1f5df7545 100644
> >> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
> >> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
> >> @@ -82,6 +82,7 @@ static const struct sunxi_pinctrl_desc
> >> a100_r_pinctrl_data = { .npins = ARRAY_SIZE(a100_r_pins),
> >> 
> >>  	.pin_base = PL_BASE,
> >>  	.irq_banks = 1,
> >> 
> >> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
> >> 
> >>  };
> >>  
> >>  static int a100_r_pinctrl_probe(struct platform_device *pdev)
> >> 
> >> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
> >> b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c index
> >> e69f6da40dc0..f682e0e4244d 100644
> >> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
> >> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
> >> @@ -684,7 +684,7 @@ static const struct sunxi_pinctrl_desc
> >> a100_pinctrl_data = { .npins = ARRAY_SIZE(a100_pins),
> >> 
> >>  	.irq_banks = 7,
> >>  	.irq_bank_map = a100_irq_bank_map,
> >> 
> >> -	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
> >> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
> >> 
> >>  };
> >>  
> >>  static int a100_pinctrl_probe(struct platform_device *pdev)
> >> 
> >> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
> >> b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c index
> >> 152b71226a80..d6ca720ee8d8 100644
> >> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
> >> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
> >> @@ -525,7 +525,7 @@ static const struct sunxi_pinctrl_desc
> >> h616_pinctrl_data = { .irq_banks = ARRAY_SIZE(h616_irq_bank_map),
> >> 
> >>  	.irq_bank_map = h616_irq_bank_map,
> >>  	.irq_read_needs_mux = true,
> >> 
> >> -	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
> >> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
> >> 
> >>  };
> >>  
> >>  static int h616_pinctrl_probe(struct platform_device *pdev)
> >> 
> >> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> >> b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 3c5e71359ca8..eb3d595f816a
> >> 100644
> >> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> >> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> >> @@ -662,6 +662,16 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct
> >> sunxi_pinctrl *pctl, reg &= ~IO_BIAS_MASK;
> >> 
> >>  		writel(reg | val, pctl->membase +
> > 
> > sunxi_grp_config_reg(pin));
> > 
> >>  		return 0;
> >> 
> >> +	case BIAS_VOLTAGE_PIO_POW_MODE_CTL:
> >> +		val = uV > 1800000 && uV <= 2500000 ? BIT(bank) : 0;
> >> +
> >> +		raw_spin_lock_irqsave(&pctl->lock, flags);
> >> +		reg = readl(pctl->membase + PIO_POW_MOD_CTL_REG);
> >> +		reg &= ~BIT(bank);
> >> +		writel(reg | val, pctl->membase + PIO_POW_MOD_CTL_REG);
> >> +		raw_spin_unlock_irqrestore(&pctl->lock, flags);
> >> +
> >> +		fallthrough;
> > 
> > Would this set bit 12 as needed? According to documentation, it's a bit
> > special case, since it covers VCC-IO, port F and port H, at least
> > according to documentation. I guess BIAS_VOLTAGE_PIO_POW_MODE_SEL has
> > same issue.
> Right, it seems we would need some mask to tell us which ports are affected
> by bit 12, and which have their own setting. The current code is unlikely
> to cause any issue, though, because in practice VCC-IO is always 3.3 V.

ok, it's good for now.

Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>

Best regards,
Jernej
diff mbox series

Patch

diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
index 21054fcacd34..afc1f5df7545 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
@@ -82,6 +82,7 @@  static const struct sunxi_pinctrl_desc a100_r_pinctrl_data = {
 	.npins = ARRAY_SIZE(a100_r_pins),
 	.pin_base = PL_BASE,
 	.irq_banks = 1,
+	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
 };
 
 static int a100_r_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
index e69f6da40dc0..f682e0e4244d 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
@@ -684,7 +684,7 @@  static const struct sunxi_pinctrl_desc a100_pinctrl_data = {
 	.npins = ARRAY_SIZE(a100_pins),
 	.irq_banks = 7,
 	.irq_bank_map = a100_irq_bank_map,
-	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
+	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
 };
 
 static int a100_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
index 152b71226a80..d6ca720ee8d8 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
@@ -525,7 +525,7 @@  static const struct sunxi_pinctrl_desc h616_pinctrl_data = {
 	.irq_banks = ARRAY_SIZE(h616_irq_bank_map),
 	.irq_bank_map = h616_irq_bank_map,
 	.irq_read_needs_mux = true,
-	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
+	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
 };
 
 static int h616_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 3c5e71359ca8..eb3d595f816a 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -662,6 +662,16 @@  static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
 		reg &= ~IO_BIAS_MASK;
 		writel(reg | val, pctl->membase + sunxi_grp_config_reg(pin));
 		return 0;
+	case BIAS_VOLTAGE_PIO_POW_MODE_CTL:
+		val = uV > 1800000 && uV <= 2500000 ? BIT(bank) : 0;
+
+		raw_spin_lock_irqsave(&pctl->lock, flags);
+		reg = readl(pctl->membase + PIO_POW_MOD_CTL_REG);
+		reg &= ~BIT(bank);
+		writel(reg | val, pctl->membase + PIO_POW_MOD_CTL_REG);
+		raw_spin_unlock_irqrestore(&pctl->lock, flags);
+
+		fallthrough;
 	case BIAS_VOLTAGE_PIO_POW_MODE_SEL:
 		val = uV <= 1800000 ? 1 : 0;
 
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index a32bb5bcb754..0f1aab58650c 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -98,6 +98,7 @@ 
 #define PINCTRL_SUN8I_V3S	BIT(10)
 
 #define PIO_POW_MOD_SEL_REG	0x340
+#define PIO_POW_MOD_CTL_REG	0x344
 
 enum sunxi_desc_bias_voltage {
 	BIAS_VOLTAGE_NONE,
@@ -111,6 +112,12 @@  enum sunxi_desc_bias_voltage {
 	 * register, as seen on H6 SoC, for example.
 	 */
 	BIAS_VOLTAGE_PIO_POW_MODE_SEL,
+	/*
+	 * Bias voltage is set through PIO_POW_MOD_SEL_REG
+	 * and PIO_POW_MOD_CTL_REG register, as seen on
+	 * A100 and D1 SoC, for example.
+	 */
+	BIAS_VOLTAGE_PIO_POW_MODE_CTL,
 };
 
 struct sunxi_desc_function {