aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeffy Chen <jeffy.chen@rock-chips.com>2018-03-23 03:38:11 -0400
committerJoerg Roedel <jroedel@suse.de>2018-03-29 06:22:28 -0400
commit5fd577c3eac3bdb9aebfec01e9b3d7f07a14f2dd (patch)
tree5e79535085ecbbcdcce2d54da229f45eddc1467c
parent9176a303d971dc0fb35469c531c0d263667d2277 (diff)
iommu/rockchip: Use OF_IOMMU to attach devices automatically
Converts the rockchip-iommu driver to use the OF_IOMMU infrastructure, which allows attaching master devices to their IOMMUs automatically according to DT properties. Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r--drivers/iommu/rockchip-iommu.c135
1 files changed, 40 insertions, 95 deletions
diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 7970d21b9858..bd8580b897e9 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -19,6 +19,7 @@
19#include <linux/mm.h> 19#include <linux/mm.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/of.h> 21#include <linux/of.h>
22#include <linux/of_iommu.h>
22#include <linux/of_platform.h> 23#include <linux/of_platform.h>
23#include <linux/platform_device.h> 24#include <linux/platform_device.h>
24#include <linux/slab.h> 25#include <linux/slab.h>
@@ -104,6 +105,10 @@ struct rk_iommu {
104 struct iommu_domain *domain; /* domain to which iommu is attached */ 105 struct iommu_domain *domain; /* domain to which iommu is attached */
105}; 106};
106 107
108struct rk_iommudata {
109 struct rk_iommu *iommu;
110};
111
107static struct device *dma_dev; 112static struct device *dma_dev;
108 113
109static inline void rk_table_flush(struct rk_iommu_domain *dom, dma_addr_t dma, 114static inline void rk_table_flush(struct rk_iommu_domain *dom, dma_addr_t dma,
@@ -807,18 +812,9 @@ static size_t rk_iommu_unmap(struct iommu_domain *domain, unsigned long _iova,
807 812
808static struct rk_iommu *rk_iommu_from_dev(struct device *dev) 813static struct rk_iommu *rk_iommu_from_dev(struct device *dev)
809{ 814{
810 struct iommu_group *group; 815 struct rk_iommudata *data = dev->archdata.iommu;
811 struct device *iommu_dev;
812 struct rk_iommu *rk_iommu;
813 816
814 group = iommu_group_get(dev); 817 return data ? data->iommu : NULL;
815 if (!group)
816 return NULL;
817 iommu_dev = iommu_group_get_iommudata(group);
818 rk_iommu = dev_get_drvdata(iommu_dev);
819 iommu_group_put(group);
820
821 return rk_iommu;
822} 818}
823 819
824static int rk_iommu_attach_device(struct iommu_domain *domain, 820static int rk_iommu_attach_device(struct iommu_domain *domain,
@@ -989,110 +985,53 @@ static void rk_iommu_domain_free(struct iommu_domain *domain)
989 iommu_put_dma_cookie(&rk_domain->domain); 985 iommu_put_dma_cookie(&rk_domain->domain);
990} 986}
991 987
992static bool rk_iommu_is_dev_iommu_master(struct device *dev) 988static int rk_iommu_add_device(struct device *dev)
993{
994 struct device_node *np = dev->of_node;
995 int ret;
996
997 /*
998 * An iommu master has an iommus property containing a list of phandles
999 * to iommu nodes, each with an #iommu-cells property with value 0.
1000 */
1001 ret = of_count_phandle_with_args(np, "iommus", "#iommu-cells");
1002 return (ret > 0);
1003}
1004
1005static int rk_iommu_group_set_iommudata(struct iommu_group *group,
1006 struct device *dev)
1007{ 989{
1008 struct device_node *np = dev->of_node; 990 struct iommu_group *group;
1009 struct platform_device *pd; 991 struct rk_iommu *iommu;
1010 int ret;
1011 struct of_phandle_args args;
1012 992
1013 /* 993 iommu = rk_iommu_from_dev(dev);
1014 * An iommu master has an iommus property containing a list of phandles 994 if (!iommu)
1015 * to iommu nodes, each with an #iommu-cells property with value 0. 995 return -ENODEV;
1016 */
1017 ret = of_parse_phandle_with_args(np, "iommus", "#iommu-cells", 0,
1018 &args);
1019 if (ret) {
1020 dev_err(dev, "of_parse_phandle_with_args(%pOF) => %d\n",
1021 np, ret);
1022 return ret;
1023 }
1024 if (args.args_count != 0) {
1025 dev_err(dev, "incorrect number of iommu params found for %pOF (found %d, expected 0)\n",
1026 args.np, args.args_count);
1027 return -EINVAL;
1028 }
1029 996
1030 pd = of_find_device_by_node(args.np); 997 group = iommu_group_get_for_dev(dev);
1031 of_node_put(args.np); 998 if (IS_ERR(group))
1032 if (!pd) { 999 return PTR_ERR(group);
1033 dev_err(dev, "iommu %pOF not found\n", args.np); 1000 iommu_group_put(group);
1034 return -EPROBE_DEFER;
1035 }
1036 1001
1037 /* TODO(djkurtz): handle multiple slave iommus for a single master */ 1002 iommu_device_link(&iommu->iommu, dev);
1038 iommu_group_set_iommudata(group, &pd->dev, NULL);
1039 1003
1040 return 0; 1004 return 0;
1041} 1005}
1042 1006
1043static int rk_iommu_add_device(struct device *dev) 1007static void rk_iommu_remove_device(struct device *dev)
1044{ 1008{
1045 struct iommu_group *group;
1046 struct rk_iommu *iommu; 1009 struct rk_iommu *iommu;
1047 int ret;
1048
1049 if (!rk_iommu_is_dev_iommu_master(dev))
1050 return -ENODEV;
1051
1052 group = iommu_group_get(dev);
1053 if (!group) {
1054 group = iommu_group_alloc();
1055 if (IS_ERR(group)) {
1056 dev_err(dev, "Failed to allocate IOMMU group\n");
1057 return PTR_ERR(group);
1058 }
1059 }
1060
1061 ret = iommu_group_add_device(group, dev);
1062 if (ret)
1063 goto err_put_group;
1064
1065 ret = rk_iommu_group_set_iommudata(group, dev);
1066 if (ret)
1067 goto err_remove_device;
1068 1010
1069 iommu = rk_iommu_from_dev(dev); 1011 iommu = rk_iommu_from_dev(dev);
1070 if (iommu)
1071 iommu_device_link(&iommu->iommu, dev);
1072 1012
1073 iommu_group_put(group); 1013 iommu_device_unlink(&iommu->iommu, dev);
1074
1075 return 0;
1076
1077err_remove_device:
1078 iommu_group_remove_device(dev); 1014 iommu_group_remove_device(dev);
1079err_put_group:
1080 iommu_group_put(group);
1081 return ret;
1082} 1015}
1083 1016
1084static void rk_iommu_remove_device(struct device *dev) 1017static int rk_iommu_of_xlate(struct device *dev,
1018 struct of_phandle_args *args)
1085{ 1019{
1086 struct rk_iommu *iommu; 1020 struct platform_device *iommu_dev;
1021 struct rk_iommudata *data;
1087 1022
1088 if (!rk_iommu_is_dev_iommu_master(dev)) 1023 data = devm_kzalloc(dma_dev, sizeof(*data), GFP_KERNEL);
1089 return; 1024 if (!data)
1025 return -ENOMEM;
1090 1026
1091 iommu = rk_iommu_from_dev(dev); 1027 iommu_dev = of_find_device_by_node(args->np);
1092 if (iommu)
1093 iommu_device_unlink(&iommu->iommu, dev);
1094 1028
1095 iommu_group_remove_device(dev); 1029 data->iommu = platform_get_drvdata(iommu_dev);
1030 dev->archdata.iommu = data;
1031
1032 of_dev_put(iommu_dev);
1033
1034 return 0;
1096} 1035}
1097 1036
1098static const struct iommu_ops rk_iommu_ops = { 1037static const struct iommu_ops rk_iommu_ops = {
@@ -1106,7 +1045,9 @@ static const struct iommu_ops rk_iommu_ops = {
1106 .add_device = rk_iommu_add_device, 1045 .add_device = rk_iommu_add_device,
1107 .remove_device = rk_iommu_remove_device, 1046 .remove_device = rk_iommu_remove_device,
1108 .iova_to_phys = rk_iommu_iova_to_phys, 1047 .iova_to_phys = rk_iommu_iova_to_phys,
1048 .device_group = generic_device_group,
1109 .pgsize_bitmap = RK_IOMMU_PGSIZE_BITMAP, 1049 .pgsize_bitmap = RK_IOMMU_PGSIZE_BITMAP,
1050 .of_xlate = rk_iommu_of_xlate,
1110}; 1051};
1111 1052
1112static int rk_iommu_probe(struct platform_device *pdev) 1053static int rk_iommu_probe(struct platform_device *pdev)
@@ -1178,6 +1119,8 @@ static int rk_iommu_probe(struct platform_device *pdev)
1178 goto err_unprepare_clocks; 1119 goto err_unprepare_clocks;
1179 1120
1180 iommu_device_set_ops(&iommu->iommu, &rk_iommu_ops); 1121 iommu_device_set_ops(&iommu->iommu, &rk_iommu_ops);
1122 iommu_device_set_fwnode(&iommu->iommu, &dev->of_node->fwnode);
1123
1181 err = iommu_device_register(&iommu->iommu); 1124 err = iommu_device_register(&iommu->iommu);
1182 if (err) 1125 if (err)
1183 goto err_remove_sysfs; 1126 goto err_remove_sysfs;
@@ -1250,6 +1193,8 @@ static int __init rk_iommu_init(void)
1250} 1193}
1251subsys_initcall(rk_iommu_init); 1194subsys_initcall(rk_iommu_init);
1252 1195
1196IOMMU_OF_DECLARE(rk_iommu_of, "rockchip,iommu");
1197
1253MODULE_DESCRIPTION("IOMMU API for Rockchip"); 1198MODULE_DESCRIPTION("IOMMU API for Rockchip");
1254MODULE_AUTHOR("Simon Xue <xxm@rock-chips.com> and Daniel Kurtz <djkurtz@chromium.org>"); 1199MODULE_AUTHOR("Simon Xue <xxm@rock-chips.com> and Daniel Kurtz <djkurtz@chromium.org>");
1255MODULE_ALIAS("platform:rockchip-iommu"); 1200MODULE_ALIAS("platform:rockchip-iommu");