diff options
Diffstat (limited to 'drivers/iommu/omap-iommu.c')
-rw-r--r-- | drivers/iommu/omap-iommu.c | 80 |
1 files changed, 37 insertions, 43 deletions
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index 8f32b2bf758..d8edd979d01 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c | |||
@@ -33,6 +33,9 @@ | |||
33 | (__i < (n)) && (cr = __iotlb_read_cr((obj), __i), true); \ | 33 | (__i < (n)) && (cr = __iotlb_read_cr((obj), __i), true); \ |
34 | __i++) | 34 | __i++) |
35 | 35 | ||
36 | /* bitmap of the page sizes currently supported */ | ||
37 | #define OMAP_IOMMU_PGSIZES (SZ_4K | SZ_64K | SZ_1M | SZ_16M) | ||
38 | |||
36 | /** | 39 | /** |
37 | * struct omap_iommu_domain - omap iommu domain | 40 | * struct omap_iommu_domain - omap iommu domain |
38 | * @pgtable: the page table | 41 | * @pgtable: the page table |
@@ -86,20 +89,24 @@ EXPORT_SYMBOL_GPL(omap_uninstall_iommu_arch); | |||
86 | 89 | ||
87 | /** | 90 | /** |
88 | * omap_iommu_save_ctx - Save registers for pm off-mode support | 91 | * omap_iommu_save_ctx - Save registers for pm off-mode support |
89 | * @obj: target iommu | 92 | * @dev: client device |
90 | **/ | 93 | **/ |
91 | void omap_iommu_save_ctx(struct omap_iommu *obj) | 94 | void omap_iommu_save_ctx(struct device *dev) |
92 | { | 95 | { |
96 | struct omap_iommu *obj = dev_to_omap_iommu(dev); | ||
97 | |||
93 | arch_iommu->save_ctx(obj); | 98 | arch_iommu->save_ctx(obj); |
94 | } | 99 | } |
95 | EXPORT_SYMBOL_GPL(omap_iommu_save_ctx); | 100 | EXPORT_SYMBOL_GPL(omap_iommu_save_ctx); |
96 | 101 | ||
97 | /** | 102 | /** |
98 | * omap_iommu_restore_ctx - Restore registers for pm off-mode support | 103 | * omap_iommu_restore_ctx - Restore registers for pm off-mode support |
99 | * @obj: target iommu | 104 | * @dev: client device |
100 | **/ | 105 | **/ |
101 | void omap_iommu_restore_ctx(struct omap_iommu *obj) | 106 | void omap_iommu_restore_ctx(struct device *dev) |
102 | { | 107 | { |
108 | struct omap_iommu *obj = dev_to_omap_iommu(dev); | ||
109 | |||
103 | arch_iommu->restore_ctx(obj); | 110 | arch_iommu->restore_ctx(obj); |
104 | } | 111 | } |
105 | EXPORT_SYMBOL_GPL(omap_iommu_restore_ctx); | 112 | EXPORT_SYMBOL_GPL(omap_iommu_restore_ctx); |
@@ -820,35 +827,23 @@ static int device_match_by_alias(struct device *dev, void *data) | |||
820 | } | 827 | } |
821 | 828 | ||
822 | /** | 829 | /** |
823 | * omap_find_iommu_device() - find an omap iommu device by name | ||
824 | * @name: name of the iommu device | ||
825 | * | ||
826 | * The generic iommu API requires the caller to provide the device | ||
827 | * he wishes to attach to a certain iommu domain. | ||
828 | * | ||
829 | * Drivers generally should not bother with this as it should just | ||
830 | * be taken care of by the DMA-API using dev_archdata. | ||
831 | * | ||
832 | * This function is provided as an interim solution until the latter | ||
833 | * materializes, and omap3isp is fully migrated to the DMA-API. | ||
834 | */ | ||
835 | struct device *omap_find_iommu_device(const char *name) | ||
836 | { | ||
837 | return driver_find_device(&omap_iommu_driver.driver, NULL, | ||
838 | (void *)name, | ||
839 | device_match_by_alias); | ||
840 | } | ||
841 | EXPORT_SYMBOL_GPL(omap_find_iommu_device); | ||
842 | |||
843 | /** | ||
844 | * omap_iommu_attach() - attach iommu device to an iommu domain | 830 | * omap_iommu_attach() - attach iommu device to an iommu domain |
845 | * @dev: target omap iommu device | 831 | * @name: name of target omap iommu device |
846 | * @iopgd: page table | 832 | * @iopgd: page table |
847 | **/ | 833 | **/ |
848 | static struct omap_iommu *omap_iommu_attach(struct device *dev, u32 *iopgd) | 834 | static struct omap_iommu *omap_iommu_attach(const char *name, u32 *iopgd) |
849 | { | 835 | { |
850 | int err = -ENOMEM; | 836 | int err = -ENOMEM; |
851 | struct omap_iommu *obj = to_iommu(dev); | 837 | struct device *dev; |
838 | struct omap_iommu *obj; | ||
839 | |||
840 | dev = driver_find_device(&omap_iommu_driver.driver, NULL, | ||
841 | (void *)name, | ||
842 | device_match_by_alias); | ||
843 | if (!dev) | ||
844 | return NULL; | ||
845 | |||
846 | obj = to_iommu(dev); | ||
852 | 847 | ||
853 | spin_lock(&obj->iommu_lock); | 848 | spin_lock(&obj->iommu_lock); |
854 | 849 | ||
@@ -1019,12 +1014,11 @@ static void iopte_cachep_ctor(void *iopte) | |||
1019 | } | 1014 | } |
1020 | 1015 | ||
1021 | static int omap_iommu_map(struct iommu_domain *domain, unsigned long da, | 1016 | static int omap_iommu_map(struct iommu_domain *domain, unsigned long da, |
1022 | phys_addr_t pa, int order, int prot) | 1017 | phys_addr_t pa, size_t bytes, int prot) |
1023 | { | 1018 | { |
1024 | struct omap_iommu_domain *omap_domain = domain->priv; | 1019 | struct omap_iommu_domain *omap_domain = domain->priv; |
1025 | struct omap_iommu *oiommu = omap_domain->iommu_dev; | 1020 | struct omap_iommu *oiommu = omap_domain->iommu_dev; |
1026 | struct device *dev = oiommu->dev; | 1021 | struct device *dev = oiommu->dev; |
1027 | size_t bytes = PAGE_SIZE << order; | ||
1028 | struct iotlb_entry e; | 1022 | struct iotlb_entry e; |
1029 | int omap_pgsz; | 1023 | int omap_pgsz; |
1030 | u32 ret, flags; | 1024 | u32 ret, flags; |
@@ -1049,19 +1043,16 @@ static int omap_iommu_map(struct iommu_domain *domain, unsigned long da, | |||
1049 | return ret; | 1043 | return ret; |
1050 | } | 1044 | } |
1051 | 1045 | ||
1052 | static int omap_iommu_unmap(struct iommu_domain *domain, unsigned long da, | 1046 | static size_t omap_iommu_unmap(struct iommu_domain *domain, unsigned long da, |
1053 | int order) | 1047 | size_t size) |
1054 | { | 1048 | { |
1055 | struct omap_iommu_domain *omap_domain = domain->priv; | 1049 | struct omap_iommu_domain *omap_domain = domain->priv; |
1056 | struct omap_iommu *oiommu = omap_domain->iommu_dev; | 1050 | struct omap_iommu *oiommu = omap_domain->iommu_dev; |
1057 | struct device *dev = oiommu->dev; | 1051 | struct device *dev = oiommu->dev; |
1058 | size_t unmap_size; | ||
1059 | |||
1060 | dev_dbg(dev, "unmapping da 0x%lx order %d\n", da, order); | ||
1061 | 1052 | ||
1062 | unmap_size = iopgtable_clear_entry(oiommu, da); | 1053 | dev_dbg(dev, "unmapping da 0x%lx size %u\n", da, size); |
1063 | 1054 | ||
1064 | return unmap_size ? get_order(unmap_size) : -EINVAL; | 1055 | return iopgtable_clear_entry(oiommu, da); |
1065 | } | 1056 | } |
1066 | 1057 | ||
1067 | static int | 1058 | static int |
@@ -1069,6 +1060,7 @@ omap_iommu_attach_dev(struct iommu_domain *domain, struct device *dev) | |||
1069 | { | 1060 | { |
1070 | struct omap_iommu_domain *omap_domain = domain->priv; | 1061 | struct omap_iommu_domain *omap_domain = domain->priv; |
1071 | struct omap_iommu *oiommu; | 1062 | struct omap_iommu *oiommu; |
1063 | struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; | ||
1072 | int ret = 0; | 1064 | int ret = 0; |
1073 | 1065 | ||
1074 | spin_lock(&omap_domain->lock); | 1066 | spin_lock(&omap_domain->lock); |
@@ -1081,14 +1073,14 @@ omap_iommu_attach_dev(struct iommu_domain *domain, struct device *dev) | |||
1081 | } | 1073 | } |
1082 | 1074 | ||
1083 | /* get a handle to and enable the omap iommu */ | 1075 | /* get a handle to and enable the omap iommu */ |
1084 | oiommu = omap_iommu_attach(dev, omap_domain->pgtable); | 1076 | oiommu = omap_iommu_attach(arch_data->name, omap_domain->pgtable); |
1085 | if (IS_ERR(oiommu)) { | 1077 | if (IS_ERR(oiommu)) { |
1086 | ret = PTR_ERR(oiommu); | 1078 | ret = PTR_ERR(oiommu); |
1087 | dev_err(dev, "can't get omap iommu: %d\n", ret); | 1079 | dev_err(dev, "can't get omap iommu: %d\n", ret); |
1088 | goto out; | 1080 | goto out; |
1089 | } | 1081 | } |
1090 | 1082 | ||
1091 | omap_domain->iommu_dev = oiommu; | 1083 | omap_domain->iommu_dev = arch_data->iommu_dev = oiommu; |
1092 | oiommu->domain = domain; | 1084 | oiommu->domain = domain; |
1093 | 1085 | ||
1094 | out: | 1086 | out: |
@@ -1100,7 +1092,8 @@ static void omap_iommu_detach_dev(struct iommu_domain *domain, | |||
1100 | struct device *dev) | 1092 | struct device *dev) |
1101 | { | 1093 | { |
1102 | struct omap_iommu_domain *omap_domain = domain->priv; | 1094 | struct omap_iommu_domain *omap_domain = domain->priv; |
1103 | struct omap_iommu *oiommu = to_iommu(dev); | 1095 | struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; |
1096 | struct omap_iommu *oiommu = dev_to_omap_iommu(dev); | ||
1104 | 1097 | ||
1105 | spin_lock(&omap_domain->lock); | 1098 | spin_lock(&omap_domain->lock); |
1106 | 1099 | ||
@@ -1114,7 +1107,7 @@ static void omap_iommu_detach_dev(struct iommu_domain *domain, | |||
1114 | 1107 | ||
1115 | omap_iommu_detach(oiommu); | 1108 | omap_iommu_detach(oiommu); |
1116 | 1109 | ||
1117 | omap_domain->iommu_dev = NULL; | 1110 | omap_domain->iommu_dev = arch_data->iommu_dev = NULL; |
1118 | 1111 | ||
1119 | out: | 1112 | out: |
1120 | spin_unlock(&omap_domain->lock); | 1113 | spin_unlock(&omap_domain->lock); |
@@ -1183,14 +1176,14 @@ static phys_addr_t omap_iommu_iova_to_phys(struct iommu_domain *domain, | |||
1183 | else if (iopte_is_large(*pte)) | 1176 | else if (iopte_is_large(*pte)) |
1184 | ret = omap_iommu_translate(*pte, da, IOLARGE_MASK); | 1177 | ret = omap_iommu_translate(*pte, da, IOLARGE_MASK); |
1185 | else | 1178 | else |
1186 | dev_err(dev, "bogus pte 0x%x", *pte); | 1179 | dev_err(dev, "bogus pte 0x%x, da 0x%lx", *pte, da); |
1187 | } else { | 1180 | } else { |
1188 | if (iopgd_is_section(*pgd)) | 1181 | if (iopgd_is_section(*pgd)) |
1189 | ret = omap_iommu_translate(*pgd, da, IOSECTION_MASK); | 1182 | ret = omap_iommu_translate(*pgd, da, IOSECTION_MASK); |
1190 | else if (iopgd_is_super(*pgd)) | 1183 | else if (iopgd_is_super(*pgd)) |
1191 | ret = omap_iommu_translate(*pgd, da, IOSUPER_MASK); | 1184 | ret = omap_iommu_translate(*pgd, da, IOSUPER_MASK); |
1192 | else | 1185 | else |
1193 | dev_err(dev, "bogus pgd 0x%x", *pgd); | 1186 | dev_err(dev, "bogus pgd 0x%x, da 0x%lx", *pgd, da); |
1194 | } | 1187 | } |
1195 | 1188 | ||
1196 | return ret; | 1189 | return ret; |
@@ -1211,6 +1204,7 @@ static struct iommu_ops omap_iommu_ops = { | |||
1211 | .unmap = omap_iommu_unmap, | 1204 | .unmap = omap_iommu_unmap, |
1212 | .iova_to_phys = omap_iommu_iova_to_phys, | 1205 | .iova_to_phys = omap_iommu_iova_to_phys, |
1213 | .domain_has_cap = omap_iommu_domain_has_cap, | 1206 | .domain_has_cap = omap_iommu_domain_has_cap, |
1207 | .pgsize_bitmap = OMAP_IOMMU_PGSIZES, | ||
1214 | }; | 1208 | }; |
1215 | 1209 | ||
1216 | static int __init omap_iommu_init(void) | 1210 | static int __init omap_iommu_init(void) |