Merge branch 'drm-patches' of master.kernel.org:/pub/scm/linux/kernel/git/airlied...
[linux-drm-fsl-dcu.git] / arch / blackfin / oprofile / common.c
1 /*
2  * File:         arch/blackfin/oprofile/common.c
3  * Based on:     arch/alpha/oprofile/common.c
4  * Author:       Anton Blanchard <anton@au.ibm.com>
5  *
6  * Created:
7  * Description:
8  *
9  * Modified:
10  *               Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
11  *               Copyright 2004-2006 Analog Devices Inc.
12  *
13  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
14  *
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 2 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, see the file COPYING, or write
27  * to the Free Software Foundation, Inc.,
28  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
29  */
30
31 #include <linux/oprofile.h>
32 #include <linux/init.h>
33 #include <linux/smp.h>
34 #include <linux/errno.h>
35 #include <linux/mutex.h>
36
37 #include <asm/ptrace.h>
38 #include <asm/system.h>
39 #include <asm/blackfin.h>
40 #include <asm/irq.h>
41 #include <asm/io.h>
42
43 #include "op_blackfin.h"
44
45 #define BFIN_533_ID  0xE5040003
46 #define BFIN_537_ID  0xE5040002
47
48 static int pfmon_enabled;
49 static struct mutex pfmon_lock;
50
51 struct op_bfin533_model *model;
52
53 struct op_counter_config ctr[OP_MAX_COUNTER];
54
55 static int op_bfin_setup(void)
56 {
57         int ret;
58
59         /* Pre-compute the values to stuff in the hardware registers.  */
60         spin_lock(&oprofilefs_lock);
61         ret = model->reg_setup(ctr);
62         spin_unlock(&oprofilefs_lock);
63
64         return ret;
65 }
66
67 static void op_bfin_shutdown(void)
68 {
69 #if 0
70         /* what is the difference between shutdown and stop? */
71 #endif
72 }
73
74 static int op_bfin_start(void)
75 {
76         int ret = -EBUSY;
77
78         printk(KERN_INFO "KSDBG:in %s\n", __FUNCTION__);
79         mutex_lock(&pfmon_lock);
80         if (!pfmon_enabled) {
81                 ret = model->start(ctr);
82                 pfmon_enabled = !ret;
83         }
84         mutex_unlock(&pfmon_lock);
85
86         return ret;
87 }
88
89 static void op_bfin_stop(void)
90 {
91         mutex_lock(&pfmon_lock);
92         if (pfmon_enabled) {
93                 model->stop();
94                 pfmon_enabled = 0;
95         }
96         mutex_unlock(&pfmon_lock);
97 }
98
99 static int op_bfin_create_files(struct super_block *sb, struct dentry *root)
100 {
101         int i;
102
103         for (i = 0; i < model->num_counters; ++i) {
104                 struct dentry *dir;
105                 char buf[3];
106                 printk(KERN_INFO "Oprofile: creating files... \n");
107
108                 snprintf(buf, sizeof buf, "%d", i);
109                 dir = oprofilefs_mkdir(sb, root, buf);
110
111                 oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled);
112                 oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event);
113                 oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count);
114                 /*
115                  * We dont support per counter user/kernel selection, but
116                  * we leave the entries because userspace expects them
117                  */
118                 oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel);
119                 oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user);
120                 oprofilefs_create_ulong(sb, dir, "unit_mask",
121                                         &ctr[i].unit_mask);
122         }
123
124         return 0;
125 }
126 int __init oprofile_arch_init(struct oprofile_operations *ops)
127 {
128 #ifdef CONFIG_HARDWARE_PM
129         unsigned int dspid;
130
131         mutex_init(&pfmon_lock);
132
133         dspid = bfin_read_DSPID();
134
135         printk(KERN_INFO "Oprofile got the cpu id is 0x%x. \n", dspid);
136
137         switch (dspid) {
138         case BFIN_533_ID:
139                 model = &op_model_bfin533;
140                 model->num_counters = 2;
141                 break;
142         case BFIN_537_ID:
143                 model = &op_model_bfin533;
144                 model->num_counters = 2;
145                 break;
146         default:
147                 return -ENODEV;
148         }
149
150         ops->cpu_type = model->name;
151         ops->create_files = op_bfin_create_files;
152         ops->setup = op_bfin_setup;
153         ops->shutdown = op_bfin_shutdown;
154         ops->start = op_bfin_start;
155         ops->stop = op_bfin_stop;
156
157         printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
158                ops->cpu_type);
159
160         return 0;
161 #else
162         return -1;
163 #endif
164 }
165
166 void oprofile_arch_exit(void)
167 {
168 }