Compare commits

...

2 Commits

Author SHA1 Message Date
70eb6cfaed jh7110: better syscrg clock structs 2025-02-14 12:10:12 +02:00
5c1c980ccd stmmac: link status reporting 2025-02-14 01:08:27 +02:00
2 changed files with 108 additions and 36 deletions

View File

@ -60,13 +60,25 @@ struct Stmmac {
impl Inner {
fn link_state(&self) -> LinkState {
// TODO read the link state properly, i.e., read from PHY's registers, I guess? I didn't
// find a nice way to read the link state from the MAC itself, it only seems to report
// the MAC<->PHY link state (which is always up, obviously)
LinkState::Ethernet(EthernetLinkState::Up(
EthernetSpeed::Unknown,
Duplex::Unknown,
))
let status = self.regs.lock().MAC.MACPHYCSR.extract();
let link = if status.matches_all(MACPHYCSR::LNKSTS::Up) {
let speed = match status.read_as_enum(MACPHYCSR::LNKSPEED) {
Some(MACPHYCSR::LNKSPEED::Value::Speed2_5MHz) => EthernetSpeed::Speed10,
Some(MACPHYCSR::LNKSPEED::Value::Speed25MHz) => EthernetSpeed::Speed100,
Some(MACPHYCSR::LNKSPEED::Value::Speed125MHz) => EthernetSpeed::Speed1000,
_ => EthernetSpeed::Unknown,
};
let duplex = if status.matches_all(MACPHYCSR::LNKMOD::FullDuplex) {
Duplex::Full
} else {
Duplex::Half
};
EthernetLinkState::Up(speed, duplex)
} else {
EthernetLinkState::Down
};
LinkState::Ethernet(link)
}
}

View File

@ -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<IrqSafeSpinlock<DeviceMemoryIoMut<'static, [u32]>>>,
}
#[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<DeviceMemoryIoMut<'static, [u32]>>, 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<u32>) -> 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<u32>) -> Result<u64, Error> {
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)
}
}