forked from M-Labs/zynq-rs
phy: implement control, status, reset
This commit is contained in:
parent
e6827a81f3
commit
5823d90db1
@ -355,6 +355,28 @@ impl<RX, TX> Eth<RX, TX> {
|
|||||||
fn wait_phy_idle(&self) {
|
fn wait_phy_idle(&self) {
|
||||||
while !self.regs.net_status.read().phy_mgmt_idle() {}
|
while !self.regs.net_status.read().phy_mgmt_idle() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reset_phy(&mut self) -> bool {
|
||||||
|
match phy::Phy::find(self) {
|
||||||
|
Some(phy) => {
|
||||||
|
phy.modify_control(self, |control|
|
||||||
|
control.set_reset(true)
|
||||||
|
);
|
||||||
|
while phy.get_control(self).reset() {
|
||||||
|
println!("Wait for PHY reset");
|
||||||
|
}
|
||||||
|
phy.modify_control(self, |control|
|
||||||
|
control.set_autoneg_enable(true)
|
||||||
|
.set_restart_autoneg(true)
|
||||||
|
);
|
||||||
|
// 125 MHz for 1000base-TX
|
||||||
|
Self::setup_gem0_clock(125);
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
None => false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'rx, TX> Eth<rx::DescList<'rx>, TX> {
|
impl<'rx, TX> Eth<rx::DescList<'rx>, TX> {
|
||||||
|
97
src/eth/phy/control.rs
Normal file
97
src/eth/phy/control.rs
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
use bit_field::BitField;
|
||||||
|
use super::PhyRegister;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
/// Basic Mode Control Register
|
||||||
|
pub struct Control(pub u16);
|
||||||
|
|
||||||
|
impl Control {
|
||||||
|
pub fn speed1(&self) -> bool {
|
||||||
|
self.0.get_bit(6)
|
||||||
|
}
|
||||||
|
pub fn set_speed1(mut self, value: bool) -> Self {
|
||||||
|
self.0.set_bit(6, value);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn collision_test(&self) -> bool {
|
||||||
|
self.0.get_bit(7)
|
||||||
|
}
|
||||||
|
pub fn set_collision_test(mut self, value: bool) -> Self {
|
||||||
|
self.0.set_bit(7, value);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn duplex(&self) -> bool {
|
||||||
|
self.0.get_bit(8)
|
||||||
|
}
|
||||||
|
pub fn set_duplex(mut self, value: bool) -> Self {
|
||||||
|
self.0.set_bit(8, value);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn restart_autoneg(&self) -> bool {
|
||||||
|
self.0.get_bit(9)
|
||||||
|
}
|
||||||
|
pub fn set_restart_autoneg(mut self, value: bool) -> Self {
|
||||||
|
self.0.set_bit(9, value);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn isolate(&self) -> bool {
|
||||||
|
self.0.get_bit(10)
|
||||||
|
}
|
||||||
|
pub fn set_isolate(mut self, value: bool) -> Self {
|
||||||
|
self.0.set_bit(10, value);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn power_down(&self) -> bool {
|
||||||
|
self.0.get_bit(11)
|
||||||
|
}
|
||||||
|
pub fn set_power_down(mut self, value: bool) -> Self {
|
||||||
|
self.0.set_bit(11, value);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn autoneg_enable(&self) -> bool {
|
||||||
|
self.0.get_bit(12)
|
||||||
|
}
|
||||||
|
pub fn set_autoneg_enable(mut self, value: bool) -> Self {
|
||||||
|
self.0.set_bit(12, value);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn speed0(&self) -> bool {
|
||||||
|
self.0.get_bit(13)
|
||||||
|
}
|
||||||
|
pub fn set_speed0(mut self, value: bool) -> Self {
|
||||||
|
self.0.set_bit(13, value);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn loopback(&self) -> bool {
|
||||||
|
self.0.get_bit(14)
|
||||||
|
}
|
||||||
|
pub fn set_loopback(mut self, value: bool) -> Self {
|
||||||
|
self.0.set_bit(14, value);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn reset(&self) -> bool {
|
||||||
|
self.0.get_bit(15)
|
||||||
|
}
|
||||||
|
pub fn set_reset(mut self, value: bool) -> Self {
|
||||||
|
self.0.set_bit(15, value);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PhyRegister for Control {
|
||||||
|
fn addr() -> u8 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u16> for Control {
|
||||||
|
fn from(value: u16) -> Self {
|
||||||
|
Control(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<u16> for Control {
|
||||||
|
fn into(self) -> u16 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,21 @@
|
|||||||
pub mod id;
|
pub mod id;
|
||||||
use id::{identify_phy, PhyIdentifier};
|
use id::{identify_phy, PhyIdentifier};
|
||||||
|
mod status;
|
||||||
|
pub use status::Status;
|
||||||
|
mod control;
|
||||||
|
pub use control::Control;
|
||||||
|
|
||||||
pub trait PhyAccess {
|
pub trait PhyAccess {
|
||||||
fn read_phy(&mut self, addr: u8, reg: u8) -> u16;
|
fn read_phy(&mut self, addr: u8, reg: u8) -> u16;
|
||||||
fn write_phy(&mut self, addr: u8, reg: u8, data: u16);
|
fn write_phy(&mut self, addr: u8, reg: u8, data: u16);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Phy {
|
pub struct Phy {
|
||||||
|
pub addr: u8,
|
||||||
|
device: PhyDevice,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum PhyDevice {
|
||||||
Marvel88E1116R,
|
Marvel88E1116R,
|
||||||
Rtl8211E,
|
Rtl8211E,
|
||||||
}
|
}
|
||||||
@ -16,20 +25,25 @@ const OUI_REALTEK: u32 = 0x000732;
|
|||||||
|
|
||||||
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<(u8, Phy)> {
|
pub fn find<PA: PhyAccess>(pa: &mut PA) -> Option<Phy> {
|
||||||
for addr in 1..32 {
|
for addr in 1..32 {
|
||||||
match identify_phy(pa, addr) {
|
let device = match identify_phy(pa, addr) {
|
||||||
Some(PhyIdentifier {
|
Some(PhyIdentifier {
|
||||||
oui: OUI_MARVEL,
|
oui: OUI_MARVEL,
|
||||||
model: 36,
|
model: 36,
|
||||||
..
|
..
|
||||||
}) => return Some((addr, Phy::Marvel88E1116R)),
|
}) => Some(PhyDevice::Marvel88E1116R),
|
||||||
Some(PhyIdentifier {
|
Some(PhyIdentifier {
|
||||||
oui: OUI_REALTEK,
|
oui: OUI_REALTEK,
|
||||||
model: 0b010001,
|
model: 0b010001,
|
||||||
rev: 0b0101,
|
rev: 0b0101,
|
||||||
}) => return Some((addr, Phy::Rtl8211E)),
|
}) => Some(PhyDevice::Rtl8211E),
|
||||||
_ => {}
|
_ => None,
|
||||||
|
};
|
||||||
|
match device {
|
||||||
|
Some(device) =>
|
||||||
|
return Some(Phy { addr, device }),
|
||||||
|
None => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,9 +51,48 @@ impl Phy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> &'static str {
|
pub fn name(&self) -> &'static str {
|
||||||
match self {
|
match self.device {
|
||||||
Phy::Marvel88E1116R => &"Marvel 88E1116R",
|
PhyDevice::Marvel88E1116R => &"Marvel 88E1116R",
|
||||||
Phy::Rtl8211E => &"RTL8211E",
|
PhyDevice::Rtl8211E => &"RTL8211E",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 trait PhyRegister {
|
||||||
|
fn addr() -> u8;
|
||||||
}
|
}
|
||||||
|
66
src/eth/phy/status.rs
Normal file
66
src/eth/phy/status.rs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
use bit_field::BitField;
|
||||||
|
use super::PhyRegister;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
/// Basic Mode Status Register
|
||||||
|
pub struct Status(pub u16);
|
||||||
|
|
||||||
|
impl Status {
|
||||||
|
pub fn extended_capability(&self) -> bool {
|
||||||
|
self.0.get_bit(0)
|
||||||
|
}
|
||||||
|
pub fn jabber_detect(&self) -> bool {
|
||||||
|
self.0.get_bit(1)
|
||||||
|
}
|
||||||
|
pub fn link_status(&self) -> bool {
|
||||||
|
self.0.get_bit(2)
|
||||||
|
}
|
||||||
|
pub fn autoneg_ability(&self) -> bool {
|
||||||
|
self.0.get_bit(3)
|
||||||
|
}
|
||||||
|
pub fn remote_fault(&self) -> bool {
|
||||||
|
self.0.get_bit(4)
|
||||||
|
}
|
||||||
|
pub fn autoneg_complete(&self) -> bool {
|
||||||
|
self.0.get_bit(5)
|
||||||
|
}
|
||||||
|
pub fn preamble_suppression(&self) -> bool {
|
||||||
|
self.0.get_bit(6)
|
||||||
|
}
|
||||||
|
pub fn cap_1000base_t_extended_status(&self) -> bool {
|
||||||
|
self.0.get_bit(8)
|
||||||
|
}
|
||||||
|
pub fn cap_10base_t2_half(&self) -> bool {
|
||||||
|
self.0.get_bit(9)
|
||||||
|
}
|
||||||
|
pub fn cap_10base_t2_full(&self) -> bool {
|
||||||
|
self.0.get_bit(10)
|
||||||
|
}
|
||||||
|
pub fn cap_10base_t_half(&self) -> bool {
|
||||||
|
self.0.get_bit(11)
|
||||||
|
}
|
||||||
|
pub fn cap_10base_t_full(&self) -> bool {
|
||||||
|
self.0.get_bit(12)
|
||||||
|
}
|
||||||
|
pub fn cap_100base_tx_half(&self) -> bool {
|
||||||
|
self.0.get_bit(13)
|
||||||
|
}
|
||||||
|
pub fn cap_100base_tx_full(&self) -> bool {
|
||||||
|
self.0.get_bit(14)
|
||||||
|
}
|
||||||
|
pub fn cap_100base_t4(&self) -> bool {
|
||||||
|
self.0.get_bit(15)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PhyRegister for Status {
|
||||||
|
fn addr() -> u8 {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u16> for Status {
|
||||||
|
fn from(value: u16) -> Self {
|
||||||
|
Status(value)
|
||||||
|
}
|
||||||
|
}
|
17
src/main.rs
17
src/main.rs
@ -75,22 +75,7 @@ fn main() {
|
|||||||
|
|
||||||
let mut eth = eth::Eth::default([0x0, 0x17, 0xde, 0xea, 0xbe, 0xef]);
|
let mut eth = eth::Eth::default([0x0, 0x17, 0xde, 0xea, 0xbe, 0xef]);
|
||||||
println!("Eth on");
|
println!("Eth on");
|
||||||
match eth::phy::Phy::find(&mut eth) {
|
eth.reset_phy();
|
||||||
Some((addr, phy)) => {
|
|
||||||
println!("Found {} PHY at addr {}", phy.name(), addr);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
use eth::phy::PhyAccess;
|
|
||||||
for addr in 1..32 {
|
|
||||||
match eth::phy::id::identify_phy(&mut eth, addr) {
|
|
||||||
Some(identifier) => {
|
|
||||||
println!("phy {}: {:?}", addr, identifier);
|
|
||||||
}
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut rx_descs: [eth::rx::DescEntry; 8] = unsafe { uninitialized() };
|
let mut rx_descs: [eth::rx::DescEntry; 8] = unsafe { uninitialized() };
|
||||||
let mut rx_buffers = [[0u8; 1536]; 8];
|
let mut rx_buffers = [[0u8; 1536]; 8];
|
||||||
|
Loading…
Reference in New Issue
Block a user