Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145507765
D38911.id118463.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D38911.id118463.diff
View Options
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,13 +108,49 @@
static struct arm_tmr_softc *arm_tmr_sc = NULL;
-static struct resource_spec timer_spec[] = {
- { SYS_RES_IRQ, GT_PHYS_SECURE, RF_ACTIVE },
+#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 | RF_OPTIONAL },
- { SYS_RES_IRQ, GT_HYP, RF_ACTIVE | RF_OPTIONAL },
+ { 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;
+ 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 int arm_tmr_attach(device_t);
static uint32_t arm_tmr_fill_vdso_timehands(struct vdso_timehands *vdso_th,
struct timecounter *tc);
@@ -384,6 +421,94 @@
return (ENXIO);
}
+
+static int
+arm_tmr_fdt_attach(device_t dev)
+{
+ struct arm_tmr_softc *sc;
+ const struct arm_tmr_irq_defs *irq_def;
+ size_t i;
+ phandle_t node;
+ int error, rid;
+ bool has_names;
+
+ sc = device_get_softc(dev);
+ node = ofw_bus_get_node(dev);
+
+ has_names = OF_hasprop(node, "interrupt-names");
+ 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;
+ 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;
+ }
+
+ 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);
+
+ goto out;
+ }
+
+ continue;
+ }
+
+ if (bootverbose) {
+ device_printf(dev,
+ "allocated irq for '%s'\n", irq_def->name);
+ }
+ }
+
+ 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.
+ */
+ bus_release_resource(dev, SYS_RES_IRQ,
+ rman_get_rid(sc->res[i]), sc->res[i]);
+ }
+ }
+ }
+
+ return (error);
+
+}
#endif
#ifdef DEV_ACPI
@@ -436,12 +561,31 @@
device_set_desc(dev, "ARM Generic Timer");
return (BUS_PROBE_NOWILDCARD);
}
+
+static int
+arm_tmr_acpi_attach(device_t dev)
+{
+ 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);
+ }
+
+ error = arm_tmr_attach(dev);
+ if (error != 0)
+ bus_release_resources(dev, timer_acpi_spec, sc->res);
+ return (error);
+}
#endif
static int
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;
@@ -482,9 +626,12 @@
return (ENXIO);
}
- if (bus_alloc_resources(dev, timer_spec, sc->res)) {
- device_printf(dev, "could not allocate resources\n");
- return (ENXIO);
+ /* Confirm that non-optional irqs were allocated before coming in. */
+ for (i = 0; i < nitems(arm_tmr_irq_defs); i++) {
+ irq_def = &arm_tmr_irq_defs[i];
+
+ MPASS(sc->res[irq_def->idx] != NULL ||
+ (irq_def->flags & RF_OPTIONAL) != 0);
}
#ifdef __aarch64__
@@ -513,6 +660,8 @@
arm_tmr_intr, NULL, sc, &sc->ihl[i]);
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]);
return (ENXIO);
}
}
@@ -550,7 +699,7 @@
#ifdef FDT
static device_method_t arm_tmr_fdt_methods[] = {
DEVMETHOD(device_probe, arm_tmr_fdt_probe),
- DEVMETHOD(device_attach, arm_tmr_attach),
+ DEVMETHOD(device_attach, arm_tmr_fdt_attach),
{ 0, 0 }
};
@@ -567,7 +716,7 @@
static device_method_t arm_tmr_acpi_methods[] = {
DEVMETHOD(device_identify, arm_tmr_acpi_identify),
DEVMETHOD(device_probe, arm_tmr_acpi_probe),
- DEVMETHOD(device_attach, arm_tmr_attach),
+ DEVMETHOD(device_attach, arm_tmr_acpi_attach),
{ 0, 0 }
};
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Feb 21, 6:03 PM (21 h, 6 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28925888
Default Alt Text
D38911.id118463.diff (5 KB)
Attached To
Mode
D38911: arm: generic_timer: use interrupt-names when available
Attached
Detach File
Event Timeline
Log In to Comment