We are developing an AM3352 based board with dual Gigabit Ethernet interface. The PHY chip we used are Micrel KSZ9031. The board are up and running since early March. However, we are seeing the board losing Ethernet packet sometimes, especially with Gigabit connection. After studying the data sheet, I realized I have not adjusted the skew timing.
- I understand that AM3352 needs 1.8ns delay for both TCLK and RCLK relative the data and control signals.
- KSZ9031 has 1.2ns built-in for RCLK. So I only needs to 0.6ns.
After studying the KSZ9031 data sheet and micrel PHY driver in the Linux kernel, I came up with the following setup in device tree:
&davinci_mdio { pinctrl-names = "default", "sleep"; pinctrl-0 = <&davinci_mdio_default>; pinctrl-1 = <&davinci_mdio_sleep>; phy0: ethernet-phy@0 { comptaible = "micrel,ksz9031"; device_type = "ethernet-phy"; rxc-skew-ps = <1500>; rxdv-skew-ps = <420>; rxd0-skew-ps = <420>; rxd1-skew-ps = <420>; rxd2-skew-ps = <420>; rxd3-skew-ps = <420>; txc-skew-ps = <1860>; txen-skew-ps = <0>; txd0-skew-ps = <0>; txd1-skew-ps = <0>; txd2-skew-ps = <0>; txd3-skew-ps = <0>; reg = <0>; }; phy2: ethernet-phy@2 { comptaible = "micrel,ksz9031"; device_type = "ethernet-phy"; rxc-skew-ps = <1500>; rxdv-skew-ps = <420>; rxd0-skew-ps = <420>; rxd1-skew-ps = <420>; rxd2-skew-ps = <420>; rxd3-skew-ps = <420>; txc-skew-ps = <1860>; txen-skew-ps = <60>; txd0-skew-ps = <60>; txd1-skew-ps = <60>; txd2-skew-ps = <60>; txd3-skew-ps = <60>; reg = <2>; }; };
I even dumps out the device tree from the U-Boot:
mdio@4a101000 { compatible = "ti,davinci_mdio"; #address-cells = <0x00000001>; #size-cells = <0x00000000>; ti,hwmods = "davinci_mdio"; clocks = <0x00000035>; clock-names = "fck"; bus_freq = <0x000f4240>; reg = <0x4a101000 0x00000100>; pinctrl-names = "default", "sleep"; pinctrl-0 = <0x00000039>; pinctrl-1 = <0x0000003a>; linux,phandle = <0x0000003b>; phandle = <0x0000003b>; ethernet-phy@0 { comptaible = "micrel,ksz9031"; device_type = "ethernet-phy"; rxc-skew-ps = <0x000005dc>; rxdv-skew-ps = <0x000001a4>; rxd0-skew-ps = <0x000001a4>; rxd1-skew-ps = <0x000001a4>; rxd2-skew-ps = <0x000001a4>; rxd3-skew-ps = <0x000001a4>; txc-skew-ps = <0x00000744>; txen-skew-ps = <0x00000000>; txd0-skew-ps = <0x00000000>; txd1-skew-ps = <0x00000000>; txd2-skew-ps = <0x00000000>; txd3-skew-ps = <0x00000000>; reg = <0x00000000>; linux,phandle = <0x0000003c>; phandle = <0x0000003c>; }; ethernet-phy@2 { comptaible = "micrel,ksz9031"; device_type = "ethernet-phy"; rxc-skew-ps = <0x000005dc>; rxdv-skew-ps = <0x000001a4>; rxd0-skew-ps = <0x000001a4>; rxd1-skew-ps = <0x000001a4>; rxd2-skew-ps = <0x000001a4>; rxd3-skew-ps = <0x000001a4>; txc-skew-ps = <0x00000744>; txen-skew-ps = <0x0000003c>; txd0-skew-ps = <0x0000003c>; txd1-skew-ps = <0x0000003c>; txd2-skew-ps = <0x0000003c>; txd3-skew-ps = <0x0000003c>; reg = <0x00000002>; linux,phandle = <0x0000003d>; phandle = <0x0000003d>; }; };
However, the skew values are not loaded into the registers. I know this because I have added debug line in the micrel.c
static int ksz9031_of_load_skew_values(struct phy_device *phydev, struct device_node *of_node, u16 reg, size_t field_sz, char *field[], u8 numfields) { int val[4] = {-1, -2, -3, -4}; int matches = 0; u16 mask; u16 maxval; u16 newval; int i; pr_info("ksz9031_of_load_skew_values: %x\n", reg); for (i = 0; i < numfields; i++) { pr_info("Field: %s\n", field[i]); if (!of_property_read_u32(of_node, field[i], val + i)) matches++; } pr_info("ksz9031_of_load_skew_values: matches %d\n", matches); if (!matches) return 0; if (matches < numfields) newval = ksz9031_extended_read(phydev, OP_DATA, 2, reg); else newval = 0; maxval = (field_sz == 4) ? 0xf : 0x1f; for (i = 0; i < numfields; i++) if (val[i] != -(i + 1)) { mask = 0xffff; mask ^= maxval << (field_sz * i); newval = (newval & mask) | (((val[i] / KSZ9031_PS_TO_REG) & maxval) << (field_sz * i)); } pr_info("ksz9031 reg: %x newval: %x\n", reg, newval); return ksz9031_extended_write(phydev, OP_DATA, 2, reg, newval); }
And the console output is the following:
[ 7.409110] ksz9031_config_init [ 7.412221] ksz9031_of_load_skew_values: 8 [ 7.416696] Field: rxc-skew-ps [ 7.419916] Field: txc-skew-ps [ 7.423114] ksz9031_of_load_skew_values: matches 0 [ 7.428224] ksz9031_of_load_skew_values: 4 [ 7.432523] Field: txen-skew-ps [ 7.435811] Field: rxdv-skew-ps [ 7.439107] ksz9031_of_load_skew_values: matches 0 [ 7.444217] ksz9031_of_load_skew_values: 5 [ 7.448530] Field: rxd0-skew-ps [ 7.451818] Field: rxd1-skew-ps [ 7.455105] Field: rxd2-skew-ps [ 7.458404] Field: rxd3-skew-ps [ 7.461692] ksz9031_of_load_skew_values: matches 0 [ 7.466802] ksz9031_of_load_skew_values: 6 [ 7.471099] Field: txd0-skew-ps [ 7.474387] Field: txd1-skew-ps [ 7.477675] Field: txd2-skew-ps [ 7.480970] Field: txd3-skew-ps [ 7.484258] ksz9031_of_load_skew_values: matches 0 [ 7.489383] net eth1: phy found : id is : 0x221622 udhcpc (v1.23.2) started Sending discover... [ 9.489221] libphy: 4a101000.mdio:02 - Link is Up - 1000/Full Sending discover... Sending select for 10.200.176.180... Lease of 10.200.176.180 obtained, lease time 43200 /etc/udhcpc.d/50default: Adding DNS 10.200.176.10 /etc/udhcpc.d/50default: Adding DNS 209.18.47.61 [ 10.789007] net eth0: initializing cpsw version 1.12 (0) [ 10.796999] ksz9031_config_init [ 10.800149] ksz9031_of_load_skew_values: 8 [ 10.804625] Field: rxc-skew-ps [ 10.807826] Field: txc-skew-ps [ 10.811035] ksz9031_of_load_skew_values: matches 0 [ 10.816145] ksz9031_of_load_skew_values: 4 [ 10.820444] Field: txen-skew-ps [ 10.823732] Field: rxdv-skew-ps [ 10.827018] ksz9031_of_load_skew_values: matches 0 [ 10.832136] ksz9031_of_load_skew_values: 5 [ 10.836425] Field: rxd0-skew-ps [ 10.839722] Field: rxd1-skew-ps [ 10.843010] Field: rxd2-skew-ps [ 10.846298] Field: rxd3-skew-ps [ 10.849592] ksz9031_of_load_skew_values: matches 0 [ 10.854702] ksz9031_of_load_skew_values: 6 [ 10.858999] Field: txd0-skew-ps [ 10.862286] Field: txd1-skew-ps [ 10.865573] Field: txd2-skew-ps [ 10.868869] Field: txd3-skew-ps [ 10.872157] ksz9031_of_load_skew_values: matches 0
Am I binding to the wrong node in the device tree? Your help are greatly appreciated.