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