1use core::ops::Deref;
2
3use alloc::{
4 string::{String, ToString},
5 vec::Vec,
6};
7use fdt_raw::Phandle;
8
9use crate::node::gerneric::NodeRefGen;
10
11#[derive(Clone, Debug, PartialEq)]
13pub enum ClockType {
14 Fixed(FixedClock),
16 Normal,
18}
19
20#[derive(Clone, Debug, PartialEq)]
22pub struct FixedClock {
23 pub name: Option<String>,
24 pub frequency: u32,
26 pub accuracy: Option<u32>,
28}
29
30#[derive(Clone, Debug)]
38pub struct ClockRef {
39 pub name: Option<String>,
41 pub phandle: Phandle,
43 pub cells: u32,
45 pub specifier: Vec<u32>,
48}
49
50impl ClockRef {
51 pub fn new(phandle: Phandle, cells: u32, specifier: Vec<u32>) -> Self {
53 Self {
54 name: None,
55 phandle,
56 cells,
57 specifier,
58 }
59 }
60
61 pub fn with_name(
63 name: Option<String>,
64 phandle: Phandle,
65 cells: u32,
66 specifier: Vec<u32>,
67 ) -> Self {
68 Self {
69 name,
70 phandle,
71 cells,
72 specifier,
73 }
74 }
75
76 pub fn select(&self) -> Option<u32> {
81 if self.cells > 0 {
82 self.specifier.first().copied()
83 } else {
84 None
85 }
86 }
87}
88
89#[derive(Clone)]
91pub struct NodeRefClock<'a> {
92 pub node: NodeRefGen<'a>,
93 pub clock_output_names: Vec<String>,
94 pub clock_cells: u32,
95 pub kind: ClockType,
96}
97
98impl<'a> NodeRefClock<'a> {
99 pub fn try_from(node: NodeRefGen<'a>) -> Result<Self, NodeRefGen<'a>> {
100 if node.find_property("#clock-cells").is_none() {
102 return Err(node);
103 }
104
105 let clock_output_names = if let Some(prop) = node.find_property("clock-output-names") {
107 let iter = prop.as_str_iter();
108 iter.map(|s| s.to_string()).collect()
109 } else {
110 Vec::new()
111 };
112
113 let clock_cells = node
115 .find_property("#clock-cells")
116 .and_then(|prop| prop.get_u32())
117 .unwrap_or(0);
118
119 let kind = if node.compatibles().any(|c| c == "fixed-clock") {
121 let frequency = node
122 .find_property("clock-frequency")
123 .and_then(|prop| prop.get_u32())
124 .unwrap_or(0);
125 let accuracy = node
126 .find_property("clock-accuracy")
127 .and_then(|prop| prop.get_u32());
128 let name = clock_output_names.first().cloned();
129
130 ClockType::Fixed(FixedClock {
131 name,
132 frequency,
133 accuracy,
134 })
135 } else {
136 ClockType::Normal
137 };
138
139 Ok(Self {
140 node,
141 clock_output_names,
142 clock_cells,
143 kind,
144 })
145 }
146
147 pub fn output_name(&self, index: usize) -> Option<&str> {
149 self.clock_output_names.get(index).map(|s| s.as_str())
150 }
151
152 pub fn clocks(&self) -> Vec<ClockRef> {
157 let Some(prop) = self.find_property("clocks") else {
158 return Vec::new();
159 };
160
161 let mut clocks = Vec::new();
162 let mut data = prop.as_reader();
163 let mut index = 0;
164
165 let clock_names = if let Some(prop) = self.find_property("clock-names") {
167 let iter = prop.as_str_iter();
168 iter.map(|s| s.to_string()).collect()
169 } else {
170 Vec::new()
171 };
172
173 while let Some(phandle_raw) = data.read_u32() {
174 let phandle = Phandle::from(phandle_raw);
175
176 let clock_cells = if let Some(provider) = self.ctx.find_by_phandle(phandle) {
178 provider
179 .get_property("#clock-cells")
180 .and_then(|p| p.get_u32())
181 .unwrap_or(1) } else {
183 1 };
185
186 let mut specifier = Vec::with_capacity(clock_cells as usize);
188 let mut complete = true;
189 for _ in 0..clock_cells {
190 if let Some(val) = data.read_u32() {
191 specifier.push(val);
192 } else {
193 complete = false;
195 break;
196 }
197 }
198
199 if !complete {
201 break;
202 }
203
204 let name = clock_names.get(index).cloned();
206
207 clocks.push(ClockRef::with_name(name, phandle, clock_cells, specifier));
208 index += 1;
209 }
210
211 clocks
212 }
213}
214
215impl<'a> Deref for NodeRefClock<'a> {
216 type Target = NodeRefGen<'a>;
217
218 fn deref(&self) -> &Self::Target {
219 &self.node
220 }
221}