Commit d6b71dfa authored by Vladimir Oltean's avatar Vladimir Oltean Committed by Mark Brown

spi: spi-fsl-dspi: Implement the PTP system timestamping for TCFQ mode

In this mode, the DSPI controller uses PIO to transfer word by word. In
comparison, in EOQ mode the 4-word deep FIFO is being used, hence the
current logic will need some adaptation for which I do not have the
hardware (Coldfire) to test. It is not clear what is the timing of DMA
transfers and whether timestamping in the driver brings any overall
performance increase compared to regular timestamping done in the core.

Short phc2sys summary after 58 minutes of running on LS1021A-TSN with
interrupts disabled during the critical section:

  offset: min -26251 max 16416 mean -21.8672 std dev 863.416
  delay: min 4720 max 57280 mean 5182.49 std dev 1607.19
  lost servo lock 3 times

Summary of the same phc2sys service running for 120 minutes with
interrupts disabled:

  offset: min -378 max 381 mean -0.0083089 std dev 101.495
  delay: min 4720 max 5920 mean 5129.38 std dev 154.899
  lost servo lock 0 times

The minimum delay (pre to post time) in nanoseconds is the same, but the
maximum delay is quite a bit higher, due to interrupts getting sometimes
executed and interfering with the measurement. Hence set disable_irqs
whenever possible (aka when the driver runs in poll mode - otherwise it
would be a contradiction in terms).
Signed-off-by: default avatarVladimir Oltean <olteanv@gmail.com>
Link: https://lore.kernel.org/r/20190905010114.26718-4-olteanv@gmail.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent b42faeee
...@@ -129,6 +129,7 @@ enum dspi_trans_mode { ...@@ -129,6 +129,7 @@ enum dspi_trans_mode {
struct fsl_dspi_devtype_data { struct fsl_dspi_devtype_data {
enum dspi_trans_mode trans_mode; enum dspi_trans_mode trans_mode;
u8 max_clock_factor; u8 max_clock_factor;
bool ptp_sts_supported;
bool xspi_mode; bool xspi_mode;
}; };
...@@ -140,12 +141,14 @@ static const struct fsl_dspi_devtype_data vf610_data = { ...@@ -140,12 +141,14 @@ static const struct fsl_dspi_devtype_data vf610_data = {
static const struct fsl_dspi_devtype_data ls1021a_v1_data = { static const struct fsl_dspi_devtype_data ls1021a_v1_data = {
.trans_mode = DSPI_TCFQ_MODE, .trans_mode = DSPI_TCFQ_MODE,
.max_clock_factor = 8, .max_clock_factor = 8,
.ptp_sts_supported = true,
.xspi_mode = true, .xspi_mode = true,
}; };
static const struct fsl_dspi_devtype_data ls2085a_data = { static const struct fsl_dspi_devtype_data ls2085a_data = {
.trans_mode = DSPI_TCFQ_MODE, .trans_mode = DSPI_TCFQ_MODE,
.max_clock_factor = 8, .max_clock_factor = 8,
.ptp_sts_supported = true,
}; };
static const struct fsl_dspi_devtype_data coldfire_data = { static const struct fsl_dspi_devtype_data coldfire_data = {
...@@ -654,6 +657,9 @@ static int dspi_rxtx(struct fsl_dspi *dspi) ...@@ -654,6 +657,9 @@ static int dspi_rxtx(struct fsl_dspi *dspi)
u16 spi_tcnt; u16 spi_tcnt;
u32 spi_tcr; u32 spi_tcr;
spi_take_timestamp_post(dspi->ctlr, dspi->cur_transfer,
dspi->tx - dspi->bytes_per_word, !dspi->irq);
/* Get transfer counter (in number of SPI transfers). It was /* Get transfer counter (in number of SPI transfers). It was
* reset to 0 when transfer(s) were started. * reset to 0 when transfer(s) were started.
*/ */
...@@ -672,6 +678,9 @@ static int dspi_rxtx(struct fsl_dspi *dspi) ...@@ -672,6 +678,9 @@ static int dspi_rxtx(struct fsl_dspi *dspi)
/* Success! */ /* Success! */
return 0; return 0;
spi_take_timestamp_pre(dspi->ctlr, dspi->cur_transfer,
dspi->tx, !dspi->irq);
if (trans_mode == DSPI_EOQ_MODE) if (trans_mode == DSPI_EOQ_MODE)
dspi_eoq_write(dspi); dspi_eoq_write(dspi);
else if (trans_mode == DSPI_TCFQ_MODE) else if (trans_mode == DSPI_TCFQ_MODE)
...@@ -779,6 +788,9 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr, ...@@ -779,6 +788,9 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
SPI_FRAME_EBITS(transfer->bits_per_word) | SPI_FRAME_EBITS(transfer->bits_per_word) |
SPI_CTARE_DTCP(1)); SPI_CTARE_DTCP(1));
spi_take_timestamp_pre(dspi->ctlr, dspi->cur_transfer,
dspi->tx, !dspi->irq);
trans_mode = dspi->devtype_data->trans_mode; trans_mode = dspi->devtype_data->trans_mode;
switch (trans_mode) { switch (trans_mode) {
case DSPI_EOQ_MODE: case DSPI_EOQ_MODE:
...@@ -1155,6 +1167,7 @@ static int dspi_probe(struct platform_device *pdev) ...@@ -1155,6 +1167,7 @@ static int dspi_probe(struct platform_device *pdev)
init_waitqueue_head(&dspi->waitq); init_waitqueue_head(&dspi->waitq);
poll_mode: poll_mode:
if (dspi->devtype_data->trans_mode == DSPI_DMA_MODE) { if (dspi->devtype_data->trans_mode == DSPI_DMA_MODE) {
ret = dspi_request_dma(dspi, res->start); ret = dspi_request_dma(dspi, res->start);
if (ret < 0) { if (ret < 0) {
...@@ -1166,6 +1179,8 @@ static int dspi_probe(struct platform_device *pdev) ...@@ -1166,6 +1179,8 @@ static int dspi_probe(struct platform_device *pdev)
ctlr->max_speed_hz = ctlr->max_speed_hz =
clk_get_rate(dspi->clk) / dspi->devtype_data->max_clock_factor; clk_get_rate(dspi->clk) / dspi->devtype_data->max_clock_factor;
ctlr->ptp_sts_supported = dspi->devtype_data->ptp_sts_supported;
platform_set_drvdata(pdev, ctlr); platform_set_drvdata(pdev, ctlr);
ret = spi_register_controller(ctlr); ret = spi_register_controller(ctlr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment