fdt_parser/cache/node/
clock.rs

1use core::ops::Deref;
2
3use crate::{cache::node::NodeBase, Phandle};
4use alloc::{string::String, string::ToString, vec::Vec};
5
6#[derive(Clone, Debug)]
7pub struct ClockInfo {
8    /// Name supplied by the consumer through `clock-names`
9    pub name: Option<String>,
10    /// Name exposed by the provider via `clock-output-names` that matches the specifier
11    pub provider_output_name: Option<String>,
12
13    pub phandle: Phandle,
14    pub select: u64,
15    /// Provider details
16    pub provider: ClockType,
17}
18
19impl ClockInfo {
20    /// Helper access to the provider node
21    pub fn provider_name(&self) -> &str {
22        self.provider.name()
23    }
24
25    /// Number of cells defined by the provider for each specifier
26    pub fn provider_clock_cells(&self) -> u32 {
27        self.provider.clock_cells()
28    }
29}
30
31#[derive(Clone, Debug)]
32pub enum ClockType {
33    Fixed(FixedClock),
34    Provider(Clock),
35}
36
37impl ClockType {
38    pub(super) fn new(node: NodeBase) -> Self {
39        let base = Clock::from_node(node.clone());
40        let compatibles = node.compatibles();
41        if compatibles.iter().any(|c| c == "fixed-clock") {
42            ClockType::Fixed(FixedClock {
43                clock: base,
44                frequency: node
45                    .find_property("clock-frequency")
46                    .and_then(|p| p.u32().ok()),
47                accuracy: node
48                    .find_property("clock-accuracy")
49                    .and_then(|p| p.u32().ok()),
50            })
51        } else {
52            ClockType::Provider(base)
53        }
54    }
55
56    pub fn clock_cells(&self) -> u32 {
57        match self {
58            ClockType::Fixed(fixed) => fixed.clock.clock_cells,
59            ClockType::Provider(clock) => clock.clock_cells,
60        }
61    }
62
63    pub fn output_name(&self, select: u64) -> Option<String> {
64        match self {
65            ClockType::Fixed(fixed) => fixed.clock.output_name(select),
66            ClockType::Provider(clock) => clock.output_name(select),
67        }
68    }
69}
70
71impl Deref for ClockType {
72    type Target = NodeBase;
73
74    fn deref(&self) -> &Self::Target {
75        match self {
76            ClockType::Fixed(fixed) => &fixed.clock.node,
77            ClockType::Provider(clock) => &clock.node,
78        }
79    }
80}
81
82#[derive(Clone, Debug)]
83pub struct FixedClock {
84    pub clock: Clock,
85    pub frequency: Option<u32>,
86    pub accuracy: Option<u32>,
87}
88
89#[derive(Clone, Debug)]
90pub struct Clock {
91    pub node: NodeBase,
92    pub clock_cells: u32,
93    pub output_names: Vec<String>,
94}
95
96impl Clock {
97    pub(crate) fn from_node(node: NodeBase) -> Self {
98        let clock_cells = node
99            .find_property("#clock-cells")
100            .and_then(|p| p.u32().ok())
101            .unwrap_or(0);
102        let output_names = node
103            .find_property("clock-output-names")
104            .map(|p| p.str_list().map(|s| s.to_string()).collect())
105            .unwrap_or_else(Vec::new);
106
107        Self {
108            node,
109            clock_cells,
110            output_names,
111        }
112    }
113
114    pub fn output_name(&self, select: u64) -> Option<String> {
115        if self.output_names.is_empty() {
116            return None;
117        }
118
119        if self.clock_cells == 0 {
120            return self.output_names.first().cloned();
121        }
122
123        let index = select as usize;
124        self.output_names.get(index).cloned()
125    }
126}