Skip to content

Commit 0ee5455

Browse files
committed
Implement EXI speed negotiation for W5500
1 parent c485d51 commit 0ee5455

1 file changed

Lines changed: 23 additions & 14 deletions

File tree

lwip/netif/w5500if.c

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
w5500if.c -- W5500 device driver
44
5-
Copyright (C) 2024 - 2025 Extrems' Corner.org
5+
Copyright (C) 2024 - 2026 Extrems' Corner.org
66
77
This software is provided 'as-is', without any express or implied
88
warranty. In no event will the authors be held liable for any
@@ -127,7 +127,9 @@ typedef enum {
127127
W5500_UPORTR0, // Unreachable Port Register 0
128128
W5500_UPORTR1, // Unreachable Port Register 1
129129
W5500_PHYCFGR, // PHY Configuration Register
130-
W5500_VERSIONR = W5500_REG(0x39), // Chip Version Register
130+
W5500_UNKNOWNR0 = W5500_REG(0x37), // Unknown Register 0
131+
W5500_UNKNOWNR1, // Unknown Register 1
132+
W5500_VERSIONR, // Chip Version Register
131133

132134
#define W5500_S(n) \
133135
W5500_S##n##_MR = W5500_REG_S(n, Sn_MR), \
@@ -188,6 +190,7 @@ typedef enum {
188190
W5500_PSID = W5500_REG(0x24), // PPPoE Session ID Register
189191
W5500_PMRU = W5500_REG(0x26), // PPPoE Maximum Receive Unit Register
190192
W5500_UPORTR = W5500_REG(0x2C), // Unreachable Port Register
193+
W5500_UNKNOWNR = W5500_REG(0x37), // Unknown Register
191194

192195
#define W5500_S(n) \
193196
W5500_S##n##_PORT = W5500_REG_S(n, Sn_PORT), \
@@ -331,6 +334,7 @@ struct w5500if {
331334

332335
static struct netif *w5500_netif;
333336
static u8 Dev[EXI_CHANNEL_MAX];
337+
static u8 Freq[EXI_CHANNEL_MAX];
334338

335339
static bool W5500_ReadCmd(s32 chan, u32 cmd, void *buf, u32 len)
336340
{
@@ -339,7 +343,7 @@ static bool W5500_ReadCmd(s32 chan, u32 cmd, void *buf, u32 len)
339343
cmd &= ~W5500_RWB;
340344
cmd = (cmd << 16) | (cmd >> 16);
341345

342-
if (!EXI_Select(chan, Dev[chan], EXI_SPEED32MHZ))
346+
if (!EXI_Select(chan, Dev[chan], Freq[chan]))
343347
return false;
344348

345349
err |= !EXI_ImmEx(chan, &cmd, 3, EXI_WRITE);
@@ -355,7 +359,7 @@ static bool W5500_WriteCmd(s32 chan, u32 cmd, const void *buf, u32 len)
355359
cmd |= W5500_RWB;
356360
cmd = (cmd << 16) | (cmd >> 16);
357361

358-
if (!EXI_Select(chan, Dev[chan], EXI_SPEED32MHZ))
362+
if (!EXI_Select(chan, Dev[chan], Freq[chan]))
359363
return false;
360364

361365
err |= !EXI_ImmEx(chan, &cmd, 3, EXI_WRITE);
@@ -374,7 +378,6 @@ static bool W5500_WriteReg(s32 chan, W5500Reg addr, u8 data)
374378
return W5500_WriteCmd(chan, W5500_OM(1) | addr, &data, 1);
375379
}
376380

377-
#if 0
378381
static bool W5500_ReadReg16(s32 chan, W5500Reg16 addr, u16 *data)
379382
{
380383
u16 tmp;
@@ -387,7 +390,6 @@ static bool W5500_ReadReg16(s32 chan, W5500Reg16 addr, u16 *data)
387390

388391
return true;
389392
}
390-
#endif
391393

392394
static bool W5500_WriteReg16(s32 chan, W5500Reg16 addr, u16 data)
393395
{
@@ -546,6 +548,7 @@ static bool W5500_Init(s32 chan, s32 dev, struct w5500if *w5500if)
546548
{
547549
bool err = false;
548550
u8 sr, versionr;
551+
u16 unknownr;
549552
u32 id;
550553

551554
while (!EXI_ProbeEx(chan));
@@ -558,12 +561,20 @@ static bool W5500_Init(s32 chan, s32 dev, struct w5500if *w5500if)
558561

559562
EXI_LockEx(chan, dev);
560563
Dev[chan] = dev;
561-
562-
if (!W5500_ReadReg(chan, W5500_VERSIONR, &versionr) || versionr != 0x04) {
563-
EXI_Unlock(chan);
564-
if (chan < EXI_CHANNEL_2 && dev == EXI_DEVICE_0)
565-
EXI_Detach(chan);
566-
return false;
564+
Freq[chan] = EXI_SPEEDMAX - 1;
565+
566+
while (!W5500_Reset(chan) ||
567+
!W5500_ReadReg16(chan, W5500_UNKNOWNR, &unknownr) || unknownr != 0x7825 ||
568+
!W5500_ReadReg(chan, W5500_VERSIONR, &versionr) || versionr != 0x04) {
569+
if (Freq[chan] > EXI_SPEED16MHZ) {
570+
Freq[chan]--;
571+
continue;
572+
} else {
573+
EXI_Unlock(chan);
574+
if (chan < EXI_CHANNEL_2 && dev == EXI_DEVICE_0)
575+
EXI_Detach(chan);
576+
return false;
577+
}
567578
}
568579

569580
w5500if->chan = chan;
@@ -572,8 +583,6 @@ static bool W5500_Init(s32 chan, s32 dev, struct w5500if *w5500if)
572583
w5500if->txQueue[0] = 0;
573584
w5500if->rxQueue = 0;
574585

575-
err |= !W5500_Reset(chan);
576-
577586
W5500_GetMACAddr(chan, w5500if->ethaddr->addr);
578587
err |= !W5500_WriteReg(chan, W5500_SHAR0, w5500if->ethaddr->addr[0]);
579588
err |= !W5500_WriteReg(chan, W5500_SHAR1, w5500if->ethaddr->addr[1]);

0 commit comments

Comments
 (0)