From: Christian Gmeiner <christian.gmei...@gmail.com>

This is a consolidation by Russell King of Christian's drm work.

Signed-off-by: Christian Gmeiner <christian.gmeiner at gmail.com>
Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk>
---
 drivers/staging/Kconfig                      |   2 +
 drivers/staging/Makefile                     |   1 +
 drivers/staging/etnaviv/Kconfig              |  20 +
 drivers/staging/etnaviv/Makefile             |  17 +
 drivers/staging/etnaviv/cmdstream.xml.h      | 218 ++++++
 drivers/staging/etnaviv/common.xml.h         | 253 +++++++
 drivers/staging/etnaviv/etnaviv_buffer.c     | 201 ++++++
 drivers/staging/etnaviv/etnaviv_drv.c        | 621 +++++++++++++++++
 drivers/staging/etnaviv/etnaviv_drv.h        | 143 ++++
 drivers/staging/etnaviv/etnaviv_gem.c        | 706 +++++++++++++++++++
 drivers/staging/etnaviv/etnaviv_gem.h        | 100 +++
 drivers/staging/etnaviv/etnaviv_gem_prime.c  |  56 ++
 drivers/staging/etnaviv/etnaviv_gem_submit.c | 407 +++++++++++
 drivers/staging/etnaviv/etnaviv_gpu.c        | 984 +++++++++++++++++++++++++++
 drivers/staging/etnaviv/etnaviv_gpu.h        | 152 +++++
 drivers/staging/etnaviv/etnaviv_iommu.c      | 185 +++++
 drivers/staging/etnaviv/etnaviv_iommu.h      |  25 +
 drivers/staging/etnaviv/etnaviv_iommu_v2.c   |  32 +
 drivers/staging/etnaviv/etnaviv_iommu_v2.h   |  25 +
 drivers/staging/etnaviv/etnaviv_mmu.c        | 111 +++
 drivers/staging/etnaviv/etnaviv_mmu.h        |  37 +
 drivers/staging/etnaviv/state.xml.h          | 348 ++++++++++
 drivers/staging/etnaviv/state_hi.xml.h       | 405 +++++++++++
 include/uapi/drm/etnaviv_drm.h               | 225 ++++++
 24 files changed, 5274 insertions(+)
 create mode 100644 drivers/staging/etnaviv/Kconfig
 create mode 100644 drivers/staging/etnaviv/Makefile
 create mode 100644 drivers/staging/etnaviv/cmdstream.xml.h
 create mode 100644 drivers/staging/etnaviv/common.xml.h
 create mode 100644 drivers/staging/etnaviv/etnaviv_buffer.c
 create mode 100644 drivers/staging/etnaviv/etnaviv_drv.c
 create mode 100644 drivers/staging/etnaviv/etnaviv_drv.h
 create mode 100644 drivers/staging/etnaviv/etnaviv_gem.c
 create mode 100644 drivers/staging/etnaviv/etnaviv_gem.h
 create mode 100644 drivers/staging/etnaviv/etnaviv_gem_prime.c
 create mode 100644 drivers/staging/etnaviv/etnaviv_gem_submit.c
 create mode 100644 drivers/staging/etnaviv/etnaviv_gpu.c
 create mode 100644 drivers/staging/etnaviv/etnaviv_gpu.h
 create mode 100644 drivers/staging/etnaviv/etnaviv_iommu.c
 create mode 100644 drivers/staging/etnaviv/etnaviv_iommu.h
 create mode 100644 drivers/staging/etnaviv/etnaviv_iommu_v2.c
 create mode 100644 drivers/staging/etnaviv/etnaviv_iommu_v2.h
 create mode 100644 drivers/staging/etnaviv/etnaviv_mmu.c
 create mode 100644 drivers/staging/etnaviv/etnaviv_mmu.h
 create mode 100644 drivers/staging/etnaviv/state.xml.h
 create mode 100644 drivers/staging/etnaviv/state_hi.xml.h
 create mode 100644 include/uapi/drm/etnaviv_drm.h

diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 45baa83be7ce..441b1afbfe4c 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -108,4 +108,6 @@ source "drivers/staging/fbtft/Kconfig"

 source "drivers/staging/i2o/Kconfig"

+source "drivers/staging/etnaviv/Kconfig"
+
 endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 29160790841f..f53cf8412c0c 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -46,3 +46,4 @@ obj-$(CONFIG_UNISYSSPAR)      += unisys/
 obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD)  += clocking-wizard/
 obj-$(CONFIG_FB_TFT)           += fbtft/
 obj-$(CONFIG_I2O)              += i2o/
