Skip to content

Commit

Permalink
net: dsa: sja1105: Implement state machine for TAS with PTP clock source
Browse files Browse the repository at this point in the history
Tested using the following bash script and the tc from iproute2-next:

	#!/bin/bash

	set -e -u -o pipefail

	NSEC_PER_SEC="1000000000"

	gatemask() {
		local tc_list="$1"
		local mask=0

		for tc in ${tc_list}; do
			mask=$((${mask} | (1 << ${tc})))
		done

		printf "%02x" ${mask}
	}

	if ! systemctl is-active --quiet ptp4l; then
		echo "Please start the ptp4l service"
		exit
	fi

	now=$(phc_ctl /dev/ptp1 get | gawk '/clock time is/ { print $5; }')
	# Phase-align the base time to the start of the next second.
	sec=$(echo "${now}" | gawk -F. '{ print $1; }')
	base_time="$(((${sec} + 1) * ${NSEC_PER_SEC}))"

	tc qdisc add dev swp5 parent root handle 100 taprio \
		num_tc 8 \
		map 0 1 2 3 5 6 7 \
		queues 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7 \
		base-time ${base_time} \
		sched-entry S $(gatemask 7) 100000 \
		sched-entry S $(gatemask "0 1 2 3 4 5 6") 400000 \
		clockid CLOCK_TAI flags 2

The "state machine" is a workqueue invoked after each manipulation
command on the PTP clock (reset, adjust time, set time, adjust
frequency) which checks over the state of the time-aware scheduler.
So it is not monitored periodically, only in reaction to a PTP command
typically triggered from a userspace daemon (linuxptp). Otherwise there
is no reason for things to go wrong.

Now that the timecounter/cyclecounter has been replaced with hardware
operations on the PTP clock, the TAS Kconfig now depends upon PTP and
the standalone clocksource operating mode has been removed.

Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Vladimir Oltean authored and David S. Miller committed Nov 14, 2019
1 parent 41603d7 commit 86db36a
Show file tree
Hide file tree
Showing 7 changed files with 487 additions and 17 deletions.
1 change: 1 addition & 0 deletions drivers/net/dsa/sja1105/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ config NET_DSA_SJA1105_TAS
bool "Support for the Time-Aware Scheduler on NXP SJA1105"
depends on NET_DSA_SJA1105 && NET_SCH_TAPRIO
depends on NET_SCH_TAPRIO=y || NET_DSA_SJA1105=m
depends on NET_DSA_SJA1105_PTP
help
This enables support for the TTEthernet-based egress scheduling
engine in the SJA1105 DSA driver, which is controlled using a
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/dsa/sja1105/sja1105.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ struct sja1105_regs {
u64 ptp_control;
u64 ptpclkval;
u64 ptpclkrate;
u64 ptpclkcorp;
u64 ptpschtm;
u64 ptpegr_ts[SJA1105_NUM_PORTS];
u64 pad_mii_tx[SJA1105_NUM_PORTS];
u64 pad_mii_id[SJA1105_NUM_PORTS];
Expand Down
30 changes: 23 additions & 7 deletions drivers/net/dsa/sja1105/sja1105_ptp.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ void sja1105et_ptp_cmd_packing(u8 *buf, struct sja1105_ptp_cmd *cmd,
u64 valid = 1;

sja1105_packing(buf, &valid, 31, 31, size, op);
sja1105_packing(buf, &cmd->ptpstrtsch, 30, 30, size, op);
sja1105_packing(buf, &cmd->ptpstopsch, 29, 29, size, op);
sja1105_packing(buf, &cmd->resptp, 2, 2, size, op);
sja1105_packing(buf, &cmd->corrclk4ts, 1, 1, size, op);
sja1105_packing(buf, &cmd->ptpclkadd, 0, 0, size, op);
Expand All @@ -214,15 +216,17 @@ void sja1105pqrs_ptp_cmd_packing(u8 *buf, struct sja1105_ptp_cmd *cmd,
u64 valid = 1;

sja1105_packing(buf, &valid, 31, 31, size, op);
sja1105_packing(buf, &cmd->ptpstrtsch, 30, 30, size, op);
sja1105_packing(buf, &cmd->ptpstopsch, 29, 29, size, op);
sja1105_packing(buf, &cmd->resptp, 3, 3, size, op);
sja1105_packing(buf, &cmd->corrclk4ts, 2, 2, size, op);
sja1105_packing(buf, &cmd->ptpclkadd, 0, 0, size, op);
}

static int sja1105_ptp_commit(struct sja1105_private *priv,
struct sja1105_ptp_cmd *cmd,
sja1105_spi_rw_mode_t rw)
int sja1105_ptp_commit(struct dsa_switch *ds, struct sja1105_ptp_cmd *cmd,
sja1105_spi_rw_mode_t rw)
{
const struct sja1105_private *priv = ds->priv;
const struct sja1105_regs *regs = priv->info->regs;
u8 buf[SJA1105_SIZE_PTP_CMD] = {0};
int rc;
Expand Down Expand Up @@ -448,7 +452,9 @@ static int sja1105_ptp_reset(struct dsa_switch *ds)
cmd.resptp = 1;

dev_dbg(ds->dev, "Resetting PTP clock\n");
rc = sja1105_ptp_commit(priv, &cmd, SPI_WRITE);
rc = sja1105_ptp_commit(ds, &cmd, SPI_WRITE);

sja1105_tas_clockstep(priv->ds);

mutex_unlock(&ptp_data->lock);

Expand Down Expand Up @@ -504,7 +510,7 @@ static int sja1105_ptp_mode_set(struct sja1105_private *priv,

ptp_data->cmd.ptpclkadd = mode;

return sja1105_ptp_commit(priv, &ptp_data->cmd, SPI_WRITE);
return sja1105_ptp_commit(priv->ds, &ptp_data->cmd, SPI_WRITE);
}

/* Write to PTPCLKVAL while PTPCLKADD is 0 */
Expand All @@ -521,7 +527,11 @@ int __sja1105_ptp_settime(struct dsa_switch *ds, u64 ns,
return rc;
}

return sja1105_ptpclkval_write(priv, ticks, ptp_sts);
rc = sja1105_ptpclkval_write(priv, ticks, ptp_sts);

sja1105_tas_clockstep(priv->ds);

return rc;
}

static int sja1105_ptp_settime(struct ptp_clock_info *ptp,
Expand Down Expand Up @@ -563,6 +573,8 @@ static int sja1105_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
rc = sja1105_xfer_u32(priv, SPI_WRITE, regs->ptpclkrate, &clkrate32,
NULL);

sja1105_tas_adjfreq(priv->ds);

mutex_unlock(&ptp_data->lock);

return rc;
Expand All @@ -581,7 +593,11 @@ int __sja1105_ptp_adjtime(struct dsa_switch *ds, s64 delta)
return rc;
}

return sja1105_ptpclkval_write(priv, ticks, NULL);
rc = sja1105_ptpclkval_write(priv, ticks, NULL);

sja1105_tas_clockstep(priv->ds);

return rc;
}

static int sja1105_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
Expand Down
12 changes: 12 additions & 0 deletions drivers/net/dsa/sja1105/sja1105_ptp.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ static inline s64 sja1105_ticks_to_ns(s64 ticks)
}

