1ff33210cSMitchell Horne /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3ff33210cSMitchell Horne *
4ff33210cSMitchell Horne * Copyright (c) 2019 Mitchell Horne <mhorne@FreeBSD.org>
5c55272fdSJessica Clarke * Copyright (c) 2021 Jessica Clarke <jrtc27@FreeBSD.org>
6ff33210cSMitchell Horne *
7ff33210cSMitchell Horne * Redistribution and use in source and binary forms, with or without
8ff33210cSMitchell Horne * modification, are permitted provided that the following conditions
9ff33210cSMitchell Horne * are met:
10ff33210cSMitchell Horne * 1. Redistributions of source code must retain the above copyright
11ff33210cSMitchell Horne * notice, this list of conditions and the following disclaimer.
12ff33210cSMitchell Horne * 2. Redistributions in binary form must reproduce the above copyright
13ff33210cSMitchell Horne * notice, this list of conditions and the following disclaimer in the
14ff33210cSMitchell Horne * documentation and/or other materials provided with the distribution.
15ff33210cSMitchell Horne *
16ff33210cSMitchell Horne * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17ff33210cSMitchell Horne * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18ff33210cSMitchell Horne * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19ff33210cSMitchell Horne * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20ff33210cSMitchell Horne * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21ff33210cSMitchell Horne * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22ff33210cSMitchell Horne * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23ff33210cSMitchell Horne * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24ff33210cSMitchell Horne * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25ff33210cSMitchell Horne * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26ff33210cSMitchell Horne * SUCH DAMAGE.
27ff33210cSMitchell Horne */
28ff33210cSMitchell Horne
29ff33210cSMitchell Horne #include <sys/param.h>
30ff33210cSMitchell Horne #include <sys/systm.h>
31c55272fdSJessica Clarke #include <sys/bus.h>
32e28d8a5bSJessica Clarke #include <sys/eventhandler.h>
33c55272fdSJessica Clarke #include <sys/kernel.h>
346ec8bf9fSJessica Clarke #include <sys/malloc.h>
35c55272fdSJessica Clarke #include <sys/module.h>
36e28d8a5bSJessica Clarke #include <sys/reboot.h>
37ff33210cSMitchell Horne
38ff33210cSMitchell Horne #include <machine/md_var.h>
39ff33210cSMitchell Horne #include <machine/sbi.h>
40ff33210cSMitchell Horne
41a1092942SMitchell Horne /* SBI Implementation-Specific Definitions */
42a1092942SMitchell Horne #define OPENSBI_VERSION_MAJOR_OFFSET 16
43a1092942SMitchell Horne #define OPENSBI_VERSION_MINOR_MASK 0xFFFF
44a1092942SMitchell Horne
45c55272fdSJessica Clarke struct sbi_softc {
46c55272fdSJessica Clarke device_t dev;
47c55272fdSJessica Clarke };
48c55272fdSJessica Clarke
496ec8bf9fSJessica Clarke struct sbi_devinfo {
506ec8bf9fSJessica Clarke struct resource_list rl;
516ec8bf9fSJessica Clarke };
526ec8bf9fSJessica Clarke
53c55272fdSJessica Clarke static struct sbi_softc *sbi_softc = NULL;
54c55272fdSJessica Clarke
55c55272fdSJessica Clarke static u_long sbi_spec_version;
56c55272fdSJessica Clarke static u_long sbi_impl_id;
57c55272fdSJessica Clarke static u_long sbi_impl_version;
58ff33210cSMitchell Horne
5989f34929SMitchell Horne static bool has_time_extension = false;
6089f34929SMitchell Horne static bool has_ipi_extension = false;
6189f34929SMitchell Horne static bool has_rfnc_extension = false;
629bae4ce6SDanjel Qyteza static bool has_srst_extension = false;
6389f34929SMitchell Horne
64ff33210cSMitchell Horne static struct sbi_ret
sbi_get_spec_version(void)65ff33210cSMitchell Horne sbi_get_spec_version(void)
66ff33210cSMitchell Horne {
67ff33210cSMitchell Horne return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_SPEC_VERSION));
68ff33210cSMitchell Horne }
69ff33210cSMitchell Horne
70ff33210cSMitchell Horne static struct sbi_ret
sbi_get_impl_id(void)71ff33210cSMitchell Horne sbi_get_impl_id(void)
72ff33210cSMitchell Horne {
73ff33210cSMitchell Horne return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_IMPL_ID));
74ff33210cSMitchell Horne }
75ff33210cSMitchell Horne
76ff33210cSMitchell Horne static struct sbi_ret
sbi_get_impl_version(void)77ff33210cSMitchell Horne sbi_get_impl_version(void)
78ff33210cSMitchell Horne {
79ff33210cSMitchell Horne return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_IMPL_VERSION));
80ff33210cSMitchell Horne }
81ff33210cSMitchell Horne
82ff33210cSMitchell Horne static struct sbi_ret
sbi_get_mvendorid(void)83ff33210cSMitchell Horne sbi_get_mvendorid(void)
84ff33210cSMitchell Horne {
85ff33210cSMitchell Horne return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_MVENDORID));
86ff33210cSMitchell Horne }
87ff33210cSMitchell Horne
88ff33210cSMitchell Horne static struct sbi_ret
sbi_get_marchid(void)89ff33210cSMitchell Horne sbi_get_marchid(void)
90ff33210cSMitchell Horne {
91ff33210cSMitchell Horne return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_MARCHID));
92ff33210cSMitchell Horne }
93ff33210cSMitchell Horne
94ff33210cSMitchell Horne static struct sbi_ret
sbi_get_mimpid(void)95ff33210cSMitchell Horne sbi_get_mimpid(void)
96ff33210cSMitchell Horne {
97ff33210cSMitchell Horne return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_MIMPID));
98ff33210cSMitchell Horne }
99ff33210cSMitchell Horne
100e28d8a5bSJessica Clarke static void
sbi_shutdown_final(void * dummy __unused,int howto)101e28d8a5bSJessica Clarke sbi_shutdown_final(void *dummy __unused, int howto)
102e28d8a5bSJessica Clarke {
103e28d8a5bSJessica Clarke if ((howto & RB_POWEROFF) != 0)
1049bae4ce6SDanjel Qyteza sbi_system_reset(SBI_SRST_TYPE_SHUTDOWN, SBI_SRST_REASON_NONE);
1059bae4ce6SDanjel Qyteza }
1069bae4ce6SDanjel Qyteza
1079bae4ce6SDanjel Qyteza void
sbi_system_reset(u_long reset_type,u_long reset_reason)1089bae4ce6SDanjel Qyteza sbi_system_reset(u_long reset_type, u_long reset_reason)
1099bae4ce6SDanjel Qyteza {
1109bae4ce6SDanjel Qyteza /* Use the SRST extension, if available. */
1119bae4ce6SDanjel Qyteza if (has_srst_extension) {
1129bae4ce6SDanjel Qyteza (void)SBI_CALL2(SBI_EXT_ID_SRST, SBI_SRST_SYSTEM_RESET,
1139bae4ce6SDanjel Qyteza reset_type, reset_reason);
1149bae4ce6SDanjel Qyteza }
1159bae4ce6SDanjel Qyteza (void)SBI_CALL0(SBI_SHUTDOWN, 0);
116e28d8a5bSJessica Clarke }
117e28d8a5bSJessica Clarke
118ff33210cSMitchell Horne void
sbi_print_version(void)119a1092942SMitchell Horne sbi_print_version(void)
120a1092942SMitchell Horne {
121a1092942SMitchell Horne u_int major;
122a1092942SMitchell Horne u_int minor;
123a1092942SMitchell Horne
124a1092942SMitchell Horne /* For legacy SBI implementations. */
125a1092942SMitchell Horne if (sbi_spec_version == 0) {
126a1092942SMitchell Horne printf("SBI: Unknown (Legacy) Implementation\n");
127a1092942SMitchell Horne printf("SBI Specification Version: 0.1\n");
128a1092942SMitchell Horne return;
129a1092942SMitchell Horne }
130a1092942SMitchell Horne
131a1092942SMitchell Horne switch (sbi_impl_id) {
132a1092942SMitchell Horne case (SBI_IMPL_ID_BBL):
1337c7b8f57SMitchell Horne printf("SBI: Berkely Boot Loader %lu\n", sbi_impl_version);
134a1092942SMitchell Horne break;
13525de8fb6SMitchell Horne case (SBI_IMPL_ID_XVISOR):
136a6405133SMitchell Horne printf("SBI: eXtensible Versatile hypervISOR %lu\n",
137a6405133SMitchell Horne sbi_impl_version);
13825de8fb6SMitchell Horne break;
13925de8fb6SMitchell Horne case (SBI_IMPL_ID_KVM):
140a6405133SMitchell Horne printf("SBI: Kernel-based Virtual Machine %lu\n",
141a6405133SMitchell Horne sbi_impl_version);
14225de8fb6SMitchell Horne break;
14325de8fb6SMitchell Horne case (SBI_IMPL_ID_RUSTSBI):
14425de8fb6SMitchell Horne printf("SBI: RustSBI %lu\n", sbi_impl_version);
14525de8fb6SMitchell Horne break;
14625de8fb6SMitchell Horne case (SBI_IMPL_ID_DIOSIX):
14725de8fb6SMitchell Horne printf("SBI: Diosix %lu\n", sbi_impl_version);
14825de8fb6SMitchell Horne break;
149a1092942SMitchell Horne case (SBI_IMPL_ID_OPENSBI):
150a1092942SMitchell Horne major = sbi_impl_version >> OPENSBI_VERSION_MAJOR_OFFSET;
151a1092942SMitchell Horne minor = sbi_impl_version & OPENSBI_VERSION_MINOR_MASK;
152a1092942SMitchell Horne printf("SBI: OpenSBI v%u.%u\n", major, minor);
153a1092942SMitchell Horne break;
154a1092942SMitchell Horne default:
1557c7b8f57SMitchell Horne printf("SBI: Unrecognized Implementation: %lu\n", sbi_impl_id);
156a1092942SMitchell Horne break;
157a1092942SMitchell Horne }
158a1092942SMitchell Horne
159a1092942SMitchell Horne major = (sbi_spec_version & SBI_SPEC_VERS_MAJOR_MASK) >>
160a1092942SMitchell Horne SBI_SPEC_VERS_MAJOR_OFFSET;
161a1092942SMitchell Horne minor = (sbi_spec_version & SBI_SPEC_VERS_MINOR_MASK);
162a1092942SMitchell Horne printf("SBI Specification Version: %u.%u\n", major, minor);
163a1092942SMitchell Horne }
164a1092942SMitchell Horne
16589f34929SMitchell Horne void
sbi_set_timer(uint64_t val)16689f34929SMitchell Horne sbi_set_timer(uint64_t val)
16789f34929SMitchell Horne {
168a56881d3SJohn Baldwin struct sbi_ret ret __diagused;
16989f34929SMitchell Horne
17089f34929SMitchell Horne /* Use the TIME legacy replacement extension, if available. */
17189f34929SMitchell Horne if (has_time_extension) {
17289f34929SMitchell Horne ret = SBI_CALL1(SBI_EXT_ID_TIME, SBI_TIME_SET_TIMER, val);
17389f34929SMitchell Horne MPASS(ret.error == SBI_SUCCESS);
17489f34929SMitchell Horne } else {
17589f34929SMitchell Horne (void)SBI_CALL1(SBI_SET_TIMER, 0, val);
17689f34929SMitchell Horne }
17789f34929SMitchell Horne }
17889f34929SMitchell Horne
17989f34929SMitchell Horne void
sbi_send_ipi(const u_long * hart_mask)18089f34929SMitchell Horne sbi_send_ipi(const u_long *hart_mask)
18189f34929SMitchell Horne {
182a56881d3SJohn Baldwin struct sbi_ret ret __diagused;
18389f34929SMitchell Horne
18489f34929SMitchell Horne /* Use the IPI legacy replacement extension, if available. */
18589f34929SMitchell Horne if (has_ipi_extension) {
18689f34929SMitchell Horne ret = SBI_CALL2(SBI_EXT_ID_IPI, SBI_IPI_SEND_IPI,
18789f34929SMitchell Horne *hart_mask, 0);
18889f34929SMitchell Horne MPASS(ret.error == SBI_SUCCESS);
18989f34929SMitchell Horne } else {
19089f34929SMitchell Horne (void)SBI_CALL1(SBI_SEND_IPI, 0, (uint64_t)hart_mask);
19189f34929SMitchell Horne }
19289f34929SMitchell Horne }
19389f34929SMitchell Horne
19489f34929SMitchell Horne void
sbi_remote_fence_i(const u_long * hart_mask)19589f34929SMitchell Horne sbi_remote_fence_i(const u_long *hart_mask)
19689f34929SMitchell Horne {
197a56881d3SJohn Baldwin struct sbi_ret ret __diagused;
19889f34929SMitchell Horne
19989f34929SMitchell Horne /* Use the RFENCE legacy replacement extension, if available. */
20089f34929SMitchell Horne if (has_rfnc_extension) {
20189f34929SMitchell Horne ret = SBI_CALL2(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_FENCE_I,
20289f34929SMitchell Horne *hart_mask, 0);
20389f34929SMitchell Horne MPASS(ret.error == SBI_SUCCESS);
20489f34929SMitchell Horne } else {
20589f34929SMitchell Horne (void)SBI_CALL1(SBI_REMOTE_FENCE_I, 0, (uint64_t)hart_mask);
20689f34929SMitchell Horne }
20789f34929SMitchell Horne }
20889f34929SMitchell Horne
20989f34929SMitchell Horne void
sbi_remote_sfence_vma(const u_long * hart_mask,u_long start,u_long size)21089f34929SMitchell Horne sbi_remote_sfence_vma(const u_long *hart_mask, u_long start, u_long size)
21189f34929SMitchell Horne {
212a56881d3SJohn Baldwin struct sbi_ret ret __diagused;
21389f34929SMitchell Horne
21489f34929SMitchell Horne /* Use the RFENCE legacy replacement extension, if available. */
21589f34929SMitchell Horne if (has_rfnc_extension) {
21689f34929SMitchell Horne ret = SBI_CALL4(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_SFENCE_VMA,
21789f34929SMitchell Horne *hart_mask, 0, start, size);
21889f34929SMitchell Horne MPASS(ret.error == SBI_SUCCESS);
21989f34929SMitchell Horne } else {
22089f34929SMitchell Horne (void)SBI_CALL3(SBI_REMOTE_SFENCE_VMA, 0, (uint64_t)hart_mask,
22189f34929SMitchell Horne start, size);
22289f34929SMitchell Horne }
22389f34929SMitchell Horne }
22489f34929SMitchell Horne
22589f34929SMitchell Horne void
sbi_remote_sfence_vma_asid(const u_long * hart_mask,u_long start,u_long size,u_long asid)22689f34929SMitchell Horne sbi_remote_sfence_vma_asid(const u_long *hart_mask, u_long start, u_long size,
22789f34929SMitchell Horne u_long asid)
22889f34929SMitchell Horne {
229a56881d3SJohn Baldwin struct sbi_ret ret __diagused;
23089f34929SMitchell Horne
23189f34929SMitchell Horne /* Use the RFENCE legacy replacement extension, if available. */
23289f34929SMitchell Horne if (has_rfnc_extension) {
233a6405133SMitchell Horne ret = SBI_CALL5(SBI_EXT_ID_RFNC,
234a6405133SMitchell Horne SBI_RFNC_REMOTE_SFENCE_VMA_ASID, *hart_mask, 0, start,
235a6405133SMitchell Horne size, asid);
23689f34929SMitchell Horne MPASS(ret.error == SBI_SUCCESS);
23789f34929SMitchell Horne } else {
23889f34929SMitchell Horne (void)SBI_CALL4(SBI_REMOTE_SFENCE_VMA_ASID, 0,
23989f34929SMitchell Horne (uint64_t)hart_mask, start, size, asid);
24089f34929SMitchell Horne }
24189f34929SMitchell Horne }
24289f34929SMitchell Horne
243bfe918faSMitchell Horne int
sbi_hsm_hart_start(u_long hart,u_long start_addr,u_long priv)244bfe918faSMitchell Horne sbi_hsm_hart_start(u_long hart, u_long start_addr, u_long priv)
245bfe918faSMitchell Horne {
246bfe918faSMitchell Horne struct sbi_ret ret;
247bfe918faSMitchell Horne
248a6405133SMitchell Horne ret = SBI_CALL3(SBI_EXT_ID_HSM, SBI_HSM_HART_START, hart, start_addr,
249a6405133SMitchell Horne priv);
250bfe918faSMitchell Horne return (ret.error != 0 ? (int)ret.error : 0);
251bfe918faSMitchell Horne }
252bfe918faSMitchell Horne
253bfe918faSMitchell Horne void
sbi_hsm_hart_stop(void)254bfe918faSMitchell Horne sbi_hsm_hart_stop(void)
255bfe918faSMitchell Horne {
256bfe918faSMitchell Horne (void)SBI_CALL0(SBI_EXT_ID_HSM, SBI_HSM_HART_STOP);
257bfe918faSMitchell Horne }
258bfe918faSMitchell Horne
259bfe918faSMitchell Horne int
sbi_hsm_hart_status(u_long hart)260bfe918faSMitchell Horne sbi_hsm_hart_status(u_long hart)
261bfe918faSMitchell Horne {
262bfe918faSMitchell Horne struct sbi_ret ret;
263bfe918faSMitchell Horne
264bfe918faSMitchell Horne ret = SBI_CALL1(SBI_EXT_ID_HSM, SBI_HSM_HART_STATUS, hart);
265bfe918faSMitchell Horne
266bfe918faSMitchell Horne return (ret.error != 0 ? (int)ret.error : (int)ret.value);
267bfe918faSMitchell Horne }
268bfe918faSMitchell Horne
269a1092942SMitchell Horne void
sbi_init(void)270ff33210cSMitchell Horne sbi_init(void)
271ff33210cSMitchell Horne {
272ff33210cSMitchell Horne struct sbi_ret sret;
273ff33210cSMitchell Horne
274ff33210cSMitchell Horne /*
275ff33210cSMitchell Horne * Get the spec version. For legacy SBI implementations this will
276ff33210cSMitchell Horne * return an error, otherwise it is guaranteed to succeed.
277ff33210cSMitchell Horne */
278ff33210cSMitchell Horne sret = sbi_get_spec_version();
279ff33210cSMitchell Horne if (sret.error != 0) {
280ff33210cSMitchell Horne /* We are running a legacy SBI implementation. */
281ff33210cSMitchell Horne sbi_spec_version = 0;
282ff33210cSMitchell Horne return;
283ff33210cSMitchell Horne }
284ff33210cSMitchell Horne
285ff33210cSMitchell Horne /* Set the SBI implementation info. */
286ff33210cSMitchell Horne sbi_spec_version = sret.value;
287ff33210cSMitchell Horne sbi_impl_id = sbi_get_impl_id().value;
288ff33210cSMitchell Horne sbi_impl_version = sbi_get_impl_version().value;
289ff33210cSMitchell Horne
290ff33210cSMitchell Horne /* Set the hardware implementation info. */
291ff33210cSMitchell Horne mvendorid = sbi_get_mvendorid().value;
292ff33210cSMitchell Horne marchid = sbi_get_marchid().value;
293ff33210cSMitchell Horne mimpid = sbi_get_mimpid().value;
294ff33210cSMitchell Horne
29589f34929SMitchell Horne /* Probe for legacy replacement extensions. */
29689f34929SMitchell Horne if (sbi_probe_extension(SBI_EXT_ID_TIME) != 0)
29789f34929SMitchell Horne has_time_extension = true;
29889f34929SMitchell Horne if (sbi_probe_extension(SBI_EXT_ID_IPI) != 0)
29989f34929SMitchell Horne has_ipi_extension = true;
30089f34929SMitchell Horne if (sbi_probe_extension(SBI_EXT_ID_RFNC) != 0)
30189f34929SMitchell Horne has_rfnc_extension = true;
3029bae4ce6SDanjel Qyteza if (sbi_probe_extension(SBI_EXT_ID_SRST) != 0)
3039bae4ce6SDanjel Qyteza has_srst_extension = true;
30489f34929SMitchell Horne
305ff33210cSMitchell Horne /*
30689f34929SMitchell Horne * Probe for legacy extensions. We still rely on many of them to be
30789f34929SMitchell Horne * implemented, but this is not guaranteed by the spec.
308ff33210cSMitchell Horne */
30989f34929SMitchell Horne KASSERT(has_time_extension || sbi_probe_extension(SBI_SET_TIMER) != 0,
310ff33210cSMitchell Horne ("SBI doesn't implement sbi_set_timer()"));
311ff33210cSMitchell Horne KASSERT(sbi_probe_extension(SBI_CONSOLE_PUTCHAR) != 0,
312ff33210cSMitchell Horne ("SBI doesn't implement sbi_console_putchar()"));
313ff33210cSMitchell Horne KASSERT(sbi_probe_extension(SBI_CONSOLE_GETCHAR) != 0,
314ff33210cSMitchell Horne ("SBI doesn't implement sbi_console_getchar()"));
31589f34929SMitchell Horne KASSERT(has_ipi_extension || sbi_probe_extension(SBI_SEND_IPI) != 0,
316ff33210cSMitchell Horne ("SBI doesn't implement sbi_send_ipi()"));
31789f34929SMitchell Horne KASSERT(has_rfnc_extension ||
31889f34929SMitchell Horne sbi_probe_extension(SBI_REMOTE_FENCE_I) != 0,
319ff33210cSMitchell Horne ("SBI doesn't implement sbi_remote_fence_i()"));
32089f34929SMitchell Horne KASSERT(has_rfnc_extension ||
32189f34929SMitchell Horne sbi_probe_extension(SBI_REMOTE_SFENCE_VMA) != 0,
322ff33210cSMitchell Horne ("SBI doesn't implement sbi_remote_sfence_vma()"));
32389f34929SMitchell Horne KASSERT(has_rfnc_extension ||
32489f34929SMitchell Horne sbi_probe_extension(SBI_REMOTE_SFENCE_VMA_ASID) != 0,
325ff33210cSMitchell Horne ("SBI doesn't implement sbi_remote_sfence_vma_asid()"));
3269bae4ce6SDanjel Qyteza KASSERT(has_srst_extension || sbi_probe_extension(SBI_SHUTDOWN) != 0,
3279bae4ce6SDanjel Qyteza ("SBI doesn't implement a shutdown or reset extension"));
328ff33210cSMitchell Horne }
329e28d8a5bSJessica Clarke
330e28d8a5bSJessica Clarke static void
sbi_identify(driver_t * driver,device_t parent)331c55272fdSJessica Clarke sbi_identify(driver_t *driver, device_t parent)
332e28d8a5bSJessica Clarke {
333c55272fdSJessica Clarke device_t dev;
334c55272fdSJessica Clarke
335c55272fdSJessica Clarke if (device_find_child(parent, "sbi", -1) != NULL)
336c55272fdSJessica Clarke return;
337c55272fdSJessica Clarke
338c55272fdSJessica Clarke dev = BUS_ADD_CHILD(parent, 0, "sbi", -1);
339c55272fdSJessica Clarke if (dev == NULL)
340c55272fdSJessica Clarke device_printf(parent, "Can't add sbi child\n");
341e28d8a5bSJessica Clarke }
342e28d8a5bSJessica Clarke
343c55272fdSJessica Clarke static int
sbi_probe(device_t dev)344c55272fdSJessica Clarke sbi_probe(device_t dev)
345c55272fdSJessica Clarke {
346c55272fdSJessica Clarke device_set_desc(dev, "RISC-V Supervisor Binary Interface");
347c55272fdSJessica Clarke
348c55272fdSJessica Clarke return (BUS_PROBE_NOWILDCARD);
349c55272fdSJessica Clarke }
350c55272fdSJessica Clarke
351c55272fdSJessica Clarke static int
sbi_attach(device_t dev)352c55272fdSJessica Clarke sbi_attach(device_t dev)
353c55272fdSJessica Clarke {
354c55272fdSJessica Clarke struct sbi_softc *sc;
3556ec8bf9fSJessica Clarke #ifdef SMP
3566ec8bf9fSJessica Clarke device_t child;
3576ec8bf9fSJessica Clarke struct sbi_devinfo *di;
3586ec8bf9fSJessica Clarke #endif
359c55272fdSJessica Clarke
360c55272fdSJessica Clarke if (sbi_softc != NULL)
361c55272fdSJessica Clarke return (ENXIO);
362c55272fdSJessica Clarke
363c55272fdSJessica Clarke sc = device_get_softc(dev);
364c55272fdSJessica Clarke sc->dev = dev;
365c55272fdSJessica Clarke sbi_softc = sc;
366c55272fdSJessica Clarke
367c55272fdSJessica Clarke EVENTHANDLER_REGISTER(shutdown_final, sbi_shutdown_final, NULL,
368c55272fdSJessica Clarke SHUTDOWN_PRI_LAST);
369c55272fdSJessica Clarke
3706ec8bf9fSJessica Clarke #ifdef SMP
3716ec8bf9fSJessica Clarke di = malloc(sizeof(*di), M_DEVBUF, M_WAITOK | M_ZERO);
3726ec8bf9fSJessica Clarke resource_list_init(&di->rl);
3736ec8bf9fSJessica Clarke child = device_add_child(dev, "sbi_ipi", -1);
3746ec8bf9fSJessica Clarke if (child == NULL) {
3756ec8bf9fSJessica Clarke device_printf(dev, "Could not add sbi_ipi child\n");
3766ec8bf9fSJessica Clarke return (ENXIO);
3776ec8bf9fSJessica Clarke }
3786ec8bf9fSJessica Clarke
3796ec8bf9fSJessica Clarke device_set_ivars(child, di);
3806ec8bf9fSJessica Clarke #endif
3816ec8bf9fSJessica Clarke
382c55272fdSJessica Clarke return (0);
383c55272fdSJessica Clarke }
384c55272fdSJessica Clarke
3856ec8bf9fSJessica Clarke static struct resource_list *
sbi_get_resource_list(device_t bus,device_t child)3866ec8bf9fSJessica Clarke sbi_get_resource_list(device_t bus, device_t child)
3876ec8bf9fSJessica Clarke {
3886ec8bf9fSJessica Clarke struct sbi_devinfo *di;
3896ec8bf9fSJessica Clarke
3906ec8bf9fSJessica Clarke di = device_get_ivars(child);
3916ec8bf9fSJessica Clarke KASSERT(di != NULL, ("%s: No devinfo", __func__));
3926ec8bf9fSJessica Clarke
3936ec8bf9fSJessica Clarke return (&di->rl);
3946ec8bf9fSJessica Clarke }
3956ec8bf9fSJessica Clarke
396c55272fdSJessica Clarke static device_method_t sbi_methods[] = {
397c55272fdSJessica Clarke /* Device interface */
398c55272fdSJessica Clarke DEVMETHOD(device_identify, sbi_identify),
399c55272fdSJessica Clarke DEVMETHOD(device_probe, sbi_probe),
400c55272fdSJessica Clarke DEVMETHOD(device_attach, sbi_attach),
401c55272fdSJessica Clarke
4026ec8bf9fSJessica Clarke /* Bus interface */
4036ec8bf9fSJessica Clarke DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
4046ec8bf9fSJessica Clarke DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
4056ec8bf9fSJessica Clarke DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
4066ec8bf9fSJessica Clarke DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
4076ec8bf9fSJessica Clarke DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
4086ec8bf9fSJessica Clarke DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
4096ec8bf9fSJessica Clarke DEVMETHOD(bus_get_resource_list, sbi_get_resource_list),
4106ec8bf9fSJessica Clarke DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
4116ec8bf9fSJessica Clarke DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
4126ec8bf9fSJessica Clarke
413c55272fdSJessica Clarke DEVMETHOD_END
414c55272fdSJessica Clarke };
415c55272fdSJessica Clarke
416c55272fdSJessica Clarke DEFINE_CLASS_0(sbi, sbi_driver, sbi_methods, sizeof(struct sbi_softc));
417c55272fdSJessica Clarke EARLY_DRIVER_MODULE(sbi, nexus, sbi_driver, 0, 0,
418c55272fdSJessica Clarke BUS_PASS_CPU + BUS_PASS_ORDER_FIRST);
419