root/drivers/spi/spi-slave-time.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. spi_slave_time_complete
  2. spi_slave_time_submit
  3. spi_slave_time_probe
  4. spi_slave_time_remove

   1 /*
   2  * SPI slave handler reporting uptime at reception of previous SPI message
   3  *
   4  * This SPI slave handler sends the time of reception of the last SPI message
   5  * as two 32-bit unsigned integers in binary format and in network byte order,
   6  * representing the number of seconds and fractional seconds (in microseconds)
   7  * since boot up.
   8  *
   9  * Copyright (C) 2016-2017 Glider bvba
  10  *
  11  * This file is subject to the terms and conditions of the GNU General Public
  12  * License.  See the file "COPYING" in the main directory of this archive
  13  * for more details.
  14  *
  15  * Usage (assuming /dev/spidev2.0 corresponds to the SPI master on the remote
  16  * system):
  17  *
  18  *   # spidev_test -D /dev/spidev2.0 -p dummy-8B
  19  *   spi mode: 0x0
  20  *   bits per word: 8
  21  *   max speed: 500000 Hz (500 KHz)
  22  *   RX | 00 00 04 6D 00 09 5B BB ...
  23  *              ^^^^^    ^^^^^^^^
  24  *              seconds  microseconds
  25  */
  26 
  27 #include <linux/completion.h>
  28 #include <linux/module.h>
  29 #include <linux/sched/clock.h>
  30 #include <linux/spi/spi.h>
  31 
  32 
  33 struct spi_slave_time_priv {
  34         struct spi_device *spi;
  35         struct completion finished;
  36         struct spi_transfer xfer;
  37         struct spi_message msg;
  38         __be32 buf[2];
  39 };
  40 
  41 static int spi_slave_time_submit(struct spi_slave_time_priv *priv);
  42 
  43 static void spi_slave_time_complete(void *arg)
  44 {
  45         struct spi_slave_time_priv *priv = arg;
  46         int ret;
  47 
  48         ret = priv->msg.status;
  49         if (ret)
  50                 goto terminate;
  51 
  52         ret = spi_slave_time_submit(priv);
  53         if (ret)
  54                 goto terminate;
  55 
  56         return;
  57 
  58 terminate:
  59         dev_info(&priv->spi->dev, "Terminating\n");
  60         complete(&priv->finished);
  61 }
  62 
  63 static int spi_slave_time_submit(struct spi_slave_time_priv *priv)
  64 {
  65         u32 rem_us;
  66         int ret;
  67         u64 ts;
  68 
  69         ts = local_clock();
  70         rem_us = do_div(ts, 1000000000) / 1000;
  71 
  72         priv->buf[0] = cpu_to_be32(ts);
  73         priv->buf[1] = cpu_to_be32(rem_us);
  74 
  75         spi_message_init_with_transfers(&priv->msg, &priv->xfer, 1);
  76 
  77         priv->msg.complete = spi_slave_time_complete;
  78         priv->msg.context = priv;
  79 
  80         ret = spi_async(priv->spi, &priv->msg);
  81         if (ret)
  82                 dev_err(&priv->spi->dev, "spi_async() failed %d\n", ret);
  83 
  84         return ret;
  85 }
  86 
  87 static int spi_slave_time_probe(struct spi_device *spi)
  88 {
  89         struct spi_slave_time_priv *priv;
  90         int ret;
  91 
  92         priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);
  93         if (!priv)
  94                 return -ENOMEM;
  95 
  96         priv->spi = spi;
  97         init_completion(&priv->finished);
  98         priv->xfer.tx_buf = priv->buf;
  99         priv->xfer.len = sizeof(priv->buf);
 100 
 101         ret = spi_slave_time_submit(priv);
 102         if (ret)
 103                 return ret;
 104 
 105         spi_set_drvdata(spi, priv);
 106         return 0;
 107 }
 108 
 109 static int spi_slave_time_remove(struct spi_device *spi)
 110 {
 111         struct spi_slave_time_priv *priv = spi_get_drvdata(spi);
 112 
 113         spi_slave_abort(spi);
 114         wait_for_completion(&priv->finished);
 115         return 0;
 116 }
 117 
 118 static struct spi_driver spi_slave_time_driver = {
 119         .driver = {
 120                 .name   = "spi-slave-time",
 121         },
 122         .probe          = spi_slave_time_probe,
 123         .remove         = spi_slave_time_remove,
 124 };
 125 module_spi_driver(spi_slave_time_driver);
 126 
 127 MODULE_AUTHOR("Geert Uytterhoeven <geert+renesas@glider.be>");
 128 MODULE_DESCRIPTION("SPI slave reporting uptime at previous SPI message");
 129 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */