diff options
74 files changed, 2630 insertions, 1015 deletions
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-ahb.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-ahb.txt new file mode 100644 index 000000000000..234406d41c12 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-ahb.txt | |||
@@ -0,0 +1,11 @@ | |||
1 | NVIDIA Tegra AHB | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : "nvidia,tegra20-ahb" or "nvidia,tegra30-ahb" | ||
5 | - reg : Should contain 1 register ranges(address and length) | ||
6 | |||
7 | Example: | ||
8 | ahb: ahb@6000c004 { | ||
9 | compatible = "nvidia,tegra20-ahb"; | ||
10 | reg = <0x6000c004 0x10c>; /* AHB Arbitration + Gizmo Controller */ | ||
11 | }; | ||
diff --git a/Documentation/devicetree/bindings/mmc/fsl-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-esdhc.txt index 64bcb8be973c..0d93b4b0e0e3 100644 --- a/Documentation/devicetree/bindings/mmc/fsl-esdhc.txt +++ b/Documentation/devicetree/bindings/mmc/fsl-esdhc.txt | |||
@@ -11,9 +11,11 @@ Required properties: | |||
11 | - interrupt-parent : interrupt source phandle. | 11 | - interrupt-parent : interrupt source phandle. |
12 | - clock-frequency : specifies eSDHC base clock frequency. | 12 | - clock-frequency : specifies eSDHC base clock frequency. |
13 | - sdhci,wp-inverted : (optional) specifies that eSDHC controller | 13 | - sdhci,wp-inverted : (optional) specifies that eSDHC controller |
14 | reports inverted write-protect state; | 14 | reports inverted write-protect state; New devices should use |
15 | the generic "wp-inverted" property. | ||
15 | - sdhci,1-bit-only : (optional) specifies that a controller can | 16 | - sdhci,1-bit-only : (optional) specifies that a controller can |
16 | only handle 1-bit data transfers. | 17 | only handle 1-bit data transfers. New devices should use the |
18 | generic "bus-width = <1>" property. | ||
17 | - sdhci,auto-cmd12: (optional) specifies that a controller can | 19 | - sdhci,auto-cmd12: (optional) specifies that a controller can |
18 | only handle auto CMD12. | 20 | only handle auto CMD12. |
19 | 21 | ||
diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt index ab22fe6e73ab..c7e404b3ef05 100644 --- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt | |||
@@ -9,7 +9,7 @@ Required properties: | |||
9 | - interrupts : Should contain eSDHC interrupt | 9 | - interrupts : Should contain eSDHC interrupt |
10 | 10 | ||
11 | Optional properties: | 11 | Optional properties: |
12 | - fsl,card-wired : Indicate the card is wired to host permanently | 12 | - non-removable : Indicate the card is wired to host permanently |
13 | - fsl,cd-internal : Indicate to use controller internal card detection | 13 | - fsl,cd-internal : Indicate to use controller internal card detection |
14 | - fsl,wp-internal : Indicate to use controller internal write protection | 14 | - fsl,wp-internal : Indicate to use controller internal write protection |
15 | - cd-gpios : Specify GPIOs for card detection | 15 | - cd-gpios : Specify GPIOs for card detection |
diff --git a/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt b/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt index 89a0084df2f7..d64aea5a4203 100644 --- a/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt +++ b/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt | |||
@@ -10,7 +10,8 @@ Required properties: | |||
10 | 10 | ||
11 | Optional properties: | 11 | Optional properties: |
12 | - gpios : may specify GPIOs in this order: Card-Detect GPIO, | 12 | - gpios : may specify GPIOs in this order: Card-Detect GPIO, |
13 | Write-Protect GPIO. | 13 | Write-Protect GPIO. Note that this does not follow the |
14 | binding from mmc.txt, for historic reasons. | ||
14 | - interrupts : the interrupt of a card detect interrupt. | 15 | - interrupts : the interrupt of a card detect interrupt. |
15 | - interrupt-parent : the phandle for the interrupt controller that | 16 | - interrupt-parent : the phandle for the interrupt controller that |
16 | services interrupts for this device. | 17 | services interrupts for this device. |
diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt new file mode 100644 index 000000000000..6e70dcde0a71 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/mmc.txt | |||
@@ -0,0 +1,27 @@ | |||
1 | These properties are common to multiple MMC host controllers. Any host | ||
2 | that requires the respective functionality should implement them using | ||
3 | these definitions. | ||
4 | |||
5 | Required properties: | ||
6 | - bus-width: Number of data lines, can be <1>, <4>, or <8> | ||
7 | |||
8 | Optional properties: | ||
9 | - cd-gpios : Specify GPIOs for card detection, see gpio binding | ||
10 | - wp-gpios : Specify GPIOs for write protection, see gpio binding | ||
11 | - cd-inverted: when present, polarity on the wp gpio line is inverted | ||
12 | - wp-inverted: when present, polarity on the wp gpio line is inverted | ||
13 | - non-removable: non-removable slot (like eMMC) | ||
14 | - max-frequency: maximum operating clock frequency | ||
15 | |||
16 | Example: | ||
17 | |||
18 | sdhci@ab000000 { | ||
19 | compatible = "sdhci"; | ||
20 | reg = <0xab000000 0x200>; | ||
21 | interrupts = <23>; | ||
22 | bus-width = <4>; | ||
23 | cd-gpios = <&gpio 69 0>; | ||
24 | cd-inverted; | ||
25 | wp-gpios = <&gpio 70 0>; | ||
26 | max-frequency = <50000000>; | ||
27 | } | ||
diff --git a/Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt b/Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt index 7e51154679a6..f77c3031607f 100644 --- a/Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt +++ b/Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt | |||
@@ -7,12 +7,12 @@ Required properties: | |||
7 | - compatible : Should be "nvidia,<chip>-sdhci" | 7 | - compatible : Should be "nvidia,<chip>-sdhci" |
8 | - reg : Should contain SD/MMC registers location and length | 8 | - reg : Should contain SD/MMC registers location and length |
9 | - interrupts : Should contain SD/MMC interrupt | 9 | - interrupts : Should contain SD/MMC interrupt |
10 | - bus-width : Number of data lines, can be <1>, <4>, or <8> | ||
10 | 11 | ||
11 | Optional properties: | 12 | Optional properties: |
12 | - cd-gpios : Specify GPIOs for card detection | 13 | - cd-gpios : Specify GPIOs for card detection |
13 | - wp-gpios : Specify GPIOs for write protection | 14 | - wp-gpios : Specify GPIOs for write protection |
14 | - power-gpios : Specify GPIOs for power control | 15 | - power-gpios : Specify GPIOs for power control |
15 | - support-8bit : Boolean, indicates if 8-bit mode should be used. | ||
16 | 16 | ||
17 | Example: | 17 | Example: |
18 | 18 | ||
@@ -23,5 +23,5 @@ sdhci@c8000200 { | |||
23 | cd-gpios = <&gpio 69 0>; /* gpio PI5 */ | 23 | cd-gpios = <&gpio 69 0>; /* gpio PI5 */ |
24 | wp-gpios = <&gpio 57 0>; /* gpio PH1 */ | 24 | wp-gpios = <&gpio 57 0>; /* gpio PH1 */ |
25 | power-gpios = <&gpio 155 0>; /* gpio PT3 */ | 25 | power-gpios = <&gpio 155 0>; /* gpio PT3 */ |
26 | support-8bit; | 26 | bus-width = <8>; |
27 | }; | 27 | }; |
diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt index dbd4368ab8cc..8a53958c9a9f 100644 --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt | |||
@@ -15,7 +15,7 @@ Optional properties: | |||
15 | ti,dual-volt: boolean, supports dual voltage cards | 15 | ti,dual-volt: boolean, supports dual voltage cards |
16 | <supply-name>-supply: phandle to the regulator device tree node | 16 | <supply-name>-supply: phandle to the regulator device tree node |
17 | "supply-name" examples are "vmmc", "vmmc_aux" etc | 17 | "supply-name" examples are "vmmc", "vmmc_aux" etc |
18 | ti,bus-width: Number of data lines, default assumed is 1 if the property is missing. | 18 | bus-width: Number of data lines, default assumed is 1 if the property is missing. |
19 | cd-gpios: GPIOs for card detection | 19 | cd-gpios: GPIOs for card detection |
20 | wp-gpios: GPIOs for write protection | 20 | wp-gpios: GPIOs for write protection |
21 | ti,non-removable: non-removable slot (like eMMC) | 21 | ti,non-removable: non-removable slot (like eMMC) |
@@ -27,7 +27,7 @@ Example: | |||
27 | reg = <0x4809c000 0x400>; | 27 | reg = <0x4809c000 0x400>; |
28 | ti,hwmods = "mmc1"; | 28 | ti,hwmods = "mmc1"; |
29 | ti,dual-volt; | 29 | ti,dual-volt; |
30 | ti,bus-width = <4>; | 30 | bus-width = <4>; |
31 | vmmc-supply = <&vmmc>; /* phandle to regulator node */ | 31 | vmmc-supply = <&vmmc>; /* phandle to regulator node */ |
32 | ti,non-removable; | 32 | ti,non-removable; |
33 | }; | 33 | }; |
diff --git a/Documentation/devicetree/bindings/usb/tegra-usb.txt b/Documentation/devicetree/bindings/usb/tegra-usb.txt index 007005ddbe12..e9b005dc7625 100644 --- a/Documentation/devicetree/bindings/usb/tegra-usb.txt +++ b/Documentation/devicetree/bindings/usb/tegra-usb.txt | |||
@@ -12,6 +12,9 @@ Required properties : | |||
12 | - nvidia,vbus-gpio : If present, specifies a gpio that needs to be | 12 | - nvidia,vbus-gpio : If present, specifies a gpio that needs to be |
13 | activated for the bus to be powered. | 13 | activated for the bus to be powered. |
14 | 14 | ||
15 | Required properties for phy_type == ulpi: | ||
16 | - nvidia,phy-reset-gpio : The GPIO used to reset the PHY. | ||
17 | |||
15 | Optional properties: | 18 | Optional properties: |
16 | - dr_mode : dual role mode. Indicates the working mode for | 19 | - dr_mode : dual role mode. Indicates the working mode for |
17 | nvidia,tegra20-ehci compatible controllers. Can be "host", "peripheral", | 20 | nvidia,tegra20-ehci compatible controllers. Can be "host", "peripheral", |
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 85348a09d655..e561adc1db0c 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug | |||
@@ -103,6 +103,35 @@ choice | |||
103 | Say Y here if you want the debug print routines to direct | 103 | Say Y here if you want the debug print routines to direct |
104 | their output to the second serial port on these devices. | 104 | their output to the second serial port on these devices. |
105 | 105 | ||
106 | config DEBUG_DAVINCI_DA8XX_UART1 | ||
107 | bool "Kernel low-level debugging on DaVinci DA8XX using UART1" | ||
108 | depends on ARCH_DAVINCI_DA8XX | ||
109 | help | ||
110 | Say Y here if you want the debug print routines to direct | ||
111 | their output to UART1 serial port on DaVinci DA8XX devices. | ||
112 | |||
113 | config DEBUG_DAVINCI_DA8XX_UART2 | ||
114 | bool "Kernel low-level debugging on DaVinci DA8XX using UART2" | ||
115 | depends on ARCH_DAVINCI_DA8XX | ||
116 | help | ||
117 | Say Y here if you want the debug print routines to direct | ||
118 | their output to UART2 serial port on DaVinci DA8XX devices. | ||
119 | |||
120 | config DEBUG_DAVINCI_DMx_UART0 | ||
121 | bool "Kernel low-level debugging on DaVinci DMx using UART0" | ||
122 | depends on ARCH_DAVINCI_DMx | ||
123 | help | ||
124 | Say Y here if you want the debug print routines to direct | ||
125 | their output to UART0 serial port on DaVinci DMx devices. | ||
126 | |||
127 | config DEBUG_DAVINCI_TNETV107X_UART1 | ||
128 | bool "Kernel low-level debugging on DaVinci TNETV107x using UART1" | ||
129 | depends on ARCH_DAVINCI_TNETV107X | ||
130 | help | ||
131 | Say Y here if you want the debug print routines to direct | ||
132 | their output to UART1 serial port on DaVinci TNETV107X | ||
133 | devices. | ||
134 | |||
106 | config DEBUG_DC21285_PORT | 135 | config DEBUG_DC21285_PORT |
107 | bool "Kernel low-level debugging messages via footbridge serial port" | 136 | bool "Kernel low-level debugging messages via footbridge serial port" |
108 | depends on FOOTBRIDGE | 137 | depends on FOOTBRIDGE |
diff --git a/arch/arm/boot/dts/imx53-smd.dts b/arch/arm/boot/dts/imx53-smd.dts index c7ee86c2dfb5..139138a556b0 100644 --- a/arch/arm/boot/dts/imx53-smd.dts +++ b/arch/arm/boot/dts/imx53-smd.dts | |||
@@ -35,7 +35,7 @@ | |||
35 | }; | 35 | }; |
36 | 36 | ||
37 | esdhc@50008000 { /* ESDHC2 */ | 37 | esdhc@50008000 { /* ESDHC2 */ |
38 | fsl,card-wired; | 38 | non-removable; |
39 | status = "okay"; | 39 | status = "okay"; |
40 | }; | 40 | }; |
41 | 41 | ||
@@ -76,7 +76,7 @@ | |||
76 | }; | 76 | }; |
77 | 77 | ||
78 | esdhc@50020000 { /* ESDHC3 */ | 78 | esdhc@50020000 { /* ESDHC3 */ |
79 | fsl,card-wired; | 79 | non-removable; |
80 | status = "okay"; | 80 | status = "okay"; |
81 | }; | 81 | }; |
82 | }; | 82 | }; |
diff --git a/arch/arm/boot/dts/imx6q-arm2.dts b/arch/arm/boot/dts/imx6q-arm2.dts index ce1c8238c897..d2eaf521c9fd 100644 --- a/arch/arm/boot/dts/imx6q-arm2.dts +++ b/arch/arm/boot/dts/imx6q-arm2.dts | |||
@@ -41,7 +41,7 @@ | |||
41 | }; | 41 | }; |
42 | 42 | ||
43 | usdhc@0219c000 { /* uSDHC4 */ | 43 | usdhc@0219c000 { /* uSDHC4 */ |
44 | fsl,card-wired; | 44 | non-removable; |
45 | vmmc-supply = <®_3p3v>; | 45 | vmmc-supply = <®_3p3v>; |
46 | status = "okay"; | 46 | status = "okay"; |
47 | }; | 47 | }; |
diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts index 8c756be4d7ad..5b4506c0a8c4 100644 --- a/arch/arm/boot/dts/omap3-beagle.dts +++ b/arch/arm/boot/dts/omap3-beagle.dts | |||
@@ -57,7 +57,7 @@ | |||
57 | &mmc1 { | 57 | &mmc1 { |
58 | vmmc-supply = <&vmmc1>; | 58 | vmmc-supply = <&vmmc1>; |
59 | vmmc_aux-supply = <&vsim>; | 59 | vmmc_aux-supply = <&vsim>; |
60 | ti,bus-width = <8>; | 60 | bus-width = <8>; |
61 | }; | 61 | }; |
62 | 62 | ||
63 | &mmc2 { | 63 | &mmc2 { |
diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts index e671361bc791..1efe0c587985 100644 --- a/arch/arm/boot/dts/omap4-panda.dts +++ b/arch/arm/boot/dts/omap4-panda.dts | |||
@@ -70,7 +70,7 @@ | |||
70 | 70 | ||
71 | &mmc1 { | 71 | &mmc1 { |
72 | vmmc-supply = <&vmmc>; | 72 | vmmc-supply = <&vmmc>; |
73 | ti,bus-width = <8>; | 73 | bus-width = <8>; |
74 | }; | 74 | }; |
75 | 75 | ||
76 | &mmc2 { | 76 | &mmc2 { |
@@ -87,5 +87,5 @@ | |||
87 | 87 | ||
88 | &mmc5 { | 88 | &mmc5 { |
89 | ti,non-removable; | 89 | ti,non-removable; |
90 | ti,bus-width = <4>; | 90 | bus-width = <4>; |
91 | }; | 91 | }; |
diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts index e5eeb6f9c6e6..d08c4d137280 100644 --- a/arch/arm/boot/dts/omap4-sdp.dts +++ b/arch/arm/boot/dts/omap4-sdp.dts | |||
@@ -137,12 +137,12 @@ | |||
137 | 137 | ||
138 | &mmc1 { | 138 | &mmc1 { |
139 | vmmc-supply = <&vmmc>; | 139 | vmmc-supply = <&vmmc>; |
140 | ti,bus-width = <8>; | 140 | bus-width = <8>; |
141 | }; | 141 | }; |
142 | 142 | ||
143 | &mmc2 { | 143 | &mmc2 { |
144 | vmmc-supply = <&vaux1>; | 144 | vmmc-supply = <&vaux1>; |
145 | ti,bus-width = <8>; | 145 | bus-width = <8>; |
146 | ti,non-removable; | 146 | ti,non-removable; |
147 | }; | 147 | }; |
148 | 148 | ||
@@ -155,6 +155,6 @@ | |||
155 | }; | 155 | }; |
156 | 156 | ||
157 | &mmc5 { | 157 | &mmc5 { |
158 | ti,bus-width = <4>; | 158 | bus-width = <4>; |
159 | ti,non-removable; | 159 | ti,non-removable; |
160 | }; | 160 | }; |
diff --git a/arch/arm/boot/dts/tegra-cardhu.dts b/arch/arm/boot/dts/tegra-cardhu.dts index 0a9f34a2c3aa..4a166357172b 100644 --- a/arch/arm/boot/dts/tegra-cardhu.dts +++ b/arch/arm/boot/dts/tegra-cardhu.dts | |||
@@ -51,6 +51,15 @@ | |||
51 | nvidia,pull = <2>; | 51 | nvidia,pull = <2>; |
52 | nvidia,tristate = <0>; | 52 | nvidia,tristate = <0>; |
53 | }; | 53 | }; |
54 | dap2_fs_pa2 { | ||
55 | nvidia,pins = "dap2_fs_pa2", | ||
56 | "dap2_sclk_pa3", | ||
57 | "dap2_din_pa4", | ||
58 | "dap2_dout_pa5"; | ||
59 | nvidia,function = "i2s1"; | ||
60 | nvidia,pull = <0>; | ||
61 | nvidia,tristate = <0>; | ||
62 | }; | ||
54 | }; | 63 | }; |
55 | }; | 64 | }; |
56 | 65 | ||
@@ -92,12 +101,27 @@ | |||
92 | 101 | ||
93 | i2c@7000d000 { | 102 | i2c@7000d000 { |
94 | clock-frequency = <100000>; | 103 | clock-frequency = <100000>; |
104 | |||
105 | wm8903: wm8903@1a { | ||
106 | compatible = "wlf,wm8903"; | ||
107 | reg = <0x1a>; | ||
108 | interrupt-parent = <&gpio>; | ||
109 | interrupts = <179 0x04>; /* gpio PW3 */ | ||
110 | |||
111 | gpio-controller; | ||
112 | #gpio-cells = <2>; | ||
113 | |||
114 | micdet-cfg = <0>; | ||
115 | micdet-delay = <100>; | ||
116 | gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>; | ||
117 | }; | ||
95 | }; | 118 | }; |
96 | 119 | ||
97 | sdhci@78000000 { | 120 | sdhci@78000000 { |
98 | cd-gpios = <&gpio 69 0>; /* gpio PI5 */ | 121 | cd-gpios = <&gpio 69 0>; /* gpio PI5 */ |
99 | wp-gpios = <&gpio 155 0>; /* gpio PT3 */ | 122 | wp-gpios = <&gpio 155 0>; /* gpio PT3 */ |
100 | power-gpios = <&gpio 31 0>; /* gpio PD7 */ | 123 | power-gpios = <&gpio 31 0>; /* gpio PD7 */ |
124 | bus-width = <4>; | ||
101 | }; | 125 | }; |
102 | 126 | ||
103 | sdhci@78000200 { | 127 | sdhci@78000200 { |
@@ -110,5 +134,46 @@ | |||
110 | 134 | ||
111 | sdhci@78000400 { | 135 | sdhci@78000400 { |
112 | support-8bit; | 136 | support-8bit; |
137 | bus-width = <8>; | ||
138 | }; | ||
139 | |||
140 | ahub@70080000 { | ||
141 | i2s@70080300 { | ||
142 | status = "disable"; | ||
143 | }; | ||
144 | |||
145 | i2s@70080500 { | ||
146 | status = "disable"; | ||
147 | }; | ||
148 | |||
149 | i2s@70080600 { | ||
150 | status = "disable"; | ||
151 | }; | ||
152 | |||
153 | i2s@70080700 { | ||
154 | status = "disable"; | ||
155 | }; | ||
156 | }; | ||
157 | |||
158 | sound { | ||
159 | compatible = "nvidia,tegra-audio-wm8903-cardhu", | ||
160 | "nvidia,tegra-audio-wm8903"; | ||
161 | nvidia,model = "NVIDIA Tegra Cardhu"; | ||
162 | |||
163 | nvidia,audio-routing = | ||
164 | "Headphone Jack", "HPOUTR", | ||
165 | "Headphone Jack", "HPOUTL", | ||
166 | "Int Spk", "ROP", | ||
167 | "Int Spk", "RON", | ||
168 | "Int Spk", "LOP", | ||
169 | "Int Spk", "LON", | ||
170 | "Mic Jack", "MICBIAS", | ||
171 | "IN1L", "Mic Jack"; | ||
172 | |||
173 | nvidia,i2s-controller = <&tegra_i2s1>; | ||
174 | nvidia,audio-codec = <&wm8903>; | ||
175 | |||
176 | nvidia,spkr-en-gpios = <&wm8903 2 0>; | ||
177 | nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */ | ||
113 | }; | 178 | }; |
114 | }; | 179 | }; |
diff --git a/arch/arm/boot/dts/tegra-harmony.dts b/arch/arm/boot/dts/tegra-harmony.dts index 1a0b1f182944..7cd513ac5ea6 100644 --- a/arch/arm/boot/dts/tegra-harmony.dts +++ b/arch/arm/boot/dts/tegra-harmony.dts | |||
@@ -167,28 +167,28 @@ | |||
167 | }; | 167 | }; |
168 | conf_ata { | 168 | conf_ata { |
169 | nvidia,pins = "ata", "atb", "atc", "atd", "ate", | 169 | nvidia,pins = "ata", "atb", "atc", "atd", "ate", |
170 | "cdev1", "dap1", "dtb", "gma", "gmb", | 170 | "cdev1", "cdev2", "dap1", "dtb", "gma", |
171 | "gmc", "gmd", "gme", "gpu7", "gpv", | 171 | "gmb", "gmc", "gmd", "gme", "gpu7", |
172 | "i2cp", "pta", "rm", "slxa", "slxk", | 172 | "gpv", "i2cp", "pta", "rm", "slxa", |
173 | "spia", "spib"; | 173 | "slxk", "spia", "spib", "uac"; |
174 | nvidia,pull = <0>; | 174 | nvidia,pull = <0>; |
175 | nvidia,tristate = <0>; | 175 | nvidia,tristate = <0>; |
176 | }; | 176 | }; |
177 | conf_cdev2 { | ||
178 | nvidia,pins = "cdev2", "csus", "spid", "spif"; | ||
179 | nvidia,pull = <1>; | ||
180 | nvidia,tristate = <1>; | ||
181 | }; | ||
182 | conf_ck32 { | 177 | conf_ck32 { |
183 | nvidia,pins = "ck32", "ddrc", "pmca", "pmcb", | 178 | nvidia,pins = "ck32", "ddrc", "pmca", "pmcb", |
184 | "pmcc", "pmcd", "pmce", "xm2c", "xm2d"; | 179 | "pmcc", "pmcd", "pmce", "xm2c", "xm2d"; |
185 | nvidia,pull = <0>; | 180 | nvidia,pull = <0>; |
186 | }; | 181 | }; |
182 | conf_csus { | ||
183 | nvidia,pins = "csus", "spid", "spif"; | ||
184 | nvidia,pull = <1>; | ||
185 | nvidia,tristate = <1>; | ||
186 | }; | ||
187 | conf_crtp { | 187 | conf_crtp { |
188 | nvidia,pins = "crtp", "dap2", "dap3", "dap4", | 188 | nvidia,pins = "crtp", "dap2", "dap3", "dap4", |
189 | "dtc", "dte", "dtf", "gpu", "sdio1", | 189 | "dtc", "dte", "dtf", "gpu", "sdio1", |
190 | "slxc", "slxd", "spdi", "spdo", "spig", | 190 | "slxc", "slxd", "spdi", "spdo", "spig", |
191 | "uac", "uda"; | 191 | "uda"; |
192 | nvidia,pull = <0>; | 192 | nvidia,pull = <0>; |
193 | nvidia,tristate = <1>; | 193 | nvidia,tristate = <1>; |
194 | }; | 194 | }; |
@@ -324,6 +324,7 @@ | |||
324 | cd-gpios = <&gpio 69 0>; /* gpio PI5 */ | 324 | cd-gpios = <&gpio 69 0>; /* gpio PI5 */ |
325 | wp-gpios = <&gpio 57 0>; /* gpio PH1 */ | 325 | wp-gpios = <&gpio 57 0>; /* gpio PH1 */ |
326 | power-gpios = <&gpio 155 0>; /* gpio PT3 */ | 326 | power-gpios = <&gpio 155 0>; /* gpio PT3 */ |
327 | bus-width = <4>; | ||
327 | }; | 328 | }; |
328 | 329 | ||
329 | sdhci@c8000400 { | 330 | sdhci@c8000400 { |
@@ -335,5 +336,10 @@ | |||
335 | wp-gpios = <&gpio 59 0>; /* gpio PH3 */ | 336 | wp-gpios = <&gpio 59 0>; /* gpio PH3 */ |
336 | power-gpios = <&gpio 70 0>; /* gpio PI6 */ | 337 | power-gpios = <&gpio 70 0>; /* gpio PI6 */ |
337 | support-8bit; | 338 | support-8bit; |
339 | bus-width = <8>; | ||
340 | }; | ||
341 | |||
342 | usb@c5004000 { | ||
343 | nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ | ||
338 | }; | 344 | }; |
339 | }; | 345 | }; |
diff --git a/arch/arm/boot/dts/tegra-paz00.dts b/arch/arm/boot/dts/tegra-paz00.dts index 10943fb2561c..8d625e4c5de5 100644 --- a/arch/arm/boot/dts/tegra-paz00.dts +++ b/arch/arm/boot/dts/tegra-paz00.dts | |||
@@ -159,18 +159,14 @@ | |||
159 | }; | 159 | }; |
160 | conf_ata { | 160 | conf_ata { |
161 | nvidia,pins = "ata", "atb", "atc", "atd", "ate", | 161 | nvidia,pins = "ata", "atb", "atc", "atd", "ate", |
162 | "cdev1", "dap1", "dap2", "dtf", "gma", | 162 | "cdev1", "cdev2", "dap1", "dap2", "dtf", |
163 | "gmb", "gmc", "gmd", "gme", "gpu", | 163 | "gma", "gmb", "gmc", "gmd", "gme", |
164 | "gpu7", "gpv", "i2cp", "pta", "rm", | 164 | "gpu", "gpu7", "gpv", "i2cp", "pta", |
165 | "sdio1", "slxk", "spdo", "uac", "uda"; | 165 | "rm", "sdio1", "slxk", "spdo", "uac", |
166 | "uda"; | ||
166 | nvidia,pull = <0>; | 167 | nvidia,pull = <0>; |
167 | nvidia,tristate = <0>; | 168 | nvidia,tristate = <0>; |
168 | }; | 169 | }; |
169 | conf_cdev2 { | ||
170 | nvidia,pins = "cdev2"; | ||
171 | nvidia,pull = <1>; | ||
172 | nvidia,tristate = <0>; | ||
173 | }; | ||
174 | conf_ck32 { | 170 | conf_ck32 { |
175 | nvidia,pins = "ck32", "ddrc", "pmca", "pmcb", | 171 | nvidia,pins = "ck32", "ddrc", "pmca", "pmcb", |
176 | "pmcc", "pmcd", "pmce", "xm2c", "xm2d"; | 172 | "pmcc", "pmcd", "pmce", "xm2c", "xm2d"; |
@@ -317,6 +313,7 @@ | |||
317 | cd-gpios = <&gpio 173 0>; /* gpio PV5 */ | 313 | cd-gpios = <&gpio 173 0>; /* gpio PV5 */ |
318 | wp-gpios = <&gpio 57 0>; /* gpio PH1 */ | 314 | wp-gpios = <&gpio 57 0>; /* gpio PH1 */ |
319 | power-gpios = <&gpio 169 0>; /* gpio PV1 */ | 315 | power-gpios = <&gpio 169 0>; /* gpio PV1 */ |
316 | bus-width = <4>; | ||
320 | }; | 317 | }; |
321 | 318 | ||
322 | sdhci@c8000200 { | 319 | sdhci@c8000200 { |
@@ -329,6 +326,7 @@ | |||
329 | 326 | ||
330 | sdhci@c8000600 { | 327 | sdhci@c8000600 { |
331 | support-8bit; | 328 | support-8bit; |
329 | bus-width = <8>; | ||
332 | }; | 330 | }; |
333 | 331 | ||
334 | gpio-keys { | 332 | gpio-keys { |
@@ -351,4 +349,8 @@ | |||
351 | linux,default-trigger = "rfkill0"; | 349 | linux,default-trigger = "rfkill0"; |
352 | }; | 350 | }; |
353 | }; | 351 | }; |
352 | |||
353 | usb@c5004000 { | ||
354 | nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */ | ||
355 | }; | ||
354 | }; | 356 | }; |
diff --git a/arch/arm/boot/dts/tegra-seaboard.dts b/arch/arm/boot/dts/tegra-seaboard.dts index ec33116f5df9..315971993cfd 100644 --- a/arch/arm/boot/dts/tegra-seaboard.dts +++ b/arch/arm/boot/dts/tegra-seaboard.dts | |||
@@ -347,10 +347,12 @@ | |||
347 | cd-gpios = <&gpio 69 0>; /* gpio PI5 */ | 347 | cd-gpios = <&gpio 69 0>; /* gpio PI5 */ |
348 | wp-gpios = <&gpio 57 0>; /* gpio PH1 */ | 348 | wp-gpios = <&gpio 57 0>; /* gpio PH1 */ |
349 | power-gpios = <&gpio 70 0>; /* gpio PI6 */ | 349 | power-gpios = <&gpio 70 0>; /* gpio PI6 */ |
350 | bus-width = <4>; | ||
350 | }; | 351 | }; |
351 | 352 | ||
352 | sdhci@c8000600 { | 353 | sdhci@c8000600 { |
353 | support-8bit; | 354 | support-8bit; |
355 | bus-width = <8>; | ||
354 | }; | 356 | }; |
355 | 357 | ||
356 | usb@c5000000 { | 358 | usb@c5000000 { |
@@ -415,4 +417,8 @@ | |||
415 | 0x00000000 0x00000000 0x00000000 0x00000000 >; | 417 | 0x00000000 0x00000000 0x00000000 0x00000000 >; |
416 | }; | 418 | }; |
417 | }; | 419 | }; |
420 | |||
421 | usb@c5004000 { | ||
422 | nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ | ||
423 | }; | ||
418 | }; | 424 | }; |
diff --git a/arch/arm/boot/dts/tegra-trimslice.dts b/arch/arm/boot/dts/tegra-trimslice.dts index 98efd5b0d7f9..e4fcf9a8178a 100644 --- a/arch/arm/boot/dts/tegra-trimslice.dts +++ b/arch/arm/boot/dts/tegra-trimslice.dts | |||
@@ -182,23 +182,23 @@ | |||
182 | nvidia,tristate = <1>; | 182 | nvidia,tristate = <1>; |
183 | }; | 183 | }; |
184 | conf_atb { | 184 | conf_atb { |
185 | nvidia,pins = "atb", "cdev1", "dap1", "gma", | 185 | nvidia,pins = "atb", "cdev1", "cdev2", "dap1", |
186 | "gmc", "gmd", "gpu", "gpu7", "gpv", | 186 | "gma", "gmc", "gmd", "gpu", "gpu7", |
187 | "sdio1", "slxa", "slxk", "uac"; | 187 | "gpv", "sdio1", "slxa", "slxk", "uac"; |
188 | nvidia,pull = <0>; | 188 | nvidia,pull = <0>; |
189 | nvidia,tristate = <0>; | 189 | nvidia,tristate = <0>; |
190 | }; | 190 | }; |
191 | conf_cdev2 { | ||
192 | nvidia,pins = "cdev2", "csus", "spia", "spib", | ||
193 | "spid", "spif"; | ||
194 | nvidia,pull = <1>; | ||
195 | nvidia,tristate = <1>; | ||
196 | }; | ||
197 | conf_ck32 { | 191 | conf_ck32 { |
198 | nvidia,pins = "ck32", "ddrc", "pmca", "pmcb", | 192 | nvidia,pins = "ck32", "ddrc", "pmca", "pmcb", |
199 | "pmcc", "pmcd", "pmce", "xm2c", "xm2d"; | 193 | "pmcc", "pmcd", "pmce", "xm2c", "xm2d"; |
200 | nvidia,pull = <0>; | 194 | nvidia,pull = <0>; |
201 | }; | 195 | }; |
196 | conf_csus { | ||
197 | nvidia,pins = "csus", "spia", "spib", | ||
198 | "spid", "spif"; | ||
199 | nvidia,pull = <1>; | ||
200 | nvidia,tristate = <1>; | ||
201 | }; | ||
202 | conf_ddc { | 202 | conf_ddc { |
203 | nvidia,pins = "ddc", "dtf", "rm", "sdc", "sdd"; | 203 | nvidia,pins = "ddc", "dtf", "rm", "sdc", "sdd"; |
204 | nvidia,pull = <2>; | 204 | nvidia,pull = <2>; |
@@ -304,4 +304,8 @@ | |||
304 | cd-gpios = <&gpio 121 0>; | 304 | cd-gpios = <&gpio 121 0>; |
305 | wp-gpios = <&gpio 122 0>; | 305 | wp-gpios = <&gpio 122 0>; |
306 | }; | 306 | }; |
307 | |||
308 | usb@c5004000 { | ||
309 | nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */ | ||
310 | }; | ||
307 | }; | 311 | }; |
diff --git a/arch/arm/boot/dts/tegra-ventana.dts b/arch/arm/boot/dts/tegra-ventana.dts index 71eb2e50a668..b922a26747e7 100644 --- a/arch/arm/boot/dts/tegra-ventana.dts +++ b/arch/arm/boot/dts/tegra-ventana.dts | |||
@@ -330,9 +330,15 @@ | |||
330 | cd-gpios = <&gpio 69 0>; /* gpio PI5 */ | 330 | cd-gpios = <&gpio 69 0>; /* gpio PI5 */ |
331 | wp-gpios = <&gpio 57 0>; /* gpio PH1 */ | 331 | wp-gpios = <&gpio 57 0>; /* gpio PH1 */ |
332 | power-gpios = <&gpio 70 0>; /* gpio PI6 */ | 332 | power-gpios = <&gpio 70 0>; /* gpio PI6 */ |
333 | bus-width = <4>; | ||
333 | }; | 334 | }; |
334 | 335 | ||
335 | sdhci@c8000600 { | 336 | sdhci@c8000600 { |
336 | support-8bit; | 337 | support-8bit; |
338 | bus-width = <8>; | ||
339 | }; | ||
340 | |||
341 | usb@c5004000 { | ||
342 | nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ | ||
337 | }; | 343 | }; |
338 | }; | 344 | }; |
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi index 62a7b39f1c9a..15200a949a81 100644 --- a/arch/arm/boot/dts/tegra30.dtsi +++ b/arch/arm/boot/dts/tegra30.dtsi | |||
@@ -183,4 +183,45 @@ | |||
183 | reg = < 0x70000868 0xd0 /* Pad control registers */ | 183 | reg = < 0x70000868 0xd0 /* Pad control registers */ |
184 | 0x70003000 0x3e0 >; /* Mux registers */ | 184 | 0x70003000 0x3e0 >; /* Mux registers */ |
185 | }; | 185 | }; |
186 | |||
187 | ahub { | ||
188 | compatible = "nvidia,tegra30-ahub"; | ||
189 | reg = <0x70080000 0x200 0x70080200 0x100>; | ||
190 | interrupts = < 0 103 0x04 >; | ||
191 | nvidia,dma-request-selector = <&apbdma 1>; | ||
192 | |||
193 | ranges; | ||
194 | #address-cells = <1>; | ||
195 | #size-cells = <1>; | ||
196 | |||
197 | tegra_i2s0: i2s@70080300 { | ||
198 | compatible = "nvidia,tegra30-i2s"; | ||
199 | reg = <0x70080300 0x100>; | ||
200 | nvidia,ahub-cif-ids = <4 4>; | ||
201 | }; | ||
202 | |||
203 | tegra_i2s1: i2s@70080400 { | ||
204 | compatible = "nvidia,tegra30-i2s"; | ||
205 | reg = <0x70080400 0x100>; | ||
206 | nvidia,ahub-cif-ids = <5 5>; | ||
207 | }; | ||
208 | |||
209 | tegra_i2s2: i2s@70080500 { | ||
210 | compatible = "nvidia,tegra30-i2s"; | ||
211 | reg = <0x70080500 0x100>; | ||
212 | nvidia,ahub-cif-ids = <6 6>; | ||
213 | }; | ||
214 | |||
215 | tegra_i2s3: i2s@70080600 { | ||
216 | compatible = "nvidia,tegra30-i2s"; | ||
217 | reg = <0x70080600 0x100>; | ||
218 | nvidia,ahub-cif-ids = <7 7>; | ||
219 | }; | ||
220 | |||
221 | tegra_i2s4: i2s@70080700 { | ||
222 | compatible = "nvidia,tegra30-i2s"; | ||
223 | reg = <0x70080700 0x100>; | ||
224 | nvidia,ahub-cif-ids = <8 8>; | ||
225 | }; | ||
226 | }; | ||
186 | }; | 227 | }; |
diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c index 95ce019c9b98..a685e9706b7b 100644 --- a/arch/arm/mach-davinci/dma.c +++ b/arch/arm/mach-davinci/dma.c | |||
@@ -353,9 +353,10 @@ static int irq2ctlr(int irq) | |||
353 | *****************************************************************************/ | 353 | *****************************************************************************/ |
354 | static irqreturn_t dma_irq_handler(int irq, void *data) | 354 | static irqreturn_t dma_irq_handler(int irq, void *data) |
355 | { | 355 | { |
356 | int i; | ||
357 | int ctlr; | 356 | int ctlr; |
358 | unsigned int cnt = 0; | 357 | u32 sh_ier; |
358 | u32 sh_ipr; | ||
359 | u32 bank; | ||
359 | 360 | ||
360 | ctlr = irq2ctlr(irq); | 361 | ctlr = irq2ctlr(irq); |
361 | if (ctlr < 0) | 362 | if (ctlr < 0) |
@@ -363,41 +364,39 @@ static irqreturn_t dma_irq_handler(int irq, void *data) | |||
363 | 364 | ||
364 | dev_dbg(data, "dma_irq_handler\n"); | 365 | dev_dbg(data, "dma_irq_handler\n"); |
365 | 366 | ||
366 | if ((edma_shadow0_read_array(ctlr, SH_IPR, 0) == 0) && | 367 | sh_ipr = edma_shadow0_read_array(ctlr, SH_IPR, 0); |
367 | (edma_shadow0_read_array(ctlr, SH_IPR, 1) == 0)) | 368 | if (!sh_ipr) { |
368 | return IRQ_NONE; | 369 | sh_ipr = edma_shadow0_read_array(ctlr, SH_IPR, 1); |
370 | if (!sh_ipr) | ||
371 | return IRQ_NONE; | ||
372 | sh_ier = edma_shadow0_read_array(ctlr, SH_IER, 1); | ||
373 | bank = 1; | ||
374 | } else { | ||
375 | sh_ier = edma_shadow0_read_array(ctlr, SH_IER, 0); | ||
376 | bank = 0; | ||
377 | } | ||
369 | 378 | ||
370 | while (1) { | 379 | do { |
371 | int j; | 380 | u32 slot; |
372 | if (edma_shadow0_read_array(ctlr, SH_IPR, 0) & | 381 | u32 channel; |
373 | edma_shadow0_read_array(ctlr, SH_IER, 0)) | 382 | |
374 | j = 0; | 383 | dev_dbg(data, "IPR%d %08x\n", bank, sh_ipr); |
375 | else if (edma_shadow0_read_array(ctlr, SH_IPR, 1) & | 384 | |
376 | edma_shadow0_read_array(ctlr, SH_IER, 1)) | 385 | slot = __ffs(sh_ipr); |
377 | j = 1; | 386 | sh_ipr &= ~(BIT(slot)); |
378 | else | 387 | |
379 | break; | 388 | if (sh_ier & BIT(slot)) { |
380 | dev_dbg(data, "IPR%d %08x\n", j, | 389 | channel = (bank << 5) | slot; |
381 | edma_shadow0_read_array(ctlr, SH_IPR, j)); | 390 | /* Clear the corresponding IPR bits */ |
382 | for (i = 0; i < 32; i++) { | 391 | edma_shadow0_write_array(ctlr, SH_ICR, bank, |
383 | int k = (j << 5) + i; | 392 | BIT(slot)); |
384 | if ((edma_shadow0_read_array(ctlr, SH_IPR, j) & BIT(i)) | 393 | if (edma_cc[ctlr]->intr_data[channel].callback) |
385 | && (edma_shadow0_read_array(ctlr, | 394 | edma_cc[ctlr]->intr_data[channel].callback( |
386 | SH_IER, j) & BIT(i))) { | 395 | channel, DMA_COMPLETE, |
387 | /* Clear the corresponding IPR bits */ | 396 | edma_cc[ctlr]->intr_data[channel].data); |
388 | edma_shadow0_write_array(ctlr, SH_ICR, j, | ||
389 | BIT(i)); | ||
390 | if (edma_cc[ctlr]->intr_data[k].callback) | ||
391 | edma_cc[ctlr]->intr_data[k].callback( | ||
392 | k, DMA_COMPLETE, | ||
393 | edma_cc[ctlr]->intr_data[k]. | ||
394 | data); | ||
395 | } | ||
396 | } | 397 | } |
397 | cnt++; | 398 | } while (sh_ipr); |
398 | if (cnt > 10) | 399 | |
399 | break; | ||
400 | } | ||
401 | edma_shadow0_write(ctlr, SH_IEVAL, 1); | 400 | edma_shadow0_write(ctlr, SH_IEVAL, 1); |
402 | return IRQ_HANDLED; | 401 | return IRQ_HANDLED; |
403 | } | 402 | } |
diff --git a/arch/arm/mach-davinci/include/mach/debug-macro.S b/arch/arm/mach-davinci/include/mach/debug-macro.S index cf94552d5274..34290d14754b 100644 --- a/arch/arm/mach-davinci/include/mach/debug-macro.S +++ b/arch/arm/mach-davinci/include/mach/debug-macro.S | |||
@@ -22,46 +22,28 @@ | |||
22 | 22 | ||
23 | #define UART_SHIFT 2 | 23 | #define UART_SHIFT 2 |
24 | 24 | ||
25 | .pushsection .data | 25 | #if defined(CONFIG_DEBUG_DAVINCI_DMx_UART0) |
26 | davinci_uart_phys: .word 0 | 26 | #define UART_BASE DAVINCI_UART0_BASE |
27 | davinci_uart_virt: .word 0 | 27 | #elif defined(CONFIG_DEBUG_DAVINCI_DA8XX_UART0) |
28 | .popsection | 28 | #define UART_BASE DA8XX_UART0_BASE |
29 | 29 | #elif defined(CONFIG_DEBUG_DAVINCI_DA8XX_UART1) | |
30 | .macro addruart, rp, rv, tmp | 30 | #define UART_BASE DA8XX_UART1_BASE |
31 | 31 | #elif defined(CONFIG_DEBUG_DAVINCI_DA8XX_UART2) | |
32 | /* Use davinci_uart_phys/virt if already configured */ | 32 | #define UART_BASE DA8XX_UART2_BASE |
33 | 10: adr \rp, 99f @ get effective addr of 99f | 33 | #elif defined(CONFIG_DEBUG_DAVINCI_TNETV107X_UART1) |
34 | ldr \rv, [\rp] @ get absolute addr of 99f | 34 | #define UART_BASE TNETV107X_UART2_BASE |
35 | sub \rv, \rv, \rp @ offset between the two | 35 | #define UART_VIRTBASE TNETV107X_UART2_VIRT |
36 | ldr \rp, [\rp, #4] @ abs addr of omap_uart_phys | 36 | #else |
37 | sub \tmp, \rp, \rv @ make it effective | 37 | #error "Select a specifc port for DEBUG_LL" |
38 | ldr \rp, [\tmp, #0] @ davinci_uart_phys | 38 | #endif |
39 | ldr \rv, [\tmp, #4] @ davinci_uart_virt | ||
40 | cmp \rp, #0 @ is port configured? | ||
41 | cmpne \rv, #0 | ||
42 | bne 100f @ already configured | ||
43 | |||
44 | /* Check the debug UART address set in uncompress.h */ | ||
45 | and \rp, pc, #0xff000000 | ||
46 | ldr \rv, =DAVINCI_UART_INFO_OFS | ||
47 | add \rp, \rp, \rv | ||
48 | |||
49 | /* Copy uart phys address from decompressor uart info */ | ||
50 | ldr \rv, [\rp, #0] | ||
51 | str \rv, [\tmp, #0] | ||
52 | |||
53 | /* Copy uart virt address from decompressor uart info */ | ||
54 | ldr \rv, [\rp, #4] | ||
55 | str \rv, [\tmp, #4] | ||
56 | |||
57 | b 10b | ||
58 | 39 | ||
59 | .align | 40 | #ifndef UART_VIRTBASE |
60 | 99: .word . | 41 | #define UART_VIRTBASE IO_ADDRESS(UART_BASE) |
61 | .word davinci_uart_phys | 42 | #endif |
62 | .ltorg | ||
63 | 43 | ||
64 | 100: | 44 | .macro addruart, rp, rv, tmp |
45 | ldr \rp, =UART_BASE | ||
46 | ldr \rv, =UART_VIRTBASE | ||
65 | .endm | 47 | .endm |
66 | 48 | ||
67 | .macro senduart,rd,rx | 49 | .macro senduart,rd,rx |
diff --git a/arch/arm/mach-davinci/include/mach/hardware.h b/arch/arm/mach-davinci/include/mach/hardware.h index 2184691ebc2f..16bb42291d39 100644 --- a/arch/arm/mach-davinci/include/mach/hardware.h +++ b/arch/arm/mach-davinci/include/mach/hardware.h | |||
@@ -22,7 +22,7 @@ | |||
22 | /* | 22 | /* |
23 | * I/O mapping | 23 | * I/O mapping |
24 | */ | 24 | */ |
25 | #define IO_PHYS 0x01c00000UL | 25 | #define IO_PHYS UL(0x01c00000) |
26 | #define IO_OFFSET 0xfd000000 /* Virtual IO = 0xfec00000 */ | 26 | #define IO_OFFSET 0xfd000000 /* Virtual IO = 0xfec00000 */ |
27 | #define IO_SIZE 0x00400000 | 27 | #define IO_SIZE 0x00400000 |
28 | #define IO_VIRT (IO_PHYS + IO_OFFSET) | 28 | #define IO_VIRT (IO_PHYS + IO_OFFSET) |
diff --git a/arch/arm/mach-davinci/include/mach/serial.h b/arch/arm/mach-davinci/include/mach/serial.h index e347d88fef91..46b3cd11c3c2 100644 --- a/arch/arm/mach-davinci/include/mach/serial.h +++ b/arch/arm/mach-davinci/include/mach/serial.h | |||
@@ -15,16 +15,6 @@ | |||
15 | 15 | ||
16 | #include <mach/hardware.h> | 16 | #include <mach/hardware.h> |
17 | 17 | ||
18 | /* | ||
19 | * Stolen area that contains debug uart physical and virtual addresses. These | ||
20 | * addresses are filled in by the uncompress.h code, and are used by the debug | ||
21 | * macros in debug-macro.S. | ||
22 | * | ||
23 | * This area sits just below the page tables (see arch/arm/kernel/head.S). | ||
24 | * We define it as a relative offset from start of usable RAM. | ||
25 | */ | ||
26 | #define DAVINCI_UART_INFO_OFS 0x3ff8 | ||
27 | |||
28 | #define DAVINCI_UART0_BASE (IO_PHYS + 0x20000) | 18 | #define DAVINCI_UART0_BASE (IO_PHYS + 0x20000) |
29 | #define DAVINCI_UART1_BASE (IO_PHYS + 0x20400) | 19 | #define DAVINCI_UART1_BASE (IO_PHYS + 0x20400) |
30 | #define DAVINCI_UART2_BASE (IO_PHYS + 0x20800) | 20 | #define DAVINCI_UART2_BASE (IO_PHYS + 0x20800) |
diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h b/arch/arm/mach-davinci/include/mach/uncompress.h index da2fb2c2155a..18cfd4977155 100644 --- a/arch/arm/mach-davinci/include/mach/uncompress.h +++ b/arch/arm/mach-davinci/include/mach/uncompress.h | |||
@@ -43,37 +43,27 @@ static inline void flush(void) | |||
43 | barrier(); | 43 | barrier(); |
44 | } | 44 | } |
45 | 45 | ||
46 | static inline void set_uart_info(u32 phys, void * __iomem virt) | 46 | static inline void set_uart_info(u32 phys) |
47 | { | 47 | { |
48 | /* | ||
49 | * Get address of some.bss variable and round it down | ||
50 | * a la CONFIG_AUTO_ZRELADDR. | ||
51 | */ | ||
52 | u32 ram_start = (u32)&uart & 0xf8000000; | ||
53 | u32 *uart_info = (u32 *)(ram_start + DAVINCI_UART_INFO_OFS); | ||
54 | |||
55 | uart = (u32 *)phys; | 48 | uart = (u32 *)phys; |
56 | uart_info[0] = phys; | ||
57 | uart_info[1] = (u32)virt; | ||
58 | } | 49 | } |
59 | 50 | ||
60 | #define _DEBUG_LL_ENTRY(machine, phys, virt) \ | 51 | #define _DEBUG_LL_ENTRY(machine, phys) \ |
61 | if (machine_is_##machine()) { \ | 52 | { \ |
62 | set_uart_info(phys, virt); \ | 53 | if (machine_is_##machine()) { \ |
63 | break; \ | 54 | set_uart_info(phys); \ |
55 | break; \ | ||
56 | } \ | ||
64 | } | 57 | } |
65 | 58 | ||
66 | #define DEBUG_LL_DAVINCI(machine, port) \ | 59 | #define DEBUG_LL_DAVINCI(machine, port) \ |
67 | _DEBUG_LL_ENTRY(machine, DAVINCI_UART##port##_BASE, \ | 60 | _DEBUG_LL_ENTRY(machine, DAVINCI_UART##port##_BASE) |
68 | IO_ADDRESS(DAVINCI_UART##port##_BASE)) | ||
69 | 61 | ||
70 | #define DEBUG_LL_DA8XX(machine, port) \ | 62 | #define DEBUG_LL_DA8XX(machine, port) \ |
71 | _DEBUG_LL_ENTRY(machine, DA8XX_UART##port##_BASE, \ | 63 | _DEBUG_LL_ENTRY(machine, DA8XX_UART##port##_BASE) |
72 | IO_ADDRESS(DA8XX_UART##port##_BASE)) | ||
73 | 64 | ||
74 | #define DEBUG_LL_TNETV107X(machine, port) \ | 65 | #define DEBUG_LL_TNETV107X(machine, port) \ |
75 | _DEBUG_LL_ENTRY(machine, TNETV107X_UART##port##_BASE, \ | 66 | _DEBUG_LL_ENTRY(machine, TNETV107X_UART##port##_BASE) |
76 | TNETV107X_UART##port##_VIRT) | ||
77 | 67 | ||
78 | static inline void __arch_decomp_setup(unsigned long arch_id) | 68 | static inline void __arch_decomp_setup(unsigned long arch_id) |
79 | { | 69 | { |
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 66b1494f23a6..ad1a91ab6acd 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c | |||
@@ -675,7 +675,7 @@ int ep93xx_keypad_acquire_gpio(struct platform_device *pdev) | |||
675 | fail_gpio_d: | 675 | fail_gpio_d: |
676 | gpio_free(EP93XX_GPIO_LINE_C(i)); | 676 | gpio_free(EP93XX_GPIO_LINE_C(i)); |
677 | fail_gpio_c: | 677 | fail_gpio_c: |
678 | for ( ; i >= 0; --i) { | 678 | for (--i; i >= 0; --i) { |
679 | gpio_free(EP93XX_GPIO_LINE_C(i)); | 679 | gpio_free(EP93XX_GPIO_LINE_C(i)); |
680 | gpio_free(EP93XX_GPIO_LINE_D(i)); | 680 | gpio_free(EP93XX_GPIO_LINE_D(i)); |
681 | } | 681 | } |
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 15b05b89cc39..e3cfd5fd7dd5 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig | |||
@@ -85,10 +85,10 @@ config EXYNOS4_SETUP_FIMD0 | |||
85 | help | 85 | help |
86 | Common setup code for FIMD0. | 86 | Common setup code for FIMD0. |
87 | 87 | ||
88 | config EXYNOS4_DEV_SYSMMU | 88 | config EXYNOS_DEV_SYSMMU |
89 | bool | 89 | bool |
90 | help | 90 | help |
91 | Common setup code for SYSTEM MMU in EXYNOS4 | 91 | Common setup code for SYSTEM MMU in EXYNOS platforms |
92 | 92 | ||
93 | config EXYNOS4_DEV_DWMCI | 93 | config EXYNOS4_DEV_DWMCI |
94 | bool | 94 | bool |
@@ -201,12 +201,12 @@ config MACH_SMDKV310 | |||
201 | select S3C_DEV_HSMMC3 | 201 | select S3C_DEV_HSMMC3 |
202 | select SAMSUNG_DEV_BACKLIGHT | 202 | select SAMSUNG_DEV_BACKLIGHT |
203 | select EXYNOS_DEV_DRM | 203 | select EXYNOS_DEV_DRM |
204 | select EXYNOS_DEV_SYSMMU | ||
204 | select EXYNOS4_DEV_AHCI | 205 | select EXYNOS4_DEV_AHCI |
205 | select SAMSUNG_DEV_KEYPAD | 206 | select SAMSUNG_DEV_KEYPAD |
206 | select EXYNOS4_DEV_DMA | 207 | select EXYNOS4_DEV_DMA |
207 | select SAMSUNG_DEV_PWM | 208 | select SAMSUNG_DEV_PWM |
208 | select EXYNOS4_DEV_USB_OHCI | 209 | select EXYNOS4_DEV_USB_OHCI |
209 | select EXYNOS4_DEV_SYSMMU | ||
210 | select EXYNOS4_SETUP_FIMD0 | 210 | select EXYNOS4_SETUP_FIMD0 |
211 | select EXYNOS4_SETUP_I2C1 | 211 | select EXYNOS4_SETUP_I2C1 |
212 | select EXYNOS4_SETUP_KEYPAD | 212 | select EXYNOS4_SETUP_KEYPAD |
@@ -225,7 +225,6 @@ config MACH_ARMLEX4210 | |||
225 | select S3C_DEV_HSMMC3 | 225 | select S3C_DEV_HSMMC3 |
226 | select EXYNOS4_DEV_AHCI | 226 | select EXYNOS4_DEV_AHCI |
227 | select EXYNOS4_DEV_DMA | 227 | select EXYNOS4_DEV_DMA |
228 | select EXYNOS4_DEV_SYSMMU | ||
229 | select EXYNOS4_SETUP_SDHCI | 228 | select EXYNOS4_SETUP_SDHCI |
230 | help | 229 | help |
231 | Machine support for Samsung ARMLEX4210 based on EXYNOS4210 | 230 | Machine support for Samsung ARMLEX4210 based on EXYNOS4210 |
@@ -256,6 +255,7 @@ config MACH_UNIVERSAL_C210 | |||
256 | select S5P_DEV_MFC | 255 | select S5P_DEV_MFC |
257 | select S5P_DEV_ONENAND | 256 | select S5P_DEV_ONENAND |
258 | select S5P_DEV_TV | 257 | select S5P_DEV_TV |
258 | select EXYNOS_DEV_SYSMMU | ||
259 | select EXYNOS4_DEV_DMA | 259 | select EXYNOS4_DEV_DMA |
260 | select EXYNOS_DEV_DRM | 260 | select EXYNOS_DEV_DRM |
261 | select EXYNOS4_SETUP_FIMD0 | 261 | select EXYNOS4_SETUP_FIMD0 |
@@ -332,6 +332,7 @@ config MACH_ORIGEN | |||
332 | select SAMSUNG_DEV_BACKLIGHT | 332 | select SAMSUNG_DEV_BACKLIGHT |
333 | select SAMSUNG_DEV_PWM | 333 | select SAMSUNG_DEV_PWM |
334 | select EXYNOS_DEV_DRM | 334 | select EXYNOS_DEV_DRM |
335 | select EXYNOS_DEV_SYSMMU | ||
335 | select EXYNOS4_DEV_DMA | 336 | select EXYNOS4_DEV_DMA |
336 | select EXYNOS4_DEV_USB_OHCI | 337 | select EXYNOS4_DEV_USB_OHCI |
337 | select EXYNOS4_SETUP_FIMD0 | 338 | select EXYNOS4_SETUP_FIMD0 |
@@ -360,6 +361,7 @@ config MACH_SMDK4212 | |||
360 | select SAMSUNG_DEV_BACKLIGHT | 361 | select SAMSUNG_DEV_BACKLIGHT |
361 | select SAMSUNG_DEV_KEYPAD | 362 | select SAMSUNG_DEV_KEYPAD |
362 | select SAMSUNG_DEV_PWM | 363 | select SAMSUNG_DEV_PWM |
364 | select EXYNOS_DEV_SYSMMU | ||
363 | select EXYNOS4_DEV_DMA | 365 | select EXYNOS4_DEV_DMA |
364 | select EXYNOS4_SETUP_I2C1 | 366 | select EXYNOS4_SETUP_I2C1 |
365 | select EXYNOS4_SETUP_I2C3 | 367 | select EXYNOS4_SETUP_I2C3 |
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index 8631840d1b5e..272625231c73 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile | |||
@@ -50,7 +50,7 @@ obj-$(CONFIG_MACH_EXYNOS5_DT) += mach-exynos5-dt.o | |||
50 | obj-y += dev-uart.o | 50 | obj-y += dev-uart.o |
51 | obj-$(CONFIG_ARCH_EXYNOS4) += dev-audio.o | 51 | 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_EXYNOS4_DEV_SYSMMU) += dev-sysmmu.o | 53 | obj-$(CONFIG_EXYNOS_DEV_SYSMMU) += dev-sysmmu.o |
54 | obj-$(CONFIG_EXYNOS4_DEV_DWMCI) += dev-dwmci.o | 54 | obj-$(CONFIG_EXYNOS4_DEV_DWMCI) += dev-dwmci.o |
55 | obj-$(CONFIG_EXYNOS4_DEV_DMA) += dma.o | 55 | obj-$(CONFIG_EXYNOS4_DEV_DMA) += dma.o |
56 | obj-$(CONFIG_EXYNOS4_DEV_USB_OHCI) += dev-ohci.o | 56 | obj-$(CONFIG_EXYNOS4_DEV_USB_OHCI) += dev-ohci.o |
diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c index 6efd1e5919fd..bcb7db453145 100644 --- a/arch/arm/mach-exynos/clock-exynos4.c +++ b/arch/arm/mach-exynos/clock-exynos4.c | |||
@@ -168,7 +168,7 @@ static int exynos4_clk_ip_tv_ctrl(struct clk *clk, int enable) | |||
168 | return s5p_gatectrl(EXYNOS4_CLKGATE_IP_TV, clk, enable); | 168 | return s5p_gatectrl(EXYNOS4_CLKGATE_IP_TV, clk, enable); |
169 | } | 169 | } |
170 | 170 | ||
171 | static int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable) | 171 | int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable) |
172 | { | 172 | { |
173 | return s5p_gatectrl(EXYNOS4_CLKGATE_IP_IMAGE, clk, enable); | 173 | return s5p_gatectrl(EXYNOS4_CLKGATE_IP_IMAGE, clk, enable); |
174 | } | 174 | } |
@@ -198,6 +198,11 @@ static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable) | |||
198 | return s5p_gatectrl(EXYNOS4_CLKGATE_IP_PERIR, clk, enable); | 198 | return s5p_gatectrl(EXYNOS4_CLKGATE_IP_PERIR, clk, enable); |
199 | } | 199 | } |
200 | 200 | ||
201 | int exynos4_clk_ip_dmc_ctrl(struct clk *clk, int enable) | ||
202 | { | ||
203 | return s5p_gatectrl(EXYNOS4_CLKGATE_IP_DMC, clk, enable); | ||
204 | } | ||
205 | |||
201 | static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable) | 206 | static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable) |
202 | { | 207 | { |
203 | return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable); | 208 | return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable); |
@@ -678,61 +683,55 @@ static struct clk exynos4_init_clocks_off[] = { | |||
678 | .enable = exynos4_clk_ip_peril_ctrl, | 683 | .enable = exynos4_clk_ip_peril_ctrl, |
679 | .ctrlbit = (1 << 14), | 684 | .ctrlbit = (1 << 14), |
680 | }, { | 685 | }, { |
681 | .name = "SYSMMU_MDMA", | 686 | .name = SYSMMU_CLOCK_NAME, |
687 | .devname = SYSMMU_CLOCK_DEVNAME(mfc_l, 0), | ||
688 | .enable = exynos4_clk_ip_mfc_ctrl, | ||
689 | .ctrlbit = (1 << 1), | ||
690 | }, { | ||
691 | .name = SYSMMU_CLOCK_NAME, | ||
692 | .devname = SYSMMU_CLOCK_DEVNAME(mfc_r, 1), | ||
693 | .enable = exynos4_clk_ip_mfc_ctrl, | ||
694 | .ctrlbit = (1 << 2), | ||
695 | }, { | ||
696 | .name = SYSMMU_CLOCK_NAME, | ||
697 | .devname = SYSMMU_CLOCK_DEVNAME(tv, 2), | ||
698 | .enable = exynos4_clk_ip_tv_ctrl, | ||
699 | .ctrlbit = (1 << 4), | ||
700 | }, { | ||
701 | .name = SYSMMU_CLOCK_NAME, | ||
702 | .devname = SYSMMU_CLOCK_DEVNAME(jpeg, 3), | ||
703 | .enable = exynos4_clk_ip_cam_ctrl, | ||
704 | .ctrlbit = (1 << 11), | ||
705 | }, { | ||
706 | .name = SYSMMU_CLOCK_NAME, | ||
707 | .devname = SYSMMU_CLOCK_DEVNAME(rot, 4), | ||
682 | .enable = exynos4_clk_ip_image_ctrl, | 708 | .enable = exynos4_clk_ip_image_ctrl, |
683 | .ctrlbit = (1 << 5), | 709 | .ctrlbit = (1 << 4), |
684 | }, { | 710 | }, { |
685 | .name = "SYSMMU_FIMC0", | 711 | .name = SYSMMU_CLOCK_NAME, |
712 | .devname = SYSMMU_CLOCK_DEVNAME(fimc0, 5), | ||
686 | .enable = exynos4_clk_ip_cam_ctrl, | 713 | .enable = exynos4_clk_ip_cam_ctrl, |
687 | .ctrlbit = (1 << 7), | 714 | .ctrlbit = (1 << 7), |
688 | }, { | 715 | }, { |
689 | .name = "SYSMMU_FIMC1", | 716 | .name = SYSMMU_CLOCK_NAME, |
717 | .devname = SYSMMU_CLOCK_DEVNAME(fimc1, 6), | ||
690 | .enable = exynos4_clk_ip_cam_ctrl, | 718 | .enable = exynos4_clk_ip_cam_ctrl, |
691 | .ctrlbit = (1 << 8), | 719 | .ctrlbit = (1 << 8), |
692 | }, { | 720 | }, { |
693 | .name = "SYSMMU_FIMC2", | 721 | .name = SYSMMU_CLOCK_NAME, |
722 | .devname = SYSMMU_CLOCK_DEVNAME(fimc2, 7), | ||
694 | .enable = exynos4_clk_ip_cam_ctrl, | 723 | .enable = exynos4_clk_ip_cam_ctrl, |
695 | .ctrlbit = (1 << 9), | 724 | .ctrlbit = (1 << 9), |
696 | }, { | 725 | }, { |
697 | .name = "SYSMMU_FIMC3", | 726 | .name = SYSMMU_CLOCK_NAME, |
727 | .devname = SYSMMU_CLOCK_DEVNAME(fimc3, 8), | ||
698 | .enable = exynos4_clk_ip_cam_ctrl, | 728 | .enable = exynos4_clk_ip_cam_ctrl, |
699 | .ctrlbit = (1 << 10), | 729 | .ctrlbit = (1 << 10), |
700 | }, { | 730 | }, { |
701 | .name = "SYSMMU_JPEG", | 731 | .name = SYSMMU_CLOCK_NAME, |
702 | .enable = exynos4_clk_ip_cam_ctrl, | 732 | .devname = SYSMMU_CLOCK_DEVNAME(fimd0, 10), |
703 | .ctrlbit = (1 << 11), | ||
704 | }, { | ||
705 | .name = "SYSMMU_FIMD0", | ||
706 | .enable = exynos4_clk_ip_lcd0_ctrl, | 733 | .enable = exynos4_clk_ip_lcd0_ctrl, |
707 | .ctrlbit = (1 << 4), | 734 | .ctrlbit = (1 << 4), |
708 | }, { | ||
709 | .name = "SYSMMU_FIMD1", | ||
710 | .enable = exynos4_clk_ip_lcd1_ctrl, | ||
711 | .ctrlbit = (1 << 4), | ||
712 | }, { | ||
713 | .name = "SYSMMU_PCIe", | ||
714 | .enable = exynos4_clk_ip_fsys_ctrl, | ||
715 | .ctrlbit = (1 << 18), | ||
716 | }, { | ||
717 | .name = "SYSMMU_G2D", | ||
718 | .enable = exynos4_clk_ip_image_ctrl, | ||
719 | .ctrlbit = (1 << 3), | ||
720 | }, { | ||
721 | .name = "SYSMMU_ROTATOR", | ||
722 | .enable = exynos4_clk_ip_image_ctrl, | ||
723 | .ctrlbit = (1 << 4), | ||
724 | }, { | ||
725 | .name = "SYSMMU_TV", | ||
726 | .enable = exynos4_clk_ip_tv_ctrl, | ||
727 | .ctrlbit = (1 << 4), | ||
728 | }, { | ||
729 | .name = "SYSMMU_MFC_L", | ||
730 | .enable = exynos4_clk_ip_mfc_ctrl, | ||
731 | .ctrlbit = (1 << 1), | ||
732 | }, { | ||
733 | .name = "SYSMMU_MFC_R", | ||
734 | .enable = exynos4_clk_ip_mfc_ctrl, | ||
735 | .ctrlbit = (1 << 2), | ||
736 | } | 735 | } |
737 | }; | 736 | }; |
738 | 737 | ||
diff --git a/arch/arm/mach-exynos/clock-exynos4.h b/arch/arm/mach-exynos/clock-exynos4.h index cb71c29c14d1..28a119701182 100644 --- a/arch/arm/mach-exynos/clock-exynos4.h +++ b/arch/arm/mach-exynos/clock-exynos4.h | |||
@@ -26,5 +26,7 @@ extern struct clk *exynos4_clkset_group_list[]; | |||
26 | extern int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable); | 26 | extern int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable); |
27 | extern int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable); | 27 | extern int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable); |
28 | extern int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable); | 28 | extern int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable); |
29 | extern int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable); | ||
30 | extern int exynos4_clk_ip_dmc_ctrl(struct clk *clk, int enable); | ||
29 | 31 | ||
30 | #endif /* __ASM_ARCH_CLOCK_H */ | 32 | #endif /* __ASM_ARCH_CLOCK_H */ |
diff --git a/arch/arm/mach-exynos/clock-exynos4210.c b/arch/arm/mach-exynos/clock-exynos4210.c index 3b131e4b6ef5..b8689ff60baf 100644 --- a/arch/arm/mach-exynos/clock-exynos4210.c +++ b/arch/arm/mach-exynos/clock-exynos4210.c | |||
@@ -26,6 +26,7 @@ | |||
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> | ||
29 | 30 | ||
30 | #include "common.h" | 31 | #include "common.h" |
31 | #include "clock-exynos4.h" | 32 | #include "clock-exynos4.h" |
@@ -94,6 +95,16 @@ static struct clk init_clocks_off[] = { | |||
94 | .devname = "exynos4-fb.1", | 95 | .devname = "exynos4-fb.1", |
95 | .enable = exynos4_clk_ip_lcd1_ctrl, | 96 | .enable = exynos4_clk_ip_lcd1_ctrl, |
96 | .ctrlbit = (1 << 0), | 97 | .ctrlbit = (1 << 0), |
98 | }, { | ||
99 | .name = SYSMMU_CLOCK_NAME, | ||
100 | .devname = SYSMMU_CLOCK_DEVNAME(2d, 14), | ||
101 | .enable = exynos4_clk_ip_image_ctrl, | ||
102 | .ctrlbit = (1 << 3), | ||
103 | }, { | ||
104 | .name = SYSMMU_CLOCK_NAME, | ||
105 | .devname = SYSMMU_CLOCK_DEVNAME(fimd1, 11), | ||
106 | .enable = exynos4_clk_ip_lcd1_ctrl, | ||
107 | .ctrlbit = (1 << 4), | ||
97 | }, | 108 | }, |
98 | }; | 109 | }; |
99 | 110 | ||
diff --git a/arch/arm/mach-exynos/clock-exynos4212.c b/arch/arm/mach-exynos/clock-exynos4212.c index 3ecc01e06f74..98823120570e 100644 --- a/arch/arm/mach-exynos/clock-exynos4212.c +++ b/arch/arm/mach-exynos/clock-exynos4212.c | |||
@@ -26,6 +26,7 @@ | |||
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> | ||
29 | 30 | ||
30 | #include "common.h" | 31 | #include "common.h" |
31 | #include "clock-exynos4.h" | 32 | #include "clock-exynos4.h" |
@@ -39,6 +40,16 @@ static struct sleep_save exynos4212_clock_save[] = { | |||
39 | }; | 40 | }; |
40 | #endif | 41 | #endif |
41 | 42 | ||
43 | static int exynos4212_clk_ip_isp0_ctrl(struct clk *clk, int enable) | ||
44 | { | ||
45 | return s5p_gatectrl(EXYNOS4_CLKGATE_IP_ISP0, clk, enable); | ||
46 | } | ||
47 | |||
48 | static int exynos4212_clk_ip_isp1_ctrl(struct clk *clk, int enable) | ||
49 | { | ||
50 | return s5p_gatectrl(EXYNOS4_CLKGATE_IP_ISP1, clk, enable); | ||
51 | } | ||
52 | |||
42 | static struct clk *clk_src_mpll_user_list[] = { | 53 | static struct clk *clk_src_mpll_user_list[] = { |
43 | [0] = &clk_fin_mpll, | 54 | [0] = &clk_fin_mpll, |
44 | [1] = &exynos4_clk_mout_mpll.clk, | 55 | [1] = &exynos4_clk_mout_mpll.clk, |
@@ -66,7 +77,22 @@ static struct clksrc_clk clksrcs[] = { | |||
66 | }; | 77 | }; |
67 | 78 | ||
68 | static struct clk init_clocks_off[] = { | 79 | static struct clk init_clocks_off[] = { |
69 | /* nothing here yet */ | 80 | { |
81 | .name = SYSMMU_CLOCK_NAME, | ||
82 | .devname = SYSMMU_CLOCK_DEVNAME(2d, 14), | ||
83 | .enable = exynos4_clk_ip_dmc_ctrl, | ||
84 | .ctrlbit = (1 << 24), | ||
85 | }, { | ||
86 | .name = SYSMMU_CLOCK_NAME, | ||
87 | .devname = SYSMMU_CLOCK_DEVNAME(isp, 9), | ||
88 | .enable = exynos4212_clk_ip_isp0_ctrl, | ||
89 | .ctrlbit = (7 << 8), | ||
90 | }, { | ||
91 | .name = SYSMMU_CLOCK_NAME2, | ||
92 | .devname = SYSMMU_CLOCK_DEVNAME(isp, 9), | ||
93 | .enable = exynos4212_clk_ip_isp1_ctrl, | ||
94 | .ctrlbit = (1 << 4), | ||
95 | } | ||
70 | }; | 96 | }; |
71 | 97 | ||
72 | #ifdef CONFIG_PM_SLEEP | 98 | #ifdef CONFIG_PM_SLEEP |
diff --git a/arch/arm/mach-exynos/clock-exynos5.c b/arch/arm/mach-exynos/clock-exynos5.c index 7ac6ff4c46bd..9f87a07b0bf8 100644 --- a/arch/arm/mach-exynos/clock-exynos5.c +++ b/arch/arm/mach-exynos/clock-exynos5.c | |||
@@ -82,6 +82,11 @@ static int exynos5_clksrc_mask_peric0_ctrl(struct clk *clk, int enable) | |||
82 | return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_PERIC0, clk, enable); | 82 | return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_PERIC0, clk, enable); |
83 | } | 83 | } |
84 | 84 | ||
85 | static int exynos5_clk_ip_acp_ctrl(struct clk *clk, int enable) | ||
86 | { | ||
87 | return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ACP, clk, enable); | ||
88 | } | ||
89 | |||
85 | static int exynos5_clk_ip_core_ctrl(struct clk *clk, int enable) | 90 | static int exynos5_clk_ip_core_ctrl(struct clk *clk, int enable) |
86 | { | 91 | { |
87 | return s5p_gatectrl(EXYNOS5_CLKGATE_IP_CORE, clk, enable); | 92 | return s5p_gatectrl(EXYNOS5_CLKGATE_IP_CORE, clk, enable); |
@@ -127,6 +132,21 @@ static int exynos5_clk_ip_peris_ctrl(struct clk *clk, int enable) | |||
127 | return s5p_gatectrl(EXYNOS5_CLKGATE_IP_PERIS, clk, enable); | 132 | return s5p_gatectrl(EXYNOS5_CLKGATE_IP_PERIS, clk, enable); |
128 | } | 133 | } |
129 | 134 | ||
135 | static int exynos5_clk_ip_gscl_ctrl(struct clk *clk, int enable) | ||
136 | { | ||
137 | return s5p_gatectrl(EXYNOS5_CLKGATE_IP_GSCL, clk, enable); | ||
138 | } | ||
139 | |||
140 | static int exynos5_clk_ip_isp0_ctrl(struct clk *clk, int enable) | ||
141 | { | ||
142 | return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ISP0, clk, enable); | ||
143 | } | ||
144 | |||
145 | static int exynos5_clk_ip_isp1_ctrl(struct clk *clk, int enable) | ||
146 | { | ||
147 | return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ISP1, clk, enable); | ||
148 | } | ||
149 | |||
130 | /* Core list of CMU_CPU side */ | 150 | /* Core list of CMU_CPU side */ |
131 | 151 | ||
132 | static struct clksrc_clk exynos5_clk_mout_apll = { | 152 | static struct clksrc_clk exynos5_clk_mout_apll = { |
@@ -630,6 +650,76 @@ static struct clk exynos5_init_clocks_off[] = { | |||
630 | .parent = &exynos5_clk_aclk_66.clk, | 650 | .parent = &exynos5_clk_aclk_66.clk, |
631 | .enable = exynos5_clk_ip_peric_ctrl, | 651 | .enable = exynos5_clk_ip_peric_ctrl, |
632 | .ctrlbit = (1 << 14), | 652 | .ctrlbit = (1 << 14), |
653 | }, { | ||
654 | .name = SYSMMU_CLOCK_NAME, | ||
655 | .devname = SYSMMU_CLOCK_DEVNAME(mfc_l, 0), | ||
656 | .enable = &exynos5_clk_ip_mfc_ctrl, | ||
657 | .ctrlbit = (1 << 1), | ||
658 | }, { | ||
659 | .name = SYSMMU_CLOCK_NAME, | ||
660 | .devname = SYSMMU_CLOCK_DEVNAME(mfc_r, 1), | ||
661 | .enable = &exynos5_clk_ip_mfc_ctrl, | ||
662 | .ctrlbit = (1 << 2), | ||
663 | }, { | ||
664 | .name = SYSMMU_CLOCK_NAME, | ||
665 | .devname = SYSMMU_CLOCK_DEVNAME(tv, 2), | ||
666 | .enable = &exynos5_clk_ip_disp1_ctrl, | ||
667 | .ctrlbit = (1 << 9) | ||
668 | }, { | ||
669 | .name = SYSMMU_CLOCK_NAME, | ||
670 | .devname = SYSMMU_CLOCK_DEVNAME(jpeg, 3), | ||
671 | .enable = &exynos5_clk_ip_gen_ctrl, | ||
672 | .ctrlbit = (1 << 7), | ||
673 | }, { | ||
674 | .name = SYSMMU_CLOCK_NAME, | ||
675 | .devname = SYSMMU_CLOCK_DEVNAME(rot, 4), | ||
676 | .enable = &exynos5_clk_ip_gen_ctrl, | ||
677 | .ctrlbit = (1 << 6) | ||
678 | }, { | ||
679 | .name = SYSMMU_CLOCK_NAME, | ||
680 | .devname = SYSMMU_CLOCK_DEVNAME(gsc0, 5), | ||
681 | .enable = &exynos5_clk_ip_gscl_ctrl, | ||
682 | .ctrlbit = (1 << 7), | ||
683 | }, { | ||
684 | .name = SYSMMU_CLOCK_NAME, | ||
685 | .devname = SYSMMU_CLOCK_DEVNAME(gsc1, 6), | ||
686 | .enable = &exynos5_clk_ip_gscl_ctrl, | ||
687 | .ctrlbit = (1 << 8), | ||
688 | }, { | ||
689 | .name = SYSMMU_CLOCK_NAME, | ||
690 | .devname = SYSMMU_CLOCK_DEVNAME(gsc2, 7), | ||
691 | .enable = &exynos5_clk_ip_gscl_ctrl, | ||
692 | .ctrlbit = (1 << 9), | ||
693 | }, { | ||
694 | .name = SYSMMU_CLOCK_NAME, | ||
695 | .devname = SYSMMU_CLOCK_DEVNAME(gsc3, 8), | ||
696 | .enable = &exynos5_clk_ip_gscl_ctrl, | ||
697 | .ctrlbit = (1 << 10), | ||
698 | }, { | ||
699 | .name = SYSMMU_CLOCK_NAME, | ||
700 | .devname = SYSMMU_CLOCK_DEVNAME(isp, 9), | ||
701 | .enable = &exynos5_clk_ip_isp0_ctrl, | ||
702 | .ctrlbit = (0x3F << 8), | ||
703 | }, { | ||
704 | .name = SYSMMU_CLOCK_NAME2, | ||
705 | .devname = SYSMMU_CLOCK_DEVNAME(isp, 9), | ||
706 | .enable = &exynos5_clk_ip_isp1_ctrl, | ||
707 | .ctrlbit = (0xF << 4), | ||
708 | }, { | ||
709 | .name = SYSMMU_CLOCK_NAME, | ||
710 | .devname = SYSMMU_CLOCK_DEVNAME(camif0, 12), | ||
711 | .enable = &exynos5_clk_ip_gscl_ctrl, | ||
712 | .ctrlbit = (1 << 11), | ||
713 | }, { | ||
714 | .name = SYSMMU_CLOCK_NAME, | ||
715 | .devname = SYSMMU_CLOCK_DEVNAME(camif1, 13), | ||
716 | .enable = &exynos5_clk_ip_gscl_ctrl, | ||
717 | .ctrlbit = (1 << 12), | ||
718 | }, { | ||
719 | .name = SYSMMU_CLOCK_NAME, | ||
720 | .devname = SYSMMU_CLOCK_DEVNAME(2d, 14), | ||
721 | .enable = &exynos5_clk_ip_acp_ctrl, | ||
722 | .ctrlbit = (1 << 7) | ||
633 | } | 723 | } |
634 | }; | 724 | }; |
635 | 725 | ||
diff --git a/arch/arm/mach-exynos/dev-sysmmu.c b/arch/arm/mach-exynos/dev-sysmmu.c index 781563fcb156..c5b1ea301df0 100644 --- a/arch/arm/mach-exynos/dev-sysmmu.c +++ b/arch/arm/mach-exynos/dev-sysmmu.c | |||
@@ -1,9 +1,9 @@ | |||
1 | /* linux/arch/arm/mach-exynos4/dev-sysmmu.c | 1 | /* linux/arch/arm/mach-exynos/dev-sysmmu.c |
2 | * | 2 | * |
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | 3 | * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd. |
4 | * http://www.samsung.com | 4 | * http://www.samsung.com |
5 | * | 5 | * |
6 | * EXYNOS4 - System MMU support | 6 | * EXYNOS - System MMU support |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 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 | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -12,222 +12,263 @@ | |||
12 | 12 | ||
13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
14 | #include <linux/dma-mapping.h> | 14 | #include <linux/dma-mapping.h> |
15 | #include <linux/export.h> | 15 | |
16 | #include <plat/cpu.h> | ||
16 | 17 | ||
17 | #include <mach/map.h> | 18 | #include <mach/map.h> |
18 | #include <mach/irqs.h> | 19 | #include <mach/irqs.h> |
19 | #include <mach/sysmmu.h> | 20 | #include <mach/sysmmu.h> |
20 | #include <plat/s5p-clock.h> | ||
21 | |||
22 | /* These names must be equal to the clock names in mach-exynos4/clock.c */ | ||
23 | const char *sysmmu_ips_name[EXYNOS4_SYSMMU_TOTAL_IPNUM] = { | ||
24 | "SYSMMU_MDMA" , | ||
25 | "SYSMMU_SSS" , | ||
26 | "SYSMMU_FIMC0" , | ||
27 | "SYSMMU_FIMC1" , | ||
28 | "SYSMMU_FIMC2" , | ||
29 | "SYSMMU_FIMC3" , | ||
30 | "SYSMMU_JPEG" , | ||
31 | "SYSMMU_FIMD0" , | ||
32 | "SYSMMU_FIMD1" , | ||
33 | "SYSMMU_PCIe" , | ||
34 | "SYSMMU_G2D" , | ||
35 | "SYSMMU_ROTATOR", | ||
36 | "SYSMMU_MDMA2" , | ||
37 | "SYSMMU_TV" , | ||
38 | "SYSMMU_MFC_L" , | ||
39 | "SYSMMU_MFC_R" , | ||
40 | }; | ||
41 | 21 | ||
42 | static struct resource exynos4_sysmmu_resource[] = { | 22 | static u64 exynos_sysmmu_dma_mask = DMA_BIT_MASK(32); |
43 | [0] = { | 23 | |
44 | .start = EXYNOS4_PA_SYSMMU_MDMA, | 24 | #define SYSMMU_PLATFORM_DEVICE(ipname, devid) \ |
45 | .end = EXYNOS4_PA_SYSMMU_MDMA + SZ_64K - 1, | 25 | static struct sysmmu_platform_data platdata_##ipname = { \ |
46 | .flags = IORESOURCE_MEM, | 26 | .dbgname = #ipname, \ |
47 | }, | 27 | }; \ |
48 | [1] = { | 28 | struct platform_device SYSMMU_PLATDEV(ipname) = \ |
49 | .start = IRQ_SYSMMU_MDMA0_0, | 29 | { \ |
50 | .end = IRQ_SYSMMU_MDMA0_0, | 30 | .name = SYSMMU_DEVNAME_BASE, \ |
51 | .flags = IORESOURCE_IRQ, | 31 | .id = devid, \ |
52 | }, | 32 | .dev = { \ |
53 | [2] = { | 33 | .dma_mask = &exynos_sysmmu_dma_mask, \ |
54 | .start = EXYNOS4_PA_SYSMMU_SSS, | 34 | .coherent_dma_mask = DMA_BIT_MASK(32), \ |
55 | .end = EXYNOS4_PA_SYSMMU_SSS + SZ_64K - 1, | 35 | .platform_data = &platdata_##ipname, \ |
56 | .flags = IORESOURCE_MEM, | 36 | }, \ |
57 | }, | 37 | } |
58 | [3] = { | 38 | |
59 | .start = IRQ_SYSMMU_SSS_0, | 39 | SYSMMU_PLATFORM_DEVICE(mfc_l, 0); |
60 | .end = IRQ_SYSMMU_SSS_0, | 40 | SYSMMU_PLATFORM_DEVICE(mfc_r, 1); |
61 | .flags = IORESOURCE_IRQ, | 41 | SYSMMU_PLATFORM_DEVICE(tv, 2); |
62 | }, | 42 | SYSMMU_PLATFORM_DEVICE(jpeg, 3); |
63 | [4] = { | 43 | SYSMMU_PLATFORM_DEVICE(rot, 4); |
64 | .start = EXYNOS4_PA_SYSMMU_FIMC0, | 44 | SYSMMU_PLATFORM_DEVICE(fimc0, 5); /* fimc* and gsc* exist exclusively */ |
65 | .end = EXYNOS4_PA_SYSMMU_FIMC0 + SZ_64K - 1, | 45 | SYSMMU_PLATFORM_DEVICE(fimc1, 6); |
66 | .flags = IORESOURCE_MEM, | 46 | SYSMMU_PLATFORM_DEVICE(fimc2, 7); |
67 | }, | 47 | SYSMMU_PLATFORM_DEVICE(fimc3, 8); |
68 | [5] = { | 48 | SYSMMU_PLATFORM_DEVICE(gsc0, 5); |
69 | .start = IRQ_SYSMMU_FIMC0_0, | 49 | SYSMMU_PLATFORM_DEVICE(gsc1, 6); |
70 | .end = IRQ_SYSMMU_FIMC0_0, | 50 | SYSMMU_PLATFORM_DEVICE(gsc2, 7); |
71 | .flags = IORESOURCE_IRQ, | 51 | SYSMMU_PLATFORM_DEVICE(gsc3, 8); |
72 | }, | 52 | SYSMMU_PLATFORM_DEVICE(isp, 9); |
73 | [6] = { | 53 | SYSMMU_PLATFORM_DEVICE(fimd0, 10); |
74 | .start = EXYNOS4_PA_SYSMMU_FIMC1, | 54 | SYSMMU_PLATFORM_DEVICE(fimd1, 11); |
75 | .end = EXYNOS4_PA_SYSMMU_FIMC1 + SZ_64K - 1, | 55 | SYSMMU_PLATFORM_DEVICE(camif0, 12); |
76 | .flags = IORESOURCE_MEM, | 56 | SYSMMU_PLATFORM_DEVICE(camif1, 13); |
77 | }, | 57 | SYSMMU_PLATFORM_DEVICE(2d, 14); |
78 | [7] = { | 58 | |
79 | .start = IRQ_SYSMMU_FIMC1_0, | 59 | #define SYSMMU_RESOURCE_NAME(core, ipname) sysmmures_##core##_##ipname |
80 | .end = IRQ_SYSMMU_FIMC1_0, | 60 | |
81 | .flags = IORESOURCE_IRQ, | 61 | #define SYSMMU_RESOURCE(core, ipname) \ |
82 | }, | 62 | static struct resource SYSMMU_RESOURCE_NAME(core, ipname)[] __initdata = |
83 | [8] = { | 63 | |
84 | .start = EXYNOS4_PA_SYSMMU_FIMC2, | 64 | #define DEFINE_SYSMMU_RESOURCE(core, mem, irq) \ |
85 | .end = EXYNOS4_PA_SYSMMU_FIMC2 + SZ_64K - 1, | 65 | DEFINE_RES_MEM_NAMED(core##_PA_SYSMMU_##mem, SZ_4K, #mem), \ |
86 | .flags = IORESOURCE_MEM, | 66 | DEFINE_RES_IRQ_NAMED(core##_IRQ_SYSMMU_##irq##_0, #mem) |
87 | }, | 67 | |
88 | [9] = { | 68 | #define SYSMMU_RESOURCE_DEFINE(core, ipname, mem, irq) \ |
89 | .start = IRQ_SYSMMU_FIMC2_0, | 69 | SYSMMU_RESOURCE(core, ipname) { \ |
90 | .end = IRQ_SYSMMU_FIMC2_0, | 70 | DEFINE_SYSMMU_RESOURCE(core, mem, irq) \ |
91 | .flags = IORESOURCE_IRQ, | 71 | } |
92 | }, | ||
93 | [10] = { | ||
94 | .start = EXYNOS4_PA_SYSMMU_FIMC3, | ||
95 | .end = EXYNOS4_PA_SYSMMU_FIMC3 + SZ_64K - 1, | ||
96 | .flags = IORESOURCE_MEM, | ||
97 | }, | ||
98 | [11] = { | ||
99 | .start = IRQ_SYSMMU_FIMC3_0, | ||
100 | .end = IRQ_SYSMMU_FIMC3_0, | ||
101 | .flags = IORESOURCE_IRQ, | ||
102 | }, | ||
103 | [12] = { | ||
104 | .start = EXYNOS4_PA_SYSMMU_JPEG, | ||
105 | .end = EXYNOS4_PA_SYSMMU_JPEG + SZ_64K - 1, | ||
106 | .flags = IORESOURCE_MEM, | ||
107 | }, | ||
108 | [13] = { | ||
109 | .start = IRQ_SYSMMU_JPEG_0, | ||
110 | .end = IRQ_SYSMMU_JPEG_0, | ||
111 | .flags = IORESOURCE_IRQ, | ||
112 | }, | ||
113 | [14] = { | ||
114 | .start = EXYNOS4_PA_SYSMMU_FIMD0, | ||
115 | .end = EXYNOS4_PA_SYSMMU_FIMD0 + SZ_64K - 1, | ||
116 | .flags = IORESOURCE_MEM, | ||
117 | }, | ||
118 | [15] = { | ||
119 | .start = IRQ_SYSMMU_LCD0_M0_0, | ||
120 | .end = IRQ_SYSMMU_LCD0_M0_0, | ||
121 | .flags = IORESOURCE_IRQ, | ||
122 | }, | ||
123 | [16] = { | ||
124 | .start = EXYNOS4_PA_SYSMMU_FIMD1, | ||
125 | .end = EXYNOS4_PA_SYSMMU_FIMD1 + SZ_64K - 1, | ||
126 | .flags = IORESOURCE_MEM, | ||
127 | }, | ||
128 | [17] = { | ||
129 | .start = IRQ_SYSMMU_LCD1_M1_0, | ||
130 | .end = IRQ_SYSMMU_LCD1_M1_0, | ||
131 | .flags = IORESOURCE_IRQ, | ||
132 | }, | ||
133 | [18] = { | ||
134 | .start = EXYNOS4_PA_SYSMMU_PCIe, | ||
135 | .end = EXYNOS4_PA_SYSMMU_PCIe + SZ_64K - 1, | ||
136 | .flags = IORESOURCE_MEM, | ||
137 | }, | ||
138 | [19] = { | ||
139 | .start = IRQ_SYSMMU_PCIE_0, | ||
140 | .end = IRQ_SYSMMU_PCIE_0, | ||
141 | .flags = IORESOURCE_IRQ, | ||
142 | }, | ||
143 | [20] = { | ||
144 | .start = EXYNOS4_PA_SYSMMU_G2D, | ||
145 | .end = EXYNOS4_PA_SYSMMU_G2D + SZ_64K - 1, | ||
146 | .flags = IORESOURCE_MEM, | ||
147 | }, | ||
148 | [21] = { | ||
149 | .start = IRQ_SYSMMU_2D_0, | ||
150 | .end = IRQ_SYSMMU_2D_0, | ||
151 | .flags = IORESOURCE_IRQ, | ||
152 | }, | ||
153 | [22] = { | ||
154 | .start = EXYNOS4_PA_SYSMMU_ROTATOR, | ||
155 | .end = EXYNOS4_PA_SYSMMU_ROTATOR + SZ_64K - 1, | ||
156 | .flags = IORESOURCE_MEM, | ||
157 | }, | ||
158 | [23] = { | ||
159 | .start = IRQ_SYSMMU_ROTATOR_0, | ||
160 | .end = IRQ_SYSMMU_ROTATOR_0, | ||
161 | .flags = IORESOURCE_IRQ, | ||
162 | }, | ||
163 | [24] = { | ||
164 | .start = EXYNOS4_PA_SYSMMU_MDMA2, | ||
165 | .end = EXYNOS4_PA_SYSMMU_MDMA2 + SZ_64K - 1, | ||
166 | .flags = IORESOURCE_MEM, | ||
167 | }, | ||
168 | [25] = { | ||
169 | .start = IRQ_SYSMMU_MDMA1_0, | ||
170 | .end = IRQ_SYSMMU_MDMA1_0, | ||
171 | .flags = IORESOURCE_IRQ, | ||
172 | }, | ||
173 | [26] = { | ||
174 | .start = EXYNOS4_PA_SYSMMU_TV, | ||
175 | .end = EXYNOS4_PA_SYSMMU_TV + SZ_64K - 1, | ||
176 | .flags = IORESOURCE_MEM, | ||
177 | }, | ||
178 | [27] = { | ||
179 | .start = IRQ_SYSMMU_TV_M0_0, | ||
180 | .end = IRQ_SYSMMU_TV_M0_0, | ||
181 | .flags = IORESOURCE_IRQ, | ||
182 | }, | ||
183 | [28] = { | ||
184 | .start = EXYNOS4_PA_SYSMMU_MFC_L, | ||
185 | .end = EXYNOS4_PA_SYSMMU_MFC_L + SZ_64K - 1, | ||
186 | .flags = IORESOURCE_MEM, | ||
187 | }, | ||
188 | [29] = { | ||
189 | .start = IRQ_SYSMMU_MFC_M0_0, | ||
190 | .end = IRQ_SYSMMU_MFC_M0_0, | ||
191 | .flags = IORESOURCE_IRQ, | ||
192 | }, | ||
193 | [30] = { | ||
194 | .start = EXYNOS4_PA_SYSMMU_MFC_R, | ||
195 | .end = EXYNOS4_PA_SYSMMU_MFC_R + SZ_64K - 1, | ||
196 | .flags = IORESOURCE_MEM, | ||
197 | }, | ||
198 | [31] = { | ||
199 | .start = IRQ_SYSMMU_MFC_M1_0, | ||
200 | .end = IRQ_SYSMMU_MFC_M1_0, | ||
201 | .flags = IORESOURCE_IRQ, | ||
202 | }, | ||
203 | }; | ||
204 | 72 | ||
205 | struct platform_device exynos4_device_sysmmu = { | 73 | struct sysmmu_resource_map { |
206 | .name = "s5p-sysmmu", | 74 | struct platform_device *pdev; |
207 | .id = 32, | 75 | struct resource *res; |
208 | .num_resources = ARRAY_SIZE(exynos4_sysmmu_resource), | 76 | u32 rnum; |
209 | .resource = exynos4_sysmmu_resource, | 77 | struct device *pdd; |
78 | char *clocknames; | ||
210 | }; | 79 | }; |
211 | EXPORT_SYMBOL(exynos4_device_sysmmu); | ||
212 | 80 | ||
213 | static struct clk *sysmmu_clk[S5P_SYSMMU_TOTAL_IPNUM]; | 81 | #define SYSMMU_RESOURCE_MAPPING(core, ipname, resname) { \ |
214 | void sysmmu_clk_init(struct device *dev, sysmmu_ips ips) | 82 | .pdev = &SYSMMU_PLATDEV(ipname), \ |
215 | { | 83 | .res = SYSMMU_RESOURCE_NAME(EXYNOS##core, resname), \ |
216 | sysmmu_clk[ips] = clk_get(dev, sysmmu_ips_name[ips]); | 84 | .rnum = ARRAY_SIZE(SYSMMU_RESOURCE_NAME(EXYNOS##core, resname)),\ |
217 | if (IS_ERR(sysmmu_clk[ips])) | 85 | .clocknames = SYSMMU_CLOCK_NAME, \ |
218 | sysmmu_clk[ips] = NULL; | ||
219 | else | ||
220 | clk_put(sysmmu_clk[ips]); | ||
221 | } | 86 | } |
222 | 87 | ||
223 | void sysmmu_clk_enable(sysmmu_ips ips) | 88 | #define SYSMMU_RESOURCE_MAPPING_MC(core, ipname, resname, pdata) { \ |
224 | { | 89 | .pdev = &SYSMMU_PLATDEV(ipname), \ |
225 | if (sysmmu_clk[ips]) | 90 | .res = SYSMMU_RESOURCE_NAME(EXYNOS##core, resname), \ |
226 | clk_enable(sysmmu_clk[ips]); | 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, \ | ||
227 | } | 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 */ | ||
228 | 167 | ||
229 | void sysmmu_clk_disable(sysmmu_ips ips) | 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) | ||
230 | { | 214 | { |
231 | if (sysmmu_clk[ips]) | 215 | int i, j; |
232 | clk_disable(sysmmu_clk[ips]); | 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; | ||
233 | } | 273 | } |
274 | arch_initcall(init_sysmmu_platform_device); | ||
diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h index c02dae7bf4a3..ddde8f3a24d4 100644 --- a/arch/arm/mach-exynos/include/mach/irqs.h +++ b/arch/arm/mach-exynos/include/mach/irqs.h | |||
@@ -154,6 +154,13 @@ | |||
154 | #define EXYNOS4_IRQ_SYSMMU_MFC_M1_0 COMBINER_IRQ(5, 6) | 154 | #define EXYNOS4_IRQ_SYSMMU_MFC_M1_0 COMBINER_IRQ(5, 6) |
155 | #define EXYNOS4_IRQ_SYSMMU_PCIE_0 COMBINER_IRQ(5, 7) | 155 | #define EXYNOS4_IRQ_SYSMMU_PCIE_0 COMBINER_IRQ(5, 7) |
156 | 156 | ||
157 | #define EXYNOS4_IRQ_SYSMMU_FIMC_LITE0_0 COMBINER_IRQ(16, 0) | ||
158 | #define EXYNOS4_IRQ_SYSMMU_FIMC_LITE1_0 COMBINER_IRQ(16, 1) | ||
159 | #define EXYNOS4_IRQ_SYSMMU_FIMC_ISP_0 COMBINER_IRQ(16, 2) | ||
160 | #define EXYNOS4_IRQ_SYSMMU_FIMC_DRC_0 COMBINER_IRQ(16, 3) | ||
161 | #define EXYNOS4_IRQ_SYSMMU_FIMC_FD_0 COMBINER_IRQ(16, 4) | ||
162 | #define EXYNOS4_IRQ_SYSMMU_FIMC_CX_0 COMBINER_IRQ(16, 5) | ||
163 | |||
157 | #define EXYNOS4_IRQ_FIMD0_FIFO COMBINER_IRQ(11, 0) | 164 | #define EXYNOS4_IRQ_FIMD0_FIFO COMBINER_IRQ(11, 0) |
158 | #define EXYNOS4_IRQ_FIMD0_VSYNC COMBINER_IRQ(11, 1) | 165 | #define EXYNOS4_IRQ_FIMD0_VSYNC COMBINER_IRQ(11, 1) |
159 | #define EXYNOS4_IRQ_FIMD0_SYSTEM COMBINER_IRQ(11, 2) | 166 | #define EXYNOS4_IRQ_FIMD0_SYSTEM COMBINER_IRQ(11, 2) |
@@ -221,24 +228,6 @@ | |||
221 | #define IRQ_KEYPAD EXYNOS4_IRQ_KEYPAD | 228 | #define IRQ_KEYPAD EXYNOS4_IRQ_KEYPAD |
222 | #define IRQ_PMU EXYNOS4_IRQ_PMU | 229 | #define IRQ_PMU EXYNOS4_IRQ_PMU |
223 | 230 | ||
224 | #define IRQ_SYSMMU_MDMA0_0 EXYNOS4_IRQ_SYSMMU_MDMA0_0 | ||
225 | #define IRQ_SYSMMU_SSS_0 EXYNOS4_IRQ_SYSMMU_SSS_0 | ||
226 | #define IRQ_SYSMMU_FIMC0_0 EXYNOS4_IRQ_SYSMMU_FIMC0_0 | ||
227 | #define IRQ_SYSMMU_FIMC1_0 EXYNOS4_IRQ_SYSMMU_FIMC1_0 | ||
228 | #define IRQ_SYSMMU_FIMC2_0 EXYNOS4_IRQ_SYSMMU_FIMC2_0 | ||
229 | #define IRQ_SYSMMU_FIMC3_0 EXYNOS4_IRQ_SYSMMU_FIMC3_0 | ||
230 | #define IRQ_SYSMMU_JPEG_0 EXYNOS4_IRQ_SYSMMU_JPEG_0 | ||
231 | #define IRQ_SYSMMU_2D_0 EXYNOS4_IRQ_SYSMMU_2D_0 | ||
232 | |||
233 | #define IRQ_SYSMMU_ROTATOR_0 EXYNOS4_IRQ_SYSMMU_ROTATOR_0 | ||
234 | #define IRQ_SYSMMU_MDMA1_0 EXYNOS4_IRQ_SYSMMU_MDMA1_0 | ||
235 | #define IRQ_SYSMMU_LCD0_M0_0 EXYNOS4_IRQ_SYSMMU_LCD0_M0_0 | ||
236 | #define IRQ_SYSMMU_LCD1_M1_0 EXYNOS4_IRQ_SYSMMU_LCD1_M1_0 | ||
237 | #define IRQ_SYSMMU_TV_M0_0 EXYNOS4_IRQ_SYSMMU_TV_M0_0 | ||
238 | #define IRQ_SYSMMU_MFC_M0_0 EXYNOS4_IRQ_SYSMMU_MFC_M0_0 | ||
239 | #define IRQ_SYSMMU_MFC_M1_0 EXYNOS4_IRQ_SYSMMU_MFC_M1_0 | ||
240 | #define IRQ_SYSMMU_PCIE_0 EXYNOS4_IRQ_SYSMMU_PCIE_0 | ||
241 | |||
242 | #define IRQ_FIMD0_FIFO EXYNOS4_IRQ_FIMD0_FIFO | 231 | #define IRQ_FIMD0_FIFO EXYNOS4_IRQ_FIMD0_FIFO |
243 | #define IRQ_FIMD0_VSYNC EXYNOS4_IRQ_FIMD0_VSYNC | 232 | #define IRQ_FIMD0_VSYNC EXYNOS4_IRQ_FIMD0_VSYNC |
244 | #define IRQ_FIMD0_SYSTEM EXYNOS4_IRQ_FIMD0_SYSTEM | 233 | #define IRQ_FIMD0_SYSTEM EXYNOS4_IRQ_FIMD0_SYSTEM |
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h index e009a66477f4..2196af2d8218 100644 --- a/arch/arm/mach-exynos/include/mach/map.h +++ b/arch/arm/mach-exynos/include/mach/map.h | |||
@@ -95,6 +95,7 @@ | |||
95 | #define EXYNOS5_PA_PDMA1 0x121B0000 | 95 | #define EXYNOS5_PA_PDMA1 0x121B0000 |
96 | 96 | ||
97 | #define EXYNOS4_PA_SYSMMU_MDMA 0x10A40000 | 97 | #define EXYNOS4_PA_SYSMMU_MDMA 0x10A40000 |
98 | #define EXYNOS4_PA_SYSMMU_2D_ACP 0x10A40000 | ||
98 | #define EXYNOS4_PA_SYSMMU_SSS 0x10A50000 | 99 | #define EXYNOS4_PA_SYSMMU_SSS 0x10A50000 |
99 | #define EXYNOS4_PA_SYSMMU_FIMC0 0x11A20000 | 100 | #define EXYNOS4_PA_SYSMMU_FIMC0 0x11A20000 |
100 | #define EXYNOS4_PA_SYSMMU_FIMC1 0x11A30000 | 101 | #define EXYNOS4_PA_SYSMMU_FIMC1 0x11A30000 |
@@ -103,6 +104,12 @@ | |||
103 | #define EXYNOS4_PA_SYSMMU_JPEG 0x11A60000 | 104 | #define EXYNOS4_PA_SYSMMU_JPEG 0x11A60000 |
104 | #define EXYNOS4_PA_SYSMMU_FIMD0 0x11E20000 | 105 | #define EXYNOS4_PA_SYSMMU_FIMD0 0x11E20000 |
105 | #define EXYNOS4_PA_SYSMMU_FIMD1 0x12220000 | 106 | #define EXYNOS4_PA_SYSMMU_FIMD1 0x12220000 |
107 | #define EXYNOS4_PA_SYSMMU_FIMC_ISP 0x12260000 | ||
108 | #define EXYNOS4_PA_SYSMMU_FIMC_DRC 0x12270000 | ||
109 | #define EXYNOS4_PA_SYSMMU_FIMC_FD 0x122A0000 | ||
110 | #define EXYNOS4_PA_SYSMMU_ISPCPU 0x122B0000 | ||
111 | #define EXYNOS4_PA_SYSMMU_FIMC_LITE0 0x123B0000 | ||
112 | #define EXYNOS4_PA_SYSMMU_FIMC_LITE1 0x123C0000 | ||
106 | #define EXYNOS4_PA_SYSMMU_PCIe 0x12620000 | 113 | #define EXYNOS4_PA_SYSMMU_PCIe 0x12620000 |
107 | #define EXYNOS4_PA_SYSMMU_G2D 0x12A20000 | 114 | #define EXYNOS4_PA_SYSMMU_G2D 0x12A20000 |
108 | #define EXYNOS4_PA_SYSMMU_ROTATOR 0x12A30000 | 115 | #define EXYNOS4_PA_SYSMMU_ROTATOR 0x12A30000 |
@@ -110,6 +117,37 @@ | |||
110 | #define EXYNOS4_PA_SYSMMU_TV 0x12E20000 | 117 | #define EXYNOS4_PA_SYSMMU_TV 0x12E20000 |
111 | #define EXYNOS4_PA_SYSMMU_MFC_L 0x13620000 | 118 | #define EXYNOS4_PA_SYSMMU_MFC_L 0x13620000 |
112 | #define EXYNOS4_PA_SYSMMU_MFC_R 0x13630000 | 119 | #define EXYNOS4_PA_SYSMMU_MFC_R 0x13630000 |
120 | |||
121 | #define EXYNOS5_PA_SYSMMU_MDMA1 0x10A40000 | ||
122 | #define EXYNOS5_PA_SYSMMU_SSS 0x10A50000 | ||
123 | #define EXYNOS5_PA_SYSMMU_2D 0x10A60000 | ||
124 | #define EXYNOS5_PA_SYSMMU_MFC_L 0x11200000 | ||
125 | #define EXYNOS5_PA_SYSMMU_MFC_R 0x11210000 | ||
126 | #define EXYNOS5_PA_SYSMMU_ROTATOR 0x11D40000 | ||
127 | #define EXYNOS5_PA_SYSMMU_MDMA2 0x11D50000 | ||
128 | #define EXYNOS5_PA_SYSMMU_JPEG 0x11F20000 | ||
129 | #define EXYNOS5_PA_SYSMMU_IOP 0x12360000 | ||
130 | #define EXYNOS5_PA_SYSMMU_RTIC 0x12370000 | ||
131 | #define EXYNOS5_PA_SYSMMU_GPS 0x12630000 | ||
132 | #define EXYNOS5_PA_SYSMMU_ISP 0x13260000 | ||
133 | #define EXYNOS5_PA_SYSMMU_DRC 0x12370000 | ||
134 | #define EXYNOS5_PA_SYSMMU_SCALERC 0x13280000 | ||
135 | #define EXYNOS5_PA_SYSMMU_SCALERP 0x13290000 | ||
136 | #define EXYNOS5_PA_SYSMMU_FD 0x132A0000 | ||
137 | #define EXYNOS5_PA_SYSMMU_ISPCPU 0x132B0000 | ||
138 | #define EXYNOS5_PA_SYSMMU_ODC 0x132C0000 | ||
139 | #define EXYNOS5_PA_SYSMMU_DIS0 0x132D0000 | ||
140 | #define EXYNOS5_PA_SYSMMU_DIS1 0x132E0000 | ||
141 | #define EXYNOS5_PA_SYSMMU_3DNR 0x132F0000 | ||
142 | #define EXYNOS5_PA_SYSMMU_LITE0 0x13C40000 | ||
143 | #define EXYNOS5_PA_SYSMMU_LITE1 0x13C50000 | ||
144 | #define EXYNOS5_PA_SYSMMU_GSC0 0x13E80000 | ||
145 | #define EXYNOS5_PA_SYSMMU_GSC1 0x13E90000 | ||
146 | #define EXYNOS5_PA_SYSMMU_GSC2 0x13EA0000 | ||
147 | #define EXYNOS5_PA_SYSMMU_GSC3 0x13EB0000 | ||
148 | #define EXYNOS5_PA_SYSMMU_FIMD1 0x14640000 | ||
149 | #define EXYNOS5_PA_SYSMMU_TV 0x14650000 | ||
150 | |||
113 | #define EXYNOS4_PA_SPI0 0x13920000 | 151 | #define EXYNOS4_PA_SPI0 0x13920000 |
114 | #define EXYNOS4_PA_SPI1 0x13930000 | 152 | #define EXYNOS4_PA_SPI1 0x13930000 |
115 | #define EXYNOS4_PA_SPI2 0x13940000 | 153 | #define EXYNOS4_PA_SPI2 0x13940000 |
diff --git a/arch/arm/mach-exynos/include/mach/regs-clock.h b/arch/arm/mach-exynos/include/mach/regs-clock.h index d9578a58ae7f..dba83e91f0fd 100644 --- a/arch/arm/mach-exynos/include/mach/regs-clock.h +++ b/arch/arm/mach-exynos/include/mach/regs-clock.h | |||
@@ -135,6 +135,9 @@ | |||
135 | #define EXYNOS4_CLKGATE_SCLKCPU EXYNOS_CLKREG(0x14800) | 135 | #define EXYNOS4_CLKGATE_SCLKCPU EXYNOS_CLKREG(0x14800) |
136 | #define EXYNOS4_CLKGATE_IP_CPU EXYNOS_CLKREG(0x14900) | 136 | #define EXYNOS4_CLKGATE_IP_CPU EXYNOS_CLKREG(0x14900) |
137 | 137 | ||
138 | #define EXYNOS4_CLKGATE_IP_ISP0 EXYNOS_CLKREG(0x18800) | ||
139 | #define EXYNOS4_CLKGATE_IP_ISP1 EXYNOS_CLKREG(0x18804) | ||
140 | |||
138 | #define EXYNOS4_APLL_LOCKTIME (0x1C20) /* 300us */ | 141 | #define EXYNOS4_APLL_LOCKTIME (0x1C20) /* 300us */ |
139 | 142 | ||
140 | #define EXYNOS4_APLLCON0_ENABLE_SHIFT (31) | 143 | #define EXYNOS4_APLLCON0_ENABLE_SHIFT (31) |
@@ -303,6 +306,8 @@ | |||
303 | #define EXYNOS5_CLKDIV_PERIC0 EXYNOS_CLKREG(0x10558) | 306 | #define EXYNOS5_CLKDIV_PERIC0 EXYNOS_CLKREG(0x10558) |
304 | 307 | ||
305 | #define EXYNOS5_CLKGATE_IP_ACP EXYNOS_CLKREG(0x08800) | 308 | #define EXYNOS5_CLKGATE_IP_ACP EXYNOS_CLKREG(0x08800) |
309 | #define EXYNOS5_CLKGATE_IP_ISP0 EXYNOS_CLKREG(0x0C800) | ||
310 | #define EXYNOS5_CLKGATE_IP_ISP1 EXYNOS_CLKREG(0x0C804) | ||
306 | #define EXYNOS5_CLKGATE_IP_GSCL EXYNOS_CLKREG(0x10920) | 311 | #define EXYNOS5_CLKGATE_IP_GSCL EXYNOS_CLKREG(0x10920) |
307 | #define EXYNOS5_CLKGATE_IP_DISP1 EXYNOS_CLKREG(0x10928) | 312 | #define EXYNOS5_CLKGATE_IP_DISP1 EXYNOS_CLKREG(0x10928) |
308 | #define EXYNOS5_CLKGATE_IP_MFC EXYNOS_CLKREG(0x1092C) | 313 | #define EXYNOS5_CLKGATE_IP_MFC EXYNOS_CLKREG(0x1092C) |
diff --git a/arch/arm/mach-exynos/include/mach/regs-sysmmu.h b/arch/arm/mach-exynos/include/mach/regs-sysmmu.h deleted file mode 100644 index 68ff6ad08a2b..000000000000 --- a/arch/arm/mach-exynos/include/mach/regs-sysmmu.h +++ /dev/null | |||
@@ -1,28 +0,0 @@ | |||
1 | /* linux/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h | ||
2 | * | ||
3 | * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * EXYNOS4 - System MMU register | ||
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 | #ifndef __ASM_ARCH_REGS_SYSMMU_H | ||
14 | #define __ASM_ARCH_REGS_SYSMMU_H __FILE__ | ||
15 | |||
16 | #define S5P_MMU_CTRL 0x000 | ||
17 | #define S5P_MMU_CFG 0x004 | ||
18 | #define S5P_MMU_STATUS 0x008 | ||
19 | #define S5P_MMU_FLUSH 0x00C | ||
20 | #define S5P_PT_BASE_ADDR 0x014 | ||
21 | #define S5P_INT_STATUS 0x018 | ||
22 | #define S5P_INT_CLEAR 0x01C | ||
23 | #define S5P_PAGE_FAULT_ADDR 0x024 | ||
24 | #define S5P_AW_FAULT_ADDR 0x028 | ||
25 | #define S5P_AR_FAULT_ADDR 0x02C | ||
26 | #define S5P_DEFAULT_SLAVE_ADDR 0x030 | ||
27 | |||
28 | #endif /* __ASM_ARCH_REGS_SYSMMU_H */ | ||
diff --git a/arch/arm/mach-exynos/include/mach/sysmmu.h b/arch/arm/mach-exynos/include/mach/sysmmu.h index 6a5fbb534e82..998daf2add92 100644 --- a/arch/arm/mach-exynos/include/mach/sysmmu.h +++ b/arch/arm/mach-exynos/include/mach/sysmmu.h | |||
@@ -1,46 +1,66 @@ | |||
1 | /* linux/arch/arm/mach-exynos4/include/mach/sysmmu.h | 1 | /* |
2 | * | 2 | * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd. |
3 | * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | 3 | * http://www.samsung.com |
5 | * | 4 | * |
6 | * Samsung sysmmu driver for EXYNOS4 | 5 | * EXYNOS - System MMU support |
7 | * | 6 | * |
8 | * This program is free software; you can redistribute it and/or modify | 7 | * 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 | 8 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
11 | */ | 10 | */ |
12 | 11 | ||
13 | #ifndef __ASM_ARM_ARCH_SYSMMU_H | 12 | #ifndef _ARM_MACH_EXYNOS_SYSMMU_H_ |
14 | #define __ASM_ARM_ARCH_SYSMMU_H __FILE__ | 13 | #define _ARM_MACH_EXYNOS_SYSMMU_H_ |
15 | 14 | ||
16 | enum exynos4_sysmmu_ips { | 15 | struct sysmmu_platform_data { |
17 | SYSMMU_MDMA, | 16 | char *dbgname; |
18 | SYSMMU_SSS, | 17 | /* comma(,) separated list of clock names for clock gating */ |
19 | SYSMMU_FIMC0, | 18 | char *clockname; |
20 | SYSMMU_FIMC1, | ||
21 | SYSMMU_FIMC2, | ||
22 | SYSMMU_FIMC3, | ||
23 | SYSMMU_JPEG, | ||
24 | SYSMMU_FIMD0, | ||
25 | SYSMMU_FIMD1, | ||
26 | SYSMMU_PCIe, | ||
27 | SYSMMU_G2D, | ||
28 | SYSMMU_ROTATOR, | ||
29 | SYSMMU_MDMA2, | ||
30 | SYSMMU_TV, | ||
31 | SYSMMU_MFC_L, | ||
32 | SYSMMU_MFC_R, | ||
33 | EXYNOS4_SYSMMU_TOTAL_IPNUM, | ||
34 | }; | 19 | }; |
35 | 20 | ||
36 | #define S5P_SYSMMU_TOTAL_IPNUM EXYNOS4_SYSMMU_TOTAL_IPNUM | 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); | ||
37 | 51 | ||
38 | extern const char *sysmmu_ips_name[EXYNOS4_SYSMMU_TOTAL_IPNUM]; | 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 | ||
39 | 59 | ||
40 | typedef enum exynos4_sysmmu_ips sysmmu_ips; | 60 | #else /* !CONFIG_EXYNOS_DEV_SYSMMU */ |
61 | #define platform_set_sysmmu(dev, sysmmu) do { } while (0) | ||
62 | #endif | ||
41 | 63 | ||
42 | void sysmmu_clk_init(struct device *dev, sysmmu_ips ips); | 64 | #define SYSMMU_CLOCK_DEVNAME(ipname, id) (SYSMMU_DEVNAME_BASE "." #id) |
43 | void sysmmu_clk_enable(sysmmu_ips ips); | ||
44 | void sysmmu_clk_disable(sysmmu_ips ips); | ||
45 | 65 | ||
46 | #endif /* __ASM_ARM_ARCH_SYSMMU_H */ | 66 | #endif /* _ARM_MACH_EXYNOS_SYSMMU_H_ */ |
diff --git a/arch/arm/mach-exynos/mach-armlex4210.c b/arch/arm/mach-exynos/mach-armlex4210.c index fed7116418eb..372e33196e8a 100644 --- a/arch/arm/mach-exynos/mach-armlex4210.c +++ b/arch/arm/mach-exynos/mach-armlex4210.c | |||
@@ -147,7 +147,6 @@ static struct platform_device *armlex4210_devices[] __initdata = { | |||
147 | &s3c_device_hsmmc3, | 147 | &s3c_device_hsmmc3, |
148 | &s3c_device_rtc, | 148 | &s3c_device_rtc, |
149 | &s3c_device_wdt, | 149 | &s3c_device_wdt, |
150 | &exynos4_device_sysmmu, | ||
151 | &samsung_asoc_dma, | 150 | &samsung_asoc_dma, |
152 | &armlex4210_smsc911x, | 151 | &armlex4210_smsc911x, |
153 | &exynos4_device_ahci, | 152 | &exynos4_device_ahci, |
diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c index 5af96064ca51..a8c7656b1fce 100644 --- a/arch/arm/mach-exynos/mach-smdkv310.c +++ b/arch/arm/mach-exynos/mach-smdkv310.c | |||
@@ -295,7 +295,6 @@ static struct platform_device *smdkv310_devices[] __initdata = { | |||
295 | &s5p_device_mfc_l, | 295 | &s5p_device_mfc_l, |
296 | &s5p_device_mfc_r, | 296 | &s5p_device_mfc_r, |
297 | &exynos4_device_spdif, | 297 | &exynos4_device_spdif, |
298 | &exynos4_device_sysmmu, | ||
299 | &samsung_asoc_dma, | 298 | &samsung_asoc_dma, |
300 | &samsung_asoc_idma, | 299 | &samsung_asoc_idma, |
301 | &s5p_device_fimd0, | 300 | &s5p_device_fimd0, |
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index d0f2546706ca..6a113a9bb87a 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig | |||
@@ -50,6 +50,14 @@ config TEGRA_PCI | |||
50 | depends on ARCH_TEGRA_2x_SOC | 50 | depends on ARCH_TEGRA_2x_SOC |
51 | select PCI | 51 | select PCI |
52 | 52 | ||
53 | config TEGRA_AHB | ||
54 | bool "Enable AHB driver for NVIDIA Tegra SoCs" | ||
55 | default y | ||
56 | help | ||
57 | Adds AHB configuration functionality for NVIDIA Tegra SoCs, | ||
58 | which controls AHB bus master arbitration and some | ||
59 | perfomance parameters(priority, prefech size). | ||
60 | |||
53 | comment "Tegra board type" | 61 | comment "Tegra board type" |
54 | 62 | ||
55 | config MACH_HARMONY | 63 | config MACH_HARMONY |
@@ -111,7 +119,7 @@ config MACH_VENTANA | |||
111 | Support for the nVidia Ventana development platform | 119 | Support for the nVidia Ventana development platform |
112 | 120 | ||
113 | choice | 121 | choice |
114 | prompt "Low-level debug console UART" | 122 | prompt "Default low-level debug console UART" |
115 | default TEGRA_DEBUG_UART_NONE | 123 | default TEGRA_DEBUG_UART_NONE |
116 | 124 | ||
117 | config TEGRA_DEBUG_UART_NONE | 125 | config TEGRA_DEBUG_UART_NONE |
@@ -134,6 +142,33 @@ config TEGRA_DEBUG_UARTE | |||
134 | 142 | ||
135 | endchoice | 143 | endchoice |
136 | 144 | ||
145 | choice | ||
146 | prompt "Automatic low-level debug console UART" | ||
147 | default TEGRA_DEBUG_UART_AUTO_NONE | ||
148 | |||
149 | config TEGRA_DEBUG_UART_AUTO_NONE | ||
150 | bool "None" | ||
151 | |||
152 | config TEGRA_DEBUG_UART_AUTO_ODMDATA | ||
153 | bool "Via ODMDATA" | ||
154 | help | ||
155 | Automatically determines which UART to use for low-level debug based | ||
156 | on the ODMDATA value. This value is part of the BCT, and is written | ||
157 | to the boot memory device using nvflash, or other flashing tool. | ||
158 | When bits 19:18 are 3, then bits 17:15 indicate which UART to use; | ||
159 | 0/1/2/3/4 are UART A/B/C/D/E. | ||
160 | |||
161 | config TEGRA_DEBUG_UART_AUTO_SCRATCH | ||
162 | bool "Via UART scratch register" | ||
163 | help | ||
164 | Automatically determines which UART to use for low-level debug based | ||
165 | on the UART scratch register value. Some bootloaders put ASCII 'D' | ||
166 | in this register when they initialize their own console UART output. | ||
167 | Using this option allows the kernel to automatically pick the same | ||
168 | UART. | ||
169 | |||
170 | endchoice | ||
171 | |||
137 | config TEGRA_SYSTEM_DMA | 172 | config TEGRA_SYSTEM_DMA |
138 | bool "Enable system DMA driver for NVIDIA Tegra SoCs" | 173 | bool "Enable system DMA driver for NVIDIA Tegra SoCs" |
139 | default y | 174 | default y |
diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c index 5f7c03e972f3..d96dae0b4aa7 100644 --- a/arch/arm/mach-tegra/board-dt-tegra30.c +++ b/arch/arm/mach-tegra/board-dt-tegra30.c | |||
@@ -51,12 +51,22 @@ struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = { | |||
51 | OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000C500, "tegra-i2c.2", NULL), | 51 | OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000C500, "tegra-i2c.2", NULL), |
52 | OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000C700, "tegra-i2c.3", NULL), | 52 | OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000C700, "tegra-i2c.3", NULL), |
53 | OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000D000, "tegra-i2c.4", NULL), | 53 | OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000D000, "tegra-i2c.4", NULL), |
54 | OF_DEV_AUXDATA("nvidia,tegra30-ahub", 0x70080000, "tegra30-ahub", NULL), | ||
54 | {} | 55 | {} |
55 | }; | 56 | }; |
56 | 57 | ||
57 | static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = { | 58 | static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = { |
58 | /* name parent rate enabled */ | 59 | /* name parent rate enabled */ |
59 | { "uarta", "pll_p", 408000000, true }, | 60 | { "uarta", "pll_p", 408000000, true }, |
61 | { "pll_a", "pll_p_out1", 564480000, true }, | ||
62 | { "pll_a_out0", "pll_a", 11289600, true }, | ||
63 | { "extern1", "pll_a_out0", 0, true }, | ||
64 | { "clk_out_1", "extern1", 0, true }, | ||
65 | { "i2s0", "pll_a_out0", 11289600, false}, | ||
66 | { "i2s1", "pll_a_out0", 11289600, false}, | ||
67 | { "i2s2", "pll_a_out0", 11289600, false}, | ||
68 | { "i2s3", "pll_a_out0", 11289600, false}, | ||
69 | { "i2s4", "pll_a_out0", 11289600, false}, | ||
60 | { NULL, NULL, 0, 0}, | 70 | { NULL, NULL, 0, 0}, |
61 | }; | 71 | }; |
62 | 72 | ||
diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c index d0735c70d688..55a1e6ccf4a2 100644 --- a/arch/arm/mach-tegra/board-paz00.c +++ b/arch/arm/mach-tegra/board-paz00.c | |||
@@ -162,6 +162,8 @@ static void paz00_i2c_init(void) | |||
162 | 162 | ||
163 | static void paz00_usb_init(void) | 163 | static void paz00_usb_init(void) |
164 | { | 164 | { |
165 | tegra_ehci2_ulpi_phy_config.reset_gpio = TEGRA_ULPI_RST; | ||
166 | |||
165 | platform_device_register(&tegra_ehci2_device); | 167 | platform_device_register(&tegra_ehci2_device); |
166 | platform_device_register(&tegra_ehci3_device); | 168 | platform_device_register(&tegra_ehci3_device); |
167 | } | 169 | } |
@@ -179,7 +181,6 @@ static __initdata struct tegra_clk_init_table paz00_clk_init_table[] = { | |||
179 | { "uarta", "pll_p", 216000000, true }, | 181 | { "uarta", "pll_p", 216000000, true }, |
180 | { "uartc", "pll_p", 216000000, true }, | 182 | { "uartc", "pll_p", 216000000, true }, |
181 | 183 | ||
182 | { "pll_p_out4", "pll_p", 24000000, true }, | ||
183 | { "usbd", "clk_m", 12000000, false }, | 184 | { "usbd", "clk_m", 12000000, false }, |
184 | { "usb2", "clk_m", 12000000, false }, | 185 | { "usb2", "clk_m", 12000000, false }, |
185 | { "usb3", "clk_m", 12000000, false }, | 186 | { "usb3", "clk_m", 12000000, false }, |
diff --git a/arch/arm/mach-tegra/board-trimslice.c b/arch/arm/mach-tegra/board-trimslice.c index bc59b379c6fe..832fa931c710 100644 --- a/arch/arm/mach-tegra/board-trimslice.c +++ b/arch/arm/mach-tegra/board-trimslice.c | |||
@@ -118,6 +118,8 @@ static void trimslice_usb_init(void) | |||
118 | pdata = tegra_ehci1_device.dev.platform_data; | 118 | pdata = tegra_ehci1_device.dev.platform_data; |
119 | pdata->vbus_gpio = TRIMSLICE_GPIO_USB1_MODE; | 119 | pdata->vbus_gpio = TRIMSLICE_GPIO_USB1_MODE; |
120 | 120 | ||
121 | tegra_ehci2_ulpi_phy_config.reset_gpio = TEGRA_GPIO_PV0; | ||
122 | |||
121 | platform_device_register(&tegra_ehci3_device); | 123 | platform_device_register(&tegra_ehci3_device); |
122 | platform_device_register(&tegra_ehci2_device); | 124 | platform_device_register(&tegra_ehci2_device); |
123 | platform_device_register(&tegra_ehci1_device); | 125 | platform_device_register(&tegra_ehci1_device); |
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index 22df10fb9972..2d80566b5383 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c | |||
@@ -82,10 +82,12 @@ static __initdata struct tegra_clk_init_table tegra20_clk_init_table[] = { | |||
82 | { "pll_p_out1", "pll_p", 28800000, true }, | 82 | { "pll_p_out1", "pll_p", 28800000, true }, |
83 | { "pll_p_out2", "pll_p", 48000000, true }, | 83 | { "pll_p_out2", "pll_p", 48000000, true }, |
84 | { "pll_p_out3", "pll_p", 72000000, true }, | 84 | { "pll_p_out3", "pll_p", 72000000, true }, |
85 | { "pll_p_out4", "pll_p", 108000000, true }, | 85 | { "pll_p_out4", "pll_p", 24000000, true }, |
86 | { "sclk", "pll_p_out4", 108000000, true }, | 86 | { "pll_c", "clk_m", 600000000, true }, |
87 | { "hclk", "sclk", 108000000, true }, | 87 | { "pll_c_out1", "pll_c", 120000000, true }, |
88 | { "pclk", "hclk", 54000000, true }, | 88 | { "sclk", "pll_c_out1", 120000000, true }, |
89 | { "hclk", "sclk", 120000000, true }, | ||
90 | { "pclk", "hclk", 60000000, true }, | ||
89 | { "csite", NULL, 0, true }, | 91 | { "csite", NULL, 0, true }, |
90 | { "emc", NULL, 0, true }, | 92 | { "emc", NULL, 0, true }, |
91 | { "cpu", NULL, 0, true }, | 93 | { "cpu", NULL, 0, true }, |
@@ -93,6 +95,17 @@ static __initdata struct tegra_clk_init_table tegra20_clk_init_table[] = { | |||
93 | }; | 95 | }; |
94 | #endif | 96 | #endif |
95 | 97 | ||
98 | #ifdef CONFIG_ARCH_TEGRA_3x_SOC | ||
99 | static __initdata struct tegra_clk_init_table tegra30_clk_init_table[] = { | ||
100 | /* name parent rate enabled */ | ||
101 | { "clk_m", NULL, 0, true }, | ||
102 | { "pll_p", "clk_m", 408000000, true }, | ||
103 | { "pll_p_out1", "pll_p", 9600000, true }, | ||
104 | { NULL, NULL, 0, 0}, | ||
105 | }; | ||
106 | #endif | ||
107 | |||
108 | |||
96 | static void __init tegra_init_cache(u32 tag_latency, u32 data_latency) | 109 | static void __init tegra_init_cache(u32 tag_latency, u32 data_latency) |
97 | { | 110 | { |
98 | #ifdef CONFIG_CACHE_L2X0 | 111 | #ifdef CONFIG_CACHE_L2X0 |
@@ -127,6 +140,7 @@ void __init tegra30_init_early(void) | |||
127 | { | 140 | { |
128 | tegra_init_fuse(); | 141 | tegra_init_fuse(); |
129 | tegra30_init_clocks(); | 142 | tegra30_init_clocks(); |
143 | tegra_clk_init_from_table(tegra30_clk_init_table); | ||
130 | tegra_init_cache(0x441, 0x551); | 144 | tegra_init_cache(0x441, 0x551); |
131 | tegra_pmc_init(); | 145 | tegra_pmc_init(); |
132 | tegra_powergate_init(); | 146 | tegra_powergate_init(); |
diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c index 2d8dfa2faf8f..c70e65ffa36b 100644 --- a/arch/arm/mach-tegra/devices.c +++ b/arch/arm/mach-tegra/devices.c | |||
@@ -439,9 +439,8 @@ static struct resource tegra_usb3_resources[] = { | |||
439 | }, | 439 | }, |
440 | }; | 440 | }; |
441 | 441 | ||
442 | static struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = { | 442 | struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = { |
443 | /* All existing boards use GPIO PV0 for phy reset */ | 443 | .reset_gpio = -1, |
444 | .reset_gpio = TEGRA_GPIO_PV0, | ||
445 | .clk = "cdev2", | 444 | .clk = "cdev2", |
446 | }; | 445 | }; |
447 | 446 | ||
diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h index 138c642e59f4..4f5052726495 100644 --- a/arch/arm/mach-tegra/devices.h +++ b/arch/arm/mach-tegra/devices.h | |||
@@ -22,6 +22,10 @@ | |||
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/platform_data/tegra_usb.h> | 23 | #include <linux/platform_data/tegra_usb.h> |
24 | 24 | ||
25 | #include <mach/usb_phy.h> | ||
26 | |||
27 | extern struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config; | ||
28 | |||
25 | extern struct tegra_ehci_platform_data tegra_ehci1_pdata; | 29 | extern struct tegra_ehci_platform_data tegra_ehci1_pdata; |
26 | extern struct tegra_ehci_platform_data tegra_ehci2_pdata; | 30 | extern struct tegra_ehci_platform_data tegra_ehci2_pdata; |
27 | extern struct tegra_ehci_platform_data tegra_ehci3_pdata; | 31 | extern struct tegra_ehci_platform_data tegra_ehci3_pdata; |
diff --git a/arch/arm/mach-tegra/include/mach/tegra-ahb.h b/arch/arm/mach-tegra/include/mach/tegra-ahb.h new file mode 100644 index 000000000000..e0f8c84b1d8c --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/tegra-ahb.h | |||
@@ -0,0 +1,19 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | */ | ||
13 | |||
14 | #ifndef __MACH_TEGRA_AHB_H__ | ||
15 | #define __MACH_TEGRA_AHB_H__ | ||
16 | |||
17 | extern int tegra_ahb_enable_smmu(struct device_node *ahb); | ||
18 | |||
19 | #endif /* __MACH_TEGRA_AHB_H__ */ | ||
diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h index 5a440f315e57..937c4c50219e 100644 --- a/arch/arm/mach-tegra/include/mach/uncompress.h +++ b/arch/arm/mach-tegra/include/mach/uncompress.h | |||
@@ -63,52 +63,86 @@ static inline void save_uart_address(void) | |||
63 | buf[0] = 0; | 63 | buf[0] = 0; |
64 | } | 64 | } |
65 | 65 | ||
66 | /* | 66 | static const struct { |
67 | * Setup before decompression. This is where we do UART selection for | 67 | u32 base; |
68 | * earlyprintk and init the uart_base register. | 68 | u32 reset_reg; |
69 | */ | 69 | u32 clock_reg; |
70 | static inline void arch_decomp_setup(void) | 70 | u32 bit; |
71 | } uarts[] = { | ||
72 | { | ||
73 | TEGRA_UARTA_BASE, | ||
74 | TEGRA_CLK_RESET_BASE + 0x04, | ||
75 | TEGRA_CLK_RESET_BASE + 0x10, | ||
76 | 6, | ||
77 | }, | ||
78 | { | ||
79 | TEGRA_UARTB_BASE, | ||
80 | TEGRA_CLK_RESET_BASE + 0x04, | ||
81 | TEGRA_CLK_RESET_BASE + 0x10, | ||
82 | 7, | ||
83 | }, | ||
84 | { | ||
85 | TEGRA_UARTC_BASE, | ||
86 | TEGRA_CLK_RESET_BASE + 0x08, | ||
87 | TEGRA_CLK_RESET_BASE + 0x14, | ||
88 | 23, | ||
89 | }, | ||
90 | { | ||
91 | TEGRA_UARTD_BASE, | ||
92 | TEGRA_CLK_RESET_BASE + 0x0c, | ||
93 | TEGRA_CLK_RESET_BASE + 0x18, | ||
94 | 1, | ||
95 | }, | ||
96 | { | ||
97 | TEGRA_UARTE_BASE, | ||
98 | TEGRA_CLK_RESET_BASE + 0x0c, | ||
99 | TEGRA_CLK_RESET_BASE + 0x18, | ||
100 | 2, | ||
101 | }, | ||
102 | }; | ||
103 | |||
104 | static inline bool uart_clocked(int i) | ||
105 | { | ||
106 | if (*(u8 *)uarts[i].reset_reg & BIT(uarts[i].bit)) | ||
107 | return false; | ||
108 | |||
109 | if (!(*(u8 *)uarts[i].clock_reg & BIT(uarts[i].bit))) | ||
110 | return false; | ||
111 | |||
112 | return true; | ||
113 | } | ||
114 | |||
115 | #ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA | ||
116 | int auto_odmdata(void) | ||
117 | { | ||
118 | volatile u32 *pmc = (volatile u32 *)TEGRA_PMC_BASE; | ||
119 | u32 odmdata = pmc[0xa0 / 4]; | ||
120 | |||
121 | /* | ||
122 | * Bits 19:18 are the console type: 0=default, 1=none, 2==DCC, 3==UART | ||
123 | * Some boards apparently swap the last two values, but we don't have | ||
124 | * any way of catering for that here, so we just accept either. If this | ||
125 | * doesn't make sense for your board, just don't enable this feature. | ||
126 | * | ||
127 | * Bits 17:15 indicate the UART to use, 0/1/2/3/4 are UART A/B/C/D/E. | ||
128 | */ | ||
129 | |||
130 | switch ((odmdata >> 18) & 3) { | ||
131 | case 2: | ||
132 | case 3: | ||
133 | break; | ||
134 | default: | ||
135 | return -1; | ||
136 | } | ||
137 | |||
138 | return (odmdata >> 15) & 7; | ||
139 | } | ||
140 | #endif | ||
141 | |||
142 | #ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH | ||
143 | int auto_scratch(void) | ||
71 | { | 144 | { |
72 | static const struct { | ||
73 | u32 base; | ||
74 | u32 reset_reg; | ||
75 | u32 clock_reg; | ||
76 | u32 bit; | ||
77 | } uarts[] = { | ||
78 | { | ||
79 | TEGRA_UARTA_BASE, | ||
80 | TEGRA_CLK_RESET_BASE + 0x04, | ||
81 | TEGRA_CLK_RESET_BASE + 0x10, | ||
82 | 6, | ||
83 | }, | ||
84 | { | ||
85 | TEGRA_UARTB_BASE, | ||
86 | TEGRA_CLK_RESET_BASE + 0x04, | ||
87 | TEGRA_CLK_RESET_BASE + 0x10, | ||
88 | 7, | ||
89 | }, | ||
90 | { | ||
91 | TEGRA_UARTC_BASE, | ||
92 | TEGRA_CLK_RESET_BASE + 0x08, | ||
93 | TEGRA_CLK_RESET_BASE + 0x14, | ||
94 | 23, | ||
95 | }, | ||
96 | { | ||
97 | TEGRA_UARTD_BASE, | ||
98 | TEGRA_CLK_RESET_BASE + 0x0c, | ||
99 | TEGRA_CLK_RESET_BASE + 0x18, | ||
100 | 1, | ||
101 | }, | ||
102 | { | ||
103 | TEGRA_UARTE_BASE, | ||
104 | TEGRA_CLK_RESET_BASE + 0x0c, | ||
105 | TEGRA_CLK_RESET_BASE + 0x18, | ||
106 | 2, | ||
107 | }, | ||
108 | }; | ||
109 | int i; | 145 | int i; |
110 | volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE; | ||
111 | u32 chip, div; | ||
112 | 146 | ||
113 | /* | 147 | /* |
114 | * Look for the first UART that: | 148 | * Look for the first UART that: |
@@ -125,20 +159,60 @@ static inline void arch_decomp_setup(void) | |||
125 | * back to what's specified in TEGRA_DEBUG_UART_BASE. | 159 | * back to what's specified in TEGRA_DEBUG_UART_BASE. |
126 | */ | 160 | */ |
127 | for (i = 0; i < ARRAY_SIZE(uarts); i++) { | 161 | for (i = 0; i < ARRAY_SIZE(uarts); i++) { |
128 | if (*(u8 *)uarts[i].reset_reg & BIT(uarts[i].bit)) | 162 | if (!uart_clocked(i)) |
129 | continue; | ||
130 | |||
131 | if (!(*(u8 *)uarts[i].clock_reg & BIT(uarts[i].bit))) | ||
132 | continue; | 163 | continue; |
133 | 164 | ||
134 | uart = (volatile u8 *)uarts[i].base; | 165 | uart = (volatile u8 *)uarts[i].base; |
135 | if (uart[UART_SCR << DEBUG_UART_SHIFT] != 'D') | 166 | if (uart[UART_SCR << DEBUG_UART_SHIFT] != 'D') |
136 | continue; | 167 | continue; |
137 | 168 | ||
138 | break; | 169 | return i; |
139 | } | 170 | } |
140 | if (i == ARRAY_SIZE(uarts)) | 171 | |
141 | uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE; | 172 | return -1; |
173 | } | ||
174 | #endif | ||
175 | |||
176 | /* | ||
177 | * Setup before decompression. This is where we do UART selection for | ||
178 | * earlyprintk and init the uart_base register. | ||
179 | */ | ||
180 | static inline void arch_decomp_setup(void) | ||
181 | { | ||
182 | int uart_id, auto_uart_id; | ||
183 | volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE; | ||
184 | u32 chip, div; | ||
185 | |||
186 | #if defined(CONFIG_TEGRA_DEBUG_UARTA) | ||
187 | uart_id = 0; | ||
188 | #elif defined(CONFIG_TEGRA_DEBUG_UARTB) | ||
189 | uart_id = 1; | ||
190 | #elif defined(CONFIG_TEGRA_DEBUG_UARTC) | ||
191 | uart_id = 2; | ||
192 | #elif defined(CONFIG_TEGRA_DEBUG_UARTD) | ||
193 | uart_id = 3; | ||
194 | #elif defined(CONFIG_TEGRA_DEBUG_UARTE) | ||
195 | uart_id = 4; | ||
196 | #else | ||
197 | uart_id = -1; | ||
198 | #endif | ||
199 | |||
200 | #if defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA) | ||
201 | auto_uart_id = auto_odmdata(); | ||
202 | #elif defined(CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH) | ||
203 | auto_uart_id = auto_scratch(); | ||
204 | #else | ||
205 | auto_uart_id = -1; | ||
206 | #endif | ||
207 | if (auto_uart_id != -1) | ||
208 | uart_id = auto_uart_id; | ||
209 | |||
210 | if (uart_id < 0 || uart_id >= ARRAY_SIZE(uarts) || | ||
211 | !uart_clocked(uart_id)) | ||
212 | uart = NULL; | ||
213 | else | ||
214 | uart = (volatile u8 *)uarts[uart_id].base; | ||
215 | |||
142 | save_uart_address(); | 216 | save_uart_address(); |
143 | if (uart == NULL) | 217 | if (uart == NULL) |
144 | return; | 218 | return; |
diff --git a/arch/arm/mach-tegra/include/mach/usb_phy.h b/arch/arm/mach-tegra/include/mach/usb_phy.h index de1a0f602b28..935ce9f65590 100644 --- a/arch/arm/mach-tegra/include/mach/usb_phy.h +++ b/arch/arm/mach-tegra/include/mach/usb_phy.h | |||
@@ -61,8 +61,8 @@ struct tegra_usb_phy { | |||
61 | struct usb_phy *ulpi; | 61 | struct usb_phy *ulpi; |
62 | }; | 62 | }; |
63 | 63 | ||
64 | struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs, | 64 | struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, |
65 | void *config, enum tegra_usb_phy_mode phy_mode); | 65 | void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode); |
66 | 66 | ||
67 | int tegra_usb_phy_power_on(struct tegra_usb_phy *phy); | 67 | int tegra_usb_phy_power_on(struct tegra_usb_phy *phy); |
68 | 68 | ||
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c index bae09b859891..b59315ce3691 100644 --- a/arch/arm/mach-tegra/tegra2_clocks.c +++ b/arch/arm/mach-tegra/tegra2_clocks.c | |||
@@ -1486,6 +1486,10 @@ static struct clk tegra_clk_m = { | |||
1486 | }; | 1486 | }; |
1487 | 1487 | ||
1488 | static struct clk_pll_freq_table tegra_pll_c_freq_table[] = { | 1488 | static struct clk_pll_freq_table tegra_pll_c_freq_table[] = { |
1489 | { 12000000, 600000000, 600, 12, 1, 8 }, | ||
1490 | { 13000000, 600000000, 600, 13, 1, 8 }, | ||
1491 | { 19200000, 600000000, 500, 16, 1, 6 }, | ||
1492 | { 26000000, 600000000, 600, 26, 1, 8 }, | ||
1489 | { 0, 0, 0, 0, 0, 0 }, | 1493 | { 0, 0, 0, 0, 0, 0 }, |
1490 | }; | 1494 | }; |
1491 | 1495 | ||
diff --git a/arch/arm/mach-tegra/tegra30_clocks.c b/arch/arm/mach-tegra/tegra30_clocks.c index 6d08b53f92d2..e33fe4b14a2a 100644 --- a/arch/arm/mach-tegra/tegra30_clocks.c +++ b/arch/arm/mach-tegra/tegra30_clocks.c | |||
@@ -3015,6 +3015,15 @@ struct clk_duplicate tegra_clk_duplicates[] = { | |||
3015 | CLK_DUPLICATE("sbc6", "spi_slave_tegra.5", NULL), | 3015 | CLK_DUPLICATE("sbc6", "spi_slave_tegra.5", NULL), |
3016 | CLK_DUPLICATE("twd", "smp_twd", NULL), | 3016 | CLK_DUPLICATE("twd", "smp_twd", NULL), |
3017 | CLK_DUPLICATE("vcp", "nvavp", "vcp"), | 3017 | CLK_DUPLICATE("vcp", "nvavp", "vcp"), |
3018 | CLK_DUPLICATE("i2s0", NULL, "i2s0"), | ||
3019 | CLK_DUPLICATE("i2s1", NULL, "i2s1"), | ||
3020 | CLK_DUPLICATE("i2s2", NULL, "i2s2"), | ||
3021 | CLK_DUPLICATE("i2s3", NULL, "i2s3"), | ||
3022 | CLK_DUPLICATE("i2s4", NULL, "i2s4"), | ||
3023 | CLK_DUPLICATE("dam0", NULL, "dam0"), | ||
3024 | CLK_DUPLICATE("dam1", NULL, "dam1"), | ||
3025 | CLK_DUPLICATE("dam2", NULL, "dam2"), | ||
3026 | CLK_DUPLICATE("spdif_in", NULL, "spdif_in"), | ||
3018 | }; | 3027 | }; |
3019 | 3028 | ||
3020 | struct clk *tegra_ptr_clks[] = { | 3029 | struct clk *tegra_ptr_clks[] = { |
diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c index d71d2fed6721..54e353c8e304 100644 --- a/arch/arm/mach-tegra/usb_phy.c +++ b/arch/arm/mach-tegra/usb_phy.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/io.h> | 27 | #include <linux/io.h> |
28 | #include <linux/gpio.h> | 28 | #include <linux/gpio.h> |
29 | #include <linux/of_gpio.h> | ||
29 | #include <linux/usb/otg.h> | 30 | #include <linux/usb/otg.h> |
30 | #include <linux/usb/ulpi.h> | 31 | #include <linux/usb/ulpi.h> |
31 | #include <asm/mach-types.h> | 32 | #include <asm/mach-types.h> |
@@ -654,8 +655,8 @@ static void ulpi_phy_power_off(struct tegra_usb_phy *phy) | |||
654 | clk_disable(phy->clk); | 655 | clk_disable(phy->clk); |
655 | } | 656 | } |
656 | 657 | ||
657 | struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs, | 658 | struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, |
658 | void *config, enum tegra_usb_phy_mode phy_mode) | 659 | void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode) |
659 | { | 660 | { |
660 | struct tegra_usb_phy *phy; | 661 | struct tegra_usb_phy *phy; |
661 | struct tegra_ulpi_config *ulpi_config; | 662 | struct tegra_ulpi_config *ulpi_config; |
@@ -711,6 +712,16 @@ struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs, | |||
711 | err = -ENXIO; | 712 | err = -ENXIO; |
712 | goto err1; | 713 | goto err1; |
713 | } | 714 | } |
715 | if (!gpio_is_valid(ulpi_config->reset_gpio)) | ||
716 | ulpi_config->reset_gpio = | ||
717 | of_get_named_gpio(dev->of_node, | ||
718 | "nvidia,phy-reset-gpio", 0); | ||
719 | if (!gpio_is_valid(ulpi_config->reset_gpio)) { | ||
720 | pr_err("%s: invalid reset gpio: %d\n", __func__, | ||
721 | ulpi_config->reset_gpio); | ||
722 | err = -EINVAL; | ||
723 | goto err1; | ||
724 | } | ||
714 | gpio_request(ulpi_config->reset_gpio, "ulpi_phy_reset_b"); | 725 | gpio_request(ulpi_config->reset_gpio, "ulpi_phy_reset_b"); |
715 | gpio_direction_output(ulpi_config->reset_gpio, 0); | 726 | gpio_direction_output(ulpi_config->reset_gpio, 0); |
716 | phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0); | 727 | phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0); |
diff --git a/arch/arm/plat-pxa/include/plat/pxa27x_keypad.h b/arch/arm/plat-pxa/include/plat/pxa27x_keypad.h index abcc36eb1242..5ce8d5e6ea51 100644 --- a/arch/arm/plat-pxa/include/plat/pxa27x_keypad.h +++ b/arch/arm/plat-pxa/include/plat/pxa27x_keypad.h | |||
@@ -44,6 +44,10 @@ struct pxa27x_keypad_platform_data { | |||
44 | /* direct keys */ | 44 | /* direct keys */ |
45 | int direct_key_num; | 45 | int direct_key_num; |
46 | unsigned int direct_key_map[MAX_DIRECT_KEY_NUM]; | 46 | unsigned int direct_key_map[MAX_DIRECT_KEY_NUM]; |
47 | /* the key output may be low active */ | ||
48 | int direct_key_low_active; | ||
49 | /* give board a chance to choose the start direct key */ | ||
50 | unsigned int direct_key_mask; | ||
47 | 51 | ||
48 | /* rotary encoders 0 */ | 52 | /* rotary encoders 0 */ |
49 | int enable_rotary0; | 53 | int enable_rotary0; |
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index 96bea3202304..2c1193c59928 100644 --- a/arch/arm/plat-s5p/Kconfig +++ b/arch/arm/plat-s5p/Kconfig | |||
@@ -50,14 +50,6 @@ config S5P_PM | |||
50 | Common code for power management support on S5P and newer SoCs | 50 | Common code for power management support on S5P and newer SoCs |
51 | Note: Do not select this for S5P6440 and S5P6450. | 51 | Note: Do not select this for S5P6440 and S5P6450. |
52 | 52 | ||
53 | comment "System MMU" | ||
54 | |||
55 | config S5P_SYSTEM_MMU | ||
56 | bool "S5P SYSTEM MMU" | ||
57 | depends on ARCH_EXYNOS4 | ||
58 | help | ||
59 | Say Y here if you want to enable System MMU | ||
60 | |||
61 | config S5P_SLEEP | 53 | config S5P_SLEEP |
62 | bool | 54 | bool |
63 | help | 55 | help |
diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile index 4bd824136659..4953d50707be 100644 --- a/arch/arm/plat-s5p/Makefile +++ b/arch/arm/plat-s5p/Makefile | |||
@@ -16,7 +16,6 @@ obj-y += clock.o | |||
16 | obj-y += irq.o | 16 | obj-y += irq.o |
17 | obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o | 17 | obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o |
18 | obj-$(CONFIG_S5P_GPIO_INT) += irq-gpioint.o | 18 | obj-$(CONFIG_S5P_GPIO_INT) += irq-gpioint.o |
19 | obj-$(CONFIG_S5P_SYSTEM_MMU) += sysmmu.o | ||
20 | obj-$(CONFIG_S5P_PM) += pm.o irq-pm.o | 19 | obj-$(CONFIG_S5P_PM) += pm.o irq-pm.o |
21 | obj-$(CONFIG_S5P_SLEEP) += sleep.o | 20 | obj-$(CONFIG_S5P_SLEEP) += sleep.o |
22 | obj-$(CONFIG_S5P_HRT) += s5p-time.o | 21 | obj-$(CONFIG_S5P_HRT) += s5p-time.o |
diff --git a/arch/arm/plat-s5p/sysmmu.c b/arch/arm/plat-s5p/sysmmu.c deleted file mode 100644 index c8bec9c7655d..000000000000 --- a/arch/arm/plat-s5p/sysmmu.c +++ /dev/null | |||
@@ -1,313 +0,0 @@ | |||
1 | /* linux/arch/arm/plat-s5p/sysmmu.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/io.h> | ||
12 | #include <linux/interrupt.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/export.h> | ||
15 | |||
16 | #include <asm/pgtable.h> | ||
17 | |||
18 | #include <mach/map.h> | ||
19 | #include <mach/regs-sysmmu.h> | ||
20 | #include <plat/sysmmu.h> | ||
21 | |||
22 | #define CTRL_ENABLE 0x5 | ||
23 | #define CTRL_BLOCK 0x7 | ||
24 | #define CTRL_DISABLE 0x0 | ||
25 | |||
26 | static struct device *dev; | ||
27 | |||
28 | static unsigned short fault_reg_offset[SYSMMU_FAULTS_NUM] = { | ||
29 | S5P_PAGE_FAULT_ADDR, | ||
30 | S5P_AR_FAULT_ADDR, | ||
31 | S5P_AW_FAULT_ADDR, | ||
32 | S5P_DEFAULT_SLAVE_ADDR, | ||
33 | S5P_AR_FAULT_ADDR, | ||
34 | S5P_AR_FAULT_ADDR, | ||
35 | S5P_AW_FAULT_ADDR, | ||
36 | S5P_AW_FAULT_ADDR | ||
37 | }; | ||
38 | |||
39 | static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = { | ||
40 | "PAGE FAULT", | ||
41 | "AR MULTI-HIT FAULT", | ||
42 | "AW MULTI-HIT FAULT", | ||
43 | "BUS ERROR", | ||
44 | "AR SECURITY PROTECTION FAULT", | ||
45 | "AR ACCESS PROTECTION FAULT", | ||
46 | "AW SECURITY PROTECTION FAULT", | ||
47 | "AW ACCESS PROTECTION FAULT" | ||
48 | }; | ||
49 | |||
50 | static int (*fault_handlers[S5P_SYSMMU_TOTAL_IPNUM])( | ||
51 | enum S5P_SYSMMU_INTERRUPT_TYPE itype, | ||
52 | unsigned long pgtable_base, | ||
53 | unsigned long fault_addr); | ||
54 | |||
55 | /* | ||
56 | * If adjacent 2 bits are true, the system MMU is enabled. | ||
57 | * The system MMU is disabled, otherwise. | ||
58 | */ | ||
59 | static unsigned long sysmmu_states; | ||
60 | |||
61 | static inline void set_sysmmu_active(sysmmu_ips ips) | ||
62 | { | ||
63 | sysmmu_states |= 3 << (ips * 2); | ||
64 | } | ||
65 | |||
66 | static inline void set_sysmmu_inactive(sysmmu_ips ips) | ||
67 | { | ||
68 | sysmmu_states &= ~(3 << (ips * 2)); | ||
69 | } | ||
70 | |||
71 | static inline int is_sysmmu_active(sysmmu_ips ips) | ||
72 | { | ||
73 | return sysmmu_states & (3 << (ips * 2)); | ||
74 | } | ||
75 | |||
76 | static void __iomem *sysmmusfrs[S5P_SYSMMU_TOTAL_IPNUM]; | ||
77 | |||
78 | static inline void sysmmu_block(sysmmu_ips ips) | ||
79 | { | ||
80 | __raw_writel(CTRL_BLOCK, sysmmusfrs[ips] + S5P_MMU_CTRL); | ||
81 | dev_dbg(dev, "%s is blocked.\n", sysmmu_ips_name[ips]); | ||
82 | } | ||
83 | |||
84 | static inline void sysmmu_unblock(sysmmu_ips ips) | ||
85 | { | ||
86 | __raw_writel(CTRL_ENABLE, sysmmusfrs[ips] + S5P_MMU_CTRL); | ||
87 | dev_dbg(dev, "%s is unblocked.\n", sysmmu_ips_name[ips]); | ||
88 | } | ||
89 | |||
90 | static inline void __sysmmu_tlb_invalidate(sysmmu_ips ips) | ||
91 | { | ||
92 | __raw_writel(0x1, sysmmusfrs[ips] + S5P_MMU_FLUSH); | ||
93 | dev_dbg(dev, "TLB of %s is invalidated.\n", sysmmu_ips_name[ips]); | ||
94 | } | ||
95 | |||
96 | static inline void __sysmmu_set_ptbase(sysmmu_ips ips, unsigned long pgd) | ||
97 | { | ||
98 | if (unlikely(pgd == 0)) { | ||
99 | pgd = (unsigned long)ZERO_PAGE(0); | ||
100 | __raw_writel(0x20, sysmmusfrs[ips] + S5P_MMU_CFG); /* 4KB LV1 */ | ||
101 | } else { | ||
102 | __raw_writel(0x0, sysmmusfrs[ips] + S5P_MMU_CFG); /* 16KB LV1 */ | ||
103 | } | ||
104 | |||
105 | __raw_writel(pgd, sysmmusfrs[ips] + S5P_PT_BASE_ADDR); | ||
106 | |||
107 | dev_dbg(dev, "Page table base of %s is initialized with 0x%08lX.\n", | ||
108 | sysmmu_ips_name[ips], pgd); | ||
109 | __sysmmu_tlb_invalidate(ips); | ||
110 | } | ||
111 | |||
112 | void sysmmu_set_fault_handler(sysmmu_ips ips, | ||
113 | int (*handler)(enum S5P_SYSMMU_INTERRUPT_TYPE itype, | ||
114 | unsigned long pgtable_base, | ||
115 | unsigned long fault_addr)) | ||
116 | { | ||
117 | BUG_ON(!((ips >= SYSMMU_MDMA) && (ips < S5P_SYSMMU_TOTAL_IPNUM))); | ||
118 | fault_handlers[ips] = handler; | ||
119 | } | ||
120 | |||
121 | static irqreturn_t s5p_sysmmu_irq(int irq, void *dev_id) | ||
122 | { | ||
123 | /* SYSMMU is in blocked when interrupt occurred. */ | ||
124 | unsigned long base = 0; | ||
125 | sysmmu_ips ips = (sysmmu_ips)dev_id; | ||
126 | enum S5P_SYSMMU_INTERRUPT_TYPE itype; | ||
127 | |||
128 | itype = (enum S5P_SYSMMU_INTERRUPT_TYPE) | ||
129 | __ffs(__raw_readl(sysmmusfrs[ips] + S5P_INT_STATUS)); | ||
130 | |||
131 | BUG_ON(!((itype >= 0) && (itype < 8))); | ||
132 | |||
133 | dev_alert(dev, "%s occurred by %s.\n", sysmmu_fault_name[itype], | ||
134 | sysmmu_ips_name[ips]); | ||
135 | |||
136 | if (fault_handlers[ips]) { | ||
137 | unsigned long addr; | ||
138 | |||
139 | base = __raw_readl(sysmmusfrs[ips] + S5P_PT_BASE_ADDR); | ||
140 | addr = __raw_readl(sysmmusfrs[ips] + fault_reg_offset[itype]); | ||
141 | |||
142 | if (fault_handlers[ips](itype, base, addr)) { | ||
143 | __raw_writel(1 << itype, | ||
144 | sysmmusfrs[ips] + S5P_INT_CLEAR); | ||
145 | dev_notice(dev, "%s from %s is resolved." | ||
146 | " Retrying translation.\n", | ||
147 | sysmmu_fault_name[itype], sysmmu_ips_name[ips]); | ||
148 | } else { | ||
149 | base = 0; | ||
150 | } | ||
151 | } | ||
152 | |||
153 | sysmmu_unblock(ips); | ||
154 | |||
155 | if (!base) | ||
156 | dev_notice(dev, "%s from %s is not handled.\n", | ||
157 | sysmmu_fault_name[itype], sysmmu_ips_name[ips]); | ||
158 | |||
159 | return IRQ_HANDLED; | ||
160 | } | ||
161 | |||
162 | void s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd) | ||
163 | { | ||
164 | if (is_sysmmu_active(ips)) { | ||
165 | sysmmu_block(ips); | ||
166 | __sysmmu_set_ptbase(ips, pgd); | ||
167 | sysmmu_unblock(ips); | ||
168 | } else { | ||
169 | dev_dbg(dev, "%s is disabled. " | ||
170 | "Skipping initializing page table base.\n", | ||
171 | sysmmu_ips_name[ips]); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | void s5p_sysmmu_enable(sysmmu_ips ips, unsigned long pgd) | ||
176 | { | ||
177 | if (!is_sysmmu_active(ips)) { | ||
178 | sysmmu_clk_enable(ips); | ||
179 | |||
180 | __sysmmu_set_ptbase(ips, pgd); | ||
181 | |||
182 | __raw_writel(CTRL_ENABLE, sysmmusfrs[ips] + S5P_MMU_CTRL); | ||
183 | |||
184 | set_sysmmu_active(ips); | ||
185 | dev_dbg(dev, "%s is enabled.\n", sysmmu_ips_name[ips]); | ||
186 | } else { | ||
187 | dev_dbg(dev, "%s is already enabled.\n", sysmmu_ips_name[ips]); | ||
188 | } | ||
189 | } | ||
190 | |||
191 | void s5p_sysmmu_disable(sysmmu_ips ips) | ||
192 | { | ||
193 | if (is_sysmmu_active(ips)) { | ||
194 | __raw_writel(CTRL_DISABLE, sysmmusfrs[ips] + S5P_MMU_CTRL); | ||
195 | set_sysmmu_inactive(ips); | ||
196 | sysmmu_clk_disable(ips); | ||
197 | dev_dbg(dev, "%s is disabled.\n", sysmmu_ips_name[ips]); | ||
198 | } else { | ||
199 | dev_dbg(dev, "%s is already disabled.\n", sysmmu_ips_name[ips]); | ||
200 | } | ||
201 | } | ||
202 | |||
203 | void s5p_sysmmu_tlb_invalidate(sysmmu_ips ips) | ||
204 | { | ||
205 | if (is_sysmmu_active(ips)) { | ||
206 | sysmmu_block(ips); | ||
207 | __sysmmu_tlb_invalidate(ips); | ||
208 | sysmmu_unblock(ips); | ||
209 | } else { | ||
210 | dev_dbg(dev, "%s is disabled. " | ||
211 | "Skipping invalidating TLB.\n", sysmmu_ips_name[ips]); | ||
212 | } | ||
213 | } | ||
214 | |||
215 | static int s5p_sysmmu_probe(struct platform_device *pdev) | ||
216 | { | ||
217 | int i, ret; | ||
218 | struct resource *res, *mem; | ||
219 | |||
220 | dev = &pdev->dev; | ||
221 | |||
222 | for (i = 0; i < S5P_SYSMMU_TOTAL_IPNUM; i++) { | ||
223 | int irq; | ||
224 | |||
225 | sysmmu_clk_init(dev, i); | ||
226 | sysmmu_clk_disable(i); | ||
227 | |||
228 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); | ||
229 | if (!res) { | ||
230 | dev_err(dev, "Failed to get the resource of %s.\n", | ||
231 | sysmmu_ips_name[i]); | ||
232 | ret = -ENODEV; | ||
233 | goto err_res; | ||
234 | } | ||
235 | |||
236 | mem = request_mem_region(res->start, resource_size(res), | ||
237 | pdev->name); | ||
238 | if (!mem) { | ||
239 | dev_err(dev, "Failed to request the memory region of %s.\n", | ||
240 | sysmmu_ips_name[i]); | ||
241 | ret = -EBUSY; | ||
242 | goto err_res; | ||
243 | } | ||
244 | |||
245 | sysmmusfrs[i] = ioremap(res->start, resource_size(res)); | ||
246 | if (!sysmmusfrs[i]) { | ||
247 | dev_err(dev, "Failed to ioremap() for %s.\n", | ||
248 | sysmmu_ips_name[i]); | ||
249 | ret = -ENXIO; | ||
250 | goto err_reg; | ||
251 | } | ||
252 | |||
253 | irq = platform_get_irq(pdev, i); | ||
254 | if (irq <= 0) { | ||
255 | dev_err(dev, "Failed to get the IRQ resource of %s.\n", | ||
256 | sysmmu_ips_name[i]); | ||
257 | ret = -ENOENT; | ||
258 | goto err_map; | ||
259 | } | ||
260 | |||
261 | if (request_irq(irq, s5p_sysmmu_irq, IRQF_DISABLED, | ||
262 | pdev->name, (void *)i)) { | ||
263 | dev_err(dev, "Failed to request IRQ for %s.\n", | ||
264 | sysmmu_ips_name[i]); | ||
265 | ret = -ENOENT; | ||
266 | goto err_map; | ||
267 | } | ||
268 | } | ||
269 | |||
270 | return 0; | ||
271 | |||
272 | err_map: | ||
273 | iounmap(sysmmusfrs[i]); | ||
274 | err_reg: | ||
275 | release_mem_region(mem->start, resource_size(mem)); | ||
276 | err_res: | ||
277 | return ret; | ||
278 | } | ||
279 | |||
280 | static int s5p_sysmmu_remove(struct platform_device *pdev) | ||
281 | { | ||
282 | return 0; | ||
283 | } | ||
284 | int s5p_sysmmu_runtime_suspend(struct device *dev) | ||
285 | { | ||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | int s5p_sysmmu_runtime_resume(struct device *dev) | ||
290 | { | ||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | const struct dev_pm_ops s5p_sysmmu_pm_ops = { | ||
295 | .runtime_suspend = s5p_sysmmu_runtime_suspend, | ||
296 | .runtime_resume = s5p_sysmmu_runtime_resume, | ||
297 | }; | ||
298 | |||
299 | static struct platform_driver s5p_sysmmu_driver = { | ||
300 | .probe = s5p_sysmmu_probe, | ||
301 | .remove = s5p_sysmmu_remove, | ||
302 | .driver = { | ||
303 | .owner = THIS_MODULE, | ||
304 | .name = "s5p-sysmmu", | ||
305 | .pm = &s5p_sysmmu_pm_ops, | ||
306 | } | ||
307 | }; | ||
308 | |||
309 | static int __init s5p_sysmmu_init(void) | ||
310 | { | ||
311 | return platform_driver_register(&s5p_sysmmu_driver); | ||
312 | } | ||
313 | arch_initcall(s5p_sysmmu_init); | ||
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index 2155d4af62a3..4067d1dd7f1c 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h | |||
@@ -133,7 +133,6 @@ extern struct platform_device exynos4_device_pcm1; | |||
133 | extern struct platform_device exynos4_device_pcm2; | 133 | extern struct platform_device exynos4_device_pcm2; |
134 | extern struct platform_device exynos4_device_pd[]; | 134 | extern struct platform_device exynos4_device_pd[]; |
135 | extern struct platform_device exynos4_device_spdif; | 135 | extern struct platform_device exynos4_device_spdif; |
136 | extern struct platform_device exynos4_device_sysmmu; | ||
137 | 136 | ||
138 | extern struct platform_device samsung_asoc_dma; | 137 | extern struct platform_device samsung_asoc_dma; |
139 | extern struct platform_device samsung_asoc_idma; | 138 | extern struct platform_device samsung_asoc_idma; |
diff --git a/arch/arm/plat-samsung/include/plat/sysmmu.h b/arch/arm/plat-samsung/include/plat/sysmmu.h deleted file mode 100644 index 5fe8ee01a5ba..000000000000 --- a/arch/arm/plat-samsung/include/plat/sysmmu.h +++ /dev/null | |||
@@ -1,95 +0,0 @@ | |||
1 | /* linux/arch/arm/plat-samsung/include/plat/sysmmu.h | ||
2 | * | ||
3 | * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * Samsung System MMU driver for S5P platform | ||
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 | #ifndef __PLAT_SAMSUNG_SYSMMU_H | ||
14 | #define __PLAT_SAMSUNG_SYSMMU_H __FILE__ | ||
15 | |||
16 | enum S5P_SYSMMU_INTERRUPT_TYPE { | ||
17 | SYSMMU_PAGEFAULT, | ||
18 | SYSMMU_AR_MULTIHIT, | ||
19 | SYSMMU_AW_MULTIHIT, | ||
20 | SYSMMU_BUSERROR, | ||
21 | SYSMMU_AR_SECURITY, | ||
22 | SYSMMU_AR_ACCESS, | ||
23 | SYSMMU_AW_SECURITY, | ||
24 | SYSMMU_AW_PROTECTION, /* 7 */ | ||
25 | SYSMMU_FAULTS_NUM | ||
26 | }; | ||
27 | |||
28 | #ifdef CONFIG_S5P_SYSTEM_MMU | ||
29 | |||
30 | #include <mach/sysmmu.h> | ||
31 | |||
32 | /** | ||
33 | * s5p_sysmmu_enable() - enable system mmu of ip | ||
34 | * @ips: The ip connected system mmu. | ||
35 | * #pgd: Base physical address of the 1st level page table | ||
36 | * | ||
37 | * This function enable system mmu to transfer address | ||
38 | * from virtual address to physical address | ||
39 | */ | ||
40 | void s5p_sysmmu_enable(sysmmu_ips ips, unsigned long pgd); | ||
41 | |||
42 | /** | ||
43 | * s5p_sysmmu_disable() - disable sysmmu mmu of ip | ||
44 | * @ips: The ip connected system mmu. | ||
45 | * | ||
46 | * This function disable system mmu to transfer address | ||
47 | * from virtual address to physical address | ||
48 | */ | ||
49 | void s5p_sysmmu_disable(sysmmu_ips ips); | ||
50 | |||
51 | /** | ||
52 | * s5p_sysmmu_set_tablebase_pgd() - set page table base address to refer page table | ||
53 | * @ips: The ip connected system mmu. | ||
54 | * @pgd: The page table base address. | ||
55 | * | ||
56 | * This function set page table base address | ||
57 | * When system mmu transfer address from virtaul address to physical address, | ||
58 | * system mmu refer address information from page table | ||
59 | */ | ||
60 | void s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd); | ||
61 | |||
62 | /** | ||
63 | * s5p_sysmmu_tlb_invalidate() - flush all TLB entry in system mmu | ||
64 | * @ips: The ip connected system mmu. | ||
65 | * | ||
66 | * This function flush all TLB entry in system mmu | ||
67 | */ | ||
68 | void s5p_sysmmu_tlb_invalidate(sysmmu_ips ips); | ||
69 | |||
70 | /** s5p_sysmmu_set_fault_handler() - Fault handler for System MMUs | ||
71 | * @itype: type of fault. | ||
72 | * @pgtable_base: the physical address of page table base. This is 0 if @ips is | ||
73 | * SYSMMU_BUSERROR. | ||
74 | * @fault_addr: the device (virtual) address that the System MMU tried to | ||
75 | * translated. This is 0 if @ips is SYSMMU_BUSERROR. | ||
76 | * Called when interrupt occurred by the System MMUs | ||
77 | * The device drivers of peripheral devices that has a System MMU can implement | ||
78 | * a fault handler to resolve address translation fault by System MMU. | ||
79 | * The meanings of return value and parameters are described below. | ||
80 | |||
81 | * return value: non-zero if the fault is correctly resolved. | ||
82 | * zero if the fault is not handled. | ||
83 | */ | ||
84 | void s5p_sysmmu_set_fault_handler(sysmmu_ips ips, | ||
85 | int (*handler)(enum S5P_SYSMMU_INTERRUPT_TYPE itype, | ||
86 | unsigned long pgtable_base, | ||
87 | unsigned long fault_addr)); | ||
88 | #else | ||
89 | #define s5p_sysmmu_enable(ips, pgd) do { } while (0) | ||
90 | #define s5p_sysmmu_disable(ips) do { } while (0) | ||
91 | #define s5p_sysmmu_set_tablebase_pgd(ips, pgd) do { } while (0) | ||
92 | #define s5p_sysmmu_tlb_invalidate(ips) do { } while (0) | ||
93 | #define s5p_sysmmu_set_fault_handler(ips, handler) do { } while (0) | ||
94 | #endif | ||
95 | #endif /* __ASM_PLAT_SYSMMU_H */ | ||
diff --git a/arch/powerpc/boot/dts/mpc8569mds.dts b/arch/powerpc/boot/dts/mpc8569mds.dts index 7e283c891b7f..fe0d60935e9b 100644 --- a/arch/powerpc/boot/dts/mpc8569mds.dts +++ b/arch/powerpc/boot/dts/mpc8569mds.dts | |||
@@ -119,6 +119,7 @@ | |||
119 | sdhc@2e000 { | 119 | sdhc@2e000 { |
120 | status = "disabled"; | 120 | status = "disabled"; |
121 | sdhci,1-bit-only; | 121 | sdhci,1-bit-only; |
122 | bus-width = <1>; | ||
122 | }; | 123 | }; |
123 | 124 | ||
124 | par_io@e0100 { | 125 | par_io@e0100 { |
diff --git a/drivers/Makefile b/drivers/Makefile index 0ee98d50f975..2ba29ffef2cb 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
@@ -18,7 +18,7 @@ obj-$(CONFIG_SFI) += sfi/ | |||
18 | # PnP must come after ACPI since it will eventually need to check if acpi | 18 | # PnP must come after ACPI since it will eventually need to check if acpi |
19 | # was used and do nothing if so | 19 | # was used and do nothing if so |
20 | obj-$(CONFIG_PNP) += pnp/ | 20 | obj-$(CONFIG_PNP) += pnp/ |
21 | obj-$(CONFIG_ARM_AMBA) += amba/ | 21 | obj-y += amba/ |
22 | # Many drivers will want to use DMA so this has to be made available | 22 | # Many drivers will want to use DMA so this has to be made available |
23 | # really early. | 23 | # really early. |
24 | obj-$(CONFIG_DMA_ENGINE) += dma/ | 24 | obj-$(CONFIG_DMA_ENGINE) += dma/ |
diff --git a/drivers/amba/Makefile b/drivers/amba/Makefile index 40fe74097be2..66e81c2f1e3c 100644 --- a/drivers/amba/Makefile +++ b/drivers/amba/Makefile | |||
@@ -1,2 +1,2 @@ | |||
1 | obj-y += bus.o | 1 | obj-$(CONFIG_ARM_AMBA) += bus.o |
2 | 2 | obj-$(CONFIG_TEGRA_AHB) += tegra-ahb.o | |
diff --git a/drivers/amba/tegra-ahb.c b/drivers/amba/tegra-ahb.c new file mode 100644 index 000000000000..aa0b1f160528 --- /dev/null +++ b/drivers/amba/tegra-ahb.c | |||
@@ -0,0 +1,293 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. | ||
3 | * Copyright (C) 2011 Google, Inc. | ||
4 | * | ||
5 | * Author: | ||
6 | * Jay Cheng <jacheng@nvidia.com> | ||
7 | * James Wylder <james.wylder@motorola.com> | ||
8 | * Benoit Goby <benoit@android.com> | ||
9 | * Colin Cross <ccross@android.com> | ||
10 | * Hiroshi DOYU <hdoyu@nvidia.com> | ||
11 | * | ||
12 | * This software is licensed under the terms of the GNU General Public | ||
13 | * License version 2, as published by the Free Software Foundation, and | ||
14 | * may be copied, distributed, and modified under those terms. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/io.h> | ||
27 | |||
28 | #define DRV_NAME "tegra-ahb" | ||
29 | |||
30 | #define AHB_ARBITRATION_DISABLE 0x00 | ||
31 | #define AHB_ARBITRATION_PRIORITY_CTRL 0x04 | ||
32 | #define AHB_PRIORITY_WEIGHT(x) (((x) & 0x7) << 29) | ||
33 | #define PRIORITY_SELECT_USB BIT(6) | ||
34 | #define PRIORITY_SELECT_USB2 BIT(18) | ||
35 | #define PRIORITY_SELECT_USB3 BIT(17) | ||
36 | |||
37 | #define AHB_GIZMO_AHB_MEM 0x0c | ||
38 | #define ENB_FAST_REARBITRATE BIT(2) | ||
39 | #define DONT_SPLIT_AHB_WR BIT(7) | ||
40 | |||
41 | #define AHB_GIZMO_APB_DMA 0x10 | ||
42 | #define AHB_GIZMO_IDE 0x18 | ||
43 | #define AHB_GIZMO_USB 0x1c | ||
44 | #define AHB_GIZMO_AHB_XBAR_BRIDGE 0x20 | ||
45 | #define AHB_GIZMO_CPU_AHB_BRIDGE 0x24 | ||
46 | #define AHB_GIZMO_COP_AHB_BRIDGE 0x28 | ||
47 | #define AHB_GIZMO_XBAR_APB_CTLR 0x2c | ||
48 | #define AHB_GIZMO_VCP_AHB_BRIDGE 0x30 | ||
49 | #define AHB_GIZMO_NAND 0x3c | ||
50 | #define AHB_GIZMO_SDMMC4 0x44 | ||
51 | #define AHB_GIZMO_XIO 0x48 | ||
52 | #define AHB_GIZMO_BSEV 0x60 | ||
53 | #define AHB_GIZMO_BSEA 0x70 | ||
54 | #define AHB_GIZMO_NOR 0x74 | ||
55 | #define AHB_GIZMO_USB2 0x78 | ||
56 | #define AHB_GIZMO_USB3 0x7c | ||
57 | #define IMMEDIATE BIT(18) | ||
58 | |||
59 | #define AHB_GIZMO_SDMMC1 0x80 | ||
60 | #define AHB_GIZMO_SDMMC2 0x84 | ||
61 | #define AHB_GIZMO_SDMMC3 0x88 | ||
62 | #define AHB_MEM_PREFETCH_CFG_X 0xd8 | ||
63 | #define AHB_ARBITRATION_XBAR_CTRL 0xdc | ||
64 | #define AHB_MEM_PREFETCH_CFG3 0xe0 | ||
65 | #define AHB_MEM_PREFETCH_CFG4 0xe4 | ||
66 | #define AHB_MEM_PREFETCH_CFG1 0xec | ||
67 | #define AHB_MEM_PREFETCH_CFG2 0xf0 | ||
68 | #define PREFETCH_ENB BIT(31) | ||
69 | #define MST_ID(x) (((x) & 0x1f) << 26) | ||
70 | #define AHBDMA_MST_ID MST_ID(5) | ||
71 | #define USB_MST_ID MST_ID(6) | ||
72 | #define USB2_MST_ID MST_ID(18) | ||
73 | #define USB3_MST_ID MST_ID(17) | ||
74 | #define ADDR_BNDRY(x) (((x) & 0xf) << 21) | ||
75 | #define INACTIVITY_TIMEOUT(x) (((x) & 0xffff) << 0) | ||
76 | |||
77 | #define AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID 0xf8 | ||
78 | |||
79 | #define AHB_ARBITRATION_XBAR_CTRL_SMMU_INIT_DONE BIT(17) | ||
80 | |||
81 | static struct platform_driver tegra_ahb_driver; | ||
82 | |||
83 | static const u32 tegra_ahb_gizmo[] = { | ||
84 | AHB_ARBITRATION_DISABLE, | ||
85 | AHB_ARBITRATION_PRIORITY_CTRL, | ||
86 | AHB_GIZMO_AHB_MEM, | ||
87 | AHB_GIZMO_APB_DMA, | ||
88 | AHB_GIZMO_IDE, | ||
89 | AHB_GIZMO_USB, | ||
90 | AHB_GIZMO_AHB_XBAR_BRIDGE, | ||
91 | AHB_GIZMO_CPU_AHB_BRIDGE, | ||
92 | AHB_GIZMO_COP_AHB_BRIDGE, | ||
93 | AHB_GIZMO_XBAR_APB_CTLR, | ||
94 | AHB_GIZMO_VCP_AHB_BRIDGE, | ||
95 | AHB_GIZMO_NAND, | ||
96 | AHB_GIZMO_SDMMC4, | ||
97 | AHB_GIZMO_XIO, | ||
98 | AHB_GIZMO_BSEV, | ||
99 | AHB_GIZMO_BSEA, | ||
100 | AHB_GIZMO_NOR, | ||
101 | AHB_GIZMO_USB2, | ||
102 | AHB_GIZMO_USB3, | ||
103 | AHB_GIZMO_SDMMC1, | ||
104 | AHB_GIZMO_SDMMC2, | ||
105 | AHB_GIZMO_SDMMC3, | ||
106 | AHB_MEM_PREFETCH_CFG_X, | ||
107 | AHB_ARBITRATION_XBAR_CTRL, | ||
108 | AHB_MEM_PREFETCH_CFG3, | ||
109 | AHB_MEM_PREFETCH_CFG4, | ||
110 | AHB_MEM_PREFETCH_CFG1, | ||
111 | AHB_MEM_PREFETCH_CFG2, | ||
112 | AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID, | ||
113 | }; | ||
114 | |||
115 | struct tegra_ahb { | ||
116 | void __iomem *regs; | ||
117 | struct device *dev; | ||
118 | u32 ctx[0]; | ||
119 | }; | ||
120 | |||
121 | static inline u32 gizmo_readl(struct tegra_ahb *ahb, u32 offset) | ||
122 | { | ||
123 | return readl(ahb->regs + offset); | ||
124 | } | ||
125 | |||
126 | static inline void gizmo_writel(struct tegra_ahb *ahb, u32 value, u32 offset) | ||
127 | { | ||
128 | writel(value, ahb->regs + offset); | ||
129 | } | ||
130 | |||
131 | #ifdef CONFIG_ARCH_TEGRA_3x_SOC | ||
132 | static int tegra_ahb_match_by_smmu(struct device *dev, void *data) | ||
133 | { | ||
134 | struct tegra_ahb *ahb = dev_get_drvdata(dev); | ||
135 | struct device_node *dn = data; | ||
136 | |||
137 | return (ahb->dev->of_node == dn) ? 1 : 0; | ||
138 | } | ||
139 | |||
140 | int tegra_ahb_enable_smmu(struct device_node *dn) | ||
141 | { | ||
142 | struct device *dev; | ||
143 | u32 val; | ||
144 | struct tegra_ahb *ahb; | ||
145 | |||
146 | dev = driver_find_device(&tegra_ahb_driver.driver, NULL, dn, | ||
147 | tegra_ahb_match_by_smmu); | ||
148 | if (!dev) | ||
149 | return -EPROBE_DEFER; | ||
150 | ahb = dev_get_drvdata(dev); | ||
151 | val = gizmo_readl(ahb, AHB_ARBITRATION_XBAR_CTRL); | ||
152 | val |= AHB_ARBITRATION_XBAR_CTRL_SMMU_INIT_DONE; | ||
153 | gizmo_writel(ahb, val, AHB_ARBITRATION_XBAR_CTRL); | ||
154 | return 0; | ||
155 | } | ||
156 | EXPORT_SYMBOL(tegra_ahb_enable_smmu); | ||
157 | #endif | ||
158 | |||
159 | static int tegra_ahb_suspend(struct device *dev) | ||
160 | { | ||
161 | int i; | ||
162 | struct tegra_ahb *ahb = dev_get_drvdata(dev); | ||
163 | |||
164 | for (i = 0; i < ARRAY_SIZE(tegra_ahb_gizmo); i++) | ||
165 | ahb->ctx[i] = gizmo_readl(ahb, tegra_ahb_gizmo[i]); | ||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static int tegra_ahb_resume(struct device *dev) | ||
170 | { | ||
171 | int i; | ||
172 | struct tegra_ahb *ahb = dev_get_drvdata(dev); | ||
173 | |||
174 | for (i = 0; i < ARRAY_SIZE(tegra_ahb_gizmo); i++) | ||
175 | gizmo_writel(ahb, ahb->ctx[i], tegra_ahb_gizmo[i]); | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static UNIVERSAL_DEV_PM_OPS(tegra_ahb_pm, | ||
180 | tegra_ahb_suspend, | ||
181 | tegra_ahb_resume, NULL); | ||
182 | |||
183 | static void tegra_ahb_gizmo_init(struct tegra_ahb *ahb) | ||
184 | { | ||
185 | u32 val; | ||
186 | |||
187 | val = gizmo_readl(ahb, AHB_GIZMO_AHB_MEM); | ||
188 | val |= ENB_FAST_REARBITRATE | IMMEDIATE | DONT_SPLIT_AHB_WR; | ||
189 | gizmo_writel(ahb, val, AHB_GIZMO_AHB_MEM); | ||
190 | |||
191 | val = gizmo_readl(ahb, AHB_GIZMO_USB); | ||
192 | val |= IMMEDIATE; | ||
193 | gizmo_writel(ahb, val, AHB_GIZMO_USB); | ||
194 | |||
195 | val = gizmo_readl(ahb, AHB_GIZMO_USB2); | ||
196 | val |= IMMEDIATE; | ||
197 | gizmo_writel(ahb, val, AHB_GIZMO_USB2); | ||
198 | |||
199 | val = gizmo_readl(ahb, AHB_GIZMO_USB3); | ||
200 | val |= IMMEDIATE; | ||
201 | gizmo_writel(ahb, val, AHB_GIZMO_USB3); | ||
202 | |||
203 | val = gizmo_readl(ahb, AHB_ARBITRATION_PRIORITY_CTRL); | ||
204 | val |= PRIORITY_SELECT_USB | | ||
205 | PRIORITY_SELECT_USB2 | | ||
206 | PRIORITY_SELECT_USB3 | | ||
207 | AHB_PRIORITY_WEIGHT(7); | ||
208 | gizmo_writel(ahb, val, AHB_ARBITRATION_PRIORITY_CTRL); | ||
209 | |||
210 | val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG1); | ||
211 | val &= ~MST_ID(~0); | ||
212 | val |= PREFETCH_ENB | | ||
213 | AHBDMA_MST_ID | | ||
214 | ADDR_BNDRY(0xc) | | ||
215 | INACTIVITY_TIMEOUT(0x1000); | ||
216 | gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG1); | ||
217 | |||
218 | val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG2); | ||
219 | val &= ~MST_ID(~0); | ||
220 | val |= PREFETCH_ENB | | ||
221 | USB_MST_ID | | ||
222 | ADDR_BNDRY(0xc) | | ||
223 | INACTIVITY_TIMEOUT(0x1000); | ||
224 | gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG2); | ||
225 | |||
226 | val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG3); | ||
227 | val &= ~MST_ID(~0); | ||
228 | val |= PREFETCH_ENB | | ||
229 | USB3_MST_ID | | ||
230 | ADDR_BNDRY(0xc) | | ||
231 | INACTIVITY_TIMEOUT(0x1000); | ||
232 | gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG3); | ||
233 | |||
234 | val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG4); | ||
235 | val &= ~MST_ID(~0); | ||
236 | val |= PREFETCH_ENB | | ||
237 | USB2_MST_ID | | ||
238 | ADDR_BNDRY(0xc) | | ||
239 | INACTIVITY_TIMEOUT(0x1000); | ||
240 | gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG4); | ||
241 | } | ||
242 | |||
243 | static int __devinit tegra_ahb_probe(struct platform_device *pdev) | ||
244 | { | ||
245 | struct resource *res; | ||
246 | struct tegra_ahb *ahb; | ||
247 | size_t bytes; | ||
248 | |||
249 | bytes = sizeof(*ahb) + sizeof(u32) * ARRAY_SIZE(tegra_ahb_gizmo); | ||
250 | ahb = devm_kzalloc(&pdev->dev, bytes, GFP_KERNEL); | ||
251 | if (!ahb) | ||
252 | return -ENOMEM; | ||
253 | |||
254 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
255 | if (!res) | ||
256 | return -ENODEV; | ||
257 | ahb->regs = devm_request_and_ioremap(&pdev->dev, res); | ||
258 | if (!ahb->regs) | ||
259 | return -EBUSY; | ||
260 | |||
261 | ahb->dev = &pdev->dev; | ||
262 | platform_set_drvdata(pdev, ahb); | ||
263 | tegra_ahb_gizmo_init(ahb); | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | static int __devexit tegra_ahb_remove(struct platform_device *pdev) | ||
268 | { | ||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static const struct of_device_id tegra_ahb_of_match[] __devinitconst = { | ||
273 | { .compatible = "nvidia,tegra30-ahb", }, | ||
274 | { .compatible = "nvidia,tegra20-ahb", }, | ||
275 | {}, | ||
276 | }; | ||
277 | |||
278 | static struct platform_driver tegra_ahb_driver = { | ||
279 | .probe = tegra_ahb_probe, | ||
280 | .remove = __devexit_p(tegra_ahb_remove), | ||
281 | .driver = { | ||
282 | .name = DRV_NAME, | ||
283 | .owner = THIS_MODULE, | ||
284 | .of_match_table = tegra_ahb_of_match, | ||
285 | .pm = &tegra_ahb_pm, | ||
286 | }, | ||
287 | }; | ||
288 | module_platform_driver(tegra_ahb_driver); | ||
289 | |||
290 | MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>"); | ||
291 | MODULE_DESCRIPTION("Tegra AHB driver"); | ||
292 | MODULE_LICENSE("GPL v2"); | ||
293 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c index f6e9b572b998..c64917ec313d 100644 --- a/drivers/dma/ep93xx_dma.c +++ b/drivers/dma/ep93xx_dma.c | |||
@@ -71,6 +71,7 @@ | |||
71 | #define M2M_CONTROL_TM_SHIFT 13 | 71 | #define M2M_CONTROL_TM_SHIFT 13 |
72 | #define M2M_CONTROL_TM_TX (1 << M2M_CONTROL_TM_SHIFT) | 72 | #define M2M_CONTROL_TM_TX (1 << M2M_CONTROL_TM_SHIFT) |
73 | #define M2M_CONTROL_TM_RX (2 << M2M_CONTROL_TM_SHIFT) | 73 | #define M2M_CONTROL_TM_RX (2 << M2M_CONTROL_TM_SHIFT) |
74 | #define M2M_CONTROL_NFBINT BIT(21) | ||
74 | #define M2M_CONTROL_RSS_SHIFT 22 | 75 | #define M2M_CONTROL_RSS_SHIFT 22 |
75 | #define M2M_CONTROL_RSS_SSPRX (1 << M2M_CONTROL_RSS_SHIFT) | 76 | #define M2M_CONTROL_RSS_SSPRX (1 << M2M_CONTROL_RSS_SHIFT) |
76 | #define M2M_CONTROL_RSS_SSPTX (2 << M2M_CONTROL_RSS_SHIFT) | 77 | #define M2M_CONTROL_RSS_SSPTX (2 << M2M_CONTROL_RSS_SHIFT) |
@@ -79,7 +80,22 @@ | |||
79 | #define M2M_CONTROL_PWSC_SHIFT 25 | 80 | #define M2M_CONTROL_PWSC_SHIFT 25 |
80 | 81 | ||
81 | #define M2M_INTERRUPT 0x0004 | 82 | #define M2M_INTERRUPT 0x0004 |
82 | #define M2M_INTERRUPT_DONEINT BIT(1) | 83 | #define M2M_INTERRUPT_MASK 6 |
84 | |||
85 | #define M2M_STATUS 0x000c | ||
86 | #define M2M_STATUS_CTL_SHIFT 1 | ||
87 | #define M2M_STATUS_CTL_IDLE (0 << M2M_STATUS_CTL_SHIFT) | ||
88 | #define M2M_STATUS_CTL_STALL (1 << M2M_STATUS_CTL_SHIFT) | ||
89 | #define M2M_STATUS_CTL_MEMRD (2 << M2M_STATUS_CTL_SHIFT) | ||
90 | #define M2M_STATUS_CTL_MEMWR (3 << M2M_STATUS_CTL_SHIFT) | ||
91 | #define M2M_STATUS_CTL_BWCWAIT (4 << M2M_STATUS_CTL_SHIFT) | ||
92 | #define M2M_STATUS_CTL_MASK (7 << M2M_STATUS_CTL_SHIFT) | ||
93 | #define M2M_STATUS_BUF_SHIFT 4 | ||
94 | #define M2M_STATUS_BUF_NO (0 << M2M_STATUS_BUF_SHIFT) | ||
95 | #define M2M_STATUS_BUF_ON (1 << M2M_STATUS_BUF_SHIFT) | ||
96 | #define M2M_STATUS_BUF_NEXT (2 << M2M_STATUS_BUF_SHIFT) | ||
97 | #define M2M_STATUS_BUF_MASK (3 << M2M_STATUS_BUF_SHIFT) | ||
98 | #define M2M_STATUS_DONE BIT(6) | ||
83 | 99 | ||
84 | #define M2M_BCR0 0x0010 | 100 | #define M2M_BCR0 0x0010 |
85 | #define M2M_BCR1 0x0014 | 101 | #define M2M_BCR1 0x0014 |
@@ -426,15 +442,6 @@ static int m2p_hw_interrupt(struct ep93xx_dma_chan *edmac) | |||
426 | 442 | ||
427 | /* | 443 | /* |
428 | * M2M DMA implementation | 444 | * M2M DMA implementation |
429 | * | ||
430 | * For the M2M transfers we don't use NFB at all. This is because it simply | ||
431 | * doesn't work well with memcpy transfers. When you submit both buffers it is | ||
432 | * extremely unlikely that you get an NFB interrupt, but it instead reports | ||
433 | * DONE interrupt and both buffers are already transferred which means that we | ||
434 | * weren't able to update the next buffer. | ||
435 | * | ||
436 | * So for now we "simulate" NFB by just submitting buffer after buffer | ||
437 | * without double buffering. | ||
438 | */ | 445 | */ |
439 | 446 | ||
440 | static int m2m_hw_setup(struct ep93xx_dma_chan *edmac) | 447 | static int m2m_hw_setup(struct ep93xx_dma_chan *edmac) |
@@ -543,6 +550,11 @@ static void m2m_hw_submit(struct ep93xx_dma_chan *edmac) | |||
543 | m2m_fill_desc(edmac); | 550 | m2m_fill_desc(edmac); |
544 | control |= M2M_CONTROL_DONEINT; | 551 | control |= M2M_CONTROL_DONEINT; |
545 | 552 | ||
553 | if (ep93xx_dma_advance_active(edmac)) { | ||
554 | m2m_fill_desc(edmac); | ||
555 | control |= M2M_CONTROL_NFBINT; | ||
556 | } | ||
557 | |||
546 | /* | 558 | /* |
547 | * Now we can finally enable the channel. For M2M channel this must be | 559 | * Now we can finally enable the channel. For M2M channel this must be |
548 | * done _after_ the BCRx registers are programmed. | 560 | * done _after_ the BCRx registers are programmed. |
@@ -560,32 +572,89 @@ static void m2m_hw_submit(struct ep93xx_dma_chan *edmac) | |||
560 | } | 572 | } |
561 | } | 573 | } |
562 | 574 | ||
575 | /* | ||
576 | * According to EP93xx User's Guide, we should receive DONE interrupt when all | ||
577 | * M2M DMA controller transactions complete normally. This is not always the | ||
578 | * case - sometimes EP93xx M2M DMA asserts DONE interrupt when the DMA channel | ||
579 | * is still running (channel Buffer FSM in DMA_BUF_ON state, and channel | ||
580 | * Control FSM in DMA_MEM_RD state, observed at least in IDE-DMA operation). | ||
581 | * In effect, disabling the channel when only DONE bit is set could stop | ||
582 | * currently running DMA transfer. To avoid this, we use Buffer FSM and | ||
583 | * Control FSM to check current state of DMA channel. | ||
584 | */ | ||
563 | static int m2m_hw_interrupt(struct ep93xx_dma_chan *edmac) | 585 | static int m2m_hw_interrupt(struct ep93xx_dma_chan *edmac) |
564 | { | 586 | { |
587 | u32 status = readl(edmac->regs + M2M_STATUS); | ||
588 | u32 ctl_fsm = status & M2M_STATUS_CTL_MASK; | ||
589 | u32 buf_fsm = status & M2M_STATUS_BUF_MASK; | ||
590 | bool done = status & M2M_STATUS_DONE; | ||
591 | bool last_done; | ||
565 | u32 control; | 592 | u32 control; |
593 | struct ep93xx_dma_desc *desc; | ||
566 | 594 | ||
567 | if (!(readl(edmac->regs + M2M_INTERRUPT) & M2M_INTERRUPT_DONEINT)) | 595 | /* Accept only DONE and NFB interrupts */ |
596 | if (!(readl(edmac->regs + M2M_INTERRUPT) & M2M_INTERRUPT_MASK)) | ||
568 | return INTERRUPT_UNKNOWN; | 597 | return INTERRUPT_UNKNOWN; |
569 | 598 | ||
570 | /* Clear the DONE bit */ | 599 | if (done) { |
571 | writel(0, edmac->regs + M2M_INTERRUPT); | 600 | /* Clear the DONE bit */ |
601 | writel(0, edmac->regs + M2M_INTERRUPT); | ||
602 | } | ||
572 | 603 | ||
573 | /* Disable interrupts and the channel */ | 604 | /* |
574 | control = readl(edmac->regs + M2M_CONTROL); | 605 | * Check whether we are done with descriptors or not. This, together |
575 | control &= ~(M2M_CONTROL_DONEINT | M2M_CONTROL_ENABLE); | 606 | * with DMA channel state, determines action to take in interrupt. |
576 | writel(control, edmac->regs + M2M_CONTROL); | 607 | */ |
608 | desc = ep93xx_dma_get_active(edmac); | ||
609 | last_done = !desc || desc->txd.cookie; | ||
577 | 610 | ||
578 | /* | 611 | /* |
579 | * Since we only get DONE interrupt we have to find out ourselves | 612 | * Use M2M DMA Buffer FSM and Control FSM to check current state of |
580 | * whether there still is something to process. So we try to advance | 613 | * DMA channel. Using DONE and NFB bits from channel status register |
581 | * the chain an see whether it succeeds. | 614 | * or bits from channel interrupt register is not reliable. |
582 | */ | 615 | */ |
583 | if (ep93xx_dma_advance_active(edmac)) { | 616 | if (!last_done && |
584 | edmac->edma->hw_submit(edmac); | 617 | (buf_fsm == M2M_STATUS_BUF_NO || |
585 | return INTERRUPT_NEXT_BUFFER; | 618 | buf_fsm == M2M_STATUS_BUF_ON)) { |
619 | /* | ||
620 | * Two buffers are ready for update when Buffer FSM is in | ||
621 | * DMA_NO_BUF state. Only one buffer can be prepared without | ||
622 | * disabling the channel or polling the DONE bit. | ||
623 | * To simplify things, always prepare only one buffer. | ||
624 | */ | ||
625 | if (ep93xx_dma_advance_active(edmac)) { | ||
626 | m2m_fill_desc(edmac); | ||
627 | if (done && !edmac->chan.private) { | ||
628 | /* Software trigger for memcpy channel */ | ||
629 | control = readl(edmac->regs + M2M_CONTROL); | ||
630 | control |= M2M_CONTROL_START; | ||
631 | writel(control, edmac->regs + M2M_CONTROL); | ||
632 | } | ||
633 | return INTERRUPT_NEXT_BUFFER; | ||
634 | } else { | ||
635 | last_done = true; | ||
636 | } | ||
637 | } | ||
638 | |||
639 | /* | ||
640 | * Disable the channel only when Buffer FSM is in DMA_NO_BUF state | ||
641 | * and Control FSM is in DMA_STALL state. | ||
642 | */ | ||
643 | if (last_done && | ||
644 | buf_fsm == M2M_STATUS_BUF_NO && | ||
645 | ctl_fsm == M2M_STATUS_CTL_STALL) { | ||
646 | /* Disable interrupts and the channel */ | ||
647 | control = readl(edmac->regs + M2M_CONTROL); | ||
648 | control &= ~(M2M_CONTROL_DONEINT | M2M_CONTROL_NFBINT | ||
649 | | M2M_CONTROL_ENABLE); | ||
650 | writel(control, edmac->regs + M2M_CONTROL); | ||
651 | return INTERRUPT_DONE; | ||
586 | } | 652 | } |
587 | 653 | ||
588 | return INTERRUPT_DONE; | 654 | /* |
655 | * Nothing to do this time. | ||
656 | */ | ||
657 | return INTERRUPT_NEXT_BUFFER; | ||
589 | } | 658 | } |
590 | 659 | ||
591 | /* | 660 | /* |
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 29fe1b2be1c1..7f7b72464a37 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c | |||
@@ -311,7 +311,15 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) | |||
311 | if (pdata->enable_rotary0 || pdata->enable_rotary1) | 311 | if (pdata->enable_rotary0 || pdata->enable_rotary1) |
312 | pxa27x_keypad_scan_rotary(keypad); | 312 | pxa27x_keypad_scan_rotary(keypad); |
313 | 313 | ||
314 | new_state = KPDK_DK(kpdk) & keypad->direct_key_mask; | 314 | /* |
315 | * The KPDR_DK only output the key pin level, so it relates to board, | ||
316 | * and low level may be active. | ||
317 | */ | ||
318 | if (pdata->direct_key_low_active) | ||
319 | new_state = ~KPDK_DK(kpdk) & keypad->direct_key_mask; | ||
320 | else | ||
321 | new_state = KPDK_DK(kpdk) & keypad->direct_key_mask; | ||
322 | |||
315 | bits_changed = keypad->direct_key_state ^ new_state; | 323 | bits_changed = keypad->direct_key_state ^ new_state; |
316 | 324 | ||
317 | if (bits_changed == 0) | 325 | if (bits_changed == 0) |
@@ -383,7 +391,14 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad) | |||
383 | if (pdata->direct_key_num > direct_key_num) | 391 | if (pdata->direct_key_num > direct_key_num) |
384 | direct_key_num = pdata->direct_key_num; | 392 | direct_key_num = pdata->direct_key_num; |
385 | 393 | ||
386 | keypad->direct_key_mask = ((2 << direct_key_num) - 1) & ~mask; | 394 | /* |
395 | * Direct keys usage may not start from KP_DKIN0, check the platfrom | ||
396 | * mask data to config the specific. | ||
397 | */ | ||
398 | if (pdata->direct_key_mask) | ||
399 | keypad->direct_key_mask = pdata->direct_key_mask; | ||
400 | else | ||
401 | keypad->direct_key_mask = ((1 << direct_key_num) - 1) & ~mask; | ||
387 | 402 | ||
388 | /* enable direct key */ | 403 | /* enable direct key */ |
389 | if (direct_key_num) | 404 | if (direct_key_num) |
@@ -399,7 +414,7 @@ static int pxa27x_keypad_open(struct input_dev *dev) | |||
399 | struct pxa27x_keypad *keypad = input_get_drvdata(dev); | 414 | struct pxa27x_keypad *keypad = input_get_drvdata(dev); |
400 | 415 | ||
401 | /* Enable unit clock */ | 416 | /* Enable unit clock */ |
402 | clk_enable(keypad->clk); | 417 | clk_prepare_enable(keypad->clk); |
403 | pxa27x_keypad_config(keypad); | 418 | pxa27x_keypad_config(keypad); |
404 | 419 | ||
405 | return 0; | 420 | return 0; |
@@ -410,7 +425,7 @@ static void pxa27x_keypad_close(struct input_dev *dev) | |||
410 | struct pxa27x_keypad *keypad = input_get_drvdata(dev); | 425 | struct pxa27x_keypad *keypad = input_get_drvdata(dev); |
411 | 426 | ||
412 | /* Disable clock unit */ | 427 | /* Disable clock unit */ |
413 | clk_disable(keypad->clk); | 428 | clk_disable_unprepare(keypad->clk); |
414 | } | 429 | } |
415 | 430 | ||
416 | #ifdef CONFIG_PM | 431 | #ifdef CONFIG_PM |
@@ -419,10 +434,14 @@ static int pxa27x_keypad_suspend(struct device *dev) | |||
419 | struct platform_device *pdev = to_platform_device(dev); | 434 | struct platform_device *pdev = to_platform_device(dev); |
420 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); | 435 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); |
421 | 436 | ||
422 | clk_disable(keypad->clk); | 437 | /* |
423 | 438 | * If the keypad is used a wake up source, clock can not be disabled. | |
439 | * Or it can not detect the key pressing. | ||
440 | */ | ||
424 | if (device_may_wakeup(&pdev->dev)) | 441 | if (device_may_wakeup(&pdev->dev)) |
425 | enable_irq_wake(keypad->irq); | 442 | enable_irq_wake(keypad->irq); |
443 | else | ||
444 | clk_disable_unprepare(keypad->clk); | ||
426 | 445 | ||
427 | return 0; | 446 | return 0; |
428 | } | 447 | } |
@@ -433,19 +452,24 @@ static int pxa27x_keypad_resume(struct device *dev) | |||
433 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); | 452 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); |
434 | struct input_dev *input_dev = keypad->input_dev; | 453 | struct input_dev *input_dev = keypad->input_dev; |
435 | 454 | ||
436 | if (device_may_wakeup(&pdev->dev)) | 455 | /* |
456 | * If the keypad is used as wake up source, the clock is not turned | ||
457 | * off. So do not need configure it again. | ||
458 | */ | ||
459 | if (device_may_wakeup(&pdev->dev)) { | ||
437 | disable_irq_wake(keypad->irq); | 460 | disable_irq_wake(keypad->irq); |
461 | } else { | ||
462 | mutex_lock(&input_dev->mutex); | ||
438 | 463 | ||
439 | mutex_lock(&input_dev->mutex); | 464 | if (input_dev->users) { |
465 | /* Enable unit clock */ | ||
466 | clk_prepare_enable(keypad->clk); | ||
467 | pxa27x_keypad_config(keypad); | ||
468 | } | ||
440 | 469 | ||
441 | if (input_dev->users) { | 470 | mutex_unlock(&input_dev->mutex); |
442 | /* Enable unit clock */ | ||
443 | clk_enable(keypad->clk); | ||
444 | pxa27x_keypad_config(keypad); | ||
445 | } | 471 | } |
446 | 472 | ||
447 | mutex_unlock(&input_dev->mutex); | ||
448 | |||
449 | return 0; | 473 | return 0; |
450 | } | 474 | } |
451 | 475 | ||
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index c69843742bb0..340893727538 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig | |||
@@ -162,4 +162,25 @@ config TEGRA_IOMMU_SMMU | |||
162 | space through the SMMU (System Memory Management Unit) | 162 | space through the SMMU (System Memory Management Unit) |
163 | hardware included on Tegra SoCs. | 163 | hardware included on Tegra SoCs. |
164 | 164 | ||
165 | config EXYNOS_IOMMU | ||
166 | bool "Exynos IOMMU Support" | ||
167 | depends on ARCH_EXYNOS && EXYNOS_DEV_SYSMMU | ||
168 | select IOMMU_API | ||
169 | help | ||
170 | Support for the IOMMU(System MMU) of Samsung Exynos application | ||
171 | processor family. This enables H/W multimedia accellerators to see | ||
172 | non-linear physical memory chunks as a linear memory in their | ||
173 | address spaces | ||
174 | |||
175 | If unsure, say N here. | ||
176 | |||
177 | config EXYNOS_IOMMU_DEBUG | ||
178 | bool "Debugging log for Exynos IOMMU" | ||
179 | depends on EXYNOS_IOMMU | ||
180 | help | ||
181 | Select this to see the detailed log message that shows what | ||
182 | happens in the IOMMU driver | ||
183 | |||
184 | Say N unless you need kernel log message for IOMMU debugging | ||
185 | |||
165 | endif # IOMMU_SUPPORT | 186 | endif # IOMMU_SUPPORT |
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 3e5e82ae9f0d..76e54ef796de 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile | |||
@@ -10,3 +10,4 @@ obj-$(CONFIG_OMAP_IOVMM) += omap-iovmm.o | |||
10 | obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o | 10 | obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o |
11 | obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o | 11 | obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o |
12 | obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o | 12 | obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o |
13 | obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o | ||
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c new file mode 100644 index 000000000000..9a114b9ff170 --- /dev/null +++ b/drivers/iommu/exynos-iommu.c | |||
@@ -0,0 +1,1076 @@ | |||
1 | /* linux/drivers/iommu/exynos_iommu.c | ||
2 | * | ||
3 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifdef CONFIG_EXYNOS_IOMMU_DEBUG | ||
12 | #define DEBUG | ||
13 | #endif | ||
14 | |||
15 | #include <linux/io.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/pm_runtime.h> | ||
20 | #include <linux/clk.h> | ||
21 | #include <linux/err.h> | ||
22 | #include <linux/mm.h> | ||
23 | #include <linux/iommu.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/list.h> | ||
26 | #include <linux/memblock.h> | ||
27 | #include <linux/export.h> | ||
28 | |||
29 | #include <asm/cacheflush.h> | ||
30 | #include <asm/pgtable.h> | ||
31 | |||
32 | #include <mach/sysmmu.h> | ||
33 | |||
34 | /* We does not consider super section mapping (16MB) */ | ||
35 | #define SECT_ORDER 20 | ||
36 | #define LPAGE_ORDER 16 | ||
37 | #define SPAGE_ORDER 12 | ||
38 | |||
39 | #define SECT_SIZE (1 << SECT_ORDER) | ||
40 | #define LPAGE_SIZE (1 << LPAGE_ORDER) | ||
41 | #define SPAGE_SIZE (1 << SPAGE_ORDER) | ||
42 | |||
43 | #define SECT_MASK (~(SECT_SIZE - 1)) | ||
44 | #define LPAGE_MASK (~(LPAGE_SIZE - 1)) | ||
45 | #define SPAGE_MASK (~(SPAGE_SIZE - 1)) | ||
46 | |||
47 | #define lv1ent_fault(sent) (((*(sent) & 3) == 0) || ((*(sent) & 3) == 3)) | ||
48 | #define lv1ent_page(sent) ((*(sent) & 3) == 1) | ||
49 | #define lv1ent_section(sent) ((*(sent) & 3) == 2) | ||
50 | |||
51 | #define lv2ent_fault(pent) ((*(pent) & 3) == 0) | ||
52 | #define lv2ent_small(pent) ((*(pent) & 2) == 2) | ||
53 | #define lv2ent_large(pent) ((*(pent) & 3) == 1) | ||
54 | |||
55 | #define section_phys(sent) (*(sent) & SECT_MASK) | ||
56 | #define section_offs(iova) ((iova) & 0xFFFFF) | ||
57 | #define lpage_phys(pent) (*(pent) & LPAGE_MASK) | ||
58 | #define lpage_offs(iova) ((iova) & 0xFFFF) | ||
59 | #define spage_phys(pent) (*(pent) & SPAGE_MASK) | ||
60 | #define spage_offs(iova) ((iova) & 0xFFF) | ||
61 | |||
62 | #define lv1ent_offset(iova) ((iova) >> SECT_ORDER) | ||
63 | #define lv2ent_offset(iova) (((iova) & 0xFF000) >> SPAGE_ORDER) | ||
64 | |||
65 | #define NUM_LV1ENTRIES 4096 | ||
66 | #define NUM_LV2ENTRIES 256 | ||
67 | |||
68 | #define LV2TABLE_SIZE (NUM_LV2ENTRIES * sizeof(long)) | ||
69 | |||
70 | #define SPAGES_PER_LPAGE (LPAGE_SIZE / SPAGE_SIZE) | ||
71 | |||
72 | #define lv2table_base(sent) (*(sent) & 0xFFFFFC00) | ||
73 | |||
74 | #define mk_lv1ent_sect(pa) ((pa) | 2) | ||
75 | #define mk_lv1ent_page(pa) ((pa) | 1) | ||
76 | #define mk_lv2ent_lpage(pa) ((pa) | 1) | ||
77 | #define mk_lv2ent_spage(pa) ((pa) | 2) | ||
78 | |||
79 | #define CTRL_ENABLE 0x5 | ||
80 | #define CTRL_BLOCK 0x7 | ||
81 | #define CTRL_DISABLE 0x0 | ||
82 | |||
83 | #define REG_MMU_CTRL 0x000 | ||
84 | #define REG_MMU_CFG 0x004 | ||
85 | #define REG_MMU_STATUS 0x008 | ||
86 | #define REG_MMU_FLUSH 0x00C | ||
87 | #define REG_MMU_FLUSH_ENTRY 0x010 | ||
88 | #define REG_PT_BASE_ADDR 0x014 | ||
89 | #define REG_INT_STATUS 0x018 | ||
90 | #define REG_INT_CLEAR 0x01C | ||
91 | |||
92 | #define REG_PAGE_FAULT_ADDR 0x024 | ||
93 | #define REG_AW_FAULT_ADDR 0x028 | ||
94 | #define REG_AR_FAULT_ADDR 0x02C | ||
95 | #define REG_DEFAULT_SLAVE_ADDR 0x030 | ||
96 | |||
97 | #define REG_MMU_VERSION 0x034 | ||
98 | |||
99 | #define REG_PB0_SADDR 0x04C | ||
100 | #define REG_PB0_EADDR 0x050 | ||
101 | #define REG_PB1_SADDR 0x054 | ||
102 | #define REG_PB1_EADDR 0x058 | ||
103 | |||
104 | static unsigned long *section_entry(unsigned long *pgtable, unsigned long iova) | ||
105 | { | ||
106 | return pgtable + lv1ent_offset(iova); | ||
107 | } | ||
108 | |||
109 | static unsigned long *page_entry(unsigned long *sent, unsigned long iova) | ||
110 | { | ||
111 | return (unsigned long *)__va(lv2table_base(sent)) + lv2ent_offset(iova); | ||
112 | } | ||
113 | |||
114 | enum exynos_sysmmu_inttype { | ||
115 | SYSMMU_PAGEFAULT, | ||
116 | SYSMMU_AR_MULTIHIT, | ||
117 | SYSMMU_AW_MULTIHIT, | ||
118 | SYSMMU_BUSERROR, | ||
119 | SYSMMU_AR_SECURITY, | ||
120 | SYSMMU_AR_ACCESS, | ||
121 | SYSMMU_AW_SECURITY, | ||
122 | SYSMMU_AW_PROTECTION, /* 7 */ | ||
123 | SYSMMU_FAULT_UNKNOWN, | ||
124 | SYSMMU_FAULTS_NUM | ||
125 | }; | ||
126 | |||
127 | /* | ||
128 | * @itype: type of fault. | ||
129 | * @pgtable_base: the physical address of page table base. This is 0 if @itype | ||
130 | * is SYSMMU_BUSERROR. | ||
131 | * @fault_addr: the device (virtual) address that the System MMU tried to | ||
132 | * translated. This is 0 if @itype is SYSMMU_BUSERROR. | ||
133 | */ | ||
134 | typedef int (*sysmmu_fault_handler_t)(enum exynos_sysmmu_inttype itype, | ||
135 | unsigned long pgtable_base, unsigned long fault_addr); | ||
136 | |||
137 | static unsigned short fault_reg_offset[SYSMMU_FAULTS_NUM] = { | ||
138 | REG_PAGE_FAULT_ADDR, | ||
139 | REG_AR_FAULT_ADDR, | ||
140 | REG_AW_FAULT_ADDR, | ||
141 | REG_DEFAULT_SLAVE_ADDR, | ||
142 | REG_AR_FAULT_ADDR, | ||
143 | REG_AR_FAULT_ADDR, | ||
144 | REG_AW_FAULT_ADDR, | ||
145 | REG_AW_FAULT_ADDR | ||
146 | }; | ||
147 | |||
148 | static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = { | ||
149 | "PAGE FAULT", | ||
150 | "AR MULTI-HIT FAULT", | ||
151 | "AW MULTI-HIT FAULT", | ||
152 | "BUS ERROR", | ||
153 | "AR SECURITY PROTECTION FAULT", | ||
154 | "AR ACCESS PROTECTION FAULT", | ||
155 | "AW SECURITY PROTECTION FAULT", | ||
156 | "AW ACCESS PROTECTION FAULT", | ||
157 | "UNKNOWN FAULT" | ||
158 | }; | ||
159 | |||
160 | struct exynos_iommu_domain { | ||
161 | struct list_head clients; /* list of sysmmu_drvdata.node */ | ||
162 | unsigned long *pgtable; /* lv1 page table, 16KB */ | ||
163 | short *lv2entcnt; /* free lv2 entry counter for each section */ | ||
164 | spinlock_t lock; /* lock for this structure */ | ||
165 | spinlock_t pgtablelock; /* lock for modifying page table @ pgtable */ | ||
166 | }; | ||
167 | |||
168 | struct sysmmu_drvdata { | ||
169 | struct list_head node; /* entry of exynos_iommu_domain.clients */ | ||
170 | struct device *sysmmu; /* System MMU's device descriptor */ | ||
171 | struct device *dev; /* Owner of system MMU */ | ||
172 | char *dbgname; | ||
173 | int nsfrs; | ||
174 | void __iomem **sfrbases; | ||
175 | struct clk *clk[2]; | ||
176 | int activations; | ||
177 | rwlock_t lock; | ||
178 | struct iommu_domain *domain; | ||
179 | sysmmu_fault_handler_t fault_handler; | ||
180 | unsigned long pgtable; | ||
181 | }; | ||
182 | |||
183 | static bool set_sysmmu_active(struct sysmmu_drvdata *data) | ||
184 | { | ||
185 | /* return true if the System MMU was not active previously | ||
186 | and it needs to be initialized */ | ||
187 | return ++data->activations == 1; | ||
188 | } | ||
189 | |||
190 | static bool set_sysmmu_inactive(struct sysmmu_drvdata *data) | ||
191 | { | ||
192 | /* return true if the System MMU is needed to be disabled */ | ||
193 | BUG_ON(data->activations < 1); | ||
194 | return --data->activations == 0; | ||
195 | } | ||
196 | |||
197 | static bool is_sysmmu_active(struct sysmmu_drvdata *data) | ||
198 | { | ||
199 | return data->activations > 0; | ||
200 | } | ||
201 | |||
202 | static void sysmmu_unblock(void __iomem *sfrbase) | ||
203 | { | ||
204 | __raw_writel(CTRL_ENABLE, sfrbase + REG_MMU_CTRL); | ||
205 | } | ||
206 | |||
207 | static bool sysmmu_block(void __iomem *sfrbase) | ||
208 | { | ||
209 | int i = 120; | ||
210 | |||
211 | __raw_writel(CTRL_BLOCK, sfrbase + REG_MMU_CTRL); | ||
212 | while ((i > 0) && !(__raw_readl(sfrbase + REG_MMU_STATUS) & 1)) | ||
213 | --i; | ||
214 | |||
215 | if (!(__raw_readl(sfrbase + REG_MMU_STATUS) & 1)) { | ||
216 | sysmmu_unblock(sfrbase); | ||
217 | return false; | ||
218 | } | ||
219 | |||
220 | return true; | ||
221 | } | ||
222 | |||
223 | static void __sysmmu_tlb_invalidate(void __iomem *sfrbase) | ||
224 | { | ||
225 | __raw_writel(0x1, sfrbase + REG_MMU_FLUSH); | ||
226 | } | ||
227 | |||
228 | static void __sysmmu_tlb_invalidate_entry(void __iomem *sfrbase, | ||
229 | unsigned long iova) | ||
230 | { | ||
231 | __raw_writel((iova & SPAGE_MASK) | 1, sfrbase + REG_MMU_FLUSH_ENTRY); | ||
232 | } | ||
233 | |||
234 | static void __sysmmu_set_ptbase(void __iomem *sfrbase, | ||
235 | unsigned long pgd) | ||
236 | { | ||
237 | __raw_writel(0x1, sfrbase + REG_MMU_CFG); /* 16KB LV1, LRU */ | ||
238 | __raw_writel(pgd, sfrbase + REG_PT_BASE_ADDR); | ||
239 | |||
240 | __sysmmu_tlb_invalidate(sfrbase); | ||
241 | } | ||
242 | |||
243 | static void __sysmmu_set_prefbuf(void __iomem *sfrbase, unsigned long base, | ||
244 | unsigned long size, int idx) | ||
245 | { | ||
246 | __raw_writel(base, sfrbase + REG_PB0_SADDR + idx * 8); | ||
247 | __raw_writel(size - 1 + base, sfrbase + REG_PB0_EADDR + idx * 8); | ||
248 | } | ||
249 | |||
250 | void exynos_sysmmu_set_prefbuf(struct device *dev, | ||
251 | unsigned long base0, unsigned long size0, | ||
252 | unsigned long base1, unsigned long size1) | ||
253 | { | ||
254 | struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); | ||
255 | unsigned long flags; | ||
256 | int i; | ||
257 | |||
258 | BUG_ON((base0 + size0) <= base0); | ||
259 | BUG_ON((size1 > 0) && ((base1 + size1) <= base1)); | ||
260 | |||
261 | read_lock_irqsave(&data->lock, flags); | ||
262 | if (!is_sysmmu_active(data)) | ||
263 | goto finish; | ||
264 | |||
265 | for (i = 0; i < data->nsfrs; i++) { | ||
266 | if ((readl(data->sfrbases[i] + REG_MMU_VERSION) >> 28) == 3) { | ||
267 | if (!sysmmu_block(data->sfrbases[i])) | ||
268 | continue; | ||
269 | |||
270 | if (size1 == 0) { | ||
271 | if (size0 <= SZ_128K) { | ||
272 | base1 = base0; | ||
273 | size1 = size0; | ||
274 | } else { | ||
275 | size1 = size0 - | ||
276 | ALIGN(size0 / 2, SZ_64K); | ||
277 | size0 = size0 - size1; | ||
278 | base1 = base0 + size0; | ||
279 | } | ||
280 | } | ||
281 | |||
282 | __sysmmu_set_prefbuf( | ||
283 | data->sfrbases[i], base0, size0, 0); | ||
284 | __sysmmu_set_prefbuf( | ||
285 | data->sfrbases[i], base1, size1, 1); | ||
286 | |||
287 | sysmmu_unblock(data->sfrbases[i]); | ||
288 | } | ||
289 | } | ||
290 | finish: | ||
291 | read_unlock_irqrestore(&data->lock, flags); | ||
292 | } | ||
293 | |||
294 | static void __set_fault_handler(struct sysmmu_drvdata *data, | ||
295 | sysmmu_fault_handler_t handler) | ||
296 | { | ||
297 | unsigned long flags; | ||
298 | |||
299 | write_lock_irqsave(&data->lock, flags); | ||
300 | data->fault_handler = handler; | ||
301 | write_unlock_irqrestore(&data->lock, flags); | ||
302 | } | ||
303 | |||
304 | void exynos_sysmmu_set_fault_handler(struct device *dev, | ||
305 | sysmmu_fault_handler_t handler) | ||
306 | { | ||
307 | struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); | ||
308 | |||
309 | __set_fault_handler(data, handler); | ||
310 | } | ||
311 | |||
312 | static int default_fault_handler(enum exynos_sysmmu_inttype itype, | ||
313 | unsigned long pgtable_base, unsigned long fault_addr) | ||
314 | { | ||
315 | unsigned long *ent; | ||
316 | |||
317 | if ((itype >= SYSMMU_FAULTS_NUM) || (itype < SYSMMU_PAGEFAULT)) | ||
318 | itype = SYSMMU_FAULT_UNKNOWN; | ||
319 | |||
320 | pr_err("%s occured at 0x%lx(Page table base: 0x%lx)\n", | ||
321 | sysmmu_fault_name[itype], fault_addr, pgtable_base); | ||
322 | |||
323 | ent = section_entry(__va(pgtable_base), fault_addr); | ||
324 | pr_err("\tLv1 entry: 0x%lx\n", *ent); | ||
325 | |||
326 | if (lv1ent_page(ent)) { | ||
327 | ent = page_entry(ent, fault_addr); | ||
328 | pr_err("\t Lv2 entry: 0x%lx\n", *ent); | ||
329 | } | ||
330 | |||
331 | pr_err("Generating Kernel OOPS... because it is unrecoverable.\n"); | ||
332 | |||
333 | BUG(); | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) | ||
339 | { | ||
340 | /* SYSMMU is in blocked when interrupt occurred. */ | ||
341 | struct sysmmu_drvdata *data = dev_id; | ||
342 | struct resource *irqres; | ||
343 | struct platform_device *pdev; | ||
344 | enum exynos_sysmmu_inttype itype; | ||
345 | unsigned long addr = -1; | ||
346 | |||
347 | int i, ret = -ENOSYS; | ||
348 | |||
349 | read_lock(&data->lock); | ||
350 | |||
351 | WARN_ON(!is_sysmmu_active(data)); | ||
352 | |||
353 | pdev = to_platform_device(data->sysmmu); | ||
354 | for (i = 0; i < (pdev->num_resources / 2); i++) { | ||
355 | irqres = platform_get_resource(pdev, IORESOURCE_IRQ, i); | ||
356 | if (irqres && ((int)irqres->start == irq)) | ||
357 | break; | ||
358 | } | ||
359 | |||
360 | if (i == pdev->num_resources) { | ||
361 | itype = SYSMMU_FAULT_UNKNOWN; | ||
362 | } else { | ||
363 | itype = (enum exynos_sysmmu_inttype) | ||
364 | __ffs(__raw_readl(data->sfrbases[i] + REG_INT_STATUS)); | ||
365 | if (WARN_ON(!((itype >= 0) && (itype < SYSMMU_FAULT_UNKNOWN)))) | ||
366 | itype = SYSMMU_FAULT_UNKNOWN; | ||
367 | else | ||
368 | addr = __raw_readl( | ||
369 | data->sfrbases[i] + fault_reg_offset[itype]); | ||
370 | } | ||
371 | |||
372 | if (data->domain) | ||
373 | ret = report_iommu_fault(data->domain, data->dev, | ||
374 | addr, itype); | ||
375 | |||
376 | if ((ret == -ENOSYS) && data->fault_handler) { | ||
377 | unsigned long base = data->pgtable; | ||
378 | if (itype != SYSMMU_FAULT_UNKNOWN) | ||
379 | base = __raw_readl( | ||
380 | data->sfrbases[i] + REG_PT_BASE_ADDR); | ||
381 | ret = data->fault_handler(itype, base, addr); | ||
382 | } | ||
383 | |||
384 | if (!ret && (itype != SYSMMU_FAULT_UNKNOWN)) | ||
385 | __raw_writel(1 << itype, data->sfrbases[i] + REG_INT_CLEAR); | ||
386 | else | ||
387 | dev_dbg(data->sysmmu, "(%s) %s is not handled.\n", | ||
388 | data->dbgname, sysmmu_fault_name[itype]); | ||
389 | |||
390 | if (itype != SYSMMU_FAULT_UNKNOWN) | ||
391 | sysmmu_unblock(data->sfrbases[i]); | ||
392 | |||
393 | read_unlock(&data->lock); | ||
394 | |||
395 | return IRQ_HANDLED; | ||
396 | } | ||
397 | |||
398 | static bool __exynos_sysmmu_disable(struct sysmmu_drvdata *data) | ||
399 | { | ||
400 | unsigned long flags; | ||
401 | bool disabled = false; | ||
402 | int i; | ||
403 | |||
404 | write_lock_irqsave(&data->lock, flags); | ||
405 | |||
406 | if (!set_sysmmu_inactive(data)) | ||
407 | goto finish; | ||
408 | |||
409 | for (i = 0; i < data->nsfrs; i++) | ||
410 | __raw_writel(CTRL_DISABLE, data->sfrbases[i] + REG_MMU_CTRL); | ||
411 | |||
412 | if (data->clk[1]) | ||
413 | clk_disable(data->clk[1]); | ||
414 | if (data->clk[0]) | ||
415 | clk_disable(data->clk[0]); | ||
416 | |||
417 | disabled = true; | ||
418 | data->pgtable = 0; | ||
419 | data->domain = NULL; | ||
420 | finish: | ||
421 | write_unlock_irqrestore(&data->lock, flags); | ||
422 | |||
423 | if (disabled) | ||
424 | dev_dbg(data->sysmmu, "(%s) Disabled\n", data->dbgname); | ||
425 | else | ||
426 | dev_dbg(data->sysmmu, "(%s) %d times left to be disabled\n", | ||
427 | data->dbgname, data->activations); | ||
428 | |||
429 | return disabled; | ||
430 | } | ||
431 | |||
432 | /* __exynos_sysmmu_enable: Enables System MMU | ||
433 | * | ||
434 | * returns -error if an error occurred and System MMU is not enabled, | ||
435 | * 0 if the System MMU has been just enabled and 1 if System MMU was already | ||
436 | * enabled before. | ||
437 | */ | ||
438 | static int __exynos_sysmmu_enable(struct sysmmu_drvdata *data, | ||
439 | unsigned long pgtable, struct iommu_domain *domain) | ||
440 | { | ||
441 | int i, ret = 0; | ||
442 | unsigned long flags; | ||
443 | |||
444 | write_lock_irqsave(&data->lock, flags); | ||
445 | |||
446 | if (!set_sysmmu_active(data)) { | ||
447 | if (WARN_ON(pgtable != data->pgtable)) { | ||
448 | ret = -EBUSY; | ||
449 | set_sysmmu_inactive(data); | ||
450 | } else { | ||
451 | ret = 1; | ||
452 | } | ||
453 | |||
454 | dev_dbg(data->sysmmu, "(%s) Already enabled\n", data->dbgname); | ||
455 | goto finish; | ||
456 | } | ||
457 | |||
458 | if (data->clk[0]) | ||
459 | clk_enable(data->clk[0]); | ||
460 | if (data->clk[1]) | ||
461 | clk_enable(data->clk[1]); | ||
462 | |||
463 | data->pgtable = pgtable; | ||
464 | |||
465 | for (i = 0; i < data->nsfrs; i++) { | ||
466 | __sysmmu_set_ptbase(data->sfrbases[i], pgtable); | ||
467 | |||
468 | if ((readl(data->sfrbases[i] + REG_MMU_VERSION) >> 28) == 3) { | ||
469 | /* System MMU version is 3.x */ | ||
470 | __raw_writel((1 << 12) | (2 << 28), | ||
471 | data->sfrbases[i] + REG_MMU_CFG); | ||
472 | __sysmmu_set_prefbuf(data->sfrbases[i], 0, -1, 0); | ||
473 | __sysmmu_set_prefbuf(data->sfrbases[i], 0, -1, 1); | ||
474 | } | ||
475 | |||
476 | __raw_writel(CTRL_ENABLE, data->sfrbases[i] + REG_MMU_CTRL); | ||
477 | } | ||
478 | |||
479 | data->domain = domain; | ||
480 | |||
481 | dev_dbg(data->sysmmu, "(%s) Enabled\n", data->dbgname); | ||
482 | finish: | ||
483 | write_unlock_irqrestore(&data->lock, flags); | ||
484 | |||
485 | return ret; | ||
486 | } | ||
487 | |||
488 | int exynos_sysmmu_enable(struct device *dev, unsigned long pgtable) | ||
489 | { | ||
490 | struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); | ||
491 | int ret; | ||
492 | |||
493 | BUG_ON(!memblock_is_memory(pgtable)); | ||
494 | |||
495 | ret = pm_runtime_get_sync(data->sysmmu); | ||
496 | if (ret < 0) { | ||
497 | dev_dbg(data->sysmmu, "(%s) Failed to enable\n", data->dbgname); | ||
498 | return ret; | ||
499 | } | ||
500 | |||
501 | ret = __exynos_sysmmu_enable(data, pgtable, NULL); | ||
502 | if (WARN_ON(ret < 0)) { | ||
503 | pm_runtime_put(data->sysmmu); | ||
504 | dev_err(data->sysmmu, | ||
505 | "(%s) Already enabled with page table %#lx\n", | ||
506 | data->dbgname, data->pgtable); | ||
507 | } else { | ||
508 | data->dev = dev; | ||
509 | } | ||
510 | |||
511 | return ret; | ||
512 | } | ||
513 | |||
514 | bool exynos_sysmmu_disable(struct device *dev) | ||
515 | { | ||
516 | struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); | ||
517 | bool disabled; | ||
518 | |||
519 | disabled = __exynos_sysmmu_disable(data); | ||
520 | pm_runtime_put(data->sysmmu); | ||
521 | |||
522 | return disabled; | ||
523 | } | ||
524 | |||
525 | static void sysmmu_tlb_invalidate_entry(struct device *dev, unsigned long iova) | ||
526 | { | ||
527 | unsigned long flags; | ||
528 | struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); | ||
529 | |||
530 | read_lock_irqsave(&data->lock, flags); | ||
531 | |||
532 | if (is_sysmmu_active(data)) { | ||
533 | int i; | ||
534 | for (i = 0; i < data->nsfrs; i++) { | ||
535 | if (sysmmu_block(data->sfrbases[i])) { | ||
536 | __sysmmu_tlb_invalidate_entry( | ||
537 | data->sfrbases[i], iova); | ||
538 | sysmmu_unblock(data->sfrbases[i]); | ||
539 | } | ||
540 | } | ||
541 | } else { | ||
542 | dev_dbg(data->sysmmu, | ||
543 | "(%s) Disabled. Skipping invalidating TLB.\n", | ||
544 | data->dbgname); | ||
545 | } | ||
546 | |||
547 | read_unlock_irqrestore(&data->lock, flags); | ||
548 | } | ||
549 | |||
550 | void exynos_sysmmu_tlb_invalidate(struct device *dev) | ||
551 | { | ||
552 | unsigned long flags; | ||
553 | struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); | ||
554 | |||
555 | read_lock_irqsave(&data->lock, flags); | ||
556 | |||
557 | if (is_sysmmu_active(data)) { | ||
558 | int i; | ||
559 | for (i = 0; i < data->nsfrs; i++) { | ||
560 | if (sysmmu_block(data->sfrbases[i])) { | ||
561 | __sysmmu_tlb_invalidate(data->sfrbases[i]); | ||
562 | sysmmu_unblock(data->sfrbases[i]); | ||
563 | } | ||
564 | } | ||
565 | } else { | ||
566 | dev_dbg(data->sysmmu, | ||
567 | "(%s) Disabled. Skipping invalidating TLB.\n", | ||
568 | data->dbgname); | ||
569 | } | ||
570 | |||
571 | read_unlock_irqrestore(&data->lock, flags); | ||
572 | } | ||
573 | |||
574 | static int exynos_sysmmu_probe(struct platform_device *pdev) | ||
575 | { | ||
576 | int i, ret; | ||
577 | struct device *dev; | ||
578 | struct sysmmu_drvdata *data; | ||
579 | |||
580 | dev = &pdev->dev; | ||
581 | |||
582 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
583 | if (!data) { | ||
584 | dev_dbg(dev, "Not enough memory\n"); | ||
585 | ret = -ENOMEM; | ||
586 | goto err_alloc; | ||
587 | } | ||
588 | |||
589 | ret = dev_set_drvdata(dev, data); | ||
590 | if (ret) { | ||
591 | dev_dbg(dev, "Unabled to initialize driver data\n"); | ||
592 | goto err_init; | ||
593 | } | ||
594 | |||
595 | data->nsfrs = pdev->num_resources / 2; | ||
596 | data->sfrbases = kmalloc(sizeof(*data->sfrbases) * data->nsfrs, | ||
597 | GFP_KERNEL); | ||
598 | if (data->sfrbases == NULL) { | ||
599 | dev_dbg(dev, "Not enough memory\n"); | ||
600 | ret = -ENOMEM; | ||
601 | goto err_init; | ||
602 | } | ||
603 | |||
604 | for (i = 0; i < data->nsfrs; i++) { | ||
605 | struct resource *res; | ||
606 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); | ||
607 | if (!res) { | ||
608 | dev_dbg(dev, "Unable to find IOMEM region\n"); | ||
609 | ret = -ENOENT; | ||
610 | goto err_res; | ||
611 | } | ||
612 | |||
613 | data->sfrbases[i] = ioremap(res->start, resource_size(res)); | ||
614 | if (!data->sfrbases[i]) { | ||
615 | dev_dbg(dev, "Unable to map IOMEM @ PA:%#x\n", | ||
616 | res->start); | ||
617 | ret = -ENOENT; | ||
618 | goto err_res; | ||
619 | } | ||
620 | } | ||
621 | |||
622 | for (i = 0; i < data->nsfrs; i++) { | ||
623 | ret = platform_get_irq(pdev, i); | ||
624 | if (ret <= 0) { | ||
625 | dev_dbg(dev, "Unable to find IRQ resource\n"); | ||
626 | goto err_irq; | ||
627 | } | ||
628 | |||
629 | ret = request_irq(ret, exynos_sysmmu_irq, 0, | ||
630 | dev_name(dev), data); | ||
631 | if (ret) { | ||
632 | dev_dbg(dev, "Unabled to register interrupt handler\n"); | ||
633 | goto err_irq; | ||
634 | } | ||
635 | } | ||
636 | |||
637 | if (dev_get_platdata(dev)) { | ||
638 | char *deli, *beg; | ||
639 | struct sysmmu_platform_data *platdata = dev_get_platdata(dev); | ||
640 | |||
641 | beg = platdata->clockname; | ||
642 | |||
643 | for (deli = beg; (*deli != '\0') && (*deli != ','); deli++) | ||
644 | /* NOTHING */; | ||
645 | |||
646 | if (*deli == '\0') | ||
647 | deli = NULL; | ||
648 | else | ||
649 | *deli = '\0'; | ||
650 | |||
651 | data->clk[0] = clk_get(dev, beg); | ||
652 | if (IS_ERR(data->clk[0])) { | ||
653 | data->clk[0] = NULL; | ||
654 | dev_dbg(dev, "No clock descriptor registered\n"); | ||
655 | } | ||
656 | |||
657 | if (data->clk[0] && deli) { | ||
658 | *deli = ','; | ||
659 | data->clk[1] = clk_get(dev, deli + 1); | ||
660 | if (IS_ERR(data->clk[1])) | ||
661 | data->clk[1] = NULL; | ||
662 | } | ||
663 | |||
664 | data->dbgname = platdata->dbgname; | ||
665 | } | ||
666 | |||
667 | data->sysmmu = dev; | ||
668 | rwlock_init(&data->lock); | ||
669 | INIT_LIST_HEAD(&data->node); | ||
670 | |||
671 | __set_fault_handler(data, &default_fault_handler); | ||
672 | |||
673 | if (dev->parent) | ||
674 | pm_runtime_enable(dev); | ||
675 | |||
676 | dev_dbg(dev, "(%s) Initialized\n", data->dbgname); | ||
677 | return 0; | ||
678 | err_irq: | ||
679 | while (i-- > 0) { | ||
680 | int irq; | ||
681 | |||
682 | irq = platform_get_irq(pdev, i); | ||
683 | free_irq(irq, data); | ||
684 | } | ||
685 | err_res: | ||
686 | while (data->nsfrs-- > 0) | ||
687 | iounmap(data->sfrbases[data->nsfrs]); | ||
688 | kfree(data->sfrbases); | ||
689 | err_init: | ||
690 | kfree(data); | ||
691 | err_alloc: | ||
692 | dev_err(dev, "Failed to initialize\n"); | ||
693 | return ret; | ||
694 | } | ||
695 | |||
696 | static struct platform_driver exynos_sysmmu_driver = { | ||
697 | .probe = exynos_sysmmu_probe, | ||
698 | .driver = { | ||
699 | .owner = THIS_MODULE, | ||
700 | .name = "exynos-sysmmu", | ||
701 | } | ||
702 | }; | ||
703 | |||
704 | static inline void pgtable_flush(void *vastart, void *vaend) | ||
705 | { | ||
706 | dmac_flush_range(vastart, vaend); | ||
707 | outer_flush_range(virt_to_phys(vastart), | ||
708 | virt_to_phys(vaend)); | ||
709 | } | ||
710 | |||
711 | static int exynos_iommu_domain_init(struct iommu_domain *domain) | ||
712 | { | ||
713 | struct exynos_iommu_domain *priv; | ||
714 | |||
715 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
716 | if (!priv) | ||
717 | return -ENOMEM; | ||
718 | |||
719 | priv->pgtable = (unsigned long *)__get_free_pages( | ||
720 | GFP_KERNEL | __GFP_ZERO, 2); | ||
721 | if (!priv->pgtable) | ||
722 | goto err_pgtable; | ||
723 | |||
724 | priv->lv2entcnt = (short *)__get_free_pages( | ||
725 | GFP_KERNEL | __GFP_ZERO, 1); | ||
726 | if (!priv->lv2entcnt) | ||
727 | goto err_counter; | ||
728 | |||
729 | pgtable_flush(priv->pgtable, priv->pgtable + NUM_LV1ENTRIES); | ||
730 | |||
731 | spin_lock_init(&priv->lock); | ||
732 | spin_lock_init(&priv->pgtablelock); | ||
733 | INIT_LIST_HEAD(&priv->clients); | ||
734 | |||
735 | domain->priv = priv; | ||
736 | return 0; | ||
737 | |||
738 | err_counter: | ||
739 | free_pages((unsigned long)priv->pgtable, 2); | ||
740 | err_pgtable: | ||
741 | kfree(priv); | ||
742 | return -ENOMEM; | ||
743 | } | ||
744 | |||
745 | static void exynos_iommu_domain_destroy(struct iommu_domain *domain) | ||
746 | { | ||
747 | struct exynos_iommu_domain *priv = domain->priv; | ||
748 | struct sysmmu_drvdata *data; | ||
749 | unsigned long flags; | ||
750 | int i; | ||
751 | |||
752 | WARN_ON(!list_empty(&priv->clients)); | ||
753 | |||
754 | spin_lock_irqsave(&priv->lock, flags); | ||
755 | |||
756 | list_for_each_entry(data, &priv->clients, node) { | ||
757 | while (!exynos_sysmmu_disable(data->dev)) | ||
758 | ; /* until System MMU is actually disabled */ | ||
759 | } | ||
760 | |||
761 | spin_unlock_irqrestore(&priv->lock, flags); | ||
762 | |||
763 | for (i = 0; i < NUM_LV1ENTRIES; i++) | ||
764 | if (lv1ent_page(priv->pgtable + i)) | ||
765 | kfree(__va(lv2table_base(priv->pgtable + i))); | ||
766 | |||
767 | free_pages((unsigned long)priv->pgtable, 2); | ||
768 | free_pages((unsigned long)priv->lv2entcnt, 1); | ||
769 | kfree(domain->priv); | ||
770 | domain->priv = NULL; | ||
771 | } | ||
772 | |||
773 | static int exynos_iommu_attach_device(struct iommu_domain *domain, | ||
774 | struct device *dev) | ||
775 | { | ||
776 | struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); | ||
777 | struct exynos_iommu_domain *priv = domain->priv; | ||
778 | unsigned long flags; | ||
779 | int ret; | ||
780 | |||
781 | ret = pm_runtime_get_sync(data->sysmmu); | ||
782 | if (ret < 0) | ||
783 | return ret; | ||
784 | |||
785 | ret = 0; | ||
786 | |||
787 | spin_lock_irqsave(&priv->lock, flags); | ||
788 | |||
789 | ret = __exynos_sysmmu_enable(data, __pa(priv->pgtable), domain); | ||
790 | |||
791 | if (ret == 0) { | ||
792 | /* 'data->node' must not be appeared in priv->clients */ | ||
793 | BUG_ON(!list_empty(&data->node)); | ||
794 | data->dev = dev; | ||
795 | list_add_tail(&data->node, &priv->clients); | ||
796 | } | ||
797 | |||
798 | spin_unlock_irqrestore(&priv->lock, flags); | ||
799 | |||
800 | if (ret < 0) { | ||
801 | dev_err(dev, "%s: Failed to attach IOMMU with pgtable %#lx\n", | ||
802 | __func__, __pa(priv->pgtable)); | ||
803 | pm_runtime_put(data->sysmmu); | ||
804 | } else if (ret > 0) { | ||
805 | dev_dbg(dev, "%s: IOMMU with pgtable 0x%lx already attached\n", | ||
806 | __func__, __pa(priv->pgtable)); | ||
807 | } else { | ||
808 | dev_dbg(dev, "%s: Attached new IOMMU with pgtable 0x%lx\n", | ||
809 | __func__, __pa(priv->pgtable)); | ||
810 | } | ||
811 | |||
812 | return ret; | ||
813 | } | ||
814 | |||
815 | static void exynos_iommu_detach_device(struct iommu_domain *domain, | ||
816 | struct device *dev) | ||
817 | { | ||
818 | struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); | ||
819 | struct exynos_iommu_domain *priv = domain->priv; | ||
820 | struct list_head *pos; | ||
821 | unsigned long flags; | ||
822 | bool found = false; | ||
823 | |||
824 | spin_lock_irqsave(&priv->lock, flags); | ||
825 | |||
826 | list_for_each(pos, &priv->clients) { | ||
827 | if (list_entry(pos, struct sysmmu_drvdata, node) == data) { | ||
828 | found = true; | ||
829 | break; | ||
830 | } | ||
831 | } | ||
832 | |||
833 | if (!found) | ||
834 | goto finish; | ||
835 | |||
836 | if (__exynos_sysmmu_disable(data)) { | ||
837 | dev_dbg(dev, "%s: Detached IOMMU with pgtable %#lx\n", | ||
838 | __func__, __pa(priv->pgtable)); | ||
839 | list_del(&data->node); | ||
840 | INIT_LIST_HEAD(&data->node); | ||
841 | |||
842 | } else { | ||
843 | dev_dbg(dev, "%s: Detaching IOMMU with pgtable %#lx delayed", | ||
844 | __func__, __pa(priv->pgtable)); | ||
845 | } | ||
846 | |||
847 | finish: | ||
848 | spin_unlock_irqrestore(&priv->lock, flags); | ||
849 | |||
850 | if (found) | ||
851 | pm_runtime_put(data->sysmmu); | ||
852 | } | ||
853 | |||
854 | static unsigned long *alloc_lv2entry(unsigned long *sent, unsigned long iova, | ||
855 | short *pgcounter) | ||
856 | { | ||
857 | if (lv1ent_fault(sent)) { | ||
858 | unsigned long *pent; | ||
859 | |||
860 | pent = kzalloc(LV2TABLE_SIZE, GFP_ATOMIC); | ||
861 | BUG_ON((unsigned long)pent & (LV2TABLE_SIZE - 1)); | ||
862 | if (!pent) | ||
863 | return NULL; | ||
864 | |||
865 | *sent = mk_lv1ent_page(__pa(pent)); | ||
866 | *pgcounter = NUM_LV2ENTRIES; | ||
867 | pgtable_flush(pent, pent + NUM_LV2ENTRIES); | ||
868 | pgtable_flush(sent, sent + 1); | ||
869 | } | ||
870 | |||
871 | return page_entry(sent, iova); | ||
872 | } | ||
873 | |||
874 | static int lv1set_section(unsigned long *sent, phys_addr_t paddr, short *pgcnt) | ||
875 | { | ||
876 | if (lv1ent_section(sent)) | ||
877 | return -EADDRINUSE; | ||
878 | |||
879 | if (lv1ent_page(sent)) { | ||
880 | if (*pgcnt != NUM_LV2ENTRIES) | ||
881 | return -EADDRINUSE; | ||
882 | |||
883 | kfree(page_entry(sent, 0)); | ||
884 | |||
885 | *pgcnt = 0; | ||
886 | } | ||
887 | |||
888 | *sent = mk_lv1ent_sect(paddr); | ||
889 | |||
890 | pgtable_flush(sent, sent + 1); | ||
891 | |||
892 | return 0; | ||
893 | } | ||
894 | |||
895 | static int lv2set_page(unsigned long *pent, phys_addr_t paddr, size_t size, | ||
896 | short *pgcnt) | ||
897 | { | ||
898 | if (size == SPAGE_SIZE) { | ||
899 | if (!lv2ent_fault(pent)) | ||
900 | return -EADDRINUSE; | ||
901 | |||
902 | *pent = mk_lv2ent_spage(paddr); | ||
903 | pgtable_flush(pent, pent + 1); | ||
904 | *pgcnt -= 1; | ||
905 | } else { /* size == LPAGE_SIZE */ | ||
906 | int i; | ||
907 | for (i = 0; i < SPAGES_PER_LPAGE; i++, pent++) { | ||
908 | if (!lv2ent_fault(pent)) { | ||
909 | memset(pent, 0, sizeof(*pent) * i); | ||
910 | return -EADDRINUSE; | ||
911 | } | ||
912 | |||
913 | *pent = mk_lv2ent_lpage(paddr); | ||
914 | } | ||
915 | pgtable_flush(pent - SPAGES_PER_LPAGE, pent); | ||
916 | *pgcnt -= SPAGES_PER_LPAGE; | ||
917 | } | ||
918 | |||
919 | return 0; | ||
920 | } | ||
921 | |||
922 | static int exynos_iommu_map(struct iommu_domain *domain, unsigned long iova, | ||
923 | phys_addr_t paddr, size_t size, int prot) | ||
924 | { | ||
925 | struct exynos_iommu_domain *priv = domain->priv; | ||
926 | unsigned long *entry; | ||
927 | unsigned long flags; | ||
928 | int ret = -ENOMEM; | ||
929 | |||
930 | BUG_ON(priv->pgtable == NULL); | ||
931 | |||
932 | spin_lock_irqsave(&priv->pgtablelock, flags); | ||
933 | |||
934 | entry = section_entry(priv->pgtable, iova); | ||
935 | |||
936 | if (size == SECT_SIZE) { | ||
937 | ret = lv1set_section(entry, paddr, | ||
938 | &priv->lv2entcnt[lv1ent_offset(iova)]); | ||
939 | } else { | ||
940 | unsigned long *pent; | ||
941 | |||
942 | pent = alloc_lv2entry(entry, iova, | ||
943 | &priv->lv2entcnt[lv1ent_offset(iova)]); | ||
944 | |||
945 | if (!pent) | ||
946 | ret = -ENOMEM; | ||
947 | else | ||
948 | ret = lv2set_page(pent, paddr, size, | ||
949 | &priv->lv2entcnt[lv1ent_offset(iova)]); | ||
950 | } | ||
951 | |||
952 | if (ret) { | ||
953 | pr_debug("%s: Failed to map iova 0x%lx/0x%x bytes\n", | ||
954 | __func__, iova, size); | ||
955 | } | ||
956 | |||
957 | spin_unlock_irqrestore(&priv->pgtablelock, flags); | ||
958 | |||
959 | return ret; | ||
960 | } | ||
961 | |||
962 | static size_t exynos_iommu_unmap(struct iommu_domain *domain, | ||
963 | unsigned long iova, size_t size) | ||
964 | { | ||
965 | struct exynos_iommu_domain *priv = domain->priv; | ||
966 | struct sysmmu_drvdata *data; | ||
967 | unsigned long flags; | ||
968 | unsigned long *ent; | ||
969 | |||
970 | BUG_ON(priv->pgtable == NULL); | ||
971 | |||
972 | spin_lock_irqsave(&priv->pgtablelock, flags); | ||
973 | |||
974 | ent = section_entry(priv->pgtable, iova); | ||
975 | |||
976 | if (lv1ent_section(ent)) { | ||
977 | BUG_ON(size < SECT_SIZE); | ||
978 | |||
979 | *ent = 0; | ||
980 | pgtable_flush(ent, ent + 1); | ||
981 | size = SECT_SIZE; | ||
982 | goto done; | ||
983 | } | ||
984 | |||
985 | if (unlikely(lv1ent_fault(ent))) { | ||
986 | if (size > SECT_SIZE) | ||
987 | size = SECT_SIZE; | ||
988 | goto done; | ||
989 | } | ||
990 | |||
991 | /* lv1ent_page(sent) == true here */ | ||
992 | |||
993 | ent = page_entry(ent, iova); | ||
994 | |||
995 | if (unlikely(lv2ent_fault(ent))) { | ||
996 | size = SPAGE_SIZE; | ||
997 | goto done; | ||
998 | } | ||
999 | |||
1000 | if (lv2ent_small(ent)) { | ||
1001 | *ent = 0; | ||
1002 | size = SPAGE_SIZE; | ||
1003 | priv->lv2entcnt[lv1ent_offset(iova)] += 1; | ||
1004 | goto done; | ||
1005 | } | ||
1006 | |||
1007 | /* lv1ent_large(ent) == true here */ | ||
1008 | BUG_ON(size < LPAGE_SIZE); | ||
1009 | |||
1010 | memset(ent, 0, sizeof(*ent) * SPAGES_PER_LPAGE); | ||
1011 | |||
1012 | size = LPAGE_SIZE; | ||
1013 | priv->lv2entcnt[lv1ent_offset(iova)] += SPAGES_PER_LPAGE; | ||
1014 | done: | ||
1015 | spin_unlock_irqrestore(&priv->pgtablelock, flags); | ||
1016 | |||
1017 | spin_lock_irqsave(&priv->lock, flags); | ||
1018 | list_for_each_entry(data, &priv->clients, node) | ||
1019 | sysmmu_tlb_invalidate_entry(data->dev, iova); | ||
1020 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1021 | |||
1022 | |||
1023 | return size; | ||
1024 | } | ||
1025 | |||
1026 | static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *domain, | ||
1027 | unsigned long iova) | ||
1028 | { | ||
1029 | struct exynos_iommu_domain *priv = domain->priv; | ||
1030 | unsigned long *entry; | ||
1031 | unsigned long flags; | ||
1032 | phys_addr_t phys = 0; | ||
1033 | |||
1034 | spin_lock_irqsave(&priv->pgtablelock, flags); | ||
1035 | |||
1036 | entry = section_entry(priv->pgtable, iova); | ||
1037 | |||
1038 | if (lv1ent_section(entry)) { | ||
1039 | phys = section_phys(entry) + section_offs(iova); | ||
1040 | } else if (lv1ent_page(entry)) { | ||
1041 | entry = page_entry(entry, iova); | ||
1042 | |||
1043 | if (lv2ent_large(entry)) | ||
1044 | phys = lpage_phys(entry) + lpage_offs(iova); | ||
1045 | else if (lv2ent_small(entry)) | ||
1046 | phys = spage_phys(entry) + spage_offs(iova); | ||
1047 | } | ||
1048 | |||
1049 | spin_unlock_irqrestore(&priv->pgtablelock, flags); | ||
1050 | |||
1051 | return phys; | ||
1052 | } | ||
1053 | |||
1054 | static struct iommu_ops exynos_iommu_ops = { | ||
1055 | .domain_init = &exynos_iommu_domain_init, | ||
1056 | .domain_destroy = &exynos_iommu_domain_destroy, | ||
1057 | .attach_dev = &exynos_iommu_attach_device, | ||
1058 | .detach_dev = &exynos_iommu_detach_device, | ||
1059 | .map = &exynos_iommu_map, | ||
1060 | .unmap = &exynos_iommu_unmap, | ||
1061 | .iova_to_phys = &exynos_iommu_iova_to_phys, | ||
1062 | .pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE, | ||
1063 | }; | ||
1064 | |||
1065 | static int __init exynos_iommu_init(void) | ||
1066 | { | ||
1067 | int ret; | ||
1068 | |||
1069 | ret = platform_driver_register(&exynos_sysmmu_driver); | ||
1070 | |||
1071 | if (ret == 0) | ||
1072 | bus_set_iommu(&platform_bus_type, &exynos_iommu_ops); | ||
1073 | |||
1074 | return ret; | ||
1075 | } | ||
1076 | subsys_initcall(exynos_iommu_init); | ||
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index a9fc714fb38d..9a7a60aeb19e 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -1781,7 +1781,7 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev) | |||
1781 | pdata->slots[0].nonremovable = true; | 1781 | pdata->slots[0].nonremovable = true; |
1782 | pdata->slots[0].no_regulator_off_init = true; | 1782 | pdata->slots[0].no_regulator_off_init = true; |
1783 | } | 1783 | } |
1784 | of_property_read_u32(np, "ti,bus-width", &bus_width); | 1784 | of_property_read_u32(np, "bus-width", &bus_width); |
1785 | if (bus_width == 4) | 1785 | if (bus_width == 4) |
1786 | pdata->slots[0].caps |= MMC_CAP_4_BIT_DATA; | 1786 | pdata->slots[0].caps |= MMC_CAP_4_BIT_DATA; |
1787 | else if (bus_width == 8) | 1787 | else if (bus_width == 8) |
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index d190d04636a7..365b16c230f8 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c | |||
@@ -404,7 +404,7 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, | |||
404 | if (!np) | 404 | if (!np) |
405 | return -ENODEV; | 405 | return -ENODEV; |
406 | 406 | ||
407 | if (of_get_property(np, "fsl,card-wired", NULL)) | 407 | if (of_get_property(np, "non-removable", NULL)) |
408 | boarddata->cd_type = ESDHC_CD_PERMANENT; | 408 | boarddata->cd_type = ESDHC_CD_PERMANENT; |
409 | 409 | ||
410 | if (of_get_property(np, "fsl,cd-controller", NULL)) | 410 | if (of_get_property(np, "fsl,cd-controller", NULL)) |
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index c5c2a48bdd94..d9a4ef4f1ed0 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c | |||
@@ -42,7 +42,8 @@ static struct sdhci_ops sdhci_pltfm_ops = { | |||
42 | #ifdef CONFIG_OF | 42 | #ifdef CONFIG_OF |
43 | static bool sdhci_of_wp_inverted(struct device_node *np) | 43 | static bool sdhci_of_wp_inverted(struct device_node *np) |
44 | { | 44 | { |
45 | if (of_get_property(np, "sdhci,wp-inverted", NULL)) | 45 | if (of_get_property(np, "sdhci,wp-inverted", NULL) || |
46 | of_get_property(np, "wp-inverted", NULL)) | ||
46 | return true; | 47 | return true; |
47 | 48 | ||
48 | /* Old device trees don't have the wp-inverted property. */ | 49 | /* Old device trees don't have the wp-inverted property. */ |
@@ -59,13 +60,16 @@ void sdhci_get_of_property(struct platform_device *pdev) | |||
59 | struct sdhci_host *host = platform_get_drvdata(pdev); | 60 | struct sdhci_host *host = platform_get_drvdata(pdev); |
60 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 61 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
61 | const __be32 *clk; | 62 | const __be32 *clk; |
63 | u32 bus_width; | ||
62 | int size; | 64 | int size; |
63 | 65 | ||
64 | if (of_device_is_available(np)) { | 66 | if (of_device_is_available(np)) { |
65 | if (of_get_property(np, "sdhci,auto-cmd12", NULL)) | 67 | if (of_get_property(np, "sdhci,auto-cmd12", NULL)) |
66 | host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; | 68 | host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; |
67 | 69 | ||
68 | if (of_get_property(np, "sdhci,1-bit-only", NULL)) | 70 | if (of_get_property(np, "sdhci,1-bit-only", NULL) || |
71 | (of_property_read_u32(np, "bus-width", &bus_width) == 0 && | ||
72 | bus_width == 1)) | ||
69 | host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; | 73 | host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; |
70 | 74 | ||
71 | if (sdhci_of_wp_inverted(np)) | 75 | if (sdhci_of_wp_inverted(np)) |
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 4a44bf833611..68548236ec42 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c | |||
@@ -722,8 +722,9 @@ static int tegra_ehci_probe(struct platform_device *pdev) | |||
722 | } | 722 | } |
723 | } | 723 | } |
724 | 724 | ||
725 | tegra->phy = tegra_usb_phy_open(instance, hcd->regs, pdata->phy_config, | 725 | tegra->phy = tegra_usb_phy_open(&pdev->dev, instance, hcd->regs, |
726 | TEGRA_USB_PHY_MODE_HOST); | 726 | pdata->phy_config, |
727 | TEGRA_USB_PHY_MODE_HOST); | ||
727 | if (IS_ERR(tegra->phy)) { | 728 | if (IS_ERR(tegra->phy)) { |
728 | dev_err(&pdev->dev, "Failed to open USB phy\n"); | 729 | dev_err(&pdev->dev, "Failed to open USB phy\n"); |
729 | err = -ENXIO; | 730 | err = -ENXIO; |