1 1.34 andvar /* $NetBSD: s3c2800_pci.c,v 1.34 2022/09/25 12:28:54 andvar Exp $ */ 2 1.1 bsh 3 1.1 bsh /* 4 1.1 bsh * Copyright (c) 2002 Fujitsu Component Limited 5 1.1 bsh * Copyright (c) 2002 Genetec Corporation 6 1.1 bsh * All rights reserved. 7 1.1 bsh * 8 1.1 bsh * Redistribution and use in source and binary forms, with or without 9 1.1 bsh * modification, are permitted provided that the following conditions 10 1.1 bsh * are met: 11 1.1 bsh * 1. Redistributions of source code must retain the above copyright 12 1.1 bsh * notice, this list of conditions and the following disclaimer. 13 1.1 bsh * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 bsh * notice, this list of conditions and the following disclaimer in the 15 1.1 bsh * documentation and/or other materials provided with the distribution. 16 1.1 bsh * 3. Neither the name of The Fujitsu Component Limited nor the name of 17 1.1 bsh * Genetec corporation may not be used to endorse or promote products 18 1.1 bsh * derived from this software without specific prior written permission. 19 1.1 bsh * 20 1.1 bsh * THIS SOFTWARE IS PROVIDED BY FUJITSU COMPONENT LIMITED AND GENETEC 21 1.1 bsh * CORPORATION ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 22 1.1 bsh * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 23 1.1 bsh * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 1.1 bsh * DISCLAIMED. IN NO EVENT SHALL FUJITSU COMPONENT LIMITED OR GENETEC 25 1.1 bsh * CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 1.1 bsh * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 1.1 bsh * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 28 1.1 bsh * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 1.1 bsh * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 1.1 bsh * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 1.1 bsh * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 1.1 bsh * SUCH DAMAGE. 33 1.1 bsh * 34 1.1 bsh * derived from evbarm/ifpga/ifpga_pci.c 35 1.1 bsh */ 36 1.1 bsh 37 1.1 bsh /* 38 1.1 bsh * Copyright (c) 2001 ARM Ltd 39 1.1 bsh * All rights reserved. 40 1.1 bsh * 41 1.1 bsh * Redistribution and use in source and binary forms, with or without 42 1.1 bsh * modification, are permitted provided that the following conditions 43 1.1 bsh * are met: 44 1.1 bsh * 1. Redistributions of source code must retain the above copyright 45 1.1 bsh * notice, this list of conditions and the following disclaimer. 46 1.1 bsh * 2. Redistributions in binary form must reproduce the above copyright 47 1.1 bsh * notice, this list of conditions and the following disclaimer in the 48 1.1 bsh * documentation and/or other materials provided with the distribution. 49 1.1 bsh * 3. The name of the company may not be used to endorse or promote 50 1.1 bsh * products derived from this software without specific prior written 51 1.1 bsh * permission. 52 1.1 bsh * 53 1.1 bsh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 54 1.1 bsh * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 55 1.1 bsh * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 56 1.1 bsh * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 57 1.1 bsh * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 58 1.1 bsh * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 59 1.1 bsh * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 1.1 bsh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 1.1 bsh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 1.1 bsh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 1.1 bsh * SUCH DAMAGE. 64 1.1 bsh * 65 1.1 bsh * Copyright (c) 1997,1998 Mark Brinicombe. 66 1.1 bsh * Copyright (c) 1997,1998 Causality Limited 67 1.1 bsh * All rights reserved. 68 1.1 bsh * 69 1.1 bsh * Redistribution and use in source and binary forms, with or without 70 1.1 bsh * modification, are permitted provided that the following conditions 71 1.1 bsh * are met: 72 1.1 bsh * 1. Redistributions of source code must retain the above copyright 73 1.1 bsh * notice, this list of conditions and the following disclaimer. 74 1.1 bsh * 2. Redistributions in binary form must reproduce the above copyright 75 1.1 bsh * notice, this list of conditions and the following disclaimer in the 76 1.1 bsh * documentation and/or other materials provided with the distribution. 77 1.1 bsh * 3. All advertising materials mentioning features or use of this software 78 1.1 bsh * must display the following acknowledgement: 79 1.1 bsh * This product includes software developed by Mark Brinicombe 80 1.1 bsh * for the NetBSD Project. 81 1.1 bsh * 4. The name of the company nor the name of the author may be used to 82 1.1 bsh * endorse or promote products derived from this software without specific 83 1.1 bsh * prior written permission. 84 1.1 bsh * 85 1.1 bsh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 86 1.1 bsh * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 87 1.1 bsh * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 88 1.1 bsh * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 89 1.1 bsh * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 90 1.1 bsh * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 91 1.1 bsh * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 92 1.1 bsh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 93 1.1 bsh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 94 1.1 bsh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 95 1.1 bsh * SUCH DAMAGE. 96 1.1 bsh */ 97 1.1 bsh 98 1.1 bsh /* 99 1.1 bsh * PCI configuration support for Samsung s3c2800. 100 1.1 bsh */ 101 1.7 lukem 102 1.7 lukem #include <sys/cdefs.h> 103 1.34 andvar __KERNEL_RCSID(0, "$NetBSD: s3c2800_pci.c,v 1.34 2022/09/25 12:28:54 andvar Exp $"); 104 1.20 matt 105 1.20 matt #include "opt_pci.h" 106 1.20 matt #include "pci.h" 107 1.1 bsh 108 1.1 bsh #include <sys/param.h> 109 1.1 bsh #include <sys/systm.h> 110 1.1 bsh #include <sys/kernel.h> 111 1.1 bsh #include <sys/device.h> 112 1.30 thorpej #include <sys/kmem.h> 113 1.1 bsh 114 1.1 bsh #include <uvm/uvm_extern.h> 115 1.1 bsh 116 1.16 dyoung #include <sys/bus.h> 117 1.1 bsh 118 1.1 bsh #include <dev/pci/pcireg.h> 119 1.20 matt #include <dev/pci/pcivar.h> 120 1.1 bsh #include <dev/pci/pciconf.h> 121 1.1 bsh 122 1.20 matt #include <arm/locore.h> 123 1.20 matt 124 1.20 matt #include <arm/s3c2xx0/s3c2800reg.h> 125 1.20 matt #include <arm/s3c2xx0/s3c2800var.h> 126 1.1 bsh 127 1.1 bsh /* 128 1.1 bsh * pci tag encoding. 129 1.1 bsh * also useful for configuration type 0 address 130 1.1 bsh */ 131 1.1 bsh #define BUSNO_SHIFT 16 132 1.1 bsh #define BUSNO_MASK (0xff<<BUSNO_SHIFT) 133 1.1 bsh #define DEVNO_SHIFT 11 134 1.1 bsh #define DEVNO_MASK (0x1f<<DEVNO_SHIFT) 135 1.1 bsh #define tag_to_devno(tag) (((tag)&DEVNO_MASK)>>DEVNO_SHIFT) 136 1.1 bsh #define FUNNO_SHIFT 8 137 1.1 bsh #define FUNNO_MASK (0x07<<FUNNO_SHIFT) 138 1.1 bsh 139 1.1 bsh #define BUS0_DEV_MIN 1 140 1.1 bsh #define BUS0_DEV_MAX 21 141 1.1 bsh 142 1.19 chs void s3c2800_pci_attach_hook(device_t, device_t, struct pcibus_attach_args *); 143 1.1 bsh int s3c2800_pci_bus_maxdevs(void *, int); 144 1.1 bsh pcitag_t s3c2800_pci_make_tag(void *, int, int, int); 145 1.1 bsh void s3c2800_pci_decompose_tag(void *, pcitag_t, int *, int *, int *); 146 1.1 bsh pcireg_t s3c2800_pci_conf_read(void *, pcitag_t, int); 147 1.1 bsh void s3c2800_pci_conf_write(void *, pcitag_t, int, pcireg_t); 148 1.18 matt void s3c2800_pci_conf_interrupt(void *, int, int, int, int, int *); 149 1.14 dyoung int s3c2800_pci_intr_map(const struct pci_attach_args *, 150 1.14 dyoung pci_intr_handle_t *); 151 1.21 christos const char *s3c2800_pci_intr_string(void *, pci_intr_handle_t, char *, size_t); 152 1.1 bsh const struct evcnt *s3c2800_pci_intr_evcnt(void *, pci_intr_handle_t); 153 1.12 christos void *s3c2800_pci_intr_establish(void *, pci_intr_handle_t, int, 154 1.25 jmcneill int (*) (void *), void *, const char *); 155 1.1 bsh void s3c2800_pci_intr_disestablish(void *, void *); 156 1.1 bsh 157 1.1 bsh #define PCI_CONF_LOCK(s) (s) = disable_interrupts(I32_bit) 158 1.1 bsh #define PCI_CONF_UNLOCK(s) restore_interrupts((s)) 159 1.1 bsh 160 1.1 bsh struct sspci_irq_handler { 161 1.1 bsh int (*func) (void *); 162 1.1 bsh void *arg; 163 1.1 bsh int level; 164 1.1 bsh SLIST_ENTRY(sspci_irq_handler) link; 165 1.1 bsh }; 166 1.1 bsh 167 1.1 bsh struct sspci_softc { 168 1.19 chs device_t sc_dev; 169 1.1 bsh 170 1.1 bsh bus_space_tag_t sc_iot; 171 1.1 bsh bus_space_handle_t sc_reg_ioh; 172 1.1 bsh bus_space_handle_t sc_conf0_ioh; /* config type0 space */ 173 1.1 bsh bus_space_handle_t sc_conf1_ioh; /* config type1 space */ 174 1.1 bsh 175 1.1 bsh uint32_t sc_pciinten; /* copy of PCIINTEN register */ 176 1.1 bsh 177 1.1 bsh /* list of interrupt handlers. SLIST is not good for removing 178 1.1 bsh * element from it, but intr_disestablish is rarely called */ 179 1.1 bsh SLIST_HEAD(, sspci_irq_handler) sc_irq_handlers; 180 1.1 bsh 181 1.1 bsh void *sc_softinterrupt; 182 1.1 bsh }; 183 1.1 bsh 184 1.19 chs static int sspci_match(device_t, cfdata_t, void *aux); 185 1.19 chs static void sspci_attach(device_t, device_t, void *); 186 1.1 bsh 187 1.1 bsh static int sspci_bs_map(void *, bus_addr_t, bus_size_t, int, 188 1.1 bsh bus_space_handle_t *); 189 1.1 bsh static int sspci_init_controller(struct sspci_softc *); 190 1.1 bsh static int sspci_intr(void *); 191 1.1 bsh static void sspci_softintr(void *); 192 1.1 bsh 193 1.1 bsh /* attach structures */ 194 1.19 chs CFATTACH_DECL_NEW(sspci, sizeof(struct sspci_softc), sspci_match, sspci_attach, 195 1.1 bsh NULL, NULL); 196 1.1 bsh 197 1.1 bsh 198 1.1 bsh struct arm32_pci_chipset sspci_chipset = { 199 1.26 jmcneill .pc_attach_hook = s3c2800_pci_attach_hook, 200 1.26 jmcneill .pc_bus_maxdevs = s3c2800_pci_bus_maxdevs, 201 1.26 jmcneill .pc_make_tag = s3c2800_pci_make_tag, 202 1.26 jmcneill .pc_decompose_tag = s3c2800_pci_decompose_tag, 203 1.26 jmcneill .pc_conf_read = s3c2800_pci_conf_read, 204 1.26 jmcneill .pc_conf_write = s3c2800_pci_conf_write, 205 1.26 jmcneill .pc_intr_map = s3c2800_pci_intr_map, 206 1.26 jmcneill .pc_intr_string = s3c2800_pci_intr_string, 207 1.26 jmcneill .pc_intr_evcnt = s3c2800_pci_intr_evcnt, 208 1.26 jmcneill .pc_intr_establish = s3c2800_pci_intr_establish, 209 1.26 jmcneill .pc_intr_disestablish = s3c2800_pci_intr_disestablish, 210 1.26 jmcneill .pc_conf_interrupt = s3c2800_pci_conf_interrupt, 211 1.1 bsh }; 212 1.1 bsh 213 1.1 bsh 214 1.1 bsh /* 215 1.1 bsh * bus space tag for PCI IO/Memory access space. 216 1.1 bsh * filled in by sspci_attach() 217 1.1 bsh */ 218 1.1 bsh struct bus_space sspci_io_tag, sspci_mem_tag; 219 1.1 bsh 220 1.1 bsh static int 221 1.19 chs sspci_match(device_t parent, cfdata_t match, void *aux) 222 1.1 bsh { 223 1.1 bsh return 1; 224 1.1 bsh } 225 1.1 bsh 226 1.1 bsh static void 227 1.19 chs sspci_attach(device_t parent, device_t self, void *aux) 228 1.1 bsh { 229 1.19 chs struct sspci_softc *sc = device_private(self); 230 1.1 bsh struct s3c2xx0_attach_args *aa = aux; 231 1.1 bsh bus_space_tag_t iot; 232 1.1 bsh bus_dma_tag_t pci_dma_tag; 233 1.1 bsh const char *error_on; /* for panic message */ 234 1.1 bsh #if defined(PCI_NETBSD_CONFIGURE) 235 1.29 thorpej struct pciconf_resources *pcires; 236 1.1 bsh struct pcibus_attach_args pci_pba; 237 1.1 bsh #endif 238 1.1 bsh 239 1.1 bsh #define FAIL(which) do { \ 240 1.1 bsh error_on=(which); goto abort; }while(/*CONSTCOND*/0) 241 1.1 bsh 242 1.19 chs sc->sc_dev = self; 243 1.1 bsh iot = sc->sc_iot = aa->sa_iot; 244 1.1 bsh if (bus_space_map(iot, S3C2800_PCICTL_BASE, 245 1.1 bsh S3C2800_PCICTL_SIZE, 0, &sc->sc_reg_ioh)) 246 1.1 bsh FAIL("control regs"); 247 1.1 bsh 248 1.1 bsh if (bus_space_map(iot, S3C2800_PCI_CONF0_BASE, 249 1.1 bsh S3C2800_PCI_CONF0_SIZE, 0, &sc->sc_conf0_ioh)) 250 1.1 bsh FAIL("config type 0 area"); 251 1.1 bsh 252 1.1 bsh #if 0 253 1.1 bsh if (bus_space_map(iot, S3C2800_PCI_CONF1_BASE, 254 1.1 bsh S3C2800_PCI_CONF1_SIZE, 0, &sc->sc_conf1_ioh)) 255 1.1 bsh FAIL("config type 1 area"); 256 1.1 bsh #endif 257 1.1 bsh printf("\n"); 258 1.1 bsh 259 1.1 bsh SLIST_INIT(&sc->sc_irq_handlers); 260 1.4 bsh if (!s3c2800_intr_establish(S3C2800_INT_PCI, IPL_AUDIO, IST_LEVEL, 261 1.1 bsh sspci_intr, sc)) 262 1.1 bsh FAIL("intr_establish"); 263 1.1 bsh 264 1.13 matt sc->sc_softinterrupt = softint_establish(SOFTINT_SERIAL, 265 1.1 bsh sspci_softintr, sc); 266 1.1 bsh if (sc->sc_softinterrupt == NULL) 267 1.13 matt FAIL("softint_establish"); 268 1.1 bsh 269 1.1 bsh #if defined(PCI_NETBSD_CONFIGURE) 270 1.1 bsh if (sspci_init_controller(sc)) { 271 1.19 chs printf("%s: failed to initialize controller\n", device_xname(self)); 272 1.1 bsh return; 273 1.1 bsh } 274 1.1 bsh #endif 275 1.1 bsh 276 1.1 bsh sc->sc_pciinten = 277 1.1 bsh PCIINT_INA | PCIINT_SER | PCIINT_TPE | PCIINT_MPE | 278 1.1 bsh PCIINT_MFE | PCIINT_PRA | PCIINT_PRD; 279 1.1 bsh 280 1.1 bsh bus_space_write_4(iot, sc->sc_reg_ioh, PCICTL_PCIINTEN, 281 1.1 bsh sc->sc_pciinten); 282 1.1 bsh 283 1.1 bsh { 284 1.1 bsh pcireg_t id_reg, class_reg; 285 1.1 bsh char buf[1000]; 286 1.1 bsh 287 1.1 bsh id_reg = bus_space_read_4(iot, sc->sc_reg_ioh, 288 1.1 bsh PCI_ID_REG); 289 1.1 bsh class_reg = bus_space_read_4(iot, 290 1.1 bsh sc->sc_reg_ioh, PCI_CLASS_REG); 291 1.1 bsh 292 1.8 kleink pci_devinfo(id_reg, class_reg, 1, buf, sizeof(buf)); 293 1.19 chs printf("%s: %s\n", device_xname(self), buf); 294 1.1 bsh } 295 1.1 bsh 296 1.1 bsh #if defined(PCI_NETBSD_CONFIGURE) 297 1.29 thorpej pcires = pciconf_resource_init(); 298 1.1 bsh 299 1.29 thorpej pciconf_resource_add(pcires, PCICONF_RESOURCE_IO, 300 1.29 thorpej 0x100, S3C2800_PCI_IOSPACE_SIZE - 0x100); 301 1.29 thorpej pciconf_resource_add(pcires, PCICONF_RESOURCE_MEM, 302 1.29 thorpej 0, S3C2800_PCI_MEMSPACE_SIZE); 303 1.1 bsh 304 1.1 bsh sspci_chipset.pc_conf_v = (void *) sc; 305 1.1 bsh sspci_chipset.pc_intr_v = (void *) sc; 306 1.1 bsh 307 1.29 thorpej pci_configure_bus(&sspci_chipset, pcires, 0, arm_dcache_align); 308 1.1 bsh 309 1.29 thorpej pciconf_resource_fini(pcires); 310 1.1 bsh #endif /* PCI_NETBSD_CONFIGURE */ 311 1.1 bsh 312 1.1 bsh /* initialize bus space tag */ 313 1.1 bsh sspci_io_tag = *iot; 314 1.1 bsh sspci_io_tag.bs_cookie = (void *) S3C2800_PCI_IOSPACE_BASE; 315 1.1 bsh sspci_io_tag.bs_map = sspci_bs_map; 316 1.1 bsh sspci_mem_tag = *iot; 317 1.1 bsh sspci_mem_tag.bs_cookie = (void *) S3C2800_PCI_MEMSPACE_BASE; 318 1.1 bsh sspci_mem_tag.bs_map = sspci_bs_map; 319 1.1 bsh 320 1.1 bsh 321 1.1 bsh /* Platform provides PCI DMA tag */ 322 1.1 bsh pci_dma_tag = s3c2800_pci_dma_init(); 323 1.1 bsh 324 1.1 bsh pci_pba.pba_pc = &sspci_chipset; 325 1.1 bsh pci_pba.pba_iot = &sspci_io_tag; 326 1.1 bsh pci_pba.pba_memt = &sspci_mem_tag; 327 1.1 bsh pci_pba.pba_dmat = pci_dma_tag; 328 1.5 fvdl pci_pba.pba_dmat64 = NULL; 329 1.15 dyoung pci_pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY; 330 1.1 bsh pci_pba.pba_bus = 0; 331 1.1 bsh pci_pba.pba_bridgetag = NULL; 332 1.1 bsh 333 1.32 thorpej config_found(self, &pci_pba, pcibusprint, CFARGS_NONE); 334 1.1 bsh 335 1.1 bsh return; 336 1.1 bsh 337 1.1 bsh #undef FAIL 338 1.1 bsh abort: 339 1.1 bsh panic("%s: map failed (%s)", 340 1.19 chs device_xname(self), error_on); 341 1.1 bsh } 342 1.1 bsh 343 1.1 bsh 344 1.1 bsh static int 345 1.1 bsh sspci_bs_map(void *t, bus_addr_t bpa, bus_size_t size, int flag, 346 1.1 bsh bus_space_handle_t * bshp) 347 1.1 bsh { 348 1.1 bsh bus_addr_t startpa, endpa; 349 1.1 bsh vaddr_t va; 350 1.1 bsh 351 1.1 bsh #ifdef PCI_DEBUG 352 1.1 bsh printf("sspci_bs_map: t=%p, addr=%lx, size=%lx, flag=%d\n", 353 1.1 bsh t, bpa, size, flag); 354 1.1 bsh #endif 355 1.1 bsh 356 1.33 andvar /* Round the allocation to page boundaries */ 357 1.1 bsh startpa = trunc_page(bpa); 358 1.1 bsh endpa = round_page(bpa + size); 359 1.1 bsh 360 1.1 bsh /* Get some VM. */ 361 1.11 yamt va = uvm_km_alloc(kernel_map, endpa - startpa, 0, 362 1.11 yamt UVM_KMF_VAONLY | UVM_KMF_NOWAIT); 363 1.1 bsh if (va == 0) 364 1.1 bsh return ENOMEM; 365 1.1 bsh 366 1.1 bsh /* Store the bus space handle */ 367 1.1 bsh *bshp = va + (bpa & PGOFSET); 368 1.1 bsh 369 1.1 bsh /* Now map the pages */ 370 1.1 bsh /* The cookie is the physical base address for PCI I/O or memory area */ 371 1.1 bsh while (startpa < endpa) { 372 1.1 bsh /* XXX pmap_kenter_pa maps pages cacheable -- not what we 373 1.1 bsh * want. */ 374 1.1 bsh pmap_enter(pmap_kernel(), va, (bus_addr_t) t + startpa, 375 1.1 bsh VM_PROT_READ | VM_PROT_WRITE, 0); 376 1.3 thorpej va += PAGE_SIZE; 377 1.3 thorpej startpa += PAGE_SIZE; 378 1.1 bsh } 379 1.1 bsh pmap_update(pmap_kernel()); 380 1.1 bsh 381 1.1 bsh return 0; 382 1.1 bsh } 383 1.1 bsh 384 1.1 bsh 385 1.1 bsh 386 1.1 bsh void 387 1.18 matt s3c2800_pci_conf_interrupt(void *v, int bus, int dev, int ipin, int swiz, int *iline) 388 1.1 bsh { 389 1.1 bsh #ifdef PCI_DEBUG 390 1.18 matt printf("pci_conf_interrupt(v(%p), bus(%d), dev(%d), ipin(%d), swiz(%d), *iline(%p)\n", v, bus, dev, ipin, swiz, iline); 391 1.1 bsh #endif 392 1.1 bsh if (bus == 0) { 393 1.1 bsh *iline = dev; 394 1.1 bsh } else { 395 1.1 bsh panic("pci_conf_interrupt: bus=%d: not yet implemented", bus); 396 1.1 bsh } 397 1.1 bsh } 398 1.1 bsh 399 1.1 bsh void 400 1.19 chs s3c2800_pci_attach_hook(device_t parent, device_t self, 401 1.1 bsh struct pcibus_attach_args * pba) 402 1.1 bsh { 403 1.1 bsh 404 1.1 bsh /* Nothing to do. */ 405 1.1 bsh #ifdef PCI_DEBUG 406 1.1 bsh printf("s3c2800_pci_attach_hook()\n"); 407 1.1 bsh #endif 408 1.1 bsh } 409 1.1 bsh 410 1.1 bsh int 411 1.1 bsh s3c2800_pci_bus_maxdevs(void *v, int busno) 412 1.1 bsh { 413 1.1 bsh 414 1.1 bsh #ifdef PCI_DEBUG 415 1.1 bsh printf("s3c2800_pci_bus_maxdevs(v=%p, busno=%d)\n", v, busno); 416 1.1 bsh #endif 417 1.1 bsh return (32); 418 1.1 bsh } 419 1.1 bsh pcitag_t 420 1.1 bsh s3c2800_pci_make_tag(void *v, int bus, int device, int function) 421 1.1 bsh { 422 1.1 bsh 423 1.1 bsh return ((bus << BUSNO_SHIFT) | (device << DEVNO_SHIFT) | 424 1.1 bsh (function << FUNNO_SHIFT)); 425 1.1 bsh } 426 1.1 bsh 427 1.1 bsh void 428 1.1 bsh s3c2800_pci_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp) 429 1.1 bsh { 430 1.1 bsh if (bp != NULL) 431 1.1 bsh *bp = (tag >> BUSNO_SHIFT) & 0xff; 432 1.1 bsh if (dp != NULL) 433 1.1 bsh *dp = (tag >> DEVNO_SHIFT) & 0x1f; 434 1.1 bsh if (fp != NULL) 435 1.1 bsh *fp = (tag >> FUNNO_SHIFT) & 0x7; 436 1.1 bsh } 437 1.1 bsh 438 1.1 bsh static vaddr_t 439 1.1 bsh make_pci_conf_va(struct sspci_softc * sc, pcitag_t tag, int offset) 440 1.1 bsh { 441 1.22 msaitoh 442 1.22 msaitoh if ((unsigned int)offset >= PCI_CONF_SIZE) 443 1.22 msaitoh return (vaddr_t) -1; 444 1.22 msaitoh 445 1.1 bsh if ((tag & BUSNO_MASK) == 0) { 446 1.1 bsh /* configuration type 0 */ 447 1.1 bsh int devno = tag_to_devno(tag); 448 1.1 bsh 449 1.1 bsh if (devno < BUS0_DEV_MIN || BUS0_DEV_MAX < devno) 450 1.1 bsh return 0; 451 1.1 bsh 452 1.1 bsh return (vaddr_t) bus_space_vaddr(sc->sc_iot, sc->sc_conf0_ioh) + 453 1.1 bsh (tag & (DEVNO_MASK | FUNNO_MASK)) + offset; 454 1.1 bsh } else { 455 1.1 bsh /* XXX */ 456 1.1 bsh return (vaddr_t) - 1; /* cause fault */ 457 1.1 bsh } 458 1.1 bsh } 459 1.1 bsh 460 1.1 bsh 461 1.1 bsh pcireg_t 462 1.1 bsh s3c2800_pci_conf_read(void *v, pcitag_t tag, int offset) 463 1.1 bsh { 464 1.1 bsh struct sspci_softc *sc = v; 465 1.1 bsh vaddr_t va = make_pci_conf_va(sc, tag, offset); 466 1.1 bsh int s; 467 1.1 bsh pcireg_t rv; 468 1.1 bsh 469 1.1 bsh #ifdef PCI_DEBUG 470 1.1 bsh printf("s3c2800_pci_conf_read: base=%lx tag=%lx offset=%x\n", 471 1.1 bsh sc->sc_conf0_ioh, tag, offset); 472 1.1 bsh #endif 473 1.1 bsh if (va == 0) 474 1.1 bsh return -1; 475 1.1 bsh 476 1.1 bsh PCI_CONF_LOCK(s); 477 1.1 bsh 478 1.1 bsh if (badaddr_read((void *) va, sizeof(rv), &rv)) { 479 1.1 bsh #if PCI_DEBUG 480 1.1 bsh printf("conf_read: %lx bad address\n", va); 481 1.1 bsh #endif 482 1.1 bsh rv = (pcireg_t) - 1; 483 1.1 bsh } 484 1.1 bsh PCI_CONF_UNLOCK(s); 485 1.1 bsh 486 1.1 bsh return rv; 487 1.1 bsh } 488 1.1 bsh 489 1.1 bsh void 490 1.1 bsh s3c2800_pci_conf_write(void *v, pcitag_t tag, int offset, pcireg_t val) 491 1.1 bsh { 492 1.1 bsh struct sspci_softc *sc = v; 493 1.1 bsh vaddr_t va = make_pci_conf_va(sc, tag, offset); 494 1.1 bsh u_int s; 495 1.1 bsh 496 1.1 bsh #ifdef PCI_DEBUG 497 1.1 bsh printf("s3c2800_pci_conf_write: tag=%lx offset=%x -> va=%lx\n", tag, offset, va); 498 1.1 bsh #endif 499 1.1 bsh 500 1.1 bsh PCI_CONF_LOCK(s); 501 1.1 bsh 502 1.1 bsh *(pcireg_t *) va = val; 503 1.1 bsh 504 1.1 bsh PCI_CONF_UNLOCK(s); 505 1.1 bsh } 506 1.1 bsh 507 1.1 bsh void * 508 1.1 bsh s3c2800_pci_intr_establish(void *pcv, pci_intr_handle_t ih, int level, 509 1.25 jmcneill int (*func) (void *), void *arg, const char *xname) 510 1.1 bsh { 511 1.1 bsh struct sspci_softc *sc = pcv; 512 1.1 bsh struct sspci_irq_handler *handler; 513 1.1 bsh int s; 514 1.1 bsh 515 1.1 bsh #ifdef PCI_DEBUG 516 1.1 bsh printf("s3c2800_pci_intr_establish(pcv=%p, ih=0x%lx, level=%d, " 517 1.25 jmcneill "func=%p, arg=%p, xname=%s)\n", pcv, ih, level, func, arg, xname); 518 1.1 bsh #endif 519 1.1 bsh 520 1.30 thorpej handler = kmem_alloc(sizeof *handler, KM_SLEEP); 521 1.1 bsh handler->func = func; 522 1.1 bsh handler->arg = arg; 523 1.1 bsh handler->level = level; 524 1.1 bsh 525 1.1 bsh s = splhigh(); 526 1.1 bsh SLIST_INSERT_HEAD(&sc->sc_irq_handlers, handler, link); 527 1.1 bsh splx(s); 528 1.1 bsh 529 1.1 bsh return (handler); 530 1.1 bsh } 531 1.1 bsh 532 1.1 bsh void 533 1.1 bsh s3c2800_pci_intr_disestablish(void *pcv, void *cookie) 534 1.1 bsh { 535 1.1 bsh struct sspci_softc *sc = pcv; 536 1.1 bsh struct sspci_irq_handler *ih = cookie; 537 1.1 bsh int s; 538 1.1 bsh 539 1.1 bsh #ifdef PCI_DEBUG 540 1.1 bsh printf("s3c2800_pci_intr_disestablish(pcv=%p, cookie=%p)\n", 541 1.1 bsh pcv, cookie); 542 1.1 bsh #endif 543 1.1 bsh 544 1.1 bsh s = splhigh(); 545 1.1 bsh SLIST_REMOVE(&sc->sc_irq_handlers, ih, sspci_irq_handler, link); 546 1.1 bsh splx(s); 547 1.1 bsh } 548 1.1 bsh 549 1.1 bsh int 550 1.14 dyoung s3c2800_pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp) 551 1.1 bsh { 552 1.1 bsh #ifdef PCI_DEBUG 553 1.1 bsh int pin = pa->pa_intrpin; 554 1.1 bsh void *pcv = pa->pa_pc; 555 1.1 bsh pcitag_t intrtag = pa->pa_intrtag; 556 1.1 bsh int bus, device, function; 557 1.1 bsh 558 1.1 bsh s3c2800_pci_decompose_tag(pcv, intrtag, &bus, &device, &function); 559 1.1 bsh printf("s3c2800_pci_intr_map: pcv=%p, tag=%08lx pin=%d dev=%d\n", 560 1.1 bsh pcv, intrtag, pin, device); 561 1.1 bsh #endif 562 1.1 bsh 563 1.1 bsh 564 1.1 bsh /* S3C2800 has only one interrupt line for PCI */ 565 1.1 bsh *ihp = 0; 566 1.1 bsh return 0; 567 1.1 bsh } 568 1.1 bsh 569 1.1 bsh const char * 570 1.21 christos s3c2800_pci_intr_string(void *pcv, pci_intr_handle_t ih, char *buf, size_t len) 571 1.1 bsh { 572 1.1 bsh /* We have only one interrupt source from PCI */ 573 1.21 christos strlcpy(buf, "pciint", len); 574 1.21 christos return buf; 575 1.1 bsh } 576 1.1 bsh 577 1.1 bsh const struct evcnt * 578 1.1 bsh s3c2800_pci_intr_evcnt(void *pcv, pci_intr_handle_t ih) 579 1.1 bsh { 580 1.1 bsh 581 1.1 bsh /* XXX for now, no evcnt parent reported */ 582 1.1 bsh return NULL; 583 1.1 bsh } 584 1.1 bsh /* 585 1.1 bsh * Initialize PCI controller 586 1.1 bsh */ 587 1.1 bsh int 588 1.1 bsh sspci_init_controller(struct sspci_softc * sc) 589 1.1 bsh { 590 1.1 bsh bus_space_tag_t iot = sc->sc_iot; 591 1.1 bsh bus_space_handle_t ioh = sc->sc_reg_ioh; 592 1.1 bsh 593 1.1 bsh /* disable PCI command */ 594 1.1 bsh bus_space_write_4(iot, ioh, PCI_COMMAND_STATUS_REG, 595 1.1 bsh 0xffff0000); 596 1.1 bsh 597 1.1 bsh /* latency=0x10, cacheline=8 */ 598 1.1 bsh bus_space_write_4(iot, ioh, PCI_BHLC_REG, 599 1.1 bsh PCI_BHLC_CODE(0, 0, 0, 0x10, 8)); 600 1.1 bsh 601 1.1 bsh bus_space_write_4(iot, ioh, PCI_INTERRUPT_REG, 602 1.1 bsh PCI_INTERRUPT_CODE(0, 0, 0, 0)); 603 1.1 bsh 604 1.1 bsh 605 1.1 bsh 606 1.1 bsh #if 1 607 1.1 bsh bus_space_write_4(iot, ioh, PCI_MAPREG_START, 608 1.1 bsh PCI_MAPREG_MEM_TYPE_32BIT | 0x80000000); 609 1.1 bsh /* Cover all DBANKs with BAR0 */ 610 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIBAM0, 0xf8000000); 611 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIBATPA0, S3C2800_DBANK0_START); 612 1.1 bsh #else 613 1.1 bsh bus_space_write_4(iot, ioh, PCI_MAPREG_START, 614 1.1 bsh PCI_MAPREG_MEM_TYPE_32BIT | 0xf0000000); 615 1.1 bsh bus_space_write_4(iot, ioh, PCI_MAPREG_START + 4, 616 1.1 bsh PCI_MAPREG_MEM_TYPE_32BIT | 0x80000000); 617 1.1 bsh 618 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIBAM0, 0xffff0000); 619 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIBATPA0, 0xffff0000); 620 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIBAM1, 0xf1000000); 621 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIBATPA1, S3C2800_DBANK0_START); 622 1.1 bsh #endif 623 1.1 bsh 624 1.1 bsh bus_space_write_4(iot, ioh, PCI_COMMAND_STATUS_REG, 625 1.1 bsh PCI_STATUS_PARITY_DETECT | 626 1.1 bsh PCI_STATUS_SPECIAL_ERROR | 627 1.1 bsh PCI_STATUS_MASTER_ABORT | 628 1.1 bsh PCI_STATUS_MASTER_TARGET_ABORT | 629 1.1 bsh PCI_STATUS_TARGET_TARGET_ABORT | 630 1.1 bsh PCI_STATUS_DEVSEL_MEDIUM | 631 1.1 bsh PCI_STATUS_PARITY_ERROR | 632 1.1 bsh PCI_STATUS_BACKTOBACK_SUPPORT | 633 1.1 bsh PCI_STATUS_CAPLIST_SUPPORT | 634 1.1 bsh PCI_COMMAND_MASTER_ENABLE | 635 1.1 bsh PCI_COMMAND_MEM_ENABLE | 636 1.1 bsh PCI_COMMAND_IO_ENABLE); 637 1.1 bsh 638 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCICON, 639 1.1 bsh PCICON_ARB | PCICON_HST); 640 1.1 bsh 641 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCISET, 0); 642 1.1 bsh /* clear all interrupts */ 643 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIINTST, 0xffffffff); 644 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIINTEN, 0); 645 1.1 bsh 646 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCICON, 647 1.1 bsh PCICON_RDY | PCICON_CFD | PCICON_ATS | 648 1.1 bsh PCICON_ARB | PCICON_HST); 649 1.1 bsh 650 1.1 bsh 651 1.1 bsh #ifdef PCI_DEBUG 652 1.1 bsh { 653 1.1 bsh pcireg_t reg; 654 1.1 bsh int i; 655 1.1 bsh 656 1.1 bsh for (i = 0; i <= 0x40; i += sizeof(pcireg_t)) { 657 1.1 bsh reg = bus_space_read_4(iot, ioh, i); 658 1.1 bsh printf("%03x: %08x\n", i, reg); 659 1.1 bsh } 660 1.1 bsh for (i = 0x100; i <= 0x154; i += sizeof(pcireg_t)) { 661 1.1 bsh reg = bus_space_read_4(iot, ioh, i); 662 1.1 bsh printf("%03x: %08x\n", i, reg); 663 1.1 bsh } 664 1.1 bsh } 665 1.1 bsh #endif 666 1.1 bsh return 0; 667 1.1 bsh } 668 1.1 bsh 669 1.1 bsh 670 1.1 bsh static const char *pci_abnormal_error_name[] = { 671 1.1 bsh "PCI reset deasserted", 672 1.1 bsh "PCI reset asserted", 673 1.1 bsh "PCI master detected fatal error", 674 1.1 bsh "PCI master detected parity error", 675 1.1 bsh "PCI target detected parity error", 676 1.1 bsh "PCI SERR# asserted", 677 1.1 bsh }; 678 1.1 bsh 679 1.1 bsh static int 680 1.1 bsh sspci_intr(void *arg) 681 1.1 bsh { 682 1.1 bsh struct sspci_softc *sc = arg; 683 1.1 bsh int s; 684 1.1 bsh bus_space_tag_t iot = sc->sc_iot; 685 1.1 bsh bus_space_handle_t ioh = sc->sc_reg_ioh; 686 1.1 bsh uint32_t interrupts, errors; 687 1.1 bsh 688 1.1 bsh interrupts = bus_space_read_4(iot, ioh, PCICTL_PCIINTST); 689 1.1 bsh 690 1.1 bsh if (interrupts & PCIINT_INA) { 691 1.1 bsh s = splhigh(); 692 1.13 matt softint_schedule(sc->sc_softinterrupt); 693 1.1 bsh 694 1.34 andvar /* mask INTA interrupt until softinterrupt is handled */ 695 1.1 bsh sc->sc_pciinten &= ~PCIINT_INA; 696 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIINTEN, 697 1.1 bsh sc->sc_pciinten); 698 1.1 bsh 699 1.1 bsh /* acknowledge INTA interrupt */ 700 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIINTST, PCIINT_INA); 701 1.1 bsh 702 1.1 bsh splx(s); 703 1.1 bsh 704 1.1 bsh interrupts &= ~PCIINT_INA; 705 1.1 bsh 706 1.1 bsh } 707 1.1 bsh errors = interrupts & (PCIINT_SER | PCIINT_TPE | PCIINT_MPE | 708 1.1 bsh PCIINT_MFE | PCIINT_PRA | PCIINT_PRD); 709 1.1 bsh if (errors) { 710 1.1 bsh int i; 711 1.1 bsh 712 1.1 bsh for (i = 0; errors; ++i) { 713 1.1 bsh if ((errors & (1 << i)) == 0) 714 1.1 bsh continue; 715 1.1 bsh 716 1.19 chs printf("%s: %s\n", device_xname(sc->sc_dev), 717 1.1 bsh pci_abnormal_error_name[i > 4 ? 5 : i]); 718 1.1 bsh 719 1.1 bsh errors &= ~(1 << i); 720 1.1 bsh } 721 1.1 bsh /* acknowledge interrupts */ 722 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIINTST, interrupts); 723 1.1 bsh } 724 1.1 bsh return 0; 725 1.1 bsh } 726 1.1 bsh 727 1.1 bsh static void 728 1.1 bsh sspci_softintr(void *arg) 729 1.1 bsh { 730 1.1 bsh struct sspci_softc *sc = arg; 731 1.1 bsh struct sspci_irq_handler *ih; 732 1.1 bsh int s; 733 1.1 bsh 734 1.1 bsh 735 1.1 bsh SLIST_FOREACH(ih, &(sc->sc_irq_handlers), link) { 736 1.1 bsh s = _splraise(ih->level); 737 1.1 bsh ih->func(ih->arg); 738 1.1 bsh splx(s); 739 1.1 bsh } 740 1.1 bsh 741 1.1 bsh /* unmask INTA interrupt */ 742 1.1 bsh s = splhigh(); 743 1.1 bsh sc->sc_pciinten |= PCIINT_INA; 744 1.1 bsh bus_space_write_4(sc->sc_iot, sc->sc_reg_ioh, PCICTL_PCIINTEN, 745 1.1 bsh sc->sc_pciinten); 746 1.1 bsh splx(s); 747 1.1 bsh } 748