diff options
author | ian <ian@FreeBSD.org> | 2014-08-17 01:28:03 +0000 |
---|---|---|
committer | ian <ian@FreeBSD.org> | 2014-08-17 01:28:03 +0000 |
commit | 2cc6abb7fbad979bb6fdddb3810bbb33c454c07d (patch) | |
tree | b2b014c39942426f2e4c0c06d2a440e2ec86233c /sys/arm | |
parent | 46d28d66fb3e9d4bfd5383e9b2ffa437115af6e6 (diff) | |
download | FreeBSD-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.c | 3 | ||||
-rw-r--r-- | sys/arm/arm/gic.c | 3 | ||||
-rw-r--r-- | sys/arm/arm/mpcore_timer.c | 3 | ||||
-rw-r--r-- | sys/arm/arm/nexus.c | 5 | ||||
-rw-r--r-- | sys/arm/arm/pl190.c | 3 | ||||
-rw-r--r-- | sys/arm/arm/pl310.c | 76 | ||||
-rw-r--r-- | sys/arm/include/pl310.h | 3 |
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; }; /** |