diff options
Diffstat (limited to 'drivers/iommu/mtk_iommu_v1.c')
| -rw-r--r-- | drivers/iommu/mtk_iommu_v1.c | 98 | 
1 files changed, 52 insertions, 46 deletions
| diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c index 82ddfe9170d4..5915d7b38211 100644 --- a/drivers/iommu/mtk_iommu_v1.c +++ b/drivers/iommu/mtk_iommu_v1.c @@ -20,6 +20,7 @@  #include <linux/iommu.h>  #include <linux/iopoll.h>  #include <linux/list.h> +#include <linux/module.h>  #include <linux/of_address.h>  #include <linux/of_iommu.h>  #include <linux/of_irq.h> @@ -423,23 +424,21 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev)  {  	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);  	struct of_phandle_args iommu_spec; -	struct of_phandle_iterator it;  	struct mtk_iommu_data *data; -	int err; +	int err, idx = 0; -	of_for_each_phandle(&it, err, dev->of_node, "iommus", -			"#iommu-cells", -1) { -		int count = of_phandle_iterator_args(&it, iommu_spec.args, -					MAX_PHANDLE_ARGS); -		iommu_spec.np = of_node_get(it.node); -		iommu_spec.args_count = count; +	while (!of_parse_phandle_with_args(dev->of_node, "iommus", +					   "#iommu-cells", +					   idx, &iommu_spec)) { -		mtk_iommu_create_mapping(dev, &iommu_spec); +		err = mtk_iommu_create_mapping(dev, &iommu_spec); +		of_node_put(iommu_spec.np); +		if (err) +			return ERR_PTR(err);  		/* dev->iommu_fwspec might have changed */  		fwspec = dev_iommu_fwspec_get(dev); - -		of_node_put(iommu_spec.np); +		idx++;  	}  	if (!fwspec || fwspec->ops != &mtk_iommu_ops) @@ -529,6 +528,7 @@ static const struct iommu_ops mtk_iommu_ops = {  	.def_domain_type = mtk_iommu_def_domain_type,  	.device_group	= generic_device_group,  	.pgsize_bitmap	= ~0UL << MT2701_IOMMU_PAGE_SHIFT, +	.owner          = THIS_MODULE,  };  static const struct of_device_id mtk_iommu_of_ids[] = { @@ -547,10 +547,8 @@ static int mtk_iommu_probe(struct platform_device *pdev)  	struct device			*dev = &pdev->dev;  	struct resource			*res;  	struct component_match		*match = NULL; -	struct of_phandle_args		larb_spec; -	struct of_phandle_iterator	it;  	void				*protect; -	int				larb_nr, ret, err; +	int				larb_nr, ret, i;  	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);  	if (!data) @@ -578,35 +576,33 @@ static int mtk_iommu_probe(struct platform_device *pdev)  	if (IS_ERR(data->bclk))  		return PTR_ERR(data->bclk); -	larb_nr = 0; -	of_for_each_phandle(&it, err, dev->of_node, -			"mediatek,larbs", NULL, 0) { +	larb_nr = of_count_phandle_with_args(dev->of_node, +					     "mediatek,larbs", NULL); +	if (larb_nr < 0) +		return larb_nr; + +	for (i = 0; i < larb_nr; i++) { +		struct device_node *larbnode;  		struct platform_device *plarbdev; -		int count = of_phandle_iterator_args(&it, larb_spec.args, -					MAX_PHANDLE_ARGS); -		if (count) -			continue; +		larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i); +		if (!larbnode) +			return -EINVAL; -		larb_spec.np = of_node_get(it.node); -		if (!of_device_is_available(larb_spec.np)) +		if (!of_device_is_available(larbnode)) { +			of_node_put(larbnode);  			continue; +		} -		plarbdev = of_find_device_by_node(larb_spec.np); +		plarbdev = of_find_device_by_node(larbnode);  		if (!plarbdev) { -			plarbdev = of_platform_device_create( -						larb_spec.np, NULL, -						platform_bus_type.dev_root); -			if (!plarbdev) { -				of_node_put(larb_spec.np); -				return -EPROBE_DEFER; -			} +			of_node_put(larbnode); +			return -EPROBE_DEFER;  		} +		data->larb_imu[i].dev = &plarbdev->dev; -		data->larb_imu[larb_nr].dev = &plarbdev->dev;  		component_match_add_release(dev, &match, release_of, -					    compare_of, larb_spec.np); -		larb_nr++; +					    compare_of, larbnode);  	}  	platform_set_drvdata(pdev, data); @@ -620,16 +616,28 @@ static int mtk_iommu_probe(struct platform_device *pdev)  	if (ret)  		return ret; -	iommu_device_set_ops(&data->iommu, &mtk_iommu_ops); - -	ret = iommu_device_register(&data->iommu); +	ret = iommu_device_register(&data->iommu, &mtk_iommu_ops, dev);  	if (ret) -		return ret; +		goto out_sysfs_remove; -	if (!iommu_present(&platform_bus_type)) -		bus_set_iommu(&platform_bus_type,  &mtk_iommu_ops); +	if (!iommu_present(&platform_bus_type)) { +		ret = bus_set_iommu(&platform_bus_type,  &mtk_iommu_ops); +		if (ret) +			goto out_dev_unreg; +	} + +	ret = component_master_add_with_match(dev, &mtk_iommu_com_ops, match); +	if (ret) +		goto out_bus_set_null; +	return ret; -	return component_master_add_with_match(dev, &mtk_iommu_com_ops, match); +out_bus_set_null: +	bus_set_iommu(&platform_bus_type, NULL); +out_dev_unreg: +	iommu_device_unregister(&data->iommu); +out_sysfs_remove: +	iommu_device_sysfs_remove(&data->iommu); +	return ret;  }  static int mtk_iommu_remove(struct platform_device *pdev) @@ -691,9 +699,7 @@ static struct platform_driver mtk_iommu_driver = {  		.pm = &mtk_iommu_pm_ops,  	}  }; +module_platform_driver(mtk_iommu_driver); -static int __init m4u_init(void) -{ -	return platform_driver_register(&mtk_iommu_driver); -} -subsys_initcall(m4u_init); +MODULE_DESCRIPTION("IOMMU API for MediaTek M4U v1 implementations"); +MODULE_LICENSE("GPL v2"); | 
