00 Ethernet PHY nedir — MAC/PHY/MII
Ethernet iletişimi iki ayrı katmana bölünmüştür: MAC (Media Access Controller) ve PHY (Physical Layer). Bu iki katmanın aralarındaki standart arayüzleri anlamak, Linux ağ sürücüsü geliştirmenin temel taşıdır.
MAC ve PHY ayrımı
MAC katmanı Ethernet çerçevelerini (frame) oluşturur, CRC hesaplar ve zamanlama yönetimini yapar. PHY katmanı ise bu dijital sinyali fiziksel ortama (bakır, fiber) uygun analog sinyale dönüştürür. SoC'lerde MAC genellikle entegre gelir; PHY ise ayrı bir yonga olarak devreye bağlanır.
Uygulama Katmanı
│
TCP/UDP
│
IP
│
Linux net stack (sk_buff)
│
MAC sürücüsü (GMAC, stmmac…)
│ ← MII/RMII/RGMII/SGMII arayüzü
PHY yonga (DP83867, KSZ9031…)
│
Fiziksel ortam (RJ45, SFP…)
MII aile arayüzleri
| Arayüz | Hız | Pin sayısı | Saat | Tipik kullanım |
|---|---|---|---|---|
| MII | 10/100 Mb/s | 18 | 25 MHz | Eski entegrasyonlar |
| RMII | 10/100 Mb/s | 9 | 50 MHz (tek saat) | Düşük pin sayısı gereken SoC |
| GMII | 10/100/1000 Mb/s | 24 | 125 MHz | Gigabit, nadiren kullanılır |
| RGMII | 10/100/1000 Mb/s | 12 | 125 MHz, DDR | Gigabit embedded, en yaygın |
| SGMII | 1 Gb/s (seri) | 4 (diff) | SerDes | SFP, FPGA, yüksek yoğunluk |
| USXGMII | 1/2.5/5/10 Gb/s | 4 (diff) | SerDes | Multi-Gig SFP+ |
RGMII zamanlama — RX/TX gecikme
RGMII'de veri 125 MHz saat sinyalinin yükselen ve düşen kenarlarında gönderilir (DDR). MAC veya PHY tarafında 2 ns'lik gecikme (delay) uygulanması gerekir; bu gecikme cihaz ağacında ya da PHY registerlarında ayarlanır.
Bu bölümde
- MAC dijital çerçeveleri oluşturur; PHY analog iletimi sağlar
- RGMII en yaygın Gigabit arayüzüdür: 12 pin, 125 MHz DDR saat
- SGMII diferansiyel seri hat — SFP modülleri ve FPGA arayüzleri için tercih edilir
- RGMII gecikmesi doğru ayarlanmazsa link kurulmaz veya hata paketleri oluşur
01 MDIO bus — clause 22 ve 45
MDIO (Management Data Input/Output), MAC'in PHY register'larını okumasını ve yazmasını sağlayan 2 telli yönetim veri yoludur. Linux'ta mdiobus alt sistemi bu yolu soyutlar.
MDIO sinyalleri
MDIO yalnızca iki sinyal kullanır: MDC (saat, MAC tarafından üretilir, maksimum 2.5 MHz) ve MDIO (çift yönlü veri). Tek bir MDC/MDIO çiftine 32 farklı PHY adresi (0–31) bağlanabilir.
Clause 22 — standart PHY register erişimi
IEEE 802.3 Clause 22, 5 bitlik PHY adresi (PRTAD) ve 5 bitlik register adresi (DEVAD) içerir; toplamda 32 register erişimi sağlar.
| Register | Adres | İşlev |
|---|---|---|
| BMCR | 0x00 | Temel Mod Kontrol — auto-neg, reset, hız |
| BMSR | 0x01 | Temel Mod Durum — link, auto-neg tamamlandı |
| PHYIDR1 | 0x02 | PHY ID üst 16 bit (OUI) |
| PHYIDR2 | 0x03 | PHY ID alt 16 bit (model, revizyon) |
| ANAR | 0x04 | Auto-neg Duyuru — desteklenen hızlar |
| ANLPAR | 0x05 | Link Partner Yeteneği |
| 1000BASET_CTRL | 0x09 | 1000BASE-T kontrol (Gigabit PHY) |
Clause 45 — genişletilmiş register uzayı
10GbE ve daha yüksek hızlar, 32 register ile yetinmez. Clause 45 bu sorunu 5 bitlik MMD (MDIO Manageable Device) ve 16 bitlik register adresiyle çözer; 65536 register/MMD erişimi sağlar.
Linux'ta mdiobus_register
/* MAC sürücüsünde MDIO bus oluşturma */
static int my_mac_mdio_probe(struct platform_device *pdev)
{
struct mii_bus *bus;
int ret;
bus = devm_mdiobus_alloc(&pdev->dev);
if (!bus)
return -ENOMEM;
bus->name = "my-mdio-bus";
bus->read = my_mdio_read; /* Clause 22 okuma */
bus->write = my_mdio_write; /* Clause 22 yazma */
bus->read_c45 = my_mdio_read_c45; /* Clause 45 — isteğe bağlı */
bus->write_c45 = my_mdio_write_c45;
bus->parent = &pdev->dev;
snprintf(bus->id, MII_BUS_ID_SIZE, "%s", pdev->name);
ret = of_mdiobus_register(bus, pdev->dev.of_node);
if (ret) {
dev_err(&pdev->dev, "MDIO bus kaydı başarısız: %d\n", ret);
return ret;
}
return 0;
}
/* Clause 22 okuma örneği */
static int my_mdio_read(struct mii_bus *bus, int phy_addr, int reg)
{
struct my_priv *priv = bus->priv;
u32 cmd, val;
int timeout = 1000;
cmd = MDIO_RD | ((phy_addr & 0x1f) << 21) | ((reg & 0x1f) << 16);
writel(cmd, priv->base + MDIO_CMD);
while (timeout-- && (readl(priv->base + MDIO_STATUS) & MDIO_BUSY))
udelay(1);
if (timeout < 0)
return -ETIMEDOUT;
val = readl(priv->base + MDIO_DATA);
return val & 0xffff;
}
mdio_read / mdio_write yardımcı fonksiyonları
/* Kullanıcı alanından da mdio_read/write çağrılabilir */
/* Kernel içinde direkt: */
int val = mdiobus_read(bus, phy_addr, MII_BMSR);
mdiobus_write(bus, phy_addr, MII_ADVERTISE, ADVERTISE_ALL | ADVERTISE_PAUSE_CAP);
/* Clause 45: */
int val = mdiobus_c45_read(bus, phy_addr, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
mdiobus_c45_write(bus, phy_addr, MDIO_MMD_PMAPMD, MDIO_CTRL1, MDIO_CTRL1_RESET);
Bu bölümde
- MDIO: MDC (saat) + MDIO (veri), 32 PHY adresi, 2.5 MHz maks.
- Clause 22: 32 register; Clause 45: 65536 register/MMD — 10G+ için zorunlu
of_mdiobus_register()cihaz ağacından PHY adreslerini otomatik tarar
02 phylib — phy_device ve bağlantı yönetimi
phylib, Linux'ta Ethernet PHY sürücülerinin standart çerçevesidir. Her fiziksel PHY için bir phy_device nesnesi oluşturur ve durum makinesini yönetir.
phy_device yaşam döngüsü
mdiobus_scan()
│
├─ phy_device_create() ← PHY ID okunur, phy_device ayrılır
│
phy_connect() ← MAC sürücüsü PHY'ye bağlanır
│
phy_start() ← durum makinesi başlar
│
┌─ PHY_DOWN → PHY_NOLINK → PHY_RUNNING
│ link değişiminde adjust_link() çağrılır
│
phy_stop() ← durum makinesi durdurulur
│
phy_disconnect() ← bağlantı kopar
phy_connect ve adjust_link
/* MAC sürücüsünde PHY bağlantısı */
static void my_adjust_link(struct net_device *ndev)
{
struct my_priv *priv = netdev_priv(ndev);
struct phy_device *phydev = ndev->phydev;
bool changed = false;
if (priv->speed != phydev->speed) {
priv->speed = phydev->speed;
changed = true;
}
if (priv->duplex != phydev->duplex) {
priv->duplex = phydev->duplex;
changed = true;
}
if (changed || priv->link != phydev->link) {
priv->link = phydev->link;
if (phydev->link)
my_mac_set_speed(priv, phydev->speed, phydev->duplex);
else
my_mac_link_down(priv);
phy_print_status(phydev);
}
}
static int my_open(struct net_device *ndev)
{
struct my_priv *priv = netdev_priv(ndev);
struct phy_device *phydev;
phydev = of_phy_connect(ndev,
priv->phy_node,
my_adjust_link,
0,
PHY_INTERFACE_MODE_RGMII_ID);
if (IS_ERR(phydev))
return PTR_ERR(phydev);
phy_start(phydev);
return 0;
}
static int my_stop(struct net_device *ndev)
{
phy_stop(ndev->phydev);
phy_disconnect(ndev->phydev);
return 0;
}
PHY durum makinesi
genphy_* yardımcı fonksiyonları
Özel bir PHY sürücüsü yazılmadığında Linux, BMSR/BMCR register'larını standart okuma kabiliyetine sahip genphy sürücüsünü kullanır. Özel sürücüler bu fonksiyonları çağırabilir:
genphy_config_init(phydev); /* Özellik maskesi — 1G/100M/10M */
genphy_config_aneg(phydev); /* Auto-negotiation başlat */
genphy_update_link(phydev); /* BMSR okunur, link durumu güncellenir */
genphy_read_status(phydev); /* Hız, duplex, link durumu toplu güncelle */
genphy_restart_aneg(phydev); /* Auto-neg yeniden başlat (BMCR ANRESTART) */
genphy_suspend(phydev); /* PHY'yi güç tasarruf moduna al */
genphy_resume(phydev); /* PHY'yi uyandır */
Bu bölümde
phy_connect()→phy_start()→ link değişimindeadjust_link()- phylib durum makinesi polling veya interrupt ile çalışabilir
genphy_*fonksiyonları standart Clause 22 işlemlerini kapsüller
03 phylink — modern MAC-PHY adaptör katmanı
phylink, 2016'dan itibaren eklenen yeni bir API'dir; MAC ve PHY'yi daha sıkı entegre eder, SFP modüllerini ve birden fazla link modu olasılığını zarif şekilde yönetir.
phylib ile phylink karşılaştırması
| Özellik | phylib (eski) | phylink (yeni) |
|---|---|---|
| SFP desteği | Yok | Yerleşik sfp-bus entegrasyonu |
| MAC konfigürasyonu | adjust_link() callback | mac_config() + mac_link_up() |
| Birden fazla arayüz modu | Sınırlı | Evet, runtime değişim |
| Fixed-link | Sınırlı | Doğrudan desteklenir |
| PAUSE çerçevesi yönetimi | Manuel | Otomatik |
| InBand signalling | Yok | 1000BASE-X, SGMII desteği |
phylink_ops — MAC tarafı callback'ler
static void my_mac_validate(struct phylink_config *config,
unsigned long *supported,
struct phylink_link_state *state)
{
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
/* MAC'in desteklediği modları belirt */
phylink_set(mask, Autoneg);
phylink_set(mask, Pause);
phylink_set(mask, Asym_Pause);
phylink_set_port_modes(mask);
phylink_set(mask, 1000baseT_Full);
phylink_set(mask, 100baseT_Full);
phylink_set(mask, 10baseT_Half);
phylink_set(mask, 10baseT_Full);
if (state->interface == PHY_INTERFACE_MODE_RGMII ||
state->interface == PHY_INTERFACE_MODE_RGMII_ID) {
phylink_set(mask, 1000baseT_Full);
}
linkmode_and(supported, supported, mask);
linkmode_and(state->advertising, state->advertising, mask);
}
static void my_mac_config(struct phylink_config *config, unsigned int mode,
const struct phylink_link_state *state)
{
struct my_priv *priv = container_of(config, struct my_priv, phylink_config);
/* Hız/duplex değiştiğinde MAC register'larını güncelle */
my_mac_update_registers(priv, state->speed, state->duplex, state->pause);
}
static void my_mac_link_down(struct phylink_config *config, unsigned int mode,
phy_interface_t interface)
{
struct my_priv *priv = container_of(config, struct my_priv, phylink_config);
my_mac_disable_tx_rx(priv);
}
static void my_mac_link_up(struct phylink_config *config,
struct phy_device *phy,
unsigned int mode, phy_interface_t interface,
int speed, int duplex,
bool tx_pause, bool rx_pause)
{
struct my_priv *priv = container_of(config, struct my_priv, phylink_config);
my_mac_set_speed_duplex(priv, speed, duplex);
my_mac_set_pause(priv, tx_pause, rx_pause);
my_mac_enable_tx_rx(priv);
}
static const struct phylink_mac_ops my_phylink_ops = {
.validate = my_mac_validate,
.mac_config = my_mac_config,
.mac_link_down = my_mac_link_down,
.mac_link_up = my_mac_link_up,
};
phylink oluşturma ve başlatma
static int my_probe(struct platform_device *pdev)
{
struct my_priv *priv = /* ... */;
struct phylink *pl;
priv->phylink_config.dev = &ndev->dev;
priv->phylink_config.type = PHYLINK_NETDEV;
pl = phylink_create(&priv->phylink_config,
of_fwnode_handle(pdev->dev.of_node),
priv->phy_mode,
&my_phylink_ops);
if (IS_ERR(pl))
return PTR_ERR(pl);
priv->phylink = pl;
return 0;
}
/* ndo_open içinde */
phylink_start(priv->phylink);
/* ndo_stop içinde */
phylink_stop(priv->phylink);
phylink_disconnect_phy(priv->phylink);
Bu bölümde
- phylink; SFP, fixed-link ve normal PHY'yi tek API ile yönetir
- MAC tarafı:
validate,mac_config,mac_link_down,mac_link_up - Yeni sürücüler phylib yerine phylink kullanmalıdır
04 PHY sürücüsü yazmak
Standart genphy sürücüsü çoğu PHY için yeterlidir. Ancak özel register'lar, vendor-specific özellikler veya enerji tasarrufu modu gerektiren durumlarda özel bir PHY sürücüsü yazılır.
phy_driver yapısı
/* drivers/net/phy/myvendor.c */
#include <linux/phy.h>
#include <linux/module.h>
/* Vendor PHY ID — PHYIDR1:PHYIDR2 register'larından alınır */
#define MYPHY_ID 0x0283BC30
#define MYPHY_ID_MASK 0xFFFFFFF0
/* Vendor özel register'lar */
#define MYPHY_EXT_CTRL 0x17
#define MYPHY_EXT_CTRL_CLKOUT BIT(0)
#define MYPHY_LED_CTRL 0x18
#define MYPHY_LED_LINK_ACT (0x6 << 4)
static int myphy_config_init(struct phy_device *phydev)
{
int val, ret;
/* Standart başlatma */
ret = genphy_config_init(phydev);
if (ret < 0)
return ret;
/* Enerji tasarruf modunu etkinleştir */
val = phy_read(phydev, MYPHY_EXT_CTRL);
if (val < 0)
return val;
val |= MYPHY_EXT_CTRL_CLKOUT;
ret = phy_write(phydev, MYPHY_EXT_CTRL, val);
if (ret)
return ret;
/* LED modunu ayarla: Link/Activity */
ret = phy_write(phydev, MYPHY_LED_CTRL, MYPHY_LED_LINK_ACT);
return ret;
}
static int myphy_read_status(struct phy_device *phydev)
{
int ret;
/* Standart okuma + vendor-specific durum
* Burada EEE (Energy Efficient Ethernet) kontrolü de yapılabilir */
ret = genphy_read_status(phydev);
if (ret)
return ret;
/* Vendor özel kablo tanısı — isteğe bağlı */
phydev->mdix = ETH_TP_MDI_AUTO;
return 0;
}
static int myphy_config_aneg(struct phy_device *phydev)
{
/* Vendor özel ayarlar yapıldıktan sonra standart auto-neg */
return genphy_config_aneg(phydev);
}
static struct phy_driver myphy_drivers[] = {
{
PHY_ID_MATCH_MODEL(MYPHY_ID),
.name = "MyVendor PHY",
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_init = myphy_config_init,
.config_aneg = myphy_config_aneg,
.read_status = myphy_read_status,
.ack_interrupt = myphy_ack_interrupt,
.config_intr = myphy_config_intr,
.suspend = genphy_suspend,
.resume = genphy_resume,
},
};
module_phy_driver(myphy_drivers);
static const struct mdio_device_id __maybe_unused myphy_tbl[] = {
{ MYPHY_ID, MYPHY_ID_MASK },
{ }
};
MODULE_DEVICE_TABLE(mdio, myphy_tbl);
MODULE_AUTHOR("Emirhan Pehlevan");
MODULE_DESCRIPTION("MyVendor PHY sürücüsü");
MODULE_LICENSE("GPL");
PHY ID nasıl bulunur
PHYIDR1 (register 0x02) üst 16 bit OUI içerir; PHYIDR2 (0x03) model ve revizyon bilgisi taşır. ethtool -i ethX komutu veya cat /sys/bus/mdio_bus/devices/*/phy_id bu değeri verir. Veri sayfasında "PHY Identifier Register" başlığı altında kontrol edilmelidir.
Bu bölümde
- PHY ID: PHYIDR1 + PHYIDR2 registerlarından oluşur, mask ile eşleştirilir
phy_driverstruct:config_init,read_status,config_anegminimum alanları- Çoğu durumda
genphy_*çağırıp vendor özelliklerini eklemek yeterlidir
05 PHY interrupt ve link değişimi
PHY link değişimini algılamanın iki yolu vardır: periyodik polling (basit ama CPU'yu meşgul eder) ve interrupt tabanlı yaklaşım (verimli, donanım desteği gerekir).
Polling vs interrupt
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| Polling (PHY_POLL) | Tüm PHY'lerde çalışır, basit | Her 1s'de schedule_delayed_work, CPU kullanımı |
| Interrupt | Anlık tepki, CPU tasarrufu | PHY'nin interrupt çıkışı olmalı, GPIO bağlantısı gerekir |
Interrupt callback'leri
/* PHY interrupt kaynağını temizle (ack) */
static int myphy_ack_interrupt(struct phy_device *phydev)
{
int val;
/* Interrupt Status Register okunarak bit'ler temizlenir */
val = phy_read(phydev, MYPHY_ISR);
return (val < 0) ? val : 0;
}
/* Interrupt'ı etkinleştir/devre dışı bırak */
static int myphy_config_intr(struct phy_device *phydev)
{
int val, ret;
if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
ret = myphy_ack_interrupt(phydev);
if (ret)
return ret;
/* IMR register'ına link up/down mask'ı yaz */
val = MYPHY_IMR_LINK_UP | MYPHY_IMR_LINK_DOWN;
ret = phy_write(phydev, MYPHY_IMR, val);
} else {
ret = phy_write(phydev, MYPHY_IMR, 0);
if (ret)
return ret;
ret = myphy_ack_interrupt(phydev);
}
return ret;
}
/* Yeni API: handle_interrupt (Linux 5.12+) */
static irqreturn_t myphy_handle_interrupt(struct phy_device *phydev)
{
int irq_status;
irq_status = phy_read(phydev, MYPHY_ISR);
if (irq_status < 0) {
phy_error(phydev);
return IRQ_NONE;
}
if (!(irq_status & (MYPHY_ISR_LINK_UP | MYPHY_ISR_LINK_DOWN)))
return IRQ_NONE;
phy_trigger_machine(phydev);
return IRQ_HANDLED;
}
genphy_update_link detayı
genphy_update_link() BMSR register'ını iki kez okur (latch-low bit için). İkinci okuma gerçek değeri yansıtır. Link takibinde bu davranış kritiktir; tek okuma yanlış link down bildirebilir.
/* Kernel kaynak: drivers/net/phy/phy_device.c */
int genphy_update_link(struct phy_device *phydev)
{
int status, bmcr;
bmcr = phy_read(phydev, MII_BMCR);
if (bmcr < 0)
return bmcr;
/* Loopback modda link her zaman var */
if (bmcr & BMCR_LOOPBACK) {
phydev->link = 1;
return 0;
}
/* Birinci okuma latch-low bit'i temizler */
status = phy_read(phydev, MII_BMSR);
if (status < 0)
return status;
/* İkinci okuma gerçek anlık değeri döndürür */
status = phy_read(phydev, MII_BMSR);
if (status < 0)
return status;
if (status & BMSR_LSTATUS)
phydev->link = 1;
else
phydev->link = 0;
return 0;
}
Bu bölümde
- PHY_HAS_INTERRUPT bayrak — interrupt etkin; yoksa PHY_POLL modu (1 sn polling)
- Linux 5.12+:
handle_interruptcallback; eski API:ack_interrupt+config_intr - BMSR iki kez okunmalı: birinci okuma "latch-low" bit'i temizler
06 SFP modül desteği
SFP (Small Form-factor Pluggable) modüller, fiber ve bakır arayüzler arasında hot-plug geçiş imkânı sunar. Linux phylink ile sfp-bus alt sistemi bu modülleri otomatik yönetir.
SFP-bus mimarisi
SFP konnektör (I2C + MDIO + GPIO)
│
sfp_bus (drivers/net/sfp-bus.c)
│
┌────┴────────────┐
│ │
SFP sürücüsü phylink upstream
(sfp.c) (MAC sürücüsü)
│ │
EEPROM mac_config()
SFP+1000BASE-SX mac_link_up()
sfp_register_upstream
/* phylink oluşturduktan sonra SFP upstream kaydı */
static int my_probe(struct platform_device *pdev)
{
struct my_priv *priv;
struct sfp_bus *sfp_bus;
int ret;
/* ... phylink oluştur ... */
/* Cihaz ağacında sfp = <&sfp_node> varsa otomatik bağlanır */
ret = phylink_of_phy_connect(priv->phylink,
pdev->dev.of_node, 0);
if (ret)
return ret;
return 0;
}
/* Düşük seviyeli sfp_bus doğrudan kullanım (nadiren gerekir): */
sfp_bus = sfp_register_upstream(fwnode, &priv->phylink_config, upstream_ops);
if (IS_ERR(sfp_bus))
return PTR_ERR(sfp_bus);
priv->sfp_bus = sfp_bus;
SFP EEPROM ve modül türleri
Device Tree SFP tanımı
sfp0: sfp-connector {
compatible = "sff,sfp";
i2c-bus = <&i2c1>;
los-gpios = <&gpio 14 GPIO_ACTIVE_HIGH>;
mod-def0-gpios = <&gpio 15 GPIO_ACTIVE_LOW>;
tx-fault-gpios = <&gpio 16 GPIO_ACTIVE_HIGH>;
tx-disable-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
maximum-power-milliwatt = <1000>;
};
&gmac0 {
phy-mode = "sgmii";
sfp = <&sfp0>;
managed = "in-band-status";
};
Bu bölümde
- sfp-bus, modül takma/çıkarma olaylarını yakalar ve phylink'e bildirir
- SFP EEPROM (I2C adres 0x50) modül türü, güç, alıcı özelliklerini içerir
- LOS, MOD-DEF0, TX-FAULT GPIO'ları cihaz ağacında tanımlanmalıdır
07 Device Tree binding
Ethernet PHY'lerin donanım açıklaması, cihaz ağacında (Device Tree) standartlaşmış bir bağlama (binding) ile yapılır. Bu bölümde yaygın senaryolar ve dikkat edilmesi gereken noktalar açıklanır.
Temel MDIO + PHY binding
/* MAC düğümü */
&gmac {
status = "okay";
phy-mode = "rgmii-id"; /* RGMII, MAC her iki gecikmeyi uygular */
phy-handle = <&phy0>; /* Hangi PHY'ye bağlı */
pinctrl-names = "default";
pinctrl-0 = <&gmac_pins>;
};
/* MDIO bus */
&mdio {
status = "okay";
/* PHY reset GPIO — zorunlu değil ama önerilir */
reset-gpios = <&gpio 10 GPIO_ACTIVE_LOW>;
reset-deassert-us = <10000>;
reset-post-delay-us = <100000>;
phy0: ethernet-phy@0 { /* @N = MDIO adresi */
reg = <0>; /* MDIO adres 0 */
compatible = "ethernet-phy-id0283.bc30", /* PHYID ile eşleşme */
"ethernet-phy-ieee802.3-c22"; /* Clause 22 fallback */
interrupt-parent = <&gpio>;
interrupts = <18 IRQ_TYPE_EDGE_FALLING>;
/* RGMII gecikme ayarları (DP83867 özel özelliği) */
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
};
};
fixed-link — PHY olmayan bağlantılar
Switch chip'e sabit bağlı bir MAC gibi MDIO erişimi olmayan durumlar için fixed-link kullanılır:
&gmac1 {
status = "okay";
phy-mode = "rgmii";
fixed-link {
speed = <1000>;
full-duplex;
pause;
asym-pause;
};
};
Önemli DT özellik tablosu
| Özellik | Değer örneği | Açıklama |
|---|---|---|
| phy-mode | "rgmii-id" | MAC-PHY arayüz modu |
| phy-handle | <&phy0> | MDIO bus'taki PHY phandle referansı |
| managed | "in-band-status" | SGMII/1000BASE-X in-band link bilgisi |
| reset-gpios | <&gpio 10 ACTIVE_LOW> | PHY hardware reset pini |
| reset-deassert-us | <10000> | Reset deassert bekleme süresi (µs) |
| max-speed | <100> | Hız kısıtı — 100 Mb/s ile sınırla |
| ethernet-phy-id | 0x0283bc30 | Vendor-specific uyumluluk dizgisi |
Bu bölümde
ethernet-phy@NdüğümünderegMDIO adresini verirreset-gpios+ zamanlamalar — kararlı başlatma için mutlaka ekleyinfixed-linkswitch-entegre bağlantılarda MDIO gerektirmez
08 Hata ayıklama
PHY ve phylink sorunlarını izlemek için çekirdek içi araçlardan kullanıcı alanı yardımcı programlarına kadar kapsamlı bir araç seti mevcuttur.
ethtool ile temel tanılama
# Bağlantı hızı, duplex, auto-neg durumu
ethtool eth0
# Sürücü bilgisi ve bus-info
ethtool -i eth0
# PHY register'larını oku (clause 22)
ethtool -d eth0
# Belirli MII register oku (BMSR = reg 1)
ethtool --dump-module eth0
# Hız ve duplex zorla (auto-neg bypass)
ethtool -s eth0 speed 100 duplex full autoneg off
# PHY istatistikleri
ethtool --phy-statistics eth0
# EEE (Energy Efficient Ethernet) durumu
ethtool --show-eee eth0
mii-tool ile düşük seviye okuma
# Bağlantı durumu
mii-tool eth0
# Ayrıntılı çıktı
mii-tool -v eth0
# Auto-neg yeniden başlat
mii-tool -r eth0
/sys/bus/mdio_bus ile register keşfi
# Sistemdeki MDIO bus'ları listele
ls /sys/bus/mdio_bus/devices/
# PHY ID (PHYIDR1:PHYIDR2)
cat /sys/bus/mdio_bus/devices/0000:00/phy_id
# PHY sürücüsü
cat /sys/bus/mdio_bus/devices/0000:00/modalias
# Bağlantı parametreleri
cat /sys/bus/mdio_bus/devices/0000:00/link
# phylink durum makinesi (debugfs)
cat /sys/kernel/debug/phylink/eth0
phylink durum makinesi izleme
# Kernel log — phylink durum geçişleri
dmesg | grep -E "phylink|PHY|eth0"
# Dinamik debug etkinleştir
echo "module phylink +p" > /sys/kernel/debug/dynamic_debug/control
echo "module phy_device +p" > /sys/kernel/debug/dynamic_debug/control
# MDIO register dump (mdio-tools paketi)
mdio-tool read 0 BMSR
mdio-tool read 0 PHYIDR1
mdio-tool read 0 PHYIDR2
Yaygın sorunlar ve çözümleri
| Belirti | Olası Neden | Çözüm |
|---|---|---|
| Link yok, PHY bulunamıyor | Reset GPIO eksik veya hatalı | DT'de reset-gpios ve zamanlamaları kontrol et |
| Link var, paket kaybı/hata | RGMII gecikme yanlış | phy-mode ve vendor delay register'larını kontrol et |
| Hız 10M'a düşüyor | Kablo hasarı veya auto-neg uyumsuzluğu | ethtool -s speed 100 duplex full autoneg off ile test et |
| PHY ID 0xFFFF | MDIO bağlantı sorunu veya yanlış adres | MDC/MDIO pinlerini ve DT reg değerini doğrula |
| SFP modül algılanmıyor | MOD-DEF0 GPIO polaritesi yanlış | DT'de ACTIVE_HIGH/LOW flag'ini kontrol et |
Bu bölümde
ethtool -d eth0ham MII register dump'ı döküm alır/sys/bus/mdio_bus/devices/tüm MDIO cihazlarını sysfs'ten gösterir- dynamic_debug ile phylink ve phy_device modüllerinde verbose log etkinleştirilebilir
- PHY ID 0xFFFF → MDIO veri yolu bağlantı sorunu (MDC/MDIO pinleri veya güç)