浏览代码

Merge branch 'mmp/dt' into next/pm

The mmp power management changes are based on this branch, so pull
it in as a dependency.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Arnd Bergmann 13 年之前
父节点
当前提交
853b20396b

+ 40 - 0
Documentation/devicetree/bindings/arm/mrvl/intc.txt

@@ -0,0 +1,40 @@
+* Marvell MMP Interrupt controller
+
+Required properties:
+- compatible : Should be "mrvl,mmp-intc", "mrvl,mmp2-intc" or
+  "mrvl,mmp2-mux-intc"
+- reg : Address and length of the register set of the interrupt controller.
+  If the interrupt controller is intc, address and length means the range
+  of the whold interrupt controller. If the interrupt controller is mux-intc,
+  address and length means one register. Since address of mux-intc is in the
+  range of intc. mux-intc is secondary interrupt controller.
+- reg-names : Name of the register set of the interrupt controller. It's
+  only required in mux-intc interrupt controller.
+- interrupts : Should be the port interrupt shared by mux interrupts. It's
+  only required in mux-intc interrupt controller.
+- interrupt-controller : Identifies the node as an interrupt controller.
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source.
+- mrvl,intc-nr-irqs : Specifies the number of interrupts in the interrupt
+  controller.
+- mrvl,clr-mfp-irq : Specifies the interrupt that needs to clear MFP edge
+  detection first.
+
+Example:
+	intc: interrupt-controller@d4282000 {
+		compatible = "mrvl,mmp2-intc";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0xd4282000 0x1000>;
+		mrvl,intc-nr-irqs = <64>;
+	};
+
+	intcmux4@d4282150 {
+		compatible = "mrvl,mmp2-mux-intc";
+		interrupts = <4>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0x150 0x4>, <0x168 0x4>;
+		reg-names = "mux status", "mux mask";
+		mrvl,intc-nr-irqs = <2>;
+	};

+ 8 - 0
Documentation/devicetree/bindings/arm/mrvl.txt → Documentation/devicetree/bindings/arm/mrvl/mrvl.txt

@@ -4,3 +4,11 @@ Marvell Platforms Device Tree Bindings
 PXA168 Aspenite Board
 PXA168 Aspenite Board
 Required root node properties:
 Required root node properties:
 	- compatible = "mrvl,pxa168-aspenite", "mrvl,pxa168";
 	- compatible = "mrvl,pxa168-aspenite", "mrvl,pxa168";
+
+PXA910 DKB Board
+Required root node properties:
+	- compatible = "mrvl,pxa910-dkb";
+
+MMP2 Brownstone Board
+Required root node properties:
+	- compatible = "mrvl,mmp2-brownstone";

+ 13 - 0
Documentation/devicetree/bindings/arm/mrvl/timer.txt

@@ -0,0 +1,13 @@
+* Marvell MMP Timer controller
+
+Required properties:
+- compatible : Should be "mrvl,mmp-timer".
+- reg : Address and length of the register set of timer controller.
+- interrupts : Should be the interrupt number.
+
+Example:
+	timer0: timer@d4014000 {
+		compatible = "mrvl,mmp-timer";
+		reg = <0xd4014000 0x100>;
+		interrupts = <13>;
+	};

+ 12 - 6
Documentation/devicetree/bindings/gpio/mrvl-gpio.txt

@@ -3,19 +3,25 @@
 Required properties:
 Required properties:
 - compatible : Should be "mrvl,pxa-gpio" or "mrvl,mmp-gpio"
 - compatible : Should be "mrvl,pxa-gpio" or "mrvl,mmp-gpio"
 - reg : Address and length of the register set for the device
 - reg : Address and length of the register set for the device
-- interrupts : Should be the port interrupt shared by all gpio pins, if
-- interrupt-name : Should be the name of irq resource.
-  one number.
+- interrupts : Should be the port interrupt shared by all gpio pins.
+  There're three gpio interrupts in arch-pxa, and they're gpio0,
+  gpio1 and gpio_mux. There're only one gpio interrupt in arch-mmp,
+  gpio_mux.
+- interrupt-name : Should be the name of irq resource. Each interrupt
+  binds its interrupt-name.
+- interrupt-controller : Identifies the node as an interrupt controller.
+- #interrupt-cells: Specifies the number of cells needed to encode an
+  interrupt source.
 - gpio-controller : Marks the device node as a gpio controller.
 - gpio-controller : Marks the device node as a gpio controller.
 - #gpio-cells : Should be one.  It is the pin number.
 - #gpio-cells : Should be one.  It is the pin number.
 
 
 Example:
 Example:
 
 
 	gpio: gpio@d4019000 {
 	gpio: gpio@d4019000 {
-		compatible = "mrvl,mmp-gpio", "mrvl,pxa-gpio";
+		compatible = "mrvl,mmp-gpio";
 		reg = <0xd4019000 0x1000>;
 		reg = <0xd4019000 0x1000>;
-		interrupts = <49>, <17>, <18>;
-		interrupt-name = "gpio_mux", "gpio0", "gpio1";
+		interrupts = <49>;
+		interrupt-name = "gpio_mux";
 		gpio-controller;
 		gpio-controller;
 		#gpio-cells = <1>;
 		#gpio-cells = <1>;
 		interrupt-controller;
 		interrupt-controller;

+ 6 - 9
Documentation/devicetree/bindings/i2c/mrvl-i2c.txt

@@ -3,34 +3,31 @@
 Required properties :
 Required properties :
 
 
  - reg : Offset and length of the register set for the device
  - reg : Offset and length of the register set for the device
- - compatible : should be "mrvl,mmp-twsi" where CHIP is the name of a
+ - compatible : should be "mrvl,mmp-twsi" where mmp is the name of a
    compatible processor, e.g. pxa168, pxa910, mmp2, mmp3.
    compatible processor, e.g. pxa168, pxa910, mmp2, mmp3.
    For the pxa2xx/pxa3xx, an additional node "mrvl,pxa-i2c" is required
    For the pxa2xx/pxa3xx, an additional node "mrvl,pxa-i2c" is required
    as shown in the example below.
    as shown in the example below.
 
 
 Recommended properties :
 Recommended properties :
 
 
- - interrupts : <a b> where a is the interrupt number and b is a
-   field that represents an encoding of the sense and level
-   information for the interrupt.  This should be encoded based on
-   the information in section 2) depending on the type of interrupt
-   controller you have.
+ - interrupts : the interrupt number
  - interrupt-parent : the phandle for the interrupt controller that
  - interrupt-parent : the phandle for the interrupt controller that
-   services interrupts for this device.
+   services interrupts for this device. If the parent is the default
+   interrupt controller in device tree, it could be ignored.
  - mrvl,i2c-polling : Disable interrupt of i2c controller. Polling
  - mrvl,i2c-polling : Disable interrupt of i2c controller. Polling
    status register of i2c controller instead.
    status register of i2c controller instead.
  - mrvl,i2c-fast-mode : Enable fast mode of i2c controller.
  - mrvl,i2c-fast-mode : Enable fast mode of i2c controller.
 
 
 Examples:
 Examples:
 	twsi1: i2c@d4011000 {
 	twsi1: i2c@d4011000 {
-		compatible = "mrvl,mmp-twsi", "mrvl,pxa-i2c";
+		compatible = "mrvl,mmp-twsi";
 		reg = <0xd4011000 0x1000>;
 		reg = <0xd4011000 0x1000>;
 		interrupts = <7>;
 		interrupts = <7>;
 		mrvl,i2c-fast-mode;
 		mrvl,i2c-fast-mode;
 	};
 	};
 	
 	
 	twsi2: i2c@d4025000 {
 	twsi2: i2c@d4025000 {
-		compatible = "mrvl,mmp-twsi", "mrvl,pxa-i2c";
+		compatible = "mrvl,mmp-twsi";
 		reg = <0xd4025000 0x1000>;
 		reg = <0xd4025000 0x1000>;
 		interrupts = <58>;
 		interrupts = <58>;
 	};
 	};

+ 1 - 0
arch/arm/Kconfig

@@ -632,6 +632,7 @@ config ARCH_MMP
 	select CLKDEV_LOOKUP
 	select CLKDEV_LOOKUP
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_CLOCKEVENTS
 	select GPIO_PXA
 	select GPIO_PXA
+	select IRQ_DOMAIN
 	select TICK_ONESHOT
 	select TICK_ONESHOT
 	select PLAT_PXA
 	select PLAT_PXA
 	select SPARSE_IRQ
 	select SPARSE_IRQ

+ 38 - 0
arch/arm/boot/dts/mmp2-brownstone.dts

@@ -0,0 +1,38 @@
+/*
+ *  Copyright (C) 2012 Marvell Technology Group Ltd.
+ *  Author: Haojian Zhuang <haojian.zhuang@marvell.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
+ *  publishhed by the Free Software Foundation.
+ */
+
+/dts-v1/;
+/include/ "mmp2.dtsi"
+
+/ {
+	model = "Marvell MMP2 Aspenite Development Board";
+	compatible = "mrvl,mmp2-brownstone", "mrvl,mmp2";
+
+	chosen {
+		bootargs = "console=ttyS2,38400 root=/dev/nfs nfsroot=192.168.1.100:/nfsroot/ ip=192.168.1.101:192.168.1.100::255.255.255.0::eth0:on";
+	};
+
+	memory {
+		reg = <0x00000000 0x04000000>;
+	};
+
+	soc {
+		apb@d4000000 {
+			uart3: uart@d4018000 {
+				status = "okay";
+			};
+			twsi1: i2c@d4011000 {
+				status = "okay";
+			};
+			rtc: rtc@d4010000 {
+				status = "okay";
+			};
+		};
+	};
+};

+ 220 - 0
arch/arm/boot/dts/mmp2.dtsi

@@ -0,0 +1,220 @@
+/*
+ *  Copyright (C) 2012 Marvell Technology Group Ltd.
+ *  Author: Haojian Zhuang <haojian.zhuang@marvell.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
+ *  publishhed by the Free Software Foundation.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	aliases {
+		serial0 = &uart1;
+		serial1 = &uart2;
+		serial2 = &uart3;
+		serial3 = &uart4;
+		i2c0 = &twsi1;
+		i2c1 = &twsi2;
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&intc>;
+		ranges;
+
+		axi@d4200000 {	/* AXI */
+			compatible = "mrvl,axi-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0xd4200000 0x00200000>;
+			ranges;
+
+			intc: interrupt-controller@d4282000 {
+				compatible = "mrvl,mmp2-intc";
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				reg = <0xd4282000 0x1000>;
+				mrvl,intc-nr-irqs = <64>;
+			};
+
+			intcmux4@d4282150 {
+				compatible = "mrvl,mmp2-mux-intc";
+				interrupts = <4>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				reg = <0x150 0x4>, <0x168 0x4>;
+				reg-names = "mux status", "mux mask";
+				mrvl,intc-nr-irqs = <2>;
+			};
+
+			intcmux5: interrupt-controller@d4282154 {
+				compatible = "mrvl,mmp2-mux-intc";
+				interrupts = <5>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				reg = <0x154 0x4>, <0x16c 0x4>;
+				reg-names = "mux status", "mux mask";
+				mrvl,intc-nr-irqs = <2>;
+				mrvl,clr-mfp-irq = <1>;
+			};
+
+			intcmux9: interrupt-controller@d4282180 {
+				compatible = "mrvl,mmp2-mux-intc";
+				interrupts = <9>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				reg = <0x180 0x4>, <0x17c 0x4>;
+				reg-names = "mux status", "mux mask";
+				mrvl,intc-nr-irqs = <3>;
+			};
+
+			intcmux17: interrupt-controller@d4282158 {
+				compatible = "mrvl,mmp2-mux-intc";
+				interrupts = <17>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				reg = <0x158 0x4>, <0x170 0x4>;
+				reg-names = "mux status", "mux mask";
+				mrvl,intc-nr-irqs = <5>;
+			};
+
+			intcmux35: interrupt-controller@d428215c {
+				compatible = "mrvl,mmp2-mux-intc";
+				interrupts = <35>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				reg = <0x15c 0x4>, <0x174 0x4>;
+				reg-names = "mux status", "mux mask";
+				mrvl,intc-nr-irqs = <15>;
+			};
+
+			intcmux51: interrupt-controller@d4282160 {
+				compatible = "mrvl,mmp2-mux-intc";
+				interrupts = <51>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				reg = <0x160 0x4>, <0x178 0x4>;
+				reg-names = "mux status", "mux mask";
+				mrvl,intc-nr-irqs = <2>;
+			};
+
+			intcmux55: interrupt-controller@d4282188 {
+				compatible = "mrvl,mmp2-mux-intc";
+				interrupts = <55>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				reg = <0x188 0x4>, <0x184 0x4>;
+				reg-names = "mux status", "mux mask";
+				mrvl,intc-nr-irqs = <2>;
+			};
+		};
+
+		apb@d4000000 {	/* APB */
+			compatible = "mrvl,apb-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0xd4000000 0x00200000>;
+			ranges;
+
+			timer0: timer@d4014000 {
+				compatible = "mrvl,mmp-timer";
+				reg = <0xd4014000 0x100>;
+				interrupts = <13>;
+			};
+
+			uart1: uart@d4030000 {
+				compatible = "mrvl,mmp-uart";
+				reg = <0xd4030000 0x1000>;
+				interrupts = <27>;
+				status = "disabled";
+			};
+
+			uart2: uart@d4017000 {
+				compatible = "mrvl,mmp-uart";
+				reg = <0xd4017000 0x1000>;
+				interrupts = <28>;
+				status = "disabled";
+			};
+
+			uart3: uart@d4018000 {
+				compatible = "mrvl,mmp-uart";
+				reg = <0xd4018000 0x1000>;
+				interrupts = <24>;
+				status = "disabled";
+			};
+
+			uart4: uart@d4016000 {
+				compatible = "mrvl,mmp-uart";
+				reg = <0xd4016000 0x1000>;
+				interrupts = <46>;
+				status = "disabled";
+			};
+
+			gpio@d4019000 {
+				compatible = "mrvl,mmp-gpio";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0xd4019000 0x1000>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupts = <49>;
+				interrupt-names = "gpio_mux";
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				ranges;
+
+				gcb0: gpio@d4019000 {
+					reg = <0xd4019000 0x4>;
+				};
+
+				gcb1: gpio@d4019004 {
+					reg = <0xd4019004 0x4>;
+				};
+
+				gcb2: gpio@d4019008 {
+					reg = <0xd4019008 0x4>;
+				};
+
+				gcb3: gpio@d4019100 {
+					reg = <0xd4019100 0x4>;
+				};
+
+				gcb4: gpio@d4019104 {
+					reg = <0xd4019104 0x4>;
+				};
+
+				gcb5: gpio@d4019108 {
+					reg = <0xd4019108 0x4>;
+				};
+			};
+
+			twsi1: i2c@d4011000 {
+				compatible = "mrvl,mmp-twsi";
+				reg = <0xd4011000 0x1000>;
+				interrupts = <7>;
+				mrvl,i2c-fast-mode;
+				status = "disabled";
+			};
+
+			twsi2: i2c@d4025000 {
+				compatible = "mrvl,mmp-twsi";
+				reg = <0xd4025000 0x1000>;
+				interrupts = <58>;
+				status = "disabled";
+			};
+
+			rtc: rtc@d4010000 {
+				compatible = "mrvl,mmp-rtc";
+				reg = <0xd4010000 0x1000>;
+				interrupts = <1 0>;
+				interrupt-names = "rtc 1Hz", "rtc alarm";
+				interrupt-parent = <&intcmux5>;
+				status = "disabled";
+			};
+		};
+	};
+};

