support the cpts found on am335x devices
v2 cover support the cpts found on am335x devices
This patch series, based on linux-3.7-rc1 plus the fixes I posted today, adds support for the Common Platform Time Sync (CPTS) found on the popular BeagleBone. The code enables hardware time stamping and a PTP Hardware Clock.
Changes in V2
- Now uses device tree
- Actually works with vanilla kernel
This work has been tested using the linuxptp PTP stack, and it seems to be working quite well. One limitation of the hardware is that not possible to adjust the clock frequency. Even without with this capability, the driver will be still be useful for 802.1AS applications, since they typically use a free running clock.
There is one open issue with this driver which will hopefully soon be resolved. Time stamping only works on UDP packets. Although Layer 2 is supposed to work according to the TRM, I have not yet figured out how. The UDP only works when setting an undocumented bit, so maybe someone from TI can fill me in on this.
Thanks,
Richard
Richard Cochran (7):
cpsw: rename register banks to match the reference manual
cpsw: add missing fields to the CPSW_SS register bank.
cpsw: correct the CPSW_PORT register bank declaration
cpsw: add a common header file for regsiter declarations
cpts: introduce time stamping code and a PTP hardware clock.
cpsw: add a DT field for the cpts offset
cpsw: use the time stamping capabilities of the cpts
Documentation/devicetree/bindings/net/cpsw.txt | 11 +- arch/arm/boot/dts/am33xx.dtsi | 5 +- drivers/net/ethernet/ti/Kconfig | 8 + drivers/net/ethernet/ti/Makefile | 2 +- drivers/net/ethernet/ti/cpsw.c | 84 ++++- drivers/net/ethernet/ti/cpsw_reg.h | 81 ++++ drivers/net/ethernet/ti/cpts.c | 468 ++++++++++++++++++++++++ drivers/net/ethernet/ti/cpts.h | 148 ++++++++ include/linux/platform_data/cpsw.h | 1 + 9 files changed, 788 insertions(+), 20 deletions(-) create mode 100644 drivers/net/ethernet/ti/cpsw_reg.h create mode 100644 drivers/net/ethernet/ti/cpts.c create mode 100644 drivers/net/ethernet/ti/cpts.h
Signature · 1 line
1.7.2.5
PATCH v2 1/7 cpsw: rename register banks to match the reference manual
The code mixes up the CPSW_SS and the CPSW_WR register naming. This patch changes the names to conform to the published Technical Reference Manual from TI, in order to make working on the code less confusing.
--- drivers/net/ethernet/ti/cpsw.c | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-)
drivers/net/ethernet/ti/cpsw.c +9 -9
@@ -129,7 +129,7 @@ static int rx_packet_max = CPSW_MAX_PACKET_SIZE;module_param (rx_packet_max, int,0 );MODULE_PARM_DESC (rx_packet_max,"maximum receive packet size (bytes)" ); -struct cpsw_ss_regs { +struct cpsw_wr_regs {u32 id_ver;u32 soft_reset;u32 control;
@@ -140,7 +140,7 @@ struct cpsw_ss_regs {u32 misc_en; }; -struct cpsw_regs { +struct cpsw_ss_regs {u32 id_ver;u32 control;u32 soft_reset;
@@ -202,8 +202,8 @@ struct cpsw_priv {struct napi_struct napi;struct device *dev;struct cpsw_platform_data data; -struct cpsw_regs __iomem *regs; -struct cpsw_ss_regs __iomem *ss_regs; +struct cpsw_ss_regs __iomem *regs; +struct cpsw_wr_regs __iomem *wr_regs;struct cpsw_host_regs __iomem *host_port_regs;u32 msg_enable;struct net_device_stats stats;
@@ -230,8 +230,8 @@ struct cpsw_priv {static void cpsw_intr_enable (struct cpsw_priv *priv) { -__raw_writel (0xFF , &priv->ss_regs->tx_en); -__raw_writel (0xFF , &priv->ss_regs->rx_en); +__raw_writel (0xFF , &priv->wr_regs->tx_en); +__raw_writel (0xFF , &priv->wr_regs->rx_en);cpdma_ctlr_int_ctrl (priv->dma, true);return ;
@@ -239,8 +239,8 @@ static void cpsw_intr_enable(struct cpsw_priv *priv)static void cpsw_intr_disable (struct cpsw_priv *priv) { -__raw_writel (0 , &priv->ss_regs->tx_en); -__raw_writel (0 , &priv->ss_regs->rx_en); +__raw_writel (0 , &priv->wr_regs->tx_en); +__raw_writel (0 , &priv->wr_regs->rx_en);cpdma_ctlr_int_ctrl (priv->dma, false);return ;
@@ -984,7 +984,7 @@ static int __devinit cpsw_probe(struct platform_device *pdev)dev_err (priv->dev,"unable to map i/o region\n" ); goto clean_cpsw_ss_iores_ret; } - priv->ss_regs = regs; + priv->wr_regs = regs;for_each_slave (priv, cpsw_slave_init, priv);
Signature · 1 line
1.7.2.5
PATCH v2 2/7 cpsw: add missing fields to the CPSW_SS register bank.
In reply to Richard Cochran--- drivers/net/ethernet/ti/cpsw.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-)
drivers/net/ethernet/ti/cpsw.c +8 -0
@@ -146,6 +146,14 @@ struct cpsw_ss_regs {u32 soft_reset;u32 stat_port_en;u32 ptype; +u32 soft_idle; +u32 thru_rate; +u32 gap_thresh; +u32 tx_start_wds; +u32 flow_control; +u32 vlan_ltype; +u32 ts_ltype; +u32 dlr_ltype; };struct cpsw_slave_regs {
Signature · 1 line
1.7.2.5
PATCH v2 3/7 cpsw: correct the CPSW_PORT register bank declaration
In reply to Richard CochranThis commit corrects and expands the slave port register bank according to TI's Technical Reference Manual.
--- Documentation/devicetree/bindings/net/cpsw.txt | 8 ++++---- arch/arm/boot/dts/am33xx.dtsi | 4 ++-- drivers/net/ethernet/ti/cpsw.c | 18 ++++++++++++++---- 3 files changed, 20 insertions(+), 10 deletions(-)
Documentation/devicetree/bindings/net/cpsw.txt +4 -4
@@ -59,14 +59,14 @@ Examples: mac_control = <0x20>; slaves = <2>; cpsw_emac0: slave at 0 { - slave_reg_ofs = <0x208>; + slave_reg_ofs = <0x200>; sliver_reg_ofs = <0xd80>; phy_id = "davinci_mdio.16:00"; /* Filled in by U-Boot */ mac-address = [ 00 00 00 00 00 00 ]; }; cpsw_emac1: slave at 1 { - slave_reg_ofs = <0x308>; + slave_reg_ofs = <0x300>; sliver_reg_ofs = <0xdc0>; phy_id = "davinci_mdio.16:01"; /* Filled in by U-Boot */
@@ -93,14 +93,14 @@ Examples: mac_control = <0x20>; slaves = <2>; cpsw_emac0: slave at 0 { - slave_reg_ofs = <0x208>; + slave_reg_ofs = <0x200>; sliver_reg_ofs = <0xd80>; phy_id = "davinci_mdio.16:00"; /* Filled in by U-Boot */ mac-address = [ 00 00 00 00 00 00 ]; }; cpsw_emac1: slave at 1 { - slave_reg_ofs = <0x308>; + slave_reg_ofs = <0x300>; sliver_reg_ofs = <0xdc0>; phy_id = "davinci_mdio.16:01"; /* Filled in by U-Boot */
arch/arm/boot/dts/am33xx.dtsi +2 -2
@@ -238,13 +238,13 @@ interrupts = <40 41 42 43>; ranges; cpsw_emac0: slave at 0 { - slave_reg_ofs = <0x208>; + slave_reg_ofs = <0x200>; sliver_reg_ofs = <0xd80>; /* Filled in by U-Boot */ mac-address = [ 00 00 00 00 00 00 ]; }; cpsw_emac1: slave at 1 { - slave_reg_ofs = <0x308>; + slave_reg_ofs = <0x300>; sliver_reg_ofs = <0xdc0>; /* Filled in by U-Boot */ mac-address = [ 00 00 00 00 00 00 ];
drivers/net/ethernet/ti/cpsw.c +14 -4
@@ -157,16 +157,26 @@ struct cpsw_ss_regs { };struct cpsw_slave_regs { +u32 control; +u32 res1;u32 max_blks;u32 blk_cnt; -u32 flow_thresh; +u32 tx_in_ctl;u32 port_vlan;u32 tx_pri_map; -u32 ts_ctl; -u32 ts_seq_ltype; -u32 ts_vlan; +u32 ts_seq_mtype;u32 sa_lo;u32 sa_hi; +u32 send_percent; +u32 res2; +u32 rx_dscp_pri_map0; +u32 rx_dscp_pri_map1; +u32 rx_dscp_pri_map2; +u32 rx_dscp_pri_map3; +u32 rx_dscp_pri_map4; +u32 rx_dscp_pri_map5; +u32 rx_dscp_pri_map6; +u32 rx_dscp_pri_map7; };struct cpsw_host_regs {
Signature · 1 line
1.7.2.5
PATCH v2 4/7 cpsw: add a common header file for regsiter declarations
In reply to Richard Cochran--- drivers/net/ethernet/ti/cpsw_reg.h | 81 ++++++++++++++++++++++++++++++++++++ 1 files changed, 81 insertions(+), 0 deletions(-) create mode 100644 drivers/net/ethernet/ti/cpsw_reg.h
drivers/net/ethernet/ti/cpsw_reg.h new file +81 -0
@@ -0,0 +1,81 @@ +/* +* Common CPSW register declarations +* +* Copyright (C) 2012 Richard Cochran <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef _TI_CPSW_REG_H_ +#define _TI_CPSW_REG_H_ + +struct cpsw_port { +u32 control;/* Control Register */ +u32 res1; +u32 max_blks;/* Maximum FIFO Blocks */ +u32 blk_cnt;/* FIFO Block Usage Count (Read Only) */ +u32 tx_in_ctl;/* Transmit FIFO Control */ +u32 port_vlan;/* VLAN Register */ +u32 tx_pri_map;/* Tx Header Priority to Switch Pri Map */ +u32 ts_seq_mtype;/* Time Sync Seq ID Offset and Msg Type */ +u32 sa_lo;/* CPGMAC_SL Source Address Low */ +u32 sa_hi;/* CPGMAC_SL Source Address High */ +u32 send_percent;/* Transmit Queue Send Percentages */ +u32 res2; +u32 rx_dscp_pri_map0;/* Rx DSCP Priority to Rx Packet Mapping */ +u32 rx_dscp_pri_map1;/* Rx DSCP Priority to Rx Packet Mapping */ +u32 rx_dscp_pri_map2;/* Rx DSCP Priority to Rx Packet Mapping */ +u32 rx_dscp_pri_map3;/* Rx DSCP Priority to Rx Packet Mapping */ +u32 rx_dscp_pri_map4;/* Rx DSCP Priority to Rx Packet Mapping */ +u32 rx_dscp_pri_map5;/* Rx DSCP Priority to Rx Packet Mapping */ +u32 rx_dscp_pri_map6;/* Rx DSCP Priority to Rx Packet Mapping */ +u32 rx_dscp_pri_map7;/* Rx DSCP Priority to Rx Packet Mapping */ +}; + +/* Bit definitions for the CONTROL register */ +#define PASS_PRI_TAGGED (1<<24)/* Pass Priority Tagged */ +#define VLAN_LTYPE2_EN (1<<21)/* VLAN LTYPE 2 enable */ +#define VLAN_LTYPE1_EN (1<<20)/* VLAN LTYPE 1 enable */ +#define DSCP_PRI_EN (1<<16)/* DSCP Priority Enable */ +#define TS_320 (1<<14)/* Time Sync Dest Port 320 enable */ +#define TS_319 (1<<13)/* Time Sync Dest Port 319 enable */ +#define TS_132 (1<<12)/* Time Sync Dest IP Addr 132 enable */ +#define TS_131 (1<<11)/* Time Sync Dest IP Addr 131 enable */ +#define TS_130 (1<<10)/* Time Sync Dest IP Addr 130 enable */ +#define TS_129 (1<<9)/* Time Sync Dest IP Addr 129 enable */ +#define TS_BIT8 (1<<8)/* ts_ttl_nonzero? */ +#define TS_ANNEX_D_EN (1<<4)/* Time Sync Annex D enable */ +#define TS_LTYPE2_EN (1<<3)/* Time Sync LTYPE 2 enable */ +#define TS_LTYPE1_EN (1<<2)/* Time Sync LTYPE 1 enable */ +#define TS_TX_EN (1<<1)/* Time Sync Transmit Enable */ +#define TS_RX_EN (1<<0)/* Time Sync Receive Enable */ + +#define CTRL_TS_BITS \ + (TS_320 | TS_319 | TS_132 | TS_131 | TS_130 | TS_129 | TS_BIT8 | \ + TS_ANNEX_D_EN | TS_LTYPE2_EN | TS_LTYPE1_EN) + +#define CTRL_ALL_TS_MASK (CTRL_TS_BITS | TS_TX_EN | TS_RX_EN) +#define CTRL_TX_TS_BITS (CTRL_TS_BITS | TS_TX_EN) +#define CTRL_RX_TS_BITS (CTRL_TS_BITS | TS_RX_EN) + +/* Bit definitions for the TS_SEQ_MTYPE register */ +#define TS_SEQ_ID_OFFSET_SHIFT (16)/* Time Sync Sequence ID Offset */ +#define TS_SEQ_ID_OFFSET_MASK (0x3f) +#define TS_MSG_TYPE_EN_SHIFT (0)/* Time Sync Message Type Enable */ +#define TS_MSG_TYPE_EN_MASK (0xffff) + +/* The PTP event messages - Sync, Delay_Req, Pdelay_Req, and Pdelay_Resp. */ +#define EVENT_MSG_BITS ((1<<0) | (1<<1) | (1<<2) | (1<<3)) + +#endif
Signature · 1 line
1.7.2.5
PATCH v2 5/7 cpts: introduce time stamping code and a PTP hardware clock.
In reply to Richard CochranThis patch adds a driver for the CPTS that offers time stamping and a PTP hardware clock. Even though the hardware does not support frequency adjustment, still the unit can be useful for 802.1AS for example.
--- drivers/net/ethernet/ti/Kconfig | 8 + drivers/net/ethernet/ti/Makefile | 2 +- drivers/net/ethernet/ti/cpts.c | 468 ++++++++++++++++++++++++++++++++++++++ drivers/net/ethernet/ti/cpts.h | 148 ++++++++++++ 4 files changed, 625 insertions(+), 1 deletions(-) create mode 100644 drivers/net/ethernet/ti/cpts.c create mode 100644 drivers/net/ethernet/ti/cpts.h
drivers/net/ethernet/ti/Kconfig +8 -0
@@ -60,6 +60,14 @@ config TI_CPSW To compile this driver as a module, choose M here: the module will be called cpsw. +config TI_CPTS + boolean "TI Common Platform Time Sync (CPTS) Support" + depends on TI_CPSW && PTP_1588_CLOCK && !(TI_CPSW=y && PTP_1588_CLOCK=m) + ---help--- + This driver supports the Common Platform Time Sync unit of + the CPSW Ethernet Switch. The unit can time stamp PTP UDP/IPv4 + and Layer 2 packets, and the driver offers a PTP Hardware Clock. + config TLAN tristate "TI ThunderLAN support" depends on (PCI || EISA)
drivers/net/ethernet/ti/Makefile +1 -1
@@ -8,4 +8,4 @@ obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o obj-$(CONFIG_TI_CPSW) += ti_cpsw.o -ti_cpsw-y := cpsw_ale.o cpsw.o +ti_cpsw-y := cpsw_ale.o cpsw.o cpts.o
drivers/net/ethernet/ti/cpts.c new file +468 -0
468 lines not on this page · raw message
drivers/net/ethernet/ti/cpts.h new file +148 -0
148 lines not on this page · raw message
Signature · 1 line
1.7.2.5
PATCH v2 6/7 cpsw: add a DT field for the cpts offset
In reply to Richard Cochran--- Documentation/devicetree/bindings/net/cpsw.txt | 3 +++ arch/arm/boot/dts/am33xx.dtsi | 1 + drivers/net/ethernet/ti/cpsw.c | 7 +++++++ include/linux/platform_data/cpsw.h | 1 + 4 files changed, 12 insertions(+), 0 deletions(-)
Documentation/devicetree/bindings/net/cpsw.txt +3 -0
@@ -16,6 +16,7 @@ Required properties: - ale_entries : Specifies No of entries ALE can hold - host_port_reg_ofs : Specifies host port register offset - hw_stats_reg_ofs : Specifies hardware statistics register offset +- cpts_reg_ofs : Specifies the offset of the CPTS registers - bd_ram_ofs : Specifies internal desciptor RAM offset - bd_ram_size : Specifies internal descriptor RAM size - rx_descs : Specifies number of Rx descriptors
@@ -52,6 +53,7 @@ Examples: ale_entries = <1024>; host_port_reg_ofs = <0x108>; hw_stats_reg_ofs = <0x900>; + cpts_reg_ofs = <0xc00>; bd_ram_ofs = <0x2000>; bd_ram_size = <0x2000>; no_bd_ram = <0>;
@@ -86,6 +88,7 @@ Examples: ale_entries = <1024>; host_port_reg_ofs = <0x108>; hw_stats_reg_ofs = <0x900>; + cpts_reg_ofs = <0xc00>; bd_ram_ofs = <0x2000>; bd_ram_size = <0x2000>; no_bd_ram = <0>;
arch/arm/boot/dts/am33xx.dtsi +1 -0
@@ -222,6 +222,7 @@ ale_entries = <1024>; host_port_reg_ofs = <0x108>; hw_stats_reg_ofs = <0x900>; + cpts_reg_ofs = <0xc00>; bd_ram_ofs = <0x2000>; bd_ram_size = <0x2000>; no_bd_ram = <0>;
drivers/net/ethernet/ti/cpsw.c +7 -0
@@ -817,6 +817,13 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, } data->hw_stats_reg_ofs = prop; +if (of_property_read_u32 (node,"cpts_reg_ofs" , &prop)) { +pr_err ("Missing cpts_reg_ofs property in the DT.\n" ); + ret = -EINVAL ; + goto error_ret; + } + data->cpts_reg_ofs = prop; +if (of_property_read_u32 (node,"bd_ram_ofs" , &prop)) {pr_err ("Missing bd_ram_ofs property in the DT.\n" ); ret = -EINVAL ;
include/linux/platform_data/cpsw.h +1 -0
@@ -41,6 +41,7 @@ struct cpsw_platform_data {u32 host_port_num;/* The port number for the host port */ u32 hw_stats_reg_ofs;/* cpsw hardware statistics counters */ +u32 cpts_reg_ofs;/* cpts registers */ u32 bd_ram_ofs;/* embedded buffer descriptor RAM offset*/ u32 bd_ram_size;/*buffer descriptor ram size */
Signature · 1 line
1.7.2.5
PATCH v2 7/7 cpsw: use the time stamping capabilities of the cpts
In reply to Richard Cochran--- drivers/net/ethernet/ti/cpsw.c | 33 +++++++++++++++++++++++++++++++++ 1 files changed, 33 insertions(+), 0 deletions(-)
drivers/net/ethernet/ti/cpsw.c +33 -0
@@ -35,6 +35,7 @@#include <linux/platform_data/cpsw.h> #include "cpsw_ale.h" +#include "cpts.h" #include "davinci_cpdma.h" #define CPSW_DEBUG (NETIF_MSG_HW | NETIF_MSG_WOL | \
@@ -236,6 +237,7 @@ struct cpsw_priv {/* snapshot of IRQ numbers */ u32 irqs_table[4 ];u32 num_irqs; +struct cpts cpts; };#define napi_to_priv (napi) container_of(napi, struct cpsw_priv, napi)
@@ -272,6 +274,7 @@ void cpsw_tx_handler(void *token, int len, int status)if (unlikely (netif_queue_stopped (ndev)))netif_start_queue (ndev); +cpts_tx_timestamp (&priv->cpts, skb); priv->stats.tx_packets++; priv->stats.tx_bytes += len;dev_kfree_skb_any (skb);
@@ -292,6 +295,7 @@ void cpsw_rx_handler(void *token, int len, int status) }if (likely (status >=0 )) {skb_put (skb, len); +cpts_rx_timestamp (&priv->cpts, skb); skb->protocol =eth_type_trans (skb, ndev);netif_receive_skb (skb); priv->stats.rx_bytes += len;
@@ -610,6 +614,11 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,return NETDEV_TX_OK ; } +if (skb_shinfo (skb)->tx_flags &SKBTX_HW_TSTAMP && priv->cpts.tx_enable) +skb_shinfo (skb)->tx_flags |=SKBTX_IN_PROGRESS ; + +skb_tx_timestamp (skb); + ret =cpdma_chan_submit (priv->txch, skb, skb->data, skb->len,GFP_KERNEL );if (unlikely (ret !=0 )) {
@@ -647,6 +656,21 @@ static void cpsw_ndo_change_rx_flags(struct net_device *ndev, int flags)dev_err (&ndev->dev,"multicast traffic cannot be filtered!\n" ); } +static int cpsw_ndo_ioctl (struct net_device *dev,struct ifreq *req,int cmd) +{ +struct cpsw_priv *priv =netdev_priv (dev); + +if (!netif_running (dev)) +return -EINVAL ; + +switch (cmd) { +case SIOCSHWTSTAMP : +return cpts_hwtstamp_ioctl (&priv->cpts, req); + } + +return -ENOTSUPP ; +} +static void cpsw_ndo_tx_timeout (struct net_device *ndev) {struct cpsw_priv *priv =netdev_priv (ndev);
@@ -687,6 +711,7 @@ static const struct net_device_ops cpsw_netdev_ops = { .ndo_stop = cpsw_ndo_stop, .ndo_start_xmit = cpsw_ndo_start_xmit, .ndo_change_rx_flags = cpsw_ndo_change_rx_flags, + .ndo_do_ioctl = cpsw_ndo_ioctl, .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = eth_change_mtu, .ndo_tx_timeout = cpsw_ndo_tx_timeout,
@@ -988,6 +1013,8 @@ static int __devinit cpsw_probe(struct platform_device *pdev) priv->regs = regs; priv->host_port = data->host_port_num; priv->host_port_regs = regs + data->host_port_reg_ofs; + priv->cpts.reg = regs + data->cpts_reg_ofs; + priv->cpts.tsp = regs + priv->data.slave_data[0 ].slave_reg_ofs; priv->cpsw_ss_res =platform_get_resource (pdev,IORESOURCE_MEM ,1 );if (!priv->cpsw_ss_res) {
@@ -1109,6 +1136,11 @@ static int __devinit cpsw_probe(struct platform_device *pdev) goto clean_irq_ret; } +if (cpts_register (&pdev->dev, &priv->cpts)) +dev_err (priv->dev,"error registering cpts device\n" ); + +__raw_writel (ETH_P_1588 , &priv->regs->ts_ltype); +cpsw_notice (priv, probe,"initialized device (regs %x, irq %d)\n" , priv->cpsw_res->start, ndev->irq);
@@ -1148,6 +1180,7 @@ static int __devexit cpsw_remove(struct platform_device *pdev)pr_info ("removing device" );platform_set_drvdata (pdev,NULL ); +cpts_unregister (&priv->cpts);free_irq (ndev->irq, priv);cpsw_ale_destroy (priv->ale);cpdma_chan_destroy (priv->txch);
Signature · 1 line
1.7.2.5
Quoted 57 lines
-----Original Message-----
From: Richard Cochran [mailto:richardcochran at gmail.com]
Sent: Tuesday, October 16, 2012 1:18 AM
To: netdev at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org; David Miller; Chemparathy, Cyril; N, Mugunthan V; Govindarajan, Sriramakrishnan
Subject: [PATCH V2 0/7] support the cpts found on am335x devicesThis patch series, based on linux-3.7-rc1 plus the fixes I posted today, adds support for the Common Platform Time Sync (CPTS) found on the popular BeagleBone. The code enables hardware time stamping and a PTP Hardware Clock.
Changes in V2
- Now uses device tree
- Actually works with vanilla kernelThis work has been tested using the linuxptp PTP stack, and it seems to be working quite well. One limitation of the hardware is that not possible to adjust the clock frequency. Even without with this capability, the driver will be still be useful for 802.1AS applications, since they typically use a free running clock.
There is one open issue with this driver which will hopefully soon be resolved. Time stamping only works on UDP packets. Although Layer 2 is supposed to work according to the TRM, I have not yet figured out how. The UDP only works when setting an undocumented bit, so maybe someone from TI can fill me in on this.
Thanks,
RichardRichard Cochran (7):
cpsw: rename register banks to match the reference manual
cpsw: add missing fields to theCPSW_SSregister bank.
cpsw: correct theCPSW_PORTregister bank declaration
cpsw: add a common header file for regsiter declarations
cpts: introduce time stamping code and a PTP hardware clock.
cpsw: add a DT field for the cpts offset
cpsw: use the time stamping capabilities of the cptsDocumentation/devicetree/bindings/net/cpsw.txt | 11 +- arch/arm/boot/dts/am33xx.dtsi | 5 +- drivers/net/ethernet/ti/Kconfig | 8 + drivers/net/ethernet/ti/Makefile | 2 +- drivers/net/ethernet/ti/cpsw.c | 84 ++++- drivers/net/ethernet/ti/cpsw_reg.h | 81 ++++ drivers/net/ethernet/ti/cpts.c | 468 ++++++++++++++++++++++++ drivers/net/ethernet/ti/cpts.h | 148 ++++++++ include/linux/platform_data/cpsw.h | 1 + 9 files changed, 788 insertions(+), 20 deletions(-) create mode 100644 drivers/net/ethernet/ti/cpsw_reg.h create mode 100644 drivers/net/ethernet/ti/cpts.c create mode 100644 drivers/net/ethernet/ti/cpts.h
Quoted 2 lines
--
1.7.2.5
Richard
I had seen some issues with the patch series.
* CPTS will hold only LSB 32 bits of 64 bit Timer and the upper 32 bit time value has to be taken care by the software, but the time stamp which is passed to skb or PTP clock consist of only 32 bit time value
* CPTS interrupts should be utilized to service Half and Full roll over events as it is non sync events with respect to get/set time and PTP pkt Tx/Rx
* CPTS Time which is obtained from hardware is not actually a nano seconds as the CPTS ref clock is tied to 250MHz for AM335x.
* CPSW register mapping done in this patch series removes the CPSW driver support for previous version found in TI814x
* CPSW Time stamping is done only for port 0 and port 1 is not done
Regards
Mugunthan V N
Quoted 1 line · Mugunthan V
I had seen some issues with the patch series.
Please take another look. Excepting the last, none of your points holds water.
Quoted 3 lines
* CPTS will hold only LSB 32 bits of 64 bit Timer and the upper 32 bit time value has to be taken care by the software, but the time stamp which is passed to skb or PTP clock consist of only 32 bit time value
The driver handles this already.
Quoted 3 lines
* CPTS interrupts should be utilized to service Half and Full roll over events as it is non sync events with respect to get/set time and PTP pkt Tx/Rx
Nope, no need for interrupts, since we already have a better way to handle this.
Quoted 2 lines
* CPTS Time which is obtained from hardware is not actually a nano seconds as the CPTS ref clock is tied to 250MHz for AM335x.
Did you even look at the code in my patch?
Quoted 2 lines
* CPSW register mapping done in this patch series removes the CPSW driver support for previous version found in TI814x
In which Linux version (or commit) did this driver appear? I never saw it.
Quoted 1 line
* CPSW Time stamping is done only for port 0 and port 1 is not done
Yes, you are right, and it is strange that the hardware time stamps on the external ports of the switch, and not at the host port as it should. Of course it does present us with a problem, since we cannot reasonably have both ports time stamping at the same time. I propose simply using a device tree attribute to tell which port to activate.
Thanks,
Richard
Quoted 14 lines
-----Original Message-----
From: Richard Cochran [mailto:richardcochran at gmail.com]
Sent: Tuesday, October 16, 2012 10:44 PM
To: N, Mugunthan V
Cc: netdev at vger.kernel.org; linux-arm-kernel at lists.infradead.org; David Miller; Chemparathy, Cyril; Govindarajan, Sriramakrishnan
Subject: Re: [PATCH V2 0/7] support the cpts found on am335x devicesQuoted 1 line · Mugunthan V
I had seen some issues with the patch series.
Please take another look. Excepting the last, none of your points holds water.
Quoted 7 lines
Quoted 1 line
* CPTS will hold only LSB 32 bits of 64 bit Timer and the upper 32
bit
Quoted 2 lines
time value has to be taken care by the software, but the time stamp which is passed to skb or PTP clock consist of only 32 bit time
value
The driver handles this already.
Yes, I do agree that driver handles it. As Half roll over and Full roll over events are not handled in the driver, I am just curious how will the misaligned TS would be handled and also in cpts set time, the Lower 32 bit time is written to CPTS counter
Quoted 9 lines
Quoted 2 lines
* CPTS interrupts should be utilized to service Half and Full roll
over
Quoted 1 line
events as it is non sync events with respect to get/set time and
PTP
Quoted 1 line
pkt Tx/Rx
Nope, no need for interrupts, since we already have a better way to handle this.
Since we poll for the 32bit over flow for every HZ * 8 cycle, won't there be a system overhead. If the CPTS ref clock is changed according to the ptp freq adjust api, how will the timecounter take care of change in frequency
Quoted 5 lines
Quoted 3 lines
* CPTS Time which is obtained from hardware is not actually a nano seconds as the CPTS ref clock is tied to 250MHz for AM335x.
Did you even look at the code in my patch?
I had gone through the patch, but the same driver can be used in TI814x where the user has the option to change the frequency from 250MHz may to 1GHz also, I thought of how it will be handled if we fix the multiplication factor
Quoted 6 lines
Quoted 3 lines
* CPSW register mapping done in this patch series removes the CPSW driver support for previous version found in TI814x
In which Linux version (or commit) did this driver appear? I never saw it.
The current driver which is in vanilla kernel doesn't use extended slave address which are conflict between TI814x CPSW IP version and AM335x CPSW IP version. I have just posted my version of CPTS implementation. May be we can work together make the driver compatible with both CPSW versions
Quoted 8 lines
Quoted 2 lines
* CPSW Time stamping is done only for port 0 and port 1 is not done
Yes, you are right, and it is strange that the hardware time stamps on the external ports of the switch, and not at the host port as it should. Of course it does present us with a problem, since we cannot reasonably have both ports time stamping at the same time. I propose simply using a device tree attribute to tell which port to activate.
Since CPSW is a 3port Switch we should not fix time stamping will be enabled only for slave 0 or passing slave number through DT. Its better if we can configure both the slaves. This can be tested with EVM-sk which has both the slave ports pinned out.
Quoted 3 lines
Thanks,
Richard
Quoted 5 lines · Mugunthan V
Yes, I do agree that driver handles it. As Half roll over and Full roll over events are not handled in the driver, I am just curious how will the misaligned TS would be handled and also in cpts set time, the Lower 32 bit time is written to CPTS counter
#include <linux/clocksource.h>
Quoted 4 lines
Since we poll for the 32bit over flow for every HZ * 8 cycle, won't there be a system overhead. If the CPTS ref clock is changed according to the ptp freq adjust api, how will the timecounter take care of change in frequency
There is nothing to do here. What are you asking?
Quoted 4 lines
The current driver which is in vanilla kernel doesn't use extended slave address which are conflict between TI814x CPSW IP version and AM335x CPSW IP version. I have just posted my version of CPTS implementation. May be we can work together make the driver compatible with both CPSW versions
Okay.
Quoted 4 lines
Since CPSW is a 3port Switch we should not fix time stamping will be enabled only for slave 0 or passing slave number through DT. Its better if we can configure both the slaves. This can be tested with EVM-sk which has both the slave ports pinned out.
I hope that you meant, "better if we can configure _either_ slave." Considering how SO_TIMESTAMPING works, you can't use both at once.
Thanks,
Richard
Quoted 10 lines
-----Original Message-----
From: Richard Cochran [mailto:richardcochran at gmail.com]
Sent: Wednesday, October 17, 2012 11:57 PM
To: N, Mugunthan V
Cc: netdev at vger.kernel.org; linux-arm-kernel at lists.infradead.org; David Miller; Chemparathy, Cyril; Govindarajan, Sriramakrishnan
Subject: Re: [PATCH V2 0/7] support the cpts found on am335x devicesQuoted 1 line · Mugunthan V
Quoted 8 lines
Quoted 1 line
Yes, I do agree that driver handles it. As Half roll over and Full
roll
Quoted 2 lines
over events are not handled in the driver, I am just curious how will the misaligned TS would be handled and also in cpts set time, the
Lower
Quoted 1 line
32 bit time is written to CPTS counter
#include <
linux/clocksource.h>
I think the timecounter_init initializes only the software. But still I am not clear how the time given in cpts_ptp_settime will be projected to hardware. Can you correct me if I am wrong.
Quoted 9 lines
Quoted 3 lines
Since we poll for the 32bit over flow for every HZ * 8 cycle, won't there be a system overhead. If the CPTS ref clock is changed
according
Quoted 1 line
to the ptp freq adjust api, how will the timecounter take care of
change
Quoted 1 line
in frequency
There is nothing to do here. What are you asking?
I think instead of fixing the driver to AM335X, let's make the driver generic as the same driver can be used to TI814X, TI813X and other upcoming platforms TI811X where the CPTS ref clock can be changed as per usage requirement.
Quoted 13 lines
Quoted 2 lines
The current driver which is in vanilla kernel doesn't use extended
slave
Quoted 1 line
address which are conflict between TI814x CPSW IP version and AM335x
CPSW
Quoted 1 line
IP version. I have just posted my version of CPTS implementation. May
be
Quoted 1 line
we can work together make the driver compatible with both CPSW
versions
Okay.
Quoted 1 line
Since CPSW is a 3port Switch we should not fix time stamping will be
Quoted 9 lines
enabled
Quoted 2 lines
only for slave 0 or passing slave number through DT. Its better if we can configure both the slaves. This can be tested with EVM-sk which
has
Quoted 1 line
both the slave ports pinned out.
I hope that you meant, "better if we can configure _either_ slave." Considering how
SO_TIMESTAMPINGworks, you can't use both at once.
Since CPSW as a Ethernet switch, the PTP packet can be delivered to any downstream port. So if we fix the PTP time stamping to one port then the driver won't receive time stamping information when the packet is delivered to the other port.
Regards
Mugunthan V N
Quoted 4 lines · Mugunthan V
I think the
timecounter_initinitializes only the software. But still I am not clear how the time given incpts_ptp_settimewill be projected to hardware. Can you correct me if I am wrong.
Look at the settime function:
+static int cpts_ptp_settime(struct ptp_clock_info *ptp,
+ const struct timespec *ts)
+{
+ u64 ns;
+ unsigned long flags;
+ struct cpts *cpts = container_of(ptp, struct cpts, info);
+
+ ns = ts->tv_sec * 1000000000ULL;
+ ns += ts->tv_nsec;
+
+ spin_lock_irqsave(&cpts->lock, flags);
+ timecounter_init(&cpts->tc, &cpts->cc, ns);
+ spin_unlock_irqrestore(&cpts->lock, flags);
+
+ return 0;
+}
Then, look at the implementation of timecounter_init().
Quoted 5 lines
Quoted 5 lines
Quoted 2 lines
Since we poll for the 32bit over flow for every HZ * 8 cycle, won't there be a system overhead. If the CPTS ref clock is changed
according
Quoted 1 line
to the ptp freq adjust api, how will the timecounter take care of
change
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
in frequency
There is nothing to do here. What are you asking?
I think instead of fixing the driver to AM335X, let's make the driver generic as the same driver can be used to TI814X, TI813X and other upcoming platforms TI811X where the CPTS ref clock can be changed as per usage requirement.
Now I see what your are worried about, but it really isn't a big problem. The solution in your driver of doing a 64 bit division in the hot path is unattractive and unnecessary. We can accomodate variable reference clock frequencies using a board specific DT, just as we do for gianfar today.
Let's just get the am335x working, shall we? Until we actually have the other boards working, all this talk about TI81xx is really just talk. I mean, ATM the CPSW does not work on *any* board at all.
Quoted 8 lines
Quoted 3 lines
I hope that you meant, "better if we can configure _either_ slave." Considering how
SO_TIMESTAMPINGworks, you can't use both at once.Since CPSW as a Ethernet switch, the PTP packet can be delivered to any downstream port. So if we fix the PTP time stamping to one port then the driver won't receive time stamping information when the packet is delivered to the other port.
And just how is this supposed to work with SO_TIMESTAMPING?
Thanks,
Richard