From beb463fde95cd3bba28b2a5d45c5f54cac9574dd Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Sat, 20 Jan 2024 17:02:43 -0800 Subject: [PATCH] refac(D1): move spin delay from `ccu` to `clint` (#305) This branch addresses a minor TODO in the `ccu` module, by moving the spin delay function from the `ccu` module into a function on the `Clint` type. Additionally, I've removed the `&self` receiver from `Clint::get_mtime`, since we don't actually use the `&self`. This lets us change `get_mtime` to a free function, and therefore remove the `unsafe` calls to `Clint::summon()` in a few places, so we can get rid of a few unneeded `unsafe` blocks. --- platforms/allwinner-d1/d1-core/src/ccu.rs | 58 +++++++++------------ platforms/allwinner-d1/d1-core/src/clint.rs | 15 +++++- 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/platforms/allwinner-d1/d1-core/src/ccu.rs b/platforms/allwinner-d1/d1-core/src/ccu.rs index 485f5b69..4addb51a 100644 --- a/platforms/allwinner-d1/d1-core/src/ccu.rs +++ b/platforms/allwinner-d1/d1-core/src/ccu.rs @@ -14,6 +14,8 @@ use d1_pac::{SPI0, SPI_DBI}; use d1_pac::{TWI0, TWI1, TWI2, TWI3}; use d1_pac::{UART0, UART1, UART2, UART3, UART4, UART5}; +use crate::clint::Clint; + pub struct Ccu { ccu: CCU, } @@ -38,16 +40,6 @@ pub trait BusGatingResetRegister { fn reset(ccu: &mut CCU, reset: BusReset); } -// TODO: should this move into the `Clint`? -fn sdelay(delay_us: usize) { - let clint = unsafe { crate::clint::Clint::summon() }; - let t = clint.get_mtime(); - // TODO: verify that mtime sourced directly from DXCO (24 MHz) - while clint.get_mtime() < (t + 24 * delay_us) { - core::hint::spin_loop() - } -} - impl Ccu { #[must_use] pub fn new(ccu: CCU) -> Self { @@ -62,7 +54,7 @@ impl Ccu { /// De-assert the reset bit and enable the clock gating bit for the given module pub fn enable_module(&mut self, _mod: &mut MODULE) { MODULE::reset(&mut self.ccu, BusReset::Deassert); - sdelay(20); + Clint::spin_delay_us(20); MODULE::gating(&mut self.ccu, BusGating::Pass); } @@ -93,32 +85,32 @@ impl Ccu { self.set_mbus(); macro_rules! set_module { - ($self: ident, $module: ident) => { - if ($self.ccu.$module.read().pll_en().bit_is_clear()) { - $self.ccu.$module.modify(|_, w| { + ($module: ident) => { + if (self.ccu.$module.read().pll_en().bit_is_clear()) { + self.ccu.$module.modify(|_, w| { w.pll_ldo_en().enable(); w.pll_en().enable(); w }); - $self.ccu.$module.modify(|_, w| w.lock_enable().enable()); + self.ccu.$module.modify(|_, w| w.lock_enable().enable()); - while $self.ccu.$module.read().lock().bit_is_clear() { + while self.ccu.$module.read().lock().bit_is_clear() { core::hint::spin_loop(); } - sdelay(20); + Clint::spin_delay_us(20); - $self.ccu.$module.modify(|_, w| w.lock_enable().disable()); + self.ccu.$module.modify(|_, w| w.lock_enable().disable()); } }; } - set_module!(self, pll_peri_ctrl); - set_module!(self, pll_video0_ctrl); - set_module!(self, pll_video1_ctrl); - set_module!(self, pll_ve_ctrl); - set_module!(self, pll_audio0_ctrl); - set_module!(self, pll_audio1_ctrl); + set_module!(pll_peri_ctrl); + set_module!(pll_video0_ctrl); + set_module!(pll_video1_ctrl); + set_module!(pll_ve_ctrl); + set_module!(pll_audio0_ctrl); + set_module!(pll_audio1_ctrl); } fn set_pll_cpux_axi(&mut self) { @@ -130,7 +122,7 @@ impl Ccu { w.div_cfg().variant(1); w }); - sdelay(1); + Clint::spin_delay_us(1); // Disable PLL gating self.ccu @@ -139,7 +131,7 @@ impl Ccu { // Enable PLL LDO self.ccu.pll_cpu_ctrl.modify(|_, w| w.pll_ldo_en().enable()); - sdelay(5); + Clint::spin_delay_us(5); // Set default clock to 1008 MHz self.ccu.pll_cpu_ctrl.modify(|r, w| { @@ -162,7 +154,7 @@ impl Ccu { while self.ccu.pll_cpu_ctrl.read().lock().bit_is_clear() { core::hint::spin_loop(); } - sdelay(20); + Clint::spin_delay_us(20); // Enable PLL gating self.ccu @@ -173,7 +165,7 @@ impl Ccu { self.ccu .pll_cpu_ctrl .modify(|_, w| w.lock_enable().disable()); - sdelay(1); + Clint::spin_delay_us(1); // Change the CPU clock source to PLL_CPU. // Sets the RISC-V clock to 1008 MHz and the RISC-V AXI clock to 504 MHz. @@ -183,7 +175,7 @@ impl Ccu { w.div_cfg().variant(0); w }); - sdelay(1); + Clint::spin_delay_us(1); } fn set_pll_periph0(&mut self) { @@ -210,7 +202,7 @@ impl Ccu { while self.ccu.pll_peri_ctrl.read().lock().bit_is_clear() { core::hint::spin_loop(); } - sdelay(20); + Clint::spin_delay_us(20); // Unlock the PLL self.ccu @@ -227,7 +219,7 @@ impl Ccu { self.ccu .psi_clk .modify(|_, w| w.clk_src_sel().pll_peri_1x()); - sdelay(1); + Clint::spin_delay_us(1); } fn set_apb(&mut self) { @@ -235,13 +227,13 @@ impl Ccu { // the `xboot` implementation which also splits this in 2 operations. self.ccu.apb_clk[0].write(|w| w.factor_m().variant(2).factor_n().n2()); self.ccu.apb_clk[0].modify(|_, w| w.clk_src_sel().pll_peri_1x()); - sdelay(1); + Clint::spin_delay_us(1); } fn set_mbus(&mut self) { // Reset the MBUS domain self.ccu.mbus_clk.modify(|_, w| w.mbus_rst().deassert()); - sdelay(1); + Clint::spin_delay_us(1); // Enable MBUS master clock gating self.ccu.mbus_mat_clk_gating.write(|w| { w.dma_mclk_en().pass(); diff --git a/platforms/allwinner-d1/d1-core/src/clint.rs b/platforms/allwinner-d1/d1-core/src/clint.rs index 71575cce..fccdeaef 100644 --- a/platforms/allwinner-d1/d1-core/src/clint.rs +++ b/platforms/allwinner-d1/d1-core/src/clint.rs @@ -34,15 +34,26 @@ impl Clint { } } + /// Spin until `delay_us` microseconds have elapsed (as determined by + /// [`Self::get_mtime`]). + // TODO: should this move into the `Clint`? + pub(crate) fn spin_delay_us(delay_us: usize) { + let t = Self::get_mtime(); + // TODO: verify that mtime sourced directly from DXCO (24 MHz) + while Self::get_mtime() < (t + 24 * delay_us) { + core::hint::spin_loop() + } + } + /// Get the (machine) time value. #[cfg(not(any(target_arch = "riscv64", target_arch = "riscv32")))] - pub fn get_mtime(&self) -> usize { + pub fn get_mtime() -> usize { unimplemented!("called `Clint::get_mtime` on a non-RISC-V architecture, this shouldn't happen while running host tests!") } /// Get the (machine) time value. #[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))] - pub fn get_mtime(&self) -> usize { + pub fn get_mtime() -> usize { // Note that the CLINT of the C906 core does not implement // the `mtime` register and we need to get the time value // with a CSR, which the `riscv` crate implements for us.