+ 51 - 16
arch/arm/boot/dts/pxa168.dtsi

@@ -18,13 +18,6 @@
 		i2c1 = &twsi2;
 		i2c1 = &twsi2;
 	};
 	};
 
 
-	intc: intc-interrupt-controller@d4282000 {
-		compatible = "mrvl,mmp-intc", "mrvl,intc";
-		interrupt-controller;
-		#interrupt-cells = <1>;
-		reg = <0xd4282000 0x1000>;
-	};
-
 	soc {
 	soc {
 		#address-cells = <1>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 		#size-cells = <1>;
@@ -32,6 +25,23 @@
 		interrupt-parent = <&intc>;
 		interrupt-parent = <&intc>;
 		ranges;
 		ranges;
 
 
+		axi@d4200000 {	/* AXI */
+			compatible = "mrvl,axi-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0xd4200000 0x00200000>;
+			ranges;
+
+			intc: interrupt-controller@d4282000 {
+				compatible = "mrvl,mmp-intc";
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				reg = <0xd4282000 0x1000>;
+				mrvl,intc-nr-irqs = <64>;
+			};
+
+		};
+
 		apb@d4000000 {	/* APB */
 		apb@d4000000 {	/* APB */
 			compatible = "mrvl,apb-bus", "simple-bus";
 			compatible = "mrvl,apb-bus", "simple-bus";
 			#address-cells = <1>;
 			#address-cells = <1>;
@@ -39,40 +49,65 @@
 			reg = <0xd4000000 0x00200000>;
 			reg = <0xd4000000 0x00200000>;
 			ranges;
 			ranges;
 
 
+			timer0: timer@d4014000 {
+				compatible = "mrvl,mmp-timer";
+				reg = <0xd4014000 0x100>;
+				interrupts = <13>;
+			};
+
 			uart1: uart@d4017000 {
 			uart1: uart@d4017000 {
-				compatible = "mrvl,mmp-uart", "mrvl,pxa-uart";
+				compatible = "mrvl,mmp-uart";
 				reg = <0xd4017000 0x1000>;
 				reg = <0xd4017000 0x1000>;
 				interrupts = <27>;
 				interrupts = <27>;
 				status = "disabled";
 				status = "disabled";
 			};
 			};
 
 
 			uart2: uart@d4018000 {
 			uart2: uart@d4018000 {
-				compatible = "mrvl,mmp-uart", "mrvl,pxa-uart";
+				compatible = "mrvl,mmp-uart";
 				reg = <0xd4018000 0x1000>;
 				reg = <0xd4018000 0x1000>;
 				interrupts = <28>;
 				interrupts = <28>;
 				status = "disabled";
 				status = "disabled";
 			};
 			};
 
 
 			uart3: uart@d4026000 {
 			uart3: uart@d4026000 {
-				compatible = "mrvl,mmp-uart", "mrvl,pxa-uart";
+				compatible = "mrvl,mmp-uart";
 				reg = <0xd4026000 0x1000>;
 				reg = <0xd4026000 0x1000>;
 				interrupts = <29>;
 				interrupts = <29>;
 				status = "disabled";
 				status = "disabled";
 			};
 			};
 
 
-			gpio: gpio@d4019000 {
-				compatible = "mrvl,mmp-gpio", "mrvl,pxa-gpio";
+			gpio@d4019000 {
+				compatible = "mrvl,mmp-gpio";
+				#address-cells = <1>;
+				#size-cells = <1>;
 				reg = <0xd4019000 0x1000>;
 				reg = <0xd4019000 0x1000>;
+				gpio-controller;
+				#gpio-cells = <2>;
 				interrupts = <49>;
 				interrupts = <49>;
 				interrupt-names = "gpio_mux";
 				interrupt-names = "gpio_mux";
-				gpio-controller;
-				#gpio-cells = <1>;
 				interrupt-controller;
 				interrupt-controller;
 				#interrupt-cells = <1>;
 				#interrupt-cells = <1>;
+				ranges;
+
+				gcb0: gpio@d4019000 {
+					reg = <0xd4019000 0x4>;
+				};
+
+				gcb1: gpio@d4019004 {
+					reg = <0xd4019004 0x4>;
+				};
+
+				gcb2: gpio@d4019008 {
+					reg = <0xd4019008 0x4>;
+				};
+
+				gcb3: gpio@d4019100 {
+					reg = <0xd4019100 0x4>;
+				};
 			};
 			};
 
 
 			twsi1: i2c@d4011000 {
 			twsi1: i2c@d4011000 {
-				compatible = "mrvl,mmp-twsi", "mrvl,pxa-i2c";
+				compatible = "mrvl,mmp-twsi";
 				reg = <0xd4011000 0x1000>;
 				reg = <0xd4011000 0x1000>;
 				interrupts = <7>;
 				interrupts = <7>;
 				mrvl,i2c-fast-mode;
 				mrvl,i2c-fast-mode;
@@ -80,7 +115,7 @@
 			};
 			};
 
 
 			twsi2: i2c@d4025000 {
 			twsi2: i2c@d4025000 {
-				compatible = "mrvl,mmp-twsi", "mrvl,pxa-i2c";
+				compatible = "mrvl,mmp-twsi";
 				reg = <0xd4025000 0x1000>;
 				reg = <0xd4025000 0x1000>;
 				interrupts = <58>;
 				interrupts = <58>;
 				status = "disabled";
 				status = "disabled";

+ 38 - 0
arch/arm/boot/dts/pxa910-dkb.dts

@@ -0,0 +1,38 @@
+/*
+ *  Copyright (C) 2012 Marvell Technology Group Ltd.
+ *  Author: Haojian Zhuang <haojian.zhuang@marvell.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
+ *  publishhed by the Free Software Foundation.
+ */
+
+/dts-v1/;
+/include/ "pxa910.dtsi"
+
+/ {
+	model = "Marvell PXA910 DKB Development Board";
+	compatible = "mrvl,pxa910-dkb", "mrvl,pxa910";
+
+	chosen {
+		bootargs = "console=ttyS0,115200 root=/dev/nfs nfsroot=192.168.1.100:/nfsroot/ ip=192.168.1.101:192.168.1.100::255.255.255.0::eth0:on";
+	};
+
+	memory {
+		reg = <0x00000000 0x10000000>;
+	};
+
+	soc {
+		apb@d4000000 {
+			uart1: uart@d4017000 {
+				status = "okay";
+			};
+			twsi1: i2c@d4011000 {
+				status = "okay";
+			};
+			rtc: rtc@d4010000 {
+				status = "okay";
+			};
+		};
+	};
+};

+ 140 - 0
arch/arm/boot/dts/pxa910.dtsi

@@ -0,0 +1,140 @@
+/*
+ *  Copyright (C) 2012 Marvell Technology Group Ltd.
+ *  Author: Haojian Zhuang <haojian.zhuang@marvell.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
+ *  publishhed by the Free Software Foundation.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	aliases {
+		serial0 = &uart1;
+		serial1 = &uart2;
+		serial2 = &uart3;
+		i2c0 = &twsi1;
+		i2c1 = &twsi2;
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&intc>;
+		ranges;
+
+		axi@d4200000 {	/* AXI */
+			compatible = "mrvl,axi-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0xd4200000 0x00200000>;
+			ranges;
+
+			intc: interrupt-controller@d4282000 {
+				compatible = "mrvl,mmp-intc";
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				reg = <0xd4282000 0x1000>;
+				mrvl,intc-nr-irqs = <64>;
+			};
+
+		};
+
+		apb@d4000000 {	/* APB */
+			compatible = "mrvl,apb-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0xd4000000 0x00200000>;
+			ranges;
+
+			timer0: timer@d4014000 {
+				compatible = "mrvl,mmp-timer";
+				reg = <0xd4014000 0x100>;
+				interrupts = <13>;
+			};
+
+			timer1: timer@d4016000 {
+				compatible = "mrvl,mmp-timer";
+				reg = <0xd4016000 0x100>;
+				interrupts = <29>;
+				status = "disabled";
+			};
+
+			uart1: uart@d4017000 {
+				compatible = "mrvl,mmp-uart";
+				reg = <0xd4017000 0x1000>;
+				interrupts = <27>;
+				status = "disabled";
+			};
+
+			uart2: uart@d4018000 {
+				compatible = "mrvl,mmp-uart";
+				reg = <0xd4018000 0x1000>;
+				interrupts = <28>;
+				status = "disabled";
+			};
+
+			uart3: uart@d4036000 {
+				compatible = "mrvl,mmp-uart";
+				reg = <0xd4036000 0x1000>;
+				interrupts = <59>;
+				status = "disabled";
+			};
+
+			gpio@d4019000 {
+				compatible = "mrvl,mmp-gpio";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0xd4019000 0x1000>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupts = <49>;
+				interrupt-names = "gpio_mux";
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				ranges;
+
+				gcb0: gpio@d4019000 {
+					reg = <0xd4019000 0x4>;
+				};
+
+				gcb1: gpio@d4019004 {
+					reg = <0xd4019004 0x4>;
+				};
+
+				gcb2: gpio@d4019008 {
+					reg = <0xd4019008 0x4>;
+				};
+
+				gcb3: gpio@d4019100 {
+					reg = <0xd4019100 0x4>;
+				};
+			};
+
+			twsi1: i2c@d4011000 {
+				compatible = "mrvl,mmp-twsi";
+				reg = <0xd4011000 0x1000>;
+				interrupts = <7>;
+				mrvl,i2c-fast-mode;
+				status = "disabled";
+			};
+
+			twsi2: i2c@d4037000 {
+				compatible = "mrvl,mmp-twsi";
+				reg = <0xd4037000 0x1000>;
+				interrupts = <54>;
+				status = "disabled";
+			};
+
+			rtc: rtc@d4010000 {
+				compatible = "mrvl,mmp-rtc";
+				reg = <0xd4010000 0x1000>;
+				interrupts = <5 6>;
+				interrupt-names = "rtc 1Hz", "rtc alarm";
+				status = "disabled";
+			};
+		};
+	};
+};

+ 19 - 10
arch/arm/mach-mmp/Kconfig

@@ -2,16 +2,6 @@ if ARCH_MMP
 
 
 menu "Marvell PXA168/910/MMP2 Implmentations"
 menu "Marvell PXA168/910/MMP2 Implmentations"
 
 
-config MACH_MMP_DT
-	bool "Support MMP2 platforms from device tree"
-	select CPU_PXA168
-	select CPU_PXA910
-	select USE_OF
-	help
-	  Include support for Marvell MMP2 based platforms using
-	  the device tree. Needn't select any other machine while
-	  MACH_MMP_DT is enabled.
-
 config MACH_ASPENITE
 config MACH_ASPENITE
 	bool "Marvell's PXA168 Aspenite Development Board"
 	bool "Marvell's PXA168 Aspenite Development Board"
 	select CPU_PXA168
 	select CPU_PXA168
@@ -94,6 +84,25 @@ config MACH_GPLUGD
 	  Say 'Y' here if you want to support the Marvell PXA168-based
 	  Say 'Y' here if you want to support the Marvell PXA168-based
 	  GuruPlug Display (gplugD) Board
 	  GuruPlug Display (gplugD) Board
 
 
+config MACH_MMP_DT
+	bool "Support MMP (ARMv5) platforms from device tree"
+	select CPU_PXA168
+	select CPU_PXA910
+	select USE_OF
+	help
+	  Include support for Marvell MMP2 based platforms using
+	  the device tree. Needn't select any other machine while
+	  MACH_MMP_DT is enabled.
+
+config MACH_MMP2_DT
+	bool "Support MMP2 (ARMv7) platforms from device tree"
+	depends on !CPU_MOHAWK
+	select CPU_MMP2
+	select USE_OF
+	help
+	  Include support for Marvell MMP2 based platforms using
+	  the device tree.
+
 endmenu
 endmenu
 
 
 config CPU_PXA168
 config CPU_PXA168

+ 5 - 4
arch/arm/mach-mmp/Makefile

@@ -2,12 +2,12 @@
 # Makefile for Marvell's PXA168 processors line
 # Makefile for Marvell's PXA168 processors line
 #
 #
 
 
-obj-y				+= common.o clock.o devices.o time.o
+obj-y				+= common.o clock.o devices.o time.o irq.o
 
 
 # SoC support
 # SoC support
-obj-$(CONFIG_CPU_PXA168)	+= pxa168.o irq-pxa168.o
-obj-$(CONFIG_CPU_PXA910)	+= pxa910.o irq-pxa168.o
-obj-$(CONFIG_CPU_MMP2)		+= mmp2.o irq-mmp2.o sram.o
+obj-$(CONFIG_CPU_PXA168)	+= pxa168.o
+obj-$(CONFIG_CPU_PXA910)	+= pxa910.o
+obj-$(CONFIG_CPU_MMP2)		+= mmp2.o sram.o
 
 
 # board support
 # board support
 obj-$(CONFIG_MACH_ASPENITE)	+= aspenite.o
 obj-$(CONFIG_MACH_ASPENITE)	+= aspenite.o
@@ -19,5 +19,6 @@ obj-$(CONFIG_MACH_BROWNSTONE)	+= brownstone.o
 obj-$(CONFIG_MACH_FLINT)	+= flint.o
 obj-$(CONFIG_MACH_FLINT)	+= flint.o
 obj-$(CONFIG_MACH_MARVELL_JASPER) += jasper.o
 obj-$(CONFIG_MACH_MARVELL_JASPER) += jasper.o
 obj-$(CONFIG_MACH_MMP_DT)	+= mmp-dt.o
 obj-$(CONFIG_MACH_MMP_DT)	+= mmp-dt.o
+obj-$(CONFIG_MACH_MMP2_DT)	+= mmp2-dt.o
 obj-$(CONFIG_MACH_TETON_BGA)	+= teton_bga.o
 obj-$(CONFIG_MACH_TETON_BGA)	+= teton_bga.o
 obj-$(CONFIG_MACH_GPLUGD)	+= gplugd.o
 obj-$(CONFIG_MACH_GPLUGD)	+= gplugd.o

+ 3 - 1
arch/arm/mach-mmp/include/mach/entry-macro.S

@@ -6,13 +6,15 @@
  * published by the Free Software Foundation.
  * published by the Free Software Foundation.
  */
  */
 
 
+#include <asm/irq.h>
 #include <mach/regs-icu.h>
 #include <mach/regs-icu.h>
 
 
 	.macro	get_irqnr_preamble, base, tmp
 	.macro	get_irqnr_preamble, base, tmp
 	mrc	p15, 0, \tmp, c0, c0, 0		@ CPUID
 	mrc	p15, 0, \tmp, c0, c0, 0		@ CPUID
 	and	\tmp, \tmp, #0xff00
 	and	\tmp, \tmp, #0xff00
 	cmp	\tmp, #0x5800
 	cmp	\tmp, #0x5800
-	ldr	\base, =ICU_VIRT_BASE
+	ldr	\base, =mmp_icu_base
+	ldr	\base, [\base, #0]
 	addne	\base, \base, #0x10c		@ PJ1 AP INT SEL register
 	addne	\base, \base, #0x10c		@ PJ1 AP INT SEL register
 	addeq	\base, \base, #0x104		@ PJ4 IRQ SEL register
 	addeq	\base, \base, #0x104		@ PJ4 IRQ SEL register
 	.endm
 	.endm

+ 19 - 8
arch/arm/mach-mmp/include/mach/irqs.h

@@ -125,7 +125,7 @@
 #define IRQ_MMP2_RTC_MUX		5
 #define IRQ_MMP2_RTC_MUX		5
 #define IRQ_MMP2_TWSI1			7
 #define IRQ_MMP2_TWSI1			7
 #define IRQ_MMP2_GPU			8
 #define IRQ_MMP2_GPU			8
-#define IRQ_MMP2_KEYPAD			9
+#define IRQ_MMP2_KEYPAD_MUX		9
 #define IRQ_MMP2_ROTARY			10
 #define IRQ_MMP2_ROTARY			10
 #define IRQ_MMP2_TRACKBALL		11
 #define IRQ_MMP2_TRACKBALL		11
 #define IRQ_MMP2_ONEWIRE		12
 #define IRQ_MMP2_ONEWIRE		12
@@ -163,11 +163,11 @@
 #define IRQ_MMP2_DMA_FIQ		47
 #define IRQ_MMP2_DMA_FIQ		47
 #define IRQ_MMP2_DMA_RIQ		48
 #define IRQ_MMP2_DMA_RIQ		48
 #define IRQ_MMP2_GPIO			49
 #define IRQ_MMP2_GPIO			49
-#define IRQ_MMP2_SSP_MUX		51
+#define IRQ_MMP2_MIPI_HSI1_MUX		51
 #define IRQ_MMP2_MMC2			52
 #define IRQ_MMP2_MMC2			52
 #define IRQ_MMP2_MMC3			53
 #define IRQ_MMP2_MMC3			53
 #define IRQ_MMP2_MMC4			54
 #define IRQ_MMP2_MMC4			54
-#define IRQ_MMP2_MIPI_HSI		55
+#define IRQ_MMP2_MIPI_HSI0_MUX		55
 #define IRQ_MMP2_MSP			58
 #define IRQ_MMP2_MSP			58
 #define IRQ_MMP2_MIPI_SLIM_DMA		59
 #define IRQ_MMP2_MIPI_SLIM_DMA		59
 #define IRQ_MMP2_PJ4_FREQ_CHG		60
 #define IRQ_MMP2_PJ4_FREQ_CHG		60
@@ -186,8 +186,14 @@
 #define IRQ_MMP2_RTC_ALARM		(IRQ_MMP2_RTC_BASE + 0)
 #define IRQ_MMP2_RTC_ALARM		(IRQ_MMP2_RTC_BASE + 0)
 #define IRQ_MMP2_RTC			(IRQ_MMP2_RTC_BASE + 1)
 #define IRQ_MMP2_RTC			(IRQ_MMP2_RTC_BASE + 1)
 
 
+/* secondary interrupt of INT #9 */
+#define IRQ_MMP2_KEYPAD_BASE		(IRQ_MMP2_RTC_BASE + 2)
+#define IRQ_MMP2_KPC			(IRQ_MMP2_KEYPAD_BASE + 0)
+#define IRQ_MMP2_ROTORY			(IRQ_MMP2_KEYPAD_BASE + 1)
+#define IRQ_MMP2_TBALL			(IRQ_MMP2_KEYPAD_BASE + 2)
+
 /* secondary interrupt of INT #17 */
 /* secondary interrupt of INT #17 */
-#define IRQ_MMP2_TWSI_BASE		(IRQ_MMP2_RTC_BASE + 2)
+#define IRQ_MMP2_TWSI_BASE		(IRQ_MMP2_KEYPAD_BASE + 3)
 #define IRQ_MMP2_TWSI2			(IRQ_MMP2_TWSI_BASE + 0)
 #define IRQ_MMP2_TWSI2			(IRQ_MMP2_TWSI_BASE + 0)
 #define IRQ_MMP2_TWSI3			(IRQ_MMP2_TWSI_BASE + 1)
 #define IRQ_MMP2_TWSI3			(IRQ_MMP2_TWSI_BASE + 1)
 #define IRQ_MMP2_TWSI4			(IRQ_MMP2_TWSI_BASE + 2)
 #define IRQ_MMP2_TWSI4			(IRQ_MMP2_TWSI_BASE + 2)
@@ -212,11 +218,16 @@
 #define IRQ_MMP2_COMMRX			(IRQ_MMP2_MISC_BASE + 14)
 #define IRQ_MMP2_COMMRX			(IRQ_MMP2_MISC_BASE + 14)
 
 
 /* secondary interrupt of INT #51 */
 /* secondary interrupt of INT #51 */
-#define IRQ_MMP2_SSP_BASE		(IRQ_MMP2_MISC_BASE + 15)
-#define IRQ_MMP2_SSP1_SRDY		(IRQ_MMP2_SSP_BASE + 0)
-#define IRQ_MMP2_SSP3_SRDY		(IRQ_MMP2_SSP_BASE + 1)
+#define IRQ_MMP2_MIPI_HSI1_BASE		(IRQ_MMP2_MISC_BASE + 15)
+#define IRQ_MMP2_HSI1_CAWAKE		(IRQ_MMP2_MIPI_HSI1_BASE + 0)
+#define IRQ_MMP2_MIPI_HSI_INT1		(IRQ_MMP2_MIPI_HSI1_BASE + 1)
+
+/* secondary interrupt of INT #55 */
+#define IRQ_MMP2_MIPI_HSI0_BASE		(IRQ_MMP2_MIPI_HSI1_BASE + 2)
+#define IRQ_MMP2_HSI0_CAWAKE		(IRQ_MMP2_MIPI_HSI0_BASE + 0)
+#define IRQ_MMP2_MIPI_HSI_INT0		(IRQ_MMP2_MIPI_HSI0_BASE + 1)
 
 
-#define IRQ_MMP2_MUX_END		(IRQ_MMP2_SSP_BASE + 2)
+#define IRQ_MMP2_MUX_END		(IRQ_MMP2_MIPI_HSI0_BASE + 2)
 
 
 #define IRQ_GPIO_START			128
 #define IRQ_GPIO_START			128
 #define MMP_NR_BUILTIN_GPIO		192
 #define MMP_NR_BUILTIN_GPIO		192

+ 0 - 158
arch/arm/mach-mmp/irq-mmp2.c

@@ -1,158 +0,0 @@
-/*
- *  linux/arch/arm/mach-mmp/irq-mmp2.c
- *
- *  Generic IRQ handling, GPIO IRQ demultiplexing, etc.
- *
- *  Author:	Haojian Zhuang <haojian.zhuang@marvell.com>
- *  Copyright:	Marvell International Ltd.
- *
- *  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/init.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include <mach/irqs.h>
-#include <mach/regs-icu.h>
-#include <mach/mmp2.h>
-
-#include "common.h"
-
-static void icu_mask_irq(struct irq_data *d)
-{
-	uint32_t r = __raw_readl(ICU_INT_CONF(d->irq));
-
-	r &= ~ICU_INT_ROUTE_PJ4_IRQ;
-	__raw_writel(r, ICU_INT_CONF(d->irq));
-}
-
-static void icu_unmask_irq(struct irq_data *d)
-{
-	uint32_t r = __raw_readl(ICU_INT_CONF(d->irq));
-
-	r |= ICU_INT_ROUTE_PJ4_IRQ;
-	__raw_writel(r, ICU_INT_CONF(d->irq));
-}
-
-static struct irq_chip icu_irq_chip = {
-	.name		= "icu_irq",
-	.irq_mask	= icu_mask_irq,
-	.irq_mask_ack	= icu_mask_irq,
-	.irq_unmask	= icu_unmask_irq,
-};
-
-static void pmic_irq_ack(struct irq_data *d)
-{
-	if (d->irq == IRQ_MMP2_PMIC)
-		mmp2_clear_pmic_int();
-}
-
-#define SECOND_IRQ_MASK(_name_, irq_base, prefix)			\
-static void _name_##_mask_irq(struct irq_data *d)			\
-{									\
-	uint32_t r;							\
-	r = __raw_readl(prefix##_MASK) | (1 << (d->irq - irq_base));	\
-	__raw_writel(r, prefix##_MASK);					\
-}
-
-#define SECOND_IRQ_UNMASK(_name_, irq_base, prefix)			\
-static void _name_##_unmask_irq(struct irq_data *d)			\
-{									\
-	uint32_t r;							\
-	r = __raw_readl(prefix##_MASK) & ~(1 << (d->irq - irq_base));	\
-	__raw_writel(r, prefix##_MASK);					\
-}
-
-#define SECOND_IRQ_DEMUX(_name_, irq_base, prefix)			\
-static void _name_##_irq_demux(unsigned int irq, struct irq_desc *desc)	\
-{									\
-	unsigned long status, mask, n;					\
-	mask = __raw_readl(prefix##_MASK);				\
-	while (1) {							\
-		status = __raw_readl(prefix##_STATUS) & ~mask;		\
-		if (status == 0)					\
-			break;						\
-		n = find_first_bit(&status, BITS_PER_LONG);		\
-		while (n < BITS_PER_LONG) {				\
-			generic_handle_irq(irq_base + n);		\
-			n = find_next_bit(&status, BITS_PER_LONG, n+1);	\
-		}							\
-	}								\
-}
-
-#define SECOND_IRQ_CHIP(_name_, irq_base, prefix)			\
-SECOND_IRQ_MASK(_name_, irq_base, prefix)				\
-SECOND_IRQ_UNMASK(_name_, irq_base, prefix)				\
-SECOND_IRQ_DEMUX(_name_, irq_base, prefix)				\
-static struct irq_chip _name_##_irq_chip = {				\
-	.name		= #_name_,					\
-	.irq_mask	= _name_##_mask_irq,				\
-	.irq_unmask	= _name_##_unmask_irq,				\
-}
-
-SECOND_IRQ_CHIP(pmic, IRQ_MMP2_PMIC_BASE, MMP2_ICU_INT4);
-SECOND_IRQ_CHIP(rtc,  IRQ_MMP2_RTC_BASE,  MMP2_ICU_INT5);
-SECOND_IRQ_CHIP(twsi, IRQ_MMP2_TWSI_BASE, MMP2_ICU_INT17);
-SECOND_IRQ_CHIP(misc, IRQ_MMP2_MISC_BASE, MMP2_ICU_INT35);
-SECOND_IRQ_CHIP(ssp,  IRQ_MMP2_SSP_BASE,  MMP2_ICU_INT51);
-
-static void init_mux_irq(struct irq_chip *chip, int start, int num)
-{
-	int irq;
-
-	for (irq = start; num > 0; irq++, num--) {
-		struct irq_data *d = irq_get_irq_data(irq);
-
-		/* mask and clear the IRQ */
-		chip->irq_mask(d);
-		if (chip->irq_ack)
-			chip->irq_ack(d);
-
-		irq_set_chip(irq, chip);
-		set_irq_flags(irq, IRQF_VALID);
-		irq_set_handler(irq, handle_level_irq);
-	}
-}
-
-void __init mmp2_init_icu(void)
-{
-	int irq;
-
-	for (irq = 0; irq < IRQ_MMP2_MUX_BASE; irq++) {
-		icu_mask_irq(irq_get_irq_data(irq));
-		irq_set_chip(irq, &icu_irq_chip);
-		set_irq_flags(irq, IRQF_VALID);
-
-		switch (irq) {
-		case IRQ_MMP2_PMIC_MUX:
-		case IRQ_MMP2_RTC_MUX:
-		case IRQ_MMP2_TWSI_MUX:
-		case IRQ_MMP2_MISC_MUX:
-		case IRQ_MMP2_SSP_MUX:
-			break;
-		default:
-			irq_set_handler(irq, handle_level_irq);
-			break;
-		}
-	}
-
-	/* NOTE: IRQ_MMP2_PMIC requires the PMIC MFPR register
-	 * to be written to clear the interrupt
-	 */
-	pmic_irq_chip.irq_ack = pmic_irq_ack;
-
-	init_mux_irq(&pmic_irq_chip, IRQ_MMP2_PMIC_BASE, 2);
-	init_mux_irq(&rtc_irq_chip, IRQ_MMP2_RTC_BASE, 2);
-	init_mux_irq(&twsi_irq_chip, IRQ_MMP2_TWSI_BASE, 5);
-	init_mux_irq(&misc_irq_chip, IRQ_MMP2_MISC_BASE, 15);
-	init_mux_irq(&ssp_irq_chip, IRQ_MMP2_SSP_BASE, 2);
-
-	irq_set_chained_handler(IRQ_MMP2_PMIC_MUX, pmic_irq_demux);
-	irq_set_chained_handler(IRQ_MMP2_RTC_MUX, rtc_irq_demux);
-	irq_set_chained_handler(IRQ_MMP2_TWSI_MUX, twsi_irq_demux);
-	irq_set_chained_handler(IRQ_MMP2_MISC_MUX, misc_irq_demux);
-	irq_set_chained_handler(IRQ_MMP2_SSP_MUX, ssp_irq_demux);
-}

+ 0 - 54
arch/arm/mach-mmp/irq-pxa168.c

@@ -1,54 +0,0 @@
-/*
- *  linux/arch/arm/mach-mmp/irq.c
- *
- *  Generic IRQ handling, GPIO IRQ demultiplexing, etc.
- *
- *  Author:	Bin Yang <bin.yang@marvell.com>
- *  Created:	Sep 30, 2008
- *  Copyright:	Marvell International Ltd.
- *
- *  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/init.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include <mach/regs-icu.h>
-
-#include "common.h"
-
-#define IRQ_ROUTE_TO_AP		(ICU_INT_CONF_AP_INT | ICU_INT_CONF_IRQ)
-
-#define PRIORITY_DEFAULT	0x1
-#define PRIORITY_NONE		0x0	/* means IRQ disabled */
-
-static void icu_mask_irq(struct irq_data *d)
-{
-	__raw_writel(PRIORITY_NONE, ICU_INT_CONF(d->irq));
-}
-
-static void icu_unmask_irq(struct irq_data *d)
-{
-	__raw_writel(IRQ_ROUTE_TO_AP | PRIORITY_DEFAULT, ICU_INT_CONF(d->irq));
-}
-
-static struct irq_chip icu_irq_chip = {
-	.name		= "icu_irq",
-	.irq_ack	= icu_mask_irq,
-	.irq_mask	= icu_mask_irq,
-	.irq_unmask	= icu_unmask_irq,
-};
-
-void __init icu_init_irq(void)
-{
-	int irq;
-
-	for (irq = 0; irq < 64; irq++) {
-		icu_mask_irq(irq_get_irq_data(irq));
-		irq_set_chip_and_handler(irq, &icu_irq_chip, handle_level_irq);
-		set_irq_flags(irq, IRQF_VALID);
-	}
-}

+ 445 - 0
arch/arm/mach-mmp/irq.c

@@ -0,0 +1,445 @@
+/*
+ *  linux/arch/arm/mach-mmp/irq.c
+ *
+ *  Generic IRQ handling, GPIO IRQ demultiplexing, etc.
+ *  Copyright (C) 2008 - 2012 Marvell Technology Group Ltd.
+ *
+ *  Author:	Bin Yang <bin.yang@marvell.com>
+ *              Haojian Zhuang <haojian.zhuang@gmail.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/module.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <mach/irqs.h>
+
+#include "common.h"
+
+#define MAX_ICU_NR		16
+
+struct icu_chip_data {
+	int			nr_irqs;
+	unsigned int		virq_base;
+	unsigned int		cascade_irq;
+	void __iomem		*reg_status;
+	void __iomem		*reg_mask;
+	unsigned int		conf_enable;
+	unsigned int		conf_disable;
+	unsigned int		conf_mask;
+	unsigned int		clr_mfp_irq_base;
+	unsigned int		clr_mfp_hwirq;
+	struct irq_domain	*domain;
+};
+
+struct mmp_intc_conf {
+	unsigned int	conf_enable;
+	unsigned int	conf_disable;
+	unsigned int	conf_mask;
+};
+
+void __iomem *mmp_icu_base;
+static struct icu_chip_data icu_data[MAX_ICU_NR];
+static int max_icu_nr;
+
+extern void mmp2_clear_pmic_int(void);
+
+static void icu_mask_ack_irq(struct irq_data *d)
+{
+	struct irq_domain *domain = d->domain;
+	struct icu_chip_data *data = (struct icu_chip_data *)domain->host_data;
+	int hwirq;
+	u32 r;
+
+	hwirq = d->irq - data->virq_base;
+	if (data == &icu_data[0]) {
+		r = readl_relaxed(mmp_icu_base + (hwirq << 2));
+		r &= ~data->conf_mask;
+		r |= data->conf_disable;
+		writel_relaxed(r, mmp_icu_base + (hwirq << 2));
+	} else {
+#ifdef CONFIG_CPU_MMP2
+		if ((data->virq_base == data->clr_mfp_irq_base)
+			&& (hwirq == data->clr_mfp_hwirq))
+			mmp2_clear_pmic_int();
+#endif
+		r = readl_relaxed(data->reg_mask) | (1 << hwirq);
+		writel_relaxed(r, data->reg_mask);
+	}
+}
+
+static void icu_mask_irq(struct irq_data *d)
+{
+	struct irq_domain *domain = d->domain;
+	struct icu_chip_data *data = (struct icu_chip_data *)domain->host_data;
+	int hwirq;
+	u32 r;
+
+	hwirq = d->irq - data->virq_base;
+	if (data == &icu_data[0]) {
+		r = readl_relaxed(mmp_icu_base + (hwirq << 2));
+		r &= ~data->conf_mask;
+		r |= data->conf_disable;
+		writel_relaxed(r, mmp_icu_base + (hwirq << 2));
+	} else {
+		r = readl_relaxed(data->reg_mask) | (1 << hwirq);
+		writel_relaxed(r, data->reg_mask);
+	}
+}
+
+static void icu_unmask_irq(struct irq_data *d)
+{
+	struct irq_domain *domain = d->domain;
+	struct icu_chip_data *data = (struct icu_chip_data *)domain->host_data;
+	int hwirq;
+	u32 r;
+
+	hwirq = d->irq - data->virq_base;
+	if (data == &icu_data[0]) {
+		r = readl_relaxed(mmp_icu_base + (hwirq << 2));
+		r &= ~data->conf_mask;
+		r |= data->conf_enable;
+		writel_relaxed(r, mmp_icu_base + (hwirq << 2));
+	} else {
+		r = readl_relaxed(data->reg_mask) & ~(1 << hwirq);
+		writel_relaxed(r, data->reg_mask);
+	}
+}
+
+static struct irq_chip icu_irq_chip = {
+	.name		= "icu_irq",
+	.irq_mask	= icu_mask_irq,
+	.irq_mask_ack	= icu_mask_ack_irq,
+	.irq_unmask	= icu_unmask_irq,
+};
+
+static void icu_mux_irq_demux(unsigned int irq, struct irq_desc *desc)
+{
+	struct irq_domain *domain;
+	struct icu_chip_data *data;
+	int i;
+	unsigned long mask, status, n;
+
+	for (i = 1; i < max_icu_nr; i++) {
+		if (irq == icu_data[i].cascade_irq) {
+			domain = icu_data[i].domain;
+			data = (struct icu_chip_data *)domain->host_data;
+			break;
+		}
+	}
+	if (i >= max_icu_nr) {
+		pr_err("Spurious irq %d in MMP INTC\n", irq);
+		return;
+	}
+
+	mask = readl_relaxed(data->reg_mask);
+	while (1) {
+		status = readl_relaxed(data->reg_status) & ~mask;
+		if (status == 0)
+			break;
+		n = find_first_bit(&status, BITS_PER_LONG);
+		while (n < BITS_PER_LONG) {
+			generic_handle_irq(icu_data[i].virq_base + n);
+			n = find_next_bit(&status, BITS_PER_LONG, n + 1);
+		}
+	}
+}
+
+static int mmp_irq_domain_map(struct irq_domain *d, unsigned int irq,
+			      irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(irq, &icu_irq_chip, handle_level_irq);
+	set_irq_flags(irq, IRQF_VALID);
+	return 0;
+}
+
+static int mmp_irq_domain_xlate(struct irq_domain *d, struct device_node *node,
+				const u32 *intspec, unsigned int intsize,
+				unsigned long *out_hwirq,
+				unsigned int *out_type)
+{
+	*out_hwirq = intspec[0];
+	return 0;
+}
+
+const struct irq_domain_ops mmp_irq_domain_ops = {
+	.map		= mmp_irq_domain_map,
+	.xlate		= mmp_irq_domain_xlate,
+};
+
+static struct mmp_intc_conf mmp_conf = {
+	.conf_enable	= 0x51,
+	.conf_disable	= 0x0,
+	.conf_mask	= 0x7f,
+};
+
+static struct mmp_intc_conf mmp2_conf = {
+	.conf_enable	= 0x20,
+	.conf_disable	= 0x0,
+	.conf_mask	= 0x7f,
+};
+
+/* MMP (ARMv5) */
+void __init icu_init_irq(void)
+{
+	int irq;
+
+	max_icu_nr = 1;
+	mmp_icu_base = ioremap(0xd4282000, 0x1000);
+	icu_data[0].conf_enable = mmp_conf.conf_enable;
+	icu_data[0].conf_disable = mmp_conf.conf_disable;
+	icu_data[0].conf_mask = mmp_conf.conf_mask;
+	icu_data[0].nr_irqs = 64;
+	icu_data[0].virq_base = 0;
+	icu_data[0].domain = irq_domain_add_legacy(NULL, 64, 0, 0,
+						   &irq_domain_simple_ops,
+						   &icu_data[0]);
+	for (irq = 0; irq < 64; irq++) {
+		icu_mask_irq(irq_get_irq_data(irq));
+		irq_set_chip_and_handler(irq, &icu_irq_chip, handle_level_irq);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+	irq_set_default_host(icu_data[0].domain);
+}
+
+/* MMP2 (ARMv7) */
+void __init mmp2_init_icu(void)
+{
+	int irq;
+
+	max_icu_nr = 8;
+	mmp_icu_base = ioremap(0xd4282000, 0x1000);
+	icu_data[0].conf_enable = mmp2_conf.conf_enable;
+	icu_data[0].conf_disable = mmp2_conf.conf_disable;
+	icu_data[0].conf_mask = mmp2_conf.conf_mask;
+	icu_data[0].nr_irqs = 64;
+	icu_data[0].virq_base = 0;
+	icu_data[0].domain = irq_domain_add_legacy(NULL, 64, 0, 0,
+						   &irq_domain_simple_ops,
+						   &icu_data[0]);
+	icu_data[1].reg_status = mmp_icu_base + 0x150;
+	icu_data[1].reg_mask = mmp_icu_base + 0x168;
+	icu_data[1].clr_mfp_irq_base = IRQ_MMP2_PMIC_BASE;
+	icu_data[1].clr_mfp_hwirq = IRQ_MMP2_PMIC - IRQ_MMP2_PMIC_BASE;
+	icu_data[1].nr_irqs = 2;
+	icu_data[1].virq_base = IRQ_MMP2_PMIC_BASE;
+	icu_data[1].domain = irq_domain_add_legacy(NULL, icu_data[1].nr_irqs,
+						   icu_data[1].virq_base, 0,
+						   &irq_domain_simple_ops,
+						   &icu_data[1]);
+	icu_data[2].reg_status = mmp_icu_base + 0x154;
+	icu_data[2].reg_mask = mmp_icu_base + 0x16c;
+	icu_data[2].nr_irqs = 2;
+	icu_data[2].virq_base = IRQ_MMP2_RTC_BASE;
+	icu_data[2].domain = irq_domain_add_legacy(NULL, icu_data[2].nr_irqs,
+						   icu_data[2].virq_base, 0,
+						   &irq_domain_simple_ops,
+						   &icu_data[2]);
+	icu_data[3].reg_status = mmp_icu_base + 0x180;
+	icu_data[3].reg_mask = mmp_icu_base + 0x17c;
+	icu_data[3].nr_irqs = 3;
+	icu_data[3].virq_base = IRQ_MMP2_KEYPAD_BASE;
+	icu_data[3].domain = irq_domain_add_legacy(NULL, icu_data[3].nr_irqs,
+						   icu_data[3].virq_base, 0,
+						   &irq_domain_simple_ops,
+						   &icu_data[3]);
+	icu_data[4].reg_status = mmp_icu_base + 0x158;
+	icu_data[4].reg_mask = mmp_icu_base + 0x170;
+	icu_data[4].nr_irqs = 5;
+	icu_data[4].virq_base = IRQ_MMP2_TWSI_BASE;
+	icu_data[4].domain = irq_domain_add_legacy(NULL, icu_data[4].nr_irqs,
+						   icu_data[4].virq_base, 0,
+						   &irq_domain_simple_ops,
+						   &icu_data[4]);
+	icu_data[5].reg_status = mmp_icu_base + 0x15c;
+	icu_data[5].reg_mask = mmp_icu_base + 0x174;
+	icu_data[5].nr_irqs = 15;
+	icu_data[5].virq_base = IRQ_MMP2_MISC_BASE;
+	icu_data[5].domain = irq_domain_add_legacy(NULL, icu_data[5].nr_irqs,
+						   icu_data[5].virq_base, 0,
+						   &irq_domain_simple_ops,
+						   &icu_data[5]);
+	icu_data[6].reg_status = mmp_icu_base + 0x160;
+	icu_data[6].reg_mask = mmp_icu_base + 0x178;
+	icu_data[6].nr_irqs = 2;
+	icu_data[6].virq_base = IRQ_MMP2_MIPI_HSI1_BASE;
+	icu_data[6].domain = irq_domain_add_legacy(NULL, icu_data[6].nr_irqs,
+						   icu_data[6].virq_base, 0,
+						   &irq_domain_simple_ops,
+						   &icu_data[6]);
+	icu_data[7].reg_status = mmp_icu_base + 0x188;
+	icu_data[7].reg_mask = mmp_icu_base + 0x184;
+	icu_data[7].nr_irqs = 2;
+	icu_data[7].virq_base = IRQ_MMP2_MIPI_HSI0_BASE;
+	icu_data[7].domain = irq_domain_add_legacy(NULL, icu_data[7].nr_irqs,
+						   icu_data[7].virq_base, 0,
+						   &irq_domain_simple_ops,
+						   &icu_data[7]);
+	for (irq = 0; irq < IRQ_MMP2_MUX_END; irq++) {
+		icu_mask_irq(irq_get_irq_data(irq));
+		switch (irq) {
+		case IRQ_MMP2_PMIC_MUX:
+		case IRQ_MMP2_RTC_MUX:
+		case IRQ_MMP2_KEYPAD_MUX:
+		case IRQ_MMP2_TWSI_MUX:
+		case IRQ_MMP2_MISC_MUX:
+		case IRQ_MMP2_MIPI_HSI1_MUX:
+		case IRQ_MMP2_MIPI_HSI0_MUX:
+			irq_set_chip(irq, &icu_irq_chip);
+			irq_set_chained_handler(irq, icu_mux_irq_demux);
+			break;
+		default:
+			irq_set_chip_and_handler(irq, &icu_irq_chip,
+						 handle_level_irq);
+			break;
+		}
+		set_irq_flags(irq, IRQF_VALID);
+	}
+	irq_set_default_host(icu_data[0].domain);
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id intc_ids[] __initconst = {
+	{ .compatible = "mrvl,mmp-intc", .data = &mmp_conf },
+	{ .compatible = "mrvl,mmp2-intc", .data = &mmp2_conf },
+	{}
+};
+
+static const struct of_device_id mmp_mux_irq_match[] __initconst = {
+	{ .compatible = "mrvl,mmp2-mux-intc" },
+	{}
+};
+
+int __init mmp2_mux_init(struct device_node *parent)
+{
+	struct device_node *node;
+	const struct of_device_id *of_id;
+	struct resource res;
+	int i, irq_base, ret, irq;
+	u32 nr_irqs, mfp_irq;
+
+	node = parent;
+	max_icu_nr = 1;
+	for (i = 1; i < MAX_ICU_NR; i++) {
+		node = of_find_matching_node(node, mmp_mux_irq_match);
+		if (!node)
+			break;
+		of_id = of_match_node(&mmp_mux_irq_match[0], node);
+		ret = of_property_read_u32(node, "mrvl,intc-nr-irqs",
+					   &nr_irqs);
+		if (ret) {
+			pr_err("Not found mrvl,intc-nr-irqs property\n");
+			ret = -EINVAL;
+			goto err;
+		}
+		ret = of_address_to_resource(node, 0, &res);
+		if (ret < 0) {
+			pr_err("Not found reg property\n");
+			ret = -EINVAL;
+			goto err;
+		}
+		icu_data[i].reg_status = mmp_icu_base + res.start;
+		ret = of_address_to_resource(node, 1, &res);
+		if (ret < 0) {
+			pr_err("Not found reg property\n");
+			ret = -EINVAL;
+			goto err;
+		}
+		icu_data[i].reg_mask = mmp_icu_base + res.start;
+		icu_data[i].cascade_irq = irq_of_parse_and_map(node, 0);
+		if (!icu_data[i].cascade_irq) {
+			ret = -EINVAL;
+			goto err;
+		}
+
+		irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0);
+		if (irq_base < 0) {
+			pr_err("Failed to allocate IRQ numbers for mux intc\n");
+			ret = irq_base;
+			goto err;
+		}
+		if (!of_property_read_u32(node, "mrvl,clr-mfp-irq",
+					  &mfp_irq)) {
+			icu_data[i].clr_mfp_irq_base = irq_base;
+			icu_data[i].clr_mfp_hwirq = mfp_irq;
+		}
+		irq_set_chained_handler(icu_data[i].cascade_irq,
+					icu_mux_irq_demux);
+		icu_data[i].nr_irqs = nr_irqs;
+		icu_data[i].virq_base = irq_base;
+		icu_data[i].domain = irq_domain_add_legacy(node, nr_irqs,
+							   irq_base, 0,
+							   &mmp_irq_domain_ops,
+							   &icu_data[i]);
+		for (irq = irq_base; irq < irq_base + nr_irqs; irq++)
+			icu_mask_irq(irq_get_irq_data(irq));
+	}
+	max_icu_nr = i;
+	return 0;
+err:
+	of_node_put(node);
+	max_icu_nr = i;
+	return ret;
+}
+
+void __init mmp_dt_irq_init(void)
+{
+	struct device_node *node;
+	const struct of_device_id *of_id;
+	struct mmp_intc_conf *conf;
+	int nr_irqs, irq_base, ret, irq;
+
+	node = of_find_matching_node(NULL, intc_ids);
+	if (!node) {
+		pr_err("Failed to find interrupt controller in arch-mmp\n");
+		return;
+	}
+	of_id = of_match_node(intc_ids, node);
+	conf = of_id->data;
+
+	ret = of_property_read_u32(node, "mrvl,intc-nr-irqs", &nr_irqs);
+	if (ret) {
+		pr_err("Not found mrvl,intc-nr-irqs property\n");
+		return;
+	}
+
+	mmp_icu_base = of_iomap(node, 0);
+	if (!mmp_icu_base) {
+		pr_err("Failed to get interrupt controller register\n");
+		return;
+	}
+
+	irq_base = irq_alloc_descs(-1, 0, nr_irqs - NR_IRQS_LEGACY, 0);
+	if (irq_base < 0) {
+		pr_err("Failed to allocate IRQ numbers\n");
+		goto err;
+	} else if (irq_base != NR_IRQS_LEGACY) {
+		pr_err("ICU's irqbase should be started from 0\n");
+		goto err;
+	}
+	icu_data[0].conf_enable = conf->conf_enable;
+	icu_data[0].conf_disable = conf->conf_disable;
+	icu_data[0].conf_mask = conf->conf_mask;
+	icu_data[0].nr_irqs = nr_irqs;
+	icu_data[0].virq_base = 0;
+	icu_data[0].domain = irq_domain_add_legacy(node, nr_irqs, 0, 0,
+						   &mmp_irq_domain_ops,
+						   &icu_data[0]);
+	irq_set_default_host(icu_data[0].domain);
+	for (irq = 0; irq < nr_irqs; irq++)
+		icu_mask_irq(irq_get_irq_data(irq));
+	mmp2_mux_init(node);
+	return;
+err:
+	iounmap(mmp_icu_base);
+}
+#endif

+ 37 - 29
arch/arm/mach-mmp/mmp-dt.c

@@ -14,14 +14,19 @@
 #include <linux/of_irq.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/of_platform.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/arch.h>
+#include <asm/mach/time.h>
 #include <mach/irqs.h>
 #include <mach/irqs.h>
 
 
 #include "common.h"
 #include "common.h"
 
 
-extern struct sys_timer pxa168_timer;
-extern void __init icu_init_irq(void);
+extern void __init mmp_dt_irq_init(void);
+extern void __init mmp_dt_init_timer(void);
 
 
-static const struct of_dev_auxdata mmp_auxdata_lookup[] __initconst = {
+static struct sys_timer mmp_dt_timer = {
+	.init	= mmp_dt_init_timer,
+};
+
+static const struct of_dev_auxdata pxa168_auxdata_lookup[] __initconst = {
 	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4017000, "pxa2xx-uart.0", NULL),
 	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4017000, "pxa2xx-uart.0", NULL),
 	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4018000, "pxa2xx-uart.1", NULL),
 	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4018000, "pxa2xx-uart.1", NULL),
 	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4026000, "pxa2xx-uart.2", NULL),
 	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4026000, "pxa2xx-uart.2", NULL),
