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