gpu: host1x: Add Tegra186 support
authorMikko Perttunen <mperttunen@nvidia.com>
Tue, 5 Sep 2017 08:43:05 +0000 (11:43 +0300)
committerThierry Reding <treding@nvidia.com>
Fri, 20 Oct 2017 12:19:51 +0000 (14:19 +0200)
Add support for the implementation of Host1x present on the Tegra186.
The register space has been shuffled around a little bit, requiring
addition of some chip-specific code sections. Tegra186 also adds
several new features, most importantly the hypervisor, but those are
not yet supported with this commit.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
Tested-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
18 files changed:
drivers/gpu/host1x/Makefile
drivers/gpu/host1x/dev.c
drivers/gpu/host1x/dev.h
drivers/gpu/host1x/hw/cdma_hw.c
drivers/gpu/host1x/hw/debug_hw.c
drivers/gpu/host1x/hw/debug_hw_1x01.c [new file with mode: 0644]
drivers/gpu/host1x/hw/debug_hw_1x06.c [new file with mode: 0644]
drivers/gpu/host1x/hw/host1x01.c
drivers/gpu/host1x/hw/host1x02.c
drivers/gpu/host1x/hw/host1x04.c
drivers/gpu/host1x/hw/host1x05.c
drivers/gpu/host1x/hw/host1x06.c [new file with mode: 0644]
drivers/gpu/host1x/hw/host1x06.h [new file with mode: 0644]
drivers/gpu/host1x/hw/host1x06_hardware.h [new file with mode: 0644]
drivers/gpu/host1x/hw/hw_host1x06_hypervisor.h [new file with mode: 0644]
drivers/gpu/host1x/hw/hw_host1x06_uclass.h [new file with mode: 0644]
drivers/gpu/host1x/hw/hw_host1x06_vm.h [new file with mode: 0644]
drivers/gpu/host1x/hw/intr_hw.c

index a1d9974..4fb61bd 100644 (file)
@@ -11,6 +11,7 @@ host1x-y = \
        hw/host1x01.o \
        hw/host1x02.o \
        hw/host1x04.o \
-       hw/host1x05.o
+       hw/host1x05.o \
+       hw/host1x06.o
 
 obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
index 34a3583..773d633 100644 (file)
 #include "hw/host1x02.h"
 #include "hw/host1x04.h"
 #include "hw/host1x05.h"
+#include "hw/host1x06.h"
+
+void host1x_hypervisor_writel(struct host1x *host1x, u32 v, u32 r)
+{
+       writel(v, host1x->hv_regs + r);
+}
+
+u32 host1x_hypervisor_readl(struct host1x *host1x, u32 r)
+{
+       return readl(host1x->hv_regs + r);
+}
 
 void host1x_sync_writel(struct host1x *host1x, u32 v, u32 r)
 {
@@ -104,7 +115,19 @@ static const struct host1x_info host1x05_info = {
        .dma_mask = DMA_BIT_MASK(34),
 };
 
+static const struct host1x_info host1x06_info = {
+       .nb_channels = 63,
+       .nb_pts = 576,
+       .nb_mlocks = 24,
+       .nb_bases = 16,
+       .init = host1x06_init,
+       .sync_offset = 0x0,
+       .dma_mask = DMA_BIT_MASK(34),
+       .has_hypervisor = true,
+};
+
 static const struct of_device_id host1x_of_match[] = {
+       { .compatible = "nvidia,tegra186-host1x", .data = &host1x06_info, },
        { .compatible = "nvidia,tegra210-host1x", .data = &host1x05_info, },
        { .compatible = "nvidia,tegra124-host1x", .data = &host1x04_info, },
        { .compatible = "nvidia,tegra114-host1x", .data = &host1x02_info, },
@@ -117,7 +140,7 @@ MODULE_DEVICE_TABLE(of, host1x_of_match);
 static int host1x_probe(struct platform_device *pdev)
 {
        struct host1x *host;
-       struct resource *regs;
+       struct resource *regs, *hv_regs = NULL;
        int syncpt_irq;
        int err;
 
@@ -127,10 +150,26 @@ static int host1x_probe(struct platform_device *pdev)
 
        host->info = of_device_get_match_data(&pdev->dev);
 
-       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!regs) {
-               dev_err(&pdev->dev, "failed to get registers\n");
-               return -ENXIO;
+       if (host->info->has_hypervisor) {
+               regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vm");
+               if (!regs) {
+                       dev_err(&pdev->dev, "failed to get vm registers\n");
+                       return -ENXIO;
+               }
+
+               hv_regs = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                                                      "hypervisor");
+               if (!hv_regs) {
+                       dev_err(&pdev->dev,
+                               "failed to get hypervisor registers\n");
+                       return -ENXIO;
+               }
+       } else {
+               regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+               if (!regs) {
+                       dev_err(&pdev->dev, "failed to get registers\n");
+                       return -ENXIO;
+               }
        }
 
        syncpt_irq = platform_get_irq(pdev, 0);
@@ -151,6 +190,12 @@ static int host1x_probe(struct platform_device *pdev)
        if (IS_ERR(host->regs))
                return PTR_ERR(host->regs);
 
+       if (host->info->has_hypervisor) {
+               host->hv_regs = devm_ioremap_resource(&pdev->dev, hv_regs);
+               if (IS_ERR(host->hv_regs))
+                       return PTR_ERR(host->hv_regs);
+       }
+
        dma_set_mask_and_coherent(host->dev, host->info->dma_mask);
 
        if (host->info->init) {
index ffdbc15..def802c 100644 (file)
@@ -100,12 +100,14 @@ struct host1x_info {
        int (*init)(struct host1x *host1x); /* initialize per SoC ops */
        unsigned int sync_offset; /* offset of syncpoint registers */
        u64 dma_mask; /* mask of addressable memory */
+       bool has_hypervisor; /* has hypervisor registers */
 };
 
 struct host1x {
        const struct host1x_info *info;
 
        void __iomem *regs;
+       void __iomem *hv_regs; /* hypervisor region */
        struct host1x_syncpt *syncpt;
        struct host1x_syncpt_base *bases;
        struct device *dev;
@@ -140,6 +142,8 @@ struct host1x {
        struct list_head list;
 };
 
+void host1x_hypervisor_writel(struct host1x *host1x, u32 r, u32 v);
+u32 host1x_hypervisor_readl(struct host1x *host1x, u32 r);
 void host1x_sync_writel(struct host1x *host1x, u32 r, u32 v);
 u32 host1x_sync_readl(struct host1x *host1x, u32 r);
 void host1x_ch_writel(struct host1x_channel *ch, u32 r, u32 v);
index 6b23111..ce32053 100644 (file)
@@ -172,6 +172,30 @@ static void cdma_stop(struct host1x_cdma *cdma)
        mutex_unlock(&cdma->lock);
 }
 
+static void cdma_hw_cmdproc_stop(struct host1x *host, struct host1x_channel *ch,
+                                bool stop)
+{
+#if HOST1X_HW >= 6
+       host1x_ch_writel(ch, stop ? 0x1 : 0x0, HOST1X_CHANNEL_CMDPROC_STOP);
+#else
+       u32 cmdproc_stop = host1x_sync_readl(host, HOST1X_SYNC_CMDPROC_STOP);
+       if (stop)
+               cmdproc_stop |= BIT(ch->id);
+       else
+               cmdproc_stop &= ~BIT(ch->id);
+       host1x_sync_writel(host, cmdproc_stop, HOST1X_SYNC_CMDPROC_STOP);
+#endif
+}
+
+static void cdma_hw_teardown(struct host1x *host, struct host1x_channel *ch)
+{
+#if HOST1X_HW >= 6
+       host1x_ch_writel(ch, 0x1, HOST1X_CHANNEL_TEARDOWN);
+#else
+       host1x_sync_writel(host, BIT(ch->id), HOST1X_SYNC_CH_TEARDOWN);
+#endif
+}
+
 /*
  * Stops both channel's command processor and CDMA immediately.
  * Also, tears down the channel and resets corresponding module.
@@ -180,7 +204,6 @@ static void cdma_freeze(struct host1x_cdma *cdma)
 {
        struct host1x *host = cdma_to_host1x(cdma);
        struct host1x_channel *ch = cdma_to_channel(cdma);
-       u32 cmdproc_stop;
 
        if (cdma->torndown && !cdma->running) {
                dev_warn(host->dev, "Already torn down\n");
@@ -189,9 +212,7 @@ static void cdma_freeze(struct host1x_cdma *cdma)
 
        dev_dbg(host->dev, "freezing channel (id %d)\n", ch->id);
 
-       cmdproc_stop = host1x_sync_readl(host, HOST1X_SYNC_CMDPROC_STOP);
-       cmdproc_stop |= BIT(ch->id);
-       host1x_sync_writel(host, cmdproc_stop, HOST1X_SYNC_CMDPROC_STOP);
+       cdma_hw_cmdproc_stop(host, ch, true);
 
        dev_dbg(host->dev, "%s: DMA GET 0x%x, PUT HW 0x%x / shadow 0x%x\n",
                __func__, host1x_ch_readl(ch, HOST1X_CHANNEL_DMAGET),
@@ -201,7 +222,7 @@ static void cdma_freeze(struct host1x_cdma *cdma)
        host1x_ch_writel(ch, HOST1X_CHANNEL_DMACTRL_DMASTOP,
                         HOST1X_CHANNEL_DMACTRL);
 
-       host1x_sync_writel(host, BIT(ch->id), HOST1X_SYNC_CH_TEARDOWN);
+       cdma_hw_teardown(host, ch);
 
        cdma->running = false;
        cdma->torndown = true;
@@ -211,15 +232,12 @@ static void cdma_resume(struct host1x_cdma *cdma, u32 getptr)
 {
        struct host1x *host1x = cdma_to_host1x(cdma);
        struct host1x_channel *ch = cdma_to_channel(cdma);
-       u32 cmdproc_stop;
 
        dev_dbg(host1x->dev,
                "resuming channel (id %u, DMAGET restart = 0x%x)\n",
                ch->id, getptr);
 
-       cmdproc_stop = host1x_sync_readl(host1x, HOST1X_SYNC_CMDPROC_STOP);
-       cmdproc_stop &= ~BIT(ch->id);
-       host1x_sync_writel(host1x, cmdproc_stop, HOST1X_SYNC_CMDPROC_STOP);
+       cdma_hw_cmdproc_stop(host1x, ch, false);
 
        cdma->torndown = false;
        cdma_timeout_restart(cdma, getptr);
@@ -232,7 +250,7 @@ static void cdma_resume(struct host1x_cdma *cdma, u32 getptr)
  */
 static void cdma_timeout_handler(struct work_struct *work)
 {
-       u32 prev_cmdproc, cmdproc_stop, syncpt_val;
+       u32 syncpt_val;
        struct host1x_cdma *cdma;
        struct host1x *host1x;
        struct host1x_channel *ch;
@@ -254,12 +272,7 @@ static void cdma_timeout_handler(struct work_struct *work)
        }
 
        /* stop processing to get a clean snapshot */
-       prev_cmdproc = host1x_sync_readl(host1x, HOST1X_SYNC_CMDPROC_STOP);
-       cmdproc_stop = prev_cmdproc | BIT(ch->id);
-       host1x_sync_writel(host1x, cmdproc_stop, HOST1X_SYNC_CMDPROC_STOP);
-
-       dev_dbg(host1x->dev, "cdma_timeout: cmdproc was 0x%x is 0x%x\n",
-               prev_cmdproc, cmdproc_stop);
+       cdma_hw_cmdproc_stop(host1x, ch, true);
 
        syncpt_val = host1x_syncpt_load(cdma->timeout.syncpt);
 
@@ -268,9 +281,7 @@ static void cdma_timeout_handler(struct work_struct *work)
                dev_dbg(host1x->dev,
                        "cdma_timeout: expired, but buffer had completed\n");
                /* restore */
-               cmdproc_stop = prev_cmdproc & ~(BIT(ch->id));
-               host1x_sync_writel(host1x, cmdproc_stop,
-                                  HOST1X_SYNC_CMDPROC_STOP);
+               cdma_hw_cmdproc_stop(host1x, ch, false);
                mutex_unlock(&cdma->lock);
                return;
        }
index 7a4a328..770d92e 100644 (file)
@@ -174,138 +174,11 @@ static void show_channel_gathers(struct output *o, struct host1x_cdma *cdma)
        }
 }
 
-static void host1x_debug_show_channel_cdma(struct host1x *host,
-                                          struct host1x_channel *ch,
-                                          struct output *o)
-{
-       struct host1x_cdma *cdma = &ch->cdma;
-       u32 dmaput, dmaget, dmactrl;
-       u32 cbstat, cbread;
-       u32 val, base, baseval;
-
-       dmaput = host1x_ch_readl(ch, HOST1X_CHANNEL_DMAPUT);
-       dmaget = host1x_ch_readl(ch, HOST1X_CHANNEL_DMAGET);
-       dmactrl = host1x_ch_readl(ch, HOST1X_CHANNEL_DMACTRL);
-       cbread = host1x_sync_readl(host, HOST1X_SYNC_CBREAD(ch->id));
-       cbstat = host1x_sync_readl(host, HOST1X_SYNC_CBSTAT(ch->id));
-
-       host1x_debug_output(o, "%u-%s: ", ch->id, dev_name(ch->dev));
-
-       if (HOST1X_CHANNEL_DMACTRL_DMASTOP_V(dmactrl) ||
-           !ch->cdma.push_buffer.mapped) {
-               host1x_debug_output(o, "inactive\n\n");
-               return;
-       }
-
-       if (HOST1X_SYNC_CBSTAT_CBCLASS_V(cbstat) == HOST1X_CLASS_HOST1X &&
-           HOST1X_SYNC_CBSTAT_CBOFFSET_V(cbstat) ==
-                       HOST1X_UCLASS_WAIT_SYNCPT)
-               host1x_debug_output(o, "waiting on syncpt %d val %d\n",
-                                   cbread >> 24, cbread & 0xffffff);
-       else if (HOST1X_SYNC_CBSTAT_CBCLASS_V(cbstat) ==
-                               HOST1X_CLASS_HOST1X &&
-                HOST1X_SYNC_CBSTAT_CBOFFSET_V(cbstat) ==
-                               HOST1X_UCLASS_WAIT_SYNCPT_BASE) {
-               base = (cbread >> 16) & 0xff;
-               baseval =
-                       host1x_sync_readl(host, HOST1X_SYNC_SYNCPT_BASE(base));
-               val = cbread & 0xffff;
-               host1x_debug_output(o, "waiting on syncpt %d val %d (base %d = %d; offset = %d)\n",
-                                   cbread >> 24, baseval + val, base,
-                                   baseval, val);
-       } else
-               host1x_debug_output(o, "active class %02x, offset %04x, val %08x\n",
-                                   HOST1X_SYNC_CBSTAT_CBCLASS_V(cbstat),
-                                   HOST1X_SYNC_CBSTAT_CBOFFSET_V(cbstat),
-                                   cbread);
-
-       host1x_debug_output(o, "DMAPUT %08x, DMAGET %08x, DMACTL %08x\n",
-                           dmaput, dmaget, dmactrl);
-       host1x_debug_output(o, "CBREAD %08x, CBSTAT %08x\n", cbread, cbstat);
-
-       show_channel_gathers(o, cdma);
-       host1x_debug_output(o, "\n");
-}
-
-static void host1x_debug_show_channel_fifo(struct host1x *host,
-                                          struct host1x_channel *ch,
-                                          struct output *o)
-{
-       u32 val, rd_ptr, wr_ptr, start, end;
-       unsigned int data_count = 0;
-
-       host1x_debug_output(o, "%u: fifo:\n", ch->id);
-
-       val = host1x_ch_readl(ch, HOST1X_CHANNEL_FIFOSTAT);
-       host1x_debug_output(o, "FIFOSTAT %08x\n", val);
-       if (HOST1X_CHANNEL_FIFOSTAT_CFEMPTY_V(val)) {
-               host1x_debug_output(o, "[empty]\n");
-               return;
-       }
-
-       host1x_sync_writel(host, 0x0, HOST1X_SYNC_CFPEEK_CTRL);
-       host1x_sync_writel(host, HOST1X_SYNC_CFPEEK_CTRL_ENA_F(1) |
-                          HOST1X_SYNC_CFPEEK_CTRL_CHANNR_F(ch->id),
-                          HOST1X_SYNC_CFPEEK_CTRL);
-
-       val = host1x_sync_readl(host, HOST1X_SYNC_CFPEEK_PTRS);
-       rd_ptr = HOST1X_SYNC_CFPEEK_PTRS_CF_RD_PTR_V(val);
-       wr_ptr = HOST1X_SYNC_CFPEEK_PTRS_CF_WR_PTR_V(val);
-
-       val = host1x_sync_readl(host, HOST1X_SYNC_CF_SETUP(ch->id));
-       start = HOST1X_SYNC_CF_SETUP_BASE_V(val);
-       end = HOST1X_SYNC_CF_SETUP_LIMIT_V(val);
-
-       do {
-               host1x_sync_writel(host, 0x0, HOST1X_SYNC_CFPEEK_CTRL);
-               host1x_sync_writel(host, HOST1X_SYNC_CFPEEK_CTRL_ENA_F(1) |
-                                  HOST1X_SYNC_CFPEEK_CTRL_CHANNR_F(ch->id) |
-                                  HOST1X_SYNC_CFPEEK_CTRL_ADDR_F(rd_ptr),
-                                  HOST1X_SYNC_CFPEEK_CTRL);
-               val = host1x_sync_readl(host, HOST1X_SYNC_CFPEEK_READ);
-
-               if (!data_count) {
-                       host1x_debug_output(o, "%08x:", val);
-                       data_count = show_channel_command(o, val);
-               } else {
-                       host1x_debug_output(o, "%08x%s", val,
-                                           data_count > 0 ? ", " : "])\n");
-                       data_count--;
-               }
-
-               if (rd_ptr == end)
-                       rd_ptr = start;
-               else
-                       rd_ptr++;
-       } while (rd_ptr != wr_ptr);
-
-       if (data_count)
-               host1x_debug_output(o, ", ...])\n");
-       host1x_debug_output(o, "\n");
-
-       host1x_sync_writel(host, 0x0, HOST1X_SYNC_CFPEEK_CTRL);
-}
-
-static void host1x_debug_show_mlocks(struct host1x *host, struct output *o)
-{
-       unsigned int i;
-
-       host1x_debug_output(o, "---- mlocks ----\n");
-
-       for (i = 0; i < host1x_syncpt_nb_mlocks(host); i++) {
-               u32 owner =
-                       host1x_sync_readl(host, HOST1X_SYNC_MLOCK_OWNER(i));
-               if (HOST1X_SYNC_MLOCK_OWNER_CH_OWNS_V(owner))
-                       host1x_debug_output(o, "%u: locked by channel %u\n",
-                               i, HOST1X_SYNC_MLOCK_OWNER_CHID_V(owner));
-               else if (HOST1X_SYNC_MLOCK_OWNER_CPU_OWNS_V(owner))
-                       host1x_debug_output(o, "%u: locked by cpu\n", i);
-               else
-                       host1x_debug_output(o, "%u: unlocked\n", i);
-       }
-
-       host1x_debug_output(o, "\n");
-}
+#if HOST1X_HW >= 6
+#include "debug_hw_1x06.c"
+#else
+#include "debug_hw_1x01.c"
+#endif
 
 static const struct host1x_debug_ops host1x_debug_ops = {
        .show_channel_cdma = host1x_debug_show_channel_cdma,
diff --git a/drivers/gpu/host1x/hw/debug_hw_1x01.c b/drivers/gpu/host1x/hw/debug_hw_1x01.c
new file mode 100644 (file)
index 0000000..8f24390
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2010 Google, Inc.
+ * Author: Erik Gilling <konkers@android.com>
+ *
+ * Copyright (C) 2011-2013 NVIDIA Corporation
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "../dev.h"
+#include "../debug.h"
+#include "../cdma.h"
+#include "../channel.h"
+
+static void host1x_debug_show_channel_cdma(struct host1x *host,
+                                          struct host1x_channel *ch,
+                                          struct output *o)
+{
+       struct host1x_cdma *cdma = &ch->cdma;
+       u32 dmaput, dmaget, dmactrl;
+       u32 cbstat, cbread;
+       u32 val, base, baseval;
+
+       dmaput = host1x_ch_readl(ch, HOST1X_CHANNEL_DMAPUT);
+       dmaget = host1x_ch_readl(ch, HOST1X_CHANNEL_DMAGET);
+       dmactrl = host1x_ch_readl(ch, HOST1X_CHANNEL_DMACTRL);
+       cbread = host1x_sync_readl(host, HOST1X_SYNC_CBREAD(ch->id));
+       cbstat = host1x_sync_readl(host, HOST1X_SYNC_CBSTAT(ch->id));
+
+       host1x_debug_output(o, "%u-%s: ", ch->id, dev_name(ch->dev));
+
+       if (HOST1X_CHANNEL_DMACTRL_DMASTOP_V(dmactrl) ||
+           !ch->cdma.push_buffer.mapped) {
+               host1x_debug_output(o, "inactive\n\n");
+               return;
+       }
+
+       if (HOST1X_SYNC_CBSTAT_CBCLASS_V(cbstat) == HOST1X_CLASS_HOST1X &&
+           HOST1X_SYNC_CBSTAT_CBOFFSET_V(cbstat) ==
+                       HOST1X_UCLASS_WAIT_SYNCPT)
+               host1x_debug_output(o, "waiting on syncpt %d val %d\n",
+                                   cbread >> 24, cbread & 0xffffff);
+       else if (HOST1X_SYNC_CBSTAT_CBCLASS_V(cbstat) ==
+                               HOST1X_CLASS_HOST1X &&
+                HOST1X_SYNC_CBSTAT_CBOFFSET_V(cbstat) ==
+                               HOST1X_UCLASS_WAIT_SYNCPT_BASE) {
+               base = (cbread >> 16) & 0xff;
+               baseval =
+                       host1x_sync_readl(host, HOST1X_SYNC_SYNCPT_BASE(base));
+               val = cbread & 0xffff;
+               host1x_debug_output(o, "waiting on syncpt %d val %d (base %d = %d; offset = %d)\n",
+                                   cbread >> 24, baseval + val, base,
+                                   baseval, val);
+       } else
+               host1x_debug_output(o, "active class %02x, offset %04x, val %08x\n",
+                                   HOST1X_SYNC_CBSTAT_CBCLASS_V(cbstat),
+                                   HOST1X_SYNC_CBSTAT_CBOFFSET_V(cbstat),
+                                   cbread);
+
+       host1x_debug_output(o, "DMAPUT %08x, DMAGET %08x, DMACTL %08x\n",
+                           dmaput, dmaget, dmactrl);
+       host1x_debug_output(o, "CBREAD %08x, CBSTAT %08x\n", cbread, cbstat);
+
+       show_channel_gathers(o, cdma);
+       host1x_debug_output(o, "\n");
+}
+
+static void host1x_debug_show_channel_fifo(struct host1x *host,
+                                          struct host1x_channel *ch,
+                                          struct output *o)
+{
+       u32 val, rd_ptr, wr_ptr, start, end;
+       unsigned int data_count = 0;
+
+       host1x_debug_output(o, "%u: fifo:\n", ch->id);
+
+       val = host1x_ch_readl(ch, HOST1X_CHANNEL_FIFOSTAT);
+       host1x_debug_output(o, "FIFOSTAT %08x\n", val);
+       if (HOST1X_CHANNEL_FIFOSTAT_CFEMPTY_V(val)) {
+               host1x_debug_output(o, "[empty]\n");
+               return;
+       }
+
+       host1x_sync_writel(host, 0x0, HOST1X_SYNC_CFPEEK_CTRL);
+       host1x_sync_writel(host, HOST1X_SYNC_CFPEEK_CTRL_ENA_F(1) |
+                          HOST1X_SYNC_CFPEEK_CTRL_CHANNR_F(ch->id),
+                          HOST1X_SYNC_CFPEEK_CTRL);
+
+       val = host1x_sync_readl(host, HOST1X_SYNC_CFPEEK_PTRS);
+       rd_ptr = HOST1X_SYNC_CFPEEK_PTRS_CF_RD_PTR_V(val);
+       wr_ptr = HOST1X_SYNC_CFPEEK_PTRS_CF_WR_PTR_V(val);
+
+       val = host1x_sync_readl(host, HOST1X_SYNC_CF_SETUP(ch->id));
+       start = HOST1X_SYNC_CF_SETUP_BASE_V(val);
+       end = HOST1X_SYNC_CF_SETUP_LIMIT_V(val);
+
+       do {
+               host1x_sync_writel(host, 0x0, HOST1X_SYNC_CFPEEK_CTRL);
+               host1x_sync_writel(host, HOST1X_SYNC_CFPEEK_CTRL_ENA_F(1) |
+                                  HOST1X_SYNC_CFPEEK_CTRL_CHANNR_F(ch->id) |
+                                  HOST1X_SYNC_CFPEEK_CTRL_ADDR_F(rd_ptr),
+                                  HOST1X_SYNC_CFPEEK_CTRL);
+               val = host1x_sync_readl(host, HOST1X_SYNC_CFPEEK_READ);
+
+               if (!data_count) {
+                       host1x_debug_output(o, "%08x:", val);
+                       data_count = show_channel_command(o, val);
+               } else {
+                       host1x_debug_output(o, "%08x%s", val,
+                                           data_count > 0 ? ", " : "])\n");
+                       data_count--;
+               }
+
+               if (rd_ptr == end)
+                       rd_ptr = start;
+               else
+                       rd_ptr++;
+       } while (rd_ptr != wr_ptr);
+
+       if (data_count)
+               host1x_debug_output(o, ", ...])\n");
+       host1x_debug_output(o, "\n");
+
+       host1x_sync_writel(host, 0x0, HOST1X_SYNC_CFPEEK_CTRL);
+}
+
+static void host1x_debug_show_mlocks(struct host1x *host, struct output *o)
+{
+       unsigned int i;
+
+       host1x_debug_output(o, "---- mlocks ----\n");
+
+       for (i = 0; i < host1x_syncpt_nb_mlocks(host); i++) {
+               u32 owner =
+                       host1x_sync_readl(host, HOST1X_SYNC_MLOCK_OWNER(i));
+               if (HOST1X_SYNC_MLOCK_OWNER_CH_OWNS_V(owner))
+                       host1x_debug_output(o, "%u: locked by channel %u\n",
+                               i, HOST1X_SYNC_MLOCK_OWNER_CHID_V(owner));
+               else if (HOST1X_SYNC_MLOCK_OWNER_CPU_OWNS_V(owner))
+                       host1x_debug_output(o, "%u: locked by cpu\n", i);
+               else
+                       host1x_debug_output(o, "%u: unlocked\n", i);
+       }
+
+       host1x_debug_output(o, "\n");
+}
diff --git a/drivers/gpu/host1x/hw/debug_hw_1x06.c b/drivers/gpu/host1x/hw/debug_hw_1x06.c
new file mode 100644 (file)
index 0000000..9cdee65
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2010 Google, Inc.
+ * Author: Erik Gilling <konkers@android.com>
+ *
+ * Copyright (C) 2011-2017 NVIDIA Corporation
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "../dev.h"
+#include "../debug.h"
+#include "../cdma.h"
+#include "../channel.h"
+
+static void host1x_debug_show_channel_cdma(struct host1x *host,
+                                          struct host1x_channel *ch,
+                                          struct output *o)
+{
+       struct host1x_cdma *cdma = &ch->cdma;
+       u32 dmaput, dmaget, dmactrl;
+       u32 offset, class;
+       u32 ch_stat;
+
+       dmaput = host1x_ch_readl(ch, HOST1X_CHANNEL_DMAPUT);
+       dmaget = host1x_ch_readl(ch, HOST1X_CHANNEL_DMAGET);
+       dmactrl = host1x_ch_readl(ch, HOST1X_CHANNEL_DMACTRL);
+       offset = host1x_ch_readl(ch, HOST1X_CHANNEL_CMDP_OFFSET);
+       class = host1x_ch_readl(ch, HOST1X_CHANNEL_CMDP_CLASS);
+       ch_stat = host1x_ch_readl(ch, HOST1X_CHANNEL_CHANNELSTAT);
+
+       host1x_debug_output(o, "%u-%s: ", ch->id, dev_name(ch->dev));
+
+       if (dmactrl & HOST1X_CHANNEL_DMACTRL_DMASTOP ||
+           !ch->cdma.push_buffer.mapped) {
+               host1x_debug_output(o, "inactive\n\n");
+               return;
+       }
+
+       if (class == HOST1X_CLASS_HOST1X && offset == HOST1X_UCLASS_WAIT_SYNCPT)
+               host1x_debug_output(o, "waiting on syncpt\n");
+       else
+               host1x_debug_output(o, "active class %02x, offset %04x\n",
+                                   class, offset);
+
+       host1x_debug_output(o, "DMAPUT %08x, DMAGET %08x, DMACTL %08x\n",
+                           dmaput, dmaget, dmactrl);
+       host1x_debug_output(o, "CHANNELSTAT %02x\n", ch_stat);
+
+       show_channel_gathers(o, cdma);
+       host1x_debug_output(o, "\n");
+}
+
+static void host1x_debug_show_channel_fifo(struct host1x *host,
+                                          struct host1x_channel *ch,
+                                          struct output *o)
+{
+       u32 val, rd_ptr, wr_ptr, start, end;
+       unsigned int data_count = 0;
+
+       host1x_debug_output(o, "%u: fifo:\n", ch->id);
+
+       val = host1x_ch_readl(ch, HOST1X_CHANNEL_CMDFIFO_STAT);
+       host1x_debug_output(o, "CMDFIFO_STAT %08x\n", val);
+       if (val & HOST1X_CHANNEL_CMDFIFO_STAT_EMPTY) {
+               host1x_debug_output(o, "[empty]\n");
+               return;
+       }
+
+       val = host1x_ch_readl(ch, HOST1X_CHANNEL_CMDFIFO_RDATA);
+       host1x_debug_output(o, "CMDFIFO_RDATA %08x\n", val);
+
+       /* Peek pointer values are invalid during SLCG, so disable it */
+       host1x_hypervisor_writel(host, 0x1, HOST1X_HV_ICG_EN_OVERRIDE);
+
+       val = 0;
+       val |= HOST1X_HV_CMDFIFO_PEEK_CTRL_ENABLE;
+       val |= HOST1X_HV_CMDFIFO_PEEK_CTRL_CHANNEL(ch->id);
+       host1x_hypervisor_writel(host, val, HOST1X_HV_CMDFIFO_PEEK_CTRL);
+
+       val = host1x_hypervisor_readl(host, HOST1X_HV_CMDFIFO_PEEK_PTRS);
+       rd_ptr = HOST1X_HV_CMDFIFO_PEEK_PTRS_RD_PTR_V(val);
+       wr_ptr = HOST1X_HV_CMDFIFO_PEEK_PTRS_WR_PTR_V(val);
+
+       val = host1x_hypervisor_readl(host, HOST1X_HV_CMDFIFO_SETUP(ch->id));
+       start = HOST1X_HV_CMDFIFO_SETUP_BASE_V(val);
+       end = HOST1X_HV_CMDFIFO_SETUP_LIMIT_V(val);
+
+       do {
+               val = 0;
+               val |= HOST1X_HV_CMDFIFO_PEEK_CTRL_ENABLE;
+               val |= HOST1X_HV_CMDFIFO_PEEK_CTRL_CHANNEL(ch->id);
+               val |= HOST1X_HV_CMDFIFO_PEEK_CTRL_ADDR(rd_ptr);
+               host1x_hypervisor_writel(host, val,
+                                        HOST1X_HV_CMDFIFO_PEEK_CTRL);
+
+               val = host1x_hypervisor_readl(host,
+                                             HOST1X_HV_CMDFIFO_PEEK_READ);
+
+               if (!data_count) {
+                       host1x_debug_output(o, "%08x:", val);
+                       data_count = show_channel_command(o, val);
+               } else {
+                       host1x_debug_output(o, "%08x%s", val,
+                                           data_count > 0 ? ", " : "])\n");
+                       data_count--;
+               }
+
+               if (rd_ptr == end)
+                       rd_ptr = start;
+               else
+                       rd_ptr++;
+       } while (rd_ptr != wr_ptr);
+
+       if (data_count)
+               host1x_debug_output(o, ", ...])\n");
+       host1x_debug_output(o, "\n");
+
+       host1x_hypervisor_writel(host, 0x0, HOST1X_HV_CMDFIFO_PEEK_CTRL);
+       host1x_hypervisor_writel(host, 0x0, HOST1X_HV_ICG_EN_OVERRIDE);
+}
+
+static void host1x_debug_show_mlocks(struct host1x *host, struct output *o)
+{
+       /* TODO */
+}
index 859b73b..bb124f8 100644 (file)
@@ -21,6 +21,8 @@
 #include "host1x01_hardware.h"
 
 /* include code */
+#define HOST1X_HW 1
+
 #include "cdma_hw.c"
 #include "channel_hw.c"
 #include "debug_hw.c"
index 928946c..c5f85db 100644 (file)
@@ -21,6 +21,8 @@
 #include "host1x02_hardware.h"
 
 /* include code */
+#define HOST1X_HW 2
+
 #include "cdma_hw.c"
 #include "channel_hw.c"
 #include "debug_hw.c"
index 8007c70..f102a1a 100644 (file)
@@ -21,6 +21,8 @@
 #include "host1x04_hardware.h"
 
 /* include code */
+#define HOST1X_HW 4
+
 #include "cdma_hw.c"
 #include "channel_hw.c"
 #include "debug_hw.c"
index 047097c..2b1239d 100644 (file)
@@ -21,6 +21,8 @@
 #include "host1x05_hardware.h"
 
 /* include code */
+#define HOST1X_HW 5
+
 #include "cdma_hw.c"
 #include "channel_hw.c"
 #include "debug_hw.c"
diff --git a/drivers/gpu/host1x/hw/host1x06.c b/drivers/gpu/host1x/hw/host1x06.c
new file mode 100644 (file)
index 0000000..a662308
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Host1x init for Tegra186 SoCs
+ *
+ * Copyright (c) 2017 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* include hw specification */
+#include "host1x06.h"
+#include "host1x06_hardware.h"
+
+/* include code */
+#define HOST1X_HW 6
+
+#include "cdma_hw.c"
+#include "channel_hw.c"
+#include "debug_hw.c"
+#include "intr_hw.c"
+#include "syncpt_hw.c"
+
+#include "../dev.h"
+
+int host1x06_init(struct host1x *host)
+{
+       host->channel_op = &host1x_channel_ops;
+       host->cdma_op = &host1x_cdma_ops;
+       host->cdma_pb_op = &host1x_pushbuffer_ops;
+       host->syncpt_op = &host1x_syncpt_ops;
+       host->intr_op = &host1x_intr_ops;
+       host->debug_op = &host1x_debug_ops;
+
+       return 0;
+}
diff --git a/drivers/gpu/host1x/hw/host1x06.h b/drivers/gpu/host1x/hw/host1x06.h
new file mode 100644 (file)
index 0000000..d9abe14
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Host1x init for Tegra186 SoCs
+ *
+ * Copyright (c) 2017 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HOST1X_HOST1X06_H
+#define HOST1X_HOST1X06_H
+
+struct host1x;
+
+int host1x06_init(struct host1x *host);
+
+#endif
diff --git a/drivers/gpu/host1x/hw/host1x06_hardware.h b/drivers/gpu/host1x/hw/host1x06_hardware.h
new file mode 100644 (file)
index 0000000..3039c92
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Tegra host1x Register Offsets for Tegra186
+ *
+ * Copyright (c) 2017 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __HOST1X_HOST1X06_HARDWARE_H
+#define __HOST1X_HOST1X06_HARDWARE_H
+
+#include <linux/types.h>
+#include <linux/bitops.h>
+
+#include "hw_host1x06_uclass.h"
+#include "hw_host1x06_vm.h"
+#include "hw_host1x06_hypervisor.h"
+
+static inline u32 host1x_class_host_wait_syncpt(
+       unsigned indx, unsigned threshold)
+{
+       return host1x_uclass_wait_syncpt_indx_f(indx)
+               | host1x_uclass_wait_syncpt_thresh_f(threshold);
+}
+
+static inline u32 host1x_class_host_load_syncpt_base(
+       unsigned indx, unsigned threshold)
+{
+       return host1x_uclass_load_syncpt_base_base_indx_f(indx)
+               | host1x_uclass_load_syncpt_base_value_f(threshold);
+}
+
+static inline u32 host1x_class_host_wait_syncpt_base(
+       unsigned indx, unsigned base_indx, unsigned offset)
+{
+       return host1x_uclass_wait_syncpt_base_indx_f(indx)
+               | host1x_uclass_wait_syncpt_base_base_indx_f(base_indx)
+               | host1x_uclass_wait_syncpt_base_offset_f(offset);
+}
+
+static inline u32 host1x_class_host_incr_syncpt_base(
+       unsigned base_indx, unsigned offset)
+{
+       return host1x_uclass_incr_syncpt_base_base_indx_f(base_indx)
+               | host1x_uclass_incr_syncpt_base_offset_f(offset);
+}
+
+static inline u32 host1x_class_host_incr_syncpt(
+       unsigned cond, unsigned indx)
+{
+       return host1x_uclass_incr_syncpt_cond_f(cond)
+               | host1x_uclass_incr_syncpt_indx_f(indx);
+}
+
+static inline u32 host1x_class_host_indoff_reg_write(
+       unsigned mod_id, unsigned offset, bool auto_inc)
+{
+       u32 v = host1x_uclass_indoff_indbe_f(0xf)
+               | host1x_uclass_indoff_indmodid_f(mod_id)
+               | host1x_uclass_indoff_indroffset_f(offset);
+       if (auto_inc)
+               v |= host1x_uclass_indoff_autoinc_f(1);
+       return v;
+}
+
+static inline u32 host1x_class_host_indoff_reg_read(
+       unsigned mod_id, unsigned offset, bool auto_inc)
+{
+       u32 v = host1x_uclass_indoff_indmodid_f(mod_id)
+               | host1x_uclass_indoff_indroffset_f(offset)
+               | host1x_uclass_indoff_rwn_read_v();
+       if (auto_inc)
+               v |= host1x_uclass_indoff_autoinc_f(1);
+       return v;
+}
+
+/* cdma opcodes */
+static inline u32 host1x_opcode_setclass(
+       unsigned class_id, unsigned offset, unsigned mask)
+{
+       return (0 << 28) | (offset << 16) | (class_id << 6) | mask;
+}
+
+static inline u32 host1x_opcode_incr(unsigned offset, unsigned count)
+{
+       return (1 << 28) | (offset << 16) | count;
+}
+
+static inline u32 host1x_opcode_nonincr(unsigned offset, unsigned count)
+{
+       return (2 << 28) | (offset << 16) | count;
+}
+
+static inline u32 host1x_opcode_mask(unsigned offset, unsigned mask)
+{
+       return (3 << 28) | (offset << 16) | mask;
+}
+
+static inline u32 host1x_opcode_imm(unsigned offset, unsigned value)
+{
+       return (4 << 28) | (offset << 16) | value;
+}
+
+static inline u32 host1x_opcode_imm_incr_syncpt(unsigned cond, unsigned indx)
+{
+       return host1x_opcode_imm(host1x_uclass_incr_syncpt_r(),
+               host1x_class_host_incr_syncpt(cond, indx));
+}
+
+static inline u32 host1x_opcode_restart(unsigned address)
+{
+       return (5 << 28) | (address >> 4);
+}
+
+static inline u32 host1x_opcode_gather(unsigned count)
+{
+       return (6 << 28) | count;
+}
+
+static inline u32 host1x_opcode_gather_nonincr(unsigned offset,        unsigned count)
+{
+       return (6 << 28) | (offset << 16) | BIT(15) | count;
+}
+
+static inline u32 host1x_opcode_gather_incr(unsigned offset, unsigned count)
+{
+       return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count;
+}
+
+#define HOST1X_OPCODE_NOP host1x_opcode_nonincr(0, 0)
+
+#endif
diff --git a/drivers/gpu/host1x/hw/hw_host1x06_hypervisor.h b/drivers/gpu/host1x/hw/hw_host1x06_hypervisor.h
new file mode 100644 (file)
index 0000000..c05dab8
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#define HOST1X_HV_SYNCPT_PROT_EN                       0x1ac4
+#define HOST1X_HV_SYNCPT_PROT_EN_CH_EN                 BIT(1)
+#define HOST1X_HV_CH_KERNEL_FILTER_GBUFFER(x)          (0x2020 + (x * 4))
+#define HOST1X_HV_CMDFIFO_PEEK_CTRL                    0x233c
+#define HOST1X_HV_CMDFIFO_PEEK_CTRL_ADDR(x)            (x)
+#define HOST1X_HV_CMDFIFO_PEEK_CTRL_CHANNEL(x)         ((x) << 16)
+#define HOST1X_HV_CMDFIFO_PEEK_CTRL_ENABLE             BIT(31)
+#define HOST1X_HV_CMDFIFO_PEEK_READ                    0x2340
+#define HOST1X_HV_CMDFIFO_PEEK_PTRS                    0x2344
+#define HOST1X_HV_CMDFIFO_PEEK_PTRS_WR_PTR_V(x)                (((x) >> 16) & 0xfff)
+#define HOST1X_HV_CMDFIFO_PEEK_PTRS_RD_PTR_V(x)                ((x) & 0xfff)
+#define HOST1X_HV_CMDFIFO_SETUP(x)                     (0x2588 + (x * 4))
+#define HOST1X_HV_CMDFIFO_SETUP_LIMIT_V(x)             (((x) >> 16) & 0xfff)
+#define HOST1X_HV_CMDFIFO_SETUP_BASE_V(x)              ((x) & 0xfff)
+#define HOST1X_HV_ICG_EN_OVERRIDE                      0x2aa8
diff --git a/drivers/gpu/host1x/hw/hw_host1x06_uclass.h b/drivers/gpu/host1x/hw/hw_host1x06_uclass.h
new file mode 100644 (file)
index 0000000..4457486
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2017 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+ /*
+  * Function naming determines intended use:
+  *
+  *     <x>_r(void) : Returns the offset for register <x>.
+  *
+  *     <x>_w(void) : Returns the word offset for word (4 byte) element <x>.
+  *
+  *     <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits.
+  *
+  *     <x>_<y>_f(u32 v) : Returns a value based on 'v' which has been shifted
+  *         and masked to place it at field <y> of register <x>.  This value
+  *         can be |'d with others to produce a full register value for
+  *         register <x>.
+  *
+  *     <x>_<y>_m(void) : Returns a mask for field <y> of register <x>.  This
+  *         value can be ~'d and then &'d to clear the value of field <y> for
+  *         register <x>.
+  *
+  *     <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted
+  *         to place it at field <y> of register <x>.  This value can be |'d
+  *         with others to produce a full register value for <x>.
+  *
+  *     <x>_<y>_v(u32 r) : Returns the value of field <y> from a full register
+  *         <x> value 'r' after being shifted to place its LSB at bit 0.
+  *         This value is suitable for direct comparison with other unshifted
+  *         values appropriate for use in field <y> of register <x>.
+  *
+  *     <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for
+  *         field <y> of register <x>.  This value is suitable for direct
+  *         comparison with unshifted values appropriate for use in field <y>
+  *         of register <x>.
+  */
+
+#ifndef HOST1X_HW_HOST1X06_UCLASS_H
+#define HOST1X_HW_HOST1X06_UCLASS_H
+
+static inline u32 host1x_uclass_incr_syncpt_r(void)
+{
+       return 0x0;
+}
+#define HOST1X_UCLASS_INCR_SYNCPT \
+       host1x_uclass_incr_syncpt_r()
+static inline u32 host1x_uclass_incr_syncpt_cond_f(u32 v)
+{
+       return (v & 0xff) << 8;
+}
+#define HOST1X_UCLASS_INCR_SYNCPT_COND_F(v) \
+       host1x_uclass_incr_syncpt_cond_f(v)
+static inline u32 host1x_uclass_incr_syncpt_indx_f(u32 v)
+{
+       return (v & 0xff) << 0;
+}
+#define HOST1X_UCLASS_INCR_SYNCPT_INDX_F(v) \
+       host1x_uclass_incr_syncpt_indx_f(v)
+static inline u32 host1x_uclass_wait_syncpt_r(void)
+{
+       return 0x8;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT \
+       host1x_uclass_wait_syncpt_r()
+static inline u32 host1x_uclass_wait_syncpt_indx_f(u32 v)
+{
+       return (v & 0xff) << 24;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_INDX_F(v) \
+       host1x_uclass_wait_syncpt_indx_f(v)
+static inline u32 host1x_uclass_wait_syncpt_thresh_f(u32 v)
+{
+       return (v & 0xffffff) << 0;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_THRESH_F(v) \
+       host1x_uclass_wait_syncpt_thresh_f(v)
+static inline u32 host1x_uclass_wait_syncpt_base_r(void)
+{
+       return 0x9;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_BASE \
+       host1x_uclass_wait_syncpt_base_r()
+static inline u32 host1x_uclass_wait_syncpt_base_indx_f(u32 v)
+{
+       return (v & 0xff) << 24;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_INDX_F(v) \
+       host1x_uclass_wait_syncpt_base_indx_f(v)
+static inline u32 host1x_uclass_wait_syncpt_base_base_indx_f(u32 v)
+{
+       return (v & 0xff) << 16;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_BASE_INDX_F(v) \
+       host1x_uclass_wait_syncpt_base_base_indx_f(v)
+static inline u32 host1x_uclass_wait_syncpt_base_offset_f(u32 v)
+{
+       return (v & 0xffff) << 0;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_OFFSET_F(v) \
+       host1x_uclass_wait_syncpt_base_offset_f(v)
+static inline u32 host1x_uclass_load_syncpt_base_r(void)
+{
+       return 0xb;
+}
+#define HOST1X_UCLASS_LOAD_SYNCPT_BASE \
+       host1x_uclass_load_syncpt_base_r()
+static inline u32 host1x_uclass_load_syncpt_base_base_indx_f(u32 v)
+{
+       return (v & 0xff) << 24;
+}
+#define HOST1X_UCLASS_LOAD_SYNCPT_BASE_BASE_INDX_F(v) \
+       host1x_uclass_load_syncpt_base_base_indx_f(v)
+static inline u32 host1x_uclass_load_syncpt_base_value_f(u32 v)
+{
+       return (v & 0xffffff) << 0;
+}
+#define HOST1X_UCLASS_LOAD_SYNCPT_BASE_VALUE_F(v) \
+       host1x_uclass_load_syncpt_base_value_f(v)
+static inline u32 host1x_uclass_incr_syncpt_base_base_indx_f(u32 v)
+{
+       return (v & 0xff) << 24;
+}
+#define HOST1X_UCLASS_INCR_SYNCPT_BASE_BASE_INDX_F(v) \
+       host1x_uclass_incr_syncpt_base_base_indx_f(v)
+static inline u32 host1x_uclass_incr_syncpt_base_offset_f(u32 v)
+{
+       return (v & 0xffffff) << 0;
+}
+#define HOST1X_UCLASS_INCR_SYNCPT_BASE_OFFSET_F(v) \
+       host1x_uclass_incr_syncpt_base_offset_f(v)
+static inline u32 host1x_uclass_indoff_r(void)
+{
+       return 0x2d;
+}
+#define HOST1X_UCLASS_INDOFF \
+       host1x_uclass_indoff_r()
+static inline u32 host1x_uclass_indoff_indbe_f(u32 v)
+{
+       return (v & 0xf) << 28;
+}
+#define HOST1X_UCLASS_INDOFF_INDBE_F(v) \
+       host1x_uclass_indoff_indbe_f(v)
+static inline u32 host1x_uclass_indoff_autoinc_f(u32 v)
+{
+       return (v & 0x1) << 27;
+}
+#define HOST1X_UCLASS_INDOFF_AUTOINC_F(v) \
+       host1x_uclass_indoff_autoinc_f(v)
+static inline u32 host1x_uclass_indoff_indmodid_f(u32 v)
+{
+       return (v & 0xff) << 18;
+}
+#define HOST1X_UCLASS_INDOFF_INDMODID_F(v) \
+       host1x_uclass_indoff_indmodid_f(v)
+static inline u32 host1x_uclass_indoff_indroffset_f(u32 v)
+{
+       return (v & 0xffff) << 2;
+}
+#define HOST1X_UCLASS_INDOFF_INDROFFSET_F(v) \
+       host1x_uclass_indoff_indroffset_f(v)
+static inline u32 host1x_uclass_indoff_rwn_read_v(void)
+{
+       return 1;
+}
+#define HOST1X_UCLASS_INDOFF_INDROFFSET_F(v) \
+       host1x_uclass_indoff_indroffset_f(v)
+
+#endif
diff --git a/drivers/gpu/host1x/hw/hw_host1x06_vm.h b/drivers/gpu/host1x/hw/hw_host1x06_vm.h
new file mode 100644 (file)
index 0000000..e54b339
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#define HOST1X_CHANNEL_DMASTART                                0x0000
+#define HOST1X_CHANNEL_DMASTART_HI                     0x0004
+#define HOST1X_CHANNEL_DMAPUT                          0x0008
+#define HOST1X_CHANNEL_DMAPUT_HI                       0x000c
+#define HOST1X_CHANNEL_DMAGET                          0x0010
+#define HOST1X_CHANNEL_DMAGET_HI                       0x0014
+#define HOST1X_CHANNEL_DMAEND                          0x0018
+#define HOST1X_CHANNEL_DMAEND_HI                       0x001c
+#define HOST1X_CHANNEL_DMACTRL                         0x0020
+#define HOST1X_CHANNEL_DMACTRL_DMASTOP                 BIT(0)
+#define HOST1X_CHANNEL_DMACTRL_DMAGETRST               BIT(1)
+#define HOST1X_CHANNEL_DMACTRL_DMAINITGET              BIT(2)
+#define HOST1X_CHANNEL_CMDFIFO_STAT                    0x0024
+#define HOST1X_CHANNEL_CMDFIFO_STAT_EMPTY              BIT(13)
+#define HOST1X_CHANNEL_CMDFIFO_RDATA                   0x0028
+#define HOST1X_CHANNEL_CMDP_OFFSET                     0x0030
+#define HOST1X_CHANNEL_CMDP_CLASS                      0x0034
+#define HOST1X_CHANNEL_CHANNELSTAT                     0x0038
+#define HOST1X_CHANNEL_CMDPROC_STOP                    0x0048
+#define HOST1X_CHANNEL_TEARDOWN                                0x004c
+
+#define HOST1X_SYNC_SYNCPT_CPU_INCR(x)                 (0x6400 + 4*(x))
+#define HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(x)   (0x6464 + 4*(x))
+#define HOST1X_SYNC_SYNCPT_THRESH_INT_ENABLE_CPU0(x)   (0x652c + 4*(x))
+#define HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(x)       (0x6590 + 4*(x))
+#define HOST1X_SYNC_SYNCPT_BASE(x)                     (0x8000 + 4*(x))
+#define HOST1X_SYNC_SYNCPT(x)                          (0x8080 + 4*(x))
+#define HOST1X_SYNC_SYNCPT_INT_THRESH(x)               (0x8a00 + 4*(x))
+#define HOST1X_SYNC_SYNCPT_CH_APP(x)                   (0x9384 + 4*(x))
+#define HOST1X_SYNC_SYNCPT_CH_APP_CH(v)                        (((v) & 0x3f) << 8)
index 37ebb51..3292392 100644 (file)
@@ -72,6 +72,23 @@ static void _host1x_intr_disable_all_syncpt_intrs(struct host1x *host)
        }
 }
 
+static void intr_hw_init(struct host1x *host, u32 cpm)
+{
+#if HOST1X_HW < 6
+       /* disable the ip_busy_timeout. this prevents write drops */
+       host1x_sync_writel(host, 0, HOST1X_SYNC_IP_BUSY_TIMEOUT);
+
+       /*
+        * increase the auto-ack timout to the maximum value. 2d will hang
+        * otherwise on Tegra2.
+        */
+       host1x_sync_writel(host, 0xff, HOST1X_SYNC_CTXSW_TIMEOUT_CFG);
+
+       /* update host clocks per usec */
+       host1x_sync_writel(host, cpm, HOST1X_SYNC_USEC_CLK);
+#endif
+}
+
 static int
 _host1x_intr_init_host_sync(struct host1x *host, u32 cpm,
                            void (*syncpt_thresh_work)(struct work_struct *))
@@ -92,17 +109,7 @@ _host1x_intr_init_host_sync(struct host1x *host, u32 cpm,
                return err;
        }
 
-       /* disable the ip_busy_timeout. this prevents write drops */
-       host1x_sync_writel(host, 0, HOST1X_SYNC_IP_BUSY_TIMEOUT);
-
-       /*
-        * increase the auto-ack timout to the maximum value. 2d will hang
-        * otherwise on Tegra2.
-        */
-       host1x_sync_writel(host, 0xff, HOST1X_SYNC_CTXSW_TIMEOUT_CFG);
-
-       /* update host clocks per usec */
-       host1x_sync_writel(host, cpm, HOST1X_SYNC_USEC_CLK);
+       intr_hw_init(host, cpm);
 
        return 0;
 }