Decouple peripheral driver from pw_kernel
diff --git a/hal/blocking/src/gpio_port.rs b/hal/blocking/src/gpio_port.rs
index f7ab53f..8c27958 100644
--- a/hal/blocking/src/gpio_port.rs
+++ b/hal/blocking/src/gpio_port.rs
@@ -242,4 +242,3 @@
     /// Disable passthrough for all pins.
     fn clear_passthrough(&mut self) -> Result<(), Self::Error>;
 }
-
diff --git a/target/ast10x0/peripherals/BUILD.bazel b/target/ast10x0/peripherals/BUILD.bazel
index 554c537..e7318f2 100644
--- a/target/ast10x0/peripherals/BUILD.bazel
+++ b/target/ast10x0/peripherals/BUILD.bazel
@@ -36,7 +36,7 @@
         "sgpiom/controller.rs",
         "sgpiom/hal_impl.rs",
         "sgpiom/mod.rs",
-        "sgpiom/register_block.rs",
+        "sgpiom/registers.rs",
         "sgpiom/types.rs",
         "smc/controller.rs",
         "smc/device/block_device.rs",
diff --git a/target/ast10x0/peripherals/sgpiom/hal_impl.rs b/target/ast10x0/peripherals/sgpiom/hal_impl.rs
index 2667cff..69cd62b 100644
--- a/target/ast10x0/peripherals/sgpiom/hal_impl.rs
+++ b/target/ast10x0/peripherals/sgpiom/hal_impl.rs
@@ -6,7 +6,7 @@
     GpioInterrupt, GpioPort, InterruptOperation, PinConfig, PinDirection, PinMask,
 };
 
-use super::register_block::Sgpiom;
+use super::registers::Sgpiom;
 use super::types::{BankDevice, Error, InterruptMode, InterruptTrigger};
 
 /// 32-bit pin mask for a single SGPIOM bank.
diff --git a/target/ast10x0/peripherals/sgpiom/mod.rs b/target/ast10x0/peripherals/sgpiom/mod.rs
index b17bac5..accd76d 100644
--- a/target/ast10x0/peripherals/sgpiom/mod.rs
+++ b/target/ast10x0/peripherals/sgpiom/mod.rs
@@ -5,13 +5,28 @@
 
 mod controller;
 mod hal_impl;
-mod register_block;
+mod registers;
 mod types;
 
 pub use controller::SgpiomController;
 pub use hal_impl::{SgpiomBankPort, SgpiomMask};
-pub use register_block::Sgpiom;
+pub use registers::{Sgpiom, SgpiomBankState};
 pub use types::{
     Bank, BankDevice, Direction, Error, InitialLevel, InterruptMode, InterruptTrigger,
     SgpiomPinConfig,
 };
+
+impl core::fmt::Display for SgpiomBankState {
+    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+        write!(
+            f,
+            "bank={} cfg(554)=0x{:08x} data(500)=0x{:08x} latch=0x{:08x} int_en=0x{:08x} int_sts=0x{:08x}",
+            self.bank as u32,
+            self.config,
+            self.data,
+            self.latch,
+            self.int_en,
+            self.int_status
+        )
+    }
+}
diff --git a/target/ast10x0/peripherals/sgpiom/register_block.rs b/target/ast10x0/peripherals/sgpiom/registers.rs
similarity index 94%
rename from target/ast10x0/peripherals/sgpiom/register_block.rs
rename to target/ast10x0/peripherals/sgpiom/registers.rs
index 00cb347..58f695c 100644
--- a/target/ast10x0/peripherals/sgpiom/register_block.rs
+++ b/target/ast10x0/peripherals/sgpiom/registers.rs
@@ -9,6 +9,18 @@
     SgpiomPinConfig,
 };
 
+/// Snapshot of live SGPIOM register state for one bank, returned by
+/// [`Sgpiom::dump_state`]. The caller decides how to log or inspect the values.
+#[derive(Debug, Clone, Copy)]
+pub struct SgpiomBankState {
+    pub bank: Bank,
+    pub config: u32,
+    pub data: u32,
+    pub latch: u32,
+    pub int_en: u32,
+    pub int_status: u32,
+}
+
 pub struct Sgpiom {
     sgpiom: *const device::sgpiom::RegisterBlock,
     /// Prevent `Send` and `Sync`.
@@ -57,20 +69,21 @@
         self.regs().gpio554().read().bits()
     }
 
