aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPraneeth Bajjuri2013-07-25 20:52:18 -0500
committerPraneeth Bajjuri2013-07-25 20:54:21 -0500
commit08d2b71b41d8acb5f0684faf18a27f3b82d17f57 (patch)
treeac2e5c3101a12294f9d2707e7f860297cea230ec
parent4d92f1b39268fdd930e36cfcf8e1b99fe7501ba0 (diff)
parentb32501a57bbf7d89b454276bb8787c22a399d720 (diff)
downloadkernel-video-08d2b71b41d8acb5f0684faf18a27f3b82d17f57.tar.gz
kernel-video-08d2b71b41d8acb5f0684faf18a27f3b82d17f57.tar.xz
kernel-video-08d2b71b41d8acb5f0684faf18a27f3b82d17f57.zip
Merge remote-tracking branch 'origin/omaplfb' into p-ti-android-3.8.y-video
This contains GC320 series * origin/omaplfb: ARM: OMAP5/DRA7: hwmod: add ADDR_TYPE_RT to bb2d address flags gc320: gcx: [WA] Allocate MMU page tables as non cached gc320: Added missing programming of MTLB base second time gc320: Increase VRAM buffers to 4 gc320: adding gcxxx support in Makefiles gc320: Adapt GC320 driver for K3.8 devices: Initialize GC320 as part of devices init platform_data: Added platform data for GC320 gc320: OMAP4: Adding cache-2dmanager Signed-off-by: Praneeth Bajjuri <praneeth@ti.com>
-rw-r--r--arch/arm/mach-omap2/devices.c67
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_54xx_data.c28
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_7xx_data.c1
-rw-r--r--arch/arm/plat-omap/sgx_omaplfb.c4
-rw-r--r--drivers/misc/Kconfig4
-rw-r--r--drivers/misc/Makefile4
-rw-r--r--drivers/misc/cache-2dmanager/Kconfig5
-rw-r--r--drivers/misc/cache-2dmanager/Makefile4
-rw-r--r--drivers/misc/cache-2dmanager/cache-2dmanager.c208
-rw-r--r--drivers/misc/gcx/gcbv/gcmain.c8
-rw-r--r--drivers/misc/gcx/gccore/gcmain.c58
-rw-r--r--drivers/misc/gcx/gccore/gcmmu.c35
-rw-r--r--drivers/misc/gcx/gccore/gcqueue.c3
-rw-r--r--drivers/misc/gcx/gcioctl/gcif.c8
-rw-r--r--include/linux/cache-2dmanager.h62
-rw-r--r--include/linux/gccore.h4
-rw-r--r--include/linux/platform_data/omap_gcx.h33
17 files changed, 499 insertions, 37 deletions
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 2d4f9c02dcc..a8f1557a225 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -22,6 +22,8 @@
22#include <linux/platform_data/omap_ocp2scp.h> 22#include <linux/platform_data/omap_ocp2scp.h>
23#include <linux/usb/omap_control_usb.h> 23#include <linux/usb/omap_control_usb.h>
24#include <linux/platform_data/mailbox-omap.h> 24#include <linux/platform_data/mailbox-omap.h>
25#include <linux/platform_data/omap_gcx.h>
26#include "omap-pm.h"
25 27
26#include <asm/mach-types.h> 28#include <asm/mach-types.h>
27#include <asm/mach/map.h> 29#include <asm/mach/map.h>
@@ -447,6 +449,70 @@ static void __init omap_init_dmic(void)
447static inline void omap_init_dmic(void) {} 449static inline void omap_init_dmic(void) {}
448#endif 450#endif
449 451
452static int gcxxx_scale_dev(struct device *dev, unsigned long val);
453static int gcxxx_set_l3_bw(struct device *dev, unsigned long val);
454
455static struct omap_gcx_platform_data omap_gcxxx = {
456 .get_context_loss_count = omap_pm_get_dev_context_loss_count,
457 .scale_dev = gcxxx_scale_dev,
458 .set_bw = gcxxx_set_l3_bw,
459};
460
461struct omap_device_pm_latency omap_gcxxx_latency[] = {
462 {
463 .deactivate_func = omap_device_idle_hwmods,
464 .activate_func = omap_device_enable_hwmods,
465 .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
466 }
467};
468
469static int gcxxx_scale_dev(struct device *dev, unsigned long val)
470{
471 /*omap_device_scale(dev, val) is not supported, returning with no-op
472 * for now. */
473 return 0;
474}
475
476static int gcxxx_set_l3_bw(struct device *dev, unsigned long val)
477{
478 return omap_pm_set_min_bus_tput(dev, OCP_INITIATOR_AGENT, val);
479}
480
481int __init gcxxx_init(void)
482{
483 int retval = 0;
484 struct omap_hwmod *oh;
485 struct platform_device *pdev;
486 /*struct omap_device *od;
487 struct device *dev;*/
488 const char *oh_name = "bb2d";
489 const char *dev_name = "gccore";
490
491 /*
492 * Hwmod lookup will fail in case our platform doesn't support the
493 * hardware spinlock module, so it is safe to run this initcall
494 * on all omaps
495 */
496 oh = omap_hwmod_lookup(oh_name);
497 if (oh == NULL)
498 return -EINVAL;
499
500 omap_gcxxx.regbase = omap_hwmod_get_mpu_rt_va(oh);
501 omap_gcxxx.is_hw_present = (soc_is_omap543x()
502 || soc_is_dra7xx()) ? true : false;
503 pdev = omap_device_build(dev_name, 0, oh, &omap_gcxxx,
504 sizeof(omap_gcxxx), omap_gcxxx_latency,
505 ARRAY_SIZE(omap_gcxxx_latency), false);
506 if (IS_ERR(pdev)) {
507 pr_err("Can't build omap_device for %s:%s\n", dev_name,
508 oh_name);
509 retval = PTR_ERR(pdev);
510 }
511
512 return retval;
513}
514
515
450#if defined(CONFIG_SND_OMAP_SOC_ABE) || \ 516#if defined(CONFIG_SND_OMAP_SOC_ABE) || \
451 defined(CONFIG_SND_OMAP_SOC_ABE_MODULE) 517 defined(CONFIG_SND_OMAP_SOC_ABE_MODULE)
452 518
@@ -683,6 +749,7 @@ static int __init omap2_init_devices(void)
683 omap_init_audio(); 749 omap_init_audio();
684 omap_init_camera(); 750 omap_init_camera();
685 omap_init_mbox(); 751 omap_init_mbox();
752 gcxxx_init();
686 /* If dtb is there, the devices will be created dynamically */ 753 /* If dtb is there, the devices will be created dynamically */
687 if (!of_have_populated_dt()) { 754 if (!of_have_populated_dt()) {
688 omap_init_control_usb(); 755 omap_init_control_usb();
diff --git a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c
index ee7f4a9a77a..73c152d17a9 100644
--- a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c
@@ -45,6 +45,9 @@
45/* Base offset for all OMAP5 dma requests */ 45/* Base offset for all OMAP5 dma requests */
46#define OMAP54XX_DMA_REQ_START 1 46#define OMAP54XX_DMA_REQ_START 1
47 47
48/* Backward references (IPs with Bus Master capability) */
49static struct omap_hwmod omap54xx_bb2d_hwmod;
50
48 51
49/* 52/*
50 * IP blocks 53 * IP blocks
@@ -339,6 +342,24 @@ static struct omap_hwmod_irq_info omap54xx_bb2d_irqs[] = {
339 { .irq = -1 } 342 { .irq = -1 }
340}; 343};
341 344
345static struct omap_hwmod_addr_space omap54xx_bb2d_addrs[] = {
346 {
347 .pa_start = 0x59000000,
348 .pa_end = 0x590007ff,
349 .flags = ADDR_TYPE_RT
350 },
351 { }
352};
353
354/* l3_main_2 -> bb2d */
355static struct omap_hwmod_ocp_if omap54xx_l3_main_2__bb2d = {
356 .master = &omap54xx_l3_main_2_hwmod,
357 .slave = &omap54xx_bb2d_hwmod,
358 .clk = "l3_iclk_div",
359 .addr = omap54xx_bb2d_addrs,
360 .user = OCP_USER_MPU | OCP_USER_SDMA,
361};
362
342static struct omap_hwmod omap54xx_bb2d_hwmod = { 363static struct omap_hwmod omap54xx_bb2d_hwmod = {
343 .name = "bb2d", 364 .name = "bb2d",
344 .class = &omap54xx_bb2d_hwmod_class, 365 .class = &omap54xx_bb2d_hwmod_class,
@@ -3961,13 +3982,6 @@ static struct omap_hwmod_ocp_if omap54xx_l4_abe__aess = {
3961 .user = OCP_USER_MPU, 3982 .user = OCP_USER_MPU,
3962}; 3983};
3963 3984
3964/* l3_main_2 -> bb2d */
3965static struct omap_hwmod_ocp_if omap54xx_l3_main_2__bb2d = {
3966 .master = &omap54xx_l3_main_2_hwmod,
3967 .slave = &omap54xx_bb2d_hwmod,
3968 .clk = "l3_iclk_div",
3969 .user = OCP_USER_MPU | OCP_USER_SDMA,
3970};
3971 3985
3972static struct omap_hwmod_addr_space omap54xx_c2c_addrs[] = { 3986static struct omap_hwmod_addr_space omap54xx_c2c_addrs[] = {
3973 { 3987 {
diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
index e8d09dfbaf6..1976fc952c5 100644
--- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
@@ -3801,6 +3801,7 @@ static struct omap_hwmod_addr_space dra7xx_bb2d_addrs[] = {
3801 { 3801 {
3802 .pa_start = 0x59000000, 3802 .pa_start = 0x59000000,
3803 .pa_end = 0x590007ff, 3803 .pa_end = 0x590007ff,
3804 .flags = ADDR_TYPE_RT
3804 }, 3805 },
3805 { } 3806 { }
3806}; 3807};
diff --git a/arch/arm/plat-omap/sgx_omaplfb.c b/arch/arm/plat-omap/sgx_omaplfb.c
index efa08a6d691..e4cad796c80 100644
--- a/arch/arm/plat-omap/sgx_omaplfb.c
+++ b/arch/arm/plat-omap/sgx_omaplfb.c
@@ -35,12 +35,12 @@
35 35
36static struct sgx_omaplfb_config omaplfb_config[OMAPLFB_NUM_DEV] = { 36static struct sgx_omaplfb_config omaplfb_config[OMAPLFB_NUM_DEV] = {
37 { 37 {
38 .vram_buffers = 2, 38 .vram_buffers = 4,
39 .swap_chain_length = 2, 39 .swap_chain_length = 2,
40 }, 40 },
41 { 41 {
42 .tiler2d_buffers = 0, 42 .tiler2d_buffers = 0,
43 .vram_buffers = 2, 43 .vram_buffers = 4,
44 .swap_chain_length = 2, 44 .swap_chain_length = 2,
45 } 45 }
46}; 46};
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 29818b28925..cd68921b36e 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -509,6 +509,10 @@ source "drivers/misc/cb710/Kconfig"
509source "drivers/misc/ti-st/Kconfig" 509source "drivers/misc/ti-st/Kconfig"
510source "drivers/misc/lis3lv02d/Kconfig" 510source "drivers/misc/lis3lv02d/Kconfig"
511source "drivers/misc/carma/Kconfig" 511source "drivers/misc/carma/Kconfig"
512source "drivers/misc/gcx/gccore/Kconfig"
513source "drivers/misc/gcx/gcioctl/Kconfig"
514source "drivers/misc/gcx/gcbv/Kconfig"
515source "drivers/misc/cache-2dmanager/Kconfig"
512source "drivers/misc/altera-stapl/Kconfig" 516source "drivers/misc/altera-stapl/Kconfig"
513source "drivers/misc/mei/Kconfig" 517source "drivers/misc/mei/Kconfig"
514endmenu 518endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f547db387dd..a43854760d2 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -50,3 +50,7 @@ obj-y += carma/
50obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o 50obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
51obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/ 51obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
52obj-$(CONFIG_INTEL_MEI) += mei/ 52obj-$(CONFIG_INTEL_MEI) += mei/
53obj-$(CONFIG_GCCORE) += gcx/gccore/
54obj-$(CONFIG_GCBV) += gcx/gcbv/
55obj-$(CONFIG_GCIOCTL) += gcx/gcioctl/
56obj-$(CONFIG_CACHE2DMANAGER) += cache-2dmanager/
diff --git a/drivers/misc/cache-2dmanager/Kconfig b/drivers/misc/cache-2dmanager/Kconfig
new file mode 100644
index 00000000000..4b74fdeb24f
--- /dev/null
+++ b/drivers/misc/cache-2dmanager/Kconfig
@@ -0,0 +1,5 @@
1config CACHE2DMANAGER
2 tristate "2D Cache operation driver"
3 default y
4 help
5 Enable 2D Cache operation support
diff --git a/drivers/misc/cache-2dmanager/Makefile b/drivers/misc/cache-2dmanager/Makefile
new file mode 100644
index 00000000000..c112df1449a
--- /dev/null
+++ b/drivers/misc/cache-2dmanager/Makefile
@@ -0,0 +1,4 @@
1obj-$(CONFIG_CACHE2DMANAGER) += cache2d.o
2
3cache2d-y := \
4 cache-2dmanager.o \
diff --git a/drivers/misc/cache-2dmanager/cache-2dmanager.c b/drivers/misc/cache-2dmanager/cache-2dmanager.c
new file mode 100644
index 00000000000..a1f0839f8e7
--- /dev/null
+++ b/drivers/misc/cache-2dmanager/cache-2dmanager.c
@@ -0,0 +1,208 @@
1/*
2 * cache-2dmanager.c
3 *
4 * Copyright (C) 2011-2012 Texas Instruments Corporation.
5 *
6 * This package is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
11 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
12 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13 */
14
15#include <linux/dma-mapping.h>
16#include <linux/module.h>
17#include <asm/cacheflush.h>
18#include <linux/sched.h>
19#include <linux/cache-2dmanager.h>
20
21static void per_cpu_cache_flush_arm(void *arg)
22{
23 flush_cache_all();
24}
25
26void c2dm_l1cache(int count, /* number of regions */
27 struct c2dmrgn rgns[], /* array of regions */
28 int dir) /* cache operation */
29{
30 unsigned long size = 0;
31 int rgn;
32 for (rgn = 0; rgn < count; rgn++)
33 size += rgns[rgn].span * rgns[rgn].lines;
34
35 /* If the total size of the caller's request exceeds the threshold,
36 * we can perform the operation on the entire cache instead.
37 *
38 * If the caller requests a clean larger than the threshold, we want
39 * to clean all. But this function does not exist in the L1 cache
40 * routines. So we use flush all.
41 *
42 * If the caller requests an invalidate larger than the threshold, we
43 * want to invalidate all. However, if the client does not fill the
44 * cache, an invalidate all will lose data from other processes, which
45 * can be catastrophic. So we must clean the entire cache before we
46 * invalidate it. Flush all cleans and invalidates in one operation.
47 */
48 if (size >= L1THRESHOLD) {
49 switch (dir) {
50 case DMA_TO_DEVICE:
51 /* Use clean all when available */
52 /* Fall through for now */
53 case DMA_BIDIRECTIONAL:
54 /* Can't invalidate all without cleaning, so fall
55 * through to flush all to do both. */
56 case DMA_FROM_DEVICE:
57 on_each_cpu(per_cpu_cache_flush_arm, NULL, 1);
58 break;
59 }
60 } else {
61 int rgn;
62 for (rgn = 0; rgn < count; rgn++) {
63 int line;
64 char *start = rgns[rgn].start;
65 for (line = 0; line < rgns[rgn].lines; line++) {
66 if (dir == DMA_BIDIRECTIONAL)
67 cpu_cache.dma_flush_range(
68 start,
69 start + rgns[rgn].span);
70 else
71 cpu_cache.dma_map_area(
72 start,
73 rgns[rgn].span,
74 dir);
75 start += rgns[rgn].stride;
76 }
77 }
78 }
79}
80EXPORT_SYMBOL(c2dm_l1cache);
81
82static u32 virt2phys(u32 usr)
83{
84 pmd_t *pmd;
85 pte_t *ptep;
86 pgd_t *pgd = pgd_offset(current->mm, usr);
87
88 if (pgd_none(*pgd) || pgd_bad(*pgd))
89 return 0;
90
91 pmd = pmd_offset((pud_t *)pgd, usr);
92 if (pmd_none(*pmd) || pmd_bad(*pmd))
93 return 0;
94
95 ptep = pte_offset_map(pmd, usr);
96 if (ptep && pte_present(*ptep))
97 return (*ptep & PAGE_MASK) | (~PAGE_MASK & usr);
98
99 return 0;
100}
101
102void c2dm_l2cache(int count, /* number of regions */
103 struct c2dmrgn rgns[], /* array of regions */
104 int dir) /* cache operation */
105{
106
107 unsigned long size = 0;
108 int rgn;
109
110 for (rgn = 0; rgn < count; rgn++)
111 size += rgns[rgn].span * rgns[rgn].lines;
112
113 if (size >= L2THRESHOLD) {
114 switch (dir) {
115 case DMA_TO_DEVICE:
116 /* Use clean all when available */
117 /* Fall through for now */
118 case DMA_BIDIRECTIONAL:
119 /* Can't invalidate all without cleaning, so fall
120 * through to flush all to do both. */
121 case DMA_FROM_DEVICE:
122 outer_flush_all();
123 break;
124 }
125 return;
126 }
127
128 for (rgn = 0; rgn < count; rgn++) {
129 int i, j;
130 unsigned long linestart, start;
131 unsigned long page_begin, end, offset,
132 pageremain, lineremain;
133 unsigned long phys, opsize;
134 int page_num;
135
136 /* beginning virtual address of each line */
137 start = (unsigned long)rgns[rgn].start;
138
139 for (i = 0; i < rgns[rgn].lines; i++) {
140
141 linestart = start + (i * rgns[rgn].stride);
142
143 /* beginning of the page for the new line */
144 page_begin = linestart & PAGE_MASK;
145
146 /* end of the new line */
147 end = (unsigned long)linestart +
148 rgns[rgn].span;
149
150 page_num = DIV_ROUND_UP(
151 end-page_begin, PAGE_SIZE);
152
153 /* offset of the new line from page begin */
154 offset = linestart - page_begin;
155
156 /* track how long it is to the end of
157 the current page */
158 pageremain = PAGE_SIZE - offset;
159
160 /* keep track of how much of the line remains
161 to be copied */
162 lineremain = rgns[rgn].span;
163
164 for (j = 0; j < page_num; j++) {
165
166 opsize = (lineremain < pageremain) ?
167 lineremain : pageremain;
168
169 phys = virt2phys(page_begin);
170 if (phys) {
171 phys = phys + offset;
172 switch (dir) {
173 case DMA_TO_DEVICE:
174 outer_clean_range(
175 phys, phys + opsize);
176 break;
177 case DMA_FROM_DEVICE:
178 outer_inv_range(
179 phys, phys + opsize);
180 break;
181 case DMA_BIDIRECTIONAL:
182 outer_flush_range(
183 phys, phys + opsize);
184 break;
185 }
186 }
187
188 lineremain -= opsize;
189 /* Move to next page */
190 page_begin += PAGE_SIZE;
191
192 /* After first page, start address
193 * will be page aligned so offset
194 * is 0 */
195 offset = 0;
196
197 if (!lineremain)
198 break;
199
200 pageremain -= opsize;
201 if (!pageremain)
202 pageremain = PAGE_SIZE;
203
204 }
205 }
206 }
207}
208EXPORT_SYMBOL(c2dm_l2cache);
diff --git a/drivers/misc/gcx/gcbv/gcmain.c b/drivers/misc/gcx/gcbv/gcmain.c
index aa8be6601ba..c9d7e8feb96 100644
--- a/drivers/misc/gcx/gcbv/gcmain.c
+++ b/drivers/misc/gcx/gcbv/gcmain.c
@@ -13,9 +13,6 @@
13 */ 13 */
14 14
15#include "gcbv.h" 15#include "gcbv.h"
16#include <plat/cpu.h>
17#include <plat/omap_hwmod.h>
18
19 16
20/******************************************************************************* 17/*******************************************************************************
21 * BLTsville interface exposure. 18 * BLTsville interface exposure.
@@ -244,9 +241,10 @@ static int __init mod_init(void)
244{ 241{
245 bv_init(); 242 bv_init();
246 243
247 /* Assign BV function parameters only if SoC contains a GC core */ 244 if (gc_is_hw_present())
248 if (cpu_is_omap447x())
249 gcbv_assign(); 245 gcbv_assign();
246 else
247 GCERR("gcx hardware is not present\n");
250 248
251 return 0; 249 return 0;
252} 250}
diff --git a/drivers/misc/gcx/gccore/gcmain.c b/drivers/misc/gcx/gccore/gcmain.c
index 26939ed0e0d..2cc723451ab 100644
--- a/drivers/misc/gcx/gccore/gcmain.c
+++ b/drivers/misc/gcx/gccore/gcmain.c
@@ -17,13 +17,13 @@
17#include <linux/uaccess.h> 17#include <linux/uaccess.h>
18#include <linux/pm_runtime.h> 18#include <linux/pm_runtime.h>
19#include <linux/delay.h> 19#include <linux/delay.h>
20#include <plat/omap_gcx.h>
21#include <linux/opp.h> 20#include <linux/opp.h>
22#include <linux/io.h> 21#include <linux/io.h>
23#include <plat/omap_hwmod.h> 22#include <linux/platform_data/omap_gcx.h>
24#include <plat/omap-pm.h>
25#include "gcmain.h" 23#include "gcmain.h"
26 24
25
26
27#define GCZONE_NONE 0 27#define GCZONE_NONE 0
28#define GCZONE_ALL (~0U) 28#define GCZONE_ALL (~0U)
29#define GCZONE_INIT (1 << 0) 29#define GCZONE_INIT (1 << 0)
@@ -188,11 +188,12 @@ void gc_write_reg(unsigned int address, unsigned int data)
188 188
189static void gcpwr_enable_clock(struct gccorecontext *gccorecontext) 189static void gcpwr_enable_clock(struct gccorecontext *gccorecontext)
190{ 190{
191 bool ctxlost; 191 int ctxlost;
192 192
193 GCENTER(GCZONE_POWER); 193 GCENTER(GCZONE_POWER);
194 194
195 ctxlost = gccorecontext->plat->get_context_loss_count(gccorecontext->device); 195 ctxlost = gccorecontext->plat->get_context_loss_count(gccorecontext->device);
196 GCDBG(GCZONE_POWER, "lost count = %d\n", ctxlost);
196 197
197 if (!gccorecontext->clockenabled) { 198 if (!gccorecontext->clockenabled) {
198 /* Enable the clock. */ 199 /* Enable the clock. */
@@ -217,6 +218,7 @@ static void gcpwr_enable_clock(struct gccorecontext *gccorecontext)
217 if (ctxlost || (gccorecontext->gcpower == GCPWR_UNKNOWN)) 218 if (ctxlost || (gccorecontext->gcpower == GCPWR_UNKNOWN))
218 gcpwr_reset(gccorecontext); 219 gcpwr_reset(gccorecontext);
219 220
221
220 GCEXIT(GCZONE_POWER); 222 GCEXIT(GCZONE_POWER);
221} 223}
222 224
@@ -235,6 +237,9 @@ static void gcpwr_disable_clock(struct gccorecontext *gccorecontext)
235 237
236 /* Clock disabled. */ 238 /* Clock disabled. */
237 gccorecontext->clockenabled = false; 239 gccorecontext->clockenabled = false;
240
241 /* Reset the current pipe. */
242 gccorecontext->gcpipe = GCPWR_UNKNOWN;
238 } 243 }
239 244
240 GCDBG(GCZONE_POWER, "clock %s.\n", 245 GCDBG(GCZONE_POWER, "clock %s.\n",
@@ -249,6 +254,9 @@ static void gcpwr_scale(struct gccorecontext *gccorecontext, int index)
249 254
250 GCENTERARG(GCZONE_FREQSCALE, "index=%d\n", index); 255 GCENTERARG(GCZONE_FREQSCALE, "index=%d\n", index);
251 256
257 if (gccorecontext->opp_count == 0)
258 goto exit;
259
252 if ((index < 0) || (index >= gccorecontext->opp_count)) { 260 if ((index < 0) || (index >= gccorecontext->opp_count)) {
253 GCERR("invalid index %d.\n", index); 261 GCERR("invalid index %d.\n", index);
254 goto exit; 262 goto exit;
@@ -260,6 +268,7 @@ static void gcpwr_scale(struct gccorecontext *gccorecontext, int index)
260 goto exit; 268 goto exit;
261 } 269 }
262 270
271
263 if (gccorecontext->cur_freq == gccorecontext->opp_freqs[index]) 272 if (gccorecontext->cur_freq == gccorecontext->opp_freqs[index])
264 goto exit; 273 goto exit;
265 274
@@ -493,6 +502,13 @@ unsigned int gcpwr_get_speed(void)
493 * Public API. 502 * Public API.
494 */ 503 */
495 504
505bool gc_is_hw_present(void)
506{
507 struct gccorecontext *gccorecontext = &g_context;
508 return gccorecontext->plat->is_hw_present;
509}
510
511
496void gc_caps(struct gcicaps *gcicaps) 512void gc_caps(struct gcicaps *gcicaps)
497{ 513{
498 struct gccorecontext *gccorecontext = &g_context; 514 struct gccorecontext *gccorecontext = &g_context;
@@ -871,22 +887,30 @@ done:
871static int gc_probe(struct platform_device *pdev) 887static int gc_probe(struct platform_device *pdev)
872{ 888{
873 struct gccorecontext *gccorecontext = &g_context; 889 struct gccorecontext *gccorecontext = &g_context;
890 int ret;
874 891
875 GCENTER(GCZONE_PROBE); 892 GCENTER(GCZONE_PROBE);
876 893
877 gccorecontext->bb2ddevice = &pdev->dev; 894 gccorecontext->bb2ddevice = &pdev->dev;
878 gccorecontext->plat = (struct omap_gcx_platform_data *) 895 gccorecontext->plat = (struct omap_gcx_platform_data *)
879 pdev->dev.platform_data; 896 pdev->dev.platform_data;
897
898 if (!gccorecontext->plat->is_hw_present) {
899 GCERR("gc_probe failed. gcx hardware is not present\n");
900 return -ENODEV;
901 }
902
880 gccorecontext->regbase = gccorecontext->plat->regbase; 903 gccorecontext->regbase = gccorecontext->plat->regbase;
881 gccorecontext->irqline = platform_get_irq(pdev, pdev->id); 904 gccorecontext->irqline = platform_get_irq(pdev, pdev->id);
882 gccorecontext->device = &pdev->dev; 905 gccorecontext->device = &pdev->dev;
883 906
907
884 pm_runtime_enable(gccorecontext->device); 908 pm_runtime_enable(gccorecontext->device);
885 gccorecontext->plat->get_context_loss_count(gccorecontext->device); 909 gccorecontext->plat->get_context_loss_count(gccorecontext->device);
886 910
887 gc_probe_opp(pdev); 911 gc_probe_opp(pdev);
888 912
889 pm_runtime_get_sync(gccorecontext->device); 913 ret = pm_runtime_get_sync(gccorecontext->device);
890 914
891 gccorecontext->gcmodel = gc_read_reg(GC_CHIP_ID_Address); 915 gccorecontext->gcmodel = gc_read_reg(GC_CHIP_ID_Address);
892 gccorecontext->gcrevision = gc_read_reg(GC_CHIP_REV_Address); 916 gccorecontext->gcrevision = gc_read_reg(GC_CHIP_REV_Address);
@@ -987,12 +1011,6 @@ static int gc_init(struct gccorecontext *gccorecontext)
987 1011
988 GCENTER(GCZONE_INIT); 1012 GCENTER(GCZONE_INIT);
989 1013
990 /* check if hardware is available */
991 if (!cpu_is_omap447x()) {
992 GCDBG(GCZONE_INIT, "gcx hardware is not present\n");
993 goto exit;
994 }
995
996 /* Initialize data structutres. */ 1014 /* Initialize data structutres. */
997 GCLOCK_INIT(&gccorecontext->powerlock); 1015 GCLOCK_INIT(&gccorecontext->powerlock);
998 GCLOCK_INIT(&gccorecontext->resetlock); 1016 GCLOCK_INIT(&gccorecontext->resetlock);
@@ -1003,13 +1021,6 @@ static int gc_init(struct gccorecontext *gccorecontext)
1003 /* Pulse skipping isn't known. */ 1021 /* Pulse skipping isn't known. */
1004 gccorecontext->pulseskipping = -1; 1022 gccorecontext->pulseskipping = -1;
1005 1023
1006 /* Initialize MMU. */
1007 if (gcmmu_init(gccorecontext) != GCERR_NONE) {
1008 GCERR("failed to initialize MMU.\n");
1009 result = -EINVAL;
1010 goto fail;
1011 }
1012
1013 result = platform_driver_register(&plat_drv); 1024 result = platform_driver_register(&plat_drv);
1014 if (result < 0) { 1025 if (result < 0) {
1015 GCERR("failed to register platform driver.\n"); 1026 GCERR("failed to register platform driver.\n");
@@ -1017,6 +1028,13 @@ static int gc_init(struct gccorecontext *gccorecontext)
1017 } 1028 }
1018 gccorecontext->platdriver = true; 1029 gccorecontext->platdriver = true;
1019 1030
1031 /* Initialize MMU. */
1032 if (gcmmu_init(gccorecontext) != GCERR_NONE) {
1033 GCERR("failed to initialize MMU.\n");
1034 result = -EINVAL;
1035 goto fail;
1036 }
1037
1020#if CONFIG_HAS_EARLYSUSPEND 1038#if CONFIG_HAS_EARLYSUSPEND
1021 register_early_suspend(&early_suspend_info); 1039 register_early_suspend(&early_suspend_info);
1022#endif 1040#endif
@@ -1031,7 +1049,6 @@ static int gc_init(struct gccorecontext *gccorecontext)
1031 /* Create debugfs entry. */ 1049 /* Create debugfs entry. */
1032 gc_debug_init(); 1050 gc_debug_init();
1033 1051
1034exit:
1035 GCEXIT(GCZONE_INIT); 1052 GCEXIT(GCZONE_INIT);
1036 return 0; 1053 return 0;
1037 1054
@@ -1046,7 +1063,7 @@ static void gc_exit(struct gccorecontext *gccorecontext)
1046{ 1063{
1047 GCENTER(GCZONE_INIT); 1064 GCENTER(GCZONE_INIT);
1048 1065
1049 if (cpu_is_omap447x()) { 1066 if (gc_is_hw_present()) {
1050 /* Stop command queue thread. */ 1067 /* Stop command queue thread. */
1051 gcqueue_stop(gccorecontext); 1068 gcqueue_stop(gccorecontext);
1052 1069
@@ -1094,6 +1111,7 @@ static void __exit gc_exit_wrapper(void)
1094 GCDBG_EXIT(); 1111 GCDBG_EXIT();
1095} 1112}
1096 1113
1114
1097MODULE_LICENSE("GPL v2"); 1115MODULE_LICENSE("GPL v2");
1098MODULE_AUTHOR("www.vivantecorp.com"); 1116MODULE_AUTHOR("www.vivantecorp.com");
1099MODULE_AUTHOR("www.ti.com"); 1117MODULE_AUTHOR("www.ti.com");
diff --git a/drivers/misc/gcx/gccore/gcmmu.c b/drivers/misc/gcx/gccore/gcmmu.c
index 31a873a09ac..2bfe52d7e0c 100644
--- a/drivers/misc/gcx/gccore/gcmmu.c
+++ b/drivers/misc/gcx/gccore/gcmmu.c
@@ -45,6 +45,8 @@ GCDBG_FILTERDEF(mmu, GCZONE_NONE,
45 "dumpunmap") 45 "dumpunmap")
46 46
47 47
48#define USE_CACHED_MASTER 0
49#define USE_CACHED_SLAVE 0
48/******************************************************************************* 50/*******************************************************************************
49 * Internal definitions. 51 * Internal definitions.
50 */ 52 */
@@ -180,7 +182,11 @@ static enum gcerror allocate_slave(struct gcmmucontext *gcmmucontext,
180 prealloccount); 182 prealloccount);
181 183
182 /* Allocate slave table pool. */ 184 /* Allocate slave table pool. */
185#if USE_CACHED_SLAVE
183 gcerror = gc_alloc_cached(&block->pages, preallocsize); 186 gcerror = gc_alloc_cached(&block->pages, preallocsize);
187#else
188 gcerror = gc_alloc_noncached(&block->pages, preallocsize);
189#endif
184 if (gcerror != GCERR_NONE) { 190 if (gcerror != GCERR_NONE) {
185 GCERR("failed to allocate slave page table\n"); 191 GCERR("failed to allocate slave page table\n");
186 gcerror = GCERR_SETGRP(gcerror, GCERR_MMU_STLB_ALLOC); 192 gcerror = GCERR_SETGRP(gcerror, GCERR_MMU_STLB_ALLOC);
@@ -218,11 +224,16 @@ static enum gcerror allocate_slave(struct gcmmucontext *gcmmucontext,
218 ((unsigned char *) logical + GCMMU_STLB_SIZE); 224 ((unsigned char *) logical + GCMMU_STLB_SIZE);
219 } 225 }
220 226
227#if USE_CACHED_MASTER
221 /* Flush CPU cache. */ 228 /* Flush CPU cache. */
222 gc_flush_region(gcmmucontext->master.physical, 229 gc_flush_region(gcmmucontext->master.physical,
223 gcmmucontext->master.logical, 230 gcmmucontext->master.logical,
224 index.loc.mtlb * sizeof(unsigned int), 231 index.loc.mtlb * sizeof(unsigned int),
225 prealloccount * sizeof(unsigned int)); 232 prealloccount * sizeof(unsigned int));
233#else
234 mb();
235#endif
236
226 237
227 GCEXIT(GCZONE_MAPPING); 238 GCEXIT(GCZONE_MAPPING);
228 return GCERR_NONE; 239 return GCERR_NONE;
@@ -499,7 +510,11 @@ enum gcerror gcmmu_create_context(struct gccorecontext *gccorecontext,
499 gcmmucontext->pid = pid; 510 gcmmucontext->pid = pid;
500 511
501 /* Allocate MTLB table. */ 512 /* Allocate MTLB table. */
513#if USE_CACHED_MASTER
502 gcerror = gc_alloc_cached(&gcmmucontext->master, GCMMU_MTLB_SIZE); 514 gcerror = gc_alloc_cached(&gcmmucontext->master, GCMMU_MTLB_SIZE);
515#else
516 gcerror = gc_alloc_noncached(&gcmmucontext->master, GCMMU_MTLB_SIZE);
517#endif
503 if (gcerror != GCERR_NONE) { 518 if (gcerror != GCERR_NONE) {
504 gcerror = GCERR_SETGRP(gcerror, GCERR_MMU_MTLB_ALLOC); 519 gcerror = GCERR_SETGRP(gcerror, GCERR_MMU_MTLB_ALLOC);
505 goto exit; 520 goto exit;
@@ -583,14 +598,26 @@ enum gcerror gcmmu_destroy_context(struct gccorecontext *gccorecontext,
583 598
584 /* Free slave tables. */ 599 /* Free slave tables. */
585 while (gcmmucontext->slavealloc != NULL) { 600 while (gcmmucontext->slavealloc != NULL) {
601#if USE_CACHED_SLAVE
586 gc_free_cached(&gcmmucontext->slavealloc->pages); 602 gc_free_cached(&gcmmucontext->slavealloc->pages);
603#else
604 gc_free_noncached(&gcmmucontext->slavealloc->pages);
605#endif
587 nextblock = gcmmucontext->slavealloc->next; 606 nextblock = gcmmucontext->slavealloc->next;
588 kfree(gcmmucontext->slavealloc); 607 kfree(gcmmucontext->slavealloc);
589 gcmmucontext->slavealloc = nextblock; 608 gcmmucontext->slavealloc = nextblock;
590 } 609 }
591 610
611 /* Reset the master table. */
612 if (gcmmu->master == gcmmucontext->mmuconfig.raw)
613 gcmmu->master = ~0U;
614
592 /* Free the master table. */ 615 /* Free the master table. */
616#if USE_CACHED_MASTER
593 gc_free_cached(&gcmmucontext->master); 617 gc_free_cached(&gcmmucontext->master);
618#else
619 gc_free_noncached(&gcmmucontext->master);
620#endif
594 621
595 /* Free arenas. */ 622 /* Free arenas. */
596 GCLOCK(&gcmmu->lock); 623 GCLOCK(&gcmmu->lock);
@@ -877,10 +904,14 @@ enum gcerror gcmmu_map(struct gccorecontext *gccorecontext,
877 | GCMMU_STLB_EXCEPTION 904 | GCMMU_STLB_EXCEPTION
878 | GCMMU_STLB_WRITEABLE; 905 | GCMMU_STLB_WRITEABLE;
879 906
907#if USE_CACHED_SLAVE
880 /* Flush CPU cache. */ 908 /* Flush CPU cache. */
881 gc_flush_region(slave->physical, slave->logical, 909 gc_flush_region(slave->physical, slave->logical,
882 index.loc.stlb * sizeof(unsigned int), 910 index.loc.stlb * sizeof(unsigned int),
883 allocated * sizeof(unsigned int)); 911 allocated * sizeof(unsigned int));
912#else
913 mb();
914#endif
884 915
885 GCDBG(GCZONE_MAPPING, "allocated %d pages at %d.%d\n", 916 GCDBG(GCZONE_MAPPING, "allocated %d pages at %d.%d\n",
886 allocated, index.loc.mtlb, index.loc.stlb); 917 allocated, index.loc.mtlb, index.loc.stlb);
@@ -1029,10 +1060,14 @@ enum gcerror gcmmu_unmap(struct gccorecontext *gccorecontext,
1029 for (i = 0; i < freed; i += 1) 1060 for (i = 0; i < freed; i += 1)
1030 *stlblogical++ = GCMMU_STLB_ENTRY_VACANT; 1061 *stlblogical++ = GCMMU_STLB_ENTRY_VACANT;
1031 1062
1063#if USE_CACHED_SLAVE
1032 /* Flush CPU cache. */ 1064 /* Flush CPU cache. */
1033 gc_flush_region(slave->physical, slave->logical, 1065 gc_flush_region(slave->physical, slave->logical,
1034 index.loc.stlb * sizeof(unsigned int), 1066 index.loc.stlb * sizeof(unsigned int),
1035 freed * sizeof(unsigned int)); 1067 freed * sizeof(unsigned int));
1068#else
1069 mb();
1070#endif
1036 1071
1037 /* Advance. */ 1072 /* Advance. */
1038 slave += 1; 1073 slave += 1;
diff --git a/drivers/misc/gcx/gccore/gcqueue.c b/drivers/misc/gcx/gccore/gcqueue.c
index c5a1921c64e..32e7d9546fa 100644
--- a/drivers/misc/gcx/gccore/gcqueue.c
+++ b/drivers/misc/gcx/gccore/gcqueue.c
@@ -772,6 +772,7 @@ static int gccmdthread(void *_gccorecontext)
772 GCSETFIELD(0, GCREG_CMD_BUFFER_CTRL, 772 GCSETFIELD(0, GCREG_CMD_BUFFER_CTRL,
773 PREFETCH, headcmdbuf->count)); 773 PREFETCH, headcmdbuf->count));
774 774
775 GCDBG(GCZONE_THREAD, "queue restarted.\n");
775 GCUNLOCK(&gcqueue->queuelock); 776 GCUNLOCK(&gcqueue->queuelock);
776 continue; 777 continue;
777 } 778 }
@@ -821,6 +822,7 @@ static int gccmdthread(void *_gccorecontext)
821 GCDBG(GCZONE_THREAD, 822 GCDBG(GCZONE_THREAD,
822 "current location @ 0x%08X.\n", 823 "current location @ 0x%08X.\n",
823 dmapc); 824 dmapc);
825 GCGPUSTATUS();
824 GCUNLOCK(&gcqueue->queuelock); 826 GCUNLOCK(&gcqueue->queuelock);
825 continue; 827 continue;
826 } 828 }
@@ -846,6 +848,7 @@ static int gccmdthread(void *_gccorecontext)
846 if (!list_empty(&gcqueue->queue)) { 848 if (!list_empty(&gcqueue->queue)) {
847 GCDBG(GCZONE_THREAD, 849 GCDBG(GCZONE_THREAD,
848 "aborting shutdown to process events\n"); 850 "aborting shutdown to process events\n");
851 GCGPUSTATUS();
849 GCUNLOCK(&gcqueue->queuelock); 852 GCUNLOCK(&gcqueue->queuelock);
850 continue; 853 continue;
851 } 854 }
diff --git a/drivers/misc/gcx/gcioctl/gcif.c b/drivers/misc/gcx/gcioctl/gcif.c
index 262522c5084..267ada8bab8 100644
--- a/drivers/misc/gcx/gcioctl/gcif.c
+++ b/drivers/misc/gcx/gcioctl/gcif.c
@@ -945,10 +945,12 @@ static struct device *dev_object;
945 945
946static int dev_open(struct inode *inode, struct file *file) 946static int dev_open(struct inode *inode, struct file *file)
947{ 947{
948 if (cpu_is_omap447x()) 948 if (gc_is_hw_present()) {
949 return 0; 949 return 0;
950 else 950 } else {
951 return -1; 951 GCERR("gcx hardware is not present\n");
952 return -ENODEV;
953 }
952} 954}
953 955
954static int dev_release(struct inode *inode, struct file *file) 956static int dev_release(struct inode *inode, struct file *file)
diff --git a/include/linux/cache-2dmanager.h b/include/linux/cache-2dmanager.h
new file mode 100644
index 00000000000..2f452da63ee
--- /dev/null
+++ b/include/linux/cache-2dmanager.h
@@ -0,0 +1,62 @@
1/*
2 * cache-2dmanager.h
3 *
4 * Copyright (C) 2011-2012 Texas Instruments Corporation.
5 *
6 * This package is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
11 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
12 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13 */
14
15#ifndef CACHE_2DMANAGER_H_
16#define CACHE_2DMANAGER_H_
17
18#include "slab.h"
19
20#ifdef CONFIG_ARCH_OMAP4
21#define L1CACHE_SIZE 32768
22#define L2CACHE_SIZE 1048576
23
24#define L1THRESHOLD L1CACHE_SIZE
25#define L2THRESHOLD L2CACHE_SIZE
26#else
27#error Cache configuration must be specified.
28#endif
29
30struct c2dmrgn {
31 char *start; /* addr of upper left of rect */
32 size_t span; /* bytes to be operated on per line */
33 size_t lines; /* lines to be operated on */
34 long stride; /* bytes per line */
35};
36
37/*
38 * c2dm_l1cache(count, rgns, dir)
39 *
40 * L1 Cache operations in 2D
41 *
42 * - count - number of regions
43 * - rgns - array of regions
44 * - dir - cache operation direction
45 *
46 */
47void c2dm_l1cache(int count, struct c2dmrgn rgns[], int dir);
48
49/*
50 * c2dm_l2cache(count, rgns, dir)
51 *
52 * L2 Cache operations in 2D
53 *
54 * - count - number of regions
55 * - rgns - array of regions
56 * - dir - cache operation direction
57 *
58 */
59void c2dm_l2cache(int count, struct c2dmrgn rgns[], int dir);
60
61
62#endif /* CACHE_2DMANAGER_H_ */
diff --git a/include/linux/gccore.h b/include/linux/gccore.h
index ce9ed4fb75e..ae64f2f75c6 100644
--- a/include/linux/gccore.h
+++ b/include/linux/gccore.h
@@ -18,6 +18,10 @@
18#include "sched.h" 18#include "sched.h"
19#include "gcioctl.h" 19#include "gcioctl.h"
20 20
21
22/* Hw availability query */
23bool gc_is_hw_present(void);
24
21/* Capability query. */ 25/* Capability query. */
22void gc_caps(struct gcicaps *gcicaps); 26void gc_caps(struct gcicaps *gcicaps);
23 27
diff --git a/include/linux/platform_data/omap_gcx.h b/include/linux/platform_data/omap_gcx.h
new file mode 100644
index 00000000000..82abd8a97fc
--- /dev/null
+++ b/include/linux/platform_data/omap_gcx.h
@@ -0,0 +1,33 @@
1/*
2 * arch/arm/plat-omap/include/plat/omap_gcx.h
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19#ifndef OMAP_GCX_H
20#define OMAP_GCX_H
21
22struct omap_gcx_platform_data {
23 bool is_hw_present;
24 void *regbase;
25 /*bool (*was_context_lost)(struct device *dev);*/
26 int (*get_context_loss_count)(struct device *dev);
27 /* device scale */
28 int (*scale_dev)(struct device *dev, unsigned long freq);
29 /* bandwith */
30 int (*set_bw)(struct device *dev, unsigned long v);
31};
32
33#endif