* acpi-x86: ACPI / boot: Add number of legacy IRQs to debug output ACPI / boot: Correct address space of __acpi_map_table() ACPI / boot: Don't define unused variables * acpi-soc: ACPI / LPSS: Don't abort ACPI scan on missing mem resource * acpi-pmic: ACPI / PMIC: xpower: Do pinswitch magic when reading GPADC * acpi-apple: spi: Use Apple device properties in absence of ACPI resources ACPI / scan: Recognize Apple SPI and I2C slaves ACPI / property: Support Apple _DSM properties ACPI / property: Don't evaluate objects for devices w/o handle treewide: Consolidate Apple DMI checks
Unified · Split
| @@ -95,7 +95,7 @@ static int __init dt_scan_depth1_nodes(unsigned long node, · 94 unmodified lines | ||
| 95 | 95 | * __acpi_map_table() will be called before page_init(), so early_ioremap() |
| 96 | 96 | * or early_memremap() should be called here to for ACPI table mapping. |
| 97 | 97 | */ |
| 98 | −char *__init __acpi_map_table(unsigned long phys, unsigned long size) | |
| 98 | +void __init __iomem *__acpi_map_table(unsigned long phys, unsigned long size) | |
| 99 | 99 | { |
| 100 | 100 | if (!size) |
| 101 | 101 | return NULL; |
| @@ -103,7 +103,7 @@ char *__init __acpi_map_table(unsigned long phys, unsigned long size) · 1 unmodified line | ||
| 103 | 103 | return early_memremap(phys, size); |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | −void __init __acpi_unmap_table(char *map, unsigned long size) | |
| 106 | +void __init __acpi_unmap_table(void __iomem *map, unsigned long size) | |
| 107 | 107 | { |
| 108 | 108 | if (!map || !size) |
| 109 | 109 | return; |
| @@ -159,12 +159,12 @@ int acpi_request_vector(u32 int_type) · 158 unmodified lines | ||
| 159 | 159 | return vector; |
| 160 | 160 | } |
| 161 | 161 | |
| 162 | −char *__init __acpi_map_table(unsigned long phys_addr, unsigned long size) | |
| 162 | +void __init __iomem *__acpi_map_table(unsigned long phys, unsigned long size) | |
| 163 | 163 | { |
| 164 | − return __va(phys_addr); | |
| 164 | + return __va(phys); | |
| 165 | 165 | } |
| 166 | 166 | |
| 167 | −void __init __acpi_unmap_table(char *map, unsigned long size) | |
| 167 | +void __init __acpi_unmap_table(void __iomem *map, unsigned long size) | |
| 168 | 168 | { |
| 169 | 169 | } |
| 170 | 170 | |
| @@ -39,6 +39,7 @@ static inline void vsmp_init(void) { } · 38 unmodified lines | ||
| 39 | 39 | #endif |
| 40 | 40 | |
| 41 | 41 | void setup_bios_corruption_check(void); |
| 42 | +void early_platform_quirks(void); | |
| 42 | 43 | |
| 43 | 44 | extern unsigned long saved_video_mode; |
| 44 | 45 | |
| @@ -118,7 +118,7 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = { · 117 unmodified lines | ||
| 118 | 118 | * This is just a simple wrapper around early_ioremap(), |
| 119 | 119 | * with sanity checks for phys == 0 and size == 0. |
| 120 | 120 | */ |
| 121 | −char *__init __acpi_map_table(unsigned long phys, unsigned long size) | |
| 121 | +void __init __iomem *__acpi_map_table(unsigned long phys, unsigned long size) | |
| 122 | 122 | { |
| 123 | 123 | |
| 124 | 124 | if (!phys || !size) |
| @@ -127,7 +127,7 @@ char *__init __acpi_map_table(unsigned long phys, unsigned long size) · 2 unmodified lines | ||
| 127 | 127 | return early_ioremap(phys, size); |
| 128 | 128 | } |
| 129 | 129 | |
| 130 | −void __init __acpi_unmap_table(char *map, unsigned long size) | |
| 130 | +void __init __acpi_unmap_table(void __iomem *map, unsigned long size) | |
| 131 | 131 | { |
| 132 | 132 | if (!map || !size) |
| 133 | 133 | return; |
| @@ -199,8 +199,10 @@ static int __init · 65 unmodified lines | ||
| 199 | 199 | acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end) |
| 200 | 200 | { |
| 201 | 201 | struct acpi_madt_local_x2apic *processor = NULL; |
| 202 | +#ifdef CONFIG_X86_X2APIC | |
| 202 | 203 | int apic_id; |
| 203 | 204 | u8 enabled; |
| 205 | +#endif | |
| 204 | 206 | |
| 205 | 207 | processor = (struct acpi_madt_local_x2apic *)header; |
| 206 | 208 | |
| @@ -209,9 +211,10 @@ acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end) · 2 unmodified lines | ||
| 209 | 211 | |
| 210 | 212 | acpi_table_print_madt_entry(header); |
| 211 | 213 | |
| 214 | +#ifdef CONFIG_X86_X2APIC | |
| 212 | 215 | apic_id = processor->local_apic_id; |
| 213 | 216 | enabled = processor->lapic_flags & ACPI_MADT_ENABLED; |
| 214 | −#ifdef CONFIG_X86_X2APIC | |
| 217 | + | |
| 215 | 218 | /* |
| 216 | 219 | * We need to register disabled CPU as well to permit |
| 217 | 220 | * counting disabled CPUs. This allows us to size |
| @@ -1083,7 +1086,7 @@ static void __init mp_config_acpi_legacy_irqs(void) · 865 unmodified lines | ||
| 1083 | 1086 | mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA; |
| 1084 | 1087 | #endif |
| 1085 | 1088 | set_bit(MP_ISA_BUS, mp_bus_not_pci); |
| 1086 | − pr_debug("Bus #%d is ISA\n", MP_ISA_BUS); | |
| 1089 | + pr_debug("Bus #%d is ISA (nIRQs: %d)\n", MP_ISA_BUS, nr_legacy_irqs()); | |
| 1087 | 1090 | |
| 1088 | 1091 | /* |
| 1089 | 1092 | * Use the default configuration for the IRQs 0-15. Unless |
| @@ -12,10 +12,10 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <linux/pci.h> |
| 13 | 13 | #include <linux/acpi.h> |
| 14 | 14 | #include <linux/delay.h> |
| 15 | −#include <linux/dmi.h> | |
| 16 | 15 | #include <linux/pci_ids.h> |
| 17 | 16 | #include <linux/bcma/bcma.h> |
| 18 | 17 | #include <linux/bcma/bcma_regs.h> |
| 18 | +#include <linux/platform_data/x86/apple.h> | |
| 19 | 19 | #include <drm/i915_drm.h> |
| 20 | 20 | #include <asm/pci-direct.h> |
| 21 | 21 | #include <asm/dma.h> |
| @@ -593,7 +593,7 @@ static void __init apple_airport_reset(int bus, int slot, int func) · 571 unmodified lines | ||
| 593 | 593 | u64 addr; |
| 594 | 594 | int i; |
| 595 | 595 | |
| 596 | − if (!dmi_match(DMI_SYS_VENDOR, "Apple Inc.")) | |
| 596 | + if (!x86_apple_machine) | |
| 597 | 597 | return; |
| 598 | 598 | |
| 599 | 599 | /* Card may have been put into PCI_D3hot by grub quirk */ |
| @@ -1,6 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * This file contains work-arounds for x86 and x86_64 platform bugs. |
| 3 | 3 | */ |
| 4 | +#include <linux/dmi.h> | |
| 4 | 5 | #include <linux/pci.h> |
| 5 | 6 | #include <linux/irq.h> |
| 6 | 7 | |
| @@ -656,3 +657,12 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fc0, quirk_intel_brickland_xeon_ · 649 unmodified lines | ||
| 656 | 657 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2083, quirk_intel_purley_xeon_ras_cap); |
| 657 | 658 | #endif |
| 658 | 659 | #endif |
| 660 | + | |
| 661 | +bool x86_apple_machine; | |
| 662 | +EXPORT_SYMBOL(x86_apple_machine); | |
| 663 | + | |
| 664 | +void __init early_platform_quirks(void) | |
| 665 | +{ | |
| 666 | + x86_apple_machine = dmi_match(DMI_SYS_VENDOR, "Apple Inc.") || | |
| 667 | + dmi_match(DMI_SYS_VENDOR, "Apple Computer, Inc."); | |
| 668 | +} | |
| @@ -1206,6 +1206,8 @@ void __init setup_arch(char **cmdline_p) · 1205 unmodified lines | ||
| 1206 | 1206 | |
| 1207 | 1207 | io_delay_init(); |
| 1208 | 1208 | |
| 1209 | + early_platform_quirks(); | |
| 1210 | + | |
| 1209 | 1211 | /* |
| 1210 | 1212 | * Parse the ACPI tables for possible boot-time SMP configuration. |
| 1211 | 1213 | */ |
| @@ -50,6 +50,7 @@ acpi-$(CONFIG_ACPI_REDUCED_HARDWARE_ONLY) += evged.o · 49 unmodified lines | ||
| 50 | 50 | acpi-y += sysfs.o |
| 51 | 51 | acpi-y += property.o |
| 52 | 52 | acpi-$(CONFIG_X86) += acpi_cmos_rtc.o |
| 53 | +acpi-$(CONFIG_X86) += x86/apple.o | |
| 53 | 54 | acpi-$(CONFIG_X86) += x86/utils.o |
| 54 | 55 | acpi-$(CONFIG_DEBUG_FS) += debugfs.o |
| 55 | 56 | acpi-$(CONFIG_ACPI_NUMA) += numa.o |
| @@ -465,7 +465,8 @@ static int acpi_lpss_create_device(struct acpi_device *adev, · 464 unmodified lines | ||
| 465 | 465 | acpi_dev_free_resource_list(&resource_list); |
| 466 | 466 | |
| 467 | 467 | if (!pdata->mmio_base) { |
| 468 | − ret = -ENOMEM; | |
| 468 | + /* Skip the device, but continue the namespace scan. */ | |
| 469 | + ret = 0; | |
| 469 | 470 | goto err_out; |
| 470 | 471 | } |
| 471 | 472 | |
| @@ -232,6 +232,12 @@ static inline void suspend_nvs_restore(void) {} · 231 unmodified lines | ||
| 232 | 232 | void acpi_init_properties(struct acpi_device *adev); |
| 233 | 233 | void acpi_free_properties(struct acpi_device *adev); |
| 234 | 234 | |
| 235 | +#ifdef CONFIG_X86 | |
| 236 | +void acpi_extract_apple_properties(struct acpi_device *adev); | |
| 237 | +#else | |
| 238 | +static inline void acpi_extract_apple_properties(struct acpi_device *adev) {} | |
| 239 | +#endif | |
| 240 | + | |
| 235 | 241 | /*-------------------------------------------------------------------------- |
| 236 | 242 | Watchdog |
| 237 | 243 | -------------------------------------------------------------------------- */ |
| @@ -27,6 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | #include <linux/kernel.h> |
| 28 | 28 | #include <linux/acpi.h> |
| 29 | 29 | #include <linux/dmi.h> |
| 30 | +#include <linux/platform_data/x86/apple.h> | |
| 30 | 31 | |
| 31 | 32 | #include "internal.h" |
| 32 | 33 | |
| @@ -257,12 +258,11 @@ bool acpi_osi_is_win8(void) · 224 unmodified lines | ||
| 257 | 258 | } |
| 258 | 259 | EXPORT_SYMBOL(acpi_osi_is_win8); |
| 259 | 260 | |
| 260 | −static void __init acpi_osi_dmi_darwin(bool enable, | |
| 261 | − const struct dmi_system_id *d) | |
| 261 | +static void __init acpi_osi_dmi_darwin(void) | |
| 262 | 262 | { |
| 263 | − pr_notice("DMI detected to setup _OSI(\"Darwin\"): %s\n", d->ident); | |
| 263 | + pr_notice("DMI detected to setup _OSI(\"Darwin\"): Apple hardware\n"); | |
| 264 | 264 | osi_config.darwin_dmi = 1; |
| 265 | − __acpi_osi_setup_darwin(enable); | |
| 265 | + __acpi_osi_setup_darwin(true); | |
| 266 | 266 | } |
| 267 | 267 | |
| 268 | 268 | static void __init acpi_osi_dmi_linux(bool enable, |
| @@ -273,13 +273,6 @@ static void __init acpi_osi_dmi_linux(bool enable, · 4 unmodified lines | ||
| 273 | 273 | __acpi_osi_setup_linux(enable); |
| 274 | 274 | } |
| 275 | 275 | |
| 276 | −static int __init dmi_enable_osi_darwin(const struct dmi_system_id *d) | |
| 277 | −{ | |
| 278 | − acpi_osi_dmi_darwin(true, d); | |
| 279 | − | |
| 280 | − return 0; | |
| 281 | −} | |
| 282 | − | |
| 283 | 276 | static int __init dmi_enable_osi_linux(const struct dmi_system_id *d) |
| 284 | 277 | { |
| 285 | 278 | acpi_osi_dmi_linux(true, d); |
| @@ -481,30 +474,16 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { · 195 unmodified lines | ||
| 481 | 474 | DMI_MATCH(DMI_PRODUCT_NAME, "1015PX"), |
| 482 | 475 | }, |
| 483 | 476 | }, |
| 484 | − | |
| 485 | − /* | |
| 486 | − * Enable _OSI("Darwin") for all apple platforms. | |
| 487 | − */ | |
| 488 | − { | |
| 489 | − .callback = dmi_enable_osi_darwin, | |
| 490 | − .ident = "Apple hardware", | |
| 491 | − .matches = { | |
| 492 | − DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | |
| 493 | − }, | |
| 494 | − }, | |
| 495 | − { | |
| 496 | − .callback = dmi_enable_osi_darwin, | |
| 497 | − .ident = "Apple hardware", | |
| 498 | − .matches = { | |
| 499 | − DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), | |
| 500 | − }, | |
| 501 | − }, | |
| 502 | 477 | {} |
| 503 | 478 | }; |
| 504 | 479 | |
| 505 | 480 | static __init void acpi_osi_dmi_blacklisted(void) |
| 506 | 481 | { |
| 507 | 482 | dmi_check_system(acpi_osi_dmi_table); |
| 483 | + | |
| 484 | + /* Enable _OSI("Darwin") for Apple platforms. */ | |
| 485 | + if (x86_apple_machine) | |
| 486 | + acpi_osi_dmi_darwin(); | |
| 508 | 487 | } |
| 509 | 488 | |
| 510 | 489 | int __init early_acpi_osi_init(void) |
| @@ -33,6 +33,7 @@ · 32 unmodified lines | ||
| 33 | 33 | #include <linux/acpi.h> |
| 34 | 34 | #include <linux/slab.h> |
| 35 | 35 | #include <linux/dmi.h> |
| 36 | +#include <linux/platform_data/x86/apple.h> | |
| 36 | 37 | #include <acpi/apei.h> /* for acpi_hest_init() */ |
| 37 | 38 | |
| 38 | 39 | #include "internal.h" |
| @@ -431,8 +432,7 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm) · 392 unmodified lines | ||
| 431 | 432 | * been called successfully. We know the feature set supported by the |
| 432 | 433 | * platform, so avoid calling _OSC at all |
| 433 | 434 | */ |
| 434 | − | |
| 435 | − if (dmi_match(DMI_SYS_VENDOR, "Apple Inc.")) { | |
| 435 | + if (x86_apple_machine) { | |
| 436 | 436 | root->osc_control_set = ~OSC_PCI_EXPRESS_PME_CONTROL; |
| 437 | 437 | decode_osc_control(root, "OS assumes control of", |
| 438 | 438 | root->osc_control_set); |
| @@ -27,6 +27,9 @@ · 26 unmodified lines | ||
| 27 | 27 | #define GPI1_LDO_ON (3 << 0) |
| 28 | 28 | #define GPI1_LDO_OFF (4 << 0) |
| 29 | 29 | |
| 30 | +#define AXP288_ADC_TS_PIN_GPADC 0xf2 | |
| 31 | +#define AXP288_ADC_TS_PIN_ON 0xf3 | |
| 32 | + | |
| 30 | 33 | static struct pmic_table power_table[] = { |
| 31 | 34 | { |
| 32 | 35 | .address = 0x00, |
| @@ -209,11 +212,23 @@ static int intel_xpower_pmic_update_power(struct regmap *regmap, int reg, · 176 unmodified lines | ||
| 209 | 212 | static int intel_xpower_pmic_get_raw_temp(struct regmap *regmap, int reg) |
| 210 | 213 | { |
| 211 | 214 | u8 buf[2]; |
| 215 | + int ret; | |
| 212 | 216 | |
| 213 | − if (regmap_bulk_read(regmap, AXP288_GP_ADC_H, buf, 2)) | |
| 214 | − return -EIO; | |
| 217 | + ret = regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, | |
| 218 | + AXP288_ADC_TS_PIN_GPADC); | |
| 219 | + if (ret) | |
| 220 | + return ret; | |
| 221 | + | |
| 222 | + /* After switching to the GPADC pin give things some time to settle */ | |
| 223 | + usleep_range(6000, 10000); | |
| 224 | + | |
| 225 | + ret = regmap_bulk_read(regmap, AXP288_GP_ADC_H, buf, 2); | |
| 226 | + if (ret == 0) | |
| 227 | + ret = (buf[0] << 4) + ((buf[1] >> 4) & 0x0f); | |
| 228 | + | |
| 229 | + regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON); | |
| 215 | 230 | |
| 216 | − return (buf[0] << 4) + ((buf[1] >> 4) & 0x0F); | |
| 231 | + return ret; | |
| 217 | 232 | } |
| 218 | 233 | |
| 219 | 234 | static struct intel_pmic_opregion_data intel_xpower_pmic_opregion_data = { |
| @@ -339,6 +339,9 @@ void acpi_init_properties(struct acpi_device *adev) · 338 unmodified lines | ||
| 339 | 339 | |
| 340 | 340 | INIT_LIST_HEAD(&adev->data.subnodes); |
| 341 | 341 | |
| 342 | + if (!adev->handle) | |
| 343 | + return; | |
| 344 | + | |
| 342 | 345 | /* |
| 343 | 346 | * Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in |
| 344 | 347 | * Device Tree compatible properties for this device. |
| @@ -373,6 +376,9 @@ void acpi_init_properties(struct acpi_device *adev) · 28 unmodified lines | ||
| 373 | 376 | if (acpi_of && !adev->flags.of_compatible_ok) |
| 374 | 377 | acpi_handle_info(adev->handle, |
| 375 | 378 | ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n"); |
| 379 | + | |
| 380 | + if (!adev->data.pointer) | |
| 381 | + acpi_extract_apple_properties(adev); | |
| 376 | 382 | } |
| 377 | 383 | |
| 378 | 384 | static void acpi_destroy_nondev_subnodes(struct list_head *list) |
| @@ -31,7 +31,7 @@ · 30 unmodified lines | ||
| 31 | 31 | #include <linux/jiffies.h> |
| 32 | 32 | #include <linux/delay.h> |
| 33 | 33 | #include <linux/power_supply.h> |
| 34 | −#include <linux/dmi.h> | |
| 34 | +#include <linux/platform_data/x86/apple.h> | |
| 35 | 35 | |
| 36 | 36 | #include "sbshc.h" |
| 37 | 37 | #include "battery.h" |
| @@ -58,8 +58,6 @@ static unsigned int cache_time = 1000; · 20 unmodified lines | ||
| 58 | 58 | module_param(cache_time, uint, 0644); |
| 59 | 59 | MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); |
| 60 | 60 | |
| 61 | −static bool sbs_manager_broken; | |
| 62 | − | |
| 63 | 61 | #define MAX_SBS_BAT 4 |
| 64 | 62 | #define ACPI_SBS_BLOCK_MAX 32 |
| 65 | 63 | |
| @@ -632,31 +630,12 @@ static void acpi_sbs_callback(void *context) · 566 unmodified lines | ||
| 632 | 630 | } |
| 633 | 631 | } |
| 634 | 632 | |
| 635 | −static int disable_sbs_manager(const struct dmi_system_id *d) | |
| 636 | −{ | |
| 637 | − sbs_manager_broken = true; | |
| 638 | − return 0; | |
| 639 | −} | |
| 640 | − | |
| 641 | −static struct dmi_system_id acpi_sbs_dmi_table[] = { | |
| 642 | − { | |
| 643 | − .callback = disable_sbs_manager, | |
| 644 | − .ident = "Apple", | |
| 645 | − .matches = { | |
| 646 | − DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc.") | |
| 647 | − }, | |
| 648 | − }, | |
| 649 | − { }, | |
| 650 | −}; | |
| 651 | − | |
| 652 | 633 | static int acpi_sbs_add(struct acpi_device *device) |
| 653 | 634 | { |
| 654 | 635 | struct acpi_sbs *sbs; |
| 655 | 636 | int result = 0; |
| 656 | 637 | int id; |
| 657 | 638 | |
| 658 | − dmi_check_system(acpi_sbs_dmi_table); | |
| 659 | − | |
| 660 | 639 | sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL); |
| 661 | 640 | if (!sbs) { |
| 662 | 641 | result = -ENOMEM; |
| @@ -677,7 +656,7 @@ static int acpi_sbs_add(struct acpi_device *device) · 14 unmodified lines | ||
| 677 | 656 | |
| 678 | 657 | result = 0; |
| 679 | 658 | |
| 680 | − if (!sbs_manager_broken) { | |
| 659 | + if (!x86_apple_machine) { | |
| 681 | 660 | result = acpi_manager_get_info(sbs); |
| 682 | 661 | if (!result) { |
| 683 | 662 | sbs->manager_present = 1; |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/dmi.h> |
| 14 | 14 | #include <linux/nls.h> |
| 15 | 15 | #include <linux/dma-mapping.h> |
| 16 | +#include <linux/platform_data/x86/apple.h> | |
| 16 | 17 | |
| 17 | 18 | #include <asm/pgtable.h> |
| 18 | 19 | |
| @@ -1527,6 +1528,12 @@ static bool acpi_is_spi_i2c_slave(struct acpi_device *device) · 1508 unmodified lines | ||
| 1527 | 1528 | struct list_head resource_list; |
| 1528 | 1529 | bool is_spi_i2c_slave = false; |
| 1529 | 1530 | |
| 1531 | + /* Macs use device properties in lieu of _CRS resources */ | |
| 1532 | + if (x86_apple_machine && | |
| 1533 | + (fwnode_property_present(&device->fwnode, "spiSclkPeriod") || | |
| 1534 | + fwnode_property_present(&device->fwnode, "i2cAddress"))) | |
| 1535 | + return true; | |
| 1536 | + | |
| 1530 | 1537 | INIT_LIST_HEAD(&resource_list); |
| 1531 | 1538 | acpi_dev_get_resources(device, &resource_list, acpi_check_spi_i2c_slave, |
| 1532 | 1539 | &is_spi_i2c_slave); |
| @@ -0,0 +1,141 @@ | ||
| 1 | +/* | |
| 2 | + * apple.c - Apple ACPI quirks | |
| 3 | + * Copyright (C) 2017 Lukas Wunner <lukas@wunner.de> | |
| 4 | + * | |
| 5 | + * This program is free software; you can redistribute it and/or modify | |
| 6 | + * it under the terms of the GNU General Public License (version 2) as | |
| 7 | + * published by the Free Software Foundation. | |
| 8 | + */ | |
| 9 | + | |
| 10 | +#include <linux/acpi.h> | |
| 11 | +#include <linux/bitmap.h> | |
| 12 | +#include <linux/platform_data/x86/apple.h> | |
| 13 | +#include <linux/uuid.h> | |
| 14 | + | |
| 15 | +/* Apple _DSM device properties GUID */ | |
| 16 | +static const guid_t apple_prp_guid = | |
| 17 | + GUID_INIT(0xa0b5b7c6, 0x1318, 0x441c, | |
| 18 | + 0xb0, 0xc9, 0xfe, 0x69, 0x5e, 0xaf, 0x94, 0x9b); | |
| 19 | + | |
| 20 | +/** | |
| 21 | + * acpi_extract_apple_properties - retrieve and convert Apple _DSM properties | |
| 22 | + * @adev: ACPI device for which to retrieve the properties | |
| 23 | + * | |
| 24 | + * Invoke Apple's custom _DSM once to check the protocol version and once more | |
| 25 | + * to retrieve the properties. They are marshalled up in a single package as | |
| 26 | + * alternating key/value elements, unlike _DSD which stores them as a package | |
| 27 | + * of 2-element packages. Convert to _DSD format and make them available under | |
| 28 | + * the primary fwnode. | |
| 29 | + */ | |
| 30 | +void acpi_extract_apple_properties(struct acpi_device *adev) | |
| 31 | +{ | |
| 32 | + unsigned int i, j = 0, newsize = 0, numprops, numvalid; | |
| 33 | + union acpi_object *props, *newprops; | |
| 34 | + unsigned long *valid = NULL; | |
| 35 | + void *free_space; | |
| 36 | + | |
| 37 | + if (!x86_apple_machine) | |
| 38 | + return; | |
| 39 | + | |
| 40 | + props = acpi_evaluate_dsm_typed(adev->handle, &apple_prp_guid, 1, 0, | |
| 41 | + NULL, ACPI_TYPE_BUFFER); | |
| 42 | + if (!props) | |
| 43 | + return; | |
| 44 | + | |
| 45 | + if (!props->buffer.length) | |
| 46 | + goto out_free; | |
| 47 | + | |
| 48 | + if (props->buffer.pointer[0] != 3) { | |
| 49 | + acpi_handle_info(adev->handle, FW_INFO | |
| 50 | + "unsupported properties version %*ph\n", | |
| 51 | + props->buffer.length, props->buffer.pointer); | |
| 52 | + goto out_free; | |
| 53 | + } | |
| 54 | + | |
| 55 | + ACPI_FREE(props); | |
| 56 | + props = acpi_evaluate_dsm_typed(adev->handle, &apple_prp_guid, 1, 1, | |
| 57 | + NULL, ACPI_TYPE_PACKAGE); | |
| 58 | + if (!props) | |
| 59 | + return; | |
| 60 | + | |
| 61 | + numprops = props->package.count / 2; | |
| 62 | + if (!numprops) | |
| 63 | + goto out_free; | |
| 64 | + | |
| 65 | + valid = kcalloc(BITS_TO_LONGS(numprops), sizeof(long), GFP_KERNEL); | |
| 66 | + if (!valid) | |
| 67 | + goto out_free; | |
| 68 | + | |
| 69 | + /* newsize = key length + value length of each tuple */ | |
| 70 | + for (i = 0; i < numprops; i++) { | |
| 71 | + union acpi_object *key = &props->package.elements[i * 2]; | |
| 72 | + union acpi_object *val = &props->package.elements[i * 2 + 1]; | |
| 73 | + | |
| 74 | + if ( key->type != ACPI_TYPE_STRING || | |
| 75 | + (val->type != ACPI_TYPE_INTEGER && | |
| 76 | + val->type != ACPI_TYPE_BUFFER)) | |
| 77 | + continue; /* skip invalid properties */ | |
| 78 | + | |
| 79 | + __set_bit(i, valid); | |
| 80 | + newsize += key->string.length + 1; | |
| 81 | + if ( val->type == ACPI_TYPE_BUFFER) | |
| 82 | + newsize += val->buffer.length; | |
| 83 | + } | |
| 84 | + | |
| 85 | + numvalid = bitmap_weight(valid, numprops); | |
| 86 | + if (numprops > numvalid) | |
| 87 | + acpi_handle_info(adev->handle, FW_INFO | |
| 88 | + "skipped %u properties: wrong type\n", | |
| 89 | + numprops - numvalid); | |
| 90 | + if (numvalid == 0) | |
| 91 | + goto out_free; | |
| 92 | + | |
| 93 | + /* newsize += top-level package + 3 objects for each key/value tuple */ | |
| 94 | + newsize += (1 + 3 * numvalid) * sizeof(union acpi_object); | |
| 95 | + newprops = ACPI_ALLOCATE_ZEROED(newsize); | |
| 96 | + if (!newprops) | |
| 97 | + goto out_free; | |
| 98 | + | |
| 99 | + /* layout: top-level package | packages | key/value tuples | strings */ | |
| 100 | + newprops->type = ACPI_TYPE_PACKAGE; | |
| 101 | + newprops->package.count = numvalid; | |
| 102 | + newprops->package.elements = &newprops[1]; | |
| 103 | + free_space = &newprops[1 + 3 * numvalid]; | |
| 104 | + | |
| 105 | + for_each_set_bit(i, valid, numprops) { | |
| 106 | + union acpi_object *key = &props->package.elements[i * 2]; | |
| 107 | + union acpi_object *val = &props->package.elements[i * 2 + 1]; | |
| 108 | + unsigned int k = 1 + numvalid + j * 2; /* index into newprops */ | |
| 109 | + unsigned int v = k + 1; | |
| 110 | + | |
| 111 | + newprops[1 + j].type = ACPI_TYPE_PACKAGE; | |
| 112 | + newprops[1 + j].package.count = 2; | |
| 113 | + newprops[1 + j].package.elements = &newprops[k]; | |
| 114 | + | |
| 115 | + newprops[k].type = ACPI_TYPE_STRING; | |
| 116 | + newprops[k].string.length = key->string.length; | |
| 117 | + newprops[k].string.pointer = free_space; | |
| 118 | + memcpy(free_space, key->string.pointer, key->string.length); | |
| 119 | + free_space += key->string.length + 1; | |
| 120 | + | |
| 121 | + newprops[v].type = val->type; | |
| 122 | + if (val->type == ACPI_TYPE_INTEGER) { | |
| 123 | + newprops[v].integer.value = val->integer.value; | |
| 124 | + } else { | |
| 125 | + newprops[v].buffer.length = val->buffer.length; | |
| 126 | + newprops[v].buffer.pointer = free_space; | |
| 127 | + memcpy(free_space, val->buffer.pointer, | |
| 128 | + val->buffer.length); | |
| 129 | + free_space += val->buffer.length; | |
| 130 | + } | |
| 131 | + j++; /* count valid properties */ | |
| 132 | + } | |
| 133 | + WARN_ON(free_space != (void *)newprops + newsize); | |
| 134 | + | |
| 135 | + adev->data.properties = newprops; | |
| 136 | + adev->data.pointer = newprops; | |
| 137 | + | |
| 138 | +out_free: | |
| 139 | + ACPI_FREE(props); | |
| 140 | + kfree(valid); | |
| 141 | +} | |
| @@ -18,8 +18,8 @@ · 17 unmodified lines | ||
| 18 | 18 | #define pr_fmt(fmt) "apple-properties: " fmt |
| 19 | 19 | |
| 20 | 20 | #include <linux/bootmem.h> |
| 21 | −#include <linux/dmi.h> | |
| 22 | 21 | #include <linux/efi.h> |
| 22 | +#include <linux/platform_data/x86/apple.h> | |
| 23 | 23 | #include <linux/property.h> |
| 24 | 24 | #include <linux/slab.h> |
| 25 | 25 | #include <linux/ucs2_string.h> |
| @@ -191,8 +191,7 @@ static int __init map_properties(void) · 165 unmodified lines | ||
| 191 | 191 | u64 pa_data; |
| 192 | 192 | int ret; |
| 193 | 193 | |
| 194 | − if (!dmi_match(DMI_SYS_VENDOR, "Apple Inc.") && | |
| 195 | − !dmi_match(DMI_SYS_VENDOR, "Apple Computer, Inc.")) | |
| 194 | + if (!x86_apple_machine) | |
| 196 | 195 | return 0; |
| 197 | 196 | |
| 198 | 197 | pa_data = boot_params.hdr.setup_data; |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <linux/sched.h> |
| 26 | 26 | #include <linux/ktime.h> |
| 27 | 27 | #include <linux/mm.h> |
| 28 | +#include <linux/platform_data/x86/apple.h> | |
| 28 | 29 | #include <asm/dma.h> /* isa_dma_bridge_buggy */ |
| 29 | 30 | #include "pci.h" |
| 30 | 31 | |
| @@ -3447,7 +3448,7 @@ static void quirk_apple_poweroff_thunderbolt(struct pci_dev *dev) · 3416 unmodified lines | ||
| 3447 | 3448 | { |
| 3448 | 3449 | acpi_handle bridge, SXIO, SXFP, SXLV; |
| 3449 | 3450 | |
| 3450 | − if (!dmi_match(DMI_BOARD_VENDOR, "Apple Inc.")) | |
| 3451 | + if (!x86_apple_machine) | |
| 3451 | 3452 | return; |
| 3452 | 3453 | if (pci_pcie_type(dev) != PCI_EXP_TYPE_UPSTREAM) |
| 3453 | 3454 | return; |
| @@ -3492,7 +3493,7 @@ static void quirk_apple_wait_for_thunderbolt(struct pci_dev *dev) · 38 unmodified lines | ||
| 3492 | 3493 | struct pci_dev *sibling = NULL; |
| 3493 | 3494 | struct pci_dev *nhi = NULL; |
| 3494 | 3495 | |
| 3495 | − if (!dmi_match(DMI_BOARD_VENDOR, "Apple Inc.")) | |
| 3496 | + if (!x86_apple_machine) | |
| 3496 | 3497 | return; |
| 3497 | 3498 | if (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM) |
| 3498 | 3499 | return; |
| @@ -40,6 +40,7 @@ · 39 unmodified lines | ||
| 40 | 40 | #include <linux/ioport.h> |
| 41 | 41 | #include <linux/acpi.h> |
| 42 | 42 | #include <linux/highmem.h> |
| 43 | +#include <linux/platform_data/x86/apple.h> | |
| 43 | 44 | |
| 44 | 45 | #define CREATE_TRACE_POINTS |
| 45 | 46 | #include <trace/events/spi.h> |
| @@ -1693,6 +1694,35 @@ static void of_register_spi_devices(struct spi_controller *ctlr) { } · 1647 unmodified lines | ||
| 1693 | 1694 | #endif |
| 1694 | 1695 | |
| 1695 | 1696 | #ifdef CONFIG_ACPI |
| 1697 | +static void acpi_spi_parse_apple_properties(struct spi_device *spi) | |
| 1698 | +{ | |
| 1699 | + struct acpi_device *dev = ACPI_COMPANION(&spi->dev); | |
| 1700 | + const union acpi_object *obj; | |
| 1701 | + | |
| 1702 | + if (!x86_apple_machine) | |
| 1703 | + return; | |
| 1704 | + | |
| 1705 | + if (!acpi_dev_get_property(dev, "spiSclkPeriod", ACPI_TYPE_BUFFER, &obj) | |
| 1706 | + && obj->buffer.length >= 4) | |
| 1707 | + spi->max_speed_hz = NSEC_PER_SEC / *(u32 *)obj->buffer.pointer; | |
| 1708 | + | |
| 1709 | + if (!acpi_dev_get_property(dev, "spiWordSize", ACPI_TYPE_BUFFER, &obj) | |
| 1710 | + && obj->buffer.length == 8) | |
| 1711 | + spi->bits_per_word = *(u64 *)obj->buffer.pointer; | |
| 1712 | + | |
| 1713 | + if (!acpi_dev_get_property(dev, "spiBitOrder", ACPI_TYPE_BUFFER, &obj) | |
| 1714 | + && obj->buffer.length == 8 && !*(u64 *)obj->buffer.pointer) | |
| 1715 | + spi->mode |= SPI_LSB_FIRST; | |
| 1716 | + | |
| 1717 | + if (!acpi_dev_get_property(dev, "spiSPO", ACPI_TYPE_BUFFER, &obj) | |
| 1718 | + && obj->buffer.length == 8 && *(u64 *)obj->buffer.pointer) | |
| 1719 | + spi->mode |= SPI_CPOL; | |
| 1720 | + | |
| 1721 | + if (!acpi_dev_get_property(dev, "spiSPH", ACPI_TYPE_BUFFER, &obj) | |
| 1722 | + && obj->buffer.length == 8 && *(u64 *)obj->buffer.pointer) | |
| 1723 | + spi->mode |= SPI_CPHA; | |
| 1724 | +} | |
| 1725 | + | |
| 1696 | 1726 | static int acpi_spi_add_resource(struct acpi_resource *ares, void *data) |
| 1697 | 1727 | { |
| 1698 | 1728 | struct spi_device *spi = data; |
| @@ -1766,6 +1796,8 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr, · 67 unmodified lines | ||
| 1766 | 1796 | acpi_spi_add_resource, spi); |
| 1767 | 1797 | acpi_dev_free_resource_list(&resource_list); |
| 1768 | 1798 | |
| 1799 | + acpi_spi_parse_apple_properties(spi); | |
| 1800 | + | |
| 1769 | 1801 | if (ret < 0 || !spi->max_speed_hz) { |
| 1770 | 1802 | spi_dev_put(spi); |
| 1771 | 1803 | return AE_OK; |
| @@ -13,9 +13,9 @@ · 12 unmodified lines | ||
| 13 | 13 | */ |
| 14 | 14 | |
| 15 | 15 | #include <linux/delay.h> |
| 16 | −#include <linux/dmi.h> | |
| 17 | 16 | #include <linux/mutex.h> |
| 18 | 17 | #include <linux/pci.h> |
| 18 | +#include <linux/platform_data/x86/apple.h> | |
| 19 | 19 | #include <linux/sizes.h> |
| 20 | 20 | #include <linux/slab.h> |
| 21 | 21 | #include <linux/workqueue.h> |
| @@ -102,11 +102,6 @@ static inline u64 get_route(u32 route_hi, u32 route_lo) · 80 unmodified lines | ||
| 102 | 102 | return (u64)route_hi << 32 | route_lo; |
| 103 | 103 | } |
| 104 | 104 | |
| 105 | −static inline bool is_apple(void) | |
| 106 | −{ | |
| 107 | − return dmi_match(DMI_BOARD_VENDOR, "Apple Inc."); | |
| 108 | −} | |
| 109 | − | |
| 110 | 105 | static bool icm_match(const struct tb_cfg_request *req, |
| 111 | 106 | const struct ctl_pkg *pkg) |
| 112 | 107 | { |
| @@ -176,7 +171,7 @@ static int icm_request(struct tb *tb, const void *request, size_t request_size, · 63 unmodified lines | ||
| 176 | 171 | |
| 177 | 172 | static bool icm_fr_is_supported(struct tb *tb) |
| 178 | 173 | { |
| 179 | − return !is_apple(); | |
| 174 | + return !x86_apple_machine; | |
| 180 | 175 | } |
| 181 | 176 | |
| 182 | 177 | static inline int icm_fr_get_switch_index(u32 port) |
| @@ -517,7 +512,7 @@ static bool icm_ar_is_supported(struct tb *tb) · 334 unmodified lines | ||
| 517 | 512 | * Starting from Alpine Ridge we can use ICM on Apple machines |
| 518 | 513 | * as well. We just need to reset and re-enable it first. |
| 519 | 514 | */ |
| 520 | − if (!is_apple()) | |
| 515 | + if (!x86_apple_machine) | |
| 521 | 516 | return true; |
| 522 | 517 | |
| 523 | 518 | /* |
| @@ -1011,7 +1006,7 @@ static int icm_start(struct tb *tb) · 487 unmodified lines | ||
| 1011 | 1006 | * don't provide images publicly either. To be on the safe side |
| 1012 | 1007 | * prevent root switch NVM upgrade on Macs for now. |
| 1013 | 1008 | */ |
| 1014 | − tb->root_switch->no_nvm_upgrade = is_apple(); | |
| 1009 | + tb->root_switch->no_nvm_upgrade = x86_apple_machine; | |
| 1015 | 1010 | |
| 1016 | 1011 | ret = tb_switch_add(tb->root_switch); |
| 1017 | 1012 | if (ret) |
| @@ -7,7 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <linux/slab.h> |
| 8 | 8 | #include <linux/errno.h> |
| 9 | 9 | #include <linux/delay.h> |
| 10 | −#include <linux/dmi.h> | |
| 10 | +#include <linux/platform_data/x86/apple.h> | |
| 11 | 11 | |
| 12 | 12 | #include "tb.h" |
| 13 | 13 | #include "tb_regs.h" |
| @@ -453,7 +453,7 @@ struct tb *tb_probe(struct tb_nhi *nhi) · 439 unmodified lines | ||
| 453 | 453 | struct tb_cm *tcm; |
| 454 | 454 | struct tb *tb; |
| 455 | 455 | |
| 456 | − if (!dmi_match(DMI_BOARD_VENDOR, "Apple Inc.")) | |
| 456 | + if (!x86_apple_machine) | |
| 457 | 457 | return NULL; |
| 458 | 458 | |
| 459 | 459 | tb = tb_domain_alloc(nhi, sizeof(*tcm)); |
| @@ -228,8 +228,8 @@ struct acpi_subtable_proc { · 227 unmodified lines | ||
| 228 | 228 | int count; |
| 229 | 229 | }; |
| 230 | 230 | |
| 231 | −char * __acpi_map_table (unsigned long phys_addr, unsigned long size); | |
| 232 | −void __acpi_unmap_table(char *map, unsigned long size); | |
| 231 | +void __iomem *__acpi_map_table(unsigned long phys, unsigned long size); | |
| 232 | +void __acpi_unmap_table(void __iomem *map, unsigned long size); | |
| 233 | 233 | int early_acpi_boot_init(void); |
| 234 | 234 | int acpi_boot_init (void); |
| 235 | 235 | void acpi_boot_table_init (void); |
| @@ -0,0 +1,13 @@ | ||
| 1 | +#ifndef PLATFORM_DATA_X86_APPLE_H | |
| 2 | +#define PLATFORM_DATA_X86_APPLE_H | |
| 3 | + | |
| 4 | +#ifdef CONFIG_X86 | |
| 5 | +/** | |
| 6 | + * x86_apple_machine - whether the machine is an x86 Apple Macintosh | |
| 7 | + */ | |
| 8 | +extern bool x86_apple_machine; | |
| 9 | +#else | |
| 10 | +#define x86_apple_machine false | |
| 11 | +#endif | |
| 12 | + | |
| 13 | +#endif | |