Home | History | Annotate | Line # | Download | only in dev
mainbus.c revision 1.1
      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
     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
     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
    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
    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
    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
    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
    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
    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 *
    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