xref: /openbmc/linux/arch/mips/kernel/segment.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
129f9087cSSteven J. Hill /*
229f9087cSSteven J. Hill  * This file is subject to the terms and conditions of the GNU General Public
329f9087cSSteven J. Hill  * License.  See the file "COPYING" in the main directory of this archive
429f9087cSSteven J. Hill  * for more details.
529f9087cSSteven J. Hill  *
629f9087cSSteven J. Hill  * Copyright (C) 2013 Imagination Technologies Ltd.
729f9087cSSteven J. Hill  */
829f9087cSSteven J. Hill 
929f9087cSSteven J. Hill #include <linux/kernel.h>
1029f9087cSSteven J. Hill #include <linux/debugfs.h>
1129f9087cSSteven J. Hill #include <linux/seq_file.h>
1229f9087cSSteven J. Hill #include <asm/cpu.h>
1375dcfc1dSPaul Burton #include <asm/debug.h>
1429f9087cSSteven J. Hill #include <asm/mipsregs.h>
1529f9087cSSteven J. Hill 
build_segment_config(char * str,unsigned int cfg)1629f9087cSSteven J. Hill static void build_segment_config(char *str, unsigned int cfg)
1729f9087cSSteven J. Hill {
1829f9087cSSteven J. Hill 	unsigned int am;
1929f9087cSSteven J. Hill 	static const char * const am_str[] = {
2029f9087cSSteven J. Hill 		"UK", "MK", "MSK", "MUSK", "MUSUK", "USK",
2129f9087cSSteven J. Hill 		"RSRVD", "UUSK"};
2229f9087cSSteven J. Hill 
2329f9087cSSteven J. Hill 	/* Segment access mode. */
2429f9087cSSteven J. Hill 	am = (cfg & MIPS_SEGCFG_AM) >> MIPS_SEGCFG_AM_SHIFT;
2529f9087cSSteven J. Hill 	str += sprintf(str, "%-5s", am_str[am]);
2629f9087cSSteven J. Hill 
2729f9087cSSteven J. Hill 	/*
2829f9087cSSteven J. Hill 	 * Access modes MK, MSK and MUSK are mapped segments. Therefore
295573f6adSJames Hogan 	 * there is no direct physical address mapping unless it becomes
305573f6adSJames Hogan 	 * unmapped uncached at error level due to EU.
3129f9087cSSteven J. Hill 	 */
325573f6adSJames Hogan 	if ((am == 0) || (am > 3) || (cfg & MIPS_SEGCFG_EU))
3329f9087cSSteven J. Hill 		str += sprintf(str, "         %03lx",
3429f9087cSSteven J. Hill 			((cfg & MIPS_SEGCFG_PA) >> MIPS_SEGCFG_PA_SHIFT));
355573f6adSJames Hogan 	else
365573f6adSJames Hogan 		str += sprintf(str, "         UND");
375573f6adSJames Hogan 
385573f6adSJames Hogan 	if ((am == 0) || (am > 3))
3929f9087cSSteven J. Hill 		str += sprintf(str, "         %01ld",
4029f9087cSSteven J. Hill 			((cfg & MIPS_SEGCFG_C) >> MIPS_SEGCFG_C_SHIFT));
415573f6adSJames Hogan 	else
4229f9087cSSteven J. Hill 		str += sprintf(str, "         U");
4329f9087cSSteven J. Hill 
4429f9087cSSteven J. Hill 	/* Exception configuration. */
4529f9087cSSteven J. Hill 	str += sprintf(str, "       %01ld\n",
4629f9087cSSteven J. Hill 		((cfg & MIPS_SEGCFG_EU) >> MIPS_SEGCFG_EU_SHIFT));
4729f9087cSSteven J. Hill }
4829f9087cSSteven J. Hill 
segments_show(struct seq_file * m,void * v)49*27a43a85SLiu Shixin static int segments_show(struct seq_file *m, void *v)
5029f9087cSSteven J. Hill {
5129f9087cSSteven J. Hill 	unsigned int segcfg;
5229f9087cSSteven J. Hill 	char str[42];
5329f9087cSSteven J. Hill 
5429f9087cSSteven J. Hill 	seq_puts(m, "Segment   Virtual    Size   Access Mode   Physical   Caching   EU\n");
5529f9087cSSteven J. Hill 	seq_puts(m, "-------   -------    ----   -----------   --------   -------   --\n");
5629f9087cSSteven J. Hill 
5729f9087cSSteven J. Hill 	segcfg = read_c0_segctl0();
5829f9087cSSteven J. Hill 	build_segment_config(str, segcfg);
5929f9087cSSteven J. Hill 	seq_printf(m, "   0      e0000000   512M      %s", str);
6029f9087cSSteven J. Hill 
6129f9087cSSteven J. Hill 	segcfg >>= 16;
6229f9087cSSteven J. Hill 	build_segment_config(str, segcfg);
6329f9087cSSteven J. Hill 	seq_printf(m, "   1      c0000000   512M      %s", str);
6429f9087cSSteven J. Hill 
6529f9087cSSteven J. Hill 	segcfg = read_c0_segctl1();
6629f9087cSSteven J. Hill 	build_segment_config(str, segcfg);
6729f9087cSSteven J. Hill 	seq_printf(m, "   2      a0000000   512M      %s", str);
6829f9087cSSteven J. Hill 
6929f9087cSSteven J. Hill 	segcfg >>= 16;
7029f9087cSSteven J. Hill 	build_segment_config(str, segcfg);
7129f9087cSSteven J. Hill 	seq_printf(m, "   3      80000000   512M      %s", str);
7229f9087cSSteven J. Hill 
7329f9087cSSteven J. Hill 	segcfg = read_c0_segctl2();
7429f9087cSSteven J. Hill 	build_segment_config(str, segcfg);
7529f9087cSSteven J. Hill 	seq_printf(m, "   4      40000000    1G       %s", str);
7629f9087cSSteven J. Hill 
7729f9087cSSteven J. Hill 	segcfg >>= 16;
7829f9087cSSteven J. Hill 	build_segment_config(str, segcfg);
7929f9087cSSteven J. Hill 	seq_printf(m, "   5      00000000    1G       %s\n", str);
8029f9087cSSteven J. Hill 
8129f9087cSSteven J. Hill 	return 0;
8229f9087cSSteven J. Hill }
83*27a43a85SLiu Shixin DEFINE_SHOW_ATTRIBUTE(segments);
8429f9087cSSteven J. Hill 
segments_info(void)8529f9087cSSteven J. Hill static int __init segments_info(void)
8629f9087cSSteven J. Hill {
87d8140426SGreg Kroah-Hartman 	if (cpu_has_segments)
88d8140426SGreg Kroah-Hartman 		debugfs_create_file("segments", S_IRUGO, mips_debugfs_dir, NULL,
8929f9087cSSteven J. Hill 				    &segments_fops);
9029f9087cSSteven J. Hill 	return 0;
9129f9087cSSteven J. Hill }
9229f9087cSSteven J. Hill 
9329f9087cSSteven J. Hill device_initcall(segments_info);
94