Home | History | Annotate | Line # | Download | only in nvidia
tegra_pcie.c revision 1.14
      1 /* $NetBSD: tegra_pcie.c,v 1.14 2015/12/13 17:39:19 jmcneill Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2015 Jared D. McNeill <jmcneill (at) invisible.ca>
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(0, "$NetBSD: tegra_pcie.c,v 1.14 2015/12/13 17:39:19 jmcneill Exp $");
     31 
     32 #include <sys/param.h>
     33 #include <sys/bus.h>
     34 #include <sys/device.h>
     35 #include <sys/intr.h>
     36 #include <sys/systm.h>
     37 #include <sys/kernel.h>
     38 #include <sys/extent.h>
     39 #include <sys/queue.h>
     40 #include <sys/mutex.h>
     41 #include <sys/kmem.h>
     42 
     43 #include <arm/cpufunc.h>
     44 
     45 #include <dev/pci/pcireg.h>
     46 #include <dev/pci/pcivar.h>
     47 #include <dev/pci/pciconf.h>
     48 
     49 #include <arm/nvidia/tegra_reg.h>
     50 #include <arm/nvidia/tegra_pciereg.h>
     51 #include <arm/nvidia/tegra_var.h>
     52 
     53 #include <dev/fdt/fdtvar.h>
     54 
     55 static int	tegra_pcie_match(device_t, cfdata_t, void *);
     56 static void	tegra_pcie_attach(device_t, device_t, void *);
     57 
     58 #define TEGRA_PCIE_NBUS 256
     59 #define TEGRA_PCIE_ECFB (1<<(12 - 8))	/* extended conf frags per bus */
     60 
     61 struct tegra_pcie_ih {
     62 	int			(*ih_callback)(void *);
     63 	void			*ih_arg;
     64 	int			ih_ipl;
     65 	TAILQ_ENTRY(tegra_pcie_ih) ih_entry;
     66 };
     67 
     68 struct tegra_pcie_softc {
     69 	device_t		sc_dev;
     70 	bus_dma_tag_t		sc_dmat;
     71 	bus_space_tag_t		sc_bst;
     72 	bus_space_handle_t	sc_bsh_afi;
     73 	bus_space_handle_t	sc_bsh_rpconf;
     74 	int			sc_phandle;
     75 
     76 	struct arm32_pci_chipset sc_pc;
     77 
     78 	void			*sc_ih;
     79 
     80 	kmutex_t		sc_lock;
     81 
     82 	TAILQ_HEAD(, tegra_pcie_ih) sc_intrs;
     83 	u_int			sc_intrgen;
     84 
     85 	bus_space_handle_t	sc_bsh_extc[TEGRA_PCIE_NBUS-1][TEGRA_PCIE_ECFB];
     86 };
     87 
     88 static int	tegra_pcie_intr(void *);
     89 static void	tegra_pcie_init(pci_chipset_tag_t, void *);
     90 static void	tegra_pcie_enable(struct tegra_pcie_softc *);
     91 static void	tegra_pcie_setup(struct tegra_pcie_softc * const);
     92 static void	tegra_pcie_conf_frag_map(struct tegra_pcie_softc * const,
     93 					 uint, uint);
     94 static void	tegra_pcie_conf_map_bus(struct tegra_pcie_softc * const, uint);
     95 static void	tegra_pcie_conf_map_buses(struct tegra_pcie_softc * const);
     96 
     97 static void	tegra_pcie_attach_hook(device_t, device_t,
     98 				       struct pcibus_attach_args *);
     99 static int	tegra_pcie_bus_maxdevs(void *, int);
    100 static pcitag_t	tegra_pcie_make_tag(void *, int, int, int);
    101 static void	tegra_pcie_decompose_tag(void *, pcitag_t, int *, int *, int *);
    102 static pcireg_t	tegra_pcie_conf_read(void *, pcitag_t, int);
    103 static void	tegra_pcie_conf_write(void *, pcitag_t, int, pcireg_t);
    104 static int	tegra_pcie_conf_hook(void *, int, int, int, pcireg_t);
    105 static void	tegra_pcie_conf_interrupt(void *, int, int, int, int, int *);
    106 
    107 static int	tegra_pcie_intr_map(const struct pci_attach_args *,
    108 				    pci_intr_handle_t *);
    109 static const char *tegra_pcie_intr_string(void *, pci_intr_handle_t,
    110 					  char *, size_t);
    111 const struct evcnt *tegra_pcie_intr_evcnt(void *, pci_intr_handle_t);
    112 static void *	tegra_pcie_intr_establish(void *, pci_intr_handle_t,
    113 					 int, int (*)(void *), void *);
    114 static void	tegra_pcie_intr_disestablish(void *, void *);
    115 
    116 CFATTACH_DECL_NEW(tegra_pcie, sizeof(struct tegra_pcie_softc),
    117 	tegra_pcie_match, tegra_pcie_attach, NULL, NULL);
    118 
    119 static int
    120 tegra_pcie_match(device_t parent, cfdata_t cf, void *aux)
    121 {
    122 	const char * const compatible[] = { "nvidia,tegra124-pcie", NULL };
    123 	struct fdt_attach_args * const faa = aux;
    124 
    125 	return of_match_compatible(faa->faa_phandle, compatible);
    126 }
    127 
    128 static void
    129 tegra_pcie_attach(device_t parent, device_t self, void *aux)
    130 {
    131 	struct tegra_pcie_softc * const sc = device_private(self);
    132 	struct fdt_attach_args * const faa = aux;
    133 	struct extent *ioext, *memext, *pmemext;
    134 	struct pcibus_attach_args pba;
    135 	bus_addr_t afi_addr, cs_addr;
    136 	bus_size_t afi_size, cs_size;
    137 	char intrstr[128];
    138 	int error;
    139 
    140 	if (fdtbus_get_reg(faa->faa_phandle, 1, &afi_addr, &afi_size) != 0) {
    141 		aprint_error(": couldn't get afi registers\n");
    142 		return;
    143 	}
    144 #if notyet
    145 	if (fdtbus_get_reg(faa->faa_phandle, 2, &cs_addr, &cs_size) != 0) {
    146 		aprint_error(": couldn't get cs registers\n");
    147 		return;
    148 	}
    149 #else
    150 	cs_addr = TEGRA_PCIE_RPCONF_BASE;
    151 	cs_size = TEGRA_PCIE_RPCONF_SIZE;
    152 #endif
    153 
    154 	sc->sc_dev = self;
    155 	sc->sc_dmat = faa->faa_dmat;
    156 	sc->sc_bst = faa->faa_bst;
    157 	sc->sc_phandle = faa->faa_phandle;
    158 	error = bus_space_map(sc->sc_bst, afi_addr, afi_size, 0,
    159 	    &sc->sc_bsh_afi);
    160 	if (error) {
    161 		aprint_error(": couldn't map afi registers: %d\n", error);
    162 		return;
    163 	}
    164 	error = bus_space_map(sc->sc_bst, cs_addr, cs_size, 0,
    165 	    &sc->sc_bsh_rpconf);
    166 	if (error) {
    167 		aprint_error(": couldn't map cs registers: %d\n", error);
    168 		return;
    169 	}
    170 
    171 	tegra_pcie_conf_map_buses(sc);
    172 
    173 	TAILQ_INIT(&sc->sc_intrs);
    174 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM);
    175 
    176 	aprint_naive("\n");
    177 	aprint_normal(": PCIE\n");
    178 
    179 	if (!fdtbus_intr_str(faa->faa_phandle, 0, intrstr, sizeof(intrstr))) {
    180 		aprint_error_dev(self, "failed to decode interrupt\n");
    181 		return;
    182 	}
    183 
    184 	sc->sc_ih = fdtbus_intr_establish(faa->faa_phandle, 0, IPL_VM, 0,
    185 	    tegra_pcie_intr, sc);
    186 	if (sc->sc_ih == NULL) {
    187 		aprint_error_dev(self, "failed to establish interrupt on %s\n",
    188 		    intrstr);
    189 		return;
    190 	}
    191 	aprint_normal_dev(self, "interrupting on %s\n", intrstr);
    192 
    193 	tegra_pcie_setup(sc);
    194 
    195 	tegra_pcie_init(&sc->sc_pc, sc);
    196 
    197 	ioext = extent_create("pciio", TEGRA_PCIE_IO_BASE,
    198 	    TEGRA_PCIE_IO_BASE + TEGRA_PCIE_IO_SIZE - 1,
    199 	    NULL, 0, EX_NOWAIT);
    200 	memext = extent_create("pcimem", TEGRA_PCIE_MEM_BASE,
    201 	    TEGRA_PCIE_MEM_BASE + TEGRA_PCIE_MEM_SIZE - 1,
    202 	    NULL, 0, EX_NOWAIT);
    203 	pmemext = extent_create("pcipmem", TEGRA_PCIE_PMEM_BASE,
    204 	    TEGRA_PCIE_PMEM_BASE + TEGRA_PCIE_PMEM_SIZE - 1,
    205 	    NULL, 0, EX_NOWAIT);
    206 
    207 	error = pci_configure_bus(&sc->sc_pc, ioext, memext, pmemext, 0,
    208 	    arm_dcache_align);
    209 
    210 	extent_destroy(ioext);
    211 	extent_destroy(memext);
    212 	extent_destroy(pmemext);
    213 
    214 	if (error) {
    215 		aprint_error_dev(self, "configuration failed (%d)\n",
    216 		    error);
    217 		return;
    218 	}
    219 
    220 	tegra_pcie_enable(sc);
    221 
    222 	memset(&pba, 0, sizeof(pba));
    223 	pba.pba_flags = PCI_FLAGS_MRL_OKAY |
    224 			PCI_FLAGS_MRM_OKAY |
    225 			PCI_FLAGS_MWI_OKAY |
    226 			PCI_FLAGS_MEM_OKAY |
    227 			PCI_FLAGS_IO_OKAY;
    228 	pba.pba_iot = sc->sc_bst;
    229 	pba.pba_memt = sc->sc_bst;
    230 	pba.pba_dmat = sc->sc_dmat;
    231 	pba.pba_pc = &sc->sc_pc;
    232 	pba.pba_bus = 0;
    233 
    234 	config_found_ia(self, "pcibus", &pba, pcibusprint);
    235 }
    236 
    237 static int
    238 tegra_pcie_legacy_intr(struct tegra_pcie_softc *sc)
    239 {
    240 	const uint32_t msg = bus_space_read_4(sc->sc_bst, sc->sc_bsh_afi,
    241 	    AFI_MSG_REG);
    242 	struct tegra_pcie_ih *pcie_ih;
    243 	int rv = 0;
    244 
    245 	if (msg & (AFI_MSG_INT0|AFI_MSG_INT1)) {
    246 		mutex_enter(&sc->sc_lock);
    247 		const u_int lastgen = sc->sc_intrgen;
    248 		TAILQ_FOREACH(pcie_ih, &sc->sc_intrs, ih_entry) {
    249 			int (*callback)(void *) = pcie_ih->ih_callback;
    250 			void *arg = pcie_ih->ih_arg;
    251 			mutex_exit(&sc->sc_lock);
    252 			rv += callback(arg);
    253 			mutex_enter(&sc->sc_lock);
    254 			if (lastgen != sc->sc_intrgen)
    255 				break;
    256 		}
    257 		mutex_exit(&sc->sc_lock);
    258 	} else if (msg & (AFI_MSG_PM_PME0|AFI_MSG_PM_PME1)) {
    259 		device_printf(sc->sc_dev, "PM PME message; AFI_MSG=%08x\n",
    260 		    msg);
    261 	} else {
    262 		bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_MSG_REG, msg);
    263 		rv = 1;
    264 	}
    265 
    266 	return rv;
    267 }
    268 
    269 static int
    270 tegra_pcie_intr(void *priv)
    271 {
    272 	struct tegra_pcie_softc *sc = priv;
    273 	int rv;
    274 
    275 	const uint32_t code = bus_space_read_4(sc->sc_bst, sc->sc_bsh_afi,
    276 	    AFI_INTR_CODE_REG);
    277 	const uint32_t sig = bus_space_read_4(sc->sc_bst, sc->sc_bsh_afi,
    278 	    AFI_INTR_SIGNATURE_REG);
    279 
    280 	switch (__SHIFTOUT(code, AFI_INTR_CODE_INT_CODE)) {
    281 	case AFI_INTR_CODE_SM_MSG:
    282 		rv = tegra_pcie_legacy_intr(sc);
    283 		break;
    284 	default:
    285 		device_printf(sc->sc_dev, "intr: code %#x sig %#x\n",
    286 		    code, sig);
    287 		rv = 1;
    288 		break;
    289 	}
    290 
    291 	bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_INTR_CODE_REG, 0);
    292 
    293 	return rv;
    294 }
    295 
    296 static void
    297 tegra_pcie_setup(struct tegra_pcie_softc * const sc)
    298 {
    299 	size_t i;
    300 
    301 	/*
    302 	 * Map PCI address spaces into ARM address space via
    303 	 * HyperTransport-like "FPCI".
    304 	 */
    305 	static const struct { uint32_t size, base, fpci; } pcie_init_table[] = {
    306 		/*
    307 		 * === BEWARE ===
    308 		 *
    309 		 * We depend on our TEGRA_PCIE_IO window overlaping the
    310 		 * TEGRA_PCIE_A1 window to allow us to use the same
    311 		 * bus_space_tag for both PCI IO and Memory spaces.
    312 		 *
    313 		 * 0xfdfc000000-0xfdfdffffff is the FPCI/HyperTransport
    314 		 * mapping for 0x0000000-0x1ffffff of PCI IO space.
    315 		 */
    316 		{ TEGRA_PCIE_IO_SIZE >> 12, TEGRA_PCIE_IO_BASE,
    317 		  (0xfdfc000000 + TEGRA_PCIE_IO_BASE) >> 8 | 0, },
    318 
    319 		/* HyperTransport Technology Type 1 Address Format */
    320 		{ TEGRA_PCIE_CONF_SIZE >> 12, TEGRA_PCIE_CONF_BASE,
    321 		  0xfdff000000 >> 8 | 0, },
    322 
    323 		/* 1:1 MMIO mapping */
    324 		{ TEGRA_PCIE_MEM_SIZE >> 12, TEGRA_PCIE_MEM_BASE,
    325 		  TEGRA_PCIE_MEM_BASE >> 8 | 1, },
    326 
    327 		/* Extended HyperTransport Technology Type 1 Address Format */
    328 		{ TEGRA_PCIE_EXTC_SIZE >> 12, TEGRA_PCIE_EXTC_BASE,
    329 		  0xfe10000000 >> 8 | 0, },
    330 
    331 		/* 1:1 prefetchable MMIO mapping */
    332 		{ TEGRA_PCIE_PMEM_SIZE >> 12, TEGRA_PCIE_PMEM_BASE,
    333 		  TEGRA_PCIE_PMEM_BASE >> 8 | 1, },
    334 	};
    335 
    336 	for (i = 0; i < AFI_AXI_NBAR; i++) {
    337 		bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi,
    338 		    AFI_AXI_BARi_SZ(i), 0);
    339 		bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi,
    340 		    AFI_AXI_BARi_START(i), 0);
    341 		bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi,
    342 		    AFI_FPCI_BARi(i), 0);
    343 	}
    344 
    345 	for (i = 0; i < __arraycount(pcie_init_table); i++) {
    346 		bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi,
    347 		    AFI_AXI_BARi_START(i), pcie_init_table[i].base);
    348 		bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi,
    349 		    AFI_FPCI_BARi(i), pcie_init_table[i].fpci);
    350 		bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi,
    351 		    AFI_AXI_BARi_SZ(i), pcie_init_table[i].size);
    352 	}
    353 }
    354 
    355 static void
    356 tegra_pcie_enable(struct tegra_pcie_softc *sc)
    357 {
    358 	/* disable MSI */
    359 	bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi,
    360 	    AFI_MSI_BAR_SZ_REG, 0);
    361 	bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi,
    362 	    AFI_MSI_FPCI_BAR_ST_REG, 0);
    363 	bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi,
    364 	    AFI_MSI_AXI_BAR_ST_REG, 0);
    365 
    366 	bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi,
    367 	    AFI_SM_INTR_ENABLE_REG, 0xffffffff);
    368 	bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi,
    369 	    AFI_AFI_INTR_ENABLE_REG, 0);
    370 	bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_INTR_CODE_REG, 0);
    371 	bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi,
    372 	    AFI_INTR_MASK_REG, AFI_INTR_MASK_INT);
    373 }
    374 
    375 static void
    376 tegra_pcie_conf_frag_map(struct tegra_pcie_softc * const sc, uint bus,
    377     uint frg)
    378 {
    379 	bus_addr_t a;
    380 
    381 	KASSERT(bus >= 1);
    382 	KASSERT(bus < TEGRA_PCIE_NBUS);
    383 	KASSERT(frg < TEGRA_PCIE_ECFB);
    384 
    385 	if (sc->sc_bsh_extc[bus-1][frg] != 0) {
    386 		device_printf(sc->sc_dev, "bus %u fragment %#x already "
    387 		    "mapped\n", bus, frg);
    388 		return;
    389 	}
    390 
    391 	a = TEGRA_PCIE_EXTC_BASE + (bus << 16) + (frg << 24);
    392 	if (bus_space_map(sc->sc_bst, a, 1 << 16, 0,
    393 	    &sc->sc_bsh_extc[bus-1][frg]) != 0)
    394 		device_printf(sc->sc_dev, "couldn't map PCIE "
    395 		    "configuration for bus %u fragment %#x", bus, frg);
    396 }
    397 
    398 /* map non-non-extended configuration space for full bus range */
    399 static void
    400 tegra_pcie_conf_map_bus(struct tegra_pcie_softc * const sc, uint bus)
    401 {
    402 	uint i;
    403 
    404 	for (i = 1; i < TEGRA_PCIE_ECFB; i++) {
    405 		tegra_pcie_conf_frag_map(sc, bus, i);
    406 	}
    407 }
    408 
    409 /* map non-extended configuration space for full bus range */
    410 static void
    411 tegra_pcie_conf_map_buses(struct tegra_pcie_softc * const sc)
    412 {
    413 	uint b;
    414 
    415 	for (b = 1; b < TEGRA_PCIE_NBUS; b++) {
    416 		tegra_pcie_conf_frag_map(sc, b, 0);
    417 	}
    418 }
    419 
    420 void
    421 tegra_pcie_init(pci_chipset_tag_t pc, void *priv)
    422 {
    423 	pc->pc_conf_v = priv;
    424 	pc->pc_attach_hook = tegra_pcie_attach_hook;
    425 	pc->pc_bus_maxdevs = tegra_pcie_bus_maxdevs;
    426 	pc->pc_make_tag = tegra_pcie_make_tag;
    427 	pc->pc_decompose_tag = tegra_pcie_decompose_tag;
    428 	pc->pc_conf_read = tegra_pcie_conf_read;
    429 	pc->pc_conf_write = tegra_pcie_conf_write;
    430 	pc->pc_conf_hook = tegra_pcie_conf_hook;
    431 	pc->pc_conf_interrupt = tegra_pcie_conf_interrupt;
    432 
    433 	pc->pc_intr_v = priv;
    434 	pc->pc_intr_map = tegra_pcie_intr_map;
    435 	pc->pc_intr_string = tegra_pcie_intr_string;
    436 	pc->pc_intr_evcnt = tegra_pcie_intr_evcnt;
    437 	pc->pc_intr_establish = tegra_pcie_intr_establish;
    438 	pc->pc_intr_disestablish = tegra_pcie_intr_disestablish;
    439 }
    440 
    441 static void
    442 tegra_pcie_attach_hook(device_t parent, device_t self,
    443     struct pcibus_attach_args *pba)
    444 {
    445 	const pci_chipset_tag_t pc = pba->pba_pc;
    446 	struct tegra_pcie_softc * const sc = pc->pc_conf_v;
    447 
    448 	if (pba->pba_bus >= 1) {
    449 		tegra_pcie_conf_map_bus(sc, pba->pba_bus);
    450 	}
    451 }
    452 
    453 static int
    454 tegra_pcie_bus_maxdevs(void *v, int busno)
    455 {
    456 	return busno == 0 ? 2 : 32;
    457 }
    458 
    459 static pcitag_t
    460 tegra_pcie_make_tag(void *v, int b, int d, int f)
    461 {
    462 	return (b << 16) | (d << 11) | (f << 8);
    463 }
    464 
    465 static void
    466 tegra_pcie_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp)
    467 {
    468 	if (bp)
    469 		*bp = (tag >> 16) & 0xff;
    470 	if (dp)
    471 		*dp = (tag >> 11) & 0x1f;
    472 	if (fp)
    473 		*fp = (tag >> 8) & 0x7;
    474 }
    475 
    476 static pcireg_t
    477 tegra_pcie_conf_read(void *v, pcitag_t tag, int offset)
    478 {
    479 	struct tegra_pcie_softc *sc = v;
    480 	bus_space_handle_t bsh;
    481 	int b, d, f;
    482 	u_int reg;
    483 
    484 	if ((unsigned int)offset >= PCI_EXTCONF_SIZE)
    485 		return (pcireg_t) -1;
    486 
    487 	tegra_pcie_decompose_tag(v, tag, &b, &d, &f);
    488 
    489 	if (b >= TEGRA_PCIE_NBUS)
    490 		return (pcireg_t) -1;
    491 
    492 	if (b == 0) {
    493 		if (d >= 2 || f != 0)
    494 			return (pcireg_t) -1;
    495 		reg = d * 0x1000 + offset;
    496 		bsh = sc->sc_bsh_rpconf;
    497 	} else {
    498 		reg = (d << 11) | (f << 8) | (offset & 0xff);
    499 		bsh = sc->sc_bsh_extc[b-1][(offset >> 8) & 0xf];
    500 		if (bsh == 0)
    501 			return (pcireg_t) -1;
    502 	}
    503 
    504 	return bus_space_read_4(sc->sc_bst, bsh, reg);
    505 }
    506 
    507 static void
    508 tegra_pcie_conf_write(void *v, pcitag_t tag, int offset, pcireg_t val)
    509 {
    510 	struct tegra_pcie_softc *sc = v;
    511 	bus_space_handle_t bsh;
    512 	int b, d, f;
    513 	u_int reg;
    514 
    515 	if ((unsigned int)offset >= PCI_EXTCONF_SIZE)
    516 		return;
    517 
    518 	tegra_pcie_decompose_tag(v, tag, &b, &d, &f);
    519 
    520 	if (b >= TEGRA_PCIE_NBUS)
    521 		return;
    522 
    523 	if (b == 0) {
    524 		if (d >= 2 || f != 0)
    525 			return;
    526 		reg = d * 0x1000 + offset;
    527 		bsh = sc->sc_bsh_rpconf;
    528 	} else {
    529 		reg = (d << 11) | (f << 8) | (offset & 0xff);
    530 		bsh = sc->sc_bsh_extc[b-1][(offset >> 8) & 0xf];
    531 		if (bsh == 0)
    532 			return;
    533 	}
    534 
    535 	bus_space_write_4(sc->sc_bst, bsh, reg, val);
    536 }
    537 
    538 static int
    539 tegra_pcie_conf_hook(void *v, int b, int d, int f, pcireg_t id)
    540 {
    541 	return PCI_CONF_ALL;
    542 }
    543 
    544 static void
    545 tegra_pcie_conf_interrupt(void *v, int bus, int dev, int ipin, int swiz,
    546     int *ilinep)
    547 {
    548 	*ilinep = 5;
    549 }
    550 
    551 static int
    552 tegra_pcie_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ih)
    553 {
    554 	if (pa->pa_intrpin == 0)
    555 		return EINVAL;
    556 	*ih = pa->pa_intrpin;
    557 	return 0;
    558 }
    559 
    560 static const char *
    561 tegra_pcie_intr_string(void *v, pci_intr_handle_t ih, char *buf, size_t len)
    562 {
    563 	struct tegra_pcie_softc *sc = v;
    564 
    565 	if (ih == PCI_INTERRUPT_PIN_NONE)
    566 		return NULL;
    567 
    568 	if (!fdtbus_intr_str(sc->sc_phandle, 0, buf, len))
    569 		return NULL;
    570 
    571 	return buf;
    572 }
    573 
    574 const struct evcnt *
    575 tegra_pcie_intr_evcnt(void *v, pci_intr_handle_t ih)
    576 {
    577 	return NULL;
    578 }
    579 
    580 static void *
    581 tegra_pcie_intr_establish(void *v, pci_intr_handle_t ih, int ipl,
    582     int (*callback)(void *), void *arg)
    583 {
    584 	struct tegra_pcie_softc *sc = v;
    585 	struct tegra_pcie_ih *pcie_ih;
    586 
    587 	if (ih == 0)
    588 		return NULL;
    589 
    590 	pcie_ih = kmem_alloc(sizeof(*pcie_ih), KM_SLEEP);
    591 	pcie_ih->ih_callback = callback;
    592 	pcie_ih->ih_arg = arg;
    593 	pcie_ih->ih_ipl = ipl;
    594 
    595 	mutex_enter(&sc->sc_lock);
    596 	TAILQ_INSERT_TAIL(&sc->sc_intrs, pcie_ih, ih_entry);
    597 	sc->sc_intrgen++;
    598 	mutex_exit(&sc->sc_lock);
    599 
    600 	return pcie_ih;
    601 }
    602 
    603 static void
    604 tegra_pcie_intr_disestablish(void *v, void *vih)
    605 {
    606 	struct tegra_pcie_softc *sc = v;
    607 	struct tegra_pcie_ih *pcie_ih = vih;
    608 
    609 	mutex_enter(&sc->sc_lock);
    610 	TAILQ_REMOVE(&sc->sc_intrs, pcie_ih, ih_entry);
    611 	mutex_exit(&sc->sc_lock);
    612 
    613 	kmem_free(pcie_ih, sizeof(*pcie_ih));
    614 }
    615