arm: Support iotrace feature
[platform/kernel/u-boot.git] / arch / arm / imx-common / cmd_bmode.c
1 /*
2  * Copyright (C) 2012 Boundary Devices Inc.
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6 #include <common.h>
7 #include <asm/errno.h>
8 #include <asm/io.h>
9 #include <asm/imx-common/boot_mode.h>
10 #include <malloc.h>
11 #include <command.h>
12
13 static const struct boot_mode *modes[2];
14
15 static const struct boot_mode *search_modes(char *arg)
16 {
17         int i;
18
19         for (i = 0; i < ARRAY_SIZE(modes); i++) {
20                 const struct boot_mode *p = modes[i];
21                 if (p) {
22                         while (p->name) {
23                                 if (!strcmp(p->name, arg))
24                                         return p;
25                                 p++;
26                         }
27                 }
28         }
29         return NULL;
30 }
31
32 static int create_usage(char *dest)
33 {
34         int i;
35         int size = 0;
36
37         for (i = 0; i < ARRAY_SIZE(modes); i++) {
38                 const struct boot_mode *p = modes[i];
39                 if (p) {
40                         while (p->name) {
41                                 int len = strlen(p->name);
42                                 if (dest) {
43                                         memcpy(dest, p->name, len);
44                                         dest += len;
45                                         *dest++ = '|';
46                                 }
47                                 size += len + 1;
48                                 p++;
49                         }
50                 }
51         }
52         if (dest)
53                 memcpy(dest - 1, " [noreset]", 11);     /* include trailing 0 */
54         size += 10;
55         return size;
56 }
57
58 static int do_boot_mode(cmd_tbl_t *cmdtp, int flag, int argc,
59                 char * const argv[])
60 {
61         const struct boot_mode *p;
62         int reset_requested = 1;
63
64         if (argc < 2)
65                 return CMD_RET_USAGE;
66         p = search_modes(argv[1]);
67         if (!p)
68                 return CMD_RET_USAGE;
69         if (argc == 3) {
70                 if (strcmp(argv[2], "noreset"))
71                         return CMD_RET_USAGE;
72                 reset_requested = 0;
73         }
74
75         boot_mode_apply(p->cfg_val);
76         if (reset_requested && p->cfg_val)
77                 do_reset(NULL, 0, 0, NULL);
78         return 0;
79 }
80
81 U_BOOT_CMD(
82         bmode, 3, 0, do_boot_mode,
83         NULL,
84         "");
85
86 void add_board_boot_modes(const struct boot_mode *p)
87 {
88         int size;
89         char *dest;
90
91         cmd_tbl_t *entry = ll_entry_get(cmd_tbl_t, bmode, cmd);
92
93         if (entry->usage) {
94                 free(entry->usage);
95                 entry->usage = NULL;
96         }
97
98         modes[0] = p;
99         modes[1] = soc_boot_modes;
100         size = create_usage(NULL);
101         dest = malloc(size);
102         if (dest) {
103                 create_usage(dest);
104                 entry->usage = dest;
105         }
106 }