From 2e7b42fc5b62f134bc1c477e4817e0c512c399b3 Mon Sep 17 00:00:00 2001
From: David Lenfesty <lenfesty@ualberta.ca>
Date: Mon, 25 Apr 2022 19:57:09 -0600
Subject: [PATCH] embassy-stm32/eth: convert LAN8742 driver to generic SMI
 driver

SMI Ethernet PHYs all share a common base set of registers that can do
90% of all tasks. The LAN8742 driver used some vendor-specific
registers to check link negotiation status, but the need for that was
debatable, so I migrated it to a generic driver instead, anybody who
wants extra functionality can copy it and impl their own on top of it.
---
 .../src/eth/{lan8742a.rs => generic_smi.rs}   | 29 ++++---------------
 embassy-stm32/src/eth/mod.rs                  |  2 +-
 examples/stm32f7/src/bin/eth.rs               |  8 ++---
 examples/stm32h7/src/bin/eth.rs               |  8 ++---
 4 files changed, 15 insertions(+), 32 deletions(-)
 rename embassy-stm32/src/eth/{lan8742a.rs => generic_smi.rs} (74%)

diff --git a/embassy-stm32/src/eth/lan8742a.rs b/embassy-stm32/src/eth/generic_smi.rs
similarity index 74%
rename from embassy-stm32/src/eth/lan8742a.rs
rename to embassy-stm32/src/eth/generic_smi.rs
index 74d0ca5d..5a323bf5 100644
--- a/embassy-stm32/src/eth/lan8742a.rs
+++ b/embassy-stm32/src/eth/generic_smi.rs
@@ -1,4 +1,4 @@
-//! SMSC LAN8742A Ethernet PHY
+//! Generic SMI Ethernet PHY
 
 use super::{StationManagement, PHY};
 
