diff options
author | Sricharan R <sricharan@codeaurora.org> | 2016-06-13 07:36:05 -0400 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2016-06-21 07:57:13 -0400 |
commit | f78ebca8ff3d61fb45fef1274595a72d1314d955 (patch) | |
tree | 9f177fd118bc148b5a1e7595468579e378679377 | |
parent | f7f125ef0b0210a2eb269148df9a1d641521857b (diff) |
iommu/msm: Add support for generic master bindings
This adds the xlate callback which gets invoked during
device registration from DT. The master devices gets added
through this.
Signed-off-by: Sricharan R <sricharan@codeaurora.org>
Tested-by: Archit Taneja <architt@codeaurora.org>
Tested-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r-- | drivers/iommu/msm_iommu.c | 61 |
1 files changed, 59 insertions, 2 deletions
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index 792b3526b4a5..8ab064324a68 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/iommu.h> | 28 | #include <linux/iommu.h> |
29 | #include <linux/clk.h> | 29 | #include <linux/clk.h> |
30 | #include <linux/err.h> | 30 | #include <linux/err.h> |
31 | #include <linux/of_iommu.h> | ||
31 | 32 | ||
32 | #include <asm/cacheflush.h> | 33 | #include <asm/cacheflush.h> |
33 | #include <asm/sizes.h> | 34 | #include <asm/sizes.h> |
@@ -702,6 +703,54 @@ static void print_ctx_regs(void __iomem *base, int ctx) | |||
702 | GET_PRRR(base, ctx), GET_NMRR(base, ctx)); | 703 | GET_PRRR(base, ctx), GET_NMRR(base, ctx)); |
703 | } | 704 | } |
704 | 705 | ||
706 | static void insert_iommu_master(struct device *dev, | ||
707 | struct msm_iommu_dev **iommu, | ||
708 | struct of_phandle_args *spec) | ||
709 | { | ||
710 | struct msm_iommu_ctx_dev *master = dev->archdata.iommu; | ||
711 | int sid; | ||
712 | |||
713 | if (list_empty(&(*iommu)->ctx_list)) { | ||
714 | master = kzalloc(sizeof(*master), GFP_ATOMIC); | ||
715 | master->of_node = dev->of_node; | ||
716 | list_add(&master->list, &(*iommu)->ctx_list); | ||
717 | dev->archdata.iommu = master; | ||
718 | } | ||
719 | |||
720 | for (sid = 0; sid < master->num_mids; sid++) | ||
721 | if (master->mids[sid] == spec->args[0]) { | ||
722 | dev_warn(dev, "Stream ID 0x%hx repeated; ignoring\n", | ||
723 | sid); | ||
724 | return; | ||
725 | } | ||
726 | |||
727 | master->mids[master->num_mids++] = spec->args[0]; | ||
728 | } | ||
729 | |||
730 | static int qcom_iommu_of_xlate(struct device *dev, | ||
731 | struct of_phandle_args *spec) | ||
732 | { | ||
733 | struct msm_iommu_dev *iommu; | ||
734 | unsigned long flags; | ||
735 | int ret = 0; | ||
736 | |||
737 | spin_lock_irqsave(&msm_iommu_lock, flags); | ||
738 | list_for_each_entry(iommu, &qcom_iommu_devices, dev_node) | ||
739 | if (iommu->dev->of_node == spec->np) | ||
740 | break; | ||
741 | |||
742 | if (!iommu || iommu->dev->of_node != spec->np) { | ||
743 | ret = -ENODEV; | ||
744 | goto fail; | ||
745 | } | ||
746 | |||
747 | insert_iommu_master(dev, &iommu, spec); | ||
748 | fail: | ||
749 | spin_unlock_irqrestore(&msm_iommu_lock, flags); | ||
750 | |||
751 | return ret; | ||
752 | } | ||
753 | |||
705 | irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id) | 754 | irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id) |
706 | { | 755 | { |
707 | struct msm_iommu_dev *iommu = dev_id; | 756 | struct msm_iommu_dev *iommu = dev_id; |
@@ -737,7 +786,7 @@ fail: | |||
737 | return 0; | 786 | return 0; |
738 | } | 787 | } |
739 | 788 | ||
740 | static const struct iommu_ops msm_iommu_ops = { | 789 | static struct iommu_ops msm_iommu_ops = { |
741 | .capable = msm_iommu_capable, | 790 | .capable = msm_iommu_capable, |
742 | .domain_alloc = msm_iommu_domain_alloc, | 791 | .domain_alloc = msm_iommu_domain_alloc, |
743 | .domain_free = msm_iommu_domain_free, | 792 | .domain_free = msm_iommu_domain_free, |
@@ -748,6 +797,7 @@ static const struct iommu_ops msm_iommu_ops = { | |||
748 | .map_sg = default_iommu_map_sg, | 797 | .map_sg = default_iommu_map_sg, |
749 | .iova_to_phys = msm_iommu_iova_to_phys, | 798 | .iova_to_phys = msm_iommu_iova_to_phys, |
750 | .pgsize_bitmap = MSM_IOMMU_PGSIZES, | 799 | .pgsize_bitmap = MSM_IOMMU_PGSIZES, |
800 | .of_xlate = qcom_iommu_of_xlate, | ||
751 | }; | 801 | }; |
752 | 802 | ||
753 | static int msm_iommu_probe(struct platform_device *pdev) | 803 | static int msm_iommu_probe(struct platform_device *pdev) |
@@ -837,6 +887,7 @@ static int msm_iommu_probe(struct platform_device *pdev) | |||
837 | } | 887 | } |
838 | 888 | ||
839 | list_add(&iommu->dev_node, &qcom_iommu_devices); | 889 | list_add(&iommu->dev_node, &qcom_iommu_devices); |
890 | of_iommu_set_ops(pdev->dev.of_node, &msm_iommu_ops); | ||
840 | 891 | ||
841 | pr_info("device mapped at %p, irq %d with %d ctx banks\n", | 892 | pr_info("device mapped at %p, irq %d with %d ctx banks\n", |
842 | iommu->base, iommu->irq, iommu->ncb); | 893 | iommu->base, iommu->irq, iommu->ncb); |
@@ -935,7 +986,13 @@ static int __init msm_iommu_init(void) | |||
935 | return 0; | 986 | return 0; |
936 | } | 987 | } |
937 | 988 | ||
938 | subsys_initcall(msm_iommu_init); | 989 | static int __init msm_iommu_of_setup(struct device_node *np) |
990 | { | ||
991 | msm_iommu_init(); | ||
992 | return 0; | ||
993 | } | ||
994 | |||
995 | IOMMU_OF_DECLARE(msm_iommu_of, "qcom,apq8064-iommu", msm_iommu_of_setup); | ||
939 | 996 | ||
940 | MODULE_LICENSE("GPL v2"); | 997 | MODULE_LICENSE("GPL v2"); |
941 | MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>"); | 998 | MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>"); |