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
15extern "C" {
16#include <libfdt.h>
17}
18
19#include "dtb.h"
20
21/* TODO: Code taken from ARM port just for building purposes */
22
23/* The potential interrupt controoller would be present in the dts as:
24 * compatible = "arm,gic-v3";
25 */
26const struct supported_interrupt_controllers {
27	const char*	dtb_compat;
28	const char*	kind;
29} kSupportedInterruptControllers[] = {
30	{ "arm,cortex-a9-gic", INTC_KIND_GICV1 },
31	{ "arm,cortex-a15-gic", INTC_KIND_GICV2 },
32	{ "ti,omap3-intc", INTC_KIND_OMAP3 },
33	{ "marvell,pxa-intc", INTC_KIND_PXA },
34};
35
36
37void
38arch_handle_fdt(const void* fdt, int node)
39{
40	const char* deviceType = (const char*)fdt_getprop(fdt, node,
41		"device_type", NULL);
42
43	if (deviceType != NULL) {
44		if (strcmp(deviceType, "cpu") == 0) {
45			platform_cpu_info* info = NULL;
46			arch_smp_register_cpu(&info);
47			if (info == NULL)
48				return;
49			info->id = fdt32_to_cpu(*(uint32*)fdt_getprop(fdt, node,
50				"reg", NULL));
51			dprintf("cpu\n");
52			dprintf("  id: %" B_PRIu32 "\n", info->id);
53
54		}
55	}
56
57	int compatibleLen;
58	const char* compatible = (const char*)fdt_getprop(fdt, node,
59		"compatible", &compatibleLen);
60
61	if (compatible == NULL)
62		return;
63
64	intc_info &interrupt_controller = gKernelArgs.arch_args.interrupt_controller;
65	if (interrupt_controller.kind[0] == 0) {
66		for (uint32 i = 0; i < B_COUNT_OF(kSupportedInterruptControllers); i++) {
67			if (dtb_has_fdt_string(compatible, compatibleLen,
68				kSupportedInterruptControllers[i].dtb_compat)) {
69
70				memcpy(interrupt_controller.kind, kSupportedInterruptControllers[i].kind,
71					sizeof(interrupt_controller.kind));
72
73				dtb_get_reg(fdt, node, 0, interrupt_controller.regs1);
74				dtb_get_reg(fdt, node, 1, interrupt_controller.regs2);
75			}
76		}
77	}
78}
79
80
81void
82arch_dtb_set_kernel_args(void)
83{
84	intc_info &interrupt_controller = gKernelArgs.arch_args.interrupt_controller;
85	dprintf("Chosen interrupt controller:\n");
86	if (interrupt_controller.kind[0] == 0) {
87		dprintf("kind: None!\n");
88	} else {
89		dprintf("  kind: %s\n", interrupt_controller.kind);
90		dprintf("  regs: %#" B_PRIx64 ", %#" B_PRIx64 "\n",
91			interrupt_controller.regs1.start,
92			interrupt_controller.regs1.size);
93		dprintf("        %#" B_PRIx64 ", %#" B_PRIx64 "\n",
94			interrupt_controller.regs2.start,
95			interrupt_controller.regs2.size);
96	}
97}
98