1 /* $OpenBSD: dwpcie.c,v 1.3 2018/04/05 21:41:49 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2018 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/systm.h> 20 #include <sys/device.h> 21 #include <sys/extent.h> 22 #include <sys/malloc.h> 23 24 #include <machine/intr.h> 25 #include <machine/bus.h> 26 #include <machine/fdt.h> 27 28 #include <dev/pci/pcidevs.h> 29 #include <dev/pci/pcireg.h> 30 #include <dev/pci/pcivar.h> 31 32 #include <dev/ofw/openfirm.h> 33 #include <dev/ofw/ofw_clock.h> 34 #include <dev/ofw/ofw_pinctrl.h> 35 #include <dev/ofw/fdt.h> 36 37 /* Registers */ 38 #define MISC_CONTROL_1 0x8bc 39 #define MISC_CONTROL_1_DBI_RO_WR_EN (1 << 0) 40 #define IATU_VIEWPORT 0x900 41 #define IATU_REGION_CTRL_1 0x904 42 #define IATU_REGION_CTRL_1_TYPE_CFG0 4 43 #define IATU_REGION_CTRL_1_TYPE_CFG1 5 44 #define IATU_REGION_CTRL_2 0x908 45 #define IATU_REGION_CTRL_2_REGION_EN (1U << 31) 46 #define IATU_LWR_BASE_ADDR 0x90c 47 #define IATU_UPPER_BASE_ADDR 0x910 48 #define IATU_LIMIT_ADDR 0x914 49 #define IATU_LWR_TARGET_ADDR 0x918 50 #define IATU_UPPER_TARGET_ADDR 0x91c 51 52 #define PCIE_GLOBAL_CTRL 0x8000 53 #define PCIE_GLOBAL_CTRL_APP_LTSSM_EN (1 << 2) 54 #define PCIE_GLOBAL_CTRL_DEVICE_TYPE_MASK (0xf << 4) 55 #define PCIE_GLOBAL_CTRL_DEVICE_TYPE_RC (0x4 << 4) 56 #define PCIE_GLOBAL_STATUS 0x8008 57 #define PCIE_GLOBAL_STATUS_RDLH_LINK_UP (1 << 1) 58 #define PCIE_GLOBAL_STATUS_PHY_LINK_UP (1 << 9) 59 #define PCIE_PM_STATUS 0x8014 60 #define PCIE_ARCACHE_TRC 0x8050 61 #define PCIE_ARCACHE_TRC_DEFAULT 0x3511 62 #define PCIE_AWCACHE_TRC 0x8054 63 #define PCIE_AWCACHE_TRC_DEFAULT 0x5311 64 #define PCIE_ARUSER 0x805c 65 #define PCIE_AWUSER 0x8060 66 #define PCIE_AXUSER_DOMAIN_MASK (0x3 << 4) 67 #define PCIE_AXUSER_DOMAIN_INNER_SHARABLE (0x1 << 4) 68 #define PCIE_AXUSER_DOMAIN_OUTER_SHARABLE (0x2 << 4) 69 70 #define HREAD4(sc, reg) \ 71 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) 72 #define HWRITE4(sc, reg, val) \ 73 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 74 #define HSET4(sc, reg, bits) \ 75 HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits)) 76 #define HCLR4(sc, reg, bits) \ 77 HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits)) 78 79 struct dwpcie_range { 80 uint32_t flags; 81 uint64_t pci_base; 82 uint64_t phys_base; 83 uint64_t size; 84 }; 85 86 struct dwpcie_softc { 87 struct device sc_dev; 88 bus_space_tag_t sc_iot; 89 bus_space_handle_t sc_ioh; 90 bus_space_handle_t sc_cfg_ioh; 91 bus_addr_t sc_cfg_addr; 92 bus_size_t sc_cfg_size; 93 94 int sc_node; 95 int sc_acells; 96 int sc_scells; 97 int sc_pacells; 98 int sc_pscells; 99 struct dwpcie_range *sc_ranges; 100 int sc_rangeslen; 101 102 struct arm64_pci_chipset sc_pc; 103 struct extent *sc_busex; 104 struct extent *sc_memex; 105 struct extent *sc_ioex; 106 char sc_busex_name[32]; 107 char sc_ioex_name[32]; 108 char sc_memex_name[32]; 109 int sc_bus; 110 }; 111 112 int dwpcie_match(struct device *, void *, void *); 113 void dwpcie_attach(struct device *, struct device *, void *); 114 115 struct cfattach dwpcie_ca = { 116 sizeof (struct dwpcie_softc), dwpcie_match, dwpcie_attach 117 }; 118 119 struct cfdriver dwpcie_cd = { 120 NULL, "dwpcie", DV_DULL 121 }; 122 123 int 124 dwpcie_match(struct device *parent, void *match, void *aux) 125 { 126 struct fdt_attach_args *faa = aux; 127 128 return OF_is_compatible(faa->fa_node, "marvell,armada8k-pcie"); 129 } 130 131 void dwpcie_armada8k_init(struct dwpcie_softc *); 132 int dwpcie_armada8k_link_up(struct dwpcie_softc *); 133 134 void dwpcie_attach_hook(struct device *, struct device *, 135 struct pcibus_attach_args *); 136 int dwpcie_bus_maxdevs(void *, int); 137 pcitag_t dwpcie_make_tag(void *, int, int, int); 138 void dwpcie_decompose_tag(void *, pcitag_t, int *, int *, int *); 139 int dwpcie_conf_size(void *, pcitag_t); 140 pcireg_t dwpcie_conf_read(void *, pcitag_t, int); 141 void dwpcie_conf_write(void *, pcitag_t, int, pcireg_t); 142 143 int dwpcie_intr_map(struct pci_attach_args *, pci_intr_handle_t *); 144 int dwpcie_intr_map_msi(struct pci_attach_args *, pci_intr_handle_t *); 145 int dwpcie_intr_map_msix(struct pci_attach_args *, int, 146 pci_intr_handle_t *); 147 const char *dwpcie_intr_string(void *, pci_intr_handle_t); 148 void *dwpcie_intr_establish(void *, pci_intr_handle_t, int, 149 int (*)(void *), void *, char *); 150 void dwpcie_intr_disestablish(void *, void *); 151 152 void 153 dwpcie_attach(struct device *parent, struct device *self, void *aux) 154 { 155 struct dwpcie_softc *sc = (struct dwpcie_softc *)self; 156 struct fdt_attach_args *faa = aux; 157 struct pcibus_attach_args pba; 158 uint32_t bus_range[2]; 159 uint32_t *ranges; 160 int i, j, nranges, rangeslen; 161 162 if (faa->fa_nreg < 2) { 163 printf(": no registers\n"); 164 return; 165 } 166 167 sc->sc_iot = faa->fa_iot; 168 sc->sc_node = faa->fa_node; 169 170 sc->sc_acells = OF_getpropint(sc->sc_node, "#address-cells", 171 faa->fa_acells); 172 sc->sc_scells = OF_getpropint(sc->sc_node, "#size-cells", 173 faa->fa_scells); 174 sc->sc_pacells = faa->fa_acells; 175 sc->sc_pscells = faa->fa_scells; 176 177 rangeslen = OF_getproplen(sc->sc_node, "ranges"); 178 if (rangeslen <= 0 || (rangeslen % sizeof(uint32_t)) || 179 (rangeslen / sizeof(uint32_t)) % (sc->sc_acells + 180 sc->sc_pacells + sc->sc_scells)) { 181 printf(": invalid ranges property\n"); 182 return; 183 } 184 185 ranges = malloc(rangeslen, M_TEMP, M_WAITOK); 186 OF_getpropintarray(sc->sc_node, "ranges", ranges, 187 rangeslen); 188 189 nranges = (rangeslen / sizeof(uint32_t)) / 190 (sc->sc_acells + sc->sc_pacells + sc->sc_scells); 191 sc->sc_ranges = mallocarray(nranges, 192 sizeof(struct dwpcie_range), M_TEMP, M_WAITOK); 193 sc->sc_rangeslen = nranges; 194 195 for (i = 0, j = 0; i < nranges; i++) { 196 sc->sc_ranges[i].flags = ranges[j++]; 197 sc->sc_ranges[i].pci_base = ranges[j++]; 198 if (sc->sc_acells - 1 == 2) { 199 sc->sc_ranges[i].pci_base <<= 32; 200 sc->sc_ranges[i].pci_base |= ranges[j++]; 201 } 202 sc->sc_ranges[i].phys_base = ranges[j++]; 203 if (sc->sc_pacells == 2) { 204 sc->sc_ranges[i].phys_base <<= 32; 205 sc->sc_ranges[i].phys_base |= ranges[j++]; 206 } 207 sc->sc_ranges[i].size = ranges[j++]; 208 if (sc->sc_scells == 2) { 209 sc->sc_ranges[i].size <<= 32; 210 sc->sc_ranges[i].size |= ranges[j++]; 211 } 212 } 213 214 free(ranges, M_TEMP, rangeslen); 215 216 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 217 faa->fa_reg[0].size, 0, &sc->sc_ioh)) { 218 printf(": can't map ctrl registers\n"); 219 return; 220 } 221 222 if (bus_space_map(sc->sc_iot, faa->fa_reg[1].addr, 223 faa->fa_reg[1].size, 0, &sc->sc_cfg_ioh)) { 224 bus_space_unmap(sc->sc_iot, sc->sc_ioh, faa->fa_reg[0].size); 225 printf(": can't map config registers\n"); 226 return; 227 } 228 sc->sc_cfg_addr = faa->fa_reg[1].addr; 229 sc->sc_cfg_size = faa->fa_reg[1].size; 230 231 printf("\n"); 232 233 pinctrl_byname(sc->sc_node, "default"); 234 235 clock_enable_all(sc->sc_node); 236 237 if (OF_is_compatible(sc->sc_node, "marvell,armada8k-pcie")) 238 dwpcie_armada8k_init(sc); 239 240 /* Enable modification of read-only bits. */ 241 HSET4(sc, MISC_CONTROL_1, MISC_CONTROL_1_DBI_RO_WR_EN); 242 243 /* A Root Port is a PCI-PCI Bridge. */ 244 HWRITE4(sc, PCI_CLASS_REG, 245 PCI_CLASS_BRIDGE << PCI_CLASS_SHIFT | 246 PCI_SUBCLASS_BRIDGE_PCI << PCI_SUBCLASS_SHIFT); 247 248 /* Clear BAR as U-Boot seems to leave garbage in it. */ 249 HWRITE4(sc, PCI_MAPREG_START, PCI_MAPREG_MEM_TYPE_64BIT); 250 HWRITE4(sc, PCI_MAPREG_START + 4, 0); 251 252 /* Make sure read-only bits are write-protected. */ 253 HCLR4(sc, MISC_CONTROL_1, MISC_CONTROL_1_DBI_RO_WR_EN); 254 255 /* Create extents for our address spaces. */ 256 snprintf(sc->sc_busex_name, sizeof(sc->sc_busex_name), 257 "%s pcibus", sc->sc_dev.dv_xname); 258 snprintf(sc->sc_ioex_name, sizeof(sc->sc_ioex_name), 259 "%s pciio", sc->sc_dev.dv_xname); 260 snprintf(sc->sc_memex_name, sizeof(sc->sc_memex_name), 261 "%s pcimem", sc->sc_dev.dv_xname); 262 sc->sc_busex = extent_create("pcibus", 0, 255, 263 M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 264 sc->sc_ioex = extent_create(sc->sc_ioex_name, 0, 0xffffffff, 265 M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 266 sc->sc_memex = extent_create(sc->sc_memex_name, 0, (u_long)-1, 267 M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 268 269 /* Set up bus range. */ 270 if (OF_getpropintarray(sc->sc_node, "bus-range", bus_range, 271 sizeof(bus_range)) != sizeof(bus_range) || 272 bus_range[0] >= 32 || bus_range[1] >= 32) { 273 bus_range[0] = 0; 274 bus_range[1] = 31; 275 } 276 sc->sc_bus = bus_range[0]; 277 extent_free(sc->sc_busex, bus_range[0], 278 bus_range[1] - bus_range[0] + 1, EX_WAITOK); 279 280 /* Set up memory mapped I/O range. */ 281 for (i = 0; i < nranges; i++) { 282 if ((sc->sc_ranges[i].flags & 0x03000000) == 0x02000000) 283 extent_free(sc->sc_memex, sc->sc_ranges[i].pci_base, 284 sc->sc_ranges[i].size, EX_NOWAIT); 285 } 286 287 sc->sc_pc.pc_conf_v = sc; 288 sc->sc_pc.pc_attach_hook = dwpcie_attach_hook; 289 sc->sc_pc.pc_bus_maxdevs = dwpcie_bus_maxdevs; 290 sc->sc_pc.pc_make_tag = dwpcie_make_tag; 291 sc->sc_pc.pc_decompose_tag = dwpcie_decompose_tag; 292 sc->sc_pc.pc_conf_size = dwpcie_conf_size; 293 sc->sc_pc.pc_conf_read = dwpcie_conf_read; 294 sc->sc_pc.pc_conf_write = dwpcie_conf_write; 295 296 sc->sc_pc.pc_intr_v = sc; 297 sc->sc_pc.pc_intr_map = dwpcie_intr_map; 298 sc->sc_pc.pc_intr_map_msi = dwpcie_intr_map_msi; 299 sc->sc_pc.pc_intr_map_msix = dwpcie_intr_map_msix; 300 sc->sc_pc.pc_intr_string = dwpcie_intr_string; 301 sc->sc_pc.pc_intr_establish = dwpcie_intr_establish; 302 sc->sc_pc.pc_intr_disestablish = dwpcie_intr_disestablish; 303 304 memset(&pba, 0, sizeof(pba)); 305 pba.pba_busname = "pci"; 306 pba.pba_iot = faa->fa_iot; 307 pba.pba_memt = faa->fa_iot; 308 pba.pba_dmat = faa->fa_dmat; 309 pba.pba_pc = &sc->sc_pc; 310 pba.pba_busex = sc->sc_busex; 311 pba.pba_memex = sc->sc_memex; 312 pba.pba_ioex = sc->sc_ioex; 313 pba.pba_domain = pci_ndomains++; 314 pba.pba_bus = sc->sc_bus; 315 316 config_found(self, &pba, NULL); 317 } 318 319 void 320 dwpcie_armada8k_init(struct dwpcie_softc *sc) 321 { 322 uint32_t reg; 323 int timo; 324 325 if (!dwpcie_armada8k_link_up(sc)) { 326 reg = HREAD4(sc, PCIE_GLOBAL_CTRL); 327 reg &= ~PCIE_GLOBAL_CTRL_APP_LTSSM_EN; 328 HWRITE4(sc, PCIE_GLOBAL_CTRL, reg); 329 } 330 331 /* Enable Root Complex mode. */ 332 reg = HREAD4(sc, PCIE_GLOBAL_CTRL); 333 reg &= ~PCIE_GLOBAL_CTRL_DEVICE_TYPE_MASK; 334 reg |= PCIE_GLOBAL_CTRL_DEVICE_TYPE_RC; 335 HWRITE4(sc, PCIE_GLOBAL_CTRL, reg); 336 337 HWRITE4(sc, PCIE_ARCACHE_TRC, PCIE_ARCACHE_TRC_DEFAULT); 338 HWRITE4(sc, PCIE_AWCACHE_TRC, PCIE_AWCACHE_TRC_DEFAULT); 339 reg = HREAD4(sc, PCIE_ARUSER); 340 reg &= ~PCIE_AXUSER_DOMAIN_MASK; 341 reg |= PCIE_AXUSER_DOMAIN_OUTER_SHARABLE; 342 HWRITE4(sc, PCIE_ARUSER, reg); 343 reg = HREAD4(sc, PCIE_AWUSER); 344 reg &= ~PCIE_AXUSER_DOMAIN_MASK; 345 reg |= PCIE_AXUSER_DOMAIN_OUTER_SHARABLE; 346 HWRITE4(sc, PCIE_AWUSER, reg); 347 348 /* Set up addres translation for PCI confg space. */ 349 HWRITE4(sc, IATU_VIEWPORT, 0); 350 HWRITE4(sc, IATU_LWR_BASE_ADDR, sc->sc_cfg_addr); 351 HWRITE4(sc, IATU_UPPER_BASE_ADDR, sc->sc_cfg_addr >> 32); 352 HWRITE4(sc, IATU_LIMIT_ADDR, sc->sc_cfg_addr + sc->sc_cfg_size - 1); 353 HWRITE4(sc, IATU_LWR_TARGET_ADDR, 0); 354 HWRITE4(sc, IATU_UPPER_TARGET_ADDR, 0); 355 HWRITE4(sc, IATU_REGION_CTRL_2, IATU_REGION_CTRL_2_REGION_EN); 356 357 if (!dwpcie_armada8k_link_up(sc)) { 358 reg = HREAD4(sc, PCIE_GLOBAL_CTRL); 359 reg |= PCIE_GLOBAL_CTRL_APP_LTSSM_EN; 360 HWRITE4(sc, PCIE_GLOBAL_CTRL, reg); 361 } 362 363 for (timo = 40; timo > 0; timo--) { 364 if (dwpcie_armada8k_link_up(sc)) 365 break; 366 delay(1000); 367 } 368 } 369 370 int 371 dwpcie_armada8k_link_up(struct dwpcie_softc *sc) 372 { 373 uint32_t reg, mask; 374 375 mask = PCIE_GLOBAL_STATUS_RDLH_LINK_UP; 376 mask |= PCIE_GLOBAL_STATUS_PHY_LINK_UP; 377 reg = HREAD4(sc, PCIE_GLOBAL_STATUS); 378 return ((reg & mask) == mask); 379 } 380 381 void 382 dwpcie_atu_config(struct dwpcie_softc *sc, pcitag_t tag, int type) 383 { 384 HWRITE4(sc, IATU_VIEWPORT, 0); 385 HWRITE4(sc, IATU_REGION_CTRL_1, type); 386 HWRITE4(sc, IATU_LWR_TARGET_ADDR, tag); 387 } 388 389 void 390 dwpcie_attach_hook(struct device *parent, struct device *self, 391 struct pcibus_attach_args *pba) 392 { 393 } 394 395 int 396 dwpcie_bus_maxdevs(void *v, int bus) 397 { 398 struct dwpcie_softc *sc = v; 399 400 if (bus == sc->sc_bus || bus == sc->sc_bus + 1) 401 return 1; 402 return 32; 403 } 404 405 pcitag_t 406 dwpcie_make_tag(void *v, int bus, int device, int function) 407 { 408 return ((bus << 24) | (device << 19) | (function << 16)); 409 } 410 411 void 412 dwpcie_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp) 413 { 414 if (bp != NULL) 415 *bp = (tag >> 24) & 0xff; 416 if (dp != NULL) 417 *dp = (tag >> 19) & 0x1f; 418 if (fp != NULL) 419 *fp = (tag >> 16) & 0x7; 420 } 421 422 int 423 dwpcie_conf_size(void *v, pcitag_t tag) 424 { 425 return PCIE_CONFIG_SPACE_SIZE; 426 } 427 428 pcireg_t 429 dwpcie_conf_read(void *v, pcitag_t tag, int reg) 430 { 431 struct dwpcie_softc *sc = v; 432 int bus, dev, fn; 433 434 dwpcie_decompose_tag(sc, tag, &bus, &dev, &fn); 435 if (bus == sc->sc_bus) { 436 KASSERT(dev == 0); 437 return HREAD4(sc, tag | reg); 438 } 439 440 if (bus == sc->sc_bus + 1) 441 dwpcie_atu_config(sc, tag, IATU_REGION_CTRL_1_TYPE_CFG0); 442 else 443 dwpcie_atu_config(sc, tag, IATU_REGION_CTRL_1_TYPE_CFG1); 444 return bus_space_read_4(sc->sc_iot, sc->sc_cfg_ioh, reg); 445 } 446 447 void 448 dwpcie_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) 449 { 450 struct dwpcie_softc *sc = v; 451 int bus, dev, fn; 452 453 dwpcie_decompose_tag(sc, tag, &bus, &dev, &fn); 454 if (bus == sc->sc_bus) { 455 KASSERT(dev == 0); 456 HWRITE4(sc, tag | reg, data); 457 return; 458 } 459 460 if (bus == sc->sc_bus + 1) 461 dwpcie_atu_config(sc, tag, IATU_REGION_CTRL_1_TYPE_CFG0); 462 else 463 dwpcie_atu_config(sc, tag, IATU_REGION_CTRL_1_TYPE_CFG1); 464 bus_space_write_4(sc->sc_iot, sc->sc_cfg_ioh, reg, data); 465 } 466 467 struct dwpcie_intr_handle { 468 pci_chipset_tag_t ih_pc; 469 pcitag_t ih_tag; 470 int ih_intrpin; 471 int ih_msi; 472 }; 473 474 int 475 dwpcie_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 476 { 477 struct dwpcie_intr_handle *ih; 478 int pin = pa->pa_rawintrpin; 479 480 if (pin == 0 || pin > PCI_INTERRUPT_PIN_MAX) 481 return -1; 482 483 if (pa->pa_tag == 0) 484 return -1; 485 486 ih = malloc(sizeof(struct dwpcie_intr_handle), M_DEVBUF, M_WAITOK); 487 ih->ih_pc = pa->pa_pc; 488 ih->ih_tag = pa->pa_intrtag; 489 ih->ih_intrpin = pa->pa_intrpin; 490 *ihp = (pci_intr_handle_t)ih; 491 492 return 0; 493 } 494 495 int 496 dwpcie_intr_map_msi(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 497 { 498 pci_chipset_tag_t pc = pa->pa_pc; 499 pcitag_t tag = pa->pa_tag; 500 struct dwpcie_intr_handle *ih; 501 502 if (pci_get_capability(pc, tag, PCI_CAP_MSI, NULL, NULL) == 0) 503 return -1; 504 505 ih = malloc(sizeof(struct dwpcie_intr_handle), M_DEVBUF, M_WAITOK); 506 ih->ih_pc = pa->pa_pc; 507 ih->ih_tag = pa->pa_tag; 508 ih->ih_intrpin = pa->pa_intrpin; 509 ih->ih_msi = 1; 510 *ihp = (pci_intr_handle_t)ih; 511 512 return 0; 513 } 514 515 int 516 dwpcie_intr_map_msix(struct pci_attach_args *pa, int vec, 517 pci_intr_handle_t *ihp) 518 { 519 return -1; 520 } 521 522 const char * 523 dwpcie_intr_string(void *v, pci_intr_handle_t ihp) 524 { 525 struct dwpcie_intr_handle *ih = (struct dwpcie_intr_handle *)ihp; 526 527 if (ih->ih_msi) 528 return "msi"; 529 530 return "intx"; 531 } 532 533 void * 534 dwpcie_intr_establish(void *v, pci_intr_handle_t ihp, int level, 535 int (*func)(void *), void *arg, char *name) 536 { 537 struct dwpcie_softc *sc = v; 538 struct dwpcie_intr_handle *ih = (struct dwpcie_intr_handle *)ihp; 539 void *cookie; 540 541 if (ih->ih_msi) { 542 uint64_t addr, data; 543 pcireg_t reg; 544 int off; 545 546 cookie = arm_intr_establish_fdt_msi(sc->sc_node, &addr, 547 &data, level, func, arg, (void *)name); 548 if (cookie == NULL) 549 return NULL; 550 551 /* TODO: translate address to the PCI device's view */ 552 553 if (pci_get_capability(ih->ih_pc, ih->ih_tag, PCI_CAP_MSI, 554 &off, ®) == 0) 555 panic("%s: no msi capability", __func__); 556 557 if (reg & PCI_MSI_MC_C64) { 558 pci_conf_write(ih->ih_pc, ih->ih_tag, 559 off + PCI_MSI_MA, addr); 560 pci_conf_write(ih->ih_pc, ih->ih_tag, 561 off + PCI_MSI_MAU32, addr >> 32); 562 pci_conf_write(ih->ih_pc, ih->ih_tag, 563 off + PCI_MSI_MD64, data); 564 } else { 565 pci_conf_write(ih->ih_pc, ih->ih_tag, 566 off + PCI_MSI_MA, addr); 567 pci_conf_write(ih->ih_pc, ih->ih_tag, 568 off + PCI_MSI_MD32, data); 569 } 570 pci_conf_write(ih->ih_pc, ih->ih_tag, 571 off, reg | PCI_MSI_MC_MSIE); 572 } else { 573 int bus, dev, fn; 574 uint32_t reg[4]; 575 576 dwpcie_decompose_tag(sc, ih->ih_tag, &bus, &dev, &fn); 577 578 reg[0] = bus << 16 | dev << 11 | fn << 8; 579 reg[1] = reg[2] = 0; 580 reg[3] = ih->ih_intrpin; 581 582 cookie = arm_intr_establish_fdt_imap(sc->sc_node, reg, 583 sizeof(reg), sc->sc_pacells, level, func, arg, 584 (void *)name); 585 } 586 587 free(ih, M_DEVBUF, sizeof(struct dwpcie_intr_handle)); 588 return cookie; 589 } 590 591 void 592 dwpcie_intr_disestablish(void *v, void *cookie) 593 { 594 } 595