verify that spi1 and sp2 read works properly and they can be erase and program. dma read is not reliable(might be a placement issue)
diff --git a/target/ast10x0/peripherals/scu/routing.rs b/target/ast10x0/peripherals/scu/routing.rs
index 784c206..5429fca 100644
--- a/target/ast10x0/peripherals/scu/routing.rs
+++ b/target/ast10x0/peripherals/scu/routing.rs
@@ -160,16 +160,10 @@
         self.unlock_write_protection();
 
         let scu0f0 = self.regs().scu0f0().read().bits();
-        pw_log::debug!("SPIM pre-config: SCU0F0=0x{:08x}", scu0f0 as u32);
         let op_idx = match ast1060_spim_op_idx(scu0f0) {
             Some(idx) => idx,
             None => return None,
         };
-        pw_log::debug!(
-            "SPIM pre-config: active SPIM index {}, op index {}",
-            ((scu0f0 & 0x7) - 1) as u32,
-            op_idx as u32
-        );
 
         let clk = AST1060_SPIM_CLK_GPIO[op_idx];
         let cs = AST1060_SPIM_CS_GPIO[op_idx];
@@ -206,11 +200,6 @@
             write_volatile(cs_scu_addr, reg_val);
         }
 
-        pw_log::debug!(
-            "SPIM pre-config: op index {}, saved CLK direction mask 0x{:08x}",
-            op_idx as u32,
-            clk_gpio_ori_val[op_idx] as u32
-        );
         Some(SpimGpioOriVal { clk_gpio_ori_val })
     }
 
diff --git a/target/ast10x0/peripherals/smc/controller.rs b/target/ast10x0/peripherals/smc/controller.rs
index 2867f9b..2e8bd5d 100644
--- a/target/ast10x0/peripherals/smc/controller.rs
+++ b/target/ast10x0/peripherals/smc/controller.rs
@@ -514,13 +514,13 @@
         if cs == ChipSelect::Cs1 && self.config.cs1.is_none() {

             return Err(SmcError::InvalidChipSelect);

         }

-

+        

         let cs_idx = cs as usize;

         // Derive user-mode base from the stored normal-read value: preserve

         // frequency bits and replace mode type with ASPEED_SPI_USER.

         let user_base = (self.normal_read_ctrl[cs_idx] & !0x7) | ASPEED_SPI_USER;

         let window = self.flash_window_base[cs_idx] as *mut u32;

-

+         pw_log::debug!("cs ctrl: {:08x}", self.regs.read_cs_ctrl(cs) as u32);

         // Assert CS: inactive first, then active (matches aspeed-rust activate_user).

         self.regs

             .write_cs_ctrl(cs, user_base | ASPEED_SPI_USER_INACTIVE);

@@ -550,6 +550,7 @@
         self.regs

             .write_cs_ctrl(cs, user_base | ASPEED_SPI_USER_INACTIVE);

         self.regs.write_cs_ctrl(cs, self.normal_read_ctrl[cs_idx]);

+        pw_log::debug!("cs ctrl: {:08x}", self.regs.read_cs_ctrl(cs) as u32);

         Ok(())

     }

 

@@ -564,7 +565,7 @@
         let cs_capacity = self.cs_capacity_bytes(cs)?;

         let use_4b_addr = spi_nor_uses_4b_addr(cs_capacity);

         let read_opcode = spi_nor_qread_cmd_for_capacity(cs_capacity);

-        //pw_log::info!("=== spi_read_init()===");

+        pw_log::info!("=== spi_read_init()===");

         let read_cmd =

             mode.data_io_bits() | (read_opcode << 16) | (dummy << 6) | ASPEED_SPI_NORMAL_READ;

 

@@ -604,8 +605,8 @@
         let reg = self.regs.read_cs_ctrl(cs);

         self.regs

             .write_cs_ctrl(cs, (reg & !SPI_CTRL_FREQ_MASK) | encoded_div);

-        self.normal_read_ctrl[cs_idx] &= (!SPI_CTRL_FREQ_MASK) | encoded_div;

-

+        self.normal_read_ctrl[cs_idx] =  self.regs.read_cs_ctrl(cs);

+        pw_log::debug!("normal_read_ctrl: {:08x}", self.normal_read_ctrl[cs_idx] as u32);

         Ok(())

     }

 

diff --git a/target/ast10x0/tests/smc/read/target_spi1.rs b/target/ast10x0/tests/smc/read/target_spi1.rs
index 04d23f7..8062d1f 100644
--- a/target/ast10x0/tests/smc/read/target_spi1.rs
+++ b/target/ast10x0/tests/smc/read/target_spi1.rs
@@ -6,6 +6,8 @@
 #![no_std]
 #![no_main]
 
