summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/arch/arm/cortex/arml2cc.c297
-rw-r--r--sys/arch/arm/cortex/files.cortex6
-rw-r--r--sys/arch/beagle/conf/GENERIC3
-rw-r--r--sys/arch/beagle/conf/RAMDISK3
4 files changed, 306 insertions, 3 deletions
diff --git a/sys/arch/arm/cortex/arml2cc.c b/sys/arch/arm/cortex/arml2cc.c
new file mode 100644
index 00000000000..cdc1b3125a7
--- /dev/null
+++ b/sys/arch/arm/cortex/arml2cc.c
@@ -0,0 +1,297 @@
+/* $OpenBSD: arml2cc.c,v 1.1 2013/05/02 19:15:53 patrick Exp $ */
+/*
+ * Copyright (c) 2013 Patrick Wildt <patrick@blueri.se>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <sys/evcount.h>
+#include <sys/socket.h>
+#include <sys/timeout.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+#include <machine/cpufunc.h>
+#include <arm/cortex/cortex.h>
+#include <arm/cortex/smc.h>
+
+#define PL310_ERRATA_727915
+
+/* offset from periphbase */
+#define L2C_ADDR 0x2000
+#define L2C_SIZE 0x1000
+
+/* registers */
+#define L2C_CACHE_ID 0x000
+#define L2C_CACHE_TYPE 0x004
+#define L2C_CTL 0x100
+#define L2C_AUXCTL 0x104
+#define L2C_TAG_RAM_CTL 0x108
+#define L2C_DATA_RAM_CTL 0x10c
+#define L2C_EVC_CTR_CTL 0x200
+#define L2C_EVC_CTR0_CTL 0x204
+#define L2C_EVC_CTR1_CTL 0x208
+#define L2C_EVC_CTR0_VAL 0x20c
+#define L2C_EVC_CTR1_VAL 0x210
+#define L2C_INT_MASK 0x214
+#define L2C_INT_MASK_STS 0x218
+#define L2C_INT_RAW_STS 0x21c
+#define L2C_INT_CLR 0x220
+#define L2C_CACHE_SYNC 0x730
+#define L2C_INV_PA 0x770
+#define L2C_INV_WAY 0x77c
+#define L2C_CLEAN_PA 0x7b0
+#define L2C_CLEAN_INDEX 0x7b8
+#define L2C_CLEAN_WAY 0x7bc
+#define L2C_CLEAN_INV_PA 0x7f0
+#define L2C_CLEAN_INV_INDEX 0x7f8
+#define L2C_CLEAN_INV_WAY 0x7fc
+#define L2C_D_LOCKDOWN0 0x900
+#define L2C_I_LOCKDOWN0 0x904
+#define L2C_D_LOCKDOWN1 0x908
+#define L2C_I_LOCKDOWN1 0x90c
+#define L2C_D_LOCKDOWN2 0x910
+#define L2C_I_LOCKDOWN2 0x914
+#define L2C_D_LOCKDOWN3 0x918
+#define L2C_I_LOCKDOWN3 0x91c
+#define L2C_D_LOCKDOWN4 0x920
+#define L2C_I_LOCKDOWN4 0x924
+#define L2C_D_LOCKDOWN5 0x928
+#define L2C_I_LOCKDOWN5 0x92c
+#define L2C_D_LOCKDOWN6 0x930
+#define L2C_I_LOCKDOWN6 0x934
+#define L2C_D_LOCKDOWN7 0x938
+#define L2C_I_LOCKDOWN7 0x93c
+#define L2C_LOCKDOWN_LINE_EN 0x950
+#define L2C_UNLOCK_WAY 0x954
+#define L2C_ADDR_FILTER_START 0xc00
+#define L2C_ADDR_FILTER_END 0xc04
+#define L2C_DEBUG_CTL 0xf40
+#define L2C_PREFETCH_CTL 0xf60
+#define L2C_POWER_CTL 0xf80
+
+#define L2C_CACHE_ID_RELEASE_MASK 0x3f
+#define L2C_CACHE_TYPE_LINESIZE 0x3
+#define L2C_AUXCTL_ASSOC_SHIFT 16
+#define L2C_AUXCTL_ASSOC_MASK 0x1
+
+#define roundup2(size, unit) (((size) + (unit) - 1) & ~((unit) - 1))
+
+struct arml2cc_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ uint32_t sc_enabled;
+ uint32_t sc_waymask;
+ uint32_t sc_dcache_line_size;
+};
+
+struct arml2cc_softc *arml2cc_sc;
+
+int arml2cc_match(struct device *, void *, void *);
+void arml2cc_attach(struct device *parent, struct device *self, void *args);
+void arml2cc_enable(struct arml2cc_softc *);
+void arml2cc_disable(struct arml2cc_softc *);
+void arml2cc_sdcache_wbinv_all(void);
+void arml2cc_sdcache_wbinv_range(vaddr_t, paddr_t, psize_t);
+void arml2cc_sdcache_inv_range(vaddr_t, paddr_t, psize_t);
+void arml2cc_sdcache_wb_range(vaddr_t, paddr_t, psize_t);
+void arml2cc_cache_range_op(paddr_t, psize_t, bus_size_t);
+void arml2cc_cache_way_op(struct arml2cc_softc *, bus_size_t, uint32_t);
+void arml2cc_cache_op(struct arml2cc_softc *, bus_size_t, uint32_t);
+void arml2cc_cache_sync(struct arml2cc_softc *);
+
+struct cfattach armliicc_ca = {
+ sizeof (struct arml2cc_softc), arml2cc_match, arml2cc_attach
+};
+
+struct cfdriver armliicc_cd = {
+ NULL, "armliicc", DV_DULL
+};
+
+int
+arml2cc_match(struct device *parent, void *cfdata, void *aux)
+{
+ return (1);
+}
+
+void
+arml2cc_attach(struct device *parent, struct device *self, void *args)
+{
+ struct cortex_attach_args *ia = args;
+ struct arml2cc_softc *sc = (struct arml2cc_softc *) self;
+
+ sc->sc_iot = ia->ca_iot;
+ if (bus_space_map(sc->sc_iot, ia->ca_periphbase + L2C_ADDR,
+ L2C_SIZE, 0, &sc->sc_ioh))
+ panic("arml2cc_attach: bus_space_map failed!");
+
+ printf(": rtl %d", bus_space_read_4(sc->sc_iot, sc->sc_ioh,
+ L2C_CACHE_ID) & 0x3f);
+
+ arml2cc_sc = sc;
+
+ if (bus_space_read_4(sc->sc_iot, sc->sc_ioh, L2C_CTL))
+ panic("L2 Cache controller was already enabled\n");
+
+ sc->sc_dcache_line_size = 32 << (bus_space_read_4(sc->sc_iot, sc->sc_ioh, L2C_CACHE_TYPE) & L2C_CACHE_TYPE_LINESIZE);
+ sc->sc_waymask = (8 << ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, L2C_AUXCTL)
+ >> L2C_AUXCTL_ASSOC_SHIFT) & L2C_AUXCTL_ASSOC_MASK)) - 1;
+ printf(" waymask: 0x%08x\n", sc->sc_waymask);
+
+ arml2cc_enable(sc);
+ sc->sc_enabled = 1;
+
+ arml2cc_sdcache_wbinv_all();
+
+ cpufuncs.cf_sdcache_wbinv_all = arml2cc_sdcache_wbinv_all;
+ cpufuncs.cf_sdcache_wbinv_range = arml2cc_sdcache_wbinv_range;
+ cpufuncs.cf_sdcache_inv_range = arml2cc_sdcache_inv_range;
+ cpufuncs.cf_sdcache_wb_range = arml2cc_sdcache_wb_range;
+}
+
+void
+arml2cc_enable(struct arml2cc_softc *sc)
+{
+ int s;
+ s = splhigh();
+
+ platform_smc_write(sc->sc_iot, sc->sc_ioh, L2C_CTL, SMC_L2_CTL,
+ 1);
+
+ arml2cc_cache_way_op(sc, L2C_INV_WAY, sc->sc_waymask);
+ arml2cc_cache_sync(sc);
+
+ splx(s);
+}
+
+void
+arml2cc_disable(struct arml2cc_softc *sc)
+{
+ int s;
+ s = splhigh();
+
+ arml2cc_cache_way_op(sc, L2C_CLEAN_INV_WAY, sc->sc_waymask);
+ arml2cc_cache_sync(sc);
+
+ platform_smc_write(sc->sc_iot, sc->sc_ioh, L2C_CTL, SMC_L2_CTL, 0);
+
+ splx(s);
+}
+
+void
+arml2cc_cache_op(struct arml2cc_softc *sc, bus_size_t off, uint32_t val)
+{
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, off, val);
+ while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, off) & 1) {
+ /* spin */
+ }
+}
+
+void
+arml2cc_cache_way_op(struct arml2cc_softc *sc, bus_size_t off, uint32_t way_mask)
+{
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, off, way_mask);
+ while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, off) & way_mask) {
+ /* spin */
+ }
+}
+
+void
+arml2cc_cache_sync(struct arml2cc_softc *sc)
+{
+ /* ARM Errata 753970 */
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, 0x740, 0xffffffff);
+}
+
+void
+arml2cc_cache_range_op(paddr_t pa, psize_t len, bus_size_t cache_op)
+{
+ struct arml2cc_softc * const sc = arml2cc_sc;
+ size_t line_size = sc->sc_dcache_line_size;
+ size_t line_mask = line_size - 1;
+ paddr_t endpa;
+
+ endpa = pa + len;
+ pa = pa & ~line_mask;
+
+ // printf("l2inv op %x %08x %08x incr %d %d\n", cache_op, pa, endpa, line_size, len);
+ while (endpa > pa) {
+ arml2cc_cache_op(sc, cache_op, pa);
+ pa += line_size;
+ }
+#endif
+}
+
+void
+arml2cc_sdcache_wbinv_all(void)
+{
+ struct arml2cc_softc *sc = arml2cc_sc;
+ if (sc == NULL || !sc->sc_enabled)
+ return;
+
+#ifdef PL310_ERRATA_727915
+ platform_smc_write(sc->sc_iot, sc->sc_ioh, L2C_DEBUG_CTL, SMC_L2_DBG, 3);
+#endif
+
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, L2C_CLEAN_INV_WAY, sc->sc_waymask);
+ while(bus_space_read_4(sc->sc_iot, sc->sc_ioh, L2C_CLEAN_INV_WAY) & sc->sc_waymask);
+
+#ifdef PL310_ERRATA_727915
+ platform_smc_write(sc->sc_iot, sc->sc_ioh, L2C_DEBUG_CTL, SMC_L2_DBG, 0);
+#endif
+
+ arml2cc_cache_sync(sc);
+}
+void
+arml2cc_sdcache_wbinv_range(vaddr_t va, paddr_t pa, psize_t len)
+{
+ struct arml2cc_softc *sc = arml2cc_sc;
+ if (sc == NULL || !sc->sc_enabled)
+ return;
+
+#ifdef PL310_ERRATA_727915
+ platform_smc_write(sc->sc_iot, sc->sc_ioh, L2C_DEBUG_CTL, SMC_L2_DBG, 3);
+#endif
+
+ arml2cc_cache_range_op(pa, len, L2C_CLEAN_INV_PA);
+ arml2cc_cache_sync(sc);
+
+#ifdef PL310_ERRATA_727915
+ platform_smc_write(sc->sc_iot, sc->sc_ioh, L2C_DEBUG_CTL, SMC_L2_DBG, 0);
+#endif
+}
+
+void
+arml2cc_sdcache_inv_range(vaddr_t va, paddr_t pa, psize_t len)
+{
+ struct arml2cc_softc *sc = arml2cc_sc;
+ if (sc == NULL || !sc->sc_enabled)
+ return;
+ arml2cc_cache_range_op(pa, len, L2C_INV_PA);
+ arml2cc_cache_sync(sc);
+}
+
+void
+arml2cc_sdcache_wb_range(vaddr_t va, paddr_t pa, psize_t len)
+{
+ struct arml2cc_softc *sc = arml2cc_sc;
+ if (sc == NULL || !sc->sc_enabled)
+ return;
+ arml2cc_cache_range_op(pa, len, L2C_CLEAN_PA);
+ arml2cc_cache_sync(sc);
+}
diff --git a/sys/arch/arm/cortex/files.cortex b/sys/arch/arm/cortex/files.cortex
index bf4eca15c2c..26ad73979a9 100644
--- a/sys/arch/arm/cortex/files.cortex
+++ b/sys/arch/arm/cortex/files.cortex
@@ -1,4 +1,4 @@
-# $OpenBSD: files.cortex,v 1.1 2013/05/01 00:16:26 patrick Exp $
+# $OpenBSD: files.cortex,v 1.2 2013/05/02 19:15:53 patrick Exp $
# ARM core
device cortex {}
@@ -12,3 +12,7 @@ file arch/arm/cortex/ampintc.c ampintc
device amptimer
attach amptimer at cortex
file arch/arm/cortex/amptimer.c amptimer
+
+device armliicc
+attach armliicc at cortex
+file arch/arm/cortex/arml2cc.c armliicc
diff --git a/sys/arch/beagle/conf/GENERIC b/sys/arch/beagle/conf/GENERIC
index c71ef541ddf..6fb5c1dbcf0 100644
--- a/sys/arch/beagle/conf/GENERIC
+++ b/sys/arch/beagle/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.15 2013/05/01 00:16:26 patrick Exp $
+# $OpenBSD: GENERIC,v 1.16 2013/05/02 19:15:53 patrick Exp $
#
# GENERIC machine description file
#
@@ -60,6 +60,7 @@ omap0 at mainbus?
cortex0 at mainbus?
ampintc* at cortex?
amptimer* at cortex?
+#armliicc* at cortex? # L2 cache controller
# OMAP3 only
intc* at soc? # interrupt controller
diff --git a/sys/arch/beagle/conf/RAMDISK b/sys/arch/beagle/conf/RAMDISK
index 3abc26e2133..a9e7e663545 100644
--- a/sys/arch/beagle/conf/RAMDISK
+++ b/sys/arch/beagle/conf/RAMDISK
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK,v 1.17 2013/05/01 00:16:26 patrick Exp $
+# $OpenBSD: RAMDISK,v 1.18 2013/05/02 19:15:53 patrick Exp $
#
# GENERIC machine description file
#
@@ -65,6 +65,7 @@ omap0 at mainbus?
cortex0 at mainbus?
ampintc* at cortex?
amptimer* at cortex?
+#armliicc* at cortex? # L2 cache controller
# OMAP3 only
intc* at soc? # interrupt controller