root/net/nfc/nci/spi.c

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

DEFINITIONS

This source file includes following definitions.
  1. __nci_spi_send
  2. nci_spi_send
  3. nci_spi_allocate_spi
  4. send_acknowledge
  5. __nci_spi_read
  6. nci_spi_check_crc
  7. nci_spi_get_ack
  8. nci_spi_read

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) 2013  Intel Corporation. All rights reserved.
   4  */
   5 
   6 #define pr_fmt(fmt) "nci_spi: %s: " fmt, __func__
   7 
   8 #include <linux/module.h>
   9 
  10 #include <linux/export.h>
  11 #include <linux/spi/spi.h>
  12 #include <linux/crc-ccitt.h>
  13 #include <net/nfc/nci_core.h>
  14 
  15 #define NCI_SPI_ACK_SHIFT               6
  16 #define NCI_SPI_MSB_PAYLOAD_MASK        0x3F
  17 
  18 #define NCI_SPI_SEND_TIMEOUT    (NCI_CMD_TIMEOUT > NCI_DATA_TIMEOUT ? \
  19                                         NCI_CMD_TIMEOUT : NCI_DATA_TIMEOUT)
  20 
  21 #define NCI_SPI_DIRECT_WRITE    0x01
  22 #define NCI_SPI_DIRECT_READ     0x02
  23 
  24 #define ACKNOWLEDGE_NONE        0
  25 #define ACKNOWLEDGE_ACK         1
  26 #define ACKNOWLEDGE_NACK        2
  27 
  28 #define CRC_INIT                0xFFFF
  29 
  30 static int __nci_spi_send(struct nci_spi *nspi, struct sk_buff *skb,
  31                           int cs_change)
  32 {
  33         struct spi_message m;
  34         struct spi_transfer t;
  35 
  36         memset(&t, 0, sizeof(struct spi_transfer));
  37         /* a NULL skb means we just want the SPI chip select line to raise */
  38         if (skb) {
  39                 t.tx_buf = skb->data;
  40                 t.len = skb->len;
  41         } else {
  42                 /* still set tx_buf non NULL to make the driver happy */
  43                 t.tx_buf = &t;
  44                 t.len = 0;
  45         }
  46         t.cs_change = cs_change;
  47         t.delay_usecs = nspi->xfer_udelay;
  48         t.speed_hz = nspi->xfer_speed_hz;
  49 
  50         spi_message_init(&m);
  51         spi_message_add_tail(&t, &m);
  52 
  53         return spi_sync(nspi->spi, &m);
  54 }
  55 
  56 int nci_spi_send(struct nci_spi *nspi,
  57                  struct completion *write_handshake_completion,
  58                  struct sk_buff *skb)
  59 {
  60         unsigned int payload_len = skb->len;
  61         unsigned char *hdr;
  62         int ret;
  63         long completion_rc;
  64 
  65         /* add the NCI SPI header to the start of the buffer */
  66         hdr = skb_push(skb, NCI_SPI_HDR_LEN);
  67         hdr[0] = NCI_SPI_DIRECT_WRITE;
  68         hdr[1] = nspi->acknowledge_mode;
  69         hdr[2] = payload_len >> 8;
  70         hdr[3] = payload_len & 0xFF;
  71 
  72         if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) {
  73                 u16 crc;
  74 
  75                 crc = crc_ccitt(CRC_INIT, skb->data, skb->len);
  76                 skb_put_u8(skb, crc >> 8);
  77                 skb_put_u8(skb, crc & 0xFF);
  78         }
  79 
  80         if (write_handshake_completion) {
  81                 /* Trick SPI driver to raise chip select */
  82                 ret = __nci_spi_send(nspi, NULL, 1);
  83                 if (ret)
  84                         goto done;
  85 
  86                 /* wait for NFC chip hardware handshake to complete */
  87                 if (wait_for_completion_timeout(write_handshake_completion,
  88                                                 msecs_to_jiffies(1000)) == 0) {
  89                         ret = -ETIME;
  90                         goto done;
  91                 }
  92         }
  93 
  94         ret = __nci_spi_send(nspi, skb, 0);
  95         if (ret != 0 || nspi->acknowledge_mode == NCI_SPI_CRC_DISABLED)
  96                 goto done;
  97 
  98         reinit_completion(&nspi->req_completion);
  99         completion_rc = wait_for_completion_interruptible_timeout(
 100                                                         &nspi->req_completion,
 101                                                         NCI_SPI_SEND_TIMEOUT);
 102 
 103         if (completion_rc <= 0 || nspi->req_result == ACKNOWLEDGE_NACK)
 104                 ret = -EIO;
 105 
 106 done:
 107         kfree_skb(skb);
 108 
 109         return ret;
 110 }
 111 EXPORT_SYMBOL_GPL(nci_spi_send);
 112 
 113 /* ---- Interface to NCI SPI drivers ---- */
 114 
 115 /**
 116  * nci_spi_allocate_spi - allocate a new nci spi
 117  *
 118  * @spi: SPI device
 119  * @acknowledge_mode: Acknowledge mode used by the NFC device
 120  * @delay: delay between transactions in us
 121  * @ndev: nci dev to send incoming nci frames to
 122  */
 123 struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi,
 124                                      u8 acknowledge_mode, unsigned int delay,
 125                                      struct nci_dev *ndev)
 126 {
 127         struct nci_spi *nspi;
 128 
 129         nspi = devm_kzalloc(&spi->dev, sizeof(struct nci_spi), GFP_KERNEL);
 130         if (!nspi)
 131                 return NULL;
 132 
 133         nspi->acknowledge_mode = acknowledge_mode;
 134         nspi->xfer_udelay = delay;
 135         /* Use controller max SPI speed by default */
 136         nspi->xfer_speed_hz = 0;
 137         nspi->spi = spi;
 138         nspi->ndev = ndev;
 139         init_completion(&nspi->req_completion);
 140 
 141         return nspi;
 142 }
 143 EXPORT_SYMBOL_GPL(nci_spi_allocate_spi);
 144 
 145 static int send_acknowledge(struct nci_spi *nspi, u8 acknowledge)
 146 {
 147         struct sk_buff *skb;
 148         unsigned char *hdr;
 149         u16 crc;
 150         int ret;
 151 
 152         skb = nci_skb_alloc(nspi->ndev, 0, GFP_KERNEL);
 153 
 154         /* add the NCI SPI header to the start of the buffer */
 155         hdr = skb_push(skb, NCI_SPI_HDR_LEN);
 156         hdr[0] = NCI_SPI_DIRECT_WRITE;
 157         hdr[1] = NCI_SPI_CRC_ENABLED;
 158         hdr[2] = acknowledge << NCI_SPI_ACK_SHIFT;
 159         hdr[3] = 0;
 160 
 161         crc = crc_ccitt(CRC_INIT, skb->data, skb->len);
 162         skb_put_u8(skb, crc >> 8);
 163         skb_put_u8(skb, crc & 0xFF);
 164 
 165         ret = __nci_spi_send(nspi, skb, 0);
 166 
 167         kfree_skb(skb);
 168 
 169         return ret;
 170 }
 171 
 172 static struct sk_buff *__nci_spi_read(struct nci_spi *nspi)
 173 {
 174         struct sk_buff *skb;
 175         struct spi_message m;
 176         unsigned char req[2], resp_hdr[2];
 177         struct spi_transfer tx, rx;
 178         unsigned short rx_len = 0;
 179         int ret;
 180 
 181         spi_message_init(&m);
 182 
 183         memset(&tx, 0, sizeof(struct spi_transfer));
 184         req[0] = NCI_SPI_DIRECT_READ;
 185         req[1] = nspi->acknowledge_mode;
 186         tx.tx_buf = req;
 187         tx.len = 2;
 188         tx.cs_change = 0;
 189         tx.speed_hz = nspi->xfer_speed_hz;
 190         spi_message_add_tail(&tx, &m);
 191 
 192         memset(&rx, 0, sizeof(struct spi_transfer));
 193         rx.rx_buf = resp_hdr;
 194         rx.len = 2;
 195         rx.cs_change = 1;
 196         rx.speed_hz = nspi->xfer_speed_hz;
 197         spi_message_add_tail(&rx, &m);
 198 
 199         ret = spi_sync(nspi->spi, &m);
 200         if (ret)
 201                 return NULL;
 202 
 203         if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED)
 204                 rx_len = ((resp_hdr[0] & NCI_SPI_MSB_PAYLOAD_MASK) << 8) +
 205                                 resp_hdr[1] + NCI_SPI_CRC_LEN;
 206         else
 207                 rx_len = (resp_hdr[0] << 8) | resp_hdr[1];
 208 
 209         skb = nci_skb_alloc(nspi->ndev, rx_len, GFP_KERNEL);
 210         if (!skb)
 211                 return NULL;
 212 
 213         spi_message_init(&m);
 214 
 215         memset(&rx, 0, sizeof(struct spi_transfer));
 216         rx.rx_buf = skb_put(skb, rx_len);
 217         rx.len = rx_len;
 218         rx.cs_change = 0;
 219         rx.delay_usecs = nspi->xfer_udelay;
 220         rx.speed_hz = nspi->xfer_speed_hz;
 221         spi_message_add_tail(&rx, &m);
 222 
 223         ret = spi_sync(nspi->spi, &m);
 224         if (ret)
 225                 goto receive_error;
 226 
 227         if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) {
 228                 *(u8 *)skb_push(skb, 1) = resp_hdr[1];
 229                 *(u8 *)skb_push(skb, 1) = resp_hdr[0];
 230         }
 231 
 232         return skb;
 233 
 234 receive_error:
 235         kfree_skb(skb);
 236 
 237         return NULL;
 238 }
 239 
 240 static int nci_spi_check_crc(struct sk_buff *skb)
 241 {
 242         u16 crc_data = (skb->data[skb->len - 2] << 8) |
 243                         skb->data[skb->len - 1];
 244         int ret;
 245 
 246         ret = (crc_ccitt(CRC_INIT, skb->data, skb->len - NCI_SPI_CRC_LEN)
 247                         == crc_data);
 248 
 249         skb_trim(skb, skb->len - NCI_SPI_CRC_LEN);
 250 
 251         return ret;
 252 }
 253 
 254 static u8 nci_spi_get_ack(struct sk_buff *skb)
 255 {
 256         u8 ret;
 257 
 258         ret = skb->data[0] >> NCI_SPI_ACK_SHIFT;
 259 
 260         /* Remove NFCC part of the header: ACK, NACK and MSB payload len */
 261         skb_pull(skb, 2);
 262 
 263         return ret;
 264 }
 265 
 266 /**
 267  * nci_spi_read - read frame from NCI SPI drivers
 268  *
 269  * @nspi: The nci spi
 270  * Context: can sleep
 271  *
 272  * This call may only be used from a context that may sleep.  The sleep
 273  * is non-interruptible, and has no timeout.
 274  *
 275  * It returns an allocated skb containing the frame on success, or NULL.
 276  */
 277 struct sk_buff *nci_spi_read(struct nci_spi *nspi)
 278 {
 279         struct sk_buff *skb;
 280 
 281         /* Retrieve frame from SPI */
 282         skb = __nci_spi_read(nspi);
 283         if (!skb)
 284                 goto done;
 285 
 286         if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) {
 287                 if (!nci_spi_check_crc(skb)) {
 288                         send_acknowledge(nspi, ACKNOWLEDGE_NACK);
 289                         goto done;
 290                 }
 291 
 292                 /* In case of acknowledged mode: if ACK or NACK received,
 293                  * unblock completion of latest frame sent.
 294                  */
 295                 nspi->req_result = nci_spi_get_ack(skb);
 296                 if (nspi->req_result)
 297                         complete(&nspi->req_completion);
 298         }
 299 
 300         /* If there is no payload (ACK/NACK only frame),
 301          * free the socket buffer
 302          */
 303         if (!skb->len) {
 304                 kfree_skb(skb);
 305                 skb = NULL;
 306                 goto done;
 307         }
 308 
 309         if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED)
 310                 send_acknowledge(nspi, ACKNOWLEDGE_ACK);
 311 
 312 done:
 313 
 314         return skb;
 315 }
 316 EXPORT_SYMBOL_GPL(nci_spi_read);
 317 
 318 MODULE_LICENSE("GPL");

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