Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Copyright (C) 2013 Imagination Technologies Ltd.
0007  */
0008 
0009 #include <linux/kernel.h>
0010 #include <linux/debugfs.h>
0011 #include <linux/seq_file.h>
0012 #include <asm/cpu.h>
0013 #include <asm/debug.h>
0014 #include <asm/mipsregs.h>
0015 
0016 static void build_segment_config(char *str, unsigned int cfg)
0017 {
0018     unsigned int am;
0019     static const char * const am_str[] = {
0020         "UK", "MK", "MSK", "MUSK", "MUSUK", "USK",
0021         "RSRVD", "UUSK"};
0022 
0023     /* Segment access mode. */
0024     am = (cfg & MIPS_SEGCFG_AM) >> MIPS_SEGCFG_AM_SHIFT;
0025     str += sprintf(str, "%-5s", am_str[am]);
0026 
0027     /*
0028      * Access modes MK, MSK and MUSK are mapped segments. Therefore
0029      * there is no direct physical address mapping unless it becomes
0030      * unmapped uncached at error level due to EU.
0031      */
0032     if ((am == 0) || (am > 3) || (cfg & MIPS_SEGCFG_EU))
0033         str += sprintf(str, "         %03lx",
0034             ((cfg & MIPS_SEGCFG_PA) >> MIPS_SEGCFG_PA_SHIFT));
0035     else
0036         str += sprintf(str, "         UND");
0037 
0038     if ((am == 0) || (am > 3))
0039         str += sprintf(str, "         %01ld",
0040             ((cfg & MIPS_SEGCFG_C) >> MIPS_SEGCFG_C_SHIFT));
0041     else
0042         str += sprintf(str, "         U");
0043 
0044     /* Exception configuration. */
0045     str += sprintf(str, "       %01ld\n",
0046         ((cfg & MIPS_SEGCFG_EU) >> MIPS_SEGCFG_EU_SHIFT));
0047 }
0048 
0049 static int show_segments(struct seq_file *m, void *v)
0050 {
0051     unsigned int segcfg;
0052     char str[42];
0053 
0054     seq_puts(m, "Segment   Virtual    Size   Access Mode   Physical   Caching   EU\n");
0055     seq_puts(m, "-------   -------    ----   -----------   --------   -------   --\n");
0056 
0057     segcfg = read_c0_segctl0();
0058     build_segment_config(str, segcfg);
0059     seq_printf(m, "   0      e0000000   512M      %s", str);
0060 
0061     segcfg >>= 16;
0062     build_segment_config(str, segcfg);
0063     seq_printf(m, "   1      c0000000   512M      %s", str);
0064 
0065     segcfg = read_c0_segctl1();
0066     build_segment_config(str, segcfg);
0067     seq_printf(m, "   2      a0000000   512M      %s", str);
0068 
0069     segcfg >>= 16;
0070     build_segment_config(str, segcfg);
0071     seq_printf(m, "   3      80000000   512M      %s", str);
0072 
0073     segcfg = read_c0_segctl2();
0074     build_segment_config(str, segcfg);
0075     seq_printf(m, "   4      40000000    1G       %s", str);
0076 
0077     segcfg >>= 16;
0078     build_segment_config(str, segcfg);
0079     seq_printf(m, "   5      00000000    1G       %s\n", str);
0080 
0081     return 0;
0082 }
0083 
0084 static int segments_open(struct inode *inode, struct file *file)
0085 {
0086     return single_open(file, show_segments, NULL);
0087 }
0088 
0089 static const struct file_operations segments_fops = {
0090     .open       = segments_open,
0091     .read       = seq_read,
0092     .llseek     = seq_lseek,
0093     .release    = single_release,
0094 };
0095 
0096 static int __init segments_info(void)
0097 {
0098     if (cpu_has_segments)
0099         debugfs_create_file("segments", S_IRUGO, mips_debugfs_dir, NULL,
0100                     &segments_fops);
0101     return 0;
0102 }
0103 
0104 device_initcall(segments_info);