1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2019 Pepperl+Fuchs
4 * Copyright (C) 2025 Altera Corporation <www.altera.com>
5 * Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
6 */
7
8 #include <command.h>
9 #include <cpu_func.h>
10 #include <dm.h>
11 #include <errno.h>
12 #include <sysreset.h>
13 #include <asm/arch/mailbox_s10.h>
14 #include <asm/arch/reset_manager.h>
15 #include <asm/secure.h>
16
17 #define GICD_CTRL_ADDRESS 0xfffc1000
18
__l2_reset_cpu(void)19 static __always_inline void __l2_reset_cpu(void)
20 {
21 asm volatile(/* Disable GIC distributor (IRQs). */
22 "str wzr, [%3]\n"
23 /* Set Magic Number */
24 "str %0, [%1]\n"
25 /* Increase timeout in rstmgr.hdsktimeout */
26 "ldr x2, =0xFFFFFF\n"
27 "str w2, [%2, #0x64]\n"
28 "ldr w2, [%2, #0x10]\n"
29 /*
30 * Set l2flushen = 1, etrstallen = 1,
31 * fpgahsen = 1 and sdrselfrefen = 1
32 * in rstmgr.hdsken to perform handshake
33 * in certain peripherals before trigger
34 * L2 reset.
35 */
36 "ldr x3, =0x10D\n"
37 "orr x2, x2, x3\n"
38 "str w2, [%2, #0x10]\n"
39 /* Trigger L2 reset in rstmgr.coldmodrst */
40 "ldr w2, [%2, #0x34]\n"
41 "orr x2, x2, #0x100\n"
42 "isb\n"
43 "dsb sy\n"
44 "str w2, [%2, #0x34]\n"
45 /* Put all cores into WFI mode */
46 "1:\n"
47 " wfi\n"
48 " b 1b\n"
49 : : "r" (L2_RESET_DONE_STATUS),
50 "r" (L2_RESET_DONE_REG),
51 "r" (SOCFPGA_RSTMGR_ADDRESS),
52 "r" (GICD_CTRL_ADDRESS)
53 : "x1", "x2", "x3");
54 }
55
l2_reset_cpu(void)56 static void l2_reset_cpu(void)
57 {
58 __l2_reset_cpu();
59 }
60
socfpga_sysreset_request(struct udevice * dev,enum sysreset_t type)61 static int socfpga_sysreset_request(struct udevice *dev,
62 enum sysreset_t type)
63 {
64 if (type == SYSRESET_WARM) {
65 /* flush dcache */
66 flush_dcache_all();
67
68 /* request a warm reset */
69 puts("Do warm reset now...\n");
70 l2_reset_cpu();
71 } else {
72 puts("Mailbox: Issuing mailbox cmd REBOOT_HPS\n");
73 mbox_reset_cold();
74 }
75
76 return -EINPROGRESS;
77 }
78
79 static struct sysreset_ops socfpga_sysreset = {
80 .request = socfpga_sysreset_request,
81 };
82
83 U_BOOT_DRIVER(sysreset_socfpga) = {
84 .id = UCLASS_SYSRESET,
85 .name = "socfpga_sysreset",
86 .ops = &socfpga_sysreset,
87 };
88