1 /* $OpenBSD: vpci.c,v 1.4 2009/03/29 22:52:11 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2008 Mark Kettenis <kettenis@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/device.h> 20 #include <sys/errno.h> 21 #include <sys/malloc.h> 22 #include <sys/systm.h> 23 24 #include <uvm/uvm_extern.h> 25 26 #define _SPARC_BUS_DMA_PRIVATE 27 #include <machine/bus.h> 28 #include <machine/autoconf.h> 29 #include <machine/hypervisor.h> 30 #include <machine/openfirm.h> 31 32 #include <dev/pci/pcivar.h> 33 #include <dev/pci/pcireg.h> 34 35 #include <sparc64/dev/viommuvar.h> 36 37 extern struct sparc_pci_chipset _sparc_pci_chipset; 38 39 struct vpci_range { 40 u_int32_t cspace; 41 u_int32_t child_hi; 42 u_int32_t child_lo; 43 u_int32_t phys_hi; 44 u_int32_t phys_lo; 45 u_int32_t size_hi; 46 u_int32_t size_lo; 47 }; 48 49 struct vpci_pbm { 50 struct vpci_softc *vp_sc; 51 uint64_t vp_devhandle; 52 53 struct vpci_range *vp_range; 54 pci_chipset_tag_t vp_pc; 55 int vp_nrange; 56 57 bus_space_tag_t vp_memt; 58 bus_space_tag_t vp_iot; 59 bus_dma_tag_t vp_dmat; 60 struct iommu_state vp_is; 61 }; 62 63 struct vpci_softc { 64 struct device sc_dv; 65 bus_dma_tag_t sc_dmat; 66 bus_space_tag_t sc_bust; 67 }; 68 69 int vpci_match(struct device *, void *, void *); 70 void vpci_attach(struct device *, struct device *, void *); 71 void vpci_init_iommu(struct vpci_softc *, struct vpci_pbm *); 72 int vpci_print(void *, const char *); 73 74 pci_chipset_tag_t vpci_alloc_chipset(struct vpci_pbm *, int, 75 pci_chipset_tag_t); 76 bus_space_tag_t vpci_alloc_mem_tag(struct vpci_pbm *); 77 bus_space_tag_t vpci_alloc_io_tag(struct vpci_pbm *); 78 bus_space_tag_t vpci_alloc_bus_tag(struct vpci_pbm *, const char *, 79 int, int, int); 80 bus_dma_tag_t vpci_alloc_dma_tag(struct vpci_pbm *); 81 82 pcireg_t vpci_conf_read(pci_chipset_tag_t, pcitag_t, int); 83 void vpci_conf_write(pci_chipset_tag_t, pcitag_t, int, pcireg_t); 84 85 int vpci_intr_map(struct pci_attach_args *, pci_intr_handle_t *); 86 int vpci_bus_map(bus_space_tag_t, bus_space_tag_t, bus_addr_t, 87 bus_size_t, int, bus_space_handle_t *); 88 paddr_t vpci_bus_mmap(bus_space_tag_t, bus_space_tag_t, bus_addr_t, off_t, 89 int, int); 90 void *vpci_intr_establish(bus_space_tag_t, bus_space_tag_t, int, int, int, 91 int (*)(void *), void *, const char *); 92 void vpci_intr_ack(struct intrhand *); 93 94 int vpci_dmamap_create(bus_dma_tag_t, bus_dma_tag_t, bus_size_t, int, 95 bus_size_t, bus_size_t, int, bus_dmamap_t *); 96 void vpci_dmamap_destroy(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t); 97 int vpci_dmamap_load(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, 98 void *, bus_size_t, struct proc *, int); 99 void vpci_dmamap_unload(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t); 100 int vpci_dmamem_alloc(bus_dma_tag_t, bus_dma_tag_t, bus_size_t, 101 bus_size_t, bus_size_t, bus_dma_segment_t *, int, int *, int); 102 int vpci_dmamem_map(bus_dma_tag_t, bus_dma_tag_t, bus_dma_segment_t *, 103 int, size_t, caddr_t *, int); 104 void vpci_dmamem_unmap(bus_dma_tag_t, bus_dma_tag_t, caddr_t, size_t); 105 106 int 107 vpci_match(struct device *parent, void *match, void *aux) 108 { 109 struct mainbus_attach_args *ma = aux; 110 char compat[32]; 111 112 if (strcmp(ma->ma_name, "pci") != 0) 113 return (0); 114 115 if (OF_getprop(ma->ma_node, "compatible", compat, sizeof(compat)) == -1) 116 return (0); 117 118 if (strcmp(compat, "SUNW,sun4v-pci") == 0) 119 return (1); 120 121 return (0); 122 } 123 124 void 125 vpci_attach(struct device *parent, struct device *self, void *aux) 126 { 127 struct vpci_softc *sc = (struct vpci_softc *)self; 128 struct mainbus_attach_args *ma = aux; 129 struct pcibus_attach_args pba; 130 struct vpci_pbm *pbm; 131 int *busranges = NULL, nranges; 132 133 sc->sc_dmat = ma->ma_dmatag; 134 sc->sc_bust = ma->ma_bustag; 135 136 pbm = malloc(sizeof(*pbm), M_DEVBUF, M_NOWAIT | M_ZERO); 137 if (pbm == NULL) 138 panic("vpci: can't alloc vpci pbm"); 139 140 pbm->vp_sc = sc; 141 pbm->vp_devhandle = (ma->ma_reg[0].ur_paddr >> 32) & 0x0fffffff; 142 143 if (getprop(ma->ma_node, "ranges", sizeof(struct vpci_range), 144 &pbm->vp_nrange, (void **)&pbm->vp_range)) 145 panic("vpci: can't get ranges"); 146 147 if (getprop(ma->ma_node, "bus-range", sizeof(int), &nranges, 148 (void **)&busranges)) 149 panic("vpci: can't get bus-range"); 150 151 printf(": bus %d to %d, ", busranges[0], busranges[1]); 152 153 pbm->vp_memt = vpci_alloc_mem_tag(pbm); 154 pbm->vp_iot = vpci_alloc_io_tag(pbm); 155 pbm->vp_dmat = vpci_alloc_dma_tag(pbm); 156 157 pbm->vp_pc = vpci_alloc_chipset(pbm, ma->ma_node, &_sparc_pci_chipset); 158 pbm->vp_pc->bustag = pbm->vp_memt; 159 160 vpci_init_iommu(sc, pbm); 161 162 bzero(&pba, sizeof(pba)); 163 pba.pba_busname = "pci"; 164 pba.pba_domain = pci_ndomains++; 165 pba.pba_bus = busranges[0]; 166 pba.pba_pc = pbm->vp_pc; 167 pba.pba_dmat = pbm->vp_dmat; 168 pba.pba_memt = pbm->vp_memt; 169 pba.pba_iot = pbm->vp_iot; 170 pba.pba_pc->conf_read = vpci_conf_read; 171 pba.pba_pc->conf_write = vpci_conf_write; 172 pba.pba_pc->intr_map = vpci_intr_map; 173 174 free(busranges, M_DEVBUF); 175 176 config_found(&sc->sc_dv, &pba, vpci_print); 177 } 178 179 void 180 vpci_init_iommu(struct vpci_softc *sc, struct vpci_pbm *pbm) 181 { 182 struct iommu_state *is = &pbm->vp_is; 183 int tsbsize = 8; 184 u_int32_t iobase = 0x80000000; 185 char *name; 186 187 name = (char *)malloc(32, M_DEVBUF, M_NOWAIT); 188 if (name == NULL) 189 panic("couldn't malloc iommu name"); 190 snprintf(name, 32, "%s dvma", sc->sc_dv.dv_xname); 191 192 viommu_init(name, is, tsbsize, iobase); 193 is->is_devhandle = pbm->vp_devhandle; 194 } 195 196 int 197 vpci_print(void *aux, const char *p) 198 { 199 if (p == NULL) 200 return (UNCONF); 201 return (QUIET); 202 } 203 204 pcireg_t 205 vpci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) 206 { 207 struct vpci_pbm *pbm = pc->cookie; 208 uint64_t error_flag, data; 209 210 hv_pci_config_get(pbm->vp_devhandle, PCITAG_OFFSET(tag), reg, 4, 211 &error_flag, &data); 212 213 return (error_flag ? (pcireg_t)~0 : data); 214 } 215 216 void 217 vpci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) 218 { 219 struct vpci_pbm *pbm = pc->cookie; 220 uint64_t error_flag; 221 222 hv_pci_config_put(pbm->vp_devhandle, PCITAG_OFFSET(tag), reg, 4, 223 data, &error_flag); 224 } 225 226 /* 227 * Bus-specific interrupt mapping 228 */ 229 int 230 vpci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 231 { 232 struct vpci_pbm *pbm = pa->pa_pc->cookie; 233 uint64_t devhandle = pbm->vp_devhandle; 234 uint64_t devino = INTINO(*ihp); 235 uint64_t sysino; 236 int err; 237 238 if (*ihp != (pci_intr_handle_t)-1) { 239 err = hv_intr_devino_to_sysino(devhandle, devino, &sysino); 240 if (err != H_EOK) 241 return (-1); 242 243 KASSERT(sysino == INTVEC(sysino)); 244 *ihp = sysino; 245 return (0); 246 } 247 248 return (-1); 249 } 250 251 bus_space_tag_t 252 vpci_alloc_mem_tag(struct vpci_pbm *pp) 253 { 254 return (vpci_alloc_bus_tag(pp, "mem", 255 0x02, /* 32-bit mem space (where's the #define???) */ 256 ASI_PRIMARY, ASI_PRIMARY_LITTLE)); 257 } 258 259 bus_space_tag_t 260 vpci_alloc_io_tag(struct vpci_pbm *pp) 261 { 262 return (vpci_alloc_bus_tag(pp, "io", 263 0x01, /* IO space (where's the #define???) */ 264 ASI_PRIMARY, ASI_PRIMARY_LITTLE)); 265 } 266 267 bus_space_tag_t 268 vpci_alloc_bus_tag(struct vpci_pbm *pbm, const char *name, int ss, 269 int asi, int sasi) 270 { 271 struct vpci_softc *sc = pbm->vp_sc; 272 struct sparc_bus_space_tag *bt; 273 274 bt = malloc(sizeof(*bt), M_DEVBUF, M_NOWAIT | M_ZERO); 275 if (bt == NULL) 276 panic("vpci: could not allocate bus tag"); 277 278 snprintf(bt->name, sizeof(bt->name), "%s-pbm_%s(%d/%2.2x)", 279 sc->sc_dv.dv_xname, name, ss, asi); 280 281 bt->cookie = pbm; 282 bt->parent = sc->sc_bust; 283 bt->default_type = ss; 284 bt->asi = asi; 285 bt->sasi = sasi; 286 bt->sparc_bus_map = vpci_bus_map; 287 bt->sparc_bus_mmap = vpci_bus_mmap; 288 bt->sparc_intr_establish = vpci_intr_establish; 289 return (bt); 290 } 291 292 bus_dma_tag_t 293 vpci_alloc_dma_tag(struct vpci_pbm *pbm) 294 { 295 struct vpci_softc *sc = pbm->vp_sc; 296 bus_dma_tag_t dt, pdt = sc->sc_dmat; 297 298 dt = malloc(sizeof(*dt), M_DEVBUF, M_NOWAIT | M_ZERO); 299 if (dt == NULL) 300 panic("vpci: could not alloc dma tag"); 301 302 dt->_cookie = pbm; 303 dt->_parent = pdt; 304 dt->_dmamap_create = vpci_dmamap_create; 305 dt->_dmamap_destroy = viommu_dvmamap_destroy; 306 dt->_dmamap_load = viommu_dvmamap_load; 307 dt->_dmamap_load_raw = viommu_dvmamap_load_raw; 308 dt->_dmamap_unload = viommu_dvmamap_unload; 309 dt->_dmamap_sync = viommu_dvmamap_sync; 310 dt->_dmamem_alloc = viommu_dvmamem_alloc; 311 dt->_dmamem_free = viommu_dvmamem_free; 312 return (dt); 313 } 314 315 pci_chipset_tag_t 316 vpci_alloc_chipset(struct vpci_pbm *pbm, int node, pci_chipset_tag_t pc) 317 { 318 pci_chipset_tag_t npc; 319 320 npc = malloc(sizeof *npc, M_DEVBUF, M_NOWAIT); 321 if (npc == NULL) 322 panic("vpci: could not allocate pci_chipset_tag_t"); 323 memcpy(npc, pc, sizeof *pc); 324 npc->cookie = pbm; 325 npc->rootnode = node; 326 return (npc); 327 } 328 329 #define BUS_DMA_FIND_PARENT(t, fn) \ 330 if (t->_parent == NULL) \ 331 panic("null bus_dma parent (" #fn ")"); \ 332 for (t = t->_parent; t->fn == NULL; t = t->_parent) \ 333 if (t->_parent == NULL) \ 334 panic("no bus_dma " #fn " located"); 335 336 int 337 vpci_dmamap_create(bus_dma_tag_t t, bus_dma_tag_t t0, bus_size_t size, 338 int nsegments, bus_size_t maxsegsz, bus_size_t boundary, int flags, 339 bus_dmamap_t *dmamap) 340 { 341 struct vpci_pbm *vp = t->_cookie; 342 343 return (viommu_dvmamap_create(t, t0, &vp->vp_is, size, nsegments, 344 maxsegsz, boundary, flags, dmamap)); 345 } 346 347 int 348 vpci_bus_map(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t offset, 349 bus_size_t size, int flags, bus_space_handle_t *hp) 350 { 351 struct vpci_pbm *pbm = t->cookie; 352 int i, ss = t->default_type; 353 354 if (t->parent == 0 || t->parent->sparc_bus_map == 0) 355 panic("vpci_bus_map: invalid parent"); 356 357 if (flags & BUS_SPACE_MAP_PROMADDRESS) { 358 return ((*t->parent->sparc_bus_map) 359 (t, t0, offset, size, flags, hp)); 360 } 361 362 for (i = 0; i < pbm->vp_nrange; i++) { 363 bus_addr_t paddr; 364 365 if (((pbm->vp_range[i].cspace >> 24) & 0x03) != ss) 366 continue; 367 368 paddr = pbm->vp_range[i].phys_lo + offset; 369 paddr |= ((bus_addr_t)pbm->vp_range[i].phys_hi) << 32; 370 return ((*t->parent->sparc_bus_map) 371 (t, t0, paddr, size, flags, hp)); 372 } 373 374 return (EINVAL); 375 } 376 377 paddr_t 378 vpci_bus_mmap(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t paddr, 379 off_t off, int prot, int flags) 380 { 381 bus_addr_t offset = paddr; 382 struct vpci_pbm *pbm = t->cookie; 383 int i, ss = t->default_type; 384 385 if (t->parent == 0 || t->parent->sparc_bus_mmap == 0) 386 panic("vpci_bus_mmap: invalid parent"); 387 388 for (i = 0; i < pbm->vp_nrange; i++) { 389 bus_addr_t paddr; 390 391 if (((pbm->vp_range[i].cspace >> 24) & 0x03) != ss) 392 continue; 393 394 paddr = pbm->vp_range[i].phys_lo + offset; 395 paddr |= ((bus_addr_t)pbm->vp_range[i].phys_hi<<32); 396 return ((*t->parent->sparc_bus_mmap) 397 (t, t0, paddr, off, prot, flags)); 398 } 399 400 return (-1); 401 } 402 403 void * 404 vpci_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int ihandle, 405 int level, int flags, int (*handler)(void *), void *arg, const char *what) 406 { 407 uint64_t sysino = INTVEC(ihandle); 408 struct intrhand *ih; 409 int err; 410 411 ih = bus_intr_allocate(t0, handler, arg, ihandle, level, 412 NULL, NULL, what); 413 if (ih == NULL) 414 return (NULL); 415 416 intr_establish(ih->ih_pil, ih); 417 ih->ih_ack = vpci_intr_ack; 418 419 err = hv_intr_settarget(sysino, cpus->ci_upaid); 420 if (err != H_EOK) 421 return (NULL); 422 423 /* Clear pending interrupts. */ 424 err = hv_intr_setstate(sysino, INTR_IDLE); 425 if (err != H_EOK) 426 return (NULL); 427 428 err = hv_intr_setenabled(sysino, INTR_ENABLED); 429 if (err != H_EOK) 430 return (NULL); 431 432 return (ih); 433 } 434 435 void 436 vpci_intr_ack(struct intrhand *ih) 437 { 438 hv_intr_setstate(ih->ih_number, INTR_IDLE); 439 } 440 441 const struct cfattach vpci_ca = { 442 sizeof(struct vpci_softc), vpci_match, vpci_attach 443 }; 444 445 struct cfdriver vpci_cd = { 446 NULL, "vpci", DV_DULL 447 }; 448