Merge git://git.denx.de/u-boot-marvell
[oweals/u-boot.git] / cmd / fastboot.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2008 - 2009 Windriver, <www.windriver.com>
4  * Author: Tom Rix <Tom.Rix@windriver.com>
5  *
6  * (C) Copyright 2014 Linaro, Ltd.
7  * Rob Herring <robh@kernel.org>
8  */
9 #include <common.h>
10 #include <command.h>
11 #include <console.h>
12 #include <g_dnl.h>
13 #include <fastboot.h>
14 #include <net.h>
15 #include <usb.h>
16 #include <watchdog.h>
17
18 static int do_fastboot_udp(int argc, char *const argv[],
19                            uintptr_t buf_addr, size_t buf_size)
20 {
21 #if CONFIG_IS_ENABLED(UDP_FUNCTION_FASTBOOT)
22         int err = net_loop(FASTBOOT);
23
24         if (err < 0) {
25                 printf("fastboot udp error: %d\n", err);
26                 return CMD_RET_FAILURE;
27         }
28
29         return CMD_RET_SUCCESS;
30 #else
31         pr_err("Fastboot UDP not enabled\n");
32         return CMD_RET_FAILURE;
33 #endif
34 }
35
36 static int do_fastboot_usb(int argc, char *const argv[],
37                            uintptr_t buf_addr, size_t buf_size)
38 {
39 #if CONFIG_IS_ENABLED(USB_FUNCTION_FASTBOOT)
40         int controller_index;
41         char *usb_controller;
42         char *endp;
43         int ret;
44
45         if (argc < 2)
46                 return CMD_RET_USAGE;
47
48         usb_controller = argv[1];
49         controller_index = simple_strtoul(usb_controller, &endp, 0);
50         if (*endp != '\0') {
51                 pr_err("Error: Wrong USB controller index format\n");
52                 return CMD_RET_FAILURE;
53         }
54
55         ret = usb_gadget_initialize(controller_index);
56         if (ret) {
57                 pr_err("USB init failed: %d\n", ret);
58                 return CMD_RET_FAILURE;
59         }
60
61         g_dnl_clear_detach();
62         ret = g_dnl_register("usb_dnl_fastboot");
63         if (ret)
64                 return ret;
65
66         if (!g_dnl_board_usb_cable_connected()) {
67                 puts("\rUSB cable not detected.\n" \
68                      "Command exit.\n");
69                 ret = CMD_RET_FAILURE;
70                 goto exit;
71         }
72
73         while (1) {
74                 if (g_dnl_detach())
75                         break;
76                 if (ctrlc())
77                         break;
78                 WATCHDOG_RESET();
79                 usb_gadget_handle_interrupts(controller_index);
80         }
81
82         ret = CMD_RET_SUCCESS;
83
84 exit:
85         g_dnl_unregister();
86         g_dnl_clear_detach();
87         usb_gadget_release(controller_index);
88
89         return ret;
90 #else
91         pr_err("Fastboot USB not enabled\n");
92         return CMD_RET_FAILURE;
93 #endif
94 }
95
96 static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
97 {
98         uintptr_t buf_addr = (uintptr_t)NULL;
99         size_t buf_size = 0;
100
101         if (argc < 2)
102                 return CMD_RET_USAGE;
103
104         while (argc > 1 && **(argv + 1) == '-') {
105                 char *arg = *++argv;
106
107                 --argc;
108                 while (*++arg) {
109                         switch (*arg) {
110                         case 'l':
111                                 if (--argc <= 0)
112                                         return CMD_RET_USAGE;
113                                 buf_addr = simple_strtoul(*++argv, NULL, 16);
114                                 goto NXTARG;
115
116                         case 's':
117                                 if (--argc <= 0)
118                                         return CMD_RET_USAGE;
119                                 buf_size = simple_strtoul(*++argv, NULL, 16);
120                                 goto NXTARG;
121
122                         default:
123                                 return CMD_RET_USAGE;
124                         }
125                 }
126 NXTARG:
127                 ;
128         }
129
130         /* Handle case when USB controller param is just '-' */
131         if (argc == 1) {
132                 pr_err("Error: Incorrect USB controller index\n");
133                 return CMD_RET_USAGE;
134         }
135
136         fastboot_init((void *)buf_addr, buf_size);
137
138         if (!strcmp(argv[1], "udp"))
139                 return do_fastboot_udp(argc, argv, buf_addr, buf_size);
140
141         if (!strcmp(argv[1], "usb")) {
142                 argv++;
143                 argc--;
144         }
145
146         return do_fastboot_usb(argc, argv, buf_addr, buf_size);
147 }
148
149 #ifdef CONFIG_SYS_LONGHELP
150 static char fastboot_help_text[] =
151         "[-l addr] [-s size] usb <controller> | udp\n"
152         "\taddr - address of buffer used during data transfers ("
153         __stringify(CONFIG_FASTBOOT_BUF_ADDR) ")\n"
154         "\tsize - size of buffer used during data transfers ("
155         __stringify(CONFIG_FASTBOOT_BUF_SIZE) ")"
156         ;
157 #endif
158
159 U_BOOT_CMD(
160         fastboot, CONFIG_SYS_MAXARGS, 1, do_fastboot,
161         "run as a fastboot usb or udp device", fastboot_help_text
162 );