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
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:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user