[BPi-R3-Mini] Airoha EN8811H 2.5G PHY driver

Great work,hope we can port the driver to uboot to have network support there too.

I am not very familiar with uboot, but does it do like so when executing network commands?

Link up - execute command - link diwn.

If so, then need to restart mcu at beginning of command, starting at second command. ,(or already at end if command)

I’m not sure but with current driver we have the problem that only first network access works then it is blocked,not sure why

I think that is why, but need to see when uboot does link up/down.

The hardware does not handle link down and then link up again very nicely.

Edit:

After firmware load the mcu is reset, so this is why it only works once. Then after link down, need to reset mcu when going link up again.

The code in net-next does like so, so perhaps porting is enough.

Maybe problem is that we use genphy_shutdown here?

Reset is done on startup (till the linked line…also a bit above).

But afair this is only called once (not on second net access).

Seems there are no link_up/down callbacks.

That version is not a port of the version that is added to net-next.

I think it has to undergo many changes to be able to be upstreamed to u-boot. These changes will be the same as I made for the linux version.

Better to start with a port of the linux (net-next) version. Using the version you have as an example how the driver would be ported.

I have shifted focus on finishing the rtl8221b patch-set and the bpi-m7. This will take all the time I have available.

Edit:

Or mix the code a bit, use a bit of both.

yes it is a mixup of openwrt version (originally taken from immortalwrt with some other firmware-options) and readded builtin firmware via h-file (i took from immortalwrt but updated to last version i had).

as far i see, most parts are related to LED which are not needed in uboot, so i guess i can safely drop them…but currently habe no idea how to map the callbacks which are completely different to linux

https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/drivers/net/phy/air_en8811h.c#n1055

I found in linux that mavell10g.c and aquantia.c are pretty good examples of how it should be done. In U-Boot they also seem like interesting examples. The also make clear, you do not have to use all the callbacks.

I just wonder if .startup() and/or .config() are called every time a u-boot command is executes, or just once.

Edit:

aquantia_config shows that firmware should be loaded in .config(), although it is not supported.

The following can be replaced (and dropped):

air_mii_cl22_read  -> phy_read
air_mii_cl22_write -> phy_write

And also these, (if C45 over C22 is setup correctly in U-Boot i assume)

air_mii_cl45_read  -> phy_read_mmd
air_mii_cl45_write -> phy_write_mmd

Everything with:

air_pbus_reg_write

Can be dropped (confirmed by Airoha).

I changed:

static unsigned int air_buckpbus_reg_read(struct phy_device *phydev, unsigned long pbus_address)
to
static int air_buckpbus_reg_read(struct phy_device *phydev, u32 pbus_address, u32 *pbus_data)

since pbus_data is 32 bits and so is PBUS_INVALID_DATA…

.

That will clean it up a bit to start with.

dropped some of the functions you’ve mention from the current driver to make a cleanup

still working, now i try to figure out this

:wink:

but it looks like the current uboot phy driver does not get into AN mode the second time

i do not see config getting called…

BPI-R3M> version
U-Boot 2024.04-bpi-r3mini-00022-g1a77c35dd64e-dirty (Apr 03 2024 - 16:51:11 +0200)

BPI-R3M> setenv ipaddr 192.168.0.19
BPI-R3M> ping 192.168.0.10 
EN8811H driver startup.
EN8811H driver load_firmware.
EN8811H PHY ready!
EN8811H Mode 1 !
Tx, Rx Polarity(0xca0f8): 01a01503
MD32 FW Version(0x3b3c) : 24011202
LED initialize OK !
EN8811H initialize OK ! (v1.0.4)
ethernet@15100000 Waiting for PHY auto negotiation to complete...... done
EN8811H driver get autoneg.
AN mode!
SPEED 1000/100!
Using ethernet@15100000 device
host 192.168.0.10 is alive
BPI-R3M> ping 192.168.0.10 
EN8811H driver startup.
EN8811H driver restart_host.
EN8811H PHY ready!
EN8811H Mode 1 !
Tx, Rx Polarity(0xca0f8): 01a01503
MD32 FW Version(0x3b3c) : 24011202
LED initialize OK !
EN8811H initialize OK ! (v1.0.4)
ethernet@15100000 Waiting for PHY auto negotiation to complete...... done
Using ethernet@15100000 device

ARP Retry count exceeded; starting again
ping failed; host 192.168.0.10 is not alive
BPI-R3M>

but startup is called everytime, but then decides between load_firmware or restart_host

it looks like the config-member is only triggered manually in the eth driver

for mediatek it should be done here

but i wonder why this did not happen

edit: i think i found the issue why it only work once…yeah…current driver checks for old_link and then exits…if i drop this, i can trigger multiple transfers :stuck_out_tongue: of course AN is done every time, and so there is some delay and messages, but i can use tftp with filelist before

1 Like

Great!!!.

i need to look into the phydev->link which and maybe reapply settings to phy to skip autoneg itself to make it clean, but i dropped many parts so driver is now smaller…

thinking of dropping the led-parts too to make it even smaller…who need ethernet-leds in bootloader?? :smiley:

and replacing some magic values to come near upstreaming

but a very productive day…nvme on r4 is basicly working too :slight_smile:

