#![allow(non_camel_case_types, non_snake_case, clippy::upper_case_acronyms)]
use crate::{
gpio::ClkCfg,
system::{
glb::{self, *},
hbn::{
self, HBN_32K_CLK_Type, HBN_32K_Sel, HBN_Power_On_Xtal_32K, HBN_Set_XCLK_CLK_Sel,
HBN_XCLK_CLK_Type,
},
pds,
},
};
use embedded_time::rate::Hertz;
pub const BSP_FCLK_DIV: u8 = 0;
pub const BSP_BCLK_DIV: u8 = 1;
#[repr(C)]
pub enum system_clock_type {
SYSTEM_CLOCK_ROOT_CLOCK = 0,
SYSTEM_CLOCK_FCLK,
SYSTEM_CLOCK_BCLK,
SYSTEM_CLOCK_XCLK,
SYSTEM_CLOCK_32K_CLK,
SYSTEM_CLOCK_AUPLL,
}
pub const SYSFREQ: u32 = 144_000_000;
pub const XTAL_FREQ: u32 = 32_000_000;
pub const UART_PLL_FREQ: u32 = 96_000_000;
#[derive(PartialEq, Eq, Copy, Clone)]
#[repr(u32)]
pub enum SysclkFreq {
Pll144Mhz = 144_000_000,
}
#[derive(Clone, Copy)]
pub struct Clocks {
sysclk: Hertz,
uart_clk: Hertz,
}
impl Clocks {
pub fn new() -> Self {
Clocks {
sysclk: Hertz(SYSFREQ),
uart_clk: Hertz(UART_PLL_FREQ),
}
}
pub fn sysclk(&self) -> Hertz {
self.sysclk
}
pub const fn uart_clk(&self) -> Hertz {
self.uart_clk
}
}
impl Default for Clocks {
fn default() -> Self {
Self::new()
}
}
pub struct ClockConfig {
sysclk: SysclkFreq,
}
impl ClockConfig {
pub fn new() -> Self {
ClockConfig {
sysclk: SysclkFreq::Pll144Mhz,
}
}
pub fn freeze(self, _clk_cfg: &mut ClkCfg) -> Clocks {
let pll_enabled = true;
let sysclk = self.sysclk;
let uart_clk_div = 1;
unsafe { hbn::ptr() }
.hbn_glb
.modify(|_, w| w.hbn_uart_clk_sel().bit(pll_enabled));
unsafe { glb::ptr() }.clk_cfg2.modify(|_, w| unsafe {
w.uart_clk_div()
.bits(uart_clk_div - 1_u8)
.uart_clk_en()
.set_bit()
});
Clocks {
sysclk: Hertz(sysclk as u32),
uart_clk: Hertz(UART_PLL_FREQ),
}
}
}
impl Default for ClockConfig {
fn default() -> Self {
Self::new()
}
}
pub fn board_clock_init() {
system_clock_init();
peripheral_clock_init();
}
pub fn system_clock_init() {
GLB_Set_System_CLK(
GLB_DLL_XTAL_Type::GLB_DLL_XTAL_32M,
GLB_SYS_CLK_Type::GLB_SYS_CLK_DLL144M,
);
GLB_Set_System_CLK_Div(BSP_FCLK_DIV, BSP_BCLK_DIV);
GLB_Set_MTimer_CLK(
1,
GLB_MTIMER_CLK_Type::GLB_MTIMER_CLK_BCLK,
mtimer_get_clk_src_div() as u8,
);
HBN_Power_On_Xtal_32K();
HBN_32K_Sel(HBN_32K_CLK_Type::HBN_32K_XTAL);
HBN_Set_XCLK_CLK_Sel(HBN_XCLK_CLK_Type::HBN_XCLK_CLK_XTAL);
}
pub fn peripheral_clock_init() {
peripheral_clock_gate_all();
unsafe {
glb::ptr().cgen_cfg1.modify(|_, w| {
w.uart0().set_bit();
w.uart1().set_bit();
w
});
}
}
pub fn system_init() {
unsafe { riscv::interrupt::disable() };
let pds = unsafe { pds::ptr() };
let glb = unsafe { glb::ptr() };
let hbn = unsafe { hbn::ptr() };
let efuse0 = unsafe { &*bl702_pac::EF_DATA_0::ptr() };
pds.pds_int.modify(|_r, w| {
w.cr_pds_wake_int_mask().set_bit(); w.cr_pds_rf_done_int_mask().set_bit(); w.cr_pds_pll_done_int_mask().set_bit(); unsafe {
w.cr_pds_wakeup_src_en().bits(0);
}
w
});
glb.seam_misc.modify(|_r, w| unsafe { w.em_sel().bits(0) });
glb.glb_parm
.modify(|_r, w| unsafe { w.uart_swap_set().bits(0) });
if system_frequency() == 57 * 6000 * 1000 {
unsafe {
hbn.hbn_rsv2.write_with_zero(|w| {
w.hbn_rsv2().bits((57.6 * 1000.0 * 1000.0 + 0.5) as u32)
});
}
}
const CLIC_HART0_ADDR: usize = 0x02800000;
const CLIC_INTIP: usize = 0x000;
const CLIC_INTIE: usize = 0x400;
const IRQ_NUM_BASE: usize = 16;
const IRQ_QTY: usize = 64;
const IRQ_ITER_END: usize = (IRQ_NUM_BASE + IRQ_QTY + 2) / 4;
let clic_e = (CLIC_HART0_ADDR + CLIC_INTIE) as *mut usize;
for i in 0..IRQ_ITER_END {
unsafe { clic_e.wrapping_add(i).write_volatile(0) };
}
let clic_p = (CLIC_HART0_ADDR + CLIC_INTIP) as *mut usize;
for i in 0..IRQ_ITER_END {
unsafe { clic_p.wrapping_add(i).write_volatile(0) };
}
let fuse = efuse0.ef_key_slot_5_w2.read().ef_key_slot_5_w2().bits();
let flash_cfg = (fuse >> 26) & 7;
let psram_cfg = (fuse >> 24) & 3;
let is_internal_flash = flash_cfg == 1 || flash_cfg == 2;
let is_internal_psram = psram_cfg == 1;
glb.gpio_use_psram__io.modify(|_r, w| {
unsafe {
if is_internal_flash && !is_internal_psram {
w.bits(0x3f);
} else {
w.bits(0);
}
}
w
});
hbn.hbn_irq_mode.modify(|_r, w| {
w.irq_bor_en().clear_bit();
w
});
hbn.hbn_misc.modify(|_r, w| {
w.pu_bor().clear_bit();
w.bor_vth().set_bit();
w.bor_sel().clear_bit();
w
});
unsafe { riscv::interrupt::enable() };
}
pub fn system_frequency() -> u32 {
let hbn = unsafe { &*bl702_pac::HBN::ptr() };
hbn.hbn_rsv2.read().hbn_rsv2().bits()
}
fn mtimer_get_clk_src_div() -> u32 {
system_clock_get(system_clock_type::SYSTEM_CLOCK_BCLK) / 1000 / 1000 - 1
}
fn system_clock_get(t: system_clock_type) -> u32 {
let clksel = GLB_Get_Root_CLK_Sel();
match t {
system_clock_type::SYSTEM_CLOCK_ROOT_CLOCK => {
if clksel == GLB_ROOT_CLK_Type::GLB_ROOT_CLK_RC32M
|| clksel == GLB_ROOT_CLK_Type::GLB_ROOT_CLK_XTAL
{
32_000_000
} else {
let pll_sel = unsafe { glb::ptr().clk_cfg0.read().reg_pll_sel().bits() };
match pll_sel {
0 => 57_600_000,
1 => 96_000_000,
2 => 144_000_000,
_ => 0,
}
}
}
system_clock_type::SYSTEM_CLOCK_FCLK => {
system_clock_get(system_clock_type::SYSTEM_CLOCK_ROOT_CLOCK)
/ (GLB_Get_HCLK_Div() as u32 + 1)
}
system_clock_type::SYSTEM_CLOCK_BCLK => {
system_clock_get(system_clock_type::SYSTEM_CLOCK_ROOT_CLOCK)
/ (GLB_Get_HCLK_Div() as u32 + 1)
/ (GLB_Get_BCLK_Div() as u32 + 1)
}
system_clock_type::SYSTEM_CLOCK_XCLK => 32_000_000,
system_clock_type::SYSTEM_CLOCK_32K_CLK => 32_000,
system_clock_type::SYSTEM_CLOCK_AUPLL => 12_288_000,
}
}