Skip to content

Commit

Permalink
net: dsa: hellcreek: Add PTP clock support
Browse files Browse the repository at this point in the history
The switch has internal PTP hardware clocks. Add support for it. There are three
clocks:

 * Synchronized
 * Syntonized
 * Free running

Currently the synchronized clock is exported to user space which is a good
default for the beginning. The free running clock might be exported later
e.g. for implementing 802.1AS-2011/2020 Time Aware Bridges (TAB). The switch
also supports cross time stamping for that purpose.

The implementation adds support setting/getting the time as well as offset and
frequency adjustments. However, the clock only holds a partial timeofday
timestamp. This is why we track the seconds completely in software (see overflow
work and last_ts).

Furthermore, add the PTP multicast addresses into the FDB to forward that
packages only to the CPU port where they are processed by a PTP program.

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>
  • Loading branch information
Kamil Alkhouri authored and Jakub Kicinski committed Nov 5, 2020
1 parent e4b27eb commit ddd56df
Show file tree
Hide file tree
Showing 6 changed files with 435 additions and 1 deletion.
1 change: 1 addition & 0 deletions drivers/net/dsa/hirschmann/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ config NET_DSA_HIRSCHMANN_HELLCREEK
tristate "Hirschmann Hellcreek TSN Switch support"
depends on HAS_IOMEM
depends on NET_DSA
depends on PTP_1588_CLOCK
select NET_DSA_TAG_HELLCREEK
help
This driver adds support for Hirschmann Hellcreek TSN switches.
4 changes: 3 additions & 1 deletion drivers/net/dsa/hirschmann/Makefile
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_NET_DSA_HIRSCHMANN_HELLCREEK) += hellcreek.o
obj-$(CONFIG_NET_DSA_HIRSCHMANN_HELLCREEK) += hellcreek_sw.o
hellcreek_sw-objs := hellcreek.o
hellcreek_sw-objs += hellcreek_ptp.o
71 changes: 71 additions & 0 deletions drivers/net/dsa/hirschmann/hellcreek.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <net/dsa.h>

#include "hellcreek.h"
#include "hellcreek_ptp.h"

static const struct hellcreek_counter hellcreek_counter[] = {
{ 0x00, "RxFiltered", },
Expand Down Expand Up @@ -959,6 +960,43 @@ static void hellcreek_setup_tc_identity_mapping(struct hellcreek *hellcreek)
}
}

static int hellcreek_setup_fdb(struct hellcreek *hellcreek)
{
static struct hellcreek_fdb_entry ptp = {
/* MAC: 01-1B-19-00-00-00 */
.mac = { 0x01, 0x1b, 0x19, 0x00, 0x00, 0x00 },
.portmask = 0x03, /* Management ports */
.age = 0,
.is_obt = 0,
.pass_blocked = 0,
.is_static = 1,
.reprio_tc = 6, /* TC: 6 as per IEEE 802.1AS */
.reprio_en = 1,
};
static struct hellcreek_fdb_entry p2p = {
/* MAC: 01-80-C2-00-00-0E */
.mac = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e },
.portmask = 0x03, /* Management ports */
.age = 0,
.is_obt = 0,
.pass_blocked = 0,
.is_static = 1,
.reprio_tc = 6, /* TC: 6 as per IEEE 802.1AS */
.reprio_en = 1,
};
int ret;

mutex_lock(&hellcreek->reg_lock);
ret = __hellcreek_fdb_add(hellcreek, &ptp);
if (ret)
goto out;
ret = __hellcreek_fdb_add(hellcreek, &p2p);
out:
mutex_unlock(&hellcreek->reg_lock);

return ret;
}

static int hellcreek_setup(struct dsa_switch *ds)
{
struct hellcreek *hellcreek = ds->priv;
Expand Down Expand Up @@ -1009,6 +1047,14 @@ static int hellcreek_setup(struct dsa_switch *ds)
*/
ds->vlan_filtering_is_global = true;

/* Intercept _all_ PTP multicast traffic */
ret = hellcreek_setup_fdb(hellcreek);
if (ret) {
dev_err(hellcreek->dev,
"Failed to insert static PTP FDB entries\n");
return ret;
}

return 0;
}

Expand Down Expand Up @@ -1160,6 +1206,7 @@ static int hellcreek_probe(struct platform_device *pdev)

mutex_init(&hellcreek->reg_lock);
mutex_init(&hellcreek->vlan_lock);
mutex_init(&hellcreek->ptp_lock);

hellcreek->dev = dev;

Expand All @@ -1175,6 +1222,18 @@ static int hellcreek_probe(struct platform_device *pdev)
return PTR_ERR(hellcreek->base);
}

res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ptp");
if (!res) {
dev_err(dev, "No PTP memory region provided!\n");
return -ENODEV;
}

hellcreek->ptp_base = devm_ioremap_resource(dev, res);
if (IS_ERR(hellcreek->ptp_base)) {
dev_err(dev, "No memory available!\n");
return PTR_ERR(hellcreek->ptp_base);
}

ret = hellcreek_detect(hellcreek);
if (ret) {
dev_err(dev, "No (known) chip found!\n");
Expand Down Expand Up @@ -1205,15 +1264,27 @@ static int hellcreek_probe(struct platform_device *pdev)
return ret;
}

ret = hellcreek_ptp_setup(hellcreek);
if (ret) {
dev_err(dev, "Failed to setup PTP!\n");
goto err_ptp_setup;
}

platform_set_drvdata(pdev, hellcreek);

return 0;

err_ptp_setup:
dsa_unregister_switch(hellcreek->ds);

return ret;
}

static int hellcreek_remove(struct platform_device *pdev)
{
struct hellcreek *hellcreek = platform_get_drvdata(pdev);

hellcreek_ptp_free(hellcreek);
dsa_unregister_switch(hellcreek->ds);
platform_set_drvdata(pdev, NULL);

Expand Down
8 changes: 8 additions & 0 deletions drivers/net/dsa/hirschmann/hellcreek.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/workqueue.h>
#include <linux/platform_data/hirschmann-hellcreek.h>
#include <linux/ptp_clock_kernel.h>
#include <linux/timecounter.h>
Expand Down Expand Up @@ -237,12 +238,19 @@ struct hellcreek {
const struct hellcreek_platform_data *pdata;
struct device *dev;
struct dsa_switch *ds;
struct ptp_clock *ptp_clock;
struct ptp_clock_info ptp_clock_info;
struct hellcreek_port *ports;
struct delayed_work overflow_work;
struct mutex reg_lock; /* Switch IP register lock */
struct mutex vlan_lock; /* VLAN bitmaps lock */
struct mutex ptp_lock; /* PTP IP register lock */
void __iomem *base;
void __iomem *ptp_base;
u16 swcfg; /* swcfg shadow */
u8 *vidmbrcfg; /* vidmbrcfg shadow */
u64 seconds; /* PTP seconds */
u64 last_ts; /* Used for overflow detection */
size_t fdb_entries;
};

Expand Down
Loading

0 comments on commit ddd56df

Please sign in to comment.