I am using IMX7D with AR8035 PHY in my own custom board.
Now I met one problem. When I want ping the board with PC, can transmit but can not receive any data.
the board boot log is in attachment, please give some advice.
the kernel file, DTS and mach-imx7d.c , SCHEMATIC are also in attachment.
Thanks a lot!
Original Attachment has been moved to: ar8035-kernel.rar
Now fec0 is ok if I change uboot board file.and it will not need mii info cmd any more.
The fec part in uboot file
#ifdef CONFIG_FEC_MXC
static iomux_v3_cfg_t const fec1_pads[] = {
MX7D_PAD_ENET1_RGMII_RX_CTL__ENET1_RGMII_RX_CTL | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
MX7D_PAD_ENET1_RGMII_RD0__ENET1_RGMII_RD0 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
MX7D_PAD_ENET1_RGMII_RD1__ENET1_RGMII_RD1 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
MX7D_PAD_ENET1_RGMII_RD2__ENET1_RGMII_RD2 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
MX7D_PAD_ENET1_RGMII_RD3__ENET1_RGMII_RD3 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
MX7D_PAD_ENET1_RGMII_RXC__ENET1_RGMII_RXC | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
MX7D_PAD_ENET1_RGMII_TX_CTL__ENET1_RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX7D_PAD_ENET1_RGMII_TD0__ENET1_RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX7D_PAD_ENET1_RGMII_TD1__ENET1_RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX7D_PAD_ENET1_RGMII_TD2__ENET1_RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX7D_PAD_ENET1_RGMII_TD3__ENET1_RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX7D_PAD_ENET1_RGMII_TXC__ENET1_RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX7D_PAD_GPIO1_IO10__ENET1_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL_MII),
MX7D_PAD_GPIO1_IO11__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL_MII),
};
static iomux_v3_cfg_t const fec2_pads[] = {
MX7D_PAD_EPDC_SDCE0__ENET2_RGMII_RX_CTL | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
MX7D_PAD_EPDC_SDCLK__ENET2_RGMII_RD0 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
MX7D_PAD_EPDC_SDLE__ENET2_RGMII_RD1 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
MX7D_PAD_EPDC_SDOE__ENET2_RGMII_RD2 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
MX7D_PAD_EPDC_SDSHR__ENET2_RGMII_RD3 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
MX7D_PAD_EPDC_SDCE1__ENET2_RGMII_RXC | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
MX7D_PAD_EPDC_GDRL__ENET2_RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX7D_PAD_EPDC_SDCE2__ENET2_RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX7D_PAD_EPDC_SDCE3__ENET2_RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX7D_PAD_EPDC_GDCLK__ENET2_RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX7D_PAD_EPDC_GDOE__ENET2_RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX7D_PAD_EPDC_GDSP__ENET2_RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX7D_PAD_GPIO1_IO10__ENET1_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL_MII),
MX7D_PAD_GPIO1_IO11__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL_MII),
};
static iomux_v3_cfg_t const phy1_rst_pads[] = {
/* PHY1 RST */
MX7D_PAD_ECSPI2_SS0__GPIO4_IO23 | MUX_PAD_CTRL(GPIO_PAD_CTRL),
};
static iomux_v3_cfg_t const phy2_rst_pads[] = {
/* PHY2 RST */
MX7D_PAD_EPDC_PWR_COM__GPIO2_IO30 | MUX_PAD_CTRL(GPIO_PAD_CTRL),
};
static void setup_iomux_fec(void) //
{
if (0 == CONFIG_FEC_ENET_DEV) {
imx_iomux_v3_setup_multiple_pads(fec1_pads, ARRAY_SIZE(fec1_pads));
//imx_iomux_v3_setup_multiple_pads(phy1_rst_pads, ARRAY_SIZE(phy1_rst_pads));
} else {
imx_iomux_v3_setup_multiple_pads(fec2_pads, ARRAY_SIZE(fec2_pads)); //diff with sabre
imx_iomux_v3_setup_multiple_pads(phy2_rst_pads, ARRAY_SIZE(phy2_rst_pads));
}
}
#define FEC1_RST_GPIO IMX_GPIO_NR(4, 23)
#define FEC2_RST_GPIO IMX_GPIO_NR(2, 30)
int board_eth_init(bd_t *bis)
{
int ret;
setup_iomux_fec();
ret = fecmxc_initialize_multi(bis, CONFIG_FEC_ENET_DEV,
CONFIG_FEC_MXC_PHYADDR, IMX_FEC_BASE);
if (ret)
printf("FEC1 MXC: %s:failed\n", __func__);
gpio_direction_output(FEC1_RST_GPIO, 0);
gpio_direction_output(FEC2_RST_GPIO, 0); //diff with sabre add fec rst
udelay(5000);
gpio_set_value(FEC1_RST_GPIO, 1);
gpio_set_value(FEC2_RST_GPIO, 1);
return ret;
}
static int setup_fec(int fec_id)
{
struct iomuxc_gpr_base_regs *const iomuxc_gpr_regs
= (struct iomuxc_gpr_base_regs *) IOMUXC_GPR_BASE_ADDR;
int ret;
if (0 == fec_id) {
/* Use 125M anatop REF_CLK1 for ENET1, clear gpr1[13], gpr1[17]*/
clrsetbits_le32(&iomuxc_gpr_regs->gpr[1],
(IOMUXC_GPR_GPR1_GPR_ENET1_TX_CLK_SEL_MASK |
IOMUXC_GPR_GPR1_GPR_ENET1_CLK_DIR_MASK), 0);
} else {
/* Use 125M anatop REF_CLK2 for ENET2, clear gpr1[14], gpr1[18]*/
clrsetbits_le32(&iomuxc_gpr_regs->gpr[1],
(IOMUXC_GPR_GPR1_GPR_ENET2_TX_CLK_SEL_MASK |
IOMUXC_GPR_GPR1_GPR_ENET2_CLK_DIR_MASK), 0);
}
ret = set_clk_enet(ENET_125MHz);
if (ret)
return ret;
return 0;
}
int board_phy_config(struct phy_device *phydev)
{
/* enable rgmii rxc skew and phy mode select to RGMII copper */
//phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x21);
//phy_write(phydev, MDIO_DEVAD_NONE, 0x1f, 0x7ea8);
//phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x2f);
//phy_write(phydev, MDIO_DEVAD_NONE, 0x1f, 0x71b7);
//below add for ar8035 diff with sabre
unsigned short val;
/* To enable AR8035 ouput a 125MHz clk from CLK_25M */
phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x7);
phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016);
phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007);
val = phy_read(phydev, MDIO_DEVAD_NONE, 0xe);
val &= 0xffe7;
val |= 0x18;
phy_write(phydev, MDIO_DEVAD_NONE, 0xe, val);
/* introduce tx clock delay */
phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x5);
val = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e);
val |= 0x0100;
phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, val);
if (phydev->drv->config)
phydev->drv->config(phydev);
return 0;
}
#endif
If I delete //imx_iomux_v3_setup_multiple_pads(phy1_rst_pads, ARRAY_SIZE(phy1_rst_pads));
then it will be ok. but the uboot log will send message :
What's wrong?
FEC0 dose not work in boot now and before.
The dts file is seems to be ok now.
Sugget you can use the DTS to try.
You can debug in the following API to see if the GPIO really get and reset the phy.
Also please measure by oscilloscope.
fec_main.c
static void fec_reset_phy(struct platform_device *pdev)
{
int err, phy_reset;
int msec = 1;
struct device_node *np = pdev->dev.of_node;
if (!np)
return;
err = of_property_read_u32(np, "phy-reset-duration", &msec);
/* A sane reset duration should not be longer than 1s */
if (!err && msec > 1000)
msec = 1;
phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
if (!gpio_is_valid(phy_reset))
return;
err = devm_gpio_request_one(&pdev->dev, phy_reset,
GPIOF_OUT_INIT_LOW, "phy-reset");
if (err) {
dev_err(&pdev->dev, "failed to get phy-reset-gpios: %d\n", err);
return;
}
msleep(msec);
gpio_set_value(phy_reset, 1);
}
#else /* CONFIG_OF */
static void fec_reset_phy(struct platform_device *pdev)
{
/*
* In case of platform probe, the reset has been done
* by machine code.
*/
}
I also seet the following statement in the imx7d-wiseiot.dts
&iomuxc_lpsr {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet_refclk>;
imx7d-pico-miscpins {
pinctrl_enet_refclk: enet_refclk {
see the MX7D_PAD_UART3_RX_DATA__GPIO4_IO4
fsl,pins = <
MX7D_PAD_GPIO1_IO01__CCM_ENET_REF_CLK3 0x1
pinctrl_enet1: enet1grp {
fsl,pins = <
MX7D_PAD_GPIO1_IO10__ENET1_MDIO 0x3
MX7D_PAD_GPIO1_IO11__ENET1_MDC 0x3
MX7D_PAD_UART3_RX_DATA__GPIO4_IO4 0x3
Suggest to use a clean DTS from NXP BSP to try.
I reviewed the schematic Ethernet1.pdf. For usinng ar8035 hardware design.
Please refer to the the hardware design for dual ethernet ar8031 in i.MX6SX. Please pay attention to the connections of clocks.
It should use the i.MX output for ar8035 or using ar8035 for feeding i.MX clock.
In the i.MX6SX has those options.
i.MX6SX schematic:
my dts fec1 fec2 redefine mdio mdc.
After I delet fec define,the log
loop: module loaded
CAN device driver interface
flexcan 30a10000.can: device registered (reg_base=f5a10000, irq=280)
30be0000.ethernet supply phy not found, using dummy regulator
pps pps0: new PPS source ptp0
libphy: fec_enet_mii_bus: probed
fec 30be0000.ethernet eth0: registered PHC device 0
30bf0000.ethernet supply phy not found, using dummy regulator
pps pps1: new PPS source ptp1
fec 30bf0000.ethernet (unnamed net_device) (uninitialized): Invalid MAC address: 00:00:00:00:00:00
fec 30bf0000.ethernet (unnamed net_device) (uninitialized): Using random MAC address: ba:66:c6:01:a8:ef
fec 30bf0000.ethernet eth1: registered PHC device 1
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
ehci-mxc: Freescale On-Chip EHCI Host driver
usbcore: registered new interface driver usb-storage
usbcore: registered new interface driver usb_ehset_test
30b10200.usbmisc supply vbus-wakeup not found, using dummy regulator
30b20200.usbmisc supply vbus-wakeup not found, using dummy regulator
30b30200.usbmisc supply vbus-wakeup not found, using dummy regulator
mousedev: PS/2 mouse device common for all mice
input: 30370000.snvs:snvs-powerkey as /devices/platform/soc/30000000.aips-bus/30370000.snvs/30370000.snvs:snvs-powerkey/input/input0
snvs_rtc 30370000.snvs:snvs-rtc-lp: rtc core: registered 30370000.snvs:snvs- as rtc0
Hi, Biyong Sun
I have rework the board, and set fec1 phy_id is to 2.
dts file add
First of all, in your log, the pin has confilct for eth0.
In the uboot, the clock is shared.
So please reset the phy in the kernel by gpio.
You can refer to the binding guide Documentation\devicetree\bindings\net\fsl-fec.txt
- phy-reset-gpios : Should specify the gpio for phy reset
- phy-reset-duration : Reset duration in milliseconds. Should present
The conflict in your log:
ps pps0: new PPS source ptp0
libphy: fec_enet_mii_bus: probed
fec 30be0000.ethernet eth0: registered PHC device 0
imx7d-pinctrl 30330000.iomuxc: pin MX7D_PAD_GPIO1_IO10 already requested by 30be0000.ethernet; cannot claim for 30bf0000.ethernet
imx7d-pinctrl 30330000.iomuxc: pin-7 (30bf0000.ethernet) status -22
imx7d-pinctrl 30330000.iomuxc: could not request pin 7 (MX7D_PAD_GPIO1_IO10) from group enet2grp on device 30330000.iomuxc
fec 30bf0000.ethernet: Error applying setting, reverse things back
30bf0000.ethernet supply phy not found, using dummy regulator
pps pps1: new PPS source ptp1
fec 30bf0000.ethernet (unnamed net_device) (uninitialized): Invalid MAC address: 00:00:00:00:00:00
fec 30bf0000.ethernet (unnamed net_device) (uninitialized): Using random MAC address: 52:41:37:b1:fd:f6
Hi, Biyong Sun
Thank you reply. I have test by changing phyid at 0x02, but it does not work.
And now the fec2 is ok in kernel .
When I use the mii info cmd in uboot and then boot the kernel, the fec1 can work now.
If there is no mii info cmd, the fec1 will not work.
The fec1 phy id is still 0 now.
So we can fix the problem on software. I miss somthing in kernel? Please help me!
=> mii info
PHY 0x00: OUI = 0x1374, Model = 0x07, Rev = 0x02, 100baseT, FDX
PHY 0x04: OUI = 0x1374, Model = 0x07, Rev = 0x02, 10baseT, HDX
Freescale i.MX Release Distro 4.1.15-1.2.0 wiseiot /dev/ttymxc0
wiseiot login: fec 30be0000.ethernet eth0: Link is Up - 1Gbps/Full - flow control rx/tx
IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
Freescale i.MX Release Distro 4.1.15-1.2.0 wiseiot /dev/ttymxc0
wiseiot login: root
root@wiseiot:~# ifconfig eth0 192.168.1.2
root@wiseiot:~# ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1): 56 data bytes
64 bytes from 192.168.1.1: seq=0 ttl=64 time=2.482 ms
64 bytes from 192.168.1.1: seq=1 ttl=64 time=1.344 ms
64 bytes from 192.168.1.1: seq=2 ttl=64 time=1.291 ms
64 bytes from 192.168.1.1: seq=3 ttl=64 time=1.327 ms
64 bytes from 192.168.1.1: seq=4 ttl=64 time=1.332 ms
^C
--- 192.168.1.1 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 1.291/1.555/2.482 ms
root@wiseiot:~#
If you don't define the phyid as the BSP release, it will do the autoscan from phyid 0. But in you hardward design the 0 should be the broadcast PHY address not unique PHY address..
The phy address is defined by "hardware". Please check the hardware design then make it in dts.
You log shows you are using the autoscan. And the 0 phyid is got.
So I provided the two ways in the previous reply. One is to use dts to define, of course according to the hardware design.
If not define the phyid in the dts to use the autoscan. Make changes in the kernel C code, to scan from 1 not 0.
It is the same in the uboot. and you will see the phyid in the result. and the software will automatically set the phyid for you.
For the uboot,
1. so far, it doesn't support two ethernet interface. It is not neccessary to support two ethernet interfaces in uboot.
2. also you can use and certain address for the mii info command: mii info <addr> - display MII PHY info
3. In the hardware design, you can make PHY Address 0 set as unique PHY address. Broadcast phy address 0 is not used under your case.
4. If you cannot re-work the hardware, you can make the mirror change as it is in the Linux kernel.
To scan from 1 not 0.
uboot-imx\common\miiphyutil.c
void mdio_list_devices(void)
{
struct list_head *entry;
list_for_each(entry, &mii_devs) {
int i;
struct mii_dev *bus = list_entry(entry, struct mii_dev, link);
printf("%s:\n", bus->name);
//for (i = 0; i < PHY_MAX_ADDR; i++) {
for (i = 1; i < PHY_MAX_ADDR; i++) {
struct phy_device *phydev = bus->phymap[i];
if (phydev) {
printf("%d - %s", i, phydev->drv->name);
if (phydev->dev)
printf(" <--> %s\n", phydev->dev->name);
else
printf("\n");
}
}
}
}
In the previous reply:
For the kernel
fec_main.c:
tatic int fec_enet_mii_probe(struct net_device *ndev)
{
struct fec_enet_private *fep = netdev_priv(ndev);
struct phy_device *phy_dev = NULL;
char mdio_bus_id[MII_BUS_ID_SIZE];
char phy_name[MII_BUS_ID_SIZE + 3];
int phy_id;
int dev_id = fep->dev_id;
fep->phy_dev = NULL;
if (fep->phy_node) {
phy_dev = of_phy_connect(ndev, fep->phy_node,
&fec_enet_adjust_link, 0,
fep->phy_interface);
if (!phy_dev)
return -ENODEV;
} else {
/* check for attached phy */
//for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
for (phy_id = 1; (phy_id < PHY_MAX_ADDR); phy_id++) {
if ((fep->mii_bus->phy_mask & (1 << phy_id)))
continue;
if (fep->mii_bus->phy_map[phy_id] == NULL)
continue;
if (fep->mii_bus->phy_map[phy_id]->phy_id == 0)
continue;
if (dev_id--)
continue;
strlcpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);
break;
}
从log 来看 用的PHY的地址ID是 00 是一个广播地址。 这个应该是硬件设计的问题。
在device tree 里面根据硬件设计配置一下PHYID 再试验一下。
或者改一下fec_main.c 从 1 开始找phy 而不是0
//for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
for (phy_id = 1; (phy_id < PHY_MAX_ADDR); phy_id++) {
dts:
&fec1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet1>;
pinctrl-assert-gpios = <&gpio_spi 5 GPIO_ACTIVE_HIGH>;
assigned-clocks = <&clks IMX7D_ENET1_TIME_ROOT_SRC>,
<&clks IMX7D_ENET1_TIME_ROOT_CLK>;
assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
assigned-clock-rates = <0>, <100000000>;
phy-mode = "rgmii";
phy-handle = <ðphy0>;
fsl,magic-packet;
status = "okay";
mdio {
#address-cells = <1>;
#size-cells = <0>;
ethphy0: ethernet-phy@0 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <0>;
};
ethphy1: ethernet-phy@1 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <1>;
};
};
};
&fec2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet2 &pinctrl_enet2_epdc0_en>;
pinctrl-assert-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
assigned-clocks = <&clks IMX7D_ENET2_TIME_ROOT_SRC>,
<&clks IMX7D_ENET2_TIME_ROOT_CLK>;
assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
assigned-clock-rates = <0>, <100000000>;
phy-mode = "rgmii";
phy-handle = <ðphy1>;
fsl,magic-packet;
status = "okay";
};
fec_main.c:
tatic int fec_enet_mii_probe(struct net_device *ndev)
{
struct fec_enet_private *fep = netdev_priv(ndev);
struct phy_device *phy_dev = NULL;
char mdio_bus_id[MII_BUS_ID_SIZE];
char phy_name[MII_BUS_ID_SIZE + 3];
int phy_id;
int dev_id = fep->dev_id;
fep->phy_dev = NULL;
if (fep->phy_node) {
phy_dev = of_phy_connect(ndev, fep->phy_node,
&fec_enet_adjust_link, 0,
fep->phy_interface);
if (!phy_dev)
return -ENODEV;
} else {
/* check for attached phy */
//for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
for (phy_id = 1; (phy_id < PHY_MAX_ADDR); phy_id++) {
if ((fep->mii_bus->phy_mask & (1 << phy_id)))
continue;
if (fep->mii_bus->phy_map[phy_id] == NULL)
continue;
if (fep->mii_bus->phy_map[phy_id]->phy_id == 0)
continue;
if (dev_id--)
continue;
strlcpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);
break;
}
Hi tian
please check with oscilloscope if rgmii timings conform to
Table 71. RGMII signal switching specifications i.MX7D Reference Manual
http://cache.nxp.com/files/32bit/doc/ref_manual/IMX7DRM.pdf
Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------