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 /* 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 */ 26 const 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 37 void 38 arch_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 81 void 82 arch_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