]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 26 May 2012 19:22:27 +0000 (12:22 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 26 May 2012 19:22:27 +0000 (12:22 -0700)
Pull arm-soc driver specific updates from Olof Johansson:
 "These changes are specific to some driver that may be used by multiple
  boards or socs.  The most significant change in here is the move of
  the samsung iommu code from a platform specific in-kernel interface to
  the generic iommu subsystem."

Fix up trivial conflicts in arch/arm/mach-exynos/Kconfig

* tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (28 commits)
  mmc: dt: Consolidate DT bindings
  iommu/exynos: Add iommu driver for EXYNOS Platforms
  ARM: davinci: optimize the DMA ISR
  ARM: davinci: implement DEBUG_LL port choice
  ARM: tegra: Add SMMU enabler in AHB
  ARM: tegra: Add Tegra AHB driver
  Input: pxa27x_keypad add choice to set direct_key_mask
  Input: pxa27x_keypad direct key may be low active
  Input: pxa27x_keypad bug fix for direct_key_mask
  Input: pxa27x_keypad keep clock on as wakeup source
  ARM: dt: tegra: pinmux changes for USB ULPI
  ARM: tegra: add USB ULPI PHY reset GPIO to device tree
  ARM: tegra: don't hard-code USB ULPI PHY reset_gpio
  ARM: tegra: change pll_p_out4's rate to 24MHz
  ARM: tegra: fix pclk rate
  ARM: tegra: reparent sclk to pll_c_out1
  ARM: tegra: Add pllc clock init table
  ARM: dt: tegra cardhu: basic audio support
  ARM: dt: tegra30.dtsi: Add audio-related nodes
  ARM: tegra: add AUXDATA required for audio
  ...

74 files changed:
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-ahb.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/fsl-esdhc.txt
Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt
Documentation/devicetree/bindings/mmc/mmc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt
Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
Documentation/devicetree/bindings/usb/tegra-usb.txt
arch/arm/Kconfig.debug
arch/arm/boot/dts/imx53-smd.dts
arch/arm/boot/dts/imx6q-arm2.dts
arch/arm/boot/dts/omap3-beagle.dts
arch/arm/boot/dts/omap4-panda.dts
arch/arm/boot/dts/omap4-sdp.dts
arch/arm/boot/dts/tegra-cardhu.dts
arch/arm/boot/dts/tegra-harmony.dts
arch/arm/boot/dts/tegra-paz00.dts
arch/arm/boot/dts/tegra-seaboard.dts
arch/arm/boot/dts/tegra-trimslice.dts
arch/arm/boot/dts/tegra-ventana.dts
arch/arm/boot/dts/tegra30.dtsi
arch/arm/mach-davinci/dma.c
arch/arm/mach-davinci/include/mach/debug-macro.S
arch/arm/mach-davinci/include/mach/hardware.h
arch/arm/mach-davinci/include/mach/serial.h
arch/arm/mach-davinci/include/mach/uncompress.h
arch/arm/mach-ep93xx/core.c
arch/arm/mach-exynos/Kconfig
arch/arm/mach-exynos/Makefile
arch/arm/mach-exynos/clock-exynos4.c
arch/arm/mach-exynos/clock-exynos4.h
arch/arm/mach-exynos/clock-exynos4210.c
arch/arm/mach-exynos/clock-exynos4212.c
arch/arm/mach-exynos/clock-exynos5.c
arch/arm/mach-exynos/dev-sysmmu.c
arch/arm/mach-exynos/include/mach/irqs.h
arch/arm/mach-exynos/include/mach/map.h
arch/arm/mach-exynos/include/mach/regs-clock.h
arch/arm/mach-exynos/include/mach/regs-sysmmu.h [deleted file]
arch/arm/mach-exynos/include/mach/sysmmu.h
arch/arm/mach-exynos/mach-armlex4210.c
arch/arm/mach-exynos/mach-smdkv310.c
arch/arm/mach-tegra/Kconfig
arch/arm/mach-tegra/board-dt-tegra30.c
arch/arm/mach-tegra/board-paz00.c
arch/arm/mach-tegra/board-trimslice.c
arch/arm/mach-tegra/common.c
arch/arm/mach-tegra/devices.c
arch/arm/mach-tegra/devices.h
arch/arm/mach-tegra/include/mach/tegra-ahb.h [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/uncompress.h
arch/arm/mach-tegra/include/mach/usb_phy.h
arch/arm/mach-tegra/tegra2_clocks.c
arch/arm/mach-tegra/tegra30_clocks.c
arch/arm/mach-tegra/usb_phy.c
arch/arm/plat-pxa/include/plat/pxa27x_keypad.h
arch/arm/plat-s5p/Kconfig
arch/arm/plat-s5p/Makefile
arch/arm/plat-s5p/sysmmu.c [deleted file]
arch/arm/plat-samsung/include/plat/devs.h
arch/arm/plat-samsung/include/plat/sysmmu.h [deleted file]
arch/powerpc/boot/dts/mpc8569mds.dts
drivers/Makefile
drivers/amba/Makefile
drivers/amba/tegra-ahb.c [new file with mode: 0644]
drivers/dma/ep93xx_dma.c
drivers/input/keyboard/pxa27x_keypad.c
drivers/iommu/Kconfig
drivers/iommu/Makefile
drivers/iommu/exynos-iommu.c [new file with mode: 0644]
drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mmc/host/sdhci-pltfm.c
drivers/usb/host/ehci-tegra.c

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 (file)
index 0000000..234406d
--- /dev/null
@@ -0,0 +1,11 @@
+NVIDIA Tegra AHB
+
+Required properties:
+- compatible : "nvidia,tegra20-ahb" or "nvidia,tegra30-ahb"
+- reg : Should contain 1 register ranges(address and length)
+
+Example:
+       ahb: ahb@6000c004 {
+               compatible = "nvidia,tegra20-ahb";
+               reg = <0x6000c004 0x10c>; /* AHB Arbitration + Gizmo Controller */
+       };
index 64bcb8be973c0574ee0b835b2698f7d7501d8ff3..0d93b4b0e0e3733f77d0b668f166f2a3ba983555 100644 (file)
@@ -11,9 +11,11 @@ Required properties:
   - interrupt-parent : interrupt source phandle.
   - clock-frequency : specifies eSDHC base clock frequency.
   - sdhci,wp-inverted : (optional) specifies that eSDHC controller
-    reports inverted write-protect state;
+    reports inverted write-protect state; New devices should use
+    the generic "wp-inverted" property.
   - sdhci,1-bit-only : (optional) specifies that a controller can
-    only handle 1-bit data transfers.
+    only handle 1-bit data transfers. New devices should use the
+    generic "bus-width = <1>" property.
   - sdhci,auto-cmd12: (optional) specifies that a controller can
     only handle auto CMD12.
 
index ab22fe6e73abf00da7bd362981ce2331db284f2b..c7e404b3ef0515b5527583cae877ab48c5d69595 100644 (file)
@@ -9,7 +9,7 @@ Required properties:
 - interrupts : Should contain eSDHC interrupt
 
 Optional properties:
-- fsl,card-wired : Indicate the card is wired to host permanently
+- non-removable : Indicate the card is wired to host permanently
 - fsl,cd-internal : Indicate to use controller internal card detection
 - fsl,wp-internal : Indicate to use controller internal write protection
 - cd-gpios : Specify GPIOs for card detection
index 89a0084df2f76e625a2cdfcccf4e6c0f4281bc12..d64aea5a42032414fa99d1fa43fb0dc20114c254 100644 (file)
@@ -10,7 +10,8 @@ Required properties:
 
 Optional properties:
 - gpios : may specify GPIOs in this order: Card-Detect GPIO,
-  Write-Protect GPIO.
+  Write-Protect GPIO. Note that this does not follow the
+  binding from mmc.txt, for historic reasons.
 - interrupts : the interrupt of a card detect interrupt.
 - interrupt-parent : the phandle for the interrupt controller that
   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 (file)
index 0000000..6e70dcd
--- /dev/null
@@ -0,0 +1,27 @@
+These properties are common to multiple MMC host controllers. Any host
+that requires the respective functionality should implement them using
+these definitions.
+
+Required properties:
+- bus-width: Number of data lines, can be <1>, <4>, or <8>
+
+Optional properties:
+- cd-gpios : Specify GPIOs for card detection, see gpio binding
+- wp-gpios : Specify GPIOs for write protection, see gpio binding
+- cd-inverted: when present, polarity on the wp gpio line is inverted
+- wp-inverted: when present, polarity on the wp gpio line is inverted
+- non-removable: non-removable slot (like eMMC)
+- max-frequency: maximum operating clock frequency
+
+Example:
+
+sdhci@ab000000 {
+       compatible = "sdhci";
+       reg = <0xab000000 0x200>;
+       interrupts = <23>;
+       bus-width = <4>;
+       cd-gpios = <&gpio 69 0>;
+       cd-inverted;
+       wp-gpios = <&gpio 70 0>;
+       max-frequency = <50000000>;
+}
index 7e51154679a6f17d47ce198b77dd2eeade185dc6..f77c3031607fbea26a250e3f7fcdd6373089dfff 100644 (file)
@@ -7,12 +7,12 @@ Required properties:
 - compatible : Should be "nvidia,<chip>-sdhci"
 - reg : Should contain SD/MMC registers location and length
 - interrupts : Should contain SD/MMC interrupt
+- bus-width : Number of data lines, can be <1>, <4>, or <8>
 
 Optional properties:
 - cd-gpios : Specify GPIOs for card detection
 - wp-gpios : Specify GPIOs for write protection
 - power-gpios : Specify GPIOs for power control
-- support-8bit : Boolean, indicates if 8-bit mode should be used.
 
 Example:
 
@@ -23,5 +23,5 @@ sdhci@c8000200 {
        cd-gpios = <&gpio 69 0>; /* gpio PI5 */
        wp-gpios = <&gpio 57 0>; /* gpio PH1 */
        power-gpios = <&gpio 155 0>; /* gpio PT3 */
-       support-8bit;
+       bus-width = <8>;
 };
index dbd4368ab8cc223bb3fc63147da349b25ed82db8..8a53958c9a9f50e71073daa1b8aa0650308ea13c 100644 (file)
@@ -15,7 +15,7 @@ Optional properties:
 ti,dual-volt: boolean, supports dual voltage cards
 <supply-name>-supply: phandle to the regulator device tree node
 "supply-name" examples are "vmmc", "vmmc_aux" etc
-ti,bus-width: Number of data lines, default assumed is 1 if the property is missing.
+bus-width: Number of data lines, default assumed is 1 if the property is missing.
 cd-gpios: GPIOs for card detection
 wp-gpios: GPIOs for write protection
 ti,non-removable: non-removable slot (like eMMC)
@@ -27,7 +27,7 @@ Example:
                reg = <0x4809c000 0x400>;
                ti,hwmods = "mmc1";
                ti,dual-volt;
-               ti,bus-width = <4>;
+               bus-width = <4>;
                vmmc-supply = <&vmmc>; /* phandle to regulator node */
                ti,non-removable;
        };
index 007005ddbe12ddbf5780061a94c243cc915bbcfe..e9b005dc762538073f553cf6a0af0f964017e7e0 100644 (file)
@@ -12,6 +12,9 @@ Required properties :
  - nvidia,vbus-gpio : If present, specifies a gpio that needs to be
    activated for the bus to be powered.
 
+Required properties for phy_type == ulpi:
+  - nvidia,phy-reset-gpio : The GPIO used to reset the PHY.
+
 Optional properties:
   - dr_mode : dual role mode. Indicates the working mode for
    nvidia,tegra20-ehci compatible controllers.  Can be "host", "peripheral",
index 85348a09d655afc220fc55f71810b07830ea8936..e561adc1db0c358a1fdb921c0106cea0b0d6b704 100644 (file)
@@ -103,6 +103,35 @@ choice
                  Say Y here if you want the debug print routines to direct
                  their output to the second serial port on these devices.
 
+       config DEBUG_DAVINCI_DA8XX_UART1
+               bool "Kernel low-level debugging on DaVinci DA8XX using UART1"
+               depends on ARCH_DAVINCI_DA8XX
+               help
+                 Say Y here if you want the debug print routines to direct
+                 their output to UART1 serial port on DaVinci DA8XX devices.
+
+       config DEBUG_DAVINCI_DA8XX_UART2
+               bool "Kernel low-level debugging on DaVinci DA8XX using UART2"
+               depends on ARCH_DAVINCI_DA8XX
+               help
+                 Say Y here if you want the debug print routines to direct
+                 their output to UART2 serial port on DaVinci DA8XX devices.
+
+       config DEBUG_DAVINCI_DMx_UART0
+               bool "Kernel low-level debugging on DaVinci DMx using UART0"
+               depends on ARCH_DAVINCI_DMx
+               help
+                 Say Y here if you want the debug print routines to direct
+                 their output to UART0 serial port on DaVinci DMx devices.
+
+       config DEBUG_DAVINCI_TNETV107X_UART1
+               bool "Kernel low-level debugging on DaVinci TNETV107x using UART1"
+               depends on ARCH_DAVINCI_TNETV107X
+               help
+                 Say Y here if you want the debug print routines to direct
+                 their output to UART1 serial port on DaVinci TNETV107X
+                 devices.
+
        config DEBUG_DC21285_PORT
                bool "Kernel low-level debugging messages via footbridge serial port"
                depends on FOOTBRIDGE
index c7ee86c2dfb530a7c77a38fc2826632b110e2e9b..139138a556b043c25d842c3d5c08f5be7aeec907 100644 (file)
@@ -35,7 +35,7 @@
                                };
 
                                esdhc@50008000 { /* ESDHC2 */
-                                       fsl,card-wired;
+                                       non-removable;
                                        status = "okay";
                                };
 
@@ -76,7 +76,7 @@
                                };
 
                                esdhc@50020000 { /* ESDHC3 */
-                                       fsl,card-wired;
+                                       non-removable;
                                        status = "okay";
                                };
                        };
index ce1c8238c8975c6b84f72304f7ff8ae68dda8c88..d2eaf521c9fd7ae7f5faafcbce609a6254413e76 100644 (file)
@@ -41,7 +41,7 @@
                        };
 
                        usdhc@0219c000 { /* uSDHC4 */
-                               fsl,card-wired;
+                               non-removable;
                                vmmc-supply = <&reg_3p3v>;
                                status = "okay";
                        };
index 8c756be4d7adbf4b15bfc83ae6dcda1324f68453..5b4506c0a8c47d7e1ef506db75cbad9da303b3ec 100644 (file)
@@ -57,7 +57,7 @@
 &mmc1 {
        vmmc-supply = <&vmmc1>;
        vmmc_aux-supply = <&vsim>;
-       ti,bus-width = <8>;
+       bus-width = <8>;
 };
 
 &mmc2 {
index e671361bc79135abb97b8754d998a7977d348f49..1efe0c5879855ebbc4165d09f21403eb86ed9be6 100644 (file)
@@ -70,7 +70,7 @@
 
 &mmc1 {
        vmmc-supply = <&vmmc>;
-       ti,bus-width = <8>;
+       bus-width = <8>;
 };
 
 &mmc2 {
@@ -87,5 +87,5 @@
 
 &mmc5 {
        ti,non-removable;
-       ti,bus-width = <4>;
+       bus-width = <4>;
 };
index e5eeb6f9c6e668e596c8a24d3e2699b81a26458e..d08c4d1372800a0f944489ace4495db188c499c7 100644 (file)
 
 &mmc1 {
        vmmc-supply = <&vmmc>;
-       ti,bus-width = <8>;
+       bus-width = <8>;
 };
 
 &mmc2 {
        vmmc-supply = <&vaux1>;
-       ti,bus-width = <8>;
+       bus-width = <8>;
        ti,non-removable;
 };
 
 };
 
 &mmc5 {
-       ti,bus-width = <4>;
+       bus-width = <4>;
        ti,non-removable;
 };
index 0a9f34a2c3aae9e09cf7a3e939ec5737e030be0b..4a166357172b9327c76d97349b218dbb60f15597 100644 (file)
                                nvidia,pull = <2>;
                                nvidia,tristate = <0>;
                        };
+                       dap2_fs_pa2 {
+                               nvidia,pins =   "dap2_fs_pa2",
+                                               "dap2_sclk_pa3",
+                                               "dap2_din_pa4",
+                                               "dap2_dout_pa5";
+                               nvidia,function = "i2s1";
+                               nvidia,pull = <0>;
+                               nvidia,tristate = <0>;
+                       };
                };
        };
 
 
        i2c@7000d000 {
                clock-frequency = <100000>;
+
+               wm8903: wm8903@1a {
+                       compatible = "wlf,wm8903";
+                       reg = <0x1a>;
+                       interrupt-parent = <&gpio>;
+                       interrupts = <179 0x04>; /* gpio PW3 */
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       micdet-cfg = <0>;
+                       micdet-delay = <100>;
+                       gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>;
+               };
        };
 
        sdhci@78000000 {
                cd-gpios = <&gpio 69 0>; /* gpio PI5 */
                wp-gpios = <&gpio 155 0>; /* gpio PT3 */
                power-gpios = <&gpio 31 0>; /* gpio PD7 */
+               bus-width = <4>;
        };
 
        sdhci@78000200 {
 
        sdhci@78000400 {
                support-8bit;
+               bus-width = <8>;
+       };
+
+       ahub@70080000 {
+               i2s@70080300 {
+                       status = "disable";
+               };
+
+               i2s@70080500 {
+                       status = "disable";
+               };
+
+               i2s@70080600 {
+                       status = "disable";
+               };
+
+               i2s@70080700 {
+                       status = "disable";
+               };
+       };
+
+       sound {
+               compatible = "nvidia,tegra-audio-wm8903-cardhu",
+                            "nvidia,tegra-audio-wm8903";
+               nvidia,model = "NVIDIA Tegra Cardhu";
+
+               nvidia,audio-routing =
+                       "Headphone Jack", "HPOUTR",
+                       "Headphone Jack", "HPOUTL",
+                       "Int Spk", "ROP",
+                       "Int Spk", "RON",
+                       "Int Spk", "LOP",
+                       "Int Spk", "LON",
+                       "Mic Jack", "MICBIAS",
+                       "IN1L", "Mic Jack";
+
+               nvidia,i2s-controller = <&tegra_i2s1>;
+               nvidia,audio-codec = <&wm8903>;
+
+               nvidia,spkr-en-gpios = <&wm8903 2 0>;
+               nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
        };
 };
index 1a0b1f182944b889838ffcd55ce374a721aa5453..7cd513ac5ea602a907db6e1aecfcd231dd85e883 100644 (file)
                        };
                        conf_ata {
                                nvidia,pins = "ata", "atb", "atc", "atd", "ate",
-                                       "cdev1", "dap1", "dtb", "gma", "gmb",
-                                       "gmc", "gmd", "gme", "gpu7", "gpv",
-                                       "i2cp", "pta", "rm", "slxa", "slxk",
-                                       "spia", "spib";
+                                       "cdev1", "cdev2", "dap1", "dtb", "gma",
+                                       "gmb", "gmc", "gmd", "gme", "gpu7",
+                                       "gpv", "i2cp", "pta", "rm", "slxa",
+                                       "slxk", "spia", "spib", "uac";
                                nvidia,pull = <0>;
                                nvidia,tristate = <0>;
                        };
-                       conf_cdev2 {
-                               nvidia,pins = "cdev2", "csus", "spid", "spif";
-                               nvidia,pull = <1>;
-                               nvidia,tristate = <1>;
-                       };
                        conf_ck32 {
                                nvidia,pins = "ck32", "ddrc", "pmca", "pmcb",
                                        "pmcc", "pmcd", "pmce", "xm2c", "xm2d";
                                nvidia,pull = <0>;
                        };
+                       conf_csus {
+                               nvidia,pins = "csus", "spid", "spif";
+                               nvidia,pull = <1>;
+                               nvidia,tristate = <1>;
+                       };
                        conf_crtp {
                                nvidia,pins = "crtp", "dap2", "dap3", "dap4",
                                        "dtc", "dte", "dtf", "gpu", "sdio1",
                                        "slxc", "slxd", "spdi", "spdo", "spig",
-                                       "uac", "uda";
+                                       "uda";
                                nvidia,pull = <0>;
                                nvidia,tristate = <1>;
                        };
                cd-gpios = <&gpio 69 0>; /* gpio PI5 */
                wp-gpios = <&gpio 57 0>; /* gpio PH1 */
                power-gpios = <&gpio 155 0>; /* gpio PT3 */
+               bus-width = <4>;
        };
 
        sdhci@c8000400 {
                wp-gpios = <&gpio 59 0>; /* gpio PH3 */
                power-gpios = <&gpio 70 0>; /* gpio PI6 */
                support-8bit;
+               bus-width = <8>;
+       };
+
+       usb@c5004000 {
+               nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
        };
 };
index 10943fb2561c905ccf04b3ffe6ff34b3aab8597c..8d625e4c5de50e9897b9f3463a89cd01ba36b52e 100644 (file)
                        };
                        conf_ata {
                                nvidia,pins = "ata", "atb", "atc", "atd", "ate",
-                                       "cdev1", "dap1", "dap2", "dtf", "gma",
-                                       "gmb", "gmc", "gmd", "gme", "gpu",
-                                       "gpu7", "gpv", "i2cp", "pta", "rm",
-                                       "sdio1", "slxk", "spdo", "uac", "uda";
+                                       "cdev1", "cdev2", "dap1", "dap2", "dtf",
+                                       "gma", "gmb", "gmc", "gmd", "gme",
+                                       "gpu", "gpu7", "gpv", "i2cp", "pta",
+                                       "rm", "sdio1", "slxk", "spdo", "uac",
+                                       "uda";
                                nvidia,pull = <0>;
                                nvidia,tristate = <0>;
                        };
-                       conf_cdev2 {
-                               nvidia,pins = "cdev2";
-                               nvidia,pull = <1>;
-                               nvidia,tristate = <0>;
-                       };
                        conf_ck32 {
                                nvidia,pins = "ck32", "ddrc", "pmca", "pmcb",
                                        "pmcc", "pmcd", "pmce", "xm2c", "xm2d";
                cd-gpios = <&gpio 173 0>; /* gpio PV5 */
                wp-gpios = <&gpio 57 0>;  /* gpio PH1 */
                power-gpios = <&gpio 169 0>; /* gpio PV1 */
+               bus-width = <4>;
        };
 
        sdhci@c8000200 {
 
        sdhci@c8000600 {
                support-8bit;
+               bus-width = <8>;
        };
 
        gpio-keys {
                        linux,default-trigger = "rfkill0";
                };
        };
+
+       usb@c5004000 {
+               nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */
+       };
 };
index ec33116f5df92a5ef2d0dda633b29d3e7218943f..315971993cfdc61d4b054e02e96754feea09354c 100644 (file)
                cd-gpios = <&gpio 69 0>; /* gpio PI5 */
                wp-gpios = <&gpio 57 0>; /* gpio PH1 */
                power-gpios = <&gpio 70 0>; /* gpio PI6 */
+               bus-width = <4>;
        };
 
        sdhci@c8000600 {
                support-8bit;
+               bus-width = <8>;
        };
 
        usb@c5000000 {
                                0x00000000 0x00000000 0x00000000 0x00000000 >;
                };
        };
+
+       usb@c5004000 {
+               nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
+       };
 };
index 98efd5b0d7f9a085584e40a43ed366f2bd28e954..e4fcf9a8178a8e8c89818904bb58bf314494d869 100644 (file)
                                nvidia,tristate = <1>;
                        };
                        conf_atb {
-                               nvidia,pins = "atb", "cdev1", "dap1", "gma",
-                                       "gmc", "gmd", "gpu", "gpu7", "gpv",
-                                       "sdio1", "slxa", "slxk", "uac";
+                               nvidia,pins = "atb", "cdev1", "cdev2", "dap1",
+                                       "gma", "gmc", "gmd", "gpu", "gpu7",
+                                       "gpv", "sdio1", "slxa", "slxk", "uac";
                                nvidia,pull = <0>;
                                nvidia,tristate = <0>;
                        };
-                       conf_cdev2 {
-                               nvidia,pins = "cdev2", "csus", "spia", "spib",
-                                       "spid", "spif";
-                               nvidia,pull = <1>;
-                               nvidia,tristate = <1>;
-                       };
                        conf_ck32 {
                                nvidia,pins = "ck32", "ddrc", "pmca", "pmcb",
                                        "pmcc", "pmcd", "pmce", "xm2c", "xm2d";
                                nvidia,pull = <0>;
                        };
+                       conf_csus {
+                               nvidia,pins = "csus", "spia", "spib",
+                                       "spid", "spif";
+                               nvidia,pull = <1>;
+                               nvidia,tristate = <1>;
+                       };
                        conf_ddc {
                                nvidia,pins = "ddc", "dtf", "rm", "sdc", "sdd";
                                nvidia,pull = <2>;
                cd-gpios = <&gpio 121 0>;
                wp-gpios = <&gpio 122 0>;
        };
+
+       usb@c5004000 {
+               nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */
+       };
 };
index 71eb2e50a66824b4f8a441c547238132ea154e02..b922a26747e7c078596e5e8cabf44c3d29126757 100644 (file)
                cd-gpios = <&gpio 69 0>; /* gpio PI5 */
                wp-gpios = <&gpio 57 0>; /* gpio PH1 */
                power-gpios = <&gpio 70 0>; /* gpio PI6 */
+               bus-width = <4>;
        };
 
        sdhci@c8000600 {
                support-8bit;
+               bus-width = <8>;
+       };
+
+       usb@c5004000 {
+               nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
        };
 };
index 62a7b39f1c9a9e8f55ca409e5c192e312fe93d3b..15200a949a8137e9a33fd62660a9514fc695edf7 100644 (file)
                reg = < 0x70000868 0xd0     /* Pad control registers */
                        0x70003000 0x3e0 >; /* Mux registers */
        };
+
+       ahub {
+               compatible = "nvidia,tegra30-ahub";
+               reg = <0x70080000 0x200 0x70080200 0x100>;
+               interrupts = < 0 103 0x04 >;
+               nvidia,dma-request-selector = <&apbdma 1>;
+
+               ranges;
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               tegra_i2s0: i2s@70080300 {
+                       compatible = "nvidia,tegra30-i2s";
+                       reg = <0x70080300 0x100>;
+                       nvidia,ahub-cif-ids = <4 4>;
+               };
+
+               tegra_i2s1: i2s@70080400 {
+                       compatible = "nvidia,tegra30-i2s";
+                       reg = <0x70080400 0x100>;
+                       nvidia,ahub-cif-ids = <5 5>;
+               };
+
+               tegra_i2s2: i2s@70080500 {
+                       compatible = "nvidia,tegra30-i2s";
+                       reg = <0x70080500 0x100>;
+                       nvidia,ahub-cif-ids = <6 6>;
+               };
+
+               tegra_i2s3: i2s@70080600 {
+                       compatible = "nvidia,tegra30-i2s";
+                       reg = <0x70080600 0x100>;
+                       nvidia,ahub-cif-ids = <7 7>;
+               };
+
+               tegra_i2s4: i2s@70080700 {
+                       compatible = "nvidia,tegra30-i2s";
+                       reg = <0x70080700 0x100>;
+                       nvidia,ahub-cif-ids = <8 8>;
+               };
+       };
 };
index 95ce019c9b98686b5fb14f69fc93665daf964f49..a685e9706b7ba305b462b103899398b3521f2917 100644 (file)
@@ -353,9 +353,10 @@ static int irq2ctlr(int irq)
  *****************************************************************************/
 static irqreturn_t dma_irq_handler(int irq, void *data)
 {
-       int i;
        int ctlr;
-       unsigned int cnt = 0;
+       u32 sh_ier;
+       u32 sh_ipr;
+       u32 bank;
 
        ctlr = irq2ctlr(irq);
        if (ctlr < 0)
@@ -363,41 +364,39 @@ static irqreturn_t dma_irq_handler(int irq, void *data)
 
        dev_dbg(data, "dma_irq_handler\n");
 
-       if ((edma_shadow0_read_array(ctlr, SH_IPR, 0) == 0) &&
-           (edma_shadow0_read_array(ctlr, SH_IPR, 1) == 0))
-               return IRQ_NONE;
+       sh_ipr = edma_shadow0_read_array(ctlr, SH_IPR, 0);
+       if (!sh_ipr) {
+               sh_ipr = edma_shadow0_read_array(ctlr, SH_IPR, 1);
+               if (!sh_ipr)
+                       return IRQ_NONE;
+               sh_ier = edma_shadow0_read_array(ctlr, SH_IER, 1);
+               bank = 1;
+       } else {
+               sh_ier = edma_shadow0_read_array(ctlr, SH_IER, 0);
+               bank = 0;
+       }
 
-       while (1) {
-               int j;
-               if (edma_shadow0_read_array(ctlr, SH_IPR, 0) &
-                               edma_shadow0_read_array(ctlr, SH_IER, 0))
-                       j = 0;
-               else if (edma_shadow0_read_array(ctlr, SH_IPR, 1) &
-                               edma_shadow0_read_array(ctlr, SH_IER, 1))
-                       j = 1;
-               else
-                       break;
-               dev_dbg(data, "IPR%d %08x\n", j,
-                               edma_shadow0_read_array(ctlr, SH_IPR, j));
-               for (i = 0; i < 32; i++) {
-                       int k = (j << 5) + i;
-                       if ((edma_shadow0_read_array(ctlr, SH_IPR, j) & BIT(i))
-                                       && (edma_shadow0_read_array(ctlr,
-                                                       SH_IER, j) & BIT(i))) {
-                               /* Clear the corresponding IPR bits */
-                               edma_shadow0_write_array(ctlr, SH_ICR, j,
-                                                       BIT(i));
-                               if (edma_cc[ctlr]->intr_data[k].callback)
-                                       edma_cc[ctlr]->intr_data[k].callback(
-                                               k, DMA_COMPLETE,
-                                               edma_cc[ctlr]->intr_data[k].
-                                               data);
-                       }
+       do {
+               u32 slot;
+               u32 channel;
+
+               dev_dbg(data, "IPR%d %08x\n", bank, sh_ipr);
+
+               slot = __ffs(sh_ipr);
+               sh_ipr &= ~(BIT(slot));
+
+               if (sh_ier & BIT(slot)) {
+                       channel = (bank << 5) | slot;
+                       /* Clear the corresponding IPR bits */
+                       edma_shadow0_write_array(ctlr, SH_ICR, bank,
+                                       BIT(slot));
+                       if (edma_cc[ctlr]->intr_data[channel].callback)
+                               edma_cc[ctlr]->intr_data[channel].callback(
+                                       channel, DMA_COMPLETE,
+                                       edma_cc[ctlr]->intr_data[channel].data);
                }
-               cnt++;
-               if (cnt > 10)
-                       break;
-       }
+       } while (sh_ipr);
+
        edma_shadow0_write(ctlr, SH_IEVAL, 1);
        return IRQ_HANDLED;
 }
index cf94552d52740cd8c8d4903aa0549a05369b73cf..34290d14754b41b827208528c1a317e5d5fa62b3 100644 (file)
 
 #define UART_SHIFT     2
 
-               .pushsection .data
-davinci_uart_phys:     .word   0
-davinci_uart_virt:     .word   0
-               .popsection
-
-               .macro addruart, rp, rv, tmp
-
-               /* Use davinci_uart_phys/virt if already configured */
-10:            adr     \rp, 99f                @ get effective addr of 99f
-               ldr     \rv, [\rp]              @ get absolute addr of 99f
-               sub     \rv, \rv, \rp           @ offset between the two
-               ldr     \rp, [\rp, #4]          @ abs addr of omap_uart_phys
-               sub     \tmp, \rp, \rv          @ make it effective
-               ldr     \rp, [\tmp, #0]         @ davinci_uart_phys
-               ldr     \rv, [\tmp, #4]         @ davinci_uart_virt
-               cmp     \rp, #0                 @ is port configured?
-               cmpne   \rv, #0
-               bne     100f                    @ already configured
-
-               /* Check the debug UART address set in uncompress.h */
-               and     \rp, pc, #0xff000000
-               ldr     \rv, =DAVINCI_UART_INFO_OFS
-               add     \rp, \rp, \rv
-
-               /* Copy uart phys address from decompressor uart info */
-               ldr     \rv, [\rp, #0]
-               str     \rv, [\tmp, #0]
-
-               /* Copy uart virt address from decompressor uart info */
-               ldr     \rv, [\rp, #4]
-               str     \rv, [\tmp, #4]
-
-               b       10b
+#if defined(CONFIG_DEBUG_DAVINCI_DMx_UART0)
+#define UART_BASE      DAVINCI_UART0_BASE
+#elif defined(CONFIG_DEBUG_DAVINCI_DA8XX_UART0)
+#define UART_BASE      DA8XX_UART0_BASE
+#elif defined(CONFIG_DEBUG_DAVINCI_DA8XX_UART1)
+#define UART_BASE      DA8XX_UART1_BASE
+#elif defined(CONFIG_DEBUG_DAVINCI_DA8XX_UART2)
+#define UART_BASE      DA8XX_UART2_BASE
+#elif defined(CONFIG_DEBUG_DAVINCI_TNETV107X_UART1)
+#define UART_BASE      TNETV107X_UART2_BASE
+#define UART_VIRTBASE  TNETV107X_UART2_VIRT
+#else
+#error "Select a specifc port for DEBUG_LL"
+#endif
 
-               .align
-99:            .word   .
-               .word   davinci_uart_phys
-               .ltorg
+#ifndef UART_VIRTBASE
+#define UART_VIRTBASE  IO_ADDRESS(UART_BASE)
+#endif
 
-100:
+               .macro addruart, rp, rv, tmp
+               ldr     \rp, =UART_BASE
+               ldr     \rv, =UART_VIRTBASE
                .endm
 
                .macro  senduart,rd,rx
index 2184691ebc2f78ddfcb5989e2d880ac77a5d3749..16bb42291d39d5154f99f1adc91590f18c2785f8 100644 (file)
@@ -22,7 +22,7 @@
 /*
  * I/O mapping
  */
-#define IO_PHYS                                0x01c00000UL
+#define IO_PHYS                                UL(0x01c00000)
 #define IO_OFFSET                      0xfd000000 /* Virtual IO = 0xfec00000 */
 #define IO_SIZE                                0x00400000
 #define IO_VIRT                                (IO_PHYS + IO_OFFSET)
index e347d88fef91dbd4a64e4ecf62bb11a7c2b753e7..46b3cd11c3c2ec582e2972202f1c6277494fe9ea 100644 (file)
 
 #include <mach/hardware.h>
 
-/*
- * Stolen area that contains debug uart physical and virtual addresses.  These
- * addresses are filled in by the uncompress.h code, and are used by the debug
- * macros in debug-macro.S.
- *
- * This area sits just below the page tables (see arch/arm/kernel/head.S).
- * We define it as a relative offset from start of usable RAM.
- */
-#define DAVINCI_UART_INFO_OFS  0x3ff8
-
 #define DAVINCI_UART0_BASE     (IO_PHYS + 0x20000)
 #define DAVINCI_UART1_BASE     (IO_PHYS + 0x20400)
 #define DAVINCI_UART2_BASE     (IO_PHYS + 0x20800)
index da2fb2c2155a2ac84d242ad76c4de2842aa33d31..18cfd4977155b468970559945663e05a48bb2000 100644 (file)
@@ -43,37 +43,27 @@ static inline void flush(void)
                barrier();
 }
 
-static inline void set_uart_info(u32 phys, void * __iomem virt)
+static inline void set_uart_info(u32 phys)
 {
-       /*
-        * Get address of some.bss variable and round it down
-        * a la CONFIG_AUTO_ZRELADDR.
-        */
-       u32 ram_start = (u32)&uart & 0xf8000000;
-       u32 *uart_info = (u32 *)(ram_start + DAVINCI_UART_INFO_OFS);
-
        uart = (u32 *)phys;
-       uart_info[0] = phys;
-       uart_info[1] = (u32)virt;
 }
 
-#define _DEBUG_LL_ENTRY(machine, phys, virt)                   \
-       if (machine_is_##machine()) {                           \
-               set_uart_info(phys, virt);                      \
-               break;                                          \
+#define _DEBUG_LL_ENTRY(machine, phys)                         \
+       {                                                       \
+               if (machine_is_##machine()) {                   \
+                       set_uart_info(phys);                    \
+                       break;                                  \
+               }                                               \
        }
 
 #define DEBUG_LL_DAVINCI(machine, port)                                \
-       _DEBUG_LL_ENTRY(machine, DAVINCI_UART##port##_BASE,     \
-                       IO_ADDRESS(DAVINCI_UART##port##_BASE))
+       _DEBUG_LL_ENTRY(machine, DAVINCI_UART##port##_BASE)
 
 #define DEBUG_LL_DA8XX(machine, port)                          \
-       _DEBUG_LL_ENTRY(machine, DA8XX_UART##port##_BASE,       \
-                       IO_ADDRESS(DA8XX_UART##port##_BASE))
+       _DEBUG_LL_ENTRY(machine, DA8XX_UART##port##_BASE)
 
 #define DEBUG_LL_TNETV107X(machine, port)                      \
-       _DEBUG_LL_ENTRY(machine, TNETV107X_UART##port##_BASE,   \
-                       TNETV107X_UART##port##_VIRT)
+       _DEBUG_LL_ENTRY(machine, TNETV107X_UART##port##_BASE)
 
 static inline void __arch_decomp_setup(unsigned long arch_id)
 {
index 66b1494f23a6f0f4b2182f23ae2433089bcd1f53..ad1a91ab6acd9978b4418b051c3b68cf90cf1565 100644 (file)
@@ -675,7 +675,7 @@ int ep93xx_keypad_acquire_gpio(struct platform_device *pdev)
 fail_gpio_d:
        gpio_free(EP93XX_GPIO_LINE_C(i));
 fail_gpio_c:
-       for ( ; i >= 0; --i) {
+       for (--i; i >= 0; --i) {
                gpio_free(EP93XX_GPIO_LINE_C(i));
                gpio_free(EP93XX_GPIO_LINE_D(i));
        }
index 15b05b89cc399ddd3bf36658ec3d68f1bc12581b..e3cfd5fd7dd54bb694789f1b3553e1abe3569bf5 100644 (file)
@@ -85,10 +85,10 @@ config EXYNOS4_SETUP_FIMD0
        help
          Common setup code for FIMD0.
 
-config EXYNOS4_DEV_SYSMMU
+config EXYNOS_DEV_SYSMMU
        bool
        help
-         Common setup code for SYSTEM MMU in EXYNOS4
+         Common setup code for SYSTEM MMU in EXYNOS platforms
 
 config EXYNOS4_DEV_DWMCI
        bool
@@ -201,12 +201,12 @@ config MACH_SMDKV310
        select S3C_DEV_HSMMC3
        select SAMSUNG_DEV_BACKLIGHT
        select EXYNOS_DEV_DRM
+       select EXYNOS_DEV_SYSMMU
        select EXYNOS4_DEV_AHCI
        select SAMSUNG_DEV_KEYPAD
        select EXYNOS4_DEV_DMA
        select SAMSUNG_DEV_PWM
        select EXYNOS4_DEV_USB_OHCI
-       select EXYNOS4_DEV_SYSMMU
        select EXYNOS4_SETUP_FIMD0
        select EXYNOS4_SETUP_I2C1
        select EXYNOS4_SETUP_KEYPAD
@@ -225,7 +225,6 @@ config MACH_ARMLEX4210
        select S3C_DEV_HSMMC3
        select EXYNOS4_DEV_AHCI
        select EXYNOS4_DEV_DMA
-       select EXYNOS4_DEV_SYSMMU
        select EXYNOS4_SETUP_SDHCI
        help
          Machine support for Samsung ARMLEX4210 based on EXYNOS4210
@@ -256,6 +255,7 @@ config MACH_UNIVERSAL_C210
        select S5P_DEV_MFC
        select S5P_DEV_ONENAND
        select S5P_DEV_TV
+       select EXYNOS_DEV_SYSMMU
        select EXYNOS4_DEV_DMA
        select EXYNOS_DEV_DRM
        select EXYNOS4_SETUP_FIMD0
@@ -332,6 +332,7 @@ config MACH_ORIGEN
        select SAMSUNG_DEV_BACKLIGHT
        select SAMSUNG_DEV_PWM
        select EXYNOS_DEV_DRM
+       select EXYNOS_DEV_SYSMMU
        select EXYNOS4_DEV_DMA
        select EXYNOS4_DEV_USB_OHCI
        select EXYNOS4_SETUP_FIMD0
@@ -360,6 +361,7 @@ config MACH_SMDK4212
        select SAMSUNG_DEV_BACKLIGHT
        select SAMSUNG_DEV_KEYPAD
        select SAMSUNG_DEV_PWM
+       select EXYNOS_DEV_SYSMMU
        select EXYNOS4_DEV_DMA
        select EXYNOS4_SETUP_I2C1
        select EXYNOS4_SETUP_I2C3
index 8631840d1b5e85ce8d959430bcdbdeadb339afbb..272625231c73d168599745b4624b11c47da72cee 100644 (file)
@@ -50,7 +50,7 @@ obj-$(CONFIG_MACH_EXYNOS5_DT)         += mach-exynos5-dt.o
 obj-y                                  += dev-uart.o
 obj-$(CONFIG_ARCH_EXYNOS4)             += dev-audio.o
 obj-$(CONFIG_EXYNOS4_DEV_AHCI)         += dev-ahci.o
-obj-$(CONFIG_EXYNOS4_DEV_SYSMMU)       += dev-sysmmu.o
+obj-$(CONFIG_EXYNOS_DEV_SYSMMU)                += dev-sysmmu.o
 obj-$(CONFIG_EXYNOS4_DEV_DWMCI)                += dev-dwmci.o
 obj-$(CONFIG_EXYNOS4_DEV_DMA)          += dma.o
 obj-$(CONFIG_EXYNOS4_DEV_USB_OHCI)     += dev-ohci.o
index 6efd1e5919fdebcd389e61cf48e25b1967a75bb1..bcb7db45314599cd975a6ad904d199c881c4e6cf 100644 (file)
@@ -168,7 +168,7 @@ static int exynos4_clk_ip_tv_ctrl(struct clk *clk, int enable)
        return s5p_gatectrl(EXYNOS4_CLKGATE_IP_TV, clk, enable);
 }
 
-static int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable)
+int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable)
 {
        return s5p_gatectrl(EXYNOS4_CLKGATE_IP_IMAGE, clk, enable);
 }
@@ -198,6 +198,11 @@ static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable)
        return s5p_gatectrl(EXYNOS4_CLKGATE_IP_PERIR, clk, enable);
 }
 
+int exynos4_clk_ip_dmc_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS4_CLKGATE_IP_DMC, clk, enable);
+}
+
 static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
 {
        return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
@@ -678,61 +683,55 @@ static struct clk exynos4_init_clocks_off[] = {
                .enable         = exynos4_clk_ip_peril_ctrl,
                .ctrlbit        = (1 << 14),
        }, {
-               .name           = "SYSMMU_MDMA",
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(mfc_l, 0),
+               .enable         = exynos4_clk_ip_mfc_ctrl,
+               .ctrlbit        = (1 << 1),
+       }, {
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(mfc_r, 1),
+               .enable         = exynos4_clk_ip_mfc_ctrl,
+               .ctrlbit        = (1 << 2),
+       }, {
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(tv, 2),
+               .enable         = exynos4_clk_ip_tv_ctrl,
+               .ctrlbit        = (1 << 4),
+       }, {
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(jpeg, 3),
+               .enable         = exynos4_clk_ip_cam_ctrl,
+               .ctrlbit        = (1 << 11),
+       }, {
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(rot, 4),
                .enable         = exynos4_clk_ip_image_ctrl,
-               .ctrlbit        = (1 << 5),
+               .ctrlbit        = (1 << 4),
        }, {
-               .name           = "SYSMMU_FIMC0",
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(fimc0, 5),
                .enable         = exynos4_clk_ip_cam_ctrl,
                .ctrlbit        = (1 << 7),
        }, {
-               .name           = "SYSMMU_FIMC1",
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(fimc1, 6),
                .enable         = exynos4_clk_ip_cam_ctrl,
                .ctrlbit        = (1 << 8),
        }, {
-               .name           = "SYSMMU_FIMC2",
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(fimc2, 7),
                .enable         = exynos4_clk_ip_cam_ctrl,
                .ctrlbit        = (1 << 9),
        }, {
-               .name           = "SYSMMU_FIMC3",
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(fimc3, 8),
                .enable         = exynos4_clk_ip_cam_ctrl,
                .ctrlbit        = (1 << 10),
        }, {
-               .name           = "SYSMMU_JPEG",
-               .enable         = exynos4_clk_ip_cam_ctrl,
-               .ctrlbit        = (1 << 11),
-       }, {
-               .name           = "SYSMMU_FIMD0",
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(fimd0, 10),
                .enable         = exynos4_clk_ip_lcd0_ctrl,
                .ctrlbit        = (1 << 4),
-       }, {
-               .name           = "SYSMMU_FIMD1",
-               .enable         = exynos4_clk_ip_lcd1_ctrl,
-               .ctrlbit        = (1 << 4),
-       }, {
-               .name           = "SYSMMU_PCIe",
-               .enable         = exynos4_clk_ip_fsys_ctrl,
-               .ctrlbit        = (1 << 18),
-       }, {
-               .name           = "SYSMMU_G2D",
-               .enable         = exynos4_clk_ip_image_ctrl,
-               .ctrlbit        = (1 << 3),
-       }, {
-               .name           = "SYSMMU_ROTATOR",
-               .enable         = exynos4_clk_ip_image_ctrl,
-               .ctrlbit        = (1 << 4),
-       }, {
-               .name           = "SYSMMU_TV",
-               .enable         = exynos4_clk_ip_tv_ctrl,
-               .ctrlbit        = (1 << 4),
-       }, {
-               .name           = "SYSMMU_MFC_L",
-               .enable         = exynos4_clk_ip_mfc_ctrl,
-               .ctrlbit        = (1 << 1),
-       }, {
-               .name           = "SYSMMU_MFC_R",
-               .enable         = exynos4_clk_ip_mfc_ctrl,
-               .ctrlbit        = (1 << 2),
        }
 };
 
index cb71c29c14d1adf7db49beeb1efe2b3a9b903ae5..28a1197011823b132c10542db7795d3b3eddb588 100644 (file)
@@ -26,5 +26,7 @@ extern struct clk *exynos4_clkset_group_list[];
 extern int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable);
 extern int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable);
 extern int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable);
+extern int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable);
+extern int exynos4_clk_ip_dmc_ctrl(struct clk *clk, int enable);
 
 #endif /* __ASM_ARCH_CLOCK_H */
index 3b131e4b6ef57ec6e21428a640f4ad092f27e2fb..b8689ff60baf5cb721a5d1d5caef45393fa60743 100644 (file)
@@ -26,6 +26,7 @@
 #include <mach/hardware.h>
 #include <mach/map.h>
 #include <mach/regs-clock.h>
+#include <mach/sysmmu.h>
 
 #include "common.h"
 #include "clock-exynos4.h"
@@ -94,6 +95,16 @@ static struct clk init_clocks_off[] = {
                .devname        = "exynos4-fb.1",
                .enable         = exynos4_clk_ip_lcd1_ctrl,
                .ctrlbit        = (1 << 0),
+       }, {
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(2d, 14),
+               .enable         = exynos4_clk_ip_image_ctrl,
+               .ctrlbit        = (1 << 3),
+       }, {
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(fimd1, 11),
+               .enable         = exynos4_clk_ip_lcd1_ctrl,
+               .ctrlbit        = (1 << 4),
        },
 };
 
index 3ecc01e06f7497c1408f795023bdf78dba8de7bb..98823120570ee1f809752e3135594776b01b2527 100644 (file)
@@ -26,6 +26,7 @@
 #include <mach/hardware.h>
 #include <mach/map.h>
 #include <mach/regs-clock.h>
+#include <mach/sysmmu.h>
 
 #include "common.h"
 #include "clock-exynos4.h"
@@ -39,6 +40,16 @@ static struct sleep_save exynos4212_clock_save[] = {
 };
 #endif
 
+static int exynos4212_clk_ip_isp0_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS4_CLKGATE_IP_ISP0, clk, enable);
+}
+
+static int exynos4212_clk_ip_isp1_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS4_CLKGATE_IP_ISP1, clk, enable);
+}
+
 static struct clk *clk_src_mpll_user_list[] = {
        [0] = &clk_fin_mpll,
        [1] = &exynos4_clk_mout_mpll.clk,
@@ -66,7 +77,22 @@ static struct clksrc_clk clksrcs[] = {
 };
 
 static struct clk init_clocks_off[] = {
-       /* nothing here yet */
+       {
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(2d, 14),
+               .enable         = exynos4_clk_ip_dmc_ctrl,
+               .ctrlbit        = (1 << 24),
+       }, {
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(isp, 9),
+               .enable         = exynos4212_clk_ip_isp0_ctrl,
+               .ctrlbit        = (7 << 8),
+       }, {
+               .name           = SYSMMU_CLOCK_NAME2,
+               .devname        = SYSMMU_CLOCK_DEVNAME(isp, 9),
+               .enable         = exynos4212_clk_ip_isp1_ctrl,
+               .ctrlbit        = (1 << 4),
+       }
 };
 
 #ifdef CONFIG_PM_SLEEP
index 7ac6ff4c46bd382839234a3d8a19ffb2042e311b..9f87a07b0bf80672ab96c70c92764eab2df32b1a 100644 (file)
@@ -82,6 +82,11 @@ static int exynos5_clksrc_mask_peric0_ctrl(struct clk *clk, int enable)
        return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_PERIC0, clk, enable);
 }
 
+static int exynos5_clk_ip_acp_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ACP, clk, enable);
+}
+
 static int exynos5_clk_ip_core_ctrl(struct clk *clk, int enable)
 {
        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)
        return s5p_gatectrl(EXYNOS5_CLKGATE_IP_PERIS, clk, enable);
 }
 
+static int exynos5_clk_ip_gscl_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_GSCL, clk, enable);
+}
+
+static int exynos5_clk_ip_isp0_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ISP0, clk, enable);
+}
+
+static int exynos5_clk_ip_isp1_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ISP1, clk, enable);
+}
+
 /* Core list of CMU_CPU side */
 
 static struct clksrc_clk exynos5_clk_mout_apll = {
@@ -630,6 +650,76 @@ static struct clk exynos5_init_clocks_off[] = {
                .parent         = &exynos5_clk_aclk_66.clk,
                .enable         = exynos5_clk_ip_peric_ctrl,
                .ctrlbit        = (1 << 14),
+       }, {
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(mfc_l, 0),
+               .enable         = &exynos5_clk_ip_mfc_ctrl,
+               .ctrlbit        = (1 << 1),
+       }, {
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(mfc_r, 1),
+               .enable         = &exynos5_clk_ip_mfc_ctrl,
+               .ctrlbit        = (1 << 2),
+       }, {
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(tv, 2),
+               .enable         = &exynos5_clk_ip_disp1_ctrl,
+               .ctrlbit        = (1 << 9)
+       }, {
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(jpeg, 3),
+               .enable         = &exynos5_clk_ip_gen_ctrl,
+               .ctrlbit        = (1 << 7),
+       }, {
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(rot, 4),
+               .enable         = &exynos5_clk_ip_gen_ctrl,
+               .ctrlbit        = (1 << 6)
+       }, {
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(gsc0, 5),
+               .enable         = &exynos5_clk_ip_gscl_ctrl,
+               .ctrlbit        = (1 << 7),
+       }, {
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(gsc1, 6),
+               .enable         = &exynos5_clk_ip_gscl_ctrl,
+               .ctrlbit        = (1 << 8),
+       }, {
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(gsc2, 7),
+               .enable         = &exynos5_clk_ip_gscl_ctrl,
+               .ctrlbit        = (1 << 9),
+       }, {
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(gsc3, 8),
+               .enable         = &exynos5_clk_ip_gscl_ctrl,
+               .ctrlbit        = (1 << 10),
+       }, {
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(isp, 9),
+               .enable         = &exynos5_clk_ip_isp0_ctrl,
+               .ctrlbit        = (0x3F << 8),
+       }, {
+               .name           = SYSMMU_CLOCK_NAME2,
+               .devname        = SYSMMU_CLOCK_DEVNAME(isp, 9),
+               .enable         = &exynos5_clk_ip_isp1_ctrl,
+               .ctrlbit        = (0xF << 4),
+       }, {
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(camif0, 12),
+               .enable         = &exynos5_clk_ip_gscl_ctrl,
+               .ctrlbit        = (1 << 11),
+       }, {
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(camif1, 13),
+               .enable         = &exynos5_clk_ip_gscl_ctrl,
+               .ctrlbit        = (1 << 12),
+       }, {
+               .name           = SYSMMU_CLOCK_NAME,
+               .devname        = SYSMMU_CLOCK_DEVNAME(2d, 14),
+               .enable         = &exynos5_clk_ip_acp_ctrl,
+               .ctrlbit        = (1 << 7)
        }
 };
 
index 781563fcb156d7dd90926fe885239fb3a8c1d82b..c5b1ea301df044567ad36469120854636786a620 100644 (file)
@@ -1,9 +1,9 @@
-/* linux/arch/arm/mach-exynos4/dev-sysmmu.c
+/* linux/arch/arm/mach-exynos/dev-sysmmu.c
  *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
  *
- * EXYNOS4 - System MMU support
+ * EXYNOS - System MMU support
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
 
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
-#include <linux/export.h>
+
+#include <plat/cpu.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
 #include <mach/sysmmu.h>
-#include <plat/s5p-clock.h>
-
-/* These names must be equal to the clock names in mach-exynos4/clock.c */
-const char *sysmmu_ips_name[EXYNOS4_SYSMMU_TOTAL_IPNUM] = {
-       "SYSMMU_MDMA"   ,
-       "SYSMMU_SSS"    ,
-       "SYSMMU_FIMC0"  ,
-       "SYSMMU_FIMC1"  ,
-       "SYSMMU_FIMC2"  ,
-       "SYSMMU_FIMC3"  ,
-       "SYSMMU_JPEG"   ,
-       "SYSMMU_FIMD0"  ,
-       "SYSMMU_FIMD1"  ,
-       "SYSMMU_PCIe"   ,
-       "SYSMMU_G2D"    ,
-       "SYSMMU_ROTATOR",
-       "SYSMMU_MDMA2"  ,
-       "SYSMMU_TV"     ,
-       "SYSMMU_MFC_L"  ,
-       "SYSMMU_MFC_R"  ,
-};
 
