aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-10-05 16:24:19 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-10-05 16:24:19 -0400
commit939558f2a4b7851c11ce8d08387730914a1e1f5f (patch)
tree4013f9577fe56da1fd3f8cc49b0de790b0e85c4f /drivers/acpi
parent65e8627aad0b9ef24d282296f4d3a1638a2438e6 (diff)
parent5159e39bdf119613adc6556901ae2d2e5e027551 (diff)
Merge branch 'acpi-apple'
* acpi-apple: ACPI / SBS: Fix check in acpi_ac_get_present() ACPI: Support _OSI("Darwin") correctly ACPI / SBS: Disable smart battery manager on Apple ACPI / SBS: Don't assume the existence of an SBS charger
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/osl.c10
-rw-r--r--drivers/acpi/pci_root.c14
-rw-r--r--drivers/acpi/sbs.c80
3 files changed, 89 insertions, 15 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 3abe9b223ba7..938b6ac71dde 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -152,6 +152,16 @@ static u32 acpi_osi_handler(acpi_string interface, u32 supported)
152 osi_linux.dmi ? " via DMI" : ""); 152 osi_linux.dmi ? " via DMI" : "");
153 } 153 }
154 154
155 if (!strcmp("Darwin", interface)) {
156 /*
157 * Apple firmware will behave poorly if it receives positive
158 * answers to "Darwin" and any other OS. Respond positively
159 * to Darwin and then disable all other vendor strings.
160 */
161 acpi_update_interfaces(ACPI_DISABLE_ALL_VENDOR_STRINGS);
162 supported = ACPI_UINT32_MAX;
163 }
164
155 return supported; 165 return supported;
156} 166}
157 167
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index e6ae603ed1a1..cd4de7e038ea 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -35,6 +35,7 @@
35#include <linux/pci-aspm.h> 35#include <linux/pci-aspm.h>
36#include <linux/acpi.h> 36#include <linux/acpi.h>
37#include <linux/slab.h> 37#include <linux/slab.h>
38#include <linux/dmi.h>
38#include <acpi/apei.h> /* for acpi_hest_init() */ 39#include <acpi/apei.h> /* for acpi_hest_init() */
39 40
40#include "internal.h" 41#include "internal.h"
@@ -430,6 +431,19 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm,
430 acpi_handle handle = device->handle; 431 acpi_handle handle = device->handle;
431 432
432 /* 433 /*
434 * Apple always return failure on _OSC calls when _OSI("Darwin") has
435 * been called successfully. We know the feature set supported by the
436 * platform, so avoid calling _OSC at all
437 */
438
439 if (dmi_match(DMI_SYS_VENDOR, "Apple Inc.")) {
440 root->osc_control_set = ~OSC_PCI_EXPRESS_PME_CONTROL;
441 decode_osc_control(root, "OS assumes control of",
442 root->osc_control_set);
443 return;
444 }
445
446 /*
433 * All supported architectures that use ACPI have support for 447 * All supported architectures that use ACPI have support for
434 * PCI domains, so we indicate this in _OSC support capabilities. 448 * PCI domains, so we indicate this in _OSC support capabilities.
435 */ 449 */
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index 366ca40a6f70..a7a3edd28beb 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -35,6 +35,7 @@
35#include <linux/jiffies.h> 35#include <linux/jiffies.h>
36#include <linux/delay.h> 36#include <linux/delay.h>
37#include <linux/power_supply.h> 37#include <linux/power_supply.h>
38#include <linux/dmi.h>
38 39
39#include "sbshc.h" 40#include "sbshc.h"
40#include "battery.h" 41#include "battery.h"
@@ -61,6 +62,8 @@ static unsigned int cache_time = 1000;
61module_param(cache_time, uint, 0644); 62module_param(cache_time, uint, 0644);
62MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); 63MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
63 64
65static bool sbs_manager_broken;
66
64#define MAX_SBS_BAT 4 67#define MAX_SBS_BAT 4
65#define ACPI_SBS_BLOCK_MAX 32 68#define ACPI_SBS_BLOCK_MAX 32
66 69
@@ -109,6 +112,7 @@ struct acpi_sbs {
109 u8 batteries_supported:4; 112 u8 batteries_supported:4;
110 u8 manager_present:1; 113 u8 manager_present:1;
111 u8 charger_present:1; 114 u8 charger_present:1;
115 u8 charger_exists:1;
112}; 116};
113 117
114#define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger) 118#define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger)
@@ -429,9 +433,19 @@ static int acpi_ac_get_present(struct acpi_sbs *sbs)
429 433
430 result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER, 434 result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER,
431 0x13, (u8 *) & status); 435 0x13, (u8 *) & status);
432 if (!result) 436
433 sbs->charger_present = (status >> 15) & 0x1; 437 if (result)
434 return result; 438 return result;
439
440 /*
441 * The spec requires that bit 4 always be 1. If it's not set, assume
442 * that the implementation doesn't support an SBS charger
443 */
444 if (!((status >> 4) & 0x1))
445 return -ENODEV;
446
447 sbs->charger_present = (status >> 15) & 0x1;
448 return 0;
435} 449}
436 450
437static ssize_t acpi_battery_alarm_show(struct device *dev, 451static ssize_t acpi_battery_alarm_show(struct device *dev,
@@ -483,16 +497,21 @@ static int acpi_battery_read(struct acpi_battery *battery)
483 ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2); 497 ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2);
484 } else if (battery->id == 0) 498 } else if (battery->id == 0)
485 battery->present = 1; 499 battery->present = 1;
500
486 if (result || !battery->present) 501 if (result || !battery->present)
487 return result; 502 return result;
488 503
489 if (saved_present != battery->present) { 504 if (saved_present != battery->present) {
490 battery->update_time = 0; 505 battery->update_time = 0;
491 result = acpi_battery_get_info(battery); 506 result = acpi_battery_get_info(battery);
492 if (result) 507 if (result) {
508 battery->present = 0;
493 return result; 509 return result;
510 }
494 } 511 }
495 result = acpi_battery_get_state(battery); 512 result = acpi_battery_get_state(battery);
513 if (result)
514 battery->present = 0;
496 return result; 515 return result;
497} 516}
498 517
@@ -524,6 +543,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
524 result = power_supply_register(&sbs->device->dev, &battery->bat); 543 result = power_supply_register(&sbs->device->dev, &battery->bat);
525 if (result) 544 if (result)
526 goto end; 545 goto end;
546
527 result = device_create_file(battery->bat.dev, &alarm_attr); 547 result = device_create_file(battery->bat.dev, &alarm_attr);
528 if (result) 548 if (result)
529 goto end; 549 goto end;
@@ -554,6 +574,7 @@ static int acpi_charger_add(struct acpi_sbs *sbs)
554 if (result) 574 if (result)
555 goto end; 575 goto end;
556 576
577 sbs->charger_exists = 1;
557 sbs->charger.name = "sbs-charger"; 578 sbs->charger.name = "sbs-charger";
558 sbs->charger.type = POWER_SUPPLY_TYPE_MAINS; 579 sbs->charger.type = POWER_SUPPLY_TYPE_MAINS;
559 sbs->charger.properties = sbs_ac_props; 580 sbs->charger.properties = sbs_ac_props;
@@ -580,9 +601,12 @@ static void acpi_sbs_callback(void *context)
580 struct acpi_battery *bat; 601 struct acpi_battery *bat;
581 u8 saved_charger_state = sbs->charger_present; 602 u8 saved_charger_state = sbs->charger_present;
582 u8 saved_battery_state; 603 u8 saved_battery_state;
583 acpi_ac_get_present(sbs); 604
584 if (sbs->charger_present != saved_charger_state) 605 if (sbs->charger_exists) {
585 kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE); 606 acpi_ac_get_present(sbs);
607 if (sbs->charger_present != saved_charger_state)
608 kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE);
609 }
586 610
587 if (sbs->manager_present) { 611 if (sbs->manager_present) {
588 for (id = 0; id < MAX_SBS_BAT; ++id) { 612 for (id = 0; id < MAX_SBS_BAT; ++id) {
@@ -598,12 +622,31 @@ static void acpi_sbs_callback(void *context)
598 } 622 }
599} 623}
600 624
625static int disable_sbs_manager(const struct dmi_system_id *d)
626{
627 sbs_manager_broken = true;
628 return 0;
629}
630
631static struct dmi_system_id acpi_sbs_dmi_table[] = {
632 {
633 .callback = disable_sbs_manager,
634 .ident = "Apple",
635 .matches = {
636 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc.")
637 },
638 },
639 { },
640};
641
601static int acpi_sbs_add(struct acpi_device *device) 642static int acpi_sbs_add(struct acpi_device *device)
602{ 643{
603 struct acpi_sbs *sbs; 644 struct acpi_sbs *sbs;
604 int result = 0; 645 int result = 0;
605 int id; 646 int id;
606 647
648 dmi_check_system(acpi_sbs_dmi_table);
649
607 sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL); 650 sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
608 if (!sbs) { 651 if (!sbs) {
609 result = -ENOMEM; 652 result = -ENOMEM;
@@ -619,17 +662,24 @@ static int acpi_sbs_add(struct acpi_device *device)
619 device->driver_data = sbs; 662 device->driver_data = sbs;
620 663
621 result = acpi_charger_add(sbs); 664 result = acpi_charger_add(sbs);
622 if (result) 665 if (result && result != -ENODEV)
623 goto end; 666 goto end;
624 667
625 result = acpi_manager_get_info(sbs); 668 result = 0;
626 if (!result) { 669
627 sbs->manager_present = 1; 670 if (!sbs_manager_broken) {
628 for (id = 0; id < MAX_SBS_BAT; ++id) 671 result = acpi_manager_get_info(sbs);
629 if ((sbs->batteries_supported & (1 << id))) 672 if (!result) {
630 acpi_battery_add(sbs, id); 673 sbs->manager_present = 0;
631 } else 674 for (id = 0; id < MAX_SBS_BAT; ++id)
675 if ((sbs->batteries_supported & (1 << id)))
676 acpi_battery_add(sbs, id);
677 }
678 }
679
680 if (!sbs->manager_present)
632 acpi_battery_add(sbs, 0); 681 acpi_battery_add(sbs, 0);
682
633 acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs); 683 acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs);
634 end: 684 end:
635 if (result) 685 if (result)