blob: e4b1140cdae060dca0de8bfdd6a5985b1429de58 [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>
Ralf Baechle54176732005-02-07 02:54:29 +000014
15#include "op_impl.h"
16
Ralf Baechle70342282013-01-22 12:59:30 +010017#define M_PERFCTL_EXL (1UL << 0)
18#define M_PERFCTL_KERNEL (1UL << 1)
19#define M_PERFCTL_SUPERVISOR (1UL << 2)
20#define M_PERFCTL_USER (1UL << 3)
21#define M_PERFCTL_INTERRUPT_ENABLE (1UL << 4)
Ralf Baechle39a51102008-01-29 10:14:59 +000022#define M_PERFCTL_EVENT(event) (((event) & 0x3ff) << 5)
Ralf Baechle70342282013-01-22 12:59:30 +010023#define M_PERFCTL_VPEID(vpe) ((vpe) << 16)
Ralf Baechle92c7b622006-06-23 18:39:00 +010024#define M_PERFCTL_MT_EN(filter) ((filter) << 20)
Ralf Baechle70342282013-01-22 12:59:30 +010025#define M_TC_EN_ALL M_PERFCTL_MT_EN(0)
26#define M_TC_EN_VPE M_PERFCTL_MT_EN(1)
27#define M_TC_EN_TC M_PERFCTL_MT_EN(2)
28#define M_PERFCTL_TCID(tcid) ((tcid) << 22)
29#define M_PERFCTL_WIDE (1UL << 30)
30#define M_PERFCTL_MORE (1UL << 31)
Ralf Baechle54176732005-02-07 02:54:29 +000031
Ralf Baechle70342282013-01-22 12:59:30 +010032#define M_COUNTER_OVERFLOW (1UL << 31)
Ralf Baechle92c7b622006-06-23 18:39:00 +010033
Madhusudan Bhatc7833902012-10-31 12:01:27 +000034/* Netlogic XLR specific, count events in all threads in a core */
Ralf Baechle70342282013-01-22 12:59:30 +010035#define M_PERFCTL_COUNT_ALL_THREADS (1UL << 13)
Madhusudan Bhatc7833902012-10-31 12:01:27 +000036
Dmitri Vorobiev46684732008-04-02 03:58:38 +040037static int (*save_perf_irq)(void);
38
Madhusudan Bhatc7833902012-10-31 12:01:27 +000039/*
40 * XLR has only one set of counters per core. Designate the
41 * first hardware thread in the core for setup and init.
42 * Skip CPUs with non-zero hardware thread id (4 hwt per core)
43 */
Jayachandran C83a18412013-03-25 06:51:52 +000044#if defined(CONFIG_CPU_XLR) && defined(CONFIG_SMP)
Madhusudan Bhatc7833902012-10-31 12:01:27 +000045#define oprofile_skip_cpu(c) ((cpu_logical_map(c) & 0x3) != 0)
46#else
47#define oprofile_skip_cpu(c) 0
48#endif
49
Ralf Baechle92c7b622006-06-23 18:39:00 +010050#ifdef CONFIG_MIPS_MT_SMP
Ralf Baechle39b8d522008-04-28 17:14:26 +010051static int cpu_has_mipsmt_pertccounters;
52#define WHAT (M_TC_EN_VPE | \
53 M_PERFCTL_VPEID(cpu_data[smp_processor_id()].vpe_id))
54#define vpe_id() (cpu_has_mipsmt_pertccounters ? \
55 0 : cpu_data[smp_processor_id()].vpe_id)
Ralf Baechle5e2862e2007-12-06 09:12:28 +000056
57/*
58 * The number of bits to shift to convert between counters per core and
59 * counters per VPE. There is no reasonable interface atm to obtain the
60 * number of VPEs used by Linux and in the 34K this number is fixed to two
61 * anyways so we hardcore a few things here for the moment. The way it's
62 * done here will ensure that oprofile VSMP kernel will run right on a lesser
63 * core like a 24K also or with maxcpus=1.
64 */
65static inline unsigned int vpe_shift(void)
66{
67 if (num_possible_cpus() > 1)
68 return 1;
69
70 return 0;
71}
72
Ralf Baechle92c7b622006-06-23 18:39:00 +010073#else
Ralf Baechle5e2862e2007-12-06 09:12:28 +000074
Ralf Baechlebe609f32006-10-23 13:22:06 +010075#define WHAT 0
Ralf Baechle6f4c5bd2007-04-24 21:42:20 +010076#define vpe_id() 0
Ralf Baechle5e2862e2007-12-06 09:12:28 +000077
78static inline unsigned int vpe_shift(void)
79{
80 return 0;
81}
82
Ralf Baechle92c7b622006-06-23 18:39:00 +010083#endif
84
Ralf Baechle5e2862e2007-12-06 09:12:28 +000085static inline unsigned int counters_total_to_per_cpu(unsigned int counters)
86{
87 return counters >> vpe_shift();
88}
89
90static inline unsigned int counters_per_cpu_to_total(unsigned int counters)
91{
92 return counters << vpe_shift();
93}
94
Ralf Baechle92c7b622006-06-23 18:39:00 +010095#define __define_perf_accessors(r, n, np) \
96 \
97static inline unsigned int r_c0_ ## r ## n(void) \
98{ \
Ralf Baechlebe609f32006-10-23 13:22:06 +010099 unsigned int cpu = vpe_id(); \
Ralf Baechle92c7b622006-06-23 18:39:00 +0100100 \
101 switch (cpu) { \
102 case 0: \
103 return read_c0_ ## r ## n(); \
104 case 1: \
105 return read_c0_ ## r ## np(); \
106 default: \
107 BUG(); \
108 } \
Thiemo Seufer30f244a2006-07-07 10:38:51 +0100109 return 0; \
Ralf Baechle92c7b622006-06-23 18:39:00 +0100110} \
111 \
112static inline void w_c0_ ## r ## n(unsigned int value) \
113{ \
Ralf Baechlebe609f32006-10-23 13:22:06 +0100114 unsigned int cpu = vpe_id(); \
Ralf Baechle92c7b622006-06-23 18:39:00 +0100115 \
116 switch (cpu) { \
117 case 0: \
118 write_c0_ ## r ## n(value); \
119 return; \
120 case 1: \
121 write_c0_ ## r ## np(value); \
122 return; \
123 default: \
124 BUG(); \
125 } \
Thiemo Seufer30f244a2006-07-07 10:38:51 +0100126 return; \
Ralf Baechle92c7b622006-06-23 18:39:00 +0100127} \
128
129__define_perf_accessors(perfcntr, 0, 2)
130__define_perf_accessors(perfcntr, 1, 3)
Chris Dearman795a2252007-03-01 17:58:24 +0000131__define_perf_accessors(perfcntr, 2, 0)
132__define_perf_accessors(perfcntr, 3, 1)
Ralf Baechle92c7b622006-06-23 18:39:00 +0100133
134__define_perf_accessors(perfctrl, 0, 2)
135__define_perf_accessors(perfctrl, 1, 3)
Chris Dearman795a2252007-03-01 17:58:24 +0000136__define_perf_accessors(perfctrl, 2, 0)
137__define_perf_accessors(perfctrl, 3, 1)
Ralf Baechle54176732005-02-07 02:54:29 +0000138
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900139struct op_mips_model op_model_mipsxx_ops;
Ralf Baechle54176732005-02-07 02:54:29 +0000140
141static struct mipsxx_register_config {
142 unsigned int control[4];
143 unsigned int counter[4];
144} reg;
145
Ralf Baechle70342282013-01-22 12:59:30 +0100146/* Compute all of the registers in preparation for enabling profiling. */
Ralf Baechle54176732005-02-07 02:54:29 +0000147
148static void mipsxx_reg_setup(struct op_counter_config *ctr)
149{
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900150 unsigned int counters = op_model_mipsxx_ops.num_counters;
Ralf Baechle54176732005-02-07 02:54:29 +0000151 int i;
152
153 /* Compute the performance counter control word. */
Ralf Baechle54176732005-02-07 02:54:29 +0000154 for (i = 0; i < counters; i++) {
155 reg.control[i] = 0;
156 reg.counter[i] = 0;
157
158 if (!ctr[i].enabled)
159 continue;
160
161 reg.control[i] = M_PERFCTL_EVENT(ctr[i].event) |
Ralf Baechle70342282013-01-22 12:59:30 +0100162 M_PERFCTL_INTERRUPT_ENABLE;
Ralf Baechle54176732005-02-07 02:54:29 +0000163 if (ctr[i].kernel)
164 reg.control[i] |= M_PERFCTL_KERNEL;
165 if (ctr[i].user)
166 reg.control[i] |= M_PERFCTL_USER;
167 if (ctr[i].exl)
168 reg.control[i] |= M_PERFCTL_EXL;
Madhusudan Bhatc7833902012-10-31 12:01:27 +0000169 if (current_cpu_type() == CPU_XLR)
170 reg.control[i] |= M_PERFCTL_COUNT_ALL_THREADS;
Ralf Baechle54176732005-02-07 02:54:29 +0000171 reg.counter[i] = 0x80000000 - ctr[i].count;
172 }
173}
174
Ralf Baechle70342282013-01-22 12:59:30 +0100175/* Program all of the registers in preparation for enabling profiling. */
Ralf Baechle54176732005-02-07 02:54:29 +0000176
Ralf Baechle49a89ef2007-10-11 23:46:15 +0100177static void mipsxx_cpu_setup(void *args)
Ralf Baechle54176732005-02-07 02:54:29 +0000178{
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900179 unsigned int counters = op_model_mipsxx_ops.num_counters;
Ralf Baechle54176732005-02-07 02:54:29 +0000180
Madhusudan Bhatc7833902012-10-31 12:01:27 +0000181 if (oprofile_skip_cpu(smp_processor_id()))
182 return;
183
Ralf Baechle54176732005-02-07 02:54:29 +0000184 switch (counters) {
185 case 4:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100186 w_c0_perfctrl3(0);
187 w_c0_perfcntr3(reg.counter[3]);
Ralf Baechle54176732005-02-07 02:54:29 +0000188 case 3:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100189 w_c0_perfctrl2(0);
190 w_c0_perfcntr2(reg.counter[2]);
Ralf Baechle54176732005-02-07 02:54:29 +0000191 case 2:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100192 w_c0_perfctrl1(0);
193 w_c0_perfcntr1(reg.counter[1]);
Ralf Baechle54176732005-02-07 02:54:29 +0000194 case 1:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100195 w_c0_perfctrl0(0);
196 w_c0_perfcntr0(reg.counter[0]);
Ralf Baechle54176732005-02-07 02:54:29 +0000197 }
198}
199
200/* Start all counters on current CPU */
201static void mipsxx_cpu_start(void *args)
202{
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900203 unsigned int counters = op_model_mipsxx_ops.num_counters;
Ralf Baechle54176732005-02-07 02:54:29 +0000204
Madhusudan Bhatc7833902012-10-31 12:01:27 +0000205 if (oprofile_skip_cpu(smp_processor_id()))
206 return;
207
Ralf Baechle54176732005-02-07 02:54:29 +0000208 switch (counters) {
209 case 4:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100210 w_c0_perfctrl3(WHAT | reg.control[3]);
Ralf Baechle54176732005-02-07 02:54:29 +0000211 case 3:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100212 w_c0_perfctrl2(WHAT | reg.control[2]);
Ralf Baechle54176732005-02-07 02:54:29 +0000213 case 2:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100214 w_c0_perfctrl1(WHAT | reg.control[1]);
Ralf Baechle54176732005-02-07 02:54:29 +0000215 case 1:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100216 w_c0_perfctrl0(WHAT | reg.control[0]);
Ralf Baechle54176732005-02-07 02:54:29 +0000217 }
218}
219
220/* Stop all counters on current CPU */
221static void mipsxx_cpu_stop(void *args)
222{
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900223 unsigned int counters = op_model_mipsxx_ops.num_counters;
Ralf Baechle54176732005-02-07 02:54:29 +0000224
Madhusudan Bhatc7833902012-10-31 12:01:27 +0000225 if (oprofile_skip_cpu(smp_processor_id()))
226 return;
227
Ralf Baechle54176732005-02-07 02:54:29 +0000228 switch (counters) {
229 case 4:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100230 w_c0_perfctrl3(0);
Ralf Baechle54176732005-02-07 02:54:29 +0000231 case 3:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100232 w_c0_perfctrl2(0);
Ralf Baechle54176732005-02-07 02:54:29 +0000233 case 2:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100234 w_c0_perfctrl1(0);
Ralf Baechle54176732005-02-07 02:54:29 +0000235 case 1:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100236 w_c0_perfctrl0(0);
Ralf Baechle54176732005-02-07 02:54:29 +0000237 }
238}
239
Ralf Baechle937a8012006-10-07 19:44:33 +0100240static int mipsxx_perfcount_handler(void)
Ralf Baechle54176732005-02-07 02:54:29 +0000241{
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900242 unsigned int counters = op_model_mipsxx_ops.num_counters;
Ralf Baechle54176732005-02-07 02:54:29 +0000243 unsigned int control;
244 unsigned int counter;
Chris Dearmanffe9ee42007-05-24 22:24:20 +0100245 int handled = IRQ_NONE;
246
247 if (cpu_has_mips_r2 && !(read_c0_cause() & (1 << 26)))
248 return handled;
Ralf Baechle54176732005-02-07 02:54:29 +0000249
250 switch (counters) {
251#define HANDLE_COUNTER(n) \
252 case n + 1: \
Ralf Baechle92c7b622006-06-23 18:39:00 +0100253 control = r_c0_perfctrl ## n(); \
254 counter = r_c0_perfcntr ## n(); \
Ralf Baechle54176732005-02-07 02:54:29 +0000255 if ((control & M_PERFCTL_INTERRUPT_ENABLE) && \
256 (counter & M_COUNTER_OVERFLOW)) { \
Ralf Baechle937a8012006-10-07 19:44:33 +0100257 oprofile_add_sample(get_irq_regs(), n); \
Ralf Baechle92c7b622006-06-23 18:39:00 +0100258 w_c0_perfcntr ## n(reg.counter[n]); \
Chris Dearmanffe9ee42007-05-24 22:24:20 +0100259 handled = IRQ_HANDLED; \
Ralf Baechle54176732005-02-07 02:54:29 +0000260 }
261 HANDLE_COUNTER(3)
262 HANDLE_COUNTER(2)
263 HANDLE_COUNTER(1)
264 HANDLE_COUNTER(0)
265 }
Ralf Baechleba339c02005-12-09 12:29:38 +0000266
267 return handled;
Ralf Baechle54176732005-02-07 02:54:29 +0000268}
269
270#define M_CONFIG1_PC (1 << 4)
271
Ralf Baechle92c7b622006-06-23 18:39:00 +0100272static inline int __n_counters(void)
Ralf Baechle54176732005-02-07 02:54:29 +0000273{
274 if (!(read_c0_config1() & M_CONFIG1_PC))
275 return 0;
Ralf Baechle39b8d522008-04-28 17:14:26 +0100276 if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
Ralf Baechle54176732005-02-07 02:54:29 +0000277 return 1;
Ralf Baechle39b8d522008-04-28 17:14:26 +0100278 if (!(read_c0_perfctrl1() & M_PERFCTL_MORE))
Ralf Baechle54176732005-02-07 02:54:29 +0000279 return 2;
Ralf Baechle39b8d522008-04-28 17:14:26 +0100280 if (!(read_c0_perfctrl2() & M_PERFCTL_MORE))
Ralf Baechle54176732005-02-07 02:54:29 +0000281 return 3;
282
283 return 4;
284}
285
Ralf Baechle92c7b622006-06-23 18:39:00 +0100286static inline int n_counters(void)
287{
Ralf Baechle714cfe72006-10-23 00:44:02 +0100288 int counters;
289
Ralf Baechle10cc3522007-10-11 23:46:15 +0100290 switch (current_cpu_type()) {
Ralf Baechle714cfe72006-10-23 00:44:02 +0100291 case CPU_R10000:
292 counters = 2;
Ralf Baechle148171b2007-02-28 15:34:22 +0000293 break;
Ralf Baechle714cfe72006-10-23 00:44:02 +0100294
295 case CPU_R12000:
296 case CPU_R14000:
297 counters = 4;
Ralf Baechle148171b2007-02-28 15:34:22 +0000298 break;
Ralf Baechle714cfe72006-10-23 00:44:02 +0100299
300 default:
301 counters = __n_counters();
302 }
Ralf Baechle92c7b622006-06-23 18:39:00 +0100303
Ralf Baechle92c7b622006-06-23 18:39:00 +0100304 return counters;
305}
306
Ralf Baechle39b8d522008-04-28 17:14:26 +0100307static void reset_counters(void *arg)
Ralf Baechle54176732005-02-07 02:54:29 +0000308{
Thiemo Seufer005ca9a2008-05-06 11:23:33 +0100309 int counters = (int)(long)arg;
Ralf Baechle54176732005-02-07 02:54:29 +0000310 switch (counters) {
311 case 4:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100312 w_c0_perfctrl3(0);
313 w_c0_perfcntr3(0);
Ralf Baechle54176732005-02-07 02:54:29 +0000314 case 3:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100315 w_c0_perfctrl2(0);
316 w_c0_perfcntr2(0);
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);
Ralf Baechle54176732005-02-07 02:54:29 +0000320 case 1:
Ralf Baechle92c7b622006-06-23 18:39:00 +0100321 w_c0_perfctrl0(0);
322 w_c0_perfcntr0(0);
Ralf Baechle54176732005-02-07 02:54:29 +0000323 }
324}
325
Felix Fietkau3572a2c2012-05-02 17:33:04 +0200326static irqreturn_t mipsxx_perfcount_int(int irq, void *dev_id)
327{
328 return mipsxx_perfcount_handler();
329}
330
Ralf Baechle54176732005-02-07 02:54:29 +0000331static int __init mipsxx_init(void)
332{
333 int counters;
334
335 counters = n_counters();
Ralf Baechle9efeae92005-12-09 12:34:45 +0000336 if (counters == 0) {
337 printk(KERN_ERR "Oprofile: CPU has no performance counters\n");
Ralf Baechle54176732005-02-07 02:54:29 +0000338 return -ENODEV;
Ralf Baechle9efeae92005-12-09 12:34:45 +0000339 }
Ralf Baechle54176732005-02-07 02:54:29 +0000340
Ralf Baechle39b8d522008-04-28 17:14:26 +0100341#ifdef CONFIG_MIPS_MT_SMP
342 cpu_has_mipsmt_pertccounters = read_c0_config7() & (1<<19);
343 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
375 case CPU_74K:
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900376 op_model_mipsxx_ops.cpu_type = "mips/74K";
Chris Dearmanc6209532006-05-02 14:08:46 +0100377 break;
Ralf Baechlefcfd9802006-02-01 17:54:30 +0000378
Ralf Baechle20659882005-12-09 12:42:13 +0000379 case CPU_5KC:
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900380 op_model_mipsxx_ops.cpu_type = "mips/5K";
Ralf Baechle20659882005-12-09 12:42:13 +0000381 break;
382
Ralf Baechle714cfe72006-10-23 00:44:02 +0100383 case CPU_R10000:
384 if ((current_cpu_data.processor_id & 0xff) == 0x20)
385 op_model_mipsxx_ops.cpu_type = "mips/r10000-v2.x";
386 else
387 op_model_mipsxx_ops.cpu_type = "mips/r10000";
388 break;
389
390 case CPU_R12000:
391 case CPU_R14000:
392 op_model_mipsxx_ops.cpu_type = "mips/r12000";
393 break;
394
Mark Masonc03bc122006-01-17 12:06:32 -0800395 case CPU_SB1:
396 case CPU_SB1A:
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900397 op_model_mipsxx_ops.cpu_type = "mips/sb1";
Mark Masonc03bc122006-01-17 12:06:32 -0800398 break;
399
Kelvin Cheung2fa36392012-06-20 20:05:32 +0100400 case CPU_LOONGSON1:
401 op_model_mipsxx_ops.cpu_type = "mips/loongson1";
402 break;
403
Madhusudan Bhatc7833902012-10-31 12:01:27 +0000404 case CPU_XLR:
405 op_model_mipsxx_ops.cpu_type = "mips/xlr";
406 break;
407
Ralf Baechle54176732005-02-07 02:54:29 +0000408 default:
409 printk(KERN_ERR "Profiling unsupported for this CPU\n");
410
411 return -ENODEV;
412 }
413
Dmitri Vorobiev46684732008-04-02 03:58:38 +0400414 save_perf_irq = perf_irq;
Ralf Baechle54176732005-02-07 02:54:29 +0000415 perf_irq = mipsxx_perfcount_handler;
416
Felix Fietkau3572a2c2012-05-02 17:33:04 +0200417 if ((cp0_perfcount_irq >= 0) && (cp0_compare_irq != cp0_perfcount_irq))
418 return request_irq(cp0_perfcount_irq, mipsxx_perfcount_int,
419 0, "Perfcounter", save_perf_irq);
420
Ralf Baechle54176732005-02-07 02:54:29 +0000421 return 0;
422}
423
424static void mipsxx_exit(void)
425{
Chris Dearman795a2252007-03-01 17:58:24 +0000426 int counters = op_model_mipsxx_ops.num_counters;
Ralf Baechle5e2862e2007-12-06 09:12:28 +0000427
Felix Fietkau3572a2c2012-05-02 17:33:04 +0200428 if ((cp0_perfcount_irq >= 0) && (cp0_compare_irq != cp0_perfcount_irq))
429 free_irq(cp0_perfcount_irq, save_perf_irq);
430
Ralf Baechle5e2862e2007-12-06 09:12:28 +0000431 counters = counters_per_cpu_to_total(counters);
Ingo Molnarf6f88e92008-07-15 22:08:52 +0200432 on_each_cpu(reset_counters, (void *)(long)counters, 1);
Ralf Baechle54176732005-02-07 02:54:29 +0000433
Dmitri Vorobiev46684732008-04-02 03:58:38 +0400434 perf_irq = save_perf_irq;
Ralf Baechle54176732005-02-07 02:54:29 +0000435}
436
Atsushi Nemoto1acf1ca2006-05-23 16:42:38 +0900437struct op_mips_model op_model_mipsxx_ops = {
Ralf Baechle54176732005-02-07 02:54:29 +0000438 .reg_setup = mipsxx_reg_setup,
439 .cpu_setup = mipsxx_cpu_setup,
440 .init = mipsxx_init,
441 .exit = mipsxx_exit,
442 .cpu_start = mipsxx_cpu_start,
443 .cpu_stop = mipsxx_cpu_stop,
444};