blob: 5417fc7f6a5d30f992095ebf20c34f23a1a0555e [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13/*
14perf-smp.c
15DESCRIPTION
16Manipulation, initialization of the ARMV7 Performance counter register.
17
18
19EXTERNALIZED FUNCTIONS
20
21INITIALIZATION AND SEQUENCING REQUIREMENTS
22*/
23
24/*
25INCLUDE FILES FOR MODULE
26*/
27#include <linux/kernel.h>
28#include <linux/string.h>
29#include <linux/time.h>
30#include <linux/device.h>
31#include <linux/interrupt.h>
32
33#include <asm/io.h>
34#include <asm/irq.h>
35#include "l2_cp15_registers.h"
36
37/*
38DEFINITIONS AND DECLARATIONS FOR MODULE
39
40This section contains definitions for constants, macros, types, variables
41and other items needed by this module.
42*/
43
44/*
45 Constant / Define Declarations
46*/
47
48#define PM_NUM_COUNTERS 4
49#define L2_PM_ERR -1
50
51/*------------------------------------------------------------------------
52 * Global control bits
53------------------------------------------------------------------------*/
54#define PM_L2_GLOBAL_ENABLE (1<<0)
55#define PM_L2_EVENT_RESET (1<<1)
56#define PM_L2_CYCLE_RESET (1<<2)
57#define PM_L2_CLKDIV (1<<3)
58#define PM_L2_GLOBAL_TRACE (1<<4)
59#define PM_L2_DISABLE_PROHIBIT (1<<5)
60
61/*---------------------------------------------------------------------------
62 * Enable and clear bits for each event/trigger
63----------------------------------------------------------------------------*/
64#define PM_L2EV0_ENABLE (1<<0)
65#define PM_L2EV1_ENABLE (1<<1)
66#define PM_L2EV2_ENABLE (1<<2)
67#define PM_L2EV3_ENABLE (1<<3)
68#define PM_L2_COUNT_ENABLE (1<<31)
69#define PM_L2_ALL_ENABLE (0x8000000F)
70
71
72/*-----------------------------------------------------------------------------
73 * Overflow actions
74------------------------------------------------------------------------------*/
75#define PM_L2_OVERFLOW_NOACTION (0)
76#define PM_L2_OVERFLOW_HALT (1)
77#define PM_L2_OVERFLOW_STOP (2)
78#define PM_L2_OVERFLOW_SKIP (3)
79
80/*
81 * Shifts for each trigger type
82 */
83#define PM_STOP_SHIFT 24
84#define PM_RELOAD_SHIFT 22
85#define PM_RESUME_SHIFT 20
86#define PM_SUSPEND_SHIFT 18
87#define PM_START_SHIFT 16
88#define PM_STOPALL_SHIFT 15
89#define PM_STOPCOND_SHIFT 12
90#define PM_RELOADCOND_SHIFT 9
91#define PM_RESUMECOND_SHIFT 6
92#define PM_SUSPENDCOND_SHIFT 3
93#define PM_STARTCOND_SHIFT 0
94
95
96/*---------------------------------------------------------------------------
97External control register. What todo when various events happen.
98Triggering events, etc.
99----------------------------------------------------------------------------*/
100#define PM_EXTTR0 0
101#define PM_EXTTR1 1
102#define PM_EXTTR2 2
103#define PM_EXTTR3 3
104
105#define PM_COND_NO_STOP 0
106#define PM_COND_STOP_CNTOVRFLW 1
107#define PM_COND_STOP_EXTERNAL 4
108#define PM_COND_STOP_TRACE 5
109#define PM_COND_STOP_EVOVRFLW 6
110#define PM_COND_STOP_EVTYPER 7
111
112/*--------------------------------------------------------------------------
113Protect against concurrent access. There is an index register that is
114used to select the appropriate bank of registers. If multiple processes
115are writting this at different times we could have a mess...
116---------------------------------------------------------------------------*/
117#define PM_LOCK()
118#define PM_UNLOCK()
119#define PRINT printk
120
121/*--------------------------------------------------------------------------
122The Event definitions
123--------------------------------------------------------------------------*/
124#define L2PM_EVT_PM0_EVT0 0x00
125#define L2PM_EVT_PM0_EVT1 0x01
126#define L2PM_EVT_PM0_EVT2 0x02
127#define L2PM_EVT_PM0_EVT3 0x03
128#define L2PM_EVT_PM1_EVT0 0x04
129#define L2PM_EVT_PM1_EVT1 0x05
130#define L2PM_EVT_PM1_EVT2 0x06
131#define L2PM_EVT_PM1_EVT3 0x07
132#define L2PM_EVT_PM2_EVT0 0x08
133#define L2PM_EVT_PM2_EVT1 0x09
134#define L2PM_EVT_PM2_EVT2 0x0a
135#define L2PM_EVT_PM2_EVT3 0x0b
136#define L2PM_EVT_PM3_EVT0 0x0c
137#define L2PM_EVT_PM3_EVT1 0x0d
138#define L2PM_EVT_PM3_EVT2 0x0e
139#define L2PM_EVT_PM3_EVT3 0x0f
140#define L2PM_EVT_PM4_EVT0 0x10
141#define L2PM_EVT_PM4_EVT1 0x11
142#define L2PM_EVT_PM4_EVT2 0x12
143#define L2PM_EVT_PM4_EVT3 0x13
144
145/*
146Type Declarations
147*/
148
149/*
150Local Object Definitions
151*/
152
153unsigned long l2_pm_cycle_overflow_count;
154unsigned long l2_pm_overflow_count[PM_NUM_COUNTERS];
155
156/*---------------------------------------------------------------------------
157Max number of events read from the config registers
158---------------------------------------------------------------------------*/
159static int pm_l2_max_events;
160
161static int irqid;
162
163/*
164Function Definitions
165*/
166
167/*
168FUNCTION l2_pm_group_stop
169
170DESCRIPTION Stop a group of the performance monitors. Event monitor 0 is bit
1710, event monitor 1 bit 1, etc. The cycle count can also be disable with
172bit 31. Macros are provided for all of the indexes including an ALL.
173
174DEPENDENCIES
175
176RETURN VALUE
177None
178
179SIDE EFFECTS
180Stops the performance monitoring for the index passed.
181*/
182void pm_l2_group_stop(unsigned long mask)
183{
184 WCP15_L2PMCNTENCLR(mask);
185}
186
187/*
188FUNCTION l2_pm_group_start
189
190DESCRIPTION Start a group of the performance monitors. Event monitor 0 is bit
1910, event monitor 1 bit 1, etc. The cycle count can also be enabled with
192bit 31. Macros are provided for all of the indexes including an ALL.
193
194DEPENDENCIES
195
196RETURN VALUE
197None
198
199SIDE EFFECTS
200Starts the performance monitoring for the index passed.
201*/
202void pm_l2_group_start(unsigned long mask)
203{
204 WCP15_L2PMCNTENSET(mask);
205}
206
207/*
208FUNCTION l2_pm_get_overflow
209
210DESCRIPTION Return the overflow condition for the index passed.
211
212DEPENDENCIES
213
214RETURN VALUE
2150 no overflow
216!0 (anything else) overflow;
217
218SIDE EFFECTS
219*/
220unsigned long l2_pm_get_overflow(int index)
221{
222 unsigned long overflow = 0;
223
224/*
225* Range check
226*/
227 if (index > pm_l2_max_events)
228 return L2_PM_ERR;
229 RCP15_L2PMOVSR(overflow);
230
231 return overflow & (1<<index);
232}
233
234/*
235FUNCTION l2_pm_get_cycle_overflow
236
237DESCRIPTION
238Returns if the cycle counter has overflowed or not.
239
240DEPENDENCIES
241
242RETURN VALUE
2430 no overflow
244!0 (anything else) overflow;
245
246SIDE EFFECTS
247*/
248unsigned long l2_pm_get_cycle_overflow(void)
249{
250 unsigned long overflow = 0;
251
252 RCP15_L2PMOVSR(overflow);
253 return overflow & PM_L2_COUNT_ENABLE;
254}
255
256/*
257FUNCTION l2_pm_reset_overflow
258
259DESCRIPTION Reset the cycle counter overflow bit.
260
261DEPENDENCIES
262
263RETURN VALUE
264None
265
266SIDE EFFECTS
267*/
268void l2_pm_reset_overflow(int index)
269{
270 WCP15_L2PMOVSR(1<<index);
271}
272
273/*
274FUNCTION l2_pm_reset_cycle_overflow
275
276DESCRIPTION Reset the cycle counter overflow bit.
277
278DEPENDENCIES
279
280RETURN VALUE
281None
282
283SIDE EFFECTS
284*/
285void l2_pm_reset_cycle_overflow(void)
286{
287 WCP15_L2PMOVSR(PM_L2_COUNT_ENABLE);
288}
289
290/*
291FUNCTION l2_pm_get_cycle_count
292
293DESCRIPTION return the count in the cycle count register.
294
295DEPENDENCIES
296
297RETURN VALUE
298The value in the cycle count register.
299
300SIDE EFFECTS
301*/
302unsigned long l2_pm_get_cycle_count(void)
303{
304 unsigned long cnt = 0;
305 RCP15_L2PMCCNTR(cnt);
306 return cnt;
307}
308
309/*
310FUNCTION l2_pm_reset_cycle_count
311
312DESCRIPTION reset the value in the cycle count register
313
314DEPENDENCIES
315
316RETURN VALUE
317NONE
318
319SIDE EFFECTS
320Resets the performance monitor cycle count register.
321Any interrupts period based on this overflow will be changed
322*/
323void l2_pm_reset_cycle_count(void)
324{
325 WCP15_L2PMCNTENCLR(PM_L2_COUNT_ENABLE);
326}
327
328/*
329FUNCTION l2_pm_cycle_div_64
330
331DESCRIPTION Set the cycle counter to count every 64th cycle instead of
332every cycle when the value passed is 1, otherwise counts every cycle.
333
334DEPENDENCIES
335
336RETURN VALUE
337none
338
339SIDE EFFECTS
340Changes the rate at which cycles are counted. Anything that is reading
341the cycle count (pmGetCyucleCount) may get different results.
342*/
343void l2_pm_cycle_div_64(int enable)
344{
345 unsigned long enables = 0;
346
347 RCP15_L2PMCR(enables);
348 if (enable)
349 WCP15_L2PMCR(enables | PM_L2_CLKDIV);
350 else
351 WCP15_L2PMCR(enables & ~PM_L2_CLKDIV);
352}
353
354/*
355FUNCTION l2_pm_enable_cycle_counter
356
357DESCRIPTION Enable the cycle counter. Sets the bit in the enable register
358so the performance monitor counter starts up counting.
359
360DEPENDENCIES
361
362RETURN VALUE
363none
364
365SIDE EFFECTS
366*/
367void l2_pm_enable_cycle_counter(void)
368{
369/*
370* Enable the counter.
371*/
372 WCP15_L2PMCNTENSET(PM_L2_COUNT_ENABLE);
373}
374
375/*
376FUNCTION l2_pm_disable_counter
377
378DESCRIPTION Disable a single counter based on the index passed.
379
380DEPENDENCIES
381
382RETURN VALUE
383none
384
385SIDE EFFECTS
386Any triggers that are based on the stoped counter may not trigger...
387*/
388void l2_pm_disable_counter(int index)
389{
390 /*
391 * Range check
392 */
393 if (index > pm_l2_max_events)
394 return;
395 WCP15_L2PMCNTENCLR(1<<index);
396}
397
398/*
399FUNCTION l2_pm_enable_counter
400
401DESCRIPTION Enable the counter with the index passed.
402
403DEPENDENCIES
404
405RETURN VALUE
406none.
407
408SIDE EFFECTS
409*/
410void l2_pm_enable_counter(int index)
411{
412 /*
413 * Range check
414 */
415 if (index > pm_l2_max_events)
416 return;
417 WCP15_L2PMCNTENSET(1<<index);
418}
419
420/*
421FUNCTION l2_pm_set_count
422
423DESCRIPTION Set the number of events in a register, used for resets
424passed.
425
426DEPENDENCIES
427
428RETURN VALUE
429-1 if the index is out of range
430
431SIDE EFFECTS
432*/
433int l2_pm_set_count(int index, unsigned long new_value)
434{
435 unsigned long reg = 0;
436
437/*
438* Range check
439*/
440 if (index > pm_l2_max_events)
441 return L2_PM_ERR;
442
443/*
444* Lock, select the index and read the count...unlock
445*/
446 PM_LOCK();
447 WCP15_L2PMSELR(index);
448 WCP15_L2PMXEVCNTR(new_value);
449 PM_UNLOCK();
450 return reg;
451}
452
453int l2_pm_reset_count(int index)
454{
455 return l2_pm_set_count(index, 0);
456}
457
458/*
459FUNCTION l2_pm_get_count
460
461DESCRIPTION Return the number of events that have happened for the index
462passed.
463
464DEPENDENCIES
465
466RETURN VALUE
467-1 if the index is out of range
468The number of events if inrange
469
470SIDE EFFECTS
471*/
472unsigned long l2_pm_get_count(int index)
473{
474 unsigned long reg = 0;
475
476/*
477* Range check
478*/
479 if (index > pm_l2_max_events)
480 return L2_PM_ERR;
481
482/*
483* Lock, select the index and read the count...unlock
484*/
485 PM_LOCK();
486 WCP15_L2PMSELR(index);
487 RCP15_L2PMXEVCNTR(reg);
488 PM_UNLOCK();
489 return reg;
490}
491
492unsigned long get_filter_code(unsigned long event)
493{
494 if (event == 0x0 || event == 0x4 || event == 0x08
495 || event == 0x0c || event == 0x10)
496 return 0x0001003f;
497 else if (event == 0x1 || event == 0x5 || event == 0x09
498 || event == 0x0d || event == 0x11)
499 return 0x0002003f;
500 else if (event == 0x2 || event == 0x6 || event == 0x0a
501 || event == 0x0e || event == 0x12)
502 return 0x0004003f;
503 else if (event == 0x3 || event == 0x7 || event == 0x0b
504 || event == 0x0f || event == 0x13)
505 return 0x0008003f;
506 else
507 return 0;
508}
509
510int l2_pm_set_event(int index, unsigned long event)
511{
512 unsigned long reg = 0;
513
514 /*
515 * Range check
516 */
517 if (index > pm_l2_max_events)
518 return L2_PM_ERR;
519
520 /*
521 * Lock, select the index and read the count...unlock
522 */
523 PM_LOCK();
524 WCP15_L2PMSELR(index);
525 WCP15_L2PMXEVTYPER(event);
526 /* WCP15_L2PMXEVFILTER(get_filter_code(event)); */
527 WCP15_L2PMXEVFILTER(0x000f003f);
528 PM_UNLOCK();
529 return reg;
530}
531
532/*
533FUNCTION pm_set_local_bu
534
535DESCRIPTION Set the local BU triggers. Note that the MSB determines if
536 these are enabled or not.
537
538DEPENDENCIES
539
540RETURN VALUE
541 NONE
542
543SIDE EFFECTS
544*/
545void pm_set_local_bu(unsigned long value)
546{
547 WCP15_L2PMEVTYPER0(value);
548}
549
550/*
551FUNCTION pm_set_local_cb
552
553DESCRIPTION Set the local CB triggers. Note that the MSB determines if
554 these are enabled or not.
555
556DEPENDENCIES
557
558RETURN VALUE
559 NONE
560
561SIDE EFFECTS
562*/
563void pm_set_local_cb(unsigned long value)
564{
565 WCP15_L2PMEVTYPER1(value);
566}
567
568/*
569FUNCTION pm_set_local_mp
570
571DESCRIPTION Set the local MP triggers. Note that the MSB determines if
572 these are enabled or not.
573
574DEPENDENCIES
575
576RETURN VALUE
577 NONE
578
579SIDE EFFECTS
580*/
581void pm_set_local_mp(unsigned long value)
582{
583 WCP15_L2PMEVTYPER2(value);
584}
585
586/*
587FUNCTION pm_set_local_sp
588
589DESCRIPTION Set the local SP triggers. Note that the MSB determines if
590 these are enabled or not.
591
592DEPENDENCIES
593
594RETURN VALUE
595 NONE
596
597SIDE EFFECTS
598*/
599void pm_set_local_sp(unsigned long value)
600{
601 WCP15_L2PMEVTYPER3(value);
602}
603
604/*
605FUNCTION pm_set_local_scu
606
607DESCRIPTION Set the local SCU triggers. Note that the MSB determines if
608 these are enabled or not.
609
610DEPENDENCIES
611
612RETURN VALUE
613 NONE
614
615SIDE EFFECTS
616*/
617void pm_set_local_scu(unsigned long value)
618{
619 WCP15_L2PMEVTYPER4(value);
620}
621
622/*
623FUNCTION l2_pm_isr
624
625DESCRIPTION:
626 Performance Monitor interrupt service routine to capture overflows
627
628DEPENDENCIES
629
630RETURN VALUE
631
632SIDE EFFECTS
633*/
634static irqreturn_t l2_pm_isr(int irq, void *d)
635{
636 int i;
637
638 for (i = 0; i < PM_NUM_COUNTERS; i++) {
639 if (l2_pm_get_overflow(i)) {
640 l2_pm_overflow_count[i]++;
641 l2_pm_reset_overflow(i);
642 }
643 }
644
645 if (l2_pm_get_cycle_overflow()) {
646 l2_pm_cycle_overflow_count++;
647 l2_pm_reset_cycle_overflow();
648 }
649
650 return IRQ_HANDLED;
651}
652
653
654void l2_pm_stop_all(void)
655{
656 WCP15_L2PMCNTENCLR(0xFFFFFFFF);
657}
658
659void l2_pm_reset_all(void)
660{
661 WCP15_L2PMCR(0xF);
662 WCP15_L2PMOVSR(PM_L2_ALL_ENABLE); /* overflow clear */
663}
664
665void l2_pm_start_all(void)
666{
667 WCP15_L2PMCNTENSET(PM_L2_ALL_ENABLE);
668}
669
670/*
671FUNCTION l2_pm_initialize
672
673DESCRIPTION Initialize the performanca monitoring for the v7 processor.
674 Ensures the cycle count is running and the event counters are enabled.
675
676DEPENDENCIES
677
678RETURN VALUE
679 NONE
680
681SIDE EFFECTS
682*/
683void l2_pm_initialize(void)
684{
685 unsigned long reg = 0;
686 unsigned char imp;
687 unsigned char id;
688 unsigned char num;
689 unsigned long enables = 0;
690 static int initialized;
691
692 if (initialized)
693 return;
694 initialized = 1;
695
696 irqid = SC_SICL2PERFMONIRPTREQ;
697 RCP15_L2PMCR(reg);
698 imp = (reg>>24) & 0xFF;
699 id = (reg>>16) & 0xFF;
700 pm_l2_max_events = num = (reg>>11) & 0xFF;
701 PRINT("V7 MP L2SCU Performance Monitor Capabilities\n");
702 PRINT(" Implementor %c(%d)\n", imp, imp);
703 PRINT(" Id %d %x\n", id, id);
704 PRINT(" Num Events %d %x\n", num, num);
705 PRINT("\nCycle counter enabled by default...\n");
706
707 /*
708 * Global enable, ensure the global enable is set so all
709 * subsequent actions take effect. Also resets the counts
710 */
711 RCP15_L2PMCR(enables);
712 WCP15_L2PMCR(enables | PM_L2_GLOBAL_ENABLE | PM_L2_EVENT_RESET |
713 PM_L2_CYCLE_RESET | PM_L2_CLKDIV);
714
715 /*
716 * Enable access from user space
717 */
718
719 /*
720 * Install interrupt handler and the enable the interrupts
721 */
722 l2_pm_reset_cycle_overflow();
723 l2_pm_reset_overflow(0);
724 l2_pm_reset_overflow(1);
725 l2_pm_reset_overflow(2);
726 l2_pm_reset_overflow(3);
727 l2_pm_reset_overflow(4);
728
729 if (0 != request_irq(irqid, l2_pm_isr, 0, "l2perfmon", 0))
730 printk(KERN_ERR "%s:%d request_irq returned error\n",
731 __FILE__, __LINE__);
732 WCP15_L2PMINTENSET(PM_L2_ALL_ENABLE);
733 /*
734 * Enable the cycle counter. Default, count 1:1 no divisor.
735 */
736 l2_pm_enable_cycle_counter();
737
738}
739
740void l2_pm_free_irq(void)
741{
742 free_irq(irqid, 0);
743}
744
745void l2_pm_deinitialize(void)
746{
747 unsigned long enables = 0;
748 RCP15_L2PMCR(enables);
749 WCP15_L2PMCR(enables & ~PM_L2_GLOBAL_ENABLE);
750}
751