Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e2294a8b authored by Andrew Lunn's avatar Andrew Lunn Committed by David S. Miller
Browse files

net: dsa: mv88e6xxx: Add hwtimestamp support for the 6165



The 6165 family supports a more restricted version of hardware time
stamps. Only L2 PTP is supported. All ports have to use the same
EtherType, and transport spec configuration. PTP can only be
enabled/disabled globally, not per port.

Signed-off-by: default avatarAndrew Lunn <andrew@lunn.ch>
Acked-by: default avatarRichard Cochran <richardcochran@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 48cb5e03
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -274,6 +274,7 @@ struct mv88e6xxx_chip {
	struct ptp_pin_desc	pin_config[MV88E6XXX_MAX_GPIO];
	u16 trig_config;
	u16 evcap_config;
	u16 enable_count;

	/* Per-port timestamping resources. */
	struct mv88e6xxx_port_hwtstamp port_hwtstamp[DSA_MAX_PORTS];
@@ -499,6 +500,8 @@ struct mv88e6xxx_ptp_ops {
	void (*event_work)(struct work_struct *ugly);
	int (*port_enable)(struct mv88e6xxx_chip *chip, int port);
	int (*port_disable)(struct mv88e6xxx_chip *chip, int port);
	int (*global_enable)(struct mv88e6xxx_chip *chip);
	int (*global_disable)(struct mv88e6xxx_chip *chip);
	int n_ext_ts;
	int arr0_sts_reg;
	int arr1_sts_reg;
+50 −0
Original line number Diff line number Diff line
@@ -51,6 +51,15 @@ static int mv88e6xxx_ptp_write(struct mv88e6xxx_chip *chip, int addr,
	return chip->info->ops->avb_ops->ptp_write(chip, addr, data);
}

static int mv88e6xxx_ptp_read(struct mv88e6xxx_chip *chip, int addr,
			      u16 *data)
{
	if (!chip->info->ops->avb_ops->ptp_read)
		return -EOPNOTSUPP;

	return chip->info->ops->avb_ops->ptp_read(chip, addr, data, 1);
}

/* TX_TSTAMP_TIMEOUT: This limits the time spent polling for a TX
 * timestamp. When working properly, hardware will produce a timestamp
 * within 1ms. Software may enounter delays due to MDIO contention, so
@@ -144,11 +153,17 @@ static int mv88e6xxx_set_hwtstamp_config(struct mv88e6xxx_chip *chip, int port,

	mutex_lock(&chip->reg_lock);
	if (tstamp_enable) {
		chip->enable_count += 1;
		if (chip->enable_count == 1 && ptp_ops->global_enable)
			ptp_ops->global_enable(chip);
		if (ptp_ops->port_enable)
			ptp_ops->port_enable(chip, port);
	} else {
		if (ptp_ops->port_disable)
			ptp_ops->port_disable(chip, port);
		chip->enable_count -= 1;
		if (chip->enable_count == 0 && ptp_ops->global_disable)
			ptp_ops->global_disable(chip);
	}
	mutex_unlock(&chip->reg_lock);

@@ -516,6 +531,33 @@ bool mv88e6xxx_port_txtstamp(struct dsa_switch *ds, int port,
	return true;
}

int mv88e6165_global_disable(struct mv88e6xxx_chip *chip)
{
	u16 val;
	int err;

	err = mv88e6xxx_ptp_read(chip, MV88E6165_PTP_CFG, &val);
	if (err)
		return err;
	val |= MV88E6165_PTP_CFG_DISABLE_PTP;

	return mv88e6xxx_ptp_write(chip, MV88E6165_PTP_CFG, val);
}

int mv88e6165_global_enable(struct mv88e6xxx_chip *chip)
{
	u16 val;
	int err;

	err = mv88e6xxx_ptp_read(chip, MV88E6165_PTP_CFG, &val);
	if (err)
		return err;

	val &= ~(MV88E6165_PTP_CFG_DISABLE_PTP | MV88E6165_PTP_CFG_TSPEC_MASK);

	return mv88e6xxx_ptp_write(chip, MV88E6165_PTP_CFG, val);
}

int mv88e6352_hwtstamp_port_disable(struct mv88e6xxx_chip *chip, int port)
{
	return mv88e6xxx_port_ptp_write(chip, port, MV88E6XXX_PORT_PTP_CFG0,
@@ -546,6 +588,7 @@ static int mv88e6xxx_hwtstamp_port_setup(struct mv88e6xxx_chip *chip, int port)

int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip)
{
	const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
	int err;
	int i;

@@ -556,6 +599,13 @@ int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip)
			return err;
	}

	/* Disable PTP globally */
	if (ptp_ops->global_disable) {
		err = ptp_ops->global_disable(chip);
		if (err)
			return err;
	}

	/* MV88E6XXX_PTP_MSG_TYPE is a mask of PTP message types to
	 * timestamp. This affects all ports that have timestamping enabled,
	 * but the timestamp config is per-port; thus we configure all events
+10 −2
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@

#include "chip.h"

/* Global PTP registers */
/* Global 6352 PTP registers */
/* Offset 0x00: PTP EtherType */
#define MV88E6XXX_PTP_ETHERTYPE	0x00

@@ -34,6 +34,12 @@
/* Offset 0x02: Timestamp Arrival Capture Pointers */
#define MV88E6XXX_PTP_TS_ARRIVAL_PTR	0x02

/* Offset 0x05: PTP Global Configuration */
#define MV88E6165_PTP_CFG			0x05
#define MV88E6165_PTP_CFG_TSPEC_MASK		0xf000
#define MV88E6165_PTP_CFG_DISABLE_TS_OVERWRITE	BIT(1)
#define MV88E6165_PTP_CFG_DISABLE_PTP		BIT(0)

/* Offset 0x07: PTP Global Configuration */
#define MV88E6341_PTP_CFG			0x07
#define MV88E6341_PTP_CFG_UPDATE		0x8000
@@ -46,7 +52,7 @@
/* Offset 0x08: PTP Interrupt Status */
#define MV88E6XXX_PTP_IRQ_STATUS	0x08

/* Per-Port PTP Registers */
/* Per-Port 6352 PTP Registers */
/* Offset 0x00: PTP Configuration 0 */
#define MV88E6XXX_PORT_PTP_CFG0				0x00
#define MV88E6XXX_PORT_PTP_CFG0_TSPEC_SHIFT		12
@@ -125,6 +131,8 @@ int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip);
void mv88e6xxx_hwtstamp_free(struct mv88e6xxx_chip *chip);
int mv88e6352_hwtstamp_port_enable(struct mv88e6xxx_chip *chip, int port);
int mv88e6352_hwtstamp_port_disable(struct mv88e6xxx_chip *chip, int port);
int mv88e6165_global_enable(struct mv88e6xxx_chip *chip);
int mv88e6165_global_disable(struct mv88e6xxx_chip *chip);

#else /* !CONFIG_NET_DSA_MV88E6XXX_PTP */

+12 −0
Original line number Diff line number Diff line
@@ -339,6 +339,18 @@ const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {

const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = {
	.clock_read = mv88e6165_ptp_clock_read,
	.global_enable = mv88e6165_global_enable,
	.global_disable = mv88e6165_global_disable,
	.arr0_sts_reg = MV88E6165_PORT_PTP_ARR0_STS,
	.arr1_sts_reg = MV88E6165_PORT_PTP_ARR1_STS,
	.dep_sts_reg = MV88E6165_PORT_PTP_DEP_STS,
	.rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
		(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
		(1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
		(1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
		(1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
		(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
		(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
};

static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc)
+35 −0
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@
/* Offset 0x00: Ether Type */
#define MV88E6XXX_PTP_GC_ETYPE			0x00

/* 6165 Global Control Registers */
/* Offset 0x01: Message ID */
#define MV88E6XXX_PTP_GC_MESSAGE_ID		0x01

@@ -105,6 +106,40 @@
#define MV88E6XXX_PTP_GC_TIME_LO		0x09
#define MV88E6XXX_PTP_GC_TIME_HI		0x0A

/* 6165 Per Port Registers */
/* Offset 0: Arrival Time 0 Status */
#define MV88E6165_PORT_PTP_ARR0_STS	0x00

/* Offset 0x01/0x02: PTP Arrival 0 Time */
#define MV88E6165_PORT_PTP_ARR0_TIME_LO	0x01
#define MV88E6165_PORT_PTP_ARR0_TIME_HI	0x02

/* Offset 0x03: PTP Arrival 0 Sequence ID */
#define MV88E6165_PORT_PTP_ARR0_SEQID	0x03

/* Offset 0x04: PTP Arrival 1 Status */
#define MV88E6165_PORT_PTP_ARR1_STS	0x04

/* Offset 0x05/0x6E: PTP Arrival 1 Time */
#define MV88E6165_PORT_PTP_ARR1_TIME_LO	0x05
#define MV88E6165_PORT_PTP_ARR1_TIME_HI	0x06

/* Offset 0x07: PTP Arrival 1 Sequence ID */
#define MV88E6165_PORT_PTP_ARR1_SEQID	0x07

/* Offset 0x08: PTP Departure Status */
#define MV88E6165_PORT_PTP_DEP_STS	0x08

/* Offset 0x09/0x0a: PTP Deperture Time */
#define MV88E6165_PORT_PTP_DEP_TIME_LO	0x09
#define MV88E6165_PORT_PTP_DEP_TIME_HI	0x0a

/* Offset 0x0b: PTP Departure Sequence ID */
#define MV88E6165_PORT_PTP_DEP_SEQID	0x0b

/* Offset 0x0d: Port Status */
#define MV88E6164_PORT_STATUS		0x0d

#ifdef CONFIG_NET_DSA_MV88E6XXX_PTP

long mv88e6xxx_hwtstamp_work(struct ptp_clock_info *ptp);