now we can see bmc spi and host spi on Master side. HOST spimonitor works for spi2@0 and spi2@1.
diff --git a/target/ast10x0/board/src/spim_wiring.rs b/target/ast10x0/board/src/spim_wiring.rs index a22224a..701b26d 100644 --- a/target/ast10x0/board/src/spim_wiring.rs +++ b/target/ast10x0/board/src/spim_wiring.rs
@@ -10,6 +10,7 @@ //! (`peripherals/spimonitor/planning/overview-and-usage-model.md`) calls for //! "configure early, validate, lock, and operate under that locked policy." +use ast1060_pac as device; use ast10x0_peripherals::scu::{ pinctrl::{ PINCTRL_GPIOL2, PINCTRL_GPIOL3, PINCTRL_SPIM1_DEFAULT, PINCTRL_SPIM2_DEFAULT, @@ -23,7 +24,6 @@ LockedSpiMonitor, MonitorPolicy, PassthroughMode, SpiMonitor, SpiMonitorController, SpiMonitorError, Uninitialized, }; -use ast1060_pac as device; /// Static wiring for one external SPI monitor path. /// @@ -118,22 +118,10 @@ let high = matches!(mux, ScuExtMuxSelect::Mux1); let (gpio_group, gpio_mask, sgpio_select, sgpio_oe_n, sgpio_reset_n) = match instance { SpiMonitorInstance::Spim0 | SpiMonitorInstance::Spim1 => { - ( - ExternalMuxGpioGroup::Abcd, - 1 << 12, - 1 << 0, - 1 << 1, - 1 << 7, - ) + (ExternalMuxGpioGroup::Abcd, 1 << 12, 1 << 0, 1 << 1, 1 << 7) } SpiMonitorInstance::Spim2 | SpiMonitorInstance::Spim3 => { - ( - ExternalMuxGpioGroup::Efgh, - 1 << 8, - 1 << 2, - 1 << 3, - 1 << 6, - ) + (ExternalMuxGpioGroup::Efgh, 1 << 8, 1 << 2, 1 << 3, 1 << 6) } }; @@ -151,20 +139,16 @@ }); match gpio_group { ExternalMuxGpioGroup::Abcd => { - gpio.gpio000().modify(|r, w| unsafe { - w.bits(update_bit(r.bits(), gpio_mask, high)) - }); - gpio.gpio004().modify(|r, w| unsafe { - w.bits(r.bits() | gpio_mask) - }); + gpio.gpio000() + .modify(|r, w| unsafe { w.bits(update_bit(r.bits(), gpio_mask, high)) }); + gpio.gpio004() + .modify(|r, w| unsafe { w.bits(r.bits() | gpio_mask) }); } ExternalMuxGpioGroup::Efgh => { - gpio.gpio020().modify(|r, w| unsafe { - w.bits(update_bit(r.bits(), gpio_mask, high)) - }); - gpio.gpio024().modify(|r, w| unsafe { - w.bits(r.bits() | gpio_mask) - }); + gpio.gpio020() + .modify(|r, w| unsafe { w.bits(update_bit(r.bits(), gpio_mask, high)) }); + gpio.gpio024() + .modify(|r, w| unsafe { w.bits(r.bits() | gpio_mask) }); } } @@ -189,27 +173,13 @@ /// Read back the board-level mux selection, output enable, and flash reset. #[must_use] -pub fn spim_external_mux_state( - instance: SpiMonitorInstance, -) -> Option<ScuExtMuxSelect> { +pub fn spim_external_mux_state(instance: SpiMonitorInstance) -> Option<ScuExtMuxSelect> { let (gpio_group, gpio_mask, sgpio_select, sgpio_oe_n, sgpio_reset_n) = match instance { SpiMonitorInstance::Spim0 | SpiMonitorInstance::Spim1 => { - ( - ExternalMuxGpioGroup::Abcd, - 1 << 12, - 1 << 0, - 1 << 1, - 1 << 7, - ) + (ExternalMuxGpioGroup::Abcd, 1 << 12, 1 << 0, 1 << 1, 1 << 7) } SpiMonitorInstance::Spim2 | SpiMonitorInstance::Spim3 => { - ( - ExternalMuxGpioGroup::Efgh, - 1 << 8, - 1 << 2, - 1 << 3, - 1 << 6, - ) + (ExternalMuxGpioGroup::Efgh, 1 << 8, 1 << 2, 1 << 3, 1 << 6) } }; let gpio = unsafe { &*device::Gpio::ptr() }; @@ -242,12 +212,10 @@ const FLASH_POWER_MASK: u32 = (1 << 26) | (1 << 27); let gpio = unsafe { &*device::Gpio::ptr() }; - gpio.gpio070().modify(|r, w| unsafe { - w.bits(r.bits() | FLASH_POWER_MASK) - }); - gpio.gpio074().modify(|r, w| unsafe { - w.bits(r.bits() | FLASH_POWER_MASK) - }); + gpio.gpio070() + .modify(|r, w| unsafe { w.bits(r.bits() | FLASH_POWER_MASK) }); + gpio.gpio074() + .modify(|r, w| unsafe { w.bits(r.bits() | FLASH_POWER_MASK) }); crate::delay_us(1_000); gpio.gpio0c8().read().bits() & FLASH_POWER_MASK == FLASH_POWER_MASK
diff --git a/target/ast10x0/peripherals/scu/pinctrl.rs b/target/ast10x0/peripherals/scu/pinctrl.rs index 2b5f872..203fe2a 100644 --- a/target/ast10x0/peripherals/scu/pinctrl.rs +++ b/target/ast10x0/peripherals/scu/pinctrl.rs
@@ -538,11 +538,8 @@ } // GPIO -pub const PINCTRL_GPIOH2: &[PinctrlPin] = &[ - CLR_PIN_SCU414_26, - CLR_PIN_SCU4B4_26, - CLR_PIN_SCU694_26, -]; +pub const PINCTRL_GPIOH2: &[PinctrlPin] = + &[CLR_PIN_SCU414_26, CLR_PIN_SCU4B4_26, CLR_PIN_SCU694_26]; pub const PINCTRL_GPIOL2: &[PinctrlPin] = &[CLR_PIN_SCU418_26]; pub const PINCTRL_GPIOL3: &[PinctrlPin] = &[CLR_PIN_SCU418_27]; pub const PINCTRL_GPIOM5: &[PinctrlPin] = &[CLR_PIN_SCU41C_5];
diff --git a/target/ast10x0/peripherals/scu/routing.rs b/target/ast10x0/peripherals/scu/routing.rs index 18a9a1f..b99d1bd 100644 --- a/target/ast10x0/peripherals/scu/routing.rs +++ b/target/ast10x0/peripherals/scu/routing.rs
@@ -208,40 +208,6 @@ }); } - /// Route the external flash-reset input through one SPIPF. - /// - /// Clears the instance's reset signal and source-selection bits in - /// SCU0F0[19:16] and [23:20], and enables its reset output in [27:24]. - pub fn configure_spim_external_flash_reset(&self, instance: SpiMonitorInstance) { - self.unlock_write_protection(); - let instance_bit = match instance { - SpiMonitorInstance::Spim0 => 1 << 0, - SpiMonitorInstance::Spim1 => 1 << 1, - SpiMonitorInstance::Spim2 => 1 << 2, - SpiMonitorInstance::Spim3 => 1 << 3, - }; - let clear_mask = (instance_bit << 16) | (instance_bit << 20); - let output_enable = instance_bit << 24; - self.regs() - .scu0f0() - .modify(|r, w| unsafe { w.bits((r.bits() & !clear_mask) | output_enable) }); - } - - /// Check the external flash-reset source and output-enable configuration. - #[must_use] - pub fn is_spim_external_flash_reset_configured(&self, instance: SpiMonitorInstance) -> bool { - let instance_bit = match instance { - SpiMonitorInstance::Spim0 => 1 << 0, - SpiMonitorInstance::Spim1 => 1 << 1, - SpiMonitorInstance::Spim2 => 1 << 2, - SpiMonitorInstance::Spim3 => 1 << 3, - }; - let cleared_mask = (instance_bit << 16) | (instance_bit << 20); - let output_enable = instance_bit << 24; - let value = self.regs().scu0f0().read().bits(); - value & cleared_mask == 0 && value & output_enable == output_enable - } - /// Disable the internal pull-down on the monitor CS output pin. pub fn disable_spim_cs_internal_pull_down(&self, instance: SpiMonitorInstance) { self.unlock_write_protection();
diff --git a/target/ast10x0/peripherals/spimonitor/commands.rs b/target/ast10x0/peripherals/spimonitor/commands.rs index 40dbb86..1024cbf 100644 --- a/target/ast10x0/peripherals/spimonitor/commands.rs +++ b/target/ast10x0/peripherals/spimonitor/commands.rs
@@ -146,9 +146,9 @@ #[test] fn complete_zephyr_allow_list_is_supported() { let commands = [ - 0x03, 0x13, 0x0b, 0x0c, 0x6b, 0x6c, 0x01, 0x05, 0x35, 0x06, 0x04, 0x20, 0x21, - 0x9f, 0x5a, 0xb7, 0xe9, 0x32, 0x34, 0xd8, 0xdc, 0x02, 0x12, 0x3b, 0x3c, 0x70, - 0xbb, 0xbc, 0x50, 0xeb, 0xec, 0xc2, + 0x03, 0x13, 0x0b, 0x0c, 0x6b, 0x6c, 0x01, 0x05, 0x35, 0x06, 0x04, 0x20, 0x21, 0x9f, + 0x5a, 0xb7, 0xe9, 0x32, 0x34, 0xd8, 0xdc, 0x02, 0x12, 0x3b, 0x3c, 0x70, 0xbb, 0xbc, + 0x50, 0xeb, 0xec, 0xc2, ]; for command in commands { assert!(table_value(command, false).is_some());
diff --git a/target/ast10x0/peripherals/spimonitor/controller.rs b/target/ast10x0/peripherals/spimonitor/controller.rs index a6f80e9..e6fbbfd 100644 --- a/target/ast10x0/peripherals/spimonitor/controller.rs +++ b/target/ast10x0/peripherals/spimonitor/controller.rs
@@ -77,13 +77,12 @@ } } - let general_slot_limit = if policy.allow_commands[..policy.allow_command_count] - .contains(&0xc5) - { - LAST_GENERAL_COMMAND_SLOT_EXCLUSIVE - } else { - COMMAND_TABLE_SLOTS - }; + let general_slot_limit = + if policy.allow_commands[..policy.allow_command_count].contains(&0xc5) { + LAST_GENERAL_COMMAND_SLOT_EXCLUSIVE + } else { + COMMAND_TABLE_SLOTS + }; let mut general_command_count = 0usize; for opcode in policy.allow_commands[..policy.allow_command_count] .iter() @@ -165,11 +164,9 @@ /// Pulse the SPIPF software-reset bit for at least 5 microseconds. pub fn software_reset(&self) { - self.regs - .modify_ctrl(|bits| *bits |= CTRL_SW_RESET_BIT); + self.regs.modify_ctrl(|bits| *bits |= CTRL_SW_RESET_BIT); delay_cycles(SW_RESET_DELAY_CYCLES); - self.regs - .modify_ctrl(|bits| *bits &= !CTRL_SW_RESET_BIT); + self.regs.modify_ctrl(|bits| *bits &= !CTRL_SW_RESET_BIT); } } @@ -414,8 +411,7 @@ pub fn acknowledge_violations(&self) -> u32 { let pending = self.pending_violations(); if pending != 0 { - self.regs - .modify_ctrl2(|bits| *bits |= pending); + self.regs.modify_ctrl2(|bits| *bits |= pending); } pending } @@ -430,8 +426,7 @@ pub fn lock(self) -> Result<SpiMonitor<Locked>> { for slot in 0..COMMAND_TABLE_SLOTS { let value = self.regs.read_allow_cmd_slot(slot); - self.regs - .write_allow_cmd_slot(slot, value | COMMAND_LOCKED); + self.regs.write_allow_cmd_slot(slot, value | COMMAND_LOCKED); } self.regs @@ -592,11 +587,7 @@ regs.modify_ctrl(|bits| *bits = (*bits & 0x00ff_ffff) | selection); } -fn verify_command_slot( - regs: &SpiMonitorRegisters, - slot: usize, - expected: u32, -) -> Result<usize> { +fn verify_command_slot(regs: &SpiMonitorRegisters, slot: usize, expected: u32) -> Result<usize> { if regs.read_allow_cmd_slot(slot) != expected { return Err(SpiMonitorError::VerificationFailed); }
diff --git a/target/ast10x0/peripherals/spimonitor/mod.rs b/target/ast10x0/peripherals/spimonitor/mod.rs index 91e5540..4fb1175 100644 --- a/target/ast10x0/peripherals/spimonitor/mod.rs +++ b/target/ast10x0/peripherals/spimonitor/mod.rs
@@ -11,11 +11,11 @@ pub mod traits; pub mod types; +pub use commands::{descriptor as command_descriptor, table_value as command_table_value}; pub use controller::{ Configured, ConfiguredSpiMonitor, Locked, LockedSpiMonitor, SpiMonitor, UninitSpiMonitor, Uninitialized, }; -pub use commands::{descriptor as command_descriptor, table_value as command_table_value}; pub use policy::{MonitorPolicy, MAX_CMD_SLOTS, MAX_REGION_SLOTS}; pub use registers::{ SpiMonitorController, SpiMonitorRegisters, SPIPF1_BASE, SPIPF2_BASE, SPIPF3_BASE, SPIPF4_BASE,
diff --git a/target/ast10x0/peripherals/spimonitor/profile.rs b/target/ast10x0/peripherals/spimonitor/profile.rs index dd6290e..e3f35e3 100644 --- a/target/ast10x0/peripherals/spimonitor/profile.rs +++ b/target/ast10x0/peripherals/spimonitor/profile.rs
@@ -36,9 +36,9 @@ pub const fn zephyr_default() -> MonitorPolicy { let mut p = MonitorPolicy::empty(); p.allow_commands = [ - 0x03, 0x13, 0x0b, 0x0c, 0x6b, 0x6c, 0x01, 0x05, 0x35, 0x06, 0x04, 0x20, 0x21, 0x9f, - 0x5a, 0xb7, 0xe9, 0x32, 0x34, 0xd8, 0xdc, 0x02, 0x12, 0x3b, 0x3c, 0x70, 0xbb, 0xbc, - 0x50, 0xeb, 0xec, 0xc2, + 0x03, 0x13, 0x0b, 0x0c, 0x6b, 0x6c, 0x01, 0x05, 0x35, 0x06, 0x04, 0x20, 0x21, 0x9f, 0x5a, + 0xb7, 0xe9, 0x32, 0x34, 0xd8, 0xdc, 0x02, 0x12, 0x3b, 0x3c, 0x70, 0xbb, 0xbc, 0x50, 0xeb, + 0xec, 0xc2, ]; p.allow_command_count = p.allow_commands.len(); p
diff --git a/target/ast10x0/tests/smc/read/target_spi2.rs b/target/ast10x0/tests/smc/read/target_spi2.rs index 7901877..e340706 100644 --- a/target/ast10x0/tests/smc/read/target_spi2.rs +++ b/target/ast10x0/tests/smc/read/target_spi2.rs
@@ -8,9 +8,7 @@ use ast10x0_board::{apply_spim_external_mux, enable_flash_power}; #[allow(unused_imports)] use ast10x0_peripherals::scu::{ - pinctrl::{ - PINCTRL_SPI2_QUAD, PINCTRL_SPIM3_DEFAULT, PINCTRL_SPIM4_DEFAULT, - }, + pinctrl::{PINCTRL_SPI2_QUAD, PINCTRL_SPIM3_DEFAULT, PINCTRL_SPIM4_DEFAULT}, ScuExtMuxSelect, ScuRegisters, SpiMonitorInstance, SpiMonitorPassthrough, SpiMonitorSource, }; use ast10x0_peripherals::smc::{
diff --git a/target/ast10x0/tests/spimonitor/setup_all_spim.rs b/target/ast10x0/tests/spimonitor/setup_all_spim.rs index c94200e..75fed1b 100644 --- a/target/ast10x0/tests/spimonitor/setup_all_spim.rs +++ b/target/ast10x0/tests/spimonitor/setup_all_spim.rs
@@ -11,16 +11,15 @@ #[path = "test_common.rs"] mod test_common; -use test_common::TestConfig; use ast10x0_board::{ - apply_spim_external_mux, delay_us, enable_flash_power, set_bmc_resets, - spim_external_mux_state, + apply_spim_external_mux, delay_us, enable_flash_power, set_bmc_resets, spim_external_mux_state, }; use ast10x0_peripherals::scu::{ScuExtMuxSelect, ScuRegisters, SpiMonitorInstance}; use ast10x0_peripherals::spimonitor::{ MonitorPolicy, PrivilegeDirection, PrivilegeOp, SpiMonitorController, }; use target_common::{declare_target, TargetInterface}; +use test_common::TestConfig; use {console_backend as _, entry as _}; struct Spim1Config; @@ -61,9 +60,8 @@ const WRITE_PROTECTED_LENGTH: u32 = 0x0010_0000; const ALLOW_COMMANDS: [u8; 32] = [ - 0x03, 0x13, 0x0b, 0x0c, 0x6b, 0x6c, 0x01, 0x05, 0x35, 0x06, 0x04, 0x20, 0x21, 0x9f, 0x5a, - 0xb7, 0xe9, 0x32, 0x34, 0xd8, 0xdc, 0x02, 0x12, 0x3b, 0x3c, 0x70, 0xbb, 0xbc, 0x50, 0xeb, - 0xec, 0xc2, + 0x03, 0x13, 0x0b, 0x0c, 0x6b, 0x6c, 0x01, 0x05, 0x35, 0x06, 0x04, 0x20, 0x21, 0x9f, 0x5a, 0xb7, + 0xe9, 0x32, 0x34, 0xd8, 0xdc, 0x02, 0x12, 0x3b, 0x3c, 0x70, 0xbb, 0xbc, 0x50, 0xeb, 0xec, 0xc2, ]; fn log_buffer(log: &'static LogRam) -> &'static mut [u32] { @@ -110,7 +108,8 @@ &policy, )?; test_common::dump_policy(&spim1, WRITE_PROTECTED_LENGTH)?; - test_common::configure_passthrough::<Spim1Config>(&spim1)?; + test_common::validate_one_mib_write_protection(&spim1)?; + test_common::validate_filtering(&spim1)?; let _spim1 = test_common::lock_monitor(spim1)?; pw_log::info!("=== SPIM2 ==="); @@ -120,7 +119,8 @@ &policy, )?; test_common::dump_policy(&spim2, WRITE_PROTECTED_LENGTH)?; - test_common::configure_passthrough::<Spim2Config>(&spim2)?; + test_common::validate_one_mib_write_protection(&spim2)?; + test_common::validate_filtering(&spim2)?; let _spim2 = test_common::lock_monitor(spim2)?; pw_log::info!("=== SPIM3 ==="); @@ -130,7 +130,8 @@ &policy, )?; test_common::dump_policy(&spim3, WRITE_PROTECTED_LENGTH)?; - test_common::configure_passthrough::<Spim3Config>(&spim3)?; + test_common::validate_one_mib_write_protection(&spim3)?; + test_common::validate_filtering(&spim3)?; let _spim3 = test_common::lock_monitor(spim3)?; pw_log::info!("=== SPIM4 ==="); @@ -140,18 +141,18 @@ &policy, )?; test_common::dump_policy(&spim4, WRITE_PROTECTED_LENGTH)?; - test_common::configure_passthrough::<Spim4Config>(&spim4)?; + test_common::validate_one_mib_write_protection(&spim4)?; + test_common::validate_filtering(&spim4)?; let _spim4 = test_common::lock_monitor(spim4)?; - if scu.route_control_raw() & 0x0fff_0000 != 0x0f00_0000 { + if scu.route_control_raw() & 0x0fff_0000 != 0 { pw_log::info!( - "FAIL: final SPIPF reset routing: 0x{:08x}", + "FAIL: unexpected SCU flash-reset routing: 0x{:08x}", scu.route_control_raw() as u32 ); return Err(test_common::TestError::Check); } - pw_log::info!("All SPIM1-4 paths are configured in passthrough mode and locked"); - pw_log::info!("SPI clock frequency must be configured to 25 MHz by the external master"); + pw_log::info!("All SPIM1-4 monitors are filtering traffic and locked"); pw_log::info!( "SCU0F0 after SPIM setup: 0x{:08x}", scu.route_control_raw() as u32
diff --git a/target/ast10x0/tests/spimonitor/test_common.rs b/target/ast10x0/tests/spimonitor/test_common.rs index 9286ca4..aa85051 100644 --- a/target/ast10x0/tests/spimonitor/test_common.rs +++ b/target/ast10x0/tests/spimonitor/test_common.rs
@@ -7,9 +7,7 @@ use core::cell::UnsafeCell; -use ast10x0_board::{ - apply_spim_external_mux, apply_spim_pinctrl, delay_us, spim_external_mux_state, -}; +use ast10x0_board::{apply_spim_external_mux, apply_spim_pinctrl, spim_external_mux_state}; use ast10x0_peripherals::scu::{ ScuError, ScuExtMuxSelect, ScuRegisters, SpiMonitorInstance, SpiMonitorPassthrough, SpiMonitorSource, @@ -139,14 +137,6 @@ "FAIL: software reset did not deassert" ); - let scu = unsafe { ScuRegisters::new_global_unlocked() }; - scu.configure_spim_external_flash_reset(C::INSTANCE); - test_check!( - scu.is_spim_external_flash_reset_configured(C::INSTANCE), - "FAIL: SPIPF external flash reset routing readback" - ); - delay_us(5_000); - let configured = monitor.apply_policy(policy)?; test_check!( configured.state() == MonitorState::Configured, @@ -200,21 +190,36 @@ } #[allow(dead_code)] -pub fn configure_passthrough<C: TestConfig>( +pub fn validate_filtering(configured: &ConfiguredSpiMonitor) -> Result<(), TestError> { + test_check!( + configured.regs().read_ctrl() & 0x7 == 0x4, + "FAIL: SPIPF filtering mode readback" + ); + pw_log::info!("PASS: SPIPF filtering mode"); + Ok(()) +} + +#[allow(dead_code)] +pub fn validate_one_mib_write_protection( configured: &ConfiguredSpiMonitor, ) -> Result<(), TestError> { - configured.disable(); - configured.set_passthrough(PassthroughMode::Enabled); - - let scu = unsafe { ScuRegisters::new_global_unlocked() }; - scu.set_spim_passthrough(C::INSTANCE, SpiMonitorPassthrough::Enabled); - scu.set_spim_miso_multi_func(C::INSTANCE, false); - test_check!( - configured.regs().read_ctrl() & 0x7 == 0x1, - "FAIL: SPIPF passthrough mode readback" + configured.privilege_word(PrivilegeDirection::Read, 0)? == u32::MAX + && configured.privilege_word(PrivilegeDirection::Read, 1)? == u32::MAX + && configured.privilege_word(PrivilegeDirection::Read, 2)? == u32::MAX, + "FAIL: read privilege table is not unrestricted" ); - pw_log::info!("PASS: SPIPF single-bit passthrough mode"); + test_check!( + configured.privilege_word(PrivilegeDirection::Write, 0)? == 0 + && configured.privilege_word(PrivilegeDirection::Write, 1)? == 0, + "FAIL: first 1 MiB is not write protected" + ); + test_check!( + configured.privilege_word(PrivilegeDirection::Write, 2)? == u32::MAX, + "FAIL: writes at and above 0x00100000 are not enabled" + ); + pw_log::info!("PASS: reads allowed; writes below 0x00100000 blocked"); + pw_log::info!("PASS: writes at 0x00110000 allowed"); Ok(()) }