-static struct resource exynos4_sysmmu_resource[] = {
-       [0] = {
-               .start  = EXYNOS4_PA_SYSMMU_MDMA,
-               .end    = EXYNOS4_PA_SYSMMU_MDMA + SZ_64K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_SYSMMU_MDMA0_0,
-               .end    = IRQ_SYSMMU_MDMA0_0,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [2] = {
-               .start  = EXYNOS4_PA_SYSMMU_SSS,
-               .end    = EXYNOS4_PA_SYSMMU_SSS + SZ_64K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [3] = {
-               .start  = IRQ_SYSMMU_SSS_0,
-               .end    = IRQ_SYSMMU_SSS_0,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [4] = {
-               .start  = EXYNOS4_PA_SYSMMU_FIMC0,
-               .end    = EXYNOS4_PA_SYSMMU_FIMC0 + SZ_64K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [5] = {
-               .start  = IRQ_SYSMMU_FIMC0_0,
-               .end    = IRQ_SYSMMU_FIMC0_0,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [6] = {
-               .start  = EXYNOS4_PA_SYSMMU_FIMC1,
-               .end    = EXYNOS4_PA_SYSMMU_FIMC1 + SZ_64K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [7] = {
-               .start  = IRQ_SYSMMU_FIMC1_0,
-               .end    = IRQ_SYSMMU_FIMC1_0,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [8] = {
-               .start  = EXYNOS4_PA_SYSMMU_FIMC2,
-               .end    = EXYNOS4_PA_SYSMMU_FIMC2 + SZ_64K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [9] = {
-               .start  = IRQ_SYSMMU_FIMC2_0,
-               .end    = IRQ_SYSMMU_FIMC2_0,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [10] = {
-               .start  = EXYNOS4_PA_SYSMMU_FIMC3,
-               .end    = EXYNOS4_PA_SYSMMU_FIMC3 + SZ_64K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [11] = {
-               .start  = IRQ_SYSMMU_FIMC3_0,
-               .end    = IRQ_SYSMMU_FIMC3_0,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [12] = {
-               .start  = EXYNOS4_PA_SYSMMU_JPEG,
-               .end    = EXYNOS4_PA_SYSMMU_JPEG + SZ_64K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [13] = {
-               .start  = IRQ_SYSMMU_JPEG_0,
-               .end    = IRQ_SYSMMU_JPEG_0,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [14] = {
-               .start  = EXYNOS4_PA_SYSMMU_FIMD0,
-               .end    = EXYNOS4_PA_SYSMMU_FIMD0 + SZ_64K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [15] = {
-               .start  = IRQ_SYSMMU_LCD0_M0_0,
-               .end    = IRQ_SYSMMU_LCD0_M0_0,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [16] = {
-               .start  = EXYNOS4_PA_SYSMMU_FIMD1,
-               .end    = EXYNOS4_PA_SYSMMU_FIMD1 + SZ_64K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [17] = {
-               .start  = IRQ_SYSMMU_LCD1_M1_0,
-               .end    = IRQ_SYSMMU_LCD1_M1_0,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [18] = {
-               .start  = EXYNOS4_PA_SYSMMU_PCIe,
-               .end    = EXYNOS4_PA_SYSMMU_PCIe + SZ_64K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [19] = {
-               .start  = IRQ_SYSMMU_PCIE_0,
-               .end    = IRQ_SYSMMU_PCIE_0,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [20] = {
-               .start  = EXYNOS4_PA_SYSMMU_G2D,
-               .end    = EXYNOS4_PA_SYSMMU_G2D + SZ_64K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [21] = {
-               .start  = IRQ_SYSMMU_2D_0,
-               .end    = IRQ_SYSMMU_2D_0,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [22] = {
-               .start  = EXYNOS4_PA_SYSMMU_ROTATOR,
-               .end    = EXYNOS4_PA_SYSMMU_ROTATOR + SZ_64K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [23] = {
-               .start  = IRQ_SYSMMU_ROTATOR_0,
-               .end    = IRQ_SYSMMU_ROTATOR_0,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [24] = {
-               .start  = EXYNOS4_PA_SYSMMU_MDMA2,
-               .end    = EXYNOS4_PA_SYSMMU_MDMA2 + SZ_64K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [25] = {
-               .start  = IRQ_SYSMMU_MDMA1_0,
-               .end    = IRQ_SYSMMU_MDMA1_0,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [26] = {
-               .start  = EXYNOS4_PA_SYSMMU_TV,
-               .end    = EXYNOS4_PA_SYSMMU_TV + SZ_64K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [27] = {
-               .start  = IRQ_SYSMMU_TV_M0_0,
-               .end    = IRQ_SYSMMU_TV_M0_0,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [28] = {
-               .start  = EXYNOS4_PA_SYSMMU_MFC_L,
-               .end    = EXYNOS4_PA_SYSMMU_MFC_L + SZ_64K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [29] = {
-               .start  = IRQ_SYSMMU_MFC_M0_0,
-               .end    = IRQ_SYSMMU_MFC_M0_0,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [30] = {
-               .start  = EXYNOS4_PA_SYSMMU_MFC_R,
-               .end    = EXYNOS4_PA_SYSMMU_MFC_R + SZ_64K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [31] = {
-               .start  = IRQ_SYSMMU_MFC_M1_0,
-               .end    = IRQ_SYSMMU_MFC_M1_0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
+static u64 exynos_sysmmu_dma_mask = DMA_BIT_MASK(32);
+
+#define SYSMMU_PLATFORM_DEVICE(ipname, devid)                          \
+static struct sysmmu_platform_data platdata_##ipname = {               \
+       .dbgname = #ipname,                                             \
+};                                                                     \
+struct platform_device SYSMMU_PLATDEV(ipname) =                                \
+{                                                                      \
+       .name           = SYSMMU_DEVNAME_BASE,                          \
+       .id             = devid,                                        \
+       .dev            = {                                             \
+               .dma_mask               = &exynos_sysmmu_dma_mask,      \
+               .coherent_dma_mask      = DMA_BIT_MASK(32),             \
+               .platform_data          = &platdata_##ipname,           \
+       },                                                              \
+}
+
+SYSMMU_PLATFORM_DEVICE(mfc_l,  0);
+SYSMMU_PLATFORM_DEVICE(mfc_r,  1);
+SYSMMU_PLATFORM_DEVICE(tv,     2);
+SYSMMU_PLATFORM_DEVICE(jpeg,   3);
+SYSMMU_PLATFORM_DEVICE(rot,    4);
+SYSMMU_PLATFORM_DEVICE(fimc0,  5); /* fimc* and gsc* exist exclusively */
+SYSMMU_PLATFORM_DEVICE(fimc1,  6);
+SYSMMU_PLATFORM_DEVICE(fimc2,  7);
+SYSMMU_PLATFORM_DEVICE(fimc3,  8);
+SYSMMU_PLATFORM_DEVICE(gsc0,   5);
+SYSMMU_PLATFORM_DEVICE(gsc1,   6);
+SYSMMU_PLATFORM_DEVICE(gsc2,   7);
+SYSMMU_PLATFORM_DEVICE(gsc3,   8);
+SYSMMU_PLATFORM_DEVICE(isp,    9);
+SYSMMU_PLATFORM_DEVICE(fimd0,  10);
+SYSMMU_PLATFORM_DEVICE(fimd1,  11);
+SYSMMU_PLATFORM_DEVICE(camif0, 12);
+SYSMMU_PLATFORM_DEVICE(camif1, 13);
+SYSMMU_PLATFORM_DEVICE(2d,     14);
+
+#define SYSMMU_RESOURCE_NAME(core, ipname) sysmmures_##core##_##ipname
+
+#define SYSMMU_RESOURCE(core, ipname)                                  \
+       static struct resource SYSMMU_RESOURCE_NAME(core, ipname)[] __initdata =
+
+#define DEFINE_SYSMMU_RESOURCE(core, mem, irq)                         \
+       DEFINE_RES_MEM_NAMED(core##_PA_SYSMMU_##mem, SZ_4K, #mem),      \
+       DEFINE_RES_IRQ_NAMED(core##_IRQ_SYSMMU_##irq##_0, #mem)
+
+#define SYSMMU_RESOURCE_DEFINE(core, ipname, mem, irq)                 \
+       SYSMMU_RESOURCE(core, ipname) {                                 \
+               DEFINE_SYSMMU_RESOURCE(core, mem, irq)                  \
+       }
 
-struct platform_device exynos4_device_sysmmu = {
-       .name           = "s5p-sysmmu",
-       .id             = 32,
-       .num_resources  = ARRAY_SIZE(exynos4_sysmmu_resource),
-       .resource       = exynos4_sysmmu_resource,
+struct sysmmu_resource_map {
+       struct platform_device *pdev;
+       struct resource *res;
+       u32 rnum;
+       struct device *pdd;
+       char *clocknames;
 };
-EXPORT_SYMBOL(exynos4_device_sysmmu);
 
-static struct clk *sysmmu_clk[S5P_SYSMMU_TOTAL_IPNUM];
-void sysmmu_clk_init(struct device *dev, sysmmu_ips ips)
-{
-       sysmmu_clk[ips] = clk_get(dev, sysmmu_ips_name[ips]);
-       if (IS_ERR(sysmmu_clk[ips]))
-               sysmmu_clk[ips] = NULL;
-       else
-               clk_put(sysmmu_clk[ips]);
+#define SYSMMU_RESOURCE_MAPPING(core, ipname, resname) {               \
+       .pdev = &SYSMMU_PLATDEV(ipname),                                \
+       .res = SYSMMU_RESOURCE_NAME(EXYNOS##core, resname),             \
+       .rnum = ARRAY_SIZE(SYSMMU_RESOURCE_NAME(EXYNOS##core, resname)),\
+       .clocknames = SYSMMU_CLOCK_NAME,                                \
 }
 
-void sysmmu_clk_enable(sysmmu_ips ips)
-{
-       if (sysmmu_clk[ips])
-               clk_enable(sysmmu_clk[ips]);
+#define SYSMMU_RESOURCE_MAPPING_MC(core, ipname, resname, pdata) {     \
+       .pdev = &SYSMMU_PLATDEV(ipname),                                \
+       .res = SYSMMU_RESOURCE_NAME(EXYNOS##core, resname),             \
+       .rnum = ARRAY_SIZE(SYSMMU_RESOURCE_NAME(EXYNOS##core, resname)),\
+       .clocknames = SYSMMU_CLOCK_NAME "," SYSMMU_CLOCK_NAME2,         \
+}
+
+#ifdef CONFIG_EXYNOS_DEV_PD
+#define SYSMMU_RESOURCE_MAPPING_PD(core, ipname, resname, pd) {                \
+       .pdev = &SYSMMU_PLATDEV(ipname),                                \
+       .res = &SYSMMU_RESOURCE_NAME(EXYNOS##core, resname),            \
+       .rnum = ARRAY_SIZE(SYSMMU_RESOURCE_NAME(EXYNOS##core, resname)),\
+       .clocknames = SYSMMU_CLOCK_NAME,                                \
+       .pdd = &exynos##core##_device_pd[pd].dev,                       \
+}
+
+#define SYSMMU_RESOURCE_MAPPING_MCPD(core, ipname, resname, pd, pdata) {\
+       .pdev = &SYSMMU_PLATDEV(ipname),                                \
+       .res = &SYSMMU_RESOURCE_NAME(EXYNOS##core, resname),            \
+       .rnum = ARRAY_SIZE(SYSMMU_RESOURCE_NAME(EXYNOS##core, resname)),\
+       .clocknames = SYSMMU_CLOCK_NAME "," SYSMMU_CLOCK_NAME2,         \
+       .pdd = &exynos##core##_device_pd[pd].dev,                       \
 }
+#else
+#define SYSMMU_RESOURCE_MAPPING_PD(core, ipname, resname, pd)          \
+               SYSMMU_RESOURCE_MAPPING(core, ipname, resname)
+#define SYSMMU_RESOURCE_MAPPING_MCPD(core, ipname, resname, pd, pdata) \
+               SYSMMU_RESOURCE_MAPPING_MC(core, ipname, resname, pdata)
+
+#endif /* CONFIG_EXYNOS_DEV_PD */
+
+#ifdef CONFIG_ARCH_EXYNOS4
+SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimc0, FIMC0,  FIMC0);
+SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimc1, FIMC1,  FIMC1);
+SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimc2, FIMC2,  FIMC2);
+SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimc3, FIMC3,  FIMC3);
+SYSMMU_RESOURCE_DEFINE(EXYNOS4, jpeg,  JPEG,   JPEG);
+SYSMMU_RESOURCE_DEFINE(EXYNOS4, 2d,    G2D,    2D);
+SYSMMU_RESOURCE_DEFINE(EXYNOS4, tv,    TV,     TV_M0);
+SYSMMU_RESOURCE_DEFINE(EXYNOS4, 2d_acp,        2D_ACP, 2D);
+SYSMMU_RESOURCE_DEFINE(EXYNOS4, rot,   ROTATOR, ROTATOR);
+SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimd0, FIMD0,  LCD0_M0);
+SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimd1, FIMD1,  LCD1_M1);
+SYSMMU_RESOURCE_DEFINE(EXYNOS4, flite0,        FIMC_LITE0, FIMC_LITE0);
+SYSMMU_RESOURCE_DEFINE(EXYNOS4, flite1,        FIMC_LITE1, FIMC_LITE1);
+SYSMMU_RESOURCE_DEFINE(EXYNOS4, mfc_r, MFC_R,  MFC_M0);
+SYSMMU_RESOURCE_DEFINE(EXYNOS4, mfc_l, MFC_L,  MFC_M1);
+SYSMMU_RESOURCE(EXYNOS4, isp) {
+       DEFINE_SYSMMU_RESOURCE(EXYNOS4, FIMC_ISP, FIMC_ISP),
+       DEFINE_SYSMMU_RESOURCE(EXYNOS4, FIMC_DRC, FIMC_DRC),
+       DEFINE_SYSMMU_RESOURCE(EXYNOS4, FIMC_FD, FIMC_FD),
+       DEFINE_SYSMMU_RESOURCE(EXYNOS4, ISPCPU, FIMC_CX),
+};
+
+static struct sysmmu_resource_map sysmmu_resmap4[] __initdata = {
+       SYSMMU_RESOURCE_MAPPING_PD(4, fimc0,    fimc0,  PD_CAM),
+       SYSMMU_RESOURCE_MAPPING_PD(4, fimc1,    fimc1,  PD_CAM),
+       SYSMMU_RESOURCE_MAPPING_PD(4, fimc2,    fimc2,  PD_CAM),
+       SYSMMU_RESOURCE_MAPPING_PD(4, fimc3,    fimc3,  PD_CAM),
+       SYSMMU_RESOURCE_MAPPING_PD(4, tv,       tv,     PD_TV),
+       SYSMMU_RESOURCE_MAPPING_PD(4, mfc_r,    mfc_r,  PD_MFC),
+       SYSMMU_RESOURCE_MAPPING_PD(4, mfc_l,    mfc_l,  PD_MFC),
+       SYSMMU_RESOURCE_MAPPING_PD(4, rot,      rot,    PD_LCD0),
+       SYSMMU_RESOURCE_MAPPING_PD(4, jpeg,     jpeg,   PD_CAM),
+       SYSMMU_RESOURCE_MAPPING_PD(4, fimd0,    fimd0,  PD_LCD0),
+};
+
+static struct sysmmu_resource_map sysmmu_resmap4210[] __initdata = {
+       SYSMMU_RESOURCE_MAPPING_PD(4, 2d,       2d,     PD_LCD0),
+       SYSMMU_RESOURCE_MAPPING_PD(4, fimd1,    fimd1,  PD_LCD1),
+};
+
+static struct sysmmu_resource_map sysmmu_resmap4212[] __initdata = {
+       SYSMMU_RESOURCE_MAPPING(4,      2d,     2d_acp),
+       SYSMMU_RESOURCE_MAPPING_PD(4,   camif0, flite0, PD_ISP),
+       SYSMMU_RESOURCE_MAPPING_PD(4,   camif1, flite1, PD_ISP),
+       SYSMMU_RESOURCE_MAPPING_PD(4,   isp,    isp,    PD_ISP),
+};
+#endif /* CONFIG_ARCH_EXYNOS4 */
 
-void sysmmu_clk_disable(sysmmu_ips ips)
+#ifdef CONFIG_ARCH_EXYNOS5
+SYSMMU_RESOURCE_DEFINE(EXYNOS5, jpeg,  JPEG,   JPEG);
+SYSMMU_RESOURCE_DEFINE(EXYNOS5, fimd1, FIMD1,  FIMD1);
+SYSMMU_RESOURCE_DEFINE(EXYNOS5, 2d,    2D,     2D);
+SYSMMU_RESOURCE_DEFINE(EXYNOS5, rot,   ROTATOR, ROTATOR);
+SYSMMU_RESOURCE_DEFINE(EXYNOS5, tv,    TV,     TV);
+SYSMMU_RESOURCE_DEFINE(EXYNOS5, flite0,        LITE0,  LITE0);
+SYSMMU_RESOURCE_DEFINE(EXYNOS5, flite1,        LITE1,  LITE1);
+SYSMMU_RESOURCE_DEFINE(EXYNOS5, gsc0,  GSC0,   GSC0);
+SYSMMU_RESOURCE_DEFINE(EXYNOS5, gsc1,  GSC1,   GSC1);
+SYSMMU_RESOURCE_DEFINE(EXYNOS5, gsc2,  GSC2,   GSC2);
+SYSMMU_RESOURCE_DEFINE(EXYNOS5, gsc3,  GSC3,   GSC3);
+SYSMMU_RESOURCE_DEFINE(EXYNOS5, mfc_r, MFC_R,  MFC_R);
+SYSMMU_RESOURCE_DEFINE(EXYNOS5, mfc_l, MFC_L,  MFC_L);
+SYSMMU_RESOURCE(EXYNOS5, isp) {
+       DEFINE_SYSMMU_RESOURCE(EXYNOS5, ISP, ISP),
+       DEFINE_SYSMMU_RESOURCE(EXYNOS5, DRC, DRC),
+       DEFINE_SYSMMU_RESOURCE(EXYNOS5, FD, FD),
+       DEFINE_SYSMMU_RESOURCE(EXYNOS5, ISPCPU, MCUISP),
+       DEFINE_SYSMMU_RESOURCE(EXYNOS5, SCALERC, SCALERCISP),
+       DEFINE_SYSMMU_RESOURCE(EXYNOS5, SCALERP, SCALERPISP),
+       DEFINE_SYSMMU_RESOURCE(EXYNOS5, ODC, ODC),
+       DEFINE_SYSMMU_RESOURCE(EXYNOS5, DIS0, DIS0),
+       DEFINE_SYSMMU_RESOURCE(EXYNOS5, DIS1, DIS1),
+       DEFINE_SYSMMU_RESOURCE(EXYNOS5, 3DNR, 3DNR),
+};
+
+static struct sysmmu_resource_map sysmmu_resmap5[] __initdata = {
+       SYSMMU_RESOURCE_MAPPING(5,      jpeg,   jpeg),
+       SYSMMU_RESOURCE_MAPPING(5,      fimd1,  fimd1),
+       SYSMMU_RESOURCE_MAPPING(5,      2d,     2d),
+       SYSMMU_RESOURCE_MAPPING(5,      rot,    rot),
+       SYSMMU_RESOURCE_MAPPING_PD(5,   tv,     tv,     PD_DISP1),
+       SYSMMU_RESOURCE_MAPPING_PD(5,   camif0, flite0, PD_GSCL),
+       SYSMMU_RESOURCE_MAPPING_PD(5,   camif1, flite1, PD_GSCL),
+       SYSMMU_RESOURCE_MAPPING_PD(5,   gsc0,   gsc0,   PD_GSCL),
+       SYSMMU_RESOURCE_MAPPING_PD(5,   gsc1,   gsc1,   PD_GSCL),
+       SYSMMU_RESOURCE_MAPPING_PD(5,   gsc2,   gsc2,   PD_GSCL),
+       SYSMMU_RESOURCE_MAPPING_PD(5,   gsc3,   gsc3,   PD_GSCL),
+       SYSMMU_RESOURCE_MAPPING_PD(5,   mfc_r,  mfc_r,  PD_MFC),
+       SYSMMU_RESOURCE_MAPPING_PD(5,   mfc_l,  mfc_l,  PD_MFC),
+       SYSMMU_RESOURCE_MAPPING_MCPD(5, isp,    isp,    PD_ISP, mc_platdata),
+};
+#endif /* CONFIG_ARCH_EXYNOS5 */
+
+static int __init init_sysmmu_platform_device(void)
 {
-       if (sysmmu_clk[ips])
-               clk_disable(sysmmu_clk[ips]);
+       int i, j;
+       struct sysmmu_resource_map *resmap[2] = {NULL, NULL};
+       int nmap[2] = {0, 0};
+
+#ifdef CONFIG_ARCH_EXYNOS5
+       if (soc_is_exynos5250()) {
+               resmap[0] = sysmmu_resmap5;
+               nmap[0] = ARRAY_SIZE(sysmmu_resmap5);
+               nmap[1] = 0;
+       }
+#endif
+
+#ifdef CONFIG_ARCH_EXYNOS4
+       if (resmap[0] == NULL) {
+               resmap[0] = sysmmu_resmap4;
+               nmap[0] = ARRAY_SIZE(sysmmu_resmap4);
+       }
+
+       if (soc_is_exynos4210()) {
+               resmap[1] = sysmmu_resmap4210;
+               nmap[1] = ARRAY_SIZE(sysmmu_resmap4210);
+       }
+
+       if (soc_is_exynos4412() || soc_is_exynos4212()) {
+               resmap[1] = sysmmu_resmap4212;
+               nmap[1] = ARRAY_SIZE(sysmmu_resmap4212);
+       }
+#endif
+
+       for (j = 0; j < 2; j++) {
+               for (i = 0; i < nmap[j]; i++) {
+                       struct sysmmu_resource_map *map;
+                       struct sysmmu_platform_data *platdata;
+
+                       map = &resmap[j][i];
+
+                       map->pdev->dev.parent = map->pdd;
+
+                       platdata = map->pdev->dev.platform_data;
+                       platdata->clockname = map->clocknames;
+
+                       if (platform_device_add_resources(map->pdev, map->res,
+                                                               map->rnum)) {
+                               pr_err("%s: Failed to add device resources for "
+                                               "%s.%d\n", __func__,
+                                               map->pdev->name, map->pdev->id);
+                               continue;
+                       }
+
+                       if (platform_device_register(map->pdev)) {
+                               pr_err("%s: Failed to register %s.%d\n",
+                                       __func__, map->pdev->name,
+                                               map->pdev->id);
+                       }
+               }
+       }
+
+       return 0;
 }
+arch_initcall(init_sysmmu_platform_device);
index c02dae7bf4a37923f99ec623337d78a08d182106..ddde8f3a24d435cdf09073d83302bc34a4e22b8b 100644 (file)
 #define EXYNOS4_IRQ_SYSMMU_MFC_M1_0    COMBINER_IRQ(5, 6)
 #define EXYNOS4_IRQ_SYSMMU_PCIE_0      COMBINER_IRQ(5, 7)
 
+#define EXYNOS4_IRQ_SYSMMU_FIMC_LITE0_0        COMBINER_IRQ(16, 0)
+#define EXYNOS4_IRQ_SYSMMU_FIMC_LITE1_0        COMBINER_IRQ(16, 1)
+#define EXYNOS4_IRQ_SYSMMU_FIMC_ISP_0  COMBINER_IRQ(16, 2)
+#define EXYNOS4_IRQ_SYSMMU_FIMC_DRC_0  COMBINER_IRQ(16, 3)
+#define EXYNOS4_IRQ_SYSMMU_FIMC_FD_0   COMBINER_IRQ(16, 4)
+#define EXYNOS4_IRQ_SYSMMU_FIMC_CX_0   COMBINER_IRQ(16, 5)
+
 #define EXYNOS4_IRQ_FIMD0_FIFO         COMBINER_IRQ(11, 0)
 #define EXYNOS4_IRQ_FIMD0_VSYNC                COMBINER_IRQ(11, 1)
 #define EXYNOS4_IRQ_FIMD0_SYSTEM       COMBINER_IRQ(11, 2)
 #define IRQ_KEYPAD                     EXYNOS4_IRQ_KEYPAD
 #define IRQ_PMU                                EXYNOS4_IRQ_PMU
 
-#define IRQ_SYSMMU_MDMA0_0             EXYNOS4_IRQ_SYSMMU_MDMA0_0
-#define IRQ_SYSMMU_SSS_0                EXYNOS4_IRQ_SYSMMU_SSS_0
-#define IRQ_SYSMMU_FIMC0_0              EXYNOS4_IRQ_SYSMMU_FIMC0_0
-#define IRQ_SYSMMU_FIMC1_0              EXYNOS4_IRQ_SYSMMU_FIMC1_0
-#define IRQ_SYSMMU_FIMC2_0              EXYNOS4_IRQ_SYSMMU_FIMC2_0
-#define IRQ_SYSMMU_FIMC3_0              EXYNOS4_IRQ_SYSMMU_FIMC3_0
-#define IRQ_SYSMMU_JPEG_0               EXYNOS4_IRQ_SYSMMU_JPEG_0
-#define IRQ_SYSMMU_2D_0                 EXYNOS4_IRQ_SYSMMU_2D_0
-
-#define IRQ_SYSMMU_ROTATOR_0            EXYNOS4_IRQ_SYSMMU_ROTATOR_0
-#define IRQ_SYSMMU_MDMA1_0              EXYNOS4_IRQ_SYSMMU_MDMA1_0
-#define IRQ_SYSMMU_LCD0_M0_0            EXYNOS4_IRQ_SYSMMU_LCD0_M0_0
-#define IRQ_SYSMMU_LCD1_M1_0            EXYNOS4_IRQ_SYSMMU_LCD1_M1_0
-#define IRQ_SYSMMU_TV_M0_0              EXYNOS4_IRQ_SYSMMU_TV_M0_0
-#define IRQ_SYSMMU_MFC_M0_0             EXYNOS4_IRQ_SYSMMU_MFC_M0_0
-#define IRQ_SYSMMU_MFC_M1_0             EXYNOS4_IRQ_SYSMMU_MFC_M1_0
-#define IRQ_SYSMMU_PCIE_0               EXYNOS4_IRQ_SYSMMU_PCIE_0
-
 #define IRQ_FIMD0_FIFO                 EXYNOS4_IRQ_FIMD0_FIFO
 #define IRQ_FIMD0_VSYNC                        EXYNOS4_IRQ_FIMD0_VSYNC
 #define IRQ_FIMD0_SYSTEM               EXYNOS4_IRQ_FIMD0_SYSTEM
index e009a66477f42e579572ff8e5edbcab914bc08a0..2196af2d8218f81e22055b9017eb66d4e4bd3d1a 100644 (file)
@@ -95,6 +95,7 @@
 #define EXYNOS5_PA_PDMA1               0x121B0000
 
 #define EXYNOS4_PA_SYSMMU_MDMA         0x10A40000
+#define EXYNOS4_PA_SYSMMU_2D_ACP       0x10A40000
 #define EXYNOS4_PA_SYSMMU_SSS          0x10A50000
 #define EXYNOS4_PA_SYSMMU_FIMC0                0x11A20000
 #define EXYNOS4_PA_SYSMMU_FIMC1                0x11A30000
 #define EXYNOS4_PA_SYSMMU_JPEG         0x11A60000
 #define EXYNOS4_PA_SYSMMU_FIMD0                0x11E20000
 #define EXYNOS4_PA_SYSMMU_FIMD1                0x12220000
+#define EXYNOS4_PA_SYSMMU_FIMC_ISP     0x12260000
+#define EXYNOS4_PA_SYSMMU_FIMC_DRC     0x12270000
+#define EXYNOS4_PA_SYSMMU_FIMC_FD      0x122A0000
+#define EXYNOS4_PA_SYSMMU_ISPCPU       0x122B0000
+#define EXYNOS4_PA_SYSMMU_FIMC_LITE0   0x123B0000
+#define EXYNOS4_PA_SYSMMU_FIMC_LITE1   0x123C0000
 #define EXYNOS4_PA_SYSMMU_PCIe         0x12620000
 #define EXYNOS4_PA_SYSMMU_G2D          0x12A20000
 #define EXYNOS4_PA_SYSMMU_ROTATOR      0x12A30000
 #define EXYNOS4_PA_SYSMMU_TV           0x12E20000
 #define EXYNOS4_PA_SYSMMU_MFC_L                0x13620000
 #define EXYNOS4_PA_SYSMMU_MFC_R                0x13630000
+
+#define EXYNOS5_PA_SYSMMU_MDMA1                0x10A40000
+#define EXYNOS5_PA_SYSMMU_SSS          0x10A50000
+#define EXYNOS5_PA_SYSMMU_2D           0x10A60000
+#define EXYNOS5_PA_SYSMMU_MFC_L                0x11200000
+#define EXYNOS5_PA_SYSMMU_MFC_R                0x11210000
+#define EXYNOS5_PA_SYSMMU_ROTATOR      0x11D40000
+#define EXYNOS5_PA_SYSMMU_MDMA2                0x11D50000
+#define EXYNOS5_PA_SYSMMU_JPEG         0x11F20000
+#define EXYNOS5_PA_SYSMMU_IOP          0x12360000
+#define EXYNOS5_PA_SYSMMU_RTIC         0x12370000
+#define EXYNOS5_PA_SYSMMU_GPS          0x12630000
+#define EXYNOS5_PA_SYSMMU_ISP          0x13260000
+#define EXYNOS5_PA_SYSMMU_DRC          0x12370000
+#define EXYNOS5_PA_SYSMMU_SCALERC      0x13280000
+#define EXYNOS5_PA_SYSMMU_SCALERP      0x13290000
+#define EXYNOS5_PA_SYSMMU_FD           0x132A0000
+#define EXYNOS5_PA_SYSMMU_ISPCPU       0x132B0000
+#define EXYNOS5_PA_SYSMMU_ODC          0x132C0000
+#define EXYNOS5_PA_SYSMMU_DIS0         0x132D0000
+#define EXYNOS5_PA_SYSMMU_DIS1         0x132E0000
+#define EXYNOS5_PA_SYSMMU_3DNR         0x132F0000
+#define EXYNOS5_PA_SYSMMU_LITE0                0x13C40000
+#define EXYNOS5_PA_SYSMMU_LITE1                0x13C50000
+#define EXYNOS5_PA_SYSMMU_GSC0         0x13E80000
+#define EXYNOS5_PA_SYSMMU_GSC1         0x13E90000
+#define EXYNOS5_PA_SYSMMU_GSC2         0x13EA0000
+#define EXYNOS5_PA_SYSMMU_GSC3         0x13EB0000
+#define EXYNOS5_PA_SYSMMU_FIMD1                0x14640000
+#define EXYNOS5_PA_SYSMMU_TV           0x14650000
+
 #define EXYNOS4_PA_SPI0                        0x13920000
 #define EXYNOS4_PA_SPI1                        0x13930000
 #define EXYNOS4_PA_SPI2                        0x13940000
index d9578a58ae7f573b35d7065609ae4d090884acbf..dba83e91f0fd6e641bfe41ed3dae5b9861a1cce6 100644 (file)
 #define EXYNOS4_CLKGATE_SCLKCPU                        EXYNOS_CLKREG(0x14800)
 #define EXYNOS4_CLKGATE_IP_CPU                 EXYNOS_CLKREG(0x14900)
 
+#define EXYNOS4_CLKGATE_IP_ISP0                        EXYNOS_CLKREG(0x18800)
+#define EXYNOS4_CLKGATE_IP_ISP1                        EXYNOS_CLKREG(0x18804)
+
 #define EXYNOS4_APLL_LOCKTIME                  (0x1C20)        /* 300us */
 
 #define EXYNOS4_APLLCON0_ENABLE_SHIFT          (31)
 #define EXYNOS5_CLKDIV_PERIC0                  EXYNOS_CLKREG(0x10558)
 
 #define EXYNOS5_CLKGATE_IP_ACP                 EXYNOS_CLKREG(0x08800)
+#define EXYNOS5_CLKGATE_IP_ISP0                        EXYNOS_CLKREG(0x0C800)
+#define EXYNOS5_CLKGATE_IP_ISP1                        EXYNOS_CLKREG(0x0C804)
 #define EXYNOS5_CLKGATE_IP_GSCL                        EXYNOS_CLKREG(0x10920)
 #define EXYNOS5_CLKGATE_IP_DISP1               EXYNOS_CLKREG(0x10928)
 #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 (file)
index 68ff6ad..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * EXYNOS4 - System MMU register
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_SYSMMU_H
-#define __ASM_ARCH_REGS_SYSMMU_H __FILE__
-
-#define S5P_MMU_CTRL                   0x000
-#define S5P_MMU_CFG                    0x004
-#define S5P_MMU_STATUS                 0x008
-#define S5P_MMU_FLUSH                  0x00C
-#define S5P_PT_BASE_ADDR               0x014
-#define S5P_INT_STATUS                 0x018
-#define S5P_INT_CLEAR                  0x01C
-#define S5P_PAGE_FAULT_ADDR            0x024
-#define S5P_AW_FAULT_ADDR              0x028
-#define S5P_AR_FAULT_ADDR              0x02C
-#define S5P_DEFAULT_SLAVE_ADDR         0x030
-
-#endif /* __ASM_ARCH_REGS_SYSMMU_H */
index 6a5fbb534e821ff4a8846704878797587f40f96e..998daf2add92d9548733bc21ebe2bc167fcbe8f0 100644 (file)
@@ -1,46 +1,66 @@
-/* linux/arch/arm/mach-exynos4/include/mach/sysmmu.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+/*
+ * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
  *
- * Samsung sysmmu driver for EXYNOS4
+ * EXYNOS - System MMU support
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARM_ARCH_SYSMMU_H
-#define __ASM_ARM_ARCH_SYSMMU_H __FILE__
-
-enum exynos4_sysmmu_ips {
-       SYSMMU_MDMA,
-       SYSMMU_SSS,
-       SYSMMU_FIMC0,
-       SYSMMU_FIMC1,
-       SYSMMU_FIMC2,
-       SYSMMU_FIMC3,
-       SYSMMU_JPEG,
-       SYSMMU_FIMD0,
-       SYSMMU_FIMD1,
-       SYSMMU_PCIe,
-       SYSMMU_G2D,
-       SYSMMU_ROTATOR,
-       SYSMMU_MDMA2,
-       SYSMMU_TV,
-       SYSMMU_MFC_L,
-       SYSMMU_MFC_R,
-       EXYNOS4_SYSMMU_TOTAL_IPNUM,
+ */
+
+#ifndef _ARM_MACH_EXYNOS_SYSMMU_H_
+#define _ARM_MACH_EXYNOS_SYSMMU_H_
+
+struct sysmmu_platform_data {
+       char *dbgname;
+       /* comma(,) separated list of clock names for clock gating */
+       char *clockname;
 };
 
-#define S5P_SYSMMU_TOTAL_IPNUM         EXYNOS4_SYSMMU_TOTAL_IPNUM
+#define SYSMMU_DEVNAME_BASE "exynos-sysmmu"
+
+#define SYSMMU_CLOCK_NAME "sysmmu"
+#define SYSMMU_CLOCK_NAME2 "sysmmu_mc"
+
+#ifdef CONFIG_EXYNOS_DEV_SYSMMU
+#include <linux/device.h>
+struct platform_device;
+
+#define SYSMMU_PLATDEV(ipname) exynos_device_sysmmu_##ipname
+
+extern struct platform_device SYSMMU_PLATDEV(mfc_l);
+extern struct platform_device SYSMMU_PLATDEV(mfc_r);
+extern struct platform_device SYSMMU_PLATDEV(tv);
+extern struct platform_device SYSMMU_PLATDEV(jpeg);
+extern struct platform_device SYSMMU_PLATDEV(rot);
+extern struct platform_device SYSMMU_PLATDEV(fimc0);
+extern struct platform_device SYSMMU_PLATDEV(fimc1);
+extern struct platform_device SYSMMU_PLATDEV(fimc2);
+extern struct platform_device SYSMMU_PLATDEV(fimc3);
+extern struct platform_device SYSMMU_PLATDEV(gsc0);
+extern struct platform_device SYSMMU_PLATDEV(gsc1);
+extern struct platform_device SYSMMU_PLATDEV(gsc2);
+extern struct platform_device SYSMMU_PLATDEV(gsc3);
+extern struct platform_device SYSMMU_PLATDEV(isp);
+extern struct platform_device SYSMMU_PLATDEV(fimd0);
+extern struct platform_device SYSMMU_PLATDEV(fimd1);
+extern struct platform_device SYSMMU_PLATDEV(camif0);
+extern struct platform_device SYSMMU_PLATDEV(camif1);
+extern struct platform_device SYSMMU_PLATDEV(2d);
 
-extern const char *sysmmu_ips_name[EXYNOS4_SYSMMU_TOTAL_IPNUM];
+#ifdef CONFIG_IOMMU_API
+static inline void platform_set_sysmmu(
+                               struct device *sysmmu, struct device *dev)
+{
+       dev->archdata.iommu = sysmmu;
+}
+#endif
 
-typedef enum exynos4_sysmmu_ips sysmmu_ips;
+#else /* !CONFIG_EXYNOS_DEV_SYSMMU */
+#define platform_set_sysmmu(dev, sysmmu) do { } while (0)
+#endif
 
-void sysmmu_clk_init(struct device *dev, sysmmu_ips ips);
-void sysmmu_clk_enable(sysmmu_ips ips);
-void sysmmu_clk_disable(sysmmu_ips ips);
+#define SYSMMU_CLOCK_DEVNAME(ipname, id) (SYSMMU_DEVNAME_BASE "." #id)
 
-#endif /* __ASM_ARM_ARCH_SYSMMU_H */
+#endif /* _ARM_MACH_EXYNOS_SYSMMU_H_ */
index fed7116418eb1315c60b2b87cb844a0ba28ba318..372e33196e8a9444f3cfabc30fe06cb065501c71 100644 (file)
@@ -147,7 +147,6 @@ static struct platform_device *armlex4210_devices[] __initdata = {
        &s3c_device_hsmmc3,
        &s3c_device_rtc,
        &s3c_device_wdt,
-       &exynos4_device_sysmmu,
        &samsung_asoc_dma,
        &armlex4210_smsc911x,
        &exynos4_device_ahci,
index 5af96064ca5109ddec70a66a444a74ff0720168c..a8c7656b1fce99a9c979d41363467d925d1bbe3d 100644 (file)
@@ -295,7 +295,6 @@ static struct platform_device *smdkv310_devices[] __initdata = {
        &s5p_device_mfc_l,
        &s5p_device_mfc_r,
        &exynos4_device_spdif,
-       &exynos4_device_sysmmu,
        &samsung_asoc_dma,
        &samsung_asoc_idma,
        &s5p_device_fimd0,
index d0f2546706ca1b53d6cae8d3eecb84dc89f79a17..6a113a9bb87a73b17368267715aec791127fcd83 100644 (file)
@@ -50,6 +50,14 @@ config TEGRA_PCI
        depends on ARCH_TEGRA_2x_SOC
        select PCI
 
+config TEGRA_AHB
+       bool "Enable AHB driver for NVIDIA Tegra SoCs"
+       default y
+       help
+         Adds AHB configuration functionality for NVIDIA Tegra SoCs,
+         which controls AHB bus master arbitration and some
+         perfomance parameters(priority, prefech size).
+
 comment "Tegra board type"
 
 config MACH_HARMONY
@@ -111,7 +119,7 @@ config MACH_VENTANA
          Support for the nVidia Ventana development platform
 
 choice
-        prompt "Low-level debug console UART"
+        prompt "Default low-level debug console UART"
         default TEGRA_DEBUG_UART_NONE
 
 config TEGRA_DEBUG_UART_NONE
@@ -134,6 +142,33 @@ config TEGRA_DEBUG_UARTE
 
 endchoice
 
+choice
+       prompt "Automatic low-level debug console UART"
+       default TEGRA_DEBUG_UART_AUTO_NONE
+
+config TEGRA_DEBUG_UART_AUTO_NONE
+       bool "None"
+
+config TEGRA_DEBUG_UART_AUTO_ODMDATA
+       bool "Via ODMDATA"
+       help
+         Automatically determines which UART to use for low-level debug based
+         on the ODMDATA value. This value is part of the BCT, and is written
+         to the boot memory device using nvflash, or other flashing tool.
+         When bits 19:18 are 3, then bits 17:15 indicate which UART to use;
+         0/1/2/3/4 are UART A/B/C/D/E.
+
+config TEGRA_DEBUG_UART_AUTO_SCRATCH
+       bool "Via UART scratch register"
+       help
+         Automatically determines which UART to use for low-level debug based
+         on the UART scratch register value. Some bootloaders put ASCII 'D'
+         in this register when they initialize their own console UART output.
+         Using this option allows the kernel to automatically pick the same
+         UART.
+
+endchoice
+
 config TEGRA_SYSTEM_DMA
        bool "Enable system DMA driver for NVIDIA Tegra SoCs"
        default y
index 5f7c03e972f3dc2654f82022d81129bb5982b0d7..d96dae0b4aa7dc04e687733238055ca30af93080 100644 (file)
@@ -51,12 +51,22 @@ struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = {
        OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000C500, "tegra-i2c.2", NULL),
        OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000C700, "tegra-i2c.3", NULL),
        OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000D000, "tegra-i2c.4", NULL),
+       OF_DEV_AUXDATA("nvidia,tegra30-ahub", 0x70080000, "tegra30-ahub", NULL),
        {}
 };
 
 static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
        /* name         parent          rate            enabled */
        { "uarta",      "pll_p",        408000000,      true },
+       { "pll_a",      "pll_p_out1",   564480000,      true },
+       { "pll_a_out0", "pll_a",        11289600,       true },
+       { "extern1",    "pll_a_out0",   0,              true },
+       { "clk_out_1",  "extern1",      0,              true },
+       { "i2s0",       "pll_a_out0",   11289600,       false},
+       { "i2s1",       "pll_a_out0",   11289600,       false},
+       { "i2s2",       "pll_a_out0",   11289600,       false},
+       { "i2s3",       "pll_a_out0",   11289600,       false},
+       { "i2s4",       "pll_a_out0",   11289600,       false},
        { NULL,         NULL,           0,              0},
 };
 
index d0735c70d688e8054fc7aa5e16f1731eb0e00c9b..55a1e6ccf4a274ad365225aa7181adfe77c3216f 100644 (file)
@@ -162,6 +162,8 @@ static void paz00_i2c_init(void)
 
 static void paz00_usb_init(void)
 {
+       tegra_ehci2_ulpi_phy_config.reset_gpio = TEGRA_ULPI_RST;
+
        platform_device_register(&tegra_ehci2_device);
        platform_device_register(&tegra_ehci3_device);
 }
@@ -179,7 +181,6 @@ static __initdata struct tegra_clk_init_table paz00_clk_init_table[] = {
        { "uarta",      "pll_p",        216000000,      true },
        { "uartc",      "pll_p",        216000000,      true },
 
-       { "pll_p_out4", "pll_p",        24000000,       true },
        { "usbd",       "clk_m",        12000000,       false },
        { "usb2",       "clk_m",        12000000,       false },
        { "usb3",       "clk_m",        12000000,       false },
index bc59b379c6fe609db1d413c874b24e54e1b378a2..832fa931c7100afcb3d07657d8f2fa24f1df6216 100644 (file)
@@ -118,6 +118,8 @@ static void trimslice_usb_init(void)
        pdata = tegra_ehci1_device.dev.platform_data;
        pdata->vbus_gpio = TRIMSLICE_GPIO_USB1_MODE;
 
+       tegra_ehci2_ulpi_phy_config.reset_gpio = TEGRA_GPIO_PV0;
+
        platform_device_register(&tegra_ehci3_device);
        platform_device_register(&tegra_ehci2_device);
        platform_device_register(&tegra_ehci1_device);
index 22df10fb9972877069f92637ff5849ba990ad9f7..2d80566b5383d5a745a62e2a6314f15c02afe796 100644 (file)
@@ -82,10 +82,12 @@ static __initdata struct tegra_clk_init_table tegra20_clk_init_table[] = {
        { "pll_p_out1", "pll_p",        28800000,       true },
        { "pll_p_out2", "pll_p",        48000000,       true },
        { "pll_p_out3", "pll_p",        72000000,       true },
-       { "pll_p_out4", "pll_p",        108000000,      true },
-       { "sclk",       "pll_p_out4",   108000000,      true },
-       { "hclk",       "sclk",         108000000,      true },
-       { "pclk",       "hclk",         54000000,       true },
+       { "pll_p_out4", "pll_p",        24000000,       true },
+       { "pll_c",      "clk_m",        600000000,      true },
+       { "pll_c_out1", "pll_c",        120000000,      true },
+       { "sclk",       "pll_c_out1",   120000000,      true },
+       { "hclk",       "sclk",         120000000,      true },
+       { "pclk",       "hclk",         60000000,       true },
        { "csite",      NULL,           0,              true },
        { "emc",        NULL,           0,              true },
        { "cpu",        NULL,           0,              true },
@@ -93,6 +95,17 @@ static __initdata struct tegra_clk_init_table tegra20_clk_init_table[] = {
 };
 #endif
 
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+static __initdata struct tegra_clk_init_table tegra30_clk_init_table[] = {
+       /* name         parent          rate            enabled */
+       { "clk_m",      NULL,           0,              true },
+       { "pll_p",      "clk_m",        408000000,      true },
+       { "pll_p_out1", "pll_p",        9600000,        true },
+       { NULL,         NULL,           0,              0},
+};
+#endif
+
+
 static void __init tegra_init_cache(u32 tag_latency, u32 data_latency)
 {
 #ifdef CONFIG_CACHE_L2X0
@@ -127,6 +140,7 @@ void __init tegra30_init_early(void)
 {
        tegra_init_fuse();
        tegra30_init_clocks();
+       tegra_clk_init_from_table(tegra30_clk_init_table);
        tegra_init_cache(0x441, 0x551);
        tegra_pmc_init();
        tegra_powergate_init();
index 2d8dfa2faf8f09d0dcdfb8f301713912ca553782..c70e65ffa36ba8a91e16b372c8c616abd4414c20 100644 (file)
@@ -439,9 +439,8 @@ static struct resource tegra_usb3_resources[] = {
        },
 };
 
-static struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
-       /* All existing boards use GPIO PV0 for phy reset */
-       .reset_gpio = TEGRA_GPIO_PV0,
+struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
+       .reset_gpio = -1,
        .clk = "cdev2",
 };
 
index 138c642e59f4cec93143845d8e072df332b083e3..4f50527264956b0f28413e462b9afef024b00322 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/platform_data/tegra_usb.h>
 
+#include <mach/usb_phy.h>
+
+extern struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config;
+
 extern struct tegra_ehci_platform_data tegra_ehci1_pdata;
 extern struct tegra_ehci_platform_data tegra_ehci2_pdata;
 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 (file)
index 0000000..e0f8c84
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#ifndef __MACH_TEGRA_AHB_H__
+#define __MACH_TEGRA_AHB_H__
+
+extern int tegra_ahb_enable_smmu(struct device_node *ahb);
+
+#endif /* __MACH_TEGRA_AHB_H__ */
index 5a440f315e575d29c43958fd1c84226843056447..937c4c50219e1a818c89b32f965598318fbd55cc 100644 (file)
@@ -63,52 +63,86 @@ static inline void save_uart_address(void)
                buf[0] = 0;
 }
 
-/*
- * Setup before decompression.  This is where we do UART selection for
- * earlyprintk and init the uart_base register.
- */
-static inline void arch_decomp_setup(void)
+static const struct {
+       u32 base;
+       u32 reset_reg;
+       u32 clock_reg;
+       u32 bit;
+} uarts[] = {
+       {
+               TEGRA_UARTA_BASE,
+               TEGRA_CLK_RESET_BASE + 0x04,
+               TEGRA_CLK_RESET_BASE + 0x10,
+               6,
+       },
+       {
+               TEGRA_UARTB_BASE,
+               TEGRA_CLK_RESET_BASE + 0x04,
+               TEGRA_CLK_RESET_BASE + 0x10,
+               7,
+       },
+       {
+               TEGRA_UARTC_BASE,
+               TEGRA_CLK_RESET_BASE + 0x08,
+               TEGRA_CLK_RESET_BASE + 0x14,
+               23,
+       },
+       {
+               TEGRA_UARTD_BASE,
+               TEGRA_CLK_RESET_BASE + 0x0c,
+               TEGRA_CLK_RESET_BASE + 0x18,
+               1,
+       },
+       {
+               TEGRA_UARTE_BASE,
+               TEGRA_CLK_RESET_BASE + 0x0c,
+               TEGRA_CLK_RESET_BASE + 0x18,
+               2,
+       },
+};
+
+static inline bool uart_clocked(int i)
+{
+       if (*(u8 *)uarts[i].reset_reg & BIT(uarts[i].bit))
+               return false;
+
+       if (!(*(u8 *)uarts[i].clock_reg & BIT(uarts[i].bit)))
+               return false;
+
+       return true;
+}
+
+#ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA
+int auto_odmdata(void)
+{
+       volatile u32 *pmc = (volatile u32 *)TEGRA_PMC_BASE;
+       u32 odmdata = pmc[0xa0 / 4];
+
+       /*
+        * Bits 19:18 are the console type: 0=default, 1=none, 2==DCC, 3==UART
+        * Some boards apparently swap the last two values, but we don't have
+        * any way of catering for that here, so we just accept either. If this
+        * doesn't make sense for your board, just don't enable this feature.
+        *
+        * Bits 17:15 indicate the UART to use, 0/1/2/3/4 are UART A/B/C/D/E.
+        */
+
+       switch  ((odmdata >> 18) & 3) {
+       case 2:
+       case 3:
+               break;
+       default:
+               return -1;
+       }
+
+       return (odmdata >> 15) & 7;
+}
+#endif
+
+#ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH
+int auto_scratch(void)
 {
-       static const struct {
-               u32 base;
-               u32 reset_reg;
-               u32 clock_reg;
-               u32 bit;
-       } uarts[] = {
-               {
-                       TEGRA_UARTA_BASE,
-                       TEGRA_CLK_RESET_BASE + 0x04,
-                       TEGRA_CLK_RESET_BASE + 0x10,
-                       6,
-               },
-               {
-                       TEGRA_UARTB_BASE,
-                       TEGRA_CLK_RESET_BASE + 0x04,
-                       TEGRA_CLK_RESET_BASE + 0x10,
-                       7,
-               },
-               {
-                       TEGRA_UARTC_BASE,
-                       TEGRA_CLK_RESET_BASE + 0x08,
-                       TEGRA_CLK_RESET_BASE + 0x14,
-                       23,
-               },
-               {
-                       TEGRA_UARTD_BASE,
-                       TEGRA_CLK_RESET_BASE + 0x0c,
-                       TEGRA_CLK_RESET_BASE + 0x18,
-                       1,
-               },
-               {
-                       TEGRA_UARTE_BASE,
-                       TEGRA_CLK_RESET_BASE + 0x0c,
-                       TEGRA_CLK_RESET_BASE + 0x18,
-                       2,
-               },
-       };
        int i;
-       volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE;
-       u32 chip, div;
 
        /*
         * Look for the first UART that:
@@ -125,20 +159,60 @@ static inline void arch_decomp_setup(void)
         * back to what's specified in TEGRA_DEBUG_UART_BASE.
         */
        for (i = 0; i < ARRAY_SIZE(uarts); i++) {
-               if (*(u8 *)uarts[i].reset_reg & BIT(uarts[i].bit))
-                       continue;
-
-               if (!(*(u8 *)uarts[i].clock_reg & BIT(uarts[i].bit)))
+               if (!uart_clocked(i))
                        continue;
 
                uart = (volatile u8 *)uarts[i].base;
                if (uart[UART_SCR << DEBUG_UART_SHIFT] != 'D')
                        continue;
 
-               break;
+               return i;
        }
-       if (i == ARRAY_SIZE(uarts))
-               uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE;
+
+       return -1;
+}
+#endif
+
+/*
+ * Setup before decompression.  This is where we do UART selection for
+ * earlyprintk and init the uart_base register.
+ */
+static inline void arch_decomp_setup(void)
+{
+       int uart_id, auto_uart_id;
+       volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE;
+       u32 chip, div;
+
+#if defined(CONFIG_TEGRA_DEBUG_UARTA)
+       uart_id = 0;
+#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
+       uart_id = 1;
+#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
+       uart_id = 2;
+#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
+       uart_id = 3;
+#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
+       uart_id = 4;
+#else
+       uart_id = -1;
+#endif
+
+#if defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
+       auto_uart_id = auto_odmdata();
+#elif defined(CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH)
+       auto_uart_id = auto_scratch();
+#else
+       auto_uart_id = -1;
+#endif
+       if (auto_uart_id != -1)
+               uart_id = auto_uart_id;
+
+       if (uart_id < 0 || uart_id >= ARRAY_SIZE(uarts) ||
+           !uart_clocked(uart_id))
+               uart = NULL;
+       else
+               uart = (volatile u8 *)uarts[uart_id].base;
+
        save_uart_address();
        if (uart == NULL)
                return;
index de1a0f602b2891c5dfd2eeb3b0322c1ba84f3adf..935ce9f6559031b79102eac935376dd3fea3e1a8 100644 (file)
@@ -61,8 +61,8 @@ struct tegra_usb_phy {
        struct usb_phy *ulpi;
 };
 
-struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
-                       void *config, enum tegra_usb_phy_mode phy_mode);
+struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
+       void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode);
 
 int tegra_usb_phy_power_on(struct tegra_usb_phy *phy);
 
index bae09b8598912b2f310ea854401457bcba9983da..b59315ce3691c8c73fefdccd9e91328b14d07dab 100644 (file)
@@ -1486,6 +1486,10 @@ static struct clk tegra_clk_m = {
 };
 
 static struct clk_pll_freq_table tegra_pll_c_freq_table[] = {
+       { 12000000, 600000000, 600, 12, 1, 8 },
+       { 13000000, 600000000, 600, 13, 1, 8 },
+       { 19200000, 600000000, 500, 16, 1, 6 },
+       { 26000000, 600000000, 600, 26, 1, 8 },
        { 0, 0, 0, 0, 0, 0 },
 };
 
index 6d08b53f92d21cde44c0834aa80ac5cda3f42bf9..e33fe4b14a2a5ab86f674c1848320740448bfa6c 100644 (file)
@@ -3015,6 +3015,15 @@ struct clk_duplicate tegra_clk_duplicates[] = {
        CLK_DUPLICATE("sbc6", "spi_slave_tegra.5", NULL),
        CLK_DUPLICATE("twd", "smp_twd", NULL),
        CLK_DUPLICATE("vcp", "nvavp", "vcp"),
+       CLK_DUPLICATE("i2s0", NULL, "i2s0"),
+       CLK_DUPLICATE("i2s1", NULL, "i2s1"),
+       CLK_DUPLICATE("i2s2", NULL, "i2s2"),
+       CLK_DUPLICATE("i2s3", NULL, "i2s3"),
+       CLK_DUPLICATE("i2s4", NULL, "i2s4"),
+       CLK_DUPLICATE("dam0", NULL, "dam0"),
+       CLK_DUPLICATE("dam1", NULL, "dam1"),
+       CLK_DUPLICATE("dam2", NULL, "dam2"),
+       CLK_DUPLICATE("spdif_in", NULL, "spdif_in"),
 };
 
 struct clk *tegra_ptr_clks[] = {
index d71d2fed67216227f1958dfa187be7e7fa5a57ad..54e353c8e3042f61e7c487c16f1cd29d22758fb6 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/of_gpio.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 #include <asm/mach-types.h>
@@ -654,8 +655,8 @@ static void ulpi_phy_power_off(struct tegra_usb_phy *phy)
        clk_disable(phy->clk);
 }
 
-struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
-                       void *config, enum tegra_usb_phy_mode phy_mode)
+struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
+       void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode)
 {
        struct tegra_usb_phy *phy;
        struct tegra_ulpi_config *ulpi_config;
@@ -711,6 +712,16 @@ struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
                        err = -ENXIO;
                        goto err1;
                }
+               if (!gpio_is_valid(ulpi_config->reset_gpio))
+                       ulpi_config->reset_gpio =
+                               of_get_named_gpio(dev->of_node,
+                                                 "nvidia,phy-reset-gpio", 0);
+               if (!gpio_is_valid(ulpi_config->reset_gpio)) {
+                       pr_err("%s: invalid reset gpio: %d\n", __func__,
+                              ulpi_config->reset_gpio);
+                       err = -EINVAL;
+                       goto err1;
+               }
                gpio_request(ulpi_config->reset_gpio, "ulpi_phy_reset_b");
                gpio_direction_output(ulpi_config->reset_gpio, 0);
                phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
index abcc36eb12425ac04a28da7e61f6e9fa171ddac0..5ce8d5e6ea518e7f4d0303b4d4ac066dcd294224 100644 (file)
@@ -44,6 +44,10 @@ struct pxa27x_keypad_platform_data {
        /* direct keys */
        int             direct_key_num;
        unsigned int    direct_key_map[MAX_DIRECT_KEY_NUM];
+       /* the key output may be low active */
+       int             direct_key_low_active;
+       /* give board a chance to choose the start direct key */
+       unsigned int    direct_key_mask;
 
        /* rotary encoders 0 */
        int             enable_rotary0;
index 96bea32023046393e200d3a87987cd1557ce0f2a..2c1193c5992884ad0a624dc463bcccfc1d372e9b 100644 (file)
@@ -50,14 +50,6 @@ config S5P_PM
          Common code for power management support on S5P and newer SoCs
          Note: Do not select this for S5P6440 and S5P6450.
 
-comment "System MMU"
-
-config S5P_SYSTEM_MMU
-       bool "S5P SYSTEM MMU"
-       depends on ARCH_EXYNOS4
-       help
-         Say Y here if you want to enable System MMU
-
 config S5P_SLEEP
        bool
        help
index 4bd8241366594c1dd4e47fad5b0c4ac8ad5cdbbf..4953d50707be79514b6302b96f7a7e868a2ee989 100644 (file)
@@ -16,7 +16,6 @@ obj-y                         += clock.o
 obj-y                          += irq.o
 obj-$(CONFIG_S5P_EXT_INT)      += irq-eint.o
 obj-$(CONFIG_S5P_GPIO_INT)     += irq-gpioint.o
-obj-$(CONFIG_S5P_SYSTEM_MMU)   += sysmmu.o
 obj-$(CONFIG_S5P_PM)           += pm.o irq-pm.o
 obj-$(CONFIG_S5P_SLEEP)                += sleep.o
 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 (file)
index c8bec9c..0000000
+++ /dev/null
@@ -1,313 +0,0 @@
-/* linux/arch/arm/plat-s5p/sysmmu.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/export.h>
-
-#include <asm/pgtable.h>
-
-#include <mach/map.h>
-#include <mach/regs-sysmmu.h>
-#include <plat/sysmmu.h>
-
-#define CTRL_ENABLE    0x5
-#define CTRL_BLOCK     0x7
-#define CTRL_DISABLE   0x0
-
-static struct device *dev;
-
-static unsigned short fault_reg_offset[SYSMMU_FAULTS_NUM] = {
-       S5P_PAGE_FAULT_ADDR,
-       S5P_AR_FAULT_ADDR,
-       S5P_AW_FAULT_ADDR,
-       S5P_DEFAULT_SLAVE_ADDR,
-       S5P_AR_FAULT_ADDR,
-       S5P_AR_FAULT_ADDR,
-       S5P_AW_FAULT_ADDR,
-       S5P_AW_FAULT_ADDR
-};
-
-static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = {
-       "PAGE FAULT",
-       "AR MULTI-HIT FAULT",
-       "AW MULTI-HIT FAULT",
-       "BUS ERROR",
-       "AR SECURITY PROTECTION FAULT",
-       "AR ACCESS PROTECTION FAULT",
-       "AW SECURITY PROTECTION FAULT",
-       "AW ACCESS PROTECTION FAULT"
-};
-
-static int (*fault_handlers[S5P_SYSMMU_TOTAL_IPNUM])(
-               enum S5P_SYSMMU_INTERRUPT_TYPE itype,
-               unsigned long pgtable_base,
-               unsigned long fault_addr);
-
-/*
- * If adjacent 2 bits are true, the system MMU is enabled.
- * The system MMU is disabled, otherwise.
- */
-static unsigned long sysmmu_states;
-
-static inline void set_sysmmu_active(sysmmu_ips ips)
-{
-       sysmmu_states |= 3 << (ips * 2);
-}
-
-static inline void set_sysmmu_inactive(sysmmu_ips ips)
-{
-       sysmmu_states &= ~(3 << (ips * 2));
-}
-
-static inline int is_sysmmu_active(sysmmu_ips ips)
-{
-       return sysmmu_states & (3 << (ips * 2));
-}
-
-static void __iomem *sysmmusfrs[S5P_SYSMMU_TOTAL_IPNUM];
-
-static inline void sysmmu_block(sysmmu_ips ips)
-{
-       __raw_writel(CTRL_BLOCK, sysmmusfrs[ips] + S5P_MMU_CTRL);
-       dev_dbg(dev, "%s is blocked.\n", sysmmu_ips_name[ips]);
-}
-
-static inline void sysmmu_unblock(sysmmu_ips ips)
-{
-       __raw_writel(CTRL_ENABLE, sysmmusfrs[ips] + S5P_MMU_CTRL);
-       dev_dbg(dev, "%s is unblocked.\n", sysmmu_ips_name[ips]);
-}
-
-static inline void __sysmmu_tlb_invalidate(sysmmu_ips ips)
-{
-       __raw_writel(0x1, sysmmusfrs[ips] + S5P_MMU_FLUSH);
-       dev_dbg(dev, "TLB of %s is invalidated.\n", sysmmu_ips_name[ips]);
-}
-
-static inline void __sysmmu_set_ptbase(sysmmu_ips ips, unsigned long pgd)
-{
-       if (unlikely(pgd == 0)) {
-               pgd = (unsigned long)ZERO_PAGE(0);
-               __raw_writel(0x20, sysmmusfrs[ips] + S5P_MMU_CFG); /* 4KB LV1 */
-       } else {
-               __raw_writel(0x0, sysmmusfrs[ips] + S5P_MMU_CFG); /* 16KB LV1 */
-       }
-
-       __raw_writel(pgd, sysmmusfrs[ips] + S5P_PT_BASE_ADDR);
-
-       dev_dbg(dev, "Page table base of %s is initialized with 0x%08lX.\n",
-                                               sysmmu_ips_name[ips], pgd);
-       __sysmmu_tlb_invalidate(ips);
-}
-
-void sysmmu_set_fault_handler(sysmmu_ips ips,
-                       int (*handler)(enum S5P_SYSMMU_INTERRUPT_TYPE itype,
-                                       unsigned long pgtable_base,
-                                       unsigned long fault_addr))
-{
-       BUG_ON(!((ips >= SYSMMU_MDMA) && (ips < S5P_SYSMMU_TOTAL_IPNUM)));
-       fault_handlers[ips] = handler;
-}
-
-static irqreturn_t s5p_sysmmu_irq(int irq, void *dev_id)
-{
-       /* SYSMMU is in blocked when interrupt occurred. */
-       unsigned long base = 0;
-       sysmmu_ips ips = (sysmmu_ips)dev_id;
-       enum S5P_SYSMMU_INTERRUPT_TYPE itype;
-
-       itype = (enum S5P_SYSMMU_INTERRUPT_TYPE)
-               __ffs(__raw_readl(sysmmusfrs[ips] + S5P_INT_STATUS));
-
-       BUG_ON(!((itype >= 0) && (itype < 8)));
-
-       dev_alert(dev, "%s occurred by %s.\n", sysmmu_fault_name[itype],
-                                                       sysmmu_ips_name[ips]);
-
-       if (fault_handlers[ips]) {
-               unsigned long addr;
-
-               base = __raw_readl(sysmmusfrs[ips] + S5P_PT_BASE_ADDR);
-               addr = __raw_readl(sysmmusfrs[ips] + fault_reg_offset[itype]);
-
-               if (fault_handlers[ips](itype, base, addr)) {
-                       __raw_writel(1 << itype,
-                                       sysmmusfrs[ips] + S5P_INT_CLEAR);
-                       dev_notice(dev, "%s from %s is resolved."
-                                       " Retrying translation.\n",
-                               sysmmu_fault_name[itype], sysmmu_ips_name[ips]);
-               } else {
-                       base = 0;
-               }
-       }
-
-       sysmmu_unblock(ips);
-
-       if (!base)
-               dev_notice(dev, "%s from %s is not handled.\n",
-                       sysmmu_fault_name[itype], sysmmu_ips_name[ips]);
-
-       return IRQ_HANDLED;
-}
-
-void s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd)
-{
-       if (is_sysmmu_active(ips)) {
-               sysmmu_block(ips);
-               __sysmmu_set_ptbase(ips, pgd);
-               sysmmu_unblock(ips);
-       } else {
-               dev_dbg(dev, "%s is disabled. "
-                       "Skipping initializing page table base.\n",
-                                               sysmmu_ips_name[ips]);
-       }
-}
-
-void s5p_sysmmu_enable(sysmmu_ips ips, unsigned long pgd)
-{
-       if (!is_sysmmu_active(ips)) {
-               sysmmu_clk_enable(ips);
-
-               __sysmmu_set_ptbase(ips, pgd);
-
-               __raw_writel(CTRL_ENABLE, sysmmusfrs[ips] + S5P_MMU_CTRL);
-
-               set_sysmmu_active(ips);
-               dev_dbg(dev, "%s is enabled.\n", sysmmu_ips_name[ips]);
-       } else {
-               dev_dbg(dev, "%s is already enabled.\n", sysmmu_ips_name[ips]);
-       }
-}
-
-void s5p_sysmmu_disable(sysmmu_ips ips)
-{
-       if (is_sysmmu_active(ips)) {
-               __raw_writel(CTRL_DISABLE, sysmmusfrs[ips] + S5P_MMU_CTRL);
-               set_sysmmu_inactive(ips);
-               sysmmu_clk_disable(ips);
-               dev_dbg(dev, "%s is disabled.\n", sysmmu_ips_name[ips]);
-       } else {
-               dev_dbg(dev, "%s is already disabled.\n", sysmmu_ips_name[ips]);
-       }
-}
-
-void s5p_sysmmu_tlb_invalidate(sysmmu_ips ips)
-{
-       if (is_sysmmu_active(ips)) {
-               sysmmu_block(ips);
-               __sysmmu_tlb_invalidate(ips);
-               sysmmu_unblock(ips);
-       } else {
-               dev_dbg(dev, "%s is disabled. "
-                       "Skipping invalidating TLB.\n", sysmmu_ips_name[ips]);
-       }
-}
-
-static int s5p_sysmmu_probe(struct platform_device *pdev)
-{
-       int i, ret;
-       struct resource *res, *mem;
-
-       dev = &pdev->dev;
-
-       for (i = 0; i < S5P_SYSMMU_TOTAL_IPNUM; i++) {
-               int irq;
-
-               sysmmu_clk_init(dev, i);
-               sysmmu_clk_disable(i);
-
-               res = platform_get_resource(pdev, IORESOURCE_MEM, i);
-               if (!res) {
-                       dev_err(dev, "Failed to get the resource of %s.\n",
-                                                       sysmmu_ips_name[i]);
-                       ret = -ENODEV;
-                       goto err_res;
-               }
-
-               mem = request_mem_region(res->start, resource_size(res),
-                                        pdev->name);
-               if (!mem) {
-                       dev_err(dev, "Failed to request the memory region of %s.\n",
-                                                       sysmmu_ips_name[i]);
-                       ret = -EBUSY;
-                       goto err_res;
-               }
-
-               sysmmusfrs[i] = ioremap(res->start, resource_size(res));
-               if (!sysmmusfrs[i]) {
-                       dev_err(dev, "Failed to ioremap() for %s.\n",
-                                                       sysmmu_ips_name[i]);
-                       ret = -ENXIO;
-                       goto err_reg;
-               }
-
-               irq = platform_get_irq(pdev, i);
-               if (irq <= 0) {
-                       dev_err(dev, "Failed to get the IRQ resource of %s.\n",
-                                                       sysmmu_ips_name[i]);
-                       ret = -ENOENT;
-                       goto err_map;
-               }
-
-               if (request_irq(irq, s5p_sysmmu_irq, IRQF_DISABLED,
-                                               pdev->name, (void *)i)) {
-                       dev_err(dev, "Failed to request IRQ for %s.\n",
-                                                       sysmmu_ips_name[i]);
-                       ret = -ENOENT;
-                       goto err_map;
-               }
-       }
-
-       return 0;
-
-err_map:
-       iounmap(sysmmusfrs[i]);
-err_reg:
-       release_mem_region(mem->start, resource_size(mem));
-err_res:
-       return ret;
-}
-
-static int s5p_sysmmu_remove(struct platform_device *pdev)
-{
-       return 0;
-}
-int s5p_sysmmu_runtime_suspend(struct device *dev)
-{
-       return 0;
-}
-
-int s5p_sysmmu_runtime_resume(struct device *dev)
-{
-       return 0;
-}
-
-const struct dev_pm_ops s5p_sysmmu_pm_ops = {
-       .runtime_suspend        = s5p_sysmmu_runtime_suspend,
-       .runtime_resume         = s5p_sysmmu_runtime_resume,
-};
-
-static struct platform_driver s5p_sysmmu_driver = {
-       .probe          = s5p_sysmmu_probe,
-       .remove         = s5p_sysmmu_remove,
-       .driver         = {
-               .owner          = THIS_MODULE,
-               .name           = "s5p-sysmmu",
-               .pm             = &s5p_sysmmu_pm_ops,
-       }
-};
-
-static int __init s5p_sysmmu_init(void)
-{
-       return platform_driver_register(&s5p_sysmmu_driver);
-}
-arch_initcall(s5p_sysmmu_init);
index 2155d4af62a30ce2d83c016e097690ba1b0ae316..4067d1dd7f1c3e067b41ebb6963b5c1226994db0 100644 (file)
@@ -133,7 +133,6 @@ extern struct platform_device exynos4_device_pcm1;
 extern struct platform_device exynos4_device_pcm2;
 extern struct platform_device exynos4_device_pd[];
 extern struct platform_device exynos4_device_spdif;
-extern struct platform_device exynos4_device_sysmmu;
 
 extern struct platform_device samsung_asoc_dma;
 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 (file)
index 5fe8ee0..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/sysmmu.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Samsung System MMU driver for S5P platform
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __PLAT_SAMSUNG_SYSMMU_H
-#define __PLAT_SAMSUNG_SYSMMU_H __FILE__
-
-enum S5P_SYSMMU_INTERRUPT_TYPE {
-       SYSMMU_PAGEFAULT,
-       SYSMMU_AR_MULTIHIT,
-       SYSMMU_AW_MULTIHIT,
-       SYSMMU_BUSERROR,
-       SYSMMU_AR_SECURITY,
-       SYSMMU_AR_ACCESS,
-       SYSMMU_AW_SECURITY,
-       SYSMMU_AW_PROTECTION, /* 7 */
-       SYSMMU_FAULTS_NUM
-};
-
-#ifdef CONFIG_S5P_SYSTEM_MMU
-
-#include <mach/sysmmu.h>
-
-/**
- * s5p_sysmmu_enable() - enable system mmu of ip
- * @ips: The ip connected system mmu.
- * #pgd: Base physical address of the 1st level page table
- *
- * This function enable system mmu to transfer address
- * from virtual address to physical address
- */
-void s5p_sysmmu_enable(sysmmu_ips ips, unsigned long pgd);
-
-/**
- * s5p_sysmmu_disable() - disable sysmmu mmu of ip
- * @ips: The ip connected system mmu.
- *
- * This function disable system mmu to transfer address
- * from virtual address to physical address
- */
-void s5p_sysmmu_disable(sysmmu_ips ips);
-
-/**
- * s5p_sysmmu_set_tablebase_pgd() - set page table base address to refer page table
- * @ips: The ip connected system mmu.
- * @pgd: The page table base address.
- *
- * This function set page table base address
- * When system mmu transfer address from virtaul address to physical address,
- * system mmu refer address information from page table
- */
-void s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd);
-
-/**
- * s5p_sysmmu_tlb_invalidate() - flush all TLB entry in system mmu
- * @ips: The ip connected system mmu.
- *
- * This function flush all TLB entry in system mmu
- */
-void s5p_sysmmu_tlb_invalidate(sysmmu_ips ips);
-
-/** s5p_sysmmu_set_fault_handler() - Fault handler for System MMUs
- * @itype: type of fault.
- * @pgtable_base: the physical address of page table base. This is 0 if @ips is
- *               SYSMMU_BUSERROR.
- * @fault_addr: the device (virtual) address that the System MMU tried to
- *             translated. This is 0 if @ips is SYSMMU_BUSERROR.
- * Called when interrupt occurred by the System MMUs
- * The device drivers of peripheral devices that has a System MMU can implement
- * a fault handler to resolve address translation fault by System MMU.
- * The meanings of return value and parameters are described below.
-
- * return value: non-zero if the fault is correctly resolved.
- *         zero if the fault is not handled.
- */
-void s5p_sysmmu_set_fault_handler(sysmmu_ips ips,
-                       int (*handler)(enum S5P_SYSMMU_INTERRUPT_TYPE itype,
-                                       unsigned long pgtable_base,
-                                       unsigned long fault_addr));
-#else
-#define s5p_sysmmu_enable(ips, pgd) do { } while (0)
-#define s5p_sysmmu_disable(ips) do { } while (0)
-#define s5p_sysmmu_set_tablebase_pgd(ips, pgd) do { } while (0)
-#define s5p_sysmmu_tlb_invalidate(ips) do { } while (0)
-#define s5p_sysmmu_set_fault_handler(ips, handler) do { } while (0)
-#endif
-#endif /* __ASM_PLAT_SYSMMU_H */
index 7e283c891b7f8871eca5dc5a64a79d9bb4e56590..fe0d60935e9be10109d2ed0ee7c65b9e493d9777 100644 (file)
                sdhc@2e000 {
                        status = "disabled";
                        sdhci,1-bit-only;
+                       bus-width = <1>;
                };
 
                par_io@e0100 {
index 0ee98d50f9752b0a77925dca996f5cd36fee12a3..2ba29ffef2cbd84ff0a55d66a861ab3eee2159fa 100644 (file)
@@ -18,7 +18,7 @@ obj-$(CONFIG_SFI)             += sfi/
 # PnP must come after ACPI since it will eventually need to check if acpi
 # was used and do nothing if so
 obj-$(CONFIG_PNP)              += pnp/
-obj-$(CONFIG_ARM_AMBA)         += amba/
+obj-y                          += amba/
 # Many drivers will want to use DMA so this has to be made available
 # really early.
 obj-$(CONFIG_DMA_ENGINE)       += dma/
index 40fe74097be23e827b22d64b2b795204fa3cf540..66e81c2f1e3ca30a1a4e9d498cdfeef16c0b5fbc 100644 (file)
@@ -1,2 +1,2 @@
-obj-         += bus.o
-
+obj-$(CONFIG_ARM_AMBA)         += bus.o
+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 (file)
index 0000000..aa0b1f1
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Author:
+ *     Jay Cheng <jacheng@nvidia.com>
+ *     James Wylder <james.wylder@motorola.com>
+ *     Benoit Goby <benoit@android.com>
+ *     Colin Cross <ccross@android.com>
+ *     Hiroshi DOYU <hdoyu@nvidia.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#define DRV_NAME "tegra-ahb"
+
+#define AHB_ARBITRATION_DISABLE                0x00
+#define AHB_ARBITRATION_PRIORITY_CTRL  0x04
+#define   AHB_PRIORITY_WEIGHT(x)       (((x) & 0x7) << 29)
+#define   PRIORITY_SELECT_USB BIT(6)
+#define   PRIORITY_SELECT_USB2 BIT(18)
+#define   PRIORITY_SELECT_USB3 BIT(17)
+
+#define AHB_GIZMO_AHB_MEM              0x0c
+#define   ENB_FAST_REARBITRATE BIT(2)
+#define   DONT_SPLIT_AHB_WR     BIT(7)
+
+#define AHB_GIZMO_APB_DMA              0x10
+#define AHB_GIZMO_IDE                  0x18
+#define AHB_GIZMO_USB                  0x1c
+#define AHB_GIZMO_AHB_XBAR_BRIDGE      0x20
+#define AHB_GIZMO_CPU_AHB_BRIDGE       0x24
+#define AHB_GIZMO_COP_AHB_BRIDGE       0x28
+#define AHB_GIZMO_XBAR_APB_CTLR                0x2c
+#define AHB_GIZMO_VCP_AHB_BRIDGE       0x30
+#define AHB_GIZMO_NAND                 0x3c
+#define AHB_GIZMO_SDMMC4               0x44
+#define AHB_GIZMO_XIO                  0x48
+#define AHB_GIZMO_BSEV                 0x60
+#define AHB_GIZMO_BSEA                 0x70
+#define AHB_GIZMO_NOR                  0x74
+#define AHB_GIZMO_USB2                 0x78
+#define AHB_GIZMO_USB3                 0x7c
+#define   IMMEDIATE    BIT(18)
+
+#define AHB_GIZMO_SDMMC1               0x80
+#define AHB_GIZMO_SDMMC2               0x84
+#define AHB_GIZMO_SDMMC3               0x88
+#define AHB_MEM_PREFETCH_CFG_X         0xd8
+#define AHB_ARBITRATION_XBAR_CTRL      0xdc
+#define AHB_MEM_PREFETCH_CFG3          0xe0
+#define AHB_MEM_PREFETCH_CFG4          0xe4
+#define AHB_MEM_PREFETCH_CFG1          0xec
+#define AHB_MEM_PREFETCH_CFG2          0xf0
+#define   PREFETCH_ENB BIT(31)
+#define   MST_ID(x)    (((x) & 0x1f) << 26)
+#define   AHBDMA_MST_ID        MST_ID(5)
+#define   USB_MST_ID   MST_ID(6)
+#define   USB2_MST_ID  MST_ID(18)
+#define   USB3_MST_ID  MST_ID(17)
+#define   ADDR_BNDRY(x)        (((x) & 0xf) << 21)
+#define   INACTIVITY_TIMEOUT(x)        (((x) & 0xffff) << 0)
+
+#define AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID   0xf8
+
+#define AHB_ARBITRATION_XBAR_CTRL_SMMU_INIT_DONE BIT(17)
+
+static struct platform_driver tegra_ahb_driver;
+
+static const u32 tegra_ahb_gizmo[] = {
+       AHB_ARBITRATION_DISABLE,
+       AHB_ARBITRATION_PRIORITY_CTRL,
+       AHB_GIZMO_AHB_MEM,
+       AHB_GIZMO_APB_DMA,
+       AHB_GIZMO_IDE,
+       AHB_GIZMO_USB,
+       AHB_GIZMO_AHB_XBAR_BRIDGE,
+       AHB_GIZMO_CPU_AHB_BRIDGE,
+       AHB_GIZMO_COP_AHB_BRIDGE,
+       AHB_GIZMO_XBAR_APB_CTLR,
+       AHB_GIZMO_VCP_AHB_BRIDGE,
+       AHB_GIZMO_NAND,
+       AHB_GIZMO_SDMMC4,
+       AHB_GIZMO_XIO,
+       AHB_GIZMO_BSEV,
+       AHB_GIZMO_BSEA,
+       AHB_GIZMO_NOR,
+       AHB_GIZMO_USB2,
+       AHB_GIZMO_USB3,
+       AHB_GIZMO_SDMMC1,
+       AHB_GIZMO_SDMMC2,
+       AHB_GIZMO_SDMMC3,
+       AHB_MEM_PREFETCH_CFG_X,
+       AHB_ARBITRATION_XBAR_CTRL,
+       AHB_MEM_PREFETCH_CFG3,
+       AHB_MEM_PREFETCH_CFG4,
+       AHB_MEM_PREFETCH_CFG1,
+       AHB_MEM_PREFETCH_CFG2,
+       AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID,
+};
+
+struct tegra_ahb {
+       void __iomem    *regs;
+       struct device   *dev;
+       u32             ctx[0];
+};
+
+static inline u32 gizmo_readl(struct tegra_ahb *ahb, u32 offset)
+{
+       return readl(ahb->regs + offset);
+}
+
+static inline void gizmo_writel(struct tegra_ahb *ahb, u32 value, u32 offset)
+{
+       writel(value, ahb->regs + offset);
+}
+
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+static int tegra_ahb_match_by_smmu(struct device *dev, void *data)
+{
+       struct tegra_ahb *ahb = dev_get_drvdata(dev);
+       struct device_node *dn = data;
+
+       return (ahb->dev->of_node == dn) ? 1 : 0;
+}
+
+int tegra_ahb_enable_smmu(struct device_node *dn)
+{
+       struct device *dev;
+       u32 val;
+       struct tegra_ahb *ahb;
+
+       dev = driver_find_device(&tegra_ahb_driver.driver, NULL, dn,
+                                tegra_ahb_match_by_smmu);
+       if (!dev)
+               return -EPROBE_DEFER;
+       ahb = dev_get_drvdata(dev);
+       val = gizmo_readl(ahb, AHB_ARBITRATION_XBAR_CTRL);
+       val |= AHB_ARBITRATION_XBAR_CTRL_SMMU_INIT_DONE;
+       gizmo_writel(ahb, val, AHB_ARBITRATION_XBAR_CTRL);
+       return 0;
+}
+EXPORT_SYMBOL(tegra_ahb_enable_smmu);
+#endif
+
+static int tegra_ahb_suspend(struct device *dev)
+{
+       int i;
+       struct tegra_ahb *ahb = dev_get_drvdata(dev);
+
+       for (i = 0; i < ARRAY_SIZE(tegra_ahb_gizmo); i++)
+               ahb->ctx[i] = gizmo_readl(ahb, tegra_ahb_gizmo[i]);
+       return 0;
+}
+
+static int tegra_ahb_resume(struct device *dev)
+{
+       int i;
+       struct tegra_ahb *ahb = dev_get_drvdata(dev);
+
+       for (i = 0; i < ARRAY_SIZE(tegra_ahb_gizmo); i++)
+               gizmo_writel(ahb, ahb->ctx[i], tegra_ahb_gizmo[i]);
+       return 0;
+}
+
+static UNIVERSAL_DEV_PM_OPS(tegra_ahb_pm,
+                           tegra_ahb_suspend,
+                           tegra_ahb_resume, NULL);
+
+static void tegra_ahb_gizmo_init(struct tegra_ahb *ahb)
+{
+       u32 val;
+
+       val = gizmo_readl(ahb, AHB_GIZMO_AHB_MEM);
+       val |= ENB_FAST_REARBITRATE | IMMEDIATE | DONT_SPLIT_AHB_WR;
+       gizmo_writel(ahb, val, AHB_GIZMO_AHB_MEM);
+
+       val = gizmo_readl(ahb, AHB_GIZMO_USB);
+       val |= IMMEDIATE;
+       gizmo_writel(ahb, val, AHB_GIZMO_USB);
+
+       val = gizmo_readl(ahb, AHB_GIZMO_USB2);
+       val |= IMMEDIATE;
+       gizmo_writel(ahb, val, AHB_GIZMO_USB2);
+
+       val = gizmo_readl(ahb, AHB_GIZMO_USB3);
+       val |= IMMEDIATE;
+       gizmo_writel(ahb, val, AHB_GIZMO_USB3);
+
+       val = gizmo_readl(ahb, AHB_ARBITRATION_PRIORITY_CTRL);
+       val |= PRIORITY_SELECT_USB |
+               PRIORITY_SELECT_USB2 |
+               PRIORITY_SELECT_USB3 |
+               AHB_PRIORITY_WEIGHT(7);
+       gizmo_writel(ahb, val, AHB_ARBITRATION_PRIORITY_CTRL);
+
+       val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG1);
+       val &= ~MST_ID(~0);
+       val |= PREFETCH_ENB |
+               AHBDMA_MST_ID |
+               ADDR_BNDRY(0xc) |
+               INACTIVITY_TIMEOUT(0x1000);
+       gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG1);
+
+       val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG2);
+       val &= ~MST_ID(~0);
+       val |= PREFETCH_ENB |
+               USB_MST_ID |
+               ADDR_BNDRY(0xc) |
+               INACTIVITY_TIMEOUT(0x1000);
+       gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG2);
+
+       val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG3);
+       val &= ~MST_ID(~0);
+       val |= PREFETCH_ENB |
+               USB3_MST_ID |
+               ADDR_BNDRY(0xc) |
+               INACTIVITY_TIMEOUT(0x1000);
+       gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG3);
+
+       val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG4);
+       val &= ~MST_ID(~0);
+       val |= PREFETCH_ENB |
+               USB2_MST_ID |
+               ADDR_BNDRY(0xc) |
+               INACTIVITY_TIMEOUT(0x1000);
+       gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG4);
+}
+
+static int __devinit tegra_ahb_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       struct tegra_ahb *ahb;
+       size_t bytes;
+
+       bytes = sizeof(*ahb) + sizeof(u32) * ARRAY_SIZE(tegra_ahb_gizmo);
+       ahb = devm_kzalloc(&pdev->dev, bytes, GFP_KERNEL);
+       if (!ahb)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENODEV;
+       ahb->regs = devm_request_and_ioremap(&pdev->dev, res);
+       if (!ahb->regs)
+               return -EBUSY;
+
+       ahb->dev = &pdev->dev;
+       platform_set_drvdata(pdev, ahb);
+       tegra_ahb_gizmo_init(ahb);
+       return 0;
+}
+
+static int __devexit tegra_ahb_remove(struct platform_device *pdev)
+{
+       return 0;
+}
+
+static const struct of_device_id tegra_ahb_of_match[] __devinitconst = {
+       { .compatible = "nvidia,tegra30-ahb", },
+       { .compatible = "nvidia,tegra20-ahb", },
+       {},
+};
+
+static struct platform_driver tegra_ahb_driver = {
+       .probe = tegra_ahb_probe,
+       .remove = __devexit_p(tegra_ahb_remove),
+       .driver = {
+               .name = DRV_NAME,
+               .owner = THIS_MODULE,
+               .of_match_table = tegra_ahb_of_match,
+               .pm = &tegra_ahb_pm,
+       },
+};
+module_platform_driver(tegra_ahb_driver);
+
+MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>");
+MODULE_DESCRIPTION("Tegra AHB driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
index f6e9b572b998919ee117cf154e560788da439de3..c64917ec313dc25d501ad41312fa8e898df8e003 100644 (file)
@@ -71,6 +71,7 @@
 #define M2M_CONTROL_TM_SHIFT           13
 #define M2M_CONTROL_TM_TX              (1 << M2M_CONTROL_TM_SHIFT)
 #define M2M_CONTROL_TM_RX              (2 << M2M_CONTROL_TM_SHIFT)
+#define M2M_CONTROL_NFBINT             BIT(21)
 #define M2M_CONTROL_RSS_SHIFT          22
 #define M2M_CONTROL_RSS_SSPRX          (1 << M2M_CONTROL_RSS_SHIFT)
 #define M2M_CONTROL_RSS_SSPTX          (2 << M2M_CONTROL_RSS_SHIFT)
 #define M2M_CONTROL_PWSC_SHIFT         25
 
 #define M2M_INTERRUPT                  0x0004
-#define M2M_INTERRUPT_DONEINT          BIT(1)
+#define M2M_INTERRUPT_MASK             6
+
+#define M2M_STATUS                     0x000c
+#define M2M_STATUS_CTL_SHIFT           1
+#define M2M_STATUS_CTL_IDLE            (0 << M2M_STATUS_CTL_SHIFT)
+#define M2M_STATUS_CTL_STALL           (1 << M2M_STATUS_CTL_SHIFT)
+#define M2M_STATUS_CTL_MEMRD           (2 << M2M_STATUS_CTL_SHIFT)
+#define M2M_STATUS_CTL_MEMWR           (3 << M2M_STATUS_CTL_SHIFT)
+#define M2M_STATUS_CTL_BWCWAIT         (4 << M2M_STATUS_CTL_SHIFT)
+#define M2M_STATUS_CTL_MASK            (7 << M2M_STATUS_CTL_SHIFT)
+#define M2M_STATUS_BUF_SHIFT           4
+#define M2M_STATUS_BUF_NO              (0 << M2M_STATUS_BUF_SHIFT)
+#define M2M_STATUS_BUF_ON              (1 << M2M_STATUS_BUF_SHIFT)
+#define M2M_STATUS_BUF_NEXT            (2 << M2M_STATUS_BUF_SHIFT)
+#define M2M_STATUS_BUF_MASK            (3 << M2M_STATUS_BUF_SHIFT)
+#define M2M_STATUS_DONE                        BIT(6)
 
 #define M2M_BCR0                       0x0010
 #define M2M_BCR1                       0x0014
@@ -426,15 +442,6 @@ static int m2p_hw_interrupt(struct ep93xx_dma_chan *edmac)
 
 /*
  * M2M DMA implementation
- *
- * For the M2M transfers we don't use NFB at all. This is because it simply
- * doesn't work well with memcpy transfers. When you submit both buffers it is
- * extremely unlikely that you get an NFB interrupt, but it instead reports
- * DONE interrupt and both buffers are already transferred which means that we
- * weren't able to update the next buffer.
- *
- * So for now we "simulate" NFB by just submitting buffer after buffer
- * without double buffering.
  */
 
 static int m2m_hw_setup(struct ep93xx_dma_chan *edmac)
@@ -543,6 +550,11 @@ static void m2m_hw_submit(struct ep93xx_dma_chan *edmac)
        m2m_fill_desc(edmac);
        control |= M2M_CONTROL_DONEINT;
 
+       if (ep93xx_dma_advance_active(edmac)) {
+               m2m_fill_desc(edmac);
+               control |= M2M_CONTROL_NFBINT;
+       }
+
        /*
         * Now we can finally enable the channel. For M2M channel this must be
         * done _after_ the BCRx registers are programmed.
@@ -560,32 +572,89 @@ static void m2m_hw_submit(struct ep93xx_dma_chan *edmac)
        }
 }
 
+/*
+ * According to EP93xx User's Guide, we should receive DONE interrupt when all
+ * M2M DMA controller transactions complete normally. This is not always the
+ * case - sometimes EP93xx M2M DMA asserts DONE interrupt when the DMA channel
+ * is still running (channel Buffer FSM in DMA_BUF_ON state, and channel
+ * Control FSM in DMA_MEM_RD state, observed at least in IDE-DMA operation).
+ * In effect, disabling the channel when only DONE bit is set could stop
+ * currently running DMA transfer. To avoid this, we use Buffer FSM and
+ * Control FSM to check current state of DMA channel.
+ */
 static int m2m_hw_interrupt(struct ep93xx_dma_chan *edmac)
 {
+       u32 status = readl(edmac->regs + M2M_STATUS);
+       u32 ctl_fsm = status & M2M_STATUS_CTL_MASK;
+       u32 buf_fsm = status & M2M_STATUS_BUF_MASK;
+       bool done = status & M2M_STATUS_DONE;
+       bool last_done;
        u32 control;
+       struct ep93xx_dma_desc *desc;
 
-       if (!(readl(edmac->regs + M2M_INTERRUPT) & M2M_INTERRUPT_DONEINT))
+       /* Accept only DONE and NFB interrupts */
+       if (!(readl(edmac->regs + M2M_INTERRUPT) & M2M_INTERRUPT_MASK))
                return INTERRUPT_UNKNOWN;
 
-       /* Clear the DONE bit */
-       writel(0, edmac->regs + M2M_INTERRUPT);
+       if (done) {
+               /* Clear the DONE bit */
+               writel(0, edmac->regs + M2M_INTERRUPT);
+       }
 
-       /* Disable interrupts and the channel */
-       control = readl(edmac->regs + M2M_CONTROL);
-       control &= ~(M2M_CONTROL_DONEINT | M2M_CONTROL_ENABLE);
-       writel(control, edmac->regs + M2M_CONTROL);
+       /*
+        * Check whether we are done with descriptors or not. This, together
+        * with DMA channel state, determines action to take in interrupt.
+        */
+       desc = ep93xx_dma_get_active(edmac);
+       last_done = !desc || desc->txd.cookie;
 
        /*
-        * Since we only get DONE interrupt we have to find out ourselves
-        * whether there still is something to process. So we try to advance
-        * the chain an see whether it succeeds.
+        * Use M2M DMA Buffer FSM and Control FSM to check current state of
+        * DMA channel. Using DONE and NFB bits from channel status register
+        * or bits from channel interrupt register is not reliable.
         */
-       if (ep93xx_dma_advance_active(edmac)) {
-               edmac->edma->hw_submit(edmac);
-               return INTERRUPT_NEXT_BUFFER;
+       if (!last_done &&
+           (buf_fsm == M2M_STATUS_BUF_NO ||
+            buf_fsm == M2M_STATUS_BUF_ON)) {
+               /*
+                * Two buffers are ready for update when Buffer FSM is in
+                * DMA_NO_BUF state. Only one buffer can be prepared without
+                * disabling the channel or polling the DONE bit.
+                * To simplify things, always prepare only one buffer.
+                */
+               if (ep93xx_dma_advance_active(edmac)) {
+                       m2m_fill_desc(edmac);
+                       if (done && !edmac->chan.private) {
+                               /* Software trigger for memcpy channel */
+                               control = readl(edmac->regs + M2M_CONTROL);
+                               control |= M2M_CONTROL_START;
+                               writel(control, edmac->regs + M2M_CONTROL);
+                       }
+                       return INTERRUPT_NEXT_BUFFER;
+               } else {
+                       last_done = true;
+               }
+       }
+
+       /*
+        * Disable the channel only when Buffer FSM is in DMA_NO_BUF state
+        * and Control FSM is in DMA_STALL state.
+        */
+       if (last_done &&
+           buf_fsm == M2M_STATUS_BUF_NO &&
+           ctl_fsm == M2M_STATUS_CTL_STALL) {
+               /* Disable interrupts and the channel */
+               control = readl(edmac->regs + M2M_CONTROL);
+               control &= ~(M2M_CONTROL_DONEINT | M2M_CONTROL_NFBINT
+                           | M2M_CONTROL_ENABLE);
+               writel(control, edmac->regs + M2M_CONTROL);
+               return INTERRUPT_DONE;
        }
 
-       return INTERRUPT_DONE;
+       /*
+        * Nothing to do this time.
+        */
+       return INTERRUPT_NEXT_BUFFER;
 }
 
 /*
index 29fe1b2be1c1f46541fba50815f4bb8d349e8847..7f7b72464a37e547f7b199a89cab5202270e2163 100644 (file)
@@ -311,7 +311,15 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad)
        if (pdata->enable_rotary0 || pdata->enable_rotary1)
                pxa27x_keypad_scan_rotary(keypad);
 
-       new_state = KPDK_DK(kpdk) & keypad->direct_key_mask;
+       /*
+        * The KPDR_DK only output the key pin level, so it relates to board,
+        * and low level may be active.
+        */
+       if (pdata->direct_key_low_active)
+               new_state = ~KPDK_DK(kpdk) & keypad->direct_key_mask;
+       else
+               new_state = KPDK_DK(kpdk) & keypad->direct_key_mask;
+
        bits_changed = keypad->direct_key_state ^ new_state;
 
        if (bits_changed == 0)
@@ -383,7 +391,14 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
        if (pdata->direct_key_num > direct_key_num)
                direct_key_num = pdata->direct_key_num;
 
-       keypad->direct_key_mask = ((2 << direct_key_num) - 1) & ~mask;
+       /*
+        * Direct keys usage may not start from KP_DKIN0, check the platfrom
+        * mask data to config the specific.
+        */
+       if (pdata->direct_key_mask)
+               keypad->direct_key_mask = pdata->direct_key_mask;
+       else
+               keypad->direct_key_mask = ((1 << direct_key_num) - 1) & ~mask;
 
        /* enable direct key */
        if (direct_key_num)
@@ -399,7 +414,7 @@ static int pxa27x_keypad_open(struct input_dev *dev)
        struct pxa27x_keypad *keypad = input_get_drvdata(dev);
 
        /* Enable unit clock */
-       clk_enable(keypad->clk);
+       clk_prepare_enable(keypad->clk);
        pxa27x_keypad_config(keypad);
 
        return 0;
@@ -410,7 +425,7 @@ static void pxa27x_keypad_close(struct input_dev *dev)
        struct pxa27x_keypad *keypad = input_get_drvdata(dev);
 
        /* Disable clock unit */
-       clk_disable(keypad->clk);
+       clk_disable_unprepare(keypad->clk);
 }
 
 #ifdef CONFIG_PM
@@ -419,10 +434,14 @@ static int pxa27x_keypad_suspend(struct device *dev)
        struct platform_device *pdev = to_platform_device(dev);
        struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
 
-       clk_disable(keypad->clk);
-
+       /*
+        * If the keypad is used a wake up source, clock can not be disabled.
+        * Or it can not detect the key pressing.
+        */
        if (device_may_wakeup(&pdev->dev))
                enable_irq_wake(keypad->irq);
+       else
+               clk_disable_unprepare(keypad->clk);
 
        return 0;
 }
@@ -433,19 +452,24 @@ static int pxa27x_keypad_resume(struct device *dev)
        struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
        struct input_dev *input_dev = keypad->input_dev;
 
-       if (device_may_wakeup(&pdev->dev))
+       /*
+        * If the keypad is used as wake up source, the clock is not turned
+        * off. So do not need configure it again.
+        */
+       if (device_may_wakeup(&pdev->dev)) {
                disable_irq_wake(keypad->irq);
+       } else {
+               mutex_lock(&input_dev->mutex);
 
-       mutex_lock(&input_dev->mutex);
+               if (input_dev->users) {
+                       /* Enable unit clock */
+                       clk_prepare_enable(keypad->clk);
+                       pxa27x_keypad_config(keypad);
+               }
 
-       if (input_dev->users) {
-               /* Enable unit clock */
-               clk_enable(keypad->clk);
-               pxa27x_keypad_config(keypad);
+               mutex_unlock(&input_dev->mutex);
        }
 
-       mutex_unlock(&input_dev->mutex);
-
        return 0;
 }
 
index c69843742bb041e911a116e0f96558c20de2bb63..34089372753893ab3cf0a247d097fd3f4f67c688 100644 (file)
@@ -162,4 +162,25 @@ config TEGRA_IOMMU_SMMU
          space through the SMMU (System Memory Management Unit)
          hardware included on Tegra SoCs.
 
+config EXYNOS_IOMMU
+       bool "Exynos IOMMU Support"
+       depends on ARCH_EXYNOS && EXYNOS_DEV_SYSMMU
+       select IOMMU_API
+       help
+         Support for the IOMMU(System MMU) of Samsung Exynos application
+         processor family. This enables H/W multimedia accellerators to see
+         non-linear physical memory chunks as a linear memory in their
+         address spaces
+
+         If unsure, say N here.
+
+config EXYNOS_IOMMU_DEBUG
+       bool "Debugging log for Exynos IOMMU"
+       depends on EXYNOS_IOMMU
+       help
+         Select this to see the detailed log message that shows what
+         happens in the IOMMU driver
+
+         Say N unless you need kernel log message for IOMMU debugging
+
 endif # IOMMU_SUPPORT
index 3e5e82ae9f0de957a7c67f004776850cc7ef3536..76e54ef796dec14864f0ca5c05dd44cc4a5f570f 100644 (file)
@@ -10,3 +10,4 @@ obj-$(CONFIG_OMAP_IOVMM) += omap-iovmm.o
 obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
 obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o
 obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o
+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 (file)
index 0000000..9a114b9
--- /dev/null
@@ -0,0 +1,1076 @@
+/* linux/drivers/iommu/exynos_iommu.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifdef CONFIG_EXYNOS_IOMMU_DEBUG
+#define DEBUG
+#endif
+
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/mm.h>
+#include <linux/iommu.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/memblock.h>
+#include <linux/export.h>
+
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+
+#include <mach/sysmmu.h>
+
+/* We does not consider super section mapping (16MB) */
+#define SECT_ORDER 20
+#define LPAGE_ORDER 16
+#define SPAGE_ORDER 12
+
+#define SECT_SIZE (1 << SECT_ORDER)
+#define LPAGE_SIZE (1 << LPAGE_ORDER)
+#define SPAGE_SIZE (1 << SPAGE_ORDER)
+
+#define SECT_MASK (~(SECT_SIZE - 1))
+#define LPAGE_MASK (~(LPAGE_SIZE - 1))
+#define SPAGE_MASK (~(SPAGE_SIZE - 1))
+
+#define lv1ent_fault(sent) (((*(sent) & 3) == 0) || ((*(sent) & 3) == 3))
+#define lv1ent_page(sent) ((*(sent) & 3) == 1)
+#define lv1ent_section(sent) ((*(sent) & 3) == 2)
+
+#define lv2ent_fault(pent) ((*(pent) & 3) == 0)
+#define lv2ent_small(pent) ((*(pent) & 2) == 2)
+#define lv2ent_large(pent) ((*(pent) & 3) == 1)
+
+#define section_phys(sent) (*(sent) & SECT_MASK)
+#define section_offs(iova) ((iova) & 0xFFFFF)
+#define lpage_phys(pent) (*(pent) & LPAGE_MASK)
+#define lpage_offs(iova) ((iova) & 0xFFFF)
+#define spage_phys(pent) (*(pent) & SPAGE_MASK)
+#define spage_offs(iova) ((iova) & 0xFFF)
+
+#define lv1ent_offset(iova) ((iova) >> SECT_ORDER)
+#define lv2ent_offset(iova) (((iova) & 0xFF000) >> SPAGE_ORDER)
+
+#define NUM_LV1ENTRIES 4096
+#define NUM_LV2ENTRIES 256
+
+#define LV2TABLE_SIZE (NUM_LV2ENTRIES * sizeof(long))
+
+#define SPAGES_PER_LPAGE (LPAGE_SIZE / SPAGE_SIZE)
+
+#define lv2table_base(sent) (*(sent) & 0xFFFFFC00)
+
+#define mk_lv1ent_sect(pa) ((pa) | 2)
+#define mk_lv1ent_page(pa) ((pa) | 1)
+#define mk_lv2ent_lpage(pa) ((pa) | 1)
+#define mk_lv2ent_spage(pa) ((pa) | 2)
+
+#define CTRL_ENABLE    0x5
+#define CTRL_BLOCK     0x7
+#define CTRL_DISABLE   0x0
+
+#define REG_MMU_CTRL           0x000
+#define REG_MMU_CFG            0x004
+#define REG_MMU_STATUS         0x008
+#define REG_MMU_FLUSH          0x00C
+#define REG_MMU_FLUSH_ENTRY    0x010
+#define REG_PT_BASE_ADDR       0x014
+#define REG_INT_STATUS         0x018
+#define REG_INT_CLEAR          0x01C
+
+#define REG_PAGE_FAULT_ADDR    0x024
+#define REG_AW_FAULT_ADDR      0x028
+#define REG_AR_FAULT_ADDR      0x02C
+#define REG_DEFAULT_SLAVE_ADDR 0x030
+
+#define REG_MMU_VERSION                0x034
+
+#define REG_PB0_SADDR          0x04C
+#define REG_PB0_EADDR          0x050
+#define REG_PB1_SADDR          0x054
+#define REG_PB1_EADDR          0x058
+
+static unsigned long *section_entry(unsigned long *pgtable, unsigned long iova)
+{
+       return pgtable + lv1ent_offset(iova);
+}
+
+static unsigned long *page_entry(unsigned long *sent, unsigned long iova)
+{
+       return (unsigned long *)__va(lv2table_base(sent)) + lv2ent_offset(iova);
+}
+
+enum exynos_sysmmu_inttype {
+       SYSMMU_PAGEFAULT,
+       SYSMMU_AR_MULTIHIT,
+       SYSMMU_AW_MULTIHIT,
+       SYSMMU_BUSERROR,
+       SYSMMU_AR_SECURITY,
+       SYSMMU_AR_ACCESS,
+       SYSMMU_AW_SECURITY,
+       SYSMMU_AW_PROTECTION, /* 7 */
+       SYSMMU_FAULT_UNKNOWN,
+       SYSMMU_FAULTS_NUM
+};
+
+/*
+ * @itype: type of fault.
+ * @pgtable_base: the physical address of page table base. This is 0 if @itype
+ *                is SYSMMU_BUSERROR.
+ * @fault_addr: the device (virtual) address that the System MMU tried to
+ *             translated. This is 0 if @itype is SYSMMU_BUSERROR.
+ */
+typedef int (*sysmmu_fault_handler_t)(enum exynos_sysmmu_inttype itype,
+                       unsigned long pgtable_base, unsigned long fault_addr);
+
+static unsigned short fault_reg_offset[SYSMMU_FAULTS_NUM] = {
+       REG_PAGE_FAULT_ADDR,
+       REG_AR_FAULT_ADDR,
+       REG_AW_FAULT_ADDR,
+       REG_DEFAULT_SLAVE_ADDR,
+       REG_AR_FAULT_ADDR,
+       REG_AR_FAULT_ADDR,
+       REG_AW_FAULT_ADDR,
+       REG_AW_FAULT_ADDR
+};
+
+static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = {
+       "PAGE FAULT",
+       "AR MULTI-HIT FAULT",
+       "AW MULTI-HIT FAULT",
+       "BUS ERROR",
+       "AR SECURITY PROTECTION FAULT",
+       "AR ACCESS PROTECTION FAULT",
+       "AW SECURITY PROTECTION FAULT",
+       "AW ACCESS PROTECTION FAULT",
+       "UNKNOWN FAULT"
+};
+
+struct exynos_iommu_domain {
+       struct list_head clients; /* list of sysmmu_drvdata.node */
+       unsigned long *pgtable; /* lv1 page table, 16KB */
+       short *lv2entcnt; /* free lv2 entry counter for each section */
+       spinlock_t lock; /* lock for this structure */
+       spinlock_t pgtablelock; /* lock for modifying page table @ pgtable */
+};
+
+struct sysmmu_drvdata {
+       struct list_head node; /* entry of exynos_iommu_domain.clients */
+       struct device *sysmmu;  /* System MMU's device descriptor */
+       struct device *dev;     /* Owner of system MMU */
+       char *dbgname;
+       int nsfrs;
+       void __iomem **sfrbases;
+       struct clk *clk[2];
+       int activations;
+       rwlock_t lock;
+       struct iommu_domain *domain;
+       sysmmu_fault_handler_t fault_handler;
+       unsigned long pgtable;
+};
+
+static bool set_sysmmu_active(struct sysmmu_drvdata *data)
+{
+       /* return true if the System MMU was not active previously
+          and it needs to be initialized */
+       return ++data->activations == 1;
+}
+
+static bool set_sysmmu_inactive(struct sysmmu_drvdata *data)
+{
+       /* return true if the System MMU is needed to be disabled */
+       BUG_ON(data->activations < 1);
+       return --data->activations == 0;
+}
+
+static bool is_sysmmu_active(struct sysmmu_drvdata *data)
+{
+       return data->activations > 0;
+}
+
+static void sysmmu_unblock(void __iomem *sfrbase)
+{
+       __raw_writel(CTRL_ENABLE, sfrbase + REG_MMU_CTRL);
+}
+
+static bool sysmmu_block(void __iomem *sfrbase)
+{
+       int i = 120;
+
+       __raw_writel(CTRL_BLOCK, sfrbase + REG_MMU_CTRL);
+       while ((i > 0) && !(__raw_readl(sfrbase + REG_MMU_STATUS) & 1))
+               --i;
+
+       if (!(__raw_readl(sfrbase + REG_MMU_STATUS) & 1)) {
+               sysmmu_unblock(sfrbase);
+               return false;
+       }
+
+       return true;
+}
+
+static void __sysmmu_tlb_invalidate(void __iomem *sfrbase)
+{
+       __raw_writel(0x1, sfrbase + REG_MMU_FLUSH);
+}
+
+static void __sysmmu_tlb_invalidate_entry(void __iomem *sfrbase,
+                                               unsigned long iova)
+{
+       __raw_writel((iova & SPAGE_MASK) | 1, sfrbase + REG_MMU_FLUSH_ENTRY);
+}
+
+static void __sysmmu_set_ptbase(void __iomem *sfrbase,
+                                      unsigned long pgd)
+{
+       __raw_writel(0x1, sfrbase + REG_MMU_CFG); /* 16KB LV1, LRU */
+       __raw_writel(pgd, sfrbase + REG_PT_BASE_ADDR);
+
+       __sysmmu_tlb_invalidate(sfrbase);
+}
+
+static void __sysmmu_set_prefbuf(void __iomem *sfrbase, unsigned long base,
+                                               unsigned long size, int idx)
+{
+       __raw_writel(base, sfrbase + REG_PB0_SADDR + idx * 8);
+       __raw_writel(size - 1 + base,  sfrbase + REG_PB0_EADDR + idx * 8);
+}
+
+void exynos_sysmmu_set_prefbuf(struct device *dev,
+                               unsigned long base0, unsigned long size0,
+                               unsigned long base1, unsigned long size1)
+{
+       struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
+       unsigned long flags;
+       int i;
+
+       BUG_ON((base0 + size0) <= base0);
+       BUG_ON((size1 > 0) && ((base1 + size1) <= base1));
+
+       read_lock_irqsave(&data->lock, flags);
+       if (!is_sysmmu_active(data))
+               goto finish;
+
+       for (i = 0; i < data->nsfrs; i++) {
+               if ((readl(data->sfrbases[i] + REG_MMU_VERSION) >> 28) == 3) {
+                       if (!sysmmu_block(data->sfrbases[i]))
+                               continue;
+
+                       if (size1 == 0) {
+                               if (size0 <= SZ_128K) {
+                                       base1 = base0;
+                                       size1 = size0;
+                               } else {
+                                       size1 = size0 -
+                                               ALIGN(size0 / 2, SZ_64K);
+                                       size0 = size0 - size1;
+                                       base1 = base0 + size0;
+                               }
+                       }
+
+                       __sysmmu_set_prefbuf(
+                                       data->sfrbases[i], base0, size0, 0);
+                       __sysmmu_set_prefbuf(
+                                       data->sfrbases[i], base1, size1, 1);
+
+                       sysmmu_unblock(data->sfrbases[i]);
+               }
+       }
+finish:
+       read_unlock_irqrestore(&data->lock, flags);
+}
+
+static void __set_fault_handler(struct sysmmu_drvdata *data,
+                                       sysmmu_fault_handler_t handler)
+{
+       unsigned long flags;
+
+       write_lock_irqsave(&data->lock, flags);
+       data->fault_handler = handler;
+       write_unlock_irqrestore(&data->lock, flags);
+}
+
+void exynos_sysmmu_set_fault_handler(struct device *dev,
+                                       sysmmu_fault_handler_t handler)
+{
+       struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
+
+       __set_fault_handler(data, handler);
+}
+
+static int default_fault_handler(enum exynos_sysmmu_inttype itype,
+                    unsigned long pgtable_base, unsigned long fault_addr)
+{
+       unsigned long *ent;
+
+       if ((itype >= SYSMMU_FAULTS_NUM) || (itype < SYSMMU_PAGEFAULT))
+               itype = SYSMMU_FAULT_UNKNOWN;
+
+       pr_err("%s occured at 0x%lx(Page table base: 0x%lx)\n",
+                       sysmmu_fault_name[itype], fault_addr, pgtable_base);
+
+       ent = section_entry(__va(pgtable_base), fault_addr);
+       pr_err("\tLv1 entry: 0x%lx\n", *ent);
+
+       if (lv1ent_page(ent)) {
+               ent = page_entry(ent, fault_addr);
+               pr_err("\t Lv2 entry: 0x%lx\n", *ent);
+       }
+
+       pr_err("Generating Kernel OOPS... because it is unrecoverable.\n");
+
+       BUG();
+
+       return 0;
+}
+
+static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id)
+{
+       /* SYSMMU is in blocked when interrupt occurred. */
+       struct sysmmu_drvdata *data = dev_id;
+       struct resource *irqres;
+       struct platform_device *pdev;
+       enum exynos_sysmmu_inttype itype;
+       unsigned long addr = -1;
+
+       int i, ret = -ENOSYS;
+
+       read_lock(&data->lock);
+
+       WARN_ON(!is_sysmmu_active(data));
+
+       pdev = to_platform_device(data->sysmmu);
+       for (i = 0; i < (pdev->num_resources / 2); i++) {
+               irqres = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+               if (irqres && ((int)irqres->start == irq))
+                       break;
+       }
+
+       if (i == pdev->num_resources) {
+               itype = SYSMMU_FAULT_UNKNOWN;
+       } else {
+               itype = (enum exynos_sysmmu_inttype)
+                       __ffs(__raw_readl(data->sfrbases[i] + REG_INT_STATUS));
+               if (WARN_ON(!((itype >= 0) && (itype < SYSMMU_FAULT_UNKNOWN))))
+                       itype = SYSMMU_FAULT_UNKNOWN;
+               else
+                       addr = __raw_readl(
+                               data->sfrbases[i] + fault_reg_offset[itype]);
+       }
+
+       if (data->domain)
+               ret = report_iommu_fault(data->domain, data->dev,
+                               addr, itype);
+
+       if ((ret == -ENOSYS) && data->fault_handler) {
+               unsigned long base = data->pgtable;
+               if (itype != SYSMMU_FAULT_UNKNOWN)
+                       base = __raw_readl(
+                                       data->sfrbases[i] + REG_PT_BASE_ADDR);
+               ret = data->fault_handler(itype, base, addr);
+       }
+
+       if (!ret && (itype != SYSMMU_FAULT_UNKNOWN))
+               __raw_writel(1 << itype, data->sfrbases[i] + REG_INT_CLEAR);
+       else
+               dev_dbg(data->sysmmu, "(%s) %s is not handled.\n",
+                               data->dbgname, sysmmu_fault_name[itype]);
+
+       if (itype != SYSMMU_FAULT_UNKNOWN)
+               sysmmu_unblock(data->sfrbases[i]);
+
+       read_unlock(&data->lock);
+
+       return IRQ_HANDLED;
+}
+
+static bool __exynos_sysmmu_disable(struct sysmmu_drvdata *data)
+{
+       unsigned long flags;
+       bool disabled = false;
+       int i;
+
+       write_lock_irqsave(&data->lock, flags);
+
+       if (!set_sysmmu_inactive(data))
+               goto finish;
+
+       for (i = 0; i < data->nsfrs; i++)
+               __raw_writel(CTRL_DISABLE, data->sfrbases[i] + REG_MMU_CTRL);
+
+       if (data->clk[1])
+               clk_disable(data->clk[1]);
+       if (data->clk[0])
+               clk_disable(data->clk[0]);
+
+       disabled = true;
+       data->pgtable = 0;
+       data->domain = NULL;
+finish:
+       write_unlock_irqrestore(&data->lock, flags);
+
+       if (disabled)
+               dev_dbg(data->sysmmu, "(%s) Disabled\n", data->dbgname);
+       else
+               dev_dbg(data->sysmmu, "(%s) %d times left to be disabled\n",
+                                       data->dbgname, data->activations);
+
+       return disabled;
+}
+
+/* __exynos_sysmmu_enable: Enables System MMU
+ *
+ * returns -error if an error occurred and System MMU is not enabled,
+ * 0 if the System MMU has been just enabled and 1 if System MMU was already
+ * enabled before.
+ */
+static int __exynos_sysmmu_enable(struct sysmmu_drvdata *data,
+                       unsigned long pgtable, struct iommu_domain *domain)
+{
+       int i, ret = 0;
+       unsigned long flags;
+
+       write_lock_irqsave(&data->lock, flags);
+
+       if (!set_sysmmu_active(data)) {
+               if (WARN_ON(pgtable != data->pgtable)) {
+                       ret = -EBUSY;
+                       set_sysmmu_inactive(data);
+               } else {
+                       ret = 1;
+               }
+
+               dev_dbg(data->sysmmu, "(%s) Already enabled\n", data->dbgname);
+               goto finish;
+       }
+
+       if (data->clk[0])
+               clk_enable(data->clk[0]);
+       if (data->clk[1])
+               clk_enable(data->clk[1]);
+
+       data->pgtable = pgtable;
+
+       for (i = 0; i < data->nsfrs; i++) {
+               __sysmmu_set_ptbase(data->sfrbases[i], pgtable);
+
+               if ((readl(data->sfrbases[i] + REG_MMU_VERSION) >> 28) == 3) {
+                       /* System MMU version is 3.x */
+                       __raw_writel((1 << 12) | (2 << 28),
+                                       data->sfrbases[i] + REG_MMU_CFG);
+                       __sysmmu_set_prefbuf(data->sfrbases[i], 0, -1, 0);
+                       __sysmmu_set_prefbuf(data->sfrbases[i], 0, -1, 1);
+               }
+
+               __raw_writel(CTRL_ENABLE, data->sfrbases[i] + REG_MMU_CTRL);
+       }
+
+       data->domain = domain;
+
+       dev_dbg(data->sysmmu, "(%s) Enabled\n", data->dbgname);
+finish:
+       write_unlock_irqrestore(&data->lock, flags);
+
+       return ret;
+}
+
+int exynos_sysmmu_enable(struct device *dev, unsigned long pgtable)
+{
+       struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
+       int ret;
+
+       BUG_ON(!memblock_is_memory(pgtable));
+
+       ret = pm_runtime_get_sync(data->sysmmu);
+       if (ret < 0) {
+               dev_dbg(data->sysmmu, "(%s) Failed to enable\n", data->dbgname);
+               return ret;
+       }
+
+       ret = __exynos_sysmmu_enable(data, pgtable, NULL);
+       if (WARN_ON(ret < 0)) {
+               pm_runtime_put(data->sysmmu);
+               dev_err(data->sysmmu,
+                       "(%s) Already enabled with page table %#lx\n",
+                       data->dbgname, data->pgtable);
+       } else {
+               data->dev = dev;
+       }
+
+       return ret;
+}
+
+bool exynos_sysmmu_disable(struct device *dev)
+{
+       struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
+       bool disabled;
+
+       disabled = __exynos_sysmmu_disable(data);
+       pm_runtime_put(data->sysmmu);
+
+       return disabled;
+}
+
+static void sysmmu_tlb_invalidate_entry(struct device *dev, unsigned long iova)
+{
+       unsigned long flags;
+       struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
+
+       read_lock_irqsave(&data->lock, flags);
+
+       if (is_sysmmu_active(data)) {
+               int i;
+               for (i = 0; i < data->nsfrs; i++) {
+                       if (sysmmu_block(data->sfrbases[i])) {
+                               __sysmmu_tlb_invalidate_entry(
+                                               data->sfrbases[i], iova);
+                               sysmmu_unblock(data->sfrbases[i]);
+                       }
+               }
+       } else {
+               dev_dbg(data->sysmmu,
+                       "(%s) Disabled. Skipping invalidating TLB.\n",
+                       data->dbgname);
+       }
+
+       read_unlock_irqrestore(&data->lock, flags);
+}
+
+void exynos_sysmmu_tlb_invalidate(struct device *dev)
+{
+       unsigned long flags;
+       struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
+
+       read_lock_irqsave(&data->lock, flags);
+
+       if (is_sysmmu_active(data)) {
+               int i;
+               for (i = 0; i < data->nsfrs; i++) {
+                       if (sysmmu_block(data->sfrbases[i])) {
+                               __sysmmu_tlb_invalidate(data->sfrbases[i]);
+                               sysmmu_unblock(data->sfrbases[i]);
+                       }
+               }
+       } else {
+               dev_dbg(data->sysmmu,
+                       "(%s) Disabled. Skipping invalidating TLB.\n",
+                       data->dbgname);
+       }
+
+       read_unlock_irqrestore(&data->lock, flags);
+}
+
+static int exynos_sysmmu_probe(struct platform_device *pdev)
+{
+       int i, ret;
+       struct device *dev;
+       struct sysmmu_drvdata *data;
+
+       dev = &pdev->dev;
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data) {
+               dev_dbg(dev, "Not enough memory\n");
+               ret = -ENOMEM;
+               goto err_alloc;
+       }
+
+       ret = dev_set_drvdata(dev, data);
+       if (ret) {
+               dev_dbg(dev, "Unabled to initialize driver data\n");
+               goto err_init;
+       }
+
+       data->nsfrs = pdev->num_resources / 2;
+       data->sfrbases = kmalloc(sizeof(*data->sfrbases) * data->nsfrs,
+                                                               GFP_KERNEL);
+       if (data->sfrbases == NULL) {
+               dev_dbg(dev, "Not enough memory\n");
+               ret = -ENOMEM;
+               goto err_init;
+       }
+
+       for (i = 0; i < data->nsfrs; i++) {
+               struct resource *res;
+               res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+               if (!res) {
+                       dev_dbg(dev, "Unable to find IOMEM region\n");
+                       ret = -ENOENT;
+                       goto err_res;
+               }
+
+               data->sfrbases[i] = ioremap(res->start, resource_size(res));
+               if (!data->sfrbases[i]) {
+                       dev_dbg(dev, "Unable to map IOMEM @ PA:%#x\n",
+                                                       res->start);
+                       ret = -ENOENT;
+                       goto err_res;
+               }
+       }
+
+       for (i = 0; i < data->nsfrs; i++) {
+               ret = platform_get_irq(pdev, i);
+               if (ret <= 0) {
+                       dev_dbg(dev, "Unable to find IRQ resource\n");
+                       goto err_irq;
+               }
+
+               ret = request_irq(ret, exynos_sysmmu_irq, 0,
+                                       dev_name(dev), data);
+               if (ret) {
+                       dev_dbg(dev, "Unabled to register interrupt handler\n");
+                       goto err_irq;
+               }
+       }
+
+       if (dev_get_platdata(dev)) {
+               char *deli, *beg;
+               struct sysmmu_platform_data *platdata = dev_get_platdata(dev);
+
+               beg = platdata->clockname;
+
+               for (deli = beg; (*deli != '\0') && (*deli != ','); deli++)
+                       /* NOTHING */;
+
+               if (*deli == '\0')
+                       deli = NULL;
+               else
+                       *deli = '\0';
+
+               data->clk[0] = clk_get(dev, beg);
+               if (IS_ERR(data->clk[0])) {
+                       data->clk[0] = NULL;
+                       dev_dbg(dev, "No clock descriptor registered\n");
+               }
+
+               if (data->clk[0] && deli) {
+                       *deli = ',';
+                       data->clk[1] = clk_get(dev, deli + 1);
+                       if (IS_ERR(data->clk[1]))
+                               data->clk[1] = NULL;
+               }
+
+               data->dbgname = platdata->dbgname;
+       }
+
+       data->sysmmu = dev;
+       rwlock_init(&data->lock);
+       INIT_LIST_HEAD(&data->node);
+
+       __set_fault_handler(data, &default_fault_handler);
+
+       if (dev->parent)
+               pm_runtime_enable(dev);
+
+       dev_dbg(dev, "(%s) Initialized\n", data->dbgname);
+       return 0;
+err_irq:
+       while (i-- > 0) {
+               int irq;
+
+               irq = platform_get_irq(pdev, i);
+               free_irq(irq, data);
+       }
+err_res:
+       while (data->nsfrs-- > 0)
+               iounmap(data->sfrbases[data->nsfrs]);
+       kfree(data->sfrbases);
+err_init:
+       kfree(data);
+err_alloc:
+       dev_err(dev, "Failed to initialize\n");
+       return ret;
+}
+
+static struct platform_driver exynos_sysmmu_driver = {
+       .probe          = exynos_sysmmu_probe,
+       .driver         = {
+               .owner          = THIS_MODULE,
+               .name           = "exynos-sysmmu",
+       }
+};
+
+static inline void pgtable_flush(void *vastart, void *vaend)
+{
+       dmac_flush_range(vastart, vaend);
+       outer_flush_range(virt_to_phys(vastart),
+                               virt_to_phys(vaend));
+}
+
+static int exynos_iommu_domain_init(struct iommu_domain *domain)
+{
+       struct exynos_iommu_domain *priv;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->pgtable = (unsigned long *)__get_free_pages(
+                                               GFP_KERNEL | __GFP_ZERO, 2);
+       if (!priv->pgtable)
+               goto err_pgtable;
+
+       priv->lv2entcnt = (short *)__get_free_pages(
+                                               GFP_KERNEL | __GFP_ZERO, 1);
+       if (!priv->lv2entcnt)
+               goto err_counter;
+
+       pgtable_flush(priv->pgtable, priv->pgtable + NUM_LV1ENTRIES);
+
+       spin_lock_init(&priv->lock);
+       spin_lock_init(&priv->pgtablelock);
+       INIT_LIST_HEAD(&priv->clients);
+
+       domain->priv = priv;
+       return 0;
+
+err_counter:
+       free_pages((unsigned long)priv->pgtable, 2);
+err_pgtable:
+       kfree(priv);
+       return -ENOMEM;
+}
+
+static void exynos_iommu_domain_destroy(struct iommu_domain *domain)
+{
+       struct exynos_iommu_domain *priv = domain->priv;
+       struct sysmmu_drvdata *data;
+       unsigned long flags;
+       int i;
+
+       WARN_ON(!list_empty(&priv->clients));
+
+       spin_lock_irqsave(&priv->lock, flags);
+
+       list_for_each_entry(data, &priv->clients, node) {
+               while (!exynos_sysmmu_disable(data->dev))
+                       ; /* until System MMU is actually disabled */
+       }
+
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       for (i = 0; i < NUM_LV1ENTRIES; i++)
+               if (lv1ent_page(priv->pgtable + i))
+                       kfree(__va(lv2table_base(priv->pgtable + i)));
+
+       free_pages((unsigned long)priv->pgtable, 2);
+       free_pages((unsigned long)priv->lv2entcnt, 1);
+       kfree(domain->priv);
+       domain->priv = NULL;
+}
+
+static int exynos_iommu_attach_device(struct iommu_domain *domain,
+                                  struct device *dev)
+{
+       struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
+       struct exynos_iommu_domain *priv = domain->priv;
+       unsigned long flags;
+       int ret;
+
+       ret = pm_runtime_get_sync(data->sysmmu);
+       if (ret < 0)
+               return ret;
+
+       ret = 0;
+
+       spin_lock_irqsave(&priv->lock, flags);
+
+       ret = __exynos_sysmmu_enable(data, __pa(priv->pgtable), domain);
+
+       if (ret == 0) {
+               /* 'data->node' must not be appeared in priv->clients */
+               BUG_ON(!list_empty(&data->node));
+               data->dev = dev;
+               list_add_tail(&data->node, &priv->clients);
+       }
+
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       if (ret < 0) {
+               dev_err(dev, "%s: Failed to attach IOMMU with pgtable %#lx\n",
+                               __func__, __pa(priv->pgtable));
+               pm_runtime_put(data->sysmmu);
+       } else if (ret > 0) {
+               dev_dbg(dev, "%s: IOMMU with pgtable 0x%lx already attached\n",
+                                       __func__, __pa(priv->pgtable));
+       } else {
+               dev_dbg(dev, "%s: Attached new IOMMU with pgtable 0x%lx\n",
+                                       __func__, __pa(priv->pgtable));
+       }
+
+       return ret;
+}
+
+static void exynos_iommu_detach_device(struct iommu_domain *domain,
+                                   struct device *dev)
+{
+       struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
+       struct exynos_iommu_domain *priv = domain->priv;
+       struct list_head *pos;
+       unsigned long flags;
+       bool found = false;
+
+       spin_lock_irqsave(&priv->lock, flags);
+
+       list_for_each(pos, &priv->clients) {
+               if (list_entry(pos, struct sysmmu_drvdata, node) == data) {
+                       found = true;
+                       break;
+               }
+       }
+
+       if (!found)
+               goto finish;
+
+       if (__exynos_sysmmu_disable(data)) {
+               dev_dbg(dev, "%s: Detached IOMMU with pgtable %#lx\n",
+                                       __func__, __pa(priv->pgtable));
+               list_del(&data->node);
+               INIT_LIST_HEAD(&data->node);
+
+       } else {
+               dev_dbg(dev, "%s: Detaching IOMMU with pgtable %#lx delayed",
+                                       __func__, __pa(priv->pgtable));
+       }
+
+finish:
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       if (found)
+               pm_runtime_put(data->sysmmu);
+}
+
+static unsigned long *alloc_lv2entry(unsigned long *sent, unsigned long iova,
+                                       short *pgcounter)
+{
+       if (lv1ent_fault(sent)) {
+               unsigned long *pent;
+
+               pent = kzalloc(LV2TABLE_SIZE, GFP_ATOMIC);
+               BUG_ON((unsigned long)pent & (LV2TABLE_SIZE - 1));
+               if (!pent)
+                       return NULL;
+
+               *sent = mk_lv1ent_page(__pa(pent));
+               *pgcounter = NUM_LV2ENTRIES;
+               pgtable_flush(pent, pent + NUM_LV2ENTRIES);
+               pgtable_flush(sent, sent + 1);
+       }
+
+       return page_entry(sent, iova);
+}
+
+static int lv1set_section(unsigned long *sent, phys_addr_t paddr, short *pgcnt)
+{
+       if (lv1ent_section(sent))
+               return -EADDRINUSE;
+
+       if (lv1ent_page(sent)) {
+               if (*pgcnt != NUM_LV2ENTRIES)
+                       return -EADDRINUSE;
+
+               kfree(page_entry(sent, 0));
+
+               *pgcnt = 0;
+       }
+
+       *sent = mk_lv1ent_sect(paddr);
+
+       pgtable_flush(sent, sent + 1);
+
+       return 0;
+}
+
+static int lv2set_page(unsigned long *pent, phys_addr_t paddr, size_t size,
+                                                               short *pgcnt)
+{
+       if (size == SPAGE_SIZE) {
+               if (!lv2ent_fault(pent))
+                       return -EADDRINUSE;
+
+               *pent = mk_lv2ent_spage(paddr);
+               pgtable_flush(pent, pent + 1);
+               *pgcnt -= 1;
+       } else { /* size == LPAGE_SIZE */
+               int i;
+               for (i = 0; i < SPAGES_PER_LPAGE; i++, pent++) {
+                       if (!lv2ent_fault(pent)) {
+                               memset(pent, 0, sizeof(*pent) * i);
+                               return -EADDRINUSE;
+                       }
+
+                       *pent = mk_lv2ent_lpage(paddr);
+               }
+               pgtable_flush(pent - SPAGES_PER_LPAGE, pent);
+               *pgcnt -= SPAGES_PER_LPAGE;
+       }
+
+       return 0;
+}
+
+static int exynos_iommu_map(struct iommu_domain *domain, unsigned long iova,
+                        phys_addr_t paddr, size_t size, int prot)
+{
+       struct exynos_iommu_domain *priv = domain->priv;
+       unsigned long *entry;
+       unsigned long flags;
+       int ret = -ENOMEM;
+
+       BUG_ON(priv->pgtable == NULL);
+
+       spin_lock_irqsave(&priv->pgtablelock, flags);
+
+       entry = section_entry(priv->pgtable, iova);
+
+       if (size == SECT_SIZE) {
+               ret = lv1set_section(entry, paddr,
+                                       &priv->lv2entcnt[lv1ent_offset(iova)]);
+       } else {
+               unsigned long *pent;
+
+               pent = alloc_lv2entry(entry, iova,
+                                       &priv->lv2entcnt[lv1ent_offset(iova)]);
+
+               if (!pent)
+                       ret = -ENOMEM;
+               else
+                       ret = lv2set_page(pent, paddr, size,
+                                       &priv->lv2entcnt[lv1ent_offset(iova)]);
+       }
+
+       if (ret) {
+               pr_debug("%s: Failed to map iova 0x%lx/0x%x bytes\n",
+                                                       __func__, iova, size);
+       }
+
+       spin_unlock_irqrestore(&priv->pgtablelock, flags);
+
+       return ret;
+}
+
+static size_t exynos_iommu_unmap(struct iommu_domain *domain,
+                                              unsigned long iova, size_t size)
+{
+       struct exynos_iommu_domain *priv = domain->priv;
+       struct sysmmu_drvdata *data;
+       unsigned long flags;
+       unsigned long *ent;
+
+       BUG_ON(priv->pgtable == NULL);
+
+       spin_lock_irqsave(&priv->pgtablelock, flags);
+
+       ent = section_entry(priv->pgtable, iova);
+
+       if (lv1ent_section(ent)) {
+               BUG_ON(size < SECT_SIZE);
+
+               *ent = 0;
+               pgtable_flush(ent, ent + 1);
+               size = SECT_SIZE;
+               goto done;
+       }
+
+       if (unlikely(lv1ent_fault(ent))) {
+               if (size > SECT_SIZE)
+                       size = SECT_SIZE;
+               goto done;
+       }
+
+       /* lv1ent_page(sent) == true here */
+
+       ent = page_entry(ent, iova);
+
+       if (unlikely(lv2ent_fault(ent))) {
+               size = SPAGE_SIZE;
+               goto done;
+       }
+
+       if (lv2ent_small(ent)) {
+               *ent = 0;
+               size = SPAGE_SIZE;
+               priv->lv2entcnt[lv1ent_offset(iova)] += 1;
+               goto done;
+       }
+
+       /* lv1ent_large(ent) == true here */
+       BUG_ON(size < LPAGE_SIZE);
+
+       memset(ent, 0, sizeof(*ent) * SPAGES_PER_LPAGE);
+
+       size = LPAGE_SIZE;
+       priv->lv2entcnt[lv1ent_offset(iova)] += SPAGES_PER_LPAGE;
+done:
+       spin_unlock_irqrestore(&priv->pgtablelock, flags);
+
+       spin_lock_irqsave(&priv->lock, flags);
+       list_for_each_entry(data, &priv->clients, node)
+               sysmmu_tlb_invalidate_entry(data->dev, iova);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+
+       return size;
+}
+
+static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *domain,
+                                         unsigned long iova)
+{
+       struct exynos_iommu_domain *priv = domain->priv;
+       unsigned long *entry;
+       unsigned long flags;
+       phys_addr_t phys = 0;
+
+       spin_lock_irqsave(&priv->pgtablelock, flags);
+
+       entry = section_entry(priv->pgtable, iova);
+
+       if (lv1ent_section(entry)) {
+               phys = section_phys(entry) + section_offs(iova);
+       } else if (lv1ent_page(entry)) {
+               entry = page_entry(entry, iova);
+
+               if (lv2ent_large(entry))
+                       phys = lpage_phys(entry) + lpage_offs(iova);
+               else if (lv2ent_small(entry))
+                       phys = spage_phys(entry) + spage_offs(iova);
+       }
+
+       spin_unlock_irqrestore(&priv->pgtablelock, flags);
+
+       return phys;
+}
+
+static struct iommu_ops exynos_iommu_ops = {
+       .domain_init = &exynos_iommu_domain_init,
+       .domain_destroy = &exynos_iommu_domain_destroy,
+       .attach_dev = &exynos_iommu_attach_device,
+       .detach_dev = &exynos_iommu_detach_device,
+       .map = &exynos_iommu_map,
+       .unmap = &exynos_iommu_unmap,
+       .iova_to_phys = &exynos_iommu_iova_to_phys,
+       .pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE,
+};
+
+static int __init exynos_iommu_init(void)
+{
+       int ret;
+
+       ret = platform_driver_register(&exynos_sysmmu_driver);
+
+       if (ret == 0)
+               bus_set_iommu(&platform_bus_type, &exynos_iommu_ops);
+
+       return ret;
+}
+subsys_initcall(exynos_iommu_init);
index a9fc714fb38daed1113aab632047c8304347ac78..9a7a60aeb19ea35dc921cd43f2e796c2bfd75469 100644 (file)
@@ -1781,7 +1781,7 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
                pdata->slots[0].nonremovable = true;
                pdata->slots[0].no_regulator_off_init = true;
        }
-       of_property_read_u32(np, "ti,bus-width", &bus_width);
+       of_property_read_u32(np, "bus-width", &bus_width);
        if (bus_width == 4)
                pdata->slots[0].caps |= MMC_CAP_4_BIT_DATA;
        else if (bus_width == 8)
index d190d04636a714e87da50a3f8748b17347ca225f..365b16c230f8905653c4987c61dda268721d5334 100644 (file)
@@ -404,7 +404,7 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
        if (!np)
                return -ENODEV;
 
-       if (of_get_property(np, "fsl,card-wired", NULL))
+       if (of_get_property(np, "non-removable", NULL))
                boarddata->cd_type = ESDHC_CD_PERMANENT;
 
        if (of_get_property(np, "fsl,cd-controller", NULL))
index c5c2a48bdd943166bff4e15ddf59718f3fbffa9a..d9a4ef4f1ed0e8b65cc212ce44a014093f5bf8fd 100644 (file)
@@ -42,7 +42,8 @@ static struct sdhci_ops sdhci_pltfm_ops = {
 #ifdef CONFIG_OF
 static bool sdhci_of_wp_inverted(struct device_node *np)
 {
-       if (of_get_property(np, "sdhci,wp-inverted", NULL))
+       if (of_get_property(np, "sdhci,wp-inverted", NULL) ||
+           of_get_property(np, "wp-inverted", NULL))
                return true;
 
        /* Old device trees don't have the wp-inverted property. */
@@ -59,13 +60,16 @@ void sdhci_get_of_property(struct platform_device *pdev)
        struct sdhci_host *host = platform_get_drvdata(pdev);
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        const __be32 *clk;
+       u32 bus_width;
        int size;
 
        if (of_device_is_available(np)) {
                if (of_get_property(np, "sdhci,auto-cmd12", NULL))
                        host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
 
-               if (of_get_property(np, "sdhci,1-bit-only", NULL))
+               if (of_get_property(np, "sdhci,1-bit-only", NULL) ||
+                   (of_property_read_u32(np, "bus-width", &bus_width) == 0 &&
+                   bus_width == 1))
                        host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
 
                if (sdhci_of_wp_inverted(np))
index 4a44bf833611bc88126005d219853ae15850621b..68548236ec4228ceb224d69845daba6345bf9971 100644 (file)
@@ -722,8 +722,9 @@ static int tegra_ehci_probe(struct platform_device *pdev)
                }
        }
 
-       tegra->phy = tegra_usb_phy_open(instance, hcd->regs, pdata->phy_config,
-                                               TEGRA_USB_PHY_MODE_HOST);
+       tegra->phy = tegra_usb_phy_open(&pdev->dev, instance, hcd->regs,
+                                       pdata->phy_config,
+                                       TEGRA_USB_PHY_MODE_HOST);
        if (IS_ERR(tegra->phy)) {
                dev_err(&pdev->dev, "Failed to open USB phy\n");
                err = -ENXIO;