diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs
index 33f22f676..214813a42 100644
--- a/embassy-stm32/src/gpio.rs
+++ b/embassy-stm32/src/gpio.rs
@@ -779,13 +779,6 @@ pub(crate) unsafe fn init(_cs: CriticalSection) {
     <crate::peripherals::AFIO as crate::rcc::SealedRccPeripheral>::enable_and_reset_with_cs(_cs);
 
     crate::_generated::init_gpio();
-
-    // Setting this bit is mandatory to use PG[15:2].
-    #[cfg(stm32u5)]
-    crate::pac::PWR.svmcr().modify(|w| {
-        w.set_io2sv(true);
-        w.set_io2vmen(true);
-    });
 }
 
 impl<'d> embedded_hal_02::digital::v2::InputPin for Input<'d> {
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 6a3d1c463..ab6ef8ef4 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -172,6 +172,14 @@ pub struct Config {
     #[cfg(dbgmcu)]
     pub enable_debug_during_sleep: bool,
 
+    /// On low-power boards (eg. `stm32l4`, `stm32l5` and `stm32u5`),
+    /// some GPIO pins are powered by an auxiliary, independent power supply (`VDDIO2`),
+    /// which needs to be enabled before these pins can be used.
+    ///
+    /// May increase power consumption. Defaults to true.
+    #[cfg(any(stm32l4, stm32l5, stm32u5))]
+    pub enable_independent_io_supply: bool,
+
     /// BDMA interrupt priority.
     ///
     /// Defaults to P0 (highest).
@@ -209,6 +217,8 @@ impl Default for Config {
             rcc: Default::default(),
             #[cfg(dbgmcu)]
             enable_debug_during_sleep: true,
+            #[cfg(any(stm32l4, stm32l5, stm32u5))]
+            enable_independent_io_supply: true,
             #[cfg(bdma)]
             bdma_interrupt_priority: Priority::P0,
             #[cfg(dma)]
@@ -270,6 +280,24 @@ pub fn init(config: Config) -> Peripherals {
         #[cfg(not(any(stm32f2, stm32f4, stm32f7, stm32l0, stm32h5, stm32h7)))]
         peripherals::FLASH::enable_and_reset_with_cs(cs);
 
+        // Enable the VDDIO2 power supply on chips that have it.
+        // Note that this requires the PWR peripheral to be enabled first.
+        #[cfg(any(stm32l4, stm32l5))]
+        {
+            crate::pac::PWR.cr2().modify(|w| {
+                // The official documentation states that we should ideally enable VDDIO2
+                // through the PVME2 bit, but it looks like this isn't required,
+                // and CubeMX itself skips this step.
+                w.set_iosv(config.enable_independent_io_supply);
+            });
+        }
+        #[cfg(stm32u5)]
+        {
+            crate::pac::PWR.svmcr().modify(|w| {
+                w.set_io2sv(config.enable_independent_io_supply);
+            });
+        }
+
         // dead battery functionality is still present on these
         // chips despite them not having UCPD- disable it
         #[cfg(any(stm32g070, stm32g0b0))]
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
index 343e09e68..77aa929ab 100644
--- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
+++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
@@ -93,12 +93,6 @@ async fn main(spawner: Spawner) {
 
     let dp = embassy_stm32::init(config);
 
-    // RM0432rev9, 5.1.2: Independent I/O supply rail
-    // After reset, the I/Os supplied by VDDIO2 are logically and electrically isolated and
-    // therefore are not available. The isolation must be removed before using any I/O from
-    // PG[15:2], by setting the IOSV bit in the PWR_CR2 register, once the VDDIO2 supply is present
-    pac::PWR.cr2().modify(|w| w.set_iosv(true));
-
     let reset_status = pac::RCC.bdcr().read().0;
     defmt::println!("bdcr before: 0x{:X}", reset_status);
 
diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs
index c379863a8..0e555efc8 100644
--- a/tests/stm32/src/common.rs
+++ b/tests/stm32/src/common.rs
@@ -251,13 +251,6 @@ define_peris!(
 );
 
 pub fn config() -> Config {
-    // Setting this bit is mandatory to use PG[15:2].
-    #[cfg(feature = "stm32u5a5zj")]
-    embassy_stm32::pac::PWR.svmcr().modify(|w| {
-        w.set_io2sv(true);
-        w.set_io2vmen(true);
-    });
-
     #[allow(unused_mut)]
     let mut config = Config::default();