Dual Ethernet

We have a custom board based upon the BBB. Added a second phy at MDIO address 5. Modified device tree to mux pins and set up phys. When the board boots I do a grep on dmesg for mdop/ I see a mask 0xffffffef, when I should see a mask of 0xffffffcf. I am having trouble understanding where this mask comes from. According to the AM335x datasheet, the mask should be from the Ethernet MDIO register alive register, inverted. When does this register get populated?
Thanks!

I meant dmesg | grep mdio. Here is output.

beaglebone:~$ dmesg | grep mdio
[ 1.319622] davinci_mdio 4a101000.mdio: davinci mdio revision 1.6, bus freq 1000000
[ 1.319638] davinci_mdio 4a101000.mdio: detected phy mask ffffffef
[ 1.338962] libphy: 4a101000.mdio: probed
[ 1.338993] davinci_mdio 4a101000.mdio: phy[4]: device 4a101000.mdio:04, driver Atheros 8035 ethernet
[ 19.657691] Atheros 8035 ethernet 4a101000.mdio:04: attached PHY driver [Atheros 8035 ethernet] (mii_bus:phy_addr=4a101000.mdio:04, irq=POLL)

Relevant portions of device tree:

cpsw_default: cpsw-default {
pinctrl-single,pins = <
/* Slave 1 /
AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /
mii1_txen.rgmii1_tctl /
AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE2) /
mii1_rxdv.rgmii1_rctl /
AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE2)
AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLDOWN, MUX_MODE2)
AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLDOWN, MUX_MODE2)
AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE2)
AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE2)
/
Slave 2 /
AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /
mii2_txen.rgmii1_tctl /
AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT_PULLDOWN, MUX_MODE2) /
mii2_rxdv.rgmii1_rctl /
AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
AM33XX_PADCONF(AM335X_PIN_GPMC_A3, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
AM33XX_PADCONF(AM335X_PIN_GPMC_A4, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_INPUT_PULLDOWN, MUX_MODE2)
AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_INPUT_PULLDOWN, MUX_MODE2)
AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT_PULLDOWN, MUX_MODE2)
AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT_PULLDOWN, MUX_MODE2)
AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_INPUT_PULLDOWN, MUX_MODE2)
AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /
reset line */

;
};

cpsw_sleep: cpsw-sleep {
pinctrl-single,pins = <
/* Slave 1 reset value /
AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)
AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE7)
AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
/
Slave 2 /
AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_INPUT_PULLDOWN, MUX_MODE7) /
mii2_txen.rgmii1_tctl /
AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT_PULLDOWN, MUX_MODE7) /
mii2_rxdv.rgmii1_rctl */
AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_INPUT_PULLDOWN, MUX_MODE7)
AM33XX_PADCONF(AM335X_PIN_GPMC_A3, PIN_INPUT_PULLDOWN, MUX_MODE7)
AM33XX_PADCONF(AM335X_PIN_GPMC_A4, PIN_INPUT_PULLDOWN, MUX_MODE7)
AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_INPUT_PULLDOWN, MUX_MODE7)
AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_INPUT_PULLDOWN, MUX_MODE7)
AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_INPUT_PULLDOWN, MUX_MODE7)
AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_INPUT_PULLDOWN, MUX_MODE7)
AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT_PULLDOWN, MUX_MODE7)
AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT_PULLDOWN, MUX_MODE7)
AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_INPUT_PULLDOWN, MUX_MODE7)

;
};

&mac {
pinctrl-names = “default”, “sleep”;
pinctrl-0 = <&cpsw_default>;
pinctrl-1 = <&cpsw_sleep>;
dual_emac = <1>;
status = “okay”;
};

&davinci_mdio {
pinctrl-names = “default”, “sleep”;
pinctrl-0 = <&davinci_mdio_default>;
pinctrl-1 = <&davinci_mdio_sleep>;
status = “okay”;
};

