ARM: tegra: iovmm: Replace IOVMM backend with IOMMU
[linux-2.6.git] / arch / arm / mach-tegra / include / mach / iovmm.h
1 /*
2  * arch/arm/mach-tegra/include/mach/iovmm.h
3  *
4  * Copyright (c) 2010-2012, NVIDIA Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed i the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20
21 #include <linux/list.h>
22 #include <linux/platform_device.h>
23 #include <linux/miscdevice.h>
24 #include <linux/rbtree.h>
25 #include <linux/rwsem.h>
26 #include <linux/spinlock.h>
27 #include <linux/types.h>
28
29 #ifndef _MACH_TEGRA_IOVMM_H_
30 #define _MACH_TEGRA_IOVMM_H_
31
32 typedef u32 tegra_iovmm_addr_t;
33
34 struct tegra_iovmm_device_ops;
35
36 /*
37  * each I/O virtual memory manager unit should register a device with
38  * the iovmm system
39  */
40 struct tegra_iovmm_device {
41         struct tegra_iovmm_device_ops   *ops;
42         const char                      *name;
43         struct list_head                list;
44         int                             pgsize_bits;
45 };
46
47 /*
48  * tegra_iovmm_domain serves a purpose analagous to mm_struct as defined in
49  * <linux/mm_types.h> - it defines a virtual address space within which
50  * tegra_iovmm_areas can be created.
51  */
52 struct tegra_iovmm_domain {
53         atomic_t                clients;
54         atomic_t                locks;
55         spinlock_t              block_lock;  /* RB-tree for iovmm_area blocks */
56         unsigned long           flags;
57         wait_queue_head_t       delay_lock;  /* when lock_client fails */
58         struct rw_semaphore     map_lock;
59         struct rb_root          all_blocks;  /* ordered by address */
60         struct rb_root          free_blocks; /* ordered by size */
61         struct tegra_iovmm_device *dev;
62 };
63
64 /*
65  * tegra_iovmm_client is analagous to an individual task in the task group
66  * which owns an mm_struct.
67  */
68
69 struct iovmm_share_group;
70
71 #if !defined(CONFIG_IOMMU_API)
72
73 struct tegra_iovmm_client {
74         const char                      *name;
75         unsigned long                   flags;
76         struct iovmm_share_group        *group;
77         struct tegra_iovmm_domain       *domain;
78         struct miscdevice               *misc_dev;
79         struct list_head                list;
80 };
81
82 /*
83  * tegra_iovmm_area serves a purpose analagous to vm_area_struct as defined
84  * in <linux/mm_types.h> - it defines a virtual memory area which can be
85  * mapped to physical memory by a client-provided mapping function. */
86
87 struct tegra_iovmm_area {
88         struct tegra_iovmm_domain       *domain;
89         tegra_iovmm_addr_t              iovm_start;
90         size_t                          iovm_length;
91         pgprot_t                        pgprot;
92         struct tegra_iovmm_area_ops     *ops;
93 };
94
95 #else   /* CONFIG_IOMMU_API */
96
97 /*
98  * To replace IOVMM with IOMMU backend
99  */
100
101 struct tegra_iovmm_client {
102         struct device *dev;
103 };
104
105 struct tegra_iovmm_area {
106         dma_addr_t              iovm_start;
107         size_t                  iovm_length;
108         pgprot_t                pgprot;
109         struct device           *dev;
110 };
111
112 #endif /* CONFIG_IOMMU_API */
113
114 struct tegra_iovmm_device_ops {
115         /* maps a VMA using the page residency functions provided by the VMA */
116         int (*map)(struct tegra_iovmm_domain *domain,
117                 struct tegra_iovmm_area *io_vma);
118         /* marks all PTEs in a VMA as invalid; decommits the virtual addres
119          * space (potentially freeing PDEs when decommit is true.) */
120         void (*unmap)(struct tegra_iovmm_domain *domain,
121                 struct tegra_iovmm_area *io_vma, bool decommit);
122         void (*map_pfn)(struct tegra_iovmm_domain *domain,
123                 struct tegra_iovmm_area *io_vma,
124                 unsigned long offs, unsigned long pfn);
125         /*
126          * ensures that a domain is resident in the hardware's mapping region
127          * so that it may be used by a client
128          */
129         int (*lock_domain)(struct tegra_iovmm_domain *domain,
130                 struct tegra_iovmm_client *client);
131         void (*unlock_domain)(struct tegra_iovmm_domain *domain,
132                 struct tegra_iovmm_client *client);
133         /*
134          * allocates a vmm_domain for the specified client; may return the same
135          * domain for multiple clients
136          */
137         struct tegra_iovmm_domain* (*alloc_domain)(
138                 struct tegra_iovmm_device *dev,
139                 struct tegra_iovmm_client *client);
140         void (*free_domain)(struct tegra_iovmm_domain *domain,
141                 struct tegra_iovmm_client *client);
142         int (*suspend)(struct tegra_iovmm_device *dev);
143         void (*resume)(struct tegra_iovmm_device *dev);
144 };
145
146 struct tegra_iovmm_area_ops {
147         /*
148          * ensures that the page of data starting at the specified offset
149          * from the start of the iovma is resident and pinned for use by
150          * DMA, returns the system pfn, or an invalid pfn if the
151          * operation fails.
152          */
153         unsigned long (*lock_makeresident)(struct tegra_iovmm_area *area,
154                 tegra_iovmm_addr_t offs);
155         /* called when the page is unmapped from the I/O VMA */
156         void (*release)(struct tegra_iovmm_area *area, tegra_iovmm_addr_t offs);
157 };
158
159 #ifdef CONFIG_TEGRA_IOVMM
160 /*
161  * called by clients to allocate an I/O VMM client mapping context which
162  * will be shared by all clients in the same share_group
163  */
164 struct tegra_iovmm_client *__tegra_iovmm_alloc_client(const char *name,
165         const char *share_group, struct miscdevice *misc_dev);
166
167 static inline struct tegra_iovmm_client *tegra_iovmm_alloc_client(
168         struct device *dev, const char *share_group,
169         struct miscdevice *misc_dev)
170 {
171         return __tegra_iovmm_alloc_client(dev_name(dev), share_group, misc_dev);
172 }
173
174 size_t tegra_iovmm_get_vm_size(struct tegra_iovmm_client *client);
175
176 void tegra_iovmm_free_client(struct tegra_iovmm_client *client);
177
178 /*
179  * called by clients to ensure that their mapping context is resident
180  * before performing any DMA operations addressing I/O VMM regions.
181  * client_lock may return -EINTR.
182  */
183 int tegra_iovmm_client_lock(struct tegra_iovmm_client *client);
184 int tegra_iovmm_client_trylock(struct tegra_iovmm_client *client);
185
186 /* called by clients after DMA operations are complete */
187 void tegra_iovmm_client_unlock(struct tegra_iovmm_client *client);
188
189 /*
190  * called by clients to allocate a new iovmm_area and reserve I/O virtual
191  * address space for it. if ops is NULL, clients should subsequently call
192  * tegra_iovmm_vm_map_pages and/or tegra_iovmm_vm_insert_pfn to explicitly
193  * map the I/O virtual address to an OS-allocated page or physical address,
194  * respectively. VM operations may be called before this call returns
195  */
196 struct tegra_iovmm_area *tegra_iovmm_create_vm(
197         struct tegra_iovmm_client *client, struct tegra_iovmm_area_ops *ops,
198         size_t size, size_t align, pgprot_t pgprot, unsigned long iovm_start);
199
200 /*
201  * called by clients to "zap" an iovmm_area, and replace all mappings
202  * in it with invalid ones, without freeing the virtual address range
203  */
204 void tegra_iovmm_zap_vm(struct tegra_iovmm_area *vm);
205
206 /*
207  * after zapping a demand-loaded iovmm_area, the client should unzap it
208  * to allow the VMM device to remap the page range.
209  */
210 void tegra_iovmm_unzap_vm(struct tegra_iovmm_area *vm);
211
212 /* called by clients to return an iovmm_area to the free pool for the domain */
213 void tegra_iovmm_free_vm(struct tegra_iovmm_area *vm);
214
215 /* returns size of largest free iovm block */
216 size_t tegra_iovmm_get_max_free(struct tegra_iovmm_client *client);
217
218 /*
219  * called by client software to map the page-aligned I/O address vaddr to
220  * a specific physical address pfn. I/O VMA should have been created with
221  * a NULL tegra_iovmm_area_ops structure.
222  */
223 void tegra_iovmm_vm_insert_pfn(struct tegra_iovmm_area *area,
224         tegra_iovmm_addr_t vaddr, unsigned long pfn);
225
226 /*
227  * called by clients to return the iovmm_area containing addr, or NULL if
228  * addr has not been allocated. caller should call tegra_iovmm_area_put when
229  * finished using the returned pointer
230  */
231 struct tegra_iovmm_area *tegra_iovmm_find_area_get(
232         struct tegra_iovmm_client *client, tegra_iovmm_addr_t addr);
233
234 struct tegra_iovmm_area *tegra_iovmm_area_get(struct tegra_iovmm_area *vm);
235 void tegra_iovmm_area_put(struct tegra_iovmm_area *vm);
236
237 /* called by drivers to initialize a tegra_iovmm_domain structure */
238 int tegra_iovmm_domain_init(struct tegra_iovmm_domain *domain,
239         struct tegra_iovmm_device *dev, tegra_iovmm_addr_t start,
240         tegra_iovmm_addr_t end);
241
242 /* called by drivers to register an I/O VMM device with the system */
243 int tegra_iovmm_register(struct tegra_iovmm_device *dev);
244
245 /* called by drivers to remove an I/O VMM device from the system */
246 int tegra_iovmm_unregister(struct tegra_iovmm_device *dev);
247
248 #else /* CONFIG_TEGRA_IOVMM */
249
250 static inline struct tegra_iovmm_client *tegra_iovmm_alloc_client(
251         const char *name, const char *share_group, struct miscdevice *misc_dev)
252 {
253         return NULL;
254 }
255
256 static inline size_t tegra_iovmm_get_vm_size(struct tegra_iovmm_client *client)
257 {
258         return 0;
259 }
260
261 static inline void tegra_iovmm_free_client(struct tegra_iovmm_client *client)
262 {
263 }
264
265 static inline int tegra_iovmm_client_lock(struct tegra_iovmm_client *client)
266 {
267         return 0;
268 }
269
270 static inline int tegra_iovmm_client_trylock(struct tegra_iovmm_client *client)
271 {
272         return 0;
273 }
274
275 static inline void tegra_iovmm_client_unlock(struct tegra_iovmm_client *client)
276 {
277 }
278
279 static inline struct tegra_iovmm_area *tegra_iovmm_create_vm(
280         struct tegra_iovmm_client *client, struct tegra_iovmm_area_ops *ops,
281         size_t size, size_t align, pgprot_t pgprot, unsigned long iovm_start)
282 {
283         return NULL;
284 }
285
286 static inline void tegra_iovmm_zap_vm(struct tegra_iovmm_area *vm)
287 {
288 }
289
290 static inline void tegra_iovmm_unzap_vm(struct tegra_iovmm_area *vm)
291 {
292 }
293
294 static inline void tegra_iovmm_free_vm(struct tegra_iovmm_area *vm)
295 {
296 }
297
298 static inline size_t tegra_iovmm_get_max_free(struct tegra_iovmm_client *client)
299 {
300         return 0;
301 }
302
303 static inline void tegra_iovmm_vm_insert_pfn(struct tegra_iovmm_area *area,
304         tegra_iovmm_addr_t vaddr, unsigned long pfn)
305 {
306 }
307
308 static inline struct tegra_iovmm_area *tegra_iovmm_find_area_get(
309         struct tegra_iovmm_client *client, tegra_iovmm_addr_t addr)
310 {
311         return NULL;
312 }
313
314 static inline struct tegra_iovmm_area *tegra_iovmm_area_get(
315         struct tegra_iovmm_area *vm)
316 {
317         return NULL;
318 }
319
320 static inline void tegra_iovmm_area_put(struct tegra_iovmm_area *vm)
321 {
322 }
323
324 static inline int tegra_iovmm_domain_init(struct tegra_iovmm_domain *domain,
325         struct tegra_iovmm_device *dev, tegra_iovmm_addr_t start,
326         tegra_iovmm_addr_t end)
327 {
328         return 0;
329 }
330
331 static inline int tegra_iovmm_register(struct tegra_iovmm_device *dev)
332 {
333         return 0;
334 }
335
336 static inline int tegra_iovmm_unregister(struct tegra_iovmm_device *dev)
337 {
338         return 0;
339 }
340
341 static inline int tegra_iovmm_suspend(void)
342 {
343         return 0;
344 }
345
346 static inline void tegra_iovmm_resume(void)
347 {
348 }
349
350 #ifdef CONFIG_IOMMU_API
351 /*
352  * Replace tegra_iovmm_*() with tegra_iommu_*() helpers
353  */
354 #include <linux/dma-mapping.h>
355 #include <linux/dma-direction.h>
356
357 #include <asm/dma-iommu.h>
358
359 #define tegra_iovmm_alloc_client(d, s, m)       tegra_iommu_alloc_client(d)
360 #define tegra_iovmm_free_client(c)              tegra_iommu_free_client(c)
361
362 #define tegra_iovmm_create_vm(c, o, s, a, p, i)         \
363         tegra_iommu_create_vm((c)->dev, i, s, p)
364 #define tegra_iovmm_free_vm(v)  tegra_iommu_free_vm(v)
365
366 #define tegra_iovmm_get_vm_size(c)      arm_iommu_iova_avail((c)->dev)
367 #define tegra_iovmm_get_max_free(c)     arm_iommu_iova_max_free((c)->dev)
368
369 #define tegra_iovmm_vm_insert_pfn(a, v, n)                              \
370         dma_map_page_at((a)->dev, pfn_to_page(n), v, 0, PAGE_SIZE, DMA_NONE);
371
372 struct tegra_iovmm_area *tegra_iommu_create_vm(struct device *dev,
373                        dma_addr_t req, size_t size, pgprot_t prot);
374
375 void tegra_iommu_free_vm(struct tegra_iovmm_area *area);
376
377 struct tegra_iovmm_client *tegra_iommu_alloc_client(struct device *dev);
378
379 void tegra_iommu_free_client(struct tegra_iovmm_client *client);
380
381 #endif /* CONFIG_IOMMU_API */
382 #endif /* CONFIG_TEGRA_IOVMM */
383 #endif /* _MACH_TEGRA_IOVMM_H_*/