^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * License. See the file "COPYING" in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2013 Imagination Technologies Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/debug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/mipsregs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static void build_segment_config(char *str, unsigned int cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) unsigned int am;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static const char * const am_str[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) "UK", "MK", "MSK", "MUSK", "MUSUK", "USK",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) "RSRVD", "UUSK"};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* Segment access mode. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) am = (cfg & MIPS_SEGCFG_AM) >> MIPS_SEGCFG_AM_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) str += sprintf(str, "%-5s", am_str[am]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * Access modes MK, MSK and MUSK are mapped segments. Therefore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * there is no direct physical address mapping unless it becomes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * unmapped uncached at error level due to EU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) if ((am == 0) || (am > 3) || (cfg & MIPS_SEGCFG_EU))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) str += sprintf(str, " %03lx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) ((cfg & MIPS_SEGCFG_PA) >> MIPS_SEGCFG_PA_SHIFT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) str += sprintf(str, " UND");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if ((am == 0) || (am > 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) str += sprintf(str, " %01ld",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) ((cfg & MIPS_SEGCFG_C) >> MIPS_SEGCFG_C_SHIFT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) str += sprintf(str, " U");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /* Exception configuration. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) str += sprintf(str, " %01ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) ((cfg & MIPS_SEGCFG_EU) >> MIPS_SEGCFG_EU_SHIFT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static int show_segments(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) unsigned int segcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) char str[42];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) seq_puts(m, "Segment Virtual Size Access Mode Physical Caching EU\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) seq_puts(m, "------- ------- ---- ----------- -------- ------- --\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) segcfg = read_c0_segctl0();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) build_segment_config(str, segcfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) seq_printf(m, " 0 e0000000 512M %s", str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) segcfg >>= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) build_segment_config(str, segcfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) seq_printf(m, " 1 c0000000 512M %s", str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) segcfg = read_c0_segctl1();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) build_segment_config(str, segcfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) seq_printf(m, " 2 a0000000 512M %s", str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) segcfg >>= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) build_segment_config(str, segcfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) seq_printf(m, " 3 80000000 512M %s", str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) segcfg = read_c0_segctl2();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) build_segment_config(str, segcfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) seq_printf(m, " 4 40000000 1G %s", str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) segcfg >>= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) build_segment_config(str, segcfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) seq_printf(m, " 5 00000000 1G %s\n", str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static int segments_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return single_open(file, show_segments, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static const struct file_operations segments_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .open = segments_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) .read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) .llseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) .release = single_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static int __init segments_info(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (cpu_has_segments)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) debugfs_create_file("segments", S_IRUGO, mips_debugfs_dir, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) &segments_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) device_initcall(segments_info);