@@ -32,44 +37,47 @@ static const struct of_dev_auxdata mmp_auxdata_lookup[] __initconst = {
 	{}
 	{}
 };
 };
 
 
-static int __init mmp_intc_add_irq_domain(struct device_node *np,
-					   struct device_node *parent)
-{
-	irq_domain_add_simple(np, 0);
-	return 0;
-}
-
-static int __init mmp_gpio_add_irq_domain(struct device_node *np,
-					   struct device_node *parent)
-{
-	irq_domain_add_simple(np, IRQ_GPIO_START);
-	return 0;
-}
-
-static const struct of_device_id mmp_irq_match[] __initconst = {
-	{ .compatible = "mrvl,mmp-intc", .data = mmp_intc_add_irq_domain, },
-	{ .compatible = "mrvl,mmp-gpio", .data = mmp_gpio_add_irq_domain, },
+static const struct of_dev_auxdata pxa910_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4017000, "pxa2xx-uart.0", NULL),
+	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4018000, "pxa2xx-uart.1", NULL),
+	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4036000, "pxa2xx-uart.2", NULL),
+	OF_DEV_AUXDATA("mrvl,mmp-twsi", 0xd4011000, "pxa2xx-i2c.0", NULL),
+	OF_DEV_AUXDATA("mrvl,mmp-twsi", 0xd4037000, "pxa2xx-i2c.1", NULL),
+	OF_DEV_AUXDATA("mrvl,mmp-gpio", 0xd4019000, "pxa-gpio", NULL),
+	OF_DEV_AUXDATA("mrvl,mmp-rtc", 0xd4010000, "sa1100-rtc", NULL),
 	{}
 	{}
 };
 };
 
 
