1 /* $OpenBSD: mcpcia.c,v 1.4 2009/03/30 21:43:13 kettenis Exp $ */ 2 /* $NetBSD: mcpcia.c,v 1.20 2007/03/04 05:59:11 christos Exp $ */ 3 4 /*- 5 * Copyright (c) 1999 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 10 * NASA Ames Research Center. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * Copyright (c) 1998 by Matthew Jacob 36 * NASA AMES Research Center. 37 * All rights reserved. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice immediately at the beginning of the file, without modification, 44 * this list of conditions, and the following disclaimer. 45 * 2. Redistributions in binary form must reproduce the above copyright 46 * notice, this list of conditions and the following disclaimer in the 47 * documentation and/or other materials provided with the distribution. 48 * 3. The name of the author may not be used to endorse or promote products 49 * derived from this software without specific prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 54 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 55 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 61 * SUCH DAMAGE. 62 */ 63 64 /* 65 * MCPCIA mcbus to PCI bus adapter 66 * found on AlphaServer 4100 systems. 67 */ 68 69 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 70 #include <sys/param.h> 71 #include <sys/systm.h> 72 #include <sys/device.h> 73 #include <sys/malloc.h> 74 75 #include <machine/autoconf.h> 76 #include <machine/rpb.h> 77 #include <machine/sysarch.h> 78 79 #include <alpha/mcbus/mcbusreg.h> 80 #include <alpha/mcbus/mcbusvar.h> 81 #include <alpha/pci/mcpciareg.h> 82 #include <alpha/pci/mcpciavar.h> 83 #include <alpha/pci/pci_kn300.h> 84 85 #define KV(_addr) ((caddr_t)ALPHA_PHYS_TO_K0SEG((_addr))) 86 #define MCPCIA_SYSBASE(mc) \ 87 ((((unsigned long) (mc)->cc_gid) << MCBUS_GID_SHIFT) | \ 88 (((unsigned long) (mc)->cc_mid) << MCBUS_MID_SHIFT) | \ 89 (MCBUS_IOSPACE)) 90 91 #define MCPCIA_PROBE(mid, gid) \ 92 badaddr((void *)KV(((((unsigned long) gid) << MCBUS_GID_SHIFT) | \ 93 (((unsigned long) mid) << MCBUS_MID_SHIFT) | \ 94 (MCBUS_IOSPACE) | MCPCIA_PCI_BRIDGE | _MCPCIA_PCI_REV)), \ 95 sizeof(u_int32_t)) 96 97 int mcpciamatch (struct device *, void *, void *); 98 void mcpciaattach (struct device *, struct device *, void *); 99 void mcpcia_config_cleanup (void); 100 101 int mcpciaprint (void *, const char *); 102 103 struct cfattach mcpcia_ca = { 104 sizeof(struct mcpcia_softc), mcpciamatch, mcpciaattach 105 }; 106 107 struct cfdriver mcpcia_cd = { 108 NULL, "mcpcia", DV_DULL, 109 }; 110 111 /* 112 * We have one statically-allocated mcpcia_config structure; this is 113 * the one used for the console (which, coincidentally, is the only 114 * MCPCIA with an EISA adapter attached to it). 115 */ 116 struct mcpcia_config mcpcia_console_configuration; 117 118 int 119 mcpciaprint(aux, pnp) 120 void *aux; 121 const char *pnp; 122 { 123 register struct pcibus_attach_args *pba = aux; 124 /* only PCIs can attach to MCPCIA for now */ 125 if (pnp) 126 printf("%s at %s", pba->pba_busname, pnp); 127 printf(" bus %d", pba->pba_bus); 128 return (UNCONF); 129 } 130 131 int 132 mcpciamatch(parent, cf, aux) 133 struct device *parent; 134 void *cf; 135 void *aux; 136 { 137 struct mcbus_dev_attach_args *ma = aux; 138 139 if (ma->ma_type == MCBUS_TYPE_PCI) 140 return (1); 141 142 return (0); 143 } 144 145 void 146 mcpciaattach(parent, self, aux) 147 struct device *parent; 148 struct device *self; 149 void *aux; 150 { 151 static int first = 1; 152 struct mcbus_dev_attach_args *ma = aux; 153 struct mcpcia_softc *mcp = (struct mcpcia_softc *)self; 154 struct mcpcia_config *ccp; 155 struct pcibus_attach_args pba; 156 u_int32_t ctl; 157 158 /* 159 * Make sure this MCPCIA exists... 160 */ 161 if (MCPCIA_PROBE(ma->ma_mid, ma->ma_gid)) { 162 mcp->mcpcia_cc = NULL; 163 printf(" (not present)\n"); 164 return; 165 } 166 printf("\n"); 167 168 /* 169 * Determine if we're the console's MCPCIA. 170 */ 171 if (ma->ma_mid == mcpcia_console_configuration.cc_mid && 172 ma->ma_gid == mcpcia_console_configuration.cc_gid) 173 ccp = &mcpcia_console_configuration; 174 else { 175 ccp = malloc(sizeof(*ccp), M_DEVBUF, M_WAITOK | M_ZERO); 176 177 ccp->cc_mid = ma->ma_mid; 178 ccp->cc_gid = ma->ma_gid; 179 } 180 mcp->mcpcia_cc = ccp; 181 ccp->cc_sc = mcp; 182 183 /* This initializes cc_sysbase so we can do register access. */ 184 mcpcia_init0(ccp, 1); 185 186 ctl = REGVAL(MCPCIA_PCI_REV(ccp)); 187 printf("%s: Horse Revision %d, %s Handed Saddle Revision %d," 188 " CAP Revision %d\n", mcp->mcpcia_dev.dv_xname, HORSE_REV(ctl), 189 (SADDLE_TYPE(ctl) & 1)? "Right": "Left", SADDLE_REV(ctl), 190 CAP_REV(ctl)); 191 192 mcpcia_dma_init(ccp); 193 194 /* 195 * Set up interrupts 196 */ 197 pci_kn300_pickintr(ccp, first); 198 first = 0; 199 200 /* 201 * Attach PCI bus 202 */ 203 bzero(&pba, sizeof(pba)); 204 pba.pba_busname = "pci"; 205 pba.pba_iot = &ccp->cc_iot; 206 pba.pba_memt = &ccp->cc_memt; 207 pba.pba_dmat = 208 alphabus_dma_get_tag(&ccp->cc_dmat_direct, ALPHA_BUS_PCI); 209 pba.pba_pc = &ccp->cc_pc; 210 pba.pba_domain = pci_ndomains++; 211 pba.pba_bus = 0; 212 213 config_found(self, &pba, mcpciaprint); 214 215 /* 216 * Clear any errors that may have occurred during the probe 217 * sequence. 218 */ 219 REGVAL(MCPCIA_CAP_ERR(ccp)) = 0xFFFFFFFF; 220 alpha_mb(); 221 } 222 223 void 224 mcpcia_init() 225 { 226 struct mcpcia_config *ccp = &mcpcia_console_configuration; 227 int i; 228 229 /* 230 * Look for all of the MCPCIAs on the system. One of them 231 * will have an EISA attached to it. This MCPCIA is the 232 * only one that can be used for the console. Once we find 233 * that one, initialize it. 234 */ 235 for (i = 0; i < MCPCIA_PER_MCBUS; i++) { 236 ccp->cc_mid = mcbus_mcpcia_probe_order[i]; 237 /* 238 * XXX If we ever support more than one MCBUS, we'll 239 * XXX have to probe for them, and map them to unit 240 * XXX numbers. 241 */ 242 ccp->cc_gid = MCBUS_GID_FROM_INSTANCE(0); 243 ccp->cc_sysbase = MCPCIA_SYSBASE(ccp); 244 245 if (badaddr((void *)ALPHA_PHYS_TO_K0SEG(MCPCIA_PCI_REV(ccp)), 246 sizeof(u_int32_t))) 247 continue; 248 249 if (EISA_PRESENT(REGVAL(MCPCIA_PCI_REV(ccp)))) { 250 mcpcia_init0(ccp, 0); 251 return; 252 } 253 } 254 255 panic("mcpcia_init: unable to find EISA bus"); 256 } 257 258 void 259 mcpcia_init0(ccp, mallocsafe) 260 struct mcpcia_config *ccp; 261 int mallocsafe; 262 { 263 u_int32_t ctl; 264 265 snprintf(ccp->pc_io_ex_name, sizeof ccp->pc_io_ex_name, 266 "mcpcia%d_bus_io", ccp->cc_mid); 267 snprintf(ccp->pc_mem_dex_name, sizeof ccp->pc_mem_dex_name, 268 "mcpciad%d_bus_mem", ccp->cc_mid); 269 snprintf(ccp->pc_mem_dex_name, sizeof ccp->pc_mem_sex_name, 270 "mcpcias%d_bus_mem", ccp->cc_mid); 271 272 if (!ccp->cc_initted) { 273 /* don't do these twice since they set up extents */ 274 mcpcia_bus_io_init(&ccp->cc_iot, ccp); 275 mcpcia_bus_mem_init(&ccp->cc_memt, ccp); 276 } 277 ccp->cc_mallocsafe = mallocsafe; 278 279 mcpcia_pci_init(&ccp->cc_pc, ccp); 280 281 /* 282 * Establish a precalculated base for convenience's sake. 283 */ 284 ccp->cc_sysbase = MCPCIA_SYSBASE(ccp); 285 286 /* 287 * Disable interrupts and clear errors prior to probing 288 */ 289 REGVAL(MCPCIA_INT_MASK0(ccp)) = 0; 290 REGVAL(MCPCIA_INT_MASK1(ccp)) = 0; 291 REGVAL(MCPCIA_CAP_ERR(ccp)) = 0xFFFFFFFF; 292 alpha_mb(); 293 294 if (ccp == &mcpcia_console_configuration) { 295 /* 296 * Use this opportunity to also find out the MID and CPU 297 * type of the currently running CPU (that's us, billybob....) 298 */ 299 ctl = REGVAL(MCPCIA_WHOAMI(ccp)); 300 mcbus_primary.mcbus_cpu_mid = MCBUS_CPU_MID(ctl); 301 if ((MCBUS_CPU_INFO(ctl) & CPU_Fill_Err) == 0 && 302 mcbus_primary.mcbus_valid == 0) { 303 mcbus_primary.mcbus_bcache = 304 MCBUS_CPU_INFO(ctl) & CPU_BCacheMask; 305 mcbus_primary.mcbus_valid = 1; 306 } 307 alpha_mb(); 308 } 309 310 alpha_pci_chipset = &ccp->cc_pc; 311 alpha_pci_chipset->pc_name = "mcpcia"; 312 alpha_pci_chipset->pc_hae_mask = 0; 313 alpha_pci_chipset->pc_dense = MCPCIA_PCI_DENSE; 314 315 ccp->cc_initted = 1; 316 } 317 318 void 319 mcpcia_config_cleanup() 320 { 321 volatile u_int32_t ctl; 322 struct mcpcia_softc *mcp; 323 struct mcpcia_config *ccp; 324 int i; 325 extern struct cfdriver mcpcia_cd; 326 327 /* 328 * Turn on Hard, Soft error interrupts. Maybe i2c too. 329 */ 330 for (i = 0; i < mcpcia_cd.cd_ndevs; i++) { 331 if ((mcp = mcpcia_cd.cd_devs[i]) == NULL) 332 continue; 333 334 ccp = mcp->mcpcia_cc; 335 if (ccp == NULL) 336 continue; 337 338 ctl = REGVAL(MCPCIA_INT_MASK0(ccp)); 339 ctl |= MCPCIA_GEN_IENABL; 340 REGVAL(MCPCIA_INT_MASK0(ccp)) = ctl; 341 alpha_mb(); 342 343 /* force stall while write completes */ 344 ctl = REGVAL(MCPCIA_INT_MASK0(ccp)); 345 } 346 } 347