diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-26 14:09:17 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-26 14:09:17 -0500 |
commit | f6c0ffa8f0b0781f4954cb06f0a81d6c10c1b434 (patch) | |
tree | f99190661706d18f129497a4ef2d37822c9c34db | |
parent | 42a0a1b0fd343888c59afc8b243a77bcec2cc11c (diff) | |
parent | 604542b824f72fa5d7fd977af277538c1e15b5f0 (diff) |
Merge tag 'iommu-updates-v3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
Pull IOMMU Updates from Joerg Roedel:
"Besides some fixes and cleanups in the code there are three more
important changes to point out this time:
* New IOMMU driver for the ARM SHMOBILE platform
* An IOMMU-API extension for non-paging IOMMUs (required for
upcoming PAMU driver)
* Rework of the way the Tegra IOMMU driver accesses its
registetrs - register windows are easier to extend now.
There are also a few changes to non-iommu code, but that is acked by
the respective maintainers."
* tag 'iommu-updates-v3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: (23 commits)
iommu/tegra: assume CONFIG_OF in SMMU driver
iommu/tegra: assume CONFIG_OF in gart driver
iommu/amd: Remove redundant NULL check before dma_ops_domain_free().
iommu/amd: Initialize device table after dma_ops
iommu/vt-d: Zero out allocated memory in dmar_enable_qi
iommu/tegra: smmu: Fix incorrect mask for regbase
iommu/exynos: Make exynos_sysmmu_disable static
ARM: mach-shmobile: r8a7740: Add IPMMU device
ARM: mach-shmobile: sh73a0: Add IPMMU device
ARM: mach-shmobile: sh7372: Add IPMMU device
iommu/shmobile: Add iommu driver for Renesas IPMMU modules
iommu: Add DOMAIN_ATTR_WINDOWS domain attribute
iommu: Add domain window handling functions
iommu: Implement DOMAIN_ATTR_PAGING attribute
iommu: Check for valid pgsize_bitmap in iommu_map/unmap
iommu: Make sure DOMAIN_ATTR_MAX is really the maximum
iommu/tegra: smmu: Change SMMU's dependency on ARCH_TEGRA
iommu/tegra: smmu: Use helper function to check for valid register offset
iommu/tegra: smmu: Support variable MMIO ranges/blocks
iommu/tegra: Add missing spinlock initialization
...
28 files changed, 1043 insertions, 462 deletions
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 85afb031b676..70f94c87479d 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig | |||
@@ -105,11 +105,6 @@ config EXYNOS4_SETUP_FIMD0 | |||
105 | help | 105 | help |
106 | Common setup code for FIMD0. | 106 | Common setup code for FIMD0. |
107 | 107 | ||
108 | config EXYNOS_DEV_SYSMMU | ||
109 | bool | ||
110 | help | ||
111 | Common setup code for SYSTEM MMU in EXYNOS platforms | ||
112 | |||
113 | config EXYNOS4_DEV_USB_OHCI | 108 | config EXYNOS4_DEV_USB_OHCI |
114 | bool | 109 | bool |
115 | help | 110 | help |
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index b189881657ec..435757e57bb4 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile | |||
@@ -52,7 +52,6 @@ obj-$(CONFIG_ARCH_EXYNOS4) += dev-audio.o | |||
52 | obj-$(CONFIG_EXYNOS4_DEV_AHCI) += dev-ahci.o | 52 | obj-$(CONFIG_EXYNOS4_DEV_AHCI) += dev-ahci.o |
53 | obj-$(CONFIG_EXYNOS_DEV_DMA) += dma.o | 53 | obj-$(CONFIG_EXYNOS_DEV_DMA) += dma.o |
54 | obj-$(CONFIG_EXYNOS4_DEV_USB_OHCI) += dev-ohci.o | 54 | obj-$(CONFIG_EXYNOS4_DEV_USB_OHCI) += dev-ohci.o |
55 | obj-$(CONFIG_EXYNOS_DEV_SYSMMU) += dev-sysmmu.o | ||
56 | 55 | ||
57 | obj-$(CONFIG_ARCH_EXYNOS) += setup-i2c0.o | 56 | obj-$(CONFIG_ARCH_EXYNOS) += setup-i2c0.o |
58 | obj-$(CONFIG_EXYNOS4_SETUP_FIMC) += setup-fimc.o | 57 | obj-$(CONFIG_EXYNOS4_SETUP_FIMC) += setup-fimc.o |
diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c index bbcb3dea0d40..8a8468d83c8c 100644 --- a/arch/arm/mach-exynos/clock-exynos4.c +++ b/arch/arm/mach-exynos/clock-exynos4.c | |||
@@ -24,7 +24,6 @@ | |||
24 | 24 | ||
25 | #include <mach/map.h> | 25 | #include <mach/map.h> |
26 | #include <mach/regs-clock.h> | 26 | #include <mach/regs-clock.h> |
27 | #include <mach/sysmmu.h> | ||
28 | 27 | ||
29 | #include "common.h" | 28 | #include "common.h" |
30 | #include "clock-exynos4.h" | 29 | #include "clock-exynos4.h" |
@@ -709,53 +708,53 @@ static struct clk exynos4_init_clocks_off[] = { | |||
709 | .enable = exynos4_clk_ip_peril_ctrl, | 708 | .enable = exynos4_clk_ip_peril_ctrl, |
710 | .ctrlbit = (1 << 14), | 709 | .ctrlbit = (1 << 14), |
711 | }, { | 710 | }, { |
712 | .name = SYSMMU_CLOCK_NAME, | 711 | .name = "sysmmu", |
713 | .devname = SYSMMU_CLOCK_DEVNAME(mfc_l, 0), | 712 | .devname = "exynos-sysmmu.0", |
714 | .enable = exynos4_clk_ip_mfc_ctrl, | 713 | .enable = exynos4_clk_ip_mfc_ctrl, |
715 | .ctrlbit = (1 << 1), | 714 | .ctrlbit = (1 << 1), |
716 | }, { | 715 | }, { |
717 | .name = SYSMMU_CLOCK_NAME, | 716 | .name = "sysmmu", |
718 | .devname = SYSMMU_CLOCK_DEVNAME(mfc_r, 1), | 717 | .devname = "exynos-sysmmu.1", |
719 | .enable = exynos4_clk_ip_mfc_ctrl, | 718 | .enable = exynos4_clk_ip_mfc_ctrl, |
720 | .ctrlbit = (1 << 2), | 719 | .ctrlbit = (1 << 2), |
721 | }, { | 720 | }, { |
722 | .name = SYSMMU_CLOCK_NAME, | 721 | .name = "sysmmu", |
723 | .devname = SYSMMU_CLOCK_DEVNAME(tv, 2), | 722 | .devname = "exynos-sysmmu.2", |
724 | .enable = exynos4_clk_ip_tv_ctrl, | 723 | .enable = exynos4_clk_ip_tv_ctrl, |
725 | .ctrlbit = (1 << 4), | 724 | .ctrlbit = (1 << 4), |
726 | }, { | 725 | }, { |
727 | .name = SYSMMU_CLOCK_NAME, | 726 | .name = "sysmmu", |
728 | .devname = SYSMMU_CLOCK_DEVNAME(jpeg, 3), | 727 | .devname = "exynos-sysmmu.3", |
729 | .enable = exynos4_clk_ip_cam_ctrl, | 728 | .enable = exynos4_clk_ip_cam_ctrl, |
730 | .ctrlbit = (1 << 11), | 729 | .ctrlbit = (1 << 11), |
731 | }, { | 730 | }, { |
732 | .name = SYSMMU_CLOCK_NAME, | 731 | .name = "sysmmu", |
733 | .devname = SYSMMU_CLOCK_DEVNAME(rot, 4), | 732 | .devname = "exynos-sysmmu.4", |
734 | .enable = exynos4_clk_ip_image_ctrl, | 733 | .enable = exynos4_clk_ip_image_ctrl, |
735 | .ctrlbit = (1 << 4), | 734 | .ctrlbit = (1 << 4), |
736 | }, { | 735 | }, { |
737 | .name = SYSMMU_CLOCK_NAME, | 736 | .name = "sysmmu", |
738 | .devname = SYSMMU_CLOCK_DEVNAME(fimc0, 5), | 737 | .devname = "exynos-sysmmu.5", |
739 | .enable = exynos4_clk_ip_cam_ctrl, | 738 | .enable = exynos4_clk_ip_cam_ctrl, |
740 | .ctrlbit = (1 << 7), | 739 | .ctrlbit = (1 << 7), |
741 | }, { | 740 | }, { |
742 | .name = SYSMMU_CLOCK_NAME, | 741 | .name = "sysmmu", |
743 | .devname = SYSMMU_CLOCK_DEVNAME(fimc1, 6), | 742 | .devname = "exynos-sysmmu.6", |
744 | .enable = exynos4_clk_ip_cam_ctrl, | 743 | .enable = exynos4_clk_ip_cam_ctrl, |
745 | .ctrlbit = (1 << 8), | 744 | .ctrlbit = (1 << 8), |
746 | }, { | 745 | }, { |
747 | .name = SYSMMU_CLOCK_NAME, | 746 | .name = "sysmmu", |
748 | .devname = SYSMMU_CLOCK_DEVNAME(fimc2, 7), | 747 | .devname = "exynos-sysmmu.7", |
749 | .enable = exynos4_clk_ip_cam_ctrl, | 748 | .enable = exynos4_clk_ip_cam_ctrl, |
750 | .ctrlbit = (1 << 9), | 749 | .ctrlbit = (1 << 9), |
751 | }, { | 750 | }, { |
752 | .name = SYSMMU_CLOCK_NAME, | 751 | .name = "sysmmu", |
753 | .devname = SYSMMU_CLOCK_DEVNAME(fimc3, 8), | 752 | .devname = "exynos-sysmmu.8", |
754 | .enable = exynos4_clk_ip_cam_ctrl, | 753 | .enable = exynos4_clk_ip_cam_ctrl, |
755 | .ctrlbit = (1 << 10), | 754 | .ctrlbit = (1 << 10), |
756 | }, { | 755 | }, { |
757 | .name = SYSMMU_CLOCK_NAME, | 756 | .name = "sysmmu", |
758 | .devname = SYSMMU_CLOCK_DEVNAME(fimd0, 10), | 757 | .devname = "exynos-sysmmu.10", |
759 | .enable = exynos4_clk_ip_lcd0_ctrl, | 758 | .enable = exynos4_clk_ip_lcd0_ctrl, |
760 | .ctrlbit = (1 << 4), | 759 | .ctrlbit = (1 << 4), |
761 | } | 760 | } |
diff --git a/arch/arm/mach-exynos/clock-exynos4210.c b/arch/arm/mach-exynos/clock-exynos4210.c index fed4c26e9dad..19af9f783c56 100644 --- a/arch/arm/mach-exynos/clock-exynos4210.c +++ b/arch/arm/mach-exynos/clock-exynos4210.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <mach/hardware.h> | 26 | #include <mach/hardware.h> |
27 | #include <mach/map.h> | 27 | #include <mach/map.h> |
28 | #include <mach/regs-clock.h> | 28 | #include <mach/regs-clock.h> |
29 | #include <mach/sysmmu.h> | ||
30 | 29 | ||
31 | #include "common.h" | 30 | #include "common.h" |
32 | #include "clock-exynos4.h" | 31 | #include "clock-exynos4.h" |
@@ -129,13 +128,13 @@ static struct clk init_clocks_off[] = { | |||
129 | .enable = exynos4_clk_ip_lcd1_ctrl, | 128 | .enable = exynos4_clk_ip_lcd1_ctrl, |
130 | .ctrlbit = (1 << 0), | 129 | .ctrlbit = (1 << 0), |
131 | }, { | 130 | }, { |
132 | .name = SYSMMU_CLOCK_NAME, | 131 | .name = "sysmmu", |
133 | .devname = SYSMMU_CLOCK_DEVNAME(2d, 14), | 132 | .devname = "exynos-sysmmu.9", |
134 | .enable = exynos4_clk_ip_image_ctrl, | 133 | .enable = exynos4_clk_ip_image_ctrl, |
135 | .ctrlbit = (1 << 3), | 134 | .ctrlbit = (1 << 3), |
136 | }, { | 135 | }, { |
137 | .name = SYSMMU_CLOCK_NAME, | 136 | .name = "sysmmu", |
138 | .devname = SYSMMU_CLOCK_DEVNAME(fimd1, 11), | 137 | .devname = "exynos-sysmmu.11", |
139 | .enable = exynos4_clk_ip_lcd1_ctrl, | 138 | .enable = exynos4_clk_ip_lcd1_ctrl, |
140 | .ctrlbit = (1 << 4), | 139 | .ctrlbit = (1 << 4), |
141 | }, { | 140 | }, { |
diff --git a/arch/arm/mach-exynos/clock-exynos4212.c b/arch/arm/mach-exynos/clock-exynos4212.c index 8fba0b5fb8ab..529476f8ec71 100644 --- a/arch/arm/mach-exynos/clock-exynos4212.c +++ b/arch/arm/mach-exynos/clock-exynos4212.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <mach/hardware.h> | 26 | #include <mach/hardware.h> |
27 | #include <mach/map.h> | 27 | #include <mach/map.h> |
28 | #include <mach/regs-clock.h> | 28 | #include <mach/regs-clock.h> |
29 | #include <mach/sysmmu.h> | ||
30 | 29 | ||
31 | #include "common.h" | 30 | #include "common.h" |
32 | #include "clock-exynos4.h" | 31 | #include "clock-exynos4.h" |
@@ -111,21 +110,31 @@ static struct clksrc_clk clksrcs[] = { | |||
111 | 110 | ||
112 | static struct clk init_clocks_off[] = { | 111 | static struct clk init_clocks_off[] = { |
113 | { | 112 | { |
114 | .name = SYSMMU_CLOCK_NAME, | 113 | .name = "sysmmu", |
115 | .devname = SYSMMU_CLOCK_DEVNAME(2d, 14), | 114 | .devname = "exynos-sysmmu.9", |
116 | .enable = exynos4_clk_ip_dmc_ctrl, | 115 | .enable = exynos4_clk_ip_dmc_ctrl, |
117 | .ctrlbit = (1 << 24), | 116 | .ctrlbit = (1 << 24), |
118 | }, { | 117 | }, { |
119 | .name = SYSMMU_CLOCK_NAME, | 118 | .name = "sysmmu", |
120 | .devname = SYSMMU_CLOCK_DEVNAME(isp, 9), | 119 | .devname = "exynos-sysmmu.12", |
121 | .enable = exynos4212_clk_ip_isp0_ctrl, | 120 | .enable = exynos4212_clk_ip_isp0_ctrl, |
122 | .ctrlbit = (7 << 8), | 121 | .ctrlbit = (7 << 8), |
123 | }, { | 122 | }, { |
124 | .name = SYSMMU_CLOCK_NAME2, | 123 | .name = "sysmmu", |
125 | .devname = SYSMMU_CLOCK_DEVNAME(isp, 9), | 124 | .devname = "exynos-sysmmu.13", |
126 | .enable = exynos4212_clk_ip_isp1_ctrl, | 125 | .enable = exynos4212_clk_ip_isp1_ctrl, |
127 | .ctrlbit = (1 << 4), | 126 | .ctrlbit = (1 << 4), |
128 | }, { | 127 | }, { |
128 | .name = "sysmmu", | ||
129 | .devname = "exynos-sysmmu.14", | ||
130 | .enable = exynos4212_clk_ip_isp0_ctrl, | ||
131 | .ctrlbit = (1 << 11), | ||
132 | }, { | ||
133 | .name = "sysmmu", | ||
134 | .devname = "exynos-sysmmu.15", | ||
135 | .enable = exynos4212_clk_ip_isp0_ctrl, | ||
136 | .ctrlbit = (1 << 12), | ||
137 | }, { | ||
129 | .name = "flite", | 138 | .name = "flite", |
130 | .devname = "exynos-fimc-lite.0", | 139 | .devname = "exynos-fimc-lite.0", |
131 | .enable = exynos4212_clk_ip_isp0_ctrl, | 140 | .enable = exynos4212_clk_ip_isp0_ctrl, |
diff --git a/arch/arm/mach-exynos/clock-exynos5.c b/arch/arm/mach-exynos/clock-exynos5.c index e9d7b80bae49..b0ea31fc9fb8 100644 --- a/arch/arm/mach-exynos/clock-exynos5.c +++ b/arch/arm/mach-exynos/clock-exynos5.c | |||
@@ -24,7 +24,6 @@ | |||
24 | 24 | ||
25 | #include <mach/map.h> | 25 | #include <mach/map.h> |
26 | #include <mach/regs-clock.h> | 26 | #include <mach/regs-clock.h> |
27 | #include <mach/sysmmu.h> | ||
28 | 27 | ||
29 | #include "common.h" | 28 | #include "common.h" |
30 | 29 | ||
@@ -859,73 +858,78 @@ static struct clk exynos5_init_clocks_off[] = { | |||
859 | .enable = exynos5_clk_ip_gscl_ctrl, | 858 | .enable = exynos5_clk_ip_gscl_ctrl, |
860 | .ctrlbit = (1 << 3), | 859 | .ctrlbit = (1 << 3), |
861 | }, { | 860 | }, { |
862 | .name = SYSMMU_CLOCK_NAME, | 861 | .name = "sysmmu", |
863 | .devname = SYSMMU_CLOCK_DEVNAME(mfc_l, 0), | 862 | .devname = "exynos-sysmmu.1", |
864 | .enable = &exynos5_clk_ip_mfc_ctrl, | 863 | .enable = &exynos5_clk_ip_mfc_ctrl, |
865 | .ctrlbit = (1 << 1), | 864 | .ctrlbit = (1 << 1), |
866 | }, { | 865 | }, { |
867 | .name = SYSMMU_CLOCK_NAME, | 866 | .name = "sysmmu", |
868 | .devname = SYSMMU_CLOCK_DEVNAME(mfc_r, 1), | 867 | .devname = "exynos-sysmmu.0", |
869 | .enable = &exynos5_clk_ip_mfc_ctrl, | 868 | .enable = &exynos5_clk_ip_mfc_ctrl, |
870 | .ctrlbit = (1 << 2), | 869 | .ctrlbit = (1 << 2), |
871 | }, { | 870 | }, { |
872 | .name = SYSMMU_CLOCK_NAME, | 871 | .name = "sysmmu", |
873 | .devname = SYSMMU_CLOCK_DEVNAME(tv, 2), | 872 | .devname = "exynos-sysmmu.2", |
874 | .enable = &exynos5_clk_ip_disp1_ctrl, | 873 | .enable = &exynos5_clk_ip_disp1_ctrl, |
875 | .ctrlbit = (1 << 9) | 874 | .ctrlbit = (1 << 9) |
876 | }, { | 875 | }, { |
877 | .name = SYSMMU_CLOCK_NAME, | 876 | .name = "sysmmu", |
878 | .devname = SYSMMU_CLOCK_DEVNAME(jpeg, 3), | 877 | .devname = "exynos-sysmmu.3", |
879 | .enable = &exynos5_clk_ip_gen_ctrl, | 878 | .enable = &exynos5_clk_ip_gen_ctrl, |
880 | .ctrlbit = (1 << 7), | 879 | .ctrlbit = (1 << 7), |
881 | }, { | 880 | }, { |
882 | .name = SYSMMU_CLOCK_NAME, | 881 | .name = "sysmmu", |
883 | .devname = SYSMMU_CLOCK_DEVNAME(rot, 4), | 882 | .devname = "exynos-sysmmu.4", |
884 | .enable = &exynos5_clk_ip_gen_ctrl, | 883 | .enable = &exynos5_clk_ip_gen_ctrl, |
885 | .ctrlbit = (1 << 6) | 884 | .ctrlbit = (1 << 6) |
886 | }, { | 885 | }, { |
887 | .name = SYSMMU_CLOCK_NAME, | 886 | .name = "sysmmu", |
888 | .devname = SYSMMU_CLOCK_DEVNAME(gsc0, 5), | 887 | .devname = "exynos-sysmmu.5", |
889 | .enable = &exynos5_clk_ip_gscl_ctrl, | 888 | .enable = &exynos5_clk_ip_gscl_ctrl, |
890 | .ctrlbit = (1 << 7), | 889 | .ctrlbit = (1 << 7), |
891 | }, { | 890 | }, { |
892 | .name = SYSMMU_CLOCK_NAME, | 891 | .name = "sysmmu", |
893 | .devname = SYSMMU_CLOCK_DEVNAME(gsc1, 6), | 892 | .devname = "exynos-sysmmu.6", |
894 | .enable = &exynos5_clk_ip_gscl_ctrl, | 893 | .enable = &exynos5_clk_ip_gscl_ctrl, |
895 | .ctrlbit = (1 << 8), | 894 | .ctrlbit = (1 << 8), |
896 | }, { | 895 | }, { |
897 | .name = SYSMMU_CLOCK_NAME, | 896 | .name = "sysmmu", |
898 | .devname = SYSMMU_CLOCK_DEVNAME(gsc2, 7), | 897 | .devname = "exynos-sysmmu.7", |
899 | .enable = &exynos5_clk_ip_gscl_ctrl, | 898 | .enable = &exynos5_clk_ip_gscl_ctrl, |
900 | .ctrlbit = (1 << 9), | 899 | .ctrlbit = (1 << 9), |
901 | }, { | 900 | }, { |
902 | .name = SYSMMU_CLOCK_NAME, | 901 | .name = "sysmmu", |
903 | .devname = SYSMMU_CLOCK_DEVNAME(gsc3, 8), | 902 | .devname = "exynos-sysmmu.8", |
904 | .enable = &exynos5_clk_ip_gscl_ctrl, | 903 | .enable = &exynos5_clk_ip_gscl_ctrl, |
905 | .ctrlbit = (1 << 10), | 904 | .ctrlbit = (1 << 10), |
906 | }, { | 905 | }, { |
907 | .name = SYSMMU_CLOCK_NAME, | 906 | .name = "sysmmu", |
908 | .devname = SYSMMU_CLOCK_DEVNAME(isp, 9), | 907 | .devname = "exynos-sysmmu.9", |
909 | .enable = &exynos5_clk_ip_isp0_ctrl, | 908 | .enable = &exynos5_clk_ip_isp0_ctrl, |
910 | .ctrlbit = (0x3F << 8), | 909 | .ctrlbit = (0x3F << 8), |
911 | }, { | 910 | }, { |
912 | .name = SYSMMU_CLOCK_NAME2, | 911 | .name = "sysmmu", |
913 | .devname = SYSMMU_CLOCK_DEVNAME(isp, 9), | 912 | .devname = "exynos-sysmmu.10", |
914 | .enable = &exynos5_clk_ip_isp1_ctrl, | 913 | .enable = &exynos5_clk_ip_isp1_ctrl, |
915 | .ctrlbit = (0xF << 4), | 914 | .ctrlbit = (0xF << 4), |
916 | }, { | 915 | }, { |
917 | .name = SYSMMU_CLOCK_NAME, | 916 | .name = "sysmmu", |
918 | .devname = SYSMMU_CLOCK_DEVNAME(camif0, 12), | 917 | .devname = "exynos-sysmmu.11", |
918 | .enable = &exynos5_clk_ip_disp1_ctrl, | ||
919 | .ctrlbit = (1 << 8) | ||
920 | }, { | ||
921 | .name = "sysmmu", | ||
922 | .devname = "exynos-sysmmu.12", | ||
919 | .enable = &exynos5_clk_ip_gscl_ctrl, | 923 | .enable = &exynos5_clk_ip_gscl_ctrl, |
920 | .ctrlbit = (1 << 11), | 924 | .ctrlbit = (1 << 11), |
921 | }, { | 925 | }, { |
922 | .name = SYSMMU_CLOCK_NAME, | 926 | .name = "sysmmu", |
923 | .devname = SYSMMU_CLOCK_DEVNAME(camif1, 13), | 927 | .devname = "exynos-sysmmu.13", |
924 | .enable = &exynos5_clk_ip_gscl_ctrl, | 928 | .enable = &exynos5_clk_ip_gscl_ctrl, |
925 | .ctrlbit = (1 << 12), | 929 | .ctrlbit = (1 << 12), |
926 | }, { | 930 | }, { |
927 | .name = SYSMMU_CLOCK_NAME, | 931 | .name = "sysmmu", |
928 | .devname = SYSMMU_CLOCK_DEVNAME(2d, 14), | 932 | .devname = "exynos-sysmmu.14", |
929 | .enable = &exynos5_clk_ip_acp_ctrl, | 933 | .enable = &exynos5_clk_ip_acp_ctrl, |
930 | .ctrlbit = (1 << 7) | 934 | .ctrlbit = (1 << 7) |
931 | } | 935 | } |
diff --git a/arch/arm/mach-exynos/dev-sysmmu.c b/arch/arm/mach-exynos/dev-sysmmu.c deleted file mode 100644 index c5b1ea301df0..000000000000 --- a/arch/arm/mach-exynos/dev-sysmmu.c +++ /dev/null | |||
@@ -1,274 +0,0 @@ | |||
1 | /* linux/arch/arm/mach-exynos/dev-sysmmu.c | ||
2 | * | ||
3 | * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * EXYNOS - System MMU support | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/dma-mapping.h> | ||
15 | |||
16 | #include <plat/cpu.h> | ||
17 | |||
18 | #include <mach/map.h> | ||
19 | #include <mach/irqs.h> | ||
20 | #include <mach/sysmmu.h> | ||
21 | |||
22 | static u64 exynos_sysmmu_dma_mask = DMA_BIT_MASK(32); | ||
23 | |||
24 | #define SYSMMU_PLATFORM_DEVICE(ipname, devid) \ | ||
25 | static struct sysmmu_platform_data platdata_##ipname = { \ | ||
26 | .dbgname = #ipname, \ | ||
27 | }; \ | ||
28 | struct platform_device SYSMMU_PLATDEV(ipname) = \ | ||
29 | { \ | ||
30 | .name = SYSMMU_DEVNAME_BASE, \ | ||
31 | .id = devid, \ | ||
32 | .dev = { \ | ||
33 | .dma_mask = &exynos_sysmmu_dma_mask, \ | ||
34 | .coherent_dma_mask = DMA_BIT_MASK(32), \ | ||
35 | .platform_data = &platdata_##ipname, \ | ||
36 | }, \ | ||
37 | } | ||
38 | |||
39 | SYSMMU_PLATFORM_DEVICE(mfc_l, 0); | ||
40 | SYSMMU_PLATFORM_DEVICE(mfc_r, 1); | ||
41 | SYSMMU_PLATFORM_DEVICE(tv, 2); | ||
42 | SYSMMU_PLATFORM_DEVICE(jpeg, 3); | ||
43 | SYSMMU_PLATFORM_DEVICE(rot, 4); | ||
44 | SYSMMU_PLATFORM_DEVICE(fimc0, 5); /* fimc* and gsc* exist exclusively */ | ||
45 | SYSMMU_PLATFORM_DEVICE(fimc1, 6); | ||
46 | SYSMMU_PLATFORM_DEVICE(fimc2, 7); | ||
47 | SYSMMU_PLATFORM_DEVICE(fimc3, 8); | ||
48 | SYSMMU_PLATFORM_DEVICE(gsc0, 5); | ||
49 | SYSMMU_PLATFORM_DEVICE(gsc1, 6); | ||
50 | SYSMMU_PLATFORM_DEVICE(gsc2, 7); | ||
51 | SYSMMU_PLATFORM_DEVICE(gsc3, 8); | ||
52 | SYSMMU_PLATFORM_DEVICE(isp, 9); | ||
53 | SYSMMU_PLATFORM_DEVICE(fimd0, 10); | ||
54 | SYSMMU_PLATFORM_DEVICE(fimd1, 11); | ||
55 | SYSMMU_PLATFORM_DEVICE(camif0, 12); | ||
56 | SYSMMU_PLATFORM_DEVICE(camif1, 13); | ||
57 | SYSMMU_PLATFORM_DEVICE(2d, 14); | ||
58 | |||
59 | #define SYSMMU_RESOURCE_NAME(core, ipname) sysmmures_##core##_##ipname | ||
60 | |||
61 | #define SYSMMU_RESOURCE(core, ipname) \ | ||
62 | static struct resource SYSMMU_RESOURCE_NAME(core, ipname)[] __initdata = | ||
63 | |||
64 | #define DEFINE_SYSMMU_RESOURCE(core, mem, irq) \ | ||
65 | DEFINE_RES_MEM_NAMED(core##_PA_SYSMMU_##mem, SZ_4K, #mem), \ | ||
66 | DEFINE_RES_IRQ_NAMED(core##_IRQ_SYSMMU_##irq##_0, #mem) | ||
67 | |||
68 | #define SYSMMU_RESOURCE_DEFINE(core, ipname, mem, irq) \ | ||
69 | SYSMMU_RESOURCE(core, ipname) { \ | ||
70 | DEFINE_SYSMMU_RESOURCE(core, mem, irq) \ | ||
71 | } | ||
72 | |||
73 | struct sysmmu_resource_map { | ||
74 | struct platform_device *pdev; | ||
75 | struct resource *res; | ||
76 | u32 rnum; | ||
77 | struct device *pdd; | ||
78 | char *clocknames; | ||
79 | }; | ||
80 | |||
81 | #define SYSMMU_RESOURCE_MAPPING(core, ipname, resname) { \ | ||
82 | .pdev = &SYSMMU_PLATDEV(ipname), \ | ||
83 | .res = SYSMMU_RESOURCE_NAME(EXYNOS##core, resname), \ | ||
84 | .rnum = ARRAY_SIZE(SYSMMU_RESOURCE_NAME(EXYNOS##core, resname)),\ | ||
85 | .clocknames = SYSMMU_CLOCK_NAME, \ | ||
86 | } | ||
87 | |||
88 | #define SYSMMU_RESOURCE_MAPPING_MC(core, ipname, resname, pdata) { \ | ||
89 | .pdev = &SYSMMU_PLATDEV(ipname), \ | ||
90 | .res = SYSMMU_RESOURCE_NAME(EXYNOS##core, resname), \ | ||
91 | .rnum = ARRAY_SIZE(SYSMMU_RESOURCE_NAME(EXYNOS##core, resname)),\ | ||
92 | .clocknames = SYSMMU_CLOCK_NAME "," SYSMMU_CLOCK_NAME2, \ | ||
93 | } | ||
94 | |||
95 | #ifdef CONFIG_EXYNOS_DEV_PD | ||
96 | #define SYSMMU_RESOURCE_MAPPING_PD(core, ipname, resname, pd) { \ | ||
97 | .pdev = &SYSMMU_PLATDEV(ipname), \ | ||
98 | .res = &SYSMMU_RESOURCE_NAME(EXYNOS##core, resname), \ | ||
99 | .rnum = ARRAY_SIZE(SYSMMU_RESOURCE_NAME(EXYNOS##core, resname)),\ | ||
100 | .clocknames = SYSMMU_CLOCK_NAME, \ | ||
101 | .pdd = &exynos##core##_device_pd[pd].dev, \ | ||
102 | } | ||
103 | |||
104 | #define SYSMMU_RESOURCE_MAPPING_MCPD(core, ipname, resname, pd, pdata) {\ | ||
105 | .pdev = &SYSMMU_PLATDEV(ipname), \ | ||
106 | .res = &SYSMMU_RESOURCE_NAME(EXYNOS##core, resname), \ | ||
107 | .rnum = ARRAY_SIZE(SYSMMU_RESOURCE_NAME(EXYNOS##core, resname)),\ | ||
108 | .clocknames = SYSMMU_CLOCK_NAME "," SYSMMU_CLOCK_NAME2, \ | ||
109 | .pdd = &exynos##core##_device_pd[pd].dev, \ | ||
110 | } | ||
111 | #else | ||
112 | #define SYSMMU_RESOURCE_MAPPING_PD(core, ipname, resname, pd) \ | ||
113 | SYSMMU_RESOURCE_MAPPING(core, ipname, resname) | ||
114 | #define SYSMMU_RESOURCE_MAPPING_MCPD(core, ipname, resname, pd, pdata) \ | ||
115 | SYSMMU_RESOURCE_MAPPING_MC(core, ipname, resname, pdata) | ||
116 | |||
117 | #endif /* CONFIG_EXYNOS_DEV_PD */ | ||
118 | |||
119 | #ifdef CONFIG_ARCH_EXYNOS4 | ||
120 | SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimc0, FIMC0, FIMC0); | ||
121 | SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimc1, FIMC1, FIMC1); | ||
122 | SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimc2, FIMC2, FIMC2); | ||
123 | SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimc3, FIMC3, FIMC3); | ||
124 | SYSMMU_RESOURCE_DEFINE(EXYNOS4, jpeg, JPEG, JPEG); | ||
125 | SYSMMU_RESOURCE_DEFINE(EXYNOS4, 2d, G2D, 2D); | ||
126 | SYSMMU_RESOURCE_DEFINE(EXYNOS4, tv, TV, TV_M0); | ||
127 | SYSMMU_RESOURCE_DEFINE(EXYNOS4, 2d_acp, 2D_ACP, 2D); | ||
128 | SYSMMU_RESOURCE_DEFINE(EXYNOS4, rot, ROTATOR, ROTATOR); | ||
129 | SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimd0, FIMD0, LCD0_M0); | ||
130 | SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimd1, FIMD1, LCD1_M1); | ||
131 | SYSMMU_RESOURCE_DEFINE(EXYNOS4, flite0, FIMC_LITE0, FIMC_LITE0); | ||
132 | SYSMMU_RESOURCE_DEFINE(EXYNOS4, flite1, FIMC_LITE1, FIMC_LITE1); | ||
133 | SYSMMU_RESOURCE_DEFINE(EXYNOS4, mfc_r, MFC_R, MFC_M0); | ||
134 | SYSMMU_RESOURCE_DEFINE(EXYNOS4, mfc_l, MFC_L, MFC_M1); | ||
135 | SYSMMU_RESOURCE(EXYNOS4, isp) { | ||
136 | DEFINE_SYSMMU_RESOURCE(EXYNOS4, FIMC_ISP, FIMC_ISP), | ||
137 | DEFINE_SYSMMU_RESOURCE(EXYNOS4, FIMC_DRC, FIMC_DRC), | ||
138 | DEFINE_SYSMMU_RESOURCE(EXYNOS4, FIMC_FD, FIMC_FD), | ||
139 | DEFINE_SYSMMU_RESOURCE(EXYNOS4, ISPCPU, FIMC_CX), | ||
140 | }; | ||
141 | |||
142 | static struct sysmmu_resource_map sysmmu_resmap4[] __initdata = { | ||
143 | SYSMMU_RESOURCE_MAPPING_PD(4, fimc0, fimc0, PD_CAM), | ||
144 | SYSMMU_RESOURCE_MAPPING_PD(4, fimc1, fimc1, PD_CAM), | ||
145 | SYSMMU_RESOURCE_MAPPING_PD(4, fimc2, fimc2, PD_CAM), | ||
146 | SYSMMU_RESOURCE_MAPPING_PD(4, fimc3, fimc3, PD_CAM), | ||
147 | SYSMMU_RESOURCE_MAPPING_PD(4, tv, tv, PD_TV), | ||
148 | SYSMMU_RESOURCE_MAPPING_PD(4, mfc_r, mfc_r, PD_MFC), | ||
149 | SYSMMU_RESOURCE_MAPPING_PD(4, mfc_l, mfc_l, PD_MFC), | ||
150 | SYSMMU_RESOURCE_MAPPING_PD(4, rot, rot, PD_LCD0), | ||
151 | SYSMMU_RESOURCE_MAPPING_PD(4, jpeg, jpeg, PD_CAM), | ||
152 | SYSMMU_RESOURCE_MAPPING_PD(4, fimd0, fimd0, PD_LCD0), | ||
153 | }; | ||
154 | |||
155 | static struct sysmmu_resource_map sysmmu_resmap4210[] __initdata = { | ||
156 | SYSMMU_RESOURCE_MAPPING_PD(4, 2d, 2d, PD_LCD0), | ||
157 | SYSMMU_RESOURCE_MAPPING_PD(4, fimd1, fimd1, PD_LCD1), | ||
158 | }; | ||
159 | |||
160 | static struct sysmmu_resource_map sysmmu_resmap4212[] __initdata = { | ||
161 | SYSMMU_RESOURCE_MAPPING(4, 2d, 2d_acp), | ||
162 | SYSMMU_RESOURCE_MAPPING_PD(4, camif0, flite0, PD_ISP), | ||
163 | SYSMMU_RESOURCE_MAPPING_PD(4, camif1, flite1, PD_ISP), | ||
164 | SYSMMU_RESOURCE_MAPPING_PD(4, isp, isp, PD_ISP), | ||
165 | }; | ||
166 | #endif /* CONFIG_ARCH_EXYNOS4 */ | ||
167 | |||
168 | #ifdef CONFIG_ARCH_EXYNOS5 | ||
169 | SYSMMU_RESOURCE_DEFINE(EXYNOS5, jpeg, JPEG, JPEG); | ||
170 | SYSMMU_RESOURCE_DEFINE(EXYNOS5, fimd1, FIMD1, FIMD1); | ||
171 | SYSMMU_RESOURCE_DEFINE(EXYNOS5, 2d, 2D, 2D); | ||
172 | SYSMMU_RESOURCE_DEFINE(EXYNOS5, rot, ROTATOR, ROTATOR); | ||
173 | SYSMMU_RESOURCE_DEFINE(EXYNOS5, tv, TV, TV); | ||
174 | SYSMMU_RESOURCE_DEFINE(EXYNOS5, flite0, LITE0, LITE0); | ||
175 | SYSMMU_RESOURCE_DEFINE(EXYNOS5, flite1, LITE1, LITE1); | ||
176 | SYSMMU_RESOURCE_DEFINE(EXYNOS5, gsc0, GSC0, GSC0); | ||
177 | SYSMMU_RESOURCE_DEFINE(EXYNOS5, gsc1, GSC1, GSC1); | ||
178 | SYSMMU_RESOURCE_DEFINE(EXYNOS5, gsc2, GSC2, GSC2); | ||
179 | SYSMMU_RESOURCE_DEFINE(EXYNOS5, gsc3, GSC3, GSC3); | ||
180 | SYSMMU_RESOURCE_DEFINE(EXYNOS5, mfc_r, MFC_R, MFC_R); | ||
181 | SYSMMU_RESOURCE_DEFINE(EXYNOS5, mfc_l, MFC_L, MFC_L); | ||
182 | SYSMMU_RESOURCE(EXYNOS5, isp) { | ||
183 | DEFINE_SYSMMU_RESOURCE(EXYNOS5, ISP, ISP), | ||
184 | DEFINE_SYSMMU_RESOURCE(EXYNOS5, DRC, DRC), | ||
185 | DEFINE_SYSMMU_RESOURCE(EXYNOS5, FD, FD), | ||
186 | DEFINE_SYSMMU_RESOURCE(EXYNOS5, ISPCPU, MCUISP), | ||
187 | DEFINE_SYSMMU_RESOURCE(EXYNOS5, SCALERC, SCALERCISP), | ||
188 | DEFINE_SYSMMU_RESOURCE(EXYNOS5, SCALERP, SCALERPISP), | ||
189 | DEFINE_SYSMMU_RESOURCE(EXYNOS5, ODC, ODC), | ||
190 | DEFINE_SYSMMU_RESOURCE(EXYNOS5, DIS0, DIS0), | ||
191 | DEFINE_SYSMMU_RESOURCE(EXYNOS5, DIS1, DIS1), | ||
192 | DEFINE_SYSMMU_RESOURCE(EXYNOS5, 3DNR, 3DNR), | ||
193 | }; | ||
194 | |||
195 | static struct sysmmu_resource_map sysmmu_resmap5[] __initdata = { | ||
196 | SYSMMU_RESOURCE_MAPPING(5, jpeg, jpeg), | ||
197 | SYSMMU_RESOURCE_MAPPING(5, fimd1, fimd1), | ||
198 | SYSMMU_RESOURCE_MAPPING(5, 2d, 2d), | ||
199 | SYSMMU_RESOURCE_MAPPING(5, rot, rot), | ||
200 | SYSMMU_RESOURCE_MAPPING_PD(5, tv, tv, PD_DISP1), | ||
201 | SYSMMU_RESOURCE_MAPPING_PD(5, camif0, flite0, PD_GSCL), | ||
202 | SYSMMU_RESOURCE_MAPPING_PD(5, camif1, flite1, PD_GSCL), | ||
203 | SYSMMU_RESOURCE_MAPPING_PD(5, gsc0, gsc0, PD_GSCL), | ||
204 | SYSMMU_RESOURCE_MAPPING_PD(5, gsc1, gsc1, PD_GSCL), | ||
205 | SYSMMU_RESOURCE_MAPPING_PD(5, gsc2, gsc2, PD_GSCL), | ||
206 | SYSMMU_RESOURCE_MAPPING_PD(5, gsc3, gsc3, PD_GSCL), | ||
207 | SYSMMU_RESOURCE_MAPPING_PD(5, mfc_r, mfc_r, PD_MFC), | ||
208 | SYSMMU_RESOURCE_MAPPING_PD(5, mfc_l, mfc_l, PD_MFC), | ||
209 | SYSMMU_RESOURCE_MAPPING_MCPD(5, isp, isp, PD_ISP, mc_platdata), | ||
210 | }; | ||
211 | #endif /* CONFIG_ARCH_EXYNOS5 */ | ||
212 | |||
213 | static int __init init_sysmmu_platform_device(void) | ||
214 | { | ||
215 | int i, j; | ||
216 | struct sysmmu_resource_map *resmap[2] = {NULL, NULL}; | ||
217 | int nmap[2] = {0, 0}; | ||
218 | |||
219 | #ifdef CONFIG_ARCH_EXYNOS5 | ||
220 | if (soc_is_exynos5250()) { | ||
221 | resmap[0] = sysmmu_resmap5; | ||
222 | nmap[0] = ARRAY_SIZE(sysmmu_resmap5); | ||
223 | nmap[1] = 0; | ||
224 | } | ||
225 | #endif | ||
226 | |||
227 | #ifdef CONFIG_ARCH_EXYNOS4 | ||
228 | if (resmap[0] == NULL) { | ||
229 | resmap[0] = sysmmu_resmap4; | ||
230 | nmap[0] = ARRAY_SIZE(sysmmu_resmap4); | ||
231 | } | ||
232 | |||
233 | if (soc_is_exynos4210()) { | ||
234 | resmap[1] = sysmmu_resmap4210; | ||
235 | nmap[1] = ARRAY_SIZE(sysmmu_resmap4210); | ||
236 | } | ||
237 | |||
238 | if (soc_is_exynos4412() || soc_is_exynos4212()) { | ||
239 | resmap[1] = sysmmu_resmap4212; | ||
240 | nmap[1] = ARRAY_SIZE(sysmmu_resmap4212); | ||
241 | } | ||
242 | #endif | ||
243 | |||
244 | for (j = 0; j < 2; j++) { | ||
245 | for (i = 0; i < nmap[j]; i++) { | ||
246 | struct sysmmu_resource_map *map; | ||
247 | struct sysmmu_platform_data *platdata; | ||
248 | |||
249 | map = &resmap[j][i]; | ||
250 | |||
251 | map->pdev->dev.parent = map->pdd; | ||
252 | |||
253 | platdata = map->pdev->dev.platform_data; | ||
254 | platdata->clockname = map->clocknames; | ||
255 | |||
256 | if (platform_device_add_resources(map->pdev, map->res, | ||
257 | map->rnum)) { | ||
258 | pr_err("%s: Failed to add device resources for " | ||
259 | "%s.%d\n", __func__, | ||
260 | map->pdev->name, map->pdev->id); | ||
261 | continue; | ||
262 | } | ||
263 | |||
264 | if (platform_device_register(map->pdev)) { | ||
265 | pr_err("%s: Failed to register %s.%d\n", | ||
266 | __func__, map->pdev->name, | ||
267 | map->pdev->id); | ||
268 | } | ||
269 | } | ||
270 | } | ||
271 | |||
272 | return 0; | ||
273 | } | ||
274 | arch_initcall(init_sysmmu_platform_device); | ||
diff --git a/arch/arm/mach-exynos/include/mach/sysmmu.h b/arch/arm/mach-exynos/include/mach/sysmmu.h deleted file mode 100644 index 88a4543b0001..000000000000 --- a/arch/arm/mach-exynos/include/mach/sysmmu.h +++ /dev/null | |||
@@ -1,66 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd. | ||
3 | * http://www.samsung.com | ||
4 | * | ||
5 | * EXYNOS - System MMU support | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef _ARM_MACH_EXYNOS_SYSMMU_H_ | ||
13 | #define _ARM_MACH_EXYNOS_SYSMMU_H_ | ||
14 | |||
15 | struct sysmmu_platform_data { | ||
16 | char *dbgname; | ||
17 | /* comma(,) separated list of clock names for clock gating */ | ||
18 | char *clockname; | ||
19 | }; | ||
20 | |||
21 | #define SYSMMU_DEVNAME_BASE "exynos-sysmmu" | ||
22 | |||
23 | #define SYSMMU_CLOCK_NAME "sysmmu" | ||
24 | #define SYSMMU_CLOCK_NAME2 "sysmmu_mc" | ||
25 | |||
26 | #ifdef CONFIG_EXYNOS_DEV_SYSMMU | ||
27 | #include <linux/device.h> | ||
28 | struct platform_device; | ||
29 | |||
30 | #define SYSMMU_PLATDEV(ipname) exynos_device_sysmmu_##ipname | ||
31 | |||
32 | extern struct platform_device SYSMMU_PLATDEV(mfc_l); | ||
33 | extern struct platform_device SYSMMU_PLATDEV(mfc_r); | ||
34 | extern struct platform_device SYSMMU_PLATDEV(tv); | ||
35 | extern struct platform_device SYSMMU_PLATDEV(jpeg); | ||
36 | extern struct platform_device SYSMMU_PLATDEV(rot); | ||
37 | extern struct platform_device SYSMMU_PLATDEV(fimc0); | ||
38 | extern struct platform_device SYSMMU_PLATDEV(fimc1); | ||
39 | extern struct platform_device SYSMMU_PLATDEV(fimc2); | ||
40 | extern struct platform_device SYSMMU_PLATDEV(fimc3); | ||
41 | extern struct platform_device SYSMMU_PLATDEV(gsc0); | ||
42 | extern struct platform_device SYSMMU_PLATDEV(gsc1); | ||
43 | extern struct platform_device SYSMMU_PLATDEV(gsc2); | ||
44 | extern struct platform_device SYSMMU_PLATDEV(gsc3); | ||
45 | extern struct platform_device SYSMMU_PLATDEV(isp); | ||
46 | extern struct platform_device SYSMMU_PLATDEV(fimd0); | ||
47 | extern struct platform_device SYSMMU_PLATDEV(fimd1); | ||
48 | extern struct platform_device SYSMMU_PLATDEV(camif0); | ||
49 | extern struct platform_device SYSMMU_PLATDEV(camif1); | ||
50 | extern struct platform_device SYSMMU_PLATDEV(2d); | ||
51 | |||
52 | #ifdef CONFIG_IOMMU_API | ||
53 | static inline void platform_set_sysmmu( | ||
54 | struct device *sysmmu, struct device *dev) | ||
55 | { | ||
56 | dev->archdata.iommu = sysmmu; | ||
57 | } | ||
58 | #endif | ||
59 | |||
60 | #else /* !CONFIG_EXYNOS_DEV_SYSMMU */ | ||
61 | #define platform_set_sysmmu(sysmmu, dev) do { } while (0) | ||
62 | #endif | ||
63 | |||
64 | #define SYSMMU_CLOCK_DEVNAME(ipname, id) (SYSMMU_DEVNAME_BASE "." #id) | ||
65 | |||
66 | #endif /* _ARM_MACH_EXYNOS_SYSMMU_H_ */ | ||
diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c index 112d10e53d20..3358088c822a 100644 --- a/arch/arm/mach-exynos/mach-exynos4-dt.c +++ b/arch/arm/mach-exynos/mach-exynos4-dt.c | |||
@@ -79,6 +79,40 @@ static const struct of_dev_auxdata exynos4_auxdata_lookup[] __initconst = { | |||
79 | OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_MDMA1, "dma-pl330.2", NULL), | 79 | OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_MDMA1, "dma-pl330.2", NULL), |
80 | OF_DEV_AUXDATA("samsung,exynos4210-tmu", EXYNOS4_PA_TMU, | 80 | OF_DEV_AUXDATA("samsung,exynos4210-tmu", EXYNOS4_PA_TMU, |
81 | "exynos-tmu", NULL), | 81 | "exynos-tmu", NULL), |
82 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13620000, | ||
83 | "exynos-sysmmu.0", NULL), /* MFC_L */ | ||
84 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13630000, | ||
85 | "exynos-sysmmu.1", NULL), /* MFC_R */ | ||
86 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13E20000, | ||
87 | "exynos-sysmmu.2", NULL), /* TV */ | ||
88 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11A60000, | ||
89 | "exynos-sysmmu.3", NULL), /* JPEG */ | ||
90 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x12A30000, | ||
91 | "exynos-sysmmu.4", NULL), /* ROTATOR */ | ||
92 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11A20000, | ||
93 | "exynos-sysmmu.5", NULL), /* FIMC0 */ | ||
94 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11A30000, | ||
95 | "exynos-sysmmu.6", NULL), /* FIMC1 */ | ||
96 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11A40000, | ||
97 | "exynos-sysmmu.7", NULL), /* FIMC2 */ | ||
98 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11A50000, | ||
99 | "exynos-sysmmu.8", NULL), /* FIMC3 */ | ||
100 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x12A20000, | ||
101 | "exynos-sysmmu.9", NULL), /* G2D(4210) */ | ||
102 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x10A40000, | ||
103 | "exynos-sysmmu.9", NULL), /* G2D(4x12) */ | ||
104 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11E20000, | ||
105 | "exynos-sysmmu.10", NULL), /* FIMD0 */ | ||
106 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x12220000, | ||
107 | "exynos-sysmmu.11", NULL), /* FIMD1(4210) */ | ||
108 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x12260000, | ||
109 | "exynos-sysmmu.12", NULL), /* IS0(4x12) */ | ||
110 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x122B0000, | ||
111 | "exynos-sysmmu.13", NULL), /* IS1(4x12) */ | ||
112 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x123B0000, | ||
113 | "exynos-sysmmu.14", NULL), /* FIMC-LITE0(4x12) */ | ||
114 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x123C0000, | ||
115 | "exynos-sysmmu.15", NULL), /* FIMC-LITE1(4x12) */ | ||
82 | {}, | 116 | {}, |
83 | }; | 117 | }; |
84 | 118 | ||
diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c index 973a06637572..acaeb14db54b 100644 --- a/arch/arm/mach-exynos/mach-exynos5-dt.c +++ b/arch/arm/mach-exynos/mach-exynos5-dt.c | |||
@@ -109,6 +109,36 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = { | |||
109 | "samsung-i2s.1", NULL), | 109 | "samsung-i2s.1", NULL), |
110 | OF_DEV_AUXDATA("samsung,i2s-v5", 0x12D70000, | 110 | OF_DEV_AUXDATA("samsung,i2s-v5", 0x12D70000, |
111 | "samsung-i2s.2", NULL), | 111 | "samsung-i2s.2", NULL), |
112 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11210000, | ||
113 | "exynos-sysmmu.0", "mfc"), /* MFC_L */ | ||
114 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11200000, | ||
115 | "exynos-sysmmu.1", "mfc"), /* MFC_R */ | ||
116 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x14650000, | ||
117 | "exynos-sysmmu.2", NULL), /* TV */ | ||
118 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11F20000, | ||
119 | "exynos-sysmmu.3", "jpeg"), /* JPEG */ | ||
120 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11D40000, | ||
121 | "exynos-sysmmu.4", NULL), /* ROTATOR */ | ||
122 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13E80000, | ||
123 | "exynos-sysmmu.5", "gscl"), /* GSCL0 */ | ||
124 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13E90000, | ||
125 | "exynos-sysmmu.6", "gscl"), /* GSCL1 */ | ||
126 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13EA0000, | ||
127 | "exynos-sysmmu.7", "gscl"), /* GSCL2 */ | ||
128 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13EB0000, | ||
129 | "exynos-sysmmu.8", "gscl"), /* GSCL3 */ | ||
130 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13260000, | ||
131 | "exynos-sysmmu.9", NULL), /* FIMC-IS0 */ | ||
132 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x132C0000, | ||
133 | "exynos-sysmmu.10", NULL), /* FIMC-IS1 */ | ||
134 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x14640000, | ||
135 | "exynos-sysmmu.11", NULL), /* FIMD1 */ | ||
136 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13C40000, | ||
137 | "exynos-sysmmu.12", NULL), /* FIMC-LITE0 */ | ||
138 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13C50000, | ||
139 | "exynos-sysmmu.13", NULL), /* FIMC-LITE1 */ | ||
140 | OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x10A60000, | ||
141 | "exynos-sysmmu.14", NULL), /* G2D */ | ||
112 | {}, | 142 | {}, |
113 | }; | 143 | }; |
114 | 144 | ||
diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c index 30ac79c7c687..8b85d4d8fab6 100644 --- a/arch/arm/mach-shmobile/setup-r8a7740.c +++ b/arch/arm/mach-shmobile/setup-r8a7740.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/serial_sci.h> | 27 | #include <linux/serial_sci.h> |
28 | #include <linux/sh_dma.h> | 28 | #include <linux/sh_dma.h> |
29 | #include <linux/sh_timer.h> | 29 | #include <linux/sh_timer.h> |
30 | #include <linux/platform_data/sh_ipmmu.h> | ||
30 | #include <mach/dma-register.h> | 31 | #include <mach/dma-register.h> |
31 | #include <mach/r8a7740.h> | 32 | #include <mach/r8a7740.h> |
32 | #include <mach/pm-rmobile.h> | 33 | #include <mach/pm-rmobile.h> |
@@ -378,6 +379,37 @@ static struct platform_device tmu02_device = { | |||
378 | .num_resources = ARRAY_SIZE(tmu02_resources), | 379 | .num_resources = ARRAY_SIZE(tmu02_resources), |
379 | }; | 380 | }; |
380 | 381 | ||
382 | /* IPMMUI (an IPMMU module for ICB/LMB) */ | ||
383 | static struct resource ipmmu_resources[] = { | ||
384 | [0] = { | ||
385 | .name = "IPMMUI", | ||
386 | .start = 0xfe951000, | ||
387 | .end = 0xfe9510ff, | ||
388 | .flags = IORESOURCE_MEM, | ||
389 | }, | ||
390 | }; | ||
391 | |||
392 | static const char * const ipmmu_dev_names[] = { | ||
393 | "sh_mobile_lcdc_fb.0", | ||
394 | "sh_mobile_lcdc_fb.1", | ||
395 | "sh_mobile_ceu.0", | ||
396 | }; | ||
397 | |||
398 | static struct shmobile_ipmmu_platform_data ipmmu_platform_data = { | ||
399 | .dev_names = ipmmu_dev_names, | ||
400 | .num_dev_names = ARRAY_SIZE(ipmmu_dev_names), | ||
401 | }; | ||
402 | |||
403 | static struct platform_device ipmmu_device = { | ||
404 | .name = "ipmmu", | ||
405 | .id = -1, | ||
406 | .dev = { | ||
407 | .platform_data = &ipmmu_platform_data, | ||
408 | }, | ||
409 | .resource = ipmmu_resources, | ||
410 | .num_resources = ARRAY_SIZE(ipmmu_resources), | ||
411 | }; | ||
412 | |||
381 | static struct platform_device *r8a7740_early_devices[] __initdata = { | 413 | static struct platform_device *r8a7740_early_devices[] __initdata = { |
382 | &scif0_device, | 414 | &scif0_device, |
383 | &scif1_device, | 415 | &scif1_device, |
@@ -392,6 +424,7 @@ static struct platform_device *r8a7740_early_devices[] __initdata = { | |||
392 | &tmu00_device, | 424 | &tmu00_device, |
393 | &tmu01_device, | 425 | &tmu01_device, |
394 | &tmu02_device, | 426 | &tmu02_device, |
427 | &ipmmu_device, | ||
395 | }; | 428 | }; |
396 | 429 | ||
397 | /* DMA */ | 430 | /* DMA */ |
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c index d2079d5e3334..59c7146bf66f 100644 --- a/arch/arm/mach-shmobile/setup-sh7372.c +++ b/arch/arm/mach-shmobile/setup-sh7372.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/sh_timer.h> | 33 | #include <linux/sh_timer.h> |
34 | #include <linux/pm_domain.h> | 34 | #include <linux/pm_domain.h> |
35 | #include <linux/dma-mapping.h> | 35 | #include <linux/dma-mapping.h> |
36 | #include <linux/platform_data/sh_ipmmu.h> | ||
36 | #include <mach/dma-register.h> | 37 | #include <mach/dma-register.h> |
37 | #include <mach/hardware.h> | 38 | #include <mach/hardware.h> |
38 | #include <mach/irqs.h> | 39 | #include <mach/irqs.h> |
@@ -1008,6 +1009,43 @@ static struct platform_device spu1_device = { | |||
1008 | .num_resources = ARRAY_SIZE(spu1_resources), | 1009 | .num_resources = ARRAY_SIZE(spu1_resources), |
1009 | }; | 1010 | }; |
1010 | 1011 | ||
1012 | /* IPMMUI (an IPMMU module for ICB/LMB) */ | ||
1013 | static struct resource ipmmu_resources[] = { | ||
1014 | [0] = { | ||
1015 | .name = "IPMMUI", | ||
1016 | .start = 0xfe951000, | ||
1017 | .end = 0xfe9510ff, | ||
1018 | .flags = IORESOURCE_MEM, | ||
1019 | }, | ||
1020 | }; | ||
1021 | |||
1022 | static const char * const ipmmu_dev_names[] = { | ||
1023 | "sh_mobile_lcdc_fb.0", | ||
1024 | "sh_mobile_lcdc_fb.1", | ||
1025 | "sh_mobile_ceu.0", | ||
1026 | "uio_pdrv_genirq.0", | ||
1027 | "uio_pdrv_genirq.1", | ||
1028 | "uio_pdrv_genirq.2", | ||
1029 | "uio_pdrv_genirq.3", | ||
1030 | "uio_pdrv_genirq.4", | ||
1031 | "uio_pdrv_genirq.5", | ||
1032 | }; | ||
1033 | |||
1034 | static struct shmobile_ipmmu_platform_data ipmmu_platform_data = { | ||
1035 | .dev_names = ipmmu_dev_names, | ||
1036 | .num_dev_names = ARRAY_SIZE(ipmmu_dev_names), | ||
1037 | }; | ||
1038 | |||
1039 | static struct platform_device ipmmu_device = { | ||
1040 | .name = "ipmmu", | ||
1041 | .id = -1, | ||
1042 | .dev = { | ||
1043 | .platform_data = &ipmmu_platform_data, | ||
1044 | }, | ||
1045 | .resource = ipmmu_resources, | ||
1046 | .num_resources = ARRAY_SIZE(ipmmu_resources), | ||
1047 | }; | ||
1048 | |||
1011 | static struct platform_device *sh7372_early_devices[] __initdata = { | 1049 | static struct platform_device *sh7372_early_devices[] __initdata = { |
1012 | &scif0_device, | 1050 | &scif0_device, |
1013 | &scif1_device, | 1051 | &scif1_device, |
@@ -1019,6 +1057,7 @@ static struct platform_device *sh7372_early_devices[] __initdata = { | |||
1019 | &cmt2_device, | 1057 | &cmt2_device, |
1020 | &tmu00_device, | 1058 | &tmu00_device, |
1021 | &tmu01_device, | 1059 | &tmu01_device, |
1060 | &ipmmu_device, | ||
1022 | }; | 1061 | }; |
1023 | 1062 | ||
1024 | static struct platform_device *sh7372_late_devices[] __initdata = { | 1063 | static struct platform_device *sh7372_late_devices[] __initdata = { |
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c index 2ecd6681692f..bdab575f88bc 100644 --- a/arch/arm/mach-shmobile/setup-sh73a0.c +++ b/arch/arm/mach-shmobile/setup-sh73a0.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/sh_dma.h> | 31 | #include <linux/sh_dma.h> |
32 | #include <linux/sh_intc.h> | 32 | #include <linux/sh_intc.h> |
33 | #include <linux/sh_timer.h> | 33 | #include <linux/sh_timer.h> |
34 | #include <linux/platform_data/sh_ipmmu.h> | ||
34 | #include <mach/dma-register.h> | 35 | #include <mach/dma-register.h> |
35 | #include <mach/hardware.h> | 36 | #include <mach/hardware.h> |
36 | #include <mach/irqs.h> | 37 | #include <mach/irqs.h> |
@@ -780,6 +781,35 @@ static struct platform_device pmu_device = { | |||
780 | .resource = pmu_resources, | 781 | .resource = pmu_resources, |
781 | }; | 782 | }; |
782 | 783 | ||
784 | /* an IPMMU module for ICB */ | ||
785 | static struct resource ipmmu_resources[] = { | ||
786 | [0] = { | ||
787 | .name = "IPMMU", | ||
788 | .start = 0xfe951000, | ||
789 | .end = 0xfe9510ff, | ||
790 | .flags = IORESOURCE_MEM, | ||
791 | }, | ||
792 | }; | ||
793 | |||
794 | static const char * const ipmmu_dev_names[] = { | ||
795 | "sh_mobile_lcdc_fb.0", | ||
796 | }; | ||
797 | |||
798 | static struct shmobile_ipmmu_platform_data ipmmu_platform_data = { | ||
799 | .dev_names = ipmmu_dev_names, | ||
800 | .num_dev_names = ARRAY_SIZE(ipmmu_dev_names), | ||
801 | }; | ||
802 | |||
803 | static struct platform_device ipmmu_device = { | ||
804 | .name = "ipmmu", | ||
805 | .id = -1, | ||
806 | .dev = { | ||
807 | .platform_data = &ipmmu_platform_data, | ||
808 | }, | ||
809 | .resource = ipmmu_resources, | ||
810 | .num_resources = ARRAY_SIZE(ipmmu_resources), | ||
811 | }; | ||
812 | |||
783 | static struct platform_device *sh73a0_early_devices_dt[] __initdata = { | 813 | static struct platform_device *sh73a0_early_devices_dt[] __initdata = { |
784 | &scif0_device, | 814 | &scif0_device, |
785 | &scif1_device, | 815 | &scif1_device, |
@@ -796,6 +826,7 @@ static struct platform_device *sh73a0_early_devices_dt[] __initdata = { | |||
796 | static struct platform_device *sh73a0_early_devices[] __initdata = { | 826 | static struct platform_device *sh73a0_early_devices[] __initdata = { |
797 | &tmu00_device, | 827 | &tmu00_device, |
798 | &tmu01_device, | 828 | &tmu01_device, |
829 | &ipmmu_device, | ||
799 | }; | 830 | }; |
800 | 831 | ||
801 | static struct platform_device *sh73a0_late_devices[] __initdata = { | 832 | static struct platform_device *sh73a0_late_devices[] __initdata = { |
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 01068987809d..5c514d0711d1 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig | |||
@@ -158,7 +158,7 @@ config TEGRA_IOMMU_GART | |||
158 | 158 | ||
159 | config TEGRA_IOMMU_SMMU | 159 | config TEGRA_IOMMU_SMMU |
160 | bool "Tegra SMMU IOMMU Support" | 160 | bool "Tegra SMMU IOMMU Support" |
161 | depends on ARCH_TEGRA_3x_SOC && TEGRA_AHB | 161 | depends on ARCH_TEGRA && TEGRA_AHB |
162 | select IOMMU_API | 162 | select IOMMU_API |
163 | help | 163 | help |
164 | Enables support for remapping discontiguous physical memory | 164 | Enables support for remapping discontiguous physical memory |
@@ -187,4 +187,78 @@ config EXYNOS_IOMMU_DEBUG | |||
187 | 187 | ||
188 | Say N unless you need kernel log message for IOMMU debugging | 188 | Say N unless you need kernel log message for IOMMU debugging |
189 | 189 | ||
190 | config SHMOBILE_IPMMU | ||
191 | bool | ||
192 | |||
193 | config SHMOBILE_IPMMU_TLB | ||
194 | bool | ||
195 | |||
196 | config SHMOBILE_IOMMU | ||
197 | bool "IOMMU for Renesas IPMMU/IPMMUI" | ||
198 | default n | ||
199 | depends on (ARM && ARCH_SHMOBILE) | ||
200 | select IOMMU_API | ||
201 | select ARM_DMA_USE_IOMMU | ||
202 | select SHMOBILE_IPMMU | ||
203 | select SHMOBILE_IPMMU_TLB | ||
204 | help | ||
205 | Support for Renesas IPMMU/IPMMUI. This option enables | ||
206 | remapping of DMA memory accesses from all of the IP blocks | ||
207 | on the ICB. | ||
208 | |||
209 | Warning: Drivers (including userspace drivers of UIO | ||
210 | devices) of the IP blocks on the ICB *must* use addresses | ||
211 | allocated from the IPMMU (iova) for DMA with this option | ||
212 | enabled. | ||
213 | |||
214 | If unsure, say N. | ||
215 | |||
216 | choice | ||
217 | prompt "IPMMU/IPMMUI address space size" | ||
218 | default SHMOBILE_IOMMU_ADDRSIZE_2048MB | ||
219 | depends on SHMOBILE_IOMMU | ||
220 | help | ||
221 | This option sets IPMMU/IPMMUI address space size by | ||
222 | adjusting the 1st level page table size. The page table size | ||
223 | is calculated as follows: | ||
224 | |||
225 | page table size = number of page table entries * 4 bytes | ||
226 | number of page table entries = address space size / 1 MiB | ||
227 | |||
228 | For example, when the address space size is 2048 MiB, the | ||
229 | 1st level page table size is 8192 bytes. | ||
230 | |||
231 | config SHMOBILE_IOMMU_ADDRSIZE_2048MB | ||
232 | bool "2 GiB" | ||
233 | |||
234 | config SHMOBILE_IOMMU_ADDRSIZE_1024MB | ||
235 | bool "1 GiB" | ||
236 | |||
237 | config SHMOBILE_IOMMU_ADDRSIZE_512MB | ||
238 | bool "512 MiB" | ||
239 | |||
240 | config SHMOBILE_IOMMU_ADDRSIZE_256MB | ||
241 | bool "256 MiB" | ||
242 | |||
243 | config SHMOBILE_IOMMU_ADDRSIZE_128MB | ||
244 | bool "128 MiB" | ||
245 | |||
246 | config SHMOBILE_IOMMU_ADDRSIZE_64MB | ||
247 | bool "64 MiB" | ||
248 | |||
249 | config SHMOBILE_IOMMU_ADDRSIZE_32MB | ||
250 | bool "32 MiB" | ||
251 | |||
252 | endchoice | ||
253 | |||
254 | config SHMOBILE_IOMMU_L1SIZE | ||
255 | int | ||
256 | default 8192 if SHMOBILE_IOMMU_ADDRSIZE_2048MB | ||
257 | default 4096 if SHMOBILE_IOMMU_ADDRSIZE_1024MB | ||
258 | default 2048 if SHMOBILE_IOMMU_ADDRSIZE_512MB | ||
259 | default 1024 if SHMOBILE_IOMMU_ADDRSIZE_256MB | ||
260 | default 512 if SHMOBILE_IOMMU_ADDRSIZE_128MB | ||
261 | default 256 if SHMOBILE_IOMMU_ADDRSIZE_64MB | ||
262 | default 128 if SHMOBILE_IOMMU_ADDRSIZE_32MB | ||
263 | |||
190 | endif # IOMMU_SUPPORT | 264 | endif # IOMMU_SUPPORT |
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index f66b816d455c..ef0e5207ad69 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile | |||
@@ -13,3 +13,5 @@ obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o | |||
13 | obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o | 13 | obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o |
14 | obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o | 14 | obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o |
15 | obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o | 15 | obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o |
16 | obj-$(CONFIG_SHMOBILE_IOMMU) += shmobile-iommu.o | ||
17 | obj-$(CONFIG_SHMOBILE_IPMMU) += shmobile-ipmmu.o | ||
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index d33eaaf783ad..98f555dafb55 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
@@ -3187,8 +3187,7 @@ int __init amd_iommu_init_dma_ops(void) | |||
3187 | free_domains: | 3187 | free_domains: |
3188 | 3188 | ||
3189 | for_each_iommu(iommu) { | 3189 | for_each_iommu(iommu) { |
3190 | if (iommu->default_dom) | 3190 | dma_ops_domain_free(iommu->default_dom); |
3191 | dma_ops_domain_free(iommu->default_dom); | ||
3192 | } | 3191 | } |
3193 | 3192 | ||
3194 | return ret; | 3193 | return ret; |
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index faf10ba1ed9a..b6ecddb63cd0 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c | |||
@@ -1876,11 +1876,6 @@ static int amd_iommu_init_dma(void) | |||
1876 | struct amd_iommu *iommu; | 1876 | struct amd_iommu *iommu; |
1877 | int ret; | 1877 | int ret; |
1878 | 1878 | ||
1879 | init_device_table_dma(); | ||
1880 | |||
1881 | for_each_iommu(iommu) | ||
1882 | iommu_flush_all_caches(iommu); | ||
1883 | |||
1884 | if (iommu_pass_through) | 1879 | if (iommu_pass_through) |
1885 | ret = amd_iommu_init_passthrough(); | 1880 | ret = amd_iommu_init_passthrough(); |
1886 | else | 1881 | else |
@@ -1889,6 +1884,11 @@ static int amd_iommu_init_dma(void) | |||
1889 | if (ret) | 1884 | if (ret) |
1890 | return ret; | 1885 | return ret; |
1891 | 1886 | ||
1887 | init_device_table_dma(); | ||
1888 | |||
1889 | for_each_iommu(iommu) | ||
1890 | iommu_flush_all_caches(iommu); | ||
1891 | |||
1892 | amd_iommu_init_api(); | 1892 | amd_iommu_init_api(); |
1893 | 1893 | ||
1894 | amd_iommu_init_notifier(); | 1894 | amd_iommu_init_notifier(); |
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 174bb654453d..dc7e478b7e5f 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c | |||
@@ -1042,7 +1042,7 @@ int dmar_enable_qi(struct intel_iommu *iommu) | |||
1042 | 1042 | ||
1043 | qi->desc = page_address(desc_page); | 1043 | qi->desc = page_address(desc_page); |
1044 | 1044 | ||
1045 | qi->desc_status = kmalloc(QI_LENGTH * sizeof(int), GFP_ATOMIC); | 1045 | qi->desc_status = kzalloc(QI_LENGTH * sizeof(int), GFP_ATOMIC); |
1046 | if (!qi->desc_status) { | 1046 | if (!qi->desc_status) { |
1047 | free_page((unsigned long) qi->desc); | 1047 | free_page((unsigned long) qi->desc); |
1048 | kfree(qi); | 1048 | kfree(qi); |
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 7fe44f83cc37..238a3caa949a 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c | |||
@@ -511,7 +511,7 @@ int exynos_sysmmu_enable(struct device *dev, unsigned long pgtable) | |||
511 | return ret; | 511 | return ret; |
512 | } | 512 | } |
513 | 513 | ||
514 | bool exynos_sysmmu_disable(struct device *dev) | 514 | static bool exynos_sysmmu_disable(struct device *dev) |
515 | { | 515 | { |
516 | struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); | 516 | struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); |
517 | bool disabled; | 517 | bool disabled; |
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index ddbdacad7768..b972d430d92b 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c | |||
@@ -734,7 +734,8 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova, | |||
734 | size_t orig_size = size; | 734 | size_t orig_size = size; |
735 | int ret = 0; | 735 | int ret = 0; |
736 | 736 | ||
737 | if (unlikely(domain->ops->map == NULL)) | 737 | if (unlikely(domain->ops->unmap == NULL || |
738 | domain->ops->pgsize_bitmap == 0UL)) | ||
738 | return -ENODEV; | 739 | return -ENODEV; |
739 | 740 | ||
740 | /* find out the minimum page size supported */ | 741 | /* find out the minimum page size supported */ |
@@ -808,7 +809,8 @@ size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) | |||
808 | size_t unmapped_page, unmapped = 0; | 809 | size_t unmapped_page, unmapped = 0; |
809 | unsigned int min_pagesz; | 810 | unsigned int min_pagesz; |
810 | 811 | ||
811 | if (unlikely(domain->ops->unmap == NULL)) | 812 | if (unlikely(domain->ops->unmap == NULL || |
813 | domain->ops->pgsize_bitmap == 0UL)) | ||
812 | return -ENODEV; | 814 | return -ENODEV; |
813 | 815 | ||
814 | /* find out the minimum page size supported */ | 816 | /* find out the minimum page size supported */ |
@@ -850,6 +852,26 @@ size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) | |||
850 | } | 852 | } |
851 | EXPORT_SYMBOL_GPL(iommu_unmap); | 853 | EXPORT_SYMBOL_GPL(iommu_unmap); |
852 | 854 | ||
855 | |||
856 | int iommu_domain_window_enable(struct iommu_domain *domain, u32 wnd_nr, | ||
857 | phys_addr_t paddr, u64 size) | ||
858 | { | ||
859 | if (unlikely(domain->ops->domain_window_enable == NULL)) | ||
860 | return -ENODEV; | ||
861 | |||
862 | return domain->ops->domain_window_enable(domain, wnd_nr, paddr, size); | ||
863 | } | ||
864 | EXPORT_SYMBOL_GPL(iommu_domain_window_enable); | ||
865 | |||
866 | void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr) | ||
867 | { | ||
868 | if (unlikely(domain->ops->domain_window_disable == NULL)) | ||
869 | return; | ||
870 | |||
871 | return domain->ops->domain_window_disable(domain, wnd_nr); | ||
872 | } | ||
873 | EXPORT_SYMBOL_GPL(iommu_domain_window_disable); | ||
874 | |||
853 | static int __init iommu_init(void) | 875 | static int __init iommu_init(void) |
854 | { | 876 | { |
855 | iommu_group_kset = kset_create_and_add("iommu_groups", | 877 | iommu_group_kset = kset_create_and_add("iommu_groups", |
@@ -861,13 +883,15 @@ static int __init iommu_init(void) | |||
861 | 883 | ||
862 | return 0; | 884 | return 0; |
863 | } | 885 | } |
864 | subsys_initcall(iommu_init); | 886 | arch_initcall(iommu_init); |
865 | 887 | ||
866 | int iommu_domain_get_attr(struct iommu_domain *domain, | 888 | int iommu_domain_get_attr(struct iommu_domain *domain, |
867 | enum iommu_attr attr, void *data) | 889 | enum iommu_attr attr, void *data) |
868 | { | 890 | { |
869 | struct iommu_domain_geometry *geometry; | 891 | struct iommu_domain_geometry *geometry; |
892 | bool *paging; | ||
870 | int ret = 0; | 893 | int ret = 0; |
894 | u32 *count; | ||
871 | 895 | ||
872 | switch (attr) { | 896 | switch (attr) { |
873 | case DOMAIN_ATTR_GEOMETRY: | 897 | case DOMAIN_ATTR_GEOMETRY: |
@@ -875,6 +899,19 @@ int iommu_domain_get_attr(struct iommu_domain *domain, | |||
875 | *geometry = domain->geometry; | 899 | *geometry = domain->geometry; |
876 | 900 | ||
877 | break; | 901 | break; |
902 | case DOMAIN_ATTR_PAGING: | ||
903 | paging = data; | ||
904 | *paging = (domain->ops->pgsize_bitmap != 0UL); | ||
905 | break; | ||
906 | case DOMAIN_ATTR_WINDOWS: | ||
907 | count = data; | ||
908 | |||
909 | if (domain->ops->domain_get_windows != NULL) | ||
910 | *count = domain->ops->domain_get_windows(domain); | ||
911 | else | ||
912 | ret = -ENODEV; | ||
913 | |||
914 | break; | ||
878 | default: | 915 | default: |
879 | if (!domain->ops->domain_get_attr) | 916 | if (!domain->ops->domain_get_attr) |
880 | return -EINVAL; | 917 | return -EINVAL; |
@@ -889,9 +926,26 @@ EXPORT_SYMBOL_GPL(iommu_domain_get_attr); | |||
889 | int iommu_domain_set_attr(struct iommu_domain *domain, | 926 | int iommu_domain_set_attr(struct iommu_domain *domain, |
890 | enum iommu_attr attr, void *data) | 927 | enum iommu_attr attr, void *data) |
891 | { | 928 | { |
892 | if (!domain->ops->domain_set_attr) | 929 | int ret = 0; |
893 | return -EINVAL; | 930 | u32 *count; |
894 | 931 | ||
895 | return domain->ops->domain_set_attr(domain, attr, data); | 932 | switch (attr) { |
933 | case DOMAIN_ATTR_WINDOWS: | ||
934 | count = data; | ||
935 | |||
936 | if (domain->ops->domain_set_windows != NULL) | ||
937 | ret = domain->ops->domain_set_windows(domain, *count); | ||
938 | else | ||
939 | ret = -ENODEV; | ||
940 | |||
941 | break; | ||
942 | default: | ||
943 | if (domain->ops->domain_set_attr == NULL) | ||
944 | return -EINVAL; | ||
945 | |||
946 | ret = domain->ops->domain_set_attr(domain, attr, data); | ||
947 | } | ||
948 | |||
949 | return ret; | ||
896 | } | 950 | } |
897 | EXPORT_SYMBOL_GPL(iommu_domain_set_attr); | 951 | EXPORT_SYMBOL_GPL(iommu_domain_set_attr); |
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index d33c980e9c20..6ac02fa5910f 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c | |||
@@ -146,7 +146,7 @@ static int iommu_enable(struct omap_iommu *obj) | |||
146 | struct platform_device *pdev = to_platform_device(obj->dev); | 146 | struct platform_device *pdev = to_platform_device(obj->dev); |
147 | struct iommu_platform_data *pdata = pdev->dev.platform_data; | 147 | struct iommu_platform_data *pdata = pdev->dev.platform_data; |
148 | 148 | ||
149 | if (!obj || !pdata) | 149 | if (!pdata) |
150 | return -EINVAL; | 150 | return -EINVAL; |
151 | 151 | ||
152 | if (!arch_iommu) | 152 | if (!arch_iommu) |
@@ -172,7 +172,7 @@ static void iommu_disable(struct omap_iommu *obj) | |||
172 | struct platform_device *pdev = to_platform_device(obj->dev); | 172 | struct platform_device *pdev = to_platform_device(obj->dev); |
173 | struct iommu_platform_data *pdata = pdev->dev.platform_data; | 173 | struct iommu_platform_data *pdata = pdev->dev.platform_data; |
174 | 174 | ||
175 | if (!obj || !pdata) | 175 | if (!pdata) |
176 | return; | 176 | return; |
177 | 177 | ||
178 | arch_iommu->disable(obj); | 178 | arch_iommu->disable(obj); |
diff --git a/drivers/iommu/shmobile-iommu.c b/drivers/iommu/shmobile-iommu.c new file mode 100644 index 000000000000..b6e8b57cf0a8 --- /dev/null +++ b/drivers/iommu/shmobile-iommu.c | |||
@@ -0,0 +1,395 @@ | |||
1 | /* | ||
2 | * IOMMU for IPMMU/IPMMUI | ||
3 | * Copyright (C) 2012 Hideki EIRAKU | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; version 2 of the License. | ||
8 | */ | ||
9 | |||
10 | #include <linux/dma-mapping.h> | ||
11 | #include <linux/io.h> | ||
12 | #include <linux/iommu.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/sizes.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <asm/dma-iommu.h> | ||
17 | #include "shmobile-ipmmu.h" | ||
18 | |||
19 | #define L1_SIZE CONFIG_SHMOBILE_IOMMU_L1SIZE | ||
20 | #define L1_LEN (L1_SIZE / 4) | ||
21 | #define L1_ALIGN L1_SIZE | ||
22 | #define L2_SIZE SZ_1K | ||
23 | #define L2_LEN (L2_SIZE / 4) | ||
24 | #define L2_ALIGN L2_SIZE | ||
25 | |||
26 | struct shmobile_iommu_domain_pgtable { | ||
27 | uint32_t *pgtable; | ||
28 | dma_addr_t handle; | ||
29 | }; | ||
30 | |||
31 | struct shmobile_iommu_archdata { | ||
32 | struct list_head attached_list; | ||
33 | struct dma_iommu_mapping *iommu_mapping; | ||
34 | spinlock_t attach_lock; | ||
35 | struct shmobile_iommu_domain *attached; | ||
36 | int num_attached_devices; | ||
37 | struct shmobile_ipmmu *ipmmu; | ||
38 | }; | ||
39 | |||
40 | struct shmobile_iommu_domain { | ||
41 | struct shmobile_iommu_domain_pgtable l1, l2[L1_LEN]; | ||
42 | spinlock_t map_lock; | ||
43 | spinlock_t attached_list_lock; | ||
44 | struct list_head attached_list; | ||
45 | }; | ||
46 | |||
47 | static struct shmobile_iommu_archdata *ipmmu_archdata; | ||
48 | static struct kmem_cache *l1cache, *l2cache; | ||
49 | |||
50 | static int pgtable_alloc(struct shmobile_iommu_domain_pgtable *pgtable, | ||
51 | struct kmem_cache *cache, size_t size) | ||
52 | { | ||
53 | pgtable->pgtable = kmem_cache_zalloc(cache, GFP_ATOMIC); | ||
54 | if (!pgtable->pgtable) | ||
55 | return -ENOMEM; | ||
56 | pgtable->handle = dma_map_single(NULL, pgtable->pgtable, size, | ||
57 | DMA_TO_DEVICE); | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static void pgtable_free(struct shmobile_iommu_domain_pgtable *pgtable, | ||
62 | struct kmem_cache *cache, size_t size) | ||
63 | { | ||
64 | dma_unmap_single(NULL, pgtable->handle, size, DMA_TO_DEVICE); | ||
65 | kmem_cache_free(cache, pgtable->pgtable); | ||
66 | } | ||
67 | |||
68 | static uint32_t pgtable_read(struct shmobile_iommu_domain_pgtable *pgtable, | ||
69 | unsigned int index) | ||
70 | { | ||
71 | return pgtable->pgtable[index]; | ||
72 | } | ||
73 | |||
74 | static void pgtable_write(struct shmobile_iommu_domain_pgtable *pgtable, | ||
75 | unsigned int index, unsigned int count, uint32_t val) | ||
76 | { | ||
77 | unsigned int i; | ||
78 | |||
79 | for (i = 0; i < count; i++) | ||
80 | pgtable->pgtable[index + i] = val; | ||
81 | dma_sync_single_for_device(NULL, pgtable->handle + index * sizeof(val), | ||
82 | sizeof(val) * count, DMA_TO_DEVICE); | ||
83 | } | ||
84 | |||
85 | static int shmobile_iommu_domain_init(struct iommu_domain *domain) | ||
86 | { | ||
87 | struct shmobile_iommu_domain *sh_domain; | ||
88 | int i, ret; | ||
89 | |||
90 | sh_domain = kmalloc(sizeof(*sh_domain), GFP_KERNEL); | ||
91 | if (!sh_domain) | ||
92 | return -ENOMEM; | ||
93 | ret = pgtable_alloc(&sh_domain->l1, l1cache, L1_SIZE); | ||
94 | if (ret < 0) { | ||
95 | kfree(sh_domain); | ||
96 | return ret; | ||
97 | } | ||
98 | for (i = 0; i < L1_LEN; i++) | ||
99 | sh_domain->l2[i].pgtable = NULL; | ||
100 | spin_lock_init(&sh_domain->map_lock); | ||
101 | spin_lock_init(&sh_domain->attached_list_lock); | ||
102 | INIT_LIST_HEAD(&sh_domain->attached_list); | ||
103 | domain->priv = sh_domain; | ||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static void shmobile_iommu_domain_destroy(struct iommu_domain *domain) | ||
108 | { | ||
109 | struct shmobile_iommu_domain *sh_domain = domain->priv; | ||
110 | int i; | ||
111 | |||
112 | for (i = 0; i < L1_LEN; i++) { | ||
113 | if (sh_domain->l2[i].pgtable) | ||
114 | pgtable_free(&sh_domain->l2[i], l2cache, L2_SIZE); | ||
115 | } | ||
116 | pgtable_free(&sh_domain->l1, l1cache, L1_SIZE); | ||
117 | kfree(sh_domain); | ||
118 | domain->priv = NULL; | ||
119 | } | ||
120 | |||
121 | static int shmobile_iommu_attach_device(struct iommu_domain *domain, | ||
122 | struct device *dev) | ||
123 | { | ||
124 | struct shmobile_iommu_archdata *archdata = dev->archdata.iommu; | ||
125 | struct shmobile_iommu_domain *sh_domain = domain->priv; | ||
126 | int ret = -EBUSY; | ||
127 | |||
128 | if (!archdata) | ||
129 | return -ENODEV; | ||
130 | spin_lock(&sh_domain->attached_list_lock); | ||
131 | spin_lock(&archdata->attach_lock); | ||
132 | if (archdata->attached != sh_domain) { | ||
133 | if (archdata->attached) | ||
134 | goto err; | ||
135 | ipmmu_tlb_set(archdata->ipmmu, sh_domain->l1.handle, L1_SIZE, | ||
136 | 0); | ||
137 | ipmmu_tlb_flush(archdata->ipmmu); | ||
138 | archdata->attached = sh_domain; | ||
139 | archdata->num_attached_devices = 0; | ||
140 | list_add(&archdata->attached_list, &sh_domain->attached_list); | ||
141 | } | ||
142 | archdata->num_attached_devices++; | ||
143 | ret = 0; | ||
144 | err: | ||
145 | spin_unlock(&archdata->attach_lock); | ||
146 | spin_unlock(&sh_domain->attached_list_lock); | ||
147 | return ret; | ||
148 | } | ||
149 | |||
150 | static void shmobile_iommu_detach_device(struct iommu_domain *domain, | ||
151 | struct device *dev) | ||
152 | { | ||
153 | struct shmobile_iommu_archdata *archdata = dev->archdata.iommu; | ||
154 | struct shmobile_iommu_domain *sh_domain = domain->priv; | ||
155 | |||
156 | if (!archdata) | ||
157 | return; | ||
158 | spin_lock(&sh_domain->attached_list_lock); | ||
159 | spin_lock(&archdata->attach_lock); | ||
160 | archdata->num_attached_devices--; | ||
161 | if (!archdata->num_attached_devices) { | ||
162 | ipmmu_tlb_set(archdata->ipmmu, 0, 0, 0); | ||
163 | ipmmu_tlb_flush(archdata->ipmmu); | ||
164 | archdata->attached = NULL; | ||
165 | list_del(&archdata->attached_list); | ||
166 | } | ||
167 | spin_unlock(&archdata->attach_lock); | ||
168 | spin_unlock(&sh_domain->attached_list_lock); | ||
169 | } | ||
170 | |||
171 | static void domain_tlb_flush(struct shmobile_iommu_domain *sh_domain) | ||
172 | { | ||
173 | struct shmobile_iommu_archdata *archdata; | ||
174 | |||
175 | spin_lock(&sh_domain->attached_list_lock); | ||
176 | list_for_each_entry(archdata, &sh_domain->attached_list, attached_list) | ||
177 | ipmmu_tlb_flush(archdata->ipmmu); | ||
178 | spin_unlock(&sh_domain->attached_list_lock); | ||
179 | } | ||
180 | |||
181 | static int l2alloc(struct shmobile_iommu_domain *sh_domain, | ||
182 | unsigned int l1index) | ||
183 | { | ||
184 | int ret; | ||
185 | |||
186 | if (!sh_domain->l2[l1index].pgtable) { | ||
187 | ret = pgtable_alloc(&sh_domain->l2[l1index], l2cache, L2_SIZE); | ||
188 | if (ret < 0) | ||
189 | return ret; | ||
190 | } | ||
191 | pgtable_write(&sh_domain->l1, l1index, 1, | ||
192 | sh_domain->l2[l1index].handle | 0x1); | ||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static void l2realfree(struct shmobile_iommu_domain_pgtable *l2) | ||
197 | { | ||
198 | if (l2->pgtable) | ||
199 | pgtable_free(l2, l2cache, L2_SIZE); | ||
200 | } | ||
201 | |||
202 | static void l2free(struct shmobile_iommu_domain *sh_domain, | ||
203 | unsigned int l1index, | ||
204 | struct shmobile_iommu_domain_pgtable *l2) | ||
205 | { | ||
206 | pgtable_write(&sh_domain->l1, l1index, 1, 0); | ||
207 | if (sh_domain->l2[l1index].pgtable) { | ||
208 | *l2 = sh_domain->l2[l1index]; | ||
209 | sh_domain->l2[l1index].pgtable = NULL; | ||
210 | } | ||
211 | } | ||
212 | |||
213 | static int shmobile_iommu_map(struct iommu_domain *domain, unsigned long iova, | ||
214 | phys_addr_t paddr, size_t size, int prot) | ||
215 | { | ||
216 | struct shmobile_iommu_domain_pgtable l2 = { .pgtable = NULL }; | ||
217 | struct shmobile_iommu_domain *sh_domain = domain->priv; | ||
218 | unsigned int l1index, l2index; | ||
219 | int ret; | ||
220 | |||
221 | l1index = iova >> 20; | ||
222 | switch (size) { | ||
223 | case SZ_4K: | ||
224 | l2index = (iova >> 12) & 0xff; | ||
225 | spin_lock(&sh_domain->map_lock); | ||
226 | ret = l2alloc(sh_domain, l1index); | ||
227 | if (!ret) | ||
228 | pgtable_write(&sh_domain->l2[l1index], l2index, 1, | ||
229 | paddr | 0xff2); | ||
230 | spin_unlock(&sh_domain->map_lock); | ||
231 | break; | ||
232 | case SZ_64K: | ||
233 | l2index = (iova >> 12) & 0xf0; | ||
234 | spin_lock(&sh_domain->map_lock); | ||
235 | ret = l2alloc(sh_domain, l1index); | ||
236 | if (!ret) | ||
237 | pgtable_write(&sh_domain->l2[l1index], l2index, 0x10, | ||
238 | paddr | 0xff1); | ||
239 | spin_unlock(&sh_domain->map_lock); | ||
240 | break; | ||
241 | case SZ_1M: | ||
242 | spin_lock(&sh_domain->map_lock); | ||
243 | l2free(sh_domain, l1index, &l2); | ||
244 | pgtable_write(&sh_domain->l1, l1index, 1, paddr | 0xc02); | ||
245 | spin_unlock(&sh_domain->map_lock); | ||
246 | ret = 0; | ||
247 | break; | ||
248 | default: | ||
249 | ret = -EINVAL; | ||
250 | } | ||
251 | if (!ret) | ||
252 | domain_tlb_flush(sh_domain); | ||
253 | l2realfree(&l2); | ||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | static size_t shmobile_iommu_unmap(struct iommu_domain *domain, | ||
258 | unsigned long iova, size_t size) | ||
259 | { | ||
260 | struct shmobile_iommu_domain_pgtable l2 = { .pgtable = NULL }; | ||
261 | struct shmobile_iommu_domain *sh_domain = domain->priv; | ||
262 | unsigned int l1index, l2index; | ||
263 | uint32_t l2entry = 0; | ||
264 | size_t ret = 0; | ||
265 | |||
266 | l1index = iova >> 20; | ||
267 | if (!(iova & 0xfffff) && size >= SZ_1M) { | ||
268 | spin_lock(&sh_domain->map_lock); | ||
269 | l2free(sh_domain, l1index, &l2); | ||
270 | spin_unlock(&sh_domain->map_lock); | ||
271 | ret = SZ_1M; | ||
272 | goto done; | ||
273 | } | ||
274 | l2index = (iova >> 12) & 0xff; | ||
275 | spin_lock(&sh_domain->map_lock); | ||
276 | if (sh_domain->l2[l1index].pgtable) | ||
277 | l2entry = pgtable_read(&sh_domain->l2[l1index], l2index); | ||
278 | switch (l2entry & 3) { | ||
279 | case 1: | ||
280 | if (l2index & 0xf) | ||
281 | break; | ||
282 | pgtable_write(&sh_domain->l2[l1index], l2index, 0x10, 0); | ||
283 | ret = SZ_64K; | ||
284 | break; | ||
285 | case 2: | ||
286 | pgtable_write(&sh_domain->l2[l1index], l2index, 1, 0); | ||
287 | ret = SZ_4K; | ||
288 | break; | ||
289 | } | ||
290 | spin_unlock(&sh_domain->map_lock); | ||
291 | done: | ||
292 | if (ret) | ||
293 | domain_tlb_flush(sh_domain); | ||
294 | l2realfree(&l2); | ||
295 | return ret; | ||
296 | } | ||
297 | |||
298 | static phys_addr_t shmobile_iommu_iova_to_phys(struct iommu_domain *domain, | ||
299 | unsigned long iova) | ||
300 | { | ||
301 | struct shmobile_iommu_domain *sh_domain = domain->priv; | ||
302 | uint32_t l1entry = 0, l2entry = 0; | ||
303 | unsigned int l1index, l2index; | ||
304 | |||
305 | l1index = iova >> 20; | ||
306 | l2index = (iova >> 12) & 0xff; | ||
307 | spin_lock(&sh_domain->map_lock); | ||
308 | if (sh_domain->l2[l1index].pgtable) | ||
309 | l2entry = pgtable_read(&sh_domain->l2[l1index], l2index); | ||
310 | else | ||
311 | l1entry = pgtable_read(&sh_domain->l1, l1index); | ||
312 | spin_unlock(&sh_domain->map_lock); | ||
313 | switch (l2entry & 3) { | ||
314 | case 1: | ||
315 | return (l2entry & ~0xffff) | (iova & 0xffff); | ||
316 | case 2: | ||
317 | return (l2entry & ~0xfff) | (iova & 0xfff); | ||
318 | default: | ||
319 | if ((l1entry & 3) == 2) | ||
320 | return (l1entry & ~0xfffff) | (iova & 0xfffff); | ||
321 | return 0; | ||
322 | } | ||
323 | } | ||
324 | |||
325 | static int find_dev_name(struct shmobile_ipmmu *ipmmu, const char *dev_name) | ||
326 | { | ||
327 | unsigned int i, n = ipmmu->num_dev_names; | ||
328 | |||
329 | for (i = 0; i < n; i++) { | ||
330 | if (strcmp(ipmmu->dev_names[i], dev_name) == 0) | ||
331 | return 1; | ||
332 | } | ||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | static int shmobile_iommu_add_device(struct device *dev) | ||
337 | { | ||
338 | struct shmobile_iommu_archdata *archdata = ipmmu_archdata; | ||
339 | struct dma_iommu_mapping *mapping; | ||
340 | |||
341 | if (!find_dev_name(archdata->ipmmu, dev_name(dev))) | ||
342 | return 0; | ||
343 | mapping = archdata->iommu_mapping; | ||
344 | if (!mapping) { | ||
345 | mapping = arm_iommu_create_mapping(&platform_bus_type, 0, | ||
346 | L1_LEN << 20, 0); | ||
347 | if (IS_ERR(mapping)) | ||
348 | return PTR_ERR(mapping); | ||
349 | archdata->iommu_mapping = mapping; | ||
350 | } | ||
351 | dev->archdata.iommu = archdata; | ||
352 | if (arm_iommu_attach_device(dev, mapping)) | ||
353 | pr_err("arm_iommu_attach_device failed\n"); | ||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | static struct iommu_ops shmobile_iommu_ops = { | ||
358 | .domain_init = shmobile_iommu_domain_init, | ||
359 | .domain_destroy = shmobile_iommu_domain_destroy, | ||
360 | .attach_dev = shmobile_iommu_attach_device, | ||
361 | .detach_dev = shmobile_iommu_detach_device, | ||
362 | .map = shmobile_iommu_map, | ||
363 | .unmap = shmobile_iommu_unmap, | ||
364 | .iova_to_phys = shmobile_iommu_iova_to_phys, | ||
365 | .add_device = shmobile_iommu_add_device, | ||
366 | .pgsize_bitmap = SZ_1M | SZ_64K | SZ_4K, | ||
367 | }; | ||
368 | |||
369 | int ipmmu_iommu_init(struct shmobile_ipmmu *ipmmu) | ||
370 | { | ||
371 | static struct shmobile_iommu_archdata *archdata; | ||
372 | |||
373 | l1cache = kmem_cache_create("shmobile-iommu-pgtable1", L1_SIZE, | ||
374 | L1_ALIGN, SLAB_HWCACHE_ALIGN, NULL); | ||
375 | if (!l1cache) | ||
376 | return -ENOMEM; | ||
377 | l2cache = kmem_cache_create("shmobile-iommu-pgtable2", L2_SIZE, | ||
378 | L2_ALIGN, SLAB_HWCACHE_ALIGN, NULL); | ||
379 | if (!l2cache) { | ||
380 | kmem_cache_destroy(l1cache); | ||
381 | return -ENOMEM; | ||
382 | } | ||
383 | archdata = kmalloc(sizeof(*archdata), GFP_KERNEL); | ||
384 | if (!archdata) { | ||
385 | kmem_cache_destroy(l1cache); | ||
386 | kmem_cache_destroy(l2cache); | ||
387 | return -ENOMEM; | ||
388 | } | ||
389 | spin_lock_init(&archdata->attach_lock); | ||
390 | archdata->attached = NULL; | ||
391 | archdata->ipmmu = ipmmu; | ||
392 | ipmmu_archdata = archdata; | ||
393 | bus_set_iommu(&platform_bus_type, &shmobile_iommu_ops); | ||
394 | return 0; | ||
395 | } | ||
diff --git a/drivers/iommu/shmobile-ipmmu.c b/drivers/iommu/shmobile-ipmmu.c new file mode 100644 index 000000000000..8321f89596c4 --- /dev/null +++ b/drivers/iommu/shmobile-ipmmu.c | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | * IPMMU/IPMMUI | ||
3 | * Copyright (C) 2012 Hideki EIRAKU | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; version 2 of the License. | ||
8 | */ | ||
9 | |||
10 | #include <linux/err.h> | ||
11 | #include <linux/export.h> | ||
12 | #include <linux/io.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/platform_data/sh_ipmmu.h> | ||
16 | #include "shmobile-ipmmu.h" | ||
17 | |||
18 | #define IMCTR1 0x000 | ||
19 | #define IMCTR2 0x004 | ||
20 | #define IMASID 0x010 | ||
21 | #define IMTTBR 0x014 | ||
22 | #define IMTTBCR 0x018 | ||
23 | |||
24 | #define IMCTR1_TLBEN (1 << 0) | ||
25 | #define IMCTR1_FLUSH (1 << 1) | ||
26 | |||
27 | static void ipmmu_reg_write(struct shmobile_ipmmu *ipmmu, unsigned long reg_off, | ||
28 | unsigned long data) | ||
29 | { | ||
30 | iowrite32(data, ipmmu->ipmmu_base + reg_off); | ||
31 | } | ||
32 | |||
33 | void ipmmu_tlb_flush(struct shmobile_ipmmu *ipmmu) | ||
34 | { | ||
35 | if (!ipmmu) | ||
36 | return; | ||
37 | |||
38 | mutex_lock(&ipmmu->flush_lock); | ||
39 | if (ipmmu->tlb_enabled) | ||
40 | ipmmu_reg_write(ipmmu, IMCTR1, IMCTR1_FLUSH | IMCTR1_TLBEN); | ||
41 | else | ||
42 | ipmmu_reg_write(ipmmu, IMCTR1, IMCTR1_FLUSH); | ||
43 | mutex_unlock(&ipmmu->flush_lock); | ||
44 | } | ||
45 | |||
46 | void ipmmu_tlb_set(struct shmobile_ipmmu *ipmmu, unsigned long phys, int size, | ||
47 | int asid) | ||
48 | { | ||
49 | if (!ipmmu) | ||
50 | return; | ||
51 | |||
52 | mutex_lock(&ipmmu->flush_lock); | ||
53 | switch (size) { | ||
54 | default: | ||
55 | ipmmu->tlb_enabled = 0; | ||
56 | break; | ||
57 | case 0x2000: | ||
58 | ipmmu_reg_write(ipmmu, IMTTBCR, 1); | ||
59 | ipmmu->tlb_enabled = 1; | ||
60 | break; | ||
61 | case 0x1000: | ||
62 | ipmmu_reg_write(ipmmu, IMTTBCR, 2); | ||
63 | ipmmu->tlb_enabled = 1; | ||
64 | break; | ||
65 | case 0x800: | ||
66 | ipmmu_reg_write(ipmmu, IMTTBCR, 3); | ||
67 | ipmmu->tlb_enabled = 1; | ||
68 | break; | ||
69 | case 0x400: | ||
70 | ipmmu_reg_write(ipmmu, IMTTBCR, 4); | ||
71 | ipmmu->tlb_enabled = 1; | ||
72 | break; | ||
73 | case 0x200: | ||
74 | ipmmu_reg_write(ipmmu, IMTTBCR, 5); | ||
75 | ipmmu->tlb_enabled = 1; | ||
76 | break; | ||
77 | case 0x100: | ||
78 | ipmmu_reg_write(ipmmu, IMTTBCR, 6); | ||
79 | ipmmu->tlb_enabled = 1; | ||
80 | break; | ||
81 | case 0x80: | ||
82 | ipmmu_reg_write(ipmmu, IMTTBCR, 7); | ||
83 | ipmmu->tlb_enabled = 1; | ||
84 | break; | ||
85 | } | ||
86 | ipmmu_reg_write(ipmmu, IMTTBR, phys); | ||
87 | ipmmu_reg_write(ipmmu, IMASID, asid); | ||
88 | mutex_unlock(&ipmmu->flush_lock); | ||
89 | } | ||
90 | |||
91 | static int ipmmu_probe(struct platform_device *pdev) | ||
92 | { | ||
93 | struct shmobile_ipmmu *ipmmu; | ||
94 | struct resource *res; | ||
95 | struct shmobile_ipmmu_platform_data *pdata = pdev->dev.platform_data; | ||
96 | |||
97 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
98 | if (!res) { | ||
99 | dev_err(&pdev->dev, "cannot get platform resources\n"); | ||
100 | return -ENOENT; | ||
101 | } | ||
102 | ipmmu = devm_kzalloc(&pdev->dev, sizeof(*ipmmu), GFP_KERNEL); | ||
103 | if (!ipmmu) { | ||
104 | dev_err(&pdev->dev, "cannot allocate device data\n"); | ||
105 | return -ENOMEM; | ||
106 | } | ||
107 | mutex_init(&ipmmu->flush_lock); | ||
108 | ipmmu->dev = &pdev->dev; | ||
109 | ipmmu->ipmmu_base = devm_ioremap_nocache(&pdev->dev, res->start, | ||
110 | resource_size(res)); | ||
111 | if (!ipmmu->ipmmu_base) { | ||
112 | dev_err(&pdev->dev, "ioremap_nocache failed\n"); | ||
113 | return -ENOMEM; | ||
114 | } | ||
115 | ipmmu->dev_names = pdata->dev_names; | ||
116 | ipmmu->num_dev_names = pdata->num_dev_names; | ||
117 | platform_set_drvdata(pdev, ipmmu); | ||
118 | ipmmu_reg_write(ipmmu, IMCTR1, 0x0); /* disable TLB */ | ||
119 | ipmmu_reg_write(ipmmu, IMCTR2, 0x0); /* disable PMB */ | ||
120 | ipmmu_iommu_init(ipmmu); | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static struct platform_driver ipmmu_driver = { | ||
125 | .probe = ipmmu_probe, | ||
126 | .driver = { | ||
127 | .owner = THIS_MODULE, | ||
128 | .name = "ipmmu", | ||
129 | }, | ||
130 | }; | ||
131 | |||
132 | static int __init ipmmu_init(void) | ||
133 | { | ||
134 | return platform_driver_register(&ipmmu_driver); | ||
135 | } | ||
136 | subsys_initcall(ipmmu_init); | ||
diff --git a/drivers/iommu/shmobile-ipmmu.h b/drivers/iommu/shmobile-ipmmu.h new file mode 100644 index 000000000000..4d53684673e1 --- /dev/null +++ b/drivers/iommu/shmobile-ipmmu.h | |||
@@ -0,0 +1,34 @@ | |||
1 | /* shmobile-ipmmu.h | ||
2 | * | ||
3 | * Copyright (C) 2012 Hideki EIRAKU | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; version 2 of the License. | ||
8 | */ | ||
9 | |||
10 | #ifndef __SHMOBILE_IPMMU_H__ | ||
11 | #define __SHMOBILE_IPMMU_H__ | ||
12 | |||
13 | struct shmobile_ipmmu { | ||
14 | struct device *dev; | ||
15 | void __iomem *ipmmu_base; | ||
16 | int tlb_enabled; | ||
17 | struct mutex flush_lock; | ||
18 | const char * const *dev_names; | ||
19 | unsigned int num_dev_names; | ||
20 | }; | ||
21 | |||
22 | #ifdef CONFIG_SHMOBILE_IPMMU_TLB | ||
23 | void ipmmu_tlb_flush(struct shmobile_ipmmu *ipmmu); | ||
24 | void ipmmu_tlb_set(struct shmobile_ipmmu *ipmmu, unsigned long phys, int size, | ||
25 | int asid); | ||
26 | int ipmmu_iommu_init(struct shmobile_ipmmu *ipmmu); | ||
27 | #else | ||
28 | static inline int ipmmu_iommu_init(struct shmobile_ipmmu *ipmmu) | ||
29 | { | ||
30 | return -EINVAL; | ||
31 | } | ||
32 | #endif | ||
33 | |||
34 | #endif /* __SHMOBILE_IPMMU_H__ */ | ||
diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c index 8219f1d596ee..86437575f94d 100644 --- a/drivers/iommu/tegra-gart.c +++ b/drivers/iommu/tegra-gart.c | |||
@@ -430,13 +430,11 @@ const struct dev_pm_ops tegra_gart_pm_ops = { | |||
430 | .resume = tegra_gart_resume, | 430 | .resume = tegra_gart_resume, |
431 | }; | 431 | }; |
432 | 432 | ||
433 | #ifdef CONFIG_OF | ||
434 | static struct of_device_id tegra_gart_of_match[] = { | 433 | static struct of_device_id tegra_gart_of_match[] = { |
435 | { .compatible = "nvidia,tegra20-gart", }, | 434 | { .compatible = "nvidia,tegra20-gart", }, |
436 | { }, | 435 | { }, |
437 | }; | 436 | }; |
438 | MODULE_DEVICE_TABLE(of, tegra_gart_of_match); | 437 | MODULE_DEVICE_TABLE(of, tegra_gart_of_match); |
439 | #endif | ||
440 | 438 | ||
441 | static struct platform_driver tegra_gart_driver = { | 439 | static struct platform_driver tegra_gart_driver = { |
442 | .probe = tegra_gart_probe, | 440 | .probe = tegra_gart_probe, |
@@ -445,7 +443,7 @@ static struct platform_driver tegra_gart_driver = { | |||
445 | .owner = THIS_MODULE, | 443 | .owner = THIS_MODULE, |
446 | .name = "tegra-gart", | 444 | .name = "tegra-gart", |
447 | .pm = &tegra_gart_pm_ops, | 445 | .pm = &tegra_gart_pm_ops, |
448 | .of_match_table = of_match_ptr(tegra_gart_of_match), | 446 | .of_match_table = tegra_gart_of_match, |
449 | }, | 447 | }, |
450 | }; | 448 | }; |
451 | 449 | ||
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index f08dbcd2f175..eb0109f98946 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * IOMMU API for SMMU in Tegra30 | 2 | * IOMMU API for SMMU in Tegra30 |
3 | * | 3 | * |
4 | * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. | 4 | * Copyright (c) 2011-2013, NVIDIA CORPORATION. All rights reserved. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
@@ -294,7 +294,11 @@ struct smmu_debugfs_info { | |||
294 | * Per SMMU device - IOMMU device | 294 | * Per SMMU device - IOMMU device |
295 | */ | 295 | */ |
296 | struct smmu_device { | 296 | struct smmu_device { |
297 | void __iomem *regs[NUM_SMMU_REG_BANKS]; | 297 | void __iomem *regbase; /* register offset base */ |
298 | void __iomem **regs; /* register block start address array */ | ||
299 | void __iomem **rege; /* register block end address array */ | ||
300 | int nregs; /* number of register blocks */ | ||
301 | |||
298 | unsigned long iovmm_base; /* remappable base address */ | 302 | unsigned long iovmm_base; /* remappable base address */ |
299 | unsigned long page_count; /* total remappable size */ | 303 | unsigned long page_count; /* total remappable size */ |
300 | spinlock_t lock; | 304 | spinlock_t lock; |
@@ -324,38 +328,37 @@ static struct smmu_device *smmu_handle; /* unique for a system */ | |||
324 | /* | 328 | /* |
325 | * SMMU register accessors | 329 | * SMMU register accessors |
326 | */ | 330 | */ |
331 | static bool inline smmu_valid_reg(struct smmu_device *smmu, | ||
332 | void __iomem *addr) | ||
333 | { | ||
334 | int i; | ||
335 | |||
336 | for (i = 0; i < smmu->nregs; i++) { | ||
337 | if (addr < smmu->regs[i]) | ||
338 | break; | ||
339 | if (addr <= smmu->rege[i]) | ||
340 | return true; | ||
341 | } | ||
342 | |||
343 | return false; | ||
344 | } | ||
345 | |||
327 | static inline u32 smmu_read(struct smmu_device *smmu, size_t offs) | 346 | static inline u32 smmu_read(struct smmu_device *smmu, size_t offs) |
328 | { | 347 | { |
329 | BUG_ON(offs < 0x10); | 348 | void __iomem *addr = smmu->regbase + offs; |
330 | if (offs < 0x3c) | 349 | |
331 | return readl(smmu->regs[0] + offs - 0x10); | 350 | BUG_ON(!smmu_valid_reg(smmu, addr)); |
332 | BUG_ON(offs < 0x1f0); | 351 | |
333 | if (offs < 0x200) | 352 | return readl(addr); |
334 | return readl(smmu->regs[1] + offs - 0x1f0); | ||
335 | BUG_ON(offs < 0x228); | ||
336 | if (offs < 0x284) | ||
337 | return readl(smmu->regs[2] + offs - 0x228); | ||
338 | BUG(); | ||
339 | } | 353 | } |
340 | 354 | ||
341 | static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs) | 355 | static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs) |
342 | { | 356 | { |
343 | BUG_ON(offs < 0x10); | 357 | void __iomem *addr = smmu->regbase + offs; |
344 | if (offs < 0x3c) { | 358 | |
345 | writel(val, smmu->regs[0] + offs - 0x10); | 359 | BUG_ON(!smmu_valid_reg(smmu, addr)); |
346 | return; | 360 | |
347 | } | 361 | writel(val, addr); |
348 | BUG_ON(offs < 0x1f0); | ||
349 | if (offs < 0x200) { | ||
350 | writel(val, smmu->regs[1] + offs - 0x1f0); | ||
351 | return; | ||
352 | } | ||
353 | BUG_ON(offs < 0x228); | ||
354 | if (offs < 0x284) { | ||
355 | writel(val, smmu->regs[2] + offs - 0x228); | ||
356 | return; | ||
357 | } | ||
358 | BUG(); | ||
359 | } | 362 | } |
360 | 363 | ||
361 | #define VA_PAGE_TO_PA(va, page) \ | 364 | #define VA_PAGE_TO_PA(va, page) \ |
@@ -1171,7 +1174,13 @@ static int tegra_smmu_probe(struct platform_device *pdev) | |||
1171 | return -ENOMEM; | 1174 | return -ENOMEM; |
1172 | } | 1175 | } |
1173 | 1176 | ||
1174 | for (i = 0; i < ARRAY_SIZE(smmu->regs); i++) { | 1177 | smmu->nregs = pdev->num_resources; |
1178 | smmu->regs = devm_kzalloc(dev, 2 * smmu->nregs * sizeof(*smmu->regs), | ||
1179 | GFP_KERNEL); | ||
1180 | smmu->rege = smmu->regs + smmu->nregs; | ||
1181 | if (!smmu->regs) | ||
1182 | return -ENOMEM; | ||
1183 | for (i = 0; i < smmu->nregs; i++) { | ||
1175 | struct resource *res; | 1184 | struct resource *res; |
1176 | 1185 | ||
1177 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); | 1186 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); |
@@ -1180,7 +1189,10 @@ static int tegra_smmu_probe(struct platform_device *pdev) | |||
1180 | smmu->regs[i] = devm_ioremap_resource(&pdev->dev, res); | 1189 | smmu->regs[i] = devm_ioremap_resource(&pdev->dev, res); |
1181 | if (IS_ERR(smmu->regs[i])) | 1190 | if (IS_ERR(smmu->regs[i])) |
1182 | return PTR_ERR(smmu->regs[i]); | 1191 | return PTR_ERR(smmu->regs[i]); |
1192 | smmu->rege[i] = smmu->regs[i] + resource_size(res) - 1; | ||
1183 | } | 1193 | } |
1194 | /* Same as "mc" 1st regiter block start address */ | ||
1195 | smmu->regbase = (void __iomem *)((u32)smmu->regs[0] & PAGE_MASK); | ||
1184 | 1196 | ||
1185 | err = of_get_dma_window(dev->of_node, NULL, 0, NULL, &base, &size); | 1197 | err = of_get_dma_window(dev->of_node, NULL, 0, NULL, &base, &size); |
1186 | if (err) | 1198 | if (err) |
@@ -1217,6 +1229,7 @@ static int tegra_smmu_probe(struct platform_device *pdev) | |||
1217 | as->pte_attr = _PTE_ATTR; | 1229 | as->pte_attr = _PTE_ATTR; |
1218 | 1230 | ||
1219 | spin_lock_init(&as->lock); | 1231 | spin_lock_init(&as->lock); |
1232 | spin_lock_init(&as->client_lock); | ||
1220 | INIT_LIST_HEAD(&as->client); | 1233 | INIT_LIST_HEAD(&as->client); |
1221 | } | 1234 | } |
1222 | spin_lock_init(&smmu->lock); | 1235 | spin_lock_init(&smmu->lock); |
@@ -1255,13 +1268,11 @@ const struct dev_pm_ops tegra_smmu_pm_ops = { | |||
1255 | .resume = tegra_smmu_resume, | 1268 | .resume = tegra_smmu_resume, |
1256 | }; | 1269 | }; |
1257 | 1270 | ||
1258 | #ifdef CONFIG_OF | ||
1259 | static struct of_device_id tegra_smmu_of_match[] = { | 1271 | static struct of_device_id tegra_smmu_of_match[] = { |
1260 | { .compatible = "nvidia,tegra30-smmu", }, | 1272 | { .compatible = "nvidia,tegra30-smmu", }, |
1261 | { }, | 1273 | { }, |
1262 | }; | 1274 | }; |
1263 | MODULE_DEVICE_TABLE(of, tegra_smmu_of_match); | 1275 | MODULE_DEVICE_TABLE(of, tegra_smmu_of_match); |
1264 | #endif | ||
1265 | 1276 | ||
1266 | static struct platform_driver tegra_smmu_driver = { | 1277 | static struct platform_driver tegra_smmu_driver = { |
1267 | .probe = tegra_smmu_probe, | 1278 | .probe = tegra_smmu_probe, |
@@ -1270,7 +1281,7 @@ static struct platform_driver tegra_smmu_driver = { | |||
1270 | .owner = THIS_MODULE, | 1281 | .owner = THIS_MODULE, |
1271 | .name = "tegra-smmu", | 1282 | .name = "tegra-smmu", |
1272 | .pm = &tegra_smmu_pm_ops, | 1283 | .pm = &tegra_smmu_pm_ops, |
1273 | .of_match_table = of_match_ptr(tegra_smmu_of_match), | 1284 | .of_match_table = tegra_smmu_of_match, |
1274 | }, | 1285 | }, |
1275 | }; | 1286 | }; |
1276 | 1287 | ||
diff --git a/include/linux/iommu.h b/include/linux/iommu.h index f3b99e1c1042..ba3b8a98a049 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h | |||
@@ -58,8 +58,10 @@ struct iommu_domain { | |||
58 | #define IOMMU_CAP_INTR_REMAP 0x2 /* isolates device intrs */ | 58 | #define IOMMU_CAP_INTR_REMAP 0x2 /* isolates device intrs */ |
59 | 59 | ||
60 | enum iommu_attr { | 60 | enum iommu_attr { |
61 | DOMAIN_ATTR_MAX, | ||
62 | DOMAIN_ATTR_GEOMETRY, | 61 | DOMAIN_ATTR_GEOMETRY, |
62 | DOMAIN_ATTR_PAGING, | ||
63 | DOMAIN_ATTR_WINDOWS, | ||
64 | DOMAIN_ATTR_MAX, | ||
63 | }; | 65 | }; |
64 | 66 | ||
65 | #ifdef CONFIG_IOMMU_API | 67 | #ifdef CONFIG_IOMMU_API |
@@ -100,6 +102,16 @@ struct iommu_ops { | |||
100 | enum iommu_attr attr, void *data); | 102 | enum iommu_attr attr, void *data); |
101 | int (*domain_set_attr)(struct iommu_domain *domain, | 103 | int (*domain_set_attr)(struct iommu_domain *domain, |
102 | enum iommu_attr attr, void *data); | 104 | enum iommu_attr attr, void *data); |
105 | |||
106 | /* Window handling functions */ | ||
107 | int (*domain_window_enable)(struct iommu_domain *domain, u32 wnd_nr, | ||
108 | phys_addr_t paddr, u64 size); | ||
109 | void (*domain_window_disable)(struct iommu_domain *domain, u32 wnd_nr); | ||
110 | /* Set the numer of window per domain */ | ||
111 | int (*domain_set_windows)(struct iommu_domain *domain, u32 w_count); | ||
112 | /* Get the numer of window per domain */ | ||
113 | u32 (*domain_get_windows)(struct iommu_domain *domain); | ||
114 | |||
103 | unsigned long pgsize_bitmap; | 115 | unsigned long pgsize_bitmap; |
104 | }; | 116 | }; |
105 | 117 | ||
@@ -157,6 +169,10 @@ extern int iommu_domain_get_attr(struct iommu_domain *domain, enum iommu_attr, | |||
157 | extern int iommu_domain_set_attr(struct iommu_domain *domain, enum iommu_attr, | 169 | extern int iommu_domain_set_attr(struct iommu_domain *domain, enum iommu_attr, |
158 | void *data); | 170 | void *data); |
159 | 171 | ||
172 | /* Window handling function prototypes */ | ||
173 | extern int iommu_domain_window_enable(struct iommu_domain *domain, u32 wnd_nr, | ||
174 | phys_addr_t offset, u64 size); | ||
175 | extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr); | ||
160 | /** | 176 | /** |
161 | * report_iommu_fault() - report about an IOMMU fault to the IOMMU framework | 177 | * report_iommu_fault() - report about an IOMMU fault to the IOMMU framework |
162 | * @domain: the iommu domain where the fault has happened | 178 | * @domain: the iommu domain where the fault has happened |
@@ -239,6 +255,18 @@ static inline int iommu_unmap(struct iommu_domain *domain, unsigned long iova, | |||
239 | return -ENODEV; | 255 | return -ENODEV; |
240 | } | 256 | } |
241 | 257 | ||
258 | static inline int iommu_domain_window_enable(struct iommu_domain *domain, | ||
259 | u32 wnd_nr, phys_addr_t paddr, | ||
260 | u64 size) | ||
261 | { | ||
262 | return -ENODEV; | ||
263 | } | ||
264 | |||
265 | static inline void iommu_domain_window_disable(struct iommu_domain *domain, | ||
266 | u32 wnd_nr) | ||
267 | { | ||
268 | } | ||
269 | |||
242 | static inline phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, | 270 | static inline phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, |
243 | unsigned long iova) | 271 | unsigned long iova) |
244 | { | 272 | { |
diff --git a/include/linux/platform_data/sh_ipmmu.h b/include/linux/platform_data/sh_ipmmu.h new file mode 100644 index 000000000000..39f7405cdac5 --- /dev/null +++ b/include/linux/platform_data/sh_ipmmu.h | |||
@@ -0,0 +1,18 @@ | |||
1 | /* sh_ipmmu.h | ||
2 | * | ||
3 | * Copyright (C) 2012 Hideki EIRAKU | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; version 2 of the License. | ||
8 | */ | ||
9 | |||
10 | #ifndef __SH_IPMMU_H__ | ||
11 | #define __SH_IPMMU_H__ | ||
12 | |||
13 | struct shmobile_ipmmu_platform_data { | ||
14 | const char * const *dev_names; | ||
15 | unsigned int num_dev_names; | ||
16 | }; | ||
17 | |||
18 | #endif /* __SH_IPMMU_H__ */ | ||