Home | History | Annotate | Line # | Download | only in acpi
      1  1.3   andvar /* $NetBSD: igpio_acpi.c,v 1.3 2024/02/02 22:14:05 andvar Exp $ */
      2  1.1     manu 
      3  1.1     manu /*-
      4  1.1     manu  * Copyright (c) 2021,2022 Emmanuel Dreyfus
      5  1.1     manu  * All rights reserved.
      6  1.1     manu  *
      7  1.1     manu  * Redistribution and use in source and binary forms, with or without
      8  1.1     manu  * modification, are permitted provided that the following conditions
      9  1.1     manu  * are met:
     10  1.1     manu  * 1. Redistributions of source code must retain the above copyright
     11  1.1     manu  *    notice, this list of conditions and the following disclaimer.
     12  1.1     manu  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1     manu  *    notice, this list of conditions and the following disclaimer in the
     14  1.1     manu  *    documentation and/or other materials provided with the distribution.
     15  1.1     manu  *
     16  1.1     manu  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17  1.1     manu  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  1.1     manu  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  1.1     manu  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20  1.1     manu  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  1.1     manu  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  1.1     manu  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23  1.1     manu  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24  1.1     manu  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25  1.1     manu  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  1.1     manu  * POSSIBILITY OF SUCH DAMAGE.
     27  1.1     manu  */
     28  1.1     manu 
     29  1.1     manu #include <sys/cdefs.h>
     30  1.3   andvar __KERNEL_RCSID(0, "$NetBSD: igpio_acpi.c,v 1.3 2024/02/02 22:14:05 andvar Exp $");
     31  1.1     manu 
     32  1.1     manu #include <sys/param.h>
     33  1.1     manu #include <sys/kmem.h>
     34  1.1     manu #include <sys/bus.h>
     35  1.1     manu #include <sys/cpu.h>
     36  1.1     manu #include <sys/device.h>
     37  1.1     manu #include <sys/gpio.h>
     38  1.1     manu 
     39  1.1     manu #include <dev/acpi/acpireg.h>
     40  1.1     manu #include <dev/acpi/acpivar.h>
     41  1.1     manu #include <dev/acpi/acpi_intr.h>
     42  1.1     manu #include <dev/acpi/acpi_event.h>
     43  1.1     manu 
     44  1.1     manu #include <dev/gpio/gpiovar.h>
     45  1.1     manu #include <dev/ic/igpiovar.h>
     46  1.1     manu 
     47  1.1     manu struct igpio_acpi_softc {
     48  1.1     manu 	ACPI_HANDLE		sc_handle;
     49  1.1     manu 	struct igpio_softc	sc_isc;
     50  1.1     manu 	struct acpi_event *	sc_event[8];
     51  1.1     manu 	int			sc_pmf;
     52  1.1     manu 	void			*sc_intr;
     53  1.1     manu };
     54  1.1     manu 
     55  1.1     manu static int	igpio_acpi_match(device_t, cfdata_t, void *);
     56  1.1     manu static void	igpio_acpi_attach(device_t, device_t, void *);
     57  1.1     manu static int	igpio_acpi_detach(device_t, int);
     58  1.1     manu 
     59  1.1     manu static void	igpio_acpi_register_event(void *, struct acpi_event *, ACPI_RESOURCE_GPIO *);
     60  1.1     manu static int	igpio_acpi_intr(void *);
     61  1.1     manu 
     62  1.1     manu CFATTACH_DECL_NEW(igpio_acpi, sizeof(struct igpio_acpi_softc), igpio_acpi_match, igpio_acpi_attach, igpio_acpi_detach, NULL);
     63  1.1     manu 
     64  1.1     manu static const struct device_compatible_entry compat_data[] = {
     65  1.1     manu 	{ .compat = "INT344B" },	/* sunrisepoint */
     66  1.1     manu 	{ .compat = "INT3450" },	/* cannonlake */
     67  1.1     manu 	{ .compat = "INT3451" },	/* sunrisepoint */
     68  1.1     manu 	{ .compat = "INT3453" },	/* geminilake */
     69  1.1     manu 	{ .compat = "INT3455" },	/* icelake */
     70  1.1     manu 	{ .compat = "INT345D" },	/* sunrisepoint */
     71  1.1     manu 	{ .compat = "INT34BB" },	/* cannonlake */
     72  1.1     manu 	{ .compat = "INT34C4" },	/* lakefield */
     73  1.1     manu 	{ .compat = "INT34C5" },	/* tigerlake */
     74  1.1     manu 	{ .compat = "INT34C6" },	/* tigerlake */
     75  1.1     manu 	{ .compat = "INT34C8" },	/* jasperlake */
     76  1.1     manu 	{ .compat = "INT3536" },	/* lewisburg */
     77  1.1     manu 	{ .compat = "INTC1055" },	/* tigerlake */
     78  1.1     manu 	{ .compat = "INTC1056" },	/* alderlake */
     79  1.1     manu 	{ .compat = "INTC1057" },	/* tigerlake */
     80  1.1     manu 	{ .compat = "INTC1071" },	/* emmitsburg */
     81  1.1     manu 	{ .compat = "INTC3000" },	/* denverton */
     82  1.1     manu 	{ .compat = "INTC3001" },	/* cedarfork */
     83  1.1     manu #ifdef notyet
     84  1.1     manu 	/*
     85  1.1     manu 	 * Complete bank setup in src/sys/dev/ic/igpioreg.h
     86  1.1     manu 	 * before enabling
     87  1.1     manu 	 */
     88  1.2  msaitoh 	{ .compat = "INT33B2" },	/* baytrail */
     89  1.2  msaitoh 	{ .compat = "INT33C7" },	/* lynxpoint */
     90  1.2  msaitoh 	{ .compat = "INT33FC" },	/* baytrail */
     91  1.2  msaitoh 	{ .compat = "INT3437" },	/* lynxpoint */
     92  1.1     manu 	{ .compat = "INT3452" },	/* broxton */
     93  1.1     manu 	{ .compat = "INT34D1" },	/* broxton */
     94  1.1     manu 	{ .compat = "apollolake-pinctrl" },	/* broxton */
     95  1.1     manu 	{ .compat = "broxton-pinctrl" },	/* broxton */
     96  1.1     manu 	{ .compat = "INT33FF" },	/* cherryview */
     97  1.1     manu #endif
     98  1.1     manu 	DEVICE_COMPAT_EOL
     99  1.1     manu };
    100  1.1     manu 
    101  1.1     manu static int
    102  1.1     manu igpio_acpi_match(device_t parent, cfdata_t cf, void *aux)
    103  1.1     manu {
    104  1.1     manu 	struct acpi_attach_args *aa = aux;
    105  1.1     manu 
    106  1.1     manu 	return acpi_compatible_match(aa, compat_data);
    107  1.1     manu }
    108  1.1     manu 
    109  1.1     manu static void
    110  1.1     manu igpio_acpi_attach(device_t parent, device_t self, void *aux)
    111  1.1     manu {
    112  1.1     manu 	struct igpio_acpi_softc * const asc = device_private(self);
    113  1.1     manu 	struct acpi_attach_args *aa = aux;
    114  1.1     manu 	ACPI_DEVICE_INFO *ad = aa->aa_node->ad_devinfo;
    115  1.1     manu 	struct acpi_resources res;
    116  1.1     manu 	struct acpi_mem *mem;
    117  1.1     manu 	struct acpi_irq *irq;
    118  1.1     manu 	int nbar;
    119  1.1     manu 	ACPI_STATUS rv;
    120  1.1     manu 	int i;
    121  1.1     manu 
    122  1.1     manu 	asc->sc_handle = aa->aa_node->ad_handle;
    123  1.1     manu 
    124  1.1     manu 	rv = acpi_resource_parse(self, aa->aa_node->ad_handle, "_CRS",
    125  1.1     manu 	    &res, &acpi_resource_parse_ops_default);
    126  1.1     manu 	if (ACPI_FAILURE(rv))
    127  1.1     manu 		return;
    128  1.1     manu 
    129  1.1     manu 	irq = acpi_res_irq(&res, 0);
    130  1.1     manu 	if (irq == NULL) {
    131  1.1     manu 		aprint_error_dev(self, "couldn't find irq resource\n");
    132  1.1     manu 		goto done;
    133  1.1     manu 	}
    134  1.1     manu 
    135  1.1     manu 	asc->sc_isc.sc_dev = self;
    136  1.1     manu 
    137  1.1     manu 	asc->sc_isc.sc_bst = aa->aa_memt;
    138  1.1     manu 	for (nbar = 0; acpi_res_mem(&res, nbar); nbar++);
    139  1.1     manu 	asc->sc_isc.sc_nbar = nbar;
    140  1.1     manu 	asc->sc_isc.sc_base =
    141  1.1     manu 	    kmem_zalloc(sizeof(*asc->sc_isc.sc_base) * nbar, KM_SLEEP);
    142  1.1     manu 	asc->sc_isc.sc_length =
    143  1.1     manu 	    kmem_zalloc(sizeof(*asc->sc_isc.sc_length) * nbar, KM_SLEEP);
    144  1.1     manu 	asc->sc_isc.sc_bsh =
    145  1.1     manu 	    kmem_zalloc(sizeof(*asc->sc_isc.sc_bsh) * nbar, KM_SLEEP);
    146  1.1     manu 
    147  1.1     manu 	asc->sc_isc.sc_acpi_hid = ad->HardwareId.String;
    148  1.1     manu 
    149  1.1     manu 	for (i = 0; i < nbar; i++) {
    150  1.1     manu 		mem = acpi_res_mem(&res, i);
    151  1.1     manu 		if (mem == NULL) {
    152  1.1     manu 			aprint_error_dev(self, "couldn't find mem resource\n");
    153  1.1     manu 			goto done;
    154  1.1     manu 		}
    155  1.1     manu 
    156  1.1     manu 		asc->sc_isc.sc_base[i] = mem->ar_base;
    157  1.1     manu 		asc->sc_isc.sc_length[i] = mem->ar_length;
    158  1.1     manu 	}
    159  1.1     manu 
    160  1.1     manu 	igpio_attach(&asc->sc_isc);
    161  1.1     manu 
    162  1.3   andvar 	/* If attachment failed */
    163  1.1     manu 	if (asc->sc_isc.sc_banks == NULL) {
    164  1.1     manu 		igpio_acpi_detach(self, 0);
    165  1.1     manu 		goto done;
    166  1.1     manu 	}
    167  1.1     manu 
    168  1.1     manu 	rv = acpi_event_create_gpio(self, asc->sc_handle, igpio_acpi_register_event, asc);
    169  1.1     manu 	if (ACPI_FAILURE(rv)) {
    170  1.1     manu 		if (rv != AE_NOT_FOUND)
    171  1.1     manu 			aprint_error_dev(self, "failed to create events: %s\n", AcpiFormatException(rv));
    172  1.1     manu 		goto done;
    173  1.1     manu 	}
    174  1.1     manu 
    175  1.1     manu 	asc->sc_intr = acpi_intr_establish(self,
    176  1.1     manu 	    (uint64_t)(uintptr_t)asc->sc_handle,
    177  1.1     manu 	    IPL_VM, false, igpio_acpi_intr, asc, device_xname(self));
    178  1.1     manu 	if (asc->sc_intr == NULL)
    179  1.1     manu 		aprint_error_dev(self, "couldn't establish interrupt\n");
    180  1.1     manu 
    181  1.1     manu done:
    182  1.1     manu 	acpi_resource_cleanup(&res);
    183  1.1     manu 	(void)pmf_device_register(self, NULL, NULL);
    184  1.1     manu 	asc->sc_pmf = 1;
    185  1.1     manu }
    186  1.1     manu 
    187  1.1     manu static int
    188  1.1     manu igpio_acpi_detach(device_t self, int flags)
    189  1.1     manu {
    190  1.1     manu 	struct igpio_acpi_softc * const asc = device_private(self);
    191  1.1     manu 	struct igpio_softc * const isc = &asc->sc_isc;
    192  1.1     manu 	int nbar = isc->sc_nbar;
    193  1.1     manu 
    194  1.1     manu 	acpi_intr_disestablish(asc->sc_intr);
    195  1.1     manu 
    196  1.1     manu 	igpio_detach(&asc->sc_isc);
    197  1.1     manu 
    198  1.1     manu 	if (isc->sc_base != NULL) {
    199  1.1     manu 		kmem_free(isc->sc_base, sizeof(*isc->sc_base) * nbar);
    200  1.1     manu 		isc->sc_base = NULL;
    201  1.1     manu 	}
    202  1.1     manu 
    203  1.1     manu 	if (isc->sc_length != NULL) {
    204  1.1     manu 		kmem_free(isc->sc_length, sizeof(*isc->sc_length) * nbar);
    205  1.1     manu 		isc->sc_length = NULL;
    206  1.1     manu 	}
    207  1.1     manu 
    208  1.1     manu 	if (isc->sc_bsh != NULL) {
    209  1.1     manu 		kmem_free(isc->sc_bsh, sizeof(*isc->sc_bsh) * nbar);
    210  1.1     manu 		isc->sc_length = NULL;
    211  1.1     manu 	}
    212  1.1     manu 
    213  1.1     manu 	if (asc->sc_pmf) {
    214  1.1     manu 		pmf_device_deregister(self);
    215  1.1     manu 		asc->sc_pmf = 0;
    216  1.1     manu 	}
    217  1.1     manu 
    218  1.1     manu 	return 0;
    219  1.1     manu }
    220  1.1     manu 
    221  1.1     manu static void
    222  1.1     manu igpio_acpi_register_event(void *priv, struct acpi_event *ev, ACPI_RESOURCE_GPIO *gpio)
    223  1.1     manu {
    224  1.1     manu 	return;
    225  1.1     manu }
    226  1.1     manu 
    227  1.1     manu static int
    228  1.1     manu igpio_acpi_intr(void *priv)
    229  1.1     manu {
    230  1.1     manu 	struct igpio_acpi_softc *asc = priv;
    231  1.1     manu 	struct igpio_softc * const isc = &asc->sc_isc;
    232  1.1     manu 	int ret;
    233  1.1     manu 
    234  1.1     manu 	ret = igpio_intr(isc);
    235  1.1     manu 
    236  1.1     manu 	return ret;
    237  1.1     manu }
    238