January 10, 2023

Kyu networking -- H3 network PHY, an old mistake discovered

First a brief note on psychology. I am amazed how many times when working on difficult problems that I figure out the answer when I am not nose to the screen working on it. It is important to collect information and get your brain charged with details. But it is surprising how many times the answer comes when taking a break and pondering with a relaxed mind.

Perhaps 5 years ago I worked on the phy/mdio code for the Allwinner H3. It was all new to me and I was up to my ears with new information. I was having strange and confusing problems with basic MDIO reads and writes. I seemed like I had to read twice to get the result I expected.

The problem had nothing to do with reads, it was a basic error in my low level mdio write routine. You must write to the data register, then write to command register telling to write that data. Simple enough.

Autonegotiation

I had some idea that this would happen when I reset the PHY. Maybe it does with some PHY chips, but not the PHY built into the H3. You enable autonegotiation, then start it. Then you poll a bit that tells you when autonegotiation is complete. It takes almost 3 full seconds!

The problem now is that I have autonegotiation working, but the network driver is dead after it finishes. I have the happy confirmation that autonegotiation is working by looking at the LED on the little Netgear switch my board is connected two. Before autonegotiation it shows the single 10 mbit LED. During autonegotiation, all the speed LED go out. When autonegotiation finishes, the 100 mbit LED is on.

When I reboot it, the LED goes out briefly, then the single 10 mbit LED comes on. So the problem now is to get the emac to be happy after the autonegotiation does the transition to 100 Mbit.

NetBSD

I took at look at the latest NetBSD sources from git.
sys/arch/arm/sunxi/sunxi_emac.c
sys/arch/arm/sunxi/sunxi_emac.h
Some quick searching turns up a routine "sunxi_emac_update_link" that is writing to registers based on speed and duplex. It writes to: It does the "update_link" (mediachg) call at the end of initialization.

It has a routine "setup_phy" that seems to entirely work with the syscon register. As a side note, it sets the internal PHY address to "1".

U-Boot

The emac drivers looks to be:
drivers/net/sun8i_emac.c

Conclusion

So, what have we learned? We now know how to perform autonegotiation with the PHY. We confirm that this has bumped us to 100 megabit by looking at the LED on my Netgear switch. However, once this has happened, the network is kaput.

One odd thing I have yet to explain:

Emac rx_count: 99
Emac tx_count: 103
It is as though I have sent and received some packets and then everything locked up. And indeed I have. I seems that Kyu has done the whole symbol table transfer just fine after initializing the driver!! And properly too.

Why can we do this, then after we are done, all networking is stuck. And why does bypassing the PHY stuff make this all work?


Have any comments? Questions? Drop me a line!

Kyu / [email protected]