1 1.20 thorpej /* $NetBSD: pci_gio.c,v 1.20 2023/12/20 15:29:07 thorpej Exp $ */ 2 1.1 rumble 3 1.1 rumble /* 4 1.1 rumble * Copyright (c) 2006 Stephen M. Rumble 5 1.1 rumble * All rights reserved. 6 1.1 rumble * 7 1.1 rumble * Redistribution and use in source and binary forms, with or without 8 1.1 rumble * modification, are permitted provided that the following conditions 9 1.1 rumble * are met: 10 1.1 rumble * 1. Redistributions of source code must retain the above copyright 11 1.1 rumble * notice, this list of conditions and the following disclaimer. 12 1.1 rumble * 2. The name of the author may not be used to endorse or promote products 13 1.1 rumble * derived from this software without specific prior written permission. 14 1.1 rumble * 15 1.1 rumble * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 1.1 rumble * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 1.1 rumble * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 1.1 rumble * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 1.1 rumble * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 1.1 rumble * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 1.1 rumble * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 1.1 rumble * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 1.1 rumble * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 1.1 rumble * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 1.1 rumble */ 26 1.1 rumble 27 1.1 rumble #include <sys/cdefs.h> 28 1.20 thorpej __KERNEL_RCSID(0, "$NetBSD: pci_gio.c,v 1.20 2023/12/20 15:29:07 thorpej Exp $"); 29 1.1 rumble 30 1.1 rumble /* 31 1.1 rumble * Glue for PCI devices that are connected to the GIO bus by various little 32 1.1 rumble * GIO<->PCI ASICs. 33 1.1 rumble * 34 1.1 rumble * We presently support the following boards: 35 1.1 rumble * o Phobos G100/G130/G160 (if_tlp, lxtphy) 36 1.1 rumble * o Set Engineering GFE (if_tl, nsphy) 37 1.1 rumble */ 38 1.1 rumble 39 1.1 rumble #include "opt_pci.h" 40 1.1 rumble #include "pci.h" 41 1.1 rumble 42 1.1 rumble #include <sys/param.h> 43 1.1 rumble #include <sys/systm.h> 44 1.1 rumble #include <sys/device.h> 45 1.1 rumble 46 1.9 dyoung #include <sys/bus.h> 47 1.1 rumble #include <machine/machtype.h> 48 1.1 rumble 49 1.1 rumble #include <sgimips/gio/giovar.h> 50 1.1 rumble #include <sgimips/gio/gioreg.h> 51 1.1 rumble #include <sgimips/gio/giodevs.h> 52 1.1 rumble 53 1.1 rumble #include <sgimips/dev/imcvar.h> 54 1.1 rumble 55 1.1 rumble #include <mips/cache.h> 56 1.1 rumble 57 1.1 rumble #include <dev/pci/pcivar.h> 58 1.1 rumble #include <dev/pci/pcireg.h> 59 1.1 rumble #include <dev/pci/pcidevs.h> 60 1.1 rumble #include <dev/pci/pciconf.h> 61 1.1 rumble 62 1.1 rumble int giopci_debug = 0; 63 1.1 rumble #define DPRINTF(_x) if (giopci_debug) printf _x 64 1.1 rumble 65 1.1 rumble struct giopci_softc { 66 1.1 rumble struct sgimips_pci_chipset sc_pc; 67 1.1 rumble int sc_slot; 68 1.1 rumble int sc_gprid; 69 1.2 rumble uint32_t sc_pci_len; 70 1.1 rumble bus_space_tag_t sc_iot; 71 1.1 rumble bus_space_handle_t sc_ioh; 72 1.1 rumble }; 73 1.1 rumble 74 1.11 chs static int giopci_match(device_t, cfdata_t, void *); 75 1.11 chs static void giopci_attach(device_t, device_t, void *); 76 1.1 rumble static int giopci_bus_maxdevs(pci_chipset_tag_t, int); 77 1.1 rumble static pcireg_t giopci_conf_read(pci_chipset_tag_t, pcitag_t, int); 78 1.1 rumble static void giopci_conf_write(pci_chipset_tag_t, pcitag_t, int, pcireg_t); 79 1.1 rumble static int giopci_conf_hook(pci_chipset_tag_t, int, int, int, pcireg_t); 80 1.7 dyoung static int giopci_intr_map(const struct pci_attach_args *, 81 1.7 dyoung pci_intr_handle_t *); 82 1.1 rumble static const char * 83 1.12 christos giopci_intr_string(pci_chipset_tag_t, pci_intr_handle_t, 84 1.12 christos char *, size_t); 85 1.1 rumble static void *giopci_intr_establish(int, int, int (*)(void *), void *); 86 1.1 rumble static void giopci_intr_disestablish(void *); 87 1.1 rumble 88 1.1 rumble #define PHOBOS_PCI_OFFSET 0x00100000 89 1.1 rumble #define PHOBOS_PCI_LENGTH 128 /* ~arbitrary */ 90 1.1 rumble #define PHOBOS_TULIP_START 0x00101000 91 1.1 rumble #define PHOBOS_TULIP_END 0x001fffff 92 1.1 rumble 93 1.1 rumble #define SETENG_MAGIC_OFFSET 0x00020000 94 1.1 rumble #define SETENG_MAGIC_VALUE 0x00001000 95 1.1 rumble #define SETENG_PCI_OFFSET 0x00080000 96 1.1 rumble #define SETENG_PCI_LENGTH 128 /* ~arbitrary */ 97 1.1 rumble #define SETENG_TLAN_START 0x00100000 98 1.1 rumble #define SETENG_TLAN_END 0x001fffff 99 1.1 rumble 100 1.11 chs CFATTACH_DECL_NEW(giopci, sizeof(struct giopci_softc), 101 1.1 rumble giopci_match, giopci_attach, NULL, NULL); 102 1.1 rumble 103 1.14 macallan static void pcimem_bus_mem_init(bus_space_tag_t, void *); 104 1.14 macallan static struct mips_bus_space pcimem_mbst; 105 1.14 macallan bus_space_tag_t gio_pci_memt = NULL; 106 1.14 macallan 107 1.1 rumble static int 108 1.11 chs giopci_match(device_t parent, cfdata_t match, void *aux) 109 1.1 rumble { 110 1.1 rumble struct gio_attach_args *ga = aux; 111 1.1 rumble int gprid; 112 1.1 rumble 113 1.1 rumble /* 114 1.3 rumble * I think that these cards are all GIO32-bis or GIO64. Thus 115 1.3 rumble * they work in either Indigo2/Challenge M or 116 1.3 rumble * Indy/Challenge S/Indigo R4k, according to form factor. However, 117 1.1 rumble * there are some exceptions (e.g. my Indigo R4k won't power 118 1.1 rumble * on with the Set Engineering card installed). 119 1.1 rumble */ 120 1.1 rumble if (mach_type != MACH_SGI_IP20 && mach_type != MACH_SGI_IP22) 121 1.1 rumble return (0); 122 1.1 rumble 123 1.1 rumble gprid = GIO_PRODUCT_PRODUCTID(ga->ga_product); 124 1.1 rumble if (gprid == PHOBOS_G100 || gprid == PHOBOS_G130 || 125 1.1 rumble gprid == PHOBOS_G160 || gprid == SETENG_GFE) 126 1.1 rumble return (1); 127 1.1 rumble 128 1.1 rumble return (0); 129 1.1 rumble } 130 1.1 rumble 131 1.1 rumble static void 132 1.11 chs giopci_attach(device_t parent, device_t self, void *aux) 133 1.1 rumble { 134 1.11 chs struct giopci_softc *sc = device_private(self); 135 1.1 rumble pci_chipset_tag_t pc = &sc->sc_pc; 136 1.1 rumble struct gio_attach_args *ga = aux; 137 1.1 rumble uint32_t pci_off, pci_len, arb; 138 1.1 rumble struct pcibus_attach_args pba; 139 1.1 rumble u_long m_start, m_end; 140 1.1 rumble #ifdef PCI_NETBSD_CONFIGURE 141 1.1 rumble extern int pci_conf_debug; 142 1.1 rumble 143 1.1 rumble pci_conf_debug = giopci_debug; 144 1.1 rumble #endif 145 1.1 rumble 146 1.1 rumble sc->sc_iot = ga->ga_iot; 147 1.1 rumble sc->sc_slot = ga->ga_slot; 148 1.1 rumble sc->sc_gprid = GIO_PRODUCT_PRODUCTID(ga->ga_product); 149 1.1 rumble 150 1.14 macallan pcimem_bus_mem_init(&pcimem_mbst, NULL); 151 1.14 macallan gio_pci_memt = &pcimem_mbst; 152 1.14 macallan 153 1.1 rumble if (mach_type == MACH_SGI_IP22 && 154 1.1 rumble mach_subtype == MACH_SGI_IP22_FULLHOUSE) 155 1.1 rumble arb = GIO_ARB_RT | GIO_ARB_MST | GIO_ARB_PIPE; 156 1.1 rumble else 157 1.1 rumble arb = GIO_ARB_RT | GIO_ARB_MST; 158 1.1 rumble 159 1.1 rumble if (gio_arb_config(ga->ga_slot, arb)) { 160 1.1 rumble printf(": failed to configure GIO bus arbiter\n"); 161 1.1 rumble return; 162 1.1 rumble } 163 1.1 rumble 164 1.1 rumble #if (NIMC > 0) 165 1.1 rumble imc_disable_sysad_parity(); 166 1.1 rumble #endif 167 1.1 rumble 168 1.1 rumble switch (sc->sc_gprid) { 169 1.1 rumble case PHOBOS_G100: 170 1.1 rumble case PHOBOS_G130: 171 1.1 rumble case PHOBOS_G160: 172 1.1 rumble pci_off = PHOBOS_PCI_OFFSET; 173 1.1 rumble pci_len = PHOBOS_PCI_LENGTH; 174 1.1 rumble m_start = MIPS_KSEG1_TO_PHYS(ga->ga_addr + PHOBOS_TULIP_START); 175 1.1 rumble m_end = MIPS_KSEG1_TO_PHYS(ga->ga_addr + PHOBOS_TULIP_END); 176 1.1 rumble break; 177 1.1 rumble 178 1.1 rumble case SETENG_GFE: 179 1.4 rumble /* 180 1.4 rumble * NB: The SetEng board does not allow the ThunderLAN's DMA 181 1.4 rumble * engine to properly transfer segments that span page 182 1.4 rumble * boundaries. See sgimips/autoconf.c where we catch a 183 1.4 rumble * tl(4) device attachment and create an appropriate 184 1.4 rumble * proplib entry to enable the workaround. 185 1.4 rumble */ 186 1.1 rumble pci_off = SETENG_PCI_OFFSET; 187 1.1 rumble pci_len = SETENG_PCI_LENGTH; 188 1.1 rumble m_start = MIPS_KSEG1_TO_PHYS(ga->ga_addr + SETENG_TLAN_START); 189 1.1 rumble m_end = MIPS_KSEG1_TO_PHYS(ga->ga_addr + SETENG_TLAN_END); 190 1.1 rumble bus_space_write_4(ga->ga_iot, ga->ga_ioh, 191 1.1 rumble SETENG_MAGIC_OFFSET, SETENG_MAGIC_VALUE); 192 1.1 rumble break; 193 1.1 rumble 194 1.1 rumble default: 195 1.1 rumble panic("giopci_attach: unsupported GIO product id 0x%02x", 196 1.1 rumble sc->sc_gprid); 197 1.1 rumble } 198 1.1 rumble 199 1.1 rumble if (bus_space_subregion(ga->ga_iot, ga->ga_ioh, pci_off, pci_len, 200 1.1 rumble &sc->sc_ioh)) { 201 1.11 chs printf("%s: unable to map PCI registers\n", device_xname(self)); 202 1.1 rumble return; 203 1.1 rumble } 204 1.2 rumble sc->sc_pci_len = pci_len; 205 1.1 rumble 206 1.1 rumble pc->pc_bus_maxdevs = giopci_bus_maxdevs; 207 1.1 rumble pc->pc_conf_read = giopci_conf_read; 208 1.1 rumble pc->pc_conf_write = giopci_conf_write; 209 1.1 rumble pc->pc_conf_hook = giopci_conf_hook; 210 1.1 rumble pc->pc_intr_map = giopci_intr_map; 211 1.1 rumble pc->pc_intr_string = giopci_intr_string; 212 1.1 rumble pc->intr_establish = giopci_intr_establish; 213 1.1 rumble pc->intr_disestablish = giopci_intr_disestablish; 214 1.1 rumble pc->iot = ga->ga_iot; 215 1.1 rumble pc->ioh = ga->ga_ioh; 216 1.1 rumble pc->cookie = sc; 217 1.1 rumble 218 1.1 rumble printf(": %s\n", gio_product_string(sc->sc_gprid)); 219 1.1 rumble 220 1.1 rumble #ifdef PCI_NETBSD_CONFIGURE 221 1.17 thorpej struct pciconf_resources *pcires = pciconf_resource_init(); 222 1.17 thorpej 223 1.17 thorpej pciconf_resource_add(pcires, PCICONF_RESOURCE_MEM, 224 1.17 thorpej m_start, (m_end - m_start) + 1); 225 1.17 thorpej 226 1.17 thorpej pci_configure_bus(pc, pcires, 0, 227 1.6 matt mips_cache_info.mci_dcache_align); 228 1.17 thorpej 229 1.17 thorpej pciconf_resource_fini(pcires); 230 1.1 rumble #endif 231 1.1 rumble 232 1.1 rumble memset(&pba, 0, sizeof(pba)); 233 1.14 macallan pba.pba_memt = gio_pci_memt; 234 1.1 rumble pba.pba_dmat = ga->ga_dmat; 235 1.1 rumble pba.pba_pc = pc; 236 1.8 dyoung pba.pba_flags = PCI_FLAGS_MEM_OKAY; 237 1.1 rumble /* NB: do not set PCI_FLAGS_{MRL,MRM,MWI}_OKAY -- true ?! */ 238 1.1 rumble 239 1.19 thorpej config_found(self, &pba, pcibusprint, CFARGS_NONE); 240 1.1 rumble } 241 1.1 rumble 242 1.1 rumble static int 243 1.1 rumble giopci_bus_maxdevs(pci_chipset_tag_t pc, int busno) 244 1.1 rumble { 245 1.1 rumble 246 1.1 rumble return (busno == 0); 247 1.1 rumble } 248 1.1 rumble 249 1.1 rumble static pcireg_t 250 1.1 rumble giopci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) 251 1.1 rumble { 252 1.1 rumble struct giopci_softc *sc = pc->cookie; 253 1.1 rumble int bus, dev, func; 254 1.1 rumble pcireg_t data; 255 1.1 rumble 256 1.15 msaitoh if ((unsigned int)reg >= PCI_CONF_SIZE) 257 1.15 msaitoh return (pcireg_t) -1; 258 1.15 msaitoh 259 1.1 rumble pci_decompose_tag(pc, tag, &bus, &dev, &func); 260 1.1 rumble if (bus != 0 || dev != 0 || func != 0) 261 1.1 rumble return (0); 262 1.1 rumble 263 1.2 rumble /* XXX - should just use bus_space_peek */ 264 1.2 rumble if (reg >= sc->sc_pci_len) { 265 1.2 rumble DPRINTF(("giopci_conf_read: reg 0x%x out of bounds\n", reg)); 266 1.2 rumble return (0); 267 1.2 rumble } 268 1.2 rumble 269 1.1 rumble DPRINTF(("giopci_conf_read: reg 0x%x = 0x", reg)); 270 1.1 rumble data = bus_space_read_4(sc->sc_iot, sc->sc_ioh, reg); 271 1.1 rumble DPRINTF(("%08x\n", data)); 272 1.1 rumble 273 1.1 rumble return (data); 274 1.1 rumble } 275 1.1 rumble 276 1.1 rumble static void 277 1.1 rumble giopci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) 278 1.1 rumble { 279 1.1 rumble struct giopci_softc *sc = pc->cookie; 280 1.1 rumble int bus, dev, func; 281 1.1 rumble 282 1.15 msaitoh if ((unsigned int)reg >= PCI_CONF_SIZE) 283 1.15 msaitoh return; 284 1.15 msaitoh 285 1.1 rumble pci_decompose_tag(pc, tag, &bus, &dev, &func); 286 1.1 rumble if (bus != 0 || dev != 0 || func != 0) 287 1.1 rumble return; 288 1.1 rumble 289 1.2 rumble /* XXX - should just use bus_space_poke */ 290 1.2 rumble if (reg >= sc->sc_pci_len) { 291 1.2 rumble DPRINTF(("giopci_conf_write: reg 0x%x out of bounds " 292 1.2 rumble "(val = 0x%08x)\n", reg, data)); 293 1.2 rumble return; 294 1.2 rumble } 295 1.2 rumble 296 1.1 rumble DPRINTF(("giopci_conf_write: reg 0x%x = 0x%08x\n", reg, data)); 297 1.1 rumble bus_space_write_4(sc->sc_iot, sc->sc_ioh, reg, data); 298 1.1 rumble } 299 1.1 rumble 300 1.1 rumble static int 301 1.1 rumble giopci_conf_hook(pci_chipset_tag_t pc, int bus, int device, int function, 302 1.1 rumble pcireg_t id) 303 1.1 rumble { 304 1.1 rumble 305 1.1 rumble /* All devices use memory accesses only. */ 306 1.1 rumble return (PCI_CONF_MAP_MEM | PCI_CONF_ENABLE_MEM | PCI_CONF_ENABLE_BM); 307 1.1 rumble } 308 1.1 rumble 309 1.1 rumble static int 310 1.7 dyoung giopci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp) 311 1.1 rumble { 312 1.1 rumble struct giopci_softc *sc = pa->pa_pc->cookie; 313 1.1 rumble 314 1.1 rumble *ihp = sc->sc_slot; 315 1.1 rumble 316 1.1 rumble return (0); 317 1.1 rumble } 318 1.1 rumble 319 1.1 rumble static const char * 320 1.12 christos giopci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih, char * buf, 321 1.13 ozaki size_t len) 322 1.1 rumble { 323 1.12 christos snprintf(buf, len, "slot %s", (ih == GIO_SLOT_EXP0) ? "EXP0" : 324 1.1 rumble (ih == GIO_SLOT_EXP1) ? "EXP1" : "GFX"); 325 1.12 christos return buf; 326 1.1 rumble } 327 1.1 rumble 328 1.1 rumble static void * 329 1.1 rumble giopci_intr_establish(int slot, int level, int (*func)(void *), void *arg) 330 1.1 rumble { 331 1.1 rumble 332 1.1 rumble return (gio_intr_establish(slot, level, func, arg)); 333 1.1 rumble } 334 1.1 rumble 335 1.1 rumble static void 336 1.1 rumble giopci_intr_disestablish(void *cookie) 337 1.1 rumble { 338 1.1 rumble 339 1.1 rumble panic("giopci_intr_disestablish: impossible."); 340 1.1 rumble } 341 1.14 macallan 342 1.14 macallan #define CHIP pcimem 343 1.14 macallan #define CHIP_MEM /* defined */ 344 1.14 macallan #define CHIP_WRONG_ENDIAN 345 1.14 macallan 346 1.14 macallan #define CHIP_W1_BUS_START(v) 0x00000000UL 347 1.14 macallan #define CHIP_W1_BUS_END(v) 0xffffffffUL 348 1.14 macallan #define CHIP_W1_SYS_START(v) 0x00000000UL 349 1.14 macallan #define CHIP_W1_SYS_END(v) 0xffffffffUL 350 1.14 macallan 351 1.14 macallan #include <mips/mips/bus_space_alignstride_chipdep.c> 352