lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <E1u3Ltf-000CPD-C4@rmk-PC.armlinux.org.uk>
Date: Fri, 11 Apr 2025 22:26:47 +0100
From: "Russell King (Oracle)" <rmk+kernel@...linux.org.uk>
To: Andrew Lunn <andrew@...n.ch>,
	Heiner Kallweit <hkallweit1@...il.com>
Cc: "David S. Miller" <davem@...emloft.net>,
	Eric Dumazet <edumazet@...gle.com>,
	Jakub Kicinski <kuba@...nel.org>,
	Kory Maincent <kory.maincent@...tlin.com>,
	netdev@...r.kernel.org,
	Paolo Abeni <pabeni@...hat.com>,
	Richard Cochran <richardcochran@...il.com>,
	Vladimir Oltean <olteanv@...il.com>
Subject: [PATCH RFC net-next 4/5] mv88e6xxx: convert to marvell TAI

---
 drivers/net/dsa/mv88e6xxx/Kconfig    |   1 +
 drivers/net/dsa/mv88e6xxx/chip.h     |  22 +-
 drivers/net/dsa/mv88e6xxx/hwtstamp.c |  23 +-
 drivers/net/dsa/mv88e6xxx/hwtstamp.h |   1 +
 drivers/net/dsa/mv88e6xxx/ptp.c      | 354 ++++++++++++++++++++++++---
 drivers/net/dsa/mv88e6xxx/ptp.h      |   1 -
 6 files changed, 361 insertions(+), 41 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/Kconfig b/drivers/net/dsa/mv88e6xxx/Kconfig
index 64ae3882d17c..595ca6cd6075 100644
--- a/drivers/net/dsa/mv88e6xxx/Kconfig
+++ b/drivers/net/dsa/mv88e6xxx/Kconfig
@@ -14,6 +14,7 @@ config NET_DSA_MV88E6XXX_PTP
 	default n
 	depends on (NET_DSA_MV88E6XXX = y && PTP_1588_CLOCK = y) || \
 	           (NET_DSA_MV88E6XXX = m && PTP_1588_CLOCK)
+	select PTP_1588_CLOCK_MARVELL
 	help
 	  Say Y to enable PTP hardware timestamping on Marvell 88E6xxx switch
 	  chips that support it.
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 86bf113c9bfa..6fb7d0fa0180 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -7,13 +7,14 @@
 
 #ifndef _MV88E6XXX_CHIP_H
 #define _MV88E6XXX_CHIP_H
-
+#define USE_MARVELL_TAI
 #include <linux/idr.h>
 #include <linux/if_vlan.h>
 #include <linux/irq.h>
 #include <linux/gpio/consumer.h>
 #include <linux/kthread.h>
 #include <linux/leds.h>
+#include <linux/marvell_ptp.h>
 #include <linux/phy.h>
 #include <linux/property.h>
 #include <linux/ptp_clock_kernel.h>
