Merge tag 'mips_5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux
[linux-2.6-microblaze.git] / drivers / iommu / fsl_pamu_domain.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *
4  * Copyright (C) 2013 Freescale Semiconductor, Inc.
5  * Author: Varun Sethi <varun.sethi@freescale.com>
6  */
7
8 #define pr_fmt(fmt)    "fsl-pamu-domain: %s: " fmt, __func__
9
10 #include "fsl_pamu_domain.h"
11
12 #include <sysdev/fsl_pci.h>
13
14 /*
15  * Global spinlock that needs to be held while
16  * configuring PAMU.
17  */
18 static DEFINE_SPINLOCK(iommu_lock);
19
20 static struct kmem_cache *fsl_pamu_domain_cache;
21 static struct kmem_cache *iommu_devinfo_cache;
22 static DEFINE_SPINLOCK(device_domain_lock);
23
24 struct iommu_device pamu_iommu; /* IOMMU core code handle */
25
26 static struct fsl_dma_domain *to_fsl_dma_domain(struct iommu_domain *dom)
27 {
28         return container_of(dom, struct fsl_dma_domain, iommu_domain);
29 }
30
31 static int __init iommu_init_mempool(void)
32 {
33         fsl_pamu_domain_cache = kmem_cache_create("fsl_pamu_domain",
34                                                   sizeof(struct fsl_dma_domain),
35                                                   0,
36                                                   SLAB_HWCACHE_ALIGN,
37                                                   NULL);
38         if (!fsl_pamu_domain_cache) {
39                 pr_debug("Couldn't create fsl iommu_domain cache\n");
40                 return -ENOMEM;
41         }
42
43         iommu_devinfo_cache = kmem_cache_create("iommu_devinfo",
44                                                 sizeof(struct device_domain_info),
45                                                 0,
46                                                 SLAB_HWCACHE_ALIGN,
47                                                 NULL);
48         if (!iommu_devinfo_cache) {
49                 pr_debug("Couldn't create devinfo cache\n");
50                 kmem_cache_destroy(fsl_pamu_domain_cache);
51                 return -ENOMEM;
52         }
53
54         return 0;
55 }
56
57 static phys_addr_t get_phys_addr(struct fsl_dma_domain *dma_domain, dma_addr_t iova)
58 {
59         u32 win_cnt = dma_domain->win_cnt;
60         struct dma_window *win_ptr = &dma_domain->win_arr[0];
61         struct iommu_domain_geometry *geom;
62
63         geom = &dma_domain->iommu_domain.geometry;
64
65         if (!win_cnt || !dma_domain->geom_size) {
66                 pr_debug("Number of windows/geometry not configured for the domain\n");
67                 return 0;
68         }
69
70         if (win_cnt > 1) {
71                 u64 subwin_size;
72                 dma_addr_t subwin_iova;
73                 u32 wnd;
74
75                 subwin_size = dma_domain->geom_size >> ilog2(win_cnt);
76                 subwin_iova = iova & ~(subwin_size - 1);
77                 wnd = (subwin_iova - geom->aperture_start) >> ilog2(subwin_size);
78                 win_ptr = &dma_domain->win_arr[wnd];
79         }
80
81         if (win_ptr->valid)
82                 return win_ptr->paddr + (iova & (win_ptr->size - 1));
83
84         return 0;
85 }
86
87 static int map_subwins(int liodn, struct fsl_dma_domain *dma_domain)
88 {
89         struct dma_window *sub_win_ptr = &dma_domain->win_arr[0];
90         int i, ret;
91         unsigned long rpn, flags;
92
93         for (i = 0; i < dma_domain->win_cnt; i++) {
94                 if (sub_win_ptr[i].valid) {
95                         rpn = sub_win_ptr[i].paddr >> PAMU_PAGE_SHIFT;
96                         spin_lock_irqsave(&iommu_lock, flags);
97                         ret = pamu_config_spaace(liodn, dma_domain->win_cnt, i,
98                                                  sub_win_ptr[i].size,
99                                                  ~(u32)0,
100                                                  rpn,
101                                                  dma_domain->snoop_id,
102                                                  dma_domain->stash_id,
103                                                  (i > 0) ? 1 : 0,
104                                                  sub_win_ptr[i].prot);
105                         spin_unlock_irqrestore(&iommu_lock, flags);
106                         if (ret) {
107                                 pr_debug("SPAACE configuration failed for liodn %d\n",
108                                          liodn);
109                                 return ret;
110                         }
111                 }
112         }
113
114         return ret;
115 }
116
117 static int map_win(int liodn, struct fsl_dma_domain *dma_domain)
118 {
119         int ret;
120         struct dma_window *wnd = &dma_domain->win_arr[0];
121         phys_addr_t wnd_addr = dma_domain->iommu_domain.geometry.aperture_start;
122         unsigned long flags;
123
124         spin_lock_irqsave(&iommu_lock, flags);
125         ret = pamu_config_ppaace(liodn, wnd_addr,
126                                  wnd->size,
127                                  ~(u32)0,
128                                  wnd->paddr >> PAMU_PAGE_SHIFT,
129                                  dma_domain->snoop_id, dma_domain->stash_id,
130                                  0, wnd->prot);
131         spin_unlock_irqrestore(&iommu_lock, flags);
132         if (ret)
133                 pr_debug("PAACE configuration failed for liodn %d\n", liodn);
134
135         return ret;
136 }
137
138 /* Map the DMA window corresponding to the LIODN */
139 static int map_liodn(int liodn, struct fsl_dma_domain *dma_domain)
140 {
141         if (dma_domain->win_cnt > 1)
142                 return map_subwins(liodn, dma_domain);
143         else
144                 return map_win(liodn, dma_domain);
145 }
146
147 /* Update window/subwindow mapping for the LIODN */
148 static int update_liodn(int liodn, struct fsl_dma_domain *dma_domain, u32 wnd_nr)
149 {
150         int ret;
151         struct dma_window *wnd = &dma_domain->win_arr[wnd_nr];
152         unsigned long flags;
153
154         spin_lock_irqsave(&iommu_lock, flags);
155         if (dma_domain->win_cnt > 1) {
156                 ret = pamu_config_spaace(liodn, dma_domain->win_cnt, wnd_nr,
157                                          wnd->size,
158                                          ~(u32)0,
159                                          wnd->paddr >> PAMU_PAGE_SHIFT,
160                                          dma_domain->snoop_id,
161                                          dma_domain->stash_id,
162                                          (wnd_nr > 0) ? 1 : 0,
163                                          wnd->prot);
164                 if (ret)
165                         pr_debug("Subwindow reconfiguration failed for liodn %d\n",
166                                  liodn);
167         } else {
168                 phys_addr_t wnd_addr;
169
170                 wnd_addr = dma_domain->iommu_domain.geometry.aperture_start;
171
172                 ret = pamu_config_ppaace(liodn, wnd_addr,
173                                          wnd->size,
174                                          ~(u32)0,
175                                          wnd->paddr >> PAMU_PAGE_SHIFT,
176                                          dma_domain->snoop_id, dma_domain->stash_id,
177                                          0, wnd->prot);
178                 if (ret)
179                         pr_debug("Window reconfiguration failed for liodn %d\n",
180                                  liodn);
181         }
182
183         spin_unlock_irqrestore(&iommu_lock, flags);
184
185         return ret;
186 }
187
188 static int update_liodn_stash(int liodn, struct fsl_dma_domain *dma_domain,
189                               u32 val)
190 {
191         int ret = 0, i;
192         unsigned long flags;
193
194         spin_lock_irqsave(&iommu_lock, flags);
195         if (!dma_domain->win_arr) {
196                 pr_debug("Windows not configured, stash destination update failed for liodn %d\n",
197                          liodn);
198                 spin_unlock_irqrestore(&iommu_lock, flags);
199                 return -EINVAL;
200         }
201
202         for (i = 0; i < dma_domain->win_cnt; i++) {
203                 ret = pamu_update_paace_stash(liodn, i, val);
204                 if (ret) {
205                         pr_debug("Failed to update SPAACE %d field for liodn %d\n ",
206                                  i, liodn);
207                         spin_unlock_irqrestore(&iommu_lock, flags);
208                         return ret;
209                 }
210         }
211
212         spin_unlock_irqrestore(&iommu_lock, flags);
213
214         return ret;
215 }
216
217 /* Set the geometry parameters for a LIODN */
218 static int pamu_set_liodn(int liodn, struct device *dev,
219                           struct fsl_dma_domain *dma_domain,
220                           struct iommu_domain_geometry *geom_attr,
221                           u32 win_cnt)
222 {
223         phys_addr_t window_addr, window_size;
224         phys_addr_t subwin_size;
225         int ret = 0, i;
226         u32 omi_index = ~(u32)0;
227         unsigned long flags;
228
229         /*
230          * Configure the omi_index at the geometry setup time.
231          * This is a static value which depends on the type of
232          * device and would not change thereafter.
233          */
234         get_ome_index(&omi_index, dev);
235
236         window_addr = geom_attr->aperture_start;
237         window_size = dma_domain->geom_size;
238
239         spin_lock_irqsave(&iommu_lock, flags);
240         ret = pamu_disable_liodn(liodn);
241         if (!ret)
242                 ret = pamu_config_ppaace(liodn, window_addr, window_size, omi_index,
243                                          0, dma_domain->snoop_id,
244                                          dma_domain->stash_id, win_cnt, 0);
245         spin_unlock_irqrestore(&iommu_lock, flags);
246         if (ret) {
247                 pr_debug("PAACE configuration failed for liodn %d, win_cnt =%d\n",
248                          liodn, win_cnt);
249                 return ret;
250         }
251
252         if (win_cnt > 1) {
253                 subwin_size = window_size >> ilog2(win_cnt);
254                 for (i = 0; i < win_cnt; i++) {
255                         spin_lock_irqsave(&iommu_lock, flags);
256                         ret = pamu_disable_spaace(liodn, i);
257                         if (!ret)
258                                 ret = pamu_config_spaace(liodn, win_cnt, i,
259                                                          subwin_size, omi_index,
260                                                          0, dma_domain->snoop_id,
261                                                          dma_domain->stash_id,
262                                                          0, 0);
263                         spin_unlock_irqrestore(&iommu_lock, flags);
264                         if (ret) {
265                                 pr_debug("SPAACE configuration failed for liodn %d\n",
266                                          liodn);
267                                 return ret;
268                         }
269                 }
270         }
271
272         return ret;
273 }
274
275 static int check_size(u64 size, dma_addr_t iova)
276 {
277         /*
278          * Size must be a power of two and at least be equal
279          * to PAMU page size.
280          */
281         if ((size & (size - 1)) || size < PAMU_PAGE_SIZE) {
282                 pr_debug("Size too small or not a power of two\n");
283                 return -EINVAL;
284         }
285
286         /* iova must be page size aligned */
287         if (iova & (size - 1)) {
288                 pr_debug("Address is not aligned with window size\n");
289                 return -EINVAL;
290         }
291
292         return 0;
293 }
294
295 static struct fsl_dma_domain *iommu_alloc_dma_domain(void)
296 {
297         struct fsl_dma_domain *domain;
298
299         domain = kmem_cache_zalloc(fsl_pamu_domain_cache, GFP_KERNEL);
300         if (!domain)
301                 return NULL;
302
303         domain->stash_id = ~(u32)0;
304         domain->snoop_id = ~(u32)0;
305         domain->win_cnt = pamu_get_max_subwin_cnt();
306         domain->geom_size = 0;
307
308         INIT_LIST_HEAD(&domain->devices);
309
310         spin_lock_init(&domain->domain_lock);
311
312         return domain;
313 }
314
315 static void remove_device_ref(struct device_domain_info *info, u32 win_cnt)
316 {
317         unsigned long flags;
318
319         list_del(&info->link);
320         spin_lock_irqsave(&iommu_lock, flags);
321         if (win_cnt > 1)
322                 pamu_free_subwins(info->liodn);
323         pamu_disable_liodn(info->liodn);
324         spin_unlock_irqrestore(&iommu_lock, flags);
325         spin_lock_irqsave(&device_domain_lock, flags);
326         dev_iommu_priv_set(info->dev, NULL);
327         kmem_cache_free(iommu_devinfo_cache, info);
328         spin_unlock_irqrestore(&device_domain_lock, flags);
329 }
330
331 static void detach_device(struct device *dev, struct fsl_dma_domain *dma_domain)
332 {
333         struct device_domain_info *info, *tmp;
334         unsigned long flags;
335
336         spin_lock_irqsave(&dma_domain->domain_lock, flags);
337         /* Remove the device from the domain device list */
338         list_for_each_entry_safe(info, tmp, &dma_domain->devices, link) {
339                 if (!dev || (info->dev == dev))
340                         remove_device_ref(info, dma_domain->win_cnt);
341         }
342         spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
343 }
344
345 static void attach_device(struct fsl_dma_domain *dma_domain, int liodn, struct device *dev)
346 {
347         struct device_domain_info *info, *old_domain_info;
348         unsigned long flags;
349
350         spin_lock_irqsave(&device_domain_lock, flags);
351         /*
352          * Check here if the device is already attached to domain or not.
353          * If the device is already attached to a domain detach it.
354          */
355         old_domain_info = dev_iommu_priv_get(dev);
356         if (old_domain_info && old_domain_info->domain != dma_domain) {
357                 spin_unlock_irqrestore(&device_domain_lock, flags);
358                 detach_device(dev, old_domain_info->domain);
359                 spin_lock_irqsave(&device_domain_lock, flags);
360         }
361
362         info = kmem_cache_zalloc(iommu_devinfo_cache, GFP_ATOMIC);
363
364         info->dev = dev;
365         info->liodn = liodn;
366         info->domain = dma_domain;
367
368         list_add(&info->link, &dma_domain->devices);
369         /*
370          * In case of devices with multiple LIODNs just store
371          * the info for the first LIODN as all
372          * LIODNs share the same domain
373          */
374         if (!dev_iommu_priv_get(dev))
375                 dev_iommu_priv_set(dev, info);
376         spin_unlock_irqrestore(&device_domain_lock, flags);
377 }
378
379 static phys_addr_t fsl_pamu_iova_to_phys(struct iommu_domain *domain,
380                                          dma_addr_t iova)
381 {
382         struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain);
383
384         if (iova < domain->geometry.aperture_start ||
385             iova > domain->geometry.aperture_end)
386                 return 0;
387
388         return get_phys_addr(dma_domain, iova);
389 }
390
391 static bool fsl_pamu_capable(enum iommu_cap cap)
392 {
393         return cap == IOMMU_CAP_CACHE_COHERENCY;
394 }
395
396 static void fsl_pamu_domain_free(struct iommu_domain *domain)
397 {
398         struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain);
399
400         /* remove all the devices from the device list */
401         detach_device(NULL, dma_domain);
402
403         dma_domain->enabled = 0;
404         dma_domain->mapped = 0;
405
406         kmem_cache_free(fsl_pamu_domain_cache, dma_domain);
407 }
408
409 static struct iommu_domain *fsl_pamu_domain_alloc(unsigned type)
410 {
411         struct fsl_dma_domain *dma_domain;
412
413         if (type != IOMMU_DOMAIN_UNMANAGED)
414                 return NULL;
415
416         dma_domain = iommu_alloc_dma_domain();
417         if (!dma_domain) {
418                 pr_debug("dma_domain allocation failed\n");
419                 return NULL;
420         }
421         /* defaul geometry 64 GB i.e. maximum system address */
422         dma_domain->iommu_domain. geometry.aperture_start = 0;
423         dma_domain->iommu_domain.geometry.aperture_end = (1ULL << 36) - 1;
424         dma_domain->iommu_domain.geometry.force_aperture = true;
425
426         return &dma_domain->iommu_domain;
427 }
428
429 /* Configure geometry settings for all LIODNs associated with domain */
430 static int pamu_set_domain_geometry(struct fsl_dma_domain *dma_domain,
431                                     struct iommu_domain_geometry *geom_attr,
432                                     u32 win_cnt)
433 {
434         struct device_domain_info *info;
435         int ret = 0;
436
437         list_for_each_entry(info, &dma_domain->devices, link) {
438                 ret = pamu_set_liodn(info->liodn, info->dev, dma_domain,
439                                      geom_attr, win_cnt);
440                 if (ret)
441                         break;
442         }
443
444         return ret;
445 }
446
447 /* Update stash destination for all LIODNs associated with the domain */
448 static int update_domain_stash(struct fsl_dma_domain *dma_domain, u32 val)
449 {
450         struct device_domain_info *info;
451         int ret = 0;
452
453         list_for_each_entry(info, &dma_domain->devices, link) {
454                 ret = update_liodn_stash(info->liodn, dma_domain, val);
455                 if (ret)
456                         break;
457         }
458
459         return ret;
460 }
461
462 /* Update domain mappings for all LIODNs associated with the domain */
463 static int update_domain_mapping(struct fsl_dma_domain *dma_domain, u32 wnd_nr)
464 {
465         struct device_domain_info *info;
466         int ret = 0;
467
468         list_for_each_entry(info, &dma_domain->devices, link) {
469                 ret = update_liodn(info->liodn, dma_domain, wnd_nr);
470                 if (ret)
471                         break;
472         }
473         return ret;
474 }
475
476 static int disable_domain_win(struct fsl_dma_domain *dma_domain, u32 wnd_nr)
477 {
478         struct device_domain_info *info;
479         int ret = 0;
480
481         list_for_each_entry(info, &dma_domain->devices, link) {
482                 if (dma_domain->win_cnt == 1 && dma_domain->enabled) {
483                         ret = pamu_disable_liodn(info->liodn);
484                         if (!ret)
485                                 dma_domain->enabled = 0;
486                 } else {
487                         ret = pamu_disable_spaace(info->liodn, wnd_nr);
488                 }
489         }
490
491         return ret;
492 }
493
494 static void fsl_pamu_window_disable(struct iommu_domain *domain, u32 wnd_nr)
495 {
496         struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain);
497         unsigned long flags;
498         int ret;
499
500         spin_lock_irqsave(&dma_domain->domain_lock, flags);
501         if (!dma_domain->win_arr) {
502                 pr_debug("Number of windows not configured\n");
503                 spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
504                 return;
505         }
506
507         if (wnd_nr >= dma_domain->win_cnt) {
508                 pr_debug("Invalid window index\n");
509                 spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
510                 return;
511         }
512
513         if (dma_domain->win_arr[wnd_nr].valid) {
514                 ret = disable_domain_win(dma_domain, wnd_nr);
515                 if (!ret) {
516                         dma_domain->win_arr[wnd_nr].valid = 0;
517                         dma_domain->mapped--;
518                 }
519         }
520
521         spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
522 }
523
524 static int fsl_pamu_window_enable(struct iommu_domain *domain, u32 wnd_nr,
525                                   phys_addr_t paddr, u64 size, int prot)
526 {
527         struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain);
528         struct dma_window *wnd;
529         int pamu_prot = 0;
530         int ret;
531         unsigned long flags;
532         u64 win_size;
533
534         if (prot & IOMMU_READ)
535                 pamu_prot |= PAACE_AP_PERMS_QUERY;
536         if (prot & IOMMU_WRITE)
537                 pamu_prot |= PAACE_AP_PERMS_UPDATE;
538
539         spin_lock_irqsave(&dma_domain->domain_lock, flags);
540         if (!dma_domain->win_arr) {
541                 pr_debug("Number of windows not configured\n");
542                 spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
543                 return -ENODEV;
544         }
545
546         if (wnd_nr >= dma_domain->win_cnt) {
547                 pr_debug("Invalid window index\n");
548                 spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
549                 return -EINVAL;
550         }
551
552         win_size = dma_domain->geom_size >> ilog2(dma_domain->win_cnt);
553         if (size > win_size) {
554                 pr_debug("Invalid window size\n");
555                 spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
556                 return -EINVAL;
557         }
558
559         if (dma_domain->win_cnt == 1) {
560                 if (dma_domain->enabled) {
561                         pr_debug("Disable the window before updating the mapping\n");
562                         spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
563                         return -EBUSY;
564                 }
565
566                 ret = check_size(size, domain->geometry.aperture_start);
567                 if (ret) {
568                         pr_debug("Aperture start not aligned to the size\n");
569                         spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
570                         return -EINVAL;
571                 }
572         }
573
574         wnd = &dma_domain->win_arr[wnd_nr];
575         if (!wnd->valid) {
576                 wnd->paddr = paddr;
577                 wnd->size = size;
578                 wnd->prot = pamu_prot;
579
580                 ret = update_domain_mapping(dma_domain, wnd_nr);
581                 if (!ret) {
582                         wnd->valid = 1;
583                         dma_domain->mapped++;
584                 }
585         } else {
586                 pr_debug("Disable the window before updating the mapping\n");
587                 ret = -EBUSY;
588         }
589
590         spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
591
592         return ret;
593 }
594
595 /*
596  * Attach the LIODN to the DMA domain and configure the geometry
597  * and window mappings.
598  */
599 static int handle_attach_device(struct fsl_dma_domain *dma_domain,
600                                 struct device *dev, const u32 *liodn,
601                                 int num)
602 {
603         unsigned long flags;
604         struct iommu_domain *domain = &dma_domain->iommu_domain;
605         int ret = 0;
606         int i;
607
608         spin_lock_irqsave(&dma_domain->domain_lock, flags);
609         for (i = 0; i < num; i++) {
610                 /* Ensure that LIODN value is valid */
611                 if (liodn[i] >= PAACE_NUMBER_ENTRIES) {
612                         pr_debug("Invalid liodn %d, attach device failed for %pOF\n",
613                                  liodn[i], dev->of_node);
614                         ret = -EINVAL;
615                         break;
616                 }
617
618                 attach_device(dma_domain, liodn[i], dev);
619                 /*
620                  * Check if geometry has already been configured
621                  * for the domain. If yes, set the geometry for
622                  * the LIODN.
623                  */
624                 if (dma_domain->win_arr) {
625                         u32 win_cnt = dma_domain->win_cnt > 1 ? dma_domain->win_cnt : 0;
626
627                         ret = pamu_set_liodn(liodn[i], dev, dma_domain,
628                                              &domain->geometry, win_cnt);
629                         if (ret)
630                                 break;
631                         if (dma_domain->mapped) {
632                                 /*
633                                  * Create window/subwindow mapping for
634                                  * the LIODN.
635                                  */
636                                 ret = map_liodn(liodn[i], dma_domain);
637                                 if (ret)
638                                         break;
639                         }
640                 }
641         }
642         spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
643
644         return ret;
645 }
646
647 static int fsl_pamu_attach_device(struct iommu_domain *domain,
648                                   struct device *dev)
649 {
650         struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain);
651         const u32 *liodn;
652         u32 liodn_cnt;
653         int len, ret = 0;
654         struct pci_dev *pdev = NULL;
655         struct pci_controller *pci_ctl;
656
657         /*
658          * Use LIODN of the PCI controller while attaching a
659          * PCI device.
660          */
661         if (dev_is_pci(dev)) {
662                 pdev = to_pci_dev(dev);
663                 pci_ctl = pci_bus_to_host(pdev->bus);
664                 /*
665                  * make dev point to pci controller device
666                  * so we can get the LIODN programmed by
667                  * u-boot.
668                  */
669                 dev = pci_ctl->parent;
670         }
671
672         liodn = of_get_property(dev->of_node, "fsl,liodn", &len);
673         if (liodn) {
674                 liodn_cnt = len / sizeof(u32);
675                 ret = handle_attach_device(dma_domain, dev, liodn, liodn_cnt);
676         } else {
677                 pr_debug("missing fsl,liodn property at %pOF\n", dev->of_node);
678                 ret = -EINVAL;
679         }
680
681         return ret;
682 }
683
684 static void fsl_pamu_detach_device(struct iommu_domain *domain,
685                                    struct device *dev)
686 {
687         struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain);
688         const u32 *prop;
689         int len;
690         struct pci_dev *pdev = NULL;
691         struct pci_controller *pci_ctl;
692
693         /*
694          * Use LIODN of the PCI controller while detaching a
695          * PCI device.
696          */
697         if (dev_is_pci(dev)) {
698                 pdev = to_pci_dev(dev);
699                 pci_ctl = pci_bus_to_host(pdev->bus);
700                 /*
701                  * make dev point to pci controller device
702                  * so we can get the LIODN programmed by
703                  * u-boot.
704                  */
705                 dev = pci_ctl->parent;
706         }
707
708         prop = of_get_property(dev->of_node, "fsl,liodn", &len);
709         if (prop)
710                 detach_device(dev, dma_domain);
711         else
712                 pr_debug("missing fsl,liodn property at %pOF\n", dev->of_node);
713 }
714
715 static  int configure_domain_geometry(struct iommu_domain *domain, void *data)
716 {
717         struct iommu_domain_geometry *geom_attr = data;
718         struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain);
719         dma_addr_t geom_size;
720         unsigned long flags;
721
722         geom_size = geom_attr->aperture_end - geom_attr->aperture_start + 1;
723         /*
724          * Sanity check the geometry size. Also, we do not support
725          * DMA outside of the geometry.
726          */
727         if (check_size(geom_size, geom_attr->aperture_start) ||
728             !geom_attr->force_aperture) {
729                 pr_debug("Invalid PAMU geometry attributes\n");
730                 return -EINVAL;
731         }
732
733         spin_lock_irqsave(&dma_domain->domain_lock, flags);
734         if (dma_domain->enabled) {
735                 pr_debug("Can't set geometry attributes as domain is active\n");
736                 spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
737                 return  -EBUSY;
738         }
739
740         /* Copy the domain geometry information */
741         memcpy(&domain->geometry, geom_attr,
742                sizeof(struct iommu_domain_geometry));
743         dma_domain->geom_size = geom_size;
744
745         spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
746
747         return 0;
748 }
749
750 /* Set the domain stash attribute */
751 static int configure_domain_stash(struct fsl_dma_domain *dma_domain, void *data)
752 {
753         struct pamu_stash_attribute *stash_attr = data;
754         unsigned long flags;
755         int ret;
756
757         spin_lock_irqsave(&dma_domain->domain_lock, flags);
758
759         memcpy(&dma_domain->dma_stash, stash_attr,
760                sizeof(struct pamu_stash_attribute));
761
762         dma_domain->stash_id = get_stash_id(stash_attr->cache,
763                                             stash_attr->cpu);
764         if (dma_domain->stash_id == ~(u32)0) {
765                 pr_debug("Invalid stash attributes\n");
766                 spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
767                 return -EINVAL;
768         }
769
770         ret = update_domain_stash(dma_domain, dma_domain->stash_id);
771
772         spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
773
774         return ret;
775 }
776
777 /* Configure domain dma state i.e. enable/disable DMA */
778 static int configure_domain_dma_state(struct fsl_dma_domain *dma_domain, bool enable)
779 {
780         struct device_domain_info *info;
781         unsigned long flags;
782         int ret;
783
784         spin_lock_irqsave(&dma_domain->domain_lock, flags);
785
786         if (enable && !dma_domain->mapped) {
787                 pr_debug("Can't enable DMA domain without valid mapping\n");
788                 spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
789                 return -ENODEV;
790         }
791
792         dma_domain->enabled = enable;
793         list_for_each_entry(info, &dma_domain->devices, link) {
794                 ret = (enable) ? pamu_enable_liodn(info->liodn) :
795                         pamu_disable_liodn(info->liodn);
796                 if (ret)
797                         pr_debug("Unable to set dma state for liodn %d",
798                                  info->liodn);
799         }
800         spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
801
802         return 0;
803 }
804
805 static int fsl_pamu_set_windows(struct iommu_domain *domain, u32 w_count)
806 {
807         struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain);
808         unsigned long flags;
809         int ret;
810
811         spin_lock_irqsave(&dma_domain->domain_lock, flags);
812         /* Ensure domain is inactive i.e. DMA should be disabled for the domain */
813         if (dma_domain->enabled) {
814                 pr_debug("Can't set geometry attributes as domain is active\n");
815                 spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
816                 return  -EBUSY;
817         }
818
819         /* Ensure that the geometry has been set for the domain */
820         if (!dma_domain->geom_size) {
821                 pr_debug("Please configure geometry before setting the number of windows\n");
822                 spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
823                 return -EINVAL;
824         }
825
826         /*
827          * Ensure we have valid window count i.e. it should be less than
828          * maximum permissible limit and should be a power of two.
829          */
830         if (w_count > pamu_get_max_subwin_cnt() || !is_power_of_2(w_count)) {
831                 pr_debug("Invalid window count\n");
832                 spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
833                 return -EINVAL;
834         }
835
836         ret = pamu_set_domain_geometry(dma_domain, &domain->geometry,
837                                        w_count > 1 ? w_count : 0);
838         if (!ret) {
839                 kfree(dma_domain->win_arr);
840                 dma_domain->win_arr = kcalloc(w_count,
841                                               sizeof(*dma_domain->win_arr),
842                                               GFP_ATOMIC);
843                 if (!dma_domain->win_arr) {
844                         spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
845                         return -ENOMEM;
846                 }
847                 dma_domain->win_cnt = w_count;
848         }
849         spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
850
851         return ret;
852 }
853
854 static int fsl_pamu_set_domain_attr(struct iommu_domain *domain,
855                                     enum iommu_attr attr_type, void *data)
856 {
857         struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain);
858         int ret = 0;
859
860         switch (attr_type) {
861         case DOMAIN_ATTR_GEOMETRY:
862                 ret = configure_domain_geometry(domain, data);
863                 break;
864         case DOMAIN_ATTR_FSL_PAMU_STASH:
865                 ret = configure_domain_stash(dma_domain, data);
866                 break;
867         case DOMAIN_ATTR_FSL_PAMU_ENABLE:
868                 ret = configure_domain_dma_state(dma_domain, *(int *)data);
869                 break;
870         case DOMAIN_ATTR_WINDOWS:
871                 ret = fsl_pamu_set_windows(domain, *(u32 *)data);
872                 break;
873         default:
874                 pr_debug("Unsupported attribute type\n");
875                 ret = -EINVAL;
876                 break;
877         }
878
879         return ret;
880 }
881
882 static int fsl_pamu_get_domain_attr(struct iommu_domain *domain,
883                                     enum iommu_attr attr_type, void *data)
884 {
885         struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain);
886         int ret = 0;
887
888         switch (attr_type) {
889         case DOMAIN_ATTR_FSL_PAMU_STASH:
890                 memcpy(data, &dma_domain->dma_stash,
891                        sizeof(struct pamu_stash_attribute));
892                 break;
893         case DOMAIN_ATTR_FSL_PAMU_ENABLE:
894                 *(int *)data = dma_domain->enabled;
895                 break;
896         case DOMAIN_ATTR_FSL_PAMUV1:
897                 *(int *)data = DOMAIN_ATTR_FSL_PAMUV1;
898                 break;
899         case DOMAIN_ATTR_WINDOWS:
900                 *(u32 *)data = dma_domain->win_cnt;
901                 break;
902         default:
903                 pr_debug("Unsupported attribute type\n");
904                 ret = -EINVAL;
905                 break;
906         }
907
908         return ret;
909 }
910
911 static struct iommu_group *get_device_iommu_group(struct device *dev)
912 {
913         struct iommu_group *group;
914
915         group = iommu_group_get(dev);
916         if (!group)
917                 group = iommu_group_alloc();
918
919         return group;
920 }
921
922 static  bool check_pci_ctl_endpt_part(struct pci_controller *pci_ctl)
923 {
924         u32 version;
925
926         /* Check the PCI controller version number by readding BRR1 register */
927         version = in_be32(pci_ctl->cfg_addr + (PCI_FSL_BRR1 >> 2));
928         version &= PCI_FSL_BRR1_VER;
929         /* If PCI controller version is >= 0x204 we can partition endpoints */
930         return version >= 0x204;
931 }
932
933 /* Get iommu group information from peer devices or devices on the parent bus */
934 static struct iommu_group *get_shared_pci_device_group(struct pci_dev *pdev)
935 {
936         struct pci_dev *tmp;
937         struct iommu_group *group;
938         struct pci_bus *bus = pdev->bus;
939
940         /*
941          * Traverese the pci bus device list to get
942          * the shared iommu group.
943          */
944         while (bus) {
945                 list_for_each_entry(tmp, &bus->devices, bus_list) {
946                         if (tmp == pdev)
947                                 continue;
948                         group = iommu_group_get(&tmp->dev);
949                         if (group)
950                                 return group;
951                 }
952
953                 bus = bus->parent;
954         }
955
956         return NULL;
957 }
958
959 static struct iommu_group *get_pci_device_group(struct pci_dev *pdev)
960 {
961         struct pci_controller *pci_ctl;
962         bool pci_endpt_partitioning;
963         struct iommu_group *group = NULL;
964
965         pci_ctl = pci_bus_to_host(pdev->bus);
966         pci_endpt_partitioning = check_pci_ctl_endpt_part(pci_ctl);
967         /* We can partition PCIe devices so assign device group to the device */
968         if (pci_endpt_partitioning) {
969                 group = pci_device_group(&pdev->dev);
970
971                 /*
972                  * PCIe controller is not a paritionable entity
973                  * free the controller device iommu_group.
974                  */
975                 if (pci_ctl->parent->iommu_group)
976                         iommu_group_remove_device(pci_ctl->parent);
977         } else {
978                 /*
979                  * All devices connected to the controller will share the
980                  * PCI controllers device group. If this is the first
981                  * device to be probed for the pci controller, copy the
982                  * device group information from the PCI controller device
983                  * node and remove the PCI controller iommu group.
984                  * For subsequent devices, the iommu group information can
985                  * be obtained from sibling devices (i.e. from the bus_devices
986                  * link list).
987                  */
988                 if (pci_ctl->parent->iommu_group) {
989                         group = get_device_iommu_group(pci_ctl->parent);
990                         iommu_group_remove_device(pci_ctl->parent);
991                 } else {
992                         group = get_shared_pci_device_group(pdev);
993                 }
994         }
995
996         if (!group)
997                 group = ERR_PTR(-ENODEV);
998
999         return group;
1000 }
1001
1002 static struct iommu_group *fsl_pamu_device_group(struct device *dev)
1003 {
1004         struct iommu_group *group = ERR_PTR(-ENODEV);
1005         int len;
1006
1007         /*
1008          * For platform devices we allocate a separate group for
1009          * each of the devices.
1010          */
1011         if (dev_is_pci(dev))
1012                 group = get_pci_device_group(to_pci_dev(dev));
1013         else if (of_get_property(dev->of_node, "fsl,liodn", &len))
1014                 group = get_device_iommu_group(dev);
1015
1016         return group;
1017 }
1018
1019 static struct iommu_device *fsl_pamu_probe_device(struct device *dev)
1020 {
1021         return &pamu_iommu;
1022 }
1023
1024 static void fsl_pamu_release_device(struct device *dev)
1025 {
1026 }
1027
1028 static const struct iommu_ops fsl_pamu_ops = {
1029         .capable        = fsl_pamu_capable,
1030         .domain_alloc   = fsl_pamu_domain_alloc,
1031         .domain_free    = fsl_pamu_domain_free,
1032         .attach_dev     = fsl_pamu_attach_device,
1033         .detach_dev     = fsl_pamu_detach_device,
1034         .domain_window_enable = fsl_pamu_window_enable,
1035         .domain_window_disable = fsl_pamu_window_disable,
1036         .iova_to_phys   = fsl_pamu_iova_to_phys,
1037         .domain_set_attr = fsl_pamu_set_domain_attr,
1038         .domain_get_attr = fsl_pamu_get_domain_attr,
1039         .probe_device   = fsl_pamu_probe_device,
1040         .release_device = fsl_pamu_release_device,
1041         .device_group   = fsl_pamu_device_group,
1042 };
1043
1044 int __init pamu_domain_init(void)
1045 {
1046         int ret = 0;
1047
1048         ret = iommu_init_mempool();
1049         if (ret)
1050                 return ret;
1051
1052         ret = iommu_device_sysfs_add(&pamu_iommu, NULL, NULL, "iommu0");
1053         if (ret)
1054                 return ret;
1055
1056         iommu_device_set_ops(&pamu_iommu, &fsl_pamu_ops);
1057
1058         ret = iommu_device_register(&pamu_iommu);
1059         if (ret) {
1060                 iommu_device_sysfs_remove(&pamu_iommu);
1061                 pr_err("Can't register iommu device\n");
1062                 return ret;
1063         }
1064
1065         bus_set_iommu(&platform_bus_type, &fsl_pamu_ops);
1066         bus_set_iommu(&pci_bus_type, &fsl_pamu_ops);
1067
1068         return ret;
1069 }