-    /// Dump the live SGPIOM register state for a bank via `pw_log::info!`.
+    /// Snapshot the live SGPIOM register state for a bank.
     ///
     /// All values are read back from hardware (not the last written value), so
     /// this confirms whether writes actually stuck and the engine reflects them.
-    pub fn debug_dump(&self, bank: Bank) {
-        pw_log::info!(
-            "sgpiom dump bank={} cfg(554)=0x{:08x} data(500)=0x{:08x} latch=0x{:08x} int_en=0x{:08x} int_sts=0x{:08x}",
-            bank as u32,
-            self.read_config() as u32,
-            self.port_get_raw(bank) as u32,
-            self.read_output_latch(bank) as u32,
-            self.int_en_read(bank) as u32,
-            self.interrupt_status(bank) as u32
-        );
+    /// The caller is responsible for logging or otherwise consuming the result.
+    #[must_use]
+    pub fn dump_state(&self, bank: Bank) -> SgpiomBankState {
+        SgpiomBankState {
+            bank,
+            config: self.read_config(),
+            data: self.port_get_raw(bank),
+            latch: self.read_output_latch(bank),
+            int_en: self.int_en_read(bank),
+            int_status: self.interrupt_status(bank),
+        }
     }
 
     /// Configures SGPIOM global settings.
diff --git a/target/ast10x0/peripherals/sgpiom/types.rs b/target/ast10x0/peripherals/sgpiom/types.rs
index d661287..a4b26ee 100644
--- a/target/ast10x0/peripherals/sgpiom/types.rs
+++ b/target/ast10x0/peripherals/sgpiom/types.rs
@@ -20,7 +20,7 @@
     High,
 }
 
-/// Low-level per-pin configuration used by [`crate::sgpiom::register_block::Sgpiom::configure_pin`].
+/// Low-level per-pin configuration used by [`crate::sgpiom::registers::Sgpiom::configure_pin`].
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
 pub struct SgpiomPinConfig {
     pub direction: Direction,
diff --git a/target/ast10x0/tests/peripherals/sgpiom/sgpiom_irq/sgpiom_irq_server_main.rs b/target/ast10x0/tests/peripherals/sgpiom/sgpiom_irq/sgpiom_irq_server_main.rs
index cc80abf..877bd54 100644
--- a/target/ast10x0/tests/peripherals/sgpiom/sgpiom_irq/sgpiom_irq_server_main.rs
+++ b/target/ast10x0/tests/peripherals/sgpiom/sgpiom_irq/sgpiom_irq_server_main.rs
@@ -117,7 +117,7 @@
             ((data >> pin) & 1) as u32
         );
     }
-    monitor.debug_dump(Bank::Ad);
+    pw_log::info!("{}", monitor.dump_state(Bank::Ad));
 
     // INPUT/IRQ: both-edge sensitivity on the watched pins.
     if port
diff --git a/target/ast10x0/tests/peripherals/sgpiom/sgpiom_smoke/target.rs b/target/ast10x0/tests/peripherals/sgpiom/sgpiom_smoke/target.rs
index 13ac5fa..735c8bc 100644
--- a/target/ast10x0/tests/peripherals/sgpiom/sgpiom_smoke/target.rs
+++ b/target/ast10x0/tests/peripherals/sgpiom/sgpiom_smoke/target.rs
@@ -164,7 +164,10 @@
 
     // HAL GpioInterrupt: configure sensitivity, then enable/query/clear/disable.
     let irq_mask = SgpiomMask(1 << 6);
-    if bank_port.irq_configure(irq_mask, EdgeSensitivity::RisingEdge).is_err() {
+    if bank_port
+        .irq_configure(irq_mask, EdgeSensitivity::RisingEdge)
+        .is_err()
+    {
         pw_log::error!("HAL irq_configure failed");
         return false;
     }
@@ -187,7 +190,10 @@
     }
 
     // IsPending must not error (status value is environment-dependent).
-    if bank_port.irq_control(irq_mask, InterruptOperation::IsPending).is_err() {
+    if bank_port
+        .irq_control(irq_mask, InterruptOperation::IsPending)
+        .is_err()
+    {
         pw_log::error!("HAL irq IsPending failed");
         return false;
     }