video: tegra: host: Add Tegra12 support
Mark Stadler [Thu, 2 Aug 2012 17:53:51 +0000 (10:53 -0700)]
Change-Id: I85eaa0199bb590fe4c55bc73b54592bfdcec0697
Signed-off-by: Mark Stadler <mastadler@nvidia.com>

12 files changed:
drivers/video/tegra/host/t124/3dctx_t124.c [new file with mode: 0644]
drivers/video/tegra/host/t124/Makefile [new file with mode: 0644]
drivers/video/tegra/host/t124/as_t124.c [new file with mode: 0644]
drivers/video/tegra/host/t124/cdma_t124.c [new file with mode: 0644]
drivers/video/tegra/host/t124/cpuaccess_t124.c [new file with mode: 0644]
drivers/video/tegra/host/t124/debug_t124.c [new file with mode: 0644]
drivers/video/tegra/host/t124/hardware_t124.h [new file with mode: 0644]
drivers/video/tegra/host/t124/intr_t124.c [new file with mode: 0644]
drivers/video/tegra/host/t124/syncpt_t124.c [new file with mode: 0644]
drivers/video/tegra/host/t124/syncpt_t124.h [new file with mode: 0644]
drivers/video/tegra/host/t124/t124.c [new file with mode: 0644]
drivers/video/tegra/host/t124/t124.h [new file with mode: 0644]

