| 1381 | |
| 1382 | #ifdef TEGRA_PCIB_MSI_ENABLE |
| 1383 | static int |
| 1384 | tegra_pcib_attach_msi(device_t dev) |
| 1385 | { |
| 1386 | struct tegra_pcib_softc *sc; |
| 1387 | uint32_t reg; |
| 1388 | int i, rv; |
| 1389 | |
| 1390 | sc = device_get_softc(dev); |
| 1391 | |
| 1392 | sc->msi_page = kmem_alloc_contig(PAGE_SIZE, M_WAITOK, 0, |
| 1393 | BUS_SPACE_MAXADDR, PAGE_SIZE, 0, VM_MEMATTR_DEFAULT); |
| 1394 | |
| 1395 | /* MSI BAR */ |
| 1396 | tegra_pcib_set_bar(sc, 9, vtophys(sc->msi_page), vtophys(sc->msi_page), |
| 1397 | PAGE_SIZE, 0); |
| 1398 | |
| 1399 | /* Disble and clear all interrupts. */ |
| 1400 | for (i = 0; i < AFI_MSI_REGS; i++) { |
| 1401 | AFI_WR4(sc, AFI_MSI_EN_VEC(i), 0); |
| 1402 | AFI_WR4(sc, AFI_MSI_VEC(i), 0xFFFFFFFF); |
| 1403 | } |
| 1404 | rv = bus_setup_intr(dev, sc->msi_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, |
| 1405 | tegra_pcib_msi_intr, NULL, sc, &sc->msi_intr_cookie); |
| 1406 | if (rv != 0) { |
| 1407 | device_printf(dev, "cannot setup MSI interrupt handler\n"); |
| 1408 | rv = ENXIO; |
| 1409 | goto out; |
| 1410 | } |
| 1411 | |
| 1412 | if (tegra_pcib_msi_attach(sc) != 0) { |
| 1413 | device_printf(dev, "WARNING: unable to attach PIC\n"); |
| 1414 | tegra_pcib_msi_detach(sc); |
| 1415 | goto out; |
| 1416 | } |
| 1417 | |
| 1418 | /* Unmask MSI interrupt. */ |
| 1419 | reg = AFI_RD4(sc, AFI_INTR_MASK); |
| 1420 | reg |= AFI_INTR_MASK_MSI_MASK; |
| 1421 | AFI_WR4(sc, AFI_INTR_MASK, reg); |
| 1422 | |
| 1423 | out: |
| 1424 | return (rv); |
| 1425 | } |
| 1426 | #endif |
| 1427 | |
| 1428 | static int |
no test coverage detected