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

View File

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