fixed clipping issue and use gpio pac instead of using volatile regiser read/write
diff --git a/target/ast10x0/peripherals/scu/routing.rs b/target/ast10x0/peripherals/scu/routing.rs
index 784c206..2ebad91 100644
--- a/target/ast10x0/peripherals/scu/routing.rs
+++ b/target/ast10x0/peripherals/scu/routing.rs
@@ -3,7 +3,7 @@
 
 //! SCU routing and mux helpers for SPI monitor integration.
 
-use core::ptr::{read_volatile, write_volatile};
+use ast1060_pac as device;
 
 use super::registers::ScuRegisters;
 use super::types::{
@@ -17,36 +17,103 @@
 
 #[derive(Clone, Copy)]
 struct SpimGpioInfo {
-    scu_reg_addr: usize,
+    scu_register: SpimScuRegister,
     scu_bit_mask: u32,
-    gpio_addr: usize,
+    gpio_group: GpioGroup,
     gpio_bit_mask: u32,
 }
 
+#[derive(Clone, Copy)]
+enum SpimScuRegister {
+    Scu690,
+    Scu694,
+}
+
+#[derive(Clone, Copy)]
+enum GpioGroup {
+    Abcd,
+    Efgh,
+}
+
+fn gpio_regs() -> &'static device::gpio::RegisterBlock {
+    // SAFETY: The PAC supplies the GPIO register block base address.
+    unsafe { &*device::Gpio::ptr() }
+}
+
+fn gpio_direction(group: GpioGroup) -> u32 {
+    match group {
+        GpioGroup::Abcd => gpio_regs().gpio004().read().bits(),
+        GpioGroup::Efgh => gpio_regs().gpio024().read().bits(),
+    }
+}
+
+fn gpio_set_direction(group: GpioGroup, mask: u32, output: bool) {
+    let update = |bits: u32| {
+        if output {
+            bits | mask
+        } else {
+            bits & !mask
+        }
+    };
+
+    match group {
+        GpioGroup::Abcd => gpio_regs()
+            .gpio004()
+            .modify(|r, w| unsafe { w.bits(update(r.bits())) }),
+        GpioGroup::Efgh => gpio_regs()
+            .gpio024()
+            .modify(|r, w| unsafe { w.bits(update(r.bits())) }),
+    };
+}
+
+fn gpio_set_data(group: GpioGroup, mask: u32, high: bool) {
+    let update = |bits: u32| {
+        if high {
+            bits | mask
+        } else {
+            bits & !mask
+        }
+    };
+
+    match group {
+        GpioGroup::Abcd => gpio_regs()
+            .gpio000()
+            .modify(|r, w| unsafe { w.bits(update(r.bits())) }),
+        GpioGroup::Efgh => gpio_regs()
+            .gpio020()
+            .modify(|r, w| unsafe { w.bits(update(r.bits())) }),
+    };
+}
+
+fn gpio_set_output(group: GpioGroup, mask: u32, high: bool) {
+    gpio_set_data(group, mask, high);
+    gpio_set_direction(group, mask, true);
+}
+
 // Literal translation of g_ast1060_spim_clk_gpio[] in spi_aspeed.c.
 const AST1060_SPIM_CLK_GPIO: [SpimGpioInfo; 4] = [
     SpimGpioInfo {
-        scu_reg_addr: 0x7e6e_2690,
+        scu_register: SpimScuRegister::Scu690,
         scu_bit_mask: 1 << 7,
-        gpio_addr: 0x7e78_0000,
+        gpio_group: GpioGroup::Abcd,
         gpio_bit_mask: 1 << 7,
     },
     SpimGpioInfo {
-        scu_reg_addr: 0x7e6e_2690,
+        scu_register: SpimScuRegister::Scu690,
         scu_bit_mask: 1 << 21,
-        gpio_addr: 0x7e78_0000,
+        gpio_group: GpioGroup::Abcd,
         gpio_bit_mask: 1 << 21,
     },
     SpimGpioInfo {
-        scu_reg_addr: 0x7e6e_2694,
+        scu_register: SpimScuRegister::Scu694,
         scu_bit_mask: 1 << 3,
-        gpio_addr: 0x7e78_0020,
+        gpio_group: GpioGroup::Efgh,
         gpio_bit_mask: 1 << 3,
     },
     SpimGpioInfo {
-        scu_reg_addr: 0x7e6e_2694,
+        scu_register: SpimScuRegister::Scu694,
         scu_bit_mask: 1 << 17,
-        gpio_addr: 0x7e78_0020,
+        gpio_group: GpioGroup::Efgh,
         gpio_bit_mask: 1 << 17,
     },
 ];
