xref: /haiku/src/system/boot/platform/efi/arch/arm/arch_dtb.cpp (revision c237c4ce593ee823d9867fd997e51e4c447f5623)
1 /*
2  * Copyright 2019-2021 Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *   Alexander von Gluck IV <kallisti5@unixzen.com>
7  */
8 
9 #include <arch_cpu_defs.h>
10 #include <arch_dtb.h>
11 #include <arch_smp.h>
12 #include <boot/platform.h>
13 #include <boot/stage2.h>
14 
15 extern "C" {
16 #include <libfdt.h>
17 }
18 
19 #include "dtb.h"
20 
21 
22 const struct supported_interrupt_controllers {
23 	const char*	dtb_compat;
24 	const char*	kind;
25 } kSupportedInterruptControllers[] = {
26 	{ "arm,cortex-a9-gic", INTC_KIND_GICV1 },
27 	{ "arm,cortex-a15-gic", INTC_KIND_GICV2 },
28 	{ "arm,gic-400", INTC_KIND_GICV2 },
29 	{ "ti,omap3-intc", INTC_KIND_OMAP3 },
30 	{ "marvell,pxa-intc", INTC_KIND_PXA },
31 	{ "allwinner,sun4i-a10-ic", INTC_KIND_SUN4I },
32 };
33 
34 
35 const struct supported_timers {
36 	const char* dtb_compat;
37 	const char* kind;
38 } kSupportedTimers[] = {
39 	{ "arm,armv7-timer",	TIMER_KIND_ARMV7 },
40 	{ "ti,omap3430-timer",	TIMER_KIND_OMAP3 },
41 	{ "marvell,pxa-timers",	TIMER_KIND_PXA },
42 };
43 
44 
45 void
46 arch_handle_fdt(const void* fdt, int node)
47 {
48 	const char* deviceType = (const char*)fdt_getprop(fdt, node,
49 		"device_type", NULL);
50 
51 	if (deviceType != NULL) {
52 		if (strcmp(deviceType, "cpu") == 0) {
53 			platform_cpu_info* info;
54 			arch_smp_register_cpu(&info);
55 			if (info == NULL)
56 				return;
57 			info->id = fdt32_to_cpu(*(uint32*)fdt_getprop(fdt, node,
58 				"reg", NULL));
59 			dprintf("cpu\n");
60 			dprintf("  id: %" B_PRIu32 "\n", info->id);
61 
62 		}
63 	}
64 
65 	int compatibleLen;
66 	const char* compatible = (const char*)fdt_getprop(fdt, node,
67 		"compatible", &compatibleLen);
68 
69 	if (compatible == NULL)
70 		return;
71 
72 	intc_info &interrupt_controller = gKernelArgs.arch_args.interrupt_controller;
73 	if (interrupt_controller.kind[0] == 0) {
74 		for (uint32 i = 0; i < B_COUNT_OF(kSupportedInterruptControllers); i++) {
75 			if (dtb_has_fdt_string(compatible, compatibleLen,
76 				kSupportedInterruptControllers[i].dtb_compat)) {
77 
78 				memcpy(interrupt_controller.kind, kSupportedInterruptControllers[i].kind,
79 					sizeof(interrupt_controller.kind));
80 
81 				dtb_get_reg(fdt, node, 0, interrupt_controller.regs1);
82 				dtb_get_reg(fdt, node, 1, interrupt_controller.regs2);
83 			}
84 		}
85 	}
86 
87 	boot_timer_info &timer = gKernelArgs.arch_args.timer;
88 	if (timer.kind[0] == 0) {
89 		for (uint32 i = 0; i < B_COUNT_OF(kSupportedTimers); i++) {
90 			if (dtb_has_fdt_string(compatible, compatibleLen,
91 				kSupportedTimers[i].dtb_compat)) {
92 
93 				memcpy(timer.kind, kSupportedTimers[i].kind,
94 					sizeof(timer.kind));
95 
96 				dtb_get_reg(fdt, node, 0, timer.regs);
97 				timer.interrupt = dtb_get_interrupt(fdt, node);
98 			}
99 		}
100 	}
101 }
102 
103 
104 void
105 arch_dtb_set_kernel_args(void)
106 {
107 	intc_info &interrupt_controller = gKernelArgs.arch_args.interrupt_controller;
108 	dprintf("Chosen interrupt controller:\n");
109 	if (interrupt_controller.kind[0] == 0) {
110 		dprintf("kind: None!\n");
111 	} else {
112 		dprintf("  kind: %s\n", interrupt_controller.kind);
113 		dprintf("  regs: %#" B_PRIx64 ", %#" B_PRIx64 "\n",
114 			interrupt_controller.regs1.start,
115 			interrupt_controller.regs1.size);
116 		dprintf("        %#" B_PRIx64 ", %#" B_PRIx64 "\n",
117 			interrupt_controller.regs2.start,
118 			interrupt_controller.regs2.size);
119 	}
120 
121 	boot_timer_info &timer = gKernelArgs.arch_args.timer;
122 	dprintf("Chosen timer:\n");
123 	if (timer.kind[0] == 0) {
124 		dprintf("kind: None!\n");
125 	} else {
126 		dprintf("  kind: %s\n", timer.kind);
127 		dprintf("  regs: %#" B_PRIx64 ", %#" B_PRIx64 "\n",
128 			timer.regs.start,
129 			timer.regs.size);
130 		dprintf("  irq: %" B_PRIu32 "\n", timer.interrupt);
131 	}
132 }
133