use crate::svd::create_peripheral;
use crate::{Error, Result};
pub mod registers;
pub struct CdnsUsb3Offsets {
pub otg: u32,
pub xhci: u32,
pub dev: u32,
}
impl<'b, 'a: 'b> TryFrom<&fdt::node::FdtNode<'b, 'a>> for CdnsUsb3Offsets {
type Error = Error;
fn try_from(val: &fdt::node::FdtNode<'b, 'a>) -> Result<Self> {
let regs = val
.reg()
.map(|c| c.starting_address as u32)
.collect::<Vec<u32>>();
let reg_names = val.property("reg-names").ok_or(Error::DeviceTree(
"CdnsUsb3 missing `reg-names` property".into(),
))?;
let mut otg = None;
let mut xhci = None;
let mut dev = None;
reg_names
.as_str_list()
.enumerate()
.for_each(|(i, r)| {
if r.contains("otg") {
otg = regs.get(i).map(|&s| s);
} else if r.contains("xhci") {
xhci = regs.get(i).map(|&s| s);
} else if r.contains("dev") {
dev = regs.get(i).map(|&s| s);
}
});
match (otg, xhci, dev) {
(Some(otg), Some(xhci), Some(dev)) => Ok(Self { otg, xhci, dev }),
_ => Err(Error::DeviceTree(format!("CdnsUsb3 missing a register offset, OTG: {otg:#x?}, XHCI: {xhci:#x?}, DEV: {dev:#x?}"))),
}
}
}
impl<'b, 'a: 'b> TryFrom<fdt::node::FdtNode<'b, 'a>> for CdnsUsb3Offsets {
type Error = Error;
fn try_from(val: fdt::node::FdtNode<'b, 'a>) -> Result<Self> {
(&val).try_into()
}
}
pub struct CdnsUsb3 {
peripheral: svd::Peripheral,
}
impl CdnsUsb3 {
pub fn create(
name: &str,
base_address: u64,
size: u32,
interrupt: Option<Vec<svd::Interrupt>>,
offsets: CdnsUsb3Offsets,
dim: u32,
) -> Result<Self> {
let dim_element = if dim > 0 {
Some(
svd::DimElement::builder()
.dim(dim)
.dim_increment(size)
.build(svd::ValidateLevel::Strict)?,
)
} else {
None
};
let peripheral = create_peripheral(
name,
format!("Cadence USB3: {name}").as_str(),
base_address,
size,
interrupt,
Some(registers::create(offsets)?),
dim_element,
)?;
Ok(Self { peripheral })
}
pub const fn peripheral(&self) -> &svd::Peripheral {
&self.peripheral
}
pub fn peripheral_mut(&mut self) -> &mut svd::Peripheral {
&mut self.peripheral
}
pub fn to_inner(self) -> svd::Peripheral {
self.peripheral
}
}