Discussion:
[Linuxptp-users] LinuxPTP on Zynq with DP83640
Wolfgang Hennig
2017-04-18 19:54:23 UTC
Permalink
Hi,

I'm working on a project where a Xilinx Zynq uses a DP83640 (eval board)
as the Ethernet PHY. I'm running Ubuntu/Linaro 15 on the Zynq's ARM
processor and successfully modified kernel options and
compiled/installed LinuxPTP to synchronize time over the network. Now I
would like to use the DP83640's configurable reference clock (output on
a GPIO pin) to clock logic in the FPGA section of the Zynq. To do that I
would need to read/write the DP83640's internal registers, but I don't
know how.

It seems that there is some functionality in setting the registers in
(2) DP83640 Driver: I found several comments that the GPIOs of the
PHYs should be connected together on order to be able to synchronize
the two PHYs (recalibrate) but I did't find the detail information
which GPIO of PHY 1should be connected to which GPIO of PHY 2.
If does not matter which GPIO. You can choose any one of these.
1, 2, 3, 4, 8, 9, 10, 11
The dp83640 driver has a module parameter that lets you configure
this.
In the code I see statements like this (e.g. line 678)
ext_write <http://lxr.free-electrons.com/ident?i=ext_write>(0, master,PAGE4 <http://lxr.free-electrons.com/ident?i=PAGE4>,PTP_CTL <http://lxr.free-electrons.com/ident?i=PTP_CTL>,val <http://lxr.free-electrons.com/ident?i=val>);
which seems to write to the PTP control register in page 4 of the
DP83640's memory. However I can't figure out how this would be used,
either through LinuxPTP or a separate user program. Any help would be
greatly appreciated.


Some more system info:
I'm using the xemacps driver for the Zynq MAC
invalid PHY address
[ 1.010225] xemacps e000b000.ethernet: pdev->id -1, baseaddr
0xe000b000, irq 147
[ 3.486259] xemacps e000b000.ethernet eth1: renamed from eth0
[ 6.282066] xemacps e000b000.ethernet: GEM: phydev ef202c00,
phydev->phy_id 0x20005ce1, phydev->addr 0x0
[ 6.282097] xemacps e000b000.ethernet: phy_addr 0x0, phy_id 0x20005ce1
[ 6.282107] xemacps e000b000.ethernet: attach [NatSemi DP83640] phy
driver
[ 8.391352] xemacps e000b000.ethernet: Set clk to 0 Hz
[ 8.391367] xemacps e000b000.ethernet: link up (100/FULL)
Though there are some warnings, I get a working connection through our
local network


ethtool reports
hardware-transmit (SOF_TIMESTAMPING_TX_HARDWARE)
hardware-receive (SOF_TIMESTAMPING_RX_HARDWARE)
hardware-raw-clock (SOF_TIMESTAMPING_RAW_HARDWARE)
PTP Hardware Clock: 0
off (HWTSTAMP_TX_OFF)
on (HWTSTAMP_TX_ON)
one-step-sync (HWTSTAMP_TX_ONESTEP_SYNC)
none (HWTSTAMP_FILTER_NONE)
ptpv1-l4-event (HWTSTAMP_FILTER_PTP_V1_L4_EVENT)
ptpv2-l4-event (HWTSTAMP_FILTER_PTP_V2_L4_EVENT)
ptpv2-l2-event (HWTSTAMP_FILTER_PTP_V2_L2_EVENT)
ptpv2-event (HWTSTAMP_FILTER_PTP_V2_EVENT)
Running ptp4l on 2 systems connected though the local network, I see
them link up and adjust to an offset of a few hundred ns.

I should add that I did not (yet) find where/how to modify the xemacps
driver per https://lwn.net/Articles/392150/
1. Before mdio_register, add
bus->locktype = MDIOBUS_ATOMIC_RW;
2. In the .ndo_start_xmit function, add
skb_tx_timestamp()
3. In the NAPI poll function, add
skb_rx_timestamp()
and so the HW timestamping might have been provided by the Zynq's build
in TSU instead of the DP83640. How would you tell? Does it matter where
in the function one adds skb_tx_timestamp()?


Thanks for your help,

Wolfgang
--
Wolfgang Hennig
XIA LLC
Richard Cochran
2017-04-18 20:44:18 UTC
Permalink
I'm working on a project where a Xilinx Zynq uses a DP83640 (eval board) as
the Ethernet PHY. I'm running Ubuntu/Linaro 15 on the Zynq's ARM processor
and successfully modified kernel options and compiled/installed LinuxPTP to
synchronize time over the network. Now I would like to use the DP83640's
configurable reference clock (output on a GPIO pin) to clock logic in the
FPGA section of the Zynq. To do that I would need to read/write the
DP83640's internal registers, but I don't know how.
It seems that there is some functionality in setting the registers in
We don't have any support for enabling the clock output. You can hack
this in using something like this:

