blob: 55d7b7fd18b6fba66ef1d2c4b9d46e637fbc3cf3 [file] [log] [blame]
Ralf Baechle54176732005-02-07 02:54:29 +00001/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
Ralf Baechle937a8012006-10-07 19:44:33 +01006 * Copyright (C) 2004, 05, 06 by Ralf Baechle
Ralf Baechle54176732005-02-07 02:54:29 +00007 * Copyright (C) 2005 by MIPS Technologies, Inc.
8 */
Ralf Baechle5e2862e2007-12-06 09:12:28 +00009#include <linux/cpumask.h>
Ralf Baechle54176732005-02-07 02:54:29 +000010#include <linux/oprofile.h>
11#include <linux/interrupt.h>
12#include <linux/smp.h>
Ralf Baechle937a8012006-10-07 19:44:33 +010013#include <asm/irq_regs.h>
Andrew Brestickera669efc2014-09-18 14:47:12 -070014#include <asm/time.h>
Ralf Baechle54176732005-02-07 02:54:29 +000015
16#include "op_impl.h"
17
James Hogan26542942017-02-06 12:37:45 +000018#define M_PERFCTL_EVENT(event) (((event) << MIPS_PERFCTRL_EVENT_S) & \
19 MIPS_PERFCTRL_EVENT)
20#define M_PERFCTL_VPEID(vpe) ((vpe) << MIPS_PERFCTRL_VPEID_S)
Ralf Baechle54176732005-02-07 02:54:29 +000021
Ralf Baechle70342282013-01-22 12:59:30 +010022#define M_COUNTER_OVERFLOW (1UL << 31)
Ralf Baechle92c7b622006-06-23 18:39:00 +010023
Dmitri Vorobiev46684732008-04-02 03:58:38 +040024static int (*save_perf_irq)(void);
Andrew Brestickera669efc2014-09-18 14:47:12 -070025static int perfcount_irq;
Dmitri Vorobiev46684732008-04-02 03:58:38 +040026
Madhusudan Bhatc7833902012-10-31 12:01:27 +000027/*
28 * XLR has only one set of counters per core. Designate the
29 * first hardware thread in the core for setup and init.
30 * Skip CPUs with non-zero hardware thread id (4 hwt per core)
31 */
Jayachandran C83a18412013-03-25 06:51:52 +000032#if defined(CONFIG_CPU_XLR) && defined(CONFIG_SMP)
Madhusudan Bhatc7833902012-10-31 12:01:27 +000033#define oprofile_skip_cpu(c) ((cpu_logical_map(c) & 0x3) != 0)
34#else
35#define oprofile_skip_cpu(c) 0
36#endif
37
Ralf Baechle92c7b622006-06-23 18:39:00 +010038#ifdef CONFIG_MIPS_MT_SMP
James Hogan26542942017-02-06 12:37:45 +000039#define WHAT (MIPS_PERFCTRL_MT_EN_VPE | \
Paul Burtonf875a8322017-08-12 19:49:35 -070040 M_PERFCTL_VPEID(cpu_vpe_id(&current_cpu_data)))
Ralf Baechle39b8d522008-04-28 17:14:26 +010041#define vpe_id() (cpu_has_mipsmt_pertccounters ? \
Paul Burtonf875a8322017-08-12 19:49:35 -070042 0 : cpu_vpe_id(&current_cpu_data))
Ralf Baechle5e2862e2007-12-06 09:12:28 +000043
44/*
45 * The number of bits to shift to convert between counters per core and
46 * counters per VPE. There is no reasonable interface atm to obtain the
47 * number of VPEs used by Linux and in the 34K this number is fixed to two
48 * anyways so we hardcore a few things here for the moment. The way it's
49 * done here will ensure that oprofile VSMP kernel will run right on a lesser
50 * core like a 24K also or with maxcpus=1.
51 */
52static inline unsigned int vpe_shift(void)
53{
54 if (num_possible_cpus() > 1)
55 return 1;
56
57 return 0;
58}
59
Ralf Baechle92c7b622006-06-23 18:39:00 +010060#else
Ralf Baechle5e2862e2007-12-06 09:12:28 +000061
Ralf Baechlebe609f32006-10-23 13:22:06 +010062#define WHAT 0
Ralf Baechle6f4c5bd2007-04-24 21:42:20 +010063#define vpe_id() 0
Ralf Baechle5e2862e2007-12-06 09:12:28 +000064
65static inline unsigned int vpe_shift(void)
66{
67 return 0;
68}
69
Ralf Baechle92c7b622006-06-23 18:39:00 +010070#endif
71
Ralf Baechle5e2862e2007-12-06 09:12:28 +000072static inline unsigned int counters_total_to_per_cpu(unsigned int counters)
73{
74 return counters >> vpe_shift();
75}
76
77static inline unsigned int counters_per_cpu_to_total(unsigned int counters)
78{
79 return counters << vpe_shift();
80}
81
Ralf Baechle92c7b622006-06-23 18:39:00 +010082#define __define_perf_accessors(r, n, np) \
83 \
84static inline unsigned int r_c0_ ## r ## n(void) \
85{ \
Ralf Baechlebe609f32006-10-23 13:22:06 +010086 unsigned int cpu = vpe_id(); \
Ralf Baechle92c7b622006-06-23 18:39:00 +010087 \
88 switch (cpu) { \
89 case 0: \
90 return read_c0_ ## r ## n(); \
91 case 1: \
92 return read_c0_ ## r ## np(); \
93 default: \
94 BUG(); \
95 } \
Thiemo Seufer30f244a2006-07-07 10:38:51 +010096 return 0; \
Ralf Baechle92c7b622006-06-23 18:39:00 +010097} \
98 \
99static inline void w_c0_ ## r ## n(unsigned int value) \
100{ \
Ralf Baechlebe609f32006-10-23 13:22:06 +0100101 unsigned int cpu = vpe_id(); \
Ralf Baechle92c7b622006-06-23 18:39:00 +0100102 \
103 switch (cpu) { \
104 case 0: \
105 write_c0_ ## r ## n(value); \
106 return; \
107 case 1: \
108 write_c0_ ## r ## np(value); \
109 return; \
110 default: \
111 BUG(); \
112 } \
Thiemo Seufer30f244a2006-07-07 10:38:51 +0100113 return; \
Ralf Baechle92c7b622006-06-23 18:39:00 +0100114} \
115
116__define_perf_accessors(perfcntr, 0, 2)
117__define_perf_accessors(perfcntr, 1, 3)
Chris Dearman795a2252007-03-01 17:58:24 +0000118__define_perf_accessors(perfcntr, 2, 0)
119__define_perf_accessors(perfcntr, 3, 1)
Ralf Baechle92c7b622006-06-23 18:39:00 +0100120
121__define_perf_accessors(perfctrl, 0, 2)
122__define_perf_accessors(perfctrl, 1, 3)
Chris Dearman795a2252007-03-01 17:58:24 +0000123__define_perf_accessors(perfctrl, 2, 0)
124__define_perf_accessors(perfctrl, 3, 1)
Ralf Baechle54176732005-02-07 02:54:29 +0000125
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900126struct op_mips_model op_model_mipsxx_ops;
Ralf Baechle54176732005-02-07 02:54:29 +0000127
128static struct mipsxx_register_config {
129 unsigned int control[4];
130 unsigned int counter[4];
131} reg;
132
Ralf Baechle70342282013-01-22 12:59:30 +0100133/* Compute all of the registers in preparation for enabling profiling. */
Ralf Baechle54176732005-02-07 02:54:29 +0000134
135static void mipsxx_reg_setup(struct op_counter_config *ctr)
136{
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900137 unsigned int counters = op_model_mipsxx_ops.num_counters;
Ralf Baechle54176732005-02-07 02:54:29 +0000138 int i;
139
140 /* Compute the performance counter control word. */
Ralf Baechle54176732005-02-07 02:54:29 +0000141 for (i = 0; i < counters; i++) {
142 reg.control[i] = 0;
143 reg.counter[i] = 0;
144
145 if (!ctr[i].enabled)
146 continue;
147
148 reg.control[i] = M_PERFCTL_EVENT(ctr[i].event) |
James Hogan26542942017-02-06 12:37:45 +0000149 MIPS_PERFCTRL_IE;
Ralf Baechle54176732005-02-07 02:54:29 +0000150 if (ctr[i].kernel)
James Hogan26542942017-02-06 12:37:45 +0000151 reg.control[i] |= MIPS_PERFCTRL_K;
Ralf Baechle54176732005-02-07 02:54:29 +0000152 if (ctr[i].user)
James Hogan26542942017-02-06 12:37:45 +0000153 reg.control[i] |= MIPS_PERFCTRL_U;
Ralf Baechle54176732005-02-07 02:54:29 +0000154 if (ctr[i].exl)
James Hogan26542942017-02-06 12:37:45 +0000155 reg.control[i] |= MIPS_PERFCTRL_EXL;
Ralf Baechlecf5b2d232013-08-01 18:31:05 +0200156 if (boot_cpu_type() == CPU_XLR)
James Hogan26542942017-02-06 12:37:45 +0000157 reg.control[i] |= XLR_PERFCTRL_ALLTHREADS;
Ralf Baechle54176732005-02-07 02:54:29 +0000158 reg.counter[i] = 0x80000000 - ctr[i].count;
159 }
160}
161
Ralf Baechle70342282013-01-22 12:59:30 +0100162/* Program all of the registers in preparation for enabling profiling. */
Ralf Baechle54176732005-02-07 02:54:29 +0000163
Ralf Baechle49a89ef2007-10-11 23:46:15 +0100164static void mipsxx_cpu_setup(void *args)
Ralf Baechle54176732005-02-07 02:54:29 +0000165{
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900166 unsigned int counters = op_model_mipsxx_ops.num_counters;
Ralf Baechle54176732005-02-07 02:54:29 +0000167
Madhusudan Bhatc7833902012-10-31 12:01:27 +0000168 if (oprofile_skip_cpu(smp_processor_id()))
169 return;
170
Ralf Baechle54176732005-02-07 02:54:29 +0000171 switch (counters) {
172 case 4:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100173 w_c0_perfctrl3(0);
174 w_c0_perfcntr3(reg.counter[3]);
Liangliang Huangc9b02992020-05-04 16:51:29 +0800175 fallthrough;
Ralf Baechle54176732005-02-07 02:54:29 +0000176 case 3:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100177 w_c0_perfctrl2(0);
178 w_c0_perfcntr2(reg.counter[2]);
Liangliang Huangc9b02992020-05-04 16:51:29 +0800179 fallthrough;
Ralf Baechle54176732005-02-07 02:54:29 +0000180 case 2:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100181 w_c0_perfctrl1(0);
182 w_c0_perfcntr1(reg.counter[1]);
Liangliang Huangc9b02992020-05-04 16:51:29 +0800183 fallthrough;
Ralf Baechle54176732005-02-07 02:54:29 +0000184 case 1:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100185 w_c0_perfctrl0(0);
186 w_c0_perfcntr0(reg.counter[0]);
Ralf Baechle54176732005-02-07 02:54:29 +0000187 }
188}
189
190/* Start all counters on current CPU */
191static void mipsxx_cpu_start(void *args)
192{
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900193 unsigned int counters = op_model_mipsxx_ops.num_counters;
Ralf Baechle54176732005-02-07 02:54:29 +0000194
Madhusudan Bhatc7833902012-10-31 12:01:27 +0000195 if (oprofile_skip_cpu(smp_processor_id()))
196 return;
197
Ralf Baechle54176732005-02-07 02:54:29 +0000198 switch (counters) {
199 case 4:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100200 w_c0_perfctrl3(WHAT | reg.control[3]);
Liangliang Huangc9b02992020-05-04 16:51:29 +0800201 fallthrough;
Ralf Baechle54176732005-02-07 02:54:29 +0000202 case 3:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100203 w_c0_perfctrl2(WHAT | reg.control[2]);
Liangliang Huangc9b02992020-05-04 16:51:29 +0800204 fallthrough;
Ralf Baechle54176732005-02-07 02:54:29 +0000205 case 2:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100206 w_c0_perfctrl1(WHAT | reg.control[1]);
Liangliang Huangc9b02992020-05-04 16:51:29 +0800207 fallthrough;
Ralf Baechle54176732005-02-07 02:54:29 +0000208 case 1:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100209 w_c0_perfctrl0(WHAT | reg.control[0]);
Ralf Baechle54176732005-02-07 02:54:29 +0000210 }
211}
212
213/* Stop all counters on current CPU */
214static void mipsxx_cpu_stop(void *args)
215{
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900216 unsigned int counters = op_model_mipsxx_ops.num_counters;
Ralf Baechle54176732005-02-07 02:54:29 +0000217
Madhusudan Bhatc7833902012-10-31 12:01:27 +0000218 if (oprofile_skip_cpu(smp_processor_id()))
219 return;
220
Ralf Baechle54176732005-02-07 02:54:29 +0000221 switch (counters) {
222 case 4:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100223 w_c0_perfctrl3(0);
Liangliang Huangc9b02992020-05-04 16:51:29 +0800224 fallthrough;
Ralf Baechle54176732005-02-07 02:54:29 +0000225 case 3:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100226 w_c0_perfctrl2(0);
Liangliang Huangc9b02992020-05-04 16:51:29 +0800227 fallthrough;
Ralf Baechle54176732005-02-07 02:54:29 +0000228 case 2:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100229 w_c0_perfctrl1(0);
Liangliang Huangc9b02992020-05-04 16:51:29 +0800230 fallthrough;
Ralf Baechle54176732005-02-07 02:54:29 +0000231 case 1:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100232 w_c0_perfctrl0(0);
Ralf Baechle54176732005-02-07 02:54:29 +0000233 }
234}
235
Ralf Baechle937a8012006-10-07 19:44:33 +0100236static int mipsxx_perfcount_handler(void)
Ralf Baechle54176732005-02-07 02:54:29 +0000237{
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900238 unsigned int counters = op_model_mipsxx_ops.num_counters;
Ralf Baechle54176732005-02-07 02:54:29 +0000239 unsigned int control;
240 unsigned int counter;
Chris Dearmanffe9ee42007-05-24 22:24:20 +0100241 int handled = IRQ_NONE;
242
James Hogan3ba50402015-01-27 21:45:48 +0000243 if (cpu_has_mips_r2 && !(read_c0_cause() & CAUSEF_PCI))
Chris Dearmanffe9ee42007-05-24 22:24:20 +0100244 return handled;
Ralf Baechle54176732005-02-07 02:54:29 +0000245
246 switch (counters) {
247#define HANDLE_COUNTER(n) \
248 case n + 1: \
Ralf Baechle92c7b622006-06-23 18:39:00 +0100249 control = r_c0_perfctrl ## n(); \
250 counter = r_c0_perfcntr ## n(); \
James Hogan26542942017-02-06 12:37:45 +0000251 if ((control & MIPS_PERFCTRL_IE) && \
Ralf Baechle54176732005-02-07 02:54:29 +0000252 (counter & M_COUNTER_OVERFLOW)) { \
Ralf Baechle937a8012006-10-07 19:44:33 +0100253 oprofile_add_sample(get_irq_regs(), n); \
Ralf Baechle92c7b622006-06-23 18:39:00 +0100254 w_c0_perfcntr ## n(reg.counter[n]); \
Chris Dearmanffe9ee42007-05-24 22:24:20 +0100255 handled = IRQ_HANDLED; \
Ralf Baechle54176732005-02-07 02:54:29 +0000256 }
257 HANDLE_COUNTER(3)
He Zhe91dbd732020-08-20 20:54:40 +0800258 fallthrough;
Ralf Baechle54176732005-02-07 02:54:29 +0000259 HANDLE_COUNTER(2)
He Zhe91dbd732020-08-20 20:54:40 +0800260 fallthrough;
Ralf Baechle54176732005-02-07 02:54:29 +0000261 HANDLE_COUNTER(1)
He Zhe91dbd732020-08-20 20:54:40 +0800262 fallthrough;
Ralf Baechle54176732005-02-07 02:54:29 +0000263 HANDLE_COUNTER(0)
264 }
Ralf Baechleba339c02005-12-09 12:29:38 +0000265
266 return handled;
Ralf Baechle54176732005-02-07 02:54:29 +0000267}
268
Ralf Baechle92c7b622006-06-23 18:39:00 +0100269static inline int __n_counters(void)
Ralf Baechle54176732005-02-07 02:54:29 +0000270{
James Hogan30228c42016-05-11 13:50:53 +0100271 if (!cpu_has_perf)
Ralf Baechle54176732005-02-07 02:54:29 +0000272 return 0;
James Hogan26542942017-02-06 12:37:45 +0000273 if (!(read_c0_perfctrl0() & MIPS_PERFCTRL_M))
Ralf Baechle54176732005-02-07 02:54:29 +0000274 return 1;
James Hogan26542942017-02-06 12:37:45 +0000275 if (!(read_c0_perfctrl1() & MIPS_PERFCTRL_M))
Ralf Baechle54176732005-02-07 02:54:29 +0000276 return 2;
James Hogan26542942017-02-06 12:37:45 +0000277 if (!(read_c0_perfctrl2() & MIPS_PERFCTRL_M))
Ralf Baechle54176732005-02-07 02:54:29 +0000278 return 3;
279
280 return 4;
281}
282
Ralf Baechle92c7b622006-06-23 18:39:00 +0100283static inline int n_counters(void)
284{
Ralf Baechle714cfe72006-10-23 00:44:02 +0100285 int counters;
286
Ralf Baechle10cc3522007-10-11 23:46:15 +0100287 switch (current_cpu_type()) {
Ralf Baechle714cfe72006-10-23 00:44:02 +0100288 case CPU_R10000:
289 counters = 2;
Ralf Baechle148171b2007-02-28 15:34:22 +0000290 break;
Ralf Baechle714cfe72006-10-23 00:44:02 +0100291
292 case CPU_R12000:
293 case CPU_R14000:
Joshua Kinard30577392015-01-21 07:59:45 -0500294 case CPU_R16000:
Ralf Baechle714cfe72006-10-23 00:44:02 +0100295 counters = 4;
Ralf Baechle148171b2007-02-28 15:34:22 +0000296 break;
Ralf Baechle714cfe72006-10-23 00:44:02 +0100297
298 default:
299 counters = __n_counters();
300 }
Ralf Baechle92c7b622006-06-23 18:39:00 +0100301
Ralf Baechle92c7b622006-06-23 18:39:00 +0100302 return counters;
303}
304
Ralf Baechle39b8d522008-04-28 17:14:26 +0100305static void reset_counters(void *arg)
Ralf Baechle54176732005-02-07 02:54:29 +0000306{
Thiemo Seufer005ca9a2008-05-06 11:23:33 +0100307 int counters = (int)(long)arg;
Ralf Baechle54176732005-02-07 02:54:29 +0000308 switch (counters) {
309 case 4:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100310 w_c0_perfctrl3(0);
311 w_c0_perfcntr3(0);
Liangliang Huangc9b02992020-05-04 16:51:29 +0800312 fallthrough;
Ralf Baechle54176732005-02-07 02:54:29 +0000313 case 3:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100314 w_c0_perfctrl2(0);
315 w_c0_perfcntr2(0);
Liangliang Huangc9b02992020-05-04 16:51:29 +0800316 fallthrough;
Ralf Baechle54176732005-02-07 02:54:29 +0000317 case 2:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100318 w_c0_perfctrl1(0);
319 w_c0_perfcntr1(0);
Liangliang Huangc9b02992020-05-04 16:51:29 +0800320 fallthrough;
Ralf Baechle54176732005-02-07 02:54:29 +0000321 case 1:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100322 w_c0_perfctrl0(0);
323 w_c0_perfcntr0(0);
Ralf Baechle54176732005-02-07 02:54:29 +0000324 }
325}
326
Felix Fietkau3572a2c2012-05-02 17:33:04 +0200327static irqreturn_t mipsxx_perfcount_int(int irq, void *dev_id)
328{
329 return mipsxx_perfcount_handler();
330}
331
Ralf Baechle54176732005-02-07 02:54:29 +0000332static int __init mipsxx_init(void)
333{
334 int counters;
335
336 counters = n_counters();
Ralf Baechle9efeae92005-12-09 12:34:45 +0000337 if (counters == 0) {
338 printk(KERN_ERR "Oprofile: CPU has no performance counters\n");
Ralf Baechle54176732005-02-07 02:54:29 +0000339 return -ENODEV;
Ralf Baechle9efeae92005-12-09 12:34:45 +0000340 }
Ralf Baechle54176732005-02-07 02:54:29 +0000341
Ralf Baechle39b8d522008-04-28 17:14:26 +0100342#ifdef CONFIG_MIPS_MT_SMP
Ralf Baechle39b8d522008-04-28 17:14:26 +0100343 if (!cpu_has_mipsmt_pertccounters)
344 counters = counters_total_to_per_cpu(counters);
345#endif
Ingo Molnarf6f88e92008-07-15 22:08:52 +0200346 on_each_cpu(reset_counters, (void *)(long)counters, 1);
Chris Dearman795a2252007-03-01 17:58:24 +0000347
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900348 op_model_mipsxx_ops.num_counters = counters;
Ralf Baechle10cc3522007-10-11 23:46:15 +0100349 switch (current_cpu_type()) {
Steven J. Hill113c62d2012-07-06 23:56:00 +0200350 case CPU_M14KC:
351 op_model_mipsxx_ops.cpu_type = "mips/M14Kc";
352 break;
353
Steven J. Hillf8fa4812012-12-07 03:51:35 +0000354 case CPU_M14KEC:
355 op_model_mipsxx_ops.cpu_type = "mips/M14KEc";
356 break;
357
Ralf Baechle20659882005-12-09 12:42:13 +0000358 case CPU_20KC:
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900359 op_model_mipsxx_ops.cpu_type = "mips/20K";
Ralf Baechle20659882005-12-09 12:42:13 +0000360 break;
361
Ralf Baechle54176732005-02-07 02:54:29 +0000362 case CPU_24K:
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900363 op_model_mipsxx_ops.cpu_type = "mips/24K";
Ralf Baechle54176732005-02-07 02:54:29 +0000364 break;
365
Ralf Baechle20659882005-12-09 12:42:13 +0000366 case CPU_25KF:
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900367 op_model_mipsxx_ops.cpu_type = "mips/25K";
Ralf Baechle20659882005-12-09 12:42:13 +0000368 break;
369
Ralf Baechle39b8d522008-04-28 17:14:26 +0100370 case CPU_1004K:
Ralf Baechlefcfd9802006-02-01 17:54:30 +0000371 case CPU_34K:
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900372 op_model_mipsxx_ops.cpu_type = "mips/34K";
Ralf Baechlefcfd9802006-02-01 17:54:30 +0000373 break;
Chris Dearmanc6209532006-05-02 14:08:46 +0100374
Steven J. Hill442e14a2014-01-17 15:03:50 -0600375 case CPU_1074K:
Chris Dearmanc6209532006-05-02 14:08:46 +0100376 case CPU_74K:
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900377 op_model_mipsxx_ops.cpu_type = "mips/74K";
Chris Dearmanc6209532006-05-02 14:08:46 +0100378 break;
Ralf Baechlefcfd9802006-02-01 17:54:30 +0000379
Leonid Yegoshin26ab96d2013-11-27 10:07:53 +0000380 case CPU_INTERAPTIV:
381 op_model_mipsxx_ops.cpu_type = "mips/interAptiv";
382 break;
383
Leonid Yegoshin708ac4b2013-11-14 16:12:27 +0000384 case CPU_PROAPTIV:
385 op_model_mipsxx_ops.cpu_type = "mips/proAptiv";
386 break;
387
James Hogan8c7f6ba2014-01-22 16:19:41 +0000388 case CPU_P5600:
389 op_model_mipsxx_ops.cpu_type = "mips/P5600";
390 break;
391
Markos Chandras4e88a862015-07-09 10:40:36 +0100392 case CPU_I6400:
393 op_model_mipsxx_ops.cpu_type = "mips/I6400";
394 break;
395
Leonid Yegoshinf36c4722014-03-04 13:34:43 +0000396 case CPU_M5150:
397 op_model_mipsxx_ops.cpu_type = "mips/M5150";
398 break;
399
Ralf Baechle20659882005-12-09 12:42:13 +0000400 case CPU_5KC:
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900401 op_model_mipsxx_ops.cpu_type = "mips/5K";
Ralf Baechle20659882005-12-09 12:42:13 +0000402 break;
403
Ralf Baechle714cfe72006-10-23 00:44:02 +0100404 case CPU_R10000:
405 if ((current_cpu_data.processor_id & 0xff) == 0x20)
406 op_model_mipsxx_ops.cpu_type = "mips/r10000-v2.x";
407 else
408 op_model_mipsxx_ops.cpu_type = "mips/r10000";
409 break;
410
411 case CPU_R12000:
412 case CPU_R14000:
413 op_model_mipsxx_ops.cpu_type = "mips/r12000";
414 break;
415
Joshua Kinard30577392015-01-21 07:59:45 -0500416 case CPU_R16000:
417 op_model_mipsxx_ops.cpu_type = "mips/r16000";
418 break;
419
Mark Masonc03bc122006-01-17 12:06:32 -0800420 case CPU_SB1:
421 case CPU_SB1A:
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900422 op_model_mipsxx_ops.cpu_type = "mips/sb1";
Mark Masonc03bc122006-01-17 12:06:32 -0800423 break;
424
Huacai Chenb2afb642019-11-04 14:11:20 +0800425 case CPU_LOONGSON32:
Kelvin Cheung2fa36392012-06-20 20:05:32 +0100426 op_model_mipsxx_ops.cpu_type = "mips/loongson1";
427 break;
428
Madhusudan Bhatc7833902012-10-31 12:01:27 +0000429 case CPU_XLR:
430 op_model_mipsxx_ops.cpu_type = "mips/xlr";
431 break;
432
Ralf Baechle54176732005-02-07 02:54:29 +0000433 default:
434 printk(KERN_ERR "Profiling unsupported for this CPU\n");
435
436 return -ENODEV;
437 }
438
Dmitri Vorobiev46684732008-04-02 03:58:38 +0400439 save_perf_irq = perf_irq;
Ralf Baechle54176732005-02-07 02:54:29 +0000440 perf_irq = mipsxx_perfcount_handler;
441
Andrew Brestickera669efc2014-09-18 14:47:12 -0700442 if (get_c0_perfcount_int)
443 perfcount_irq = get_c0_perfcount_int();
James Hogan7eca5b12015-01-27 21:45:49 +0000444 else if (cp0_perfcount_irq >= 0)
Andrew Brestickera669efc2014-09-18 14:47:12 -0700445 perfcount_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
446 else
447 perfcount_irq = -1;
448
449 if (perfcount_irq >= 0)
450 return request_irq(perfcount_irq, mipsxx_perfcount_int,
James Hogan369a93b2015-01-27 21:45:54 +0000451 IRQF_PERCPU | IRQF_NOBALANCING |
452 IRQF_NO_THREAD | IRQF_NO_SUSPEND |
453 IRQF_SHARED,
454 "Perfcounter", save_perf_irq);
Felix Fietkau3572a2c2012-05-02 17:33:04 +0200455
Ralf Baechle54176732005-02-07 02:54:29 +0000456 return 0;
457}
458
459static void mipsxx_exit(void)
460{
Chris Dearman795a2252007-03-01 17:58:24 +0000461 int counters = op_model_mipsxx_ops.num_counters;
Ralf Baechle5e2862e2007-12-06 09:12:28 +0000462
Andrew Brestickera669efc2014-09-18 14:47:12 -0700463 if (perfcount_irq >= 0)
464 free_irq(perfcount_irq, save_perf_irq);
Felix Fietkau3572a2c2012-05-02 17:33:04 +0200465
Ralf Baechle5e2862e2007-12-06 09:12:28 +0000466 counters = counters_per_cpu_to_total(counters);
Ingo Molnarf6f88e92008-07-15 22:08:52 +0200467 on_each_cpu(reset_counters, (void *)(long)counters, 1);
Ralf Baechle54176732005-02-07 02:54:29 +0000468
Dmitri Vorobiev46684732008-04-02 03:58:38 +0400469 perf_irq = save_perf_irq;
Ralf Baechle54176732005-02-07 02:54:29 +0000470}
471
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900472struct op_mips_model op_model_mipsxx_ops = {
Ralf Baechle54176732005-02-07 02:54:29 +0000473 .reg_setup = mipsxx_reg_setup,
474 .cpu_setup = mipsxx_cpu_setup,
475 .init = mipsxx_init,
476 .exit = mipsxx_exit,
477 .cpu_start = mipsxx_cpu_start,
478 .cpu_stop = mipsxx_cpu_stop,
479};