1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2021-2023 Val Packett <val@packett.cool>
5 * Copyright (c) 2023 Vladimir Kondratyev <wulf@FreeBSD.org>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include "opt_acpi.h"
30 #include "opt_hid.h"
31
32 #include <sys/param.h>
33 #include <sys/bus.h>
34 #include <sys/kernel.h>
35 #include <sys/malloc.h>
36 #include <sys/mutex.h>
37 #include <sys/module.h>
38 #include <sys/rman.h>
39 #include <sys/sx.h>
40 #include <sys/taskqueue.h>
41
42 #include <contrib/dev/acpica/include/acpi.h>
43 #include <contrib/dev/acpica/include/accommon.h>
44 #include <contrib/dev/acpica/include/acevents.h>
45 #include <dev/acpica/acpivar.h>
46 #include <dev/acpica/acpiio.h>
47
48 #include <dev/backlight/backlight.h>
49
50 #include <dev/evdev/input.h>
51
52 #define HID_DEBUG_VAR atopcase_debug
53 #include <dev/hid/hid.h>
54 #include <dev/hid/hidquirk.h>
55
56 #include <dev/spibus/spi.h>
57 #include <dev/spibus/spibusvar.h>
58
59 #include "backlight_if.h"
60 #include "hid_if.h"
61
62 #include "atopcase_reg.h"
63 #include "atopcase_var.h"
64
65 /*
66 * XXX: The Linux driver only supports ACPI GPEs, but we only receive
67 * interrupts in this driver on a MacBookPro 12,1 and 14,1. This is because
68 * Linux responds to _OSI("Darwin") while we don't!
69 *
70 * ACPI GPE is enabled on FreeBSD by addition of following lines to
71 * /boot/loader.conf:
72 * hw.acpi.install_interface="Darwin"
73 * hw.acpi.remove_interface="Windows 2009, Windows 2012"
74 */
75
76 static const char *atopcase_ids[] = { "APP000D", NULL };
77
78 static device_probe_t atopcase_acpi_probe;
79 static device_attach_t atopcase_acpi_attach;
80 static device_detach_t atopcase_acpi_detach;
81 static device_suspend_t atopcase_acpi_suspend;
82 static device_resume_t atopcase_acpi_resume;
83
84 static bool
acpi_is_atopcase(ACPI_HANDLE handle)85 acpi_is_atopcase(ACPI_HANDLE handle)
86 {
87 const char **ids;
88 UINT32 sta;
89
90 for (ids = atopcase_ids; *ids != NULL; ids++) {
91 if (acpi_MatchHid(handle, *ids))
92 break;
93 }
94 if (*ids == NULL)
95 return (false);
96
97 /*
98 * If no _STA method or if it failed, then assume that
99 * the device is present.
100 */
101 if (ACPI_FAILURE(acpi_GetInteger(handle, "_STA", &sta)) ||
102 ACPI_DEVICE_PRESENT(sta))
103 return (true);
104
105 return (false);
106 }
107
108 static int
atopcase_acpi_set_comm_enabled(struct atopcase_softc * sc,char * prop,const bool on)109 atopcase_acpi_set_comm_enabled(struct atopcase_softc *sc, char *prop,
110 const bool on)
111 {
112 ACPI_OBJECT argobj;
113 ACPI_OBJECT_LIST args;
114
115 argobj.Type = ACPI_TYPE_INTEGER;
116 argobj.Integer.Value = on;
117 args.Count = 1;
118 args.Pointer = &argobj;
119
120 if (ACPI_FAILURE(
121 AcpiEvaluateObject(sc->sc_handle, prop, &args, NULL)))
122 return (ENXIO);
123
124 DELAY(100);
125
126 return (0);
127 }
128
129 static int
atopcase_acpi_test_comm_enabled(ACPI_HANDLE handle,char * prop,int * enabled)130 atopcase_acpi_test_comm_enabled(ACPI_HANDLE handle, char *prop, int *enabled)
131 {
132 if (ACPI_FAILURE(acpi_GetInteger(handle, prop, enabled)))
133 return (ENXIO);
134
135 return (0);
136 }
137
138 static void
atopcase_acpi_task(void * ctx,int pending __unused)139 atopcase_acpi_task(void *ctx, int pending __unused)
140 {
141 struct atopcase_softc *sc = ctx;
142 int err = EAGAIN;
143
144 DPRINTFN(ATOPCASE_LLEVEL_DEBUG, "Timer event\n");
145
146 sx_xlock(&sc->sc_write_sx);
147 err = atopcase_receive_packet(sc);
148 sx_xunlock(&sc->sc_write_sx);
149
150 /* Rearm timer */
151 taskqueue_enqueue_timeout(sc->sc_tq, &sc->sc_task,
152 hz / (err == EAGAIN ? 10 : 120));
153 }
154
155 static void
atopcase_acpi_gpe_task(void * ctx)156 atopcase_acpi_gpe_task(void *ctx)
157 {
158 struct atopcase_softc *sc = ctx;
159
160 DPRINTFN(ATOPCASE_LLEVEL_DEBUG, "GPE event\n");
161
162 sx_xlock(&sc->sc_sx);
163 (void)atopcase_intr(sc);
164 sx_xunlock(&sc->sc_sx);
165
166 /* Rearm GPE */
167 if (ACPI_FAILURE(AcpiFinishGpe(NULL, sc->sc_gpe_bit)))
168 device_printf(sc->sc_dev, "GPE rearm failed\n");
169 }
170
171 static UINT32
atopcase_acpi_notify(ACPI_HANDLE h __unused,UINT32 notify __unused,void * ctx)172 atopcase_acpi_notify(ACPI_HANDLE h __unused, UINT32 notify __unused, void *ctx)
173 {
174 AcpiOsExecute(OSL_GPE_HANDLER, atopcase_acpi_gpe_task, ctx);
175 return (0);
176 }
177
178 static void
atopcase_acpi_intr(void * ctx)179 atopcase_acpi_intr(void *ctx)
180 {
181 struct atopcase_softc *sc = ctx;
182
183 DPRINTFN(ATOPCASE_LLEVEL_DEBUG, "Interrupt event\n");
184
185 mtx_lock(&sc->sc_mtx);
186 sc->sc_intr_cnt++;
187 (void)atopcase_intr(sc);
188 mtx_unlock(&sc->sc_mtx);
189 }
190
191 static int
atopcase_acpi_probe(device_t dev)192 atopcase_acpi_probe(device_t dev)
193 {
194 ACPI_HANDLE handle;
195 int usb_enabled;
196
197 if (acpi_disabled("atopcase"))
198 return (ENXIO);
199
200 handle = acpi_get_handle(dev);
201 if (handle == NULL)
202 return (ENXIO);
203
204 if (!acpi_is_atopcase(handle))
205 return (ENXIO);
206
207 /* If USB interface exists and is enabled, use USB driver */
208 if (atopcase_acpi_test_comm_enabled(handle, "UIST", &usb_enabled) == 0
209 && usb_enabled != 0)
210 return (ENXIO);
211
212 device_set_desc(dev, "Apple MacBook SPI Topcase");
213
214 return (BUS_PROBE_DEFAULT);
215 }
216
217 static int
atopcase_acpi_attach(device_t dev)218 atopcase_acpi_attach(device_t dev)
219 {
220 struct atopcase_softc *sc = device_get_softc(dev);
221 ACPI_DEVICE_INFO *device_info;
222 uint32_t cs_delay;
223 int spi_enabled, err;
224
225 sc->sc_dev = dev;
226 sc->sc_handle = acpi_get_handle(dev);
227
228 if (atopcase_acpi_test_comm_enabled(sc->sc_handle, "SIST",
229 &spi_enabled) != 0) {
230 device_printf(dev, "can't test SPI communication\n");
231 return (ENXIO);
232 }
233
234 /* Turn SPI off if enabled to force "booted" packet to appear */
235 if (spi_enabled != 0 &&
236 atopcase_acpi_set_comm_enabled(sc, "SIEN", false) != 0) {
237 device_printf(dev, "can't disable SPI communication\n");
238 return (ENXIO);
239 }
240
241 if (atopcase_acpi_set_comm_enabled(sc, "SIEN", true) != 0) {
242 device_printf(dev, "can't enable SPI communication\n");
243 return (ENXIO);
244 }
245
246 /*
247 * Apple encodes a CS delay in ACPI properties, but
248 * - they're encoded in a non-standard way that predates _DSD, and
249 * - they're only exported if you respond to _OSI(Darwin) which we don't
250 * - because that has more side effects than we're prepared to handle
251 * - Apple makes a Windows driver and Windows is not Darwin
252 * - so presumably that one uses hardcoded values too
253 */
254 spibus_get_cs_delay(sc->sc_dev, &cs_delay);
255 if (cs_delay == 0)
256 spibus_set_cs_delay(sc->sc_dev, 10);
257
258 /* Retrieve ACPI _HID */
259 if (ACPI_FAILURE(AcpiGetObjectInfo(sc->sc_handle, &device_info)))
260 return (ENXIO);
261 if (device_info->Valid & ACPI_VALID_HID)
262 strlcpy(sc->sc_hid, device_info->HardwareId.String,
263 sizeof(sc->sc_hid));
264 AcpiOsFree(device_info);
265
266 sx_init(&sc->sc_write_sx, "atc_wr");
267 sx_init(&sc->sc_sx, "atc_sx");
268 mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
269
270 err = ENXIO;
271 sc->sc_irq_res = bus_alloc_resource_any(sc->sc_dev,
272 SYS_RES_IRQ, &sc->sc_irq_rid, RF_ACTIVE);
273 if (sc->sc_irq_res != NULL) {
274 if (bus_setup_intr(dev, sc->sc_irq_res,
275 INTR_TYPE_MISC | INTR_MPSAFE, NULL,
276 atopcase_acpi_intr, sc, &sc->sc_irq_ih) != 0) {
277 device_printf(dev, "can't setup interrupt handler\n");
278 goto err;
279 }
280 device_printf(dev, "Using interrupts.\n");
281 /*
282 * On some hardware interrupts are not acked by SPI read for
283 * unknown reasons that leads to interrupt storm due to level
284 * triggering. GPE does not suffer from this problem.
285 *
286 * TODO: Find out what Windows driver does to ack IRQ.
287 */
288 pause("atopcase", hz / 5);
289 DPRINTF("interrupts asserted: %u\n", sc->sc_intr_cnt);
290 if (sc->sc_intr_cnt > 2 || sc->sc_intr_cnt == 0) {
291 bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_ih);
292 sc->sc_irq_ih = NULL;
293 device_printf(dev, "Interrupt storm detected. "
294 "Falling back to polling\n");
295 sc->sc_tq = taskqueue_create("atc_tq", M_WAITOK|M_ZERO,
296 taskqueue_thread_enqueue, &sc->sc_tq);
297 TIMEOUT_TASK_INIT(sc->sc_tq, &sc->sc_task, 0,
298 atopcase_acpi_task, sc);
299 taskqueue_start_threads(&sc->sc_tq, 1, PI_TTY,
300 "%s taskq", device_get_nameunit(dev));
301 }
302 /*
303 * Interrupts does not work at all. It may happen if kernel
304 * erroneously detected stray irq at bus_teardown_intr() and
305 * completelly disabled it after than.
306 * Fetch "booted" packet manually to pass communication check.
307 */
308 if (sc->sc_intr_cnt == 0)
309 atopcase_receive_packet(sc);
310 } else {
311 if (bootverbose)
312 device_printf(dev, "can't allocate IRQ resource\n");
313 if (ACPI_FAILURE(acpi_GetInteger(sc->sc_handle, "_GPE",
314 &sc->sc_gpe_bit))) {
315 device_printf(dev, "can't allocate nor IRQ nor GPE\n");
316 goto err;
317 }
318 if (ACPI_FAILURE(AcpiInstallGpeHandler(NULL, sc->sc_gpe_bit,
319 ACPI_GPE_LEVEL_TRIGGERED, atopcase_acpi_notify, sc))) {
320 device_printf(dev, "can't install ACPI GPE handler\n");
321 goto err;
322 }
323 if (ACPI_FAILURE(AcpiEnableGpe(NULL, sc->sc_gpe_bit))) {
324 device_printf(dev, "can't enable ACPI notification\n");
325 goto err;
326 }
327 device_printf(dev, "Using ACPI GPE.\n");
328 if (bootverbose)
329 device_printf(dev, "GPE int %d\n", sc->sc_gpe_bit);
330 }
331
332 err = atopcase_init(sc);
333
334 err:
335 if (err != 0)
336 atopcase_acpi_detach(dev);
337 return (err);
338 }
339
340 static int
atopcase_acpi_detach(device_t dev)341 atopcase_acpi_detach(device_t dev)
342 {
343 struct atopcase_softc *sc = device_get_softc(dev);
344 int err;
345
346 err = atopcase_destroy(sc);
347 if (err != 0)
348 return (err);
349
350 if (sc->sc_irq_ih)
351 bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_ih);
352 if (sc->sc_irq_res != NULL)
353 bus_release_resource(dev, SYS_RES_IRQ,
354 sc->sc_irq_rid, sc->sc_irq_res);
355
356 if (sc->sc_tq != NULL) {
357 while (taskqueue_cancel_timeout(sc->sc_tq, &sc->sc_task, NULL))
358 taskqueue_drain_timeout(sc->sc_tq, &sc->sc_task);
359 taskqueue_free(sc->sc_tq);
360 }
361
362 if (sc->sc_gpe_bit != 0 && ACPI_FAILURE(AcpiRemoveGpeHandler(NULL,
363 sc->sc_gpe_bit, atopcase_acpi_notify)))
364 device_printf(dev, "can't remove ACPI GPE handler\n");
365
366 if (atopcase_acpi_set_comm_enabled(sc, "SIEN", false) != 0)
367 device_printf(dev, "can't disable SPI communication\n");
368
369 mtx_destroy(&sc->sc_mtx);
370 sx_destroy(&sc->sc_sx);
371 sx_destroy(&sc->sc_write_sx);
372
373 return (0);
374 }
375
376 static int
atopcase_acpi_suspend(device_t dev)377 atopcase_acpi_suspend(device_t dev)
378 {
379 struct atopcase_softc *sc = device_get_softc(dev);
380 int err;
381
382 err = bus_generic_suspend(dev);
383 if (err)
384 return (err);
385
386 if (sc->sc_gpe_bit != 0)
387 AcpiDisableGpe(NULL, sc->sc_gpe_bit);
388
389 if (sc->sc_tq != NULL)
390 while (taskqueue_cancel_timeout(sc->sc_tq, &sc->sc_task, NULL))
391 taskqueue_drain_timeout(sc->sc_tq, &sc->sc_task);
392
393 if (atopcase_acpi_set_comm_enabled(sc, "SIEN", false) != 0)
394 device_printf(dev, "can't disable SPI communication\n");
395
396 return (0);
397 }
398
399 static int
atopcase_acpi_resume(device_t dev)400 atopcase_acpi_resume(device_t dev)
401 {
402 struct atopcase_softc *sc = device_get_softc(dev);
403
404 if (sc->sc_gpe_bit != 0)
405 AcpiEnableGpe(NULL, sc->sc_gpe_bit);
406
407 if (sc->sc_tq != NULL)
408 taskqueue_enqueue_timeout(sc->sc_tq, &sc->sc_task, hz / 120);
409
410 if (atopcase_acpi_set_comm_enabled(sc, "SIEN", true) != 0) {
411 device_printf(dev, "can't enable SPI communication\n");
412 return (ENXIO);
413 }
414
415 return (bus_generic_resume(dev));
416 }
417
418 static device_method_t atopcase_methods[] = {
419 /* Device interface */
420 DEVMETHOD(device_probe, atopcase_acpi_probe),
421 DEVMETHOD(device_attach, atopcase_acpi_attach),
422 DEVMETHOD(device_detach, atopcase_acpi_detach),
423 DEVMETHOD(device_suspend, atopcase_acpi_suspend),
424 DEVMETHOD(device_resume, atopcase_acpi_resume),
425
426 /* HID interrupt interface */
427 DEVMETHOD(hid_intr_setup, atopcase_intr_setup),
428 DEVMETHOD(hid_intr_unsetup, atopcase_intr_unsetup),
429 DEVMETHOD(hid_intr_start, atopcase_intr_start),
430 DEVMETHOD(hid_intr_stop, atopcase_intr_stop),
431 DEVMETHOD(hid_intr_poll, atopcase_intr_poll),
432
433 /* HID interface */
434 DEVMETHOD(hid_get_rdesc, atopcase_get_rdesc),
435 DEVMETHOD(hid_set_report, atopcase_set_report),
436
437 /* Backlight interface */
438 DEVMETHOD(backlight_update_status, atopcase_backlight_update_status),
439 DEVMETHOD(backlight_get_status, atopcase_backlight_get_status),
440 DEVMETHOD(backlight_get_info, atopcase_backlight_get_info),
441
442 DEVMETHOD_END
443 };
444
445 static driver_t atopcase_driver = {
446 "atopcase",
447 atopcase_methods,
448 sizeof(struct atopcase_softc),
449 };
450
451 DRIVER_MODULE(atopcase, spibus, atopcase_driver, 0, 0);
452 MODULE_DEPEND(atopcase, acpi, 1, 1, 1);
453 MODULE_DEPEND(atopcase, backlight, 1, 1, 1);
454 MODULE_DEPEND(atopcase, hid, 1, 1, 1);
455 MODULE_DEPEND(atopcase, hidbus, 1, 1, 1);
456 MODULE_DEPEND(atopcase, spibus, 1, 1, 1);
457 MODULE_VERSION(atopcase, 1);
458 SPIBUS_ACPI_PNP_INFO(atopcase_ids);
459