blob: a537bf98912c0b65068c9fac7919cb1b1cd94a2b [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]);
Gustavo A. R. Silva2d291e62019-07-29 18:32:10 -0500175 /* fall through */
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]);
Gustavo A. R. Silva2d291e62019-07-29 18:32:10 -0500179 /* fall through */
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]);
Gustavo A. R. Silva2d291e62019-07-29 18:32:10 -0500183 /* fall through */
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]);
Gustavo A. R. Silva2d291e62019-07-29 18:32:10 -0500201 /* fall through */
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]);
Gustavo A. R. Silva2d291e62019-07-29 18:32:10 -0500204 /* fall through */
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]);
Gustavo A. R. Silva2d291e62019-07-29 18:32:10 -0500207 /* fall through */
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);
Gustavo A. R. Silva2d291e62019-07-29 18:32:10 -0500224 /* fall through */
Ralf Baechle54176732005-02-07 02:54:29 +0000225 case 3:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100226 w_c0_perfctrl2(0);
Gustavo A. R. Silva2d291e62019-07-29 18:32:10 -0500227 /* fall through */
Ralf Baechle54176732005-02-07 02:54:29 +0000228 case 2:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100229 w_c0_perfctrl1(0);
Gustavo A. R. Silva2d291e62019-07-29 18:32:10 -0500230 /* fall through */
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) \
Gustavo A. R. Silva2d291e62019-07-29 18:32:10 -0500248 /* fall through */ \
Ralf Baechle54176732005-02-07 02:54:29 +0000249 case n + 1: \
Ralf Baechle92c7b622006-06-23 18:39:00 +0100250 control = r_c0_perfctrl ## n(); \
251 counter = r_c0_perfcntr ## n(); \
James Hogan26542942017-02-06 12:37:45 +0000252 if ((control & MIPS_PERFCTRL_IE) && \
Ralf Baechle54176732005-02-07 02:54:29 +0000253 (counter & M_COUNTER_OVERFLOW)) { \
Ralf Baechle937a8012006-10-07 19:44:33 +0100254 oprofile_add_sample(get_irq_regs(), n); \
Ralf Baechle92c7b622006-06-23 18:39:00 +0100255 w_c0_perfcntr ## n(reg.counter[n]); \
Chris Dearmanffe9ee42007-05-24 22:24:20 +0100256 handled = IRQ_HANDLED; \
Ralf Baechle54176732005-02-07 02:54:29 +0000257 }
258 HANDLE_COUNTER(3)
259 HANDLE_COUNTER(2)
260 HANDLE_COUNTER(1)
261 HANDLE_COUNTER(0)
262 }
Ralf Baechleba339c02005-12-09 12:29:38 +0000263
264 return handled;
Ralf Baechle54176732005-02-07 02:54:29 +0000265}
266
Ralf Baechle92c7b622006-06-23 18:39:00 +0100267static inline int __n_counters(void)
Ralf Baechle54176732005-02-07 02:54:29 +0000268{
James Hogan30228c42016-05-11 13:50:53 +0100269 if (!cpu_has_perf)
Ralf Baechle54176732005-02-07 02:54:29 +0000270 return 0;
James Hogan26542942017-02-06 12:37:45 +0000271 if (!(read_c0_perfctrl0() & MIPS_PERFCTRL_M))
Ralf Baechle54176732005-02-07 02:54:29 +0000272 return 1;
James Hogan26542942017-02-06 12:37:45 +0000273 if (!(read_c0_perfctrl1() & MIPS_PERFCTRL_M))
Ralf Baechle54176732005-02-07 02:54:29 +0000274 return 2;
James Hogan26542942017-02-06 12:37:45 +0000275 if (!(read_c0_perfctrl2() & MIPS_PERFCTRL_M))
Ralf Baechle54176732005-02-07 02:54:29 +0000276 return 3;
277
278 return 4;
279}
280
Ralf Baechle92c7b622006-06-23 18:39:00 +0100281static inline int n_counters(void)
282{
Ralf Baechle714cfe72006-10-23 00:44:02 +0100283 int counters;
284
Ralf Baechle10cc3522007-10-11 23:46:15 +0100285 switch (current_cpu_type()) {
Ralf Baechle714cfe72006-10-23 00:44:02 +0100286 case CPU_R10000:
287 counters = 2;
Ralf Baechle148171b2007-02-28 15:34:22 +0000288 break;
Ralf Baechle714cfe72006-10-23 00:44:02 +0100289
290 case CPU_R12000:
291 case CPU_R14000:
Joshua Kinard30577392015-01-21 07:59:45 -0500292 case CPU_R16000:
Ralf Baechle714cfe72006-10-23 00:44:02 +0100293 counters = 4;
Ralf Baechle148171b2007-02-28 15:34:22 +0000294 break;
Ralf Baechle714cfe72006-10-23 00:44:02 +0100295
296 default:
297 counters = __n_counters();
298 }
Ralf Baechle92c7b622006-06-23 18:39:00 +0100299
Ralf Baechle92c7b622006-06-23 18:39:00 +0100300 return counters;
301}
302
Ralf Baechle39b8d522008-04-28 17:14:26 +0100303static void reset_counters(void *arg)
Ralf Baechle54176732005-02-07 02:54:29 +0000304{
Thiemo Seufer005ca9a2008-05-06 11:23:33 +0100305 int counters = (int)(long)arg;
Ralf Baechle54176732005-02-07 02:54:29 +0000306 switch (counters) {
307 case 4:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100308 w_c0_perfctrl3(0);
309 w_c0_perfcntr3(0);
Gustavo A. R. Silva2d291e62019-07-29 18:32:10 -0500310 /* fall through */
Ralf Baechle54176732005-02-07 02:54:29 +0000311 case 3:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100312 w_c0_perfctrl2(0);
313 w_c0_perfcntr2(0);
Gustavo A. R. Silva2d291e62019-07-29 18:32:10 -0500314 /* fall through */
Ralf Baechle54176732005-02-07 02:54:29 +0000315 case 2:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100316 w_c0_perfctrl1(0);
317 w_c0_perfcntr1(0);
Gustavo A. R. Silva2d291e62019-07-29 18:32:10 -0500318 /* fall through */
Ralf Baechle54176732005-02-07 02:54:29 +0000319 case 1:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100320 w_c0_perfctrl0(0);
321 w_c0_perfcntr0(0);
Ralf Baechle54176732005-02-07 02:54:29 +0000322 }
323}
324
Felix Fietkau3572a2c2012-05-02 17:33:04 +0200325static irqreturn_t mipsxx_perfcount_int(int irq, void *dev_id)
326{
327 return mipsxx_perfcount_handler();
328}
329
Ralf Baechle54176732005-02-07 02:54:29 +0000330static int __init mipsxx_init(void)
331{
332 int counters;
333
334 counters = n_counters();
Ralf Baechle9efeae92005-12-09 12:34:45 +0000335 if (counters == 0) {
336 printk(KERN_ERR "Oprofile: CPU has no performance counters\n");
Ralf Baechle54176732005-02-07 02:54:29 +0000337 return -ENODEV;
Ralf Baechle9efeae92005-12-09 12:34:45 +0000338 }
Ralf Baechle54176732005-02-07 02:54:29 +0000339
Ralf Baechle39b8d522008-04-28 17:14:26 +0100340#ifdef CONFIG_MIPS_MT_SMP
Ralf Baechle39b8d522008-04-28 17:14:26 +0100341 if (!cpu_has_mipsmt_pertccounters)
342 counters = counters_total_to_per_cpu(counters);
343#endif
Ingo Molnarf6f88e92008-07-15 22:08:52 +0200344 on_each_cpu(reset_counters, (void *)(long)counters, 1);
Chris Dearman795a2252007-03-01 17:58:24 +0000345
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900346 op_model_mipsxx_ops.num_counters = counters;
Ralf Baechle10cc3522007-10-11 23:46:15 +0100347 switch (current_cpu_type()) {
Steven J. Hill113c62d2012-07-06 23:56:00 +0200348 case CPU_M14KC:
349 op_model_mipsxx_ops.cpu_type = "mips/M14Kc";
350 break;
351
Steven J. Hillf8fa4812012-12-07 03:51:35 +0000352 case CPU_M14KEC:
353 op_model_mipsxx_ops.cpu_type = "mips/M14KEc";
354 break;
355
Ralf Baechle20659882005-12-09 12:42:13 +0000356 case CPU_20KC:
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900357 op_model_mipsxx_ops.cpu_type = "mips/20K";
Ralf Baechle20659882005-12-09 12:42:13 +0000358 break;
359
Ralf Baechle54176732005-02-07 02:54:29 +0000360 case CPU_24K:
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900361 op_model_mipsxx_ops.cpu_type = "mips/24K";
Ralf Baechle54176732005-02-07 02:54:29 +0000362 break;
363
Ralf Baechle20659882005-12-09 12:42:13 +0000364 case CPU_25KF:
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900365 op_model_mipsxx_ops.cpu_type = "mips/25K";
Ralf Baechle20659882005-12-09 12:42:13 +0000366 break;
367
Ralf Baechle39b8d522008-04-28 17:14:26 +0100368 case CPU_1004K:
Ralf Baechlefcfd9802006-02-01 17:54:30 +0000369 case CPU_34K:
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900370 op_model_mipsxx_ops.cpu_type = "mips/34K";
Ralf Baechlefcfd9802006-02-01 17:54:30 +0000371 break;
Chris Dearmanc6209532006-05-02 14:08:46 +0100372
Steven J. Hill442e14a2014-01-17 15:03:50 -0600373 case CPU_1074K:
Chris Dearmanc6209532006-05-02 14:08:46 +0100374 case CPU_74K:
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900375 op_model_mipsxx_ops.cpu_type = "mips/74K";
Chris Dearmanc6209532006-05-02 14:08:46 +0100376 break;
Ralf Baechlefcfd9802006-02-01 17:54:30 +0000377
Leonid Yegoshin26ab96d2013-11-27 10:07:53 +0000378 case CPU_INTERAPTIV:
379 op_model_mipsxx_ops.cpu_type = "mips/interAptiv";
380 break;
381
Leonid Yegoshin708ac4b2013-11-14 16:12:27 +0000382 case CPU_PROAPTIV:
383 op_model_mipsxx_ops.cpu_type = "mips/proAptiv";
384 break;
385
James Hogan8c7f6ba2014-01-22 16:19:41 +0000386 case CPU_P5600:
387 op_model_mipsxx_ops.cpu_type = "mips/P5600";
388 break;
389
Markos Chandras4e88a862015-07-09 10:40:36 +0100390 case CPU_I6400:
391 op_model_mipsxx_ops.cpu_type = "mips/I6400";
392 break;
393
Leonid Yegoshinf36c4722014-03-04 13:34:43 +0000394 case CPU_M5150:
395 op_model_mipsxx_ops.cpu_type = "mips/M5150";
396 break;
397
Ralf Baechle20659882005-12-09 12:42:13 +0000398 case CPU_5KC:
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900399 op_model_mipsxx_ops.cpu_type = "mips/5K";
Ralf Baechle20659882005-12-09 12:42:13 +0000400 break;
401
Ralf Baechle714cfe72006-10-23 00:44:02 +0100402 case CPU_R10000:
403 if ((current_cpu_data.processor_id & 0xff) == 0x20)
404 op_model_mipsxx_ops.cpu_type = "mips/r10000-v2.x";
405 else
406 op_model_mipsxx_ops.cpu_type = "mips/r10000";
407 break;
408
409 case CPU_R12000:
410 case CPU_R14000:
411 op_model_mipsxx_ops.cpu_type = "mips/r12000";
412 break;
413
Joshua Kinard30577392015-01-21 07:59:45 -0500414 case CPU_R16000:
415 op_model_mipsxx_ops.cpu_type = "mips/r16000";
416 break;
417
Mark Masonc03bc122006-01-17 12:06:32 -0800418 case CPU_SB1:
419 case CPU_SB1A:
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900420 op_model_mipsxx_ops.cpu_type = "mips/sb1";
Mark Masonc03bc122006-01-17 12:06:32 -0800421 break;
422
Huacai Chenb2afb642019-11-04 14:11:20 +0800423 case CPU_LOONGSON32:
Kelvin Cheung2fa36392012-06-20 20:05:32 +0100424 op_model_mipsxx_ops.cpu_type = "mips/loongson1";
425 break;
426
Madhusudan Bhatc7833902012-10-31 12:01:27 +0000427 case CPU_XLR:
428 op_model_mipsxx_ops.cpu_type = "mips/xlr";
429 break;
430
Ralf Baechle54176732005-02-07 02:54:29 +0000431 default:
432 printk(KERN_ERR "Profiling unsupported for this CPU\n");
433
434 return -ENODEV;
435 }
436
Dmitri Vorobiev46684732008-04-02 03:58:38 +0400437 save_perf_irq = perf_irq;
Ralf Baechle54176732005-02-07 02:54:29 +0000438 perf_irq = mipsxx_perfcount_handler;
439
Andrew Brestickera669efc2014-09-18 14:47:12 -0700440 if (get_c0_perfcount_int)
441 perfcount_irq = get_c0_perfcount_int();
James Hogan7eca5b12015-01-27 21:45:49 +0000442 else if (cp0_perfcount_irq >= 0)
Andrew Brestickera669efc2014-09-18 14:47:12 -0700443 perfcount_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
444 else
445 perfcount_irq = -1;
446
447 if (perfcount_irq >= 0)
448 return request_irq(perfcount_irq, mipsxx_perfcount_int,
James Hogan369a93b2015-01-27 21:45:54 +0000449 IRQF_PERCPU | IRQF_NOBALANCING |
450 IRQF_NO_THREAD | IRQF_NO_SUSPEND |
451 IRQF_SHARED,
452 "Perfcounter", save_perf_irq);
Felix Fietkau3572a2c2012-05-02 17:33:04 +0200453
Ralf Baechle54176732005-02-07 02:54:29 +0000454 return 0;
455}
456
457static void mipsxx_exit(void)
458{
Chris Dearman795a2252007-03-01 17:58:24 +0000459 int counters = op_model_mipsxx_ops.num_counters;
Ralf Baechle5e2862e2007-12-06 09:12:28 +0000460
Andrew Brestickera669efc2014-09-18 14:47:12 -0700461 if (perfcount_irq >= 0)
462 free_irq(perfcount_irq, save_perf_irq);
Felix Fietkau3572a2c2012-05-02 17:33:04 +0200463
Ralf Baechle5e2862e2007-12-06 09:12:28 +0000464 counters = counters_per_cpu_to_total(counters);
Ingo Molnarf6f88e92008-07-15 22:08:52 +0200465 on_each_cpu(reset_counters, (void *)(long)counters, 1);
Ralf Baechle54176732005-02-07 02:54:29 +0000466
Dmitri Vorobiev46684732008-04-02 03:58:38 +0400467 perf_irq = save_perf_irq;
Ralf Baechle54176732005-02-07 02:54:29 +0000468}
469
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900470struct op_mips_model op_model_mipsxx_ops = {
Ralf Baechle54176732005-02-07 02:54:29 +0000471 .reg_setup = mipsxx_reg_setup,
472 .cpu_setup = mipsxx_cpu_setup,
473 .init = mipsxx_init,
474 .exit = mipsxx_exit,
475 .cpu_start = mipsxx_cpu_start,
476 .cpu_stop = mipsxx_cpu_stop,
477};