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 {