spi_statistics_add_transfer_stats(statm, xfer, ctlr);
                spi_statistics_add_transfer_stats(stats, xfer, ctlr);
 
+               if (!ctlr->ptp_sts_supported) {
+                       xfer->ptp_sts_word_pre = 0;
+                       ptp_read_system_prets(xfer->ptp_sts);
+               }
+
                if (xfer->tx_buf || xfer->rx_buf) {
                        reinit_completion(&ctlr->xfer_completion);
 
                                        xfer->len);
                }
 
+               if (!ctlr->ptp_sts_supported) {
+                       ptp_read_system_postts(xfer->ptp_sts);
+                       xfer->ptp_sts_word_post = xfer->len;
+               }
+
                trace_spi_transfer_stop(msg, xfer);
 
                if (msg->status != -EINPROGRESS)
  */
 static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread)
 {
+       struct spi_transfer *xfer;
        struct spi_message *msg;
        bool was_busy = false;
        unsigned long flags;
                goto out;
        }
 
+       if (!ctlr->ptp_sts_supported && !ctlr->transfer_one) {
+               list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+                       xfer->ptp_sts_word_pre = 0;
+                       ptp_read_system_prets(xfer->ptp_sts);
+               }
+       }
+
        ret = ctlr->transfer_one_message(ctlr, msg);
        if (ret) {
                dev_err(&ctlr->dev,
        __spi_pump_messages(ctlr, true);
 }
 
+/**
+ * spi_take_timestamp_pre - helper for drivers to collect the beginning of the
+ *                         TX timestamp for the requested byte from the SPI
+ *                         transfer. The frequency with which this function
+ *                         must be called (once per word, once for the whole
+ *                         transfer, once per batch of words etc) is arbitrary
+ *                         as long as the @tx buffer offset is greater than or
+ *                         equal to the requested byte at the time of the
+ *                         call. The timestamp is only taken once, at the
+ *                         first such call. It is assumed that the driver
+ *                         advances its @tx buffer pointer monotonically.
+ * @ctlr: Pointer to the spi_controller structure of the driver
+ * @xfer: Pointer to the transfer being timestamped
+ * @tx: Pointer to the current word within the xfer->tx_buf that the driver is
+ *     preparing to transmit right now.
+ * @irqs_off: If true, will disable IRQs and preemption for the duration of the
+ *           transfer, for less jitter in time measurement. Only compatible
+ *           with PIO drivers. If true, must follow up with
+ *           spi_take_timestamp_post or otherwise system will crash.
+ *           WARNING: for fully predictable results, the CPU frequency must
+ *           also be under control (governor).
+ */
+void spi_take_timestamp_pre(struct spi_controller *ctlr,
+                           struct spi_transfer *xfer,
+                           const void *tx, bool irqs_off)
+{
+       u8 bytes_per_word = DIV_ROUND_UP(xfer->bits_per_word, 8);
+
+       if (!xfer->ptp_sts)
+               return;
+
+       if (xfer->timestamped_pre)
+               return;
+
+       if (tx < (xfer->tx_buf + xfer->ptp_sts_word_pre * bytes_per_word))
+               return;
+
+       /* Capture the resolution of the timestamp */
+       xfer->ptp_sts_word_pre = (tx - xfer->tx_buf) / bytes_per_word;
+
+       xfer->timestamped_pre = true;
+
+       if (irqs_off) {
+               local_irq_save(ctlr->irq_flags);
+               preempt_disable();
+       }
+
+       ptp_read_system_prets(xfer->ptp_sts);
+}
+EXPORT_SYMBOL_GPL(spi_take_timestamp_pre);
+
+/**
+ * spi_take_timestamp_post - helper for drivers to collect the end of the
+ *                          TX timestamp for the requested byte from the SPI
+ *                          transfer. Can be called with an arbitrary
+ *                          frequency: only the first call where @tx exceeds
+ *                          or is equal to the requested word will be
+ *                          timestamped.
+ * @ctlr: Pointer to the spi_controller structure of the driver
+ * @xfer: Pointer to the transfer being timestamped
+ * @tx: Pointer to the current word within the xfer->tx_buf that the driver has
+ *     just transmitted.
+ * @irqs_off: If true, will re-enable IRQs and preemption for the local CPU.
+ */
+void spi_take_timestamp_post(struct spi_controller *ctlr,
+                            struct spi_transfer *xfer,
+                            const void *tx, bool irqs_off)
+{
+       u8 bytes_per_word = DIV_ROUND_UP(xfer->bits_per_word, 8);
+
+       if (!xfer->ptp_sts)
+               return;
+
+       if (xfer->timestamped_post)
+               return;
+
+       if (tx < (xfer->tx_buf + xfer->ptp_sts_word_post * bytes_per_word))
+               return;
+
+       ptp_read_system_postts(xfer->ptp_sts);
+
+       if (irqs_off) {
+               local_irq_restore(ctlr->irq_flags);
+               preempt_enable();
+       }
+
+       /* Capture the resolution of the timestamp */
+       xfer->ptp_sts_word_post = (tx - xfer->tx_buf) / bytes_per_word;
+
+       xfer->timestamped_post = true;
+}
+EXPORT_SYMBOL_GPL(spi_take_timestamp_post);
+
 /**
  * spi_set_thread_rt - set the controller to pump at realtime priority
  * @ctlr: controller to boost priority of
  */
 void spi_finalize_current_message(struct spi_controller *ctlr)
 {
+       struct spi_transfer *xfer;
        struct spi_message *mesg;
        unsigned long flags;
        int ret;
        mesg = ctlr->cur_msg;
        spin_unlock_irqrestore(&ctlr->queue_lock, flags);
 
+       if (!ctlr->ptp_sts_supported && !ctlr->transfer_one) {
+               list_for_each_entry(xfer, &mesg->transfers, transfer_list) {
+                       ptp_read_system_postts(xfer->ptp_sts);
+                       xfer->ptp_sts_word_post = xfer->len;
+               }
+       }
+
        spi_unmap_msg(ctlr, mesg);
 
        if (ctlr->cur_msg_prepared && ctlr->unprepare_message) {
 static int __spi_async(struct spi_device *spi, struct spi_message *message)
 {
        struct spi_controller *ctlr = spi->controller;
+       struct spi_transfer *xfer;
 
        /*
         * Some controllers do not support doing regular SPI transfers. Return
 
        trace_spi_message_submit(message);
 
+       if (!ctlr->ptp_sts_supported) {
+               list_for_each_entry(xfer, &message->transfers, transfer_list) {
+                       xfer->ptp_sts_word_pre = 0;
+                       ptp_read_system_prets(xfer->ptp_sts);
+               }
+       }
+
        return ctlr->transfer(spi, message);
 }
 
 
 #include <linux/completion.h>
 #include <linux/scatterlist.h>
 #include <linux/gpio/consumer.h>
+#include <linux/ptp_clock_kernel.h>
 
 struct dma_chan;
 struct property_entry;
  * @fw_translate_cs: If the boot firmware uses different numbering scheme
  *     what Linux expects, this optional hook can be used to translate
  *     between the two.
+ * @ptp_sts_supported: If the driver sets this to true, it must provide a
+ *     time snapshot in @spi_transfer->ptp_sts as close as possible to the
+ *     moment in time when @spi_transfer->ptp_sts_word_pre and
+ *     @spi_transfer->ptp_sts_word_post were transmitted.
+ *     If the driver does not set this, the SPI core takes the snapshot as
+ *     close to the driver hand-over as possible.
  *
  * Each SPI controller can communicate with one or more @spi_device
  * children.  These make a small bus, sharing MOSI, MISO and SCK signals
        void                    *dummy_tx;
 
        int (*fw_translate_cs)(struct spi_controller *ctlr, unsigned cs);
+
+       /*
+        * Driver sets this field to indicate it is able to snapshot SPI
+        * transfers (needed e.g. for reading the time of POSIX clocks)
+        */
+       bool                    ptp_sts_supported;
+
+       /* Interrupt enable state during PTP system timestamping */
+       unsigned long           irq_flags;
 };
 
 static inline void *spi_controller_get_devdata(struct spi_controller *ctlr)
 extern void spi_finalize_current_message(struct spi_controller *ctlr);
 extern void spi_finalize_current_transfer(struct spi_controller *ctlr);
 
+/* Helper calls for driver to timestamp transfer */
+void spi_take_timestamp_pre(struct spi_controller *ctlr,
+                           struct spi_transfer *xfer,
+                           const void *tx, bool irqs_off);
+void spi_take_timestamp_post(struct spi_controller *ctlr,
+                            struct spi_transfer *xfer,
+                            const void *tx, bool irqs_off);
+
 /* the spi driver core manages memory for the spi_controller classdev */
 extern struct spi_controller *__spi_alloc_controller(struct device *host,
                                                unsigned int size, bool slave);
  * @transfer_list: transfers are sequenced through @spi_message.transfers
  * @tx_sg: Scatterlist for transmit, currently not for client use
  * @rx_sg: Scatterlist for receive, currently not for client use
+ * @ptp_sts_word_pre: The word (subject to bits_per_word semantics) offset
+ *     within @tx_buf for which the SPI device is requesting that the time
+ *     snapshot for this transfer begins. Upon completing the SPI transfer,
+ *     this value may have changed compared to what was requested, depending
+ *     on the available snapshotting resolution (DMA transfer,
+ *     @ptp_sts_supported is false, etc).
+ * @ptp_sts_word_post: See @ptp_sts_word_post. The two can be equal (meaning
+ *     that a single byte should be snapshotted).
+ *     If the core takes care of the timestamp (if @ptp_sts_supported is false
+ *     for this controller), it will set @ptp_sts_word_pre to 0, and
+ *     @ptp_sts_word_post to the length of the transfer. This is done
+ *     purposefully (instead of setting to spi_transfer->len - 1) to denote
+ *     that a transfer-level snapshot taken from within the driver may still
+ *     be of higher quality.
+ * @ptp_sts: Pointer to a memory location held by the SPI slave device where a
+ *     PTP system timestamp structure may lie. If drivers use PIO or their
+ *     hardware has some sort of assist for retrieving exact transfer timing,
+ *     they can (and should) assert @ptp_sts_supported and populate this
+ *     structure using the ptp_read_system_*ts helper functions.
+ *     The timestamp must represent the time at which the SPI slave device has
+ *     processed the word, i.e. the "pre" timestamp should be taken before
+ *     transmitting the "pre" word, and the "post" timestamp after receiving
+ *     transmit confirmation from the controller for the "post" word.
+ * @timestamped_pre: Set by the SPI controller driver to denote it has acted
+ *     upon the @ptp_sts request. Not set when the SPI core has taken care of
+ *     the task. SPI device drivers are free to print a warning if this comes
+ *     back unset and they need the better resolution.
+ * @timestamped_post: See above. The reason why both exist is that these
+ *     booleans are also used to keep state in the core SPI logic.
  *
  * SPI transfers always write the same number of bytes as they read.
  * Protocol drivers should always provide @rx_buf and/or @tx_buf.
 
        u32             effective_speed_hz;
 
+       unsigned int    ptp_sts_word_pre;
+       unsigned int    ptp_sts_word_post;
+
+       struct ptp_system_timestamp *ptp_sts;
+
+       bool            timestamped_pre;
+       bool            timestamped_post;
+
        struct list_head transfer_list;
 };