diff options
author | Kevin Hilman <khilman@linaro.org> | 2013-12-20 11:58:25 -0500 |
---|---|---|
committer | Kevin Hilman <khilman@linaro.org> | 2013-12-20 11:58:51 -0500 |
commit | 23621799f24c3c4e8e8dcdf5fdeb3ebd2be148f9 (patch) | |
tree | d748b287a26c8e52206aeca675ec63709b1187bf | |
parent | 7f457160dae592b71b4aac03258237b0f2a67a3e (diff) | |
parent | 1c37fa10b275d3e5b6285066b5b27c8feae688c8 (diff) |
Merge branch 'berlin/soc' into next/soc
From Sebastian Hesselbarth:
* berlin/soc:
ARM: add initial support for Marvell Berlin SoCs
ARM: add Armada 1500-mini and Chromecast device tree files
ARM: add Armada 1500 and Sony NSZ-GS7 device tree files
ARM: add Marvell Berlin UART0 lowlevel debug
ARM: add Marvell Berlin SoCs to multi_v7_defconfig
ARM: add Marvell Berlin SoC familiy to Marvell doc
MAINTAINERS: add ARM Marvell Berlin SoC
irqchip: add DesignWare APB ICTL interrupt controller
Signed-off-by: Kevin Hilman <khilman@linaro.org>
-rw-r--r-- | Documentation/arm/Marvell/README | 24 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/arm/marvell,berlin.txt | 24 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/interrupt-controller/snps,dw-apb-ictl.txt | 32 | ||||
-rw-r--r-- | MAINTAINERS | 6 | ||||
-rw-r--r-- | arch/arm/Kconfig | 2 | ||||
-rw-r--r-- | arch/arm/Kconfig.debug | 10 | ||||
-rw-r--r-- | arch/arm/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/boot/dts/Makefile | 3 | ||||
-rw-r--r-- | arch/arm/boot/dts/berlin2-sony-nsz-gs7.dts | 29 | ||||
-rw-r--r-- | arch/arm/boot/dts/berlin2.dtsi | 227 | ||||
-rw-r--r-- | arch/arm/boot/dts/berlin2cd-google-chromecast.dts | 29 | ||||
-rw-r--r-- | arch/arm/boot/dts/berlin2cd.dtsi | 210 | ||||
-rw-r--r-- | arch/arm/configs/multi_v7_defconfig | 3 | ||||
-rw-r--r-- | arch/arm/mach-berlin/Kconfig | 29 | ||||
-rw-r--r-- | arch/arm/mach-berlin/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-berlin/berlin.c | 39 | ||||
-rw-r--r-- | drivers/irqchip/Kconfig | 4 | ||||
-rw-r--r-- | drivers/irqchip/Makefile | 1 | ||||
-rw-r--r-- | drivers/irqchip/irq-dw-apb-ictl.c | 150 |
19 files changed, 824 insertions, 0 deletions
diff --git a/Documentation/arm/Marvell/README b/Documentation/arm/Marvell/README index da0151db9964..5a930c1528ad 100644 --- a/Documentation/arm/Marvell/README +++ b/Documentation/arm/Marvell/README | |||
@@ -211,6 +211,30 @@ MMP/MMP2 family (communication processor) | |||
211 | Linux kernel mach directory: arch/arm/mach-mmp | 211 | Linux kernel mach directory: arch/arm/mach-mmp |
212 | Linux kernel plat directory: arch/arm/plat-pxa | 212 | Linux kernel plat directory: arch/arm/plat-pxa |
213 | 213 | ||
214 | Berlin family (Digital Entertainment) | ||
215 | ------------------------------------- | ||
216 | |||
217 | Flavors: | ||
218 | 88DE3005, Armada 1500-mini | ||
219 | Design name: BG2CD | ||
220 | Core: ARM Cortex-A9, PL310 L2CC | ||
221 | Homepage: http://www.marvell.com/digital-entertainment/armada-1500-mini/ | ||
222 | 88DE3100, Armada 1500 | ||
223 | Design name: BG2 | ||
224 | Core: Marvell PJ4B (ARMv7), Tauros3 L2CC | ||
225 | Homepage: http://www.marvell.com/digital-entertainment/armada-1500/ | ||
226 | Product Brief: http://www.marvell.com/digital-entertainment/armada-1500/assets/Marvell-ARMADA-1500-Product-Brief.pdf | ||
227 | 88DE???? | ||
228 | Design name: BG3 | ||
229 | Core: ARM Cortex-A15, CA15 integrated L2CC | ||
230 | |||
231 | Homepage: http://www.marvell.com/digital-entertainment/ | ||
232 | Directory: arch/arm/mach-berlin | ||
233 | |||
234 | Comments: | ||
235 | * This line of SoCs is based on Marvell Sheeva or ARM Cortex CPUs | ||
236 | with Synopsys DesignWare (IRQ, GPIO, Timers, ...) and PXA IP (SDHCI, USB, ETH, ...). | ||
237 | |||
214 | Long-term plans | 238 | Long-term plans |
215 | --------------- | 239 | --------------- |
216 | 240 | ||
diff --git a/Documentation/devicetree/bindings/arm/marvell,berlin.txt b/Documentation/devicetree/bindings/arm/marvell,berlin.txt new file mode 100644 index 000000000000..737afa5f8148 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/marvell,berlin.txt | |||
@@ -0,0 +1,24 @@ | |||
1 | Marvell Berlin SoC Family Device Tree Bindings | ||
2 | --------------------------------------------------------------- | ||
3 | |||
4 | Boards with a SoC of the Marvell Berlin family, e.g. Armada 1500 | ||
5 | shall have the following properties: | ||
6 | |||
7 | * Required root node properties: | ||
8 | compatible: must contain "marvell,berlin" | ||
9 | |||
10 | In addition, the above compatible shall be extended with the specific | ||
11 | SoC and board used. Currently known SoC compatibles are: | ||
12 | "marvell,berlin2" for Marvell Armada 1500 (BG2, 88DE3100), | ||
13 | "marvell,berlin2cd" for Marvell Armada 1500-mini (BG2CD, 88DE3005) | ||
14 | "marvell,berlin2ct" for Marvell Armada ? (BG2CT, 88DE????) | ||
15 | "marvell,berlin3" for Marvell Armada ? (BG3, 88DE????) | ||
16 | |||
17 | * Example: | ||
18 | |||
19 | / { | ||
20 | model = "Sony NSZ-GS7"; | ||
21 | compatible = "sony,nsz-gs7", "marvell,berlin2", "marvell,berlin"; | ||
22 | |||
23 | ... | ||
24 | } | ||
diff --git a/Documentation/devicetree/bindings/interrupt-controller/snps,dw-apb-ictl.txt b/Documentation/devicetree/bindings/interrupt-controller/snps,dw-apb-ictl.txt new file mode 100644 index 000000000000..492911744ca3 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/snps,dw-apb-ictl.txt | |||
@@ -0,0 +1,32 @@ | |||
1 | Synopsys DesignWare APB interrupt controller (dw_apb_ictl) | ||
2 | |||
3 | Synopsys DesignWare provides interrupt controller IP for APB known as | ||
4 | dw_apb_ictl. The IP is used as secondary interrupt controller in some SoCs with | ||
5 | APB bus, e.g. Marvell Armada 1500. | ||
6 | |||
7 | Required properties: | ||
8 | - compatible: shall be "snps,dw-apb-ictl" | ||
9 | - reg: physical base address of the controller and length of memory mapped | ||
10 | region starting with ENABLE_LOW register | ||
11 | - interrupt-controller: identifies the node as an interrupt controller | ||
12 | - #interrupt-cells: number of cells to encode an interrupt-specifier, shall be 1 | ||
13 | - interrupts: interrupt reference to primary interrupt controller | ||
14 | - interrupt-parent: (optional) reference specific primary interrupt controller | ||
15 | |||
16 | The interrupt sources map to the corresponding bits in the interrupt | ||
17 | registers, i.e. | ||
18 | - 0 maps to bit 0 of low interrupts, | ||
19 | - 1 maps to bit 1 of low interrupts, | ||
20 | - 32 maps to bit 0 of high interrupts, | ||
21 | - 33 maps to bit 1 of high interrupts, | ||
22 | - (optional) fast interrupts start at 64. | ||
23 | |||
24 | Example: | ||
25 | aic: interrupt-controller@3000 { | ||
26 | compatible = "snps,dw-apb-ictl"; | ||
27 | reg = <0x3000 0xc00>; | ||
28 | interrupt-controller; | ||
29 | #interrupt-cells = <1>; | ||
30 | interrupt-parent = <&gic>; | ||
31 | interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>; | ||
32 | }; | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 8285ed4676b6..33c7187f417b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1032,6 +1032,12 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | |||
1032 | S: Maintained | 1032 | S: Maintained |
1033 | F: arch/arm/mach-mvebu/ | 1033 | F: arch/arm/mach-mvebu/ |
1034 | 1034 | ||
1035 | ARM/Marvell Berlin SoC support | ||
1036 | M: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> | ||
1037 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | ||
1038 | S: Maintained | ||
1039 | F: arch/arm/mach-berlin/ | ||
1040 | |||
1035 | ARM/Marvell Dove/Kirkwood/MV78xx0/Orion SOC support | 1041 | ARM/Marvell Dove/Kirkwood/MV78xx0/Orion SOC support |
1036 | M: Jason Cooper <jason@lakedaemon.net> | 1042 | M: Jason Cooper <jason@lakedaemon.net> |
1037 | M: Andrew Lunn <andrew@lunn.ch> | 1043 | M: Andrew Lunn <andrew@lunn.ch> |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c1f1a7eee953..121153f57796 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -911,6 +911,8 @@ source "arch/arm/mach-bcm/Kconfig" | |||
911 | 911 | ||
912 | source "arch/arm/mach-bcm2835/Kconfig" | 912 | source "arch/arm/mach-bcm2835/Kconfig" |
913 | 913 | ||
914 | source "arch/arm/mach-berlin/Kconfig" | ||
915 | |||
914 | source "arch/arm/mach-clps711x/Kconfig" | 916 | source "arch/arm/mach-clps711x/Kconfig" |
915 | 917 | ||
916 | source "arch/arm/mach-cns3xxx/Kconfig" | 918 | source "arch/arm/mach-cns3xxx/Kconfig" |
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 5765abf5ce84..257155874bce 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug | |||
@@ -94,6 +94,14 @@ choice | |||
94 | depends on ARCH_BCM2835 | 94 | depends on ARCH_BCM2835 |
95 | select DEBUG_UART_PL01X | 95 | select DEBUG_UART_PL01X |
96 | 96 | ||
97 | config DEBUG_BERLIN_UART | ||
98 | bool "Marvell Berlin SoC Debug UART" | ||
99 | depends on ARCH_BERLIN | ||
100 | select DEBUG_UART_8250 | ||
101 | help | ||
102 | Say Y here if you want kernel low-level debugging support | ||
103 | on Marvell Berlin SoC based platforms. | ||
104 | |||
97 | config DEBUG_CLPS711X_UART1 | 105 | config DEBUG_CLPS711X_UART1 |
98 | bool "Kernel low-level debugging messages via UART1" | 106 | bool "Kernel low-level debugging messages via UART1" |
99 | depends on ARCH_CLPS711X | 107 | depends on ARCH_CLPS711X |
@@ -1011,6 +1019,7 @@ config DEBUG_UART_PHYS | |||
1011 | default 0xf1012000 if DEBUG_MVEBU_UART_ALTERNATE | 1019 | default 0xf1012000 if DEBUG_MVEBU_UART_ALTERNATE |
1012 | default 0xf1012000 if ARCH_DOVE || ARCH_KIRKWOOD || ARCH_MV78XX0 || \ | 1020 | default 0xf1012000 if ARCH_DOVE || ARCH_KIRKWOOD || ARCH_MV78XX0 || \ |
1013 | ARCH_ORION5X | 1021 | ARCH_ORION5X |
1022 | default 0xf7fc9000 if DEBUG_BERLIN_UART | ||
1014 | default 0xf8b00000 if DEBUG_HI3716_UART | 1023 | default 0xf8b00000 if DEBUG_HI3716_UART |
1015 | default 0xfcb00000 if DEBUG_HI3620_UART | 1024 | default 0xfcb00000 if DEBUG_HI3620_UART |
1016 | default 0xfe800000 if ARCH_IOP32X | 1025 | default 0xfe800000 if ARCH_IOP32X |
@@ -1036,6 +1045,7 @@ config DEBUG_UART_VIRT | |||
1036 | default 0xf2100000 if DEBUG_PXA_UART1 | 1045 | default 0xf2100000 if DEBUG_PXA_UART1 |
1037 | default 0xf4090000 if ARCH_LPC32XX | 1046 | default 0xf4090000 if ARCH_LPC32XX |
1038 | default 0xf4200000 if ARCH_GEMINI | 1047 | default 0xf4200000 if ARCH_GEMINI |
1048 | default 0xf7fc9000 if DEBUG_BERLIN_UART | ||
1039 | default 0xf8009000 if DEBUG_VEXPRESS_UART0_CA9 | 1049 | default 0xf8009000 if DEBUG_VEXPRESS_UART0_CA9 |
1040 | default 0xf8090000 if DEBUG_VEXPRESS_UART0_RS1 | 1050 | default 0xf8090000 if DEBUG_VEXPRESS_UART0_RS1 |
1041 | default 0xfb009000 if DEBUG_REALVIEW_STD_PORT | 1051 | default 0xfb009000 if DEBUG_REALVIEW_STD_PORT |
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index c99b1086d83d..483abc7a9834 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile | |||
@@ -148,6 +148,7 @@ textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000 | |||
148 | machine-$(CONFIG_ARCH_AT91) += at91 | 148 | machine-$(CONFIG_ARCH_AT91) += at91 |
149 | machine-$(CONFIG_ARCH_BCM) += bcm | 149 | machine-$(CONFIG_ARCH_BCM) += bcm |
150 | machine-$(CONFIG_ARCH_BCM2835) += bcm2835 | 150 | machine-$(CONFIG_ARCH_BCM2835) += bcm2835 |
151 | machine-$(CONFIG_ARCH_BERLIN) += berlin | ||
151 | machine-$(CONFIG_ARCH_CLPS711X) += clps711x | 152 | machine-$(CONFIG_ARCH_CLPS711X) += clps711x |
152 | machine-$(CONFIG_ARCH_CNS3XXX) += cns3xxx | 153 | machine-$(CONFIG_ARCH_CNS3XXX) += cns3xxx |
153 | machine-$(CONFIG_ARCH_DAVINCI) += davinci | 154 | machine-$(CONFIG_ARCH_DAVINCI) += davinci |
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index d57c1a65b24f..5c92212ee3a7 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile | |||
@@ -45,6 +45,9 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb | |||
45 | dtb-$(CONFIG_ARCH_BCM_MOBILE) += bcm11351-brt.dtb \ | 45 | dtb-$(CONFIG_ARCH_BCM_MOBILE) += bcm11351-brt.dtb \ |
46 | bcm28155-ap.dtb | 46 | bcm28155-ap.dtb |
47 | dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb | 47 | dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb |
48 | dtb-$(CONFIG_ARCH_BERLIN) += \ | ||
49 | berlin2-sony-nsz-gs7.dtb \ | ||
50 | berlin2cd-google-chromecast.dtb | ||
48 | dtb-$(CONFIG_ARCH_DAVINCI) += da850-enbw-cmc.dtb \ | 51 | dtb-$(CONFIG_ARCH_DAVINCI) += da850-enbw-cmc.dtb \ |
49 | da850-evm.dtb | 52 | da850-evm.dtb |
50 | dtb-$(CONFIG_ARCH_DOVE) += dove-cm-a510.dtb \ | 53 | dtb-$(CONFIG_ARCH_DOVE) += dove-cm-a510.dtb \ |
diff --git a/arch/arm/boot/dts/berlin2-sony-nsz-gs7.dts b/arch/arm/boot/dts/berlin2-sony-nsz-gs7.dts new file mode 100644 index 000000000000..c72bfd468d10 --- /dev/null +++ b/arch/arm/boot/dts/berlin2-sony-nsz-gs7.dts | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | * Device Tree file for Sony NSZ-GS7 | ||
3 | * | ||
4 | * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public | ||
7 | * License version 2. This program is licensed "as is" without any | ||
8 | * warranty of any kind, whether express or implied. | ||
9 | */ | ||
10 | |||
11 | /dts-v1/; | ||
12 | |||
13 | #include "berlin2.dtsi" | ||
14 | |||
15 | / { | ||
16 | model = "Sony NSZ-GS7"; | ||
17 | compatible = "sony,nsz-gs7", "marvell,berlin2", "marvell,berlin"; | ||
18 | |||
19 | chosen { | ||
20 | bootargs = "console=ttyS0,115200 earlyprintk"; | ||
21 | }; | ||
22 | |||
23 | memory { | ||
24 | device_type = "memory"; | ||
25 | reg = <0x00000000 0x40000000>; /* 1 GB */ | ||
26 | }; | ||
27 | }; | ||
28 | |||
29 | &uart0 { status = "okay"; }; | ||
diff --git a/arch/arm/boot/dts/berlin2.dtsi b/arch/arm/boot/dts/berlin2.dtsi new file mode 100644 index 000000000000..56a1af2f1052 --- /dev/null +++ b/arch/arm/boot/dts/berlin2.dtsi | |||
@@ -0,0 +1,227 @@ | |||
1 | /* | ||
2 | * Device Tree Include file for Marvell Armada 1500 (Berlin BG2) SoC | ||
3 | * | ||
4 | * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> | ||
5 | * | ||
6 | * based on GPL'ed 2.6 kernel sources | ||
7 | * (c) Marvell International Ltd. | ||
8 | * | ||
9 | * This file is licensed under the terms of the GNU General Public | ||
10 | * License version 2. This program is licensed "as is" without any | ||
11 | * warranty of any kind, whether express or implied. | ||
12 | */ | ||
13 | |||
14 | #include "skeleton.dtsi" | ||
15 | #include <dt-bindings/interrupt-controller/arm-gic.h> | ||
16 | |||
17 | / { | ||
18 | model = "Marvell Armada 1500 (BG2) SoC"; | ||
19 | compatible = "marvell,berlin2", "marvell,berlin"; | ||
20 | |||
21 | cpus { | ||
22 | #address-cells = <1>; | ||
23 | #size-cells = <0>; | ||
24 | |||
25 | cpu@0 { | ||
26 | compatible = "marvell,pj4b"; | ||
27 | device_type = "cpu"; | ||
28 | next-level-cache = <&l2>; | ||
29 | reg = <0>; | ||
30 | }; | ||
31 | |||
32 | cpu@1 { | ||
33 | compatible = "marvell,pj4b"; | ||
34 | device_type = "cpu"; | ||
35 | next-level-cache = <&l2>; | ||
36 | reg = <1>; | ||
37 | }; | ||
38 | }; | ||
39 | |||
40 | clocks { | ||
41 | smclk: sysmgr-clock { | ||
42 | compatible = "fixed-clock"; | ||
43 | #clock-cells = <0>; | ||
44 | clock-frequency = <25000000>; | ||
45 | }; | ||
46 | |||
47 | cfgclk: cfg-clock { | ||
48 | compatible = "fixed-clock"; | ||
49 | #clock-cells = <0>; | ||
50 | clock-frequency = <100000000>; | ||
51 | }; | ||
52 | |||
53 | sysclk: system-clock { | ||
54 | compatible = "fixed-clock"; | ||
55 | #clock-cells = <0>; | ||
56 | clock-frequency = <400000000>; | ||
57 | }; | ||
58 | }; | ||
59 | |||
60 | soc { | ||
61 | compatible = "simple-bus"; | ||
62 | #address-cells = <1>; | ||
63 | #size-cells = <1>; | ||
64 | interrupt-parent = <&gic>; | ||
65 | |||
66 | ranges = <0 0xf7000000 0x1000000>; | ||
67 | |||
68 | l2: l2-cache-controller@ac0000 { | ||
69 | compatible = "marvell,tauros3-cache", "arm,pl310-cache"; | ||
70 | reg = <0xac0000 0x1000>; | ||
71 | cache-unified; | ||
72 | cache-level = <2>; | ||
73 | }; | ||
74 | |||
75 | gic: interrupt-controller@ad1000 { | ||
76 | compatible = "arm,cortex-a9-gic"; | ||
77 | reg = <0xad1000 0x1000>, <0xad0100 0x0100>; | ||
78 | interrupt-controller; | ||
79 | #interrupt-cells = <3>; | ||
80 | }; | ||
81 | |||
82 | local-timer@ad0600 { | ||
83 | compatible = "arm,cortex-a9-twd-timer"; | ||
84 | reg = <0xad0600 0x20>; | ||
85 | interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>; | ||
86 | clocks = <&sysclk>; | ||
87 | }; | ||
88 | |||
89 | apb@e80000 { | ||
90 | compatible = "simple-bus"; | ||
91 | #address-cells = <1>; | ||
92 | #size-cells = <1>; | ||
93 | |||
94 | ranges = <0 0xe80000 0x10000>; | ||
95 | interrupt-parent = <&aic>; | ||
96 | |||
97 | timer0: timer@2c00 { | ||
98 | compatible = "snps,dw-apb-timer"; | ||
99 | reg = <0x2c00 0x14>; | ||
100 | interrupts = <8>; | ||
101 | clocks = <&cfgclk>; | ||
102 | clock-names = "timer"; | ||
103 | status = "okay"; | ||
104 | }; | ||
105 | |||
106 | timer1: timer@2c14 { | ||
107 | compatible = "snps,dw-apb-timer"; | ||
108 | reg = <0x2c14 0x14>; | ||
109 | interrupts = <9>; | ||
110 | clocks = <&cfgclk>; | ||
111 | clock-names = "timer"; | ||
112 | status = "okay"; | ||
113 | }; | ||
114 | |||
115 | timer2: timer@2c28 { | ||
116 | compatible = "snps,dw-apb-timer"; | ||
117 | reg = <0x2c28 0x14>; | ||
118 | interrupts = <10>; | ||
119 | clocks = <&cfgclk>; | ||
120 | clock-names = "timer"; | ||
121 | status = "disabled"; | ||
122 | }; | ||
123 | |||
124 | timer3: timer@2c3c { | ||
125 | compatible = "snps,dw-apb-timer"; | ||
126 | reg = <0x2c3c 0x14>; | ||
127 | interrupts = <11>; | ||
128 | clocks = <&cfgclk>; | ||
129 | clock-names = "timer"; | ||
130 | status = "disabled"; | ||
131 | }; | ||
132 | |||
133 | timer4: timer@2c50 { | ||
134 | compatible = "snps,dw-apb-timer"; | ||
135 | reg = <0x2c50 0x14>; | ||
136 | interrupts = <12>; | ||
137 | clocks = <&cfgclk>; | ||
138 | clock-names = "timer"; | ||
139 | status = "disabled"; | ||
140 | }; | ||
141 | |||
142 | timer5: timer@2c64 { | ||
143 | compatible = "snps,dw-apb-timer"; | ||
144 | reg = <0x2c64 0x14>; | ||
145 | interrupts = <13>; | ||
146 | clocks = <&cfgclk>; | ||
147 | clock-names = "timer"; | ||
148 | status = "disabled"; | ||
149 | }; | ||
150 | |||
151 | timer6: timer@2c78 { | ||
152 | compatible = "snps,dw-apb-timer"; | ||
153 | reg = <0x2c78 0x14>; | ||
154 | interrupts = <14>; | ||
155 | clocks = <&cfgclk>; | ||
156 | clock-names = "timer"; | ||
157 | status = "disabled"; | ||
158 | }; | ||
159 | |||
160 | timer7: timer@2c8c { | ||
161 | compatible = "snps,dw-apb-timer"; | ||
162 | reg = <0x2c8c 0x14>; | ||
163 | interrupts = <15>; | ||
164 | clocks = <&cfgclk>; | ||
165 | clock-names = "timer"; | ||
166 | status = "disabled"; | ||
167 | }; | ||
168 | |||
169 | aic: interrupt-controller@3000 { | ||
170 | compatible = "snps,dw-apb-ictl"; | ||
171 | reg = <0x3000 0xc00>; | ||
172 | interrupt-controller; | ||
173 | #interrupt-cells = <1>; | ||
174 | interrupt-parent = <&gic>; | ||
175 | interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>; | ||
176 | }; | ||
177 | }; | ||
178 | |||
179 | apb@fc0000 { | ||
180 | compatible = "simple-bus"; | ||
181 | #address-cells = <1>; | ||
182 | #size-cells = <1>; | ||
183 | |||
184 | ranges = <0 0xfc0000 0x10000>; | ||
185 | interrupt-parent = <&sic>; | ||
186 | |||
187 | uart0: serial@9000 { | ||
188 | compatible = "snps,dw-apb-uart"; | ||
189 | reg = <0x9000 0x100>; | ||
190 | reg-shift = <2>; | ||
191 | reg-io-width = <1>; | ||
192 | interrupts = <8>; | ||
193 | clocks = <&smclk>; | ||
194 | status = "disabled"; | ||
195 | }; | ||
196 | |||
197 | uart1: serial@a000 { | ||
198 | compatible = "snps,dw-apb-uart"; | ||
199 | reg = <0xa000 0x100>; | ||
200 | reg-shift = <2>; | ||
201 | reg-io-width = <1>; | ||
202 | interrupts = <9>; | ||
203 | clocks = <&smclk>; | ||
204 | status = "disabled"; | ||
205 | }; | ||
206 | |||
207 | uart2: serial@b000 { | ||
208 | compatible = "snps,dw-apb-uart"; | ||
209 | reg = <0xb000 0x100>; | ||
210 | reg-shift = <2>; | ||
211 | reg-io-width = <1>; | ||
212 | interrupts = <10>; | ||
213 | clocks = <&smclk>; | ||
214 | status = "disabled"; | ||
215 | }; | ||
216 | |||
217 | sic: interrupt-controller@e000 { | ||
218 | compatible = "snps,dw-apb-ictl"; | ||
219 | reg = <0xe000 0x400>; | ||
220 | interrupt-controller; | ||
221 | #interrupt-cells = <1>; | ||
222 | interrupt-parent = <&gic>; | ||
223 | interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>; | ||
224 | }; | ||
225 | }; | ||
226 | }; | ||
227 | }; | ||
diff --git a/arch/arm/boot/dts/berlin2cd-google-chromecast.dts b/arch/arm/boot/dts/berlin2cd-google-chromecast.dts new file mode 100644 index 000000000000..bcd81ffc495d --- /dev/null +++ b/arch/arm/boot/dts/berlin2cd-google-chromecast.dts | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | * Device Tree file for Google Chromecast | ||
3 | * | ||
4 | * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public | ||
7 | * License version 2. This program is licensed "as is" without any | ||
8 | * warranty of any kind, whether express or implied. | ||
9 | */ | ||
10 | |||
11 | /dts-v1/; | ||
12 | |||
13 | #include "berlin2cd.dtsi" | ||
14 | |||
15 | / { | ||
16 | model = "Google Chromecast"; | ||
17 | compatible = "google,chromecast", "marvell,berlin2cd", "marvell,berlin"; | ||
18 | |||
19 | chosen { | ||
20 | bootargs = "console=ttyS0,115200 earlyprintk"; | ||
21 | }; | ||
22 | |||
23 | memory { | ||
24 | device_type = "memory"; | ||
25 | reg = <0x00000000 0x20000000>; /* 512 MB */ | ||
26 | }; | ||
27 | }; | ||
28 | |||
29 | &uart0 { status = "okay"; }; | ||
diff --git a/arch/arm/boot/dts/berlin2cd.dtsi b/arch/arm/boot/dts/berlin2cd.dtsi new file mode 100644 index 000000000000..094968c27533 --- /dev/null +++ b/arch/arm/boot/dts/berlin2cd.dtsi | |||
@@ -0,0 +1,210 @@ | |||
1 | /* | ||
2 | * Device Tree Include file for Marvell Armada 1500-mini (Berlin BG2CD) SoC | ||
3 | * | ||
4 | * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> | ||
5 | * | ||
6 | * based on GPL'ed 2.6 kernel sources | ||
7 | * (c) Marvell International Ltd. | ||
8 | * | ||
9 | * This file is licensed under the terms of the GNU General Public | ||
10 | * License version 2. This program is licensed "as is" without any | ||
11 | * warranty of any kind, whether express or implied. | ||
12 | */ | ||
13 | |||
14 | #include "skeleton.dtsi" | ||
15 | #include <dt-bindings/interrupt-controller/arm-gic.h> | ||
16 | |||
17 | / { | ||
18 | model = "Marvell Armada 1500-mini (BG2CD) SoC"; | ||
19 | compatible = "marvell,berlin2cd", "marvell,berlin"; | ||
20 | |||
21 | cpus { | ||
22 | #address-cells = <1>; | ||
23 | #size-cells = <0>; | ||
24 | |||
25 | cpu@0 { | ||
26 | compatible = "arm,cortex-a9"; | ||
27 | device_type = "cpu"; | ||
28 | next-level-cache = <&l2>; | ||
29 | reg = <0>; | ||
30 | }; | ||
31 | }; | ||
32 | |||
33 | clocks { | ||
34 | smclk: sysmgr-clock { | ||
35 | compatible = "fixed-clock"; | ||
36 | #clock-cells = <0>; | ||
37 | clock-frequency = <25000000>; | ||
38 | }; | ||
39 | |||
40 | cfgclk: cfg-clock { | ||
41 | compatible = "fixed-clock"; | ||
42 | #clock-cells = <0>; | ||
43 | clock-frequency = <75000000>; | ||
44 | }; | ||
45 | |||
46 | sysclk: system-clock { | ||
47 | compatible = "fixed-clock"; | ||
48 | #clock-cells = <0>; | ||
49 | clock-frequency = <300000000>; | ||
50 | }; | ||
51 | }; | ||
52 | |||
53 | soc { | ||
54 | compatible = "simple-bus"; | ||
55 | #address-cells = <1>; | ||
56 | #size-cells = <1>; | ||
57 | interrupt-parent = <&gic>; | ||
58 | |||
59 | ranges = <0 0xf7000000 0x1000000>; | ||
60 | |||
61 | l2: l2-cache-controller@ac0000 { | ||
62 | compatible = "arm,pl310-cache"; | ||
63 | reg = <0xac0000 0x1000>; | ||
64 | cache-unified; | ||
65 | cache-level = <2>; | ||
66 | }; | ||
67 | |||
68 | gic: interrupt-controller@ad1000 { | ||
69 | compatible = "arm,cortex-a9-gic"; | ||
70 | reg = <0xad1000 0x1000>, <0xad0100 0x0100>; | ||
71 | interrupt-controller; | ||
72 | #interrupt-cells = <3>; | ||
73 | }; | ||
74 | |||
75 | local-timer@ad0600 { | ||
76 | compatible = "arm,cortex-a9-twd-timer"; | ||
77 | reg = <0xad0600 0x20>; | ||
78 | interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>; | ||
79 | clocks = <&sysclk>; | ||
80 | }; | ||
81 | |||
82 | apb@e80000 { | ||
83 | compatible = "simple-bus"; | ||
84 | #address-cells = <1>; | ||
85 | #size-cells = <1>; | ||
86 | |||
87 | ranges = <0 0xe80000 0x10000>; | ||
88 | interrupt-parent = <&aic>; | ||
89 | |||
90 | timer0: timer@2c00 { | ||
91 | compatible = "snps,dw-apb-timer"; | ||
92 | reg = <0x2c00 0x14>; | ||
93 | interrupts = <8>; | ||
94 | clocks = <&cfgclk>; | ||
95 | clock-names = "timer"; | ||
96 | status = "okay"; | ||
97 | }; | ||
98 | |||
99 | timer1: timer@2c14 { | ||
100 | compatible = "snps,dw-apb-timer"; | ||
101 | reg = <0x2c14 0x14>; | ||
102 | interrupts = <9>; | ||
103 | clocks = <&cfgclk>; | ||
104 | clock-names = "timer"; | ||
105 | status = "okay"; | ||
106 | }; | ||
107 | |||
108 | timer2: timer@2c28 { | ||
109 | compatible = "snps,dw-apb-timer"; | ||
110 | reg = <0x2c28 0x14>; | ||
111 | interrupts = <10>; | ||
112 | clocks = <&cfgclk>; | ||
113 | clock-names = "timer"; | ||
114 | status = "disabled"; | ||
115 | }; | ||
116 | |||
117 | timer3: timer@2c3c { | ||
118 | compatible = "snps,dw-apb-timer"; | ||
119 | reg = <0x2c3c 0x14>; | ||
120 | interrupts = <11>; | ||
121 | clocks = <&cfgclk>; | ||
122 | clock-names = "timer"; | ||
123 | status = "disabled"; | ||
124 | }; | ||
125 | |||
126 | timer4: timer@2c50 { | ||
127 | compatible = "snps,dw-apb-timer"; | ||
128 | reg = <0x2c50 0x14>; | ||
129 | interrupts = <12>; | ||
130 | clocks = <&cfgclk>; | ||
131 | clock-names = "timer"; | ||
132 | status = "disabled"; | ||
133 | }; | ||
134 | |||
135 | timer5: timer@2c64 { | ||
136 | compatible = "snps,dw-apb-timer"; | ||
137 | reg = <0x2c64 0x14>; | ||
138 | interrupts = <13>; | ||
139 | clocks = <&cfgclk>; | ||
140 | clock-names = "timer"; | ||
141 | status = "disabled"; | ||
142 | }; | ||
143 | |||
144 | timer6: timer@2c78 { | ||
145 | compatible = "snps,dw-apb-timer"; | ||
146 | reg = <0x2c78 0x14>; | ||
147 | interrupts = <14>; | ||
148 | clocks = <&cfgclk>; | ||
149 | clock-names = "timer"; | ||
150 | status = "disabled"; | ||
151 | }; | ||
152 | |||
153 | timer7: timer@2c8c { | ||
154 | compatible = "snps,dw-apb-timer"; | ||
155 | reg = <0x2c8c 0x14>; | ||
156 | interrupts = <15>; | ||
157 | clocks = <&cfgclk>; | ||
158 | clock-names = "timer"; | ||
159 | status = "disabled"; | ||
160 | }; | ||
161 | |||
162 | aic: interrupt-controller@3000 { | ||
163 | compatible = "snps,dw-apb-ictl"; | ||
164 | reg = <0x3000 0xc00>; | ||
165 | interrupt-controller; | ||
166 | #interrupt-cells = <1>; | ||
167 | interrupt-parent = <&gic>; | ||
168 | interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>; | ||
169 | }; | ||
170 | }; | ||
171 | |||
172 | apb@fc0000 { | ||
173 | compatible = "simple-bus"; | ||
174 | #address-cells = <1>; | ||
175 | #size-cells = <1>; | ||
176 | |||
177 | ranges = <0 0xfc0000 0x10000>; | ||
178 | interrupt-parent = <&sic>; | ||
179 | |||
180 | uart0: serial@9000 { | ||
181 | compatible = "snps,dw-apb-uart"; | ||
182 | reg = <0x9000 0x100>; | ||
183 | reg-shift = <2>; | ||
184 | reg-io-width = <1>; | ||
185 | interrupts = <8>; | ||
186 | clocks = <&smclk>; | ||
187 | status = "disabled"; | ||
188 | }; | ||
189 | |||
190 | uart1: serial@a000 { | ||
191 | compatible = "snps,dw-apb-uart"; | ||
192 | reg = <0xa000 0x100>; | ||
193 | reg-shift = <2>; | ||
194 | reg-io-width = <1>; | ||
195 | interrupts = <9>; | ||
196 | clocks = <&smclk>; | ||
197 | status = "disabled"; | ||
198 | }; | ||
199 | |||
200 | sic: interrupt-controller@e000 { | ||
201 | compatible = "snps,dw-apb-ictl"; | ||
202 | reg = <0xe000 0x400>; | ||
203 | interrupt-controller; | ||
204 | #interrupt-cells = <1>; | ||
205 | interrupt-parent = <&gic>; | ||
206 | interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>; | ||
207 | }; | ||
208 | }; | ||
209 | }; | ||
210 | }; | ||
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 4a5903e04827..cce415045668 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig | |||
@@ -7,6 +7,9 @@ CONFIG_MACH_ARMADA_370=y | |||
7 | CONFIG_MACH_ARMADA_XP=y | 7 | CONFIG_MACH_ARMADA_XP=y |
8 | CONFIG_ARCH_BCM=y | 8 | CONFIG_ARCH_BCM=y |
9 | CONFIG_ARCH_BCM_MOBILE=y | 9 | CONFIG_ARCH_BCM_MOBILE=y |
10 | CONFIG_ARCH_BERLIN=y | ||
11 | CONFIG_MACH_BERLIN_BG2=y | ||
12 | CONFIG_MACH_BERLIN_BG2CD=y | ||
10 | CONFIG_GPIO_PCA953X=y | 13 | CONFIG_GPIO_PCA953X=y |
11 | CONFIG_ARCH_HIGHBANK=y | 14 | CONFIG_ARCH_HIGHBANK=y |
12 | CONFIG_ARCH_KEYSTONE=y | 15 | CONFIG_ARCH_KEYSTONE=y |
diff --git a/arch/arm/mach-berlin/Kconfig b/arch/arm/mach-berlin/Kconfig new file mode 100644 index 000000000000..7a02d222c378 --- /dev/null +++ b/arch/arm/mach-berlin/Kconfig | |||
@@ -0,0 +1,29 @@ | |||
1 | config ARCH_BERLIN | ||
2 | bool "Marvell Berlin SoCs" if ARCH_MULTI_V7 | ||
3 | select ARM_GIC | ||
4 | select GENERIC_CLOCKEVENTS | ||
5 | select GENERIC_IRQ_CHIP | ||
6 | select COMMON_CLK | ||
7 | select DW_APB_ICTL | ||
8 | select DW_APB_TIMER_OF | ||
9 | |||
10 | if ARCH_BERLIN | ||
11 | |||
12 | menu "Marvell Berlin SoC variants" | ||
13 | |||
14 | config MACH_BERLIN_BG2 | ||
15 | bool "Marvell Armada 1500 (BG2)" | ||
16 | select CACHE_L2X0 | ||
17 | select CPU_PJ4B | ||
18 | select HAVE_ARM_TWD if SMP | ||
19 | select HAVE_SMP | ||
20 | |||
21 | config MACH_BERLIN_BG2CD | ||
22 | bool "Marvell Armada 1500-mini (BG2CD)" | ||
23 | select CACHE_L2X0 | ||
24 | select CPU_V7 | ||
25 | select HAVE_ARM_TWD if SMP | ||
26 | |||
27 | endmenu | ||
28 | |||
29 | endif | ||
diff --git a/arch/arm/mach-berlin/Makefile b/arch/arm/mach-berlin/Makefile new file mode 100644 index 000000000000..ab69fe956f49 --- /dev/null +++ b/arch/arm/mach-berlin/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-y += berlin.o | |||
diff --git a/arch/arm/mach-berlin/berlin.c b/arch/arm/mach-berlin/berlin.c new file mode 100644 index 000000000000..025bcb5473eb --- /dev/null +++ b/arch/arm/mach-berlin/berlin.c | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * Device Tree support for Marvell Berlin SoCs. | ||
3 | * | ||
4 | * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> | ||
5 | * | ||
6 | * based on GPL'ed 2.6 kernel sources | ||
7 | * (c) Marvell International Ltd. | ||
8 | * | ||
9 | * This file is licensed under the terms of the GNU General Public | ||
10 | * License version 2. This program is licensed "as is" without any | ||
11 | * warranty of any kind, whether express or implied. | ||
12 | */ | ||
13 | |||
14 | #include <linux/init.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/of_platform.h> | ||
18 | #include <asm/hardware/cache-l2x0.h> | ||
19 | #include <asm/mach/arch.h> | ||
20 | |||
21 | static void __init berlin_init_machine(void) | ||
22 | { | ||
23 | /* | ||
24 | * with DT probing for L2CCs, berlin_init_machine can be removed. | ||
25 | * Note: 88DE3005 (Armada 1500-mini) uses pl310 l2cc | ||
26 | */ | ||
27 | l2x0_of_init(0x70c00000, 0xfeffffff); | ||
28 | of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); | ||
29 | } | ||
30 | |||
31 | static const char * const berlin_dt_compat[] = { | ||
32 | "marvell,berlin", | ||
33 | NULL, | ||
34 | }; | ||
35 | |||
36 | DT_MACHINE_START(BERLIN_DT, "Marvell Berlin") | ||
37 | .dt_compat = berlin_dt_compat, | ||
38 | .init_machine = berlin_init_machine, | ||
39 | MACHINE_END | ||
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 3792a1aa52b8..940638ddc982 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig | |||
@@ -30,6 +30,10 @@ config ARM_VIC_NR | |||
30 | The maximum number of VICs available in the system, for | 30 | The maximum number of VICs available in the system, for |
31 | power management. | 31 | power management. |
32 | 32 | ||
33 | config DW_APB_ICTL | ||
34 | bool | ||
35 | select IRQ_DOMAIN | ||
36 | |||
33 | config IMGPDC_IRQ | 37 | config IMGPDC_IRQ |
34 | bool | 38 | bool |
35 | select GENERIC_IRQ_CHIP | 39 | select GENERIC_IRQ_CHIP |
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index c60b9010b152..6427323af4c3 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile | |||
@@ -6,6 +6,7 @@ obj-$(CONFIG_ARCH_MMP) += irq-mmp.o | |||
6 | obj-$(CONFIG_ARCH_MVEBU) += irq-armada-370-xp.o | 6 | obj-$(CONFIG_ARCH_MVEBU) += irq-armada-370-xp.o |
7 | obj-$(CONFIG_ARCH_MXS) += irq-mxs.o | 7 | obj-$(CONFIG_ARCH_MXS) += irq-mxs.o |
8 | obj-$(CONFIG_ARCH_S3C24XX) += irq-s3c24xx.o | 8 | obj-$(CONFIG_ARCH_S3C24XX) += irq-s3c24xx.o |
9 | obj-$(CONFIG_DW_APB_ICTL) += irq-dw-apb-ictl.o | ||
9 | obj-$(CONFIG_METAG) += irq-metag-ext.o | 10 | obj-$(CONFIG_METAG) += irq-metag-ext.o |
10 | obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o | 11 | obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o |
11 | obj-$(CONFIG_ARCH_MOXART) += irq-moxart.o | 12 | obj-$(CONFIG_ARCH_MOXART) += irq-moxart.o |
diff --git a/drivers/irqchip/irq-dw-apb-ictl.c b/drivers/irqchip/irq-dw-apb-ictl.c new file mode 100644 index 000000000000..31e231e1f566 --- /dev/null +++ b/drivers/irqchip/irq-dw-apb-ictl.c | |||
@@ -0,0 +1,150 @@ | |||
1 | /* | ||
2 | * Synopsys DW APB ICTL irqchip driver. | ||
3 | * | ||
4 | * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> | ||
5 | * | ||
6 | * based on GPL'ed 2.6 kernel sources | ||
7 | * (c) Marvell International Ltd. | ||
8 | * | ||
9 | * This file is licensed under the terms of the GNU General Public | ||
10 | * License version 2. This program is licensed "as is" without any | ||
11 | * warranty of any kind, whether express or implied. | ||
12 | */ | ||
13 | |||
14 | #include <linux/io.h> | ||
15 | #include <linux/irq.h> | ||
16 | #include <linux/irqchip/chained_irq.h> | ||
17 | #include <linux/of_address.h> | ||
18 | #include <linux/of_irq.h> | ||
19 | |||
20 | #include "irqchip.h" | ||
21 | |||
22 | #define APB_INT_ENABLE_L 0x00 | ||
23 | #define APB_INT_ENABLE_H 0x04 | ||
24 | #define APB_INT_MASK_L 0x08 | ||
25 | #define APB_INT_MASK_H 0x0c | ||
26 | #define APB_INT_FINALSTATUS_L 0x30 | ||
27 | #define APB_INT_FINALSTATUS_H 0x34 | ||
28 | |||
29 | static void dw_apb_ictl_handler(unsigned int irq, struct irq_desc *desc) | ||
30 | { | ||
31 | struct irq_chip *chip = irq_get_chip(irq); | ||
32 | struct irq_chip_generic *gc = irq_get_handler_data(irq); | ||
33 | struct irq_domain *d = gc->private; | ||
34 | u32 stat; | ||
35 | int n; | ||
36 | |||
37 | chained_irq_enter(chip, desc); | ||
38 | |||
39 | for (n = 0; n < gc->num_ct; n++) { | ||
40 | stat = readl_relaxed(gc->reg_base + | ||
41 | APB_INT_FINALSTATUS_L + 4 * n); | ||
42 | while (stat) { | ||
43 | u32 hwirq = ffs(stat) - 1; | ||
44 | generic_handle_irq(irq_find_mapping(d, | ||
45 | gc->irq_base + hwirq + 32 * n)); | ||
46 | stat &= ~(1 << hwirq); | ||
47 | } | ||
48 | } | ||
49 | |||
50 | chained_irq_exit(chip, desc); | ||
51 | } | ||
52 | |||
53 | static int __init dw_apb_ictl_init(struct device_node *np, | ||
54 | struct device_node *parent) | ||
55 | { | ||
56 | unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; | ||
57 | struct resource r; | ||
58 | struct irq_domain *domain; | ||
59 | struct irq_chip_generic *gc; | ||
60 | void __iomem *iobase; | ||
61 | int ret, nrirqs, irq; | ||
62 | u32 reg; | ||
63 | |||
64 | /* Map the parent interrupt for the chained handler */ | ||
65 | irq = irq_of_parse_and_map(np, 0); | ||
66 | if (irq <= 0) { | ||
67 | pr_err("%s: unable to parse irq\n", np->full_name); | ||
68 | return -EINVAL; | ||
69 | } | ||
70 | |||
71 | ret = of_address_to_resource(np, 0, &r); | ||
72 | if (ret) { | ||
73 | pr_err("%s: unable to get resource\n", np->full_name); | ||
74 | return ret; | ||
75 | } | ||
76 | |||
77 | if (!request_mem_region(r.start, resource_size(&r), np->full_name)) { | ||
78 | pr_err("%s: unable to request mem region\n", np->full_name); | ||
79 | return -ENOMEM; | ||
80 | } | ||
81 | |||
82 | iobase = ioremap(r.start, resource_size(&r)); | ||
83 | if (!iobase) { | ||
84 | pr_err("%s: unable to map resource\n", np->full_name); | ||
85 | ret = -ENOMEM; | ||
86 | goto err_release; | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * DW IP can be configured to allow 2-64 irqs. We can determine | ||
91 | * the number of irqs supported by writing into enable register | ||
92 | * and look for bits not set, as corresponding flip-flops will | ||
93 | * have been removed by sythesis tool. | ||
94 | */ | ||
95 | |||
96 | /* mask and enable all interrupts */ | ||
97 | writel(~0, iobase + APB_INT_MASK_L); | ||
98 | writel(~0, iobase + APB_INT_MASK_H); | ||
99 | writel(~0, iobase + APB_INT_ENABLE_L); | ||
100 | writel(~0, iobase + APB_INT_ENABLE_H); | ||
101 | |||
102 | reg = readl(iobase + APB_INT_ENABLE_H); | ||
103 | if (reg) | ||
104 | nrirqs = 32 + fls(reg); | ||
105 | else | ||
106 | nrirqs = fls(readl(iobase + APB_INT_ENABLE_L)); | ||
107 | |||
108 | domain = irq_domain_add_linear(np, nrirqs, | ||
109 | &irq_generic_chip_ops, NULL); | ||
110 | if (!domain) { | ||
111 | pr_err("%s: unable to add irq domain\n", np->full_name); | ||
112 | ret = -ENOMEM; | ||
113 | goto err_unmap; | ||
114 | } | ||
115 | |||
116 | ret = irq_alloc_domain_generic_chips(domain, 32, (nrirqs > 32) ? 2 : 1, | ||
117 | np->name, handle_level_irq, clr, 0, | ||
118 | IRQ_GC_INIT_MASK_CACHE); | ||
119 | if (ret) { | ||
120 | pr_err("%s: unable to alloc irq domain gc\n", np->full_name); | ||
121 | goto err_unmap; | ||
122 | } | ||
123 | |||
124 | gc = irq_get_domain_generic_chip(domain, 0); | ||
125 | gc->private = domain; | ||
126 | gc->reg_base = iobase; | ||
127 | |||
128 | gc->chip_types[0].regs.mask = APB_INT_MASK_L; | ||
129 | gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit; | ||
130 | gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit; | ||
131 | |||
132 | if (nrirqs > 32) { | ||
133 | gc->chip_types[1].regs.mask = APB_INT_MASK_H; | ||
134 | gc->chip_types[1].chip.irq_mask = irq_gc_mask_set_bit; | ||
135 | gc->chip_types[1].chip.irq_unmask = irq_gc_mask_clr_bit; | ||
136 | } | ||
137 | |||
138 | irq_set_handler_data(irq, gc); | ||
139 | irq_set_chained_handler(irq, dw_apb_ictl_handler); | ||
140 | |||
141 | return 0; | ||
142 | |||
143 | err_unmap: | ||
144 | iounmap(iobase); | ||
145 | err_release: | ||
146 | release_mem_region(r.start, resource_size(&r)); | ||
147 | return ret; | ||
148 | } | ||
149 | IRQCHIP_DECLARE(dw_apb_ictl, | ||
150 | "snps,dw-apb-ictl", dw_apb_ictl_init); | ||