//! SMSC LAN8742A Ethernet PHY use super::{StationManagement, PHY}; #[allow(dead_code)] mod phy_consts { pub const PHY_REG_BCR: u8 = 0x00; pub const PHY_REG_BSR: u8 = 0x01; pub const PHY_REG_ID1: u8 = 0x02; pub const PHY_REG_ID2: u8 = 0x03; pub const PHY_REG_ANTX: u8 = 0x04; pub const PHY_REG_ANRX: u8 = 0x05; 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 pub const PHY_REG_WUCSR: u16 = 0x8010; pub const PHY_REG_BCR_COLTEST: u16 = 1 << 7; pub const PHY_REG_BCR_FD: u16 = 1 << 8; pub const PHY_REG_BCR_ANRST: u16 = 1 << 9; pub const PHY_REG_BCR_ISOLATE: u16 = 1 << 10; pub const PHY_REG_BCR_POWERDN: u16 = 1 << 11; pub const PHY_REG_BCR_AN: u16 = 1 << 12; pub const PHY_REG_BCR_100M: u16 = 1 << 13; pub const PHY_REG_BCR_LOOPBACK: u16 = 1 << 14; pub const PHY_REG_BCR_RESET: u16 = 1 << 15; pub const PHY_REG_BSR_JABBER: u16 = 1 << 1; 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; unsafe impl PHY for LAN8742A { /// Reset PHY and wait for it to come out of reset. fn phy_reset(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 {} } /// PHY initialisation. fn phy_init(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, ); } fn poll_link(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 { return false; } // No link if link is down 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 { // Writes a value to an extended PHY register in MMD address space fn smi_write_ext(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); } }