axplat-dyn 0.6.2

A dynamic platform module for ArceOS, providing runtime platform detection and configuration
Documentation
use ax_arm_pl031::Rtc;
use rdrive::{PlatformDevice, module_driver, probe::OnProbeError, register::FdtInfo};

use crate::drivers::iomap;

module_driver!(
    name: "pl031 rtc",
    level: ProbeLevel::PostKernel,
    priority: ProbePriority::DEFAULT,
    probe_kinds: &[ProbeKind::Fdt {
        compatibles: &["arm,pl031"],
        on_probe: probe
    }],
);

fn probe(info: FdtInfo<'_>, _plat_dev: PlatformDevice) -> Result<(), OnProbeError> {
    let regs = info.node.regs();
    let Some(base_reg) = regs.first() else {
        return Err(OnProbeError::other(alloc::format!(
            "[{}] has no reg",
            info.node.name()
        )));
    };

    let mmio_size = base_reg.size.unwrap_or(0x1000);
    let mmio_base = iomap((base_reg.address as usize).into(), mmio_size as usize)?;
    let rtc = unsafe { Rtc::new(mmio_base.as_ptr().cast()) };
    let unix_timestamp = rtc.get_unix_timestamp();
    if unix_timestamp == 0 {
        return Err(OnProbeError::other(alloc::format!(
            "[{}] returned zero unix timestamp",
            info.node.name()
        )));
    }

    let epoch_time_nanos = u64::from(unix_timestamp) * 1_000_000_000;
    if crate::generic_timer::try_init_epoch_offset(epoch_time_nanos) {
        info!("Initialized wall clock from {}", info.node.name());
    } else {
        debug!(
            "Skipping RTC {} because epoch offset is already initialized",
            info.node.name()
        );
    }

    Ok(())
}