Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/cortex Add L2 cache flush routines. (not yet e...
details: https://anonhg.NetBSD.org/src/rev/26e5c4f5c310
branches: trunk
changeset: 781546:26e5c4f5c310
user: matt <matt%NetBSD.org@localhost>
date: Fri Sep 14 03:51:01 2012 +0000
description:
Add L2 cache flush routines. (not yet enabled).
diffstat:
sys/arch/arm/cortex/pl310.c | 173 +++++++++++++++++++++++++++++++++----------
1 files changed, 131 insertions(+), 42 deletions(-)
diffs (256 lines):
diff -r ca64850ba612 -r 26e5c4f5c310 sys/arch/arm/cortex/pl310.c
--- a/sys/arch/arm/cortex/pl310.c Thu Sep 13 21:44:49 2012 +0000
+++ b/sys/arch/arm/cortex/pl310.c Fri Sep 14 03:51:01 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pl310.c,v 1.4 2012/09/07 21:18:58 matt Exp $ */
+/* $NetBSD: pl310.c,v 1.5 2012/09/14 03:51:01 matt Exp $ */
/*-
* Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -30,12 +30,13 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pl310.c,v 1.4 2012/09/07 21:18:58 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pl310.c,v 1.5 2012/09/14 03:51:01 matt Exp $");
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/cpu.h>
#include <sys/device.h>
+#include <sys/atomic.h>
#include <arm/cortex/mpcore_var.h>
#include <arm/cortex/pl310_reg.h>
@@ -51,14 +52,28 @@
device_t sc_dev;
bus_space_tag_t sc_memt;
bus_space_handle_t sc_memh;
+ kmutex_t sc_lock;
+ uint32_t sc_waymask;
+ struct evcnt sc_ev_inv __aligned(8);
+ struct evcnt sc_ev_wb;
+ struct evcnt sc_ev_wbinv;
+ bool sc_enabled;
};
+__CTASSERT(offsetof(struct arml2cc_softc, sc_ev_inv.ev_count) % 8 == 0);
+__CTASSERT(offsetof(struct arml2cc_softc, sc_ev_wb.ev_count) % 8 == 0);
+__CTASSERT(offsetof(struct arml2cc_softc, sc_ev_wbinv.ev_count) % 8 == 0);
+
CFATTACH_DECL_NEW(arml2cc, sizeof(struct arml2cc_softc),
arml2cc_match, arml2cc_attach, NULL, NULL);
static void arml2cc_disable(struct arml2cc_softc *);
+static void arml2cc_enable(struct arml2cc_softc *);
+static void arml2cc_sdcache_wb_range(vaddr_t, paddr_t, psize_t);
+static void arml2cc_sdcache_inv_range(vaddr_t, paddr_t, psize_t);
+static void arml2cc_sdcache_wbinv_range(vaddr_t, paddr_t, psize_t);
-static bool attached;
+static struct arml2cc_softc *arml2cc_sc;
static inline uint32_t
arml2cc_read_4(struct arml2cc_softc *sc, bus_size_t o)
@@ -79,7 +94,7 @@
{
struct mpcore_attach_args * const mpcaa = aux;
- if (attached)
+ if (arml2cc_sc)
return 0;
if (!CPU_ID_CORTEX_A9_P(curcpu()->ci_arm_cpuid))
@@ -116,9 +131,21 @@
{
struct arml2cc_softc * const sc = device_private(self);
struct mpcore_attach_args * const mpcaa = aux;
+ const char * const xname = device_xname(self);
+ arml2cc_sc = sc;
sc->sc_dev = self;
sc->sc_memt = mpcaa->mpcaa_memt;
+ sc->sc_waymask = __BIT(arm_scache.dcache_ways) - 1;
+
+ evcnt_attach_dynamic(&sc->sc_ev_inv, EVCNT_TYPE_MISC, NULL,
+ xname, "L2 inv requests");
+ evcnt_attach_dynamic(&sc->sc_ev_wb, EVCNT_TYPE_MISC, NULL,
+ xname, "L2 wb requests");
+ evcnt_attach_dynamic(&sc->sc_ev_wbinv, EVCNT_TYPE_MISC, NULL,
+ xname, "L2 wbinv requests");
+
+ mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_HIGH);
bus_space_subregion(sc->sc_memt, mpcaa->mpcaa_memh,
L2CC_BASE, L2CC_SIZE, &sc->sc_memh);
@@ -140,33 +167,82 @@
aprint_normal(": ARM PL310%s L2 Cache Controller%s\n",
revstr, enabled_p ? "" : " (disabled)");
+#if 1
if (enabled_p) {
- arml2cc_disable(sc);
+ if (1) {
+ arml2cc_disable(sc);
+ aprint_normal_dev(self, "cache %s\n",
+ arml2cc_read_4(sc, L2C_CTL) ? "enabled" : "disabled");
+ sc->sc_enabled = false;
+ } else {
+ cpufuncs.cf_sdcache_wb_range = arml2cc_sdcache_wb_range;
+ cpufuncs.cf_sdcache_inv_range = arml2cc_sdcache_inv_range;
+ cpufuncs.cf_sdcache_wbinv_range = arml2cc_sdcache_wbinv_range;
+ sc->sc_enabled = true;
+ }
+ }
+#else
+ if (!enabled_p) {
+ arml2cc_enable(sc);
aprint_normal_dev(self, "cache %s\n",
arml2cc_read_4(sc, L2C_CTL) ? "enabled" : "disabled");
}
+ cpufuncs.cf_sdcache_wb_range = arml2cc_sdcache_wb_range;
+ cpufuncs.cf_sdcache_inv_range = arml2cc_sdcache_inv_range;
+ cpufuncs.cf_sdcache_wbinv_range = arml2cc_sdcache_wbinv_range;
+ sc->sc_enabled = true;
+#endif
KASSERT(arm_pcache.dcache_line_size == arm_scache.dcache_line_size);
}
-void
+static inline void
+arml2cc_cache_op(struct arml2cc_softc *sc, bus_size_t off, uint32_t val)
+{
+ arml2cc_write_4(sc, off, val);
+ while (arml2cc_read_4(sc, off) & 1) {
+ /* spin */
+ }
+}
+
+static inline void
+arml2cc_cache_way_op(struct arml2cc_softc *sc, bus_size_t off, uint32_t way_mask)
+{
+ arml2cc_write_4(sc, off, way_mask);
+ while (arml2cc_read_4(sc, off) & way_mask) {
+ /* spin */
+ }
+}
+
+static inline void
+arml2cc_cache_sync(struct arml2cc_softc *sc)
+{
+ arml2cc_cache_op(sc, L2C_CACHE_SYNC, 0);
+}
+
+static inline void
arml2cc_disable(struct arml2cc_softc *sc)
{
- uint32_t way_mask = __BIT(arm_scache.dcache_ways) - 1;
- register_t psw = cpsid(I32_bit);
+ mutex_spin_enter(&sc->sc_lock);
- arml2cc_write_4(sc, L2C_CLEAN_INV_WAY, way_mask);
- while (arml2cc_read_4(sc, L2C_CLEAN_INV_WAY) != 0) {
- /* spin */
- }
+ arml2cc_cache_way_op(sc, L2C_CLEAN_INV_WAY, sc->sc_waymask);
+ arml2cc_cache_sync(sc);
+
+ arml2cc_write_4(sc, L2C_CTL, 0); // turn it off
+ mutex_spin_exit(&sc->sc_lock);
+}
- arml2cc_write_4(sc, L2C_CACHE_SYNC, 0);
- while (arml2cc_read_4(sc, L2C_CACHE_SYNC) & 1) {
- /* spin */
- }
+static inline void
+arml2cc_enable(struct arml2cc_softc *sc)
+{
+ mutex_spin_enter(&sc->sc_lock);
- arml2cc_write_4(sc, L2C_CTL, 0); // turn it off */
- cpsie(psw);
+ arml2cc_write_4(sc, L2C_CTL, 1); // turn it on
+
+ //arml2cc_cache_way_op(sc, L2C_INV_WAY, sc->sc_waymask);
+ arml2cc_cache_sync(sc);
+
+ mutex_spin_exit(&sc->sc_lock);
}
void
@@ -198,36 +274,49 @@
}
}
-#if 0
static void
-arml2cc_dcache_wb_range(vaddr_t va, vsize_t len)
+arml2cc_cache_range_op(paddr_t pa, psize_t len, bus_size_t cache_op)
{
- const size_t line_size = arm_pcache.dcache_line_size;
+ struct arml2cc_softc * const sc = arml2cc_sc;
+ const size_t line_size = arm_scache.dcache_line_size;
const size_t line_mask = line_size - 1;
- size_t off = va & line_mask;
- size_t page_len = 0;
- paddr_t pa = 0;
+ size_t off = pa & line_mask;
if (off) {
len += off;
- va -= off;
+ pa -= off;
}
- for (const vaddr_t endva = va + roundup2(len, line_size);
- va < endva;
- va += line_size) {
- armreg_dccmvac(va); /* this may fault */
- __asm __volatile("dsb");
- if (page_len == 0) {
- armreg_ats1cpr_write(va);
- pa = armreg_par_read();
- const psize = __predict_false(pa & 1) ? L1_SS_SIZE : L2_S_SIZE;
- pa &= -psize;
- endpa = pa + psize;
- page_len = (va & (psize - 1);
+ len = roundup2(len, line_size);
+ off = pa & PAGE_MASK;
+ for (const paddr_t endpa = pa + len; pa < endpa; off = 0) {
+ psize_t seglen = min(len, PAGE_SIZE - off);
+
+ mutex_spin_enter(&sc->sc_lock);
+ if (!sc->sc_enabled)
+ return;
+ for (paddr_t segend = pa + seglen; pa < segend; pa += line_size) {
+ arml2cc_cache_op(sc, cache_op, pa);
}
- size_t set = va
- arml2cc_write_4(sc, L2C_CLEAN_PA, pa);
-
- va += line_size;
+ mutex_spin_exit(&sc->sc_lock);
}
}
-#endif
+
+static void
+arml2cc_sdcache_inv_range(vaddr_t va, paddr_t pa, psize_t len)
+{
+ atomic_inc_64(&arml2cc_sc->sc_ev_inv.ev_count);
+ arml2cc_cache_range_op(pa, len, L2C_INV_PA);
+}
+
+static void
+arml2cc_sdcache_wb_range(vaddr_t va, paddr_t pa, psize_t len)
+{
+ atomic_inc_64(&arml2cc_sc->sc_ev_wb.ev_count);
+ arml2cc_cache_range_op(pa, len, L2C_CLEAN_PA);
+}
+
+static void
+arml2cc_sdcache_wbinv_range(vaddr_t va, paddr_t pa, psize_t len)
+{
+ atomic_inc_64(&arml2cc_sc->sc_ev_wbinv.ev_count);
+ arml2cc_cache_range_op(pa, len, L2C_CLEAN_INV_PA);
+}
Home |
Main Index |
Thread Index |
Old Index