Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch Add Tegra K1 PCIE support.



details:   https://anonhg.NetBSD.org/src/rev/57eaf00036ac
branches:  trunk
changeset: 808043:57eaf00036ac
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sun May 03 01:07:44 2015 +0000

description:
Add Tegra K1 PCIE support.

diffstat:

 sys/arch/arm/nvidia/files.tegra       |    7 +-
 sys/arch/arm/nvidia/tegra_intr.h      |    5 +-
 sys/arch/arm/nvidia/tegra_io.c        |   12 +-
 sys/arch/arm/nvidia/tegra_pcie.c      |  405 ++++++++++++++++++++++++++++++++++
 sys/arch/arm/nvidia/tegra_pciereg.h   |   45 +++
 sys/arch/arm/nvidia/tegra_reg.h       |   20 +-
 sys/arch/arm/nvidia/tegra_soc.c       |   26 ++-
 sys/arch/arm/nvidia/tegra_var.h       |    5 +-
 sys/arch/evbarm/conf/JETSONTK1        |   15 +-
 sys/arch/evbarm/conf/std.tegra        |    4 +-
 sys/arch/evbarm/tegra/tegra_machdep.c |    7 +-
 11 files changed, 538 insertions(+), 13 deletions(-)

diffs (truncated from 748 to 300 lines):

diff -r 24d4cc3641f4 -r 57eaf00036ac sys/arch/arm/nvidia/files.tegra
--- a/sys/arch/arm/nvidia/files.tegra   Sun May 03 00:04:06 2015 +0000
+++ b/sys/arch/arm/nvidia/files.tegra   Sun May 03 01:07:44 2015 +0000
@@ -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 @@
 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
diff -r 24d4cc3641f4 -r 57eaf00036ac sys/arch/arm/nvidia/tegra_intr.h
--- a/sys/arch/arm/nvidia/tegra_intr.h  Sun May 03 00:04:06 2015 +0000
+++ b/sys/arch/arm/nvidia/tegra_intr.h  Sun May 03 01:07:44 2015 +0000
@@ -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 <jmcneill%invisible.ca@localhost>
@@ -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 */
diff -r 24d4cc3641f4 -r 57eaf00036ac sys/arch/arm/nvidia/tegra_io.c
--- a/sys/arch/arm/nvidia/tegra_io.c    Sun May 03 00:04:06 2015 +0000
+++ b/sys/arch/arm/nvidia/tegra_io.c    Sun May 03 01:07:44 2015 +0000
@@ -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 <jmcneill%invisible.ca@localhost>
@@ -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 @@
     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 @@
            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 @@
                        .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);
diff -r 24d4cc3641f4 -r 57eaf00036ac sys/arch/arm/nvidia/tegra_pcie.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/nvidia/tegra_pcie.c  Sun May 03 01:07:44 2015 +0000
@@ -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 <jmcneill%invisible.ca@localhost>
+ * 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);



Home | Main Index | Thread Index | Old Index