1 1.43 thorpej /* $NetBSD: dwlpx.c,v 1.43 2021/08/07 16:18:41 thorpej Exp $ */ 2 1.1 cgd 3 1.1 cgd /* 4 1.2 cgd * Copyright (c) 1997 by Matthew Jacob 5 1.1 cgd * NASA AMES Research Center. 6 1.1 cgd * All rights reserved. 7 1.1 cgd * 8 1.1 cgd * Redistribution and use in source and binary forms, with or without 9 1.1 cgd * modification, are permitted provided that the following conditions 10 1.1 cgd * are met: 11 1.1 cgd * 1. Redistributions of source code must retain the above copyright 12 1.1 cgd * notice immediately at the beginning of the file, without modification, 13 1.1 cgd * this list of conditions, and the following disclaimer. 14 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 cgd * notice, this list of conditions and the following disclaimer in the 16 1.1 cgd * documentation and/or other materials provided with the distribution. 17 1.1 cgd * 3. The name of the author may not be used to endorse or promote products 18 1.1 cgd * derived from this software without specific prior written permission. 19 1.1 cgd * 20 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 24 1.1 cgd * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 1.1 cgd * SUCH DAMAGE. 31 1.1 cgd */ 32 1.3 cgd 33 1.4 cgd #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 34 1.4 cgd 35 1.43 thorpej __KERNEL_RCSID(0, "$NetBSD: dwlpx.c,v 1.43 2021/08/07 16:18:41 thorpej Exp $"); 36 1.1 cgd 37 1.1 cgd #include <sys/param.h> 38 1.1 cgd #include <sys/systm.h> 39 1.1 cgd #include <sys/kernel.h> 40 1.1 cgd #include <sys/device.h> 41 1.39 thorpej #include <sys/cpu.h> 42 1.15 thorpej 43 1.1 cgd #include <machine/autoconf.h> 44 1.15 thorpej 45 1.1 cgd #include <dev/pci/pcireg.h> 46 1.1 cgd #include <dev/pci/pcivar.h> 47 1.15 thorpej 48 1.1 cgd #include <alpha/tlsb/tlsbreg.h> 49 1.1 cgd #include <alpha/tlsb/kftxxvar.h> 50 1.1 cgd #include <alpha/tlsb/kftxxreg.h> 51 1.1 cgd #include <alpha/pci/dwlpxreg.h> 52 1.1 cgd #include <alpha/pci/dwlpxvar.h> 53 1.1 cgd 54 1.32 christos #define KV(_addr) ((void *)ALPHA_PHYS_TO_K0SEG((_addr))) 55 1.14 mjacob #define DWLPX_SYSBASE(sc) \ 56 1.14 mjacob ((((unsigned long)((sc)->dwlpx_node - 4)) << 36) | \ 57 1.14 mjacob (((unsigned long) (sc)->dwlpx_hosenum) << 34) | \ 58 1.14 mjacob (1LL << 39)) 59 1.30 ragge #define DWLPX_SYSBASE1(node, hosenum) \ 60 1.30 ragge ((((unsigned long)(node - 4)) << 36) | \ 61 1.30 ragge (((unsigned long) hosenum) << 34) | \ 62 1.30 ragge (1LL << 39)) 63 1.14 mjacob 64 1.1 cgd 65 1.37 matt static int dwlpxmatch(device_t, cfdata_t, void *); 66 1.37 matt static void dwlpxattach(device_t, device_t, void *); 67 1.37 matt 68 1.37 matt CFATTACH_DECL_NEW(dwlpx, sizeof(struct dwlpx_softc), 69 1.26 thorpej dwlpxmatch, dwlpxattach, NULL, NULL); 70 1.1 cgd 71 1.13 thorpej extern struct cfdriver dwlpx_cd; 72 1.1 cgd 73 1.23 thorpej void dwlpx_errintr(void *, u_long vec); 74 1.1 cgd 75 1.1 cgd static int 76 1.37 matt dwlpxmatch(device_t parent, cfdata_t cf, void *aux) 77 1.1 cgd { 78 1.1 cgd struct kft_dev_attach_args *ka = aux; 79 1.30 ragge unsigned long ls; 80 1.38 matt uint32_t ctl; 81 1.1 cgd 82 1.1 cgd if (strcmp(ka->ka_name, dwlpx_cd.cd_name) != 0) 83 1.1 cgd return (0); 84 1.30 ragge 85 1.30 ragge ls = DWLPX_SYSBASE1(ka->ka_node, ka->ka_hosenum); 86 1.30 ragge 87 1.30 ragge /* 88 1.30 ragge * Probe the first HPC to make sure this really is a dwlpx and 89 1.30 ragge * nothing else. 90 1.38 matt */ 91 1.30 ragge if (badaddr(KV(PCIA_CTL(1) + ls), sizeof (ctl)) != 0) { 92 1.30 ragge /* 93 1.30 ragge * If we are here something went wrong. One reason 94 1.30 ragge * could be that this is a dwlma and not a dwlpx. 95 1.30 ragge * 96 1.30 ragge * We can not clear potential illegal CSR errors here 97 1.38 matt * since it is unknown hardware. 98 1.30 ragge */ 99 1.30 ragge return (0); 100 1.30 ragge } 101 1.30 ragge 102 1.1 cgd return (1); 103 1.1 cgd } 104 1.1 cgd 105 1.1 cgd static void 106 1.37 matt dwlpxattach(device_t parent, device_t self, void *aux) 107 1.1 cgd { 108 1.37 matt struct dwlpx_softc *sc = device_private(self); 109 1.8 thorpej struct dwlpx_config *ccp = &sc->dwlpx_cc; 110 1.1 cgd struct kft_dev_attach_args *ka = aux; 111 1.1 cgd struct pcibus_attach_args pba; 112 1.38 matt uint32_t pcia_present; 113 1.1 cgd 114 1.37 matt sc->dwlpx_dev = self; 115 1.1 cgd sc->dwlpx_node = ka->ka_node; 116 1.1 cgd sc->dwlpx_dtype = ka->ka_dtype; 117 1.1 cgd sc->dwlpx_hosenum = ka->ka_hosenum; 118 1.23 thorpej 119 1.1 cgd dwlpx_init(sc); 120 1.16 thorpej dwlpx_dma_init(ccp); 121 1.8 thorpej 122 1.8 thorpej pcia_present = REGVAL(PCIA_PRESENT + ccp->cc_sysbase); 123 1.37 matt aprint_normal(": PCIA rev. %d, STD I/O %spresent, %dK S/G entries\n", 124 1.14 mjacob (pcia_present >> PCIA_PRESENT_REVSHIFT) & PCIA_PRESENT_REVMASK, 125 1.14 mjacob (pcia_present & PCIA_PRESENT_STDIO) == 0 ? "not " : "", 126 1.17 thorpej sc->dwlpx_sgmapsz == DWLPX_SG128K ? 128 : 32); 127 1.8 thorpej 128 1.17 thorpej #if 0 129 1.8 thorpej { 130 1.8 thorpej int hpc, slot, slotval; 131 1.8 thorpej const char *str; 132 1.8 thorpej for (hpc = 0; hpc < sc->dwlpx_nhpc; hpc++) { 133 1.8 thorpej for (slot = 0; slot < 4; slot++) { 134 1.8 thorpej slotval = (pcia_present >> 135 1.8 thorpej PCIA_PRESENT_SLOTSHIFT(hpc, slot)) & 136 1.8 thorpej PCIA_PRESENT_SLOT_MASK; 137 1.8 thorpej if (slotval == PCIA_PRESENT_SLOT_NONE) 138 1.8 thorpej continue; 139 1.8 thorpej switch (slotval) { 140 1.8 thorpej case PCIA_PRESENT_SLOT_25W: 141 1.8 thorpej str = "25"; 142 1.8 thorpej break; 143 1.8 thorpej case PCIA_PRESENT_SLOT_15W: 144 1.8 thorpej str = "15"; 145 1.8 thorpej break; 146 1.8 thorpej case PCIA_PRESENT_SLOW_7W: 147 1.8 thorpej default: /* XXX gcc */ 148 1.8 thorpej str = "7.5"; 149 1.8 thorpej break; 150 1.8 thorpej } 151 1.37 matt aprint_normal_dev(sc->dwlpx_dev, 152 1.37 matt "hpc %d slot %d: %s watt module\n", 153 1.37 matt hpc, slot, str); 154 1.8 thorpej } 155 1.8 thorpej } 156 1.8 thorpej } 157 1.8 thorpej #endif 158 1.8 thorpej 159 1.41 thorpej /* 160 1.41 thorpej * Set up interrupts 161 1.41 thorpej */ 162 1.42 thorpej alpha_pci_intr_init(&sc->dwlpx_cc, &sc->dwlpx_cc.cc_iot, 163 1.42 thorpej &sc->dwlpx_cc.cc_memt, &sc->dwlpx_cc.cc_pc); 164 1.1 cgd 165 1.1 cgd /* 166 1.1 cgd * Attach PCI bus 167 1.1 cgd */ 168 1.11 thorpej pba.pba_iot = &sc->dwlpx_cc.cc_iot; 169 1.11 thorpej pba.pba_memt = &sc->dwlpx_cc.cc_memt; 170 1.6 thorpej pba.pba_dmat = /* start with direct, may change... */ 171 1.6 thorpej alphabus_dma_get_tag(&sc->dwlpx_cc.cc_dmat_direct, ALPHA_BUS_PCI); 172 1.28 fvdl pba.pba_dmat64 = NULL; 173 1.1 cgd pba.pba_pc = &sc->dwlpx_cc.cc_pc; 174 1.1 cgd pba.pba_bus = 0; 175 1.24 thorpej pba.pba_bridgetag = NULL; 176 1.36 dyoung pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY | 177 1.19 thorpej PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY; 178 1.43 thorpej config_found(self, &pba, pcibusprint, CFARGS_NONE); 179 1.1 cgd } 180 1.1 cgd 181 1.1 cgd void 182 1.34 dsl dwlpx_init(struct dwlpx_softc *sc) 183 1.1 cgd { 184 1.38 matt uint32_t ctl; 185 1.1 cgd struct dwlpx_config *ccp = &sc->dwlpx_cc; 186 1.23 thorpej unsigned long vec, ls = DWLPX_SYSBASE(sc); 187 1.23 thorpej int i; 188 1.1 cgd 189 1.1 cgd if (ccp->cc_initted == 0) { 190 1.14 mjacob /* 191 1.14 mjacob * On reads, you get a fault if you read a nonexisted HPC. 192 1.14 mjacob * We know the internal KFTIA hose (hose 0) has only 2 HPCs, 193 1.14 mjacob * but we can also actually probe for HPCs. 194 1.14 mjacob * Assume at least one. 195 1.14 mjacob */ 196 1.14 mjacob for (sc->dwlpx_nhpc = 1; sc->dwlpx_nhpc < NHPC; 197 1.14 mjacob sc->dwlpx_nhpc++) { 198 1.14 mjacob if (badaddr(KV(PCIA_CTL(sc->dwlpx_nhpc) + ls), 199 1.14 mjacob sizeof (ctl)) != 0) { 200 1.14 mjacob break; 201 1.14 mjacob } 202 1.14 mjacob } 203 1.14 mjacob if (sc->dwlpx_nhpc != NHPC) { 204 1.14 mjacob /* clear (potential) Illegal CSR Address Error */ 205 1.14 mjacob REGVAL(PCIA_ERR(0) + DWLPX_SYSBASE(sc)) = 206 1.14 mjacob PCIA_ERR_ALLERR; 207 1.14 mjacob } 208 1.14 mjacob 209 1.10 thorpej dwlpx_bus_io_init(&ccp->cc_iot, ccp); 210 1.10 thorpej dwlpx_bus_mem_init(&ccp->cc_memt, ccp); 211 1.1 cgd } 212 1.1 cgd dwlpx_pci_init(&ccp->cc_pc, ccp); 213 1.1 cgd ccp->cc_sc = sc; 214 1.1 cgd 215 1.1 cgd /* 216 1.1 cgd * Establish a precalculated base for convenience's sake. 217 1.1 cgd */ 218 1.14 mjacob ccp->cc_sysbase = ls; 219 1.1 cgd 220 1.1 cgd /* 221 1.14 mjacob * If there are only 2 HPCs, then the 'present' register is not 222 1.14 mjacob * implemented, so there will only ever be 32K SG entries. Otherwise 223 1.14 mjacob * any revision greater than zero will have 128K entries. 224 1.14 mjacob */ 225 1.14 mjacob ctl = REGVAL(PCIA_PRESENT + ccp->cc_sysbase); 226 1.14 mjacob if (sc->dwlpx_nhpc == 2) { 227 1.14 mjacob sc->dwlpx_sgmapsz = DWLPX_SG32K; 228 1.17 thorpej #if 0 229 1.14 mjacob /* 230 1.14 mjacob * As of 2/25/98- When I enable SG128K, and then have to flip 231 1.14 mjacob * TBIT below, I get bad SGRAM errors. We'll fix this later 232 1.14 mjacob * if this gets important. 233 1.14 mjacob */ 234 1.14 mjacob } else if ((ctl >> PCIA_PRESENT_REVSHIFT) & PCIA_PRESENT_REVMASK) { 235 1.14 mjacob sc->dwlpx_sgmapsz = DWLPX_SG128K; 236 1.14 mjacob #endif 237 1.14 mjacob } else { 238 1.14 mjacob sc->dwlpx_sgmapsz = DWLPX_SG32K; 239 1.14 mjacob } 240 1.14 mjacob 241 1.14 mjacob /* 242 1.1 cgd * Set up interrupt stuff for this DWLPX. 243 1.1 cgd * 244 1.1 cgd * Note that all PCI interrupt pins are disabled at this time. 245 1.1 cgd * 246 1.1 cgd * Do this even for all HPCs- even for the nonexistent 247 1.1 cgd * one on hose zero of a KFTIA. 248 1.1 cgd */ 249 1.39 thorpej mutex_enter(&cpu_lock); 250 1.23 thorpej vec = scb_alloc(dwlpx_errintr, sc); 251 1.39 thorpej mutex_exit(&cpu_lock); 252 1.23 thorpej if (vec == SCB_ALLOC_FAILED) 253 1.23 thorpej panic("%s: unable to allocate error vector", 254 1.37 matt device_xname(sc->dwlpx_dev)); 255 1.37 matt aprint_normal_dev(sc->dwlpx_dev, "error interrupt at vector 0x%lx\n", 256 1.37 matt vec); 257 1.1 cgd for (i = 0; i < NHPC; i++) { 258 1.1 cgd REGVAL(PCIA_IMASK(i) + ccp->cc_sysbase) = DWLPX_IMASK_DFLT; 259 1.23 thorpej REGVAL(PCIA_ERRVEC(i) + ccp->cc_sysbase) = vec; 260 1.1 cgd } 261 1.23 thorpej 262 1.1 cgd /* 263 1.1 cgd * Establish HAE values, as well as make sure of sanity elsewhere. 264 1.1 cgd */ 265 1.1 cgd for (i = 0; i < sc->dwlpx_nhpc; i++) { 266 1.14 mjacob ctl = REGVAL(PCIA_CTL(i) + ccp->cc_sysbase); 267 1.1 cgd ctl &= 0x0fffffff; 268 1.9 mjacob ctl &= ~(PCIA_CTL_MHAE(0x1f) | PCIA_CTL_IHAE(0x1f)); 269 1.9 mjacob /* 270 1.9 mjacob * I originally also had it or'ing in 3, which makes no sense. 271 1.9 mjacob */ 272 1.9 mjacob 273 1.9 mjacob ctl |= PCIA_CTL_RMMENA | PCIA_CTL_RMMARB; 274 1.9 mjacob 275 1.9 mjacob /* 276 1.9 mjacob * Only valid if we're attached to a KFTIA or a KTHA. 277 1.9 mjacob */ 278 1.9 mjacob ctl |= PCIA_CTL_3UP; 279 1.9 mjacob 280 1.9 mjacob ctl |= PCIA_CTL_CUTENA; 281 1.9 mjacob 282 1.14 mjacob /* 283 1.14 mjacob * Fit in appropriate S/G Map Ram size. 284 1.14 mjacob */ 285 1.14 mjacob if (sc->dwlpx_sgmapsz == DWLPX_SG32K) 286 1.14 mjacob ctl |= PCIA_CTL_SG32K; 287 1.14 mjacob else if (sc->dwlpx_sgmapsz == DWLPX_SG128K) 288 1.14 mjacob ctl |= PCIA_CTL_SG128K; 289 1.14 mjacob else 290 1.14 mjacob ctl |= PCIA_CTL_SG32K; 291 1.14 mjacob 292 1.1 cgd REGVAL(PCIA_CTL(i) + ccp->cc_sysbase) = ctl; 293 1.1 cgd } 294 1.14 mjacob /* 295 1.14 mjacob * Enable TBIT if required 296 1.14 mjacob */ 297 1.14 mjacob if (sc->dwlpx_sgmapsz == DWLPX_SG128K) 298 1.14 mjacob REGVAL(PCIA_TBIT + ccp->cc_sysbase) = 1; 299 1.14 mjacob alpha_mb(); 300 1.1 cgd ccp->cc_initted = 1; 301 1.14 mjacob } 302 1.14 mjacob 303 1.14 mjacob void 304 1.34 dsl dwlpx_errintr(void *arg, unsigned long vec) 305 1.14 mjacob { 306 1.23 thorpej struct dwlpx_softc *sc = arg; 307 1.23 thorpej struct dwlpx_config *ccp = &sc->dwlpx_cc; 308 1.23 thorpej int i; 309 1.14 mjacob struct { 310 1.38 matt uint32_t err; 311 1.38 matt uint32_t addr; 312 1.14 mjacob } hpcs[NHPC]; 313 1.14 mjacob 314 1.14 mjacob for (i = 0; i < sc->dwlpx_nhpc; i++) { 315 1.14 mjacob hpcs[i].err = REGVAL(PCIA_ERR(i) + ccp->cc_sysbase); 316 1.14 mjacob hpcs[i].addr = REGVAL(PCIA_FADR(i) + ccp->cc_sysbase); 317 1.14 mjacob } 318 1.37 matt aprint_error_dev(sc->dwlpx_dev, "node %d hose %d error interrupt\n", 319 1.37 matt sc->dwlpx_node, sc->dwlpx_hosenum); 320 1.14 mjacob 321 1.14 mjacob for (i = 0; i < sc->dwlpx_nhpc; i++) { 322 1.14 mjacob if ((hpcs[i].err & PCIA_ERR_ERROR) == 0) 323 1.14 mjacob continue; 324 1.37 matt aprint_error("\tHPC %d: ERR=0x%08x; DMA %s Memory, " 325 1.14 mjacob "Failing Address 0x%x\n", 326 1.14 mjacob i, hpcs[i].err, hpcs[i].addr & 0x1? "write to" : 327 1.14 mjacob "read from", hpcs[i].addr & ~3); 328 1.14 mjacob if (hpcs[i].err & PCIA_ERR_SERR_L) 329 1.37 matt aprint_error("\t PCI device asserted SERR_L\n"); 330 1.14 mjacob if (hpcs[i].err & PCIA_ERR_ILAT) 331 1.37 matt aprint_error("\t Incremental Latency Exceeded\n"); 332 1.14 mjacob if (hpcs[i].err & PCIA_ERR_SGPRTY) 333 1.37 matt aprint_error("\t CPU access of SG RAM Parity Error\n"); 334 1.14 mjacob if (hpcs[i].err & PCIA_ERR_ILLCSR) 335 1.37 matt aprint_error("\t Illegal CSR Address Error\n"); 336 1.14 mjacob if (hpcs[i].err & PCIA_ERR_PCINXM) 337 1.37 matt aprint_error("\t Nonexistent PCI Address Error\n"); 338 1.14 mjacob if (hpcs[i].err & PCIA_ERR_DSCERR) 339 1.37 matt aprint_error("\t PCI Target Disconnect Error\n"); 340 1.14 mjacob if (hpcs[i].err & PCIA_ERR_ABRT) 341 1.37 matt aprint_error("\t PCI Target Abort Error\n"); 342 1.14 mjacob if (hpcs[i].err & PCIA_ERR_WPRTY) 343 1.37 matt aprint_error("\t PCI Write Parity Error\n"); 344 1.14 mjacob if (hpcs[i].err & PCIA_ERR_DPERR) 345 1.37 matt aprint_error("\t PCI Data Parity Error\n"); 346 1.14 mjacob if (hpcs[i].err & PCIA_ERR_APERR) 347 1.37 matt aprint_error("\t PCI Address Parity Error\n"); 348 1.14 mjacob if (hpcs[i].err & PCIA_ERR_DFLT) 349 1.37 matt aprint_error("\t SG Map RAM Invalid Entry Error\n"); 350 1.14 mjacob if (hpcs[i].err & PCIA_ERR_DPRTY) 351 1.37 matt aprint_error("\t DMA access of SG RAM Parity Error\n"); 352 1.14 mjacob if (hpcs[i].err & PCIA_ERR_DRPERR) 353 1.37 matt aprint_error("\t DMA Read Return Parity Error\n"); 354 1.14 mjacob if (hpcs[i].err & PCIA_ERR_MABRT) 355 1.37 matt aprint_error("\t PCI Master Abort Error\n"); 356 1.14 mjacob if (hpcs[i].err & PCIA_ERR_CPRTY) 357 1.37 matt aprint_error("\t CSR Parity Error\n"); 358 1.14 mjacob if (hpcs[i].err & PCIA_ERR_COVR) 359 1.37 matt aprint_error("\t CSR Overrun Error\n"); 360 1.14 mjacob if (hpcs[i].err & PCIA_ERR_MBPERR) 361 1.37 matt aprint_error("\t Mailbox Parity Error\n"); 362 1.14 mjacob if (hpcs[i].err & PCIA_ERR_MBILI) 363 1.37 matt aprint_error("\t Mailbox Illegal Length Error\n"); 364 1.14 mjacob REGVAL(PCIA_ERR(i) + ccp->cc_sysbase) = hpcs[i].err; 365 1.14 mjacob } 366 1.1 cgd } 367