&cpsw_emac0 {
phy_id = <&davinci_mdio>, <4>;
phy-mode = “rgmii-txid”;
dual_emac_res_vlan = <1>;
};

&cpsw_emac1 {
phy_id = <&davinci_mdio>, <5>;
phy-mode = “rgmii-txid”;
dual_emac_res_vlan = <2>;
};

I have a 3 year old BB-X15 with a dual PHY at home. I haven’t touched Linux for a couple of years, but am trying to pick it back up on a hobby basis. We were working on a custom board with a dual PHY, but that effort was put on hold a couple of year’s ago. Message me if you need me to try anything on the BB-X15 which could help with your custom board. If something useful flushes out then it should be posted in public forums.

On my BB-X15, I just downloaded the latest image and did dmesg|grep mdio (without anything plugged into the Ethernet ports):

debian@beaglebone:~$ dmesg|grep mdio
[ 1.112050] davinci_mdio 48485000.mdio: davinci mdio revision 1.6, bus freq 1000000
[ 1.112061] libphy: 48485000.mdio: probed
[ 1.134048] davinci_mdio 48485000.mdio: phy[1]: device 48485000.mdio:01, driver Micrel KSZ9031 Gigabit PHY
[ 1.134059] davinci_mdio 48485000.mdio: phy[2]: device 48485000.mdio:02, driver Micrel KSZ9031 Gigabit PHY
[ 6.572870] Micrel KSZ9031 Gigabit PHY 48485000.mdio:01: attached PHY driver [Micrel KSZ9031 Gigabit PHY] (mii_bus:phy_addr=48485000.mdio:01, irq=POLL)
[ 6.710705] Micrel KSZ9031 Gigabit PHY 48485000.mdio:02: attached PHY driver [Micrel KSZ9031 Gigabit PHY] (mii_bus:phy_addr=48485000.mdio:02, irq=POLL)
[ 24.576701] Micrel KSZ9031 Gigabit PHY 48485000.mdio:01: attached PHY driver [Micrel KSZ9031 Gigabit PHY] (mii_bus:phy_addr=48485000.mdio:01, irq=POLL)
[ 24.684787] Micrel KSZ9031 Gigabit PHY 48485000.mdio:02: attached PHY driver [Micrel KSZ9031 Gigabit PHY] (mii_bus:phy_addr=48485000.mdio:02, irq=POLL)
debian@beaglebone:~$

debian@beaglebone:~$ uname -a
Linux beaglebone 4.14.108-ti-r131 #1buster SMP PREEMPT Tue Mar 24 19:18:36 UTC 2020 armv7l GNU/Linux
debian@beaglebone:~$ cat /etc/debian_version
10.3

uname -r
cat /etc/debian_version:

Thanks!

Also, we found that it was useful for custom board issues to consult both beagleboard.org and TI-E2E, but for the latter, it was necessary to switch to the TI-SDK builds as TI didn’t support beagleboard/Debian builds at the time…

FYI,

I think I can help if interested. I just finished supporting a custom project that used Bone Debian. The board used two ethernet PHYs. Setting everything up can be a pain. I can share what I did, but the actual PHYs just happened to have configuration stuff already installed so adding to a custom devicw tree was a bit simpler.
If using an unsupported Ethernet Chip, you may have to see if they have a header file in C that can be imported into a device tree.

Ray.

We are using a supported phy. The Atheros, just like on the TI EVM. The only differences between our board and the TI EVM are that we are using an oscillator to clock both phys instead of a crystal per phy and we have them wired to be MDIO addresses 4 & 5 instead of 0 & 1.

I appreciate any help you can provide!

Correct me if I’m wrong, but what your saying is only one Ethernet PHY works and the other one doesn’t (based on seeing in your dmesg only 4 came active)? Did you connect both to an unmanaged switch and still only seen 4?

If so, it sounds like one of two things:

  1. The one designated as address 5 on the mdio bus is the wrong device address. Interestingly, I had a similar thing happen and we thought we identified the address according to the schematics but wasn’t working. After recounting the binary numbers for the address based what lines where used to create the address in the schematic, we were off. It showed up in dmesg after that with the corrected mdio bus address.

  2. Whenever you have two PHYS you have to do three things to get it to work better.

