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