This commit is contained in:
Sebastien Bourdeauducq 2021-07-05 13:45:22 +08:00
parent a42e5a95ff
commit 2c161720fa
1 changed files with 97 additions and 138 deletions

View File

@ -1,4 +1,5 @@
pub mod id; pub mod id;
use id::{identify_phy, PhyIdentifier};
mod status; mod status;
pub use status::Status; pub use status::Status;
mod control; mod control;
@ -34,150 +35,108 @@ pub trait PhyRegister {
fn addr() -> u8; fn addr() -> u8;
} }
#[cfg(not(feature = "target_kasli_soc"))]
mod phy_impl {
use super::*;
use id::{identify_phy, PhyIdentifier};
#[derive(Clone)] #[derive(Clone)]
pub struct Phy { pub struct Phy {
pub addr: u8, pub addr: u8,
} }
const OUI_MARVELL: u32 = 0x005043; const OUI_MARVELL: u32 = 0x005043;
const OUI_REALTEK: u32 = 0x000732; const OUI_REALTEK: u32 = 0x000732;
const OUI_LANTIQ : u32 = 0x355969; const OUI_LANTIQ : u32 = 0x355969;
impl Phy { impl Phy {
/// Probe all addresses on MDIO for a known PHY /// Probe all addresses on MDIO for a known PHY
pub fn find<PA: PhyAccess>(pa: &mut PA) -> Option<Phy> { pub fn find<PA: PhyAccess>(pa: &mut PA) -> Option<Phy> {
(0..32).find(|addr| { (0..32).find(|addr| {
match identify_phy(pa, *addr) { match identify_phy(pa, *addr) {
Some(PhyIdentifier { Some(PhyIdentifier {
oui: OUI_MARVELL, oui: OUI_MARVELL,
// Marvell 88E1116R // Marvell 88E1116R
model: 36, model: 36,
.. ..
}) => true, }) => true,
Some(PhyIdentifier { Some(PhyIdentifier {
oui: OUI_MARVELL, oui: OUI_MARVELL,
// Marvell 88E1512 // Marvell 88E1512
model: 29, model: 29,
.. ..
}) => true, }) => true,
Some(PhyIdentifier { Some(PhyIdentifier {
oui: OUI_REALTEK, oui: OUI_REALTEK,
// RTL 8211E // RTL 8211E
model: 0b010001, model: 0b010001,
rev: 0b0101, rev: 0b0101,
}) => true, }) => true,
Some(PhyIdentifier { Some(PhyIdentifier {
oui: OUI_LANTIQ, oui: OUI_LANTIQ,
// Intel XWAY PHY11G (PEF 7071/PEF 7072) v1.5 / v1.6 // Intel XWAY PHY11G (PEF 7071/PEF 7072) v1.5 / v1.6
model: 0, model: 0,
.. ..
}) => true, }) => true,
_ => false, _ => false,
}
}).map(|addr| Phy { addr })
}
pub fn read_reg<PA, PR>(&self, pa: &mut PA) -> PR
where
PA: PhyAccess,
PR: PhyRegister + From<u16>,
{
pa.read_phy(self.addr, PR::addr()).into()
}
pub fn modify_reg<PA, PR, F>(&self, pa: &mut PA, mut f: F)
where
PA: PhyAccess,
PR: PhyRegister + From<u16> + Into<u16>,
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<PA, F>(&self, pa: &mut PA, f: F)
where
PA: PhyAccess,
F: FnMut(Control) -> Control,
{
self.modify_reg(pa, f)
}
pub fn get_control<PA: PhyAccess>(&self, pa: &mut PA) -> Control {
self.read_reg(pa)
}
pub fn get_status<PA: PhyAccess>(&self, pa: &mut PA) -> Status {
self.read_reg(pa)
}
pub fn get_link<PA: PhyAccess>(&self, pa: &mut PA) -> Option<Link> {
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()
} }
} }).map(|addr| Phy { addr })
}
pub fn reset<PA: PhyAccess>(&self, pa: &mut PA) { pub fn read_reg<PA, PR>(&self, pa: &mut PA) -> PR
self.modify_control(pa, |control| where
control.set_reset(true) PA: PhyAccess,
); PR: PhyRegister + From<u16>,
while self.get_control(pa).reset() {} {
} pa.read_phy(self.addr, PR::addr()).into()
}
pub fn restart_autoneg<PA: PhyAccess>(&self, pa: &mut PA) { pub fn modify_reg<PA, PR, F>(&self, pa: &mut PA, mut f: F)
self.modify_control(pa, |control| where
control.set_autoneg_enable(true) PA: PhyAccess,
.set_restart_autoneg(true) PR: PhyRegister + From<u16> + Into<u16>,
); 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<PA, F>(&self, pa: &mut PA, f: F)
where
PA: PhyAccess,
F: FnMut(Control) -> Control,
{
self.modify_reg(pa, f)
}
pub fn get_control<PA: PhyAccess>(&self, pa: &mut PA) -> Control {
self.read_reg(pa)
}
pub fn get_status<PA: PhyAccess>(&self, pa: &mut PA) -> Status {
self.read_reg(pa)
}
pub fn get_link<PA: PhyAccess>(&self, pa: &mut PA) -> Option<Link> {
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<PA: PhyAccess>(&self, pa: &mut PA) {
self.modify_control(pa, |control|
control.set_reset(true)
);
while self.get_control(pa).reset() {}
}
pub fn restart_autoneg<PA: PhyAccess>(&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: PhyAccess>(_pa: &mut PA) -> Option<Phy> {
Some(Phy {})
}
pub fn get_link<PA: PhyAccess>(&self, _pa: &mut PA) -> Option<Link> {
Some(Link {
speed: LinkSpeed::S1000,
duplex: LinkDuplex::Full,
})
}
pub fn modify_control<PA, F>(&self, _pa: &mut PA, _f: F)
where
PA: PhyAccess,
F: FnMut(Control) -> Control,
{
}
pub fn reset<PA: PhyAccess>(&self, _pa: &mut PA) {
}
pub fn restart_autoneg<PA: PhyAccess>(&self, _pa: &mut PA) {
}
}
}
pub use phy_impl::*;