// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2019 Pepperl+Fuchs * Copyright (C) 2025 Altera Corporation * Simon Goldschmidt */ #include #include #include #include #include #include #include #include #define GICD_CTRL_ADDRESS 0xfffc1000 static __always_inline void __l2_reset_cpu(void) { asm volatile(/* Disable GIC distributor (IRQs). */ "str wzr, [%3]\n" /* Set Magic Number */ "str %0, [%1]\n" /* Increase timeout in rstmgr.hdsktimeout */ "ldr x2, =0xFFFFFF\n" "str w2, [%2, #0x64]\n" "ldr w2, [%2, #0x10]\n" /* * Set l2flushen = 1, etrstallen = 1, * fpgahsen = 1 and sdrselfrefen = 1 * in rstmgr.hdsken to perform handshake * in certain peripherals before trigger * L2 reset. */ "ldr x3, =0x10D\n" "orr x2, x2, x3\n" "str w2, [%2, #0x10]\n" /* Trigger L2 reset in rstmgr.coldmodrst */ "ldr w2, [%2, #0x34]\n" "orr x2, x2, #0x100\n" "isb\n" "dsb sy\n" "str w2, [%2, #0x34]\n" /* Put all cores into WFI mode */ "1:\n" " wfi\n" " b 1b\n" : : "r" (L2_RESET_DONE_STATUS), "r" (L2_RESET_DONE_REG), "r" (SOCFPGA_RSTMGR_ADDRESS), "r" (GICD_CTRL_ADDRESS) : "x1", "x2", "x3"); } static void l2_reset_cpu(void) { __l2_reset_cpu(); } static int socfpga_sysreset_request(struct udevice *dev, enum sysreset_t type) { if (type == SYSRESET_WARM) { /* flush dcache */ flush_dcache_all(); /* request a warm reset */ puts("Do warm reset now...\n"); l2_reset_cpu(); } else { puts("Mailbox: Issuing mailbox cmd REBOOT_HPS\n"); mbox_reset_cold(); } return -EINPROGRESS; } static struct sysreset_ops socfpga_sysreset = { .request = socfpga_sysreset_request, }; U_BOOT_DRIVER(sysreset_socfpga) = { .id = UCLASS_SYSRESET, .name = "socfpga_sysreset", .ops = &socfpga_sysreset, };