Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Processor capabilities determination functions.
  4 *
  5 * Copyright (C) xxxx  the Anonymous
  6 * Copyright (C) 1994 - 2006 Ralf Baechle
  7 * Copyright (C) 2003, 2004  Maciej W. Rozycki
  8 * Copyright (C) 2001, 2004, 2011, 2012	 MIPS Technologies, Inc.
  9 */
 10#include <linux/init.h>
 11#include <linux/kernel.h>
 12#include <linux/ptrace.h>
 13#include <linux/smp.h>
 14#include <linux/stddef.h>
 15#include <linux/export.h>
 16
 17#include <asm/bugs.h>
 18#include <asm/cpu.h>
 19#include <asm/cpu-features.h>
 20#include <asm/cpu-type.h>
 21#include <asm/fpu.h>
 22#include <asm/mipsregs.h>
 23#include <asm/elf.h>
 24#include <asm/traps.h>
 25
 26#include "fpu-probe.h"
 27
 28/* Hardware capabilities */
 29unsigned int elf_hwcap __read_mostly;
 30EXPORT_SYMBOL_GPL(elf_hwcap);
 31
 32void __init check_bugs32(void)
 33{
 34
 35}
 36
 37/*
 38 * Probe whether cpu has config register by trying to play with
 39 * alternate cache bit and see whether it matters.
 40 * It's used by cpu_probe to distinguish between R3000A and R3081.
 41 */
 42static inline int cpu_has_confreg(void)
 43{
 44#ifdef CONFIG_CPU_R3000
 45	extern unsigned long r3k_cache_size(unsigned long);
 46	unsigned long size1, size2;
 47	unsigned long cfg = read_c0_conf();
 48
 49	size1 = r3k_cache_size(ST0_ISC);
 50	write_c0_conf(cfg ^ R30XX_CONF_AC);
 51	size2 = r3k_cache_size(ST0_ISC);
 52	write_c0_conf(cfg);
 53	return size1 != size2;
 54#else
 55	return 0;
 56#endif
 57}
 58
 59static inline void set_elf_platform(int cpu, const char *plat)
 60{
 61	if (cpu == 0)
 62		__elf_platform = plat;
 63}
 64
 65const char *__cpu_name[NR_CPUS];
 66const char *__elf_platform;
 67const char *__elf_base_platform;
 68
 69void cpu_probe(void)
 70{
 71	struct cpuinfo_mips *c = &current_cpu_data;
 72	unsigned int cpu = smp_processor_id();
 73
 74	/*
 75	 * Set a default elf platform, cpu probe may later
 76	 * overwrite it with a more precise value
 77	 */
 78	set_elf_platform(cpu, "mips");
 79
 80	c->processor_id = PRID_IMP_UNKNOWN;
 81	c->fpu_id	= FPIR_IMP_NONE;
 82	c->cputype	= CPU_UNKNOWN;
 83	c->writecombine = _CACHE_UNCACHED;
 84
 85	c->fpu_csr31	= FPU_CSR_RN;
 86	c->fpu_msk31	= FPU_CSR_RSVD | FPU_CSR_ABS2008 | FPU_CSR_NAN2008 |
 87			  FPU_CSR_CONDX | FPU_CSR_FS;
 88
 89	c->srsets = 1;
 90
 91	c->processor_id = read_c0_prid();
 92	switch (c->processor_id & (PRID_COMP_MASK | PRID_IMP_MASK)) {
 93	case PRID_COMP_LEGACY | PRID_IMP_R2000:
 94		c->cputype = CPU_R2000;
 95		__cpu_name[cpu] = "R2000";
 96		c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
 97			     MIPS_CPU_NOFPUEX;
 98		if (__cpu_has_fpu())
 99			c->options |= MIPS_CPU_FPU;
100		c->tlbsize = 64;
101		break;
102	case PRID_COMP_LEGACY | PRID_IMP_R3000:
103		if ((c->processor_id & PRID_REV_MASK) == PRID_REV_R3000A) {
104			if (cpu_has_confreg()) {
105				c->cputype = CPU_R3081E;
106				__cpu_name[cpu] = "R3081";
107			} else {
108				c->cputype = CPU_R3000A;
109				__cpu_name[cpu] = "R3000A";
110			}
111		} else {
112			c->cputype = CPU_R3000;
113			__cpu_name[cpu] = "R3000";
114		}
115		c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
116			     MIPS_CPU_NOFPUEX;
117		if (__cpu_has_fpu())
118			c->options |= MIPS_CPU_FPU;
119		c->tlbsize = 64;
120		break;
121	}
122
123	BUG_ON(!__cpu_name[cpu]);
124	BUG_ON(c->cputype == CPU_UNKNOWN);
125
126	/*
127	 * Platform code can force the cpu type to optimize code
128	 * generation. In that case be sure the cpu type is correctly
129	 * manually setup otherwise it could trigger some nasty bugs.
130	 */
131	BUG_ON(current_cpu_type() != c->cputype);
132
133	if (mips_fpu_disabled)
134		c->options &= ~MIPS_CPU_FPU;
135
136	if (c->options & MIPS_CPU_FPU)
137		cpu_set_fpu_opts(c);
138	else
139		cpu_set_nofpu_opts(c);
140
141	reserve_exception_space(0, 0x400);
142}
143
144void cpu_report(void)
145{
146	struct cpuinfo_mips *c = &current_cpu_data;
147
148	pr_info("CPU%d revision is: %08x (%s)\n",
149		smp_processor_id(), c->processor_id, cpu_name_string());
150	if (c->options & MIPS_CPU_FPU)
151		pr_info("FPU revision is: %08x\n", c->fpu_id);
152}