-static void __init mmp_dt_init(void)
+static void __init pxa168_dt_init(void)
 {
 {
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     pxa168_auxdata_lookup, NULL);
+}
 
 
-	of_irq_init(mmp_irq_match);
-
+static void __init pxa910_dt_init(void)
+{
 	of_platform_populate(NULL, of_default_bus_match_table,
 	of_platform_populate(NULL, of_default_bus_match_table,
-			     mmp_auxdata_lookup, NULL);
+			     pxa910_auxdata_lookup, NULL);
 }
 }
 
 
-static const char *pxa168_dt_board_compat[] __initdata = {
+static const char *mmp_dt_board_compat[] __initdata = {
 	"mrvl,pxa168-aspenite",
 	"mrvl,pxa168-aspenite",
+	"mrvl,pxa910-dkb",
 	NULL,
 	NULL,
 };
 };
 
 
 DT_MACHINE_START(PXA168_DT, "Marvell PXA168 (Device Tree Support)")
 DT_MACHINE_START(PXA168_DT, "Marvell PXA168 (Device Tree Support)")
 	.map_io		= mmp_map_io,
 	.map_io		= mmp_map_io,
-	.init_irq	= icu_init_irq,
-	.timer		= &pxa168_timer,
-	.init_machine	= mmp_dt_init,
-	.dt_compat	= pxa168_dt_board_compat,
+	.init_irq	= mmp_dt_irq_init,
+	.timer		= &mmp_dt_timer,
+	.init_machine	= pxa168_dt_init,
+	.dt_compat	= mmp_dt_board_compat,
+MACHINE_END
+
+DT_MACHINE_START(PXA910_DT, "Marvell PXA910 (Device Tree Support)")
+	.map_io		= mmp_map_io,
+	.init_irq	= mmp_dt_irq_init,
+	.timer		= &mmp_dt_timer,
+	.init_machine	= pxa910_dt_init,
+	.dt_compat	= mmp_dt_board_compat,
 MACHINE_END
 MACHINE_END

