continue
Some checks failed
ci / Check build (push) Has been cancelled
ci / Check formatting (push) Has been cancelled
ci / Check Documentation Build (push) Has been cancelled
ci / Clippy (push) Has been cancelled
ci / Check build (pull_request) Has been cancelled
ci / Check formatting (pull_request) Has been cancelled
ci / Check Documentation Build (pull_request) Has been cancelled
ci / Clippy (pull_request) Has been cancelled

This commit is contained in:
2025-07-02 10:20:39 +02:00
parent 0fb096a1db
commit 75934754c2
3 changed files with 74 additions and 45 deletions

View File

@@ -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

View File

@@ -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)
}
}

View File

@@ -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