aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2010-05-30 20:01:50 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2010-05-30 20:01:50 -0400
commitecca1a34befbb13fc23d9a2cc0d6b725c7727fb2 (patch)
tree6539480b50258f30af799a6ab38529d7b2d7e538
parent3d00d4ff11686895925f46265f4a78dc78196c2e (diff)
parent48936a08b85518c22a9467a8eaac35d43af54ab4 (diff)
Merge commit 'kumar/next' into next
Conflicts: arch/powerpc/sysdev/fsl_msi.c
-rw-r--r--arch/powerpc/Kconfig2
-rw-r--r--arch/powerpc/boot/dts/mpc8548cds.dts4
-rw-r--r--arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts15
-rw-r--r--arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts7
-rw-r--r--arch/powerpc/boot/dts/p1021mds.dts698
-rw-r--r--arch/powerpc/include/asm/cputable.h1
-rw-r--r--arch/powerpc/include/asm/kexec.h13
-rw-r--r--arch/powerpc/include/asm/reg_booke.h33
-rw-r--r--arch/powerpc/kernel/Makefile8
-rw-r--r--arch/powerpc/kernel/cputable.c2
-rw-r--r--arch/powerpc/kernel/crash.c4
-rw-r--r--arch/powerpc/kernel/fsl_booke_entry_mapping.S237
-rw-r--r--arch/powerpc/kernel/head_fsl_booke.S200
-rw-r--r--arch/powerpc/kernel/misc_32.S17
-rw-r--r--arch/powerpc/kernel/swsusp_booke.S193
-rw-r--r--arch/powerpc/kernel/traps.c88
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_mds.c102
-rw-r--r--arch/powerpc/sysdev/fsl_msi.c117
-rw-r--r--arch/powerpc/sysdev/fsl_msi.h3
19 files changed, 1494 insertions, 250 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 66a315e06dce..328774bd41ee 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -351,7 +351,7 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE
351 351
352config KEXEC 352config KEXEC
353 bool "kexec system call (EXPERIMENTAL)" 353 bool "kexec system call (EXPERIMENTAL)"
354 depends on PPC_BOOK3S && EXPERIMENTAL 354 depends on (PPC_BOOK3S || (FSL_BOOKE && !SMP)) && EXPERIMENTAL
355 help 355 help
356 kexec is a system call that implements the ability to shutdown your 356 kexec is a system call that implements the ability to shutdown your
357 current kernel, and to start another kernel. It is like a reboot 357 current kernel, and to start another kernel. It is like a reboot
diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts
index 4173af387c63..0f5262452682 100644
--- a/arch/powerpc/boot/dts/mpc8548cds.dts
+++ b/arch/powerpc/boot/dts/mpc8548cds.dts
@@ -20,10 +20,8 @@
20 aliases { 20 aliases {
21 ethernet0 = &enet0; 21 ethernet0 = &enet0;
22 ethernet1 = &enet1; 22 ethernet1 = &enet1;
23/*
24 ethernet2 = &enet2; 23 ethernet2 = &enet2;
25 ethernet3 = &enet3; 24 ethernet3 = &enet3;
26*/
27 serial0 = &serial0; 25 serial0 = &serial0;
28 serial1 = &serial1; 26 serial1 = &serial1;
29 pci0 = &pci0; 27 pci0 = &pci0;
@@ -254,7 +252,6 @@
254 }; 252 };
255 }; 253 };
256 254
257/* eTSEC 3/4 are currently broken
258 enet2: ethernet@26000 { 255 enet2: ethernet@26000 {
259 #address-cells = <1>; 256 #address-cells = <1>;
260 #size-cells = <1>; 257 #size-cells = <1>;
@@ -310,7 +307,6 @@
310 }; 307 };
311 }; 308 };
312 }; 309 };
313 */
314 310
315 serial0: serial@4500 { 311 serial0: serial@4500 {
316 cell-index = <0>; 312 cell-index = <0>;
diff --git a/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts b/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts
index 5bd1011fde96..3375c2ab0c32 100644
--- a/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts
+++ b/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts
@@ -215,6 +215,18 @@
215 clock-frequency = <0>; 215 clock-frequency = <0>;
216 }; 216 };
217 217
218 msi@41600 {
219 compatible = "fsl,mpc8572-msi", "fsl,mpic-msi";
220 reg = <0x41600 0x80>;
221 msi-available-ranges = <0 0x80>;
222 interrupts = <
223 0xe0 0
224 0xe1 0
225 0xe2 0
226 0xe3 0>;
227 interrupt-parent = <&mpic>;
228 };
229
218 global-utilities@e0000 { //global utilities block 230 global-utilities@e0000 { //global utilities block
219 compatible = "fsl,mpc8572-guts"; 231 compatible = "fsl,mpc8572-guts";
220 reg = <0xe0000 0x1000>; 232 reg = <0xe0000 0x1000>;
@@ -243,8 +255,7 @@
243 protected-sources = < 255 protected-sources = <
244 31 32 33 37 38 39 /* enet2 enet3 */ 256 31 32 33 37 38 39 /* enet2 enet3 */
245 76 77 78 79 26 42 /* dma2 pci2 serial*/ 257 76 77 78 79 26 42 /* dma2 pci2 serial*/
246 0xe0 0xe1 0xe2 0xe3 /* msi */ 258 0xe4 0xe5 0xe6 0xe7 /* msi */
247 0xe4 0xe5 0xe6 0xe7
248 >; 259 >;
249 }; 260 };
250 }; 261 };
diff --git a/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts b/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts
index 0efc3456e297..e7b477f6a3fe 100644
--- a/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts
+++ b/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts
@@ -154,12 +154,8 @@
154 msi@41600 { 154 msi@41600 {
155 compatible = "fsl,mpc8572-msi", "fsl,mpic-msi"; 155 compatible = "fsl,mpc8572-msi", "fsl,mpic-msi";
156 reg = <0x41600 0x80>; 156 reg = <0x41600 0x80>;
157 msi-available-ranges = <0 0x100>; 157 msi-available-ranges = <0x80 0x80>;
158 interrupts = < 158 interrupts = <
159 0xe0 0
160 0xe1 0
161 0xe2 0
162 0xe3 0
163 0xe4 0 159 0xe4 0
164 0xe5 0 160 0xe5 0
165 0xe6 0 161 0xe6 0
@@ -190,6 +186,7 @@
190 0x1 0x2 0x3 0x4 /* pci slot */ 186 0x1 0x2 0x3 0x4 /* pci slot */
191 0x9 0xa 0xb 0xc /* usb */ 187 0x9 0xa 0xb 0xc /* usb */
192 0x6 0x7 0xe 0x5 /* Audio elgacy SATA */ 188 0x6 0x7 0xe 0x5 /* Audio elgacy SATA */
189 0xe0 0xe1 0xe2 0xe3 /* msi */
193 >; 190 >;
194 }; 191 };
195 }; 192 };
diff --git a/arch/powerpc/boot/dts/p1021mds.dts b/arch/powerpc/boot/dts/p1021mds.dts
new file mode 100644
index 000000000000..7fad2df25981
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1021mds.dts
@@ -0,0 +1,698 @@
1/*
2 * P1021 MDS Device Tree Source
3 *
4 * Copyright 2010 Freescale Semiconductor Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12/dts-v1/;
13/ {
14 model = "fsl,P1021";
15 compatible = "fsl,P1021MDS";
16 #address-cells = <2>;
17 #size-cells = <2>;
18
19 aliases {
20 serial0 = &serial0;
21 serial1 = &serial1;
22 ethernet0 = &enet0;
23 ethernet1 = &enet1;
24 ethernet2 = &enet2;
25 ethernet3 = &enet3;
26 ethernet4 = &enet4;
27 pci0 = &pci0;
28 pci1 = &pci1;
29 };
30
31 cpus {
32 #address-cells = <1>;
33 #size-cells = <0>;
34
35 PowerPC,P1021@0 {
36 device_type = "cpu";
37 reg = <0x0>;
38 next-level-cache = <&L2>;
39 };
40
41 PowerPC,P1021@1 {
42 device_type = "cpu";
43 reg = <0x1>;
44 next-level-cache = <&L2>;
45 };
46 };
47
48 memory {
49 device_type = "memory";
50 };
51
52 localbus@ffe05000 {
53 #address-cells = <2>;
54 #size-cells = <1>;
55 compatible = "fsl,p1021-elbc", "fsl,elbc", "simple-bus";
56 reg = <0 0xffe05000 0 0x1000>;
57 interrupts = <19 2>;
58 interrupt-parent = <&mpic>;
59
60 /* NAND Flash, BCSR, PMC0/1*/
61 ranges = <0x0 0x0 0x0 0xfc000000 0x02000000
62 0x1 0x0 0x0 0xf8000000 0x00008000
63 0x2 0x0 0x0 0xf8010000 0x00020000
64 0x3 0x0 0x0 0xf8020000 0x00020000>;
65
66 nand@0,0 {
67 #address-cells = <1>;
68 #size-cells = <1>;
69 compatible = "fsl,p1021-fcm-nand",
70 "fsl,elbc-fcm-nand";
71 reg = <0x0 0x0 0x40000>;
72
73 partition@0 {
74 /* This location must not be altered */
75 /* 1MB for u-boot Bootloader Image */
76 reg = <0x0 0x00100000>;
77 label = "NAND (RO) U-Boot Image";
78 read-only;
79 };
80
81 partition@100000 {
82 /* 1MB for DTB Image */
83 reg = <0x00100000 0x00100000>;
84 label = "NAND (RO) DTB Image";
85 read-only;
86 };
87
88 partition@200000 {
89 /* 4MB for Linux Kernel Image */
90 reg = <0x00200000 0x00400000>;
91 label = "NAND (RO) Linux Kernel Image";
92 read-only;
93 };
94
95 partition@600000 {
96 /* 5MB for Compressed Root file System Image */
97 reg = <0x00600000 0x00500000>;
98 label = "NAND (RO) Compressed RFS Image";
99 read-only;
100 };
101
102 partition@b00000 {
103 /* 6MB for JFFS2 based Root file System */
104 reg = <0x00a00000 0x00600000>;
105 label = "NAND (RW) JFFS2 Root File System";
106 };
107
108 partition@1100000 {
109 /* 14MB for JFFS2 based Root file System */
110 reg = <0x01100000 0x00e00000>;
111 label = "NAND (RW) Writable User area";
112 };
113
114 partition@1f00000 {
115 /* 1MB for microcode */
116 reg = <0x01f00000 0x00100000>;
117 label = "NAND (RO) QE Ucode";
118 read-only;
119 };
120 };
121
122 bcsr@1,0 {
123 #address-cells = <1>;
124 #size-cells = <1>;
125 compatible = "fsl,p1021mds-bcsr";
126 reg = <1 0 0x8000>;
127 ranges = <0 1 0 0x8000>;
128 };
129
130 pib@2,0 {
131 compatible = "fsl,p1021mds-pib";
132 reg = <2 0 0x10000>;
133 };
134
135 pib@3,0 {
136 compatible = "fsl,p1021mds-pib";
137 reg = <3 0 0x10000>;
138 };
139 };
140
141 soc@ffe00000 {
142
143 #address-cells = <1>;
144 #size-cells = <1>;
145 device_type = "soc";
146 compatible = "fsl,p1021-immr", "simple-bus";
147 ranges = <0x0 0x0 0xffe00000 0x100000>;
148 bus-frequency = <0>; // Filled out by uboot.
149
150 ecm-law@0 {
151 compatible = "fsl,ecm-law";
152 reg = <0x0 0x1000>;
153 fsl,num-laws = <12>;
154 };
155
156 ecm@1000 {
157 compatible = "fsl,p1021-ecm", "fsl,ecm";
158 reg = <0x1000 0x1000>;
159 interrupts = <16 2>;
160 interrupt-parent = <&mpic>;
161 };
162
163 memory-controller@2000 {
164 compatible = "fsl,p1021-memory-controller";
165 reg = <0x2000 0x1000>;
166 interrupt-parent = <&mpic>;
167 interrupts = <16 2>;
168 };
169
170 i2c@3000 {
171 #address-cells = <1>;
172 #size-cells = <0>;
173 cell-index = <0>;
174 compatible = "fsl-i2c";
175 reg = <0x3000 0x100>;
176 interrupts = <43 2>;
177 interrupt-parent = <&mpic>;
178 dfsrr;
179 rtc@68 {
180 compatible = "dallas,ds1374";
181 reg = <0x68>;
182 };
183 };
184
185 i2c@3100 {
186 #address-cells = <1>;
187 #size-cells = <0>;
188 cell-index = <1>;
189 compatible = "fsl-i2c";
190 reg = <0x3100 0x100>;
191 interrupts = <43 2>;
192 interrupt-parent = <&mpic>;
193 dfsrr;
194 };
195
196 serial0: serial@4500 {
197 cell-index = <0>;
198 device_type = "serial";
199 compatible = "ns16550";
200 reg = <0x4500 0x100>;
201 clock-frequency = <0>;
202 interrupts = <42 2>;
203 interrupt-parent = <&mpic>;
204 };
205
206 serial1: serial@4600 {
207 cell-index = <1>;
208 device_type = "serial";
209 compatible = "ns16550";
210 reg = <0x4600 0x100>;
211 clock-frequency = <0>;
212 interrupts = <42 2>;
213 interrupt-parent = <&mpic>;
214 };
215
216 spi@7000 {
217 cell-index = <0>;
218 #address-cells = <1>;
219 #size-cells = <0>;
220 compatible = "fsl,espi";
221 reg = <0x7000 0x1000>;
222 interrupts = <59 0x2>;
223 interrupt-parent = <&mpic>;
224 espi,num-ss-bits = <4>;
225 mode = "cpu";
226
227 fsl_m25p80@0 {
228 #address-cells = <1>;
229 #size-cells = <1>;
230 compatible = "fsl,espi-flash";
231 reg = <0>;
232 linux,modalias = "fsl_m25p80";
233 spi-max-frequency = <40000000>; /* input clock */
234 partition@u-boot {
235 label = "u-boot-spi";
236 reg = <0x00000000 0x00100000>;
237 read-only;
238 };
239 partition@kernel {
240 label = "kernel-spi";
241 reg = <0x00100000 0x00500000>;
242 read-only;
243 };
244 partition@dtb {
245 label = "dtb-spi";
246 reg = <0x00600000 0x00100000>;
247 read-only;
248 };
249 partition@fs {
250 label = "file system-spi";
251 reg = <0x00700000 0x00900000>;
252 };
253 };
254 };
255
256 gpio: gpio-controller@f000 {
257 #gpio-cells = <2>;
258 compatible = "fsl,mpc8572-gpio";
259 reg = <0xf000 0x100>;
260 interrupts = <47 0x2>;
261 interrupt-parent = <&mpic>;
262 gpio-controller;
263 };
264
265 L2: l2-cache-controller@20000 {
266 compatible = "fsl,p1021-l2-cache-controller";
267 reg = <0x20000 0x1000>;
268 cache-line-size = <32>; // 32 bytes
269 cache-size = <0x40000>; // L2,256K
270 interrupt-parent = <&mpic>;
271 interrupts = <16 2>;
272 };
273
274 dma@21300 {
275 #address-cells = <1>;
276 #size-cells = <1>;
277 compatible = "fsl,eloplus-dma";
278 reg = <0x21300 0x4>;
279 ranges = <0x0 0x21100 0x200>;
280 cell-index = <0>;
281 dma-channel@0 {
282 compatible = "fsl,eloplus-dma-channel";
283 reg = <0x0 0x80>;
284 cell-index = <0>;
285 interrupt-parent = <&mpic>;
286 interrupts = <20 2>;
287 };
288 dma-channel@80 {
289 compatible = "fsl,eloplus-dma-channel";
290 reg = <0x80 0x80>;
291 cell-index = <1>;
292 interrupt-parent = <&mpic>;
293 interrupts = <21 2>;
294 };
295 dma-channel@100 {
296 compatible = "fsl,eloplus-dma-channel";
297 reg = <0x100 0x80>;
298 cell-index = <2>;
299 interrupt-parent = <&mpic>;
300 interrupts = <22 2>;
301 };
302 dma-channel@180 {
303 compatible = "fsl,eloplus-dma-channel";
304 reg = <0x180 0x80>;
305 cell-index = <3>;
306 interrupt-parent = <&mpic>;
307 interrupts = <23 2>;
308 };
309 };
310
311 usb@22000 {
312 #address-cells = <1>;
313 #size-cells = <0>;
314 compatible = "fsl-usb2-dr";
315 reg = <0x22000 0x1000>;
316 interrupt-parent = <&mpic>;
317 interrupts = <28 0x2>;
318 phy_type = "ulpi";
319 };
320
321 mdio@24000 {
322 #address-cells = <1>;
323 #size-cells = <0>;
324 compatible = "fsl,etsec2-mdio";
325 reg = <0x24000 0x1000 0xb0030 0x4>;
326
327 phy0: ethernet-phy@0 {
328 interrupt-parent = <&mpic>;
329 interrupts = <1 1>;
330 reg = <0x0>;
331 };
332 phy1: ethernet-phy@1 {
333 interrupt-parent = <&mpic>;
334 interrupts = <2 1>;
335 reg = <0x1>;
336 };
337 phy4: ethernet-phy@4 {
338 interrupt-parent = <&mpic>;
339 reg = <0x4>;
340 };
341 };
342
343 mdio@25000 {
344 #address-cells = <1>;
345 #size-cells = <0>;
346 compatible = "fsl,etsec2-tbi";
347 reg = <0x25000 0x1000 0xb1030 0x4>;
348 tbi0: tbi-phy@11 {
349 reg = <0x11>;
350 device_type = "tbi-phy";
351 };
352 };
353
354 enet0: ethernet@B0000 {
355 #address-cells = <1>;
356 #size-cells = <1>;
357 cell-index = <0>;
358 device_type = "network";
359 model = "eTSEC";
360 compatible = "fsl,etsec2";
361 fsl,num_rx_queues = <0x8>;
362 fsl,num_tx_queues = <0x8>;
363 local-mac-address = [ 00 00 00 00 00 00 ];
364 interrupt-parent = <&mpic>;
365 phy-handle = <&phy0>;
366 phy-connection-type = "rgmii-id";
367 queue-group@0{
368 #address-cells = <1>;
369 #size-cells = <1>;
370 reg = <0xB0000 0x1000>;
371 interrupts = <29 2 30 2 34 2>;
372 };
373 queue-group@1{
374 #address-cells = <1>;
375 #size-cells = <1>;
376 reg = <0xB4000 0x1000>;
377 interrupts = <17 2 18 2 24 2>;
378 };
379 };
380
381 enet1: ethernet@B1000 {
382 #address-cells = <1>;
383 #size-cells = <1>;
384 cell-index = <0>;
385 device_type = "network";
386 model = "eTSEC";
387 compatible = "fsl,etsec2";
388 fsl,num_rx_queues = <0x8>;
389 fsl,num_tx_queues = <0x8>;
390 local-mac-address = [ 00 00 00 00 00 00 ];
391 interrupt-parent = <&mpic>;
392 phy-handle = <&phy4>;
393 tbi-handle = <&tbi0>;
394 phy-connection-type = "sgmii";
395 queue-group@0{
396 #address-cells = <1>;
397 #size-cells = <1>;
398 reg = <0xB1000 0x1000>;
399 interrupts = <35 2 36 2 40 2>;
400 };
401 queue-group@1{
402 #address-cells = <1>;
403 #size-cells = <1>;
404 reg = <0xB5000 0x1000>;
405 interrupts = <51 2 52 2 67 2>;
406 };
407 };
408
409 enet2: ethernet@B2000 {
410 #address-cells = <1>;
411 #size-cells = <1>;
412 cell-index = <0>;
413 device_type = "network";
414 model = "eTSEC";
415 compatible = "fsl,etsec2";
416 fsl,num_rx_queues = <0x8>;
417 fsl,num_tx_queues = <0x8>;
418 local-mac-address = [ 00 00 00 00 00 00 ];
419 interrupt-parent = <&mpic>;
420 phy-handle = <&phy1>;
421 phy-connection-type = "rgmii-id";
422 queue-group@0{
423 #address-cells = <1>;
424 #size-cells = <1>;
425 reg = <0xB2000 0x1000>;
426 interrupts = <31 2 32 2 33 2>;
427 };
428 queue-group@1{
429 #address-cells = <1>;
430 #size-cells = <1>;
431 reg = <0xB6000 0x1000>;
432 interrupts = <25 2 26 2 27 2>;
433 };
434 };
435
436 sdhci@2e000 {
437 compatible = "fsl,p1021-esdhc", "fsl,esdhc";
438 reg = <0x2e000 0x1000>;
439 interrupts = <72 0x2>;
440 interrupt-parent = <&mpic>;
441 /* Filled in by U-Boot */
442 clock-frequency = <0>;
443 };
444
445 crypto@30000 {
446 compatible = "fsl,sec3.3", "fsl,sec3.1",
447 "fsl,sec3.0", "fsl,sec2.4",
448 "fsl,sec2.2", "fsl,sec2.1", "fsl,sec2.0";
449 reg = <0x30000 0x10000>;
450 interrupts = <45 2 58 2>;
451 interrupt-parent = <&mpic>;
452 fsl,num-channels = <4>;
453 fsl,channel-fifo-len = <24>;
454 fsl,exec-units-mask = <0x97c>;
455 fsl,descriptor-types-mask = <0x3a30abf>;
456 };
457
458 mpic: pic@40000 {
459 interrupt-controller;
460 #address-cells = <0>;
461 #interrupt-cells = <2>;
462 reg = <0x40000 0x40000>;
463 compatible = "chrp,open-pic";
464 device_type = "open-pic";
465 };
466
467 msi@41600 {
468 compatible = "fsl,p1021-msi", "fsl,mpic-msi";
469 reg = <0x41600 0x80>;
470 msi-available-ranges = <0 0x100>;
471 interrupts = <
472 0xe0 0
473 0xe1 0
474 0xe2 0
475 0xe3 0
476 0xe4 0
477 0xe5 0
478 0xe6 0
479 0xe7 0>;
480 interrupt-parent = <&mpic>;
481 };
482
483 global-utilities@e0000 { //global utilities block
484 compatible = "fsl,p1021-guts";
485 reg = <0xe0000 0x1000>;
486 fsl,has-rstcr;
487 };
488
489 par_io@e0100 {
490 #address-cells = <1>;
491 #size-cells = <1>;
492 reg = <0xe0100 0x60>;
493 ranges = <0x0 0xe0100 0x60>;
494 device_type = "par_io";
495 num-ports = <3>;
496 pio1: ucc_pin@01 {
497 pio-map = <
498 /* port pin dir open_drain assignment has_irq */
499 0x1 0x13 0x1 0x0 0x1 0x0 /* QE_MUX_MDC */
500 0x1 0x14 0x3 0x0 0x1 0x0 /* QE_MUX_MDIO */
501 0x0 0x17 0x2 0x0 0x2 0x0 /* CLK12 */
502 0x0 0x18 0x2 0x0 0x1 0x0 /* CLK9
503*/
504 0x0 0x7 0x1 0x0 0x2 0x0 /* ENET1_TXD0_SER1_TXD0 */
505 0x0 0x9 0x1 0x0 0x2 0x0 /* ENET1_TXD1_SER1_TXD1 */
506 0x0 0xb 0x1 0x0 0x2 0x0 /* ENET1_TXD2_SER1_TXD2 */
507 0x0 0xc 0x1 0x0 0x2 0x0 /* ENET1_TXD3_SER1_TXD3 */
508 0x0 0x6 0x2 0x0 0x2 0x0 /* ENET1_RXD0_SER1_RXD0 */
509 0x0 0xa 0x2 0x0 0x2 0x0 /* ENET1_RXD1_SER1_RXD1 */
510 0x0 0xe 0x2 0x0 0x2 0x0 /* ENET1_RXD2_SER1_RXD2 */
511 0x0 0xf 0x2 0x0 0x2 0x0 /* ENET1_RXD3_SER1_RXD3 */
512 0x0 0x5 0x1 0x0 0x2 0x0 /* ENET1_TX_EN_SER1_RTS_B */
513 0x0 0xd 0x1 0x0 0x2 0x0 /* ENET1_TX_ER */
514 0x0 0x4 0x2 0x0 0x2 0x0 /* ENET1_RX_DV_SER1_CTS_B */
515 0x0 0x8 0x2 0x0 0x2 0x0 /* ENET1_RX_ER_SER1_CD_B */
516 0x0 0x11 0x2 0x0 0x2 0x0 /* ENET1_CRS */
517 0x0 0x10 0x2 0x0 0x2 0x0>; /* ENET1_COL */
518 };
519
520 pio2: ucc_pin@02 {
521 pio-map = <
522 /* port pin dir open_drain assignment has_irq */
523 0x1 0x13 0x1 0x0 0x1 0x0 /* QE_MUX_MDC */
524 0x1 0x14 0x3 0x0 0x1 0x0 /* QE_MUX_MDIO */
525 0x1 0xb 0x2 0x0 0x1 0x0 /* CLK13 */
526 0x1 0x7 0x1 0x0 0x2 0x0 /* ENET5_TXD0_SER5_TXD0 */
527 0x1 0xa 0x1 0x0 0x2 0x0 /* ENET5_TXD1_SER5_TXD1 */
528 0x1 0x6 0x2 0x0 0x2 0x0 /* ENET5_RXD0_SER5_RXD0 */
529 0x1 0x9 0x2 0x0 0x2 0x0 /* ENET5_RXD1_SER5_RXD1 */
530 0x1 0x5 0x1 0x0 0x2 0x0 /* ENET5_TX_EN_SER5_RTS_B */
531 0x1 0x4 0x2 0x0 0x2 0x0 /* ENET5_RX_DV_SER5_CTS_B */
532 0x1 0x8 0x2 0x0 0x2 0x0>; /* ENET5_RX_ER_SER5_CD_B */
533 };
534 };
535 };
536
537 pci0: pcie@ffe09000 {
538 compatible = "fsl,mpc8548-pcie";
539 device_type = "pci";
540 #interrupt-cells = <1>;
541 #size-cells = <2>;
542 #address-cells = <3>;
543 reg = <0 0xffe09000 0 0x1000>;
544 bus-range = <0 255>;
545 ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
546 0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
547 clock-frequency = <33333333>;
548 interrupt-parent = <&mpic>;
549 interrupts = <16 2>;
550 interrupt-map-mask = <0xf800 0 0 7>;
551 interrupt-map = <
552 /* IDSEL 0x0 */
553 0000 0 0 1 &mpic 4 1
554 0000 0 0 2 &mpic 5 1
555 0000 0 0 3 &mpic 6 1
556 0000 0 0 4 &mpic 7 1
557 >;
558 pcie@0 {
559 reg = <0x0 0x0 0x0 0x0 0x0>;
560 #size-cells = <2>;
561 #address-cells = <3>;
562 device_type = "pci";
563 ranges = <0x2000000 0x0 0xa0000000
564 0x2000000 0x0 0xa0000000
565 0x0 0x20000000
566
567 0x1000000 0x0 0x0
568 0x1000000 0x0 0x0
569 0x0 0x100000>;
570 };
571 };
572
573 pci1: pcie@ffe0a000 {
574 compatible = "fsl,mpc8548-pcie";
575 device_type = "pci";
576 #interrupt-cells = <1>;
577 #size-cells = <2>;
578 #address-cells = <3>;
579 reg = <0 0xffe0a000 0 0x1000>;
580 bus-range = <0 255>;
581 ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x20000000
582 0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>;
583 clock-frequency = <33333333>;
584 interrupt-parent = <&mpic>;
585 interrupts = <16 2>;
586 interrupt-map-mask = <0xf800 0 0 7>;
587 interrupt-map = <
588 /* IDSEL 0x0 */
589 0000 0 0 1 &mpic 0 1
590 0000 0 0 2 &mpic 1 1
591 0000 0 0 3 &mpic 2 1
592 0000 0 0 4 &mpic 3 1
593 >;
594 pcie@0 {
595 reg = <0x0 0x0 0x0 0x0 0x0>;
596 #size-cells = <2>;
597 #address-cells = <3>;
598 device_type = "pci";
599 ranges = <0x2000000 0x0 0xc0000000
600 0x2000000 0x0 0xc0000000
601 0x0 0x20000000
602
603 0x1000000 0x0 0x0
604 0x1000000 0x0 0x0
605 0x0 0x100000>;
606 };
607 };
608
609 qe@ffe80000 {
610 #address-cells = <1>;
611 #size-cells = <1>;
612 device_type = "qe";
613 compatible = "fsl,qe";
614 ranges = <0x0 0x0 0xffe80000 0x40000>;
615 reg = <0 0xffe80000 0 0x480>;
616 brg-frequency = <0>;
617 bus-frequency = <0>;
618 fsl,qe-num-riscs = <1>;
619 fsl,qe-num-snums = <28>;
620
621 qeic: interrupt-controller@80 {
622 interrupt-controller;
623 compatible = "fsl,qe-ic";
624 #address-cells = <0>;
625 #interrupt-cells = <1>;
626 reg = <0x80 0x80>;
627 interrupts = <63 2 60 2>; //high:47 low:44
628 interrupt-parent = <&mpic>;
629 };
630
631 enet3: ucc@2000 {
632 device_type = "network";
633 compatible = "ucc_geth";
634 cell-index = <1>;
635 reg = <0x2000 0x200>;
636 interrupts = <32>;
637 interrupt-parent = <&qeic>;
638 local-mac-address = [ 00 00 00 00 00 00 ];
639 rx-clock-name = "clk12";
640 tx-clock-name = "clk9";
641 pio-handle = <&pio1>;
642 phy-handle = <&qe_phy0>;
643 phy-connection-type = "mii";
644 };
645
646 mdio@2120 {
647 #address-cells = <1>;
648 #size-cells = <0>;
649 reg = <0x2120 0x18>;
650 compatible = "fsl,ucc-mdio";
651
652 qe_phy0: ethernet-phy@0 {
653 interrupt-parent = <&mpic>;
654 interrupts = <4 1>;
655 reg = <0x0>;
656 device_type = "ethernet-phy";
657 };
658 qe_phy1: ethernet-phy@03 {
659 interrupt-parent = <&mpic>;
660 interrupts = <5 1>;
661 reg = <0x3>;
662 device_type = "ethernet-phy";
663 };
664 tbi-phy@11 {
665 reg = <0x11>;
666 device_type = "tbi-phy";
667 };
668 };
669
670 enet4: ucc@2400 {
671 device_type = "network";
672 compatible = "ucc_geth";
673 cell-index = <5>;
674 reg = <0x2400 0x200>;
675 interrupts = <40>;
676 interrupt-parent = <&qeic>;
677 local-mac-address = [ 00 00 00 00 00 00 ];
678 rx-clock-name = "none";
679 tx-clock-name = "clk13";
680 pio-handle = <&pio2>;
681 phy-handle = <&qe_phy1>;
682 phy-connection-type = "rmii";
683 };
684
685 muram@10000 {
686 #address-cells = <1>;
687 #size-cells = <1>;
688 compatible = "fsl,qe-muram", "fsl,cpm-muram";
689 ranges = <0x0 0x10000 0x6000>;
690
691 data-only@0 {
692 compatible = "fsl,qe-muram-data",
693 "fsl,cpm-muram-data";
694 reg = <0x0 0x6000>;
695 };
696 };
697 };
698};
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index e3cba4e1eb34..b0b21134f61a 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -70,6 +70,7 @@ struct pt_regs;
70extern int machine_check_generic(struct pt_regs *regs); 70extern int machine_check_generic(struct pt_regs *regs);
71extern int machine_check_4xx(struct pt_regs *regs); 71extern int machine_check_4xx(struct pt_regs *regs);
72extern int machine_check_440A(struct pt_regs *regs); 72extern int machine_check_440A(struct pt_regs *regs);
73extern int machine_check_e500mc(struct pt_regs *regs);
73extern int machine_check_e500(struct pt_regs *regs); 74extern int machine_check_e500(struct pt_regs *regs);
74extern int machine_check_e200(struct pt_regs *regs); 75extern int machine_check_e200(struct pt_regs *regs);
75extern int machine_check_47x(struct pt_regs *regs); 76extern int machine_check_47x(struct pt_regs *regs);
diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h
index a6ca6da1430b..2a9cd74a841e 100644
--- a/arch/powerpc/include/asm/kexec.h
+++ b/arch/powerpc/include/asm/kexec.h
@@ -2,6 +2,18 @@
2#define _ASM_POWERPC_KEXEC_H 2#define _ASM_POWERPC_KEXEC_H
3#ifdef __KERNEL__ 3#ifdef __KERNEL__
4 4
5#ifdef CONFIG_FSL_BOOKE
6
7/*
8 * On FSL-BookE we setup a 1:1 mapping which covers the first 2GiB of memory
9 * and therefore we can only deal with memory within this range
10 */
11#define KEXEC_SOURCE_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL)
12#define KEXEC_DESTINATION_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL)
13#define KEXEC_CONTROL_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL)
14
15#else
16
5/* 17/*
6 * Maximum page that is mapped directly into kernel memory. 18 * Maximum page that is mapped directly into kernel memory.
7 * XXX: Since we copy virt we can use any page we allocate 19 * XXX: Since we copy virt we can use any page we allocate
@@ -21,6 +33,7 @@
21/* TASK_SIZE, probably left over from use_mm ?? */ 33/* TASK_SIZE, probably left over from use_mm ?? */
22#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE 34#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE
23#endif 35#endif
36#endif
24 37
25#define KEXEC_CONTROL_PAGE_SIZE 4096 38#define KEXEC_CONTROL_PAGE_SIZE 4096
26 39
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h
index 5304a37ba425..2360317179a9 100644
--- a/arch/powerpc/include/asm/reg_booke.h
+++ b/arch/powerpc/include/asm/reg_booke.h
@@ -4,6 +4,12 @@
4 * are not true Book E PowerPCs, they borrowed a number of features 4 * are not true Book E PowerPCs, they borrowed a number of features
5 * before Book E was finalized, and are included here as well. Unfortunatly, 5 * before Book E was finalized, and are included here as well. Unfortunatly,
6 * they sometimes used different locations than true Book E CPUs did. 6 * they sometimes used different locations than true Book E CPUs did.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation.
11 *
12 * Copyright 2009-2010 Freescale Semiconductor, Inc.
7 */ 13 */
8#ifdef __KERNEL__ 14#ifdef __KERNEL__
9#ifndef __ASM_POWERPC_REG_BOOKE_H__ 15#ifndef __ASM_POWERPC_REG_BOOKE_H__
@@ -88,6 +94,7 @@
88#define SPRN_IVOR35 0x213 /* Interrupt Vector Offset Register 35 */ 94#define SPRN_IVOR35 0x213 /* Interrupt Vector Offset Register 35 */
89#define SPRN_IVOR36 0x214 /* Interrupt Vector Offset Register 36 */ 95#define SPRN_IVOR36 0x214 /* Interrupt Vector Offset Register 36 */
90#define SPRN_IVOR37 0x215 /* Interrupt Vector Offset Register 37 */ 96#define SPRN_IVOR37 0x215 /* Interrupt Vector Offset Register 37 */
97#define SPRN_MCARU 0x239 /* Machine Check Address Register Upper */
91#define SPRN_MCSRR0 0x23A /* Machine Check Save and Restore Register 0 */ 98#define SPRN_MCSRR0 0x23A /* Machine Check Save and Restore Register 0 */
92#define SPRN_MCSRR1 0x23B /* Machine Check Save and Restore Register 1 */ 99#define SPRN_MCSRR1 0x23B /* Machine Check Save and Restore Register 1 */
93#define SPRN_MCSR 0x23C /* Machine Check Status Register */ 100#define SPRN_MCSR 0x23C /* Machine Check Status Register */
@@ -196,8 +203,11 @@
196#define PPC47x_MCSR_IPR 0x00400000 /* Imprecise Machine Check Exception */ 203#define PPC47x_MCSR_IPR 0x00400000 /* Imprecise Machine Check Exception */
197 204
198#ifdef CONFIG_E500 205#ifdef CONFIG_E500
206/* All e500 */
199#define MCSR_MCP 0x80000000UL /* Machine Check Input Pin */ 207#define MCSR_MCP 0x80000000UL /* Machine Check Input Pin */
200#define MCSR_ICPERR 0x40000000UL /* I-Cache Parity Error */ 208#define MCSR_ICPERR 0x40000000UL /* I-Cache Parity Error */
209
210/* e500v1/v2 */
201#define MCSR_DCP_PERR 0x20000000UL /* D-Cache Push Parity Error */ 211#define MCSR_DCP_PERR 0x20000000UL /* D-Cache Push Parity Error */
202#define MCSR_DCPERR 0x10000000UL /* D-Cache Parity Error */ 212#define MCSR_DCPERR 0x10000000UL /* D-Cache Parity Error */
203#define MCSR_BUS_IAERR 0x00000080UL /* Instruction Address Error */ 213#define MCSR_BUS_IAERR 0x00000080UL /* Instruction Address Error */
@@ -209,12 +219,20 @@
209#define MCSR_BUS_IPERR 0x00000002UL /* Instruction parity Error */ 219#define MCSR_BUS_IPERR 0x00000002UL /* Instruction parity Error */
210#define MCSR_BUS_RPERR 0x00000001UL /* Read parity Error */ 220#define MCSR_BUS_RPERR 0x00000001UL /* Read parity Error */
211 221
212/* e500 parts may set unused bits in MCSR; mask these off */ 222/* e500mc */
213#define MCSR_MASK (MCSR_MCP | MCSR_ICPERR | MCSR_DCP_PERR | \ 223#define MCSR_DCPERR_MC 0x20000000UL /* D-Cache Parity Error */
214 MCSR_DCPERR | MCSR_BUS_IAERR | MCSR_BUS_RAERR | \ 224#define MCSR_L2MMU_MHIT 0x04000000UL /* Hit on multiple TLB entries */
215 MCSR_BUS_WAERR | MCSR_BUS_IBERR | MCSR_BUS_RBERR | \ 225#define MCSR_NMI 0x00100000UL /* Non-Maskable Interrupt */
216 MCSR_BUS_WBERR | MCSR_BUS_IPERR | MCSR_BUS_RPERR) 226#define MCSR_MAV 0x00080000UL /* MCAR address valid */
227#define MCSR_MEA 0x00040000UL /* MCAR is effective address */
228#define MCSR_IF 0x00010000UL /* Instruction Fetch */
229#define MCSR_LD 0x00008000UL /* Load */
230#define MCSR_ST 0x00004000UL /* Store */
231#define MCSR_LDG 0x00002000UL /* Guarded Load */
232#define MCSR_TLBSYNC 0x00000002UL /* Multiple tlbsyncs detected */
233#define MCSR_BSL2_ERR 0x00000001UL /* Backside L2 cache error */
217#endif 234#endif
235
218#ifdef CONFIG_E200 236#ifdef CONFIG_E200
219#define MCSR_MCP 0x80000000UL /* Machine Check Input Pin */ 237#define MCSR_MCP 0x80000000UL /* Machine Check Input Pin */
220#define MCSR_CP_PERR 0x20000000UL /* Cache Push Parity Error */ 238#define MCSR_CP_PERR 0x20000000UL /* Cache Push Parity Error */
@@ -225,11 +243,6 @@
225#define MCSR_BUS_DRERR 0x00000008UL /* Read Bus Error on data load */ 243#define MCSR_BUS_DRERR 0x00000008UL /* Read Bus Error on data load */
226#define MCSR_BUS_WRERR 0x00000004UL /* Write Bus Error on buffered 244#define MCSR_BUS_WRERR 0x00000004UL /* Write Bus Error on buffered
227 store or cache line push */ 245 store or cache line push */
228
229/* e200 parts may set unused bits in MCSR; mask these off */
230#define MCSR_MASK (MCSR_MCP | MCSR_CP_PERR | MCSR_CPERR | \
231 MCSR_EXCP_ERR | MCSR_BUS_IRERR | MCSR_BUS_DRERR | \
232 MCSR_BUS_WRERR)
233#endif 246#endif
234 247
235/* Bit definitions for the DBSR. */ 248/* Bit definitions for the DBSR. */
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 877326320e74..58d0572de6f9 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -57,8 +57,12 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
57obj-$(CONFIG_E500) += idle_e500.o 57obj-$(CONFIG_E500) += idle_e500.o
58obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o 58obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
59obj-$(CONFIG_TAU) += tau_6xx.o 59obj-$(CONFIG_TAU) += tau_6xx.o
60obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o \ 60obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o
61 swsusp_$(CONFIG_WORD_SIZE).o 61ifeq ($(CONFIG_FSL_BOOKE),y)
62obj-$(CONFIG_HIBERNATION) += swsusp_booke.o
63else
64obj-$(CONFIG_HIBERNATION) += swsusp_$(CONFIG_WORD_SIZE).o
65endif
62obj64-$(CONFIG_HIBERNATION) += swsusp_asm64.o 66obj64-$(CONFIG_HIBERNATION) += swsusp_asm64.o
63obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o 67obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o
64obj-$(CONFIG_44x) += cpu_setup_44x.o 68obj-$(CONFIG_44x) += cpu_setup_44x.o
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 9556be903e96..87aa0f3c6047 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -1840,7 +1840,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
1840 .oprofile_cpu_type = "ppc/e500mc", 1840 .oprofile_cpu_type = "ppc/e500mc",
1841 .oprofile_type = PPC_OPROFILE_FSL_EMB, 1841 .oprofile_type = PPC_OPROFILE_FSL_EMB,
1842 .cpu_setup = __setup_cpu_e500mc, 1842 .cpu_setup = __setup_cpu_e500mc,
1843 .machine_check = machine_check_e500, 1843 .machine_check = machine_check_e500mc,
1844 .platform = "ppce500mc", 1844 .platform = "ppce500mc",
1845 }, 1845 },
1846 { /* default match */ 1846 { /* default match */
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
index 8c066d6a8e4b..b46f2e09bd81 100644
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -163,6 +163,7 @@ static void crash_kexec_prepare_cpus(int cpu)
163} 163}
164 164
165/* wait for all the CPUs to hit real mode but timeout if they don't come in */ 165/* wait for all the CPUs to hit real mode but timeout if they don't come in */
166#ifdef CONFIG_PPC_STD_MMU_64
166static void crash_kexec_wait_realmode(int cpu) 167static void crash_kexec_wait_realmode(int cpu)
167{ 168{
168 unsigned int msecs; 169 unsigned int msecs;
@@ -187,6 +188,7 @@ static void crash_kexec_wait_realmode(int cpu)
187 } 188 }
188 mb(); 189 mb();
189} 190}
191#endif
190 192
191/* 193/*
192 * This function will be called by secondary cpus or by kexec cpu 194 * This function will be called by secondary cpus or by kexec cpu
@@ -445,7 +447,9 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
445 crash_kexec_prepare_cpus(crashing_cpu); 447 crash_kexec_prepare_cpus(crashing_cpu);
446 cpu_set(crashing_cpu, cpus_in_crash); 448 cpu_set(crashing_cpu, cpus_in_crash);
447 crash_kexec_stop_spus(); 449 crash_kexec_stop_spus();
450#ifdef CONFIG_PPC_STD_MMU_64
448 crash_kexec_wait_realmode(crashing_cpu); 451 crash_kexec_wait_realmode(crashing_cpu);
452#endif
449 if (ppc_md.kexec_cpu_down) 453 if (ppc_md.kexec_cpu_down)
450 ppc_md.kexec_cpu_down(1, 0); 454 ppc_md.kexec_cpu_down(1, 0);
451} 455}
diff --git a/arch/powerpc/kernel/fsl_booke_entry_mapping.S b/arch/powerpc/kernel/fsl_booke_entry_mapping.S
new file mode 100644
index 000000000000..beb4d78a2304
--- /dev/null
+++ b/arch/powerpc/kernel/fsl_booke_entry_mapping.S
@@ -0,0 +1,237 @@
1
2/* 1. Find the index of the entry we're executing in */
3 bl invstr /* Find our address */
4invstr: mflr r6 /* Make it accessible */
5 mfmsr r7
6 rlwinm r4,r7,27,31,31 /* extract MSR[IS] */
7 mfspr r7, SPRN_PID0
8 slwi r7,r7,16
9 or r7,r7,r4
10 mtspr SPRN_MAS6,r7
11 tlbsx 0,r6 /* search MSR[IS], SPID=PID0 */
12 mfspr r7,SPRN_MAS1
13 andis. r7,r7,MAS1_VALID@h
14 bne match_TLB
15
16 mfspr r7,SPRN_MMUCFG
17 rlwinm r7,r7,21,28,31 /* extract MMUCFG[NPIDS] */
18 cmpwi r7,3
19 bne match_TLB /* skip if NPIDS != 3 */
20
21 mfspr r7,SPRN_PID1
22 slwi r7,r7,16
23 or r7,r7,r4
24 mtspr SPRN_MAS6,r7
25 tlbsx 0,r6 /* search MSR[IS], SPID=PID1 */
26 mfspr r7,SPRN_MAS1
27 andis. r7,r7,MAS1_VALID@h
28 bne match_TLB
29 mfspr r7, SPRN_PID2
30 slwi r7,r7,16
31 or r7,r7,r4
32 mtspr SPRN_MAS6,r7
33 tlbsx 0,r6 /* Fall through, we had to match */
34
35match_TLB:
36 mfspr r7,SPRN_MAS0
37 rlwinm r3,r7,16,20,31 /* Extract MAS0(Entry) */
38
39 mfspr r7,SPRN_MAS1 /* Insure IPROT set */
40 oris r7,r7,MAS1_IPROT@h
41 mtspr SPRN_MAS1,r7
42 tlbwe
43
44/* 2. Invalidate all entries except the entry we're executing in */
45 mfspr r9,SPRN_TLB1CFG
46 andi. r9,r9,0xfff
47 li r6,0 /* Set Entry counter to 0 */
481: lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
49 rlwimi r7,r6,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r6) */
50 mtspr SPRN_MAS0,r7
51 tlbre
52 mfspr r7,SPRN_MAS1
53 rlwinm r7,r7,0,2,31 /* Clear MAS1 Valid and IPROT */
54 cmpw r3,r6
55 beq skpinv /* Dont update the current execution TLB */
56 mtspr SPRN_MAS1,r7
57 tlbwe
58 isync
59skpinv: addi r6,r6,1 /* Increment */
60 cmpw r6,r9 /* Are we done? */
61 bne 1b /* If not, repeat */
62
63 /* Invalidate TLB0 */
64 li r6,0x04
65 tlbivax 0,r6
66 TLBSYNC
67 /* Invalidate TLB1 */
68 li r6,0x0c
69 tlbivax 0,r6
70 TLBSYNC
71
72/* 3. Setup a temp mapping and jump to it */
73 andi. r5, r3, 0x1 /* Find an entry not used and is non-zero */
74 addi r5, r5, 0x1
75 lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
76 rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */
77 mtspr SPRN_MAS0,r7
78 tlbre
79
80 /* grab and fixup the RPN */
81 mfspr r6,SPRN_MAS1 /* extract MAS1[SIZE] */
82 rlwinm r6,r6,25,27,31
83 li r8,-1
84 addi r6,r6,10
85 slw r6,r8,r6 /* convert to mask */
86
87 bl 1f /* Find our address */
881: mflr r7
89
90 mfspr r8,SPRN_MAS3
91#ifdef CONFIG_PHYS_64BIT
92 mfspr r23,SPRN_MAS7
93#endif
94 and r8,r6,r8
95 subfic r9,r6,-4096
96 and r9,r9,r7
97
98 or r25,r8,r9
99 ori r8,r25,(MAS3_SX|MAS3_SW|MAS3_SR)
100
101 /* Just modify the entry ID and EPN for the temp mapping */
102 lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
103 rlwimi r7,r5,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r5) */
104 mtspr SPRN_MAS0,r7
105 xori r6,r4,1 /* Setup TMP mapping in the other Address space */
106 slwi r6,r6,12
107 oris r6,r6,(MAS1_VALID|MAS1_IPROT)@h
108 ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_4K))@l
109 mtspr SPRN_MAS1,r6
110 mfspr r6,SPRN_MAS2
111 li r7,0 /* temp EPN = 0 */
112 rlwimi r7,r6,0,20,31
113 mtspr SPRN_MAS2,r7
114 mtspr SPRN_MAS3,r8
115 tlbwe
116
117 xori r6,r4,1
118 slwi r6,r6,5 /* setup new context with other address space */
119 bl 1f /* Find our address */
1201: mflr r9
121 rlwimi r7,r9,0,20,31
122 addi r7,r7,(2f - 1b)
123 mtspr SPRN_SRR0,r7
124 mtspr SPRN_SRR1,r6
125 rfi
1262:
127/* 4. Clear out PIDs & Search info */
128 li r6,0
129 mtspr SPRN_MAS6,r6
130 mtspr SPRN_PID0,r6
131
132 mfspr r7,SPRN_MMUCFG
133 rlwinm r7,r7,21,28,31 /* extract MMUCFG[NPIDS] */
134 cmpwi r7,3
135 bne 2f /* skip if NPIDS != 3 */
136
137 mtspr SPRN_PID1,r6
138 mtspr SPRN_PID2,r6
139
140/* 5. Invalidate mapping we started in */
1412:
142 lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
143 rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */
144 mtspr SPRN_MAS0,r7
145 tlbre
146 mfspr r6,SPRN_MAS1
147 rlwinm r6,r6,0,2,0 /* clear IPROT */
148 mtspr SPRN_MAS1,r6
149 tlbwe
150 /* Invalidate TLB1 */
151 li r9,0x0c
152 tlbivax 0,r9
153 TLBSYNC
154
155/* The mapping only needs to be cache-coherent on SMP */
156#ifdef CONFIG_SMP
157#define M_IF_SMP MAS2_M
158#else
159#define M_IF_SMP 0
160#endif
161
162#if defined(ENTRY_MAPPING_BOOT_SETUP)
163
164/* 6. Setup KERNELBASE mapping in TLB1[0] */
165 lis r6,0x1000 /* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */
166 mtspr SPRN_MAS0,r6
167 lis r6,(MAS1_VALID|MAS1_IPROT)@h
168 ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_64M))@l
169 mtspr SPRN_MAS1,r6
170 lis r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@h
171 ori r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@l
172 mtspr SPRN_MAS2,r6
173 mtspr SPRN_MAS3,r8
174 tlbwe
175
176/* 7. Jump to KERNELBASE mapping */
177 lis r6,(KERNELBASE & ~0xfff)@h
178 ori r6,r6,(KERNELBASE & ~0xfff)@l
179
180#elif defined(ENTRY_MAPPING_KEXEC_SETUP)
181/*
182 * 6. Setup a 1:1 mapping in TLB1. Esel 0 is unsued, 1 or 2 contains the tmp
183 * mapping so we start at 3. We setup 8 mappings, each 256MiB in size. This
184 * will cover the first 2GiB of memory.
185 */
186
187 lis r10, (MAS1_VALID|MAS1_IPROT)@h
188 ori r10,r10, (MAS1_TSIZE(BOOK3E_PAGESZ_256M))@l
189 li r11, 0
190 li r0, 8
191 mtctr r0
192
193next_tlb_setup:
194 addi r0, r11, 3
195 rlwinm r0, r0, 16, 4, 15 // Compute esel
196 rlwinm r9, r11, 28, 0, 3 // Compute [ER]PN
197 oris r0, r0, (MAS0_TLBSEL(1))@h
198 mtspr SPRN_MAS0,r0
199 mtspr SPRN_MAS1,r10
200 mtspr SPRN_MAS2,r9
201 ori r9, r9, (MAS3_SX|MAS3_SW|MAS3_SR)
202 mtspr SPRN_MAS3,r9
203 tlbwe
204 addi r11, r11, 1
205 bdnz+ next_tlb_setup
206
207/* 7. Jump to our 1:1 mapping */
208 li r6, 0
209
210#else
211 #error You need to specify the mapping or not use this at all.
212#endif
213
214 lis r7,MSR_KERNEL@h
215 ori r7,r7,MSR_KERNEL@l
216 bl 1f /* Find our address */
2171: mflr r9
218 rlwimi r6,r9,0,20,31
219 addi r6,r6,(2f - 1b)
220 add r6, r6, r25
221 mtspr SPRN_SRR0,r6
222 mtspr SPRN_SRR1,r7
223 rfi /* start execution out of TLB1[0] entry */
224
225/* 8. Clear out the temp mapping */
2262: lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
227 rlwimi r7,r5,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r5) */
228 mtspr SPRN_MAS0,r7
229 tlbre
230 mfspr r8,SPRN_MAS1
231 rlwinm r8,r8,0,2,0 /* clear IPROT */
232 mtspr SPRN_MAS1,r8
233 tlbwe
234 /* Invalidate TLB1 */
235 li r9,0x0c
236 tlbivax 0,r9
237 TLBSYNC
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index edd4a57fd29e..4faeba247854 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -94,204 +94,10 @@ _ENTRY(_start);
94 */ 94 */
95 95
96_ENTRY(__early_start) 96_ENTRY(__early_start)
97/* 1. Find the index of the entry we're executing in */
98 bl invstr /* Find our address */
99invstr: mflr r6 /* Make it accessible */
100 mfmsr r7
101 rlwinm r4,r7,27,31,31 /* extract MSR[IS] */
102 mfspr r7, SPRN_PID0
103 slwi r7,r7,16
104 or r7,r7,r4
105 mtspr SPRN_MAS6,r7
106 tlbsx 0,r6 /* search MSR[IS], SPID=PID0 */
107 mfspr r7,SPRN_MAS1
108 andis. r7,r7,MAS1_VALID@h
109 bne match_TLB
110
111 mfspr r7,SPRN_MMUCFG
112 rlwinm r7,r7,21,28,31 /* extract MMUCFG[NPIDS] */
113 cmpwi r7,3
114 bne match_TLB /* skip if NPIDS != 3 */
115
116 mfspr r7,SPRN_PID1
117 slwi r7,r7,16
118 or r7,r7,r4
119 mtspr SPRN_MAS6,r7
120 tlbsx 0,r6 /* search MSR[IS], SPID=PID1 */
121 mfspr r7,SPRN_MAS1
122 andis. r7,r7,MAS1_VALID@h
123 bne match_TLB
124 mfspr r7, SPRN_PID2
125 slwi r7,r7,16
126 or r7,r7,r4
127 mtspr SPRN_MAS6,r7
128 tlbsx 0,r6 /* Fall through, we had to match */
129
130match_TLB:
131 mfspr r7,SPRN_MAS0
132 rlwinm r3,r7,16,20,31 /* Extract MAS0(Entry) */
133
134 mfspr r7,SPRN_MAS1 /* Insure IPROT set */
135 oris r7,r7,MAS1_IPROT@h
136 mtspr SPRN_MAS1,r7
137 tlbwe
138
139/* 2. Invalidate all entries except the entry we're executing in */
140 mfspr r9,SPRN_TLB1CFG
141 andi. r9,r9,0xfff
142 li r6,0 /* Set Entry counter to 0 */
1431: lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
144 rlwimi r7,r6,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r6) */
145 mtspr SPRN_MAS0,r7
146 tlbre
147 mfspr r7,SPRN_MAS1
148 rlwinm r7,r7,0,2,31 /* Clear MAS1 Valid and IPROT */
149 cmpw r3,r6
150 beq skpinv /* Dont update the current execution TLB */
151 mtspr SPRN_MAS1,r7
152 tlbwe
153 isync
154skpinv: addi r6,r6,1 /* Increment */
155 cmpw r6,r9 /* Are we done? */
156 bne 1b /* If not, repeat */
157
158 /* Invalidate TLB0 */
159 li r6,0x04
160 tlbivax 0,r6
161 TLBSYNC
162 /* Invalidate TLB1 */
163 li r6,0x0c
164 tlbivax 0,r6
165 TLBSYNC
166
167/* 3. Setup a temp mapping and jump to it */
168 andi. r5, r3, 0x1 /* Find an entry not used and is non-zero */
169 addi r5, r5, 0x1
170 lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
171 rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */
172 mtspr SPRN_MAS0,r7
173 tlbre
174
175 /* grab and fixup the RPN */
176 mfspr r6,SPRN_MAS1 /* extract MAS1[SIZE] */
177 rlwinm r6,r6,25,27,31
178 li r8,-1
179 addi r6,r6,10
180 slw r6,r8,r6 /* convert to mask */
181
182 bl 1f /* Find our address */
1831: mflr r7
184
185 mfspr r8,SPRN_MAS3
186#ifdef CONFIG_PHYS_64BIT
187 mfspr r23,SPRN_MAS7
188#endif
189 and r8,r6,r8
190 subfic r9,r6,-4096
191 and r9,r9,r7
192
193 or r25,r8,r9
194 ori r8,r25,(MAS3_SX|MAS3_SW|MAS3_SR)
195
196 /* Just modify the entry ID and EPN for the temp mapping */
197 lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
198 rlwimi r7,r5,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r5) */
199 mtspr SPRN_MAS0,r7
200 xori r6,r4,1 /* Setup TMP mapping in the other Address space */
201 slwi r6,r6,12
202 oris r6,r6,(MAS1_VALID|MAS1_IPROT)@h
203 ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_4K))@l
204 mtspr SPRN_MAS1,r6
205 mfspr r6,SPRN_MAS2
206 li r7,0 /* temp EPN = 0 */
207 rlwimi r7,r6,0,20,31
208 mtspr SPRN_MAS2,r7
209 mtspr SPRN_MAS3,r8
210 tlbwe
211
212 xori r6,r4,1
213 slwi r6,r6,5 /* setup new context with other address space */
214 bl 1f /* Find our address */
2151: mflr r9
216 rlwimi r7,r9,0,20,31
217 addi r7,r7,(2f - 1b)
218 mtspr SPRN_SRR0,r7
219 mtspr SPRN_SRR1,r6
220 rfi
2212:
222/* 4. Clear out PIDs & Search info */
223 li r6,0
224 mtspr SPRN_MAS6,r6
225 mtspr SPRN_PID0,r6
226
227 mfspr r7,SPRN_MMUCFG
228 rlwinm r7,r7,21,28,31 /* extract MMUCFG[NPIDS] */
229 cmpwi r7,3
230 bne 2f /* skip if NPIDS != 3 */
231 97
232 mtspr SPRN_PID1,r6 98#define ENTRY_MAPPING_BOOT_SETUP
233 mtspr SPRN_PID2,r6 99#include "fsl_booke_entry_mapping.S"
234 100#undef ENTRY_MAPPING_BOOT_SETUP
235/* 5. Invalidate mapping we started in */
2362:
237 lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
238 rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */
239 mtspr SPRN_MAS0,r7
240 tlbre
241 mfspr r6,SPRN_MAS1
242 rlwinm r6,r6,0,2,0 /* clear IPROT */
243 mtspr SPRN_MAS1,r6
244 tlbwe
245 /* Invalidate TLB1 */
246 li r9,0x0c
247 tlbivax 0,r9
248 TLBSYNC
249
250/* The mapping only needs to be cache-coherent on SMP */
251#ifdef CONFIG_SMP
252#define M_IF_SMP MAS2_M
253#else
254#define M_IF_SMP 0
255#endif
256
257/* 6. Setup KERNELBASE mapping in TLB1[0] */
258 lis r6,0x1000 /* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */
259 mtspr SPRN_MAS0,r6
260 lis r6,(MAS1_VALID|MAS1_IPROT)@h
261 ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_64M))@l
262 mtspr SPRN_MAS1,r6
263 lis r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@h
264 ori r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@l
265 mtspr SPRN_MAS2,r6
266 mtspr SPRN_MAS3,r8
267 tlbwe
268
269/* 7. Jump to KERNELBASE mapping */
270 lis r6,(KERNELBASE & ~0xfff)@h
271 ori r6,r6,(KERNELBASE & ~0xfff)@l
272 lis r7,MSR_KERNEL@h
273 ori r7,r7,MSR_KERNEL@l
274 bl 1f /* Find our address */
2751: mflr r9
276 rlwimi r6,r9,0,20,31
277 addi r6,r6,(2f - 1b)
278 mtspr SPRN_SRR0,r6
279 mtspr SPRN_SRR1,r7
280 rfi /* start execution out of TLB1[0] entry */
281
282/* 8. Clear out the temp mapping */
2832: lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
284 rlwimi r7,r5,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r5) */
285 mtspr SPRN_MAS0,r7
286 tlbre
287 mfspr r8,SPRN_MAS1
288 rlwinm r8,r8,0,2,0 /* clear IPROT */
289 mtspr SPRN_MAS1,r8
290 tlbwe
291 /* Invalidate TLB1 */
292 li r9,0x0c
293 tlbivax 0,r9
294 TLBSYNC
295 101
296 /* Establish the interrupt vector offsets */ 102 /* Establish the interrupt vector offsets */
297 SET_IVOR(0, CriticalInput); 103 SET_IVOR(0, CriticalInput);
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 8043d1b73cf0..dc66d52dcff5 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -711,6 +711,22 @@ relocate_new_kernel:
711 /* r4 = reboot_code_buffer */ 711 /* r4 = reboot_code_buffer */
712 /* r5 = start_address */ 712 /* r5 = start_address */
713 713
714#ifdef CONFIG_FSL_BOOKE
715
716 mr r29, r3
717 mr r30, r4
718 mr r31, r5
719
720#define ENTRY_MAPPING_KEXEC_SETUP
721#include "fsl_booke_entry_mapping.S"
722#undef ENTRY_MAPPING_KEXEC_SETUP
723
724 mr r3, r29
725 mr r4, r30
726 mr r5, r31
727
728 li r0, 0
729#else
714 li r0, 0 730 li r0, 0
715 731
716 /* 732 /*
@@ -727,6 +743,7 @@ relocate_new_kernel:
727 rfi 743 rfi
728 744
7291: 7451:
746#endif
730 /* from this point address translation is turned off */ 747 /* from this point address translation is turned off */
731 /* and interrupts are disabled */ 748 /* and interrupts are disabled */
732 749
diff --git a/arch/powerpc/kernel/swsusp_booke.S b/arch/powerpc/kernel/swsusp_booke.S
new file mode 100644
index 000000000000..11a39307dd71
--- /dev/null
+++ b/arch/powerpc/kernel/swsusp_booke.S
@@ -0,0 +1,193 @@
1/*
2 * Based on swsusp_32.S, modified for FSL BookE by
3 * Anton Vorontsov <avorontsov@ru.mvista.com>
4 * Copyright (c) 2009-2010 MontaVista Software, LLC.
5 */
6
7#include <linux/threads.h>
8#include <asm/processor.h>
9#include <asm/page.h>
10#include <asm/cputable.h>
11#include <asm/thread_info.h>
12#include <asm/ppc_asm.h>
13#include <asm/asm-offsets.h>
14#include <asm/mmu.h>
15
16/*
17 * Structure for storing CPU registers on the save area.
18 */
19#define SL_SP 0
20#define SL_PC 4
21#define SL_MSR 8
22#define SL_TCR 0xc
23#define SL_SPRG0 0x10
24#define SL_SPRG1 0x14
25#define SL_SPRG2 0x18
26#define SL_SPRG3 0x1c
27#define SL_SPRG4 0x20
28#define SL_SPRG5 0x24
29#define SL_SPRG6 0x28
30#define SL_SPRG7 0x2c
31#define SL_TBU 0x30
32#define SL_TBL 0x34
33#define SL_R2 0x38
34#define SL_CR 0x3c
35#define SL_LR 0x40
36#define SL_R12 0x44 /* r12 to r31 */
37#define SL_SIZE (SL_R12 + 80)
38
39 .section .data
40 .align 5
41
42_GLOBAL(swsusp_save_area)
43 .space SL_SIZE
44
45
46 .section .text
47 .align 5
48
49_GLOBAL(swsusp_arch_suspend)
50 lis r11,swsusp_save_area@h
51 ori r11,r11,swsusp_save_area@l
52
53 mflr r0
54 stw r0,SL_LR(r11)
55 mfcr r0
56 stw r0,SL_CR(r11)
57 stw r1,SL_SP(r11)
58 stw r2,SL_R2(r11)
59 stmw r12,SL_R12(r11)
60
61 /* Save MSR & TCR */
62 mfmsr r4
63 stw r4,SL_MSR(r11)
64 mfspr r4,SPRN_TCR
65 stw r4,SL_TCR(r11)
66
67 /* Get a stable timebase and save it */
681: mfspr r4,SPRN_TBRU
69 stw r4,SL_TBU(r11)
70 mfspr r5,SPRN_TBRL
71 stw r5,SL_TBL(r11)
72 mfspr r3,SPRN_TBRU
73 cmpw r3,r4
74 bne 1b
75
76 /* Save SPRGs */
77 mfsprg r4,0
78 stw r4,SL_SPRG0(r11)
79 mfsprg r4,1
80 stw r4,SL_SPRG1(r11)
81 mfsprg r4,2
82 stw r4,SL_SPRG2(r11)
83 mfsprg r4,3
84 stw r4,SL_SPRG3(r11)
85 mfsprg r4,4
86 stw r4,SL_SPRG4(r11)
87 mfsprg r4,5
88 stw r4,SL_SPRG5(r11)
89 mfsprg r4,6
90 stw r4,SL_SPRG6(r11)
91 mfsprg r4,7
92 stw r4,SL_SPRG7(r11)
93
94 /* Call the low level suspend stuff (we should probably have made
95 * a stackframe...
96 */
97 bl swsusp_save
98
99 /* Restore LR from the save area */
100 lis r11,swsusp_save_area@h
101 ori r11,r11,swsusp_save_area@l
102 lwz r0,SL_LR(r11)
103 mtlr r0
104
105 blr
106
107_GLOBAL(swsusp_arch_resume)
108 sync
109
110 /* Load ptr the list of pages to copy in r3 */
111 lis r11,(restore_pblist)@h
112 ori r11,r11,restore_pblist@l
113 lwz r3,0(r11)
114
115 /* Copy the pages. This is a very basic implementation, to
116 * be replaced by something more cache efficient */
1171:
118 li r0,256
119 mtctr r0
120 lwz r5,pbe_address(r3) /* source */
121 lwz r6,pbe_orig_address(r3) /* destination */
1222:
123 lwz r8,0(r5)
124 lwz r9,4(r5)
125 lwz r10,8(r5)
126 lwz r11,12(r5)
127 addi r5,r5,16
128 stw r8,0(r6)
129 stw r9,4(r6)
130 stw r10,8(r6)
131 stw r11,12(r6)
132 addi r6,r6,16
133 bdnz 2b
134 lwz r3,pbe_next(r3)
135 cmpwi 0,r3,0
136 bne 1b
137
138 bl flush_dcache_L1
139 bl flush_instruction_cache
140
141 lis r11,swsusp_save_area@h
142 ori r11,r11,swsusp_save_area@l
143
144 lwz r4,SL_SPRG0(r11)
145 mtsprg 0,r4
146 lwz r4,SL_SPRG1(r11)
147 mtsprg 1,r4
148 lwz r4,SL_SPRG2(r11)
149 mtsprg 2,r4
150 lwz r4,SL_SPRG3(r11)
151 mtsprg 3,r4
152 lwz r4,SL_SPRG4(r11)
153 mtsprg 4,r4
154 lwz r4,SL_SPRG5(r11)
155 mtsprg 5,r4
156 lwz r4,SL_SPRG6(r11)
157 mtsprg 6,r4
158 lwz r4,SL_SPRG7(r11)
159 mtsprg 7,r4
160
161 /* restore the MSR */
162 lwz r3,SL_MSR(r11)
163 mtmsr r3
164
165 /* Restore TB */
166 li r3,0
167 mtspr SPRN_TBWL,r3
168 lwz r3,SL_TBU(r11)
169 lwz r4,SL_TBL(r11)
170 mtspr SPRN_TBWU,r3
171 mtspr SPRN_TBWL,r4
172
173 /* Restore TCR and clear any pending bits in TSR. */
174 lwz r4,SL_TCR(r11)
175 mtspr SPRN_TCR,r4
176 lis r4, (TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS)@h
177 mtspr SPRN_TSR,r4
178
179 /* Kick decrementer */
180 li r0,1
181 mtdec r0
182
183 /* Restore the callee-saved registers and return */
184 lwz r0,SL_CR(r11)
185 mtcr r0
186 lwz r2,SL_R2(r11)
187 lmw r12,SL_R12(r11)
188 lwz r1,SL_SP(r11)
189 lwz r0,SL_LR(r11)
190 mtlr r0
191
192 li r3,0
193 blr
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 3031fc712ad0..25fc33984c2b 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 2 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
3 * Copyright 2007-2010 Freescale Semiconductor, Inc.
3 * 4 *
4 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License 6 * modify it under the terms of the GNU General Public License
@@ -305,7 +306,7 @@ static inline int check_io_access(struct pt_regs *regs)
305#ifndef CONFIG_FSL_BOOKE 306#ifndef CONFIG_FSL_BOOKE
306#define get_mc_reason(regs) ((regs)->dsisr) 307#define get_mc_reason(regs) ((regs)->dsisr)
307#else 308#else
308#define get_mc_reason(regs) (mfspr(SPRN_MCSR) & MCSR_MASK) 309#define get_mc_reason(regs) (mfspr(SPRN_MCSR))
309#endif 310#endif
310#define REASON_FP ESR_FP 311#define REASON_FP ESR_FP
311#define REASON_ILLEGAL (ESR_PIL | ESR_PUO) 312#define REASON_ILLEGAL (ESR_PIL | ESR_PUO)
@@ -421,6 +422,91 @@ int machine_check_47x(struct pt_regs *regs)
421 return 0; 422 return 0;
422} 423}
423#elif defined(CONFIG_E500) 424#elif defined(CONFIG_E500)
425int machine_check_e500mc(struct pt_regs *regs)
426{
427 unsigned long mcsr = mfspr(SPRN_MCSR);
428 unsigned long reason = mcsr;
429 int recoverable = 1;
430
431 printk("Machine check in kernel mode.\n");
432 printk("Caused by (from MCSR=%lx): ", reason);
433
434 if (reason & MCSR_MCP)
435 printk("Machine Check Signal\n");
436
437 if (reason & MCSR_ICPERR) {
438 printk("Instruction Cache Parity Error\n");
439
440 /*
441 * This is recoverable by invalidating the i-cache.
442 */
443 mtspr(SPRN_L1CSR1, mfspr(SPRN_L1CSR1) | L1CSR1_ICFI);
444 while (mfspr(SPRN_L1CSR1) & L1CSR1_ICFI)
445 ;
446
447 /*
448 * This will generally be accompanied by an instruction
449 * fetch error report -- only treat MCSR_IF as fatal
450 * if it wasn't due to an L1 parity error.
451 */
452 reason &= ~MCSR_IF;
453 }
454
455 if (reason & MCSR_DCPERR_MC) {
456 printk("Data Cache Parity Error\n");
457 recoverable = 0;
458 }
459
460 if (reason & MCSR_L2MMU_MHIT) {
461 printk("Hit on multiple TLB entries\n");
462 recoverable = 0;
463 }
464
465 if (reason & MCSR_NMI)
466 printk("Non-maskable interrupt\n");
467
468 if (reason & MCSR_IF) {
469 printk("Instruction Fetch Error Report\n");
470 recoverable = 0;
471 }
472
473 if (reason & MCSR_LD) {
474 printk("Load Error Report\n");
475 recoverable = 0;
476 }
477
478 if (reason & MCSR_ST) {
479 printk("Store Error Report\n");
480 recoverable = 0;
481 }
482
483 if (reason & MCSR_LDG) {
484 printk("Guarded Load Error Report\n");
485 recoverable = 0;
486 }
487
488 if (reason & MCSR_TLBSYNC)
489 printk("Simultaneous tlbsync operations\n");
490
491 if (reason & MCSR_BSL2_ERR) {
492 printk("Level 2 Cache Error\n");
493 recoverable = 0;
494 }
495
496 if (reason & MCSR_MAV) {
497 u64 addr;
498
499 addr = mfspr(SPRN_MCAR);
500 addr |= (u64)mfspr(SPRN_MCARU) << 32;
501
502 printk("Machine Check %s Address: %#llx\n",
503 reason & MCSR_MEA ? "Effective" : "Physical", addr);
504 }
505
506 mtspr(SPRN_MCSR, mcsr);
507 return mfspr(SPRN_MCSR) == 0 && recoverable;
508}
509
424int machine_check_e500(struct pt_regs *regs) 510int machine_check_e500(struct pt_regs *regs)
425{ 511{
426 unsigned long reason = get_mc_reason(regs); 512 unsigned long reason = get_mc_reason(regs);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index f0684c8ac960..8fe87fc61485 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) Freescale Semicondutor, Inc. 2006-2007. All rights reserved. 2 * Copyright (C) Freescale Semicondutor, Inc. 2006-2010. All rights reserved.
3 * 3 *
4 * Author: Andy Fleming <afleming@freescale.com> 4 * Author: Andy Fleming <afleming@freescale.com>
5 * 5 *
@@ -154,6 +154,10 @@ static int mpc8568_mds_phy_fixups(struct phy_device *phydev)
154 * Setup the architecture 154 * Setup the architecture
155 * 155 *
156 */ 156 */
157#ifdef CONFIG_SMP
158extern void __init mpc85xx_smp_init(void);
159#endif
160
157static void __init mpc85xx_mds_setup_arch(void) 161static void __init mpc85xx_mds_setup_arch(void)
158{ 162{
159 struct device_node *np; 163 struct device_node *np;
@@ -194,6 +198,10 @@ static void __init mpc85xx_mds_setup_arch(void)
194 } 198 }
195#endif 199#endif
196 200
201#ifdef CONFIG_SMP
202 mpc85xx_smp_init();
203#endif
204
197#ifdef CONFIG_QUICC_ENGINE 205#ifdef CONFIG_QUICC_ENGINE
198 np = of_find_compatible_node(NULL, NULL, "fsl,qe"); 206 np = of_find_compatible_node(NULL, NULL, "fsl,qe");
199 if (!np) { 207 if (!np) {
@@ -271,9 +279,49 @@ static void __init mpc85xx_mds_setup_arch(void)
271 BCSR_UCC_RGMII, BCSR_UCC_RTBI); 279 BCSR_UCC_RGMII, BCSR_UCC_RTBI);
272 } 280 }
273 281
282 } else if (machine_is(p1021_mds)) {
283#define BCSR11_ENET_MICRST (0x1 << 5)
284 /* Reset Micrel PHY */
285 clrbits8(&bcsr_regs[11], BCSR11_ENET_MICRST);
286 setbits8(&bcsr_regs[11], BCSR11_ENET_MICRST);
274 } 287 }
288
275 iounmap(bcsr_regs); 289 iounmap(bcsr_regs);
276 } 290 }
291
292 if (machine_is(p1021_mds)) {
293#define MPC85xx_PMUXCR_OFFSET 0x60
294#define MPC85xx_PMUXCR_QE0 0x00008000
295#define MPC85xx_PMUXCR_QE3 0x00001000
296#define MPC85xx_PMUXCR_QE9 0x00000040
297#define MPC85xx_PMUXCR_QE12 0x00000008
298 static __be32 __iomem *pmuxcr;
299
300 np = of_find_node_by_name(NULL, "global-utilities");
301
302 if (np) {
303 pmuxcr = of_iomap(np, 0) + MPC85xx_PMUXCR_OFFSET;
304
305 if (!pmuxcr)
306 printk(KERN_EMERG "Error: Alternate function"
307 " signal multiplex control register not"
308 " mapped!\n");
309 else
310 /* P1021 has pins muxed for QE and other functions. To
311 * enable QE UEC mode, we need to set bit QE0 for UCC1
312 * in Eth mode, QE0 and QE3 for UCC5 in Eth mode, QE9
313 * and QE12 for QE MII management singals in PMUXCR
314 * register.
315 */
316 setbits32(pmuxcr, MPC85xx_PMUXCR_QE0 |
317 MPC85xx_PMUXCR_QE3 |
318 MPC85xx_PMUXCR_QE9 |
319 MPC85xx_PMUXCR_QE12);
320
321 of_node_put(np);
322 }
323
324 }
277#endif /* CONFIG_QUICC_ENGINE */ 325#endif /* CONFIG_QUICC_ENGINE */
278 326
279#ifdef CONFIG_SWIOTLB 327#ifdef CONFIG_SWIOTLB
@@ -330,6 +378,16 @@ static struct of_device_id mpc85xx_ids[] = {
330 {}, 378 {},
331}; 379};
332 380
381static struct of_device_id p1021_ids[] = {
382 { .type = "soc", },
383 { .compatible = "soc", },
384 { .compatible = "simple-bus", },
385 { .type = "qe", },
386 { .compatible = "fsl,qe", },
387 { .compatible = "gianfar", },
388 {},
389};
390
333static int __init mpc85xx_publish_devices(void) 391static int __init mpc85xx_publish_devices(void)
334{ 392{
335 if (machine_is(mpc8568_mds)) 393 if (machine_is(mpc8568_mds))
@@ -342,11 +400,22 @@ static int __init mpc85xx_publish_devices(void)
342 400
343 return 0; 401 return 0;
344} 402}
403
404static int __init p1021_publish_devices(void)
405{
406 /* Publish the QE devices */
407 of_platform_bus_probe(NULL, p1021_ids, NULL);
408
409 return 0;
410}
411
345machine_device_initcall(mpc8568_mds, mpc85xx_publish_devices); 412machine_device_initcall(mpc8568_mds, mpc85xx_publish_devices);
346machine_device_initcall(mpc8569_mds, mpc85xx_publish_devices); 413machine_device_initcall(mpc8569_mds, mpc85xx_publish_devices);
414machine_device_initcall(p1021_mds, p1021_publish_devices);
347 415
348machine_arch_initcall(mpc8568_mds, swiotlb_setup_bus_notifier); 416machine_arch_initcall(mpc8568_mds, swiotlb_setup_bus_notifier);
349machine_arch_initcall(mpc8569_mds, swiotlb_setup_bus_notifier); 417machine_arch_initcall(mpc8569_mds, swiotlb_setup_bus_notifier);
418machine_arch_initcall(p1021_mds, swiotlb_setup_bus_notifier);
350 419
351static void __init mpc85xx_mds_pic_init(void) 420static void __init mpc85xx_mds_pic_init(void)
352{ 421{
@@ -366,7 +435,7 @@ static void __init mpc85xx_mds_pic_init(void)
366 435
367 mpic = mpic_alloc(np, r.start, 436 mpic = mpic_alloc(np, r.start,
368 MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN | 437 MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN |
369 MPIC_BROKEN_FRR_NIRQS, 438 MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU,
370 0, 256, " OpenPIC "); 439 0, 256, " OpenPIC ");
371 BUG_ON(mpic == NULL); 440 BUG_ON(mpic == NULL);
372 of_node_put(np); 441 of_node_put(np);
@@ -380,7 +449,11 @@ static void __init mpc85xx_mds_pic_init(void)
380 if (!np) 449 if (!np)
381 return; 450 return;
382 } 451 }
383 qe_ic_init(np, 0, qe_ic_cascade_muxed_mpic, NULL); 452 if (machine_is(p1021_mds))
453 qe_ic_init(np, 0, qe_ic_cascade_low_mpic,
454 qe_ic_cascade_high_mpic);
455 else
456 qe_ic_init(np, 0, qe_ic_cascade_muxed_mpic, NULL);
384 of_node_put(np); 457 of_node_put(np);
385#endif /* CONFIG_QUICC_ENGINE */ 458#endif /* CONFIG_QUICC_ENGINE */
386} 459}
@@ -426,3 +499,26 @@ define_machine(mpc8569_mds) {
426 .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 499 .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
427#endif 500#endif
428}; 501};
502
503static int __init p1021_mds_probe(void)
504{
505 unsigned long root = of_get_flat_dt_root();
506
507 return of_flat_dt_is_compatible(root, "fsl,P1021MDS");
508
509}
510
511define_machine(p1021_mds) {
512 .name = "P1021 MDS",
513 .probe = p1021_mds_probe,
514 .setup_arch = mpc85xx_mds_setup_arch,
515 .init_IRQ = mpc85xx_mds_pic_init,
516 .get_irq = mpic_get_irq,
517 .restart = fsl_rstcr_restart,
518 .calibrate_decr = generic_calibrate_decr,
519 .progress = udbg_progress,
520#ifdef CONFIG_PCI
521 .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
522#endif
523};
524
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index a7be144f5874..0f5bee90ee4e 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2007-2008 Freescale Semiconductor, Inc. All rights reserved. 2 * Copyright (C) 2007-2010 Freescale Semiconductor, Inc.
3 * 3 *
4 * Author: Tony Li <tony.li@freescale.com> 4 * Author: Tony Li <tony.li@freescale.com>
5 * Jason Jin <Jason.jin@freescale.com> 5 * Jason Jin <Jason.jin@freescale.com>
@@ -22,14 +22,20 @@
22#include <asm/prom.h> 22#include <asm/prom.h>
23#include <asm/hw_irq.h> 23#include <asm/hw_irq.h>
24#include <asm/ppc-pci.h> 24#include <asm/ppc-pci.h>
25#include <asm/mpic.h>
25#include "fsl_msi.h" 26#include "fsl_msi.h"
26 27
28LIST_HEAD(msi_head);
29
27struct fsl_msi_feature { 30struct fsl_msi_feature {
28 u32 fsl_pic_ip; 31 u32 fsl_pic_ip;
29 u32 msiir_offset; 32 u32 msiir_offset;
30}; 33};
31 34
32static struct fsl_msi *fsl_msi; 35struct fsl_msi_cascade_data {
36 struct fsl_msi *msi_data;
37 int index;
38};
33 39
34static inline u32 fsl_msi_read(u32 __iomem *base, unsigned int reg) 40static inline u32 fsl_msi_read(u32 __iomem *base, unsigned int reg)
35{ 41{
@@ -54,10 +60,12 @@ static struct irq_chip fsl_msi_chip = {
54static int fsl_msi_host_map(struct irq_host *h, unsigned int virq, 60static int fsl_msi_host_map(struct irq_host *h, unsigned int virq,
55 irq_hw_number_t hw) 61 irq_hw_number_t hw)
56{ 62{
63 struct fsl_msi *msi_data = h->host_data;
57 struct irq_chip *chip = &fsl_msi_chip; 64 struct irq_chip *chip = &fsl_msi_chip;
58 65
59 irq_to_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING; 66 irq_to_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING;
60 67
68 set_irq_chip_data(virq, msi_data);
61 set_irq_chip_and_handler(virq, chip, handle_edge_irq); 69 set_irq_chip_and_handler(virq, chip, handle_edge_irq);
62 70
63 return 0; 71 return 0;
@@ -96,11 +104,12 @@ static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type)
96static void fsl_teardown_msi_irqs(struct pci_dev *pdev) 104static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
97{ 105{
98 struct msi_desc *entry; 106 struct msi_desc *entry;
99 struct fsl_msi *msi_data = fsl_msi; 107 struct fsl_msi *msi_data;
100 108
101 list_for_each_entry(entry, &pdev->msi_list, list) { 109 list_for_each_entry(entry, &pdev->msi_list, list) {
102 if (entry->irq == NO_IRQ) 110 if (entry->irq == NO_IRQ)
103 continue; 111 continue;
112 msi_data = get_irq_data(entry->irq);
104 set_irq_msi(entry->irq, NULL); 113 set_irq_msi(entry->irq, NULL);
105 msi_bitmap_free_hwirqs(&msi_data->bitmap, 114 msi_bitmap_free_hwirqs(&msi_data->bitmap,
106 virq_to_hw(entry->irq), 1); 115 virq_to_hw(entry->irq), 1);
@@ -111,9 +120,10 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
111} 120}
112 121
113static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, 122static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
114 struct msi_msg *msg) 123 struct msi_msg *msg,
124 struct fsl_msi *fsl_msi_data)
115{ 125{
116 struct fsl_msi *msi_data = fsl_msi; 126 struct fsl_msi *msi_data = fsl_msi_data;
117 struct pci_controller *hose = pci_bus_to_host(pdev->bus); 127 struct pci_controller *hose = pci_bus_to_host(pdev->bus);
118 u32 base = 0; 128 u32 base = 0;
119 129
@@ -130,14 +140,19 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
130 140
131static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) 141static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
132{ 142{
133 int rc, hwirq; 143 int rc, hwirq = -ENOMEM;
134 unsigned int virq; 144 unsigned int virq;
135 struct msi_desc *entry; 145 struct msi_desc *entry;
136 struct msi_msg msg; 146 struct msi_msg msg;
137 struct fsl_msi *msi_data = fsl_msi; 147 struct fsl_msi *msi_data;
138 148
139 list_for_each_entry(entry, &pdev->msi_list, list) { 149 list_for_each_entry(entry, &pdev->msi_list, list) {
140 hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1); 150 list_for_each_entry(msi_data, &msi_head, list) {
151 hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);
152 if (hwirq >= 0)
153 break;
154 }
155
141 if (hwirq < 0) { 156 if (hwirq < 0) {
142 rc = hwirq; 157 rc = hwirq;
143 pr_debug("%s: fail allocating msi interrupt\n", 158 pr_debug("%s: fail allocating msi interrupt\n",
@@ -154,25 +169,31 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
154 rc = -ENOSPC; 169 rc = -ENOSPC;
155 goto out_free; 170 goto out_free;
156 } 171 }
172 set_irq_data(virq, msi_data);
157 set_irq_msi(virq, entry); 173 set_irq_msi(virq, entry);
158 174
159 fsl_compose_msi_msg(pdev, hwirq, &msg); 175 fsl_compose_msi_msg(pdev, hwirq, &msg, msi_data);
160 write_msi_msg(virq, &msg); 176 write_msi_msg(virq, &msg);
161 } 177 }
162 return 0; 178 return 0;
163 179
164out_free: 180out_free:
181 /* free by the caller of this function */
165 return rc; 182 return rc;
166} 183}
167 184
168static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) 185static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
169{ 186{
170 unsigned int cascade_irq; 187 unsigned int cascade_irq;
171 struct fsl_msi *msi_data = fsl_msi; 188 struct fsl_msi *msi_data;
172 int msir_index = -1; 189 int msir_index = -1;
173 u32 msir_value = 0; 190 u32 msir_value = 0;
174 u32 intr_index; 191 u32 intr_index;
175 u32 have_shift = 0; 192 u32 have_shift = 0;
193 struct fsl_msi_cascade_data *cascade_data;
194
195 cascade_data = (struct fsl_msi_cascade_data *)get_irq_data(irq);
196 msi_data = cascade_data->msi_data;
176 197
177 raw_spin_lock(&desc->lock); 198 raw_spin_lock(&desc->lock);
178 if ((msi_data->feature & FSL_PIC_IP_MASK) == FSL_PIC_IP_IPIC) { 199 if ((msi_data->feature & FSL_PIC_IP_MASK) == FSL_PIC_IP_IPIC) {
@@ -187,13 +208,13 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
187 if (unlikely(desc->status & IRQ_INPROGRESS)) 208 if (unlikely(desc->status & IRQ_INPROGRESS))
188 goto unlock; 209 goto unlock;
189 210
190 msir_index = (int)desc->handler_data; 211 msir_index = cascade_data->index;
191 212
192 if (msir_index >= NR_MSI_REG) 213 if (msir_index >= NR_MSI_REG)
193 cascade_irq = NO_IRQ; 214 cascade_irq = NO_IRQ;
194 215
195 desc->status |= IRQ_INPROGRESS; 216 desc->status |= IRQ_INPROGRESS;
196 switch (fsl_msi->feature & FSL_PIC_IP_MASK) { 217 switch (msi_data->feature & FSL_PIC_IP_MASK) {
197 case FSL_PIC_IP_MPIC: 218 case FSL_PIC_IP_MPIC:
198 msir_value = fsl_msi_read(msi_data->msi_regs, 219 msir_value = fsl_msi_read(msi_data->msi_regs,
199 msir_index * 0x10); 220 msir_index * 0x10);
@@ -229,6 +250,30 @@ unlock:
229 raw_spin_unlock(&desc->lock); 250 raw_spin_unlock(&desc->lock);
230} 251}
231 252
253static int fsl_of_msi_remove(struct of_device *ofdev)
254{
255 struct fsl_msi *msi = ofdev->dev.platform_data;
256 int virq, i;
257 struct fsl_msi_cascade_data *cascade_data;
258
259 if (msi->list.prev != NULL)
260 list_del(&msi->list);
261 for (i = 0; i < NR_MSI_REG; i++) {
262 virq = msi->msi_virqs[i];
263 if (virq != NO_IRQ) {
264 cascade_data = get_irq_data(virq);
265 kfree(cascade_data);
266 irq_dispose_mapping(virq);
267 }
268 }
269 if (msi->bitmap.bitmap)
270 msi_bitmap_free(&msi->bitmap);
271 iounmap(msi->msi_regs);
272 kfree(msi);
273
274 return 0;
275}
276
232static int __devinit fsl_of_msi_probe(struct of_device *dev, 277static int __devinit fsl_of_msi_probe(struct of_device *dev,
233 const struct of_device_id *match) 278 const struct of_device_id *match)
234{ 279{
@@ -239,15 +284,18 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
239 int virt_msir; 284 int virt_msir;
240 const u32 *p; 285 const u32 *p;
241 struct fsl_msi_feature *features = match->data; 286 struct fsl_msi_feature *features = match->data;
287 struct fsl_msi_cascade_data *cascade_data = NULL;
288 int len;
289 u32 offset;
242 290
243 printk(KERN_DEBUG "Setting up Freescale MSI support\n"); 291 printk(KERN_DEBUG "Setting up Freescale MSI support\n");
244 292
245 msi = kzalloc(sizeof(struct fsl_msi), GFP_KERNEL); 293 msi = kzalloc(sizeof(struct fsl_msi), GFP_KERNEL);
246 if (!msi) { 294 if (!msi) {
247 dev_err(&dev->dev, "No memory for MSI structure\n"); 295 dev_err(&dev->dev, "No memory for MSI structure\n");
248 err = -ENOMEM; 296 return -ENOMEM;
249 goto error_out;
250 } 297 }
298 dev->dev.platform_data = msi;
251 299
252 msi->irqhost = irq_alloc_host(dev->dev.of_node, IRQ_HOST_MAP_LINEAR, 300 msi->irqhost = irq_alloc_host(dev->dev.of_node, IRQ_HOST_MAP_LINEAR,
253 NR_MSI_IRQS, &fsl_msi_host_ops, 0); 301 NR_MSI_IRQS, &fsl_msi_host_ops, 0);
@@ -298,27 +346,47 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
298 err = -EINVAL; 346 err = -EINVAL;
299 goto error_out; 347 goto error_out;
300 } 348 }
349 offset = 0;
350 p = of_get_property(dev->node, "msi-available-ranges", &len);
351 if (p)
352 offset = *p / IRQS_PER_MSI_REG;
301 353
302 count /= sizeof(u32); 354 count /= sizeof(u32);
303 for (i = 0; i < count / 2; i++) { 355 for (i = 0; i < min(count / 2, NR_MSI_REG); i++) {
304 if (i > NR_MSI_REG)
305 break;
306 virt_msir = irq_of_parse_and_map(dev->dev.of_node, i); 356 virt_msir = irq_of_parse_and_map(dev->dev.of_node, i);
307 if (virt_msir != NO_IRQ) { 357 if (virt_msir != NO_IRQ) {
308 set_irq_data(virt_msir, (void *)i); 358 cascade_data = kzalloc(
359 sizeof(struct fsl_msi_cascade_data),
360 GFP_KERNEL);
361 if (!cascade_data) {
362 dev_err(&dev->dev,
363 "No memory for MSI cascade data\n");
364 err = -ENOMEM;
365 goto error_out;
366 }
367 msi->msi_virqs[i] = virt_msir;
368 cascade_data->index = i + offset;
369 cascade_data->msi_data = msi;
370 set_irq_data(virt_msir, (void *)cascade_data);
309 set_irq_chained_handler(virt_msir, fsl_msi_cascade); 371 set_irq_chained_handler(virt_msir, fsl_msi_cascade);
310 } 372 }
311 } 373 }
312 374
313 fsl_msi = msi; 375 list_add_tail(&msi->list, &msi_head);
314 376
315 WARN_ON(ppc_md.setup_msi_irqs); 377 /* The multiple setting ppc_md.setup_msi_irqs will not harm things */
316 ppc_md.setup_msi_irqs = fsl_setup_msi_irqs; 378 if (!ppc_md.setup_msi_irqs) {
317 ppc_md.teardown_msi_irqs = fsl_teardown_msi_irqs; 379 ppc_md.setup_msi_irqs = fsl_setup_msi_irqs;
318 ppc_md.msi_check_device = fsl_msi_check_device; 380 ppc_md.teardown_msi_irqs = fsl_teardown_msi_irqs;
381 ppc_md.msi_check_device = fsl_msi_check_device;
382 } else if (ppc_md.setup_msi_irqs != fsl_setup_msi_irqs) {
383 dev_err(&dev->dev, "Different MSI driver already installed!\n");
384 err = -ENODEV;
385 goto error_out;
386 }
319 return 0; 387 return 0;
320error_out: 388error_out:
321 kfree(msi); 389 fsl_of_msi_remove(dev);
322 return err; 390 return err;
323} 391}
324 392
@@ -351,6 +419,7 @@ static struct of_platform_driver fsl_of_msi_driver = {
351 .of_match_table = fsl_of_msi_ids, 419 .of_match_table = fsl_of_msi_ids,
352 }, 420 },
353 .probe = fsl_of_msi_probe, 421 .probe = fsl_of_msi_probe,
422 .remove = fsl_of_msi_remove,
354}; 423};
355 424
356static __init int fsl_of_msi_init(void) 425static __init int fsl_of_msi_init(void)
diff --git a/arch/powerpc/sysdev/fsl_msi.h b/arch/powerpc/sysdev/fsl_msi.h
index 331c7e7025b7..624580c252d7 100644
--- a/arch/powerpc/sysdev/fsl_msi.h
+++ b/arch/powerpc/sysdev/fsl_msi.h
@@ -32,8 +32,11 @@ struct fsl_msi {
32 u32 msi_addr_hi; 32 u32 msi_addr_hi;
33 void __iomem *msi_regs; 33 void __iomem *msi_regs;
34 u32 feature; 34 u32 feature;
35 int msi_virqs[NR_MSI_REG];
35 36
36 struct msi_bitmap bitmap; 37 struct msi_bitmap bitmap;
38
39 struct list_head list; /* support multiple MSI banks */
37}; 40};
38 41
39#endif /* _POWERPC_SYSDEV_FSL_MSI_H */ 42#endif /* _POWERPC_SYSDEV_FSL_MSI_H */