|
14 | 14 | #include <linux/delay.h>
|
15 | 15 | #include <linux/module.h>
|
16 | 16 | #include <linux/interrupt.h>
|
| 17 | +#include <linux/dmi.h> |
17 | 18 | #include "sbshc.h"
|
18 | 19 |
|
19 | 20 | #define PREFIX "ACPI: "
|
@@ -87,6 +88,8 @@ enum acpi_smb_offset {
|
87 | 88 | ACPI_SMB_ALARM_DATA = 0x26, /* 2 bytes alarm data */
|
88 | 89 | };
|
89 | 90 |
|
| 91 | +static bool macbook; |
| 92 | + |
90 | 93 | static inline int smb_hc_read(struct acpi_smb_hc *hc, u8 address, u8 *data)
|
91 | 94 | {
|
92 | 95 | return ec_read(hc->offset + address, data);
|
@@ -132,6 +135,8 @@ static int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol,
|
132 | 135 | }
|
133 | 136 |
|
134 | 137 | mutex_lock(&hc->lock);
|
| 138 | + if (macbook) |
| 139 | + udelay(5); |
135 | 140 | if (smb_hc_read(hc, ACPI_SMB_PROTOCOL, &temp))
|
136 | 141 | goto end;
|
137 | 142 | if (temp) {
|
@@ -257,12 +262,29 @@ extern int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
|
257 | 262 | acpi_handle handle, acpi_ec_query_func func,
|
258 | 263 | void *data);
|
259 | 264 |
|
| 265 | +static int macbook_dmi_match(const struct dmi_system_id *d) |
| 266 | +{ |
| 267 | + pr_debug("Detected MacBook, enabling workaround\n"); |
| 268 | + macbook = true; |
| 269 | + return 0; |
| 270 | +} |
| 271 | + |
| 272 | +static struct dmi_system_id acpi_smbus_dmi_table[] = { |
| 273 | + { macbook_dmi_match, "Apple MacBook", { |
| 274 | + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), |
| 275 | + DMI_MATCH(DMI_PRODUCT_NAME, "MacBook") }, |
| 276 | + }, |
| 277 | + { }, |
| 278 | +}; |
| 279 | + |
260 | 280 | static int acpi_smbus_hc_add(struct acpi_device *device)
|
261 | 281 | {
|
262 | 282 | int status;
|
263 | 283 | unsigned long long val;
|
264 | 284 | struct acpi_smb_hc *hc;
|
265 | 285 |
|
| 286 | + dmi_check_system(acpi_smbus_dmi_table); |
| 287 | + |
266 | 288 | if (!device)
|
267 | 289 | return -EINVAL;
|
268 | 290 |
|
|
0 commit comments