1 1.12 thorpej /* $NetBSD: u3.c,v 1.12 2022/01/21 19:12:28 thorpej Exp $ */ 2 1.2 garbled 3 1.1 sanjayl /* 4 1.1 sanjayl * Copyright 2006 Kyma Systems LLC. 5 1.1 sanjayl * All rights reserved. 6 1.1 sanjayl * 7 1.1 sanjayl * Written by Sanjay Lal <sanjayl (at) kymasys.com> 8 1.1 sanjayl * 9 1.1 sanjayl * Redistribution and use in source and binary forms, with or without 10 1.1 sanjayl * modification, are permitted provided that the following conditions 11 1.1 sanjayl * are met: 12 1.1 sanjayl * 1. Redistributions of source code must retain the above copyright 13 1.1 sanjayl * notice, this list of conditions and the following disclaimer. 14 1.1 sanjayl * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 sanjayl * notice, this list of conditions and the following disclaimer in the 16 1.1 sanjayl * documentation and/or other materials provided with the distribution. 17 1.1 sanjayl * 3. All advertising materials mentioning features or use of this software 18 1.1 sanjayl * must display the following acknowledgement: 19 1.1 sanjayl * This product includes software developed for the NetBSD Project by 20 1.1 sanjayl * Kyma Systems LLC. 21 1.1 sanjayl * 4. The name of Kyma Systems LLC may not be used to endorse 22 1.1 sanjayl * or promote products derived from this software without specific prior 23 1.1 sanjayl * written permission. 24 1.1 sanjayl * 25 1.1 sanjayl * THIS SOFTWARE IS PROVIDED BY KYMA SYSTEMS LLC ``AS IS'' AND 26 1.1 sanjayl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 1.1 sanjayl * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 1.1 sanjayl * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KYMA SYSTEMS LLC 29 1.1 sanjayl * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 1.1 sanjayl * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 1.1 sanjayl * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 1.1 sanjayl * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 1.1 sanjayl * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 1.1 sanjayl * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 1.1 sanjayl * POSSIBILITY OF SUCH DAMAGE. 36 1.1 sanjayl */ 37 1.1 sanjayl 38 1.1 sanjayl #include <sys/cdefs.h> 39 1.1 sanjayl 40 1.1 sanjayl #include <sys/param.h> 41 1.1 sanjayl #include <sys/device.h> 42 1.1 sanjayl #include <sys/systm.h> 43 1.1 sanjayl 44 1.1 sanjayl #include <dev/pci/pcivar.h> 45 1.1 sanjayl #include <dev/ofw/openfirm.h> 46 1.1 sanjayl #include <dev/ofw/ofw_pci.h> 47 1.1 sanjayl 48 1.1 sanjayl #include <machine/autoconf.h> 49 1.6 chs #include <machine/pio.h> 50 1.1 sanjayl 51 1.1 sanjayl struct ibmcpc_softc 52 1.1 sanjayl { 53 1.7 macallan device_t sc_dev; 54 1.2 garbled struct genppc_pci_chipset sc_pc[8]; 55 1.2 garbled struct powerpc_bus_space sc_iot; 56 1.2 garbled struct powerpc_bus_space sc_memt; 57 1.9 macallan int sc_ranges[8]; 58 1.1 sanjayl }; 59 1.1 sanjayl 60 1.9 macallan /* kinda ugly but there can be only one */ 61 1.9 macallan static struct ibmcpc_softc *cpc0 = NULL; 62 1.9 macallan 63 1.4 matt static void ibmcpc_attach(device_t, device_t, void *); 64 1.4 matt static int ibmcpc_match(device_t, cfdata_t, void *); 65 1.1 sanjayl 66 1.2 garbled static pcireg_t ibmcpc_conf_read(void *, pcitag_t, int); 67 1.2 garbled static void ibmcpc_conf_write(void *, pcitag_t, int, pcireg_t); 68 1.1 sanjayl 69 1.6 chs CFATTACH_DECL_NEW(ibmcpc, sizeof(struct ibmcpc_softc), 70 1.1 sanjayl ibmcpc_match, ibmcpc_attach, NULL, NULL); 71 1.1 sanjayl 72 1.1 sanjayl #define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) 73 1.1 sanjayl 74 1.2 garbled static int 75 1.4 matt ibmcpc_match(device_t parent, cfdata_t cf, void *aux) 76 1.1 sanjayl { 77 1.2 garbled struct confargs *ca = aux; 78 1.2 garbled char compat[32]; 79 1.1 sanjayl 80 1.2 garbled if (strcmp(ca->ca_name, "ht") != 0) 81 1.2 garbled return 0; 82 1.1 sanjayl 83 1.2 garbled memset(compat, 0, sizeof(compat)); 84 1.2 garbled OF_getprop(ca->ca_node, "compatible", compat, sizeof(compat)); 85 1.1 sanjayl 86 1.2 garbled if (strcmp(compat, "u3-ht") != 0) 87 1.2 garbled return 0; 88 1.1 sanjayl 89 1.2 garbled return 1; 90 1.1 sanjayl } 91 1.1 sanjayl 92 1.2 garbled static void 93 1.4 matt ibmcpc_attach(device_t parent, device_t self, void *aux) 94 1.1 sanjayl { 95 1.6 chs struct ibmcpc_softc *sc = device_private(self); 96 1.2 garbled pci_chipset_tag_t pc = sc->sc_pc; 97 1.2 garbled struct confargs *ca = aux; 98 1.2 garbled struct pcibus_attach_args pba; 99 1.2 garbled int node = ca->ca_node, child; 100 1.2 garbled uint32_t reg[6], busrange[2], i; 101 1.2 garbled void *pc_data; 102 1.2 garbled char name[32]; 103 1.2 garbled 104 1.2 garbled aprint_normal("\n"); 105 1.7 macallan sc->sc_dev = self; 106 1.2 garbled 107 1.2 garbled /* u3 address */ 108 1.2 garbled if (OF_getprop(node, "reg", reg, sizeof(reg)) < 24) { 109 1.2 garbled return; 110 1.2 garbled } 111 1.2 garbled aprint_normal("Mapping in config space @ pa 0x%08x, size: 0x%08x\n", 112 1.2 garbled reg[1], reg[2]); 113 1.5 matt pc_data = mapiodev(reg[1], reg[2], false); 114 1.2 garbled 115 1.9 macallan cpc0 = sc; 116 1.9 macallan 117 1.2 garbled for (child = OF_child(OF_finddevice("/ht")), i = 1; child; 118 1.2 garbled child = OF_peer(child), i++) { 119 1.2 garbled 120 1.2 garbled memset(name, 0, sizeof(name)); 121 1.2 garbled 122 1.2 garbled if (OF_getprop(child, "name", name, sizeof(name)) == -1) 123 1.2 garbled continue; 124 1.2 garbled 125 1.2 garbled if (strcmp(name, "pci") != 0) 126 1.2 garbled continue; 127 1.2 garbled 128 1.2 garbled if (OF_getprop(child, "bus-range", busrange, 8) < 8) 129 1.2 garbled continue; 130 1.2 garbled 131 1.7 macallan memset(&sc->sc_iot, 0, sizeof(sc->sc_iot)); 132 1.2 garbled sc->sc_iot.pbs_flags = _BUS_SPACE_LITTLE_ENDIAN | 133 1.2 garbled _BUS_SPACE_IO_TYPE; 134 1.2 garbled sc->sc_iot.pbs_base = 0x00000000; 135 1.2 garbled if (ofwoea_map_space(RANGE_TYPE_PCI, RANGE_IO, child, 136 1.2 garbled &sc->sc_iot, "ibmcpc io") != 0) 137 1.2 garbled panic("Can't init ibmcpc io tag"); 138 1.2 garbled 139 1.7 macallan memset(&sc->sc_memt, 0, sizeof(sc->sc_memt)); 140 1.2 garbled sc->sc_memt.pbs_flags = _BUS_SPACE_LITTLE_ENDIAN | 141 1.2 garbled _BUS_SPACE_MEM_TYPE; 142 1.2 garbled sc->sc_memt.pbs_base = 0x00000000; 143 1.2 garbled if (ofwoea_map_space(RANGE_TYPE_PCI, RANGE_MEM, child, 144 1.2 garbled &sc->sc_memt, "ibmcpc mem") != 0) 145 1.2 garbled panic("Can't init ibmcpc mem tag"); 146 1.2 garbled 147 1.2 garbled macppc_pci_get_chipset_tag(pc); 148 1.2 garbled pc->pc_node = child; 149 1.2 garbled pc->pc_bus = busrange[0]; 150 1.9 macallan sc->sc_ranges[pc->pc_bus] = busrange[1]; 151 1.2 garbled pc->pc_addr = 0x0; 152 1.2 garbled pc->pc_data = pc_data; 153 1.2 garbled pc->pc_conf_read = ibmcpc_conf_read; 154 1.2 garbled pc->pc_conf_write = ibmcpc_conf_write; 155 1.2 garbled pc->pc_memt = &sc->sc_memt; 156 1.2 garbled pc->pc_iot = &sc->sc_iot; 157 1.2 garbled 158 1.2 garbled memset(&pba, 0, sizeof(pba)); 159 1.2 garbled pba.pba_memt = pc->pc_memt; 160 1.2 garbled pba.pba_iot = pc->pc_iot; 161 1.2 garbled pba.pba_dmat = &pci_bus_dma_tag; 162 1.2 garbled pba.pba_dmat64 = NULL; 163 1.2 garbled pba.pba_bridgetag = NULL; 164 1.2 garbled pba.pba_pc = pc; 165 1.2 garbled pba.pba_bus = pc->pc_bus; 166 1.3 dyoung pba.pba_flags = PCI_FLAGS_MEM_OKAY | PCI_FLAGS_IO_OKAY; 167 1.10 thorpej 168 1.10 thorpej config_found(self, &pba, pcibusprint, 169 1.12 thorpej CFARGS(.devhandle = device_handle(self))); 170 1.1 sanjayl 171 1.2 garbled pc++; 172 1.2 garbled } 173 1.1 sanjayl } 174 1.1 sanjayl 175 1.2 garbled static pcireg_t 176 1.2 garbled ibmcpc_conf_read(void *cookie, pcitag_t tag, int reg) 177 1.1 sanjayl { 178 1.2 garbled pci_chipset_tag_t pc = cookie; 179 1.9 macallan struct ibmcpc_softc *sc = cpc0; 180 1.2 garbled u_int32_t daddr = (u_int32_t) pc->pc_data; 181 1.2 garbled pcireg_t data; 182 1.2 garbled u_int32_t bus, dev, func, x, devfn; 183 1.2 garbled 184 1.8 msaitoh if ((unsigned int)reg >= PCI_CONF_SIZE) 185 1.8 msaitoh return (pcireg_t) -1; 186 1.8 msaitoh 187 1.2 garbled pci_decompose_tag(pc, tag, &bus, &dev, &func); 188 1.1 sanjayl 189 1.9 macallan if ((bus < pc->pc_bus) || (bus > sc->sc_ranges[pc->pc_bus])) { 190 1.9 macallan data = 0xffffffff; 191 1.9 macallan goto done; 192 1.9 macallan } 193 1.9 macallan 194 1.2 garbled devfn = PCI_DEVFN(dev, func); 195 1.1 sanjayl 196 1.2 garbled if (bus == 0) { 197 1.1 sanjayl 198 1.2 garbled if (devfn == 0x0) { 199 1.1 sanjayl 200 1.2 garbled data = 0xffffffff; 201 1.2 garbled goto done; 202 1.2 garbled } 203 1.1 sanjayl 204 1.2 garbled x = daddr + ((devfn << 8) | reg); 205 1.2 garbled } else 206 1.2 garbled x = daddr + ((devfn << 8) | reg) + (bus << 16) + 0x01000000UL; 207 1.1 sanjayl 208 1.2 garbled data = in32rb(x); 209 1.1 sanjayl 210 1.2 garbled done: 211 1.2 garbled return data; 212 1.1 sanjayl } 213 1.1 sanjayl 214 1.2 garbled static void 215 1.2 garbled ibmcpc_conf_write(void *cookie, pcitag_t tag, int reg, pcireg_t data) 216 1.1 sanjayl { 217 1.2 garbled pci_chipset_tag_t pc = cookie; 218 1.9 macallan struct ibmcpc_softc *sc = cpc0; 219 1.2 garbled int32_t *daddr = pc->pc_data; 220 1.2 garbled u_int32_t bus, dev, func; 221 1.2 garbled u_int32_t x, devfn; 222 1.2 garbled 223 1.8 msaitoh if ((unsigned int)reg >= PCI_CONF_SIZE) 224 1.8 msaitoh return; 225 1.8 msaitoh 226 1.2 garbled pci_decompose_tag(pc, tag, &bus, &dev, &func); 227 1.2 garbled 228 1.9 macallan if ((bus < pc->pc_bus) || (bus > sc->sc_ranges[pc->pc_bus])) 229 1.9 macallan return; 230 1.9 macallan 231 1.2 garbled devfn = PCI_DEVFN(dev, func); 232 1.2 garbled 233 1.2 garbled if (bus == 0) { 234 1.2 garbled 235 1.2 garbled if (devfn == 0x0) { 236 1.2 garbled goto done; 237 1.2 garbled } 238 1.2 garbled x = (u_int32_t) daddr + ((devfn << 8) | reg); 239 1.2 garbled } else 240 1.2 garbled x = (u_int32_t) daddr + ((devfn << 8) | reg) + (bus << 16) + 241 1.2 garbled 0x01000000UL; 242 1.1 sanjayl 243 1.2 garbled out32rb(x, data); 244 1.1 sanjayl 245 1.2 garbled done: 246 1.2 garbled return; 247 1.1 sanjayl } 248