1 /* $NetBSD: pci_mace.c,v 1.21 2016/08/05 20:21:58 macallan Exp $ */ 2 3 /* 4 * Copyright (c) 2001,2003 Christopher Sekiya 5 * Copyright (c) 2000 Soren S. Jorvang 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, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed for the 19 * NetBSD Project. See http://www.NetBSD.org/ for 20 * information about NetBSD. 21 * 4. The name of the author may not be used to endorse or promote products 22 * derived from this software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 __KERNEL_RCSID(0, "$NetBSD: pci_mace.c,v 1.21 2016/08/05 20:21:58 macallan Exp $"); 38 39 #include "opt_pci.h" 40 #include "pci.h" 41 42 #include <sys/param.h> 43 #include <sys/device.h> 44 #include <sys/systm.h> 45 46 #include <machine/cpu.h> 47 #include <machine/locore.h> 48 #include <machine/autoconf.h> 49 #include <machine/vmparam.h> 50 #include <sys/bus.h> 51 #include <machine/machtype.h> 52 53 #include <mips/cache.h> 54 55 #include <dev/pci/pcivar.h> 56 #include <dev/pci/pcireg.h> 57 #include <dev/pci/pcidevs.h> 58 59 #include <sys/extent.h> 60 #include <sys/malloc.h> 61 #include <dev/pci/pciconf.h> 62 63 #include <sgimips/mace/macereg.h> 64 #include <sgimips/mace/macevar.h> 65 66 #include <sgimips/mace/pcireg_mace.h> 67 68 #ifndef __mips_o32 69 #define USE_HIGH_PCI 70 #endif 71 72 73 struct macepci_softc { 74 struct sgimips_pci_chipset sc_pc; 75 }; 76 77 static int macepci_match(device_t, cfdata_t, void *); 78 static void macepci_attach(device_t, device_t, void *); 79 static int macepci_bus_maxdevs(pci_chipset_tag_t, int); 80 static pcireg_t macepci_conf_read(pci_chipset_tag_t, pcitag_t, int); 81 static void macepci_conf_write(pci_chipset_tag_t, pcitag_t, int, pcireg_t); 82 static int macepci_intr_map(const struct pci_attach_args *, 83 pci_intr_handle_t *); 84 static const char * 85 macepci_intr_string(pci_chipset_tag_t, pci_intr_handle_t, 86 char *, size_t); 87 static int macepci_intr(void *); 88 89 CFATTACH_DECL_NEW(macepci, sizeof(struct macepci_softc), 90 macepci_match, macepci_attach, NULL, NULL); 91 92 static void pcimem_bus_mem_init(bus_space_tag_t, void *); 93 static void pciio_bus_mem_init(bus_space_tag_t, void *); 94 static struct mips_bus_space pcimem_mbst; 95 static struct mips_bus_space pciio_mbst; 96 bus_space_tag_t mace_pci_memt = NULL; 97 bus_space_tag_t mace_pci_iot = NULL; 98 99 static int 100 macepci_match(device_t parent, cfdata_t match, void *aux) 101 { 102 103 return (1); 104 } 105 106 static void 107 macepci_attach(device_t parent, device_t self, void *aux) 108 { 109 struct macepci_softc *sc = device_private(self); 110 pci_chipset_tag_t pc = &sc->sc_pc; 111 struct mace_attach_args *maa = aux; 112 struct pcibus_attach_args pba; 113 u_int32_t control; 114 int rev; 115 116 if (bus_space_subregion(maa->maa_st, maa->maa_sh, 117 maa->maa_offset, 0, &pc->ioh) ) 118 panic("macepci_attach: couldn't map"); 119 120 pc->iot = maa->maa_st; 121 122 rev = bus_space_read_4(pc->iot, pc->ioh, MACEPCI_REVISION); 123 printf(": rev %d\n", rev); 124 125 pcimem_bus_mem_init(&pcimem_mbst, NULL); 126 mace_pci_memt = &pcimem_mbst; 127 pciio_bus_mem_init(&pciio_mbst, NULL); 128 mace_pci_iot = &pciio_mbst; 129 130 pc->pc_bus_maxdevs = macepci_bus_maxdevs; 131 pc->pc_conf_read = macepci_conf_read; 132 pc->pc_conf_write = macepci_conf_write; 133 pc->pc_intr_map = macepci_intr_map; 134 pc->pc_intr_string = macepci_intr_string; 135 pc->intr_establish = mace_intr_establish; 136 pc->intr_disestablish = mace_intr_disestablish; 137 138 bus_space_write_4(pc->iot, pc->ioh, MACE_PCI_ERROR_ADDR, 0); 139 bus_space_write_4(pc->iot, pc->ioh, MACE_PCI_ERROR_FLAGS, 0); 140 141 /* Turn on PCI error interrupts */ 142 bus_space_write_4(pc->iot, pc->ioh, MACE_PCI_CONTROL, 143 MACE_PCI_CONTROL_SERR_ENA | 144 MACE_PCI_CONTROL_PARITY_ERR | 145 MACE_PCI_CONTROL_PARK_LIU | 146 MACE_PCI_CONTROL_OVERRUN_INT | 147 MACE_PCI_CONTROL_PARITY_INT | 148 MACE_PCI_CONTROL_SERR_INT | 149 MACE_PCI_CONTROL_IT_INT | 150 MACE_PCI_CONTROL_RE_INT | 151 MACE_PCI_CONTROL_DPED_INT | 152 MACE_PCI_CONTROL_TAR_INT | 153 MACE_PCI_CONTROL_MAR_INT); 154 155 /* 156 * Enable all MACE PCI interrupts. They will be masked by 157 * the CRIME code. 158 */ 159 control = bus_space_read_4(pc->iot, pc->ioh, MACEPCI_CONTROL); 160 control |= CONTROL_INT_MASK; 161 bus_space_write_4(pc->iot, pc->ioh, MACEPCI_CONTROL, control); 162 163 #if NPCI > 0 164 #ifdef USE_HIGH_PCI 165 pc->pc_ioext = extent_create("macepciio", 0x00001000, 0x01ffffff, 166 NULL, 0, EX_NOWAIT); 167 pc->pc_memext = extent_create("macepcimem", 0x80000000, 0xffffffff, 168 NULL, 0, EX_NOWAIT); 169 #else 170 pc->pc_ioext = extent_create("macepciio", 0x00001000, 0x01ffffff, 171 NULL, 0, EX_NOWAIT); 172 /* XXX no idea why we limit ourselves to only half of the 32MB window */ 173 pc->pc_memext = extent_create("macepcimem", 0x80100000, 0x81ffffff, 174 NULL, 0, EX_NOWAIT); 175 #endif /* USE_HIGH_PCI */ 176 pci_configure_bus(pc, pc->pc_ioext, pc->pc_memext, NULL, 0, 177 mips_cache_info.mci_dcache_align); 178 memset(&pba, 0, sizeof pba); 179 pba.pba_iot = mace_pci_iot; 180 pba.pba_memt = mace_pci_memt; 181 pba.pba_dmat = &pci_bus_dma_tag; 182 pba.pba_dmat64 = NULL; 183 pba.pba_bus = 0; 184 pba.pba_bridgetag = NULL; 185 pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY | 186 PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY; 187 pba.pba_pc = pc; 188 189 #ifdef MACEPCI_IO_WAS_BUGGY 190 if (rev == 0) 191 pba.pba_flags &= ~PCI_FLAGS_IO_OKAY; /* Buggy? */ 192 #endif 193 194 cpu_intr_establish(maa->maa_intr, IPL_NONE, macepci_intr, sc); 195 196 config_found_ia(self, "pcibus", &pba, pcibusprint); 197 #endif 198 } 199 200 int 201 macepci_bus_maxdevs(pci_chipset_tag_t pc, int busno) 202 { 203 204 if (busno == 0) 205 return 5; /* 2 on-board SCSI chips, slots 0, 1 and 2 */ 206 else 207 return 0; /* XXX */ 208 } 209 210 pcireg_t 211 macepci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) 212 { 213 pcireg_t data; 214 215 if ((unsigned int)reg >= PCI_CONF_SIZE) 216 return (pcireg_t) -1; 217 218 bus_space_write_4(pc->iot, pc->ioh, MACE_PCI_CONFIG_ADDR, (tag | reg)); 219 data = bus_space_read_4(pc->iot, pc->ioh, MACE_PCI_CONFIG_DATA); 220 bus_space_write_4(pc->iot, pc->ioh, MACE_PCI_CONFIG_ADDR, 0); 221 222 return data; 223 } 224 225 void 226 macepci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) 227 { 228 229 if ((unsigned int)reg >= PCI_CONF_SIZE) 230 return; 231 232 bus_space_write_4(pc->iot, pc->ioh, MACE_PCI_CONFIG_ADDR, (tag | reg)); 233 bus_space_write_4(pc->iot, pc->ioh, MACE_PCI_CONFIG_DATA, data); 234 bus_space_write_4(pc->iot, pc->ioh, MACE_PCI_CONFIG_ADDR, 0); 235 } 236 237 int 238 macepci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp) 239 { 240 pci_chipset_tag_t pc = pa->pa_pc; 241 pcitag_t intrtag = pa->pa_intrtag; 242 int pin = pa->pa_intrpin; 243 int bus, dev, func, start; 244 245 pci_decompose_tag(pc, intrtag, &bus, &dev, &func); 246 247 if (dev < 3 && pin != PCI_INTERRUPT_PIN_A) 248 panic("SCSI0 and SCSI1 must be hardwired!"); 249 250 switch (pin) { 251 default: 252 case PCI_INTERRUPT_PIN_NONE: 253 return -1; 254 255 case PCI_INTERRUPT_PIN_A: 256 /* 257 * Each of SCSI{0,1}, & slots 0 - 2 has dedicated interrupt 258 * for pin A? 259 */ 260 *ihp = dev + 7; 261 return 0; 262 263 case PCI_INTERRUPT_PIN_B: 264 start = 0; 265 break; 266 case PCI_INTERRUPT_PIN_C: 267 start = 1; 268 break; 269 case PCI_INTERRUPT_PIN_D: 270 start = 2; 271 break; 272 } 273 274 /* Pins B,C,D are mapped to PCI_SHARED0 - PCI_SHARED2 interrupts */ 275 *ihp = 13 /* PCI_SHARED0 */ + (start + dev - 3) % 3; 276 return 0; 277 } 278 279 const char * 280 macepci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih, char *buf, 281 size_t len) 282 { 283 snprintf(buf, len, "crime interrupt %d", ih); 284 return buf; 285 } 286 287 288 /* 289 * Handle PCI error interrupts. 290 */ 291 int 292 macepci_intr(void *arg) 293 { 294 struct macepci_softc *sc = (struct macepci_softc *)arg; 295 pci_chipset_tag_t pc = &sc->sc_pc; 296 uint32_t error, address; 297 298 error = bus_space_read_4(pc->iot, pc->ioh, MACE_PCI_ERROR_FLAGS); 299 address = bus_space_read_4(pc->iot, pc->ioh, MACE_PCI_ERROR_ADDR); 300 if (error & 0xffc00000) { 301 if (error & MACE_PERR_MASTER_ABORT) { 302 /* 303 * this seems to be a more-or-less normal error 304 * condition (e.g., "pcictl pci0 list" generates 305 * a _lot_ of these errors, so no message for now 306 * while I figure out if I missed a trick somewhere. 307 */ 308 } 309 310 if (error & MACE_PERR_TARGET_ABORT) { 311 printf("mace: target abort at %x\n", address); 312 } 313 314 if (error & MACE_PERR_DATA_PARITY_ERR) { 315 printf("mace: parity error at %x\n", address); 316 } 317 318 if (error & MACE_PERR_RETRY_ERR) { 319 printf("mace: retry error at %x\n", address); 320 } 321 322 if (error & MACE_PERR_ILLEGAL_CMD) { 323 printf("mace: illegal command at %x\n", address); 324 } 325 326 if (error & MACE_PERR_SYSTEM_ERR) { 327 printf("mace: system error at %x\n", address); 328 } 329 330 if (error & MACE_PERR_INTERRUPT_TEST) { 331 printf("mace: interrupt test at %x\n", address); 332 } 333 334 if (error & MACE_PERR_PARITY_ERR) { 335 printf("mace: parity error at %x\n", address); 336 } 337 338 if (error & MACE_PERR_RSVD) { 339 printf("mace: reserved condition at %x\n", address); 340 } 341 342 if (error & MACE_PERR_OVERRUN) { 343 printf("mace: overrun at %x\n", address); 344 } 345 346 /* clear all */ 347 bus_space_write_4(pc->iot, pc->ioh, 348 MACE_PCI_ERROR_FLAGS, error & ~0xffc00000); 349 } 350 return 0; 351 } 352 353 /* 354 * use the 32MB windows to access PCI space when running a 32bit kernel, 355 * use full views at >4GB in LP64 356 * XXX access to PCI space is endian-twiddled which can't be turned off so we 357 * need to instruct bus_space to un-twiddle them for us so 8bit and 16bit 358 * accesses look little-endian 359 */ 360 #define CHIP pcimem 361 #define CHIP_MEM /* defined */ 362 #define CHIP_WRONG_ENDIAN 363 364 /* 365 * the lower 2GB of PCI space are two views of system memory, with and without 366 * endianness twiddling 367 */ 368 #define CHIP_W1_BUS_START(v) 0x80000000UL 369 #define CHIP_W1_BUS_END(v) 0xffffffffUL 370 #ifdef USE_HIGH_PCI 371 #define CHIP_W1_SYS_START(v) MACE_PCI_HI_MEMORY 372 #define CHIP_W1_SYS_END(v) MACE_PCI_HI_MEMORY + 0x7fffffffUL 373 #else 374 #define CHIP_W1_SYS_START(v) MACE_PCI_LOW_MEMORY 375 #define CHIP_W1_SYS_END(v) MACE_PCI_LOW_MEMORY + 0x01ffffffUL 376 #endif 377 378 #include <mips/mips/bus_space_alignstride_chipdep.c> 379 380 #undef CHIP 381 #undef CHIP_W1_BUS_START 382 #undef CHIP_W1_BUS_END 383 #undef CHIP_W1_SYS_START 384 #undef CHIP_W1_SYS_END 385 386 #define CHIP pciio 387 /* 388 * Even though it's PCI IO space, it's memory mapped so there is no reason not 389 * to allow linear mappings or mmapings into userland. In fact we may need to 390 * do just that in order to use things like PCI graphics cards in X. 391 */ 392 #define CHIP_MEM /* defined */ 393 #define CHIP_W1_BUS_START(v) 0x00000000UL 394 #define CHIP_W1_BUS_END(v) 0xffffffffUL 395 #ifdef USE_HIGH_PCI 396 #define CHIP_W1_SYS_START(v) MACE_PCI_HI_IO 397 #define CHIP_W1_SYS_END(v) MACE_PCI_HI_IO + 0xffffffffUL 398 #else 399 #define CHIP_W1_SYS_START(v) MACE_PCI_LOW_IO 400 #define CHIP_W1_SYS_END(v) MACE_PCI_LOW_IO + 0x01ffffffUL 401 #endif 402 403 #include <mips/mips/bus_space_alignstride_chipdep.c> 404