Skip to main content

fdt_edit/node/view/
intc.rs

1//! Interrupt controller node view specialization.
2
3use core::ops::Deref;
4
5use alloc::{
6    string::{String, ToString},
7    vec::Vec,
8};
9
10use fdt_raw::Phandle;
11
12use super::NodeView;
13use crate::{NodeGeneric, NodeGenericMut, Property, ViewMutOp, ViewOp};
14
15/// Interrupt reference, used to parse the `interrupts` property.
16#[derive(Clone, Debug, PartialEq, Eq)]
17pub struct InterruptRef {
18    /// Optional interrupt name from `interrupt-names`.
19    pub name: Option<String>,
20    /// Effective interrupt parent controller phandle.
21    pub interrupt_parent: Phandle,
22    /// Provider `#interrupt-cells` value used to parse the specifier.
23    pub cells: u32,
24    /// Raw interrupt specifier cells.
25    pub specifier: Vec<u32>,
26}
27
28impl InterruptRef {
29    /// Creates a named interrupt reference.
30    pub fn with_name(
31        name: Option<String>,
32        interrupt_parent: Phandle,
33        cells: u32,
34        specifier: Vec<u32>,
35    ) -> Self {
36        Self {
37            name,
38            interrupt_parent,
39            cells,
40            specifier,
41        }
42    }
43}
44
45// ---------------------------------------------------------------------------
46// IntcNodeView
47// ---------------------------------------------------------------------------
48
49/// Specialized view for interrupt controller nodes.
50#[derive(Clone, Copy)]
51pub struct IntcNodeView<'a> {
52    pub(super) inner: NodeGeneric<'a>,
53}
54
55impl<'a> ViewOp<'a> for IntcNodeView<'a> {
56    fn as_view(&self) -> NodeView<'a> {
57        self.inner.as_view()
58    }
59}
60
61impl<'a> Deref for IntcNodeView<'a> {
62    type Target = NodeGeneric<'a>;
63    fn deref(&self) -> &Self::Target {
64        &self.inner
65    }
66}
67
68impl<'a> IntcNodeView<'a> {
69    pub(crate) fn try_from_view(view: NodeView<'a>) -> Option<Self> {
70        if view.as_node().is_interrupt_controller() {
71            Some(Self {
72                inner: NodeGeneric { inner: view },
73            })
74        } else {
75            None
76        }
77    }
78
79    /// Returns the `#interrupt-cells` property value.
80    pub fn interrupt_cells(&self) -> Option<u32> {
81        self.as_view().as_node().interrupt_cells()
82    }
83
84    /// Returns the `#address-cells` property value used by `interrupt-map`.
85    pub fn interrupt_address_cells(&self) -> Option<u32> {
86        self.as_view().as_node().address_cells()
87    }
88
89    /// This is always `true` for `IntcNodeView` (type-level guarantee).
90    pub fn is_interrupt_controller(&self) -> bool {
91        true
92    }
93
94    /// Returns all compatible strings as owned values.
95    pub fn compatibles(&self) -> Vec<String> {
96        self.as_view()
97            .as_node()
98            .compatibles()
99            .map(|s| s.to_string())
100            .collect()
101    }
102}
103
104// ---------------------------------------------------------------------------
105// IntcNodeViewMut
106// ---------------------------------------------------------------------------
107
108/// Mutable view for interrupt controller nodes.
109pub struct IntcNodeViewMut<'a> {
110    pub(super) inner: NodeGenericMut<'a>,
111}
112
113impl<'a> ViewOp<'a> for IntcNodeViewMut<'a> {
114    fn as_view(&self) -> NodeView<'a> {
115        self.inner.as_view()
116    }
117}
118
119impl<'a> ViewMutOp<'a> for IntcNodeViewMut<'a> {
120    fn new(node: NodeGenericMut<'a>) -> Self {
121        let mut s = Self { inner: node };
122        let n = s.inner.inner.as_node_mut();
123        n.set_property(Property::new("interrupt-controller", Vec::new()));
124        s
125    }
126}
127
128impl<'a> Deref for IntcNodeViewMut<'a> {
129    type Target = NodeGenericMut<'a>;
130    fn deref(&self) -> &Self::Target {
131        &self.inner
132    }
133}
134
135impl<'a> IntcNodeViewMut<'a> {
136    pub(crate) fn try_from_view(view: NodeView<'a>) -> Option<Self> {
137        if view.as_node().is_interrupt_controller() {
138            Some(Self {
139                inner: NodeGenericMut { inner: view },
140            })
141        } else {
142            None
143        }
144    }
145}