Module Name:    src
Committed By:   jmcneill
Date:           Sun May  3 01:07:44 UTC 2015

Modified Files:
        src/sys/arch/arm/nvidia: files.tegra tegra_intr.h tegra_io.c
            tegra_reg.h tegra_soc.c tegra_var.h
        src/sys/arch/evbarm/conf: JETSONTK1 std.tegra
        src/sys/arch/evbarm/tegra: tegra_machdep.c
Added Files:
        src/sys/arch/arm/nvidia: tegra_pcie.c tegra_pciereg.h

Log Message:
Add Tegra K1 PCIE support.


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/arm/nvidia/files.tegra \
    src/sys/arch/arm/nvidia/tegra_reg.h
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/nvidia/tegra_intr.h
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/nvidia/tegra_io.c \
    src/sys/arch/arm/nvidia/tegra_soc.c
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/nvidia/tegra_pcie.c \
    src/sys/arch/arm/nvidia/tegra_pciereg.h
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/arm/nvidia/tegra_var.h
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/evbarm/conf/JETSONTK1
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/evbarm/conf/std.tegra
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/evbarm/tegra/tegra_machdep.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/nvidia/files.tegra
diff -u src/sys/arch/arm/nvidia/files.tegra:1.5 src/sys/arch/arm/nvidia/files.tegra:1.6
--- src/sys/arch/arm/nvidia/files.tegra:1.5	Sat May  2 17:15:20 2015
+++ src/sys/arch/arm/nvidia/files.tegra	Sun May  3 01:07:44 2015
@@ -1,4 +1,4 @@
-#	$NetBSD: files.tegra,v 1.5 2015/05/02 17:15:20 jmcneill Exp $
+#	$NetBSD: files.tegra,v 1.6 2015/05/03 01:07:44 jmcneill Exp $
 #
 # Configuration info for NVIDIA Tegra ARM Peripherals
 #
@@ -53,6 +53,11 @@ file	arch/arm/nvidia/tegra_ehci.c		tegra
 attach	sdhc at tegraio with tegra_sdhc
 file	arch/arm/nvidia/tegra_sdhc.c		tegra_sdhc
 
+# PCIE
+device	tegrapcie: pcibus
+attach	tegrapcie at tegraio with tegra_pcie
+file	arch/arm/nvidia/tegra_pcie.c		tegra_pcie
+
 # SATA
 attach	ahcisata at tegraio with tegra_ahcisata
 file	arch/arm/nvidia/tegra_ahcisata.c	tegra_ahcisata
