mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-20 23:38:21 +07:00
Merge branch 'net-ethernet-ti-k3-introduce-common-platform-time-sync-driver-cpts'
Grygorii Strashko says: ==================== net: ethernet: ti: k3: introduce common platform time sync driver - cpts This series introduced support for significantly upgraded TI A65x/J721E Common platform time sync (CPTS) modules which are part of AM65xx Time Synchronization Architecture [1]. The TI A65x/J721E now contain more than one CPTS instance: - MCU CPSW CPTS (IEEE 1588 compliant) - Main NAVSS CPTS (central) - PCIe CPTS(s) (PTM compliant) - J721E: Main CPSW9g CPTS (IEEE 1588 compliant) which can work as separately as interact to each other through Time Sync Router (TSR) and Compare Event Router (CER). In addition there are also ICSS-G IEP blocks which can perform similar timsync functions, but require FW support. More info also available in TRM [2][3]. Not all above modules are available to the Linux by as of now as some of them are reserved for RTOS/FW purposes. The scope of this submission is TI A65x/J721E CPSW CPTS and Main NAVSS CPTS, and TSR was used for testing purposes. +---------------------------+ | MCU CPSW | +-------------------+ +------------------------+ | TS | | Main Navss CPTS | | Time Sync Router (TSR) | | +-------------+ | | | | | | | | | | HW1_TS +<----------+ | | +--------v-----+ +--+--+ | | | | | | CPTS | |Port | | ... | | | X+-->HW1_TS | | | | HW8_TS <------------<---------+ | X|-->HW2_TS | +--^--+ | | | | +--------------->HW3_TS | | | | | | | +--------------->HW4_TS | | | | | | | | | | | | | | | | | | | | | | | | Genf0 +-----------> (A)---------+ +<--------------+Genf0 | | | | | | | | | | | | | | ... | | +-----------> <---------------+Genf1 ESTf+-------+ | | | | | | | | | | | | | | +--------------+ | | Genf8 +---------->+ | | | | | | SYNC0 ... SYNC3 | | | +-------------------+ +------+------------+----+ +---------------------------+ + + X X (A) shows possible routing path for MCU CPSW CPTS Genf0 signal as an example. Main features of the new TI A65x/J721E CPTS modules are: - 64-bit timestamp/counter mode support in ns by using add_val - implemented in HW PPM and nudge adjustment. - control of time sync events via interrupt or polling - selection of multiple external reference clock sources - hardware timestamp of ext. inputs events (HWx_TS_PUSH) - periodic generator function outputs (TS_GENFx) - (CPSW only) Ethernet Enhanced Scheduled Traffic Operations (CPTS_ESTFn), which drives TSN schedule - timestamping of all RX packets bypassing CPTS FIFO Patch 1 - DT bindings Patch 2 - the AM65x/J721E driver Patch 3 - enables packet timestamping support in TI AM65x/J721E MCU CPSW driver. Patches 4-7 - DT updates. === PTP Testing: phc2sys -s CLOCK_REALTIME -c eth0 -m -O 0 -u30 phc2sys[627.331]: eth0 rms 409912446712787392 max 1587584079521858304 freq -6665 +/- 35040 delay 832 +/- 27 phc2sys[657.335]: eth0 rms 33 max 66 freq -0 +/- 28 delay 820 +/- 30 phc2sys[687.339]: eth0 rms 37 max 70 freq -1 +/- 32 delay 830 +/- 29 phc2sys[717.343]: eth0 rms 33 max 71 freq -0 +/- 29 delay 828 +/- 23 phc2sys[747.346]: eth0 rms 35 max 75 freq -0 +/- 31 delay 829 +/- 26 phc2sys[777.350]: eth0 rms 37 max 68 freq -1 +/- 32 delay 825 +/- 25 phc2sys[807.354]: eth0 rms 28 max 57 freq -1 +/- 25 delay 824 +/- 21 phc2sys[837.358]: eth0 rms 43 max 81 freq -1 +/- 37 delay 836 +/- 23 phc2sys[867.361]: eth0 rms 33 max 74 freq +0 +/- 29 delay 828 +/- 24 phc2sys[897.365]: eth0 rms 35 max 77 freq -2 +/- 30 delay 824 +/- 25 phc2sys[927.369]: eth0 rms 28 max 50 freq +0 +/- 25 delay 825 +/- 25 ptp4l -P -2 -H -i eth0 -l 6 -m -q -p /dev/ptp1 -f ptp.cfg -s ptp4l[22095.754]: port 1: MASTER to UNCALIBRATED on RS_SLAVE ptp4l[22097.754]: port 1: UNCALIBRATED to SLAVE on MASTER_CLOCK_SELECTED ptp4l[22159.757]: rms 317 max 1418 freq +79 +/- 186 delay 410 +/- 1 ptp4l[22223.760]: rms 9 max 24 freq +42 +/- 12 delay 409 +/- 1 ptp4l[22287.763]: rms 10 max 28 freq +41 +/- 11 delay 410 +/- 1 ptp4l[22351.767]: rms 10 max 26 freq +34 +/- 12 delay 410 +/- 1 ptp4l[22415.770]: rms 10 max 26 freq +49 +/- 14 delay 410 +/- 1 === Ext. HW_TS and Genf testing: For testing purposes Time Sync Router (TSR) can be modeled in DT as pin controller + timesync_router: timesync_router@A40000 { + compatible = "pinctrl-single"; + reg = <0x0 0xA40000 0x0 0x800>; + #address-cells = <1>; + #size-cells = <0>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x800007ff>; + }; then signals routing can be done in board file, for example: +#define TS_OFFSET(pa, val) (0x4+(pa)*4) (0x80000000 | val) + +×ync_router { + pinctrl-names = "default"; + pinctrl-0 = <&mcu_cpts>; + + /* Example of the timesync routing */ + mcu_cpts: mcu_cpts { + pinctrl-single,pins = < + /* [cpts genf1] in13 -> out25 [cpts hw4_push] */ + TS_OFFSET(25, 13) + /* [cpts genf1] in13 -> out0 [main cpts hw1_push] */ + TS_OFFSET(0, 13) + /* [main cpts genf0] in4 -> out1 [main cpts hw2_push] */ + TS_OFFSET(1, 4) + /* [main cpts genf0] in4 -> out24 [cpts hw3_push] */ + TS_OFFSET(24, 4) + >; + }; +}; will create link: cpsw cpts Genf1 -> main cpts hw1_push -> cpsw cpts hw4_push main cpts Genf0 -> main cpts hw2_push -> cpsw cpts hw3_push testptp -d /dev/ptp0 -i 0 -p 1000000000 periodic output request okay testptp -d /dev/ptp0 -i 1 -e 5 external time stamp request okay event index 1 at 22583.000000025 event index 1 at 22584.000000025 event index 1 at 22585.000000025 event index 1 at 22586.000000025 event index 1 at 22587.000000025 testptp -d /dev/ptp1 -i 2 -e 5 external time stamp request okay event index 2 at 1587606764.249304554 event index 2 at 1587606765.249304467 event index 2 at 1587606766.249304380 event index 2 at 1587606767.249304293 event index 2 at 1587606768.249304206 [1] https://www.ti.com/lit/pdf/spracp7 [2] https://www.ti.com/lit/pdf/sprz452 [3] https://www.ti.com/lit/pdf/spruil1 ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
ea84c84290
@ -144,6 +144,13 @@ patternProperties:
|
||||
description:
|
||||
CPSW MDIO bus.
|
||||
|
||||
"^cpts$":
|
||||
type: object
|
||||
allOf:
|
||||
- $ref: "ti,am654-cpts.yaml#"
|
||||
description:
|
||||
CPSW Common Platform Time Sync (CPTS) module.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
152
Documentation/devicetree/bindings/net/ti,k3-am654-cpts.yaml
Normal file
152
Documentation/devicetree/bindings/net/ti,k3-am654-cpts.yaml
Normal file
@ -0,0 +1,152 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/ti,am654-cpts.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: The TI AM654x/J721E Common Platform Time Sync (CPTS) module Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Grygorii Strashko <grygorii.strashko@ti.com>
|
||||
- Sekhar Nori <nsekhar@ti.com>
|
||||
|
||||
description: |+
|
||||
The TI AM654x/J721E CPTS module is used to facilitate host control of time
|
||||
sync operations.
|
||||
Main features of CPTS module are
|
||||
- selection of multiple external clock sources
|
||||
- Software control of time sync events via interrupt or polling
|
||||
- 64-bit timestamp mode in ns with PPM and nudge adjustment.
|
||||
- hardware timestamp push inputs (HWx_TS_PUSH)
|
||||
- timestamp counter compare output (TS_COMP)
|
||||
- timestamp counter bit output (TS_SYNC)
|
||||
- periodic Generator function outputs (TS_GENFx)
|
||||
- Ethernet Enhanced Scheduled Traffic Operations (CPTS_ESTFn) (TSN)
|
||||
- external hardware timestamp push inputs (HWx_TS_PUSH) timestamping
|
||||
|
||||
Depending on integration it enables compliance with the IEEE 1588-2008
|
||||
standard for a precision clock synchronization protocol, Ethernet Enhanced
|
||||
Scheduled Traffic Operations (CPTS_ESTFn) and PCIe Subsystem Precision Time
|
||||
Measurement (PTM).
|
||||
|
||||
TI AM654x/J721E SoCs has several similar CPTS modules integrated into the
|
||||
different parts of the system which could be synchronized with each other
|
||||
- Main CPTS
|
||||
- MCU CPSW CPTS with IEEE 1588-2008 support
|
||||
- PCIe subsystem CPTS for PTM support
|
||||
|
||||
Depending on CPTS module integration and when CPTS is integral part of
|
||||
another module (MCU CPSW for example) "compatible" and "reg" can
|
||||
be omitted - parent module is fully responsible for CPTS enabling and
|
||||
configuration.
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: "^cpts(@.*|-[0-9a-f])*$"
|
||||
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: ti,am65-cpts
|
||||
- const: ti,j721e-cpts
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
description:
|
||||
The physical base address and size of CPTS IO range
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: cpts
|
||||
|
||||
clocks:
|
||||
description: CPTS reference clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: cpts
|
||||
|
||||
interrupts-extended:
|
||||
items:
|
||||
- description: CPTS events interrupt
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: "cpts"
|
||||
|
||||
ti,cpts-ext-ts-inputs:
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
maximum: 8
|
||||
description:
|
||||
Number of hardware timestamp push inputs (HWx_TS_PUSH)
|
||||
|
||||
ti,cpts-periodic-outputs:
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
maximum: 8
|
||||
description:
|
||||
Number of timestamp Generator function outputs (TS_GENFx)
|
||||
|
||||
refclk-mux:
|
||||
type: object
|
||||
description: CPTS reference clock multiplexer clock
|
||||
properties:
|
||||
'#clock-cells':
|
||||
const: 0
|
||||
|
||||
clocks:
|
||||
maxItems: 8
|
||||
|
||||
assigned-clocks:
|
||||
maxItems: 1
|
||||
|
||||
assigned-clocks-parents:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- clocks
|
||||
|
||||
required:
|
||||
- clocks
|
||||
- clock-names
|
||||
- interrupts-extended
|
||||
- interrupt-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
cpts@310d0000 {
|
||||
compatible = "ti,am65-cpts";
|
||||
reg = <0x0 0x310d0000 0x0 0x400>;
|
||||
reg-names = "cpts";
|
||||
clocks = <&main_cpts_mux>;
|
||||
clock-names = "cpts";
|
||||
interrupts-extended = <&k3_irq 163 0 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "cpts";
|
||||
ti,cpts-periodic-outputs = <6>;
|
||||
ti,cpts-ext-ts-inputs = <8>;
|
||||
|
||||
main_cpts_mux: refclk-mux {
|
||||
#clock-cells = <0>;
|
||||
clocks = <&k3_clks 118 5>, <&k3_clks 118 11>,
|
||||
<&k3_clks 157 91>, <&k3_clks 157 77>,
|
||||
<&k3_clks 157 102>, <&k3_clks 157 80>,
|
||||
<&k3_clks 120 3>, <&k3_clks 121 3>;
|
||||
assigned-clocks = <&main_cpts_mux>;
|
||||
assigned-clock-parents = <&k3_clks 118 11>;
|
||||
};
|
||||
};
|
||||
- |
|
||||
|
||||
cpts {
|
||||
clocks = <&k3_clks 18 2>;
|
||||
clock-names = "cpts";
|
||||
interrupts-extended = <&gic500 GIC_SPI 858 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "cpts";
|
||||
ti,cpts-ext-ts-inputs = <4>;
|
||||
ti,cpts-periodic-outputs = <2>;
|
||||
};
|
@ -570,6 +570,28 @@ main_udmap: dma-controller@31150000 {
|
||||
<0x5>; /* RX_CHAN */
|
||||
ti,sci-rm-range-rflow = <0x6>; /* GP RFLOW */
|
||||
};
|
||||
|
||||
cpts@310d0000 {
|
||||
compatible = "ti,am65-cpts";
|
||||
reg = <0x0 0x310d0000 0x0 0x400>;
|
||||
reg-names = "cpts";
|
||||
clocks = <&main_cpts_mux>;
|
||||
clock-names = "cpts";
|
||||
interrupts-extended = <&intr_main_navss 163 0>;
|
||||
interrupt-names = "cpts";
|
||||
ti,cpts-periodic-outputs = <6>;
|
||||
ti,cpts-ext-ts-inputs = <8>;
|
||||
|
||||
main_cpts_mux: refclk-mux {
|
||||
#clock-cells = <0>;
|
||||
clocks = <&k3_clks 118 5>, <&k3_clks 118 11>,
|
||||
<&k3_clks 118 6>, <&k3_clks 118 3>,
|
||||
<&k3_clks 118 8>, <&k3_clks 118 14>,
|
||||
<&k3_clks 120 3>, <&k3_clks 121 3>;
|
||||
assigned-clocks = <&main_cpts_mux>;
|
||||
assigned-clock-parents = <&k3_clks 118 5>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
main_gpio0: main_gpio0@600000 {
|
||||
|
@ -247,5 +247,24 @@ davinci_mdio: mdio@f00 {
|
||||
clock-names = "fck";
|
||||
bus_freq = <1000000>;
|
||||
};
|
||||
|
||||
cpts {
|
||||
clocks = <&mcu_cpsw_cpts_mux>;
|
||||
clock-names = "cpts";
|
||||
interrupts-extended = <&gic500 GIC_SPI 570 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "cpts";
|
||||
ti,cpts-ext-ts-inputs = <4>;
|
||||
ti,cpts-periodic-outputs = <2>;
|
||||
|
||||
mcu_cpsw_cpts_mux: refclk-mux {
|
||||
#clock-cells = <0>;
|
||||
clocks = <&k3_clks 118 5>, <&k3_clks 118 11>,
|
||||
<&k3_clks 118 6>, <&k3_clks 118 3>,
|
||||
<&k3_clks 118 8>, <&k3_clks 118 14>,
|
||||
<&k3_clks 120 3>, <&k3_clks 121 3>;
|
||||
assigned-clocks = <&mcu_cpsw_cpts_mux>;
|
||||
assigned-clock-parents = <&k3_clks 118 5>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -254,6 +254,18 @@ main_udmap: dma-controller@31150000 {
|
||||
<0x0c>; /* RX_UHCHAN */
|
||||
ti,sci-rm-range-rflow = <0x00>; /* GP RFLOW */
|
||||
};
|
||||
|
||||
cpts@310d0000 {
|
||||
compatible = "ti,j721e-cpts";
|
||||
reg = <0x0 0x310d0000 0x0 0x400>;
|
||||
reg-names = "cpts";
|
||||
clocks = <&k3_clks 201 1>;
|
||||
clock-names = "cpts";
|
||||
interrupts-extended = <&main_navss_intr 201 0>;
|
||||
interrupt-names = "cpts";
|
||||
ti,cpts-periodic-outputs = <6>;
|
||||
ti,cpts-ext-ts-inputs = <8>;
|
||||
};
|
||||
};
|
||||
|
||||
main_pmx0: pinmux@11c000 {
|
||||
|
@ -338,5 +338,14 @@ davinci_mdio: mdio@f00 {
|
||||
clock-names = "fck";
|
||||
bus_freq = <1000000>;
|
||||
};
|
||||
|
||||
cpts {
|
||||
clocks = <&k3_clks 18 2>;
|
||||
clock-names = "cpts";
|
||||
interrupts-extended = <&gic500 GIC_SPI 858 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "cpts";
|
||||
ti,cpts-ext-ts-inputs = <4>;
|
||||
ti,cpts-periodic-outputs = <2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -100,6 +100,7 @@ config TI_K3_AM65_CPSW_NUSS
|
||||
depends on ARCH_K3 && OF && TI_K3_UDMA_GLUE_LAYER
|
||||
select TI_DAVINCI_MDIO
|
||||
imply PHY_TI_GMII_SEL
|
||||
imply TI_AM65_CPTS
|
||||
help
|
||||
This driver supports TI K3 AM654/J721E CPSW2G Ethernet SubSystem.
|
||||
The two-port Gigabit Ethernet MAC (MCU_CPSW0) subsystem provides
|
||||
@ -110,6 +111,20 @@ config TI_K3_AM65_CPSW_NUSS
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called ti-am65-cpsw-nuss.
|
||||
|
||||
config TI_K3_AM65_CPTS
|
||||
tristate "TI K3 AM65x CPTS"
|
||||
depends on ARCH_K3 && OF && PTP_1588_CLOCK
|
||||
depends on PTP_1588_CLOCK
|
||||
select NET_PTP_CLASSIFY
|
||||
help
|
||||
Say y here to support the TI K3 AM65x CPTS with 1588 features such as
|
||||
PTP hardware clock for each CPTS device and network packets
|
||||
timestamping where applicable.
|
||||
Depending on integration CPTS blocks enable compliance with
|
||||
the IEEE 1588-2008 standard for a precision clock synchronization
|
||||
protocol, Ethernet Enhanced Scheduled Traffic Operations (CPTS_ESTFn)
|
||||
and PCIe Subsystem Precision Time Measurement (PTM).
|
||||
|
||||
config TI_KEYSTONE_NETCP
|
||||
tristate "TI Keystone NETCP Core Support"
|
||||
select TI_DAVINCI_MDIO
|
||||
|
@ -26,3 +26,4 @@ keystone_netcp_ethss-y := netcp_ethss.o netcp_sgmii.o netcp_xgbepcsr.o cpsw_ale.
|
||||
|
||||
obj-$(CONFIG_TI_K3_AM65_CPSW_NUSS) += ti-am65-cpsw-nuss.o
|
||||
ti-am65-cpsw-nuss-y := am65-cpsw-nuss.o cpsw_sl.o am65-cpsw-ethtool.o cpsw_ale.o k3-cppi-desc-pool.o
|
||||
obj-$(CONFIG_TI_K3_AM65_CPTS) += am65-cpts.o
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "am65-cpsw-nuss.h"
|
||||
#include "cpsw_ale.h"
|
||||
#include "am65-cpts.h"
|
||||
|
||||
#define AM65_CPSW_REGDUMP_VER 0x1
|
||||
|
||||
@ -694,6 +695,27 @@ static void am65_cpsw_get_ethtool_stats(struct net_device *ndev,
|
||||
hw_stats[i].offset);
|
||||
}
|
||||
|
||||
static int am65_cpsw_get_ethtool_ts_info(struct net_device *ndev,
|
||||
struct ethtool_ts_info *info)
|
||||
{
|
||||
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
|
||||
|
||||
if (!IS_ENABLED(CONFIG_TI_K3_AM65_CPTS))
|
||||
return ethtool_op_get_ts_info(ndev, info);
|
||||
|
||||
info->so_timestamping =
|
||||
SOF_TIMESTAMPING_TX_HARDWARE |
|
||||
SOF_TIMESTAMPING_TX_SOFTWARE |
|
||||
SOF_TIMESTAMPING_RX_HARDWARE |
|
||||
SOF_TIMESTAMPING_RX_SOFTWARE |
|
||||
SOF_TIMESTAMPING_SOFTWARE |
|
||||
SOF_TIMESTAMPING_RAW_HARDWARE;
|
||||
info->phc_index = am65_cpts_phc_index(common->cpts);
|
||||
info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);
|
||||
info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 am65_cpsw_get_ethtool_priv_flags(struct net_device *ndev)
|
||||
{
|
||||
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
|
||||
@ -730,7 +752,7 @@ const struct ethtool_ops am65_cpsw_ethtool_ops_slave = {
|
||||
.get_sset_count = am65_cpsw_get_sset_count,
|
||||
.get_strings = am65_cpsw_get_strings,
|
||||
.get_ethtool_stats = am65_cpsw_get_ethtool_stats,
|
||||
.get_ts_info = ethtool_op_get_ts_info,
|
||||
.get_ts_info = am65_cpsw_get_ethtool_ts_info,
|
||||
.get_priv_flags = am65_cpsw_get_ethtool_priv_flags,
|
||||
.set_priv_flags = am65_cpsw_set_ethtool_priv_flags,
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "cpsw_sl.h"
|
||||
#include "am65-cpsw-nuss.h"
|
||||
#include "k3-cppi-desc-pool.h"
|
||||
#include "am65-cpts.h"
|
||||
|
||||
#define AM65_CPSW_SS_BASE 0x0
|
||||
#define AM65_CPSW_SGMII_BASE 0x100
|
||||
@ -668,6 +669,18 @@ static void am65_cpsw_nuss_rx_cleanup(void *data, dma_addr_t desc_dma)
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
static void am65_cpsw_nuss_rx_ts(struct sk_buff *skb, u32 *psdata)
|
||||
{
|
||||
struct skb_shared_hwtstamps *ssh;
|
||||
u64 ns;
|
||||
|
||||
ns = ((u64)psdata[1] << 32) | psdata[0];
|
||||
|
||||
ssh = skb_hwtstamps(skb);
|
||||
memset(ssh, 0, sizeof(*ssh));
|
||||
ssh->hwtstamp = ns_to_ktime(ns);
|
||||
}
|
||||
|
||||
/* RX psdata[2] word format - checksum information */
|
||||
#define AM65_CPSW_RX_PSD_CSUM_ADD GENMASK(15, 0)
|
||||
#define AM65_CPSW_RX_PSD_CSUM_ERR BIT(16)
|
||||
@ -745,6 +758,9 @@ static int am65_cpsw_nuss_rx_packets(struct am65_cpsw_common *common,
|
||||
skb->dev = ndev;
|
||||
|
||||
psdata = cppi5_hdesc_get_psdata(desc_rx);
|
||||
/* add RX timestamp */
|
||||
if (port->rx_ts_enabled)
|
||||
am65_cpsw_nuss_rx_ts(skb, psdata);
|
||||
csum_info = psdata[2];
|
||||
dev_dbg(dev, "%s rx csum_info:%#x\n", __func__, csum_info);
|
||||
|
||||
@ -904,6 +920,8 @@ static int am65_cpsw_nuss_tx_compl_packets(struct am65_cpsw_common *common,
|
||||
|
||||
ndev = skb->dev;
|
||||
|
||||
am65_cpts_tx_timestamp(common->cpts, skb);
|
||||
|
||||
ndev_priv = netdev_priv(ndev);
|
||||
stats = this_cpu_ptr(ndev_priv->stats);
|
||||
u64_stats_update_begin(&stats->syncp);
|
||||
@ -995,6 +1013,10 @@ static netdev_tx_t am65_cpsw_nuss_ndo_slave_xmit(struct sk_buff *skb,
|
||||
/* padding enabled in hw */
|
||||
pkt_len = skb_headlen(skb);
|
||||
|
||||
/* SKB TX timestamp */
|
||||
if (port->tx_ts_enabled)
|
||||
am65_cpts_prep_tx_timestamp(common->cpts, skb);
|
||||
|
||||
q_idx = skb_get_queue_mapping(skb);
|
||||
dev_dbg(dev, "%s skb_queue:%d\n", __func__, q_idx);
|
||||
|
||||
@ -1158,6 +1180,111 @@ static int am65_cpsw_nuss_ndo_slave_set_mac_address(struct net_device *ndev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int am65_cpsw_nuss_hwtstamp_set(struct net_device *ndev,
|
||||
struct ifreq *ifr)
|
||||
{
|
||||
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
|
||||
struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
|
||||
u32 ts_ctrl, seq_id, ts_ctrl_ltype2, ts_vlan_ltype;
|
||||
struct hwtstamp_config cfg;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_TI_K3_AM65_CPTS))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
|
||||
return -EFAULT;
|
||||
|
||||
/* TX HW timestamp */
|
||||
switch (cfg.tx_type) {
|
||||
case HWTSTAMP_TX_OFF:
|
||||
case HWTSTAMP_TX_ON:
|
||||
break;
|
||||
default:
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
switch (cfg.rx_filter) {
|
||||
case HWTSTAMP_FILTER_NONE:
|
||||
port->rx_ts_enabled = false;
|
||||
break;
|
||||
case HWTSTAMP_FILTER_ALL:
|
||||
case HWTSTAMP_FILTER_SOME:
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
|
||||
case HWTSTAMP_FILTER_PTP_V2_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
|
||||
case HWTSTAMP_FILTER_NTP_ALL:
|
||||
port->rx_ts_enabled = true;
|
||||
cfg.rx_filter = HWTSTAMP_FILTER_ALL;
|
||||
break;
|
||||
default:
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
port->tx_ts_enabled = (cfg.tx_type == HWTSTAMP_TX_ON);
|
||||
|
||||
/* cfg TX timestamp */
|
||||
seq_id = (AM65_CPSW_TS_SEQ_ID_OFFSET <<
|
||||
AM65_CPSW_PN_TS_SEQ_ID_OFFSET_SHIFT) | ETH_P_1588;
|
||||
|
||||
ts_vlan_ltype = ETH_P_8021Q;
|
||||
|
||||
ts_ctrl_ltype2 = ETH_P_1588 |
|
||||
AM65_CPSW_PN_TS_CTL_LTYPE2_TS_107 |
|
||||
AM65_CPSW_PN_TS_CTL_LTYPE2_TS_129 |
|
||||
AM65_CPSW_PN_TS_CTL_LTYPE2_TS_130 |
|
||||
AM65_CPSW_PN_TS_CTL_LTYPE2_TS_131 |
|
||||
AM65_CPSW_PN_TS_CTL_LTYPE2_TS_132 |
|
||||
AM65_CPSW_PN_TS_CTL_LTYPE2_TS_319 |
|
||||
AM65_CPSW_PN_TS_CTL_LTYPE2_TS_320 |
|
||||
AM65_CPSW_PN_TS_CTL_LTYPE2_TS_TTL_NONZERO;
|
||||
|
||||
ts_ctrl = AM65_CPSW_TS_EVENT_MSG_TYPE_BITS <<
|
||||
AM65_CPSW_PN_TS_CTL_MSG_TYPE_EN_SHIFT;
|
||||
|
||||
if (port->tx_ts_enabled)
|
||||
ts_ctrl |= AM65_CPSW_TS_TX_ANX_ALL_EN |
|
||||
AM65_CPSW_PN_TS_CTL_TX_VLAN_LT1_EN;
|
||||
|
||||
writel(seq_id, port->port_base + AM65_CPSW_PORTN_REG_TS_SEQ_LTYPE_REG);
|
||||
writel(ts_vlan_ltype, port->port_base +
|
||||
AM65_CPSW_PORTN_REG_TS_VLAN_LTYPE_REG);
|
||||
writel(ts_ctrl_ltype2, port->port_base +
|
||||
AM65_CPSW_PORTN_REG_TS_CTL_LTYPE2);
|
||||
writel(ts_ctrl, port->port_base + AM65_CPSW_PORTN_REG_TS_CTL);
|
||||
|
||||
/* en/dis RX timestamp */
|
||||
am65_cpts_rx_enable(common->cpts, port->rx_ts_enabled);
|
||||
|
||||
return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
|
||||
}
|
||||
|
||||
static int am65_cpsw_nuss_hwtstamp_get(struct net_device *ndev,
|
||||
struct ifreq *ifr)
|
||||
{
|
||||
struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
|
||||
struct hwtstamp_config cfg;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_TI_K3_AM65_CPTS))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
cfg.flags = 0;
|
||||
cfg.tx_type = port->tx_ts_enabled ?
|
||||
HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
|
||||
cfg.rx_filter = port->rx_ts_enabled ?
|
||||
HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE;
|
||||
|
||||
return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
|
||||
}
|
||||
|
||||
static int am65_cpsw_nuss_ndo_slave_ioctl(struct net_device *ndev,
|
||||
struct ifreq *req, int cmd)
|
||||
{
|
||||
@ -1166,6 +1293,13 @@ static int am65_cpsw_nuss_ndo_slave_ioctl(struct net_device *ndev,
|
||||
if (!netif_running(ndev))
|
||||
return -EINVAL;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCSHWTSTAMP:
|
||||
return am65_cpsw_nuss_hwtstamp_set(ndev, req);
|
||||
case SIOCGHWTSTAMP:
|
||||
return am65_cpsw_nuss_hwtstamp_get(ndev, req);
|
||||
}
|
||||
|
||||
if (!port->slave.phy)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
@ -1531,6 +1665,40 @@ static int am65_cpsw_am654_get_efuse_macid(struct device_node *of_node,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int am65_cpsw_init_cpts(struct am65_cpsw_common *common)
|
||||
{
|
||||
struct device *dev = common->dev;
|
||||
struct device_node *node;
|
||||
struct am65_cpts *cpts;
|
||||
void __iomem *reg_base;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_TI_K3_AM65_CPTS))
|
||||
return 0;
|
||||
|
||||
node = of_get_child_by_name(dev->of_node, "cpts");
|
||||
if (!node) {
|
||||
dev_err(dev, "%s cpts not found\n", __func__);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
reg_base = common->cpsw_base + AM65_CPSW_NU_CPTS_BASE;
|
||||
cpts = am65_cpts_create(dev, reg_base, node);
|
||||
if (IS_ERR(cpts)) {
|
||||
int ret = PTR_ERR(cpts);
|
||||
|
||||
if (ret == -EOPNOTSUPP) {
|
||||
dev_info(dev, "cpts disabled\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_err(dev, "cpts create err %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
common->cpts = cpts;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int am65_cpsw_nuss_init_slave_ports(struct am65_cpsw_common *common)
|
||||
{
|
||||
struct device_node *node, *port_np;
|
||||
@ -1899,6 +2067,10 @@ static int am65_cpsw_nuss_probe(struct platform_device *pdev)
|
||||
goto err_of_clear;
|
||||
}
|
||||
|
||||
ret = am65_cpsw_init_cpts(common);
|
||||
if (ret)
|
||||
goto err_of_clear;
|
||||
|
||||
/* init ports */
|
||||
for (i = 0; i < common->port_num; i++)
|
||||
am65_cpsw_nuss_slave_disable_unused(&common->ports[i]);
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
struct am65_cpts;
|
||||
|
||||
#define HOST_PORT_NUM 0
|
||||
|
||||
#define AM65_CPSW_MAX_TX_QUEUES 8
|
||||
@ -37,6 +39,8 @@ struct am65_cpsw_port {
|
||||
void __iomem *stat_base;
|
||||
bool disabled;
|
||||
struct am65_cpsw_slave_data slave;
|
||||
bool tx_ts_enabled;
|
||||
bool rx_ts_enabled;
|
||||
};
|
||||
|
||||
struct am65_cpsw_host {
|
||||
@ -96,8 +100,8 @@ struct am65_cpsw_common {
|
||||
|
||||
u32 nuss_ver;
|
||||
u32 cpsw_ver;
|
||||
|
||||
bool pf_p0_rx_ptype_rrobin;
|
||||
struct am65_cpts *cpts;
|
||||
};
|
||||
|
||||
struct am65_cpsw_ndev_stats {
|
||||
|
1041
drivers/net/ethernet/ti/am65-cpts.c
Normal file
1041
drivers/net/ethernet/ti/am65-cpts.c
Normal file
File diff suppressed because it is too large
Load Diff
50
drivers/net/ethernet/ti/am65-cpts.h
Normal file
50
drivers/net/ethernet/ti/am65-cpts.h
Normal file
@ -0,0 +1,50 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/* TI K3 AM65 CPTS driver interface
|
||||
*
|
||||
* Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com
|
||||
*/
|
||||
|
||||
#ifndef K3_CPTS_H_
|
||||
#define K3_CPTS_H_
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
struct am65_cpts;
|
||||
|
||||
#if IS_ENABLED(CONFIG_TI_K3_AM65_CPTS)
|
||||
struct am65_cpts *am65_cpts_create(struct device *dev, void __iomem *regs,
|
||||
struct device_node *node);
|
||||
int am65_cpts_phc_index(struct am65_cpts *cpts);
|
||||
void am65_cpts_tx_timestamp(struct am65_cpts *cpts, struct sk_buff *skb);
|
||||
void am65_cpts_prep_tx_timestamp(struct am65_cpts *cpts, struct sk_buff *skb);
|
||||
void am65_cpts_rx_enable(struct am65_cpts *cpts, bool en);
|
||||
#else
|
||||
static inline struct am65_cpts *am65_cpts_create(struct device *dev,
|
||||
void __iomem *regs,
|
||||
struct device_node *node)
|
||||
{
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline int am65_cpts_phc_index(struct am65_cpts *cpts)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline void am65_cpts_tx_timestamp(struct am65_cpts *cpts,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void am65_cpts_prep_tx_timestamp(struct am65_cpts *cpts,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void am65_cpts_rx_enable(struct am65_cpts *cpts, bool en)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* K3_CPTS_H_ */
|
Loading…
Reference in New Issue
Block a user