Skip to content

Commit

Permalink
ACPI / SBS: Don't assume the existence of an SBS charger
Browse files Browse the repository at this point in the history
Apple hardware continues to expose an ACPI AC charger even when using
SBS to report battery state. The charger status byte returns all 0s in
this case.  Since the spec requires that bit 4 be 1 at all times, assume
that there's not really a charger if it's set to zero.

Signed-off-by: Matthew Garrett <[email protected]>
Signed-off-by: Andreas Noever <[email protected]>
Signed-off-by: Rafael J. Wysocki <[email protected]>
  • Loading branch information
Matthew Garrett authored and rafaeljw committed Sep 24, 2014
1 parent 0f33be0 commit 3031cdd
Showing 1 changed file with 22 additions and 7 deletions.
29 changes: 22 additions & 7 deletions drivers/acpi/sbs.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ struct acpi_sbs {
u8 batteries_supported:4;
u8 manager_present:1;
u8 charger_present:1;
u8 charger_exists:1;
};

#define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger)
Expand Down Expand Up @@ -429,9 +430,19 @@ static int acpi_ac_get_present(struct acpi_sbs *sbs)

result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER,
0x13, (u8 *) & status);
if (!result)
sbs->charger_present = (status >> 15) & 0x1;
return result;

if (result)
return result;

/*
* The spec requires that bit 4 always be 1. If it's not set, assume
* that the implementation doesn't support an SBS charger
*/
if (!(status >> 4) & 0x1)
return -ENODEV;

sbs->charger_present = (status >> 15) & 0x1;
return 0;
}

static ssize_t acpi_battery_alarm_show(struct device *dev,
Expand Down Expand Up @@ -554,6 +565,7 @@ static int acpi_charger_add(struct acpi_sbs *sbs)
if (result)
goto end;

sbs->charger_exists = 1;
sbs->charger.name = "sbs-charger";
sbs->charger.type = POWER_SUPPLY_TYPE_MAINS;
sbs->charger.properties = sbs_ac_props;
Expand All @@ -580,9 +592,12 @@ static void acpi_sbs_callback(void *context)
struct acpi_battery *bat;
u8 saved_charger_state = sbs->charger_present;
u8 saved_battery_state;
acpi_ac_get_present(sbs);
if (sbs->charger_present != saved_charger_state)
kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE);

if (sbs->charger_exists) {
acpi_ac_get_present(sbs);
if (sbs->charger_present != saved_charger_state)
kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE);
}

if (sbs->manager_present) {
for (id = 0; id < MAX_SBS_BAT; ++id) {
Expand Down Expand Up @@ -619,7 +634,7 @@ static int acpi_sbs_add(struct acpi_device *device)
device->driver_data = sbs;

result = acpi_charger_add(sbs);
if (result)
if (result && result != -ENODEV)
goto end;

result = acpi_manager_get_info(sbs);
Expand Down

0 comments on commit 3031cdd

Please sign in to comment.