aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/sibyte
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/sibyte')
-rw-r--r--arch/mips/sibyte/Kconfig26
-rw-r--r--arch/mips/sibyte/bcm1480/Makefile2
-rw-r--r--arch/mips/sibyte/bcm1480/irq.c6
-rw-r--r--arch/mips/sibyte/bcm1480/setup.c10
-rw-r--r--arch/mips/sibyte/bcm1480/smp.c6
-rw-r--r--arch/mips/sibyte/cfe/setup.c8
-rw-r--r--arch/mips/sibyte/common/Makefile5
-rw-r--r--arch/mips/sibyte/common/sb_tbprof.c (renamed from arch/mips/sibyte/sb1250/bcm1250_tbprof.c)407
-rw-r--r--arch/mips/sibyte/sb1250/Makefile3
-rw-r--r--arch/mips/sibyte/sb1250/irq.c2
-rw-r--r--arch/mips/sibyte/sb1250/setup.c38
-rw-r--r--arch/mips/sibyte/swarm/setup.c18
12 files changed, 378 insertions, 153 deletions
diff --git a/arch/mips/sibyte/Kconfig b/arch/mips/sibyte/Kconfig
index ec7a2cffacf0..e6b003ec6716 100644
--- a/arch/mips/sibyte/Kconfig
+++ b/arch/mips/sibyte/Kconfig
@@ -1,35 +1,41 @@
1config SIBYTE_SB1250 1config SIBYTE_SB1250
2 bool 2 bool
3 select HW_HAS_PCI 3 select HW_HAS_PCI
4 select SIBYTE_HAS_LDT 4 select SIBYTE_ENABLE_LDT_IF_PCI
5 select SIBYTE_HAS_ZBUS_PROFILING
5 select SIBYTE_SB1xxx_SOC 6 select SIBYTE_SB1xxx_SOC
6 select SYS_SUPPORTS_SMP 7 select SYS_SUPPORTS_SMP
7 8
8config SIBYTE_BCM1120 9config SIBYTE_BCM1120
9 bool 10 bool
10 select SIBYTE_BCM112X 11 select SIBYTE_BCM112X
12 select SIBYTE_HAS_ZBUS_PROFILING
11 select SIBYTE_SB1xxx_SOC 13 select SIBYTE_SB1xxx_SOC
12 14
13config SIBYTE_BCM1125 15config SIBYTE_BCM1125
14 bool 16 bool
15 select HW_HAS_PCI 17 select HW_HAS_PCI
16 select SIBYTE_BCM112X 18 select SIBYTE_BCM112X
19 select SIBYTE_HAS_ZBUS_PROFILING
17 select SIBYTE_SB1xxx_SOC 20 select SIBYTE_SB1xxx_SOC
18 21
19config SIBYTE_BCM1125H 22config SIBYTE_BCM1125H
20 bool 23 bool
21 select HW_HAS_PCI 24 select HW_HAS_PCI
22 select SIBYTE_BCM112X 25 select SIBYTE_BCM112X
23 select SIBYTE_HAS_LDT 26 select SIBYTE_ENABLE_LDT_IF_PCI
27 select SIBYTE_HAS_ZBUS_PROFILING
24 select SIBYTE_SB1xxx_SOC 28 select SIBYTE_SB1xxx_SOC
25 29
26config SIBYTE_BCM112X 30config SIBYTE_BCM112X
27 bool 31 bool
28 select SIBYTE_SB1xxx_SOC 32 select SIBYTE_SB1xxx_SOC
33 select SIBYTE_HAS_ZBUS_PROFILING
29 34
30config SIBYTE_BCM1x80 35config SIBYTE_BCM1x80
31 bool 36 bool
32 select HW_HAS_PCI 37 select HW_HAS_PCI
38 select SIBYTE_HAS_ZBUS_PROFILING
33 select SIBYTE_SB1xxx_SOC 39 select SIBYTE_SB1xxx_SOC
34 select SYS_SUPPORTS_SMP 40 select SYS_SUPPORTS_SMP
35 41
@@ -37,6 +43,7 @@ config SIBYTE_BCM1x55
37 bool 43 bool
38 select HW_HAS_PCI 44 select HW_HAS_PCI
39 select SIBYTE_SB1xxx_SOC 45 select SIBYTE_SB1xxx_SOC
46 select SIBYTE_HAS_ZBUS_PROFILING
40 select SYS_SUPPORTS_SMP 47 select SYS_SUPPORTS_SMP
41 48
42config SIBYTE_SB1xxx_SOC 49config SIBYTE_SB1xxx_SOC
@@ -95,8 +102,10 @@ config CPU_SB1_PASS_2
95 102
96config SIBYTE_HAS_LDT 103config SIBYTE_HAS_LDT
97 bool 104 bool
98 depends on PCI && (SIBYTE_SB1250 || SIBYTE_BCM1125H) 105
99 default y 106config SIBYTE_ENABLE_LDT_IF_PCI
107 bool
108 select SIBYTE_HAS_LDT if PCI
100 109
101config SIMULATION 110config SIMULATION
102 bool "Running under simulation" 111 bool "Running under simulation"
@@ -116,6 +125,7 @@ config SB1_CERR_STALL
116config SIBYTE_CFE 125config SIBYTE_CFE
117 bool "Booting from CFE" 126 bool "Booting from CFE"
118 depends on SIBYTE_SB1xxx_SOC 127 depends on SIBYTE_SB1xxx_SOC
128 select SYS_HAS_EARLY_PRINTK
119 help 129 help
120 Make use of the CFE API for enumerating available memory, 130 Make use of the CFE API for enumerating available memory,
121 controlling secondary CPUs, and possibly console output. 131 controlling secondary CPUs, and possibly console output.
@@ -131,6 +141,7 @@ config SIBYTE_CFE_CONSOLE
131config SIBYTE_STANDALONE 141config SIBYTE_STANDALONE
132 bool 142 bool
133 depends on SIBYTE_SB1xxx_SOC && !SIBYTE_CFE 143 depends on SIBYTE_SB1xxx_SOC && !SIBYTE_CFE
144 select SYS_HAS_EARLY_PRINTK
134 default y 145 default y
135 146
136config SIBYTE_STANDALONE_RAM_SIZE 147config SIBYTE_STANDALONE_RAM_SIZE
@@ -160,5 +171,8 @@ config SIBYTE_SB1250_PROF
160 depends on SIBYTE_SB1xxx_SOC 171 depends on SIBYTE_SB1xxx_SOC
161 172
162config SIBYTE_TBPROF 173config SIBYTE_TBPROF
163 bool "Support for ZBbus profiling" 174 tristate "Support for ZBbus profiling"
164 depends on SIBYTE_SB1xxx_SOC 175 depends on SIBYTE_HAS_ZBUS_PROFILING
176
177config SIBYTE_HAS_ZBUS_PROFILING
178 bool
diff --git a/arch/mips/sibyte/bcm1480/Makefile b/arch/mips/sibyte/bcm1480/Makefile
index 7b36ff3873b7..cdc4c56c3e29 100644
--- a/arch/mips/sibyte/bcm1480/Makefile
+++ b/arch/mips/sibyte/bcm1480/Makefile
@@ -1,5 +1,3 @@
1obj-y := setup.o irq.o time.o 1obj-y := setup.o irq.o time.o
2 2
3obj-$(CONFIG_SMP) += smp.o 3obj-$(CONFIG_SMP) += smp.o
4
5EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c
index 1dc5d05d8962..ba0c4b776c85 100644
--- a/arch/mips/sibyte/bcm1480/irq.c
+++ b/arch/mips/sibyte/bcm1480/irq.c
@@ -141,11 +141,11 @@ static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask)
141 unsigned long flags; 141 unsigned long flags;
142 unsigned int irq_dirty; 142 unsigned int irq_dirty;
143 143
144 i = first_cpu(mask); 144 if (cpus_weight(mask) != 1) {
145 if (next_cpu(i, mask) <= NR_CPUS) {
146 printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq); 145 printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
147 return; 146 return;
148 } 147 }
148 i = first_cpu(mask);
149 149
150 /* Convert logical CPU to physical CPU */ 150 /* Convert logical CPU to physical CPU */
151 cpu = cpu_logical_map(i); 151 cpu = cpu_logical_map(i);
@@ -420,7 +420,7 @@ void __init arch_init_irq(void)
420#ifdef CONFIG_GDB_CONSOLE 420#ifdef CONFIG_GDB_CONSOLE
421 register_gdb_console(); 421 register_gdb_console();
422#endif 422#endif
423 prom_printf("Waiting for GDB on UART port %d\n", kgdb_port); 423 printk("Waiting for GDB on UART port %d\n", kgdb_port);
424 set_debug_traps(); 424 set_debug_traps();
425 breakpoint(); 425 breakpoint();
426 } 426 }
diff --git a/arch/mips/sibyte/bcm1480/setup.c b/arch/mips/sibyte/bcm1480/setup.c
index 8236d0c48542..bdaac34ae708 100644
--- a/arch/mips/sibyte/bcm1480/setup.c
+++ b/arch/mips/sibyte/bcm1480/setup.c
@@ -69,7 +69,7 @@ static inline int sys_rev_decode(void)
69 break; 69 break;
70 70
71 default: 71 default:
72 prom_printf("Unknown part type %x\n", part_type); 72 printk("Unknown part type %x\n", part_type);
73 ret = 1; 73 ret = 1;
74 break; 74 break;
75 } 75 }
@@ -102,7 +102,7 @@ static inline int setup_bcm1x80_bcm1x55(void)
102 pass_str = "B0 (pass2)"; 102 pass_str = "B0 (pass2)";
103 break; 103 break;
104 default: 104 default:
105 prom_printf("Unknown %s rev %x\n", soc_str, soc_pass); 105 printk("Unknown %s rev %x\n", soc_str, soc_pass);
106 periph_rev = 1; 106 periph_rev = 1;
107 pass_str = "Unknown Revision"; 107 pass_str = "Unknown Revision";
108 break; 108 break;
@@ -122,14 +122,14 @@ void bcm1480_setup(void)
122 soc_pass = G_SYS_REVISION(sys_rev); 122 soc_pass = G_SYS_REVISION(sys_rev);
123 123
124 if (sys_rev_decode()) { 124 if (sys_rev_decode()) {
125 prom_printf("Restart after failure to identify SiByte chip\n"); 125 printk("Restart after failure to identify SiByte chip\n");
126 machine_restart(NULL); 126 machine_restart(NULL);
127 } 127 }
128 128
129 plldiv = G_BCM1480_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG))); 129 plldiv = G_BCM1480_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG)));
130 zbbus_mhz = ((plldiv >> 1) * 50) + ((plldiv & 1) * 25); 130 zbbus_mhz = ((plldiv >> 1) * 50) + ((plldiv & 1) * 25);
131 131
132 prom_printf("Broadcom SiByte %s %s @ %d MHz (SB-1A rev %d)\n", 132 printk("Broadcom SiByte %s %s @ %d MHz (SB-1A rev %d)\n",
133 soc_str, pass_str, zbbus_mhz * 2, sb1_pass); 133 soc_str, pass_str, zbbus_mhz * 2, sb1_pass);
134 prom_printf("Board type: %s\n", get_system_type()); 134 printk("Board type: %s\n", get_system_type());
135} 135}
diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c
index bf328277c775..6eac36d1b8c8 100644
--- a/arch/mips/sibyte/bcm1480/smp.c
+++ b/arch/mips/sibyte/bcm1480/smp.c
@@ -34,21 +34,21 @@ extern void smp_call_function_interrupt(void);
34 * independent of board/firmware 34 * independent of board/firmware
35 */ 35 */
36 36
37static volatile void *mailbox_0_set_regs[] = { 37static void *mailbox_0_set_regs[] = {
38 IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU), 38 IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
39 IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU), 39 IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
40 IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU), 40 IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
41 IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU), 41 IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
42}; 42};
43 43
44static volatile void *mailbox_0_clear_regs[] = { 44static void *mailbox_0_clear_regs[] = {
45 IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU), 45 IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
46 IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU), 46 IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
47 IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU), 47 IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
48 IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU), 48 IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
49}; 49};
50 50
51static volatile void *mailbox_0_regs[] = { 51static void *mailbox_0_regs[] = {
52 IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_CPU), 52 IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
53 IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_CPU), 53 IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
54 IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_CPU), 54 IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
diff --git a/arch/mips/sibyte/cfe/setup.c b/arch/mips/sibyte/cfe/setup.c
index 9e6099e69622..ae4a92c3e529 100644
--- a/arch/mips/sibyte/cfe/setup.c
+++ b/arch/mips/sibyte/cfe/setup.c
@@ -221,10 +221,10 @@ static int __init initrd_setup(char *str)
221 goto fail; 221 goto fail;
222 } 222 }
223 initrd_end = initrd_start + initrd_size; 223 initrd_end = initrd_start + initrd_size;
224 prom_printf("Found initrd of %lx@%lx\n", initrd_size, initrd_start); 224 printk("Found initrd of %lx@%lx\n", initrd_size, initrd_start);
225 return 1; 225 return 1;
226 fail: 226 fail:
227 prom_printf("Bad initrd argument. Disabling initrd\n"); 227 printk("Bad initrd argument. Disabling initrd\n");
228 initrd_start = 0; 228 initrd_start = 0;
229 initrd_end = 0; 229 initrd_end = 0;
230 return 1; 230 return 1;
@@ -281,7 +281,7 @@ void __init prom_init(void)
281 } 281 }
282 if (cfe_eptseal != CFE_EPTSEAL) { 282 if (cfe_eptseal != CFE_EPTSEAL) {
283 /* too early for panic to do any good */ 283 /* too early for panic to do any good */
284 prom_printf("CFE's entrypoint seal doesn't match. Spinning."); 284 printk("CFE's entrypoint seal doesn't match. Spinning.");
285 while (1) ; 285 while (1) ;
286 } 286 }
287 cfe_init(cfe_handle, cfe_ept); 287 cfe_init(cfe_handle, cfe_ept);
@@ -303,7 +303,7 @@ void __init prom_init(void)
303 } else { 303 } else {
304 /* The loader should have set the command line */ 304 /* The loader should have set the command line */
305 /* too early for panic to do any good */ 305 /* too early for panic to do any good */
306 prom_printf("LINUX_CMDLINE not defined in cfe."); 306 printk("LINUX_CMDLINE not defined in cfe.");
307 while (1) ; 307 while (1) ;
308 } 308 }
309 } 309 }
diff --git a/arch/mips/sibyte/common/Makefile b/arch/mips/sibyte/common/Makefile
new file mode 100644
index 000000000000..8a06a4fb5212
--- /dev/null
+++ b/arch/mips/sibyte/common/Makefile
@@ -0,0 +1,5 @@
1obj-y :=
2
3obj-$(CONFIG_SIBYTE_TBPROF) += sb_tbprof.o
4
5EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sibyte/sb1250/bcm1250_tbprof.c b/arch/mips/sibyte/common/sb_tbprof.c
index 212547c57310..4fcdaa8ba514 100644
--- a/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
+++ b/arch/mips/sibyte/common/sb_tbprof.c
@@ -1,6 +1,4 @@
1/* 1/*
2 * Copyright (C) 2001, 2002, 2003 Broadcom Corporation
3 *
4 * This program is free software; you can redistribute it and/or 2 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License 3 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2 4 * as published by the Free Software Foundation; either version 2
@@ -14,10 +12,16 @@
14 * You should have received a copy of the GNU General Public License 12 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software 13 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 *
16 * Copyright (C) 2001, 2002, 2003 Broadcom Corporation
17 * Copyright (C) 2007 Ralf Baechle <ralf@linux-mips.org>
18 * Copyright (C) 2007 MIPS Technologies, Inc.
19 * written by Ralf Baechle <ralf@linux-mips.org>
17 */ 20 */
18 21
19#define SBPROF_TB_DEBUG 0 22#undef DEBUG
20 23
24#include <linux/device.h>
21#include <linux/module.h> 25#include <linux/module.h>
22#include <linux/kernel.h> 26#include <linux/kernel.h>
23#include <linux/types.h> 27#include <linux/types.h>
@@ -27,24 +31,113 @@
27#include <linux/vmalloc.h> 31#include <linux/vmalloc.h>
28#include <linux/fs.h> 32#include <linux/fs.h>
29#include <linux/errno.h> 33#include <linux/errno.h>
30#include <linux/reboot.h>
31#include <linux/smp_lock.h>
32#include <linux/wait.h> 34#include <linux/wait.h>
33#include <asm/uaccess.h>
34#include <asm/io.h> 35#include <asm/io.h>
35#include <asm/sibyte/sb1250.h> 36#include <asm/sibyte/sb1250.h>
37
38#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
39#include <asm/sibyte/bcm1480_regs.h>
40#include <asm/sibyte/bcm1480_scd.h>
41#include <asm/sibyte/bcm1480_int.h>
42#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
36#include <asm/sibyte/sb1250_regs.h> 43#include <asm/sibyte/sb1250_regs.h>
37#include <asm/sibyte/sb1250_scd.h> 44#include <asm/sibyte/sb1250_scd.h>
38#include <asm/sibyte/sb1250_int.h> 45#include <asm/sibyte/sb1250_int.h>
39#include <asm/sibyte/trace_prof.h> 46#else
47#error invalid SiByte UART configuation
48#endif
49
50#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
51#undef K_INT_TRACE_FREEZE
52#define K_INT_TRACE_FREEZE K_BCM1480_INT_TRACE_FREEZE
53#undef K_INT_PERF_CNT
54#define K_INT_PERF_CNT K_BCM1480_INT_PERF_CNT
55#endif
56
57#include <asm/system.h>
58#include <asm/uaccess.h>
40 59
41#define DEVNAME "bcm1250_tbprof" 60#define SBPROF_TB_MAJOR 240
61
62typedef u64 tb_sample_t[6*256];
63
64enum open_status {
65 SB_CLOSED,
66 SB_OPENING,
67 SB_OPEN
68};
69
70struct sbprof_tb {
71 wait_queue_head_t tb_sync;
72 wait_queue_head_t tb_read;
73 struct mutex lock;
74 enum open_status open;
75 tb_sample_t *sbprof_tbbuf;
76 int next_tb_sample;
77
78 volatile int tb_enable;
79 volatile int tb_armed;
80
81};
42 82
43static struct sbprof_tb sbp; 83static struct sbprof_tb sbp;
44 84
85#define MAX_SAMPLE_BYTES (24*1024*1024)
86#define MAX_TBSAMPLE_BYTES (12*1024*1024)
87
88#define MAX_SAMPLES (MAX_SAMPLE_BYTES/sizeof(u_int32_t))
89#define TB_SAMPLE_SIZE (sizeof(tb_sample_t))
90#define MAX_TB_SAMPLES (MAX_TBSAMPLE_BYTES/TB_SAMPLE_SIZE)
91
92/* ioctls */
93#define SBPROF_ZBSTART _IOW('s', 0, int)
94#define SBPROF_ZBSTOP _IOW('s', 1, int)
95#define SBPROF_ZBWAITFULL _IOW('s', 2, int)
96
97/*
98 * Routines for using 40-bit SCD cycle counter
99 *
100 * Client responsible for either handling interrupts or making sure
101 * the cycles counter never saturates, e.g., by doing
102 * zclk_timer_init(0) at least every 2^40 - 1 ZCLKs.
103 */
104
105/*
106 * Configures SCD counter 0 to count ZCLKs starting from val;
107 * Configures SCD counters1,2,3 to count nothing.
108 * Must not be called while gathering ZBbus profiles.
109 */
110
111#define zclk_timer_init(val) \
112 __asm__ __volatile__ (".set push;" \
113 ".set mips64;" \
114 "la $8, 0xb00204c0;" /* SCD perf_cnt_cfg */ \
115 "sd %0, 0x10($8);" /* write val to counter0 */ \
116 "sd %1, 0($8);" /* config counter0 for zclks*/ \
117 ".set pop" \
118 : /* no outputs */ \
119 /* enable, counter0 */ \
120 : /* inputs */ "r"(val), "r" ((1ULL << 33) | 1ULL) \
121 : /* modifies */ "$8" )
122
123
124/* Reads SCD counter 0 and puts result in value
125 unsigned long long val; */
126#define zclk_get(val) \
127 __asm__ __volatile__ (".set push;" \
128 ".set mips64;" \
129 "la $8, 0xb00204c0;" /* SCD perf_cnt_cfg */ \
130 "ld %0, 0x10($8);" /* write val to counter0 */ \
131 ".set pop" \
132 : /* outputs */ "=r"(val) \
133 : /* inputs */ \
134 : /* modifies */ "$8" )
135
136#define DEVNAME "sb_tbprof"
137
45#define TB_FULL (sbp.next_tb_sample == MAX_TB_SAMPLES) 138#define TB_FULL (sbp.next_tb_sample == MAX_TB_SAMPLES)
46 139
47/************************************************************************ 140/*
48 * Support for ZBbus sampling using the trace buffer 141 * Support for ZBbus sampling using the trace buffer
49 * 142 *
50 * We use the SCD performance counter interrupt, caused by a Zclk counter 143 * We use the SCD performance counter interrupt, caused by a Zclk counter
@@ -55,28 +148,46 @@ static struct sbprof_tb sbp;
55 * 148 *
56 * We map the interrupt for trace_buffer_freeze to handle it on CPU 0. 149 * We map the interrupt for trace_buffer_freeze to handle it on CPU 0.
57 * 150 *
58 ************************************************************************/ 151 */
59 152
60static u_int64_t tb_period; 153static u64 tb_period;
61 154
62static void arm_tb(void) 155static void arm_tb(void)
63{ 156{
64 u_int64_t scdperfcnt; 157 u64 scdperfcnt;
65 u_int64_t next = (1ULL << 40) - tb_period; 158 u64 next = (1ULL << 40) - tb_period;
66 u_int64_t tb_options = M_SCD_TRACE_CFG_FREEZE_FULL; 159 u64 tb_options = M_SCD_TRACE_CFG_FREEZE_FULL;
67 /* Generate an SCD_PERFCNT interrupt in TB_PERIOD Zclks to 160
68 trigger start of trace. XXX vary sampling period */ 161 /*
162 * Generate an SCD_PERFCNT interrupt in TB_PERIOD Zclks to
163 * trigger start of trace. XXX vary sampling period
164 */
69 __raw_writeq(0, IOADDR(A_SCD_PERF_CNT_1)); 165 __raw_writeq(0, IOADDR(A_SCD_PERF_CNT_1));
70 scdperfcnt = __raw_readq(IOADDR(A_SCD_PERF_CNT_CFG)); 166 scdperfcnt = __raw_readq(IOADDR(A_SCD_PERF_CNT_CFG));
71 /* Unfortunately, in Pass 2 we must clear all counters to knock down 167
72 a previous interrupt request. This means that bus profiling 168 /*
73 requires ALL of the SCD perf counters. */ 169 * Unfortunately, in Pass 2 we must clear all counters to knock down
170 * a previous interrupt request. This means that bus profiling
171 * requires ALL of the SCD perf counters.
172 */
173#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
174 __raw_writeq((scdperfcnt & ~M_SPC_CFG_SRC1) |
175 /* keep counters 0,2,3,4,5,6,7 as is */
176 V_SPC_CFG_SRC1(1), /* counter 1 counts cycles */
177 IOADDR(A_BCM1480_SCD_PERF_CNT_CFG0));
178 __raw_writeq(
179 M_SPC_CFG_ENABLE | /* enable counting */
180 M_SPC_CFG_CLEAR | /* clear all counters */
181 V_SPC_CFG_SRC1(1), /* counter 1 counts cycles */
182 IOADDR(A_BCM1480_SCD_PERF_CNT_CFG1));
183#else
74 __raw_writeq((scdperfcnt & ~M_SPC_CFG_SRC1) | 184 __raw_writeq((scdperfcnt & ~M_SPC_CFG_SRC1) |
75 // keep counters 0,2,3 as is 185 /* keep counters 0,2,3 as is */
76 M_SPC_CFG_ENABLE | // enable counting 186 M_SPC_CFG_ENABLE | /* enable counting */
77 M_SPC_CFG_CLEAR | // clear all counters 187 M_SPC_CFG_CLEAR | /* clear all counters */
78 V_SPC_CFG_SRC1(1), // counter 1 counts cycles 188 V_SPC_CFG_SRC1(1), /* counter 1 counts cycles */
79 IOADDR(A_SCD_PERF_CNT_CFG)); 189 IOADDR(A_SCD_PERF_CNT_CFG));
190#endif
80 __raw_writeq(next, IOADDR(A_SCD_PERF_CNT_1)); 191 __raw_writeq(next, IOADDR(A_SCD_PERF_CNT_1));
81 /* Reset the trace buffer */ 192 /* Reset the trace buffer */
82 __raw_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG)); 193 __raw_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
@@ -91,49 +202,51 @@ static void arm_tb(void)
91static irqreturn_t sbprof_tb_intr(int irq, void *dev_id) 202static irqreturn_t sbprof_tb_intr(int irq, void *dev_id)
92{ 203{
93 int i; 204 int i;
94 DBG(printk(DEVNAME ": tb_intr\n")); 205
206 pr_debug(DEVNAME ": tb_intr\n");
207
95 if (sbp.next_tb_sample < MAX_TB_SAMPLES) { 208 if (sbp.next_tb_sample < MAX_TB_SAMPLES) {
96 /* XXX should use XKPHYS to make writes bypass L2 */ 209 /* XXX should use XKPHYS to make writes bypass L2 */
97 u_int64_t *p = sbp.sbprof_tbbuf[sbp.next_tb_sample++]; 210 u64 *p = sbp.sbprof_tbbuf[sbp.next_tb_sample++];
98 /* Read out trace */ 211 /* Read out trace */
99 __raw_writeq(M_SCD_TRACE_CFG_START_READ, 212 __raw_writeq(M_SCD_TRACE_CFG_START_READ,
100 IOADDR(A_SCD_TRACE_CFG)); 213 IOADDR(A_SCD_TRACE_CFG));
101 __asm__ __volatile__ ("sync" : : : "memory"); 214 __asm__ __volatile__ ("sync" : : : "memory");
102 /* Loop runs backwards because bundles are read out in reverse order */ 215 /* Loop runs backwards because bundles are read out in reverse order */
103 for (i = 256 * 6; i > 0; i -= 6) { 216 for (i = 256 * 6; i > 0; i -= 6) {
104 // Subscripts decrease to put bundle in the order 217 /* Subscripts decrease to put bundle in the order */
105 // t0 lo, t0 hi, t1 lo, t1 hi, t2 lo, t2 hi 218 /* t0 lo, t0 hi, t1 lo, t1 hi, t2 lo, t2 hi */
106 p[i - 1] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); 219 p[i - 1] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
107 // read t2 hi 220 /* read t2 hi */
108 p[i - 2] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); 221 p[i - 2] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
109 // read t2 lo 222 /* read t2 lo */
110 p[i - 3] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); 223 p[i - 3] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
111 // read t1 hi 224 /* read t1 hi */
112 p[i - 4] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); 225 p[i - 4] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
113 // read t1 lo 226 /* read t1 lo */
114 p[i - 5] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); 227 p[i - 5] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
115 // read t0 hi 228 /* read t0 hi */
116 p[i - 6] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); 229 p[i - 6] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
117 // read t0 lo 230 /* read t0 lo */
118 } 231 }
119 if (!sbp.tb_enable) { 232 if (!sbp.tb_enable) {
120 DBG(printk(DEVNAME ": tb_intr shutdown\n")); 233 pr_debug(DEVNAME ": tb_intr shutdown\n");
121 __raw_writeq(M_SCD_TRACE_CFG_RESET, 234 __raw_writeq(M_SCD_TRACE_CFG_RESET,
122 IOADDR(A_SCD_TRACE_CFG)); 235 IOADDR(A_SCD_TRACE_CFG));
123 sbp.tb_armed = 0; 236 sbp.tb_armed = 0;
124 wake_up(&sbp.tb_sync); 237 wake_up_interruptible(&sbp.tb_sync);
125 } else { 238 } else {
126 arm_tb(); // knock down current interrupt and get another one later 239 /* knock down current interrupt and get another one later */
240 arm_tb();
127 } 241 }
128 } else { 242 } else {
129 /* No more trace buffer samples */ 243 /* No more trace buffer samples */
130 DBG(printk(DEVNAME ": tb_intr full\n")); 244 pr_debug(DEVNAME ": tb_intr full\n");
131 __raw_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG)); 245 __raw_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
132 sbp.tb_armed = 0; 246 sbp.tb_armed = 0;
133 if (!sbp.tb_enable) { 247 if (!sbp.tb_enable)
134 wake_up(&sbp.tb_sync); 248 wake_up_interruptible(&sbp.tb_sync);
135 } 249 wake_up_interruptible(&sbp.tb_read);
136 wake_up(&sbp.tb_read);
137 } 250 }
138 return IRQ_HANDLED; 251 return IRQ_HANDLED;
139} 252}
@@ -144,23 +257,30 @@ static irqreturn_t sbprof_pc_intr(int irq, void *dev_id)
144 return IRQ_NONE; 257 return IRQ_NONE;
145} 258}
146 259
147int sbprof_zbprof_start(struct file *filp) 260/*
261 * Requires: Already called zclk_timer_init with a value that won't
262 * saturate 40 bits. No subsequent use of SCD performance counters
263 * or trace buffer.
264 */
265
266static int sbprof_zbprof_start(struct file *filp)
148{ 267{
149 u_int64_t scdperfcnt; 268 u64 scdperfcnt;
269 int err;
150 270
151 if (sbp.tb_enable) 271 if (xchg(&sbp.tb_enable, 1))
152 return -EBUSY; 272 return -EBUSY;
153 273
154 DBG(printk(DEVNAME ": starting\n")); 274 pr_debug(DEVNAME ": starting\n");
155 275
156 sbp.tb_enable = 1;
157 sbp.next_tb_sample = 0; 276 sbp.next_tb_sample = 0;
158 filp->f_pos = 0; 277 filp->f_pos = 0;
159 278
160 if (request_irq 279 err = request_irq (K_INT_TRACE_FREEZE, sbprof_tb_intr, 0,
161 (K_INT_TRACE_FREEZE, sbprof_tb_intr, 0, DEVNAME " trace freeze", &sbp)) { 280 DEVNAME " trace freeze", &sbp);
281 if (err)
162 return -EBUSY; 282 return -EBUSY;
163 } 283
164 /* Make sure there isn't a perf-cnt interrupt waiting */ 284 /* Make sure there isn't a perf-cnt interrupt waiting */
165 scdperfcnt = __raw_readq(IOADDR(A_SCD_PERF_CNT_CFG)); 285 scdperfcnt = __raw_readq(IOADDR(A_SCD_PERF_CNT_CFG));
166 /* Disable and clear counters, override SRC_1 */ 286 /* Disable and clear counters, override SRC_1 */
@@ -168,21 +288,30 @@ int sbprof_zbprof_start(struct file *filp)
168 M_SPC_CFG_ENABLE | M_SPC_CFG_CLEAR | V_SPC_CFG_SRC1(1), 288 M_SPC_CFG_ENABLE | M_SPC_CFG_CLEAR | V_SPC_CFG_SRC1(1),
169 IOADDR(A_SCD_PERF_CNT_CFG)); 289 IOADDR(A_SCD_PERF_CNT_CFG));
170 290
171 /* We grab this interrupt to prevent others from trying to use 291 /*
172 it, even though we don't want to service the interrupts 292 * We grab this interrupt to prevent others from trying to use
173 (they only feed into the trace-on-interrupt mechanism) */ 293 * it, even though we don't want to service the interrupts
174 if (request_irq 294 * (they only feed into the trace-on-interrupt mechanism)
175 (K_INT_PERF_CNT, sbprof_pc_intr, 0, DEVNAME " scd perfcnt", &sbp)) { 295 */
296 if (request_irq(K_INT_PERF_CNT, sbprof_pc_intr, 0, DEVNAME " scd perfcnt", &sbp)) {
176 free_irq(K_INT_TRACE_FREEZE, &sbp); 297 free_irq(K_INT_TRACE_FREEZE, &sbp);
177 return -EBUSY; 298 return -EBUSY;
178 } 299 }
179 300
180 /* I need the core to mask these, but the interrupt mapper to 301 /*
181 pass them through. I am exploiting my knowledge that 302 * I need the core to mask these, but the interrupt mapper to
182 cp0_status masks out IP[5]. krw */ 303 * pass them through. I am exploiting my knowledge that
304 * cp0_status masks out IP[5]. krw
305 */
306#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
307 __raw_writeq(K_BCM1480_INT_MAP_I3,
308 IOADDR(A_BCM1480_IMR_REGISTER(0, R_BCM1480_IMR_INTERRUPT_MAP_BASE_L) +
309 ((K_BCM1480_INT_PERF_CNT & 0x3f) << 3)));
310#else
183 __raw_writeq(K_INT_MAP_I3, 311 __raw_writeq(K_INT_MAP_I3,
184 IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) + 312 IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
185 (K_INT_PERF_CNT << 3))); 313 (K_INT_PERF_CNT << 3)));
314#endif
186 315
187 /* Initialize address traps */ 316 /* Initialize address traps */
188 __raw_writeq(0, IOADDR(A_ADDR_TRAP_UP_0)); 317 __raw_writeq(0, IOADDR(A_ADDR_TRAP_UP_0));
@@ -201,7 +330,7 @@ int sbprof_zbprof_start(struct file *filp)
201 __raw_writeq(0, IOADDR(A_ADDR_TRAP_CFG_3)); 330 __raw_writeq(0, IOADDR(A_ADDR_TRAP_CFG_3));
202 331
203 /* Initialize Trace Event 0-7 */ 332 /* Initialize Trace Event 0-7 */
204 // when interrupt 333 /* when interrupt */
205 __raw_writeq(M_SCD_TREVT_INTERRUPT, IOADDR(A_SCD_TRACE_EVENT_0)); 334 __raw_writeq(M_SCD_TREVT_INTERRUPT, IOADDR(A_SCD_TRACE_EVENT_0));
206 __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_1)); 335 __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_1));
207 __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_2)); 336 __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_2));
@@ -212,10 +341,10 @@ int sbprof_zbprof_start(struct file *filp)
212 __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_7)); 341 __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_7));
213 342
214 /* Initialize Trace Sequence 0-7 */ 343 /* Initialize Trace Sequence 0-7 */
215 // Start on event 0 (interrupt) 344 /* Start on event 0 (interrupt) */
216 __raw_writeq(V_SCD_TRSEQ_FUNC_START | 0x0fff, 345 __raw_writeq(V_SCD_TRSEQ_FUNC_START | 0x0fff,
217 IOADDR(A_SCD_TRACE_SEQUENCE_0)); 346 IOADDR(A_SCD_TRACE_SEQUENCE_0));
218 // dsamp when d used | asamp when a used 347 /* dsamp when d used | asamp when a used */
219 __raw_writeq(M_SCD_TRSEQ_ASAMPLE | M_SCD_TRSEQ_DSAMPLE | 348 __raw_writeq(M_SCD_TRSEQ_ASAMPLE | M_SCD_TRSEQ_DSAMPLE |
220 K_SCD_TRSEQ_TRIGGER_ALL, 349 K_SCD_TRSEQ_TRIGGER_ALL,
221 IOADDR(A_SCD_TRACE_SEQUENCE_1)); 350 IOADDR(A_SCD_TRACE_SEQUENCE_1));
@@ -227,40 +356,47 @@ int sbprof_zbprof_start(struct file *filp)
227 __raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_7)); 356 __raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_7));
228 357
229 /* Now indicate the PERF_CNT interrupt as a trace-relevant interrupt */ 358 /* Now indicate the PERF_CNT interrupt as a trace-relevant interrupt */
359#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
360 __raw_writeq(1ULL << (K_BCM1480_INT_PERF_CNT & 0x3f),
361 IOADDR(A_BCM1480_IMR_REGISTER(0, R_BCM1480_IMR_INTERRUPT_TRACE_L)));
362#else
230 __raw_writeq(1ULL << K_INT_PERF_CNT, 363 __raw_writeq(1ULL << K_INT_PERF_CNT,
231 IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_TRACE))); 364 IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_TRACE)));
232 365#endif
233 arm_tb(); 366 arm_tb();
234 367
235 DBG(printk(DEVNAME ": done starting\n")); 368 pr_debug(DEVNAME ": done starting\n");
236 369
237 return 0; 370 return 0;
238} 371}
239 372
240int sbprof_zbprof_stop(void) 373static int sbprof_zbprof_stop(void)
241{ 374{
242 DEFINE_WAIT(wait); 375 int err = 0;
243 DBG(printk(DEVNAME ": stopping\n")); 376
377 pr_debug(DEVNAME ": stopping\n");
244 378
245 if (sbp.tb_enable) { 379 if (sbp.tb_enable) {
380 /*
381 * XXXKW there is a window here where the intr handler may run,
382 * see the disable, and do the wake_up before this sleep
383 * happens.
384 */
385 pr_debug(DEVNAME ": wait for disarm\n");
386 err = wait_event_interruptible(sbp.tb_sync, !sbp.tb_armed);
387 pr_debug(DEVNAME ": disarm complete, stat %d\n", err);
388
389 if (err)
390 return err;
391
246 sbp.tb_enable = 0; 392 sbp.tb_enable = 0;
247 /* XXXKW there is a window here where the intr handler
248 may run, see the disable, and do the wake_up before
249 this sleep happens. */
250 if (sbp.tb_armed) {
251 DBG(printk(DEVNAME ": wait for disarm\n"));
252 prepare_to_wait(&sbp.tb_sync, &wait, TASK_INTERRUPTIBLE);
253 schedule();
254 finish_wait(&sbp.tb_sync, &wait);
255 DBG(printk(DEVNAME ": disarm complete\n"));
256 }
257 free_irq(K_INT_TRACE_FREEZE, &sbp); 393 free_irq(K_INT_TRACE_FREEZE, &sbp);
258 free_irq(K_INT_PERF_CNT, &sbp); 394 free_irq(K_INT_PERF_CNT, &sbp);
259 } 395 }
260 396
261 DBG(printk(DEVNAME ": done stopping\n")); 397 pr_debug(DEVNAME ": done stopping\n");
262 398
263 return 0; 399 return err;
264} 400}
265 401
266static int sbprof_tb_open(struct inode *inode, struct file *filp) 402static int sbprof_tb_open(struct inode *inode, struct file *filp)
@@ -268,22 +404,22 @@ static int sbprof_tb_open(struct inode *inode, struct file *filp)
268 int minor; 404 int minor;
269 405
270 minor = iminor(inode); 406 minor = iminor(inode);
271 if (minor != 0) { 407 if (minor != 0)
272 return -ENODEV; 408 return -ENODEV;
273 } 409
274 if (sbp.open) { 410 if (xchg(&sbp.open, SB_OPENING) != SB_CLOSED)
275 return -EBUSY; 411 return -EBUSY;
276 }
277 412
278 memset(&sbp, 0, sizeof(struct sbprof_tb)); 413 memset(&sbp, 0, sizeof(struct sbprof_tb));
279 sbp.sbprof_tbbuf = vmalloc(MAX_TBSAMPLE_BYTES); 414 sbp.sbprof_tbbuf = vmalloc(MAX_TBSAMPLE_BYTES);
280 if (!sbp.sbprof_tbbuf) { 415 if (!sbp.sbprof_tbbuf)
281 return -ENOMEM; 416 return -ENOMEM;
282 }
283 memset(sbp.sbprof_tbbuf, 0, MAX_TBSAMPLE_BYTES); 417 memset(sbp.sbprof_tbbuf, 0, MAX_TBSAMPLE_BYTES);
284 init_waitqueue_head(&sbp.tb_sync); 418 init_waitqueue_head(&sbp.tb_sync);
285 init_waitqueue_head(&sbp.tb_read); 419 init_waitqueue_head(&sbp.tb_read);
286 sbp.open = 1; 420 mutex_init(&sbp.lock);
421
422 sbp.open = SB_OPEN;
287 423
288 return 0; 424 return 0;
289} 425}
@@ -293,17 +429,19 @@ static int sbprof_tb_release(struct inode *inode, struct file *filp)
293 int minor; 429 int minor;
294 430
295 minor = iminor(inode); 431 minor = iminor(inode);
296 if (minor != 0 || !sbp.open) { 432 if (minor != 0 || !sbp.open)
297 return -ENODEV; 433 return -ENODEV;
298 }
299 434
300 if (sbp.tb_armed || sbp.tb_enable) { 435 mutex_lock(&sbp.lock);
436
437 if (sbp.tb_armed || sbp.tb_enable)
301 sbprof_zbprof_stop(); 438 sbprof_zbprof_stop();
302 }
303 439
304 vfree(sbp.sbprof_tbbuf); 440 vfree(sbp.sbprof_tbbuf);
305 sbp.open = 0; 441 sbp.open = 0;
306 442
443 mutex_unlock(&sbp.lock);
444
307 return 0; 445 return 0;
308} 446}
309 447
@@ -316,16 +454,29 @@ static ssize_t sbprof_tb_read(struct file *filp, char *buf,
316 char *dest = buf; 454 char *dest = buf;
317 long cur_off = *offp; 455 long cur_off = *offp;
318 456
457 if (!access_ok(VERIFY_WRITE, buf, size))
458 return -EFAULT;
459
460 mutex_lock(&sbp.lock);
461
319 count = 0; 462 count = 0;
320 cur_sample = cur_off / TB_SAMPLE_SIZE; 463 cur_sample = cur_off / TB_SAMPLE_SIZE;
321 sample_off = cur_off % TB_SAMPLE_SIZE; 464 sample_off = cur_off % TB_SAMPLE_SIZE;
322 sample_left = TB_SAMPLE_SIZE - sample_off; 465 sample_left = TB_SAMPLE_SIZE - sample_off;
466
323 while (size && (cur_sample < sbp.next_tb_sample)) { 467 while (size && (cur_sample < sbp.next_tb_sample)) {
468 int err;
469
324 cur_count = size < sample_left ? size : sample_left; 470 cur_count = size < sample_left ? size : sample_left;
325 src = (char *)(((long)sbp.sbprof_tbbuf[cur_sample])+sample_off); 471 src = (char *)(((long)sbp.sbprof_tbbuf[cur_sample])+sample_off);
326 copy_to_user(dest, src, cur_count); 472 err = __copy_to_user(dest, src, cur_count);
327 DBG(printk(DEVNAME ": read from sample %d, %d bytes\n", 473 if (err) {
328 cur_sample, cur_count)); 474 *offp = cur_off + cur_count - err;
475 mutex_unlock(&sbp.lock);
476 return err;
477 }
478 pr_debug(DEVNAME ": read from sample %d, %d bytes\n",
479 cur_sample, cur_count);
329 size -= cur_count; 480 size -= cur_count;
330 sample_left -= cur_count; 481 sample_left -= cur_count;
331 if (!sample_left) { 482 if (!sample_left) {
@@ -340,6 +491,7 @@ static ssize_t sbprof_tb_read(struct file *filp, char *buf,
340 count += cur_count; 491 count += cur_count;
341 } 492 }
342 *offp = cur_off; 493 *offp = cur_off;
494 mutex_unlock(&sbp.lock);
343 495
344 return count; 496 return count;
345} 497}
@@ -348,30 +500,36 @@ static long sbprof_tb_ioctl(struct file *filp,
348 unsigned int command, 500 unsigned int command,
349 unsigned long arg) 501 unsigned long arg)
350{ 502{
351 int error = 0; 503 int err = 0;
352 504
353 lock_kernel();
354 switch (command) { 505 switch (command) {
355 case SBPROF_ZBSTART: 506 case SBPROF_ZBSTART:
356 error = sbprof_zbprof_start(filp); 507 mutex_lock(&sbp.lock);
508 err = sbprof_zbprof_start(filp);
509 mutex_unlock(&sbp.lock);
357 break; 510 break;
511
358 case SBPROF_ZBSTOP: 512 case SBPROF_ZBSTOP:
359 error = sbprof_zbprof_stop(); 513 mutex_lock(&sbp.lock);
514 err = sbprof_zbprof_stop();
515 mutex_unlock(&sbp.lock);
516 break;
517
518 case SBPROF_ZBWAITFULL: {
519 err = wait_event_interruptible(sbp.tb_read, TB_FULL);
520 if (err)
521 break;
522
523 err = put_user(TB_FULL, (int *) arg);
360 break; 524 break;
361 case SBPROF_ZBWAITFULL: 525 }
362 DEFINE_WAIT(wait); 526
363 prepare_to_wait(&sbp.tb_read, &wait, TASK_INTERRUPTIBLE);
364 schedule();
365 finish_wait(&sbp.tb_read, &wait);
366 /* XXXKW check if interrupted? */
367 return put_user(TB_FULL, (int *) arg);
368 default: 527 default:
369 error = -EINVAL; 528 err = -EINVAL;
370 break; 529 break;
371 } 530 }
372 unlock_kernel();
373 531
374 return error; 532 return err;
375} 533}
376 534
377static const struct file_operations sbprof_tb_fops = { 535static const struct file_operations sbprof_tb_fops = {
@@ -384,23 +542,60 @@ static const struct file_operations sbprof_tb_fops = {
384 .mmap = NULL, 542 .mmap = NULL,
385}; 543};
386 544
545static struct class *tb_class;
546static struct device *tb_dev;
547
387static int __init sbprof_tb_init(void) 548static int __init sbprof_tb_init(void)
388{ 549{
550 struct device *dev;
551 struct class *tbc;
552 int err;
553
389 if (register_chrdev(SBPROF_TB_MAJOR, DEVNAME, &sbprof_tb_fops)) { 554 if (register_chrdev(SBPROF_TB_MAJOR, DEVNAME, &sbprof_tb_fops)) {
390 printk(KERN_WARNING DEVNAME ": initialization failed (dev %d)\n", 555 printk(KERN_WARNING DEVNAME ": initialization failed (dev %d)\n",
391 SBPROF_TB_MAJOR); 556 SBPROF_TB_MAJOR);
392 return -EIO; 557 return -EIO;
393 } 558 }
559
560 tbc = class_create(THIS_MODULE, "sb_tracebuffer");
561 if (IS_ERR(tbc)) {
562 err = PTR_ERR(tbc);
563 goto out_chrdev;
564 }
565
566 tb_class = tbc;
567
568 dev = device_create(tbc, NULL, MKDEV(SBPROF_TB_MAJOR, 0), "tb");
569 if (IS_ERR(dev)) {
570 err = PTR_ERR(dev);
571 goto out_class;
572 }
573 tb_dev = dev;
574
394 sbp.open = 0; 575 sbp.open = 0;
395 tb_period = zbbus_mhz * 10000LL; 576 tb_period = zbbus_mhz * 10000LL;
396 printk(KERN_INFO DEVNAME ": initialized - tb_period = %lld\n", tb_period); 577 pr_info(DEVNAME ": initialized - tb_period = %lld\n",
578 (long long) tb_period);
397 return 0; 579 return 0;
580
581out_class:
582 class_destroy(tb_class);
583out_chrdev:
584 unregister_chrdev(SBPROF_TB_MAJOR, DEVNAME);
585
586 return err;
398} 587}
399 588
400static void __exit sbprof_tb_cleanup(void) 589static void __exit sbprof_tb_cleanup(void)
401{ 590{
591 device_destroy(tb_class, MKDEV(SBPROF_TB_MAJOR, 0));
402 unregister_chrdev(SBPROF_TB_MAJOR, DEVNAME); 592 unregister_chrdev(SBPROF_TB_MAJOR, DEVNAME);
593 class_destroy(tb_class);
403} 594}
404 595
405module_init(sbprof_tb_init); 596module_init(sbprof_tb_init);
406module_exit(sbprof_tb_cleanup); 597module_exit(sbprof_tb_cleanup);
598
599MODULE_ALIAS_CHARDEV_MAJOR(SBPROF_TB_MAJOR);
600MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
601MODULE_LICENSE("GPL");
diff --git a/arch/mips/sibyte/sb1250/Makefile b/arch/mips/sibyte/sb1250/Makefile
index a2fdbd62f8ac..df662c61473a 100644
--- a/arch/mips/sibyte/sb1250/Makefile
+++ b/arch/mips/sibyte/sb1250/Makefile
@@ -1,8 +1,5 @@
1obj-y := setup.o irq.o time.o 1obj-y := setup.o irq.o time.o
2 2
3obj-$(CONFIG_SMP) += smp.o 3obj-$(CONFIG_SMP) += smp.o
4obj-$(CONFIG_SIBYTE_TBPROF) += bcm1250_tbprof.o
5obj-$(CONFIG_SIBYTE_STANDALONE) += prom.o 4obj-$(CONFIG_SIBYTE_STANDALONE) += prom.o
6obj-$(CONFIG_SIBYTE_BUS_WATCHER) += bus_watcher.o 5obj-$(CONFIG_SIBYTE_BUS_WATCHER) += bus_watcher.o
7
8EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index 148239446e6e..0e6a13c0bd0e 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -421,7 +421,7 @@ asmlinkage void plat_irq_dispatch(void)
421 * blasting the high 32 bits. 421 * blasting the high 32 bits.
422 */ 422 */
423 423
424 pending = read_c0_cause() & read_c0_status(); 424 pending = read_c0_cause() & read_c0_status() & ST0_IM;
425 425
426#ifdef CONFIG_SIBYTE_SB1250_PROF 426#ifdef CONFIG_SIBYTE_SB1250_PROF
427 if (pending & CAUSEF_IP7) /* Cpu performance counter interrupt */ 427 if (pending & CAUSEF_IP7) /* Cpu performance counter interrupt */
diff --git a/arch/mips/sibyte/sb1250/setup.c b/arch/mips/sibyte/sb1250/setup.c
index d0ee1d5b8223..f4a6169aa0a4 100644
--- a/arch/mips/sibyte/sb1250/setup.c
+++ b/arch/mips/sibyte/sb1250/setup.c
@@ -16,6 +16,7 @@
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */ 17 */
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/module.h>
19#include <linux/kernel.h> 20#include <linux/kernel.h>
20#include <linux/reboot.h> 21#include <linux/reboot.h>
21#include <linux/string.h> 22#include <linux/string.h>
@@ -32,6 +33,7 @@ unsigned int soc_pass;
32unsigned int soc_type; 33unsigned int soc_type;
33unsigned int periph_rev; 34unsigned int periph_rev;
34unsigned int zbbus_mhz; 35unsigned int zbbus_mhz;
36EXPORT_SYMBOL(zbbus_mhz);
35 37
36static char *soc_str; 38static char *soc_str;
37static char *pass_str; 39static char *pass_str;
@@ -67,7 +69,7 @@ static int __init sys_rev_decode(void)
67 ret = setup_bcm112x(); 69 ret = setup_bcm112x();
68 break; 70 break;
69 default: 71 default:
70 prom_printf("Unknown SOC type %x\n", soc_type); 72 printk("Unknown SOC type %x\n", soc_type);
71 ret = 1; 73 ret = 1;
72 break; 74 break;
73 } 75 }
@@ -112,7 +114,7 @@ static int __init setup_bcm1250(void)
112 pass_str = "A0-A6"; 114 pass_str = "A0-A6";
113 war_pass = K_SYS_REVISION_BCM1250_PASS2; 115 war_pass = K_SYS_REVISION_BCM1250_PASS2;
114 } else { 116 } else {
115 prom_printf("Unknown BCM1250 rev %x\n", soc_pass); 117 printk("Unknown BCM1250 rev %x\n", soc_pass);
116 ret = 1; 118 ret = 1;
117 } 119 }
118 break; 120 break;
@@ -139,8 +141,20 @@ static int __init setup_bcm112x(void)
139 periph_rev = 3; 141 periph_rev = 3;
140 pass_str = "A2"; 142 pass_str = "A2";
141 break; 143 break;
144 case K_SYS_REVISION_BCM112x_A3:
145 periph_rev = 3;
146 pass_str = "A3";
147 break;
148 case K_SYS_REVISION_BCM112x_A4:
149 periph_rev = 3;
150 pass_str = "A4";
151 break;
152 case K_SYS_REVISION_BCM112x_B0:
153 periph_rev = 3;
154 pass_str = "B0";
155 break;
142 default: 156 default:
143 prom_printf("Unknown %s rev %x\n", soc_str, soc_pass); 157 printk("Unknown %s rev %x\n", soc_str, soc_pass);
144 ret = 1; 158 ret = 1;
145 } 159 }
146 return ret; 160 return ret;
@@ -158,21 +172,21 @@ void __init sb1250_setup(void)
158 soc_pass = G_SYS_REVISION(sys_rev); 172 soc_pass = G_SYS_REVISION(sys_rev);
159 173
160 if (sys_rev_decode()) { 174 if (sys_rev_decode()) {
161 prom_printf("Restart after failure to identify SiByte chip\n"); 175 printk("Restart after failure to identify SiByte chip\n");
162 machine_restart(NULL); 176 machine_restart(NULL);
163 } 177 }
164 178
165 plldiv = G_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG))); 179 plldiv = G_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG)));
166 zbbus_mhz = ((plldiv >> 1) * 50) + ((plldiv & 1) * 25); 180 zbbus_mhz = ((plldiv >> 1) * 50) + ((plldiv & 1) * 25);
167 181
168 prom_printf("Broadcom SiByte %s %s @ %d MHz (SB1 rev %d)\n", 182 printk("Broadcom SiByte %s %s @ %d MHz (SB1 rev %d)\n",
169 soc_str, pass_str, zbbus_mhz * 2, sb1_pass); 183 soc_str, pass_str, zbbus_mhz * 2, sb1_pass);
170 prom_printf("Board type: %s\n", get_system_type()); 184 printk("Board type: %s\n", get_system_type());
171 185
172 switch (war_pass) { 186 switch (war_pass) {
173 case K_SYS_REVISION_BCM1250_PASS1: 187 case K_SYS_REVISION_BCM1250_PASS1:
174#ifndef CONFIG_SB1_PASS_1_WORKAROUNDS 188#ifndef CONFIG_SB1_PASS_1_WORKAROUNDS
175 prom_printf("@@@@ This is a BCM1250 A0-A2 (Pass 1) board, " 189 printk("@@@@ This is a BCM1250 A0-A2 (Pass 1) board, "
176 "and the kernel doesn't have the proper " 190 "and the kernel doesn't have the proper "
177 "workarounds compiled in. @@@@\n"); 191 "workarounds compiled in. @@@@\n");
178 bad_config = 1; 192 bad_config = 1;
@@ -182,27 +196,27 @@ void __init sb1250_setup(void)
182 /* Pass 2 - easiest as default for now - so many numbers */ 196 /* Pass 2 - easiest as default for now - so many numbers */
183#if !defined(CONFIG_SB1_PASS_2_WORKAROUNDS) || \ 197#if !defined(CONFIG_SB1_PASS_2_WORKAROUNDS) || \
184 !defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) 198 !defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS)
185 prom_printf("@@@@ This is a BCM1250 A3-A10 board, and the " 199 printk("@@@@ This is a BCM1250 A3-A10 board, and the "
186 "kernel doesn't have the proper workarounds " 200 "kernel doesn't have the proper workarounds "
187 "compiled in. @@@@\n"); 201 "compiled in. @@@@\n");
188 bad_config = 1; 202 bad_config = 1;
189#endif 203#endif
190#ifdef CONFIG_CPU_HAS_PREFETCH 204#ifdef CONFIG_CPU_HAS_PREFETCH
191 prom_printf("@@@@ Prefetches may be enabled in this kernel, " 205 printk("@@@@ Prefetches may be enabled in this kernel, "
192 "but are buggy on this board. @@@@\n"); 206 "but are buggy on this board. @@@@\n");
193 bad_config = 1; 207 bad_config = 1;
194#endif 208#endif
195 break; 209 break;
196 case K_SYS_REVISION_BCM1250_PASS2_2: 210 case K_SYS_REVISION_BCM1250_PASS2_2:
197#ifndef CONFIG_SB1_PASS_2_WORKAROUNDS 211#ifndef CONFIG_SB1_PASS_2_WORKAROUNDS
198 prom_printf("@@@@ This is a BCM1250 B1/B2. board, and the " 212 printk("@@@@ This is a BCM1250 B1/B2. board, and the "
199 "kernel doesn't have the proper workarounds " 213 "kernel doesn't have the proper workarounds "
200 "compiled in. @@@@\n"); 214 "compiled in. @@@@\n");
201 bad_config = 1; 215 bad_config = 1;
202#endif 216#endif
203#if defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) || \ 217#if defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) || \
204 !defined(CONFIG_CPU_HAS_PREFETCH) 218 !defined(CONFIG_CPU_HAS_PREFETCH)
205 prom_printf("@@@@ This is a BCM1250 B1/B2, but the kernel is " 219 printk("@@@@ This is a BCM1250 B1/B2, but the kernel is "
206 "conservatively configured for an 'A' stepping. " 220 "conservatively configured for an 'A' stepping. "
207 "@@@@\n"); 221 "@@@@\n");
208#endif 222#endif
@@ -211,7 +225,7 @@ void __init sb1250_setup(void)
211 break; 225 break;
212 } 226 }
213 if (bad_config) { 227 if (bad_config) {
214 prom_printf("Invalid configuration for this chip.\n"); 228 printk("Invalid configuration for this chip.\n");
215 machine_restart(NULL); 229 machine_restart(NULL);
216 } 230 }
217} 231}
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c
index defa1f1452ad..83572d8f3e14 100644
--- a/arch/mips/sibyte/swarm/setup.c
+++ b/arch/mips/sibyte/swarm/setup.c
@@ -169,17 +169,19 @@ void __init plat_mem_setup(void)
169#define LEDS_PHYS MLEDS_PHYS 169#define LEDS_PHYS MLEDS_PHYS
170#endif 170#endif
171 171
172#define setled(index, c) \
173 ((unsigned char *)(IOADDR(LEDS_PHYS)+0x20))[(3-(index))<<3] = (c)
174void setleds(char *str) 172void setleds(char *str)
175{ 173{
174 void *reg;
176 int i; 175 int i;
176
177 for (i = 0; i < 4; i++) { 177 for (i = 0; i < 4; i++) {
178 if (!str[i]) { 178 reg = IOADDR(LEDS_PHYS) + 0x20 + ((3 - i) << 3);
179 setled(i, ' '); 179
180 } else { 180 if (!str[i])
181 setled(i, str[i]); 181 writeb(' ', reg);
182 } 182 else
183 writeb(str[i], reg);
183 } 184 }
184} 185}
185#endif 186
187#endif /* LEDS_PHYS */