+ 60 - 0
arch/arm/mach-mmp/mmp2-dt.c

@@ -0,0 +1,60 @@
+/*
+ *  linux/arch/arm/mach-mmp/mmp2-dt.c
+ *
+ *  Copyright (C) 2012 Marvell Technology Group Ltd.
+ *  Author: Haojian Zhuang <haojian.zhuang@marvell.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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/irqs.h>
+#include <mach/regs-apbc.h>
+
+#include "common.h"
+
+extern void __init mmp_dt_irq_init(void);
+extern void __init mmp_dt_init_timer(void);
+
+static struct sys_timer mmp_dt_timer = {
+	.init	= mmp_dt_init_timer,
+};
+
+static const struct of_dev_auxdata mmp2_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4030000, "pxa2xx-uart.0", NULL),
+	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4017000, "pxa2xx-uart.1", NULL),
+	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4018000, "pxa2xx-uart.2", NULL),
+	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4016000, "pxa2xx-uart.3", NULL),
+	OF_DEV_AUXDATA("mrvl,mmp-twsi", 0xd4011000, "pxa2xx-i2c.0", NULL),
+	OF_DEV_AUXDATA("mrvl,mmp-twsi", 0xd4025000, "pxa2xx-i2c.1", NULL),
+	OF_DEV_AUXDATA("mrvl,mmp-gpio", 0xd4019000, "pxa-gpio", NULL),
+	OF_DEV_AUXDATA("mrvl,mmp-rtc", 0xd4010000, "sa1100-rtc", NULL),
+	{}
+};
+
+static void __init mmp2_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     mmp2_auxdata_lookup, NULL);
+}
+
+static const char *mmp2_dt_board_compat[] __initdata = {
+	"mrvl,mmp2-brownstone",
+	NULL,
+};
+
+DT_MACHINE_START(MMP2_DT, "Marvell MMP2 (Device Tree Support)")
+	.map_io		= mmp_map_io,
+	.init_irq	= mmp_dt_irq_init,
+	.timer		= &mmp_dt_timer,
+	.init_machine	= mmp2_dt_init,
+	.dt_compat	= mmp2_dt_board_compat,
+MACHINE_END

+ 60 - 21
arch/arm/mach-mmp/time.c

@@ -25,6 +25,9 @@
 
 
 #include <linux/io.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 
 #include <asm/sched_clock.h>
 #include <asm/sched_clock.h>
 #include <mach/addr-map.h>
 #include <mach/addr-map.h>
@@ -41,6 +44,8 @@
 #define MAX_DELTA		(0xfffffffe)
 #define MAX_DELTA		(0xfffffffe)
 #define MIN_DELTA		(16)
 #define MIN_DELTA		(16)
 
 
+static void __iomem *mmp_timer_base = TIMERS_VIRT_BASE;
+
 /*
 /*
  * FIXME: the timer needs some delay to stablize the counter capture
  * FIXME: the timer needs some delay to stablize the counter capture
  */
  */