@@ -412,20 +413,29 @@ struct mv88e6xxx_chip {
 	/* GPIO resources */
 	u8 gpio_data[2];
 
+#ifdef USE_MARVELL_TAI
+	struct marvell_tai	*tai;
+#else
+
 	/* This cyclecounter abstracts the switch PTP time.
 	 * reg_lock must be held for any operation that read()s.
 	 */
 	struct cyclecounter	tstamp_cc;
 	struct timecounter	tstamp_tc;
 	struct delayed_work	overflow_work;
+#endif
 	const struct mv88e6xxx_cc_coeffs *cc_coeffs;
 
+#ifndef USE_MARVELL_TAI
 	struct ptp_clock	*ptp_clock;
 	struct ptp_clock_info	ptp_clock_info;
 	struct delayed_work	tai_event_work;
+#endif
 	struct ptp_pin_desc	pin_config[MV88E6XXX_MAX_GPIO];
+#ifndef USE_MARVELL_TAI
 	u16 trig_config;
 	u16 evcap_config;
+#endif
 	u16 enable_count;
 
 	/* Current ingress and egress monitor ports */
@@ -732,10 +742,12 @@ struct mv88e6xxx_avb_ops {
 };
 
 struct mv88e6xxx_ptp_ops {
-	u64 (*clock_read)(const struct cyclecounter *cc);
-	int (*ptp_enable)(struct ptp_clock_info *ptp,
-			  struct ptp_clock_request *rq, int on);
-	int (*ptp_verify)(struct ptp_clock_info *ptp, unsigned int pin,
+	u64 (*clock_read)(struct mv88e6xxx_chip *chip);
+	int (*ptp_enable_extts)(struct mv88e6xxx_chip *chip,
+			        struct ptp_clock_request *rq, int on);
+	int (*ptp_pin_setup)(struct mv88e6xxx_chip *chip, int pin,
+			     unsigned int flags, int enable);
+	int (*ptp_verify)(struct mv88e6xxx_chip *chip, unsigned int pin,
 			  enum ptp_pin_function func, unsigned int chan);
 	void (*event_work)(struct work_struct *ugly);
 	int (*port_enable)(struct mv88e6xxx_chip *chip, int port);
diff --git a/drivers/net/dsa/mv88e6xxx/hwtstamp.c b/drivers/net/dsa/mv88e6xxx/hwtstamp.c
index 49e6e1355142..232deff1b2ba 100644
--- a/drivers/net/dsa/mv88e6xxx/hwtstamp.c
+++ b/drivers/net/dsa/mv88e6xxx/hwtstamp.c
@@ -79,7 +79,11 @@ int mv88e6xxx_get_ts_info(struct dsa_switch *ds, int port,
 		SOF_TIMESTAMPING_TX_HARDWARE |
 		SOF_TIMESTAMPING_RX_HARDWARE |
 		SOF_TIMESTAMPING_RAW_HARDWARE;
+#ifdef USE_MARVELL_TAI
+	info->phc_index = marvell_tai_ptp_clock_index(chip->tai);
+#else
 	info->phc_index = ptp_clock_index(chip->ptp_clock);
+#endif
 	info->tx_types =
 		(1 << HWTSTAMP_TX_OFF) |
 		(1 << HWTSTAMP_TX_ON);
@@ -293,9 +297,13 @@ static void mv88e6xxx_get_rxts(struct mv88e6xxx_chip *chip,
 		if (mv88e6xxx_ts_valid(status) && seq_match(skb, seq_id)) {
 			ns = timehi << 16 | timelo;
 
+#ifdef USE_MARVELL_TAI
+			ns = marvell_tai_cyc2time(chip->tai, ns);
+#else
 			mv88e6xxx_reg_lock(chip);
 			ns = timecounter_cyc2time(&chip->tstamp_tc, ns);
 			mv88e6xxx_reg_unlock(chip);
+#endif
 			shwt = skb_hwtstamps(skb);
 			memset(shwt, 0, sizeof(*shwt));
 			shwt->hwtstamp = ns_to_ktime(ns);
@@ -352,7 +360,11 @@ bool mv88e6xxx_port_rxtstamp(struct dsa_switch *ds, int port,
 	else
 		skb_queue_tail(&ps->rx_queue, skb);
 
+#ifdef USE_MARVELL_TAI
+	marvell_tai_schedule(chip->tai, 0);
+#else
 	ptp_schedule_worker(chip->ptp_clock, 0);
+#endif
 
 	return true;
 }
@@ -413,9 +425,13 @@ static int mv88e6xxx_txtstamp_work(struct mv88e6xxx_chip *chip,
 
 	memset(&shhwtstamps, 0, sizeof(shhwtstamps));
 	time_raw = ((u32)departure_block[2] << 16) | departure_block[1];
+#ifdef USE_MARVELL_TAI
+	ns = marvell_tai_cyc2time(chip->tai, time_raw);
+#else
 	mv88e6xxx_reg_lock(chip);
 	ns = timecounter_cyc2time(&chip->tstamp_tc, time_raw);
 	mv88e6xxx_reg_unlock(chip);
+#endif
 	shhwtstamps.hwtstamp = ns_to_ktime(ns);
 
 	dev_dbg(chip->dev,
@@ -443,9 +459,8 @@ static int mv88e6xxx_txtstamp_work(struct mv88e6xxx_chip *chip,
 	return 0;
 }
 
-long mv88e6xxx_hwtstamp_work(struct ptp_clock_info *ptp)
+long mv88e6xxx_hwtstamp_work(struct mv88e6xxx_chip *chip)
 {
-	struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
 	struct dsa_switch *ds = chip->ds;
 	struct mv88e6xxx_port_hwtstamp *ps;
 	int i, restart = 0;
@@ -495,7 +510,11 @@ void mv88e6xxx_port_txtstamp(struct dsa_switch *ds, int port,
 	ps->tx_tstamp_start = jiffies;
 	ps->tx_seq_id = be16_to_cpu(hdr->sequence_id);
 
+#ifdef USE_MARVELL_TAI
+	marvell_tai_schedule(chip->tai, 0);
+#else
 	ptp_schedule_worker(chip->ptp_clock, 0);
+#endif
 }
 
 int mv88e6165_global_disable(struct mv88e6xxx_chip *chip)
diff --git a/drivers/net/dsa/mv88e6xxx/hwtstamp.h b/drivers/net/dsa/mv88e6xxx/hwtstamp.h
index 85acc758e3eb..6013d7edbf73 100644
--- a/drivers/net/dsa/mv88e6xxx/hwtstamp.h
+++ b/drivers/net/dsa/mv88e6xxx/hwtstamp.h
@@ -129,6 +129,7 @@ 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);
+long mv88e6xxx_hwtstamp_work(struct mv88e6xxx_chip *chip);
 
 #else /* !CONFIG_NET_DSA_MV88E6XXX_PTP */
 
diff --git a/drivers/net/dsa/mv88e6xxx/ptp.c b/drivers/net/dsa/mv88e6xxx/ptp.c
index aed4a4b07f34..9d6f880b2430 100644
--- a/drivers/net/dsa/mv88e6xxx/ptp.c
+++ b/drivers/net/dsa/mv88e6xxx/ptp.c
@@ -87,6 +87,7 @@ static int mv88e6xxx_tai_read(struct mv88e6xxx_chip *chip, int addr,
 	return chip->info->ops->avb_ops->tai_read(chip, addr, data, len);
 }
 
+#ifndef USE_MARVELL_TAI
 static int mv88e6xxx_tai_write(struct mv88e6xxx_chip *chip, int addr, u16 data)
 {
 	if (!chip->info->ops->avb_ops->tai_write)
@@ -94,6 +95,7 @@ static int mv88e6xxx_tai_write(struct mv88e6xxx_chip *chip, int addr, u16 data)
 
 	return chip->info->ops->avb_ops->tai_write(chip, addr, data);
 }
+#endif
 
 /* TODO: places where this are called should be using pinctrl */
 static int mv88e6352_set_gpio_func(struct mv88e6xxx_chip *chip, int pin,
@@ -138,9 +140,8 @@ mv88e6xxx_cc_coeff_get(struct mv88e6xxx_chip *chip)
 	}
 }
 
-static u64 mv88e6352_ptp_clock_read(const struct cyclecounter *cc)
+static u64 mv88e6352_ptp_clock_read(struct mv88e6xxx_chip *chip)
 {
-	struct mv88e6xxx_chip *chip = cc_to_chip(cc);
 	u16 phc_time[2];
 	int err;
 
@@ -152,9 +153,8 @@ static u64 mv88e6352_ptp_clock_read(const struct cyclecounter *cc)
 		return ((u32)phc_time[1] << 16) | phc_time[0];
 }
 
-static u64 mv88e6165_ptp_clock_read(const struct cyclecounter *cc)
+static u64 mv88e6165_ptp_clock_read(struct mv88e6xxx_chip *chip)
 {
-	struct mv88e6xxx_chip *chip = cc_to_chip(cc);
 	u16 phc_time[2];
 	int err;
 
@@ -166,6 +166,7 @@ static u64 mv88e6165_ptp_clock_read(const struct cyclecounter *cc)
 		return ((u32)phc_time[1] << 16) | phc_time[0];
 }
 
+#ifndef USE_MARVELL_TAI
 /* mv88e6352_config_eventcap - configure TAI event capture
  * @event: PTP_CLOCK_PPS (internal) or PTP_CLOCK_EXTTS (external)
  * @rising: zero for falling-edge trigger, else rising-edge trigger
@@ -324,6 +325,52 @@ static int mv88e6xxx_ptp_settime(struct ptp_clock_info *ptp,
 	return 0;
 }
 
+static int mv88e6xxx_ptp_enable_extts(struct mv88e6xxx_chip *chip,
+				      struct ptp_extts_request *req, int on)
+{
+	int pin;
+
+	/* Reject requests with unsupported flags */
+	if (req->flags & ~(PTP_ENABLE_FEATURE |
+			   PTP_RISING_EDGE |
+			   PTP_FALLING_EDGE |
+			   PTP_STRICT_FLAGS))
+		return -EOPNOTSUPP;
+
+	if (!chip->info->ops->ptp_ops->ptp_enable_extts)
+		return -EOPNOTSUPP;
+
+	pin = ptp_find_pin(chip->ptp_clock, PTP_PF_EXTTS, req->index);
+	if (pin < 0)
+		return -EBUSY;
+
+	return chip->info->ops->ptp_ops->ptp_enable_extts(chip, rq, on);
+}
+
+static int mv88e6xxx_ptp_enable(struct ptp_clock_info *ptp,
+				struct ptp_clock_request *rq, int on)
+{
+	struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
+
+	switch (rq->type) {
+	case PTP_CLK_REQ_EXTTS:
+		return mv88e6xxx_ptp_enable_extts(chip, &rq->extts, on);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int mv88e6xxx_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
+				enum ptp_pin_function func, unsigned int chan)
+{
+	struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
+
+	if (!chip->info->ops->ptp_ops->ptp_verify)
+		return -EOPNOTSUPP;
+
+	return chip->info->ops->ptp_ops->ptp_verify(chip, pin, func, chan);
+}
+
 static int mv88e6352_ptp_enable_extts(struct mv88e6xxx_chip *chip,
 				      struct ptp_clock_request *rq, int on)
 {
@@ -376,21 +423,30 @@ static int mv88e6352_ptp_enable_extts(struct mv88e6xxx_chip *chip,
 
 	return err;
 }
+#endif
 
-static int mv88e6352_ptp_enable(struct ptp_clock_info *ptp,
-				struct ptp_clock_request *rq, int on)
+static int mv88e6352_ptp_pin_setup(struct mv88e6xxx_chip *chip,
+				   int pin, unsigned int flags, int enable)
 {
-	struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
+	int func, err;
 
-	switch (rq->type) {
-	case PTP_CLK_REQ_EXTTS:
-		return mv88e6352_ptp_enable_extts(chip, rq, on);
-	default:
+	/* Reject requests to enable time stamping on both edges. */
+	if (flags & PTP_STRICT_FLAGS &&
+	    flags & PTP_ENABLE_FEATURE &&
+	    (flags & PTP_EXTTS_EDGES) == PTP_EXTTS_EDGES)
 		return -EOPNOTSUPP;
-	}
+
+	if (enable)
+		func = MV88E6352_G2_SCRATCH_GPIO_PCTL_EVREQ;
+	else
+		func = MV88E6352_G2_SCRATCH_GPIO_PCTL_GPIO;
+
+	err = mv88e6352_set_gpio_func(chip, pin, func, true);
+
+	return enable ? err : 0;
 }
 
-static int mv88e6352_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
+static int mv88e6352_ptp_verify(struct mv88e6xxx_chip *chip, unsigned int pin,
 				enum ptp_pin_function func, unsigned int chan)
 {
 	switch (func) {
@@ -422,9 +478,13 @@ const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = {
 
 const struct mv88e6xxx_ptp_ops mv88e6250_ptp_ops = {
 	.clock_read = mv88e6352_ptp_clock_read,
-	.ptp_enable = mv88e6352_ptp_enable,
 	.ptp_verify = mv88e6352_ptp_verify,
+#ifndef USE_MARVELL_TAI
+	.ptp_enable_extts = mv88e6352_ptp_enable_extts,
 	.event_work = mv88e6352_tai_event_work,
+#else
+	.ptp_pin_setup = mv88e6352_ptp_pin_setup,
+#endif
 	.port_enable = mv88e6352_hwtstamp_port_enable,
 	.port_disable = mv88e6352_hwtstamp_port_disable,
 	.n_ext_ts = 1,
@@ -445,9 +505,13 @@ const struct mv88e6xxx_ptp_ops mv88e6250_ptp_ops = {
 
 const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {
 	.clock_read = mv88e6352_ptp_clock_read,
-	.ptp_enable = mv88e6352_ptp_enable,
 	.ptp_verify = mv88e6352_ptp_verify,
+#ifndef USE_MARVELL_TAI
+	.ptp_enable_extts = mv88e6352_ptp_enable_extts,
 	.event_work = mv88e6352_tai_event_work,
+#else
+	.ptp_pin_setup = mv88e6352_ptp_pin_setup,
+#endif
 	.port_enable = mv88e6352_hwtstamp_port_enable,
 	.port_disable = mv88e6352_hwtstamp_port_disable,
 	.n_ext_ts = 1,
@@ -468,9 +532,13 @@ const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {
 
 const struct mv88e6xxx_ptp_ops mv88e6390_ptp_ops = {
 	.clock_read = mv88e6352_ptp_clock_read,
-	.ptp_enable = mv88e6352_ptp_enable,
 	.ptp_verify = mv88e6352_ptp_verify,
+#ifndef USE_MARVELL_TAI
+	.ptp_enable_extts = mv88e6352_ptp_enable_extts,
 	.event_work = mv88e6352_tai_event_work,
+#else
+	.ptp_pin_setup = mv88e6352_ptp_pin_setup,
+#endif
 	.port_enable = mv88e6352_hwtstamp_port_enable,
 	.port_disable = mv88e6352_hwtstamp_port_disable,
 	.set_ptp_cpu_port = mv88e6390_g1_set_ptp_cpu_port,
@@ -490,12 +558,32 @@ const struct mv88e6xxx_ptp_ops mv88e6390_ptp_ops = {
 		(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
 };
 
+static int mv88e6xxx_set_ptp_cpu_port(struct mv88e6xxx_chip *chip)
+{
+	const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
+	struct dsa_port *dp;
+	int upstream = 0;
+	int err;
+
+	dsa_switch_for_each_user_port(dp, chip->ds) {
+		upstream = dsa_upstream_port(chip->ds, dp->index);
+		break;
+	}
+
+	err = ptp_ops->set_ptp_cpu_port(chip, upstream);
+	if (err)
+		dev_err(chip->dev, "Failed to set PTP CPU destination port!\n");
+
+	return err;
+}
+
+#ifndef USE_MARVELL_TAI
 static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc)
 {
 	struct mv88e6xxx_chip *chip = cc_to_chip(cc);
 
 	if (chip->info->ops->ptp_ops->clock_read)
-		return chip->info->ops->ptp_ops->clock_read(cc);
+		return chip->info->ops->ptp_ops->clock_read(chip);
 
 	return 0;
 }
@@ -516,6 +604,11 @@ static void mv88e6xxx_ptp_overflow_check(struct work_struct *work)
 			      MV88E6XXX_TAI_OVERFLOW_PERIOD);
 }
 
+static long mv88e6xxx_ptp_aux_work(struct ptp_clock_info *ptp)
+{
+	return mv88e6xxx_hwtstamp_work(ptp_to_chip(ptp));
+}
+
 int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
 {
 	const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
@@ -555,6 +648,7 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
 		ppd->index = i;
 		ppd->func = PTP_PF_NONE;
 	}
+
 	chip->ptp_clock_info.pin_config = chip->pin_config;
 
 	chip->ptp_clock_info.max_adj    = MV88E6XXX_MAX_ADJ_PPB;
@@ -562,25 +656,14 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
 	chip->ptp_clock_info.adjtime	= mv88e6xxx_ptp_adjtime;
 	chip->ptp_clock_info.gettime64	= mv88e6xxx_ptp_gettime;
 	chip->ptp_clock_info.settime64	= mv88e6xxx_ptp_settime;
-	chip->ptp_clock_info.enable	= ptp_ops->ptp_enable;
-	chip->ptp_clock_info.verify	= ptp_ops->ptp_verify;
-	chip->ptp_clock_info.do_aux_work = mv88e6xxx_hwtstamp_work;
+	chip->ptp_clock_info.enable	= mv88e6xxx_ptp_enable;
+	chip->ptp_clock_info.verify	= mv88e6xxx_ptp_verify;
+	chip->ptp_clock_info.do_aux_work = mv88e6xxx_ptp_aux_work;
 
 	if (ptp_ops->set_ptp_cpu_port) {
-		struct dsa_port *dp;
-		int upstream = 0;
-		int err;
-
-		dsa_switch_for_each_user_port(dp, chip->ds) {
-			upstream = dsa_upstream_port(chip->ds, dp->index);
-			break;
-		}
-
-		err = ptp_ops->set_ptp_cpu_port(chip, upstream);
-		if (err) {
-			dev_err(chip->dev, "Failed to set PTP CPU destination port!\n");
+		err = mv88e6xxx_set_ptp_cpu_port(chip);
+		if (err)
 			return err;
-		}
 	}
 
 	chip->ptp_clock = ptp_clock_register(&chip->ptp_clock_info, chip->dev);
@@ -604,3 +687,208 @@ void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip)
 		chip->ptp_clock = NULL;
 	}
 }
+#else
+static struct mv88e6xxx_chip *dev_to_chip(struct device *dev)
+{
+	struct dsa_switch *ds = dev_get_drvdata(dev);
+
+	return ds->priv;
+}
+
+static int mv88e6xxx_tai_enable(struct device *dev)
+{
+	return 0;
+}
+
+static u64 mv88e6xxx_tai_clock_read(struct device *dev,
+				    struct ptp_system_timestamp *sts)
+{
+	struct mv88e6xxx_chip *chip = dev_to_chip(dev);
+	int err = 0;
+
+	if (chip->info->ops->ptp_ops->clock_read) {
+		mv88e6xxx_reg_lock(chip);
+		ptp_read_system_prets(sts);
+		err = chip->info->ops->ptp_ops->clock_read(chip);
+		ptp_read_system_postts(sts);
+		mv88e6xxx_reg_unlock(chip);
+	}
+
+	return err;
+}
+
+static int mv88e6xxx_tai_extts_read(struct device *dev, int reg,
+				    struct marvell_extts *extts)
+{
+	struct mv88e6xxx_chip *chip = dev_to_chip(dev);
+	u16 regs[3];
+	int ret;
+
+	mv88e6xxx_reg_lock(chip);
+	ret = chip->info->ops->avb_ops->tai_read(chip, reg, regs, 3);
+	if (ret < 0)
+		goto unlock;
+
+	extts->status = regs[0];
+	extts->time = regs[1] | regs[2] << 16;
+
+	/* Clear valid if set */
+	if (regs[0] & MV_STATUS_EVENTCAPVALID) {
+		chip->info->ops->avb_ops->tai_write(chip, reg, 0);
+		ret = 1;
+	} else {
+		ret = 0;
+	}
+
+unlock:
+	mv88e6xxx_reg_unlock(chip);
+
+	return ret;
+}
+
+static int mv88e6xxx_tai_pin_verify(struct device *dev, int pin,
+				    enum ptp_pin_function func,
+				    unsigned int chan)
+{
+	struct mv88e6xxx_chip *chip = dev_to_chip(dev);
+
+	if (!chip->info->ops->ptp_ops->ptp_verify)
+		return -EOPNOTSUPP;
+
+	return chip->info->ops->ptp_ops->ptp_verify(chip, pin, func, chan);
+}
+
+static int mv88e6xxx_tai_pin_setup(struct device *dev, int pin,
+				   unsigned int flags, int enable)
+{
+	struct mv88e6xxx_chip *chip = dev_to_chip(dev);
+
+	if (!chip->info->ops->ptp_ops->ptp_pin_setup)
+		return -EOPNOTSUPP;
+
+	return chip->info->ops->ptp_ops->ptp_pin_setup(chip, pin, flags,
+						       enable);
+}
+
+static int mv88e6xxx_tai_write(struct device *dev, u8 reg, u16 val)
+{
+	struct mv88e6xxx_chip *chip = dev_to_chip(dev);
+	int err;
+
+	mv88e6xxx_reg_lock(chip);
+	err = chip->info->ops->avb_ops->tai_write(chip, reg, val);
+	mv88e6xxx_reg_unlock(chip);
+
+	return err;
+}
+
+static int mv88e6xxx_tai_modify(struct device *dev, u8 reg, u16 mask, u16 val)
+{
+	struct mv88e6xxx_chip *chip = dev_to_chip(dev);
+	u16 old, new;
+	int err;
+
+	mv88e6xxx_reg_lock(chip);
+	err = chip->info->ops->avb_ops->tai_read(chip, reg, &old, 1);
+	if (err < 0)
+		goto unlock;
+
+	new = (old & ~mask) | val;
+	if (new != old)
+		err = chip->info->ops->avb_ops->tai_write(chip, reg, new);
+
+unlock:
+	mv88e6xxx_reg_unlock(chip);
+	return err;
+}
+
+static int mv88e6xxx_ptp_global_write(struct device *dev, u8 reg, u16 val)
+{
+	return 0;
+}
+
+static int mv88e6xxx_ptp_port_read_ts(struct device *dev, struct marvell_ts *ts,
+				      u8 reg)
+{
+	return 0;
+}
+
+static int mv88e6xxx_ptp_port_write(struct device *dev, u8 reg, u16 val)
+{
+	return 0;
+}
+
+static int mv88e6xxx_ptp_port_modify(struct device *dev, u8 reg, u16 mask,
+				     u16 val)
+{
+	return 0;
+}
+
+static long mv88e6xxx_ptp_aux_work(struct device *dev)
+{
+	return mv88e6xxx_hwtstamp_work(dev_to_chip(dev));
+}
+
+static const struct marvell_ptp_ops mv88e6xxx_ptp_ops = {
+	.tai_enable = mv88e6xxx_tai_enable,
+	.tai_clock_read = mv88e6xxx_tai_clock_read,
+	.tai_extts_read = mv88e6xxx_tai_extts_read,
+	.tai_pin_verify = mv88e6xxx_tai_pin_verify,
+	.tai_pin_setup = mv88e6xxx_tai_pin_setup,
+	.tai_write = mv88e6xxx_tai_write,
+	.tai_modify = mv88e6xxx_tai_modify,
+	.ptp_global_write = mv88e6xxx_ptp_global_write,
+	.ptp_port_read_ts = mv88e6xxx_ptp_port_read_ts,
+	.ptp_port_write = mv88e6xxx_ptp_port_write,
+	.ptp_port_modify = mv88e6xxx_ptp_port_modify,
+	.ptp_aux_work = mv88e6xxx_ptp_aux_work,
+};
+
+int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
+{
+	const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
+	struct marvell_tai_param tai_param;
+	int i, n_pins, err;
+
+	/* Set up the cycle counter */
+	chip->cc_coeffs = mv88e6xxx_cc_coeff_get(chip);
+	if (IS_ERR(chip->cc_coeffs))
+		return PTR_ERR(chip->cc_coeffs);
+
+	if (ptp_ops->set_ptp_cpu_port) {
+		err = mv88e6xxx_set_ptp_cpu_port(chip);
+		if (err)
+			return err;
+	}
+
+	memset(&tai_param, 0, sizeof(tai_param));
+	tai_param.cc_mult_num = chip->cc_coeffs->cc_mult_num;
+	tai_param.cc_mult_den = chip->cc_coeffs->cc_mult_dem;
+	tai_param.cc_mult = chip->cc_coeffs->cc_mult;
+	tai_param.cc_shift = chip->cc_coeffs->cc_shift;
+	tai_param.n_ext_ts = ptp_ops->n_ext_ts;
+
+	n_pins = mv88e6xxx_num_gpio(chip);
+	for (i = 0; i < n_pins; ++i) {
+		struct ptp_pin_desc *ppd = &chip->pin_config[i];
+
+		snprintf(ppd->name, sizeof(ppd->name), "mv88e6xxx_gpio%d", i);
+		ppd->index = i;
+		ppd->func = PTP_PF_NONE;
+	}
+
+	mv88e6xxx_reg_unlock(chip);
+	err = marvell_tai_probe(&chip->tai, &mv88e6xxx_ptp_ops, &tai_param,
+				chip->pin_config, n_pins,
+				dev_name(chip->dev), chip->dev);
+	mv88e6xxx_reg_lock(chip);
+
+	return err;
+}
+
+void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip)
+{
+	if (chip->tai)
+		marvell_tai_remove(chip->tai);
+}
+#endif
diff --git a/drivers/net/dsa/mv88e6xxx/ptp.h b/drivers/net/dsa/mv88e6xxx/ptp.h
index 6c4d09adc93c..f10ca6e91fe4 100644
--- a/drivers/net/dsa/mv88e6xxx/ptp.h
+++ b/drivers/net/dsa/mv88e6xxx/ptp.h
@@ -141,7 +141,6 @@
 
 #ifdef CONFIG_NET_DSA_MV88E6XXX_PTP
 
-long mv88e6xxx_hwtstamp_work(struct ptp_clock_info *ptp);
 int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip);
 void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip);
 
-- 
2.30.2


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