A. Remove connmanctl ($ sudo apt remove connman) This is a network manager that doesn’t play well with two phys unless you really know what you’re doing (you have to give each phy a designator for it’s MAC address with connmanctl). I found it’s just easier to remove it from the Kernel.

B. You should define two phys in the “interfaces” file located at /etc/network

Change this:
#auto eth0

#iface eth0 inet dhcp

To (dhcp only):

auto eth0

iface eth0 inet dhcp

auto eth1
iface eth1 inet dhcp

or To (static ip address):
auto eth0

iface eth0 inet static
address 192.168.50.1
netmask 255.255.255.0

auto eth1
iface eth1 inet static
address 192.168.100.1

netmask 255.255.255.0

C. This one may be the biggest issue I seen with using two phys in older kernels as it will rename the second one really strange or not use it at all. If using an older Kernel, check for it to have /etc/udev/rules.d/70-persistent-net.rules If it has that file, you will need to edit it to remove the renaming and usage. The devleopment prototype I was working on had two PHYs and did not work correclty until I edited this file then both showed up after deisgnated in the interfaces file. If you need to know more about what to edit… reply and I’ll help.

Regards,
Ray

We are using a supported phy. The Atheros, just like on the TI EVM. The only differences between our board and the TI EVM are that we are using an oscillator to clock both phys instead of a crystal per phy and we have them wired to be MDIO addresses 4 & 5 instead of 0 & 1.

I appreciate any help you can provide!

Also,

$ ifconfig is your best friend if you’re not using it. Learn it’s other functions like ifup and ifdown too. You can reset a phy without rebooting. Right now, it sounds like if you used $ ifconfig you’d get eth0 but no eth1, … other than USB and loopback (lo).

Correct me if I’m wrong, but what your saying is only one Ethernet PHY works and the other one doesn’t (based on seeing in your dmesg only 4 came active)? Did you connect both to an unmanaged switch and still only seen 4?

If so, it sounds like one of two things:

  1. The one designated as address 5 on the mdio bus is the wrong device address. Interestingly, I had a similar thing happen and we thought we identified the address according to the schematics but wasn’t working. After recounting the binary numbers for the address based what lines where used to create the address in the schematic, we were off. It showed up in dmesg after that with the corrected mdio bus address.

  2. Whenever you have two PHYS you have to do three things to get it to work better.

A. Remove connmanctl ($ sudo apt remove connman) This is a network manager that doesn’t play well with two phys unless you really know what you’re doing (you have to give each phy a designator for it’s MAC address with connmanctl). I found it’s just easier to remove it from the Kernel.

B. You should define two phys in the “interfaces” file located at /etc/network

Change this:
#auto eth0

#iface eth0 inet dhcp

To (dhcp only):

auto eth0

iface eth0 inet dhcp

auto eth1
iface eth1 inet dhcp

or To (static ip address):
auto eth0

iface eth0 inet static
address 192.168.50.1
netmask 255.255.255.0

auto eth1
iface eth1 inet static
address 192.168.100.1

netmask 255.255.255.0

C. This one may be the biggest issue I seen with using two phys in older kernels as it will rename the second one really strange or not use it at all. If using an older Kernel, check for it to have /etc/udev/rules.d/70-persistent-net.rules If it has that file, you will need to edit it to remove the renaming and usage. The devleopment prototype I was working on had two PHYs and did not work correclty until I edited this file then both showed up after deisgnated in the interfaces file. If you need to know more about what to edit… reply and I’ll help.

Regards,
Ray

We are using a supported phy. The Atheros, just like on the TI EVM. The only differences between our board and the TI EVM are that we are using an oscillator to clock both phys instead of a crystal per phy and we have them wired to be MDIO addresses 4 & 5 instead of 0 & 1.

