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 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 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 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 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 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 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 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 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 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 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 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 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