183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
22e192b24SSimon Glass /*
32e192b24SSimon Glass * Copyright 2008 - 2009 Windriver, <www.windriver.com>
42e192b24SSimon Glass * Author: Tom Rix <Tom.Rix@windriver.com>
52e192b24SSimon Glass *
62e192b24SSimon Glass * (C) Copyright 2014 Linaro, Ltd.
72e192b24SSimon Glass * Rob Herring <robh@kernel.org>
82e192b24SSimon Glass */
92e192b24SSimon Glass #include <common.h>
102e192b24SSimon Glass #include <command.h>
112e192b24SSimon Glass #include <console.h>
122e192b24SSimon Glass #include <g_dnl.h>
13f73a7df9SAlex Kiernan #include <fastboot.h>
14f73a7df9SAlex Kiernan #include <net.h>
152e192b24SSimon Glass #include <usb.h>
16*731785dfSSean Nyekjaer #include <watchdog.h>
172e192b24SSimon Glass
do_fastboot_udp(int argc,char * const argv[],uintptr_t buf_addr,size_t buf_size)18f73a7df9SAlex Kiernan static int do_fastboot_udp(int argc, char *const argv[],
19f73a7df9SAlex Kiernan uintptr_t buf_addr, size_t buf_size)
202e192b24SSimon Glass {
21f73a7df9SAlex Kiernan #if CONFIG_IS_ENABLED(UDP_FUNCTION_FASTBOOT)
22f73a7df9SAlex Kiernan int err = net_loop(FASTBOOT);
23f73a7df9SAlex Kiernan
24f73a7df9SAlex Kiernan if (err < 0) {
25f73a7df9SAlex Kiernan printf("fastboot udp error: %d\n", err);
26f73a7df9SAlex Kiernan return CMD_RET_FAILURE;
27f73a7df9SAlex Kiernan }
28f73a7df9SAlex Kiernan
29f73a7df9SAlex Kiernan return CMD_RET_SUCCESS;
30f73a7df9SAlex Kiernan #else
31f73a7df9SAlex Kiernan pr_err("Fastboot UDP not enabled\n");
32f73a7df9SAlex Kiernan return CMD_RET_FAILURE;
33f73a7df9SAlex Kiernan #endif
34f73a7df9SAlex Kiernan }
35f73a7df9SAlex Kiernan
do_fastboot_usb(int argc,char * const argv[],uintptr_t buf_addr,size_t buf_size)36f73a7df9SAlex Kiernan static int do_fastboot_usb(int argc, char *const argv[],
37f73a7df9SAlex Kiernan uintptr_t buf_addr, size_t buf_size)
38f73a7df9SAlex Kiernan {
39f73a7df9SAlex Kiernan #if CONFIG_IS_ENABLED(USB_FUNCTION_FASTBOOT)
402e192b24SSimon Glass int controller_index;
412e192b24SSimon Glass char *usb_controller;
42aa51579fSSam Protsenko char *endp;
432e192b24SSimon Glass int ret;
442e192b24SSimon Glass
452e192b24SSimon Glass if (argc < 2)
462e192b24SSimon Glass return CMD_RET_USAGE;
472e192b24SSimon Glass
482e192b24SSimon Glass usb_controller = argv[1];
49aa51579fSSam Protsenko controller_index = simple_strtoul(usb_controller, &endp, 0);
50aa51579fSSam Protsenko if (*endp != '\0') {
51aa51579fSSam Protsenko pr_err("Error: Wrong USB controller index format\n");
52aa51579fSSam Protsenko return CMD_RET_FAILURE;
53aa51579fSSam Protsenko }
542e192b24SSimon Glass
55a06955aeSJean-Jacques Hiblot ret = usb_gadget_initialize(controller_index);
562e192b24SSimon Glass if (ret) {
5771002b50SSeung-Woo Kim pr_err("USB init failed: %d\n", ret);
582e192b24SSimon Glass return CMD_RET_FAILURE;
592e192b24SSimon Glass }
602e192b24SSimon Glass
612e192b24SSimon Glass g_dnl_clear_detach();
622e192b24SSimon Glass ret = g_dnl_register("usb_dnl_fastboot");
632e192b24SSimon Glass if (ret)
642e192b24SSimon Glass return ret;
652e192b24SSimon Glass
662e192b24SSimon Glass if (!g_dnl_board_usb_cable_connected()) {
672e192b24SSimon Glass puts("\rUSB cable not detected.\n" \
682e192b24SSimon Glass "Command exit.\n");
692e192b24SSimon Glass ret = CMD_RET_FAILURE;
702e192b24SSimon Glass goto exit;
712e192b24SSimon Glass }
722e192b24SSimon Glass
732e192b24SSimon Glass while (1) {
742e192b24SSimon Glass if (g_dnl_detach())
752e192b24SSimon Glass break;
762e192b24SSimon Glass if (ctrlc())
772e192b24SSimon Glass break;
78*731785dfSSean Nyekjaer WATCHDOG_RESET();
792e192b24SSimon Glass usb_gadget_handle_interrupts(controller_index);
802e192b24SSimon Glass }
812e192b24SSimon Glass
822e192b24SSimon Glass ret = CMD_RET_SUCCESS;
832e192b24SSimon Glass
842e192b24SSimon Glass exit:
852e192b24SSimon Glass g_dnl_unregister();
862e192b24SSimon Glass g_dnl_clear_detach();
87a06955aeSJean-Jacques Hiblot usb_gadget_release(controller_index);
882e192b24SSimon Glass
892e192b24SSimon Glass return ret;
90f73a7df9SAlex Kiernan #else
91f73a7df9SAlex Kiernan pr_err("Fastboot USB not enabled\n");
92f73a7df9SAlex Kiernan return CMD_RET_FAILURE;
93f73a7df9SAlex Kiernan #endif
942e192b24SSimon Glass }
952e192b24SSimon Glass
do_fastboot(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])96f73a7df9SAlex Kiernan static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
97f73a7df9SAlex Kiernan {
98f73a7df9SAlex Kiernan uintptr_t buf_addr = (uintptr_t)NULL;
99f73a7df9SAlex Kiernan size_t buf_size = 0;
100f73a7df9SAlex Kiernan
101f73a7df9SAlex Kiernan if (argc < 2)
102f73a7df9SAlex Kiernan return CMD_RET_USAGE;
103f73a7df9SAlex Kiernan
104f73a7df9SAlex Kiernan while (argc > 1 && **(argv + 1) == '-') {
105f73a7df9SAlex Kiernan char *arg = *++argv;
106f73a7df9SAlex Kiernan
107f73a7df9SAlex Kiernan --argc;
108f73a7df9SAlex Kiernan while (*++arg) {
109f73a7df9SAlex Kiernan switch (*arg) {
110f73a7df9SAlex Kiernan case 'l':
111f73a7df9SAlex Kiernan if (--argc <= 0)
112f73a7df9SAlex Kiernan return CMD_RET_USAGE;
113f73a7df9SAlex Kiernan buf_addr = simple_strtoul(*++argv, NULL, 16);
114f73a7df9SAlex Kiernan goto NXTARG;
115f73a7df9SAlex Kiernan
116f73a7df9SAlex Kiernan case 's':
117f73a7df9SAlex Kiernan if (--argc <= 0)
118f73a7df9SAlex Kiernan return CMD_RET_USAGE;
119f73a7df9SAlex Kiernan buf_size = simple_strtoul(*++argv, NULL, 16);
120f73a7df9SAlex Kiernan goto NXTARG;
121f73a7df9SAlex Kiernan
122f73a7df9SAlex Kiernan default:
123f73a7df9SAlex Kiernan return CMD_RET_USAGE;
124f73a7df9SAlex Kiernan }
125f73a7df9SAlex Kiernan }
126f73a7df9SAlex Kiernan NXTARG:
127f73a7df9SAlex Kiernan ;
128f73a7df9SAlex Kiernan }
129f73a7df9SAlex Kiernan
130aa51579fSSam Protsenko /* Handle case when USB controller param is just '-' */
131aa51579fSSam Protsenko if (argc == 1) {
132aa51579fSSam Protsenko pr_err("Error: Incorrect USB controller index\n");
133aa51579fSSam Protsenko return CMD_RET_USAGE;
134aa51579fSSam Protsenko }
135aa51579fSSam Protsenko
136f73a7df9SAlex Kiernan fastboot_init((void *)buf_addr, buf_size);
137f73a7df9SAlex Kiernan
138f73a7df9SAlex Kiernan if (!strcmp(argv[1], "udp"))
139f73a7df9SAlex Kiernan return do_fastboot_udp(argc, argv, buf_addr, buf_size);
140f73a7df9SAlex Kiernan
141f73a7df9SAlex Kiernan if (!strcmp(argv[1], "usb")) {
142f73a7df9SAlex Kiernan argv++;
143f73a7df9SAlex Kiernan argc--;
144f73a7df9SAlex Kiernan }
145f73a7df9SAlex Kiernan
146f73a7df9SAlex Kiernan return do_fastboot_usb(argc, argv, buf_addr, buf_size);
147f73a7df9SAlex Kiernan }
148f73a7df9SAlex Kiernan
149f73a7df9SAlex Kiernan #ifdef CONFIG_SYS_LONGHELP
150f73a7df9SAlex Kiernan static char fastboot_help_text[] =
151f73a7df9SAlex Kiernan "[-l addr] [-s size] usb <controller> | udp\n"
152f73a7df9SAlex Kiernan "\taddr - address of buffer used during data transfers ("
153f73a7df9SAlex Kiernan __stringify(CONFIG_FASTBOOT_BUF_ADDR) ")\n"
154f73a7df9SAlex Kiernan "\tsize - size of buffer used during data transfers ("
155f73a7df9SAlex Kiernan __stringify(CONFIG_FASTBOOT_BUF_SIZE) ")"
156f73a7df9SAlex Kiernan ;
157f73a7df9SAlex Kiernan #endif
158f73a7df9SAlex Kiernan
1592e192b24SSimon Glass U_BOOT_CMD(
160f73a7df9SAlex Kiernan fastboot, CONFIG_SYS_MAXARGS, 1, do_fastboot,
161f73a7df9SAlex Kiernan "run as a fastboot usb or udp device", fastboot_help_text
1622e192b24SSimon Glass );
163