| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (c) 2011,2016 Samsung Electronics Co., Ltd. |
|---|
| 3 | 4 | * http://www.samsung.com |
|---|
| 4 | | - * |
|---|
| 5 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 6 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 7 | | - * published by the Free Software Foundation. |
|---|
| 8 | 5 | */ |
|---|
| 9 | 6 | |
|---|
| 10 | 7 | #ifdef CONFIG_EXYNOS_IOMMU_DEBUG |
|---|
| .. | .. |
|---|
| 176 | 173 | #define REG_V5_FAULT_AR_VA 0x070 |
|---|
| 177 | 174 | #define REG_V5_FAULT_AW_VA 0x080 |
|---|
| 178 | 175 | |
|---|
| 179 | | -#define has_sysmmu(dev) (dev->archdata.iommu != NULL) |
|---|
| 176 | +#define has_sysmmu(dev) (dev_iommu_priv_get(dev) != NULL) |
|---|
| 180 | 177 | |
|---|
| 181 | 178 | static struct device *dma_dev; |
|---|
| 182 | 179 | static struct kmem_cache *lv2table_kmem_cache; |
|---|
| .. | .. |
|---|
| 229 | 226 | }; |
|---|
| 230 | 227 | |
|---|
| 231 | 228 | /* |
|---|
| 232 | | - * This structure is attached to dev.archdata.iommu of the master device |
|---|
| 229 | + * This structure is attached to dev->iommu->priv of the master device |
|---|
| 233 | 230 | * on device add, contains a list of SYSMMU controllers defined by device tree, |
|---|
| 234 | 231 | * which are bound to given master device. It is usually referenced by 'owner' |
|---|
| 235 | 232 | * pointer. |
|---|
| .. | .. |
|---|
| 569 | 566 | |
|---|
| 570 | 567 | static const struct iommu_ops exynos_iommu_ops; |
|---|
| 571 | 568 | |
|---|
| 572 | | -static int __init exynos_sysmmu_probe(struct platform_device *pdev) |
|---|
| 569 | +static int exynos_sysmmu_probe(struct platform_device *pdev) |
|---|
| 573 | 570 | { |
|---|
| 574 | 571 | int irq, ret; |
|---|
| 575 | 572 | struct device *dev = &pdev->dev; |
|---|
| .. | .. |
|---|
| 586 | 583 | return PTR_ERR(data->sfrbase); |
|---|
| 587 | 584 | |
|---|
| 588 | 585 | irq = platform_get_irq(pdev, 0); |
|---|
| 589 | | - if (irq <= 0) { |
|---|
| 590 | | - dev_err(dev, "Unable to find IRQ resource\n"); |
|---|
| 586 | + if (irq <= 0) |
|---|
| 591 | 587 | return irq; |
|---|
| 592 | | - } |
|---|
| 593 | 588 | |
|---|
| 594 | 589 | ret = devm_request_irq(dev, irq, exynos_sysmmu_irq, 0, |
|---|
| 595 | 590 | dev_name(dev), data); |
|---|
| .. | .. |
|---|
| 640 | 635 | |
|---|
| 641 | 636 | ret = iommu_device_register(&data->iommu); |
|---|
| 642 | 637 | if (ret) |
|---|
| 643 | | - return ret; |
|---|
| 638 | + goto err_iommu_register; |
|---|
| 644 | 639 | |
|---|
| 645 | 640 | platform_set_drvdata(pdev, data); |
|---|
| 646 | 641 | |
|---|
| .. | .. |
|---|
| 667 | 662 | pm_runtime_enable(dev); |
|---|
| 668 | 663 | |
|---|
| 669 | 664 | return 0; |
|---|
| 665 | + |
|---|
| 666 | +err_iommu_register: |
|---|
| 667 | + iommu_device_sysfs_remove(&data->iommu); |
|---|
| 668 | + return ret; |
|---|
| 670 | 669 | } |
|---|
| 671 | 670 | |
|---|
| 672 | 671 | static int __maybe_unused exynos_sysmmu_suspend(struct device *dev) |
|---|
| .. | .. |
|---|
| 675 | 674 | struct device *master = data->master; |
|---|
| 676 | 675 | |
|---|
| 677 | 676 | if (master) { |
|---|
| 678 | | - struct exynos_iommu_owner *owner = master->archdata.iommu; |
|---|
| 677 | + struct exynos_iommu_owner *owner = dev_iommu_priv_get(master); |
|---|
| 679 | 678 | |
|---|
| 680 | 679 | mutex_lock(&owner->rpm_lock); |
|---|
| 681 | 680 | if (data->domain) { |
|---|
| .. | .. |
|---|
| 693 | 692 | struct device *master = data->master; |
|---|
| 694 | 693 | |
|---|
| 695 | 694 | if (master) { |
|---|
| 696 | | - struct exynos_iommu_owner *owner = master->archdata.iommu; |
|---|
| 695 | + struct exynos_iommu_owner *owner = dev_iommu_priv_get(master); |
|---|
| 697 | 696 | |
|---|
| 698 | 697 | mutex_lock(&owner->rpm_lock); |
|---|
| 699 | 698 | if (data->domain) { |
|---|
| .. | .. |
|---|
| 726 | 725 | } |
|---|
| 727 | 726 | }; |
|---|
| 728 | 727 | |
|---|
| 729 | | -static inline void update_pte(sysmmu_pte_t *ent, sysmmu_pte_t val) |
|---|
| 728 | +static inline void exynos_iommu_set_pte(sysmmu_pte_t *ent, sysmmu_pte_t val) |
|---|
| 730 | 729 | { |
|---|
| 731 | 730 | dma_sync_single_for_cpu(dma_dev, virt_to_phys(ent), sizeof(*ent), |
|---|
| 732 | 731 | DMA_TO_DEVICE); |
|---|
| .. | .. |
|---|
| 842 | 841 | static void exynos_iommu_detach_device(struct iommu_domain *iommu_domain, |
|---|
| 843 | 842 | struct device *dev) |
|---|
| 844 | 843 | { |
|---|
| 845 | | - struct exynos_iommu_owner *owner = dev->archdata.iommu; |
|---|
| 846 | 844 | struct exynos_iommu_domain *domain = to_exynos_domain(iommu_domain); |
|---|
| 845 | + struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev); |
|---|
| 847 | 846 | phys_addr_t pagetable = virt_to_phys(domain->pgtable); |
|---|
| 848 | 847 | struct sysmmu_drvdata *data, *next; |
|---|
| 849 | 848 | unsigned long flags; |
|---|
| .. | .. |
|---|
| 880 | 879 | static int exynos_iommu_attach_device(struct iommu_domain *iommu_domain, |
|---|
| 881 | 880 | struct device *dev) |
|---|
| 882 | 881 | { |
|---|
| 883 | | - struct exynos_iommu_owner *owner = dev->archdata.iommu; |
|---|
| 884 | 882 | struct exynos_iommu_domain *domain = to_exynos_domain(iommu_domain); |
|---|
| 883 | + struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev); |
|---|
| 885 | 884 | struct sysmmu_drvdata *data; |
|---|
| 886 | 885 | phys_addr_t pagetable = virt_to_phys(domain->pgtable); |
|---|
| 887 | 886 | unsigned long flags; |
|---|
| .. | .. |
|---|
| 938 | 937 | if (!pent) |
|---|
| 939 | 938 | return ERR_PTR(-ENOMEM); |
|---|
| 940 | 939 | |
|---|
| 941 | | - update_pte(sent, mk_lv1ent_page(virt_to_phys(pent))); |
|---|
| 940 | + exynos_iommu_set_pte(sent, mk_lv1ent_page(virt_to_phys(pent))); |
|---|
| 942 | 941 | kmemleak_ignore(pent); |
|---|
| 943 | 942 | *pgcounter = NUM_LV2ENTRIES; |
|---|
| 944 | 943 | handle = dma_map_single(dma_dev, pent, LV2TABLE_SIZE, |
|---|
| .. | .. |
|---|
| 999 | 998 | *pgcnt = 0; |
|---|
| 1000 | 999 | } |
|---|
| 1001 | 1000 | |
|---|
| 1002 | | - update_pte(sent, mk_lv1ent_sect(paddr, prot)); |
|---|
| 1001 | + exynos_iommu_set_pte(sent, mk_lv1ent_sect(paddr, prot)); |
|---|
| 1003 | 1002 | |
|---|
| 1004 | 1003 | spin_lock(&domain->lock); |
|---|
| 1005 | 1004 | if (lv1ent_page_zero(sent)) { |
|---|
| .. | .. |
|---|
| 1023 | 1022 | if (WARN_ON(!lv2ent_fault(pent))) |
|---|
| 1024 | 1023 | return -EADDRINUSE; |
|---|
| 1025 | 1024 | |
|---|
| 1026 | | - update_pte(pent, mk_lv2ent_spage(paddr, prot)); |
|---|
| 1025 | + exynos_iommu_set_pte(pent, mk_lv2ent_spage(paddr, prot)); |
|---|
| 1027 | 1026 | *pgcnt -= 1; |
|---|
| 1028 | 1027 | } else { /* size == LPAGE_SIZE */ |
|---|
| 1029 | 1028 | int i; |
|---|
| .. | .. |
|---|
| 1078 | 1077 | */ |
|---|
| 1079 | 1078 | static int exynos_iommu_map(struct iommu_domain *iommu_domain, |
|---|
| 1080 | 1079 | unsigned long l_iova, phys_addr_t paddr, size_t size, |
|---|
| 1081 | | - int prot) |
|---|
| 1080 | + int prot, gfp_t gfp) |
|---|
| 1082 | 1081 | { |
|---|
| 1083 | 1082 | struct exynos_iommu_domain *domain = to_exynos_domain(iommu_domain); |
|---|
| 1084 | 1083 | sysmmu_pte_t *entry; |
|---|
| .. | .. |
|---|
| 1133 | 1132 | } |
|---|
| 1134 | 1133 | |
|---|
| 1135 | 1134 | static size_t exynos_iommu_unmap(struct iommu_domain *iommu_domain, |
|---|
| 1136 | | - unsigned long l_iova, size_t size) |
|---|
| 1135 | + unsigned long l_iova, size_t size, |
|---|
| 1136 | + struct iommu_iotlb_gather *gather) |
|---|
| 1137 | 1137 | { |
|---|
| 1138 | 1138 | struct exynos_iommu_domain *domain = to_exynos_domain(iommu_domain); |
|---|
| 1139 | 1139 | sysmmu_iova_t iova = (sysmmu_iova_t)l_iova; |
|---|
| .. | .. |
|---|
| 1154 | 1154 | } |
|---|
| 1155 | 1155 | |
|---|
| 1156 | 1156 | /* workaround for h/w bug in System MMU v3.3 */ |
|---|
| 1157 | | - update_pte(ent, ZERO_LV2LINK); |
|---|
| 1157 | + exynos_iommu_set_pte(ent, ZERO_LV2LINK); |
|---|
| 1158 | 1158 | size = SECT_SIZE; |
|---|
| 1159 | 1159 | goto done; |
|---|
| 1160 | 1160 | } |
|---|
| .. | .. |
|---|
| 1175 | 1175 | } |
|---|
| 1176 | 1176 | |
|---|
| 1177 | 1177 | if (lv2ent_small(ent)) { |
|---|
| 1178 | | - update_pte(ent, 0); |
|---|
| 1178 | + exynos_iommu_set_pte(ent, 0); |
|---|
| 1179 | 1179 | size = SPAGE_SIZE; |
|---|
| 1180 | 1180 | domain->lv2entcnt[lv1ent_offset(iova)] += 1; |
|---|
| 1181 | 1181 | goto done; |
|---|
| .. | .. |
|---|
| 1239 | 1239 | return phys; |
|---|
| 1240 | 1240 | } |
|---|
| 1241 | 1241 | |
|---|
| 1242 | | -static int exynos_iommu_add_device(struct device *dev) |
|---|
| 1242 | +static struct iommu_device *exynos_iommu_probe_device(struct device *dev) |
|---|
| 1243 | 1243 | { |
|---|
| 1244 | | - struct exynos_iommu_owner *owner = dev->archdata.iommu; |
|---|
| 1244 | + struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev); |
|---|
| 1245 | 1245 | struct sysmmu_drvdata *data; |
|---|
| 1246 | | - struct iommu_group *group; |
|---|
| 1247 | 1246 | |
|---|
| 1248 | 1247 | if (!has_sysmmu(dev)) |
|---|
| 1249 | | - return -ENODEV; |
|---|
| 1250 | | - |
|---|
| 1251 | | - group = iommu_group_get_for_dev(dev); |
|---|
| 1252 | | - |
|---|
| 1253 | | - if (IS_ERR(group)) |
|---|
| 1254 | | - return PTR_ERR(group); |
|---|
| 1248 | + return ERR_PTR(-ENODEV); |
|---|
| 1255 | 1249 | |
|---|
| 1256 | 1250 | list_for_each_entry(data, &owner->controllers, owner_node) { |
|---|
| 1257 | 1251 | /* |
|---|
| .. | .. |
|---|
| 1263 | 1257 | DL_FLAG_STATELESS | |
|---|
| 1264 | 1258 | DL_FLAG_PM_RUNTIME); |
|---|
| 1265 | 1259 | } |
|---|
| 1266 | | - iommu_group_put(group); |
|---|
| 1267 | 1260 | |
|---|
| 1268 | | - return 0; |
|---|
| 1261 | + /* There is always at least one entry, see exynos_iommu_of_xlate() */ |
|---|
| 1262 | + data = list_first_entry(&owner->controllers, |
|---|
| 1263 | + struct sysmmu_drvdata, owner_node); |
|---|
| 1264 | + |
|---|
| 1265 | + return &data->iommu; |
|---|
| 1269 | 1266 | } |
|---|
| 1270 | 1267 | |
|---|
| 1271 | | -static void exynos_iommu_remove_device(struct device *dev) |
|---|
| 1268 | +static void exynos_iommu_release_device(struct device *dev) |
|---|
| 1272 | 1269 | { |
|---|
| 1273 | | - struct exynos_iommu_owner *owner = dev->archdata.iommu; |
|---|
| 1270 | + struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev); |
|---|
| 1274 | 1271 | struct sysmmu_drvdata *data; |
|---|
| 1275 | 1272 | |
|---|
| 1276 | 1273 | if (!has_sysmmu(dev)) |
|---|
| .. | .. |
|---|
| 1286 | 1283 | iommu_group_put(group); |
|---|
| 1287 | 1284 | } |
|---|
| 1288 | 1285 | } |
|---|
| 1289 | | - iommu_group_remove_device(dev); |
|---|
| 1290 | 1286 | |
|---|
| 1291 | 1287 | list_for_each_entry(data, &owner->controllers, owner_node) |
|---|
| 1292 | 1288 | device_link_del(data->link); |
|---|
| .. | .. |
|---|
| 1295 | 1291 | static int exynos_iommu_of_xlate(struct device *dev, |
|---|
| 1296 | 1292 | struct of_phandle_args *spec) |
|---|
| 1297 | 1293 | { |
|---|
| 1298 | | - struct exynos_iommu_owner *owner = dev->archdata.iommu; |
|---|
| 1299 | 1294 | struct platform_device *sysmmu = of_find_device_by_node(spec->np); |
|---|
| 1295 | + struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev); |
|---|
| 1300 | 1296 | struct sysmmu_drvdata *data, *entry; |
|---|
| 1301 | 1297 | |
|---|
| 1302 | 1298 | if (!sysmmu) |
|---|
| .. | .. |
|---|
| 1317 | 1313 | |
|---|
| 1318 | 1314 | INIT_LIST_HEAD(&owner->controllers); |
|---|
| 1319 | 1315 | mutex_init(&owner->rpm_lock); |
|---|
| 1320 | | - dev->archdata.iommu = owner; |
|---|
| 1316 | + dev_iommu_priv_set(dev, owner); |
|---|
| 1321 | 1317 | } |
|---|
| 1322 | 1318 | |
|---|
| 1323 | 1319 | list_for_each_entry(entry, &owner->controllers, owner_node) |
|---|
| .. | .. |
|---|
| 1339 | 1335 | .unmap = exynos_iommu_unmap, |
|---|
| 1340 | 1336 | .iova_to_phys = exynos_iommu_iova_to_phys, |
|---|
| 1341 | 1337 | .device_group = generic_device_group, |
|---|
| 1342 | | - .add_device = exynos_iommu_add_device, |
|---|
| 1343 | | - .remove_device = exynos_iommu_remove_device, |
|---|
| 1338 | + .probe_device = exynos_iommu_probe_device, |
|---|
| 1339 | + .release_device = exynos_iommu_release_device, |
|---|
| 1344 | 1340 | .pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE, |
|---|
| 1345 | 1341 | .of_xlate = exynos_iommu_of_xlate, |
|---|
| 1346 | 1342 | }; |
|---|