linux/drivers/net/dsa/sja1105/sja1105_ptp.c

// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2019, Vladimir Oltean <[email protected]>
 */
#include <linux/spi/spi.h>
#include "sja1105.h"

/* The adjfine API clamps ppb between [-32,768,000, 32,768,000], and
 * therefore scaled_ppm between [-2,147,483,648, 2,147,483,647].
 * Set the maximum supported ppb to a round value smaller than the maximum.
 *
 * Percentually speaking, this is a +/- 0.032x adjustment of the
 * free-running counter (0.968x to 1.032x).
 */
#define SJA1105_MAX_ADJ_PPB
#define SJA1105_SIZE_PTP_CMD

/* PTPSYNCTS has no interrupt or update mechanism, because the intended
 * hardware use case is for the timestamp to be collected synchronously,
 * immediately after the CAS_MASTER SJA1105 switch has performed a CASSYNC
 * one-shot toggle (no return to level) on the PTP_CLK pin. When used as a
 * generic extts source, the PTPSYNCTS register needs polling and a comparison
 * with the old value. The polling interval is configured as the Nyquist rate
 * of a signal with 50% duty cycle and 1Hz frequency, which is sadly all that
 * this hardware can do (but may be enough for some setups). Anything of higher
 * frequency than 1 Hz will be lost, since there is no timestamp FIFO.
 */
#define SJA1105_EXTTS_INTERVAL

/*            This range is actually +/- SJA1105_MAX_ADJ_PPB
 *            divided by 1000 (ppb -> ppm) and with a 16-bit
 *            "fractional" part (actually fixed point).
 *                                    |
 *                                    v
 * Convert scaled_ppm from the +/- ((10^6) << 16) range
 * into the +/- (1 << 31) range.
 *
 * This forgoes a "ppb" numeric representation (up to NSEC_PER_SEC)
 * and defines the scaling factor between scaled_ppm and the actual
 * frequency adjustments of the PHC.
 *
 *   ptpclkrate = scaled_ppm * 2^31 / (10^6 * 2^16)
 *   simplifies to
 *   ptpclkrate = scaled_ppm * 2^9 / 5^6
 */
#define SJA1105_CC_MULT_NUM
#define SJA1105_CC_MULT_DEM
#define SJA1105_CC_MULT

enum sja1105_ptp_clk_mode {};

#define extts_to_data(t)
#define ptp_caps_to_data(d)
#define ptp_data_to_sja1105(d)

int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr)
{}

int sja1105_hwtstamp_get(struct dsa_switch *ds, int port, struct ifreq *ifr)
{}

int sja1105_get_ts_info(struct dsa_switch *ds, int port,
			struct kernel_ethtool_ts_info *info)
{}

void sja1105et_ptp_cmd_packing(u8 *buf, struct sja1105_ptp_cmd *cmd,
			       enum packing_op op)
{}

void sja1105pqrs_ptp_cmd_packing(u8 *buf, struct sja1105_ptp_cmd *cmd,
				 enum packing_op op)
{}

int sja1105_ptp_commit(struct dsa_switch *ds, struct sja1105_ptp_cmd *cmd,
		       sja1105_spi_rw_mode_t rw)
{}

/* The switch returns partial timestamps (24 bits for SJA1105 E/T, which wrap
 * around in 0.135 seconds, and 32 bits for P/Q/R/S, wrapping around in 34.35
 * seconds).
 *
 * This receives the RX or TX MAC timestamps, provided by hardware as
 * the lower bits of the cycle counter, sampled at the time the timestamp was
 * collected.
 *
 * To reconstruct into a full 64-bit-wide timestamp, the cycle counter is
 * read and the high-order bits are filled in.
 *
 * Must be called within one wraparound period of the partial timestamp since
 * it was generated by the MAC.
 */
static u64 sja1105_tstamp_reconstruct(struct dsa_switch *ds, u64 now,
				      u64 ts_partial)
{}

/* Reads the SPI interface for an egress timestamp generated by the switch
 * for frames sent using management routes.
 *
 * SJA1105 E/T layout of the 4-byte SPI payload:
 *
 * 31    23    15    7     0
 * |     |     |     |     |
 * +-----+-----+-----+     ^
 *          ^              |
 *          |              |
 *  24-bit timestamp   Update bit
 *
 *
 * SJA1105 P/Q/R/S layout of the 8-byte SPI payload:
 *
 * 31    23    15    7     0     63    55    47    39    32
 * |     |     |     |     |     |     |     |     |     |
 *                         ^     +-----+-----+-----+-----+
 *                         |                 ^
 *                         |                 |
 *                    Update bit    32-bit timestamp
 *
 * Notice that the update bit is in the same place.
 * To have common code for E/T and P/Q/R/S for reading the timestamp,
 * we need to juggle with the offset and the bit indices.
 */
