1 1.37 thorpej /* $NetBSD: imc.c,v 1.37 2021/08/07 16:19:04 thorpej Exp $ */ 2 1.1 thorpej 3 1.1 thorpej /* 4 1.1 thorpej * Copyright (c) 2001 Rafal K. Boni 5 1.1 thorpej * All rights reserved. 6 1.4 simonb * 7 1.1 thorpej * Redistribution and use in source and binary forms, with or without 8 1.1 thorpej * modification, are permitted provided that the following conditions 9 1.1 thorpej * are met: 10 1.1 thorpej * 1. Redistributions of source code must retain the above copyright 11 1.1 thorpej * notice, this list of conditions and the following disclaimer. 12 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 thorpej * notice, this list of conditions and the following disclaimer in the 14 1.1 thorpej * documentation and/or other materials provided with the distribution. 15 1.1 thorpej * 3. The name of the author may not be used to endorse or promote products 16 1.1 thorpej * derived from this software without specific prior written permission. 17 1.4 simonb * 18 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 1.1 thorpej * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 1.1 thorpej * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 1.1 thorpej * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 1.1 thorpej * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 1.1 thorpej * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 1.1 thorpej * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 1.1 thorpej * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 1.1 thorpej * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 1.1 thorpej * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 1.1 thorpej */ 29 1.9 lukem 30 1.9 lukem #include <sys/cdefs.h> 31 1.37 thorpej __KERNEL_RCSID(0, "$NetBSD: imc.c,v 1.37 2021/08/07 16:19:04 thorpej Exp $"); 32 1.1 thorpej 33 1.1 thorpej #include <sys/param.h> 34 1.1 thorpej #include <sys/device.h> 35 1.1 thorpej #include <sys/systm.h> 36 1.1 thorpej 37 1.1 thorpej #include <machine/cpu.h> 38 1.1 thorpej #include <machine/locore.h> 39 1.1 thorpej #include <machine/autoconf.h> 40 1.32 dyoung #include <sys/bus.h> 41 1.2 thorpej #include <machine/machtype.h> 42 1.12 sekiya #include <machine/sysconf.h> 43 1.1 thorpej 44 1.3 rafal #include <sgimips/dev/imcreg.h> 45 1.26 rumble #include <sgimips/dev/imcvar.h> 46 1.26 rumble 47 1.26 rumble #include <sgimips/gio/giovar.h> 48 1.3 rafal 49 1.1 thorpej #include "locators.h" 50 1.1 thorpej 51 1.1 thorpej struct imc_softc { 52 1.10 sekiya bus_space_tag_t iot; 53 1.10 sekiya bus_space_handle_t ioh; 54 1.10 sekiya 55 1.19 sekiya int eisa_present; 56 1.1 thorpej }; 57 1.1 thorpej 58 1.33 chs static int imc_match(device_t, cfdata_t, void *); 59 1.33 chs static void imc_attach(device_t, device_t, void *); 60 1.1 thorpej static int imc_print(void *, const char *); 61 1.18 rumble static void imc_bus_reset(void); 62 1.30 matt static void imc_bus_error(vaddr_t, uint32_t, uint32_t); 63 1.18 rumble static void imc_watchdog_reset(void); 64 1.18 rumble static void imc_watchdog_disable(void); 65 1.18 rumble static void imc_watchdog_enable(void); 66 1.1 thorpej 67 1.33 chs CFATTACH_DECL_NEW(imc, sizeof(struct imc_softc), 68 1.7 thorpej imc_match, imc_attach, NULL, NULL); 69 1.1 thorpej 70 1.1 thorpej struct imc_attach_args { 71 1.1 thorpej const char* iaa_name; 72 1.1 thorpej 73 1.1 thorpej bus_space_tag_t iaa_st; 74 1.1 thorpej bus_space_handle_t iaa_sh; 75 1.1 thorpej 76 1.1 thorpej /* ? */ 77 1.4 simonb long iaa_offset; 78 1.4 simonb int iaa_intr; 79 1.1 thorpej #if 0 80 1.4 simonb int iaa_stride; 81 1.1 thorpej #endif 82 1.1 thorpej }; 83 1.1 thorpej 84 1.26 rumble int imc_gio64_arb_config(int, uint32_t); 85 1.26 rumble 86 1.10 sekiya struct imc_softc isc; 87 1.10 sekiya 88 1.1 thorpej static int 89 1.33 chs imc_match(device_t parent, cfdata_t match, void *aux) 90 1.1 thorpej { 91 1.1 thorpej 92 1.29 tsutsui if ((mach_type == MACH_SGI_IP22) || (mach_type == MACH_SGI_IP20)) 93 1.29 tsutsui return 1; 94 1.2 thorpej 95 1.29 tsutsui return 0; 96 1.1 thorpej } 97 1.1 thorpej 98 1.1 thorpej static void 99 1.33 chs imc_attach(device_t parent, device_t self, void *aux) 100 1.1 thorpej { 101 1.29 tsutsui uint32_t reg; 102 1.1 thorpej struct imc_attach_args iaa; 103 1.10 sekiya struct mainbus_attach_args *ma = aux; 104 1.29 tsutsui uint32_t sysid; 105 1.10 sekiya 106 1.34 macallan isc.iot = normal_memt; 107 1.34 macallan if (bus_space_map(isc.iot, ma->ma_addr, 0x100, 108 1.24 tsutsui BUS_SPACE_MAP_LINEAR, &isc.ioh)) 109 1.35 macallan panic("imc_attach: could not map registers\n"); 110 1.10 sekiya 111 1.12 sekiya platform.bus_reset = imc_bus_reset; 112 1.14 sekiya platform.watchdog_reset = imc_watchdog_reset; 113 1.14 sekiya platform.watchdog_disable = imc_watchdog_disable; 114 1.14 sekiya platform.watchdog_enable = imc_watchdog_enable; 115 1.12 sekiya 116 1.10 sekiya sysid = bus_space_read_4(isc.iot, isc.ioh, IMC_SYSID); 117 1.1 thorpej 118 1.23 sekiya /* EISA exists on IP22 only */ 119 1.23 sekiya if (mach_subtype == MACH_SGI_IP22_FULLHOUSE) 120 1.23 sekiya isc.eisa_present = (sysid & IMC_SYSID_HAVEISA); 121 1.23 sekiya else 122 1.19 sekiya isc.eisa_present = 0; 123 1.1 thorpej 124 1.16 sekiya printf(": revision %d", (sysid & IMC_SYSID_REVMASK)); 125 1.1 thorpej 126 1.10 sekiya if (isc.eisa_present) 127 1.4 simonb printf(", EISA bus present"); 128 1.1 thorpej 129 1.1 thorpej printf("\n"); 130 1.1 thorpej 131 1.1 thorpej /* Clear CPU/GIO error status registers to clear any leftover bits. */ 132 1.17 sekiya imc_bus_reset(); 133 1.17 sekiya 134 1.17 sekiya /* Hook the bus error handler into the ISR */ 135 1.17 sekiya platform.intr4 = imc_bus_error; 136 1.1 thorpej 137 1.4 simonb /* 138 1.3 rafal * Enable parity reporting on GIO/main memory transactions. 139 1.3 rafal * Disable parity checking on CPU bus transactions (as turning 140 1.3 rafal * it on seems to cause spurious bus errors), but enable parity 141 1.4 simonb * checking on CPU reads from main memory (note that this bit 142 1.3 rafal * has the opposite sense... Turning it on turns the checks off!). 143 1.3 rafal * Finally, turn on interrupt writes to the CPU from the MC. 144 1.1 thorpej */ 145 1.10 sekiya reg = bus_space_read_4(isc.iot, isc.ioh, IMC_CPUCTRL0); 146 1.3 rafal reg &= ~IMC_CPUCTRL0_NCHKMEMPAR; 147 1.3 rafal reg |= (IMC_CPUCTRL0_GPR | IMC_CPUCTRL0_MPR | IMC_CPUCTRL0_INTENA); 148 1.10 sekiya bus_space_write_4(isc.iot, isc.ioh, IMC_CPUCTRL0, reg); 149 1.4 simonb 150 1.1 thorpej /* Setup the MC write buffer depth */ 151 1.10 sekiya reg = bus_space_read_4(isc.iot, isc.ioh, IMC_CPUCTRL1); 152 1.3 rafal reg = (reg & ~IMC_CPUCTRL1_MCHWMSK) | 13; 153 1.20 rumble 154 1.20 rumble /* 155 1.20 rumble * Force endianness on the onboard HPC and both slots. 156 1.20 rumble * This should be safe for Fullhouse, but leave it conditional 157 1.20 rumble * for now. 158 1.20 rumble */ 159 1.20 rumble if (mach_type == MACH_SGI_IP20 || (mach_type == MACH_SGI_IP22 && 160 1.27 rumble mach_subtype == MACH_SGI_IP22_GUINNESS)) { 161 1.20 rumble reg |= IMC_CPUCTRL1_HPCFX; 162 1.20 rumble reg |= IMC_CPUCTRL1_EXP0FX; 163 1.20 rumble reg |= IMC_CPUCTRL1_EXP1FX; 164 1.20 rumble reg &= ~IMC_CPUCTRL1_HPCLITTLE; 165 1.20 rumble reg &= ~IMC_CPUCTRL1_EXP0LITTLE; 166 1.20 rumble reg &= ~IMC_CPUCTRL1_EXP1LITTLE; 167 1.20 rumble } 168 1.10 sekiya bus_space_write_4(isc.iot, isc.ioh, IMC_CPUCTRL1, reg); 169 1.10 sekiya 170 1.1 thorpej 171 1.4 simonb /* 172 1.3 rafal * Set GIO64 arbitrator configuration register: 173 1.3 rafal * 174 1.3 rafal * Preserve PROM-set graphics-related bits, as they seem to depend 175 1.4 simonb * on the graphics variant present and I'm not sure how to figure 176 1.3 rafal * that out or 100% sure what the correct settings are for each. 177 1.3 rafal */ 178 1.10 sekiya reg = bus_space_read_4(isc.iot, isc.ioh, IMC_GIO64ARB); 179 1.3 rafal reg &= (IMC_GIO64ARB_GRX64 | IMC_GIO64ARB_GRXRT | IMC_GIO64ARB_GRXMST); 180 1.1 thorpej 181 1.31 wiz /* Rest of settings are machine/board dependent */ 182 1.29 tsutsui if (mach_type == MACH_SGI_IP20) { 183 1.20 rumble reg |= IMC_GIO64ARB_ONEGIO; 184 1.20 rumble reg |= (IMC_GIO64ARB_EXP0RT | IMC_GIO64ARB_EXP1RT); 185 1.20 rumble reg |= (IMC_GIO64ARB_EXP0MST | IMC_GIO64ARB_EXP1MST); 186 1.24 tsutsui reg &= ~(IMC_GIO64ARB_HPC64 | 187 1.24 tsutsui IMC_GIO64ARB_HPCEXP64 | IMC_GIO64ARB_EISA64 | 188 1.24 tsutsui IMC_GIO64ARB_EXP064 | IMC_GIO64ARB_EXP164 | 189 1.24 tsutsui IMC_GIO64ARB_EXP0PIPE | IMC_GIO64ARB_EXP1PIPE); 190 1.29 tsutsui } else { 191 1.20 rumble /* 192 1.20 rumble * GIO64 invariant for all IP22 platforms: one GIO bus, 193 1.20 rumble * HPC1 @ 64 194 1.20 rumble */ 195 1.20 rumble reg |= IMC_GIO64ARB_ONEGIO | IMC_GIO64ARB_HPC64; 196 1.20 rumble 197 1.10 sekiya switch (mach_subtype) { 198 1.27 rumble case MACH_SGI_IP22_GUINNESS: 199 1.20 rumble /* XXX is MST mutually exclusive? */ 200 1.20 rumble reg |= (IMC_GIO64ARB_EXP0RT | IMC_GIO64ARB_EXP1RT); 201 1.20 rumble reg |= (IMC_GIO64ARB_EXP0MST | IMC_GIO64ARB_EXP1MST); 202 1.20 rumble 203 1.10 sekiya /* EISA can bus-master, is 64-bit */ 204 1.10 sekiya reg |= (IMC_GIO64ARB_EISAMST | IMC_GIO64ARB_EISA64); 205 1.10 sekiya break; 206 1.4 simonb 207 1.10 sekiya case MACH_SGI_IP22_FULLHOUSE: 208 1.4 simonb /* 209 1.4 simonb * All Fullhouse boards have a 64-bit HPC2 and pipelined 210 1.4 simonb * EXP0 slot. 211 1.4 simonb */ 212 1.10 sekiya reg |= (IMC_GIO64ARB_HPCEXP64 | IMC_GIO64ARB_EXP0PIPE); 213 1.4 simonb 214 1.10 sekiya if (mach_boardrev < 2) { 215 1.4 simonb /* EXP0 realtime, EXP1 can master */ 216 1.29 tsutsui reg |= (IMC_GIO64ARB_EXP0RT | 217 1.29 tsutsui IMC_GIO64ARB_EXP1MST); 218 1.10 sekiya } else { 219 1.10 sekiya /* EXP1 pipelined as well, EISA masters */ 220 1.29 tsutsui reg |= (IMC_GIO64ARB_EXP1PIPE | 221 1.29 tsutsui IMC_GIO64ARB_EISAMST); 222 1.10 sekiya } 223 1.10 sekiya break; 224 1.4 simonb } 225 1.3 rafal } 226 1.4 simonb 227 1.10 sekiya bus_space_write_4(isc.iot, isc.ioh, IMC_GIO64ARB, reg); 228 1.1 thorpej 229 1.10 sekiya if (isc.eisa_present) { 230 1.1 thorpej #if notyet 231 1.4 simonb memset(&iaa, 0, sizeof(iaa)); 232 1.3 rafal 233 1.36 thorpej config_found(self, &iaa, eisabusprint, 234 1.37 thorpej CFARGS(.iattr = "eisabus")); 235 1.1 thorpej #endif 236 1.1 thorpej } 237 1.1 thorpej 238 1.1 thorpej memset(&iaa, 0, sizeof(iaa)); 239 1.1 thorpej 240 1.36 thorpej config_found(self, &iaa, imc_print, 241 1.37 thorpej CFARGS(.iattr = "giobus")); 242 1.11 sekiya 243 1.14 sekiya imc_watchdog_enable(); 244 1.1 thorpej } 245 1.1 thorpej 246 1.1 thorpej 247 1.1 thorpej static int 248 1.23 sekiya imc_print(void *aux, const char *name) 249 1.1 thorpej { 250 1.29 tsutsui 251 1.1 thorpej if (name) 252 1.23 sekiya aprint_normal("gio at %s", name); 253 1.1 thorpej 254 1.1 thorpej return UNCONF; 255 1.1 thorpej } 256 1.1 thorpej 257 1.18 rumble static void 258 1.10 sekiya imc_bus_reset(void) 259 1.10 sekiya { 260 1.29 tsutsui 261 1.10 sekiya bus_space_write_4(isc.iot, isc.ioh, IMC_CPU_ERRSTAT, 0); 262 1.10 sekiya bus_space_write_4(isc.iot, isc.ioh, IMC_GIO_ERRSTAT, 0); 263 1.10 sekiya } 264 1.11 sekiya 265 1.18 rumble static void 266 1.30 matt imc_bus_error(vaddr_t pc, uint32_t status, uint32_t ipending) 267 1.11 sekiya { 268 1.29 tsutsui 269 1.11 sekiya printf("bus error: cpu_stat %08x addr %08x, gio_stat %08x addr %08x\n", 270 1.11 sekiya bus_space_read_4(isc.iot, isc.ioh, IMC_CPU_ERRSTAT), 271 1.11 sekiya bus_space_read_4(isc.iot, isc.ioh, IMC_CPU_ERRADDR), 272 1.11 sekiya bus_space_read_4(isc.iot, isc.ioh, IMC_GIO_ERRSTAT), 273 1.11 sekiya bus_space_read_4(isc.iot, isc.ioh, IMC_GIO_ERRADDR) ); 274 1.11 sekiya imc_bus_reset(); 275 1.11 sekiya } 276 1.11 sekiya 277 1.18 rumble static void 278 1.14 sekiya imc_watchdog_reset(void) 279 1.11 sekiya { 280 1.29 tsutsui 281 1.11 sekiya bus_space_write_4(isc.iot, isc.ioh, IMC_WDOG, 0); 282 1.11 sekiya } 283 1.18 rumble 284 1.18 rumble static void 285 1.14 sekiya imc_watchdog_disable(void) 286 1.14 sekiya { 287 1.29 tsutsui uint32_t reg; 288 1.14 sekiya 289 1.14 sekiya bus_space_write_4(isc.iot, isc.ioh, IMC_WDOG, 0); 290 1.14 sekiya reg = bus_space_read_4(isc.iot, isc.ioh, IMC_CPUCTRL0); 291 1.15 sekiya reg &= ~(IMC_CPUCTRL0_WDOG); 292 1.24 tsutsui bus_space_write_4(isc.iot, isc.ioh, IMC_CPUCTRL0, reg); 293 1.14 sekiya } 294 1.14 sekiya 295 1.18 rumble static void 296 1.14 sekiya imc_watchdog_enable(void) 297 1.14 sekiya { 298 1.29 tsutsui uint32_t reg; 299 1.14 sekiya 300 1.14 sekiya /* enable watchdog and clear it */ 301 1.14 sekiya reg = bus_space_read_4(isc.iot, isc.ioh, IMC_CPUCTRL0); 302 1.14 sekiya reg |= IMC_CPUCTRL0_WDOG; 303 1.14 sekiya bus_space_write_4(isc.iot, isc.ioh, IMC_CPUCTRL0, reg); 304 1.14 sekiya imc_watchdog_reset(); 305 1.14 sekiya } 306 1.26 rumble 307 1.26 rumble /* intended to be called from gio/gio.c only */ 308 1.26 rumble int 309 1.26 rumble imc_gio64_arb_config(int slot, uint32_t flags) 310 1.26 rumble { 311 1.26 rumble uint32_t reg; 312 1.26 rumble 313 1.26 rumble /* GIO_SLOT_EXP1 is unusable on Fullhouse */ 314 1.26 rumble if (slot == GIO_SLOT_EXP1 && mach_subtype == MACH_SGI_IP22_FULLHOUSE) 315 1.29 tsutsui return EINVAL; 316 1.26 rumble 317 1.26 rumble /* GIO_SLOT_GFX is only usable on Fullhouse */ 318 1.26 rumble if (slot == GIO_SLOT_GFX && mach_subtype != MACH_SGI_IP22_FULLHOUSE) 319 1.29 tsutsui return EINVAL; 320 1.26 rumble 321 1.26 rumble /* GIO_SLOT_GFX is always pipelined */ 322 1.26 rumble if (slot == GIO_SLOT_GFX && (flags & GIO_ARB_NOPIPE)) 323 1.29 tsutsui return EINVAL; 324 1.26 rumble 325 1.26 rumble /* IP20 does not support pipelining (XXX what about Indy?) */ 326 1.26 rumble if (((flags & GIO_ARB_PIPE) || (flags & GIO_ARB_NOPIPE)) && 327 1.26 rumble mach_type == MACH_SGI_IP20) 328 1.29 tsutsui return EINVAL; 329 1.26 rumble 330 1.26 rumble reg = bus_space_read_4(isc.iot, isc.ioh, IMC_GIO64ARB); 331 1.26 rumble 332 1.26 rumble if (flags & GIO_ARB_RT) { 333 1.26 rumble if (slot == GIO_SLOT_EXP0) 334 1.26 rumble reg |= IMC_GIO64ARB_EXP0RT; 335 1.26 rumble else if (slot == GIO_SLOT_EXP1) 336 1.26 rumble reg |= IMC_GIO64ARB_EXP1RT; 337 1.26 rumble else if (slot == GIO_SLOT_GFX) 338 1.26 rumble reg |= IMC_GIO64ARB_GRXRT; 339 1.26 rumble } 340 1.26 rumble 341 1.26 rumble if (flags & GIO_ARB_MST) { 342 1.26 rumble if (slot == GIO_SLOT_EXP0) 343 1.26 rumble reg |= IMC_GIO64ARB_EXP0MST; 344 1.26 rumble else if (slot == GIO_SLOT_EXP1) 345 1.26 rumble reg |= IMC_GIO64ARB_EXP1MST; 346 1.26 rumble else if (slot == GIO_SLOT_GFX) 347 1.26 rumble reg |= IMC_GIO64ARB_GRXMST; 348 1.26 rumble } 349 1.26 rumble 350 1.26 rumble if (flags & GIO_ARB_PIPE) { 351 1.26 rumble if (slot == GIO_SLOT_EXP0) 352 1.26 rumble reg |= IMC_GIO64ARB_EXP0PIPE; 353 1.26 rumble else if (slot == GIO_SLOT_EXP1) 354 1.26 rumble reg |= IMC_GIO64ARB_EXP1PIPE; 355 1.26 rumble } 356 1.26 rumble 357 1.26 rumble if (flags & GIO_ARB_LB) { 358 1.26 rumble if (slot == GIO_SLOT_EXP0) 359 1.26 rumble reg &= ~IMC_GIO64ARB_EXP0RT; 360 1.26 rumble else if (slot == GIO_SLOT_EXP1) 361 1.26 rumble reg &= ~IMC_GIO64ARB_EXP1RT; 362 1.26 rumble else if (slot == GIO_SLOT_GFX) 363 1.26 rumble reg &= ~IMC_GIO64ARB_GRXRT; 364 1.26 rumble } 365 1.26 rumble 366 1.26 rumble if (flags & GIO_ARB_SLV) { 367 1.26 rumble if (slot == GIO_SLOT_EXP0) 368 1.26 rumble reg &= ~IMC_GIO64ARB_EXP0MST; 369 1.26 rumble else if (slot == GIO_SLOT_EXP1) 370 1.26 rumble reg &= ~IMC_GIO64ARB_EXP1MST; 371 1.26 rumble else if (slot == GIO_SLOT_GFX) 372 1.26 rumble reg &= ~IMC_GIO64ARB_GRXMST; 373 1.26 rumble } 374 1.26 rumble 375 1.26 rumble if (flags & GIO_ARB_NOPIPE) { 376 1.26 rumble if (slot == GIO_SLOT_EXP0) 377 1.26 rumble reg &= ~IMC_GIO64ARB_EXP0PIPE; 378 1.26 rumble else if (slot == GIO_SLOT_EXP1) 379 1.26 rumble reg &= ~IMC_GIO64ARB_EXP1PIPE; 380 1.26 rumble } 381 1.26 rumble 382 1.28 rumble if (flags & GIO_ARB_32BIT) { 383 1.28 rumble if (slot == GIO_SLOT_EXP0) 384 1.28 rumble reg &= ~IMC_GIO64ARB_EXP064; 385 1.28 rumble else if (slot == GIO_SLOT_EXP1) 386 1.28 rumble reg &= ~IMC_GIO64ARB_EXP164; 387 1.28 rumble } 388 1.28 rumble 389 1.28 rumble if (flags & GIO_ARB_64BIT) { 390 1.28 rumble if (slot == GIO_SLOT_EXP0) 391 1.28 rumble reg |= IMC_GIO64ARB_EXP064; 392 1.28 rumble else if (slot == GIO_SLOT_EXP1) 393 1.28 rumble reg |= IMC_GIO64ARB_EXP164; 394 1.28 rumble } 395 1.28 rumble 396 1.28 rumble if (flags & GIO_ARB_HPC2_32BIT) 397 1.28 rumble reg &= ~IMC_GIO64ARB_HPCEXP64; 398 1.28 rumble 399 1.28 rumble if (flags & GIO_ARB_HPC2_64BIT) 400 1.28 rumble reg |= IMC_GIO64ARB_HPCEXP64; 401 1.28 rumble 402 1.26 rumble bus_space_write_4(isc.iot, isc.ioh, IMC_GIO64ARB, reg); 403 1.26 rumble 404 1.29 tsutsui return 0; 405 1.26 rumble } 406 1.26 rumble 407 1.26 rumble /* 408 1.26 rumble * According to chapter 19 of the "IRIX Device Driver Programmer's Guide", 409 1.26 rumble * some GIO devices, which do not drive all data lines, may cause false 410 1.26 rumble * memory read parity errors on the SysAD bus. The workaround is to disable 411 1.26 rumble * parity checking. 412 1.26 rumble */ 413 1.26 rumble void 414 1.29 tsutsui imc_disable_sysad_parity(void) 415 1.26 rumble { 416 1.26 rumble uint32_t reg; 417 1.26 rumble 418 1.26 rumble if (mach_type != MACH_SGI_IP20 && mach_type != MACH_SGI_IP22) 419 1.26 rumble return; 420 1.26 rumble 421 1.26 rumble reg = bus_space_read_4(isc.iot, isc.ioh, IMC_CPUCTRL0); 422 1.26 rumble reg |= IMC_CPUCTRL0_NCHKMEMPAR; 423 1.26 rumble bus_space_write_4(isc.iot, isc.ioh, IMC_CPUCTRL0, reg); 424 1.26 rumble } 425 1.26 rumble 426 1.26 rumble void 427 1.29 tsutsui imc_enable_sysad_parity(void) 428 1.26 rumble { 429 1.26 rumble uint32_t reg; 430 1.26 rumble 431 1.26 rumble if (mach_type != MACH_SGI_IP20 && mach_type != MACH_SGI_IP22) 432 1.26 rumble return; 433 1.26 rumble 434 1.26 rumble reg = bus_space_read_4(isc.iot, isc.ioh, IMC_CPUCTRL0); 435 1.26 rumble reg &= ~IMC_CPUCTRL0_NCHKMEMPAR; 436 1.26 rumble bus_space_write_4(isc.iot, isc.ioh, IMC_CPUCTRL0, reg); 437 1.26 rumble } 438 1.26 rumble 439 1.26 rumble int 440 1.29 tsutsui imc_is_sysad_parity_enabled(void) 441 1.26 rumble { 442 1.26 rumble uint32_t reg; 443 1.26 rumble 444 1.26 rumble if (mach_type != MACH_SGI_IP20 && mach_type != MACH_SGI_IP22) 445 1.29 tsutsui return 0; 446 1.26 rumble 447 1.26 rumble reg = bus_space_read_4(isc.iot, isc.ioh, IMC_CPUCTRL0); 448 1.26 rumble 449 1.29 tsutsui return reg & IMC_CPUCTRL0_NCHKMEMPAR; 450 1.26 rumble } 451