summaryrefslogtreecommitdiffstats
path: root/sys/arm
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2014-08-17 01:28:03 +0000
committerian <ian@FreeBSD.org>2014-08-17 01:28:03 +0000
commit2cc6abb7fbad979bb6fdddb3810bbb33c454c07d (patch)
treeb2b014c39942426f2e4c0c06d2a440e2ec86233c /sys/arm
parent46d28d66fb3e9d4bfd5383e9b2ffa437115af6e6 (diff)
downloadFreeBSD-src-2cc6abb7fbad979bb6fdddb3810bbb33c454c07d.zip
FreeBSD-src-2cc6abb7fbad979bb6fdddb3810bbb33c454c07d.tar.gz
MFC r269594, r269596, r269597, r269598, r269605, r269606:
Set ofwbus and simplebus to attach during BUS_PASS_BUS. Define names that drivers can use to adjust their position relative to other drivers within a BUS_PASS Adjust ofwbus and simplebus to attach at BUS_PASS_ORDER_MIDDLE, so that a platform can attach some other bus first if necessary. Set the pl310 L2 cache driver to attach during the middle of BUS_PASS_CPU. Attach arm generic interrupt and timer drivers in the middle of BUS_PASS_INTERRUPT and BUS_PASS_TIMER, respectively. Add an arm option, ARM_DEVICE_MULTIPASS, used to opt-in to multi-pass device attachment on arm platforms. If this is defined, nexus attaches early in BUS_PASS_BUS, and other busses and devices attach later, in the pass number they are set up for. Without it defined, nexus attaches in BUS_PASS_DEFAULT and thus so does everything else, which is status quo.
Diffstat (limited to 'sys/arm')
-rw-r--r--sys/arm/arm/generic_timer.c3
-rw-r--r--sys/arm/arm/gic.c3
-rw-r--r--sys/arm/arm/mpcore_timer.c3
-rw-r--r--sys/arm/arm/nexus.c5
-rw-r--r--sys/arm/arm/pl190.c3
-rw-r--r--sys/arm/arm/pl310.c76
-rw-r--r--sys/arm/include/pl310.h3
7 files changed, 65 insertions, 31 deletions
diff --git a/sys/arm/arm/generic_timer.c b/sys/arm/arm/generic_timer.c
index 63e1717..df7d0cd 100644
--- a/sys/arm/arm/generic_timer.c
+++ b/sys/arm/arm/generic_timer.c
@@ -343,7 +343,8 @@ static driver_t arm_tmr_driver = {
static devclass_t arm_tmr_devclass;
-DRIVER_MODULE(timer, simplebus, arm_tmr_driver, arm_tmr_devclass, 0, 0);
+EARLY_DRIVER_MODULE(timer, simplebus, arm_tmr_driver, arm_tmr_devclass, 0, 0,
+ BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
void
DELAY(int usec)
diff --git a/sys/arm/arm/gic.c b/sys/arm/arm/gic.c
index 4d523c3..49d3c62 100644
--- a/sys/arm/arm/gic.c
+++ b/sys/arm/arm/gic.c
@@ -263,7 +263,8 @@ static driver_t arm_gic_driver = {
static devclass_t arm_gic_devclass;
-DRIVER_MODULE(gic, simplebus, arm_gic_driver, arm_gic_devclass, 0, 0);
+EARLY_DRIVER_MODULE(gic, simplebus, arm_gic_driver, arm_gic_devclass, 0, 0,
+ BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
static void
gic_post_filter(void *arg)
diff --git a/sys/arm/arm/mpcore_timer.c b/sys/arm/arm/mpcore_timer.c
index bf30707..3f87a2a 100644
--- a/sys/arm/arm/mpcore_timer.c
+++ b/sys/arm/arm/mpcore_timer.c
@@ -382,7 +382,8 @@ static driver_t arm_tmr_driver = {
static devclass_t arm_tmr_devclass;
-DRIVER_MODULE(mp_tmr, simplebus, arm_tmr_driver, arm_tmr_devclass, 0, 0);
+EARLY_DRIVER_MODULE(mp_tmr, simplebus, arm_tmr_driver, arm_tmr_devclass, 0, 0,
+ BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
/*
* Handle a change in clock frequency. The mpcore timer runs at half the CPU
diff --git a/sys/arm/arm/nexus.c b/sys/arm/arm/nexus.c
index fe1261f..a66fc3e 100644
--- a/sys/arm/arm/nexus.c
+++ b/sys/arm/arm/nexus.c
@@ -125,7 +125,12 @@ static driver_t nexus_driver = {
nexus_methods,
1 /* no softc */
};
+#ifdef ARM_DEVICE_MULTIPASS
+EARLY_DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0,
+ BUS_PASS_BUS + BUS_PASS_ORDER_EARLY);
+#else
DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0);
+#endif
static int
nexus_probe(device_t dev)
diff --git a/sys/arm/arm/pl190.c b/sys/arm/arm/pl190.c
index 01cd84a..5e81134 100644
--- a/sys/arm/arm/pl190.c
+++ b/sys/arm/arm/pl190.c
@@ -152,7 +152,8 @@ static driver_t pl190_intc_driver = {
static devclass_t pl190_intc_devclass;
-DRIVER_MODULE(intc, simplebus, pl190_intc_driver, pl190_intc_devclass, 0, 0);
+EARLY_DRIVER_MODULE(intc, simplebus, pl190_intc_driver, pl190_intc_devclass,
+ 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
int
arm_get_next_irq(int last_irq)
diff --git a/sys/arm/arm/pl310.c b/sys/arm/arm/pl310.c
index cf19d6c..76ad17b 100644
--- a/sys/arm/arm/pl310.c
+++ b/sys/arm/arm/pl310.c
@@ -378,6 +378,44 @@ pl310_set_way_sizes(struct pl310_softc *sc)
g_l2cache_size = g_way_size * g_ways_assoc;
}
+/*
+ * Setup interrupt handling. This is done only if the cache controller is
+ * disabled, for debugging. We set counters so when a cache event happens we'll
+ * get interrupted and be warned that something is wrong, because no cache
+ * events should happen if we're disabled.
+ */
+static void
+pl310_config_intr(void *arg)
+{
+ struct pl310_softc * sc;
+
+ sc = arg;
+
+ /* activate the interrupt */
+ bus_setup_intr(sc->sc_dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ pl310_filter, NULL, sc, &sc->sc_irq_h);
+
+ /* Cache Line Eviction for Counter 0 */
+ pl310_write4(sc, PL310_EVENT_COUNTER0_CONF,
+ EVENT_COUNTER_CONF_INCR | EVENT_COUNTER_CONF_CO);
+ /* Data Read Request for Counter 1 */
+ pl310_write4(sc, PL310_EVENT_COUNTER1_CONF,
+ EVENT_COUNTER_CONF_INCR | EVENT_COUNTER_CONF_DRREQ);
+
+ /* Enable and clear pending interrupts */
+ pl310_write4(sc, PL310_INTR_CLEAR, INTR_MASK_ECNTR);
+ pl310_write4(sc, PL310_INTR_MASK, INTR_MASK_ALL);
+
+ /* Enable counters and reset C0 and C1 */
+ pl310_write4(sc, PL310_EVENT_COUNTER_CTRL,
+ EVENT_COUNTER_CTRL_ENABLED |
+ EVENT_COUNTER_CTRL_C0_RESET |
+ EVENT_COUNTER_CTRL_C1_RESET);
+
+ config_intrhook_disestablish(sc->sc_ich);
+ free(sc->sc_ich, M_DEVBUF);
+}
+
static int
pl310_probe(device_t dev)
{
@@ -416,10 +454,6 @@ pl310_attach(device_t dev)
pl310_softc = sc;
mtx_init(&sc->sc_mtx, "pl310lock", NULL, MTX_SPIN);
- /* activate the interrupt */
- bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
- pl310_filter, NULL, sc, &sc->sc_irq_h);
-
cache_id = pl310_read4(sc, PL310_CACHE_ID);
sc->sc_rtl_revision = (cache_id >> CACHE_ID_RELEASE_SHIFT) &
CACHE_ID_RELEASE_MASK;
@@ -466,28 +500,14 @@ pl310_attach(device_t dev)
if (bootverbose)
pl310_print_config(sc);
} else {
- /*
- * Set counters so when cache event happens we'll get interrupt
- * and be warned that something is off.
- */
-
- /* Cache Line Eviction for Counter 0 */
- pl310_write4(sc, PL310_EVENT_COUNTER0_CONF,
- EVENT_COUNTER_CONF_INCR | EVENT_COUNTER_CONF_CO);
- /* Data Read Request for Counter 1 */
- pl310_write4(sc, PL310_EVENT_COUNTER1_CONF,
- EVENT_COUNTER_CONF_INCR | EVENT_COUNTER_CONF_DRREQ);
-
- /* Enable and clear pending interrupts */
- pl310_write4(sc, PL310_INTR_CLEAR, INTR_MASK_ECNTR);
- pl310_write4(sc, PL310_INTR_MASK, INTR_MASK_ALL);
-
- /* Enable counters and reset C0 and C1 */
- pl310_write4(sc, PL310_EVENT_COUNTER_CTRL,
- EVENT_COUNTER_CTRL_ENABLED |
- EVENT_COUNTER_CTRL_C0_RESET |
- EVENT_COUNTER_CTRL_C1_RESET);
-
+ malloc(sizeof(*sc->sc_ich), M_DEVBUF, M_WAITOK);
+ sc->sc_ich->ich_func = pl310_config_intr;
+ sc->sc_ich->ich_arg = sc;
+ if (config_intrhook_establish(sc->sc_ich) != 0) {
+ device_printf(dev,
+ "config_intrhook_establish failed\n");
+ return(ENXIO);
+ }
device_printf(dev, "L2 Cache disabled\n");
}
@@ -514,4 +534,6 @@ static driver_t pl310_driver = {
};
static devclass_t pl310_devclass;
-DRIVER_MODULE(pl310, simplebus, pl310_driver, pl310_devclass, 0, 0);
+EARLY_DRIVER_MODULE(pl310, simplebus, pl310_driver, pl310_devclass, 0, 0,
+ BUS_PASS_CPU + BUS_PASS_ORDER_MIDDLE);
+
diff --git a/sys/arm/include/pl310.h b/sys/arm/include/pl310.h
index 8730877..f7c75e9 100644
--- a/sys/arm/include/pl310.h
+++ b/sys/arm/include/pl310.h
@@ -137,6 +137,8 @@
#define POWER_CTRL_ENABLE_GATING (1 << 0)
#define POWER_CTRL_ENABLE_STANDBY (1 << 1)
+struct intr_config_hook;
+
struct pl310_softc {
device_t sc_dev;
struct resource *sc_mem_res;
@@ -145,6 +147,7 @@ struct pl310_softc {
int sc_enabled;
struct mtx sc_mtx;
u_int sc_rtl_revision;
+ struct intr_config_hook *sc_ich;
};
/**
OpenPOWER on IntegriCloud