summaryrefslogtreecommitdiff
path: root/ports/stm32/eth_phy.c
diff options
context:
space:
mode:
Diffstat (limited to 'ports/stm32/eth_phy.c')
-rw-r--r--ports/stm32/eth_phy.c68
1 files changed, 64 insertions, 4 deletions
diff --git a/ports/stm32/eth_phy.c b/ports/stm32/eth_phy.c
index 56cddba9c..cdc632f26 100644
--- a/ports/stm32/eth_phy.c
+++ b/ports/stm32/eth_phy.c
@@ -31,18 +31,45 @@
#if defined(MICROPY_HW_ETH_MDC)
#define PHY_SCSR_LAN87XX (0x001f)
-#define PHY_SCSR_LAN87XX_SPEED_Pos (2)
-#define PHY_SCSR_LAN87XX_SPEED_Msk (7)
+#define PHY_SCSR_LAN87XX_10M_Msk (0x0004)
+#define PHY_SCSR_LAN87XX_100M_Msk (0x0008)
+#define PHY_SCSR_LAN87XX_DUPLEX_Msk (0x0010)
#define PHY_SCSR_DP838XX (0x0010)
#define PHY_RECR_DP838XX (0x0015)
#define PHY_SCSR_DP838XX_DUPLEX_Msk (4)
#define PHY_SCSR_DP838XX_10M_Msk (2)
+#define PHY_RTL8211_DEFAULT_PAGE (0xa42)
+#define PHY_RTL8211_PAGSR_ADDR (0x1f)
+#define PHY_RTL8211_PHYSR_PAGE (0xa43)
+#define PHY_RTL8211_PHYSR_ADDR (0x1a)
+#define PHY_RTL8211_PHYSR_SPEED_Pos (4)
+#define PHY_RTL8211_PHYSR_SPEED_Msk (3 << PHY_RTL8211_PHYSR_SPEED_Pos)
+#define PHY_RTL8211_PHYSR_DUPLEX_Msk (0x0008)
+#define PHY_RTL8211_LCR_PAGE (0xd04)
+#define PHY_RTL8211_LCR_ADDR (0x10)
+
+void eth_phy_generic_init(uint32_t phy_addr) {
+ // Reset the PHY.
+ eth_phy_write(phy_addr, PHY_BCR, PHY_BCR_SOFT_RESET);
+ mp_hal_delay_ms(50);
+}
+
int16_t eth_phy_lan87xx_get_link_status(uint32_t phy_addr) {
// Get the link mode & speed
- int16_t scsr = eth_phy_read(phy_addr, PHY_SCSR_LAN87XX);
- return (scsr >> PHY_SCSR_LAN87XX_SPEED_Pos) & PHY_SCSR_LAN87XX_SPEED_Msk;
+ uint16_t scsr = eth_phy_read(phy_addr, PHY_SCSR_LAN87XX);
+ int16_t status = 0;
+ if (scsr & PHY_SCSR_LAN87XX_10M_Msk) {
+ status |= PHY_SPEED_10HALF;
+ }
+ if (scsr & PHY_SCSR_LAN87XX_100M_Msk) {
+ status |= PHY_SPEED_100HALF;
+ }
+ if (scsr & PHY_SCSR_LAN87XX_DUPLEX_Msk) {
+ status |= PHY_DUPLEX;
+ }
+ return status;
}
int16_t eth_phy_dp838xx_get_link_status(uint32_t phy_addr) {
@@ -56,4 +83,37 @@ int16_t eth_phy_dp838xx_get_link_status(uint32_t phy_addr) {
return scsr;
}
+void eth_phy_rtl8211_init(uint32_t phy_addr) {
+ // Perform generic PHY initialization.
+ eth_phy_generic_init(phy_addr);
+
+ // Configure LED0 output to show 10/100/1000 link speed, and activity.
+ eth_phy_write(phy_addr, PHY_RTL8211_PAGSR_ADDR, PHY_RTL8211_LCR_PAGE);
+ eth_phy_write(phy_addr, PHY_RTL8211_LCR_ADDR, 0x001b);
+ eth_phy_write(phy_addr, PHY_RTL8211_PAGSR_ADDR, PHY_RTL8211_DEFAULT_PAGE);
+}
+
+int16_t eth_phy_rtl8211_get_link_status(uint32_t phy_addr) {
+ // Get the link mode & speed
+ eth_phy_write(phy_addr, PHY_RTL8211_PAGSR_ADDR, PHY_RTL8211_PHYSR_PAGE);
+ int16_t physr = eth_phy_read(phy_addr, PHY_RTL8211_PHYSR_ADDR);
+ eth_phy_write(phy_addr, PHY_RTL8211_PAGSR_ADDR, PHY_RTL8211_DEFAULT_PAGE);
+ int16_t status = 0;
+ switch ((physr & PHY_RTL8211_PHYSR_SPEED_Msk) >> PHY_RTL8211_PHYSR_SPEED_Pos) {
+ case 0:
+ status |= PHY_SPEED_10HALF;
+ break;
+ case 1:
+ status |= PHY_SPEED_100HALF;
+ break;
+ case 2:
+ status |= PHY_SPEED_1000HALF;
+ break;
+ }
+ if (physr & PHY_RTL8211_PHYSR_DUPLEX_Msk) {
+ status |= PHY_DUPLEX;
+ }
+ return status;
+}
+
#endif