 29f9087c52
			
		
	
	
	29f9087c52
	
	
	
		
			
			Add a new mips/segments debugfs file to print the 6 segmentation control registers for supported cores. A sample from a proAptiv core is given below: Signed-off-by: John Crispin <blogic@openwrt.org> Patchwork: http://patchwork.linux-mips.org/patch/6137/ Segment Virtual Size Access Mode Physical Caching EU ------- ------- ---- ----------- -------- ------- -- 0 e0000000 512M MK UND U 0 1 c0000000 512M MSK UND U 0 2 a0000000 512M UK 000 2 0 3 80000000 512M UK 000 3 0 4 40000000 1G MUSK UND U 1 5 00000000 1G MUSK UND U 1 Reviewed-by: James Hogan <james.hogan@imgtec.com> Signed-off-by: Steven J. Hill <Steven.Hill@imgtec.com> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
		
			
				
	
	
		
			110 lines
		
	
	
	
		
			2.8 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			110 lines
		
	
	
	
		
			2.8 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * This file is subject to the terms and conditions of the GNU General Public
 | |
|  * License.  See the file "COPYING" in the main directory of this archive
 | |
|  * for more details.
 | |
|  *
 | |
|  * Copyright (C) 2013 Imagination Technologies Ltd.
 | |
|  */
 | |
| 
 | |
| #include <linux/kernel.h>
 | |
| #include <linux/debugfs.h>
 | |
| #include <linux/seq_file.h>
 | |
| #include <asm/cpu.h>
 | |
| #include <asm/mipsregs.h>
 | |
| 
 | |
| static void build_segment_config(char *str, unsigned int cfg)
 | |
| {
 | |
| 	unsigned int am;
 | |
| 	static const char * const am_str[] = {
 | |
| 		"UK", "MK", "MSK", "MUSK", "MUSUK", "USK",
 | |
| 		"RSRVD", "UUSK"};
 | |
| 
 | |
| 	/* Segment access mode. */
 | |
| 	am = (cfg & MIPS_SEGCFG_AM) >> MIPS_SEGCFG_AM_SHIFT;
 | |
| 	str += sprintf(str, "%-5s", am_str[am]);
 | |
| 
 | |
| 	/*
 | |
| 	 * Access modes MK, MSK and MUSK are mapped segments. Therefore
 | |
| 	 * there is no direct physical address mapping.
 | |
| 	 */
 | |
| 	if ((am == 0) || (am > 3)) {
 | |
| 		str += sprintf(str, "         %03lx",
 | |
| 			((cfg & MIPS_SEGCFG_PA) >> MIPS_SEGCFG_PA_SHIFT));
 | |
| 		str += sprintf(str, "         %01ld",
 | |
| 			((cfg & MIPS_SEGCFG_C) >> MIPS_SEGCFG_C_SHIFT));
 | |
| 	} else {
 | |
| 		str += sprintf(str, "         UND");
 | |
| 		str += sprintf(str, "         U");
 | |
| 	}
 | |
| 
 | |
| 	/* Exception configuration. */
 | |
| 	str += sprintf(str, "       %01ld\n",
 | |
| 		((cfg & MIPS_SEGCFG_EU) >> MIPS_SEGCFG_EU_SHIFT));
 | |
| }
 | |
| 
 | |
| static int show_segments(struct seq_file *m, void *v)
 | |
| {
 | |
| 	unsigned int segcfg;
 | |
| 	char str[42];
 | |
| 
 | |
| 	seq_puts(m, "Segment   Virtual    Size   Access Mode   Physical   Caching   EU\n");
 | |
| 	seq_puts(m, "-------   -------    ----   -----------   --------   -------   --\n");
 | |
| 
 | |
| 	segcfg = read_c0_segctl0();
 | |
| 	build_segment_config(str, segcfg);
 | |
| 	seq_printf(m, "   0      e0000000   512M      %s", str);
 | |
| 
 | |
| 	segcfg >>= 16;
 | |
| 	build_segment_config(str, segcfg);
 | |
| 	seq_printf(m, "   1      c0000000   512M      %s", str);
 | |
| 
 | |
| 	segcfg = read_c0_segctl1();
 | |
| 	build_segment_config(str, segcfg);
 | |
| 	seq_printf(m, "   2      a0000000   512M      %s", str);
 | |
| 
 | |
| 	segcfg >>= 16;
 | |
| 	build_segment_config(str, segcfg);
 | |
| 	seq_printf(m, "   3      80000000   512M      %s", str);
 | |
| 
 | |
| 	segcfg = read_c0_segctl2();
 | |
| 	build_segment_config(str, segcfg);
 | |
| 	seq_printf(m, "   4      40000000    1G       %s", str);
 | |
| 
 | |
| 	segcfg >>= 16;
 | |
| 	build_segment_config(str, segcfg);
 | |
| 	seq_printf(m, "   5      00000000    1G       %s\n", str);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int segments_open(struct inode *inode, struct file *file)
 | |
| {
 | |
| 	return single_open(file, show_segments, NULL);
 | |
| }
 | |
| 
 | |
| static const struct file_operations segments_fops = {
 | |
| 	.open		= segments_open,
 | |
| 	.read		= seq_read,
 | |
| 	.llseek		= seq_lseek,
 | |
| 	.release	= single_release,
 | |
| };
 | |
| 
 | |
| static int __init segments_info(void)
 | |
| {
 | |
| 	extern struct dentry *mips_debugfs_dir;
 | |
| 	struct dentry *segments;
 | |
| 
 | |
| 	if (cpu_has_segments) {
 | |
| 		if (!mips_debugfs_dir)
 | |
| 			return -ENODEV;
 | |
| 
 | |
| 		segments = debugfs_create_file("segments", S_IRUGO,
 | |
| 					       mips_debugfs_dir, NULL,
 | |
| 					       &segments_fops);
 | |
| 		if (!segments)
 | |
| 			return -ENOMEM;
 | |
| 	}
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| device_initcall(segments_info);
 |