diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2012-06-24 20:29:47 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2012-06-24 20:29:47 +0000 |
commit | 49d690944db033dc6fc96dc5d76af53f1c0cf152 (patch) | |
tree | f46393e4260b7f76fbe32011774c60fae2826ded /sys/arch/sgi | |
parent | de10434ad1afd89bf0b896a3ed7f6f4f1e48aeb0 (diff) |
Code for the external L2 cache controller on Indy/Indigo2 R4600SC and Indy
R5000SC processor modules; these sport an up to 512KB, physically indexed,
write-through L2 cache which is not connected to the canonical external cache
interface of these processors (hence requiring specific code to drive it).
The cache is enabled early and disabled before returning to ARCBios (for very
nasty things happen otherwise).
Tested on R5000SC, will be tested on R4600SC soon.
Diffstat (limited to 'sys/arch/sgi')
-rw-r--r-- | sys/arch/sgi/sgi/ip22.h | 4 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/ip22_machdep.c | 141 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/machdep.c | 12 |
3 files changed, 153 insertions, 4 deletions
diff --git a/sys/arch/sgi/sgi/ip22.h b/sys/arch/sgi/sgi/ip22.h index 974655933bd..150263e0941 100644 --- a/sys/arch/sgi/sgi/ip22.h +++ b/sys/arch/sgi/sgi/ip22.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip22.h,v 1.6 2012/05/27 14:27:10 miod Exp $ */ +/* $OpenBSD: ip22.h,v 1.7 2012/06/24 20:29:46 miod Exp $ */ /* * Copyright (c) 2012 Miodrag Vallat. @@ -39,3 +39,5 @@ extern int ip22_ecc; /* nonzero if runinng with an ECC memory system */ int ip22_fast_mode(void); int ip22_slow_mode(void); int ip22_restore_mode(int); + +void ip22_ConfigCache(struct cpu_info *); diff --git a/sys/arch/sgi/sgi/ip22_machdep.c b/sys/arch/sgi/sgi/ip22_machdep.c index 5b0d227668a..3f4a63bc142 100644 --- a/sys/arch/sgi/sgi/ip22_machdep.c +++ b/sys/arch/sgi/sgi/ip22_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip22_machdep.c,v 1.11 2012/05/27 19:13:04 miod Exp $ */ +/* $OpenBSD: ip22_machdep.c,v 1.12 2012/06/24 20:29:46 miod Exp $ */ /* * Copyright (c) 2012 Miodrag Vallat. @@ -56,6 +56,7 @@ int ip22_ecc = 0; void ip22_arcbios_walk(void); int ip22_arcbios_walk_component(arc_config_t *); +void ip22_cache_halt(int); void ip22_ecc_halt(int); void ip22_ecc_init(void); void ip22_memory_setup(void); @@ -662,3 +663,141 @@ ip22_ecc_halt(int howto) ip22_slow_mode(); arcbios_halt(howto); } + +#if (defined(TGT_INDY) || defined(TGT_INDIGO2)) && \ + (defined(CPU_R4600) || defined(CPU_R5000)) + +/* + * Cache routines for the secondary cache found on R4600SC and R5000SC + * systems. + */ + +#include <mips64/cache.h> +CACHE_PROTOS(ip22) + +#define IP22_L2_LINE 32UL +#define IP22_CACHE_TAG_ADDRESS 0x80000000UL + +static inline void ip22_l2_disable(void) +{ + /* halfword write: disable entire cache */ + *(volatile uint16_t *)(PHYS_TO_XKPHYS(IP22_CACHE_TAG_ADDRESS, CCA_NC)) = + 0; +} +static inline void ip22_l2_enable(void) +{ + /* byte write: enable entire cache */ + *(volatile uint8_t *)(PHYS_TO_XKPHYS(IP22_CACHE_TAG_ADDRESS, CCA_NC)) = + 0; +} + +void +ip22_cache_halt(int howto) +{ + ip22_l2_disable(); + arcbios_halt(howto); +} + +void +ip22_ConfigCache(struct cpu_info *ci) +{ + uint l2line, l2size; + + /* + * Note that we are relying upon machdep.c only invoking us if we + * are running on an R4600 or R5000 system. + */ + if ((ip22_arcwalk_results & IP22_HAS_L2) == 0) { + Mips5k_ConfigCache(ci); + return; + } + + l2line = ci->ci_l2line; + l2size = ci->ci_l2size; + + Mips5k_ConfigCache(ci); + + if (l2line != IP22_L2_LINE) { + /* + * This should not happen. Better not try and tame an + * unknown beast. + */ + return; + } + + ci->ci_l2line = l2line; + ci->ci_l2size = l2size; + + ci->ci_SyncCache = ip22_SyncCache; + ci->ci_IOSyncDCache = ip22_IOSyncDCache; + + md_halt = ip22_cache_halt; + ip22_l2_enable(); +} + +void +ip22_SyncCache(struct cpu_info *ci) +{ + vaddr_t sva, eva; + + Mips5k_SyncCache(ci); + + sva = PHYS_TO_XKPHYS(IP22_CACHE_TAG_ADDRESS, CCA_NC); + eva = sva + ci->ci_l2size; + + while (sva < eva) { + *(volatile uint32_t *)sva = 0; + sva += IP22_L2_LINE; + } +} + +void +ip22_IOSyncDCache(struct cpu_info *ci, vaddr_t _va, size_t _sz, int how) +{ + vaddr_t va; + size_t sz; + paddr_t pa; + + /* do whatever L1 work is necessary */ + Mips5k_IOSyncDCache(ci, _va, _sz, how); + + switch (how) { + default: + case CACHE_SYNC_W: + break; + case CACHE_SYNC_X: + case CACHE_SYNC_R: + /* extend the range to integral cache lines */ + va = _va & ~(IP22_L2_LINE - 1); + sz = ((_va + _sz + IP22_L2_LINE - 1) & ~(IP22_L2_LINE - 1)) - + va; + + while (sz != 0) { + /* get the proper physical address */ + if (pmap_extract(pmap_kernel(), va, &pa) == 0) { +#ifdef DIAGNOSTIC + panic("%s: invalid va %p", __func__, va); +#else + /* should not happen */ +#endif + } + + pa &= ci->ci_l2size - 1; + pa |= PHYS_TO_XKPHYS(IP22_CACHE_TAG_ADDRESS, CCA_NC); + + while (sz != 0) { + /* word write: invalidate line */ + *(volatile uint32_t *)pa = 0; + + pa += IP22_L2_LINE; + va += IP22_L2_LINE; + sz -= IP22_L2_LINE; + if ((va & PAGE_MASK) == 0) + break; /* need pmap_extract() */ + } + } + break; + } +} + +#endif diff --git a/sys/arch/sgi/sgi/machdep.c b/sys/arch/sgi/sgi/machdep.c index 0fbb2daaaf8..e66256e152e 100644 --- a/sys/arch/sgi/sgi/machdep.c +++ b/sys/arch/sgi/sgi/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.126 2012/06/24 16:26:04 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.127 2012/06/24 20:29:46 miod Exp $ */ /* * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -62,6 +62,9 @@ #ifdef TGT_ORIGIN #include <machine/mnode.h> #endif +#if defined(TGT_INDY) || defined(TGT_INDIGO2) +CACHE_PROTOS(ip22) +#endif #ifdef CPU_RM7000 #include <mips64/rm7000.h> @@ -450,7 +453,12 @@ mips_init(int argc, void *argv, caddr_t boot_esym) #endif #if defined(CPU_R4600) || defined(CPU_R5000) || defined(CPU_RM7000) case MIPS_R5000: - Mips5k_ConfigCache(ci); +#if defined(TGT_INDY) || defined(TGT_INDIGO2) + if (sys_config.system_type == SGI_IP22) + ip22_ConfigCache(ci); + else +#endif + Mips5k_ConfigCache(ci); break; #endif #ifdef CPU_R10000 |