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