1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2023 Beckhoff Automation GmbH & Co. KG
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/module.h>
34 #include <sys/malloc.h>
35 #include <sys/bus.h>
36 #include <sys/cpu.h>
37 #include <machine/bus.h>
38
39 #include <dev/ofw/openfirm.h>
40 #include <dev/ofw/ofw_bus.h>
41 #include <dev/ofw/ofw_bus_subr.h>
42
43 #include <dev/hwreset/hwreset.h>
44
45 #include <dev/firmware/xilinx/pm_defs.h>
46
47 #include "hwreset_if.h"
48 #include "zynqmp_firmware_if.h"
49
50 #define ZYNQMP_RESET_PCIE_CFG 0
51 #define ZYNQMP_RESET_PCIE_BRIDGE 1
52 #define ZYNQMP_RESET_PCIE_CTRL 2
53 #define ZYNQMP_RESET_DP 3
54 #define ZYNQMP_RESET_SWDT_CRF 4
55 #define ZYNQMP_RESET_AFI_FM5 5
56 #define ZYNQMP_RESET_AFI_FM4 6
57 #define ZYNQMP_RESET_AFI_FM3 7
58 #define ZYNQMP_RESET_AFI_FM2 8
59 #define ZYNQMP_RESET_AFI_FM1 9
60 #define ZYNQMP_RESET_AFI_FM0 10
61 #define ZYNQMP_RESET_GDMA 11
62 #define ZYNQMP_RESET_GPU_PP1 12
63 #define ZYNQMP_RESET_GPU_PP0 13
64 #define ZYNQMP_RESET_GPU 14
65 #define ZYNQMP_RESET_GT 15
66 #define ZYNQMP_RESET_SATA 16
67 #define ZYNQMP_RESET_ACPU3_PWRON 17
68 #define ZYNQMP_RESET_ACPU2_PWRON 18
69 #define ZYNQMP_RESET_ACPU1_PWRON 19
70 #define ZYNQMP_RESET_ACPU0_PWRON 20
71 #define ZYNQMP_RESET_APU_L2 21
72 #define ZYNQMP_RESET_ACPU3 22
73 #define ZYNQMP_RESET_ACPU2 23
74 #define ZYNQMP_RESET_ACPU1 24
75 #define ZYNQMP_RESET_ACPU0 25
76 #define ZYNQMP_RESET_DDR 26
77 #define ZYNQMP_RESET_APM_FPD 27
78 #define ZYNQMP_RESET_SOFT 28
79 #define ZYNQMP_RESET_GEM0 29
80 #define ZYNQMP_RESET_GEM1 30
81 #define ZYNQMP_RESET_GEM2 31
82 #define ZYNQMP_RESET_GEM3 32
83 #define ZYNQMP_RESET_QSPI 33
84 #define ZYNQMP_RESET_UART0 34
85 #define ZYNQMP_RESET_UART1 35
86 #define ZYNQMP_RESET_SPI0 36
87 #define ZYNQMP_RESET_SPI1 37
88 #define ZYNQMP_RESET_SDIO0 38
89 #define ZYNQMP_RESET_SDIO1 39
90 #define ZYNQMP_RESET_CAN0 40
91 #define ZYNQMP_RESET_CAN1 41
92 #define ZYNQMP_RESET_I2C0 42
93 #define ZYNQMP_RESET_I2C1 43
94 #define ZYNQMP_RESET_TTC0 44
95 #define ZYNQMP_RESET_TTC1 45
96 #define ZYNQMP_RESET_TTC2 46
97 #define ZYNQMP_RESET_TTC3 47
98 #define ZYNQMP_RESET_SWDT_CRL 48
99 #define ZYNQMP_RESET_NAND 49
100 #define ZYNQMP_RESET_ADMA 50
101 #define ZYNQMP_RESET_GPIO 51
102 #define ZYNQMP_RESET_IOU_CC 52
103 #define ZYNQMP_RESET_TIMESTAMP 53
104 #define ZYNQMP_RESET_RPU_R50 54
105 #define ZYNQMP_RESET_RPU_R51 55
106 #define ZYNQMP_RESET_RPU_AMBA 56
107 #define ZYNQMP_RESET_OCM 57
108 #define ZYNQMP_RESET_RPU_PGE 58
109 #define ZYNQMP_RESET_USB0_CORERESET 59
110 #define ZYNQMP_RESET_USB1_CORERESET 60
111 #define ZYNQMP_RESET_USB0_HIBERRESET 61
112 #define ZYNQMP_RESET_USB1_HIBERRESET 62
113 #define ZYNQMP_RESET_USB0_APB 63
114 #define ZYNQMP_RESET_USB1_APB 64
115 #define ZYNQMP_RESET_IPI 65
116 #define ZYNQMP_RESET_APM_LPD 66
117 #define ZYNQMP_RESET_RTC 67
118 #define ZYNQMP_RESET_SYSMON 68
119 #define ZYNQMP_RESET_AFI_FM6 69
120 #define ZYNQMP_RESET_LPD_SWDT 70
121 #define ZYNQMP_RESET_FPD 71
122 #define ZYNQMP_RESET_RPU_DBG1 72
123 #define ZYNQMP_RESET_RPU_DBG0 73
124 #define ZYNQMP_RESET_DBG_LPD 74
125 #define ZYNQMP_RESET_DBG_FPD 75
126 #define ZYNQMP_RESET_APLL 76
127 #define ZYNQMP_RESET_DPLL 77
128 #define ZYNQMP_RESET_VPLL 78
129 #define ZYNQMP_RESET_IOPLL 79
130 #define ZYNQMP_RESET_RPLL 80
131 #define ZYNQMP_RESET_GPO3_PL_0 81
132 #define ZYNQMP_RESET_GPO3_PL_1 82
133 #define ZYNQMP_RESET_GPO3_PL_2 83
134 #define ZYNQMP_RESET_GPO3_PL_3 84
135 #define ZYNQMP_RESET_GPO3_PL_4 85
136 #define ZYNQMP_RESET_GPO3_PL_5 86
137 #define ZYNQMP_RESET_GPO3_PL_6 87
138 #define ZYNQMP_RESET_GPO3_PL_7 88
139 #define ZYNQMP_RESET_GPO3_PL_8 89
140 #define ZYNQMP_RESET_GPO3_PL_9 90
141 #define ZYNQMP_RESET_GPO3_PL_10 91
142 #define ZYNQMP_RESET_GPO3_PL_11 92
143 #define ZYNQMP_RESET_GPO3_PL_12 93
144 #define ZYNQMP_RESET_GPO3_PL_13 94
145 #define ZYNQMP_RESET_GPO3_PL_14 95
146 #define ZYNQMP_RESET_GPO3_PL_15 96
147 #define ZYNQMP_RESET_GPO3_PL_16 97
148 #define ZYNQMP_RESET_GPO3_PL_17 98
149 #define ZYNQMP_RESET_GPO3_PL_18 99
150 #define ZYNQMP_RESET_GPO3_PL_19 100
151 #define ZYNQMP_RESET_GPO3_PL_20 101
152 #define ZYNQMP_RESET_GPO3_PL_21 102
153 #define ZYNQMP_RESET_GPO3_PL_22 103
154 #define ZYNQMP_RESET_GPO3_PL_23 104
155 #define ZYNQMP_RESET_GPO3_PL_24 105
156 #define ZYNQMP_RESET_GPO3_PL_25 106
157 #define ZYNQMP_RESET_GPO3_PL_26 107
158 #define ZYNQMP_RESET_GPO3_PL_27 108
159 #define ZYNQMP_RESET_GPO3_PL_28 109
160 #define ZYNQMP_RESET_GPO3_PL_29 110
161 #define ZYNQMP_RESET_GPO3_PL_30 111
162 #define ZYNQMP_RESET_GPO3_PL_31 112
163 #define ZYNQMP_RESET_RPU_LS 113
164 #define ZYNQMP_RESET_PS_ONLY 114
165 #define ZYNQMP_RESET_PL 115
166 #define ZYNQMP_RESET_PS_PL0 116
167 #define ZYNQMP_RESET_PS_PL1 117
168 #define ZYNQMP_RESET_PS_PL2 118
169 #define ZYNQMP_RESET_PS_PL3 119
170 #define ZYNQMP_RESET_MAX ZYNQMP_RESET_PS_PL3
171
172 struct zynqmp_reset_softc {
173 device_t dev;
174 device_t parent;
175 };
176
177 static int
zynqmp_reset_assert(device_t dev,intptr_t id,bool reset)178 zynqmp_reset_assert(device_t dev, intptr_t id, bool reset)
179 {
180 struct zynqmp_reset_softc *sc;
181 int rv;
182
183 if (id > ZYNQMP_RESET_MAX)
184 return (EINVAL);
185 sc = device_get_softc(dev);
186 rv = ZYNQMP_FIRMWARE_RESET_ASSERT(sc->parent, id, reset);
187 return (rv);
188 }
189
190 static int
zynqmp_reset_is_asserted(device_t dev,intptr_t id,bool * reset)191 zynqmp_reset_is_asserted(device_t dev, intptr_t id, bool *reset)
192 {
193 struct zynqmp_reset_softc *sc;
194 int rv;
195
196 if (id > ZYNQMP_RESET_MAX)
197 return (EINVAL);
198 sc = device_get_softc(dev);
199 rv = ZYNQMP_FIRMWARE_RESET_GET_STATUS(sc->parent, id, reset);
200
201 return (rv);
202 }
203
204 static int
zynqmp_reset_probe(device_t dev)205 zynqmp_reset_probe(device_t dev)
206 {
207
208 if (!ofw_bus_status_okay(dev))
209 return (ENXIO);
210 if (!ofw_bus_is_compatible(dev, "xlnx,zynqmp-reset"))
211 return (ENXIO);
212 device_set_desc(dev, "ZynqMP Reset Controller");
213
214 return (BUS_PROBE_DEFAULT);
215 }
216
217 static int
zynqmp_reset_attach(device_t dev)218 zynqmp_reset_attach(device_t dev)
219 {
220 struct zynqmp_reset_softc *sc;
221
222 sc = device_get_softc(dev);
223 sc->dev = dev;
224 sc->parent = device_get_parent(dev);
225
226 /* register our self as a reset provider */
227 hwreset_register_ofw_provider(dev);
228
229 return (0);
230 }
231
232 static device_method_t zynqmp_reset_methods[] = {
233 /* device_if */
234 DEVMETHOD(device_probe, zynqmp_reset_probe),
235 DEVMETHOD(device_attach, zynqmp_reset_attach),
236
237 /* Reset interface */
238 DEVMETHOD(hwreset_assert, zynqmp_reset_assert),
239 DEVMETHOD(hwreset_is_asserted, zynqmp_reset_is_asserted),
240
241 DEVMETHOD_END
242 };
243
244 static driver_t zynqmp_reset_driver = {
245 "zynqmp_reset",
246 zynqmp_reset_methods,
247 sizeof(struct zynqmp_reset_softc),
248 };
249
250 EARLY_DRIVER_MODULE(zynqmp_reset, simplebus, zynqmp_reset_driver, 0, 0,
251 BUS_PASS_BUS + BUS_PASS_ORDER_LAST);
252