22
33w5500if.c -- W5500 device driver
44
5- Copyright (C) 2024 - 2025 Extrems' Corner.org
5+ Copyright (C) 2024 - 2026 Extrems' Corner.org
66
77This software is provided 'as-is', without any express or implied
88warranty. 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
332335static struct netif * w5500_netif ;
333336static u8 Dev [EXI_CHANNEL_MAX ];
337+ static u8 Freq [EXI_CHANNEL_MAX ];
334338
335339static 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
378381static 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
392394static 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