@@ -48,12 +53,12 @@ static inline uint32_t timer_read(void)
 {
 {
 	int delay = 100;
 	int delay = 100;
 
 
-	__raw_writel(1, TIMERS_VIRT_BASE + TMR_CVWR(1));
+	__raw_writel(1, mmp_timer_base + TMR_CVWR(1));
 
 
 	while (delay--)
 	while (delay--)
 		cpu_relax();
 		cpu_relax();
 
 
-	return __raw_readl(TIMERS_VIRT_BASE + TMR_CVWR(1));
+	return __raw_readl(mmp_timer_base + TMR_CVWR(1));
 }
 }
 
 
 static u32 notrace mmp_read_sched_clock(void)
 static u32 notrace mmp_read_sched_clock(void)
@@ -68,12 +73,12 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
 	/*
 	/*
 	 * Clear pending interrupt status.
 	 * Clear pending interrupt status.
 	 */
 	 */
-	__raw_writel(0x01, TIMERS_VIRT_BASE + TMR_ICR(0));
+	__raw_writel(0x01, mmp_timer_base + TMR_ICR(0));
 
 
 	/*
 	/*
 	 * Disable timer 0.
 	 * Disable timer 0.
 	 */
 	 */
-	__raw_writel(0x02, TIMERS_VIRT_BASE + TMR_CER);
+	__raw_writel(0x02, mmp_timer_base + TMR_CER);
 
 
 	c->event_handler(c);
 	c->event_handler(c);
 
 
@@ -90,23 +95,23 @@ static int timer_set_next_event(unsigned long delta,
 	/*
 	/*
 	 * Disable timer 0.
 	 * Disable timer 0.
 	 */
 	 */
-	__raw_writel(0x02, TIMERS_VIRT_BASE + TMR_CER);
+	__raw_writel(0x02, mmp_timer_base + TMR_CER);
 
 
 	/*
 	/*
 	 * Clear and enable timer match 0 interrupt.
 	 * Clear and enable timer match 0 interrupt.
 	 */
 	 */
-	__raw_writel(0x01, TIMERS_VIRT_BASE + TMR_ICR(0));
-	__raw_writel(0x01, TIMERS_VIRT_BASE + TMR_IER(0));
+	__raw_writel(0x01, mmp_timer_base + TMR_ICR(0));
+	__raw_writel(0x01, mmp_timer_base + TMR_IER(0));
 
 
 	/*
 	/*
 	 * Setup new clockevent timer value.
 	 * Setup new clockevent timer value.
 	 */
 	 */
-	__raw_writel(delta - 1, TIMERS_VIRT_BASE + TMR_TN_MM(0, 0));
+	__raw_writel(delta - 1, mmp_timer_base + TMR_TN_MM(0, 0));
 
 
 	/*
 	/*
 	 * Enable timer 0.
 	 * Enable timer 0.
 	 */
 	 */
-	__raw_writel(0x03, TIMERS_VIRT_BASE + TMR_CER);
+	__raw_writel(0x03, mmp_timer_base + TMR_CER);
 
 
 	local_irq_restore(flags);
 	local_irq_restore(flags);
 
 
@@ -124,7 +129,7 @@ static void timer_set_mode(enum clock_event_mode mode,
 	case CLOCK_EVT_MODE_UNUSED:
 	case CLOCK_EVT_MODE_UNUSED:
 	case CLOCK_EVT_MODE_SHUTDOWN:
 	case CLOCK_EVT_MODE_SHUTDOWN:
 		/* disable the matching interrupt */
 		/* disable the matching interrupt */
-		__raw_writel(0x00, TIMERS_VIRT_BASE + TMR_IER(0));
+		__raw_writel(0x00, mmp_timer_base + TMR_IER(0));
 		break;
 		break;
 	case CLOCK_EVT_MODE_RESUME:
 	case CLOCK_EVT_MODE_RESUME:
 	case CLOCK_EVT_MODE_PERIODIC:
 	case CLOCK_EVT_MODE_PERIODIC:
@@ -157,27 +162,27 @@ static struct clocksource cksrc = {
 
 
 static void __init timer_config(void)
 static void __init timer_config(void)
 {
 {
-	uint32_t ccr = __raw_readl(TIMERS_VIRT_BASE + TMR_CCR);
+	uint32_t ccr = __raw_readl(mmp_timer_base + TMR_CCR);
 
 
-	__raw_writel(0x0, TIMERS_VIRT_BASE + TMR_CER); /* disable */
+	__raw_writel(0x0, mmp_timer_base + TMR_CER); /* disable */
 
 
 	ccr &= (cpu_is_mmp2()) ? (TMR_CCR_CS_0(0) | TMR_CCR_CS_1(0)) :
 	ccr &= (cpu_is_mmp2()) ? (TMR_CCR_CS_0(0) | TMR_CCR_CS_1(0)) :
 		(TMR_CCR_CS_0(3) | TMR_CCR_CS_1(3));
 		(TMR_CCR_CS_0(3) | TMR_CCR_CS_1(3));
-	__raw_writel(ccr, TIMERS_VIRT_BASE + TMR_CCR);
+	__raw_writel(ccr, mmp_timer_base + TMR_CCR);
 
 
 	/* set timer 0 to periodic mode, and timer 1 to free-running mode */
 	/* set timer 0 to periodic mode, and timer 1 to free-running mode */
-	__raw_writel(0x2, TIMERS_VIRT_BASE + TMR_CMR);
+	__raw_writel(0x2, mmp_timer_base + TMR_CMR);
 
 
-	__raw_writel(0x1, TIMERS_VIRT_BASE + TMR_PLCR(0)); /* periodic */
-	__raw_writel(0x7, TIMERS_VIRT_BASE + TMR_ICR(0));  /* clear status */
-	__raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(0));
+	__raw_writel(0x1, mmp_timer_base + TMR_PLCR(0)); /* periodic */
+	__raw_writel(0x7, mmp_timer_base + TMR_ICR(0));  /* clear status */
+	__raw_writel(0x0, mmp_timer_base + TMR_IER(0));
 
 
-	__raw_writel(0x0, TIMERS_VIRT_BASE + TMR_PLCR(1)); /* free-running */
-	__raw_writel(0x7, TIMERS_VIRT_BASE + TMR_ICR(1));  /* clear status */
-	__raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(1));
+	__raw_writel(0x0, mmp_timer_base + TMR_PLCR(1)); /* free-running */
+	__raw_writel(0x7, mmp_timer_base + TMR_ICR(1));  /* clear status */
+	__raw_writel(0x0, mmp_timer_base + TMR_IER(1));
 
 
 	/* enable timer 1 counter */
 	/* enable timer 1 counter */
-	__raw_writel(0x2, TIMERS_VIRT_BASE + TMR_CER);
+	__raw_writel(0x2, mmp_timer_base + TMR_CER);
 }
 }
 
 
 static struct irqaction timer_irq = {
 static struct irqaction timer_irq = {
@@ -203,3 +208,37 @@ void __init timer_init(int irq)
 	clocksource_register_hz(&cksrc, CLOCK_TICK_RATE);
 	clocksource_register_hz(&cksrc, CLOCK_TICK_RATE);
 	clockevents_register_device(&ckevt);
 	clockevents_register_device(&ckevt);
 }
 }
+
+#ifdef CONFIG_OF
+static struct of_device_id mmp_timer_dt_ids[] = {
+	{ .compatible = "mrvl,mmp-timer", },
+	{}
+};
+
+void __init mmp_dt_init_timer(void)
+{
+	struct device_node *np;
+	int irq, ret;
+
+	np = of_find_matching_node(NULL, mmp_timer_dt_ids);
+	if (!np) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	irq = irq_of_parse_and_map(np, 0);
+	if (!irq) {
+		ret = -EINVAL;
+		goto out;
+	}
+	mmp_timer_base = of_iomap(np, 0);
+	if (!mmp_timer_base) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	timer_init(irq);
+	return;
+out:
+	pr_err("Failed to get timer from device tree with error:%d\n", ret);
+}
+#endif

+ 98 - 18
drivers/gpio/gpio-pxa.c

@@ -11,13 +11,17 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  *  published by the Free Software Foundation.
  */
  */
+#include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
 #include <linux/gpio.h>
 #include <linux/gpio-pxa.h>
 #include <linux/gpio-pxa.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/io.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/syscore_ops.h>
 #include <linux/syscore_ops.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
@@ -56,6 +60,10 @@
 
 
 int pxa_last_gpio;
 int pxa_last_gpio;
 
 
+#ifdef CONFIG_OF
+static struct irq_domain *domain;
+#endif
+
 struct pxa_gpio_chip {
 struct pxa_gpio_chip {
 	struct gpio_chip chip;
 	struct gpio_chip chip;
 	void __iomem	*regbase;
 	void __iomem	*regbase;
@@ -81,7 +89,6 @@ enum {
 	PXA3XX_GPIO,
 	PXA3XX_GPIO,
 	PXA93X_GPIO,
 	PXA93X_GPIO,
 	MMP_GPIO = 0x10,
 	MMP_GPIO = 0x10,
-	MMP2_GPIO,
 };
 };
 
 
 static DEFINE_SPINLOCK(gpio_lock);
 static DEFINE_SPINLOCK(gpio_lock);
@@ -475,22 +482,92 @@ static int pxa_gpio_nums(void)
 		gpio_type = MMP_GPIO;
 		gpio_type = MMP_GPIO;
 	} else if (cpu_is_mmp2()) {
 	} else if (cpu_is_mmp2()) {
 		count = 191;
 		count = 191;
-		gpio_type = MMP2_GPIO;
+		gpio_type = MMP_GPIO;
 	}
 	}
 #endif /* CONFIG_ARCH_MMP */
 #endif /* CONFIG_ARCH_MMP */
 	return count;
 	return count;
 }
 }
 
 
