[R3mini] uboot getting ethernet/nvme to work

Hi,

i use dts and airoha phy driver from immortalwrt and try to get network working.


U-Boot 2024.01-bpi-r3mini-00008-g9448f7a5c567-dirty (Jan 17 2024 - 22:57:09 +0100)                                                
                                                                                                                                  
CPU:   MediaTek MT7986                                                                                                            
Model: Bananapi BPi-R3 Mini                                                                                                       
DRAM:  2 GiB                                                                                                                      
Core:  44 devices, 19 uclasses, devicetree: separate                                                                              
MMC:   mmc@11230000: 0                                                                                                            
Loading Environment from MMC... *** Warning - bad CRC, using default environment                                                  
                                                                                                                                  
In:    serial@11002000                                                                                                            
Out:   serial@11002000                                                                                                            
Err:   serial@11002000                                                                                                            
Net:   PHY = 3a2 - a411                                                                                                           
EN8811H PHY ready!                                                                                                                
EN8811H Mode 1 !                                                                                                                  
Tx, Rx Polarity(0xca0f8): 01a01501                                                                                                
MD32 FW Version(0x3b3c) : 23051209                                                                                                
LED initialize OK !                                                                                                               
EN8811H initialize OK ! (v1.0.4)                                                                                                  
                                                                                                                                  
Warning: ethernet@15100000 (eth0) using random MAC address - 3e:6b:b9:29:93:16                                                    
eth0: ethernet@15100000                                                                                                           
Hit any key to stop autoboot:  0                                                                                                  
BPI-R3M>                                                                                                                          
BPI-R3M> printenv ipaddr                                                                                                          
ipaddr=192.168.0.19                                                                                                               
BPI-R3M> setenv ipaddr 192.168.90.2                                                                                               
BPI-R3M> printenv ethadddr                                                                                                        
## Error: "ethadddr" not defined                                                                                                  
BPI-R3M> printenv ethaddr                                                                                                         
ethaddr=3e:6b:b9:29:93:16                                                                                                         
BPI-R3M> setenv ethaddr 00:e0:4c:68:01:1b                                                                                         
BPI-R3M> printenv ethaddr                                                                                                         
ethaddr=00:e0:4c:68:01:1b                                                                                                         
BPI-R3M> ping 192.168.90.1                                                                                                        
Using ethernet@15100000 device                                                                                                    
                                                                                                                                  
ARP Retry count exceeded; starting again                                                                                          
ping failed; host 192.168.90.1 is not alive                                                                                       
BPI-R3M>

it is based on this PR: mediatek: add support for Bananapi BPi-R3 Mini support by 1715173329 · Pull Request #1100 · immortalwrt/immortalwrt · GitHub

i do not see anything in tcpdump on the other side, not even any arp packets

btw. in linux i got network/nvme working with the help from eric using this code:

On R3mini: serdes rx needs reversed, tx needs normal.

#define EN8811H_POLARITY		0xca0f8
#define   EN8811H_POLARITY_TX_NORMAL		BIT(0)
#define   EN8811H_POLARITY_RX_REVERSE		BIT(1)

This means both bit 0 and 1 need to be set in 0xca0f8, if I remember correctly.

A bit confusing how these bits are defined, I cleaned here the original code a bit in the linux code. They used 4 defines describing the 2 bits…

So the code became actually quite simple:

	/* Serdes polarity */
	ret = air_buckpbus_reg_read(phydev, EN8811H_POLARITY, &pbus_value);
	if (ret < 0)
		return ret;
	if (device_property_read_bool(dev, "airoha,pnswap-rx"))
		pbus_value |=  EN8811H_POLARITY_RX_REVERSE;
	else
		pbus_value &= ~EN8811H_POLARITY_RX_REVERSE;
	if (device_property_read_bool(dev, "airoha,pnswap-tx"))
		pbus_value &= ~EN8811H_POLARITY_TX_NORMAL;
	else
		pbus_value |=  EN8811H_POLARITY_TX_NORMAL;
	ret = air_buckpbus_reg_write(phydev, EN8811H_POLARITY, pbus_value);
	if (ret < 0)
		return ret;

You could do the same in the u-boot code…

1 Like

seems this is already there:

see also print outputs:

Net:   PHY = 3a2 - a411                                                                                                           
EN8811H PHY ready!                                                                                                                
EN8811H Mode 1 !                                                                                                                  
Tx, Rx Polarity(0xca0f8): 01a01501                                                                                                
MD32 FW Version(0x3b3c) : 23051209                                                                                                
LED initialize OK !                                                                                                               
EN8811H initialize OK ! (v1.0.4)

