From 75934754c2afc91fbefb7ee658ad61f28aabce5f Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 2 Jul 2025 10:20:39 +0200 Subject: [PATCH] continue --- examples/zedboard/src/bin/ethernet.rs | 7 +- examples/zedboard/src/phy_marvell.rs | 108 ++++++++++++++++---------- zynq7000-hal/src/eth/mod.rs | 4 +- 3 files changed, 74 insertions(+), 45 deletions(-) diff --git a/examples/zedboard/src/bin/ethernet.rs b/examples/zedboard/src/bin/ethernet.rs index 6eb22b2..3f947c6 100644 --- a/examples/zedboard/src/bin/ethernet.rs +++ b/examples/zedboard/src/bin/ethernet.rs @@ -1,8 +1,6 @@ #![no_std] #![no_main] -use arbitrary_int::{u2, u4, u5}; -use bitbybit::bitfield; use core::{mem::MaybeUninit, panic::PanicInfo}; use cortex_ar::asm::nop; use embassy_executor::Spawner; @@ -22,7 +20,7 @@ use zynq7000_hal::{ BootMode, }; -use zynq7000::{eth::MdcClkDiv, slcr::LevelShifterConfig, PsPeripherals}; +use zynq7000::{slcr::LevelShifterConfig, PsPeripherals}; use zynq7000_rt::{self as _, mmu::section_attrs::SHAREABLE_DEVICE, mmu_l1_table_mut}; const INIT_STRING: &str = "-- Zynq 7000 Zedboard Ethernet Example --\n\r"; @@ -168,7 +166,8 @@ async fn main(_spawner: Spawner) -> ! { ); eth.set_rx_buf_descriptor_base_address(rx_descr_ref.base_addr()); eth.set_tx_buf_descriptor_base_address(tx_descr_ref.base_addr()); - let (mut phy, phy_rev) = Marvell88E1518Phy::new_autoprobe_addr(eth.mdio_mut()).unwrap(); + let (mut phy, phy_rev) = + zedboard::phy_marvell::Marvell88E1518Phy::new_autoprobe_addr(eth.mdio_mut()).unwrap(); info!( "Detected Marvell 88E1518 PHY with revision number: {:?}", phy_rev diff --git a/examples/zedboard/src/phy_marvell.rs b/examples/zedboard/src/phy_marvell.rs index 45905d4..4f86b78 100644 --- a/examples/zedboard/src/phy_marvell.rs +++ b/examples/zedboard/src/phy_marvell.rs @@ -1,3 +1,5 @@ +use arbitrary_int::{u2, u4, u5}; + #[derive(Clone, Debug)] pub struct PhyIdentifier { pub oui: u32, @@ -11,43 +13,11 @@ const MARVELL_88E1518_MODELL_NUMBER: u8 = 0b011101; #[bitbybit::bitenum(u5, exhaustive = false)] pub enum MarvellRegistersPage0 { - CopperControl = 0x00, - CopperStatus = 0x01, - IdReg1 = 0x02, - IdReg2 = 0x03, -} - -pub struct Marvell88E1518Phy { - mdio: zynq7000_hal::eth::mdio::Mdio, - addr: u5, -} - -impl<'mdio> Marvell88E1518Phy<'mdio> { - pub fn new_autoprobe_addr(mdio: &zynq7000_hal::eth::mdio::Mdio) -> Option<(Self, u4)> { - for addr in 0..32 { - let phy_id_1 = - mdio.read_blocking(u5::new(addr), MarvellRegistersPage0::IdReg1.raw_value()); - let phy_id_2 = - mdio.read_blocking(u5::new(addr), MarvellRegistersPage0::IdReg2.raw_value()); - let oui = (((phy_id_2 as u32) >> 10) << 19) | ((phy_id_1 as u32) << 3); - let model_number = ((phy_id_2 >> 4) & 0b111111) as u8; - let revision_number = u4::new((phy_id_2 & 0b1111) as u8); - if oui == MARVELL_88E1518_OUI && model_number == MARVELL_88E1518_MODELL_NUMBER { - return Some(( - Self { - mdio: unsafe { mdio.clone() }, - addr: u5::new(addr), - }, - revision_number, - )); - } - } - None - } - - pub fn new(mdio: zynq7000_hal::eth::mdio::Mdio, addr: u5) -> Self { - Self { mdio, addr } - } + CopperControl = 0, + CopperStatus = 1, + IdReg1 = 2, + IdReg2 = 3, + CopperSpecificStatus = 17, } #[bitbybit::bitfield(u16)] @@ -154,10 +124,55 @@ pub struct CopperSpecificStatusRegister { speed_and_duplex_resolved: bool, /// This is the real-time link status. #[bit(10, r)] - copper_link: bool + copper_link: bool, + #[bit(9, r)] + transmit_pause_enabled: bool, + #[bit(8, r)] + received_pause_enabled: bool, + #[bit(6, r)] + mdi_crossover_status: bool, + #[bit(4, r)] + copper_energy_detect_status: bool, + #[bit(3, r)] + global_link_status: bool, + #[bit(1, r)] + polarity: bool, + #[bit(0, r)] + jabber: bool, } -impl Marvell88E1518Phy<'_> { +pub struct Marvell88E1518Phy { + mdio: zynq7000_hal::eth::mdio::Mdio, + addr: u5, +} + +impl Marvell88E1518Phy { + pub fn new_autoprobe_addr(mdio: &mut zynq7000_hal::eth::mdio::Mdio) -> Option<(Self, u4)> { + for addr in 0..32 { + let phy_id_1 = + mdio.read_blocking(u5::new(addr), MarvellRegistersPage0::IdReg1.raw_value()); + let phy_id_2 = + mdio.read_blocking(u5::new(addr), MarvellRegistersPage0::IdReg2.raw_value()); + let oui = (((phy_id_2 as u32) >> 10) << 19) | ((phy_id_1 as u32) << 3); + let model_number = ((phy_id_2 >> 4) & 0b111111) as u8; + let revision_number = u4::new((phy_id_2 & 0b1111) as u8); + if oui == MARVELL_88E1518_OUI && model_number == MARVELL_88E1518_MODELL_NUMBER { + return Some(( + Self { + mdio: unsafe { mdio.clone() }, + addr: u5::new(addr), + }, + revision_number, + )); + } + } + None + } + + pub fn new(mdio: zynq7000_hal::eth::mdio::Mdio, addr: u5) -> Self { + Self { mdio, addr } + } + pub fn reset(&mut self) { let mut ctrl = CopperControlRegister::new_with_raw_value( self.mdio @@ -184,4 +199,19 @@ impl Marvell88E1518Phy<'_> { ctrl.raw_value(), ); } + + pub fn read_copper_status(&mut self) -> CopperStatusRegister { + let raw_value = self + .mdio + .read_blocking(self.addr, MarvellRegistersPage0::CopperStatus.raw_value()); + CopperStatusRegister::new_with_raw_value(raw_value) + } + + pub fn read_copper_specific_status_register_1(&mut self) -> CopperSpecificStatusRegister { + let raw_value = self.mdio.read_blocking( + self.addr, + MarvellRegistersPage0::CopperSpecificStatus.raw_value(), + ); + CopperSpecificStatusRegister::new_with_raw_value(raw_value) + } } diff --git a/zynq7000-hal/src/eth/mod.rs b/zynq7000-hal/src/eth/mod.rs index 299196c..fa9e795 100644 --- a/zynq7000-hal/src/eth/mod.rs +++ b/zynq7000-hal/src/eth/mod.rs @@ -1,7 +1,7 @@ use arbitrary_int::{u2, u3}; pub use zynq7000::eth::MdcClkDiv; use zynq7000::eth::{ - BurstLength, DmaRxBufSize, MmioEthernet, NetworkConfig, SpeedMode, GEM_0_BASE_ADDR, + BurstLength, DmaRxBufSize, MmioEthernet, SpeedMode, GEM_0_BASE_ADDR, GEM_1_BASE_ADDR, }; @@ -394,7 +394,7 @@ impl Ethernet { ll.configure_clock(config.clk_config); let mut mdio = mdio::Mdio::new(&ll, true); mdio.configure_clock_div(config.mdc_clk_div); - let eth = Ethernet { ll, mdio } + let mut eth = Ethernet { ll, mdio }; eth.set_rx_buf_descriptor_base_address(0); eth.set_tx_buf_descriptor_base_address(0); eth