@@ -13,7 +13,6 @@ mod phy_consts {
     pub const PHY_REG_ANEXP: u8 = 0x06;
     pub const PHY_REG_ANNPTX: u8 = 0x07;
     pub const PHY_REG_ANNPRX: u8 = 0x08;
-    pub const PHY_REG_SSR: u8 = 0x1F; // Special Status Register
     pub const PHY_REG_CTL: u8 = 0x0D; // Ethernet PHY Register Control
     pub const PHY_REG_ADDAR: u8 = 0x0E; // Ethernet PHY Address or Data
 
@@ -33,20 +32,13 @@ mod phy_consts {
     pub const PHY_REG_BSR_UP: u16 = 1 << 2;
     pub const PHY_REG_BSR_FAULT: u16 = 1 << 4;
     pub const PHY_REG_BSR_ANDONE: u16 = 1 << 5;
-
-    pub const PHY_REG_SSR_ANDONE: u16 = 1 << 12;
-    pub const PHY_REG_SSR_SPEED: u16 = 0b111 << 2;
-    pub const PHY_REG_SSR_10BASE_HD: u16 = 0b001 << 2;
-    pub const PHY_REG_SSR_10BASE_FD: u16 = 0b101 << 2;
-    pub const PHY_REG_SSR_100BASE_HD: u16 = 0b010 << 2;
-    pub const PHY_REG_SSR_100BASE_FD: u16 = 0b110 << 2;
 }
 use self::phy_consts::*;
 
-/// SMSC LAN8742A Ethernet PHY
-pub struct LAN8742A;
+/// Generic SMI Ethernet PHY
+pub struct GenericSMI;
 
-unsafe impl PHY for LAN8742A {
+unsafe impl PHY for GenericSMI {
     /// Reset PHY and wait for it to come out of reset.
     fn phy_reset<S: StationManagement>(sm: &mut S) {
         sm.smi_write(PHY_REG_BCR, PHY_REG_BCR_RESET);
@@ -67,7 +59,6 @@ unsafe impl PHY for LAN8742A {
 
     fn poll_link<S: StationManagement>(sm: &mut S) -> bool {
         let bsr = sm.smi_read(PHY_REG_BSR);
-        let ssr = sm.smi_read(PHY_REG_SSR);
 
         // No link without autonegotiate
         if bsr & PHY_REG_BSR_ANDONE == 0 {
@@ -77,22 +68,14 @@ unsafe impl PHY for LAN8742A {
         if bsr & PHY_REG_BSR_UP == 0 {
             return false;
         }
-        // No link if autonegotiate incomplete
-        if ssr & PHY_REG_SSR_ANDONE == 0 {
-            return false;
-        }
-        // No link if other side isn't 100Mbps full duplex
-        if ssr & PHY_REG_SSR_SPEED != PHY_REG_SSR_100BASE_FD {
-            return false;
-        }
 
         // Got link
         true
     }
 }
 
-/// Public functions for the LAN8742A
-impl LAN8742A {
+/// Public functions for the PHY
+impl GenericSMI {
     // Writes a value to an extended PHY register in MMD address space
     fn smi_write_ext<S: StationManagement>(sm: &mut S, reg_addr: u16, reg_data: u16) {
         sm.smi_write(PHY_REG_CTL, 0x0003); // set address
diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs
index ef5424e5..1c0d13fe 100644
--- a/embassy-stm32/src/eth/mod.rs
+++ b/embassy-stm32/src/eth/mod.rs
@@ -5,7 +5,7 @@
 #[cfg_attr(eth_v2, path = "v2/mod.rs")]
 #[cfg_attr(eth_v1, path = "v1.rs")]
 mod _version;
-pub mod lan8742a;
+pub mod generic_smi;
 
 pub use _version::*;
 
diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs
index 446756c2..33e41de9 100644
--- a/examples/stm32f7/src/bin/eth.rs
+++ b/examples/stm32f7/src/bin/eth.rs
@@ -11,7 +11,7 @@ use embassy::util::Forever;
 use embassy_net::{
     Config as NetConfig, Ipv4Address, Ipv4Cidr, StackResources, StaticConfigurator, TcpSocket,
 };
-use embassy_stm32::eth::lan8742a::LAN8742A;
+use embassy_stm32::eth::generic_smi::GenericSMI;
 use embassy_stm32::eth::{Ethernet, State};
 use embassy_stm32::interrupt;
 use embassy_stm32::peripherals::ETH;
@@ -26,7 +26,7 @@ use panic_probe as _;
 
 #[embassy::task]
 async fn main_task(
-    device: &'static mut Ethernet<'static, ETH, LAN8742A, 4, 4>,
+    device: &'static mut Ethernet<'static, ETH, GenericSMI, 4, 4>,
     config: &'static mut StaticConfigurator,
     spawner: Spawner,
 ) {
@@ -82,7 +82,7 @@ static mut RNG_INST: Option<Rng<RNG>> = None;
 
 static EXECUTOR: Forever<Executor> = Forever::new();
 static STATE: Forever<State<'static, ETH, 4, 4>> = Forever::new();
-static ETH: Forever<Ethernet<'static, ETH, LAN8742A, 4, 4>> = Forever::new();
+static ETH: Forever<Ethernet<'static, ETH, GenericSMI, 4, 4>> = Forever::new();
 static CONFIG: Forever<StaticConfigurator> = Forever::new();
 static NET_RESOURCES: Forever<StackResources<1, 2, 8>> = Forever::new();
 
@@ -112,7 +112,7 @@ fn main() -> ! {
     let eth = unsafe {
         ETH.put(Ethernet::new(
             state, p.ETH, eth_int, p.PA1, p.PA2, p.PC1, p.PA7, p.PC4, p.PC5, p.PG13, p.PB13,
-            p.PG11, LAN8742A, mac_addr, 0,
+            p.PG11, GenericSMI, mac_addr, 0,
         ))
     };
 
diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs
index 4eb5421a..9a2e7a33 100644
--- a/examples/stm32h7/src/bin/eth.rs
+++ b/examples/stm32h7/src/bin/eth.rs
@@ -14,7 +14,7 @@ use embassy::util::Forever;
 use embassy_net::{
     Config as NetConfig, Ipv4Address, Ipv4Cidr, StackResources, StaticConfigurator, TcpSocket,
 };
-use embassy_stm32::eth::lan8742a::LAN8742A;
+use embassy_stm32::eth::generic_smi::GenericSMI;
 use embassy_stm32::eth::{Ethernet, State};
 use embassy_stm32::interrupt;
 use embassy_stm32::peripherals::ETH;
@@ -26,7 +26,7 @@ use heapless::Vec;
 
 #[embassy::task]
 async fn main_task(
-    device: &'static mut Ethernet<'static, ETH, LAN8742A, 4, 4>,
+    device: &'static mut Ethernet<'static, ETH, GenericSMI, 4, 4>,
     config: &'static mut StaticConfigurator,
     spawner: Spawner,
 ) {
@@ -82,7 +82,7 @@ static mut RNG_INST: Option<Rng<RNG>> = None;
 
 static EXECUTOR: Forever<Executor> = Forever::new();
 static STATE: Forever<State<'static, ETH, 4, 4>> = Forever::new();
-static ETH: Forever<Ethernet<'static, ETH, LAN8742A, 4, 4>> = Forever::new();
+static ETH: Forever<Ethernet<'static, ETH, GenericSMI, 4, 4>> = Forever::new();
 static CONFIG: Forever<StaticConfigurator> = Forever::new();
 static NET_RESOURCES: Forever<StackResources<1, 2, 8>> = Forever::new();
 
@@ -114,7 +114,7 @@ fn main() -> ! {
     let eth = unsafe {
         ETH.put(Ethernet::new(
             state, p.ETH, eth_int, p.PA1, p.PA2, p.PC1, p.PA7, p.PC4, p.PC5, p.PG13, p.PB13,
-            p.PG11, LAN8742A, mac_addr, 0,
+            p.PG11, GenericSMI, mac_addr, 0,
         ))
     };