stm32/eth: Move phy_addr
from Ethernet
to PHY
Previously, PHY addressing was a concern of the `Ethernet` struct which limited the `PHY` implementations which very often have to manage multiple PHYs internally and thus possibly need to address many of them. This change extends `StationManagement` to allow addressing different PHY addresses via SMI.
This commit is contained in:
parent
c3ef98a73d
commit
7526b8edba
@ -41,39 +41,40 @@ mod phy_consts {
|
||||
}
|
||||
use self::phy_consts::*;
|
||||
|
||||
/// Generic SMI Ethernet PHY
|
||||
/// Generic SMI Ethernet PHY implementation
|
||||
pub struct GenericSMI {
|
||||
phy_addr: u8,
|
||||
#[cfg(feature = "time")]
|
||||
poll_interval: Duration,
|
||||
#[cfg(not(feature = "time"))]
|
||||
_private: (),
|
||||
}
|
||||
|
||||
impl GenericSMI {
|
||||
pub fn new() -> Self {
|
||||
/// Construct the PHY. It assumes the address `phy_addr` in the SMI communication
|
||||
pub fn new(phy_addr: u8) -> Self {
|
||||
Self {
|
||||
phy_addr,
|
||||
#[cfg(feature = "time")]
|
||||
poll_interval: Duration::from_millis(500),
|
||||
#[cfg(not(feature = "time"))]
|
||||
_private: (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl PHY for GenericSMI {
|
||||
/// Reset PHY and wait for it to come out of reset.
|
||||
fn phy_reset<S: StationManagement>(&mut self, sm: &mut S) {
|
||||
sm.smi_write(PHY_REG_BCR, PHY_REG_BCR_RESET);
|
||||
while sm.smi_read(PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {}
|
||||
sm.smi_write(self.phy_addr, PHY_REG_BCR, PHY_REG_BCR_RESET);
|
||||
while sm.smi_read(self.phy_addr, PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {}
|
||||
}
|
||||
|
||||
/// PHY initialisation.
|
||||
fn phy_init<S: StationManagement>(&mut self, sm: &mut S) {
|
||||
// Clear WU CSR
|
||||
self.smi_write_ext(sm, PHY_REG_WUCSR, 0);
|
||||
|
||||
// Enable auto-negotiation
|
||||
sm.smi_write(PHY_REG_BCR, PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M);
|
||||
sm.smi_write(
|
||||
self.phy_addr,
|
||||
PHY_REG_BCR,
|
||||
PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M,
|
||||
);
|
||||
}
|
||||
|
||||
fn poll_link<S: StationManagement>(&mut self, sm: &mut S, cx: &mut Context) -> bool {
|
||||
@ -83,7 +84,7 @@ unsafe impl PHY for GenericSMI {
|
||||
#[cfg(feature = "time")]
|
||||
let _ = Timer::after(self.poll_interval).poll_unpin(cx);
|
||||
|
||||
let bsr = sm.smi_read(PHY_REG_BSR);
|
||||
let bsr = sm.smi_read(self.phy_addr, PHY_REG_BSR);
|
||||
|
||||
// No link without autonegotiate
|
||||
if bsr & PHY_REG_BSR_ANDONE == 0 {
|
||||
@ -108,9 +109,9 @@ impl GenericSMI {
|
||||
|
||||
// Writes a value to an extended PHY register in MMD address space
|
||||
fn smi_write_ext<S: StationManagement>(&mut self, sm: &mut S, reg_addr: u16, reg_data: u16) {
|
||||
sm.smi_write(PHY_REG_CTL, 0x0003); // set address
|
||||
sm.smi_write(PHY_REG_ADDAR, reg_addr);
|
||||
sm.smi_write(PHY_REG_CTL, 0x4003); // set data
|
||||
sm.smi_write(PHY_REG_ADDAR, reg_data);
|
||||
sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x0003); // set address
|
||||
sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_addr);
|
||||
sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x4003); // set data
|
||||
sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_data);
|
||||
}
|
||||
}
|
||||
|
@ -134,9 +134,9 @@ impl<'a, 'd> embassy_net_driver::TxToken for TxToken<'a, 'd> {
|
||||
/// The methods cannot move out of self
|
||||
pub unsafe trait StationManagement {
|
||||
/// Read a register over SMI.
|
||||
fn smi_read(&mut self, reg: u8) -> u16;
|
||||
fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16;
|
||||
/// Write a register over SMI.
|
||||
fn smi_write(&mut self, reg: u8, val: u16);
|
||||
fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16);
|
||||
}
|
||||
|
||||
/// Traits for an Ethernet PHY
|
||||
|
@ -107,7 +107,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
|
||||
tx_en: impl Peripheral<P = impl TXEnPin<T>> + 'd,
|
||||
phy: P,
|
||||
mac_addr: [u8; 6],
|
||||
phy_addr: u8,
|
||||
) -> Self {
|
||||
into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
|
||||
|
||||
@ -227,7 +226,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
|
||||
station_management: EthernetStationManagement {
|
||||
peri: PhantomData,
|
||||
clock_range: clock_range,
|
||||
phy_addr: phy_addr,
|
||||
},
|
||||
mac_addr,
|
||||
tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf),
|
||||
@ -271,15 +269,14 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
|
||||
pub struct EthernetStationManagement<T: Instance> {
|
||||
peri: PhantomData<T>,
|
||||
clock_range: Cr,
|
||||
phy_addr: u8,
|
||||
}
|
||||
|
||||
unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
|
||||
fn smi_read(&mut self, reg: u8) -> u16 {
|
||||
fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 {
|
||||
let mac = ETH.ethernet_mac();
|
||||
|
||||
mac.macmiiar().modify(|w| {
|
||||
w.set_pa(self.phy_addr);
|
||||
w.set_pa(phy_addr);
|
||||
w.set_mr(reg);
|
||||
w.set_mw(Mw::READ); // read operation
|
||||
w.set_cr(self.clock_range);
|
||||
@ -289,12 +286,12 @@ unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
|
||||
mac.macmiidr().read().md()
|
||||
}
|
||||
|
||||
fn smi_write(&mut self, reg: u8, val: u16) {
|
||||
fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) {
|
||||
let mac = ETH.ethernet_mac();
|
||||
|
||||
mac.macmiidr().write(|w| w.set_md(val));
|
||||
mac.macmiiar().modify(|w| {
|
||||
w.set_pa(self.phy_addr);
|
||||
w.set_pa(phy_addr);
|
||||
w.set_mr(reg);
|
||||
w.set_mw(Mw::WRITE); // write
|
||||
w.set_cr(self.clock_range);
|
||||
|
@ -71,7 +71,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
|
||||
tx_en: impl Peripheral<P = impl TXEnPin<T>> + 'd,
|
||||
phy: P,
|
||||
mac_addr: [u8; 6],
|
||||
phy_addr: u8,
|
||||
) -> Self {
|
||||
into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
|
||||
|
||||
@ -202,7 +201,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
|
||||
station_management: EthernetStationManagement {
|
||||
peri: PhantomData,
|
||||
clock_range: clock_range,
|
||||
phy_addr: phy_addr,
|
||||
},
|
||||
mac_addr,
|
||||
};
|
||||
@ -242,15 +240,14 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
|
||||
pub struct EthernetStationManagement<T: Instance> {
|
||||
peri: PhantomData<T>,
|
||||
clock_range: u8,
|
||||
phy_addr: u8,
|
||||
}
|
||||
|
||||
unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
|
||||
fn smi_read(&mut self, reg: u8) -> u16 {
|
||||
fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 {
|
||||
let mac = ETH.ethernet_mac();
|
||||
|
||||
mac.macmdioar().modify(|w| {
|
||||
w.set_pa(self.phy_addr);
|
||||
w.set_pa(phy_addr);
|
||||
w.set_rda(reg);
|
||||
w.set_goc(0b11); // read
|
||||
w.set_cr(self.clock_range);
|
||||
@ -260,12 +257,12 @@ unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
|
||||
mac.macmdiodr().read().md()
|
||||
}
|
||||
|
||||
fn smi_write(&mut self, reg: u8, val: u16) {
|
||||
fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) {
|
||||
let mac = ETH.ethernet_mac();
|
||||
|
||||
mac.macmdiodr().write(|w| w.set_md(val));
|
||||
mac.macmdioar().modify(|w| {
|
||||
w.set_pa(self.phy_addr);
|
||||
w.set_pa(phy_addr);
|
||||
w.set_rda(reg);
|
||||
w.set_goc(0b01); // write
|
||||
w.set_cr(self.clock_range);
|
||||
|
Loading…
Reference in New Issue
Block a user