aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Yen2012-12-24 06:59:51 -0600
committerSundar Raman2013-07-25 09:18:49 -0500
commit99f5cb085dccd1eb095e2858484f64c23bb86e5a (patch)
tree1ab4d6400b032facb164c99f83980e4a3b22c04a
parent00e93c003d4748df442f6d2a5c259941bc47202c (diff)
downloadkernel-video-99f5cb085dccd1eb095e2858484f64c23bb86e5a.tar.gz
kernel-video-99f5cb085dccd1eb095e2858484f64c23bb86e5a.tar.xz
kernel-video-99f5cb085dccd1eb095e2858484f64c23bb86e5a.zip
gc320: OMAP4: Adding cache-2dmanager
Based on k3.0 commit: p-android-omap-3.0: 43eb373199a [Jack Yen <jyen@ti.com>] Change-Id: I7e43de75a20a1cead49e902a7fedad9d4f568855 Signed-off-by: Jack Yen <jyen@ti.com> Signed-off-by: Volodymyr Mieshkov <volodymyr.mieshkov@ti.com> Signed-off-by: Sundar Raman <sunds@ti.com>
-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--include/linux/cache-2dmanager.h62
4 files changed, 279 insertions, 0 deletions
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/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_ */