diff options
Diffstat (limited to 'arch/arm/plat-omap/iommu.c')
-rw-r--r-- | arch/arm/plat-omap/iommu.c | 69 |
1 files changed, 48 insertions, 21 deletions
diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c index b1107c08da56..8a51fd58f656 100644 --- a/arch/arm/plat-omap/iommu.c +++ b/arch/arm/plat-omap/iommu.c | |||
@@ -104,6 +104,9 @@ static int iommu_enable(struct iommu *obj) | |||
104 | if (!obj) | 104 | if (!obj) |
105 | return -EINVAL; | 105 | return -EINVAL; |
106 | 106 | ||
107 | if (!arch_iommu) | ||
108 | return -ENODEV; | ||
109 | |||
107 | clk_enable(obj->clk); | 110 | clk_enable(obj->clk); |
108 | 111 | ||
109 | err = arch_iommu->enable(obj); | 112 | err = arch_iommu->enable(obj); |
@@ -780,25 +783,19 @@ static void iopgtable_clear_entry_all(struct iommu *obj) | |||
780 | */ | 783 | */ |
781 | static irqreturn_t iommu_fault_handler(int irq, void *data) | 784 | static irqreturn_t iommu_fault_handler(int irq, void *data) |
782 | { | 785 | { |
783 | u32 stat, da; | 786 | u32 da, errs; |
784 | u32 *iopgd, *iopte; | 787 | u32 *iopgd, *iopte; |
785 | int err = -EIO; | ||
786 | struct iommu *obj = data; | 788 | struct iommu *obj = data; |
787 | 789 | ||
788 | if (!obj->refcount) | 790 | if (!obj->refcount) |
789 | return IRQ_NONE; | 791 | return IRQ_NONE; |
790 | 792 | ||
791 | /* Dynamic loading TLB or PTE */ | ||
792 | if (obj->isr) | ||
793 | err = obj->isr(obj); | ||
794 | |||
795 | if (!err) | ||
796 | return IRQ_HANDLED; | ||
797 | |||
798 | clk_enable(obj->clk); | 793 | clk_enable(obj->clk); |
799 | stat = iommu_report_fault(obj, &da); | 794 | errs = iommu_report_fault(obj, &da); |
800 | clk_disable(obj->clk); | 795 | clk_disable(obj->clk); |
801 | if (!stat) | 796 | |
797 | /* Fault callback or TLB/PTE Dynamic loading */ | ||
798 | if (obj->isr && !obj->isr(obj, da, errs, obj->isr_priv)) | ||
802 | return IRQ_HANDLED; | 799 | return IRQ_HANDLED; |
803 | 800 | ||
804 | iommu_disable(obj); | 801 | iommu_disable(obj); |
@@ -806,15 +803,16 @@ static irqreturn_t iommu_fault_handler(int irq, void *data) | |||
806 | iopgd = iopgd_offset(obj, da); | 803 | iopgd = iopgd_offset(obj, da); |
807 | 804 | ||
808 | if (!iopgd_is_table(*iopgd)) { | 805 | if (!iopgd_is_table(*iopgd)) { |
809 | dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x\n", __func__, | 806 | dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p " |
810 | da, iopgd, *iopgd); | 807 | "*pgd:px%08x\n", obj->name, errs, da, iopgd, *iopgd); |
811 | return IRQ_NONE; | 808 | return IRQ_NONE; |
812 | } | 809 | } |
813 | 810 | ||
814 | iopte = iopte_offset(iopgd, da); | 811 | iopte = iopte_offset(iopgd, da); |
815 | 812 | ||
816 | dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x pte:%p *pte:%08x\n", | 813 | dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p *pgd:0x%08x " |
817 | __func__, da, iopgd, *iopgd, iopte, *iopte); | 814 | "pte:0x%p *pte:0x%08x\n", obj->name, errs, da, iopgd, *iopgd, |
815 | iopte, *iopte); | ||
818 | 816 | ||
819 | return IRQ_NONE; | 817 | return IRQ_NONE; |
820 | } | 818 | } |
@@ -917,6 +915,33 @@ void iommu_put(struct iommu *obj) | |||
917 | } | 915 | } |
918 | EXPORT_SYMBOL_GPL(iommu_put); | 916 | EXPORT_SYMBOL_GPL(iommu_put); |
919 | 917 | ||
918 | int iommu_set_isr(const char *name, | ||
919 | int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs, | ||
920 | void *priv), | ||
921 | void *isr_priv) | ||
922 | { | ||
923 | struct device *dev; | ||
924 | struct iommu *obj; | ||
925 | |||
926 | dev = driver_find_device(&omap_iommu_driver.driver, NULL, (void *)name, | ||
927 | device_match_by_alias); | ||
928 | if (!dev) | ||
929 | return -ENODEV; | ||
930 | |||
931 | obj = to_iommu(dev); | ||
932 | mutex_lock(&obj->iommu_lock); | ||
933 | if (obj->refcount != 0) { | ||
934 | mutex_unlock(&obj->iommu_lock); | ||
935 | return -EBUSY; | ||
936 | } | ||
937 | obj->isr = isr; | ||
938 | obj->isr_priv = isr_priv; | ||
939 | mutex_unlock(&obj->iommu_lock); | ||
940 | |||
941 | return 0; | ||
942 | } | ||
943 | EXPORT_SYMBOL_GPL(iommu_set_isr); | ||
944 | |||
920 | /* | 945 | /* |
921 | * OMAP Device MMU(IOMMU) detection | 946 | * OMAP Device MMU(IOMMU) detection |
922 | */ | 947 | */ |
@@ -957,11 +982,6 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev) | |||
957 | err = -ENODEV; | 982 | err = -ENODEV; |
958 | goto err_mem; | 983 | goto err_mem; |
959 | } | 984 | } |
960 | obj->regbase = ioremap(res->start, resource_size(res)); | ||
961 | if (!obj->regbase) { | ||
962 | err = -ENOMEM; | ||
963 | goto err_mem; | ||
964 | } | ||
965 | 985 | ||
966 | res = request_mem_region(res->start, resource_size(res), | 986 | res = request_mem_region(res->start, resource_size(res), |
967 | dev_name(&pdev->dev)); | 987 | dev_name(&pdev->dev)); |
@@ -970,6 +990,12 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev) | |||
970 | goto err_mem; | 990 | goto err_mem; |
971 | } | 991 | } |
972 | 992 | ||
993 | obj->regbase = ioremap(res->start, resource_size(res)); | ||
994 | if (!obj->regbase) { | ||
995 | err = -ENOMEM; | ||
996 | goto err_ioremap; | ||
997 | } | ||
998 | |||
973 | irq = platform_get_irq(pdev, 0); | 999 | irq = platform_get_irq(pdev, 0); |
974 | if (irq < 0) { | 1000 | if (irq < 0) { |
975 | err = -ENODEV; | 1001 | err = -ENODEV; |
@@ -998,8 +1024,9 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev) | |||
998 | err_pgd: | 1024 | err_pgd: |
999 | free_irq(irq, obj); | 1025 | free_irq(irq, obj); |
1000 | err_irq: | 1026 | err_irq: |
1001 | release_mem_region(res->start, resource_size(res)); | ||
1002 | iounmap(obj->regbase); | 1027 | iounmap(obj->regbase); |
1028 | err_ioremap: | ||
1029 | release_mem_region(res->start, resource_size(res)); | ||
1003 | err_mem: | 1030 | err_mem: |
1004 | clk_put(obj->clk); | 1031 | clk_put(obj->clk); |
1005 | err_clk: | 1032 | err_clk: |