85 lines
2.5 KiB
Rust
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
|
|
});
|
|
}
|