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