diff --git a/drivers/video/tegra/host/t124/3dctx_t124.c b/drivers/video/tegra/host/t124/3dctx_t124.c
new file mode 100644 (file)
index 0000000..8c16ae1
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * drivers/video/tegra/host/t124/3dctx_t124.c
+ *
+ * Tegra Graphics Host 3d hardware context
+ *
+ * Copyright (c) 2011-2012, 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 "../nvhost_hwctx.h"
+#include "../dev.h"
+
+#include "t124.h"
+#include "hardware_t124.h"
+
+#include "../gk20a/gk20a.h"
+
+static void t124_ctx3d_free(struct kref *ref)
+{
+       struct nvhost_hwctx *ctx = container_of(ref, struct nvhost_hwctx, ref);
+
+       gk20a_free_channel(ctx);
+       kfree(ctx);
+}
+
+struct nvhost_hwctx *t124_3dctx_alloc(struct nvhost_hwctx_handler *h,
+                       struct nvhost_channel *ch)
+{
+       struct nvhost_hwctx *ctx;
+
+       nvhost_dbg_fn("");
+
+       /* it seems odd to be allocating a channel here but the
+        * t20/t30 notion of a channel is mapped on top of gk20a's
+        * channel.  this works because there is only one module
+        * under gk20a's host (gr).
+        */
+       /* call gk20a_channel_alloc */
+
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return NULL;
+
+       kref_init(&ctx->ref);
+       return gk20a_open_channel(ch, ctx);
+}
+
+void t124_3dctx_get(struct nvhost_hwctx *hwctx)
+{
+       nvhost_dbg_fn("");
+       kref_get(&hwctx->ref);
+}
+
+void t124_3dctx_put(struct nvhost_hwctx *hwctx)
+{
+       nvhost_dbg_fn("");
+       kref_put(&hwctx->ref, t124_ctx3d_free);
+}
+
+void t124_3dctx_save_push(struct nvhost_hwctx *ctx, struct nvhost_cdma *cdma)
+{
+       nvhost_dbg_fn("");
+}
+
+void t124_3dctx_save_service(struct nvhost_hwctx *ctx)
+{
+       nvhost_dbg_fn("");
+}
+
+int __init t124_nvhost_3dctx_handler_init(struct nvhost_hwctx_handler *h)
+{
+       nvhost_dbg_fn("");
+
+       h->alloc = t124_3dctx_alloc;
+       h->get   = t124_3dctx_get;
+       h->put   = t124_3dctx_put;
+       h->save_push = t124_3dctx_save_push;
+       h->save_service = t124_3dctx_save_service;
+
+       return 0;
+}
+
+int __init t124_nvhost_mpectx_handler_init(struct nvhost_hwctx_handler *h)
+{
+       nvhost_dbg_fn("");
+       return 0;
+}
diff --git a/drivers/video/tegra/host/t124/Makefile b/drivers/video/tegra/host/t124/Makefile
new file mode 100644 (file)
index 0000000..e4de0e2
--- /dev/null
@@ -0,0 +1,13 @@
+GCOV_PROFILE := y
+EXTRA_CFLAGS += -Idrivers/video/tegra/host
+
+nvhost-t124-objs  = \
+       t124.o \
+       as_t124.o \
+       syncpt_t124.o \
+       intr_t124.o \
+       cdma_t124.o \
+       3dctx_t124.o \
+       debug_t124.o
+
+obj-$(CONFIG_TEGRA_GRHOST) += nvhost-t124.o
diff --git a/drivers/video/tegra/host/t124/as_t124.c b/drivers/video/tegra/host/t124/as_t124.c
new file mode 100644 (file)
index 0000000..33f54e9
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * drivers/video/tegra/host/t124/as_t124.c
+ *
+ * Tegra Graphics Host Address Space Support for T124 Architecture Chips
+ *
+ * Copyright (c) 2010-2012, 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 "dev.h"
+#include "nvhost_as.h"
+#include "t124.h"
+#include "gk20a/gk20a.h"
+
+
+
+static int t124_as_init(struct nvhost_master *host, struct nvhost_as *as)
+{
+       if (as->ch->dev == &gk20a_device)
+               as->ops = &gk20a_as_moduleops;
+       return 0;
+}
+
+int nvhost_init_t124_as_support(struct nvhost_chip_support *op)
+{
+       nvhost_dbg_fn("");
+
+       op->as.init = t124_as_init;
+       return 0;
+}
diff --git a/drivers/video/tegra/host/t124/cdma_t124.c b/drivers/video/tegra/host/t124/cdma_t124.c
new file mode 100644 (file)
index 0000000..201a181
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * drivers/video/tegra/host/t124/cdma_t124.c
+ *
+ * Tegra Graphics Host Command DMA
+ *
+ * Copyright (c) 2011-2012, 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 "nvhost_cdma.h"
+#include "dev.h"
+
+#include "t124.h"
+#include "hardware_t124.h"
+#include "host1x/hw_host1x02_sync.h"
+#include "host1x/hw_host1x02_channel.h"
+
+#include "gk20a/gk20a.h"
+#include "gk20a/cdma_gk20a.h"
+
+#include "chip_support.h"
+
+#include "host1x/host1x_cdma.c"
+
+static void t124_push_buffer_reset(struct push_buffer *pb)
+{
+       struct nvhost_cdma *cdma = pb_to_cdma(pb);
+       struct nvhost_channel *ch = cdma_to_channel(cdma);
+
+       nvhost_dbg_fn("");
+       if (ch->dev == &gk20a_device )
+               gk20a_push_buffer_reset(pb);
+       else
+               host1x_pushbuffer_ops.reset(pb);
+}
+
+/**
+ * Init push buffer resources
+ */
+static int t124_push_buffer_init(struct push_buffer *pb)
+{
+       struct nvhost_cdma *cdma = pb_to_cdma(pb);
+       struct nvhost_channel *ch = cdma_to_channel(cdma);
+
+       nvhost_dbg_fn("");
+       if (ch->dev == &gk20a_device)
+               return gk20a_push_buffer_init(pb);
+       else
+               return host1x_pushbuffer_ops.init(pb);
+}
+
+/**
+ * Clean up push buffer resources
+ */
+static void t124_push_buffer_destroy(struct push_buffer *pb)
+{
+       struct nvhost_cdma *cdma = pb_to_cdma(pb);
+       struct nvhost_channel *ch = cdma_to_channel(cdma);
+
+       nvhost_dbg_fn("");
+       if (ch->dev == &gk20a_device)
+               gk20a_push_buffer_destroy(pb);
+       else
+               host1x_pushbuffer_ops.destroy(pb);
+}
+
+/**
+ * Push two words to the push buffer
+ * Caller must ensure push buffer is not full
+ */
+static void t124_push_buffer_push_to(struct push_buffer *pb,
+                           struct mem_mgr *client,
+                           struct mem_handle *handle, u32 op1, u32 op2)
+{
+       struct nvhost_cdma *cdma = pb_to_cdma(pb);
+       struct nvhost_channel *ch = cdma_to_channel(cdma);
+
+       nvhost_dbg_fn("");
+       if (ch->dev == &gk20a_device)
+               gk20a_push_buffer_push_to(pb, client, handle, op1, op2);
+       else
+               host1x_pushbuffer_ops.push_to(pb, client, handle, op1, op2);
+}
+
+/**
+ * Pop a number of two word slots from the push buffer
+ * Caller must ensure push buffer is not empty
+ */
+static void t124_push_buffer_pop_from(struct push_buffer *pb, unsigned int slots)
+{
+       struct nvhost_cdma *cdma = pb_to_cdma(pb);
+       struct nvhost_channel *ch = cdma_to_channel(cdma);
+
+       nvhost_dbg_fn("");
+       if (ch->dev == &gk20a_device)
+               gk20a_push_buffer_pop_from(pb, slots);
+       else
+               host1x_pushbuffer_ops.pop_from(pb, slots);
+}
+
+/**
+ * Return the number of two word slots free in the push buffer
+ */
+static u32 t124_push_buffer_space(struct push_buffer *pb)
+{
+       struct nvhost_cdma *cdma = pb_to_cdma(pb);
+       struct nvhost_channel *ch = cdma_to_channel(cdma);
+
+       nvhost_dbg_fn("");
+       if (ch->dev == &gk20a_device)
+               return gk20a_push_buffer_space(pb);
+       else
+               return host1x_pushbuffer_ops.space(pb);
+}
+
+static u32 t124_push_buffer_putptr(struct push_buffer *pb)
+{
+       struct nvhost_cdma *cdma = pb_to_cdma(pb);
+       struct nvhost_channel *ch = cdma_to_channel(cdma);
+
+       nvhost_dbg_fn("");
+       if (ch->dev == &gk20a_device)
+               return gk20a_push_buffer_putptr(pb);
+       else
+               return host1x_pushbuffer_ops.putptr(pb);
+}
+
+/*
+ * The syncpt incr buffer is filled with methods to increment syncpts, which
+ * is later GATHER-ed into the mainline PB. It's used when a timed out context
+ * is interleaved with other work, so needs to inline the syncpt increments
+ * to maintain the count (but otherwise does no work).
+ */
+
+/**
+ * Init timeout and syncpt incr buffer resources
+ */
+static int t124_cdma_timeout_init(struct nvhost_cdma *cdma,
+                                u32 syncpt_id)
+{
+       struct nvhost_channel *ch = cdma_to_channel(cdma);
+
+       nvhost_dbg_fn("");
+       if (ch->dev == &gk20a_device)
+               return -EINVAL; /*XXX gk20a_cdma_timeout_init(cdma, syncpt_id);*/
+       else
+               return host1x_cdma_ops.timeout_init(cdma, syncpt_id);
+}
+static void t124_cdma_timeout_destroy(struct nvhost_cdma *cdma)
+{
+       struct nvhost_channel *ch = cdma_to_channel(cdma);
+
+       nvhost_dbg_fn("");
+       if (ch->dev == &gk20a_device)
+               return; /*XXX gk20a_cdma_timeout_destroy(cdma);*/
+       else
+               host1x_cdma_ops.timeout_destroy(cdma);
+}
+
+void t124_cdma_timeout_teardown_begin(struct nvhost_cdma *cdma)
+{
+       struct nvhost_channel *ch = cdma_to_channel(cdma);
+
+       nvhost_dbg_fn("");
+       if (ch->dev == &gk20a_device)
+               return; /*XXX gk20a_cdma_teardown_begin(cdma);*/
+       else
+               host1x_cdma_ops.timeout_teardown_begin(cdma);
+}
+
+void t124_cdma_timeout_teardown_end(struct nvhost_cdma *cdma, u32 getptr)
+{
+       struct nvhost_channel *ch = cdma_to_channel(cdma);
+
+       nvhost_dbg_fn("");
+       if (ch->dev == &gk20a_device)
+               return; /*XXX gk20a_cdma_teardown_end(cdma, getptr);*/
+       else
+               host1x_cdma_ops.timeout_teardown_end(cdma, getptr);
+}
+static void t124_cdma_timeout_cpu_incr(struct nvhost_cdma *cdma, u32 getptr,
+       u32 syncpt_incrs, u32 syncval, u32 nr_slots, u32 waitbases)
+{
+       struct nvhost_channel *ch = cdma_to_channel(cdma);
+
+       nvhost_dbg_fn("");
+       if (ch->dev == &gk20a_device)
+               return; /*XXX gk20a_cdma_timeout_cpu_incr(cdma, getptr,
+                         syncpt_incrs, syncval, nr_slots);*/
+       else
+               host1x_cdma_ops.timeout_cpu_incr(cdma, getptr, syncpt_incrs,
+                                         syncval, nr_slots, waitbases);
+}
+
+/**
+ * Start channel DMA
+ */
+static void t124_cdma_start(struct nvhost_cdma *cdma)
+{
+       struct nvhost_channel *ch = cdma_to_channel(cdma);
+
+       nvhost_dbg_fn("");
+       if (ch->dev == &gk20a_device)
+               gk20a_cdma_start(cdma);
+       else
+               host1x_cdma_ops.start(cdma);
+}
+
+/**
+ * Kick channel DMA into action by writing its PUT offset (if it has changed)
+ */
+static void t124_cdma_kick(struct nvhost_cdma *cdma)
+{
+       struct nvhost_channel *ch = cdma_to_channel(cdma);
+
+       nvhost_dbg_fn("");
+       if (ch->dev == &gk20a_device)
+               gk20a_cdma_kick(cdma);
+       else
+               host1x_cdma_ops.kick(cdma);
+}
+
+static void t124_cdma_stop(struct nvhost_cdma *cdma)
+{
+       struct nvhost_channel *ch = cdma_to_channel(cdma);
+
+       nvhost_dbg_fn("");
+       if (ch->dev == &gk20a_device)
+               gk20a_cdma_stop(cdma);
+       else
+               host1x_cdma_ops.stop(cdma);
+}
+
+int nvhost_init_t124_cdma_support(struct nvhost_chip_support *op)
+{
+       /* i'm of half a mind to call t30 init here and crib its
+          pointers and call them only for host1x channels, and
+          call out to gk20a stuff for gr
+       */
+
+       nvhost_dbg_fn("");
+       op->cdma.start = t124_cdma_start;
+       op->cdma.stop = t124_cdma_stop;
+       op->cdma.kick = t124_cdma_kick;
+
+       op->cdma.timeout_init = t124_cdma_timeout_init;
+       op->cdma.timeout_destroy = t124_cdma_timeout_destroy;
+       op->cdma.timeout_teardown_begin = t124_cdma_timeout_teardown_begin;
+       op->cdma.timeout_teardown_end = t124_cdma_timeout_teardown_end;
+       op->cdma.timeout_cpu_incr = t124_cdma_timeout_cpu_incr;
+
+       op->push_buffer.reset = t124_push_buffer_reset;
+       op->push_buffer.init = t124_push_buffer_init;
+       op->push_buffer.destroy = t124_push_buffer_destroy;
+       op->push_buffer.push_to = t124_push_buffer_push_to;
+       op->push_buffer.pop_from = t124_push_buffer_pop_from;
+       op->push_buffer.space = t124_push_buffer_space;
+       op->push_buffer.putptr = t124_push_buffer_putptr;
+
+       return 0;
+}
diff --git a/drivers/video/tegra/host/t124/cpuaccess_t124.c b/drivers/video/tegra/host/t124/cpuaccess_t124.c
new file mode 100644 (file)
index 0000000..0373a08
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * drivers/video/tegra/host/t124/cpuaccess_t124.c
+ *
+ * Tegra Graphics Host Cpu Register Access
+ *
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "../nvhost_cpuaccess.h"
+#include "../dev.h"
+
+#include "t124.h"
+#include "hardware_t124.h"
+
+static int t124_cpuaccess_mutex_try_lock(struct nvhost_cpuaccess *ctx,
+                                       unsigned int idx)
+{
+       struct nvhost_master *dev = cpuaccess_to_dev(ctx);
+       void __iomem *sync_regs = dev->sync_aperture;
+
+       nvhost_dbg_fn("");
+       /* mlock registers returns 0 when the lock is aquired.
+        * writing 0 clears the lock. */
+       return !!readl(sync_regs + (host1x_sync_mlock_0_0_r() + idx * 4));
+}
+
+static void t124_cpuaccess_mutex_unlock(struct nvhost_cpuaccess *ctx,
+                                      unsigned int idx)
+{
+       struct nvhost_master *dev = cpuaccess_to_dev(ctx);
+       void __iomem *sync_regs = dev->sync_aperture;
+
+       nvhost_dbg_fn("");
+       writel(0, sync_regs + (host1x_sync_mlock_0_0_r() + idx * 4));
+}
+
+int nvhost_init_t124_cpuaccess_support(struct nvhost_master *host,
+                                     struct nvhost_chip_support *op)
+{
+       host->nb_modules = NVHOST_MODULE_NUM;
+
+       op->cpuaccess.mutex_try_lock = t124_cpuaccess_mutex_try_lock;
+       op->cpuaccess.mutex_unlock = t124_cpuaccess_mutex_unlock;
+
+       return 0;
+}
diff --git a/drivers/video/tegra/host/t124/debug_t124.c b/drivers/video/tegra/host/t124/debug_t124.c
new file mode 100644 (file)
index 0000000..3c61ebd
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * drivers/video/tegra/host/t124/debug_t124.c
+ *
+ * Copyright (c) 2011-2012, 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 <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include <linux/io.h>
+
+#include "dev.h"
+#include "debug.h"
+#include "nvhost_cdma.h"
+
+#include "t124.h"
+#include "hardware_t124.h"
+#include "gk20a/gk20a.h"
+#include "gk20a/debug_gk20a.h"
+#include "t20/t20.h"
+
+#include "chip_support.h"
+
+#include "host1x/hw_host1x02_sync.h"
+#include "host1x/hw_host1x02_channel.h"
+#include "host1x/host1x_debug.c"
+
+static void t124_debug_show_channel_cdma(struct nvhost_master *m,
+       struct nvhost_channel *ch, struct output *o, int chid)
+{
+       nvhost_dbg_fn("");
+       if (ch->dev == &gk20a_device)
+               gk20a_debug_show_channel_cdma(m, ch, o, chid);
+       else
+               t20_debug_show_channel_cdma(m, ch, o, chid);
+}
+
+void t124_debug_show_channel_fifo(struct nvhost_master *m,
+       struct nvhost_channel *ch, struct output *o, int chid)
+{
+       nvhost_dbg_fn("");
+       if (ch->dev == &gk20a_device)
+               gk20a_debug_show_channel_fifo(m, ch, o, chid);
+       else
+               t20_debug_show_channel_fifo(m, ch, o, chid);
+}
+
+static void t124_debug_show_mlocks(struct nvhost_master *m, struct output *o)
+{
+       u32 __iomem *mlo_regs = m->sync_aperture +
+               host1x_sync_mlock_owner_0_0_r();
+       int i;
+
+       nvhost_debug_output(o, "---- mlocks ----\n");
+       for (i = 0; i < NV_HOST1X_NB_MLOCKS; i++) {
+               u32 owner = readl(mlo_regs + i * 4);
+               if (owner & 0x1)
+                       nvhost_debug_output(o, "%d: locked by channel %d\n",
+                                           i, (owner >> 8) & 0xf);
+               else if (owner & 0x2)
+                       nvhost_debug_output(o, "%d: locked by cpu\n", i);
+               else
+                       nvhost_debug_output(o, "%d: unlocked\n", i);
+       }
+       nvhost_debug_output(o, "\n");
+}
+
+int nvhost_init_t124_debug_support(struct nvhost_chip_support *op)
+{
+       op->debug.show_channel_cdma = t124_debug_show_channel_cdma;
+       op->debug.show_channel_fifo = t124_debug_show_channel_fifo;
+       op->debug.show_mlocks = t124_debug_show_mlocks;
+
+       return 0;
+}
diff --git a/drivers/video/tegra/host/t124/hardware_t124.h b/drivers/video/tegra/host/t124/hardware_t124.h
new file mode 100644 (file)
index 0000000..0b297d2
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * drivers/video/tegra/host/t124/hardware_t124.h
+ *
+ * Tegra T124 HOST1X Register Definitions
+ *
+ * Copyright (c) 2011, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __NVHOST_HARDWARE_T124_H
+#define __NVHOST_HARDWARE_T124_H
+
+#include "host1x/hw_host1x04_sync.h"
+#include "host1x/hw_host1x04_uclass.h"
+#include "host1x/hw_host1x04_channel.h"
+
+#define NV_HOST1X_CHANNELS     9
+#define NV_HOST1X_SYNC_MLOCK_NUM 16
+
+/* sync registers */
+#define NV_HOST1X_SYNCPT_NB_PTS 192
+#define NV_HOST1X_SYNCPT_NB_BASES 64
+#define NV_HOST1X_NB_MLOCKS 16
+#define HOST1X_CHANNEL_SYNC_REG_BASE 0x3000
+#define NV_HOST1X_CHANNEL_MAP_SIZE_BYTES 16384
+
+/* Faked for now until the tool can handle mobile register def files*/
+
+static inline u32 host1x_sync_intmask_0_r(void) { return 0x04; }
+static inline u32 host1x_sync_intc0mask_0_r(void) { return 0x08; }
+static inline u32 host1x_sync_hintstatus_0_r(void) { return 0x20; }
+static inline u32 host1x_sync_hintmask_0_r(void) { return 0x24; }
+static inline u32 host1x_sync_hintstatus_ext_0_r(void) { return 0x28; }
+static inline u32 host1x_sync_hintmask_ext_0_r(void) { return 0x2c; }
+static inline u32 host1x_sync_syncpt_thresh_cpu0_int_status_0_r(void) { return 0x40; }
+static inline u32 host1x_sync_syncpt_thresh_cpu0_int_status_1_0_r(void) { return 0x44; } /* thru ... */
+static inline u32 host1x_sync_syncpt_thresh_cpu0_int_status_5_0_r(void) { return 0x54; }
+static inline u32 host1x_sync_syncpt_thresh_cpu1_int_status_0_r(void) { return 0x58; }
+static inline u32 host1x_sync_syncpt_thresh_cpu1_int_status_1_0_r(void) { return 0x5c; } /* thru ... */
+static inline u32 host1x_sync_syncpt_thresh_cpu1_int_status_5_0_r(void) { return 0x6c; }
+static inline u32 host1x_sync_syncpt_thresh_int_disable_0_r(void) { return 0xa0; }
+static inline u32 host1x_sync_syncpt_thresh_int_disable_1_0_r(void) { return 0xa4; } /* thru ... */
+static inline u32 host1x_sync_syncpt_thresh_int_disable_5_0_r(void) { return 0xb4; }
+static inline u32 host1x_sync_syncpt_thresh_int_enable_cpu0_0_r(void) { return 0xb8; }
+static inline u32 host1x_sync_syncpt_thresh_int_enable_cpu0_1_0_r(void) { return 0xbc; } /* thru ... */
+static inline u32 host1x_sync_syncpt_thresh_int_enable_cpu0_5_0_r(void) { return 0xcc; }
+static inline u32 host1x_sync_usec_clk_0_r(void) { return 0x244; }
+static inline u32 host1x_sync_ctxsw_timeout_cfg_0_r(void) { return 0x248; }
+static inline u32 host1x_sync_ip_busy_timeout_0_r(void) { return 0x25c; }
+static inline u32 host1x_sync_ip_read_timeout_addr_0_r(void) { return 0x260; }
+static inline u32 host1x_sync_ip_write_timeout_addr_0_r(void) { return 0x264; }
+static inline u32 host1x_sync_mlock_0_0_r(void) { return 0x380; }
+static inline u32 host1x_sync_mlock_1_0_r(void) { return 0x384; } /* thru ... */
+static inline u32 host1x_sync_mlock_15_0_r(void) { return 0x3bc; }
+static inline u32 host1x_sync_mlock_owner_0_0_r(void) { return 0x400; }
+static inline u32 host1x_sync_mlock_owner_1_0_r(void) { return 0x404; } /* thru ... */
+static inline u32 host1x_sync_mlock_owner_15_0_r(void) { return 0x43c; }
+static inline u32 host1x_sync_syncpt_0_0_r(void) { return 0x500; }
+static inline u32 host1x_sync_syncpt_1_0_r(void) { return 0x504; } /* thru ... */
+static inline u32 host1x_sync_syncpt_191_0_r(void) { return 0x7fc; }
+static inline u32 host1x_sync_syncpt_int_thresh_0_0_r(void) { return 0x800; }
+static inline u32 host1x_sync_syncpt_int_thresh_1_0_r(void) { return 0x804; } /* thru ... */
+static inline u32 host1x_sync_syncpt_int_thresh_191_0_r(void) { return 0xafc; }
+static inline u32 host1x_sync_syncpt_base_0_0_r(void) { return 0xb00; }
+static inline u32 host1x_sync_syncpt_base_1_0_r(void) { return 0xb04; } /* thru... */
+static inline u32 host1x_sync_syncpt_base_63_0_r(void) { return 0xbfc; }
+static inline u32 host1x_sync_syncpt_cpu_incr_0_0_r(void) { return 0xc00; }
+static inline u32 host1x_sync_syncpt_cpu_incr_1_0_r(void) { return 0xc04; } /* thru ... */
+static inline u32 host1x_sync_syncpt_cpu_incr_5_0_r(void) { return 0xc14; }
+
+/* Switch to bitfield defs when the tools work */
+static inline bool nvhost_sync_hintstatus_ext_ip_read_int(u32 reg)
+{
+       return (reg & BIT(30)) != 0;
+}
+
+static inline bool nvhost_sync_hintstatus_ext_ip_write_int(u32 reg)
+{
+       return (reg & BIT(31)) != 0;
+}
+
+static inline bool nvhost_sync_mlock_owner_ch_owns(u32 reg)
+{
+       return (reg & BIT(0)) != 0;
+}
+
+static inline bool nvhost_sync_mlock_owner_cpu_owns(u32 reg)
+{
+       return (reg & BIT(1)) != 0;
+}
+
+static inline unsigned int nvhost_sync_mlock_owner_owner_chid(u32 reg)
+{
+       return (reg >> 8) & 0xf;
+}
+
+/* Generic support */
+static inline u32 nvhost_class_host_wait_syncpt(
+       unsigned indx, unsigned threshold)
+{
+       return (indx << 24) | (threshold & 0xffffff);
+}
+
+static inline u32 nvhost_class_host_load_syncpt_base(
+       unsigned indx, unsigned threshold)
+{
+       return host1x_uclass_wait_syncpt_indx_f(indx)
+               | host1x_uclass_wait_syncpt_thresh_f(threshold);
+}
+
+static inline u32 nvhost_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 nvhost_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 nvhost_class_host_incr_syncpt(
+       unsigned cond, unsigned indx)
+{
+       return host1x_uclass_incr_syncpt_cond_f(cond)
+               | host1x_uclass_incr_syncpt_indx_f(indx);
+}
+
+enum {
+       NV_HOST_MODULE_HOST1X = 0,
+       NV_HOST_MODULE_MPE = 1,
+       NV_HOST_MODULE_GR3D = 6
+};
+
+static inline u32 nvhost_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 nvhost_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 nvhost_opcode_setclass(
+       unsigned class_id, unsigned offset, unsigned mask)
+{
+       return (0 << 28) | (offset << 16) | (class_id << 6) | mask;
+}
+
+static inline u32 nvhost_opcode_incr(unsigned offset, unsigned count)
+{
+       return (1 << 28) | (offset << 16) | count;
+}
+
+static inline u32 nvhost_opcode_nonincr(unsigned offset, unsigned count)
+{
+       return (2 << 28) | (offset << 16) | count;
+}
+
+static inline u32 nvhost_opcode_mask(unsigned offset, unsigned mask)
+{
+       return (3 << 28) | (offset << 16) | mask;
+}
+
+static inline u32 nvhost_opcode_imm(unsigned offset, unsigned value)
+{
+       return (4 << 28) | (offset << 16) | value;
+}
+
+static inline u32 nvhost_opcode_imm_incr_syncpt(unsigned cond, unsigned indx)
+{
+       return nvhost_opcode_imm(host1x_uclass_incr_syncpt_r(),
+               nvhost_class_host_incr_syncpt(cond, indx));
+}
+
+static inline u32 nvhost_opcode_restart(unsigned address)
+{
+       return (5 << 28) | (address >> 4);
+}
+
+static inline u32 nvhost_opcode_gather(unsigned count)
+{
+       return (6 << 28) | count;
+}
+
+static inline u32 nvhost_opcode_gather_nonincr(unsigned offset,        unsigned count)
+{
+       return (6 << 28) | (offset << 16) | BIT(15) | count;
+}
+
+static inline u32 nvhost_opcode_gather_incr(unsigned offset, unsigned count)
+{
+       return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count;
+}
+
+#define NVHOST_OPCODE_NOOP nvhost_opcode_nonincr(0, 0)
+
+static inline u32 nvhost_mask2(unsigned x, unsigned y)
+{
+       return 1 | (1 << (y - x));
+}
+
+#endif /* __NVHOST_HARDWARE_T124_H */
diff --git a/drivers/video/tegra/host/t124/intr_t124.c b/drivers/video/tegra/host/t124/intr_t124.c
new file mode 100644 (file)
index 0000000..a37a4b6
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ * drivers/video/tegra/host/t124/intr_t124.c
+ *
+ * Tegra Graphics Host Interrupt Management
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <asm/mach/irq.h>
+
+#include "../nvhost_intr.h"
+#include "../dev.h"
+
+#include "t124.h"
+#include "hardware_t124.h"
+
+#include "chip_support.h"
+
+static void syncpt_thresh_mask(struct irq_data *data)
+{
+       (void)data;
+}
+
+static void syncpt_thresh_unmask(struct irq_data *data)
+{
+       (void)data;
+}
+
+static void syncpt_thresh_cascade(unsigned int irq, struct irq_desc *desc)
+{
+       void __iomem *sync_regs = irq_desc_get_handler_data(desc);
+       unsigned long reg;
+       int i, id;
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+
+       chained_irq_enter(chip, desc);
+
+       for (i = 0; i < INT_SYNCPT_THRESH_NR / 32; i++) {
+               reg = readl(sync_regs +
+                       host1x_sync_syncpt_thresh_cpu0_int_status_0_r() + i * 4);
+
+               for_each_set_bit(id, &reg, 32)
+                       generic_handle_irq(id + INT_SYNCPT_THRESH_BASE + i *32);
+       }
+
+       chained_irq_exit(chip, desc);
+}
+
+static struct irq_chip syncpt_thresh_irq = {
+       .name           = "syncpt",
+       .irq_mask       = syncpt_thresh_mask,
+       .irq_unmask     = syncpt_thresh_unmask
+};
+
+static void t124_intr_init_host_sync(struct nvhost_intr *intr)
+{
+       struct nvhost_master *dev = intr_to_dev(intr);
+       void __iomem *sync_regs = dev->sync_aperture;
+       int i, irq;
+
+       writel(0xffffffffUL,
+               sync_regs + host1x_sync_syncpt_thresh_int_disable_0_r());
+       writel(0xffffffffUL,
+               sync_regs + host1x_sync_syncpt_thresh_cpu0_int_status_0_r());
+
+       for (i = 0; i < INT_SYNCPT_THRESH_NR; i++) {
+               irq = INT_SYNCPT_THRESH_BASE + i;
+               irq_set_chip_and_handler(irq, &syncpt_thresh_irq,
+                       handle_simple_irq);
+               irq_set_chip_data(irq, sync_regs);
+               set_irq_flags(irq, IRQF_VALID);
+       }
+       irq_set_chained_handler(INT_HOST1X_MPCORE_SYNCPT,
+               syncpt_thresh_cascade);
+       irq_set_handler_data(INT_HOST1X_MPCORE_SYNCPT, sync_regs);
+
+       nvhost_dbg_fn("");
+       /* disable the ip_busy_timeout. this prevents write drops, etc.
+        * there's no real way to recover from a hung client anyway.
+        */
+       writel(0, sync_regs + host1x_sync_ip_busy_timeout_0_r());
+
+       /* increase the auto-ack timout to the maximum value.
+        *  T124?
+        */
+       writel(0xff, sync_regs + host1x_sync_ctxsw_timeout_cfg_0_r());
+}
+
+static void t124_intr_set_host_clocks_per_usec(struct nvhost_intr *intr, u32 cpm)
+{
+       struct nvhost_master *dev = intr_to_dev(intr);
+       void __iomem *sync_regs = dev->sync_aperture;
+
+       nvhost_dbg_fn("");
+       /* write microsecond clock register */
+       writel(cpm, sync_regs + host1x_sync_usec_clk_0_r());
+}
+
+static void t124_intr_set_syncpt_threshold(struct nvhost_intr *intr,
+                                         u32 id, u32 thresh)
+{
+       struct nvhost_master *dev = intr_to_dev(intr);
+       void __iomem *sync_regs = dev->sync_aperture;
+
+       nvhost_dbg_fn("");
+       thresh &= 0xffff;
+       writel(thresh, sync_regs + (host1x_sync_syncpt_int_thresh_0_0_r() +
+                                   id * 4));
+}
+
+static void t124_intr_enable_syncpt_intr(struct nvhost_intr *intr, u32 id)
+{
+       struct nvhost_master *dev = intr_to_dev(intr);
+       void __iomem *sync_regs = dev->sync_aperture;
+       u32 reg_offset = (id / 32) * 4;
+
+       nvhost_dbg_fn("");
+       BUG_ON(reg_offset > (nvhost_syncpt_nb_pts(&dev->syncpt) / 32) * 4);
+       writel(BIT(id & (32 - 1)), sync_regs +
+               host1x_sync_syncpt_thresh_int_enable_cpu0_0_r() + reg_offset);
+}
+
+static void t124_intr_disable_all_syncpt_intrs(struct nvhost_intr *intr)
+{
+       struct nvhost_master *dev = intr_to_dev(intr);
+       void __iomem *sync_regs = dev->sync_aperture;
+       u32 reg_offset;
+
+       nvhost_dbg_fn("");
+
+       for (reg_offset = 0;
+            reg_offset <= (nvhost_syncpt_nb_pts(&dev->syncpt) / 32) * 4;
+            reg_offset += 4) {
+
+               /* disable interrupts for both cpu's */
+               writel(0, sync_regs +
+                      host1x_sync_syncpt_thresh_int_disable_0_r() +
+                      reg_offset);
+
+               /* clear status for both cpu's */
+               writel(0xfffffffful, sync_regs +
+                       host1x_sync_syncpt_thresh_cpu0_int_status_0_r() +
+                      reg_offset);
+
+               writel(0xfffffffful, sync_regs +
+                       host1x_sync_syncpt_thresh_cpu1_int_status_0_r() +
+                      reg_offset);
+       }
+}
+
+/**
+ * Sync point threshold interrupt service function
+ * Handles sync point threshold triggers, in interrupt context
+ */
+irqreturn_t t124_intr_syncpt_thresh_isr(int irq, void *dev_id)
+{
+       struct nvhost_intr_syncpt *syncpt = dev_id;
+       unsigned int id = syncpt->id;
+       struct nvhost_intr *intr = intr_syncpt_to_intr(syncpt);
+       void __iomem *sync_regs = intr_to_dev(intr)->sync_aperture;
+
+       u32 reg_offset = (id / 32) * 4;
+       id &= 32 - 1;
+
+       nvhost_dbg_fn("");
+       writel(BIT(id),
+              sync_regs +
+               host1x_sync_syncpt_thresh_int_disable_0_r() + reg_offset);
+       writel(BIT(id),
+              sync_regs +
+               host1x_sync_syncpt_thresh_cpu0_int_status_0_r() + reg_offset);
+
+       return IRQ_WAKE_THREAD;
+}
+
+/**
+ * Host general interrupt service function
+ * Handles read / write failures
+ */
+static irqreturn_t t124_intr_host1x_isr(int irq, void *dev_id)
+{
+       struct nvhost_intr *intr = dev_id;
+       void __iomem *sync_regs = intr_to_dev(intr)->sync_aperture;
+       u32 stat;
+       u32 ext_stat;
+       u32 addr;
+       nvhost_dbg_fn("");
+
+       stat = readl(sync_regs + host1x_sync_hintstatus_0_r());
+       ext_stat = readl(sync_regs + host1x_sync_hintstatus_ext_0_r());
+
+       if (nvhost_sync_hintstatus_ext_ip_read_int(ext_stat)) {
+               addr = readl(sync_regs +
+                            host1x_sync_ip_read_timeout_addr_0_r());
+               pr_err("Host read timeout at address %x\n", addr);
+       }
+
+       if (nvhost_sync_hintstatus_ext_ip_write_int(ext_stat)) {
+               addr = readl(sync_regs +
+                            host1x_sync_ip_write_timeout_addr_0_r());
+               pr_err("Host write timeout at address %x\n", addr);
+       }
+
+       writel(ext_stat, sync_regs + host1x_sync_hintstatus_ext_0_r());
+       writel(stat, sync_regs + host1x_sync_hintstatus_0_r());
+
+       return IRQ_HANDLED;
+}
+
+static int t124_intr_request_host_general_irq(struct nvhost_intr *intr)
+{
+       void __iomem *sync_regs = intr_to_dev(intr)->sync_aperture;
+       int err;
+       nvhost_dbg_fn("");
+
+       if (intr->host_general_irq_requested)
+               return 0;
+
+       /* master disable for general (not syncpt) host interrupts */
+       writel(0, sync_regs + host1x_sync_intmask_0_r());
+
+       /* clear status & extstatus */
+       writel(0xfffffffful, sync_regs + host1x_sync_hintstatus_ext_0_r());
+       writel(0xfffffffful, sync_regs + host1x_sync_hintstatus_ext_0_r());
+
+       err = request_irq(intr->host_general_irq, t124_intr_host1x_isr, 0,
+                         "host_status", intr);
+       if (err)
+               return err;
+       /* enable extra interrupt sources IP_READ_INT and IP_WRITE_INT */
+       writel(BIT(30) | BIT(31), sync_regs + host1x_sync_hintmask_ext_0_r());
+
+       /* enable extra interrupt sources */
+       writel(BIT(31), sync_regs + host1x_sync_hintmask_0_r());
+
+       /* enable host module interrupt to CPU0 */
+       writel(BIT(0), sync_regs + host1x_sync_intc0mask_0_r());
+
+       /* master enable for general (not syncpt) host interrupts */
+       writel(BIT(0), sync_regs + host1x_sync_intmask_0_r());
+
+       intr->host_general_irq_requested = true;
+
+       return err;
+}
+
+static void t124_intr_free_host_general_irq(struct nvhost_intr *intr)
+{
+       nvhost_dbg_fn("");
+       if (intr->host_general_irq_requested) {
+               void __iomem *sync_regs = intr_to_dev(intr)->sync_aperture;
+
+               /* master disable for general (not syncpt) host interrupts */
+               writel(0, sync_regs + host1x_sync_intmask_0_r());
+
+               free_irq(intr->host_general_irq, intr);
+               intr->host_general_irq_requested = false;
+       }
+}
+
+static int t124_request_syncpt_irq(struct nvhost_intr_syncpt *syncpt)
+{
+       int err;
+       if (syncpt->irq_requested)
+               return 0;
+
+       err = request_threaded_irq(syncpt->irq,
+                                  t124_intr_syncpt_thresh_isr, nvhost_syncpt_thresh_fn,
+                                  0, syncpt->thresh_irq_name, syncpt);
+       if (err)
+               return err;
+
+       syncpt->irq_requested = 1;
+       return 0;
+}
+
+int nvhost_init_t124_intr_support(struct nvhost_chip_support *op)
+{
+       op->intr.init_host_sync = t124_intr_init_host_sync;
+       op->intr.set_host_clocks_per_usec =
+         t124_intr_set_host_clocks_per_usec;
+       op->intr.set_syncpt_threshold = t124_intr_set_syncpt_threshold;
+       op->intr.enable_syncpt_intr = t124_intr_enable_syncpt_intr;
+       op->intr.disable_all_syncpt_intrs =
+         t124_intr_disable_all_syncpt_intrs;
+       op->intr.request_host_general_irq =
+         t124_intr_request_host_general_irq;
+       op->intr.free_host_general_irq =
+         t124_intr_free_host_general_irq;
+       op->intr.request_syncpt_irq =
+               t124_request_syncpt_irq;
+
+       return 0;
+}
diff --git a/drivers/video/tegra/host/t124/syncpt_t124.c b/drivers/video/tegra/host/t124/syncpt_t124.c
new file mode 100644 (file)
index 0000000..ed8b3b7
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * drivers/video/tegra/host/t124/syncpt_t124.c
+ *
+ * Tegra Graphics Host Syncpoints for T124
+ *
+ * Copyright (c) 2011-2012, 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 <linux/io.h>
+#include "dev.h"
+#include "nvhost_syncpt.h"
+#include "nvhost_acm.h"
+
+#include "t124.h"
+#include "hardware_t124.h"
+#include "syncpt_t124.h"
+
+#include "chip_support.h"
+
+#include "gk20a/gk20a.h"
+
+/**
+ * Write the current syncpoint value back to hw.
+ */
+static void t124_syncpt_reset(struct nvhost_syncpt *sp, u32 id)
+{
+       struct nvhost_master *dev = syncpt_to_dev(sp);
+       int min = nvhost_syncpt_read_min(sp, id);
+       nvhost_dbg_fn("");
+       writel(min, dev->sync_aperture + (host1x_sync_syncpt_0_0_r() + id * 4));
+}
+
+/**
+ * Write the current waitbase value back to hw.
+ */
+static void t124_syncpt_reset_wait_base(struct nvhost_syncpt *sp, u32 id)
+{
+       struct nvhost_master *dev = syncpt_to_dev(sp);
+
+       nvhost_dbg_fn("");
+       writel(sp->base_val[id],
+               dev->sync_aperture + (host1x_sync_syncpt_base_0_0_r() +
+                                     id * 4));
+}
+
+/**
+ * Read waitbase value from hw.
+ */
+static void t124_syncpt_read_wait_base(struct nvhost_syncpt *sp, u32 id)
+{
+       struct nvhost_master *dev = syncpt_to_dev(sp);
+
+       nvhost_dbg_fn("");
+       sp->base_val[id] = readl(dev->sync_aperture +
+                                (host1x_sync_syncpt_base_0_0_r() +
+                                 id * 4));
+}
+
+/**
+ * Updates the last value read from hardware.
+ * (was nvhost_syncpt_update_min)
+ */
+static u32 t124_syncpt_update_min(struct nvhost_syncpt *sp, u32 id)
+{
+       struct nvhost_master *dev = syncpt_to_dev(sp);
+       void __iomem *sync_regs = dev->sync_aperture;
+       u32 old, live;
+
+       nvhost_dbg_fn("");
+       do {
+               old = nvhost_syncpt_read_min(sp, id);
+               live = readl(sync_regs + (host1x_sync_syncpt_0_0_r() + id * 4));
+       } while ((u32)atomic_cmpxchg(&sp->min_val[id], old, live) != old);
+
+       if (!nvhost_syncpt_check_max(sp, id, live))
+               dev_err(&syncpt_to_dev(sp)->dev->dev,
+                               "%s failed: id=%u\n",
+                               __func__,
+                               id);
+
+       return live;
+}
+
+/**
+ * Write a cpu syncpoint increment to the hardware, without touching
+ * the cache. Caller is responsible for host being powered.
+ */
+static void t124_syncpt_cpu_incr(struct nvhost_syncpt *sp, u32 id)
+{
+       struct nvhost_master *dev = syncpt_to_dev(sp);
+       u32 reg_offset = id / 32;
+
+       nvhost_dbg_fn("");
+       BUG_ON(!nvhost_module_powered(dev->dev));
+       if (!nvhost_syncpt_client_managed(sp, id) && nvhost_syncpt_min_eq_max(sp, id)) {
+               dev_err(&syncpt_to_dev(sp)->dev->dev,
+                       "Trying to increment syncpoint id %d beyond max\n",
+                       id);
+               nvhost_debug_dump(syncpt_to_dev(sp));
+               return;
+       }
+
+       writel(BIT(id & (32 - 1)), dev->sync_aperture +
+              host1x_sync_syncpt_cpu_incr_0_0_r() + reg_offset * 4);
+       wmb();
+}
+
+/* remove a wait pointed to by patch_addr */
+static int t124_syncpt_patch_wait(struct nvhost_syncpt *sp,
+        void *patch_addr)
+{
+    u32 override = nvhost_class_host_wait_syncpt(
+            NVSYNCPT_GRAPHICS_HOST, 0);
+    __raw_writel(override, patch_addr);
+    return 0;
+}
+
+static const char *s_syncpt_names[NV_HOST1X_SYNCPT_NB_PTS] = {
+       "", "", "", "", "", "", "", "", "", "", "vic", "",
+       "vi_isp_0", "vi_isp_1", "vi_isp_2", "vi_isp_3", "vi_isp_4", "vi_isp_5",
+       "2d_0", "2d_1",
+       "", "",
+       "3d", "mpe", "disp0", "disp1", "vblank0", "vblank1",
+       "mpe_ebm_eof", "mpe_wr_safe",
+       "2d_tinyblt", "dsi",
+       "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+       "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+       "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+       "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+       "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+       "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+       "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+       "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+       "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+       "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""
+};
+
+static const char *t124_syncpt_name(struct nvhost_syncpt *sp, u32 id)
+{
+       struct host1x_device_info *info = &syncpt_to_dev(sp)->info;
+
+       BUG_ON(id > ARRAY_SIZE(s_syncpt_names));
+       return (id >= info->nb_pts) ? NULL : info->syncpt_names[id];
+}
+
+static void t124_syncpt_debug(struct nvhost_syncpt *sp)
+{
+       nvhost_dbg_fn("");
+}
+
+static int t124_syncpt_mutex_try_lock(struct nvhost_syncpt *sp,
+               unsigned int idx)
+{
+       void __iomem *sync_regs = syncpt_to_dev(sp)->sync_aperture;
+       /* mlock registers returns 0 when the lock is aquired.
+        * writing 0 clears the lock. */
+       return !!readl(sync_regs + (host1x_sync_mlock_0_0_r() + idx * 4));
+}
+
+static void t124_syncpt_mutex_unlock(struct nvhost_syncpt *sp,
+               unsigned int idx)
+{
+       void __iomem *sync_regs = syncpt_to_dev(sp)->sync_aperture;
+
+       writel(0, sync_regs + (host1x_sync_mlock_0_0_r() + idx * 4));
+}
+
+int nvhost_init_t124_syncpt_support(struct nvhost_master *host,
+               struct nvhost_chip_support *op)
+{
+       host->info.nb_pts       = NV_HOST1X_SYNCPT_NB_PTS;
+       host->info.nb_mlocks    = NV_HOST1X_SYNC_MLOCK_NUM;
+       host->info.nb_bases     = NV_HOST1X_SYNCPT_NB_BASES;
+       host->info.syncpt_names = s_syncpt_names;
+       host->info.client_managed = NVSYNCPTS_CLIENT_MANAGED;
+
+       host->sync_aperture = host->aperture + HOST1X_CHANNEL_SYNC_REG_BASE;
+
+       op->syncpt.reset = t124_syncpt_reset;
+       op->syncpt.reset_wait_base = t124_syncpt_reset_wait_base;
+       op->syncpt.read_wait_base = t124_syncpt_read_wait_base;
+       op->syncpt.update_min = t124_syncpt_update_min;
+       op->syncpt.cpu_incr = t124_syncpt_cpu_incr;
+       op->syncpt.patch_wait = t124_syncpt_patch_wait;
+       op->syncpt.debug = t124_syncpt_debug;
+       op->syncpt.name = t124_syncpt_name;
+       op->syncpt.mutex_try_lock = t124_syncpt_mutex_try_lock;
+       op->syncpt.mutex_unlock = t124_syncpt_mutex_unlock;
+
+       gk20a_device.syncpt_base = NVSYNCPT_GK20A_BASE;
+
+       return 0;
+}
diff --git a/drivers/video/tegra/host/t124/syncpt_t124.h b/drivers/video/tegra/host/t124/syncpt_t124.h
new file mode 100644 (file)
index 0000000..4db42e5
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * drivers/video/tegra/host/t124/syncpt_t124.h
+ *
+ * Tegra Graphics Host Syncpoints for T124
+ *
+ * Copyright (c) 2011, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __NVHOST_SYNCPT_T124_H
+#define __NVHOST_SYNCPT_T124_H
+
+#define NVSYNCPT_VI_0_0   1
+#define NVSYNCPT_VI_0_1   2
+#define NVSYNCPT_VI_0_2   3
+#define NVSYNCPT_VI_0_3   4
+#define NVSYNCPT_VI_0_4   5
+#define NVSYNCPT_VI_1_0   6
+#define NVSYNCPT_VI_1_1   7
+#define NVSYNCPT_VI_1_2   8
+#define NVSYNCPT_VI_1_3   9
+#define NVSYNCPT_VI_1_4  10
+#define NVSYNCPT_ISP_0_0 11
+#define NVSYNCPT_ISP_0_1 12
+#define NVSYNCPT_ISP_0_2 13
+#define NVSYNCPT_ISP_0_3 14
+#define NVSYNCPT_ISP_1_0 15
+#define NVSYNCPT_ISP_1_1 16
+#define NVSYNCPT_ISP_1_2 17
+#define NVSYNCPT_ISP_1_3 18
+#define NVSYNCPT_TSEC   19
+#define NVSYNCPT_3D     20
+#define NVSYNCPT_MSENC  21
+#define NVSYNCPT_DISP0  22
+#define NVSYNCPT_DISP1  23
+#define NVSYNCPT_VBLANK0 24
+#define NVSYNCPT_VBLANK1 25
+#define NVSYNCPT_DSI     26
+
+#ifdef CONFIG_ARCH_TEGRA_VIC
+#define NVSYNCPT_VIC     27
+#endif
+
+
+#define NVSYNCPT_GK20A_BASE 32
+/* following is base + number of gk20a channels. TODO: remove magic */
+#define NVSYNCPT_GK20A_LAST (NVSYNCPT_GK20A_BASE + 127)
+
+
+#define NV_VI_0_SYNCPTS ( \
+       BIT(NVSYNCPT_VI_0_0) | \
+       BIT(NVSYNCPT_VI_0_1) | \
+       BIT(NVSYNCPT_VI_0_2) | \
+       BIT(NVSYNCPT_VI_0_3) | \
+       BIT(NVSYNCPT_VI_0_4) | \
+       0 )
+
+#define NV_VI_1_SYNCPTS ( \
+       BIT(NVSYNCPT_VI_1_0) | \
+       BIT(NVSYNCPT_VI_1_1) | \
+       BIT(NVSYNCPT_VI_1_2) | \
+       BIT(NVSYNCPT_VI_1_3) | \
+       BIT(NVSYNCPT_VI_1_4) | \
+       0 )
+
+#define NV_ISP_0_SYNCPTS ( \
+       BIT(NVSYNCPT_ISP_0_0) | \
+       BIT(NVSYNCPT_ISP_0_1) | \
+       BIT(NVSYNCPT_ISP_0_2) | \
+       BIT(NVSYNCPT_ISP_0_3) | \
+       0 )
+
+#define NV_ISP_1_SYNCPTS ( \
+       BIT(NVSYNCPT_ISP_1_0) | \
+       BIT(NVSYNCPT_ISP_1_1) | \
+       BIT(NVSYNCPT_ISP_1_2) | \
+       BIT(NVSYNCPT_ISP_1_3) | \
+       0 )
+
+
+#define NVCAMERA_MANAGED_SYNCPTS ( \
+       NV_VI_0_SYNCPTS  | NV_VI_1_SYNCPTS  | \
+       NV_ISP_0_SYNCPTS | NV_ISP_1_SYNCPTS | \
+       0 )
+
+/* sync points that are wholly managed by the client */
+#define NVSYNCPTS_CLIENT_MANAGED ( \
+       BIT(NVSYNCPT_DISP0) | BIT(NVSYNCPT_DISP1) | \
+       BIT(NVSYNCPT_DSI) |                         \
+       NVCAMERA_MANAGED_SYNCPTS | \
+   0 )
+
+
+#define NVWAITBASE_3D   (3)
+#define NVWAITBASE_MSENC  (4)
+#define NVWAITBASE_TSEC   (5)
+
+int nvhost_t124_init_syncpt(struct nvhost_master *host);
+
+#endif /* __NVHOST_SYNCPT_T124_H */
diff --git a/drivers/video/tegra/host/t124/t124.c b/drivers/video/tegra/host/t124/t124.c
new file mode 100644 (file)
index 0000000..d7b8cd8
--- /dev/null
@@ -0,0 +1,472 @@
+/*
+ * drivers/video/tegra/host/t124/t124.c
+ *
+ * Tegra Graphics Init for T124 Architecture Chips
+ *
+ * Copyright (c) 2011-2012, 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 <linux/slab.h>
+
+#include "dev.h"
+#include "nvhost_job.h"
+#include "class_ids.h"
+
+#include "t124.h"
+#include "host1x/host1x.h"
+
+#include "hardware_t124.h"
+#include "syncpt_t124.h"
+
+#include "gk20a/gk20a.h"
+#include "t20/t20.h"
+#include "vic03/vic03.h"
+#include "msenc/msenc.h"
+#include "tsec/tsec.h"
+
+#include "nvhost_memmgr.h"
+#include "chip_support.h"
+
+static int t124_num_alloc_channels = 0;
+
+static struct resource tegra_host1x04_resources[] = {
+       {
+               .start = TEGRA_HOST1X_BASE,
+               .end = TEGRA_HOST1X_BASE + TEGRA_HOST1X_SIZE - 1,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .start = INT_SYNCPT_THRESH_BASE,
+               .end = INT_SYNCPT_THRESH_BASE + INT_SYNCPT_THRESH_NR - 1,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = INT_HOST1X_MPCORE_GENERAL,
+               .end = INT_HOST1X_MPCORE_GENERAL,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct host1x_device_info host1x04_info = {
+       .nb_channels    = T124_NVHOST_NUMCHANNELS,
+};
+
+static struct nvhost_device tegra_host1x04_device = {
+       .dev            = {.platform_data = &host1x04_info},
+       .name           = "host1x",
+       .id             = -1,
+       .resource       = tegra_host1x04_resources,
+       .num_resources  = ARRAY_SIZE(tegra_host1x04_resources),
+       .clocks         = {{"host1x", UINT_MAX}, {} },
+       NVHOST_MODULE_NO_POWERGATE_IDS,
+};
+
+static struct resource msenc_resources[] = {
+       {
+               .name = "regs",
+               .start = TEGRA_MSENC_BASE,
+               .end = TEGRA_MSENC_BASE + TEGRA_MSENC_SIZE - 1,
+               .flags = IORESOURCE_MEM,
+       },
+};
+
+static struct resource tsec_resources[] = {
+       {
+               .name = "regs",
+               .start = TEGRA_TSEC_BASE,
+               .end = TEGRA_TSEC_BASE + TEGRA_TSEC_SIZE - 1,
+               .flags = IORESOURCE_MEM,
+       },
+};
+
+static struct nvhost_device *channel_devices[] = {
+       &tegra_host1x04_device,
+(struct nvhost_device []){{
+       .name          = "display",
+       .syncpts       = BIT(NVSYNCPT_DISP0) | BIT(NVSYNCPT_DISP1) |
+                        BIT(NVSYNCPT_VBLANK0) | BIT(NVSYNCPT_VBLANK1),
+       .modulemutexes = BIT(NVMODMUTEX_DISPLAYA) | BIT(NVMODMUTEX_DISPLAYB),
+       NVHOST_MODULE_NO_POWERGATE_IDS,
+       NVHOST_DEFAULT_CLOCKGATE_DELAY,
+       .moduleid      = NVHOST_MODULE_NONE,
+},},
+(struct nvhost_device []){{
+       .name    = "isp",
+       .syncpts = NV_ISP_0_SYNCPTS,
+       .modulemutexes = BIT(NVMODMUTEX_ISP_0),
+       .clocks = {{"isp", UINT_MAX}, {} },
+       NVHOST_MODULE_NO_POWERGATE_IDS,
+       NVHOST_DEFAULT_CLOCKGATE_DELAY,
+       .moduleid      = NVHOST_MODULE_ISP,
+},},
+(struct nvhost_device []){{
+       .name    = "isp",
+       .id      = 1, /* .1 on the dev node */
+       .syncpts       = NV_ISP_1_SYNCPTS,
+       .modulemutexes = BIT(NVMODMUTEX_ISP_1),
+       .clocks = {{"isp.1", UINT_MAX}, {} },
+       .exclusive     = true,
+       NVHOST_MODULE_NO_POWERGATE_IDS,
+       NVHOST_DEFAULT_CLOCKGATE_DELAY,
+       .moduleid      = (1 << 16) | NVHOST_MODULE_ISP,
+},},
+(struct nvhost_device [])
+{{     .name          = "vi",
+       .syncpts       = NV_VI_0_SYNCPTS,
+       .modulemutexes = BIT(NVMODMUTEX_VI_0),
+       .exclusive     = true,
+       .clocks = {{"vi", UINT_MAX}, {} },
+       NVHOST_MODULE_NO_POWERGATE_IDS,
+       NVHOST_DEFAULT_CLOCKGATE_DELAY,
+       .moduleid      = NVHOST_MODULE_VI,
+},},
+(struct nvhost_device [])
+{{     .name          = "vi",
+       .id            = 1, /* .1 on the dev node */
+       .syncpts       = NV_VI_1_SYNCPTS,
+       .modulemutexes = BIT(NVMODMUTEX_VI_1),
+       .exclusive     = true,
+       .clocks = {{"vi.1", UINT_MAX}, {} },
+       NVHOST_MODULE_NO_POWERGATE_IDS,
+       NVHOST_DEFAULT_CLOCKGATE_DELAY,
+       .moduleid      = (1 << 16 | NVHOST_MODULE_VI),
+},},
+(struct nvhost_device []){{
+       .name          = "msenc",
+       .resource      = msenc_resources,
+       .num_resources = ARRAY_SIZE(msenc_resources),
+       .syncpts       = BIT(NVSYNCPT_MSENC),
+       .waitbases     = BIT(NVWAITBASE_MSENC),
+       .class         = NV_VIDEO_ENCODE_MSENC_CLASS_ID,
+       .exclusive     = true,
+       .keepalive     = true,
+       .init          = nvhost_msenc_init,
+       .deinit        = nvhost_msenc_deinit,
+#define HOST_EMC_FLOOR 300000000
+       .clocks = {{"msenc", UINT_MAX}, {"emc", HOST_EMC_FLOOR} },
+       NVHOST_MODULE_NO_POWERGATE_IDS,
+       NVHOST_DEFAULT_CLOCKGATE_DELAY,
+       .moduleid      = NVHOST_MODULE_MSENC,
+},},
+(struct nvhost_device []){{
+       .name          = "dsi",
+       .syncpts       = BIT(NVSYNCPT_DSI),
+       .modulemutexes = BIT(NVMODMUTEX_DSI),
+       NVHOST_MODULE_NO_POWERGATE_IDS,
+       NVHOST_DEFAULT_CLOCKGATE_DELAY,
+       .moduleid      = NVHOST_MODULE_NONE,
+},},
+(struct nvhost_device []){{
+       .name          = "tsec",
+       .resource      = tsec_resources,
+       .num_resources = ARRAY_SIZE(tsec_resources),
+       .waitbases     = BIT(NVWAITBASE_TSEC),
+       .class         = NV_TSEC_CLASS_ID,
+       .exclusive     = true,
+       .init          = nvhost_tsec_init,
+       .deinit        = nvhost_tsec_deinit,
+       .clocks = {{"tsec", UINT_MAX}, {"emc", HOST_EMC_FLOOR} },
+       NVHOST_MODULE_NO_POWERGATE_IDS,
+       NVHOST_DEFAULT_CLOCKGATE_DELAY,
+       .moduleid      = NVHOST_MODULE_TSEC,
+},},
+     &gk20a_device,
+#ifdef CONFIG_ARCH_TEGRA_VIC
+    &vic03_device,
+#endif
+};
+
+int tegra12_register_host1x_devices(void)
+{
+       nvhost_dbg_fn("");
+       return nvhost_add_devices(channel_devices, ARRAY_SIZE(channel_devices));
+}
+
+static inline void __iomem *t124_channel_aperture(void __iomem *p, int ndx)
+{
+       return p;
+}
+
+static int t124_channel_init(struct nvhost_channel *ch,
+                           struct nvhost_master *dev, int index)
+{
+       ch->chid = index;
+       mutex_init(&ch->reflock);
+       mutex_init(&ch->submitlock);
+
+       ch->aperture = t124_channel_aperture(dev->aperture, index);
+
+       nvhost_dbg_fn("dev=%s chid=%d ap=%p",
+                     dev_name(&ch->dev->dev),
+                     ch->chid,
+                     ch->aperture);
+
+       return t124_nvhost_hwctx_handler_init(ch);
+}
+
+#include "host1x/host1x_channel.c"
+static int t124_channel_submit(struct nvhost_job *job)
+{
+       nvhost_dbg_fn("");
+       if (job->ch->dev == &gk20a_device)
+               return gk20a_channel_submit(job);
+       else
+               return host1x_channel_submit(job);
+}
+
+static int t124_channel_alloc_obj(struct nvhost_hwctx *hwctx,
+                                struct nvhost_alloc_obj_ctx_args *args)
+{
+       nvhost_dbg_fn("");
+       return gk20a_alloc_obj_ctx(hwctx->priv, args);
+}
+
+static int t124_channel_free_obj(struct nvhost_hwctx *hwctx,
+                               struct nvhost_free_obj_ctx_args *args)
+{
+       nvhost_dbg_fn("");
+       return gk20a_free_obj_ctx(hwctx->priv, args);
+}
+
+static int t124_channel_alloc_gpfifo(struct nvhost_hwctx *hwctx,
+                                   struct nvhost_alloc_gpfifo_args *args)
+{
+       nvhost_dbg_fn("");
+       return gk20a_alloc_channel_gpfifo(hwctx->priv, args);
+}
+
+static int t124_channel_submit_gpfifo(struct nvhost_hwctx *hwctx,
+                                    struct nvhost_gpfifo *gpfifo, u32 num_entries,
+                                    struct nvhost_fence *fence, u32 flags)
+{
+       nvhost_dbg_fn("");
+       return gk20a_submit_channel_gpfifo(hwctx->priv, gpfifo, num_entries,
+                                       fence, flags);
+}
+
+static int t124_channel_map_buffer(struct nvhost_hwctx *hwctx,
+                                   struct nvhost_map_buffer_args *args)
+{
+       nvhost_dbg_fn("");
+       return gk20a_channel_map_buffer(hwctx->priv, args);
+}
+
+static int t124_channel_unmap_buffer(struct nvhost_hwctx *hwctx,
+                                   struct nvhost_unmap_buffer_args *args)
+{
+       nvhost_dbg_fn("");
+       return gk20a_channel_unmap_buffer(hwctx->priv, args);
+}
+
+static int t124_channel_wait(struct nvhost_hwctx *hwctx,
+                           struct nvhost_wait_args *args)
+{
+       nvhost_dbg_fn("");
+       return gk20a_channel_wait(hwctx->priv, args);
+}
+
+static int t124_channel_read_3d_reg(struct nvhost_channel *channel,
+                       struct nvhost_hwctx *hwctx,
+                       u32 offset,
+                       u32 *value)
+{
+       return -EPERM;
+}
+
+static int t124_channel_zcull_get_size(struct nvhost_hwctx *hwctx,
+                           struct nvhost_zcull_get_size_args *args)
+{
+       nvhost_dbg_fn("");
+       return gk20a_channel_zcull_get_size(hwctx->priv, args);
+}
+
+static int t124_channel_zcull_bind(struct nvhost_hwctx *hwctx,
+                           struct nvhost_zcull_bind_args *args)
+{
+       nvhost_dbg_fn("");
+       return gk20a_channel_zcull_bind(hwctx->priv, args);
+}
+
+static int t124_channel_zcull_get_info(struct nvhost_hwctx *hwctx,
+                           struct nvhost_zcull_get_info_args *args)
+{
+       nvhost_dbg_fn("");
+       return gk20a_channel_zcull_get_info(hwctx->priv, args);
+}
+
+static int t124_channel_zbc_set_table(struct nvhost_hwctx *hwctx,
+                               struct nvhost_zbc_set_table_args *args)
+{
+       nvhost_dbg_fn("");
+       return gk20a_channel_zbc_set_table(hwctx->priv, args);
+}
+
+static int t124_channel_zbc_query_table(struct nvhost_hwctx *hwctx,
+                               struct nvhost_zbc_query_table_args *args)
+{
+       nvhost_dbg_fn("");
+       return gk20a_channel_zbc_query_table(hwctx->priv, args);
+}
+
+static void t124_free_nvhost_channel(struct nvhost_channel *ch)
+{
+       nvhost_dbg_fn("");
+       nvhost_free_channel_internal(ch, &t124_num_alloc_channels);
+}
+
+static struct nvhost_channel *t124_alloc_nvhost_channel(
+               struct nvhost_device *dev)
+{
+       nvhost_dbg_fn("");
+       return nvhost_alloc_channel_internal(dev->index,
+               nvhost_get_host(dev)->info.nb_channels,
+               &t124_num_alloc_channels);
+}
+
+int nvhost_init_t124_channel_support(struct nvhost_master *host,
+       struct nvhost_chip_support *op)
+{
+       int i, nb_channels;
+       nvhost_dbg_fn("max channels=%d devices=%d",
+                     NV_HOST1X_CHANNELS,
+                     ARRAY_SIZE(channel_devices));
+       BUILD_BUG_ON(T124_NVHOST_NUMCHANNELS < ARRAY_SIZE(channel_devices));
+
+       nb_channels =  ARRAY_SIZE(channel_devices);
+
+       /* Set indices dynamically as we can have
+        * missing/non-static devices above (e.g.: vic, gk20a).
+        */
+
+       for (i = 0; i < nb_channels; i++ ) {
+               struct nvhost_device *dev = channel_devices[i];
+
+               dev->index = i;
+
+               if (dev == &vic03_device) {
+                       dev->modulemutexes = BIT(NVMODMUTEX_VIC);
+                       dev->syncpts = BIT(NVSYNCPT_VIC);
+               }
+               if (dev == &gk20a_device) {
+                       dev->syncpts       = BIT(NVSYNCPT_3D);
+                       dev->waitbases     = BIT(NVWAITBASE_3D);
+                       dev->modulemutexes = BIT(NVMODMUTEX_3D);
+               }
+       }
+
+       op->channel.init          = t124_channel_init;
+       op->channel.submit        = t124_channel_submit;
+       op->channel.alloc_obj     = t124_channel_alloc_obj;
+       op->channel.free_obj      = t124_channel_free_obj;
+       op->channel.alloc_gpfifo  = t124_channel_alloc_gpfifo;
+       op->channel.submit_gpfifo = t124_channel_submit_gpfifo;
+       op->channel.map_buffer    = t124_channel_map_buffer;
+       op->channel.unmap_buffer  = t124_channel_unmap_buffer;
+       op->channel.wait          = t124_channel_wait;
+       op->channel.read3dreg     = t124_channel_read_3d_reg;
+
+       op->channel.zcull.get_size = t124_channel_zcull_get_size;
+       op->channel.zcull.bind     = t124_channel_zcull_bind;
+       op->channel.zcull.get_info = t124_channel_zcull_get_info;
+
+       op->channel.zbc.set_table   = t124_channel_zbc_set_table;
+       op->channel.zbc.query_table = t124_channel_zbc_query_table;
+
+       op->nvhost_dev.alloc_nvhost_channel = t124_alloc_nvhost_channel;
+       op->nvhost_dev.free_nvhost_channel = t124_free_nvhost_channel;
+
+       return 0;
+}
+
+int t124_nvhost_hwctx_handler_init(struct nvhost_channel *ch)
+{
+       int err = 0;
+       unsigned long syncpts = ch->dev->syncpts;
+       unsigned long waitbases = ch->dev->waitbases;
+       u32 syncpt = find_first_bit(&syncpts, BITS_PER_LONG);
+       u32 waitbase = find_first_bit(&waitbases, BITS_PER_LONG);
+
+       nvhost_dbg_fn("");
+
+       if (ch->dev->alloc_hwctx_handler) {
+               ch->ctxhandler = ch->dev->alloc_hwctx_handler(syncpt,
+                               waitbase, ch);
+               if (!ch->ctxhandler)
+                       err = -ENOMEM;
+       }
+
+       return err;
+}
+
+static void t124_remove_support(struct nvhost_chip_support *op)
+{
+       kfree(op->priv);
+       op->priv = 0;
+}
+
+int nvhost_init_t124_support(struct nvhost_master *host,
+       struct nvhost_chip_support *op)
+{
+       int err;
+       struct t124 *t124 = 0;
+
+       /* don't worry about cleaning up on failure... "remove" does it. */
+       err = nvhost_init_t124_channel_support(host, op);
+       if (err)
+               return err;
+
+       err = nvhost_init_t124_cdma_support(op);
+       if (err)
+               return err;
+
+       err = nvhost_init_t124_debug_support(op);
+       if (err)
+               return err;
+
+       err = nvhost_init_t124_syncpt_support(host, op);
+       if (err)
+               return err;
+
+       err = nvhost_init_t124_intr_support(op);
+       if (err)
+               return err;
+       err = nvhost_memmgr_init(op);
+       if (err)
+               return err;
+
+       err = nvhost_init_t124_as_support(op);
+       if (err)
+               return err;
+
+       t124 = kzalloc(sizeof(struct t124), GFP_KERNEL);
+       if (!t124) {
+               err = -ENOMEM;
+               goto err;
+       }
+
+       t124->host = host;
+       op->priv = t124;
+       op->remove_support = t124_remove_support;
+       op->nvhost_dev.alloc_nvhost_channel = t124_alloc_nvhost_channel;
+       op->nvhost_dev.free_nvhost_channel = t124_free_nvhost_channel;
+
+       return 0;
+
+err:
+       kfree(t124);
+
+       op->priv = 0;
+       op->remove_support = 0;
+       return err;
+}
diff --git a/drivers/video/tegra/host/t124/t124.h b/drivers/video/tegra/host/t124/t124.h
new file mode 100644 (file)
index 0000000..70bed76
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * drivers/video/tegra/host/t124/t124.h
+ *
+ * Tegra Graphics Chip support for T124
+ *
+ * Copyright (c) 2011-2012, 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 _NVHOST_T124_H_
+#define _NVHOST_T124_H_
+
+/* HACK.  Get this from auto-generated hardware def'n instead... */
+#define T124_NVHOST_NUMCHANNELS 12
+#define NVHOST_CHANNEL_BASE 0
+
+/*
+ * NOTE: currently we have user-mode code which is relying upon
+ * this *exact* ordering of module mutexes across *all* SOCs.
+ * For now just deal with it as we have the space to accomodate.
+ * The entries marked "n/a" below can be removed when that issue is
+ * fixed (and the entries could then be re-ordered/packed).
+ */
+#define NVMODMUTEX_2D_FULL_X   (1) /* n/a */
+#define NVMODMUTEX_2D_SIMPLE_X (2) /* n/a */
+#define NVMODMUTEX_2D_SB_A_X   (3) /* n/a */
+#define NVMODMUTEX_2D_SB_B_X   (4) /* n/a */
+#define NVMODMUTEX_3D        (5)
+#define NVMODMUTEX_DISPLAYA  (6)
+#define NVMODMUTEX_DISPLAYB  (7)
+#define NVMODMUTEX_VI_0      (8)
+#define NVMODMUTEX_DSI       (9)
+#ifdef CONFIG_ARCH_TEGRA_VIC
+#define NVMODMUTEX_VIC       (10)
+#endif
+#define NVMODMUTEX_VI_1      (11)
+#define NVMODMUTEX_ISP_0     (1) /* above "1" isn't used in practice on t124 */
+#define NVMODMUTEX_ISP_1     (2) /* above "2" isn't used in practice on t124 */
+
+struct nvhost_chip_support;
+
+int nvhost_init_t124_support(struct nvhost_master *,
+               struct nvhost_chip_support *);
+int nvhost_init_t124_channel_support(struct nvhost_master *,
+               struct nvhost_chip_support *);
+int nvhost_init_t124_cdma_support(struct nvhost_chip_support *);
+int nvhost_init_t124_debug_support(struct nvhost_chip_support *);
+int nvhost_init_t124_syncpt_support(struct nvhost_master *,
+               struct nvhost_chip_support *);
+int nvhost_init_t124_intr_support(struct nvhost_chip_support *);
+int nvhost_init_t124_cpuaccess_support(struct nvhost_master *,
+               struct nvhost_chip_support *);
+int nvhost_init_t124_as_support(struct nvhost_chip_support *);
+
+/* these sort of stick out, per module support */
+int t124_nvhost_hwctx_handler_init(struct nvhost_channel *ch);
+
+struct gk20a;
+
+struct t124 {
+       struct nvhost_master *host;
+       struct gk20a *gk20a;
+};
+
+#endif /* _NVHOST_T124_H_ */