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
19static 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
27void
28arch_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