#![allow(dead_code)]
use tock_registers::{register_bitfields, register_structs, registers::ReadWrite};
use crate::rstc::{Rstc, RSTC_BASE};
pub use crate::soc::SEC_SYS_BASE;
register_bitfields! [
u32,
pub SEC_SYS_CTRL [
SEC_CPU_EN OFFSET(13) NUMBITS(1) []
],
pub SEC_SYS_BOOT_ADDR_L [
ADDR_L OFFSET(0) NUMBITS(32) []
],
pub SEC_SYS_BOOT_ADDR_H [
ADDR_H OFFSET(0) NUMBITS(32) []
]
];
register_structs! {
pub SecSysRegisters {
(0x000 => _reserved0),
(0x004 => pub ctrl: ReadWrite<u32, SEC_SYS_CTRL::Register>),
(0x008 => _reserved1),
(0x020 => pub boot_addr_l: ReadWrite<u32, SEC_SYS_BOOT_ADDR_L::Register>),
(0x024 => pub boot_addr_h: ReadWrite<u32, SEC_SYS_BOOT_ADDR_H::Register>),
(0x028 => @END),
}
}
pub struct SecSys {
regs: &'static SecSysRegisters,
}
impl SecSys {
pub unsafe fn new(base: usize) -> Self {
unsafe {
Self {
regs: &*(base as *const SecSysRegisters),
}
}
}
pub fn enable_secondary_cpu(&self) {
use tock_registers::interfaces::ReadWriteable;
self.regs.ctrl.modify(SEC_SYS_CTRL::SEC_CPU_EN::SET);
}
pub fn disable_secondary_cpu(&self) {
use tock_registers::interfaces::ReadWriteable;
self.regs.ctrl.modify(SEC_SYS_CTRL::SEC_CPU_EN::CLEAR);
}
pub fn is_secondary_cpu_enabled(&self) -> bool {
use tock_registers::interfaces::Readable;
self.regs.ctrl.is_set(SEC_SYS_CTRL::SEC_CPU_EN)
}
pub fn set_boot_address(&self, addr: u64) {
use tock_registers::interfaces::Writeable;
self.regs
.boot_addr_l
.write(SEC_SYS_BOOT_ADDR_L::ADDR_L.val(addr as u32));
self.regs
.boot_addr_h
.write(SEC_SYS_BOOT_ADDR_H::ADDR_H.val((addr >> 32) as u32));
}
pub fn get_boot_address(&self) -> u64 {
use tock_registers::interfaces::Readable;
let low = self.regs.boot_addr_l.read(SEC_SYS_BOOT_ADDR_L::ADDR_L) as u64;
let high = self.regs.boot_addr_h.read(SEC_SYS_BOOT_ADDR_H::ADDR_H) as u64;
(high << 32) | low
}
pub unsafe fn start_secondary_core(&self, entry: u64) {
unsafe {
let rstc = Rstc::new(RSTC_BASE);
rstc.assert_cpu_sys_reset(2);
self.enable_secondary_cpu();
self.set_boot_address(entry);
#[cfg(target_arch = "riscv64")]
{
core::arch::asm!("fence.i");
}
#[cfg(target_arch = "riscv32")]
{
core::arch::asm!("fence.i");
}
#[cfg(not(any(target_arch = "riscv64", target_arch = "riscv32")))]
{
core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst);
}
rstc.release_cpu_sys_reset(2);
#[cfg(target_arch = "riscv64")]
{
core::arch::asm!("fence.i");
}
#[cfg(target_arch = "riscv32")]
{
core::arch::asm!("fence.i");
}
#[cfg(not(any(target_arch = "riscv64", target_arch = "riscv32")))]
{
core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst);
}
}
}
pub fn regs(&self) -> &'static SecSysRegisters {
self.regs
}
}