[ARM/tegra] Add Tegra3 support
[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, 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 #if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
33 typedef u32 tegra_iovmm_addr_t;
34 #else
35 #error "Unsupported tegra architecture family"
36 #endif
37
38 struct tegra_iovmm_device_ops;
39
40 /* each I/O virtual memory manager unit should register a device with
41  * the iovmm system
42  */
43 struct tegra_iovmm_device {
44         struct tegra_iovmm_device_ops   *ops;
45         const char                      *name;
46         struct list_head                list;
47         int                             pgsize_bits;
48 };
49
50 /* tegra_iovmm_domain serves a purpose analagous to mm_struct as defined in
51  * <linux/mm_types.h> - it defines a virtual address space within which
52  * tegra_iovmm_areas can be created.
53  */
54 struct tegra_iovmm_domain {
55         atomic_t                clients;
56         atomic_t                locks;
57         spinlock_t              block_lock;
58         unsigned long           flags;
59         wait_queue_head_t       delay_lock;  /* when lock_client fails */
60         struct rw_semaphore     map_lock;
61         struct rb_root          all_blocks;  /* ordered by address */
62         struct rb_root          free_blocks; /* ordered by size */
63         struct tegra_iovmm_device *dev;
64 };
65
66 /* tegra_iovmm_client is analagous to an individual task in the task group
67  * which owns an mm_struct.
68  */
69
70 struct iovmm_share_group;
71
72 struct tegra_iovmm_client {
73         const char                      *name;
74         unsigned long                   flags;
75         struct iovmm_share_group        *group;
76         struct tegra_iovmm_domain       *domain;
77         struct miscdevice               *misc_dev;
78         struct list_head                list;
79 };
80
81 /* tegra_iovmm_area serves a purpose analagous to vm_area_struct as defined
82  * in <linux/mm_types.h> - it defines a virtual memory area which can be
83  * mapped to physical memory by a client-provided mapping function. */
84
85 struct tegra_iovmm_area {
86         struct tegra_iovmm_domain       *domain;
87         tegra_iovmm_addr_t              iovm_start;
88         tegra_iovmm_addr_t              iovm_length;
89         pgprot_t                        pgprot;
90         struct tegra_iovmm_area_ops     *ops;
91 };
92
93 struct tegra_iovmm_device_ops {
94         /* maps a VMA using the page residency functions provided by the VMA */
95         int (*map)(struct tegra_iovmm_domain *domain,
96                 struct tegra_iovmm_area *io_vma);
97         /* marks all PTEs in a VMA as invalid; decommits the virtual addres
98          * space (potentially freeing PDEs when decommit is true.) */
99         void (*unmap)(struct tegra_iovmm_domain *domain,
100                 struct tegra_iovmm_area *io_vma, bool decommit);
101         void (*map_pfn)(struct tegra_iovmm_domain *domain,
102                 struct tegra_iovmm_area *io_vma,
103                 tegra_iovmm_addr_t offs, unsigned long pfn);
104         /* ensures that a domain is resident in the hardware's mapping region
105          * so that it may be used by a client */
106         int (*lock_domain)(struct tegra_iovmm_domain *domain,
107                 struct tegra_iovmm_client *client);
108         void (*unlock_domain)(struct tegra_iovmm_domain *domain,
109                 struct tegra_iovmm_client *client);
110         /* allocates a vmm_domain for the specified client; may return the same
111          * domain for multiple clients */
112         struct tegra_iovmm_domain* (*alloc_domain)(
113                 struct tegra_iovmm_device *dev,
114                 struct tegra_iovmm_client *client);
115         void (*free_domain)(struct tegra_iovmm_domain *domain,
116                 struct tegra_iovmm_client *client);
117         int (*suspend)(struct tegra_iovmm_device *dev);
118         void (*resume)(struct tegra_iovmm_device *dev);
119 };
120
121 struct tegra_iovmm_area_ops {
122         /* ensures that the page of data starting at the specified offset
123          * from the start of the iovma is resident and pinned for use by
124          * DMA, returns the system pfn, or an invalid pfn if the
125          * operation fails. */
126         unsigned long (*lock_makeresident)(struct tegra_iovmm_area *area,
127                 tegra_iovmm_addr_t offs);
128         /* called when the page is unmapped from the I/O VMA */
129         void (*release)(struct tegra_iovmm_area *area, tegra_iovmm_addr_t offs);
130 };
131
132 #ifdef CONFIG_TEGRA_IOVMM
133 /* called by clients to allocate an I/O VMM client mapping context which
134  * will be shared by all clients in the same share_group */
135 struct tegra_iovmm_client *tegra_iovmm_alloc_client(const char *name,
136         const char *share_group, struct miscdevice *misc_dev);
137
138 size_t tegra_iovmm_get_vm_size(struct tegra_iovmm_client *client);
139
140 void tegra_iovmm_free_client(struct tegra_iovmm_client *client);
141
142 /* called by clients to ensure that their mapping context is resident
143  * before performing any DMA operations addressing I/O VMM regions.
144  * client_lock may return -EINTR. */
145 int tegra_iovmm_client_lock(struct tegra_iovmm_client *client);
146 int tegra_iovmm_client_trylock(struct tegra_iovmm_client *client);
147
148 /* called by clients after DMA operations are complete */
149 void tegra_iovmm_client_unlock(struct tegra_iovmm_client *client);
150
151 /* called by clients to allocate a new iovmm_area and reserve I/O virtual
152  * address space for it. if ops is NULL, clients should subsequently call
153  * tegra_iovmm_vm_map_pages and/or tegra_iovmm_vm_insert_pfn to explicitly
154  * map the I/O virtual address to an OS-allocated page or physical address,
155  * respectively. VM operations may be called before this call returns */
156 struct tegra_iovmm_area *tegra_iovmm_create_vm(
157         struct tegra_iovmm_client *client, struct tegra_iovmm_area_ops *ops,
158         unsigned long size, pgprot_t pgprot);
159
160 /* called by clients to "zap" an iovmm_area, and replace all mappings
161  * in it with invalid ones, without freeing the virtual address range */
162 void tegra_iovmm_zap_vm(struct tegra_iovmm_area *vm);
163
164 /* after zapping a demand-loaded iovmm_area, the client should unzap it
165  * to allow the VMM device to remap the page range. */
166 void tegra_iovmm_unzap_vm(struct tegra_iovmm_area *vm);
167
168 /* called by clients to return an iovmm_area to the free pool for the domain */
169 void tegra_iovmm_free_vm(struct tegra_iovmm_area *vm);
170
171 /* called by client software to map the page-aligned I/O address vaddr to
172  * a specific physical address pfn. I/O VMA should have been created with
173  * a NULL tegra_iovmm_area_ops structure. */
174 void tegra_iovmm_vm_insert_pfn(struct tegra_iovmm_area *area,
175         tegra_iovmm_addr_t vaddr, unsigned long pfn);
176
177 /* called by clients to return the iovmm_area containing addr, or NULL if
178  * addr has not been allocated. caller should call tegra_iovmm_put_area when
179  * finished using the returned pointer */
180 struct tegra_iovmm_area *tegra_iovmm_find_area_get(
181         struct tegra_iovmm_client *client, tegra_iovmm_addr_t addr);
182
183 struct tegra_iovmm_area *tegra_iovmm_area_get(struct tegra_iovmm_area *vm);
184 void tegra_iovmm_area_put(struct tegra_iovmm_area *vm);
185
186 /* called by drivers to initialize a tegra_iovmm_domain structure */
187 int tegra_iovmm_domain_init(struct tegra_iovmm_domain *domain,
188         struct tegra_iovmm_device *dev, tegra_iovmm_addr_t start,
189         tegra_iovmm_addr_t end);
190
191 /* called by drivers to register an I/O VMM device with the system */
192 int tegra_iovmm_register(struct tegra_iovmm_device *dev);
193
194 /* called by drivers to remove an I/O VMM device from the system */
195 int tegra_iovmm_unregister(struct tegra_iovmm_device *dev);
196
197 #else /* CONFIG_TEGRA_IOVMM */
198
199 static inline struct tegra_iovmm_client *tegra_iovmm_alloc_client(
200         const char *name, const char *share_group, struct miscdevice *misc_dev)
201 {
202         return NULL;
203 }
204
205 static inline size_t tegra_iovmm_get_vm_size(struct tegra_iovmm_client *client)
206 {
207         return 0;
208 }
209
210 static inline void tegra_iovmm_free_client(struct tegra_iovmm_client *client)
211 {}
212
213 static inline int tegra_iovmm_client_lock(struct tegra_iovmm_client *client)
214 {
215         return 0;
216 }
217
218 static inline int tegra_iovmm_client_trylock(struct tegra_iovmm_client *client)
219 {
220         return 0;
221 }
222
223 static inline void tegra_iovmm_client_unlock(struct tegra_iovmm_client *client)
224 {}
225
226 static inline struct tegra_iovmm_area *tegra_iovmm_create_vm(
227         struct tegra_iovmm_client *client, struct tegra_iovmm_area_ops *ops,
228         unsigned long size, pgprot_t pgprot)
229 {
230         return NULL;
231 }
232
233 static inline void tegra_iovmm_zap_vm(struct tegra_iovmm_area *vm) { }
234
235 static inline void tegra_iovmm_unzap_vm(struct tegra_iovmm_area *vm) { }
236
237 static inline void tegra_iovmm_free_vm(struct tegra_iovmm_area *vm) { }
238
239 static inline void tegra_iovmm_vm_insert_pfn(struct tegra_iovmm_area *area,
240         tegra_iovmm_addr_t vaddr, unsigned long pfn) { }
241
242 static inline struct tegra_iovmm_area *tegra_iovmm_find_area_get(
243         struct tegra_iovmm_client *client, tegra_iovmm_addr_t addr)
244 {
245         return NULL;
246 }
247
248 static inline struct tegra_iovmm_area *tegra_iovmm_area_get(
249         struct tegra_iovmm_area *vm)
250 {
251         return NULL;
252 }
253
254 static inline void tegra_iovmm_area_put(struct tegra_iovmm_area *vm) { }
255
256 static inline int tegra_iovmm_domain_init(struct tegra_iovmm_domain *domain,
257         struct tegra_iovmm_device *dev, tegra_iovmm_addr_t start,
258         tegra_iovmm_addr_t end)
259 {
260         return 0;
261 }
262
263 static inline int tegra_iovmm_register(struct tegra_iovmm_device *dev)
264 {
265         return 0;
266 }
267
268 static inline int tegra_iovmm_unregister(struct tegra_iovmm_device *dev)
269 {
270         return 0;
271 }
272
273 static inline int tegra_iovmm_suspend(void)
274 {
275         return 0;
276 }
277
278 static inline void tegra_iovmm_resume(void) { }
279 #endif /* CONFIG_TEGRA_IOVMM */
280
281
282 #endif