dm: sysreset: support mode args for reboot/reset command
Support command like: reboot loader/bootloader/recovery, etc. It depends on the node whose compatible is "syscon-reboot-mode". Change-Id: I3ef497c6a4355a0d8be9a277bd77bbee43df57fb Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
This commit is contained in:
parent
467d16db4b
commit
bcb84b5d64
|
@ -5,9 +5,15 @@
|
|||
#
|
||||
|
||||
obj-$(CONFIG_$(SPL_TPL_)SYSRESET) += sysreset-uclass.o
|
||||
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
obj-$(CONFIG_SYSRESET) += sysreset-syscon-reboot.o
|
||||
endif
|
||||
|
||||
ifndef CONFIG_TPL_BUILD
|
||||
obj-$(CONFIG_SYSRESET_PSCI) += sysreset_psci.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_SYSRESET_SYSCON) += sysreset_syscon.o
|
||||
obj-$(CONFIG_SYSRESET_WATCHDOG) += sysreset_watchdog.o
|
||||
|
||||
|
@ -16,6 +22,7 @@ obj-$(CONFIG_ARCH_SNAPDRAGON) += sysreset_snapdragon.o
|
|||
obj-$(CONFIG_ARCH_STI) += sysreset_sti.o
|
||||
obj-$(CONFIG_TARGET_XTFPGA) += sysreset_xtfpga.o
|
||||
obj-$(CONFIG_ARCH_ASPEED) += sysreset_ast.o
|
||||
|
||||
ifndef CONFIG_TPL_BUILD
|
||||
obj-$(CONFIG_ARCH_ROCKCHIP) += sysreset_rockchip.o
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* (C) Copyright 2019 Rockchip Electronics Co., Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <sysreset.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/arch/boot_mode.h>
|
||||
|
||||
#define CMD_PREFIX "mode-"
|
||||
|
||||
struct command {
|
||||
const char *name;
|
||||
u32 magic;
|
||||
};
|
||||
|
||||
static const struct command static_defined_command[] = {
|
||||
{ .name = "bootrom", .magic = BOOT_BROM_DOWNLOAD, }
|
||||
};
|
||||
|
||||
static int syscon_reboot_request_by_mode(struct udevice *dev, const char *mode)
|
||||
{
|
||||
const char *prefix = CMD_PREFIX;
|
||||
char *command;
|
||||
u32 magic;
|
||||
int i;
|
||||
|
||||
if (!mode)
|
||||
return 0;
|
||||
|
||||
command = calloc(1, strlen(mode) + sizeof(prefix));
|
||||
if (!command)
|
||||
return -ENOMEM;
|
||||
|
||||
strcat(command, prefix);
|
||||
strcat(command, mode);
|
||||
|
||||
magic = dev_read_u32_default(dev, command, BOOT_NORMAL);
|
||||
if (magic == BOOT_NORMAL) {
|
||||
for (i = 0; i < ARRAY_SIZE(static_defined_command); i++) {
|
||||
if (!strcmp(static_defined_command[i].name, mode)) {
|
||||
magic = static_defined_command[i].magic;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("## Reboot mode: %s(%x)\n\n", mode, magic);
|
||||
|
||||
writel(magic, CONFIG_ROCKCHIP_BOOT_MODE_REG);
|
||||
free(command);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sysreset_ops syscon_reboot_ops = {
|
||||
.request_by_mode = syscon_reboot_request_by_mode,
|
||||
};
|
||||
|
||||
static const struct udevice_id syscon_reboot_match[] = {
|
||||
{ .compatible = "syscon-reboot-mode", },
|
||||
{},
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sysreset_syscon_reboot) = {
|
||||
.name = "sysreset_syscon_reboot",
|
||||
.id = UCLASS_SYSRESET,
|
||||
.of_match = syscon_reboot_match,
|
||||
.ops = &syscon_reboot_ops,
|
||||
};
|
|
@ -81,10 +81,36 @@ void reset_cpu(ulong addr)
|
|||
sysreset_walk_halt(SYSRESET_WARM);
|
||||
}
|
||||
|
||||
void reboot(const char *mode)
|
||||
{
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
struct sysreset_ops *ops;
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
if (!mode)
|
||||
goto finish;
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_SYSRESET,
|
||||
DM_GET_DRIVER(sysreset_syscon_reboot),
|
||||
&dev);
|
||||
if (!ret) {
|
||||
ops = sysreset_get_ops(dev);
|
||||
if (ops && ops->request_by_mode)
|
||||
ops->request_by_mode(dev, mode);
|
||||
}
|
||||
finish:
|
||||
#endif
|
||||
flushc();
|
||||
sysreset_walk_halt(SYSRESET_COLD);
|
||||
}
|
||||
|
||||
int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
sysreset_walk_halt(SYSRESET_COLD);
|
||||
if (argc > 1)
|
||||
reboot(argv[1]);
|
||||
else
|
||||
reboot(NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,19 @@ struct sysreset_ops {
|
|||
* (in which case this method will not actually return)
|
||||
*/
|
||||
int (*request)(struct udevice *dev, enum sysreset_t type);
|
||||
|
||||
/**
|
||||
* request_by_mode() - request a sysreset of the given mode
|
||||
*
|
||||
* Note that this function may return before the reset takes effect.
|
||||
*
|
||||
* @mode: mode to request
|
||||
* @return -EINPROGRESS if the reset has been started and
|
||||
* will complete soon, -EPROTONOSUPPORT if not supported
|
||||
* by this device, 0 if the reset has already happened
|
||||
* (in which case this method will not actually return)
|
||||
*/
|
||||
int (*request_by_mode)(struct udevice *dev, const char *mode);
|
||||
};
|
||||
|
||||
#define sysreset_get_ops(dev) ((struct sysreset_ops *)(dev)->driver->ops)
|
||||
|
@ -68,4 +81,11 @@ void sysreset_walk_halt(enum sysreset_t type);
|
|||
*/
|
||||
void reset_cpu(ulong addr);
|
||||
|
||||
/**
|
||||
* reboot() - calls sysreset_walk(SYSRESET_WARM)
|
||||
*
|
||||
* Support the command like: reboot loader/bootloader/recovery, etc.
|
||||
*/
|
||||
void reboot(const char *mode);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue