Add support for multiple PMUs

This commit is contained in:
jmcneill 2019-06-29 12:53:05 +00:00
parent e4c2eafeb5
commit 8a273b316a

View File

@ -1,4 +1,4 @@
/* $NetBSD: pmu_fdt.c,v 1.5 2019/01/21 08:04:26 skrll Exp $ */
/* $NetBSD: pmu_fdt.c,v 1.6 2019/06/29 12:53:05 jmcneill Exp $ */
/*-
* Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca>
@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: pmu_fdt.c,v 1.5 2019/01/21 08:04:26 skrll Exp $");
__KERNEL_RCSID(0, "$NetBSD: pmu_fdt.c,v 1.6 2019/06/29 12:53:05 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@ -37,6 +37,7 @@ __KERNEL_RCSID(0, "$NetBSD: pmu_fdt.c,v 1.5 2019/01/21 08:04:26 skrll Exp $");
#include <sys/cpu.h>
#include <sys/interrupt.h>
#include <sys/kmem.h>
#include <sys/xcall.h>
#include <dev/fdt/fdtvar.h>
@ -52,6 +53,9 @@ __KERNEL_RCSID(0, "$NetBSD: pmu_fdt.c,v 1.5 2019/01/21 08:04:26 skrll Exp $");
#include <arm/armreg.h>
static bool pmu_fdt_uses_ppi;
static int pmu_fdt_count;
static int pmu_fdt_match(device_t, cfdata_t, void *);
static void pmu_fdt_attach(device_t, device_t, void *);
@ -108,6 +112,12 @@ pmu_fdt_attach(device_t parent, device_t self, void *aux)
config_interrupts(self, pmu_fdt_init);
}
static void
pmu_fdt_init_cpu(void *arg1, void *arg2)
{
arm_pmu_init();
}
static void
pmu_fdt_init(device_t self)
{
@ -115,14 +125,25 @@ pmu_fdt_init(device_t self)
const int phandle = sc->sc_phandle;
char intrstr[128];
int error, n;
uint64_t xc;
void **ih;
error = arm_pmu_init();
if (error != 0) {
aprint_error_dev(self, "failed to initialize PMU\n");
if (pmu_fdt_uses_ppi && pmu_fdt_count > 0) {
/*
* Second instance of a PMU where PPIs are used. Since the PMU
* is already initialized and the PPI interrupt handler has
* already been installed, there is nothing left to do here.
*/
if (fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr)))
aprint_normal_dev(self, "interrupting on %s\n", intrstr);
return;
}
if (pmu_fdt_count == 0) {
xc = xc_broadcast(0, pmu_fdt_init_cpu, NULL, NULL);
xc_wait(xc);
}
ih = kmem_zalloc(sizeof(void *) * ncpu, KM_SLEEP);
for (n = 0; n < ncpu; n++) {
@ -158,6 +179,9 @@ pmu_fdt_init(device_t self)
}
}
pmu_fdt_count++;
pmu_fdt_uses_ppi = nirq == 1 && ncpu > 1;
cleanup:
kmem_free(ih, sizeof(void *) * ncpu);
}