Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee13...
[linux-2.6] / arch / powerpc / kernel / perfmon_fsl_booke.c
1 /* arch/powerpc/kernel/perfmon_fsl_booke.c
2  * Freescale Book-E Performance Monitor code
3  *
4  * Author: Andy Fleming
5  * Copyright (c) 2004 Freescale Semiconductor, Inc
6  *
7  *  This program is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU General Public License
9  *  as published by the Free Software Foundation; either version
10  *  2 of the License, or (at your option) any later version.
11  */
12
13 #include <linux/errno.h>
14 #include <linux/sched.h>
15 #include <linux/kernel.h>
16 #include <linux/mm.h>
17 #include <linux/stddef.h>
18 #include <linux/unistd.h>
19 #include <linux/ptrace.h>
20 #include <linux/slab.h>
21 #include <linux/user.h>
22 #include <linux/a.out.h>
23 #include <linux/interrupt.h>
24 #include <linux/init.h>
25 #include <linux/module.h>
26 #include <linux/prctl.h>
27
28 #include <asm/pgtable.h>
29 #include <asm/uaccess.h>
30 #include <asm/system.h>
31 #include <asm/io.h>
32 #include <asm/reg.h>
33 #include <asm/xmon.h>
34 #include <asm/pmc.h>
35
36 static inline u32 get_pmlca(int ctr);
37 static inline void set_pmlca(int ctr, u32 pmlca);
38
39 static inline u32 get_pmlca(int ctr)
40 {
41         u32 pmlca;
42
43         switch (ctr) {
44                 case 0:
45                         pmlca = mfpmr(PMRN_PMLCA0);
46                         break;
47                 case 1:
48                         pmlca = mfpmr(PMRN_PMLCA1);
49                         break;
50                 case 2:
51                         pmlca = mfpmr(PMRN_PMLCA2);
52                         break;
53                 case 3:
54                         pmlca = mfpmr(PMRN_PMLCA3);
55                         break;
56                 default:
57                         panic("Bad ctr number\n");
58         }
59
60         return pmlca;
61 }
62
63 static inline void set_pmlca(int ctr, u32 pmlca)
64 {
65         switch (ctr) {
66                 case 0:
67                         mtpmr(PMRN_PMLCA0, pmlca);
68                         break;
69                 case 1:
70                         mtpmr(PMRN_PMLCA1, pmlca);
71                         break;
72                 case 2:
73                         mtpmr(PMRN_PMLCA2, pmlca);
74                         break;
75                 case 3:
76                         mtpmr(PMRN_PMLCA3, pmlca);
77                         break;
78                 default:
79                         panic("Bad ctr number\n");
80         }
81 }
82
83 void init_pmc_stop(int ctr)
84 {
85         u32 pmlca = (PMLCA_FC | PMLCA_FCS | PMLCA_FCU |
86                         PMLCA_FCM1 | PMLCA_FCM0);
87         u32 pmlcb = 0;
88
89         switch (ctr) {
90                 case 0:
91                         mtpmr(PMRN_PMLCA0, pmlca);
92                         mtpmr(PMRN_PMLCB0, pmlcb);
93                         break;
94                 case 1:
95                         mtpmr(PMRN_PMLCA1, pmlca);
96                         mtpmr(PMRN_PMLCB1, pmlcb);
97                         break;
98                 case 2:
99                         mtpmr(PMRN_PMLCA2, pmlca);
100                         mtpmr(PMRN_PMLCB2, pmlcb);
101                         break;
102                 case 3:
103                         mtpmr(PMRN_PMLCA3, pmlca);
104                         mtpmr(PMRN_PMLCB3, pmlcb);
105                         break;
106                 default:
107                         panic("Bad ctr number!\n");
108         }
109 }
110
111 void set_pmc_event(int ctr, int event)
112 {
113         u32 pmlca;
114
115         pmlca = get_pmlca(ctr);
116
117         pmlca = (pmlca & ~PMLCA_EVENT_MASK) |
118                 ((event << PMLCA_EVENT_SHIFT) &
119                  PMLCA_EVENT_MASK);
120
121         set_pmlca(ctr, pmlca);
122 }
123
124 void set_pmc_user_kernel(int ctr, int user, int kernel)
125 {
126         u32 pmlca;
127
128         pmlca = get_pmlca(ctr);
129
130         if(user)
131                 pmlca &= ~PMLCA_FCU;
132         else
133                 pmlca |= PMLCA_FCU;
134
135         if(kernel)
136                 pmlca &= ~PMLCA_FCS;
137         else
138                 pmlca |= PMLCA_FCS;
139
140         set_pmlca(ctr, pmlca);
141 }
142
143 void set_pmc_marked(int ctr, int mark0, int mark1)
144 {
145         u32 pmlca = get_pmlca(ctr);
146
147         if(mark0)
148                 pmlca &= ~PMLCA_FCM0;
149         else
150                 pmlca |= PMLCA_FCM0;
151
152         if(mark1)
153                 pmlca &= ~PMLCA_FCM1;
154         else
155                 pmlca |= PMLCA_FCM1;
156
157         set_pmlca(ctr, pmlca);
158 }
159
160 void pmc_start_ctr(int ctr, int enable)
161 {
162         u32 pmlca = get_pmlca(ctr);
163
164         pmlca &= ~PMLCA_FC;
165
166         if (enable)
167                 pmlca |= PMLCA_CE;
168         else
169                 pmlca &= ~PMLCA_CE;
170
171         set_pmlca(ctr, pmlca);
172 }
173
174 void pmc_start_ctrs(int enable)
175 {
176         u32 pmgc0 = mfpmr(PMRN_PMGC0);
177
178         pmgc0 &= ~PMGC0_FAC;
179         pmgc0 |= PMGC0_FCECE;
180
181         if (enable)
182                 pmgc0 |= PMGC0_PMIE;
183         else
184                 pmgc0 &= ~PMGC0_PMIE;
185
186         mtpmr(PMRN_PMGC0, pmgc0);
187 }
188
189 void pmc_stop_ctrs(void)
190 {
191         u32 pmgc0 = mfpmr(PMRN_PMGC0);
192
193         pmgc0 |= PMGC0_FAC;
194
195         pmgc0 &= ~(PMGC0_PMIE | PMGC0_FCECE);
196
197         mtpmr(PMRN_PMGC0, pmgc0);
198 }
199
200 void dump_pmcs(void)
201 {
202         printk("pmgc0: %x\n", mfpmr(PMRN_PMGC0));
203         printk("pmc\t\tpmlca\t\tpmlcb\n");
204         printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC0),
205                         mfpmr(PMRN_PMLCA0), mfpmr(PMRN_PMLCB0));
206         printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC1),
207                         mfpmr(PMRN_PMLCA1), mfpmr(PMRN_PMLCB1));
208         printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC2),
209                         mfpmr(PMRN_PMLCA2), mfpmr(PMRN_PMLCB2));
210         printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC3),
211                         mfpmr(PMRN_PMLCA3), mfpmr(PMRN_PMLCB3));
212 }
213
214 EXPORT_SYMBOL(init_pmc_stop);
215 EXPORT_SYMBOL(set_pmc_event);
216 EXPORT_SYMBOL(set_pmc_user_kernel);
217 EXPORT_SYMBOL(set_pmc_marked);
218 EXPORT_SYMBOL(pmc_start_ctr);
219 EXPORT_SYMBOL(pmc_start_ctrs);
220 EXPORT_SYMBOL(pmc_stop_ctrs);
221 EXPORT_SYMBOL(dump_pmcs);