Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update PHY code in _up #2474

Merged
merged 1 commit into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 27 additions & 18 deletions mongoose.c
Original file line number Diff line number Diff line change
Expand Up @@ -8710,6 +8710,12 @@ static void rt10xx_phy_write(uint8_t addr, uint8_t reg, uint16_t val) {
while ((ENET->EIR & MG_BIT(23)) == 0) (void) 0;
}

static uint32_t rt10xx_phy_id(uint8_t addr) {
uint16_t phy_id1 = rt10xx_phy_read(addr, PHY_ID1);
uint16_t phy_id2 = rt10xx_phy_read(addr, PHY_ID2);
return (uint32_t) phy_id1 << 16 | phy_id2;
}

// MDC clock is generated from IPS Bus clock (ipg_clk); as per 802.3,
// it must not exceed 2.5MHz
// The PHY receives the PLL6-generated 50MHz clock
Expand Down Expand Up @@ -8744,21 +8750,20 @@ static bool mg_tcpip_driver_rt1020_init(struct mg_tcpip_if *ifp) {
rt10xx_phy_write(d->phy_addr, PHY_BCR, MG_BIT(12)); // Set autonegotiation

// PHY: Enable 50 MHz external ref clock at XI (preserve defaults)
uint16_t phy_id1 = rt10xx_phy_read(d->phy_addr, PHY_ID1);
uint16_t phy_id2 = rt10xx_phy_read(d->phy_addr, PHY_ID2);
MG_INFO(("PHY ID: %#04x %#04x", phy_id1, phy_id2));
uint32_t id = rt10xx_phy_id(d->phy_addr);
MG_INFO(("PHY ID: %#04x %#04x", (uint16_t) (id >> 16), (uint16_t) id));
// 2000 a140 - TI DP83825I
// 0007 c0fx - LAN8720
// 0022 1561 - KSZ8081RNB

if (phy_id1 == 0x22) { // KSZ8081RNB, like EVK-RTxxxx boards
if ((id & 0xffff0000) == 0x220000) { // KSZ8081RNB, like EVK-RTxxxx boards
rt10xx_phy_write(d->phy_addr, 31,
MG_BIT(15) | MG_BIT(8) | MG_BIT(7)); // PC2R
} else if (phy_id1 == 0x2000) { // DP83825I, like Teensy4.1
rt10xx_phy_write(d->phy_addr, 23, 0x81); // 50Mhz clock input
rt10xx_phy_write(d->phy_addr, 24, 0x280); // LED status, active high
} else { // Default to LAN8720
MG_INFO(("Defauling to LAN8720 PHY..."));
} else if ((id & 0xffff0000) == 0x20000000) { // DP83825I, like Teensy4.1
rt10xx_phy_write(d->phy_addr, 23, 0x81); // 50MHz clock input
rt10xx_phy_write(d->phy_addr, 24, 0x280); // LED status, active high
} else { // Default to LAN8720
MG_INFO(("Defaulting to LAN8720 PHY...")); // TODO()
}

// Select RMII mode, 100M, keep CRC, set max rx length, disable loop
Expand Down Expand Up @@ -8793,18 +8798,13 @@ static size_t mg_tcpip_driver_rt1020_tx(const void *buf, size_t len,
MG_ERROR(("No descriptors available"));
len = 0; // retry later
} else {
//MG_DEBUG(("sending %4lu, d=%u, c=%#hx %#lx %#lx", len, s_txno,
// s_txdesc[s_txno].control, ENET->EIR, ENET->ATSTMP));
memcpy(s_txbuf[s_txno], buf, len); // Copy data
s_txdesc[s_txno].length = (uint16_t) len; // Set data len
// Table 37-34, R, L, TC (Ready, last, transmit CRC after frame
s_txdesc[s_txno].control |=
(uint16_t) (MG_BIT(15) | MG_BIT(11) | MG_BIT(10));
ENET->TDAR = MG_BIT(24); // Descriptor ring updated
if (++s_txno >= ETH_DESC_CNT) s_txno = 0;

// Artificial delay. TODO(cpq): find a proper way to transmit reliably
for (volatile int i = 0; i < 99999; i++) (void) 0;
}
(void) ifp;
return len;
Expand All @@ -8818,10 +8818,19 @@ static bool mg_tcpip_driver_rt1020_up(struct mg_tcpip_if *ifp) {
if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up
uint32_t tcr = ENET->TCR |= MG_BIT(2); // Full-duplex
uint32_t rcr = ENET->RCR &= ~MG_BIT(9); // 100M
if (rt10xx_phy_read(d->phy_addr, PHY_ID1)) { // KSZ8081RNB ?
uint32_t pc1r = rt10xx_phy_read(d->phy_addr, 30); // Read PC2R
if ((pc1r & 3) == 1) rcr |= MG_BIT(9); // 10M
if ((pc1r & MG_BIT(2)) == 0) tcr &= ~MG_BIT(2); // Half-duplex
uint32_t phy_id = rt10xx_phy_id(d->phy_addr);
if ((phy_id & 0xffff0000) == 0x220000) { // KSZ8081RNB
uint16_t pc1r = rt10xx_phy_read(d->phy_addr, 30); // Read PC1R
if ((pc1r & 3) == 1) rcr |= MG_BIT(9); // 10M
if ((pc1r & MG_BIT(2)) == 0) tcr &= ~MG_BIT(2); // Half-duplex
} else if ((phy_id & 0xffff0000) == 0x20000000) { // DP83825I
uint16_t physts = rt10xx_phy_read(d->phy_addr, 16); // Read PHYSTS
if (physts & 1) rcr |= MG_BIT(9); // 10M
if ((physts & MG_BIT(2)) == 0) tcr &= ~MG_BIT(2); // Half-duplex
} else { // Default to LAN8720
uint16_t scsr = rt10xx_phy_read(d->phy_addr, 31); // Read CSCR
if ((scsr & MG_BIT(3)) == 0) rcr |= MG_BIT(9); // 10M
if ((scsr & MG_BIT(4)) == 0) tcr &= ~MG_BIT(2); // Half-duplex
}
ENET->TCR = tcr; // IRQ handler does not fiddle with these registers
ENET->RCR = rcr;
Expand Down
45 changes: 27 additions & 18 deletions src/drivers/rt1020.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ static void rt10xx_phy_write(uint8_t addr, uint8_t reg, uint16_t val) {
while ((ENET->EIR & MG_BIT(23)) == 0) (void) 0;
}

static uint32_t rt10xx_phy_id(uint8_t addr) {
uint16_t phy_id1 = rt10xx_phy_read(addr, PHY_ID1);
uint16_t phy_id2 = rt10xx_phy_read(addr, PHY_ID2);
return (uint32_t) phy_id1 << 16 | phy_id2;
}

// MDC clock is generated from IPS Bus clock (ipg_clk); as per 802.3,
// it must not exceed 2.5MHz
// The PHY receives the PLL6-generated 50MHz clock
Expand Down Expand Up @@ -99,21 +105,20 @@ static bool mg_tcpip_driver_rt1020_init(struct mg_tcpip_if *ifp) {
rt10xx_phy_write(d->phy_addr, PHY_BCR, MG_BIT(12)); // Set autonegotiation

// PHY: Enable 50 MHz external ref clock at XI (preserve defaults)
uint16_t phy_id1 = rt10xx_phy_read(d->phy_addr, PHY_ID1);
uint16_t phy_id2 = rt10xx_phy_read(d->phy_addr, PHY_ID2);
MG_INFO(("PHY ID: %#04x %#04x", phy_id1, phy_id2));
uint32_t id = rt10xx_phy_id(d->phy_addr);
MG_INFO(("PHY ID: %#04x %#04x", (uint16_t) (id >> 16), (uint16_t) id));
// 2000 a140 - TI DP83825I
// 0007 c0fx - LAN8720
// 0022 1561 - KSZ8081RNB

if (phy_id1 == 0x22) { // KSZ8081RNB, like EVK-RTxxxx boards
if ((id & 0xffff0000) == 0x220000) { // KSZ8081RNB, like EVK-RTxxxx boards
rt10xx_phy_write(d->phy_addr, 31,
MG_BIT(15) | MG_BIT(8) | MG_BIT(7)); // PC2R
} else if (phy_id1 == 0x2000) { // DP83825I, like Teensy4.1
rt10xx_phy_write(d->phy_addr, 23, 0x81); // 50Mhz clock input
rt10xx_phy_write(d->phy_addr, 24, 0x280); // LED status, active high
} else { // Default to LAN8720
MG_INFO(("Defauling to LAN8720 PHY..."));
} else if ((id & 0xffff0000) == 0x20000000) { // DP83825I, like Teensy4.1
rt10xx_phy_write(d->phy_addr, 23, 0x81); // 50MHz clock input
rt10xx_phy_write(d->phy_addr, 24, 0x280); // LED status, active high
} else { // Default to LAN8720
MG_INFO(("Defaulting to LAN8720 PHY...")); // TODO()
}

// Select RMII mode, 100M, keep CRC, set max rx length, disable loop
Expand Down Expand Up @@ -148,18 +153,13 @@ static size_t mg_tcpip_driver_rt1020_tx(const void *buf, size_t len,
MG_ERROR(("No descriptors available"));
len = 0; // retry later
} else {
//MG_DEBUG(("sending %4lu, d=%u, c=%#hx %#lx %#lx", len, s_txno,
// s_txdesc[s_txno].control, ENET->EIR, ENET->ATSTMP));
memcpy(s_txbuf[s_txno], buf, len); // Copy data
s_txdesc[s_txno].length = (uint16_t) len; // Set data len
// Table 37-34, R, L, TC (Ready, last, transmit CRC after frame
s_txdesc[s_txno].control |=
(uint16_t) (MG_BIT(15) | MG_BIT(11) | MG_BIT(10));
ENET->TDAR = MG_BIT(24); // Descriptor ring updated
if (++s_txno >= ETH_DESC_CNT) s_txno = 0;

// Artificial delay. TODO(cpq): find a proper way to transmit reliably
for (volatile int i = 0; i < 99999; i++) (void) 0;
}
(void) ifp;
return len;
Expand All @@ -173,10 +173,19 @@ static bool mg_tcpip_driver_rt1020_up(struct mg_tcpip_if *ifp) {
if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up
uint32_t tcr = ENET->TCR |= MG_BIT(2); // Full-duplex
uint32_t rcr = ENET->RCR &= ~MG_BIT(9); // 100M
if (rt10xx_phy_read(d->phy_addr, PHY_ID1)) { // KSZ8081RNB ?
uint32_t pc1r = rt10xx_phy_read(d->phy_addr, 30); // Read PC2R
if ((pc1r & 3) == 1) rcr |= MG_BIT(9); // 10M
if ((pc1r & MG_BIT(2)) == 0) tcr &= ~MG_BIT(2); // Half-duplex
uint32_t phy_id = rt10xx_phy_id(d->phy_addr);
if ((phy_id & 0xffff0000) == 0x220000) { // KSZ8081RNB
uint16_t pc1r = rt10xx_phy_read(d->phy_addr, 30); // Read PC1R
if ((pc1r & 3) == 1) rcr |= MG_BIT(9); // 10M
if ((pc1r & MG_BIT(2)) == 0) tcr &= ~MG_BIT(2); // Half-duplex
} else if ((phy_id & 0xffff0000) == 0x20000000) { // DP83825I
uint16_t physts = rt10xx_phy_read(d->phy_addr, 16); // Read PHYSTS
if (physts & 1) rcr |= MG_BIT(9); // 10M
if ((physts & MG_BIT(2)) == 0) tcr &= ~MG_BIT(2); // Half-duplex
} else { // Default to LAN8720
uint16_t scsr = rt10xx_phy_read(d->phy_addr, 31); // Read CSCR
if ((scsr & MG_BIT(3)) == 0) rcr |= MG_BIT(9); // 10M
if ((scsr & MG_BIT(4)) == 0) tcr &= ~MG_BIT(2); // Half-duplex
}
ENET->TCR = tcr; // IRQ handler does not fiddle with these registers
ENET->RCR = rcr;
Expand Down