aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2014-03-09 01:53:27 -0500
committerOlof Johansson <olof@lixom.net>2014-03-09 01:53:27 -0500
commitba0e1fa928e6e7a47d54008b1a701b02a858d0e4 (patch)
tree1678c0ca4697b7e698a0a162481eca28272758a1
parentcfbf8d4857c26a8a307fb7cd258074c9dcd8c691 (diff)
parent29525484cd2524a31ee0924831ab43b46ea6ebe1 (diff)
Merge branch 'integrator/multiplatform-base' into next/cleanup2
* integrator/multiplatform-base: ARM: integrator: select GPIO block ARM: integrator: register the IM-PD1 VIC ARM: integrator: use managed resources for the IM-PD1 irqchip: support cascaded VICs irqchip: vic: update the base IRQ member correctly clk: versatile: respect parent rate in ICST clock clk: versatile: pass a parent to the ICST clock ARM: integrator: switch to fetch clocks from device tree ARM: SP804: make Integrator/CP timer pick clock from DT ARM: integrator: define clocks in the device trees
-rw-r--r--Documentation/devicetree/bindings/clock/arm-integrator.txt34
-rw-r--r--arch/arm/boot/dts/integratorap.dts35
-rw-r--r--arch/arm/boot/dts/integratorcp.dts102
-rw-r--r--arch/arm/common/timer-sp.c8
-rw-r--r--arch/arm/mach-integrator/Kconfig3
-rw-r--r--arch/arm/mach-integrator/impd1.c81
-rw-r--r--arch/arm/mach-integrator/integrator_ap.c19
-rw-r--r--arch/arm/mach-integrator/integrator_cp.c6
-rw-r--r--arch/arm/mach-versatile/core.c2
-rw-r--r--drivers/clk/versatile/clk-icst.c21
-rw-r--r--drivers/clk/versatile/clk-icst.h1
-rw-r--r--drivers/clk/versatile/clk-impd1.c6
-rw-r--r--drivers/clk/versatile/clk-integrator.c83
-rw-r--r--drivers/clk/versatile/clk-realview.c4
-rw-r--r--drivers/irqchip/irq-vic.c59
-rw-r--r--include/linux/irqchip/arm-vic.h6
-rw-r--r--include/linux/platform_data/clk-integrator.h1
17 files changed, 353 insertions, 118 deletions
diff --git a/Documentation/devicetree/bindings/clock/arm-integrator.txt b/Documentation/devicetree/bindings/clock/arm-integrator.txt
new file mode 100644
index 000000000000..652914b17b95
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/arm-integrator.txt
@@ -0,0 +1,34 @@
1Clock bindings for ARM Integrator Core Module clocks
2
3Auxilary Oscillator Clock
4
5This is a configurable clock fed from a 24 MHz chrystal,
6used for generating e.g. video clocks. It is located on the
7core module and there is only one of these.
8
9This clock node *must* be a subnode of the core module, since
10it obtains the base address for it's address range from its
11parent node.
12
13
14Required properties:
15- compatible: must be "arm,integrator-cm-auxosc"
16- #clock-cells: must be <0>
17
18Optional properties:
19- clocks: parent clock(s)
20
21Example:
22
23core-module@10000000 {
24 xtal24mhz: xtal24mhz@24M {
25 #clock-cells = <0>;
26 compatible = "fixed-clock";
27 clock-frequency = <24000000>;
28 };
29 auxosc: cm_aux_osc@25M {
30 #clock-cells = <0>;
31 compatible = "arm,integrator-cm-auxosc";
32 clocks = <&xtal24mhz>;
33 };
34};
diff --git a/arch/arm/boot/dts/integratorap.dts b/arch/arm/boot/dts/integratorap.dts
index e6be9315ff0a..b10e6351da53 100644
--- a/arch/arm/boot/dts/integratorap.dts
+++ b/arch/arm/boot/dts/integratorap.dts
@@ -18,6 +18,28 @@
18 bootargs = "root=/dev/ram0 console=ttyAM0,38400n8 earlyprintk"; 18 bootargs = "root=/dev/ram0 console=ttyAM0,38400n8 earlyprintk";
19 }; 19 };
20 20
21 /* 24 MHz chrystal on the core module */
22 xtal24mhz: xtal24mhz@24M {
23 #clock-cells = <0>;
24 compatible = "fixed-clock";
25 clock-frequency = <24000000>;
26 };
27
28 pclk: pclk@0 {
29 #clock-cells = <0>;
30 compatible = "fixed-factor-clock";
31 clock-div = <1>;
32 clock-mult = <1>;
33 clocks = <&xtal24mhz>;
34 };
35
36 /* The UART clock is 14.74 MHz divided by an ICS525 */
37 uartclk: uartclk@14.74M {
38 #clock-cells = <0>;
39 compatible = "fixed-clock";
40 clock-frequency = <14745600>;
41 };
42
21 syscon { 43 syscon {
22 compatible = "arm,integrator-ap-syscon"; 44 compatible = "arm,integrator-ap-syscon";
23 reg = <0x11000000 0x100>; 45 reg = <0x11000000 0x100>;
@@ -28,14 +50,17 @@
28 50
29 timer0: timer@13000000 { 51 timer0: timer@13000000 {
30 compatible = "arm,integrator-timer"; 52 compatible = "arm,integrator-timer";
53 clocks = <&xtal24mhz>;
31 }; 54 };
32 55
33 timer1: timer@13000100 { 56 timer1: timer@13000100 {
34 compatible = "arm,integrator-timer"; 57 compatible = "arm,integrator-timer";
58 clocks = <&xtal24mhz>;
35 }; 59 };
36 60
37 timer2: timer@13000200 { 61 timer2: timer@13000200 {
38 compatible = "arm,integrator-timer"; 62 compatible = "arm,integrator-timer";
63 clocks = <&xtal24mhz>;
39 }; 64 };
40 65
41 pic: pic@14000000 { 66 pic: pic@14000000 {
@@ -92,26 +117,36 @@
92 rtc: rtc@15000000 { 117 rtc: rtc@15000000 {
93 compatible = "arm,pl030", "arm,primecell"; 118 compatible = "arm,pl030", "arm,primecell";
94 arm,primecell-periphid = <0x00041030>; 119 arm,primecell-periphid = <0x00041030>;
120 clocks = <&pclk>;
121 clock-names = "apb_pclk";
95 }; 122 };
96 123
97 uart0: uart@16000000 { 124 uart0: uart@16000000 {
98 compatible = "arm,pl010", "arm,primecell"; 125 compatible = "arm,pl010", "arm,primecell";
99 arm,primecell-periphid = <0x00041010>; 126 arm,primecell-periphid = <0x00041010>;
127 clocks = <&uartclk>, <&pclk>;
128 clock-names = "uartclk", "apb_pclk";
100 }; 129 };
101 130
102 uart1: uart@17000000 { 131 uart1: uart@17000000 {
103 compatible = "arm,pl010", "arm,primecell"; 132 compatible = "arm,pl010", "arm,primecell";
104 arm,primecell-periphid = <0x00041010>; 133 arm,primecell-periphid = <0x00041010>;
134 clocks = <&uartclk>, <&pclk>;
135 clock-names = "uartclk", "apb_pclk";
105 }; 136 };
106 137
107 kmi0: kmi@18000000 { 138 kmi0: kmi@18000000 {
108 compatible = "arm,pl050", "arm,primecell"; 139 compatible = "arm,pl050", "arm,primecell";
109 arm,primecell-periphid = <0x00041050>; 140 arm,primecell-periphid = <0x00041050>;
141 clocks = <&xtal24mhz>, <&pclk>;
142 clock-names = "KMIREFCLK", "apb_pclk";
110 }; 143 };
111 144
112 kmi1: kmi@19000000 { 145 kmi1: kmi@19000000 {
113 compatible = "arm,pl050", "arm,primecell"; 146 compatible = "arm,pl050", "arm,primecell";
114 arm,primecell-periphid = <0x00041050>; 147 arm,primecell-periphid = <0x00041050>;
148 clocks = <&xtal24mhz>, <&pclk>;
149 clock-names = "KMIREFCLK", "apb_pclk";
115 }; 150 };
116 }; 151 };
117}; 152};
diff --git a/arch/arm/boot/dts/integratorcp.dts b/arch/arm/boot/dts/integratorcp.dts
index a21c17de9a5e..d43f15b4f79a 100644
--- a/arch/arm/boot/dts/integratorcp.dts
+++ b/arch/arm/boot/dts/integratorcp.dts
@@ -13,25 +13,107 @@
13 bootargs = "root=/dev/ram0 console=ttyAMA0,38400n8 earlyprintk"; 13 bootargs = "root=/dev/ram0 console=ttyAMA0,38400n8 earlyprintk";
14 }; 14 };
15 15
16 /*
17 * The Integrator/CP overall clocking architecture can be found in
18 * ARM DUI 0184B page 7-28 "Integrator/CP922T system clocks" which
19 * appear to illustrate the layout used in most configurations.
20 */
21
22 /* The codec chrystal operates at 24.576 MHz */
23 xtal_codec: xtal24.576@24.576M {
24 #clock-cells = <0>;
25 compatible = "fixed-clock";
26 clock-frequency = <24576000>;
27 };
28
29 /* The chrystal is divided by 2 by the codec for the AACI bit clock */
30 aaci_bitclk: aaci_bitclk@12.288M {
31 #clock-cells = <0>;
32 compatible = "fixed-factor-clock";
33 clock-div = <2>;
34 clock-mult = <1>;
35 clocks = <&xtal_codec>;
36 };
37
38 /* This is a 25MHz chrystal on the base board */
39 xtal25mhz: xtal25mhz@25M {
40 #clock-cells = <0>;
41 compatible = "fixed-clock";
42 clock-frequency = <25000000>;
43 };
44
45 /* The UART clock is 14.74 MHz divided from 25MHz by an ICS525 */
46 uartclk: uartclk@14.74M {
47 #clock-cells = <0>;
48 compatible = "fixed-clock";
49 clock-frequency = <14745600>;
50 };
51
52 /* Actually sysclk I think */
53 pclk: pclk@0 {
54 #clock-cells = <0>;
55 compatible = "fixed-clock";
56 clock-frequency = <0>;
57 };
58
59 core-module@10000000 {
60 /* 24 MHz chrystal on the core module */
61 xtal24mhz: xtal24mhz@24M {
62 #clock-cells = <0>;
63 compatible = "fixed-clock";
64 clock-frequency = <24000000>;
65 };
66
67 /*
68 * External oscillator on the core module, usually used
69 * to drive video circuitry. Driven from the 24MHz clock.
70 */
71 auxosc: cm_aux_osc@25M {
72 #clock-cells = <0>;
73 compatible = "arm,integrator-cm-auxosc";
74 clocks = <&xtal24mhz>;
75 };
76
77 /* The KMI clock is the 24 MHz oscillator divided to 8MHz */
78 kmiclk: kmiclk@1M {
79 #clock-cells = <0>;
80 compatible = "fixed-factor-clock";
81 clock-div = <3>;
82 clock-mult = <1>;
83 clocks = <&xtal24mhz>;
84 };
85
86 /* The timer clock is the 24 MHz oscillator divided to 1MHz */
87 timclk: timclk@1M {
88 #clock-cells = <0>;
89 compatible = "fixed-factor-clock";
90 clock-div = <24>;
91 clock-mult = <1>;
92 clocks = <&xtal24mhz>;
93 };
94 };
95
16 syscon { 96 syscon {
17 compatible = "arm,integrator-cp-syscon"; 97 compatible = "arm,integrator-cp-syscon";
18 reg = <0xcb000000 0x100>; 98 reg = <0xcb000000 0x100>;
19 }; 99 };
20 100
21 timer0: timer@13000000 { 101 timer0: timer@13000000 {
22 /* TIMER0 runs @ 25MHz */ 102 /* TIMER0 runs directly on the 25MHz chrystal */
23 compatible = "arm,integrator-cp-timer"; 103 compatible = "arm,integrator-cp-timer";
24 status = "disabled"; 104 clocks = <&xtal25mhz>;
25 }; 105 };
26 106
27 timer1: timer@13000100 { 107 timer1: timer@13000100 {
28 /* TIMER1 runs @ 1MHz */ 108 /* TIMER1 runs @ 1MHz */
29 compatible = "arm,integrator-cp-timer"; 109 compatible = "arm,integrator-cp-timer";
110 clocks = <&timclk>;
30 }; 111 };
31 112
32 timer2: timer@13000200 { 113 timer2: timer@13000200 {
33 /* TIMER2 runs @ 1MHz */ 114 /* TIMER2 runs @ 1MHz */
34 compatible = "arm,integrator-cp-timer"; 115 compatible = "arm,integrator-cp-timer";
116 clocks = <&timclk>;
35 }; 117 };
36 118
37 pic: pic@14000000 { 119 pic: pic@14000000 {
@@ -74,22 +156,32 @@
74 */ 156 */
75 rtc@15000000 { 157 rtc@15000000 {
76 compatible = "arm,pl031", "arm,primecell"; 158 compatible = "arm,pl031", "arm,primecell";
159 clocks = <&pclk>;
160 clock-names = "apb_pclk";
77 }; 161 };
78 162
79 uart@16000000 { 163 uart@16000000 {
80 compatible = "arm,pl011", "arm,primecell"; 164 compatible = "arm,pl011", "arm,primecell";
165 clocks = <&uartclk>, <&pclk>;
166 clock-names = "uartclk", "apb_pclk";
81 }; 167 };
82 168
83 uart@17000000 { 169 uart@17000000 {
84 compatible = "arm,pl011", "arm,primecell"; 170 compatible = "arm,pl011", "arm,primecell";
171 clocks = <&uartclk>, <&pclk>;
172 clock-names = "uartclk", "apb_pclk";
85 }; 173 };
86 174
87 kmi@18000000 { 175 kmi@18000000 {
88 compatible = "arm,pl050", "arm,primecell"; 176 compatible = "arm,pl050", "arm,primecell";
177 clocks = <&kmiclk>, <&pclk>;
178 clock-names = "KMIREFCLK", "apb_pclk";
89 }; 179 };
90 180
91 kmi@19000000 { 181 kmi@19000000 {
92 compatible = "arm,pl050", "arm,primecell"; 182 compatible = "arm,pl050", "arm,primecell";
183 clocks = <&kmiclk>, <&pclk>;
184 clock-names = "KMIREFCLK", "apb_pclk";
93 }; 185 };
94 186
95 /* 187 /*
@@ -100,18 +192,24 @@
100 reg = <0x1c000000 0x1000>; 192 reg = <0x1c000000 0x1000>;
101 interrupts = <23 24>; 193 interrupts = <23 24>;
102 max-frequency = <515633>; 194 max-frequency = <515633>;
195 clocks = <&uartclk>, <&pclk>;
196 clock-names = "mclk", "apb_pclk";
103 }; 197 };
104 198
105 aaci@1d000000 { 199 aaci@1d000000 {
106 compatible = "arm,pl041", "arm,primecell"; 200 compatible = "arm,pl041", "arm,primecell";
107 reg = <0x1d000000 0x1000>; 201 reg = <0x1d000000 0x1000>;
108 interrupts = <25>; 202 interrupts = <25>;
203 clocks = <&pclk>;
204 clock-names = "apb_pclk";
109 }; 205 };
110 206
111 clcd@c0000000 { 207 clcd@c0000000 {
112 compatible = "arm,pl110", "arm,primecell"; 208 compatible = "arm,pl110", "arm,primecell";
113 reg = <0xC0000000 0x1000>; 209 reg = <0xC0000000 0x1000>;
114 interrupts = <22>; 210 interrupts = <22>;
211 clocks = <&auxosc>, <&pclk>;
212 clock-names = "clcd", "apb_pclk";
115 }; 213 };
116 }; 214 };
117}; 215};
diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c
index 53c6a26b633d..fd6bff0c5b96 100644
--- a/arch/arm/common/timer-sp.c
+++ b/arch/arm/common/timer-sp.c
@@ -271,10 +271,14 @@ static void __init integrator_cp_of_init(struct device_node *np)
271 void __iomem *base; 271 void __iomem *base;
272 int irq; 272 int irq;
273 const char *name = of_get_property(np, "compatible", NULL); 273 const char *name = of_get_property(np, "compatible", NULL);
274 struct clk *clk;
274 275
275 base = of_iomap(np, 0); 276 base = of_iomap(np, 0);
276 if (WARN_ON(!base)) 277 if (WARN_ON(!base))
277 return; 278 return;
279 clk = of_clk_get(np, 0);
280 if (WARN_ON(IS_ERR(clk)))
281 return;
278 282
279 /* Ensure timer is disabled */ 283 /* Ensure timer is disabled */
280 writel(0, base + TIMER_CTRL); 284 writel(0, base + TIMER_CTRL);
@@ -283,13 +287,13 @@ static void __init integrator_cp_of_init(struct device_node *np)
283 goto err; 287 goto err;
284 288
285 if (!init_count) 289 if (!init_count)
286 sp804_clocksource_init(base, name); 290 __sp804_clocksource_and_sched_clock_init(base, name, clk, 0);
287 else { 291 else {
288 irq = irq_of_parse_and_map(np, 0); 292 irq = irq_of_parse_and_map(np, 0);
289 if (irq <= 0) 293 if (irq <= 0)
290 goto err; 294 goto err;
291 295
292 sp804_clockevents_init(base, irq, name); 296 __sp804_clockevents_init(base, irq, clk, name);
293 } 297 }
294 298
295 init_count++; 299 init_count++;
diff --git a/arch/arm/mach-integrator/Kconfig b/arch/arm/mach-integrator/Kconfig
index abeff25532ab..6e8b0e10b420 100644
--- a/arch/arm/mach-integrator/Kconfig
+++ b/arch/arm/mach-integrator/Kconfig
@@ -30,6 +30,9 @@ config ARCH_CINTEGRATOR
30config INTEGRATOR_IMPD1 30config INTEGRATOR_IMPD1
31 tristate "Include support for Integrator/IM-PD1" 31 tristate "Include support for Integrator/IM-PD1"
32 depends on ARCH_INTEGRATOR_AP 32 depends on ARCH_INTEGRATOR_AP
33 select ARCH_REQUIRE_GPIOLIB
34 select ARM_VIC
35 select GPIO_PL061 if GPIOLIB
33 help 36 help
34 The IM-PD1 is an add-on logic module for the Integrator which 37 The IM-PD1 is an add-on logic module for the Integrator which
35 allows ARM(R) Ltd PrimeCells to be developed and evaluated. 38 allows ARM(R) Ltd PrimeCells to be developed and evaluated.
diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c
index 9f82f9dcbb98..d9b784824808 100644
--- a/arch/arm/mach-integrator/impd1.c
+++ b/arch/arm/mach-integrator/impd1.c
@@ -23,6 +23,7 @@
23#include <linux/io.h> 23#include <linux/io.h>
24#include <linux/platform_data/clk-integrator.h> 24#include <linux/platform_data/clk-integrator.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/irqchip/arm-vic.h>
26 27
27#include <mach/lm.h> 28#include <mach/lm.h>
28#include <mach/impd1.h> 29#include <mach/impd1.h>
@@ -35,6 +36,7 @@ MODULE_PARM_DESC(lmid, "logic module stack position");
35 36
36struct impd1_module { 37struct impd1_module {
37 void __iomem *base; 38 void __iomem *base;
39 void __iomem *vic_base;
38}; 40};
39 41
40void impd1_tweak_control(struct device *dev, u32 mask, u32 val) 42void impd1_tweak_control(struct device *dev, u32 mask, u32 val)
@@ -262,9 +264,6 @@ struct impd1_device {
262 264
263static struct impd1_device impd1_devs[] = { 265static struct impd1_device impd1_devs[] = {
264 { 266 {
265 .offset = 0x03000000,
266 .id = 0x00041190,
267 }, {
268 .offset = 0x00100000, 267 .offset = 0x00100000,
269 .irq = { 1 }, 268 .irq = { 1 },
270 .id = 0x00141011, 269 .id = 0x00141011,
@@ -304,46 +303,72 @@ static struct impd1_device impd1_devs[] = {
304 } 303 }
305}; 304};
306 305
307static int impd1_probe(struct lm_device *dev) 306/*
307 * Valid IRQs: 0 thru 9 and 11, 10 unused.
308 */
309#define IMPD1_VALID_IRQS 0x00000bffU
310
311static int __init impd1_probe(struct lm_device *dev)
308{ 312{
309 struct impd1_module *impd1; 313 struct impd1_module *impd1;
310 int i, ret; 314 int irq_base;
315 int i;
311 316
312 if (dev->id != module_id) 317 if (dev->id != module_id)
313 return -EINVAL; 318 return -EINVAL;
314 319
315 if (!request_mem_region(dev->resource.start, SZ_4K, "LM registers")) 320 if (!devm_request_mem_region(&dev->dev, dev->resource.start,
321 SZ_4K, "LM registers"))
316 return -EBUSY; 322 return -EBUSY;
317 323
318 impd1 = kzalloc(sizeof(struct impd1_module), GFP_KERNEL); 324 impd1 = devm_kzalloc(&dev->dev, sizeof(struct impd1_module),
319 if (!impd1) { 325 GFP_KERNEL);
320 ret = -ENOMEM; 326 if (!impd1)
321 goto release_lm; 327 return -ENOMEM;
322 }
323 328
324 impd1->base = ioremap(dev->resource.start, SZ_4K); 329 impd1->base = devm_ioremap(&dev->dev, dev->resource.start, SZ_4K);
325 if (!impd1->base) { 330 if (!impd1->base)
326 ret = -ENOMEM; 331 return -ENOMEM;
327 goto free_impd1;
328 }
329 332
330 lm_set_drvdata(dev, impd1); 333 integrator_impd1_clk_init(impd1->base, dev->id);
331 334
332 printk("IM-PD1 found at 0x%08lx\n", 335 if (!devm_request_mem_region(&dev->dev,
333 (unsigned long)dev->resource.start); 336 dev->resource.start + 0x03000000,
337 SZ_4K, "VIC"))
338 return -EBUSY;
334 339
335 integrator_impd1_clk_init(impd1->base, dev->id); 340 impd1->vic_base = devm_ioremap(&dev->dev,
341 dev->resource.start + 0x03000000,
342 SZ_4K);
343 if (!impd1->vic_base)
344 return -ENOMEM;
345
346 irq_base = vic_init_cascaded(impd1->vic_base, dev->irq,
347 IMPD1_VALID_IRQS, 0);
348
349 lm_set_drvdata(dev, impd1);
350
351 dev_info(&dev->dev, "IM-PD1 found at 0x%08lx\n",
352 (unsigned long)dev->resource.start);
336 353
337 for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) { 354 for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) {
338 struct impd1_device *idev = impd1_devs + i; 355 struct impd1_device *idev = impd1_devs + i;
339 struct amba_device *d; 356 struct amba_device *d;
340 unsigned long pc_base; 357 unsigned long pc_base;
341 char devname[32]; 358 char devname[32];
359 int irq1 = idev->irq[0];
360 int irq2 = idev->irq[1];
361
362 /* Translate IRQs to IM-PD1 local numberspace */
363 if (irq1)
364 irq1 += irq_base;
365 if (irq2)
366 irq2 += irq_base;
342 367
343 pc_base = dev->resource.start + idev->offset; 368 pc_base = dev->resource.start + idev->offset;
344 snprintf(devname, 32, "lm%x:%5.5lx", dev->id, idev->offset >> 12); 369 snprintf(devname, 32, "lm%x:%5.5lx", dev->id, idev->offset >> 12);
345 d = amba_ahb_device_add_res(&dev->dev, devname, pc_base, SZ_4K, 370 d = amba_ahb_device_add_res(&dev->dev, devname, pc_base, SZ_4K,
346 dev->irq, dev->irq, 371 irq1, irq2,
347 idev->platform_data, idev->id, 372 idev->platform_data, idev->id,
348 &dev->resource); 373 &dev->resource);
349 if (IS_ERR(d)) { 374 if (IS_ERR(d)) {
@@ -353,14 +378,6 @@ static int impd1_probe(struct lm_device *dev)
353 } 378 }
354 379
355 return 0; 380 return 0;
356
357 free_impd1:
358 if (impd1 && impd1->base)
359 iounmap(impd1->base);
360 kfree(impd1);
361 release_lm:
362 release_mem_region(dev->resource.start, SZ_4K);
363 return ret;
364} 381}
365 382
366static int impd1_remove_one(struct device *dev, void *data) 383static int impd1_remove_one(struct device *dev, void *data)
@@ -371,16 +388,10 @@ static int impd1_remove_one(struct device *dev, void *data)
371 388
372static void impd1_remove(struct lm_device *dev) 389static void impd1_remove(struct lm_device *dev)
373{ 390{
374 struct impd1_module *impd1 = lm_get_drvdata(dev);
375
376 device_for_each_child(&dev->dev, NULL, impd1_remove_one); 391 device_for_each_child(&dev->dev, NULL, impd1_remove_one);
377 integrator_impd1_clk_exit(dev->id); 392 integrator_impd1_clk_exit(dev->id);
378 393
379 lm_set_drvdata(dev, NULL); 394 lm_set_drvdata(dev, NULL);
380
381 iounmap(impd1->base);
382 kfree(impd1);
383 release_mem_region(dev->resource.start, SZ_4K);
384} 395}
385 396
386static struct lm_driver impd1_driver = { 397static struct lm_driver impd1_driver = {
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index 17c0fe627435..fedcd2fab094 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -42,6 +42,7 @@
42#include <linux/sys_soc.h> 42#include <linux/sys_soc.h>
43#include <linux/termios.h> 43#include <linux/termios.h>
44#include <linux/sched_clock.h> 44#include <linux/sched_clock.h>
45#include <linux/clk-provider.h>
45 46
46#include <mach/hardware.h> 47#include <mach/hardware.h>
47#include <mach/platform.h> 48#include <mach/platform.h>
@@ -402,10 +403,7 @@ static void __init ap_of_timer_init(void)
402 struct clk *clk; 403 struct clk *clk;
403 unsigned long rate; 404 unsigned long rate;
404 405
405 clk = clk_get_sys("ap_timer", NULL); 406 of_clk_init(NULL);
406 BUG_ON(IS_ERR(clk));
407 clk_prepare_enable(clk);
408 rate = clk_get_rate(clk);
409 407
410 err = of_property_read_string(of_aliases, 408 err = of_property_read_string(of_aliases,
411 "arm,timer-primary", &path); 409 "arm,timer-primary", &path);
@@ -415,6 +413,12 @@ static void __init ap_of_timer_init(void)
415 base = of_iomap(node, 0); 413 base = of_iomap(node, 0);
416 if (WARN_ON(!base)) 414 if (WARN_ON(!base))
417 return; 415 return;
416
417 clk = of_clk_get(node, 0);
418 BUG_ON(IS_ERR(clk));
419 clk_prepare_enable(clk);
420 rate = clk_get_rate(clk);
421
418 writel(0, base + TIMER_CTRL); 422 writel(0, base + TIMER_CTRL);
419 integrator_clocksource_init(rate, base); 423 integrator_clocksource_init(rate, base);
420 424
@@ -427,6 +431,12 @@ static void __init ap_of_timer_init(void)
427 if (WARN_ON(!base)) 431 if (WARN_ON(!base))
428 return; 432 return;
429 irq = irq_of_parse_and_map(node, 0); 433 irq = irq_of_parse_and_map(node, 0);
434
435 clk = of_clk_get(node, 0);
436 BUG_ON(IS_ERR(clk));
437 clk_prepare_enable(clk);
438 rate = clk_get_rate(clk);
439
430 writel(0, base + TIMER_CTRL); 440 writel(0, base + TIMER_CTRL);
431 integrator_clockevent_init(rate, base, irq); 441 integrator_clockevent_init(rate, base, irq);
432} 442}
@@ -440,7 +450,6 @@ static void __init ap_init_irq_of(void)
440{ 450{
441 cm_init(); 451 cm_init();
442 of_irq_init(fpga_irq_of_match); 452 of_irq_init(fpga_irq_of_match);
443 integrator_clk_init(false);
444} 453}
445 454
446/* For the Device Tree, add in the UART callbacks as AUXDATA */ 455/* For the Device Tree, add in the UART callbacks as AUXDATA */
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index a3ef961e4a93..0ad5f60598c8 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -23,7 +23,6 @@
23#include <linux/irqchip/versatile-fpga.h> 23#include <linux/irqchip/versatile-fpga.h>
24#include <linux/gfp.h> 24#include <linux/gfp.h>
25#include <linux/mtd/physmap.h> 25#include <linux/mtd/physmap.h>
26#include <linux/platform_data/clk-integrator.h>
27#include <linux/of_irq.h> 26#include <linux/of_irq.h>
28#include <linux/of_address.h> 27#include <linux/of_address.h>
29#include <linux/of_platform.h> 28#include <linux/of_platform.h>
@@ -33,8 +32,6 @@
33#include <mach/platform.h> 32#include <mach/platform.h>
34#include <asm/setup.h> 33#include <asm/setup.h>
35#include <asm/mach-types.h> 34#include <asm/mach-types.h>
36#include <asm/hardware/arm_timer.h>
37#include <asm/hardware/icst.h>
38 35
39#include <mach/lm.h> 36#include <mach/lm.h>
40 37
@@ -43,8 +40,6 @@
43#include <asm/mach/map.h> 40#include <asm/mach/map.h>
44#include <asm/mach/time.h> 41#include <asm/mach/time.h>
45 42
46#include <asm/hardware/timer-sp.h>
47
48#include <plat/clcd.h> 43#include <plat/clcd.h>
49#include <plat/sched_clock.h> 44#include <plat/sched_clock.h>
50 45
@@ -250,7 +245,6 @@ static void __init intcp_init_irq_of(void)
250{ 245{
251 cm_init(); 246 cm_init();
252 of_irq_init(fpga_irq_of_match); 247 of_irq_init(fpga_irq_of_match);
253 integrator_clk_init(true);
254} 248}
255 249
256/* 250/*
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index a335126ae18f..f2c89fb8fca9 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -108,7 +108,7 @@ void __init versatile_init_irq(void)
108 108
109 np = of_find_matching_node_by_address(NULL, vic_of_match, 109 np = of_find_matching_node_by_address(NULL, vic_of_match,
110 VERSATILE_VIC_BASE); 110 VERSATILE_VIC_BASE);
111 __vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0, np); 111 __vic_init(VA_VIC_BASE, 0, IRQ_VIC_START, ~0, 0, np);
112 112
113 writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR); 113 writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
114 114
diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c
index 8cbfcf88fae3..a820b0cfcf57 100644
--- a/drivers/clk/versatile/clk-icst.c
+++ b/drivers/clk/versatile/clk-icst.c
@@ -33,7 +33,7 @@ struct clk_icst {
33 struct clk_hw hw; 33 struct clk_hw hw;
34 void __iomem *vcoreg; 34 void __iomem *vcoreg;
35 void __iomem *lockreg; 35 void __iomem *lockreg;
36 const struct icst_params *params; 36 struct icst_params *params;
37 unsigned long rate; 37 unsigned long rate;
38}; 38};
39 39
@@ -84,6 +84,8 @@ static unsigned long icst_recalc_rate(struct clk_hw *hw,
84 struct clk_icst *icst = to_icst(hw); 84 struct clk_icst *icst = to_icst(hw);
85 struct icst_vco vco; 85 struct icst_vco vco;
86 86
87 if (parent_rate)
88 icst->params->ref = parent_rate;
87 vco = vco_get(icst->vcoreg); 89 vco = vco_get(icst->vcoreg);
88 icst->rate = icst_hz(icst->params, vco); 90 icst->rate = icst_hz(icst->params, vco);
89 return icst->rate; 91 return icst->rate;
@@ -105,6 +107,8 @@ static int icst_set_rate(struct clk_hw *hw, unsigned long rate,
105 struct clk_icst *icst = to_icst(hw); 107 struct clk_icst *icst = to_icst(hw);
106 struct icst_vco vco; 108 struct icst_vco vco;
107 109
110 if (parent_rate)
111 icst->params->ref = parent_rate;
108 vco = icst_hz_to_vco(icst->params, rate); 112 vco = icst_hz_to_vco(icst->params, rate);
109 icst->rate = icst_hz(icst->params, vco); 113 icst->rate = icst_hz(icst->params, vco);
110 vco_set(icst->lockreg, icst->vcoreg, vco); 114 vco_set(icst->lockreg, icst->vcoreg, vco);
@@ -120,24 +124,33 @@ static const struct clk_ops icst_ops = {
120struct clk *icst_clk_register(struct device *dev, 124struct clk *icst_clk_register(struct device *dev,
121 const struct clk_icst_desc *desc, 125 const struct clk_icst_desc *desc,
122 const char *name, 126 const char *name,
127 const char *parent_name,
123 void __iomem *base) 128 void __iomem *base)
124{ 129{
125 struct clk *clk; 130 struct clk *clk;
126 struct clk_icst *icst; 131 struct clk_icst *icst;
127 struct clk_init_data init; 132 struct clk_init_data init;
133 struct icst_params *pclone;
128 134
129 icst = kzalloc(sizeof(struct clk_icst), GFP_KERNEL); 135 icst = kzalloc(sizeof(struct clk_icst), GFP_KERNEL);
130 if (!icst) { 136 if (!icst) {
131 pr_err("could not allocate ICST clock!\n"); 137 pr_err("could not allocate ICST clock!\n");
132 return ERR_PTR(-ENOMEM); 138 return ERR_PTR(-ENOMEM);
133 } 139 }
140
141 pclone = kmemdup(desc->params, sizeof(*pclone), GFP_KERNEL);
142 if (!pclone) {
143 pr_err("could not clone ICST params\n");
144 return ERR_PTR(-ENOMEM);
145 }
146
134 init.name = name; 147 init.name = name;
135 init.ops = &icst_ops; 148 init.ops = &icst_ops;
136 init.flags = CLK_IS_ROOT; 149 init.flags = CLK_IS_ROOT;
137 init.parent_names = NULL; 150 init.parent_names = (parent_name ? &parent_name : NULL);
138 init.num_parents = 0; 151 init.num_parents = (parent_name ? 1 : 0);
139 icst->hw.init = &init; 152 icst->hw.init = &init;
140 icst->params = desc->params; 153 icst->params = pclone;
141 icst->vcoreg = base + desc->vco_offset; 154 icst->vcoreg = base + desc->vco_offset;
142 icst->lockreg = base + desc->lock_offset; 155 icst->lockreg = base + desc->lock_offset;
143 156
diff --git a/drivers/clk/versatile/clk-icst.h b/drivers/clk/versatile/clk-icst.h
index be99dd0da785..04e6f0aef588 100644
--- a/drivers/clk/versatile/clk-icst.h
+++ b/drivers/clk/versatile/clk-icst.h
@@ -16,4 +16,5 @@ struct clk_icst_desc {
16struct clk *icst_clk_register(struct device *dev, 16struct clk *icst_clk_register(struct device *dev,
17 const struct clk_icst_desc *desc, 17 const struct clk_icst_desc *desc,
18 const char *name, 18 const char *name,
19 const char *parent_name,
19 void __iomem *base); 20 void __iomem *base);
diff --git a/drivers/clk/versatile/clk-impd1.c b/drivers/clk/versatile/clk-impd1.c
index 844f8d711a12..6d8b8e1a080a 100644
--- a/drivers/clk/versatile/clk-impd1.c
+++ b/drivers/clk/versatile/clk-impd1.c
@@ -93,13 +93,15 @@ void integrator_impd1_clk_init(void __iomem *base, unsigned int id)
93 imc = &impd1_clks[id]; 93 imc = &impd1_clks[id];
94 94
95 imc->vco1name = kasprintf(GFP_KERNEL, "lm%x-vco1", id); 95 imc->vco1name = kasprintf(GFP_KERNEL, "lm%x-vco1", id);
96 clk = icst_clk_register(NULL, &impd1_icst1_desc, imc->vco1name, base); 96 clk = icst_clk_register(NULL, &impd1_icst1_desc, imc->vco1name, NULL,
97 base);
97 imc->vco1clk = clk; 98 imc->vco1clk = clk;
98 imc->clks[0] = clkdev_alloc(clk, NULL, "lm%x:01000", id); 99 imc->clks[0] = clkdev_alloc(clk, NULL, "lm%x:01000", id);
99 100
100 /* VCO2 is also called "CLK2" */ 101 /* VCO2 is also called "CLK2" */
101 imc->vco2name = kasprintf(GFP_KERNEL, "lm%x-vco2", id); 102 imc->vco2name = kasprintf(GFP_KERNEL, "lm%x-vco2", id);
102 clk = icst_clk_register(NULL, &impd1_icst2_desc, imc->vco2name, base); 103 clk = icst_clk_register(NULL, &impd1_icst2_desc, imc->vco2name, NULL,
104 base);
103 imc->vco2clk = clk; 105 imc->vco2clk = clk;
104 106
105 /* MMCI uses CLK2 right off */ 107 /* MMCI uses CLK2 right off */
diff --git a/drivers/clk/versatile/clk-integrator.c b/drivers/clk/versatile/clk-integrator.c
index bda8967e09c2..734c4b8fe6ab 100644
--- a/drivers/clk/versatile/clk-integrator.c
+++ b/drivers/clk/versatile/clk-integrator.c
@@ -10,21 +10,17 @@
10#include <linux/clk.h> 10#include <linux/clk.h>
11#include <linux/clkdev.h> 11#include <linux/clkdev.h>
12#include <linux/err.h> 12#include <linux/err.h>
13#include <linux/platform_data/clk-integrator.h> 13#include <linux/of.h>
14 14#include <linux/of_address.h>
15#include <mach/hardware.h>
16#include <mach/platform.h>
17 15
18#include "clk-icst.h" 16#include "clk-icst.h"
19 17
20/* 18#define INTEGRATOR_HDR_LOCK_OFFSET 0x14
21 * Implementation of the ARM Integrator/AP and Integrator/CP clock tree.
22 * Inspired by portions of:
23 * plat-versatile/clock.c and plat-versatile/include/plat/clock.h
24 */
25 19
26static const struct icst_params cp_auxvco_params = { 20/* Base offset for the core module */
27 .ref = 24000000, 21static void __iomem *cm_base;
22
23static const struct icst_params cp_auxosc_params = {
28 .vco_max = ICST525_VCO_MAX_5V, 24 .vco_max = ICST525_VCO_MAX_5V,
29 .vco_min = ICST525_VCO_MIN, 25 .vco_min = ICST525_VCO_MIN,
30 .vd_min = 8, 26 .vd_min = 8,
@@ -35,50 +31,39 @@ static const struct icst_params cp_auxvco_params = {
35 .idx2s = icst525_idx2s, 31 .idx2s = icst525_idx2s,
36}; 32};
37 33
38static const struct clk_icst_desc __initdata cp_icst_desc = { 34static const struct clk_icst_desc __initdata cm_auxosc_desc = {
39 .params = &cp_auxvco_params, 35 .params = &cp_auxosc_params,
40 .vco_offset = 0x1c, 36 .vco_offset = 0x1c,
41 .lock_offset = INTEGRATOR_HDR_LOCK_OFFSET, 37 .lock_offset = INTEGRATOR_HDR_LOCK_OFFSET,
42}; 38};
43 39
44/* 40static void __init of_integrator_cm_osc_setup(struct device_node *np)
45 * integrator_clk_init() - set up the integrator clock tree
46 * @is_cp: pass true if it's the Integrator/CP else AP is assumed
47 */
48void __init integrator_clk_init(bool is_cp)
49{ 41{
50 struct clk *clk; 42 struct clk *clk = ERR_PTR(-EINVAL);
51 43 const char *clk_name = np->name;
52 /* APB clock dummy */ 44 const struct clk_icst_desc *desc = &cm_auxosc_desc;
53 clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0); 45 const char *parent_name;
54 clk_register_clkdev(clk, "apb_pclk", NULL);
55
56 /* UART reference clock */
57 clk = clk_register_fixed_rate(NULL, "uartclk", NULL, CLK_IS_ROOT,
58 14745600);
59 clk_register_clkdev(clk, NULL, "uart0");
60 clk_register_clkdev(clk, NULL, "uart1");
61 if (is_cp)
62 clk_register_clkdev(clk, NULL, "mmci");
63
64 /* 24 MHz clock */
65 clk = clk_register_fixed_rate(NULL, "clk24mhz", NULL, CLK_IS_ROOT,
66 24000000);
67 clk_register_clkdev(clk, NULL, "kmi0");
68 clk_register_clkdev(clk, NULL, "kmi1");
69 if (!is_cp)
70 clk_register_clkdev(clk, NULL, "ap_timer");
71 46
72 if (!is_cp) 47 if (!cm_base) {
73 return; 48 /* Remap the core module base if not done yet */
49 struct device_node *parent;
74 50
75 /* 1 MHz clock */ 51 parent = of_get_parent(np);
76 clk = clk_register_fixed_rate(NULL, "clk1mhz", NULL, CLK_IS_ROOT, 52 if (!np) {
77 1000000); 53 pr_err("no parent on core module clock\n");
78 clk_register_clkdev(clk, NULL, "sp804"); 54 return;
55 }
56 cm_base = of_iomap(parent, 0);
57 if (!cm_base) {
58 pr_err("could not remap core module base\n");
59 return;
60 }
61 }
79 62
80 /* ICST VCO clock used on the Integrator/CP CLCD */ 63 parent_name = of_clk_get_parent_name(np, 0);
81 clk = icst_clk_register(NULL, &cp_icst_desc, "icst", 64 clk = icst_clk_register(NULL, desc, clk_name, parent_name, cm_base);
82 __io_address(INTEGRATOR_HDR_BASE)); 65 if (!IS_ERR(clk))
83 clk_register_clkdev(clk, NULL, "clcd"); 66 of_clk_add_provider(np, of_clk_src_simple_get, clk);
84} 67}
68CLK_OF_DECLARE(integrator_cm_auxosc_clk,
69 "arm,integrator-cm-auxosc", of_integrator_cm_osc_setup);
diff --git a/drivers/clk/versatile/clk-realview.c b/drivers/clk/versatile/clk-realview.c
index 747e7b31117c..c8b523117fb7 100644
--- a/drivers/clk/versatile/clk-realview.c
+++ b/drivers/clk/versatile/clk-realview.c
@@ -85,10 +85,10 @@ void __init realview_clk_init(void __iomem *sysbase, bool is_pb1176)
85 /* ICST VCO clock */ 85 /* ICST VCO clock */
86 if (is_pb1176) 86 if (is_pb1176)
87 clk = icst_clk_register(NULL, &realview_osc0_desc, 87 clk = icst_clk_register(NULL, &realview_osc0_desc,
88 "osc0", sysbase); 88 "osc0", NULL, sysbase);
89 else 89 else
90 clk = icst_clk_register(NULL, &realview_osc4_desc, 90 clk = icst_clk_register(NULL, &realview_osc4_desc,
91 "osc4", sysbase); 91 "osc4", NULL, sysbase);
92 92
93 clk_register_clkdev(clk, NULL, "dev:clcd"); 93 clk_register_clkdev(clk, NULL, "dev:clcd");
94 clk_register_clkdev(clk, NULL, "issp:clcd"); 94 clk_register_clkdev(clk, NULL, "issp:clcd");
diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c
index 8e21ae0bab46..6002942a231c 100644
--- a/drivers/irqchip/irq-vic.c
+++ b/drivers/irqchip/irq-vic.c
@@ -57,6 +57,7 @@
57 57
58/** 58/**
59 * struct vic_device - VIC PM device 59 * struct vic_device - VIC PM device
60 * @parent_irq: The parent IRQ number of the VIC if cascaded, or 0.
60 * @irq: The IRQ number for the base of the VIC. 61 * @irq: The IRQ number for the base of the VIC.
61 * @base: The register base for the VIC. 62 * @base: The register base for the VIC.
62 * @valid_sources: A bitmask of valid interrupts 63 * @valid_sources: A bitmask of valid interrupts
@@ -224,6 +225,17 @@ static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
224 return handled; 225 return handled;
225} 226}
226 227
228static void vic_handle_irq_cascaded(unsigned int irq, struct irq_desc *desc)
229{
230 u32 stat, hwirq;
231 struct vic_device *vic = irq_desc_get_handler_data(desc);
232
233 while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) {
234 hwirq = ffs(stat) - 1;
235 generic_handle_irq(irq_find_mapping(vic->domain, hwirq));
236 }
237}
238
227/* 239/*
228 * Keep iterating over all registered VIC's until there are no pending 240 * Keep iterating over all registered VIC's until there are no pending
229 * interrupts. 241 * interrupts.
@@ -246,6 +258,7 @@ static struct irq_domain_ops vic_irqdomain_ops = {
246/** 258/**
247 * vic_register() - Register a VIC. 259 * vic_register() - Register a VIC.
248 * @base: The base address of the VIC. 260 * @base: The base address of the VIC.
261 * @parent_irq: The parent IRQ if cascaded, else 0.
249 * @irq: The base IRQ for the VIC. 262 * @irq: The base IRQ for the VIC.
250 * @valid_sources: bitmask of valid interrupts 263 * @valid_sources: bitmask of valid interrupts
251 * @resume_sources: bitmask of interrupts allowed for resume sources. 264 * @resume_sources: bitmask of interrupts allowed for resume sources.
@@ -257,7 +270,8 @@ static struct irq_domain_ops vic_irqdomain_ops = {
257 * 270 *
258 * This also configures the IRQ domain for the VIC. 271 * This also configures the IRQ domain for the VIC.
259 */ 272 */
260static void __init vic_register(void __iomem *base, unsigned int irq, 273static void __init vic_register(void __iomem *base, unsigned int parent_irq,
274 unsigned int irq,
261 u32 valid_sources, u32 resume_sources, 275 u32 valid_sources, u32 resume_sources,
262 struct device_node *node) 276 struct device_node *node)
263{ 277{
@@ -273,15 +287,25 @@ static void __init vic_register(void __iomem *base, unsigned int irq,
273 v->base = base; 287 v->base = base;
274 v->valid_sources = valid_sources; 288 v->valid_sources = valid_sources;
275 v->resume_sources = resume_sources; 289 v->resume_sources = resume_sources;
276 v->irq = irq;
277 set_handle_irq(vic_handle_irq); 290 set_handle_irq(vic_handle_irq);
278 vic_id++; 291 vic_id++;
292
293 if (parent_irq) {
294 irq_set_handler_data(parent_irq, v);
295 irq_set_chained_handler(parent_irq, vic_handle_irq_cascaded);
296 }
297
279 v->domain = irq_domain_add_simple(node, fls(valid_sources), irq, 298 v->domain = irq_domain_add_simple(node, fls(valid_sources), irq,
280 &vic_irqdomain_ops, v); 299 &vic_irqdomain_ops, v);
281 /* create an IRQ mapping for each valid IRQ */ 300 /* create an IRQ mapping for each valid IRQ */
282 for (i = 0; i < fls(valid_sources); i++) 301 for (i = 0; i < fls(valid_sources); i++)
283 if (valid_sources & (1 << i)) 302 if (valid_sources & (1 << i))
284 irq_create_mapping(v->domain, i); 303 irq_create_mapping(v->domain, i);
304 /* If no base IRQ was passed, figure out our allocated base */
305 if (irq)
306 v->irq = irq;
307 else
308 v->irq = irq_find_mapping(v->domain, 0);
285} 309}
286 310
287static void vic_ack_irq(struct irq_data *d) 311static void vic_ack_irq(struct irq_data *d)
@@ -409,10 +433,10 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start,
409 writel(32, base + VIC_PL190_DEF_VECT_ADDR); 433 writel(32, base + VIC_PL190_DEF_VECT_ADDR);
410 } 434 }
411 435
412 vic_register(base, irq_start, vic_sources, 0, node); 436 vic_register(base, 0, irq_start, vic_sources, 0, node);
413} 437}
414 438
415void __init __vic_init(void __iomem *base, int irq_start, 439void __init __vic_init(void __iomem *base, int parent_irq, int irq_start,
416 u32 vic_sources, u32 resume_sources, 440 u32 vic_sources, u32 resume_sources,
417 struct device_node *node) 441 struct device_node *node)
418{ 442{
@@ -449,7 +473,7 @@ void __init __vic_init(void __iomem *base, int irq_start,
449 473
450 vic_init2(base); 474 vic_init2(base);
451 475
452 vic_register(base, irq_start, vic_sources, resume_sources, node); 476 vic_register(base, parent_irq, irq_start, vic_sources, resume_sources, node);
453} 477}
454 478
455/** 479/**
@@ -462,7 +486,28 @@ void __init __vic_init(void __iomem *base, int irq_start,
462void __init vic_init(void __iomem *base, unsigned int irq_start, 486void __init vic_init(void __iomem *base, unsigned int irq_start,
463 u32 vic_sources, u32 resume_sources) 487 u32 vic_sources, u32 resume_sources)
464{ 488{
465 __vic_init(base, irq_start, vic_sources, resume_sources, NULL); 489 __vic_init(base, 0, irq_start, vic_sources, resume_sources, NULL);
490}
491
492/**
493 * vic_init_cascaded() - initialise a cascaded vectored interrupt controller
494 * @base: iomem base address
495 * @parent_irq: the parent IRQ we're cascaded off
496 * @irq_start: starting interrupt number, must be muliple of 32
497 * @vic_sources: bitmask of interrupt sources to allow
498 * @resume_sources: bitmask of interrupt sources to allow for resume
499 *
500 * This returns the base for the new interrupts or negative on error.
501 */
502int __init vic_init_cascaded(void __iomem *base, unsigned int parent_irq,
503 u32 vic_sources, u32 resume_sources)
504{
505 struct vic_device *v;
506
507 v = &vic_devices[vic_id];
508 __vic_init(base, parent_irq, 0, vic_sources, resume_sources, NULL);
509 /* Return out acquired base */
510 return v->irq;
466} 511}
467 512
468#ifdef CONFIG_OF 513#ifdef CONFIG_OF
@@ -485,7 +530,7 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent)
485 /* 530 /*
486 * Passing 0 as first IRQ makes the simple domain allocate descriptors 531 * Passing 0 as first IRQ makes the simple domain allocate descriptors
487 */ 532 */
488 __vic_init(regs, 0, interrupt_mask, wakeup_mask, node); 533 __vic_init(regs, 0, 0, interrupt_mask, wakeup_mask, node);
489 534
490 return 0; 535 return 0;
491} 536}
diff --git a/include/linux/irqchip/arm-vic.h b/include/linux/irqchip/arm-vic.h
index e3c82dc95756..ba46c794b4e5 100644
--- a/include/linux/irqchip/arm-vic.h
+++ b/include/linux/irqchip/arm-vic.h
@@ -29,8 +29,10 @@
29struct device_node; 29struct device_node;
30struct pt_regs; 30struct pt_regs;
31 31
32void __vic_init(void __iomem *base, int irq_start, u32 vic_sources, 32void __vic_init(void __iomem *base, int parent_irq, int irq_start,
33 u32 resume_sources, struct device_node *node); 33 u32 vic_sources, u32 resume_sources, struct device_node *node);
34void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources); 34void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources);
35int vic_init_cascaded(void __iomem *base, unsigned int parent_irq,
36 u32 vic_sources, u32 resume_sources);
35 37
36#endif 38#endif
diff --git a/include/linux/platform_data/clk-integrator.h b/include/linux/platform_data/clk-integrator.h
index 280edac9d0a5..addd48cac625 100644
--- a/include/linux/platform_data/clk-integrator.h
+++ b/include/linux/platform_data/clk-integrator.h
@@ -1,3 +1,2 @@
1void integrator_clk_init(bool is_cp);
2void integrator_impd1_clk_init(void __iomem *base, unsigned int id); 1void integrator_impd1_clk_init(void __iomem *base, unsigned int id);
3void integrator_impd1_clk_exit(unsigned int id); 2void integrator_impd1_clk_exit(unsigned int id);