Changeset View
Changeset View
Standalone View
Standalone View
sys/arm/arm/pmu.c
Show First 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | |||||
#include <dev/ofw/openfirm.h> | #include <dev/ofw/openfirm.h> | ||||
#include <dev/ofw/ofw_bus.h> | #include <dev/ofw/ofw_bus.h> | ||||
#include <dev/ofw/ofw_bus_subr.h> | #include <dev/ofw/ofw_bus_subr.h> | ||||
#include <machine/bus.h> | #include <machine/bus.h> | ||||
#include <machine/cpu.h> | #include <machine/cpu.h> | ||||
#include <machine/intr.h> | #include <machine/intr.h> | ||||
#define MAX_RLEN 8 | |||||
struct pmu_softc { | struct pmu_softc { | ||||
struct resource *res[1]; | struct resource *res[MAX_RLEN]; | ||||
device_t dev; | device_t dev; | ||||
void *ih; | void *ih[MAX_RLEN]; | ||||
struct resource_list irq_resources; | |||||
}; | }; | ||||
static struct ofw_compat_data compat_data[] = { | static struct ofw_compat_data compat_data[] = { | ||||
{"arm,armv8-pmuv3", 1}, | |||||
{"arm,cortex-a17-pmu", 1}, | {"arm,cortex-a17-pmu", 1}, | ||||
{"arm,cortex-a15-pmu", 1}, | {"arm,cortex-a15-pmu", 1}, | ||||
{"arm,cortex-a12-pmu", 1}, | {"arm,cortex-a12-pmu", 1}, | ||||
{"arm,cortex-a9-pmu", 1}, | {"arm,cortex-a9-pmu", 1}, | ||||
{"arm,cortex-a8-pmu", 1}, | {"arm,cortex-a8-pmu", 1}, | ||||
{"arm,cortex-a7-pmu", 1}, | {"arm,cortex-a7-pmu", 1}, | ||||
{"arm,cortex-a5-pmu", 1}, | {"arm,cortex-a5-pmu", 1}, | ||||
{"arm,arm11mpcore-pmu", 1}, | {"arm,arm11mpcore-pmu", 1}, | ||||
{"arm,arm1176-pmu", 1}, | {"arm,arm1176-pmu", 1}, | ||||
{"arm,arm1136-pmu", 1}, | {"arm,arm1136-pmu", 1}, | ||||
{"qcom,krait-pmu", 1}, | {"qcom,krait-pmu", 1}, | ||||
{NULL, 0} | {NULL, 0} | ||||
}; | }; | ||||
static struct resource_spec pmu_spec[] = { | |||||
{ SYS_RES_IRQ, 0, RF_ACTIVE }, | |||||
{ -1, 0 } | |||||
}; | |||||
static int | static int | ||||
pmu_intr(void *arg) | pmu_intr(void *arg) | ||||
{ | { | ||||
struct trapframe *tf; | struct trapframe *tf; | ||||
tf = arg; | tf = arg; | ||||
#ifdef HWPMC_HOOKS | #ifdef HWPMC_HOOKS | ||||
Show All 18 Lines | pmu_probe(device_t dev) | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
static int | static int | ||||
pmu_attach(device_t dev) | pmu_attach(device_t dev) | ||||
{ | { | ||||
struct pmu_softc *sc; | struct pmu_softc *sc; | ||||
phandle_t node; | |||||
uint32_t rlen; | |||||
int err; | int err; | ||||
int i; | |||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
sc->dev = dev; | sc->dev = dev; | ||||
if (bus_alloc_resources(dev, pmu_spec, sc->res)) { | node = ofw_bus_get_node(sc->dev); | ||||
device_printf(dev, "could not allocate resources\n"); | resource_list_init(&sc->irq_resources); | ||||
err = ofw_bus_intr_to_rl(dev, node, &sc->irq_resources, &rlen); | |||||
andrew: It should be the parent that sets the interrupt resources, not the device. This will also be… | |||||
brAuthorUnsubmitted Done Inline Actionssounds reasonable, so I rewrote this br: sounds reasonable, so I rewrote this | |||||
if (err) { | |||||
device_printf(dev, "Unable to find interrupt resources.\n"); | |||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
if (rlen > MAX_RLEN) | |||||
device_printf(sc->dev, "Warning: too many interrupt lines\n"); | |||||
for (i = 0; i < min(rlen, MAX_RLEN); i++) { | |||||
/* Request the IRQ resources */ | |||||
sc->res[i] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i, RF_ACTIVE); | |||||
if (sc->res[i] == NULL) { | |||||
device_printf(dev, "Error: could not allocate irq resources\n"); | |||||
return (ENXIO); | |||||
} | |||||
/* Setup interrupt handler */ | /* Setup interrupt handler */ | ||||
err = bus_setup_intr(dev, sc->res[0], INTR_MPSAFE | INTR_TYPE_MISC, | err = bus_setup_intr(dev, sc->res[i], INTR_MPSAFE | INTR_TYPE_MISC, | ||||
pmu_intr, NULL, NULL, &sc->ih); | pmu_intr, NULL, NULL, &sc->ih[i]); | ||||
if (err) { | if (err) { | ||||
device_printf(dev, "Unable to setup interrupt handler.\n"); | device_printf(dev, "Unable to setup interrupt handler.\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | |||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static device_method_t pmu_methods[] = { | static device_method_t pmu_methods[] = { | ||||
DEVMETHOD(device_probe, pmu_probe), | DEVMETHOD(device_probe, pmu_probe), | ||||
DEVMETHOD(device_attach, pmu_attach), | DEVMETHOD(device_attach, pmu_attach), | ||||
Show All 12 Lines |
It should be the parent that sets the interrupt resources, not the device. This will also be problematic with ACPI.