use alloc::format;
use log::info;
use rdrive::{probe::OnProbeError, register::ProbeFdt};
use some_serial::pl011;
use super::{PlatformSerialDevice, prop_u32, serial_device_info, serial_runtime};
model_register!(
name: "PL011 serial",
level: ProbeLevel::PreKernel,
priority: ProbePriority::DEFAULT,
probe_kinds: &[ProbeKind::Fdt {
compatibles: &["arm,pl011"],
on_probe: probe
}],
);
fn probe(probe: ProbeFdt<'_>) -> Result<(), OnProbeError> {
let (info, plat_dev) = probe.into_parts();
info!("Probing PL011 serial device: {}", info.node.name());
let base_reg = info
.node
.regs()
.into_iter()
.next()
.ok_or_else(|| OnProbeError::other(format!("[{}] has no reg", info.node.name())))?;
let mmio_size = base_reg.size.unwrap_or(0x1000);
let mmio_base = crate::mmio::iomap(base_reg.address as usize, mmio_size as usize)?;
let clock_freq = prop_u32(info.node.as_node(), "clock-frequency").unwrap_or(24_000_000);
let raw = pl011::Pl011::new(mmio_base, clock_freq);
let serial = serial_runtime(raw);
let base = serial.base_addr;
let baudrate = serial.baudrate;
let device_info = serial_device_info(&info, &base_reg, base, baudrate);
info!("PL011 serial@{base:#x} registered successfully");
plat_dev.register(PlatformSerialDevice::new(
serial.name.into(),
device_info,
serial.runtime,
));
Ok(())
}