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