In SDK 2.00.01 net-booting worked perfectly. Upon migrating to SDK 3.0, we have lost this functionality. Is there additional configuration of the Ethernet hardware required to get networking support in the new u-boot?
Abbreviated U-Boot failing trace:
Net: Could not get PHY for ethernet@48484000: addr 0
Warning: ethernet@48484000 using MAC address from ROM
eth0: ethernet@48484000
...
reading uEnv.txt
1184 bytes read in 4 ms (289.1 KiB/s)
Loaded env from uEnv.txt
Importing environment from mmc0 ...
Running uenvcmd ...
Booting from network ...
BOOTP broadcast 1
BOOTP broadcast 2
BOOTP broadcast 3
...
Retry time exceeded; starting again
*** ERROR: `ipaddr' not set
*** ERROR: `ipaddr' not set
Bad Linux ARM zImage magic!
switch to partitions #0, OK
mmc0 is current device
SD/MMC found on device 0
3432672 bytes read in 196 ms (16.7 MiB/s)
89665 bytes read in 65 ms (1.3 MiB/s)
Booting from mmc0 ...
...
(Once the kernel starts it finds the hardware and initializes it)
[ 1.586930] cpsw 48484000.ethernet: Detected MACID = b4:99:4c:3f:87:55
[ 1.594116] cpsw 48484000.ethernet: cpsw: Detected MACID = b4:99:4c:64:6b:56
We are using uEnv.txt to setup our MAC addresses for eth0 and 1.
Abbreviated trace from U-Boot from 2.00.01.11 SDK:
Net: cpsw
Hit any key to stop autoboot: 0
switch to partitions #0, OK
mmc0 is current device
reading uEnv.txt
626 bytes read in 5 ms (122.1 KiB/s)
Importing environment from mmc0 ...
cpsw Waiting for PHY auto negotiation to complete......... done
link up on port 0, speed 1000, full duplex
BOOTP broadcast 1
BOOTP broadcast 2
DHCP client bound to address <address> (266 ms)
link up on port 0, speed 1000, full duplex
Using cpsw device
We are using devicetree in u-boot now to describe our hardware. The ethernet nodes are the same as our kernel devicetree, and our kernel is able to initialize the hardware. Once the system is fully started, the networking hardware is functional. Only in u-boot does it seem to be non-functional.
Relevant flattened device tree sections:
aliases {
ethernet0 = "/ocp/ethernet@48484000/slave@48480200";
ethernet1 = "/ocp/ethernet@48484000/slave@48480300";
...
ethernet@48484000 {
compatible = "ti,cpsw";
ti,hwmods = "gmac";
clocks = <0x00000022 0x000005ac>;
clock-names = "fck", "cpts";
cpdma_channels = <0x00000008>;
ale_entries = <0x00000400>;
bd_ram_size = <0x00002000>;
no_bd_ram = <0x00000000>;
rx_descs = <0x00000040>;
mac_control = <0x00000020>;
slaves = <0x00000002>;
active_slave = <0x00000000>;
cpts_clock_mult = <0x80000000>;
cpts_clock_shift = <0x0000001d>;
syscon = <0x00000004>;
reg = <0x48484000 0x00000003 0x00000003 0x00000003>;
#address-cells = <0x00000001>;
#size-cells = <0x00000001>;
interrupts = <0x00000000 0x0000014f 0x00000004 0x00000003 0x00000005 0x00000003 0x6d64696f 0x00000003 0x6176696e 0x00000004 0x00000004 0x0000000d>;
ranges;
status = "okay";
dual_emac;
mdio@48485000 {
compatible = "ti,davinci_mdio";
#address-cells = <0x00000001>;
#size-cells = <0x00000000>;
ti,hwmods = "davinci_mdio";
bus_freq = <0x000f4240>;
reg = <0x48485000 0x00000124>;
linux,phandle = <0x000000c5>;
phandle = <0x000000c5>;
};
slave@48480200 {
mac-address = [00 00 00 00 00 00];
phy_id = <0x000000c5 0x000007b2>;
phy-mode = "rgmii";
dual_emac_res_vlan = <0x00000001>;
};
slave@48480300 {
mac-address = [00 00 00 00 00 00];
phy_id = <0x000000c5 0x000007b2>;
phy-mode = "rgmii";
dual_emac_res_vlan = <0x00000002>;
};
cpsw-phy-sel@4a002554 {
compatible = "ti,dra7xx-cpsw-phy-sel";
reg = <0x4a002554 0x000002b2>;
reg-names = "gmii-sel";
};
};
From what I can tell, we are not able to find our Ethernet phy based on the address we are passing to phy_connect, should we be passing an address other than zero? If so how may I determine the correct address, and where would I add that address (devicetree?) so that it would be used by u-boot?
Relevant code from: drivers/net/phy/phy.c:
#ifdef CONFIG_DM_ETH
struct phy_device *phy_connect(struct mii_dev *bus, int addr,
struct udevice *dev, phy_interface_t interface)
#else
struct phy_device *phy_connect(struct mii_dev *bus, int addr,
struct eth_device *dev, phy_interface_t interface)
#endif
{
struct phy_device *phydev;
phydev = phy_find_by_mask(bus, 1 << addr, interface);
if (phydev)
phy_connect_dev(phydev, dev);
else
printf("Could not get PHY for %s: addr %d\n", bus->name, addr);
return phydev;
}
struct phy_device *phy_find_by_mask(struct mii_dev *bus, unsigned phy_mask,
phy_interface_t interface)
{
/* Reset the bus */
if (bus->reset) {
bus->reset(bus);
/* Wait 15ms to make sure the PHY has come out of hard reset */
udelay(15000);
}
return get_phy_device_by_mask(bus, phy_mask, interface);
}
static struct phy_device *get_phy_device_by_mask(struct mii_dev *bus,
unsigned phy_mask, phy_interface_t interface)
{
int i;
struct phy_device *phydev;
phydev = search_for_existing_phy(bus, phy_mask, interface);
if (phydev)
return phydev;
/* Try Standard (ie Clause 22) access */
/* Otherwise we have to try Clause 45 */
for (i = 0; i < 5; i++) {
phydev = create_phy_by_mask(bus, phy_mask,
i ? i : MDIO_DEVAD_NONE, interface);
if (IS_ERR(phydev))
return NULL;
if (phydev)
return phydev;
}
debug("\n%s PHY: ", bus->name);
while (phy_mask) {
int addr = ffs(phy_mask) - 1;
debug("%d ", addr);
phy_mask &= ~(1 << addr);
}
debug("not found\n");
return NULL;
}
static struct phy_device *create_phy_by_mask(struct mii_dev *bus,
unsigned phy_mask, int devad, phy_interface_t interface)
{
u32 phy_id = 0xffffffff;
while (phy_mask) {
int addr = ffs(phy_mask) - 1;
int r = get_phy_id(bus, addr, devad, &phy_id);
/* If the PHY ID is mostly f's, we didn't find anything */
if (r == 0 && (phy_id & 0x1fffffff) != 0x1fffffff)
return phy_device_create(bus, addr, phy_id, interface);
phy_mask &= ~(1 << addr);
}
return NULL;
}
Thanks for any help on this,
Weston