+static struct of_device_id pxa_gpio_dt_ids[] = {
+	{ .compatible = "mrvl,pxa-gpio" },
+	{ .compatible = "mrvl,mmp-gpio", .data = (void *)MMP_GPIO },
+	{}
+};
+
+static int pxa_irq_domain_map(struct irq_domain *d, unsigned int irq,
+			      irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
+				 handle_edge_irq);
+	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	return 0;
+}
+
+const struct irq_domain_ops pxa_irq_domain_ops = {
+	.map	= pxa_irq_domain_map,
+};
+
+#ifdef CONFIG_OF
+static int __devinit pxa_gpio_probe_dt(struct platform_device *pdev)
+{
+	int ret, nr_banks, nr_gpios, irq_base;
+	struct device_node *prev, *next, *np = pdev->dev.of_node;
+	const struct of_device_id *of_id =
+				of_match_device(pxa_gpio_dt_ids, &pdev->dev);
+
+	if (!of_id) {
+		dev_err(&pdev->dev, "Failed to find gpio controller\n");
+		return -EFAULT;
+	}
+	gpio_type = (int)of_id->data;
+
+	next = of_get_next_child(np, NULL);
+	prev = next;
+	if (!next) {
+		dev_err(&pdev->dev, "Failed to find child gpio node\n");
+		ret = -EINVAL;
+		goto err;
+	}
+	for (nr_banks = 1; ; nr_banks++) {
+		next = of_get_next_child(np, prev);
+		if (!next)
+			break;
+		prev = next;
+	}
+	of_node_put(prev);
+	nr_gpios = nr_banks << 5;
+	pxa_last_gpio = nr_gpios - 1;
+
+	irq_base = irq_alloc_descs(-1, 0, nr_gpios, 0);
+	if (irq_base < 0) {
+		dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
+		goto err;
+	}
+	domain = irq_domain_add_legacy(np, nr_gpios, irq_base, 0,
+				       &pxa_irq_domain_ops, NULL);
+	return 0;
+err:
+	iounmap(gpio_reg_base);
+	return ret;
+}
+#else
+#define pxa_gpio_probe_dt(pdev)		(-1)
+#endif
+
 static int __devinit pxa_gpio_probe(struct platform_device *pdev)
 static int __devinit pxa_gpio_probe(struct platform_device *pdev)
 {
 {
 	struct pxa_gpio_chip *c;
 	struct pxa_gpio_chip *c;
 	struct resource *res;
 	struct resource *res;
 	struct clk *clk;
 	struct clk *clk;
 	struct pxa_gpio_platform_data *info;
 	struct pxa_gpio_platform_data *info;
-	int gpio, irq, ret;
+	int gpio, irq, ret, use_of = 0;
 	int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0;
 	int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0;
 
 
-	pxa_last_gpio = pxa_gpio_nums();
+	ret = pxa_gpio_probe_dt(pdev);
+	if (ret < 0)
+		pxa_last_gpio = pxa_gpio_nums();
+	else
+		use_of = 1;
 	if (!pxa_last_gpio)
 	if (!pxa_last_gpio)
 		return -EINVAL;
 		return -EINVAL;
 
 
@@ -545,25 +622,27 @@ static int __devinit pxa_gpio_probe(struct platform_device *pdev)
 			writel_relaxed(~0, c->regbase + ED_MASK_OFFSET);
 			writel_relaxed(~0, c->regbase + ED_MASK_OFFSET);
 	}
 	}
 
 
+	if (!use_of) {
 #ifdef CONFIG_ARCH_PXA
 #ifdef CONFIG_ARCH_PXA
-	irq = gpio_to_irq(0);
-	irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
-				 handle_edge_irq);
-	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-	irq_set_chained_handler(IRQ_GPIO0, pxa_gpio_demux_handler);
-
-	irq = gpio_to_irq(1);
-	irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
-				 handle_edge_irq);
-	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-	irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler);
-#endif
+		irq = gpio_to_irq(0);
+		irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
+					 handle_edge_irq);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+		irq_set_chained_handler(IRQ_GPIO0, pxa_gpio_demux_handler);
 
 
-	for (irq  = gpio_to_irq(gpio_offset);
-		irq <= gpio_to_irq(pxa_last_gpio); irq++) {
+		irq = gpio_to_irq(1);
 		irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
 		irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
 					 handle_edge_irq);
 					 handle_edge_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+		irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler);
+#endif
+
+		for (irq  = gpio_to_irq(gpio_offset);
+			irq <= gpio_to_irq(pxa_last_gpio); irq++) {
+			irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
+						 handle_edge_irq);
+			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+		}
 	}
 	}
 
 
 	irq_set_chained_handler(irq_mux, pxa_gpio_demux_handler);
 	irq_set_chained_handler(irq_mux, pxa_gpio_demux_handler);
@@ -574,6 +653,7 @@ static struct platform_driver pxa_gpio_driver = {
 	.probe		= pxa_gpio_probe,
 	.probe		= pxa_gpio_probe,
 	.driver		= {
 	.driver		= {
 		.name	= "pxa-gpio",
 		.name	= "pxa-gpio",
+		.of_match_table = pxa_gpio_dt_ids,
 	},
 	},
 };
 };