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