diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/Makefile | 1 | ||||
-rw-r--r-- | drivers/acpi/acpi_lpss.c | 3 | ||||
-rw-r--r-- | drivers/acpi/internal.h | 6 | ||||
-rw-r--r-- | drivers/acpi/osi.c | 37 | ||||
-rw-r--r-- | drivers/acpi/pci_root.c | 4 | ||||
-rw-r--r-- | drivers/acpi/pmic/intel_pmic_xpower.c | 21 | ||||
-rw-r--r-- | drivers/acpi/property.c | 6 | ||||
-rw-r--r-- | drivers/acpi/sbs.c | 25 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 7 | ||||
-rw-r--r-- | drivers/acpi/x86/apple.c | 141 | ||||
-rw-r--r-- | drivers/firmware/efi/apple-properties.c | 5 | ||||
-rw-r--r-- | drivers/pci/quirks.c | 5 | ||||
-rw-r--r-- | drivers/spi/spi.c | 32 | ||||
-rw-r--r-- | drivers/thunderbolt/icm.c | 13 | ||||
-rw-r--r-- | drivers/thunderbolt/tb.c | 4 |
15 files changed, 236 insertions, 74 deletions
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index b1aacfc62b1f..90265ab4437a 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -50,6 +50,7 @@ acpi-$(CONFIG_ACPI_REDUCED_HARDWARE_ONLY) += evged.o acpi-y += sysfs.o acpi-y += property.o acpi-$(CONFIG_X86) += acpi_cmos_rtc.o +acpi-$(CONFIG_X86) += x86/apple.o acpi-$(CONFIG_X86) += x86/utils.o acpi-$(CONFIG_DEBUG_FS) += debugfs.o acpi-$(CONFIG_ACPI_NUMA) += numa.o diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index f88caf5aab76..032ae44710e5 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -465,7 +465,8 @@ static int acpi_lpss_create_device(struct acpi_device *adev, acpi_dev_free_resource_list(&resource_list); if (!pdata->mmio_base) { - ret = -ENOMEM; + /* Skip the device, but continue the namespace scan. */ + ret = 0; goto err_out; } diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 3f5af4d7a739..4361c4415b4f 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -232,6 +232,12 @@ static inline void suspend_nvs_restore(void) {} void acpi_init_properties(struct acpi_device *adev); void acpi_free_properties(struct acpi_device *adev); +#ifdef CONFIG_X86 +void acpi_extract_apple_properties(struct acpi_device *adev); +#else +static inline void acpi_extract_apple_properties(struct acpi_device *adev) {} +#endif + /*-------------------------------------------------------------------------- Watchdog -------------------------------------------------------------------------- */ diff --git a/drivers/acpi/osi.c b/drivers/acpi/osi.c index 723bee58bbcf..19cdd8a783a9 100644 --- a/drivers/acpi/osi.c +++ b/drivers/acpi/osi.c @@ -27,6 +27,7 @@ #include <linux/kernel.h> #include <linux/acpi.h> #include <linux/dmi.h> +#include <linux/platform_data/x86/apple.h> #include "internal.h" @@ -257,12 +258,11 @@ bool acpi_osi_is_win8(void) } EXPORT_SYMBOL(acpi_osi_is_win8); -static void __init acpi_osi_dmi_darwin(bool enable, - const struct dmi_system_id *d) +static void __init acpi_osi_dmi_darwin(void) { - pr_notice("DMI detected to setup _OSI(\"Darwin\"): %s\n", d->ident); + pr_notice("DMI detected to setup _OSI(\"Darwin\"): Apple hardware\n"); osi_config.darwin_dmi = 1; - __acpi_osi_setup_darwin(enable); + __acpi_osi_setup_darwin(true); } static void __init acpi_osi_dmi_linux(bool enable, @@ -273,13 +273,6 @@ static void __init acpi_osi_dmi_linux(bool enable, __acpi_osi_setup_linux(enable); } -static int __init dmi_enable_osi_darwin(const struct dmi_system_id *d) -{ - acpi_osi_dmi_darwin(true, d); - - return 0; -} - static int __init dmi_enable_osi_linux(const struct dmi_system_id *d) { acpi_osi_dmi_linux(true, d); @@ -481,30 +474,16 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "1015PX"), }, }, - - /* - * Enable _OSI("Darwin") for all apple platforms. - */ - { - .callback = dmi_enable_osi_darwin, - .ident = "Apple hardware", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), - }, - }, - { - .callback = dmi_enable_osi_darwin, - .ident = "Apple hardware", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), - }, - }, {} }; static __init void acpi_osi_dmi_blacklisted(void) { dmi_check_system(acpi_osi_dmi_table); + + /* Enable _OSI("Darwin") for Apple platforms. */ + if (x86_apple_machine) + acpi_osi_dmi_darwin(); } int __init early_acpi_osi_init(void) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 9eec3095e6c3..6fc204a52493 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -33,6 +33,7 @@ #include <linux/acpi.h> #include <linux/slab.h> #include <linux/dmi.h> +#include <linux/platform_data/x86/apple.h> #include <acpi/apei.h> /* for acpi_hest_init() */ #include "internal.h" @@ -431,8 +432,7 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm) * been called successfully. We know the feature set supported by the * platform, so avoid calling _OSC at all */ - - if (dmi_match(DMI_SYS_VENDOR, "Apple Inc.")) { + if (x86_apple_machine) { root->osc_control_set = ~OSC_PCI_EXPRESS_PME_CONTROL; decode_osc_control(root, "OS assumes control of", root->osc_control_set); diff --git a/drivers/acpi/pmic/intel_pmic_xpower.c b/drivers/acpi/pmic/intel_pmic_xpower.c index 3b7d5be5b7ed..6c99d3f81095 100644 --- a/drivers/acpi/pmic/intel_pmic_xpower.c +++ b/drivers/acpi/pmic/intel_pmic_xpower.c @@ -27,6 +27,9 @@ #define GPI1_LDO_ON (3 << 0) #define GPI1_LDO_OFF (4 << 0) +#define AXP288_ADC_TS_PIN_GPADC 0xf2 +#define AXP288_ADC_TS_PIN_ON 0xf3 + static struct pmic_table power_table[] = { { .address = 0x00, @@ -209,11 +212,23 @@ static int intel_xpower_pmic_update_power(struct regmap *regmap, int reg, static int intel_xpower_pmic_get_raw_temp(struct regmap *regmap, int reg) { u8 buf[2]; + int ret; - if (regmap_bulk_read(regmap, AXP288_GP_ADC_H, buf, 2)) - return -EIO; + ret = regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, + AXP288_ADC_TS_PIN_GPADC); + if (ret) + return ret; + + /* After switching to the GPADC pin give things some time to settle */ + usleep_range(6000, 10000); + + ret = regmap_bulk_read(regmap, AXP288_GP_ADC_H, buf, 2); + if (ret == 0) + ret = (buf[0] << 4) + ((buf[1] >> 4) & 0x0f); + + regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON); - return (buf[0] << 4) + ((buf[1] >> 4) & 0x0F); + return ret; } static struct intel_pmic_opregion_data intel_xpower_pmic_opregion_data = { diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index 476a52c60cf3..09b7974b6c62 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -339,6 +339,9 @@ void acpi_init_properties(struct acpi_device *adev) INIT_LIST_HEAD(&adev->data.subnodes); + if (!adev->handle) + return; + /* * Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in * Device Tree compatible properties for this device. @@ -373,6 +376,9 @@ void acpi_init_properties(struct acpi_device *adev) if (acpi_of && !adev->flags.of_compatible_ok) acpi_handle_info(adev->handle, ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n"); + + if (!adev->data.pointer) + acpi_extract_apple_properties(adev); } static void acpi_destroy_nondev_subnodes(struct list_head *list) diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index ad0b13ad4bbb..a18463799ad7 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -31,7 +31,7 @@ #include <linux/jiffies.h> #include <linux/delay.h> #include <linux/power_supply.h> -#include <linux/dmi.h> +#include <linux/platform_data/x86/apple.h> #include "sbshc.h" #include "battery.h" @@ -58,8 +58,6 @@ static unsigned int cache_time = 1000; module_param(cache_time, uint, 0644); MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); -static bool sbs_manager_broken; - #define MAX_SBS_BAT 4 #define ACPI_SBS_BLOCK_MAX 32 @@ -632,31 +630,12 @@ static void acpi_sbs_callback(void *context) } } -static int disable_sbs_manager(const struct dmi_system_id *d) -{ - sbs_manager_broken = true; - return 0; -} - -static struct dmi_system_id acpi_sbs_dmi_table[] = { - { - .callback = disable_sbs_manager, - .ident = "Apple", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc.") - }, - }, - { }, -}; - static int acpi_sbs_add(struct acpi_device *device) { struct acpi_sbs *sbs; int result = 0; int id; - dmi_check_system(acpi_sbs_dmi_table); - sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL); if (!sbs) { result = -ENOMEM; @@ -677,7 +656,7 @@ static int acpi_sbs_add(struct acpi_device *device) result = 0; - if (!sbs_manager_broken) { + if (!x86_apple_machine) { result = acpi_manager_get_info(sbs); if (!result) { sbs->manager_present = 1; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 9288ce417c74..ac8a8a52ee4a 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -13,6 +13,7 @@ #include <linux/dmi.h> #include <linux/nls.h> #include <linux/dma-mapping.h> +#include <linux/platform_data/x86/apple.h> #include <asm/pgtable.h> @@ -1527,6 +1528,12 @@ static bool acpi_is_spi_i2c_slave(struct acpi_device *device) struct list_head resource_list; bool is_spi_i2c_slave = false; + /* Macs use device properties in lieu of _CRS resources */ + if (x86_apple_machine && + (fwnode_property_present(&device->fwnode, "spiSclkPeriod") || + fwnode_property_present(&device->fwnode, "i2cAddress"))) + return true; + INIT_LIST_HEAD(&resource_list); acpi_dev_get_resources(device, &resource_list, acpi_check_spi_i2c_slave, &is_spi_i2c_slave); diff --git a/drivers/acpi/x86/apple.c b/drivers/acpi/x86/apple.c new file mode 100644 index 000000000000..51b4cf9f25da --- /dev/null +++ b/drivers/acpi/x86/apple.c @@ -0,0 +1,141 @@ +/* + * apple.c - Apple ACPI quirks + * Copyright (C) 2017 Lukas Wunner <lukas@wunner.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2) as + * published by the Free Software Foundation. + */ + +#include <linux/acpi.h> +#include <linux/bitmap.h> +#include <linux/platform_data/x86/apple.h> +#include <linux/uuid.h> + +/* Apple _DSM device properties GUID */ +static const guid_t apple_prp_guid = + GUID_INIT(0xa0b5b7c6, 0x1318, 0x441c, + 0xb0, 0xc9, 0xfe, 0x69, 0x5e, 0xaf, 0x94, 0x9b); + +/** + * acpi_extract_apple_properties - retrieve and convert Apple _DSM properties + * @adev: ACPI device for which to retrieve the properties + * + * Invoke Apple's custom _DSM once to check the protocol version and once more + * to retrieve the properties. They are marshalled up in a single package as + * alternating key/value elements, unlike _DSD which stores them as a package + * of 2-element packages. Convert to _DSD format and make them available under + * the primary fwnode. + */ +void acpi_extract_apple_properties(struct acpi_device *adev) +{ + unsigned int i, j = 0, newsize = 0, numprops, numvalid; + union acpi_object *props, *newprops; + unsigned long *valid = NULL; + void *free_space; + + if (!x86_apple_machine) + return; + + props = acpi_evaluate_dsm_typed(adev->handle, &apple_prp_guid, 1, 0, + NULL, ACPI_TYPE_BUFFER); + if (!props) + return; + + if (!props->buffer.length) + goto out_free; + + if (props->buffer.pointer[0] != 3) { + acpi_handle_info(adev->handle, FW_INFO + "unsupported properties version %*ph\n", + props->buffer.length, props->buffer.pointer); + goto out_free; + } + + ACPI_FREE(props); + props = acpi_evaluate_dsm_typed(adev->handle, &apple_prp_guid, 1, 1, + NULL, ACPI_TYPE_PACKAGE); + if (!props) + return; + + numprops = props->package.count / 2; + if (!numprops) + goto out_free; + + valid = kcalloc(BITS_TO_LONGS(numprops), sizeof(long), GFP_KERNEL); + if (!valid) + goto out_free; + + /* newsize = key length + value length of each tuple */ + for (i = 0; i < numprops; i++) { + union acpi_object *key = &props->package.elements[i * 2]; + union acpi_object *val = &props->package.elements[i * 2 + 1]; + + if ( key->type != ACPI_TYPE_STRING || + (val->type != ACPI_TYPE_INTEGER && + val->type != ACPI_TYPE_BUFFER)) + continue; /* skip invalid properties */ + + __set_bit(i, valid); + newsize += key->string.length + 1; + if ( val->type == ACPI_TYPE_BUFFER) + newsize += val->buffer.length; + } + + numvalid = bitmap_weight(valid, numprops); + if (numprops > numvalid) + acpi_handle_info(adev->handle, FW_INFO + "skipped %u properties: wrong type\n", + numprops - numvalid); + if (numvalid == 0) + goto out_free; + + /* newsize += top-level package + 3 objects for each key/value tuple */ + newsize += (1 + 3 * numvalid) * sizeof(union acpi_object); + newprops = ACPI_ALLOCATE_ZEROED(newsize); + if (!newprops) + goto out_free; + + /* layout: top-level package | packages | key/value tuples | strings */ + newprops->type = ACPI_TYPE_PACKAGE; + newprops->package.count = numvalid; + newprops->package.elements = &newprops[1]; + free_space = &newprops[1 + 3 * numvalid]; + + for_each_set_bit(i, valid, numprops) { + union acpi_object *key = &props->package.elements[i * 2]; + union acpi_object *val = &props->package.elements[i * 2 + 1]; + unsigned int k = 1 + numvalid + j * 2; /* index into newprops */ + unsigned int v = k + 1; + + newprops[1 + j].type = ACPI_TYPE_PACKAGE; + newprops[1 + j].package.count = 2; + newprops[1 + j].package.elements = &newprops[k]; + + newprops[k].type = ACPI_TYPE_STRING; + newprops[k].string.length = key->string.length; + newprops[k].string.pointer = free_space; + memcpy(free_space, key->string.pointer, key->string.length); + free_space += key->string.length + 1; + + newprops[v].type = val->type; + if (val->type == ACPI_TYPE_INTEGER) { + newprops[v].integer.value = val->integer.value; + } else { + newprops[v].buffer.length = val->buffer.length; + newprops[v].buffer.pointer = free_space; + memcpy(free_space, val->buffer.pointer, + val->buffer.length); + free_space += val->buffer.length; + } + j++; /* count valid properties */ + } + WARN_ON(free_space != (void *)newprops + newsize); + + adev->data.properties = newprops; + adev->data.pointer = newprops; + +out_free: + ACPI_FREE(props); + kfree(valid); +} diff --git a/drivers/firmware/efi/apple-properties.c b/drivers/firmware/efi/apple-properties.c index c473f4c5ca34..9f6bcf173b0e 100644 --- a/drivers/firmware/efi/apple-properties.c +++ b/drivers/firmware/efi/apple-properties.c @@ -18,8 +18,8 @@ #define pr_fmt(fmt) "apple-properties: " fmt #include <linux/bootmem.h> -#include <linux/dmi.h> #include <linux/efi.h> +#include <linux/platform_data/x86/apple.h> #include <linux/property.h> #include <linux/slab.h> #include <linux/ucs2_string.h> @@ -191,8 +191,7 @@ static int __init map_properties(void) u64 pa_data; int ret; - if (!dmi_match(DMI_SYS_VENDOR, "Apple Inc.") && - !dmi_match(DMI_SYS_VENDOR, "Apple Computer, Inc.")) + if (!x86_apple_machine) return 0; pa_data = boot_params.hdr.setup_data; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 140760403f36..a346487a9532 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -25,6 +25,7 @@ #include <linux/sched.h> #include <linux/ktime.h> #include <linux/mm.h> +#include <linux/platform_data/x86/apple.h> #include <asm/dma.h> /* isa_dma_bridge_buggy */ #include "pci.h" @@ -3447,7 +3448,7 @@ static void quirk_apple_poweroff_thunderbolt(struct pci_dev *dev) { acpi_handle bridge, SXIO, SXFP, SXLV; - if (!dmi_match(DMI_BOARD_VENDOR, "Apple Inc.")) + if (!x86_apple_machine) return; if (pci_pcie_type(dev) != PCI_EXP_TYPE_UPSTREAM) return; @@ -3492,7 +3493,7 @@ static void quirk_apple_wait_for_thunderbolt(struct pci_dev *dev) struct pci_dev *sibling = NULL; struct pci_dev *nhi = NULL; - if (!dmi_match(DMI_BOARD_VENDOR, "Apple Inc.")) + if (!x86_apple_machine) return; if (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM) return; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 4fcbb0aa71d3..7d920ea19957 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -40,6 +40,7 @@ #include <linux/ioport.h> #include <linux/acpi.h> #include <linux/highmem.h> +#include <linux/platform_data/x86/apple.h> #define CREATE_TRACE_POINTS #include <trace/events/spi.h> @@ -1693,6 +1694,35 @@ static void of_register_spi_devices(struct spi_controller *ctlr) { } #endif #ifdef CONFIG_ACPI +static void acpi_spi_parse_apple_properties(struct spi_device *spi) +{ + struct acpi_device *dev = ACPI_COMPANION(&spi->dev); + const union acpi_object *obj; + + if (!x86_apple_machine) + return; + + if (!acpi_dev_get_property(dev, "spiSclkPeriod", ACPI_TYPE_BUFFER, &obj) + && obj->buffer.length >= 4) + spi->max_speed_hz = NSEC_PER_SEC / *(u32 *)obj->buffer.pointer; + + if (!acpi_dev_get_property(dev, "spiWordSize", ACPI_TYPE_BUFFER, &obj) + && obj->buffer.length == 8) + spi->bits_per_word = *(u64 *)obj->buffer.pointer; + + if (!acpi_dev_get_property(dev, "spiBitOrder", ACPI_TYPE_BUFFER, &obj) + && obj->buffer.length == 8 && !*(u64 *)obj->buffer.pointer) + spi->mode |= SPI_LSB_FIRST; + + if (!acpi_dev_get_property(dev, "spiSPO", ACPI_TYPE_BUFFER, &obj) + && obj->buffer.length == 8 && *(u64 *)obj->buffer.pointer) + spi->mode |= SPI_CPOL; + + if (!acpi_dev_get_property(dev, "spiSPH", ACPI_TYPE_BUFFER, &obj) + && obj->buffer.length == 8 && *(u64 *)obj->buffer.pointer) + spi->mode |= SPI_CPHA; +} + static int acpi_spi_add_resource(struct acpi_resource *ares, void *data) { struct spi_device *spi = data; @@ -1766,6 +1796,8 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr, acpi_spi_add_resource, spi); acpi_dev_free_resource_list(&resource_list); + acpi_spi_parse_apple_properties(spi); + if (ret < 0 || !spi->max_speed_hz) { spi_dev_put(spi); return AE_OK; diff --git a/drivers/thunderbolt/icm.c b/drivers/thunderbolt/icm.c index bdaac1ff00a5..53250fc057e1 100644 --- a/drivers/thunderbolt/icm.c +++ b/drivers/thunderbolt/icm.c @@ -13,9 +13,9 @@ */ #include <linux/delay.h> -#include <linux/dmi.h> #include <linux/mutex.h> #include <linux/pci.h> +#include <linux/platform_data/x86/apple.h> #include <linux/sizes.h> #include <linux/slab.h> #include <linux/workqueue.h> @@ -102,11 +102,6 @@ static inline u64 get_route(u32 route_hi, u32 route_lo) return (u64)route_hi << 32 | route_lo; } -static inline bool is_apple(void) -{ - return dmi_match(DMI_BOARD_VENDOR, "Apple Inc."); -} - static bool icm_match(const struct tb_cfg_request *req, const struct ctl_pkg *pkg) { @@ -176,7 +171,7 @@ static int icm_request(struct tb *tb, const void *request, size_t request_size, static bool icm_fr_is_supported(struct tb *tb) { - return !is_apple(); + return !x86_apple_machine; } static inline int icm_fr_get_switch_index(u32 port) @@ -517,7 +512,7 @@ static bool icm_ar_is_supported(struct tb *tb) * Starting from Alpine Ridge we can use ICM on Apple machines * as well. We just need to reset and re-enable it first. */ - if (!is_apple()) + if (!x86_apple_machine) return true; /* @@ -1011,7 +1006,7 @@ static int icm_start(struct tb *tb) * don't provide images publicly either. To be on the safe side * prevent root switch NVM upgrade on Macs for now. */ - tb->root_switch->no_nvm_upgrade = is_apple(); + tb->root_switch->no_nvm_upgrade = x86_apple_machine; ret = tb_switch_add(tb->root_switch); if (ret) diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index 1b02ca0b6129..0b22ad9d68b4 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -7,7 +7,7 @@ #include <linux/slab.h> #include <linux/errno.h> #include <linux/delay.h> -#include <linux/dmi.h> +#include <linux/platform_data/x86/apple.h> #include "tb.h" #include "tb_regs.h" @@ -453,7 +453,7 @@ struct tb *tb_probe(struct tb_nhi *nhi) struct tb_cm *tcm; struct tb *tb; - if (!dmi_match(DMI_BOARD_VENDOR, "Apple Inc.")) + if (!x86_apple_machine) return NULL; tb = tb_domain_alloc(nhi, sizeof(*tcm)); |