Source-Changes-HG archive

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

[src/trunk]: src/sys/arch Add xhci(4) attachment glue and firmware handler fo...



details:   https://anonhg.NetBSD.org/src/rev/7182f6598dad
branches:  trunk
changeset: 347961:7182f6598dad
user:      jakllsch <jakllsch%NetBSD.org@localhost>
date:      Mon Sep 26 20:05:03 2016 +0000

description:
Add xhci(4) attachment glue and firmware handler for Tegra K1 "XUSB"
xHCI controller.  Adjustments to tegraxusbpad(4) will be needed
to connect the controller to actual USB ports.

diffstat:

 sys/arch/arm/nvidia/files.tegra      |    6 +-
 sys/arch/arm/nvidia/tegra_xusb-fw.mk |   12 +
 sys/arch/arm/nvidia/tegra_xusb.c     |  800 +++++++++++++++++++++++++++++++++++
 sys/arch/arm/nvidia/tegra_xusbreg.h  |   89 +++
 sys/arch/evbarm/conf/TEGRA           |    6 +-
 sys/arch/evbarm/conf/mk.tegra        |    4 +-
 6 files changed, 914 insertions(+), 3 deletions(-)

diffs (truncated from 967 to 300 lines):

diff -r fcbb9f919752 -r 7182f6598dad sys/arch/arm/nvidia/files.tegra
--- a/sys/arch/arm/nvidia/files.tegra   Mon Sep 26 19:43:43 2016 +0000
+++ b/sys/arch/arm/nvidia/files.tegra   Mon Sep 26 20:05:03 2016 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.tegra,v 1.28 2015/12/22 22:10:36 jmcneill Exp $
+#      $NetBSD: files.tegra,v 1.29 2016/09/26 20:05:03 jakllsch Exp $
 #
 # Configuration info for NVIDIA Tegra ARM Peripherals
 #
@@ -90,6 +90,10 @@
 attach ehci at fdt with tegra_ehci
 file   arch/arm/nvidia/tegra_ehci.c            tegra_ehci
 
+# XUSB (USB 3.0)
+attach xhci at fdt with tegra_xusb
+file   arch/arm/nvidia/tegra_xusb.c            tegra_xusb
+
 # SDMMC
 attach sdhc at fdt with tegra_sdhc
 file   arch/arm/nvidia/tegra_sdhc.c            tegra_sdhc
