Merge branch 'mmp/dt' into next/pm
authorArnd Bergmann <arnd@arndb.de>
Mon, 14 May 2012 19:37:04 +0000 (21:37 +0200)
committerArnd Bergmann <arnd@arndb.de>
Mon, 14 May 2012 19:37:04 +0000 (21:37 +0200)
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>
22 files changed:
Documentation/devicetree/bindings/arm/mrvl/intc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/mrvl/mrvl.txt [moved from Documentation/devicetree/bindings/arm/mrvl.txt with 53% similarity]
Documentation/devicetree/bindings/arm/mrvl/timer.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpio/mrvl-gpio.txt
Documentation/devicetree/bindings/i2c/mrvl-i2c.txt
arch/arm/Kconfig
arch/arm/boot/dts/mmp2-brownstone.dts [new file with mode: 0644]
arch/arm/boot/dts/mmp2.dtsi [new file with mode: 0644]
arch/arm/boot/dts/pxa168.dtsi
arch/arm/boot/dts/pxa910-dkb.dts [new file with mode: 0644]
arch/arm/boot/dts/pxa910.dtsi [new file with mode: 0644]
arch/arm/mach-mmp/Kconfig
arch/arm/mach-mmp/Makefile
arch/arm/mach-mmp/include/mach/entry-macro.S
arch/arm/mach-mmp/include/mach/irqs.h
arch/arm/mach-mmp/irq-mmp2.c [deleted file]
arch/arm/mach-mmp/irq-pxa168.c [deleted file]
arch/arm/mach-mmp/irq.c [new file with mode: 0644]
arch/arm/mach-mmp/mmp-dt.c
arch/arm/mach-mmp/mmp2-dt.c [new file with mode: 0644]
arch/arm/mach-mmp/time.c
drivers/gpio/gpio-pxa.c

diff --git a/Documentation/devicetree/bindings/arm/mrvl/intc.txt b/Documentation/devicetree/bindings/arm/mrvl/intc.txt
new file mode 100644 (file)
index 0000000..80b9a94
--- /dev/null
@@ -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>;
+       };
@@ -4,3 +4,11 @@ Marvell Platforms Device Tree Bindings
 PXA168 Aspenite Board
 Required root node properties:
        - 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";
diff --git a/Documentation/devicetree/bindings/arm/mrvl/timer.txt b/Documentation/devicetree/bindings/arm/mrvl/timer.txt
new file mode 100644 (file)
index 0000000..9a6e251
--- /dev/null
@@ -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>;
+       };
index 1e34cfe..05428f3 100644 (file)
@@ -3,19 +3,25 @@
 Required properties:
 - compatible : Should be "mrvl,pxa-gpio" or "mrvl,mmp-gpio"
 - 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-cells : Should be one.  It is the pin number.
 
 Example:
 
        gpio: gpio@d4019000 {
-               compatible = "mrvl,mmp-gpio", "mrvl,pxa-gpio";
+               compatible = "mrvl,mmp-gpio";
                reg = <0xd4019000 0x1000>;
-               interrupts = <49>, <17>, <18>;
-               interrupt-name = "gpio_mux", "gpio0", "gpio1";
+               interrupts = <49>;
+               interrupt-name = "gpio_mux";
                gpio-controller;
                #gpio-cells = <1>;
                interrupt-controller;
index 071eb3c..b891ee2 100644 (file)
@@ -3,34 +3,31 @@
 Required properties :
 
  - 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.
    For the pxa2xx/pxa3xx, an additional node "mrvl,pxa-i2c" is required
    as shown in the example below.
 
 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
-   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
    status register of i2c controller instead.
  - mrvl,i2c-fast-mode : Enable fast mode of i2c controller.
 
 Examples:
        twsi1: i2c@d4011000 {
-               compatible = "mrvl,mmp-twsi", "mrvl,pxa-i2c";
+               compatible = "mrvl,mmp-twsi";
                reg = <0xd4011000 0x1000>;
                interrupts = <7>;
                mrvl,i2c-fast-mode;
        };
        
        twsi2: i2c@d4025000 {
-               compatible = "mrvl,mmp-twsi", "mrvl,pxa-i2c";
+               compatible = "mrvl,mmp-twsi";
                reg = <0xd4025000 0x1000>;
                interrupts = <58>;
        };
index cf006d4..4cf9d42 100644 (file)
@@ -632,6 +632,7 @@ config ARCH_MMP
        select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
        select GPIO_PXA
+       select IRQ_DOMAIN
        select TICK_ONESHOT
        select PLAT_PXA
        select SPARSE_IRQ
diff --git a/arch/arm/boot/dts/mmp2-brownstone.dts b/arch/arm/boot/dts/mmp2-brownstone.dts
new file mode 100644 (file)
index 0000000..153a4b2
--- /dev/null
@@ -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";
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/mmp2.dtsi b/arch/arm/boot/dts/mmp2.dtsi
new file mode 100644 (file)
index 0000000..80f74e2
--- /dev/null
@@ -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";
+                       };
+               };
+       };
+};
index d32d512..31a7186 100644 (file)
                i2c1 = &twsi2;
        };
 