and you can put the contents of the .h in the .c file, ending up with 1 file.

That makes the file bigger again…another thought was moving led code into separate c file to compile/link only when the config is set…this way we can drop most of the ifdefs

But idk how to proceed with the config-callback which seems not called

also noted that speed was only 100 instead of 1000 Mbit…fixed it by changing & to | for common_adv_gb :slight_smile:

				lpagb = phy_read(phydev, MDIO_DEVAD_NONE, MII_STAT1000);
				if (lpagb < 0 )
					return lpagb;
				advgb = phy_read(phydev, MDIO_DEVAD_NONE, MII_CTRL1000);
				if (advgb < 0 )
					return advgb;
				common_adv_gb = (lpagb & (advgb << 2)); //why shifting and then & (=masking with returned value)...imho should  be |

and after the link-check basicly only reads are done for autoneg…so i wonder why exiting before it breaks functionality…maybe startup should not return 0 more the result of AN

Mhm…genphy_parse_link also returns 0 and its return is used for return in genphy_startup

maybe we can use this function to drop the big codeblock for getting the link mode…

@1715173329 @dangowrt imho the changes are also usefultfor you (drop of some functions, change to HIWORD/LOWORD, 1g fix, drop of return on existing link - maybe you have an idea why this happens…return 0 should be ok).

1 Like

using genphy_parse_link seems not working here…code looks similar, structured differently, but does not work like this way:

			ret = en8811h_get_autonego(phydev, &phydev->autoneg);
			if (ret) {
				printf("EN8811H get AN fail.\n");
				return ret;
			}
			ret = genphy_parse_link(phydev);
			printf("EN8811H genphy_parse_link (ret:%d)...\n",ret);
			printf("EN8811H speed (after genphy): %d duplex: %d pause: %d asym_pause: %d\n",phydev->speed, phydev->duplex,phydev->pause,phydev->asym_pause);
EN8811H speed: 100 duplex: 1 pause: 0 asym_pause: 0
EN8811H BMSR_LSTATUS
EN8811H driver get autoneg.
EN8811H genphy_parse_link (ret:0)...
EN8811H speed (after genphy): 100 duplex: 1 pause: 0 asym_pause: 0
Using ethernet@15100000 device

ARP Retry count exceeded; starting again
ping failed; host 192.168.0.10 is not alive
BPI-R3M>

current code matches for LPA flags where genphy looks for SUPPORTED_1000baseT_Full

	if (common_adv_gb & (LPA_1000FULL | LPA_1000HALF))
	else if (common_adv & (LPA_100FULL | LPA_100HALF))

seems like current phy-driver does not set the phydev->supported field…so i added like this:

phydev->supported = ( SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half);

and genphy_parselink returns with

EN8811H speed (after genphy): 1000 duplex: 1 pause: 0 asym_pause: 0

but ping does not work ;(

something is still different…but output is same (and after adding the phylink-suported set i can change back the 1G-“fix” back to &)

EN8811H speed: 100 duplex: 1 pause: 0 asym_pause: 0
EN8811H BMSR_LSTATUS
EN8811H driver get autoneg.
EN8811H genphy_parse_link (ret:0)...
EN8811H (after genphy) speed: 1000 duplex: 1 pause: 0 asym_pause: 0
AN mode...SPEED 1000/100!
EN8811H speed detection (adv_gb: 0x00000800,adv: 0x00000101)...
EN8811H speed 1000...
EN8811H (after original code) speed: 1000 duplex: 1 pause: 0 asym_pause: 0      
Using ethernet@15100000 device                                                  
host 192.168.0.10 is alive                                                      
BPI-R3M>

wonder why genphy is not enough…both seem to only read and set only the phydev members and do this to same values

Check the other phy drivers in u-boot: drivers/net/phy · master · U-Boot / U-Boot · GitLab (denx.de)

They all have the #define’s inside 1 file, together with the code.

yes i can do later, but first i need to fix the genphy-issue…it looks like code does the same as in the airoha driver, but it does not work…it sets only the phydev fields the same way…no external writes/calls to the phy itself…only changing the struct that is then read from the phylib

i guess the or change is wrong…i guess it should intersect the advertised modes with the received advertising…

I’ve modified the driver to load the EN8811H firmware from either eMMC boot1 or a UBI volume called ‘en8811h-firmware’ from UBI – that will allow updating the firmware for U-Boot without having to replace U-Boot itself. It also prevents the firmware being linked into U-Boot which would require it to be licensed under GPL-2.0+ (like U-Boot)…

I had not got the flash of firmware to emmc boot1 working [R3mini] uboot getting ethernet/nvme to work - #18 by frank-w

we can also continue in this thread as this is u-boot specific

@dangowrt have you an idea why genphy function does not work?

btw. my current code is in branch 2024-04-bpi-r3mini…and now 1000Mbit works without the or-change (maybe because the phydev->supported addition) a cleaner version (without the genphy part) is in 2024-04-bpi…if you want to change openwrt/immortalwrt at this point to get the second network access working

@eric: have you seen that on Mar 28, 2024 firmware got an update (merged today based on ML)?

Btw. Added phy driver to my 6.6-main and also the other patches to support r3mini - also tested with new firmware…seems to work well :wink:

Thanks!!!