use sbi_spec::binary::SbiRet;
pub trait Reset: Send + Sync {
fn system_reset(&self, reset_type: u32, reset_reason: u32) -> SbiRet;
#[cfg(feature = "legacy")]
fn legacy_reset(&self) -> ! {
use sbi_spec::srst::{RESET_REASON_NO_REASON, RESET_TYPE_SHUTDOWN};
self.system_reset(RESET_TYPE_SHUTDOWN, RESET_REASON_NO_REASON);
unreachable!()
}
}
impl<T: Reset> Reset for &T {
#[inline]
fn system_reset(&self, reset_type: u32, reset_reason: u32) -> SbiRet {
T::system_reset(self, reset_type, reset_reason)
}
#[cfg(feature = "legacy")]
#[inline]
fn legacy_reset(&self) -> ! {
T::legacy_reset(self)
}
}
#[cfg(feature = "singleton")]
use crate::util::AmoOnceRef;
#[cfg(feature = "singleton")]
static RESET: AmoOnceRef<dyn Reset> = AmoOnceRef::new();
#[cfg(feature = "singleton")]
pub fn init_reset(reset: &'static dyn Reset) {
if !RESET.try_call_once(reset) {
panic!("load sbi module when already loaded")
}
}
#[cfg(feature = "singleton")]
#[inline]
pub(crate) fn probe_reset() -> bool {
RESET.get().is_some()
}
#[cfg(feature = "singleton")]
#[inline]
pub(crate) fn system_reset(reset_type: u32, reset_reason: u32) -> SbiRet {
if let Some(obj) = RESET.get() {
return obj.system_reset(reset_type, reset_reason);
}
SbiRet::not_supported()
}
#[cfg(all(feature = "singleton", feature = "legacy"))]
#[inline]
pub(crate) fn legacy_reset() -> ! {
if let Some(obj) = RESET.get() {
obj.legacy_reset()
}
unreachable!("no reset handler available; this is okay if your platform didn't declare a legacy reset handler")
}