diff options
author | Eric Lapuyade <eric.lapuyade@linux.intel.com> | 2013-09-05 05:02:21 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2013-09-24 19:35:41 -0400 |
commit | fa544fff62aeeb0cf8008c61077aae10fb1407a9 (patch) | |
tree | 42e24efbcaca24ad48bde91259696649388483d3 /net/nfc | |
parent | 08f13acff960d6c95a371f67ab98785aa9969179 (diff) |
NFC: NCI: Simplify NCI SPI to become a simple framing/checking layer
NCI SPI layer should not manage the nci dev, this is the job of the nci
chipset driver. This layer should be limited to frame/deframe nci
packets, and optionnaly check integrity (crc) and manage the ack/nak
protocol.
The NCI SPI must not be mixed up with an NCI dev. spi_[dev|device] are
therefore renamed to a simple spi for more clarity.
The header and crc sizes are moved to nci.h so that drivers can use
them to reserve space in outgoing skbs.
nci_spi_send() is exported to be accessible by drivers.
Signed-off-by: Eric Lapuyade <eric.lapuyade@intel.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net/nfc')
-rw-r--r-- | net/nfc/nci/spi.c | 180 |
1 files changed, 55 insertions, 125 deletions
diff --git a/net/nfc/nci/spi.c b/net/nfc/nci/spi.c index e66fda4d9ede..910dfd8015f4 100644 --- a/net/nfc/nci/spi.c +++ b/net/nfc/nci/spi.c | |||
@@ -24,8 +24,6 @@ | |||
24 | #include <linux/nfc.h> | 24 | #include <linux/nfc.h> |
25 | #include <net/nfc/nci_core.h> | 25 | #include <net/nfc/nci_core.h> |
26 | 26 | ||
27 | #define NCI_SPI_HDR_LEN 4 | ||
28 | #define NCI_SPI_CRC_LEN 2 | ||
29 | #define NCI_SPI_ACK_SHIFT 6 | 27 | #define NCI_SPI_ACK_SHIFT 6 |
30 | #define NCI_SPI_MSB_PAYLOAD_MASK 0x3F | 28 | #define NCI_SPI_MSB_PAYLOAD_MASK 0x3F |
31 | 29 | ||
@@ -41,21 +39,7 @@ | |||
41 | 39 | ||
42 | #define CRC_INIT 0xFFFF | 40 | #define CRC_INIT 0xFFFF |
43 | 41 | ||
44 | static int nci_spi_open(struct nci_dev *ndev) | 42 | static int __nci_spi_send(struct nci_spi *nspi, struct sk_buff *skb) |
45 | { | ||
46 | struct nci_spi_dev *nsdev = nci_get_drvdata(ndev); | ||
47 | |||
48 | return nsdev->ops->open(nsdev); | ||
49 | } | ||
50 | |||
51 | static int nci_spi_close(struct nci_dev *ndev) | ||
52 | { | ||
53 | struct nci_spi_dev *nsdev = nci_get_drvdata(ndev); | ||
54 | |||
55 | return nsdev->ops->close(nsdev); | ||
56 | } | ||
57 | |||
58 | static int __nci_spi_send(struct nci_spi_dev *nsdev, struct sk_buff *skb) | ||
59 | { | 43 | { |
60 | struct spi_message m; | 44 | struct spi_message m; |
61 | struct spi_transfer t; | 45 | struct spi_transfer t; |
@@ -63,32 +47,31 @@ static int __nci_spi_send(struct nci_spi_dev *nsdev, struct sk_buff *skb) | |||
63 | t.tx_buf = skb->data; | 47 | t.tx_buf = skb->data; |
64 | t.len = skb->len; | 48 | t.len = skb->len; |
65 | t.cs_change = 0; | 49 | t.cs_change = 0; |
66 | t.delay_usecs = nsdev->xfer_udelay; | 50 | t.delay_usecs = nspi->xfer_udelay; |
67 | 51 | ||
68 | spi_message_init(&m); | 52 | spi_message_init(&m); |
69 | spi_message_add_tail(&t, &m); | 53 | spi_message_add_tail(&t, &m); |
70 | 54 | ||
71 | return spi_sync(nsdev->spi, &m); | 55 | return spi_sync(nspi->spi, &m); |
72 | } | 56 | } |
73 | 57 | ||
74 | static int nci_spi_send(struct nci_dev *ndev, struct sk_buff *skb) | 58 | int nci_spi_send(struct nci_spi *nspi, struct sk_buff *skb) |
75 | { | 59 | { |
76 | struct nci_spi_dev *nsdev = nci_get_drvdata(ndev); | ||
77 | unsigned int payload_len = skb->len; | 60 | unsigned int payload_len = skb->len; |
78 | unsigned char *hdr; | 61 | unsigned char *hdr; |
79 | int ret; | 62 | int ret; |
80 | long completion_rc; | 63 | long completion_rc; |
81 | 64 | ||
82 | nsdev->ops->deassert_int(nsdev); | 65 | nspi->ops->deassert_int(nspi); |
83 | 66 | ||
84 | /* add the NCI SPI header to the start of the buffer */ | 67 | /* add the NCI SPI header to the start of the buffer */ |
85 | hdr = skb_push(skb, NCI_SPI_HDR_LEN); | 68 | hdr = skb_push(skb, NCI_SPI_HDR_LEN); |
86 | hdr[0] = NCI_SPI_DIRECT_WRITE; | 69 | hdr[0] = NCI_SPI_DIRECT_WRITE; |
87 | hdr[1] = nsdev->acknowledge_mode; | 70 | hdr[1] = nspi->acknowledge_mode; |
88 | hdr[2] = payload_len >> 8; | 71 | hdr[2] = payload_len >> 8; |
89 | hdr[3] = payload_len & 0xFF; | 72 | hdr[3] = payload_len & 0xFF; |
90 | 73 | ||
91 | if (nsdev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { | 74 | if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) { |
92 | u16 crc; | 75 | u16 crc; |
93 | 76 | ||
94 | crc = crc_ccitt(CRC_INIT, skb->data, skb->len); | 77 | crc = crc_ccitt(CRC_INIT, skb->data, skb->len); |
@@ -96,123 +79,70 @@ static int nci_spi_send(struct nci_dev *ndev, struct sk_buff *skb) | |||
96 | *skb_put(skb, 1) = crc & 0xFF; | 79 | *skb_put(skb, 1) = crc & 0xFF; |
97 | } | 80 | } |
98 | 81 | ||
99 | ret = __nci_spi_send(nsdev, skb); | 82 | ret = __nci_spi_send(nspi, skb); |
100 | 83 | ||
101 | kfree_skb(skb); | 84 | kfree_skb(skb); |
102 | nsdev->ops->assert_int(nsdev); | 85 | nspi->ops->assert_int(nspi); |
103 | 86 | ||
104 | if (ret != 0 || nsdev->acknowledge_mode == NCI_SPI_CRC_DISABLED) | 87 | if (ret != 0 || nspi->acknowledge_mode == NCI_SPI_CRC_DISABLED) |
105 | goto done; | 88 | goto done; |
106 | 89 | ||
107 | init_completion(&nsdev->req_completion); | 90 | init_completion(&nspi->req_completion); |
108 | completion_rc = wait_for_completion_interruptible_timeout( | 91 | completion_rc = wait_for_completion_interruptible_timeout( |
109 | &nsdev->req_completion, | 92 | &nspi->req_completion, |
110 | NCI_SPI_SEND_TIMEOUT); | 93 | NCI_SPI_SEND_TIMEOUT); |
111 | 94 | ||
112 | if (completion_rc <= 0 || nsdev->req_result == ACKNOWLEDGE_NACK) | 95 | if (completion_rc <= 0 || nspi->req_result == ACKNOWLEDGE_NACK) |
113 | ret = -EIO; | 96 | ret = -EIO; |
114 | 97 | ||
115 | done: | 98 | done: |
116 | return ret; | 99 | return ret; |
117 | } | 100 | } |
118 | 101 | EXPORT_SYMBOL_GPL(nci_spi_send); | |
119 | static struct nci_ops nci_spi_ops = { | ||
120 | .open = nci_spi_open, | ||
121 | .close = nci_spi_close, | ||
122 | .send = nci_spi_send, | ||
123 | }; | ||
124 | 102 | ||
125 | /* ---- Interface to NCI SPI drivers ---- */ | 103 | /* ---- Interface to NCI SPI drivers ---- */ |
126 | 104 | ||
127 | /** | 105 | /** |
128 | * nci_spi_allocate_device - allocate a new nci spi device | 106 | * nci_spi_allocate_spi - allocate a new nci spi |
129 | * | 107 | * |
130 | * @spi: SPI device | 108 | * @spi: SPI device |
131 | * @ops: device operations | 109 | * @ops: device operations |
132 | * @supported_protocols: NFC protocols supported by the device | 110 | * @acknowledge_mode: Acknowledge mode used by the NFC device |
133 | * @supported_se: NFC Secure Elements supported by the device | ||
134 | * @acknowledge_mode: Acknowledge mode used by the device | ||
135 | * @delay: delay between transactions in us | 111 | * @delay: delay between transactions in us |
112 | * @ndev: nci dev to send incoming nci frames to | ||
136 | */ | 113 | */ |
137 | struct nci_spi_dev *nci_spi_allocate_device(struct spi_device *spi, | 114 | struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi, |
138 | struct nci_spi_ops *ops, | 115 | struct nci_spi_ops *ops, |
139 | u32 supported_protocols, | 116 | u8 acknowledge_mode, unsigned int delay, |
140 | u32 supported_se, | 117 | struct nci_dev *ndev) |
141 | u8 acknowledge_mode, | ||
142 | unsigned int delay) | ||
143 | { | 118 | { |
144 | struct nci_spi_dev *nsdev; | 119 | struct nci_spi *nspi; |
145 | int tailroom = 0; | ||
146 | |||
147 | if (!ops->open || !ops->close || !ops->assert_int || !ops->deassert_int) | ||
148 | return NULL; | ||
149 | |||
150 | if (!supported_protocols) | ||
151 | return NULL; | ||
152 | 120 | ||
153 | nsdev = devm_kzalloc(&spi->dev, sizeof(struct nci_spi_dev), GFP_KERNEL); | 121 | if (!ops->assert_int || !ops->deassert_int) |
154 | if (!nsdev) | ||
155 | return NULL; | 122 | return NULL; |
156 | 123 | ||
157 | nsdev->ops = ops; | 124 | nspi = devm_kzalloc(&spi->dev, sizeof(struct nci_spi), GFP_KERNEL); |
158 | nsdev->acknowledge_mode = acknowledge_mode; | 125 | if (!nspi) |
159 | nsdev->xfer_udelay = delay; | ||
160 | |||
161 | if (acknowledge_mode == NCI_SPI_CRC_ENABLED) | ||
162 | tailroom += NCI_SPI_CRC_LEN; | ||
163 | |||
164 | nsdev->ndev = nci_allocate_device(&nci_spi_ops, supported_protocols, | ||
165 | NCI_SPI_HDR_LEN, tailroom); | ||
166 | if (!nsdev->ndev) | ||
167 | return NULL; | 126 | return NULL; |
168 | 127 | ||
169 | nci_set_drvdata(nsdev->ndev, nsdev); | 128 | nspi->ops = ops; |
170 | 129 | nspi->acknowledge_mode = acknowledge_mode; | |
171 | return nsdev; | 130 | nspi->xfer_udelay = delay; |
172 | } | ||
173 | EXPORT_SYMBOL_GPL(nci_spi_allocate_device); | ||
174 | |||
175 | /** | ||
176 | * nci_spi_free_device - deallocate nci spi device | ||
177 | * | ||
178 | * @nsdev: The nci spi device to deallocate | ||
179 | */ | ||
180 | void nci_spi_free_device(struct nci_spi_dev *nsdev) | ||
181 | { | ||
182 | nci_free_device(nsdev->ndev); | ||
183 | } | ||
184 | EXPORT_SYMBOL_GPL(nci_spi_free_device); | ||
185 | 131 | ||
186 | /** | 132 | nspi->ndev = ndev; |
187 | * nci_spi_register_device - register a nci spi device in the nfc subsystem | ||
188 | * | ||
189 | * @pdev: The nci spi device to register | ||
190 | */ | ||
191 | int nci_spi_register_device(struct nci_spi_dev *nsdev) | ||
192 | { | ||
193 | return nci_register_device(nsdev->ndev); | ||
194 | } | ||
195 | EXPORT_SYMBOL_GPL(nci_spi_register_device); | ||
196 | 133 | ||
197 | /** | 134 | return nspi; |
198 | * nci_spi_unregister_device - unregister a nci spi device in the nfc subsystem | ||
199 | * | ||
200 | * @dev: The nci spi device to unregister | ||
201 | */ | ||
202 | void nci_spi_unregister_device(struct nci_spi_dev *nsdev) | ||
203 | { | ||
204 | nci_unregister_device(nsdev->ndev); | ||
205 | } | 135 | } |
206 | EXPORT_SYMBOL_GPL(nci_spi_unregister_device); | 136 | EXPORT_SYMBOL_GPL(nci_spi_allocate_spi); |
207 | 137 | ||
208 | static int send_acknowledge(struct nci_spi_dev *nsdev, u8 acknowledge) | 138 | static int send_acknowledge(struct nci_spi *nspi, u8 acknowledge) |
209 | { | 139 | { |
210 | struct sk_buff *skb; | 140 | struct sk_buff *skb; |
211 | unsigned char *hdr; | 141 | unsigned char *hdr; |
212 | u16 crc; | 142 | u16 crc; |
213 | int ret; | 143 | int ret; |
214 | 144 | ||
215 | skb = nci_skb_alloc(nsdev->ndev, 0, GFP_KERNEL); | 145 | skb = nci_skb_alloc(nspi->ndev, 0, GFP_KERNEL); |
216 | 146 | ||
217 | /* add the NCI SPI header to the start of the buffer */ | 147 | /* add the NCI SPI header to the start of the buffer */ |
218 | hdr = skb_push(skb, NCI_SPI_HDR_LEN); | 148 | hdr = skb_push(skb, NCI_SPI_HDR_LEN); |
@@ -225,14 +155,14 @@ static int send_acknowledge(struct nci_spi_dev *nsdev, u8 acknowledge) | |||
225 | *skb_put(skb, 1) = crc >> 8; | 155 | *skb_put(skb, 1) = crc >> 8; |
226 | *skb_put(skb, 1) = crc & 0xFF; | 156 | *skb_put(skb, 1) = crc & 0xFF; |
227 | 157 | ||
228 | ret = __nci_spi_send(nsdev, skb); | 158 | ret = __nci_spi_send(nspi, skb); |
229 | 159 | ||
230 | kfree_skb(skb); | 160 | kfree_skb(skb); |
231 | 161 | ||
232 | return ret; | 162 | return ret; |
233 | } | 163 | } |
234 | 164 | ||
235 | static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *nsdev) | 165 | static struct sk_buff *__nci_spi_recv_frame(struct nci_spi *nspi) |
236 | { | 166 | { |
237 | struct sk_buff *skb; | 167 | struct sk_buff *skb; |
238 | struct spi_message m; | 168 | struct spi_message m; |
@@ -243,7 +173,7 @@ static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *nsdev) | |||
243 | 173 | ||
244 | spi_message_init(&m); | 174 | spi_message_init(&m); |
245 | req[0] = NCI_SPI_DIRECT_READ; | 175 | req[0] = NCI_SPI_DIRECT_READ; |
246 | req[1] = nsdev->acknowledge_mode; | 176 | req[1] = nspi->acknowledge_mode; |
247 | tx.tx_buf = req; | 177 | tx.tx_buf = req; |
248 | tx.len = 2; | 178 | tx.len = 2; |
249 | tx.cs_change = 0; | 179 | tx.cs_change = 0; |
@@ -252,18 +182,18 @@ static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *nsdev) | |||
252 | rx.len = 2; | 182 | rx.len = 2; |
253 | rx.cs_change = 1; | 183 | rx.cs_change = 1; |
254 | spi_message_add_tail(&rx, &m); | 184 | spi_message_add_tail(&rx, &m); |
255 | ret = spi_sync(nsdev->spi, &m); | 185 | ret = spi_sync(nspi->spi, &m); |
256 | 186 | ||
257 | if (ret) | 187 | if (ret) |
258 | return NULL; | 188 | return NULL; |
259 | 189 | ||
260 | if (nsdev->acknowledge_mode == NCI_SPI_CRC_ENABLED) | 190 | if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) |
261 | rx_len = ((resp_hdr[0] & NCI_SPI_MSB_PAYLOAD_MASK) << 8) + | 191 | rx_len = ((resp_hdr[0] & NCI_SPI_MSB_PAYLOAD_MASK) << 8) + |
262 | resp_hdr[1] + NCI_SPI_CRC_LEN; | 192 | resp_hdr[1] + NCI_SPI_CRC_LEN; |
263 | else | 193 | else |
264 | rx_len = (resp_hdr[0] << 8) | resp_hdr[1]; | 194 | rx_len = (resp_hdr[0] << 8) | resp_hdr[1]; |
265 | 195 | ||
266 | skb = nci_skb_alloc(nsdev->ndev, rx_len, GFP_KERNEL); | 196 | skb = nci_skb_alloc(nspi->ndev, rx_len, GFP_KERNEL); |
267 | if (!skb) | 197 | if (!skb) |
268 | return NULL; | 198 | return NULL; |
269 | 199 | ||
@@ -271,14 +201,14 @@ static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *nsdev) | |||
271 | rx.rx_buf = skb_put(skb, rx_len); | 201 | rx.rx_buf = skb_put(skb, rx_len); |
272 | rx.len = rx_len; | 202 | rx.len = rx_len; |
273 | rx.cs_change = 0; | 203 | rx.cs_change = 0; |
274 | rx.delay_usecs = nsdev->xfer_udelay; | 204 | rx.delay_usecs = nspi->xfer_udelay; |
275 | spi_message_add_tail(&rx, &m); | 205 | spi_message_add_tail(&rx, &m); |
276 | ret = spi_sync(nsdev->spi, &m); | 206 | ret = spi_sync(nspi->spi, &m); |
277 | 207 | ||
278 | if (ret) | 208 | if (ret) |
279 | goto receive_error; | 209 | goto receive_error; |
280 | 210 | ||
281 | if (nsdev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { | 211 | if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) { |
282 | *skb_push(skb, 1) = resp_hdr[1]; | 212 | *skb_push(skb, 1) = resp_hdr[1]; |
283 | *skb_push(skb, 1) = resp_hdr[0]; | 213 | *skb_push(skb, 1) = resp_hdr[0]; |
284 | } | 214 | } |
@@ -320,7 +250,7 @@ static u8 nci_spi_get_ack(struct sk_buff *skb) | |||
320 | /** | 250 | /** |
321 | * nci_spi_recv_frame - receive frame from NCI SPI drivers | 251 | * nci_spi_recv_frame - receive frame from NCI SPI drivers |
322 | * | 252 | * |
323 | * @nsdev: The nci spi device | 253 | * @nspi: The nci spi |
324 | * Context: can sleep | 254 | * Context: can sleep |
325 | * | 255 | * |
326 | * This call may only be used from a context that may sleep. The sleep | 256 | * This call may only be used from a context that may sleep. The sleep |
@@ -328,32 +258,32 @@ static u8 nci_spi_get_ack(struct sk_buff *skb) | |||
328 | * | 258 | * |
329 | * It returns zero on success, else a negative error code. | 259 | * It returns zero on success, else a negative error code. |
330 | */ | 260 | */ |
331 | int nci_spi_recv_frame(struct nci_spi_dev *nsdev) | 261 | int nci_spi_recv_frame(struct nci_spi *nspi) |
332 | { | 262 | { |
333 | struct sk_buff *skb; | 263 | struct sk_buff *skb; |
334 | int ret = 0; | 264 | int ret = 0; |
335 | 265 | ||
336 | nsdev->ops->deassert_int(nsdev); | 266 | nspi->ops->deassert_int(nspi); |
337 | 267 | ||
338 | /* Retrieve frame from SPI */ | 268 | /* Retrieve frame from SPI */ |
339 | skb = __nci_spi_recv_frame(nsdev); | 269 | skb = __nci_spi_recv_frame(nspi); |
340 | if (!skb) { | 270 | if (!skb) { |
341 | ret = -EIO; | 271 | ret = -EIO; |
342 | goto done; | 272 | goto done; |
343 | } | 273 | } |
344 | 274 | ||
345 | if (nsdev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { | 275 | if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) { |
346 | if (!nci_spi_check_crc(skb)) { | 276 | if (!nci_spi_check_crc(skb)) { |
347 | send_acknowledge(nsdev, ACKNOWLEDGE_NACK); | 277 | send_acknowledge(nspi, ACKNOWLEDGE_NACK); |
348 | goto done; | 278 | goto done; |
349 | } | 279 | } |
350 | 280 | ||
351 | /* In case of acknowledged mode: if ACK or NACK received, | 281 | /* In case of acknowledged mode: if ACK or NACK received, |
352 | * unblock completion of latest frame sent. | 282 | * unblock completion of latest frame sent. |
353 | */ | 283 | */ |
354 | nsdev->req_result = nci_spi_get_ack(skb); | 284 | nspi->req_result = nci_spi_get_ack(skb); |
355 | if (nsdev->req_result) | 285 | if (nspi->req_result) |
356 | complete(&nsdev->req_completion); | 286 | complete(&nspi->req_completion); |
357 | } | 287 | } |
358 | 288 | ||
359 | /* If there is no payload (ACK/NACK only frame), | 289 | /* If there is no payload (ACK/NACK only frame), |
@@ -364,14 +294,14 @@ int nci_spi_recv_frame(struct nci_spi_dev *nsdev) | |||
364 | goto done; | 294 | goto done; |
365 | } | 295 | } |
366 | 296 | ||
367 | if (nsdev->acknowledge_mode == NCI_SPI_CRC_ENABLED) | 297 | if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) |
368 | send_acknowledge(nsdev, ACKNOWLEDGE_ACK); | 298 | send_acknowledge(nspi, ACKNOWLEDGE_ACK); |
369 | 299 | ||
370 | /* Forward skb to NCI core layer */ | 300 | /* Forward skb to NCI core layer */ |
371 | ret = nci_recv_frame(nsdev->ndev, skb); | 301 | ret = nci_recv_frame(nspi->ndev, skb); |
372 | 302 | ||
373 | done: | 303 | done: |
374 | nsdev->ops->assert_int(nsdev); | 304 | nspi->ops->assert_int(nspi); |
375 | 305 | ||
376 | return ret; | 306 | return ret; |
377 | } | 307 | } |