xref: /rk3399_rockchip-uboot/common/dfu.c (revision 05341a87646aceac90a63624fbd5fa620f8dc263)
1 /*
2  * dfu.c -- dfu command
3  *
4  * Copyright (C) 2015
5  * Lukasz Majewski <l.majewski@majess.pl>
6  *
7  * Copyright (C) 2012 Samsung Electronics
8  * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
9  *	    Lukasz Majewski <l.majewski@samsung.com>
10  *
11  * SPDX-License-Identifier:	GPL-2.0+
12  */
13 
14 #include <common.h>
15 #include <watchdog.h>
16 #include <dfu.h>
17 #include <console.h>
18 #include <g_dnl.h>
19 #include <usb.h>
20 #include <net.h>
21 
22 int run_usb_dnl_gadget(int usbctrl_index, char *usb_dnl_gadget)
23 {
24 	bool dfu_reset = false;
25 	int ret, i = 0;
26 
27 	board_usb_init(usbctrl_index, USB_INIT_DEVICE);
28 	g_dnl_clear_detach();
29 	g_dnl_register(usb_dnl_gadget);
30 	while (1) {
31 		if (g_dnl_detach()) {
32 			/*
33 			 * Check if USB bus reset is performed after detach,
34 			 * which indicates that -R switch has been passed to
35 			 * dfu-util. In this case reboot the device
36 			 */
37 			if (dfu_usb_get_reset()) {
38 				dfu_reset = true;
39 				goto exit;
40 			}
41 
42 			/*
43 			 * This extra number of usb_gadget_handle_interrupts()
44 			 * calls is necessary to assure correct transmission
45 			 * completion with dfu-util
46 			 */
47 			if (++i == 10000)
48 				goto exit;
49 		}
50 
51 		if (ctrlc())
52 			goto exit;
53 
54 		if (dfu_get_defer_flush()) {
55 			/*
56 			 * Call to usb_gadget_handle_interrupts() is necessary
57 			 * to act on ZLP OUT transaction from HOST PC after
58 			 * transmitting the whole file.
59 			 *
60 			 * If this ZLP OUT packet is NAK'ed, the HOST libusb
61 			 * function fails after timeout (by default it is set to
62 			 * 5 seconds). In such situation the dfu-util program
63 			 * exits with error message.
64 			 */
65 			usb_gadget_handle_interrupts(usbctrl_index);
66 			ret = dfu_flush(dfu_get_defer_flush(), NULL, 0, 0);
67 			dfu_set_defer_flush(NULL);
68 			if (ret) {
69 				error("Deferred dfu_flush() failed!");
70 				goto exit;
71 			}
72 		}
73 
74 		WATCHDOG_RESET();
75 		usb_gadget_handle_interrupts(usbctrl_index);
76 	}
77 exit:
78 	g_dnl_unregister();
79 	board_usb_cleanup(usbctrl_index, USB_INIT_DEVICE);
80 
81 	if (dfu_reset)
82 		run_command("reset", 0);
83 
84 	g_dnl_clear_detach();
85 
86 	return ret;
87 }
88