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 { "ti,omap3-intc", INTC_KIND_OMAP3 }, 29 { "marvell,pxa-intc", INTC_KIND_PXA }, 30 }; 31 32 33 void 34 arch_handle_fdt(const void* fdt, int node, uint32 addressCells, uint32 sizeCells) 35 { 36 const char* deviceType = (const char*)fdt_getprop(fdt, node, 37 "device_type", NULL); 38 39 if (deviceType != NULL) { 40 if (strcmp(deviceType, "cpu") == 0) { 41 platform_cpu_info* info; 42 arch_smp_register_cpu(&info); 43 if (info == NULL) 44 return; 45 info->id = fdt32_to_cpu(*(uint32*)fdt_getprop(fdt, node, 46 "reg", NULL)); 47 dprintf("cpu\n"); 48 dprintf(" id: %" B_PRIu32 "\n", info->id); 49 50 } 51 } 52 53 int compatibleLen; 54 const char* compatible = (const char*)fdt_getprop(fdt, node, 55 "compatible", &compatibleLen); 56 57 if (compatible == NULL) 58 return; 59 60 intc_info &interrupt_controller = gKernelArgs.arch_args.interrupt_controller; 61 if (interrupt_controller.kind[0] == 0) { 62 for (uint32 i = 0; i < B_COUNT_OF(kSupportedInterruptControllers); i++) { 63 if (dtb_has_fdt_string(compatible, compatibleLen, 64 kSupportedInterruptControllers[i].dtb_compat)) { 65 66 memcpy(interrupt_controller.kind, kSupportedInterruptControllers[i].kind, 67 sizeof(interrupt_controller.kind)); 68 69 dtb_get_reg(fdt, node, addressCells, sizeCells, 0, 70 interrupt_controller.regs1); 71 dtb_get_reg(fdt, node, addressCells, sizeCells, 1, 72 interrupt_controller.regs2); 73 } 74 } 75 } 76 } 77 78 79 void 80 arch_dtb_set_kernel_args(void) 81 { 82 intc_info &interrupt_controller = gKernelArgs.arch_args.interrupt_controller; 83 dprintf("Chosen interrupt controller:\n"); 84 if (interrupt_controller.kind[0] == 0) { 85 dprintf("kind: None!\n"); 86 } else { 87 dprintf(" kind: %s\n", interrupt_controller.kind); 88 dprintf(" regs: %#" B_PRIx64 ", %#" B_PRIx64 "\n", 89 interrupt_controller.regs1.start, 90 interrupt_controller.regs1.size); 91 dprintf(" %#" B_PRIx64 ", %#" B_PRIx64 "\n", 92 interrupt_controller.regs2.start, 93 interrupt_controller.regs2.size); 94 } 95 } 96