ext_write(0, phydev, PAGE6, PTP_COC, coc);
I should add that I did not (yet) find where/how to modify the xemacps
driver per https://lwn.net/Articles/392150/
1. Before mdio_register, add
bus->locktype = MDIOBUS_ATOMIC_RW;
2. In the .ndo_start_xmit function, add
skb_tx_timestamp()
3. In the NAPI poll function, add
skb_rx_timestamp()
That info is obsolete. All you need is a MAC driver that uses phylib
and calls skb_tx_timestamp().
and so the HW timestamping might have been provided by the Zynq's build in
TSU instead of the DP83640. How would you tell?
If your Zynq driver implements time stamping or PHC, then you should
disable or remove that code.

BTW you can check sysfs to see the PHC device names:

What: /sys/class/ptp/ptpN/clock_name
Description:
This file contains the name of the PTP hardware clock
as a human readable string. The purpose of this
attribute is to provide the user with a "friendly
name" and to help distinguish PHY based devices from
MAC based ones. The string does not necessarily have
to be any kind of unique id.
Does it matter where in the
function one adds skb_tx_timestamp()?
See the comment in include/linux/skbuff.h.

Thanks,
Richard
Wolfgang Hennig
2017-04-20 21:44:48 UTC
Permalink
Post by Richard Cochran
I'm working on a project where a Xilinx Zynq uses a DP83640 (eval board) as
the Ethernet PHY. I'm running Ubuntu/Linaro 15 on the Zynq's ARM processor
and successfully modified kernel options and compiled/installed LinuxPTP to
synchronize time over the network. Now I would like to use the DP83640's
configurable reference clock (output on a GPIO pin) to clock logic in the
FPGA section of the Zynq. To do that I would need to read/write the
DP83640's internal registers, but I don't know how.
It seems that there is some functionality in setting the registers in
We don't have any support for enabling the clock output. You can hack
ext_write(0, phydev, PAGE6, PTP_COC, coc);
That worked pretty well.
I put it in dp838640_config_init (as a first test).
Post by Richard Cochran
I should add that I did not (yet) find where/how to modify the xemacps
driver per https://lwn.net/Articles/392150/
1. Before mdio_register, add
bus->locktype = MDIOBUS_ATOMIC_RW;
2. In the .ndo_start_xmit function, add
skb_tx_timestamp()
3. In the NAPI poll function, add
skb_rx_timestamp()
That info is obsolete. All you need is a MAC driver that uses phylib
and calls skb_tx_timestamp().
and so the HW timestamping might have been provided by the Zynq's build in
TSU instead of the DP83640. How would you tell?
If your Zynq driver implements time stamping or PHC, then you should
disable or remove that code.
There was definitely an issue there. Three changes in/for the xemacps
driver were required:
1) turn off option CONFIG_XILINX_PS_EMAC_HWTSTAMP for the kernel compile
2) in ~line 2800 of xilinx_emacps.c, function xemacps_ioctl, add the
#else section below so that it responds with the PHY's HW timestamping
capabilities when queried by ptp4l. (Interestingly, ethtool -T always
reports the PHY's capabilities)
switch (cmd) {
case SIOCGMIIPHY:
case SIOCGMIIREG:
case SIOCSMIIREG:
return phy_mii_ioctl(phydev, rq, cmd);
#ifdef CONFIG_XILINX_PS_EMAC_HWTSTAMP
case SIOCSHWTSTAMP:
return xemacps_hwtstamp_ioctl(ndev, rq, cmd);
#else
case SIOCSHWTSTAMP:
return phy_mii_ioctl(phydev, rq, cmd);
#endif
3) I added skb_tx_timestamp(skb) in line 2256 of xilinx_emacps.c, before
the for loop over nr_frags. Seems to work, didn't experiment with other
locations.



I now get offsets from master of about 100ns through our local network
and <10ns when connecting 2 boards back to back. The DP83640's CLK_OUT
signals are pretty well synchronized (looking at an oscilloscope I see
the edges drifting by about 10ns relative to each other).


Thank you very much for the hints, Richard, that was very helpful.

Wolfgang
Post by Richard Cochran
What: /sys/class/ptp/ptpN/clock_name
This file contains the name of the PTP hardware clock
as a human readable string. The purpose of this
attribute is to provide the user with a "friendly
name" and to help distinguish PHY based devices from
MAC based ones. The string does not necessarily have
to be any kind of unique id.
Does it matter where in the
function one adds skb_tx_timestamp()?
See the comment in include/linux/skbuff.h.
Thanks,
Richard
--
Wolfgang Hennig, Ph.D.
XIA LLC
31057 Genstar Rd.
Hayward CA 94544
Loading...