This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Linux/AM4378: u-boot not running DHCP, ethernet in half duplex mode

Mastermind 7315 points

Replies: 31

Views: 1452

Part Number: AM4378

Tool/software: Linux


Linux host ubuntu 16.04


U-Boot 2017.01-00458-gccd1c34

custom board loosely based on the am4378 gp evm

we've had some issues getting the board to come up but we did finally get u-boot to start and run. now i am trying to get dhcp to happen and it isn't.


our u-boot environment output is:

=> pr
args_mmc=run finduuid;setenv bootargs console=${console} ${optargs} root=PARTUU}
bootcmd=run findfdt; run getuenv; setenv autoload no;dhcp ;tftp ${loadaddr} zIm}
bootscript=echo Running bootscript from mmc${mmcdev} ...; source ${loadaddr}
dfu_alt_info_emmc=rawemmc raw 0 3751936;boot part 1 1;rootfs part 1 2;MLO fat 11
dfu_alt_info_mmc=boot part 0 1;rootfs part 0 2;MLO fat 0 1;MLO.raw raw 0x100 0x1
dfu_alt_info_qspi=u-boot.bin raw 0x0 0x080000;u-boot.backup raw 0x080000 0x08000
dfu_alt_info_ram=kernel ram 0x80200000 0x4000000;fdt ram 0x80f80000 0x80000;ram0
envboot=mmc dev ${mmcdev}; if mmc rescan; then echo SD/MMC found on device ${mm;
finduuid=part uuid mmc ${bootpart} uuid
getuenv=setenv devnum ${mmcdev}; if mmc rescan; then if run loadbootenv; then r;
importbootenv=echo Importing environment from mmc${mmcdev} ...; env import -t $}
loadbootenv=fatload mmc ${mmcdev} ${loadaddr} ${bootenvfile}
loadbootscript=load mmc ${mmcdev} ${loadaddr} boot.scr
loadfdt=load ${devtype} ${bootpart} ${fdtaddr} ${bootdir}/${fdtfile}
loadfit=run args_mmc; bootm ${loadaddr}#${fdtfile};
loadimage=load ${devtype} ${bootpart} ${loadaddr} ${bootdir}/${bootfile}
loadramdisk=load ${devtype} ${devnum} ${rdaddr} ramdisk.gz
mmcboot=mmc dev ${mmcdev}; setenv devnum ${mmcdev}; setenv devtype mmc; if mmc ;
mmcloados=run args_mmc; if test ${boot_fdt} = yes || test ${boot_fdt} = try; th;
mmcrootfstype=ext4 rootwait
nandargs=setenv bootargs console=${console} ${optargs} root=${nandroot} rootfst}
nandboot=echo Booting from nand ...; run nandargs; nand read ${fdtaddr} NAND.u-}
nandroot=ubi0:rootfs rw ubi.mtd=NAND.file-system,4096
nandrootfstype=ubifs rootwait=1
netargs=setenv bootargs console=${console} ${optargs} root=/dev/nfs nfsroot=${sp
netboot=echo Booting from network ...; setenv autoload no; dhcp; run netloadima}
netloadfdt=tftp ${fdtaddr} ${fdtfile}
netloadimage=tftp ${loadaddr} ${bootfile}
ramargs=setenv bootargs console=${console} ${optargs} root=${ramroot} rootfstyp}
ramroot=/dev/ram0 rw
update_to_fit=setenv loadaddr ${fit_loadaddr}; setenv bootfile ${fit_bootfile}
usbargs=setenv bootargs console=${console} ${optargs} root=${usbroot} rootfstyp}
usbboot=setenv devnum ${usbdev}; setenv devtype usb; usb start ${usbdev}; if usi
usbroot=/dev/sda2 rw
usbrootfstype=ext4 rootwait
ver=U-Boot 2017.01-00458-gccd1c34-dirty (Apr 03 2019 - 16:17:58 -0500)

Environment size: 5662/65532 bytes


the pinmux for mii1 is:

