Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[MIPS] IP28 support

Add support for SGI IP28 machines (Indigo 2 with R10k CPUs)
This work is mainly based on Peter Fuersts work.

Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by

Thomas Bogendoerfer and committed by
Ralf Baechle
e2defae5 81149be1

+693 -10
+64 -3
arch/mips/Kconfig
··· 127 127 select ARCH_MAY_HAVE_PC_FDC 128 128 select CEVT_R4K 129 129 select CSRC_R4K 130 + select DEFAULT_SGI_PARTITION if CPU_BIG_ENDIAN 130 131 select GENERIC_ISA_DMA 131 132 select IRQ_CPU 132 133 select I8253 ··· 402 401 select BOOT_ELF32 403 402 select CEVT_R4K 404 403 select CSRC_R4K 404 + select DEFAULT_SGI_PARTITION 405 405 select DMA_NONCOHERENT 406 406 select HW_HAS_EISA 407 407 select I8253 ··· 410 408 select IP22_CPU_SCACHE 411 409 select IRQ_CPU 412 410 select GENERIC_ISA_DMA_SUPPORT_BROKEN 411 + select SGI_HAS_DS1286 412 + select SGI_HAS_I8042 413 + select SGI_HAS_INDYDOG 414 + select SGI_HAS_SEEQ 415 + select SGI_HAS_WD93 416 + select SGI_HAS_ZILOG 413 417 select SWAP_IO_SPACE 414 418 select SYS_HAS_CPU_R4X00 415 419 select SYS_HAS_CPU_R5000 ··· 433 425 select ARC 434 426 select ARC64 435 427 select BOOT_ELF64 428 + select DEFAULT_SGI_PARTITION 436 429 select DMA_IP27 437 430 select SYS_HAS_EARLY_PRINTK 438 431 select HW_HAS_PCI ··· 449 440 This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics 450 441 workstations. To compile a Linux kernel that runs on these, say Y 451 442 here. 443 + 444 + config SGI_IP28 445 + bool "SGI IP28 (Indigo2 R10k) (EXPERIMENTAL)" 446 + depends on EXPERIMENTAL 447 + select ARC 448 + select ARC64 449 + select BOOT_ELF64 450 + select CEVT_R4K 451 + select CSRC_R4K 452 + select DEFAULT_SGI_PARTITION 453 + select DMA_NONCOHERENT 454 + select GENERIC_ISA_DMA_SUPPORT_BROKEN 455 + select IRQ_CPU 456 + select HW_HAS_EISA 457 + select I8253 458 + select I8259 459 + select SGI_HAS_DS1286 460 + select SGI_HAS_I8042 461 + select SGI_HAS_INDYDOG 462 + select SGI_HAS_SEEQ 463 + select SGI_HAS_WD93 464 + select SGI_HAS_ZILOG 465 + select SWAP_IO_SPACE 466 + select SYS_HAS_CPU_R10000 467 + select SYS_HAS_EARLY_PRINTK 468 + select SYS_SUPPORTS_64BIT_KERNEL 469 + select SYS_SUPPORTS_BIG_ENDIAN 470 + help 471 + This is the SGI Indigo2 with R10000 processor. To compile a Linux 472 + kernel that runs on these, say Y here. 452 473 453 474 config SGI_IP32 454 475 bool "SGI IP32 (O2)" ··· 606 567 select BOOT_ELF32 607 568 select CEVT_R4K 608 569 select CSRC_R4K 570 + select DEFAULT_SGI_PARTITION if CPU_BIG_ENDIAN 609 571 select DMA_NONCOHERENT 610 572 select GENERIC_ISA_DMA 611 573 select HW_HAS_EISA ··· 979 939 config SERIAL_RM9000 980 940 bool 981 941 942 + config SGI_HAS_DS1286 943 + bool 944 + 945 + config SGI_HAS_INDYDOG 946 + bool 947 + 948 + config SGI_HAS_SEEQ 949 + bool 950 + 951 + config SGI_HAS_WD93 952 + bool 953 + 954 + config SGI_HAS_ZILOG 955 + bool 956 + 957 + config SGI_HAS_I8042 958 + bool 959 + 960 + config DEFAULT_SGI_PARTITION 961 + bool 962 + 982 963 config ARC32 983 964 bool 984 965 ··· 1009 948 config MIPS_L1_CACHE_SHIFT 1010 949 int 1011 950 default "4" if MACH_DECSTATION 1012 - default "7" if SGI_IP27 || SNI_RM 951 + default "7" if SGI_IP27 || SGI_IP28 || SNI_RM 1013 952 default "4" if PMC_MSP4200_EVAL 1014 953 default "5" 1015 954 ··· 1018 957 1019 958 config ARC_CONSOLE 1020 959 bool "ARC console support" 1021 - depends on SGI_IP22 || (SNI_RM && CPU_LITTLE_ENDIAN) 960 + depends on SGI_IP22 || SGI_IP28 || (SNI_RM && CPU_LITTLE_ENDIAN) 1022 961 1023 962 config ARC_MEMORY 1024 963 bool ··· 1027 966 1028 967 config ARC_PROMLIB 1029 968 bool 1030 - depends on MACH_JAZZ || SNI_RM || SGI_IP22 || SGI_IP32 969 + depends on MACH_JAZZ || SNI_RM || SGI_IP22 || SGI_IP28 || SGI_IP32 1031 970 default y 1032 971 1033 972 config ARC64
+14
arch/mips/Makefile
··· 479 479 endif 480 480 481 481 # 482 + # SGI IP28 (Indigo2 R10k) 483 + # 484 + # Set the load address to >= 0xa800000020080000 if you want to leave space for 485 + # symmon, 0xa800000020004000 for production kernels ? Note that the value must 486 + # be 16kb aligned or the handling of the current variable will break. 487 + # Simplified: what IP22 does at 128MB+ in ksegN, IP28 does at 512MB+ in xkphys 488 + # 489 + #core-$(CONFIG_SGI_IP28) += arch/mips/sgi-ip22/ arch/mips/arc/arc_con.o 490 + core-$(CONFIG_SGI_IP28) += arch/mips/sgi-ip22/ 491 + cflags-$(CONFIG_SGI_IP28) += -mr10k-cache-barrier=1 -Iinclude/asm-mips/mach-ip28 492 + #cflags-$(CONFIG_SGI_IP28) += -Iinclude/asm-mips/mach-ip28 493 + load-$(CONFIG_SGI_IP28) += 0xa800000020004000 494 + 495 + # 482 496 # SGI-IP32 (O2) 483 497 # 484 498 # Set the load address to >= 80069000 if you want to leave space for symmon,
+5 -3
arch/mips/sgi-ip22/Makefile
··· 3 3 # under Linux. 4 4 # 5 5 6 - obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-berr.o \ 7 - ip22-time.o ip22-nvram.o ip22-platform.o ip22-reset.o ip22-setup.o 6 + obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-time.o ip22-nvram.o \ 7 + ip22-platform.o ip22-reset.o ip22-setup.o 8 8 9 + obj-$(CONFIG_SGI_IP22) += ip22-berr.o 10 + obj-$(CONFIG_SGI_IP28) += ip28-berr.o 9 11 obj-$(CONFIG_EISA) += ip22-eisa.o 10 12 11 - EXTRA_CFLAGS += -Werror 13 + # EXTRA_CFLAGS += -Werror
+4
arch/mips/sgi-ip22/ip22-mc.c
··· 4 4 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) 5 5 * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) - Indigo2 changes 6 6 * Copyright (C) 2003 Ladislav Michl (ladis@linux-mips.org) 7 + * Copyright (C) 2004 Peter Fuerst (pf@net.alphadv.de) - IP28 7 8 */ 8 9 9 10 #include <linux/init.h> ··· 138 137 /* Step 2: Enable all parity checking in cpu control register 139 138 * zero. 140 139 */ 140 + /* don't touch parity settings for IP28 */ 141 + #ifndef CONFIG_SGI_IP28 141 142 tmp = sgimc->cpuctrl0; 142 143 tmp |= (SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM | 143 144 SGIMC_CCTRL0_R4KNOCHKPARR); 145 + #endif 144 146 sgimc->cpuctrl0 = tmp; 145 147 146 148 /* Step 3: Setup the MC write buffer depth, this is controlled
+502
arch/mips/sgi-ip22/ip28-berr.c
··· 1 + /* 2 + * ip28-berr.c: Bus error handling. 3 + * 4 + * Copyright (C) 2002, 2003 Ladislav Michl (ladis@linux-mips.org) 5 + * Copyright (C) 2005 Peter Fuerst (pf@net.alphadv.de) - IP28 6 + */ 7 + 8 + #include <linux/init.h> 9 + #include <linux/kernel.h> 10 + #include <linux/sched.h> 11 + #include <linux/seq_file.h> 12 + 13 + #include <asm/addrspace.h> 14 + #include <asm/system.h> 15 + #include <asm/traps.h> 16 + #include <asm/branch.h> 17 + #include <asm/irq_regs.h> 18 + #include <asm/sgi/mc.h> 19 + #include <asm/sgi/hpc3.h> 20 + #include <asm/sgi/ioc.h> 21 + #include <asm/sgi/ip22.h> 22 + #include <asm/r4kcache.h> 23 + #include <asm/uaccess.h> 24 + #include <asm/bootinfo.h> 25 + 26 + static unsigned int count_be_is_fixup; 27 + static unsigned int count_be_handler; 28 + static unsigned int count_be_interrupt; 29 + static int debug_be_interrupt; 30 + 31 + static unsigned int cpu_err_stat; /* Status reg for CPU */ 32 + static unsigned int gio_err_stat; /* Status reg for GIO */ 33 + static unsigned int cpu_err_addr; /* Error address reg for CPU */ 34 + static unsigned int gio_err_addr; /* Error address reg for GIO */ 35 + static unsigned int extio_stat; 36 + static unsigned int hpc3_berr_stat; /* Bus error interrupt status */ 37 + 38 + struct hpc3_stat { 39 + unsigned long addr; 40 + unsigned int ctrl; 41 + unsigned int cbp; 42 + unsigned int ndptr; 43 + }; 44 + 45 + static struct { 46 + struct hpc3_stat pbdma[8]; 47 + struct hpc3_stat scsi[2]; 48 + struct hpc3_stat ethrx, ethtx; 49 + } hpc3; 50 + 51 + static struct { 52 + unsigned long err_addr; 53 + struct { 54 + u32 lo; 55 + u32 hi; 56 + } tags[1][2], tagd[4][2], tagi[4][2]; /* Way 0/1 */ 57 + } cache_tags; 58 + 59 + static inline void save_cache_tags(unsigned busaddr) 60 + { 61 + unsigned long addr = CAC_BASE | busaddr; 62 + int i; 63 + cache_tags.err_addr = addr; 64 + 65 + /* 66 + * Starting with a bus-address, save secondary cache (indexed by 67 + * PA[23..18:7..6]) tags first. 68 + */ 69 + addr &= ~1L; 70 + #define tag cache_tags.tags[0] 71 + cache_op(Index_Load_Tag_S, addr); 72 + tag[0].lo = read_c0_taglo(); /* PA[35:18], VA[13:12] */ 73 + tag[0].hi = read_c0_taghi(); /* PA[39:36] */ 74 + cache_op(Index_Load_Tag_S, addr | 1L); 75 + tag[1].lo = read_c0_taglo(); /* PA[35:18], VA[13:12] */ 76 + tag[1].hi = read_c0_taghi(); /* PA[39:36] */ 77 + #undef tag 78 + 79 + /* 80 + * Save all primary data cache (indexed by VA[13:5]) tags which 81 + * might fit to this bus-address, knowing that VA[11:0] == PA[11:0]. 82 + * Saving all tags and evaluating them later is easier and safer 83 + * than relying on VA[13:12] from the secondary cache tags to pick 84 + * matching primary tags here already. 85 + */ 86 + addr &= (0xffL << 56) | ((1 << 12) - 1); 87 + #define tag cache_tags.tagd[i] 88 + for (i = 0; i < 4; ++i, addr += (1 << 12)) { 89 + cache_op(Index_Load_Tag_D, addr); 90 + tag[0].lo = read_c0_taglo(); /* PA[35:12] */ 91 + tag[0].hi = read_c0_taghi(); /* PA[39:36] */ 92 + cache_op(Index_Load_Tag_D, addr | 1L); 93 + tag[1].lo = read_c0_taglo(); /* PA[35:12] */ 94 + tag[1].hi = read_c0_taghi(); /* PA[39:36] */ 95 + } 96 + #undef tag 97 + 98 + /* 99 + * Save primary instruction cache (indexed by VA[13:6]) tags 100 + * the same way. 101 + */ 102 + addr &= (0xffL << 56) | ((1 << 12) - 1); 103 + #define tag cache_tags.tagi[i] 104 + for (i = 0; i < 4; ++i, addr += (1 << 12)) { 105 + cache_op(Index_Load_Tag_I, addr); 106 + tag[0].lo = read_c0_taglo(); /* PA[35:12] */ 107 + tag[0].hi = read_c0_taghi(); /* PA[39:36] */ 108 + cache_op(Index_Load_Tag_I, addr | 1L); 109 + tag[1].lo = read_c0_taglo(); /* PA[35:12] */ 110 + tag[1].hi = read_c0_taghi(); /* PA[39:36] */ 111 + } 112 + #undef tag 113 + } 114 + 115 + #define GIO_ERRMASK 0xff00 116 + #define CPU_ERRMASK 0x3f00 117 + 118 + static void save_and_clear_buserr(void) 119 + { 120 + int i; 121 + 122 + /* save status registers */ 123 + cpu_err_addr = sgimc->cerr; 124 + cpu_err_stat = sgimc->cstat; 125 + gio_err_addr = sgimc->gerr; 126 + gio_err_stat = sgimc->gstat; 127 + extio_stat = sgioc->extio; 128 + hpc3_berr_stat = hpc3c0->bestat; 129 + 130 + hpc3.scsi[0].addr = (unsigned long)&hpc3c0->scsi_chan0; 131 + hpc3.scsi[0].ctrl = hpc3c0->scsi_chan0.ctrl; /* HPC3_SCTRL_ACTIVE ? */ 132 + hpc3.scsi[0].cbp = hpc3c0->scsi_chan0.cbptr; 133 + hpc3.scsi[0].ndptr = hpc3c0->scsi_chan0.ndptr; 134 + 135 + hpc3.scsi[1].addr = (unsigned long)&hpc3c0->scsi_chan1; 136 + hpc3.scsi[1].ctrl = hpc3c0->scsi_chan1.ctrl; /* HPC3_SCTRL_ACTIVE ? */ 137 + hpc3.scsi[1].cbp = hpc3c0->scsi_chan1.cbptr; 138 + hpc3.scsi[1].ndptr = hpc3c0->scsi_chan1.ndptr; 139 + 140 + hpc3.ethrx.addr = (unsigned long)&hpc3c0->ethregs.rx_cbptr; 141 + hpc3.ethrx.ctrl = hpc3c0->ethregs.rx_ctrl; /* HPC3_ERXCTRL_ACTIVE ? */ 142 + hpc3.ethrx.cbp = hpc3c0->ethregs.rx_cbptr; 143 + hpc3.ethrx.ndptr = hpc3c0->ethregs.rx_ndptr; 144 + 145 + hpc3.ethtx.addr = (unsigned long)&hpc3c0->ethregs.tx_cbptr; 146 + hpc3.ethtx.ctrl = hpc3c0->ethregs.tx_ctrl; /* HPC3_ETXCTRL_ACTIVE ? */ 147 + hpc3.ethtx.cbp = hpc3c0->ethregs.tx_cbptr; 148 + hpc3.ethtx.ndptr = hpc3c0->ethregs.tx_ndptr; 149 + 150 + for (i = 0; i < 8; ++i) { 151 + /* HPC3_PDMACTRL_ISACT ? */ 152 + hpc3.pbdma[i].addr = (unsigned long)&hpc3c0->pbdma[i]; 153 + hpc3.pbdma[i].ctrl = hpc3c0->pbdma[i].pbdma_ctrl; 154 + hpc3.pbdma[i].cbp = hpc3c0->pbdma[i].pbdma_bptr; 155 + hpc3.pbdma[i].ndptr = hpc3c0->pbdma[i].pbdma_dptr; 156 + } 157 + i = 0; 158 + if (gio_err_stat & CPU_ERRMASK) 159 + i = gio_err_addr; 160 + if (cpu_err_stat & CPU_ERRMASK) 161 + i = cpu_err_addr; 162 + save_cache_tags(i); 163 + 164 + sgimc->cstat = sgimc->gstat = 0; 165 + } 166 + 167 + static void print_cache_tags(void) 168 + { 169 + u32 scb, scw; 170 + int i; 171 + 172 + printk(KERN_ERR "Cache tags @ %08x:\n", (unsigned)cache_tags.err_addr); 173 + 174 + /* PA[31:12] shifted to PTag0 (PA[35:12]) format */ 175 + scw = (cache_tags.err_addr >> 4) & 0x0fffff00; 176 + 177 + scb = cache_tags.err_addr & ((1 << 12) - 1) & ~((1 << 5) - 1); 178 + for (i = 0; i < 4; ++i) { /* for each possible VA[13:12] value */ 179 + if ((cache_tags.tagd[i][0].lo & 0x0fffff00) != scw && 180 + (cache_tags.tagd[i][1].lo & 0x0fffff00) != scw) 181 + continue; 182 + printk(KERN_ERR 183 + "D: 0: %08x %08x, 1: %08x %08x (VA[13:5] %04x)\n", 184 + cache_tags.tagd[i][0].hi, cache_tags.tagd[i][0].lo, 185 + cache_tags.tagd[i][1].hi, cache_tags.tagd[i][1].lo, 186 + scb | (1 << 12)*i); 187 + } 188 + scb = cache_tags.err_addr & ((1 << 12) - 1) & ~((1 << 6) - 1); 189 + for (i = 0; i < 4; ++i) { /* for each possible VA[13:12] value */ 190 + if ((cache_tags.tagi[i][0].lo & 0x0fffff00) != scw && 191 + (cache_tags.tagi[i][1].lo & 0x0fffff00) != scw) 192 + continue; 193 + printk(KERN_ERR 194 + "I: 0: %08x %08x, 1: %08x %08x (VA[13:6] %04x)\n", 195 + cache_tags.tagi[i][0].hi, cache_tags.tagi[i][0].lo, 196 + cache_tags.tagi[i][1].hi, cache_tags.tagi[i][1].lo, 197 + scb | (1 << 12)*i); 198 + } 199 + i = read_c0_config(); 200 + scb = i & (1 << 13) ? 7:6; /* scblksize = 2^[7..6] */ 201 + scw = ((i >> 16) & 7) + 19 - 1; /* scwaysize = 2^[24..19] / 2 */ 202 + 203 + i = ((1 << scw) - 1) & ~((1 << scb) - 1); 204 + printk(KERN_ERR "S: 0: %08x %08x, 1: %08x %08x (PA[%u:%u] %05x)\n", 205 + cache_tags.tags[0][0].hi, cache_tags.tags[0][0].lo, 206 + cache_tags.tags[0][1].hi, cache_tags.tags[0][1].lo, 207 + scw-1, scb, i & (unsigned)cache_tags.err_addr); 208 + } 209 + 210 + static inline const char *cause_excode_text(int cause) 211 + { 212 + static const char *txt[32] = 213 + { "Interrupt", 214 + "TLB modification", 215 + "TLB (load or instruction fetch)", 216 + "TLB (store)", 217 + "Address error (load or instruction fetch)", 218 + "Address error (store)", 219 + "Bus error (instruction fetch)", 220 + "Bus error (data: load or store)", 221 + "Syscall", 222 + "Breakpoint", 223 + "Reserved instruction", 224 + "Coprocessor unusable", 225 + "Arithmetic Overflow", 226 + "Trap", 227 + "14", 228 + "Floating-Point", 229 + "16", "17", "18", "19", "20", "21", "22", 230 + "Watch Hi/Lo", 231 + "24", "25", "26", "27", "28", "29", "30", "31", 232 + }; 233 + return txt[(cause & 0x7c) >> 2]; 234 + } 235 + 236 + static void print_buserr(const struct pt_regs *regs) 237 + { 238 + const int field = 2 * sizeof(unsigned long); 239 + int error = 0; 240 + 241 + if (extio_stat & EXTIO_MC_BUSERR) { 242 + printk(KERN_ERR "MC Bus Error\n"); 243 + error |= 1; 244 + } 245 + if (extio_stat & EXTIO_HPC3_BUSERR) { 246 + printk(KERN_ERR "HPC3 Bus Error 0x%x:<id=0x%x,%s,lane=0x%x>\n", 247 + hpc3_berr_stat, 248 + (hpc3_berr_stat & HPC3_BESTAT_PIDMASK) >> 249 + HPC3_BESTAT_PIDSHIFT, 250 + (hpc3_berr_stat & HPC3_BESTAT_CTYPE) ? "PIO" : "DMA", 251 + hpc3_berr_stat & HPC3_BESTAT_BLMASK); 252 + error |= 2; 253 + } 254 + if (extio_stat & EXTIO_EISA_BUSERR) { 255 + printk(KERN_ERR "EISA Bus Error\n"); 256 + error |= 4; 257 + } 258 + if (cpu_err_stat & CPU_ERRMASK) { 259 + printk(KERN_ERR "CPU error 0x%x<%s%s%s%s%s%s> @ 0x%08x\n", 260 + cpu_err_stat, 261 + cpu_err_stat & SGIMC_CSTAT_RD ? "RD " : "", 262 + cpu_err_stat & SGIMC_CSTAT_PAR ? "PAR " : "", 263 + cpu_err_stat & SGIMC_CSTAT_ADDR ? "ADDR " : "", 264 + cpu_err_stat & SGIMC_CSTAT_SYSAD_PAR ? "SYSAD " : "", 265 + cpu_err_stat & SGIMC_CSTAT_SYSCMD_PAR ? "SYSCMD " : "", 266 + cpu_err_stat & SGIMC_CSTAT_BAD_DATA ? "BAD_DATA " : "", 267 + cpu_err_addr); 268 + error |= 8; 269 + } 270 + if (gio_err_stat & GIO_ERRMASK) { 271 + printk(KERN_ERR "GIO error 0x%x:<%s%s%s%s%s%s%s%s> @ 0x%08x\n", 272 + gio_err_stat, 273 + gio_err_stat & SGIMC_GSTAT_RD ? "RD " : "", 274 + gio_err_stat & SGIMC_GSTAT_WR ? "WR " : "", 275 + gio_err_stat & SGIMC_GSTAT_TIME ? "TIME " : "", 276 + gio_err_stat & SGIMC_GSTAT_PROM ? "PROM " : "", 277 + gio_err_stat & SGIMC_GSTAT_ADDR ? "ADDR " : "", 278 + gio_err_stat & SGIMC_GSTAT_BC ? "BC " : "", 279 + gio_err_stat & SGIMC_GSTAT_PIO_RD ? "PIO_RD " : "", 280 + gio_err_stat & SGIMC_GSTAT_PIO_WR ? "PIO_WR " : "", 281 + gio_err_addr); 282 + error |= 16; 283 + } 284 + if (!error) 285 + printk(KERN_ERR "MC: Hmm, didn't find any error condition.\n"); 286 + else { 287 + printk(KERN_ERR "CP0: config %08x, " 288 + "MC: cpuctrl0/1: %08x/%05x, giopar: %04x\n" 289 + "MC: cpu/gio_memacc: %08x/%05x, memcfg0/1: %08x/%08x\n", 290 + read_c0_config(), 291 + sgimc->cpuctrl0, sgimc->cpuctrl0, sgimc->giopar, 292 + sgimc->cmacc, sgimc->gmacc, 293 + sgimc->mconfig0, sgimc->mconfig1); 294 + print_cache_tags(); 295 + } 296 + printk(KERN_ALERT "%s, epc == %0*lx, ra == %0*lx\n", 297 + cause_excode_text(regs->cp0_cause), 298 + field, regs->cp0_epc, field, regs->regs[31]); 299 + } 300 + 301 + /* 302 + * Check, whether MC's (virtual) DMA address caused the bus error. 303 + * See "Virtual DMA Specification", Draft 1.5, Feb 13 1992, SGI 304 + */ 305 + 306 + static int addr_is_ram(unsigned long addr, unsigned sz) 307 + { 308 + int i; 309 + 310 + for (i = 0; i < boot_mem_map.nr_map; i++) { 311 + unsigned long a = boot_mem_map.map[i].addr; 312 + if (a <= addr && addr+sz <= a+boot_mem_map.map[i].size) 313 + return 1; 314 + } 315 + return 0; 316 + } 317 + 318 + static int check_microtlb(u32 hi, u32 lo, unsigned long vaddr) 319 + { 320 + /* This is likely rather similar to correct code ;-) */ 321 + 322 + vaddr &= 0x7fffffff; /* Doc. states that top bit is ignored */ 323 + 324 + /* If tlb-entry is valid and VPN-high (bits [30:21] ?) matches... */ 325 + if ((lo & 2) && (vaddr >> 21) == ((hi<<1) >> 22)) { 326 + u32 ctl = sgimc->dma_ctrl; 327 + if (ctl & 1) { 328 + unsigned int pgsz = (ctl & 2) ? 14:12; /* 16k:4k */ 329 + /* PTEIndex is VPN-low (bits [22:14]/[20:12] ?) */ 330 + unsigned long pte = (lo >> 6) << 12; /* PTEBase */ 331 + pte += 8*((vaddr >> pgsz) & 0x1ff); 332 + if (addr_is_ram(pte, 8)) { 333 + /* 334 + * Note: Since DMA hardware does look up 335 + * translation on its own, this PTE *must* 336 + * match the TLB/EntryLo-register format ! 337 + */ 338 + unsigned long a = *(unsigned long *) 339 + PHYS_TO_XKSEG_UNCACHED(pte); 340 + a = (a & 0x3f) << 6; /* PFN */ 341 + a += vaddr & ((1 << pgsz) - 1); 342 + return (cpu_err_addr == a); 343 + } 344 + } 345 + } 346 + return 0; 347 + } 348 + 349 + static int check_vdma_memaddr(void) 350 + { 351 + if (cpu_err_stat & CPU_ERRMASK) { 352 + u32 a = sgimc->maddronly; 353 + 354 + if (!(sgimc->dma_ctrl & 0x100)) /* Xlate-bit clear ? */ 355 + return (cpu_err_addr == a); 356 + 357 + if (check_microtlb(sgimc->dtlb_hi0, sgimc->dtlb_lo0, a) || 358 + check_microtlb(sgimc->dtlb_hi1, sgimc->dtlb_lo1, a) || 359 + check_microtlb(sgimc->dtlb_hi2, sgimc->dtlb_lo2, a) || 360 + check_microtlb(sgimc->dtlb_hi3, sgimc->dtlb_lo3, a)) 361 + return 1; 362 + } 363 + return 0; 364 + } 365 + 366 + static int check_vdma_gioaddr(void) 367 + { 368 + if (gio_err_stat & GIO_ERRMASK) { 369 + u32 a = sgimc->gio_dma_trans; 370 + a = (sgimc->gmaddronly & ~a) | (sgimc->gio_dma_sbits & a); 371 + return (gio_err_addr == a); 372 + } 373 + return 0; 374 + } 375 + 376 + /* 377 + * MC sends an interrupt whenever bus or parity errors occur. In addition, 378 + * if the error happened during a CPU read, it also asserts the bus error 379 + * pin on the R4K. Code in bus error handler save the MC bus error registers 380 + * and then clear the interrupt when this happens. 381 + */ 382 + 383 + static int ip28_be_interrupt(const struct pt_regs *regs) 384 + { 385 + int i; 386 + 387 + save_and_clear_buserr(); 388 + /* 389 + * Try to find out, whether we got here by a mispredicted speculative 390 + * load/store operation. If so, it's not fatal, we can go on. 391 + */ 392 + /* Any cause other than "Interrupt" (ExcCode 0) is fatal. */ 393 + if (regs->cp0_cause & CAUSEF_EXCCODE) 394 + goto mips_be_fatal; 395 + 396 + /* Any cause other than "Bus error interrupt" (IP6) is weird. */ 397 + if ((regs->cp0_cause & CAUSEF_IP6) != CAUSEF_IP6) 398 + goto mips_be_fatal; 399 + 400 + if (extio_stat & (EXTIO_HPC3_BUSERR | EXTIO_EISA_BUSERR)) 401 + goto mips_be_fatal; 402 + 403 + /* Any state other than "Memory bus error" is fatal. */ 404 + if (cpu_err_stat & CPU_ERRMASK & ~SGIMC_CSTAT_ADDR) 405 + goto mips_be_fatal; 406 + 407 + /* GIO errors other than timeouts are fatal */ 408 + if (gio_err_stat & GIO_ERRMASK & ~SGIMC_GSTAT_TIME) 409 + goto mips_be_fatal; 410 + 411 + /* 412 + * Now we have an asynchronous bus error, speculatively or DMA caused. 413 + * Need to search all DMA descriptors for the error address. 414 + */ 415 + for (i = 0; i < sizeof(hpc3)/sizeof(struct hpc3_stat); ++i) { 416 + struct hpc3_stat *hp = (struct hpc3_stat *)&hpc3 + i; 417 + if ((cpu_err_stat & CPU_ERRMASK) && 418 + (cpu_err_addr == hp->ndptr || cpu_err_addr == hp->cbp)) 419 + break; 420 + if ((gio_err_stat & GIO_ERRMASK) && 421 + (gio_err_addr == hp->ndptr || gio_err_addr == hp->cbp)) 422 + break; 423 + } 424 + if (i < sizeof(hpc3)/sizeof(struct hpc3_stat)) { 425 + struct hpc3_stat *hp = (struct hpc3_stat *)&hpc3 + i; 426 + printk(KERN_ERR "at DMA addresses: HPC3 @ %08lx:" 427 + " ctl %08x, ndp %08x, cbp %08x\n", 428 + CPHYSADDR(hp->addr), hp->ctrl, hp->ndptr, hp->cbp); 429 + goto mips_be_fatal; 430 + } 431 + /* Check MC's virtual DMA stuff. */ 432 + if (check_vdma_memaddr()) { 433 + printk(KERN_ERR "at GIO DMA: mem address 0x%08x.\n", 434 + sgimc->maddronly); 435 + goto mips_be_fatal; 436 + } 437 + if (check_vdma_gioaddr()) { 438 + printk(KERN_ERR "at GIO DMA: gio address 0x%08x.\n", 439 + sgimc->gmaddronly); 440 + goto mips_be_fatal; 441 + } 442 + /* A speculative bus error... */ 443 + if (debug_be_interrupt) { 444 + print_buserr(regs); 445 + printk(KERN_ERR "discarded!\n"); 446 + } 447 + return MIPS_BE_DISCARD; 448 + 449 + mips_be_fatal: 450 + print_buserr(regs); 451 + return MIPS_BE_FATAL; 452 + } 453 + 454 + void ip22_be_interrupt(int irq) 455 + { 456 + const struct pt_regs *regs = get_irq_regs(); 457 + 458 + count_be_interrupt++; 459 + 460 + if (ip28_be_interrupt(regs) != MIPS_BE_DISCARD) { 461 + /* Assume it would be too dangerous to continue ... */ 462 + die_if_kernel("Oops", regs); 463 + force_sig(SIGBUS, current); 464 + } else if (debug_be_interrupt) 465 + show_regs((struct pt_regs *)regs); 466 + } 467 + 468 + static int ip28_be_handler(struct pt_regs *regs, int is_fixup) 469 + { 470 + /* 471 + * We arrive here only in the unusual case of do_be() invocation, 472 + * i.e. by a bus error exception without a bus error interrupt. 473 + */ 474 + if (is_fixup) { 475 + count_be_is_fixup++; 476 + save_and_clear_buserr(); 477 + return MIPS_BE_FIXUP; 478 + } 479 + count_be_handler++; 480 + return ip28_be_interrupt(regs); 481 + } 482 + 483 + void __init ip22_be_init(void) 484 + { 485 + board_be_handler = ip28_be_handler; 486 + } 487 + 488 + int ip28_show_be_info(struct seq_file *m) 489 + { 490 + seq_printf(m, "IP28 be fixups\t\t: %u\n", count_be_is_fixup); 491 + seq_printf(m, "IP28 be interrupts\t: %u\n", count_be_interrupt); 492 + seq_printf(m, "IP28 be handler\t\t: %u\n", count_be_handler); 493 + 494 + return 0; 495 + } 496 + 497 + static int __init debug_be_setup(char *str) 498 + { 499 + debug_be_interrupt++; 500 + return 1; 501 + } 502 + __setup("ip28_debug_be", debug_be_setup);
+3 -4
include/asm-mips/dma.h
··· 84 84 * Deskstations or Acer PICA but not the much more versatile DMA logic used 85 85 * for the local devices on Acer PICA or Magnums. 86 86 */ 87 - #ifdef CONFIG_SGI_IP22 88 - /* Horrible hack to have a correct DMA window on IP22 */ 89 - #include <asm/sgi/mc.h> 90 - #define MAX_DMA_ADDRESS (PAGE_OFFSET + SGIMC_SEG0_BADDR + 0x01000000) 87 + #if defined(CONFIG_SGI_IP22) || defined(CONFIG_SGI_IP28) 88 + /* don't care; ISA bus master won't work, ISA slave DMA supports 32bit addr */ 89 + #define MAX_DMA_ADDRESS PAGE_OFFSET 91 90 #else 92 91 #define MAX_DMA_ADDRESS (PAGE_OFFSET + 0x01000000) 93 92 #endif
+50
include/asm-mips/mach-ip28/cpu-feature-overrides.h
··· 1 + /* 2 + * This file is subject to the terms and conditions of the GNU General Public 3 + * License. See the file "COPYING" in the main directory of this archive 4 + * for more details. 5 + * 6 + * Copyright (C) 2003 Ralf Baechle 7 + * 6/2004 pf 8 + */ 9 + #ifndef __ASM_MACH_IP28_CPU_FEATURE_OVERRIDES_H 10 + #define __ASM_MACH_IP28_CPU_FEATURE_OVERRIDES_H 11 + 12 + /* 13 + * IP28 only comes with R10000 family processors all using the same config 14 + */ 15 + #define cpu_has_watch 1 16 + #define cpu_has_mips16 0 17 + #define cpu_has_divec 0 18 + #define cpu_has_vce 0 19 + #define cpu_has_cache_cdex_p 0 20 + #define cpu_has_cache_cdex_s 0 21 + #define cpu_has_prefetch 1 22 + #define cpu_has_mcheck 0 23 + #define cpu_has_ejtag 0 24 + 25 + #define cpu_has_llsc 1 26 + #define cpu_has_vtag_icache 0 27 + #define cpu_has_dc_aliases 0 /* see probe_pcache() */ 28 + #define cpu_has_ic_fills_f_dc 0 29 + #define cpu_has_dsp 0 30 + #define cpu_icache_snoops_remote_store 1 31 + #define cpu_has_mipsmt 0 32 + #define cpu_has_userlocal 0 33 + 34 + #define cpu_has_nofpuex 0 35 + #define cpu_has_64bits 1 36 + 37 + #define cpu_has_4kex 1 38 + #define cpu_has_4k_cache 1 39 + 40 + #define cpu_has_inclusive_pcaches 1 41 + 42 + #define cpu_dcache_line_size() 32 43 + #define cpu_icache_line_size() 64 44 + 45 + #define cpu_has_mips32r1 0 46 + #define cpu_has_mips32r2 0 47 + #define cpu_has_mips64r1 0 48 + #define cpu_has_mips64r2 0 49 + 50 + #endif /* __ASM_MACH_IP28_CPU_FEATURE_OVERRIDES_H */
+4
include/asm-mips/mach-ip28/ds1286.h
··· 1 + #ifndef __ASM_MACH_IP28_DS1286_H 2 + #define __ASM_MACH_IP28_DS1286_H 3 + #include <asm/mach-ip22/ds1286.h> 4 + #endif /* __ASM_MACH_IP28_DS1286_H */
+22
include/asm-mips/mach-ip28/spaces.h
··· 1 + /* 2 + * This file is subject to the terms and conditions of the GNU General Public 3 + * License. See the file "COPYING" in the main directory of this archive 4 + * for more details. 5 + * 6 + * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle 7 + * Copyright (C) 2000, 2002 Maciej W. Rozycki 8 + * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc. 9 + * 2004 pf 10 + */ 11 + #ifndef _ASM_MACH_IP28_SPACES_H 12 + #define _ASM_MACH_IP28_SPACES_H 13 + 14 + #define CAC_BASE 0xa800000000000000 15 + 16 + #define HIGHMEM_START (~0UL) 17 + 18 + #define PHYS_OFFSET _AC(0x20000000, UL) 19 + 20 + #include <asm/mach-generic/spaces.h> 21 + 22 + #endif /* _ASM_MACH_IP28_SPACES_H */
+25
include/asm-mips/mach-ip28/war.h
··· 1 + /* 2 + * This file is subject to the terms and conditions of the GNU General Public 3 + * License. See the file "COPYING" in the main directory of this archive 4 + * for more details. 5 + * 6 + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> 7 + */ 8 + #ifndef __ASM_MIPS_MACH_IP28_WAR_H 9 + #define __ASM_MIPS_MACH_IP28_WAR_H 10 + 11 + #define R4600_V1_INDEX_ICACHEOP_WAR 0 12 + #define R4600_V1_HIT_CACHEOP_WAR 0 13 + #define R4600_V2_HIT_CACHEOP_WAR 0 14 + #define R5432_CP0_INTERRUPT_WAR 0 15 + #define BCM1250_M3_WAR 0 16 + #define SIBYTE_1956_WAR 0 17 + #define MIPS4K_ICACHE_REFILL_WAR 0 18 + #define MIPS_CACHE_SYNC_WAR 0 19 + #define TX49XX_ICACHE_INDEX_INV_WAR 0 20 + #define RM9000_CDEX_SMP_WAR 0 21 + #define ICACHE_REFILLS_WORKAROUND_WAR 0 22 + #define R10000_LLSC_WAR 1 23 + #define MIPS34K_MISSED_ITLB_WAR 0 24 + 25 + #endif /* __ASM_MIPS_MACH_IP28_WAR_H */