Index: sys/arm/arm/generic_timer.c =================================================================== --- sys/arm/arm/generic_timer.c +++ sys/arm/arm/generic_timer.c @@ -34,6 +34,9 @@ * Cortex-A7, Cortex-A15, ARMv8 and later Generic Timer */ +#include "opt_acpi.h" +#include "opt_platform.h" + #include __FBSDID("$FreeBSD$"); @@ -51,12 +54,17 @@ #include #include +#ifdef FDT #include #include #include #include +#endif -#include +#ifdef DEV_ACPI +#include +#include +#endif #define GT_CTRL_ENABLE (1 << 0) #define GT_CTRL_INT_MASK (1 << 1) @@ -247,8 +255,9 @@ return (FILTER_HANDLED); } +#ifdef FDT static int -arm_tmr_probe(device_t dev) +arm_tmr_fdt_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) @@ -264,14 +273,68 @@ return (ENXIO); } +#endif + +#ifdef DEV_ACPI +static void +arm_tmr_acpi_identify(driver_t *driver, device_t parent) +{ + ACPI_TABLE_GTDT *gtdt; + vm_paddr_t physaddr; + device_t dev; + + physaddr = acpi_find_table(ACPI_SIG_GTDT); + if (physaddr == 0) + return; + + gtdt = acpi_map_table(physaddr, ACPI_SIG_GTDT); + if (gtdt == NULL) { + device_printf(parent, "gic: Unable to map the GTDT\n"); + return; + } + + dev = BUS_ADD_CHILD(parent, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE, + "generic_timer", -1); + if (dev == NULL) { + device_printf(parent, "add gic child failed\n"); + goto out; + } + + BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 0, + gtdt->SecureEl1Interrupt, 1); + BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 1, + gtdt->NonSecureEl1Interrupt, 1); + BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 2, + gtdt->VirtualTimerInterrupt, 1); + +out: + acpi_unmap_table(gtdt); +} + +static int +arm_tmr_acpi_probe(device_t dev) +{ + + if (device_get_unit(dev) != 0) + return (ENXIO); + + if (acpi_get_type(dev) != ACPI_TYPE_NOT_FOUND) + return (ENXIO); + + device_set_desc(dev, "ARM Generic Timer"); + return (BUS_PROBE_DEFAULT); +} +#endif static int arm_tmr_attach(device_t dev) { struct arm_tmr_softc *sc; +#ifdef FDT phandle_t node; pcell_t clock; +#endif int error; int i; @@ -279,12 +342,17 @@ if (arm_tmr_sc) return (ENXIO); +#ifdef FDT /* Get the base clock frequency */ node = ofw_bus_get_node(dev); - error = OF_getprop(node, "clock-frequency", &clock, sizeof(clock)); - if (error > 0) { - sc->clkfreq = fdt32_to_cpu(clock); + if (node > 0) { + error = OF_getprop(node, "clock-frequency", &clock, + sizeof(clock)); + if (error > 0) { + sc->clkfreq = fdt32_to_cpu(clock); + } } +#endif if (sc->clkfreq == 0) { /* Try to get clock frequency from timer */ @@ -339,24 +407,46 @@ return (0); } -static device_method_t arm_tmr_methods[] = { - DEVMETHOD(device_probe, arm_tmr_probe), +#ifdef FDT +static device_method_t arm_tmr_fdt_methods[] = { + DEVMETHOD(device_probe, arm_tmr_fdt_probe), DEVMETHOD(device_attach, arm_tmr_attach), { 0, 0 } }; -static driver_t arm_tmr_driver = { +static driver_t arm_tmr_fdt_driver = { "generic_timer", - arm_tmr_methods, + arm_tmr_fdt_methods, sizeof(struct arm_tmr_softc), }; -static devclass_t arm_tmr_devclass; +static devclass_t arm_tmr_fdt_devclass; + +EARLY_DRIVER_MODULE(timer, simplebus, arm_tmr_fdt_driver, arm_tmr_fdt_devclass, + 0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); +EARLY_DRIVER_MODULE(timer, ofwbus, arm_tmr_fdt_driver, arm_tmr_fdt_devclass, + 0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); +#endif -EARLY_DRIVER_MODULE(timer, simplebus, arm_tmr_driver, arm_tmr_devclass, 0, 0, - BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); -EARLY_DRIVER_MODULE(timer, ofwbus, arm_tmr_driver, arm_tmr_devclass, 0, 0, - BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); +#ifdef DEV_ACPI +static device_method_t arm_tmr_acpi_methods[] = { + DEVMETHOD(device_identify, arm_tmr_acpi_identify), + DEVMETHOD(device_probe, arm_tmr_acpi_probe), + DEVMETHOD(device_attach, arm_tmr_attach), + { 0, 0 } +}; + +static driver_t arm_tmr_acpi_driver = { + "generic_timer", + arm_tmr_acpi_methods, + sizeof(struct arm_tmr_softc), +}; + +static devclass_t arm_tmr_acpi_devclass; + +EARLY_DRIVER_MODULE(timer, acpi, arm_tmr_acpi_driver, arm_tmr_acpi_devclass, + 0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); +#endif void DELAY(int usec) Index: sys/arm64/acpica/OsdEnvironment.c =================================================================== --- /dev/null +++ sys/arm64/acpica/OsdEnvironment.c @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 2000,2001 Michael Smith + * Copyright (c) 2000 BSDi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: head/sys/x86/acpica/OsdEnvironment.c 281475 2015-04-12 22:40:27Z jkim $"); + +#include +#include +#include + +#include +#include + +static u_long acpi_root_phys; + +SYSCTL_ULONG(_machdep, OID_AUTO, acpi_root, CTLFLAG_RD, &acpi_root_phys, 0, + "The physical address of the RSDP"); + +ACPI_STATUS +AcpiOsInitialize(void) +{ + + return (AE_OK); +} + +ACPI_STATUS +AcpiOsTerminate(void) +{ + + return (AE_OK); +} + +static u_long +acpi_get_root_from_loader(void) +{ + long acpi_root; + + if (resource_long_value("acpi", 0, "rsdp", &acpi_root) == 0) + return (acpi_root); + + return (0); +} + +ACPI_PHYSICAL_ADDRESS +AcpiOsGetRootPointer(void) +{ + + if (acpi_root_phys == 0) + acpi_root_phys = acpi_get_root_from_loader(); + + return (acpi_root_phys); +} Index: sys/arm64/acpica/acpi_machdep.c =================================================================== --- /dev/null +++ sys/arm64/acpica/acpi_machdep.c @@ -0,0 +1,217 @@ +/*- + * Copyright (c) 2001 Mitsuru IWASAKI + * Copyright (c) 2015 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Andrew Turner under + * sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +int +acpi_machdep_init(device_t dev) +{ + + return (0); +} + +int +acpi_machdep_quirks(int *quirks) +{ + + return (0); +} + +static void * +map_table(vm_paddr_t pa, int offset, const char *sig) +{ + ACPI_TABLE_HEADER *header; + vm_offset_t length; + void *table; + + header = pmap_mapbios(pa, sizeof(ACPI_TABLE_HEADER)); + if (strncmp(header->Signature, sig, ACPI_NAME_SIZE) != 0) { + pmap_unmapbios((vm_offset_t)header, sizeof(ACPI_TABLE_HEADER)); + return (NULL); + } + length = header->Length; + pmap_unmapbios((vm_offset_t)header, sizeof(ACPI_TABLE_HEADER)); + + table = pmap_mapbios(pa, length); + if (ACPI_FAILURE(AcpiTbChecksum(table, length))) { + if (bootverbose) + printf("ACPI: Failed checksum for table %s\n", sig); +#if (ACPI_CHECKSUM_ABORT) + pmap_unmapbios(table, length); + return (NULL); +#endif + } + return (table); +} + +/* + * See if a given ACPI table is the requested table. Returns the + * length of the able if it matches or zero on failure. + */ +static int +probe_table(vm_paddr_t address, const char *sig) +{ + ACPI_TABLE_HEADER *table; + + table = pmap_mapbios(address, sizeof(ACPI_TABLE_HEADER)); + if (table == NULL) { + if (bootverbose) + printf("ACPI: Failed to map table at 0x%jx\n", + (uintmax_t)address); + return (0); + } + if (bootverbose) + printf("Table '%.4s' at 0x%jx\n", table->Signature, + (uintmax_t)address); + + if (strncmp(table->Signature, sig, ACPI_NAME_SIZE) != 0) { + pmap_unmapbios((vm_offset_t)table, sizeof(ACPI_TABLE_HEADER)); + return (0); + } + pmap_unmapbios((vm_offset_t)table, sizeof(ACPI_TABLE_HEADER)); + return (1); +} + +/* Unmap a table previously mapped via acpi_map_table(). */ +void +acpi_unmap_table(void *table) +{ + ACPI_TABLE_HEADER *header; + + header = (ACPI_TABLE_HEADER *)table; + pmap_unmapbios((vm_offset_t)table, header->Length); +} + +/* + * Try to map a table at a given physical address previously returned + * by acpi_find_table(). + */ +void * +acpi_map_table(vm_paddr_t pa, const char *sig) +{ + + return (map_table(pa, 0, sig)); +} + +/* + * Return the physical address of the requested table or zero if one + * is not found. + */ +vm_paddr_t +acpi_find_table(const char *sig) +{ + ACPI_PHYSICAL_ADDRESS rsdp_ptr; + ACPI_TABLE_RSDP *rsdp; + ACPI_TABLE_XSDT *xsdt; + ACPI_TABLE_HEADER *table; + vm_paddr_t addr; + int i, count; + + if (resource_disabled("acpi", 0)) + return (0); + + /* + * Map in the RSDP. Since ACPI uses AcpiOsMapMemory() which in turn + * calls pmap_mapbios() to find the RSDP, we assume that we can use + * pmap_mapbios() to map the RSDP. + */ + if ((rsdp_ptr = AcpiOsGetRootPointer()) == 0) + return (0); + rsdp = pmap_mapbios(rsdp_ptr, sizeof(ACPI_TABLE_RSDP)); + if (rsdp == NULL) { + if (bootverbose) + printf("ACPI: Failed to map RSDP\n"); + return (0); + } + + addr = 0; + if (rsdp->Revision >= 2 && rsdp->XsdtPhysicalAddress != 0) { + /* + * AcpiOsGetRootPointer only verifies the checksum for + * the version 1.0 portion of the RSDP. Version 2.0 has + * an additional checksum that we verify first. + */ + if (AcpiTbChecksum((UINT8 *)rsdp, ACPI_RSDP_XCHECKSUM_LENGTH)) { + if (bootverbose) + printf("ACPI: RSDP failed extended checksum\n"); + return (0); + } + xsdt = map_table(rsdp->XsdtPhysicalAddress, 2, ACPI_SIG_XSDT); + if (xsdt == NULL) { + if (bootverbose) + printf("ACPI: Failed to map XSDT\n"); + pmap_unmapbios((vm_offset_t)rsdp, + sizeof(ACPI_TABLE_RSDP)); + return (0); + } + count = (xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) / + sizeof(UINT64); + for (i = 0; i < count; i++) + if (probe_table(xsdt->TableOffsetEntry[i], sig)) { + addr = xsdt->TableOffsetEntry[i]; + break; + } + acpi_unmap_table(xsdt); + } + pmap_unmapbios((vm_offset_t)rsdp, sizeof(ACPI_TABLE_RSDP)); + + if (addr == 0) { + if (bootverbose) + printf("ACPI: No %s table found\n", sig); + return (0); + } + if (bootverbose) + printf("%s: Found table at 0x%jx\n", sig, (uintmax_t)addr); + + /* + * Verify that we can map the full table and that its checksum is + * correct, etc. + */ + table = map_table(addr, 0, sig); + if (table == NULL) + return (0); + acpi_unmap_table(table); + + return (addr); +} Index: sys/arm64/acpica/acpi_wakeup.c =================================================================== --- /dev/null +++ sys/arm64/acpica/acpi_wakeup.c @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 2015 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Andrew Turner under + * sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include + +#include + +/* + * ARM64TODO: Implement this. + */ +int +acpi_sleep_machdep(struct acpi_softc *sc, int state) +{ + + return (-1); +} + +int +acpi_wakeup_machdep(struct acpi_softc *sc, int state, int sleep_result, + int intr_enabled) +{ + + /* ARM64TODO: We will need this with acpi_sleep_machdep */ + KASSERT(sleep_result == -1, + ("acpi_wakeup_machdep: Invalid sleep result")); + + return (sleep_result); +} Index: sys/arm64/arm64/gic.h =================================================================== --- /dev/null +++ sys/arm64/arm64/gic.h @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2011 The FreeBSD Foundation + * Copyright (c) 2014 Andrew Turner + * All rights reserved. + * + * Developed by Damjan Marion + * + * Based on OMAP4 GIC code by Ben Gray + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _ARM64_GIC_H_ +#define _ARM64_GIC_H_ + +DECLARE_CLASS(arm_gic_driver); + +struct arm_gic_softc { + device_t gic_dev; + struct resource * gic_res[3]; + bus_space_tag_t gic_c_bst; + bus_space_tag_t gic_d_bst; + bus_space_handle_t gic_c_bsh; + bus_space_handle_t gic_d_bsh; + uint8_t ver; + struct mtx mutex; + uint32_t nirqs; +}; + +#endif Index: sys/arm64/arm64/gic.c =================================================================== --- sys/arm64/arm64/gic.c +++ sys/arm64/arm64/gic.c @@ -51,11 +51,7 @@ #include #include -#include -#include -#include -#include - +#include #include "pic_if.h" @@ -102,18 +98,6 @@ #define GICD_ICFGR_TRIG_EDGE (1 << 1) #define GICD_ICFGR_TRIG_MASK 0x2 -struct arm_gic_softc { - device_t gic_dev; - struct resource * gic_res[3]; - bus_space_tag_t gic_c_bst; - bus_space_tag_t gic_d_bst; - bus_space_handle_t gic_c_bsh; - bus_space_handle_t gic_d_bsh; - uint8_t ver; - struct mtx mutex; - uint32_t nirqs; -}; - static struct resource_spec arm_gic_spec[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Distributor registers */ { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* CPU Interrupt Intf. registers */ @@ -136,31 +120,6 @@ static pic_mask_t gic_mask_irq; static pic_unmask_t gic_unmask_irq; -static struct ofw_compat_data compat_data[] = { - {"arm,gic", true}, /* Non-standard, used in FreeBSD dts. */ - {"arm,gic-400", true}, - {"arm,cortex-a15-gic", true}, - {"arm,cortex-a9-gic", true}, - {"arm,cortex-a7-gic", true}, - {"arm,arm11mp-gic", true}, - {"brcm,brahma-b15-gic", true}, - {NULL, false} -}; - -static int -arm_gic_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) - return (ENXIO); - - device_set_desc(dev, "ARM Generic Interrupt Controller"); - return (BUS_PROBE_DEFAULT); -} - #ifdef SMP static void gic_init_secondary(device_t dev) @@ -367,7 +326,6 @@ static device_method_t arm_gic_methods[] = { /* Device interface */ - DEVMETHOD(device_probe, arm_gic_probe), DEVMETHOD(device_attach, arm_gic_attach), /* pic_if */ @@ -384,15 +342,5 @@ { 0, 0 } }; -static driver_t arm_gic_driver = { - "gic", - arm_gic_methods, - sizeof(struct arm_gic_softc), -}; - -static devclass_t arm_gic_devclass; - -EARLY_DRIVER_MODULE(gic, simplebus, arm_gic_driver, arm_gic_devclass, 0, 0, - BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); -EARLY_DRIVER_MODULE(gic, ofwbus, arm_gic_driver, arm_gic_devclass, 0, 0, - BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); +DEFINE_CLASS_0(gic, arm_gic_driver, arm_gic_methods, + sizeof(struct arm_gic_softc)); Index: sys/arm64/arm64/gic_acpi.c =================================================================== --- /dev/null +++ sys/arm64/arm64/gic_acpi.c @@ -0,0 +1,167 @@ +/*- + * Copyright (c) 2015 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Andrew Turner under + * sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include + +#include + +#include + +#include + +struct arm_gic_acpi_softc { + struct arm_gic_softc gic_sc; + struct resource_list res; +}; + +struct madt_table_data { + device_t parent; + ACPI_MADT_GENERIC_DISTRIBUTOR *dist; + ACPI_MADT_GENERIC_INTERRUPT *intr; +}; + +static void +madt_handler(ACPI_SUBTABLE_HEADER *entry, void *arg) +{ + struct madt_table_data *madt_data; + + madt_data = (struct madt_table_data *)arg; + + switch(entry->Type) { + case ACPI_MADT_TYPE_GENERIC_INTERRUPT: + if (madt_data->intr != NULL) { + if (bootverbose) + device_printf(madt_data->parent, + "gic: Already have an interrupt table"); + break; + } + + madt_data->intr = (ACPI_MADT_GENERIC_INTERRUPT *)entry; + break; + + case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR: + if (madt_data->dist != NULL) { + if (bootverbose) + device_printf(madt_data->parent, + "gic: Already have a distributor table"); + break; + } + + madt_data->dist = (ACPI_MADT_GENERIC_DISTRIBUTOR *)entry; + break; + + default: + break; + } +} + +static void +arm_gic_acpi_identify(driver_t *driver, device_t parent) +{ + struct madt_table_data madt_data; + ACPI_TABLE_MADT *madt; + vm_paddr_t physaddr; + device_t dev; + + physaddr = acpi_find_table(ACPI_SIG_MADT); + if (physaddr == 0) + return; + + madt = acpi_map_table(physaddr, ACPI_SIG_MADT); + if (madt == NULL) { + device_printf(parent, "gic: Unable to map the MADT\n"); + return; + } + + madt_data.parent = parent; + madt_data.dist = NULL; + madt_data.intr = NULL; + + acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length, + madt_handler, &madt_data); + if (madt_data.intr == NULL || madt_data.dist == NULL) { + device_printf(parent, + "No gic interrupt or distributor table\n"); + goto out; + } + + dev = BUS_ADD_CHILD(parent, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE, + "gic", -1); + if (dev == NULL) { + device_printf(parent, "add gic child failed\n"); + goto out; + } + + /* Add the MADT data */ + BUS_SET_RESOURCE(parent, dev, SYS_RES_MEMORY, 0, + madt_data.dist->BaseAddress, PAGE_SIZE); + BUS_SET_RESOURCE(parent, dev, SYS_RES_MEMORY, 1, + madt_data.intr->BaseAddress, PAGE_SIZE); + +out: + acpi_unmap_table(madt); +} + +static int +arm_gic_acpi_probe(device_t dev) +{ + + if (device_get_unit(dev) != 0) + return (ENXIO); + + if (acpi_get_type(dev) != ACPI_TYPE_NOT_FOUND) + return (ENXIO); + + device_set_desc(dev, "ARM Generic Interrupt Controller"); + return (BUS_PROBE_DEFAULT); +} + +static device_method_t arm_gic_acpi_methods[] = { + /* Device interface */ + DEVMETHOD(device_identify, arm_gic_acpi_identify), + DEVMETHOD(device_probe, arm_gic_acpi_probe), + + DEVMETHOD_END +}; + +DEFINE_CLASS_1(gic, arm_gic_acpi_driver, arm_gic_acpi_methods, + sizeof(struct arm_gic_acpi_softc), arm_gic_driver); + +static devclass_t arm_gic_acpi_devclass; + +EARLY_DRIVER_MODULE(gic, acpi, arm_gic_acpi_driver, + arm_gic_acpi_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); Index: sys/arm64/arm64/gic_fdt.c =================================================================== --- /dev/null +++ sys/arm64/arm64/gic_fdt.c @@ -0,0 +1,87 @@ +/*- + * Copyright (c) 2015 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Andrew Turner under + * sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +static struct ofw_compat_data compat_data[] = { + {"arm,gic", true}, /* Non-standard, used in FreeBSD dts. */ + {"arm,gic-400", true}, + {"arm,cortex-a15-gic", true}, + {"arm,cortex-a9-gic", true}, + {"arm,cortex-a7-gic", true}, + {"arm,arm11mp-gic", true}, + {"brcm,brahma-b15-gic", true}, + {NULL, false} +}; + +static int +arm_gic_fdt_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) + return (ENXIO); + + device_set_desc(dev, "ARM Generic Interrupt Controller"); + return (BUS_PROBE_DEFAULT); +} + +static device_method_t arm_gic_fdt_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, arm_gic_fdt_probe), + + DEVMETHOD_END +}; + +DEFINE_CLASS_1(gic, arm_gic_fdt_driver, arm_gic_fdt_methods, + sizeof(struct arm_gic_softc), arm_gic_driver); + +static devclass_t arm_gic_fdt_devclass; + +EARLY_DRIVER_MODULE(gic, simplebus, arm_gic_fdt_driver, + arm_gic_fdt_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); +EARLY_DRIVER_MODULE(gic, ofwbus, arm_gic_fdt_driver, arm_gic_fdt_devclass, + 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); Index: sys/arm64/arm64/machdep.c =================================================================== --- sys/arm64/arm64/machdep.c +++ sys/arm64/arm64/machdep.c @@ -392,6 +392,8 @@ void cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) { + + pcpu->pc_acpi_id = 0xffffffff; } void Index: sys/arm64/arm64/nexus.c =================================================================== --- sys/arm64/arm64/nexus.c +++ sys/arm64/arm64/nexus.c @@ -60,12 +60,17 @@ #include #include +#include "opt_acpi.h" #include "opt_platform.h" #ifdef FDT #include #include "ofw_bus_if.h" #endif +#ifdef DEV_ACPI +#include +#include +#endif extern struct bus_space memmap_bus; @@ -78,9 +83,19 @@ #define DEVTONX(dev) ((struct nexus_device *)device_get_ivars(dev)) static struct rman mem_rman; +static struct rman irq_rman; -static int nexus_probe(device_t); static int nexus_attach(device_t); + +#ifdef FDT +static device_probe_t nexus_fdt_probe; +static device_attach_t nexus_fdt_attach; +#endif +#ifdef DEV_ACPI +static device_probe_t nexus_acpi_probe; +static device_attach_t nexus_acpi_attach; +#endif + static int nexus_print_child(device_t, device_t); static device_t nexus_add_child(device_t, u_int, const char *, int); static struct resource *nexus_alloc_resource(device_t, device_t, int, int *, @@ -89,6 +104,8 @@ struct resource *); static int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, enum intr_polarity pol); +static struct resource_list *nexus_get_reslist(device_t, device_t); +static int nexus_set_resource(device_t, device_t, int, int, u_long, u_long); static int nexus_deactivate_resource(device_t, device_t, int, int, struct resource *); @@ -102,21 +119,18 @@ #endif static device_method_t nexus_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, nexus_probe), - DEVMETHOD(device_attach, nexus_attach), /* Bus interface */ DEVMETHOD(bus_print_child, nexus_print_child), DEVMETHOD(bus_add_child, nexus_add_child), DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), DEVMETHOD(bus_activate_resource, nexus_activate_resource), DEVMETHOD(bus_config_intr, nexus_config_intr), + DEVMETHOD(bus_get_resource_list, nexus_get_reslist), + DEVMETHOD(bus_set_resource, nexus_set_resource), DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), DEVMETHOD(bus_setup_intr, nexus_setup_intr), DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), -#ifdef FDT - DEVMETHOD(ofw_bus_map_intr, nexus_ofw_map_intr), -#endif + { 0, 0 } }; @@ -129,15 +143,6 @@ DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0); static int -nexus_probe(device_t dev) -{ - - device_quiet(dev); /* suppress attach message for neatness */ - - return (BUS_PROBE_DEFAULT); -} - -static int nexus_attach(device_t dev) { @@ -146,15 +151,14 @@ mem_rman.rm_type = RMAN_ARRAY; mem_rman.rm_descr = "I/O memory addresses"; if (rman_init(&mem_rman) || rman_manage_region(&mem_rman, 0, ~0)) - panic("nexus_probe mem_rman"); - - /* Add the ofwbus device */ - /* ARM64TODO: Alternatively add acpi */ - nexus_add_child(dev, 10, "ofwbus", 0); + panic("nexus_attach mem_rman"); + irq_rman.rm_start = 0; + irq_rman.rm_end = ~0ul; + irq_rman.rm_type = RMAN_ARRAY; + irq_rman.rm_descr = "Interrupts"; + if (rman_init(&irq_rman) || rman_manage_region(&irq_rman, 0, ~0)) + panic("nexus_attach irq_rman"); - /* - * First, deal with the children we know about already - */ bus_generic_probe(dev); bus_generic_attach(dev); @@ -201,11 +205,34 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { + struct nexus_device *ndev = DEVTONX(child); struct resource *rv; + struct resource_list_entry *rle; struct rman *rm; int needactivate = flags & RF_ACTIVE; + /* + * If this is an allocation of the "default" range for a given + * RID, and we know what the resources for this device are + * (ie. they aren't maintained by a child bus), then work out + * the start/end values. + */ + if ((start == 0UL) && (end == ~0UL) && (count == 1)) { + if (device_get_parent(child) != bus || ndev == NULL) + return(NULL); + rle = resource_list_find(&ndev->nx_resources, type, *rid); + if (rle == NULL) + return(NULL); + start = rle->start; + end = rle->end; + count = rle->count; + } + switch (type) { + case SYS_RES_IRQ: + rm = &irq_rman; + break; + case SYS_RES_MEMORY: case SYS_RES_IOPORT: rm = &mem_rman; @@ -297,6 +324,28 @@ return (0); } +static struct resource_list * +nexus_get_reslist(device_t dev, device_t child) +{ + struct nexus_device *ndev = DEVTONX(child); + + return (&ndev->nx_resources); +} + +static int +nexus_set_resource(device_t dev, device_t child, int type, int rid, + u_long start, u_long count) +{ + struct nexus_device *ndev = DEVTONX(child); + struct resource_list *rl = &ndev->nx_resources; + + /* XXX this should return a success/failure indicator */ + resource_list_add(rl, type, rid, start, start + count - 1, count); + + return(0); +} + + static int nexus_deactivate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) @@ -317,6 +366,41 @@ } #ifdef FDT +static device_method_t nexus_fdt_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, nexus_fdt_probe), + DEVMETHOD(device_attach, nexus_fdt_attach), + + /* OFW interface */ + DEVMETHOD(ofw_bus_map_intr, nexus_ofw_map_intr), +}; + +#define nexus_baseclasses nexus_fdt_baseclasses +DEFINE_CLASS_1(nexus, nexus_fdt_driver, nexus_fdt_methods, 1, nexus_driver); +#undef nexus_baseclasses +static devclass_t nexus_fdt_devclass; + +DRIVER_MODULE(nexus_fdt, root, nexus_fdt_driver, nexus_fdt_devclass, 0, 0); + +static int +nexus_fdt_probe(device_t dev) +{ + + if (OF_peer(0) == 0) + return (ENXIO); + + device_quiet(dev); + return (BUS_PROBE_DEFAULT); +} + +static int +nexus_fdt_attach(device_t dev) +{ + + nexus_add_child(dev, 10, "ofwbus", 0); + return (nexus_attach(dev)); +} + static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, pcell_t *intr) @@ -336,3 +420,37 @@ } #endif +#ifdef DEV_ACPI +static device_method_t nexus_acpi_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, nexus_acpi_probe), + DEVMETHOD(device_attach, nexus_acpi_attach), +}; + +#define nexus_baseclasses nexus_acpi_baseclasses +DEFINE_CLASS_1(nexus, nexus_acpi_driver, nexus_acpi_methods, 1, + nexus_driver); +#undef nexus_baseclasses +static devclass_t nexus_acpi_devclass; + +DRIVER_MODULE(nexus_acpi, root, nexus_acpi_driver, nexus_acpi_devclass, 0, 0); + +static int +nexus_acpi_probe(device_t dev) +{ + + if (acpi_identify() != 0) + return (ENXIO); + + device_quiet(dev); + return (BUS_PROBE_LOW_PRIORITY); +} + +static int +nexus_acpi_attach(device_t dev) +{ + + nexus_add_child(dev, 10, "acpi", 0); + return (nexus_attach(dev)); +} +#endif Index: sys/arm64/conf/GENERIC =================================================================== --- sys/arm64/conf/GENERIC +++ sys/arm64/conf/GENERIC @@ -95,3 +95,4 @@ device bpf # Berkeley packet filter options FDT +device acpi Index: sys/arm64/include/acpica_machdep.h =================================================================== --- /dev/null +++ sys/arm64/include/acpica_machdep.h @@ -0,0 +1,94 @@ +/*- + * Copyright (c) 2002 Mitsuru IWASAKI + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/****************************************************************************** + * + * Name: acpica_machdep.h - arch-specific defines, etc. + * $Revision$ + * + *****************************************************************************/ + +#ifndef __ACPICA_MACHDEP_H__ +#define __ACPICA_MACHDEP_H__ + + +#ifdef _KERNEL +/* + * Calling conventions: + * + * ACPI_SYSTEM_XFACE - Interfaces to host OS (handlers, threads) + * ACPI_EXTERNAL_XFACE - External ACPI interfaces + * ACPI_INTERNAL_XFACE - Internal ACPI interfaces + * ACPI_INTERNAL_VAR_XFACE - Internal variable-parameter list interfaces + */ +#if 0 +#define ACPI_SYSTEM_XFACE +#define ACPI_EXTERNAL_XFACE +#define ACPI_INTERNAL_XFACE +#define ACPI_INTERNAL_VAR_XFACE + +/* Asm macros */ + +#define ACPI_ASM_MACROS +#define BREAKPOINT3 +#define ACPI_DISABLE_IRQS() disable_intr() +#define ACPI_ENABLE_IRQS() enable_intr() + +#define ACPI_FLUSH_CPU_CACHE() wbinvd() +#endif + +/* Section 5.2.10.1: global lock acquire/release functions */ +int acpi_acquire_global_lock(volatile uint32_t *); +int acpi_release_global_lock(volatile uint32_t *); +#if 0 +#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) do { \ + (Acq) = acpi_acquire_global_lock(&((GLptr)->GlobalLock)); \ +} while (0) +#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) do { \ + (Acq) = acpi_release_global_lock(&((GLptr)->GlobalLock)); \ +} while (0) + +enum intr_trigger; +enum intr_polarity; + +void acpi_SetDefaultIntrModel(int model); +void acpi_cpu_c1(void); +#endif +void *acpi_map_table(vm_paddr_t pa, const char *sig); +void acpi_unmap_table(void *table); +vm_paddr_t acpi_find_table(const char *sig); +#if 0 +void madt_parse_interrupt_values(void *entry, + enum intr_trigger *trig, enum intr_polarity *pol); + +extern int madt_found_sci_override; +#endif /* 0 */ + +#endif /* _KERNEL */ + +#endif /* __ACPICA_MACHDEP_H__ */ Index: sys/arm64/include/iodev.h =================================================================== --- /dev/null +++ sys/arm64/include/iodev.h @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2015 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Andrew Turner under + * sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_IODEV_H_ +#define _MACHINE_IODEV_H_ + +#define iodev_read_1(a) \ +({ \ + uint8_t val; \ + __asm __volatile("ldrb %w0, [%1]" : "=&r" (val) : "r"(a)); \ + val; \ +}) + +#define iodev_read_2(a) \ +({ \ + uint16_t val; \ + __asm __volatile("ldrh %w0, [%1]" : "=&r" (val) : "r"(a)); \ + val; \ +}) + +#define iodev_read_4(a) \ +({ \ + uint32_t val; \ + __asm __volatile("ldr %w0, [%1]" : "=&r" (val) : "r"(a)); \ + val; \ +}) + +#define iodev_write_1(a, v) \ + __asm __volatile("strb %w0, [%1]" :: "r" (v), "r"(a)) + +#define iodev_write_2(a, v) \ + __asm __volatile("strh %w0, [%1]" :: "r" (v), "r"(a)) + +#define iodev_write_4(a, v) \ + __asm __volatile("str %w0, [%1]" :: "r" (v), "r"(a)) + +#endif /* _MACHINE_IODEV_H_ */ Index: sys/arm64/include/pci_cfgreg.h =================================================================== --- /dev/null +++ sys/arm64/include/pci_cfgreg.h @@ -0,0 +1 @@ +/* $FreeBSD$ */ Index: sys/arm64/include/pcpu.h =================================================================== --- sys/arm64/include/pcpu.h +++ sys/arm64/include/pcpu.h @@ -36,7 +36,8 @@ #define ALT_STACK_SIZE 128 #define PCPU_MD_FIELDS \ - char __pad[129] + u_int pc_acpi_id; /* ACPI CPU id */ \ + char __pad[125] #ifdef _KERNEL Index: sys/conf/Makefile.arm64 =================================================================== --- sys/conf/Makefile.arm64 +++ sys/conf/Makefile.arm64 @@ -33,6 +33,9 @@ # Reserve x18 for pcpu data CFLAGS += -ffixed-x18 +# Only use the reduced hardware model +CFLAGS += -DACPI_REDUCED_HARDWARE + .if !empty(DDB_ENABLED) CFLAGS += -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer .endif Index: sys/conf/files.arm64 =================================================================== --- sys/conf/files.arm64 +++ sys/conf/files.arm64 @@ -2,6 +2,9 @@ arm/arm/devmap.c standard arm/arm/generic_timer.c standard arm/arm/pmu.c standard +arm64/acpica/acpi_machdep.c optional acpi +arm64/acpica/OsdEnvironment.c optional acpi +arm64/acpica/acpi_wakeup.c optional acpi arm64/arm64/autoconf.c standard arm64/arm64/bcopy.c standard arm64/arm64/bus_machdep.c standard @@ -20,6 +23,8 @@ arm64/arm64/elf_machdep.c standard arm64/arm64/exception.S standard arm64/arm64/gic.c standard +arm64/arm64/gic_acpi.c optional acpi +arm64/arm64/gic_fdt.c optional fdt arm64/arm64/gic_v3.c standard arm64/arm64/gic_v3_fdt.c optional fdt arm64/arm64/identcpu.c standard @@ -40,6 +45,7 @@ arm64/arm64/uio_machdep.c standard arm64/arm64/vfp.c standard arm64/arm64/vm_machdep.c standard +dev/acpica/acpi_if.m optional acpi dev/fdt/fdt_arm64.c optional fdt dev/hwpmc/hwpmc_arm64.c optional hwpmc dev/hwpmc/hwpmc_arm64_md.c optional hwpmc Index: sys/dev/acpica/Osd/OsdHardware.c =================================================================== --- sys/dev/acpica/Osd/OsdHardware.c +++ sys/dev/acpica/Osd/OsdHardware.c @@ -89,6 +89,10 @@ UINT32 Width) { +#ifdef __aarch64__ + /* ARM64TODO: Add pci support */ + return (AE_SUPPORT); +#else if (Width == 64) return (AE_SUPPORT); @@ -99,6 +103,7 @@ PciId->Function, Register, Width / 8); return (AE_OK); +#endif } @@ -107,6 +112,10 @@ UINT64 Value, UINT32 Width) { +#ifdef __aarch64__ + /* ARM64TODO: Add pci support */ + return (AE_SUPPORT); +#else if (Width == 64) return (AE_SUPPORT); @@ -117,4 +126,5 @@ Value, Width / 8); return (AE_OK); +#endif } Index: sys/dev/acpica/acpi_cpu.c =================================================================== --- sys/dev/acpica/acpi_cpu.c +++ sys/dev/acpica/acpi_cpu.c @@ -183,7 +183,9 @@ static void acpi_cpu_startup(void *arg); static void acpi_cpu_startup_cx(struct acpi_cpu_softc *sc); static void acpi_cpu_cx_list(struct acpi_cpu_softc *sc); +#if defined(__i386__) || defined(__amd64__) static void acpi_cpu_idle(sbintime_t sbt); +#endif static void acpi_cpu_notify(ACPI_HANDLE h, UINT32 notify, void *context); static int acpi_cpu_quirks(void); static int acpi_cpu_usage_sysctl(SYSCTL_HANDLER_ARGS); @@ -474,12 +476,14 @@ sc->cpu_disable_idle = FALSE; } +#if defined(__i386__) || defined(__amd64__) static int is_idle_disabled(struct acpi_cpu_softc *sc) { return (sc->cpu_disable_idle); } +#endif /* * Disable any entry to the idle function during suspend and re-enable it @@ -998,7 +1002,9 @@ sc = device_get_softc(cpu_devices[i]); enable_idle(sc); } +#if defined(__i386__) || defined(__amd64__) cpu_idle_hook = acpi_cpu_idle; +#endif } static void @@ -1060,6 +1066,7 @@ } } +#if defined(__i386__) || defined(__amd64__) /* * Idle the CPU in the lowest state possible. This function is called with * interrupts disabled. Note that once it re-enables interrupts, a task @@ -1206,6 +1213,7 @@ sc->cpu_prev_sleep = (sc->cpu_prev_sleep * 3 + PM_USEC(end_time)) / 4; } +#endif /* * Re-evaluate the _CST object when we are notified that it changed. @@ -1242,8 +1250,10 @@ static int acpi_cpu_quirks(void) { +#if defined(__i386__) || defined(__amd64__) device_t acpi_dev; uint32_t val; +#endif ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); @@ -1277,6 +1287,7 @@ "acpi_cpu: SMP, using flush cache mode for C3\n")); } +#if defined(__i386__) || defined(__amd64__) /* Look for various quirks of the PIIX4 part. */ acpi_dev = pci_find_device(PCI_VENDOR_INTEL, PCI_DEVICE_82371AB_3); if (acpi_dev != NULL) { @@ -1326,6 +1337,7 @@ break; } } +#endif return (0); } Index: sys/dev/acpica/acpi_throttle.c =================================================================== --- sys/dev/acpica/acpi_throttle.c +++ sys/dev/acpica/acpi_throttle.c @@ -317,6 +317,7 @@ static int acpi_throttle_quirks(struct acpi_throttle_softc *sc) { +#if defined(__i386__) || defined(__amd64__) device_t acpi_dev; /* Look for various quirks of the PIIX4 part. */ @@ -339,6 +340,7 @@ break; } } +#endif return (0); }