diff options
Diffstat (limited to 'arch/blackfin/kernel/cplb-mpu/cplbinfo.c')
-rw-r--r-- | arch/blackfin/kernel/cplb-mpu/cplbinfo.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinfo.c b/arch/blackfin/kernel/cplb-mpu/cplbinfo.c new file mode 100644 index 000000000000..bd072299f7f2 --- /dev/null +++ b/arch/blackfin/kernel/cplb-mpu/cplbinfo.c @@ -0,0 +1,144 @@ +/* + * File: arch/blackfin/mach-common/cplbinfo.c + * Based on: + * Author: Sonic Zhang <sonic.zhang@analog.com> + * + * Created: Jan. 2005 + * Description: Display CPLB status + * + * Modified: + * Copyright 2004-2006 Analog Devices Inc. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/proc_fs.h> +#include <linux/uaccess.h> + +#include <asm/current.h> +#include <asm/system.h> +#include <asm/cplb.h> +#include <asm/cplbinit.h> +#include <asm/blackfin.h> + +#define CPLB_I 1 +#define CPLB_D 2 + +#define SYNC_SYS SSYNC() +#define SYNC_CORE CSYNC() + +#define CPLB_BIT_PAGESIZE 0x30000 + +static char page_size_string_table[][4] = { "1K", "4K", "1M", "4M" }; + +static char *cplb_print_entry(char *buf, struct cplb_entry *tbl, int switched) +{ + int i; + buf += sprintf(buf, "Index\tAddress\t\tData\tSize\tU/RD\tU/WR\tS/WR\tSwitch\n"); + for (i = 0; i < MAX_CPLBS; i++) { + unsigned long data = tbl[i].data; + unsigned long addr = tbl[i].addr; + if (!(data & CPLB_VALID)) + continue; + + buf += + sprintf(buf, + "%d\t0x%08lx\t%06lx\t%s\t%c\t%c\t%c\t%c\n", + i, addr, data, + page_size_string_table[(data & 0x30000) >> 16], + (data & CPLB_USER_RD) ? 'Y' : 'N', + (data & CPLB_USER_WR) ? 'Y' : 'N', + (data & CPLB_SUPV_WR) ? 'Y' : 'N', + i < switched ? 'N' : 'Y'); + } + buf += sprintf(buf, "\n"); + + return buf; +} + +int cplbinfo_proc_output(char *buf) +{ + char *p; + + p = buf; + + p += sprintf(p, "------------------ CPLB Information ------------------\n\n"); + + if (bfin_read_IMEM_CONTROL() & ENICPLB) { + p += sprintf(p, "Instruction CPLB entry:\n"); + p = cplb_print_entry(p, icplb_tbl, first_switched_icplb); + } else + p += sprintf(p, "Instruction CPLB is disabled.\n\n"); + + if (1 || bfin_read_DMEM_CONTROL() & ENDCPLB) { + p += sprintf(p, "Data CPLB entry:\n"); + p = cplb_print_entry(p, dcplb_tbl, first_switched_dcplb); + } else + p += sprintf(p, "Data CPLB is disabled.\n"); + + p += sprintf(p, "ICPLB miss: %d\nICPLB supervisor miss: %d\n", + nr_icplb_miss, nr_icplb_supv_miss); + p += sprintf(p, "DCPLB miss: %d\nDCPLB protection fault:%d\n", + nr_dcplb_miss, nr_dcplb_prot); + p += sprintf(p, "CPLB flushes: %d\n", + nr_cplb_flush); + + return p - buf; +} + +static int cplbinfo_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len; + + len = cplbinfo_proc_output(page); + if (len <= off + count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; +} + +static int __init cplbinfo_init(void) +{ + struct proc_dir_entry *entry; + + entry = create_proc_entry("cplbinfo", 0, NULL); + if (!entry) + return -ENOMEM; + + entry->read_proc = cplbinfo_read_proc; + entry->data = NULL; + + return 0; +} + +static void __exit cplbinfo_exit(void) +{ + remove_proc_entry("cplbinfo", NULL); +} + +module_init(cplbinfo_init); +module_exit(cplbinfo_exit); |