1 /* $NetBSD: imc.c,v 1.4 2002/03/13 13:12:26 simonb Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Rafal K. Boni 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/param.h> 31 #include <sys/device.h> 32 #include <sys/systm.h> 33 34 #include <machine/cpu.h> 35 #include <machine/locore.h> 36 #include <machine/autoconf.h> 37 #include <machine/bus.h> 38 #include <machine/machtype.h> 39 40 #include <sgimips/dev/imcreg.h> 41 42 #include "locators.h" 43 44 struct imc_softc { 45 struct device sc_dev; 46 47 int eisa_present : 1; 48 }; 49 50 static int imc_match(struct device *, struct cfdata *, void *); 51 static void imc_attach(struct device *, struct device *, void *); 52 static int imc_print(void *, const char *); 53 54 struct cfattach imc_ca = { 55 sizeof(struct imc_softc), imc_match, imc_attach 56 }; 57 58 struct imc_attach_args { 59 const char* iaa_name; 60 61 bus_space_tag_t iaa_st; 62 bus_space_handle_t iaa_sh; 63 64 /* ? */ 65 long iaa_offset; 66 int iaa_intr; 67 #if 0 68 int iaa_stride; 69 #endif 70 }; 71 72 static int 73 imc_match(parent, match, aux) 74 struct device *parent; 75 struct cfdata *match; 76 void *aux; 77 { 78 79 /* 80 * The IMC is an INDY/INDIGO2 thing. 81 */ 82 if (mach_type != MACH_SGI_IP22) 83 return (0); 84 85 /* Make sure it's actually there and readable */ 86 if (badaddr((void*)MIPS_PHYS_TO_KSEG1(IMC_SYSID), sizeof(u_int32_t))) 87 return (0); 88 89 return (1); 90 } 91 92 static void 93 imc_attach(parent, self, aux) 94 struct device *parent; 95 struct device *self; 96 void *aux; 97 { 98 u_int32_t reg; 99 struct imc_attach_args iaa; 100 struct imc_softc *isc = (void *) self; 101 u_int32_t sysid = *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(IMC_SYSID); 102 103 /* EISA present bit is on even on Indys, so don't trust it! */ 104 if (mach_subtype == MACH_SGI_IP22_FULLHOUSE) 105 isc->eisa_present = (sysid & IMC_SYSID_HAVEISA); 106 else 107 isc->eisa_present = 0; 108 109 printf("\nimc0: Revision %d", (sysid & IMC_SYSID_REVMASK)); 110 111 if (isc->eisa_present) 112 printf(", EISA bus present"); 113 114 printf("\n"); 115 116 /* Clear CPU/GIO error status registers to clear any leftover bits. */ 117 *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(IMC_CPU_ERRSTAT) = 0; 118 *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(IMC_GIO_ERRSTAT) = 0; 119 120 /* 121 * Enable parity reporting on GIO/main memory transactions. 122 * Disable parity checking on CPU bus transactions (as turning 123 * it on seems to cause spurious bus errors), but enable parity 124 * checking on CPU reads from main memory (note that this bit 125 * has the opposite sense... Turning it on turns the checks off!). 126 * Finally, turn on interrupt writes to the CPU from the MC. 127 */ 128 reg = *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(IMC_CPUCTRL0); 129 reg &= ~IMC_CPUCTRL0_NCHKMEMPAR; 130 reg |= (IMC_CPUCTRL0_GPR | IMC_CPUCTRL0_MPR | IMC_CPUCTRL0_INTENA); 131 *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(IMC_CPUCTRL0) = reg; 132 133 /* Setup the MC write buffer depth */ 134 reg = *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(IMC_CPUCTRL1); 135 reg = (reg & ~IMC_CPUCTRL1_MCHWMSK) | 13; 136 *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(IMC_CPUCTRL1) = reg; 137 138 /* 139 * Set GIO64 arbitrator configuration register: 140 * 141 * Preserve PROM-set graphics-related bits, as they seem to depend 142 * on the graphics variant present and I'm not sure how to figure 143 * that out or 100% sure what the correct settings are for each. 144 */ 145 reg = *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(IMC_GIO64ARB); 146 reg &= (IMC_GIO64ARB_GRX64 | IMC_GIO64ARB_GRXRT | IMC_GIO64ARB_GRXMST); 147 148 /* GIO64 invariant for all IP22 platforms: one GIO bus, HPC1 @ 64 */ 149 reg |= IMC_GIO64ARB_ONEGIO | IMC_GIO64ARB_HPC64; 150 151 /* Rest of settings are machine/board dependant */ 152 switch (mach_subtype) { 153 case MACH_SGI_IP22_GUINESS: 154 /* EISA can bus-master, is 64-bit */ 155 reg |= (IMC_GIO64ARB_EISAMST | IMC_GIO64ARB_EISA64); 156 break; 157 158 case MACH_SGI_IP22_FULLHOUSE: 159 /* 160 * All Fullhouse boards have a 64-bit HPC2 and pipelined 161 * EXP0 slot. 162 */ 163 reg |= (IMC_GIO64ARB_HPCEXP64 | IMC_GIO64ARB_EXP0PIPE); 164 165 if (mach_boardrev < 2) { 166 /* EXP0 realtime, EXP1 can master */ 167 reg |= (IMC_GIO64ARB_EXP0RT | IMC_GIO64ARB_EXP1MST); 168 } else { 169 /* EXP1 pipelined as well, EISA masters */ 170 reg |= (IMC_GIO64ARB_EXP1PIPE | IMC_GIO64ARB_EISAMST); 171 } 172 break; 173 } 174 175 *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(IMC_GIO64ARB) = reg; 176 177 if (isc->eisa_present) { 178 #if notyet 179 memset(&iaa, 0, sizeof(iaa)); 180 181 iaa.iaa_name = "eisa"; 182 (void)config_found(self, (void*)&iaa, imc_print); 183 #endif 184 } 185 186 memset(&iaa, 0, sizeof(iaa)); 187 188 iaa.iaa_name = "gio"; 189 (void)config_found(self, (void*)&iaa, imc_print); 190 } 191 192 193 static int 194 imc_print(aux, name) 195 void *aux; 196 const char *name; 197 { 198 struct imc_attach_args* iaa = aux; 199 200 if (name) 201 printf("%s at %s", iaa->iaa_name, name); 202 203 return UNCONF; 204 } 205 206