rk3368: iommu: remove hjc's commit
[firefly-linux-kernel-4.4.55.git] / drivers / iommu / rockchip-iovmm.c
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License version 2 as
4  * published by the Free Software Foundation.
5  */
6
7 #ifdef CONFIG_ROCKCHIP_IOMMU_DEBUG
8 #define DEBUG
9 #endif
10
11 #include <linux/kernel.h>
12 #include <linux/hardirq.h>
13 #include <linux/slab.h>
14 #include <linux/scatterlist.h>
15 #include <linux/err.h>
16
17 #include <linux/of.h>
18 #include <linux/of_platform.h>
19
20 #include "rockchip-iommu.h"
21
22 static struct rk_vm_region *find_region(struct rk_iovmm *vmm, dma_addr_t iova)
23 {
24         struct rk_vm_region *region;
25
26         list_for_each_entry(region, &vmm->regions_list, node)
27                 if (region->start == iova)
28                         return region;
29
30         return NULL;
31 }
32
33 int rockchip_iovmm_invalidate_tlb(struct device *dev)
34 {
35         int ret = rockchip_iommu_tlb_invalidate_global(dev);
36
37         return ret;
38 }
39
40 void rockchip_iovmm_set_fault_handler(struct device *dev,
41                                        rockchip_iommu_fault_handler_t handler)
42 {
43         struct iommu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
44
45         data->fault_handler = handler;
46 }
47
48 int rockchip_iovmm_activate(struct device *dev)
49 {
50         struct rk_iovmm *vmm = rockchip_get_iovmm(dev);
51
52         return iommu_attach_device(vmm->domain, dev);
53 }
54
55 void rockchip_iovmm_deactivate(struct device *dev)
56 {
57         struct rk_iovmm *vmm = rockchip_get_iovmm(dev);
58
59         iommu_detach_device(vmm->domain, dev);
60 }
61
62 dma_addr_t rockchip_iovmm_map(struct device *dev,
63         struct scatterlist *sg, off_t offset, size_t size)
64 {
65         off_t start_off;
66         dma_addr_t addr, start = 0;
67         size_t mapped_size = 0;
68         struct rk_vm_region *region;
69         struct rk_iovmm *vmm = rockchip_get_iovmm(dev);
70         int order;
71         int ret;
72         
73         for (; sg_dma_len(sg) < offset; sg = sg_next(sg))
74                 offset -= sg_dma_len(sg);
75
76         start_off = offset_in_page(sg_phys(sg) + offset);
77         size = PAGE_ALIGN(size + start_off);
78
79         order = __fls(min_t(size_t, size, SZ_1M));
80
81         region = kmalloc(sizeof(*region), GFP_KERNEL);
82         if (!region) {
83                 ret = -ENOMEM;
84                 goto err_map_nomem;
85         }
86
87         start = (dma_addr_t)gen_pool_alloc(vmm->vmm_pool, size);
88         if (!start) {
89                 ret = -ENOMEM;
90                 goto err_map_noiomem;
91         }
92
93         pr_debug("%s: size = %zx\n", __func__, size);
94
95         addr = start;
96         do {
97                 phys_addr_t phys;
98                 size_t len;
99
100                 phys = sg_phys(sg);
101                 len = sg_dma_len(sg);
102
103                 /* if back to back sg entries are contiguous consolidate them */
104                 while (sg_next(sg) && sg_phys(sg) +
105                        sg_dma_len(sg) == sg_phys(sg_next(sg))) {
106                         len += sg_dma_len(sg_next(sg));
107                         sg = sg_next(sg);
108                 }
109
110                 if (offset > 0) {
111                         len -= offset;
112                         phys += offset;
113                         offset = 0;
114                 }
115
116                 if (offset_in_page(phys)) {
117                         len += offset_in_page(phys);
118                         phys = round_down(phys, PAGE_SIZE);
119                 }
120
121                 len = PAGE_ALIGN(len);
122
123                 if (len > (size - mapped_size))
124                         len = size - mapped_size;
125                 pr_debug("addr = %pad, phys = %pa, len = %zx\n", &addr, &phys, len);
126                 ret = iommu_map(vmm->domain, addr, phys, len, 0);
127                 if (ret)
128                         break;
129
130                 addr += len;
131                 mapped_size += len;
132         } while ((sg = sg_next(sg)) && (mapped_size < size));
133
134         BUG_ON(mapped_size > size);
135
136         if (mapped_size < size)
137                 goto err_map_map;
138
139         region->start = start + start_off;
140         region->size = size;
141
142         INIT_LIST_HEAD(&region->node);
143
144         spin_lock(&vmm->lock);
145
146         list_add(&region->node, &vmm->regions_list);
147
148         spin_unlock(&vmm->lock);
149
150         ret = rockchip_iommu_tlb_invalidate(dev);
151         if (ret)
152                 goto err_map_map;
153
154         dev_dbg(dev->archdata.iommu, "IOVMM: Allocated VM region @ %p/%#X bytes.\n",
155         &region->start, region->size);
156
157         return region->start;
158
159 err_map_map:
160         spin_lock(&vmm->lock);
161         list_del(&region->node);
162         spin_unlock(&vmm->lock);
163         iommu_unmap(vmm->domain, start, mapped_size);
164         gen_pool_free(vmm->vmm_pool, start, size);
165 err_map_noiomem:
166         kfree(region);
167 err_map_nomem:
168         dev_err(dev->archdata.iommu, "IOVMM: Failed to allocated VM region for %zx bytes.\n", size);
169         return (dma_addr_t)ret;
170 }
171
172 void rockchip_iovmm_unmap(struct device *dev, dma_addr_t iova)
173 {
174         struct rk_vm_region *region;
175         struct rk_iovmm *vmm = rockchip_get_iovmm(dev);
176         size_t unmapped_size;
177
178         /* This function must not be called in IRQ handlers */
179         BUG_ON(in_irq());
180
181         spin_lock(&vmm->lock);
182
183         region = find_region(vmm, iova);
184         if (WARN_ON(!region)) {
185                 spin_unlock(&vmm->lock);
186                 return;
187         }
188
189         list_del(&region->node);
190
191         spin_unlock(&vmm->lock);
192
193         region->start = round_down(region->start, PAGE_SIZE);
194
195         unmapped_size = iommu_unmap(vmm->domain,
196                                     region->start, region->size);
197         /*
198         rockchip_iommu_tlb_invalidate(dev);
199         */
200         gen_pool_free(vmm->vmm_pool, region->start, region->size);
201
202         WARN_ON(unmapped_size != region->size);
203         
204         dev_dbg(dev->archdata.iommu, "IOVMM: Unmapped %zx bytes from %pad.\n",
205                 unmapped_size, &region->start);
206         
207         kfree(region);
208 }
209
210 int rockchip_iovmm_map_oto(struct device *dev, phys_addr_t phys, size_t size)
211 {
212         struct rk_vm_region *region;
213         struct rk_iovmm *vmm = rockchip_get_iovmm(dev);
214         int ret;
215
216         if (WARN_ON((phys + size) >= IOVA_START)) {
217                 dev_err(dev->archdata.iommu, "Unable to create one to one mapping for %zx @ %pa\n",
218                        size, &phys);
219                 return -EINVAL;
220         }
221
222         region = kmalloc(sizeof(*region), GFP_KERNEL);
223         if (!region)
224                 return -ENOMEM;
225
226         if (WARN_ON(phys & ~PAGE_MASK))
227                 phys = round_down(phys, PAGE_SIZE);
228
229
230         ret = iommu_map(vmm->domain, (dma_addr_t)phys, phys, size, 0);
231         if (ret < 0) {
232                 kfree(region);
233                 return ret;
234         }
235
236         region->start = (dma_addr_t)phys;
237         region->size = size;
238         INIT_LIST_HEAD(&region->node);
239
240         spin_lock(&vmm->lock);
241
242         list_add(&region->node, &vmm->regions_list);
243
244         spin_unlock(&vmm->lock);
245
246         ret = rockchip_iommu_tlb_invalidate(dev);
247         if (ret)
248                 return ret;
249
250         return 0;
251 }
252
253 void rockchip_iovmm_unmap_oto(struct device *dev, phys_addr_t phys)
254 {
255         struct rk_vm_region *region;
256         struct rk_iovmm *vmm = rockchip_get_iovmm(dev);
257         size_t unmapped_size;
258
259         /* This function must not be called in IRQ handlers */
260         BUG_ON(in_irq());
261
262         if (WARN_ON(phys & ~PAGE_MASK))
263                 phys = round_down(phys, PAGE_SIZE);
264
265         spin_lock(&vmm->lock);
266
267         region = find_region(vmm, (dma_addr_t)phys);
268         if (WARN_ON(!region)) {
269                 spin_unlock(&vmm->lock);
270                 return;
271         }
272
273         list_del(&region->node);
274
275         spin_unlock(&vmm->lock);
276
277         unmapped_size = iommu_unmap(vmm->domain, region->start, region->size);
278         WARN_ON(unmapped_size != region->size);
279         dev_dbg(dev->archdata.iommu, "IOVMM: Unmapped %zx bytes from %pad.\n",
280                unmapped_size, &region->start);
281
282         kfree(region);
283 }
284
285 int rockchip_init_iovmm(struct device *iommu, struct rk_iovmm *vmm)
286 {
287         int ret = 0;
288
289         vmm->vmm_pool = gen_pool_create(PAGE_SHIFT, -1);
290         if (!vmm->vmm_pool) {
291                 ret = -ENOMEM;
292                 goto err_setup_genalloc;
293         }
294
295         /* (1GB - 4KB) addr space from 0x10000000 */
296         ret = gen_pool_add(vmm->vmm_pool, IOVA_START, IOVM_SIZE, -1);
297         if (ret)
298                 goto err_setup_domain;
299
300         vmm->domain = iommu_domain_alloc(&platform_bus_type);
301         if (!vmm->domain) {
302                 ret = -ENOMEM;
303                 goto err_setup_domain;
304         }
305
306         spin_lock_init(&vmm->lock);
307
308         INIT_LIST_HEAD(&vmm->regions_list);
309
310         dev_info(iommu, "IOVMM: Created %#x B IOVMM from %#x.\n",
311                 IOVM_SIZE, IOVA_START);
312         return 0;
313 err_setup_domain:
314         gen_pool_destroy(vmm->vmm_pool);
315 err_setup_genalloc:
316         dev_err(iommu, "IOVMM: Failed to create IOVMM (%d)\n", ret);
317
318         return ret;
319 }