I appreciate any help you can provide!

Ray,

Thanks for the detailed response. Greatly appreciated!

What was wrong with your schematic? And how did you get it to show up in dmesg? I have triple checked our schematic, the board layout and the resistors on the board itself. And, yes, the phy on address 4 is detected and works find. The phy on address 5 is not detected and does not work when connected to a switch. I am running debian 4.19. I am rebuilding the kernel with the MDIO ALIVE register overriden by a hard-coded mask of 0xffffffcf in davinci_mdio.c. That is the value I would expect. The mask is actually the inverted value of the MDIO ALIVE register. I suspect this register is populated by the boot ROM. I didn’t get a chance to check if this modification to the davinci_mdio driver actually works on the board. Won’t be until Mon.

Todd

Our schematic had one more line set for the address than we thought and instead of unsoldering something, we just changed the address in the devicetree, and then it showed up. For our prototype we were using two dp83867 phys.
I think the second phy came up as a undefined phy device even when it wasn’t set correctly. That’s how we knew it was there, just not right.

If you are only seeing one phy, it leads me to believe it’s not wired correctly or the phy chip is defective. You could monitor the mdio bus with an oscilloscope or bus analyzer to see if anything else responds when it boots. I think the phy sends an alive message during bootup. If it’s not getting that… something is physically wrong.

Hardware blames software, software blames hardware… :slight_smile:

Ray.

So, I got both phys to be recognized at boot:

debian@beaglebone:~$ dmesg | grep mdio
[ 1.323628] davinci_mdio 4a101000.mdio: davinci mdio revision 1.6, bus freq 1000000
[ 1.323645] davinci_mdio 4a101000.mdio: detected phy mask ffffffcf
[ 1.360081] libphy: 4a101000.mdio: probed
[ 1.360113] davinci_mdio 4a101000.mdio: phy[4]: device 4a101000.mdio:04, driver Atheros 8035 ethernet
[ 1.360121] davinci_mdio 4a101000.mdio: phy[5]: device 4a101000.mdio:05, driver Atheros 8035 ethernet
[ 20.193934] Atheros 8035 ethernet 4a101000.mdio:04: attached PHY driver [Atheros 8035 ethernet] (mii_bus:phy_addr=4a101000.mdio:04, irq=POLL)

The second phy was being held in reset. Fixed that. Now, I see that the RGMII2 pins on the processor are in the ‘sleep’ configuration (mode 7). Also, with the TI EVM I have, the last dmesg is repeated for the second phy at address 5 and the pins are muxed properly. I have scoured the Internet to no avail to figure out why not.

All help is greatly appreciated!

Do you solve your problem, I have same issue with you

1 Like

Wasn’t a big priority, so no.

1 Like

I know you’ve already sorted out the phy not being discovered, but just to clarify: the “mdio alive” register is filled in by hardware based on periodic scanning of the mdio bus.

Also, I notice that you’re configuring the interface to “rgmii-txid”, but the am335x does not support internal delay for RGMII.

Are you saying the pins are muxed for only one of the two RGMII interfaces? Because that would be quite strange since the pins for both RGMII interfaces are declared in the same pinmux node. The only explanation I’d have is that the first RGMII interface is perhaps already muxed by u-boot and the kernel isn’t applying the pinmux at all for whatever reason, e.g. a conflict with another pinmux node. That should however result in an obvious error in the kernel log.

You can also use my show-pins utility with the -v option to tell whether the pins are actually being configured by the kernel, e.g.:

eth mii tx en                     69 fast    down 2 rgmii 0 txctl    ethernet@4a100000 (cpsw_default)

would mean the pin is muxed by the kernel (by the cpsw_default pinmux node attached to the ethernet@4a100000 device), while

eth mii tx en                     69 fast    down 2 rgmii 0 txctl    

would mean the pin is not currently claimed by any device, even though it has been muxed to rgmii (either by u-boot or by the kernel for a device whose probe has subsequently failed).

1 Like