|
@@ -35,6 +35,7 @@
|
|
|
#include <linux/jiffies.h>
|
|
#include <linux/jiffies.h>
|
|
|
#include <linux/delay.h>
|
|
#include <linux/delay.h>
|
|
|
#include <linux/power_supply.h>
|
|
#include <linux/power_supply.h>
|
|
|
|
|
+#include <linux/dmi.h>
|
|
|
|
|
|
|
|
#include "sbshc.h"
|
|
#include "sbshc.h"
|
|
|
#include "battery.h"
|
|
#include "battery.h"
|
|
@@ -61,6 +62,8 @@ static unsigned int cache_time = 1000;
|
|
|
module_param(cache_time, uint, 0644);
|
|
module_param(cache_time, uint, 0644);
|
|
|
MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
|
|
MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
|
|
|
|
|
|
|
|
|
|
+static bool sbs_manager_broken;
|
|
|
|
|
+
|
|
|
#define MAX_SBS_BAT 4
|
|
#define MAX_SBS_BAT 4
|
|
|
#define ACPI_SBS_BLOCK_MAX 32
|
|
#define ACPI_SBS_BLOCK_MAX 32
|
|
|
|
|
|
|
@@ -494,16 +497,21 @@ static int acpi_battery_read(struct acpi_battery *battery)
|
|
|
ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2);
|
|
ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2);
|
|
|
} else if (battery->id == 0)
|
|
} else if (battery->id == 0)
|
|
|
battery->present = 1;
|
|
battery->present = 1;
|
|
|
|
|
+
|
|
|
if (result || !battery->present)
|
|
if (result || !battery->present)
|
|
|
return result;
|
|
return result;
|
|
|
|
|
|
|
|
if (saved_present != battery->present) {
|
|
if (saved_present != battery->present) {
|
|
|
battery->update_time = 0;
|
|
battery->update_time = 0;
|
|
|
result = acpi_battery_get_info(battery);
|
|
result = acpi_battery_get_info(battery);
|
|
|
- if (result)
|
|
|
|
|
|
|
+ if (result) {
|
|
|
|
|
+ battery->present = 0;
|
|
|
return result;
|
|
return result;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
result = acpi_battery_get_state(battery);
|
|
result = acpi_battery_get_state(battery);
|
|
|
|
|
+ if (result)
|
|
|
|
|
+ battery->present = 0;
|
|
|
return result;
|
|
return result;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -535,6 +543,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
|
|
|
result = power_supply_register(&sbs->device->dev, &battery->bat);
|
|
result = power_supply_register(&sbs->device->dev, &battery->bat);
|
|
|
if (result)
|
|
if (result)
|
|
|
goto end;
|
|
goto end;
|
|
|
|
|
+
|
|
|
result = device_create_file(battery->bat.dev, &alarm_attr);
|
|
result = device_create_file(battery->bat.dev, &alarm_attr);
|
|
|
if (result)
|
|
if (result)
|
|
|
goto end;
|
|
goto end;
|
|
@@ -613,12 +622,31 @@ 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)
|
|
static int acpi_sbs_add(struct acpi_device *device)
|
|
|
{
|
|
{
|
|
|
struct acpi_sbs *sbs;
|
|
struct acpi_sbs *sbs;
|
|
|
int result = 0;
|
|
int result = 0;
|
|
|
int id;
|
|
int id;
|
|
|
|
|
|
|
|
|
|
+ dmi_check_system(acpi_sbs_dmi_table);
|
|
|
|
|
+
|
|
|
sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
|
|
sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
|
|
|
if (!sbs) {
|
|
if (!sbs) {
|
|
|
result = -ENOMEM;
|
|
result = -ENOMEM;
|
|
@@ -637,14 +665,21 @@ static int acpi_sbs_add(struct acpi_device *device)
|
|
|
if (result && result != -ENODEV)
|
|
if (result && result != -ENODEV)
|
|
|
goto end;
|
|
goto end;
|
|
|
|
|
|
|
|
- result = acpi_manager_get_info(sbs);
|
|
|
|
|
- if (!result) {
|
|
|
|
|
- sbs->manager_present = 1;
|
|
|
|
|
- for (id = 0; id < MAX_SBS_BAT; ++id)
|
|
|
|
|
- if ((sbs->batteries_supported & (1 << id)))
|
|
|
|
|
- acpi_battery_add(sbs, id);
|
|
|
|
|
- } else
|
|
|
|
|
|
|
+ result = 0;
|
|
|
|
|
+
|
|
|
|
|
+ if (!sbs_manager_broken) {
|
|
|
|
|
+ result = acpi_manager_get_info(sbs);
|
|
|
|
|
+ if (!result) {
|
|
|
|
|
+ sbs->manager_present = 0;
|
|
|
|
|
+ for (id = 0; id < MAX_SBS_BAT; ++id)
|
|
|
|
|
+ if ((sbs->batteries_supported & (1 << id)))
|
|
|
|
|
+ acpi_battery_add(sbs, id);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!sbs->manager_present)
|
|
|
acpi_battery_add(sbs, 0);
|
|
acpi_battery_add(sbs, 0);
|
|
|
|
|
+
|
|
|
acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs);
|
|
acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs);
|
|
|
end:
|
|
end:
|
|
|
if (result)
|
|
if (result)
|