struct sja1105_ptp_cmd {
u64 ptpstrtsch; /* start schedule */
u64 ptpstopsch; /* stop schedule */
u64 resptp; /* reset */
u64 corrclk4ts; /* use the corrected clock for timestamps */
u64 ptpclkadd; /* enum sja1105_ptp_clk_mode */
Expand Down Expand Up @@ -69,6 +71,9 @@ int __sja1105_ptp_settime(struct dsa_switch *ds, u64 ns,

int __sja1105_ptp_adjtime(struct dsa_switch *ds, s64 delta);

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

#else

struct sja1105_ptp_cmd;
Expand Down Expand Up @@ -110,6 +115,13 @@ static inline int __sja1105_ptp_adjtime(struct dsa_switch *ds, s64 delta)
return 0;
}

static inline int sja1105_ptp_commit(struct dsa_switch *ds,
struct sja1105_ptp_cmd *cmd,
sja1105_spi_rw_mode_t rw)
{
return 0;
}

#define sja1105et_ptp_cmd_packing NULL

#define sja1105pqrs_ptp_cmd_packing NULL
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/dsa/sja1105/sja1105_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -539,9 +539,11 @@ static struct sja1105_regs sja1105et_regs = {
.rmii_ref_clk = {0x100015, 0x10001C, 0x100023, 0x10002A, 0x100031},
.rmii_ext_tx_clk = {0x100018, 0x10001F, 0x100026, 0x10002D, 0x100034},
.ptpegr_ts = {0xC0, 0xC2, 0xC4, 0xC6, 0xC8},
.ptpschtm = 0x12, /* Spans 0x12 to 0x13 */
.ptp_control = 0x17,
.ptpclkval = 0x18, /* Spans 0x18 to 0x19 */
.ptpclkrate = 0x1A,
.ptpclkcorp = 0x1D,
};

static struct sja1105_regs sja1105pqrs_regs = {
Expand Down Expand Up @@ -569,9 +571,11 @@ static struct sja1105_regs sja1105pqrs_regs = {
.rmii_ext_tx_clk = {0x100017, 0x10001D, 0x100023, 0x100029, 0x10002F},
.qlevel = {0x604, 0x614, 0x624, 0x634, 0x644},
.ptpegr_ts = {0xC0, 0xC4, 0xC8, 0xCC, 0xD0},
.ptpschtm = 0x13, /* Spans 0x13 to 0x14 */
.ptp_control = 0x18,
.ptpclkval = 0x19,
.ptpclkrate = 0x1B,
.ptpclkcorp = 0x1E,
};

struct sja1105_info sja1105e_info = {
Expand Down
Loading

0 comments on commit 86db36a

Please sign in to comment.