video: tegra: refactor for multiple chip support
Ken Adams [Sat, 18 Jun 2011 14:14:42 +0000 (10:14 -0400)]
Original-Change-Id: Ia203886a3b013612b4159393ff43a25a313d1ece
Reviewed-on: http://git-master/r/35911
Reviewed-by: Varun Colbert <vcolbert@nvidia.com>
Tested-by: Varun Colbert <vcolbert@nvidia.com>

Rebase-Id: R01b763362c13e09111f60700c3d3a7d2a9a3fc1c

33 files changed:
drivers/video/tegra/dc/dc_priv.h
drivers/video/tegra/host/Makefile
drivers/video/tegra/host/chip_support.h [new file with mode: 0644]
drivers/video/tegra/host/debug.c
drivers/video/tegra/host/debug.h [new file with mode: 0644]
drivers/video/tegra/host/dev.c
drivers/video/tegra/host/dev.h
drivers/video/tegra/host/nvhost_acm.c
drivers/video/tegra/host/nvhost_cdma.c
drivers/video/tegra/host/nvhost_cdma.h
drivers/video/tegra/host/nvhost_channel.c
drivers/video/tegra/host/nvhost_channel.h
drivers/video/tegra/host/nvhost_cpuaccess.c
drivers/video/tegra/host/nvhost_cpuaccess.h
drivers/video/tegra/host/nvhost_hwctx.h
drivers/video/tegra/host/nvhost_intr.c
drivers/video/tegra/host/nvhost_intr.h
drivers/video/tegra/host/nvhost_syncpt.c
drivers/video/tegra/host/nvhost_syncpt.h
drivers/video/tegra/host/t20/3dctx_t20.c [moved from drivers/video/tegra/host/nvhost_3dctx.c with 98% similarity]
drivers/video/tegra/host/t20/Makefile [new file with mode: 0644]
drivers/video/tegra/host/t20/cdma_t20.c [new file with mode: 0644]
drivers/video/tegra/host/t20/channel_t20.c [new file with mode: 0644]
drivers/video/tegra/host/t20/cpuaccess_t20.c [new file with mode: 0644]
drivers/video/tegra/host/t20/debug_t20.c [new file with mode: 0644]
drivers/video/tegra/host/t20/hardware_t20.h [moved from drivers/video/tegra/host/nvhost_hardware.h with 90% similarity]
drivers/video/tegra/host/t20/intr_t20.c [new file with mode: 0644]
drivers/video/tegra/host/t20/syncpt_t20.c [new file with mode: 0644]
drivers/video/tegra/host/t20/syncpt_t20.h [new file with mode: 0644]
drivers/video/tegra/host/t20/t20.c [new file with mode: 0644]
drivers/video/tegra/host/t20/t20.h [new file with mode: 0644]
drivers/video/tegra/host/t30/Makefile [new file with mode: 0644]
drivers/video/tegra/host/t30/t30.c [new file with mode: 0644]

index 31706de..df03d17 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/completion.h>
 
 #include "../host/dev.h"
+#include "../host/t20/syncpt_t20.h"
 
 #define WIN_IS_TILED(win)      ((win)->flags & TEGRA_WIN_FLAG_TILED)
 #define WIN_IS_ENABLED(win)    ((win)->flags & TEGRA_WIN_FLAG_ENABLED)
index c13f834..e6b7edf 100644 (file)
@@ -5,9 +5,10 @@ nvhost-objs = \
        nvhost_cpuaccess.o \
        nvhost_intr.o \
        nvhost_channel.o \
-       nvhost_3dctx.o \
        dev.o \
        bus.o \
        debug.o
 
+obj-$(CONFIG_TEGRA_GRHOST) += t20/
+obj-$(CONFIG_TEGRA_GRHOST) += t30/
 obj-$(CONFIG_TEGRA_GRHOST) += nvhost.o
diff --git a/drivers/video/tegra/host/chip_support.h b/drivers/video/tegra/host/chip_support.h
new file mode 100644 (file)
index 0000000..0f44770
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * drivers/video/tegra/host/chip_support.h
+ *
+ * Tegra Graphics Host Chip Support
+ *
+ * Copyright (c) 2011, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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 Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef _NVHOST_CHIP_SUPPORT_H_
+#define _NVHOST_CHIP_SUPPORT_H_
+
+struct output;
+
+struct nvhost_chip_support {
+       struct {
+               int (*init)(struct nvhost_channel *,
+                           struct nvhost_master *,
+                           int chid);
+               int (*submit)(struct nvhost_channel *,
+                             struct nvhost_hwctx *,
+                             struct nvmap_client *,
+                             u32 *gather,
+                             u32 *gather_end,
+                             struct nvhost_waitchk *waitchk,
+                             struct nvhost_waitchk *waitchk_end,
+                             u32 waitchk_mask,
+                             struct nvmap_handle **unpins,
+                             int nr_unpins,
+                             u32 syncpt_id,
+                             u32 syncpt_incrs,
+                             u32 *syncpt_value,
+                             bool null_kickoff);
+       } channel;
+
+       struct {
+               void (*start)(struct nvhost_cdma *);
+               void (*stop)(struct nvhost_cdma *);
+               void (*kick)(struct  nvhost_cdma *);
+       } cdma;
+
+       struct {
+               void (*reset)(struct push_buffer *);
+               int (*init)(struct push_buffer *);
+               void (*destroy)(struct push_buffer *);
+               void (*push_to)(struct push_buffer *,
+                               u32 op1, u32 op2);
+               void (*pop_from)(struct push_buffer *,
+                                unsigned int slots);
+               u32 (*space)(struct push_buffer *);
+               u32 (*putptr)(struct push_buffer *);
+       } push_buffer;
+
+       struct {
+               void (*show_channel_cdma)(struct nvhost_master *,
+                                         struct output *,
+                                         int chid);
+               void (*show_channel_fifo)(struct nvhost_master *,
+                                         struct output *,
+                                         int chid);
+               void (*show_mlocks)(struct nvhost_master *m,
+                                   struct output *o);
+
+       } debug;
+
+       struct {
+               void (*reset)(struct nvhost_syncpt *, u32 id);
+               void (*reset_wait_base)(struct nvhost_syncpt *, u32 id);
+               void (*read_wait_base)(struct nvhost_syncpt *, u32 id);
+               u32 (*update_min)(struct nvhost_syncpt *, u32 id);
+               void (*cpu_incr)(struct nvhost_syncpt *, u32 id);
+               int (*wait_check)(struct nvhost_syncpt *sp,
+                                 struct nvmap_client *nvmap,
+                                 u32 waitchk_mask,
+                                 struct nvhost_waitchk *wait,
+                                 struct nvhost_waitchk *waitend);
+               void (*debug)(struct nvhost_syncpt *);
+               const char * (*name)(struct nvhost_syncpt *, u32 id);
+       } syncpt;
+
+       struct {
+               void (*init_host_sync)(struct nvhost_intr *);
+               void (*set_host_clocks_per_usec)(
+                       struct nvhost_intr *, u32 clocks);
+               void (*set_syncpt_threshold)(
+                       struct nvhost_intr *, u32 id, u32 thresh);
+               void (*enable_syncpt_intr)(struct nvhost_intr *, u32 id);
+               void (*disable_all_syncpt_intrs)(struct nvhost_intr *);
+               int  (*request_host_general_irq)(struct nvhost_intr *);
+               void (*free_host_general_irq)(struct nvhost_intr *);
+       } intr;
+
+       struct {
+               int (*mutex_try_lock)(struct nvhost_cpuaccess *,
+                                     unsigned int idx);
+               void (*mutex_unlock)(struct nvhost_cpuaccess *,
+                                    unsigned int idx);
+       } cpuaccess;
+};
+
+
+int nvhost_init_t20_support(struct nvhost_master *host);
+int nvhost_init_t30_support(struct nvhost_master *host);
+
+
+/* place holder for chip id assumed to live in kernel/arch/arm/mach-tegra */
+struct tegra_chip_info {
+#define TEGRA_SOC_CHIP_ARCH_T20 0
+#define TEGRA_SOC_CHIP_IMPL_T20 0
+       u16 arch;
+#define TEGRA_SOC_CHIP_ARCH_T30 1
+#define TEGRA_SOC_CHIP_IMPL_T30 0
+       u16 impl;
+};
+
+#if 0
+extern int tegra_get_chip_info(struct tegra_chip_info *);
+#else
+static inline int tegra_get_chip_info(struct tegra_chip_info *ci)
+{
+#if defined(CONFIG_ARCH_TEGRA_3x_SOC)
+       ci->arch = TEGRA_SOC_CHIP_ARCH_T30;
+       ci->impl = TEGRA_SOC_CHIP_IMPL_T30;
+
+#elif defined(CONFIG_ARCH_TEGRA_2x_SOC)
+       ci->arch = TEGRA_SOC_CHIP_ARCH_T20;
+       ci->impl = TEGRA_SOC_CHIP_IMPL_T20;
+
+#else
+       return -ENODEV;
+#endif
+
+       return 0;
+}
+#endif
+
+#endif /* _NVHOST_CHIP_SUPPORT_H_ */
index f4c6562..c0cdf65 100644 (file)
 #include <asm/io.h>
 
 #include "dev.h"
-
-struct output {
-       void (*fn)(void *ctx, const char* str, size_t len);
-       void *ctx;
-       char buf[256];
-};
+#include "debug.h"
 
 pid_t nvhost_debug_null_kickoff_pid;
 
-static void write_to_seqfile(void *ctx, const char* str, size_t len)
-{
-       seq_write((struct seq_file *)ctx, str, len);
-}
-
-static void write_to_printk(void *ctx, const char* str, size_t len)
-{
-       printk("%s", str);
-}
-
-static void output(struct output *o, const char* fmt, ...)
+void nvhost_debug_output(struct output *o, const char* fmt, ...)
 {
        va_list args;
        int len;
@@ -53,294 +38,40 @@ static void output(struct output *o, const char* fmt, ...)
        o->fn(o->ctx, o->buf, len);
 }
 
