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