xref: /haiku/src/system/boot/platform/efi/arch/arm64/arch_acpi.cpp (revision 97f11716bfaa0f385eb0e28a52bf56a5023b9e99)
117f0f4b6Smilek7 /*
217f0f4b6Smilek7  * Copyright 2019-2022 Haiku, Inc. All rights reserved.
317f0f4b6Smilek7  * Released under the terms of the MIT License.
417f0f4b6Smilek7  */
517f0f4b6Smilek7 
617f0f4b6Smilek7 #include "string.h"
717f0f4b6Smilek7 
817f0f4b6Smilek7 #include <boot/platform.h>
917f0f4b6Smilek7 #include <boot/stage2.h>
1017f0f4b6Smilek7 #include <arch_acpi.h>
1117f0f4b6Smilek7 
1217f0f4b6Smilek7 #include "serial.h"
1317f0f4b6Smilek7 #include "acpi.h"
1417f0f4b6Smilek7 
1517f0f4b6Smilek7 #include <arch/arm/arch_uart_pl011.h>
1617f0f4b6Smilek7 #include <arch/generic/debug_uart_8250.h>
1717f0f4b6Smilek7 
1817f0f4b6Smilek7 
arch_acpi_get_uart_pl011(const uart_info & uart)1917f0f4b6Smilek7 static void arch_acpi_get_uart_pl011(const uart_info &uart)
2017f0f4b6Smilek7 {
2117f0f4b6Smilek7 	static char sUART[sizeof(ArchUARTPL011)];
2217f0f4b6Smilek7 	gUART = new(sUART) ArchUARTPL011(uart.regs.start,
2317f0f4b6Smilek7 		uart.clock != 0 ? uart.clock : 0x16e3600);
2417f0f4b6Smilek7 }
2517f0f4b6Smilek7 
2617f0f4b6Smilek7 
2717f0f4b6Smilek7 void
arch_handle_acpi()2817f0f4b6Smilek7 arch_handle_acpi()
2917f0f4b6Smilek7 {
3017f0f4b6Smilek7 	acpi_spcr *spcr = (acpi_spcr*)acpi_find_table(ACPI_SPCR_SIGNATURE);
3117f0f4b6Smilek7 	if (spcr != NULL) {
3217f0f4b6Smilek7 		uart_info &uart = gKernelArgs.arch_args.uart;
3317f0f4b6Smilek7 
3417f0f4b6Smilek7 		if (spcr->interface_type == ACPI_SPCR_INTERFACE_TYPE_PL011) {
3517f0f4b6Smilek7 			strcpy(uart.kind, UART_KIND_PL011);
3617f0f4b6Smilek7 		} else if (spcr->interface_type == ACPI_SPCR_INTERFACE_TYPE_16550) {
3717f0f4b6Smilek7 			strcpy(uart.kind, UART_KIND_8250);
3817f0f4b6Smilek7 		}
3917f0f4b6Smilek7 
4017f0f4b6Smilek7 		uart.regs.start = spcr->base_address.address;
4117f0f4b6Smilek7 		uart.regs.size = B_PAGE_SIZE;
4217f0f4b6Smilek7 		uart.irq = spcr->gisv;
4317f0f4b6Smilek7 		uart.clock = spcr->clock;
4417f0f4b6Smilek7 
4517f0f4b6Smilek7 		if (spcr->interface_type == ACPI_SPCR_INTERFACE_TYPE_PL011) {
4617f0f4b6Smilek7 			arch_acpi_get_uart_pl011(uart);
4717f0f4b6Smilek7 		}
4817f0f4b6Smilek7 
4917f0f4b6Smilek7 		dprintf("discovered uart from acpi: base=%lx, irq=%u, clock=%lu\n",
5017f0f4b6Smilek7 			uart.regs.start, uart.irq, uart.clock);
5117f0f4b6Smilek7 	}
52*81e0d2d4Smilek7 
53*81e0d2d4Smilek7 	acpi_madt *madt = (acpi_madt*)acpi_find_table(ACPI_MADT_SIGNATURE);
54*81e0d2d4Smilek7 	if (madt != NULL) {
55*81e0d2d4Smilek7 		uint64 gicc_base = 0;
56*81e0d2d4Smilek7 		uint64 gicd_base = 0;
57*81e0d2d4Smilek7 		uint8 version = 0;
58*81e0d2d4Smilek7 
59*81e0d2d4Smilek7 		acpi_apic *desc = (acpi_apic*)(madt + 1);
60*81e0d2d4Smilek7 		while (desc != (acpi_apic*)((char*)madt + madt->header.length)) {
61*81e0d2d4Smilek7 			if (desc->type == ACPI_MADT_GIC_INTERFACE) {
62*81e0d2d4Smilek7 				acpi_gic_interface *acpi_gicc = (acpi_gic_interface*)desc;
63*81e0d2d4Smilek7 				if (acpi_gicc->cpu_interface_num == 0)
64*81e0d2d4Smilek7 					gicc_base = acpi_gicc->base_address;
65*81e0d2d4Smilek7 			} else if (desc->type == ACPI_MADT_GIC_DISTRIBUTOR) {
66*81e0d2d4Smilek7 				acpi_gic_distributor *acpi_gicd = (acpi_gic_distributor*)desc;
67*81e0d2d4Smilek7 				gicd_base = acpi_gicd->base_address;
68*81e0d2d4Smilek7 				version = acpi_gicd->gic_version;
69*81e0d2d4Smilek7 			}
70*81e0d2d4Smilek7 			desc = (acpi_apic*)((char*)desc + desc->length);
71*81e0d2d4Smilek7 		}
72*81e0d2d4Smilek7 
73*81e0d2d4Smilek7 		if (version == 2 && gicc_base != 0 && gicd_base != 0) {
74*81e0d2d4Smilek7 			intc_info &intc = gKernelArgs.arch_args.interrupt_controller;
75*81e0d2d4Smilek7 			strcpy(intc.kind, INTC_KIND_GICV2);
76*81e0d2d4Smilek7 			intc.regs1.start = gicd_base;
77*81e0d2d4Smilek7 			intc.regs2.start = gicc_base;
78*81e0d2d4Smilek7 
79*81e0d2d4Smilek7 			dprintf("discovered gic from acpi: version=%d, gicd=%lx, gicc=%lx\n",
80*81e0d2d4Smilek7 				version, gicd_base, gicc_base);
81*81e0d2d4Smilek7 		}
82*81e0d2d4Smilek7 	}
8317f0f4b6Smilek7 }
84