Home | History | Annotate | Line # | Download | only in hb68k
      1 /*	$NetBSD: machdep.c,v 1.4 2026/08/02 15:44:21 thorpej Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2026 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 /*
     33  * Copyright (c) 1988 University of Utah.
     34  * Copyright (c) 1982, 1986, 1990, 1993
     35  *	The Regents of the University of California.  All rights reserved.
     36  *
     37  * This code is derived from software contributed to Berkeley by
     38  * the Systems Programming Group of the University of Utah Computer
     39  * Science Department.
     40  *
     41  * Redistribution and use in source and binary forms, with or without
     42  * modification, are permitted provided that the following conditions
     43  * are met:
     44  * 1. Redistributions of source code must retain the above copyright
     45  *    notice, this list of conditions and the following disclaimer.
     46  * 2. Redistributions in binary form must reproduce the above copyright
     47  *    notice, this list of conditions and the following disclaimer in the
     48  *    documentation and/or other materials provided with the distribution.
     49  * 3. Neither the name of the University nor the names of its contributors
     50  *    may be used to endorse or promote products derived from this software
     51  *    without specific prior written permission.
     52  *
     53  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     54  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     56  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     57  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     58  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     59  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     60  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     61  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     62  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     63  * SUCH DAMAGE.
     64  *
     65  * from: Utah $Hdr: machdep.c 1.74 92/12/20$
     66  *
     67  *	@(#)machdep.c	8.10 (Berkeley) 4/20/94
     68  */
     69 
     70 #include <sys/cdefs.h>
     71 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.4 2026/08/02 15:44:21 thorpej Exp $");
     72 
     73 #include "opt_ddb.h"
     74 #include "opt_modular.h"
     75 #include "opt_m68k_arch.h"
     76 #include "opt_hb68k_config.h"
     77 
     78 #include "ksyms.h"
     79 
     80 #define	_M68K_BUS_SPACE_PRIVATE
     81 #define	_M68K_BUS_DMA_PRIVATE
     82 
     83 #include <sys/param.h>
     84 #include <sys/systm.h>
     85 #include <sys/kernel.h>
     86 #include <sys/reboot.h>
     87 #include <sys/conf.h>
     88 #include <sys/ksyms.h>
     89 #include <sys/module.h>
     90 #include <sys/device.h>
     91 #include <sys/cpu.h>
     92 #include <sys/boot_flag.h>
     93 #include <sys/bus.h>
     94 
     95 #include <dev/fdt/fdtvar.h>
     96 #include <dev/fdt/fdt_boot.h>
     97 #include <dev/fdt/fdt_console.h>
     98 #include <dev/fdt/fdt_platform.h>
     99 
    100 #include <dev/ofw/openfirm.h>
    101 
    102 #include <uvm/uvm_extern.h>
    103 
    104 #include <sys/sysctl.h>
    105 
    106 #include <dev/cons.h>
    107 
    108 #if defined(CONFIG_LINUX_BOOTINFO)
    109 #include <m68k/linux_bootinfo.h>
    110 #endif
    111 
    112 #ifdef DDB
    113 #include <machine/db_machdep.h>
    114 #include <ddb/db_extern.h>
    115 #include <ddb/db_output.h>
    116 #endif
    117 
    118 /* Default to the fastest CPU we could have in this configuration. */
    119 #if defined(M68060)
    120 #define	DELAY_DIVISOR_DEFAULT	delay_divisor_est60(80)
    121 #elif defined(M68040)
    122 #define	DELAY_DIVISOR_DEFAULT	delay_divisor_est40(33)
    123 #elif defined(M68030)
    124 #define	DELAY_DIVISOR_DEFAULT	delay_divisor_est(50)
    125 #elif defined(M68020)
    126 #define	DELAY_DIVISOR_DEFAULT	delay_divisor_est(25)
    127 #else
    128 #define	DELAY_DIVISOR_DEFAULT	delay_divisor_est(12)
    129 #endif
    130 
    131 int	delay_divisor = DELAY_DIVISOR_DEFAULT;
    132 
    133 /* Machine-dependent initialization routines. */
    134 void	machine_init(paddr_t);
    135 
    136 #if defined(M68K_MMU_MOTOROLA)
    137 struct pmap_bootmap machine_bootmap[MACHINE_BOOTMAP_ENTRY_COUNT+1] = {
    138 	/*
    139 	 * pmap_bootstrap1() will skip any entry with pmbm_size == 0.
    140 	 * The machine-specific bootstrap() function simply needs to
    141 	 * fill in machine_bootmap[] entries it wishes to use.
    142 	 */
    143 	[MACHINE_BOOTMAP_ENTRY_COUNT] = { .pmbm_vaddr = -1 }
    144 };
    145 #endif /* M68K_MMU_MOTOROLA */
    146 
    147 bool
    148 machine_fdt_init(void *addr)
    149 {
    150 	static bool fdt_initialized;
    151 
    152 	if (fdt_initialized) {
    153 		return true;
    154 	}
    155 
    156 	if (fdtbus_init(addr)) {
    157 		fdt_initialized = true;
    158 	}
    159 	return fdt_initialized;
    160 }
    161 
    162 const struct fdt_platform *
    163 machine_platform(void)
    164 {
    165 	static const struct fdt_platform *this_plat;
    166 
    167 	if (__predict_false(this_plat == NULL)) {
    168 		this_plat = fdt_platform_find();
    169 	}
    170 	return this_plat;
    171 }
    172 
    173 static struct m68k_bus_dma_tag hb68k_simple_dma_tag = {
    174 	NULL,
    175 	0,
    176 	_bus_dmamap_create,
    177 	_bus_dmamap_destroy,
    178 	_bus_dmamap_load_direct,
    179 	_bus_dmamap_load_mbuf_direct,
    180 	_bus_dmamap_load_uio_direct,
    181 	_bus_dmamap_load_raw_direct,
    182 	_bus_dmamap_unload,
    183 	_bus_dmamap_sync,
    184 	_bus_dmamem_alloc,
    185 	_bus_dmamem_free,
    186 	_bus_dmamem_map,
    187 	_bus_dmamem_unmap,
    188 	_bus_dmamem_mmap
    189 };
    190 
    191 bus_dma_tag_t
    192 fdtbus_dma_tag_create(int phandle, const struct fdt_dma_range *ranges,
    193     u_int nranges)
    194 {
    195 	KASSERT(nranges == 0);
    196 	return &hb68k_simple_dma_tag;
    197 }
    198 
    199 bus_space_tag_t
    200 fdtbus_bus_tag_create(int phandle, uint32_t flags)
    201 {
    202 	return &m68k_simple_bus_space;
    203 }
    204 
    205 void
    206 machine_init_attach_args(struct fdt_attach_args *faa)
    207 {
    208 	memset(faa, 0, sizeof(*faa));
    209 
    210 	faa->faa_bst = &m68k_simple_bus_space;
    211 	faa->faa_dmat = &hb68k_simple_dma_tag;
    212 }
    213 
    214 #if NKSYMS || defined(DDB) || defined(MODULAR)
    215 vaddr_t ksym_start, ksym_end;
    216 
    217 static bool
    218 machine_find_ksyms(void)
    219 {
    220 	/*
    221 	 * If they've already been found, then no more work to do!
    222 	 */
    223 	if (ksym_end - ksym_start != 0) {
    224 		return true;
    225 	}
    226 
    227 #if defined(CONFIG_LINUX_BOOTINFO)
    228 	struct bootinfo_data *bid = bootinfo_data();
    229 	if (bid->bootinfo_ksym_size != 0) {
    230 		ksym_start = bid->bootinfo_ksym_start;
    231 		ksym_end = ksym_start + bid->bootinfo_ksym_size;
    232 		return true;
    233 	}
    234 #endif
    235 
    236 	return false;
    237 }
    238 #endif /* NKSYMS || DDB || MODULAR */
    239 
    240 static const char *
    241 machine_parse_bootflags(const char *cp)
    242 {
    243 	while (*cp != '\0') {
    244 		if (*cp == ' ' || *cp == '\t') {
    245 			break;
    246 		}
    247 		BOOT_FLAG(*cp, boothowto);
    248 		cp++;
    249 	}
    250 	return cp;
    251 }
    252 
    253 static void
    254 machine_parse_cmdline(void)
    255 {
    256 	/*
    257 	 * We are pretty flexible with what we accept.  Here, we're
    258 	 * just interested in boot flags, so we can do:
    259 	 *
    260 	 *	flags=...
    261 	 * -or-
    262 	 *	-...
    263 	 *
    264 	 * Or any combination of that, really.
    265 	 *
    266 	 * We also notice root= and pass that to machine_set_bootspec().
    267 	 */
    268 	const char *cp = NULL;
    269 
    270 #if defined(CONFIG_LINUX_BOOTINFO)
    271 	if (cp == NULL) {
    272 		struct bi_record *bi = bootinfo_find(BI_COMMAND_LINE);
    273 		if (bi != NULL) {
    274 			cp = bootinfo_dataptr(bi);
    275 		}
    276 	}
    277 #endif
    278 	if (cp == NULL) {
    279 		cp = fdt_get_bootargs();
    280 	}
    281 
    282 	if (cp == NULL) {
    283 		return;
    284 	}
    285 
    286 	while (*cp != '\0') {
    287 		if (*cp == '-') {
    288 			cp = machine_parse_bootflags(cp + 1);
    289 			continue;
    290 		}
    291 		if (strncmp(cp, "flags=", 6) == 0) {
    292 			cp = machine_parse_bootflags(cp + 6);
    293 			continue;
    294 		}
    295 		if (strncmp(cp, "root=", 5) == 0) {
    296 			cp = machine_set_bootspec(cp + 5);
    297 			continue;
    298 		}
    299 		cp++;
    300 	}
    301 }
    302 
    303 /*
    304  * Early initialization, right before main is called.
    305  */
    306 void
    307 machine_init(paddr_t nextpa)
    308 {
    309 	int phandle;
    310 	uint32_t val;
    311 
    312 #if defined(CONFIG_LINUX_BOOTINFO)
    313 	/*
    314 	 * For the FDT machtype, the device tree is passed as a
    315 	 * blob directly in the bootinfo.
    316 	 */
    317 	struct bi_record *bi =
    318 	    bootinfo_find_machdep(BI_MACH_FDT, BI_FDT_BLOB);
    319 	if (bi != NULL) {
    320 		struct bi_data *d = bootinfo_dataptr(bi);
    321 		machine_fdt_init(&d->data_bytes[0]);
    322 	}
    323 #endif
    324 
    325 	const struct fdt_platform *plat = machine_platform();
    326 	if (plat->fp_machine_init != NULL) {
    327 		nextpa = plat->fp_machine_init(nextpa);
    328 	}
    329 
    330 	phandle = OF_finddevice("/cpus/cpu@0");
    331 	if (phandle >= 0 &&
    332 	    of_getprop_uint32(phandle, "clock-frequency", &val) != -1) {
    333 		cpuspeed_khz = val / 1000;
    334 
    335 		/*
    336 		 * Set initial delay divisor; this may get properly
    337 		 * calibrated later.
    338 		 */
    339 		switch (cputype) {
    340 #ifdef M68060
    341 		case CPU_68060:
    342 			delay_divisor =
    343 			    delay_divisor_est60(cpuspeed_khz / 1000);
    344 			break;
    345 #endif
    346 #ifdef M68040
    347 		case CPU_68040:
    348 			delay_divisor =
    349 			    delay_divisor_est40(cpuspeed_khz / 1000);
    350 			break;
    351 #endif
    352 		default:
    353 			delay_divisor =
    354 			    delay_divisor_est(cpuspeed_khz / 1000);
    355 			break;
    356 		}
    357 	}
    358 
    359 #if defined(CONFIG_LINUX_BOOTINFO)
    360 	/*
    361 	 * Pass 2 at parsing bootinfo now that the MMU is enabled.
    362 	 */
    363 	bootinfo_startup2(nextpa);
    364 #endif
    365 
    366 	/*
    367 	 * Just use the default pager_map_size for now.  We may decide
    368 	 * to make it larger for large memory configs.
    369 	 */
    370 
    371 	machine_init_common(nextpa);
    372 
    373 	machine_parse_cmdline();
    374 }
    375 
    376 /*
    377  * Console initialization: called early on from main,
    378  * before vm init or startup.  Do enough configuration
    379  * to choose and initialize a console.
    380  */
    381 void
    382 consinit(void)
    383 {
    384 	static bool initialized = false;
    385 	const struct fdt_platform *plat = machine_platform();
    386 	const struct fdt_console *cons = fdtbus_get_console();
    387 	const int phandle = fdtbus_get_stdout_phandle();
    388 	struct fdt_attach_args faa;
    389 	u_int uart_freq = 0;
    390 
    391 	if (initialized || cons == NULL) {
    392 		return;
    393 	}
    394 
    395 	machine_init_attach_args(&faa);
    396 
    397 	if (of_getprop_uint32(phandle, "clock-frequency", &uart_freq)) {
    398 		if (plat->fp_uart_freq != NULL) {
    399 			uart_freq = plat->fp_uart_freq();
    400 		}
    401 	}
    402 
    403 	faa.faa_phandle = phandle;
    404 	cons->consinit(&faa, uart_freq);
    405 
    406 	initialized = true;
    407 
    408 #if NKSYMS || defined(DDB) || defined(MODULAR)
    409 	/*
    410 	 * Add kernel symbols now because traditionally consinit()
    411 	 * is the boot-into-debugger hook.
    412 	 */
    413 	if (machine_find_ksyms()) {
    414 		ksyms_addsyms_elf(ksym_end - ksym_start,
    415 		    (void *)ksym_start, (void *)ksym_end);
    416 	}
    417 #endif
    418 #ifdef DDB
    419 	if (boothowto & RB_KDB)
    420 		Debugger();
    421 #endif
    422 }
    423 
    424 /*
    425  * cpu_startup: allocate memory for variable-sized tables,
    426  * initialize CPU, and do autoconfiguration.
    427  */
    428 void
    429 cpu_startup(void)
    430 {
    431 
    432 	cpu_startup_common();
    433 
    434 #if defined(CONFIG_LINUX_BOOTINFO)
    435 	struct bootinfo_data *bid = bootinfo_data();
    436 	if (bid->bootinfo_mem_segments_ignored) {
    437 		printf("WARNING: ignored %zd bytes of memory in %d segments.\n",
    438 		    bid->bootinfo_mem_segments_ignored_bytes,
    439 		    bid->bootinfo_mem_segments_ignored);
    440 	}
    441 #endif
    442 }
    443 
    444 void
    445 machine_set_model(void)
    446 {
    447 	int phandle;
    448 	char buf[40];
    449 
    450 	phandle = OF_finddevice("/");
    451 	if (phandle < 0 ||
    452 	    OF_getprop(phandle, "model", buf, sizeof(buf)) < 0) {
    453 		cpu_setmodel("Unknown Homebrew");
    454 	} else {
    455 		cpu_setmodel("%s", buf);
    456 	}
    457 }
    458 
    459 /*
    460  * machine dependent system variables.
    461  */
    462 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
    463 {
    464 	sysctl_createv(clog, 0, NULL, NULL,
    465 		       CTLFLAG_PERMANENT,
    466 		       CTLTYPE_NODE, "machdep", NULL,
    467 		       NULL, 0, NULL, 0,
    468 		       CTL_MACHDEP, CTL_EOL);
    469 
    470 	sysctl_createv(clog, 0, NULL, NULL,
    471 		       CTLFLAG_PERMANENT,
    472 		       CTLTYPE_STRUCT, "console_device", NULL,
    473 		       sysctl_consdev, 0, NULL, sizeof(dev_t),
    474 		       CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
    475 }
    476 
    477 void
    478 machine_powerdown(void)
    479 {
    480 	const struct fdt_platform *plat = machine_platform();
    481 
    482 	if (plat->fp_powerdown != NULL) {
    483 		(*plat->fp_powerdown)();
    484 	} else {
    485 		machine_powerdown_default();
    486 	}
    487 }
    488 
    489 void
    490 machine_halt(void)
    491 {
    492 	const struct fdt_platform *plat = machine_platform();
    493 
    494 	if (plat->fp_halt != NULL) {
    495 		(*plat->fp_halt)();
    496 	} else {
    497 		machine_halt_default();
    498 	}
    499 }
    500 
    501 void
    502 machine_reboot(int howto, char *bootstr)
    503 {
    504 	const struct fdt_platform *plat = machine_platform();
    505 
    506 	if (plat->fp_reboot != NULL) {
    507 		(*plat->fp_reboot)(howto, bootstr);
    508 	}
    509 }
    510 
    511 /*
    512  * Level 7 interrupts are caused by e.g. the ABORT switch.
    513  *
    514  * If we have DDB, then break into DDB on ABORT.  In a production
    515  * environment, bumping the ABORT switch would be bad, so we enable
    516  * panic'ing on ABORT with the kernel option "PANICBUTTON".
    517  */
    518 int
    519 nmihand(void *arg)
    520 {
    521 
    522 	printf("NMI ignored.\n");
    523 
    524 	return 1;
    525 }
    526