1bcb84b5dSJoseph Chen /*
2bcb84b5dSJoseph Chen * (C) Copyright 2019 Rockchip Electronics Co., Ltd
3bcb84b5dSJoseph Chen *
4bcb84b5dSJoseph Chen * SPDX-License-Identifier: GPL-2.0
5bcb84b5dSJoseph Chen */
6bcb84b5dSJoseph Chen
7bcb84b5dSJoseph Chen #include <common.h>
8bcb84b5dSJoseph Chen #include <dm.h>
9bcb84b5dSJoseph Chen #include <sysreset.h>
10bcb84b5dSJoseph Chen #include <linux/io.h>
11bcb84b5dSJoseph Chen #include <asm/arch/boot_mode.h>
12bcb84b5dSJoseph Chen
13bcb84b5dSJoseph Chen #define CMD_PREFIX "mode-"
14bcb84b5dSJoseph Chen
15bcb84b5dSJoseph Chen struct command {
16bcb84b5dSJoseph Chen const char *name;
17bcb84b5dSJoseph Chen u32 magic;
18bcb84b5dSJoseph Chen };
19bcb84b5dSJoseph Chen
20bcb84b5dSJoseph Chen static const struct command static_defined_command[] = {
21bcb84b5dSJoseph Chen { .name = "bootrom", .magic = BOOT_BROM_DOWNLOAD, }
22bcb84b5dSJoseph Chen };
23bcb84b5dSJoseph Chen
syscon_reboot_request_by_mode(struct udevice * dev,const char * mode)24*c3249a03SJoseph Chen static int syscon_reboot_request_by_mode(struct udevice *dev, const char *mode)
25bcb84b5dSJoseph Chen {
26bcb84b5dSJoseph Chen const char *prefix = CMD_PREFIX;
27bcb84b5dSJoseph Chen char *command;
28bcb84b5dSJoseph Chen u32 magic;
29bcb84b5dSJoseph Chen int i;
30bcb84b5dSJoseph Chen
31*c3249a03SJoseph Chen if (!mode)
32*c3249a03SJoseph Chen return 0;
33*c3249a03SJoseph Chen
34bcb84b5dSJoseph Chen command = calloc(1, strlen(mode) + sizeof(prefix));
35bcb84b5dSJoseph Chen if (!command)
36bcb84b5dSJoseph Chen return -ENOMEM;
37bcb84b5dSJoseph Chen
38bcb84b5dSJoseph Chen strcat(command, prefix);
39bcb84b5dSJoseph Chen strcat(command, mode);
40bcb84b5dSJoseph Chen
41*c3249a03SJoseph Chen magic = dev_read_u32_default(dev, command, BOOT_NORMAL);
42*c3249a03SJoseph Chen if (magic == BOOT_NORMAL) {
43bcb84b5dSJoseph Chen for (i = 0; i < ARRAY_SIZE(static_defined_command); i++) {
44bcb84b5dSJoseph Chen if (!strcmp(static_defined_command[i].name, mode)) {
45bcb84b5dSJoseph Chen magic = static_defined_command[i].magic;
46bcb84b5dSJoseph Chen break;
47bcb84b5dSJoseph Chen }
48bcb84b5dSJoseph Chen }
49bcb84b5dSJoseph Chen }
50bcb84b5dSJoseph Chen
51*c3249a03SJoseph Chen printf("## Reboot mode: %s(%x)\n\n", mode, magic);
52bcb84b5dSJoseph Chen
53bcb84b5dSJoseph Chen writel(magic, CONFIG_ROCKCHIP_BOOT_MODE_REG);
54bcb84b5dSJoseph Chen free(command);
55bcb84b5dSJoseph Chen
56bcb84b5dSJoseph Chen return 0;
57bcb84b5dSJoseph Chen }
58bcb84b5dSJoseph Chen
59bcb84b5dSJoseph Chen static const struct sysreset_ops syscon_reboot_ops = {
60bcb84b5dSJoseph Chen .request_by_mode = syscon_reboot_request_by_mode,
61bcb84b5dSJoseph Chen };
62bcb84b5dSJoseph Chen
63bcb84b5dSJoseph Chen static const struct udevice_id syscon_reboot_match[] = {
64bcb84b5dSJoseph Chen { .compatible = "syscon-reboot-mode", },
65bcb84b5dSJoseph Chen {},
66bcb84b5dSJoseph Chen };
67bcb84b5dSJoseph Chen
68bcb84b5dSJoseph Chen U_BOOT_DRIVER(sysreset_syscon_reboot) = {
69bcb84b5dSJoseph Chen .name = "sysreset_syscon_reboot",
70bcb84b5dSJoseph Chen .id = UCLASS_SYSRESET,
71bcb84b5dSJoseph Chen .of_match = syscon_reboot_match,
72bcb84b5dSJoseph Chen .ops = &syscon_reboot_ops,
73bcb84b5dSJoseph Chen };
74