11fc1a228SAndrew Turner /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
31fc1a228SAndrew Turner *
41fc1a228SAndrew Turner * Copyright (c) 2020 Amazon.com, Inc. or its affiliates.
51fc1a228SAndrew Turner * All rights reserved.
61fc1a228SAndrew Turner *
71fc1a228SAndrew Turner * Redistribution and use in source and binary forms, with or without
81fc1a228SAndrew Turner * modification, are permitted provided that the following conditions
91fc1a228SAndrew Turner * are met:
101fc1a228SAndrew Turner * 1. Redistributions of source code must retain the above copyright
111fc1a228SAndrew Turner * notice, this list of conditions and the following disclaimer.
121fc1a228SAndrew Turner * 2. Redistributions in binary form must reproduce the above copyright
131fc1a228SAndrew Turner * notice, this list of conditions and the following disclaimer in the
141fc1a228SAndrew Turner * documentation and/or other materials provided with the distribution.
151fc1a228SAndrew Turner *
161fc1a228SAndrew Turner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
171fc1a228SAndrew Turner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
181fc1a228SAndrew Turner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
191fc1a228SAndrew Turner * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
201fc1a228SAndrew Turner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
211fc1a228SAndrew Turner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
221fc1a228SAndrew Turner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
231fc1a228SAndrew Turner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
241fc1a228SAndrew Turner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
251fc1a228SAndrew Turner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
261fc1a228SAndrew Turner * SUCH DAMAGE.
271fc1a228SAndrew Turner */
281fc1a228SAndrew Turner
291fc1a228SAndrew Turner #include "opt_acpi.h"
301fc1a228SAndrew Turner
311fc1a228SAndrew Turner #include <sys/param.h>
321fc1a228SAndrew Turner #include <sys/systm.h>
331fc1a228SAndrew Turner #include <sys/bus.h>
341fc1a228SAndrew Turner #include <sys/kernel.h>
351fc1a228SAndrew Turner #include <sys/module.h>
361fc1a228SAndrew Turner #include <sys/lock.h>
371fc1a228SAndrew Turner #include <sys/mutex.h>
381fc1a228SAndrew Turner
391fc1a228SAndrew Turner #include <machine/intr.h>
401fc1a228SAndrew Turner
411fc1a228SAndrew Turner #include <contrib/dev/acpica/include/acpi.h>
421fc1a228SAndrew Turner #include <contrib/dev/acpica/include/accommon.h>
431fc1a228SAndrew Turner
441fc1a228SAndrew Turner #include <dev/acpica/acpivar.h>
451fc1a228SAndrew Turner #include <dev/gpio/gpiobusvar.h>
461fc1a228SAndrew Turner
471fc1a228SAndrew Turner #include "pl061.h"
481fc1a228SAndrew Turner
491fc1a228SAndrew Turner static char *gpio_ids[] = { "ARMH0061", NULL };
501fc1a228SAndrew Turner
511fc1a228SAndrew Turner static int
pl061_acpi_probe(device_t dev)521fc1a228SAndrew Turner pl061_acpi_probe(device_t dev)
531fc1a228SAndrew Turner {
541fc1a228SAndrew Turner int rv;
551fc1a228SAndrew Turner
561fc1a228SAndrew Turner if (acpi_disabled("gpio"))
571fc1a228SAndrew Turner return (ENXIO);
581fc1a228SAndrew Turner
591fc1a228SAndrew Turner rv = ACPI_ID_PROBE(device_get_parent(dev), dev, gpio_ids, NULL);
601fc1a228SAndrew Turner
611fc1a228SAndrew Turner if (rv <= 0)
621fc1a228SAndrew Turner device_set_desc(dev, "Arm PL061 GPIO Controller");
631fc1a228SAndrew Turner
641fc1a228SAndrew Turner return (rv);
651fc1a228SAndrew Turner }
661fc1a228SAndrew Turner
671fc1a228SAndrew Turner static int
pl061_acpi_attach(device_t dev)681fc1a228SAndrew Turner pl061_acpi_attach(device_t dev)
691fc1a228SAndrew Turner {
701fc1a228SAndrew Turner int error;
711fc1a228SAndrew Turner
721fc1a228SAndrew Turner error = pl061_attach(dev);
731fc1a228SAndrew Turner if (error != 0)
741fc1a228SAndrew Turner return (error);
751fc1a228SAndrew Turner
7615fe2adaSAndrew Turner if (!intr_pic_register(dev, ACPI_GPIO_XREF)) {
771fc1a228SAndrew Turner device_printf(dev, "couldn't register PIC\n");
781fc1a228SAndrew Turner pl061_detach(dev);
791fc1a228SAndrew Turner error = ENXIO;
801fc1a228SAndrew Turner }
811fc1a228SAndrew Turner
821fc1a228SAndrew Turner return (error);
831fc1a228SAndrew Turner }
841fc1a228SAndrew Turner
851fc1a228SAndrew Turner static device_method_t pl061_acpi_methods[] = {
861fc1a228SAndrew Turner /* Device interface */
871fc1a228SAndrew Turner DEVMETHOD(device_probe, pl061_acpi_probe),
881fc1a228SAndrew Turner DEVMETHOD(device_attach, pl061_acpi_attach),
891fc1a228SAndrew Turner
901fc1a228SAndrew Turner DEVMETHOD_END
911fc1a228SAndrew Turner };
921fc1a228SAndrew Turner
93128e746cSAndrew Turner DEFINE_CLASS_1(gpio, pl061_acpi_driver, pl061_acpi_methods,
941fc1a228SAndrew Turner sizeof(struct pl061_softc), pl061_driver);
951fc1a228SAndrew Turner
9684c5f982SJohn Baldwin EARLY_DRIVER_MODULE(pl061, acpi, pl061_acpi_driver, NULL, NULL,
9715fe2adaSAndrew Turner BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
981fc1a228SAndrew Turner MODULE_DEPEND(pl061, acpi, 1, 1, 1);
991fc1a228SAndrew Turner MODULE_DEPEND(pl061, gpiobus, 1, 1, 1);
100