jh7110: syscrg/aoncrg map memory in probe

This commit is contained in:
Mark Poliakov 2025-02-14 18:47:51 +02:00
parent 41944890b6
commit 99f5ad0987
2 changed files with 21 additions and 30 deletions

View File

@ -13,7 +13,7 @@ use device_tree::{
DeviceTreePropertyRead, TProp,
};
use libk_mm::{address::PhysicalAddress, device::DeviceMemoryIo};
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
use libk_util::sync::IrqSafeSpinlock;
use tock_registers::{
interfaces::{Readable, Writeable},
register_structs,
@ -58,28 +58,21 @@ enum ClockParent {
pub struct Aoncrg {
base: PhysicalAddress,
clock_parents: [ClockHandle; 7],
mapping: OneTimeInit<IrqSafeSpinlock<DeviceMemoryIo<'static, Regs>>>,
mapping: IrqSafeSpinlock<DeviceMemoryIo<'static, Regs>>,
}
impl Aoncrg {
fn ensure_init(&self) -> Result<&IrqSafeSpinlock<DeviceMemoryIo<'static, Regs>>, Error> {
self.mapping.or_try_init_with(|| {
unsafe { DeviceMemoryIo::map(self.base, Default::default()) }.map(IrqSafeSpinlock::new)
})
}
fn clk_enable_int(&self, index: u32) -> Result<(), Error> {
let (name, reg) = Self::map_clock_index(index)
.ok_or(Error::InvalidArgument)
.inspect_err(|_| log::warn!("jh7110-syscrg: undefined clock {:?}", index))?;
let regs = self.ensure_init()?;
match reg {
ClockRegister::Fixed => Ok(()),
ClockRegister::Gate(bit, parent) => {
self.clk_enable_parent(parent)?;
log::info!("jh7110-aoncrg: enable {name:?} @ {index}");
let lock = regs.lock();
let lock = self.mapping.lock();
lock.CLOCKS[index as usize].set(lock.CLOCKS[index as usize].get() | (1 << bit));
Ok(())
}
@ -145,8 +138,7 @@ impl ClockController for Aoncrg {
impl ResetController for Aoncrg {
fn assert_reset(&self, reset: Option<u32>) -> Result<(), Error> {
let reset = reset.ok_or(Error::InvalidArgument)?;
let mapping = self.ensure_init()?;
let regs = mapping.lock();
let regs = self.mapping.lock();
let val = regs.RESETS.get();
regs.RESETS.set(val | (1 << reset));
Ok(())
@ -154,8 +146,7 @@ impl ResetController for Aoncrg {
fn deassert_reset(&self, reset: Option<u32>) -> Result<(), Error> {
let reset = reset.ok_or(Error::InvalidArgument)?;
let mapping = self.ensure_init()?;
let regs = mapping.lock();
let regs = self.mapping.lock();
let val = regs.RESETS.get();
regs.RESETS.set(val & !(1 << reset));
Ok(())
@ -204,11 +195,14 @@ device_tree_driver! {
node.named_clock("rtc_osc")?,
];
let mapping = unsafe { DeviceMemoryIo::map(base, Default::default()) }.ok()?;
let aoncrg = Arc::new(Aoncrg {
base,
clock_parents,
mapping: OneTimeInit::new()
mapping: IrqSafeSpinlock::new(mapping)
});
node.make_reset_controller(aoncrg.clone());
node.make_clock_controller(aoncrg.clone());
Some(aoncrg)

View File

@ -14,14 +14,14 @@ use device_tree::{
DeviceTreePropertyRead, TProp,
};
use libk_mm::{address::PhysicalAddress, device::DeviceMemoryIoMut};
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
use libk_util::sync::IrqSafeSpinlock;
const PARENT_CLK_OSC: usize = 0;
struct Syscrg {
base: PhysicalAddress,
parents: [ClockHandle; 1],
mapping: OneTimeInit<IrqSafeSpinlock<DeviceMemoryIoMut<'static, [u32]>>>,
mapping: IrqSafeSpinlock<DeviceMemoryIoMut<'static, [u32]>>,
}
#[derive(Debug, Clone, Copy)]
@ -43,31 +43,23 @@ enum ClockRegister {
}
impl Syscrg {
fn ensure_init(&self) -> Result<&IrqSafeSpinlock<DeviceMemoryIoMut<'static, [u32]>>, Error> {
self.mapping.or_try_init_with(move || {
unsafe { DeviceMemoryIoMut::map_slice(self.base, 256, Default::default()) }
.map(IrqSafeSpinlock::new)
})
}
fn clk_enable_int(&self, index: u32, depth: u32) -> Result<(), Error> {
let (name, reg) = Self::map_clock_index(index)
.ok_or(Error::InvalidArgument)
.inspect_err(|_| log::warn!("jh7110-syscrg: undefined clock {:?}", index))?;
let regs = self.ensure_init()?;
match reg {
ClockRegister::Gate(bit, parent) => {
log::info!("jh7110-syscrg: enable {name:?} @ {index} /{depth}");
self.clk_enable_parent(parent, depth)?;
let mut lock = regs.lock();
let mut lock = self.mapping.lock();
lock[index as usize] |= 1 << bit;
Ok(())
}
ClockRegister::Inv(bit, parent) => {
log::info!("jh7110-syscrg: enable clk inv {name:?} @ {index}");
self.clk_enable_parent(parent, depth)?;
let mut lock = regs.lock();
let mut lock = self.mapping.lock();
lock[index as usize] |= 1 << bit;
Ok(())
}
@ -182,8 +174,7 @@ impl Syscrg {
fn rst_trigger(&self, reset: u32, assert: bool) -> Result<(), Error> {
let reg = (190 + reset / 32) as usize;
let bit = reset % 32;
let regs = self.ensure_init()?;
let mut regs = regs.lock();
let mut regs = self.mapping.lock();
let expect = if assert {
regs[reg] |= 1 << bit;
@ -246,17 +237,23 @@ impl DeviceTreeResetController for Syscrg {
}
}
unsafe impl Sync for Syscrg {}
unsafe impl Send for Syscrg {}
device_tree_driver! {
compatible: ["starfive,jh7110-syscrg"],
driver: {
fn probe(&self, node: &Arc<Node>, context: &mut ProbeContext) -> Option<Arc<dyn Device>> {
let base = node.map_base(context, 0)?;
let osc = node.named_clock("osc")?;
let mapping = unsafe { DeviceMemoryIoMut::map_slice(base, 256, Default::default()) }
.inspect_err(|error| log::error!("jh7110-syscrg: {error:?}"))
.ok()?;
let syscrg = Arc::new(Syscrg {
base,
parents: [osc],
mapping: OneTimeInit::new(),
mapping: IrqSafeSpinlock::new(mapping),
});
node.make_reset_controller(syscrg.clone());
node.make_clock_controller(syscrg.clone());