diff options
author | Mike Frysinger <vapier.adi@gmail.com> | 2008-11-18 04:48:22 -0500 |
---|---|---|
committer | Bryan Wu <cooloney@kernel.org> | 2008-11-18 04:48:22 -0500 |
commit | ff4c02e4be00dccfb4b7baa8e56300b6ab3e290a (patch) | |
tree | 75093ea97d661d59f5b7e882f05cb99dbad8fae7 /arch | |
parent | 4db557d4aeb6a9a6713e66e222949bc93b2bf2e9 (diff) |
Blackfin arch: unify cplbinfo files
Merge MPU and noMPU version of CPLB info code to one common version.
Signed-off-by: Mike Frysinger <vapier.adi@gmail.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/blackfin/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/blackfin/kernel/cplb-mpu/Makefile | 3 | ||||
-rw-r--r-- | arch/blackfin/kernel/cplb-mpu/cplbinfo.c | 149 | ||||
-rw-r--r-- | arch/blackfin/kernel/cplb-nompu/Makefile | 3 | ||||
-rw-r--r-- | arch/blackfin/kernel/cplb-nompu/cplbinfo.c | 208 | ||||
-rw-r--r-- | arch/blackfin/kernel/cplbinfo.c | 200 |
6 files changed, 201 insertions, 363 deletions
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile index 751115970dee..01a60ca69216 100644 --- a/arch/blackfin/kernel/Makefile +++ b/arch/blackfin/kernel/Makefile | |||
@@ -16,6 +16,7 @@ else | |||
16 | endif | 16 | endif |
17 | 17 | ||
18 | obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o | 18 | obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o |
19 | obj-$(CONFIG_CPLB_INFO) += cplbinfo.o | ||
19 | obj-$(CONFIG_MODULES) += module.o | 20 | obj-$(CONFIG_MODULES) += module.o |
20 | obj-$(CONFIG_KGDB) += kgdb.o | 21 | obj-$(CONFIG_KGDB) += kgdb.o |
21 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 22 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
diff --git a/arch/blackfin/kernel/cplb-mpu/Makefile b/arch/blackfin/kernel/cplb-mpu/Makefile index 286b69357f97..bd92301a704b 100644 --- a/arch/blackfin/kernel/cplb-mpu/Makefile +++ b/arch/blackfin/kernel/cplb-mpu/Makefile | |||
@@ -3,6 +3,3 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := cplbinit.o cacheinit.o cplbmgr.o | 5 | obj-y := cplbinit.o cacheinit.o cplbmgr.o |
6 | |||
7 | obj-$(CONFIG_CPLB_INFO) += cplbinfo.o | ||
8 | |||
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinfo.c b/arch/blackfin/kernel/cplb-mpu/cplbinfo.c deleted file mode 100644 index 00cb2cf3a420..000000000000 --- a/arch/blackfin/kernel/cplb-mpu/cplbinfo.c +++ /dev/null | |||
@@ -1,149 +0,0 @@ | |||
1 | /* | ||
2 | * File: arch/blackfin/mach-common/cplbinfo.c | ||
3 | * Based on: | ||
4 | * Author: Sonic Zhang <sonic.zhang@analog.com> | ||
5 | * | ||
6 | * Created: Jan. 2005 | ||
7 | * Description: Display CPLB status | ||
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/module.h> | ||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/proc_fs.h> | ||
34 | #include <linux/uaccess.h> | ||
35 | |||
36 | #include <asm/current.h> | ||
37 | #include <asm/system.h> | ||
38 | #include <asm/cplb.h> | ||
39 | #include <asm/cplbinit.h> | ||
40 | #include <asm/blackfin.h> | ||
41 | |||
42 | static char page_size_string_table[][4] = { "1K", "4K", "1M", "4M" }; | ||
43 | |||
44 | static char *cplb_print_entry(char *buf, struct cplb_entry *tbl, int switched) | ||
45 | { | ||
46 | int i; | ||
47 | buf += sprintf(buf, "Index\tAddress\t\tData\tSize\tU/RD\tU/WR\tS/WR\tSwitch\n"); | ||
48 | for (i = 0; i < MAX_CPLBS; i++) { | ||
49 | unsigned long data = tbl[i].data; | ||
50 | unsigned long addr = tbl[i].addr; | ||
51 | if (!(data & CPLB_VALID)) | ||
52 | continue; | ||
53 | |||
54 | buf += | ||
55 | sprintf(buf, | ||
56 | "%d\t0x%08lx\t%06lx\t%s\t%c\t%c\t%c\t%c\n", | ||
57 | i, addr, data, | ||
58 | page_size_string_table[(data & 0x30000) >> 16], | ||
59 | (data & CPLB_USER_RD) ? 'Y' : 'N', | ||
60 | (data & CPLB_USER_WR) ? 'Y' : 'N', | ||
61 | (data & CPLB_SUPV_WR) ? 'Y' : 'N', | ||
62 | i < switched ? 'N' : 'Y'); | ||
63 | } | ||
64 | buf += sprintf(buf, "\n"); | ||
65 | |||
66 | return buf; | ||
67 | } | ||
68 | |||
69 | int cplbinfo_proc_output(char *buf, void *data) | ||
70 | { | ||
71 | char *p; | ||
72 | unsigned int cpu = (unsigned int)data;; | ||
73 | |||
74 | p = buf; | ||
75 | |||
76 | p += sprintf(p, "------------- CPLB Information on CPU%u --------------\n\n", cpu); | ||
77 | if (bfin_read_IMEM_CONTROL() & ENICPLB) { | ||
78 | p += sprintf(p, "Instruction CPLB entry:\n"); | ||
79 | p = cplb_print_entry(p, icplb_tbl[cpu], first_switched_icplb); | ||
80 | } else | ||
81 | p += sprintf(p, "Instruction CPLB is disabled.\n\n"); | ||
82 | |||
83 | if (1 || bfin_read_DMEM_CONTROL() & ENDCPLB) { | ||
84 | p += sprintf(p, "Data CPLB entry:\n"); | ||
85 | p = cplb_print_entry(p, dcplb_tbl[cpu], first_switched_dcplb); | ||
86 | } else | ||
87 | p += sprintf(p, "Data CPLB is disabled.\n"); | ||
88 | |||
89 | p += sprintf(p, "ICPLB miss: %d\nICPLB supervisor miss: %d\n", | ||
90 | nr_icplb_miss[cpu], nr_icplb_supv_miss[cpu]); | ||
91 | p += sprintf(p, "DCPLB miss: %d\nDCPLB protection fault:%d\n", | ||
92 | nr_dcplb_miss[cpu], nr_dcplb_prot[cpu]); | ||
93 | p += sprintf(p, "CPLB flushes: %d\n", | ||
94 | nr_cplb_flush[cpu]); | ||
95 | |||
96 | return p - buf; | ||
97 | } | ||
98 | |||
99 | static int cplbinfo_read_proc(char *page, char **start, off_t off, | ||
100 | int count, int *eof, void *data) | ||
101 | { | ||
102 | int len; | ||
103 | |||
104 | len = cplbinfo_proc_output(page, data); | ||
105 | if (len <= off + count) | ||
106 | *eof = 1; | ||
107 | *start = page + off; | ||
108 | len -= off; | ||
109 | if (len > count) | ||
110 | len = count; | ||
111 | if (len < 0) | ||
112 | len = 0; | ||
113 | return len; | ||
114 | } | ||
115 | |||
116 | static int __init cplbinfo_init(void) | ||
117 | { | ||
118 | struct proc_dir_entry *parent, *entry; | ||
119 | unsigned int cpu; | ||
120 | unsigned char str[10]; | ||
121 | |||
122 | parent = proc_mkdir("cplbinfo", NULL); | ||
123 | |||
124 | for_each_online_cpu(cpu) { | ||
125 | sprintf(str, "cpu%u", cpu); | ||
126 | entry = create_proc_entry(str, 0, parent); | ||
127 | if (!entry) | ||
128 | return -ENOMEM; | ||
129 | |||
130 | entry->read_proc = cplbinfo_read_proc; | ||
131 | entry->data = (void *)cpu; | ||
132 | } | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static void __exit cplbinfo_exit(void) | ||
138 | { | ||
139 | unsigned int cpu; | ||
140 | unsigned char str[20]; | ||
141 | for_each_online_cpu(cpu) { | ||
142 | sprintf(str, "cplbinfo/cpu%u", cpu); | ||
143 | remove_proc_entry(str, NULL); | ||
144 | } | ||
145 | remove_proc_entry("cplbinfo", NULL); | ||
146 | } | ||
147 | |||
148 | module_init(cplbinfo_init); | ||
149 | module_exit(cplbinfo_exit); | ||
diff --git a/arch/blackfin/kernel/cplb-nompu/Makefile b/arch/blackfin/kernel/cplb-nompu/Makefile index d36ea9b5382e..4010eca1c6c2 100644 --- a/arch/blackfin/kernel/cplb-nompu/Makefile +++ b/arch/blackfin/kernel/cplb-nompu/Makefile | |||
@@ -3,6 +3,3 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := cplbinit.o cacheinit.o cplbhdlr.o cplbmgr.o | 5 | obj-y := cplbinit.o cacheinit.o cplbhdlr.o cplbmgr.o |
6 | |||
7 | obj-$(CONFIG_CPLB_INFO) += cplbinfo.o | ||
8 | |||
diff --git a/arch/blackfin/kernel/cplb-nompu/cplbinfo.c b/arch/blackfin/kernel/cplb-nompu/cplbinfo.c deleted file mode 100644 index 3f0080954e6f..000000000000 --- a/arch/blackfin/kernel/cplb-nompu/cplbinfo.c +++ /dev/null | |||
@@ -1,208 +0,0 @@ | |||
1 | /* | ||
2 | * File: arch/blackfin/mach-common/cplbinfo.c | ||
3 | * Based on: | ||
4 | * Author: Sonic Zhang <sonic.zhang@analog.com> | ||
5 | * | ||
6 | * Created: Jan. 2005 | ||
7 | * Description: Display CPLB status | ||
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/module.h> | ||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/proc_fs.h> | ||
34 | #include <linux/uaccess.h> | ||
35 | |||
36 | #include <asm/cplbinit.h> | ||
37 | #include <asm/blackfin.h> | ||
38 | |||
39 | #define CPLB_I 1 | ||
40 | #define CPLB_D 2 | ||
41 | |||
42 | #define SYNC_SYS SSYNC() | ||
43 | #define SYNC_CORE CSYNC() | ||
44 | |||
45 | #define CPLB_BIT_PAGESIZE 0x30000 | ||
46 | |||
47 | static int page_size_table[4] = { | ||
48 | 0x00000400, /* 1K */ | ||
49 | 0x00001000, /* 4K */ | ||
50 | 0x00100000, /* 1M */ | ||
51 | 0x00400000 /* 4M */ | ||
52 | }; | ||
53 | |||
54 | static char page_size_string_table[][4] = { "1K", "4K", "1M", "4M" }; | ||
55 | |||
56 | static int cplb_find_entry(unsigned long *cplb_addr, | ||
57 | unsigned long *cplb_data, unsigned long addr, | ||
58 | unsigned long data) | ||
59 | { | ||
60 | int ii; | ||
61 | |||
62 | for (ii = 0; ii < 16; ii++) | ||
63 | if (addr >= cplb_addr[ii] && addr < cplb_addr[ii] + | ||
64 | page_size_table[(cplb_data[ii] & CPLB_BIT_PAGESIZE) >> 16] | ||
65 | && (cplb_data[ii] == data)) | ||
66 | return ii; | ||
67 | |||
68 | return -1; | ||
69 | } | ||
70 | |||
71 | static char *cplb_print_entry(char *buf, int type, unsigned int cpu) | ||
72 | { | ||
73 | unsigned long *p_addr = dpdt_tables[cpu]; | ||
74 | unsigned long *p_data = dpdt_tables[cpu] + 1; | ||
75 | unsigned long *p_icount = dpdt_swapcount_tables[cpu]; | ||
76 | unsigned long *p_ocount = dpdt_swapcount_tables[cpu] + 1; | ||
77 | unsigned long *cplb_addr = (unsigned long *)DCPLB_ADDR0; | ||
78 | unsigned long *cplb_data = (unsigned long *)DCPLB_DATA0; | ||
79 | int entry = 0, used_cplb = 0; | ||
80 | |||
81 | if (type == CPLB_I) { | ||
82 | buf += sprintf(buf, "Instruction CPLB entry:\n"); | ||
83 | p_addr = ipdt_tables[cpu]; | ||
84 | p_data = ipdt_tables[cpu] + 1; | ||
85 | p_icount = ipdt_swapcount_tables[cpu]; | ||
86 | p_ocount = ipdt_swapcount_tables[cpu] + 1; | ||
87 | cplb_addr = (unsigned long *)ICPLB_ADDR0; | ||
88 | cplb_data = (unsigned long *)ICPLB_DATA0; | ||
89 | } else | ||
90 | buf += sprintf(buf, "Data CPLB entry:\n"); | ||
91 | |||
92 | buf += sprintf(buf, "Address\t\tData\tSize\tValid\tLocked\tSwapin\tiCount\toCount\n"); | ||
93 | |||
94 | while (*p_addr != 0xffffffff) { | ||
95 | entry = cplb_find_entry(cplb_addr, cplb_data, *p_addr, *p_data); | ||
96 | if (entry >= 0) | ||
97 | used_cplb |= 1 << entry; | ||
98 | |||
99 | buf += | ||
100 | sprintf(buf, | ||
101 | "0x%08lx\t0x%05lx\t%s\t%c\t%c\t%2d\t%ld\t%ld\n", | ||
102 | *p_addr, *p_data, | ||
103 | page_size_string_table[(*p_data & 0x30000) >> 16], | ||
104 | (*p_data & CPLB_VALID) ? 'Y' : 'N', | ||
105 | (*p_data & CPLB_LOCK) ? 'Y' : 'N', entry, *p_icount, | ||
106 | *p_ocount); | ||
107 | |||
108 | p_addr += 2; | ||
109 | p_data += 2; | ||
110 | p_icount += 2; | ||
111 | p_ocount += 2; | ||
112 | } | ||
113 | |||
114 | if (used_cplb != 0xffff) { | ||
115 | buf += sprintf(buf, "Unused/mismatched CPLBs:\n"); | ||
116 | |||
117 | for (entry = 0; entry < 16; entry++) | ||
118 | if (0 == ((1 << entry) & used_cplb)) { | ||
119 | int flags = cplb_data[entry]; | ||
120 | buf += | ||
121 | sprintf(buf, | ||
122 | "%2d: 0x%08lx\t0x%05x\t%s\t%c\t%c\n", | ||
123 | entry, cplb_addr[entry], flags, | ||
124 | page_size_string_table[(flags & | ||
125 | 0x30000) >> | ||
126 | 16], | ||
127 | (flags & CPLB_VALID) ? 'Y' : 'N', | ||
128 | (flags & CPLB_LOCK) ? 'Y' : 'N'); | ||
129 | } | ||
130 | } | ||
131 | |||
132 | buf += sprintf(buf, "\n"); | ||
133 | |||
134 | return buf; | ||
135 | } | ||
136 | |||
137 | static int cplbinfo_proc_output(char *buf, void *data) | ||
138 | { | ||
139 | unsigned int cpu = (unsigned int)data; | ||
140 | char *p; | ||
141 | |||
142 | p = buf; | ||
143 | |||
144 | p += sprintf(p, "------------- CPLB Information on CPU%u--------------\n\n", cpu); | ||
145 | |||
146 | if (bfin_read_IMEM_CONTROL() & ENICPLB) | ||
147 | p = cplb_print_entry(p, CPLB_I, cpu); | ||
148 | else | ||
149 | p += sprintf(p, "Instruction CPLB is disabled.\n\n"); | ||
150 | |||
151 | if (bfin_read_DMEM_CONTROL() & ENDCPLB) | ||
152 | p = cplb_print_entry(p, CPLB_D, cpu); | ||
153 | else | ||
154 | p += sprintf(p, "Data CPLB is disabled.\n"); | ||
155 | return p - buf; | ||
156 | } | ||
157 | |||
158 | static int cplbinfo_read_proc(char *page, char **start, off_t off, | ||
159 | int count, int *eof, void *data) | ||
160 | { | ||
161 | int len; | ||
162 | |||
163 | len = cplbinfo_proc_output(page, data); | ||
164 | if (len <= off + count) | ||
165 | *eof = 1; | ||
166 | *start = page + off; | ||
167 | len -= off; | ||
168 | if (len > count) | ||
169 | len = count; | ||
170 | if (len < 0) | ||
171 | len = 0; | ||
172 | return len; | ||
173 | } | ||
174 | |||
175 | static int __init cplbinfo_init(void) | ||
176 | { | ||
177 | struct proc_dir_entry *parent, *entry; | ||
178 | unsigned int cpu; | ||
179 | unsigned char str[10]; | ||
180 | |||
181 | parent = proc_mkdir("cplbinfo", NULL); | ||
182 | |||
183 | for_each_online_cpu(cpu) { | ||
184 | sprintf(str, "cpu%u", cpu); | ||
185 | entry = create_proc_entry(str, 0, parent); | ||
186 | if (!entry) | ||
187 | return -ENOMEM; | ||
188 | |||
189 | entry->read_proc = cplbinfo_read_proc; | ||
190 | entry->data = (void *)cpu; | ||
191 | } | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static void __exit cplbinfo_exit(void) | ||
197 | { | ||
198 | unsigned int cpu; | ||
199 | unsigned char str[20]; | ||
200 | for_each_online_cpu(cpu) { | ||
201 | sprintf(str, "cplbinfo/cpu%u", cpu); | ||
202 | remove_proc_entry(str, NULL); | ||
203 | } | ||
204 | remove_proc_entry("cplbinfo", NULL); | ||
205 | } | ||
206 | |||
207 | module_init(cplbinfo_init); | ||
208 | module_exit(cplbinfo_exit); | ||
diff --git a/arch/blackfin/kernel/cplbinfo.c b/arch/blackfin/kernel/cplbinfo.c new file mode 100644 index 000000000000..dc584fe18e5f --- /dev/null +++ b/arch/blackfin/kernel/cplbinfo.c | |||
@@ -0,0 +1,200 @@ | |||
1 | /* | ||
2 | * arch/blackfin/kernel/cplbinfo.c - display CPLB status | ||
3 | * | ||
4 | * Copyright 2004-2008 Analog Devices Inc. | ||
5 | * Licensed under the GPL-2 or later. | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/proc_fs.h> | ||
12 | #include <linux/uaccess.h> | ||
13 | |||
14 | #include <asm/cplbinit.h> | ||
15 | #include <asm/blackfin.h> | ||
16 | |||
17 | typedef enum { ICPLB, DCPLB } cplb_type; | ||
18 | |||
19 | static char page_strtbl[][3] = { "1K", "4K", "1M", "4M" }; | ||
20 | #define page(flags) (((flags) & 0x30000) >> 16) | ||
21 | #define strpage(flags) page_strtbl[page(flags)] | ||
22 | |||
23 | #ifdef CONFIG_MPU | ||
24 | |||
25 | static char *cplb_print_entry(char *buf, cplb_type type, unsigned int cpu) | ||
26 | { | ||
27 | struct cplb_entry *tbl; | ||
28 | int switched; | ||
29 | int i; | ||
30 | |||
31 | if (type == ICPLB) { | ||
32 | tbl = icplb_tbl[cpu]; | ||
33 | switched = first_switched_icplb; | ||
34 | } else { | ||
35 | tbl = dcplb_tbl[cpu]; | ||
36 | switched = first_switched_dcplb; | ||
37 | } | ||
38 | |||
39 | buf += sprintf(buf, "Index\tAddress\t\tData\tSize\tU/RD\tU/WR\tS/WR\tSwitch\n"); | ||
40 | for (i = 0; i < MAX_CPLBS; ++i) { | ||
41 | unsigned long data = tbl[i].data; | ||
42 | unsigned long addr = tbl[i].addr; | ||
43 | |||
44 | if (!(data & CPLB_VALID)) | ||
45 | continue; | ||
46 | |||
47 | buf += sprintf(buf, | ||
48 | "%d\t0x%08lx\t%05lx\t%s\t%c\t%c\t%c\t%c\n", | ||
49 | i, addr, data, strpage(data), | ||
50 | (data & CPLB_USER_RD) ? 'Y' : 'N', | ||
51 | (data & CPLB_USER_WR) ? 'Y' : 'N', | ||
52 | (data & CPLB_SUPV_WR) ? 'Y' : 'N', | ||
53 | i < switched ? 'N' : 'Y'); | ||
54 | } | ||
55 | buf += sprintf(buf, "\n"); | ||
56 | |||
57 | return buf; | ||
58 | } | ||
59 | |||
60 | #else | ||
61 | |||
62 | static int page_size_table[4] = { | ||
63 | 0x00000400, /* 1K */ | ||
64 | 0x00001000, /* 4K */ | ||
65 | 0x00100000, /* 1M */ | ||
66 | 0x00400000 /* 4M */ | ||
67 | }; | ||
68 | |||
69 | static int cplb_find_entry(unsigned long *cplb_addr, | ||
70 | unsigned long *cplb_data, unsigned long addr, | ||
71 | unsigned long data) | ||
72 | { | ||
73 | int i; | ||
74 | |||
75 | for (i = 0; i < 16; ++i) | ||
76 | if (addr >= cplb_addr[i] && | ||
77 | addr < cplb_addr[i] + page_size_table[page(cplb_data[i])] && | ||
78 | cplb_data[i] == data) | ||
79 | return i; | ||
80 | |||
81 | return -1; | ||
82 | } | ||
83 | |||
84 | static char *cplb_print_entry(char *buf, cplb_type type, unsigned int cpu) | ||
85 | { | ||
86 | unsigned long *p_addr, *p_data, *p_icount, *p_ocount; | ||
87 | unsigned long *cplb_addr, *cplb_data; | ||
88 | int entry = 0, used_cplb = 0; | ||
89 | |||
90 | if (type == ICPLB) { | ||
91 | p_addr = ipdt_tables[cpu]; | ||
92 | p_data = ipdt_tables[cpu] + 1; | ||
93 | p_icount = ipdt_swapcount_tables[cpu]; | ||
94 | p_ocount = ipdt_swapcount_tables[cpu] + 1; | ||
95 | cplb_addr = (unsigned long *)ICPLB_ADDR0; | ||
96 | cplb_data = (unsigned long *)ICPLB_DATA0; | ||
97 | } else { | ||
98 | p_addr = dpdt_tables[cpu]; | ||
99 | p_data = dpdt_tables[cpu] + 1; | ||
100 | p_icount = dpdt_swapcount_tables[cpu]; | ||
101 | p_ocount = dpdt_swapcount_tables[cpu] + 1; | ||
102 | cplb_addr = (unsigned long *)DCPLB_ADDR0; | ||
103 | cplb_data = (unsigned long *)DCPLB_DATA0; | ||
104 | } | ||
105 | |||
106 | buf += sprintf(buf, "Address\t\tData\tSize\tValid\tLocked\tSwapin\tiCount\toCount\n"); | ||
107 | |||
108 | while (*p_addr != 0xffffffff) { | ||
109 | entry = cplb_find_entry(cplb_addr, cplb_data, *p_addr, *p_data); | ||
110 | if (entry >= 0) | ||
111 | used_cplb |= 1 << entry; | ||
112 | |||
113 | buf += sprintf(buf, | ||
114 | "0x%08lx\t0x%05lx\t%s\t%c\t%c\t%2d\t%ld\t%ld\n", | ||
115 | *p_addr, *p_data, strpage(*p_data), | ||
116 | (*p_data & CPLB_VALID) ? 'Y' : 'N', | ||
117 | (*p_data & CPLB_LOCK) ? 'Y' : 'N', entry, *p_icount, | ||
118 | *p_ocount); | ||
119 | |||
120 | p_addr += 2; | ||
121 | p_data += 2; | ||
122 | p_icount += 2; | ||
123 | p_ocount += 2; | ||
124 | } | ||
125 | |||
126 | if (used_cplb != 0xffff) { | ||
127 | buf += sprintf(buf, "Unused/mismatched CPLBs:\n"); | ||
128 | |||
129 | for (entry = 0; entry < 16; ++entry) | ||
130 | if (0 == ((1 << entry) & used_cplb)) { | ||
131 | int flags = cplb_data[entry]; | ||
132 | buf += sprintf(buf, | ||
133 | "%2d: 0x%08lx\t0x%05x\t%s\t%c\t%c\n", | ||
134 | entry, cplb_addr[entry], flags, strpage(flags), | ||
135 | (flags & CPLB_VALID) ? 'Y' : 'N', | ||
136 | (flags & CPLB_LOCK) ? 'Y' : 'N'); | ||
137 | } | ||
138 | } | ||
139 | |||
140 | buf += sprintf(buf, "\n"); | ||
141 | |||
142 | return buf; | ||
143 | } | ||
144 | |||
145 | #endif | ||
146 | |||
147 | static int cplbinfo_proc_output(char *buf, void *data) | ||
148 | { | ||
149 | unsigned int cpu = (unsigned int)data; | ||
150 | char *p = buf; | ||
151 | |||
152 | if (bfin_read_IMEM_CONTROL() & ENICPLB) { | ||
153 | p += sprintf(p, "Instruction CPLB entry:\n"); | ||
154 | p = cplb_print_entry(p, ICPLB, cpu); | ||
155 | } else | ||
156 | p += sprintf(p, "Instruction CPLB is disabled.\n\n"); | ||
157 | |||
158 | if (bfin_read_DMEM_CONTROL() & ENDCPLB) { | ||
159 | p += sprintf(p, "Data CPLB entry:\n"); | ||
160 | p = cplb_print_entry(p, DCPLB, cpu); | ||
161 | } else | ||
162 | p += sprintf(p, "Data CPLB is disabled.\n\n"); | ||
163 | |||
164 | return p - buf; | ||
165 | } | ||
166 | |||
167 | static int cplbinfo_read_proc(char *page, char **start, off_t off, | ||
168 | int count, int *eof, void *data) | ||
169 | { | ||
170 | int len = cplbinfo_proc_output(page, data); | ||
171 | if (len <= off + count) | ||
172 | *eof = 1; | ||
173 | *start = page + off; | ||
174 | len -= off; | ||
175 | return max(min(len, count), 0); | ||
176 | } | ||
177 | |||
178 | static int __init cplbinfo_init(void) | ||
179 | { | ||
180 | struct proc_dir_entry *parent, *entry; | ||
181 | unsigned int cpu; | ||
182 | unsigned char str[10]; | ||
183 | |||
184 | parent = proc_mkdir("cplbinfo", NULL); | ||
185 | if (!parent) | ||
186 | return -ENOMEM; | ||
187 | |||
188 | for_each_online_cpu(cpu) { | ||
189 | sprintf(str, "cpu%u", cpu); | ||
190 | entry = create_proc_entry(str, 0, parent); | ||
191 | if (!entry) | ||
192 | return -ENOMEM; | ||
193 | |||
194 | entry->read_proc = cplbinfo_read_proc; | ||
195 | entry->data = (void *)cpu; | ||
196 | } | ||
197 | |||
198 | return 0; | ||
199 | } | ||
200 | late_initcall(cplbinfo_init); | ||