1*f83db12cSthorpej /* $NetBSD: mainbus.c,v 1.1 2024/01/02 07:40:59 thorpej Exp $ */
2*f83db12cSthorpej
3*f83db12cSthorpej /*-
4*f83db12cSthorpej * Copyright (c) 2023 The NetBSD Foundation, Inc.
5*f83db12cSthorpej * All rights reserved.
6*f83db12cSthorpej *
7*f83db12cSthorpej * This code is derived from software contributed to The NetBSD Foundation
8*f83db12cSthorpej * by Jason R. Thorpe.
9*f83db12cSthorpej *
10*f83db12cSthorpej * Redistribution and use in source and binary forms, with or without
11*f83db12cSthorpej * modification, are permitted provided that the following conditions
12*f83db12cSthorpej * are met:
13*f83db12cSthorpej * 1. Redistributions of source code must retain the above copyright
14*f83db12cSthorpej * notice, this list of conditions and the following disclaimer.
15*f83db12cSthorpej * 2. Redistributions in binary form must reproduce the above copyright
16*f83db12cSthorpej * notice, this list of conditions and the following disclaimer in the
17*f83db12cSthorpej * documentation and/or other materials provided with the distribution.
18*f83db12cSthorpej *
19*f83db12cSthorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*f83db12cSthorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*f83db12cSthorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*f83db12cSthorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*f83db12cSthorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*f83db12cSthorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*f83db12cSthorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*f83db12cSthorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*f83db12cSthorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*f83db12cSthorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*f83db12cSthorpej * POSSIBILITY OF SUCH DAMAGE.
30*f83db12cSthorpej */
31*f83db12cSthorpej
32*f83db12cSthorpej #include <sys/cdefs.h>
33*f83db12cSthorpej __KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.1 2024/01/02 07:40:59 thorpej Exp $");
34*f83db12cSthorpej
35*f83db12cSthorpej #define _VIRT68K_BUS_DMA_PRIVATE
36*f83db12cSthorpej #define _VIRT68K_BUS_SPACE_PRIVATE
37*f83db12cSthorpej
38*f83db12cSthorpej #include <sys/param.h>
39*f83db12cSthorpej #include <sys/kernel.h>
40*f83db12cSthorpej #include <sys/systm.h>
41*f83db12cSthorpej #include <sys/device.h>
42*f83db12cSthorpej #include <sys/bus.h>
43*f83db12cSthorpej #include <sys/intr.h>
44*f83db12cSthorpej
45*f83db12cSthorpej #include <machine/bootinfo.h>
46*f83db12cSthorpej #include <machine/cpu.h>
47*f83db12cSthorpej
48*f83db12cSthorpej #include <virt68k/dev/mainbusvar.h>
49*f83db12cSthorpej
50*f83db12cSthorpej struct virt68k_bus_dma_tag _mainbus_dma_tag = {
51*f83db12cSthorpej NULL,
52*f83db12cSthorpej _bus_dmamap_create,
53*f83db12cSthorpej _bus_dmamap_destroy,
54*f83db12cSthorpej _bus_dmamap_load_direct,
55*f83db12cSthorpej _bus_dmamap_load_mbuf_direct,
56*f83db12cSthorpej _bus_dmamap_load_uio_direct,
57*f83db12cSthorpej _bus_dmamap_load_raw_direct,
58*f83db12cSthorpej _bus_dmamap_unload,
59*f83db12cSthorpej NULL, /* Set up at run-time */
60*f83db12cSthorpej _bus_dmamem_alloc,
61*f83db12cSthorpej _bus_dmamem_free,
62*f83db12cSthorpej _bus_dmamem_map,
63*f83db12cSthorpej _bus_dmamem_unmap,
64*f83db12cSthorpej _bus_dmamem_mmap
65*f83db12cSthorpej };
66*f83db12cSthorpej
67*f83db12cSthorpej struct virt68k_bus_space_tag _mainbus_space_tag = {
68*f83db12cSthorpej NULL,
69*f83db12cSthorpej _bus_space_map,
70*f83db12cSthorpej _bus_space_unmap,
71*f83db12cSthorpej _bus_space_peek_1,
72*f83db12cSthorpej _bus_space_peek_2,
73*f83db12cSthorpej _bus_space_peek_4,
74*f83db12cSthorpej _bus_space_poke_1,
75*f83db12cSthorpej _bus_space_poke_2,
76*f83db12cSthorpej _bus_space_poke_4
77*f83db12cSthorpej };
78*f83db12cSthorpej
79*f83db12cSthorpej static int
mainbus_print(void * aux,const char * cp)80*f83db12cSthorpej mainbus_print(void *aux, const char *cp)
81*f83db12cSthorpej {
82*f83db12cSthorpej struct mainbus_attach_args *ma = aux;
83*f83db12cSthorpej
84*f83db12cSthorpej if (cp) {
85*f83db12cSthorpej aprint_normal("%s at %s", ma->ma_compatible, cp);
86*f83db12cSthorpej }
87*f83db12cSthorpej
88*f83db12cSthorpej aprint_normal(" addr 0x%lx", ma->ma_addr);
89*f83db12cSthorpej
90*f83db12cSthorpej return UNCONF;
91*f83db12cSthorpej }
92*f83db12cSthorpej
93*f83db12cSthorpej static int
mainbus_match(device_t parent __unused,cfdata_t cf __unused,void * args __unused)94*f83db12cSthorpej mainbus_match(device_t parent __unused, cfdata_t cf __unused,
95*f83db12cSthorpej void *args __unused)
96*f83db12cSthorpej {
97*f83db12cSthorpej static int mainbus_matched;
98*f83db12cSthorpej
99*f83db12cSthorpej if (mainbus_matched)
100*f83db12cSthorpej return 0;
101*f83db12cSthorpej
102*f83db12cSthorpej return (mainbus_matched = 1);
103*f83db12cSthorpej }
104*f83db12cSthorpej
105*f83db12cSthorpej static bool
mainbus_attach_gfpic(struct bi_record * bi,void * v)106*f83db12cSthorpej mainbus_attach_gfpic(struct bi_record *bi, void *v)
107*f83db12cSthorpej {
108*f83db12cSthorpej struct mainbus_attach_args ma = {
109*f83db12cSthorpej .ma_st = &_mainbus_space_tag,
110*f83db12cSthorpej .ma_dmat = &_mainbus_dma_tag,
111*f83db12cSthorpej };
112*f83db12cSthorpej device_t self = v;
113*f83db12cSthorpej struct bi_virt_dev *vd = bootinfo_dataptr(bi);
114*f83db12cSthorpej int i;
115*f83db12cSthorpej
116*f83db12cSthorpej if (bi->bi_tag == BI_VIRT_GF_PIC_BASE) {
117*f83db12cSthorpej for (i = 0; i < NPIC; i++) {
118*f83db12cSthorpej ma.ma_compatible = "google,goldfish-pic";
119*f83db12cSthorpej ma.ma_addr = vd->vd_mmio_base + (i * 0x1000);
120*f83db12cSthorpej ma.ma_size = 0x1000;
121*f83db12cSthorpej ma.ma_irq = vd->vd_irq_base + i;
122*f83db12cSthorpej config_found(self, &ma, mainbus_print, CFARGS_NONE);
123*f83db12cSthorpej }
124*f83db12cSthorpej return false; /* done searching */
125*f83db12cSthorpej }
126*f83db12cSthorpej return true; /* keep searching */
127*f83db12cSthorpej }
128*f83db12cSthorpej
129*f83db12cSthorpej static bool
mainbus_attach_gfother(struct bi_record * bi,void * v)130*f83db12cSthorpej mainbus_attach_gfother(struct bi_record *bi, void *v)
131*f83db12cSthorpej {
132*f83db12cSthorpej struct mainbus_attach_args ma = {
133*f83db12cSthorpej .ma_st = &_mainbus_space_tag,
134*f83db12cSthorpej .ma_dmat = &_mainbus_dma_tag,
135*f83db12cSthorpej };
136*f83db12cSthorpej device_t self = v;
137*f83db12cSthorpej struct bi_virt_dev *vd = bootinfo_dataptr(bi);
138*f83db12cSthorpej int i;
139*f83db12cSthorpej
140*f83db12cSthorpej switch (bi->bi_tag) {
141*f83db12cSthorpej case BI_VIRT_GF_RTC_BASE:
142*f83db12cSthorpej /*
143*f83db12cSthorpej * There are 2 Goldfish RTC instances on the virt68k
144*f83db12cSthorpej * platform:
145*f83db12cSthorpej *
146*f83db12cSthorpej * 1- This is used as the system timer / hard-clock.
147*f83db12cSthorpej * 2- This is used as the TODR.
148*f83db12cSthorpej */
149*f83db12cSthorpej for (i = 0; i < 2; i++) {
150*f83db12cSthorpej ma.ma_compatible = (i == 0)
151*f83db12cSthorpej ? "netbsd,goldfish-rtc-hardclock"
152*f83db12cSthorpej : "google,goldfish-rtc";
153*f83db12cSthorpej ma.ma_addr = vd->vd_mmio_base + (i * 0x1000);
154*f83db12cSthorpej ma.ma_size = 0x1000;
155*f83db12cSthorpej ma.ma_irq = vd->vd_irq_base + i;
156*f83db12cSthorpej config_found(self, &ma, mainbus_print, CFARGS_NONE);
157*f83db12cSthorpej }
158*f83db12cSthorpej break;
159*f83db12cSthorpej
160*f83db12cSthorpej case BI_VIRT_GF_TTY_BASE:
161*f83db12cSthorpej ma.ma_compatible = "google,goldfish-tty";
162*f83db12cSthorpej ma.ma_addr = vd->vd_mmio_base;
163*f83db12cSthorpej ma.ma_size = 0x1000;
164*f83db12cSthorpej ma.ma_irq = vd->vd_irq_base;
165*f83db12cSthorpej config_found(self, &ma, mainbus_print, CFARGS_NONE);
166*f83db12cSthorpej break;
167*f83db12cSthorpej }
168*f83db12cSthorpej
169*f83db12cSthorpej return true; /* keep searching */
170*f83db12cSthorpej }
171*f83db12cSthorpej
172*f83db12cSthorpej #define VIRTIO_MMIO_DEVICE_ID 0x008
173*f83db12cSthorpej
174*f83db12cSthorpej static void
mainbus_attach_virtio(device_t self,struct mainbus_attach_args * ma)175*f83db12cSthorpej mainbus_attach_virtio(device_t self, struct mainbus_attach_args *ma)
176*f83db12cSthorpej {
177*f83db12cSthorpej bus_space_handle_t bsh;
178*f83db12cSthorpej uint32_t val;
179*f83db12cSthorpej
180*f83db12cSthorpej /*
181*f83db12cSthorpej * Probe the virtio slot to see if there's actually something
182*f83db12cSthorpej * there before we claim that it is "found".
183*f83db12cSthorpej */
184*f83db12cSthorpej if (bus_space_map(ma->ma_st, ma->ma_addr, ma->ma_size, 0, &bsh) != 0) {
185*f83db12cSthorpej aprint_error_dev(self,
186*f83db12cSthorpej "unable to map virtio slot @ 0x%lx\n", ma->ma_addr);
187*f83db12cSthorpej return;
188*f83db12cSthorpej }
189*f83db12cSthorpej val = bus_space_read_4(ma->ma_st, bsh, VIRTIO_MMIO_DEVICE_ID);
190*f83db12cSthorpej bus_space_unmap(ma->ma_st, bsh, ma->ma_size);
191*f83db12cSthorpej
192*f83db12cSthorpej if (val != 0) {
193*f83db12cSthorpej config_found(self, ma, mainbus_print, CFARGS_NONE);
194*f83db12cSthorpej }
195*f83db12cSthorpej }
196*f83db12cSthorpej
197*f83db12cSthorpej static bool
mainbus_attach_other(struct bi_record * bi,void * v)198*f83db12cSthorpej mainbus_attach_other(struct bi_record *bi, void *v)
199*f83db12cSthorpej {
200*f83db12cSthorpej struct mainbus_attach_args ma = {
201*f83db12cSthorpej .ma_st = &_mainbus_space_tag,
202*f83db12cSthorpej .ma_dmat = &_mainbus_dma_tag,
203*f83db12cSthorpej };
204*f83db12cSthorpej device_t self = v;
205*f83db12cSthorpej struct bi_virt_dev *vd = bootinfo_dataptr(bi);
206*f83db12cSthorpej int i;
207*f83db12cSthorpej
208*f83db12cSthorpej switch (bi->bi_tag) {
209*f83db12cSthorpej case BI_VIRT_QEMU_VERSION:
210*f83db12cSthorpej case BI_VIRT_GF_PIC_BASE:
211*f83db12cSthorpej case BI_VIRT_GF_RTC_BASE:
212*f83db12cSthorpej case BI_VIRT_GF_TTY_BASE:
213*f83db12cSthorpej /* Handled elsewhere. */
214*f83db12cSthorpej break;
215*f83db12cSthorpej
216*f83db12cSthorpej case BI_VIRT_VIRTIO_BASE:
217*f83db12cSthorpej for (i = 0; i < (32 * 4); i++) {
218*f83db12cSthorpej ma.ma_compatible = "virtio,mmio";
219*f83db12cSthorpej ma.ma_addr = vd->vd_mmio_base + (i * 0x200);
220*f83db12cSthorpej ma.ma_size = 0x200;
221*f83db12cSthorpej ma.ma_irq = vd->vd_irq_base + i;
222*f83db12cSthorpej mainbus_attach_virtio(self, &ma);
223*f83db12cSthorpej }
224*f83db12cSthorpej break;
225*f83db12cSthorpej
226*f83db12cSthorpej case BI_VIRT_CTRL_BASE:
227*f83db12cSthorpej ma.ma_compatible = "netbsd,qemu-virt-ctrl"; /* XXX */
228*f83db12cSthorpej ma.ma_addr = vd->vd_mmio_base;
229*f83db12cSthorpej ma.ma_size = 0x1000;
230*f83db12cSthorpej ma.ma_irq = vd->vd_irq_base;
231*f83db12cSthorpej config_found(self, &ma, mainbus_print, CFARGS_NONE);
232*f83db12cSthorpej break;
233*f83db12cSthorpej
234*f83db12cSthorpej default:
235*f83db12cSthorpej if (bi->bi_tag >= BI_MACHDEP(0)) {
236*f83db12cSthorpej aprint_error_dev(self,
237*f83db12cSthorpej "unknown bootinfo tag: 0x%08x\n", bi->bi_tag);
238*f83db12cSthorpej }
239*f83db12cSthorpej break;
240*f83db12cSthorpej }
241*f83db12cSthorpej return true; /* keep searching */
242*f83db12cSthorpej }
243*f83db12cSthorpej
244*f83db12cSthorpej static void
mainbus_attach(device_t parent __unused,device_t self,void * args __unused)245*f83db12cSthorpej mainbus_attach(device_t parent __unused, device_t self, void *args __unused)
246*f83db12cSthorpej {
247*f83db12cSthorpej
248*f83db12cSthorpej printf("\n");
249*f83db12cSthorpej
250*f83db12cSthorpej _mainbus_dma_tag._dmamap_sync =
251*f83db12cSthorpej (mmutype == MMU_68040) ? _bus_dmamap_sync_0460
252*f83db12cSthorpej : _bus_dmamap_sync_030;
253*f83db12cSthorpej
254*f83db12cSthorpej /* Attach the PICs first. */
255*f83db12cSthorpej bootinfo_enumerate(mainbus_attach_gfpic, self);
256*f83db12cSthorpej
257*f83db12cSthorpej /* Attach the reset of the Goldfish devices next. */
258*f83db12cSthorpej bootinfo_enumerate(mainbus_attach_gfother, self);
259*f83db12cSthorpej
260*f83db12cSthorpej /* Now the rest. */
261*f83db12cSthorpej bootinfo_enumerate(mainbus_attach_other, self);
262*f83db12cSthorpej }
263*f83db12cSthorpej
264*f83db12cSthorpej int
mainbus_compatible_match(const struct mainbus_attach_args * const ma,const struct device_compatible_entry * driver_compats)265*f83db12cSthorpej mainbus_compatible_match(const struct mainbus_attach_args * const ma,
266*f83db12cSthorpej const struct device_compatible_entry * driver_compats)
267*f83db12cSthorpej {
268*f83db12cSthorpej const char *device_compats[1] = {
269*f83db12cSthorpej [0] = ma->ma_compatible,
270*f83db12cSthorpej };
271*f83db12cSthorpej return device_compatible_match(device_compats,
272*f83db12cSthorpej __arraycount(device_compats), driver_compats);
273*f83db12cSthorpej }
274*f83db12cSthorpej
275*f83db12cSthorpej const struct device_compatible_entry *
mainbus_compatible_lookup(const struct mainbus_attach_args * const ma,const struct device_compatible_entry * driver_compats)276*f83db12cSthorpej mainbus_compatible_lookup(const struct mainbus_attach_args * const ma,
277*f83db12cSthorpej const struct device_compatible_entry * driver_compats)
278*f83db12cSthorpej {
279*f83db12cSthorpej const char *device_compats[1] = {
280*f83db12cSthorpej [0] = ma->ma_compatible,
281*f83db12cSthorpej };
282*f83db12cSthorpej return device_compatible_lookup(device_compats,
283*f83db12cSthorpej __arraycount(device_compats), driver_compats);
284*f83db12cSthorpej }
285*f83db12cSthorpej
286*f83db12cSthorpej CFATTACH_DECL_NEW(mainbus, 0,
287*f83db12cSthorpej mainbus_match, mainbus_attach, NULL, NULL);
288