mirror of
https://github.com/soypat/lneto.git
synced 2026-08-15 04:13:44 +00:00
begin adding phy package
This commit is contained in:
+14
@@ -0,0 +1,14 @@
|
||||
package phy
|
||||
|
||||
// MDIOBus is a HAL for MDIO bus access supporting both Clause 22 and Clause 45 devices.
|
||||
// Implementations should use devaddr to select the framing:
|
||||
// - devaddr=0: Clause 22 framing (devaddr ignored in transaction)
|
||||
// - devaddr>=1: Clause 45 framing (PMA/PMD=1, WIS=2, PCS=3, PHY XS=4, DTE XS=5, AN=7)
|
||||
//
|
||||
// Register address range: Clause 22 uses 0-31, Clause 45 uses 0-65535.
|
||||
type MDIOBus interface {
|
||||
// Read reads a 16-bit register from the PHY.
|
||||
Read(phyAddr, devaddr uint8, regAddr uint16) (value uint16, err error)
|
||||
// Write writes a 16-bit value to a PHY register.
|
||||
Write(phyAddr, devaddr uint8, regAddr, value uint16) error
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
// Package phy provides Ethernet PHY management via MDIO.
|
||||
// It supports IEEE 802.3 Clause 22 and Clause 45 register access
|
||||
// for configuring and monitoring physical layer transceivers.
|
||||
package phy
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
// FindPHYs finds all regular non-clause45 PHYs on the MDIO bus and writes them to dst.
|
||||
func FindPHYs(mdio MDIOBus, dst []uint8) (n int, err error) {
|
||||
const maxAddr = 31
|
||||
const regBasicStatus = 0x01
|
||||
if len(dst) < 32 {
|
||||
return -1, errors.New("require buffer length 32 for FindPHYs")
|
||||
}
|
||||
n = 0
|
||||
for addr := uint8(0); addr <= maxAddr; addr++ {
|
||||
// Future proofing for supported clause 45.
|
||||
// Check PMA/PMD device (DEVAD 1), register 0 (control)
|
||||
const devAddr = 1
|
||||
var val uint16
|
||||
val, err = mdio.Read(addr, devAddr, BMCRAddr)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
// Basic status has some bits that must be zero and one, so if this check fails then we know its a bad address.
|
||||
if val != 0xffff && val != 0x0000 {
|
||||
dst[n] = addr
|
||||
n++
|
||||
}
|
||||
time.Sleep(150 * time.Microsecond)
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
type Device struct {
|
||||
mdio MDIOBus
|
||||
phyaddr uint8
|
||||
// Is 1 for Clause 45 devices and 0 for clause 22 devices.
|
||||
clause45 uint8
|
||||
}
|
||||
|
||||
func (d *Device) BasicControl() (BMCR, error) {
|
||||
ctl, err := d.rread(BMCRAddr)
|
||||
return BMCR(ctl), err
|
||||
}
|
||||
|
||||
func (d *Device) BasicStatus(phyaddr uint8) (BMSR, error) {
|
||||
stat, err := d.rread(BMSRAddr)
|
||||
return BMSR(stat), err
|
||||
}
|
||||
|
||||
func (d *Device) ID1() (uint16, error) {
|
||||
return d.rread(regPhyId1)
|
||||
}
|
||||
|
||||
func (d *Device) ID2() (uint16, error) {
|
||||
return d.rread(regPhyId2)
|
||||
}
|
||||
|
||||
func (d *Device) Reset(phyaddr uint8) error {
|
||||
err := d.rwrite(BMCRAddr, uint16(BMCRReset))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Wait for reset to complete (bit self-clears).
|
||||
// IEEE 802.3 allows up to 500ms.
|
||||
const maxPolls = 50
|
||||
const resetTimeout = 500 * time.Millisecond // As per standard.
|
||||
for i := 0; i < maxPolls; i++ {
|
||||
time.Sleep(resetTimeout / maxPolls)
|
||||
ctl, err := d.BasicControl()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if ctl&BMCRReset == 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errors.New("PHY reset timeout")
|
||||
}
|
||||
|
||||
// rwrite mdio register write.
|
||||
func (d *Device) rwrite(addr uint16, value uint16) error {
|
||||
return d.mdio.Write(d.phyaddr, d.clause45, addr, value)
|
||||
}
|
||||
|
||||
// rread mdio register read.
|
||||
func (d *Device) rread(addr uint16) (value uint16, _ error) {
|
||||
return d.mdio.Read(d.phyaddr, d.clause45, addr)
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
package phy
|
||||
|
||||
// Registers 0..15 as defined by 802.3.
|
||||
const (
|
||||
// First two registers are BMCR and BMSR. See below.
|
||||
|
||||
regPhyId1 = 0x02
|
||||
regPhyId2 = 0x03
|
||||
|
||||
regAutoNegotiationAdvertisement = 0x04
|
||||
regAutoNegotiationLinkPartnerAbility = 0x05
|
||||
regAutoNegotiationExpansion = 0x05
|
||||
regModeControlStatus = 0x11
|
||||
regSpecialModes = 0x12
|
||||
regSymbolErorCounter = 0x1a
|
||||
regSpecialControlStatusIndications = 0x1b
|
||||
regIRQSourceFlag = 0x1d
|
||||
regIRQMask = 0x1e
|
||||
regPhySpecialScontrolStatus = 0x1f
|
||||
)
|
||||
|
||||
// BMCR represents the Basic Mode Control Register at address 0x00.
|
||||
// Reference: IEEE 802.3 Clause 22.2.4.1
|
||||
type BMCR uint16
|
||||
|
||||
const (
|
||||
BMCRAddr = 0x00
|
||||
|
||||
BMCRSpeed1000 BMCR = 0x0040 // MSB of Speed (1000Mbps)
|
||||
BMCRCollision BMCR = 0x0080 // Collision test
|
||||
BMCRFullDuplex BMCR = 0x0100 // Full duplex mode
|
||||
BMCRANRestart BMCR = 0x0200 // Restart auto-negotiation
|
||||
BMCRIsolate BMCR = 0x0400 // Isolate PHY from MII
|
||||
BMCRPowerDown BMCR = 0x0800 // Power down PHY
|
||||
BMCRANEnable BMCR = 0x1000 // Enable auto-negotiation
|
||||
BMCRSpeed100 BMCR = 0x2000 // Select 100Mbps
|
||||
BMCRLoopback BMCR = 0x4000 // Enable TXD loopback
|
||||
BMCRReset BMCR = 0x8000 // Software reset (self-clearing)
|
||||
)
|
||||
|
||||
// BMSR represents the Basic Mode Status Register at address 0x01.
|
||||
// Reference: IEEE 802.3 Clause 22.2.4.2
|
||||
type BMSR uint16
|
||||
|
||||
const (
|
||||
BMSRAddr = 0x01
|
||||
|
||||
BMSRExtCap BMSR = 0x0001 // Extended register capability
|
||||
BMSRJabber BMSR = 0x0002 // Jabber detected
|
||||
BMSRLinkStatus BMSR = 0x0004 // Link status (1=up)
|
||||
BMSRANCap BMSR = 0x0008 // Auto-negotiation capable
|
||||
BMSRRemoteFault BMSR = 0x0010 // Remote fault detected
|
||||
BMSRANComplete BMSR = 0x0020 // Auto-negotiation complete
|
||||
BMSRNoPreamble BMSR = 0x0040 // Preamble suppression capable
|
||||
BMSRExtStatus BMSR = 0x0100 // Extended status in register 15
|
||||
BMSR100Half2 BMSR = 0x0200 // 100BASE-T2 half-duplex capable
|
||||
BMSR100Full2 BMSR = 0x0400 // 100BASE-T2 full-duplex capable
|
||||
BMSR10Half BMSR = 0x0800 // 10Mbps half-duplex capable
|
||||
BMSR10Full BMSR = 0x1000 // 10Mbps full-duplex capable
|
||||
BMSR100Half BMSR = 0x2000 // 100Mbps half-duplex capable
|
||||
BMSR100Full BMSR = 0x4000 // 100Mbps full-duplex capable
|
||||
BMSR100Base4 BMSR = 0x8000 // 100BASE-T4 capable
|
||||
)
|
||||
Reference in New Issue
Block a user