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