+const TEST_OFFSET: u32 = 0x10_0000;
+
 use ast10x0_peripherals::scu::{
     pinctrl::{PINCTRL_SPI1_QUAD, PINCTRL_SPIM1_DEFAULT},
     ScuExtMuxSelect, ScuRegisters, SpiMonitorInstance, SpiMonitorPassthrough, SpiMonitorSource,
@@ -100,13 +102,13 @@
     }
     dump_smc_read(&buf, buf.len() as u32);
 
-    pw_log::info!("=== SPI1 DMA read @ 0x00000000 ===");
+    pw_log::info!("=== SPI1 DMA read @ {:08x} ===", TEST_OFFSET as u32);
     let dma_buf = unsafe { core::slice::from_raw_parts_mut(0x41500 as *mut u8, 256) };
     let mut dma_txn = SpiTransaction::dma_read_with_spim(
         &mut spi,
         SpiMonitorInstance::Spim0,
         ChipSelect::Cs0,
-        0x0,
+        TEST_OFFSET,
         0x41500usize,
         dma_buf.len() as u32,
     )?;
diff --git a/target/ast10x0/tests/smc/read/target_spi2.rs b/target/ast10x0/tests/smc/read/target_spi2.rs
index 1b67bb3..bcbf546 100644
--- a/target/ast10x0/tests/smc/read/target_spi2.rs
+++ b/target/ast10x0/tests/smc/read/target_spi2.rs
@@ -26,6 +26,8 @@
 mod target_debug;
 use target_debug::{dump_smc_read, dump_smc_register};
 
+const TEST_OFFSET: u32 = 0x10_0000;
+
 const SPI_FLASH_CONFIG: FlashConfig = FlashConfig {
     capacity_mb: 32,
     page_size: 256,
@@ -185,7 +187,7 @@
         &mut spi,
         SpiMonitorInstance::Spim2,
         ChipSelect::Cs0,
-        0x0,
+        TEST_OFFSET,
         &mut buf,
     )?;
     if n != buf.len() {
@@ -193,13 +195,13 @@
     }
     dump_smc_read(&buf, buf.len() as u32);
 
-    pw_log::info!("=== SPI2 DMA read @ 0x00000000 ===");
+    pw_log::info!("=== SPI2 DMA read @ {:08x} ===", TEST_OFFSET as u32);
     let dma_buf = unsafe { core::slice::from_raw_parts_mut(0x41500 as *mut u8, 256) };
     let mut dma_txn = SpiTransaction::dma_read_with_spim(
         &mut spi,
         SpiMonitorInstance::Spim2,
         ChipSelect::Cs0,
-        0x0,
+        TEST_OFFSET,
         0x41500usize,
         dma_buf.len() as u32,
     )?;
diff --git a/target/ast10x0/tests/smc/write/spi_write_common.rs b/target/ast10x0/tests/smc/write/spi_write_common.rs
index 72a3d21..99d64d8 100644
--- a/target/ast10x0/tests/smc/write/spi_write_common.rs
+++ b/target/ast10x0/tests/smc/write/spi_write_common.rs
@@ -3,6 +3,8 @@
 
 //! Shared destructive SPI flash test flow.
 
