From 559e6256f855e61f987598a18ed4f2e20bc530e7 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Tue, 6 Aug 2019 17:21:02 +0200 Subject: arm: meson: add sm cmd to retrieve SoC serial The Secure Monitor offers multiple services, like returning the SoC unique serial number, already used to generate an unique MAC address. This adds a new, Amlogic specific, "sm" cmd with a "serial" subcommand to write the SoC unique serial to memory. This "cm" command will be extended in further patches. Signed-off-by: Neil Armstrong --- arch/arm/mach-meson/sm.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'arch/arm/mach-meson') diff --git a/arch/arm/mach-meson/sm.c b/arch/arm/mach-meson/sm.c index 05b7f0b..99fa17d 100644 --- a/arch/arm/mach-meson/sm.c +++ b/arch/arm/mach-meson/sm.c @@ -77,3 +77,51 @@ int meson_sm_get_serial(void *buffer, size_t size) return 0; } + +static int do_sm_serial(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + ulong address; + int ret; + + if (argc < 2) + return CMD_RET_USAGE; + + address = simple_strtoul(argv[1], NULL, 0); + + ret = meson_sm_get_serial((void *)address, SM_CHIP_ID_SIZE); + if (ret) + return CMD_RET_FAILURE; + + return CMD_RET_SUCCESS; +} + +static cmd_tbl_t cmd_sm_sub[] = { + U_BOOT_CMD_MKENT(serial, 2, 1, do_sm_serial, "", ""), +}; + +static int do_sm(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + cmd_tbl_t *c; + + if (argc < 2) + return CMD_RET_USAGE; + + /* Strip off leading 'sm' command argument */ + argc--; + argv++; + + c = find_cmd_tbl(argv[0], &cmd_sm_sub[0], ARRAY_SIZE(cmd_sm_sub)); + + if (c) + return c->cmd(cmdtp, flag, argc, argv); + else + return CMD_RET_USAGE; +} + +U_BOOT_CMD( + sm, 5, 0, do_sm, + "Secure Monitor Control", + "serial
- read chip unique id to memory address" +); -- cgit v1.1 From b1dd7debeaf5b55f0d6091406ea4e767e4fdaaac Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Tue, 6 Aug 2019 17:28:36 +0200 Subject: arm: meson: add sm command to retrieve the reboot reason The Secure Monitor offers multiple services, like returning the SoC unique serial number, and can provide the "reboot reason" as set by the previous booted system. This extends the Amlogic specific "sm" cmd with a "reboot_reason" subcommand to print or set a specified environment variable with the reboot reason in human readable format. Signed-off-by: Neil Armstrong --- arch/arm/mach-meson/sm.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) (limited to 'arch/arm/mach-meson') diff --git a/arch/arm/mach-meson/sm.c b/arch/arm/mach-meson/sm.c index 99fa17d..fabcb3b 100644 --- a/arch/arm/mach-meson/sm.c +++ b/arch/arm/mach-meson/sm.c @@ -8,6 +8,10 @@ #include #include #include +#include +#include +#include +#include #define FN_GET_SHARE_MEM_INPUT_BASE 0x82000020 #define FN_GET_SHARE_MEM_OUTPUT_BASE 0x82000021 @@ -78,6 +82,39 @@ int meson_sm_get_serial(void *buffer, size_t size) return 0; } +#define AO_SEC_SD_CFG15 0xfc +#define REBOOT_REASON_MASK GENMASK(15, 12) + +int meson_sm_get_reboot_reason(void) +{ + struct regmap *regmap; + int nodeoffset; + ofnode node; + unsigned int reason; + + /* find the offset of compatible node */ + nodeoffset = fdt_node_offset_by_compatible(gd->fdt_blob, -1, + "amlogic,meson-gx-ao-secure"); + if (nodeoffset < 0) { + printf("%s: failed to get amlogic,meson-gx-ao-secure\n", + __func__); + return -ENODEV; + } + + /* get regmap from the syscon node */ + node = offset_to_ofnode(nodeoffset); + regmap = syscon_node_to_regmap(node); + if (IS_ERR(regmap)) { + printf("%s: failed to get regmap\n", __func__); + return -EINVAL; + } + + regmap_read(regmap, AO_SEC_SD_CFG15, &reason); + + /* The SMC call is not used, we directly use AO_SEC_SD_CFG15 */ + return FIELD_GET(REBOOT_REASON_MASK, reason); +} + static int do_sm_serial(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { @@ -96,8 +133,55 @@ static int do_sm_serial(cmd_tbl_t *cmdtp, int flag, int argc, return CMD_RET_SUCCESS; } +#define MAX_REBOOT_REASONS 14 + +static const char *reboot_reasons[MAX_REBOOT_REASONS] = { + [REBOOT_REASON_COLD] = "cold_boot", + [REBOOT_REASON_NORMAL] = "normal", + [REBOOT_REASON_RECOVERY] = "recovery", + [REBOOT_REASON_UPDATE] = "update", + [REBOOT_REASON_FASTBOOT] = "fastboot", + [REBOOT_REASON_SUSPEND_OFF] = "suspend_off", + [REBOOT_REASON_HIBERNATE] = "hibernate", + [REBOOT_REASON_BOOTLOADER] = "bootloader", + [REBOOT_REASON_SHUTDOWN_REBOOT] = "shutdown_reboot", + [REBOOT_REASON_RPMBP] = "rpmbp", + [REBOOT_REASON_CRASH_DUMP] = "crash_dump", + [REBOOT_REASON_KERNEL_PANIC] = "kernel_panic", + [REBOOT_REASON_WATCHDOG_REBOOT] = "watchdog_reboot", +}; + +static int do_sm_reboot_reason(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + const char *reason_str; + char *destarg = NULL; + int reason; + + if (argc > 1) + destarg = argv[1]; + + reason = meson_sm_get_reboot_reason(); + if (reason < 0) + return CMD_RET_FAILURE; + + if (reason >= MAX_REBOOT_REASONS || + !reboot_reasons[reason]) + reason_str = "unknown"; + else + reason_str = reboot_reasons[reason]; + + if (destarg) + env_set(destarg, reason_str); + else + printf("reboot reason: %s (%x)\n", reason_str, reason); + + return CMD_RET_SUCCESS; +} + static cmd_tbl_t cmd_sm_sub[] = { U_BOOT_CMD_MKENT(serial, 2, 1, do_sm_serial, "", ""), + U_BOOT_CMD_MKENT(reboot_reason, 1, 1, do_sm_reboot_reason, "", ""), }; static int do_sm(cmd_tbl_t *cmdtp, int flag, int argc, @@ -123,5 +207,6 @@ static int do_sm(cmd_tbl_t *cmdtp, int flag, int argc, U_BOOT_CMD( sm, 5, 0, do_sm, "Secure Monitor Control", - "serial
- read chip unique id to memory address" + "serial
- read chip unique id to memory address\n" + "sm reboot_reason [name] - get reboot reason and store to to environment" ); -- cgit v1.1 From 9a34dedfae0ebb031a45324c2fed8c39b2c6fcf2 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 22 May 2019 13:30:25 +0200 Subject: ARM: meson: Add support for fastboot_set_reboot_flag() Add support for fastboot_set_reboot_flag() by storing the reboot flag in the common code to be used by the custom PSCI reboot handler. Signed-off-by: Neil Armstrong --- arch/arm/mach-meson/board-common.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'arch/arm/mach-meson') diff --git a/arch/arm/mach-meson/board-common.c b/arch/arm/mach-meson/board-common.c index 18383f7..9b3fb47 100644 --- a/arch/arm/mach-meson/board-common.c +++ b/arch/arm/mach-meson/board-common.c @@ -14,6 +14,11 @@ #include #include +#if CONFIG_IS_ENABLED(FASTBOOT) +#include +#include +#endif + DECLARE_GLOBAL_DATA_PTR; __weak int board_init(void) @@ -142,7 +147,35 @@ int board_late_init(void) return meson_board_late_init(); } +#if CONFIG_IS_ENABLED(FASTBOOT) +static unsigned int reboot_reason = REBOOT_REASON_NORMAL; + +int fastboot_set_reboot_flag() +{ + reboot_reason = REBOOT_REASON_BOOTLOADER; + + printf("Using reboot reason: 0x%x\n", reboot_reason); + + return 0; +} + +void reset_cpu(ulong addr) +{ + struct pt_regs regs; + + regs.regs[0] = ARM_PSCI_0_2_FN_SYSTEM_RESET; + regs.regs[1] = reboot_reason; + + printf("Rebooting with reason: 0x%lx\n", regs.regs[1]); + + smc_call(®s); + + while (1) + ; +} +#else void reset_cpu(ulong addr) { psci_system_reset(); } +#endif -- cgit v1.1