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 @@ -97,9 +97,16 @@ #define GT_CNTKCTL_PL0VCTEN (1 << 1) /* PL0 CNTVCT and CNTFRQ access */ #define GT_CNTKCTL_PL0PCTEN (1 << 0) /* PL0 CNTPCT and CNTFRQ access */ +struct arm_tmr_softc; + +struct arm_tmr_irq { + struct resource *res; + void *ihl; + int rid; +}; + struct arm_tmr_softc { - struct resource *res[GT_IRQ_COUNT]; - void *ihl[GT_IRQ_COUNT]; + struct arm_tmr_irq irqs[GT_IRQ_COUNT]; uint64_t (*get_cntxct)(bool); uint32_t clkfreq; struct eventtimer et; @@ -108,16 +115,6 @@ static struct arm_tmr_softc *arm_tmr_sc = NULL; -#ifdef DEV_ACPI -static struct resource_spec timer_acpi_spec[] = { - { SYS_RES_IRQ, GT_PHYS_SECURE, RF_ACTIVE | RF_OPTIONAL }, - { SYS_RES_IRQ, GT_PHYS_NONSECURE, RF_ACTIVE }, - { SYS_RES_IRQ, GT_VIRT, RF_ACTIVE }, - { SYS_RES_IRQ, GT_HYP_PHYS, RF_ACTIVE | RF_OPTIONAL }, - { -1, 0 } -}; -#endif - static const struct arm_tmr_irq_defs { int idx; const char *name; @@ -402,6 +399,29 @@ return (FILTER_HANDLED); } +static int +arm_tmr_attach_irq(device_t dev, struct arm_tmr_softc *sc, + const struct arm_tmr_irq_defs *irq_def, int rid, int flags) +{ + sc->irqs[irq_def->idx].res = bus_alloc_resource_any(dev, SYS_RES_IRQ, + &rid, flags); + if (sc->irqs[irq_def->idx].res == NULL) { + if (bootverbose || (flags & RF_OPTIONAL) == 0) { + device_printf(dev, + "could not allocate irq for %s interrupt '%s'\n", + (flags & RF_OPTIONAL) != 0 ? "optional" : + "required", irq_def->name); + } + + if ((flags & RF_OPTIONAL) == 0) + return (ENXIO); + } else if (bootverbose) { + device_printf(dev, "allocated irq for '%s'\n", irq_def->name); + } + + return (0); +} + #ifdef FDT static int arm_tmr_fdt_probe(device_t dev) @@ -479,42 +499,18 @@ flags &= ~RF_OPTIONAL; } - sc->res[irq_def->idx] = bus_alloc_resource_any(dev, - SYS_RES_IRQ, &rid, flags); - - if (sc->res[irq_def->idx] == NULL) { - device_printf(dev, - "could not allocate irq for %s interrupt '%s'\n", - (flags & RF_OPTIONAL) != 0 ? "optional" : - "required", irq_def->name); - - if ((flags & RF_OPTIONAL) == 0) { - error = ENXIO; - goto out; - } - - continue; - } - - if (bootverbose) { - device_printf(dev, - "allocated irq for '%s'\n", irq_def->name); - } + error = arm_tmr_attach_irq(dev, sc, irq_def, rid, flags); + if (error != 0) + goto out; } error = arm_tmr_attach(dev); out: if (error != 0) { for (i = 0; i < GT_IRQ_COUNT; i++) { - if (sc->res[i] != NULL) { - /* - * rid may not match the index into sc->res in - * a number of cases; e.g., optional sec-phys or - * interrupt-names specifying them in a - * different order than expected. - */ + if (sc->irqs[i].res != NULL) { bus_release_resource(dev, SYS_RES_IRQ, - rman_get_rid(sc->res[i]), sc->res[i]); + sc->irqs[i].rid, sc->irqs[i].res); } } } @@ -578,18 +574,29 @@ static int arm_tmr_acpi_attach(device_t dev) { + const struct arm_tmr_irq_defs *irq_def; struct arm_tmr_softc *sc; int error; sc = device_get_softc(dev); - if (bus_alloc_resources(dev, timer_acpi_spec, sc->res)) { - device_printf(dev, "could not allocate resources\n"); - return (ENXIO); + for (int i = 0; i < nitems(arm_tmr_irq_defs); i++) { + irq_def = &arm_tmr_irq_defs[i]; + error = arm_tmr_attach_irq(dev, sc, irq_def, irq_def->idx, + irq_def->flags); + if (error != 0) + goto out; } error = arm_tmr_attach(dev); - if (error != 0) - bus_release_resources(dev, timer_acpi_spec, sc->res); +out: + if (error != 0) { + for (int i = 0; i < GT_IRQ_COUNT; i++) { + if (sc->irqs[i].res != NULL) { + bus_release_resource(dev, SYS_RES_IRQ, + sc->irqs[i].rid, sc->irqs[i].res); + } + } + } return (error); } #endif @@ -643,13 +650,13 @@ for (i = 0; i < nitems(arm_tmr_irq_defs); i++) { irq_def = &arm_tmr_irq_defs[i]; - MPASS(sc->res[irq_def->idx] != NULL || + MPASS(sc->irqs[irq_def->idx].res != NULL || (irq_def->flags & RF_OPTIONAL) != 0); } #ifdef __aarch64__ /* Use the virtual timer if we have one. */ - if (sc->res[GT_VIRT] != NULL) { + if (sc->irqs[GT_VIRT].res != NULL) { sc->physical = false; first_timer = GT_VIRT; last_timer = GT_VIRT; @@ -667,24 +674,25 @@ /* Setup secure, non-secure and virtual IRQs handler */ for (i = first_timer; i <= last_timer; i++) { /* If we do not have the interrupt, skip it. */ - if (sc->res[i] == NULL) + if (sc->irqs[i].res == NULL) continue; - error = bus_setup_intr(dev, sc->res[i], INTR_TYPE_CLK, - arm_tmr_intr, NULL, sc, &sc->ihl[i]); + error = bus_setup_intr(dev, sc->irqs[i].res, INTR_TYPE_CLK, + arm_tmr_intr, NULL, sc, &sc->irqs[i].ihl); if (error) { device_printf(dev, "Unable to alloc int resource.\n"); for (int j = first_timer; j < i; j++) - bus_teardown_intr(dev, sc->res[j], &sc->ihl[j]); + bus_teardown_intr(dev, sc->irqs[j].res, + &sc->irqs[j].ihl); return (ENXIO); } } /* Disable the virtual timer until we are ready */ - if (sc->res[GT_VIRT] != NULL) + if (sc->irqs[GT_VIRT].res != NULL) arm_tmr_disable(false); /* And the physical */ - if ((sc->res[GT_PHYS_SECURE] != NULL || - sc->res[GT_PHYS_NONSECURE] != NULL) && HAS_PHYS) + if ((sc->irqs[GT_PHYS_SECURE].res != NULL || + sc->irqs[GT_PHYS_NONSECURE].res != NULL) && HAS_PHYS) arm_tmr_disable(true); arm_tmr_timecount.tc_frequency = sc->clkfreq;