Dash:
[t2.git] / package / base / linux / acpi-sbs-unbrick.patch.disabled
blob082e052efe8f1e8b80bdafb271a6021bddd2045a
1 WARNING: NO WARRANTIES, USE AT YOUR OWN RISK!
2 DONT SUE US WHEN YOUR BATTERY, MACBOOK, HOUSE OR ANYTHING ELSE
3 BURNS DOWN !!!
5 Potentially unbricking e.g. Apple MacBook batteries with
6 too low of a safety voltage and permanent failure bit set.
7 By unsealing and clearing the Permanent Failure Status bit!
9 1st: for this to have an effect and work you need to first
10 open the battery without damaging the cells, check that
11 they are ok, not expanded, burned, ... and pre-charge them
12 with a lab power supply until they have an initial high
13 enough minimal cell voltage.
15 Only then run this modifed ACPI code to reset the bit.
16 (if you run this without pre-charging the battery pack
17 will likely instantly go back into fail mode due to
18 stil being below the minimal safety voltage.
20 The pack I test this with did not instantly start charging,
21 but had to be ejected from the MacBook and inserted again.
23 Please let ms know if and when you try this and your result!
24 Outputs will be in the system dmesg.
26   - RenĂ© Rebe <rene@rebe.name>
28 --- linux-5.0/drivers/acpi/sbs.c.vanilla        2019-04-02 12:52:24.448537687 +0200
29 +++ linux-5.0/drivers/acpi/sbs.c        2019-04-02 12:56:38.944548238 +0200
30 @@ -521,6 +521,40 @@
31         return result;
32  }
34 +static const char* mfg_status[16] = {
35 +       "Wake up",
36 +       "Normal discharge", 
37 +       "",
38 +       "Precharge",
39 +       "",
40 +       "Charge",
41 +       "Charge termination",
42 +       "",
43 +       "Fault charge terminate",
44 +       "Permanent failure",
45 +       "Overcurrent",
46 +       "Overtemperature",
47 +       "Battery failure",
48 +       "Sleep",
49 +       "Reserved",
50 +       "Battery removed",
51 +};
53 +static const char* fet_status[4] = {
54 +       "both on",
55 +       "CHG off, DSG on",
56 +       "both off",
57 +       "CHG on, DSG off",
58 +};
60 +static const char* pf_status[4] = {
61 +       "Fuse blown (if failure)",
62 +       "Cell imbalance",
63 +       "Safety Volt fail",
64 +       "FET fail",
65 +};
68  /* Smart Battery */
69  static int acpi_battery_add(struct acpi_sbs *sbs, int id)
70  {
71 @@ -563,6 +597,49 @@
72         printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n",
73                ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
74                battery->name, battery->present ? "present" : "absent");
76 +       /* RxR wild hacking */
77 +       u16 value = 0x0006; /* ManufacturerStatus */
78 +       result = acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value, 2);
79 +       if (result) {
80 +               printk(KERN_INFO "error: %d\n", result);
81 +       } else {
82 +               result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value);
83 +               printk(KERN_INFO "result: %d %04x %s\n", result, value, mfg_status[(value >> 8) & 0xf]);
84 +               printk(KERN_INFO "result: FETs: %s, PF: %s\n", fet_status[(value >> 14) & 0x3], pf_status[(value >> 12) & 0x3]);
85 +               bool wasPF = ((value >> 8) & 0xf) == 0x9;
87 +               value = 0x53;
88 +               acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value, 2);
89 +               result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value);
90 +               printk(KERN_INFO "PFStatus: %d %04x\n", result, value);
91 +               value = 0x54;
92 +               acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value, 2);
93 +               result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value);
94 +               printk(KERN_INFO "OpStatus: %d %04x\n", result, value);
96 +               // unseal
97 +               if (wasPF) {
98 +                       value = 0x0414;
99 +                       result = acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value, 2);
100 +                       value = 0x3672;
101 +                       result |= acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value, 2);
102 +                       printk(KERN_INFO "Unseal: %d\n", result);
104 +                       /* clear permanent failure */
105 +                       value = 0x2673;
106 +                       result = acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value, 2);
107 +                       value = 0x1712;
108 +                       result |= acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value, 2);
109 +                       printk(KERN_INFO "clear pf: %d\n", result);
111 +                       /* seal */
112 +                       value = 0x20;
113 +                       result = acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value, 2);
114 +                       printk(KERN_INFO "re-sealed: %d\n", result);
115 +               }
116 +       }
118         return result;