Files
yggdrasil/kernel/lib/device-tree/src/driver/mod.rs
T

85 lines
2.5 KiB
Rust

//! Device tree-based driver definitions
use alloc::sync::Arc;
use device_api::gpio::GpioPinLevel;
use yggdrasil_abi::error::Error;
mod controller;
mod macros;
mod registry;
mod syscon;
mod traits;
mod tree;
pub mod util;
pub use controller::{map_interrupt, map_interrupt_at};
pub use macros::device_tree_driver;
pub use registry::{lookup_phandle, register_driver};
pub use syscon::DeviceTreeSyscon;
pub use traits::{
DeviceTreeClockController, DeviceTreeInterruptController, DeviceTreePinController,
DeviceTreeResetController, Driver, ProbeContext,
};
pub use tree::{find_node, unflatten_device_tree, walk_device_tree, Node};
/// Contextual information about a GPIO pin being configured
pub struct DeviceTreeGpioPins {
/// Whether to enable input on the pin
pub input: bool,
/// Whether to enable output on the pin
pub output: bool,
/// Initial level to configure the GPIO with
pub initial_level: GpioPinLevel,
}
/// Specifies initialization sequence requirement for a driver
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum InitSequence {
/// Driver can be initialized during early boot
Early = 1,
/// Driver must be initialized when sleep function is available
Late = 2,
}
/// Performs a walk of the device tree and initializes nodes which haven't already been
/// initialized/probed.
///
/// Reports successful initializations via `success_handler` and
/// failures via `error_handler`.
pub fn lazy_init<S: Fn(&Arc<Node>), F: Fn(&Arc<Node>, Error)>(
success_handler: S,
error_handler: F,
sequence: InitSequence,
) {
walk_device_tree::<(), _>(|node| {
match node.clone().lazy_init(sequence) {
Some(Ok(())) => success_handler(node),
Some(Err(error)) => error_handler(node, error),
None => (),
}
None
});
}
/// Performs a walk of the device and initializes IRQs for nodes. Additionally performs lazy
/// initialization (if need to enable IRQs, but a device is not initialized).
///
/// Reports successful initializations via `success_handler` and
/// failures via `error_handler`.
pub fn init_irqs<S: Fn(&Arc<Node>), F: Fn(&Arc<Node>, Error)>(
success_handler: S,
error_handler: F,
sequence: InitSequence,
) {
walk_device_tree::<(), _>(|node| {
match node.clone().init_irqs(sequence) {
Some(Ok(())) => success_handler(node),
Some(Err(error)) => error_handler(node, error),
None => (),
}
None
});
}