2 * Marvell NFC-over-USB driver: USB interface related functions
4 * Copyright (C) 2014, Marvell International Ltd.
6 * This software file (the "File") is distributed by Marvell International
7 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
8 * (the "License"). You may use, redistribute and/or modify this File in
9 * accordance with the terms and conditions of the License, a copy of which
10 * is available on the worldwide web at
11 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
14 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
15 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
16 * this warranty disclaimer.
19 #include <linux/module.h>
20 #include <linux/usb.h>
21 #include <linux/nfc.h>
22 #include <net/nfc/nci.h>
23 #include <net/nfc/nci_core.h>
26 static struct usb_device_id nfcmrvl_table
[] = {
27 { USB_DEVICE_AND_INTERFACE_INFO(0x1286, 0x2046,
28 USB_CLASS_VENDOR_SPEC
, 4, 1) },
29 { } /* Terminating entry */
32 MODULE_DEVICE_TABLE(usb
, nfcmrvl_table
);
34 #define NFCMRVL_USB_BULK_RUNNING 1
35 #define NFCMRVL_USB_SUSPENDING 2
37 struct nfcmrvl_usb_drv_data
{
38 struct usb_device
*udev
;
39 struct usb_interface
*intf
;
41 struct work_struct waker
;
42 struct usb_anchor tx_anchor
;
43 struct usb_anchor bulk_anchor
;
44 struct usb_anchor deferred
;
46 /* protects tx_in_flight */
48 struct usb_endpoint_descriptor
*bulk_tx_ep
;
49 struct usb_endpoint_descriptor
*bulk_rx_ep
;
51 struct nfcmrvl_private
*priv
;
54 static int nfcmrvl_inc_tx(struct nfcmrvl_usb_drv_data
*drv_data
)
59 spin_lock_irqsave(&drv_data
->txlock
, flags
);
60 rv
= test_bit(NFCMRVL_USB_SUSPENDING
, &drv_data
->flags
);
62 drv_data
->tx_in_flight
++;
63 spin_unlock_irqrestore(&drv_data
->txlock
, flags
);
68 static void nfcmrvl_bulk_complete(struct urb
*urb
)
70 struct nfcmrvl_usb_drv_data
*drv_data
= urb
->context
;
74 dev_dbg(&drv_data
->udev
->dev
, "urb %p status %d count %d\n",
75 urb
, urb
->status
, urb
->actual_length
);
77 if (!test_bit(NFCMRVL_NCI_RUNNING
, &drv_data
->flags
))
81 skb
= nci_skb_alloc(drv_data
->priv
->ndev
, urb
->actual_length
,
84 nfc_err(&drv_data
->udev
->dev
, "failed to alloc mem\n");
86 skb_put_data(skb
, urb
->transfer_buffer
,
88 if (nfcmrvl_nci_recv_frame(drv_data
->priv
, skb
) < 0)
89 nfc_err(&drv_data
->udev
->dev
,
90 "corrupted Rx packet\n");
94 if (!test_bit(NFCMRVL_USB_BULK_RUNNING
, &drv_data
->flags
))
97 usb_anchor_urb(urb
, &drv_data
->bulk_anchor
);
98 usb_mark_last_busy(drv_data
->udev
);
100 err
= usb_submit_urb(urb
, GFP_ATOMIC
);
102 /* -EPERM: urb is being killed;
103 * -ENODEV: device got disconnected
105 if (err
!= -EPERM
&& err
!= -ENODEV
)
106 nfc_err(&drv_data
->udev
->dev
,
107 "urb %p failed to resubmit (%d)\n", urb
, -err
);
108 usb_unanchor_urb(urb
);
113 nfcmrvl_submit_bulk_urb(struct nfcmrvl_usb_drv_data
*drv_data
, gfp_t mem_flags
)
118 int err
, size
= NFCMRVL_NCI_MAX_EVENT_SIZE
;
120 if (!drv_data
->bulk_rx_ep
)
123 urb
= usb_alloc_urb(0, mem_flags
);
127 buf
= kmalloc(size
, mem_flags
);
133 pipe
= usb_rcvbulkpipe(drv_data
->udev
,
134 drv_data
->bulk_rx_ep
->bEndpointAddress
);
136 usb_fill_bulk_urb(urb
, drv_data
->udev
, pipe
, buf
, size
,
137 nfcmrvl_bulk_complete
, drv_data
);
139 urb
->transfer_flags
|= URB_FREE_BUFFER
;
141 usb_mark_last_busy(drv_data
->udev
);
142 usb_anchor_urb(urb
, &drv_data
->bulk_anchor
);
144 err
= usb_submit_urb(urb
, mem_flags
);
146 if (err
!= -EPERM
&& err
!= -ENODEV
)
147 nfc_err(&drv_data
->udev
->dev
,
148 "urb %p submission failed (%d)\n", urb
, -err
);
149 usb_unanchor_urb(urb
);
157 static void nfcmrvl_tx_complete(struct urb
*urb
)
159 struct sk_buff
*skb
= urb
->context
;
160 struct nci_dev
*ndev
= (struct nci_dev
*)skb
->dev
;
161 struct nfcmrvl_private
*priv
= nci_get_drvdata(ndev
);
162 struct nfcmrvl_usb_drv_data
*drv_data
= priv
->drv_data
;
164 nfc_info(priv
->dev
, "urb %p status %d count %d\n",
165 urb
, urb
->status
, urb
->actual_length
);
167 spin_lock(&drv_data
->txlock
);
168 drv_data
->tx_in_flight
--;
169 spin_unlock(&drv_data
->txlock
);
171 kfree(urb
->setup_packet
);
175 static int nfcmrvl_usb_nci_open(struct nfcmrvl_private
*priv
)
177 struct nfcmrvl_usb_drv_data
*drv_data
= priv
->drv_data
;
180 err
= usb_autopm_get_interface(drv_data
->intf
);
184 drv_data
->intf
->needs_remote_wakeup
= 1;
186 err
= nfcmrvl_submit_bulk_urb(drv_data
, GFP_KERNEL
);
190 set_bit(NFCMRVL_USB_BULK_RUNNING
, &drv_data
->flags
);
191 nfcmrvl_submit_bulk_urb(drv_data
, GFP_KERNEL
);
193 usb_autopm_put_interface(drv_data
->intf
);
197 usb_autopm_put_interface(drv_data
->intf
);
201 static void nfcmrvl_usb_stop_traffic(struct nfcmrvl_usb_drv_data
*drv_data
)
203 usb_kill_anchored_urbs(&drv_data
->bulk_anchor
);
206 static int nfcmrvl_usb_nci_close(struct nfcmrvl_private
*priv
)
208 struct nfcmrvl_usb_drv_data
*drv_data
= priv
->drv_data
;
211 cancel_work_sync(&drv_data
->waker
);
213 clear_bit(NFCMRVL_USB_BULK_RUNNING
, &drv_data
->flags
);
215 nfcmrvl_usb_stop_traffic(drv_data
);
216 usb_kill_anchored_urbs(&drv_data
->tx_anchor
);
217 err
= usb_autopm_get_interface(drv_data
->intf
);
221 drv_data
->intf
->needs_remote_wakeup
= 0;
222 usb_autopm_put_interface(drv_data
->intf
);
225 usb_scuttle_anchored_urbs(&drv_data
->deferred
);
229 static int nfcmrvl_usb_nci_send(struct nfcmrvl_private
*priv
,
232 struct nfcmrvl_usb_drv_data
*drv_data
= priv
->drv_data
;
237 if (!drv_data
->bulk_tx_ep
)
240 urb
= usb_alloc_urb(0, GFP_ATOMIC
);
244 pipe
= usb_sndbulkpipe(drv_data
->udev
,
245 drv_data
->bulk_tx_ep
->bEndpointAddress
);
247 usb_fill_bulk_urb(urb
, drv_data
->udev
, pipe
, skb
->data
, skb
->len
,
248 nfcmrvl_tx_complete
, skb
);
250 err
= nfcmrvl_inc_tx(drv_data
);
252 usb_anchor_urb(urb
, &drv_data
->deferred
);
253 schedule_work(&drv_data
->waker
);
258 usb_anchor_urb(urb
, &drv_data
->tx_anchor
);
260 err
= usb_submit_urb(urb
, GFP_ATOMIC
);
262 if (err
!= -EPERM
&& err
!= -ENODEV
)
263 nfc_err(&drv_data
->udev
->dev
,
264 "urb %p submission failed (%d)\n", urb
, -err
);
265 kfree(urb
->setup_packet
);
266 usb_unanchor_urb(urb
);
268 usb_mark_last_busy(drv_data
->udev
);
276 static struct nfcmrvl_if_ops usb_ops
= {
277 .nci_open
= nfcmrvl_usb_nci_open
,
278 .nci_close
= nfcmrvl_usb_nci_close
,
279 .nci_send
= nfcmrvl_usb_nci_send
,
282 static void nfcmrvl_waker(struct work_struct
*work
)
284 struct nfcmrvl_usb_drv_data
*drv_data
=
285 container_of(work
, struct nfcmrvl_usb_drv_data
, waker
);
288 err
= usb_autopm_get_interface(drv_data
->intf
);
292 usb_autopm_put_interface(drv_data
->intf
);
295 static int nfcmrvl_probe(struct usb_interface
*intf
,
296 const struct usb_device_id
*id
)
298 struct usb_endpoint_descriptor
*ep_desc
;
299 struct nfcmrvl_usb_drv_data
*drv_data
;
300 struct nfcmrvl_private
*priv
;
302 struct usb_device
*udev
= interface_to_usbdev(intf
);
303 struct nfcmrvl_platform_data config
;
305 /* No configuration for USB */
306 memset(&config
, 0, sizeof(config
));
308 nfc_info(&udev
->dev
, "intf %p id %p\n", intf
, id
);
310 drv_data
= devm_kzalloc(&intf
->dev
, sizeof(*drv_data
), GFP_KERNEL
);
314 for (i
= 0; i
< intf
->cur_altsetting
->desc
.bNumEndpoints
; i
++) {
315 ep_desc
= &intf
->cur_altsetting
->endpoint
[i
].desc
;
317 if (!drv_data
->bulk_tx_ep
&&
318 usb_endpoint_is_bulk_out(ep_desc
)) {
319 drv_data
->bulk_tx_ep
= ep_desc
;
323 if (!drv_data
->bulk_rx_ep
&&
324 usb_endpoint_is_bulk_in(ep_desc
)) {
325 drv_data
->bulk_rx_ep
= ep_desc
;
330 if (!drv_data
->bulk_tx_ep
|| !drv_data
->bulk_rx_ep
)
333 drv_data
->udev
= udev
;
334 drv_data
->intf
= intf
;
336 INIT_WORK(&drv_data
->waker
, nfcmrvl_waker
);
337 spin_lock_init(&drv_data
->txlock
);
339 init_usb_anchor(&drv_data
->tx_anchor
);
340 init_usb_anchor(&drv_data
->bulk_anchor
);
341 init_usb_anchor(&drv_data
->deferred
);
343 priv
= nfcmrvl_nci_register_dev(NFCMRVL_PHY_USB
, drv_data
, &usb_ops
,
344 &intf
->dev
, &config
);
346 return PTR_ERR(priv
);
348 drv_data
->priv
= priv
;
349 drv_data
->priv
->support_fw_dnld
= false;
351 usb_set_intfdata(intf
, drv_data
);
356 static void nfcmrvl_disconnect(struct usb_interface
*intf
)
358 struct nfcmrvl_usb_drv_data
*drv_data
= usb_get_intfdata(intf
);
363 nfc_info(&drv_data
->udev
->dev
, "intf %p\n", intf
);
365 nfcmrvl_nci_unregister_dev(drv_data
->priv
);
367 usb_set_intfdata(drv_data
->intf
, NULL
);
371 static int nfcmrvl_suspend(struct usb_interface
*intf
, pm_message_t message
)
373 struct nfcmrvl_usb_drv_data
*drv_data
= usb_get_intfdata(intf
);
375 nfc_info(&drv_data
->udev
->dev
, "intf %p\n", intf
);
377 if (drv_data
->suspend_count
++)
380 spin_lock_irq(&drv_data
->txlock
);
381 if (!(PMSG_IS_AUTO(message
) && drv_data
->tx_in_flight
)) {
382 set_bit(NFCMRVL_USB_SUSPENDING
, &drv_data
->flags
);
383 spin_unlock_irq(&drv_data
->txlock
);
385 spin_unlock_irq(&drv_data
->txlock
);
386 drv_data
->suspend_count
--;
390 nfcmrvl_usb_stop_traffic(drv_data
);
391 usb_kill_anchored_urbs(&drv_data
->tx_anchor
);
396 static void nfcmrvl_play_deferred(struct nfcmrvl_usb_drv_data
*drv_data
)
401 while ((urb
= usb_get_from_anchor(&drv_data
->deferred
))) {
402 err
= usb_submit_urb(urb
, GFP_ATOMIC
);
406 drv_data
->tx_in_flight
++;
408 usb_scuttle_anchored_urbs(&drv_data
->deferred
);
411 static int nfcmrvl_resume(struct usb_interface
*intf
)
413 struct nfcmrvl_usb_drv_data
*drv_data
= usb_get_intfdata(intf
);
416 nfc_info(&drv_data
->udev
->dev
, "intf %p\n", intf
);
418 if (--drv_data
->suspend_count
)
421 if (!test_bit(NFCMRVL_NCI_RUNNING
, &drv_data
->flags
))
424 if (test_bit(NFCMRVL_USB_BULK_RUNNING
, &drv_data
->flags
)) {
425 err
= nfcmrvl_submit_bulk_urb(drv_data
, GFP_NOIO
);
427 clear_bit(NFCMRVL_USB_BULK_RUNNING
, &drv_data
->flags
);
431 nfcmrvl_submit_bulk_urb(drv_data
, GFP_NOIO
);
434 spin_lock_irq(&drv_data
->txlock
);
435 nfcmrvl_play_deferred(drv_data
);
436 clear_bit(NFCMRVL_USB_SUSPENDING
, &drv_data
->flags
);
437 spin_unlock_irq(&drv_data
->txlock
);
442 usb_scuttle_anchored_urbs(&drv_data
->deferred
);
444 spin_lock_irq(&drv_data
->txlock
);
445 clear_bit(NFCMRVL_USB_SUSPENDING
, &drv_data
->flags
);
446 spin_unlock_irq(&drv_data
->txlock
);
452 static struct usb_driver nfcmrvl_usb_driver
= {
454 .probe
= nfcmrvl_probe
,
455 .disconnect
= nfcmrvl_disconnect
,
457 .suspend
= nfcmrvl_suspend
,
458 .resume
= nfcmrvl_resume
,
459 .reset_resume
= nfcmrvl_resume
,
461 .id_table
= nfcmrvl_table
,
462 .supports_autosuspend
= 1,
463 .disable_hub_initiated_lpm
= 1,
466 module_usb_driver(nfcmrvl_usb_driver
);
468 MODULE_AUTHOR("Marvell International Ltd.");
469 MODULE_DESCRIPTION("Marvell NFC-over-USB driver");
470 MODULE_LICENSE("GPL v2");