forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 423
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
rust: add fwnode api to access unified device tree
Added abstraction APIs for accessing device's fwnode. Signed-off-by: Vinay Varma <[email protected]>
- Loading branch information
Showing
2 changed files
with
112 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
|
||
//! Unified device property interface. | ||
//! | ||
//! C header: [`include/linux/property.h`](../../../../include/linux/property.h) | ||
|
||
use crate::{bindings, device, sync::Arc}; | ||
use core::ptr::null_mut; | ||
|
||
fn next_endpoint(handle: &DeviceNode, curr: &Option<Arc<Node>>) -> Option<Arc<Node>> { | ||
let res_ptr = match curr { | ||
// SAFETY: By the type invariants, `handle` owns a reference, so it is safe to access `ptr` | ||
None => unsafe { | ||
bindings::fwnode_graph_get_next_endpoint( | ||
handle.ptr, | ||
null_mut::<bindings::fwnode_handle>(), | ||
) | ||
}, | ||
// SAFETY: By the type invariants, `handle` owns a reference, so it safe to access it's | ||
// `ptr`. `node` is a reference counted object (Arc) and hence its safe to access the | ||
// internal `ptr` | ||
Some(node) => unsafe { | ||
bindings::fwnode_graph_get_next_endpoint(handle.ptr, node.as_ref().ptr) | ||
}, | ||
}; | ||
if res_ptr.is_null() { | ||
None | ||
} else { | ||
Arc::try_new(Node { ptr: res_ptr }).ok() | ||
} | ||
} | ||
|
||
/// Represents the root `struct fwnode_handle *` associated to a device | ||
/// | ||
/// # Invariants | ||
/// | ||
/// The pointer is valid. | ||
pub struct DeviceNode { | ||
ptr: *mut bindings::fwnode_handle, | ||
} | ||
|
||
impl DeviceNode { | ||
/// Creates a new DeviceNode instance from an existing [`device::Device`] instance. | ||
pub fn from(dev: &device::Device) -> Self { | ||
Self { | ||
// SAFETY: By the type invariants, `dev` owns a reference, so it is safe to access | ||
// `ptr` | ||
ptr: unsafe { bindings::dev_fwnode(dev.ptr) }, | ||
} | ||
} | ||
/// Creates an instance of `NodeIterator` | ||
/// | ||
/// This provides an `Iterator` wrapping the internal C functionality of invoking | ||
/// `fwnode_graph_get_next_endpoint` | ||
pub fn endpoints(self) -> NodeIterator { | ||
NodeIterator { | ||
handle: self, | ||
curr_node: None, | ||
iter_fn: next_endpoint, | ||
} | ||
} | ||
} | ||
|
||
// SAFETY: `DeviceNode` only holds a pointer to a C fwnode_handle, which is safe to be used from any thread. | ||
unsafe impl Send for DeviceNode {} | ||
|
||
// SAFETY: `DeviceNode` only holds a pointer to a C fwnode_handle, references to which are safe to be used | ||
// from any thread. | ||
unsafe impl Sync for DeviceNode {} | ||
impl Drop for DeviceNode { | ||
fn drop(&mut self) { | ||
// SAFETY: By the type invariants, `self` owns a reference, so it is safe to | ||
// relinquish it now. | ||
unsafe { bindings::fwnode_handle_put(self.ptr) } | ||
} | ||
} | ||
|
||
/// Represents a `struct fwnode_handle *` part of a device's fwnode graph | ||
/// | ||
/// # Invariants | ||
/// | ||
/// The pointer is valid. | ||
pub struct Node { | ||
pub(crate) ptr: *mut bindings::fwnode_handle, | ||
} | ||
|
||
impl Drop for Node { | ||
fn drop(&mut self) { | ||
// SAFETY: By the type invariants, `self` owns a reference, so it is safe to | ||
// relinquish it now. | ||
unsafe { bindings::fwnode_handle_put(self.ptr) } | ||
} | ||
} | ||
|
||
/// A function that optionally returns a `Node` given the `parent` and `prev` | ||
type NodeIteratorFn = fn(parent: &DeviceNode, prev: &Option<Arc<Node>>) -> Option<Arc<Node>>; | ||
|
||
/// Implements the Iterator trait to iterate the device's fwnode graph given the `DeviceNode` and a `NodeIteratorFn` | ||
pub struct NodeIterator { | ||
handle: DeviceNode, | ||
curr_node: Option<Arc<Node>>, | ||
iter_fn: NodeIteratorFn, | ||
} | ||
impl Iterator for NodeIterator { | ||
type Item = Arc<Node>; | ||
|
||
fn next(&mut self) -> Option<Self::Item> { | ||
self.curr_node = (self.iter_fn)(&self.handle, &self.curr_node); | ||
self.curr_node.clone() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters