Module Name: src Committed By: jmcneill Date: Sat Oct 17 21:18:16 UTC 2015
Modified Files: src/sys/arch/arm/nvidia: files.tegra tegra_io.c Added Files: src/sys/arch/arm/nvidia: tegra_nouveau.c Log Message: Add bus glue for attaching nouveau DRM To generate a diff of this commit: cvs rdiff -u -r1.16 -r1.17 src/sys/arch/arm/nvidia/files.tegra cvs rdiff -u -r1.13 -r1.14 src/sys/arch/arm/nvidia/tegra_io.c cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/nvidia/tegra_nouveau.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.16 src/sys/arch/arm/nvidia/files.tegra:1.17 --- src/sys/arch/arm/nvidia/files.tegra:1.16 Sat Aug 22 15:10:04 2015 +++ src/sys/arch/arm/nvidia/files.tegra Sat Oct 17 21:18:16 2015 @@ -1,4 +1,4 @@ -# $NetBSD: files.tegra,v 1.16 2015/08/22 15:10:04 jmcneill Exp $ +# $NetBSD: files.tegra,v 1.17 2015/10/17 21:18:16 jmcneill Exp $ # # Configuration info for NVIDIA Tegra ARM Peripherals # @@ -116,6 +116,10 @@ device tegracec: hdmicecbus attach tegracec at tegraio with tegra_cec file arch/arm/nvidia/tegra_cec.c tegra_cec +# GPU +attach nouveau at tegraio with tegra_nouveau +file arch/arm/nvidia/tegra_nouveau.c tegra_nouveau + # Console parameters defparam opt_tegra.h CONADDR defparam opt_tegra.h CONSPEED Index: src/sys/arch/arm/nvidia/tegra_io.c diff -u src/sys/arch/arm/nvidia/tegra_io.c:1.13 src/sys/arch/arm/nvidia/tegra_io.c:1.14 --- src/sys/arch/arm/nvidia/tegra_io.c:1.13 Sat Aug 1 21:20:11 2015 +++ src/sys/arch/arm/nvidia/tegra_io.c Sat Oct 17 21:18:16 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: tegra_io.c,v 1.13 2015/08/01 21:20:11 jmcneill Exp $ */ +/* $NetBSD: tegra_io.c,v 1.14 2015/10/17 21:18:16 jmcneill Exp $ */ /*- * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca> @@ -29,7 +29,7 @@ #include "opt_tegra.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tegra_io.c,v 1.13 2015/08/01 21:20:11 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tegra_io.c,v 1.14 2015/10/17 21:18:16 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -144,6 +144,10 @@ static const struct tegra_locators tegra TEGRA_HDMI_OFFSET, TEGRA_HDMI_SIZE, NOPORT, TEGRA_INTR_HDMI }, }; +static const struct tegra_locators tegra_gpu_locators[] = { + { "nouveau", 0, TEGRA_GPU_SIZE, NOPORT, NOINTR } +}; + int tegraio_match(device_t parent, cfdata_t cf, void *aux) { @@ -171,6 +175,8 @@ tegraio_attach(device_t parent, device_t tegraio_scan(self, (bus_space_handle_t)NULL, tegra_ghost_locators, __arraycount(tegra_ghost_locators)); tegraio_scan(self, (bus_space_handle_t)NULL, + tegra_gpu_locators, __arraycount(tegra_gpu_locators)); + tegraio_scan(self, (bus_space_handle_t)NULL, tegra_pcie_locators, __arraycount(tegra_pcie_locators)); } Added files: Index: src/sys/arch/arm/nvidia/tegra_nouveau.c diff -u /dev/null src/sys/arch/arm/nvidia/tegra_nouveau.c:1.1 --- /dev/null Sat Oct 17 21:18:16 2015 +++ src/sys/arch/arm/nvidia/tegra_nouveau.c Sat Oct 17 21:18:16 2015 @@ -0,0 +1,225 @@ +/* $NetBSD: tegra_nouveau.c,v 1.1 2015/10/17 21:18:16 jmcneill Exp $ */ + +/*- + * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca> + * 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_nouveau.c,v 1.1 2015/10/17 21:18:16 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/module.h> + +#include <arm/nvidia/tegra_reg.h> +#include <arm/nvidia/tegra_var.h> + +#include <drm/drmP.h> +#include <engine/device.h> + +extern char *nouveau_config; +extern char *nouveau_debug; +extern struct drm_driver *const nouveau_drm_driver; + +static int tegra_nouveau_match(device_t, cfdata_t, void *); +static void tegra_nouveau_attach(device_t, device_t, void *); + +struct tegra_nouveau_softc { + device_t sc_dev; + struct drm_device *sc_drm_dev; + struct platform_device sc_platform_dev; + struct nouveau_device *sc_nv_dev; +}; + +static int tegra_nouveau_init(struct tegra_nouveau_softc *); + +static int tegra_nouveau_get_irq(struct drm_device *); +static const char *tegra_nouveau_get_name(struct drm_device *); +static int tegra_nouveau_set_busid(struct drm_device *, + struct drm_master *); +static int tegra_nouveau_irq_install(struct drm_device *, + irqreturn_t (*)(void *), + int, const char *, void *, + struct drm_bus_irq_cookie **); +static void tegra_nouveau_irq_uninstall(struct drm_device *, + struct drm_bus_irq_cookie *); + +static struct drm_bus drm_tegra_nouveau_bus = { + .bus_type = DRIVER_BUS_PLATFORM, + .get_irq = tegra_nouveau_get_irq, + .get_name = tegra_nouveau_get_name, + .set_busid = tegra_nouveau_set_busid, + .irq_install = tegra_nouveau_irq_install, + .irq_uninstall = tegra_nouveau_irq_uninstall +}; + +CFATTACH_DECL_NEW(tegra_nouveau, sizeof(struct tegra_nouveau_softc), + tegra_nouveau_match, tegra_nouveau_attach, NULL, NULL); + +static int +tegra_nouveau_match(device_t parent, cfdata_t cf, void *aux) +{ + return 1; +} + +static void +tegra_nouveau_attach(device_t parent, device_t self, void *aux) +{ + struct tegra_nouveau_softc * const sc = device_private(self); +#if notyet + struct tegraio_attach_args * const tio = aux; + const struct tegra_locators * const loc = &tio->tio_loc; +#endif + int error; + + sc->sc_dev = self; +#if notyet + sc->sc_bst = tio->tio_bst; + bus_space_subregion(tio->tio_bst, tio->tio_bsh, + loc->loc_offset, loc->loc_size, &sc->sc_bsh); +#endif + + aprint_naive("\n"); + aprint_normal(": GPU\n"); + + tegra_car_gpu_enable(); + + error = -nouveau_device_create(&sc->sc_platform_dev, + NOUVEAU_BUS_PLATFORM, -1, device_xname(self), + nouveau_config, nouveau_debug, &sc->sc_nv_dev); + if (error) { + aprint_error_dev(self, "couldn't create nouveau device: %d\n", + error); + return; + } + + error = tegra_nouveau_init(sc); + if (error) { + aprint_error_dev(self, "couldn't attach drm: %d\n", error); + return; + } +} + +static int +tegra_nouveau_init(struct tegra_nouveau_softc *sc) +{ + struct drm_driver * const driver = nouveau_drm_driver; + struct drm_device *dev; + bus_space_tag_t bst = &armv7_generic_bs_tag; + int error; + + driver->kdriver.platform_device = &sc->sc_platform_dev; + driver->bus = &drm_tegra_nouveau_bus; + + dev = drm_dev_alloc(driver, sc->sc_dev); + if (dev == NULL) + return ENOMEM; + dev->platformdev = &sc->sc_platform_dev; + + dev->platformdev->id = -1; + dev->platformdev->nresource = 2; + dev->platformdev->resource[0].tag = bst; + dev->platformdev->resource[0].start = TEGRA_GPU_BASE; + dev->platformdev->resource[0].len = 0x01000000; + dev->platformdev->resource[1].tag = bst; + dev->platformdev->resource[1].start = TEGRA_GPU_BASE + + dev->platformdev->resource[0].len; + dev->platformdev->resource[1].len = 0x01000000; + + error = -drm_dev_register(dev, 0); + if (error) { + drm_dev_unref(dev); + Debugger(); + return error; + } + + device_printf(sc->sc_dev, "initialized %s %d.%d.%d %s on minor %d\n", + driver->name, driver->major, driver->minor, driver->patchlevel, + driver->date, dev->primary->index); + + return 0; +} + +static int +tegra_nouveau_get_irq(struct drm_device *dev) +{ + return TEGRA_INTR_GPU; +} + +static const char *tegra_nouveau_get_name(struct drm_device *dev) +{ + return "tegra_nouveau"; +} + +static int +tegra_nouveau_set_busid(struct drm_device *dev, struct drm_master *master) +{ + int id; + + id = dev->platformdev->id; + if (id < 0) + id = 0; + + master->unique = kmem_asprintf("platform:tegra_nouveau:%02d", id); + if (master->unique == NULL) + return -ENOMEM; + master->unique_len = strlen(master->unique); + + return 0; +} + +static int +tegra_nouveau_irq_install(struct drm_device *dev, + irqreturn_t (*handler)(void *), int flags, const char *name, void *arg, + struct drm_bus_irq_cookie **cookiep) +{ + void *ih; + int irq = TEGRA_INTR_GPU; + + ih = intr_establish(irq, IPL_DRM, IST_LEVEL, handler, arg); + if (ih == NULL) { + aprint_error_dev(dev->dev, + "couldn't establish interrupt (%s)\n", name); + return -ENOENT; + } + + aprint_normal_dev(dev->dev, "interrupting on irq %d (%s)\n", + irq, name); + *cookiep = (struct drm_bus_irq_cookie *)ih; + return 0; +} + +static void +tegra_nouveau_irq_uninstall(struct drm_device *dev, + struct drm_bus_irq_cookie *cookie) +{ + intr_disestablish(cookie); +}