@@ -54,27 +121,27 @@
 // Literal translation of g_ast1060_spim_cs_gpio[] in spi_aspeed.c.
 const AST1060_SPIM_CS_GPIO: [SpimGpioInfo; 4] = [
     SpimGpioInfo {
-        scu_reg_addr: 0x7e6e_2690,
+        scu_register: SpimScuRegister::Scu690,
         scu_bit_mask: 1 << 1,
-        gpio_addr: 0x7e78_0000,
+        gpio_group: GpioGroup::Abcd,
         gpio_bit_mask: 1 << 6,
     },
     SpimGpioInfo {
-        scu_reg_addr: 0x7e6e_2690,
+        scu_register: SpimScuRegister::Scu690,
         scu_bit_mask: 1 << 20,
-        gpio_addr: 0x7e78_0000,
+        gpio_group: GpioGroup::Abcd,
         gpio_bit_mask: 1 << 20,
     },
     SpimGpioInfo {
-        scu_reg_addr: 0x7e6e_2694,
+        scu_register: SpimScuRegister::Scu694,
         scu_bit_mask: 1 << 2,
-        gpio_addr: 0x7e78_0020,
+        gpio_group: GpioGroup::Efgh,
         gpio_bit_mask: 1 << 2,
     },
     SpimGpioInfo {
-        scu_reg_addr: 0x7e6e_2694,
+        scu_register: SpimScuRegister::Scu694,
         scu_bit_mask: 1 << 16,
-        gpio_addr: 0x7e78_0020,
+        gpio_group: GpioGroup::Efgh,
         gpio_bit_mask: 1 << 16,
     },
 ];
