fdt_edit/node/view/
clock.rs1use core::ops::Deref;
4
5use alloc::{borrow::ToOwned, string::String, vec::Vec};
6use fdt_raw::Phandle;
7
8use super::NodeView;
9use crate::{NodeGeneric, NodeGenericMut, Property, ViewMutOp, ViewOp};
10
11#[derive(Clone, Debug, PartialEq)]
17pub enum ClockType {
18 Fixed(FixedClock),
20 Normal,
22}
23
24#[derive(Clone, Debug, PartialEq)]
28pub struct FixedClock {
29 pub name: Option<String>,
31 pub frequency: u32,
33 pub accuracy: Option<u32>,
35}
36
37#[derive(Clone, Debug)]
45pub struct ClockRef {
46 pub name: Option<String>,
48 pub phandle: Phandle,
50 pub cells: u32,
52 pub specifier: Vec<u32>,
55}
56
57impl ClockRef {
58 pub fn new(phandle: Phandle, cells: u32, specifier: Vec<u32>) -> Self {
60 Self {
61 name: None,
62 phandle,
63 cells,
64 specifier,
65 }
66 }
67
68 pub fn with_name(
70 name: Option<String>,
71 phandle: Phandle,
72 cells: u32,
73 specifier: Vec<u32>,
74 ) -> Self {
75 Self {
76 name,
77 phandle,
78 cells,
79 specifier,
80 }
81 }
82
83 pub fn select(&self) -> Option<u32> {
88 if self.cells > 0 {
89 self.specifier.first().copied()
90 } else {
91 None
92 }
93 }
94}
95
96#[derive(Clone, Copy)]
102pub struct ClockNodeView<'a> {
103 pub(super) inner: NodeGeneric<'a>,
104}
105
106impl<'a> Deref for ClockNodeView<'a> {
107 type Target = NodeGeneric<'a>;
108
109 fn deref(&self) -> &Self::Target {
110 &self.inner
111 }
112}
113
114impl<'a> ViewOp<'a> for ClockNodeView<'a> {
115 fn as_view(&self) -> NodeView<'a> {
116 self.inner.as_view()
117 }
118}
119
120impl<'a> ClockNodeView<'a> {
121 pub(crate) fn try_from_view(view: NodeView<'a>) -> Option<Self> {
122 if view.as_node().is_clock() {
123 Some(Self {
124 inner: NodeGeneric { inner: view },
125 })
126 } else {
127 None
128 }
129 }
130
131 pub fn clock_cells(&self) -> u32 {
133 self.as_view()
134 .as_node()
135 .get_property("#clock-cells")
136 .and_then(|prop| prop.get_u32())
137 .unwrap_or(0)
138 }
139
140 pub fn clock_output_names(&self) -> Vec<String> {
142 self.as_view()
143 .as_node()
144 .get_property("clock-output-names")
145 .map(|prop| prop.as_str_iter().map(|s| s.to_owned()).collect())
146 .unwrap_or_default()
147 }
148
149 pub fn output_name(&self, index: usize) -> Option<String> {
151 self.clock_output_names().get(index).cloned()
152 }
153
154 pub fn clock_type(&self) -> ClockType {
156 let node = self.as_view().as_node();
157
158 let is_fixed = node
160 .get_property("compatible")
161 .and_then(|prop| prop.as_str_iter().find(|&c| c == "fixed-clock"))
162 .is_some();
163
164 if is_fixed {
165 let frequency = node
166 .get_property("clock-frequency")
167 .and_then(|prop| prop.get_u32())
168 .unwrap_or(0);
169
170 let accuracy = node
171 .get_property("clock-accuracy")
172 .and_then(|prop| prop.get_u32());
173
174 let name = self.clock_output_names().first().cloned();
175
176 ClockType::Fixed(FixedClock {
177 name,
178 frequency,
179 accuracy,
180 })
181 } else {
182 ClockType::Normal
183 }
184 }
185}
186
187pub struct ClockNodeViewMut<'a> {
193 pub(super) inner: NodeGenericMut<'a>,
194}
195
196impl<'a> Deref for ClockNodeViewMut<'a> {
197 type Target = NodeGenericMut<'a>;
198
199 fn deref(&self) -> &Self::Target {
200 &self.inner
201 }
202}
203
204impl<'a> ViewOp<'a> for ClockNodeViewMut<'a> {
205 fn as_view(&self) -> NodeView<'a> {
206 self.inner.as_view()
207 }
208}
209
210impl<'a> ViewMutOp<'a> for ClockNodeViewMut<'a> {
211 fn new(node: NodeGenericMut<'a>) -> Self {
212 let mut s = Self { inner: node };
213 let n = s.inner.inner.as_node_mut();
214 n.set_property(Property::new("#clock-cells", (0u32).to_be_bytes().to_vec()));
216 s
217 }
218}
219
220impl<'a> ClockNodeViewMut<'a> {
221 pub(crate) fn try_from_view(view: NodeView<'a>) -> Option<Self> {
222 if view.as_node().is_clock() {
223 Some(Self {
224 inner: NodeGenericMut { inner: view },
225 })
226 } else {
227 None
228 }
229 }
230}