Index: src/sys/arch/arm/nvidia/tegra_reg.h
diff -u src/sys/arch/arm/nvidia/tegra_reg.h:1.5 src/sys/arch/arm/nvidia/tegra_reg.h:1.6
--- src/sys/arch/arm/nvidia/tegra_reg.h:1.5	Sat May  2 12:08:32 2015
+++ src/sys/arch/arm/nvidia/tegra_reg.h	Sun May  3 01:07:44 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_reg.h,v 1.5 2015/05/02 12:08:32 jmcneill Exp $ */
+/* $NetBSD: tegra_reg.h,v 1.6 2015/05/03 01:07:44 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <[email protected]>
@@ -33,6 +33,24 @@
 
 #define TEGRA_EXTMEM_BASE	0x80000000
 
+#define TEGRA_PCIE_OFFSET	0x01000000
+#define TEGRA_PCIE_SIZE		0x3effffff
+#define TEGRA_PCIE_PADS_BASE	0x01003000
+#define TEGRA_PCIE_PADS_SIZE	0x00000800
+#define TEGRA_PCIE_AFI_BASE	0x01003800
+#define TEGRA_PCIE_AFI_SIZE	0x00000800
+#define TEGRA_PCIE_A1_BASE	0x01000000
+#define TEGRA_PCIE_A1_SIZE	0x00002000
+#define TEGRA_PCIE_A2_BASE	0x02000000
+#define TEGRA_PCIE_A2_SIZE	0x01000000
+
+#define TEGRA_PCIE_IO_BASE	0x12000000
+#define TEGRA_PCIE_IO_SIZE	0x00010000
+#define TEGRA_PCIE_MEM_BASE	0x13000000
+#define TEGRA_PCIE_MEM_SIZE	0x0d000000
+#define TEGRA_PCIE_PMEM_BASE	0x20000000
+#define TEGRA_PCIE_PMEM_SIZE	0x20000000
+
 #define TEGRA_HOST1X_BASE	0x50000000
 #define TEGRA_HOST1X_SIZE	0x00100000
 #define TEGRA_PPSB_BASE		0x60000000

Index: src/sys/arch/arm/nvidia/tegra_intr.h
diff -u src/sys/arch/arm/nvidia/tegra_intr.h:1.2 src/sys/arch/arm/nvidia/tegra_intr.h:1.3
--- src/sys/arch/arm/nvidia/tegra_intr.h:1.2	Sun Mar 29 10:44:54 2015
+++ src/sys/arch/arm/nvidia/tegra_intr.h	Sun May  3 01:07:44 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_intr.h,v 1.2 2015/03/29 10:44:54 jmcneill Exp $ */
+/* $NetBSD: tegra_intr.h,v 1.3 2015/05/03 01:07:44 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <[email protected]>
@@ -50,5 +50,8 @@
 #define TEGRA_INTR_HDA		TEGRA_INTR(81)
 #define TEGRA_INTR_UARTD	TEGRA_INTR(90)
 #define TEGRA_INTR_USB3		TEGRA_INTR(97)
+#define TEGRA_INTR_PCIE_INT	TEGRA_INTR(98)
+#define TEGRA_INTR_PCIE_MSI	TEGRA_INTR(99)
+#define TEGRA_INTR_PCIE_WAKE	TEGRA_INTR(100)
 
 #endif /* _ARM_TEGRA_INTR_H */

