use rdrive::{DriverGeneric, KError, probe::OnProbeError};
use rockchip_soc::{ClkId, Cru, CruOp};
mod rk3568;
mod rk3588;
pub struct ClkDrv {
name: &'static str,
inner: Cru,
}
impl ClkDrv {
pub const fn new(name: &'static str, cru: Cru) -> Self {
Self { name, inner: cru }
}
fn enable_clock(&mut self, id: u32) -> Result<(), OnProbeError> {
let id = ClkId::from(id);
if self.inner.clk_is_enabled(id).unwrap_or(false) {
return Ok(());
}
self.inner.clk_enable(id).map_err(|err| {
OnProbeError::other(alloc::format!("failed to enable clock {id}: {err}"))
})
}
fn set_clock_rate(&mut self, id: u32, rate: u64) -> Result<(), OnProbeError> {
self.inner
.clk_set_rate(ClkId::from(id), rate)
.map_err(|err| {
OnProbeError::other(alloc::format!("failed to set clock {id}: {err}"))
})?;
Ok(())
}
fn reset_assert(&mut self, id: u64) {
self.inner.reset_assert(id.into());
}
fn reset_deassert(&mut self, id: u64) {
self.inner.reset_deassert(id.into());
}
}
unsafe impl Send for ClkDrv {}
impl DriverGeneric for ClkDrv {
fn name(&self) -> &str {
self.name
}
}
impl rdif_clk::Interface for ClkDrv {
fn perper_enable(&mut self) {}
fn get_rate(&self, id: rdif_clk::ClockId) -> Result<u64, KError> {
self.inner
.clk_get_rate(clock_id(id))
.map_err(|_| KError::InvalidArg { name: "clock_id" })
}
fn set_rate(&mut self, id: rdif_clk::ClockId, rate: u64) -> Result<(), KError> {
self.inner
.clk_set_rate(clock_id(id), rate)
.map_err(|_| KError::InvalidArg { name: "clock_id" })?;
Ok(())
}
}
fn clock_id(id: rdif_clk::ClockId) -> ClkId {
let id: usize = id.into();
ClkId::from(id)
}
fn with_clk_drv<T>(
f: impl FnOnce(&mut ClkDrv) -> Result<T, OnProbeError>,
) -> Result<T, OnProbeError> {
let clk = rdrive::get_one::<rdif_clk::Clk>()
.ok_or_else(|| OnProbeError::other("Rockchip CRU clock device not registered"))?;
let mut clk = clk.lock().map_err(|err| {
OnProbeError::other(alloc::format!(
"failed to lock Rockchip CRU clock device: {err}"
))
})?;
let drv = clk
.typed_mut::<ClkDrv>()
.ok_or_else(|| OnProbeError::other("Rockchip CRU clock device type mismatch"))?;
f(drv)
}
pub(crate) fn rk3588_enable_clock(id: u32) -> Result<(), OnProbeError> {
with_clk_drv(|drv| drv.enable_clock(id))
}
pub(crate) fn rk3588_set_clock_rate(id: u32, rate: u64) -> Result<(), OnProbeError> {
with_clk_drv(|drv| drv.set_clock_rate(id, rate))
}
pub(crate) fn rk3588_reset_assert(id: u64) -> Result<(), OnProbeError> {
with_clk_drv(|drv| {
drv.reset_assert(id);
Ok(())
})
}
pub(crate) fn rk3588_reset_deassert(id: u64) -> Result<(), OnProbeError> {
with_clk_drv(|drv| {
drv.reset_deassert(id);
Ok(())
})
}