mirror of
https://github.com/torvalds/linux
synced 2024-10-24 04:06:04 +00:00
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>
This commit is contained in:
commit
853b20396b
40
Documentation/devicetree/bindings/arm/mrvl/intc.txt
Normal file
40
Documentation/devicetree/bindings/arm/mrvl/intc.txt
Normal file
|
@ -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";
|
13
Documentation/devicetree/bindings/arm/mrvl/timer.txt
Normal file
13
Documentation/devicetree/bindings/arm/mrvl/timer.txt
Normal file
|
@ -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>;
|
||||
};
|
|
@ -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;
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
38
arch/arm/boot/dts/mmp2-brownstone.dts
Normal file
38
arch/arm/boot/dts/mmp2-brownstone.dts
Normal file
|
@ -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
arch/arm/boot/dts/mmp2.dtsi
Normal file
220
arch/arm/boot/dts/mmp2.dtsi
Normal file
|
@ -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";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -18,13 +18,6 @@ aliases {
|
|||
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>;
|
||||
|
@ -32,6 +25,23 @@ soc {
|
|||
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>;
|
||||
|
@ -39,40 +49,65 @@ apb@d4000000 { /* APB */
|
|||
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;
|
||||
|
@ -80,7 +115,7 @@ twsi1: i2c@d4011000 {
|
|||
};
|
||||
|
||||
twsi2: i2c@d4025000 {
|
||||
compatible = "mrvl,mmp-twsi", "mrvl,pxa-i2c";
|
||||
compatible = "mrvl,mmp-twsi";
|
||||
reg = <0xd4025000 0x1000>;
|
||||
interrupts = <58>;
|
||||
status = "disabled";
|
||||
|
|
38
arch/arm/boot/dts/pxa910-dkb.dts
Normal file
38
arch/arm/boot/dts/pxa910-dkb.dts
Normal file
|
@ -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
arch/arm/boot/dts/pxa910.dtsi
Normal file
140
arch/arm/boot/dts/pxa910.dtsi
Normal file
|
@ -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";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -125,7 +125,7 @@
|
|||
#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
|
||||
|
@ -163,11 +163,11 @@
|
|||
#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
|
||||
|
@ -186,8 +186,14 @@
|
|||
#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)
|
||||
|
@ -212,11 +218,16 @@
|
|||
#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)
|
||||
|
||||
#define IRQ_MMP2_MUX_END (IRQ_MMP2_SSP_BASE + 2)
|
||||
/* 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_MIPI_HSI0_BASE + 2)
|
||||
|
||||
#define IRQ_GPIO_START 128
|
||||
#define MMP_NR_BUILTIN_GPIO 192
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
arch/arm/mach-mmp/irq.c
Normal file
445
arch/arm/mach-mmp/irq.c
Normal file
|
@ -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
|
|
@ -14,14 +14,19 @@
|
|||
#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_irq_init(mmp_irq_match);
|
||||
|
||||
of_platform_populate(NULL, of_default_bus_match_table,
|
||||
mmp_auxdata_lookup, NULL);
|
||||
pxa168_auxdata_lookup, NULL);
|
||||
}
|
||||
|
||||
static const char *pxa168_dt_board_compat[] __initdata = {
|
||||
static void __init pxa910_dt_init(void)
|
||||
{
|
||||
of_platform_populate(NULL, of_default_bus_match_table,
|
||||
pxa910_auxdata_lookup, NULL);
|
||||
}
|
||||
|
||||
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
|
||||
|
|
60
arch/arm/mach-mmp/mmp2-dt.c
Normal file
60
arch/arm/mach-mmp/mmp2-dt.c
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -11,13 +11,17 @@
|
|||
* 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>
|
||||
|
@ -56,6 +60,10 @@
|
|||
|
||||
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
|
||||
|
||||
for (irq = gpio_to_irq(gpio_offset);
|
||||
irq <= gpio_to_irq(pxa_last_gpio); irq++) {
|
||||
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
|
||||
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue