diff options
author | Antony Pavlov <antonynpavlov@gmail.com> | 2012-05-22 16:17:00 +0400 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2012-05-23 18:47:53 +0200 |
commit | e41b0717dc6594e8cf063b7023fde814f2ac97b4 (patch) | |
tree | b226ae682ed82ed9ca14d48b51a5d91c74730e0a /arch/mips/lib | |
parent | 6a1e9a7c9b384d80c6977f2a1d5682a4e9e39de1 (diff) | |
download | barebox-e41b0717dc6594e8cf063b7023fde814f2ac97b4.tar.gz barebox-e41b0717dc6594e8cf063b7023fde814f2ac97b4.tar.xz |
MIPS: import CPU and cache detection code from Linux 3.4
Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com>
Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/mips/lib')
-rw-r--r-- | arch/mips/lib/Makefile | 4 | ||||
-rw-r--r-- | arch/mips/lib/c-r4k.c | 97 | ||||
-rw-r--r-- | arch/mips/lib/cpu-probe.c | 143 |
3 files changed, 244 insertions, 0 deletions
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index 85aa19418d..b99bb71837 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -4,6 +4,10 @@ obj-y += lshrdi3.o obj-y += ashldi3.o obj-y += ashrdi3.o obj-y += memory.o +obj-y += cpu-probe.o + +obj-$(CONFIG_CPU_MIPS32) += c-r4k.o +obj-$(CONFIG_CPU_MIPS64) += c-r4k.o obj-$(CONFIG_CMD_MIPS_CPUINFO) += cpuinfo.o obj-$(CONFIG_CMD_BOOTM) += bootm.o diff --git a/arch/mips/lib/c-r4k.c b/arch/mips/lib/c-r4k.c new file mode 100644 index 0000000000..01b8665193 --- /dev/null +++ b/arch/mips/lib/c-r4k.c @@ -0,0 +1,97 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996 David S. Miller (davem@davemloft.net) + * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + */ +#include <common.h> +#include <asm/io.h> +#include <asm/mipsregs.h> +#include <asm/cpu.h> +#include <asm/cpu-info.h> +#include <asm/bitops.h> + +void r4k_cache_init(void); + +static void probe_pcache(void) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + unsigned int icache_size, dcache_size; + unsigned int config = read_c0_config(); + unsigned long config1; + unsigned int lsize; + + switch (c->cputype) { + + default: + /* + * So we seem to be a MIPS32 or MIPS64 CPU + * So let's probe the I-cache ... + */ + config1 = read_c0_config1(); + + if ((lsize = ((config1 >> 19) & 7))) + c->icache.linesz = 2 << lsize; + else + c->icache.linesz = lsize; + c->icache.sets = 64 << ((config1 >> 22) & 7); + c->icache.ways = 1 + ((config1 >> 16) & 7); + + icache_size = c->icache.sets * + c->icache.ways * + c->icache.linesz; + c->icache.waybit = __ffs(icache_size/c->icache.ways); + + if (config & 0x8) /* VI bit */ + c->icache.flags |= MIPS_CACHE_VTAG; + + /* + * Now probe the MIPS32 / MIPS64 data cache. + */ + c->dcache.flags = 0; + + if ((lsize = ((config1 >> 10) & 7))) + c->dcache.linesz = 2 << lsize; + else + c->dcache.linesz= lsize; + c->dcache.sets = 64 << ((config1 >> 13) & 7); + c->dcache.ways = 1 + ((config1 >> 7) & 7); + + dcache_size = c->dcache.sets * + c->dcache.ways * + c->dcache.linesz; + c->dcache.waybit = __ffs(dcache_size/c->dcache.ways); + + c->options |= MIPS_CPU_PREFETCH; + break; + } + + /* compute a couple of other cache variables */ + c->icache.waysize = icache_size / c->icache.ways; + c->dcache.waysize = dcache_size / c->dcache.ways; + + c->icache.sets = c->icache.linesz ? + icache_size / (c->icache.linesz * c->icache.ways) : 0; + c->dcache.sets = c->dcache.linesz ? + dcache_size / (c->dcache.linesz * c->dcache.ways) : 0; + + /* + * R10000 and R12000 P-caches are odd in a positive way. They're 32kB + * 2-way virtually indexed so normally would suffer from aliases. So + * normally they'd suffer from aliases but magic in the hardware deals + * with that for us so we don't need to take care ourselves. + */ + switch (c->cputype) { + default: + if (c->dcache.waysize > PAGE_SIZE) + c->dcache.flags |= MIPS_CACHE_ALIASES; + } +} + +void r4k_cache_init(void) +{ + probe_pcache(); +} diff --git a/arch/mips/lib/cpu-probe.c b/arch/mips/lib/cpu-probe.c new file mode 100644 index 0000000000..de45421df7 --- /dev/null +++ b/arch/mips/lib/cpu-probe.c @@ -0,0 +1,143 @@ +/* + * Processor capabilities determination functions. + * + * Copyright (C) xxxx the Anonymous + * Copyright (C) 1994 - 2006 Ralf Baechle + * Copyright (C) 2003, 2004 Maciej W. Rozycki + * Copyright (C) 2001, 2004 MIPS Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include <common.h> +#include <asm/mipsregs.h> +#include <asm/cpu-info.h> +#include <asm/cpu.h> + +const char *__cpu_name; +struct cpuinfo_mips cpu_data[1]; + +static char unknown_isa[] = KERN_ERR \ + "Unsupported ISA type, c0.config0: %d."; + +static inline unsigned int decode_config0(struct cpuinfo_mips *c) +{ + unsigned int config0; + int isa; + + config0 = read_c0_config(); + + if (((config0 & MIPS_CONF_MT) >> 7) == 1) + c->options |= MIPS_CPU_TLB; + isa = (config0 & MIPS_CONF_AT) >> 13; + switch (isa) { + case 0: + switch ((config0 & MIPS_CONF_AR) >> 10) { + case 0: + c->isa_level = MIPS_CPU_ISA_M32R1; + break; + case 1: + c->isa_level = MIPS_CPU_ISA_M32R2; + break; + default: + goto unknown; + } + break; + case 2: + switch ((config0 & MIPS_CONF_AR) >> 10) { + case 0: + c->isa_level = MIPS_CPU_ISA_M64R1; + break; + case 1: + c->isa_level = MIPS_CPU_ISA_M64R2; + break; + default: + goto unknown; + } + break; + default: + goto unknown; + } + + return config0 & MIPS_CONF_M; + +unknown: + panic(unknown_isa, config0); +} + +static void decode_configs(struct cpuinfo_mips *c) +{ + int ok; + + /* MIPS32 or MIPS64 compliant CPU. */ + c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER | + MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK; + + c->scache.flags = MIPS_CACHE_NOT_PRESENT; + + ok = decode_config0(c); /* Read Config registers. */ + BUG_ON(!ok); /* Arch spec violation! */ +} + +static inline void cpu_probe_mips(struct cpuinfo_mips *c) +{ + decode_configs(c); + switch (c->processor_id & 0xff00) { + case PRID_IMP_24K: + case PRID_IMP_24KE: + c->cputype = CPU_24K; + __cpu_name = "MIPS 24Kc"; + break; + } +} + +static inline void cpu_probe_broadcom(struct cpuinfo_mips *c) +{ + decode_configs(c); + switch (c->processor_id & 0xff00) { + case PRID_IMP_BMIPS3300: + c->cputype = CPU_BMIPS3300; + __cpu_name = "Broadcom BMIPS3300"; + break; + } +} + +static inline void cpu_probe_ingenic(struct cpuinfo_mips *c) +{ + decode_configs(c); + /* JZRISC does not implement the CP0 counter. */ + c->options &= ~MIPS_CPU_COUNTER; + switch (c->processor_id & 0xff00) { + case PRID_IMP_JZRISC: + c->cputype = CPU_JZRISC; + __cpu_name = "Ingenic JZRISC"; + break; + default: + panic("Unknown Ingenic Processor ID!"); + break; + } +} + +void cpu_probe(void) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + + c->processor_id = PRID_IMP_UNKNOWN; + c->fpu_id = FPIR_IMP_NONE; + c->cputype = CPU_UNKNOWN; + + c->processor_id = read_c0_prid(); + switch (c->processor_id & 0xff0000) { + case PRID_COMP_MIPS: + cpu_probe_mips(c); + break; + case PRID_COMP_BROADCOM: + cpu_probe_broadcom(c); + break; + case PRID_COMP_INGENIC: + cpu_probe_ingenic(c); + break; + } +} |