diff --git a/sys/conf/files b/sys/conf/files --- a/sys/conf/files +++ b/sys/conf/files @@ -3143,6 +3143,7 @@ dev/sound/midi/mpufoi_if.m optional sound dev/sound/midi/sequencer.c optional sound dev/sound/midi/synth_if.m optional sound +dev/spibus/acpi_spibus.c optional acpi spibus dev/spibus/ofw_spibus.c optional fdt spibus dev/spibus/spibus.c optional spibus \ dependency "spibus_if.h" diff --git a/sys/dev/spibus/acpi_spibus.c b/sys/dev/spibus/acpi_spibus.c new file mode 100644 --- /dev/null +++ b/sys/dev/spibus/acpi_spibus.c @@ -0,0 +1,580 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Vladimir Kondratyev + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +/* + * Make a copy of ACPI_RESOURCE_SPI_SERIALBUS type and replace "pointer to ACPI + * object name string" field with pointer to ACPI object itself. + * This saves us extra strdup()/free() pair on acpi_spibus_get_acpi_res call. + */ +typedef ACPI_RESOURCE_SPI_SERIALBUS ACPI_SPIBUS_RESOURCE_SPI_SERIALBUS; +#define ResourceSource_Handle ResourceSource.StringPtr + +/* Hooks for the ACPI CA debugging infrastructure. */ +#define _COMPONENT ACPI_BUS +ACPI_MODULE_NAME("SPI") + +#if defined (__amd64__) || defined (__i386__) +static bool is_apple; +#endif + +struct acpi_spibus_ivar { + struct spibus_ivar super_ivar; + ACPI_HANDLE handle; +}; + +static inline bool +acpi_resource_is_spi_serialbus(ACPI_RESOURCE *res) +{ + return (res->Type == ACPI_RESOURCE_TYPE_SERIAL_BUS && + res->Data.CommonSerialBus.Type == ACPI_RESOURCE_SERIAL_TYPE_SPI); +} + +static ACPI_STATUS +acpi_spibus_get_acpi_res_cb(ACPI_RESOURCE *res, void *context) +{ + ACPI_SPIBUS_RESOURCE_SPI_SERIALBUS *sb = context; + ACPI_STATUS status; + ACPI_HANDLE handle; + + if (acpi_resource_is_spi_serialbus(res)) { + status = AcpiGetHandle(ACPI_ROOT_OBJECT, + res->Data.SpiSerialBus.ResourceSource.StringPtr, &handle); + if (ACPI_FAILURE(status)) + return (status); + memcpy(sb, &res->Data.SpiSerialBus, + sizeof(ACPI_SPIBUS_RESOURCE_SPI_SERIALBUS)); + /* + * replace "pointer to ACPI object name string" field + * with pointer to ACPI object itself. + */ + sb->ResourceSource_Handle = handle; + return (AE_CTRL_TERMINATE); + } else if (res->Type == ACPI_RESOURCE_TYPE_END_TAG) + return (AE_NOT_FOUND); + + return (AE_OK); +} + +static void +acpi_spibus_dump_res(device_t dev, ACPI_SPIBUS_RESOURCE_SPI_SERIALBUS *sb) +{ + device_printf(dev, "found ACPI child\n"); + printf(" DeviceSelection: 0x%04hx\n", sb->DeviceSelection); + printf(" ConnectionSpeed: %uHz\n", sb->ConnectionSpeed); + printf(" WireMode: %s\n", + sb->WireMode == ACPI_SPI_4WIRE_MODE ? + "FourWireMode" : "ThreeWireMode"); + printf(" DevicePolarity: %s\n", + sb->DevicePolarity == ACPI_SPI_ACTIVE_LOW ? + "PolarityLow" : "PolarityHigh"); + printf(" DataBitLength: %uBit\n", sb->DataBitLength); + printf(" ClockPhase: %s\n", + sb->ClockPhase == ACPI_SPI_FIRST_PHASE ? + "ClockPhaseFirst" : "ClockPhaseSecond"); + printf(" ClockPolarity: %s\n", + sb->ClockPolarity == ACPI_SPI_START_LOW ? + "ClockPolarityLow" : "ClockPolarityHigh"); + printf(" SlaveMode: %s\n", + sb->SlaveMode == ACPI_CONTROLLER_INITIATED ? + "ControllerInitiated" : "DeviceInitiated"); + printf(" ConnectionSharing: %s\n", sb->ConnectionSharing == 0 ? + "Exclusive" : "Shared"); +} + +static int +acpi_spibus_get_acpi_res(device_t spibus, ACPI_HANDLE dev, + struct spibus_ivar *res) +{ + ACPI_SPIBUS_RESOURCE_SPI_SERIALBUS sb; + + /* + * Read "SPI Serial Bus Connection Resource Descriptor" + * described in p.19.6.126 of ACPI specification. + */ + bzero(&sb, sizeof(ACPI_SPIBUS_RESOURCE_SPI_SERIALBUS)); + if (ACPI_FAILURE(AcpiWalkResources(dev, "_CRS", + acpi_spibus_get_acpi_res_cb, &sb))) + return (ENXIO); + if (sb.ResourceSource_Handle != + acpi_get_handle(device_get_parent(spibus))) + return (ENXIO); + if (bootverbose) + acpi_spibus_dump_res(spibus, &sb); + /* + * The Windows Baytrail and Braswell SPI host controller + * drivers uses 1 as the first (and only) value for ACPI + * DeviceSelection. + */ + if (sb.DeviceSelection != 0 && + (acpi_MatchHid(sb.ResourceSource_Handle, "80860F0E") || + acpi_MatchHid(sb.ResourceSource_Handle, "8086228E"))) + res->cs = sb.DeviceSelection - 1; + else + res->cs = sb.DeviceSelection; + res->mode = + (sb.ClockPhase != ACPI_SPI_FIRST_PHASE ? SPIBUS_MODE_CPHA : 0) | + (sb.ClockPolarity != ACPI_SPI_START_LOW ? SPIBUS_MODE_CPOL : 0); + res->clock = sb.ConnectionSpeed; + + return (0); +} + +#if defined (__amd64__) || defined (__i386__) +static int +acpi_spibus_get_apple_res(device_t spibus, ACPI_HANDLE dev, + struct spibus_ivar *ivar) +{ + /* a0b5b7c6-1318-441c-b0c9-fe695eaf949b */ + static const uint8_t apple_guid[ACPI_UUID_LENGTH] = { + 0xC6, 0xB7, 0xB5, 0xA0, 0x18, 0x13, 0x1C, 0x44, + 0xB0, 0xC9, 0xFE, 0x69, 0x5E, 0xAF, 0x94, 0x9B, + }; + ACPI_BUFFER buf; + ACPI_OBJECT *pkg, *comp; + ACPI_HANDLE parent; + char *k; + uint64_t val; + + /* Apple does not use _CRS but nested devices for SPI slaves */ + if (ACPI_FAILURE(AcpiGetParent(dev, &parent))) + return (ENXIO); + if (parent != acpi_get_handle(device_get_parent(spibus))) + return (ENXIO); + if (ACPI_FAILURE(acpi_EvaluateDSMTyped(dev, apple_guid, + 1, 1, NULL, &buf, ACPI_TYPE_PACKAGE))) + return (ENXIO); + + pkg = ((ACPI_OBJECT *)buf.Pointer); + if (pkg->Package.Count % 2 != 0) { + device_printf(spibus, "_DSM length %d not even\n", + pkg->Package.Count); + AcpiOsFree(pkg); + return (ENXIO); + } + + if (bootverbose) + device_printf(spibus, "found ACPI child\n"); + + for (comp = pkg->Package.Elements; + comp < pkg->Package.Elements + pkg->Package.Count; + comp += 2) { + + if (comp[0].Type != ACPI_TYPE_STRING || + comp[1].Type != ACPI_TYPE_BUFFER) { + device_printf(spibus, "expected string+buffer, " + "got %d+%d\n", comp[0].Type, comp[1].Type); + continue; + } + k = comp[0].String.Pointer; + val = comp[1].Buffer.Length >= 8 ? + *(uint64_t *)comp[1].Buffer.Pointer : 0; + + if (bootverbose) + printf(" %s: %zu\n", k, (intmax_t)val); + + if (strcmp(k, "spiSclkPeriod") == 0) { + if (val != 0) + ivar->clock = 1000000000 / val; + } else if (strcmp(k, "spiSPO") == 0) { + if (val != 0) + ivar->mode |= SPIBUS_MODE_CPOL; + } else if (strcmp(k, "spiSPH") == 0) { + if (val != 0) + ivar->mode |= SPIBUS_MODE_CPHA; + } else if (strcmp(k, "spiCSDelay") == 0) { + ivar->cs_delay = val; + } + } + + AcpiOsFree(pkg); + + return (0); +} +#endif + +static int +acpi_spibus_delete_acpi_child(ACPI_HANDLE handle) +{ + device_t acpi_child, acpi0; + + /* Delete existing child of acpi bus */ + acpi_child = acpi_get_device(handle); + if (acpi_child != NULL) { + acpi0 = devclass_get_device(devclass_find("acpi"), 0); + if (device_get_parent(acpi_child) != acpi0) + return (ENXIO); + + if (device_is_attached(acpi_child)) + return (ENXIO); + + if (device_delete_child(acpi0, acpi_child) != 0) + return (ENXIO); + } + + return (0); +} + +static device_t +acpi_spibus_add_child(device_t dev, u_int order, const char *name, int unit) +{ + return (spibus_add_child_common( + dev, order, name, unit, sizeof(struct acpi_spibus_ivar))); +} + +static ACPI_STATUS +acpi_spibus_enumerate_child(ACPI_HANDLE handle, UINT32 level, + void *context, void **result) +{ + device_t spibus, child; + struct spibus_ivar res; + ACPI_STATUS status; + UINT32 sta; + bool found = false; + + spibus = context; + + /* + * If no _STA method or if it failed, then assume that + * the device is present. + */ + if (!ACPI_FAILURE(acpi_GetInteger(handle, "_STA", &sta)) && + !ACPI_DEVICE_PRESENT(sta)) + return (AE_OK); + + if (!acpi_has_hid(handle)) + return (AE_OK); + + bzero(&res, sizeof(res)); + if (acpi_spibus_get_acpi_res(spibus, handle, &res) == 0) + found = true; +#if defined (__amd64__) || defined (__i386__) + if (!found && is_apple && + acpi_spibus_get_apple_res(spibus, handle, &res) == 0) + found = true; +#endif + if (!found || res.clock == 0) + return (AE_OK); + + /* Delete existing child of acpi bus */ + if (acpi_spibus_delete_acpi_child(handle) != 0) + return (AE_OK); + + child = BUS_ADD_CHILD(spibus, 0, NULL, -1); + if (child == NULL) { + device_printf(spibus, "add child failed\n"); + return (AE_OK); + } + + spibus_set_cs(child, res.cs); + spibus_set_mode(child, res.mode); + spibus_set_clock(child, res.clock); + spibus_set_cs_delay(child, res.cs_delay); + acpi_set_handle(child, handle); + acpi_parse_resources(child, handle, &acpi_res_parse_set, NULL); + + /* + * Update ACPI-CA to use the IIC enumerated device_t for this handle. + */ + status = AcpiAttachData(handle, acpi_fake_objhandler, child); + if (ACPI_FAILURE(status)) + printf("WARNING: Unable to attach object data to %s - %s\n", + acpi_name(handle), AcpiFormatException(status)); + + return (AE_OK); +} + +static ACPI_STATUS +acpi_spibus_enumerate_children(device_t dev) +{ + return (AcpiWalkNamespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, acpi_spibus_enumerate_child, NULL, dev, NULL)); +} + +static void +acpi_spibus_set_power_children(device_t dev, int state, bool all_children) +{ + device_t *devlist; + int i, numdevs; + + if (device_get_children(dev, &devlist, &numdevs) != 0) + return; + + for (i = 0; i < numdevs; i++) + if (all_children || device_is_attached(devlist[i]) != 0) + acpi_set_powerstate(devlist[i], state); + + free(devlist, M_TEMP); +} + +static int +acpi_spibus_probe(device_t dev) +{ + ACPI_HANDLE handle; + device_t controller; + + if (acpi_disabled("spibus")) + return (ENXIO); + + controller = device_get_parent(dev); + if (controller == NULL) + return (ENXIO); + + handle = acpi_get_handle(controller); + if (handle == NULL) + return (ENXIO); + + device_set_desc(dev, "SPI bus (ACPI-hinted)"); + return (BUS_PROBE_DEFAULT + 1); +} + +static int +acpi_spibus_attach(device_t dev) +{ + +#if defined (__amd64__) || defined (__i386__) + char *vendor = kern_getenv("smbios.bios.vendor"); + if (vendor != NULL && + (strcmp(vendor, "Apple Inc.") == 0 || + strcmp(vendor, "Apple Computer, Inc.") == 0)) + is_apple = true; +#endif + + if (ACPI_FAILURE(acpi_spibus_enumerate_children(dev))) + device_printf(dev, "children enumeration failed\n"); + + acpi_spibus_set_power_children(dev, ACPI_STATE_D0, true); + return (spibus_attach(dev)); +} + +static int +acpi_spibus_detach(device_t dev) +{ + acpi_spibus_set_power_children(dev, ACPI_STATE_D3, false); + + return (spibus_detach(dev)); +} + +static int +acpi_spibus_suspend(device_t dev) +{ + acpi_spibus_set_power_children(dev, ACPI_STATE_D3, false); + + return (bus_generic_suspend(dev)); +} + +static int +acpi_spibus_resume(device_t dev) +{ + acpi_spibus_set_power_children(dev, ACPI_STATE_D0, false); + + return (bus_generic_resume(dev)); +} + +#ifndef INTRNG +/* Mostly copy of acpi_alloc_resource() */ +static struct resource * +acpi_spibus_alloc_resource(device_t dev, device_t child, int type, int *rid, + rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) +{ + ACPI_RESOURCE ares; + struct resource_list *rl; + struct resource *res; + + if (device_get_parent(child) != dev) + return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child, + type, rid, start, end, count, flags)); + + rl = BUS_GET_RESOURCE_LIST(dev, child); + if (rl == NULL) + return (NULL); + + res = resource_list_alloc(rl, dev, child, type, rid, + start, end, count, flags); + if (res != NULL && type == SYS_RES_IRQ && + ACPI_SUCCESS(acpi_lookup_irq_resource(child, *rid, res, &ares))) + acpi_config_intr(child, &ares); + + return (res); +} +#endif + +/* + * If this device is an ACPI child but no one claimed it, attempt + * to power it off. We'll power it back up when a driver is added. + */ +static void +acpi_spibus_probe_nomatch(device_t bus, device_t child) +{ + spibus_probe_nomatch(bus, child); + acpi_set_powerstate(child, ACPI_STATE_D3); +} + +/* + * If a new driver has a chance to probe a child, first power it up. + */ +static void +acpi_spibus_driver_added(device_t dev, driver_t *driver) +{ + device_t child, *devlist; + int i, numdevs; + + DEVICE_IDENTIFY(driver, dev); + if (device_get_children(dev, &devlist, &numdevs) != 0) + return; + + for (i = 0; i < numdevs; i++) { + child = devlist[i]; + if (device_get_state(child) == DS_NOTPRESENT) { + acpi_set_powerstate(child, ACPI_STATE_D0); + if (device_probe_and_attach(child) != 0) + acpi_set_powerstate(child, ACPI_STATE_D3); + } + } + free(devlist, M_TEMP); +} + +static void +acpi_spibus_child_deleted(device_t bus, device_t child) +{ + struct acpi_spibus_ivar *devi = device_get_ivars(child); + + if (acpi_get_device(devi->handle) == child) + AcpiDetachData(devi->handle, acpi_fake_objhandler); +} + +static int +acpi_spibus_read_ivar(device_t bus, device_t child, int which, uintptr_t *res) +{ + struct acpi_spibus_ivar *devi = device_get_ivars(child); + + switch (which) { + case ACPI_IVAR_HANDLE: + *res = (uintptr_t)devi->handle; + break; + default: + return (spibus_read_ivar(bus, child, which, res)); + } + + return (0); +} + +static int +acpi_spibus_write_ivar(device_t bus, device_t child, int which, uintptr_t val) +{ + struct acpi_spibus_ivar *devi = device_get_ivars(child); + + switch (which) { + case ACPI_IVAR_HANDLE: + if (devi->handle != NULL) + return (EINVAL); + devi->handle = (ACPI_HANDLE)val; + break; + default: + return (spibus_write_ivar(bus, child, which, val)); + } + + return (0); +} + +/* Location hint for devctl(8). Concatenate IIC and ACPI hints. */ +static int +acpi_spibus_child_location(device_t bus, device_t child, struct sbuf *sb) +{ + struct acpi_spibus_ivar *devi = device_get_ivars(child); + int error; + + /* read SPI location hint string into the buffer. */ + error = spibus_child_location(bus, child, sb); + if (error != 0) + return (error); + + /* Place ACPI string right after IIC one's terminating NUL. */ + if (devi->handle != NULL) + sbuf_printf(sb, " handle=%s", acpi_name(devi->handle)); + + return (0); +} + +/* PnP information for devctl(8). */ +static int +acpi_spibus_child_pnpinfo(device_t bus, device_t child, struct sbuf *sb) +{ + struct acpi_spibus_ivar *devi = device_get_ivars(child); + + return ( + devi->handle == NULL ? ENOTSUP : acpi_pnpinfo(devi->handle, sb)); +} + +static device_method_t acpi_spibus_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, acpi_spibus_probe), + DEVMETHOD(device_attach, acpi_spibus_attach), + DEVMETHOD(device_detach, acpi_spibus_detach), + DEVMETHOD(device_suspend, acpi_spibus_suspend), + DEVMETHOD(device_resume, acpi_spibus_resume), + + /* Bus interface */ +#ifndef INTRNG + DEVMETHOD(bus_alloc_resource, acpi_spibus_alloc_resource), +#endif + DEVMETHOD(bus_add_child, acpi_spibus_add_child), + DEVMETHOD(bus_probe_nomatch, acpi_spibus_probe_nomatch), + DEVMETHOD(bus_driver_added, acpi_spibus_driver_added), + DEVMETHOD(bus_child_deleted, acpi_spibus_child_deleted), + DEVMETHOD(bus_read_ivar, acpi_spibus_read_ivar), + DEVMETHOD(bus_write_ivar, acpi_spibus_write_ivar), + DEVMETHOD(bus_child_location, acpi_spibus_child_location), + DEVMETHOD(bus_child_pnpinfo, acpi_spibus_child_pnpinfo), + DEVMETHOD(bus_get_device_path, acpi_get_acpi_device_path), + + DEVMETHOD_END, +}; + +DEFINE_CLASS_1(spibus, acpi_spibus_driver, acpi_spibus_methods, + sizeof(struct spibus_softc), spibus_driver); +DRIVER_MODULE(acpi_spibus, spi, acpi_spibus_driver, NULL, NULL); +MODULE_VERSION(acpi_spibus, 1); +MODULE_DEPEND(acpi_spibus, acpi, 1, 1, 1); diff --git a/sys/dev/spibus/spibus.c b/sys/dev/spibus/spibus.c --- a/sys/dev/spibus/spibus.c +++ b/sys/dev/spibus/spibus.c @@ -53,7 +53,7 @@ return (BUS_PROBE_DEFAULT); } -static int +int spibus_attach(device_t dev) { struct spibus_softc *sc = SPIBUS_SOFTC(dev); @@ -67,7 +67,7 @@ * Since this is not a self-enumerating bus, and since we always add * children in attach, we have to always delete children here. */ -static int +int spibus_detach(device_t dev) { return (device_delete_children(dev)); @@ -102,7 +102,7 @@ return (retval); } -static void +void spibus_probe_nomatch(device_t bus, device_t child) { struct spibus_ivar *devi = SPIBUS_IVAR(child); @@ -112,7 +112,7 @@ return; } -static int +int spibus_child_location(device_t bus, device_t child, struct sbuf *sb) { struct spibus_ivar *devi = SPIBUS_IVAR(child); @@ -123,7 +123,7 @@ return (0); } -static int +int spibus_read_ivar(device_t bus, device_t child, int which, uintptr_t *result) { struct spibus_ivar *devi = SPIBUS_IVAR(child); @@ -147,7 +147,7 @@ return (0); } -static int +int spibus_write_ivar(device_t bus, device_t child, int which, uintptr_t value) { struct spibus_ivar *devi = SPIBUS_IVAR(child); @@ -181,8 +181,9 @@ return (0); } -static device_t -spibus_add_child(device_t dev, u_int order, const char *name, int unit) +device_t +spibus_add_child_common(device_t dev, u_int order, const char *name, int unit, + size_t ivars_size) { device_t child; struct spibus_ivar *devi; @@ -190,7 +191,7 @@ child = device_add_child_ordered(dev, order, name, unit); if (child == NULL) return (child); - devi = malloc(sizeof(struct spibus_ivar), M_DEVBUF, M_NOWAIT | M_ZERO); + devi = malloc(ivars_size, M_DEVBUF, M_NOWAIT | M_ZERO); if (devi == NULL) { device_delete_child(dev, child); return (0); @@ -200,6 +201,13 @@ return (child); } +static device_t +spibus_add_child(device_t dev, u_int order, const char *name, int unit) +{ + return (spibus_add_child_common( + dev, order, name, unit, sizeof(struct spibus_ivar))); +} + static void spibus_hinted_child(device_t bus, const char *dname, int dunit) { diff --git a/sys/dev/spibus/spibusvar.h b/sys/dev/spibus/spibusvar.h --- a/sys/dev/spibus/spibusvar.h +++ b/sys/dev/spibus/spibusvar.h @@ -73,7 +73,15 @@ SPIBUS_ACCESSOR(cs, CS, uint32_t) SPIBUS_ACCESSOR(mode, MODE, uint32_t) SPIBUS_ACCESSOR(clock, CLOCK, uint32_t) -SPIBUS_ACCESSOR(cs_delay, CS_DELAY, uint32_t) +SPIBUS_ACCESSOR(cs_delay, CS_DELAY, uint32_t) extern driver_t spibus_driver; extern driver_t ofw_spibus_driver; + +int spibus_attach(device_t); +int spibus_detach(device_t); +device_t spibus_add_child_common(device_t, u_int, const char *, int, size_t); +void spibus_probe_nomatch(device_t, device_t); +int spibus_child_location(device_t, device_t, struct sbuf *); +int spibus_read_ivar(device_t, device_t, int, uintptr_t *); +int spibus_write_ivar(device_t, device_t, int, uintptr_t); diff --git a/sys/modules/spi/spibus/Makefile b/sys/modules/spi/spibus/Makefile --- a/sys/modules/spi/spibus/Makefile +++ b/sys/modules/spi/spibus/Makefile @@ -9,6 +9,11 @@ SRCS+= ofw_spibus.c ofw_bus_if.h .endif +.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" || \ + ${MACHINE_CPUARCH} == "i386" +SRCS+= acpi_spibus.c opt_acpi.h acpi_if.h +.endif + # Generated files... SRCS+= \ bus_if.h \