blob: 5810ba7c142827e9babe300dcc5c2b60d4ba855e [file] [log] [blame]
Duy Truong790f06d2013-02-13 16:38:12 -08001/* Copyright (c) 2010, The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
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-v7.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 "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 PM_V7_ERR -1
50
51/*------------------------------------------------------------------------
52 * Global control bits
53------------------------------------------------------------------------*/
54#define PM_GLOBAL_ENABLE (1<<0)
55#define PM_EVENT_RESET (1<<1)
56#define PM_CYCLE_RESET (1<<2)
57#define PM_CLKDIV (1<<3)
58#define PM_GLOBAL_TRACE (1<<4)
59#define PM_DISABLE_PROHIBIT (1<<5)
60
61/*---------------------------------------------------------------------------
62 * Enable and clear bits for each event/trigger
63----------------------------------------------------------------------------*/
64#define PM_EV0_ENABLE (1<<0)
65#define PM_EV1_ENABLE (1<<1)
66#define PM_EV2_ENABLE (1<<2)
67#define PM_EV3_ENABLE (1<<3)
68#define PM_COUNT_ENABLE (1<<31)
69#define PM_ALL_ENABLE (0x8000000F)
70
71
72/*-----------------------------------------------------------------------------
73 * Overflow actions
74------------------------------------------------------------------------------*/
75#define PM_OVERFLOW_NOACTION (0)
76#define PM_OVERFLOW_HALT (1)
77#define PM_OVERFLOW_STOP (2)
78#define PM_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 PM_EVT_SW_INCREMENT 0
125#define PM_EVT_L1_I_MISS 1
126#define PM_EVT_ITLB_MISS 2
127#define PM_EVT_L1_D_MISS 3
128#define PM_EVT_L1_D_ACCESS 4
129#define PM_EVT_DTLB_MISS 5
130#define PM_EVT_DATA_READ 6
131#define PM_EVT_DATA_WRITE 7
132#define PM_EVT_INSTRUCTION 8
133#define PM_EVT_EXCEPTIONS 9
134#define PM_EVT_EXCEPTION_RET 10
135#define PM_EVT_CTX_CHANGE 11
136#define PM_EVT_PC_CHANGE 12
137#define PM_EVT_BRANCH 13
138#define PM_EVT_RETURN 14
139#define PM_EVT_UNALIGNED 15
140#define PM_EVT_BRANCH_MISS 16
141#define PM_EVT_EXTERNAL0 0x40
142#define PM_EVT_EXTERNAL1 0x41
143#define PM_EVT_EXTERNAL2 0x42
144#define PM_EVT_EXTERNAL3 0x43
145#define PM_EVT_TRACE0 0x44
146#define PM_EVT_TRACE1 0x45
147#define PM_EVT_TRACE2 0x46
148#define PM_EVT_TRACE3 0x47
149#define PM_EVT_PM0 0x48
150#define PM_EVT_PM1 0x49
151#define PM_EVT_PM2 0x4a
152#define PM_EVT_PM3 0x4b
153#define PM_EVT_LPM0_EVT0 0x4c
154#define PM_EVT_LPM0_EVT1 0x4d
155#define PM_EVT_LPM0_EVT2 0x4e
156#define PM_EVT_LPM0_EVT3 0x4f
157#define PM_EVT_LPM1_EVT0 0x50
158#define PM_EVT_LPM1_EVT1 0x51
159#define PM_EVT_LPM1_EVT2 0x52
160#define PM_EVT_LPM1_EVT3 0x53
161#define PM_EVT_LPM2_EVT0 0x54
162#define PM_EVT_LPM2_EVT1 0x55
163#define PM_EVT_LPM2_EVT2 0x56
164#define PM_EVT_LPM2_EVT3 0x57
165#define PM_EVT_L2_EVT0 0x58
166#define PM_EVT_L2_EVT1 0x59
167#define PM_EVT_L2_EVT2 0x5a
168#define PM_EVT_L2_EVT3 0x5b
169#define PM_EVT_VLP_EVT0 0x5c
170#define PM_EVT_VLP_EVT1 0x5d
171#define PM_EVT_VLP_EVT2 0x5e
172#define PM_EVT_VLP_EVT3 0x5f
173
174/*
175Type Declarations
176*/
177
178/*--------------------------------------------------------------------------
179A performance monitor trigger setup/initialization structure. Contains
180all of the fields necessary to setup a complex trigger with the internal
181performance monitor.
182---------------------------------------------------------------------------*/
183struct pm_trigger_s {
184 int index;
185 int event_type;
186 bool interrupt;
187 bool overflow_enable;
188 bool event_export;
189 unsigned char overflow_action;
190 unsigned char stop_index;
191 unsigned char reload_index;
192 unsigned char resume_index;
193 unsigned char suspend_index;
194 unsigned char start_index;
195 bool overflow_stop;
196 unsigned char stop_condition;
197 unsigned char reload_condition;
198 unsigned char resume_condition;
199 unsigned char suspend_condition;
200 unsigned char start_condition;
201};
202
203/*
204* Name and index place holder so we can display the event
205*/
206struct pm_name_s {
207 unsigned long index;
208 char *name;
209};
210
211/*
212Local Object Definitions
213*/
214
215unsigned long pm_cycle_overflow_count;
216unsigned long pm_overflow_count[PM_NUM_COUNTERS];
217
218/*---------------------------------------------------------------------------
219Max number of events read from the config registers
220---------------------------------------------------------------------------*/
221static int pm_max_events;
222
223/*--------------------------------------------------------------------------
224Storage area for each of the triggers
225*---------------------------------------------------------------------------*/
226static struct pm_trigger_s pm_triggers[4];
227
228/*--------------------------------------------------------------------------
229Names and indexes of the events
230--------------------------------------------------------------------------*/
231static struct pm_name_s pm_names[] = {
232 { PM_EVT_SW_INCREMENT, "SW Increment"},
233 { PM_EVT_L1_I_MISS, "L1 I MISS"},
234 { PM_EVT_ITLB_MISS, "L1 ITLB MISS"},
235 { PM_EVT_L1_D_MISS, "L1 D MISS"},
236 { PM_EVT_L1_D_ACCESS, "L1 D ACCESS"},
237 { PM_EVT_DTLB_MISS, "DTLB MISS"},
238 { PM_EVT_DATA_READ, "DATA READ"},
239 { PM_EVT_DATA_WRITE, "DATA WRITE"},
240 { PM_EVT_INSTRUCTION, "INSTRUCTIONS"},
241 { PM_EVT_EXCEPTIONS, "EXCEPTIONS"},
242 { PM_EVT_EXCEPTION_RET, "EXCEPTION RETURN"},
243 { PM_EVT_CTX_CHANGE, "CTX CHANGE"},
244 { PM_EVT_PC_CHANGE, "PC CHANGE"},
245 { PM_EVT_BRANCH, "BRANCH"},
246 { PM_EVT_RETURN, "RETURN"},
247 { PM_EVT_UNALIGNED, "UNALIGNED"},
248 { PM_EVT_BRANCH_MISS, "BRANCH MISS"},
249 { PM_EVT_EXTERNAL0, "EXTERNAL 0"},
250 { PM_EVT_EXTERNAL1, "EXTERNAL 1"},
251 { PM_EVT_EXTERNAL2, "EXTERNAL 2"},
252 { PM_EVT_EXTERNAL3, "EXTERNAL 3"},
253 { PM_EVT_TRACE0, "TRACE 0"},
254 { PM_EVT_TRACE1, "TRACE 1"},
255 { PM_EVT_TRACE2, "TRACE 2"},
256 { PM_EVT_TRACE3, "TRACE 3"},
257 { PM_EVT_PM0, "PM0"},
258 { PM_EVT_PM1, "PM1"},
259 { PM_EVT_PM2, "PM2"},
260 { PM_EVT_PM3, "PM3"},
261 { PM_EVT_LPM0_EVT0, "LPM0 E0"},
262 { PM_EVT_LPM0_EVT1, "LPM0 E1"},
263 { PM_EVT_LPM0_EVT2 , "LPM0 E2"},
264 { PM_EVT_LPM0_EVT3, "LPM0 E3"},
265 { PM_EVT_LPM1_EVT0, "LPM1 E0"},
266 { PM_EVT_LPM1_EVT1, "LPM1 E1"},
267 { PM_EVT_LPM1_EVT2, "LPM1 E2"},
268 { PM_EVT_LPM1_EVT3, "LPM1 E3"},
269 { PM_EVT_LPM2_EVT0, "LPM2 E0"},
270 { PM_EVT_LPM2_EVT1 , "LPM2 E1"},
271 { PM_EVT_LPM2_EVT2, "LPM2 E2"},
272 { PM_EVT_LPM2_EVT3, "LPM2 E3"},
273 { PM_EVT_L2_EVT0 , "L2 E0"},
274 { PM_EVT_L2_EVT1, "L2 E1"},
275 { PM_EVT_L2_EVT2, "L2 E2"},
276 { PM_EVT_L2_EVT3 , "L2 E3"},
277 { PM_EVT_VLP_EVT0 , "VLP E0"},
278 { PM_EVT_VLP_EVT1, "VLP E1"},
279 { PM_EVT_VLP_EVT2, "VLP E2"},
280 { PM_EVT_VLP_EVT3, "VLP E3"},
281};
282
283static int irqid;
284
285/*
286Function Definitions
287*/
288
289/*
290FUNCTION pm_find_event_name
291
292DESCRIPTION Find the name associated with the event index passed and return
293the pointer.
294
295DEPENDENCIES
296
297RETURN VALUE
298Pointer to text string containing the name of the event or pointer to
299an error string. Either way access to the returned string will not
300cause an access error.
301
302SIDE EFFECTS
303*/
304char *pm_find_event_name(unsigned long index)
305{
306 unsigned long i = 0;
307
308 while (pm_names[i].index != -1) {
309 if (pm_names[i].index == index)
310 return pm_names[i].name;
311 i++;
312 }
313 return "BAD INDEX";
314}
315
316/*
317FUNCTION pm_group_stop
318
319DESCRIPTION Stop a group of the performance monitors. Event monitor 0 is bit
3200, event monitor 1 bit 1, etc. The cycle count can also be disabled with
321bit 31. Macros are provided for all of the indexes including an ALL.
322
323DEPENDENCIES
324
325RETURN VALUE
326None
327
328SIDE EFFECTS
329Stops the performance monitoring for the index passed.
330*/
331void pm_group_stop(unsigned long mask)
332{
333 WCP15_PMCNTENCLR(mask);
334}
335
336/*
337FUNCTION pm_group_start
338
339DESCRIPTION Start a group of the performance monitors. Event monitor 0 is bit
3400, event monitor 1 bit 1, etc. The cycle count can also be enabled with
341bit 31. Macros are provided for all of the indexes including an ALL.
342
343DEPENDENCIES
344
345RETURN VALUE
346None
347
348SIDE EFFECTS
349Starts the performance monitoring for the index passed.
350*/
351void pm_group_start(unsigned long mask)
352{
353 WCP15_PMCNTENSET(mask);
354}
355
356/*
357FUNCTION pm_cycle_overflow_action
358
359DESCRIPTION Action to take for an overflow of the cycle counter.
360
361DEPENDENCIES
362
363RETURN VALUE
364None
365
366SIDE EFFECTS
367Modify the state actions for overflow
368*/
369void pm_cycle_overflow_action(int action)
370{
371 unsigned long reg = 0;
372
373 if ((action > PM_OVERFLOW_SKIP) || (action < 0))
374 return;
375
376 RCP15_PMACTLR(reg);
377 reg &= ~(1<<30); /*clear it*/
378 WCP15_PMACTLR(reg | (action<<30));
379}
380
381/*
382FUNCTION pm_get_overflow
383
384DESCRIPTION Return the overflow condition for the index passed.
385
386DEPENDENCIES
387
388RETURN VALUE
3890 no overflow
390!0 (anything else) overflow;
391
392SIDE EFFECTS
393*/
394unsigned long pm_get_overflow(int index)
395{
396 unsigned long overflow = 0;
397
398/*
399* Range check
400*/
401 if (index > pm_max_events)
402 return PM_V7_ERR;
403 RCP15_PMOVSR(overflow);
404
405 return overflow & (1<<index);
406}
407
408/*
409FUNCTION pm_get_cycle_overflow
410
411DESCRIPTION
412Returns if the cycle counter has overflowed or not.
413
414DEPENDENCIES
415
416RETURN VALUE
4170 no overflow
418!0 (anything else) overflow;
419
420SIDE EFFECTS
421*/
422unsigned long pm_get_cycle_overflow(void)
423{
424 unsigned long overflow = 0;
425
426 RCP15_PMOVSR(overflow);
427 return overflow & PM_COUNT_ENABLE;
428}
429
430/*
431FUNCTION pm_reset_overflow
432
433DESCRIPTION Reset the cycle counter overflow bit.
434
435DEPENDENCIES
436
437RETURN VALUE
438None
439
440SIDE EFFECTS
441*/
442void pm_reset_overflow(int index)
443{
444 WCP15_PMOVSR(1<<index);
445}
446
447/*
448FUNCTION pm_reset_cycle_overflow
449
450DESCRIPTION Reset the cycle counter overflow bit.
451
452DEPENDENCIES
453
454RETURN VALUE
455None
456
457SIDE EFFECTS
458*/
459void pm_reset_cycle_overflow(void)
460{
461 WCP15_PMOVSR(PM_COUNT_ENABLE);
462}
463
464/*
465FUNCTION pm_get_cycle_count
466
467DESCRIPTION return the count in the cycle count register.
468
469DEPENDENCIES
470
471RETURN VALUE
472The value in the cycle count register.
473
474SIDE EFFECTS
475*/
476unsigned long pm_get_cycle_count(void)
477{
478 unsigned long cnt = 0;
479 RCP15_PMCCNTR(cnt);
480 return cnt;
481}
482
483/*
484FUNCTION pm_reset_cycle_count
485
486DESCRIPTION reset the value in the cycle count register
487
488DEPENDENCIES
489
490RETURN VALUE
491NONE
492
493SIDE EFFECTS
494Resets the performance monitor cycle count register.
495Any interrupts period based on this overflow will be changed
496*/
497void pm_reset_cycle_count(void)
498{
499 WCP15_PMCNTENCLR(PM_COUNT_ENABLE);
500}
501
502/*
503FUNCTION pm_cycle_div_64
504
505DESCRIPTION Set the cycle counter to count every 64th cycle instead of
506every cycle when the value passed is 1, otherwise counts every cycle.
507
508DEPENDENCIES
509
510RETURN VALUE
511none
512
513SIDE EFFECTS
514Changes the rate at which cycles are counted. Anything that is reading
515the cycle count (pmGetCyucleCount) may get different results.
516*/
517void pm_cycle_div_64(int enable)
518{
519 unsigned long enables = 0;
520
521 RCP15_PMCR(enables);
522 if (enable)
523 WCP15_PMCR(enables | PM_CLKDIV);
524 else
525 WCP15_PMCR(enables & ~PM_CLKDIV);
526}
527
528/*
529FUNCTION pm_enable_cycle_counter
530
531DESCRIPTION Enable the cycle counter. Sets the bit in the enable register
532so the performance monitor counter starts up counting.
533
534DEPENDENCIES
535
536RETURN VALUE
537none
538
539SIDE EFFECTS
540*/
541void pm_enable_cycle_counter(void)
542{
543/*
544* Enable the counter.
545*/
546 WCP15_PMCNTENSET(PM_COUNT_ENABLE);
547}
548
549/*
550FUNCTION pm_disable_counter
551
552DESCRIPTION Disable a single counter based on the index passed.
553
554DEPENDENCIES
555
556RETURN VALUE
557none
558
559SIDE EFFECTS
560Any triggers that are based on the stoped counter may not trigger...
561*/
562void pm_disable_counter(int index)
563{
564 /*
565 * Range check
566 */
567 if (index > pm_max_events)
568 return;
569 WCP15_PMCNTENCLR(1<<index);
570}
571
572/*
573FUNCTION pm_enable_counter
574
575DESCRIPTION Enable the counter with the index passed.
576
577DEPENDENCIES
578
579RETURN VALUE
580none.
581
582SIDE EFFECTS
583*/
584void pm_enable_counter(int index)
585{
586 /*
587 * Range check
588 */
589 if (index > pm_max_events)
590 return;
591 WCP15_PMCNTENSET(1<<index);
592}
593
594/*
595FUNCTION pm_set_count
596
597DESCRIPTION Set the number of events in a register, used for resets
598passed.
599
600DEPENDENCIES
601
602RETURN VALUE
603-1 if the index is out of range
604
605SIDE EFFECTS
606*/
607int pm_set_count(int index, unsigned long new_value)
608{
609 unsigned long reg = 0;
610
611/*
612* Range check
613*/
614 if (index > pm_max_events)
615 return PM_V7_ERR;
616
617/*
618* Lock, select the index and read the count...unlock
619*/
620 PM_LOCK();
621 WCP15_PMSELR(index);
622 WCP15_PMXEVCNTR(new_value);
623 PM_UNLOCK();
624 return reg;
625}
626
627int pm_reset_count(int index)
628{
629 return pm_set_count(index, 0);
630}
631
632/*
633FUNCTION pm_get_count
634
635DESCRIPTION Return the number of events that have happened for the index
636passed.
637
638DEPENDENCIES
639
640RETURN VALUE
641-1 if the index is out of range
642The number of events if inrange
643
644SIDE EFFECTS
645*/
646unsigned long pm_get_count(int index)
647{
648 unsigned long reg = 0;
649
650/*
651* Range check
652*/
653 if (index > pm_max_events)
654 return PM_V7_ERR;
655
656/*
657* Lock, select the index and read the count...unlock
658*/
659 PM_LOCK();
660 WCP15_PMSELR(index);
661 RCP15_PMXEVCNTR(reg);
662 PM_UNLOCK();
663 return reg;
664}
665
666/*
667FUNCTION pm_show_event_info
668
669DESCRIPTION Display (print) the information about the event at the index
670passed. Shows the index, name and count if a valid index is passed. If
671the index is not valid, then nothing is displayed.
672
673DEPENDENCIES
674
675RETURN VALUE
676None
677
678SIDE EFFECTS
679*/
680void pm_show_event_info(unsigned long index)
681{
682 unsigned long count;
683 unsigned long event_type;
684
685 if (index > pm_max_events)
686 return;
687 if (pm_triggers[index].index > pm_max_events)
688 return;
689
690 count = pm_get_count(index);
691 event_type = pm_triggers[index].event_type;
692
693 PRINT("Event %ld Trigger %s(%ld) count:%ld\n", index,
694 pm_find_event_name(event_type), event_type, count);
695}
696
697/*
698FUNCTION pm_event_init
699
700DESCRIPTION Given the struct pm_trigger_s info passed, configure the event.
701This can be a complex trigger or a simple trigger. Any old values in the
702event are lost.
703
704DEPENDENCIES
705
706RETURN VALUE
707status
708
709SIDE EFFECTS
710stops and clears the event at the index passed.
711*/
712int pm_event_init(struct pm_trigger_s *data)
713{
714 unsigned long trigger;
715 unsigned long actlr = 0;
716
717 if (0 == data)
718 return PM_V7_ERR;
719 if (data->index > pm_max_events)
720 return PM_V7_ERR;
721
722 /*
723 * Setup the trigger based ont he passed values
724 */
725 trigger = ((data->overflow_enable&1)<<31) |
726 ((data->event_export&1)<<30) |
727 ((data->stop_index&3)<<PM_STOP_SHIFT) |
728 ((data->reload_index&3)<<PM_RELOAD_SHIFT) |
729 ((data->resume_index&3)<<PM_RESUME_SHIFT) |
730 ((data->suspend_index&3)<<PM_SUSPEND_SHIFT) |
731 ((data->start_index&3)<<PM_START_SHIFT) |
732 ((data->overflow_stop&1)<<PM_STOPALL_SHIFT) |
733 ((data->stop_condition&7)<<PM_STOPCOND_SHIFT) |
734 ((data->reload_condition&7)<<PM_RELOADCOND_SHIFT) |
735 ((data->resume_condition&7)<<PM_RESUMECOND_SHIFT) |
736 ((data->suspend_condition&7)<<PM_SUSPENDCOND_SHIFT) |
737 ((data->start_condition&7)<<PM_STARTCOND_SHIFT);
738
739 /*
740 * Disable this counter while we are updating.
741 */
742 pm_disable_counter(data->index);
743
744 /*
745 * Lock, select the bank, set the trigger event and the event type
746 * then unlock.
747 */
748 PM_LOCK();
749 RCP15_PMACTLR(actlr);
750 actlr &= ~(3<<(data->index<<1));
751 WCP15_PMACTLR(actlr | ((data->overflow_action&3) << (data->index<<1)));
752 WCP15_PMSELR(data->index);
753 WCP15_PMXEVTYPER(data->event_type);
754 WCP15_PMXEVCNTCR(trigger);
755 PM_UNLOCK();
756
757 /*
758 * Make a copy of the trigger so we know what it is when/if it triggers.
759 */
760 memcpy(&pm_triggers[data->index], data, sizeof(*data));
761
762 /*
763 * We do not re-enable this here so events can be started together with
764 * pm_group_start() that way an accurate measure can be taken...
765 */
766
767 return 0;
768}
769
770int pm_set_event(int index, unsigned long event)
771{
772 unsigned long reg = 0;
773
774 /*
775 * Range check
776 */
777 if (index > pm_max_events)
778 return PM_V7_ERR;
779
780 /*
781 * Lock, select the index and read the count...unlock
782 */
783 PM_LOCK();
784 WCP15_PMSELR(index);
785 WCP15_PMXEVTYPER(event);
786 PM_UNLOCK();
787 return reg;
788}
789
790/*
791FUNCTION pm_set_local_iu
792
793DESCRIPTION Set the local IU triggers. Note that the MSB determines if
794 these are enabled or not.
795
796DEPENDENCIES
797
798RETURN VALUE
799 NONE
800
801SIDE EFFECTS
802*/
803void pm_set_local_iu(unsigned long value)
804{
805 WCP15_LPM0EVTYPER(value);
806}
807
808/*
809FUNCTION pm_set_local_iu
810
811DESCRIPTION Set the local IU triggers. Note that the MSB determines if
812 these are enabled or not.
813
814DEPENDENCIES
815
816RETURN VALUE
817 NONE
818
819SIDE EFFECTS
820*/
821void pm_set_local_xu(unsigned long value)
822{
823 WCP15_LPM1EVTYPER(value);
824}
825
826/*
827FUNCTION pm_set_local_su
828
829DESCRIPTION Set the local SU triggers. Note that the MSB determines if
830 these are enabled or not.
831
832DEPENDENCIES
833
834RETURN VALUE
835 NONE
836
837SIDE EFFECTS
838*/
839void pm_set_local_su(unsigned long value)
840{
841 WCP15_LPM2EVTYPER(value);
842}
843
844/*
845FUNCTION pm_set_local_l2
846
847DESCRIPTION Set the local L2 triggers. Note that the MSB determines if
848 these are enabled or not.
849
850DEPENDENCIES
851
852RETURN VALUE
853 NONE
854
855SIDE EFFECTS
856*/
857void pm_set_local_l2(unsigned long value)
858{
859 WCP15_L2LPMEVTYPER(value);
860}
861
862/*
863FUNCTION pm_set_local_vu
864
865DESCRIPTION Set the local VU triggers. Note that the MSB determines if
866 these are enabled or not.
867
868DEPENDENCIES
869
870RETURN VALUE
871 NONE
872
873SIDE EFFECTS
874*/
875void pm_set_local_vu(unsigned long value)
876{
877 WCP15_VLPMEVTYPER(value);
878}
879
880/*
881FUNCTION pm_isr
882
883DESCRIPTION:
884 Performance Monitor interrupt service routine to capture overflows
885
886DEPENDENCIES
887
888RETURN VALUE
889
890SIDE EFFECTS
891*/
892static irqreturn_t pm_isr(int irq, void *d)
893{
894 int i;
895
896 for (i = 0; i < PM_NUM_COUNTERS; i++) {
897 if (pm_get_overflow(i)) {
898 pm_overflow_count[i]++;
899 pm_reset_overflow(i);
900 }
901 }
902
903 if (pm_get_cycle_overflow()) {
904 pm_cycle_overflow_count++;
905 pm_reset_cycle_overflow();
906 }
907
908 return IRQ_HANDLED;
909}
910
911
912void pm_stop_all(void)
913{
914 WCP15_PMCNTENCLR(0xFFFFFFFF);
915}
916
917void pm_reset_all(void)
918{
919 WCP15_PMCR(0xF);
920 WCP15_PMOVSR(PM_ALL_ENABLE); /* overflow clear */
921}
922
923void pm_start_all(void)
924{
925 WCP15_PMCNTENSET(PM_ALL_ENABLE);
926}
927
928/*
929FUNCTION pm_initialize
930
931DESCRIPTION Initialize the performanca monitoring for the v7 processor.
932 Ensures the cycle count is running and the event counters are enabled.
933
934DEPENDENCIES
935
936RETURN VALUE
937 NONE
938
939SIDE EFFECTS
940*/
941void pm_initialize(void)
942{
943 unsigned long reg = 0;
944 unsigned char imp;
945 unsigned char id;
946 unsigned char num;
947 unsigned long enables = 0;
948 static int initialized;
949
950 if (initialized)
951 return;
952 initialized = 1;
953
954 irqid = INT_ARMQC_PERFMON;
955 RCP15_PMCR(reg);
956 imp = (reg>>24) & 0xFF;
957 id = (reg>>16) & 0xFF;
958 pm_max_events = num = (reg>>11) & 0xFF;
959 PRINT("V7Performance Monitor Capabilities\n");
960 PRINT(" Implementor %c(%d)\n", imp, imp);
961 PRINT(" Id %d %x\n", id, id);
962 PRINT(" Num Events %d %x\n", num, num);
963 PRINT("\nCycle counter enabled by default...\n");
964
965 /*
966 * Global enable, ensure the global enable is set so all
967 * subsequent actions take effect. Also resets the counts
968 */
969 RCP15_PMCR(enables);
970 WCP15_PMCR(enables | PM_GLOBAL_ENABLE | PM_EVENT_RESET |
971 PM_CYCLE_RESET | PM_CLKDIV);
972
973 /*
974 * Enable access from user space
975 */
976 WCP15_PMUSERENR(1);
977 WCP15_PMACTLR(1);
978
979 /*
980 * Install interrupt handler and the enable the interrupts
981 */
982 pm_reset_cycle_overflow();
983 pm_reset_overflow(0);
984 pm_reset_overflow(1);
985 pm_reset_overflow(2);
986 pm_reset_overflow(3);
987
988 if (0 != request_irq(irqid, pm_isr, 0, "perfmon", 0))
989 printk(KERN_ERR "%s:%d request_irq returned error\n",
990 __FILE__, __LINE__);
991 WCP15_PMINTENSET(PM_ALL_ENABLE);
992 /*
993 * Enable the cycle counter. Default, count 1:1 no divisor.
994 */
995 pm_enable_cycle_counter();
996
997}
998
999void pm_free_irq(void)
1000{
1001 free_irq(irqid, 0);
1002}
1003
1004void pm_deinitialize(void)
1005{
1006 unsigned long enables = 0;
1007 RCP15_PMCR(enables);
1008 WCP15_PMCR(enables & ~PM_GLOBAL_ENABLE);
1009}