diff options
author | 2013-05-02 19:15:53 +0000 | |
---|---|---|
committer | 2013-05-02 19:15:53 +0000 | |
commit | d1433e4ad9bae9aa02aef97743bfd6ee09c39f96 (patch) | |
tree | e7fed2a8957b1d776f57b3d5a5af496109233d08 | |
parent | typos (diff) | |
download | wireguard-openbsd-d1433e4ad9bae9aa02aef97743bfd6ee09c39f96.tar.xz wireguard-openbsd-d1433e4ad9bae9aa02aef97743bfd6ee09c39f96.zip |
Add a driver for the secondary cache controller on the PandaBoard and
other ARM Cortex based boards. Disabled for now, until proper
secondary cache flushing is done where it's needed.
ok miod@
-rw-r--r-- | sys/arch/arm/cortex/arml2cc.c | 297 | ||||
-rw-r--r-- | sys/arch/arm/cortex/files.cortex | 6 | ||||
-rw-r--r-- | sys/arch/beagle/conf/GENERIC | 3 | ||||
-rw-r--r-- | sys/arch/beagle/conf/RAMDISK | 3 |
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 |