Add the start of INTRNG support for ACPI.
This adds a new acpi_bus interface with a map_intr method. This is similar to the Open Firmware map_intr method and allows us to create the needed mapping from ACPI space to INTRNG space. Obtained from: ABT Systems Ltd Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D8617
This commit is contained in:
parent
c751f90c0c
commit
224c3776f6
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=327835
@ -72,6 +72,7 @@ __FBSDID("$FreeBSD$");
|
||||
#ifdef DEV_ACPI
|
||||
#include <contrib/dev/acpica/include/acpi.h>
|
||||
#include <dev/acpica/acpivar.h>
|
||||
#include "acpi_bus_if.h"
|
||||
#endif
|
||||
|
||||
#define GT_CTRL_ENABLE (1 << 0)
|
||||
@ -312,6 +313,15 @@ arm_tmr_fdt_probe(device_t dev)
|
||||
#endif
|
||||
|
||||
#ifdef DEV_ACPI
|
||||
static void
|
||||
arm_tmr_acpi_add_irq(device_t parent, device_t dev, int rid, u_int irq)
|
||||
{
|
||||
|
||||
irq = ACPI_BUS_MAP_INTR(parent, dev, irq,
|
||||
INTR_TRIGGER_LEVEL, INTR_POLARITY_HIGH);
|
||||
BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, rid, irq, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
arm_tmr_acpi_identify(driver_t *driver, device_t parent)
|
||||
{
|
||||
@ -336,12 +346,9 @@ arm_tmr_acpi_identify(driver_t *driver, device_t parent)
|
||||
goto out;
|
||||
}
|
||||
|
||||
BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 0,
|
||||
gtdt->SecureEl1Interrupt, 1);
|
||||
BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 1,
|
||||
gtdt->NonSecureEl1Interrupt, 1);
|
||||
BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 2,
|
||||
gtdt->VirtualTimerInterrupt, 1);
|
||||
arm_tmr_acpi_add_irq(parent, dev, 0, gtdt->SecureEl1Interrupt);
|
||||
arm_tmr_acpi_add_irq(parent, dev, 1, gtdt->NonSecureEl1Interrupt);
|
||||
arm_tmr_acpi_add_irq(parent, dev, 2, gtdt->VirtualTimerInterrupt);
|
||||
|
||||
out:
|
||||
acpi_unmap_table(gtdt);
|
||||
|
@ -72,6 +72,7 @@ __FBSDID("$FreeBSD$");
|
||||
#ifdef DEV_ACPI
|
||||
#include <contrib/dev/acpica/include/acpi.h>
|
||||
#include <dev/acpica/acpivar.h>
|
||||
#include "acpi_bus_if.h"
|
||||
#endif
|
||||
|
||||
extern struct bus_space memmap_bus;
|
||||
@ -460,11 +461,16 @@ nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells,
|
||||
#endif
|
||||
|
||||
#ifdef DEV_ACPI
|
||||
static int nexus_acpi_map_intr(device_t dev, device_t child, u_int irq, int trig, int pol);
|
||||
|
||||
static device_method_t nexus_acpi_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, nexus_acpi_probe),
|
||||
DEVMETHOD(device_attach, nexus_acpi_attach),
|
||||
|
||||
/* ACPI interface */
|
||||
DEVMETHOD(acpi_bus_map_intr, nexus_acpi_map_intr),
|
||||
|
||||
DEVMETHOD_END,
|
||||
};
|
||||
|
||||
@ -495,4 +501,30 @@ nexus_acpi_attach(device_t dev)
|
||||
nexus_add_child(dev, 10, "acpi", 0);
|
||||
return (nexus_attach(dev));
|
||||
}
|
||||
|
||||
static int
|
||||
nexus_acpi_map_intr(device_t dev, device_t child, u_int irq, int trig, int pol)
|
||||
{
|
||||
struct intr_map_data_acpi *acpi_data;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*acpi_data);
|
||||
acpi_data = (struct intr_map_data_acpi *)intr_alloc_map_data(
|
||||
INTR_MAP_DATA_ACPI, len, M_WAITOK | M_ZERO);
|
||||
acpi_data->irq = irq;
|
||||
acpi_data->pol = pol;
|
||||
acpi_data->trig = trig;
|
||||
|
||||
/*
|
||||
* TODO: This will only handle a single interrupt controller.
|
||||
* ACPI will map multiple controllers into a single virtual IRQ
|
||||
* space. Each controller has a System Vector Base to hold the
|
||||
* first irq it handles in this space. As such the correct way
|
||||
* to handle interrupts with ACPI is to search through the
|
||||
* controllers for the largest base value that is no larger than
|
||||
* the IRQ value.
|
||||
*/
|
||||
irq = intr_map_irq(NULL, 0, (struct intr_map_data *)acpi_data);
|
||||
return (irq);
|
||||
}
|
||||
#endif
|
||||
|
@ -167,6 +167,7 @@ armv8_crypto_wrap.o optional armv8crypto \
|
||||
clean "armv8_crypto_wrap.o"
|
||||
crypto/blowfish/bf_enc.c optional crypto | ipsec | ipsec_support
|
||||
crypto/des/des_enc.c optional crypto | ipsec | ipsec_support | netsmb
|
||||
dev/acpica/acpi_bus_if.m optional acpi
|
||||
dev/acpica/acpi_if.m optional acpi
|
||||
dev/ahci/ahci_generic.c optional ahci
|
||||
dev/axgbe/if_axgbe.c optional axgbe
|
||||
|
@ -1358,7 +1358,9 @@ static struct resource *
|
||||
acpi_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
|
||||
{
|
||||
#ifndef INTRNG
|
||||
ACPI_RESOURCE ares;
|
||||
#endif
|
||||
struct acpi_device *ad;
|
||||
struct resource_list_entry *rle;
|
||||
struct resource_list *rl;
|
||||
@ -1385,6 +1387,7 @@ acpi_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
resource_list_add(rl, type, *rid, start, end, count);
|
||||
res = resource_list_alloc(rl, bus, child, type, rid, start, end, count,
|
||||
flags);
|
||||
#ifndef INTRNG
|
||||
if (res != NULL && type == SYS_RES_IRQ) {
|
||||
/*
|
||||
* Since bus_config_intr() takes immediate effect, we cannot
|
||||
@ -1397,6 +1400,7 @@ acpi_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
if (ACPI_SUCCESS(acpi_lookup_irq_resource(child, *rid, res, &ares)))
|
||||
acpi_config_intr(child, &ares);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If this is an allocation of the "default" range for a given
|
||||
|
67
sys/dev/acpica/acpi_bus_if.m
Normal file
67
sys/dev/acpica/acpi_bus_if.m
Normal file
@ -0,0 +1,67 @@
|
||||
#-
|
||||
# Copyright (c) 2016 The FreeBSD Foundation
|
||||
# All rights reserved.
|
||||
#
|
||||
# This software was developed by Andrew Turner under
|
||||
# sponsorship from the FreeBSD Foundation.
|
||||
#
|
||||
# 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 AUTHOR 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 AUTHOR 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.
|
||||
#
|
||||
# $FreeBSD$
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
INTERFACE acpi_bus;
|
||||
|
||||
CODE {
|
||||
static acpi_bus_map_intr_t acpi_bus_default_map_intr;
|
||||
|
||||
int
|
||||
acpi_bus_default_map_intr(device_t bus, device_t dev, u_int irq,
|
||||
int trig, int pol)
|
||||
{
|
||||
device_t parent;
|
||||
|
||||
/* Pass up the hierarchy */
|
||||
parent = device_get_parent(bus);
|
||||
if (parent != NULL)
|
||||
return (ACPI_BUS_MAP_INTR(parent, dev, irq, trig, pol));
|
||||
|
||||
panic("Unable to map interrupt %u", irq);
|
||||
}
|
||||
};
|
||||
|
||||
# Map an interrupt from ACPI space to the FreeBSD IRQ space. Note that
|
||||
# both of these may be different than the pysical interrupt space as this
|
||||
# may be local to each interrupt controller.
|
||||
#
|
||||
# This method also associates interrupt metadata with the interrupt,
|
||||
# removing the need for a post hoc configure step.
|
||||
METHOD int map_intr {
|
||||
device_t bus;
|
||||
device_t dev;
|
||||
u_int irq;
|
||||
int trig;
|
||||
int pol;
|
||||
} DEFAULT acpi_bus_default_map_intr;
|
@ -45,6 +45,10 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <dev/acpica/acpivar.h>
|
||||
|
||||
#ifdef INTRNG
|
||||
#include "acpi_bus_if.h"
|
||||
#endif
|
||||
|
||||
/* Hooks for the ACPI CA debugging infrastructure */
|
||||
#define _COMPONENT ACPI_BUS
|
||||
ACPI_MODULE_NAME("RESOURCE")
|
||||
@ -556,6 +560,7 @@ acpi_res_set_irq(device_t dev, void *context, uint8_t *irq, int count,
|
||||
int trig, int pol)
|
||||
{
|
||||
struct acpi_res_context *cp = (struct acpi_res_context *)context;
|
||||
rman_res_t intr;
|
||||
|
||||
if (cp == NULL || irq == NULL)
|
||||
return;
|
||||
@ -564,7 +569,14 @@ acpi_res_set_irq(device_t dev, void *context, uint8_t *irq, int count,
|
||||
if (count != 1)
|
||||
return;
|
||||
|
||||
bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
|
||||
#ifdef INTRNG
|
||||
intr = ACPI_BUS_MAP_INTR(device_get_parent(dev), dev, *irq,
|
||||
(trig == ACPI_EDGE_SENSITIVE) ? INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL,
|
||||
(pol == ACPI_ACTIVE_HIGH) ? INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
|
||||
#else
|
||||
intr = *irq;
|
||||
#endif
|
||||
bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, intr, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -572,6 +584,7 @@ acpi_res_set_ext_irq(device_t dev, void *context, uint32_t *irq, int count,
|
||||
int trig, int pol)
|
||||
{
|
||||
struct acpi_res_context *cp = (struct acpi_res_context *)context;
|
||||
rman_res_t intr;
|
||||
|
||||
if (cp == NULL || irq == NULL)
|
||||
return;
|
||||
@ -580,7 +593,14 @@ acpi_res_set_ext_irq(device_t dev, void *context, uint32_t *irq, int count,
|
||||
if (count != 1)
|
||||
return;
|
||||
|
||||
bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
|
||||
#ifdef INTRNG
|
||||
intr = ACPI_BUS_MAP_INTR(device_get_parent(dev), dev, *irq,
|
||||
(trig == ACPI_EDGE_SENSITIVE) ? INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL,
|
||||
(pol == ACPI_ACTIVE_HIGH) ? INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
|
||||
#else
|
||||
intr = *irq;
|
||||
#endif
|
||||
bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, intr, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -36,6 +36,9 @@
|
||||
#include "acpi_if.h"
|
||||
#include "bus_if.h"
|
||||
#include <sys/eventhandler.h>
|
||||
#ifdef INTRNG
|
||||
#include <sys/intr.h>
|
||||
#endif
|
||||
#include <sys/ktr.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
@ -91,6 +94,16 @@ struct acpi_device {
|
||||
struct resource_list ad_rl;
|
||||
};
|
||||
|
||||
#ifdef INTRNG
|
||||
struct intr_map_data_acpi {
|
||||
struct intr_map_data hdr;
|
||||
u_int irq;
|
||||
u_int pol;
|
||||
u_int trig;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* Track device (/dev/{apm,apmctl} and /dev/acpi) notification status. */
|
||||
struct apm_clone_data {
|
||||
STAILQ_ENTRY(apm_clone_data) entries;
|
||||
|
Loading…
Reference in New Issue
Block a user