summaryrefslogtreecommitdiff
path: root/drivers/mxc/amd-gpu/platform
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mxc/amd-gpu/platform')
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX35/gsl_buildconfig.h62
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX35/gsl_config.h195
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX35/gsl_halconfig.h63
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX35/linux/gsl_hal.c524
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX35/memcfg/gsl_memcfg.c31
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX35/memcfg/gsl_memcfg.h41
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX51/gsl_buildconfig.h62
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX51/gsl_config.h222
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX51/gsl_halconfig.h58
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX51/linux/gsl_hal.c598
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX51/memcfg/gsl_memcfg.c31
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX51/memcfg/gsl_memcfg.h40
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/linux/gsl_hwaccess.h155
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod.c973
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod_cleanup.c269
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod_cleanup.h90
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/linux/gsl_linux_map.c221
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/linux/gsl_linux_map.h46
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/linux/misc.c129
19 files changed, 3810 insertions, 0 deletions
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX35/gsl_buildconfig.h b/drivers/mxc/amd-gpu/platform/hal/MX35/gsl_buildconfig.h
new file mode 100644
index 000000000000..9cfe9fe5b3b8
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX35/gsl_buildconfig.h
@@ -0,0 +1,62 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __GSL__BUILDCONFIG_H
+#define __GSL__BUILDCONFIG_H
+
+#define GSL_BLD_G12
+
+#define GSL_LOCKING_COURSEGRAIN
+#define GSL_MMU_TRANSLATION_ENABLED
+//#define GSL_MMU_PAGETABLE_PERPROCESS
+
+#if defined(_WIN32_WCE) && (_WIN32_WCE >= 600)
+#define GSL_DEVICE_SHADOW_MEMSTORE_TO_USER
+#endif
+
+//#define GSL_LOG
+
+#define GSL_STATS_MEM
+#define GSL_STATS_RINGBUFFER
+#define GSL_STATS_MMU
+
+#define GSL_RB_USE_MEM_RPTR
+#define GSL_RB_USE_MEM_TIMESTAMP
+//#define GSL_RB_USE_WPTR_POLLING
+
+
+#define GSL_CALLER_PROCESS_MAX 10
+#define GSL_SHMEM_MAX_APERTURES 3
+
+#ifdef _WIN32
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+#endif // _WIN32
+
+#endif // __GSL__BUILDCONFIG_H
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX35/gsl_config.h b/drivers/mxc/amd-gpu/platform/hal/MX35/gsl_config.h
new file mode 100644
index 000000000000..58a38c608de9
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX35/gsl_config.h
@@ -0,0 +1,195 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __GSL__CONFIG_H
+#define __GSL__CONFIG_H
+
+
+// ---------------------
+// G12 MH arbiter config
+// ---------------------
+static const REG_MH_ARBITER_CONFIG gsl_cfg_g12_mharb =
+{
+ 0x10, // SAME_PAGE_LIMIT
+ 0, // SAME_PAGE_GRANULARITY
+ 1, // L1_ARB_ENABLE
+ 1, // L1_ARB_HOLD_ENABLE
+ 0, // L2_ARB_CONTROL
+ 1, // PAGE_SIZE
+ 1, // TC_REORDER_ENABLE
+ 1, // TC_ARB_HOLD_ENABLE
+ 0, // IN_FLIGHT_LIMIT_ENABLE
+ 0x8, // IN_FLIGHT_LIMIT
+ 1, // CP_CLNT_ENABLE
+ 1, // VGT_CLNT_ENABLE
+ 1, // TC_CLNT_ENABLE
+ 1, // RB_CLNT_ENABLE
+ 1, // PA_CLNT_ENABLE
+};
+
+// -----------------------------
+// interrupt block register data
+// -----------------------------
+static const gsl_intrblock_reg_t gsl_cfg_intrblock_reg[GSL_INTR_BLOCK_COUNT] =
+{
+ { // Yamato MH
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ },
+ { // Yamato CP
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ },
+ { // Yamato RBBM
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ },
+ { // Yamato SQ
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ },
+ { // G12
+ GSL_INTR_BLOCK_G12,
+ GSL_INTR_G12_MH,
+#ifndef _Z180
+ GSL_INTR_G12_FBC,
+#else
+ GSL_INTR_G12_FIFO,
+#endif //_Z180
+ (ADDR_VGC_IRQSTATUS >> 2),
+ (ADDR_VGC_IRQSTATUS >> 2),
+ (ADDR_VGC_IRQENABLE >> 2)
+ },
+ { // G12 MH
+ GSL_INTR_BLOCK_G12_MH,
+ GSL_INTR_G12_MH_AXI_READ_ERROR,
+ GSL_INTR_G12_MH_MMU_PAGE_FAULT,
+ ADDR_MH_INTERRUPT_STATUS, // G12 MH offsets are considered to be dword based, therefore no down shift
+ ADDR_MH_INTERRUPT_CLEAR,
+ ADDR_MH_INTERRUPT_MASK
+ },
+};
+
+// -----------------------
+// interrupt mask bit data
+// -----------------------
+static const int gsl_cfg_intr_mask[GSL_INTR_COUNT] =
+{
+ 0,
+ 0,
+ 0,
+
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+
+ 0,
+ 0,
+ 0,
+
+ 0,
+ 0,
+
+ (1 << VGC_IRQENABLE_MH_FSHIFT),
+ (1 << VGC_IRQENABLE_G2D_FSHIFT),
+ (1 << VGC_IRQENABLE_FIFO_FSHIFT),
+#ifndef _Z180
+ (1 << VGC_IRQENABLE_FBC_FSHIFT),
+#endif
+ 0,
+ 0,
+ 0,
+};
+
+// -----------------
+// mmu register data
+// -----------------
+static const gsl_mmu_reg_t gsl_cfg_mmu_reg[GSL_DEVICE_MAX] =
+{
+ { // Yamato
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ },
+ { // G12 - MH offsets are considered to be dword based, therefore no down shift
+ ADDR_MH_MMU_CONFIG,
+ ADDR_MH_MMU_MPU_BASE,
+ ADDR_MH_MMU_MPU_END,
+ ADDR_MH_MMU_VA_RANGE,
+ ADDR_MH_MMU_PT_BASE,
+ ADDR_MH_MMU_PAGE_FAULT,
+ ADDR_MH_MMU_TRAN_ERROR,
+ ADDR_MH_MMU_INVALIDATE,
+ }
+};
+
+// -----------------
+// mh interrupt data
+// -----------------
+static const gsl_mh_intr_t gsl_cfg_mh_intr[GSL_DEVICE_MAX] =
+{
+ { // Yamato
+ 0,
+ 0,
+ 0,
+ },
+ { // G12
+ GSL_INTR_G12_MH_AXI_READ_ERROR,
+ GSL_INTR_G12_MH_AXI_WRITE_ERROR,
+ GSL_INTR_G12_MH_MMU_PAGE_FAULT,
+ }
+};
+
+#endif // __GSL__CONFIG_H
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX35/gsl_halconfig.h b/drivers/mxc/amd-gpu/platform/hal/MX35/gsl_halconfig.h
new file mode 100644
index 000000000000..011041236013
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX35/gsl_halconfig.h
@@ -0,0 +1,63 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __GSL_HALCONFIG_H
+#define __GSL_HALCONFIG_H
+
+
+
+#define GSL_HAL_PLATFORM "i.MX35G"
+
+
+#define GSL_HAL_GPUBASE_GMEM 0x00100000 // 1MB
+#define GSL_HAL_GPUBASE_GMEM_PHYS 0x20000000 // 1MB
+
+#define GSL_HAL_GPUBASE_REG_YDX 0x30000000
+#define GSL_HAL_GPUBASE_REG_G12 0x20000000
+
+#define GSL_HAL_SIZE_REG_YDX 0x00020000 // 128KB
+#define GSL_HAL_SIZE_REG_G12 0x00001000 // 4KB
+#define GSL_HAL_SIZE_GMEM 0x00040000 // 256KB - 0 to 384KB in 128KB increments
+
+#if defined(_LINUX) && defined(GSL_MMU_TRANSLATION_ENABLED)
+#define GSL_HAL_SHMEM_SIZE_EMEM1 0x02400000 // 36MB
+#define GSL_HAL_SHMEM_SIZE_EMEM2 0x00400000 // 4MB
+#define GSL_HAL_SHMEM_SIZE_PHYS 0x00400000 // 4MB
+#elif defined(_LINUX) //MX35 Linux can able to allocate only 4MB
+#define GSL_HAL_SHMEM_SIZE_EMEM1 0x00400000 // 4MB
+#define GSL_HAL_SHMEM_SIZE_EMEM2 0x00200000 // 2MB
+#define GSL_HAL_SHMEM_SIZE_PHYS 0x00200000 // 2MB
+#else //Not possible to allocate 24 MB on WinCE
+#define GSL_HAL_SHMEM_SIZE_EMEM1 0x00D00000 // 13MB
+#define GSL_HAL_SHMEM_SIZE_EMEM2 0x00200000 // 2MB
+#define GSL_HAL_SHMEM_SIZE_PHYS 0x00100000 // 1MB
+#endif
+
+#define MX35_G12_INTERRUPT 16
+
+#endif // __GSL_HALCONFIG_H
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX35/linux/gsl_hal.c b/drivers/mxc/amd-gpu/platform/hal/MX35/linux/gsl_hal.c
new file mode 100644
index 000000000000..294cd9eb5af9
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX35/linux/gsl_hal.c
@@ -0,0 +1,524 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include "gsl_hal.h"
+#include "gsl_halconfig.h"
+#include "gsl_linux_map.h"
+
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+
+#include <asm/atomic.h>
+#include <asm/uaccess.h>
+#include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
+
+//////////////////////////////////////////////////////////////////////////////
+// constants
+//////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////////
+// defines
+//////////////////////////////////////////////////////////////////////////////
+
+#define GSL_HAL_MEM1 0
+#define GSL_HAL_MEM2 1
+#define GSL_HAL_MEM3 2
+
+//#define GSL_HAL_DEBUG
+//////////////////////////////////////////////////////////////////////////////
+// types
+//////////////////////////////////////////////////////////////////////////////
+
+typedef struct _gsl_hal_t {
+ gsl_memregion_t z160_regspace;
+#if 0
+ gsl_memregion_t z430_regspace;
+#endif
+ gsl_memregion_t memchunk;
+ gsl_memregion_t memspace[GSL_SHMEM_MAX_APERTURES];
+} gsl_hal_t;
+
+//////////////////////////////////////////////////////////////////////////////
+// functions
+//////////////////////////////////////////////////////////////////////////////
+
+KGSLHAL_API int
+kgsl_hal_allocphysical(unsigned int virtaddr, unsigned int numpages, unsigned int scattergatterlist[])
+{
+ //
+ // allocate physically contiguous memory
+ //
+
+ int i;
+ void *va;
+
+ va = (void*)gsl_linux_map_alloc(virtaddr, numpages*PAGE_SIZE);
+
+ if (!va)
+ return (GSL_FAILURE_OUTOFMEM);
+
+ for(i = 0; i < numpages; i++)
+ {
+ scattergatterlist[i] = page_to_phys(vmalloc_to_page(va));
+ va += PAGE_SIZE;
+ }
+
+ return (GSL_SUCCESS);
+}
+
+// ---------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_freephysical(unsigned int virtaddr, unsigned int numpages, unsigned int scattergatterlist[])
+{
+ //
+ // free physical memory
+ //
+
+ gsl_linux_map_free(virtaddr);
+
+ return(GSL_SUCCESS);
+}
+
+//----------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_init(void)
+{
+ gsl_hal_t *hal;
+ unsigned long totalsize, mem1size;
+ unsigned int va, pa;
+
+ if (gsl_driver.hal)
+ {
+ return (GSL_FAILURE_ALREADYINITIALIZED);
+ }
+
+ gsl_driver.hal = (void *)kos_malloc(sizeof(gsl_hal_t));
+
+ if (!gsl_driver.hal)
+ {
+ return (GSL_FAILURE_OUTOFMEM);
+ }
+
+ kos_memset(gsl_driver.hal, 0, sizeof(gsl_hal_t));
+
+
+ // overlay structure on hal memory
+ hal = (gsl_hal_t *) gsl_driver.hal;
+
+#if 0
+ // setup register space
+ hal->z430_regspace.mmio_phys_base = GSL_HAL_GPUBASE_REG_YDX;
+ hal->z430_regspace.sizebytes = GSL_HAL_SIZE_REG_YDX;
+ hal->z430_regspace.mmio_virt_base = (unsigned char*)ioremap(hal->z430_regspace.mmio_phys_base, hal->z430_regspace.sizebytes);
+
+ if (hal->z430_regspace.mmio_virt_base == NULL)
+ {
+ return (GSL_FAILURE_SYSTEMERROR);
+ }
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->z430_regspace.mmio_phys_base = 0x%p\n", __func__, (void*)hal->z430_regspace.mmio_phys_base);
+ printk(KERN_INFO "%s: hal->z430_regspace.mmio_virt_base = 0x%p\n", __func__, (void*)hal->z430_regspace.mmio_virt_base);
+ printk(KERN_INFO "%s: hal->z430_regspace.sizebytes = 0x%08x\n", __func__, hal->z430_regspace.sizebytes);
+#endif
+#endif
+
+ hal->z160_regspace.mmio_phys_base = GSL_HAL_GPUBASE_REG_G12;
+ hal->z160_regspace.sizebytes = GSL_HAL_SIZE_REG_G12;
+ hal->z160_regspace.mmio_virt_base = (unsigned char*)ioremap(hal->z160_regspace.mmio_phys_base, hal->z160_regspace.sizebytes);
+
+ if (hal->z160_regspace.mmio_virt_base == NULL)
+ {
+ return (GSL_FAILURE_SYSTEMERROR);
+ }
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->z160_regspace.mmio_phys_base = 0x%p\n", __func__, (void*)hal->z160_regspace.mmio_phys_base);
+ printk(KERN_INFO "%s: hal->z160_regspace.mmio_virt_base = 0x%p\n", __func__, (void*)hal->z160_regspace.mmio_virt_base);
+ printk(KERN_INFO "%s: hal->z160_regspace.sizebytes = 0x%08x\n", __func__, hal->z160_regspace.sizebytes);
+#endif
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ totalsize = GSL_HAL_SHMEM_SIZE_EMEM2 + GSL_HAL_SHMEM_SIZE_PHYS;
+ mem1size = GSL_HAL_SHMEM_SIZE_EMEM1;
+#else
+ totalsize = GSL_HAL_SHMEM_SIZE_EMEM1 + GSL_HAL_SHMEM_SIZE_EMEM2 + GSL_HAL_SHMEM_SIZE_PHYS;
+ mem1size = GSL_HAL_SHMEM_SIZE_EMEM1;
+#endif
+
+ // allocate a single chunk of physical memory
+ va = (unsigned int)dma_alloc_coherent(0, totalsize, (dma_addr_t *)&pa, GFP_DMA | GFP_KERNEL);
+
+ if (va)
+ {
+ kos_memset((void *)va, 0, totalsize);
+
+ hal->memchunk.mmio_virt_base = (void *)va;
+ hal->memchunk.mmio_phys_base = pa;
+ hal->memchunk.sizebytes = totalsize;
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->memchunk.mmio_phys_base = 0x%p\n", __func__, (void*)hal->memchunk.mmio_phys_base);
+ printk(KERN_INFO "%s: hal->memchunk.mmio_virt_base = 0x%p\n", __func__, (void*)hal->memchunk.mmio_virt_base);
+ printk(KERN_INFO "%s: hal->memchunk.sizebytes = 0x%08x\n", __func__, hal->memchunk.sizebytes);
+#endif
+
+ hal->memspace[GSL_HAL_MEM2].mmio_virt_base = (void *) va;
+ hal->memspace[GSL_HAL_MEM2].gpu_base = pa;
+ hal->memspace[GSL_HAL_MEM2].sizebytes = GSL_HAL_SHMEM_SIZE_EMEM2;
+ va += GSL_HAL_SHMEM_SIZE_EMEM2;
+ pa += GSL_HAL_SHMEM_SIZE_EMEM2;
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM2].gpu_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM2].gpu_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM2].mmio_virt_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM2].mmio_virt_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM2].sizebytes = 0x%08x\n", __func__, hal->memspace[GSL_HAL_MEM2].sizebytes);
+#endif
+
+ hal->memspace[GSL_HAL_MEM3].mmio_virt_base = (void *) va;
+ hal->memspace[GSL_HAL_MEM3].gpu_base = pa;
+ hal->memspace[GSL_HAL_MEM3].sizebytes = GSL_HAL_SHMEM_SIZE_PHYS;
+ va += GSL_HAL_SHMEM_SIZE_PHYS;
+ pa += GSL_HAL_SHMEM_SIZE_PHYS;
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM3].gpu_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM3].gpu_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM3].mmio_virt_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM3].mmio_virt_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM3].sizebytes = 0x%08x\n", __func__, hal->memspace[GSL_HAL_MEM3].sizebytes);
+#endif
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ gsl_linux_map_init();
+ hal->memspace[GSL_HAL_MEM1].mmio_virt_base = (void *)GSL_LINUX_MAP_RANGE_START;
+ hal->memspace[GSL_HAL_MEM1].gpu_base = GSL_LINUX_MAP_RANGE_START;
+ hal->memspace[GSL_HAL_MEM1].sizebytes = mem1size;
+#else
+ hal->memspace[GSL_HAL_MEM1].mmio_virt_base = (void *) va;
+ hal->memspace[GSL_HAL_MEM1].gpu_base = pa;
+ hal->memspace[GSL_HAL_MEM1].sizebytes = mem1size;
+#endif
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM1].gpu_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM1].gpu_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM1].mmio_virt_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM1].mmio_virt_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM1].sizebytes = 0x%08x\n", __func__, hal->memspace[GSL_HAL_MEM1].sizebytes);
+#endif
+ }
+ else
+ {
+ kgsl_hal_close();
+ return (GSL_FAILURE_SYSTEMERROR);
+ }
+
+ return GSL_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_close(void)
+{
+ gsl_hal_t *hal;
+
+ if (gsl_driver.hal)
+ {
+ // overlay structure on hal memory
+ hal = (gsl_hal_t *) gsl_driver.hal;
+
+ // unmap registers
+#if 0
+ if (hal->z430_regspace.mmio_virt_base)
+ {
+ iounmap(hal->z430_regspace.mmio_virt_base);
+ }
+#endif
+ if (hal->z160_regspace.mmio_virt_base)
+ {
+ iounmap(hal->z160_regspace.mmio_virt_base);
+ }
+
+ // free physical block
+ if (hal->memchunk.mmio_virt_base)
+ {
+ dma_free_coherent(0, hal->memchunk.sizebytes, hal->memchunk.mmio_virt_base, hal->memchunk.mmio_phys_base);
+ }
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ gsl_linux_map_destroy();
+#endif
+
+ // release hal struct
+ kos_memset(hal, 0, sizeof(gsl_hal_t));
+ kos_free(gsl_driver.hal);
+ gsl_driver.hal = NULL;
+ }
+
+ return (GSL_SUCCESS);
+}
+
+//----------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_getshmemconfig(gsl_shmemconfig_t *config)
+{
+ int status = GSL_FAILURE_DEVICEERROR;
+ gsl_hal_t *hal = (gsl_hal_t *) gsl_driver.hal;
+
+ kos_memset(config, 0, sizeof(gsl_shmemconfig_t));
+
+ if (hal)
+ {
+ config->numapertures = GSL_SHMEM_MAX_APERTURES;
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ config->apertures[0].id = GSL_APERTURE_MMU;
+#else
+ config->apertures[0].id = GSL_APERTURE_EMEM;
+#endif
+ config->apertures[0].channel = GSL_CHANNEL_1;
+ config->apertures[0].hostbase = (unsigned int)hal->memspace[GSL_HAL_MEM1].mmio_virt_base;
+ config->apertures[0].gpubase = hal->memspace[GSL_HAL_MEM1].gpu_base;
+ config->apertures[0].sizebytes = hal->memspace[GSL_HAL_MEM1].sizebytes;
+
+ config->apertures[1].id = GSL_APERTURE_EMEM;
+ config->apertures[1].channel = GSL_CHANNEL_2;
+ config->apertures[1].hostbase = (unsigned int)hal->memspace[GSL_HAL_MEM2].mmio_virt_base;
+ config->apertures[1].gpubase = hal->memspace[GSL_HAL_MEM2].gpu_base;
+ config->apertures[1].sizebytes = hal->memspace[GSL_HAL_MEM2].sizebytes;
+
+ config->apertures[2].id = GSL_APERTURE_PHYS;
+ config->apertures[2].channel = GSL_CHANNEL_1;
+ config->apertures[2].hostbase = (unsigned int)hal->memspace[GSL_HAL_MEM3].mmio_virt_base;
+ config->apertures[2].gpubase = hal->memspace[GSL_HAL_MEM3].gpu_base;
+ config->apertures[2].sizebytes = hal->memspace[GSL_HAL_MEM3].sizebytes;
+
+ status = GSL_SUCCESS;
+ }
+
+ return (status);
+}
+
+//----------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_getdevconfig(gsl_deviceid_t device_id, gsl_devconfig_t *config)
+{
+ int status = GSL_FAILURE_DEVICEERROR;
+ gsl_hal_t *hal = (gsl_hal_t *) gsl_driver.hal;
+
+ kos_memset(config, 0, sizeof(gsl_devconfig_t));
+
+ if (hal)
+ {
+ switch (device_id)
+ {
+ case GSL_DEVICE_YAMATO:
+ {
+#if 0
+ mh_mmu_config_u mmu_config = {0};
+
+ config->gmemspace.gpu_base = 0;
+ config->gmemspace.mmio_virt_base = 0;
+ config->gmemspace.mmio_phys_base = 0;
+ config->gmemspace.sizebytes = GSL_HAL_SIZE_GMEM;
+
+ config->regspace.gpu_base = 0;
+ config->regspace.mmio_virt_base = (unsigned char *)hal->z430_regspace.mmio_virt_base;
+ config->regspace.mmio_phys_base = (unsigned int) hal->z430_regspace.mmio_phys_base;
+ config->regspace.sizebytes = GSL_HAL_SIZE_REG_YDX;
+
+ mmu_config.f.mmu_enable = 1;
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ mmu_config.f.split_mode_enable = 0;
+ mmu_config.f.rb_w_clnt_behavior = 1;
+ mmu_config.f.cp_w_clnt_behavior = 1;
+ mmu_config.f.cp_r0_clnt_behavior = 1;
+ mmu_config.f.cp_r1_clnt_behavior = 1;
+ mmu_config.f.cp_r2_clnt_behavior = 1;
+ mmu_config.f.cp_r3_clnt_behavior = 1;
+ mmu_config.f.cp_r4_clnt_behavior = 1;
+ mmu_config.f.vgt_r0_clnt_behavior = 1;
+ mmu_config.f.vgt_r1_clnt_behavior = 1;
+ mmu_config.f.tc_r_clnt_behavior = 1;
+ mmu_config.f.pa_w_clnt_behavior = 1;
+#endif // GSL_MMU_TRANSLATION_ENABLED
+
+ config->mmu_config = mmu_config.val;
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ config->va_base = hal->memspace[GSL_HAL_MEM1].gpu_base;
+ config->va_range = hal->memspace[GSL_HAL_MEM1].sizebytes;
+#else
+ config->va_base = 0x00000000;
+ config->va_range = 0x00000000;
+#endif // GSL_MMU_TRANSLATION_ENABLED
+
+ // turn off memory protection unit by setting acceptable physical address range to include all pages
+ config->mpu_base = 0x00000000; // hal->memchunk.mmio_virt_base;
+ config->mpu_range = 0xFFFFF000; // hal->memchunk.sizebytes;
+
+ status = GSL_SUCCESS;
+#endif
+ break;
+ }
+
+ case GSL_DEVICE_G12:
+ {
+#ifndef GSL_MMU_TRANSLATION_ENABLED
+ unsigned int mmu_config = {0};
+#endif
+ config->regspace.gpu_base = 0;
+ config->regspace.mmio_virt_base = (unsigned char *)hal->z160_regspace.mmio_virt_base;
+ config->regspace.mmio_phys_base = (unsigned int) hal->z160_regspace.mmio_phys_base;
+ config->regspace.sizebytes = GSL_HAL_SIZE_REG_G12;
+
+
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ config->mmu_config = 0x00555551;
+ config->va_base = hal->memspace[GSL_HAL_MEM1].gpu_base;
+ config->va_range = hal->memspace[GSL_HAL_MEM1].sizebytes;
+#else
+ config->mmu_config = mmu_config;
+ config->va_base = 0x00000000;
+ config->va_range = 0x00000000;
+#endif // GSL_MMU_TRANSLATION_ENABLED
+
+ config->mpu_base = 0x00000000; //(unsigned int) hal->memchunk.mmio_virt_base;
+ config->mpu_range = 0xFFFFF000; //hal->memchunk.sizebytes;
+
+ status = GSL_SUCCESS;
+ break;
+ }
+
+ default:
+
+ break;
+ }
+ }
+
+ return (status);
+}
+
+//----------------------------------------------------------------------------
+//
+// kgsl_hal_getchipid
+//
+// The proper platform method, build from RBBM_PERIPHIDx and RBBM_PATCH_RELEASE
+//
+KGSLHAL_API gsl_chipid_t
+kgsl_hal_getchipid(gsl_deviceid_t device_id)
+{
+ return (0);
+}
+
+//----------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_getplatformtype(char *platform)
+{
+ if (gsl_driver.hal)
+ {
+ kos_strcpy(platform, GSL_HAL_PLATFORM);
+ return (GSL_SUCCESS);
+ }
+ else
+ {
+ return (GSL_FAILURE_NOTINITIALIZED);
+ }
+}
+
+//---------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_setpowerstate(gsl_deviceid_t device_id, int state, unsigned int value)
+{
+ gsl_device_t *device = &gsl_driver.device[device_id-1]; // device_id is 1 based
+ struct clk *gpu_clk = 0;
+
+ // unreferenced formal parameters
+ (void) value;
+
+ switch (device_id)
+ {
+ case GSL_DEVICE_G12:
+ gpu_clk = clk_get(0, "gpu2d_clk");
+ break;
+ default:
+ return (GSL_FAILURE_DEVICEERROR);
+ }
+
+ if (!gpu_clk)
+ return (GSL_FAILURE_DEVICEERROR);
+
+ switch (state)
+ {
+ case GSL_PWRFLAGS_CLK_ON:
+ break;
+ case GSL_PWRFLAGS_POWER_ON:
+ clk_enable(gpu_clk);
+ kgsl_device_autogate_init(&gsl_driver.device[device_id-1]);
+ break;
+ case GSL_PWRFLAGS_CLK_OFF:
+ break;
+ case GSL_PWRFLAGS_POWER_OFF:
+ if (device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT) != GSL_SUCCESS)
+ {
+ return (GSL_FAILURE_DEVICEERROR);
+ }
+ kgsl_device_autogate_exit(&gsl_driver.device[device_id-1]);
+ clk_disable(gpu_clk);
+ break;
+ default:
+ break;
+ }
+
+ return (GSL_SUCCESS);
+}
+
+KGSLHAL_API int kgsl_clock(gsl_deviceid_t dev, int enable)
+{
+ struct clk *gpu_clk = 0;
+
+ switch (dev)
+ {
+ case GSL_DEVICE_G12:
+ gpu_clk = clk_get(0, "gpu2d_clk");
+ break;
+ default:
+ printk(KERN_ERR "GPU device %d is invalid!\n", dev);
+ return (GSL_FAILURE_DEVICEERROR);
+ }
+
+ if (IS_ERR(gpu_clk)) {
+ printk(KERN_ERR "%s: GPU clock get failed!\n", __func__);
+ return (GSL_FAILURE_DEVICEERROR);
+ }
+
+ if (enable)
+ clk_enable(gpu_clk);
+ else
+ clk_disable(gpu_clk);
+
+ return (GSL_SUCCESS);
+}
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX35/memcfg/gsl_memcfg.c b/drivers/mxc/amd-gpu/platform/hal/MX35/memcfg/gsl_memcfg.c
new file mode 100644
index 000000000000..f3ca6191d7c2
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX35/memcfg/gsl_memcfg.c
@@ -0,0 +1,31 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include "kos_libapi.h"
+
+//
+// Return the maximum amount of memory that can be allocated to the Z160. This number
+// will be constrained to 2MB as a minimum and the original hardcoded value for the caller
+// as a maximum. If the return value is outside of this range, then the original value in
+// the caller will be used. For this reason, returning 0 is used to signify to use the
+// original value as the default.
+//
+KOS_DLLEXPORT unsigned long kgsl_get_z160_memory_amount(void)
+{
+ return(0);
+}
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX35/memcfg/gsl_memcfg.h b/drivers/mxc/amd-gpu/platform/hal/MX35/memcfg/gsl_memcfg.h
new file mode 100644
index 000000000000..164a17c925c4
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX35/memcfg/gsl_memcfg.h
@@ -0,0 +1,41 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GSL_MEMCFG_H
+#define GSL_MEMCFG_H
+
+//
+// Return the maximum amount of memory that can be allocated to the Z430. This number
+// will be constrained to 2MB as a minimum and the original hardcoded value for the caller
+// as a maximum. If the return value is outside of this range, then the original value in
+// the caller will be used. For this reason, returning 0 is used to signify to use the
+// original value as the default.
+//
+KOS_DLLEXPORT unsigned long kgsl_get_z160_memory_amount(void);
+
+#endif
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX51/gsl_buildconfig.h b/drivers/mxc/amd-gpu/platform/hal/MX51/gsl_buildconfig.h
new file mode 100644
index 000000000000..82824f511d5e
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX51/gsl_buildconfig.h
@@ -0,0 +1,62 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __GSL__BUILDCONFIG_H
+#define __GSL__BUILDCONFIG_H
+
+#define GSL_BLD_YAMATO
+#define GSL_BLD_G12
+
+#define GSL_LOCKING_COURSEGRAIN
+
+#define GSL_STATS_MEM
+#define GSL_STATS_RINGBUFFER
+#define GSL_STATS_MMU
+
+#define GSL_RB_USE_MEM_RPTR
+#define GSL_RB_USE_MEM_TIMESTAMP
+#define GSL_RB_TIMESTAMP_INTERUPT
+//#define GSL_RB_USE_WPTR_POLLING
+
+#if defined(_WIN32_WCE) && (_WIN32_WCE >= 600)
+#define GSL_DEVICE_SHADOW_MEMSTORE_TO_USER
+#endif
+
+//#define GSL_MMU_TRANSLATION_ENABLED
+//#define GSL_MMU_PAGETABLE_PERPROCESS
+
+#define GSL_CALLER_PROCESS_MAX 10
+#define GSL_SHMEM_MAX_APERTURES 3
+
+#ifdef _WIN32
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+#endif // _WIN32
+
+#endif // __GSL__BUILDCONFIG_H
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX51/gsl_config.h b/drivers/mxc/amd-gpu/platform/hal/MX51/gsl_config.h
new file mode 100644
index 000000000000..6fad1d01277f
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX51/gsl_config.h
@@ -0,0 +1,222 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __GSL__CONFIG_H
+#define __GSL__CONFIG_H
+
+// ------------------------
+// Yamato ringbuffer config
+// ------------------------
+static const unsigned int gsl_cfg_rb_sizelog2quadwords = GSL_RB_SIZE_32K;
+static const unsigned int gsl_cfg_rb_blksizequadwords = GSL_RB_SIZE_16;
+
+// ------------------------
+// Yamato MH arbiter config
+// ------------------------
+static const mh_arbiter_config_t gsl_cfg_yamato_mharb =
+{
+ 0x10, // same_page_limit
+ 0, // same_page_granularity
+ 1, // l1_arb_enable
+ 1, // l1_arb_hold_enable
+ 0, // l2_arb_control
+ 1, // page_size
+ 1, // tc_reorder_enable
+ 1, // tc_arb_hold_enable
+ 1, // in_flight_limit_enable
+ 0x8, // in_flight_limit
+ 1, // cp_clnt_enable
+ 1, // vgt_clnt_enable
+ 1, // tc_clnt_enable
+ 1, // rb_clnt_enable
+ 1, // pa_clnt_enable
+};
+
+// ---------------------
+// G12 MH arbiter config
+// ---------------------
+static const REG_MH_ARBITER_CONFIG gsl_cfg_g12_mharb =
+{
+ 0x10, // SAME_PAGE_LIMIT
+ 0, // SAME_PAGE_GRANULARITY
+ 1, // L1_ARB_ENABLE
+ 1, // L1_ARB_HOLD_ENABLE
+ 0, // L2_ARB_CONTROL
+ 1, // PAGE_SIZE
+ 1, // TC_REORDER_ENABLE
+ 1, // TC_ARB_HOLD_ENABLE
+ 0, // IN_FLIGHT_LIMIT_ENABLE
+ 0x8, // IN_FLIGHT_LIMIT
+ 1, // CP_CLNT_ENABLE
+ 1, // VGT_CLNT_ENABLE
+ 1, // TC_CLNT_ENABLE
+ 1, // RB_CLNT_ENABLE
+ 1, // PA_CLNT_ENABLE
+};
+
+// -----------------------------
+// interrupt block register data
+// -----------------------------
+static const gsl_intrblock_reg_t gsl_cfg_intrblock_reg[GSL_INTR_BLOCK_COUNT] =
+{
+ { // Yamato MH
+ GSL_INTR_BLOCK_YDX_MH,
+ GSL_INTR_YDX_MH_AXI_READ_ERROR,
+ GSL_INTR_YDX_MH_MMU_PAGE_FAULT,
+ mmMH_INTERRUPT_STATUS,
+ mmMH_INTERRUPT_CLEAR,
+ mmMH_INTERRUPT_MASK
+ },
+ { // Yamato CP
+ GSL_INTR_BLOCK_YDX_CP,
+ GSL_INTR_YDX_CP_SW_INT,
+ GSL_INTR_YDX_CP_RING_BUFFER,
+ mmCP_INT_STATUS,
+ mmCP_INT_ACK,
+ mmCP_INT_CNTL
+ },
+ { // Yamato RBBM
+ GSL_INTR_BLOCK_YDX_RBBM,
+ GSL_INTR_YDX_RBBM_READ_ERROR,
+ GSL_INTR_YDX_RBBM_GUI_IDLE,
+ mmRBBM_INT_STATUS,
+ mmRBBM_INT_ACK,
+ mmRBBM_INT_CNTL
+ },
+ { // Yamato SQ
+ GSL_INTR_BLOCK_YDX_SQ,
+ GSL_INTR_YDX_SQ_PS_WATCHDOG,
+ GSL_INTR_YDX_SQ_VS_WATCHDOG,
+ mmSQ_INT_STATUS,
+ mmSQ_INT_ACK,
+ mmSQ_INT_CNTL
+ },
+ { // G12
+ GSL_INTR_BLOCK_G12,
+ GSL_INTR_G12_MH,
+#ifndef _Z180
+ GSL_INTR_G12_FBC,
+#else
+ GSL_INTR_G12_FIFO,
+#endif //_Z180
+ (ADDR_VGC_IRQSTATUS >> 2),
+ (ADDR_VGC_IRQSTATUS >> 2),
+ (ADDR_VGC_IRQENABLE >> 2)
+ },
+ { // G12 MH
+ GSL_INTR_BLOCK_G12_MH,
+ GSL_INTR_G12_MH_AXI_READ_ERROR,
+ GSL_INTR_G12_MH_MMU_PAGE_FAULT,
+ ADDR_MH_INTERRUPT_STATUS, // G12 MH offsets are considered to be dword based, therefore no down shift
+ ADDR_MH_INTERRUPT_CLEAR,
+ ADDR_MH_INTERRUPT_MASK
+ },
+};
+
+// -----------------------
+// interrupt mask bit data
+// -----------------------
+static const int gsl_cfg_intr_mask[GSL_INTR_COUNT] =
+{
+ MH_INTERRUPT_MASK__AXI_READ_ERROR,
+ MH_INTERRUPT_MASK__AXI_WRITE_ERROR,
+ MH_INTERRUPT_MASK__MMU_PAGE_FAULT,
+
+ CP_INT_CNTL__SW_INT_MASK,
+ CP_INT_CNTL__T0_PACKET_IN_IB_MASK,
+ CP_INT_CNTL__OPCODE_ERROR_MASK,
+ CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK,
+ CP_INT_CNTL__RESERVED_BIT_ERROR_MASK,
+ CP_INT_CNTL__IB_ERROR_MASK,
+ CP_INT_CNTL__IB2_INT_MASK,
+ CP_INT_CNTL__IB1_INT_MASK,
+ CP_INT_CNTL__RB_INT_MASK,
+
+ RBBM_INT_CNTL__RDERR_INT_MASK,
+ RBBM_INT_CNTL__DISPLAY_UPDATE_INT_MASK,
+ RBBM_INT_CNTL__GUI_IDLE_INT_MASK,
+
+ SQ_INT_CNTL__PS_WATCHDOG_MASK,
+ SQ_INT_CNTL__VS_WATCHDOG_MASK,
+
+ (1 << VGC_IRQENABLE_MH_FSHIFT),
+ (1 << VGC_IRQENABLE_G2D_FSHIFT),
+ (1 << VGC_IRQENABLE_FIFO_FSHIFT),
+#ifndef _Z180
+ (1 << VGC_IRQENABLE_FBC_FSHIFT),
+#endif
+ (1 << MH_INTERRUPT_MASK_AXI_READ_ERROR_FSHIFT),
+ (1 << MH_INTERRUPT_MASK_AXI_WRITE_ERROR_FSHIFT),
+ (1 << MH_INTERRUPT_MASK_MMU_PAGE_FAULT_FSHIFT),
+};
+
+// -----------------
+// mmu register data
+// -----------------
+static const gsl_mmu_reg_t gsl_cfg_mmu_reg[GSL_DEVICE_MAX] =
+{
+ { // Yamato
+ mmMH_MMU_CONFIG,
+ mmMH_MMU_MPU_BASE,
+ mmMH_MMU_MPU_END,
+ mmMH_MMU_VA_RANGE,
+ mmMH_MMU_PT_BASE,
+ mmMH_MMU_PAGE_FAULT,
+ mmMH_MMU_TRAN_ERROR,
+ mmMH_MMU_INVALIDATE,
+ },
+ { // G12 - MH offsets are considered to be dword based, therefore no down shift
+ ADDR_MH_MMU_CONFIG,
+ ADDR_MH_MMU_MPU_BASE,
+ ADDR_MH_MMU_MPU_END,
+ ADDR_MH_MMU_VA_RANGE,
+ ADDR_MH_MMU_PT_BASE,
+ ADDR_MH_MMU_PAGE_FAULT,
+ ADDR_MH_MMU_TRAN_ERROR,
+ ADDR_MH_MMU_INVALIDATE,
+ }
+};
+
+// -----------------
+// mh interrupt data
+// -----------------
+static const gsl_mh_intr_t gsl_cfg_mh_intr[GSL_DEVICE_MAX] =
+{
+ { // Yamato
+ GSL_INTR_YDX_MH_AXI_READ_ERROR,
+ GSL_INTR_YDX_MH_AXI_WRITE_ERROR,
+ GSL_INTR_YDX_MH_MMU_PAGE_FAULT,
+ },
+ { // G12
+ GSL_INTR_G12_MH_AXI_READ_ERROR,
+ GSL_INTR_G12_MH_AXI_WRITE_ERROR,
+ GSL_INTR_G12_MH_MMU_PAGE_FAULT,
+ }
+};
+
+#endif // __GSL__CONFIG_H
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX51/gsl_halconfig.h b/drivers/mxc/amd-gpu/platform/hal/MX51/gsl_halconfig.h
new file mode 100644
index 000000000000..589c56fa9bfa
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX51/gsl_halconfig.h
@@ -0,0 +1,58 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __GSL_HALCONFIG_H
+#define __GSL_HALCONFIG_H
+
+
+#define GSL_HAL_PLATFORM "i.MX51"
+
+#define GSL_HAL_GPUBASE_GMEM 0x00100000 // 1MB
+#define GSL_HAL_GPUBASE_GMEM_PHYS 0x20000000 // 1MB
+
+#define GSL_HAL_GPUBASE_REG_YDX 0x30000000
+#define GSL_HAL_GPUBASE_REG_G12 0xD0000000
+
+#define GSL_HAL_SIZE_REG_YDX 0x00020000 // 128KB
+#define GSL_HAL_SIZE_REG_G12 0x00001000 // 4KB
+#define GSL_HAL_SIZE_GMEM 0x00020000 // 128KB - 0 to 384KB in 128KB increments
+
+#if defined(GSL_MMU_TRANSLATION_ENABLED)
+#define GSL_HAL_SHMEM_SIZE_EMEM1 0x02400000 // 36MB
+#define GSL_HAL_SHMEM_SIZE_EMEM2 0x00400000 // 4MB
+#define GSL_HAL_SHMEM_SIZE_PHYS 0x00400000 // 4MB
+#else
+#define GSL_HAL_SHMEM_SIZE_EMEM1 0x00D00000 // 13MB
+#define GSL_HAL_SHMEM_SIZE_EMEM2 0x00200000 // 2MB
+#define GSL_HAL_SHMEM_SIZE_PHYS 0x00100000 // 1MB
+#endif
+
+#define MX51_G12_INTERRUPT 84 // Interrupt line taken from Reference Manual
+#define MX51_YDX_INTERRUPT 12 // Interrupt line taken from Reference Manual
+
+#endif // __GSL_HALCONFIG_H
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX51/linux/gsl_hal.c b/drivers/mxc/amd-gpu/platform/hal/MX51/linux/gsl_hal.c
new file mode 100644
index 000000000000..965416b59ec1
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX51/linux/gsl_hal.c
@@ -0,0 +1,598 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include "gsl_hal.h"
+#include "gsl_halconfig.h"
+#include "gsl_memcfg.h"
+#include "gsl_linux_map.h"
+
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+
+#include <asm/atomic.h>
+#include <asm/uaccess.h>
+#include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
+
+//////////////////////////////////////////////////////////////////////////////
+// constants
+//////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////////
+// defines
+//////////////////////////////////////////////////////////////////////////////
+
+#define GSL_HAL_MEM1 0
+#define GSL_HAL_MEM2 1
+#define GSL_HAL_MEM3 2
+
+//#define GSL_HAL_DEBUG
+
+//////////////////////////////////////////////////////////////////////////////
+// types
+//////////////////////////////////////////////////////////////////////////////
+
+typedef struct _gsl_hal_t {
+ gsl_memregion_t z160_regspace;
+ gsl_memregion_t z430_regspace;
+ gsl_memregion_t memchunk;
+ gsl_memregion_t memspace[GSL_SHMEM_MAX_APERTURES];
+} gsl_hal_t;
+
+extern phys_addr_t gpu_2d_regbase;
+extern int gpu_2d_regsize;
+extern phys_addr_t gpu_3d_regbase;
+extern int gpu_3d_regsize;
+extern int gmem_size;
+extern phys_addr_t gpu_reserved_mem;
+extern int gpu_reserved_mem_size;
+
+//////////////////////////////////////////////////////////////////////////////
+// functions
+//////////////////////////////////////////////////////////////////////////////
+
+KGSLHAL_API int
+kgsl_hal_allocphysical(unsigned int virtaddr, unsigned int numpages, unsigned int scattergatterlist[])
+{
+ //
+ // allocate physically contiguous memory
+ //
+
+ int i;
+ void *va;
+
+ va = gsl_linux_map_alloc(virtaddr, numpages*PAGE_SIZE);
+
+ if (!va)
+ return (GSL_FAILURE_OUTOFMEM);
+
+ for(i = 0; i < numpages; i++)
+ {
+ scattergatterlist[i] = page_to_phys(vmalloc_to_page(va));
+ va += PAGE_SIZE;
+ }
+
+ return (GSL_SUCCESS);
+}
+
+// ---------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_freephysical(unsigned int virtaddr, unsigned int numpages, unsigned int scattergatterlist[])
+{
+ //
+ // free physical memory
+ //
+
+ gsl_linux_map_free(virtaddr);
+
+ return(GSL_SUCCESS);
+}
+
+//----------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_init(void)
+{
+ gsl_hal_t *hal;
+ unsigned long totalsize, mem1size;
+ unsigned int va, pa;
+
+ if (gsl_driver.hal)
+ {
+ return (GSL_FAILURE_ALREADYINITIALIZED);
+ }
+
+ gsl_driver.hal = (void *)kos_malloc(sizeof(gsl_hal_t));
+
+ if (!gsl_driver.hal)
+ {
+ return (GSL_FAILURE_OUTOFMEM);
+ }
+
+ kos_memset(gsl_driver.hal, 0, sizeof(gsl_hal_t));
+
+
+ // overlay structure on hal memory
+ hal = (gsl_hal_t *) gsl_driver.hal;
+
+ // setup register space
+ if(gpu_3d_regbase && gpu_3d_regsize){
+ hal->z430_regspace.mmio_phys_base = gpu_3d_regbase;
+ hal->z430_regspace.sizebytes = gpu_3d_regsize;
+ }else{
+ hal->z430_regspace.mmio_phys_base = GSL_HAL_GPUBASE_REG_YDX;
+ hal->z430_regspace.sizebytes = GSL_HAL_SIZE_REG_YDX;
+ }
+ hal->z430_regspace.mmio_virt_base = (unsigned char*)ioremap(hal->z430_regspace.mmio_phys_base, hal->z430_regspace.sizebytes);
+
+ if (hal->z430_regspace.mmio_virt_base == NULL)
+ {
+ return (GSL_FAILURE_SYSTEMERROR);
+ }
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->z430_regspace.mmio_phys_base = 0x%p\n", __func__, (void*)hal->z430_regspace.mmio_phys_base);
+ printk(KERN_INFO "%s: hal->z430_regspace.mmio_virt_base = 0x%p\n", __func__, (void*)hal->z430_regspace.mmio_virt_base);
+ printk(KERN_INFO "%s: hal->z430_regspace.sizebytes = 0x%08x\n", __func__, hal->z430_regspace.sizebytes);
+#endif
+
+ if(gpu_2d_regbase && gpu_2d_regsize){
+ hal->z160_regspace.mmio_phys_base = gpu_2d_regbase;
+ hal->z160_regspace.sizebytes = gpu_2d_regsize;
+ }else{
+ hal->z160_regspace.mmio_phys_base = GSL_HAL_GPUBASE_REG_G12;
+ hal->z160_regspace.sizebytes = GSL_HAL_SIZE_REG_G12;
+ }
+ hal->z160_regspace.mmio_virt_base = (unsigned char*)ioremap(hal->z160_regspace.mmio_phys_base, hal->z160_regspace.sizebytes);
+
+ if (hal->z160_regspace.mmio_virt_base == NULL)
+ {
+ return (GSL_FAILURE_SYSTEMERROR);
+ }
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->z160_regspace.mmio_phys_base = 0x%p\n", __func__, (void*)hal->z160_regspace.mmio_phys_base);
+ printk(KERN_INFO "%s: hal->z160_regspace.mmio_virt_base = 0x%p\n", __func__, (void*)hal->z160_regspace.mmio_virt_base);
+ printk(KERN_INFO "%s: hal->z160_regspace.sizebytes = 0x%08x\n", __func__, hal->z160_regspace.sizebytes);
+#endif
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ totalsize = GSL_HAL_SHMEM_SIZE_EMEM2 + GSL_HAL_SHMEM_SIZE_PHYS;
+ mem1size = GSL_HAL_SHMEM_SIZE_EMEM1;
+ if (gpu_reserved_mem && gpu_reserved_mem_size >= totalsize)
+ {
+ pa = gpu_reserved_mem;
+ va = (unsigned int)ioremap(gpu_reserved_mem, totalsize);
+ }
+ else
+ {
+ va = (unsigned int)dma_alloc_coherent(0, totalsize, (dma_addr_t *)&pa, GFP_DMA | GFP_KERNEL);
+ }
+#else
+ if(gpu_reserved_mem && gpu_reserved_mem_size >= SZ_8M){
+ totalsize = gpu_reserved_mem_size;
+ pa = gpu_reserved_mem;
+ va = (unsigned int)ioremap(gpu_reserved_mem, gpu_reserved_mem_size);
+ }else{
+ gpu_reserved_mem = 0;
+ totalsize = GSL_HAL_SHMEM_SIZE_EMEM1 + GSL_HAL_SHMEM_SIZE_EMEM2 + GSL_HAL_SHMEM_SIZE_PHYS;
+ va = (unsigned int)dma_alloc_coherent(0, totalsize, (dma_addr_t *)&pa, GFP_DMA | GFP_KERNEL);
+ }
+ mem1size = totalsize - (GSL_HAL_SHMEM_SIZE_EMEM2 + GSL_HAL_SHMEM_SIZE_PHYS);
+#endif
+
+ if (va)
+ {
+ kos_memset((void *)va, 0, totalsize);
+
+ hal->memchunk.mmio_virt_base = (void *)va;
+ hal->memchunk.mmio_phys_base = pa;
+ hal->memchunk.sizebytes = totalsize;
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->memchunk.mmio_phys_base = 0x%p\n", __func__, (void*)hal->memchunk.mmio_phys_base);
+ printk(KERN_INFO "%s: hal->memchunk.mmio_virt_base = 0x%p\n", __func__, (void*)hal->memchunk.mmio_virt_base);
+ printk(KERN_INFO "%s: hal->memchunk.sizebytes = 0x%08x\n", __func__, hal->memchunk.sizebytes);
+#endif
+
+ hal->memspace[GSL_HAL_MEM2].mmio_virt_base = (void *) va;
+ hal->memspace[GSL_HAL_MEM2].gpu_base = pa;
+ hal->memspace[GSL_HAL_MEM2].sizebytes = GSL_HAL_SHMEM_SIZE_EMEM2;
+ va += GSL_HAL_SHMEM_SIZE_EMEM2;
+ pa += GSL_HAL_SHMEM_SIZE_EMEM2;
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM2].gpu_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM2].gpu_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM2].mmio_virt_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM2].mmio_virt_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM2].sizebytes = 0x%08x\n", __func__, hal->memspace[GSL_HAL_MEM2].sizebytes);
+#endif
+
+ hal->memspace[GSL_HAL_MEM3].mmio_virt_base = (void *) va;
+ hal->memspace[GSL_HAL_MEM3].gpu_base = pa;
+ hal->memspace[GSL_HAL_MEM3].sizebytes = GSL_HAL_SHMEM_SIZE_PHYS;
+ va += GSL_HAL_SHMEM_SIZE_PHYS;
+ pa += GSL_HAL_SHMEM_SIZE_PHYS;
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM3].gpu_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM3].gpu_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM3].mmio_virt_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM3].mmio_virt_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM3].sizebytes = 0x%08x\n", __func__, hal->memspace[GSL_HAL_MEM3].sizebytes);
+#endif
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ gsl_linux_map_init();
+ hal->memspace[GSL_HAL_MEM1].mmio_virt_base = (void *)GSL_LINUX_MAP_RANGE_START;
+ hal->memspace[GSL_HAL_MEM1].gpu_base = GSL_LINUX_MAP_RANGE_START;
+ hal->memspace[GSL_HAL_MEM1].sizebytes = mem1size;
+#else
+ hal->memspace[GSL_HAL_MEM1].mmio_virt_base = (void *) va;
+ hal->memspace[GSL_HAL_MEM1].gpu_base = pa;
+ hal->memspace[GSL_HAL_MEM1].sizebytes = mem1size;
+#endif
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM1].gpu_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM1].gpu_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM1].mmio_virt_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM1].mmio_virt_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM1].sizebytes = 0x%08x\n", __func__, hal->memspace[GSL_HAL_MEM1].sizebytes);
+#endif
+ }
+ else
+ {
+ kgsl_hal_close();
+ return (GSL_FAILURE_SYSTEMERROR);
+ }
+
+ return GSL_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_close(void)
+{
+ gsl_hal_t *hal;
+
+ if (gsl_driver.hal)
+ {
+ // overlay structure on hal memory
+ hal = (gsl_hal_t *) gsl_driver.hal;
+
+ // unmap registers
+ if (hal->z430_regspace.mmio_virt_base)
+ {
+ iounmap(hal->z430_regspace.mmio_virt_base);
+ }
+ if (hal->z160_regspace.mmio_virt_base)
+ {
+ iounmap(hal->z160_regspace.mmio_virt_base);
+ }
+
+ // free physical block
+ if (hal->memchunk.mmio_virt_base && gpu_reserved_mem)
+ {
+ iounmap(hal->memchunk.mmio_virt_base);
+ }
+ else
+ {
+ dma_free_coherent(0, hal->memchunk.sizebytes, hal->memchunk.mmio_virt_base, hal->memchunk.mmio_phys_base);
+ }
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ gsl_linux_map_destroy();
+#endif
+
+ // release hal struct
+ kos_memset(hal, 0, sizeof(gsl_hal_t));
+ kos_free(gsl_driver.hal);
+ gsl_driver.hal = NULL;
+ }
+
+ return (GSL_SUCCESS);
+}
+
+//----------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_getshmemconfig(gsl_shmemconfig_t *config)
+{
+ int status = GSL_FAILURE_DEVICEERROR;
+ gsl_hal_t *hal = (gsl_hal_t *) gsl_driver.hal;
+
+ kos_memset(config, 0, sizeof(gsl_shmemconfig_t));
+
+ if (hal)
+ {
+ config->numapertures = GSL_SHMEM_MAX_APERTURES;
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ config->apertures[0].id = GSL_APERTURE_MMU;
+#else
+ config->apertures[0].id = GSL_APERTURE_EMEM;
+#endif
+ config->apertures[0].channel = GSL_CHANNEL_1;
+ config->apertures[0].hostbase = (unsigned int)hal->memspace[GSL_HAL_MEM1].mmio_virt_base;
+ config->apertures[0].gpubase = hal->memspace[GSL_HAL_MEM1].gpu_base;
+ config->apertures[0].sizebytes = hal->memspace[GSL_HAL_MEM1].sizebytes;
+
+ config->apertures[1].id = GSL_APERTURE_EMEM;
+ config->apertures[1].channel = GSL_CHANNEL_2;
+ config->apertures[1].hostbase = (unsigned int)hal->memspace[GSL_HAL_MEM2].mmio_virt_base;
+ config->apertures[1].gpubase = hal->memspace[GSL_HAL_MEM2].gpu_base;
+ config->apertures[1].sizebytes = hal->memspace[GSL_HAL_MEM2].sizebytes;
+
+ config->apertures[2].id = GSL_APERTURE_PHYS;
+ config->apertures[2].channel = GSL_CHANNEL_1;
+ config->apertures[2].hostbase = (unsigned int)hal->memspace[GSL_HAL_MEM3].mmio_virt_base;
+ config->apertures[2].gpubase = hal->memspace[GSL_HAL_MEM3].gpu_base;
+ config->apertures[2].sizebytes = hal->memspace[GSL_HAL_MEM3].sizebytes;
+
+ status = GSL_SUCCESS;
+ }
+
+ return (status);
+}
+
+//----------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_getdevconfig(gsl_deviceid_t device_id, gsl_devconfig_t *config)
+{
+ int status = GSL_FAILURE_DEVICEERROR;
+ gsl_hal_t *hal = (gsl_hal_t *) gsl_driver.hal;
+
+ kos_memset(config, 0, sizeof(gsl_devconfig_t));
+
+ if (hal)
+ {
+ switch (device_id)
+ {
+ case GSL_DEVICE_YAMATO:
+ {
+ mh_mmu_config_u mmu_config = {0};
+
+ config->gmemspace.gpu_base = 0;
+ config->gmemspace.mmio_virt_base = 0;
+ config->gmemspace.mmio_phys_base = 0;
+ if(gmem_size){
+ config->gmemspace.sizebytes = gmem_size;
+ }else{
+ config->gmemspace.sizebytes = GSL_HAL_SIZE_GMEM;
+ }
+
+ config->regspace.gpu_base = 0;
+ config->regspace.mmio_virt_base = (unsigned char *)hal->z430_regspace.mmio_virt_base;
+ config->regspace.mmio_phys_base = (unsigned int) hal->z430_regspace.mmio_phys_base;
+ config->regspace.sizebytes = GSL_HAL_SIZE_REG_YDX;
+
+ mmu_config.f.mmu_enable = 1;
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ mmu_config.f.split_mode_enable = 0;
+ mmu_config.f.rb_w_clnt_behavior = 1;
+ mmu_config.f.cp_w_clnt_behavior = 1;
+ mmu_config.f.cp_r0_clnt_behavior = 1;
+ mmu_config.f.cp_r1_clnt_behavior = 1;
+ mmu_config.f.cp_r2_clnt_behavior = 1;
+ mmu_config.f.cp_r3_clnt_behavior = 1;
+ mmu_config.f.cp_r4_clnt_behavior = 1;
+ mmu_config.f.vgt_r0_clnt_behavior = 1;
+ mmu_config.f.vgt_r1_clnt_behavior = 1;
+ mmu_config.f.tc_r_clnt_behavior = 1;
+ mmu_config.f.pa_w_clnt_behavior = 1;
+#endif // GSL_MMU_TRANSLATION_ENABLED
+
+ config->mmu_config = mmu_config.val;
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ config->va_base = hal->memspace[GSL_HAL_MEM1].gpu_base;
+ config->va_range = hal->memspace[GSL_HAL_MEM1].sizebytes;
+#else
+ config->va_base = 0x00000000;
+ config->va_range = 0x00000000;
+#endif // GSL_MMU_TRANSLATION_ENABLED
+
+ // turn off memory protection unit by setting acceptable physical address range to include all pages
+ config->mpu_base = 0x00000000; // hal->memchunk.mmio_virt_base;
+ config->mpu_range = 0xFFFFF000; // hal->memchunk.sizebytes;
+
+ status = GSL_SUCCESS;
+ break;
+ }
+
+ case GSL_DEVICE_G12:
+ {
+ mh_mmu_config_u mmu_config = {0};
+
+ config->regspace.gpu_base = 0;
+ config->regspace.mmio_virt_base = (unsigned char *)hal->z160_regspace.mmio_virt_base;
+ config->regspace.mmio_phys_base = (unsigned int) hal->z160_regspace.mmio_phys_base;
+ config->regspace.sizebytes = GSL_HAL_SIZE_REG_G12;
+
+ mmu_config.f.mmu_enable = 1;
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ config->mmu_config = 0x00555551;
+ config->va_base = hal->memspace[GSL_HAL_MEM1].gpu_base;
+ config->va_range = hal->memspace[GSL_HAL_MEM1].sizebytes;
+#else
+ config->mmu_config = mmu_config.val;
+ config->va_base = 0x00000000;
+ config->va_range = 0x00000000;
+#endif // GSL_MMU_TRANSLATION_ENABLED
+
+ config->mpu_base = 0x00000000; //(unsigned int) hal->memchunk.mmio_virt_base;
+ config->mpu_range = 0xFFFFF000; //hal->memchunk.sizebytes;
+
+ status = GSL_SUCCESS;
+ break;
+ }
+
+ default:
+
+ break;
+ }
+ }
+
+ return (status);
+}
+
+//----------------------------------------------------------------------------
+//
+// kgsl_hal_getchipid
+//
+// The proper platform method, build from RBBM_PERIPHIDx and RBBM_PATCH_RELEASE
+//
+KGSLHAL_API gsl_chipid_t
+kgsl_hal_getchipid(gsl_deviceid_t device_id)
+{
+ gsl_device_t *device = &gsl_driver.device[device_id-1];
+ gsl_chipid_t chipid;
+ unsigned int coreid, majorid, minorid, patchid, revid;
+
+ // YDX
+ device->ftbl.device_regread(device, mmRBBM_PERIPHID1, &coreid);
+ coreid &= 0xF;
+
+ // 2.
+ device->ftbl.device_regread(device, mmRBBM_PERIPHID2, &majorid);
+ majorid = (majorid >> 4) & 0xF;
+
+ device->ftbl.device_regread(device, mmRBBM_PATCH_RELEASE, &revid);
+
+ // 2.
+ minorid = ((revid >> 0) & 0xFF); // this is a 16bit field, but extremely unlikely it would ever get this high
+
+ // 1
+ patchid = ((revid >> 16) & 0xFF);
+
+ chipid = ((coreid << 24) | (majorid << 16) | (minorid << 8) | (patchid << 0));
+
+ return (chipid);
+}
+
+//----------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_getplatformtype(char *platform)
+{
+ if (gsl_driver.hal)
+ {
+ kos_strcpy(platform, GSL_HAL_PLATFORM);
+ return (GSL_SUCCESS);
+ }
+ else
+ {
+ return (GSL_FAILURE_NOTINITIALIZED);
+ }
+}
+
+//---------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_setpowerstate(gsl_deviceid_t device_id, int state, unsigned int value)
+{
+ gsl_device_t *device = &gsl_driver.device[device_id-1];
+ struct clk *gpu_clk = 0;
+ struct clk *garb_clk = clk_get(0, "garb_clk");
+ struct clk *emi_garb_clk = clk_get(0, "emi_garb_clk");
+
+ // unreferenced formal parameters
+ (void) value;
+
+ switch (device_id)
+ {
+ case GSL_DEVICE_G12:
+ gpu_clk = clk_get(0, "gpu2d_clk");
+ break;
+ case GSL_DEVICE_YAMATO:
+ gpu_clk = clk_get(0, "gpu3d_clk");
+ break;
+ default:
+ return (GSL_FAILURE_DEVICEERROR);
+ }
+
+ if (!gpu_clk)
+ return (GSL_FAILURE_DEVICEERROR);
+
+ switch (state)
+ {
+ case GSL_PWRFLAGS_CLK_ON:
+ break;
+ case GSL_PWRFLAGS_POWER_ON:
+ clk_enable(gpu_clk);
+ clk_enable(garb_clk);
+ clk_enable(emi_garb_clk);
+ kgsl_device_autogate_init(&gsl_driver.device[device_id-1]);
+ break;
+ case GSL_PWRFLAGS_CLK_OFF:
+ break;
+ case GSL_PWRFLAGS_POWER_OFF:
+ if (device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT) != GSL_SUCCESS)
+ {
+ return (GSL_FAILURE_DEVICEERROR);
+ }
+ kgsl_device_autogate_exit(&gsl_driver.device[device_id-1]);
+ clk_disable(gpu_clk);
+ clk_disable(garb_clk);
+ clk_disable(emi_garb_clk);
+ break;
+ default:
+ break;
+ }
+
+ return (GSL_SUCCESS);
+}
+
+KGSLHAL_API int kgsl_clock(gsl_deviceid_t dev, int enable)
+{
+ struct clk *gpu_clk;
+ struct clk *garb_clk = clk_get(0, "garb_clk");
+ struct clk *emi_garb_clk = clk_get(0, "emi_garb_clk");
+
+ switch (dev)
+ {
+ case GSL_DEVICE_G12:
+ gpu_clk = clk_get(0, "gpu2d_clk");
+ break;
+ case GSL_DEVICE_YAMATO:
+ gpu_clk = clk_get(0, "gpu3d_clk");
+ break;
+ default:
+ printk(KERN_ERR "GPU device %d is invalid!\n", dev);
+ return (GSL_FAILURE_DEVICEERROR);
+ }
+
+ if (IS_ERR(gpu_clk)) {
+ printk(KERN_ERR "%s: GPU clock get failed!\n", __func__);
+ return (GSL_FAILURE_DEVICEERROR);
+ }
+
+ if (enable) {
+ clk_enable(gpu_clk);
+ clk_enable(garb_clk);
+ clk_enable(emi_garb_clk);
+ } else {
+ clk_disable(gpu_clk);
+ clk_disable(garb_clk);
+ clk_disable(emi_garb_clk);
+ }
+
+ return (GSL_SUCCESS);
+}
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX51/memcfg/gsl_memcfg.c b/drivers/mxc/amd-gpu/platform/hal/MX51/memcfg/gsl_memcfg.c
new file mode 100644
index 000000000000..93fab327a830
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX51/memcfg/gsl_memcfg.c
@@ -0,0 +1,31 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include "kos_libapi.h"
+
+//
+// Return the maximum amount of memory that can be allocated to the Z430. This number
+// will be constrained to 2MB as a minimum and the original hardcoded value for the caller
+// as a maximum. If the return value is outside of this range, then the original value in
+// the caller will be used. For this reason, returning 0 is used to signify to use the
+// original value as the default.
+//
+KOS_DLLEXPORT unsigned long kgsl_get_z430_memory_amount(void)
+{
+ return(0);
+}
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX51/memcfg/gsl_memcfg.h b/drivers/mxc/amd-gpu/platform/hal/MX51/memcfg/gsl_memcfg.h
new file mode 100644
index 000000000000..e68387f1609a
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX51/memcfg/gsl_memcfg.h
@@ -0,0 +1,40 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GSL_MEMCFG_H
+#define GSL_MEMCFG_H
+
+//
+// Return the maximum amount of memory that can be allocated to the Z430. This number
+// will be constrained to 2MB as a minimum and the original hardcoded value for the caller
+// as a maximum. If the return value is outside of this range, then the original value in
+// the caller will be used. For this reason, returning 0 is used to signify to use the
+// original value as the default.
+//
+KOS_DLLEXPORT unsigned long kgsl_get_z430_memory_amount(void);
+#endif
diff --git a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_hwaccess.h b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_hwaccess.h
new file mode 100644
index 000000000000..65eadb1e79cf
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_hwaccess.h
@@ -0,0 +1,155 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __GSL_HWACCESS_LINUX_H
+#define __GSL_HWACCESS_LINUX_H
+
+#ifdef _LINUX
+#include "gsl_linux_map.h"
+#endif
+
+#include <linux/io.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+OSINLINE void
+kgsl_hwaccess_memread(void *dst, unsigned int gpubase, unsigned int gpuoffset, unsigned int sizebytes, unsigned int touserspace)
+{
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ if(gpubase >= GSL_LINUX_MAP_RANGE_START && gpubase < GSL_LINUX_MAP_RANGE_END)
+ {
+ gsl_linux_map_read(dst, gpubase+gpuoffset, sizebytes, touserspace);
+ }
+ else
+#endif
+ {
+ mb();
+ dsb();
+ if (touserspace)
+ {
+ if (copy_to_user(dst, (void *)(gpubase + gpuoffset), sizebytes))
+ {
+ return;
+ }
+ }
+ else
+ {
+ kos_memcpy(dst, (void *) (gpubase + gpuoffset), sizebytes);
+ }
+ mb();
+ dsb();
+ }
+}
+
+//----------------------------------------------------------------------------
+
+OSINLINE void
+kgsl_hwaccess_memwrite(unsigned int gpubase, unsigned int gpuoffset, void *src, unsigned int sizebytes, unsigned int fromuserspace)
+{
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ if(gpubase >= GSL_LINUX_MAP_RANGE_START && gpubase < GSL_LINUX_MAP_RANGE_END)
+ {
+ gsl_linux_map_write(src, gpubase+gpuoffset, sizebytes, fromuserspace);
+ }
+ else
+#endif
+ {
+ mb();
+ dsb();
+ if (fromuserspace)
+ {
+ if (copy_from_user((void *)(gpubase + gpuoffset), src, sizebytes))
+ {
+ return;
+ }
+ }
+ else
+ {
+ kos_memcpy((void *)(gpubase + gpuoffset), src, sizebytes);
+ }
+ mb();
+ dsb();
+ }
+}
+
+//----------------------------------------------------------------------------
+
+OSINLINE void
+kgsl_hwaccess_memset(unsigned int gpubase, unsigned int gpuoffset, unsigned int value, unsigned int sizebytes)
+{
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ if(gpubase >= GSL_LINUX_MAP_RANGE_START && gpubase < GSL_LINUX_MAP_RANGE_END)
+ gsl_linux_map_set(gpuoffset+gpubase, value, sizebytes);
+ else
+#endif
+ {
+ mb();
+ dsb();
+ kos_memset((void *)(gpubase + gpuoffset), value, sizebytes);
+ mb();
+ dsb();
+ }
+}
+
+//----------------------------------------------------------------------------
+
+OSINLINE void
+kgsl_hwaccess_regread(gsl_deviceid_t device_id, unsigned int gpubase, unsigned int offsetwords, unsigned int *data)
+{
+ unsigned int *reg;
+
+ // unreferenced formal parameter
+ (void) device_id;
+
+ reg = (unsigned int *)(gpubase + (offsetwords << 2));
+
+ mb();
+ dsb();
+ *data = __raw_readl(reg);
+ mb();
+ dsb();
+}
+
+//----------------------------------------------------------------------------
+
+OSINLINE void
+kgsl_hwaccess_regwrite(gsl_deviceid_t device_id, unsigned int gpubase, unsigned int offsetwords, unsigned int data)
+{
+ unsigned int *reg;
+
+ // unreferenced formal parameter
+ (void) device_id;
+
+ reg = (unsigned int *)(gpubase + (offsetwords << 2));
+ mb();
+ dsb();
+ __raw_writel(data, reg);
+ mb();
+ dsb();
+}
+#endif // __GSL_HWACCESS_WINCE_MX51_H
diff --git a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod.c b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod.c
new file mode 100644
index 000000000000..30f783e1cf12
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod.c
@@ -0,0 +1,973 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include "gsl_types.h"
+#include "gsl.h"
+#include "gsl_buildconfig.h"
+#include "gsl_halconfig.h"
+#include "gsl_ioctl.h"
+#include "gsl_kmod_cleanup.h"
+#include "gsl_linux_map.h"
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <asm/uaccess.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/cdev.h>
+
+#include <linux/platform_device.h>
+#include <linux/vmalloc.h>
+
+static int gpu_2d_irq, gpu_3d_irq;
+
+phys_addr_t gpu_2d_regbase;
+int gpu_2d_regsize;
+phys_addr_t gpu_3d_regbase;
+int gpu_3d_regsize;
+int gmem_size;
+phys_addr_t gpu_reserved_mem;
+int gpu_reserved_mem_size;
+
+static ssize_t gsl_kmod_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr);
+static ssize_t gsl_kmod_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr);
+static int gsl_kmod_ioctl(struct inode *inode, struct file *fd, unsigned int cmd, unsigned long arg);
+static int gsl_kmod_mmap(struct file *fd, struct vm_area_struct *vma);
+static int gsl_kmod_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
+static int gsl_kmod_open(struct inode *inode, struct file *fd);
+static int gsl_kmod_release(struct inode *inode, struct file *fd);
+static irqreturn_t z160_irq_handler(int irq, void *dev_id);
+#if defined(MX51)
+static irqreturn_t z430_irq_handler(int irq, void *dev_id);
+#endif
+
+static int gsl_kmod_major;
+static struct class *gsl_kmod_class;
+DEFINE_MUTEX(gsl_mutex);
+
+static const struct file_operations gsl_kmod_fops =
+{
+ .owner = THIS_MODULE,
+ .read = gsl_kmod_read,
+ .write = gsl_kmod_write,
+ .ioctl = gsl_kmod_ioctl,
+ .mmap = gsl_kmod_mmap,
+ .open = gsl_kmod_open,
+ .release = gsl_kmod_release
+};
+
+static struct vm_operations_struct gsl_kmod_vmops =
+{
+ .fault = gsl_kmod_fault,
+};
+
+static ssize_t gsl_kmod_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
+{
+ return 0;
+}
+
+static ssize_t gsl_kmod_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+{
+ return 0;
+}
+
+static int gsl_kmod_ioctl(struct inode *inode, struct file *fd, unsigned int cmd, unsigned long arg)
+{
+ int kgslStatus = GSL_FAILURE;
+
+ switch (cmd) {
+ case IOCTL_KGSL_DEVICE_START:
+ {
+ kgsl_device_start_t param;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_device_start_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = kgsl_device_start(param.device_id, param.flags);
+ break;
+ }
+ case IOCTL_KGSL_DEVICE_STOP:
+ {
+ kgsl_device_stop_t param;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_device_stop_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = kgsl_device_stop(param.device_id);
+ break;
+ }
+ case IOCTL_KGSL_DEVICE_IDLE:
+ {
+ kgsl_device_idle_t param;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_device_idle_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = kgsl_device_idle(param.device_id, param.timeout);
+ break;
+ }
+ case IOCTL_KGSL_DEVICE_GETPROPERTY:
+ {
+ kgsl_device_getproperty_t param;
+ void *tmp;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_device_getproperty_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ tmp = kmalloc(param.sizebytes, GFP_KERNEL);
+ if (!tmp)
+ {
+ printk(KERN_ERR "%s:kmalloc error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = kgsl_device_getproperty(param.device_id, param.type, tmp, param.sizebytes);
+ if (kgslStatus == GSL_SUCCESS)
+ {
+ if (copy_to_user(param.value, tmp, param.sizebytes))
+ {
+ printk(KERN_ERR "%s: copy_to_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ kfree(tmp);
+ break;
+ }
+ }
+ else
+ {
+ printk(KERN_ERR "%s: kgsl_device_getproperty error\n", __func__);
+ }
+ kfree(tmp);
+ break;
+ }
+ case IOCTL_KGSL_DEVICE_SETPROPERTY:
+ {
+ kgsl_device_setproperty_t param;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_device_setproperty_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = kgsl_device_setproperty(param.device_id, param.type, param.value, param.sizebytes);
+ if (kgslStatus != GSL_SUCCESS)
+ {
+ printk(KERN_ERR "%s: kgsl_device_setproperty error\n", __func__);
+ }
+ break;
+ }
+ case IOCTL_KGSL_DEVICE_REGREAD:
+ {
+ kgsl_device_regread_t param;
+ unsigned int tmp;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_device_regread_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = kgsl_device_regread(param.device_id, param.offsetwords, &tmp);
+ if (kgslStatus == GSL_SUCCESS)
+ {
+ if (copy_to_user(param.value, &tmp, sizeof(unsigned int)))
+ {
+ printk(KERN_ERR "%s: copy_to_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ }
+ break;
+ }
+ case IOCTL_KGSL_DEVICE_REGWRITE:
+ {
+ kgsl_device_regwrite_t param;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_device_regwrite_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = kgsl_device_regwrite(param.device_id, param.offsetwords, param.value);
+ break;
+ }
+ case IOCTL_KGSL_DEVICE_WAITIRQ:
+ {
+ kgsl_device_waitirq_t param;
+ unsigned int count;
+
+ printk(KERN_ERR "IOCTL_KGSL_DEVICE_WAITIRQ obsoleted!\n");
+// kgslStatus = -ENOTTY; break;
+
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_device_waitirq_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = kgsl_device_waitirq(param.device_id, param.intr_id, &count, param.timeout);
+ if (kgslStatus == GSL_SUCCESS)
+ {
+ if (copy_to_user(param.count, &count, sizeof(unsigned int)))
+ {
+ printk(KERN_ERR "%s: copy_to_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ }
+ break;
+ }
+ case IOCTL_KGSL_CMDSTREAM_ISSUEIBCMDS:
+ {
+ kgsl_cmdstream_issueibcmds_t param;
+ gsl_timestamp_t tmp;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_cmdstream_issueibcmds_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = kgsl_cmdstream_issueibcmds(param.device_id, param.drawctxt_index, param.ibaddr, param.sizedwords, &tmp, param.flags);
+ if (kgslStatus == GSL_SUCCESS)
+ {
+ if (copy_to_user(param.timestamp, &tmp, sizeof(gsl_timestamp_t)))
+ {
+ printk(KERN_ERR "%s: copy_to_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ }
+ break;
+ }
+ case IOCTL_KGSL_CMDSTREAM_READTIMESTAMP:
+ {
+ kgsl_cmdstream_readtimestamp_t param;
+ gsl_timestamp_t tmp;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_cmdstream_readtimestamp_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ tmp = kgsl_cmdstream_readtimestamp(param.device_id, param.type);
+ if (copy_to_user(param.timestamp, &tmp, sizeof(gsl_timestamp_t)))
+ {
+ printk(KERN_ERR "%s: copy_to_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = GSL_SUCCESS;
+ break;
+ }
+ case IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP:
+ {
+ int err;
+ kgsl_cmdstream_freememontimestamp_t param;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_cmdstream_freememontimestamp_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ err = del_memblock_from_allocated_list(fd, param.memdesc);
+ if(err)
+ {
+ /* tried to remove a block of memory that is not allocated!
+ * NOTE that -EINVAL is Linux kernel's error codes!
+ * the drivers error codes COULD mix up with kernel's. */
+ kgslStatus = -EINVAL;
+ }
+ else
+ {
+ kgslStatus = kgsl_cmdstream_freememontimestamp(param.device_id,
+ param.memdesc,
+ param.timestamp,
+ param.type);
+ }
+ break;
+ }
+ case IOCTL_KGSL_CMDSTREAM_WAITTIMESTAMP:
+ {
+ kgsl_cmdstream_waittimestamp_t param;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_cmdstream_waittimestamp_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = kgsl_cmdstream_waittimestamp(param.device_id, param.timestamp, param.timeout);
+ break;
+ }
+ case IOCTL_KGSL_CMDWINDOW_WRITE:
+ {
+ kgsl_cmdwindow_write_t param;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_cmdwindow_write_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = kgsl_cmdwindow_write(param.device_id, param.target, param.addr, param.data);
+ break;
+ }
+ case IOCTL_KGSL_CONTEXT_CREATE:
+ {
+ kgsl_context_create_t param;
+ unsigned int tmp;
+ int tmpStatus;
+
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_context_create_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = kgsl_context_create(param.device_id, param.type, &tmp, param.flags);
+ if (kgslStatus == GSL_SUCCESS)
+ {
+ if (copy_to_user(param.drawctxt_id, &tmp, sizeof(unsigned int)))
+ {
+ tmpStatus = kgsl_context_destroy(param.device_id, tmp);
+ /* is asserting ok? Basicly we should return the error from copy_to_user
+ * but will the user space interpret it correctly? Will the user space
+ * always check against GSL_SUCCESS or GSL_FAILURE as they are not the only
+ * return values.
+ */
+ KOS_ASSERT(tmpStatus == GSL_SUCCESS);
+ printk(KERN_ERR "%s: copy_to_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ else
+ {
+ add_device_context_to_array(fd, param.device_id, tmp);
+ }
+ }
+ break;
+ }
+ case IOCTL_KGSL_CONTEXT_DESTROY:
+ {
+ kgsl_context_destroy_t param;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_context_destroy_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = kgsl_context_destroy(param.device_id, param.drawctxt_id);
+ del_device_context_from_array(fd, param.device_id, param.drawctxt_id);
+ break;
+ }
+ case IOCTL_KGSL_DRAWCTXT_BIND_GMEM_SHADOW:
+ {
+ kgsl_drawctxt_bind_gmem_shadow_t param;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_drawctxt_bind_gmem_shadow_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = kgsl_drawctxt_bind_gmem_shadow(param.device_id, param.drawctxt_id, param.gmem_rect, param.shadow_x, param.shadow_y, param.shadow_buffer, param.buffer_id);
+ break;
+ }
+ case IOCTL_KGSL_SHAREDMEM_ALLOC:
+ {
+ kgsl_sharedmem_alloc_t param;
+ gsl_memdesc_t tmp;
+ int tmpStatus;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_sharedmem_alloc_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = kgsl_sharedmem_alloc(param.device_id, param.flags, param.sizebytes, &tmp);
+ if (kgslStatus == GSL_SUCCESS)
+ {
+ if (copy_to_user(param.memdesc, &tmp, sizeof(gsl_memdesc_t)))
+ {
+ tmpStatus = kgsl_sharedmem_free(&tmp);
+ KOS_ASSERT(tmpStatus == GSL_SUCCESS);
+ printk(KERN_ERR "%s: copy_to_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ else
+ {
+ add_memblock_to_allocated_list(fd, &tmp);
+ }
+ }
+ break;
+ }
+ case IOCTL_KGSL_SHAREDMEM_FREE:
+ {
+ kgsl_sharedmem_free_t param;
+ gsl_memdesc_t tmp;
+ int err;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_sharedmem_free_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ if (copy_from_user(&tmp, (void __user *)param.memdesc, sizeof(gsl_memdesc_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ err = del_memblock_from_allocated_list(fd, &tmp);
+ if(err)
+ {
+ printk(KERN_ERR "%s: tried to free memdesc that was not allocated!\n", __func__);
+ kgslStatus = err;
+ break;
+ }
+ kgslStatus = kgsl_sharedmem_free(&tmp);
+ if (kgslStatus == GSL_SUCCESS)
+ {
+ if (copy_to_user(param.memdesc, &tmp, sizeof(gsl_memdesc_t)))
+ {
+ printk(KERN_ERR "%s: copy_to_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ }
+ break;
+ }
+ case IOCTL_KGSL_SHAREDMEM_READ:
+ {
+ kgsl_sharedmem_read_t param;
+ gsl_memdesc_t memdesc;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_sharedmem_read_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ if (copy_from_user(&memdesc, (void __user *)param.memdesc, sizeof(gsl_memdesc_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = kgsl_sharedmem_read(&memdesc, param.dst, param.offsetbytes, param.sizebytes, true);
+ if (kgslStatus != GSL_SUCCESS)
+ {
+ printk(KERN_ERR "%s: kgsl_sharedmem_read failed\n", __func__);
+ }
+ break;
+ }
+ case IOCTL_KGSL_SHAREDMEM_WRITE:
+ {
+ kgsl_sharedmem_write_t param;
+ gsl_memdesc_t memdesc;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_sharedmem_write_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ if (copy_from_user(&memdesc, (void __user *)param.memdesc, sizeof(gsl_memdesc_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = kgsl_sharedmem_write(&memdesc, param.offsetbytes, param.src, param.sizebytes, true);
+ if (kgslStatus != GSL_SUCCESS)
+ {
+ printk(KERN_ERR "%s: kgsl_sharedmem_write failed\n", __func__);
+ }
+
+ break;
+ }
+ case IOCTL_KGSL_SHAREDMEM_SET:
+ {
+ kgsl_sharedmem_set_t param;
+ gsl_memdesc_t memdesc;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_sharedmem_set_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ if (copy_from_user(&memdesc, (void __user *)param.memdesc, sizeof(gsl_memdesc_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = kgsl_sharedmem_set(&memdesc, param.offsetbytes, param.value, param.sizebytes);
+ break;
+ }
+ case IOCTL_KGSL_SHAREDMEM_LARGESTFREEBLOCK:
+ {
+ kgsl_sharedmem_largestfreeblock_t param;
+ unsigned int largestfreeblock;
+
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_sharedmem_largestfreeblock_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ largestfreeblock = kgsl_sharedmem_largestfreeblock(param.device_id, param.flags);
+ if (copy_to_user(param.largestfreeblock, &largestfreeblock, sizeof(unsigned int)))
+ {
+ printk(KERN_ERR "%s: copy_to_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = GSL_SUCCESS;
+ break;
+ }
+ case IOCTL_KGSL_SHAREDMEM_CACHEOPERATION:
+ {
+ kgsl_sharedmem_cacheoperation_t param;
+ gsl_memdesc_t memdesc;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_sharedmem_cacheoperation_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ if (copy_from_user(&memdesc, (void __user *)param.memdesc, sizeof(gsl_memdesc_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = kgsl_sharedmem_cacheoperation(&memdesc, param.offsetbytes, param.sizebytes, param.operation);
+ break;
+ }
+ case IOCTL_KGSL_SHAREDMEM_FROMHOSTPOINTER:
+ {
+ kgsl_sharedmem_fromhostpointer_t param;
+ gsl_memdesc_t memdesc;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_sharedmem_fromhostpointer_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ if (copy_from_user(&memdesc, (void __user *)param.memdesc, sizeof(gsl_memdesc_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = kgsl_sharedmem_fromhostpointer(param.device_id, &memdesc, param.hostptr);
+ break;
+ }
+ case IOCTL_KGSL_ADD_TIMESTAMP:
+ {
+ kgsl_add_timestamp_t param;
+ gsl_timestamp_t tmp;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_add_timestamp_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ tmp = kgsl_add_timestamp(param.device_id, &tmp);
+ if (copy_to_user(param.timestamp, &tmp, sizeof(gsl_timestamp_t)))
+ {
+ printk(KERN_ERR "%s: copy_to_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = GSL_SUCCESS;
+ break;
+ }
+
+ case IOCTL_KGSL_DEVICE_CLOCK:
+ {
+ kgsl_device_clock_t param;
+ if (copy_from_user(&param, (void __user *)arg, sizeof(kgsl_device_clock_t)))
+ {
+ printk(KERN_ERR "%s: copy_from_user error\n", __func__);
+ kgslStatus = GSL_FAILURE;
+ break;
+ }
+ kgslStatus = kgsl_device_clock(param.device, param.enable);
+ break;
+ }
+ default:
+ kgslStatus = -ENOTTY;
+ break;
+ }
+
+ return kgslStatus;
+}
+
+static int gsl_kmod_mmap(struct file *fd, struct vm_area_struct *vma)
+{
+ int status = 0;
+ unsigned long start = vma->vm_start;
+ unsigned long pfn = vma->vm_pgoff;
+ unsigned long size = vma->vm_end - vma->vm_start;
+ unsigned long prot = pgprot_writecombine(vma->vm_page_prot);
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ unsigned long addr = vma->vm_pgoff << PAGE_SHIFT;
+ void *va;
+#endif
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ if (addr < GSL_LINUX_MAP_RANGE_END && addr >= GSL_LINUX_MAP_RANGE_START)
+ {
+ va = gsl_linux_map_find(addr);
+ while (size > 0)
+ {
+ if (remap_pfn_range(vma, start, vmalloc_to_pfn(va), PAGE_SIZE, prot))
+ {
+ return -EAGAIN;
+ }
+ start += PAGE_SIZE;
+ va += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+ }
+ else
+#endif
+ {
+ if (remap_pfn_range(vma, start, pfn, size, prot))
+ {
+ status = -EAGAIN;
+ }
+ }
+
+ vma->vm_ops = &gsl_kmod_vmops;
+
+ return status;
+}
+
+static int gsl_kmod_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+ return VM_FAULT_SIGBUS;
+}
+
+static int gsl_kmod_open(struct inode *inode, struct file *fd)
+{
+ gsl_flags_t flags = 0;
+ struct gsl_kmod_per_fd_data *datp;
+ int err = 0;
+
+ if(mutex_lock_interruptible(&gsl_mutex))
+ {
+ return -EINTR;
+ }
+
+ if (kgsl_driver_entry(flags) != GSL_SUCCESS)
+ {
+ printk(KERN_INFO "%s: kgsl_driver_entry error\n", __func__);
+ err = -EIO; // TODO: not sure why did it fail?
+ }
+ else
+ {
+ /* allocate per file descriptor data structure */
+ datp = (struct gsl_kmod_per_fd_data *)kzalloc(
+ sizeof(struct gsl_kmod_per_fd_data),
+ GFP_KERNEL);
+ if(datp)
+ {
+ init_created_contexts_array(datp->created_contexts_array[0]);
+ INIT_LIST_HEAD(&datp->allocated_blocks_head);
+
+ fd->private_data = (void *)datp;
+ }
+ else
+ {
+ err = -ENOMEM;
+ }
+ }
+
+ mutex_unlock(&gsl_mutex);
+
+ return err;
+}
+
+static int gsl_kmod_release(struct inode *inode, struct file *fd)
+{
+ struct gsl_kmod_per_fd_data *datp;
+ int err = 0;
+
+ if(mutex_lock_interruptible(&gsl_mutex))
+ {
+ return -EINTR;
+ }
+
+ /* make sure contexts are destroyed */
+ del_all_devices_contexts(fd);
+
+ if (kgsl_driver_exit() != GSL_SUCCESS)
+ {
+ printk(KERN_INFO "%s: kgsl_driver_exit error\n", __func__);
+ err = -EIO; // TODO: find better error code
+ }
+ else
+ {
+ /* release per file descriptor data structure */
+ datp = (struct gsl_kmod_per_fd_data *)fd->private_data;
+ del_all_memblocks_from_allocated_list(fd);
+ kfree(datp);
+ fd->private_data = 0;
+ }
+
+ mutex_unlock(&gsl_mutex);
+
+ return err;
+}
+
+static struct class *gsl_kmod_class;
+
+static irqreturn_t z160_irq_handler(int irq, void *dev_id)
+{
+ kgsl_intr_isr();
+ return IRQ_HANDLED;
+}
+
+#if defined(MX51)
+static irqreturn_t z430_irq_handler(int irq, void *dev_id)
+{
+ kgsl_intr_isr();
+ return IRQ_HANDLED;
+}
+#endif
+
+static int gpu_probe(struct platform_device *pdev)
+{
+ int i;
+ struct resource *res;
+ struct device *dev;
+
+ for(i = 0; i < 2; i++){
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+ if (!res) {
+ if (i == 0) {
+ printk(KERN_ERR "gpu: unable to get gpu irq\n");
+ return -ENODEV;
+ } else {
+ break;
+ }
+ }
+ if(strcmp(res->name, "gpu_2d_irq") == 0){
+ gpu_2d_irq = res->start;
+ }else if(strcmp(res->name, "gpu_3d_irq") == 0){
+ gpu_3d_irq = res->start;
+ }
+ }
+
+ for(i = 0; i < 4; i++){
+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+ if (!res) {
+ gpu_2d_regbase = 0;
+ gpu_2d_regsize = 0;
+ gpu_3d_regbase = 0;
+ gpu_2d_regsize = 0;
+ gmem_size = 0;
+ gpu_reserved_mem = 0;
+ gpu_reserved_mem_size = 0;
+ break;
+ }else{
+ if(strcmp(res->name, "gpu_2d_registers") == 0){
+ gpu_2d_regbase = res->start;
+ gpu_2d_regsize = res->end - res->start + 1;
+ }else if(strcmp(res->name, "gpu_3d_registers") == 0){
+ gpu_3d_regbase = res->start;
+ gpu_3d_regsize = res->end - res->start + 1;
+ }else if(strcmp(res->name, "gpu_graphics_mem") == 0){
+ gmem_size = res->end - res->start + 1;
+ }else if(strcmp(res->name, "gpu_reserved_mem") == 0){
+ gpu_reserved_mem = res->start;
+ gpu_reserved_mem_size = res->end - res->start + 1;
+ }
+ }
+ }
+
+ if (kgsl_driver_init() != GSL_SUCCESS)
+ {
+ printk(KERN_ERR "%s: kgsl_driver_init error\n", __func__);
+ goto kgsl_driver_init_error;
+ }
+
+#if defined(MX51)
+ if (request_irq(gpu_3d_irq, z430_irq_handler, 0, "ydx", NULL) < 0)
+ {
+ printk(KERN_ERR "%s: request_irq error\n", __func__);
+ goto request_irq_error;
+ }
+#endif
+
+ if (request_irq(gpu_2d_irq, z160_irq_handler, 0, "g12", NULL) < 0)
+ {
+ printk(KERN_ERR "2D Acceleration Enabled, OpenVG Disabled!\n");
+ gpu_2d_irq = 0;
+ }
+
+ gsl_kmod_major = register_chrdev(0, "gsl_kmod", &gsl_kmod_fops);
+ gsl_kmod_vmops.fault = gsl_kmod_fault;
+
+ if (gsl_kmod_major <= 0)
+ {
+ pr_err("%s: register_chrdev error\n", __func__);
+ goto register_chrdev_error;
+ }
+
+ gsl_kmod_class = class_create(THIS_MODULE, "gsl_kmod");
+
+ if (IS_ERR(gsl_kmod_class))
+ {
+ pr_err("%s: class_create error\n", __func__);
+ goto class_create_error;
+ }
+
+ #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28))
+ dev = device_create(gsl_kmod_class, NULL, MKDEV(gsl_kmod_major, 0), "gsl_kmod");
+ #else
+ dev = device_create(gsl_kmod_class, NULL, MKDEV(gsl_kmod_major, 0), NULL,"gsl_kmod");
+ #endif
+
+ if (!IS_ERR(dev))
+ {
+ // gsl_kmod_data.device = dev;
+ return 0;
+ }
+
+ pr_err("%s: device_create error\n", __func__);
+
+class_create_error:
+ class_destroy(gsl_kmod_class);
+
+register_chrdev_error:
+ unregister_chrdev(gsl_kmod_major, "gsl_kmod");
+
+request_irq_error:
+kgsl_driver_init_error:
+ kgsl_driver_close();
+ return 0; // TODO: return proper error code
+}
+
+static int gpu_remove(struct platform_device *pdev)
+{
+ device_destroy(gsl_kmod_class, MKDEV(gsl_kmod_major, 0));
+ class_destroy(gsl_kmod_class);
+ unregister_chrdev(gsl_kmod_major, "gsl_kmod");
+#if defined(MX51)
+ if (gpu_3d_irq)
+ {
+ free_irq(gpu_3d_irq, NULL);
+ }
+
+ if (gpu_2d_irq)
+ {
+ free_irq(gpu_2d_irq, NULL);
+ }
+#elif defined(MX35)
+ if (gpu_2d_irq)
+ {
+ free_irq(gpu_2d_irq, NULL);
+ }
+#endif
+ kgsl_driver_close();
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int gpu_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ int i;
+ gsl_powerprop_t power;
+
+ power.flags = GSL_PWRFLAGS_POWER_OFF;
+ for (i = 0; i < GSL_DEVICE_MAX; i++)
+ {
+ kgsl_device_setproperty(
+ (gsl_deviceid_t) (i+1),
+ GSL_PROP_DEVICE_POWER,
+ &power,
+ sizeof(gsl_powerprop_t));
+ }
+
+ return 0;
+}
+
+static int gpu_resume(struct platform_device *pdev)
+{
+ int i;
+ gsl_powerprop_t power;
+
+ power.flags = GSL_PWRFLAGS_POWER_ON;
+ for (i = 0; i < GSL_DEVICE_MAX; i++)
+ {
+ kgsl_device_setproperty(
+ (gsl_deviceid_t) (i+1),
+ GSL_PROP_DEVICE_POWER,
+ &power,
+ sizeof(gsl_powerprop_t));
+ }
+
+ return 0;
+}
+#else
+#define gpu_suspend NULL
+#define gpu_resume NULL
+#endif /* !CONFIG_PM */
+
+/*! Driver definition
+ */
+static struct platform_driver gpu_driver = {
+ .driver = {
+ .name = "mxc_gpu",
+ },
+ .probe = gpu_probe,
+ .remove = gpu_remove,
+ .suspend = gpu_suspend,
+ .resume = gpu_resume,
+};
+
+static int __init gsl_kmod_init(void)
+{
+ return platform_driver_register(&gpu_driver);
+}
+
+static void __exit gsl_kmod_exit(void)
+{
+ platform_driver_unregister(&gpu_driver);
+}
+
+module_init(gsl_kmod_init);
+module_exit(gsl_kmod_exit);
+MODULE_AUTHOR("Advanced Micro Devices");
+#if defined(MX51)
+MODULE_DESCRIPTION("AMD 2D/3D graphics core driver for i.MX51");
+#elif defined(MX35)
+MODULE_DESCRIPTION("AMD 2D graphics core driver for i.MX35");
+#endif
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod_cleanup.c b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod_cleanup.c
new file mode 100644
index 000000000000..3685a5756baf
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod_cleanup.c
@@ -0,0 +1,269 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include "gsl.h"
+#include "gsl_kmod_cleanup.h"
+
+#include <linux/kernel.h>
+#include <linux/fs.h>
+
+/*
+ * Local helper functions to check and convert device/context id's (1 based)
+ * to index (0 based).
+ */
+static u32 device_id_to_device_index(gsl_deviceid_t device_id)
+{
+ KOS_ASSERT((GSL_DEVICE_ANY < device_id) &&
+ (device_id <= GSL_DEVICE_MAX));
+ return (u32)(device_id - 1);
+}
+
+/*
+ * Local helper function to check and get pointer to per file descriptor data
+ */
+static struct gsl_kmod_per_fd_data *get_fd_private_data(struct file *fd)
+{
+ struct gsl_kmod_per_fd_data *datp;
+
+ KOS_ASSERT(fd);
+ datp = (struct gsl_kmod_per_fd_data *)fd->private_data;
+ KOS_ASSERT(datp);
+ return datp;
+}
+
+static s8 *find_first_entry_with(s8 *subarray, s8 context_id)
+{
+ s8 *entry = NULL;
+ int i;
+
+//printk(KERN_DEBUG "At %s, ctx_id = %d\n", __func__, context_id);
+
+ KOS_ASSERT(context_id >= EMPTY_ENTRY);
+ KOS_ASSERT(context_id <= GSL_CONTEXT_MAX); // TODO: check the bound.
+
+ for(i = 0; i < GSL_CONTEXT_MAX; i++) // TODO: check the bound.
+ {
+ if(subarray[i] == (s8)context_id)
+ {
+ entry = &subarray[i];
+ break;
+ }
+ }
+
+ return entry;
+}
+
+
+/*
+ * Add a memdesc into a list of allocated memory blocks for this file
+ * descriptor. The list is build in such a way that it implements FIFO (i.e.
+ * list). Traces of tiger, tiger_ri and VG11 CTs should be analysed to make
+ * informed choice.
+ *
+ * NOTE! gsl_memdesc_ts are COPIED so user space should NOT change them.
+ */
+int add_memblock_to_allocated_list(struct file *fd,
+ gsl_memdesc_t *allocated_block)
+{
+ int err = 0;
+ struct gsl_kmod_per_fd_data *datp;
+ struct gsl_kmod_alloc_list *lisp;
+ struct list_head *head;
+
+ KOS_ASSERT(allocated_block);
+
+ datp = get_fd_private_data(fd);
+
+ head = &datp->allocated_blocks_head;
+ KOS_ASSERT(head);
+
+ /* allocate and put new entry in the list of allocated memory descriptors */
+ lisp = (struct gsl_kmod_alloc_list *)kzalloc(sizeof(struct gsl_kmod_alloc_list), GFP_KERNEL);
+ if(lisp)
+ {
+ INIT_LIST_HEAD(&lisp->node);
+
+ /* builds FIFO (list_add() would build LIFO) */
+ list_add_tail(&lisp->node, head);
+ memcpy(&lisp->allocated_block, allocated_block, sizeof(gsl_memdesc_t));
+ lisp->allocation_number = datp->maximum_number_of_blocks;
+// printk(KERN_DEBUG "List entry #%u allocated\n", lisp->allocation_number);
+
+ datp->maximum_number_of_blocks++;
+ datp->number_of_allocated_blocks++;
+
+ err = 0;
+ }
+ else
+ {
+ printk(KERN_ERR "%s: Could not allocate new list element\n", __func__);
+ err = -ENOMEM;
+ }
+
+ return err;
+}
+
+/* Delete a previously allocated memdesc from a list of allocated memory blocks */
+int del_memblock_from_allocated_list(struct file *fd,
+ gsl_memdesc_t *freed_block)
+{
+ struct gsl_kmod_per_fd_data *datp;
+ struct gsl_kmod_alloc_list *cursor, *next;
+ struct list_head *head;
+// int is_different;
+
+ KOS_ASSERT(freed_block);
+
+ datp = get_fd_private_data(fd);
+
+ head = &datp->allocated_blocks_head;
+ KOS_ASSERT(head);
+
+ KOS_ASSERT(datp->number_of_allocated_blocks > 0);
+
+ if(!list_empty(head))
+ {
+ list_for_each_entry_safe(cursor, next, head, node)
+ {
+ if(cursor->allocated_block.gpuaddr == freed_block->gpuaddr)
+ {
+// is_different = memcmp(&cursor->allocated_block, freed_block, sizeof(gsl_memdesc_t));
+// KOS_ASSERT(!is_different);
+
+ list_del(&cursor->node);
+// printk(KERN_DEBUG "List entry #%u freed\n", cursor->allocation_number);
+ kfree(cursor);
+ datp->number_of_allocated_blocks--;
+ return 0;
+ }
+ }
+ }
+ return -EINVAL; // tried to free entry not existing or from empty list.
+}
+
+/* Delete all previously allocated memdescs from a list */
+int del_all_memblocks_from_allocated_list(struct file *fd)
+{
+ struct gsl_kmod_per_fd_data *datp;
+ struct gsl_kmod_alloc_list *cursor, *next;
+ struct list_head *head;
+
+ datp = get_fd_private_data(fd);
+
+ head = &datp->allocated_blocks_head;
+ KOS_ASSERT(head);
+
+ if(!list_empty(head))
+ {
+ printk(KERN_INFO "Not all allocated memory blocks were freed. Doing it now.\n");
+ list_for_each_entry_safe(cursor, next, head, node)
+ {
+ printk(KERN_INFO "Freeing list entry #%u, gpuaddr=%x\n", (u32)cursor->allocation_number, cursor->allocated_block.gpuaddr);
+ kgsl_sharedmem_free(&cursor->allocated_block);
+ list_del(&cursor->node);
+ kfree(cursor);
+ }
+ }
+
+ KOS_ASSERT(list_empty(head));
+ datp->number_of_allocated_blocks = 0;
+
+ return 0;
+}
+
+void init_created_contexts_array(s8 *array)
+{
+ memset((void*)array, EMPTY_ENTRY, GSL_DEVICE_MAX * GSL_CONTEXT_MAX);
+}
+
+
+void add_device_context_to_array(struct file *fd,
+ gsl_deviceid_t device_id,
+ unsigned int context_id)
+{
+ struct gsl_kmod_per_fd_data *datp;
+ s8 *entry;
+ s8 *subarray;
+ u32 device_index = device_id_to_device_index(device_id);
+
+ datp = get_fd_private_data(fd);
+
+ subarray = datp->created_contexts_array[device_index];
+ entry = find_first_entry_with(subarray, EMPTY_ENTRY);
+
+ KOS_ASSERT(entry);
+ KOS_ASSERT((datp->created_contexts_array[device_index] <= entry) &&
+ (entry < datp->created_contexts_array[device_index] + GSL_CONTEXT_MAX));
+ KOS_ASSERT(context_id < 127);
+ *entry = (s8)context_id;
+}
+
+void del_device_context_from_array(struct file *fd,
+ gsl_deviceid_t device_id,
+ unsigned int context_id)
+{
+ struct gsl_kmod_per_fd_data *datp;
+ u32 device_index = device_id_to_device_index(device_id);
+ s8 *entry;
+ s8 *subarray;
+
+ datp = get_fd_private_data(fd);
+
+ KOS_ASSERT(context_id < 127);
+ subarray = &(datp->created_contexts_array[device_index][0]);
+ entry = find_first_entry_with(subarray, context_id);
+ KOS_ASSERT(entry);
+ KOS_ASSERT((datp->created_contexts_array[device_index] <= entry) &&
+ (entry < datp->created_contexts_array[device_index] + GSL_CONTEXT_MAX));
+ *entry = EMPTY_ENTRY;
+}
+
+void del_all_devices_contexts(struct file *fd)
+{
+ struct gsl_kmod_per_fd_data *datp;
+ gsl_deviceid_t id;
+ u32 device_index;
+ u32 ctx_array_index;
+ s8 ctx;
+ int err;
+
+ datp = get_fd_private_data(fd);
+
+ /* device_id is 1 based */
+ for(id = GSL_DEVICE_ANY + 1; id <= GSL_DEVICE_MAX; id++)
+ {
+ device_index = device_id_to_device_index(id);
+ for(ctx_array_index = 0; ctx_array_index < GSL_CONTEXT_MAX; ctx_array_index++)
+ {
+ ctx = datp->created_contexts_array[device_index][ctx_array_index];
+ if(ctx != EMPTY_ENTRY)
+ {
+ err = kgsl_context_destroy(id, ctx);
+ if(err != GSL_SUCCESS)
+ {
+ printk(KERN_ERR "%s: could not destroy context %d on device id = %u\n", __func__, ctx, id);
+ }
+ else
+ {
+ printk(KERN_DEBUG "%s: Destroyed context %d on device id = %u\n", __func__, ctx, id);
+ }
+ }
+ }
+ }
+}
+
diff --git a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod_cleanup.h b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod_cleanup.h
new file mode 100644
index 000000000000..475ee3be2e50
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod_cleanup.h
@@ -0,0 +1,90 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __GSL_KMOD_CLEANUP_H
+#define __GSL_KMOD_CLEANUP_H
+#include "gsl_types.h"
+
+#include <linux/gfp.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/list.h>
+
+#if (GSL_CONTEXT_MAX > 127)
+ #error created_contexts_array supports context numbers only 127 or less.
+#endif
+
+static const s8 EMPTY_ENTRY = -1;
+
+/* A structure to make list of allocated memory blocks. List per fd. */
+/* should probably be allocated from slab cache to minimise fragmentation */
+struct gsl_kmod_alloc_list
+{
+ struct list_head node;
+ gsl_memdesc_t allocated_block;
+ u32 allocation_number;
+};
+
+/* A structure to hold abovementioned list of blocks. Contain per fd data. */
+struct gsl_kmod_per_fd_data
+{
+ struct list_head allocated_blocks_head; // list head
+ u32 maximum_number_of_blocks;
+ u32 number_of_allocated_blocks;
+ s8 created_contexts_array[GSL_DEVICE_MAX][GSL_CONTEXT_MAX];
+};
+
+
+/*
+ * prototypes
+ */
+
+/* allocated memory block tracking */
+int add_memblock_to_allocated_list(struct file *fd,
+ gsl_memdesc_t *allocated_block);
+
+int del_memblock_from_allocated_list(struct file *fd,
+ gsl_memdesc_t *freed_block);
+
+int del_all_memblocks_from_allocated_list(struct file *fd);
+
+/* created contexts tracking */
+void init_created_contexts_array(s8 *array);
+
+void add_device_context_to_array(struct file *fd,
+ gsl_deviceid_t device_id,
+ unsigned int context_id);
+
+void del_device_context_from_array(struct file *fd,
+ gsl_deviceid_t device_id,
+ unsigned int context_id);
+
+void del_all_devices_contexts(struct file *fd);
+
+#endif // __GSL_KMOD_CLEANUP_H
+
diff --git a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_linux_map.c b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_linux_map.c
new file mode 100644
index 000000000000..7fee7b814411
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_linux_map.c
@@ -0,0 +1,221 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+
+#include "gsl_linux_map.h"
+
+struct gsl_linux_map
+{
+ struct list_head list;
+ unsigned int gpu_addr;
+ void *kernel_virtual_addr;
+ unsigned int size;
+};
+
+static LIST_HEAD(gsl_linux_map_list);
+static DEFINE_MUTEX(gsl_linux_map_mutex);
+
+int gsl_linux_map_init()
+{
+ mutex_lock(&gsl_linux_map_mutex);
+ INIT_LIST_HEAD(&gsl_linux_map_list);
+ mutex_unlock(&gsl_linux_map_mutex);
+
+ return 0;
+}
+
+void *gsl_linux_map_alloc(unsigned int gpu_addr, unsigned int size)
+{
+ struct gsl_linux_map * map;
+ struct list_head *p;
+ void *va;
+
+ mutex_lock(&gsl_linux_map_mutex);
+
+ list_for_each(p, &gsl_linux_map_list){
+ map = list_entry(p, struct gsl_linux_map, list);
+ if(map->gpu_addr == gpu_addr){
+ mutex_unlock(&gsl_linux_map_mutex);
+ return map->kernel_virtual_addr;
+ }
+ }
+
+ va = __vmalloc(size, GFP_KERNEL, pgprot_noncached(pgprot_kernel));
+ if(va == NULL){
+ mutex_unlock(&gsl_linux_map_mutex);
+ return NULL;
+ }
+
+ map = (struct gsl_linux_map *)kmalloc(sizeof(*map), GFP_KERNEL);
+ map->gpu_addr = gpu_addr;
+ map->kernel_virtual_addr = va;
+ map->size = size;
+
+ INIT_LIST_HEAD(&map->list);
+ list_add_tail(&map->list, &gsl_linux_map_list);
+
+ mutex_unlock(&gsl_linux_map_mutex);
+ return va;
+}
+
+void gsl_linux_map_free(unsigned int gpu_addr)
+{
+ int found = 0;
+ struct gsl_linux_map * map;
+ struct list_head *p;
+
+ mutex_lock(&gsl_linux_map_mutex);
+
+ list_for_each(p, &gsl_linux_map_list){
+ map = list_entry(p, struct gsl_linux_map, list);
+ if(map->gpu_addr == gpu_addr){
+ found = 1;
+ break;
+ }
+ }
+
+ if(found){
+ vfree(map->kernel_virtual_addr);
+ list_del(&map->list);
+ kfree(map);
+ }
+
+ mutex_unlock(&gsl_linux_map_mutex);
+}
+
+void *gsl_linux_map_find(unsigned int gpu_addr)
+{
+ struct gsl_linux_map * map;
+ struct list_head *p;
+
+ mutex_lock(&gsl_linux_map_mutex);
+
+ list_for_each(p, &gsl_linux_map_list){
+ map = list_entry(p, struct gsl_linux_map, list);
+ if(map->gpu_addr == gpu_addr){
+ mutex_unlock(&gsl_linux_map_mutex);
+ return map->kernel_virtual_addr;
+ }
+ }
+
+ mutex_unlock(&gsl_linux_map_mutex);
+ return NULL;
+}
+
+void *gsl_linux_map_read(void *dst, unsigned int gpuoffset, unsigned int sizebytes, unsigned int touserspace)
+{
+ struct gsl_linux_map * map;
+ struct list_head *p;
+
+ mutex_lock(&gsl_linux_map_mutex);
+
+ list_for_each(p, &gsl_linux_map_list){
+ map = list_entry(p, struct gsl_linux_map, list);
+ if(map->gpu_addr <= gpuoffset &&
+ (map->gpu_addr + map->size) > gpuoffset){
+ void *src = map->kernel_virtual_addr + (gpuoffset - map->gpu_addr);
+ mutex_unlock(&gsl_linux_map_mutex);
+ if (touserspace)
+ {
+ return (void *)copy_to_user(dst, map->kernel_virtual_addr + gpuoffset - map->gpu_addr, sizebytes);
+ }
+ else
+ {
+ return memcpy(dst, src, sizebytes);
+ }
+ }
+ }
+
+ mutex_unlock(&gsl_linux_map_mutex);
+ return NULL;
+}
+
+void *gsl_linux_map_write(void *src, unsigned int gpuoffset, unsigned int sizebytes, unsigned int fromuserspace)
+{
+ struct gsl_linux_map * map;
+ struct list_head *p;
+
+ mutex_lock(&gsl_linux_map_mutex);
+
+ list_for_each(p, &gsl_linux_map_list){
+ map = list_entry(p, struct gsl_linux_map, list);
+ if(map->gpu_addr <= gpuoffset &&
+ (map->gpu_addr + map->size) > gpuoffset){
+ void *dst = map->kernel_virtual_addr + (gpuoffset - map->gpu_addr);
+ mutex_unlock(&gsl_linux_map_mutex);
+ if (fromuserspace)
+ {
+ return (void *)copy_from_user(map->kernel_virtual_addr + gpuoffset - map->gpu_addr, src, sizebytes);
+ }
+ else
+ {
+ return memcpy(dst, src, sizebytes);
+ }
+ }
+ }
+
+ mutex_unlock(&gsl_linux_map_mutex);
+ return NULL;
+}
+
+void *gsl_linux_map_set(unsigned int gpuoffset, unsigned int value, unsigned int sizebytes)
+{
+ struct gsl_linux_map * map;
+ struct list_head *p;
+
+ mutex_lock(&gsl_linux_map_mutex);
+
+ list_for_each(p, &gsl_linux_map_list){
+ map = list_entry(p, struct gsl_linux_map, list);
+ if(map->gpu_addr <= gpuoffset &&
+ (map->gpu_addr + map->size) > gpuoffset){
+ void *ptr = map->kernel_virtual_addr + (gpuoffset - map->gpu_addr);
+ mutex_unlock(&gsl_linux_map_mutex);
+ return memset(ptr, value, sizebytes);
+ }
+ }
+
+ mutex_unlock(&gsl_linux_map_mutex);
+ return NULL;
+}
+
+int gsl_linux_map_destroy()
+{
+ struct gsl_linux_map * map;
+ struct list_head *p, *tmp;
+
+ mutex_lock(&gsl_linux_map_mutex);
+
+ list_for_each_safe(p, tmp, &gsl_linux_map_list){
+ map = list_entry(p, struct gsl_linux_map, list);
+ vfree(map->kernel_virtual_addr);
+ list_del(&map->list);
+ kfree(map);
+ }
+
+ INIT_LIST_HEAD(&gsl_linux_map_list);
+
+ mutex_unlock(&gsl_linux_map_mutex);
+ return 0;
+}
diff --git a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_linux_map.h b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_linux_map.h
new file mode 100644
index 000000000000..0469d2b912be
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_linux_map.h
@@ -0,0 +1,46 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __GSL_LINUX_MAP_H__
+#define __GSL_LINUX_MAP_H__
+
+#include "gsl_halconfig.h"
+
+#define GSL_LINUX_MAP_RANGE_START (1024*1024)
+#define GSL_LINUX_MAP_RANGE_END (GSL_LINUX_MAP_RANGE_START+GSL_HAL_SHMEM_SIZE_EMEM1)
+
+int gsl_linux_map_init(void);
+void *gsl_linux_map_alloc(unsigned int gpu_addr, unsigned int size);
+void gsl_linux_map_free(unsigned int gpu_addr);
+void *gsl_linux_map_find(unsigned int gpu_addr);
+void *gsl_linux_map_read(void *dst, unsigned int gpuoffset, unsigned int sizebytes, unsigned int touserspace);
+void *gsl_linux_map_write(void *src, unsigned int gpuoffset, unsigned int sizebytes, unsigned int fromuserspace);
+void *gsl_linux_map_set(unsigned int gpuoffset, unsigned int value, unsigned int sizebytes);
+int gsl_linux_map_destroy(void);
+
+#endif
diff --git a/drivers/mxc/amd-gpu/platform/hal/linux/misc.c b/drivers/mxc/amd-gpu/platform/hal/linux/misc.c
new file mode 100644
index 000000000000..a356f334b187
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/linux/misc.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <gsl.h>
+
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+
+typedef struct _gsl_autogate_t {
+ struct timer_list timer;
+ spinlock_t lock;
+ int active;
+ int timeout;
+ gsl_device_t *dev;
+} gsl_autogate_t;
+
+
+#define KGSL_DEVICE_IDLE_TIMEOUT 5000 /* unit ms */
+
+int kgsl_device_active(gsl_device_t *dev)
+{
+ unsigned long flags;
+ gsl_autogate_t *autogate = dev->autogate;
+ if (!autogate) {
+ printk(KERN_ERR "%s: autogate has exited!\n", __func__);
+ return 0;
+ }
+// printk(KERN_ERR "%s:%d id %d active %d\n", __func__, __LINE__, dev->id, autogate->active);
+
+ spin_lock_irqsave(&autogate->lock, flags);
+ if (!autogate->active)
+ kgsl_clock(autogate->dev->id, 1);
+ autogate->active = 1;
+ mod_timer(&autogate->timer, jiffies + msecs_to_jiffies(autogate->timeout));
+ spin_unlock_irqrestore(&autogate->lock, flags);
+ return 0;
+}
+
+static void kgsl_device_inactive(unsigned long data)
+{
+ gsl_autogate_t *autogate = (gsl_autogate_t *)data;
+ unsigned long flags;
+
+// printk(KERN_ERR "%s:%d id %d active %d\n", __func__, __LINE__, autogate->dev->id, autogate->active);
+ del_timer(&autogate->timer);
+ spin_lock_irqsave(&autogate->lock, flags);
+ WARN(!autogate->active, "GPU Device %d is already inactive\n", autogate->dev->id);
+ autogate->active = 0;
+ /* idle check may sleep, so don't use it */
+// if (autogate->dev->ftbl.device_idle)
+// autogate->dev->ftbl.device_idle(autogate->dev, GSL_TIMEOUT_DEFAULT);
+ kgsl_clock(autogate->dev->id, 0);
+ spin_unlock_irqrestore(&autogate->lock, flags);
+}
+
+int kgsl_device_clock(gsl_deviceid_t id, int enable)
+{
+ int ret = GSL_SUCCESS;
+ gsl_device_t *device;
+
+ device = &gsl_driver.device[id-1]; // device_id is 1 based
+ if (device->flags & GSL_FLAGS_INITIALIZED) {
+ if (enable)
+ kgsl_device_active(device);
+ else
+ kgsl_device_inactive((unsigned long)device);
+ } else {
+ printk(KERN_ERR "%s: Dev %d clock is already off!\n", __func__, id);
+ ret = GSL_FAILURE;
+ }
+
+ return ret;
+}
+
+int kgsl_device_autogate_init(gsl_device_t *dev)
+{
+ gsl_autogate_t *autogate;
+
+// printk(KERN_ERR "%s:%d id %d\n", __func__, __LINE__, dev->id);
+ autogate = kmalloc(sizeof(gsl_autogate_t), GFP_KERNEL);
+ if (!autogate) {
+ printk(KERN_ERR "%s: out of memory!\n", __func__);
+ return -ENOMEM;
+ }
+ autogate->dev = dev;
+ autogate->active = 1;
+ spin_lock_init(&autogate->lock);
+ autogate->timeout = KGSL_DEVICE_IDLE_TIMEOUT;
+ init_timer(&autogate->timer);
+ autogate->timer.expires = jiffies + msecs_to_jiffies(autogate->timeout);
+ autogate->timer.function = kgsl_device_inactive;
+ autogate->timer.data = (unsigned long)autogate;
+ add_timer(&autogate->timer);
+ dev->autogate = autogate;
+ return 0;
+}
+
+void kgsl_device_autogate_exit(gsl_device_t *dev)
+{
+ gsl_autogate_t *autogate = dev->autogate;
+
+// printk(KERN_ERR "%s:%d id %d active %d\n", __func__, __LINE__, dev->id, autogate->active);
+ if (autogate->active)
+ del_timer(&autogate->timer);
+ else
+ kgsl_clock(autogate->dev->id, 1);
+
+ kfree(autogate);
+ dev->autogate = NULL;
+
+}