-       intc: intc-interrupt-controller@d4282000 {
-               compatible = "mrvl,mmp-intc", "mrvl,intc";
-               interrupt-controller;
-               #interrupt-cells = <1>;
-               reg = <0xd4282000 0x1000>;
-       };
-
        soc {
                #address-cells = <1>;
                #size-cells = <1>;
                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>;
                        reg = <0xd4000000 0x00200000>;
                        ranges;
 
+                       timer0: timer@d4014000 {
+                               compatible = "mrvl,mmp-timer";
+                               reg = <0xd4014000 0x100>;
+                               interrupts = <13>;
+                       };
+
                        uart1: uart@d4017000 {
-                               compatible = "mrvl,mmp-uart", "mrvl,pxa-uart";
+                               compatible = "mrvl,mmp-uart";
                                reg = <0xd4017000 0x1000>;
                                interrupts = <27>;
                                status = "disabled";
                        };
 
                        uart2: uart@d4018000 {
-                               compatible = "mrvl,mmp-uart", "mrvl,pxa-uart";
+                               compatible = "mrvl,mmp-uart";
                                reg = <0xd4018000 0x1000>;
                                interrupts = <28>;
                                status = "disabled";
                        };
 
                        uart3: uart@d4026000 {
-                               compatible = "mrvl,mmp-uart", "mrvl,pxa-uart";
+                               compatible = "mrvl,mmp-uart";
                                reg = <0xd4026000 0x1000>;
                                interrupts = <29>;
                                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>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
                                interrupts = <49>;
                                interrupt-names = "gpio_mux";
-                               gpio-controller;
-                               #gpio-cells = <1>;
                                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", "mrvl,pxa-i2c";
+                               compatible = "mrvl,mmp-twsi";
                                reg = <0xd4011000 0x1000>;
                                interrupts = <7>;
                                mrvl,i2c-fast-mode;
                        };
 
                        twsi2: i2c@d4025000 {
-                               compatible = "mrvl,mmp-twsi", "mrvl,pxa-i2c";
+                               compatible = "mrvl,mmp-twsi";
                                reg = <0xd4025000 0x1000>;
                                interrupts = <58>;
                                status = "disabled";
diff --git a/arch/arm/boot/dts/pxa910-dkb.dts b/arch/arm/boot/dts/pxa910-dkb.dts
new file mode 100644 (file)
index 0000000..e92be5a
--- /dev/null
@@ -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";
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/pxa910.dtsi b/arch/arm/boot/dts/pxa910.dtsi
new file mode 100644 (file)
index 0000000..aebf32d
--- /dev/null
@@ -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";
+                       };
+               };
+       };
+};
index 5a90b9a..ede7216 100644 (file)
@@ -2,16 +2,6 @@ if ARCH_MMP
 
 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
        bool "Marvell's PXA168 Aspenite Development Board"
        select CPU_PXA168
@@ -94,6 +84,25 @@ config MACH_GPLUGD
          Say 'Y' here if you want to support the Marvell PXA168-based
          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
 
 config CPU_PXA168
index 4fc0ff5..b920b9b 100644 (file)
@@ -2,12 +2,12 @@
 # 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
-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
 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_MARVELL_JASPER) += jasper.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_GPLUGD)      += gplugd.o
index 9cff9e7..bd152e2 100644 (file)
@@ -6,13 +6,15 @@
  * published by the Free Software Foundation.
  */
 
+#include <asm/irq.h>
 #include <mach/regs-icu.h>
 
        .macro  get_irqnr_preamble, base, tmp
        mrc     p15, 0, \tmp, c0, c0, 0         @ CPUID
        and     \tmp, \tmp, #0xff00
        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
        addeq   \base, \base, #0x104            @ PJ4 IRQ SEL register
        .endm
index d0e7466..fb492a5 100644 (file)
 #define IRQ_MMP2_RTC_MUX               5
 #define IRQ_MMP2_TWSI1                 7
 #define IRQ_MMP2_GPU                   8
-#define IRQ_MMP2_KEYPAD                        9
+#define IRQ_MMP2_KEYPAD_MUX            9
 #define IRQ_MMP2_ROTARY                        10
 #define IRQ_MMP2_TRACKBALL             11
 #define IRQ_MMP2_ONEWIRE               12
 #define IRQ_MMP2_DMA_FIQ               47
 #define IRQ_MMP2_DMA_RIQ               48
 #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_MMC3                  53
 #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_MIPI_SLIM_DMA         59
 #define IRQ_MMP2_PJ4_FREQ_CHG          60
 #define IRQ_MMP2_RTC_ALARM             (IRQ_MMP2_RTC_BASE + 0)
 #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 */
