1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * Driver for NXP PN532 NFC Chip - UART transport layer |
4 | * |
5 | * Copyright (C) 2018 Lemonage Software GmbH |
6 | * Author: Lars Pöschel <poeschel@lemonage.de> |
7 | * All rights reserved. |
8 | */ |
9 | |
10 | #include <linux/device.h> |
11 | #include <linux/kernel.h> |
12 | #include <linux/module.h> |
13 | #include <linux/nfc.h> |
14 | #include <linux/netdevice.h> |
15 | #include <linux/of.h> |
16 | #include <linux/serdev.h> |
17 | #include "pn533.h" |
18 | |
19 | #define PN532_UART_SKB_BUFF_LEN (PN533_CMD_DATAEXCH_DATA_MAXLEN * 2) |
20 | |
21 | enum send_wakeup { |
22 | PN532_SEND_NO_WAKEUP = 0, |
23 | PN532_SEND_WAKEUP, |
24 | PN532_SEND_LAST_WAKEUP, |
25 | }; |
26 | |
27 | |
28 | struct pn532_uart_phy { |
29 | struct serdev_device *serdev; |
30 | struct sk_buff *recv_skb; |
31 | struct pn533 *priv; |
32 | /* |
33 | * send_wakeup variable is used to control if we need to send a wakeup |
34 | * request to the pn532 chip prior to our actual command. There is a |
35 | * little propability of a race condition. We decided to not mutex the |
36 | * variable as the worst that could happen is, that we send a wakeup |
37 | * to the chip that is already awake. This does not hurt. It is a |
38 | * no-op to the chip. |
39 | */ |
40 | enum send_wakeup send_wakeup; |
41 | struct timer_list cmd_timeout; |
42 | struct sk_buff *cur_out_buf; |
43 | }; |
44 | |
45 | static int pn532_uart_send_frame(struct pn533 *dev, |
46 | struct sk_buff *out) |
47 | { |
48 | /* wakeup sequence and dummy bytes for waiting time */ |
49 | static const u8 wakeup[] = { |
50 | 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
51 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
52 | struct pn532_uart_phy *pn532 = dev->phy; |
53 | int err; |
54 | |
55 | print_hex_dump_debug("PN532_uart TX: " , DUMP_PREFIX_NONE, 16, 1, |
56 | out->data, out->len, false); |
57 | |
58 | pn532->cur_out_buf = out; |
59 | if (pn532->send_wakeup) { |
60 | err = serdev_device_write(pn532->serdev, |
61 | wakeup, sizeof(wakeup), |
62 | MAX_SCHEDULE_TIMEOUT); |
63 | if (err < 0) |
64 | return err; |
65 | } |
66 | |
67 | if (pn532->send_wakeup == PN532_SEND_LAST_WAKEUP) |
68 | pn532->send_wakeup = PN532_SEND_NO_WAKEUP; |
69 | |
70 | err = serdev_device_write(pn532->serdev, out->data, out->len, |
71 | MAX_SCHEDULE_TIMEOUT); |
72 | if (err < 0) |
73 | return err; |
74 | |
75 | mod_timer(timer: &pn532->cmd_timeout, HZ / 40 + jiffies); |
76 | return 0; |
77 | } |
78 | |
79 | static int pn532_uart_send_ack(struct pn533 *dev, gfp_t flags) |
80 | { |
81 | /* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */ |
82 | static const u8 ack[PN533_STD_FRAME_ACK_SIZE] = { |
83 | 0x00, 0x00, 0xff, 0x00, 0xff, 0x00}; |
84 | struct pn532_uart_phy *pn532 = dev->phy; |
85 | int err; |
86 | |
87 | err = serdev_device_write(pn532->serdev, ack, sizeof(ack), |
88 | MAX_SCHEDULE_TIMEOUT); |
89 | if (err < 0) |
90 | return err; |
91 | |
92 | return 0; |
93 | } |
94 | |
95 | static void pn532_uart_abort_cmd(struct pn533 *dev, gfp_t flags) |
96 | { |
97 | /* An ack will cancel the last issued command */ |
98 | pn532_uart_send_ack(dev, flags); |
99 | /* schedule cmd_complete_work to finish current command execution */ |
100 | pn533_recv_frame(dev, NULL, status: -ENOENT); |
101 | } |
102 | |
103 | static int pn532_dev_up(struct pn533 *dev) |
104 | { |
105 | struct pn532_uart_phy *pn532 = dev->phy; |
106 | int ret = 0; |
107 | |
108 | ret = serdev_device_open(pn532->serdev); |
109 | if (ret) |
110 | return ret; |
111 | |
112 | pn532->send_wakeup = PN532_SEND_LAST_WAKEUP; |
113 | return ret; |
114 | } |
115 | |
116 | static int pn532_dev_down(struct pn533 *dev) |
117 | { |
118 | struct pn532_uart_phy *pn532 = dev->phy; |
119 | |
120 | serdev_device_close(pn532->serdev); |
121 | pn532->send_wakeup = PN532_SEND_WAKEUP; |
122 | |
123 | return 0; |
124 | } |
125 | |
126 | static const struct pn533_phy_ops uart_phy_ops = { |
127 | .send_frame = pn532_uart_send_frame, |
128 | .send_ack = pn532_uart_send_ack, |
129 | .abort_cmd = pn532_uart_abort_cmd, |
130 | .dev_up = pn532_dev_up, |
131 | .dev_down = pn532_dev_down, |
132 | }; |
133 | |
134 | static void pn532_cmd_timeout(struct timer_list *t) |
135 | { |
136 | struct pn532_uart_phy *dev = from_timer(dev, t, cmd_timeout); |
137 | |
138 | pn532_uart_send_frame(dev: dev->priv, out: dev->cur_out_buf); |
139 | } |
140 | |
141 | /* |
142 | * scans the buffer if it contains a pn532 frame. It is not checked if the |
143 | * frame is really valid. This is later done with pn533_rx_frame_is_valid. |
144 | * This is useful for malformed or errornous transmitted frames. Adjusts the |
145 | * bufferposition where the frame starts, since pn533_recv_frame expects a |
146 | * well formed frame. |
147 | */ |
148 | static int pn532_uart_rx_is_frame(struct sk_buff *skb) |
149 | { |
150 | struct pn533_std_frame *std; |
151 | struct pn533_ext_frame *ext; |
152 | u16 frame_len; |
153 | int i; |
154 | |
155 | for (i = 0; i + PN533_STD_FRAME_ACK_SIZE <= skb->len; i++) { |
156 | std = (struct pn533_std_frame *)&skb->data[i]; |
157 | /* search start code */ |
158 | if (std->start_frame != cpu_to_be16(PN533_STD_FRAME_SOF)) |
159 | continue; |
160 | |
161 | /* frame type */ |
162 | switch (std->datalen) { |
163 | case PN533_FRAME_DATALEN_ACK: |
164 | if (std->datalen_checksum == 0xff) { |
165 | skb_pull(skb, len: i); |
166 | return 1; |
167 | } |
168 | |
169 | break; |
170 | case PN533_FRAME_DATALEN_ERROR: |
171 | if ((std->datalen_checksum == 0xff) && |
172 | (skb->len >= |
173 | PN533_STD_ERROR_FRAME_SIZE)) { |
174 | skb_pull(skb, len: i); |
175 | return 1; |
176 | } |
177 | |
178 | break; |
179 | case PN533_FRAME_DATALEN_EXTENDED: |
180 | ext = (struct pn533_ext_frame *)&skb->data[i]; |
181 | frame_len = be16_to_cpu(ext->datalen); |
182 | if (skb->len >= frame_len + |
183 | sizeof(struct pn533_ext_frame) + |
184 | 2 /* CKS + Postamble */) { |
185 | skb_pull(skb, len: i); |
186 | return 1; |
187 | } |
188 | |
189 | break; |
190 | default: /* normal information frame */ |
191 | frame_len = std->datalen; |
192 | if (skb->len >= frame_len + |
193 | sizeof(struct pn533_std_frame) + |
194 | 2 /* CKS + Postamble */) { |
195 | skb_pull(skb, len: i); |
196 | return 1; |
197 | } |
198 | |
199 | break; |
200 | } |
201 | } |
202 | |
203 | return 0; |
204 | } |
205 | |
206 | static size_t pn532_receive_buf(struct serdev_device *serdev, |
207 | const u8 *data, size_t count) |
208 | { |
209 | struct pn532_uart_phy *dev = serdev_device_get_drvdata(serdev); |
210 | size_t i; |
211 | |
212 | del_timer(timer: &dev->cmd_timeout); |
213 | for (i = 0; i < count; i++) { |
214 | skb_put_u8(skb: dev->recv_skb, val: *data++); |
215 | if (!pn532_uart_rx_is_frame(skb: dev->recv_skb)) |
216 | continue; |
217 | |
218 | pn533_recv_frame(dev: dev->priv, skb: dev->recv_skb, status: 0); |
219 | dev->recv_skb = alloc_skb(PN532_UART_SKB_BUFF_LEN, GFP_KERNEL); |
220 | if (!dev->recv_skb) |
221 | return 0; |
222 | } |
223 | |
224 | return i; |
225 | } |
226 | |
227 | static const struct serdev_device_ops pn532_serdev_ops = { |
228 | .receive_buf = pn532_receive_buf, |
229 | .write_wakeup = serdev_device_write_wakeup, |
230 | }; |
231 | |
232 | static const struct of_device_id pn532_uart_of_match[] = { |
233 | { .compatible = "nxp,pn532" , }, |
234 | {}, |
235 | }; |
236 | MODULE_DEVICE_TABLE(of, pn532_uart_of_match); |
237 | |
238 | static int pn532_uart_probe(struct serdev_device *serdev) |
239 | { |
240 | struct pn532_uart_phy *pn532; |
241 | struct pn533 *priv; |
242 | int err; |
243 | |
244 | err = -ENOMEM; |
245 | pn532 = kzalloc(size: sizeof(*pn532), GFP_KERNEL); |
246 | if (!pn532) |
247 | goto err_exit; |
248 | |
249 | pn532->recv_skb = alloc_skb(PN532_UART_SKB_BUFF_LEN, GFP_KERNEL); |
250 | if (!pn532->recv_skb) |
251 | goto err_free; |
252 | |
253 | pn532->serdev = serdev; |
254 | serdev_device_set_drvdata(serdev, data: pn532); |
255 | serdev_device_set_client_ops(serdev, ops: &pn532_serdev_ops); |
256 | err = serdev_device_open(serdev); |
257 | if (err) { |
258 | dev_err(&serdev->dev, "Unable to open device\n" ); |
259 | goto err_skb; |
260 | } |
261 | |
262 | err = serdev_device_set_baudrate(serdev, 115200); |
263 | if (err != 115200) { |
264 | err = -EINVAL; |
265 | goto err_serdev; |
266 | } |
267 | |
268 | serdev_device_set_flow_control(serdev, false); |
269 | pn532->send_wakeup = PN532_SEND_WAKEUP; |
270 | timer_setup(&pn532->cmd_timeout, pn532_cmd_timeout, 0); |
271 | priv = pn53x_common_init(PN533_DEVICE_PN532_AUTOPOLL, |
272 | protocol_type: PN533_PROTO_REQ_ACK_RESP, |
273 | phy: pn532, phy_ops: &uart_phy_ops, NULL, |
274 | dev: &pn532->serdev->dev); |
275 | if (IS_ERR(ptr: priv)) { |
276 | err = PTR_ERR(ptr: priv); |
277 | goto err_serdev; |
278 | } |
279 | |
280 | pn532->priv = priv; |
281 | err = pn533_finalize_setup(dev: pn532->priv); |
282 | if (err) |
283 | goto err_clean; |
284 | |
285 | serdev_device_close(serdev); |
286 | err = pn53x_register_nfc(priv, PN533_NO_TYPE_B_PROTOCOLS, parent: &serdev->dev); |
287 | if (err) { |
288 | pn53x_common_clean(priv: pn532->priv); |
289 | goto err_skb; |
290 | } |
291 | |
292 | return err; |
293 | |
294 | err_clean: |
295 | pn53x_common_clean(priv: pn532->priv); |
296 | err_serdev: |
297 | serdev_device_close(serdev); |
298 | err_skb: |
299 | kfree_skb(skb: pn532->recv_skb); |
300 | err_free: |
301 | kfree(objp: pn532); |
302 | err_exit: |
303 | return err; |
304 | } |
305 | |
306 | static void pn532_uart_remove(struct serdev_device *serdev) |
307 | { |
308 | struct pn532_uart_phy *pn532 = serdev_device_get_drvdata(serdev); |
309 | |
310 | pn53x_unregister_nfc(priv: pn532->priv); |
311 | serdev_device_close(serdev); |
312 | pn53x_common_clean(priv: pn532->priv); |
313 | timer_shutdown_sync(timer: &pn532->cmd_timeout); |
314 | kfree_skb(skb: pn532->recv_skb); |
315 | kfree(objp: pn532); |
316 | } |
317 | |
318 | static struct serdev_device_driver pn532_uart_driver = { |
319 | .probe = pn532_uart_probe, |
320 | .remove = pn532_uart_remove, |
321 | .driver = { |
322 | .name = "pn532_uart" , |
323 | .of_match_table = pn532_uart_of_match, |
324 | }, |
325 | }; |
326 | |
327 | module_serdev_device_driver(pn532_uart_driver); |
328 | |
329 | MODULE_AUTHOR("Lars Pöschel <poeschel@lemonage.de>" ); |
330 | MODULE_DESCRIPTION("PN532 UART driver" ); |
331 | MODULE_LICENSE("GPL" ); |
332 | |