From a11cb852a8d5448f6e5c4cd8bbb85846eba9f667 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sat, 29 May 2021 12:50:28 +0800 Subject: [PATCH] libboard_zynq: work around Kasli-SoC MDIO breakage (#78) --- libboard_zynq/src/eth/phy/mod.rs | 254 ++++++++++++++++++------------- 1 file changed, 148 insertions(+), 106 deletions(-) diff --git a/libboard_zynq/src/eth/phy/mod.rs b/libboard_zynq/src/eth/phy/mod.rs index 9fdfbc7..e4639bb 100644 --- a/libboard_zynq/src/eth/phy/mod.rs +++ b/libboard_zynq/src/eth/phy/mod.rs @@ -1,5 +1,4 @@ pub mod id; -use id::{identify_phy, PhyIdentifier}; mod status; pub use status::Status; mod control; @@ -31,111 +30,154 @@ pub trait PhyAccess { fn write_phy(&mut self, addr: u8, reg: u8, data: u16); } -#[derive(Clone)] -pub struct Phy { - pub addr: u8, -} - -const OUI_MARVELL: u32 = 0x005043; -const OUI_REALTEK: u32 = 0x000732; -const OUI_LANTIQ : u32 = 0x355969; - -impl Phy { - /// Probe all addresses on MDIO for a known PHY - pub fn find(pa: &mut PA) -> Option { - (1..32).find(|addr| { - match identify_phy(pa, *addr) { - Some(PhyIdentifier { - oui: OUI_MARVELL, - // Marvell 88E1116R - model: 36, - .. - }) => true, - Some(PhyIdentifier { - oui: OUI_MARVELL, - // Marvell 88E1512 - model: 29, - .. - }) => true, - Some(PhyIdentifier { - oui: OUI_REALTEK, - // RTL 8211E - model: 0b010001, - rev: 0b0101, - }) => true, - Some(PhyIdentifier { - oui: OUI_LANTIQ, - // Intel XWAY PHY11G (PEF 7071/PEF 7072) v1.5 / v1.6 - model: 0, - .. - }) => true, - _ => false, - } - }).map(|addr| Phy { addr }) - } - - pub fn read_reg(&self, pa: &mut PA) -> PR - where - PA: PhyAccess, - PR: PhyRegister + From, - { - pa.read_phy(self.addr, PR::addr()).into() - } - - pub fn modify_reg(&self, pa: &mut PA, mut f: F) - where - PA: PhyAccess, - PR: PhyRegister + From + Into, - F: FnMut(PR) -> PR, - { - let reg = pa.read_phy(self.addr, PR::addr()).into(); - let reg = f(reg); - pa.write_phy(self.addr, PR::addr(), reg.into()) - } - - pub fn modify_control(&self, pa: &mut PA, f: F) - where - PA: PhyAccess, - F: FnMut(Control) -> Control, - { - self.modify_reg(pa, f) - } - - pub fn get_control(&self, pa: &mut PA) -> Control { - self.read_reg(pa) - } - - pub fn get_status(&self, pa: &mut PA) -> Status { - self.read_reg(pa) - } - - pub fn get_link(&self, pa: &mut PA) -> Option { - let status = self.get_status(pa); - if !status.link_status() { - None - } else if status.cap_1000base_t_extended_status() { - let phy_status: PSSR = self.read_reg(pa); - phy_status.get_link() - } else { - status.get_link() - } - } - - pub fn reset(&self, pa: &mut PA) { - self.modify_control(pa, |control| - control.set_reset(true) - ); - while self.get_control(pa).reset() {} - } - - pub fn restart_autoneg(&self, pa: &mut PA) { - self.modify_control(pa, |control| - control.set_autoneg_enable(true) - .set_restart_autoneg(true) - ); - } -} - pub trait PhyRegister { fn addr() -> u8; } + +#[cfg(not(feature = "target_kasli_soc"))] +mod phy_impl { + use super::*; + use id::{identify_phy, PhyIdentifier}; + + #[derive(Clone)] + pub struct Phy { + pub addr: u8, + } + + const OUI_MARVELL: u32 = 0x005043; + const OUI_REALTEK: u32 = 0x000732; + const OUI_LANTIQ : u32 = 0x355969; + + impl Phy { + /// Probe all addresses on MDIO for a known PHY + pub fn find(pa: &mut PA) -> Option { + (1..32).find(|addr| { + match identify_phy(pa, *addr) { + Some(PhyIdentifier { + oui: OUI_MARVELL, + // Marvell 88E1116R + model: 36, + .. + }) => true, + Some(PhyIdentifier { + oui: OUI_MARVELL, + // Marvell 88E1512 + model: 29, + .. + }) => true, + Some(PhyIdentifier { + oui: OUI_REALTEK, + // RTL 8211E + model: 0b010001, + rev: 0b0101, + }) => true, + Some(PhyIdentifier { + oui: OUI_LANTIQ, + // Intel XWAY PHY11G (PEF 7071/PEF 7072) v1.5 / v1.6 + model: 0, + .. + }) => true, + _ => false, + } + }).map(|addr| Phy { addr }) + } + + pub fn read_reg(&self, pa: &mut PA) -> PR + where + PA: PhyAccess, + PR: PhyRegister + From, + { + pa.read_phy(self.addr, PR::addr()).into() + } + + pub fn modify_reg(&self, pa: &mut PA, mut f: F) + where + PA: PhyAccess, + PR: PhyRegister + From + Into, + F: FnMut(PR) -> PR, + { + let reg = pa.read_phy(self.addr, PR::addr()).into(); + let reg = f(reg); + pa.write_phy(self.addr, PR::addr(), reg.into()) + } + + pub fn modify_control(&self, pa: &mut PA, f: F) + where + PA: PhyAccess, + F: FnMut(Control) -> Control, + { + self.modify_reg(pa, f) + } + + pub fn get_control(&self, pa: &mut PA) -> Control { + self.read_reg(pa) + } + + pub fn get_status(&self, pa: &mut PA) -> Status { + self.read_reg(pa) + } + + pub fn get_link(&self, pa: &mut PA) -> Option { + let status = self.get_status(pa); + if !status.link_status() { + None + } else if status.cap_1000base_t_extended_status() { + let phy_status: PSSR = self.read_reg(pa); + phy_status.get_link() + } else { + status.get_link() + } + } + + pub fn reset(&self, pa: &mut PA) { + self.modify_control(pa, |control| + control.set_reset(true) + ); + while self.get_control(pa).reset() {} + } + + pub fn restart_autoneg(&self, pa: &mut PA) { + self.modify_control(pa, |control| + control.set_autoneg_enable(true) + .set_restart_autoneg(true) + ); + } + } +} + +#[cfg(feature = "target_kasli_soc")] +mod phy_impl { + use super::*; + + #[derive(Clone)] + pub struct Phy { + } + + impl Phy { + pub fn find(_pa: &mut PA) -> Option { + Some(Phy {}) + } + + pub fn get_link(&self, _pa: &mut PA) -> Option { + Some(Link { + speed: LinkSpeed::S1000, + duplex: LinkDuplex::Full, + }) + } + + pub fn modify_control(&self, _pa: &mut PA, _f: F) + where + PA: PhyAccess, + F: FnMut(Control) -> Control, + { + } + + pub fn reset(&self, _pa: &mut PA) { + } + + pub fn restart_autoneg(&self, _pa: &mut PA) { + } + } +} + +pub use phy_impl::*;