jh7110: syscrg/aoncrg map memory in probe
This commit is contained in:
parent
41944890b6
commit
99f5ad0987
@ -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)
|
||||||
|
@ -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());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user