Add initial support for Intel GPIO chips
This commit is contained in:
parent
9d5e1357c3
commit
b33073320a
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: GENERIC,v 1.593 2021/10/31 00:31:48 simonb Exp $
|
||||
# $NetBSD: GENERIC,v 1.594 2022/03/24 02:24:24 manu Exp $
|
||||
#
|
||||
# GENERIC machine description file
|
||||
#
|
||||
|
@ -22,7 +22,7 @@ include "arch/amd64/conf/std.amd64"
|
|||
|
||||
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
|
||||
|
||||
#ident "GENERIC-$Revision: 1.593 $"
|
||||
#ident "GENERIC-$Revision: 1.594 $"
|
||||
|
||||
maxusers 64 # estimated number of users
|
||||
|
||||
|
@ -596,6 +596,9 @@ iic* at dwiic?
|
|||
#sdtemp* at iic? addr 0x1e
|
||||
#sdtemp* at iic? addr 0x1f
|
||||
|
||||
# Intel GPIO
|
||||
igpio* at acpi?
|
||||
|
||||
# I2C HID devices
|
||||
ihidev* at iic?
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: files,v 1.1295 2022/02/16 20:14:30 riastradh Exp $
|
||||
# $NetBSD: files,v 1.1296 2022/03/24 02:24:24 manu Exp $
|
||||
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
|
||||
|
||||
version 20171118
|
||||
|
@ -1357,6 +1357,10 @@ file dev/ic/pl061.c plgpio
|
|||
device plmmc: sdmmcbus
|
||||
file dev/ic/pl181.c plmmc
|
||||
|
||||
# Intel GPIO
|
||||
device igpio: gpiobus
|
||||
file dev/ic/igpio.c igpio
|
||||
|
||||
# Myson MTD803 3-in-1 Fast Ethernet Controller
|
||||
device mtd: arp, ether, ifnet, mii
|
||||
file dev/ic/mtd803.c mtd
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: files.acpi,v 1.124 2022/02/16 20:14:30 riastradh Exp $
|
||||
# $NetBSD: files.acpi,v 1.125 2022/03/24 02:24:25 manu Exp $
|
||||
|
||||
defflag opt_acpi.h ACPIVERBOSE ACPI_DEBUG ACPI_ACTIVATE_DEV
|
||||
ACPI_DSDT_OVERRIDE ACPI_SCANPCI ACPI_BREAKPOINT
|
||||
|
@ -300,6 +300,10 @@ file dev/acpi/genet_acpi.c genet_acpi
|
|||
attach eqos at acpinodebus with eqos_acpi
|
||||
file dev/acpi/eqos_acpi.c eqos_acpi
|
||||
|
||||
# Intel GPIO
|
||||
attach igpio at acpinodebus with igpio_acpi
|
||||
file dev/acpi/igpio_acpi.c igpio_acpi
|
||||
|
||||
# DesignWare Mobile Storage Host Controller
|
||||
attach dwcmmc at acpinodebus with dwcmmc_acpi
|
||||
file dev/acpi/dwcmmc_acpi.c dwcmmc_acpi
|
||||
|
|
|
@ -0,0 +1,237 @@
|
|||
/* $NetBSD: igpio_acpi.c,v 1.1 2022/03/24 02:24:25 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2021,2022 Emmanuel Dreyfus
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: igpio_acpi.c,v 1.1 2022/03/24 02:24:25 manu Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kmem.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/cpu.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/gpio.h>
|
||||
|
||||
#include <dev/acpi/acpireg.h>
|
||||
#include <dev/acpi/acpivar.h>
|
||||
#include <dev/acpi/acpi_intr.h>
|
||||
#include <dev/acpi/acpi_event.h>
|
||||
|
||||
#include <dev/gpio/gpiovar.h>
|
||||
#include <dev/ic/igpiovar.h>
|
||||
|
||||
struct igpio_acpi_softc {
|
||||
ACPI_HANDLE sc_handle;
|
||||
struct igpio_softc sc_isc;
|
||||
struct acpi_event * sc_event[8];
|
||||
int sc_pmf;
|
||||
void *sc_intr;
|
||||
};
|
||||
|
||||
static int igpio_acpi_match(device_t, cfdata_t, void *);
|
||||
static void igpio_acpi_attach(device_t, device_t, void *);
|
||||
static int igpio_acpi_detach(device_t, int);
|
||||
|
||||
static void igpio_acpi_register_event(void *, struct acpi_event *, ACPI_RESOURCE_GPIO *);
|
||||
static int igpio_acpi_intr(void *);
|
||||
|
||||
CFATTACH_DECL_NEW(igpio_acpi, sizeof(struct igpio_acpi_softc), igpio_acpi_match, igpio_acpi_attach, igpio_acpi_detach, NULL);
|
||||
|
||||
static const struct device_compatible_entry compat_data[] = {
|
||||
{ .compat = "INT33B2" }, /* baytrail */
|
||||
{ .compat = "INT33C7" }, /* lynxpoint */
|
||||
{ .compat = "INT33FC" }, /* baytrail */
|
||||
{ .compat = "INT3437" }, /* lynxpoint */
|
||||
{ .compat = "INT344B" }, /* sunrisepoint */
|
||||
{ .compat = "INT3450" }, /* cannonlake */
|
||||
{ .compat = "INT3451" }, /* sunrisepoint */
|
||||
{ .compat = "INT3453" }, /* geminilake */
|
||||
{ .compat = "INT3455" }, /* icelake */
|
||||
{ .compat = "INT345D" }, /* sunrisepoint */
|
||||
{ .compat = "INT34BB" }, /* cannonlake */
|
||||
{ .compat = "INT34C4" }, /* lakefield */
|
||||
{ .compat = "INT34C5" }, /* tigerlake */
|
||||
{ .compat = "INT34C6" }, /* tigerlake */
|
||||
{ .compat = "INT34C8" }, /* jasperlake */
|
||||
{ .compat = "INT3536" }, /* lewisburg */
|
||||
{ .compat = "INTC1055" }, /* tigerlake */
|
||||
{ .compat = "INTC1056" }, /* alderlake */
|
||||
{ .compat = "INTC1057" }, /* tigerlake */
|
||||
{ .compat = "INTC1071" }, /* emmitsburg */
|
||||
{ .compat = "INTC3000" }, /* denverton */
|
||||
{ .compat = "INTC3001" }, /* cedarfork */
|
||||
#ifdef notyet
|
||||
/*
|
||||
* Complete bank setup in src/sys/dev/ic/igpioreg.h
|
||||
* before enabling
|
||||
*/
|
||||
{ .compat = "INT3452" }, /* broxton */
|
||||
{ .compat = "INT34D1" }, /* broxton */
|
||||
{ .compat = "apollolake-pinctrl" }, /* broxton */
|
||||
{ .compat = "broxton-pinctrl" }, /* broxton */
|
||||
{ .compat = "INT33FF" }, /* cherryview */
|
||||
#endif
|
||||
DEVICE_COMPAT_EOL
|
||||
};
|
||||
|
||||
static int
|
||||
igpio_acpi_match(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
struct acpi_attach_args *aa = aux;
|
||||
|
||||
return acpi_compatible_match(aa, compat_data);
|
||||
}
|
||||
|
||||
static void
|
||||
igpio_acpi_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct igpio_acpi_softc * const asc = device_private(self);
|
||||
struct acpi_attach_args *aa = aux;
|
||||
ACPI_DEVICE_INFO *ad = aa->aa_node->ad_devinfo;
|
||||
struct acpi_resources res;
|
||||
struct acpi_mem *mem;
|
||||
struct acpi_irq *irq;
|
||||
int nbar;
|
||||
ACPI_STATUS rv;
|
||||
int i;
|
||||
|
||||
asc->sc_handle = aa->aa_node->ad_handle;
|
||||
|
||||
rv = acpi_resource_parse(self, aa->aa_node->ad_handle, "_CRS",
|
||||
&res, &acpi_resource_parse_ops_default);
|
||||
if (ACPI_FAILURE(rv))
|
||||
return;
|
||||
|
||||
irq = acpi_res_irq(&res, 0);
|
||||
if (irq == NULL) {
|
||||
aprint_error_dev(self, "couldn't find irq resource\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
asc->sc_isc.sc_dev = self;
|
||||
|
||||
asc->sc_isc.sc_bst = aa->aa_memt;
|
||||
for (nbar = 0; acpi_res_mem(&res, nbar); nbar++);
|
||||
asc->sc_isc.sc_nbar = nbar;
|
||||
asc->sc_isc.sc_base =
|
||||
kmem_zalloc(sizeof(*asc->sc_isc.sc_base) * nbar, KM_SLEEP);
|
||||
asc->sc_isc.sc_length =
|
||||
kmem_zalloc(sizeof(*asc->sc_isc.sc_length) * nbar, KM_SLEEP);
|
||||
asc->sc_isc.sc_bsh =
|
||||
kmem_zalloc(sizeof(*asc->sc_isc.sc_bsh) * nbar, KM_SLEEP);
|
||||
|
||||
asc->sc_isc.sc_acpi_hid = ad->HardwareId.String;
|
||||
|
||||
for (i = 0; i < nbar; i++) {
|
||||
mem = acpi_res_mem(&res, i);
|
||||
if (mem == NULL) {
|
||||
aprint_error_dev(self, "couldn't find mem resource\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
asc->sc_isc.sc_base[i] = mem->ar_base;
|
||||
asc->sc_isc.sc_length[i] = mem->ar_length;
|
||||
}
|
||||
|
||||
igpio_attach(&asc->sc_isc);
|
||||
|
||||
/* If attachement failed */
|
||||
if (asc->sc_isc.sc_banks == NULL) {
|
||||
igpio_acpi_detach(self, 0);
|
||||
goto done;
|
||||
}
|
||||
|
||||
rv = acpi_event_create_gpio(self, asc->sc_handle, igpio_acpi_register_event, asc);
|
||||
if (ACPI_FAILURE(rv)) {
|
||||
if (rv != AE_NOT_FOUND)
|
||||
aprint_error_dev(self, "failed to create events: %s\n", AcpiFormatException(rv));
|
||||
goto done;
|
||||
}
|
||||
|
||||
asc->sc_intr = acpi_intr_establish(self,
|
||||
(uint64_t)(uintptr_t)asc->sc_handle,
|
||||
IPL_VM, false, igpio_acpi_intr, asc, device_xname(self));
|
||||
if (asc->sc_intr == NULL)
|
||||
aprint_error_dev(self, "couldn't establish interrupt\n");
|
||||
|
||||
done:
|
||||
acpi_resource_cleanup(&res);
|
||||
(void)pmf_device_register(self, NULL, NULL);
|
||||
asc->sc_pmf = 1;
|
||||
}
|
||||
|
||||
static int
|
||||
igpio_acpi_detach(device_t self, int flags)
|
||||
{
|
||||
struct igpio_acpi_softc * const asc = device_private(self);
|
||||
struct igpio_softc * const isc = &asc->sc_isc;
|
||||
int nbar = isc->sc_nbar;
|
||||
|
||||
acpi_intr_disestablish(asc->sc_intr);
|
||||
|
||||
igpio_detach(&asc->sc_isc);
|
||||
|
||||
if (isc->sc_base != NULL) {
|
||||
kmem_free(isc->sc_base, sizeof(*isc->sc_base) * nbar);
|
||||
isc->sc_base = NULL;
|
||||
}
|
||||
|
||||
if (isc->sc_length != NULL) {
|
||||
kmem_free(isc->sc_length, sizeof(*isc->sc_length) * nbar);
|
||||
isc->sc_length = NULL;
|
||||
}
|
||||
|
||||
if (isc->sc_bsh != NULL) {
|
||||
kmem_free(isc->sc_bsh, sizeof(*isc->sc_bsh) * nbar);
|
||||
isc->sc_length = NULL;
|
||||
}
|
||||
|
||||
if (asc->sc_pmf) {
|
||||
pmf_device_deregister(self);
|
||||
asc->sc_pmf = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
igpio_acpi_register_event(void *priv, struct acpi_event *ev, ACPI_RESOURCE_GPIO *gpio)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
igpio_acpi_intr(void *priv)
|
||||
{
|
||||
struct igpio_acpi_softc *asc = priv;
|
||||
struct igpio_softc * const isc = &asc->sc_isc;
|
||||
int ret;
|
||||
|
||||
ret = igpio_intr(isc);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,806 @@
|
|||
/* $NetBSD: igpio.c,v 1.1 2022/03/24 02:24:25 manu Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2021,2022 Emmanuel Dreyfus
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/intr.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/kmem.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/gpio.h>
|
||||
|
||||
#include <dev/gpio/gpiovar.h>
|
||||
#include "gpio.h"
|
||||
|
||||
#include <dev/ic/igpiovar.h>
|
||||
#include <dev/ic/igpioreg.h>
|
||||
|
||||
struct igpio_intr {
|
||||
int (*ii_func)(void *);
|
||||
void *ii_arg;
|
||||
struct igpio_bank *ii_bank;
|
||||
int ii_pin;
|
||||
};
|
||||
|
||||
struct igpio_bank {
|
||||
int ib_barno;
|
||||
int ib_revid;
|
||||
int ib_cap;
|
||||
int ib_padbar;
|
||||
struct igpio_bank_setup *ib_setup;
|
||||
struct igpio_softc *ib_sc;
|
||||
struct igpio_intr *ib_intr;
|
||||
kmutex_t ib_mtx;
|
||||
};
|
||||
|
||||
|
||||
static int igpio_debug = 0;
|
||||
#define DPRINTF(x) if (igpio_debug) printf x;
|
||||
|
||||
static char *
|
||||
igpio_padcfg0_print(uint32_t val, int idx)
|
||||
{
|
||||
uint32_t rxev, pmode;
|
||||
static char buf0[256];
|
||||
static char buf1[256];
|
||||
char *buf = (idx % 2) ? &buf0[0] : &buf1[0];
|
||||
size_t len = sizeof(buf0) - 1;
|
||||
size_t wr = 0;
|
||||
uint32_t unknown_bits =
|
||||
__BITS(3,7)|__BITS(14,16)|__BITS(21,22)|__BITS(27,31);
|
||||
int b;
|
||||
|
||||
rxev =
|
||||
(val & IGPIO_PADCFG0_RXEVCFG_MASK) >> IGPIO_PADCFG0_RXEVCFG_SHIFT;
|
||||
wr += snprintf(buf + wr, len - wr, "rxev ");
|
||||
switch (rxev) {
|
||||
case IGPIO_PADCFG0_RXEVCFG_LEVEL:
|
||||
wr += snprintf(buf + wr, len - wr, "level");
|
||||
break;
|
||||
case IGPIO_PADCFG0_RXEVCFG_EDGE:
|
||||
wr += snprintf(buf + wr, len - wr, "edge");
|
||||
break;
|
||||
case IGPIO_PADCFG0_RXEVCFG_DISABLED:
|
||||
wr += snprintf(buf + wr, len - wr, "disabled");
|
||||
break;
|
||||
case IGPIO_PADCFG0_RXEVCFG_EDGE_BOTH:
|
||||
wr += snprintf(buf + wr, len - wr, "edge both");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (val & IGPIO_PADCFG0_PREGFRXSEL)
|
||||
wr += snprintf(buf + wr, len - wr, ", pregfrxsel");
|
||||
|
||||
if (val & IGPIO_PADCFG0_RXINV)
|
||||
wr += snprintf(buf + wr, len - wr, ", rxinv");
|
||||
|
||||
if (val & (IGPIO_PADCFG0_GPIROUTIOXAPIC|IGPIO_PADCFG0_GPIROUTSCI|
|
||||
IGPIO_PADCFG0_GPIROUTSMI|IGPIO_PADCFG0_GPIROUTNMI)) {
|
||||
wr += snprintf(buf + wr, len - wr, ", gpirout");
|
||||
|
||||
if (val & IGPIO_PADCFG0_GPIROUTIOXAPIC)
|
||||
wr += snprintf(buf + wr, len - wr, " ioxapic");
|
||||
|
||||
if (val & IGPIO_PADCFG0_GPIROUTSCI)
|
||||
wr += snprintf(buf + wr, len - wr, " sci");
|
||||
|
||||
if (val & IGPIO_PADCFG0_GPIROUTSMI)
|
||||
wr += snprintf(buf + wr, len - wr, " smi");
|
||||
|
||||
if (val & IGPIO_PADCFG0_GPIROUTNMI)
|
||||
wr += snprintf(buf + wr, len - wr, " nmi");
|
||||
}
|
||||
|
||||
pmode =
|
||||
(val & IGPIO_PADCFG0_PMODE_MASK) >> IGPIO_PADCFG0_PMODE_SHIFT;
|
||||
switch (pmode) {
|
||||
case IGPIO_PADCFG0_PMODE_GPIO:
|
||||
wr += snprintf(buf + wr, len - wr, ", pmode gpio");
|
||||
break;
|
||||
default:
|
||||
wr += snprintf(buf + wr, len - wr, ", pmode %d", pmode);
|
||||
break;
|
||||
}
|
||||
|
||||
if (val & IGPIO_PADCFG0_GPIORXDIS)
|
||||
wr += snprintf(buf + wr, len - wr, ", rx disabled");
|
||||
else
|
||||
wr += snprintf(buf + wr, len - wr, ", rx %d",
|
||||
!!(val & IGPIO_PADCFG0_GPIORXSTATE));
|
||||
|
||||
if (val & IGPIO_PADCFG0_GPIOTXDIS)
|
||||
wr += snprintf(buf + wr, len - wr, ", tx disabled");
|
||||
else
|
||||
wr += snprintf(buf + wr, len - wr, ", tx %d",
|
||||
!!(val & IGPIO_PADCFG0_GPIOTXSTATE));
|
||||
|
||||
if (val & unknown_bits) {
|
||||
wr += snprintf(buf + wr, len - wr, ", unknown bits");
|
||||
for (b = 0; b < 32; b++) {
|
||||
if (!(__BIT(b) & unknown_bits & val))
|
||||
continue;
|
||||
wr += snprintf(buf + wr, len - wr, " %d", b);
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
static struct igpio_bank_setup *
|
||||
igpio_find_bank_setup(struct igpio_bank *ib, int barno)
|
||||
{
|
||||
struct igpio_bank_setup *ibs;
|
||||
|
||||
for (ibs = igpio_bank_setup; ibs->ibs_acpi_hid; ibs++) {
|
||||
if (strcmp(ib->ib_sc->sc_acpi_hid, ibs->ibs_acpi_hid) != 0)
|
||||
continue;
|
||||
if (ibs->ibs_barno != barno)
|
||||
continue;
|
||||
|
||||
return ibs;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct igpio_bank *
|
||||
igpio_find_bank(struct igpio_softc *sc, int pin)
|
||||
{
|
||||
int i;
|
||||
struct igpio_bank *ib;
|
||||
|
||||
for (i = 0; i < sc->sc_nbar; i++) {
|
||||
ib = &sc->sc_banks[i];
|
||||
if (pin >= ib->ib_setup->ibs_first_pin &&
|
||||
pin <= ib->ib_setup->ibs_last_pin)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ib = NULL;
|
||||
out:
|
||||
return ib;
|
||||
}
|
||||
|
||||
static int
|
||||
igpio_bank_pin(struct igpio_bank *ib, int pin)
|
||||
{
|
||||
return pin - ib->ib_setup->ibs_first_pin;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
igpio_hexdump(struct igpio_softc *sc, int n)
|
||||
{
|
||||
int i, j;
|
||||
uint8_t v;
|
||||
size_t len = MIN(sc->sc_length[n], 2048);
|
||||
|
||||
printf("bar %d\n", n);
|
||||
for (j = 0; j < len; j += 16) {
|
||||
printf("%04x ", j);
|
||||
for (i = 0; i < 16 && i + j < len; i++) {
|
||||
v = bus_space_read_1(sc->sc_bst, sc->sc_bsh[n], i + j);
|
||||
printf("%02x ", v);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
igpio_attach(struct igpio_softc *sc)
|
||||
{
|
||||
device_t self = sc->sc_dev;
|
||||
int i,j;
|
||||
struct gpiobus_attach_args gba;
|
||||
int success = 0;
|
||||
|
||||
sc->sc_banks =
|
||||
kmem_zalloc(sizeof(*sc->sc_banks) * sc->sc_nbar, KM_SLEEP);
|
||||
|
||||
sc->sc_npins = 0;
|
||||
|
||||
for (i = 0; i < sc->sc_nbar; i++) {
|
||||
struct igpio_bank *ib = &sc->sc_banks[i];
|
||||
struct igpio_bank_setup *ibs;
|
||||
bus_size_t reg;
|
||||
uint32_t val;
|
||||
int error;
|
||||
int npins;
|
||||
|
||||
ib->ib_barno = i;
|
||||
ib->ib_sc = sc;
|
||||
|
||||
mutex_init(&ib->ib_mtx, MUTEX_DEFAULT, IPL_VM);
|
||||
|
||||
error = bus_space_map(sc->sc_bst, sc->sc_base[i],
|
||||
sc->sc_length[i], 0, &sc->sc_bsh[i]);
|
||||
if (error) {
|
||||
aprint_error_dev(self, "couldn't map registers\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
reg = IGPIO_REVID;
|
||||
val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[i], reg);
|
||||
if (val == 0) {
|
||||
aprint_error_dev(self, "couldn't find revid\n");
|
||||
goto out;
|
||||
}
|
||||
ib->ib_revid = val >> 16;
|
||||
|
||||
DPRINTF(("revid[%d] = #%x\n", i, ib->ib_revid));
|
||||
|
||||
if (ib->ib_revid > 0x94) {
|
||||
ib->ib_cap |= IGPIO_PINCTRL_FEATURE_DEBOUNCE;
|
||||
ib->ib_cap |= IGPIO_PINCTRL_FEATURE_1K_PD;
|
||||
}
|
||||
|
||||
reg = IGPIO_CAPLIST;
|
||||
do {
|
||||
/* higher 16 bits: value, lower 16 bits, next reg */
|
||||
val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[i], reg);
|
||||
|
||||
reg = val & 0xffff;
|
||||
val = val >> 16;
|
||||
|
||||
switch (val) {
|
||||
case IGPIO_CAPLIST_ID_GPIO_HW_INFO:
|
||||
ib->ib_cap |=
|
||||
IGPIO_PINCTRL_FEATURE_GPIO_HW_INFO;
|
||||
break;
|
||||
case IGPIO_CAPLIST_ID_PWM:
|
||||
ib->ib_cap |= IGPIO_PINCTRL_FEATURE_PWM;
|
||||
break;
|
||||
case IGPIO_CAPLIST_ID_BLINK:
|
||||
ib->ib_cap |= IGPIO_PINCTRL_FEATURE_BLINK;
|
||||
break;
|
||||
case IGPIO_CAPLIST_ID_EXP:
|
||||
ib->ib_cap |= IGPIO_PINCTRL_FEATURE_EXP;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} while (reg);
|
||||
DPRINTF(("cap[%d] = #%x\n", i, ib->ib_cap));
|
||||
|
||||
reg = IGPIO_PADBAR;
|
||||
val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[i], reg);
|
||||
ib->ib_padbar = val;
|
||||
DPRINTF(("padbar[%d] = #%x\n", i, ib->ib_padbar));
|
||||
if (ib->ib_padbar > sc->sc_length[i]) {
|
||||
printf("PADBAR = #%x higher than max #%lx\n",
|
||||
ib->ib_padbar, sc->sc_length[i]);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ib->ib_setup = igpio_find_bank_setup(ib, i);
|
||||
if (ib->ib_setup == NULL) {
|
||||
printf("Missing BAR %d\n", i);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ibs = ib->ib_setup;
|
||||
|
||||
DPRINTF(("setup[%d] = "
|
||||
"{ barno = %d, first_pin = %d, last_pin = %d }\n",
|
||||
i, ibs->ibs_barno, ibs->ibs_first_pin, ibs->ibs_last_pin));
|
||||
|
||||
npins = 1 + ibs->ibs_last_pin - ibs->ibs_first_pin;
|
||||
|
||||
ib->ib_intr =
|
||||
kmem_zalloc(sizeof(*ib->ib_intr) * npins, KM_SLEEP);
|
||||
|
||||
sc->sc_npins += npins;
|
||||
}
|
||||
|
||||
if (sc->sc_npins < 1 || sc->sc_npins > 4096) {
|
||||
printf("Unexpected pin count %d\n", sc->sc_npins);
|
||||
goto out;
|
||||
}
|
||||
|
||||
sc->sc_pins =
|
||||
kmem_zalloc(sizeof(*sc->sc_pins) * sc->sc_npins, KM_SLEEP);
|
||||
|
||||
for (j = 0; j < sc->sc_npins; j++) {
|
||||
sc->sc_pins[j].pin_num = j;
|
||||
sc->sc_pins[j].pin_caps =
|
||||
GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_INOUT |
|
||||
GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN | GPIO_PIN_INVIN;
|
||||
sc->sc_pins[j].pin_intrcaps =
|
||||
GPIO_INTR_POS_EDGE | GPIO_INTR_NEG_EDGE |
|
||||
GPIO_INTR_DOUBLE_EDGE | GPIO_INTR_HIGH_LEVEL |
|
||||
GPIO_INTR_LOW_LEVEL | GPIO_INTR_MPSAFE;
|
||||
sc->sc_pins[j].pin_state = igpio_pin_read(sc, j);
|
||||
}
|
||||
|
||||
sc->sc_gc.gp_cookie = sc;
|
||||
sc->sc_gc.gp_pin_read = igpio_pin_read;
|
||||
sc->sc_gc.gp_pin_write = igpio_pin_write;
|
||||
sc->sc_gc.gp_pin_ctl = igpio_pin_ctl;
|
||||
sc->sc_gc.gp_intr_establish = igpio_intr_establish;
|
||||
sc->sc_gc.gp_intr_disestablish = igpio_intr_disestablish;
|
||||
sc->sc_gc.gp_intr_str = igpio_intr_str;
|
||||
|
||||
memset(&gba, 0, sizeof(gba));
|
||||
gba.gba_gc = &sc->sc_gc;
|
||||
gba.gba_pins = sc->sc_pins;
|
||||
gba.gba_npins = sc->sc_npins;
|
||||
|
||||
#if NGPIO > 0
|
||||
config_found(sc->sc_dev, &gba, gpiobus_print, CFARGS_NONE);
|
||||
#endif
|
||||
|
||||
success = 1;
|
||||
out:
|
||||
if (!success)
|
||||
igpio_detach(sc);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
igpio_detach(struct igpio_softc *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sc->sc_nbar; i++) {
|
||||
struct igpio_bank *ib = &sc->sc_banks[i];
|
||||
struct igpio_bank_setup *ibs = ib->ib_setup;
|
||||
int npins = 1 + ibs->ibs_last_pin - ibs->ibs_first_pin;
|
||||
|
||||
if (ib->ib_intr != NULL) {
|
||||
kmem_free(ib->ib_intr, sizeof(*ib->ib_intr) * npins);
|
||||
ib->ib_intr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (sc->sc_pins != NULL) {
|
||||
kmem_free(sc->sc_pins, sizeof(*sc->sc_pins) * sc->sc_npins);
|
||||
sc->sc_pins = NULL;
|
||||
}
|
||||
|
||||
if (sc->sc_banks != NULL) {
|
||||
kmem_free(sc->sc_banks, sizeof(*sc->sc_banks) * sc->sc_nbar);
|
||||
sc->sc_banks = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static bus_addr_t
|
||||
igpio_pincfg(struct igpio_bank *ib, int pin, int reg)
|
||||
{
|
||||
int nregs = (ib->ib_cap & IGPIO_PINCTRL_FEATURE_DEBOUNCE) ? 4 : 2;
|
||||
bus_addr_t pincfg;
|
||||
|
||||
pincfg = ib->ib_padbar + reg + (pin * nregs * 4);
|
||||
#if 0
|
||||
DPRINTF(("%s bar %d pin %d reg #%x pincfg = %p\n",
|
||||
__func__, ib->ib_barno, pin, reg, (void *)pincfg));
|
||||
#endif
|
||||
return pincfg;
|
||||
}
|
||||
|
||||
#if notyet
|
||||
static struct igpio_pin_group *
|
||||
igpio_find_group(struct igpio_bank *ib, int pin)
|
||||
{
|
||||
struct igpio_bank_setup *ibs = ib->ib_setup;
|
||||
struct igpio_pin_group *found_ipg = NULL;
|
||||
struct igpio_pin_group *ipg;
|
||||
|
||||
if (pin > ibs->ibs_last_pin) {
|
||||
DPRINTF(("%s: barno %d, pin = %d > past pin = %d\n", __func__,
|
||||
ibs->ibs_barno, pin, ibs->ibs_last_pin));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (ipg = igpio_pin_group; ipg->ipg_acpi_hid; ipg++) {
|
||||
if (strcmp(ipg->ipg_acpi_hid, ibs->ibs_acpi_hid) != 0)
|
||||
continue;
|
||||
|
||||
if (pin > ipg->ipg_first_pin) {
|
||||
found_ipg = ipg;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return found_ipg;
|
||||
}
|
||||
|
||||
static bus_addr_t
|
||||
igpio_groupcfg(struct igpio_bank *ib, int pin)
|
||||
{
|
||||
struct igpio_bank_setup *ibs = ib->ib_setup;
|
||||
struct igpio_pin_group *ipg;
|
||||
bus_addr_t groupcfg;
|
||||
|
||||
if ((ipg = igpio_find_group(ib, pin)) == NULL)
|
||||
return (bus_addr_t)NULL;
|
||||
|
||||
groupcfg = ib->ib_padbar
|
||||
+ (ipg->ipg_groupno * 4)
|
||||
+ (pin - ipg->ipg_first_pin) / 2;
|
||||
|
||||
DPRINTF(("%s: barno %d, pin = %d, found group %d \"%s\", cfg %p\n", \
|
||||
__func__, ibs->ibs_barno, pin, ipg->ipg_groupno, \
|
||||
ipg->ipg_name, (void *)groupcfg));
|
||||
|
||||
return groupcfg;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
igpio_pin_read(void *priv, int pin)
|
||||
{
|
||||
struct igpio_softc *sc = priv;
|
||||
struct igpio_bank *ib = igpio_find_bank(sc, pin);
|
||||
bus_addr_t cfg0;
|
||||
uint32_t val;
|
||||
|
||||
pin = igpio_bank_pin(ib, pin);
|
||||
cfg0 = igpio_pincfg(ib, pin, IGPIO_PADCFG0);
|
||||
|
||||
mutex_enter(&ib->ib_mtx);
|
||||
|
||||
val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0);
|
||||
DPRINTF(("%s: bar %d pin %d val #%x (%s)\n", __func__,
|
||||
ib->ib_barno, pin, val, igpio_padcfg0_print(val, 0)));
|
||||
|
||||
if (val & IGPIO_PADCFG0_GPIOTXDIS)
|
||||
val = (val & IGPIO_PADCFG0_GPIORXSTATE) ? 1 : 0;
|
||||
else
|
||||
val = (val & IGPIO_PADCFG0_GPIOTXSTATE) ? 1 : 0;
|
||||
|
||||
mutex_exit(&ib->ib_mtx);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void
|
||||
igpio_pin_write(void *priv, int pin, int value)
|
||||
{
|
||||
struct igpio_softc *sc = priv;
|
||||
struct igpio_bank *ib = igpio_find_bank(sc, pin);
|
||||
bus_addr_t cfg0;
|
||||
uint32_t val, newval;
|
||||
|
||||
pin = igpio_bank_pin(ib, pin);
|
||||
cfg0 = igpio_pincfg(ib, pin, IGPIO_PADCFG0);
|
||||
|
||||
mutex_enter(&ib->ib_mtx);
|
||||
|
||||
val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0);
|
||||
|
||||
if (value)
|
||||
newval = val | IGPIO_PADCFG0_GPIOTXSTATE;
|
||||
else
|
||||
newval = val & ~IGPIO_PADCFG0_GPIOTXSTATE;
|
||||
|
||||
DPRINTF(("%s: bar %d pin %d value %d val #%x (%s) -> #%x (%s)\n",
|
||||
__func__, ib->ib_barno, pin, value,
|
||||
val, igpio_padcfg0_print(val, 0),
|
||||
newval, igpio_padcfg0_print(newval, 1)));
|
||||
|
||||
bus_space_write_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0, newval);
|
||||
|
||||
mutex_exit(&ib->ib_mtx);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
igpio_pin_ctl(void *priv, int pin, int flags)
|
||||
{
|
||||
struct igpio_softc *sc = priv;
|
||||
struct igpio_bank *ib = igpio_find_bank(sc, pin);
|
||||
bus_addr_t cfg0, cfg1;
|
||||
uint32_t val0, newval0;
|
||||
uint32_t val1, newval1;
|
||||
|
||||
pin = igpio_bank_pin(ib, pin);
|
||||
cfg0 = igpio_pincfg(ib, pin, IGPIO_PADCFG0);
|
||||
cfg1 = igpio_pincfg(ib, pin, IGPIO_PADCFG1);
|
||||
|
||||
mutex_enter(&ib->ib_mtx);
|
||||
|
||||
val0 = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0);
|
||||
val1 = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg1);
|
||||
|
||||
newval0 = val0;
|
||||
newval1 = val1;
|
||||
|
||||
newval0 &= ~IGPIO_PADCFG0_PMODE_MASK;
|
||||
newval0 |= IGPIO_PADCFG0_PMODE_GPIO;
|
||||
|
||||
newval0 |= IGPIO_PADCFG0_GPIORXDIS;
|
||||
newval0 |= IGPIO_PADCFG0_GPIOTXDIS;
|
||||
|
||||
newval0 &= ~(IGPIO_PADCFG0_GPIROUTIOXAPIC | IGPIO_PADCFG0_GPIROUTSCI);
|
||||
newval0 &= ~(IGPIO_PADCFG0_GPIROUTSMI | IGPIO_PADCFG0_GPIROUTNMI);
|
||||
|
||||
if (flags & GPIO_PIN_INPUT) {
|
||||
newval0 &= ~IGPIO_PADCFG0_GPIORXDIS;
|
||||
newval0 |= IGPIO_PADCFG0_GPIOTXDIS;
|
||||
}
|
||||
|
||||
if (flags & GPIO_PIN_OUTPUT) {
|
||||
newval0 &= ~IGPIO_PADCFG0_GPIOTXDIS;
|
||||
newval0 |= IGPIO_PADCFG0_GPIORXDIS;
|
||||
}
|
||||
|
||||
if (flags & GPIO_PIN_INOUT) {
|
||||
newval0 &= ~IGPIO_PADCFG0_GPIOTXDIS;
|
||||
newval0 &= ~IGPIO_PADCFG0_GPIORXDIS;
|
||||
}
|
||||
|
||||
if (flags & GPIO_PIN_INVIN)
|
||||
newval0 |= IGPIO_PADCFG0_RXINV;
|
||||
else
|
||||
newval0 &= ~IGPIO_PADCFG0_RXINV;
|
||||
|
||||
newval1 &= ~IGPIO_PADCFG1_TERM_MASK;
|
||||
if (flags & GPIO_PIN_PULLUP) {
|
||||
newval1 |= IGPIO_PADCFG1_TERM_UP;
|
||||
newval1 |= IGPIO_PADCFG1_TERM_5K;
|
||||
}
|
||||
|
||||
if (flags & GPIO_PIN_PULLDOWN) {
|
||||
newval1 &= ~IGPIO_PADCFG1_TERM_UP;
|
||||
newval1 |= IGPIO_PADCFG1_TERM_5K;
|
||||
}
|
||||
|
||||
DPRINTF(("%s: bar %d pin %d flags #%x val0 #%x (%s) -> #%x (%s), "
|
||||
"val1 #%x -> #%x\n", __func__, ib->ib_barno, pin, flags,
|
||||
val0, igpio_padcfg0_print(val0, 0),
|
||||
newval0, igpio_padcfg0_print(newval0, 1),
|
||||
val1, newval1));
|
||||
|
||||
bus_space_write_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0, newval0);
|
||||
bus_space_write_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg1, newval1);
|
||||
|
||||
mutex_exit(&ib->ib_mtx);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void *
|
||||
igpio_intr_establish(void *priv, int pin, int ipl, int irqmode,
|
||||
int (*func)(void *), void *arg)
|
||||
{
|
||||
struct igpio_softc *sc = priv;
|
||||
struct igpio_bank *ib = igpio_find_bank(sc, pin);
|
||||
bus_addr_t cfg0;
|
||||
uint32_t val, newval;
|
||||
struct igpio_intr *ii;
|
||||
|
||||
pin = igpio_bank_pin(ib, pin);
|
||||
cfg0 = igpio_pincfg(ib, pin, IGPIO_PADCFG0);
|
||||
|
||||
ii = &ib->ib_intr[pin];
|
||||
ii->ii_func = func;
|
||||
ii->ii_arg = arg;
|
||||
ii->ii_pin = pin;
|
||||
ii->ii_bank = ib;
|
||||
|
||||
mutex_enter(&ib->ib_mtx);
|
||||
|
||||
val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0);
|
||||
newval = val;
|
||||
|
||||
newval &= ~IGPIO_PADCFG0_PMODE_MASK;
|
||||
newval |= IGPIO_PADCFG0_PMODE_GPIO;
|
||||
|
||||
newval &= ~IGPIO_PADCFG0_GPIORXDIS;
|
||||
newval |= IGPIO_PADCFG0_GPIOTXDIS;
|
||||
|
||||
newval |= (IGPIO_PADCFG0_GPIROUTIOXAPIC | IGPIO_PADCFG0_GPIROUTSCI);
|
||||
newval |= (IGPIO_PADCFG0_GPIROUTSMI | IGPIO_PADCFG0_GPIROUTNMI);
|
||||
|
||||
newval &= ~IGPIO_PADCFG0_RXINV;
|
||||
newval &= ~IGPIO_PADCFG0_RXEVCFG_EDGE;
|
||||
newval &= ~IGPIO_PADCFG0_RXEVCFG_LEVEL;
|
||||
newval &= ~IGPIO_PADCFG0_RXEVCFG_DISABLED;
|
||||
|
||||
switch (irqmode & GPIO_INTR_EDGE_MASK) {
|
||||
case GPIO_INTR_DOUBLE_EDGE:
|
||||
newval |= IGPIO_PADCFG0_RXEVCFG_EDGE_BOTH;
|
||||
break;
|
||||
case GPIO_INTR_NEG_EDGE:
|
||||
newval |= IGPIO_PADCFG0_RXEVCFG_EDGE;
|
||||
newval |= IGPIO_PADCFG0_RXINV;
|
||||
break;
|
||||
case GPIO_INTR_POS_EDGE:
|
||||
newval |= IGPIO_PADCFG0_RXEVCFG_EDGE;
|
||||
break;
|
||||
default:
|
||||
switch (irqmode & GPIO_INTR_LEVEL_MASK) {
|
||||
case GPIO_INTR_HIGH_LEVEL:
|
||||
newval |= IGPIO_PADCFG0_RXEVCFG_LEVEL;
|
||||
break;
|
||||
case GPIO_INTR_LOW_LEVEL:
|
||||
newval |= IGPIO_PADCFG0_RXEVCFG_LEVEL;
|
||||
newval |= IGPIO_PADCFG0_RXINV;
|
||||
break;
|
||||
default:
|
||||
newval |= IGPIO_PADCFG0_RXEVCFG_DISABLED;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
DPRINTF(("%s: bar %d pin %d val #%x (%s) -> #%x (%s)\n",
|
||||
__func__, ib->ib_barno, pin,
|
||||
val, igpio_padcfg0_print(val, 0),
|
||||
newval, igpio_padcfg0_print(newval, 1)));
|
||||
|
||||
bus_space_write_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0, newval);
|
||||
|
||||
mutex_exit(&ib->ib_mtx);
|
||||
|
||||
return ii;
|
||||
}
|
||||
|
||||
void
|
||||
igpio_intr_disestablish(void *priv, void *ih)
|
||||
{
|
||||
struct igpio_softc *sc = priv;
|
||||
struct igpio_bank *ib;
|
||||
struct igpio_intr *ii = ih;
|
||||
int pin;
|
||||
bus_addr_t cfg0;
|
||||
uint32_t val, newval;
|
||||
|
||||
if (ih == NULL)
|
||||
return;
|
||||
|
||||
pin = ii->ii_pin;
|
||||
ib = igpio_find_bank(sc, pin);
|
||||
pin = igpio_bank_pin(ib, pin);
|
||||
cfg0 = igpio_pincfg(ib, pin, IGPIO_PADCFG0);
|
||||
|
||||
mutex_enter(&ib->ib_mtx);
|
||||
|
||||
val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0);
|
||||
newval = val;
|
||||
|
||||
newval &= ~IGPIO_PADCFG0_PMODE_MASK;
|
||||
newval |= IGPIO_PADCFG0_PMODE_GPIO;
|
||||
|
||||
newval &= ~(IGPIO_PADCFG0_GPIROUTIOXAPIC | IGPIO_PADCFG0_GPIROUTSCI);
|
||||
newval &= ~(IGPIO_PADCFG0_GPIROUTSMI | IGPIO_PADCFG0_GPIROUTNMI);
|
||||
|
||||
DPRINTF(("%s: bar %d pin %d val #%x (%s) -> #%x (%s)\n", \
|
||||
__func__, ib->ib_barno, pin,
|
||||
val, igpio_padcfg0_print(val, 0),
|
||||
newval, igpio_padcfg0_print(newval, 1)));
|
||||
|
||||
bus_space_write_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0, newval);
|
||||
|
||||
mutex_exit(&ib->ib_mtx);
|
||||
|
||||
ii->ii_func = NULL;
|
||||
ii->ii_arg = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool
|
||||
igpio_intr_str(void *priv, int pin, int irqmode,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
struct igpio_softc *sc = priv;
|
||||
const char *name = sc->sc_dev->dv_xname;
|
||||
int rv;
|
||||
|
||||
rv = snprintf(buf, buflen, "%s pin %d", name, pin);
|
||||
|
||||
return (rv < buflen);
|
||||
}
|
||||
|
||||
int
|
||||
igpio_intr(void *priv)
|
||||
{
|
||||
struct igpio_softc *sc = priv;
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i < sc->sc_nbar; i++) {
|
||||
struct igpio_bank *ib = &sc->sc_banks[i];
|
||||
struct igpio_bank_setup *ibs = ib->ib_setup;
|
||||
bus_space_handle_t bsh = sc->sc_bsh[i];
|
||||
struct igpio_pin_group *ipg;
|
||||
|
||||
mutex_enter(&ib->ib_mtx);
|
||||
|
||||
for (ipg = igpio_pin_group; ipg->ipg_acpi_hid; ipg++) {
|
||||
int offset;
|
||||
bus_addr_t is_reg;
|
||||
bus_addr_t ie_reg;
|
||||
uint32_t raised;
|
||||
uint32_t pending;
|
||||
uint32_t enabled;
|
||||
int b;
|
||||
|
||||
if (strcmp(ipg->ipg_acpi_hid,
|
||||
ibs->ibs_acpi_hid) != 0)
|
||||
continue;
|
||||
|
||||
offset = ib->ib_padbar + ipg->ipg_groupno * 4;
|
||||
is_reg = offset + ibs->ibs_gpi_is;
|
||||
ie_reg = offset + ibs->ibs_gpi_ie;
|
||||
|
||||
raised = bus_space_read_4(sc->sc_bst, bsh, is_reg);
|
||||
enabled = bus_space_read_4(sc->sc_bst, bsh, ie_reg);
|
||||
|
||||
/*
|
||||
* find pins for which interupt is pending
|
||||
* and enabled
|
||||
*/
|
||||
pending = raised & enabled;
|
||||
|
||||
for (b = 0; b < 32; b++) {
|
||||
int pin;
|
||||
int (*func)(void *);
|
||||
void *arg;
|
||||
|
||||
if ((pending & (1 << b)) == 0)
|
||||
continue;
|
||||
|
||||
pin = ipg->ipg_first_pin + b;
|
||||
func = ib->ib_intr[pin].ii_func;
|
||||
arg = ib->ib_intr[pin].ii_arg;
|
||||
|
||||
/* XXX ack intr, handled or not? */
|
||||
raised &= ~(1 << b);
|
||||
|
||||
if (func == NULL)
|
||||
continue;
|
||||
|
||||
ret |= func(arg);
|
||||
}
|
||||
|
||||
bus_space_write_4(sc->sc_bst, bsh, is_reg, raised);
|
||||
|
||||
}
|
||||
|
||||
mutex_exit(&ib->ib_mtx);
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,493 @@
|
|||
/* $NetBSD: igpioreg.h,v 1.1 2022/03/24 02:24:25 manu Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2021 Emmanuel Dreyfus
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _IGPIOREG_H
|
||||
#define _IGPIOREG_H
|
||||
|
||||
#define IGPIO_REVID 0x0000
|
||||
#define IGPIO_CAPLIST 0x0004
|
||||
#define IGPIO_PADBAR 0x000c
|
||||
|
||||
#define IGPIO_PADCFG0 0x0000
|
||||
|
||||
#define IGPIO_PADCFG0_RXEVCFG_SHIFT 25
|
||||
#define IGPIO_PADCFG0_RXEVCFG_MASK __BITS(26, 25)
|
||||
#define IGPIO_PADCFG0_RXEVCFG_LEVEL 0
|
||||
#define IGPIO_PADCFG0_RXEVCFG_EDGE 1
|
||||
#define IGPIO_PADCFG0_RXEVCFG_DISABLED 2
|
||||
#define IGPIO_PADCFG0_RXEVCFG_EDGE_BOTH 3
|
||||
#define IGPIO_PADCFG0_PREGFRXSEL __BIT(24)
|
||||
#define IGPIO_PADCFG0_RXINV __BIT(23)
|
||||
#define IGPIO_PADCFG0_GPIROUTIOXAPIC __BIT(20)
|
||||
#define IGPIO_PADCFG0_GPIROUTSCI __BIT(19)
|
||||
#define IGPIO_PADCFG0_GPIROUTSMI __BIT(18)
|
||||
#define IGPIO_PADCFG0_GPIROUTNMI __BIT(17)
|
||||
#define IGPIO_PADCFG0_PMODE_SHIFT 10
|
||||
#define IGPIO_PADCFG0_PMODE_MASK __BITS(13, 10)
|
||||
#define IGPIO_PADCFG0_PMODE_GPIO 0
|
||||
#define IGPIO_PADCFG0_GPIORXDIS __BIT(9)
|
||||
#define IGPIO_PADCFG0_GPIOTXDIS __BIT(8)
|
||||
#define IGPIO_PADCFG0_GPIORXSTATE __BIT(1)
|
||||
#define IGPIO_PADCFG0_GPIOTXSTATE __BIT(0)
|
||||
|
||||
#define IGPIO_PADCFG1 0x0004
|
||||
#define IGPIO_PADCFG1_TERM_UP __BIT(13)
|
||||
#define IGPIO_PADCFG1_TERM_SHIFT 10
|
||||
#define IGPIO_PADCFG1_TERM_MASK __BITS(12, 10)
|
||||
#define IGPIO_PADCFG1_TERM_20K __BIT(2)
|
||||
#define IGPIO_PADCFG1_TERM_5K __BIT(1)
|
||||
#define IGPIO_PADCFG1_TERM_1K __BIT(0)
|
||||
#define IGPIO_PADCFG1_TERM_833 (__BIT(1) | BIT(0))
|
||||
|
||||
#define IGPIO_CAPLIST_ID_GPIO_HW_INFO 1
|
||||
#define IGPIO_CAPLIST_ID_PWM 2
|
||||
#define IGPIO_CAPLIST_ID_BLINK 3
|
||||
#define IGPIO_CAPLIST_ID_EXP 4
|
||||
|
||||
|
||||
#define IGPIO_PINCTRL_FEATURE_DEBOUNCE 0x001
|
||||
#define IGPIO_PINCTRL_FEATURE_1K_PD 0x002
|
||||
#define IGPIO_PINCTRL_FEATURE_GPIO_HW_INFO 0x004
|
||||
#define IGPIO_PINCTRL_FEATURE_PWM 0x010
|
||||
#define IGPIO_PINCTRL_FEATURE_BLINK 0x020
|
||||
#define IGPIO_PINCTRL_FEATURE_EXP 0x040
|
||||
|
||||
struct igpio_bank_setup {
|
||||
const char *ibs_acpi_hid;
|
||||
int ibs_barno;
|
||||
int ibs_first_pin;
|
||||
int ibs_last_pin;
|
||||
int ibs_gpi_is;
|
||||
int ibs_gpi_ie;
|
||||
};
|
||||
|
||||
struct igpio_pin_group {
|
||||
const char *ipg_acpi_hid;
|
||||
int ipg_groupno;
|
||||
int ipg_first_pin;
|
||||
const char *ipg_name;
|
||||
};
|
||||
|
||||
struct igpio_bank_setup igpio_bank_setup[] = {
|
||||
/* Sunrisepoint-LP */
|
||||
{ "INT344B", 0, 0, 47, 0x100, 0x120 },
|
||||
{ "INT344B", 1, 48, 119, 0x100, 0x120 },
|
||||
{ "INT344B", 2, 120, 151, 0x100, 0x120 },
|
||||
|
||||
/* Sunrisepoint-H */
|
||||
{ "INT3451", 0, 0, 47, 0x100, 0x120 },
|
||||
{ "INT3451", 1, 48, 180, 0x100, 0x120 },
|
||||
{ "INT3451", 2, 181, 191, 0x100, 0x120 },
|
||||
|
||||
/* Sunrisepoint-H */
|
||||
{ "INT345D", 0, 0, 47, 0x100, 0x120 },
|
||||
{ "INT345D", 1, 48, 180, 0x100, 0x120 },
|
||||
{ "INT345D", 2, 181, 191, 0x100, 0x120 },
|
||||
|
||||
/* Baytrail XXX GPI_IS and GPI_IE */
|
||||
{ "INT33B2", 0, 0, 101, 0x000, 0x000 },
|
||||
{ "INT33FC", 0, 0, 101, 0x000, 0x000 },
|
||||
|
||||
/* Lynxpoint XXX GPI_IS and GPI_IE */
|
||||
{ "INT33C7", 0, 0, 94, 0x000, 0x000 },
|
||||
{ "INT3437", 0, 0, 94, 0x000, 0x000 },
|
||||
|
||||
/* Cannonlake-H */
|
||||
{ "INT3450", 0, 0, 50, 0x100, 0x120 },
|
||||
{ "INT3450", 1, 51, 154, 0x100, 0x120 },
|
||||
{ "INT3450", 2, 155, 248, 0x100, 0x120 },
|
||||
{ "INT3450", 3, 249, 298, 0x100, 0x120 },
|
||||
|
||||
/* Cannonlake-LP */
|
||||
{ "INT34BB", 0, 0, 67, 0x100, 0x120 },
|
||||
{ "INT34BB", 1, 68, 180, 0x100, 0x120 },
|
||||
{ "INT34BB", 2, 181, 243, 0x100, 0x120 },
|
||||
|
||||
/* Alderlake */
|
||||
{ "INTC1056", 0, 0, 94, 0x200, 0x220 },
|
||||
{ "INTC1056", 1, 95, 150, 0x200, 0x220 },
|
||||
{ "INTC1056", 2, 151, 199, 0x200, 0x220 },
|
||||
{ "INTC1056", 3, 200, 269, 0x200, 0x220 },
|
||||
{ "INTC1056", 4, 270, 303, 0x200, 0x220 },
|
||||
|
||||
/* Icelake */
|
||||
{ "INT3455", 0, 0, 58, 0x100, 0x110 },
|
||||
{ "INT3455", 1, 59, 152, 0x100, 0x110 },
|
||||
{ "INT3455", 2, 153, 215, 0x100, 0x110 },
|
||||
{ "INT3455", 3, 216, 240, 0x100, 0x110 },
|
||||
|
||||
/* Lakefield */
|
||||
{ "INT34C4", 0, 0, 59, 0x100, 0x110 },
|
||||
{ "INT34C4", 1, 60, 148, 0x100, 0x110 },
|
||||
{ "INT34C4", 2, 149, 237, 0x100, 0x110 },
|
||||
{ "INT34C4", 3, 238, 266, 0x100, 0x110 },
|
||||
|
||||
/* Tigerlake-LP */
|
||||
{ "INT34C5", 0, 0, 66, 0x100, 0x120 },
|
||||
{ "INT34C5", 1, 67, 170, 0x100, 0x120 },
|
||||
{ "INT34C5", 2, 171, 259, 0x100, 0x120 },
|
||||
{ "INT34C5", 3, 260, 276, 0x100, 0x120 },
|
||||
|
||||
/* Tigerlake-LP */
|
||||
{ "INTC1055", 0, 0, 66, 0x100, 0x120 },
|
||||
{ "INTC1055", 1, 67, 170, 0x100, 0x120 },
|
||||
{ "INTC1055", 2, 171, 259, 0x100, 0x120 },
|
||||
{ "INTC1055", 3, 260, 276, 0x100, 0x120 },
|
||||
|
||||
/* Tigerlake-LP */
|
||||
{ "INTC1057", 0, 0, 66, 0x100, 0x120 },
|
||||
{ "INTC1057", 1, 67, 170, 0x100, 0x120 },
|
||||
{ "INTC1057", 2, 171, 259, 0x100, 0x120 },
|
||||
{ "INTC1057", 3, 260, 276, 0x100, 0x120 },
|
||||
|
||||
/* Tigerlake-H */
|
||||
{ "INT34C6", 0, 0, 78, 0x100, 0x120 },
|
||||
{ "INT34C6", 1, 79, 180, 0x100, 0x120 },
|
||||
{ "INT34C6", 2, 181, 217, 0x100, 0x120 },
|
||||
{ "INT34C6", 3, 218, 266, 0x100, 0x120 },
|
||||
{ "INT34C6", 4, 267, 290, 0x100, 0x120 },
|
||||
|
||||
/* Jasperlake */
|
||||
{ "INT34C8", 0, 0, 91, 0x100, 0x120 },
|
||||
{ "INT34C8", 1, 92, 194, 0x100, 0x120 },
|
||||
{ "INT34C8", 2, 195, 224, 0x100, 0x120 },
|
||||
{ "INT34C8", 3, 225, 232, 0x100, 0x120 },
|
||||
|
||||
/* Lewisburg */
|
||||
{ "INT3536", 0, 0, 7, 0x100, 0x110 },
|
||||
{ "INT3536", 1, 72, 13, 0x100, 0x110 },
|
||||
{ "INT3536", 3, 133, 14, 0x100, 0x110 },
|
||||
{ "INT3536", 4, 144, 17, 0x100, 0x110 },
|
||||
{ "INT3536", 5, 179, 246, 0x100, 0x110 },
|
||||
|
||||
/* Emmitsburg */
|
||||
{ "INTC1071", 0, 0, 65, 0x200, 0x210 },
|
||||
{ "INTC1071", 1, 66, 111, 0x200, 0x210 },
|
||||
{ "INTC1071", 2, 112, 145, 0x200, 0x210 },
|
||||
{ "INTC1071", 3, 146, 183, 0x200, 0x210 },
|
||||
{ "INTC1071", 4, 184, 261, 0x200, 0x210 },
|
||||
|
||||
/* Denverton */
|
||||
{ "INTC3000", 0, 0, 40, 0x100, 0x120 },
|
||||
{ "INTC3000", 1, 41, 153, 0x100, 0x120 },
|
||||
|
||||
/* Cedarfork */
|
||||
{ "INTC3001", 0, 0, 167, 0x200, 0x230 },
|
||||
{ "INTC3001", 1, 168, 236, 0x200, 0x230 },
|
||||
|
||||
/* Geminilake */
|
||||
{ "INT3453", 0, 0, 34, 0x100, 0x110 },
|
||||
|
||||
#ifdef notyet
|
||||
/*
|
||||
* BAR mappings not obvious, further studying required
|
||||
*/
|
||||
/* Broxton */
|
||||
{ "apollolake-pinctrl", 0, 0, 0, 0x100, 0x110 },
|
||||
{ "broxton-pinctrl", 0, 0, 0, 0x100, 0x110 },
|
||||
{ "INT34D1", 0, 0, 0, 0x100, 0x110 },
|
||||
{ "INT3452", 0, 0, 0, 0x100, 0x110 },
|
||||
|
||||
/* Cherryview */
|
||||
{ "INT33FF", 0, 0, 0, 0x000, 0x000 },
|
||||
#endif
|
||||
|
||||
{ NULL, 0, 0, 0, 0x000, 0x000 },
|
||||
};
|
||||
|
||||
struct igpio_pin_group igpio_pin_group[] = {
|
||||
/* Sunrisepoint-LP */
|
||||
{ "INT344B", 0, 151, "A" },
|
||||
|
||||
/* Sunrisepoint-H */
|
||||
{ "INT3451", 0, 0, "A" },
|
||||
{ "INT3451", 1, 24, "B" },
|
||||
{ "INT3451", 0, 48, "C" },
|
||||
{ "INT3451", 1, 72, "D" },
|
||||
{ "INT3451", 2, 96, "E" },
|
||||
{ "INT3451", 3, 109, "F" },
|
||||
{ "INT3451", 4, 133, "G" },
|
||||
{ "INT3451", 5, 157, "H" },
|
||||
{ "INT3451", 0, 181, "I" },
|
||||
|
||||
/* Sunrisepoint-H */
|
||||
{ "INT345D", 0, 0, "A" },
|
||||
{ "INT345D", 1, 24, "B" },
|
||||
{ "INT345D", 0, 48, "C" },
|
||||
{ "INT345D", 1, 72, "D" },
|
||||
{ "INT345D", 2, 96, "E" },
|
||||
{ "INT345D", 3, 109, "F" },
|
||||
{ "INT345D", 4, 133, "G" },
|
||||
{ "INT345D", 5, 157, "H" },
|
||||
{ "INT345D", 0, 181, "I" },
|
||||
|
||||
|
||||
/* Baytrail */
|
||||
{ "INT33B2", 0, 101, "A" },
|
||||
|
||||
/* Lynxpoint */
|
||||
{ "INT33C7", 0, 94, "A" },
|
||||
{ "INT3437", 0, 94, "A" },
|
||||
|
||||
/* Cannonlake-H */
|
||||
{ "INT3450", 0, 0, "GPP_A" },
|
||||
{ "INT3450", 1, 25, "GPP_B" },
|
||||
{ "INT3450", 0, 51, "GPP_C" },
|
||||
{ "INT3450", 1, 75, "GPP_D" },
|
||||
{ "INT3450", 2, 99, "GPP_G" },
|
||||
{ "INT3450", 3, 107, "AZA" },
|
||||
{ "INT3450", 4, 115, "vGPIO_0" },
|
||||
{ "INT3450", 5, 147, "vGPIO_1" },
|
||||
{ "INT3450", 0, 155, "GPP_K" },
|
||||
{ "INT3450", 1, 179, "GPP_H" },
|
||||
{ "INT3450", 2, 203, "GPP_E" },
|
||||
{ "INT3450", 3, 216, "GPP_F" },
|
||||
{ "INT3450", 4, 240, "SPI" },
|
||||
{ "INT3450", 0, 249, "CPU" },
|
||||
{ "INT3450", 1, 260, "JTAG" },
|
||||
{ "INT3450", 2, 269, "GPP_I" },
|
||||
{ "INT3450", 3, 287, "GPP_J" },
|
||||
|
||||
/* Cannonlake-LP */
|
||||
{ "INT34BB", 0, 0, "GPP_A" },
|
||||
{ "INT34BB", 1, 25, "GPP_B" },
|
||||
{ "INT34BB", 2, 51, "GPP_G" },
|
||||
{ "INT34BB", 3, 59, "SPI" },
|
||||
{ "INT34BB", 0, 68, "GPP_D" },
|
||||
{ "INT34BB", 1, 93, "GPP_F" },
|
||||
{ "INT34BB", 2, 117, "GPP_H" },
|
||||
{ "INT34BB", 3, 141, "vGPIO" },
|
||||
{ "INT34BB", 4, 173, "vGPIO" },
|
||||
{ "INT34BB", 0, 181, "GPP_C" },
|
||||
{ "INT34BB", 1, 205, "GPP_E" },
|
||||
{ "INT34BB", 2, 229, "JTAG" },
|
||||
{ "INT34BB", 3, 238, "HVCMOS" },
|
||||
|
||||
/* Alderlake */
|
||||
{ "INTC1056", 0, 0, "GPP_I" },
|
||||
{ "INTC1056", 1, 25, "GPP_R" },
|
||||
{ "INTC1056", 2, 48, "GPP_J" },
|
||||
{ "INTC1056", 3, 60, "vGPIO" },
|
||||
{ "INTC1056", 4, 87, "vGPIO_0" },
|
||||
{ "INTC1056", 0, 95, "GPP_B" },
|
||||
{ "INTC1056", 1, 119, "GPP_G" },
|
||||
{ "INTC1056", 2, 127, "GPP_H" },
|
||||
{ "INTC1056", 0, 151, "SPI0" },
|
||||
{ "INTC1056", 1, 160, "GPP_A" },
|
||||
{ "INTC1056", 2, 176, "GPP_C" },
|
||||
{ "INTC1056", 0, 200, "GPP_S" },
|
||||
{ "INTC1056", 1, 208, "GPP_E" },
|
||||
{ "INTC1056", 2, 231, "GPP_K" },
|
||||
{ "INTC1056", 3, 246, "GPP_F" },
|
||||
{ "INTC1056", 0, 270, "GPP_D" },
|
||||
{ "INTC1056", 1, 295, "JTAG" },
|
||||
|
||||
|
||||
/* Icelake */
|
||||
{ "INT3455", 0, 0, "GPP_G" },
|
||||
{ "INT3455", 1, 8, "GPP_B" },
|
||||
{ "INT3455", 2, 34, "GPP_A" },
|
||||
{ "INT3455", 0, 59, "GPP_H" },
|
||||
{ "INT3455", 1, 83, "GPP_D" },
|
||||
{ "INT3455", 2, 104, "GPP_F" },
|
||||
{ "INT3455", 3, 124, "vGPIO" },
|
||||
{ "INT3455", 0, 153, "GPP_C" },
|
||||
{ "INT3455", 1, 177, "HVCMOS" },
|
||||
{ "INT3455", 2, 183, "GPP_E" },
|
||||
{ "INT3455", 3, 207, "JTAG" },
|
||||
{ "INT3455", 2, 232, "SPI" },
|
||||
|
||||
|
||||
/* Lakefield */
|
||||
{ "INT34C4", 0, 0, "EAST_0" },
|
||||
{ "INT34C4", 1, 32, "EAST_1" },
|
||||
{ "INT34C4", 0, 60, "NORTHWEST_0" },
|
||||
{ "INT34C4", 1, 92, "NORTHWEST_1" },
|
||||
{ "INT34C4", 2, 124, "NORTHWEST_2" },
|
||||
{ "INT34C4", 0, 149, "WEST_0" },
|
||||
{ "INT34C4", 1, 181, "WEST_1" },
|
||||
{ "INT34C4", 2, 213, "WEST_2" },
|
||||
{ "INT34C4", 0, 238, "SOUTHEAST" },
|
||||
|
||||
|
||||
/* Tigerlake-LP */
|
||||
{ "INT34C5", 0, 0, "GPP_A" },
|
||||
{ "INT34C5", 1, 25, "GPP_R" },
|
||||
{ "INT34C5", 2, 45, "GPP_B" },
|
||||
{ "INT34C5", 3, 71, "vGPIO_0" },
|
||||
{ "INT34C5", 0, 79, "GPP_D" },
|
||||
{ "INT34C5", 1, 105, "GPP_C" },
|
||||
{ "INT34C5", 2, 129, "GPP_S" },
|
||||
{ "INT34C5", 3, 137, "GPP_G" },
|
||||
{ "INT34C5", 4, 154, "vGPIO" },
|
||||
{ "INT34C5", 0, 181, "GPP_E" },
|
||||
{ "INT34C5", 1, 194, "GPP_F" },
|
||||
{ "INT34C5", 0, 218, "GPP_H" },
|
||||
{ "INT34C5", 1, 242, "GPP_J" },
|
||||
{ "INT34C5", 2, 252, "GPP_K" },
|
||||
{ "INT34C5", 0, 267, "GPP_I" },
|
||||
{ "INT34C5", 1, 282, "JTAG" },
|
||||
|
||||
|
||||
/* Tigerlake-LP */
|
||||
{ "INTC1055", 0, 0, "GPP_A" },
|
||||
{ "INTC1055", 1, 25, "GPP_R" },
|
||||
{ "INTC1055", 2, 45, "GPP_B" },
|
||||
{ "INTC1055", 3, 71, "vGPIO_0" },
|
||||
{ "INTC1055", 0, 79, "GPP_D" },
|
||||
{ "INTC1055", 1, 105, "GPP_C" },
|
||||
{ "INTC1055", 2, 129, "GPP_S" },
|
||||
{ "INTC1055", 3, 137, "GPP_G" },
|
||||
{ "INTC1055", 4, 154, "vGPIO" },
|
||||
{ "INTC1055", 0, 181, "GPP_E" },
|
||||
{ "INTC1055", 1, 194, "GPP_F" },
|
||||
{ "INTC1055", 0, 218, "GPP_H" },
|
||||
{ "INTC1055", 1, 242, "GPP_J" },
|
||||
{ "INTC1055", 2, 252, "GPP_K" },
|
||||
{ "INTC1055", 0, 267, "GPP_I" },
|
||||
{ "INTC1055", 1, 282, "JTAG" },
|
||||
|
||||
|
||||
/* Tigerlake-LP */
|
||||
{ "INTC1057", 0, 0, "GPP_A" },
|
||||
{ "INTC1057", 1, 25, "GPP_R" },
|
||||
{ "INTC1057", 2, 45, "GPP_B" },
|
||||
{ "INTC1057", 3, 71, "vGPIO_0" },
|
||||
{ "INTC1057", 0, 79, "GPP_D" },
|
||||
{ "INTC1057", 1, 105, "GPP_C" },
|
||||
{ "INTC1057", 2, 129, "GPP_S" },
|
||||
{ "INTC1057", 3, 137, "GPP_G" },
|
||||
{ "INTC1057", 4, 154, "vGPIO" },
|
||||
{ "INTC1057", 0, 181, "GPP_E" },
|
||||
{ "INTC1057", 1, 194, "GPP_F" },
|
||||
{ "INTC1057", 0, 218, "GPP_H" },
|
||||
{ "INTC1057", 1, 242, "GPP_J" },
|
||||
{ "INTC1057", 2, 252, "GPP_K" },
|
||||
{ "INTC1057", 0, 267, "GPP_I" },
|
||||
{ "INTC1057", 1, 282, "JTAG" },
|
||||
|
||||
/* Tigerlake-H */
|
||||
{ "INT34C6", 0, 0, "GPP_B" },
|
||||
{ "INT34C6", 1, 26, "GPP_T" },
|
||||
{ "INT34C6", 2, 42, "GPP_A" },
|
||||
{ "INT34C6", 0, 67, "GPP_S" },
|
||||
{ "INT34C6", 1, 75, "GPP_H" },
|
||||
{ "INT34C6", 2, 99, "GPP_D" },
|
||||
{ "INT34C6", 3, 120, "GPP_U" },
|
||||
{ "INT34C6", 4, 144, "vGPIO" },
|
||||
{ "INT34C6", 0, 171, "GPP_C" },
|
||||
{ "INT34C6", 1, 195, "GPP_F" },
|
||||
{ "INT34C6", 2, 220, "HVCMOS" },
|
||||
{ "INT34C6", 3, 226, "GPP_E" },
|
||||
{ "INT34C6", 4, 251, "JTAG" },
|
||||
{ "INT34C6", 0, 260, "GPP_R" },
|
||||
{ "INT34C6", 1, 268, "SPI" },
|
||||
|
||||
/* Jasperlake */
|
||||
{ "INT34C8", 0, 0, "GPP_F" },
|
||||
{ "INT34C8", 1, 20, "SPI" },
|
||||
{ "INT34C8", 2, 29, "GPP_B" },
|
||||
{ "INT34C8", 3, 55, "GPP_A" },
|
||||
{ "INT34C8", 4, 76, "GPP_S" },
|
||||
{ "INT34C8", 5, 84, "GPP_R" },
|
||||
{ "INT34C8", 0, 92, "GPP_H" },
|
||||
{ "INT34C8", 1, 116, "GPP_D" },
|
||||
{ "INT34C8", 2, 142, "vGPIO" },
|
||||
{ "INT34C8", 3, 171, "GPP_C" },
|
||||
{ "INT34C8", 0, 195, "HVCMOS" },
|
||||
{ "INT34C8", 1, 201, "GPP_E" },
|
||||
{ "INT34C8", 0, 225, "GPP_G" },
|
||||
|
||||
|
||||
/* Lewisburg */
|
||||
{ "INT3536", 0, 7, "" },
|
||||
|
||||
/* Emmitsburg */
|
||||
{ "INTC1071", 0, 0, "GPP_A" },
|
||||
{ "INTC1071", 1, 21, "GPP_B" },
|
||||
{ "INTC1071", 2, 45, "SPI" },
|
||||
{ "INTC1071", 0, 66, "GPP_C" },
|
||||
{ "INTC1071", 1, 88, "GPP_D" },
|
||||
{ "INTC1071", 0, 112, "GPP_E" },
|
||||
{ "INTC1071", 1, 136, "JTAG" },
|
||||
{ "INTC1071", 0, 146, "GPP_H" },
|
||||
{ "INTC1071", 1, 166, "GPP_J" },
|
||||
{ "INTC1071", 0, 184, "GPP_I" },
|
||||
{ "INTC1071", 1, 208, "GPP_L" },
|
||||
{ "INTC1071", 2, 226, "GPP_M" },
|
||||
{ "INTC1071", 3, 244, "GPP_N" },
|
||||
|
||||
/* Denverton */
|
||||
{ "INTC3000", 0, 0, "North" },
|
||||
{ "INTC3000", 1, 32, "North" },
|
||||
{ "INTC3000", 0, 41, "South" },
|
||||
{ "INTC3000", 1, 59, "South" },
|
||||
{ "INTC3000", 2, 91, "South" },
|
||||
{ "INTC3000", 3, 112, "South" },
|
||||
{ "INTC3000", 4, 144, "South" },
|
||||
|
||||
|
||||
/* Cedarfork */
|
||||
{ "INTC3001", 0, 0, "WEST2" },
|
||||
{ "INTC3001", 1, 24, "WEST3" },
|
||||
{ "INTC3001", 2, 48, "WEST01" },
|
||||
{ "INTC3001", 3, 71, "WEST5" },
|
||||
{ "INTC3001", 4, 91, "WESTC" },
|
||||
{ "INTC3001", 5, 97, "WESTC_DFX" },
|
||||
{ "INTC3001", 6, 102, "WESTA" },
|
||||
{ "INTC3001", 7, 112, "WESTB" },
|
||||
{ "INTC3001", 8, 124, "WESTD" },
|
||||
{ "INTC3001", 9, 144, "WESTD_PECI" },
|
||||
{ "INTC3001", 10, 145, "WESTF" },
|
||||
{ "INTC3001", 0, 168, "EAST2" },
|
||||
{ "INTC3001", 1, 192, "EAST3" },
|
||||
{ "INTC3001", 2, 203, "EAST0" },
|
||||
{ "INTC3001", 3, 226, "EMMC" },
|
||||
|
||||
/* Geminilake */
|
||||
{ "INT3453", 0, 34, "" },
|
||||
|
||||
#ifdef notyet
|
||||
/*
|
||||
* BAR mappings not obvious, further studying required
|
||||
*/
|
||||
/* Broxton */
|
||||
{ "apollolake-pinctrl", 0, 0, "" },
|
||||
{ "broxton-pinctrl", 0, 0, "" },
|
||||
{ "INT34D1", 0, 0, "" },
|
||||
{ "INT3452", 0, 0, "" },
|
||||
|
||||
/* Cherryview */
|
||||
{ "INT33FF", 0, 0, "" },
|
||||
#endif
|
||||
|
||||
{ NULL, 0, 0, 0 },
|
||||
};
|
||||
|
||||
#endif /* _IGPIOREG_H */
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/* $NetBSD: igpiovar.h,v 1.1 2022/03/24 02:24:25 manu Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2021 Emmanuel Dreyfus
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _IGPIOVAR_H
|
||||
#define _IGPIOVAR_H
|
||||
|
||||
struct igpio_softc {
|
||||
device_t sc_dev;
|
||||
const char *sc_acpi_hid;
|
||||
bus_space_tag_t sc_bst;
|
||||
int sc_nbar;
|
||||
bus_addr_t *sc_base;
|
||||
bus_size_t *sc_length;
|
||||
bus_space_handle_t *sc_bsh;
|
||||
|
||||
gpio_pin_t *sc_pins;
|
||||
int sc_npins;
|
||||
struct gpio_chipset_tag sc_gc;
|
||||
|
||||
uint32_t sc_reserved_mask;
|
||||
|
||||
struct igpio_bank *sc_banks;
|
||||
};
|
||||
|
||||
void igpio_attach(struct igpio_softc *);
|
||||
void igpio_detach(struct igpio_softc *);
|
||||
|
||||
int igpio_pin_read(void *, int);
|
||||
void igpio_pin_write(void *, int, int);
|
||||
void igpio_pin_ctl(void *, int, int);
|
||||
void *igpio_intr_establish(void *, int, int, int, int (*)(void *), void *);
|
||||
void igpio_intr_disestablish(void *, void *);
|
||||
bool igpio_intr_str(void *, int, int, char *, size_t);
|
||||
int igpio_intr(void *);
|
||||
|
||||
|
||||
|
||||
#endif /* !_IGPIOVAR_H */
|
Loading…
Reference in New Issue