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} 70 71static int op_bfin_start(void) 72{ 73 int ret = -EBUSY; 74 75 printk(KERN_INFO "KSDBG:in %s\n", __FUNCTION__); 76 mutex_lock(&pfmon_lock); 77 if (!pfmon_enabled) { 78 ret = model->start(ctr); 79 pfmon_enabled = !ret; 80 } 81 mutex_unlock(&pfmon_lock); 82 83 return ret; 84} 85 86static void op_bfin_stop(void) 87{ 88 mutex_lock(&pfmon_lock); 89 if (pfmon_enabled) { 90 model->stop(); 91 pfmon_enabled = 0; 92 } 93 mutex_unlock(&pfmon_lock); 94} 95 96static int op_bfin_create_files(struct super_block *sb, struct dentry *root) 97{ 98 int i; 99 100 for (i = 0; i < model->num_counters; ++i) { 101 struct dentry *dir; 102 char buf[3]; 103 printk(KERN_INFO "Oprofile: creating files... \n"); 104 105 snprintf(buf, sizeof buf, "%d", i); 106 dir = oprofilefs_mkdir(sb, root, buf); 107 108 oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled); 109 oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event); 110 oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count); 111 /* 112 * We dont support per counter user/kernel selection, but 113 * we leave the entries because userspace expects them 114 */ 115 oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel); 116 oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user); 117 oprofilefs_create_ulong(sb, dir, "unit_mask", 118 &ctr[i].unit_mask); 119 } 120 121 return 0; 122} 123int __init oprofile_arch_init(struct oprofile_operations *ops) 124{ 125#ifdef CONFIG_HARDWARE_PM 126 unsigned int dspid; 127 128 mutex_init(&pfmon_lock); 129 130 dspid = bfin_read_DSPID(); 131 132 printk(KERN_INFO "Oprofile got the cpu id is 0x%x. \n", dspid); 133 134 switch (dspid) { 135 case BFIN_533_ID: 136 model = &op_model_bfin533; 137 model->num_counters = 2; 138 break; 139 case BFIN_537_ID: 140 model = &op_model_bfin533; 141 model->num_counters = 2; 142 break; 143 default: 144 return -ENODEV; 145 } 146 147 ops->cpu_type = model->name; 148 ops->create_files = op_bfin_create_files; 149 ops->setup = op_bfin_setup; 150 ops->shutdown = op_bfin_shutdown; 151 ops->start = op_bfin_start; 152 ops->stop = op_bfin_stop; 153 154 printk(KERN_INFO "oprofile: using %s performance monitoring.\n", 155 ops->cpu_type); 156 157 return 0; 158#else 159 return -1; 160#endif 161} 162 163void oprofile_arch_exit(void) 164{ 165} 166