mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-04 09:34:12 +08:00
f5b8fcb48b
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iQIcBAABAgAGBQJRi4ZDAAoJEJommM3PjknHTDYP/j/xtxd9IEsqVS6lGoNhvOL2 L3q+BbvijtsYVR08iQhroeCGCm8S7V6vdWNlFOjZESP1mDO9JAyDOloaWe/asPB5 HJVrfD+Z4taRTaeRq1br2T/knYMezDEKTxxilZcGYnLkx4a+uOT7kGywgd82jR2J VlZcpa4JRSiWa1jB3kQNz1+6LHPNogFeufUY4VsHnOEuiD667c3wd865OTicsxil eomr9VHOhA4nj5ac9Qlf+HZAQGkp71ugAx9YBzfLxt0lHpYTU2aqGwzkVD3PShH4 5zYQA7nYIGskLWyGNopomdXY9SmOwe0sIU5r0BcDQEaiizZFX0CnO00i2zdcH104 +Q2iCaU+NNTb5QDnUUnAuj7vFcwiSMBHFADvgloyuwafLPtF6X8Xi4qB/NOPneM4 q03i7kT0K723XVtqjpaaf904TuAmhoZREOESMkzPrEM+Dm7KReO3VBUhIs/BjcFO DGIBRhIIFNzSfGjVBP0idWRTqQoJ0Akf/dLnDbTM+IvBaYcL+ck6gKYZ0UvCM3IO 16VEtUuIxNeJsLD5xwGKTOJ6cyYqmYrZ8ZIG5Fc/b3Y1EFcexSY1FwtplG9yHx2Q ulRxLpmY25KWVa5Op9Hl9MU131FWaZ5qJJXvW6nU8C4bvGjP97MoS9ObsuD20fwI TiUpia3+Dom2O4dtvx7N =0WkM -----END PGP SIGNATURE----- Merge tag 'for-linus' of git://github.com/realmz/blackfin-linux Pull blackfin updates from Steven Miao. * tag 'for-linus' of git://github.com/realmz/blackfin-linux: bfin cache: dcplb map: add 16M dcplb map for BF60x blackfin: smp: fix smp build after drop asm/system.h blackfin: fix bootup core clock and system clock display Platform Nand: Set the GPIO for NAND read as input blackfin: rename vmImage to uImage after we move to buildroot blackfin: twi: Remove bogus #endif bf609: rsi: Add bf609 rsi MMR macro and board platform data. blackfin: dmc: Improve DDR2 write through in DMC effict controller.
181 lines
3.8 KiB
C
181 lines
3.8 KiB
C
/*
|
|
* arch/blackfin/kernel/cplbinfo.c - display CPLB status
|
|
*
|
|
* Copyright 2004-2008 Analog Devices Inc.
|
|
*
|
|
* Licensed under the GPL-2 or later.
|
|
*/
|
|
|
|
#include <linux/ctype.h>
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
#include <linux/proc_fs.h>
|
|
#include <linux/seq_file.h>
|
|
#include <linux/uaccess.h>
|
|
|
|
#include <asm/cplbinit.h>
|
|
#include <asm/blackfin.h>
|
|
|
|
static char const page_strtbl[][4] = {
|
|
"1K", "4K", "1M", "4M",
|
|
#ifdef CONFIG_BF60x
|
|
"16K", "64K", "16M", "64M",
|
|
#endif
|
|
};
|
|
#define page(flags) (((flags) & 0x70000) >> 16)
|
|
#define strpage(flags) page_strtbl[page(flags)]
|
|
|
|
struct cplbinfo_data {
|
|
loff_t pos;
|
|
char cplb_type;
|
|
u32 mem_control;
|
|
struct cplb_entry *tbl;
|
|
int switched;
|
|
};
|
|
|
|
static void cplbinfo_print_header(struct seq_file *m)
|
|
{
|
|
seq_printf(m, "Index\tAddress\t\tData\tSize\tU/RD\tU/WR\tS/WR\tSwitch\n");
|
|
}
|
|
|
|
static int cplbinfo_nomore(struct cplbinfo_data *cdata)
|
|
{
|
|
return cdata->pos >= MAX_CPLBS;
|
|
}
|
|
|
|
static int cplbinfo_show(struct seq_file *m, void *p)
|
|
{
|
|
struct cplbinfo_data *cdata;
|
|
unsigned long data, addr;
|
|
loff_t pos;
|
|
|
|
cdata = p;
|
|
pos = cdata->pos;
|
|
addr = cdata->tbl[pos].addr;
|
|
data = cdata->tbl[pos].data;
|
|
|
|
seq_printf(m,
|
|
"%d\t0x%08lx\t%05lx\t%s\t%c\t%c\t%c\t%c\n",
|
|
(int)pos, addr, data, strpage(data),
|
|
(data & CPLB_USER_RD) ? 'Y' : 'N',
|
|
(data & CPLB_USER_WR) ? 'Y' : 'N',
|
|
(data & CPLB_SUPV_WR) ? 'Y' : 'N',
|
|
pos < cdata->switched ? 'N' : 'Y');
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void cplbinfo_seq_init(struct cplbinfo_data *cdata, unsigned int cpu)
|
|
{
|
|
if (cdata->cplb_type == 'I') {
|
|
cdata->mem_control = bfin_read_IMEM_CONTROL();
|
|
cdata->tbl = icplb_tbl[cpu];
|
|
cdata->switched = first_switched_icplb;
|
|
} else {
|
|
cdata->mem_control = bfin_read_DMEM_CONTROL();
|
|
cdata->tbl = dcplb_tbl[cpu];
|
|
cdata->switched = first_switched_dcplb;
|
|
}
|
|
}
|
|
|
|
static void *cplbinfo_start(struct seq_file *m, loff_t *pos)
|
|
{
|
|
struct cplbinfo_data *cdata = m->private;
|
|
|
|
if (!*pos) {
|
|
seq_printf(m, "%cCPLBs are %sabled: 0x%x\n", cdata->cplb_type,
|
|
(cdata->mem_control & ENDCPLB ? "en" : "dis"),
|
|
cdata->mem_control);
|
|
cplbinfo_print_header(m);
|
|
} else if (cplbinfo_nomore(cdata))
|
|
return NULL;
|
|
|
|
get_cpu();
|
|
return cdata;
|
|
}
|
|
|
|
static void *cplbinfo_next(struct seq_file *m, void *p, loff_t *pos)
|
|
{
|
|
struct cplbinfo_data *cdata = p;
|
|
cdata->pos = ++(*pos);
|
|
if (cplbinfo_nomore(cdata))
|
|
return NULL;
|
|
else
|
|
return cdata;
|
|
}
|
|
|
|
static void cplbinfo_stop(struct seq_file *m, void *p)
|
|
{
|
|
put_cpu();
|
|
}
|
|
|
|
static const struct seq_operations cplbinfo_sops = {
|
|
.start = cplbinfo_start,
|
|
.next = cplbinfo_next,
|
|
.stop = cplbinfo_stop,
|
|
.show = cplbinfo_show,
|
|
};
|
|
|
|
#define CPLBINFO_DCPLB_FLAG 0x80000000
|
|
|
|
static int cplbinfo_open(struct inode *inode, struct file *file)
|
|
{
|
|
char cplb_type;
|
|
unsigned int cpu = (unsigned long)PDE_DATA(file_inode(file));
|
|
int ret;
|
|
struct seq_file *m;
|
|
struct cplbinfo_data *cdata;
|
|
|
|
cplb_type = cpu & CPLBINFO_DCPLB_FLAG ? 'D' : 'I';
|
|
cpu &= ~CPLBINFO_DCPLB_FLAG;
|
|
|
|
if (!cpu_online(cpu))
|
|
return -ENODEV;
|
|
|
|
ret = seq_open_private(file, &cplbinfo_sops, sizeof(*cdata));
|
|
if (ret)
|
|
return ret;
|
|
m = file->private_data;
|
|
cdata = m->private;
|
|
|
|
cdata->pos = 0;
|
|
cdata->cplb_type = cplb_type;
|
|
cplbinfo_seq_init(cdata, cpu);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct file_operations cplbinfo_fops = {
|
|
.open = cplbinfo_open,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.release = seq_release_private,
|
|
};
|
|
|
|
static int __init cplbinfo_init(void)
|
|
{
|
|
struct proc_dir_entry *cplb_dir, *cpu_dir;
|
|
char buf[10];
|
|
unsigned int cpu;
|
|
|
|
cplb_dir = proc_mkdir("cplbinfo", NULL);
|
|
if (!cplb_dir)
|
|
return -ENOMEM;
|
|
|
|
for_each_possible_cpu(cpu) {
|
|
sprintf(buf, "cpu%i", cpu);
|
|
cpu_dir = proc_mkdir(buf, cplb_dir);
|
|
if (!cpu_dir)
|
|
return -ENOMEM;
|
|
|
|
proc_create_data("icplb", S_IRUGO, cpu_dir, &cplbinfo_fops,
|
|
(void *)cpu);
|
|
proc_create_data("dcplb", S_IRUGO, cpu_dir, &cplbinfo_fops,
|
|
(void *)(cpu | CPLBINFO_DCPLB_FLAG));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
late_initcall(cplbinfo_init);
|