+obj-$(CONFIG_DRM_ETNAVIV)      += etnaviv/
diff --git a/drivers/staging/etnaviv/Kconfig b/drivers/staging/etnaviv/Kconfig
new file mode 100644
index 000000000000..6f034eda914c
--- /dev/null
+++ b/drivers/staging/etnaviv/Kconfig
@@ -0,0 +1,20 @@
+
+config DRM_ETNAVIV
+       tristate "etnaviv DRM"
+       depends on DRM
+       select SHMEM
+       select TMPFS
+       select IOMMU_API
+       select IOMMU_SUPPORT
+       default y
+       help
+         DRM driver for Vivante GPUs.
+
+config DRM_ETNAVIV_REGISTER_LOGGING
+       bool "etnaviv DRM register logging"
+       depends on DRM_ETNAVIV
+       default n
+       help
+         Compile in support for logging register reads/writes in a format
+         that can be parsed by envytools demsm tool.  If enabled, register
+         logging can be switched on via etnaviv.reglog=y module param.
diff --git a/drivers/staging/etnaviv/Makefile b/drivers/staging/etnaviv/Makefile
new file mode 100644
index 000000000000..ef0cffabdcce
--- /dev/null
+++ b/drivers/staging/etnaviv/Makefile
@@ -0,0 +1,17 @@
+ccflags-y := -Iinclude/drm -Idrivers/staging/vivante
+ifeq (, $(findstring -W,$(EXTRA_CFLAGS)))
+       ccflags-y += -Werror
+endif
+
+etnaviv-y := \
+       etnaviv_drv.o \
+       etnaviv_gem.o \
+       etnaviv_gem_prime.o \
+       etnaviv_gem_submit.o \
+       etnaviv_gpu.o \
+       etnaviv_iommu.o \
+       etnaviv_iommu_v2.o \
+       etnaviv_mmu.o \
+       etnaviv_buffer.o
+
+obj-$(CONFIG_DRM_ETNAVIV)      += etnaviv.o
diff --git a/drivers/staging/etnaviv/cmdstream.xml.h 
b/drivers/staging/etnaviv/cmdstream.xml.h
new file mode 100644
index 000000000000..844f82977e3e
--- /dev/null
+++ b/drivers/staging/etnaviv/cmdstream.xml.h
@@ -0,0 +1,218 @@
+#ifndef CMDSTREAM_XML
+#define CMDSTREAM_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git 
repository:
+http://0x04.net/cgit/index.cgi/rules-ng-ng
+git clone git://0x04.net/rules-ng-ng
+
+The rules-ng-ng source files this header was generated from are:
+- /home/orion/projects/etna_viv/rnndb/cmdstream.xml (  12589 bytes, from 
2013-09-01 10:53:22)
+- /home/orion/projects/etna_viv/rnndb/common.xml    (  18379 bytes, from 
2014-01-27 15:58:05)
+
+Copyright (C) 2013
+*/
+
+
+#define FE_OPCODE_LOAD_STATE                                   0x00000001
+#define FE_OPCODE_END                                          0x00000002
+#define FE_OPCODE_NOP                                          0x00000003
+#define FE_OPCODE_DRAW_2D                                      0x00000004
+#define FE_OPCODE_DRAW_PRIMITIVES                              0x00000005
+#define FE_OPCODE_DRAW_INDEXED_PRIMITIVES                      0x00000006
+#define FE_OPCODE_WAIT                                         0x00000007
+#define FE_OPCODE_LINK                                         0x00000008
+#define FE_OPCODE_STALL                                                
0x00000009
+#define FE_OPCODE_CALL                                         0x0000000a
+#define FE_OPCODE_RETURN                                       0x0000000b
+#define FE_OPCODE_CHIP_SELECT                                  0x0000000d
+#define PRIMITIVE_TYPE_POINTS                                  0x00000001
+#define PRIMITIVE_TYPE_LINES                                   0x00000002
+#define PRIMITIVE_TYPE_LINE_STRIP                              0x00000003
+#define PRIMITIVE_TYPE_TRIANGLES                               0x00000004
+#define PRIMITIVE_TYPE_TRIANGLE_STRIP                          0x00000005
+#define PRIMITIVE_TYPE_TRIANGLE_FAN                            0x00000006
+#define PRIMITIVE_TYPE_LINE_LOOP                               0x00000007
+#define PRIMITIVE_TYPE_QUADS                                   0x00000008
+#define VIV_FE_LOAD_STATE                                      0x00000000
+
+#define VIV_FE_LOAD_STATE_HEADER                               0x00000000
+#define VIV_FE_LOAD_STATE_HEADER_OP__MASK                      0xf8000000
+#define VIV_FE_LOAD_STATE_HEADER_OP__SHIFT                     27
+#define VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE                 0x08000000
+#define VIV_FE_LOAD_STATE_HEADER_FIXP                          0x04000000
+#define VIV_FE_LOAD_STATE_HEADER_COUNT__MASK                   0x03ff0000
+#define VIV_FE_LOAD_STATE_HEADER_COUNT__SHIFT                  16
+#define VIV_FE_LOAD_STATE_HEADER_COUNT(x)                      (((x) << 
VIV_FE_LOAD_STATE_HEADER_COUNT__SHIFT) & VIV_FE_LOAD_STATE_HEADER_COUNT__MASK)
+#define VIV_FE_LOAD_STATE_HEADER_OFFSET__MASK                  0x0000ffff
+#define VIV_FE_LOAD_STATE_HEADER_OFFSET__SHIFT                 0
+#define VIV_FE_LOAD_STATE_HEADER_OFFSET(x)                     (((x) << 
VIV_FE_LOAD_STATE_HEADER_OFFSET__SHIFT) & VIV_FE_LOAD_STATE_HEADER_OFFSET__MASK)
+#define VIV_FE_LOAD_STATE_HEADER_OFFSET__SHR                   2
+
+#define VIV_FE_END                                             0x00000000
+
+#define VIV_FE_END_HEADER                                      0x00000000
+#define VIV_FE_END_HEADER_EVENT_ID__MASK                       0x0000001f
+#define VIV_FE_END_HEADER_EVENT_ID__SHIFT                      0
+#define VIV_FE_END_HEADER_EVENT_ID(x)                          (((x) << 
VIV_FE_END_HEADER_EVENT_ID__SHIFT) & VIV_FE_END_HEADER_EVENT_ID__MASK)
+#define VIV_FE_END_HEADER_EVENT_ENABLE                         0x00000100
+#define VIV_FE_END_HEADER_OP__MASK                             0xf8000000
+#define VIV_FE_END_HEADER_OP__SHIFT                            27
+#define VIV_FE_END_HEADER_OP_END                               0x10000000
+
+#define VIV_FE_NOP                                             0x00000000
+
+#define VIV_FE_NOP_HEADER                                      0x00000000
+#define VIV_FE_NOP_HEADER_OP__MASK                             0xf8000000
+#define VIV_FE_NOP_HEADER_OP__SHIFT                            27
+#define VIV_FE_NOP_HEADER_OP_NOP                               0x18000000
+
+#define VIV_FE_DRAW_2D                                         0x00000000
+
+#define VIV_FE_DRAW_2D_HEADER                                  0x00000000
+#define VIV_FE_DRAW_2D_HEADER_COUNT__MASK                      0x0000ff00
+#define VIV_FE_DRAW_2D_HEADER_COUNT__SHIFT                     8
+#define VIV_FE_DRAW_2D_HEADER_COUNT(x)                         (((x) << 
VIV_FE_DRAW_2D_HEADER_COUNT__SHIFT) & VIV_FE_DRAW_2D_HEADER_COUNT__MASK)
+#define VIV_FE_DRAW_2D_HEADER_DATA_COUNT__MASK                 0x07ff0000
+#define VIV_FE_DRAW_2D_HEADER_DATA_COUNT__SHIFT                        16
+#define VIV_FE_DRAW_2D_HEADER_DATA_COUNT(x)                    (((x) << 
VIV_FE_DRAW_2D_HEADER_DATA_COUNT__SHIFT) & 
VIV_FE_DRAW_2D_HEADER_DATA_COUNT__MASK)
+#define VIV_FE_DRAW_2D_HEADER_OP__MASK                         0xf8000000
+#define VIV_FE_DRAW_2D_HEADER_OP__SHIFT                                27
+#define VIV_FE_DRAW_2D_HEADER_OP_DRAW_2D                       0x20000000
+
+#define VIV_FE_DRAW_2D_TOP_LEFT                                        
0x00000008
+#define VIV_FE_DRAW_2D_TOP_LEFT_X__MASK                                
0x0000ffff
+#define VIV_FE_DRAW_2D_TOP_LEFT_X__SHIFT                       0
+#define VIV_FE_DRAW_2D_TOP_LEFT_X(x)                           (((x) << 
VIV_FE_DRAW_2D_TOP_LEFT_X__SHIFT) & VIV_FE_DRAW_2D_TOP_LEFT_X__MASK)
+#define VIV_FE_DRAW_2D_TOP_LEFT_Y__MASK                                
0xffff0000
+#define VIV_FE_DRAW_2D_TOP_LEFT_Y__SHIFT                       16
+#define VIV_FE_DRAW_2D_TOP_LEFT_Y(x)                           (((x) << 
VIV_FE_DRAW_2D_TOP_LEFT_Y__SHIFT) & VIV_FE_DRAW_2D_TOP_LEFT_Y__MASK)
+
+#define VIV_FE_DRAW_2D_BOTTOM_RIGHT                            0x0000000c
+#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_X__MASK                    0x0000ffff
+#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_X__SHIFT                   0
+#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_X(x)                       (((x) << 
VIV_FE_DRAW_2D_BOTTOM_RIGHT_X__SHIFT) & VIV_FE_DRAW_2D_BOTTOM_RIGHT_X__MASK)
+#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y__MASK                    0xffff0000
+#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y__SHIFT                   16
+#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y(x)                       (((x) << 
VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y__SHIFT) & VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y__MASK)
+
+#define VIV_FE_DRAW_PRIMITIVES                                 0x00000000
+
+#define VIV_FE_DRAW_PRIMITIVES_HEADER                          0x00000000
+#define VIV_FE_DRAW_PRIMITIVES_HEADER_OP__MASK                 0xf8000000
+#define VIV_FE_DRAW_PRIMITIVES_HEADER_OP__SHIFT                        27
+#define VIV_FE_DRAW_PRIMITIVES_HEADER_OP_DRAW_PRIMITIVES       0x28000000
+
+#define VIV_FE_DRAW_PRIMITIVES_COMMAND                         0x00000004
+#define VIV_FE_DRAW_PRIMITIVES_COMMAND_TYPE__MASK              0x000000ff
+#define VIV_FE_DRAW_PRIMITIVES_COMMAND_TYPE__SHIFT             0
+#define VIV_FE_DRAW_PRIMITIVES_COMMAND_TYPE(x)                 (((x) << 
VIV_FE_DRAW_PRIMITIVES_COMMAND_TYPE__SHIFT) & 
VIV_FE_DRAW_PRIMITIVES_COMMAND_TYPE__MASK)
+
+#define VIV_FE_DRAW_PRIMITIVES_START                           0x00000008
+
+#define VIV_FE_DRAW_PRIMITIVES_COUNT                           0x0000000c
+
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES                         0x00000000
+
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_HEADER                  0x00000000
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_HEADER_OP__MASK         0xf8000000
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_HEADER_OP__SHIFT                27
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_HEADER_OP_DRAW_INDEXED_PRIMITIVES       
0x30000000
+
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND                 0x00000004
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND_TYPE__MASK      0x000000ff
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND_TYPE__SHIFT     0
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND_TYPE(x)         (((x) << 
VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND_TYPE__SHIFT) & 
VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND_TYPE__MASK)
+
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_START                   0x00000008
+
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_COUNT                   0x0000000c
+
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_OFFSET                  0x00000010
+
+#define VIV_FE_WAIT                                            0x00000000
+
+#define VIV_FE_WAIT_HEADER                                     0x00000000
+#define VIV_FE_WAIT_HEADER_DELAY__MASK                         0x0000ffff
+#define VIV_FE_WAIT_HEADER_DELAY__SHIFT                                0
+#define VIV_FE_WAIT_HEADER_DELAY(x)                            (((x) << 
VIV_FE_WAIT_HEADER_DELAY__SHIFT) & VIV_FE_WAIT_HEADER_DELAY__MASK)
+#define VIV_FE_WAIT_HEADER_OP__MASK                            0xf8000000
+#define VIV_FE_WAIT_HEADER_OP__SHIFT                           27
+#define VIV_FE_WAIT_HEADER_OP_WAIT                             0x38000000
+
+#define VIV_FE_LINK                                            0x00000000
+
+#define VIV_FE_LINK_HEADER                                     0x00000000
+#define VIV_FE_LINK_HEADER_PREFETCH__MASK                      0x0000ffff
+#define VIV_FE_LINK_HEADER_PREFETCH__SHIFT                     0
+#define VIV_FE_LINK_HEADER_PREFETCH(x)                         (((x) << 
VIV_FE_LINK_HEADER_PREFETCH__SHIFT) & VIV_FE_LINK_HEADER_PREFETCH__MASK)
+#define VIV_FE_LINK_HEADER_OP__MASK                            0xf8000000
+#define VIV_FE_LINK_HEADER_OP__SHIFT                           27
+#define VIV_FE_LINK_HEADER_OP_LINK                             0x40000000
+
+#define VIV_FE_LINK_ADDRESS                                    0x00000004
+
+#define VIV_FE_STALL                                           0x00000000
+
+#define VIV_FE_STALL_HEADER                                    0x00000000
+#define VIV_FE_STALL_HEADER_OP__MASK                           0xf8000000
+#define VIV_FE_STALL_HEADER_OP__SHIFT                          27
+#define VIV_FE_STALL_HEADER_OP_STALL                           0x48000000
+
+#define VIV_FE_STALL_TOKEN                                     0x00000004
+#define VIV_FE_STALL_TOKEN_FROM__MASK                          0x0000001f
+#define VIV_FE_STALL_TOKEN_FROM__SHIFT                         0
+#define VIV_FE_STALL_TOKEN_FROM(x)                             (((x) << 
VIV_FE_STALL_TOKEN_FROM__SHIFT) & VIV_FE_STALL_TOKEN_FROM__MASK)
+#define VIV_FE_STALL_TOKEN_TO__MASK                            0x00001f00
+#define VIV_FE_STALL_TOKEN_TO__SHIFT                           8
+#define VIV_FE_STALL_TOKEN_TO(x)                               (((x) << 
VIV_FE_STALL_TOKEN_TO__SHIFT) & VIV_FE_STALL_TOKEN_TO__MASK)
+
+#define VIV_FE_CALL                                            0x00000000
+
+#define VIV_FE_CALL_HEADER                                     0x00000000
+#define VIV_FE_CALL_HEADER_PREFETCH__MASK                      0x0000ffff
+#define VIV_FE_CALL_HEADER_PREFETCH__SHIFT                     0
+#define VIV_FE_CALL_HEADER_PREFETCH(x)                         (((x) << 
VIV_FE_CALL_HEADER_PREFETCH__SHIFT) & VIV_FE_CALL_HEADER_PREFETCH__MASK)
+#define VIV_FE_CALL_HEADER_OP__MASK                            0xf8000000
+#define VIV_FE_CALL_HEADER_OP__SHIFT                           27
+#define VIV_FE_CALL_HEADER_OP_CALL                             0x50000000
+
+#define VIV_FE_CALL_ADDRESS                                    0x00000004
+
+#define VIV_FE_CALL_RETURN_PREFETCH                            0x00000008
+
+#define VIV_FE_CALL_RETURN_ADDRESS                             0x0000000c
+
+#define VIV_FE_RETURN                                          0x00000000
+
+#define VIV_FE_RETURN_HEADER                                   0x00000000
+#define VIV_FE_RETURN_HEADER_OP__MASK                          0xf8000000
+#define VIV_FE_RETURN_HEADER_OP__SHIFT                         27
+#define VIV_FE_RETURN_HEADER_OP_RETURN                         0x58000000
+
+#define VIV_FE_CHIP_SELECT                                     0x00000000
+
+#define VIV_FE_CHIP_SELECT_HEADER                              0x00000000
+#define VIV_FE_CHIP_SELECT_HEADER_OP__MASK                     0xf8000000
+#define VIV_FE_CHIP_SELECT_HEADER_OP__SHIFT                    27
+#define VIV_FE_CHIP_SELECT_HEADER_OP_CHIP_SELECT               0x68000000
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP15                        
0x00008000
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP14                        
0x00004000
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP13                        
0x00002000
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP12                        
0x00001000
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP11                        
0x00000800
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP10                        
0x00000400
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP9                 0x00000200
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP8                 0x00000100
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP7                 0x00000080
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP6                 0x00000040
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP5                 0x00000020
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP4                 0x00000010
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP3                 0x00000008
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP2                 0x00000004
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP1                 0x00000002
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP0                 0x00000001
+
+
+#endif /* CMDSTREAM_XML */
diff --git a/drivers/staging/etnaviv/common.xml.h 
b/drivers/staging/etnaviv/common.xml.h
new file mode 100644
index 000000000000..36fa0e4cf56b
--- /dev/null
+++ b/drivers/staging/etnaviv/common.xml.h
@@ -0,0 +1,253 @@
+#ifndef COMMON_XML
+#define COMMON_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git 
repository:
+http://0x04.net/cgit/index.cgi/rules-ng-ng
+git clone git://0x04.net/rules-ng-ng
+
+The rules-ng-ng source files this header was generated from are:
+- /home/orion/projects/etna_viv/rnndb/state.xml    (  18526 bytes, from 
2013-09-11 16:52:32)
+- /home/orion/projects/etna_viv/rnndb/common.xml   (  18379 bytes, from 
2014-01-27 15:58:05)
+- /home/orion/projects/etna_viv/rnndb/state_hi.xml (  22236 bytes, from 
2014-01-27 15:56:46)
+- /home/orion/projects/etna_viv/rnndb/state_2d.xml (  51191 bytes, from 
2013-10-04 06:36:55)
+- /home/orion/projects/etna_viv/rnndb/state_3d.xml (  54570 bytes, from 
2013-10-12 15:25:03)
+- /home/orion/projects/etna_viv/rnndb/state_vg.xml (   5942 bytes, from 
2013-09-01 10:53:22)
+
+Copyright (C) 2014
+*/
+
+
+#define PIPE_ID_PIPE_3D                                                
0x00000000
+#define PIPE_ID_PIPE_2D                                                
0x00000001
+#define SYNC_RECIPIENT_FE                                      0x00000001
+#define SYNC_RECIPIENT_RA                                      0x00000005
+#define SYNC_RECIPIENT_PE                                      0x00000007
+#define SYNC_RECIPIENT_DE                                      0x0000000b
+#define SYNC_RECIPIENT_VG                                      0x0000000f
+#define SYNC_RECIPIENT_TESSELATOR                              0x00000010
+#define SYNC_RECIPIENT_VG2                                     0x00000011
+#define SYNC_RECIPIENT_TESSELATOR2                             0x00000012
+#define SYNC_RECIPIENT_VG3                                     0x00000013
+#define SYNC_RECIPIENT_TESSELATOR3                             0x00000014
+#define ENDIAN_MODE_NO_SWAP                                    0x00000000
+#define ENDIAN_MODE_SWAP_16                                    0x00000001
+#define ENDIAN_MODE_SWAP_32                                    0x00000002
+#define chipModel_GC300                                                
0x00000300
+#define chipModel_GC320                                                
0x00000320
+#define chipModel_GC350                                                
0x00000350
+#define chipModel_GC355                                                
0x00000355
+#define chipModel_GC400                                                
0x00000400
+#define chipModel_GC410                                                
0x00000410
+#define chipModel_GC420                                                
0x00000420
+#define chipModel_GC450                                                
0x00000450
+#define chipModel_GC500                                                
0x00000500
+#define chipModel_GC530                                                
0x00000530
+#define chipModel_GC600                                                
0x00000600
+#define chipModel_GC700                                                
0x00000700
+#define chipModel_GC800                                                
0x00000800
+#define chipModel_GC860                                                
0x00000860
+#define chipModel_GC880                                                
0x00000880
+#define chipModel_GC1000                                       0x00001000
+#define chipModel_GC2000                                       0x00002000
+#define chipModel_GC2100                                       0x00002100
+#define chipModel_GC4000                                       0x00004000
+#define RGBA_BITS_R                                            0x00000001
+#define RGBA_BITS_G                                            0x00000002
+#define RGBA_BITS_B                                            0x00000004
+#define RGBA_BITS_A                                            0x00000008
+#define chipFeatures_FAST_CLEAR                                        
0x00000001
+#define chipFeatures_SPECIAL_ANTI_ALIASING                     0x00000002
+#define chipFeatures_PIPE_3D                                   0x00000004
+#define chipFeatures_DXT_TEXTURE_COMPRESSION                   0x00000008
+#define chipFeatures_DEBUG_MODE                                        
0x00000010
+#define chipFeatures_Z_COMPRESSION                             0x00000020
+#define chipFeatures_YUV420_SCALER                             0x00000040
+#define chipFeatures_MSAA                                      0x00000080
+#define chipFeatures_DC                                                
0x00000100
+#define chipFeatures_PIPE_2D                                   0x00000200
+#define chipFeatures_ETC1_TEXTURE_COMPRESSION                  0x00000400
+#define chipFeatures_FAST_SCALER                               0x00000800
+#define chipFeatures_HIGH_DYNAMIC_RANGE                                
0x00001000
+#define chipFeatures_YUV420_TILER                              0x00002000
+#define chipFeatures_MODULE_CG                                 0x00004000
+#define chipFeatures_MIN_AREA                                  0x00008000
+#define chipFeatures_NO_EARLY_Z                                        
0x00010000
+#define chipFeatures_NO_422_TEXTURE                            0x00020000
+#define chipFeatures_BUFFER_INTERLEAVING                       0x00040000
+#define chipFeatures_BYTE_WRITE_2D                             0x00080000
+#define chipFeatures_NO_SCALER                                 0x00100000
+#define chipFeatures_YUY2_AVERAGING                            0x00200000
+#define chipFeatures_HALF_PE_CACHE                             0x00400000
+#define chipFeatures_HALF_TX_CACHE                             0x00800000
+#define chipFeatures_YUY2_RENDER_TARGET                                
0x01000000
+#define chipFeatures_MEM32                                     0x02000000
+#define chipFeatures_PIPE_VG                                   0x04000000
+#define chipFeatures_VGTS                                      0x08000000
+#define chipFeatures_FE20                                      0x10000000
+#define chipFeatures_BYTE_WRITE_3D                             0x20000000
+#define chipFeatures_RS_YUV_TARGET                             0x40000000
+#define chipFeatures_32_BIT_INDICES                            0x80000000
+#define chipMinorFeatures0_FLIP_Y                              0x00000001
+#define chipMinorFeatures0_DUAL_RETURN_BUS                     0x00000002
+#define chipMinorFeatures0_ENDIANNESS_CONFIG                   0x00000004
+#define chipMinorFeatures0_TEXTURE_8K                          0x00000008
+#define chipMinorFeatures0_CORRECT_TEXTURE_CONVERTER           0x00000010
+#define chipMinorFeatures0_SPECIAL_MSAA_LOD                    0x00000020
+#define chipMinorFeatures0_FAST_CLEAR_FLUSH                    0x00000040
+#define chipMinorFeatures0_2DPE20                              0x00000080
+#define chipMinorFeatures0_CORRECT_AUTO_DISABLE                        
0x00000100
+#define chipMinorFeatures0_RENDERTARGET_8K                     0x00000200
+#define chipMinorFeatures0_2BITPERTILE                         0x00000400
+#define chipMinorFeatures0_SEPARATE_TILE_STATUS_WHEN_INTERLEAVED       
0x00000800
+#define chipMinorFeatures0_SUPER_TILED                         0x00001000
+#define chipMinorFeatures0_VG_20                               0x00002000
+#define chipMinorFeatures0_TS_EXTENDED_COMMANDS                        
0x00004000
+#define chipMinorFeatures0_COMPRESSION_FIFO_FIXED              0x00008000
+#define chipMinorFeatures0_HAS_SIGN_FLOOR_CEIL                 0x00010000
+#define chipMinorFeatures0_VG_FILTER                           0x00020000
+#define chipMinorFeatures0_VG_21                               0x00040000
+#define chipMinorFeatures0_SHADER_HAS_W                                
0x00080000
+#define chipMinorFeatures0_HAS_SQRT_TRIG                       0x00100000
+#define chipMinorFeatures0_MORE_MINOR_FEATURES                 0x00200000
+#define chipMinorFeatures0_MC20                                        
0x00400000
+#define chipMinorFeatures0_MSAA_SIDEBAND                       0x00800000
+#define chipMinorFeatures0_BUG_FIXES0                          0x01000000
+#define chipMinorFeatures0_VAA                                 0x02000000
+#define chipMinorFeatures0_BYPASS_IN_MSAA                      0x04000000
+#define chipMinorFeatures0_HZ                                  0x08000000
+#define chipMinorFeatures0_NEW_TEXTURE                         0x10000000
+#define chipMinorFeatures0_2D_A8_TARGET                                
0x20000000
+#define chipMinorFeatures0_CORRECT_STENCIL                     0x40000000
+#define chipMinorFeatures0_ENHANCE_VR                          0x80000000
+#define chipMinorFeatures1_RSUV_SWIZZLE                                
0x00000001
+#define chipMinorFeatures1_V2_COMPRESSION                      0x00000002
+#define chipMinorFeatures1_VG_DOUBLE_BUFFER                    0x00000004
+#define chipMinorFeatures1_EXTRA_EVENT_STATES                  0x00000008
+#define chipMinorFeatures1_NO_STRIPING_NEEDED                  0x00000010
+#define chipMinorFeatures1_TEXTURE_STRIDE                      0x00000020
+#define chipMinorFeatures1_BUG_FIXES3                          0x00000040
+#define chipMinorFeatures1_AUTO_DISABLE                                
0x00000080
+#define chipMinorFeatures1_AUTO_RESTART_TS                     0x00000100
+#define chipMinorFeatures1_DISABLE_PE_GATING                   0x00000200
+#define chipMinorFeatures1_L2_WINDOWING                                
0x00000400
+#define chipMinorFeatures1_HALF_FLOAT                          0x00000800
+#define chipMinorFeatures1_PIXEL_DITHER                                
0x00001000
+#define chipMinorFeatures1_TWO_STENCIL_REFERENCE               0x00002000
+#define chipMinorFeatures1_EXTENDED_PIXEL_FORMAT               0x00004000
+#define chipMinorFeatures1_CORRECT_MIN_MAX_DEPTH               0x00008000
+#define chipMinorFeatures1_2D_DITHER                           0x00010000
+#define chipMinorFeatures1_BUG_FIXES5                          0x00020000
+#define chipMinorFeatures1_NEW_2D                              0x00040000
+#define chipMinorFeatures1_NEW_FP                              0x00080000
+#define chipMinorFeatures1_TEXTURE_HALIGN                      0x00100000
+#define chipMinorFeatures1_NON_POWER_OF_TWO                    0x00200000
+#define chipMinorFeatures1_LINEAR_TEXTURE_SUPPORT              0x00400000
+#define chipMinorFeatures1_HALTI0                              0x00800000
+#define chipMinorFeatures1_CORRECT_OVERFLOW_VG                 0x01000000
+#define chipMinorFeatures1_NEGATIVE_LOG_FIX                    0x02000000
+#define chipMinorFeatures1_RESOLVE_OFFSET                      0x04000000
+#define chipMinorFeatures1_OK_TO_GATE_AXI_CLOCK                        
0x08000000
+#define chipMinorFeatures1_MMU_VERSION                         0x10000000
+#define chipMinorFeatures1_WIDE_LINE                           0x20000000
+#define chipMinorFeatures1_BUG_FIXES6                          0x40000000
+#define chipMinorFeatures1_FC_FLUSH_STALL                      0x80000000
+#define chipMinorFeatures2_LINE_LOOP                           0x00000001
+#define chipMinorFeatures2_LOGIC_OP                            0x00000002
+#define chipMinorFeatures2_UNK2                                        
0x00000004
+#define chipMinorFeatures2_SUPERTILED_TEXTURE                  0x00000008
+#define chipMinorFeatures2_UNK4                                        
0x00000010
+#define chipMinorFeatures2_RECT_PRIMITIVE                      0x00000020
+#define chipMinorFeatures2_COMPOSITION                         0x00000040
+#define chipMinorFeatures2_CORRECT_AUTO_DISABLE_COUNT          0x00000080
+#define chipMinorFeatures2_UNK8                                        
0x00000100
+#define chipMinorFeatures2_UNK9                                        
0x00000200
+#define chipMinorFeatures2_UNK10                               0x00000400
+#define chipMinorFeatures2_SAMPLERBASE_16                      0x00000800
+#define chipMinorFeatures2_UNK12                               0x00001000
+#define chipMinorFeatures2_UNK13                               0x00002000
+#define chipMinorFeatures2_UNK14                               0x00004000
+#define chipMinorFeatures2_EXTRA_TEXTURE_STATE                 0x00008000
+#define chipMinorFeatures2_FULL_DIRECTFB                       0x00010000
+#define chipMinorFeatures2_2D_TILING                           0x00020000
+#define chipMinorFeatures2_THREAD_WALKER_IN_PS                 0x00040000
+#define chipMinorFeatures2_TILE_FILLER                         0x00080000
+#define chipMinorFeatures2_UNK20                               0x00100000
+#define chipMinorFeatures2_2D_MULTI_SOURCE_BLIT                        
0x00200000
+#define chipMinorFeatures2_UNK22                               0x00400000
+#define chipMinorFeatures2_UNK23                               0x00800000
+#define chipMinorFeatures2_UNK24                               0x01000000
+#define chipMinorFeatures2_MIXED_STREAMS                       0x02000000
+#define chipMinorFeatures2_2D_420_L2CACHE                      0x04000000
+#define chipMinorFeatures2_UNK27                               0x08000000
+#define chipMinorFeatures2_2D_NO_INDEX8_BRUSH                  0x10000000
+#define chipMinorFeatures2_TEXTURE_TILED_READ                  0x20000000
+#define chipMinorFeatures2_UNK30                               0x40000000
+#define chipMinorFeatures2_UNK31                               0x80000000
+#define chipMinorFeatures3_ROTATION_STALL_FIX                  0x00000001
+#define chipMinorFeatures3_UNK1                                        
0x00000002
+#define chipMinorFeatures3_2D_MULTI_SOURCE_BLT_EX              0x00000004
+#define chipMinorFeatures3_UNK3                                        
0x00000008
+#define chipMinorFeatures3_UNK4                                        
0x00000010
+#define chipMinorFeatures3_UNK5                                        
0x00000020
+#define chipMinorFeatures3_UNK6                                        
0x00000040
+#define chipMinorFeatures3_UNK7                                        
0x00000080
+#define chipMinorFeatures3_UNK8                                        
0x00000100
+#define chipMinorFeatures3_UNK9                                        
0x00000200
+#define chipMinorFeatures3_BUG_FIXES10                         0x00000400
+#define chipMinorFeatures3_UNK11                               0x00000800
+#define chipMinorFeatures3_BUG_FIXES11                         0x00001000
+#define chipMinorFeatures3_UNK13                               0x00002000
+#define chipMinorFeatures3_UNK14                               0x00004000
+#define chipMinorFeatures3_UNK15                               0x00008000
+#define chipMinorFeatures3_UNK16                               0x00010000
+#define chipMinorFeatures3_UNK17                               0x00020000
+#define chipMinorFeatures3_UNK18                               0x00040000
+#define chipMinorFeatures3_UNK19                               0x00080000
+#define chipMinorFeatures3_UNK20                               0x00100000
+#define chipMinorFeatures3_UNK21                               0x00200000
+#define chipMinorFeatures3_UNK22                               0x00400000
+#define chipMinorFeatures3_UNK23                               0x00800000
+#define chipMinorFeatures3_UNK24                               0x01000000
+#define chipMinorFeatures3_UNK25                               0x02000000
+#define chipMinorFeatures3_UNK26                               0x04000000
+#define chipMinorFeatures3_UNK27                               0x08000000
+#define chipMinorFeatures3_UNK28                               0x10000000
+#define chipMinorFeatures3_UNK29                               0x20000000
+#define chipMinorFeatures3_UNK30                               0x40000000
+#define chipMinorFeatures3_UNK31                               0x80000000
+#define chipMinorFeatures4_UNK0                                        
0x00000001
+#define chipMinorFeatures4_UNK1                                        
0x00000002
+#define chipMinorFeatures4_UNK2                                        
0x00000004
+#define chipMinorFeatures4_UNK3                                        
0x00000008
+#define chipMinorFeatures4_UNK4                                        
0x00000010
+#define chipMinorFeatures4_UNK5                                        
0x00000020
+#define chipMinorFeatures4_UNK6                                        
0x00000040
+#define chipMinorFeatures4_UNK7                                        
0x00000080
+#define chipMinorFeatures4_UNK8                                        
0x00000100
+#define chipMinorFeatures4_UNK9                                        
0x00000200
+#define chipMinorFeatures4_UNK10                               0x00000400
+#define chipMinorFeatures4_UNK11                               0x00000800
+#define chipMinorFeatures4_UNK12                               0x00001000
+#define chipMinorFeatures4_UNK13                               0x00002000
+#define chipMinorFeatures4_UNK14                               0x00004000
+#define chipMinorFeatures4_UNK15                               0x00008000
+#define chipMinorFeatures4_UNK16                               0x00010000
+#define chipMinorFeatures4_UNK17                               0x00020000
+#define chipMinorFeatures4_UNK18                               0x00040000
+#define chipMinorFeatures4_UNK19                               0x00080000
+#define chipMinorFeatures4_UNK20                               0x00100000
+#define chipMinorFeatures4_UNK21                               0x00200000
+#define chipMinorFeatures4_UNK22                               0x00400000
+#define chipMinorFeatures4_UNK23                               0x00800000
+#define chipMinorFeatures4_UNK24                               0x01000000
+#define chipMinorFeatures4_UNK25                               0x02000000
+#define chipMinorFeatures4_UNK26                               0x04000000
+#define chipMinorFeatures4_UNK27                               0x08000000
+#define chipMinorFeatures4_UNK28                               0x10000000
+#define chipMinorFeatures4_UNK29                               0x20000000
+#define chipMinorFeatures4_UNK30                               0x40000000
+#define chipMinorFeatures4_UNK31                               0x80000000
+
+#endif /* COMMON_XML */
diff --git a/drivers/staging/etnaviv/etnaviv_buffer.c 
b/drivers/staging/etnaviv/etnaviv_buffer.c
new file mode 100644
index 000000000000..32764e15c5f7
--- /dev/null
+++ b/drivers/staging/etnaviv/etnaviv_buffer.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2014 2014 Etnaviv Project
+ * Author: Christian Gmeiner <christian.gmeiner at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "etnaviv_gpu.h"
+#include "etnaviv_gem.h"
+
+#include "common.xml.h"
+#include "state.xml.h"
+#include "cmdstream.xml.h"
+
+/*
+ * Command Buffer helper:
+ */
+
+
+static inline void OUT(struct etnaviv_gem_object *buffer, uint32_t data)
+{
+       u32 *vaddr = (u32 *)buffer->vaddr;
+       BUG_ON(buffer->offset >= buffer->base.size);
+
+       vaddr[buffer->offset++] = data;
+}
+
+static inline void CMD_LOAD_STATE(struct etnaviv_gem_object *buffer, u32 reg, 
u32 value)
+{
+       buffer->offset = ALIGN(buffer->offset, 2);
+
+       /* write a register via cmd stream */
+       OUT(buffer, VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE | 
VIV_FE_LOAD_STATE_HEADER_COUNT(1) |
+                       VIV_FE_LOAD_STATE_HEADER_OFFSET(reg >> 
VIV_FE_LOAD_STATE_HEADER_OFFSET__SHR));
+       OUT(buffer, value);
+}
+
+static inline void CMD_LOAD_STATES(struct etnaviv_gem_object *buffer, u32 reg, 
u16 count, u32 *values)
+{
+       u16 i;
+       buffer->offset = ALIGN(buffer->offset, 2);
+
+       OUT(buffer, VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE | 
VIV_FE_LOAD_STATE_HEADER_COUNT(count) |
+                       VIV_FE_LOAD_STATE_HEADER_OFFSET(reg >> 
VIV_FE_LOAD_STATE_HEADER_OFFSET__SHR));
+
+       for (i = 0; i < count; i++)
+               OUT(buffer, values[i]);
+}
+
+static inline void CMD_END(struct etnaviv_gem_object *buffer)
+{
+       buffer->offset = ALIGN(buffer->offset, 2);
+
+       OUT(buffer, VIV_FE_END_HEADER_OP_END);
+}
+
+static inline void CMD_NOP(struct etnaviv_gem_object *buffer)
+{
+       buffer->offset = ALIGN(buffer->offset, 2);
+
+       OUT(buffer, VIV_FE_NOP_HEADER_OP_NOP);
+}
+
+static inline void CMD_WAIT(struct etnaviv_gem_object *buffer)
+{
+       buffer->offset = ALIGN(buffer->offset, 2);
+
+       OUT(buffer, VIV_FE_WAIT_HEADER_OP_WAIT | 200);
+}
+
+static inline void CMD_LINK(struct etnaviv_gem_object *buffer, u16 prefetch, 
u32 address)
+{
+       buffer->offset = ALIGN(buffer->offset, 2);
+
+       OUT(buffer, VIV_FE_LINK_HEADER_OP_LINK | 
VIV_FE_LINK_HEADER_PREFETCH(prefetch));
+       OUT(buffer, address);
+}
+
+static inline void CMD_STALL(struct etnaviv_gem_object *buffer, u32 from, u32 
to)
+{
+       buffer->offset = ALIGN(buffer->offset, 2);
+
+       OUT(buffer, VIV_FE_STALL_HEADER_OP_STALL);
+       OUT(buffer, VIV_FE_STALL_TOKEN_FROM(from) | VIV_FE_STALL_TOKEN_TO(to));
+}
+
+static void etnaviv_cmd_select_pipe(struct etnaviv_gem_object *buffer, u8 pipe)
+{
+       u32 flush;
+       u32 stall;
+
+       if (pipe == ETNA_PIPE_2D)
+               flush = VIVS_GL_FLUSH_CACHE_DEPTH | VIVS_GL_FLUSH_CACHE_COLOR;
+       else
+               flush = VIVS_GL_FLUSH_CACHE_TEXTURE;
+
+       stall = VIVS_GL_SEMAPHORE_TOKEN_FROM(SYNC_RECIPIENT_FE) |
+                       VIVS_GL_SEMAPHORE_TOKEN_TO(SYNC_RECIPIENT_PE);
+
+       CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE, flush);
+       CMD_LOAD_STATE(buffer, VIVS_GL_SEMAPHORE_TOKEN, stall);
+
+       CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
+
+       CMD_LOAD_STATE(buffer, VIVS_GL_PIPE_SELECT, 
VIVS_GL_PIPE_SELECT_PIPE(pipe));
+}
+
+static void etnaviv_buffer_dump(struct etnaviv_gem_object *obj, u32 len)
+{
+       u32 size = obj->base.size;
+       u32 *ptr = obj->vaddr;
+
+       dev_dbg(obj->gpu->dev->dev, "virt %p phys 0x%08x free 0x%08x\n",
+                       obj->vaddr, obj->paddr, size - len * 4);
+
+       print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4,
+                       ptr, len * 4, 0);
+}
+
+u32 etnaviv_buffer_init(struct etnaviv_gpu *gpu)
+{
+       struct etnaviv_gem_object *buffer = to_etnaviv_bo(gpu->buffer);
+
+       /* initialize buffer */
+       buffer->offset = 0;
+
+       etnaviv_cmd_select_pipe(buffer, gpu->pipe);
+
+       CMD_WAIT(buffer);
+       CMD_LINK(buffer, 2, buffer->paddr + ((buffer->offset - 1) * 4));
+
+       return buffer->offset;
+}
+
+void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event, struct 
etnaviv_gem_submit *submit)
+{
+       struct etnaviv_gem_object *buffer = to_etnaviv_bo(gpu->buffer);
+       struct etnaviv_gem_object *cmd;
+       u32 *lw = buffer->vaddr + ((buffer->offset - 4) * 4);
+       u32 back;
+       u32 i;
+
+       etnaviv_buffer_dump(buffer, 0x50);
+
+       /* save offset back into main buffer */
+       back = buffer->offset;
+
+       /* trigger event */
+       CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) | 
VIVS_GL_EVENT_FROM_PE);
+
+       /* append WAIT/LINK to main buffer */
+       CMD_WAIT(buffer);
+       CMD_LINK(buffer, 2, buffer->paddr + ((buffer->offset - 1) * 4));
+
+       /* update offset for every cmd stream */
+       for (i = 0; i < submit->nr_cmds; i++)
+               submit->cmd[i].obj->offset = submit->cmd[i].size;
+
+       /* TODO: inter-connect all cmd buffers */
+
+       /* jump back from last cmd to main buffer */
+       cmd = submit->cmd[submit->nr_cmds - 1].obj;
+       CMD_LINK(cmd, 4, buffer->paddr + (back * 4));
+
+       printk(KERN_ERR "stream link @ 0x%08x\n", cmd->paddr + ((cmd->offset - 
1) * 4));
+       printk(KERN_ERR "stream link @ %p\n", cmd->vaddr + ((cmd->offset - 1) * 
4));
+
+       for (i = 0; i < submit->nr_cmds; i++) {
+               struct etnaviv_gem_object *obj = submit->cmd[i].obj;
+
+               /* TODO: remove later */
+               if (unlikely(drm_debug & DRM_UT_CORE))
+                       etnaviv_buffer_dump(obj, obj->offset);
+       }
+
+       /* change ll to NOP */
+       printk(KERN_ERR "link op: %p\n", lw);
+       printk(KERN_ERR "link addr: %p\n", lw + 1);
+       printk(KERN_ERR "addr: 0x%08x\n", submit->cmd[0].obj->paddr);
+       printk(KERN_ERR "back: 0x%08x\n", buffer->paddr + (back * 4));
+       printk(KERN_ERR "event: %d\n", event);
+
+       /* Change WAIT into a LINK command; write the address first. */
+       i = VIV_FE_LINK_HEADER_OP_LINK | 
VIV_FE_LINK_HEADER_PREFETCH(submit->cmd[0].size * 2);
+       *(lw + 1) = submit->cmd[0].obj->paddr;
+       mb();
+       *(lw)= i;
+       mb();
+
+       etnaviv_buffer_dump(buffer, 0x50);
+}
diff --git a/drivers/staging/etnaviv/etnaviv_drv.c 
b/drivers/staging/etnaviv/etnaviv_drv.c
new file mode 100644
index 000000000000..39586b45200d
--- /dev/null
+++ b/drivers/staging/etnaviv/etnaviv_drv.c
@@ -0,0 +1,621 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/component.h>
+#include <linux/of_platform.h>
+
+#include "etnaviv_drv.h"
+#include "etnaviv_gpu.h"
+
+void etnaviv_register_mmu(struct drm_device *dev, struct etnaviv_iommu *mmu)
+{
+       struct etnaviv_drm_private *priv = dev->dev_private;
+       priv->mmu = mmu;
+}
+
+#ifdef CONFIG_DRM_ETNAVIV_REGISTER_LOGGING
+static bool reglog = false;
+MODULE_PARM_DESC(reglog, "Enable register read/write logging");
+module_param(reglog, bool, 0600);
+#else
+#define reglog 0
+#endif
+
+void __iomem *etnaviv_ioremap(struct platform_device *pdev, const char *name,
+               const char *dbgname)
+{
+       struct resource *res;
+       unsigned long size;
+       void __iomem *ptr;
+
+       if (name)
+               res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
+       else
+               res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       if (!res) {
+               dev_err(&pdev->dev, "failed to get memory resource: %s\n", 
name);
+               return ERR_PTR(-EINVAL);
+       }
+
+       size = resource_size(res);
+
+       ptr = devm_ioremap_nocache(&pdev->dev, res->start, size);
+       if (!ptr) {
+               dev_err(&pdev->dev, "failed to ioremap: %s\n", name);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       if (reglog)
+               printk(KERN_DEBUG "IO:region %s %08x %08lx\n", dbgname, 
(u32)ptr, size);
+
+       return ptr;
+}
+
+void etnaviv_writel(u32 data, void __iomem *addr)
+{
+       if (reglog)
+               printk(KERN_DEBUG "IO:W %08x %08x\n", (u32)addr, data);
+       writel(data, addr);
+}
+
+u32 etnaviv_readl(const void __iomem *addr)
+{
+       u32 val = readl(addr);
+       if (reglog)
+               printk(KERN_ERR "IO:R %08x %08x\n", (u32)addr, val);
+       return val;
+}
+
+/*
+ * DRM operations:
+ */
+
+static int etnaviv_unload(struct drm_device *dev)
+{
+       struct etnaviv_drm_private *priv = dev->dev_private;
+       unsigned int i;
+
+       flush_workqueue(priv->wq);
+       destroy_workqueue(priv->wq);
+
+       mutex_lock(&dev->struct_mutex);
+       for (i = 0; i < ETNA_MAX_PIPES; i++) {
+               struct etnaviv_gpu *g = priv->gpu[i];
+               if (g)
+                       etnaviv_gpu_pm_suspend(g);
+       }
+       mutex_unlock(&dev->struct_mutex);
+
+       component_unbind_all(dev->dev, dev);
+
+       dev->dev_private = NULL;
+
+       kfree(priv);
+
+       return 0;
+}
+
+
+static void load_gpu(struct drm_device *dev)
+{
+       struct etnaviv_drm_private *priv = dev->dev_private;
+       unsigned int i;
+
+       mutex_lock(&dev->struct_mutex);
+
+       for (i = 0; i < ETNA_MAX_PIPES; i++) {
+               struct etnaviv_gpu *g = priv->gpu[i];
+               if (g) {
+                       int ret;
+                       etnaviv_gpu_pm_resume(g);
+                       ret = etnaviv_gpu_init(g);
+                       if (ret) {
+                               dev_err(dev->dev, "%s hw init failed: %d\n", 
g->name, ret);
+                               priv->gpu[i] = NULL;
+                       }
+               }
+       }
+
+       mutex_unlock(&dev->struct_mutex);
+}
+
+static int etnaviv_load(struct drm_device *dev, unsigned long flags)
+{
+       struct platform_device *pdev = dev->platformdev;
+       struct etnaviv_drm_private *priv;
+       int err;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv) {
+               dev_err(dev->dev, "failed to allocate private data\n");
+               return -ENOMEM;
+       }
+
+       dev->dev_private = priv;
+
+       priv->wq = alloc_ordered_workqueue("etnaviv", 0);
+       init_waitqueue_head(&priv->fence_event);
+
+       INIT_LIST_HEAD(&priv->inactive_list);
+
+       platform_set_drvdata(pdev, dev);
+
+       err = component_bind_all(dev->dev, dev);
+       if (err < 0)
+               return err;
+
+       load_gpu(dev);
+
+       return 0;
+}
+
+static int etnaviv_open(struct drm_device *dev, struct drm_file *file)
+{
+       struct etnaviv_file_private *ctx;
+
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       file->driver_priv = ctx;
+
+       return 0;
+}
+
+static void etnaviv_preclose(struct drm_device *dev, struct drm_file *file)
+{
+       struct etnaviv_drm_private *priv = dev->dev_private;
+       struct etnaviv_file_private *ctx = file->driver_priv;
+
+       mutex_lock(&dev->struct_mutex);
+       if (ctx == priv->lastctx)
+               priv->lastctx = NULL;
+       mutex_unlock(&dev->struct_mutex);
+
+       kfree(ctx);
+}
+
+/*
+ * DRM debugfs:
+ */
+
+#ifdef CONFIG_DEBUG_FS
+static int etnaviv_gpu_show(struct drm_device *dev, struct seq_file *m)
+{
+       struct etnaviv_drm_private *priv = dev->dev_private;
+       struct etnaviv_gpu *gpu;
+       unsigned int i;
+
+       for (i = 0; i < ETNA_MAX_PIPES; i++) {
+               gpu = priv->gpu[i];
+               if (gpu) {
+                       seq_printf(m, "%s Status:\n", gpu->name);
+                       etnaviv_gpu_debugfs(gpu, m);
+               }
+       }
+
+       return 0;
+}
+
+static int etnaviv_gem_show(struct drm_device *dev, struct seq_file *m)
+{
+       struct etnaviv_drm_private *priv = dev->dev_private;
+       struct etnaviv_gpu *gpu;
+       unsigned int i;
+
+       for (i = 0; i < ETNA_MAX_PIPES; i++) {
+               gpu = priv->gpu[i];
+               if (gpu) {
+                       seq_printf(m, "Active Objects (%s):\n", gpu->name);
+                       msm_gem_describe_objects(&gpu->active_list, m);
+               }
+       }
+
+       seq_puts(m, "Inactive Objects:\n");
+       msm_gem_describe_objects(&priv->inactive_list, m);
+
+       return 0;
+}
+
+static int etnaviv_mm_show(struct drm_device *dev, struct seq_file *m)
+{
+       return drm_mm_dump_table(m, &dev->vma_offset_manager->vm_addr_space_mm);
+}
+
+static int show_locked(struct seq_file *m, void *arg)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+       int (*show)(struct drm_device *dev, struct seq_file *m) =
+                       node->info_ent->data;
+       int ret;
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
+
+       ret = show(dev, m);
+
+       mutex_unlock(&dev->struct_mutex);
+
+       return ret;
+}
+
+static struct drm_info_list ETNAVIV_debugfs_list[] = {
+               {"gpu", show_locked, 0, etnaviv_gpu_show},
+               {"gem", show_locked, 0, etnaviv_gem_show},
+               { "mm", show_locked, 0, etnaviv_mm_show },
+};
+
+static int etnaviv_debugfs_init(struct drm_minor *minor)
+{
+       struct drm_device *dev = minor->dev;
+       int ret;
+
+       ret = drm_debugfs_create_files(ETNAVIV_debugfs_list,
+                       ARRAY_SIZE(ETNAVIV_debugfs_list),
+                       minor->debugfs_root, minor);
+
+       if (ret) {
+               dev_err(dev->dev, "could not install ETNAVIV_debugfs_list\n");
+               return ret;
+       }
+
+       return ret;
+}
+
+static void etnaviv_debugfs_cleanup(struct drm_minor *minor)
+{
+       drm_debugfs_remove_files(ETNAVIV_debugfs_list,
+                       ARRAY_SIZE(ETNAVIV_debugfs_list), minor);
+}
+#endif
+
+/*
+ * Fences:
+ */
+int etnaviv_wait_fence_interruptable(struct drm_device *dev, uint32_t pipe,
+               uint32_t fence, struct timespec *timeout)
+{
+       struct etnaviv_drm_private *priv = dev->dev_private;
+       struct etnaviv_gpu *gpu;
+       int ret;
+
+       if (pipe >= ETNA_MAX_PIPES)
+               return -EINVAL;
+
+       gpu = priv->gpu[pipe];
+       if (!gpu)
+               return -ENXIO;
+
+       if (fence > gpu->submitted_fence) {
+               DRM_ERROR("waiting on invalid fence: %u (of %u)\n",
+                               fence, gpu->submitted_fence);
+               return -EINVAL;
+       }
+
+       if (!timeout) {
+               /* no-wait: */
+               ret = fence_completed(dev, fence) ? 0 : -EBUSY;
+       } else {
+               unsigned long timeout_jiffies = timespec_to_jiffies(timeout);
+               unsigned long start_jiffies = jiffies;
+               unsigned long remaining_jiffies;
+
+               if (time_after(start_jiffies, timeout_jiffies))
+                       remaining_jiffies = 0;
+               else
+                       remaining_jiffies = timeout_jiffies - start_jiffies;
+
+               ret = wait_event_interruptible_timeout(priv->fence_event,
+                               fence_completed(dev, fence),
+                               remaining_jiffies);
+
+               if (ret == 0) {
+                       DBG("timeout waiting for fence: %u (completed: %u)",
+                                       fence, priv->completed_fence);
+                       ret = -ETIMEDOUT;
+               } else if (ret != -ERESTARTSYS) {
+                       ret = 0;
+               }
+       }
+
+       return ret;
+}
+
+/* called from workqueue */
+void etnaviv_update_fence(struct drm_device *dev, uint32_t fence)
+{
+       struct etnaviv_drm_private *priv = dev->dev_private;
+
+       mutex_lock(&dev->struct_mutex);
+       priv->completed_fence = max(fence, priv->completed_fence);
+       mutex_unlock(&dev->struct_mutex);
+
+       wake_up_all(&priv->fence_event);
+}
+
+/*
+ * DRM ioctls:
+ */
+
+static int etnaviv_ioctl_get_param(struct drm_device *dev, void *data,
+               struct drm_file *file)
+{
+       struct etnaviv_drm_private *priv = dev->dev_private;
+       struct drm_etnaviv_param *args = data;
+       struct etnaviv_gpu *gpu;
+
+       if (args->pipe >= ETNA_MAX_PIPES)
+               return -EINVAL;
+
+       gpu = priv->gpu[args->pipe];
+       if (!gpu)
+               return -ENXIO;
+
+       return etnaviv_gpu_get_param(gpu, args->param, &args->value);
+}
+
+static int etnaviv_ioctl_gem_new(struct drm_device *dev, void *data,
+               struct drm_file *file)
+{
+       struct drm_etnaviv_gem_new *args = data;
+       return etnaviv_gem_new_handle(dev, file, args->size,
+                       args->flags, &args->handle);
+}
+
+#define TS(t) ((struct timespec){ .tv_sec = (t).tv_sec, .tv_nsec = (t).tv_nsec 
})
+
+static int etnaviv_ioctl_gem_cpu_prep(struct drm_device *dev, void *data,
+               struct drm_file *file)
+{
+       struct drm_etnaviv_gem_cpu_prep *args = data;
+       struct drm_gem_object *obj;
+       int ret;
+
+       obj = drm_gem_object_lookup(dev, file, args->handle);
+       if (!obj)
+               return -ENOENT;
+
+       ret = etnaviv_gem_cpu_prep(obj, args->op, &TS(args->timeout));
+
+       drm_gem_object_unreference_unlocked(obj);
+
+       return ret;
+}
+
+static int etnaviv_ioctl_gem_cpu_fini(struct drm_device *dev, void *data,
+               struct drm_file *file)
+{
+       struct drm_etnaviv_gem_cpu_fini *args = data;
+       struct drm_gem_object *obj;
+       int ret;
+
+       obj = drm_gem_object_lookup(dev, file, args->handle);
+       if (!obj)
+               return -ENOENT;
+
+       ret = etnaviv_gem_cpu_fini(obj);
+
+       drm_gem_object_unreference_unlocked(obj);
+
+       return ret;
+}
+
+static int etnaviv_ioctl_gem_info(struct drm_device *dev, void *data,
+               struct drm_file *file)
+{
+       struct drm_etnaviv_gem_info *args = data;
+       struct drm_gem_object *obj;
+       int ret = 0;
+
+       if (args->pad)
+               return -EINVAL;
+
+       obj = drm_gem_object_lookup(dev, file, args->handle);
+       if (!obj)
+               return -ENOENT;
+
+       args->offset = msm_gem_mmap_offset(obj);
+
+       drm_gem_object_unreference_unlocked(obj);
+
+       return ret;
+}
+
+static int etnaviv_ioctl_wait_fence(struct drm_device *dev, void *data,
+               struct drm_file *file)
+{
+       struct drm_etnaviv_wait_fence *args = data;
+       return etnaviv_wait_fence_interruptable(dev, args->pipe, args->fence, 
&TS(args->timeout));
+}
+
+static const struct drm_ioctl_desc etnaviv_ioctls[] = {
+       DRM_IOCTL_DEF_DRV(ETNAVIV_GET_PARAM,    etnaviv_ioctl_get_param,    
DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(ETNAVIV_GEM_NEW,      etnaviv_ioctl_gem_new,      
DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(ETNAVIV_GEM_INFO,     etnaviv_ioctl_gem_info,     
DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(ETNAVIV_GEM_CPU_PREP, etnaviv_ioctl_gem_cpu_prep, 
DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(ETNAVIV_GEM_CPU_FINI, etnaviv_ioctl_gem_cpu_fini, 
DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(ETNAVIV_GEM_SUBMIT,   etnaviv_ioctl_gem_submit,   
DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(ETNAVIV_WAIT_FENCE,   etnaviv_ioctl_wait_fence,   
DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
+};
+
+static const struct vm_operations_struct vm_ops = {
+       .fault = etnaviv_gem_fault,
+       .open = drm_gem_vm_open,
+       .close = drm_gem_vm_close,
+};
+
+static const struct file_operations fops = {
+       .owner              = THIS_MODULE,
+       .open               = drm_open,
+       .release            = drm_release,
+       .unlocked_ioctl     = drm_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl       = drm_compat_ioctl,
+#endif
+       .poll               = drm_poll,
+       .read               = drm_read,
+       .llseek             = no_llseek,
+       .mmap               = etnaviv_gem_mmap,
+};
+
+static struct drm_driver etnaviv_drm_driver = {
+       .driver_features    = DRIVER_HAVE_IRQ |
+                               DRIVER_GEM |
+                               DRIVER_PRIME |
+                               DRIVER_RENDER,
+       .load               = etnaviv_load,
+       .unload             = etnaviv_unload,
+       .open               = etnaviv_open,
+       .preclose           = etnaviv_preclose,
+       .set_busid          = drm_platform_set_busid,
+       .gem_free_object    = etnaviv_gem_free_object,
+       .gem_vm_ops         = &vm_ops,
+       .dumb_create        = msm_gem_dumb_create,
+       .dumb_map_offset    = msm_gem_dumb_map_offset,
+       .dumb_destroy       = drm_gem_dumb_destroy,
+       .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+       .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+       .gem_prime_export   = drm_gem_prime_export,
+       .gem_prime_import   = drm_gem_prime_import,
+       .gem_prime_pin      = msm_gem_prime_pin,
+       .gem_prime_unpin    = msm_gem_prime_unpin,
+       .gem_prime_get_sg_table = msm_gem_prime_get_sg_table,
+       .gem_prime_import_sg_table = msm_gem_prime_import_sg_table,
+       .gem_prime_vmap     = msm_gem_prime_vmap,
+       .gem_prime_vunmap   = msm_gem_prime_vunmap,
+#ifdef CONFIG_DEBUG_FS
+       .debugfs_init       = etnaviv_debugfs_init,
+       .debugfs_cleanup    = etnaviv_debugfs_cleanup,
+#endif
+       .ioctls             = etnaviv_ioctls,
+       .num_ioctls         = DRM_ETNAVIV_NUM_IOCTLS,
+       .fops               = &fops,
+       .name               = "etnaviv",
+       .desc               = "etnaviv DRM",
+       .date               = "20130625",
+       .major              = 1,
+       .minor              = 0,
+};
+
+/*
+ * Platform driver:
+ */
+
+static int etnaviv_compare(struct device *dev, void *data)
+{
+       struct device_node *np = data;
+
+       return dev->of_node == np;
+}
+
+static int etnaviv_add_components(struct device *master, struct master *m)
+{
+       struct device_node *np  = master->of_node;
+       struct device_node *child_np;
+
+       child_np = of_get_next_available_child(np, NULL);
+
+       while (child_np) {
+               DRM_INFO("add child %s\n", child_np->name);
+               component_master_add_child(m, etnaviv_compare, child_np);
+               of_node_put(child_np);
+               child_np = of_get_next_available_child(np, child_np);
+       }
+
+       return 0;
+}
+
+static int etnaviv_bind(struct device *dev)
+{
+       return drm_platform_init(&etnaviv_drm_driver, to_platform_device(dev));
+}
+
+static void etnaviv_unbind(struct device *dev)
+{
+       drm_put_dev(dev_get_drvdata(dev));
+}
+
+static const struct component_master_ops etnaviv_master_ops = {
+       .add_components = etnaviv_add_components,
+       .bind = etnaviv_bind,
+       .unbind = etnaviv_unbind,
+};
+
+static int etnaviv_pdev_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *node = dev->of_node;
+
+       of_platform_populate(node, NULL, NULL, dev);
+
+       dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+
+       return component_master_add(&pdev->dev, &etnaviv_master_ops);
+}
+
+static int etnaviv_pdev_remove(struct platform_device *pdev)
+{
+       component_master_del(&pdev->dev, &etnaviv_master_ops);
+
+       return 0;
+}
+
+static const struct of_device_id dt_match[] = {
+       { .compatible = "vivante,gccore" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, dt_match);
+
+static struct platform_driver etnaviv_platform_driver = {
+       .probe      = etnaviv_pdev_probe,
+       .remove     = etnaviv_pdev_remove,
+       .driver     = {
+               .owner  = THIS_MODULE,
+               .name   = "vivante",
+               .of_match_table = dt_match,
+       },
+};
+
+static int __init etnaviv_init(void)
+{
+       int ret;
+
+       ret = platform_driver_register(&etnaviv_gpu_driver);
+       if (ret != 0)
+               return ret;
+
+       ret = platform_driver_register(&etnaviv_platform_driver);
+       if (ret != 0)
+               platform_driver_unregister(&etnaviv_gpu_driver);
+
+       return ret;
+}
+module_init(etnaviv_init);
+
+static void __exit etnaviv_exit(void)
+{
+       platform_driver_unregister(&etnaviv_gpu_driver);
+       platform_driver_unregister(&etnaviv_platform_driver);
+}
+module_exit(etnaviv_exit);
+
+MODULE_AUTHOR("Rob Clark <robdclark at gmail.com");
+MODULE_DESCRIPTION("etnaviv DRM Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/etnaviv/etnaviv_drv.h 
b/drivers/staging/etnaviv/etnaviv_drv.h
new file mode 100644
index 000000000000..63994f22d8c9
--- /dev/null
+++ b/drivers/staging/etnaviv/etnaviv_drv.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ETNAVIV_DRV_H__
+#define __ETNAVIV_DRV_H__
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/cpufreq.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/iommu.h>
+#include <linux/types.h>
+#include <linux/sizes.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem.h>
+#include <drm/etnaviv_drm.h>
+
+struct etnaviv_gpu;
+struct etnaviv_mmu;
+struct etnaviv_gem_submit;
+
+struct etnaviv_file_private {
+       /* currently we don't do anything useful with this.. but when
+        * per-context address spaces are supported we'd keep track of
+        * the context's page-tables here.
+        */
+       int dummy;
+};
+
+struct etnaviv_drm_private {
+       struct etnaviv_gpu *gpu[ETNA_MAX_PIPES];
+       struct etnaviv_file_private *lastctx;
+
+       uint32_t next_fence, completed_fence;
+       wait_queue_head_t fence_event;
+
+       /* list of GEM objects: */
+       struct list_head inactive_list;
+
+       struct workqueue_struct *wq;
+
+       /* registered MMUs: */
+       struct etnaviv_iommu *mmu;
+};
+
+void etnaviv_register_mmu(struct drm_device *dev, struct etnaviv_iommu *mmu);
+
+int etnaviv_wait_fence_interruptable(struct drm_device *dev, uint32_t pipe,
+               uint32_t fence, struct timespec *timeout);
+void etnaviv_update_fence(struct drm_device *dev, uint32_t fence);
+
+int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
+               struct drm_file *file);
+
+int etnaviv_gem_mmap(struct file *filp, struct vm_area_struct *vma);
+int etnaviv_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
+uint64_t msm_gem_mmap_offset(struct drm_gem_object *obj);
+int etnaviv_gem_get_iova_locked(struct etnaviv_gpu *gpu, struct drm_gem_object 
*obj,
+               uint32_t *iova);
+int etnaviv_gem_get_iova(struct etnaviv_gpu *gpu, struct drm_gem_object *obj, 
int id, uint32_t *iova);
+struct page **etnaviv_gem_get_pages(struct drm_gem_object *obj);
+void msm_gem_put_pages(struct drm_gem_object *obj);
+void etnaviv_gem_put_iova(struct drm_gem_object *obj);
+int msm_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
+               struct drm_mode_create_dumb *args);
+int msm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
+               uint32_t handle, uint64_t *offset);
+struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj);
+void *msm_gem_prime_vmap(struct drm_gem_object *obj);
+void msm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
+struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev,
+               size_t size, struct sg_table *sg);
+int msm_gem_prime_pin(struct drm_gem_object *obj);
+void msm_gem_prime_unpin(struct drm_gem_object *obj);
+void *etnaviv_gem_vaddr_locked(struct drm_gem_object *obj);
+void *msm_gem_vaddr(struct drm_gem_object *obj);
+dma_addr_t etnaviv_gem_paddr_locked(struct drm_gem_object *obj);
+void etnaviv_gem_move_to_active(struct drm_gem_object *obj,
+               struct etnaviv_gpu *gpu, bool write, uint32_t fence);
+void etnaviv_gem_move_to_inactive(struct drm_gem_object *obj);
+int etnaviv_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op,
+               struct timespec *timeout);
+int etnaviv_gem_cpu_fini(struct drm_gem_object *obj);
+void etnaviv_gem_free_object(struct drm_gem_object *obj);
+int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file,
+               uint32_t size, uint32_t flags, uint32_t *handle);
+struct drm_gem_object *etnaviv_gem_new(struct drm_device *dev,
+               uint32_t size, uint32_t flags);
+struct drm_gem_object *msm_gem_import(struct drm_device *dev,
+               uint32_t size, struct sg_table *sgt);
+u32 etnaviv_buffer_init(struct etnaviv_gpu *gpu);
+void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event, struct 
etnaviv_gem_submit *submit);
+
+#ifdef CONFIG_DEBUG_FS
+void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m);
+void msm_gem_describe_objects(struct list_head *list, struct seq_file *m);
+void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m);
+#endif
+
+void __iomem *etnaviv_ioremap(struct platform_device *pdev, const char *name,
+               const char *dbgname);
+void etnaviv_writel(u32 data, void __iomem *addr);
+u32 etnaviv_readl(const void __iomem *addr);
+
+#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
+#define VERB(fmt, ...) if (0) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
+
+static inline bool fence_completed(struct drm_device *dev, uint32_t fence)
+{
+       struct etnaviv_drm_private *priv = dev->dev_private;
+       return priv->completed_fence >= fence;
+}
+
+static inline int align_pitch(int width, int bpp)
+{
+       int bytespp = (bpp + 7) / 8;
+       /* adreno needs pitch aligned to 32 pixels: */
+       return bytespp * ALIGN(width, 32);
+}
+
+#endif /* __ETNAVIV_DRV_H__ */
diff --git a/drivers/staging/etnaviv/etnaviv_gem.c 
b/drivers/staging/etnaviv/etnaviv_gem.c
new file mode 100644
index 000000000000..42149a2b7404
--- /dev/null
+++ b/drivers/staging/etnaviv/etnaviv_gem.c
@@ -0,0 +1,706 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/shmem_fs.h>
+#include <linux/dma-buf.h>
+
+#include "etnaviv_drv.h"
+#include "etnaviv_gem.h"
+#include "etnaviv_gpu.h"
+#include "etnaviv_mmu.h"
+
+/* called with dev->struct_mutex held */
+static struct page **get_pages(struct drm_gem_object *obj)
+{
+       struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+
+       if (!etnaviv_obj->pages) {
+               struct drm_device *dev = obj->dev;
+               struct page **p;
+               int npages = obj->size >> PAGE_SHIFT;
+
+               p = drm_gem_get_pages(obj);
+
+               if (IS_ERR(p)) {
+                       dev_err(dev->dev, "could not get pages: %ld\n",
+                                       PTR_ERR(p));
+                       return p;
+               }
+
+               etnaviv_obj->sgt = drm_prime_pages_to_sg(p, npages);
+               if (IS_ERR(etnaviv_obj->sgt)) {
+                       dev_err(dev->dev, "failed to allocate sgt\n");
+                       return ERR_CAST(etnaviv_obj->sgt);
+               }
+
+               etnaviv_obj->pages = p;
+
+               /* For non-cached buffers, ensure the new pages are clean
+                * because display controller, GPU, etc. are not coherent:
+                */
+               if (etnaviv_obj->flags & (ETNA_BO_WC|ETNA_BO_UNCACHED))
+                       dma_map_sg(dev->dev, etnaviv_obj->sgt->sgl,
+                                       etnaviv_obj->sgt->nents, 
DMA_BIDIRECTIONAL);
+       }
+
+       return etnaviv_obj->pages;
+}
+
+static void put_pages(struct drm_gem_object *obj)
+{
+       struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+
+       if (etnaviv_obj->pages) {
+               /* For non-cached buffers, ensure the new pages are clean
+                * because display controller, GPU, etc. are not coherent:
+                */
+               if (etnaviv_obj->flags & (ETNA_BO_WC|ETNA_BO_UNCACHED))
+                       dma_unmap_sg(obj->dev->dev, etnaviv_obj->sgt->sgl,
+                                       etnaviv_obj->sgt->nents, 
DMA_BIDIRECTIONAL);
+               sg_free_table(etnaviv_obj->sgt);
+               kfree(etnaviv_obj->sgt);
+
+               drm_gem_put_pages(obj, etnaviv_obj->pages, true, false);
+
+               etnaviv_obj->pages = NULL;
+       }
+}
+
+struct page **etnaviv_gem_get_pages(struct drm_gem_object *obj)
+{
+       struct drm_device *dev = obj->dev;
+       struct page **p;
+       mutex_lock(&dev->struct_mutex);
+       p = get_pages(obj);
+       mutex_unlock(&dev->struct_mutex);
+       return p;
+}
+
+void msm_gem_put_pages(struct drm_gem_object *obj)
+{
+       /* when we start tracking the pin count, then do something here */
+}
+
+static int etnaviv_gem_mmap_cmd(struct drm_gem_object *obj,
+       struct vm_area_struct *vma)
+{
+       struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+       int ret;
+
+       /*
+        * Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the
+        * vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map
+        * the whole buffer.
+        */
+       vma->vm_flags &= ~VM_PFNMAP;
+       vma->vm_pgoff = 0;
+
+       ret = dma_mmap_coherent(obj->dev->dev, vma,
+                               etnaviv_obj->vaddr, etnaviv_obj->paddr,
+                               vma->vm_end - vma->vm_start);
+
+       return ret;
+}
+
+static int etnaviv_gem_mmap_obj(struct drm_gem_object *obj,
+               struct vm_area_struct *vma)
+{
+       struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+
+       vma->vm_flags &= ~VM_PFNMAP;
+       vma->vm_flags |= VM_MIXEDMAP;
+
+       if (etnaviv_obj->flags & ETNA_BO_WC) {
+               vma->vm_page_prot = 
pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
+       } else if (etnaviv_obj->flags & ETNA_BO_UNCACHED) {
+               vma->vm_page_prot = 
pgprot_noncached(vm_get_page_prot(vma->vm_flags));
+       } else {
+               /*
+                * Shunt off cached objs to shmem file so they have their own
+                * address_space (so unmap_mapping_range does what we want,
+                * in particular in the case of mmap'd dmabufs)
+                */
+               fput(vma->vm_file);
+               get_file(obj->filp);
+               vma->vm_pgoff = 0;
+               vma->vm_file  = obj->filp;
+
+               vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+       }
+
+       return 0;
+}
+
+int etnaviv_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+       struct etnaviv_gem_object *obj;
+       int ret;
+
+       ret = drm_gem_mmap(filp, vma);
+       if (ret) {
+               DBG("mmap failed: %d", ret);
+               return ret;
+       }
+
+       obj = to_etnaviv_bo(vma->vm_private_data);
+       if (obj->flags & ETNA_BO_CMDSTREAM)
+               ret = etnaviv_gem_mmap_cmd(vma->vm_private_data, vma);
+       else
+               ret = etnaviv_gem_mmap_obj(vma->vm_private_data, vma);
+
+       return ret;
+}
+
+int etnaviv_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+       struct drm_gem_object *obj = vma->vm_private_data;
+       struct drm_device *dev = obj->dev;
+       struct page **pages;
+       unsigned long pfn;
+       pgoff_t pgoff;
+       int ret;
+
+       /* Make sure we don't parallel update on a fault, nor move or remove
+        * something from beneath our feet
+        */
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               goto out;
+
+       /* make sure we have pages attached now */
+       pages = get_pages(obj);
+       if (IS_ERR(pages)) {
+               ret = PTR_ERR(pages);
+               goto out_unlock;
+       }
+
+       /* We don't use vmf->pgoff since that has the fake offset: */
+       pgoff = ((unsigned long)vmf->virtual_address -
+                       vma->vm_start) >> PAGE_SHIFT;
+
+       pfn = page_to_pfn(pages[pgoff]);
+
+       VERB("Inserting %p pfn %lx, pa %lx", vmf->virtual_address,
+                       pfn, pfn << PAGE_SHIFT);
+
+       ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn);
+
+out_unlock:
+       mutex_unlock(&dev->struct_mutex);
+out:
+       switch (ret) {
+       case -EAGAIN:
+       case 0:
+       case -ERESTARTSYS:
+       case -EINTR:
+       case -EBUSY:
+               /*
+                * EBUSY is ok: this just means that another thread
+                * already did the job.
+                */
+               return VM_FAULT_NOPAGE;
+       case -ENOMEM:
+               return VM_FAULT_OOM;
+       default:
+               return VM_FAULT_SIGBUS;
+       }
+}
+
+/** get mmap offset */
+static uint64_t mmap_offset(struct drm_gem_object *obj)
+{
+       struct drm_device *dev = obj->dev;
+       int ret;
+
+       WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+       /* Make it mmapable */
+       ret = drm_gem_create_mmap_offset(obj);
+
+       if (ret) {
+               dev_err(dev->dev, "could not allocate mmap offset\n");
+               return 0;
+       }
+
+       return drm_vma_node_offset_addr(&obj->vma_node);
+}
+
+uint64_t msm_gem_mmap_offset(struct drm_gem_object *obj)
+{
+       uint64_t offset;
+       mutex_lock(&obj->dev->struct_mutex);
+       offset = mmap_offset(obj);
+       mutex_unlock(&obj->dev->struct_mutex);
+       return offset;
+}
+
+/* should be called under struct_mutex.. although it can be called
+ * from atomic context without struct_mutex to acquire an extra
+ * iova ref if you know one is already held.
+ *
+ * That means when I do eventually need to add support for unpinning
+ * the refcnt counter needs to be atomic_t.
+ */
+int etnaviv_gem_get_iova_locked(struct etnaviv_gpu * gpu, struct 
drm_gem_object *obj,
+               uint32_t *iova)
+{
+       struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+       int ret = 0;
+
+       if (!etnaviv_obj->iova  && !(etnaviv_obj->flags & ETNA_BO_CMDSTREAM)) {
+               struct etnaviv_drm_private *priv = obj->dev->dev_private;
+               struct etnaviv_iommu *mmu = priv->mmu;
+               struct page **pages = get_pages(obj);
+               uint32_t offset;
+               struct drm_mm_node *node = NULL;
+
+               if (IS_ERR(pages))
+                       return PTR_ERR(pages);
+
+               node = kzalloc(sizeof(*node), GFP_KERNEL);
+               if (!node)
+                       return -ENOMEM;
+
+               ret = drm_mm_insert_node(&gpu->mm, node, obj->size, 0,
+                               DRM_MM_SEARCH_DEFAULT);
+
+               if (!ret) {
+                       offset = node->start;
+                       etnaviv_obj->iova = offset;
+                       etnaviv_obj->gpu_vram_node = node;
+
+                       ret = etnaviv_iommu_map(mmu, offset, etnaviv_obj->sgt,
+                                       obj->size, IOMMU_READ | IOMMU_WRITE);
+               } else
+                       kfree(node);
+       }
+
+       if (!ret)
+               *iova = etnaviv_obj->iova;
+
+       return ret;
+}
+
+int etnaviv_gem_get_iova(struct etnaviv_gpu *gpu, struct drm_gem_object *obj, 
int id, uint32_t *iova)
+{
+       struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+       int ret;
+
+       /* this is safe right now because we don't unmap until the
+        * bo is deleted:
+        */
+       if (etnaviv_obj->iova) {
+               *iova = etnaviv_obj->iova;
+               return 0;
+       }
+
+       mutex_lock(&obj->dev->struct_mutex);
+       ret = etnaviv_gem_get_iova_locked(gpu, obj, iova);
+       mutex_unlock(&obj->dev->struct_mutex);
+       return ret;
+}
+
+void etnaviv_gem_put_iova(struct drm_gem_object *obj)
+{
+       // XXX TODO ..
+       // NOTE: probably don't need a _locked() version.. we wouldn't
+       // normally unmap here, but instead just mark that it could be
+       // unmapped (if the iova refcnt drops to zero), but then later
+       // if another _get_iova_locked() fails we can start unmapping
+       // things that are no longer needed..
+}
+
+int msm_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
+               struct drm_mode_create_dumb *args)
+{
+       args->pitch = align_pitch(args->width, args->bpp);
+       args->size  = PAGE_ALIGN(args->pitch * args->height);
+       /* TODO: re-check flags */
+       return etnaviv_gem_new_handle(dev, file, args->size,
+                       ETNA_BO_WC, &args->handle);
+}
+
+int msm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
+               uint32_t handle, uint64_t *offset)
+{
+       struct drm_gem_object *obj;
+       int ret = 0;
+
+       /* GEM does all our handle to object mapping */
+       obj = drm_gem_object_lookup(dev, file, handle);
+       if (obj == NULL) {
+               ret = -ENOENT;
+               goto fail;
+       }
+
+       *offset = msm_gem_mmap_offset(obj);
+
+       drm_gem_object_unreference_unlocked(obj);
+
+fail:
+       return ret;
+}
+
+void *etnaviv_gem_vaddr_locked(struct drm_gem_object *obj)
+{
+       struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+       WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));
+       if (!etnaviv_obj->vaddr) {
+               struct page **pages = get_pages(obj);
+               if (IS_ERR(pages))
+                       return ERR_CAST(pages);
+               etnaviv_obj->vaddr = vmap(pages, obj->size >> PAGE_SHIFT,
+                               VM_MAP, pgprot_writecombine(PAGE_KERNEL));
+       }
+       return etnaviv_obj->vaddr;
+}
+
+void *msm_gem_vaddr(struct drm_gem_object *obj)
+{
+       void *ret;
+       mutex_lock(&obj->dev->struct_mutex);
+       ret = etnaviv_gem_vaddr_locked(obj);
+       mutex_unlock(&obj->dev->struct_mutex);
+       return ret;
+}
+
+dma_addr_t etnaviv_gem_paddr_locked(struct drm_gem_object *obj)
+{
+       struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+       WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));
+
+       return etnaviv_obj->paddr;
+}
+
+void etnaviv_gem_move_to_active(struct drm_gem_object *obj,
+               struct etnaviv_gpu *gpu, bool write, uint32_t fence)
+{
+       struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+       etnaviv_obj->gpu = gpu;
+       if (write)
+               etnaviv_obj->write_fence = fence;
+       else
+               etnaviv_obj->read_fence = fence;
+       list_del_init(&etnaviv_obj->mm_list);
+       list_add_tail(&etnaviv_obj->mm_list, &gpu->active_list);
+}
+
+void etnaviv_gem_move_to_inactive(struct drm_gem_object *obj)
+{
+       struct drm_device *dev = obj->dev;
+       struct etnaviv_drm_private *priv = dev->dev_private;
+       struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+
+       WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+       etnaviv_obj->gpu = NULL;
+       etnaviv_obj->read_fence = 0;
+       etnaviv_obj->write_fence = 0;
+       list_del_init(&etnaviv_obj->mm_list);
+       list_add_tail(&etnaviv_obj->mm_list, &priv->inactive_list);
+}
+
+int etnaviv_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op,
+               struct timespec *timeout)
+{
+/*
+       struct drm_device *dev = obj->dev;
+       struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+*/
+       int ret = 0;
+       /* TODO */
+#if 0
+       if (is_active(etnaviv_obj)) {
+               uint32_t fence = 0;
+
+               if (op & MSM_PREP_READ)
+                       fence = etnaviv_obj->write_fence;
+               if (op & MSM_PREP_WRITE)
+                       fence = max(fence, etnaviv_obj->read_fence);
+               if (op & MSM_PREP_NOSYNC)
+                       timeout = NULL;
+
+               ret = etnaviv_wait_fence_interruptable(dev, fence, timeout);
+       }
+
+       /* TODO cache maintenance */
+#endif
+       return ret;
+}
+
+int etnaviv_gem_cpu_fini(struct drm_gem_object *obj)
+{
+       /* TODO cache maintenance */
+       return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
+{
+       struct drm_device *dev = obj->dev;
+       struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+       uint64_t off = drm_vma_node_start(&obj->vma_node);
+
+       WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+       seq_printf(m, "%08x: %c(r=%u,w=%u) %2d (%2d) %08llx %p %d\n",
+                       etnaviv_obj->flags, is_active(etnaviv_obj) ? 'A' : 'I',
+                       etnaviv_obj->read_fence, etnaviv_obj->write_fence,
+                       obj->name, obj->refcount.refcount.counter,
+                       off, etnaviv_obj->vaddr, obj->size);
+}
+
+void msm_gem_describe_objects(struct list_head *list, struct seq_file *m)
+{
+       struct etnaviv_gem_object *etnaviv_obj;
+       int count = 0;
+       size_t size = 0;
+
+       list_for_each_entry(etnaviv_obj, list, mm_list) {
+               struct drm_gem_object *obj = &etnaviv_obj->base;
+               seq_puts(m, "   ");
+               msm_gem_describe(obj, m);
+               count++;
+               size += obj->size;
+       }
+
+       seq_printf(m, "Total %d objects, %zu bytes\n", count, size);
+}
+#endif
+
+static void etnaviv_free_cmd(struct drm_gem_object *obj)
+{
+       struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+
+       drm_gem_free_mmap_offset(obj);
+
+       dma_free_coherent(obj->dev->dev, obj->size,
+               etnaviv_obj->vaddr, etnaviv_obj->paddr);
+
+       drm_gem_object_release(obj);
+}
+
+static void etnaviv_free_obj(struct drm_gem_object *obj)
+{
+       struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+       struct etnaviv_drm_private *priv = obj->dev->dev_private;
+       struct etnaviv_iommu *mmu = priv->mmu;
+
+       if (mmu && etnaviv_obj->iova) {
+               uint32_t offset = etnaviv_obj->gpu_vram_node->start;
+               etnaviv_iommu_unmap(mmu, offset, etnaviv_obj->sgt, obj->size);
+               drm_mm_remove_node(etnaviv_obj->gpu_vram_node);
+               kfree(etnaviv_obj->gpu_vram_node);
+       }
+
+       drm_gem_free_mmap_offset(obj);
+
+       if (obj->import_attach) {
+               if (etnaviv_obj->vaddr)
+                       dma_buf_vunmap(obj->import_attach->dmabuf, 
etnaviv_obj->vaddr);
+
+               /* Don't drop the pages for imported dmabuf, as they are not
+                * ours, just free the array we allocated:
+                */
+               if (etnaviv_obj->pages)
+                       drm_free_large(etnaviv_obj->pages);
+
+       } else {
+               if (etnaviv_obj->vaddr)
+                       vunmap(etnaviv_obj->vaddr);
+               put_pages(obj);
+       }
+
+       if (etnaviv_obj->resv == &etnaviv_obj->_resv)
+               reservation_object_fini(etnaviv_obj->resv);
+
+       drm_gem_object_release(obj);
+}
+
+void etnaviv_gem_free_object(struct drm_gem_object *obj)
+{
+       struct drm_device *dev = obj->dev;
+       struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+
+       WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+       /* object should not be on active list: */
+       WARN_ON(is_active(etnaviv_obj));
+
+       list_del(&etnaviv_obj->mm_list);
+
+       if (etnaviv_obj->flags & ETNA_BO_CMDSTREAM)
+               etnaviv_free_cmd(obj);
+       else
+               etnaviv_free_obj(obj);
+
+       kfree(etnaviv_obj);
+}
+
+/* convenience method to construct a GEM buffer object, and userspace handle */
+int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file,
+               uint32_t size, uint32_t flags, uint32_t *handle)
+{
+       struct drm_gem_object *obj;
+       int ret;
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
+
+       obj = etnaviv_gem_new(dev, size, flags);
+
+       mutex_unlock(&dev->struct_mutex);
+
+       if (IS_ERR(obj))
+               return PTR_ERR(obj);
+
+       ret = drm_gem_handle_create(file, obj, handle);
+
+       /* drop reference from allocate - handle holds it now */
+       drm_gem_object_unreference_unlocked(obj);
+
+       return ret;
+}
+
+static int etnaviv_gem_new_impl(struct drm_device *dev,
+               uint32_t size, uint32_t flags,
+               struct drm_gem_object **obj)
+{
+       struct etnaviv_drm_private *priv = dev->dev_private;
+       struct etnaviv_gem_object *etnaviv_obj;
+       unsigned sz = sizeof(*etnaviv_obj);
+       bool valid = true;
+
+       /* validate flags */
+       if (flags & ETNA_BO_CMDSTREAM) {
+               if ((flags & ETNA_BO_CACHE_MASK) != 0)
+                       valid = false;
+       } else {
+               switch (flags & ETNA_BO_CACHE_MASK) {
+               case ETNA_BO_UNCACHED:
+               case ETNA_BO_CACHED:
+               case ETNA_BO_WC:
+                       break;
+               default:
+                       valid = false;
+               }
+       }
+
+       if (!valid) {
+               dev_err(dev->dev, "invalid cache flag: %x (cmd: %d)\n",
+                               (flags & ETNA_BO_CACHE_MASK),
+                               (flags & ETNA_BO_CMDSTREAM));
+               return -EINVAL;
+       }
+
+       etnaviv_obj = kzalloc(sz, GFP_KERNEL);
+       if (!etnaviv_obj)
+               return -ENOMEM;
+
+       if (flags & ETNA_BO_CMDSTREAM) {
+               etnaviv_obj->vaddr = dma_alloc_coherent(dev->dev, size,
+                               &etnaviv_obj->paddr, GFP_KERNEL);
+
+               if (!etnaviv_obj->vaddr) {
+                       kfree(etnaviv_obj);
+                       return -ENOMEM;
+               }
+       }
+
+       etnaviv_obj->flags = flags;
+
+       etnaviv_obj->resv = &etnaviv_obj->_resv;
+       reservation_object_init(etnaviv_obj->resv);
+
+       INIT_LIST_HEAD(&etnaviv_obj->submit_entry);
+       list_add_tail(&etnaviv_obj->mm_list, &priv->inactive_list);
+
+       *obj = &etnaviv_obj->base;
+
+       return 0;
+}
+
+struct drm_gem_object *etnaviv_gem_new(struct drm_device *dev,
+               uint32_t size, uint32_t flags)
+{
+       struct drm_gem_object *obj = NULL;
+       int ret;
+
+       WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+       size = PAGE_ALIGN(size);
+
+       ret = etnaviv_gem_new_impl(dev, size, flags, &obj);
+       if (ret)
+               goto fail;
+
+       ret = 0;
+       if (flags & ETNA_BO_CMDSTREAM)
+               drm_gem_private_object_init(dev, obj, size);
+       else
+               ret = drm_gem_object_init(dev, obj, size);
+
+       if (ret)
+               goto fail;
+
+       return obj;
+
+fail:
+       if (obj)
+               drm_gem_object_unreference(obj);
+
+       return ERR_PTR(ret);
+}
+
+struct drm_gem_object *msm_gem_import(struct drm_device *dev,
+               uint32_t size, struct sg_table *sgt)
+{
+       struct etnaviv_gem_object *etnaviv_obj;
+       struct drm_gem_object *obj;
+       int ret, npages;
+
+       size = PAGE_ALIGN(size);
+
+       ret = etnaviv_gem_new_impl(dev, size, ETNA_BO_WC, &obj);
+       if (ret)
+               goto fail;
+
+       drm_gem_private_object_init(dev, obj, size);
+
+       npages = size / PAGE_SIZE;
+
+       etnaviv_obj = to_etnaviv_bo(obj);
+       etnaviv_obj->sgt = sgt;
+       etnaviv_obj->pages = drm_malloc_ab(npages, sizeof(struct page *));
+       if (!etnaviv_obj->pages) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       ret = drm_prime_sg_to_page_addr_arrays(sgt, etnaviv_obj->pages, NULL, 
npages);
+       if (ret)
+               goto fail;
+
+       return obj;
+
+fail:
+       if (obj)
+               drm_gem_object_unreference_unlocked(obj);
+
+       return ERR_PTR(ret);
+}
diff --git a/drivers/staging/etnaviv/etnaviv_gem.h 
b/drivers/staging/etnaviv/etnaviv_gem.h
new file mode 100644
index 000000000000..597ff8233fb1
--- /dev/null
+++ b/drivers/staging/etnaviv/etnaviv_gem.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ETNAVIV_GEM_H__
+#define __ETNAVIV_GEM_H__
+
+#include <linux/reservation.h>
+#include "etnaviv_drv.h"
+
+struct etnaviv_gem_object {
+       struct drm_gem_object base;
+
+       uint32_t flags;
+
+       /* And object is either:
+        *  inactive - on priv->inactive_list
+        *  active   - on one one of the gpu's active_list..  well, at
+        *     least for now we don't have (I don't think) hw sync between
+        *     2d and 3d one devices which have both, meaning we need to
+        *     block on submit if a bo is already on other ring
+        *
+        */
+       struct list_head mm_list;
+       struct etnaviv_gpu *gpu;     /* non-null if active */
+       uint32_t read_fence, write_fence;
+
+       /* Transiently in the process of submit ioctl, objects associated
+        * with the submit are on submit->bo_list.. this only lasts for
+        * the duration of the ioctl, so one bo can never be on multiple
+        * submit lists.
+        */
+       struct list_head submit_entry;
+
+       struct page **pages;
+       struct sg_table *sgt;
+       void *vaddr;
+       uint32_t iova;
+
+       /* for ETNA_BO_CMDSTREAM */
+       dma_addr_t paddr;
+
+       /* normally (resv == &_resv) except for imported bo's */
+       struct reservation_object *resv;
+       struct reservation_object _resv;
+
+       struct drm_mm_node *gpu_vram_node;
+
+       /* for buffer manipulation during submit */
+       u32 offset;
+};
+#define to_etnaviv_bo(x) container_of(x, struct etnaviv_gem_object, base)
+
+static inline bool is_active(struct etnaviv_gem_object *etnaviv_obj)
+{
+       return etnaviv_obj->gpu != NULL;
+}
+
+#define MAX_CMDS 4
+
+/* Created per submit-ioctl, to track bo's and cmdstream bufs, etc,
+ * associated with the cmdstream submission for synchronization (and
+ * make it easier to unwind when things go wrong, etc).  This only
+ * lasts for the duration of the submit-ioctl.
+ */
+struct etnaviv_gem_submit {
+       struct drm_device *dev;
+       struct etnaviv_gpu *gpu;
+       struct list_head bo_list;
+       struct ww_acquire_ctx ticket;
+       uint32_t fence;
+       bool valid;
+       unsigned int nr_cmds;
+       unsigned int nr_bos;
+       struct {
+               uint32_t type;
+               uint32_t size;  /* in dwords */
+               struct etnaviv_gem_object *obj;
+       } cmd[MAX_CMDS];
+       struct {
+               uint32_t flags;
+               struct etnaviv_gem_object *obj;
+               uint32_t iova;
+       } bos[0];
+};
+
+#endif /* __ETNAVIV_GEM_H__ */
diff --git a/drivers/staging/etnaviv/etnaviv_gem_prime.c 
b/drivers/staging/etnaviv/etnaviv_gem_prime.c
new file mode 100644
index 000000000000..78dd843a8e97
--- /dev/null
+++ b/drivers/staging/etnaviv/etnaviv_gem_prime.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "etnaviv_drv.h"
+#include "etnaviv_gem.h"
+
+
+struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj)
+{
+       struct etnaviv_gem_object *etnaviv_obj= to_etnaviv_bo(obj);
+       BUG_ON(!etnaviv_obj->sgt);  /* should have already pinned! */
+       return etnaviv_obj->sgt;
+}
+
+void *msm_gem_prime_vmap(struct drm_gem_object *obj)
+{
+       return msm_gem_vaddr(obj);
+}
+
+void msm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
+{
+       /* TODO msm_gem_vunmap() */
+}
+
+struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev,
+               size_t size, struct sg_table *sg)
+{
+       return msm_gem_import(dev, size, sg);
+}
+
+int msm_gem_prime_pin(struct drm_gem_object *obj)
+{
+       if (!obj->import_attach)
+               etnaviv_gem_get_pages(obj);
+       return 0;
+}
+
+void msm_gem_prime_unpin(struct drm_gem_object *obj)
+{
+       if (!obj->import_attach)
+               msm_gem_put_pages(obj);
+}
diff --git a/drivers/staging/etnaviv/etnaviv_gem_submit.c 
b/drivers/staging/etnaviv/etnaviv_gem_submit.c
new file mode 100644
index 000000000000..dd87fdfe7ab5
--- /dev/null
+++ b/drivers/staging/etnaviv/etnaviv_gem_submit.c
@@ -0,0 +1,407 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "etnaviv_drv.h"
+#include "etnaviv_gpu.h"
+#include "etnaviv_gem.h"
+
+/*
+ * Cmdstream submission:
+ */
+
+#define BO_INVALID_FLAGS ~(ETNA_SUBMIT_BO_READ | ETNA_SUBMIT_BO_WRITE)
+/* make sure these don't conflict w/ MSM_SUBMIT_BO_x */
+#define BO_VALID    0x8000
+#define BO_LOCKED   0x4000
+#define BO_PINNED   0x2000
+
+static inline void __user *to_user_ptr(u64 address)
+{
+       return (void __user *)(uintptr_t)address;
+}
+
+static struct etnaviv_gem_submit *submit_create(struct drm_device *dev,
+               struct etnaviv_gpu *gpu, int nr)
+{
+       struct etnaviv_gem_submit *submit;
+       int sz = sizeof(*submit) + (nr * sizeof(submit->bos[0]));
+
+       submit = kmalloc(sz, GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY);
+       if (submit) {
+               submit->dev = dev;
+               submit->gpu = gpu;
+
+               /* initially, until copy_from_user() and bo lookup succeeds: */
+               submit->nr_bos = 0;
+               submit->nr_cmds = 0;
+
+               INIT_LIST_HEAD(&submit->bo_list);
+               ww_acquire_init(&submit->ticket, &reservation_ww_class);
+       }
+
+       return submit;
+}
+
+static int submit_lookup_objects(struct etnaviv_gem_submit *submit,
+               struct drm_etnaviv_gem_submit *args, struct drm_file *file)
+{
+       unsigned i;
+       int ret = 0;
+
+       spin_lock(&file->table_lock);
+
+       for (i = 0; i < args->nr_bos; i++) {
+               struct drm_etnaviv_gem_submit_bo submit_bo;
+               struct drm_gem_object *obj;
+               struct etnaviv_gem_object *etnaviv_obj;
+               void __user *userptr =
+                       to_user_ptr(args->bos + (i * sizeof(submit_bo)));
+
+               ret = copy_from_user(&submit_bo, userptr, sizeof(submit_bo));
+               if (ret) {
+                       ret = -EFAULT;
+                       goto out_unlock;
+               }
+
+               if (submit_bo.flags & BO_INVALID_FLAGS) {
+                       DRM_ERROR("invalid flags: %x\n", submit_bo.flags);
+                       ret = -EINVAL;
+                       goto out_unlock;
+               }
+
+               submit->bos[i].flags = submit_bo.flags;
+               /* in validate_objects() we figure out if this is true: */
+               submit->bos[i].iova  = submit_bo.presumed;
+
+               /* normally use drm_gem_object_lookup(), but for bulk lookup
+                * all under single table_lock just hit object_idr directly:
+                */
+               obj = idr_find(&file->object_idr, submit_bo.handle);
+               if (!obj) {
+                       DRM_ERROR("invalid handle %u at index %u\n", 
submit_bo.handle, i);
+                       ret = -EINVAL;
+                       goto out_unlock;
+               }
+
+               etnaviv_obj = to_etnaviv_bo(obj);
+
+               if (!list_empty(&etnaviv_obj->submit_entry)) {
+                       DRM_ERROR("handle %u at index %u already on submit 
list\n",
+                                       submit_bo.handle, i);
+                       ret = -EINVAL;
+                       goto out_unlock;
+               }
+
+               drm_gem_object_reference(obj);
+
+               submit->bos[i].obj = etnaviv_obj;
+
+               list_add_tail(&etnaviv_obj->submit_entry, &submit->bo_list);
+       }
+
+out_unlock:
+       submit->nr_bos = i;
+       spin_unlock(&file->table_lock);
+
+       return ret;
+}
+
+static void submit_unlock_unpin_bo(struct etnaviv_gem_submit *submit, int i)
+{
+       struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;
+
+       if (submit->bos[i].flags & BO_PINNED)
+               etnaviv_gem_put_iova(&etnaviv_obj->base);
+
+       if (submit->bos[i].flags & BO_LOCKED)
+               ww_mutex_unlock(&etnaviv_obj->resv->lock);
+
+       if (!(submit->bos[i].flags & BO_VALID))
+               submit->bos[i].iova = 0;
+
+       submit->bos[i].flags &= ~(BO_LOCKED | BO_PINNED);
+}
+
+/* This is where we make sure all the bo's are reserved and pin'd: */
+static int submit_validate_objects(struct etnaviv_gem_submit *submit)
+{
+       int contended, slow_locked = -1, i, ret = 0;
+
+retry:
+       submit->valid = true;
+
+       for (i = 0; i < submit->nr_bos; i++) {
+               struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;
+               uint32_t iova;
+
+               if (slow_locked == i)
+                       slow_locked = -1;
+
+               contended = i;
+
+               if (!(submit->bos[i].flags & BO_LOCKED)) {
+                       ret = 
ww_mutex_lock_interruptible(&etnaviv_obj->resv->lock,
+                                       &submit->ticket);
+                       if (ret)
+                               goto fail;
+                       submit->bos[i].flags |= BO_LOCKED;
+               }
+
+
+               /* if locking succeeded, pin bo: */
+               ret = etnaviv_gem_get_iova_locked(submit->gpu, 
&etnaviv_obj->base, &iova);
+
+               /* this would break the logic in the fail path.. there is no
+                * reason for this to happen, but just to be on the safe side
+                * let's notice if this starts happening in the future:
+                */
+               WARN_ON(ret == -EDEADLK);
+
+               if (ret)
+                       goto fail;
+
+               submit->bos[i].flags |= BO_PINNED;
+
+               if (iova == submit->bos[i].iova) {
+                       submit->bos[i].flags |= BO_VALID;
+               } else {
+                       submit->bos[i].iova = iova;
+                       submit->bos[i].flags &= ~BO_VALID;
+                       submit->valid = false;
+               }
+       }
+
+       ww_acquire_done(&submit->ticket);
+
+       return 0;
+
+fail:
+       for (; i >= 0; i--)
+               submit_unlock_unpin_bo(submit, i);
+
+       if (slow_locked > 0)
+               submit_unlock_unpin_bo(submit, slow_locked);
+
+       if (ret == -EDEADLK) {
+               struct etnaviv_gem_object *etnaviv_obj = 
submit->bos[contended].obj;
+               /* we lost out in a seqno race, lock and retry.. */
+               ret = ww_mutex_lock_slow_interruptible(&etnaviv_obj->resv->lock,
+                               &submit->ticket);
+               if (!ret) {
+                       submit->bos[contended].flags |= BO_LOCKED;
+                       slow_locked = contended;
+                       goto retry;
+               }
+       }
+
+       return ret;
+}
+
+static int submit_bo(struct etnaviv_gem_submit *submit, uint32_t idx,
+               struct etnaviv_gem_object **obj, uint32_t *iova, bool *valid)
+{
+       if (idx >= submit->nr_bos) {
+               DRM_ERROR("invalid buffer index: %u (out of %u)\n",
+                               idx, submit->nr_bos);
+               return -EINVAL;
+       }
+
+       if (obj)
+               *obj = submit->bos[idx].obj;
+       if (iova)
+               *iova = submit->bos[idx].iova;
+       if (valid)
+               *valid = !!(submit->bos[idx].flags & BO_VALID);
+
+       return 0;
+}
+
+/* process the reloc's and patch up the cmdstream as needed: */
+static int submit_reloc(struct etnaviv_gem_submit *submit, struct 
etnaviv_gem_object *obj,
+               uint32_t offset, uint32_t nr_relocs, uint64_t relocs)
+{
+       uint32_t i, last_offset = 0;
+       uint32_t *ptr = obj->vaddr;
+       int ret;
+
+       if (offset % 4) {
+               DRM_ERROR("non-aligned cmdstream buffer: %u\n", offset);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < nr_relocs; i++) {
+               struct drm_etnaviv_gem_submit_reloc submit_reloc;
+               void __user *userptr =
+                       to_user_ptr(relocs + (i * sizeof(submit_reloc)));
+               uint32_t iova, off;
+               bool valid;
+
+               ret = copy_from_user(&submit_reloc, userptr, 
sizeof(submit_reloc));
+               if (ret)
+                       return -EFAULT;
+
+               if (submit_reloc.submit_offset % 4) {
+                       DRM_ERROR("non-aligned reloc offset: %u\n",
+                                       submit_reloc.submit_offset);
+                       return -EINVAL;
+               }
+
+               /* offset in dwords: */
+               off = submit_reloc.submit_offset / 4;
+
+               if ((off >= (obj->base.size / 4)) ||
+                               (off < last_offset)) {
+                       DRM_ERROR("invalid offset %u at reloc %u\n", off, i);
+                       return -EINVAL;
+               }
+
+               ret = submit_bo(submit, submit_reloc.reloc_idx, NULL, &iova, 
&valid);
+               if (ret)
+                       return ret;
+
+               if (valid)
+                       continue;
+
+               iova += submit_reloc.reloc_offset;
+
+               if (submit_reloc.shift < 0)
+                       iova >>= -submit_reloc.shift;
+               else
+                       iova <<= submit_reloc.shift;
+
+               ptr[off] = iova | submit_reloc.or;
+
+               last_offset = off;
+       }
+
+       return 0;
+}
+
+static void submit_cleanup(struct etnaviv_gem_submit *submit, bool fail)
+{
+       unsigned i;
+
+       for (i = 0; i < submit->nr_bos; i++) {
+               struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;
+               submit_unlock_unpin_bo(submit, i);
+               list_del_init(&etnaviv_obj->submit_entry);
+               drm_gem_object_unreference(&etnaviv_obj->base);
+       }
+
+       ww_acquire_fini(&submit->ticket);
+       kfree(submit);
+}
+
+int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
+               struct drm_file *file)
+{
+       struct etnaviv_drm_private *priv = dev->dev_private;
+       struct drm_etnaviv_gem_submit *args = data;
+       struct etnaviv_file_private *ctx = file->driver_priv;
+       struct etnaviv_gem_submit *submit;
+       struct etnaviv_gpu *gpu;
+       unsigned i;
+       int ret;
+
+       if (args->pipe >= ETNA_MAX_PIPES)
+               return -EINVAL;
+
+       gpu = priv->gpu[args->pipe];
+       if (!gpu)
+               return -ENXIO;
+
+       if (args->nr_cmds > MAX_CMDS)
+               return -EINVAL;
+
+       mutex_lock(&dev->struct_mutex);
+
+       submit = submit_create(dev, gpu, args->nr_bos);
+       if (!submit) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       ret = submit_lookup_objects(submit, args, file);
+       if (ret)
+               goto out;
+
+       ret = submit_validate_objects(submit);
+       if (ret)
+               goto out;
+
+       for (i = 0; i < args->nr_cmds; i++) {
+               struct drm_etnaviv_gem_submit_cmd submit_cmd;
+               void __user *userptr =
+                       to_user_ptr(args->cmds + (i * sizeof(submit_cmd)));
+               struct etnaviv_gem_object *etnaviv_obj;
+
+               ret = copy_from_user(&submit_cmd, userptr, sizeof(submit_cmd));
+               if (ret) {
+                       ret = -EFAULT;
+                       goto out;
+               }
+
+               ret = submit_bo(submit, submit_cmd.submit_idx,
+                               &etnaviv_obj, NULL, NULL);
+               if (ret)
+                       goto out;
+
+               if (!(etnaviv_obj->flags & ETNA_BO_CMDSTREAM)) {
+                       DRM_ERROR("cmdstream bo has flag ETNA_BO_CMDSTREAM not 
set\n");
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               if (submit_cmd.size % 4) {
+                       DRM_ERROR("non-aligned cmdstream buffer size: %u\n",
+                                       submit_cmd.size);
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               if ((submit_cmd.size + submit_cmd.submit_offset) >=
+                               etnaviv_obj->base.size) {
+                       DRM_ERROR("invalid cmdstream size: %u\n", 
submit_cmd.size);
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               submit->cmd[i].type = submit_cmd.type;
+               submit->cmd[i].size = submit_cmd.size / 4;
+               submit->cmd[i].obj = etnaviv_obj;
+
+               if (submit->valid)
+                       continue;
+
+               ret = submit_reloc(submit, etnaviv_obj, 
submit_cmd.submit_offset,
+                               submit_cmd.nr_relocs, submit_cmd.relocs);
+               if (ret)
+                       goto out;
+       }
+
+       submit->nr_cmds = i;
+
+       ret = etnaviv_gpu_submit(gpu, submit, ctx);
+
+       args->fence = submit->fence;
+
+out:
+       if (submit)
+               submit_cleanup(submit, !!ret);
+       mutex_unlock(&dev->struct_mutex);
+       return ret;
+}
diff --git a/drivers/staging/etnaviv/etnaviv_gpu.c 
b/drivers/staging/etnaviv/etnaviv_gpu.c
new file mode 100644
index 000000000000..d2d0556a9bad
--- /dev/null
+++ b/drivers/staging/etnaviv/etnaviv_gpu.c
@@ -0,0 +1,984 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/component.h>
+#include <linux/of_device.h>
+#include "etnaviv_gpu.h"
+#include "etnaviv_gem.h"
+#include "etnaviv_mmu.h"
+#include "etnaviv_iommu.h"
+#include "etnaviv_iommu_v2.h"
+#include "common.xml.h"
+#include "state.xml.h"
+#include "state_hi.xml.h"
+#include "cmdstream.xml.h"
+
+
+/*
+ * Driver functions:
+ */
+
+int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, uint32_t param, uint64_t 
*value)
+{
+       switch (param) {
+       case ETNAVIV_PARAM_GPU_MODEL:
+               *value = gpu->identity.model;
+               break;
+
+       case ETNAVIV_PARAM_GPU_REVISION:
+               *value = gpu->identity.revision;
+               break;
+
+       case ETNAVIV_PARAM_GPU_FEATURES_0:
+               *value = gpu->identity.features;
+               break;
+
+       case ETNAVIV_PARAM_GPU_FEATURES_1:
+               *value = gpu->identity.minor_features0;
+               break;
+
+       case ETNAVIV_PARAM_GPU_FEATURES_2:
+               *value = gpu->identity.minor_features1;
+               break;
+
+       case ETNAVIV_PARAM_GPU_FEATURES_3:
+               *value = gpu->identity.minor_features2;
+               break;
+
+       case ETNAVIV_PARAM_GPU_FEATURES_4:
+               *value = gpu->identity.minor_features3;
+               break;
+
+       case ETNAVIV_PARAM_GPU_STREAM_COUNT:
+               *value = gpu->identity.stream_count;
+               break;
+
+       case ETNAVIV_PARAM_GPU_REGISTER_MAX:
+               *value = gpu->identity.register_max;
+               break;
+
+       case ETNAVIV_PARAM_GPU_THREAD_COUNT:
+               *value = gpu->identity.thread_count;
+               break;
+
+       case ETNAVIV_PARAM_GPU_VERTEX_CACHE_SIZE:
+               *value = gpu->identity.vertex_cache_size;
+               break;
+
+       case ETNAVIV_PARAM_GPU_SHADER_CORE_COUNT:
+               *value = gpu->identity.shader_core_count;
+               break;
+
+       case ETNAVIV_PARAM_GPU_PIXEL_PIPES:
+               *value = gpu->identity.pixel_pipes;
+               break;
+
+       case ETNAVIV_PARAM_GPU_VERTEX_OUTPUT_BUFFER_SIZE:
+               *value = gpu->identity.vertex_output_buffer_size;
+               break;
+
+       case ETNAVIV_PARAM_GPU_BUFFER_SIZE:
+               *value = gpu->identity.buffer_size;
+               break;
+
+       case ETNAVIV_PARAM_GPU_INSTRUCTION_COUNT:
+               *value = gpu->identity.instruction_count;
+               break;
+
+       case ETNAVIV_PARAM_GPU_NUM_CONSTANTS:
+               *value = gpu->identity.num_constants;
+               break;
+
+       default:
+               DBG("%s: invalid param: %u", gpu->name, param);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void etnaviv_hw_specs(struct etnaviv_gpu *gpu)
+{
+       if (gpu->identity.minor_features0 & 
chipMinorFeatures0_MORE_MINOR_FEATURES) {
+               u32 specs[2];
+
+               specs[0] = gpu_read(gpu, VIVS_HI_CHIP_SPECS);
+               specs[1] = gpu_read(gpu, VIVS_HI_CHIP_SPECS_2);
+
+               gpu->identity.stream_count = (specs[0] & 
VIVS_HI_CHIP_SPECS_STREAM_COUNT__MASK)
+                               >> VIVS_HI_CHIP_SPECS_STREAM_COUNT__SHIFT;
+               gpu->identity.register_max = (specs[0] & 
VIVS_HI_CHIP_SPECS_REGISTER_MAX__MASK)
+                               >> VIVS_HI_CHIP_SPECS_REGISTER_MAX__SHIFT;
+               gpu->identity.thread_count = (specs[0] & 
VIVS_HI_CHIP_SPECS_THREAD_COUNT__MASK)
+                               >> VIVS_HI_CHIP_SPECS_THREAD_COUNT__SHIFT;
+               gpu->identity.vertex_cache_size = (specs[0] & 
VIVS_HI_CHIP_SPECS_VERTEX_CACHE_SIZE__MASK)
+                               >> VIVS_HI_CHIP_SPECS_VERTEX_CACHE_SIZE__SHIFT;
+               gpu->identity.shader_core_count = (specs[0] & 
VIVS_HI_CHIP_SPECS_SHADER_CORE_COUNT__MASK)
+                               >> VIVS_HI_CHIP_SPECS_SHADER_CORE_COUNT__SHIFT;
+               gpu->identity.pixel_pipes = (specs[0] & 
VIVS_HI_CHIP_SPECS_PIXEL_PIPES__MASK)
+                               >> VIVS_HI_CHIP_SPECS_PIXEL_PIPES__SHIFT;
+               gpu->identity.vertex_output_buffer_size = (specs[0] & 
VIVS_HI_CHIP_SPECS_VERTEX_OUTPUT_BUFFER_SIZE__MASK)
+                               >> 
VIVS_HI_CHIP_SPECS_VERTEX_OUTPUT_BUFFER_SIZE__SHIFT;
+
+               gpu->identity.buffer_size = (specs[1] & 
VIVS_HI_CHIP_SPECS_2_BUFFER_SIZE__MASK)
+                               >> VIVS_HI_CHIP_SPECS_2_BUFFER_SIZE__SHIFT;
+               gpu->identity.instruction_count = (specs[1] & 
VIVS_HI_CHIP_SPECS_2_INSTRUCTION_COUNT__MASK)
+                               >> 
VIVS_HI_CHIP_SPECS_2_INSTRUCTION_COUNT__SHIFT;
+               gpu->identity.num_constants = (specs[1] & 
VIVS_HI_CHIP_SPECS_2_NUM_CONSTANTS__MASK)
+                               >> VIVS_HI_CHIP_SPECS_2_NUM_CONSTANTS__SHIFT;
+
+               gpu->identity.register_max = 1 << gpu->identity.register_max;
+               gpu->identity.thread_count = 1 << gpu->identity.thread_count;
+               gpu->identity.vertex_output_buffer_size = 1 << 
gpu->identity.vertex_output_buffer_size;
+       } else {
+               dev_err(gpu->dev->dev, "TODO: determine GPU specs based on 
model\n");
+       }
+
+       switch (gpu->identity.instruction_count) {
+       case 0:
+               gpu->identity.instruction_count = 256;
+               break;
+
+       case 1:
+               gpu->identity.instruction_count = 1024;
+               break;
+
+       case 2:
+               gpu->identity.instruction_count = 2048;
+               break;
+
+       default:
+               gpu->identity.instruction_count = 256;
+               break;
+       }
+
+       dev_info(gpu->dev->dev, "stream_count:  %x\n", 
gpu->identity.stream_count);
+       dev_info(gpu->dev->dev, "register_max: %x\n", 
gpu->identity.register_max);
+       dev_info(gpu->dev->dev, "thread_count: %x\n", 
gpu->identity.thread_count);
+       dev_info(gpu->dev->dev, "vertex_cache_size: %x\n", 
gpu->identity.vertex_cache_size);
+       dev_info(gpu->dev->dev, "shader_core_count: %x\n", 
gpu->identity.shader_core_count);
+       dev_info(gpu->dev->dev, "pixel_pipes: %x\n", gpu->identity.pixel_pipes);
+       dev_info(gpu->dev->dev, "vertex_output_buffer_size: %x\n", 
gpu->identity.vertex_output_buffer_size);
+       dev_info(gpu->dev->dev, "buffer_size: %x\n", gpu->identity.buffer_size);
+       dev_info(gpu->dev->dev, "instruction_count: %x\n", 
gpu->identity.instruction_count);
+       dev_info(gpu->dev->dev, "num_constants: %x\n", 
gpu->identity.num_constants);
+}
+
+static void etnaviv_hw_identify(struct etnaviv_gpu *gpu)
+{
+       u32 chipIdentity;
+
+       chipIdentity = gpu_read(gpu, VIVS_HI_CHIP_IDENTITY);
+
+       /* Special case for older graphic cores. */
+       if (VIVS_HI_CHIP_IDENTITY_FAMILY(chipIdentity) ==  0x01) {
+               gpu->identity.model    = 0x500; /* gc500 */
+               gpu->identity.revision = 
VIVS_HI_CHIP_IDENTITY_REVISION(chipIdentity);
+       } else {
+
+               gpu->identity.model = gpu_read(gpu, VIVS_HI_CHIP_MODEL);
+               gpu->identity.revision = gpu_read(gpu, VIVS_HI_CHIP_REV);
+
+               /* !!!! HACK ALERT !!!! */
+               /* Because people change device IDs without letting software 
know
+               ** about it - here is the hack to make it all look the same.  
Only
+               ** for GC400 family.  Next time - TELL ME!!! */
+               if (((gpu->identity.model & 0xFF00) == 0x0400)
+               && (gpu->identity.model != 0x0420)) {
+                       gpu->identity.model = gpu->identity.model & 0x0400;
+               }
+
+               /* An other special case */
+               if ((gpu->identity.model    == 0x300)
+               &&  (gpu->identity.revision == 0x2201)) {
+                       u32 chipDate = gpu_read(gpu, VIVS_HI_CHIP_DATE);
+                       u32 chipTime = gpu_read(gpu, VIVS_HI_CHIP_TIME);
+
+                       if ((chipDate == 0x20080814) && (chipTime == 
0x12051100)) {
+                               /* This IP has an ECO; put the correct revision 
in it. */
+                               gpu->identity.revision = 0x1051;
+                       }
+               }
+       }
+
+       dev_info(gpu->dev->dev, "model: %x\n", gpu->identity.model);
+       dev_info(gpu->dev->dev, "revision: %x\n", gpu->identity.revision);
+
+       gpu->identity.features = gpu_read(gpu, VIVS_HI_CHIP_FEATURE);
+
+       /* Disable fast clear on GC700. */
+       if (gpu->identity.model == 0x700)
+               gpu->identity.features &= ~BIT(0);
+
+       if (((gpu->identity.model == 0x500) && (gpu->identity.revision < 2))
+       ||  ((gpu->identity.model == 0x300) && (gpu->identity.revision < 
0x2000))) {
+
+               /* GC500 rev 1.x and GC300 rev < 2.0 doesn't have these 
registers. */
+               gpu->identity.minor_features0 = 0;
+               gpu->identity.minor_features1 = 0;
+               gpu->identity.minor_features2 = 0;
+               gpu->identity.minor_features3 = 0;
+       } else
+               gpu->identity.minor_features0 = gpu_read(gpu, 
VIVS_HI_CHIP_MINOR_FEATURE_0);
+
+       if (gpu->identity.minor_features0 & BIT(21)) {
+               gpu->identity.minor_features1 = gpu_read(gpu, 
VIVS_HI_CHIP_MINOR_FEATURE_1);
+               gpu->identity.minor_features2 = gpu_read(gpu, 
VIVS_HI_CHIP_MINOR_FEATURE_2);
+               gpu->identity.minor_features3 = gpu_read(gpu, 
VIVS_HI_CHIP_MINOR_FEATURE_3);
+       }
+
+       dev_info(gpu->dev->dev, "minor_features:  %x\n", 
gpu->identity.minor_features0);
+       dev_info(gpu->dev->dev, "minor_features1: %x\n", 
gpu->identity.minor_features1);
+       dev_info(gpu->dev->dev, "minor_features2: %x\n", 
gpu->identity.minor_features2);
+       dev_info(gpu->dev->dev, "minor_features3: %x\n", 
gpu->identity.minor_features3);
+
+       etnaviv_hw_specs(gpu);
+}
+
+static void etnaviv_hw_reset(struct etnaviv_gpu *gpu)
+{
+       u32 control, idle;
+
+       /* TODO
+        *
+        * - clock gating
+        * - puls eater
+        * - what about VG?
+        */
+
+       while (true) {
+               control = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
+
+               /* isolate the GPU. */
+               control |= VIVS_HI_CLOCK_CONTROL_ISOLATE_GPU;
+               gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);
+
+               /* set soft reset. */
+               control |= VIVS_HI_CLOCK_CONTROL_SOFT_RESET;
+               gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);
+
+               /* wait for reset. */
+               msleep(1);
+
+               /* reset soft reset bit. */
+               control &= ~VIVS_HI_CLOCK_CONTROL_SOFT_RESET;
+               gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);
+
+               /* reset GPU isolation. */
+               control &= ~VIVS_HI_CLOCK_CONTROL_ISOLATE_GPU;
+               gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);
+
+               /* read idle register. */
+               idle = gpu_read(gpu, VIVS_HI_IDLE_STATE);
+
+               /* try reseting again if FE it not idle */
+               if ((idle & VIVS_HI_IDLE_STATE_FE) == 0) {
+                       dev_dbg(gpu->dev->dev, "%s: FE is not idle\n", 
gpu->name);
+                       continue;
+               }
+
+               /* read reset register. */
+               control = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
+
+               /* is the GPU idle? */
+               if (((control & VIVS_HI_CLOCK_CONTROL_IDLE_3D) == 0)
+               || ((control & VIVS_HI_CLOCK_CONTROL_IDLE_2D) == 0)) {
+                       dev_dbg(gpu->dev->dev, "%s: GPU is not idle\n", 
gpu->name);
+                       continue;
+               }
+
+               break;
+       }
+}
+
+int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
+{
+       int ret, i;
+       u32 words; /* 32 bit words */
+       struct iommu_domain *iommu;
+       bool mmuv2;
+
+       etnaviv_hw_identify(gpu);
+       etnaviv_hw_reset(gpu);
+
+       /* set base addresses */
+       gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_RA, 0x0);
+       gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_FE, 0x0);
+       gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_TX, 0x0);
+       gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_PEZ, 0x0);
+       gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_PE, 0x0);
+
+       /* Setup IOMMU.. eventually we will (I think) do this once per context
+        * and have separate page tables per context.  For now, to keep things
+        * simple and to get something working, just use a single address space:
+        */
+       mmuv2 = gpu->identity.minor_features1 & chipMinorFeatures1_MMU_VERSION;
+       dev_dbg(gpu->dev->dev, "mmuv2: %d\n", mmuv2);
+
+       if (!mmuv2)
+               iommu = etnaviv_iommu_domain_alloc(gpu);
+       else
+               iommu = etnaviv_iommu_v2_domain_alloc(gpu);
+
+       if (!iommu) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       /* TODO: we will leak here memory - fix it! */
+
+       gpu->mmu = etnaviv_iommu_new(gpu->dev, iommu);
+       if (!gpu->mmu) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+       etnaviv_register_mmu(gpu->dev, gpu->mmu);
+
+       /* Create buffer: */
+       gpu->buffer = etnaviv_gem_new(gpu->dev, PAGE_SIZE, ETNA_BO_CMDSTREAM);
+       if (IS_ERR(gpu->buffer)) {
+               ret = PTR_ERR(gpu->buffer);
+               gpu->buffer = NULL;
+               dev_err(gpu->dev->dev, "could not create buffer: %d\n", ret);
+               goto fail;
+       }
+
+       /* Setup event management */
+       spin_lock_init(&gpu->event_spinlock);
+       init_completion(&gpu->event_free);
+       for (i = 0; i < ARRAY_SIZE(gpu->event_used); i++) {
+               gpu->event_used[i] = false;
+               complete(&gpu->event_free);
+       }
+
+       /* Start command processor */
+       words = etnaviv_buffer_init(gpu);
+
+       /* convert number of 32 bit words to number of 64 bit words */
+       words = ALIGN(words, 2) / 2;
+
+       gpu_write(gpu, VIVS_HI_INTR_ENBL, ~0U);
+       gpu_write(gpu, VIVS_FE_COMMAND_ADDRESS, 
etnaviv_gem_paddr_locked(gpu->buffer));
+       gpu_write(gpu, VIVS_FE_COMMAND_CONTROL, VIVS_FE_COMMAND_CONTROL_ENABLE 
| VIVS_FE_COMMAND_CONTROL_PREFETCH(words));
+
+       return 0;
+
+fail:
+       return ret;
+}
+
+#ifdef CONFIG_DEBUG_FS
+struct dma_debug {
+       u32 address[2];
+       u32 state[2];
+};
+
+static void verify_dma(struct etnaviv_gpu *gpu, struct dma_debug *debug)
+{
+       u32 i;
+
+       debug->address[0] = gpu_read(gpu, VIVS_FE_DMA_ADDRESS);
+       debug->state[0]   = gpu_read(gpu, VIVS_FE_DMA_DEBUG_STATE);
+
+       for (i = 0; i < 500; i++) {
+               debug->address[1] = gpu_read(gpu, VIVS_FE_DMA_ADDRESS);
+               debug->state[1]   = gpu_read(gpu, VIVS_FE_DMA_DEBUG_STATE);
+
+               if (debug->address[0] != debug->address[1])
+                       break;
+
+               if (debug->state[0] != debug->state[1])
+                       break;
+       }
+}
+
+void etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m)
+{
+       struct dma_debug debug;
+       u32 dma_lo = gpu_read(gpu, VIVS_FE_DMA_LOW);
+       u32 dma_hi = gpu_read(gpu, VIVS_FE_DMA_HIGH);
+       u32 axi = gpu_read(gpu, VIVS_HI_AXI_STATUS);
+       u32 idle = gpu_read(gpu, VIVS_HI_IDLE_STATE);
+
+       verify_dma(gpu, &debug);
+
+       seq_printf(m, "\taxi: 0x08%x\n", axi);
+       seq_printf(m, "\tidle: 0x08%x\n", idle);
+       if ((idle & VIVS_HI_IDLE_STATE_FE) == 0)
+               seq_puts(m, "\t FE is not idle\n");
+       if ((idle & VIVS_HI_IDLE_STATE_DE) == 0)
+               seq_puts(m, "\t DE is not idle\n");
+       if ((idle & VIVS_HI_IDLE_STATE_PE) == 0)
+               seq_puts(m, "\t PE is not idle\n");
+       if ((idle & VIVS_HI_IDLE_STATE_SH) == 0)
+               seq_puts(m, "\t SH is not idle\n");
+       if ((idle & VIVS_HI_IDLE_STATE_PA) == 0)
+               seq_puts(m, "\t PA is not idle\n");
+       if ((idle & VIVS_HI_IDLE_STATE_SE) == 0)
+               seq_puts(m, "\t SE is not idle\n");
+       if ((idle & VIVS_HI_IDLE_STATE_RA) == 0)
+               seq_puts(m, "\t RA is not idle\n");
+       if ((idle & VIVS_HI_IDLE_STATE_TX) == 0)
+               seq_puts(m, "\t TX is not idle\n");
+       if ((idle & VIVS_HI_IDLE_STATE_VG) == 0)
+               seq_puts(m, "\t VG is not idle\n");
+       if ((idle & VIVS_HI_IDLE_STATE_IM) == 0)
+               seq_puts(m, "\t IM is not idle\n");
+       if ((idle & VIVS_HI_IDLE_STATE_FP) == 0)
+               seq_puts(m, "\t FP is not idle\n");
+       if ((idle & VIVS_HI_IDLE_STATE_TS) == 0)
+               seq_puts(m, "\t TS is not idle\n");
+       if (idle & VIVS_HI_IDLE_STATE_AXI_LP)
+               seq_puts(m, "\t AXI low power mode\n");
+
+       if (gpu->identity.features & chipFeatures_DEBUG_MODE) {
+               u32 read0 = gpu_read(gpu, VIVS_MC_DEBUG_READ0);
+               u32 read1 = gpu_read(gpu, VIVS_MC_DEBUG_READ1);
+               u32 write = gpu_read(gpu, VIVS_MC_DEBUG_WRITE);
+
+               seq_puts(m, "\tMC\n");
+               seq_printf(m, "\t read0: 0x%08x\n", read0);
+               seq_printf(m, "\t read1: 0x%08x\n", read1);
+               seq_printf(m, "\t write: 0x%08x\n", write);
+       }
+
+       seq_puts(m, "\tDMA ");
+
+       if ((debug.address[0] == debug.address[1]) && (debug.state[0] == 
debug.state[1])) {
+               seq_puts(m, "seems to be stuck\n");
+       } else {
+               if (debug.address[0] == debug.address[1])
+                       seq_puts(m, "adress is constant\n");
+               else
+                       seq_puts(m, "is runing\n");
+       }
+
+       seq_printf(m, "\t address 0: 0x%08x\n", debug.address[0]);
+       seq_printf(m, "\t address 1: 0x%08x\n", debug.address[1]);
+       seq_printf(m, "\t state 0: 0x%08x\n", debug.state[0]);
+       seq_printf(m, "\t state 1: 0x%08x\n", debug.state[1]);
+       seq_printf(m, "\t last fetch 64 bit word: 0x%08x-0x%08x\n", dma_hi, 
dma_lo);
+}
+#endif
+
+/*
+ * Power Management:
+ */
+
+static int enable_pwrrail(struct etnaviv_gpu *gpu)
+{
+#if 0
+       struct drm_device *dev = gpu->dev;
+       int ret = 0;
+
+       if (gpu->gpu_reg) {
+               ret = regulator_enable(gpu->gpu_reg);
+               if (ret) {
+                       dev_err(dev->dev, "failed to enable 'gpu_reg': %d\n", 
ret);
+                       return ret;
+               }
+       }
+
+       if (gpu->gpu_cx) {
+               ret = regulator_enable(gpu->gpu_cx);
+               if (ret) {
+                       dev_err(dev->dev, "failed to enable 'gpu_cx': %d\n", 
ret);
+                       return ret;
+               }
+       }
+#endif
+       return 0;
+}
+
+static int disable_pwrrail(struct etnaviv_gpu *gpu)
+{
+#if 0
+       if (gpu->gpu_cx)
+               regulator_disable(gpu->gpu_cx);
+       if (gpu->gpu_reg)
+               regulator_disable(gpu->gpu_reg);
+#endif
+       return 0;
+}
+
+static int enable_clk(struct etnaviv_gpu *gpu)
+{
+       if (gpu->clk_core)
+               clk_prepare_enable(gpu->clk_core);
+       if (gpu->clk_shader)
+               clk_prepare_enable(gpu->clk_shader);
+
+       return 0;
+}
+
+static int disable_clk(struct etnaviv_gpu *gpu)
+{
+       if (gpu->clk_core)
+               clk_disable_unprepare(gpu->clk_core);
+       if (gpu->clk_shader)
+               clk_disable_unprepare(gpu->clk_shader);
+
+       return 0;
+}
+
+static int enable_axi(struct etnaviv_gpu *gpu)
+{
+       if (gpu->clk_bus)
+               clk_prepare_enable(gpu->clk_bus);
+
+       return 0;
+}
+
+static int disable_axi(struct etnaviv_gpu *gpu)
+{
+       if (gpu->clk_bus)
+               clk_disable_unprepare(gpu->clk_bus);
+
+       return 0;
+}
+
+int etnaviv_gpu_pm_resume(struct etnaviv_gpu *gpu)
+{
+       int ret;
+
+       DBG("%s", gpu->name);
+
+       ret = enable_pwrrail(gpu);
+       if (ret)
+               return ret;
+
+       ret = enable_clk(gpu);
+       if (ret)
+               return ret;
+
+       ret = enable_axi(gpu);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+int etnaviv_gpu_pm_suspend(struct etnaviv_gpu *gpu)
+{
+       int ret;
+
+       DBG("%s", gpu->name);
+
+       ret = disable_axi(gpu);
+       if (ret)
+               return ret;
+
+       ret = disable_clk(gpu);
+       if (ret)
+               return ret;
+
+       ret = disable_pwrrail(gpu);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+/*
+ * Hangcheck detection for locked gpu:
+ */
+static void recover_worker(struct work_struct *work)
+{
+       struct etnaviv_gpu *gpu = container_of(work, struct etnaviv_gpu, 
recover_work);
+       struct drm_device *dev = gpu->dev;
+
+       dev_err(dev->dev, "%s: hangcheck recover!\n", gpu->name);
+
+       mutex_lock(&dev->struct_mutex);
+       /* TODO gpu->funcs->recover(gpu); */
+       mutex_unlock(&dev->struct_mutex);
+
+       etnaviv_gpu_retire(gpu);
+}
+
+static void hangcheck_timer_reset(struct etnaviv_gpu *gpu)
+{
+       DBG("%s", gpu->name);
+       mod_timer(&gpu->hangcheck_timer,
+                       round_jiffies_up(jiffies + DRM_MSM_HANGCHECK_JIFFIES));
+}
+
+static void hangcheck_handler(unsigned long data)
+{
+       struct etnaviv_gpu *gpu = (struct etnaviv_gpu *)data;
+       struct drm_device *dev = gpu->dev;
+       struct etnaviv_drm_private *priv = dev->dev_private;
+       uint32_t fence = gpu->retired_fence;
+
+       if (fence != gpu->hangcheck_fence) {
+               /* some progress has been made.. ya! */
+               gpu->hangcheck_fence = fence;
+       } else if (fence < gpu->submitted_fence) {
+               /* no progress and not done.. hung! */
+               gpu->hangcheck_fence = fence;
+               dev_err(dev->dev, "%s: hangcheck detected gpu lockup!\n",
+                               gpu->name);
+               dev_err(dev->dev, "%s:     completed fence: %u\n",
+                               gpu->name, fence);
+               dev_err(dev->dev, "%s:     submitted fence: %u\n",
+                               gpu->name, gpu->submitted_fence);
+               queue_work(priv->wq, &gpu->recover_work);
+       }
+
+       /* if still more pending work, reset the hangcheck timer: */
+       if (gpu->submitted_fence > gpu->hangcheck_fence)
+               hangcheck_timer_reset(gpu);
+}
+
+/*
+ * event management:
+ */
+
+static unsigned int event_alloc(struct etnaviv_gpu *gpu)
+{
+       unsigned long ret, flags;
+       unsigned int i, event = ~0U;
+
+       ret = wait_for_completion_timeout(&gpu->event_free, msecs_to_jiffies(10 
* 10000));
+       if (!ret)
+               dev_err(gpu->dev->dev, "wait_for_completion_timeout failed");
+
+       spin_lock_irqsave(&gpu->event_spinlock, flags);
+
+       /* find first free event */
+       for (i = 0; i < ARRAY_SIZE(gpu->event_used); i++) {
+               if (gpu->event_used[i] == false) {
+                       gpu->event_used[i] = true;
+                       event = i;
+                       break;
+               }
+       }
+
+       spin_unlock_irqrestore(&gpu->event_spinlock, flags);
+
+       return event;
+}
+
+static void event_free(struct etnaviv_gpu *gpu, unsigned int event)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&gpu->event_spinlock, flags);
+
+       if (gpu->event_used[event] == false) {
+               dev_warn(gpu->dev->dev, "event %u is already marked as free", 
event);
+               spin_unlock_irqrestore(&gpu->event_spinlock, flags);
+       } else {
+               gpu->event_used[event] = false;
+               spin_unlock_irqrestore(&gpu->event_spinlock, flags);
+
+               complete(&gpu->event_free);
+       }
+}
+
+/*
+ * Cmdstream submission/retirement:
+ */
+
+static void retire_worker(struct work_struct *work)
+{
+       struct etnaviv_gpu *gpu = container_of(work, struct etnaviv_gpu, 
retire_work);
+       struct drm_device *dev = gpu->dev;
+       uint32_t fence = gpu->retired_fence;
+
+       etnaviv_update_fence(gpu->dev, fence);
+
+       mutex_lock(&dev->struct_mutex);
+
+       while (!list_empty(&gpu->active_list)) {
+               struct etnaviv_gem_object *obj;
+
+               obj = list_first_entry(&gpu->active_list,
+                               struct etnaviv_gem_object, mm_list);
+
+               if ((obj->read_fence <= fence) &&
+                               (obj->write_fence <= fence)) {
+                       /* move to inactive: */
+                       etnaviv_gem_move_to_inactive(&obj->base);
+                       etnaviv_gem_put_iova(&obj->base);
+                       drm_gem_object_unreference(&obj->base);
+               } else {
+                       break;
+               }
+       }
+
+       mutex_unlock(&dev->struct_mutex);
+}
+
+/* call from irq handler to schedule work to retire bo's */
+void etnaviv_gpu_retire(struct etnaviv_gpu *gpu)
+{
+       struct etnaviv_drm_private *priv = gpu->dev->dev_private;
+       queue_work(priv->wq, &gpu->retire_work);
+}
+
+/* add bo's to gpu's ring, and kick gpu: */
+int etnaviv_gpu_submit(struct etnaviv_gpu *gpu, struct etnaviv_gem_submit 
*submit,
+               struct etnaviv_file_private *ctx)
+{
+       struct drm_device *dev = gpu->dev;
+       struct etnaviv_drm_private *priv = dev->dev_private;
+       int ret = 0;
+       unsigned int event, i;
+
+       submit->fence = ++priv->next_fence;
+
+       gpu->submitted_fence = submit->fence;
+
+       /*
+        * TODO
+        *
+        * - flush
+        * - data endian
+        * - prefetch
+        *
+        */
+
+       event = event_alloc(gpu);
+       if (unlikely(event == ~0U)) {
+               DRM_ERROR("no free event\n");
+               ret = -EBUSY;
+               goto fail;
+       }
+
+       gpu->event_to_fence[event] = submit->fence;
+
+       etnaviv_buffer_queue(gpu, event, submit);
+
+       priv->lastctx = ctx;
+
+       for (i = 0; i < submit->nr_bos; i++) {
+               struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;
+
+               /* can't happen yet.. but when we add 2d support we'll have
+                * to deal w/ cross-ring synchronization:
+                */
+               WARN_ON(is_active(etnaviv_obj) && (etnaviv_obj->gpu != gpu));
+
+               if (!is_active(etnaviv_obj)) {
+                       uint32_t iova;
+
+                       /* ring takes a reference to the bo and iova: */
+                       drm_gem_object_reference(&etnaviv_obj->base);
+                       etnaviv_gem_get_iova_locked(gpu, &etnaviv_obj->base, 
&iova);
+               }
+
+               if (submit->bos[i].flags & ETNA_SUBMIT_BO_READ)
+                       etnaviv_gem_move_to_active(&etnaviv_obj->base, gpu, 
false, submit->fence);
+
+               if (submit->bos[i].flags & ETNA_SUBMIT_BO_WRITE)
+                       etnaviv_gem_move_to_active(&etnaviv_obj->base, gpu, 
true, submit->fence);
+       }
+       hangcheck_timer_reset(gpu);
+
+fail:
+       return ret;
+}
+
+/*
+ * Init/Cleanup:
+ */
+static irqreturn_t irq_handler(int irq, void *data)
+{
+       struct etnaviv_gpu *gpu = data;
+       irqreturn_t ret = IRQ_NONE;
+
+       u32 intr = gpu_read(gpu, VIVS_HI_INTR_ACKNOWLEDGE);
+
+       if (intr != 0) {
+               dev_dbg(gpu->dev->dev, "intr 0x%08x\n", intr);
+
+               if (intr & VIVS_HI_INTR_ACKNOWLEDGE_AXI_BUS_ERROR)
+                       dev_err(gpu->dev->dev, "AXI bus error\n");
+               else {
+                       uint8_t event = __fls(intr);
+                       dev_dbg(gpu->dev->dev, "event %u\n", event);
+                       gpu->retired_fence = gpu->event_to_fence[event];
+                       event_free(gpu, event);
+                       etnaviv_gpu_retire(gpu);
+               }
+
+               ret = IRQ_HANDLED;
+       }
+
+       return ret;
+}
+
+static int etnaviv_gpu_bind(struct device *dev, struct device *master,
+       void *data)
+{
+       struct drm_device *drm = data;
+       struct etnaviv_drm_private *priv = drm->dev_private;
+       struct etnaviv_gpu *gpu = dev_get_drvdata(dev);
+       int idx = gpu->pipe;
+
+       dev_info(dev, "pre gpu[idx]: 0x%08x\n", (u32)priv->gpu[idx]);
+
+       if (priv->gpu[idx] == 0) {
+               dev_info(dev, "adding core @idx %d\n", idx);
+               priv->gpu[idx] = gpu;
+       } else {
+               dev_err(dev, "failed to add core @idx %d\n", idx);
+               goto fail;
+       }
+
+       dev_info(dev, "post gpu[idx]: 0x%08x\n", (u32)priv->gpu[idx]);
+
+       gpu->dev = drm;
+
+       INIT_LIST_HEAD(&gpu->active_list);
+       INIT_WORK(&gpu->retire_work, retire_worker);
+       INIT_WORK(&gpu->recover_work, recover_worker);
+
+       setup_timer(&gpu->hangcheck_timer, hangcheck_handler,
+                       (unsigned long)gpu);
+       return 0;
+fail:
+       return -1;
+}
+
+static void etnaviv_gpu_unbind(struct device *dev, struct device *master,
+       void *data)
+{
+       struct etnaviv_gpu *gpu = dev_get_drvdata(dev);
+
+       DBG("%s", gpu->name);
+
+       WARN_ON(!list_empty(&gpu->active_list));
+
+       if (gpu->buffer)
+               drm_gem_object_unreference(gpu->buffer);
+
+       if (gpu->mmu)
+               etnaviv_iommu_destroy(gpu->mmu);
+
+       drm_mm_takedown(&gpu->mm);
+}
+
+static const struct component_ops gpu_ops = {
+       .bind = etnaviv_gpu_bind,
+       .unbind = etnaviv_gpu_unbind,
+};
+
+static const struct of_device_id etnaviv_gpu_match[] = {
+       {
+               .compatible = "vivante,vivante-gpu-2d",
+               .data = (void *)ETNA_PIPE_2D
+       },
+       {
+               .compatible = "vivante,vivante-gpu-3d",
+               .data = (void *)ETNA_PIPE_3D
+       },
+       {
+               .compatible = "vivante,vivante-gpu-vg",
+               .data = (void *)ETNA_PIPE_VG
+       },
+       { }
+};
+
+static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *match;
+       struct device *dev = &pdev->dev;
+       struct etnaviv_gpu *gpu;
+       int err = 0;
+
+       gpu = devm_kzalloc(dev, sizeof(*gpu), GFP_KERNEL);
+       if (!gpu)
+               return -ENOMEM;
+
+       match = of_match_device(etnaviv_gpu_match, &pdev->dev);
+       if (!match)
+               return -EINVAL;
+
+       gpu->name = pdev->name;
+
+       /* Map registers: */
+       gpu->mmio = etnaviv_ioremap(pdev, NULL, gpu->name);
+       if (IS_ERR(gpu->mmio))
+               return PTR_ERR(gpu->mmio);
+
+       /* Get Interrupt: */
+       gpu->irq = platform_get_irq(pdev, 0);
+       if (gpu->irq < 0) {
+               err = gpu->irq;
+               dev_err(dev, "failed to get irq: %d\n", err);
+               goto fail;
+       }
+
+       err = devm_request_irq(&pdev->dev, gpu->irq, irq_handler,
+                       IRQF_TRIGGER_HIGH, gpu->name, gpu);
+       if (err) {
+               dev_err(dev, "failed to request IRQ%u: %d\n", gpu->irq, err);
+               goto fail;
+       }
+
+       /* Get Clocks: */
+       gpu->clk_bus = devm_clk_get(&pdev->dev, "bus");
+       DBG("clk_bus: %p", gpu->clk_bus);
+       if (IS_ERR(gpu->clk_bus))
+               gpu->clk_bus = NULL;
+
+       gpu->clk_core = devm_clk_get(&pdev->dev, "core");
+       DBG("clk_core: %p", gpu->clk_core);
+       if (IS_ERR(gpu->clk_core))
+               gpu->clk_core = NULL;
+
+       gpu->clk_shader = devm_clk_get(&pdev->dev, "shader");
+       DBG("clk_shader: %p", gpu->clk_shader);
+       if (IS_ERR(gpu->clk_shader))
+               gpu->clk_shader = NULL;
+
+       gpu->pipe = (int)match->data;
+
+       /* TODO: figure out max mapped size */
+       drm_mm_init(&gpu->mm, 0x80000000, SZ_1G);
+
+       dev_set_drvdata(dev, gpu);
+
+       err = component_add(&pdev->dev, &gpu_ops);
+       if (err < 0) {
+               dev_err(&pdev->dev, "failed to register component: %d\n", err);
+               goto fail;
+       }
+
+       return 0;
+
+fail:
+       return err;
+}
+
+static int etnaviv_gpu_platform_remove(struct platform_device *pdev)
+{
+       component_del(&pdev->dev, &gpu_ops);
+       return 0;
+}
+
+struct platform_driver etnaviv_gpu_driver = {
+       .driver = {
+               .name = "etnaviv-gpu",
+               .owner = THIS_MODULE,
+               .of_match_table = etnaviv_gpu_match,
+       },
+       .probe = etnaviv_gpu_platform_probe,
+       .remove = etnaviv_gpu_platform_remove,
+};
diff --git a/drivers/staging/etnaviv/etnaviv_gpu.h 
b/drivers/staging/etnaviv/etnaviv_gpu.h
new file mode 100644
index 000000000000..707096b5fe98
--- /dev/null
+++ b/drivers/staging/etnaviv/etnaviv_gpu.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ETNAVIV_GPU_H__
+#define __ETNAVIV_GPU_H__
+
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+
+#include "etnaviv_drv.h"
+
+struct etnaviv_gem_submit;
+
+struct etnaviv_chip_identity {
+       /* Chip model. */
+       uint32_t model;
+
+       /* Revision value.*/
+       uint32_t revision;
+
+       /* Supported feature fields. */
+       uint32_t features;
+
+       /* Supported minor feature fields. */
+       uint32_t minor_features0;
+
+       /* Supported minor feature 1 fields. */
+       uint32_t minor_features1;
+
+       /* Supported minor feature 2 fields. */
+       uint32_t minor_features2;
+
+       /* Supported minor feature 3 fields. */
+       uint32_t minor_features3;
+
+       /* Number of streams supported. */
+       uint32_t stream_count;
+
+       /* Total number of temporary registers per thread. */
+       uint32_t register_max;
+
+       /* Maximum number of threads. */
+       uint32_t thread_count;
+
+       /* Number of shader cores. */
+       uint32_t shader_core_count;
+
+       /* Size of the vertex cache. */
+       uint32_t vertex_cache_size;
+
+       /* Number of entries in the vertex output buffer. */
+       uint32_t vertex_output_buffer_size;
+
+       /* Number of pixel pipes. */
+       uint32_t pixel_pipes;
+
+       /* Number of instructions. */
+       uint32_t instruction_count;
+
+       /* Number of constants. */
+       uint32_t num_constants;
+
+       /* Buffer size */
+       uint32_t buffer_size;
+};
+
+struct etnaviv_gpu {
+       const char *name;
+       struct drm_device *dev;
+       struct etnaviv_chip_identity identity;
+       int pipe;
+
+       /* 'ring'-buffer: */
+       struct drm_gem_object *buffer;
+
+       /* event management: */
+       bool event_used[30];
+       uint32_t event_to_fence[30];
+       struct completion event_free;
+       struct spinlock event_spinlock;
+
+       /* list of GEM active objects: */
+       struct list_head active_list;
+
+       uint32_t submitted_fence;
+       uint32_t retired_fence;
+
+       /* worker for handling active-list retiring: */
+       struct work_struct retire_work;
+
+       void __iomem *mmio;
+       int irq;
+
+       struct etnaviv_iommu *mmu;
+
+       /* memory manager for GPU address area */
+       struct drm_mm mm;
+
+       /* Power Control: */
+       struct clk *clk_bus;
+       struct clk *clk_core;
+       struct clk *clk_shader;
+
+       /* Hang Detction: */
+#define DRM_MSM_HANGCHECK_PERIOD 500 /* in ms */
+#define DRM_MSM_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_MSM_HANGCHECK_PERIOD)
+       struct timer_list hangcheck_timer;
+       uint32_t hangcheck_fence;
+       struct work_struct recover_work;
+};
+
+static inline void gpu_write(struct etnaviv_gpu *gpu, u32 reg, u32 data)
+{
+       etnaviv_writel(data, gpu->mmio + reg);
+}
+
+static inline u32 gpu_read(struct etnaviv_gpu *gpu, u32 reg)
+{
+       return etnaviv_readl(gpu->mmio + reg);
+}
+
+int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, uint32_t param, uint64_t 
*value);
+
+int etnaviv_gpu_init(struct etnaviv_gpu *gpu);
+int etnaviv_gpu_pm_suspend(struct etnaviv_gpu *gpu);
+int etnaviv_gpu_pm_resume(struct etnaviv_gpu *gpu);
+
+#ifdef CONFIG_DEBUG_FS
+void etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m);
+#endif
+
+void etnaviv_gpu_retire(struct etnaviv_gpu *gpu);
+int etnaviv_gpu_submit(struct etnaviv_gpu *gpu, struct etnaviv_gem_submit 
*submit,
+               struct etnaviv_file_private *ctx);
+
+extern struct platform_driver etnaviv_gpu_driver;
+
+#endif /* __ETNAVIV_GPU_H__ */
diff --git a/drivers/staging/etnaviv/etnaviv_iommu.c 
b/drivers/staging/etnaviv/etnaviv_iommu.c
new file mode 100644
index 000000000000..d0811fb13363
--- /dev/null
+++ b/drivers/staging/etnaviv/etnaviv_iommu.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2014 Christian Gmeiner <christian.gmeiner at gmail.com>
+  *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/iommu.h>
+#include <linux/platform_device.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/bitops.h>
+
+#include "etnaviv_gpu.h"
+#include "state_hi.xml.h"
+
+#define PT_SIZE                SZ_256K
+#define PT_ENTRIES     (PT_SIZE / sizeof(uint32_t))
+
+#define GPU_MEM_START  0x80000000
+
+struct etnaviv_iommu_domain_pgtable {
+       uint32_t *pgtable;
+       dma_addr_t paddr;
+};
+
+struct etnaviv_iommu_domain {
+       struct etnaviv_iommu_domain_pgtable pgtable;
+       spinlock_t map_lock;
+};
+
+static int pgtable_alloc(struct etnaviv_iommu_domain_pgtable *pgtable,
+                        size_t size)
+{
+       pgtable->pgtable = dma_alloc_coherent(NULL, size, &pgtable->paddr, 
GFP_KERNEL);
+       if (!pgtable->pgtable)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static void pgtable_free(struct etnaviv_iommu_domain_pgtable *pgtable,
+                        size_t size)
+{
+       dma_free_coherent(NULL, size, pgtable->pgtable, pgtable->paddr);
+}
+
+static uint32_t pgtable_read(struct etnaviv_iommu_domain_pgtable *pgtable,
+                          unsigned long iova)
+{
+       /* calcuate index into page table */
+       unsigned int index = (iova - GPU_MEM_START) / SZ_4K;
+       phys_addr_t paddr;
+
+       paddr = pgtable->pgtable[index];
+
+       return paddr;
+}
+
+static void pgtable_write(struct etnaviv_iommu_domain_pgtable *pgtable,
+                         unsigned long iova, phys_addr_t paddr)
+{
+       /* calcuate index into page table */
+       unsigned int index = (iova - GPU_MEM_START) / SZ_4K;
+
+       pgtable->pgtable[index] = paddr;
+}
+
+static int etnaviv_iommu_domain_init(struct iommu_domain *domain)
+{
+       struct etnaviv_iommu_domain *etnaviv_domain;
+       int ret;
+
+       etnaviv_domain = kmalloc(sizeof(*etnaviv_domain), GFP_KERNEL);
+       if (!etnaviv_domain)
+               return -ENOMEM;
+
+       ret = pgtable_alloc(&etnaviv_domain->pgtable, PT_SIZE);
+       if (ret < 0) {
+               kfree(etnaviv_domain);
+               return ret;
+       }
+
+       spin_lock_init(&etnaviv_domain->map_lock);
+       domain->priv = etnaviv_domain;
+       return 0;
+}
+
+static void etnaviv_iommu_domain_destroy(struct iommu_domain *domain)
+{
+       struct etnaviv_iommu_domain *etnaviv_domain = domain->priv;
+
+       pgtable_free(&etnaviv_domain->pgtable, PT_SIZE);
+
+       kfree(etnaviv_domain);
+       domain->priv = NULL;
+}
+
+static int etnaviv_iommu_map(struct iommu_domain *domain, unsigned long iova,
+          phys_addr_t paddr, size_t size, int prot)
+{
+       struct etnaviv_iommu_domain *etnaviv_domain = domain->priv;
+
+       if (size != SZ_4K)
+               return -EINVAL;
+
+       spin_lock(&etnaviv_domain->map_lock);
+       pgtable_write(&etnaviv_domain->pgtable, iova, paddr);
+       spin_unlock(&etnaviv_domain->map_lock);
+
+       return 0;
+}
+
+static size_t etnaviv_iommu_unmap(struct iommu_domain *domain, unsigned long 
iova,
+            size_t size)
+{
+       struct etnaviv_iommu_domain *etnaviv_domain = domain->priv;
+
+       if (size != SZ_4K)
+               return -EINVAL;
+
+       spin_lock(&etnaviv_domain->map_lock);
+       pgtable_write(&etnaviv_domain->pgtable, iova, ~0);
+       spin_unlock(&etnaviv_domain->map_lock);
+
+       return 0;
+}
+
+phys_addr_t etnaviv_iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t 
iova)
+{
+       struct etnaviv_iommu_domain *etnaviv_domain = domain->priv;
+
+       return pgtable_read(&etnaviv_domain->pgtable, iova);
+}
+
+static struct iommu_ops etnaviv_iommu_ops = {
+               .domain_init = etnaviv_iommu_domain_init,
+               .domain_destroy = etnaviv_iommu_domain_destroy,
+               .map = etnaviv_iommu_map,
+               .unmap = etnaviv_iommu_unmap,
+               .iova_to_phys = etnaviv_iommu_iova_to_phys,
+               .pgsize_bitmap = SZ_4K,
+};
+
+struct iommu_domain *etnaviv_iommu_domain_alloc(struct etnaviv_gpu *gpu)
+{
+       struct iommu_domain *domain;
+       struct etnaviv_iommu_domain *etnaviv_domain;
+       int ret;
+
+       domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+       if (!domain)
+               return NULL;
+
+       domain->ops = &etnaviv_iommu_ops;
+
+       ret = domain->ops->domain_init(domain);
+       if (ret)
+               goto out_free;
+
+       /* set page table address in MC */
+       etnaviv_domain = domain->priv;
+
+       gpu_write(gpu, VIVS_MC_MMU_FE_PAGE_TABLE, 
(uint32_t)etnaviv_domain->pgtable.paddr);
+       gpu_write(gpu, VIVS_MC_MMU_TX_PAGE_TABLE, 
(uint32_t)etnaviv_domain->pgtable.paddr);
+       gpu_write(gpu, VIVS_MC_MMU_PE_PAGE_TABLE, 
(uint32_t)etnaviv_domain->pgtable.paddr);
+       gpu_write(gpu, VIVS_MC_MMU_PEZ_PAGE_TABLE, 
(uint32_t)etnaviv_domain->pgtable.paddr);
+       gpu_write(gpu, VIVS_MC_MMU_RA_PAGE_TABLE, 
(uint32_t)etnaviv_domain->pgtable.paddr);
+
+       return domain;
+
+out_free:
+       kfree(domain);
+       return NULL;
+}
diff --git a/drivers/staging/etnaviv/etnaviv_iommu.h 
b/drivers/staging/etnaviv/etnaviv_iommu.h
new file mode 100644
index 000000000000..3103ff3efcbe
--- /dev/null
+++ b/drivers/staging/etnaviv/etnaviv_iommu.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2014 Christian Gmeiner <christian.gmeiner at gmail.com>
+  *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ETNAVIV_IOMMU_H__
+#define __ETNAVIV_IOMMU_H__
+
+#include <linux/iommu.h>
+struct etnaviv_gpu;
+
+struct iommu_domain *etnaviv_iommu_domain_alloc(struct etnaviv_gpu *gpu);
+
+#endif /* __ETNAVIV_IOMMU_H__ */
diff --git a/drivers/staging/etnaviv/etnaviv_iommu_v2.c 
b/drivers/staging/etnaviv/etnaviv_iommu_v2.c
new file mode 100644
index 000000000000..3039ee9cbc6d
--- /dev/null
+++ b/drivers/staging/etnaviv/etnaviv_iommu_v2.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 Christian Gmeiner <christian.gmeiner at gmail.com>
+  *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/iommu.h>
+#include <linux/platform_device.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/bitops.h>
+
+#include "etnaviv_gpu.h"
+#include "state_hi.xml.h"
+
+
+struct iommu_domain *etnaviv_iommu_v2_domain_alloc(struct etnaviv_gpu *gpu)
+{
+       /* TODO */
+       return NULL;
+}
diff --git a/drivers/staging/etnaviv/etnaviv_iommu_v2.h 
b/drivers/staging/etnaviv/etnaviv_iommu_v2.h
new file mode 100644
index 000000000000..603ea41c5389
--- /dev/null
+++ b/drivers/staging/etnaviv/etnaviv_iommu_v2.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2014 Christian Gmeiner <christian.gmeiner at gmail.com>
+  *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ETNAVIV_IOMMU_V2_H__
+#define __ETNAVIV_IOMMU_V2_H__
+
+#include <linux/iommu.h>
+struct etnaviv_gpu;
+
+struct iommu_domain *etnaviv_iommu_v2_domain_alloc(struct etnaviv_gpu *gpu);
+
+#endif /* __ETNAVIV_IOMMU_V2_H__ */
diff --git a/drivers/staging/etnaviv/etnaviv_mmu.c 
b/drivers/staging/etnaviv/etnaviv_mmu.c
new file mode 100644
index 000000000000..cee97e11117d
--- /dev/null
+++ b/drivers/staging/etnaviv/etnaviv_mmu.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "etnaviv_drv.h"
+#include "etnaviv_mmu.h"
+
+static int etnaviv_fault_handler(struct iommu_domain *iommu, struct device 
*dev,
+               unsigned long iova, int flags, void *arg)
+{
+       DBG("*** fault: iova=%08lx, flags=%d", iova, flags);
+       return 0;
+}
+
+int etnaviv_iommu_map(struct etnaviv_iommu *iommu, uint32_t iova,
+               struct sg_table *sgt, unsigned len, int prot)
+{
+       struct iommu_domain *domain = iommu->domain;
+       struct scatterlist *sg;
+       unsigned int da = iova;
+       unsigned int i, j;
+       int ret;
+
+       if (!domain || !sgt)
+               return -EINVAL;
+
+       for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+               u32 pa = sg_phys(sg) - sg->offset;
+               size_t bytes = sg->length + sg->offset;
+
+               VERB("map[%d]: %08x %08x(%x)", i, iova, pa, bytes);
+
+               ret = iommu_map(domain, da, pa, bytes, prot);
+               if (ret)
+                       goto fail;
+
+               da += bytes;
+       }
+
+       return 0;
+
+fail:
+       da = iova;
+
+       for_each_sg(sgt->sgl, sg, i, j) {
+               size_t bytes = sg->length + sg->offset;
+               iommu_unmap(domain, da, bytes);
+               da += bytes;
+       }
+       return ret;
+}
+
+int etnaviv_iommu_unmap(struct etnaviv_iommu *iommu, uint32_t iova,
+               struct sg_table *sgt, unsigned len)
+{
+       struct iommu_domain *domain = iommu->domain;
+       struct scatterlist *sg;
+       unsigned int da = iova;
+       int i;
+
+       for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+               size_t bytes = sg->length + sg->offset;
+               size_t unmapped;
+
+               unmapped = iommu_unmap(domain, da, bytes);
+               if (unmapped < bytes)
+                       return unmapped;
+
+               VERB("unmap[%d]: %08x(%x)", i, iova, bytes);
+
+               BUG_ON(!PAGE_ALIGNED(bytes));
+
+               da += bytes;
+       }
+
+       return 0;
+}
+
+void etnaviv_iommu_destroy(struct etnaviv_iommu *mmu)
+{
+       iommu_domain_free(mmu->domain);
+       kfree(mmu);
+}
+
+struct etnaviv_iommu *etnaviv_iommu_new(struct drm_device *dev, struct 
iommu_domain *domain)
+{
+       struct etnaviv_iommu *mmu;
+
+       mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
+       if (!mmu)
+               return ERR_PTR(-ENOMEM);
+
+       mmu->domain = domain;
+       mmu->dev = dev;
+       iommu_set_fault_handler(domain, etnaviv_fault_handler, dev);
+
+       return mmu;
+}
diff --git a/drivers/staging/etnaviv/etnaviv_mmu.h 
b/drivers/staging/etnaviv/etnaviv_mmu.h
new file mode 100644
index 000000000000..02e7adcc96d7
--- /dev/null
+++ b/drivers/staging/etnaviv/etnaviv_mmu.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ETNAVIV_MMU_H__
+#define __ETNAVIV_MMU_H__
+
+#include <linux/iommu.h>
+
+struct etnaviv_iommu {
+       struct drm_device *dev;
+       struct iommu_domain *domain;
+};
+
+int etnaviv_iommu_attach(struct etnaviv_iommu *iommu, const char **names, int 
cnt);
+int etnaviv_iommu_map(struct etnaviv_iommu *iommu, uint32_t iova, struct 
sg_table *sgt,
+               unsigned len, int prot);
+int etnaviv_iommu_unmap(struct etnaviv_iommu *iommu, uint32_t iova, struct 
sg_table *sgt,
+               unsigned len);
+void etnaviv_iommu_destroy(struct etnaviv_iommu *iommu);
+
+struct etnaviv_iommu *etnaviv_iommu_new(struct drm_device *dev, struct 
iommu_domain *domain);
+
+#endif /* __ETNAVIV_MMU_H__ */
diff --git a/drivers/staging/etnaviv/state.xml.h 
b/drivers/staging/etnaviv/state.xml.h
new file mode 100644
index 000000000000..e7b36df1e4e3
--- /dev/null
+++ b/drivers/staging/etnaviv/state.xml.h
@@ -0,0 +1,348 @@
+#ifndef STATE_XML
+#define STATE_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git 
repository:
+http://0x04.net/cgit/index.cgi/rules-ng-ng
+git clone git://0x04.net/rules-ng-ng
+
+The rules-ng-ng source files this header was generated from are:
+- /home/orion/projects/etna_viv/rnndb/state.xml    (  18526 bytes, from 
2013-09-11 16:52:32)
+- /home/orion/projects/etna_viv/rnndb/common.xml   (  18379 bytes, from 
2014-01-27 15:58:05)
+- /home/orion/projects/etna_viv/rnndb/state_hi.xml (  22236 bytes, from 
2014-01-27 15:56:46)
+- /home/orion/projects/etna_viv/rnndb/state_2d.xml (  51191 bytes, from 
2013-10-04 06:36:55)
+- /home/orion/projects/etna_viv/rnndb/state_3d.xml (  54570 bytes, from 
2013-10-12 15:25:03)
+- /home/orion/projects/etna_viv/rnndb/state_vg.xml (   5942 bytes, from 
2013-09-01 10:53:22)
+
+Copyright (C) 2013
+*/
+
+
+#define VARYING_COMPONENT_USE_UNUSED                           0x00000000
+#define VARYING_COMPONENT_USE_USED                             0x00000001
+#define VARYING_COMPONENT_USE_POINTCOORD_X                     0x00000002
+#define VARYING_COMPONENT_USE_POINTCOORD_Y                     0x00000003
+#define FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE__MASK           0x000000ff
+#define FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE__SHIFT          0
+#define FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE(x)              (((x) << 
FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE__SHIFT) & 
FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE__MASK)
+#define VIVS_FE                                                        
0x00000000
+
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG(i0)                     (0x00000600 + 
0x4*(i0))
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG__ESIZE                   0x00000004
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG__LEN                     0x00000010
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE__MASK               0x0000000f
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE__SHIFT              0
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_BYTE                        
0x00000000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_UNSIGNED_BYTE       0x00000001
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_SHORT               0x00000002
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_UNSIGNED_SHORT      0x00000003
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_INT                 0x00000004
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_UNSIGNED_INT                
0x00000005
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_FLOAT               0x00000008
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_HALF_FLOAT          0x00000009
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_FIXED               0x0000000b
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_INT_10_10_10_2      0x0000000c
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_UNSIGNED_INT_10_10_10_2     
0x0000000d
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__MASK             0x00000030
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__SHIFT            4
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN(x)                        (((x) 
<< VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__SHIFT) & 
VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__MASK)
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NONCONSECUTIVE           0x00000080
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM__MASK             0x00000700
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM__SHIFT            8
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM(x)                        (((x) 
<< VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM__SHIFT) & 
VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM__MASK)
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM__MASK                        
0x00003000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM__SHIFT               12
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM(x)                   (((x) << 
VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM__SHIFT) & 
VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM__MASK)
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE__MASK          0x0000c000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE__SHIFT         14
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF            0x00000000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_ON             0x00008000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_START__MASK              0x00ff0000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_START__SHIFT             16
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_START(x)                 (((x) << 
VIVS_FE_VERTEX_ELEMENT_CONFIG_START__SHIFT) & 
VIVS_FE_VERTEX_ELEMENT_CONFIG_START__MASK)
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_END__MASK                        
0xff000000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_END__SHIFT               24
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_END(x)                   (((x) << 
VIVS_FE_VERTEX_ELEMENT_CONFIG_END__SHIFT) & 
VIVS_FE_VERTEX_ELEMENT_CONFIG_END__MASK)
+
+#define VIVS_FE_CMD_STREAM_BASE_ADDR                           0x00000640
+
+#define VIVS_FE_INDEX_STREAM_BASE_ADDR                         0x00000644
+
+#define VIVS_FE_INDEX_STREAM_CONTROL                           0x00000648
+#define VIVS_FE_INDEX_STREAM_CONTROL_TYPE__MASK                        
0x00000003
+#define VIVS_FE_INDEX_STREAM_CONTROL_TYPE__SHIFT               0
+#define VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_CHAR                
0x00000000
+#define VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_SHORT       0x00000001
+#define VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_INT         0x00000002
+
+#define VIVS_FE_VERTEX_STREAM_BASE_ADDR                                
0x0000064c
+
+#define VIVS_FE_VERTEX_STREAM_CONTROL                          0x00000650
+
+#define VIVS_FE_COMMAND_ADDRESS                                        
0x00000654
+
+#define VIVS_FE_COMMAND_CONTROL                                        
0x00000658
+#define VIVS_FE_COMMAND_CONTROL_PREFETCH__MASK                 0x0000ffff
+#define VIVS_FE_COMMAND_CONTROL_PREFETCH__SHIFT                        0
+#define VIVS_FE_COMMAND_CONTROL_PREFETCH(x)                    (((x) << 
VIVS_FE_COMMAND_CONTROL_PREFETCH__SHIFT) & 
VIVS_FE_COMMAND_CONTROL_PREFETCH__MASK)
+#define VIVS_FE_COMMAND_CONTROL_ENABLE                         0x00010000
+
+#define VIVS_FE_DMA_STATUS                                     0x0000065c
+
+#define VIVS_FE_DMA_DEBUG_STATE                                        
0x00000660
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE__MASK                        
0x0000001f
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE__SHIFT               0
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_IDLE                 0x00000000
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_DEC                  0x00000001
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_ADR0                 0x00000002
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_LOAD0                        
0x00000003
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_ADR1                 0x00000004
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_LOAD1                        
0x00000005
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_3DADR                        
0x00000006
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_3DCMD                        
0x00000007
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_3DCNTL               0x00000008
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_3DIDXCNTL            0x00000009
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_INITREQDMA           0x0000000a
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_DRAWIDX              0x0000000b
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_DRAW                 0x0000000c
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_2DRECT0              0x0000000d
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_2DRECT1              0x0000000e
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_2DDATA0              0x0000000f
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_2DDATA1              0x00000010
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_WAITFIFO             0x00000011
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_WAIT                 0x00000012
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_LINK                 0x00000013
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_END                  0x00000014
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_STALL                        
0x00000015
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE__MASK            0x00000300
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE__SHIFT           8
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE_IDLE             0x00000000
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE_START            0x00000100
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE_REQ              0x00000200
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE_END              0x00000300
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_FETCH_STATE__MASK          0x00000c00
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_FETCH_STATE__SHIFT         10
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_FETCH_STATE_IDLE           0x00000000
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_FETCH_STATE_RAMVALID       0x00000400
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_FETCH_STATE_VALID          0x00000800
+#define VIVS_FE_DMA_DEBUG_STATE_REQ_DMA_STATE__MASK            0x00003000
+#define VIVS_FE_DMA_DEBUG_STATE_REQ_DMA_STATE__SHIFT           12
+#define VIVS_FE_DMA_DEBUG_STATE_REQ_DMA_STATE_IDLE             0x00000000
+#define VIVS_FE_DMA_DEBUG_STATE_REQ_DMA_STATE_WAITIDX          0x00001000
+#define VIVS_FE_DMA_DEBUG_STATE_REQ_DMA_STATE_CAL              0x00002000
+#define VIVS_FE_DMA_DEBUG_STATE_CAL_STATE__MASK                        
0x0000c000
+#define VIVS_FE_DMA_DEBUG_STATE_CAL_STATE__SHIFT               14
+#define VIVS_FE_DMA_DEBUG_STATE_CAL_STATE_IDLE                 0x00000000
+#define VIVS_FE_DMA_DEBUG_STATE_CAL_STATE_LDADR                        
0x00004000
+#define VIVS_FE_DMA_DEBUG_STATE_CAL_STATE_IDXCALC              0x00008000
+#define VIVS_FE_DMA_DEBUG_STATE_VE_REQ_STATE__MASK             0x00030000
+#define VIVS_FE_DMA_DEBUG_STATE_VE_REQ_STATE__SHIFT            16
+#define VIVS_FE_DMA_DEBUG_STATE_VE_REQ_STATE_IDLE              0x00000000
+#define VIVS_FE_DMA_DEBUG_STATE_VE_REQ_STATE_CKCACHE           0x00010000
+#define VIVS_FE_DMA_DEBUG_STATE_VE_REQ_STATE_MISS              0x00020000
+
+#define VIVS_FE_DMA_ADDRESS                                    0x00000664
+
+#define VIVS_FE_DMA_LOW                                                
0x00000668
+
+#define VIVS_FE_DMA_HIGH                                       0x0000066c
+
+#define VIVS_FE_AUTO_FLUSH                                     0x00000670
+
+#define VIVS_FE_UNK00678                                       0x00000678
+
+#define VIVS_FE_UNK0067C                                       0x0000067c
+
+#define VIVS_FE_VERTEX_STREAMS(i0)                            (0x00000000 + 
0x4*(i0))
+#define VIVS_FE_VERTEX_STREAMS__ESIZE                          0x00000004
+#define VIVS_FE_VERTEX_STREAMS__LEN                            0x00000008
+
+#define VIVS_FE_VERTEX_STREAMS_BASE_ADDR(i0)                  (0x00000680 + 
0x4*(i0))
+
+#define VIVS_FE_VERTEX_STREAMS_CONTROL(i0)                    (0x000006a0 + 
0x4*(i0))
+
+#define VIVS_FE_UNK00700(i0)                                  (0x00000700 + 
0x4*(i0))
+#define VIVS_FE_UNK00700__ESIZE                                        
0x00000004
+#define VIVS_FE_UNK00700__LEN                                  0x00000010
+
+#define VIVS_FE_UNK00740(i0)                                  (0x00000740 + 
0x4*(i0))
+#define VIVS_FE_UNK00740__ESIZE                                        
0x00000004
+#define VIVS_FE_UNK00740__LEN                                  0x00000010
+
+#define VIVS_FE_UNK00780(i0)                                  (0x00000780 + 
0x4*(i0))
+#define VIVS_FE_UNK00780__ESIZE                                        
0x00000004
+#define VIVS_FE_UNK00780__LEN                                  0x00000010
+
+#define VIVS_GL                                                        
0x00000000
+
+#define VIVS_GL_PIPE_SELECT                                    0x00003800
+#define VIVS_GL_PIPE_SELECT_PIPE__MASK                         0x00000001
+#define VIVS_GL_PIPE_SELECT_PIPE__SHIFT                                0
+#define VIVS_GL_PIPE_SELECT_PIPE(x)                            (((x) << 
VIVS_GL_PIPE_SELECT_PIPE__SHIFT) & VIVS_GL_PIPE_SELECT_PIPE__MASK)
+
+#define VIVS_GL_EVENT                                          0x00003804
+#define VIVS_GL_EVENT_EVENT_ID__MASK                           0x0000001f
+#define VIVS_GL_EVENT_EVENT_ID__SHIFT                          0
+#define VIVS_GL_EVENT_EVENT_ID(x)                              (((x) << 
VIVS_GL_EVENT_EVENT_ID__SHIFT) & VIVS_GL_EVENT_EVENT_ID__MASK)
+#define VIVS_GL_EVENT_FROM_FE                                  0x00000020
+#define VIVS_GL_EVENT_FROM_PE                                  0x00000040
+#define VIVS_GL_EVENT_SOURCE__MASK                             0x00001f00
+#define VIVS_GL_EVENT_SOURCE__SHIFT                            8
+#define VIVS_GL_EVENT_SOURCE(x)                                        (((x) 
<< VIVS_GL_EVENT_SOURCE__SHIFT) & VIVS_GL_EVENT_SOURCE__MASK)
+
+#define VIVS_GL_SEMAPHORE_TOKEN                                        
0x00003808
+#define VIVS_GL_SEMAPHORE_TOKEN_FROM__MASK                     0x0000001f
+#define VIVS_GL_SEMAPHORE_TOKEN_FROM__SHIFT                    0
+#define VIVS_GL_SEMAPHORE_TOKEN_FROM(x)                                (((x) 
<< VIVS_GL_SEMAPHORE_TOKEN_FROM__SHIFT) & VIVS_GL_SEMAPHORE_TOKEN_FROM__MASK)
+#define VIVS_GL_SEMAPHORE_TOKEN_TO__MASK                       0x00001f00
+#define VIVS_GL_SEMAPHORE_TOKEN_TO__SHIFT                      8
+#define VIVS_GL_SEMAPHORE_TOKEN_TO(x)                          (((x) << 
VIVS_GL_SEMAPHORE_TOKEN_TO__SHIFT) & VIVS_GL_SEMAPHORE_TOKEN_TO__MASK)
+
+#define VIVS_GL_FLUSH_CACHE                                    0x0000380c
+#define VIVS_GL_FLUSH_CACHE_DEPTH                              0x00000001
+#define VIVS_GL_FLUSH_CACHE_COLOR                              0x00000002
+#define VIVS_GL_FLUSH_CACHE_TEXTURE                            0x00000004
+#define VIVS_GL_FLUSH_CACHE_PE2D                               0x00000008
+#define VIVS_GL_FLUSH_CACHE_TEXTUREVS                          0x00000010
+#define VIVS_GL_FLUSH_CACHE_SHADER_L1                          0x00000020
+#define VIVS_GL_FLUSH_CACHE_SHADER_L2                          0x00000040
+
+#define VIVS_GL_FLUSH_MMU                                      0x00003810
+#define VIVS_GL_FLUSH_MMU_FLUSH_FEMMU                          0x00000001
+#define VIVS_GL_FLUSH_MMU_FLUSH_PEMMU                          0x00000002
+
+#define VIVS_GL_VERTEX_ELEMENT_CONFIG                          0x00003814
+
+#define VIVS_GL_MULTI_SAMPLE_CONFIG                            0x00003818
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES__MASK         0x00000003
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES__SHIFT                0
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_NONE          0x00000000
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_2X            0x00000001
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_4X            0x00000002
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_MASK          0x00000008
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES__MASK         0x000000f0
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES__SHIFT                4
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES(x)            (((x) << 
VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES__SHIFT) & 
VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES__MASK)
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES_MASK          0x00000100
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12__MASK                        
0x00007000
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12__SHIFT               12
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12(x)                   (((x) << 
VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12__SHIFT) & 
VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12__MASK)
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12_MASK                 0x00008000
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16__MASK                        
0x00030000
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16__SHIFT               16
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16(x)                   (((x) << 
VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16__SHIFT) & 
VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16__MASK)
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16_MASK                 0x00080000
+
+#define VIVS_GL_VARYING_TOTAL_COMPONENTS                       0x0000381c
+#define VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM__MASK             0x000000ff
+#define VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM__SHIFT            0
+#define VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM(x)                        (((x) 
<< VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM__SHIFT) & 
VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM__MASK)
+
+#define VIVS_GL_VARYING_NUM_COMPONENTS                         0x00003820
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR0__MASK              0x00000007
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR0__SHIFT             0
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR0(x)                 (((x) << 
VIVS_GL_VARYING_NUM_COMPONENTS_VAR0__SHIFT) & 
VIVS_GL_VARYING_NUM_COMPONENTS_VAR0__MASK)
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR1__MASK              0x00000070
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR1__SHIFT             4
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR1(x)                 (((x) << 
VIVS_GL_VARYING_NUM_COMPONENTS_VAR1__SHIFT) & 
VIVS_GL_VARYING_NUM_COMPONENTS_VAR1__MASK)
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR2__MASK              0x00000700
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR2__SHIFT             8
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR2(x)                 (((x) << 
VIVS_GL_VARYING_NUM_COMPONENTS_VAR2__SHIFT) & 
VIVS_GL_VARYING_NUM_COMPONENTS_VAR2__MASK)
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR3__MASK              0x00007000
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR3__SHIFT             12
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR3(x)                 (((x) << 
VIVS_GL_VARYING_NUM_COMPONENTS_VAR3__SHIFT) & 
VIVS_GL_VARYING_NUM_COMPONENTS_VAR3__MASK)
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR4__MASK              0x00070000
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR4__SHIFT             16
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR4(x)                 (((x) << 
VIVS_GL_VARYING_NUM_COMPONENTS_VAR4__SHIFT) & 
VIVS_GL_VARYING_NUM_COMPONENTS_VAR4__MASK)
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR5__MASK              0x00700000
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR5__SHIFT             20
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR5(x)                 (((x) << 
VIVS_GL_VARYING_NUM_COMPONENTS_VAR5__SHIFT) & 
VIVS_GL_VARYING_NUM_COMPONENTS_VAR5__MASK)
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR6__MASK              0x07000000
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR6__SHIFT             24
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR6(x)                 (((x) << 
VIVS_GL_VARYING_NUM_COMPONENTS_VAR6__SHIFT) & 
VIVS_GL_VARYING_NUM_COMPONENTS_VAR6__MASK)
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR7__MASK              0x70000000
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR7__SHIFT             28
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR7(x)                 (((x) << 
VIVS_GL_VARYING_NUM_COMPONENTS_VAR7__SHIFT) & 
VIVS_GL_VARYING_NUM_COMPONENTS_VAR7__MASK)
+
+#define VIVS_GL_VARYING_COMPONENT_USE(i0)                     (0x00003828 + 
0x4*(i0))
+#define VIVS_GL_VARYING_COMPONENT_USE__ESIZE                   0x00000004
+#define VIVS_GL_VARYING_COMPONENT_USE__LEN                     0x00000002
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP0__MASK              0x00000003
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP0__SHIFT             0
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP0(x)                 (((x) << 
VIVS_GL_VARYING_COMPONENT_USE_COMP0__SHIFT) & 
VIVS_GL_VARYING_COMPONENT_USE_COMP0__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP1__MASK              0x0000000c
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP1__SHIFT             2
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP1(x)                 (((x) << 
VIVS_GL_VARYING_COMPONENT_USE_COMP1__SHIFT) & 
VIVS_GL_VARYING_COMPONENT_USE_COMP1__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP2__MASK              0x00000030
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP2__SHIFT             4
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP2(x)                 (((x) << 
VIVS_GL_VARYING_COMPONENT_USE_COMP2__SHIFT) & 
VIVS_GL_VARYING_COMPONENT_USE_COMP2__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP3__MASK              0x000000c0
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP3__SHIFT             6
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP3(x)                 (((x) << 
VIVS_GL_VARYING_COMPONENT_USE_COMP3__SHIFT) & 
VIVS_GL_VARYING_COMPONENT_USE_COMP3__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP4__MASK              0x00000300
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP4__SHIFT             8
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP4(x)                 (((x) << 
VIVS_GL_VARYING_COMPONENT_USE_COMP4__SHIFT) & 
VIVS_GL_VARYING_COMPONENT_USE_COMP4__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP5__MASK              0x00000c00
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP5__SHIFT             10
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP5(x)                 (((x) << 
VIVS_GL_VARYING_COMPONENT_USE_COMP5__SHIFT) & 
VIVS_GL_VARYING_COMPONENT_USE_COMP5__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP6__MASK              0x00003000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP6__SHIFT             12
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP6(x)                 (((x) << 
VIVS_GL_VARYING_COMPONENT_USE_COMP6__SHIFT) & 
VIVS_GL_VARYING_COMPONENT_USE_COMP6__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP7__MASK              0x0000c000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP7__SHIFT             14
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP7(x)                 (((x) << 
VIVS_GL_VARYING_COMPONENT_USE_COMP7__SHIFT) & 
VIVS_GL_VARYING_COMPONENT_USE_COMP7__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP8__MASK              0x00030000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP8__SHIFT             16
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP8(x)                 (((x) << 
VIVS_GL_VARYING_COMPONENT_USE_COMP8__SHIFT) & 
VIVS_GL_VARYING_COMPONENT_USE_COMP8__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP9__MASK              0x000c0000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP9__SHIFT             18
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP9(x)                 (((x) << 
VIVS_GL_VARYING_COMPONENT_USE_COMP9__SHIFT) & 
VIVS_GL_VARYING_COMPONENT_USE_COMP9__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP10__MASK             0x00300000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP10__SHIFT            20
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP10(x)                        (((x) 
<< VIVS_GL_VARYING_COMPONENT_USE_COMP10__SHIFT) & 
VIVS_GL_VARYING_COMPONENT_USE_COMP10__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP11__MASK             0x00c00000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP11__SHIFT            22
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP11(x)                        (((x) 
<< VIVS_GL_VARYING_COMPONENT_USE_COMP11__SHIFT) & 
VIVS_GL_VARYING_COMPONENT_USE_COMP11__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP12__MASK             0x03000000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP12__SHIFT            24
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP12(x)                        (((x) 
<< VIVS_GL_VARYING_COMPONENT_USE_COMP12__SHIFT) & 
VIVS_GL_VARYING_COMPONENT_USE_COMP12__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP13__MASK             0x0c000000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP13__SHIFT            26
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP13(x)                        (((x) 
<< VIVS_GL_VARYING_COMPONENT_USE_COMP13__SHIFT) & 
VIVS_GL_VARYING_COMPONENT_USE_COMP13__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP14__MASK             0x30000000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP14__SHIFT            28
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP14(x)                        (((x) 
<< VIVS_GL_VARYING_COMPONENT_USE_COMP14__SHIFT) & 
VIVS_GL_VARYING_COMPONENT_USE_COMP14__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP15__MASK             0xc0000000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP15__SHIFT            30
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP15(x)                        (((x) 
<< VIVS_GL_VARYING_COMPONENT_USE_COMP15__SHIFT) & 
VIVS_GL_VARYING_COMPONENT_USE_COMP15__MASK)
+
+#define VIVS_GL_UNK03834                                       0x00003834
+
+#define VIVS_GL_UNK03838                                       0x00003838
+
+#define VIVS_GL_API_MODE                                       0x0000384c
+#define VIVS_GL_API_MODE_OPENGL                                        
0x00000000
+#define VIVS_GL_API_MODE_OPENVG                                        
0x00000001
+#define VIVS_GL_API_MODE_OPENCL                                        
0x00000002
+
+#define VIVS_GL_CONTEXT_POINTER                                        
0x00003850
+
+#define VIVS_GL_UNK03A00                                       0x00003a00
+
+#define VIVS_GL_STALL_TOKEN                                    0x00003c00
+#define VIVS_GL_STALL_TOKEN_FROM__MASK                         0x0000001f
+#define VIVS_GL_STALL_TOKEN_FROM__SHIFT                                0
+#define VIVS_GL_STALL_TOKEN_FROM(x)                            (((x) << 
VIVS_GL_STALL_TOKEN_FROM__SHIFT) & VIVS_GL_STALL_TOKEN_FROM__MASK)
+#define VIVS_GL_STALL_TOKEN_TO__MASK                           0x00001f00
+#define VIVS_GL_STALL_TOKEN_TO__SHIFT                          8
+#define VIVS_GL_STALL_TOKEN_TO(x)                              (((x) << 
VIVS_GL_STALL_TOKEN_TO__SHIFT) & VIVS_GL_STALL_TOKEN_TO__MASK)
+#define VIVS_GL_STALL_TOKEN_FLIP0                              0x40000000
+#define VIVS_GL_STALL_TOKEN_FLIP1                              0x80000000
+
+#define VIVS_DUMMY                                             0x00000000
+
+#define VIVS_DUMMY_DUMMY                                       0x0003fffc
+
+
+#endif /* STATE_XML */
diff --git a/drivers/staging/etnaviv/state_hi.xml.h 
b/drivers/staging/etnaviv/state_hi.xml.h
new file mode 100644
index 000000000000..9799d7473e5e
--- /dev/null
+++ b/drivers/staging/etnaviv/state_hi.xml.h
@@ -0,0 +1,405 @@
+#ifndef STATE_HI_XML
+#define STATE_HI_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git 
repository:
+http://0x04.net/cgit/index.cgi/rules-ng-ng
+git clone git://0x04.net/rules-ng-ng
+
+The rules-ng-ng source files this header was generated from are:
+- /home/christian/projects/etna_viv/rnndb/state.xml    (  18526 bytes, from 
2014-09-06 05:57:57)
+- /home/christian/projects/etna_viv/rnndb/common.xml   (  18379 bytes, from 
2014-09-06 05:57:57)
+- /home/christian/projects/etna_viv/rnndb/state_hi.xml (  23176 bytes, from 
2014-09-06 06:07:47)
+- /home/christian/projects/etna_viv/rnndb/state_2d.xml (  51191 bytes, from 
2014-09-06 05:57:57)
+- /home/christian/projects/etna_viv/rnndb/state_3d.xml (  54570 bytes, from 
2014-09-06 05:57:57)
+- /home/christian/projects/etna_viv/rnndb/state_vg.xml (   5942 bytes, from 
2014-09-06 05:57:57)
+
+Copyright (C) 2014
+*/
+
+
+#define MMU_EXCEPTION_SLAVE_NOT_PRESENT                                
0x00000001
+#define MMU_EXCEPTION_PAGE_NOT_PRESENT                         0x00000002
+#define MMU_EXCEPTION_WRITE_VIOLATION                          0x00000003
+#define VIVS_HI                                                        
0x00000000
+
+#define VIVS_HI_CLOCK_CONTROL                                  0x00000000
+#define VIVS_HI_CLOCK_CONTROL_CLK3D_DIS                                
0x00000001
+#define VIVS_HI_CLOCK_CONTROL_CLK2D_DIS                                
0x00000002
+#define VIVS_HI_CLOCK_CONTROL_FSCALE_VAL__MASK                 0x000001fc
+#define VIVS_HI_CLOCK_CONTROL_FSCALE_VAL__SHIFT                        2
+#define VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(x)                    (((x) << 
VIVS_HI_CLOCK_CONTROL_FSCALE_VAL__SHIFT) & 
VIVS_HI_CLOCK_CONTROL_FSCALE_VAL__MASK)
+#define VIVS_HI_CLOCK_CONTROL_FSCALE_CMD_LOAD                  0x00000200
+#define VIVS_HI_CLOCK_CONTROL_DISABLE_RAM_CLK_GATING           0x00000400
+#define VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS          0x00000800
+#define VIVS_HI_CLOCK_CONTROL_SOFT_RESET                       0x00001000
+#define VIVS_HI_CLOCK_CONTROL_IDLE_3D                          0x00010000
+#define VIVS_HI_CLOCK_CONTROL_IDLE_2D                          0x00020000
+#define VIVS_HI_CLOCK_CONTROL_IDLE_VG                          0x00040000
+#define VIVS_HI_CLOCK_CONTROL_ISOLATE_GPU                      0x00080000
+#define VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK           0x00f00000
+#define VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__SHIFT          20
+#define VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE(x)              (((x) << 
VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__SHIFT) & 
VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK)
+
+#define VIVS_HI_IDLE_STATE                                     0x00000004
+#define VIVS_HI_IDLE_STATE_FE                                  0x00000001
+#define VIVS_HI_IDLE_STATE_DE                                  0x00000002
+#define VIVS_HI_IDLE_STATE_PE                                  0x00000004
+#define VIVS_HI_IDLE_STATE_SH                                  0x00000008
+#define VIVS_HI_IDLE_STATE_PA                                  0x00000010
+#define VIVS_HI_IDLE_STATE_SE                                  0x00000020
+#define VIVS_HI_IDLE_STATE_RA                                  0x00000040
+#define VIVS_HI_IDLE_STATE_TX                                  0x00000080
+#define VIVS_HI_IDLE_STATE_VG                                  0x00000100
+#define VIVS_HI_IDLE_STATE_IM                                  0x00000200
+#define VIVS_HI_IDLE_STATE_FP                                  0x00000400
+#define VIVS_HI_IDLE_STATE_TS                                  0x00000800
+#define VIVS_HI_IDLE_STATE_AXI_LP                              0x80000000
+
+#define VIVS_HI_AXI_CONFIG                                     0x00000008
+#define VIVS_HI_AXI_CONFIG_AWID__MASK                          0x0000000f
+#define VIVS_HI_AXI_CONFIG_AWID__SHIFT                         0
+#define VIVS_HI_AXI_CONFIG_AWID(x)                             (((x) << 
VIVS_HI_AXI_CONFIG_AWID__SHIFT) & VIVS_HI_AXI_CONFIG_AWID__MASK)
+#define VIVS_HI_AXI_CONFIG_ARID__MASK                          0x000000f0
+#define VIVS_HI_AXI_CONFIG_ARID__SHIFT                         4
+#define VIVS_HI_AXI_CONFIG_ARID(x)                             (((x) << 
VIVS_HI_AXI_CONFIG_ARID__SHIFT) & VIVS_HI_AXI_CONFIG_ARID__MASK)
+#define VIVS_HI_AXI_CONFIG_AWCACHE__MASK                       0x00000f00
+#define VIVS_HI_AXI_CONFIG_AWCACHE__SHIFT                      8
+#define VIVS_HI_AXI_CONFIG_AWCACHE(x)                          (((x) << 
VIVS_HI_AXI_CONFIG_AWCACHE__SHIFT) & VIVS_HI_AXI_CONFIG_AWCACHE__MASK)
+#define VIVS_HI_AXI_CONFIG_ARCACHE__MASK                       0x0000f000
+#define VIVS_HI_AXI_CONFIG_ARCACHE__SHIFT                      12
+#define VIVS_HI_AXI_CONFIG_ARCACHE(x)                          (((x) << 
VIVS_HI_AXI_CONFIG_ARCACHE__SHIFT) & VIVS_HI_AXI_CONFIG_ARCACHE__MASK)
+
+#define VIVS_HI_AXI_STATUS                                     0x0000000c
+#define VIVS_HI_AXI_STATUS_WR_ERR_ID__MASK                     0x0000000f
+#define VIVS_HI_AXI_STATUS_WR_ERR_ID__SHIFT                    0
+#define VIVS_HI_AXI_STATUS_WR_ERR_ID(x)                                (((x) 
<< VIVS_HI_AXI_STATUS_WR_ERR_ID__SHIFT) & VIVS_HI_AXI_STATUS_WR_ERR_ID__MASK)
+#define VIVS_HI_AXI_STATUS_RD_ERR_ID__MASK                     0x000000f0
+#define VIVS_HI_AXI_STATUS_RD_ERR_ID__SHIFT                    4
+#define VIVS_HI_AXI_STATUS_RD_ERR_ID(x)                                (((x) 
<< VIVS_HI_AXI_STATUS_RD_ERR_ID__SHIFT) & VIVS_HI_AXI_STATUS_RD_ERR_ID__MASK)
+#define VIVS_HI_AXI_STATUS_DET_WR_ERR                          0x00000100
+#define VIVS_HI_AXI_STATUS_DET_RD_ERR                          0x00000200
+
+#define VIVS_HI_INTR_ACKNOWLEDGE                               0x00000010
+#define VIVS_HI_INTR_ACKNOWLEDGE_INTR_VEC__MASK                        
0x7fffffff
+#define VIVS_HI_INTR_ACKNOWLEDGE_INTR_VEC__SHIFT               0
+#define VIVS_HI_INTR_ACKNOWLEDGE_INTR_VEC(x)                   (((x) << 
VIVS_HI_INTR_ACKNOWLEDGE_INTR_VEC__SHIFT) & 
VIVS_HI_INTR_ACKNOWLEDGE_INTR_VEC__MASK)
+#define VIVS_HI_INTR_ACKNOWLEDGE_AXI_BUS_ERROR                 0x80000000
+
+#define VIVS_HI_INTR_ENBL                                      0x00000014
+#define VIVS_HI_INTR_ENBL_INTR_ENBL_VEC__MASK                  0xffffffff
+#define VIVS_HI_INTR_ENBL_INTR_ENBL_VEC__SHIFT                 0
+#define VIVS_HI_INTR_ENBL_INTR_ENBL_VEC(x)                     (((x) << 
VIVS_HI_INTR_ENBL_INTR_ENBL_VEC__SHIFT) & VIVS_HI_INTR_ENBL_INTR_ENBL_VEC__MASK)
+
+#define VIVS_HI_CHIP_IDENTITY                                  0x00000018
+#define VIVS_HI_CHIP_IDENTITY_FAMILY__MASK                     0xff000000
+#define VIVS_HI_CHIP_IDENTITY_FAMILY__SHIFT                    24
+#define VIVS_HI_CHIP_IDENTITY_FAMILY(x)                                (((x) 
<< VIVS_HI_CHIP_IDENTITY_FAMILY__SHIFT) & VIVS_HI_CHIP_IDENTITY_FAMILY__MASK)
+#define VIVS_HI_CHIP_IDENTITY_PRODUCT__MASK                    0x00ff0000
+#define VIVS_HI_CHIP_IDENTITY_PRODUCT__SHIFT                   16
+#define VIVS_HI_CHIP_IDENTITY_PRODUCT(x)                       (((x) << 
VIVS_HI_CHIP_IDENTITY_PRODUCT__SHIFT) & VIVS_HI_CHIP_IDENTITY_PRODUCT__MASK)
+#define VIVS_HI_CHIP_IDENTITY_REVISION__MASK                   0x0000f000
+#define VIVS_HI_CHIP_IDENTITY_REVISION__SHIFT                  12
+#define VIVS_HI_CHIP_IDENTITY_REVISION(x)                      (((x) << 
VIVS_HI_CHIP_IDENTITY_REVISION__SHIFT) & VIVS_HI_CHIP_IDENTITY_REVISION__MASK)
+
+#define VIVS_HI_CHIP_FEATURE                                   0x0000001c
+
+#define VIVS_HI_CHIP_MODEL                                     0x00000020
+
+#define VIVS_HI_CHIP_REV                                       0x00000024
+
+#define VIVS_HI_CHIP_DATE                                      0x00000028
+
+#define VIVS_HI_CHIP_TIME                                      0x0000002c
+
+#define VIVS_HI_CHIP_MINOR_FEATURE_0                           0x00000034
+
+#define VIVS_HI_CACHE_CONTROL                                  0x00000038
+
+#define VIVS_HI_MEMORY_COUNTER_RESET                           0x0000003c
+
+#define VIVS_HI_PROFILE_READ_BYTES8                            0x00000040
+
+#define VIVS_HI_PROFILE_WRITE_BYTES8                           0x00000044
+
+#define VIVS_HI_CHIP_SPECS                                     0x00000048
+#define VIVS_HI_CHIP_SPECS_STREAM_COUNT__MASK                  0x0000000f
+#define VIVS_HI_CHIP_SPECS_STREAM_COUNT__SHIFT                 0
+#define VIVS_HI_CHIP_SPECS_STREAM_COUNT(x)                     (((x) << 
VIVS_HI_CHIP_SPECS_STREAM_COUNT__SHIFT) & VIVS_HI_CHIP_SPECS_STREAM_COUNT__MASK)
+#define VIVS_HI_CHIP_SPECS_REGISTER_MAX__MASK                  0x000000f0
+#define VIVS_HI_CHIP_SPECS_REGISTER_MAX__SHIFT                 4
+#define VIVS_HI_CHIP_SPECS_REGISTER_MAX(x)                     (((x) << 
VIVS_HI_CHIP_SPECS_REGISTER_MAX__SHIFT) & VIVS_HI_CHIP_SPECS_REGISTER_MAX__MASK)
+#define VIVS_HI_CHIP_SPECS_THREAD_COUNT__MASK                  0x00000f00
+#define VIVS_HI_CHIP_SPECS_THREAD_COUNT__SHIFT                 8
+#define VIVS_HI_CHIP_SPECS_THREAD_COUNT(x)                     (((x) << 
VIVS_HI_CHIP_SPECS_THREAD_COUNT__SHIFT) & VIVS_HI_CHIP_SPECS_THREAD_COUNT__MASK)
+#define VIVS_HI_CHIP_SPECS_VERTEX_CACHE_SIZE__MASK             0x0001f000
+#define VIVS_HI_CHIP_SPECS_VERTEX_CACHE_SIZE__SHIFT            12
+#define VIVS_HI_CHIP_SPECS_VERTEX_CACHE_SIZE(x)                        (((x) 
<< VIVS_HI_CHIP_SPECS_VERTEX_CACHE_SIZE__SHIFT) & 
VIVS_HI_CHIP_SPECS_VERTEX_CACHE_SIZE__MASK)
+#define VIVS_HI_CHIP_SPECS_SHADER_CORE_COUNT__MASK             0x01f00000
+#define VIVS_HI_CHIP_SPECS_SHADER_CORE_COUNT__SHIFT            20
+#define VIVS_HI_CHIP_SPECS_SHADER_CORE_COUNT(x)                        (((x) 
<< VIVS_HI_CHIP_SPECS_SHADER_CORE_COUNT__SHIFT) & 
VIVS_HI_CHIP_SPECS_SHADER_CORE_COUNT__MASK)
+#define VIVS_HI_CHIP_SPECS_PIXEL_PIPES__MASK                   0x0e000000
+#define VIVS_HI_CHIP_SPECS_PIXEL_PIPES__SHIFT                  25
+#define VIVS_HI_CHIP_SPECS_PIXEL_PIPES(x)                      (((x) << 
VIVS_HI_CHIP_SPECS_PIXEL_PIPES__SHIFT) & VIVS_HI_CHIP_SPECS_PIXEL_PIPES__MASK)
+#define VIVS_HI_CHIP_SPECS_VERTEX_OUTPUT_BUFFER_SIZE__MASK     0xf0000000
+#define VIVS_HI_CHIP_SPECS_VERTEX_OUTPUT_BUFFER_SIZE__SHIFT    28
+#define VIVS_HI_CHIP_SPECS_VERTEX_OUTPUT_BUFFER_SIZE(x)                (((x) 
<< VIVS_HI_CHIP_SPECS_VERTEX_OUTPUT_BUFFER_SIZE__SHIFT) & 
VIVS_HI_CHIP_SPECS_VERTEX_OUTPUT_BUFFER_SIZE__MASK)
+
+#define VIVS_HI_PROFILE_WRITE_BURSTS                           0x0000004c
+
+#define VIVS_HI_PROFILE_WRITE_REQUESTS                         0x00000050
+
+#define VIVS_HI_PROFILE_READ_BURSTS                            0x00000058
+
+#define VIVS_HI_PROFILE_READ_REQUESTS                          0x0000005c
+
+#define VIVS_HI_PROFILE_READ_LASTS                             0x00000060
+
+#define VIVS_HI_GP_OUT0                                                
0x00000064
+
+#define VIVS_HI_GP_OUT1                                                
0x00000068
+
+#define VIVS_HI_GP_OUT2                                                
0x0000006c
+
+#define VIVS_HI_AXI_CONTROL                                    0x00000070
+#define VIVS_HI_AXI_CONTROL_WR_FULL_BURST_MODE                 0x00000001
+
+#define VIVS_HI_CHIP_MINOR_FEATURE_1                           0x00000074
+
+#define VIVS_HI_PROFILE_TOTAL_CYCLES                           0x00000078
+
+#define VIVS_HI_PROFILE_IDLE_CYCLES                            0x0000007c
+
+#define VIVS_HI_CHIP_SPECS_2                                   0x00000080
+#define VIVS_HI_CHIP_SPECS_2_BUFFER_SIZE__MASK                 0x000000ff
+#define VIVS_HI_CHIP_SPECS_2_BUFFER_SIZE__SHIFT                        0
+#define VIVS_HI_CHIP_SPECS_2_BUFFER_SIZE(x)                    (((x) << 
VIVS_HI_CHIP_SPECS_2_BUFFER_SIZE__SHIFT) & 
VIVS_HI_CHIP_SPECS_2_BUFFER_SIZE__MASK)
+#define VIVS_HI_CHIP_SPECS_2_INSTRUCTION_COUNT__MASK           0x0000ff00
+#define VIVS_HI_CHIP_SPECS_2_INSTRUCTION_COUNT__SHIFT          8
+#define VIVS_HI_CHIP_SPECS_2_INSTRUCTION_COUNT(x)              (((x) << 
VIVS_HI_CHIP_SPECS_2_INSTRUCTION_COUNT__SHIFT) & 
VIVS_HI_CHIP_SPECS_2_INSTRUCTION_COUNT__MASK)
+#define VIVS_HI_CHIP_SPECS_2_NUM_CONSTANTS__MASK               0xffff0000
+#define VIVS_HI_CHIP_SPECS_2_NUM_CONSTANTS__SHIFT              16
+#define VIVS_HI_CHIP_SPECS_2_NUM_CONSTANTS(x)                  (((x) << 
VIVS_HI_CHIP_SPECS_2_NUM_CONSTANTS__SHIFT) & 
VIVS_HI_CHIP_SPECS_2_NUM_CONSTANTS__MASK)
+
+#define VIVS_HI_CHIP_MINOR_FEATURE_2                           0x00000084
+
+#define VIVS_HI_CHIP_MINOR_FEATURE_3                           0x00000088
+
+#define VIVS_HI_CHIP_MINOR_FEATURE_4                           0x00000094
+
+#define VIVS_PM                                                        
0x00000000
+
+#define VIVS_PM_POWER_CONTROLS                                 0x00000100
+#define VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING      0x00000001
+#define VIVS_PM_POWER_CONTROLS_DISABLE_STALL_MODULE_CLOCK_GATING       
0x00000002
+#define VIVS_PM_POWER_CONTROLS_DISABLE_STARVE_MODULE_CLOCK_GATING      
0x00000004
+#define VIVS_PM_POWER_CONTROLS_TURN_ON_COUNTER__MASK           0x000000f0
+#define VIVS_PM_POWER_CONTROLS_TURN_ON_COUNTER__SHIFT          4
+#define VIVS_PM_POWER_CONTROLS_TURN_ON_COUNTER(x)              (((x) << 
VIVS_PM_POWER_CONTROLS_TURN_ON_COUNTER__SHIFT) & 
VIVS_PM_POWER_CONTROLS_TURN_ON_COUNTER__MASK)
+#define VIVS_PM_POWER_CONTROLS_TURN_OFF_COUNTER__MASK          0xffff0000
+#define VIVS_PM_POWER_CONTROLS_TURN_OFF_COUNTER__SHIFT         16
+#define VIVS_PM_POWER_CONTROLS_TURN_OFF_COUNTER(x)             (((x) << 
VIVS_PM_POWER_CONTROLS_TURN_OFF_COUNTER__SHIFT) & 
VIVS_PM_POWER_CONTROLS_TURN_OFF_COUNTER__MASK)
+
+#define VIVS_PM_MODULE_CONTROLS                                        
0x00000104
+#define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_FE 0x00000001
+#define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_DE 0x00000002
+#define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_PE 0x00000004
+
+#define VIVS_PM_MODULE_STATUS                                  0x00000108
+#define VIVS_PM_MODULE_STATUS_MODULE_CLOCK_GATED_FE            0x00000001
+#define VIVS_PM_MODULE_STATUS_MODULE_CLOCK_GATED_DE            0x00000002
+#define VIVS_PM_MODULE_STATUS_MODULE_CLOCK_GATED_PE            0x00000004
+
+#define VIVS_PM_PULSE_EATER                                    0x0000010c
+
+#define VIVS_MMUv2                                             0x00000000
+
+#define VIVS_MMUv2_SAFE_ADDRESS                                        
0x00000180
+
+#define VIVS_MMUv2_CONFIGURATION                               0x00000184
+#define VIVS_MMUv2_CONFIGURATION_MODE__MASK                    0x00000001
+#define VIVS_MMUv2_CONFIGURATION_MODE__SHIFT                   0
+#define VIVS_MMUv2_CONFIGURATION_MODE_MODE4_K                  0x00000000
+#define VIVS_MMUv2_CONFIGURATION_MODE_MODE1_K                  0x00000001
+#define VIVS_MMUv2_CONFIGURATION_MODE_MASK                     0x00000008
+#define VIVS_MMUv2_CONFIGURATION_FLUSH__MASK                   0x00000010
+#define VIVS_MMUv2_CONFIGURATION_FLUSH__SHIFT                  4
+#define VIVS_MMUv2_CONFIGURATION_FLUSH_FLUSH                   0x00000010
+#define VIVS_MMUv2_CONFIGURATION_FLUSH_MASK                    0x00000080
+#define VIVS_MMUv2_CONFIGURATION_ADDRESS_MASK                  0x00000100
+#define VIVS_MMUv2_CONFIGURATION_ADDRESS__MASK                 0xfffffc00
+#define VIVS_MMUv2_CONFIGURATION_ADDRESS__SHIFT                        10
+#define VIVS_MMUv2_CONFIGURATION_ADDRESS(x)                    (((x) << 
VIVS_MMUv2_CONFIGURATION_ADDRESS__SHIFT) & 
VIVS_MMUv2_CONFIGURATION_ADDRESS__MASK)
+
+#define VIVS_MMUv2_STATUS                                      0x00000188
+#define VIVS_MMUv2_STATUS_EXCEPTION0__MASK                     0x00000003
+#define VIVS_MMUv2_STATUS_EXCEPTION0__SHIFT                    0
+#define VIVS_MMUv2_STATUS_EXCEPTION0(x)                                (((x) 
<< VIVS_MMUv2_STATUS_EXCEPTION0__SHIFT) & VIVS_MMUv2_STATUS_EXCEPTION0__MASK)
+#define VIVS_MMUv2_STATUS_EXCEPTION1__MASK                     0x00000030
+#define VIVS_MMUv2_STATUS_EXCEPTION1__SHIFT                    4
+#define VIVS_MMUv2_STATUS_EXCEPTION1(x)                                (((x) 
<< VIVS_MMUv2_STATUS_EXCEPTION1__SHIFT) & VIVS_MMUv2_STATUS_EXCEPTION1__MASK)
+#define VIVS_MMUv2_STATUS_EXCEPTION2__MASK                     0x00000300
+#define VIVS_MMUv2_STATUS_EXCEPTION2__SHIFT                    8
+#define VIVS_MMUv2_STATUS_EXCEPTION2(x)                                (((x) 
<< VIVS_MMUv2_STATUS_EXCEPTION2__SHIFT) & VIVS_MMUv2_STATUS_EXCEPTION2__MASK)
+#define VIVS_MMUv2_STATUS_EXCEPTION3__MASK                     0x00003000
+#define VIVS_MMUv2_STATUS_EXCEPTION3__SHIFT                    12
+#define VIVS_MMUv2_STATUS_EXCEPTION3(x)                                (((x) 
<< VIVS_MMUv2_STATUS_EXCEPTION3__SHIFT) & VIVS_MMUv2_STATUS_EXCEPTION3__MASK)
+
+#define VIVS_MMUv2_CONTROL                                     0x0000018c
+#define VIVS_MMUv2_CONTROL_ENABLE                              0x00000001
+
+#define VIVS_MMUv2_EXCEPTION_ADDR(i0)                         (0x00000190 + 
0x4*(i0))
+#define VIVS_MMUv2_EXCEPTION_ADDR__ESIZE                       0x00000004
+#define VIVS_MMUv2_EXCEPTION_ADDR__LEN                         0x00000004
+
+#define VIVS_MC                                                        
0x00000000
+
+#define VIVS_MC_MMU_FE_PAGE_TABLE                              0x00000400
+
+#define VIVS_MC_MMU_TX_PAGE_TABLE                              0x00000404
+
+#define VIVS_MC_MMU_PE_PAGE_TABLE                              0x00000408
+
+#define VIVS_MC_MMU_PEZ_PAGE_TABLE                             0x0000040c
+
+#define VIVS_MC_MMU_RA_PAGE_TABLE                              0x00000410
+
+#define VIVS_MC_DEBUG_MEMORY                                   0x00000414
+#define VIVS_MC_DEBUG_MEMORY_SPECIAL_PATCH_GC320               0x00000008
+#define VIVS_MC_DEBUG_MEMORY_FAST_CLEAR_BYPASS                 0x00100000
+#define VIVS_MC_DEBUG_MEMORY_COMPRESSION_BYPASS                        
0x00200000
+
+#define VIVS_MC_MEMORY_BASE_ADDR_RA                            0x00000418
+
+#define VIVS_MC_MEMORY_BASE_ADDR_FE                            0x0000041c
+
+#define VIVS_MC_MEMORY_BASE_ADDR_TX                            0x00000420
+
+#define VIVS_MC_MEMORY_BASE_ADDR_PEZ                           0x00000424
+
+#define VIVS_MC_MEMORY_BASE_ADDR_PE                            0x00000428
+
+#define VIVS_MC_MEMORY_TIMING_CONTROL                          0x0000042c
+
+#define VIVS_MC_MEMORY_FLUSH                                   0x00000430
+
+#define VIVS_MC_PROFILE_CYCLE_COUNTER                          0x00000438
+
+#define VIVS_MC_DEBUG_READ0                                    0x0000043c
+
+#define VIVS_MC_DEBUG_READ1                                    0x00000440
+
+#define VIVS_MC_DEBUG_WRITE                                    0x00000444
+
+#define VIVS_MC_PROFILE_RA_READ                                        
0x00000448
+
+#define VIVS_MC_PROFILE_TX_READ                                        
0x0000044c
+
+#define VIVS_MC_PROFILE_FE_READ                                        
0x00000450
+
+#define VIVS_MC_PROFILE_PE_READ                                        
0x00000454
+
+#define VIVS_MC_PROFILE_DE_READ                                        
0x00000458
+
+#define VIVS_MC_PROFILE_SH_READ                                        
0x0000045c
+
+#define VIVS_MC_PROFILE_PA_READ                                        
0x00000460
+
+#define VIVS_MC_PROFILE_SE_READ                                        
0x00000464
+
+#define VIVS_MC_PROFILE_MC_READ                                        
0x00000468
+
+#define VIVS_MC_PROFILE_HI_READ                                        
0x0000046c
+
+#define VIVS_MC_PROFILE_CONFIG0                                        
0x00000470
+#define VIVS_MC_PROFILE_CONFIG0_FE__MASK                       0x0000000f
+#define VIVS_MC_PROFILE_CONFIG0_FE__SHIFT                      0
+#define VIVS_MC_PROFILE_CONFIG0_FE_RESET                       0x0000000f
+#define VIVS_MC_PROFILE_CONFIG0_DE__MASK                       0x00000f00
+#define VIVS_MC_PROFILE_CONFIG0_DE__SHIFT                      8
+#define VIVS_MC_PROFILE_CONFIG0_DE_RESET                       0x00000f00
+#define VIVS_MC_PROFILE_CONFIG0_PE__MASK                       0x000f0000
+#define VIVS_MC_PROFILE_CONFIG0_PE__SHIFT                      16
+#define VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_COLOR_PIPE    
0x00000000
+#define VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_DEPTH_PIPE    
0x00010000
+#define VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_COLOR_PIPE     
0x00020000
+#define VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE     
0x00030000
+#define VIVS_MC_PROFILE_CONFIG0_PE_PIXELS_RENDERED_2D          0x000b0000
+#define VIVS_MC_PROFILE_CONFIG0_PE_RESET                       0x000f0000
+#define VIVS_MC_PROFILE_CONFIG0_SH__MASK                       0x0f000000
+#define VIVS_MC_PROFILE_CONFIG0_SH__SHIFT                      24
+#define VIVS_MC_PROFILE_CONFIG0_SH_SHADER_CYCLES               0x04000000
+#define VIVS_MC_PROFILE_CONFIG0_SH_PS_INST_COUNTER             0x07000000
+#define VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_PIXEL_COUNTER      0x08000000
+#define VIVS_MC_PROFILE_CONFIG0_SH_VS_INST_COUNTER             0x09000000
+#define VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_VERTICE_COUNTER    0x0a000000
+#define VIVS_MC_PROFILE_CONFIG0_SH_VTX_BRANCH_INST_COUNTER     0x0b000000
+#define VIVS_MC_PROFILE_CONFIG0_SH_VTX_TEXLD_INST_COUNTER      0x0c000000
+#define VIVS_MC_PROFILE_CONFIG0_SH_PXL_BRANCH_INST_COUNTER     0x0d000000
+#define VIVS_MC_PROFILE_CONFIG0_SH_PXL_TEXLD_INST_COUNTER      0x0e000000
+#define VIVS_MC_PROFILE_CONFIG0_SH_RESET                       0x0f000000
+
+#define VIVS_MC_PROFILE_CONFIG1                                        
0x00000474
+#define VIVS_MC_PROFILE_CONFIG1_PA__MASK                       0x0000000f
+#define VIVS_MC_PROFILE_CONFIG1_PA__SHIFT                      0
+#define VIVS_MC_PROFILE_CONFIG1_PA_INPUT_VTX_COUNTER           0x00000003
+#define VIVS_MC_PROFILE_CONFIG1_PA_INPUT_PRIM_COUNTER          0x00000004
+#define VIVS_MC_PROFILE_CONFIG1_PA_OUTPUT_PRIM_COUNTER         0x00000005
+#define VIVS_MC_PROFILE_CONFIG1_PA_DEPTH_CLIPPED_COUNTER       0x00000006
+#define VIVS_MC_PROFILE_CONFIG1_PA_TRIVIAL_REJECTED_COUNTER    0x00000007
+#define VIVS_MC_PROFILE_CONFIG1_PA_CULLED_COUNTER              0x00000008
+#define VIVS_MC_PROFILE_CONFIG1_PA_RESET                       0x0000000f
+#define VIVS_MC_PROFILE_CONFIG1_SE__MASK                       0x00000f00
+#define VIVS_MC_PROFILE_CONFIG1_SE__SHIFT                      8
+#define VIVS_MC_PROFILE_CONFIG1_SE_CULLED_TRIANGLE_COUNT       0x00000000
+#define VIVS_MC_PROFILE_CONFIG1_SE_CULLED_LINES_COUNT          0x00000100
+#define VIVS_MC_PROFILE_CONFIG1_SE_RESET                       0x00000f00
+#define VIVS_MC_PROFILE_CONFIG1_RA__MASK                       0x000f0000
+#define VIVS_MC_PROFILE_CONFIG1_RA__SHIFT                      16
+#define VIVS_MC_PROFILE_CONFIG1_RA_VALID_PIXEL_COUNT           0x00000000
+#define VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_QUAD_COUNT            0x00010000
+#define VIVS_MC_PROFILE_CONFIG1_RA_VALID_QUAD_COUNT_AFTER_EARLY_Z      
0x00020000
+#define VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_PRIMITIVE_COUNT       0x00030000
+#define VIVS_MC_PROFILE_CONFIG1_RA_PIPE_CACHE_MISS_COUNTER     0x00090000
+#define VIVS_MC_PROFILE_CONFIG1_RA_PREFETCH_CACHE_MISS_COUNTER 0x000a0000
+#define VIVS_MC_PROFILE_CONFIG1_RA_CULLED_QUAD_COUNT           0x000b0000
+#define VIVS_MC_PROFILE_CONFIG1_RA_RESET                       0x000f0000
+#define VIVS_MC_PROFILE_CONFIG1_TX__MASK                       0x0f000000
+#define VIVS_MC_PROFILE_CONFIG1_TX__SHIFT                      24
+#define VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_BILINEAR_REQUESTS     0x00000000
+#define VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TRILINEAR_REQUESTS    0x01000000
+#define VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_DISCARDED_TEXTURE_REQUESTS    
0x02000000
+#define VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TEXTURE_REQUESTS      0x03000000
+#define VIVS_MC_PROFILE_CONFIG1_TX_UNKNOWN                     0x04000000
+#define VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_COUNT              0x05000000
+#define VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_IN_8B_COUNT                
0x06000000
+#define VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_COUNT            0x07000000
+#define VIVS_MC_PROFILE_CONFIG1_TX_CACHE_HIT_TEXEL_COUNT       0x08000000
+#define VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_TEXEL_COUNT      0x09000000
+#define VIVS_MC_PROFILE_CONFIG1_TX_RESET                       0x0f000000
+
+#define VIVS_MC_PROFILE_CONFIG2                                        
0x00000478
+#define VIVS_MC_PROFILE_CONFIG2_MC__MASK                       0x0000000f
+#define VIVS_MC_PROFILE_CONFIG2_MC__SHIFT                      0
+#define VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_PIPELINE     
0x00000001
+#define VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_IP   0x00000002
+#define VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_WRITE_REQ_8B_FROM_PIPELINE    
0x00000003
+#define VIVS_MC_PROFILE_CONFIG2_MC_RESET                       0x0000000f
+#define VIVS_MC_PROFILE_CONFIG2_HI__MASK                       0x00000f00
+#define VIVS_MC_PROFILE_CONFIG2_HI__SHIFT                      8
+#define VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_READ_REQUEST_STALLED     
0x00000000
+#define VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_REQUEST_STALLED    
0x00000100
+#define VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_DATA_STALLED       
0x00000200
+#define VIVS_MC_PROFILE_CONFIG2_HI_RESET                       0x00000f00
+
+#define VIVS_MC_PROFILE_CONFIG3                                        
0x0000047c
+
+#define VIVS_MC_BUS_CONFIG                                     0x00000480
+
+#define VIVS_MC_START_COMPOSITION                              0x00000554
+
+#define VIVS_MC_128B_MERGE                                     0x00000558
+
+
+#endif /* STATE_HI_XML */
diff --git a/include/uapi/drm/etnaviv_drm.h b/include/uapi/drm/etnaviv_drm.h
new file mode 100644
index 000000000000..f7b5ac6f3842
--- /dev/null
+++ b/include/uapi/drm/etnaviv_drm.h
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ETNAVIV_DRM_H__
+#define __ETNAVIV_DRM_H__
+
+#include <stddef.h>
+#include <drm/drm.h>
+
+/* Please note that modifications to all structs defined here are
+ * subject to backwards-compatibility constraints:
+ *  1) Do not use pointers, use uint64_t instead for 32 bit / 64 bit
+ *     user/kernel compatibility
+ *  2) Keep fields aligned to their size
+ *  3) Because of how drm_ioctl() works, we can add new fields at
+ *     the end of an ioctl if some care is taken: drm_ioctl() will
+ *     zero out the new fields at the tail of the ioctl, so a zero
+ *     value should have a backwards compatible meaning.  And for
+ *     output params, userspace won't see the newly added output
+ *     fields.. so that has to be somehow ok.
+ */
+
+#define ETNA_PIPE_3D      0x00
+#define ETNA_PIPE_2D      0x01
+#define ETNA_PIPE_VG      0x02
+
+#define ETNA_MAX_PIPES    3
+
+/* timeouts are specified in clock-monotonic absolute times (to simplify
+ * restarting interrupted ioctls).  The following struct is logically the
+ * same as 'struct timespec' but 32/64b ABI safe.
+ */
+struct drm_etnaviv_timespec {
+       int64_t tv_sec;          /* seconds */
+       int64_t tv_nsec;         /* nanoseconds */
+};
+
+#define ETNAVIV_PARAM_GPU_MODEL                     0x01
+#define ETNAVIV_PARAM_GPU_REVISION                  0x02
+#define ETNAVIV_PARAM_GPU_FEATURES_0                0x03
+#define ETNAVIV_PARAM_GPU_FEATURES_1                0x04
+#define ETNAVIV_PARAM_GPU_FEATURES_2                0x05
+#define ETNAVIV_PARAM_GPU_FEATURES_3                0x06
+#define ETNAVIV_PARAM_GPU_FEATURES_4                0x07
+
+#define ETNAVIV_PARAM_GPU_STREAM_COUNT              0x10
+#define ETNAVIV_PARAM_GPU_REGISTER_MAX              0x11
+#define ETNAVIV_PARAM_GPU_THREAD_COUNT              0x12
+#define ETNAVIV_PARAM_GPU_VERTEX_CACHE_SIZE         0x13
+#define ETNAVIV_PARAM_GPU_SHADER_CORE_COUNT         0x14
+#define ETNAVIV_PARAM_GPU_PIXEL_PIPES               0x15
+#define ETNAVIV_PARAM_GPU_VERTEX_OUTPUT_BUFFER_SIZE 0x16
+#define ETNAVIV_PARAM_GPU_BUFFER_SIZE               0x17
+#define ETNAVIV_PARAM_GPU_INSTRUCTION_COUNT         0x18
+#define ETNAVIV_PARAM_GPU_NUM_CONSTANTS             0x19
+
+//#define MSM_PARAM_GMEM_SIZE  0x02
+
+struct drm_etnaviv_param {
+       uint32_t pipe;           /* in, ETNA_PIPE_x */
+       uint32_t param;          /* in, ETNAVIV_PARAM_x */
+       uint64_t value;          /* out (get_param) or in (set_param) */
+};
+
+/*
+ * GEM buffers:
+ */
+
+#define ETNA_BO_CMDSTREAM    0x00000001
+#define ETNA_BO_CACHE_MASK   0x000f0000
+/* cache modes */
+#define ETNA_BO_CACHED       0x00010000
+#define ETNA_BO_WC           0x00020000
+#define ETNA_BO_UNCACHED     0x00040000
+
+struct drm_etnaviv_gem_new {
+       uint64_t size;           /* in */
+       uint32_t flags;          /* in, mask of ETNA_BO_x */
+       uint32_t handle;         /* out */
+};
+
+struct drm_etnaviv_gem_info {
+       uint32_t handle;         /* in */
+       uint32_t pad;
+       uint64_t offset;         /* out, offset to pass to mmap() */
+};
+
+#define ETNA_PREP_READ        0x01
+#define ETNA_PREP_WRITE       0x02
+#define ETNA_PREP_NOSYNC      0x04
+
+struct drm_etnaviv_gem_cpu_prep {
+       uint32_t handle;         /* in */
+       uint32_t op;             /* in, mask of ETNA_PREP_x */
+       struct drm_etnaviv_timespec timeout;   /* in */
+};
+
+struct drm_etnaviv_gem_cpu_fini {
+       uint32_t handle;         /* in */
+};
+
+/*
+ * Cmdstream Submission:
+ */
+
+/* The value written into the cmdstream is logically:
+ *
+ *   ((relocbuf->gpuaddr + reloc_offset) << shift) | or
+ *
+ * When we have GPU's w/ >32bit ptrs, it should be possible to deal
+ * with this by emit'ing two reloc entries with appropriate shift
+ * values.  Or a new ETNA_SUBMIT_CMD_x type would also be an option.
+ *
+ * NOTE that reloc's must be sorted by order of increasing submit_offset,
+ * otherwise EINVAL.
+ */
+struct drm_etnaviv_gem_submit_reloc {
+       uint32_t submit_offset;  /* in, offset from submit_bo */
+       uint32_t or;             /* in, value OR'd with result */
+       int32_t  shift;          /* in, amount of left shift (can be negative) 
*/
+       uint32_t reloc_idx;      /* in, index of reloc_bo buffer */
+       uint64_t reloc_offset;   /* in, offset from start of reloc_bo */
+};
+
+/* submit-types:
+ *   BUF - this cmd buffer is executed normally.
+ *   IB_TARGET_BUF - this cmd buffer is an IB target.  Reloc's are
+ *      processed normally, but the kernel does not setup an IB to
+ *      this buffer in the first-level ringbuffer
+ *   CTX_RESTORE_BUF - only executed if there has been a GPU context
+ *      switch since the last SUBMIT ioctl
+ */
+#define ETNA_SUBMIT_CMD_BUF             0x0001
+#define ETNA_SUBMIT_CMD_IB_TARGET_BUF   0x0002
+#define ETNA_SUBMIT_CMD_CTX_RESTORE_BUF 0x0003
+struct drm_etnaviv_gem_submit_cmd {
+       uint32_t type;           /* in, one of ETNA_SUBMIT_CMD_x */
+       uint32_t submit_idx;     /* in, index of submit_bo cmdstream buffer */
+       uint32_t submit_offset;  /* in, offset into submit_bo */
+       uint32_t size;           /* in, cmdstream size */
+       uint32_t pad;
+       uint32_t nr_relocs;      /* in, number of submit_reloc's */
+       uint64_t __user relocs;  /* in, ptr to array of submit_reloc's */
+};
+
+/* Each buffer referenced elsewhere in the cmdstream submit (ie. the
+ * cmdstream buffer(s) themselves or reloc entries) has one (and only
+ * one) entry in the submit->bos[] table.
+ *
+ * As a optimization, the current buffer (gpu virtual address) can be
+ * passed back through the 'presumed' field.  If on a subsequent reloc,
+ * userspace passes back a 'presumed' address that is still valid,
+ * then patching the cmdstream for this entry is skipped.  This can
+ * avoid kernel needing to map/access the cmdstream bo in the common
+ * case.
+ */
+#define ETNA_SUBMIT_BO_READ             0x0001
+#define ETNA_SUBMIT_BO_WRITE            0x0002
+struct drm_etnaviv_gem_submit_bo {
+       uint32_t flags;          /* in, mask of ETNA_SUBMIT_BO_x */
+       uint32_t handle;         /* in, GEM handle */
+       uint64_t presumed;       /* in/out, presumed buffer address */
+};
+
+/* Each cmdstream submit consists of a table of buffers involved, and
+ * one or more cmdstream buffers.  This allows for conditional execution
+ * (context-restore), and IB buffers needed for per tile/bin draw cmds.
+ */
+struct drm_etnaviv_gem_submit {
+       uint32_t pipe;           /* in, ETNA_PIPE_x */
+       uint32_t fence;          /* out */
+       uint32_t nr_bos;         /* in, number of submit_bo's */
+       uint32_t nr_cmds;        /* in, number of submit_cmd's */
+       uint64_t __user bos;     /* in, ptr to array of submit_bo's */
+       uint64_t __user cmds;    /* in, ptr to array of submit_cmd's */
+};
+
+/* The normal way to synchronize with the GPU is just to CPU_PREP on
+ * a buffer if you need to access it from the CPU (other cmdstream
+ * submission from same or other contexts, PAGE_FLIP ioctl, etc, all
+ * handle the required synchronization under the hood).  This ioctl
+ * mainly just exists as a way to implement the gallium pipe_fence
+ * APIs without requiring a dummy bo to synchronize on.
+ */
+struct drm_etnaviv_wait_fence {
+       uint32_t pipe;           /* in, ETNA_PIPE_x */
+       uint32_t fence;          /* in */
+       struct drm_etnaviv_timespec timeout;   /* in */
+};
+
+#define DRM_ETNAVIV_GET_PARAM          0x00
+/* placeholder:
+#define DRM_MSM_SET_PARAM              0x01
+ */
+#define DRM_ETNAVIV_GEM_NEW            0x02
+#define DRM_ETNAVIV_GEM_INFO           0x03
+#define DRM_ETNAVIV_GEM_CPU_PREP       0x04
+#define DRM_ETNAVIV_GEM_CPU_FINI       0x05
+#define DRM_ETNAVIV_GEM_SUBMIT         0x06
+#define DRM_ETNAVIV_WAIT_FENCE         0x07
+#define DRM_ETNAVIV_NUM_IOCTLS         0x08
+
+#define DRM_IOCTL_ETNAVIV_GET_PARAM    DRM_IOWR(DRM_COMMAND_BASE + 
DRM_ETNAVIV_GET_PARAM, struct drm_etnaviv_param)
+#define DRM_IOCTL_ETNAVIV_GEM_NEW      DRM_IOWR(DRM_COMMAND_BASE + 
DRM_ETNAVIV_GEM_NEW, struct drm_etnaviv_gem_new)
+#define DRM_IOCTL_ETNAVIV_GEM_INFO     DRM_IOWR(DRM_COMMAND_BASE + 
DRM_ETNAVIV_GEM_INFO, struct drm_etnaviv_gem_info)
+#define DRM_IOCTL_ETNAVIV_GEM_CPU_PREP DRM_IOW (DRM_COMMAND_BASE + 
DRM_ETNAVIV_GEM_CPU_PREP, struct drm_etnaviv_gem_cpu_prep)
+#define DRM_IOCTL_ETNAVIV_GEM_CPU_FINI DRM_IOW (DRM_COMMAND_BASE + 
DRM_ETNAVIV_GEM_CPU_FINI, struct drm_etnaviv_gem_cpu_fini)
+#define DRM_IOCTL_ETNAVIV_GEM_SUBMIT   DRM_IOWR(DRM_COMMAND_BASE + 
DRM_ETNAVIV_GEM_SUBMIT, struct drm_etnaviv_gem_submit)
+#define DRM_IOCTL_ETNAVIV_WAIT_FENCE   DRM_IOW (DRM_COMMAND_BASE + 
DRM_ETNAVIV_WAIT_FENCE, struct drm_etnaviv_wait_fence)
+
+#endif /* __ETNAVIV_DRM_H__ */
-- 
2.1.4

Reply via email to