aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/oprofile
diff options
context:
space:
mode:
authorBryan Wu <bryan.wu@analog.com>2007-05-06 17:50:22 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-07 15:12:58 -0400
commit1394f03221790a988afc3e4b3cb79f2e477246a9 (patch)
tree2c1963c9a4f2d84a5e021307fde240c5d567cf70 /arch/blackfin/oprofile
parent73243284463a761e04d69d22c7516b2be7de096c (diff)
blackfin architecture
This adds support for the Analog Devices Blackfin processor architecture, and currently supports the BF533, BF532, BF531, BF537, BF536, BF534, and BF561 (Dual Core) devices, with a variety of development platforms including those avaliable from Analog Devices (BF533-EZKit, BF533-STAMP, BF537-STAMP, BF561-EZKIT), and Bluetechnix! Tinyboards. The Blackfin architecture was jointly developed by Intel and Analog Devices Inc. (ADI) as the Micro Signal Architecture (MSA) core and introduced it in December of 2000. Since then ADI has put this core into its Blackfin processor family of devices. The Blackfin core has the advantages of a clean, orthogonal,RISC-like microprocessor instruction set. It combines a dual-MAC (Multiply/Accumulate), state-of-the-art signal processing engine and single-instruction, multiple-data (SIMD) multimedia capabilities into a single instruction-set architecture. The Blackfin architecture, including the instruction set, is described by the ADSP-BF53x/BF56x Blackfin Processor Programming Reference http://blackfin.uclinux.org/gf/download/frsrelease/29/2549/Blackfin_PRM.pdf The Blackfin processor is already supported by major releases of gcc, and there are binary and source rpms/tarballs for many architectures at: http://blackfin.uclinux.org/gf/project/toolchain/frs There is complete documentation, including "getting started" guides available at: http://docs.blackfin.uclinux.org/ which provides links to the sources and patches you will need in order to set up a cross-compiling environment for bfin-linux-uclibc This patch, as well as the other patches (toolchain, distribution, uClibc) are actively supported by Analog Devices Inc, at: http://blackfin.uclinux.org/ We have tested this on LTP, and our test plan (including pass/fails) can be found at: http://docs.blackfin.uclinux.org/doku.php?id=testing_the_linux_kernel [m.kozlowski@tuxland.pl: balance parenthesis in blackfin header files] Signed-off-by: Bryan Wu <bryan.wu@analog.com> Signed-off-by: Mariusz Kozlowski <m.kozlowski@tuxland.pl> Signed-off-by: Aubrey Li <aubrey.li@analog.com> Signed-off-by: Jie Zhang <jie.zhang@analog.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/blackfin/oprofile')
-rw-r--r--arch/blackfin/oprofile/Kconfig29
-rw-r--r--arch/blackfin/oprofile/Makefile14
-rw-r--r--arch/blackfin/oprofile/common.c168
-rw-r--r--arch/blackfin/oprofile/op_blackfin.h98
-rw-r--r--arch/blackfin/oprofile/op_model_bf533.c161
-rw-r--r--arch/blackfin/oprofile/timer_int.c74
6 files changed, 544 insertions, 0 deletions
diff --git a/arch/blackfin/oprofile/Kconfig b/arch/blackfin/oprofile/Kconfig
new file mode 100644
index 000000000000..0a2fd999c941
--- /dev/null
+++ b/arch/blackfin/oprofile/Kconfig
@@ -0,0 +1,29 @@
1menu "Profiling support"
2depends on EXPERIMENTAL
3
4config PROFILING
5 bool "Profiling support (EXPERIMENTAL)"
6 help
7 Say Y here to enable the extended profiling support mechanisms used
8 by profilers such as OProfile.
9
10config OPROFILE
11 tristate "OProfile system profiling (EXPERIMENTAL)"
12 depends on PROFILING
13 help
14 OProfile is a profiling system capable of profiling the
15 whole system, include the kernel, kernel modules, libraries,
16 and applications.
17
18 If unsure, say N.
19
20config HARDWARE_PM
21 tristate "Hardware Performance Monitor Profiling"
22 depends on PROFILING
23 help
24 take use of hardware performance monitor to profiling the kernel
25 and application.
26
27 If unsure, say N.
28
29endmenu
diff --git a/arch/blackfin/oprofile/Makefile b/arch/blackfin/oprofile/Makefile
new file mode 100644
index 000000000000..634e300d67e2
--- /dev/null
+++ b/arch/blackfin/oprofile/Makefile
@@ -0,0 +1,14 @@
1#
2# arch/blackfin/oprofile/Makefile
3#
4
5obj-$(CONFIG_OPROFILE) += oprofile.o
6
7DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
8 oprof.o cpu_buffer.o buffer_sync.o \
9 event_buffer.o oprofile_files.o \
10 oprofilefs.o oprofile_stats.o \
11 timer_int.o )
12
13oprofile-y := $(DRIVER_OBJS) common.o
14oprofile-$(CONFIG_HARDWARE_PM) += op_model_bf533.o
diff --git a/arch/blackfin/oprofile/common.c b/arch/blackfin/oprofile/common.c
new file mode 100644
index 000000000000..009a1700c854
--- /dev/null
+++ b/arch/blackfin/oprofile/common.c
@@ -0,0 +1,168 @@
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
48static int pfmon_enabled;
49static struct mutex pfmon_lock;
50
51struct op_bfin533_model *model;
52
53struct op_counter_config ctr[OP_MAX_COUNTER];
54
55static 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
67static void op_bfin_shutdown(void)
68{
69#if 0
70 /* what is the difference between shutdown and stop? */
71#endif
72}
73
74static 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
89static 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
99static 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}
126int __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
166void oprofile_arch_exit(void)
167{
168}
diff --git a/arch/blackfin/oprofile/op_blackfin.h b/arch/blackfin/oprofile/op_blackfin.h
new file mode 100644
index 000000000000..f88f446c814f
--- /dev/null
+++ b/arch/blackfin/oprofile/op_blackfin.h
@@ -0,0 +1,98 @@
1/*
2 * File: arch/blackfin/oprofile/op_blackfin.h
3 * Based on:
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#ifndef OP_BLACKFIN_H
32#define OP_BLACKFIN_H 1
33
34#define OP_MAX_COUNTER 2
35
36#include <asm/blackfin.h>
37
38/* Per-counter configuration as set via oprofilefs. */
39struct op_counter_config {
40 unsigned long valid;
41 unsigned long enabled;
42 unsigned long event;
43 unsigned long count;
44 unsigned long kernel;
45 unsigned long user;
46 unsigned long unit_mask;
47};
48
49/* System-wide configuration as set via oprofilefs. */
50struct op_system_config {
51 unsigned long enable_kernel;
52 unsigned long enable_user;
53};
54
55/* Per-arch configuration */
56struct op_bfin533_model {
57 int (*reg_setup) (struct op_counter_config *);
58 int (*start) (struct op_counter_config *);
59 void (*stop) (void);
60 int num_counters;
61 char *name;
62};
63
64extern struct op_bfin533_model op_model_bfin533;
65
66static inline unsigned int ctr_read(void)
67{
68 unsigned int tmp;
69
70 tmp = bfin_read_PFCTL();
71 __builtin_bfin_csync();
72
73 return tmp;
74}
75
76static inline void ctr_write(unsigned int val)
77{
78 bfin_write_PFCTL(val);
79 __builtin_bfin_csync();
80}
81
82static inline void count_read(unsigned int *count)
83{
84 count[0] = bfin_read_PFCNTR0();
85 count[1] = bfin_read_PFCNTR1();
86 __builtin_bfin_csync();
87}
88
89static inline void count_write(unsigned int *count)
90{
91 bfin_write_PFCNTR0(count[0]);
92 bfin_write_PFCNTR1(count[1]);
93 __builtin_bfin_csync();
94}
95
96extern int pm_overflow_handler(int irq, struct pt_regs *regs);
97
98#endif
diff --git a/arch/blackfin/oprofile/op_model_bf533.c b/arch/blackfin/oprofile/op_model_bf533.c
new file mode 100644
index 000000000000..b7a20a006b49
--- /dev/null
+++ b/arch/blackfin/oprofile/op_model_bf533.c
@@ -0,0 +1,161 @@
1/*
2 * File: arch/blackfin/oprofile/op_model_bf533.c
3 * Based on:
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/interrupt.h>
35#include <asm/ptrace.h>
36#include <asm/system.h>
37#include <asm/processor.h>
38#include <asm/blackfin.h>
39#include <asm/irq.h>
40#include <asm/io.h>
41
42#include "op_blackfin.h"
43
44#define PM_ENABLE 0x01;
45#define PM_CTL1_ENABLE 0x18
46#define PM_CTL0_ENABLE 0xC000
47#define COUNT_EDGE_ONLY 0x3000000
48
49static int oprofile_running;
50
51static unsigned curr_pfctl, curr_count[2];
52
53static int bfin533_reg_setup(struct op_counter_config *ctr)
54{
55 unsigned int pfctl = ctr_read();
56 unsigned int count[2];
57
58 /* set Blackfin perf monitor regs with ctr */
59 if (ctr[0].enabled) {
60 pfctl |= (PM_CTL0_ENABLE | ((char)ctr[0].event << 5));
61 count[0] = 0xFFFFFFFF - ctr[0].count;
62 curr_count[0] = count[0];
63 }
64 if (ctr[1].enabled) {
65 pfctl |= (PM_CTL1_ENABLE | ((char)ctr[1].event << 16));
66 count[1] = 0xFFFFFFFF - ctr[1].count;
67 curr_count[1] = count[1];
68 }
69
70 pr_debug("ctr[0].enabled=%d,ctr[1].enabled=%d,ctr[0].event<<5=0x%x,ctr[1].event<<16=0x%x\n", ctr[0].enabled, ctr[1].enabled, ctr[0].event << 5, ctr[1].event << 16);
71 pfctl |= COUNT_EDGE_ONLY;
72 curr_pfctl = pfctl;
73
74 pr_debug("write 0x%x to pfctl\n", pfctl);
75 ctr_write(pfctl);
76 count_write(count);
77
78 return 0;
79}
80
81static int bfin533_start(struct op_counter_config *ctr)
82{
83 unsigned int pfctl = ctr_read();
84
85 pfctl |= PM_ENABLE;
86 curr_pfctl = pfctl;
87
88 ctr_write(pfctl);
89
90 oprofile_running = 1;
91 pr_debug("start oprofile counter \n");
92
93 return 0;
94}
95
96static void bfin533_stop(void)
97{
98 int pfctl;
99
100 pfctl = ctr_read();
101 pfctl &= ~PM_ENABLE;
102 /* freeze counters */
103 ctr_write(pfctl);
104
105 oprofile_running = 0;
106 pr_debug("stop oprofile counter \n");
107}
108
109static int get_kernel(void)
110{
111 int ipend, is_kernel;
112
113 ipend = bfin_read_IPEND();
114
115 /* test bit 15 */
116 is_kernel = ((ipend & 0x8000) != 0);
117
118 return is_kernel;
119}
120
121int pm_overflow_handler(int irq, struct pt_regs *regs)
122{
123 int is_kernel;
124 int i, cpu;
125 unsigned int pc, pfctl;
126 unsigned int count[2];
127
128 pr_debug("get interrupt in %s\n", __FUNCTION__);
129 if (oprofile_running == 0) {
130 pr_debug("error: entering interrupt when oprofile is stopped.\n\r");
131 return -1;
132 }
133
134 is_kernel = get_kernel();
135 cpu = smp_processor_id();
136 pc = regs->pc;
137 pfctl = ctr_read();
138
139 /* read the two event counter regs */
140 count_read(count);
141
142 /* if the counter overflows, add sample to oprofile buffer */
143 for (i = 0; i < 2; ++i) {
144 if (oprofile_running) {
145 oprofile_add_sample(regs, i);
146 }
147 }
148
149 /* reset the perfmon counter */
150 ctr_write(curr_pfctl);
151 count_write(curr_count);
152 return 0;
153}
154
155struct op_bfin533_model op_model_bfin533 = {
156 .reg_setup = bfin533_reg_setup,
157 .start = bfin533_start,
158 .stop = bfin533_stop,
159 .num_counters = 2,
160 .name = "blackfin/bf533"
161};
diff --git a/arch/blackfin/oprofile/timer_int.c b/arch/blackfin/oprofile/timer_int.c
new file mode 100644
index 000000000000..8fba16c846c9
--- /dev/null
+++ b/arch/blackfin/oprofile/timer_int.c
@@ -0,0 +1,74 @@
1/*
2 * File: arch/blackfin/oprofile/timer_int.c
3 * Based on:
4 * Author: Michael Kang
5 *
6 * Created:
7 * Description:
8 *
9 * Modified:
10 * Copyright 2004-2006 Analog Devices Inc.
11 *
12 * Bugs: Enter bugs at http://blackfin.uclinux.org/
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, see the file COPYING, or write
26 * to the Free Software Foundation, Inc.,
27 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 */
29
30#include <linux/init.h>
31#include <linux/smp.h>
32#include <linux/irq.h>
33#include <linux/oprofile.h>
34
35#include <asm/ptrace.h>
36
37static void enable_sys_timer0()
38{
39}
40static void disable_sys_timer0()
41{
42}
43
44static irqreturn_t sys_timer0_int_handler(int irq, void *dev_id,
45 struct pt_regs *regs)
46{
47 oprofile_add_sample(regs, 0);
48 return IRQ_HANDLED;
49}
50
51static int sys_timer0_start(void)
52{
53 enable_sys_timer0();
54 return request_irq(IVG11, sys_timer0_int_handler, 0, "sys_timer0", NULL);
55}
56
57static void sys_timer0_stop(void)
58{
59 disable_sys_timer();
60}
61
62int __init sys_timer0_init(struct oprofile_operations *ops)
63{
64 extern int nmi_active;
65
66 if (nmi_active <= 0)
67 return -ENODEV;
68
69 ops->start = timer_start;
70 ops->stop = timer_stop;
71 ops->cpu_type = "timer";
72 printk(KERN_INFO "oprofile: using NMI timer interrupt.\n");
73 return 0;
74}