cpu-r3k-probe.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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. #include <asm/bugs.h>
  17. #include <asm/cpu.h>
  18. #include <asm/cpu-features.h>
  19. #include <asm/cpu-type.h>
  20. #include <asm/fpu.h>
  21. #include <asm/mipsregs.h>
  22. #include <asm/elf.h>
  23. #include <asm/traps.h>
  24. #include "fpu-probe.h"
  25. /* Hardware capabilities */
  26. unsigned int elf_hwcap __read_mostly;
  27. EXPORT_SYMBOL_GPL(elf_hwcap);
  28. void __init check_bugs32(void)
  29. {
  30. }
  31. /*
  32. * Probe whether cpu has config register by trying to play with
  33. * alternate cache bit and see whether it matters.
  34. * It's used by cpu_probe to distinguish between R3000A and R3081.
  35. */
  36. static inline int cpu_has_confreg(void)
  37. {
  38. #ifdef CONFIG_CPU_R3000
  39. extern unsigned long r3k_cache_size(unsigned long);
  40. unsigned long size1, size2;
  41. unsigned long cfg = read_c0_conf();
  42. size1 = r3k_cache_size(ST0_ISC);
  43. write_c0_conf(cfg ^ R30XX_CONF_AC);
  44. size2 = r3k_cache_size(ST0_ISC);
  45. write_c0_conf(cfg);
  46. return size1 != size2;
  47. #else
  48. return 0;
  49. #endif
  50. }
  51. static inline void set_elf_platform(int cpu, const char *plat)
  52. {
  53. if (cpu == 0)
  54. __elf_platform = plat;
  55. }
  56. const char *__cpu_name[NR_CPUS];
  57. const char *__elf_platform;
  58. const char *__elf_base_platform;
  59. void cpu_probe(void)
  60. {
  61. struct cpuinfo_mips *c = &current_cpu_data;
  62. unsigned int cpu = smp_processor_id();
  63. /*
  64. * Set a default elf platform, cpu probe may later
  65. * overwrite it with a more precise value
  66. */
  67. set_elf_platform(cpu, "mips");
  68. c->processor_id = PRID_IMP_UNKNOWN;
  69. c->fpu_id = FPIR_IMP_NONE;
  70. c->cputype = CPU_UNKNOWN;
  71. c->writecombine = _CACHE_UNCACHED;
  72. c->fpu_csr31 = FPU_CSR_RN;
  73. c->fpu_msk31 = FPU_CSR_RSVD | FPU_CSR_ABS2008 | FPU_CSR_NAN2008 |
  74. FPU_CSR_CONDX | FPU_CSR_FS;
  75. c->srsets = 1;
  76. c->processor_id = read_c0_prid();
  77. switch (c->processor_id & (PRID_COMP_MASK | PRID_IMP_MASK)) {
  78. case PRID_COMP_LEGACY | PRID_IMP_R2000:
  79. c->cputype = CPU_R2000;
  80. __cpu_name[cpu] = "R2000";
  81. c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
  82. MIPS_CPU_NOFPUEX;
  83. if (__cpu_has_fpu())
  84. c->options |= MIPS_CPU_FPU;
  85. c->tlbsize = 64;
  86. break;
  87. case PRID_COMP_LEGACY | PRID_IMP_R3000:
  88. if ((c->processor_id & PRID_REV_MASK) == PRID_REV_R3000A) {
  89. if (cpu_has_confreg()) {
  90. c->cputype = CPU_R3081E;
  91. __cpu_name[cpu] = "R3081";
  92. } else {
  93. c->cputype = CPU_R3000A;
  94. __cpu_name[cpu] = "R3000A";
  95. }
  96. } else {
  97. c->cputype = CPU_R3000;
  98. __cpu_name[cpu] = "R3000";
  99. }
  100. c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
  101. MIPS_CPU_NOFPUEX;
  102. if (__cpu_has_fpu())
  103. c->options |= MIPS_CPU_FPU;
  104. c->tlbsize = 64;
  105. break;
  106. }
  107. BUG_ON(!__cpu_name[cpu]);
  108. BUG_ON(c->cputype == CPU_UNKNOWN);
  109. /*
  110. * Platform code can force the cpu type to optimize code
  111. * generation. In that case be sure the cpu type is correctly
  112. * manually setup otherwise it could trigger some nasty bugs.
  113. */
  114. BUG_ON(current_cpu_type() != c->cputype);
  115. if (mips_fpu_disabled)
  116. c->options &= ~MIPS_CPU_FPU;
  117. if (c->options & MIPS_CPU_FPU)
  118. cpu_set_fpu_opts(c);
  119. else
  120. cpu_set_nofpu_opts(c);
  121. reserve_exception_space(0, 0x400);
  122. }
  123. void cpu_report(void)
  124. {
  125. struct cpuinfo_mips *c = &current_cpu_data;
  126. pr_info("CPU%d revision is: %08x (%s)\n",
  127. smp_processor_id(), c->processor_id, cpu_name_string());
  128. if (c->options & MIPS_CPU_FPU)
  129. pr_info("FPU revision is: %08x\n", c->fpu_id);
  130. }