Skip to content

Commit

Permalink
refac(D1): move spin delay from ccu to clint (#305)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
hawkw authored Jan 21, 2024
1 parent 563cb0f commit beb463f
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 35 deletions.
58 changes: 25 additions & 33 deletions platforms/allwinner-d1/d1-core/src/ccu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand All @@ -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 {
Expand All @@ -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<MODULE: BusGatingResetRegister>(&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);
}

Expand Down Expand Up @@ -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) {
Expand All @@ -130,7 +122,7 @@ impl Ccu {
w.div_cfg().variant(1);
w
});
sdelay(1);
Clint::spin_delay_us(1);

// Disable PLL gating
self.ccu
Expand All @@ -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| {
Expand All @@ -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
Expand All @@ -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.
Expand All @@ -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) {
Expand All @@ -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
Expand All @@ -227,21 +219,21 @@ 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) {
// This could potentially be done in a single write, but we follow
// 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();
Expand Down
15 changes: 13 additions & 2 deletions platforms/allwinner-d1/d1-core/src/clint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit beb463f

Please sign in to comment.