Index: src/sys/arch/arm/nvidia/tegra_io.c
diff -u src/sys/arch/arm/nvidia/tegra_io.c:1.4 src/sys/arch/arm/nvidia/tegra_io.c:1.5
--- src/sys/arch/arm/nvidia/tegra_io.c:1.4	Sat May  2 12:08:32 2015
+++ src/sys/arch/arm/nvidia/tegra_io.c	Sun May  3 01:07:44 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_io.c,v 1.4 2015/05/02 12:08:32 jmcneill Exp $ */
+/* $NetBSD: tegra_io.c,v 1.5 2015/05/03 01:07:44 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <[email protected]>
@@ -29,7 +29,7 @@
 #include "opt_tegra.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_io.c,v 1.4 2015/05/02 12:08:32 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_io.c,v 1.5 2015/05/03 01:07:44 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -104,6 +104,11 @@ static const struct tegra_locators tegra
     TEGRA_USB3_OFFSET, TEGRA_USB3_SIZE, 2, TEGRA_INTR_USB3 },
 };
 
+static const struct tegra_locators tegra_pcie_locators[] = {
+  { "tegrapcie",
+    TEGRA_PCIE_OFFSET, TEGRA_PCIE_SIZE, NOPORT, TEGRA_INTR_PCIE_INT },
+};
+
 int
 tegraio_match(device_t parent, cfdata_t cf, void *aux)
 {
@@ -126,6 +131,8 @@ tegraio_attach(device_t parent, device_t
 	    tegra_apb_locators, __arraycount(tegra_apb_locators));
 	tegraio_scan(self, tegra_ahb_a2_bsh,
 	    tegra_ahb_a2_locators, __arraycount(tegra_ahb_a2_locators));
+	tegraio_scan(self, (bus_space_handle_t)NULL,
+	    tegra_pcie_locators, __arraycount(tegra_pcie_locators));
 }
 
 static void
@@ -140,6 +147,7 @@ tegraio_scan(device_t self, bus_space_ha
 			.tio_a4x_bst = &armv7_generic_a4x_bs_tag,
 			.tio_bsh = bsh,
 			.tio_dmat = &tegra_dma_tag,
+			.tio_coherent_dmat = &tegra_coherent_dma_tag,
 		};
 		cfdata_t cf = config_search_ia(tegraio_find, self,
 		    "tegraio", &tio);
Index: src/sys/arch/arm/nvidia/tegra_soc.c
diff -u src/sys/arch/arm/nvidia/tegra_soc.c:1.4 src/sys/arch/arm/nvidia/tegra_soc.c:1.5
--- src/sys/arch/arm/nvidia/tegra_soc.c:1.4	Tue Apr 28 11:15:55 2015
+++ src/sys/arch/arm/nvidia/tegra_soc.c	Sun May  3 01:07:44 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_soc.c,v 1.4 2015/04/28 11:15:55 jmcneill Exp $ */
+/* $NetBSD: tegra_soc.c,v 1.5 2015/05/03 01:07:44 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <[email protected]>
@@ -30,7 +30,7 @@
 #include "opt_multiprocessor.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_soc.c,v 1.4 2015/04/28 11:15:55 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_soc.c,v 1.5 2015/05/03 01:07:44 jmcneill Exp $");
 
 #define	_ARM32_BUS_DMA_PRIVATE
 #include <sys/param.h>
@@ -59,6 +59,22 @@ struct arm32_bus_dma_tag tegra_dma_tag =
 	_BUS_DMATAG_FUNCS,
 };
 
+static struct arm32_dma_range tegra_coherent_dma_ranges[] = {
+	[0] = {
+		.dr_sysbase = TEGRA_EXTMEM_BASE,
+		.dr_busbase = TEGRA_EXTMEM_BASE,
+		.dr_flags = _BUS_DMAMAP_COHERENT,
+	},
+};
+
+struct arm32_bus_dma_tag tegra_coherent_dma_tag = {
+	._ranges = tegra_coherent_dma_ranges,
+	._nranges = __arraycount(tegra_coherent_dma_ranges),
+	_BUS_DMAMAP_FUNCS,
+	_BUS_DMAMEM_FUNCS,
+	_BUS_DMATAG_FUNCS,
+};
+
 static void	tegra_mpinit(void);
 
 void
@@ -86,6 +102,12 @@ tegra_bootstrap(void)
 	tegra_mpinit();
 }
 
+void
+tegra_dma_bootstrap(psize_t psize)
+{
+	tegra_coherent_dma_ranges[0].dr_len = psize;
+}
+
 static void
 tegra_mpinit(void)
 {

Index: src/sys/arch/arm/nvidia/tegra_var.h
diff -u src/sys/arch/arm/nvidia/tegra_var.h:1.6 src/sys/arch/arm/nvidia/tegra_var.h:1.7
--- src/sys/arch/arm/nvidia/tegra_var.h:1.6	Sat May  2 17:06:53 2015
+++ src/sys/arch/arm/nvidia/tegra_var.h	Sun May  3 01:07:44 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_var.h,v 1.6 2015/05/02 17:06:53 jmcneill Exp $ */
+/* $NetBSD: tegra_var.h,v 1.7 2015/05/03 01:07:44 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <[email protected]>
@@ -50,6 +50,7 @@ struct tegraio_attach_args {
 	bus_space_tag_t tio_a4x_bst;
 	bus_space_handle_t tio_bsh;
 	bus_dma_tag_t tio_dmat;
+	bus_dma_tag_t tio_coherent_dmat;
 };
 
 extern struct bus_space armv7_generic_bs_tag;
@@ -59,6 +60,7 @@ extern bus_space_handle_t tegra_ppsb_bsh
 extern bus_space_handle_t tegra_apb_bsh;
 extern bus_space_handle_t tegra_ahb_a2_bsh;
 extern struct arm32_bus_dma_tag tegra_dma_tag;
+extern struct arm32_bus_dma_tag tegra_coherent_dma_tag;
 
 #define CHIP_ID_TEGRA20		0x20
 #define CHIP_ID_TEGRA30		0x30
@@ -69,6 +71,7 @@ extern struct arm32_bus_dma_tag tegra_dm
 u_int	tegra_chip_id(void);
 const char *tegra_chip_name(void);
 void	tegra_bootstrap(void);
+void	tegra_dma_bootstrap(psize_t);
 
 u_int	tegra_car_osc_rate(void);
 u_int	tegra_car_pllx_rate(void);

Index: src/sys/arch/evbarm/conf/JETSONTK1
diff -u src/sys/arch/evbarm/conf/JETSONTK1:1.8 src/sys/arch/evbarm/conf/JETSONTK1:1.9
--- src/sys/arch/evbarm/conf/JETSONTK1:1.8	Sat May  2 17:15:20 2015
+++ src/sys/arch/evbarm/conf/JETSONTK1	Sun May  3 01:07:44 2015
@@ -1,5 +1,5 @@
 #
-#	$NetBSD: JETSONTK1,v 1.8 2015/05/02 17:15:20 jmcneill Exp $
+#	$NetBSD: JETSONTK1,v 1.9 2015/05/03 01:07:44 jmcneill Exp $
 #
 #	NVIDIA Jetson TK1 - Tegra K1 development kit
 #	https://developer.nvidia.com/jetson-tk1
@@ -19,7 +19,7 @@ options 	DEBUG
 options 	LOCKDEBUG
 #options 	PMAP_DEBUG	# Enable pmap_debug_level code
 #options 	IPKDB		# remote kernel debugging
-options 	VERBOSE_INIT_ARM # verbose bootstraping messages
+#options 	VERBOSE_INIT_ARM # verbose bootstraping messages
 makeoptions	DEBUG="-g"	# compile full symbol table
 makeoptions	COPY_SYMTAB=1
 
@@ -49,6 +49,17 @@ tegracar0	at tegraio?		# CAR
 tegragpio0	at tegraio?		# GPIO
 gpio*		at gpiobus?
 
+# PCIE
+tegrapcie0	at tegraio?		# PCIE
+pci*		at tegrapcie0
+ppb*		at pci? dev ? function ?
+pci*		at ppb?
+
+# Ethernet
+re*		at pci? dev ? function ?	# Realtek RTL8111GS
+rgephy*		at mii? phy ?
+ukphy*		at mii? phy ?
+
 # UART
 com3		at tegraio? port 3	# UART-D
 options 	CONSADDR=0x70006300, CONSPEED=115200

Index: src/sys/arch/evbarm/conf/std.tegra
diff -u src/sys/arch/evbarm/conf/std.tegra:1.3 src/sys/arch/evbarm/conf/std.tegra:1.4
--- src/sys/arch/evbarm/conf/std.tegra:1.3	Sun Apr 26 18:03:48 2015
+++ src/sys/arch/evbarm/conf/std.tegra	Sun May  3 01:07:44 2015
@@ -1,4 +1,4 @@
-#	$NetBSD: std.tegra,v 1.3 2015/04/26 18:03:48 jmcneill Exp $
+#	$NetBSD: std.tegra,v 1.4 2015/05/03 01:07:44 jmcneill Exp $
 #
 
 machine	evbarm arm
@@ -17,6 +17,8 @@ options 	__HAVE_MM_MD_DIRECT_MAPPED_PHYS
 options 	TPIDRPRW_IS_CURCPU
 options 	KERNEL_BASE_EXT=0x80000000
 options 	FPU_VFP
+options 	PCI_NETBSD_CONFIGURE
+options 	__HAVE_PCI_CONF_HOOK
 
 makeoptions	KERNEL_BASE_PHYS="0x81000000"
 makeoptions	KERNEL_BASE_VIRT="0x81000000"

Index: src/sys/arch/evbarm/tegra/tegra_machdep.c
diff -u src/sys/arch/evbarm/tegra/tegra_machdep.c:1.8 src/sys/arch/evbarm/tegra/tegra_machdep.c:1.9
--- src/sys/arch/evbarm/tegra/tegra_machdep.c:1.8	Sat May  2 17:15:20 2015
+++ src/sys/arch/evbarm/tegra/tegra_machdep.c	Sun May  3 01:07:44 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_machdep.c,v 1.8 2015/05/02 17:15:20 jmcneill Exp $ */
+/* $NetBSD: tegra_machdep.c,v 1.9 2015/05/03 01:07:44 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <[email protected]>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_machdep.c,v 1.8 2015/05/02 17:15:20 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_machdep.c,v 1.9 2015/05/03 01:07:44 jmcneill Exp $");
 
 #include "opt_tegra.h"
 #include "opt_machdep.h"
@@ -288,6 +288,9 @@ initarm(void *arg)
 	KASSERTMSG(ram_size > 0, "RAM size unknown and MEMSIZE undefined");
 #endif
 
+	/* DMA tag setup */
+	tegra_dma_bootstrap(ram_size);
+
 	/* Fake bootconfig structure for the benefit of pmap.c. */
 	bootconfig.dramblocks = 1;
 	bootconfig.dram[0].address = TEGRA_EXTMEM_BASE; /* DDR PHY addr */

