summaryrefslogtreecommitdiff
path: root/drivers/net/dsa/hirschmann/hellcreek.c
diff options
context:
space:
mode:
authorKamil Alkhouri <kamil.alkhouri@hs-offenburg.de>2020-11-03 08:10:58 +0100
committerJakub Kicinski <kuba@kernel.org>2020-11-05 14:04:49 -0800
commitf0d4ba9eff75a79fccb7793f4d9f12303d458603 (patch)
treea429e4c4e9c6b3828be46d2a4f8086419981d24c /drivers/net/dsa/hirschmann/hellcreek.c
parentddd56dfe52c987d82964595902db0600970ef406 (diff)
net: dsa: hellcreek: Add support for hardware timestamping
The switch has the ability to take hardware generated time stamps per port for PTPv2 event messages in Rx and Tx direction. That is useful for achieving needed time synchronization precision for TSN devices/switches. So add support for it. There are two directions: * RX The switch has a single register per port to capture a timestamp. That mechanism is not used due to correlation problems. If the software processing is too slow and a PTPv2 event message is received before the previous one has been processed, false timestamps will be captured. Therefore, the switch can do "inline" timestamping which means it can insert the nanoseconds part of the timestamp directly into the PTPv2 event message. The reserved field (4 bytes) is leveraged for that. This might not be in accordance with (older) PTP standards, but is the only way to get reliable results. * TX In Tx direction there is no correlation problem, because the software and the driver has to ensure that only one event message is "on the fly". However, the switch provides also a mechanism to check whether a timestamp is lost. That can only happen when a timestamp is read and at this point another message is timestamped. So, that lost bit is checked just in case to indicate to the user that the driver or the software is somewhat buggy. Signed-off-by: Kamil Alkhouri <kamil.alkhouri@hs-offenburg.de> Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de> Acked-by: Richard Cochran <richardcochran@gmail.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net/dsa/hirschmann/hellcreek.c')
-rw-r--r--drivers/net/dsa/hirschmann/hellcreek.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/drivers/net/dsa/hirschmann/hellcreek.c b/drivers/net/dsa/hirschmann/hellcreek.c
index eb177f43ff16..dfa66f7260d6 100644
--- a/drivers/net/dsa/hirschmann/hellcreek.c
+++ b/drivers/net/dsa/hirschmann/hellcreek.c
@@ -26,6 +26,7 @@
#include "hellcreek.h"
#include "hellcreek_ptp.h"
+#include "hellcreek_hwtstamp.h"
static const struct hellcreek_counter hellcreek_counter[] = {
{ 0x00, "RxFiltered", },
@@ -1139,6 +1140,7 @@ static const struct dsa_switch_ops hellcreek_ds_ops = {
.get_sset_count = hellcreek_get_sset_count,
.get_strings = hellcreek_get_strings,
.get_tag_protocol = hellcreek_get_tag_protocol,
+ .get_ts_info = hellcreek_get_ts_info,
.phylink_validate = hellcreek_phylink_validate,
.port_bridge_join = hellcreek_port_bridge_join,
.port_bridge_leave = hellcreek_port_bridge_leave,
@@ -1147,8 +1149,12 @@ static const struct dsa_switch_ops hellcreek_ds_ops = {
.port_fdb_add = hellcreek_fdb_add,
.port_fdb_del = hellcreek_fdb_del,
.port_fdb_dump = hellcreek_fdb_dump,
+ .port_hwtstamp_set = hellcreek_port_hwtstamp_set,
+ .port_hwtstamp_get = hellcreek_port_hwtstamp_get,
.port_prechangeupper = hellcreek_port_prechangeupper,
+ .port_rxtstamp = hellcreek_port_rxtstamp,
.port_stp_state_set = hellcreek_port_stp_state_set,
+ .port_txtstamp = hellcreek_port_txtstamp,
.port_vlan_add = hellcreek_vlan_add,
.port_vlan_del = hellcreek_vlan_del,
.port_vlan_filtering = hellcreek_vlan_filtering,
@@ -1270,10 +1276,18 @@ static int hellcreek_probe(struct platform_device *pdev)
goto err_ptp_setup;
}
+ ret = hellcreek_hwtstamp_setup(hellcreek);
+ if (ret) {
+ dev_err(dev, "Failed to setup hardware timestamping!\n");
+ goto err_tstamp_setup;
+ }
+
platform_set_drvdata(pdev, hellcreek);
return 0;
+err_tstamp_setup:
+ hellcreek_ptp_free(hellcreek);
err_ptp_setup:
dsa_unregister_switch(hellcreek->ds);
@@ -1284,6 +1298,7 @@ static int hellcreek_remove(struct platform_device *pdev)
{
struct hellcreek *hellcreek = platform_get_drvdata(pdev);
+ hellcreek_hwtstamp_free(hellcreek);
hellcreek_ptp_free(hellcreek);
dsa_unregister_switch(hellcreek->ds);
platform_set_drvdata(pdev, NULL);