rdif_pinctrl/
interface.rs1use alloc::{boxed::Box, vec::Vec};
2use core::any::Any;
3
4use rdif_base::DriverGeneric;
5
6use crate::{
7 ConfigSetting, ConfigTarget, FunctionId, GpioBank, GpioBankId, GpioIrqHandler, GpioIrqSourceId,
8 GpioIrqSourceInfo, GpioRange, GroupId, PinDesc, PinFunction, PinGroup, PinState, PinctrlError,
9};
10#[cfg(feature = "fdt")]
11use crate::{FdtPinctrl, FdtPinctrlParser};
12
13#[cfg(feature = "fdt")]
14pub type BFdtPinctrlParser = Box<dyn FdtPinctrlParser + Send>;
15
16pub type BPinctrl = Box<dyn Interface>;
17pub type BGpioBank = Box<dyn GpioBank>;
18pub type BGpioIrqHandler = Box<dyn GpioIrqHandler>;
19
20pub struct PinctrlDevice {
21 interface: BPinctrl,
22 #[cfg(feature = "fdt")]
23 fdt_parser: Option<BFdtPinctrlParser>,
24}
25
26impl PinctrlDevice {
27 pub fn new(interface: impl Interface + 'static) -> Self {
28 Self {
29 interface: Box::new(interface),
30 #[cfg(feature = "fdt")]
31 fdt_parser: None,
32 }
33 }
34
35 #[cfg(feature = "fdt")]
36 pub fn with_fdt_parser(
37 interface: impl Interface + 'static,
38 parser: impl FdtPinctrlParser + Send + 'static,
39 ) -> Self {
40 Self {
41 interface: Box::new(interface),
42 fdt_parser: Some(Box::new(parser)),
43 }
44 }
45
46 pub fn boxed(interface: BPinctrl) -> Self {
47 Self {
48 interface,
49 #[cfg(feature = "fdt")]
50 fdt_parser: None,
51 }
52 }
53
54 #[cfg(feature = "fdt")]
55 pub fn boxed_with_fdt_parser(interface: BPinctrl, parser: BFdtPinctrlParser) -> Self {
56 Self {
57 interface,
58 fdt_parser: Some(parser),
59 }
60 }
61
62 pub fn interface(&self) -> &dyn Interface {
63 self.interface.as_ref()
64 }
65
66 pub fn interface_mut(&mut self) -> &mut dyn Interface {
67 self.interface.as_mut()
68 }
69
70 pub fn typed_ref<T: Interface>(&self) -> Option<&T> {
71 self.raw_any()?.downcast_ref()
72 }
73
74 pub fn typed_mut<T: Interface>(&mut self) -> Option<&mut T> {
75 self.raw_any_mut()?.downcast_mut()
76 }
77
78 #[cfg(feature = "fdt")]
79 pub fn fdt_parser(&self) -> Option<&dyn FdtPinctrlParser> {
80 self.fdt_parser
81 .as_deref()
82 .map(|parser| parser as &dyn FdtPinctrlParser)
83 }
84
85 #[cfg(feature = "fdt")]
86 pub fn apply_fdt_default_state(
87 &mut self,
88 fdt: &fdt_edit::Fdt,
89 node: &fdt_edit::Node,
90 ) -> Result<(), PinctrlError> {
91 if node.get_property("pinctrl-0").is_none() {
92 return Ok(());
93 }
94 let Self {
95 interface,
96 fdt_parser,
97 } = self;
98 let Some(parser) = fdt_parser.as_deref() else {
99 return Ok(());
100 };
101 FdtPinctrl::apply_state_from_consumer(interface.as_mut(), fdt, node, 0, parser)
102 }
103
104 #[cfg(feature = "fdt")]
105 pub fn apply_fdt_fixed_regulator(
106 &mut self,
107 fdt: &fdt_edit::Fdt,
108 regulator_node: &fdt_edit::Node,
109 owner: &str,
110 ) -> Result<(), PinctrlError> {
111 let Self {
112 interface,
113 fdt_parser,
114 } = self;
115 let Some(parser) = fdt_parser.as_deref() else {
116 return Ok(());
117 };
118 FdtPinctrl::apply_fixed_regulator(interface.as_mut(), fdt, regulator_node, parser, owner)
119 }
120}
121
122impl DriverGeneric for PinctrlDevice {
123 fn name(&self) -> &str {
124 self.interface.name()
125 }
126
127 fn raw_any(&self) -> Option<&dyn Any> {
128 Some(self.interface.as_ref() as &dyn Any)
129 }
130
131 fn raw_any_mut(&mut self) -> Option<&mut dyn Any> {
132 Some(self.interface.as_mut() as &mut dyn Any)
133 }
134}
135
136impl Interface for PinctrlDevice {
137 fn pins(&self) -> &[PinDesc] {
138 self.interface.pins()
139 }
140
141 fn groups(&self) -> &[PinGroup] {
142 self.interface.groups()
143 }
144
145 fn functions(&self) -> &[PinFunction] {
146 self.interface.functions()
147 }
148
149 fn gpio_ranges(&self) -> &[GpioRange] {
150 self.interface.gpio_ranges()
151 }
152
153 fn can_mux(&self, group: GroupId, function: FunctionId) -> bool {
154 self.interface.can_mux(group, function)
155 }
156
157 fn validate_state(&self, state: &PinState) -> Result<(), PinctrlError> {
158 self.interface.validate_state(state)
159 }
160
161 fn apply_state(&mut self, state: &PinState) -> Result<(), PinctrlError> {
162 self.interface.apply_state(state)
163 }
164
165 fn apply_mux(&mut self, setting: &crate::MuxSetting) -> Result<(), PinctrlError> {
166 self.interface.apply_mux(setting)
167 }
168
169 fn apply_config(&mut self, setting: &ConfigSetting) -> Result<(), PinctrlError> {
170 self.interface.apply_config(setting)
171 }
172
173 fn create_gpio_bank(&mut self, bank_id: GpioBankId) -> Option<BGpioBank> {
174 self.interface.create_gpio_bank(bank_id)
175 }
176
177 fn irq_sources(&self) -> Vec<GpioIrqSourceInfo> {
178 self.interface.irq_sources()
179 }
180
181 fn take_irq_handler(&mut self, source_id: GpioIrqSourceId) -> Option<BGpioIrqHandler> {
182 self.interface.take_irq_handler(source_id)
183 }
184}
185
186pub trait Interface: DriverGeneric {
187 fn pins(&self) -> &[PinDesc] {
188 &[]
189 }
190
191 fn groups(&self) -> &[PinGroup] {
192 &[]
193 }
194
195 fn functions(&self) -> &[PinFunction] {
196 &[]
197 }
198
199 fn gpio_ranges(&self) -> &[GpioRange] {
200 &[]
201 }
202
203 fn can_mux(&self, group: GroupId, function: FunctionId) -> bool {
204 self.functions()
205 .iter()
206 .find(|candidate| candidate.id == function)
207 .is_some_and(|candidate| candidate.groups.contains(&group))
208 }
209
210 fn validate_state(&self, state: &PinState) -> Result<(), PinctrlError> {
211 for mux in state.muxes() {
212 if !self.groups().iter().any(|group| group.id == mux.group) {
213 return Err(PinctrlError::InvalidGroup(mux.group));
214 }
215 if !self
216 .functions()
217 .iter()
218 .any(|function| function.id == mux.function)
219 {
220 return Err(PinctrlError::InvalidFunction(mux.function));
221 }
222 if !self.can_mux(mux.group, mux.function) {
223 return Err(PinctrlError::InvalidMux {
224 group: mux.group,
225 function: mux.function,
226 });
227 }
228 }
229
230 for config in state.configs() {
231 match config.target {
232 ConfigTarget::Pin(pin) => {
233 if !self.pins().iter().any(|desc| desc.id == pin) {
234 return Err(PinctrlError::InvalidPin(pin));
235 }
236 }
237 ConfigTarget::Group(group) => {
238 if !self.groups().iter().any(|desc| desc.id == group) {
239 return Err(PinctrlError::InvalidGroup(group));
240 }
241 }
242 }
243 }
244
245 Ok(())
246 }
247
248 fn apply_state(&mut self, state: &PinState) -> Result<(), PinctrlError> {
249 self.validate_state(state)?;
250 for mux in state.muxes() {
251 self.apply_mux(mux)?;
252 }
253 for config in state.configs() {
254 self.apply_config(config)?;
255 }
256 Ok(())
257 }
258
259 fn apply_mux(&mut self, _setting: &crate::MuxSetting) -> Result<(), PinctrlError> {
260 Err(PinctrlError::NotSupported)
261 }
262
263 fn apply_config(&mut self, _setting: &ConfigSetting) -> Result<(), PinctrlError> {
264 Err(PinctrlError::NotSupported)
265 }
266
267 fn create_gpio_bank(&mut self, _bank_id: GpioBankId) -> Option<BGpioBank> {
268 None
269 }
270
271 fn irq_sources(&self) -> Vec<GpioIrqSourceInfo> {
272 Vec::new()
273 }
274
275 fn take_irq_handler(&mut self, _source_id: GpioIrqSourceId) -> Option<BGpioIrqHandler> {
276 None
277 }
278}