static struct module_pin_mux mii1_pin_mux[] = {
{OFFSET(mii1_txen), MODE(0)}, /* MII1_TCTL */
{OFFSET(mii1_rxdv), MODE(0) | RXACTIVE}, /* MII1_RCTL */
{OFFSET(mii1_txd3), MODE(0)}, /* MII1_TD3 */
{OFFSET(mii1_txd2), MODE(0)}, /* MII1_TD2 */
{OFFSET(mii1_txd1), MODE(0)}, /* MII1_TD1 */
{OFFSET(mii1_txd0), MODE(0)}, /* MII1_TD0 */
{OFFSET(mii1_txclk), MODE(0)}, /* MII1_TCLK */
{OFFSET(mii1_rxclk), MODE(0) | RXACTIVE}, /* MII1_RCLK */
{OFFSET(mii1_rxd3), MODE(0) | RXACTIVE}, /* MII1_RD3 */
{OFFSET(mii1_rxd2), MODE(0) | RXACTIVE}, /* MII1_RD2 */
{OFFSET(mii1_rxd1), MODE(0) | RXACTIVE}, /* MII1_RD1 */
{OFFSET(mii1_rxd0), MODE(0) | RXACTIVE}, /* MII1_RD0 */
{OFFSET(mii1_col), MODE(0) | RXACTIVE}, /* MII1_COL */
{OFFSET(mii1_crs), MODE(0) | RXACTIVE}, /* MII1_CRS */
{OFFSET(mii1_rxerr), MODE(0) | RXACTIVE}, /* MII1_RXERR */


the ethernet setup in the board.c looks like:

#if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) || \
static void cpsw_control(int enabled)
/* Additional controls can be added here */

static struct cpsw_slave_data cpsw_slaves[] = {
.slave_reg_ofs = 0x208,
.sliver_reg_ofs = 0xd80,
.phy_addr = 16,
.slave_reg_ofs = 0x308,
.sliver_reg_ofs = 0xdc0,
.phy_addr = 1,

static struct cpsw_platform_data cpsw_data = {
.mdio_base = CPSW_MDIO_BASE,
.cpsw_base = CPSW_BASE,
.mdio_div = 0xff,
.channels = 8,
.cpdma_reg_ofs = 0x800,
.slaves = 1,
.slave_data = cpsw_slaves,
.ale_reg_ofs = 0xd00,
.ale_entries = 1024,
.host_port_reg_ofs = 0x108,
.hw_stats_reg_ofs = 0x900,
.bd_ram_ofs = 0x2000,
.mac_control = (1 << 5),
.control = cpsw_control,
.host_port_num = 0,
.version = CPSW_CTRL_VERSION_2,

* This function will:
* Read the eFuse for MAC addresses, and set ethaddr/eth1addr/usbnet_devaddr
* in the environment
* Perform fixups to the PHY present on certain boards. We only need this
* function in:
* - SPL with either CPSW or USB ethernet support
* - Full U-Boot, with either CPSW or USB ethernet
* Build in only these cases to avoid warnings about unused variables
* when we build an SPL that has neither option but full U-Boot will.
#if ((defined(CONFIG_SPL_ETH_SUPPORT) || \
defined(CONFIG_SPL_BUILD)) || \
((defined(CONFIG_DRIVER_TI_CPSW) || \
defined(CONFIG_USB_ETHER)) && !defined(CONFIG_SPL_BUILD))
int board_eth_init(bd_t *bis)
int rv;
uint8_t mac_addr[6];
uint32_t mac_hi, mac_lo;

/* try reading mac address from efuse */
mac_lo = readl(&cdev->macid0l);
mac_hi = readl(&cdev->macid0h);
mac_addr[0] = mac_hi & 0xFF;
mac_addr[1] = (mac_hi & 0xFF00) >> 8;
mac_addr[2] = (mac_hi & 0xFF0000) >> 16;
mac_addr[3] = (mac_hi & 0xFF000000) >> 24;
mac_addr[4] = mac_lo & 0xFF;
mac_addr[5] = (mac_lo & 0xFF00) >> 8;

printf("Mac Addr = %x:%x:%x:%x:%x:%x\n", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);

#if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) || \
if (!getenv("ethaddr")) {
puts("<ethaddr> not set. Validating first E-fuse MAC\n");
if (is_valid_ethaddr(mac_addr))
eth_setenv_enetaddr("ethaddr", mac_addr);

mac_lo = readl(&cdev->macid1l);
mac_hi = readl(&cdev->macid1h);
mac_addr[0] = mac_hi & 0xFF;
mac_addr[1] = (mac_hi & 0xFF00) >> 8;
mac_addr[2] = (mac_hi & 0xFF0000) >> 16;
mac_addr[3] = (mac_hi & 0xFF000000) >> 24;
mac_addr[4] = mac_lo & 0xFF;
mac_addr[5] = (mac_lo & 0xFF00) >> 8;

if (!getenv("eth1addr")) {
if (is_valid_ethaddr(mac_addr))
eth_setenv_enetaddr("eth1addr", mac_addr);
writel(MII_MODE_ENABLE, &cdev->miisel);
cpsw_slaves[0].phy_if = PHY_INTERFACE_MODE_MII;
cpsw_slaves[0].phy_addr = 1;

rv = cpsw_register(&cpsw_data);
if (rv < 0) {
printf("Error %d registering CPSW switch\n", rv);
return rv;

return rv;


the output of the u-boot when trying to dhcp is:

U-Boot SPL 2017.01-00458-gccd1c34-dirty (Apr 03 2019 - 16:17:58)
Trying to boot from MMC1
SPL: Please implement spl_start_uboot() for your board
SPL: Direct Linux boot not active!
reading u-boot.img
reading u-boot.img
reading u-boot.img
reading u-boot.img

U-Boot 2017.01-00458-gccd1c34-dirty (Apr 03 2019 - 16:17:58 -0500)

CPU : AM437X-GP rev 1.2
Model: TI AM437x UTI BOARD
DRAM: 512 MiB
Pinmux for MII1_COL: 40000
Board Init
Power Init
PMIC: TPS65218
reading uboot.env
Board late Init
Processes Called: 0
Net: Mac Addr = f0:b5:d1:3e:83:62
Hit any key to stop autoboot: 0
## Error: "findfdt" not defined
reading uEnv.txt
717 bytes read in 4 ms (174.8 KiB/s)
Importing environment from mmc0 ...
link up on port 0, speed 100, full duplex
BOOTP broadcast 1
BOOTP broadcast 2
BOOTP broadcast 3
BOOTP broadcast 4
BOOTP broadcast 5
BOOTP broadcast 6
BOOTP broadcast 7
BOOTP broadcast 8
BOOTP broadcast 9
BOOTP broadcast 10
BOOTP broadcast 11
BOOTP broadcast 12
BOOTP broadcast 13
BOOTP broadcast 14
BOOTP broadcast 15
BOOTP broadcast 16
BOOTP broadcast 17
BOOTP broadcast 18
BOOTP broadcast 19
BOOTP broadcast 20
BOOTP broadcast 21
BOOTP broadcast 22
BOOTP broadcast 23
BOOTP broadcast 24
BOOTP broadcast 25
BOOTP broadcast 26
BOOTP broadcast 27
BOOTP broadcast 28
BOOTP broadcast 29

Retry time exceeded; starting again
link up on port 0, speed 100, full duplex
*** ERROR: `ipaddr' not set
link up on port 0, speed 100, full duplex
*** ERROR: `ipaddr' not set

when i wireshark the line there are no DHCP packets present

the PHY reset is high so it is not in reset

where else do i look to fix this?

31 Replies

  • In reply to cobsonchael:

    sorry for the spam

    now that i can get to the command line, when i run ifconfig i get this output:
    root@am437x-evm:/sys/class/gpio/gpio86# ifconfig
    eth0 Link encap:Ethernet HWaddr F0:B5:D1:3E:99:88
    RX packets:0 errors:0 dropped:0 overruns:0 frame:0
    TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:1000
    RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

    lo Link encap:Local Loopback
    inet addr: Mask:
    inet6 addr: ::1%763860/128 Scope:Host
    UP LOOPBACK RUNNING MTU:65536 Metric:1
    RX packets:9760 errors:0 dropped:0 overruns:0 frame:0
    TX packets:9760 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:1
    RX bytes:741760 (724.3 KiB) TX bytes:741760 (724.3 KiB)

    it looks like we are in loopback mode. how does that happen?
  • In reply to cobsonchael:


    Since you running in a Linux context there are some basic link checkout steps that can be used, could you please look at this link for doing basic ethernet triage. I would like to add to please attach the results to post and not cut and paste them into the thread window. We are asking for a lot data.

    The checklist is asking to you use some linux tools to make sure that there is a link partner, the hardware stats of the MAC and asking to attach the dts board file or at least the portion involving the pin mux and nodes used for network definition. Also please attach any dtsi files that were modified. Some of these steps or results will look the same as what has already been established during the u-boot debug you were doing. The boot log is also requested to be attached and we to see the entire boot log from power on.

    We still need to see if you are seeing the same no packets out of the MAC. 

    Best Regards,


  • In reply to Schuyler Patton:

    well part of my problem with doing it in linux is this:

    we have the ethernet PHY reset on a gpio line. in u-boot in board.c i take the PHY out of reset. when linux loads it appears to put the PHy back into reset. i only know this because 1) the PHY LED is off when the kernel loads and 2)the kernel can't find the PHY but u-boot can.

    i thought that if i took it out of reset in u-boot that the kernel wouldn't touch it but apparently it does. what can i do about this?
  • In reply to cobsonchael:


    Linux has a means to control the PHY reset line via a DTS property value for either the MDIO or MAC node. I want to confirm though that the PHY reset in the board design is intended to be handled via the network drivers, is that the case? The DTS binding docs for the mdio and MAC nodes cover this, but I will confirm after I hear back from you.

    Best Regards,
  • In reply to Schuyler Patton:

    our board designer connected a GPIO to the PHY reset. i don't have anywhere in the DTS file that tells the system that this is the reset line for the PHY since i don't know how to do that (what field exists? which module is it included in? i'm not an expert here). i am currently writing directly to the GPIO registers to handle the reset and that it working for u-boot but not for the kernel

    if you could fill me in on the DTS propertly value for the reset that would be great.

    i have tried phy_id = <&davinci_mdio>, <0>; and phy_id = <&davinci_mdio>, <1>; and it doesn't make a difference (assuming the <#> is the phy address)

    my ethernet portion of my DTS looks just like the EVM:

    &mac {
    slaves = <1>;
    pinctrl-names = "default", "sleep";
    pinctrl-0 = <&mii_1_pins_default>;
    pinctrl-1 = <&mii_1_pins_sleep>;
    status = "okay";

    &davinci_mdio {
    pinctrl-names = "default", "sleep";
    pinctrl-0 = <&mdio_1_pins_default>;
    pinctrl-1 = <&mdio_1_pins_sleep>;
    status = "okay";

    &cpsw_emac0 {
    phy_id = <&davinci_mdio>, <0>;
    phy-mode = "mii";
  • In reply to cobsonchael:

    so her's the update

    I added ti,no-reset-on-init; to the gpio bank that performed the PHY reset and i changed to phy_id = <&davinci_mdio>, <1>; and when linux boots i get an address and i have internet access. however when i do "dhcp" from u-boot i still get nothing but BOOTP. in addition when i do get to the kernel i cannot do DNS. every single time i have to give the command "udhcpc" and then i am able to access DNS. i got this trick from this post:

    does u-boot just not work with my phy? it is because i am at phy address 1 and not 0?

  • In reply to cobsonchael:


    Using the ti, no-reset-on-init will work if the PHY is getting reset in U-Boot. It is important that the PHY is reset for certain amount of time. Are you exercising the reset line in U-Boot?

    The example I was thinking of would be found in arch/arm/boot/dts/am572x-idk.dts, this particular example is for the AM572x processors that are on the PRUs. In the pruss2_mdio node are two properties reset-gpios and reset-delay-us.

    To understand the first property you will need to look at the AM572x schematic to see the GPIOs selected to act as a reset to the PHY. Link to AM572x product page. The schematic is under the design files area.

    The second property refers to how the to how long of a reset pulse is needed. Please refer to Docmentation/devicetree/bindings/net/mdio.txt for details on these two properties.

    If you are able to get an address with an address of 1 for the PHY then this same address should work for U-Boot. The DHCP process should happen automatically too. Which file system are you using? The TI one? Could you attach the boot log?

    I will be out of the office this week and return on the 29th.

    Best Regards,
  • In reply to Schuyler Patton:

    i see:

    &pruss2_mdio {

    reset-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>,

         <&gpio5 9 GPIO_ACTIVE_LOW>;

    reset-delay-us = <2>; /* PHY datasheet states 1uS min */


    following this example i was able to get linux to reset the phy, but u-boot did not take the phy out of reset (i removed my reset code from u-boot as i thought the addition of the reset code in the DTS file would do it for me). it would appear the dts file for the reset pin works in the kernel but nto u-boot

    i do know the importance of reset lines, and timing. this isn't my first board, it's just my first linux board

    we are using TI everything.

    here is the whole boot log:


  • In reply to cobsonchael:


    Something went wrong with the attached boot log, the link that is shown looks to be empty. Could you please try to attach the boot log again?

    I looked in the u-boot source and I believe I see why the reset-delay-us property is not working. This property works in Linux because the MDIO driver uses it and not the CPSW driver. In U-boot there is not an MDIO driver provided. Since U-Boot's is single threaded in nature the CPSW will do anything it needs to init, start and run a network transaction. The CPSW driver has it's own functions to read the mdio bus and gets the PHY information such as the PHY address stored in platform data which is in the board.c file. The CPSW driver does not read in the reset-delay-us property since it does not have code to perform the reset.

    Best Regards,
  • In reply to Schuyler Patton:

    reattaching even though "output6.txt" worked for me when i downloaded it and opened it


    so resetting the PHY via gpio will never allow us to turn on the PHY in u-boot and we would have to do it via registers directly. is that accurate?

This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.