mcpcia.c revision 1.3
1/* $NetBSD: mcpcia.c,v 1.3 1998/06/06 01:33:23 thorpej Exp $ */ 2 3/* 4 * Copyright (c) 1998 by Matthew Jacob 5 * NASA AMES Research Center. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice immediately at the beginning of the file, without modification, 13 * this list of conditions, and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33/* 34 * MCPCIA mcbus to PCI bus adapter 35 * found on AlphaServer 4100 systems. 36 */ 37 38#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 39 40__KERNEL_RCSID(0, "$NetBSD: mcpcia.c,v 1.3 1998/06/06 01:33:23 thorpej Exp $"); 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/device.h> 45#include <sys/malloc.h> 46 47#include <machine/autoconf.h> 48#include <machine/rpb.h> 49#include <machine/pte.h> 50 51#include <alpha/mcbus/mcbusreg.h> 52#include <alpha/mcbus/mcbusvar.h> 53#include <alpha/pci/mcpciareg.h> 54#include <alpha/pci/mcpciavar.h> 55#include <alpha/pci/pci_kn300.h> 56 57struct mcpcia_softc *mcpcias = NULL; 58static struct mcpcia_softc *mcpcia_lt = NULL; 59 60#define KV(_addr) ((caddr_t)ALPHA_PHYS_TO_K0SEG((_addr))) 61#define MCPCIA_SYSBASE(sc) \ 62 ((((unsigned long) (sc)->mcpcia_gid) << MCBUS_GID_SHIFT) | \ 63 (((unsigned long) (sc)->mcpcia_mid) << MCBUS_MID_SHIFT) | \ 64 (MCBUS_IOSPACE)) 65 66static int mcpciamatch __P((struct device *, struct cfdata *, void *)); 67static void mcpciaattach __P((struct device *, struct device *, void *)); 68struct cfattach mcpcia_ca = { 69 sizeof(struct mcpcia_softc), mcpciamatch, mcpciaattach 70}; 71 72static int mcpciaprint __P((void *, const char *)); 73 74static int 75mcpciaprint(aux, pnp) 76 void *aux; 77 const char *pnp; 78{ 79 register struct pcibus_attach_args *pba = aux; 80 /* only PCIs can attach to MCPCIA for now */ 81 if (pnp) 82 printf("%s at %s", pba->pba_busname, pnp); 83 printf(" bus %d", pba->pba_bus); 84 return (UNCONF); 85} 86 87static int 88mcpciamatch(parent, cf, aux) 89 struct device *parent; 90 struct cfdata *cf; 91 void *aux; 92{ 93 struct mcbus_dev_attach_args *ma = aux; 94 if (ma->ma_type == MCBUS_TYPE_PCI) 95 return (1); 96 return (0); 97} 98 99static void 100mcpciaattach(parent, self, aux) 101 struct device *parent; 102 struct device *self; 103 void *aux; 104{ 105 static int first = 1; 106 struct mcbus_dev_attach_args *ma = aux; 107 struct mcpcia_softc *mcp = (struct mcpcia_softc *)self; 108 struct pcibus_attach_args pba; 109 110 mcp->mcpcia_dev = *self; 111 mcp->mcpcia_mid = ma->ma_mid; 112 mcp->mcpcia_gid = ma->ma_gid; 113 114 printf("\n"); 115 116 mcpcia_init(mcp); 117 mcpcia_dma_init(&mcp->mcpcia_cc); 118 119 mcp->mcpcia_next = NULL; 120 if (mcpcia_lt == NULL) { 121 mcpcias = mcp; 122 } else { 123 mcpcia_lt->mcpcia_next = mcp; 124 } 125 mcpcia_lt = mcp; 126 127 /* 128 * Set up interrupts 129 */ 130 pci_kn300_pickintr(&mcp->mcpcia_cc, first); 131#ifdef EVCNT_COUNTERS 132 if (first == 1) { 133 evcnt_attach(self, "intr", kn300_intr_evcnt); 134 first = 0; 135 } 136#else 137 first = 0; 138#endif 139 140 /* 141 * Attach PCI bus 142 */ 143 pba.pba_busname = "pci"; 144 pba.pba_iot = &mcp->mcpcia_cc.cc_iot; 145 pba.pba_memt = &mcp->mcpcia_cc.cc_memt; 146 pba.pba_dmat = /* start with direct, may change... */ 147 alphabus_dma_get_tag(&mcp->mcpcia_cc.cc_dmat_direct, ALPHA_BUS_PCI); 148 pba.pba_pc = &mcp->mcpcia_cc.cc_pc; 149 pba.pba_bus = 0; 150 pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED; 151 config_found(self, &pba, mcpciaprint); 152} 153 154void 155mcpcia_init(mcp) 156 struct mcpcia_softc *mcp; 157{ 158 u_int32_t ctl; 159 struct mcpcia_config *ccp = &mcp->mcpcia_cc; 160 161 if (ccp->cc_initted == 0) { 162 mcpcia_bus_io_init(&ccp->cc_iot, ccp); 163 mcpcia_bus_mem_init(&ccp->cc_memt, ccp); 164 } 165 mcpcia_pci_init(&ccp->cc_pc, ccp); 166 ccp->cc_sc = mcp; 167 168 /* 169 * Establish a precalculated base for convenience's sake. 170 */ 171 ccp->cc_sysbase = MCPCIA_SYSBASE(mcp); 172 173 174 ctl = REGVAL(MCPCIA_PCI_REV(mcp)); 175 printf("%s: Horse Revision %d, %s Handed Saddle Revision %d," 176 " CAP Revision %d\n", mcp->mcpcia_dev.dv_xname, HORSE_REV(ctl), 177 (SADDLE_TYPE(ctl) & 1)? "Right": "Left", SADDLE_REV(ctl), 178 CAP_REV(ctl)); 179 180 /* 181 * Disable interrupts and clear errors prior to probing 182 */ 183 REGVAL(MCPCIA_INT_MASK0(mcp)) = 0; 184 REGVAL(MCPCIA_INT_MASK1(mcp)) = 0; 185 REGVAL(MCPCIA_CAP_ERR(mcp)) = 0xFFFFFFFF; 186 alpha_mb(); 187 188 /* 189 * Clean up any post probe errors (W1TC). 190 */ 191 REGVAL(MCPCIA_CAP_ERR(mcp)) = 0xFFFFFFFF; 192 alpha_mb(); 193 194 /* 195 * Use this opportunity to also find out the MID and CPU 196 * type of the currently running CPU (that's us, billybob....) 197 */ 198 ctl = REGVAL(MCPCIA_WHOAMI(mcp)); 199 mcbus_primary.mcbus_cpu_mid = MCBUS_CPU_MID(ctl); 200 if ((ctl & CPU_Fill_Err) == 0 && mcbus_primary.mcbus_valid == 0) { 201 mcbus_primary.mcbus_bcache = 202 MCBUS_CPU_INFO(ctl) & CPU_BCacheMask; 203 mcbus_primary.mcbus_valid = 1; 204 } 205 alpha_mb(); 206 ccp->cc_initted = 1; 207} 208 209void 210mcpcia_config_cleanup() 211{ 212 volatile u_int32_t ctl; 213 struct mcpcia_softc *mcp; 214 215 /* 216 * Turn on Hard, Soft error interrupts. Maybe i2c too. 217 */ 218 for (mcp = mcpcias; mcp; mcp = mcp->mcpcia_next) { 219 ctl = REGVAL(MCPCIA_INT_MASK0(mcp)); 220 ctl |= MCPCIA_GEN_IENABL; 221 REGVAL(MCPCIA_INT_MASK0(mcp)) = ctl; 222 alpha_mb(); 223 /* force stall while write completes */ 224 ctl = REGVAL(MCPCIA_INT_MASK0(mcp)); 225 } 226} 227