From 70eb6cfaed1370ddc1f8e0bb77a1d5ece2ed2cd9 Mon Sep 17 00:00:00 2001 From: Mark Poliakov Date: Fri, 14 Feb 2025 12:10:12 +0200 Subject: [PATCH] jh7110: better syscrg clock structs --- kernel/src/device/clock/jh7110_syscrg.rs | 118 +++++++++++++++++------ 1 file changed, 89 insertions(+), 29 deletions(-) diff --git a/kernel/src/device/clock/jh7110_syscrg.rs b/kernel/src/device/clock/jh7110_syscrg.rs index 5c6df03b..42355416 100644 --- a/kernel/src/device/clock/jh7110_syscrg.rs +++ b/kernel/src/device/clock/jh7110_syscrg.rs @@ -16,25 +16,7 @@ use device_tree::{ use libk_mm::{address::PhysicalAddress, device::DeviceMemoryIoMut}; use libk_util::{sync::IrqSafeSpinlock, OneTimeInit}; -const CLK_OSC: usize = 0; - -// gmac0; -// 1:kernel/src/device/clock/jh7110_aoncrg.rs:69: jh7110: enable clock Some(3) -// 1:kernel/src/device/clock/jh7110_aoncrg.rs:69: jh7110: enable clock Some(2) -// 1:kernel/src/device/clock/jh7110_syscrg.rs:51: TODO: jh7110-syscrg: enable clock Some(109) -// 1:kernel/src/device/clock/jh7110_aoncrg.rs:69: jh7110: enable clock Some(6) -// 1:kernel/src/device/clock/jh7110_syscrg.rs:51: TODO: jh7110-syscrg: enable clock Some(111) -// 1:kernel/src/device/clock/jh7110_aoncrg.rs:86: jh7110: deassert reset Some(0) -// 1:kernel/src/device/clock/jh7110_aoncrg.rs:86: jh7110: deassert reset Some(1) - -// gmac1: -// 1:kernel/src/device/clock/jh7110_syscrg.rs:51: TODO: jh7110-syscrg: enable clock Some(98) -// 1:kernel/src/device/clock/jh7110_syscrg.rs:51: TODO: jh7110-syscrg: enable clock Some(97) -// 1:kernel/src/device/clock/jh7110_syscrg.rs:51: TODO: jh7110-syscrg: enable clock Some(102) -// 1:kernel/src/device/clock/jh7110_syscrg.rs:51: TODO: jh7110-syscrg: enable clock Some(106) -// 1:kernel/src/device/clock/jh7110_syscrg.rs:51: TODO: jh7110-syscrg: enable clock Some(107) - -const CLK_UART0_CORE: u32 = 146; +const PARENT_CLK_OSC: usize = 0; struct Syscrg { base: PhysicalAddress, @@ -42,6 +24,25 @@ struct Syscrg { mapping: OneTimeInit>>, } +#[derive(Debug, Clone, Copy)] +enum ClockParent { + #[allow(unused)] + Int(u32), + Ext(usize), + None, +} + +#[derive(Debug, Clone, Copy)] +enum ClockRegister { + // Clock gate + Gate(u32, ClockParent), + // Clock inverter + Inv(u32), + // Clock delay selector (TODO) + Delay, + Unimp, +} + impl Syscrg { fn ensure_init(&self) -> Result<&IrqSafeSpinlock>, Error> { self.mapping.or_try_init_with(move || { @@ -49,6 +50,38 @@ impl Syscrg { .map(IrqSafeSpinlock::new) }) } + + fn map_clock_index(index: u32) -> Option<(&'static str, ClockRegister)> { + const CLOCKS: &[(&'static str, ClockRegister)] = &const { + use ClockParent::*; + use ClockRegister::*; + + let mut t = [("", Unimp); 256]; + t[0x184 / 4] = ("clk_gmac5_axi64_ahb", Gate(31, None)); + t[0x188 / 4] = ("clk_gmac5_axi64_axi", Gate(31, None)); + t[0x18C / 4] = ("clk_gmac_source", Unimp); + t[0x190 / 4] = ("clk_gmac1_gtx", Unimp); + t[0x194 / 4] = ("clk_gmac1_rmii_rtx", Unimp); + t[0x198 / 4] = ("clk_gmac5_axi64_ptp", Gate(31, None)); + t[0x19C / 4] = ("clk_gmac5_axi64_rx", Unimp); + t[0x1A0 / 4] = ("clk_gmac5_axi64_rx_inv", Inv(30)); + t[0x1A4 / 4] = ("clk_gmac5_axi64_tx", Gate(31, None)); + t[0x1A8 / 4] = ("clk_gmac5_axi64_tx_inv", Inv(30)); + t[0x1AC / 4] = ("clk_gmac1_gtxc", Delay); + t[0x1B0 / 4] = ("clk_gmac0_gtx", Gate(31, None)); + t[0x1B4 / 4] = ("clk_gmac0_ptp", Gate(31, None)); + t[0x1B8 / 4] = ("clk_gmac_phy", Gate(31, None)); + t[0x1BC / 4] = ("clk_gmac0_gtxc", Delay); + + t[0x244 / 4] = ("clk_u0_uart_apb", Gate(31, None)); + t[0x248 / 4] = ("clk_u0_uart_core", Gate(31, Ext(PARENT_CLK_OSC))); + + t + }; + + let index = index as usize; + CLOCKS.get(index).copied() + } } impl Device for Syscrg { @@ -64,15 +97,27 @@ impl Device for Syscrg { impl ClockController for Syscrg { fn enable_clock(&self, clock: Option) -> Result<(), Error> { + let index = clock.ok_or(Error::InvalidArgument)?; + let (name, reg) = Self::map_clock_index(index) + .ok_or(Error::InvalidArgument) + .inspect_err(|_| log::warn!("jh7110-syscrg: undefined clock {:?}", clock))?; let regs = self.ensure_init()?; - match clock.ok_or(Error::InvalidArgument)? { - 109 => { - regs.lock()[109] |= 1 << 31; + let mut lock = regs.lock(); + + match reg { + ClockRegister::Gate(bit, _) => { + log::info!("jh7110-syscrg: enable {name:?}"); + lock[index as usize] |= 1 << bit; Ok(()) } - 111 => Ok(()), - _ => { - log::warn!("TODO: jh7110-syscrg: enable clock {clock:?}"); + ClockRegister::Inv(bit) => { + log::info!("jh7110-syscrg: enable clk inv {name:?}"); + lock[index as usize] |= 1 << bit; + Ok(()) + } + ClockRegister::Delay => Ok(()), + ClockRegister::Unimp => { + log::warn!("jh7110-syscrg: clock not implemented: {name:?}"); Err(Error::NotImplemented) } } @@ -84,10 +129,25 @@ impl ClockController for Syscrg { } fn clock_rate(&self, clock: Option) -> Result { - match clock.ok_or(Error::InvalidArgument)? { - CLK_UART0_CORE => self.parents[CLK_OSC].rate(), - _ => { - log::warn!("TODO: jh7110-syscrg: read rate {:#x?}", clock); + let (name, reg) = clock + .and_then(Self::map_clock_index) + .ok_or(Error::InvalidArgument) + .inspect_err(|_| log::warn!("jh7110-syscrg: undefined clock {:?}", clock))?; + + match reg { + ClockRegister::Gate(_, parent) => match parent { + ClockParent::Ext(n) => self.parents[n].rate(), + ClockParent::Int(_) => { + log::warn!("jh7110-syscrg: todo internal clock parents: {:?}", name); + Err(Error::NotImplemented) + } + ClockParent::None => { + log::warn!("jh7110-syscrg: clock parent not specified {:?}", name); + Err(Error::NotImplemented) + } + }, + ClockRegister::Unimp | ClockRegister::Delay | ClockRegister::Inv(_) => { + log::warn!("jh7110-syscrg: unimplemented clock {:?}", name); Err(Error::NotImplemented) } }