svd_generator/svd/peripheral/
cdns_usb3.rs

1use crate::svd::create_peripheral;
2use crate::{Error, Result};
3
4pub mod registers;
5
6/// Represents the offsets of Cadence USB3 register cluster groups.
7pub struct CdnsUsb3Offsets {
8    /// Dual-role OTG (on-the-go) registers.
9    pub otg: u32,
10    /// XHCI registers.
11    pub xhci: u32,
12    /// Device registers.
13    pub dev: u32,
14}
15
16impl<'b, 'a: 'b> TryFrom<&fdt::node::FdtNode<'b, 'a>> for CdnsUsb3Offsets {
17    type Error = Error;
18
19    fn try_from(val: &fdt::node::FdtNode<'b, 'a>) -> Result<Self> {
20        let regs = val
21            .reg()
22            .map(|c| c.starting_address as u32)
23            .collect::<Vec<u32>>();
24
25        let reg_names = val.property("reg-names").ok_or(Error::DeviceTree(
26            "CdnsUsb3 missing `reg-names` property".into(),
27        ))?;
28
29        let mut otg = None;
30        let mut xhci = None;
31        let mut dev = None;
32
33        reg_names.iter_str().enumerate().for_each(|(i, r)| {
34            if r.contains("otg") {
35                otg = regs.get(i).copied();
36            } else if r.contains("xhci") {
37                xhci = regs.get(i).copied();
38            } else if r.contains("dev") {
39                dev = regs.get(i).copied();
40            }
41        });
42
43        match (otg, xhci, dev) {
44            (Some(otg), Some(xhci), Some(dev)) => Ok(Self { otg, xhci, dev }),
45            _ => Err(Error::DeviceTree(format!("CdnsUsb3 missing a register offset, OTG: {otg:#x?}, XHCI: {xhci:#x?}, DEV: {dev:#x?}"))), 
46        }
47    }
48}
49
50impl<'b, 'a: 'b> TryFrom<fdt::node::FdtNode<'b, 'a>> for CdnsUsb3Offsets {
51    type Error = Error;
52
53    fn try_from(val: fdt::node::FdtNode<'b, 'a>) -> Result<Self> {
54        (&val).try_into()
55    }
56}
57
58/// Represents a Cadence USB3 compatible peripheral definition.
59pub struct CdnsUsb3 {
60    peripheral: svd::Peripheral,
61}
62
63impl CdnsUsb3 {
64    /// Creates a new [CdnsUsb3] peripheral.
65    pub fn create(
66        name: &str,
67        base_address: u64,
68        size: u32,
69        interrupt: Option<Vec<svd::Interrupt>>,
70        offsets: CdnsUsb3Offsets,
71        dim: u32,
72    ) -> Result<Self> {
73        let dim_element = if dim > 0 {
74            Some(
75                svd::DimElement::builder()
76                    .dim(dim)
77                    .dim_increment(size)
78                    .build(svd::ValidateLevel::Strict)?,
79            )
80        } else {
81            None
82        };
83
84        let peripheral = create_peripheral(
85            name,
86            format!("Cadence USB3: {name}").as_str(),
87            base_address,
88            size,
89            interrupt,
90            Some(registers::create(offsets)?),
91            dim_element,
92        )?;
93
94        Ok(Self { peripheral })
95    }
96
97    /// Gets a reference to the SVD [`Peripheral`](svd::Peripheral).
98    pub const fn peripheral(&self) -> &svd::Peripheral {
99        &self.peripheral
100    }
101
102    /// Gets a mutable reference to the SVD [`Peripheral`](svd::Peripheral).
103    pub fn peripheral_mut(&mut self) -> &mut svd::Peripheral {
104        &mut self.peripheral
105    }
106
107    /// Converts the [CdnsUsb3] into the inner SVD [`Peripheral`](svd::Peripheral).
108    pub fn to_inner(self) -> svd::Peripheral {
109        self.peripheral
110    }
111}