Skip to main content

rdif_pinctrl/
interface.rs

1use 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}