+use core::cell::UnsafeCell;
+
 use ast10x0_peripherals::smc::{
     ChipSelect, FlashConfig, SmcConfig, SmcController, SmcError, SmcTopology, SpiReady,
     SpiTransaction, SpiUninit, TransferMode,
@@ -24,9 +26,24 @@
 const TEST_OFFSET: u32 = 0x10_0000;
 const PAGE_LEN: usize = 256;
 const SECTOR_LEN: usize = 4096;
-const BACKUP_ADDR: usize = 0x41000;
 const STATUS_WIP: u8 = 1;
+const STATUS_WEL: u8 = 1 << 1;
 const STATUS_MAX_POLLS: u32 = 1_000_000;
+const STATUS_CLEAR_SAMPLES: u8 = 3;
+const STATUS_POLL_DELAY: u32 = 64;
+const DMA_BUFFER: u32 = 0x41500;
+
+#[repr(align(256))]
+struct BackupBuffer(UnsafeCell<[u8; SECTOR_LEN]>);
+
+#[repr(align(256))]
+struct PageBuffer([u8; PAGE_LEN]);
+
+// The test runs synchronously on one core and borrows this buffer only for the
+// duration of run_flash_test().
+unsafe impl Sync for BackupBuffer {}
+
+static BACKUP_BUFFER: BackupBuffer = BackupBuffer(UnsafeCell::new([0; SECTOR_LEN]));
 
 fn fill_test_pattern(out: &mut [u8; PAGE_LEN], salt: u8) {
     let mut i = 0usize;
@@ -37,20 +54,31 @@
 }
 
 fn expect_erased(buf: &[u8]) -> Result<(), SmcError> {
-    for &byte in buf {
+    for (index, &byte) in buf.iter().enumerate() {
         if byte != 0xff {
+            pw_log::info!(
+                "erase verify failed at 0x{:08x}: expected ff, got {:02x}",
+                (TEST_OFFSET as usize + index) as u32,
+                byte as u32
+            );
             return Err(SmcError::HardwareError);
         }
     }
     Ok(())
 }
 
+#[allow(dead_code)]
+fn is_erased(buf: &[u8]) -> bool {
+    buf.iter().all(|&byte| byte == 0xff)
+}
+
 fn command_with_spim(
     spi: &mut SpiReady,
     spim: SpiMonitorInstance,
     cmd: &[u8],
     tx: &[u8],
     rx: &mut [u8],
+    mode: TransferMode,
 ) -> Result<(), SmcError> {
     SpiTransaction::transceive_user_with_spim(
         spi,
@@ -59,40 +87,124 @@
         cmd,
         tx,
         rx,
-        TransferMode::Mode111,
+        mode,
     )
 }
 
-fn read_with_spim(
+fn dma_read_with_spim(
     spi: &mut SpiReady,
     spim: SpiMonitorInstance,
     offset: u32,
     buf: &mut [u8],
 ) -> Result<(), SmcError> {
-    let n = SpiTransaction::read_with_spim(spi, spim, ChipSelect::Cs0, offset, buf)?;
-    if n != buf.len() {
+    let mut dma_txn = SpiTransaction::dma_read_with_spim(
+        spi,
+        spim,
+        ChipSelect::Cs0,
+        offset,
+        buf.as_mut_ptr() as usize,
+        u32::try_from(buf.len()).map_err(|_| SmcError::InvalidCapacity)?,
+    )?;
+
+    loop {
+        match dma_txn.poll_dma_completion() {
+            core::task::Poll::Pending => core::hint::spin_loop(),
+            core::task::Poll::Ready(result) => return result,
+        }
+    }
+}
+
+fn read_status(spi: &mut SpiReady, spim: SpiMonitorInstance) -> Result<u8, SmcError> {
+    let mut status = [0u8; 1];
+    command_with_spim(
+        spi,
+        spim,
+        &[0x05],
+        &[],
+        &mut status,
+        TransferMode::Mode111,
+    )?;
+    Ok(status[0])
+}
+
+fn write_enable(spi: &mut SpiReady, spim: SpiMonitorInstance) -> Result<(), SmcError> {
+    command_with_spim(
+        spi,
+        spim,
+        &[0x06],
+        &[],
+        &mut [],
+        TransferMode::Mode111,
+    )?;
+
+    let status = read_status(spi, spim)?;
+    if status & STATUS_WEL == 0 {
+        pw_log::info!("write enable failed: SR1=0x{:02x}", status as u32);
         return Err(SmcError::HardwareError);
     }
     Ok(())
 }
 
-fn write_enable(spi: &mut SpiReady, spim: SpiMonitorInstance) -> Result<(), SmcError> {
-    command_with_spim(spi, spim, &[0x06], &[], &mut [])
+fn status_poll_delay() {
+    let mut cycles = 0u32;
+    while cycles < STATUS_POLL_DELAY {
+        core::hint::spin_loop();
+        cycles += 1;
+    }
 }
 
-fn wait_write_complete(spi: &mut SpiReady, spim: SpiMonitorInstance) -> Result<(), SmcError> {
+fn wait_write_complete(
+    spi: &mut SpiReady,
+    spim: SpiMonitorInstance,
+    initial_status: u8,
+) -> Result<(), SmcError> {
     let mut polls = 0u32;
+    let mut clear_samples = 0u8;
+    let mut status = initial_status;
+
     while polls < STATUS_MAX_POLLS {
-        let mut status = [0u8; 1];
-        command_with_spim(spi, spim, &[0x05], &[], &mut status)?;
-        if status[0] & STATUS_WIP == 0 {
-            return Ok(());
+        if status & STATUS_WIP == 0 {
+            clear_samples += 1;
+            if clear_samples == STATUS_CLEAR_SAMPLES {
+                pw_log::info!(
+                    "write complete: SR1=0x{:02x}, polls={}",
+                    status as u32,
+                    polls as u32
+                );
+                return Ok(());
+            }
+        } else {
+            clear_samples = 0;
         }
+
+        status_poll_delay();
+        status = read_status(spi, spim)?;
         polls += 1;
     }
     Err(SmcError::Timeout)
 }
 
+fn read_fast_with_spim(
+    spi: &mut SpiReady,
+    spim: SpiMonitorInstance,
+    offset: u32,
+    buf: &mut [u8],
+) -> Result<(), SmcError> {
+    let address = offset.to_be_bytes();
+    // 0x0C: 4-byte-address Fast Read, followed by one dummy byte.
+    let cmd = [
+        0x0c, address[0], address[1], address[2], address[3], 0x00,
+    ];
+    command_with_spim(
+        spi,
+        spim,
+        &cmd,
+        &[],
+        buf,
+        TransferMode::Mode114,
+    )
+}
+
 fn erase_sector(
     spi: &mut SpiReady,
     spim: SpiMonitorInstance,
@@ -101,8 +213,21 @@
     write_enable(spi, spim)?;
     let address = offset.to_be_bytes();
     let cmd = [0x21, address[0], address[1], address[2], address[3]];
-    command_with_spim(spi, spim, &cmd, &[], &mut [])?;
-    wait_write_complete(spi, spim)
+    command_with_spim(
+        spi,
+        spim,
+        &cmd,
+        &[],
+        &mut [],
+        TransferMode::Mode111,
+    )?;
+    let status = read_status(spi, spim)?;
+    pw_log::info!("erase command SR1=0x{:02x}", status as u32);
+    if status & STATUS_WIP == 0 {
+        pw_log::info!("erase command did not enter busy state");
+        return Err(SmcError::HardwareError);
+    }
+    wait_write_complete(spi, spim, status)
 }
 
 fn program_page(
@@ -114,27 +239,49 @@
     write_enable(spi, spim)?;
     let address = offset.to_be_bytes();
     let cmd = [0x12, address[0], address[1], address[2], address[3]];
-    command_with_spim(spi, spim, &cmd, data, &mut [])?;
-    wait_write_complete(spi, spim)
+    command_with_spim(
+        spi,
+        spim,
+        &cmd,
+        data,
+        &mut [],
+        TransferMode::Mode114,
+    )?;
+    let status = read_status(spi, spim)?;
+    pw_log::info!("program command SR1=0x{:02x}", status as u32);
+    wait_write_complete(spi, spim, status)
 }
 
+#[allow(dead_code)]
 fn verify_data(
     spi: &mut SpiReady,
     spim: SpiMonitorInstance,
     offset: u32,
     expected: &[u8],
 ) -> Result<(), SmcError> {
-    let mut read_buf = [0u8; PAGE_LEN];
+    let dma_buf = unsafe { core::slice::from_raw_parts_mut(DMA_BUFFER as *mut u8, 256) };
     let mut cursor = 0usize;
     while cursor < expected.len() {
         let len = core::cmp::min(PAGE_LEN, expected.len() - cursor);
-        read_with_spim(
+        dma_read_with_spim(
             spi,
             spim,
             offset + cursor as u32,
-            &mut read_buf[..len],
+            &mut dma_buf[..len],
         )?;
-        if read_buf[..len] != expected[cursor..cursor + len] {
+        if dma_buf[..len] != expected[cursor..cursor + len] {
+            let mut mismatch = 0usize;
+            while mismatch < len
+                && dma_buf[mismatch] == expected[cursor + mismatch]
+            {
+                mismatch += 1;
+            }
+            pw_log::info!(
+                "data verify failed at 0x{:08x}: expected {:02x}, got {:02x}",
+                (offset as usize + cursor + mismatch) as u32,
+                expected[cursor + mismatch] as u32,
+                dma_buf[mismatch] as u32
+            );
             return Err(SmcError::HardwareError);
         }
         cursor += len;
@@ -142,6 +289,7 @@
     Ok(())
 }
 
+#[allow(dead_code)]
 fn restore_sector(
     spi: &mut SpiReady,
     spim: SpiMonitorInstance,
@@ -152,12 +300,10 @@
     let mut cursor = 0usize;
     while cursor < original.len() {
         let len = core::cmp::min(PAGE_LEN, original.len() - cursor);
-        program_page(
-            spi,
-            spim,
-            TEST_OFFSET + cursor as u32,
-            &original[cursor..cursor + len],
-        )?;
+        let page = &original[cursor..cursor + len];
+        if !is_erased(page) {
+            program_page(spi, spim, TEST_OFFSET + cursor as u32, page)?;
+        }
         cursor += len;
     }
 
@@ -171,21 +317,46 @@
 ) -> Result<(), SmcError> {
     erase_sector(spi, spim, TEST_OFFSET)?;
 
-    let mut read_buf = [0u8; PAGE_LEN];
-    read_with_spim(spi, spim, TEST_OFFSET, &mut read_buf)?;
-    expect_erased(&read_buf)?;
-    dump_smc_read(&read_buf, PAGE_LEN as u32);
+    let mut read_buf = PageBuffer([0u8; PAGE_LEN]);
+    
+    read_fast_with_spim(spi, spim, TEST_OFFSET, &mut read_buf.0)?;
+    if let Err(error) = expect_erased(&read_buf.0) {
+        pw_log::info!("user-mode erase verification failed");
+        return Err(error);
+    }
+    pw_log::info!("user-mode erase verification passed");
+
+    let dma_buf = unsafe { core::slice::from_raw_parts_mut((DMA_BUFFER+0x100) as *mut u8, 256) };
+    dma_read_with_spim(spi, spim, TEST_OFFSET, dma_buf)?;
+    expect_erased(dma_buf)?;
+
+    //dump_smc_read(dma_buf, PAGE_LEN as u32);
 
     let mut pattern = [0u8; PAGE_LEN];
     fill_test_pattern(&mut pattern, salt);
     program_page(spi, spim, TEST_OFFSET, &pattern)?;
 
-    read_buf.fill(0);
-    read_with_spim(spi, spim, TEST_OFFSET, &mut read_buf)?;
-    if read_buf != pattern {
+    dma_read_with_spim(spi, spim, TEST_OFFSET, dma_buf)?;
+
+    
+    if dma_buf != pattern {
+        let mut mismatch = 0usize;
+        while mismatch < PAGE_LEN && dma_buf[mismatch] == pattern[mismatch] {
+            mismatch += 1;
+        }
+        pw_log::info!(
+            "program verify failed at 0x{:08x}: expected {:02x}, got {:02x}",
+            (TEST_OFFSET as usize + mismatch) as u32,
+            pattern[mismatch] as u32,
+            dma_buf[mismatch] as u32
+        );
+        pw_log::info!("pattern::");
+        dump_smc_read(&pattern, PAGE_LEN as u32);
+        pw_log::info!("dma buffer::");
+        dump_smc_read(dma_buf, PAGE_LEN as u32);
         return Err(SmcError::HardwareError);
     }
-    dump_smc_read(&read_buf, PAGE_LEN as u32);
+    
     Ok(())
 }
 
@@ -195,7 +366,14 @@
     salt: u8,
 ) -> Result<(), SmcError> {
     let mut jedec = [0u8; 3];
-    command_with_spim(spi, spim, &[0x9f], &[], &mut jedec)?;
+    command_with_spim(
+        spi,
+        spim,
+        &[0x9f],
+        &[],
+        &mut jedec,
+        TransferMode::Mode111,
+    )?;
     pw_log::info!(
         "JEDEC ID: {:02x} {:02x} {:02x}",
         jedec[0] as u32,
@@ -207,17 +385,20 @@
     }
 
     pw_log::info!("=== backup test sector ===");
-    let original = unsafe { core::slice::from_raw_parts_mut(BACKUP_ADDR as *mut u8, SECTOR_LEN) };
-    read_with_spim(spi, spim, TEST_OFFSET, original)?;
+    // SAFETY: This test has exclusive access to BACKUP_BUFFER until it returns.
+    let original = unsafe { &mut *BACKUP_BUFFER.0.get() };
+    dma_read_with_spim(spi, spim, TEST_OFFSET, original)?;
 
     pw_log::info!("=== erase/write/read test sector ===");
     let test_result = destructive_test(spi, spim, salt);
-
+    /*
     pw_log::info!("=== restore test sector ===");
     let restore_result = restore_sector(spi, spim, original);
 
     test_result?;
     restore_result
+    */
+    test_result
 }
 
 pub fn new_spi(
@@ -228,7 +409,7 @@
         controller_id: controller,
         cs0: Some(FLASH_CONFIG),
         cs1: None,
-        dma_enabled: false,
+        dma_enabled: true,
         enable_interrupts: false,
         topology,
     };