-#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_TWSI3                 (IRQ_MMP2_TWSI_BASE + 1)
 #define IRQ_MMP2_TWSI4                 (IRQ_MMP2_TWSI_BASE + 2)
 #define IRQ_MMP2_COMMRX                        (IRQ_MMP2_MISC_BASE + 14)
 
 /* 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 MMP_NR_BUILTIN_GPIO            192
diff --git a/arch/arm/mach-mmp/irq-mmp2.c b/arch/arm/mach-mmp/irq-mmp2.c
deleted file mode 100644 (file)
index 7895d27..0000000
+++ /dev/null
@@ -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);
-}
diff --git a/arch/arm/mach-mmp/irq-pxa168.c b/arch/arm/mach-mmp/irq-pxa168.c
deleted file mode 100644 (file)
index 89706a0..0000000
+++ /dev/null
@@ -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);
-       }
-}
diff --git a/arch/arm/mach-mmp/irq.c b/arch/arm/mach-mmp/irq.c
new file mode 100644 (file)
index 0000000..3705470
--- /dev/null
@@ -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
index 6707539..033cc31 100644 (file)
 #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 "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", 0xd4018000, "pxa2xx-uart.1", 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,
-                            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,pxa910-dkb",
        NULL,
 };
 
 DT_MACHINE_START(PXA168_DT, "Marvell PXA168 (Device Tree Support)")
        .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
diff --git a/arch/arm/mach-mmp/mmp2-dt.c b/arch/arm/mach-mmp/mmp2-dt.c
new file mode 100644 (file)
index 0000000..535a5ed
--- /dev/null
@@ -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
index 71fc4ee..936447c 100644 (file)
@@ -25,6 +25,9 @@
 
 #include <linux/io.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 <mach/addr-map.h>
@@ -41,6 +44,8 @@
 #define MAX_DELTA              (0xfffffffe)
 #define MIN_DELTA              (16)
 
+static void __iomem *mmp_timer_base = TIMERS_VIRT_BASE;
+
 /*
  * 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;
 
-       __raw_writel(1, TIMERS_VIRT_BASE + TMR_CVWR(1));
+       __raw_writel(1, mmp_timer_base + TMR_CVWR(1));
 
        while (delay--)
                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)
@@ -68,12 +73,12 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
        /*
         * 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.
         */
-       __raw_writel(0x02, TIMERS_VIRT_BASE + TMR_CER);
+       __raw_writel(0x02, mmp_timer_base + TMR_CER);
 
        c->event_handler(c);
 
@@ -90,23 +95,23 @@ static int timer_set_next_event(unsigned long delta,
        /*
         * 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.
         */
-       __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.
         */
-       __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.
         */
-       __raw_writel(0x03, TIMERS_VIRT_BASE + TMR_CER);
+       __raw_writel(0x03, mmp_timer_base + TMR_CER);
 
        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_SHUTDOWN:
                /* disable the matching interrupt */
-               __raw_writel(0x00, TIMERS_VIRT_BASE + TMR_IER(0));
+               __raw_writel(0x00, mmp_timer_base + TMR_IER(0));
                break;
        case CLOCK_EVT_MODE_RESUME:
        case CLOCK_EVT_MODE_PERIODIC:
@@ -157,27 +162,27 @@ static struct clocksource cksrc = {
 
 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)) :
                (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 */
-       __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 */
-       __raw_writel(0x2, TIMERS_VIRT_BASE + TMR_CER);
+       __raw_writel(0x2, mmp_timer_base + TMR_CER);
 }
 
 static struct irqaction timer_irq = {
@@ -203,3 +208,37 @@ void __init timer_init(int irq)
        clocksource_register_hz(&cksrc, CLOCK_TICK_RATE);
        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
index fc3ace3..58a6a63 100644 (file)
  *  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/clk.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
 #include <linux/gpio-pxa.h>
 #include <linux/init.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/syscore_ops.h>
 #include <linux/slab.h>
 
 int pxa_last_gpio;
 
+#ifdef CONFIG_OF
+static struct irq_domain *domain;
+#endif
+
 struct pxa_gpio_chip {
        struct gpio_chip chip;
        void __iomem    *regbase;
@@ -81,7 +89,6 @@ enum {
        PXA3XX_GPIO,
        PXA93X_GPIO,
        MMP_GPIO = 0x10,
-       MMP2_GPIO,
 };
 
 static DEFINE_SPINLOCK(gpio_lock);
@@ -475,22 +482,92 @@ static int pxa_gpio_nums(void)
                gpio_type = MMP_GPIO;
        } else if (cpu_is_mmp2()) {
                count = 191;
-               gpio_type = MMP2_GPIO;
+               gpio_type = MMP_GPIO;
        }
 #endif /* CONFIG_ARCH_MMP */
        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)
 {
        struct pxa_gpio_chip *c;
        struct resource *res;
        struct clk *clk;
        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;
 
-       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)
                return -EINVAL;
 
@@ -545,25 +622,27 @@ static int __devinit pxa_gpio_probe(struct platform_device *pdev)
                        writel_relaxed(~0, c->regbase + ED_MASK_OFFSET);
        }
 
+       if (!use_of) {
 #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,
                                         handle_edge_irq);
                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);
@@ -574,6 +653,7 @@ static struct platform_driver pxa_gpio_driver = {
        .probe          = pxa_gpio_probe,
        .driver         = {
                .name   = "pxa-gpio",
+               .of_match_table = pxa_gpio_dt_ids,
        },
 };