xref: /haiku/src/system/boot/platform/riscv/fdt.cpp (revision 4b5c7fe7e1f43487370b747e8176478dcd09e3b5)
1a182bd6eSX512 /*
2a182bd6eSX512  * Copyright 2021, Haiku, Inc.
3a182bd6eSX512  * Distributed under the terms of the MIT License.
4a182bd6eSX512  */
5a182bd6eSX512 
6a182bd6eSX512 
7a182bd6eSX512 #include "fdt.h"
8a182bd6eSX512 #include <SupportDefs.h>
9a182bd6eSX512 #include <ByteOrder.h>
10a182bd6eSX512 #include <KernelExport.h>
11a182bd6eSX512 #include <boot/stage2.h>
12a182bd6eSX512 
13a182bd6eSX512 extern "C" {
14a182bd6eSX512 #include <libfdt.h>
15a182bd6eSX512 }
16a182bd6eSX512 
17a182bd6eSX512 #include "mmu.h"
18a182bd6eSX512 #include "graphics.h"
19a182bd6eSX512 #include "virtio.h"
20a182bd6eSX512 
21a182bd6eSX512 
22a182bd6eSX512 void* gFdt = NULL;
23a182bd6eSX512 
24a182bd6eSX512 
25a182bd6eSX512 static void
26a182bd6eSX512 HandleFdt(const void* fdt, int node, uint32_t addressCells, uint32_t sizeCells,
27a182bd6eSX512 	uint32_t interruptCells /* from parent node */)
28a182bd6eSX512 {
29a182bd6eSX512 	// TODO: handle different field sizes
30a182bd6eSX512 
31a182bd6eSX512 	const char* device_type = (const char*)fdt_getprop(fdt, node,
32a182bd6eSX512 		"device_type", NULL);
33a182bd6eSX512 	if (device_type != NULL && strcmp(device_type, "memory") == 0) {
34a182bd6eSX512 		gMemBase = (uint8*)fdt64_to_cpu(*((uint64_t*)fdt_getprop(fdt, node,
35a182bd6eSX512 			"reg", NULL) + 0));
36a182bd6eSX512 		gTotalMem = fdt64_to_cpu(*((uint64_t*)fdt_getprop(fdt, node,
37a182bd6eSX512 			"reg", NULL) + 1));
38a182bd6eSX512 		return;
39a182bd6eSX512 	}
40a182bd6eSX512 	const char* compatible = (const char*)fdt_getprop(fdt, node,
41a182bd6eSX512 		"compatible", NULL);
42a182bd6eSX512 	if (compatible == NULL) return;
43a182bd6eSX512 	if (strcmp(compatible, "virtio,mmio") == 0) {
44a182bd6eSX512 		virtio_register(
45a182bd6eSX512 			fdt64_to_cpu(*((uint64_t*)fdt_getprop(fdt, node, "reg", NULL) + 0)),
46a182bd6eSX512 			fdt64_to_cpu(*((uint64_t*)fdt_getprop(fdt, node, "reg", NULL) + 1)),
47a182bd6eSX512 			fdt32_to_cpu(*((uint32_t*)fdt_getprop(fdt, node,
48a182bd6eSX512 				"interrupts-extended", NULL) + 1))
49a182bd6eSX512 		);
50a182bd6eSX512 	} else if (strcmp(compatible, "simple-framebuffer") == 0) {
51a182bd6eSX512 		gFramebuf.colors = (uint32_t*)fdt64_to_cpu(
52a182bd6eSX512 			*(uint64_t*)fdt_getprop(fdt, node, "reg", NULL));
53a182bd6eSX512 		gFramebuf.stride = fdt32_to_cpu(
54a182bd6eSX512 			*(uint32_t*)fdt_getprop(fdt, node, "stride", NULL)) / 4;
55a182bd6eSX512 		gFramebuf.width = fdt32_to_cpu(
56a182bd6eSX512 			*(uint32_t*)fdt_getprop(fdt, node, "width", NULL));
57a182bd6eSX512 		gFramebuf.height = fdt32_to_cpu(
58a182bd6eSX512 			*(uint32_t*)fdt_getprop(fdt, node, "height", NULL));
59a182bd6eSX512 	}
60a182bd6eSX512 }
61a182bd6eSX512 
62a182bd6eSX512 
63a182bd6eSX512 void
64a182bd6eSX512 fdt_init(void* fdt)
65a182bd6eSX512 {
66a182bd6eSX512 	dprintf("FDT: %p\n", fdt);
67a182bd6eSX512 	gFdt = fdt;
68a182bd6eSX512 
69a182bd6eSX512 	int res = fdt_check_header(gFdt);
70a182bd6eSX512 	if (res != 0) {
71a182bd6eSX512 		panic("Invalid FDT: %s\n", fdt_strerror(res));
72a182bd6eSX512 	}
73a182bd6eSX512 
74a182bd6eSX512 	dprintf("FDT valid, size: %" B_PRIu32 "\n", fdt_totalsize(gFdt));
75a182bd6eSX512 
76a182bd6eSX512 	int node = -1;
77a182bd6eSX512 	int depth = 0;
78a182bd6eSX512 	while ((node = fdt_next_node(gFdt, node, &depth)) >= 0) {
79a182bd6eSX512 		HandleFdt(gFdt, node, 2, 2, 2);
80a182bd6eSX512 	}
81a182bd6eSX512 }
82a182bd6eSX512 
83a182bd6eSX512 
84a182bd6eSX512 void
85a182bd6eSX512 fdt_set_kernel_args()
86a182bd6eSX512 {
87c9d6d52bSAlexander von Gluck IV 	uint32_t fdtSize = fdt_totalsize(gFdt);
88c9d6d52bSAlexander von Gluck IV 
89*4b5c7fe7SAlexander von Gluck IV 	// libfdt requires 8-byte alignment
90*4b5c7fe7SAlexander von Gluck IV 	gKernelArgs.arch_args.fdt = (void*)(addr_t)kernel_args_malloc(fdtSize, 8);
91c9d6d52bSAlexander von Gluck IV 
92a182bd6eSX512 	if (gKernelArgs.arch_args.fdt != NULL) {
93c9d6d52bSAlexander von Gluck IV 		memcpy(gKernelArgs.arch_args.fdt, gFdt, fdtSize);
94a182bd6eSX512 	} else
95a182bd6eSX512 		panic("unable to malloc for FDT!\n");
96c9d6d52bSAlexander von Gluck IV 
97c9d6d52bSAlexander von Gluck IV 	dprintf("FDT getting passed to kernel @ %p\n", (void*)gKernelArgs.arch_args.fdt.Pointer());
98a182bd6eSX512 }
99