Added files:

Index: src/sys/arch/arm/nvidia/tegra_pcie.c
diff -u /dev/null src/sys/arch/arm/nvidia/tegra_pcie.c:1.1
--- /dev/null	Sun May  3 01:07:44 2015
+++ src/sys/arch/arm/nvidia/tegra_pcie.c	Sun May  3 01:07:44 2015
@@ -0,0 +1,405 @@
+/* $NetBSD: tegra_pcie.c,v 1.1 2015/05/03 01:07:44 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2015 Jared D. McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "locators.h"
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: tegra_pcie.c,v 1.1 2015/05/03 01:07:44 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/extent.h>
+#include <sys/queue.h>
+#include <sys/mutex.h>
+#include <sys/kmem.h>
+
+#include <arm/cpufunc.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pciconf.h>
+
+#include <arm/nvidia/tegra_reg.h>
+#include <arm/nvidia/tegra_pciereg.h>
+#include <arm/nvidia/tegra_var.h>
+
+static int	tegra_pcie_match(device_t, cfdata_t, void *);
+static void	tegra_pcie_attach(device_t, device_t, void *);
+
+struct tegra_pcie_ih {
+	int			(*ih_callback)(void *);
+	void			*ih_arg;
+	int			ih_ipl;
+	TAILQ_ENTRY(tegra_pcie_ih) ih_entry;
+};
+
+struct tegra_pcie_softc {
+	device_t		sc_dev;
+	bus_dma_tag_t		sc_dmat;
+	bus_space_tag_t		sc_bst;
+	bus_space_handle_t	sc_bsh_afi;
+	bus_space_handle_t	sc_bsh_a1;
+	bus_space_handle_t	sc_bsh_a2;
+	int			sc_intr;
+
+	struct arm32_pci_chipset sc_pc;
+
+	void			*sc_ih;
+
+	kmutex_t		sc_lock;
+
+	TAILQ_HEAD(, tegra_pcie_ih) sc_intrs;
+	u_int			sc_intrgen;
+};
+
+static int	tegra_pcie_intr(void *);
+static void	tegra_pcie_init(pci_chipset_tag_t, void *);
+static void	tegra_pcie_enable(struct tegra_pcie_softc *);
+
+static void	tegra_pcie_attach_hook(device_t, device_t,
+				       struct pcibus_attach_args *);
+static int	tegra_pcie_bus_maxdevs(void *, int);
+static pcitag_t	tegra_pcie_make_tag(void *, int, int, int);
+static void	tegra_pcie_decompose_tag(void *, pcitag_t, int *, int *, int *);
+static pcireg_t	tegra_pcie_conf_read(void *, pcitag_t, int);
+static void	tegra_pcie_conf_write(void *, pcitag_t, int, pcireg_t);
+static int	tegra_pcie_conf_hook(void *, int, int, int, pcireg_t);
+static void	tegra_pcie_conf_interrupt(void *, int, int, int, int, int *);
+
+static int	tegra_pcie_intr_map(const struct pci_attach_args *,
+				    pci_intr_handle_t *);
+static const char *tegra_pcie_intr_string(void *, pci_intr_handle_t,
+					  char *, size_t);
+const struct evcnt *tegra_pcie_intr_evcnt(void *, pci_intr_handle_t);
+static void *	tegra_pcie_intr_establish(void *, pci_intr_handle_t,
+					 int, int (*)(void *), void *);
+static void	tegra_pcie_intr_disestablish(void *, void *);
+
+CFATTACH_DECL_NEW(tegra_pcie, sizeof(struct tegra_pcie_softc),
+	tegra_pcie_match, tegra_pcie_attach, NULL, NULL);
+
+static int
+tegra_pcie_match(device_t parent, cfdata_t cf, void *aux)
+{
+	return 1;
+}
+
+static void
+tegra_pcie_attach(device_t parent, device_t self, void *aux)
+{
+	struct tegra_pcie_softc * const sc = device_private(self);
+	struct tegraio_attach_args * const tio = aux;
+	const struct tegra_locators * const loc = &tio->tio_loc;
+	struct extent *memext, *pmemext;
+	struct pcibus_attach_args pba;
+	int error;
+
+	sc->sc_dev = self;
+	sc->sc_dmat = tio->tio_coherent_dmat;
+	sc->sc_bst = tio->tio_bst;
+	sc->sc_intr = loc->loc_intr;
+	if (bus_space_map(sc->sc_bst, TEGRA_PCIE_AFI_BASE, TEGRA_PCIE_AFI_SIZE,
+	    0, &sc->sc_bsh_afi) != 0)
+		panic("couldn't map PCIE AFI");
+	if (bus_space_map(sc->sc_bst, TEGRA_PCIE_A1_BASE, TEGRA_PCIE_A1_SIZE,
+	    0, &sc->sc_bsh_a1) != 0)
+		panic("couldn't map PCIE A1");
+	if (bus_space_map(sc->sc_bst, TEGRA_PCIE_A2_BASE, TEGRA_PCIE_A2_SIZE,
+	    0, &sc->sc_bsh_a2) != 0)
+		panic("couldn't map PCIE A2");
+
+	TAILQ_INIT(&sc->sc_intrs);
+	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM);
+
+	aprint_naive("\n");
+	aprint_normal(": PCIE\n");
+
+	sc->sc_ih = intr_establish(loc->loc_intr, IPL_VM, IST_LEVEL,
+	    tegra_pcie_intr, sc);
+	if (sc->sc_ih == NULL) {
+		aprint_error_dev(self, "failed to establish interrupt %d\n",
+		    loc->loc_intr);
+		return;
+	}
+	aprint_normal_dev(self, "interrupting on irq %d\n", loc->loc_intr);
+
+	tegra_pcie_init(&sc->sc_pc, sc);
+
+	memext = extent_create("pcimem", TEGRA_PCIE_MEM_BASE,
+	    TEGRA_PCIE_MEM_BASE + TEGRA_PCIE_MEM_SIZE - 1,
+	    NULL, 0, EX_NOWAIT);
+	pmemext = extent_create("pcipmem", TEGRA_PCIE_PMEM_BASE,
+	    TEGRA_PCIE_PMEM_BASE + TEGRA_PCIE_PMEM_SIZE - 1,
+	    NULL, 0, EX_NOWAIT);
+
+	error = pci_configure_bus(&sc->sc_pc, NULL, memext, pmemext, 0,
+	    arm_dcache_align);
+
+	extent_destroy(memext);
+	extent_destroy(pmemext);
+
+	if (error) {
+		aprint_error_dev(self, "configuration failed (%d)\n",
+		    error);
+		return;
+	}
+
+	tegra_pcie_enable(sc);
+
+	memset(&pba, 0, sizeof(pba));
+	pba.pba_flags = PCI_FLAGS_MRL_OKAY |
+			PCI_FLAGS_MRM_OKAY |
+			PCI_FLAGS_MWI_OKAY |
+			PCI_FLAGS_MEM_OKAY;
+	pba.pba_memt = sc->sc_bst;
+	pba.pba_dmat = sc->sc_dmat;
+	pba.pba_pc = &sc->sc_pc;
+	pba.pba_bus = 0;
+
+	config_found_ia(self, "pcibus", &pba, pcibusprint);
+}
+
+static int
+tegra_pcie_intr(void *priv)
+{
+	struct tegra_pcie_softc *sc = priv;
+	struct tegra_pcie_ih *pcie_ih;
+
+	const uint32_t code = bus_space_read_4(sc->sc_bst, sc->sc_bsh_afi,
+	    AFI_INTR_CODE_REG);
+	const uint32_t sig = bus_space_read_4(sc->sc_bst, sc->sc_bsh_afi,
+	    AFI_INTR_SIGNATURE_REG);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_INTR_CODE_REG, 0);
+
+	switch (__SHIFTOUT(code, AFI_INTR_CODE_INT_CODE)) {
+	case AFI_INTR_CODE_SM_MSG:
+		mutex_enter(&sc->sc_lock);
+		const u_int lastgen = sc->sc_intrgen;
+		TAILQ_FOREACH(pcie_ih, &sc->sc_intrs, ih_entry) {
+			int (*callback)(void *) = pcie_ih->ih_callback;
+			void *arg = pcie_ih->ih_arg;
+			mutex_exit(&sc->sc_lock);
+			const int rv = callback(arg);
+			if (rv)
+				return rv;
+			mutex_enter(&sc->sc_lock);
+			if (lastgen != sc->sc_intrgen)
+				break;
+		}
+		mutex_exit(&sc->sc_lock);
+		return 0;
+	default:
+		device_printf(sc->sc_dev, "intr: code %#x sig %#x\n",
+		    code, sig);
+		return 1;
+	}
+}
+
+static void
+tegra_pcie_enable(struct tegra_pcie_softc *sc)
+{
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi,
+	    AFI_SM_INTR_ENABLE_REG, 0xffffffff);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi,
+	    AFI_AFI_INTR_ENABLE_REG, 0);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_INTR_CODE_REG, 0);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi,
+	    AFI_INTR_MASK_REG, AFI_INTR_MASK_INT);
+}
+
+void
+tegra_pcie_init(pci_chipset_tag_t pc, void *priv)
+{
+	pc->pc_conf_v = priv;
+	pc->pc_attach_hook = tegra_pcie_attach_hook;
+	pc->pc_bus_maxdevs = tegra_pcie_bus_maxdevs;
+	pc->pc_make_tag = tegra_pcie_make_tag;
+	pc->pc_decompose_tag = tegra_pcie_decompose_tag;
+	pc->pc_conf_read = tegra_pcie_conf_read;
+	pc->pc_conf_write = tegra_pcie_conf_write;
+	pc->pc_conf_hook = tegra_pcie_conf_hook;
+	pc->pc_conf_interrupt = tegra_pcie_conf_interrupt;
+
+	pc->pc_intr_v = priv;
+	pc->pc_intr_map = tegra_pcie_intr_map;
+	pc->pc_intr_string = tegra_pcie_intr_string;
+	pc->pc_intr_evcnt = tegra_pcie_intr_evcnt;
+	pc->pc_intr_establish = tegra_pcie_intr_establish;
+	pc->pc_intr_disestablish = tegra_pcie_intr_disestablish;
+}
+
+static void
+tegra_pcie_attach_hook(device_t parent, device_t self,
+    struct pcibus_attach_args *pba)
+{
+}
+
+static int
+tegra_pcie_bus_maxdevs(void *v, int busno)
+{
+	return busno == 0 ? 2 : 32;
+}
+
+static pcitag_t
+tegra_pcie_make_tag(void *v, int b, int d, int f)
+{
+	return (b << 16) | (d << 11) | (f << 8);
+}
+
+static void
+tegra_pcie_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp)
+{
+	if (bp)
+		*bp = (tag >> 16) & 0xff;
+	if (dp)
+		*dp = (tag >> 11) & 0x1f;
+	if (fp)
+		*fp = (tag >> 8) & 0x7;
+}
+
+static pcireg_t
+tegra_pcie_conf_read(void *v, pcitag_t tag, int offset)
+{
+	struct tegra_pcie_softc *sc = v;
+	bus_space_handle_t bsh;
+	int b, d, f;
+	u_int reg;
+
+	tegra_pcie_decompose_tag(v, tag, &b, &d, &f);
+
+	if (b == 0) {
+		reg = d * 0x1000 + offset;
+		bsh = sc->sc_bsh_a1;
+	} else {
+		reg = tag | offset;
+		bsh = sc->sc_bsh_a2;
+	}
+
+	return bus_space_read_4(sc->sc_bst, bsh, reg);
+}
+
+static void
+tegra_pcie_conf_write(void *v, pcitag_t tag, int offset, pcireg_t val)
+{
+	struct tegra_pcie_softc *sc = v;
+	bus_space_handle_t bsh;
+	int b, d, f;
+	u_int reg;
+
+	tegra_pcie_decompose_tag(v, tag, &b, &d, &f);
+
+	if (b == 0) {
+		reg = d * 0x1000 + offset;
+		bsh = sc->sc_bsh_a1;
+	} else {
+		reg = tag | offset;
+		bsh = sc->sc_bsh_a2;
+	}
+
+	bus_space_write_4(sc->sc_bst, bsh, reg, val);
+}
+
+static int
+tegra_pcie_conf_hook(void *v, int b, int d, int f, pcireg_t id)
+{
+	return PCI_CONF_ENABLE_MEM | PCI_CONF_MAP_MEM | PCI_CONF_ENABLE_BM;
+}
+
+static void
+tegra_pcie_conf_interrupt(void *v, int bus, int dev, int ipin, int swiz,
+    int *ilinep)
+{
+	*ilinep = 5;
+}
+
+static int
+tegra_pcie_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ih)
+{
+	if (pa->pa_intrpin == 0)
+		return EINVAL;
+	*ih = pa->pa_intrpin;
+	return 0;
+}
+				    
+static const char *
+tegra_pcie_intr_string(void *v, pci_intr_handle_t ih, char *buf, size_t len)
+{
+	struct tegra_pcie_softc *sc = v;
+
+	if (ih == PCI_INTERRUPT_PIN_NONE)
+		return NULL;
+
+	snprintf(buf, len, "irq %d", sc->sc_intr);
+	return buf;
+}
+
+const struct evcnt *
+tegra_pcie_intr_evcnt(void *v, pci_intr_handle_t ih)
+{
+	return NULL;
+}
+
+static void *
+tegra_pcie_intr_establish(void *v, pci_intr_handle_t ih, int ipl,
+    int (*callback)(void *), void *arg)
+{
+	struct tegra_pcie_softc *sc = v;
+	struct tegra_pcie_ih *pcie_ih;
+
+	if (ih == 0)
+		return NULL;
+
+	pcie_ih = kmem_alloc(sizeof(*pcie_ih), KM_SLEEP);
+	pcie_ih->ih_callback = callback;
+	pcie_ih->ih_arg = arg;
+	pcie_ih->ih_ipl = ipl;
+
+	mutex_enter(&sc->sc_lock);
+	TAILQ_INSERT_TAIL(&sc->sc_intrs, pcie_ih, ih_entry);
+	sc->sc_intrgen++;
+	mutex_exit(&sc->sc_lock);
+
+	return pcie_ih;
+}
+
+static void
+tegra_pcie_intr_disestablish(void *v, void *vih)
+{
+	struct tegra_pcie_softc *sc = v;
+	struct tegra_pcie_ih *pcie_ih = vih;
+
+	mutex_enter(&sc->sc_lock);
+	TAILQ_REMOVE(&sc->sc_intrs, pcie_ih, ih_entry);
+	mutex_exit(&sc->sc_lock);
+
+	kmem_free(pcie_ih, sizeof(*pcie_ih));
+}
Index: src/sys/arch/arm/nvidia/tegra_pciereg.h
diff -u /dev/null src/sys/arch/arm/nvidia/tegra_pciereg.h:1.1
--- /dev/null	Sun May  3 01:07:44 2015
+++ src/sys/arch/arm/nvidia/tegra_pciereg.h	Sun May  3 01:07:44 2015
@@ -0,0 +1,45 @@
+/* $NetBSD: tegra_pciereg.h,v 1.1 2015/05/03 01:07:44 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2015 Jared D. McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ARM_TEGRA_PCIEREG_H
+#define _ARM_TEGRA_PCIEREG_H
+
+/* AFI */
+#define AFI_INTR_MASK_REG	0xb4
+#define AFI_INTR_CODE_REG	0xb8
+#define AFI_INTR_SIGNATURE_REG	0xbc
+#define AFI_SM_INTR_ENABLE_REG	0xc4
+#define AFI_AFI_INTR_ENABLE_REG	0xc8
+
+#define AFI_INTR_MASK_MSI	__BIT(8)
+#define AFI_INTR_MASK_INT	__BIT(0)
+
+#define AFI_INTR_CODE_INT_CODE	__BITS(4,0)
+#define AFI_INTR_CODE_SM_MSG	6
+
+#endif /* _ARM_TEGRA_PCIEREG_H */

Reply via email to