static int sja1105_ptpegr_ts_poll(struct dsa_switch *ds, int port, u64 *ts)
{}

/* Caller must hold ptp_data->lock */
static int sja1105_ptpclkval_read(struct sja1105_private *priv, u64 *ticks,
				  struct ptp_system_timestamp *ptp_sts)
{}

/* Caller must hold ptp_data->lock */
static int sja1105_ptpclkval_write(struct sja1105_private *priv, u64 ticks,
				   struct ptp_system_timestamp *ptp_sts)
{}

static void sja1105_extts_poll(struct sja1105_private *priv)
{}

static long sja1105_rxtstamp_work(struct ptp_clock_info *ptp)
{}

bool sja1105_rxtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
{}

bool sja1110_rxtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
{}

/* Called from dsa_skb_defer_rx_timestamp */
bool sja1105_port_rxtstamp(struct dsa_switch *ds, int port,
			   struct sk_buff *skb, unsigned int type)
{}

void sja1110_process_meta_tstamp(struct dsa_switch *ds, int port, u8 ts_id,
				 enum sja1110_meta_tstamp dir, u64 tstamp)
{}

/* In addition to cloning the skb which is done by the common
 * sja1105_port_txtstamp, we need to generate a timestamp ID and save the
 * packet to the TX timestamping queue.
 */
void sja1110_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
{}

/* Called from dsa_skb_tx_timestamp. This callback is just to clone
 * the skb and have it available in SJA1105_SKB_CB in the .port_deferred_xmit
 * callback, where we will timestamp it synchronously.
 */
void sja1105_port_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
{}

static int sja1105_ptp_reset(struct dsa_switch *ds)
{}

/* Caller must hold ptp_data->lock */
int __sja1105_ptp_gettimex(struct dsa_switch *ds, u64 *ns,
			   struct ptp_system_timestamp *ptp_sts)
{}

static int sja1105_ptp_gettimex(struct ptp_clock_info *ptp,
				struct timespec64 *ts,
				struct ptp_system_timestamp *ptp_sts)
{}

/* Caller must hold ptp_data->lock */
static int sja1105_ptp_mode_set(struct sja1105_private *priv,
				enum sja1105_ptp_clk_mode mode)
{}

/* Write to PTPCLKVAL while PTPCLKADD is 0 */
int __sja1105_ptp_settime(struct dsa_switch *ds, u64 ns,
			  struct ptp_system_timestamp *ptp_sts)
{}

static int sja1105_ptp_settime(struct ptp_clock_info *ptp,
			       const struct timespec64 *ts)
{}

static int sja1105_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
{}

/* Write to PTPCLKVAL while PTPCLKADD is 1 */
int __sja1105_ptp_adjtime(struct dsa_switch *ds, s64 delta)
{}

static int sja1105_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
{}

static void sja1105_ptp_extts_setup_timer(struct sja1105_ptp_data *ptp_data)
{}

static void sja1105_ptp_extts_timer(struct timer_list *t)
{}

static int sja1105_change_ptp_clk_pin_func(struct sja1105_private *priv,
					   enum ptp_pin_function func)
{}

/* The PTP_CLK pin may be configured to toggle with a 50% duty cycle and a
 * frequency f:
 *
 *           NSEC_PER_SEC
 * f = ----------------------
 *     (PTPPINDUR * 8 ns) * 2
 */
static int sja1105_per_out_enable(struct sja1105_private *priv,
				  struct ptp_perout_request *perout,
				  bool on)
{}

static int sja1105_extts_enable(struct sja1105_private *priv,
				struct ptp_extts_request *extts,
				bool on)
{}

static int sja1105_ptp_enable(struct ptp_clock_info *ptp,
			      struct ptp_clock_request *req, int on)
{}

static int sja1105_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin,
				  enum ptp_pin_function func, unsigned int chan)
{}

static struct ptp_pin_desc sja1105_ptp_pin =;

int sja1105_ptp_clock_register(struct dsa_switch *ds)
{}

void sja1105_ptp_clock_unregister(struct dsa_switch *ds)
{}

void sja1105_ptp_txtstamp_skb(struct dsa_switch *ds, int port,
			      struct sk_buff *skb)
{}