Skip to content

Commit

Permalink
Merge branch 'PTP-clock-source-for-SJA1105-tc-taprio-offload'
Browse files Browse the repository at this point in the history
Vladimir Oltean says:

====================
PTP clock source for SJA1105 tc-taprio offload

This series makes the IEEE 802.1Qbv egress scheduler of the sja1105
switch use a time reference that is synchronized to the network. This
enables quite a few real Time Sensitive Networking use cases, since in
this mode the switch can offer its clients a TDMA sort of access to the
network, and guaranteed latency for frames that are properly scheduled
based on the common PTP time.

The driver needs to do a 2-part activity:
- Program the gate control list into the static config and upload it
  over SPI to the switch (already supported)
- Write the activation time of the scheduler (base-time) into the
  PTPSCHTM register, and set the PTPSTRTSCH bit.
- Monitor the activation of the scheduler at the planned time and its
  health.

Ok, 3 parts.

The time-aware scheduler cannot be programmed to activate at a time in
the past, and there is some logic to avoid that.

PTPCLKCORP is one of those "black magic" registers that just need to be
written to the length of the cycle. There is a 40-line long comment in
the second patch which explains why.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Nov 14, 2019
2 parents 72c9960 + 86db36a commit ccb6899
Show file tree
Hide file tree
Showing 7 changed files with 534 additions and 55 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
16 changes: 9 additions & 7 deletions drivers/net/dsa/sja1105/sja1105.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
*/
#define SJA1105_AGEING_TIME_MS(ms) ((ms) / 10)

typedef enum {
SPI_READ = 0,
SPI_WRITE = 1,
} sja1105_spi_rw_mode_t;

#include "sja1105_tas.h"
#include "sja1105_ptp.h"

Expand All @@ -35,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 Expand Up @@ -71,15 +78,15 @@ struct sja1105_info {
const struct sja1105_dynamic_table_ops *dyn_ops;
const struct sja1105_table_ops *static_ops;
const struct sja1105_regs *regs;
int (*ptp_cmd)(const struct dsa_switch *ds,
const struct sja1105_ptp_cmd *cmd);
int (*reset_cmd)(const void *ctx, const void *data);
int (*setup_rgmii_delay)(const void *ctx, int port);
/* Prototypes from include/net/dsa.h */
int (*fdb_add_cmd)(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid);
int (*fdb_del_cmd)(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid);
void (*ptp_cmd_packing)(u8 *buf, struct sja1105_ptp_cmd *cmd,
enum packing_op op);
const char *name;
};

Expand Down Expand Up @@ -109,11 +116,6 @@ struct sja1105_spi_message {
u64 address;
};

typedef enum {
SPI_READ = 0,
SPI_WRITE = 1,
} sja1105_spi_rw_mode_t;

/* From sja1105_main.c */
enum sja1105_reset_reason {
SJA1105_VLAN_FILTERING = 0,
Expand Down
77 changes: 51 additions & 26 deletions drivers/net/dsa/sja1105/sja1105_ptp.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,42 +193,54 @@ int sja1105_get_ts_info(struct dsa_switch *ds, int port,
return 0;
}

int sja1105et_ptp_cmd(const struct dsa_switch *ds,
const struct sja1105_ptp_cmd *cmd)
void sja1105et_ptp_cmd_packing(u8 *buf, struct sja1105_ptp_cmd *cmd,
enum packing_op op)
{
const struct sja1105_private *priv = ds->priv;
const struct sja1105_regs *regs = priv->info->regs;
const int size = SJA1105_SIZE_PTP_CMD;
u8 buf[SJA1105_SIZE_PTP_CMD] = {0};
/* No need to keep this as part of the structure */
u64 valid = 1;

sja1105_pack(buf, &valid, 31, 31, size);
sja1105_pack(buf, &cmd->resptp, 2, 2, size);
sja1105_pack(buf, &cmd->corrclk4ts, 1, 1, size);
sja1105_pack(buf, &cmd->ptpclkadd, 0, 0, size);
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);
}

return sja1105_xfer_buf(priv, SPI_WRITE, regs->ptp_control, buf,
SJA1105_SIZE_PTP_CMD);
void sja1105pqrs_ptp_cmd_packing(u8 *buf, struct sja1105_ptp_cmd *cmd,
enum packing_op op)
{
const int size = SJA1105_SIZE_PTP_CMD;
/* No need to keep this as part of the structure */
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);
}

int sja1105pqrs_ptp_cmd(const struct dsa_switch *ds,
const struct sja1105_ptp_cmd *cmd)
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;
const int size = SJA1105_SIZE_PTP_CMD;
u8 buf[SJA1105_SIZE_PTP_CMD] = {0};
/* No need to keep this as part of the structure */
u64 valid = 1;
int rc;

sja1105_pack(buf, &valid, 31, 31, size);
sja1105_pack(buf, &cmd->resptp, 3, 3, size);
sja1105_pack(buf, &cmd->corrclk4ts, 2, 2, size);
sja1105_pack(buf, &cmd->ptpclkadd, 0, 0, size);
if (rw == SPI_WRITE)
priv->info->ptp_cmd_packing(buf, cmd, PACK);

