diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/dsa/sja1105/sja1105.h | 6 | ||||
-rw-r--r-- | drivers/net/dsa/sja1105/sja1105_main.c | 3 | ||||
-rw-r--r-- | drivers/net/dsa/sja1105/sja1105_ptp.c | 26 | ||||
-rw-r--r-- | drivers/net/dsa/sja1105/sja1105_spi.c | 48 |
4 files changed, 61 insertions, 22 deletions
diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index 91063ed3ef1b..64b3ee7b9771 100644 --- a/drivers/net/dsa/sja1105/sja1105.h +++ b/drivers/net/dsa/sja1105/sja1105.h @@ -122,9 +122,11 @@ int sja1105_xfer_buf(const struct sja1105_private *priv, sja1105_spi_rw_mode_t rw, u64 reg_addr, u8 *buf, size_t len); int sja1105_xfer_u32(const struct sja1105_private *priv, - sja1105_spi_rw_mode_t rw, u64 reg_addr, u32 *value); + sja1105_spi_rw_mode_t rw, u64 reg_addr, u32 *value, + struct ptp_system_timestamp *ptp_sts); int sja1105_xfer_u64(const struct sja1105_private *priv, - sja1105_spi_rw_mode_t rw, u64 reg_addr, u64 *value); + sja1105_spi_rw_mode_t rw, u64 reg_addr, u64 *value, + struct ptp_system_timestamp *ptp_sts); int sja1105_static_config_upload(struct sja1105_private *priv); int sja1105_inhibit_tx(const struct sja1105_private *priv, unsigned long port_bitmap, bool tx_inhibited); diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index d5dfda335aa1..d545edbbef9e 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -1973,7 +1973,8 @@ static int sja1105_check_device_id(struct sja1105_private *priv) u64 part_no; int rc; - rc = sja1105_xfer_u32(priv, SPI_READ, regs->device_id, &device_id); + rc = sja1105_xfer_u32(priv, SPI_READ, regs->device_id, &device_id, + NULL); if (rc < 0) return rc; diff --git a/drivers/net/dsa/sja1105/sja1105_ptp.c b/drivers/net/dsa/sja1105/sja1105_ptp.c index 783100397f8a..fac72af24baf 100644 --- a/drivers/net/dsa/sja1105/sja1105_ptp.c +++ b/drivers/net/dsa/sja1105/sja1105_ptp.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2019, Vladimir Oltean <olteanv@gmail.com> */ +#include <linux/spi/spi.h> #include "sja1105.h" /* The adjfine API clamps ppb between [-32,768,000, 32,768,000], and @@ -335,11 +336,13 @@ 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) +static int sja1105_ptpclkval_read(struct sja1105_private *priv, u64 *ticks, + struct ptp_system_timestamp *ptp_sts) { const struct sja1105_regs *regs = priv->info->regs; - return sja1105_xfer_u64(priv, SPI_READ, regs->ptpclkval, ticks); + return sja1105_xfer_u64(priv, SPI_READ, regs->ptpclkval, ticks, + ptp_sts); } /* Caller must hold ptp_data->lock */ @@ -347,7 +350,8 @@ static int sja1105_ptpclkval_write(struct sja1105_private *priv, u64 ticks) { const struct sja1105_regs *regs = priv->info->regs; - return sja1105_xfer_u64(priv, SPI_WRITE, regs->ptpclkval, &ticks); + return sja1105_xfer_u64(priv, SPI_WRITE, regs->ptpclkval, &ticks, + NULL); } #define rxtstamp_to_tagger(d) \ @@ -370,7 +374,7 @@ static void sja1105_rxtstamp_work(struct work_struct *work) u64 ticks, ts; int rc; - rc = sja1105_ptpclkval_read(priv, &ticks); + rc = sja1105_ptpclkval_read(priv, &ticks, NULL); if (rc < 0) { dev_err(ds->dev, "Failed to read PTP clock: %d\n", rc); kfree_skb(skb); @@ -441,8 +445,9 @@ int sja1105_ptp_reset(struct dsa_switch *ds) return rc; } -static int sja1105_ptp_gettime(struct ptp_clock_info *ptp, - struct timespec64 *ts) +static int sja1105_ptp_gettimex(struct ptp_clock_info *ptp, + struct timespec64 *ts, + struct ptp_system_timestamp *ptp_sts) { struct sja1105_ptp_data *ptp_data = ptp_caps_to_data(ptp); struct sja1105_private *priv = ptp_data_to_sja1105(ptp_data); @@ -451,7 +456,7 @@ static int sja1105_ptp_gettime(struct ptp_clock_info *ptp, mutex_lock(&ptp_data->lock); - rc = sja1105_ptpclkval_read(priv, &ticks); + rc = sja1105_ptpclkval_read(priv, &ticks, ptp_sts); *ts = ns_to_timespec64(sja1105_ticks_to_ns(ticks)); mutex_unlock(&ptp_data->lock); @@ -516,7 +521,8 @@ static int sja1105_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) mutex_lock(&ptp_data->lock); - rc = sja1105_xfer_u32(priv, SPI_WRITE, regs->ptpclkrate, &clkrate32); + rc = sja1105_xfer_u32(priv, SPI_WRITE, regs->ptpclkrate, &clkrate32, + NULL); mutex_unlock(&ptp_data->lock); @@ -558,7 +564,7 @@ int sja1105_ptp_clock_register(struct dsa_switch *ds) .name = "SJA1105 PHC", .adjfine = sja1105_ptp_adjfine, .adjtime = sja1105_ptp_adjtime, - .gettime64 = sja1105_ptp_gettime, + .gettimex64 = sja1105_ptp_gettimex, .settime64 = sja1105_ptp_settime, .max_adj = SJA1105_MAX_ADJ_PPB, }; @@ -604,7 +610,7 @@ void sja1105_ptp_txtstamp_skb(struct dsa_switch *ds, int slot, mutex_lock(&ptp_data->lock); - rc = sja1105_ptpclkval_read(priv, &ticks); + rc = sja1105_ptpclkval_read(priv, &ticks, NULL); if (rc < 0) { dev_err(ds->dev, "Failed to read PTP clock: %d\n", rc); kfree_skb(skb); diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c index ed02410a9366..691cd250e50a 100644 --- a/drivers/net/dsa/sja1105/sja1105_spi.c +++ b/drivers/net/dsa/sja1105/sja1105_spi.c @@ -42,9 +42,9 @@ sja1105_spi_message_pack(void *buf, const struct sja1105_spi_message *msg) * - SPI_READ: creates and sends an SPI read message from absolute * address reg_addr, writing @len bytes into *buf */ -int sja1105_xfer_buf(const struct sja1105_private *priv, - sja1105_spi_rw_mode_t rw, u64 reg_addr, - u8 *buf, size_t len) +static int sja1105_xfer(const struct sja1105_private *priv, + sja1105_spi_rw_mode_t rw, u64 reg_addr, u8 *buf, + size_t len, struct ptp_system_timestamp *ptp_sts) { struct sja1105_chunk chunk = { .len = min_t(size_t, len, SJA1105_SIZE_SPI_MSG_MAXLEN), @@ -81,6 +81,7 @@ int sja1105_xfer_buf(const struct sja1105_private *priv, struct spi_transfer *chunk_xfer = sja1105_chunk_xfer(xfers, i); struct spi_transfer *hdr_xfer = sja1105_hdr_xfer(xfers, i); u8 *hdr_buf = sja1105_hdr_buf(hdr_bufs, i); + struct spi_transfer *ptp_sts_xfer; struct sja1105_spi_message msg; /* Populate the transfer's header buffer */ @@ -102,6 +103,26 @@ int sja1105_xfer_buf(const struct sja1105_private *priv, chunk_xfer->tx_buf = chunk.buf; chunk_xfer->len = chunk.len; + /* Request timestamping for the transfer. Instead of letting + * callers specify which byte they want to timestamp, we can + * make certain assumptions: + * - A read operation will request a software timestamp when + * what's being read is the PTP time. That is snapshotted by + * the switch hardware at the end of the command portion + * (hdr_xfer). + * - A write operation will request a software timestamp on + * actions that modify the PTP time. Taking clock stepping as + * an example, the switch writes the PTP time at the end of + * the data portion (chunk_xfer). + */ + if (rw == SPI_READ) + ptp_sts_xfer = hdr_xfer; + else + ptp_sts_xfer = chunk_xfer; + ptp_sts_xfer->ptp_sts_word_pre = ptp_sts_xfer->len - 1; + ptp_sts_xfer->ptp_sts_word_post = ptp_sts_xfer->len - 1; + ptp_sts_xfer->ptp_sts = ptp_sts; + /* Calculate next chunk */ chunk.buf += chunk.len; chunk.reg_addr += chunk.len / 4; @@ -123,6 +144,13 @@ int sja1105_xfer_buf(const struct sja1105_private *priv, return rc; } +int sja1105_xfer_buf(const struct sja1105_private *priv, + sja1105_spi_rw_mode_t rw, u64 reg_addr, + u8 *buf, size_t len) +{ + return sja1105_xfer(priv, rw, reg_addr, buf, len, NULL); +} + /* If @rw is: * - SPI_WRITE: creates and sends an SPI write message at absolute * address reg_addr @@ -133,7 +161,8 @@ int sja1105_xfer_buf(const struct sja1105_private *priv, * CPU endianness and directly usable by software running on the core. */ int sja1105_xfer_u64(const struct sja1105_private *priv, - sja1105_spi_rw_mode_t rw, u64 reg_addr, u64 *value) + sja1105_spi_rw_mode_t rw, u64 reg_addr, u64 *value, + struct ptp_system_timestamp *ptp_sts) { u8 packed_buf[8]; int rc; @@ -141,7 +170,7 @@ int sja1105_xfer_u64(const struct sja1105_private *priv, if (rw == SPI_WRITE) sja1105_pack(packed_buf, value, 63, 0, 8); - rc = sja1105_xfer_buf(priv, rw, reg_addr, packed_buf, 8); + rc = sja1105_xfer(priv, rw, reg_addr, packed_buf, 8, ptp_sts); if (rw == SPI_READ) sja1105_unpack(packed_buf, value, 63, 0, 8); @@ -151,7 +180,8 @@ int sja1105_xfer_u64(const struct sja1105_private *priv, /* Same as above, but transfers only a 4 byte word */ int sja1105_xfer_u32(const struct sja1105_private *priv, - sja1105_spi_rw_mode_t rw, u64 reg_addr, u32 *value) + sja1105_spi_rw_mode_t rw, u64 reg_addr, u32 *value, + struct ptp_system_timestamp *ptp_sts) { u8 packed_buf[4]; u64 tmp; @@ -165,7 +195,7 @@ int sja1105_xfer_u32(const struct sja1105_private *priv, sja1105_pack(packed_buf, &tmp, 31, 0, 4); } - rc = sja1105_xfer_buf(priv, rw, reg_addr, packed_buf, 4); + rc = sja1105_xfer(priv, rw, reg_addr, packed_buf, 4, ptp_sts); if (rw == SPI_READ) { sja1105_unpack(packed_buf, &tmp, 31, 0, 4); @@ -293,7 +323,7 @@ int sja1105_inhibit_tx(const struct sja1105_private *priv, int rc; rc = sja1105_xfer_u32(priv, SPI_READ, regs->port_control, - &inhibit_cmd); + &inhibit_cmd, NULL); if (rc < 0) return rc; @@ -303,7 +333,7 @@ int sja1105_inhibit_tx(const struct sja1105_private *priv, inhibit_cmd &= ~port_bitmap; return sja1105_xfer_u32(priv, SPI_WRITE, regs->port_control, - &inhibit_cmd); + &inhibit_cmd, NULL); } struct sja1105_status { |