Skip to content
  • Lukas Wunner's avatar
    ACPI / property: Support Apple _DSM properties · 899596e0
    Lukas Wunner authored
    While the rest of the world has standardized on _DSD as the way to store
    device properties in AML (introduced with ACPI 5.1 in 2014), Apple has
    been using a custom _DSM to achieve the same for much longer (ever since
    they switched from DeviceTree-based PowerPC to Intel in 2005, verified
    with MacOS X 10.4.11).
    
    The theory of operation on macOS is as follows:  AppleACPIPlatform.kext
    invokes mergeEFIproperties() and mergeDSMproperties() for each device to
    merge properties conveyed by EFI drivers as well as properties stored in
    AML into the I/O Kit registry from which they can be retrieved by
    drivers.  We've been supporting EFI properties since commit 58c5475a
    ("x86/efi: Retrieve and assign Apple device properties").  The present
    commit adds support for _DSM properties, thereby completing our support
    for Apple device properties.  The _DSM properties are made available
    under the primary fwnode, the EFI properties under the secondary fwnode.
    So for devices which possess both property types, they can all be
    elegantly accessed with the uniform API in <linux/property.h>.
    
    Until recently we had no need to support _DSM properties, they contained
    only uninteresting garbage.  The situation has changed with MacBooks and
    MacBook Pros introduced since 2015:  Their keyboard is attached with SPI
    instead of USB and the _CRS data which is necessary to initialize the
    spi driver only contains valid information if OSPM responds "false" to
    _OSI("Darwin").  If OSPM responds "true", _CRS is empty and the spi
    driver fails to initialize.  The rationale is very simple, Apple only
    cares about macOS and Windows:  On Windows, _CRS contains valid data,
    whereas on macOS it is empty.  Instead, macOS gleans the necessary data
    from the _DSM properties.
    
    Since Linux deliberately defaults to responding "true" to _OSI("Darwin"),
    we need to emulate macOS' behaviour by initializing the spi driver with
    data returned by the _DSM.
    
    An out-of-tree driver for the SPI keyboard exists which currently binds
    to the ACPI device, invokes the _DSM, parses the returned package and
    instantiates an SPI device with the data gleaned from the _DSM:
    https://github.com/cb22/macbook12-spi-driver/commit/9a416d699ef4
    https://github.com/cb22/macbook12-spi-driver/commit/0c34936ed9a1
    
    
    
    By adding support for Apple's _DSM properties in generic ACPI code, the
    out-of-tree driver will be able to register as a regular SPI driver,
    significantly reducing its amount of code and improving its chances to
    be mainlined.
    
    The SPI keyboard will not be the only user of this commit:  E.g. on the
    MacBook8,1, the UART-attached Bluetooth device likewise returns empty
    _CRS data if OSPM returns "true" to _OSI("Darwin").
    
    The _DSM returns a Package whose format unfortunately deviates slightly
    from the _DSD spec:  The properties are marshalled up in a single Package
    as alternating key/value elements, unlike _DSD which stores them as a
    Package of 2-element Packages.  The present commit therefore converts
    the Package to _DSD format and the ACPI core can then treat the data as
    if Apple would follow the standard.
    
    Well, except for one small annoyance:  The properties returned by the
    _DSM only ever have one of two types, Integer or Buffer.  The former is
    retrievable as usual with device_property_read_u64(), but the latter is
    not part of the _DSD spec and it is not possible to retrieve Buffer
    properties with the device_property_read_*() functions due to the type
    checking performed in drivers/acpi/property.c.  It is however possible
    to retrieve them with acpi_dev_get_property().  Apple is using the
    Buffer type somewhat sloppily to store null-terminated strings but also
    integers.  The real data type is not distinguishable by the ACPI core
    and the onus is on the caller to use the contents of the Buffer in an
    appropriate way.
    
    In case Apple moves to _DSD in the future, this commit first checks for
    _DSD and falls back to _DSM only if _DSD is not found.
    
    Tested-by: default avatarRonald Tschalär <ronald@innovation.ch>
    Acked-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
    Reviewed-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
    Signed-off-by: default avatarLukas Wunner <lukas@wunner.de>
    Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
    899596e0