Limit Ethernet to 100MBits

      Limit Ethernet to 100MBits

      We use the efusA9 as a replacement for an old CPU board. For ethernet we use an RJ45 connector which only supports 100Mbits (4 wires).
      As the efusA9 supports 1GBits I don't know what will happen if we use a 1Gbit switch (we only have 1Gbit network). How can we limit
      the device to only use 100MBit?
      We also want to use only 4 wires with a legacy device. With the actual BSP this doesn't work with a 1 Gbit network because the auto negotiation for ETH leads to an attempt to establish a 1 Gbit connection (8 wires needed). (As workaround you can connect via a 100 Mbit router.)

      F&S announces the 100MBit support in its roadmap of Windows CE for Version 1.90:
      - 0002778: [Ethernet] Add possibility to limit transfer speed to 100MBit - new

      You can check with F&S if they can provide the same functionality for Linux.

      Post was edited 1 time, last by “Steffen” ().

      In arch/arm/mach-mx6/board-mx6_efusa9.c, look for function mx6_fec_phy_init(). Add the following lines at the end of the function (before the return 0):

      Source Code

      1. /* Reduce speed to 100MHz */
      2. val = phy_read(phydev, 0x9);
      3. val &= ~0x0300;
      4. phy_write(phydev, 0x9, val);


      Then recompile the kernel.

      This modification clears the bits in the PHY register that advertise the 1000MBit connection during auto negotiation.

      If you also need this modification in U-Boot, you can modify this setting at runtime. Issue the following commands before doing any network transfers.

      Source Code

      1. mdio write FEC 9 0
      2. mdio write FEC 0 3300
      3. sleep 1

      The first command clears again the advertise-bits. The second restarts auto negotiation. The third waits until negotiation is complete. I'm not sure if the sleep is necessary, you can also try without.

      Your F&S Support Team
      F&S Elektronik Systeme GmbH
      As this is an international forum, please try to post in English.
      Da dies ein internationales Forum ist, bitten wir darum, Beiträge möglichst in Englisch zu verfassen.

      Post was edited 2 times, last by “fs-support_HK” ().

      I applied the kernel patch and tested it. Nothing changed.... link speed is still 1000MBit.


      PHY: 1:04 - Link is Up - 1000/Full
      ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready

      I didn't change the rate in u-boot.....

      Any ideas?

      I also see a different in U-Boot and C example:
      val &= ~0x0300; vs
      dio write FEC 0 3300

      Please look again. In Linux, we are modifying register 9. And in U-Boot, we write 0 to register 9, so we also clear the appropriate bits. In fact only one of these two bits is active in register 9, so clearing it results in value 0, which is what we write to this register in U-Boot.

      The value 3300 written to register 0 triggers the auto-negotiation again. Without this, the 1000 MBit/s remains active.

      Maybe this is the reason why your Linux link also shows the high rate. You have to start the link in Linux anew. I'm not sure what happens if the link remains active from U-Boot to Linux. So either keep network off and only start it in Linux, or toggle your network DOWN and UP again.

      And are you really sure that the setting is active? You can add a printk() message to the above settings. If you see the message at runtime, it should work. If not, then you are doing something wrong when compiling or downloading the new kernel to your board.

      Your F&S Support Team
      F&S Elektronik Systeme GmbH
      As this is an international forum, please try to post in English.
      Da dies ein internationales Forum ist, bitten wir darum, Beiträge möglichst in Englisch zu verfassen.
      This is the code which is used...

      Source Code

      1. /* introduce tx clock delay */
      2. phy_write(phydev, 0x1d, 0x5);
      3. val = phy_read(phydev, 0x1e);
      4. val |= 0x0100;
      5. phy_write(phydev, 0x1e, val);
      6. /* Reduce speed to 100MBits */
      7. printk("Limit ethernet to 100MBits");
      8. val = phy_read(phydev, 0x9);
      9. val &= ~0x0300;
      10. phy_write(phydev, 0x9, val);
      11. return 0;


      Kernel output.... check first line and last lines

      Source Code

      1. Jan 1 00:00:09 telemax user.warn kernel: Limit ethernet to 100MBits
      2. Jan 1 00:00:09 telemax user.info kernel: ADDRCONF(NETDEV_UP): eth0: link is not ready
      3. Jan 1 00:00:09 telemax user.info kernel: hub 2-1:1.0: USB hub found
      4. Jan 1 00:00:09 telemax user.info kernel: hub 2-1:1.0: 4 ports detected
      5. Jan 1 00:00:09 telemax user.debug kernel: USB Host suspend begins
      6. Jan 1 00:00:09 telemax user.debug kernel: will suspend roothub and its children
      7. Jan 1 00:00:09 telemax user.debug kernel: ehci_fsl_bus_suspend begins, DR
      8. Jan 1 00:00:09 telemax user.debug kernel: ehci_fsl_bus_suspend ends, DR
      9. Jan 1 00:00:09 telemax user.debug kernel: host suspend ends
      10. Jan 1 00:00:09 telemax user.debug kernel: ehci_fsl_bus_suspend begins, Host 1
      11. Jan 1 00:00:09 telemax user.debug kernel: ehci_fsl_bus_suspend ends, Host 1
      12. Jan 1 00:00:09 telemax user.info kernel: PHY: 1:04 - Link is Up - 1000/Full
      13. Jan 1 00:00:09 telemax user.info kernel: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready


      Limiting the speed in U-Boot works as you suggested. But as soon as the kernel is started it switches back to 1GBits.

      Post was edited 1 time, last by “telerob” ().

      How do you start the network? Have you added an additional package like NetworkManager?

      Are you already on fsimx6-V2.1 or still on V2.0?

      Your F&S Support Team
      F&S Elektronik Systeme GmbH
      As this is an international forum, please try to post in English.
      Da dies ein internationales Forum ist, bitten wir darum, Beiträge möglichst in Englisch zu verfassen.
      I use fsimx6-V2.1 we also added some packages based on the minimal configuration.

      Network is initialized over the /etc/network/interfaces.conf:

      Source Code

      1. # interface file auto-generated by buildroot
      2. auto lo
      3. iface lo inet loopback
      4. auto eth0
      5. iface eth0 inet static
      6. address 192.168.25.77
      7. netmask 255.255.254.0
      8. auto can0
      9. iface can0 inet manual
      10. up /sbin/ip link set $IFACE down
      11. up /sbin/ip link set $IFACE up txqueuelen 1000 type can bitrate 1000000 sample-point 0.7 triple-sampling off restart-ms 500
      12. auto can1
      13. iface can1 inet manual
      14. up /sbin/ip link set $IFACE down
      15. up /sbin/ip link set $IFACE up txqueuelen 1000 type can bitrate 1000000 sample-point 0.7 triple-sampling off restart-ms 500


      This is my buildroot configuration:

      Source Code

      1. BR2_arm=y
      2. BR2_cortex_a9=y
      3. BR2_ARM_EABIHF=y
      4. BR2_ARM_ENABLE_NEON=y
      5. BR2_CCACHE=y
      6. BR2_TOOLCHAIN_EXTERNAL=y
      7. BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y
      8. BR2_TOOLCHAIN_EXTERNAL_PATH="/usr/local/arm/fs-toolchain-4.7.2-cortexa5-neonvfpv4"
      9. BR2_TOOLCHAIN_EXTERNAL_HEADERS_3_3=y
      10. BR2_TOOLCHAIN_EXTERNAL_CUSTOM_GLIBC=y
      11. BR2_TOOLCHAIN_EXTERNAL_CXX=y
      12. BR2_TOOLCHAIN_EXTERNAL_GDB_SERVER_COPY=y
      13. BR2_ENABLE_LOCALE_PURGE=y
      14. BR2_TARGET_OPTIMIZATION="-pipe -march=armv7-a"
      15. BR2_ECLIPSE_REGISTER=y
      16. BR2_TARGET_GENERIC_HOSTNAME="telemax"
      17. BR2_TARGET_GENERIC_ISSUE="Welcome to teleworld"
      18. BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
      19. BR2_ROOTFS_DEVICE_TABLE=""
      20. BR2_TARGET_GENERIC_GETTY_PORT="ttymxc1"
      21. # BR2_TARGET_GENERIC_REMOUNT_ROOTFS_RW is not set
      22. BR2_ROOTFS_OVERLAY="$(TOPDIR)/board/telerob/fsimx6/overlay"
      23. BR2_ROOTFS_POST_BUILD_SCRIPT="$(TOPDIR)/board/telerob/fsimx6/final_script_min"
      24. BR2_LINUX_KERNEL=y
      25. BR2_LINUX_KERNEL_LOCAL_DIR=y
      26. BR2_LINUX_KERNEL_CUSTOM_DIR_LOCATION="$(TOPDIR)/../linux-fsimx6"
      27. BR2_LINUX_KERNEL_DEFCONFIG="fsimx6"
      28. BR2_LINUX_KERNEL_PATCH="board/telerob/fsimx6/linux-limit100Mbit.patch"
      29. BR2_PACKAGE_BUSYBOX_CONFIG="board/telerob/common/busybox-1.23.x.config"
      30. BR2_PACKAGE_LINUX_FIRMWARE=y
      31. BR2_PACKAGE_LINUX_FIRMWARE_TI_WL127X=y
      32. BR2_PACKAGE_IPROUTE2=y
      33. BR2_TARGET_ROOTFS_EXT2=y
      34. BR2_TARGET_ROOTFS_EXT2_4=y
      35. # BR2_TARGET_ROOTFS_TAR is not set
      36. BR2_TARGET_ROOTFS_UBIFS=y
      37. BR2_TARGET_ROOTFS_UBIFS_LEBSIZE=0x1f000
      38. BR2_PACKAGE_AVAHI=y
      39. BR2_PACKAGE_AVAHI_AUTOIPD=y
      40. BR2_PACKAGE_AVAHI_DAEMON=y
      41. BR2_PACKAGE_CAN_UTILS=y
      42. BR2_PACKAGE_LIGHTTPD=y
      43. BR2_PACKAGE_OPENSSH=y
      44. BR2_PACKAGE_PYTHON3=y
      45. BR2_PACKAGE_PYTHON3_PYC_ONLY=y
      46. BR2_PACKAGE_PYTHON3_UNICODEDATA=y
      47. BR2_PACKAGE_PURE_FTPD=y
      48. #BR2_PACKAGE_LINUX_PAM=y
      I don't have any deep knowledge of the kernel but after some code research I found the following lines in drivers/net/fec.c:

      Source Code

      1. /* mask with MAC supported features */
      2. if (cpu_is_mx6q() || cpu_is_mx6dl())
      3. phy_dev->supported &= PHY_BASIC_FEATURES;
      4. else
      5. phy_dev->supported &= PHY_BASIC_FEATURES;


      I changed it to:

      Source Code

      1. /* mask with MAC supported features */
      2. if (cpu_is_mx6q() || cpu_is_mx6dl())
      3. //phy_dev->supported &= PHY_GBIT_FEATURES;
      4. phy_dev->supported &= PHY_BASIC_FEATURES;
      5. else
      6. phy_dev->supported &= PHY_BASIC_FEATURES;


      As I can see ethernet is now running on 100MBits. I don't think that this is a "good" solution so maybe you have a better idea.
      [Update]
      Both patches must be applied, if not, network is running on 100MBit but it has many RX errors and no connection can be established.

      Post was edited 1 time, last by “HWeber” ().

      On device trees, there is already a feature to limit the transfer speed. Unfortunately this is part of the PHY which is not explicitly defined in our default device tree yet. Please try to modify the fec node in arch/arm/boot/dts/efusa9qdl.dtsi as follows. Then recompile the dtb file and download it to the board.

      Source Code

      1. &fec {
      2. pinctrl-names = "default";
      3. pinctrl-0 = <&pinctrl_enet>;
      4. phy-mode = "rgmii";
      5. phy-handle = <&ethphy>;
      6. status = "okay";
      7. mdio {
      8. #address-cells = <1>;
      9. #size-cells = <0>;
      10. ethphy: ethernet-phy@4 {
      11. compatible = "ethernet-phy-ieee802.3-c22";
      12. reg = <4>;
      13. max-speed = <100>;
      14. };
      15. };
      16. };


      I haven't tested it though. So can you please give some feedback whether this works or not? Thanks.

      Your F&S Support Team
      F&S Elektronik Systeme GmbH
      As this is an international forum, please try to post in English.
      Da dies ein internationales Forum ist, bitten wir darum, Beiträge möglichst in Englisch zu verfassen.