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}