blob: b0868aa871311bdcd222e96cddcd7691b3a289fc [file] [log] [blame]
Troy Kisky124a06d2012-08-15 10:31:20 +00001/*
2 * Copyright (C) 2012 Boundary Devices Inc.
3 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02004 * SPDX-License-Identifier: GPL-2.0+
Troy Kisky124a06d2012-08-15 10:31:20 +00005 */
6#include <common.h>
Masahiro Yamada1221ce42016-09-21 11:28:55 +09007#include <linux/errno.h>
Troy Kisky124a06d2012-08-15 10:31:20 +00008#include <asm/io.h>
9#include <asm/imx-common/boot_mode.h>
10#include <malloc.h>
Marek Vasut6c7c9462012-10-12 10:27:04 +000011#include <command.h>
Troy Kisky124a06d2012-08-15 10:31:20 +000012
13static const struct boot_mode *modes[2];
14
15static 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
32static 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
58static 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
81U_BOOT_CMD(
82 bmode, 3, 0, do_boot_mode,
83 NULL,
84 "");
85
86void add_board_boot_modes(const struct boot_mode *p)
87{
88 int size;
89 char *dest;
90
Marek Vasut6c7c9462012-10-12 10:27:04 +000091 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;
Troy Kisky124a06d2012-08-15 10:31:20 +000096 }
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);
Marek Vasut6c7c9462012-10-12 10:27:04 +0000104 entry->usage = dest;
Troy Kisky124a06d2012-08-15 10:31:20 +0000105 }
106}