diff --git a/sys/arm/arm/generic_timer.c b/sys/arm/arm/generic_timer.c --- a/sys/arm/arm/generic_timer.c +++ b/sys/arm/arm/generic_timer.c @@ -79,8 +79,9 @@ #define GT_PHYS_SECURE 0 #define GT_PHYS_NONSECURE 1 #define GT_VIRT 2 -#define GT_HYP 3 -#define GT_IRQ_COUNT 4 +#define GT_HYP_PHYS 3 +#define GT_HYP_VIRT 4 +#define GT_IRQ_COUNT 5 #define GT_CTRL_ENABLE (1 << 0) #define GT_CTRL_INT_MASK (1 << 1) @@ -107,12 +108,36 @@ static struct arm_tmr_softc *arm_tmr_sc = NULL; -static struct resource_spec timer_spec[] = { - { SYS_RES_IRQ, GT_PHYS_SECURE, RF_ACTIVE }, - { SYS_RES_IRQ, GT_PHYS_NONSECURE, RF_ACTIVE }, - { SYS_RES_IRQ, GT_VIRT, RF_ACTIVE | RF_OPTIONAL }, - { SYS_RES_IRQ, GT_HYP, RF_ACTIVE | RF_OPTIONAL }, - { -1, 0 } +static const struct arm_tmr_irq_defs { + int idx; + const char *name; + int flags; +} arm_tmr_irq_defs[] = { + { + .idx = GT_PHYS_SECURE, + .name = "sec-phys", + .flags = RF_ACTIVE | RF_OPTIONAL, + }, + { + .idx = GT_PHYS_NONSECURE, + .name = "phys", + .flags = RF_ACTIVE, + }, + { + .idx = GT_VIRT, + .name = "virt", + .flags = RF_ACTIVE, + }, + { + .idx = GT_HYP_PHYS, + .name = "hyp-phys", + .flags = RF_ACTIVE | RF_OPTIONAL, + }, + { + .idx = GT_HYP_VIRT, + .name = "hyp-virt", + .flags = RF_ACTIVE | RF_OPTIONAL, + }, }; static uint32_t arm_tmr_fill_vdso_timehands(struct vdso_timehands *vdso_th, @@ -442,12 +467,16 @@ arm_tmr_attach(device_t dev) { struct arm_tmr_softc *sc; + const struct arm_tmr_irq_defs *irq_def; #ifdef FDT phandle_t node; pcell_t clock; #endif int error; - int i, first_timer, last_timer; + int i, first_timer, last_timer, rid; +#ifdef FDT + bool has_names; +#endif sc = device_get_softc(dev); if (arm_tmr_sc) @@ -482,9 +511,64 @@ return (ENXIO); } - if (bus_alloc_resources(dev, timer_spec, sc->res)) { - device_printf(dev, "could not allocate resources\n"); - return (ENXIO); + /* + * Allocate for any interrupts we can find, we'll make decisions about + * which to use/disable after. + */ +#ifdef FDT + has_names = OF_hasprop(node, "interrupt-names"); +#endif + for (i = 0; i < nitems(arm_tmr_irq_defs); i++) { + int flags; + + /* + * If we don't have names to go off of, we assume that they're + * in the "usual" order with sec-phys first and allocate by idx. + */ + irq_def = &arm_tmr_irq_defs[i]; + rid = irq_def->idx; + flags = irq_def->flags; +#ifdef FDT + if (has_names) { + error = ofw_bus_find_string_index(node, + "interrupt-names", irq_def->name, &rid); + + /* + * If we have names, missing a name means we don't + * have it. + */ + if (error != 0) { + device_printf(dev, + "could not find irq for '%s'\n", + irq_def->name); + continue; + } + + /* + * Warn about failing to activate if we did actually + * have the name present. + */ + flags &= ~RF_OPTIONAL; + } +#endif + + sc->res[irq_def->idx] = bus_alloc_resource_any(dev, + SYS_RES_IRQ, &rid, flags); + + if (sc->res[irq_def->idx] == NULL) { + if ((flags & RF_OPTIONAL) == 0) { + device_printf(dev, + "could not allocate irq for '%s'\n", + irq_def->name); + } + + continue; + } + + if (bootverbose) { + device_printf(dev, + "allocated irq for '%s'\n", irq_def->name); + } } #ifdef __aarch64__