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