syscon_rs/
lib.rs

1#![no_std]
2#![feature(pointer_byte_offsets)]
3#![feature(never_type)]
4
5use log::{log, Level};
6
7static mut MMIO: mmio::VolBox<u32, mmio::Deny, mmio::Allow> = unsafe {mmio::VolBox::new(core::ptr::null_mut())};
8static mut OFF: u32 = 0;
9static mut REBOOT: u32 = 0;
10
11pub fn init(fdt_ptr: *const u8) ->  Option<()> {
12    unsafe {
13        let fdt = fdt::Fdt::from_ptr(fdt_ptr).expect("Invalid Fdt pointer");
14
15        let node = fdt.find_compatible(&["syscon-poweroff"])?;
16        let offset = node.property("offset")?.as_usize()?;
17        OFF = node.property("value")?.as_usize()? as u32;
18
19        let node = fdt.find_compatible(&["syscon-reboot"])?;
20        let offset = node.property("offset")?.as_usize()?;
21        REBOOT = node.property("value")?.as_usize()? as u32;
22
23        let syscon_phandle = node.property("regmap")?.as_usize()? as u32;
24        let syscon_node = fdt.find_phandle(syscon_phandle)?;
25        let syscon_mmio = syscon_node.reg()?.next()?.starting_address.cast::<u32>().cast_mut();
26
27        let mmio: mmio::VolBox<u32, mmio::Deny, mmio::Allow> = mmio::VolBox::new(syscon_mmio);
28
29        MMIO = mmio;
30    }
31
32    Some(())
33}
34
35pub fn power_off() -> ! {
36    log!(Level::Info, "Power off requested");
37
38    unsafe {
39        MMIO.write(OFF);
40    }
41
42    unreachable!("ERROR OCCURED WHILE POWERING OFF");
43}
44
45pub fn reboot() -> ! {
46    log!(Level::Info, "Reboot requested");
47    
48    unsafe {
49        MMIO.write(REBOOT);
50    }
51
52    unreachable!("ERROR OCCURED WHILE REBOOTING");
53}