-enum {
-       NVHOST_DBG_STATE_CMD = 0,
-       NVHOST_DBG_STATE_DATA = 1,
-       NVHOST_DBG_STATE_GATHER = 2
-};
-
-static int show_channel_command(struct output *o, u32 val, int *count)
-{
-       unsigned mask;
-       unsigned subop;
-
-       switch (val >> 28) {
-       case 0x0:
-               mask = val & 0x3f;
-               if (mask) {
-                       output(o, "SETCL(class=%03x, offset=%03x, mask=%02x, [",
-                                  val >> 6 & 0x3ff, val >> 16 & 0xfff, mask);
-                       *count = hweight8(mask);
-                       return NVHOST_DBG_STATE_DATA;
-               } else {
-                       output(o, "SETCL(class=%03x)\n", val >> 6 & 0x3ff);
-                       return NVHOST_DBG_STATE_CMD;
-               }
-
-       case 0x1:
-               output(o, "INCR(offset=%03x, [", val >> 16 & 0xfff);
-               *count = val & 0xffff;
-               return NVHOST_DBG_STATE_DATA;
-
-       case 0x2:
-               output(o, "NONINCR(offset=%03x, [", val >> 16 & 0xfff);
-               *count = val & 0xffff;
-               return NVHOST_DBG_STATE_DATA;
-
-       case 0x3:
-               mask = val & 0xffff;
-               output(o, "MASK(offset=%03x, mask=%03x, [",
-                          val >> 16 & 0xfff, mask);
-               *count = hweight16(mask);
-               return NVHOST_DBG_STATE_DATA;
-
-       case 0x4:
-               output(o, "IMM(offset=%03x, data=%03x)\n",
-                          val >> 16 & 0xfff, val & 0xffff);
-               return NVHOST_DBG_STATE_CMD;
-
-       case 0x5:
-               output(o, "RESTART(offset=%08x)\n", val << 4);
-               return NVHOST_DBG_STATE_CMD;
-
-       case 0x6:
-               output(o, "GATHER(offset=%03x, insert=%d, type=%d, count=%04x, addr=[",
-                          val >> 16 & 0xfff, val >> 15 & 0x1, val >> 14 & 0x1,
-                          val & 0x3fff);
-               *count = val & 0x3fff; // TODO: insert
-               return NVHOST_DBG_STATE_GATHER;
-
-       case 0xe:
-               subop = val >> 24 & 0xf;
-               if (subop == 0)
-                       output(o, "ACQUIRE_MLOCK(index=%d)\n", val & 0xff);
-               else if (subop == 1)
-                       output(o, "RELEASE_MLOCK(index=%d)\n", val & 0xff);
-               else
-                       output(o, "EXTEND_UNKNOWN(%08x)\n", val);
-               return NVHOST_DBG_STATE_CMD;
-
-       default:
-               return NVHOST_DBG_STATE_CMD;
-       }
-}
-
-static void show_channel_gather(struct output *o, phys_addr_t phys_addr,
-                               u32 words);
-
-static void show_channel_word(struct output *o, int *state, int *count,
-                                    u32 addr, u32 val)
-{
-       switch (*state) {
-       case NVHOST_DBG_STATE_CMD:
-               if (addr)
-                       output(o, "%08x: %08x:", addr, val);
-               else
-                       output(o, "%08x:", val);
-
-               *state = show_channel_command(o, val, count);
-               if (*state == NVHOST_DBG_STATE_DATA && *count == 0) {
-                       *state = NVHOST_DBG_STATE_CMD;
-                       output(o, "])\n");
-               }
-               break;
-
-       case NVHOST_DBG_STATE_DATA:
-               (*count)--;
-               output(o, "%08x%s", val, *count > 0 ? ", " : "])\n");
-               if (*count == 0)
-                       *state = NVHOST_DBG_STATE_CMD;
-               break;
-
-       case NVHOST_DBG_STATE_GATHER:
-               *state = NVHOST_DBG_STATE_CMD;
-               output(o, "%08x]):\n", val);
-               show_channel_gather(o, val, *count);
-               break;
-       }
-}
-
-/*
- * TODO: This uses ioremap_xxx on memory which is deprecated.
- * Also, it won't work properly with SMMU.
- */
-static void show_channel_gather(struct output *o, phys_addr_t phys_addr,
-                               u32 words)
-{
-       phys_addr_t map_base = phys_addr & PAGE_MASK;
-       phys_addr_t map_end = (phys_addr + words * 4 + PAGE_SIZE - 1) & PAGE_MASK;
-       phys_addr_t map_size = map_end - map_base;
-       phys_addr_t map_offset = phys_addr - map_base;
-       void *map_addr = ioremap_nocache(map_base, map_size);
-       int state = NVHOST_DBG_STATE_CMD;
-       int count, i;
-
-       if (!map_addr)
-               return;
-       for (i = 0; i < words; i++)
-               show_channel_word(o, &state, &count, phys_addr + i * 4,
-                               readl(map_addr + map_offset + i * 4));
-       iounmap(map_addr);
-}
-
-static void show_channel_pair(struct output *o, u32 addr,
-                               u32 w0, u32 w1)
-{
-       int state = NVHOST_DBG_STATE_CMD;
-       int count;
-
-       show_channel_word(o, &state, &count, addr, w0);
-       show_channel_word(o, &state, &count, addr, w1);
-}
-
-static void show_channel_cdma(struct nvhost_master *m,
-                       struct output *o, int chid)
-{
-       struct nvhost_channel *channel = m->channels + chid;
-       u32 dmaput, dmaget, dmactrl;
-       u32 cbstat, cbread;
-       u32 val, base, baseval;
-       u32 pbw[2];
-
-       dmaput = readl(channel->aperture + HOST1X_CHANNEL_DMAPUT);
-       dmaget = readl(channel->aperture + HOST1X_CHANNEL_DMAGET);
-       dmactrl = readl(channel->aperture + HOST1X_CHANNEL_DMACTRL);
-       cbread = readl(m->aperture + HOST1X_SYNC_CBREAD(chid));
-       cbstat = readl(m->aperture + HOST1X_SYNC_CBSTAT(chid));
-
-       output(o, "%d-%s (%d): ", chid,
-               channel->mod.name, atomic_read(&channel->mod.refcount));
-
-       if ((dmactrl & 1) || !channel->cdma.push_buffer.mapped) {
-               output(o, "inactive\n\n");
-               return;
-       }
-
-       switch (cbstat) {
-       case 0x00010008:
-               output(o, "waiting on syncpt %d val %d\n",
-                       cbread >> 24, cbread & 0xffffff);
-               break;
-
-       case 0x00010009:
-               base = (cbread >> 16) & 0xff;
-               val = readl(m->aperture + HOST1X_SYNC_SYNCPT_BASE(base));
-               baseval = val & 0xffff;
-               val = cbread & 0xffff;
-               output(o, "waiting on syncpt %d val %d "
-                         "(base %d = %d; offset = %d)\n",
-                       cbread >> 24, baseval + val,
-                       base, baseval, val);
-               break;
-
-       default:
-               output(o, "active class %02x, offset %04x, val %08x\n",
-                       cbstat >> 16, cbstat & 0xffff, cbread);
-               break;
-       }
-
-       nvhost_cdma_peek(&channel->cdma, dmaget, -1, pbw);
-       show_channel_pair(o, chid, pbw[0], pbw[1]);
-       output(o, "\n");
-}
-
-void show_channel_fifo(struct nvhost_master *m,
-                       struct output *o, int chid)
-{
-       u32 val, rd_ptr, wr_ptr, start, end;
-       int state, count;
-
-       val = readl(m->aperture + HOST1X_CHANNEL_FIFOSTAT);
-       if (val & (1 << 10))
-               return;
-
-       writel(0x0, m->aperture + HOST1X_SYNC_CFPEEK_CTRL);
-       writel((1 << 31) | (chid << 16),
-               m->aperture + HOST1X_SYNC_CFPEEK_CTRL);
-
-       val = readl(m->aperture + HOST1X_SYNC_CFPEEK_PTRS);
-       rd_ptr = val & 0x1ff;
-       wr_ptr = (val >> 16) & 0x1ff;
-
-       val = readl(m->aperture + HOST1X_SYNC_CF_SETUP(chid));
-       start = val & 0x1ff;
-       end = (val >> 16) & 0x1ff;
-
-       state = NVHOST_DBG_STATE_CMD;
-       output(o, "%d: fifo:\n", chid);
-
-       do {
-               writel(0x0, m->aperture + HOST1X_SYNC_CFPEEK_CTRL);
-               writel((1 << 31) | (chid << 16) | rd_ptr,
-                       m->aperture + HOST1X_SYNC_CFPEEK_CTRL);
-               val = readl(m->aperture + HOST1X_SYNC_CFPEEK_READ);
-
-               show_channel_word(o, &state, &count, 0, val);
-
-               if (rd_ptr == end)
-                       rd_ptr = start;
-               else
-                       rd_ptr++;
-       } while (rd_ptr != wr_ptr);
-
-       if (state == NVHOST_DBG_STATE_DATA)
-               output(o, ", ...])\n");
-       output(o, "\n");
-
-       writel(0x0, m->aperture + HOST1X_SYNC_CFPEEK_CTRL);
-}
 
 static void show_channels(struct nvhost_master *m, struct output *o)
 {
        int i;
-       output(o, "---- channels ----\n");
-       for (i = 0; i < NVHOST_NUMCHANNELS; i++) {
-               show_channel_cdma(m, o, i);
-               show_channel_fifo(m, o, i);
+       nvhost_debug_output(o, "---- channels ----\n");
+       for (i = 0; i < m->nb_channels; i++) {
+               m->op.debug.show_channel_cdma(m, o, i);
+               m->op.debug.show_channel_fifo(m, o, i);
        }
 }
 
-static void show_mlocks(struct nvhost_master *m, struct output *o)
-{
-       u32 __iomem *mlo_regs = m->sync_aperture + HOST1X_SYNC_MLOCK_OWNER_0;
-       int i;
-
-       output(o, "---- mlocks ----\n");
-       for (i = 0; i < NV_HOST1X_NB_MLOCKS; i++) {
-               u32 owner = readl(mlo_regs + i);
-               if (owner & 0x1)
-                       output(o, "%d: locked by channel %d\n",
-                               i, (owner >> 8) & 0xf);
-               else if (owner & 0x2)
-                       output(o, "%d: locked by cpu\n", i);
-               else
-                       output(o, "%d: unlocked\n", i);
-       }
-       output(o, "\n");
-}
 
 static void show_syncpts(struct nvhost_master *m, struct output *o)
 {
        int i;
-
-       output(o, "---- syncpts ----\n");
-       for (i = 0; i < NV_HOST1X_SYNCPT_NB_PTS; i++) {
+       BUG_ON(!m->op.syncpt.name);
+       nvhost_debug_output(o, "---- syncpts ----\n");
+       for (i = 0; i < m->syncpt.nb_pts; i++) {
                u32 max = nvhost_syncpt_read_max(&m->syncpt, i);
                if (!max)
                        continue;
-               output(o, "id %d (%s) min %d max %d\n",
-                       i, nvhost_syncpt_name(i),
+               nvhost_debug_output(o, "id %d (%s) min %d max %d\n",
+                                   i, m->op.syncpt.name(&m->syncpt, i),
                        nvhost_syncpt_update_min(&m->syncpt, i), max);
 
        }
-       output(o, "\n");
+       nvhost_debug_output(o, "\n");
 }
 
 static void show_all(struct nvhost_master *m, struct output *o)
 {
        nvhost_module_busy(&m->mod);
 
-       show_mlocks(m, o);
+       m->op.debug.show_mlocks(m, o);
        show_syncpts(m, o);
        show_channels(m, o);
 
diff --git a/drivers/video/tegra/host/debug.h b/drivers/video/tegra/host/debug.h
new file mode 100644 (file)
index 0000000..829c29e
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * drivers/video/tegra/host/debug.h
+ *
+ * Tegra Graphics Host Debug
+ *
+ * Copyright (c) 2011 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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 Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef __NVHOST_DEBUG_H
+#define __NVHOST_DEBUG_H
+
+struct output {
+       void (*fn)(void *ctx, const char* str, size_t len);
+       void *ctx;
+       char buf[256];
+};
+
+static inline void write_to_seqfile(void *ctx, const char* str, size_t len)
+{
+       seq_write((struct seq_file *)ctx, str, len);
+}
+
+static inline void write_to_printk(void *ctx, const char* str, size_t len)
+{
+       printk("%s", str);
+}
+
+void nvhost_debug_output(struct output *o, const char* fmt, ...);
+
+#endif /*__NVHOST_DEBUG_H */
index 09ab33f..bfb7e11 100644 (file)
@@ -45,7 +45,7 @@
 #define IFACE_NAME "nvhost"
 
 static int nvhost_major = NVHOST_MAJOR;
-static int nvhost_minor = NVHOST_CHANNEL_BASE;
+static int nvhost_minor;
 static unsigned int register_sets;
 
 struct nvhost_channel_userctx {
@@ -65,7 +65,7 @@ struct nvhost_channel_userctx {
 
 struct nvhost_ctrl_userctx {
        struct nvhost_master *dev;
-       u32 mod_locks[NV_HOST1X_NB_MLOCKS];
+       u32 *mod_locks;
 };
 
 static int nvhost_channelrelease(struct inode *inode, struct file *filp)
@@ -308,7 +308,8 @@ static int nvhost_ioctl_channel_flush(
                null_kickoff = 1;
 
        /* context switch if needed, and submit user's gathers to the channel */
-       err = nvhost_channel_submit(ctx->ch, ctx->hwctx, ctx->nvmap,
+       BUG_ON(!channel_op(ctx->ch).submit);
+       err = channel_op(ctx->ch).submit(ctx->ch, ctx->hwctx, ctx->nvmap,
                                ctx->gathers, ctx->cur_gather,
                                ctx->waitchks, ctx->cur_waitchk,
                                ctx->hdr.waitchk_mask,
@@ -438,9 +439,10 @@ static int nvhost_ctrlrelease(struct inode *inode, struct file *filp)
        filp->private_data = NULL;
        if (priv->mod_locks[0])
                nvhost_module_idle(&priv->dev->mod);
-       for (i = 1; i < NV_HOST1X_NB_MLOCKS; i++)
+       for (i = 1; i < priv->dev->nb_mlocks; i++)
                if (priv->mod_locks[i])
                        nvhost_mutex_unlock(&priv->dev->cpuaccess, i);
+       kfree(priv->mod_locks);
        kfree(priv);
        return 0;
 }
@@ -449,14 +451,21 @@ static int nvhost_ctrlopen(struct inode *inode, struct file *filp)
 {
        struct nvhost_master *host = container_of(inode->i_cdev, struct nvhost_master, cdev);
        struct nvhost_ctrl_userctx *priv;
+       u32 *mod_locks;
 
        trace_nvhost_ctrlopen(host->mod.name);
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-       if (!priv)
+       mod_locks = kzalloc(sizeof(u32)*host->nb_mlocks, GFP_KERNEL);
+
+       if (!(priv && mod_locks)) {
+               kfree(priv);
+               kfree(mod_locks);
                return -ENOMEM;
+       }
 
        priv->dev = host;
+       priv->mod_locks = mod_locks;
        filp->private_data = priv;
        return 0;
 }
@@ -465,7 +474,7 @@ static int nvhost_ioctl_ctrl_syncpt_read(
        struct nvhost_ctrl_userctx *ctx,
        struct nvhost_ctrl_syncpt_read_args *args)
 {
-       if (args->id >= NV_HOST1X_SYNCPT_NB_PTS)
+       if (args->id >= ctx->dev->syncpt.nb_pts)
                return -EINVAL;
        trace_nvhost_ioctl_ctrl_syncpt_read(args->id);
        args->value = nvhost_syncpt_read(&ctx->dev->syncpt, args->id);
@@ -476,7 +485,7 @@ static int nvhost_ioctl_ctrl_syncpt_incr(
        struct nvhost_ctrl_userctx *ctx,
        struct nvhost_ctrl_syncpt_incr_args *args)
 {
-       if (args->id >= NV_HOST1X_SYNCPT_NB_PTS)
+       if (args->id >= ctx->dev->syncpt.nb_pts)
                return -EINVAL;
        trace_nvhost_ioctl_ctrl_syncpt_incr(args->id);
        nvhost_syncpt_incr(&ctx->dev->syncpt, args->id);
@@ -488,7 +497,7 @@ static int nvhost_ioctl_ctrl_syncpt_waitex(
        struct nvhost_ctrl_syncpt_waitex_args *args)
 {
        u32 timeout;
-       if (args->id >= NV_HOST1X_SYNCPT_NB_PTS)
+       if (args->id >= ctx->dev->syncpt.nb_pts)
                return -EINVAL;
        if (args->timeout == NVHOST_NO_TIMEOUT)
                timeout = MAX_SCHEDULE_TIMEOUT;
@@ -506,7 +515,7 @@ static int nvhost_ioctl_ctrl_module_mutex(
        struct nvhost_ctrl_module_mutex_args *args)
 {
        int err = 0;
-       if (args->id >= NV_HOST1X_NB_MLOCKS ||
+       if (args->id >= ctx->dev->nb_mlocks ||
            args->lock > 1)
                return -EINVAL;
 
@@ -538,7 +547,7 @@ static int nvhost_ioctl_ctrl_module_regrdwr(
        void *values = args->values;
        u32 vals[64];
 
-       if (!nvhost_access_module_regs(&ctx->dev->cpuaccess, args->id) ||
+       if (!(args->id < ctx->dev->nb_modules) ||
            (num_offsets == 0))
                return -EINVAL;
 
@@ -638,7 +647,7 @@ static void power_host(struct nvhost_module *mod, enum nvhost_power_action actio
                 */
        } else if (action == NVHOST_POWER_ACTION_OFF) {
                int i;
-               for (i = 0; i < NVHOST_NUMCHANNELS; i++)
+               for (i = 0; i < dev->nb_channels; i++)
                        nvhost_channel_suspend(&dev->channels[i]);
                nvhost_syncpt_save(&dev->syncpt);
                nvhost_intr_stop(&dev->intr);
@@ -658,10 +667,11 @@ static int __devinit nvhost_user_init(struct nvhost_master *host)
 
        if (nvhost_major) {
                devno = MKDEV(nvhost_major, nvhost_minor);
-               err = register_chrdev_region(devno, NVHOST_NUMCHANNELS + 1, IFACE_NAME);
+               err = register_chrdev_region(devno, host->nb_channels + 1,
+                                            IFACE_NAME);
        } else {
                err = alloc_chrdev_region(&devno, nvhost_minor,
-                                       NVHOST_NUMCHANNELS + 1, IFACE_NAME);
+                                       host->nb_channels + 1, IFACE_NAME);
                nvhost_major = MAJOR(devno);
        }
        if (err < 0) {
@@ -669,14 +679,9 @@ static int __devinit nvhost_user_init(struct nvhost_master *host)
                goto fail;
        }
 
-       for (i = 0; i < NVHOST_NUMCHANNELS; i++) {
+       for (i = 0; i < host->nb_channels; i++) {
                struct nvhost_channel *ch = &host->channels[i];
 
-               if (!strcmp(ch->desc->name, "display") &&
-                   !nvhost_access_module_regs(&host->cpuaccess,
-                                               NVHOST_MODULE_DISPLAY_A))
-                       continue;
-
                cdev_init(&ch->cdev, &nvhost_channelops);
                ch->cdev.owner = THIS_MODULE;
 
@@ -697,7 +702,7 @@ static int __devinit nvhost_user_init(struct nvhost_master *host)
 
        cdev_init(&host->cdev, &nvhost_ctrlops);
        host->cdev.owner = THIS_MODULE;
-       devno = MKDEV(nvhost_major, nvhost_minor + NVHOST_NUMCHANNELS);
+       devno = MKDEV(nvhost_major, nvhost_minor + host->nb_channels);
        err = cdev_add(&host->cdev, devno, 1);
        if (err < 0)
                goto fail;
@@ -714,6 +719,91 @@ fail:
        return err;
 }
 
+static void nvhost_remove_chip_support(struct nvhost_master *host)
+{
+
+       kfree(host->channels);
+       host->channels = 0;
+
+       kfree(host->syncpt.min_val);
+       host->syncpt.min_val = 0;
+
+       kfree(host->syncpt.max_val);
+       host->syncpt.max_val = 0;
+
+       kfree(host->syncpt.base_val);
+       host->syncpt.base_val = 0;
+
+       kfree(host->intr.syncpt);
+       host->intr.syncpt = 0;
+
+       kfree(host->cpuaccess.regs);
+       host->cpuaccess.regs = 0;
+
+       kfree(host->cpuaccess.reg_mem);
+       host->cpuaccess.reg_mem = 0;
+
+       kfree(host->cpuaccess.lock_counts);
+       host->cpuaccess.lock_counts = 0;
+}
+
+static int __devinit nvhost_init_chip_support(struct nvhost_master *host)
+{
+       int err;
+       err = tegra_get_chip_info(&host->chip_info);
+       if (err)
+               return err;
+
+       switch (host->chip_info.arch) {
+       case TEGRA_SOC_CHIP_ARCH_T20:
+               err = nvhost_init_t20_support(host);
+               break;
+
+       case TEGRA_SOC_CHIP_ARCH_T30:
+               err = nvhost_init_t30_support(host);
+               break;
+       default:
+               return -ENODEV;
+       }
+
+       if (err)
+               return err;
+
+       /* allocate items sized in chip specific support init */
+       host->channels = kzalloc(sizeof(struct nvhost_channel) *
+                                host->nb_channels, GFP_KERNEL);
+
+       host->syncpt.min_val = kzalloc(sizeof(atomic_t) *
+                                      host->syncpt.nb_pts, GFP_KERNEL);
+
+       host->syncpt.max_val = kzalloc(sizeof(atomic_t) *
+                                      host->syncpt.nb_pts, GFP_KERNEL);
+
+       host->syncpt.base_val = kzalloc(sizeof(u32) *
+                                       host->syncpt.nb_bases, GFP_KERNEL);
+
+       host->intr.syncpt = kzalloc(sizeof(struct nvhost_intr_syncpt) *
+                                   host->syncpt.nb_pts, GFP_KERNEL);
+
+       host->cpuaccess.reg_mem = kzalloc(sizeof(struct resource *) *
+                                      host->nb_modules, GFP_KERNEL);
+
+       host->cpuaccess.regs = kzalloc(sizeof(void __iomem *) *
+                                      host->nb_modules, GFP_KERNEL);
+
+       host->cpuaccess.lock_counts = kzalloc(sizeof(atomic_t) *
+                                      host->nb_mlocks, GFP_KERNEL);
+
+       if (!(host->channels && host->syncpt.min_val &&
+             host->syncpt.max_val && host->syncpt.base_val &&
+             host->intr.syncpt && host->cpuaccess.reg_mem &&
+             host->cpuaccess.regs && host->cpuaccess.lock_counts)) {
+               /* frees happen in the support removal phase */
+               return -ENOMEM;
+       }
+
+       return 0;
+}
 static int __devinit nvhost_probe(struct platform_device *pdev)
 {
        struct nvhost_master *host;
@@ -755,27 +845,40 @@ static int __devinit nvhost_probe(struct platform_device *pdev)
                err = -ENXIO;
                goto fail;
        }
-       host->sync_aperture = host->aperture +
-               (NV_HOST1X_CHANNEL0_BASE +
-                       HOST1X_CHANNEL_SYNC_REG_BASE);
 
-       for (i = 0; i < NVHOST_NUMCHANNELS; i++) {
+       err = nvhost_init_chip_support(host);
+       if (err) {
+               dev_err(&pdev->dev, "failed to init chip support\n");
+               goto fail;
+       }
+
+       for (i = 0; i < host->nb_channels; i++) {
                struct nvhost_channel *ch = &host->channels[i];
-               err = nvhost_channel_init(ch, host, i);
+               BUG_ON(!host_channel_op(host).init);
+               err = host_channel_op(host).init(ch, host, i);
                if (err < 0) {
                        dev_err(&pdev->dev, "failed to init channel %d\n", i);
                        goto fail;
                }
        }
 
+
        err = nvhost_cpuaccess_init(&host->cpuaccess, pdev);
-       if (err) goto fail;
+       if (err)
+               goto fail;
+
        err = nvhost_intr_init(&host->intr, intr1->start, intr0->start);
-       if (err) goto fail;
+       if (err)
+               goto fail;
+
        err = nvhost_user_init(host);
-       if (err) goto fail;
+       if (err)
+               goto fail;
+
        err = nvhost_module_init(&host->mod, "host1x", power_host, NULL, &pdev->dev);
-       if (err) goto fail;
+       if (err)
+               goto fail;
+
 
        platform_set_drvdata(pdev, host);
 
@@ -791,6 +894,7 @@ static int __devinit nvhost_probe(struct platform_device *pdev)
        return 0;
 
 fail:
+       nvhost_remove_chip_support(host);
        if (host->nvmap)
                nvmap_client_put(host->nvmap);
        /* TODO: [ahatala 2010-05-04] */
@@ -800,6 +904,9 @@ fail:
 
 static int __exit nvhost_remove(struct platform_device *pdev)
 {
+       struct nvhost_master *host = platform_get_drvdata(pdev);
+       nvhost_remove_chip_support(host);
+       /*kfree(host);?*/
        return 0;
 }
 
index 688fa43..ee79bdd 100644 (file)
@@ -28,7 +28,7 @@
 #include "nvhost_intr.h"
 #include "nvhost_cpuaccess.h"
 #include "nvhost_channel.h"
-#include "nvhost_hardware.h"
+#include "chip_support.h"
 
 #define NVHOST_MAJOR 0 /* dynamic */
 
@@ -43,9 +43,17 @@ struct nvhost_master {
        struct nvhost_syncpt syncpt;
        struct nvmap_client *nvmap;
        struct nvhost_cpuaccess cpuaccess;
+       u32 nb_mlocks;
        struct nvhost_intr intr;
        struct nvhost_module mod;
-       struct nvhost_channel channels[NVHOST_NUMCHANNELS];
+       struct nvhost_channel *channels;
+       u32 nb_channels;
+       u32 nb_modules;
+
+       u32 sync_queue_size;
+
+       struct tegra_chip_info chip_info;
+       struct nvhost_chip_support op;
 };
 
 void nvhost_debug_init(struct nvhost_master *master);
index 8d06ee7..725aebf 100644 (file)
@@ -205,14 +205,14 @@ static void debug_not_idle(struct nvhost_master *dev)
        int i;
        bool lock_released = true;
 
-       for (i = 0; i < NVHOST_NUMCHANNELS; i++) {
+       for (i = 0; i < dev->nb_channels; i++) {
                struct nvhost_module *m = &dev->channels[i].mod;
                if (m->name)
                        printk("tegra_grhost: %s: refcnt %d\n",
                                m->name, atomic_read(&m->refcount));
        }
 
-       for (i = 0; i < NV_HOST1X_SYNC_MLOCK_NUM; i++) {
+       for (i = 0; i < dev->nb_mlocks; i++) {
                int c = atomic_read(&dev->cpuaccess.lock_counts[i]);
                if (c) {
                        printk("tegra_grhost: lock id %d: refcnt %d\n", i, c);
index 05d563c..edebeeb 100644 (file)
@@ -23,7 +23,7 @@
 #include "nvhost_cdma.h"
 #include "dev.h"
 #include <asm/cacheflush.h>
-
+#include <linux/slab.h>
 /*
  * TODO:
  *   stats
  *     - some channels hardly need any, some channels (3d) could use more
  */
 
-#define cdma_to_channel(cdma) container_of(cdma, struct nvhost_channel, cdma)
-#define cdma_to_dev(cdma) ((cdma_to_channel(cdma))->dev)
-#define cdma_to_nvmap(cdma) ((cdma_to_dev(cdma))->nvmap)
-#define pb_to_cdma(pb) container_of(pb, struct nvhost_cdma, push_buffer)
-
-/*
- * push_buffer
- *
- * The push buffer is a circular array of words to be fetched by command DMA.
- * Note that it works slightly differently to the sync queue; fence == cur
- * means that the push buffer is full, not empty.
- */
-
-// 8 bytes per slot. (This number does not include the final RESTART.)
-#define PUSH_BUFFER_SIZE (NVHOST_GATHER_QUEUE_SIZE * 8)
-
-static void destroy_push_buffer(struct push_buffer *pb);
-
-/**
- * Reset to empty push buffer
- */
-static void reset_push_buffer(struct push_buffer *pb)
-{
-       pb->fence = PUSH_BUFFER_SIZE - 8;
-       pb->cur = 0;
-}
-
-/**
- * Init push buffer resources
- */
-static int init_push_buffer(struct push_buffer *pb)
-{
-       struct nvhost_cdma *cdma = pb_to_cdma(pb);
-       struct nvmap_client *nvmap = cdma_to_nvmap(cdma);
-       pb->mem = NULL;
-       pb->mapped = NULL;
-       pb->phys = 0;
-       reset_push_buffer(pb);
-
-       /* allocate and map pushbuffer memory */
-       pb->mem = nvmap_alloc(nvmap, PUSH_BUFFER_SIZE + 4, 32,
-                             NVMAP_HANDLE_WRITE_COMBINE);
-       if (IS_ERR_OR_NULL(pb->mem)) {
-               pb->mem = NULL;
-               goto fail;
-       }
-       pb->mapped = nvmap_mmap(pb->mem);
-       if (pb->mapped == NULL)
-               goto fail;
-
-       /* pin pushbuffer and get physical address */
-       pb->phys = nvmap_pin(nvmap, pb->mem);
-       if (pb->phys >= 0xfffff000) {
-               pb->phys = 0;
-               goto fail;
-       }
-
-       /* put the restart at the end of pushbuffer memory */
-       *(pb->mapped + (PUSH_BUFFER_SIZE >> 2)) = nvhost_opcode_restart(pb->phys);
-
-       return 0;
-
-fail:
-       destroy_push_buffer(pb);
-       return -ENOMEM;
-}
-
-/**
- * Clean up push buffer resources
- */
-static void destroy_push_buffer(struct push_buffer *pb)
-{
-       struct nvhost_cdma *cdma = pb_to_cdma(pb);
-       struct nvmap_client *nvmap = cdma_to_nvmap(cdma);
-       if (pb->mapped)
-               nvmap_munmap(pb->mem, pb->mapped);
-
-       if (pb->phys != 0)
-               nvmap_unpin(nvmap, pb->mem);
-
-       if (pb->mem)
-               nvmap_free(nvmap, pb->mem);
-
-       pb->mem = NULL;
-       pb->mapped = NULL;
-       pb->phys = 0;
-}
-
-/**
- * Push two words to the push buffer
- * Caller must ensure push buffer is not full
- */
-static void push_to_push_buffer(struct push_buffer *pb, u32 op1, u32 op2)
-{
-       u32 cur = pb->cur;
-       u32 *p = (u32*)((u32)pb->mapped + cur);
-       BUG_ON(cur == pb->fence);
-       *(p++) = op1;
-       *(p++) = op2;
-       pb->cur = (cur + 8) & (PUSH_BUFFER_SIZE - 1);
-       /* printk("push_to_push_buffer: op1=%08x; op2=%08x; cur=%x\n", op1, op2, pb->cur); */
-}
-
-/**
- * Pop a number of two word slots from the push buffer
- * Caller must ensure push buffer is not empty
- */
-static void pop_from_push_buffer(struct push_buffer *pb, unsigned int slots)
-{
-       pb->fence = (pb->fence + slots * 8) & (PUSH_BUFFER_SIZE - 1);
-}
-
-/**
- * Return the number of two word slots free in the push buffer
- */
-static u32 push_buffer_space(struct push_buffer *pb)
-{
-       return ((pb->fence - pb->cur) & (PUSH_BUFFER_SIZE - 1)) / 8;
-}
-
-static u32 push_buffer_putptr(struct push_buffer *pb)
-{
-       return pb->phys + pb->cur;
-}
-
-
 /* Sync Queue
  *
  * The sync queue is a circular buffer of u32s interpreted as:
@@ -198,12 +72,18 @@ static void reset_sync_queue(struct sync_queue *queue)
  */
 static unsigned int sync_queue_space(struct sync_queue *queue)
 {
+       struct nvhost_cdma *cdma;
+       struct nvhost_master *host;
+
        unsigned int read = queue->read;
        unsigned int write = queue->write;
        u32 size;
 
-       BUG_ON(read  > (NVHOST_SYNC_QUEUE_SIZE - SYNC_QUEUE_MIN_ENTRY));
-       BUG_ON(write > (NVHOST_SYNC_QUEUE_SIZE - SYNC_QUEUE_MIN_ENTRY));
+       cdma = container_of(queue, struct nvhost_cdma, sync_queue);
+       host = cdma_to_dev(cdma);
+
+       BUG_ON(read  > (host->sync_queue_size - SYNC_QUEUE_MIN_ENTRY));
+       BUG_ON(write > (host->sync_queue_size - SYNC_QUEUE_MIN_ENTRY));
 
        /*
         * We can use all of the space up to the end of the buffer, unless the
@@ -213,7 +93,7 @@ static unsigned int sync_queue_space(struct sync_queue *queue)
        if (read > write) {
                size = (read - 1) - write;
        } else {
-               size = NVHOST_SYNC_QUEUE_SIZE - write;
+               size = host->sync_queue_size - write;
 
                /*
                 * If the read position is zero, it gets complicated. We can't
@@ -248,15 +128,20 @@ static void add_to_sync_queue(struct sync_queue *queue,
                              u32 nr_slots, struct nvmap_client *user_nvmap,
                              struct nvmap_handle **handles, u32 nr_handles)
 {
+       struct nvhost_cdma *cdma;
+       struct nvhost_master *host;
        u32 write = queue->write;
        u32 *p = queue->buffer + write;
        u32 size = 4 + (entry_size(nr_handles));
 
+       cdma = container_of(queue, struct nvhost_cdma, sync_queue);
+       host = cdma_to_dev(cdma);
+
        BUG_ON(sync_point_id == NVSYNCPT_INVALID);
        BUG_ON(sync_queue_space(queue) < nr_handles);
 
        write += size;
-       BUG_ON(write > NVHOST_SYNC_QUEUE_SIZE);
+       BUG_ON(write > host->sync_queue_size);
 
        *p++ = sync_point_id;
        *p++ = sync_point_value;
@@ -271,7 +156,7 @@ static void add_to_sync_queue(struct sync_queue *queue,
                memcpy(p, handles, nr_handles * sizeof(struct nvmap_handle *));
 
        /* If there's not enough room for another entry, wrap to the start. */
-       if ((write + SYNC_QUEUE_MIN_ENTRY) > NVHOST_SYNC_QUEUE_SIZE) {
+       if ((write + SYNC_QUEUE_MIN_ENTRY) > host->sync_queue_size) {
                /*
                 * It's an error for the read position to be zero, as that
                 * would mean we emptied the queue while adding something.
@@ -289,11 +174,15 @@ static void add_to_sync_queue(struct sync_queue *queue,
  */
 static u32 *sync_queue_head(struct sync_queue *queue)
 {
+       struct nvhost_cdma *cdma = container_of(queue,
+                                               struct nvhost_cdma,
+                                               sync_queue);
+       struct nvhost_master *host = cdma_to_dev(cdma);
        u32 read = queue->read;
        u32 write = queue->write;
 
-       BUG_ON(read  > (NVHOST_SYNC_QUEUE_SIZE - SYNC_QUEUE_MIN_ENTRY));
-       BUG_ON(write > (NVHOST_SYNC_QUEUE_SIZE - SYNC_QUEUE_MIN_ENTRY));
+       BUG_ON(read  > (host->sync_queue_size - SYNC_QUEUE_MIN_ENTRY));
+       BUG_ON(write > (host->sync_queue_size - SYNC_QUEUE_MIN_ENTRY));
 
        if (read == write)
                return NULL;
@@ -306,6 +195,10 @@ static u32 *sync_queue_head(struct sync_queue *queue)
 static void
 dequeue_sync_queue_head(struct sync_queue *queue)
 {
+       struct nvhost_cdma *cdma = container_of(queue,
+                                               struct nvhost_cdma,
+                                               sync_queue);
+       struct nvhost_master *host = cdma_to_dev(cdma);
        u32 read = queue->read;
        u32 size;
 
@@ -314,62 +207,16 @@ dequeue_sync_queue_head(struct sync_queue *queue)
        size = 4 + entry_size(queue->buffer[read + 3]);
 
        read += size;
-       BUG_ON(read > NVHOST_SYNC_QUEUE_SIZE);
+       BUG_ON(read > host->sync_queue_size);
 
        /* If there's not enough room for another entry, wrap to the start. */
-       if ((read + SYNC_QUEUE_MIN_ENTRY) > NVHOST_SYNC_QUEUE_SIZE)
+       if ((read + SYNC_QUEUE_MIN_ENTRY) > host->sync_queue_size)
                read = 0;
 
        queue->read = read;
 }
 
 
-/*** Cdma internal stuff ***/
-
-/**
- * Start channel DMA
- */
-static void start_cdma(struct nvhost_cdma *cdma)
-{
-       void __iomem *chan_regs = cdma_to_channel(cdma)->aperture;
-
-       if (cdma->running)
-               return;
-
-       cdma->last_put = push_buffer_putptr(&cdma->push_buffer);
-
-       writel(nvhost_channel_dmactrl(true, false, false),
-               chan_regs + HOST1X_CHANNEL_DMACTRL);
-
-       /* set base, put, end pointer (all of memory) */
-       writel(0, chan_regs + HOST1X_CHANNEL_DMASTART);
-       writel(cdma->last_put, chan_regs + HOST1X_CHANNEL_DMAPUT);
-       writel(0xFFFFFFFF, chan_regs + HOST1X_CHANNEL_DMAEND);
-
-       /* reset GET */
-       writel(nvhost_channel_dmactrl(true, true, true),
-               chan_regs + HOST1X_CHANNEL_DMACTRL);
-
-       /* start the command DMA */
-       writel(nvhost_channel_dmactrl(false, false, false),
-               chan_regs + HOST1X_CHANNEL_DMACTRL);
-
-       cdma->running = true;
-}
-
-/**
- * Kick channel DMA into action by writing its PUT offset (if it has changed)
- */
-static void kick_cdma(struct nvhost_cdma *cdma)
-{
-       u32 put = push_buffer_putptr(&cdma->push_buffer);
-       if (put != cdma->last_put) {
-               void __iomem *chan_regs = cdma_to_channel(cdma)->aperture;
-               wmb();
-               writel(put, chan_regs + HOST1X_CHANNEL_DMAPUT);
-               cdma->last_put = put;
-       }
-}
 
 /**
  * Return the status of the cdma's sync queue or push buffer for the given event
@@ -385,8 +232,11 @@ static unsigned int cdma_status(struct nvhost_cdma *cdma, enum cdma_event event)
                return sync_queue_head(&cdma->sync_queue) ? 0 : 1;
        case CDMA_EVENT_SYNC_QUEUE_SPACE:
                return sync_queue_space(&cdma->sync_queue);
-       case CDMA_EVENT_PUSH_BUFFER_SPACE:
-               return push_buffer_space(&cdma->push_buffer);
+       case CDMA_EVENT_PUSH_BUFFER_SPACE: {
+               struct push_buffer *pb = &cdma->push_buffer;
+               BUG_ON(!cdma_pb_op(cdma).space);
+               return cdma_pb_op(cdma).space(pb);
+       }
        default:
                return 0;
        }
@@ -401,7 +251,7 @@ static unsigned int cdma_status(struct nvhost_cdma *cdma, enum cdma_event event)
  *     - Return the amount of space (> 0)
  * Must be called with the cdma lock held.
  */
-static unsigned int wait_cdma(struct nvhost_cdma *cdma, enum cdma_event event)
+unsigned int nvhost_cdma_wait(struct nvhost_cdma *cdma, enum cdma_event event)
 {
        for (;;) {
                unsigned int space = cdma_status(cdma, event);
@@ -476,7 +326,9 @@ static void update_cdma(struct nvhost_cdma *cdma)
 
                /* Pop push buffer slots */
                if (nr_slots) {
-                       pop_from_push_buffer(&cdma->push_buffer, nr_slots);
+                       struct push_buffer *pb = &cdma->push_buffer;
+                       BUG_ON(!cdma_pb_op(cdma).pop_from);
+                       cdma_pb_op(cdma).pop_from(pb, nr_slots);
                        if (cdma->event == CDMA_EVENT_PUSH_BUFFER_SPACE)
                                signal = true;
                }
@@ -499,12 +351,20 @@ static void update_cdma(struct nvhost_cdma *cdma)
 int nvhost_cdma_init(struct nvhost_cdma *cdma)
 {
        int err;
-
+       struct push_buffer *pb = &cdma->push_buffer;
+       BUG_ON(!cdma_pb_op(cdma).init);
        mutex_init(&cdma->lock);
        sema_init(&cdma->sem, 0);
        cdma->event = CDMA_EVENT_NONE;
        cdma->running = false;
-       err = init_push_buffer(&cdma->push_buffer);
+
+       /* allocate sync queue memory */
+       cdma->sync_queue.buffer = kzalloc(cdma_to_dev(cdma)->sync_queue_size
+                                         * sizeof(u32), GFP_KERNEL);
+       if (!cdma->sync_queue.buffer)
+               return -ENOMEM;
+
+       err = cdma_pb_op(cdma).init(pb);
        if (err)
                return err;
        reset_sync_queue(&cdma->sync_queue);
@@ -516,32 +376,24 @@ int nvhost_cdma_init(struct nvhost_cdma *cdma)
  */
 void nvhost_cdma_deinit(struct nvhost_cdma *cdma)
 {
+       struct push_buffer *pb = &cdma->push_buffer;
+       BUG_ON(!cdma_pb_op(cdma).destroy);
        BUG_ON(cdma->running);
-       destroy_push_buffer(&cdma->push_buffer);
+       kfree(cdma->sync_queue.buffer);
+       cdma->sync_queue.buffer = 0;
+       cdma_pb_op(cdma).destroy(pb);
 }
 
-void nvhost_cdma_stop(struct nvhost_cdma *cdma)
-{
-       void __iomem *chan_regs = cdma_to_channel(cdma)->aperture;
-
-       mutex_lock(&cdma->lock);
-       if (cdma->running) {
-               wait_cdma(cdma, CDMA_EVENT_SYNC_QUEUE_EMPTY);
-               writel(nvhost_channel_dmactrl(true, false, false),
-                       chan_regs + HOST1X_CHANNEL_DMACTRL);
-               cdma->running = false;
-       }
-       mutex_unlock(&cdma->lock);
-}
 
 /**
  * Begin a cdma submit
  */
 void nvhost_cdma_begin(struct nvhost_cdma *cdma)
 {
+       BUG_ON(!cdma_op(cdma).start);
        mutex_lock(&cdma->lock);
        if (!cdma->running)
-               start_cdma(cdma);
+               cdma_op(cdma).start(cdma);
        cdma->slots_free = 0;
        cdma->slots_used = 0;
 }
@@ -553,13 +405,16 @@ void nvhost_cdma_begin(struct nvhost_cdma *cdma)
 void nvhost_cdma_push(struct nvhost_cdma *cdma, u32 op1, u32 op2)
 {
        u32 slots_free = cdma->slots_free;
+       struct push_buffer *pb = &cdma->push_buffer;
+       BUG_ON(!cdma_pb_op(cdma).push_to);
+       BUG_ON(!cdma_op(cdma).kick);
        if (slots_free == 0) {
-               kick_cdma(cdma);
-               slots_free = wait_cdma(cdma, CDMA_EVENT_PUSH_BUFFER_SPACE);
+               cdma_op(cdma).kick(cdma);
+               slots_free = nvhost_cdma_wait(cdma, CDMA_EVENT_PUSH_BUFFER_SPACE);
        }
        cdma->slots_free = slots_free - 1;
        cdma->slots_used++;
-       push_to_push_buffer(&cdma->push_buffer, op1, op2);
+       cdma_pb_op(cdma).push_to(pb, op1, op2);
 }
 
 /**
@@ -575,7 +430,8 @@ void nvhost_cdma_end(struct nvhost_cdma *cdma,
                u32 sync_point_id, u32 sync_point_value,
                struct nvmap_handle **handles, unsigned int nr_handles)
 {
-       kick_cdma(cdma);
+       BUG_ON(!cdma_op(cdma).kick);
+       cdma_op(cdma).kick(cdma);
 
        while (nr_handles || cdma->slots_used) {
                unsigned int count;
@@ -583,7 +439,7 @@ void nvhost_cdma_end(struct nvhost_cdma *cdma,
                 * Wait until there's enough room in the
                 * sync queue to write something.
                 */
-               count = wait_cdma(cdma, CDMA_EVENT_SYNC_QUEUE_SPACE);
+               count = nvhost_cdma_wait(cdma, CDMA_EVENT_SYNC_QUEUE_SPACE);
 
                /* Add reloc entries to sync queue (as many as will fit) */
                if (count > nr_handles)
@@ -626,16 +482,3 @@ void nvhost_cdma_flush(struct nvhost_cdma *cdma)
        mutex_unlock(&cdma->lock);
 }
 
-/**
- * Retrieve the op pair at a slot offset from a DMA address
- */
-void nvhost_cdma_peek(struct nvhost_cdma *cdma,
-               u32 dmaget, int slot, u32 *out)
-{
-       u32 offset = dmaget - cdma->push_buffer.phys;
-       u32 *p = cdma->push_buffer.mapped;
-
-       offset = ((offset + slot * 8) & (PUSH_BUFFER_SIZE - 1)) >> 2;
-       out[0] = p[offset];
-       out[1] = p[offset + 1];
-}
index a587667..64d1724 100644 (file)
  *     update - call to update sync queue and push buffer, unpin memory
  */
 
-/* Size of the sync queue. If it is too small, we won't be able to queue up
- * many command buffers. If it is too large, we waste memory. */
-#define NVHOST_SYNC_QUEUE_SIZE 8192
-
-/* Number of gathers we allow to be queued up per channel. Must be a
-   power of two. Currently sized such that pushbuffer is 4KB (512*8B). */
-#define NVHOST_GATHER_QUEUE_SIZE 512
 
 struct push_buffer {
        struct nvmap_handle_ref *mem; /* handle to pushbuffer memory */
@@ -64,7 +57,7 @@ struct push_buffer {
 struct sync_queue {
        unsigned int read;                  /* read position within buffer */
        unsigned int write;                 /* write position within buffer */
-       u32 buffer[NVHOST_SYNC_QUEUE_SIZE]; /* queue data */
+       u32 *buffer;                        /* queue data */
 };
 
 enum cdma_event {
@@ -84,8 +77,17 @@ struct nvhost_cdma {
        struct push_buffer push_buffer; /* channel's push buffer */
        struct sync_queue sync_queue;   /* channel's sync queue */
        bool running;
+
 };
 
+#define cdma_to_channel(cdma) container_of(cdma, struct nvhost_channel, cdma)
+#define cdma_to_dev(cdma) ((cdma_to_channel(cdma))->dev)
+#define cdma_op(cdma) (cdma_to_dev(cdma)->op.cdma)
+#define cdma_to_nvmap(cdma) ((cdma_to_dev(cdma))->nvmap)
+#define pb_to_cdma(pb) container_of(pb, struct nvhost_cdma, push_buffer)
+#define cdma_pb_op(cdma) (cdma_to_dev(cdma)->op.push_buffer)
+
+
 int    nvhost_cdma_init(struct nvhost_cdma *cdma);
 void   nvhost_cdma_deinit(struct nvhost_cdma *cdma);
 void   nvhost_cdma_stop(struct nvhost_cdma *cdma);
@@ -100,4 +102,5 @@ void        nvhost_cdma_flush(struct nvhost_cdma *cdma);
 void   nvhost_cdma_peek(struct nvhost_cdma *cdma,
                u32 dmaget, int slot, u32 *out);
 
+unsigned int nvhost_cdma_wait(struct nvhost_cdma *cdma, enum cdma_event event);
 #endif
index f7776e6..ad8d403 100644 (file)
 
 #include <linux/platform_device.h>
 
-#define NVMODMUTEX_2D_FULL   (1)
-#define NVMODMUTEX_2D_SIMPLE (2)
-#define NVMODMUTEX_2D_SB_A   (3)
-#define NVMODMUTEX_2D_SB_B   (4)
-#define NVMODMUTEX_3D        (5)
-#define NVMODMUTEX_DISPLAYA  (6)
-#define NVMODMUTEX_DISPLAYB  (7)
-#define NVMODMUTEX_VI        (8)
-#define NVMODMUTEX_DSI       (9)
 
-static void power_2d(struct nvhost_module *mod, enum nvhost_power_action action);
-static void power_3d(struct nvhost_module *mod, enum nvhost_power_action action);
-static void power_mpe(struct nvhost_module *mod, enum nvhost_power_action action);
-
-static const struct nvhost_channeldesc channelmap[] = {
-{
-       /* channel 0 */
-       .name          = "display",
-       .syncpts       = BIT(NVSYNCPT_DISP0) | BIT(NVSYNCPT_DISP1) |
-                        BIT(NVSYNCPT_VBLANK0) | BIT(NVSYNCPT_VBLANK1),
-       .modulemutexes = BIT(NVMODMUTEX_DISPLAYA) | BIT(NVMODMUTEX_DISPLAYB),
-},
-{
-       /* channel 1 */
-       .name          = "gr3d",
-       .syncpts       = BIT(NVSYNCPT_3D),
-       .waitbases     = BIT(NVWAITBASE_3D),
-       .modulemutexes = BIT(NVMODMUTEX_3D),
-       .class         = NV_GRAPHICS_3D_CLASS_ID,
-       .power         = power_3d,
-},
-{
-       /* channel 2 */
-       .name          = "gr2d",
-       .syncpts       = BIT(NVSYNCPT_2D_0) | BIT(NVSYNCPT_2D_1),
-       .waitbases     = BIT(NVWAITBASE_2D_0) | BIT(NVWAITBASE_2D_1),
-       .modulemutexes = BIT(NVMODMUTEX_2D_FULL) | BIT(NVMODMUTEX_2D_SIMPLE) |
-                        BIT(NVMODMUTEX_2D_SB_A) | BIT(NVMODMUTEX_2D_SB_B),
-       .power         = power_2d,
-},
-{
-       /* channel 3 */
-       .name    = "isp",
-       .syncpts = 0,
-},
-{
-       /* channel 4 */
-       .name          = "vi",
-       .syncpts       = BIT(NVSYNCPT_CSI_VI_0) | BIT(NVSYNCPT_CSI_VI_1) |
-                        BIT(NVSYNCPT_VI_ISP_0) | BIT(NVSYNCPT_VI_ISP_1) |
-                        BIT(NVSYNCPT_VI_ISP_2) | BIT(NVSYNCPT_VI_ISP_3) |
-                        BIT(NVSYNCPT_VI_ISP_4),
-       .modulemutexes = BIT(NVMODMUTEX_VI),
-       .exclusive     = true,
-},
-{
-       /* channel 5 */
-       .name          = "mpe",
-       .syncpts       = BIT(NVSYNCPT_MPE) | BIT(NVSYNCPT_MPE_EBM_EOF) |
-                        BIT(NVSYNCPT_MPE_WR_SAFE),
-       .waitbases     = BIT(NVWAITBASE_MPE),
-       .class         = NV_VIDEO_ENCODE_MPEG_CLASS_ID,
-       .power         = power_mpe,
-       .exclusive     = true,
-       .keepalive     = true,
-},
-{
-       /* channel 6 */
-       .name          = "dsi",
-       .syncpts       = BIT(NVSYNCPT_DSI),
-       .modulemutexes = BIT(NVMODMUTEX_DSI),
-}};
-
-static inline void __iomem *channel_aperture(void __iomem *p, int ndx)
-{
-       ndx += NVHOST_CHANNEL_BASE;
-       p += NV_HOST1X_CHANNEL0_BASE;
-       p += ndx * NV_HOST1X_CHANNEL_MAP_SIZE_BYTES;
-       return p;
-}
-
-int __init nvhost_channel_init(struct nvhost_channel *ch,
-                       struct nvhost_master *dev, int index)
-{
-       BUILD_BUG_ON(NVHOST_NUMCHANNELS != ARRAY_SIZE(channelmap));
-
-       ch->dev = dev;
-       ch->desc = &channelmap[index];
-       ch->aperture = channel_aperture(dev->aperture, index);
-       mutex_init(&ch->reflock);
-       mutex_init(&ch->submitlock);
-
-       return nvhost_hwctx_handler_init(&ch->ctxhandler, ch->desc->name);
-}
 
 struct nvhost_channel *nvhost_getchannel(struct nvhost_channel *ch)
 {
@@ -152,6 +59,8 @@ struct nvhost_channel *nvhost_getchannel(struct nvhost_channel *ch)
 
 void nvhost_putchannel(struct nvhost_channel *ch, struct nvhost_hwctx *ctx)
 {
+       BUG_ON(!channel_cdma_op(ch).stop);
+
        if (ctx) {
                mutex_lock(&ch->submitlock);
                if (ch->cur_ctx == ctx)
@@ -167,7 +76,8 @@ void nvhost_putchannel(struct nvhost_channel *ch, struct nvhost_hwctx *ctx)
        if (ch->refcount == 1) {
                nvhost_module_deinit(&ch->mod);
                /* cdma may already be stopped, that's ok */
-               nvhost_cdma_stop(&ch->cdma);
+
+               channel_cdma_op(ch).stop(&ch->cdma);
                nvhost_cdma_deinit(&ch->cdma);
        }
        ch->refcount--;
@@ -178,211 +88,9 @@ void nvhost_channel_suspend(struct nvhost_channel *ch)
 {
        mutex_lock(&ch->reflock);
        BUG_ON(nvhost_module_powered(&ch->mod));
+       BUG_ON(!channel_cdma_op(ch).stop);
+
        if (ch->refcount)
-               nvhost_cdma_stop(&ch->cdma);
+               channel_cdma_op(ch).stop(&ch->cdma);
        mutex_unlock(&ch->reflock);
 }
-
-int nvhost_channel_submit(struct nvhost_channel *channel,
-                       struct nvhost_hwctx *hwctx,
-                       struct nvmap_client *user_nvmap,
-                       u32 *gather,
-                       u32 *gather_end,
-                       struct nvhost_waitchk *waitchk,
-                       struct nvhost_waitchk *waitchk_end,
-                       u32 waitchk_mask,
-                       struct nvmap_handle **unpins,
-                       int nr_unpins,
-                       u32 syncpt_id,
-                       u32 syncpt_incrs,
-                       u32 *syncpt_value,
-                       bool null_kickoff)
-{
-       struct nvhost_hwctx *hwctx_to_save = NULL;
-       u32 user_syncpt_incrs = syncpt_incrs;
-       bool need_restore = false;
-       u32 syncval;
-       int err;
-
-       /* keep module powered */
-       nvhost_module_busy(&channel->mod);
-
-       /* get submit lock */
-       err = mutex_lock_interruptible(&channel->submitlock);
-       if (err) {
-               nvhost_module_idle(&channel->mod);
-               return err;
-       }
-
-       /* remove stale waits */
-       if (waitchk != waitchk_end) {
-               err = nvhost_syncpt_wait_check(user_nvmap,
-                               &channel->dev->syncpt, waitchk_mask,
-                               waitchk, waitchk_end);
-               if (err) {
-                       dev_warn(&channel->dev->pdev->dev,
-                               "nvhost_syncpt_wait_check failed: %d\n", err);
-                       mutex_unlock(&channel->submitlock);
-                       nvhost_module_idle(&channel->mod);
-                       return err;
-               }
-       }
-
-       /* context switch */
-       if (channel->cur_ctx != hwctx) {
-               trace_nvhost_channel_context_switch(channel->desc->name,
-                 channel->cur_ctx, hwctx);
-               hwctx_to_save = channel->cur_ctx;
-               if (hwctx_to_save) {
-                       syncpt_incrs += hwctx_to_save->save_incrs;
-                       hwctx_to_save->valid = true;
-                       channel->ctxhandler.get(hwctx_to_save);
-               }
-               channel->cur_ctx = hwctx;
-               if (channel->cur_ctx && channel->cur_ctx->valid) {
-                       need_restore = true;
-                       syncpt_incrs += channel->cur_ctx->restore_incrs;
-               }
-       }
-
-       /* get absolute sync value */
-       if (BIT(syncpt_id) & NVSYNCPTS_CLIENT_MANAGED)
-               syncval = nvhost_syncpt_set_max(&channel->dev->syncpt,
-                                               syncpt_id, syncpt_incrs);
-       else
-               syncval = nvhost_syncpt_incr_max(&channel->dev->syncpt,
-                                               syncpt_id, syncpt_incrs);
-
-       /* begin a CDMA submit */
-       nvhost_cdma_begin(&channel->cdma);
-
-       /* push save buffer (pre-gather setup depends on unit) */
-       if (hwctx_to_save)
-               channel->ctxhandler.save_push(&channel->cdma, hwctx_to_save);
-
-       /* gather restore buffer */
-       if (need_restore)
-               nvhost_cdma_push(&channel->cdma,
-                       nvhost_opcode_gather(channel->cur_ctx->restore_size),
-                       channel->cur_ctx->restore_phys);
-
-       /* add a setclass for modules that require it (unless ctxsw added it) */
-       if (!hwctx_to_save && !need_restore && channel->desc->class)
-               nvhost_cdma_push(&channel->cdma,
-                       nvhost_opcode_setclass(channel->desc->class, 0, 0),
-                       NVHOST_OPCODE_NOOP);
-
-       if (null_kickoff) {
-               int incr;
-               u32 op_incr;
-
-               /* TODO ideally we'd also perform host waits here */
-
-               /* push increments that correspond to nulled out commands */
-               op_incr = nvhost_opcode_imm(0, 0x100 | syncpt_id);
-               for (incr = 0; incr < (user_syncpt_incrs >> 1); incr++)
-                       nvhost_cdma_push(&channel->cdma, op_incr, op_incr);
-               if (user_syncpt_incrs & 1)
-                       nvhost_cdma_push(&channel->cdma,
-                                       op_incr, NVHOST_OPCODE_NOOP);
-
-               /* for 3d, waitbase needs to be incremented after each submit */
-               if (channel->desc->class == NV_GRAPHICS_3D_CLASS_ID)
-                       nvhost_cdma_push(&channel->cdma,
-                                       nvhost_opcode_setclass(
-                                               NV_HOST1X_CLASS_ID,
-                                               NV_CLASS_HOST_INCR_SYNCPT_BASE,
-                                               1),
-                                       nvhost_class_host_incr_syncpt_base(
-                                               NVWAITBASE_3D,
-                                               user_syncpt_incrs));
-       }
-       else {
-               /* push user gathers */
-               for ( ; gather != gather_end; gather += 2)
-                       nvhost_cdma_push(&channel->cdma,
-                                       nvhost_opcode_gather(gather[0]),
-                                       gather[1]);
-       }
-
-       /* end CDMA submit & stash pinned hMems into sync queue */
-       nvhost_cdma_end(&channel->cdma, user_nvmap,
-                       syncpt_id, syncval, unpins, nr_unpins);
-
-       /*
-        * schedule a context save interrupt (to drain the host FIFO
-        * if necessary, and to release the restore buffer)
-        */
-       if (hwctx_to_save)
-               nvhost_intr_add_action(&channel->dev->intr, syncpt_id,
-                       syncval - syncpt_incrs + hwctx_to_save->save_thresh,
-                       NVHOST_INTR_ACTION_CTXSAVE, hwctx_to_save, NULL);
-
-       /* schedule a submit complete interrupt */
-       nvhost_intr_add_action(&channel->dev->intr, syncpt_id, syncval,
-                       NVHOST_INTR_ACTION_SUBMIT_COMPLETE, channel, NULL);
-
-       mutex_unlock(&channel->submitlock);
-
-       *syncpt_value = syncval;
-       return 0;
-}
-
-static void power_2d(struct nvhost_module *mod, enum nvhost_power_action action)
-{
-       /* TODO: [ahatala 2010-06-17] reimplement EPP hang war */
-       if (action == NVHOST_POWER_ACTION_OFF) {
-               /* TODO: [ahatala 2010-06-17] reset EPP */
-       }
-}
-
-static void power_3d(struct nvhost_module *mod, enum nvhost_power_action action)
-{
-       struct nvhost_channel *ch = container_of(mod, struct nvhost_channel, mod);
-       struct nvhost_hwctx *hwctx_to_save;
-       DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
-       u32 syncpt_incrs, syncpt_val;
-       void *ref;
-
-       if (action != NVHOST_POWER_ACTION_OFF)
-               return;
-
-       mutex_lock(&ch->submitlock);
-       hwctx_to_save = ch->cur_ctx;
-       if (!hwctx_to_save) {
-               mutex_unlock(&ch->submitlock);
-               return;
-       }
-
-       hwctx_to_save->valid = true;
-       ch->ctxhandler.get(hwctx_to_save);
-       ch->cur_ctx = NULL;
-
-       syncpt_incrs = hwctx_to_save->save_incrs;
-       syncpt_val = nvhost_syncpt_incr_max(&ch->dev->syncpt,
-                                       NVSYNCPT_3D, syncpt_incrs);
-
-       nvhost_cdma_begin(&ch->cdma);
-       ch->ctxhandler.save_push(&ch->cdma, hwctx_to_save);
-       nvhost_cdma_end(&ch->cdma, ch->dev->nvmap, NVSYNCPT_3D, syncpt_val, NULL, 0);
-
-       nvhost_intr_add_action(&ch->dev->intr, NVSYNCPT_3D,
-                       syncpt_val - syncpt_incrs + hwctx_to_save->save_thresh,
-                       NVHOST_INTR_ACTION_CTXSAVE, hwctx_to_save, NULL);
-
-       nvhost_intr_add_action(&ch->dev->intr, NVSYNCPT_3D, syncpt_val,
-                       NVHOST_INTR_ACTION_WAKEUP, &wq, &ref);
-       wait_event(wq,
-               nvhost_syncpt_min_cmp(&ch->dev->syncpt,
-                               NVSYNCPT_3D, syncpt_val));
-
-       nvhost_intr_put_ref(&ch->dev->intr, ref);
-
-       nvhost_cdma_update(&ch->cdma);
-
-       mutex_unlock(&ch->submitlock);
-}
-
-static void power_mpe(struct nvhost_module *mod, enum nvhost_power_action action)
-{
-}
index b1515c4..2afd65d 100644 (file)
@@ -30,8 +30,6 @@
 #include <linux/cdev.h>
 #include <linux/io.h>
 
-#define NVHOST_CHANNEL_BASE 0
-#define NVHOST_NUMCHANNELS (NV_HOST1X_CHANNELS - 1)
 #define NVHOST_MAX_WAIT_CHECKS 256
 #define NVHOST_MAX_GATHERS 512
 #define NVHOST_MAX_HANDLES 1280
@@ -98,4 +96,7 @@ struct nvhost_channel *nvhost_getchannel(struct nvhost_channel *ch);
 void nvhost_putchannel(struct nvhost_channel *ch, struct nvhost_hwctx *ctx);
 void nvhost_channel_suspend(struct nvhost_channel *ch);
 
+#define channel_cdma_op(ch) (ch->dev->op.cdma)
+#define channel_op(ch) (ch->dev->op.channel)
+#define host_channel_op(host) (host->op.channel)
 #endif
index 4a5c34d..dd585fb 100644 (file)
 #include "dev.h"
 #include <linux/string.h>
 
-#define cpuaccess_to_dev(ctx) container_of(ctx, struct nvhost_master, cpuaccess)
-
 int nvhost_cpuaccess_init(struct nvhost_cpuaccess *ctx,
                        struct platform_device *pdev)
 {
+       struct nvhost_master *host = cpuaccess_to_dev(ctx);
        int i;
-       for (i = 0; i < NVHOST_MODULE_NUM; i++) {
+
+       for (i = 0; i < host->nb_modules; i++) {
                struct resource *mem;
                mem = platform_get_resource(pdev, IORESOURCE_MEM, i+1);
                if (!mem) {
                        dev_err(&pdev->dev, "missing module memory resource\n");
                        return -ENXIO;
                }
-
+               ctx->reg_mem[i] = mem;
                ctx->regs[i] = ioremap(mem->start, resource_size(mem));
                if (!ctx->regs[i]) {
                        dev_err(&pdev->dev, "failed to map module registers\n");
@@ -50,8 +50,10 @@ int nvhost_cpuaccess_init(struct nvhost_cpuaccess *ctx,
 
 void nvhost_cpuaccess_deinit(struct nvhost_cpuaccess *ctx)
 {
+       struct nvhost_master *host = cpuaccess_to_dev(ctx);
        int i;
-       for (i = 0; i < NVHOST_MODULE_NUM; i++) {
+
+       for (i = 0; i < host->nb_modules; i++) {
                iounmap(ctx->regs[i]);
                release_resource(ctx->reg_mem[i]);
        }
@@ -60,13 +62,11 @@ void nvhost_cpuaccess_deinit(struct nvhost_cpuaccess *ctx)
 int nvhost_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;
        u32 reg;
+       BUG_ON(!cpuaccess_op(ctx).mutex_try_lock);
 
-       /* mlock registers returns 0 when the lock is aquired.
-        * writing 0 clears the lock. */
        nvhost_module_busy(&dev->mod);
-       reg = readl(sync_regs + (HOST1X_SYNC_MLOCK_0 + idx * 4));
+       reg = cpuaccess_op(ctx).mutex_try_lock(ctx, idx);
        if (reg) {
                nvhost_module_idle(&dev->mod);
                return -ERESTARTSYS;
@@ -78,8 +78,9 @@ int nvhost_mutex_try_lock(struct nvhost_cpuaccess *ctx, unsigned int idx)
 void nvhost_mutex_unlock(struct nvhost_cpuaccess *ctx, unsigned int idx)
 {
        struct nvhost_master *dev = cpuaccess_to_dev(ctx);
-       void __iomem *sync_regs = dev->sync_aperture;
-       writel(0, sync_regs + (HOST1X_SYNC_MLOCK_0 + idx * 4));
+       BUG_ON(!cpuaccess_op(ctx).mutex_unlock);
+
+       cpuaccess_op(ctx).mutex_unlock(ctx, idx);
        nvhost_module_idle(&dev->mod);
        atomic_dec(&ctx->lock_counts[idx]);
 }
index 98ea1e1..2e210b7 100644 (file)
@@ -23,7 +23,6 @@
 #ifndef __NVHOST_CPUACCESS_H
 #define __NVHOST_CPUACCESS_H
 
-#include "nvhost_hardware.h"
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
@@ -43,26 +42,20 @@ enum nvhost_module_id {
 };
 
 struct nvhost_cpuaccess {
-       struct resource *reg_mem[NVHOST_MODULE_NUM];
-       void __iomem *regs[NVHOST_MODULE_NUM];
-       atomic_t lock_counts[NV_HOST1X_SYNC_MLOCK_NUM];
+       struct resource **reg_mem;
+       void __iomem **regs;
+       atomic_t *lock_counts;
 };
 
+#define cpuaccess_to_dev(ctx) container_of(ctx, struct nvhost_master, cpuaccess)
+#define cpuaccess_op(ctx) (cpuaccess_to_dev(ctx)->op.cpuaccess)
 int nvhost_cpuaccess_init(struct nvhost_cpuaccess *ctx,
                        struct platform_device *pdev);
 
-void nvhost_cpuaccess_deinit(struct nvhost_cpuaccess *ctx);
-
 int nvhost_mutex_try_lock(struct nvhost_cpuaccess *ctx, unsigned int idx);
 
 void nvhost_mutex_unlock(struct nvhost_cpuaccess *ctx, unsigned int idx);
 
-static inline bool nvhost_access_module_regs(
-       struct nvhost_cpuaccess *ctx, u32 module)
-{
-       return (module < NVHOST_MODULE_NUM);
-}
-
 void nvhost_read_module_regs(struct nvhost_cpuaccess *ctx, u32 module,
                        u32 offset, size_t size, void *values);
 
index 67c3c7f..83d93bd 100644 (file)
@@ -57,20 +57,6 @@ struct nvhost_hwctx_handler {
        void (*save_service) (struct nvhost_hwctx *ctx);
 };
 
-int nvhost_3dctx_handler_init(struct nvhost_hwctx_handler *h);
-int nvhost_mpectx_handler_init(struct nvhost_hwctx_handler *h);
-
-static inline int nvhost_hwctx_handler_init(
-       struct nvhost_hwctx_handler *h,
-       const char *module)
-{
-       if (strcmp(module, "gr3d") == 0)
-               return nvhost_3dctx_handler_init(h);
-       else if (strcmp(module, "mpe") == 0)
-               return nvhost_mpectx_handler_init(h);
-
-       return 0;
-}
 
 struct hwctx_reginfo {
        unsigned int offset:12;
index 729a0e3..ef51139 100644 (file)
 #include <linux/slab.h>
 #include <linux/irq.h>
 
-#define intr_to_dev(x) container_of(x, struct nvhost_master, intr)
 
 
-/*** HW host sync management ***/
-
-void init_host_sync(void __iomem *sync_regs)
-{
-       /* 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);
-
-       /* increase the auto-ack timout to the maximum value. 2d will hang
-        * otherwise on ap20.
-        */
-       writel(0xff, sync_regs + HOST1X_SYNC_CTXSW_TIMEOUT_CFG);
-}
-
-void set_host_clocks_per_microsecond(void __iomem *sync_regs, u32 cpm)
-{
-       /* write microsecond clock register */
-       writel(cpm, sync_regs + HOST1X_SYNC_USEC_CLK);
-}
-
-static void set_syncpt_threshold(void __iomem *sync_regs, u32 id, u32 thresh)
-{
-       thresh &= 0xffff;
-       writel(thresh, sync_regs + (HOST1X_SYNC_SYNCPT_INT_THRESH_0 + id * 4));
-}
-
-static void enable_syncpt_interrupt(void __iomem *sync_regs, u32 id)
-{
-       writel(BIT(id), sync_regs + HOST1X_SYNC_SYNCPT_THRESH_INT_ENABLE_CPU0);
-}
-
-void disable_all_syncpt_interrupts(void __iomem *sync_regs)
-{
-       /* disable interrupts for both cpu's */
-       writel(0, sync_regs + HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE);
-
-       /* clear status for both cpu's */
-       writel(0xfffffffful, sync_regs +
-               HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS);
-       writel(0xfffffffful, sync_regs +
-               HOST1X_SYNC_SYNCPT_THRESH_CPU1_INT_STATUS);
-}
 
 
 /*** Wait list management ***/
@@ -156,14 +112,17 @@ static void remove_completed_waiters(struct list_head *head, u32 sync,
        }
 }
 
-void reset_threshold_interrupt(struct list_head *head,
-               unsigned int id, void __iomem *sync_regs)
+void reset_threshold_interrupt(struct nvhost_intr *intr,
+                              struct list_head *head,
+                              unsigned int id)
 {
        u32 thresh = list_first_entry(head,
                                struct nvhost_waitlist, list)->thresh;
+       BUG_ON(!(intr_op(intr).set_syncpt_threshold &&
+                intr_op(intr).enable_syncpt_intr));
 
-       set_syncpt_threshold(sync_regs, id, thresh);
-       enable_syncpt_interrupt(sync_regs, id);
+       intr_op(intr).set_syncpt_threshold(intr, id, thresh);
+       intr_op(intr).enable_syncpt_intr(intr, id);
 }
 
 
@@ -230,8 +189,9 @@ static void run_handlers(struct list_head completed[NVHOST_INTR_ACTION_COUNT])
 /**
  * Remove & handle all waiters that have completed for the given syncpt
  */
-static int process_wait_list(struct nvhost_intr_syncpt *syncpt,
-               u32 threshold, void __iomem *sync_regs)
+static int process_wait_list(struct nvhost_intr *intr,
+                            struct nvhost_intr_syncpt *syncpt,
+                            u32 threshold)
 {
        struct list_head completed[NVHOST_INTR_ACTION_COUNT];
        unsigned int i;
@@ -246,8 +206,8 @@ static int process_wait_list(struct nvhost_intr_syncpt *syncpt,
 
        empty = list_empty(&syncpt->wait_head);
        if (!empty)
-               reset_threshold_interrupt(&syncpt->wait_head,
-                                       syncpt->id, sync_regs);
+               reset_threshold_interrupt(intr, &syncpt->wait_head,
+                                         syncpt->id);
 
        spin_unlock(&syncpt->lock);
 
@@ -256,29 +216,7 @@ static int process_wait_list(struct nvhost_intr_syncpt *syncpt,
        return empty;
 }
 
-
 /*** host syncpt interrupt service functions ***/
-
-/**
- * Sync point threshold interrupt service function
- * Handles sync point threshold triggers, in interrupt context
- */
-static irqreturn_t syncpt_thresh_isr(int irq, void *dev_id)
-{
-       struct nvhost_intr_syncpt *syncpt = dev_id;
-       unsigned int id = syncpt->id;
-       struct nvhost_intr *intr = container_of(syncpt, struct nvhost_intr,
-                                               syncpt[id]);
-       void __iomem *sync_regs = intr_to_dev(intr)->sync_aperture;
-
-       writel(BIT(id),
-               sync_regs + HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE);
-       writel(BIT(id),
-               sync_regs + HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS);
-
-       return IRQ_WAKE_THREAD;
-}
-
 /**
  * Sync point threshold interrupt service thread function
  * Handles sync point threshold triggers, in thread context
@@ -287,13 +225,11 @@ static irqreturn_t syncpt_thresh_fn(int irq, void *dev_id)
 {
        struct nvhost_intr_syncpt *syncpt = dev_id;
        unsigned int id = syncpt->id;
-       struct nvhost_intr *intr = container_of(syncpt, struct nvhost_intr,
-                                               syncpt[id]);
+       struct nvhost_intr *intr = intr_syncpt_to_intr(syncpt);
        struct nvhost_master *dev = intr_to_dev(intr);
 
-       (void)process_wait_list(syncpt,
-                       nvhost_syncpt_update_min(&dev->syncpt, id),
-                       dev->sync_aperture);
+       (void)process_wait_list(intr, syncpt,
+                               nvhost_syncpt_update_min(&dev->syncpt, id));
 
        return IRQ_HANDLED;
 }
@@ -304,12 +240,12 @@ static irqreturn_t syncpt_thresh_fn(int irq, void *dev_id)
 static int request_syncpt_irq(struct nvhost_intr_syncpt *syncpt)
 {
        int err;
-
+       extern irqreturn_t t20_intr_syncpt_thresh_isr(int irq, void *dev_id);
        if (syncpt->irq_requested)
                return 0;
 
        err = request_threaded_irq(syncpt->irq,
-                               syncpt_thresh_isr, syncpt_thresh_fn,
+                               t20_intr_syncpt_thresh_isr, syncpt_thresh_fn,
                                0, syncpt->thresh_irq_name, syncpt);
        if (err)
                return err;
@@ -332,87 +268,6 @@ static void free_syncpt_irq(struct nvhost_intr_syncpt *syncpt)
 
 /*** host general interrupt service functions ***/
 
-/**
- * Host general interrupt service function
- * Handles read / write failures
- */
-static irqreturn_t 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;
-
-       stat = readl(sync_regs + HOST1X_SYNC_HINTSTATUS);
-       ext_stat = readl(sync_regs + HOST1X_SYNC_HINTSTATUS_EXT);
-
-       if (nvhost_sync_hintstatus_ext_ip_read_int(ext_stat)) {
-               addr = readl(sync_regs + HOST1X_SYNC_IP_READ_TIMEOUT_ADDR);
-               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);
-               pr_err("Host write timeout at address %x\n", addr);
-       }
-
-       writel(ext_stat, sync_regs + HOST1X_SYNC_HINTSTATUS_EXT);
-       writel(stat, sync_regs + HOST1X_SYNC_HINTSTATUS);
-
-       return IRQ_HANDLED;
-}
-
-static int request_host_general_irq(struct nvhost_intr *intr)
-{
-       void __iomem *sync_regs = intr_to_dev(intr)->sync_aperture;
-       int err;
-
-       if (intr->host_general_irq_requested)
-               return 0;
-
-       /* master disable for general (not syncpt) host interrupts */
-       writel(0, sync_regs + HOST1X_SYNC_INTMASK);
-
-       /* clear status & extstatus */
-       writel(0xfffffffful, sync_regs + HOST1X_SYNC_HINTSTATUS_EXT);
-       writel(0xfffffffful, sync_regs + HOST1X_SYNC_HINTSTATUS);
-
-       err = request_irq(intr->host_general_irq, 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);
-
-       /* enable extra interrupt sources */
-       writel(BIT(31), sync_regs + HOST1X_SYNC_HINTMASK);
-
-       /* enable host module interrupt to CPU0 */
-       writel(BIT(0), sync_regs + HOST1X_SYNC_INTC0MASK);
-
-       /* master enable for general (not syncpt) host interrupts */
-       writel(BIT(0), sync_regs + HOST1X_SYNC_INTMASK);
-
-       intr->host_general_irq_requested = true;
-
-       return err;
-}
-
-static void free_host_general_irq(struct nvhost_intr *intr)
-{
-       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);
-
-               free_irq(intr->host_general_irq, intr);
-               intr->host_general_irq_requested = false;
-       }
-}
-
 
 /*** Main API ***/
 
@@ -422,10 +277,12 @@ int nvhost_intr_add_action(struct nvhost_intr *intr, u32 id, u32 thresh,
 {
        struct nvhost_waitlist *waiter;
        struct nvhost_intr_syncpt *syncpt;
-       void __iomem *sync_regs;
        int queue_was_empty;
        int err;
 
+       BUG_ON(!(intr_op(intr).set_syncpt_threshold &&
+                intr_op(intr).enable_syncpt_intr));
+
        /* create and initialize a new waiter */
        waiter = kmalloc(sizeof(*waiter), GFP_KERNEL);
        if (!waiter)
@@ -440,9 +297,8 @@ int nvhost_intr_add_action(struct nvhost_intr *intr, u32 id, u32 thresh,
        waiter->data = data;
        waiter->count = 1;
 
-       BUG_ON(id >= NV_HOST1X_SYNCPT_NB_PTS);
+       BUG_ON(id >= intr_to_dev(intr)->syncpt.nb_pts);
        syncpt = intr->syncpt + id;
-       sync_regs = intr_to_dev(intr)->sync_aperture;
 
        spin_lock(&syncpt->lock);
 
@@ -466,11 +322,11 @@ int nvhost_intr_add_action(struct nvhost_intr *intr, u32 id, u32 thresh,
 
        if (add_waiter_to_queue(waiter, &syncpt->wait_head)) {
                /* added at head of list - new threshold value */
-               set_syncpt_threshold(sync_regs, id, thresh);
+               intr_op(intr).set_syncpt_threshold(intr, id, thresh);
 
                /* added as first waiter - enable interrupt */
                if (queue_was_empty)
-                       enable_syncpt_interrupt(sync_regs, id);
+                       intr_op(intr).enable_syncpt_intr(intr, id);
        }
 
        spin_unlock(&syncpt->lock);
@@ -498,14 +354,18 @@ int nvhost_intr_init(struct nvhost_intr *intr, u32 irq_gen, u32 irq_sync)
 {
        unsigned int id;
        struct nvhost_intr_syncpt *syncpt;
+       struct nvhost_master *host =
+               container_of(intr, struct nvhost_master, intr);
+       u32 nb_pts = host->syncpt.nb_pts;
 
        mutex_init(&intr->mutex);
        intr->host_general_irq = irq_gen;
        intr->host_general_irq_requested = false;
 
        for (id = 0, syncpt = intr->syncpt;
-            id < NV_HOST1X_SYNCPT_NB_PTS;
+            id < nb_pts;
             ++id, ++syncpt) {
+               syncpt->intr = &host->intr;
                syncpt->id = id;
                syncpt->irq = irq_sync + id;
                syncpt->irq_requested = 0;
@@ -526,31 +386,36 @@ void nvhost_intr_deinit(struct nvhost_intr *intr)
 
 void nvhost_intr_start(struct nvhost_intr *intr, u32 hz)
 {
-       struct nvhost_master *dev = intr_to_dev(intr);
-       void __iomem *sync_regs = dev->sync_aperture;
+       BUG_ON(!(intr_op(intr).init_host_sync &&
+                intr_op(intr).set_host_clocks_per_usec &&
+                intr_op(intr).request_host_general_irq));
 
        mutex_lock(&intr->mutex);
 
-       init_host_sync(sync_regs);
-       set_host_clocks_per_microsecond(sync_regs, (hz + 1000000 - 1)/1000000);
+       intr_op(intr).init_host_sync(intr);
+       intr_op(intr).set_host_clocks_per_usec(intr,
+                                              (hz + 1000000 - 1)/1000000);
 
-       request_host_general_irq(intr);
+       intr_op(intr).request_host_general_irq(intr);
 
        mutex_unlock(&intr->mutex);
 }
 
 void nvhost_intr_stop(struct nvhost_intr *intr)
 {
-       void __iomem *sync_regs = intr_to_dev(intr)->sync_aperture;
        unsigned int id;
        struct nvhost_intr_syncpt *syncpt;
+       u32 nb_pts = intr_to_dev(intr)->syncpt.nb_pts;
+
+       BUG_ON(!(intr_op(intr).disable_all_syncpt_intrs &&
+                intr_op(intr).free_host_general_irq));
 
        mutex_lock(&intr->mutex);
 
-       disable_all_syncpt_interrupts(sync_regs);
+       intr_op(intr).disable_all_syncpt_intrs(intr);
 
        for (id = 0, syncpt = intr->syncpt;
-            id < NV_HOST1X_SYNCPT_NB_PTS;
+            id < nb_pts;
             ++id, ++syncpt) {
                struct nvhost_waitlist *waiter, *next;
                list_for_each_entry_safe(waiter, next, &syncpt->wait_head, list) {
@@ -569,7 +434,7 @@ void nvhost_intr_stop(struct nvhost_intr *intr)
                free_syncpt_irq(syncpt);
        }
 
-       free_host_general_irq(intr);
+       intr_op(intr).free_host_general_irq(intr);
 
        mutex_unlock(&intr->mutex);
 }
index fb3e613..150fd6c 100644 (file)
@@ -26,8 +26,6 @@
 #include <linux/kthread.h>
 #include <linux/semaphore.h>
 
-#include "nvhost_hardware.h"
-
 struct nvhost_channel;
 
 enum nvhost_intr_action {
@@ -58,7 +56,10 @@ enum nvhost_intr_action {
        NVHOST_INTR_ACTION_COUNT
 };
 
+struct nvhost_intr;
+
 struct nvhost_intr_syncpt {
+       struct  nvhost_intr *intr;
        u8 id;
        u8 irq_requested;
        u16 irq;
@@ -68,11 +69,14 @@ struct nvhost_intr_syncpt {
 };
 
 struct nvhost_intr {
-       struct nvhost_intr_syncpt syncpt[NV_HOST1X_SYNCPT_NB_PTS];
+       struct nvhost_intr_syncpt *syncpt;
        struct mutex mutex;
        int host_general_irq;
        bool host_general_irq_requested;
 };
+#define intr_to_dev(x) container_of(x, struct nvhost_master, intr)
+#define intr_op(intr) (intr_to_dev(intr)->op.intr)
+#define intr_syncpt_to_intr(is) is->intr
 
 /**
  * Schedule an action to be taken when a sync point reaches the given threshold.
index 9420308..88059b0 100644 (file)
 #include "nvhost_syncpt.h"
 #include "dev.h"
 
-#define client_managed(id) (BIT(id) & NVSYNCPTS_CLIENT_MANAGED)
-#define syncpt_to_dev(sp) container_of(sp, struct nvhost_master, syncpt)
-#define SYNCPT_CHECK_PERIOD 2*HZ
-
-static bool check_max(struct nvhost_syncpt *sp, u32 id, u32 real)
-{
-       u32 max;
-       if (client_managed(id))
-               return true;
-       smp_rmb();
-       max = (u32)atomic_read(&sp->max_val[id]);
-       return ((s32)(max - real) >= 0);
-}
-
-/**
- * Write the current syncpoint value back to hw.
- */
-static void reset_syncpt(struct nvhost_syncpt *sp, u32 id)
-{
-       struct nvhost_master *dev = syncpt_to_dev(sp);
-       int min;
-       smp_rmb();
-       min = atomic_read(&sp->min_val[id]);
-       writel(min, dev->sync_aperture + (HOST1X_SYNC_SYNCPT_0 + id * 4));
-}
-
-/**
- * Write the current waitbase value back to hw.
- */
-static void reset_syncpt_wait_base(struct nvhost_syncpt *sp, u32 id)
-{
-       struct nvhost_master *dev = syncpt_to_dev(sp);
-       writel(sp->base_val[id],
-               dev->sync_aperture + (HOST1X_SYNC_SYNCPT_BASE_0 + id * 4));
-}
-
-/**
- * Read waitbase value from hw.
- */
-static void read_syncpt_wait_base(struct nvhost_syncpt *sp, u32 id)
-{
-       struct nvhost_master *dev = syncpt_to_dev(sp);
-       sp->base_val[id] = readl(dev->sync_aperture +
-                               (HOST1X_SYNC_SYNCPT_BASE_0 + id * 4));
-}
 
 /**
  * Resets syncpoint and waitbase values to sw shadows
@@ -75,10 +30,12 @@ static void read_syncpt_wait_base(struct nvhost_syncpt *sp, u32 id)
 void nvhost_syncpt_reset(struct nvhost_syncpt *sp)
 {
        u32 i;
-       for (i = 0; i < NV_HOST1X_SYNCPT_NB_PTS; i++)
-               reset_syncpt(sp, i);
-       for (i = 0; i < NV_HOST1X_SYNCPT_NB_BASES; i++)
-               reset_syncpt_wait_base(sp, i);
+       BUG_ON(!(syncpt_op(sp).reset && syncpt_op(sp).reset_wait_base));
+
+       for (i = 0; i < sp->nb_pts; i++)
+               syncpt_op(sp).reset(sp, i);
+       for (i = 0; i < sp->nb_bases; i++)
+               syncpt_op(sp).reset_wait_base(sp, i);
        wmb();
 }
 
@@ -88,16 +45,17 @@ void nvhost_syncpt_reset(struct nvhost_syncpt *sp)
 void nvhost_syncpt_save(struct nvhost_syncpt *sp)
 {
        u32 i;
+       BUG_ON(!(syncpt_op(sp).update_min && syncpt_op(sp).read_wait_base));
 
-       for (i = 0; i < NV_HOST1X_SYNCPT_NB_PTS; i++) {
+       for (i = 0; i < sp->nb_pts; i++) {
                if (client_managed(i))
-                       nvhost_syncpt_update_min(sp, i);
+                       syncpt_op(sp).update_min(sp, i);
                else
                        BUG_ON(!nvhost_syncpt_min_eq_max(sp, i));
        }
 
-       for (i = 0; i < NV_HOST1X_SYNCPT_NB_BASES; i++)
-               read_syncpt_wait_base(sp, i);
+       for (i = 0; i < sp->nb_bases; i++)
+               syncpt_op(sp).read_wait_base(sp, i);
 }
 
 /**
@@ -105,19 +63,9 @@ void nvhost_syncpt_save(struct nvhost_syncpt *sp)
  */
 u32 nvhost_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;
-
-       do {
-               smp_rmb();
-               old = (u32)atomic_read(&sp->min_val[id]);
-               live = readl(sync_regs + (HOST1X_SYNC_SYNCPT_0 + id * 4));
-       } while ((u32)atomic_cmpxchg(&sp->min_val[id], old, live) != old);
-
-       BUG_ON(!check_max(sp, id, live));
+       BUG_ON(!syncpt_op(sp).update_min);
 
-       return live;
+       return syncpt_op(sp).update_min(sp, id);
 }
 
 /**
@@ -126,9 +74,9 @@ u32 nvhost_syncpt_update_min(struct nvhost_syncpt *sp, u32 id)
 u32 nvhost_syncpt_read(struct nvhost_syncpt *sp, u32 id)
 {
        u32 val;
-
+       BUG_ON(!syncpt_op(sp).update_min);
        nvhost_module_busy(&syncpt_to_dev(sp)->mod);
-       val = nvhost_syncpt_update_min(sp, id);
+       val = syncpt_op(sp).update_min(sp, id);
        nvhost_module_idle(&syncpt_to_dev(sp)->mod);
        return val;
 }
@@ -139,11 +87,8 @@ u32 nvhost_syncpt_read(struct nvhost_syncpt *sp, u32 id)
  */
 void nvhost_syncpt_cpu_incr(struct nvhost_syncpt *sp, u32 id)
 {
-       struct nvhost_master *dev = syncpt_to_dev(sp);
-       BUG_ON(!nvhost_module_powered(&dev->mod));
-       BUG_ON(!client_managed(id) && nvhost_syncpt_min_eq_max(sp, id));
-       writel(BIT(id), dev->sync_aperture + HOST1X_SYNC_SYNCPT_CPU_INCR);
-       wmb();
+       BUG_ON(!syncpt_op(sp).cpu_incr);
+       syncpt_op(sp).cpu_incr(sp, id);
 }
 
 /**
@@ -169,8 +114,8 @@ int nvhost_syncpt_wait_timeout(struct nvhost_syncpt *sp, u32 id,
 
        if (value)
                *value = 0;
-
-       BUG_ON(!check_max(sp, id, thresh));
+       BUG_ON(!syncpt_op(sp).update_min);
+       BUG_ON(!nvhost_syncpt_check_max(sp, id, thresh));
 
        /* first check cache */
        if (nvhost_syncpt_min_cmp(sp, id, thresh)) {
@@ -184,7 +129,7 @@ int nvhost_syncpt_wait_timeout(struct nvhost_syncpt *sp, u32 id,
 
        if (client_managed(id) || !nvhost_syncpt_min_eq_max(sp, id)) {
                /* try to read from register */
-               u32 val = nvhost_syncpt_update_min(sp, id);
+               u32 val = syncpt_op(sp).update_min(sp, id);
                if ((s32)(val - thresh) >= 0) {
                        if (value)
                                *value = val;
@@ -225,8 +170,8 @@ int nvhost_syncpt_wait_timeout(struct nvhost_syncpt *sp, u32 id,
                if (timeout) {
                        dev_warn(&syncpt_to_dev(sp)->pdev->dev,
                                "syncpoint id %d (%s) stuck waiting %d\n",
-                               id, nvhost_syncpt_name(id), thresh);
-                       nvhost_syncpt_debug(sp);
+                                id, syncpt_op(sp).name(sp, id), thresh);
+                       syncpt_op(sp).debug(sp);
                }
        }
        nvhost_intr_put_ref(&(syncpt_to_dev(sp)->intr), ref);
@@ -236,98 +181,17 @@ done:
        return err;
 }
 
-static const char *s_syncpt_names[32] = {
-       "gfx_host", "", "", "", "", "", "", "", "", "", "",
-       "csi_vi_0", "csi_vi_1", "vi_isp_0", "vi_isp_1", "vi_isp_2", "vi_isp_3", "vi_isp_4",
-       "2d_0", "2d_1",
-       "", "",
-       "3d", "mpe", "disp0", "disp1", "vblank0", "vblank1", "mpe_ebm_eof", "mpe_wr_safe",
-       "2d_tinyblt", "dsi"
-};
-
-const char *nvhost_syncpt_name(u32 id)
-{
-       BUG_ON(id > ARRAY_SIZE(s_syncpt_names));
-       return s_syncpt_names[id];
-}
-
 void nvhost_syncpt_debug(struct nvhost_syncpt *sp)
 {
-       u32 i;
-       for (i = 0; i < NV_HOST1X_SYNCPT_NB_PTS; i++) {
-               u32 max = nvhost_syncpt_read_max(sp, i);
-               if (!max)
-                       continue;
-               dev_info(&syncpt_to_dev(sp)->pdev->dev,
-                       "id %d (%s) min %d max %d\n",
-                       i, nvhost_syncpt_name(i),
-                       nvhost_syncpt_update_min(sp, i), max);
-
-       }
-}
-
-/* returns true, if a <= b < c using wrapping comparison */
-static inline bool nvhost_syncpt_is_between(u32 a, u32 b, u32 c)
-{
-       return b-a < c-a;
-}
-
-/* returns true, if syncpt >= threshold (mod 1 << 32) */
-static bool nvhost_syncpt_wrapping_comparison(u32 syncpt, u32 threshold)
-{
-       return nvhost_syncpt_is_between(threshold, syncpt,
-                                       (1UL<<31UL)+threshold);
+       syncpt_op(sp).debug(sp);
 }
 
 /* check for old WAITs to be removed (avoiding a wrap) */
-int nvhost_syncpt_wait_check(struct nvmap_client *nvmap,
-                       struct nvhost_syncpt *sp, u32 waitchk_mask,
-                       struct nvhost_waitchk *wait,
-                       struct nvhost_waitchk *waitend)
+int nvhost_syncpt_wait_check(struct nvhost_syncpt *sp,
+                            struct nvmap_client *nvmap,
+                            u32 waitchk_mask,
+                            struct nvhost_waitchk *wait,
+                            struct nvhost_waitchk *waitend)
 {
-       u32 idx;
-       int err = 0;
-
-       /* get current syncpt values */
-       for (idx = 0; idx < NV_HOST1X_SYNCPT_NB_PTS; idx++) {
-               if (BIT(idx) & waitchk_mask)
-                       nvhost_syncpt_update_min(sp, idx);
-       }
-
-       BUG_ON(!wait && !waitend);
-
-       /* compare syncpt vs wait threshold */
-       while (wait != waitend) {
-               u32 syncpt, override;
-
-               BUG_ON(wait->syncpt_id > NV_HOST1X_SYNCPT_NB_PTS);
-
-               syncpt = atomic_read(&sp->min_val[wait->syncpt_id]);
-               if (nvhost_syncpt_wrapping_comparison(syncpt, wait->thresh)) {
-                       /*
-                        * NULL an already satisfied WAIT_SYNCPT host method,
-                        * by patching its args in the command stream. The
-                        * method data is changed to reference a reserved
-                        * (never given out or incr) NVSYNCPT_GRAPHICS_HOST
-                        * syncpt with a matching threshold value of 0, so
-                        * is guaranteed to be popped by the host HW.
-                        */
-                       dev_dbg(&syncpt_to_dev(sp)->pdev->dev,
-                           "drop WAIT id %d (%s) thresh 0x%x, syncpt 0x%x\n",
-                           wait->syncpt_id,
-                           nvhost_syncpt_name(wait->syncpt_id),
-                           wait->thresh, syncpt);
-
-                       /* patch the wait */
-                       override = nvhost_class_host_wait_syncpt(
-                                       NVSYNCPT_GRAPHICS_HOST, 0);
-                       err = nvmap_patch_word(nvmap,
-                                       (struct nvmap_handle *)wait->mem,
-                                       wait->offset, override);
-                       if (err)
-                               break;
-               }
-               wait++;
-       }
-       return err;
+       return syncpt_op(sp).wait_check(sp, nvmap, waitchk_mask, wait, waitend);
 }
index 564cc83..b6db72e 100644 (file)
 #include <mach/nvmap.h>
 #include <asm/atomic.h>
 
-#include "nvhost_hardware.h"
-
+/* host managed and invalid syncpt id */
 #define NVSYNCPT_GRAPHICS_HOST              (0)
-#define NVSYNCPT_CSI_VI_0                   (11)
-#define NVSYNCPT_CSI_VI_1                   (12)
-#define NVSYNCPT_VI_ISP_0                   (13)
-#define NVSYNCPT_VI_ISP_1                   (14)
-#define NVSYNCPT_VI_ISP_2                   (15)
-#define NVSYNCPT_VI_ISP_3                   (16)
-#define NVSYNCPT_VI_ISP_4                   (17)
-#define NVSYNCPT_2D_0                       (18)
-#define NVSYNCPT_2D_1                       (19)
-#define NVSYNCPT_3D                         (22)
-#define NVSYNCPT_MPE                        (23)
-#define NVSYNCPT_DISP0                      (24)
-#define NVSYNCPT_DISP1                      (25)
-#define NVSYNCPT_VBLANK0                    (26)
-#define NVSYNCPT_VBLANK1                    (27)
-#define NVSYNCPT_MPE_EBM_EOF                (28)
-#define NVSYNCPT_MPE_WR_SAFE                (29)
-#define NVSYNCPT_DSI                        (31)
 #define NVSYNCPT_INVALID                    (-1)
 
-/*#define NVSYNCPT_2D_CHANNEL2_0    (20) */
-/*#define NVSYNCPT_2D_CHANNEL2_1    (21) */
-/*#define NVSYNCPT_2D_TINYBLT_WAR                   (30)*/
-/*#define NVSYNCPT_2D_TINYBLT_RESTORE_CLASS_ID (30)*/
-
-/* sync points that are wholly managed by the client */
-#define NVSYNCPTS_CLIENT_MANAGED ( \
-       BIT(NVSYNCPT_DISP0) | BIT(NVSYNCPT_DISP1) | BIT(NVSYNCPT_DSI) | \
-       BIT(NVSYNCPT_CSI_VI_0) | BIT(NVSYNCPT_CSI_VI_1) | \
-       BIT(NVSYNCPT_VI_ISP_1) | BIT(NVSYNCPT_VI_ISP_2) | \
-       BIT(NVSYNCPT_VI_ISP_3) | BIT(NVSYNCPT_VI_ISP_4) | \
-       BIT(NVSYNCPT_MPE_EBM_EOF) | BIT(NVSYNCPT_MPE_WR_SAFE) | \
-       BIT(NVSYNCPT_2D_1))
-
-#define NVWAITBASE_2D_0 (1)
-#define NVWAITBASE_2D_1 (2)
-#define NVWAITBASE_3D   (3)
-#define NVWAITBASE_MPE  (4)
-
 struct nvhost_syncpt {
-       atomic_t min_val[NV_HOST1X_SYNCPT_NB_PTS];
-       atomic_t max_val[NV_HOST1X_SYNCPT_NB_PTS];
-       u32 base_val[NV_HOST1X_SYNCPT_NB_BASES];
+       atomic_t *min_val;
+       atomic_t *max_val;
+       u32 *base_val;
+       u32 nb_pts;
+       u32 nb_bases;
+       u32 client_managed;
 };
 
+int nvhost_syncpt_init(struct nvhost_syncpt *);
+#define client_managed(id) (BIT(id) & sp->client_managed)
+#define syncpt_to_dev(sp) container_of(sp, struct nvhost_master, syncpt)
+#define syncpt_op(sp) (syncpt_to_dev(sp)->op.syncpt)
+#define SYNCPT_CHECK_PERIOD 2*HZ
+static inline bool nvhost_syncpt_check_max(struct nvhost_syncpt *sp, u32 id, u32 real)
+{
+       u32 max;
+       if (client_managed(id))
+               return true;
+       smp_rmb();
+       max = (u32)atomic_read(&sp->max_val[id]);
+       return ((s32)(max - real) >= 0);
+}
+
+
 /**
  * Updates the value sent to hardware.
  */
@@ -159,14 +140,15 @@ static inline int nvhost_syncpt_wait(struct nvhost_syncpt *sp, u32 id, u32 thres
  * that have already been satisfied and NULL the comparison (to
  * avoid a wrap condition in the HW).
  *
- * @param: nvmap - needed to access command buffer
  * @param: sp - global shadowed syncpt struct
+ * @param: nvmap - needed to access command buffer
  * @param: mask - bit mask of syncpt IDs referenced in WAITs
  * @param: wait - start of filled in array of waitchk structs
  * @param: waitend - end ptr (one beyond last valid waitchk)
  */
-int nvhost_syncpt_wait_check(struct nvmap_client *nvmap,
-                       struct nvhost_syncpt *sp, u32 mask,
+int nvhost_syncpt_wait_check(struct nvhost_syncpt *sp,
+                       struct nvmap_client *nvmap,
+                       u32 mask,
                        struct nvhost_waitchk *wait,
                        struct nvhost_waitchk *waitend);
 
similarity index 98%
rename from drivers/video/tegra/host/nvhost_3dctx.c
rename to drivers/video/tegra/host/t20/3dctx_t20.c
index ecbca73..b9068b0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/video/tegra/host/nvhost_3dctx.c
+ * drivers/video/tegra/host/t20/3dctx_t20.c
  *
  * Tegra Graphics Host 3d hardware context
  *
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-#include "nvhost_hwctx.h"
-#include "dev.h"
+#include "../nvhost_hwctx.h"
+#include "../dev.h"
+#include "hardware_t20.h"
+#include "syncpt_t20.h"
 
 #include <mach/gpufuse.h>
 #include <mach/hardware.h>
 #include <linux/slab.h>
 
+
 #define NV_WAR_789194 1
 
 /*  99 > 2, which makes kernel panic if register set is incorrect */
@@ -38,6 +41,8 @@ static bool s_is_v1 = true;
 #endif
 static bool s_war_insert_syncpoints;
 
+
+
 const struct hwctx_reginfo ctxsave_regs_3d_global[] = {
        HWCTX_REGINFO(0, 0xe00,    4, DIRECT),
        HWCTX_REGINFO(0, 0xe05,   30, DIRECT),
@@ -769,10 +774,7 @@ static const struct ctx_saver v1_saver __initconst = {
        .ctx3d_save_service = NULL
 };
 
-
-/*** nvhost_3dctx ***/
-
-int __init nvhost_3dctx_handler_init(struct nvhost_hwctx_handler *h)
+int __init t20_nvhost_3dctx_handler_init(struct nvhost_hwctx_handler *h)
 {
        const struct ctx_saver *saver = s_is_v1 ? &v1_saver : &v0_saver;
        struct nvhost_channel *ch;
@@ -819,7 +821,7 @@ int __init nvhost_3dctx_handler_init(struct nvhost_hwctx_handler *h)
 }
 
 /* TODO: [ahatala 2010-05-27] */
-int __init nvhost_mpectx_handler_init(struct nvhost_hwctx_handler *h)
+int __init t20_nvhost_mpectx_handler_init(struct nvhost_hwctx_handler *h)
 {
        return 0;
 }
diff --git a/drivers/video/tegra/host/t20/Makefile b/drivers/video/tegra/host/t20/Makefile
new file mode 100644 (file)
index 0000000..a4d4040
--- /dev/null
@@ -0,0 +1,11 @@
+nvhost-t20-objs  = \
+       t20.o \
+       syncpt_t20.o \
+       cpuaccess_t20.o \
+       channel_t20.o \
+       intr_t20.o \
+       cdma_t20.o \
+       3dctx_t20.o \
+       debug_t20.o
+
+obj-$(CONFIG_TEGRA_GRHOST) += nvhost-t20.o
diff --git a/drivers/video/tegra/host/t20/cdma_t20.c b/drivers/video/tegra/host/t20/cdma_t20.c
new file mode 100644 (file)
index 0000000..77f514e
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * drivers/video/tegra/host/t20/cdma_t20.c
+ *
+ * Tegra Graphics Host Command DMA
+ *
+ * Copyright (c) 2010-2011, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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 Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "../nvhost_cdma.h"
+#include "../dev.h"
+
+#include "hardware_t20.h"
+
+/*
+ * push_buffer
+ *
+ * The push buffer is a circular array of words to be fetched by command DMA.
+ * Note that it works slightly differently to the sync queue; fence == cur
+ * means that the push buffer is full, not empty.
+ */
+
+
+/**
+ * Reset to empty push buffer
+ */
+static void t20_push_buffer_reset(struct push_buffer *pb)
+{
+       pb->fence = PUSH_BUFFER_SIZE - 8;
+       pb->cur = 0;
+}
+
+/**
+ * Init push buffer resources
+ */
+static int t20_push_buffer_init(struct push_buffer *pb)
+{
+       struct nvhost_cdma *cdma = pb_to_cdma(pb);
+       struct nvmap_client *nvmap = cdma_to_nvmap(cdma);
+       pb->mem = NULL;
+       pb->mapped = NULL;
+       pb->phys = 0;
+
+       BUG_ON(!cdma_pb_op(cdma).reset);
+       cdma_pb_op(cdma).reset(pb);
+
+       /* allocate and map pushbuffer memory */
+       pb->mem = nvmap_alloc(nvmap, PUSH_BUFFER_SIZE + 4, 32,
+                             NVMAP_HANDLE_WRITE_COMBINE);
+       if (IS_ERR_OR_NULL(pb->mem)) {
+               pb->mem = NULL;
+               goto fail;
+       }
+       pb->mapped = nvmap_mmap(pb->mem);
+       if (pb->mapped == NULL)
+               goto fail;
+
+       /* pin pushbuffer and get physical address */
+       pb->phys = nvmap_pin(nvmap, pb->mem);
+       if (pb->phys >= 0xfffff000) {
+               pb->phys = 0;
+               goto fail;
+       }
+
+       /* put the restart at the end of pushbuffer memory */
+       *(pb->mapped + (PUSH_BUFFER_SIZE >> 2)) = nvhost_opcode_restart(pb->phys);
+
+       return 0;
+
+fail:
+       cdma_pb_op(cdma).destroy(pb);
+       return -ENOMEM;
+}
+
+/**
+ * Clean up push buffer resources
+ */
+static void t20_push_buffer_destroy(struct push_buffer *pb)
+{
+       struct nvhost_cdma *cdma = pb_to_cdma(pb);
+       struct nvmap_client *nvmap = cdma_to_nvmap(cdma);
+       if (pb->mapped)
+               nvmap_munmap(pb->mem, pb->mapped);
+
+       if (pb->phys != 0)
+               nvmap_unpin(nvmap, pb->mem);
+
+       if (pb->mem)
+               nvmap_free(nvmap, pb->mem);
+
+       pb->mem = NULL;
+       pb->mapped = NULL;
+       pb->phys = 0;
+}
+
+/**
+ * Push two words to the push buffer
+ * Caller must ensure push buffer is not full
+ */
+static void t20_push_buffer_push_to(struct push_buffer *pb, u32 op1, u32 op2)
+{
+       u32 cur = pb->cur;
+       u32 *p = (u32*)((u32)pb->mapped + cur);
+       BUG_ON(cur == pb->fence);
+       *(p++) = op1;
+       *(p++) = op2;
+       pb->cur = (cur + 8) & (PUSH_BUFFER_SIZE - 1);
+       /* printk("push_to_push_buffer: op1=%08x; op2=%08x; cur=%x\n", op1, op2, pb->cur); */
+}
+
+/**
+ * Pop a number of two word slots from the push buffer
+ * Caller must ensure push buffer is not empty
+ */
+static void t20_push_buffer_pop_from(struct push_buffer *pb, unsigned int slots)
+{
+       pb->fence = (pb->fence + slots * 8) & (PUSH_BUFFER_SIZE - 1);
+}
+
+/**
+ * Return the number of two word slots free in the push buffer
+ */
+static u32 t20_push_buffer_space(struct push_buffer *pb)
+{
+       return ((pb->fence - pb->cur) & (PUSH_BUFFER_SIZE - 1)) / 8;
+}
+
+static u32 t20_push_buffer_putptr(struct push_buffer *pb)
+{
+       return pb->phys + pb->cur;
+}
+
+
+/**
+ * Start channel DMA
+ */
+static void t20_cdma_start(struct nvhost_cdma *cdma)
+{
+       void __iomem *chan_regs = cdma_to_channel(cdma)->aperture;
+
+       if (cdma->running)
+               return;
+
+       BUG_ON(!cdma_pb_op(cdma).putptr);
+
+       cdma->last_put = cdma_pb_op(cdma).putptr(&cdma->push_buffer);
+
+       writel(nvhost_channel_dmactrl(true, false, false),
+               chan_regs + HOST1X_CHANNEL_DMACTRL);
+
+       /* set base, put, end pointer (all of memory) */
+       writel(0, chan_regs + HOST1X_CHANNEL_DMASTART);
+       writel(cdma->last_put, chan_regs + HOST1X_CHANNEL_DMAPUT);
+       writel(0xFFFFFFFF, chan_regs + HOST1X_CHANNEL_DMAEND);
+
+       /* reset GET */
+       writel(nvhost_channel_dmactrl(true, true, true),
+               chan_regs + HOST1X_CHANNEL_DMACTRL);
+
+       /* start the command DMA */
+       writel(nvhost_channel_dmactrl(false, false, false),
+               chan_regs + HOST1X_CHANNEL_DMACTRL);
+
+       cdma->running = true;
+}
+
+/**
+ * Kick channel DMA into action by writing its PUT offset (if it has changed)
+ */
+static void t20_cdma_kick(struct nvhost_cdma *cdma)
+{
+       u32 put;
+       BUG_ON(!cdma_pb_op(cdma).putptr);
+
+       put = cdma_pb_op(cdma).putptr(&cdma->push_buffer);
+
+       if (put != cdma->last_put) {
+               void __iomem *chan_regs = cdma_to_channel(cdma)->aperture;
+               wmb();
+               writel(put, chan_regs + HOST1X_CHANNEL_DMAPUT);
+               cdma->last_put = put;
+       }
+}
+
+static void t20_cdma_stop(struct nvhost_cdma *cdma)
+{
+       void __iomem *chan_regs = cdma_to_channel(cdma)->aperture;
+
+       mutex_lock(&cdma->lock);
+       if (cdma->running) {
+               nvhost_cdma_wait(cdma, CDMA_EVENT_SYNC_QUEUE_EMPTY);
+               writel(nvhost_channel_dmactrl(true, false, false),
+                       chan_regs + HOST1X_CHANNEL_DMACTRL);
+               cdma->running = false;
+       }
+       mutex_unlock(&cdma->lock);
+}
+
+/**
+ * Retrieve the op pair at a slot offset from a DMA address
+ */
+void t20_cdma_peek(struct nvhost_cdma *cdma,
+                         u32 dmaget, int slot, u32 *out)
+{
+       u32 offset = dmaget - cdma->push_buffer.phys;
+       u32 *p = cdma->push_buffer.mapped;
+
+       offset = ((offset + slot * 8) & (PUSH_BUFFER_SIZE - 1)) >> 2;
+       out[0] = p[offset];
+       out[1] = p[offset + 1];
+}
+
+int nvhost_init_t20_cdma_support(struct nvhost_master *host)
+{
+       host->op.cdma.start = t20_cdma_start;
+       host->op.cdma.stop = t20_cdma_stop;
+       host->op.cdma.kick = t20_cdma_kick;
+
+       host->sync_queue_size = NVHOST_SYNC_QUEUE_SIZE;
+
+       host->op.push_buffer.reset = t20_push_buffer_reset;
+       host->op.push_buffer.init = t20_push_buffer_init;
+       host->op.push_buffer.destroy = t20_push_buffer_destroy;
+       host->op.push_buffer.push_to = t20_push_buffer_push_to;
+       host->op.push_buffer.pop_from = t20_push_buffer_pop_from;
+       host->op.push_buffer.space = t20_push_buffer_space;
+       host->op.push_buffer.putptr = t20_push_buffer_putptr;
+
+       return 0;
+}
diff --git a/drivers/video/tegra/host/t20/channel_t20.c b/drivers/video/tegra/host/t20/channel_t20.c
new file mode 100644 (file)
index 0000000..68cffd7
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * drivers/video/tegra/host/t20/channel_t20.c
+ *
+ * Tegra Graphics Host Channel
+ *
+ * Copyright (c) 2010-2011, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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 Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "../nvhost_channel.h"
+#include "../dev.h"
+#include "../nvhost_hwctx.h"
+#include <trace/events/nvhost.h>
+
+#include "hardware_t20.h"
+#include "syncpt_t20.h"
+
+#define NVHOST_NUMCHANNELS (NV_HOST1X_CHANNELS - 1)
+#define NVHOST_CHANNEL_BASE 0
+
+#define NVMODMUTEX_2D_FULL   (1)
+#define NVMODMUTEX_2D_SIMPLE (2)
+#define NVMODMUTEX_2D_SB_A   (3)
+#define NVMODMUTEX_2D_SB_B   (4)
+#define NVMODMUTEX_3D        (5)
+#define NVMODMUTEX_DISPLAYA  (6)
+#define NVMODMUTEX_DISPLAYB  (7)
+#define NVMODMUTEX_VI        (8)
+#define NVMODMUTEX_DSI       (9)
+
+static void power_2d(struct nvhost_module *mod, enum nvhost_power_action action);
+static void power_3d(struct nvhost_module *mod, enum nvhost_power_action action);
+static void power_mpe(struct nvhost_module *mod, enum nvhost_power_action action);
+
+
+
+static const struct nvhost_channeldesc channelmap[] = {
+{
+       /* channel 0 */
+       .name          = "display",
+       .syncpts       = BIT(NVSYNCPT_DISP0) | BIT(NVSYNCPT_DISP1) |
+                        BIT(NVSYNCPT_VBLANK0) | BIT(NVSYNCPT_VBLANK1),
+       .modulemutexes = BIT(NVMODMUTEX_DISPLAYA) | BIT(NVMODMUTEX_DISPLAYB),
+},
+{
+       /* channel 1 */
+       .name          = "gr3d",
+       .syncpts       = BIT(NVSYNCPT_3D),
+       .waitbases     = BIT(NVWAITBASE_3D),
+       .modulemutexes = BIT(NVMODMUTEX_3D),
+       .class         = NV_GRAPHICS_3D_CLASS_ID,
+       .power         = power_3d,
+},
+{
+       /* channel 2 */
+       .name          = "gr2d",
+       .syncpts       = BIT(NVSYNCPT_2D_0) | BIT(NVSYNCPT_2D_1),
+       .waitbases     = BIT(NVWAITBASE_2D_0) | BIT(NVWAITBASE_2D_1),
+       .modulemutexes = BIT(NVMODMUTEX_2D_FULL) | BIT(NVMODMUTEX_2D_SIMPLE) |
+                        BIT(NVMODMUTEX_2D_SB_A) | BIT(NVMODMUTEX_2D_SB_B),
+       .power         = power_2d,
+},
+{
+       /* channel 3 */
+       .name    = "isp",
+       .syncpts = 0,
+},
+{
+       /* channel 4 */
+       .name          = "vi",
+       .syncpts       = BIT(NVSYNCPT_CSI_VI_0) | BIT(NVSYNCPT_CSI_VI_1) |
+                        BIT(NVSYNCPT_VI_ISP_0) | BIT(NVSYNCPT_VI_ISP_1) |
+                        BIT(NVSYNCPT_VI_ISP_2) | BIT(NVSYNCPT_VI_ISP_3) |
+                        BIT(NVSYNCPT_VI_ISP_4),
+       .modulemutexes = BIT(NVMODMUTEX_VI),
+       .exclusive     = true,
+},
+{
+       /* channel 5 */
+       .name          = "mpe",
+       .syncpts       = BIT(NVSYNCPT_MPE) | BIT(NVSYNCPT_MPE_EBM_EOF) |
+                        BIT(NVSYNCPT_MPE_WR_SAFE),
+       .waitbases     = BIT(NVWAITBASE_MPE),
+       .class         = NV_VIDEO_ENCODE_MPEG_CLASS_ID,
+       .power         = power_mpe,
+       .exclusive     = true,
+       .keepalive     = true,
+},
+{
+       /* channel 6 */
+       .name          = "dsi",
+       .syncpts       = BIT(NVSYNCPT_DSI),
+       .modulemutexes = BIT(NVMODMUTEX_DSI),
+}};
+
+static inline void __iomem *t20_channel_aperture(void __iomem *p, int ndx)
+{
+       ndx += NVHOST_CHANNEL_BASE;
+       p += NV_HOST1X_CHANNEL0_BASE;
+       p += ndx * NV_HOST1X_CHANNEL_MAP_SIZE_BYTES;
+       return p;
+}
+
+
+int t20_nvhost_3dctx_handler_init(struct nvhost_hwctx_handler *h);
+int t20_nvhost_mpectx_handler_init(struct nvhost_hwctx_handler *h);
+
+static inline int t20_nvhost_hwctx_handler_init(
+       struct nvhost_hwctx_handler *h,
+       const char *module)
+{
+       if (strcmp(module, "gr3d") == 0)
+               return t20_nvhost_3dctx_handler_init(h);
+       else if (strcmp(module, "mpe") == 0)
+               return t20_nvhost_mpectx_handler_init(h);
+
+       return 0;
+}
+
+
+static int t20_channel_init(struct nvhost_channel *ch,
+                           struct nvhost_master *dev, int index)
+{
+       ch->dev = dev;
+       ch->desc = channelmap + index;
+       mutex_init(&ch->reflock);
+       mutex_init(&ch->submitlock);
+
+       ch->aperture = t20_channel_aperture(dev->aperture, index);
+
+       return t20_nvhost_hwctx_handler_init(&ch->ctxhandler, ch->desc->name);
+}
+
+
+
+static int t20_channel_submit(struct nvhost_channel *channel,
+                             struct nvhost_hwctx *hwctx,
+                             struct nvmap_client *user_nvmap,
+                             u32 *gather,
+                             u32 *gather_end,
+                             struct nvhost_waitchk *waitchk,
+                             struct nvhost_waitchk *waitchk_end,
+                             u32 waitchk_mask,
+                             struct nvmap_handle **unpins,
+                             int nr_unpins,
+                             u32 syncpt_id,
+                             u32 syncpt_incrs,
+                             u32 *syncpt_value,
+                             bool null_kickoff)
+{
+       struct nvhost_hwctx *hwctx_to_save = NULL;
+       struct nvhost_syncpt *sp = &channel->dev->syncpt;
+       u32 user_syncpt_incrs = syncpt_incrs;
+       bool need_restore = false;
+       u32 syncval;
+       int err;
+
+       /* keep module powered */
+       nvhost_module_busy(&channel->mod);
+
+       /* get submit lock */
+       err = mutex_lock_interruptible(&channel->submitlock);
+       if (err) {
+               nvhost_module_idle(&channel->mod);
+               return err;
+       }
+
+       /* remove stale waits */
+       if (waitchk != waitchk_end) {
+               err = nvhost_syncpt_wait_check(sp,
+                                              user_nvmap,
+                                              waitchk_mask,
+                                              waitchk, waitchk_end);
+               if (err) {
+                       dev_warn(&channel->dev->pdev->dev,
+                                "nvhost_syncpt_wait_check failed: %d\n", err);
+                       mutex_unlock(&channel->submitlock);
+                       nvhost_module_idle(&channel->mod);
+                       return err;
+               }
+       }
+
+       /* context switch */
+       if (channel->cur_ctx != hwctx) {
+               trace_nvhost_channel_context_switch(channel->desc->name,
+                 channel->cur_ctx, hwctx);
+               hwctx_to_save = channel->cur_ctx;
+               if (hwctx_to_save) {
+                       syncpt_incrs += hwctx_to_save->save_incrs;
+                       hwctx_to_save->valid = true;
+                       channel->ctxhandler.get(hwctx_to_save);
+               }
+               channel->cur_ctx = hwctx;
+               if (channel->cur_ctx && channel->cur_ctx->valid) {
+                       need_restore = true;
+                       syncpt_incrs += channel->cur_ctx->restore_incrs;
+               }
+       }
+
+       /* get absolute sync value */
+       if (BIT(syncpt_id) & sp->client_managed)
+               syncval = nvhost_syncpt_set_max(sp,
+                                               syncpt_id, syncpt_incrs);
+       else
+               syncval = nvhost_syncpt_incr_max(sp,
+                                               syncpt_id, syncpt_incrs);
+
+       /* begin a CDMA submit */
+       nvhost_cdma_begin(&channel->cdma);
+
+       /* push save buffer (pre-gather setup depends on unit) */
+       if (hwctx_to_save)
+               channel->ctxhandler.save_push(&channel->cdma, hwctx_to_save);
+
+       /* gather restore buffer */
+       if (need_restore)
+               nvhost_cdma_push(&channel->cdma,
+                       nvhost_opcode_gather(channel->cur_ctx->restore_size),
+                       channel->cur_ctx->restore_phys);
+
+       /* add a setclass for modules that require it (unless ctxsw added it) */
+       if (!hwctx_to_save && !need_restore && channel->desc->class)
+               nvhost_cdma_push(&channel->cdma,
+                       nvhost_opcode_setclass(channel->desc->class, 0, 0),
+                       NVHOST_OPCODE_NOOP);
+
+       if (null_kickoff) {
+               int incr;
+               u32 op_incr;
+
+               /* TODO ideally we'd also perform host waits here */
+
+               /* push increments that correspond to nulled out commands */
+               op_incr = nvhost_opcode_imm(0, 0x100 | syncpt_id);
+               for (incr = 0; incr < (user_syncpt_incrs >> 1); incr++)
+                       nvhost_cdma_push(&channel->cdma, op_incr, op_incr);
+               if (user_syncpt_incrs & 1)
+                       nvhost_cdma_push(&channel->cdma,
+                                       op_incr, NVHOST_OPCODE_NOOP);
+
+               /* for 3d, waitbase needs to be incremented after each submit */
+               if (channel->desc->class == NV_GRAPHICS_3D_CLASS_ID)
+                       nvhost_cdma_push(&channel->cdma,
+                                       nvhost_opcode_setclass(
+                                               NV_HOST1X_CLASS_ID,
+                                               NV_CLASS_HOST_INCR_SYNCPT_BASE,
+                                               1),
+                                       nvhost_class_host_incr_syncpt_base(
+                                               NVWAITBASE_3D,
+                                               user_syncpt_incrs));
+       }
+       else {
+               /* push user gathers */
+               for ( ; gather != gather_end; gather += 2)
+                       nvhost_cdma_push(&channel->cdma,
+                                       nvhost_opcode_gather(gather[0]),
+                                       gather[1]);
+       }
+
+       /* end CDMA submit & stash pinned hMems into sync queue */
+       nvhost_cdma_end(&channel->cdma, user_nvmap,
+                       syncpt_id, syncval, unpins, nr_unpins);
+
+       /*
+        * schedule a context save interrupt (to drain the host FIFO
+        * if necessary, and to release the restore buffer)
+        */
+       if (hwctx_to_save)
+               nvhost_intr_add_action(&channel->dev->intr, syncpt_id,
+                       syncval - syncpt_incrs + hwctx_to_save->save_thresh,
+                       NVHOST_INTR_ACTION_CTXSAVE, hwctx_to_save, NULL);
+
+       /* schedule a submit complete interrupt */
+       nvhost_intr_add_action(&channel->dev->intr, syncpt_id, syncval,
+                       NVHOST_INTR_ACTION_SUBMIT_COMPLETE, channel, NULL);
+
+       mutex_unlock(&channel->submitlock);
+
+       *syncpt_value = syncval;
+       return 0;
+}
+
+static void power_2d(struct nvhost_module *mod, enum nvhost_power_action action)
+{
+       /* TODO: [ahatala 2010-06-17] reimplement EPP hang war */
+       if (action == NVHOST_POWER_ACTION_OFF) {
+               /* TODO: [ahatala 2010-06-17] reset EPP */
+       }
+}
+
+static void power_3d(struct nvhost_module *mod, enum nvhost_power_action action)
+{
+       struct nvhost_channel *ch = container_of(mod, struct nvhost_channel, mod);
+       struct nvhost_hwctx *hwctx_to_save;
+       DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
+       u32 syncpt_incrs, syncpt_val;
+       void *ref;
+
+       if (action != NVHOST_POWER_ACTION_OFF)
+               return;
+
+       mutex_lock(&ch->submitlock);
+       hwctx_to_save = ch->cur_ctx;
+       if (!hwctx_to_save) {
+               mutex_unlock(&ch->submitlock);
+               return;
+       }
+
+       hwctx_to_save->valid = true;
+       ch->ctxhandler.get(hwctx_to_save);
+       ch->cur_ctx = NULL;
+
+       syncpt_incrs = hwctx_to_save->save_incrs;
+       syncpt_val = nvhost_syncpt_incr_max(&ch->dev->syncpt,
+                                       NVSYNCPT_3D, syncpt_incrs);
+
+       nvhost_cdma_begin(&ch->cdma);
+       ch->ctxhandler.save_push(&ch->cdma, hwctx_to_save);
+       nvhost_cdma_end(&ch->cdma, ch->dev->nvmap, NVSYNCPT_3D, syncpt_val, NULL, 0);
+
+       nvhost_intr_add_action(&ch->dev->intr, NVSYNCPT_3D,
+                       syncpt_val - syncpt_incrs + hwctx_to_save->save_thresh,
+                       NVHOST_INTR_ACTION_CTXSAVE, hwctx_to_save, NULL);
+
+       nvhost_intr_add_action(&ch->dev->intr, NVSYNCPT_3D, syncpt_val,
+                       NVHOST_INTR_ACTION_WAKEUP, &wq, &ref);
+       wait_event(wq,
+               nvhost_syncpt_min_cmp(&ch->dev->syncpt,
+                               NVSYNCPT_3D, syncpt_val));
+
+       nvhost_intr_put_ref(&ch->dev->intr, ref);
+
+       nvhost_cdma_update(&ch->cdma);
+
+       mutex_unlock(&ch->submitlock);
+}
+
+static void power_mpe(struct nvhost_module *mod, enum nvhost_power_action action)
+{
+}
+
+int nvhost_init_t20_channel_support(struct nvhost_master *host)
+{
+
+       BUILD_BUG_ON(NVHOST_NUMCHANNELS != ARRAY_SIZE(channelmap));
+
+       host->nb_mlocks =  NV_HOST1X_SYNC_MLOCK_NUM;
+       host->nb_channels =  NVHOST_NUMCHANNELS;
+
+       host->op.channel.init = t20_channel_init;
+       host->op.channel.submit = t20_channel_submit;
+
+       return 0;
+}
diff --git a/drivers/video/tegra/host/t20/cpuaccess_t20.c b/drivers/video/tegra/host/t20/cpuaccess_t20.c
new file mode 100644 (file)
index 0000000..f6bb76f
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * drivers/video/tegra/host/cpuaccess_t20.c
+ *
+ * Tegra Graphics Host Cpu Register Access
+ *
+ * Copyright (c) 2010-2011, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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 Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "../nvhost_cpuaccess.h"
+#include "../dev.h"
+
+#include "hardware_t20.h"
+
+static int t20_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;
+       /* mlock registers returns 0 when the lock is aquired.
+        * writing 0 clears the lock. */
+       return !!readl(sync_regs + (HOST1X_SYNC_MLOCK_0 + idx * 4));
+}
+
+static void t20_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;
+
+       writel(0, sync_regs + (HOST1X_SYNC_MLOCK_0 + idx * 4));
+}
+
+int nvhost_init_t20_cpuaccess_support(struct nvhost_master *host)
+{
+       host->nb_modules = NVHOST_MODULE_NUM;
+
+       host->op.cpuaccess.mutex_try_lock = t20_cpuaccess_mutex_try_lock;
+       host->op.cpuaccess.mutex_unlock = t20_cpuaccess_mutex_unlock;
+
+       return 0;
+}
diff --git a/drivers/video/tegra/host/t20/debug_t20.c b/drivers/video/tegra/host/t20/debug_t20.c
new file mode 100644 (file)
index 0000000..0c77745
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * drivers/video/tegra/host/t20/debug_t20.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Author: Erik Gilling <konkers@android.com>
+ *
+ * Copyright (C) 2011 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 <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include <asm/io.h>
+
+#include "../dev.h"
+#include "../debug.h"
+#include "../nvhost_cdma.h"
+
+#include "hardware_t20.h"
+
+enum {
+       NVHOST_DBG_STATE_CMD = 0,
+       NVHOST_DBG_STATE_DATA = 1,
+       NVHOST_DBG_STATE_GATHER = 2
+};
+
+static int show_channel_command(struct output *o, u32 val, int *count)
+{
+       unsigned mask;
+       unsigned subop;
+
+       switch (val >> 28) {
+       case 0x0:
+               mask = val & 0x3f;
+               if (mask) {
+                       nvhost_debug_output(o, "SETCL(class=%03x, offset=%03x, mask=%02x, [",
+                                  val >> 6 & 0x3ff, val >> 16 & 0xfff, mask);
+                       *count = hweight8(mask);
+                       return NVHOST_DBG_STATE_DATA;
+               } else {
+                       nvhost_debug_output(o, "SETCL(class=%03x)\n", val >> 6 & 0x3ff);
+                       return NVHOST_DBG_STATE_CMD;
+               }
+
+       case 0x1:
+               nvhost_debug_output(o, "INCR(offset=%03x, [", val >> 16 & 0xfff);
+               *count = val & 0xffff;
+               return NVHOST_DBG_STATE_DATA;
+
+       case 0x2:
+               nvhost_debug_output(o, "NONINCR(offset=%03x, [", val >> 16 & 0xfff);
+               *count = val & 0xffff;
+               return NVHOST_DBG_STATE_DATA;
+
+       case 0x3:
+               mask = val & 0xffff;
+               nvhost_debug_output(o, "MASK(offset=%03x, mask=%03x, [",
+                          val >> 16 & 0xfff, mask);
+               *count = hweight16(mask);
+               return NVHOST_DBG_STATE_DATA;
+
+       case 0x4:
+               nvhost_debug_output(o, "IMM(offset=%03x, data=%03x)\n",
+                          val >> 16 & 0xfff, val & 0xffff);
+               return NVHOST_DBG_STATE_CMD;
+
+       case 0x5:
+               nvhost_debug_output(o, "RESTART(offset=%08x)\n", val << 4);
+               return NVHOST_DBG_STATE_CMD;
+
+       case 0x6:
+               nvhost_debug_output(o, "GATHER(offset=%03x, insert=%d, type=%d, count=%04x, addr=[",
+                          val >> 16 & 0xfff, val >> 15 & 0x1, val >> 14 & 0x1,
+                          val & 0x3fff);
+               *count = val & 0x3fff; // TODO: insert
+               return NVHOST_DBG_STATE_GATHER;
+
+       case 0xe:
+               subop = val >> 24 & 0xf;
+               if (subop == 0)
+                       nvhost_debug_output(o, "ACQUIRE_MLOCK(index=%d)\n", val & 0xff);
+               else if (subop == 1)
+                       nvhost_debug_output(o, "RELEASE_MLOCK(index=%d)\n", val & 0xff);
+               else
+                       nvhost_debug_output(o, "EXTEND_UNKNOWN(%08x)\n", val);
+               return NVHOST_DBG_STATE_CMD;
+
+       default:
+               return NVHOST_DBG_STATE_CMD;
+       }
+}
+
+/*
+ * TODO: This uses ioremap_xxx on memory which is deprecated.
+ * Also, it won't work properly with SMMU.
+ */
+static void show_channel_gather(struct output *o, u32 phys_addr,
+                               phys_addr_t words);
+
+static void show_channel_word(struct output *o, int *state, int *count,
+                                    u32 addr, u32 val)
+{
+       switch (*state) {
+       case NVHOST_DBG_STATE_CMD:
+               if (addr)
+                       nvhost_debug_output(o, "%08x: %08x:", addr, val);
+               else
+                       nvhost_debug_output(o, "%08x:", val);
+
+               *state = show_channel_command(o, val, count);
+               if (*state == NVHOST_DBG_STATE_DATA && *count == 0) {
+                       *state = NVHOST_DBG_STATE_CMD;
+                       nvhost_debug_output(o, "])\n");
+               }
+               break;
+
+       case NVHOST_DBG_STATE_DATA:
+               (*count)--;
+               nvhost_debug_output(o, "%08x%s", val, *count > 0 ? ", " : "])\n");
+               if (*count == 0)
+                       *state = NVHOST_DBG_STATE_CMD;
+               break;
+
+       case NVHOST_DBG_STATE_GATHER:
+               *state = NVHOST_DBG_STATE_CMD;
+               nvhost_debug_output(o, "%08x]):\n", val);
+               show_channel_gather(o, val, *count);
+               break;
+       }
+}
+
+static void show_channel_gather(struct output *o, phys_addr_t phys_addr,
+                               u32 words)
+{
+       phys_addr_t map_base = phys_addr & PAGE_MASK;
+       phys_addr_t map_end = (phys_addr + words * 4 + PAGE_SIZE - 1) & PAGE_MASK;
+       phys_addr_t map_size = map_end - map_base;
+       phys_addr_t map_offset = phys_addr - map_base;
+       void *map_addr = ioremap_nocache(map_base, map_size);
+       int state = NVHOST_DBG_STATE_CMD;
+       int count, i;
+
+       if (!map_addr)
+               return;
+       for (i = 0; i < words; i++)
+               show_channel_word(o, &state, &count, phys_addr + i * 4,
+                               readl(map_addr + map_offset + i * 4));
+       iounmap(map_addr);
+}
+
+static void show_channel_pair(struct output *o, u32 addr,
+                               u32 w0, u32 w1)
+{
+       int state = NVHOST_DBG_STATE_CMD;
+       int count;
+
+       show_channel_word(o, &state, &count, addr, w0);
+       show_channel_word(o, &state, &count, addr, w1);
+}
+
+/**
+ * Retrieve the op pair at a slot offset from a DMA address
+ */
+static void cdma_peek(struct nvhost_cdma *cdma,
+                     u32 dmaget, int slot, u32 *out)
+{
+       u32 offset = dmaget - cdma->push_buffer.phys;
+       u32 *p = cdma->push_buffer.mapped;
+
+       offset = ((offset + slot * 8) & (PUSH_BUFFER_SIZE - 1)) >> 2;
+       out[0] = p[offset];
+       out[1] = p[offset + 1];
+}
+
+static void t20_debug_show_channel_cdma(struct nvhost_master *m,
+                                       struct output *o, int chid)
+{
+       struct nvhost_channel *channel = m->channels + chid;
+       u32 dmaput, dmaget, dmactrl;
+       u32 cbstat, cbread;
+       u32 val, base, baseval;
+       u32 pbw[2];
+
+       dmaput = readl(channel->aperture + HOST1X_CHANNEL_DMAPUT);
+       dmaget = readl(channel->aperture + HOST1X_CHANNEL_DMAGET);
+       dmactrl = readl(channel->aperture + HOST1X_CHANNEL_DMACTRL);
+       cbread = readl(m->aperture + HOST1X_SYNC_CBREAD(chid));
+       cbstat = readl(m->aperture + HOST1X_SYNC_CBSTAT(chid));
+
+       nvhost_debug_output(o, "%d-%s (%d): ", chid,
+                           channel->mod.name, atomic_read(&channel->mod.refcount));
+
+       if ((dmactrl & 1) || !channel->cdma.push_buffer.mapped) {
+               nvhost_debug_output(o, "inactive\n\n");
+               return;
+       }
+
+       switch (cbstat) {
+       case 0x00010008:
+               nvhost_debug_output(o, "waiting on syncpt %d val %d\n",
+                       cbread >> 24, cbread & 0xffffff);
+               break;
+
+       case 0x00010009:
+               base = (cbread >> 16) & 0xff;
+               val = readl(m->aperture + HOST1X_SYNC_SYNCPT_BASE(base));
+               baseval = val & 0xffff;
+               val = cbread & 0xffff;
+               nvhost_debug_output(o, "waiting on syncpt %d val %d "
+                         "(base %d = %d; offset = %d)\n",
+                       cbread >> 24, baseval + val,
+                       base, baseval, val);
+               break;
+
+       default:
+               nvhost_debug_output(o, "active class %02x, offset %04x, val %08x\n",
+                       cbstat >> 16, cbstat & 0xffff, cbread);
+               break;
+       }
+
+       cdma_peek(&channel->cdma, dmaget, -1, pbw);
+       show_channel_pair(o, chid, pbw[0], pbw[1]);
+       nvhost_debug_output(o, "\n");
+}
+
+void t20_debug_show_channel_fifo(struct nvhost_master *m,
+                                struct output *o, int chid)
+{
+       u32 val, rd_ptr, wr_ptr, start, end;
+       int state, count;
+
+       val = readl(m->aperture + HOST1X_CHANNEL_FIFOSTAT);
+       if (val & (1 << 10))
+               return;
+
+       writel(0x0, m->aperture + HOST1X_SYNC_CFPEEK_CTRL);
+       writel((1 << 31) | (chid << 16),
+               m->aperture + HOST1X_SYNC_CFPEEK_CTRL);
+
+       val = readl(m->aperture + HOST1X_SYNC_CFPEEK_PTRS);
+       rd_ptr = val & 0x1ff;
+       wr_ptr = (val >> 16) & 0x1ff;
+
+       val = readl(m->aperture + HOST1X_SYNC_CF_SETUP(chid));
+       start = val & 0x1ff;
+       end = (val >> 16) & 0x1ff;
+
+       state = NVHOST_DBG_STATE_CMD;
+       nvhost_debug_output(o, "%d: fifo:\n", chid);
+
+       do {
+               writel(0x0, m->aperture + HOST1X_SYNC_CFPEEK_CTRL);
+               writel((1 << 31) | (chid << 16) | rd_ptr,
+                       m->aperture + HOST1X_SYNC_CFPEEK_CTRL);
+               val = readl(m->aperture + HOST1X_SYNC_CFPEEK_READ);
+
+               show_channel_word(o, &state, &count, 0, val);
+
+               if (rd_ptr == end)
+                       rd_ptr = start;
+               else
+                       rd_ptr++;
+       } while (rd_ptr != wr_ptr);
+
+       if (state == NVHOST_DBG_STATE_DATA)
+               nvhost_debug_output(o, ", ...])\n");
+       nvhost_debug_output(o, "\n");
+
+       writel(0x0, m->aperture + HOST1X_SYNC_CFPEEK_CTRL);
+}
+
+static void t20_debug_show_mlocks(struct nvhost_master *m, struct output *o)
+{
+       u32 __iomem *mlo_regs = m->sync_aperture + HOST1X_SYNC_MLOCK_OWNER_0;
+       int i;
+
+       nvhost_debug_output(o, "---- mlocks ----\n");
+       for (i = 0; i < NV_HOST1X_NB_MLOCKS; i++) {
+               u32 owner = readl(mlo_regs + i);
+               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_t20_debug_support(struct nvhost_master *host)
+{
+       host->op.debug.show_channel_cdma = t20_debug_show_channel_cdma;
+       host->op.debug.show_channel_fifo = t20_debug_show_channel_fifo;
+       host->op.debug.show_mlocks = t20_debug_show_mlocks;
+
+       return 0;
+}
similarity index 90%
rename from drivers/video/tegra/host/nvhost_hardware.h
rename to drivers/video/tegra/host/t20/hardware_t20.h
index 8fa2195..f94137c 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * drivers/video/tegra/host/nvhost_hardware.h
+ * drivers/video/tegra/host/t20/hardware_t20.h
  *
  * Tegra Graphics Host Register Offsets
  *
- * Copyright (c) 2010, NVIDIA Corporation.
+ * Copyright (c) 2010,2011 NVIDIA Corporation.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,8 +20,8 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-#ifndef __NVHOST_HARDWARE_H
-#define __NVHOST_HARDWARE_H
+#ifndef __NVHOST_HARDWARE_T20_H
+#define __NVHOST_HARDWARE_T20_H
 
 #include <linux/types.h>
 #include <linux/bitops.h>
@@ -256,5 +256,15 @@ static inline u32 nvhost_mask2(unsigned x, unsigned y)
        return 1 | (1 << (y - x));
 }
 
-#endif /* __NVHOST_HARDWARE_H */
+/* Size of the sync queue. If it is too small, we won't be able to queue up
+ * many command buffers. If it is too large, we waste memory. */
+#define NVHOST_SYNC_QUEUE_SIZE 8192
 
+/* Number of gathers we allow to be queued up per channel. Must be a
+ * power of two. Currently sized such that pushbuffer is 4KB (512*8B). */
+#define NVHOST_GATHER_QUEUE_SIZE 512
+
+/* 8 bytes per slot. (This number does not include the final RESTART.) */
+#define PUSH_BUFFER_SIZE (NVHOST_GATHER_QUEUE_SIZE * 8)
+
+#endif /* __NVHOST_HARDWARE_T20_H */
diff --git a/drivers/video/tegra/host/t20/intr_t20.c b/drivers/video/tegra/host/t20/intr_t20.c
new file mode 100644 (file)
index 0000000..94bdae4
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * drivers/video/tegra/host/t20/intr_t20.c
+ *
+ * Tegra Graphics Host Interrupt Management
+ *
+ * Copyright (c) 2010-2011, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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 Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include "../nvhost_intr.h"
+#include "../dev.h"
+
+#include "hardware_t20.h"
+
+
+/*** HW host sync management ***/
+
+static void t20_intr_init_host_sync(struct nvhost_intr *intr)
+{
+       struct nvhost_master *dev = intr_to_dev(intr);
+       void __iomem *sync_regs = dev->sync_aperture;
+       /* 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);
+
+       /* increase the auto-ack timout to the maximum value. 2d will hang
+        * otherwise on ap20.
+        */
+       writel(0xff, sync_regs + HOST1X_SYNC_CTXSW_TIMEOUT_CFG);
+}
+
+static void t20_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;
+       /* write microsecond clock register */
+       writel(cpm, sync_regs + HOST1X_SYNC_USEC_CLK);
+}
+
+static void t20_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;
+       thresh &= 0xffff;
+       writel(thresh, sync_regs + (HOST1X_SYNC_SYNCPT_INT_THRESH_0 + id * 4));
+}
+
+static void t20_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;
+       writel(BIT(id), sync_regs + HOST1X_SYNC_SYNCPT_THRESH_INT_ENABLE_CPU0);
+}
+
+static void t20_intr_disable_all_syncpt_intrs(struct nvhost_intr *intr)
+{
+       struct nvhost_master *dev = intr_to_dev(intr);
+       void __iomem *sync_regs = dev->sync_aperture;
+       /* disable interrupts for both cpu's */
+       writel(0, sync_regs + HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE);
+
+       /* clear status for both cpu's */
+       writel(0xfffffffful, sync_regs +
+               HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS);
+       writel(0xfffffffful, sync_regs +
+               HOST1X_SYNC_SYNCPT_THRESH_CPU1_INT_STATUS);
+}
+
+/**
+ * Sync point threshold interrupt service function
+ * Handles sync point threshold triggers, in interrupt context
+ */
+irqreturn_t t20_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;
+
+       writel(BIT(id),
+               sync_regs + HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE);
+       writel(BIT(id),
+               sync_regs + HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS);
+
+       return IRQ_WAKE_THREAD;
+}
+
+/**
+ * Host general interrupt service function
+ * Handles read / write failures
+ */
+static irqreturn_t t20_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;
+
+       stat = readl(sync_regs + HOST1X_SYNC_HINTSTATUS);
+       ext_stat = readl(sync_regs + HOST1X_SYNC_HINTSTATUS_EXT);
+
+       if (nvhost_sync_hintstatus_ext_ip_read_int(ext_stat)) {
+               addr = readl(sync_regs + HOST1X_SYNC_IP_READ_TIMEOUT_ADDR);
+               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);
+               pr_err("Host write timeout at address %x\n", addr);
+       }
+
+       writel(ext_stat, sync_regs + HOST1X_SYNC_HINTSTATUS_EXT);
+       writel(stat, sync_regs + HOST1X_SYNC_HINTSTATUS);
+
+       return IRQ_HANDLED;
+}
+static int t20_intr_request_host_general_irq(struct nvhost_intr *intr)
+{
+       void __iomem *sync_regs = intr_to_dev(intr)->sync_aperture;
+       int err;
+
+       if (intr->host_general_irq_requested)
+               return 0;
+
+       /* master disable for general (not syncpt) host interrupts */
+       writel(0, sync_regs + HOST1X_SYNC_INTMASK);
+
+       /* clear status & extstatus */
+       writel(0xfffffffful, sync_regs + HOST1X_SYNC_HINTSTATUS_EXT);
+       writel(0xfffffffful, sync_regs + HOST1X_SYNC_HINTSTATUS);
+
+       err = request_irq(intr->host_general_irq, t20_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);
+
+       /* enable extra interrupt sources */
+       writel(BIT(31), sync_regs + HOST1X_SYNC_HINTMASK);
+
+       /* enable host module interrupt to CPU0 */
+       writel(BIT(0), sync_regs + HOST1X_SYNC_INTC0MASK);
+
+       /* master enable for general (not syncpt) host interrupts */
+       writel(BIT(0), sync_regs + HOST1X_SYNC_INTMASK);
+
+       intr->host_general_irq_requested = true;
+
+       return err;
+}
+
+static void t20_intr_free_host_general_irq(struct nvhost_intr *intr)
+{
+       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);
+
+               free_irq(intr->host_general_irq, intr);
+               intr->host_general_irq_requested = false;
+       }
+}
+
+int nvhost_init_t20_intr_support(struct nvhost_master *host)
+{
+       host->op.intr.init_host_sync = t20_intr_init_host_sync;
+       host->op.intr.set_host_clocks_per_usec =
+               t20_intr_set_host_clocks_per_usec;
+       host->op.intr.set_syncpt_threshold = t20_intr_set_syncpt_threshold;
+       host->op.intr.enable_syncpt_intr = t20_intr_enable_syncpt_intr;
+       host->op.intr.disable_all_syncpt_intrs =
+               t20_intr_disable_all_syncpt_intrs;
+       host->op.intr.request_host_general_irq =
+               t20_intr_request_host_general_irq;
+       host->op.intr.free_host_general_irq =
+               t20_intr_free_host_general_irq;
+
+       return 0;
+}
diff --git a/drivers/video/tegra/host/t20/syncpt_t20.c b/drivers/video/tegra/host/t20/syncpt_t20.c
new file mode 100644 (file)
index 0000000..07fdb02
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * drivers/video/tegra/host/t20/syncpt_t20.c
+ *
+ * Tegra Graphics Host Syncpoints for T20
+ *
+ * Copyright (c) 2010-2011, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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 Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "../nvhost_syncpt.h"
+#include "../dev.h"
+
+#include "syncpt_t20.h"
+#include "hardware_t20.h"
+
+/**
+ * Write the current syncpoint value back to hw.
+ */
+static void t20_syncpt_reset(struct nvhost_syncpt *sp, u32 id)
+{
+       struct nvhost_master *dev = syncpt_to_dev(sp);
+       int min;
+       smp_rmb();
+       min = atomic_read(&sp->min_val[id]);
+       writel(min, dev->sync_aperture + (HOST1X_SYNC_SYNCPT_0 + id * 4));
+}
+
+/**
+ * Write the current waitbase value back to hw.
+ */
+static void t20_syncpt_reset_wait_base(struct nvhost_syncpt *sp, u32 id)
+{
+       struct nvhost_master *dev = syncpt_to_dev(sp);
+       writel(sp->base_val[id],
+               dev->sync_aperture + (HOST1X_SYNC_SYNCPT_BASE_0 + id * 4));
+}
+
+/**
+ * Read waitbase value from hw.
+ */
+static void t20_syncpt_read_wait_base(struct nvhost_syncpt *sp, u32 id)
+{
+       struct nvhost_master *dev = syncpt_to_dev(sp);
+       sp->base_val[id] = readl(dev->sync_aperture +
+                               (HOST1X_SYNC_SYNCPT_BASE_0 + id * 4));
+}
+
+/**
+ * Updates the last value read from hardware.
+ * (was nvhost_syncpt_update_min)
+ */
+static u32 t20_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;
+
+       do {
+               smp_rmb();
+               old = (u32)atomic_read(&sp->min_val[id]);
+               live = readl(sync_regs + (HOST1X_SYNC_SYNCPT_0 + id * 4));
+       } while ((u32)atomic_cmpxchg(&sp->min_val[id], old, live) != old);
+
+       BUG_ON(!nvhost_syncpt_check_max(sp, id, live));
+
+       return live;
+}
+
+/**
+ * Write a cpu syncpoint increment to the hardware, without touching
+ * the cache. Caller is responsible for host being powered.
+ */
+static void t20_syncpt_cpu_incr(struct nvhost_syncpt *sp, u32 id)
+{
+       struct nvhost_master *dev = syncpt_to_dev(sp);
+       BUG_ON(!nvhost_module_powered(&dev->mod));
+       BUG_ON(!client_managed(id) && nvhost_syncpt_min_eq_max(sp, id));
+       writel(BIT(id), dev->sync_aperture + HOST1X_SYNC_SYNCPT_CPU_INCR);
+       wmb();
+}
+
+/* returns true, if a <= b < c using wrapping comparison */
+static inline bool nvhost_syncpt_is_between(u32 a, u32 b, u32 c)
+{
+       return b-a < c-a;
+}
+
+/* returns true, if syncpt >= threshold (mod 1 << 32) */
+static bool nvhost_syncpt_wrapping_comparison(u32 syncpt, u32 threshold)
+{
+       return nvhost_syncpt_is_between(threshold, syncpt,
+                                       (1UL<<31UL)+threshold);
+}
+
+/* check for old WAITs to be removed (avoiding a wrap) */
+static int t20_syncpt_wait_check(struct nvhost_syncpt *sp,
+                                struct nvmap_client *nvmap,
+                                u32 waitchk_mask,
+                                struct nvhost_waitchk *wait,
+                                struct nvhost_waitchk *waitend)
+{
+       u32 idx;
+       int err = 0;
+
+       /* get current syncpt values */
+       for (idx = 0; idx < NV_HOST1X_SYNCPT_NB_PTS; idx++) {
+               if (BIT(idx) & waitchk_mask)
+                       nvhost_syncpt_update_min(sp, idx);
+       }
+
+       BUG_ON(!wait && !waitend);
+
+       /* compare syncpt vs wait threshold */
+       while (wait != waitend) {
+               u32 syncpt, override;
+
+               BUG_ON(wait->syncpt_id > NV_HOST1X_SYNCPT_NB_PTS);
+
+               syncpt = atomic_read(&sp->min_val[wait->syncpt_id]);
+               if (nvhost_syncpt_wrapping_comparison(syncpt, wait->thresh)) {
+                       /*
+                        * NULL an already satisfied WAIT_SYNCPT host method,
+                        * by patching its args in the command stream. The
+                        * method data is changed to reference a reserved
+                        * (never given out or incr) NVSYNCPT_GRAPHICS_HOST
+                        * syncpt with a matching threshold value of 0, so
+                        * is guaranteed to be popped by the host HW.
+                        */
+                       dev_dbg(&syncpt_to_dev(sp)->pdev->dev,
+                           "drop WAIT id %d (%s) thresh 0x%x, syncpt 0x%x\n",
+                           wait->syncpt_id,
+                           nvhost_syncpt_name(wait->syncpt_id),
+                           wait->thresh, syncpt);
+
+                       /* patch the wait */
+                       override = nvhost_class_host_wait_syncpt(
+                                       NVSYNCPT_GRAPHICS_HOST, 0);
+                       err = nvmap_patch_word(nvmap,
+                                       (struct nvmap_handle *)wait->mem,
+                                       wait->offset, override);
+                       if (err)
+                               break;
+               }
+               wait++;
+       }
+       return err;
+}
+
+
+static const char *s_syncpt_names[32] = {
+       "gfx_host", "", "", "", "", "", "", "", "", "", "",
+       "csi_vi_0", "csi_vi_1", "vi_isp_0", "vi_isp_1", "vi_isp_2", "vi_isp_3", "vi_isp_4",
+       "2d_0", "2d_1",
+       "", "",
+       "3d", "mpe", "disp0", "disp1", "vblank0", "vblank1", "mpe_ebm_eof", "mpe_wr_safe",
+       "2d_tinyblt", "dsi"
+};
+
+static const char *t20_syncpt_name(struct nvhost_syncpt *s, u32 id)
+{
+       BUG_ON(id > ARRAY_SIZE(s_syncpt_names));
+       return s_syncpt_names[id];
+}
+
+static void t20_syncpt_debug(struct nvhost_syncpt *sp)
+{
+       u32 i;
+       for (i = 0; i < NV_HOST1X_SYNCPT_NB_PTS; i++) {
+               u32 max = nvhost_syncpt_read_max(sp, i);
+               if (!max)
+                       continue;
+               dev_info(&syncpt_to_dev(sp)->pdev->dev,
+                       "id %d (%s) min %d max %d\n",
+                        i, syncpt_op(sp).name(sp, i),
+                       nvhost_syncpt_update_min(sp, i), max);
+
+       }
+}
+
+int nvhost_init_t20_syncpt_support(struct nvhost_master *host)
+{
+
+       host->sync_aperture = host->aperture +
+               (NV_HOST1X_CHANNEL0_BASE +
+                       HOST1X_CHANNEL_SYNC_REG_BASE);
+
+       host->op.syncpt.reset = t20_syncpt_reset;
+       host->op.syncpt.reset_wait_base = t20_syncpt_reset_wait_base;
+       host->op.syncpt.read_wait_base = t20_syncpt_read_wait_base;
+       host->op.syncpt.update_min = t20_syncpt_update_min;
+       host->op.syncpt.cpu_incr = t20_syncpt_cpu_incr;
+       host->op.syncpt.wait_check = t20_syncpt_wait_check;
+       host->op.syncpt.debug = t20_syncpt_debug;
+       host->op.syncpt.name = t20_syncpt_name;
+
+       host->syncpt.nb_pts = NV_HOST1X_SYNCPT_NB_PTS;
+       host->syncpt.nb_bases = NV_HOST1X_SYNCPT_NB_BASES;
+       host->syncpt.client_managed = NVSYNCPTS_CLIENT_MANAGED;
+
+       return 0;
+}
diff --git a/drivers/video/tegra/host/t20/syncpt_t20.h b/drivers/video/tegra/host/t20/syncpt_t20.h
new file mode 100644 (file)
index 0000000..5c7c04c
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * drivers/video/tegra/host/t20/syncpt_t20.h
+ *
+ * Tegra Graphics Host Syncpoints for T20
+ *
+ * Copyright (c) 2010-2011, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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 Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __NVHOST_SYNCPT_T20_H
+#define __NVHOST_SYNCPT_T20_H
+
+#define NVSYNCPT_CSI_VI_0                   (11)
+#define NVSYNCPT_CSI_VI_1                   (12)
+#define NVSYNCPT_VI_ISP_0                   (13)
+#define NVSYNCPT_VI_ISP_1                   (14)
+#define NVSYNCPT_VI_ISP_2                   (15)
+#define NVSYNCPT_VI_ISP_3                   (16)
+#define NVSYNCPT_VI_ISP_4                   (17)
+#define NVSYNCPT_2D_0                       (18)
+#define NVSYNCPT_2D_1                       (19)
+#define NVSYNCPT_3D                         (22)
+#define NVSYNCPT_MPE                        (23)
+#define NVSYNCPT_DISP0                      (24)
+#define NVSYNCPT_DISP1                      (25)
+#define NVSYNCPT_VBLANK0                    (26)
+#define NVSYNCPT_VBLANK1                    (27)
+#define NVSYNCPT_MPE_EBM_EOF                (28)
+#define NVSYNCPT_MPE_WR_SAFE                (29)
+#define NVSYNCPT_DSI                        (31)
+
+
+/*#define NVSYNCPT_2D_CHANNEL2_0    (20) */
+/*#define NVSYNCPT_2D_CHANNEL2_1    (21) */
+/*#define NVSYNCPT_2D_TINYBLT_WAR                   (30)*/
+/*#define NVSYNCPT_2D_TINYBLT_RESTORE_CLASS_ID (30)*/
+
+/* sync points that are wholly managed by the client */
+#define NVSYNCPTS_CLIENT_MANAGED ( \
+       BIT(NVSYNCPT_DISP0) | BIT(NVSYNCPT_DISP1) | BIT(NVSYNCPT_DSI) | \
+       BIT(NVSYNCPT_CSI_VI_0) | BIT(NVSYNCPT_CSI_VI_1) | \
+       BIT(NVSYNCPT_VI_ISP_1) | BIT(NVSYNCPT_VI_ISP_2) | \
+       BIT(NVSYNCPT_VI_ISP_3) | BIT(NVSYNCPT_VI_ISP_4) | \
+       BIT(NVSYNCPT_MPE_EBM_EOF) | BIT(NVSYNCPT_MPE_WR_SAFE) | \
+       BIT(NVSYNCPT_2D_1))
+
+
+#define NVWAITBASE_2D_0 (1)
+#define NVWAITBASE_2D_1 (2)
+#define NVWAITBASE_3D   (3)
+#define NVWAITBASE_MPE  (4)
+
+int nvhost_t20_init_syncpt(struct nvhost_master *host);
+
+#endif /* __NVHOST_SYNCPT_T20_H */
diff --git a/drivers/video/tegra/host/t20/t20.c b/drivers/video/tegra/host/t20/t20.c
new file mode 100644 (file)
index 0000000..c846ce7
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * drivers/video/tegra/host/t20/t20.c
+ *
+ * Tegra Graphics Init for T20 Architecture Chips
+ *
+ * Copyright (c) 2011, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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 Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "../dev.h"
+
+#include "t20.h"
+
+int nvhost_init_t20_support(struct nvhost_master *host)
+{
+       int err;
+
+       /* don't worry about cleaning up on failure... "remove" does it. */
+       err = nvhost_init_t20_channel_support(host);
+       if (err)
+               return err;
+       err = nvhost_init_t20_cdma_support(host);
+       if (err)
+               return err;
+       err = nvhost_init_t20_debug_support(host);
+       if (err)
+               return err;
+       err = nvhost_init_t20_syncpt_support(host);
+       if (err)
+               return err;
+       err = nvhost_init_t20_intr_support(host);
+       if (err)
+               return err;
+       err = nvhost_init_t20_cpuaccess_support(host);
+       if (err)
+               return err;
+       return 0;
+}
diff --git a/drivers/video/tegra/host/t20/t20.h b/drivers/video/tegra/host/t20/t20.h
new file mode 100644 (file)
index 0000000..8a8426c
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * drivers/video/tegra/host/t20/t20.h
+ *
+ * Tegra Graphics Chip support for T20
+ *
+ * Copyright (c) 2011, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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 Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef _NVHOST_T20_H_
+#define _NVHOST_T20_H_
+
+int nvhost_init_t20_channel_support(struct nvhost_master *);
+int nvhost_init_t20_cdma_support(struct nvhost_master *);
+int nvhost_init_t20_debug_support(struct nvhost_master *);
+int nvhost_init_t20_syncpt_support(struct nvhost_master *);
+int nvhost_init_t20_intr_support(struct nvhost_master *);
+int nvhost_init_t20_cpuaccess_support(struct nvhost_master *);
+
+#endif /* _NVHOST_T20_H_ */
diff --git a/drivers/video/tegra/host/t30/Makefile b/drivers/video/tegra/host/t30/Makefile
new file mode 100644 (file)
index 0000000..f394706
--- /dev/null
@@ -0,0 +1,4 @@
+nvhost-t30-objs  = \
+       t30.o
+
+obj-$(CONFIG_TEGRA_GRHOST) += nvhost-t30.o
diff --git a/drivers/video/tegra/host/t30/t30.c b/drivers/video/tegra/host/t30/t30.c
new file mode 100644 (file)
index 0000000..5185541
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * drivers/video/tegra/host/t30/t30.c
+ *
+ * Tegra Graphics Init for T30 Architecture Chips
+ *
+ * Copyright (c) 2011, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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 Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "../dev.h"
+
+/* t30 uses t20 entry points */
+#include "../t20/t20.h"
+
+#if defined(CONFIG_ARCH_TEGRA_3x_SOC)
+int nvhost_init_t30_support(struct nvhost_master *host)
+{
+       int err;
+
+       /* don't worry about cleaning up on failure... "remove" does it. */
+       err = nvhost_init_t20_channel_support(host);
+       if (err)
+               return err;
+       err = nvhost_init_t20_cdma_support(host);
+       if (err)
+               return err;
+       err = nvhost_init_t20_debug_support(host);
+       if (err)
+               return err;
+       err = nvhost_init_t20_syncpt_support(host);
+       if (err)
+               return err;
+       err = nvhost_init_t20_intr_support(host);
+       if (err)
+               return err;
+       err = nvhost_init_t20_cpuaccess_support(host);
+       if (err)
+               return err;
+       return 0;
+}
+#endif