diff -r fcbb9f919752 -r 7182f6598dad sys/arch/arm/nvidia/tegra_xusb-fw.mk
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/nvidia/tegra_xusb-fw.mk      Mon Sep 26 20:05:03 2016 +0000
@@ -0,0 +1,12 @@
+#      $NetBSD: tegra_xusb-fw.mk,v 1.1 2016/09/26 20:05:03 jakllsch Exp $
+
+.if defined(TEGRA124_XUSB_BIN_STATIC)
+MD_OBJS+=      tegra124_xusb_bin.o
+CPPFLAGS+=     -DTEGRA124_XUSB_BIN_STATIC
+
+tegra124_xusb_bin.o:   $S/arch/arm/nvidia/tegra124_xusb.bin
+       -rm -f ${.OBJDIR}/tegra124_xusb.bin
+       -ln -s $S/arch/arm/nvidia/tegra124_xusb.bin ${.OBJDIR}
+       ${OBJCOPY} -I binary -O default -B arm tegra124_xusb.bin \
+           --rename-section .data=.rodata ${.TARGET}
+.endif
diff -r fcbb9f919752 -r 7182f6598dad sys/arch/arm/nvidia/tegra_xusb.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/nvidia/tegra_xusb.c  Mon Sep 26 20:05:03 2016 +0000
@@ -0,0 +1,800 @@
+/* $NetBSD: tegra_xusb.c,v 1.1 2016/09/26 20:05:03 jakllsch Exp $ */
+
+/*
+ * Copyright (c) 2016 Jonathan A. Kollasch
+ * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT HOLDER OR
+ * CONTRIBUTORS 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 "opt_tegra.h"
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: tegra_xusb.c,v 1.1 2016/09/26 20:05:03 jakllsch 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 <arm/nvidia/tegra_reg.h>
+#include <arm/nvidia/tegra_var.h>
+
+#include <arm/nvidia/tegra_xusbreg.h>
+#include <dev/pci/pcireg.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#include <dev/firmload.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/usb_mem.h>
+
+#include <dev/usb/xhcireg.h>
+#include <dev/usb/xhcivar.h>
+
+static int     tegra_xusb_match(device_t, cfdata_t, void *);
+static void    tegra_xusb_attach(device_t, device_t, void *);
+static void    tegra_xusb_mountroot(device_t);
+
+static int     tegra_xusb_intr_mbox(void *);
+
+#ifdef TEGRA124_XUSB_BIN_STATIC
+extern const char _binary_tegra124_xusb_bin_size[];
+extern const char _binary_tegra124_xusb_bin_start[];
+#endif
+
+struct fw_dma {
+       bus_dmamap_t            map;
+       void *                  addr;
+       bus_dma_segment_t       segs[1];
+       int                     nsegs;
+       size_t                  size;
+};
+
+struct tegra_xusb_softc {
+       struct xhci_softc       sc_xhci;
+       int                     sc_phandle;
+       bus_space_handle_t      sc_bsh_xhci;
+       bus_space_handle_t      sc_bsh_fpci;
+       bus_space_handle_t      sc_bsh_ipfs;
+       void                    *sc_ih;
+       void                    *sc_ih_mbox;
+       struct fw_dma           sc_fw_dma;
+       struct clk              *sc_clk_ss_src;
+};
+
+static uint32_t        csb_read_4(struct tegra_xusb_softc * const, bus_size_t);
+static void    csb_write_4(struct tegra_xusb_softc * const, bus_size_t,
+    uint32_t);
+       
+static void    tegra_xusb_init(struct tegra_xusb_softc * const);
+static void    tegra_xusb_load_fw(struct tegra_xusb_softc * const);
+
+static int     xusb_mailbox_send(struct tegra_xusb_softc * const, uint32_t);
+
+CFATTACH_DECL_NEW(tegra_xusb, sizeof(struct tegra_xusb_softc),
+       tegra_xusb_match, tegra_xusb_attach, NULL, NULL);
+
+static int
+tegra_xusb_match(device_t parent, cfdata_t cf, void *aux)
+{
+       const char * const compatible[] = { "nvidia,tegra124-xusb", NULL };
+       struct fdt_attach_args * const faa = aux;
+
+       return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+tegra_xusb_attach(device_t parent, device_t self, void *aux)
+{
+       struct tegra_xusb_softc * const psc = device_private(self);
+       struct xhci_softc * const sc = &psc->sc_xhci;
+       struct fdt_attach_args * const faa = aux;
+       char intrstr[128];
+       bus_addr_t addr;
+       bus_size_t size;
+       int error;
+       struct clk *clk;
+       uint32_t rate;
+       struct fdtbus_reset *rst;
+
+       aprint_naive("\n");
+       aprint_normal(": XUSB\n");
+
+       sc->sc_dev = self;
+       sc->sc_iot = faa->faa_bst;
+       sc->sc_bus.ub_hcpriv = sc;
+       sc->sc_bus.ub_dmatag = faa->faa_dmat;
+       psc->sc_phandle = faa->faa_phandle;
+
+       if (fdtbus_get_reg(faa->faa_phandle, 0, &addr, &size) != 0) {
+               aprint_error(": couldn't get registers\n");
+               return;
+       }
+       error = bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh);
+       if (error) {
+               aprint_error(": couldn't map %#llx: %d", (uint64_t)addr, error);
+               return;
+       }
+       printf("mapped %#llx\n", (uint64_t)addr);
+
+       if (fdtbus_get_reg(faa->faa_phandle, 1, &addr, &size) != 0) {
+               aprint_error(": couldn't get registers\n");
+               return;
+       }
+       error = bus_space_map(sc->sc_iot, addr, size, 0, &psc->sc_bsh_fpci);
+       if (error) {
+               aprint_error(": couldn't map %#llx: %d", (uint64_t)addr, error);
+               return;
+       }
+       printf("mapped %#llx\n", (uint64_t)addr);
+
+       if (fdtbus_get_reg(faa->faa_phandle, 2, &addr, &size) != 0) {
+               aprint_error(": couldn't get registers\n");
+               return;
+       }
+       error = bus_space_map(sc->sc_iot, addr, size, 0, &psc->sc_bsh_ipfs);
+       if (error) {
+               aprint_error(": couldn't map %#llx: %d", (uint64_t)addr, error);
+               return;
+       }
+       printf("mapped %#llx\n", (uint64_t)addr);
+
+       if (!fdtbus_intr_str(faa->faa_phandle, 0, intrstr, sizeof(intrstr))) {
+               aprint_error_dev(self, "failed to decode interrupt\n");
+               return;
+       }
+
+       psc->sc_ih = fdtbus_intr_establish(faa->faa_phandle, 0, IPL_USB,
+           0, xhci_intr, sc);
+       if (psc->sc_ih == NULL) {
+               aprint_error_dev(self, "failed to establish interrupt on %s\n",
+                   intrstr);
+               return;
+       }
+       aprint_normal_dev(self, "interrupting on %s\n", intrstr);
+
+       if (!fdtbus_intr_str(faa->faa_phandle, 1, intrstr, sizeof(intrstr))) {
+               aprint_error_dev(self, "failed to decode interrupt\n");
+               return;
+       }
+
+       psc->sc_ih_mbox = fdtbus_intr_establish(faa->faa_phandle, 1, IPL_VM,
+           0, tegra_xusb_intr_mbox, psc);
+       if (psc->sc_ih_mbox == NULL) {
+               aprint_error_dev(self, "failed to establish interrupt on %s\n",
+                   intrstr);
+               return;
+       }
+       aprint_normal_dev(self, "interrupting on %s\n", intrstr);
+
+       struct clk * const pll_p_out0 = clk_get("pll_p_out0");
+       KASSERT(pll_p_out0 != NULL);
+
+       struct clk * const pll_u_48 = clk_get("pll_u_48");
+       KASSERT(pll_u_48 != NULL);
+
+       struct clk * const pll_u_480 = clk_get("pll_u_480");
+       KASSERT(pll_u_480 != NULL);
+
+       clk = fdtbus_clock_get(faa->faa_phandle, "pll_e");
+       rate = clk_get_rate(clk);
+       error = clk_enable(clk); /* XXX set frequency */
+       device_printf(sc->sc_dev, "rate %u error %d\n", rate, error);
+
+       clk = fdtbus_clock_get(faa->faa_phandle, "xusb_host_src");
+       error = clk_set_parent(clk, pll_p_out0);
+       rate = clk_get_rate(clk);
+       device_printf(sc->sc_dev, "rate %u error %d\n", rate, error);
+       error = clk_set_rate(clk, 102000000);
+       rate = clk_get_rate(clk);
+       error = clk_enable(clk); /* XXX set frequency */
+       device_printf(sc->sc_dev, "rate %u error %d\n", rate, error);
+
+       clk = fdtbus_clock_get(faa->faa_phandle, "xusb_falcon_src");
+       error = clk_set_parent(clk, pll_p_out0);
+       rate = clk_get_rate(clk);
+       device_printf(sc->sc_dev, "rate %u error %d\n", rate, error);
+       error = clk_set_rate(clk, 204000000);
+       rate = clk_get_rate(clk);
+       error = clk_enable(clk);
+       device_printf(sc->sc_dev, "rate %u error %d\n", rate, error);
+
+       clk = fdtbus_clock_get(faa->faa_phandle, "xusb_host");
+       rate = clk_get_rate(clk);
+       error = clk_enable(clk); /* XXX set frequency */
+       device_printf(sc->sc_dev, "rate %u error %d\n", rate, error);
+
+       clk = fdtbus_clock_get(faa->faa_phandle, "xusb_ss");
+       rate = clk_get_rate(clk);
+       error = clk_enable(clk); /* XXX set frequency */
+       device_printf(sc->sc_dev, "xusb_ss rate %u error %d\n", rate, error);
+
+       psc->sc_clk_ss_src = fdtbus_clock_get(faa->faa_phandle, "xusb_ss_src");
+       if (psc->sc_clk_ss_src == NULL) {
+               printf("psc->sc_clk_ss_src %p\n", psc->sc_clk_ss_src);
+               Debugger();
+       }
+       error = 0;
+       rate = clk_get_rate(psc->sc_clk_ss_src);
+       device_printf(sc->sc_dev, "xusb_ss_src rate %u error %d\n", rate,
+           error);
+
+       error = clk_set_rate(psc->sc_clk_ss_src, 2000000);
+       rate = clk_get_rate(psc->sc_clk_ss_src);
+       device_printf(sc->sc_dev, "xusb_ss_src rate %u error %d\n", rate,
+           error);
+
+       error = clk_set_parent(psc->sc_clk_ss_src, pll_u_480);
+       rate = clk_get_rate(psc->sc_clk_ss_src);
+       device_printf(sc->sc_dev, "ss_src rate %u error %d\n", rate, error);
+
+       error = clk_set_rate(psc->sc_clk_ss_src, 120000000);
+       rate = clk_get_rate(psc->sc_clk_ss_src);
+       device_printf(sc->sc_dev, "ss_src rate %u error %d\n", rate, error);
+



Home | Main Index | Thread Index | Old Index