mhm…so the value (0x01a01501) should be 3 at the end…i have only 0x1

this is how values are defined in the header-file

#define EN8811H_TX_POLARITY_NORMAL   0x1
#define EN8811H_TX_POLARITY_REVERSE  0x0

#define EN8811H_RX_POLARITY_NORMAL  (0x0 << 1)
#define EN8811H_RX_POLARITY_REVERSE (0x1 << 1)

based on your code the values are right, and TX-polarity is set (the lowest bit), but rx seems indeed wrong

it seems that ofnode_read_bool does return 0…

int rx_reverse=ofnode_read_bool(node, "airoha,rx-pol-reverse");
printf("Rx Polarity set in dts: %d\n", rx_reverse);
Rx Polarity set in dts: 0                                                                                                         
Tx, Rx Polarity(0xca0f8) to be written: 01a01501

I’ve changed it to these names after the rfc-patch comment from Andrew Lunn.

It uses almost the same name as:

mediatek,pnswap

i had understood that :wink: but this is not the problem…i wonder why ofnode_read_bool return 0 for rx…property is set and there is no typo…just try to debug drivers/core/ofnode.c now (seems not printing the debug-message when adding “#define DEBUG 1” before includes)

screenshot from @nezar_taima here confirms that the value written for serdes polarity is different

Symbol: OF_REAL [=y]

debug by adding #define DEBUG 1 before includes brings no additional debug-messages

can i print the current dts in uboot somehow? just to be sure the property still exists? but phy node is probed, so it should also find the property

it looks like the property is searched in the wrong node

PHY = 3a2 - a411                                                                                                                  
EN8811H PHY ready!                                                                                                                
EN8811H Mode 1 !                                                                                                                  
ofnode_has_property airoha,rx-pol-reverse (is_np? 1)                                                                              
of_find_property np:00000000bfaa25e0 airoha,rx-pol-reverse                                                                        
of_find_property compatible == airoha,rx-pol-reverse?                                                                             
of_find_property reg == airoha,rx-pol-reverse?                                                                                    
of_find_property resets == airoha,rx-pol-reverse?                                                                                 
of_find_property reset-names == airoha,rx-pol-reverse?                                                                            
of_find_property mediatek,ethsys == airoha,rx-pol-reverse?                                                                        
of_find_property mediatek,sgmiisys == airoha,rx-pol-reverse?                                                                      
of_find_property #address-cells == airoha,rx-pol-reverse?                                                                         
of_find_property #size-cells == airoha,rx-pol-reverse?                                                                            
of_find_property status == airoha,rx-pol-reverse?                                                                                 
of_find_property pinctrl-names == airoha,rx-pol-reverse?                                                                          
of_find_property pinctrl-0 == airoha,rx-pol-reverse?                                                                              
of_find_property mediatek,gmac-id == airoha,rx-pol-reverse?                                                                       
of_find_property phy-mode == airoha,rx-pol-reverse?                                                                               
of_find_property phy-handle == airoha,rx-pol-reverse?                                                                             
of_find_property phandle == airoha,rx-pol-reverse?                                                                                
readbool: airoha,rx-pol-reverse false                                                                                             
Rx Polarity set in dts: 0

it searches in the eth node not the phy node…

so possibly this is wrong:

static int en8811h_config(struct phy_device *phydev)
{
    ofnode node = phy_get_ofnode(phydev);

or this conversion in ofnode_has_property:

of_find_property(ofnode_to_np(node),…

@1715173329 have you an idea whats going on here or how i can debug this? I wonder why it is working in your build…which uboot version do you use (maybe new bug in 2024.01) maybe additional patches for of-functions or different parser (external fdt)?

if i skip the dt-property and set rx-reverse manually, and then it works once

BPI-R3M> setenv ipaddr 192.168.90.2
BPI-R3M> ping 192.168.90.1         
Using ethernet@15100000 device
host 192.168.90.1 is alive
BPI-R3M> ping 192.168.90.1
Using ethernet@15100000 device

Abort
ping failed; host 192.168.90.1 is not alive
BPI-R3M>

so same as in your tests…after first usage it is stalled…and the of-handling is strange

@hackpascal have you an idea about the hang (and maybe the wrong node)?

@ericwoud: i think the function you pointed should not be used as phydev have already an ofnode

And so this should be used:

But need to check it

i tried to print the related information, but it is crashing

if (phydev->dev)
    printf("%s devname: %s\n", __func__,phydev->dev->name);
if (node.np)
    printf("%s nodename: %s\n", __func__, node.np->name);

seems crash is caused by node.np->name

but it turnes out that phy-device is already the ethernet-node

en8811h_config devname: ethernet@15100000

basicly i can use phy-handle to go to the linked phy, but wonder why config gets the parent node and it works with the ethernet-node (yes i know that the phy is connected over the mdio-bus of ethernet-controller)

did this and it seems to work:

struct ofnode_phandle_args node_args;
if (ret) {
	printf("can't parse phy-handle (%d)\n",
		ret);
} else node = node_args.node;

int rx_reverse=ofnode_read_bool(node, "airoha,rx-pol-reverse");
printf("Rx Polarity set in dts: %d\n", rx_reverse);

results in:

en8811h_config devname: ethernet@15100000
PHY = 3a2 - a411
EN8811H PHY ready!
EN8811H Mode 1 !
readbool: airoha,rx-pol-reverse true
Rx Polarity set in dts: 1
readbool: airoha,tx-pol-reverse false
Tx, Rx Polarity(0xca0f8) to be written: 01a01503
Tx, Rx Polarity(0xca0f8): 01a01503
MD32 FW Version(0x3b3c) : 23051209
LED initialize OK !
EN8811H initialize OK ! (v1.0.4)

How do you handle the enable signals? Do the pio 16 and 17 pins stay low?

You mean the regulators for powering the phy?

I took this 1:1 from immortalwrt

But maybe it is better to define them as regulators…done this, but same problem


BPI-R3M> setenv ipaddr 192.168.90.2
BPI-R3M> ping 192.168.90.1         
Using ethernet@15100000 device
host 192.168.90.1 is alive
BPI-R3M> ping 192.168.90.1
Using ethernet@15100000 device

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

So which functions get called here again

oh, hawk eye…have not noticed this…but this seems right

net/ping.c:73:	printf("Using %s device\n", eth_get_name());

same message also exists in tftp.c and others.

Btw, where did you select which gmac to use? Is a second mac supported in uboot? Did you try other port?

Imho this is done by this property in the eth node:

mediatek,gmac-id = <0>;

Does not look like i can use both gmacs together. I can only try to set it to 1,but then imho i will need to use the other phy.

Would this have anything to do with env_get("ethrotate") ?

Is it set to 'no' ?

It’s just really strange, first attempt it works…

Where have you seen this? I do not see it in driver

https://github.com/u-boot/u-boot/blob/master/net/eth-uclass.c#L286
		/*
		 * If ethrotate is enabled, this will change "current",
		 * otherwise we will drop out of this while loop immediately
		 */

both times ethrotate is null (but called both times)

@dangowrt i tried to use your version of phy driver and added the old way with builtin firmware

looks like one option is using boot1 from emmc…how have you written it for testing?

i guess something like this:

cat files/bpi-r3mini/{EthMD32.dm.bin,EthMD32.DSP.bin} > en8811h.bin

tried to flash this file to emmc boot1, but failed

BPI-R3M> fatload usb 0:1 $loadaddr r3mini/en8811h.bin
147456 bytes read in 16 ms (8.8 MiB/s)
BPI-R3M> mmc partconf 0 1 1 2
BPI-R3M> mmc write $loadaddr 0x0 $filesize

MMC write: dev # 0, block # 0, count 147456 ... mmc write failed
0 blocks written: ERROR
BPI-R3M>

edit: got first problem (loading firmware from header) solved…missed CONFIG_PHY_ETHERNET_ID=y

edit: @ericwoud tried adding your host_restart way…but it does not solve the issue ;(

any idea?

Maybe this should only be done when firmware_version not set

Maybe i should move resets and firmware-load to probe,which is only called once. Edit: this results in crash :(, tried moving phy-reset in the condition (firmware not loaded yet), but same issue…only working once

made also some cleanup like replacing magic numbers for firmware-load with constants like in erics code and fixed indentation.

Nvme seems my fault,had to put missing constant in different block (with higher value).

I would not put too much effort into this driver. Once Eric’s driver got merged in upstream Linux, the best would be to port that to U-Boot (and just keep the firmware loading from {MMC,UBI/SNAND,MTD/NOR} options added, so firmware can always be loaded even if runtime firmware or filesystems are damaged).

I tried to write firmware to mmc (the easiest way i think to do manually because ubi needs to create ubifs first and nor is not available on r3mini),but got write error…any idea on this?