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