return sja1105_xfer_buf(priv, SPI_WRITE, regs->ptp_control, buf,
SJA1105_SIZE_PTP_CMD);
rc = sja1105_xfer_buf(priv, SPI_WRITE, regs->ptp_control, buf,
SJA1105_SIZE_PTP_CMD);

if (rw == SPI_READ)
priv->info->ptp_cmd_packing(buf, cmd, UNPACK);

return rc;
}

/* The switch returns partial timestamps (24 bits for SJA1105 E/T, which wrap
Expand Down Expand Up @@ -438,8 +450,11 @@ static int sja1105_ptp_reset(struct dsa_switch *ds)
mutex_lock(&ptp_data->lock);

cmd.resptp = 1;

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

sja1105_tas_clockstep(priv->ds);

mutex_unlock(&ptp_data->lock);

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

ptp_data->cmd.ptpclkadd = mode;

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

/* Write to PTPCLKVAL while PTPCLKADD is 0 */
Expand All @@ -512,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 @@ -554,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 @@ -572,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
24 changes: 18 additions & 6 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 All @@ -39,11 +41,11 @@ int sja1105_ptp_clock_register(struct dsa_switch *ds);

void sja1105_ptp_clock_unregister(struct dsa_switch *ds);

int sja1105et_ptp_cmd(const struct dsa_switch *ds,
const struct sja1105_ptp_cmd *cmd);
void sja1105et_ptp_cmd_packing(u8 *buf, struct sja1105_ptp_cmd *cmd,
enum packing_op op);

int sja1105pqrs_ptp_cmd(const struct dsa_switch *ds,
const struct sja1105_ptp_cmd *cmd);
void sja1105pqrs_ptp_cmd_packing(u8 *buf, struct sja1105_ptp_cmd *cmd,
enum packing_op op);

int sja1105_get_ts_info(struct dsa_switch *ds, int port,
struct ethtool_ts_info *ts);
Expand All @@ -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,9 +115,16 @@ static inline int __sja1105_ptp_adjtime(struct dsa_switch *ds, s64 delta)
return 0;
}

#define sja1105et_ptp_cmd NULL
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 NULL
#define sja1105pqrs_ptp_cmd_packing NULL

#define sja1105_get_ts_info NULL

Expand Down
16 changes: 10 additions & 6 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 All @@ -584,7 +588,7 @@ struct sja1105_info sja1105e_info = {
.reset_cmd = sja1105et_reset_cmd,
.fdb_add_cmd = sja1105et_fdb_add,
.fdb_del_cmd = sja1105et_fdb_del,
.ptp_cmd = sja1105et_ptp_cmd,
.ptp_cmd_packing = sja1105et_ptp_cmd_packing,
.regs = &sja1105et_regs,
.name = "SJA1105E",
};
Expand All @@ -598,7 +602,7 @@ struct sja1105_info sja1105t_info = {
.reset_cmd = sja1105et_reset_cmd,
.fdb_add_cmd = sja1105et_fdb_add,
.fdb_del_cmd = sja1105et_fdb_del,
.ptp_cmd = sja1105et_ptp_cmd,
.ptp_cmd_packing = sja1105et_ptp_cmd_packing,
.regs = &sja1105et_regs,
.name = "SJA1105T",
};
Expand All @@ -613,7 +617,7 @@ struct sja1105_info sja1105p_info = {
.reset_cmd = sja1105pqrs_reset_cmd,
.fdb_add_cmd = sja1105pqrs_fdb_add,
.fdb_del_cmd = sja1105pqrs_fdb_del,
.ptp_cmd = sja1105pqrs_ptp_cmd,
.ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing,
.regs = &sja1105pqrs_regs,
.name = "SJA1105P",
};
Expand All @@ -628,7 +632,7 @@ struct sja1105_info sja1105q_info = {
.reset_cmd = sja1105pqrs_reset_cmd,
.fdb_add_cmd = sja1105pqrs_fdb_add,
.fdb_del_cmd = sja1105pqrs_fdb_del,
.ptp_cmd = sja1105pqrs_ptp_cmd,
.ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing,
.regs = &sja1105pqrs_regs,
.name = "SJA1105Q",
};
Expand All @@ -643,7 +647,7 @@ struct sja1105_info sja1105r_info = {
.reset_cmd = sja1105pqrs_reset_cmd,
.fdb_add_cmd = sja1105pqrs_fdb_add,
.fdb_del_cmd = sja1105pqrs_fdb_del,
.ptp_cmd = sja1105pqrs_ptp_cmd,
.ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing,
.regs = &sja1105pqrs_regs,
.name = "SJA1105R",
};
Expand All @@ -659,6 +663,6 @@ struct sja1105_info sja1105s_info = {
.reset_cmd = sja1105pqrs_reset_cmd,
.fdb_add_cmd = sja1105pqrs_fdb_add,
.fdb_del_cmd = sja1105pqrs_fdb_del,
.ptp_cmd = sja1105pqrs_ptp_cmd,
.ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing,
.name = "SJA1105S",
};
Loading

0 comments on commit ccb6899

Please sign in to comment.