1 /* 2 * Copyright 2019-2022 Haiku, Inc. All rights reserved. 3 * Released under the terms of the MIT License. 4 */ 5 6 #include "string.h" 7 8 #include <boot/platform.h> 9 #include <boot/stage2.h> 10 #include <arch_acpi.h> 11 12 #include "serial.h" 13 #include "acpi.h" 14 15 #include <arch/arm/arch_uart_pl011.h> 16 #include <arch/generic/debug_uart_8250.h> 17 18 19 static void arch_acpi_get_uart_pl011(const uart_info &uart) 20 { 21 static char sUART[sizeof(ArchUARTPL011)]; 22 gUART = new(sUART) ArchUARTPL011(uart.regs.start, 23 uart.clock != 0 ? uart.clock : 0x16e3600); 24 } 25 26 27 void 28 arch_handle_acpi() 29 { 30 acpi_spcr *spcr = (acpi_spcr*)acpi_find_table(ACPI_SPCR_SIGNATURE); 31 if (spcr != NULL) { 32 uart_info &uart = gKernelArgs.arch_args.uart; 33 34 if (spcr->interface_type == ACPI_SPCR_INTERFACE_TYPE_PL011) { 35 strcpy(uart.kind, UART_KIND_PL011); 36 } else if (spcr->interface_type == ACPI_SPCR_INTERFACE_TYPE_16550) { 37 strcpy(uart.kind, UART_KIND_8250); 38 } 39 40 uart.regs.start = spcr->base_address.address; 41 uart.regs.size = B_PAGE_SIZE; 42 uart.irq = spcr->gisv; 43 uart.clock = spcr->clock; 44 45 if (spcr->interface_type == ACPI_SPCR_INTERFACE_TYPE_PL011) { 46 arch_acpi_get_uart_pl011(uart); 47 } 48 49 dprintf("discovered uart from acpi: base=%lx, irq=%u, clock=%lu\n", 50 uart.regs.start, uart.irq, uart.clock); 51 } 52 53 acpi_madt *madt = (acpi_madt*)acpi_find_table(ACPI_MADT_SIGNATURE); 54 if (madt != NULL) { 55 uint64 gicc_base = 0; 56 uint64 gicd_base = 0; 57 uint8 version = 0; 58 59 acpi_apic *desc = (acpi_apic*)(madt + 1); 60 while (desc != (acpi_apic*)((char*)madt + madt->header.length)) { 61 if (desc->type == ACPI_MADT_GIC_INTERFACE) { 62 acpi_gic_interface *acpi_gicc = (acpi_gic_interface*)desc; 63 if (acpi_gicc->cpu_interface_num == 0) 64 gicc_base = acpi_gicc->base_address; 65 } else if (desc->type == ACPI_MADT_GIC_DISTRIBUTOR) { 66 acpi_gic_distributor *acpi_gicd = (acpi_gic_distributor*)desc; 67 gicd_base = acpi_gicd->base_address; 68 version = acpi_gicd->gic_version; 69 } 70 desc = (acpi_apic*)((char*)desc + desc->length); 71 } 72 73 if (version == 2 && gicc_base != 0 && gicd_base != 0) { 74 intc_info &intc = gKernelArgs.arch_args.interrupt_controller; 75 strcpy(intc.kind, INTC_KIND_GICV2); 76 intc.regs1.start = gicd_base; 77 intc.regs2.start = gicc_base; 78 79 dprintf("discovered gic from acpi: version=%d, gicd=%lx, gicc=%lx\n", 80 version, gicd_base, gicc_base); 81 } 82 } 83 } 84