@@ -92,6 +159,27 @@
 }
 
 impl ScuRegisters {
+    fn set_spim_pin_function(&self, pin: SpimGpioInfo, enabled: bool) {
+        let update = |bits: u32| {
+            if enabled {
+                bits | pin.scu_bit_mask
+            } else {
+                bits & !pin.scu_bit_mask
+            }
+        };
+
+        match pin.scu_register {
+            SpimScuRegister::Scu690 => self
+                .regs()
+                .scu690()
+                .modify(|r, w| unsafe { w.bits(update(r.bits())) }),
+            SpimScuRegister::Scu694 => self
+                .regs()
+                .scu694()
+                .modify(|r, w| unsafe { w.bits(update(r.bits())) }),
+        };
+    }
+
     /// Enable or disable passthrough for a SPI monitor instance. Uses SCU0F0[7:4].
     pub fn set_spim_passthrough(
         &self,
@@ -174,37 +262,18 @@
         let clk = AST1060_SPIM_CLK_GPIO[op_idx];
         let cs = AST1060_SPIM_CS_GPIO[op_idx];
         let mut clk_gpio_ori_val = [0u32; 4];
+        // Change the paired SPIM CLKOUT pin to GPIO mode.
+        self.set_spim_pin_function(clk, false);
 
-        unsafe {
-            // Change the paired SPIM CLKOUT pin to GPIO mode.
-            let mut reg_val = read_volatile(clk.scu_reg_addr as *const u32);
-            reg_val &= !clk.scu_bit_mask;
-            write_volatile(clk.scu_reg_addr as *mut u32, reg_val);
+        // Save its GPIO direction bit, then configure it as an input.
+        clk_gpio_ori_val[op_idx] = gpio_direction(clk.gpio_group) & clk.gpio_bit_mask;
+        gpio_set_direction(clk.gpio_group, clk.gpio_bit_mask, false);
 
-            // Save its GPIO direction bit, then configure it as an input.
-            let clk_dir_addr = (clk.gpio_addr + 0x4) as *mut u32;
-            reg_val = read_volatile(clk_dir_addr);
-            clk_gpio_ori_val[op_idx] = reg_val & clk.gpio_bit_mask;
-            reg_val &= !clk.gpio_bit_mask;
-            write_volatile(clk_dir_addr, reg_val);
+        // Drive the paired SPIM CSOUT GPIO high and configure it as output.
+        gpio_set_output(cs.gpio_group, cs.gpio_bit_mask, true);
 
-            // Drive the paired SPIM CSOUT GPIO high and configure it as output.
-            let cs_data_addr = cs.gpio_addr as *mut u32;
-            reg_val = read_volatile(cs_data_addr);
-            reg_val |= cs.gpio_bit_mask;
-            write_volatile(cs_data_addr, reg_val);
-
-            let cs_dir_addr = (cs.gpio_addr + 0x4) as *mut u32;
-            reg_val = read_volatile(cs_dir_addr);
-            reg_val |= cs.gpio_bit_mask;
-            write_volatile(cs_dir_addr, reg_val);
-
-            // Change the paired SPIM CSOUT pin to GPIO mode.
-            let cs_scu_addr = cs.scu_reg_addr as *mut u32;
-            reg_val = read_volatile(cs_scu_addr);
-            reg_val &= !cs.scu_bit_mask;
-            write_volatile(cs_scu_addr, reg_val);
-        }
+        // Change the paired SPIM CSOUT pin to GPIO mode.
+        self.set_spim_pin_function(cs, false);
 
         pw_log::debug!(
             "SPIM pre-config: op index {}, saved CLK direction mask 0x{:08x}",
@@ -225,7 +294,6 @@
         };
         let clk = AST1060_SPIM_CLK_GPIO[op_idx];
         let cs = AST1060_SPIM_CS_GPIO[op_idx];
-
         pw_log::debug!(
             "SPIM post-config: SCU0F0=0x{:08x}, op index {}, saved CLK direction mask 0x{:08x}",
             scu0f0 as u32,
@@ -233,25 +301,13 @@
             gpio_ori_val.clk_gpio_ori_val[op_idx] as u32
         );
 
-        unsafe {
-            // Restore the paired CLKOUT GPIO direction bit.
-            let clk_dir_addr = (clk.gpio_addr + 0x4) as *mut u32;
-            let mut reg_val = read_volatile(clk_dir_addr);
-            reg_val &= !clk.gpio_bit_mask;
-            reg_val |= gpio_ori_val.clk_gpio_ori_val[op_idx];
-            write_volatile(clk_dir_addr, reg_val);
+        // Restore the paired CLKOUT GPIO direction bit.
+        let was_output = gpio_ori_val.clk_gpio_ori_val[op_idx] != 0;
+        gpio_set_direction(clk.gpio_group, clk.gpio_bit_mask, was_output);
 
-            // Return paired CLKOUT and CSOUT pins to SPIM mode.
-            let clk_scu_addr = clk.scu_reg_addr as *mut u32;
-            reg_val = read_volatile(clk_scu_addr);
-            reg_val |= clk.scu_bit_mask;
-            write_volatile(clk_scu_addr, reg_val);
-
-            let cs_scu_addr = cs.scu_reg_addr as *mut u32;
-            reg_val = read_volatile(cs_scu_addr);
-            reg_val |= cs.scu_bit_mask;
-            write_volatile(cs_scu_addr, reg_val);
-        }
+        // Return paired CLKOUT and CSOUT pins to SPIM mode.
+        self.set_spim_pin_function(clk, true);
+        self.set_spim_pin_function(cs, true);
 
         pw_log::debug!("SPIM post-config: restore complete");
     }
diff --git a/target/ast10x0/tests/smc/read/BUILD.bazel b/target/ast10x0/tests/smc/read/BUILD.bazel
index f10f3a0..3caf693 100644
--- a/target/ast10x0/tests/smc/read/BUILD.bazel
+++ b/target/ast10x0/tests/smc/read/BUILD.bazel
@@ -64,6 +64,7 @@
         ":linker_script",
         "//target/ast10x0:entry",
         "//target/ast10x0/peripherals",
+        "@ast1060_pac",
         "@pigweed//pw_kernel/arch/arm_cortex_m:arch_arm_cortex_m",
         "@pigweed//pw_kernel/kernel",
         "@pigweed//pw_kernel/subsys/console:console_backend",
diff --git a/target/ast10x0/tests/smc/read/target_spi2.rs b/target/ast10x0/tests/smc/read/target_spi2.rs
index 1b67bb3..43759a1 100644
--- a/target/ast10x0/tests/smc/read/target_spi2.rs
+++ b/target/ast10x0/tests/smc/read/target_spi2.rs
@@ -5,6 +5,7 @@
 
 #![no_std]
 #![no_main]
+use ast1060_pac as device;
 #[allow(unused_imports)]
 use ast10x0_peripherals::scu::{
     pinctrl::{
@@ -18,7 +19,6 @@
     SpiUninit, TransferMode,
 };
 use console_backend::console_backend_write_all;
-use core::ptr::{read_volatile, write_volatile};
 use target_common::{declare_target, TargetInterface};
 use {console_backend as _, entry as _};
 
@@ -41,62 +41,68 @@
 GPIO074 = 0x7E78_0074, set bits 26, 27
 */
 fn gpio_flash_power() {
-    // const SCU418: *mut u32 = 0x7E6E_2418 as *mut u32;
-    const GPIO_DATA: *mut u32 = 0x7E78_0070 as *mut u32;
-    const GPIO_DIR: *mut u32 = 0x7E78_0074 as *mut u32;
     const GPIOL2_L3_MASK: u32 = (1 << 26) | (1 << 27);
 
-    unsafe {
-        // Select GPIO function for GPIOL2/GPIOL3.
-        // write_volatile(SCU418, read_volatile(SCU418) & !GPIOL2_L3_MASK);
-        // Configure GPIOL2/GPIOL3 as outputs and drive them high.
-        write_volatile(GPIO_DIR, read_volatile(GPIO_DIR) | GPIOL2_L3_MASK);
-        write_volatile(GPIO_DATA, read_volatile(GPIO_DATA) | GPIOL2_L3_MASK);
-    }
+    // SAFETY: Board initialization has exclusive access to the PAC singleton.
+    let gpio = unsafe { &*device::Gpio::ptr() };
+    gpio.gpio070()
+        .modify(|r, w| unsafe { w.bits(r.bits() | GPIOL2_L3_MASK) });
+    gpio.gpio074()
+        .modify(|r, w| unsafe { w.bits(r.bits() | GPIOL2_L3_MASK) });
 
     for _ in 0..1_000_000 {
         core::hint::spin_loop();
     }
 }
 
-// Temporary raw-MMIO implementation until GPIO and SGPIOM peripherals exist.
 #[allow(dead_code)]
 fn configure_spi2_external_mux(select_mux1: bool) {
-    const SCU41C: *mut u32 = 0x7E6E_241C as *mut u32;
-    const SGPIOM_PIN_MASK: u32 = 0xF << 8;
-
-    const GPIO_E_H_DATA: *mut u32 = 0x7E78_0020 as *mut u32;
-    const GPIO_E_H_DIR: *mut u32 = 0x7E78_0024 as *mut u32;
     const GPIO_E8: u32 = 1 << 8;
-
-    const SGPIOM_DATA_A_D: *mut u32 = 0x7E78_0500 as *mut u32;
-    const SGPIOM_CONFIG: *mut u32 = 0x7E78_0554 as *mut u32;
-    const SGPIOM_WRITE_LATCH_A_D: *const u32 = 0x7E78_0570 as *const u32;
     const SGPIOM_A_D_2: u32 = 1 << 2;
-    const SGPIOM_CONFIG_MASK: u32 = 1 | (0x1F << 6) | (0xFFFF << 16);
-    const SGPIOM_CONFIG_1MHZ_128_PINS: u32 = 1 | (16 << 6) | (24 << 16);
 
-    unsafe {
-        // Select the SGPIOM physical pins and initialize the controller using
-        // the same 1 MHz / 128-pin settings as the Zephyr board configuration.
-        write_volatile(SCU41C, read_volatile(SCU41C) | SGPIOM_PIN_MASK);
-        let config = read_volatile(SGPIOM_CONFIG) & !SGPIOM_CONFIG_MASK;
-        write_volatile(SGPIOM_CONFIG, config | SGPIOM_CONFIG_1MHZ_128_PINS);
+    // SAFETY: Board initialization has exclusive access to the PAC singletons.
+    let gpio = unsafe { &*device::Gpio::ptr() };
+    let sgpio = unsafe { &*device::Sgpiom::ptr() };
+    let _scu_unlocked = unsafe { ScuRegisters::new_global_unlocked() };
+    let scu = unsafe { &*device::Scu::ptr() };
 
-        let mut gpio_data = read_volatile(GPIO_E_H_DATA);
-        let mut sgpio_data = read_volatile(SGPIOM_WRITE_LATCH_A_D);
-        if select_mux1 {
-            gpio_data |= GPIO_E8;
-            sgpio_data |= SGPIOM_A_D_2;
+    scu.scu41c().modify(|_, w| {
+        w.enbl_sgpiomaster_ckfn_pin()
+            .set_bit()
+            .enbl_sgpiomaster_ldfn_pin()
+            .set_bit()
+            .enbl_sgpiomaster_dofn_pin()
+            .set_bit()
+            .enbl_sgpiomaster_difn_pin()
+            .set_bit()
+    });
+    sgpio.gpio554().modify(|_, w| unsafe {
+        w.enbl_of_serial_gpio()
+            .set_bit()
+            .numbers_of_serial_gpiopins()
+            .bits(16)
+            .serial_gpioclk_division()
+            .bits(24)
+    });
+
+    gpio.gpio020().modify(|r, w| unsafe {
+        let bits = if select_mux1 {
+            r.bits() | GPIO_E8
         } else {
-            gpio_data &= !GPIO_E8;
-            sgpio_data &= !SGPIOM_A_D_2;
-        }
+            r.bits() & !GPIO_E8
+        };
+        w.bits(bits)
+    });
+    gpio.gpio024()
+        .modify(|r, w| unsafe { w.bits(r.bits() | GPIO_E8) });
 
-        write_volatile(GPIO_E_H_DATA, gpio_data);
-        write_volatile(GPIO_E_H_DIR, read_volatile(GPIO_E_H_DIR) | GPIO_E8);
-        write_volatile(SGPIOM_DATA_A_D, sgpio_data);
-    }
+    let sgpio_latch = sgpio.gpio570().read().bits();
+    let sgpio_data = if select_mux1 {
+        sgpio_latch | SGPIOM_A_D_2
+    } else {
+        sgpio_latch & !SGPIOM_A_D_2
+    };
+    sgpio.gpio500().write(|w| unsafe { w.bits(sgpio_data) });
 
     // Match the overlay's ext-mux-sel-delay-us = <1000>.
     for _ in 0..100_000 {