diff options
author | Lachlan McIlroy <lachlan@redback.melbourne.sgi.com> | 2009-01-14 00:29:51 -0500 |
---|---|---|
committer | Lachlan McIlroy <lachlan@redback.melbourne.sgi.com> | 2009-01-14 00:29:51 -0500 |
commit | cb7a97d01521797cad9f63e8478403c3e51fea49 (patch) | |
tree | 84cddf20369f82f10c1c3712e6cce20dd1b9d863 /arch/powerpc | |
parent | 0335cb76aa3fa913a2164bc9b669e5aef9d56fa3 (diff) | |
parent | a6525042bfdfcab128bd91fad264de10fd24a55e (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into for-linus
Diffstat (limited to 'arch/powerpc')
71 files changed, 2465 insertions, 644 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 79f25cef32df..84b861316ce7 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -108,6 +108,8 @@ config ARCH_NO_VIRT_TO_BUS | |||
108 | config PPC | 108 | config PPC |
109 | bool | 109 | bool |
110 | default y | 110 | default y |
111 | select HAVE_FTRACE_MCOUNT_RECORD | ||
112 | select HAVE_DYNAMIC_FTRACE | ||
111 | select HAVE_FUNCTION_TRACER | 113 | select HAVE_FUNCTION_TRACER |
112 | select ARCH_WANT_OPTIONAL_GPIOLIB | 114 | select ARCH_WANT_OPTIONAL_GPIOLIB |
113 | select HAVE_IDE | 115 | select HAVE_IDE |
@@ -326,7 +328,8 @@ config KEXEC | |||
326 | 328 | ||
327 | config CRASH_DUMP | 329 | config CRASH_DUMP |
328 | bool "Build a kdump crash kernel" | 330 | bool "Build a kdump crash kernel" |
329 | depends on (PPC64 && RELOCATABLE) || 6xx | 331 | depends on PPC64 || 6xx |
332 | select RELOCATABLE if PPC64 | ||
330 | help | 333 | help |
331 | Build a kernel suitable for use as a kdump capture kernel. | 334 | Build a kernel suitable for use as a kdump capture kernel. |
332 | The same kernel binary can be used as production kernel and dump | 335 | The same kernel binary can be used as production kernel and dump |
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index ab6dda372438..e84df338ea29 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile | |||
@@ -356,7 +356,7 @@ $(obj)/zImage.initrd: $(addprefix $(obj)/, $(initrd-y)) | |||
356 | @rm -f $@; ln $< $@ | 356 | @rm -f $@; ln $< $@ |
357 | 357 | ||
358 | install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y)) | 358 | install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y)) |
359 | sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $< | 359 | sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $^ |
360 | 360 | ||
361 | # anything not in $(targets) | 361 | # anything not in $(targets) |
362 | clean-files += $(image-) $(initrd-) cuImage.* dtbImage.* treeImage.* \ | 362 | clean-files += $(image-) $(initrd-) cuImage.* dtbImage.* treeImage.* \ |
diff --git a/arch/powerpc/boot/dts/gef_sbc610.dts b/arch/powerpc/boot/dts/gef_sbc610.dts index 9708b3423bbd..e78c355c7bac 100644 --- a/arch/powerpc/boot/dts/gef_sbc610.dts +++ b/arch/powerpc/boot/dts/gef_sbc610.dts | |||
@@ -88,6 +88,21 @@ | |||
88 | compatible = "gef,fpga-regs"; | 88 | compatible = "gef,fpga-regs"; |
89 | reg = <0x4 0x0 0x40>; | 89 | reg = <0x4 0x0 0x40>; |
90 | }; | 90 | }; |
91 | |||
92 | wdt@4,2000 { | ||
93 | compatible = "gef,fpga-wdt"; | ||
94 | reg = <0x4 0x2000 0x8>; | ||
95 | interrupts = <0x1a 0x4>; | ||
96 | interrupt-parent = <&gef_pic>; | ||
97 | }; | ||
98 | /* Second watchdog available, driver currently supports one. | ||
99 | wdt@4,2010 { | ||
100 | compatible = "gef,fpga-wdt"; | ||
101 | reg = <0x4 0x2010 0x8>; | ||
102 | interrupts = <0x1b 0x4>; | ||
103 | interrupt-parent = <&gef_pic>; | ||
104 | }; | ||
105 | */ | ||
91 | gef_pic: pic@4,4000 { | 106 | gef_pic: pic@4,4000 { |
92 | #interrupt-cells = <1>; | 107 | #interrupt-cells = <1>; |
93 | interrupt-controller; | 108 | interrupt-controller; |
diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts index 14534d04e4db..6e34f170fa62 100644 --- a/arch/powerpc/boot/dts/mpc836x_mds.dts +++ b/arch/powerpc/boot/dts/mpc836x_mds.dts | |||
@@ -69,8 +69,18 @@ | |||
69 | }; | 69 | }; |
70 | 70 | ||
71 | bcsr@1,0 { | 71 | bcsr@1,0 { |
72 | #address-cells = <1>; | ||
73 | #size-cells = <1>; | ||
72 | compatible = "fsl,mpc8360mds-bcsr"; | 74 | compatible = "fsl,mpc8360mds-bcsr"; |
73 | reg = <1 0 0x8000>; | 75 | reg = <1 0 0x8000>; |
76 | ranges = <0 1 0 0x8000>; | ||
77 | |||
78 | bcsr13: gpio-controller@d { | ||
79 | #gpio-cells = <2>; | ||
80 | compatible = "fsl,mpc8360mds-bcsr-gpio"; | ||
81 | reg = <0xd 1>; | ||
82 | gpio-controller; | ||
83 | }; | ||
74 | }; | 84 | }; |
75 | }; | 85 | }; |
76 | 86 | ||
@@ -195,10 +205,21 @@ | |||
195 | }; | 205 | }; |
196 | 206 | ||
197 | par_io@1400 { | 207 | par_io@1400 { |
208 | #address-cells = <1>; | ||
209 | #size-cells = <1>; | ||
198 | reg = <0x1400 0x100>; | 210 | reg = <0x1400 0x100>; |
211 | ranges = <0 0x1400 0x100>; | ||
199 | device_type = "par_io"; | 212 | device_type = "par_io"; |
200 | num-ports = <7>; | 213 | num-ports = <7>; |
201 | 214 | ||
215 | qe_pio_b: gpio-controller@18 { | ||
216 | #gpio-cells = <2>; | ||
217 | compatible = "fsl,mpc8360-qe-pario-bank", | ||
218 | "fsl,mpc8323-qe-pario-bank"; | ||
219 | reg = <0x18 0x18>; | ||
220 | gpio-controller; | ||
221 | }; | ||
222 | |||
202 | pio1: ucc_pin@01 { | 223 | pio1: ucc_pin@01 { |
203 | pio-map = < | 224 | pio-map = < |
204 | /* port pin dir open_drain assignment has_irq */ | 225 | /* port pin dir open_drain assignment has_irq */ |
@@ -282,6 +303,15 @@ | |||
282 | }; | 303 | }; |
283 | }; | 304 | }; |
284 | 305 | ||
306 | timer@440 { | ||
307 | compatible = "fsl,mpc8360-qe-gtm", | ||
308 | "fsl,qe-gtm", "fsl,gtm"; | ||
309 | reg = <0x440 0x40>; | ||
310 | clock-frequency = <132000000>; | ||
311 | interrupts = <12 13 14 15>; | ||
312 | interrupt-parent = <&qeic>; | ||
313 | }; | ||
314 | |||
285 | spi@4c0 { | 315 | spi@4c0 { |
286 | cell-index = <0>; | 316 | cell-index = <0>; |
287 | compatible = "fsl,spi"; | 317 | compatible = "fsl,spi"; |
@@ -301,11 +331,20 @@ | |||
301 | }; | 331 | }; |
302 | 332 | ||
303 | usb@6c0 { | 333 | usb@6c0 { |
304 | compatible = "qe_udc"; | 334 | compatible = "fsl,mpc8360-qe-usb", |
335 | "fsl,mpc8323-qe-usb"; | ||
305 | reg = <0x6c0 0x40 0x8b00 0x100>; | 336 | reg = <0x6c0 0x40 0x8b00 0x100>; |
306 | interrupts = <11>; | 337 | interrupts = <11>; |
307 | interrupt-parent = <&qeic>; | 338 | interrupt-parent = <&qeic>; |
308 | mode = "slave"; | 339 | fsl,fullspeed-clock = "clk21"; |
340 | fsl,lowspeed-clock = "brg9"; | ||
341 | gpios = <&qe_pio_b 2 0 /* USBOE */ | ||
342 | &qe_pio_b 3 0 /* USBTP */ | ||
343 | &qe_pio_b 8 0 /* USBTN */ | ||
344 | &qe_pio_b 9 0 /* USBRP */ | ||
345 | &qe_pio_b 11 0 /* USBRN */ | ||
346 | &bcsr13 5 0 /* SPEED */ | ||
347 | &bcsr13 4 1>; /* POWER */ | ||
309 | }; | 348 | }; |
310 | 349 | ||
311 | enet0: ucc@2000 { | 350 | enet0: ucc@2000 { |
diff --git a/arch/powerpc/boot/dts/mpc836x_rdk.dts b/arch/powerpc/boot/dts/mpc836x_rdk.dts index decadf3d9e98..37b789510d68 100644 --- a/arch/powerpc/boot/dts/mpc836x_rdk.dts +++ b/arch/powerpc/boot/dts/mpc836x_rdk.dts | |||
@@ -218,8 +218,23 @@ | |||
218 | reg = <0x440 0x40>; | 218 | reg = <0x440 0x40>; |
219 | interrupts = <12 13 14 15>; | 219 | interrupts = <12 13 14 15>; |
220 | interrupt-parent = <&qeic>; | 220 | interrupt-parent = <&qeic>; |
221 | /* filled by u-boot */ | 221 | clock-frequency = <166666666>; |
222 | clock-frequency = <0>; | 222 | }; |
223 | |||
224 | usb@6c0 { | ||
225 | compatible = "fsl,mpc8360-qe-usb", | ||
226 | "fsl,mpc8323-qe-usb"; | ||
227 | reg = <0x6c0 0x40 0x8b00 0x100>; | ||
228 | interrupts = <11>; | ||
229 | interrupt-parent = <&qeic>; | ||
230 | fsl,fullspeed-clock = "clk21"; | ||
231 | gpios = <&qe_pio_b 2 0 /* USBOE */ | ||
232 | &qe_pio_b 3 0 /* USBTP */ | ||
233 | &qe_pio_b 8 0 /* USBTN */ | ||
234 | &qe_pio_b 9 0 /* USBRP */ | ||
235 | &qe_pio_b 11 0 /* USBRN */ | ||
236 | &qe_pio_e 20 0 /* SPEED */ | ||
237 | &qe_pio_e 21 1 /* POWER */>; | ||
223 | }; | 238 | }; |
224 | 239 | ||
225 | spi@4c0 { | 240 | spi@4c0 { |
diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts index 35d5e248ccd7..4481532cbe77 100644 --- a/arch/powerpc/boot/dts/mpc8641_hpcn.dts +++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts | |||
@@ -26,7 +26,13 @@ | |||
26 | serial1 = &serial1; | 26 | serial1 = &serial1; |
27 | pci0 = &pci0; | 27 | pci0 = &pci0; |
28 | pci1 = &pci1; | 28 | pci1 = &pci1; |
29 | rapidio0 = &rapidio0; | 29 | /* |
30 | * Only one of Rapid IO or PCI can be present due to HW limitations and | ||
31 | * due to the fact that the 2 now share address space in the new memory | ||
32 | * map. The most likely case is that we have PCI, so comment out the | ||
33 | * rapidio node. Leave it here for reference. | ||
34 | */ | ||
35 | /* rapidio0 = &rapidio0; */ | ||
30 | }; | 36 | }; |
31 | 37 | ||
32 | cpus { | 38 | cpus { |
@@ -62,18 +68,17 @@ | |||
62 | reg = <0x00000000 0x40000000>; // 1G at 0x0 | 68 | reg = <0x00000000 0x40000000>; // 1G at 0x0 |
63 | }; | 69 | }; |
64 | 70 | ||
65 | localbus@f8005000 { | 71 | localbus@ffe05000 { |
66 | #address-cells = <2>; | 72 | #address-cells = <2>; |
67 | #size-cells = <1>; | 73 | #size-cells = <1>; |
68 | compatible = "fsl,mpc8641-localbus", "simple-bus"; | 74 | compatible = "fsl,mpc8641-localbus", "simple-bus"; |
69 | reg = <0xf8005000 0x1000>; | 75 | reg = <0xffe05000 0x1000>; |
70 | interrupts = <19 2>; | 76 | interrupts = <19 2>; |
71 | interrupt-parent = <&mpic>; | 77 | interrupt-parent = <&mpic>; |
72 | 78 | ||
73 | ranges = <0 0 0xff800000 0x00800000 | 79 | ranges = <0 0 0xef800000 0x00800000 |
74 | 1 0 0xfe000000 0x01000000 | 80 | 2 0 0xffdf8000 0x00008000 |
75 | 2 0 0xf8200000 0x00100000 | 81 | 3 0 0xffdf0000 0x00008000>; |
76 | 3 0 0xf8100000 0x00100000>; | ||
77 | 82 | ||
78 | flash@0,0 { | 83 | flash@0,0 { |
79 | compatible = "cfi-flash"; | 84 | compatible = "cfi-flash"; |
@@ -103,13 +108,13 @@ | |||
103 | }; | 108 | }; |
104 | }; | 109 | }; |
105 | 110 | ||
106 | soc8641@f8000000 { | 111 | soc8641@ffe00000 { |
107 | #address-cells = <1>; | 112 | #address-cells = <1>; |
108 | #size-cells = <1>; | 113 | #size-cells = <1>; |
109 | device_type = "soc"; | 114 | device_type = "soc"; |
110 | compatible = "simple-bus"; | 115 | compatible = "simple-bus"; |
111 | ranges = <0x00000000 0xf8000000 0x00100000>; | 116 | ranges = <0x00000000 0xffe00000 0x00100000>; |
112 | reg = <0xf8000000 0x00001000>; // CCSRBAR | 117 | reg = <0xffe00000 0x00001000>; // CCSRBAR |
113 | bus-frequency = <0>; | 118 | bus-frequency = <0>; |
114 | 119 | ||
115 | i2c@3000 { | 120 | i2c@3000 { |
@@ -340,17 +345,17 @@ | |||
340 | }; | 345 | }; |
341 | }; | 346 | }; |
342 | 347 | ||
343 | pci0: pcie@f8008000 { | 348 | pci0: pcie@ffe08000 { |
344 | cell-index = <0>; | 349 | cell-index = <0>; |
345 | compatible = "fsl,mpc8641-pcie"; | 350 | compatible = "fsl,mpc8641-pcie"; |
346 | device_type = "pci"; | 351 | device_type = "pci"; |
347 | #interrupt-cells = <1>; | 352 | #interrupt-cells = <1>; |
348 | #size-cells = <2>; | 353 | #size-cells = <2>; |
349 | #address-cells = <3>; | 354 | #address-cells = <3>; |
350 | reg = <0xf8008000 0x1000>; | 355 | reg = <0xffe08000 0x1000>; |
351 | bus-range = <0x0 0xff>; | 356 | bus-range = <0x0 0xff>; |
352 | ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x20000000 | 357 | ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x20000000 |
353 | 0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>; | 358 | 0x01000000 0x0 0x00000000 0xffc00000 0x0 0x00010000>; |
354 | clock-frequency = <33333333>; | 359 | clock-frequency = <33333333>; |
355 | interrupt-parent = <&mpic>; | 360 | interrupt-parent = <&mpic>; |
356 | interrupts = <24 2>; | 361 | interrupts = <24 2>; |
@@ -481,7 +486,7 @@ | |||
481 | 486 | ||
482 | 0x01000000 0x0 0x00000000 | 487 | 0x01000000 0x0 0x00000000 |
483 | 0x01000000 0x0 0x00000000 | 488 | 0x01000000 0x0 0x00000000 |
484 | 0x0 0x00100000>; | 489 | 0x0 0x00010000>; |
485 | uli1575@0 { | 490 | uli1575@0 { |
486 | reg = <0 0 0 0 0>; | 491 | reg = <0 0 0 0 0>; |
487 | #size-cells = <2>; | 492 | #size-cells = <2>; |
@@ -491,7 +496,7 @@ | |||
491 | 0x0 0x20000000 | 496 | 0x0 0x20000000 |
492 | 0x01000000 0x0 0x00000000 | 497 | 0x01000000 0x0 0x00000000 |
493 | 0x01000000 0x0 0x00000000 | 498 | 0x01000000 0x0 0x00000000 |
494 | 0x0 0x00100000>; | 499 | 0x0 0x00010000>; |
495 | isa@1e { | 500 | isa@1e { |
496 | device_type = "isa"; | 501 | device_type = "isa"; |
497 | #interrupt-cells = <2>; | 502 | #interrupt-cells = <2>; |
@@ -549,17 +554,17 @@ | |||
549 | 554 | ||
550 | }; | 555 | }; |
551 | 556 | ||
552 | pci1: pcie@f8009000 { | 557 | pci1: pcie@ffe09000 { |
553 | cell-index = <1>; | 558 | cell-index = <1>; |
554 | compatible = "fsl,mpc8641-pcie"; | 559 | compatible = "fsl,mpc8641-pcie"; |
555 | device_type = "pci"; | 560 | device_type = "pci"; |
556 | #interrupt-cells = <1>; | 561 | #interrupt-cells = <1>; |
557 | #size-cells = <2>; | 562 | #size-cells = <2>; |
558 | #address-cells = <3>; | 563 | #address-cells = <3>; |
559 | reg = <0xf8009000 0x1000>; | 564 | reg = <0xffe09000 0x1000>; |
560 | bus-range = <0 0xff>; | 565 | bus-range = <0 0xff>; |
561 | ranges = <0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000 | 566 | ranges = <0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000 |
562 | 0x01000000 0x0 0x00000000 0xe3000000 0x0 0x00100000>; | 567 | 0x01000000 0x0 0x00000000 0xffc10000 0x0 0x00010000>; |
563 | clock-frequency = <33333333>; | 568 | clock-frequency = <33333333>; |
564 | interrupt-parent = <&mpic>; | 569 | interrupt-parent = <&mpic>; |
565 | interrupts = <25 2>; | 570 | interrupts = <25 2>; |
@@ -582,18 +587,21 @@ | |||
582 | 587 | ||
583 | 0x01000000 0x0 0x00000000 | 588 | 0x01000000 0x0 0x00000000 |
584 | 0x01000000 0x0 0x00000000 | 589 | 0x01000000 0x0 0x00000000 |
585 | 0x0 0x00100000>; | 590 | 0x0 0x00010000>; |
586 | }; | 591 | }; |
587 | }; | 592 | }; |
588 | rapidio0: rapidio@f80c0000 { | 593 | /* |
594 | rapidio0: rapidio@ffec0000 { | ||
589 | #address-cells = <2>; | 595 | #address-cells = <2>; |
590 | #size-cells = <2>; | 596 | #size-cells = <2>; |
591 | compatible = "fsl,rapidio-delta"; | 597 | compatible = "fsl,rapidio-delta"; |
592 | reg = <0xf80c0000 0x20000>; | 598 | reg = <0xffec0000 0x20000>; |
593 | ranges = <0 0 0xc0000000 0 0x20000000>; | 599 | ranges = <0 0 0x80000000 0 0x20000000>; |
594 | interrupt-parent = <&mpic>; | 600 | interrupt-parent = <&mpic>; |
595 | /* err_irq bell_outb_irq bell_inb_irq | 601 | // err_irq bell_outb_irq bell_inb_irq |
596 | msg1_tx_irq msg1_rx_irq msg2_tx_irq msg2_rx_irq */ | 602 | // msg1_tx_irq msg1_rx_irq msg2_tx_irq msg2_rx_irq |
597 | interrupts = <48 2 49 2 50 2 53 2 54 2 55 2 56 2>; | 603 | interrupts = <48 2 49 2 50 2 53 2 54 2 55 2 56 2>; |
598 | }; | 604 | }; |
605 | */ | ||
606 | |||
599 | }; | 607 | }; |
diff --git a/arch/powerpc/boot/install.sh b/arch/powerpc/boot/install.sh index b002bfd56786..51b2387bdba0 100644 --- a/arch/powerpc/boot/install.sh +++ b/arch/powerpc/boot/install.sh | |||
@@ -15,7 +15,7 @@ | |||
15 | # $2 - kernel image file | 15 | # $2 - kernel image file |
16 | # $3 - kernel map file | 16 | # $3 - kernel map file |
17 | # $4 - default install path (blank if root directory) | 17 | # $4 - default install path (blank if root directory) |
18 | # $5 - kernel boot file, the zImage | 18 | # $5 and more - kernel boot files; zImage*, uImage, cuImage.*, etc. |
19 | # | 19 | # |
20 | 20 | ||
21 | # User may have a custom install script | 21 | # User may have a custom install script |
@@ -38,3 +38,15 @@ fi | |||
38 | 38 | ||
39 | cat $2 > $4/$image_name | 39 | cat $2 > $4/$image_name |
40 | cp $3 $4/System.map | 40 | cp $3 $4/System.map |
41 | |||
42 | # Copy all the bootable image files | ||
43 | path=$4 | ||
44 | shift 4 | ||
45 | while [ $# -ne 0 ]; do | ||
46 | image_name=`basename $1` | ||
47 | if [ -f $path/$image_name ]; then | ||
48 | mv $path/$image_name $path/$image_name.old | ||
49 | fi | ||
50 | cat $1 > $path/$image_name | ||
51 | shift | ||
52 | done; | ||
diff --git a/arch/powerpc/configs/85xx/mpc8572_ds_defconfig b/arch/powerpc/configs/85xx/mpc8572_ds_defconfig index 635588319e0d..32aeb79216f7 100644 --- a/arch/powerpc/configs/85xx/mpc8572_ds_defconfig +++ b/arch/powerpc/configs/85xx/mpc8572_ds_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.28-rc3 | 3 | # Linux kernel version: 2.6.28-rc8 |
4 | # Sat Nov 8 12:40:13 2008 | 4 | # Tue Dec 30 11:17:46 2008 |
5 | # | 5 | # |
6 | # CONFIG_PPC64 is not set | 6 | # CONFIG_PPC64 is not set |
7 | 7 | ||
@@ -21,7 +21,10 @@ CONFIG_FSL_BOOKE=y | |||
21 | CONFIG_FSL_EMB_PERFMON=y | 21 | CONFIG_FSL_EMB_PERFMON=y |
22 | # CONFIG_PHYS_64BIT is not set | 22 | # CONFIG_PHYS_64BIT is not set |
23 | CONFIG_SPE=y | 23 | CONFIG_SPE=y |
24 | CONFIG_PPC_MMU_NOHASH=y | ||
24 | # CONFIG_PPC_MM_SLICES is not set | 25 | # CONFIG_PPC_MM_SLICES is not set |
26 | CONFIG_SMP=y | ||
27 | CONFIG_NR_CPUS=2 | ||
25 | CONFIG_PPC32=y | 28 | CONFIG_PPC32=y |
26 | CONFIG_WORD_SIZE=32 | 29 | CONFIG_WORD_SIZE=32 |
27 | # CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set | 30 | # CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set |
@@ -50,7 +53,7 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y | |||
50 | CONFIG_PPC_OF=y | 53 | CONFIG_PPC_OF=y |
51 | CONFIG_OF=y | 54 | CONFIG_OF=y |
52 | CONFIG_PPC_UDBG_16550=y | 55 | CONFIG_PPC_UDBG_16550=y |
53 | # CONFIG_GENERIC_TBSYNC is not set | 56 | CONFIG_GENERIC_TBSYNC=y |
54 | CONFIG_AUDIT_ARCH=y | 57 | CONFIG_AUDIT_ARCH=y |
55 | CONFIG_GENERIC_BUG=y | 58 | CONFIG_GENERIC_BUG=y |
56 | CONFIG_DEFAULT_UIMAGE=y | 59 | CONFIG_DEFAULT_UIMAGE=y |
@@ -62,7 +65,7 @@ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" | |||
62 | # General setup | 65 | # General setup |
63 | # | 66 | # |
64 | CONFIG_EXPERIMENTAL=y | 67 | CONFIG_EXPERIMENTAL=y |
65 | CONFIG_BROKEN_ON_SMP=y | 68 | CONFIG_LOCK_KERNEL=y |
66 | CONFIG_INIT_ENV_ARG_LIMIT=32 | 69 | CONFIG_INIT_ENV_ARG_LIMIT=32 |
67 | CONFIG_LOCALVERSION="" | 70 | CONFIG_LOCALVERSION="" |
68 | CONFIG_LOCALVERSION_AUTO=y | 71 | CONFIG_LOCALVERSION_AUTO=y |
@@ -126,6 +129,7 @@ CONFIG_HAVE_IOREMAP_PROT=y | |||
126 | CONFIG_HAVE_KPROBES=y | 129 | CONFIG_HAVE_KPROBES=y |
127 | CONFIG_HAVE_KRETPROBES=y | 130 | CONFIG_HAVE_KRETPROBES=y |
128 | CONFIG_HAVE_ARCH_TRACEHOOK=y | 131 | CONFIG_HAVE_ARCH_TRACEHOOK=y |
132 | CONFIG_USE_GENERIC_SMP_HELPERS=y | ||
129 | # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set | 133 | # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set |
130 | CONFIG_SLABINFO=y | 134 | CONFIG_SLABINFO=y |
131 | CONFIG_RT_MUTEXES=y | 135 | CONFIG_RT_MUTEXES=y |
@@ -138,6 +142,7 @@ CONFIG_MODULE_FORCE_UNLOAD=y | |||
138 | CONFIG_MODVERSIONS=y | 142 | CONFIG_MODVERSIONS=y |
139 | # CONFIG_MODULE_SRCVERSION_ALL is not set | 143 | # CONFIG_MODULE_SRCVERSION_ALL is not set |
140 | CONFIG_KMOD=y | 144 | CONFIG_KMOD=y |
145 | CONFIG_STOP_MACHINE=y | ||
141 | CONFIG_BLOCK=y | 146 | CONFIG_BLOCK=y |
142 | CONFIG_LBD=y | 147 | CONFIG_LBD=y |
143 | # CONFIG_BLK_DEV_IO_TRACE is not set | 148 | # CONFIG_BLK_DEV_IO_TRACE is not set |
@@ -197,6 +202,7 @@ CONFIG_PPC_I8259=y | |||
197 | # CONFIG_CPM2 is not set | 202 | # CONFIG_CPM2 is not set |
198 | CONFIG_FSL_ULI1575=y | 203 | CONFIG_FSL_ULI1575=y |
199 | # CONFIG_MPC8xxx_GPIO is not set | 204 | # CONFIG_MPC8xxx_GPIO is not set |
205 | # CONFIG_SIMPLE_GPIO is not set | ||
200 | 206 | ||
201 | # | 207 | # |
202 | # Kernel options | 208 | # Kernel options |
@@ -224,6 +230,7 @@ CONFIG_MATH_EMULATION=y | |||
224 | CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y | 230 | CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y |
225 | CONFIG_ARCH_HAS_WALK_MEMORY=y | 231 | CONFIG_ARCH_HAS_WALK_MEMORY=y |
226 | CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y | 232 | CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y |
233 | # CONFIG_IRQ_ALL_CPUS is not set | ||
227 | CONFIG_ARCH_FLATMEM_ENABLE=y | 234 | CONFIG_ARCH_FLATMEM_ENABLE=y |
228 | CONFIG_ARCH_POPULATES_NODE_MAP=y | 235 | CONFIG_ARCH_POPULATES_NODE_MAP=y |
229 | CONFIG_SELECT_MEMORY_MODEL=y | 236 | CONFIG_SELECT_MEMORY_MODEL=y |
@@ -241,6 +248,9 @@ CONFIG_ZONE_DMA_FLAG=1 | |||
241 | CONFIG_BOUNCE=y | 248 | CONFIG_BOUNCE=y |
242 | CONFIG_VIRT_TO_BUS=y | 249 | CONFIG_VIRT_TO_BUS=y |
243 | CONFIG_UNEVICTABLE_LRU=y | 250 | CONFIG_UNEVICTABLE_LRU=y |
251 | CONFIG_PPC_4K_PAGES=y | ||
252 | # CONFIG_PPC_16K_PAGES is not set | ||
253 | # CONFIG_PPC_64K_PAGES is not set | ||
244 | CONFIG_FORCE_MAX_ZONEORDER=11 | 254 | CONFIG_FORCE_MAX_ZONEORDER=11 |
245 | CONFIG_PROC_DEVICETREE=y | 255 | CONFIG_PROC_DEVICETREE=y |
246 | # CONFIG_CMDLINE_BOOL is not set | 256 | # CONFIG_CMDLINE_BOOL is not set |
@@ -443,8 +453,10 @@ CONFIG_MISC_DEVICES=y | |||
443 | # CONFIG_EEPROM_93CX6 is not set | 453 | # CONFIG_EEPROM_93CX6 is not set |
444 | # CONFIG_SGI_IOC4 is not set | 454 | # CONFIG_SGI_IOC4 is not set |
445 | # CONFIG_TIFM_CORE is not set | 455 | # CONFIG_TIFM_CORE is not set |
456 | # CONFIG_ICS932S401 is not set | ||
446 | # CONFIG_ENCLOSURE_SERVICES is not set | 457 | # CONFIG_ENCLOSURE_SERVICES is not set |
447 | # CONFIG_HP_ILO is not set | 458 | # CONFIG_HP_ILO is not set |
459 | # CONFIG_C2PORT is not set | ||
448 | CONFIG_HAVE_IDE=y | 460 | CONFIG_HAVE_IDE=y |
449 | # CONFIG_IDE is not set | 461 | # CONFIG_IDE is not set |
450 | 462 | ||
@@ -784,6 +796,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y | |||
784 | CONFIG_UNIX98_PTYS=y | 796 | CONFIG_UNIX98_PTYS=y |
785 | CONFIG_LEGACY_PTYS=y | 797 | CONFIG_LEGACY_PTYS=y |
786 | CONFIG_LEGACY_PTY_COUNT=256 | 798 | CONFIG_LEGACY_PTY_COUNT=256 |
799 | # CONFIG_HVC_UDBG is not set | ||
787 | # CONFIG_IPMI_HANDLER is not set | 800 | # CONFIG_IPMI_HANDLER is not set |
788 | CONFIG_HW_RANDOM=y | 801 | CONFIG_HW_RANDOM=y |
789 | CONFIG_NVRAM=y | 802 | CONFIG_NVRAM=y |
@@ -869,11 +882,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y | |||
869 | # CONFIG_THERMAL is not set | 882 | # CONFIG_THERMAL is not set |
870 | # CONFIG_THERMAL_HWMON is not set | 883 | # CONFIG_THERMAL_HWMON is not set |
871 | # CONFIG_WATCHDOG is not set | 884 | # CONFIG_WATCHDOG is not set |
885 | CONFIG_SSB_POSSIBLE=y | ||
872 | 886 | ||
873 | # | 887 | # |
874 | # Sonics Silicon Backplane | 888 | # Sonics Silicon Backplane |
875 | # | 889 | # |
876 | CONFIG_SSB_POSSIBLE=y | ||
877 | # CONFIG_SSB is not set | 890 | # CONFIG_SSB is not set |
878 | 891 | ||
879 | # | 892 | # |
@@ -886,14 +899,7 @@ CONFIG_SSB_POSSIBLE=y | |||
886 | # CONFIG_PMIC_DA903X is not set | 899 | # CONFIG_PMIC_DA903X is not set |
887 | # CONFIG_MFD_WM8400 is not set | 900 | # CONFIG_MFD_WM8400 is not set |
888 | # CONFIG_MFD_WM8350_I2C is not set | 901 | # CONFIG_MFD_WM8350_I2C is not set |
889 | |||
890 | # | ||
891 | # Voltage and Current regulators | ||
892 | # | ||
893 | # CONFIG_REGULATOR is not set | 902 | # CONFIG_REGULATOR is not set |
894 | # CONFIG_REGULATOR_FIXED_VOLTAGE is not set | ||
895 | # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set | ||
896 | # CONFIG_REGULATOR_BQ24022 is not set | ||
897 | 903 | ||
898 | # | 904 | # |
899 | # Multimedia devices | 905 | # Multimedia devices |
@@ -1252,11 +1258,11 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y | |||
1252 | # CONFIG_USB_TMC is not set | 1258 | # CONFIG_USB_TMC is not set |
1253 | 1259 | ||
1254 | # | 1260 | # |
1255 | # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' | 1261 | # NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; |
1256 | # | 1262 | # |
1257 | 1263 | ||
1258 | # | 1264 | # |
1259 | # may also be needed; see USB_STORAGE Help for more information | 1265 | # see USB_STORAGE Help for more information |
1260 | # | 1266 | # |
1261 | CONFIG_USB_STORAGE=y | 1267 | CONFIG_USB_STORAGE=y |
1262 | # CONFIG_USB_STORAGE_DEBUG is not set | 1268 | # CONFIG_USB_STORAGE_DEBUG is not set |
@@ -1348,6 +1354,7 @@ CONFIG_RTC_INTF_DEV=y | |||
1348 | # CONFIG_RTC_DRV_M41T80 is not set | 1354 | # CONFIG_RTC_DRV_M41T80 is not set |
1349 | # CONFIG_RTC_DRV_S35390A is not set | 1355 | # CONFIG_RTC_DRV_S35390A is not set |
1350 | # CONFIG_RTC_DRV_FM3130 is not set | 1356 | # CONFIG_RTC_DRV_FM3130 is not set |
1357 | # CONFIG_RTC_DRV_RX8581 is not set | ||
1351 | 1358 | ||
1352 | # | 1359 | # |
1353 | # SPI RTC drivers | 1360 | # SPI RTC drivers |
@@ -1624,6 +1631,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y | |||
1624 | # CONFIG_SAMPLES is not set | 1631 | # CONFIG_SAMPLES is not set |
1625 | CONFIG_HAVE_ARCH_KGDB=y | 1632 | CONFIG_HAVE_ARCH_KGDB=y |
1626 | # CONFIG_KGDB is not set | 1633 | # CONFIG_KGDB is not set |
1634 | CONFIG_PRINT_STACK_DEPTH=64 | ||
1627 | # CONFIG_DEBUG_STACKOVERFLOW is not set | 1635 | # CONFIG_DEBUG_STACKOVERFLOW is not set |
1628 | # CONFIG_DEBUG_STACK_USAGE is not set | 1636 | # CONFIG_DEBUG_STACK_USAGE is not set |
1629 | # CONFIG_DEBUG_PAGEALLOC is not set | 1637 | # CONFIG_DEBUG_PAGEALLOC is not set |
@@ -1649,11 +1657,16 @@ CONFIG_CRYPTO=y | |||
1649 | # | 1657 | # |
1650 | # CONFIG_CRYPTO_FIPS is not set | 1658 | # CONFIG_CRYPTO_FIPS is not set |
1651 | CONFIG_CRYPTO_ALGAPI=y | 1659 | CONFIG_CRYPTO_ALGAPI=y |
1660 | CONFIG_CRYPTO_ALGAPI2=y | ||
1652 | CONFIG_CRYPTO_AEAD=y | 1661 | CONFIG_CRYPTO_AEAD=y |
1662 | CONFIG_CRYPTO_AEAD2=y | ||
1653 | CONFIG_CRYPTO_BLKCIPHER=y | 1663 | CONFIG_CRYPTO_BLKCIPHER=y |
1664 | CONFIG_CRYPTO_BLKCIPHER2=y | ||
1654 | CONFIG_CRYPTO_HASH=y | 1665 | CONFIG_CRYPTO_HASH=y |
1655 | CONFIG_CRYPTO_RNG=y | 1666 | CONFIG_CRYPTO_HASH2=y |
1667 | CONFIG_CRYPTO_RNG2=y | ||
1656 | CONFIG_CRYPTO_MANAGER=y | 1668 | CONFIG_CRYPTO_MANAGER=y |
1669 | CONFIG_CRYPTO_MANAGER2=y | ||
1657 | # CONFIG_CRYPTO_GF128MUL is not set | 1670 | # CONFIG_CRYPTO_GF128MUL is not set |
1658 | # CONFIG_CRYPTO_NULL is not set | 1671 | # CONFIG_CRYPTO_NULL is not set |
1659 | # CONFIG_CRYPTO_CRYPTD is not set | 1672 | # CONFIG_CRYPTO_CRYPTD is not set |
diff --git a/arch/powerpc/configs/86xx/gef_sbc610_defconfig b/arch/powerpc/configs/86xx/gef_sbc610_defconfig index cd1ffa449327..391874c7b436 100644 --- a/arch/powerpc/configs/86xx/gef_sbc610_defconfig +++ b/arch/powerpc/configs/86xx/gef_sbc610_defconfig | |||
@@ -1164,6 +1164,7 @@ CONFIG_WATCHDOG=y | |||
1164 | # CONFIG_SOFT_WATCHDOG is not set | 1164 | # CONFIG_SOFT_WATCHDOG is not set |
1165 | # CONFIG_ALIM7101_WDT is not set | 1165 | # CONFIG_ALIM7101_WDT is not set |
1166 | # CONFIG_8xxx_WDT is not set | 1166 | # CONFIG_8xxx_WDT is not set |
1167 | CONFIG_GEF_WDT=y | ||
1167 | 1168 | ||
1168 | # | 1169 | # |
1169 | # PCI-based Watchdog Cards | 1170 | # PCI-based Watchdog Cards |
diff --git a/arch/powerpc/include/asm/cell-pmu.h b/arch/powerpc/include/asm/cell-pmu.h index 8066eede3a0c..b4b7338ad79e 100644 --- a/arch/powerpc/include/asm/cell-pmu.h +++ b/arch/powerpc/include/asm/cell-pmu.h | |||
@@ -37,9 +37,11 @@ | |||
37 | #define CBE_PM_STOP_AT_MAX 0x40000000 | 37 | #define CBE_PM_STOP_AT_MAX 0x40000000 |
38 | #define CBE_PM_TRACE_MODE_GET(pm_control) (((pm_control) >> 28) & 0x3) | 38 | #define CBE_PM_TRACE_MODE_GET(pm_control) (((pm_control) >> 28) & 0x3) |
39 | #define CBE_PM_TRACE_MODE_SET(mode) (((mode) & 0x3) << 28) | 39 | #define CBE_PM_TRACE_MODE_SET(mode) (((mode) & 0x3) << 28) |
40 | #define CBE_PM_TRACE_BUF_OVFLW(bit) (((bit) & 0x1) << 17) | ||
40 | #define CBE_PM_COUNT_MODE_SET(count) (((count) & 0x3) << 18) | 41 | #define CBE_PM_COUNT_MODE_SET(count) (((count) & 0x3) << 18) |
41 | #define CBE_PM_FREEZE_ALL_CTRS 0x00100000 | 42 | #define CBE_PM_FREEZE_ALL_CTRS 0x00100000 |
42 | #define CBE_PM_ENABLE_EXT_TRACE 0x00008000 | 43 | #define CBE_PM_ENABLE_EXT_TRACE 0x00008000 |
44 | #define CBE_PM_SPU_ADDR_TRACE_SET(msk) (((msk) & 0x3) << 9) | ||
43 | 45 | ||
44 | /* Macros for the trace_address register. */ | 46 | /* Macros for the trace_address register. */ |
45 | #define CBE_PM_TRACE_BUF_FULL 0x00000800 | 47 | #define CBE_PM_TRACE_BUF_FULL 0x00000800 |
diff --git a/arch/powerpc/include/asm/ioctls.h b/arch/powerpc/include/asm/ioctls.h index 279a6229584b..1842186d872c 100644 --- a/arch/powerpc/include/asm/ioctls.h +++ b/arch/powerpc/include/asm/ioctls.h | |||
@@ -89,6 +89,8 @@ | |||
89 | #define TIOCSBRK 0x5427 /* BSD compatibility */ | 89 | #define TIOCSBRK 0x5427 /* BSD compatibility */ |
90 | #define TIOCCBRK 0x5428 /* BSD compatibility */ | 90 | #define TIOCCBRK 0x5428 /* BSD compatibility */ |
91 | #define TIOCGSID 0x5429 /* Return the session ID of FD */ | 91 | #define TIOCGSID 0x5429 /* Return the session ID of FD */ |
92 | #define TIOCGRS485 0x542e | ||
93 | #define TIOCSRS485 0x542f | ||
92 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ | 94 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ |
93 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ | 95 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ |
94 | 96 | ||
diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h index 6dbffc981702..7e06b43720d3 100644 --- a/arch/powerpc/include/asm/kexec.h +++ b/arch/powerpc/include/asm/kexec.h | |||
@@ -48,63 +48,8 @@ static inline void crash_setup_regs(struct pt_regs *newregs, | |||
48 | { | 48 | { |
49 | if (oldregs) | 49 | if (oldregs) |
50 | memcpy(newregs, oldregs, sizeof(*newregs)); | 50 | memcpy(newregs, oldregs, sizeof(*newregs)); |
51 | #ifdef __powerpc64__ | ||
52 | else { | ||
53 | /* FIXME Merge this with xmon_save_regs ?? */ | ||
54 | unsigned long tmp1, tmp2; | ||
55 | __asm__ __volatile__ ( | ||
56 | "std 0,0(%2)\n" | ||
57 | "std 1,8(%2)\n" | ||
58 | "std 2,16(%2)\n" | ||
59 | "std 3,24(%2)\n" | ||
60 | "std 4,32(%2)\n" | ||
61 | "std 5,40(%2)\n" | ||
62 | "std 6,48(%2)\n" | ||
63 | "std 7,56(%2)\n" | ||
64 | "std 8,64(%2)\n" | ||
65 | "std 9,72(%2)\n" | ||
66 | "std 10,80(%2)\n" | ||
67 | "std 11,88(%2)\n" | ||
68 | "std 12,96(%2)\n" | ||
69 | "std 13,104(%2)\n" | ||
70 | "std 14,112(%2)\n" | ||
71 | "std 15,120(%2)\n" | ||
72 | "std 16,128(%2)\n" | ||
73 | "std 17,136(%2)\n" | ||
74 | "std 18,144(%2)\n" | ||
75 | "std 19,152(%2)\n" | ||
76 | "std 20,160(%2)\n" | ||
77 | "std 21,168(%2)\n" | ||
78 | "std 22,176(%2)\n" | ||
79 | "std 23,184(%2)\n" | ||
80 | "std 24,192(%2)\n" | ||
81 | "std 25,200(%2)\n" | ||
82 | "std 26,208(%2)\n" | ||
83 | "std 27,216(%2)\n" | ||
84 | "std 28,224(%2)\n" | ||
85 | "std 29,232(%2)\n" | ||
86 | "std 30,240(%2)\n" | ||
87 | "std 31,248(%2)\n" | ||
88 | "mfmsr %0\n" | ||
89 | "std %0, 264(%2)\n" | ||
90 | "mfctr %0\n" | ||
91 | "std %0, 280(%2)\n" | ||
92 | "mflr %0\n" | ||
93 | "std %0, 288(%2)\n" | ||
94 | "bl 1f\n" | ||
95 | "1: mflr %1\n" | ||
96 | "std %1, 256(%2)\n" | ||
97 | "mtlr %0\n" | ||
98 | "mfxer %0\n" | ||
99 | "std %0, 296(%2)\n" | ||
100 | : "=&r" (tmp1), "=&r" (tmp2) | ||
101 | : "b" (newregs) | ||
102 | : "memory"); | ||
103 | } | ||
104 | #else | ||
105 | else | 51 | else |
106 | ppc_save_regs(newregs); | 52 | ppc_save_regs(newregs); |
107 | #endif /* __powerpc64__ */ | ||
108 | } | 53 | } |
109 | 54 | ||
110 | extern void kexec_smp_wait(void); /* get and clear naca physid, wait for | 55 | extern void kexec_smp_wait(void); /* get and clear naca physid, wait for |
diff --git a/arch/powerpc/include/asm/oprofile_impl.h b/arch/powerpc/include/asm/oprofile_impl.h index 95035c602ba6..639dc96077ab 100644 --- a/arch/powerpc/include/asm/oprofile_impl.h +++ b/arch/powerpc/include/asm/oprofile_impl.h | |||
@@ -32,6 +32,12 @@ struct op_system_config { | |||
32 | unsigned long mmcr0; | 32 | unsigned long mmcr0; |
33 | unsigned long mmcr1; | 33 | unsigned long mmcr1; |
34 | unsigned long mmcra; | 34 | unsigned long mmcra; |
35 | #ifdef CONFIG_OPROFILE_CELL | ||
36 | /* Register for oprofile user tool to check cell kernel profiling | ||
37 | * suport. | ||
38 | */ | ||
39 | unsigned long cell_support; | ||
40 | #endif | ||
35 | #endif | 41 | #endif |
36 | unsigned long enable_kernel; | 42 | unsigned long enable_kernel; |
37 | unsigned long enable_user; | 43 | unsigned long enable_user; |
diff --git a/arch/powerpc/include/asm/ps3.h b/arch/powerpc/include/asm/ps3.h index cff30c0ef1ff..eead5c67197a 100644 --- a/arch/powerpc/include/asm/ps3.h +++ b/arch/powerpc/include/asm/ps3.h | |||
@@ -320,6 +320,7 @@ enum ps3_match_id { | |||
320 | 320 | ||
321 | enum ps3_match_sub_id { | 321 | enum ps3_match_sub_id { |
322 | PS3_MATCH_SUB_ID_GPU_FB = 1, | 322 | PS3_MATCH_SUB_ID_GPU_FB = 1, |
323 | PS3_MATCH_SUB_ID_GPU_RAMDISK = 2, | ||
323 | }; | 324 | }; |
324 | 325 | ||
325 | #define PS3_MODULE_ALIAS_EHCI "ps3:1:0" | 326 | #define PS3_MODULE_ALIAS_EHCI "ps3:1:0" |
@@ -332,6 +333,7 @@ enum ps3_match_sub_id { | |||
332 | #define PS3_MODULE_ALIAS_STOR_FLASH "ps3:8:0" | 333 | #define PS3_MODULE_ALIAS_STOR_FLASH "ps3:8:0" |
333 | #define PS3_MODULE_ALIAS_SOUND "ps3:9:0" | 334 | #define PS3_MODULE_ALIAS_SOUND "ps3:9:0" |
334 | #define PS3_MODULE_ALIAS_GPU_FB "ps3:10:1" | 335 | #define PS3_MODULE_ALIAS_GPU_FB "ps3:10:1" |
336 | #define PS3_MODULE_ALIAS_GPU_RAMDISK "ps3:10:2" | ||
335 | #define PS3_MODULE_ALIAS_LPM "ps3:11:0" | 337 | #define PS3_MODULE_ALIAS_LPM "ps3:11:0" |
336 | 338 | ||
337 | enum ps3_system_bus_device_type { | 339 | enum ps3_system_bus_device_type { |
diff --git a/arch/powerpc/include/asm/qe.h b/arch/powerpc/include/asm/qe.h index edee15d269ea..a0a15311d0d8 100644 --- a/arch/powerpc/include/asm/qe.h +++ b/arch/powerpc/include/asm/qe.h | |||
@@ -17,6 +17,8 @@ | |||
17 | #ifdef __KERNEL__ | 17 | #ifdef __KERNEL__ |
18 | 18 | ||
19 | #include <linux/spinlock.h> | 19 | #include <linux/spinlock.h> |
20 | #include <linux/errno.h> | ||
21 | #include <linux/err.h> | ||
20 | #include <asm/cpm.h> | 22 | #include <asm/cpm.h> |
21 | #include <asm/immap_qe.h> | 23 | #include <asm/immap_qe.h> |
22 | 24 | ||
@@ -84,7 +86,11 @@ static inline bool qe_clock_is_brg(enum qe_clock clk) | |||
84 | extern spinlock_t cmxgcr_lock; | 86 | extern spinlock_t cmxgcr_lock; |
85 | 87 | ||
86 | /* Export QE common operations */ | 88 | /* Export QE common operations */ |
89 | #ifdef CONFIG_QUICC_ENGINE | ||
87 | extern void __init qe_reset(void); | 90 | extern void __init qe_reset(void); |
91 | #else | ||
92 | static inline void qe_reset(void) {} | ||
93 | #endif | ||
88 | 94 | ||
89 | /* QE PIO */ | 95 | /* QE PIO */ |
90 | #define QE_PIO_PINS 32 | 96 | #define QE_PIO_PINS 32 |
@@ -101,16 +107,43 @@ struct qe_pio_regs { | |||
101 | #endif | 107 | #endif |
102 | }; | 108 | }; |
103 | 109 | ||
104 | extern int par_io_init(struct device_node *np); | ||
105 | extern int par_io_of_config(struct device_node *np); | ||
106 | #define QE_PIO_DIR_IN 2 | 110 | #define QE_PIO_DIR_IN 2 |
107 | #define QE_PIO_DIR_OUT 1 | 111 | #define QE_PIO_DIR_OUT 1 |
108 | extern void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin, | 112 | extern void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin, |
109 | int dir, int open_drain, int assignment, | 113 | int dir, int open_drain, int assignment, |
110 | int has_irq); | 114 | int has_irq); |
115 | #ifdef CONFIG_QUICC_ENGINE | ||
116 | extern int par_io_init(struct device_node *np); | ||
117 | extern int par_io_of_config(struct device_node *np); | ||
111 | extern int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain, | 118 | extern int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain, |
112 | int assignment, int has_irq); | 119 | int assignment, int has_irq); |
113 | extern int par_io_data_set(u8 port, u8 pin, u8 val); | 120 | extern int par_io_data_set(u8 port, u8 pin, u8 val); |
121 | #else | ||
122 | static inline int par_io_init(struct device_node *np) { return -ENOSYS; } | ||
123 | static inline int par_io_of_config(struct device_node *np) { return -ENOSYS; } | ||
124 | static inline int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain, | ||
125 | int assignment, int has_irq) { return -ENOSYS; } | ||
126 | static inline int par_io_data_set(u8 port, u8 pin, u8 val) { return -ENOSYS; } | ||
127 | #endif /* CONFIG_QUICC_ENGINE */ | ||
128 | |||
129 | /* | ||
130 | * Pin multiplexing functions. | ||
131 | */ | ||
132 | struct qe_pin; | ||
133 | #ifdef CONFIG_QE_GPIO | ||
134 | extern struct qe_pin *qe_pin_request(struct device_node *np, int index); | ||
135 | extern void qe_pin_free(struct qe_pin *qe_pin); | ||
136 | extern void qe_pin_set_gpio(struct qe_pin *qe_pin); | ||
137 | extern void qe_pin_set_dedicated(struct qe_pin *pin); | ||
138 | #else | ||
139 | static inline struct qe_pin *qe_pin_request(struct device_node *np, int index) | ||
140 | { | ||
141 | return ERR_PTR(-ENOSYS); | ||
142 | } | ||
143 | static inline void qe_pin_free(struct qe_pin *qe_pin) {} | ||
144 | static inline void qe_pin_set_gpio(struct qe_pin *qe_pin) {} | ||
145 | static inline void qe_pin_set_dedicated(struct qe_pin *pin) {} | ||
146 | #endif /* CONFIG_QE_GPIO */ | ||
114 | 147 | ||
115 | /* QE internal API */ | 148 | /* QE internal API */ |
116 | int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input); | 149 | int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input); |
diff --git a/arch/powerpc/include/asm/qe_ic.h b/arch/powerpc/include/asm/qe_ic.h index 56a7745ca343..cf519663a791 100644 --- a/arch/powerpc/include/asm/qe_ic.h +++ b/arch/powerpc/include/asm/qe_ic.h | |||
@@ -17,6 +17,9 @@ | |||
17 | 17 | ||
18 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
19 | 19 | ||
20 | struct device_node; | ||
21 | struct qe_ic; | ||
22 | |||
20 | #define NUM_OF_QE_IC_GROUPS 6 | 23 | #define NUM_OF_QE_IC_GROUPS 6 |
21 | 24 | ||
22 | /* Flags when we init the QE IC */ | 25 | /* Flags when we init the QE IC */ |
@@ -54,17 +57,27 @@ enum qe_ic_grp_id { | |||
54 | QE_IC_GRP_RISCB /* QE interrupt controller RISC group B */ | 57 | QE_IC_GRP_RISCB /* QE interrupt controller RISC group B */ |
55 | }; | 58 | }; |
56 | 59 | ||
60 | #ifdef CONFIG_QUICC_ENGINE | ||
57 | void qe_ic_init(struct device_node *node, unsigned int flags, | 61 | void qe_ic_init(struct device_node *node, unsigned int flags, |
58 | void (*low_handler)(unsigned int irq, struct irq_desc *desc), | 62 | void (*low_handler)(unsigned int irq, struct irq_desc *desc), |
59 | void (*high_handler)(unsigned int irq, struct irq_desc *desc)); | 63 | void (*high_handler)(unsigned int irq, struct irq_desc *desc)); |
64 | unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic); | ||
65 | unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic); | ||
66 | #else | ||
67 | static inline void qe_ic_init(struct device_node *node, unsigned int flags, | ||
68 | void (*low_handler)(unsigned int irq, struct irq_desc *desc), | ||
69 | void (*high_handler)(unsigned int irq, struct irq_desc *desc)) | ||
70 | {} | ||
71 | static inline unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic) | ||
72 | { return 0; } | ||
73 | static inline unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic) | ||
74 | { return 0; } | ||
75 | #endif /* CONFIG_QUICC_ENGINE */ | ||
76 | |||
60 | void qe_ic_set_highest_priority(unsigned int virq, int high); | 77 | void qe_ic_set_highest_priority(unsigned int virq, int high); |
61 | int qe_ic_set_priority(unsigned int virq, unsigned int priority); | 78 | int qe_ic_set_priority(unsigned int virq, unsigned int priority); |
62 | int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high); | 79 | int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high); |
63 | 80 | ||
64 | struct qe_ic; | ||
65 | unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic); | ||
66 | unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic); | ||
67 | |||
68 | static inline void qe_ic_cascade_low_ipic(unsigned int irq, | 81 | static inline void qe_ic_cascade_low_ipic(unsigned int irq, |
69 | struct irq_desc *desc) | 82 | struct irq_desc *desc) |
70 | { | 83 | { |
diff --git a/arch/powerpc/include/asm/spu.h b/arch/powerpc/include/asm/spu.h index 8b2eb044270a..0ab8d869e3d6 100644 --- a/arch/powerpc/include/asm/spu.h +++ b/arch/powerpc/include/asm/spu.h | |||
@@ -128,7 +128,7 @@ struct spu { | |||
128 | int number; | 128 | int number; |
129 | unsigned int irqs[3]; | 129 | unsigned int irqs[3]; |
130 | u32 node; | 130 | u32 node; |
131 | u64 flags; | 131 | unsigned long flags; |
132 | u64 class_0_pending; | 132 | u64 class_0_pending; |
133 | u64 class_0_dar; | 133 | u64 class_0_dar; |
134 | u64 class_1_dar; | 134 | u64 class_1_dar; |
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 1308a86e9070..8d1a419df35d 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -29,7 +29,7 @@ endif | |||
29 | obj-y := cputable.o ptrace.o syscalls.o \ | 29 | obj-y := cputable.o ptrace.o syscalls.o \ |
30 | irq.o align.o signal_32.o pmc.o vdso.o \ | 30 | irq.o align.o signal_32.o pmc.o vdso.o \ |
31 | init_task.o process.o systbl.o idle.o \ | 31 | init_task.o process.o systbl.o idle.o \ |
32 | signal.o sysfs.o | 32 | signal.o sysfs.o cacheinfo.o |
33 | obj-y += vdso32/ | 33 | obj-y += vdso32/ |
34 | obj-$(CONFIG_PPC64) += setup_64.o sys_ppc32.o \ | 34 | obj-$(CONFIG_PPC64) += setup_64.o sys_ppc32.o \ |
35 | signal_64.o ptrace32.o \ | 35 | signal_64.o ptrace32.o \ |
diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c new file mode 100644 index 000000000000..b33f0417a4bf --- /dev/null +++ b/arch/powerpc/kernel/cacheinfo.c | |||
@@ -0,0 +1,837 @@ | |||
1 | /* | ||
2 | * Processor cache information made available to userspace via sysfs; | ||
3 | * intended to be compatible with x86 intel_cacheinfo implementation. | ||
4 | * | ||
5 | * Copyright 2008 IBM Corporation | ||
6 | * Author: Nathan Lynch | ||
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 | ||
10 | * 2 as published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/cpu.h> | ||
14 | #include <linux/cpumask.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/kobject.h> | ||
18 | #include <linux/list.h> | ||
19 | #include <linux/notifier.h> | ||
20 | #include <linux/of.h> | ||
21 | #include <linux/percpu.h> | ||
22 | #include <asm/prom.h> | ||
23 | |||
24 | #include "cacheinfo.h" | ||
25 | |||
26 | /* per-cpu object for tracking: | ||
27 | * - a "cache" kobject for the top-level directory | ||
28 | * - a list of "index" objects representing the cpu's local cache hierarchy | ||
29 | */ | ||
30 | struct cache_dir { | ||
31 | struct kobject *kobj; /* bare (not embedded) kobject for cache | ||
32 | * directory */ | ||
33 | struct cache_index_dir *index; /* list of index objects */ | ||
34 | }; | ||
35 | |||
36 | /* "index" object: each cpu's cache directory has an index | ||
37 | * subdirectory corresponding to a cache object associated with the | ||
38 | * cpu. This object's lifetime is managed via the embedded kobject. | ||
39 | */ | ||
40 | struct cache_index_dir { | ||
41 | struct kobject kobj; | ||
42 | struct cache_index_dir *next; /* next index in parent directory */ | ||
43 | struct cache *cache; | ||
44 | }; | ||
45 | |||
46 | /* Template for determining which OF properties to query for a given | ||
47 | * cache type */ | ||
48 | struct cache_type_info { | ||
49 | const char *name; | ||
50 | const char *size_prop; | ||
51 | |||
52 | /* Allow for both [di]-cache-line-size and | ||
53 | * [di]-cache-block-size properties. According to the PowerPC | ||
54 | * Processor binding, -line-size should be provided if it | ||
55 | * differs from the cache block size (that which is operated | ||
56 | * on by cache instructions), so we look for -line-size first. | ||
57 | * See cache_get_line_size(). */ | ||
58 | |||
59 | const char *line_size_props[2]; | ||
60 | const char *nr_sets_prop; | ||
61 | }; | ||
62 | |||
63 | /* These are used to index the cache_type_info array. */ | ||
64 | #define CACHE_TYPE_UNIFIED 0 | ||
65 | #define CACHE_TYPE_INSTRUCTION 1 | ||
66 | #define CACHE_TYPE_DATA 2 | ||
67 | |||
68 | static const struct cache_type_info cache_type_info[] = { | ||
69 | { | ||
70 | /* PowerPC Processor binding says the [di]-cache-* | ||
71 | * must be equal on unified caches, so just use | ||
72 | * d-cache properties. */ | ||
73 | .name = "Unified", | ||
74 | .size_prop = "d-cache-size", | ||
75 | .line_size_props = { "d-cache-line-size", | ||
76 | "d-cache-block-size", }, | ||
77 | .nr_sets_prop = "d-cache-sets", | ||
78 | }, | ||
79 | { | ||
80 | .name = "Instruction", | ||
81 | .size_prop = "i-cache-size", | ||
82 | .line_size_props = { "i-cache-line-size", | ||
83 | "i-cache-block-size", }, | ||
84 | .nr_sets_prop = "i-cache-sets", | ||
85 | }, | ||
86 | { | ||
87 | .name = "Data", | ||
88 | .size_prop = "d-cache-size", | ||
89 | .line_size_props = { "d-cache-line-size", | ||
90 | "d-cache-block-size", }, | ||
91 | .nr_sets_prop = "d-cache-sets", | ||
92 | }, | ||
93 | }; | ||
94 | |||
95 | /* Cache object: each instance of this corresponds to a distinct cache | ||
96 | * in the system. There are separate objects for Harvard caches: one | ||
97 | * each for instruction and data, and each refers to the same OF node. | ||
98 | * The refcount of the OF node is elevated for the lifetime of the | ||
99 | * cache object. A cache object is released when its shared_cpu_map | ||
100 | * is cleared (see cache_cpu_clear). | ||
101 | * | ||
102 | * A cache object is on two lists: an unsorted global list | ||
103 | * (cache_list) of cache objects; and a singly-linked list | ||
104 | * representing the local cache hierarchy, which is ordered by level | ||
105 | * (e.g. L1d -> L1i -> L2 -> L3). | ||
106 | */ | ||
107 | struct cache { | ||
108 | struct device_node *ofnode; /* OF node for this cache, may be cpu */ | ||
109 | struct cpumask shared_cpu_map; /* online CPUs using this cache */ | ||
110 | int type; /* split cache disambiguation */ | ||
111 | int level; /* level not explicit in device tree */ | ||
112 | struct list_head list; /* global list of cache objects */ | ||
113 | struct cache *next_local; /* next cache of >= level */ | ||
114 | }; | ||
115 | |||
116 | static DEFINE_PER_CPU(struct cache_dir *, cache_dir); | ||
117 | |||
118 | /* traversal/modification of this list occurs only at cpu hotplug time; | ||
119 | * access is serialized by cpu hotplug locking | ||
120 | */ | ||
121 | static LIST_HEAD(cache_list); | ||
122 | |||
123 | static struct cache_index_dir *kobj_to_cache_index_dir(struct kobject *k) | ||
124 | { | ||
125 | return container_of(k, struct cache_index_dir, kobj); | ||
126 | } | ||
127 | |||
128 | static const char *cache_type_string(const struct cache *cache) | ||
129 | { | ||
130 | return cache_type_info[cache->type].name; | ||
131 | } | ||
132 | |||
133 | static void __cpuinit cache_init(struct cache *cache, int type, int level, struct device_node *ofnode) | ||
134 | { | ||
135 | cache->type = type; | ||
136 | cache->level = level; | ||
137 | cache->ofnode = of_node_get(ofnode); | ||
138 | INIT_LIST_HEAD(&cache->list); | ||
139 | list_add(&cache->list, &cache_list); | ||
140 | } | ||
141 | |||
142 | static struct cache *__cpuinit new_cache(int type, int level, struct device_node *ofnode) | ||
143 | { | ||
144 | struct cache *cache; | ||
145 | |||
146 | cache = kzalloc(sizeof(*cache), GFP_KERNEL); | ||
147 | if (cache) | ||
148 | cache_init(cache, type, level, ofnode); | ||
149 | |||
150 | return cache; | ||
151 | } | ||
152 | |||
153 | static void release_cache_debugcheck(struct cache *cache) | ||
154 | { | ||
155 | struct cache *iter; | ||
156 | |||
157 | list_for_each_entry(iter, &cache_list, list) | ||
158 | WARN_ONCE(iter->next_local == cache, | ||
159 | "cache for %s(%s) refers to cache for %s(%s)\n", | ||
160 | iter->ofnode->full_name, | ||
161 | cache_type_string(iter), | ||
162 | cache->ofnode->full_name, | ||
163 | cache_type_string(cache)); | ||
164 | } | ||
165 | |||
166 | static void release_cache(struct cache *cache) | ||
167 | { | ||
168 | if (!cache) | ||
169 | return; | ||
170 | |||
171 | pr_debug("freeing L%d %s cache for %s\n", cache->level, | ||
172 | cache_type_string(cache), cache->ofnode->full_name); | ||
173 | |||
174 | release_cache_debugcheck(cache); | ||
175 | list_del(&cache->list); | ||
176 | of_node_put(cache->ofnode); | ||
177 | kfree(cache); | ||
178 | } | ||
179 | |||
180 | static void cache_cpu_set(struct cache *cache, int cpu) | ||
181 | { | ||
182 | struct cache *next = cache; | ||
183 | |||
184 | while (next) { | ||
185 | WARN_ONCE(cpumask_test_cpu(cpu, &next->shared_cpu_map), | ||
186 | "CPU %i already accounted in %s(%s)\n", | ||
187 | cpu, next->ofnode->full_name, | ||
188 | cache_type_string(next)); | ||
189 | cpumask_set_cpu(cpu, &next->shared_cpu_map); | ||
190 | next = next->next_local; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | static int cache_size(const struct cache *cache, unsigned int *ret) | ||
195 | { | ||
196 | const char *propname; | ||
197 | const u32 *cache_size; | ||
198 | |||
199 | propname = cache_type_info[cache->type].size_prop; | ||
200 | |||
201 | cache_size = of_get_property(cache->ofnode, propname, NULL); | ||
202 | if (!cache_size) | ||
203 | return -ENODEV; | ||
204 | |||
205 | *ret = *cache_size; | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static int cache_size_kb(const struct cache *cache, unsigned int *ret) | ||
210 | { | ||
211 | unsigned int size; | ||
212 | |||
213 | if (cache_size(cache, &size)) | ||
214 | return -ENODEV; | ||
215 | |||
216 | *ret = size / 1024; | ||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | /* not cache_line_size() because that's a macro in include/linux/cache.h */ | ||
221 | static int cache_get_line_size(const struct cache *cache, unsigned int *ret) | ||
222 | { | ||
223 | const u32 *line_size; | ||
224 | int i, lim; | ||
225 | |||
226 | lim = ARRAY_SIZE(cache_type_info[cache->type].line_size_props); | ||
227 | |||
228 | for (i = 0; i < lim; i++) { | ||
229 | const char *propname; | ||
230 | |||
231 | propname = cache_type_info[cache->type].line_size_props[i]; | ||
232 | line_size = of_get_property(cache->ofnode, propname, NULL); | ||
233 | if (line_size) | ||
234 | break; | ||
235 | } | ||
236 | |||
237 | if (!line_size) | ||
238 | return -ENODEV; | ||
239 | |||
240 | *ret = *line_size; | ||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static int cache_nr_sets(const struct cache *cache, unsigned int *ret) | ||
245 | { | ||
246 | const char *propname; | ||
247 | const u32 *nr_sets; | ||
248 | |||
249 | propname = cache_type_info[cache->type].nr_sets_prop; | ||
250 | |||
251 | nr_sets = of_get_property(cache->ofnode, propname, NULL); | ||
252 | if (!nr_sets) | ||
253 | return -ENODEV; | ||
254 | |||
255 | *ret = *nr_sets; | ||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static int cache_associativity(const struct cache *cache, unsigned int *ret) | ||
260 | { | ||
261 | unsigned int line_size; | ||
262 | unsigned int nr_sets; | ||
263 | unsigned int size; | ||
264 | |||
265 | if (cache_nr_sets(cache, &nr_sets)) | ||
266 | goto err; | ||
267 | |||
268 | /* If the cache is fully associative, there is no need to | ||
269 | * check the other properties. | ||
270 | */ | ||
271 | if (nr_sets == 1) { | ||
272 | *ret = 0; | ||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | if (cache_get_line_size(cache, &line_size)) | ||
277 | goto err; | ||
278 | if (cache_size(cache, &size)) | ||
279 | goto err; | ||
280 | |||
281 | if (!(nr_sets > 0 && size > 0 && line_size > 0)) | ||
282 | goto err; | ||
283 | |||
284 | *ret = (size / nr_sets) / line_size; | ||
285 | return 0; | ||
286 | err: | ||
287 | return -ENODEV; | ||
288 | } | ||
289 | |||
290 | /* helper for dealing with split caches */ | ||
291 | static struct cache *cache_find_first_sibling(struct cache *cache) | ||
292 | { | ||
293 | struct cache *iter; | ||
294 | |||
295 | if (cache->type == CACHE_TYPE_UNIFIED) | ||
296 | return cache; | ||
297 | |||
298 | list_for_each_entry(iter, &cache_list, list) | ||
299 | if (iter->ofnode == cache->ofnode && iter->next_local == cache) | ||
300 | return iter; | ||
301 | |||
302 | return cache; | ||
303 | } | ||
304 | |||
305 | /* return the first cache on a local list matching node */ | ||
306 | static struct cache *cache_lookup_by_node(const struct device_node *node) | ||
307 | { | ||
308 | struct cache *cache = NULL; | ||
309 | struct cache *iter; | ||
310 | |||
311 | list_for_each_entry(iter, &cache_list, list) { | ||
312 | if (iter->ofnode != node) | ||
313 | continue; | ||
314 | cache = cache_find_first_sibling(iter); | ||
315 | break; | ||
316 | } | ||
317 | |||
318 | return cache; | ||
319 | } | ||
320 | |||
321 | static bool cache_node_is_unified(const struct device_node *np) | ||
322 | { | ||
323 | return of_get_property(np, "cache-unified", NULL); | ||
324 | } | ||
325 | |||
326 | static struct cache *__cpuinit cache_do_one_devnode_unified(struct device_node *node, int level) | ||
327 | { | ||
328 | struct cache *cache; | ||
329 | |||
330 | pr_debug("creating L%d ucache for %s\n", level, node->full_name); | ||
331 | |||
332 | cache = new_cache(CACHE_TYPE_UNIFIED, level, node); | ||
333 | |||
334 | return cache; | ||
335 | } | ||
336 | |||
337 | static struct cache *__cpuinit cache_do_one_devnode_split(struct device_node *node, int level) | ||
338 | { | ||
339 | struct cache *dcache, *icache; | ||
340 | |||
341 | pr_debug("creating L%d dcache and icache for %s\n", level, | ||
342 | node->full_name); | ||
343 | |||
344 | dcache = new_cache(CACHE_TYPE_DATA, level, node); | ||
345 | icache = new_cache(CACHE_TYPE_INSTRUCTION, level, node); | ||
346 | |||
347 | if (!dcache || !icache) | ||
348 | goto err; | ||
349 | |||
350 | dcache->next_local = icache; | ||
351 | |||
352 | return dcache; | ||
353 | err: | ||
354 | release_cache(dcache); | ||
355 | release_cache(icache); | ||
356 | return NULL; | ||
357 | } | ||
358 | |||
359 | static struct cache *__cpuinit cache_do_one_devnode(struct device_node *node, int level) | ||
360 | { | ||
361 | struct cache *cache; | ||
362 | |||
363 | if (cache_node_is_unified(node)) | ||
364 | cache = cache_do_one_devnode_unified(node, level); | ||
365 | else | ||
366 | cache = cache_do_one_devnode_split(node, level); | ||
367 | |||
368 | return cache; | ||
369 | } | ||
370 | |||
371 | static struct cache *__cpuinit cache_lookup_or_instantiate(struct device_node *node, int level) | ||
372 | { | ||
373 | struct cache *cache; | ||
374 | |||
375 | cache = cache_lookup_by_node(node); | ||
376 | |||
377 | WARN_ONCE(cache && cache->level != level, | ||
378 | "cache level mismatch on lookup (got %d, expected %d)\n", | ||
379 | cache->level, level); | ||
380 | |||
381 | if (!cache) | ||
382 | cache = cache_do_one_devnode(node, level); | ||
383 | |||
384 | return cache; | ||
385 | } | ||
386 | |||
387 | static void __cpuinit link_cache_lists(struct cache *smaller, struct cache *bigger) | ||
388 | { | ||
389 | while (smaller->next_local) { | ||
390 | if (smaller->next_local == bigger) | ||
391 | return; /* already linked */ | ||
392 | smaller = smaller->next_local; | ||
393 | } | ||
394 | |||
395 | smaller->next_local = bigger; | ||
396 | } | ||
397 | |||
398 | static void __cpuinit do_subsidiary_caches_debugcheck(struct cache *cache) | ||
399 | { | ||
400 | WARN_ON_ONCE(cache->level != 1); | ||
401 | WARN_ON_ONCE(strcmp(cache->ofnode->type, "cpu")); | ||
402 | } | ||
403 | |||
404 | static void __cpuinit do_subsidiary_caches(struct cache *cache) | ||
405 | { | ||
406 | struct device_node *subcache_node; | ||
407 | int level = cache->level; | ||
408 | |||
409 | do_subsidiary_caches_debugcheck(cache); | ||
410 | |||
411 | while ((subcache_node = of_find_next_cache_node(cache->ofnode))) { | ||
412 | struct cache *subcache; | ||
413 | |||
414 | level++; | ||
415 | subcache = cache_lookup_or_instantiate(subcache_node, level); | ||
416 | of_node_put(subcache_node); | ||
417 | if (!subcache) | ||
418 | break; | ||
419 | |||
420 | link_cache_lists(cache, subcache); | ||
421 | cache = subcache; | ||
422 | } | ||
423 | } | ||
424 | |||
425 | static struct cache *__cpuinit cache_chain_instantiate(unsigned int cpu_id) | ||
426 | { | ||
427 | struct device_node *cpu_node; | ||
428 | struct cache *cpu_cache = NULL; | ||
429 | |||
430 | pr_debug("creating cache object(s) for CPU %i\n", cpu_id); | ||
431 | |||
432 | cpu_node = of_get_cpu_node(cpu_id, NULL); | ||
433 | WARN_ONCE(!cpu_node, "no OF node found for CPU %i\n", cpu_id); | ||
434 | if (!cpu_node) | ||
435 | goto out; | ||
436 | |||
437 | cpu_cache = cache_lookup_or_instantiate(cpu_node, 1); | ||
438 | if (!cpu_cache) | ||
439 | goto out; | ||
440 | |||
441 | do_subsidiary_caches(cpu_cache); | ||
442 | |||
443 | cache_cpu_set(cpu_cache, cpu_id); | ||
444 | out: | ||
445 | of_node_put(cpu_node); | ||
446 | |||
447 | return cpu_cache; | ||
448 | } | ||
449 | |||
450 | static struct cache_dir *__cpuinit cacheinfo_create_cache_dir(unsigned int cpu_id) | ||
451 | { | ||
452 | struct cache_dir *cache_dir; | ||
453 | struct sys_device *sysdev; | ||
454 | struct kobject *kobj = NULL; | ||
455 | |||
456 | sysdev = get_cpu_sysdev(cpu_id); | ||
457 | WARN_ONCE(!sysdev, "no sysdev for CPU %i\n", cpu_id); | ||
458 | if (!sysdev) | ||
459 | goto err; | ||
460 | |||
461 | kobj = kobject_create_and_add("cache", &sysdev->kobj); | ||
462 | if (!kobj) | ||
463 | goto err; | ||
464 | |||
465 | cache_dir = kzalloc(sizeof(*cache_dir), GFP_KERNEL); | ||
466 | if (!cache_dir) | ||
467 | goto err; | ||
468 | |||
469 | cache_dir->kobj = kobj; | ||
470 | |||
471 | WARN_ON_ONCE(per_cpu(cache_dir, cpu_id) != NULL); | ||
472 | |||
473 | per_cpu(cache_dir, cpu_id) = cache_dir; | ||
474 | |||
475 | return cache_dir; | ||
476 | err: | ||
477 | kobject_put(kobj); | ||
478 | return NULL; | ||
479 | } | ||
480 | |||
481 | static void cache_index_release(struct kobject *kobj) | ||
482 | { | ||
483 | struct cache_index_dir *index; | ||
484 | |||
485 | index = kobj_to_cache_index_dir(kobj); | ||
486 | |||
487 | pr_debug("freeing index directory for L%d %s cache\n", | ||
488 | index->cache->level, cache_type_string(index->cache)); | ||
489 | |||
490 | kfree(index); | ||
491 | } | ||
492 | |||
493 | static ssize_t cache_index_show(struct kobject *k, struct attribute *attr, char *buf) | ||
494 | { | ||
495 | struct kobj_attribute *kobj_attr; | ||
496 | |||
497 | kobj_attr = container_of(attr, struct kobj_attribute, attr); | ||
498 | |||
499 | return kobj_attr->show(k, kobj_attr, buf); | ||
500 | } | ||
501 | |||
502 | static struct cache *index_kobj_to_cache(struct kobject *k) | ||
503 | { | ||
504 | struct cache_index_dir *index; | ||
505 | |||
506 | index = kobj_to_cache_index_dir(k); | ||
507 | |||
508 | return index->cache; | ||
509 | } | ||
510 | |||
511 | static ssize_t size_show(struct kobject *k, struct kobj_attribute *attr, char *buf) | ||
512 | { | ||
513 | unsigned int size_kb; | ||
514 | struct cache *cache; | ||
515 | |||
516 | cache = index_kobj_to_cache(k); | ||
517 | |||
518 | if (cache_size_kb(cache, &size_kb)) | ||
519 | return -ENODEV; | ||
520 | |||
521 | return sprintf(buf, "%uK\n", size_kb); | ||
522 | } | ||
523 | |||
524 | static struct kobj_attribute cache_size_attr = | ||
525 | __ATTR(size, 0444, size_show, NULL); | ||
526 | |||
527 | |||
528 | static ssize_t line_size_show(struct kobject *k, struct kobj_attribute *attr, char *buf) | ||
529 | { | ||
530 | unsigned int line_size; | ||
531 | struct cache *cache; | ||
532 | |||
533 | cache = index_kobj_to_cache(k); | ||
534 | |||
535 | if (cache_get_line_size(cache, &line_size)) | ||
536 | return -ENODEV; | ||
537 | |||
538 | return sprintf(buf, "%u\n", line_size); | ||
539 | } | ||
540 | |||
541 | static struct kobj_attribute cache_line_size_attr = | ||
542 | __ATTR(coherency_line_size, 0444, line_size_show, NULL); | ||
543 | |||
544 | static ssize_t nr_sets_show(struct kobject *k, struct kobj_attribute *attr, char *buf) | ||
545 | { | ||
546 | unsigned int nr_sets; | ||
547 | struct cache *cache; | ||
548 | |||
549 | cache = index_kobj_to_cache(k); | ||
550 | |||
551 | if (cache_nr_sets(cache, &nr_sets)) | ||
552 | return -ENODEV; | ||
553 | |||
554 | return sprintf(buf, "%u\n", nr_sets); | ||
555 | } | ||
556 | |||
557 | static struct kobj_attribute cache_nr_sets_attr = | ||
558 | __ATTR(number_of_sets, 0444, nr_sets_show, NULL); | ||
559 | |||
560 | static ssize_t associativity_show(struct kobject *k, struct kobj_attribute *attr, char *buf) | ||
561 | { | ||
562 | unsigned int associativity; | ||
563 | struct cache *cache; | ||
564 | |||
565 | cache = index_kobj_to_cache(k); | ||
566 | |||
567 | if (cache_associativity(cache, &associativity)) | ||
568 | return -ENODEV; | ||
569 | |||
570 | return sprintf(buf, "%u\n", associativity); | ||
571 | } | ||
572 | |||
573 | static struct kobj_attribute cache_assoc_attr = | ||
574 | __ATTR(ways_of_associativity, 0444, associativity_show, NULL); | ||
575 | |||
576 | static ssize_t type_show(struct kobject *k, struct kobj_attribute *attr, char *buf) | ||
577 | { | ||
578 | struct cache *cache; | ||
579 | |||
580 | cache = index_kobj_to_cache(k); | ||
581 | |||
582 | return sprintf(buf, "%s\n", cache_type_string(cache)); | ||
583 | } | ||
584 | |||
585 | static struct kobj_attribute cache_type_attr = | ||
586 | __ATTR(type, 0444, type_show, NULL); | ||
587 | |||
588 | static ssize_t level_show(struct kobject *k, struct kobj_attribute *attr, char *buf) | ||
589 | { | ||
590 | struct cache_index_dir *index; | ||
591 | struct cache *cache; | ||
592 | |||
593 | index = kobj_to_cache_index_dir(k); | ||
594 | cache = index->cache; | ||
595 | |||
596 | return sprintf(buf, "%d\n", cache->level); | ||
597 | } | ||
598 | |||
599 | static struct kobj_attribute cache_level_attr = | ||
600 | __ATTR(level, 0444, level_show, NULL); | ||
601 | |||
602 | static ssize_t shared_cpu_map_show(struct kobject *k, struct kobj_attribute *attr, char *buf) | ||
603 | { | ||
604 | struct cache_index_dir *index; | ||
605 | struct cache *cache; | ||
606 | int len; | ||
607 | int n = 0; | ||
608 | |||
609 | index = kobj_to_cache_index_dir(k); | ||
610 | cache = index->cache; | ||
611 | len = PAGE_SIZE - 2; | ||
612 | |||
613 | if (len > 1) { | ||
614 | n = cpumask_scnprintf(buf, len, &cache->shared_cpu_map); | ||
615 | buf[n++] = '\n'; | ||
616 | buf[n] = '\0'; | ||
617 | } | ||
618 | return n; | ||
619 | } | ||
620 | |||
621 | static struct kobj_attribute cache_shared_cpu_map_attr = | ||
622 | __ATTR(shared_cpu_map, 0444, shared_cpu_map_show, NULL); | ||
623 | |||
624 | /* Attributes which should always be created -- the kobject/sysfs core | ||
625 | * does this automatically via kobj_type->default_attrs. This is the | ||
626 | * minimum data required to uniquely identify a cache. | ||
627 | */ | ||
628 | static struct attribute *cache_index_default_attrs[] = { | ||
629 | &cache_type_attr.attr, | ||
630 | &cache_level_attr.attr, | ||
631 | &cache_shared_cpu_map_attr.attr, | ||
632 | NULL, | ||
633 | }; | ||
634 | |||
635 | /* Attributes which should be created if the cache device node has the | ||
636 | * right properties -- see cacheinfo_create_index_opt_attrs | ||
637 | */ | ||
638 | static struct kobj_attribute *cache_index_opt_attrs[] = { | ||
639 | &cache_size_attr, | ||
640 | &cache_line_size_attr, | ||
641 | &cache_nr_sets_attr, | ||
642 | &cache_assoc_attr, | ||
643 | }; | ||
644 | |||
645 | static struct sysfs_ops cache_index_ops = { | ||
646 | .show = cache_index_show, | ||
647 | }; | ||
648 | |||
649 | static struct kobj_type cache_index_type = { | ||
650 | .release = cache_index_release, | ||
651 | .sysfs_ops = &cache_index_ops, | ||
652 | .default_attrs = cache_index_default_attrs, | ||
653 | }; | ||
654 | |||
655 | static void __cpuinit cacheinfo_create_index_opt_attrs(struct cache_index_dir *dir) | ||
656 | { | ||
657 | const char *cache_name; | ||
658 | const char *cache_type; | ||
659 | struct cache *cache; | ||
660 | char *buf; | ||
661 | int i; | ||
662 | |||
663 | buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
664 | if (!buf) | ||
665 | return; | ||
666 | |||
667 | cache = dir->cache; | ||
668 | cache_name = cache->ofnode->full_name; | ||
669 | cache_type = cache_type_string(cache); | ||
670 | |||
671 | /* We don't want to create an attribute that can't provide a | ||
672 | * meaningful value. Check the return value of each optional | ||
673 | * attribute's ->show method before registering the | ||
674 | * attribute. | ||
675 | */ | ||
676 | for (i = 0; i < ARRAY_SIZE(cache_index_opt_attrs); i++) { | ||
677 | struct kobj_attribute *attr; | ||
678 | ssize_t rc; | ||
679 | |||
680 | attr = cache_index_opt_attrs[i]; | ||
681 | |||
682 | rc = attr->show(&dir->kobj, attr, buf); | ||
683 | if (rc <= 0) { | ||
684 | pr_debug("not creating %s attribute for " | ||
685 | "%s(%s) (rc = %zd)\n", | ||
686 | attr->attr.name, cache_name, | ||
687 | cache_type, rc); | ||
688 | continue; | ||
689 | } | ||
690 | if (sysfs_create_file(&dir->kobj, &attr->attr)) | ||
691 | pr_debug("could not create %s attribute for %s(%s)\n", | ||
692 | attr->attr.name, cache_name, cache_type); | ||
693 | } | ||
694 | |||
695 | kfree(buf); | ||
696 | } | ||
697 | |||
698 | static void __cpuinit cacheinfo_create_index_dir(struct cache *cache, int index, struct cache_dir *cache_dir) | ||
699 | { | ||
700 | struct cache_index_dir *index_dir; | ||
701 | int rc; | ||
702 | |||
703 | index_dir = kzalloc(sizeof(*index_dir), GFP_KERNEL); | ||
704 | if (!index_dir) | ||
705 | goto err; | ||
706 | |||
707 | index_dir->cache = cache; | ||
708 | |||
709 | rc = kobject_init_and_add(&index_dir->kobj, &cache_index_type, | ||
710 | cache_dir->kobj, "index%d", index); | ||
711 | if (rc) | ||
712 | goto err; | ||
713 | |||
714 | index_dir->next = cache_dir->index; | ||
715 | cache_dir->index = index_dir; | ||
716 | |||
717 | cacheinfo_create_index_opt_attrs(index_dir); | ||
718 | |||
719 | return; | ||
720 | err: | ||
721 | kfree(index_dir); | ||
722 | } | ||
723 | |||
724 | static void __cpuinit cacheinfo_sysfs_populate(unsigned int cpu_id, struct cache *cache_list) | ||
725 | { | ||
726 | struct cache_dir *cache_dir; | ||
727 | struct cache *cache; | ||
728 | int index = 0; | ||
729 | |||
730 | cache_dir = cacheinfo_create_cache_dir(cpu_id); | ||
731 | if (!cache_dir) | ||
732 | return; | ||
733 | |||
734 | cache = cache_list; | ||
735 | while (cache) { | ||
736 | cacheinfo_create_index_dir(cache, index, cache_dir); | ||
737 | index++; | ||
738 | cache = cache->next_local; | ||
739 | } | ||
740 | } | ||
741 | |||
742 | void __cpuinit cacheinfo_cpu_online(unsigned int cpu_id) | ||
743 | { | ||
744 | struct cache *cache; | ||
745 | |||
746 | cache = cache_chain_instantiate(cpu_id); | ||
747 | if (!cache) | ||
748 | return; | ||
749 | |||
750 | cacheinfo_sysfs_populate(cpu_id, cache); | ||
751 | } | ||
752 | |||
753 | #ifdef CONFIG_HOTPLUG_CPU /* functions needed for cpu offline */ | ||
754 | |||
755 | static struct cache *cache_lookup_by_cpu(unsigned int cpu_id) | ||
756 | { | ||
757 | struct device_node *cpu_node; | ||
758 | struct cache *cache; | ||
759 | |||
760 | cpu_node = of_get_cpu_node(cpu_id, NULL); | ||
761 | WARN_ONCE(!cpu_node, "no OF node found for CPU %i\n", cpu_id); | ||
762 | if (!cpu_node) | ||
763 | return NULL; | ||
764 | |||
765 | cache = cache_lookup_by_node(cpu_node); | ||
766 | of_node_put(cpu_node); | ||
767 | |||
768 | return cache; | ||
769 | } | ||
770 | |||
771 | static void remove_index_dirs(struct cache_dir *cache_dir) | ||
772 | { | ||
773 | struct cache_index_dir *index; | ||
774 | |||
775 | index = cache_dir->index; | ||
776 | |||
777 | while (index) { | ||
778 | struct cache_index_dir *next; | ||
779 | |||
780 | next = index->next; | ||
781 | kobject_put(&index->kobj); | ||
782 | index = next; | ||
783 | } | ||
784 | } | ||
785 | |||
786 | static void remove_cache_dir(struct cache_dir *cache_dir) | ||
787 | { | ||
788 | remove_index_dirs(cache_dir); | ||
789 | |||
790 | kobject_put(cache_dir->kobj); | ||
791 | |||
792 | kfree(cache_dir); | ||
793 | } | ||
794 | |||
795 | static void cache_cpu_clear(struct cache *cache, int cpu) | ||
796 | { | ||
797 | while (cache) { | ||
798 | struct cache *next = cache->next_local; | ||
799 | |||
800 | WARN_ONCE(!cpumask_test_cpu(cpu, &cache->shared_cpu_map), | ||
801 | "CPU %i not accounted in %s(%s)\n", | ||
802 | cpu, cache->ofnode->full_name, | ||
803 | cache_type_string(cache)); | ||
804 | |||
805 | cpumask_clear_cpu(cpu, &cache->shared_cpu_map); | ||
806 | |||
807 | /* Release the cache object if all the cpus using it | ||
808 | * are offline */ | ||
809 | if (cpumask_empty(&cache->shared_cpu_map)) | ||
810 | release_cache(cache); | ||
811 | |||
812 | cache = next; | ||
813 | } | ||
814 | } | ||
815 | |||
816 | void cacheinfo_cpu_offline(unsigned int cpu_id) | ||
817 | { | ||
818 | struct cache_dir *cache_dir; | ||
819 | struct cache *cache; | ||
820 | |||
821 | /* Prevent userspace from seeing inconsistent state - remove | ||
822 | * the sysfs hierarchy first */ | ||
823 | cache_dir = per_cpu(cache_dir, cpu_id); | ||
824 | |||
825 | /* careful, sysfs population may have failed */ | ||
826 | if (cache_dir) | ||
827 | remove_cache_dir(cache_dir); | ||
828 | |||
829 | per_cpu(cache_dir, cpu_id) = NULL; | ||
830 | |||
831 | /* clear the CPU's bit in its cache chain, possibly freeing | ||
832 | * cache objects */ | ||
833 | cache = cache_lookup_by_cpu(cpu_id); | ||
834 | if (cache) | ||
835 | cache_cpu_clear(cache, cpu_id); | ||
836 | } | ||
837 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
diff --git a/arch/powerpc/kernel/cacheinfo.h b/arch/powerpc/kernel/cacheinfo.h new file mode 100644 index 000000000000..a7b74d36acd7 --- /dev/null +++ b/arch/powerpc/kernel/cacheinfo.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef _PPC_CACHEINFO_H | ||
2 | #define _PPC_CACHEINFO_H | ||
3 | |||
4 | /* These are just hooks for sysfs.c to use. */ | ||
5 | extern void cacheinfo_cpu_online(unsigned int cpu_id); | ||
6 | extern void cacheinfo_cpu_offline(unsigned int cpu_id); | ||
7 | |||
8 | #endif /* _PPC_CACHEINFO_H */ | ||
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 2538030954d8..da5a3855a0c4 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
@@ -16,7 +16,7 @@ | |||
16 | * 2 of the License, or (at your option) any later version. | 16 | * 2 of the License, or (at your option) any later version. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #undef DEBUG | 19 | #define DEBUG |
20 | 20 | ||
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/pci.h> | 22 | #include <linux/pci.h> |
@@ -1356,6 +1356,63 @@ static void __init pcibios_allocate_resources(int pass) | |||
1356 | } | 1356 | } |
1357 | } | 1357 | } |
1358 | 1358 | ||
1359 | static void __init pcibios_reserve_legacy_regions(struct pci_bus *bus) | ||
1360 | { | ||
1361 | struct pci_controller *hose = pci_bus_to_host(bus); | ||
1362 | resource_size_t offset; | ||
1363 | struct resource *res, *pres; | ||
1364 | int i; | ||
1365 | |||
1366 | pr_debug("Reserving legacy ranges for domain %04x\n", pci_domain_nr(bus)); | ||
1367 | |||
1368 | /* Check for IO */ | ||
1369 | if (!(hose->io_resource.flags & IORESOURCE_IO)) | ||
1370 | goto no_io; | ||
1371 | offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
1372 | res = kzalloc(sizeof(struct resource), GFP_KERNEL); | ||
1373 | BUG_ON(res == NULL); | ||
1374 | res->name = "Legacy IO"; | ||
1375 | res->flags = IORESOURCE_IO; | ||
1376 | res->start = offset; | ||
1377 | res->end = (offset + 0xfff) & 0xfffffffful; | ||
1378 | pr_debug("Candidate legacy IO: %pR\n", res); | ||
1379 | if (request_resource(&hose->io_resource, res)) { | ||
1380 | printk(KERN_DEBUG | ||
1381 | "PCI %04x:%02x Cannot reserve Legacy IO %pR\n", | ||
1382 | pci_domain_nr(bus), bus->number, res); | ||
1383 | kfree(res); | ||
1384 | } | ||
1385 | |||
1386 | no_io: | ||
1387 | /* Check for memory */ | ||
1388 | offset = hose->pci_mem_offset; | ||
1389 | pr_debug("hose mem offset: %016llx\n", (unsigned long long)offset); | ||
1390 | for (i = 0; i < 3; i++) { | ||
1391 | pres = &hose->mem_resources[i]; | ||
1392 | if (!(pres->flags & IORESOURCE_MEM)) | ||
1393 | continue; | ||
1394 | pr_debug("hose mem res: %pR\n", pres); | ||
1395 | if ((pres->start - offset) <= 0xa0000 && | ||
1396 | (pres->end - offset) >= 0xbffff) | ||
1397 | break; | ||
1398 | } | ||
1399 | if (i >= 3) | ||
1400 | return; | ||
1401 | res = kzalloc(sizeof(struct resource), GFP_KERNEL); | ||
1402 | BUG_ON(res == NULL); | ||
1403 | res->name = "Legacy VGA memory"; | ||
1404 | res->flags = IORESOURCE_MEM; | ||
1405 | res->start = 0xa0000 + offset; | ||
1406 | res->end = 0xbffff + offset; | ||
1407 | pr_debug("Candidate VGA memory: %pR\n", res); | ||
1408 | if (request_resource(pres, res)) { | ||
1409 | printk(KERN_DEBUG | ||
1410 | "PCI %04x:%02x Cannot reserve VGA memory %pR\n", | ||
1411 | pci_domain_nr(bus), bus->number, res); | ||
1412 | kfree(res); | ||
1413 | } | ||
1414 | } | ||
1415 | |||
1359 | void __init pcibios_resource_survey(void) | 1416 | void __init pcibios_resource_survey(void) |
1360 | { | 1417 | { |
1361 | struct pci_bus *b; | 1418 | struct pci_bus *b; |
@@ -1371,6 +1428,18 @@ void __init pcibios_resource_survey(void) | |||
1371 | pcibios_allocate_resources(1); | 1428 | pcibios_allocate_resources(1); |
1372 | } | 1429 | } |
1373 | 1430 | ||
1431 | /* Before we start assigning unassigned resource, we try to reserve | ||
1432 | * the low IO area and the VGA memory area if they intersect the | ||
1433 | * bus available resources to avoid allocating things on top of them | ||
1434 | */ | ||
1435 | if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) { | ||
1436 | list_for_each_entry(b, &pci_root_buses, node) | ||
1437 | pcibios_reserve_legacy_regions(b); | ||
1438 | } | ||
1439 | |||
1440 | /* Now, if the platform didn't decide to blindly trust the firmware, | ||
1441 | * we proceed to assigning things that were left unassigned | ||
1442 | */ | ||
1374 | if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) { | 1443 | if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) { |
1375 | pr_debug("PCI: Assigning unassigned resouces...\n"); | 1444 | pr_debug("PCI: Assigning unassigned resouces...\n"); |
1376 | pci_assign_unassigned_resources(); | 1445 | pci_assign_unassigned_resources(); |
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 39fadc6e1492..586962f65c2a 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
@@ -560,9 +560,14 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus, | |||
560 | * G5 machines... So when something asks for bus 0 io base | 560 | * G5 machines... So when something asks for bus 0 io base |
561 | * (bus 0 is HT root), we return the AGP one instead. | 561 | * (bus 0 is HT root), we return the AGP one instead. |
562 | */ | 562 | */ |
563 | if (machine_is_compatible("MacRISC4")) | 563 | if (in_bus == 0 && machine_is_compatible("MacRISC4")) { |
564 | if (in_bus == 0) | 564 | struct device_node *agp; |
565 | |||
566 | agp = of_find_compatible_node(NULL, NULL, "u3-agp"); | ||
567 | if (agp) | ||
565 | in_bus = 0xf0; | 568 | in_bus = 0xf0; |
569 | of_node_put(agp); | ||
570 | } | ||
566 | 571 | ||
567 | /* That syscall isn't quite compatible with PCI domains, but it's | 572 | /* That syscall isn't quite compatible with PCI domains, but it's |
568 | * used on pre-domains setup. We return the first match | 573 | * used on pre-domains setup. We return the first match |
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index dcec1325d340..c8b27bb4dbde 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
@@ -165,6 +165,7 @@ EXPORT_SYMBOL(timer_interrupt); | |||
165 | EXPORT_SYMBOL(irq_desc); | 165 | EXPORT_SYMBOL(irq_desc); |
166 | EXPORT_SYMBOL(tb_ticks_per_jiffy); | 166 | EXPORT_SYMBOL(tb_ticks_per_jiffy); |
167 | EXPORT_SYMBOL(cacheable_memcpy); | 167 | EXPORT_SYMBOL(cacheable_memcpy); |
168 | EXPORT_SYMBOL(cacheable_memzero); | ||
168 | #endif | 169 | #endif |
169 | 170 | ||
170 | #ifdef CONFIG_PPC32 | 171 | #ifdef CONFIG_PPC32 |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 6f73c739f1e2..c09cffafb6ee 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -824,11 +824,11 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
824 | #endif | 824 | #endif |
825 | 825 | ||
826 | #ifdef CONFIG_KEXEC | 826 | #ifdef CONFIG_KEXEC |
827 | lprop = (u64*)of_get_flat_dt_prop(node, "linux,crashkernel-base", NULL); | 827 | lprop = of_get_flat_dt_prop(node, "linux,crashkernel-base", NULL); |
828 | if (lprop) | 828 | if (lprop) |
829 | crashk_res.start = *lprop; | 829 | crashk_res.start = *lprop; |
830 | 830 | ||
831 | lprop = (u64*)of_get_flat_dt_prop(node, "linux,crashkernel-size", NULL); | 831 | lprop = of_get_flat_dt_prop(node, "linux,crashkernel-size", NULL); |
832 | if (lprop) | 832 | if (lprop) |
833 | crashk_res.end = crashk_res.start + *lprop - 1; | 833 | crashk_res.end = crashk_res.start + *lprop - 1; |
834 | #endif | 834 | #endif |
@@ -893,12 +893,12 @@ static int __init early_init_dt_scan_drconf_memory(unsigned long node) | |||
893 | u64 base, size, lmb_size; | 893 | u64 base, size, lmb_size; |
894 | unsigned int is_kexec_kdump = 0, rngs; | 894 | unsigned int is_kexec_kdump = 0, rngs; |
895 | 895 | ||
896 | ls = (cell_t *)of_get_flat_dt_prop(node, "ibm,lmb-size", &l); | 896 | ls = of_get_flat_dt_prop(node, "ibm,lmb-size", &l); |
897 | if (ls == NULL || l < dt_root_size_cells * sizeof(cell_t)) | 897 | if (ls == NULL || l < dt_root_size_cells * sizeof(cell_t)) |
898 | return 0; | 898 | return 0; |
899 | lmb_size = dt_mem_next_cell(dt_root_size_cells, &ls); | 899 | lmb_size = dt_mem_next_cell(dt_root_size_cells, &ls); |
900 | 900 | ||
901 | dm = (cell_t *)of_get_flat_dt_prop(node, "ibm,dynamic-memory", &l); | 901 | dm = of_get_flat_dt_prop(node, "ibm,dynamic-memory", &l); |
902 | if (dm == NULL || l < sizeof(cell_t)) | 902 | if (dm == NULL || l < sizeof(cell_t)) |
903 | return 0; | 903 | return 0; |
904 | 904 | ||
@@ -907,7 +907,7 @@ static int __init early_init_dt_scan_drconf_memory(unsigned long node) | |||
907 | return 0; | 907 | return 0; |
908 | 908 | ||
909 | /* check if this is a kexec/kdump kernel. */ | 909 | /* check if this is a kexec/kdump kernel. */ |
910 | usm = (cell_t *)of_get_flat_dt_prop(node, "linux,drconf-usable-memory", | 910 | usm = of_get_flat_dt_prop(node, "linux,drconf-usable-memory", |
911 | &l); | 911 | &l); |
912 | if (usm != NULL) | 912 | if (usm != NULL) |
913 | is_kexec_kdump = 1; | 913 | is_kexec_kdump = 1; |
@@ -981,9 +981,9 @@ static int __init early_init_dt_scan_memory(unsigned long node, | |||
981 | } else if (strcmp(type, "memory") != 0) | 981 | } else if (strcmp(type, "memory") != 0) |
982 | return 0; | 982 | return 0; |
983 | 983 | ||
984 | reg = (cell_t *)of_get_flat_dt_prop(node, "linux,usable-memory", &l); | 984 | reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l); |
985 | if (reg == NULL) | 985 | if (reg == NULL) |
986 | reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); | 986 | reg = of_get_flat_dt_prop(node, "reg", &l); |
987 | if (reg == NULL) | 987 | if (reg == NULL) |
988 | return 0; | 988 | return 0; |
989 | 989 | ||
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 2445945d3761..7f1b33d5e30d 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -1210,7 +1210,7 @@ static void __init prom_initialize_tce_table(void) | |||
1210 | /* Initialize the table to have a one-to-one mapping | 1210 | /* Initialize the table to have a one-to-one mapping |
1211 | * over the allocated size. | 1211 | * over the allocated size. |
1212 | */ | 1212 | */ |
1213 | tce_entryp = (unsigned long *)base; | 1213 | tce_entryp = (u64 *)base; |
1214 | for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) { | 1214 | for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) { |
1215 | tce_entry = (i << PAGE_SHIFT); | 1215 | tce_entry = (i << PAGE_SHIFT); |
1216 | tce_entry |= 0x3; | 1216 | tce_entry |= 0x3; |
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 0c64f10087b9..4a2ee08af6a7 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #include <asm/machdep.h> | 18 | #include <asm/machdep.h> |
19 | #include <asm/smp.h> | 19 | #include <asm/smp.h> |
20 | 20 | ||
21 | #include "cacheinfo.h" | ||
22 | |||
21 | #ifdef CONFIG_PPC64 | 23 | #ifdef CONFIG_PPC64 |
22 | #include <asm/paca.h> | 24 | #include <asm/paca.h> |
23 | #include <asm/lppaca.h> | 25 | #include <asm/lppaca.h> |
@@ -25,8 +27,6 @@ | |||
25 | 27 | ||
26 | static DEFINE_PER_CPU(struct cpu, cpu_devices); | 28 | static DEFINE_PER_CPU(struct cpu, cpu_devices); |
27 | 29 | ||
28 | static DEFINE_PER_CPU(struct kobject *, cache_toplevel); | ||
29 | |||
30 | /* | 30 | /* |
31 | * SMT snooze delay stuff, 64-bit only for now | 31 | * SMT snooze delay stuff, 64-bit only for now |
32 | */ | 32 | */ |
@@ -343,283 +343,6 @@ static struct sysdev_attribute pa6t_attrs[] = { | |||
343 | #endif /* HAS_PPC_PMC_PA6T */ | 343 | #endif /* HAS_PPC_PMC_PA6T */ |
344 | #endif /* HAS_PPC_PMC_CLASSIC */ | 344 | #endif /* HAS_PPC_PMC_CLASSIC */ |
345 | 345 | ||
346 | struct cache_desc { | ||
347 | struct kobject kobj; | ||
348 | struct cache_desc *next; | ||
349 | const char *type; /* Instruction, Data, or Unified */ | ||
350 | u32 size; /* total cache size in KB */ | ||
351 | u32 line_size; /* in bytes */ | ||
352 | u32 nr_sets; /* number of sets */ | ||
353 | u32 level; /* e.g. 1, 2, 3... */ | ||
354 | u32 associativity; /* e.g. 8-way... 0 is fully associative */ | ||
355 | }; | ||
356 | |||
357 | DEFINE_PER_CPU(struct cache_desc *, cache_desc); | ||
358 | |||
359 | static struct cache_desc *kobj_to_cache_desc(struct kobject *k) | ||
360 | { | ||
361 | return container_of(k, struct cache_desc, kobj); | ||
362 | } | ||
363 | |||
364 | static void cache_desc_release(struct kobject *k) | ||
365 | { | ||
366 | struct cache_desc *desc = kobj_to_cache_desc(k); | ||
367 | |||
368 | pr_debug("%s: releasing %s\n", __func__, kobject_name(k)); | ||
369 | |||
370 | if (desc->next) | ||
371 | kobject_put(&desc->next->kobj); | ||
372 | |||
373 | kfree(kobj_to_cache_desc(k)); | ||
374 | } | ||
375 | |||
376 | static ssize_t cache_desc_show(struct kobject *k, struct attribute *attr, char *buf) | ||
377 | { | ||
378 | struct kobj_attribute *kobj_attr; | ||
379 | |||
380 | kobj_attr = container_of(attr, struct kobj_attribute, attr); | ||
381 | |||
382 | return kobj_attr->show(k, kobj_attr, buf); | ||
383 | } | ||
384 | |||
385 | static struct sysfs_ops cache_desc_sysfs_ops = { | ||
386 | .show = cache_desc_show, | ||
387 | }; | ||
388 | |||
389 | static struct kobj_type cache_desc_type = { | ||
390 | .release = cache_desc_release, | ||
391 | .sysfs_ops = &cache_desc_sysfs_ops, | ||
392 | }; | ||
393 | |||
394 | static ssize_t cache_size_show(struct kobject *k, struct kobj_attribute *attr, char *buf) | ||
395 | { | ||
396 | struct cache_desc *cache = kobj_to_cache_desc(k); | ||
397 | |||
398 | return sprintf(buf, "%uK\n", cache->size); | ||
399 | } | ||
400 | |||
401 | static struct kobj_attribute cache_size_attr = | ||
402 | __ATTR(size, 0444, cache_size_show, NULL); | ||
403 | |||
404 | static ssize_t cache_line_size_show(struct kobject *k, struct kobj_attribute *attr, char *buf) | ||
405 | { | ||
406 | struct cache_desc *cache = kobj_to_cache_desc(k); | ||
407 | |||
408 | return sprintf(buf, "%u\n", cache->line_size); | ||
409 | } | ||
410 | |||
411 | static struct kobj_attribute cache_line_size_attr = | ||
412 | __ATTR(coherency_line_size, 0444, cache_line_size_show, NULL); | ||
413 | |||
414 | static ssize_t cache_nr_sets_show(struct kobject *k, struct kobj_attribute *attr, char *buf) | ||
415 | { | ||
416 | struct cache_desc *cache = kobj_to_cache_desc(k); | ||
417 | |||
418 | return sprintf(buf, "%u\n", cache->nr_sets); | ||
419 | } | ||
420 | |||
421 | static struct kobj_attribute cache_nr_sets_attr = | ||
422 | __ATTR(number_of_sets, 0444, cache_nr_sets_show, NULL); | ||
423 | |||
424 | static ssize_t cache_type_show(struct kobject *k, struct kobj_attribute *attr, char *buf) | ||
425 | { | ||
426 | struct cache_desc *cache = kobj_to_cache_desc(k); | ||
427 | |||
428 | return sprintf(buf, "%s\n", cache->type); | ||
429 | } | ||
430 | |||
431 | static struct kobj_attribute cache_type_attr = | ||
432 | __ATTR(type, 0444, cache_type_show, NULL); | ||
433 | |||
434 | static ssize_t cache_level_show(struct kobject *k, struct kobj_attribute *attr, char *buf) | ||
435 | { | ||
436 | struct cache_desc *cache = kobj_to_cache_desc(k); | ||
437 | |||
438 | return sprintf(buf, "%u\n", cache->level); | ||
439 | } | ||
440 | |||
441 | static struct kobj_attribute cache_level_attr = | ||
442 | __ATTR(level, 0444, cache_level_show, NULL); | ||
443 | |||
444 | static ssize_t cache_assoc_show(struct kobject *k, struct kobj_attribute *attr, char *buf) | ||
445 | { | ||
446 | struct cache_desc *cache = kobj_to_cache_desc(k); | ||
447 | |||
448 | return sprintf(buf, "%u\n", cache->associativity); | ||
449 | } | ||
450 | |||
451 | static struct kobj_attribute cache_assoc_attr = | ||
452 | __ATTR(ways_of_associativity, 0444, cache_assoc_show, NULL); | ||
453 | |||
454 | struct cache_desc_info { | ||
455 | const char *type; | ||
456 | const char *size_prop; | ||
457 | const char *line_size_prop; | ||
458 | const char *nr_sets_prop; | ||
459 | }; | ||
460 | |||
461 | /* PowerPC Processor binding says the [di]-cache-* must be equal on | ||
462 | * unified caches, so just use d-cache properties. */ | ||
463 | static struct cache_desc_info ucache_info = { | ||
464 | .type = "Unified", | ||
465 | .size_prop = "d-cache-size", | ||
466 | .line_size_prop = "d-cache-line-size", | ||
467 | .nr_sets_prop = "d-cache-sets", | ||
468 | }; | ||
469 | |||
470 | static struct cache_desc_info dcache_info = { | ||
471 | .type = "Data", | ||
472 | .size_prop = "d-cache-size", | ||
473 | .line_size_prop = "d-cache-line-size", | ||
474 | .nr_sets_prop = "d-cache-sets", | ||
475 | }; | ||
476 | |||
477 | static struct cache_desc_info icache_info = { | ||
478 | .type = "Instruction", | ||
479 | .size_prop = "i-cache-size", | ||
480 | .line_size_prop = "i-cache-line-size", | ||
481 | .nr_sets_prop = "i-cache-sets", | ||
482 | }; | ||
483 | |||
484 | static struct cache_desc * __cpuinit create_cache_desc(struct device_node *np, struct kobject *parent, int index, int level, struct cache_desc_info *info) | ||
485 | { | ||
486 | const u32 *cache_line_size; | ||
487 | struct cache_desc *new; | ||
488 | const u32 *cache_size; | ||
489 | const u32 *nr_sets; | ||
490 | int rc; | ||
491 | |||
492 | new = kzalloc(sizeof(*new), GFP_KERNEL); | ||
493 | if (!new) | ||
494 | return NULL; | ||
495 | |||
496 | rc = kobject_init_and_add(&new->kobj, &cache_desc_type, parent, | ||
497 | "index%d", index); | ||
498 | if (rc) | ||
499 | goto err; | ||
500 | |||
501 | /* type */ | ||
502 | new->type = info->type; | ||
503 | rc = sysfs_create_file(&new->kobj, &cache_type_attr.attr); | ||
504 | WARN_ON(rc); | ||
505 | |||
506 | /* level */ | ||
507 | new->level = level; | ||
508 | rc = sysfs_create_file(&new->kobj, &cache_level_attr.attr); | ||
509 | WARN_ON(rc); | ||
510 | |||
511 | /* size */ | ||
512 | cache_size = of_get_property(np, info->size_prop, NULL); | ||
513 | if (cache_size) { | ||
514 | new->size = *cache_size / 1024; | ||
515 | rc = sysfs_create_file(&new->kobj, | ||
516 | &cache_size_attr.attr); | ||
517 | WARN_ON(rc); | ||
518 | } | ||
519 | |||
520 | /* coherency_line_size */ | ||
521 | cache_line_size = of_get_property(np, info->line_size_prop, NULL); | ||
522 | if (cache_line_size) { | ||
523 | new->line_size = *cache_line_size; | ||
524 | rc = sysfs_create_file(&new->kobj, | ||
525 | &cache_line_size_attr.attr); | ||
526 | WARN_ON(rc); | ||
527 | } | ||
528 | |||
529 | /* number_of_sets */ | ||
530 | nr_sets = of_get_property(np, info->nr_sets_prop, NULL); | ||
531 | if (nr_sets) { | ||
532 | new->nr_sets = *nr_sets; | ||
533 | rc = sysfs_create_file(&new->kobj, | ||
534 | &cache_nr_sets_attr.attr); | ||
535 | WARN_ON(rc); | ||
536 | } | ||
537 | |||
538 | /* ways_of_associativity */ | ||
539 | if (new->nr_sets == 1) { | ||
540 | /* fully associative */ | ||
541 | new->associativity = 0; | ||
542 | goto create_assoc; | ||
543 | } | ||
544 | |||
545 | if (new->nr_sets && new->size && new->line_size) { | ||
546 | /* If we have values for all of these we can derive | ||
547 | * the associativity. */ | ||
548 | new->associativity = | ||
549 | ((new->size * 1024) / new->nr_sets) / new->line_size; | ||
550 | create_assoc: | ||
551 | rc = sysfs_create_file(&new->kobj, | ||
552 | &cache_assoc_attr.attr); | ||
553 | WARN_ON(rc); | ||
554 | } | ||
555 | |||
556 | return new; | ||
557 | err: | ||
558 | kfree(new); | ||
559 | return NULL; | ||
560 | } | ||
561 | |||
562 | static bool cache_is_unified(struct device_node *np) | ||
563 | { | ||
564 | return of_get_property(np, "cache-unified", NULL); | ||
565 | } | ||
566 | |||
567 | static struct cache_desc * __cpuinit create_cache_index_info(struct device_node *np, struct kobject *parent, int index, int level) | ||
568 | { | ||
569 | struct device_node *next_cache; | ||
570 | struct cache_desc *new, **end; | ||
571 | |||
572 | pr_debug("%s(node = %s, index = %d)\n", __func__, np->full_name, index); | ||
573 | |||
574 | if (cache_is_unified(np)) { | ||
575 | new = create_cache_desc(np, parent, index, level, | ||
576 | &ucache_info); | ||
577 | } else { | ||
578 | new = create_cache_desc(np, parent, index, level, | ||
579 | &dcache_info); | ||
580 | if (new) { | ||
581 | index++; | ||
582 | new->next = create_cache_desc(np, parent, index, level, | ||
583 | &icache_info); | ||
584 | } | ||
585 | } | ||
586 | if (!new) | ||
587 | return NULL; | ||
588 | |||
589 | end = &new->next; | ||
590 | while (*end) | ||
591 | end = &(*end)->next; | ||
592 | |||
593 | next_cache = of_find_next_cache_node(np); | ||
594 | if (!next_cache) | ||
595 | goto out; | ||
596 | |||
597 | *end = create_cache_index_info(next_cache, parent, ++index, ++level); | ||
598 | |||
599 | of_node_put(next_cache); | ||
600 | out: | ||
601 | return new; | ||
602 | } | ||
603 | |||
604 | static void __cpuinit create_cache_info(struct sys_device *sysdev) | ||
605 | { | ||
606 | struct kobject *cache_toplevel; | ||
607 | struct device_node *np = NULL; | ||
608 | int cpu = sysdev->id; | ||
609 | |||
610 | cache_toplevel = kobject_create_and_add("cache", &sysdev->kobj); | ||
611 | if (!cache_toplevel) | ||
612 | return; | ||
613 | per_cpu(cache_toplevel, cpu) = cache_toplevel; | ||
614 | np = of_get_cpu_node(cpu, NULL); | ||
615 | if (np != NULL) { | ||
616 | per_cpu(cache_desc, cpu) = | ||
617 | create_cache_index_info(np, cache_toplevel, 0, 1); | ||
618 | of_node_put(np); | ||
619 | } | ||
620 | return; | ||
621 | } | ||
622 | |||
623 | static void __cpuinit register_cpu_online(unsigned int cpu) | 346 | static void __cpuinit register_cpu_online(unsigned int cpu) |
624 | { | 347 | { |
625 | struct cpu *c = &per_cpu(cpu_devices, cpu); | 348 | struct cpu *c = &per_cpu(cpu_devices, cpu); |
@@ -684,25 +407,10 @@ static void __cpuinit register_cpu_online(unsigned int cpu) | |||
684 | sysdev_create_file(s, &attr_dscr); | 407 | sysdev_create_file(s, &attr_dscr); |
685 | #endif /* CONFIG_PPC64 */ | 408 | #endif /* CONFIG_PPC64 */ |
686 | 409 | ||
687 | create_cache_info(s); | 410 | cacheinfo_cpu_online(cpu); |
688 | } | 411 | } |
689 | 412 | ||
690 | #ifdef CONFIG_HOTPLUG_CPU | 413 | #ifdef CONFIG_HOTPLUG_CPU |
691 | static void remove_cache_info(struct sys_device *sysdev) | ||
692 | { | ||
693 | struct kobject *cache_toplevel; | ||
694 | struct cache_desc *cache_desc; | ||
695 | int cpu = sysdev->id; | ||
696 | |||
697 | cache_desc = per_cpu(cache_desc, cpu); | ||
698 | if (cache_desc != NULL) | ||
699 | kobject_put(&cache_desc->kobj); | ||
700 | |||
701 | cache_toplevel = per_cpu(cache_toplevel, cpu); | ||
702 | if (cache_toplevel != NULL) | ||
703 | kobject_put(cache_toplevel); | ||
704 | } | ||
705 | |||
706 | static void unregister_cpu_online(unsigned int cpu) | 414 | static void unregister_cpu_online(unsigned int cpu) |
707 | { | 415 | { |
708 | struct cpu *c = &per_cpu(cpu_devices, cpu); | 416 | struct cpu *c = &per_cpu(cpu_devices, cpu); |
@@ -769,7 +477,7 @@ static void unregister_cpu_online(unsigned int cpu) | |||
769 | sysdev_remove_file(s, &attr_dscr); | 477 | sysdev_remove_file(s, &attr_dscr); |
770 | #endif /* CONFIG_PPC64 */ | 478 | #endif /* CONFIG_PPC64 */ |
771 | 479 | ||
772 | remove_cache_info(s); | 480 | cacheinfo_cpu_offline(cpu); |
773 | } | 481 | } |
774 | #endif /* CONFIG_HOTPLUG_CPU */ | 482 | #endif /* CONFIG_HOTPLUG_CPU */ |
775 | 483 | ||
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h index 4314b39b6faf..ad123bced404 100644 --- a/arch/powerpc/mm/mmu_decl.h +++ b/arch/powerpc/mm/mmu_decl.h | |||
@@ -30,11 +30,11 @@ | |||
30 | #if defined(CONFIG_40x) || defined(CONFIG_8xx) | 30 | #if defined(CONFIG_40x) || defined(CONFIG_8xx) |
31 | static inline void _tlbil_all(void) | 31 | static inline void _tlbil_all(void) |
32 | { | 32 | { |
33 | asm volatile ("sync; tlbia; isync" : : : "memory") | 33 | asm volatile ("sync; tlbia; isync" : : : "memory"); |
34 | } | 34 | } |
35 | static inline void _tlbil_pid(unsigned int pid) | 35 | static inline void _tlbil_pid(unsigned int pid) |
36 | { | 36 | { |
37 | asm volatile ("sync; tlbia; isync" : : : "memory") | 37 | asm volatile ("sync; tlbia; isync" : : : "memory"); |
38 | } | 38 | } |
39 | #else /* CONFIG_40x || CONFIG_8xx */ | 39 | #else /* CONFIG_40x || CONFIG_8xx */ |
40 | extern void _tlbil_all(void); | 40 | extern void _tlbil_all(void); |
@@ -47,7 +47,7 @@ extern void _tlbil_pid(unsigned int pid); | |||
47 | #ifdef CONFIG_8xx | 47 | #ifdef CONFIG_8xx |
48 | static inline void _tlbil_va(unsigned long address, unsigned int pid) | 48 | static inline void _tlbil_va(unsigned long address, unsigned int pid) |
49 | { | 49 | { |
50 | asm volatile ("tlbie %0; sync" : : "r" (address) : "memory") | 50 | asm volatile ("tlbie %0; sync" : : "r" (address) : "memory"); |
51 | } | 51 | } |
52 | #else /* CONFIG_8xx */ | 52 | #else /* CONFIG_8xx */ |
53 | extern void _tlbil_va(unsigned long address, unsigned int pid); | 53 | extern void _tlbil_va(unsigned long address, unsigned int pid); |
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index cf81049e1e51..7393bd76d698 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
@@ -822,42 +822,50 @@ static void __init dump_numa_memory_topology(void) | |||
822 | * required. nid is the preferred node and end is the physical address of | 822 | * required. nid is the preferred node and end is the physical address of |
823 | * the highest address in the node. | 823 | * the highest address in the node. |
824 | * | 824 | * |
825 | * Returns the physical address of the memory. | 825 | * Returns the virtual address of the memory. |
826 | */ | 826 | */ |
827 | static void __init *careful_allocation(int nid, unsigned long size, | 827 | static void __init *careful_zallocation(int nid, unsigned long size, |
828 | unsigned long align, | 828 | unsigned long align, |
829 | unsigned long end_pfn) | 829 | unsigned long end_pfn) |
830 | { | 830 | { |
831 | void *ret; | ||
831 | int new_nid; | 832 | int new_nid; |
832 | unsigned long ret = __lmb_alloc_base(size, align, end_pfn << PAGE_SHIFT); | 833 | unsigned long ret_paddr; |
834 | |||
835 | ret_paddr = __lmb_alloc_base(size, align, end_pfn << PAGE_SHIFT); | ||
833 | 836 | ||
834 | /* retry over all memory */ | 837 | /* retry over all memory */ |
835 | if (!ret) | 838 | if (!ret_paddr) |
836 | ret = __lmb_alloc_base(size, align, lmb_end_of_DRAM()); | 839 | ret_paddr = __lmb_alloc_base(size, align, lmb_end_of_DRAM()); |
837 | 840 | ||
838 | if (!ret) | 841 | if (!ret_paddr) |
839 | panic("numa.c: cannot allocate %lu bytes on node %d", | 842 | panic("numa.c: cannot allocate %lu bytes for node %d", |
840 | size, nid); | 843 | size, nid); |
841 | 844 | ||
845 | ret = __va(ret_paddr); | ||
846 | |||
842 | /* | 847 | /* |
843 | * If the memory came from a previously allocated node, we must | 848 | * We initialize the nodes in numeric order: 0, 1, 2... |
844 | * retry with the bootmem allocator. | 849 | * and hand over control from the LMB allocator to the |
850 | * bootmem allocator. If this function is called for | ||
851 | * node 5, then we know that all nodes <5 are using the | ||
852 | * bootmem allocator instead of the LMB allocator. | ||
853 | * | ||
854 | * So, check the nid from which this allocation came | ||
855 | * and double check to see if we need to use bootmem | ||
856 | * instead of the LMB. We don't free the LMB memory | ||
857 | * since it would be useless. | ||
845 | */ | 858 | */ |
846 | new_nid = early_pfn_to_nid(ret >> PAGE_SHIFT); | 859 | new_nid = early_pfn_to_nid(ret_paddr >> PAGE_SHIFT); |
847 | if (new_nid < nid) { | 860 | if (new_nid < nid) { |
848 | ret = (unsigned long)__alloc_bootmem_node(NODE_DATA(new_nid), | 861 | ret = __alloc_bootmem_node(NODE_DATA(new_nid), |
849 | size, align, 0); | 862 | size, align, 0); |
850 | 863 | ||
851 | if (!ret) | 864 | dbg("alloc_bootmem %p %lx\n", ret, size); |
852 | panic("numa.c: cannot allocate %lu bytes on node %d", | ||
853 | size, new_nid); | ||
854 | |||
855 | ret = __pa(ret); | ||
856 | |||
857 | dbg("alloc_bootmem %lx %lx\n", ret, size); | ||
858 | } | 865 | } |
859 | 866 | ||
860 | return (void *)ret; | 867 | memset(ret, 0, size); |
868 | return ret; | ||
861 | } | 869 | } |
862 | 870 | ||
863 | static struct notifier_block __cpuinitdata ppc64_numa_nb = { | 871 | static struct notifier_block __cpuinitdata ppc64_numa_nb = { |
@@ -952,7 +960,7 @@ void __init do_init_bootmem(void) | |||
952 | 960 | ||
953 | for_each_online_node(nid) { | 961 | for_each_online_node(nid) { |
954 | unsigned long start_pfn, end_pfn; | 962 | unsigned long start_pfn, end_pfn; |
955 | unsigned long bootmem_paddr; | 963 | void *bootmem_vaddr; |
956 | unsigned long bootmap_pages; | 964 | unsigned long bootmap_pages; |
957 | 965 | ||
958 | get_pfn_range_for_nid(nid, &start_pfn, &end_pfn); | 966 | get_pfn_range_for_nid(nid, &start_pfn, &end_pfn); |
@@ -964,11 +972,9 @@ void __init do_init_bootmem(void) | |||
964 | * previous nodes' bootmem to be initialized and have | 972 | * previous nodes' bootmem to be initialized and have |
965 | * all reserved areas marked. | 973 | * all reserved areas marked. |
966 | */ | 974 | */ |
967 | NODE_DATA(nid) = careful_allocation(nid, | 975 | NODE_DATA(nid) = careful_zallocation(nid, |
968 | sizeof(struct pglist_data), | 976 | sizeof(struct pglist_data), |
969 | SMP_CACHE_BYTES, end_pfn); | 977 | SMP_CACHE_BYTES, end_pfn); |
970 | NODE_DATA(nid) = __va(NODE_DATA(nid)); | ||
971 | memset(NODE_DATA(nid), 0, sizeof(struct pglist_data)); | ||
972 | 978 | ||
973 | dbg("node %d\n", nid); | 979 | dbg("node %d\n", nid); |
974 | dbg("NODE_DATA() = %p\n", NODE_DATA(nid)); | 980 | dbg("NODE_DATA() = %p\n", NODE_DATA(nid)); |
@@ -984,20 +990,20 @@ void __init do_init_bootmem(void) | |||
984 | dbg("end_paddr = %lx\n", end_pfn << PAGE_SHIFT); | 990 | dbg("end_paddr = %lx\n", end_pfn << PAGE_SHIFT); |
985 | 991 | ||
986 | bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); | 992 | bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); |
987 | bootmem_paddr = (unsigned long)careful_allocation(nid, | 993 | bootmem_vaddr = careful_zallocation(nid, |
988 | bootmap_pages << PAGE_SHIFT, | 994 | bootmap_pages << PAGE_SHIFT, |
989 | PAGE_SIZE, end_pfn); | 995 | PAGE_SIZE, end_pfn); |
990 | memset(__va(bootmem_paddr), 0, bootmap_pages << PAGE_SHIFT); | ||
991 | 996 | ||
992 | dbg("bootmap_paddr = %lx\n", bootmem_paddr); | 997 | dbg("bootmap_vaddr = %p\n", bootmem_vaddr); |
993 | 998 | ||
994 | init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT, | 999 | init_bootmem_node(NODE_DATA(nid), |
1000 | __pa(bootmem_vaddr) >> PAGE_SHIFT, | ||
995 | start_pfn, end_pfn); | 1001 | start_pfn, end_pfn); |
996 | 1002 | ||
997 | free_bootmem_with_active_regions(nid, end_pfn); | 1003 | free_bootmem_with_active_regions(nid, end_pfn); |
998 | /* | 1004 | /* |
999 | * Be very careful about moving this around. Future | 1005 | * Be very careful about moving this around. Future |
1000 | * calls to careful_allocation() depend on this getting | 1006 | * calls to careful_zallocation() depend on this getting |
1001 | * done correctly. | 1007 | * done correctly. |
1002 | */ | 1008 | */ |
1003 | mark_reserved_regions_for_nid(nid); | 1009 | mark_reserved_regions_for_nid(nid); |
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index 38ff35f2142a..22972cd83cc9 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c | |||
@@ -266,7 +266,8 @@ int map_page(unsigned long va, phys_addr_t pa, int flags) | |||
266 | /* The PTE should never be already set nor present in the | 266 | /* The PTE should never be already set nor present in the |
267 | * hash table | 267 | * hash table |
268 | */ | 268 | */ |
269 | BUG_ON(pte_val(*pg) & (_PAGE_PRESENT | _PAGE_HASHPTE)); | 269 | BUG_ON((pte_val(*pg) & (_PAGE_PRESENT | _PAGE_HASHPTE)) && |
270 | flags); | ||
270 | set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT, | 271 | set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT, |
271 | __pgprot(flags))); | 272 | __pgprot(flags))); |
272 | } | 273 | } |
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c index 803a64c02b06..39ac22b13c73 100644 --- a/arch/powerpc/mm/tlb_nohash.c +++ b/arch/powerpc/mm/tlb_nohash.c | |||
@@ -189,8 +189,9 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end) | |||
189 | smp_call_function(do_flush_tlb_mm_ipi, NULL, 1); | 189 | smp_call_function(do_flush_tlb_mm_ipi, NULL, 1); |
190 | _tlbil_pid(0); | 190 | _tlbil_pid(0); |
191 | preempt_enable(); | 191 | preempt_enable(); |
192 | #endif | 192 | #else |
193 | _tlbil_pid(0); | 193 | _tlbil_pid(0); |
194 | #endif | ||
194 | } | 195 | } |
195 | EXPORT_SYMBOL(flush_tlb_kernel_range); | 196 | EXPORT_SYMBOL(flush_tlb_kernel_range); |
196 | 197 | ||
diff --git a/arch/powerpc/oprofile/cell/pr_util.h b/arch/powerpc/oprofile/cell/pr_util.h index 628009c01958..964b93974d89 100644 --- a/arch/powerpc/oprofile/cell/pr_util.h +++ b/arch/powerpc/oprofile/cell/pr_util.h | |||
@@ -30,6 +30,10 @@ | |||
30 | extern struct delayed_work spu_work; | 30 | extern struct delayed_work spu_work; |
31 | extern int spu_prof_running; | 31 | extern int spu_prof_running; |
32 | 32 | ||
33 | #define TRACE_ARRAY_SIZE 1024 | ||
34 | |||
35 | extern spinlock_t oprof_spu_smpl_arry_lck; | ||
36 | |||
33 | struct spu_overlay_info { /* map of sections within an SPU overlay */ | 37 | struct spu_overlay_info { /* map of sections within an SPU overlay */ |
34 | unsigned int vma; /* SPU virtual memory address from elf */ | 38 | unsigned int vma; /* SPU virtual memory address from elf */ |
35 | unsigned int size; /* size of section from elf */ | 39 | unsigned int size; /* size of section from elf */ |
@@ -79,7 +83,7 @@ struct spu_buffer { | |||
79 | * the vma-to-fileoffset map. | 83 | * the vma-to-fileoffset map. |
80 | */ | 84 | */ |
81 | struct vma_to_fileoffset_map *create_vma_map(const struct spu *spu, | 85 | struct vma_to_fileoffset_map *create_vma_map(const struct spu *spu, |
82 | u64 objectid); | 86 | unsigned long objectid); |
83 | unsigned int vma_map_lookup(struct vma_to_fileoffset_map *map, | 87 | unsigned int vma_map_lookup(struct vma_to_fileoffset_map *map, |
84 | unsigned int vma, const struct spu *aSpu, | 88 | unsigned int vma, const struct spu *aSpu, |
85 | int *grd_val); | 89 | int *grd_val); |
@@ -89,10 +93,11 @@ void vma_map_free(struct vma_to_fileoffset_map *map); | |||
89 | * Entry point for SPU profiling. | 93 | * Entry point for SPU profiling. |
90 | * cycles_reset is the SPU_CYCLES count value specified by the user. | 94 | * cycles_reset is the SPU_CYCLES count value specified by the user. |
91 | */ | 95 | */ |
92 | int start_spu_profiling(unsigned int cycles_reset); | 96 | int start_spu_profiling_cycles(unsigned int cycles_reset); |
93 | 97 | void start_spu_profiling_events(void); | |
94 | void stop_spu_profiling(void); | ||
95 | 98 | ||
99 | void stop_spu_profiling_cycles(void); | ||
100 | void stop_spu_profiling_events(void); | ||
96 | 101 | ||
97 | /* add the necessary profiling hooks */ | 102 | /* add the necessary profiling hooks */ |
98 | int spu_sync_start(void); | 103 | int spu_sync_start(void); |
diff --git a/arch/powerpc/oprofile/cell/spu_profiler.c b/arch/powerpc/oprofile/cell/spu_profiler.c index 83faa958b9d4..9305ddaac512 100644 --- a/arch/powerpc/oprofile/cell/spu_profiler.c +++ b/arch/powerpc/oprofile/cell/spu_profiler.c | |||
@@ -18,11 +18,21 @@ | |||
18 | #include <asm/cell-pmu.h> | 18 | #include <asm/cell-pmu.h> |
19 | #include "pr_util.h" | 19 | #include "pr_util.h" |
20 | 20 | ||
21 | #define TRACE_ARRAY_SIZE 1024 | ||
22 | #define SCALE_SHIFT 14 | 21 | #define SCALE_SHIFT 14 |
23 | 22 | ||
24 | static u32 *samples; | 23 | static u32 *samples; |
25 | 24 | ||
25 | /* spu_prof_running is a flag used to indicate if spu profiling is enabled | ||
26 | * or not. It is set by the routines start_spu_profiling_cycles() and | ||
27 | * start_spu_profiling_events(). The flag is cleared by the routines | ||
28 | * stop_spu_profiling_cycles() and stop_spu_profiling_events(). These | ||
29 | * routines are called via global_start() and global_stop() which are called in | ||
30 | * op_powerpc_start() and op_powerpc_stop(). These routines are called once | ||
31 | * per system as a result of the user starting/stopping oprofile. Hence, only | ||
32 | * one CPU per user at a time will be changing the value of spu_prof_running. | ||
33 | * In general, OProfile does not protect against multiple users trying to run | ||
34 | * OProfile at a time. | ||
35 | */ | ||
26 | int spu_prof_running; | 36 | int spu_prof_running; |
27 | static unsigned int profiling_interval; | 37 | static unsigned int profiling_interval; |
28 | 38 | ||
@@ -31,8 +41,8 @@ static unsigned int profiling_interval; | |||
31 | 41 | ||
32 | #define SPU_PC_MASK 0xFFFF | 42 | #define SPU_PC_MASK 0xFFFF |
33 | 43 | ||
34 | static DEFINE_SPINLOCK(sample_array_lock); | 44 | DEFINE_SPINLOCK(oprof_spu_smpl_arry_lck); |
35 | unsigned long sample_array_lock_flags; | 45 | unsigned long oprof_spu_smpl_arry_lck_flags; |
36 | 46 | ||
37 | void set_spu_profiling_frequency(unsigned int freq_khz, unsigned int cycles_reset) | 47 | void set_spu_profiling_frequency(unsigned int freq_khz, unsigned int cycles_reset) |
38 | { | 48 | { |
@@ -145,13 +155,13 @@ static enum hrtimer_restart profile_spus(struct hrtimer *timer) | |||
145 | * sample array must be loaded and then processed for a given | 155 | * sample array must be loaded and then processed for a given |
146 | * cpu. The sample array is not per cpu. | 156 | * cpu. The sample array is not per cpu. |
147 | */ | 157 | */ |
148 | spin_lock_irqsave(&sample_array_lock, | 158 | spin_lock_irqsave(&oprof_spu_smpl_arry_lck, |
149 | sample_array_lock_flags); | 159 | oprof_spu_smpl_arry_lck_flags); |
150 | num_samples = cell_spu_pc_collection(cpu); | 160 | num_samples = cell_spu_pc_collection(cpu); |
151 | 161 | ||
152 | if (num_samples == 0) { | 162 | if (num_samples == 0) { |
153 | spin_unlock_irqrestore(&sample_array_lock, | 163 | spin_unlock_irqrestore(&oprof_spu_smpl_arry_lck, |
154 | sample_array_lock_flags); | 164 | oprof_spu_smpl_arry_lck_flags); |
155 | continue; | 165 | continue; |
156 | } | 166 | } |
157 | 167 | ||
@@ -162,8 +172,8 @@ static enum hrtimer_restart profile_spus(struct hrtimer *timer) | |||
162 | num_samples); | 172 | num_samples); |
163 | } | 173 | } |
164 | 174 | ||
165 | spin_unlock_irqrestore(&sample_array_lock, | 175 | spin_unlock_irqrestore(&oprof_spu_smpl_arry_lck, |
166 | sample_array_lock_flags); | 176 | oprof_spu_smpl_arry_lck_flags); |
167 | 177 | ||
168 | } | 178 | } |
169 | smp_wmb(); /* insure spu event buffer updates are written */ | 179 | smp_wmb(); /* insure spu event buffer updates are written */ |
@@ -182,13 +192,13 @@ static enum hrtimer_restart profile_spus(struct hrtimer *timer) | |||
182 | 192 | ||
183 | static struct hrtimer timer; | 193 | static struct hrtimer timer; |
184 | /* | 194 | /* |
185 | * Entry point for SPU profiling. | 195 | * Entry point for SPU cycle profiling. |
186 | * NOTE: SPU profiling is done system-wide, not per-CPU. | 196 | * NOTE: SPU profiling is done system-wide, not per-CPU. |
187 | * | 197 | * |
188 | * cycles_reset is the count value specified by the user when | 198 | * cycles_reset is the count value specified by the user when |
189 | * setting up OProfile to count SPU_CYCLES. | 199 | * setting up OProfile to count SPU_CYCLES. |
190 | */ | 200 | */ |
191 | int start_spu_profiling(unsigned int cycles_reset) | 201 | int start_spu_profiling_cycles(unsigned int cycles_reset) |
192 | { | 202 | { |
193 | ktime_t kt; | 203 | ktime_t kt; |
194 | 204 | ||
@@ -212,10 +222,30 @@ int start_spu_profiling(unsigned int cycles_reset) | |||
212 | return 0; | 222 | return 0; |
213 | } | 223 | } |
214 | 224 | ||
215 | void stop_spu_profiling(void) | 225 | /* |
226 | * Entry point for SPU event profiling. | ||
227 | * NOTE: SPU profiling is done system-wide, not per-CPU. | ||
228 | * | ||
229 | * cycles_reset is the count value specified by the user when | ||
230 | * setting up OProfile to count SPU_CYCLES. | ||
231 | */ | ||
232 | void start_spu_profiling_events(void) | ||
233 | { | ||
234 | spu_prof_running = 1; | ||
235 | schedule_delayed_work(&spu_work, DEFAULT_TIMER_EXPIRE); | ||
236 | |||
237 | return; | ||
238 | } | ||
239 | |||
240 | void stop_spu_profiling_cycles(void) | ||
216 | { | 241 | { |
217 | spu_prof_running = 0; | 242 | spu_prof_running = 0; |
218 | hrtimer_cancel(&timer); | 243 | hrtimer_cancel(&timer); |
219 | kfree(samples); | 244 | kfree(samples); |
220 | pr_debug("SPU_PROF: stop_spu_profiling issued\n"); | 245 | pr_debug("SPU_PROF: stop_spu_profiling_cycles issued\n"); |
246 | } | ||
247 | |||
248 | void stop_spu_profiling_events(void) | ||
249 | { | ||
250 | spu_prof_running = 0; | ||
221 | } | 251 | } |
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c index 17807acb05d9..21f16edf6c8d 100644 --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c | |||
@@ -132,6 +132,28 @@ static int op_powerpc_create_files(struct super_block *sb, struct dentry *root) | |||
132 | oprofilefs_create_ulong(sb, root, "mmcr0", &sys.mmcr0); | 132 | oprofilefs_create_ulong(sb, root, "mmcr0", &sys.mmcr0); |
133 | oprofilefs_create_ulong(sb, root, "mmcr1", &sys.mmcr1); | 133 | oprofilefs_create_ulong(sb, root, "mmcr1", &sys.mmcr1); |
134 | oprofilefs_create_ulong(sb, root, "mmcra", &sys.mmcra); | 134 | oprofilefs_create_ulong(sb, root, "mmcra", &sys.mmcra); |
135 | #ifdef CONFIG_OPROFILE_CELL | ||
136 | /* create a file the user tool can check to see what level of profiling | ||
137 | * support exits with this kernel. Initialize bit mask to indicate | ||
138 | * what support the kernel has: | ||
139 | * bit 0 - Supports SPU event profiling in addition to PPU | ||
140 | * event and cycles; and SPU cycle profiling | ||
141 | * bits 1-31 - Currently unused. | ||
142 | * | ||
143 | * If the file does not exist, then the kernel only supports SPU | ||
144 | * cycle profiling, PPU event and cycle profiling. | ||
145 | */ | ||
146 | oprofilefs_create_ulong(sb, root, "cell_support", &sys.cell_support); | ||
147 | sys.cell_support = 0x1; /* Note, the user OProfile tool must check | ||
148 | * that this bit is set before attempting to | ||
149 | * user SPU event profiling. Older kernels | ||
150 | * will not have this file, hence the user | ||
151 | * tool is not allowed to do SPU event | ||
152 | * profiling on older kernels. Older kernels | ||
153 | * will accept SPU events but collected data | ||
154 | * is garbage. | ||
155 | */ | ||
156 | #endif | ||
135 | #endif | 157 | #endif |
136 | 158 | ||
137 | for (i = 0; i < model->num_counters; ++i) { | 159 | for (i = 0; i < model->num_counters; ++i) { |
diff --git a/arch/powerpc/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c index 25a4ec2514a3..ae06c6236d9c 100644 --- a/arch/powerpc/oprofile/op_model_cell.c +++ b/arch/powerpc/oprofile/op_model_cell.c | |||
@@ -40,14 +40,15 @@ | |||
40 | #include "../platforms/cell/interrupt.h" | 40 | #include "../platforms/cell/interrupt.h" |
41 | #include "cell/pr_util.h" | 41 | #include "cell/pr_util.h" |
42 | 42 | ||
43 | static void cell_global_stop_spu(void); | 43 | #define PPU_PROFILING 0 |
44 | #define SPU_PROFILING_CYCLES 1 | ||
45 | #define SPU_PROFILING_EVENTS 2 | ||
44 | 46 | ||
45 | /* | 47 | #define SPU_EVENT_NUM_START 4100 |
46 | * spu_cycle_reset is the number of cycles between samples. | 48 | #define SPU_EVENT_NUM_STOP 4399 |
47 | * This variable is used for SPU profiling and should ONLY be set | 49 | #define SPU_PROFILE_EVENT_ADDR 4363 /* spu, address trace, decimal */ |
48 | * at the beginning of cell_reg_setup; otherwise, it's read-only. | 50 | #define SPU_PROFILE_EVENT_ADDR_MASK_A 0x146 /* sub unit set to zero */ |
49 | */ | 51 | #define SPU_PROFILE_EVENT_ADDR_MASK_B 0x186 /* sub unit set to zero */ |
50 | static unsigned int spu_cycle_reset; | ||
51 | 52 | ||
52 | #define NUM_SPUS_PER_NODE 8 | 53 | #define NUM_SPUS_PER_NODE 8 |
53 | #define SPU_CYCLES_EVENT_NUM 2 /* event number for SPU_CYCLES */ | 54 | #define SPU_CYCLES_EVENT_NUM 2 /* event number for SPU_CYCLES */ |
@@ -66,6 +67,21 @@ static unsigned int spu_cycle_reset; | |||
66 | 67 | ||
67 | #define MAX_SPU_COUNT 0xFFFFFF /* maximum 24 bit LFSR value */ | 68 | #define MAX_SPU_COUNT 0xFFFFFF /* maximum 24 bit LFSR value */ |
68 | 69 | ||
70 | /* Minumum HW interval timer setting to send value to trace buffer is 10 cycle. | ||
71 | * To configure counter to send value every N cycles set counter to | ||
72 | * 2^32 - 1 - N. | ||
73 | */ | ||
74 | #define NUM_INTERVAL_CYC 0xFFFFFFFF - 10 | ||
75 | |||
76 | /* | ||
77 | * spu_cycle_reset is the number of cycles between samples. | ||
78 | * This variable is used for SPU profiling and should ONLY be set | ||
79 | * at the beginning of cell_reg_setup; otherwise, it's read-only. | ||
80 | */ | ||
81 | static unsigned int spu_cycle_reset; | ||
82 | static unsigned int profiling_mode; | ||
83 | static int spu_evnt_phys_spu_indx; | ||
84 | |||
69 | struct pmc_cntrl_data { | 85 | struct pmc_cntrl_data { |
70 | unsigned long vcntr; | 86 | unsigned long vcntr; |
71 | unsigned long evnts; | 87 | unsigned long evnts; |
@@ -105,6 +121,8 @@ struct pm_cntrl { | |||
105 | u16 trace_mode; | 121 | u16 trace_mode; |
106 | u16 freeze; | 122 | u16 freeze; |
107 | u16 count_mode; | 123 | u16 count_mode; |
124 | u16 spu_addr_trace; | ||
125 | u8 trace_buf_ovflw; | ||
108 | }; | 126 | }; |
109 | 127 | ||
110 | static struct { | 128 | static struct { |
@@ -122,7 +140,7 @@ static struct { | |||
122 | #define GET_INPUT_CONTROL(x) ((x & 0x00000004) >> 2) | 140 | #define GET_INPUT_CONTROL(x) ((x & 0x00000004) >> 2) |
123 | 141 | ||
124 | static DEFINE_PER_CPU(unsigned long[NR_PHYS_CTRS], pmc_values); | 142 | static DEFINE_PER_CPU(unsigned long[NR_PHYS_CTRS], pmc_values); |
125 | 143 | static unsigned long spu_pm_cnt[MAX_NUMNODES * NUM_SPUS_PER_NODE]; | |
126 | static struct pmc_cntrl_data pmc_cntrl[NUM_THREADS][NR_PHYS_CTRS]; | 144 | static struct pmc_cntrl_data pmc_cntrl[NUM_THREADS][NR_PHYS_CTRS]; |
127 | 145 | ||
128 | /* | 146 | /* |
@@ -152,6 +170,7 @@ static u32 hdw_thread; | |||
152 | 170 | ||
153 | static u32 virt_cntr_inter_mask; | 171 | static u32 virt_cntr_inter_mask; |
154 | static struct timer_list timer_virt_cntr; | 172 | static struct timer_list timer_virt_cntr; |
173 | static struct timer_list timer_spu_event_swap; | ||
155 | 174 | ||
156 | /* | 175 | /* |
157 | * pm_signal needs to be global since it is initialized in | 176 | * pm_signal needs to be global since it is initialized in |
@@ -165,7 +184,7 @@ static int spu_rtas_token; /* token for SPU cycle profiling */ | |||
165 | static u32 reset_value[NR_PHYS_CTRS]; | 184 | static u32 reset_value[NR_PHYS_CTRS]; |
166 | static int num_counters; | 185 | static int num_counters; |
167 | static int oprofile_running; | 186 | static int oprofile_running; |
168 | static DEFINE_SPINLOCK(virt_cntr_lock); | 187 | static DEFINE_SPINLOCK(cntr_lock); |
169 | 188 | ||
170 | static u32 ctr_enabled; | 189 | static u32 ctr_enabled; |
171 | 190 | ||
@@ -336,13 +355,13 @@ static void set_pm_event(u32 ctr, int event, u32 unit_mask) | |||
336 | for (i = 0; i < NUM_DEBUG_BUS_WORDS; i++) { | 355 | for (i = 0; i < NUM_DEBUG_BUS_WORDS; i++) { |
337 | if (bus_word & (1 << i)) { | 356 | if (bus_word & (1 << i)) { |
338 | pm_regs.debug_bus_control |= | 357 | pm_regs.debug_bus_control |= |
339 | (bus_type << (30 - (2 * i))); | 358 | (bus_type << (30 - (2 * i))); |
340 | 359 | ||
341 | for (j = 0; j < NUM_INPUT_BUS_WORDS; j++) { | 360 | for (j = 0; j < NUM_INPUT_BUS_WORDS; j++) { |
342 | if (input_bus[j] == 0xff) { | 361 | if (input_bus[j] == 0xff) { |
343 | input_bus[j] = i; | 362 | input_bus[j] = i; |
344 | pm_regs.group_control |= | 363 | pm_regs.group_control |= |
345 | (i << (30 - (2 * j))); | 364 | (i << (30 - (2 * j))); |
346 | 365 | ||
347 | break; | 366 | break; |
348 | } | 367 | } |
@@ -367,12 +386,16 @@ static void write_pm_cntrl(int cpu) | |||
367 | if (pm_regs.pm_cntrl.stop_at_max == 1) | 386 | if (pm_regs.pm_cntrl.stop_at_max == 1) |
368 | val |= CBE_PM_STOP_AT_MAX; | 387 | val |= CBE_PM_STOP_AT_MAX; |
369 | 388 | ||
370 | if (pm_regs.pm_cntrl.trace_mode == 1) | 389 | if (pm_regs.pm_cntrl.trace_mode != 0) |
371 | val |= CBE_PM_TRACE_MODE_SET(pm_regs.pm_cntrl.trace_mode); | 390 | val |= CBE_PM_TRACE_MODE_SET(pm_regs.pm_cntrl.trace_mode); |
372 | 391 | ||
392 | if (pm_regs.pm_cntrl.trace_buf_ovflw == 1) | ||
393 | val |= CBE_PM_TRACE_BUF_OVFLW(pm_regs.pm_cntrl.trace_buf_ovflw); | ||
373 | if (pm_regs.pm_cntrl.freeze == 1) | 394 | if (pm_regs.pm_cntrl.freeze == 1) |
374 | val |= CBE_PM_FREEZE_ALL_CTRS; | 395 | val |= CBE_PM_FREEZE_ALL_CTRS; |
375 | 396 | ||
397 | val |= CBE_PM_SPU_ADDR_TRACE_SET(pm_regs.pm_cntrl.spu_addr_trace); | ||
398 | |||
376 | /* | 399 | /* |
377 | * Routine set_count_mode must be called previously to set | 400 | * Routine set_count_mode must be called previously to set |
378 | * the count mode based on the user selection of user and kernel. | 401 | * the count mode based on the user selection of user and kernel. |
@@ -441,7 +464,7 @@ static void cell_virtual_cntr(unsigned long data) | |||
441 | * not both playing with the counters on the same node. | 464 | * not both playing with the counters on the same node. |
442 | */ | 465 | */ |
443 | 466 | ||
444 | spin_lock_irqsave(&virt_cntr_lock, flags); | 467 | spin_lock_irqsave(&cntr_lock, flags); |
445 | 468 | ||
446 | prev_hdw_thread = hdw_thread; | 469 | prev_hdw_thread = hdw_thread; |
447 | 470 | ||
@@ -480,7 +503,7 @@ static void cell_virtual_cntr(unsigned long data) | |||
480 | cbe_disable_pm_interrupts(cpu); | 503 | cbe_disable_pm_interrupts(cpu); |
481 | for (i = 0; i < num_counters; i++) { | 504 | for (i = 0; i < num_counters; i++) { |
482 | per_cpu(pmc_values, cpu + prev_hdw_thread)[i] | 505 | per_cpu(pmc_values, cpu + prev_hdw_thread)[i] |
483 | = cbe_read_ctr(cpu, i); | 506 | = cbe_read_ctr(cpu, i); |
484 | 507 | ||
485 | if (per_cpu(pmc_values, cpu + next_hdw_thread)[i] | 508 | if (per_cpu(pmc_values, cpu + next_hdw_thread)[i] |
486 | == 0xFFFFFFFF) | 509 | == 0xFFFFFFFF) |
@@ -527,7 +550,7 @@ static void cell_virtual_cntr(unsigned long data) | |||
527 | cbe_enable_pm(cpu); | 550 | cbe_enable_pm(cpu); |
528 | } | 551 | } |
529 | 552 | ||
530 | spin_unlock_irqrestore(&virt_cntr_lock, flags); | 553 | spin_unlock_irqrestore(&cntr_lock, flags); |
531 | 554 | ||
532 | mod_timer(&timer_virt_cntr, jiffies + HZ / 10); | 555 | mod_timer(&timer_virt_cntr, jiffies + HZ / 10); |
533 | } | 556 | } |
@@ -541,38 +564,146 @@ static void start_virt_cntrs(void) | |||
541 | add_timer(&timer_virt_cntr); | 564 | add_timer(&timer_virt_cntr); |
542 | } | 565 | } |
543 | 566 | ||
544 | /* This function is called once for all cpus combined */ | 567 | static int cell_reg_setup_spu_cycles(struct op_counter_config *ctr, |
545 | static int cell_reg_setup(struct op_counter_config *ctr, | ||
546 | struct op_system_config *sys, int num_ctrs) | 568 | struct op_system_config *sys, int num_ctrs) |
547 | { | 569 | { |
548 | int i, j, cpu; | 570 | spu_cycle_reset = ctr[0].count; |
549 | spu_cycle_reset = 0; | ||
550 | 571 | ||
551 | if (ctr[0].event == SPU_CYCLES_EVENT_NUM) { | 572 | /* |
552 | spu_cycle_reset = ctr[0].count; | 573 | * Each node will need to make the rtas call to start |
574 | * and stop SPU profiling. Get the token once and store it. | ||
575 | */ | ||
576 | spu_rtas_token = rtas_token("ibm,cbe-spu-perftools"); | ||
577 | |||
578 | if (unlikely(spu_rtas_token == RTAS_UNKNOWN_SERVICE)) { | ||
579 | printk(KERN_ERR | ||
580 | "%s: rtas token ibm,cbe-spu-perftools unknown\n", | ||
581 | __func__); | ||
582 | return -EIO; | ||
583 | } | ||
584 | return 0; | ||
585 | } | ||
586 | |||
587 | /* Unfortunately, the hardware will only support event profiling | ||
588 | * on one SPU per node at a time. Therefore, we must time slice | ||
589 | * the profiling across all SPUs in the node. Note, we do this | ||
590 | * in parallel for each node. The following routine is called | ||
591 | * periodically based on kernel timer to switch which SPU is | ||
592 | * being monitored in a round robbin fashion. | ||
593 | */ | ||
594 | static void spu_evnt_swap(unsigned long data) | ||
595 | { | ||
596 | int node; | ||
597 | int cur_phys_spu, nxt_phys_spu, cur_spu_evnt_phys_spu_indx; | ||
598 | unsigned long flags; | ||
599 | int cpu; | ||
600 | int ret; | ||
601 | u32 interrupt_mask; | ||
602 | |||
603 | |||
604 | /* enable interrupts on cntr 0 */ | ||
605 | interrupt_mask = CBE_PM_CTR_OVERFLOW_INTR(0); | ||
606 | |||
607 | hdw_thread = 0; | ||
608 | |||
609 | /* Make sure spu event interrupt handler and spu event swap | ||
610 | * don't access the counters simultaneously. | ||
611 | */ | ||
612 | spin_lock_irqsave(&cntr_lock, flags); | ||
613 | |||
614 | cur_spu_evnt_phys_spu_indx = spu_evnt_phys_spu_indx; | ||
615 | |||
616 | if (++(spu_evnt_phys_spu_indx) == NUM_SPUS_PER_NODE) | ||
617 | spu_evnt_phys_spu_indx = 0; | ||
618 | |||
619 | pm_signal[0].sub_unit = spu_evnt_phys_spu_indx; | ||
620 | pm_signal[1].sub_unit = spu_evnt_phys_spu_indx; | ||
621 | pm_signal[2].sub_unit = spu_evnt_phys_spu_indx; | ||
622 | |||
623 | /* switch the SPU being profiled on each node */ | ||
624 | for_each_online_cpu(cpu) { | ||
625 | if (cbe_get_hw_thread_id(cpu)) | ||
626 | continue; | ||
627 | |||
628 | node = cbe_cpu_to_node(cpu); | ||
629 | cur_phys_spu = (node * NUM_SPUS_PER_NODE) | ||
630 | + cur_spu_evnt_phys_spu_indx; | ||
631 | nxt_phys_spu = (node * NUM_SPUS_PER_NODE) | ||
632 | + spu_evnt_phys_spu_indx; | ||
553 | 633 | ||
554 | /* | 634 | /* |
555 | * Each node will need to make the rtas call to start | 635 | * stop counters, save counter values, restore counts |
556 | * and stop SPU profiling. Get the token once and store it. | 636 | * for previous physical SPU |
557 | */ | 637 | */ |
558 | spu_rtas_token = rtas_token("ibm,cbe-spu-perftools"); | 638 | cbe_disable_pm(cpu); |
639 | cbe_disable_pm_interrupts(cpu); | ||
559 | 640 | ||
560 | if (unlikely(spu_rtas_token == RTAS_UNKNOWN_SERVICE)) { | 641 | spu_pm_cnt[cur_phys_spu] |
561 | printk(KERN_ERR | 642 | = cbe_read_ctr(cpu, 0); |
562 | "%s: rtas token ibm,cbe-spu-perftools unknown\n", | 643 | |
563 | __func__); | 644 | /* restore previous count for the next spu to sample */ |
564 | return -EIO; | 645 | /* NOTE, hardware issue, counter will not start if the |
565 | } | 646 | * counter value is at max (0xFFFFFFFF). |
647 | */ | ||
648 | if (spu_pm_cnt[nxt_phys_spu] >= 0xFFFFFFFF) | ||
649 | cbe_write_ctr(cpu, 0, 0xFFFFFFF0); | ||
650 | else | ||
651 | cbe_write_ctr(cpu, 0, spu_pm_cnt[nxt_phys_spu]); | ||
652 | |||
653 | pm_rtas_reset_signals(cbe_cpu_to_node(cpu)); | ||
654 | |||
655 | /* setup the debug bus measure the one event and | ||
656 | * the two events to route the next SPU's PC on | ||
657 | * the debug bus | ||
658 | */ | ||
659 | ret = pm_rtas_activate_signals(cbe_cpu_to_node(cpu), 3); | ||
660 | if (ret) | ||
661 | printk(KERN_ERR "%s: pm_rtas_activate_signals failed, " | ||
662 | "SPU event swap\n", __func__); | ||
663 | |||
664 | /* clear the trace buffer, don't want to take PC for | ||
665 | * previous SPU*/ | ||
666 | cbe_write_pm(cpu, trace_address, 0); | ||
667 | |||
668 | enable_ctr(cpu, 0, pm_regs.pm07_cntrl); | ||
669 | |||
670 | /* Enable interrupts on the CPU thread that is starting */ | ||
671 | cbe_enable_pm_interrupts(cpu, hdw_thread, | ||
672 | interrupt_mask); | ||
673 | cbe_enable_pm(cpu); | ||
566 | } | 674 | } |
567 | 675 | ||
568 | pm_rtas_token = rtas_token("ibm,cbe-perftools"); | 676 | spin_unlock_irqrestore(&cntr_lock, flags); |
569 | 677 | ||
678 | /* swap approximately every 0.1 seconds */ | ||
679 | mod_timer(&timer_spu_event_swap, jiffies + HZ / 25); | ||
680 | } | ||
681 | |||
682 | static void start_spu_event_swap(void) | ||
683 | { | ||
684 | init_timer(&timer_spu_event_swap); | ||
685 | timer_spu_event_swap.function = spu_evnt_swap; | ||
686 | timer_spu_event_swap.data = 0UL; | ||
687 | timer_spu_event_swap.expires = jiffies + HZ / 25; | ||
688 | add_timer(&timer_spu_event_swap); | ||
689 | } | ||
690 | |||
691 | static int cell_reg_setup_spu_events(struct op_counter_config *ctr, | ||
692 | struct op_system_config *sys, int num_ctrs) | ||
693 | { | ||
694 | int i; | ||
695 | |||
696 | /* routine is called once for all nodes */ | ||
697 | |||
698 | spu_evnt_phys_spu_indx = 0; | ||
570 | /* | 699 | /* |
571 | * For all events excetp PPU CYCLEs, each node will need to make | 700 | * For all events except PPU CYCLEs, each node will need to make |
572 | * the rtas cbe-perftools call to setup and reset the debug bus. | 701 | * the rtas cbe-perftools call to setup and reset the debug bus. |
573 | * Make the token lookup call once and store it in the global | 702 | * Make the token lookup call once and store it in the global |
574 | * variable pm_rtas_token. | 703 | * variable pm_rtas_token. |
575 | */ | 704 | */ |
705 | pm_rtas_token = rtas_token("ibm,cbe-perftools"); | ||
706 | |||
576 | if (unlikely(pm_rtas_token == RTAS_UNKNOWN_SERVICE)) { | 707 | if (unlikely(pm_rtas_token == RTAS_UNKNOWN_SERVICE)) { |
577 | printk(KERN_ERR | 708 | printk(KERN_ERR |
578 | "%s: rtas token ibm,cbe-perftools unknown\n", | 709 | "%s: rtas token ibm,cbe-perftools unknown\n", |
@@ -580,6 +711,58 @@ static int cell_reg_setup(struct op_counter_config *ctr, | |||
580 | return -EIO; | 711 | return -EIO; |
581 | } | 712 | } |
582 | 713 | ||
714 | /* setup the pm_control register settings, | ||
715 | * settings will be written per node by the | ||
716 | * cell_cpu_setup() function. | ||
717 | */ | ||
718 | pm_regs.pm_cntrl.trace_buf_ovflw = 1; | ||
719 | |||
720 | /* Use the occurrence trace mode to have SPU PC saved | ||
721 | * to the trace buffer. Occurrence data in trace buffer | ||
722 | * is not used. Bit 2 must be set to store SPU addresses. | ||
723 | */ | ||
724 | pm_regs.pm_cntrl.trace_mode = 2; | ||
725 | |||
726 | pm_regs.pm_cntrl.spu_addr_trace = 0x1; /* using debug bus | ||
727 | event 2 & 3 */ | ||
728 | |||
729 | /* setup the debug bus event array with the SPU PC routing events. | ||
730 | * Note, pm_signal[0] will be filled in by set_pm_event() call below. | ||
731 | */ | ||
732 | pm_signal[1].signal_group = SPU_PROFILE_EVENT_ADDR / 100; | ||
733 | pm_signal[1].bus_word = GET_BUS_WORD(SPU_PROFILE_EVENT_ADDR_MASK_A); | ||
734 | pm_signal[1].bit = SPU_PROFILE_EVENT_ADDR % 100; | ||
735 | pm_signal[1].sub_unit = spu_evnt_phys_spu_indx; | ||
736 | |||
737 | pm_signal[2].signal_group = SPU_PROFILE_EVENT_ADDR / 100; | ||
738 | pm_signal[2].bus_word = GET_BUS_WORD(SPU_PROFILE_EVENT_ADDR_MASK_B); | ||
739 | pm_signal[2].bit = SPU_PROFILE_EVENT_ADDR % 100; | ||
740 | pm_signal[2].sub_unit = spu_evnt_phys_spu_indx; | ||
741 | |||
742 | /* Set the user selected spu event to profile on, | ||
743 | * note, only one SPU profiling event is supported | ||
744 | */ | ||
745 | num_counters = 1; /* Only support one SPU event at a time */ | ||
746 | set_pm_event(0, ctr[0].event, ctr[0].unit_mask); | ||
747 | |||
748 | reset_value[0] = 0xFFFFFFFF - ctr[0].count; | ||
749 | |||
750 | /* global, used by cell_cpu_setup */ | ||
751 | ctr_enabled |= 1; | ||
752 | |||
753 | /* Initialize the count for each SPU to the reset value */ | ||
754 | for (i=0; i < MAX_NUMNODES * NUM_SPUS_PER_NODE; i++) | ||
755 | spu_pm_cnt[i] = reset_value[0]; | ||
756 | |||
757 | return 0; | ||
758 | } | ||
759 | |||
760 | static int cell_reg_setup_ppu(struct op_counter_config *ctr, | ||
761 | struct op_system_config *sys, int num_ctrs) | ||
762 | { | ||
763 | /* routine is called once for all nodes */ | ||
764 | int i, j, cpu; | ||
765 | |||
583 | num_counters = num_ctrs; | 766 | num_counters = num_ctrs; |
584 | 767 | ||
585 | if (unlikely(num_ctrs > NR_PHYS_CTRS)) { | 768 | if (unlikely(num_ctrs > NR_PHYS_CTRS)) { |
@@ -589,14 +772,6 @@ static int cell_reg_setup(struct op_counter_config *ctr, | |||
589 | __func__); | 772 | __func__); |
590 | return -EIO; | 773 | return -EIO; |
591 | } | 774 | } |
592 | pm_regs.group_control = 0; | ||
593 | pm_regs.debug_bus_control = 0; | ||
594 | |||
595 | /* setup the pm_control register */ | ||
596 | memset(&pm_regs.pm_cntrl, 0, sizeof(struct pm_cntrl)); | ||
597 | pm_regs.pm_cntrl.stop_at_max = 1; | ||
598 | pm_regs.pm_cntrl.trace_mode = 0; | ||
599 | pm_regs.pm_cntrl.freeze = 1; | ||
600 | 775 | ||
601 | set_count_mode(sys->enable_kernel, sys->enable_user); | 776 | set_count_mode(sys->enable_kernel, sys->enable_user); |
602 | 777 | ||
@@ -665,6 +840,63 @@ static int cell_reg_setup(struct op_counter_config *ctr, | |||
665 | } | 840 | } |
666 | 841 | ||
667 | 842 | ||
843 | /* This function is called once for all cpus combined */ | ||
844 | static int cell_reg_setup(struct op_counter_config *ctr, | ||
845 | struct op_system_config *sys, int num_ctrs) | ||
846 | { | ||
847 | int ret=0; | ||
848 | spu_cycle_reset = 0; | ||
849 | |||
850 | /* initialize the spu_arr_trace value, will be reset if | ||
851 | * doing spu event profiling. | ||
852 | */ | ||
853 | pm_regs.group_control = 0; | ||
854 | pm_regs.debug_bus_control = 0; | ||
855 | pm_regs.pm_cntrl.stop_at_max = 1; | ||
856 | pm_regs.pm_cntrl.trace_mode = 0; | ||
857 | pm_regs.pm_cntrl.freeze = 1; | ||
858 | pm_regs.pm_cntrl.trace_buf_ovflw = 0; | ||
859 | pm_regs.pm_cntrl.spu_addr_trace = 0; | ||
860 | |||
861 | /* | ||
862 | * For all events except PPU CYCLEs, each node will need to make | ||
863 | * the rtas cbe-perftools call to setup and reset the debug bus. | ||
864 | * Make the token lookup call once and store it in the global | ||
865 | * variable pm_rtas_token. | ||
866 | */ | ||
867 | pm_rtas_token = rtas_token("ibm,cbe-perftools"); | ||
868 | |||
869 | if (unlikely(pm_rtas_token == RTAS_UNKNOWN_SERVICE)) { | ||
870 | printk(KERN_ERR | ||
871 | "%s: rtas token ibm,cbe-perftools unknown\n", | ||
872 | __func__); | ||
873 | return -EIO; | ||
874 | } | ||
875 | |||
876 | if (ctr[0].event == SPU_CYCLES_EVENT_NUM) { | ||
877 | profiling_mode = SPU_PROFILING_CYCLES; | ||
878 | ret = cell_reg_setup_spu_cycles(ctr, sys, num_ctrs); | ||
879 | } else if ((ctr[0].event >= SPU_EVENT_NUM_START) && | ||
880 | (ctr[0].event <= SPU_EVENT_NUM_STOP)) { | ||
881 | profiling_mode = SPU_PROFILING_EVENTS; | ||
882 | spu_cycle_reset = ctr[0].count; | ||
883 | |||
884 | /* for SPU event profiling, need to setup the | ||
885 | * pm_signal array with the events to route the | ||
886 | * SPU PC before making the FW call. Note, only | ||
887 | * one SPU event for profiling can be specified | ||
888 | * at a time. | ||
889 | */ | ||
890 | cell_reg_setup_spu_events(ctr, sys, num_ctrs); | ||
891 | } else { | ||
892 | profiling_mode = PPU_PROFILING; | ||
893 | ret = cell_reg_setup_ppu(ctr, sys, num_ctrs); | ||
894 | } | ||
895 | |||
896 | return ret; | ||
897 | } | ||
898 | |||
899 | |||
668 | 900 | ||
669 | /* This function is called once for each cpu */ | 901 | /* This function is called once for each cpu */ |
670 | static int cell_cpu_setup(struct op_counter_config *cntr) | 902 | static int cell_cpu_setup(struct op_counter_config *cntr) |
@@ -672,8 +904,13 @@ static int cell_cpu_setup(struct op_counter_config *cntr) | |||
672 | u32 cpu = smp_processor_id(); | 904 | u32 cpu = smp_processor_id(); |
673 | u32 num_enabled = 0; | 905 | u32 num_enabled = 0; |
674 | int i; | 906 | int i; |
907 | int ret; | ||
675 | 908 | ||
676 | if (spu_cycle_reset) | 909 | /* Cycle based SPU profiling does not use the performance |
910 | * counters. The trace array is configured to collect | ||
911 | * the data. | ||
912 | */ | ||
913 | if (profiling_mode == SPU_PROFILING_CYCLES) | ||
677 | return 0; | 914 | return 0; |
678 | 915 | ||
679 | /* There is one performance monitor per processor chip (i.e. node), | 916 | /* There is one performance monitor per processor chip (i.e. node), |
@@ -686,7 +923,6 @@ static int cell_cpu_setup(struct op_counter_config *cntr) | |||
686 | cbe_disable_pm(cpu); | 923 | cbe_disable_pm(cpu); |
687 | cbe_disable_pm_interrupts(cpu); | 924 | cbe_disable_pm_interrupts(cpu); |
688 | 925 | ||
689 | cbe_write_pm(cpu, pm_interval, 0); | ||
690 | cbe_write_pm(cpu, pm_start_stop, 0); | 926 | cbe_write_pm(cpu, pm_start_stop, 0); |
691 | cbe_write_pm(cpu, group_control, pm_regs.group_control); | 927 | cbe_write_pm(cpu, group_control, pm_regs.group_control); |
692 | cbe_write_pm(cpu, debug_bus_control, pm_regs.debug_bus_control); | 928 | cbe_write_pm(cpu, debug_bus_control, pm_regs.debug_bus_control); |
@@ -703,7 +939,20 @@ static int cell_cpu_setup(struct op_counter_config *cntr) | |||
703 | * The pm_rtas_activate_signals will return -EIO if the FW | 939 | * The pm_rtas_activate_signals will return -EIO if the FW |
704 | * call failed. | 940 | * call failed. |
705 | */ | 941 | */ |
706 | return pm_rtas_activate_signals(cbe_cpu_to_node(cpu), num_enabled); | 942 | if (profiling_mode == SPU_PROFILING_EVENTS) { |
943 | /* For SPU event profiling also need to setup the | ||
944 | * pm interval timer | ||
945 | */ | ||
946 | ret = pm_rtas_activate_signals(cbe_cpu_to_node(cpu), | ||
947 | num_enabled+2); | ||
948 | /* store PC from debug bus to Trace buffer as often | ||
949 | * as possible (every 10 cycles) | ||
950 | */ | ||
951 | cbe_write_pm(cpu, pm_interval, NUM_INTERVAL_CYC); | ||
952 | return ret; | ||
953 | } else | ||
954 | return pm_rtas_activate_signals(cbe_cpu_to_node(cpu), | ||
955 | num_enabled); | ||
707 | } | 956 | } |
708 | 957 | ||
709 | #define ENTRIES 303 | 958 | #define ENTRIES 303 |
@@ -885,7 +1134,122 @@ static struct notifier_block cpu_freq_notifier_block = { | |||
885 | }; | 1134 | }; |
886 | #endif | 1135 | #endif |
887 | 1136 | ||
888 | static int cell_global_start_spu(struct op_counter_config *ctr) | 1137 | /* |
1138 | * Note the generic OProfile stop calls do not support returning | ||
1139 | * an error on stop. Hence, will not return an error if the FW | ||
1140 | * calls fail on stop. Failure to reset the debug bus is not an issue. | ||
1141 | * Failure to disable the SPU profiling is not an issue. The FW calls | ||
1142 | * to enable the performance counters and debug bus will work even if | ||
1143 | * the hardware was not cleanly reset. | ||
1144 | */ | ||
1145 | static void cell_global_stop_spu_cycles(void) | ||
1146 | { | ||
1147 | int subfunc, rtn_value; | ||
1148 | unsigned int lfsr_value; | ||
1149 | int cpu; | ||
1150 | |||
1151 | oprofile_running = 0; | ||
1152 | smp_wmb(); | ||
1153 | |||
1154 | #ifdef CONFIG_CPU_FREQ | ||
1155 | cpufreq_unregister_notifier(&cpu_freq_notifier_block, | ||
1156 | CPUFREQ_TRANSITION_NOTIFIER); | ||
1157 | #endif | ||
1158 | |||
1159 | for_each_online_cpu(cpu) { | ||
1160 | if (cbe_get_hw_thread_id(cpu)) | ||
1161 | continue; | ||
1162 | |||
1163 | subfunc = 3; /* | ||
1164 | * 2 - activate SPU tracing, | ||
1165 | * 3 - deactivate | ||
1166 | */ | ||
1167 | lfsr_value = 0x8f100000; | ||
1168 | |||
1169 | rtn_value = rtas_call(spu_rtas_token, 3, 1, NULL, | ||
1170 | subfunc, cbe_cpu_to_node(cpu), | ||
1171 | lfsr_value); | ||
1172 | |||
1173 | if (unlikely(rtn_value != 0)) { | ||
1174 | printk(KERN_ERR | ||
1175 | "%s: rtas call ibm,cbe-spu-perftools " \ | ||
1176 | "failed, return = %d\n", | ||
1177 | __func__, rtn_value); | ||
1178 | } | ||
1179 | |||
1180 | /* Deactivate the signals */ | ||
1181 | pm_rtas_reset_signals(cbe_cpu_to_node(cpu)); | ||
1182 | } | ||
1183 | |||
1184 | stop_spu_profiling_cycles(); | ||
1185 | } | ||
1186 | |||
1187 | static void cell_global_stop_spu_events(void) | ||
1188 | { | ||
1189 | int cpu; | ||
1190 | oprofile_running = 0; | ||
1191 | |||
1192 | stop_spu_profiling_events(); | ||
1193 | smp_wmb(); | ||
1194 | |||
1195 | for_each_online_cpu(cpu) { | ||
1196 | if (cbe_get_hw_thread_id(cpu)) | ||
1197 | continue; | ||
1198 | |||
1199 | cbe_sync_irq(cbe_cpu_to_node(cpu)); | ||
1200 | /* Stop the counters */ | ||
1201 | cbe_disable_pm(cpu); | ||
1202 | cbe_write_pm07_control(cpu, 0, 0); | ||
1203 | |||
1204 | /* Deactivate the signals */ | ||
1205 | pm_rtas_reset_signals(cbe_cpu_to_node(cpu)); | ||
1206 | |||
1207 | /* Deactivate interrupts */ | ||
1208 | cbe_disable_pm_interrupts(cpu); | ||
1209 | } | ||
1210 | del_timer_sync(&timer_spu_event_swap); | ||
1211 | } | ||
1212 | |||
1213 | static void cell_global_stop_ppu(void) | ||
1214 | { | ||
1215 | int cpu; | ||
1216 | |||
1217 | /* | ||
1218 | * This routine will be called once for the system. | ||
1219 | * There is one performance monitor per node, so we | ||
1220 | * only need to perform this function once per node. | ||
1221 | */ | ||
1222 | del_timer_sync(&timer_virt_cntr); | ||
1223 | oprofile_running = 0; | ||
1224 | smp_wmb(); | ||
1225 | |||
1226 | for_each_online_cpu(cpu) { | ||
1227 | if (cbe_get_hw_thread_id(cpu)) | ||
1228 | continue; | ||
1229 | |||
1230 | cbe_sync_irq(cbe_cpu_to_node(cpu)); | ||
1231 | /* Stop the counters */ | ||
1232 | cbe_disable_pm(cpu); | ||
1233 | |||
1234 | /* Deactivate the signals */ | ||
1235 | pm_rtas_reset_signals(cbe_cpu_to_node(cpu)); | ||
1236 | |||
1237 | /* Deactivate interrupts */ | ||
1238 | cbe_disable_pm_interrupts(cpu); | ||
1239 | } | ||
1240 | } | ||
1241 | |||
1242 | static void cell_global_stop(void) | ||
1243 | { | ||
1244 | if (profiling_mode == PPU_PROFILING) | ||
1245 | cell_global_stop_ppu(); | ||
1246 | else if (profiling_mode == SPU_PROFILING_EVENTS) | ||
1247 | cell_global_stop_spu_events(); | ||
1248 | else | ||
1249 | cell_global_stop_spu_cycles(); | ||
1250 | } | ||
1251 | |||
1252 | static int cell_global_start_spu_cycles(struct op_counter_config *ctr) | ||
889 | { | 1253 | { |
890 | int subfunc; | 1254 | int subfunc; |
891 | unsigned int lfsr_value; | 1255 | unsigned int lfsr_value; |
@@ -951,18 +1315,18 @@ static int cell_global_start_spu(struct op_counter_config *ctr) | |||
951 | 1315 | ||
952 | /* start profiling */ | 1316 | /* start profiling */ |
953 | ret = rtas_call(spu_rtas_token, 3, 1, NULL, subfunc, | 1317 | ret = rtas_call(spu_rtas_token, 3, 1, NULL, subfunc, |
954 | cbe_cpu_to_node(cpu), lfsr_value); | 1318 | cbe_cpu_to_node(cpu), lfsr_value); |
955 | 1319 | ||
956 | if (unlikely(ret != 0)) { | 1320 | if (unlikely(ret != 0)) { |
957 | printk(KERN_ERR | 1321 | printk(KERN_ERR |
958 | "%s: rtas call ibm,cbe-spu-perftools failed, return = %d\n", | 1322 | "%s: rtas call ibm,cbe-spu-perftools failed, " \ |
959 | __func__, ret); | 1323 | "return = %d\n", __func__, ret); |
960 | rtas_error = -EIO; | 1324 | rtas_error = -EIO; |
961 | goto out; | 1325 | goto out; |
962 | } | 1326 | } |
963 | } | 1327 | } |
964 | 1328 | ||
965 | rtas_error = start_spu_profiling(spu_cycle_reset); | 1329 | rtas_error = start_spu_profiling_cycles(spu_cycle_reset); |
966 | if (rtas_error) | 1330 | if (rtas_error) |
967 | goto out_stop; | 1331 | goto out_stop; |
968 | 1332 | ||
@@ -970,11 +1334,74 @@ static int cell_global_start_spu(struct op_counter_config *ctr) | |||
970 | return 0; | 1334 | return 0; |
971 | 1335 | ||
972 | out_stop: | 1336 | out_stop: |
973 | cell_global_stop_spu(); /* clean up the PMU/debug bus */ | 1337 | cell_global_stop_spu_cycles(); /* clean up the PMU/debug bus */ |
974 | out: | 1338 | out: |
975 | return rtas_error; | 1339 | return rtas_error; |
976 | } | 1340 | } |
977 | 1341 | ||
1342 | static int cell_global_start_spu_events(struct op_counter_config *ctr) | ||
1343 | { | ||
1344 | int cpu; | ||
1345 | u32 interrupt_mask = 0; | ||
1346 | int rtn = 0; | ||
1347 | |||
1348 | hdw_thread = 0; | ||
1349 | |||
1350 | /* spu event profiling, uses the performance counters to generate | ||
1351 | * an interrupt. The hardware is setup to store the SPU program | ||
1352 | * counter into the trace array. The occurrence mode is used to | ||
1353 | * enable storing data to the trace buffer. The bits are set | ||
1354 | * to send/store the SPU address in the trace buffer. The debug | ||
1355 | * bus must be setup to route the SPU program counter onto the | ||
1356 | * debug bus. The occurrence data in the trace buffer is not used. | ||
1357 | */ | ||
1358 | |||
1359 | /* This routine gets called once for the system. | ||
1360 | * There is one performance monitor per node, so we | ||
1361 | * only need to perform this function once per node. | ||
1362 | */ | ||
1363 | |||
1364 | for_each_online_cpu(cpu) { | ||
1365 | if (cbe_get_hw_thread_id(cpu)) | ||
1366 | continue; | ||
1367 | |||
1368 | /* | ||
1369 | * Setup SPU event-based profiling. | ||
1370 | * Set perf_mon_control bit 0 to a zero before | ||
1371 | * enabling spu collection hardware. | ||
1372 | * | ||
1373 | * Only support one SPU event on one SPU per node. | ||
1374 | */ | ||
1375 | if (ctr_enabled & 1) { | ||
1376 | cbe_write_ctr(cpu, 0, reset_value[0]); | ||
1377 | enable_ctr(cpu, 0, pm_regs.pm07_cntrl); | ||
1378 | interrupt_mask |= | ||
1379 | CBE_PM_CTR_OVERFLOW_INTR(0); | ||
1380 | } else { | ||
1381 | /* Disable counter */ | ||
1382 | cbe_write_pm07_control(cpu, 0, 0); | ||
1383 | } | ||
1384 | |||
1385 | cbe_get_and_clear_pm_interrupts(cpu); | ||
1386 | cbe_enable_pm_interrupts(cpu, hdw_thread, interrupt_mask); | ||
1387 | cbe_enable_pm(cpu); | ||
1388 | |||
1389 | /* clear the trace buffer */ | ||
1390 | cbe_write_pm(cpu, trace_address, 0); | ||
1391 | } | ||
1392 | |||
1393 | /* Start the timer to time slice collecting the event profile | ||
1394 | * on each of the SPUs. Note, can collect profile on one SPU | ||
1395 | * per node at a time. | ||
1396 | */ | ||
1397 | start_spu_event_swap(); | ||
1398 | start_spu_profiling_events(); | ||
1399 | oprofile_running = 1; | ||
1400 | smp_wmb(); | ||
1401 | |||
1402 | return rtn; | ||
1403 | } | ||
1404 | |||
978 | static int cell_global_start_ppu(struct op_counter_config *ctr) | 1405 | static int cell_global_start_ppu(struct op_counter_config *ctr) |
979 | { | 1406 | { |
980 | u32 cpu, i; | 1407 | u32 cpu, i; |
@@ -994,8 +1421,7 @@ static int cell_global_start_ppu(struct op_counter_config *ctr) | |||
994 | if (ctr_enabled & (1 << i)) { | 1421 | if (ctr_enabled & (1 << i)) { |
995 | cbe_write_ctr(cpu, i, reset_value[i]); | 1422 | cbe_write_ctr(cpu, i, reset_value[i]); |
996 | enable_ctr(cpu, i, pm_regs.pm07_cntrl); | 1423 | enable_ctr(cpu, i, pm_regs.pm07_cntrl); |
997 | interrupt_mask |= | 1424 | interrupt_mask |= CBE_PM_CTR_OVERFLOW_INTR(i); |
998 | CBE_PM_CTR_OVERFLOW_INTR(i); | ||
999 | } else { | 1425 | } else { |
1000 | /* Disable counter */ | 1426 | /* Disable counter */ |
1001 | cbe_write_pm07_control(cpu, i, 0); | 1427 | cbe_write_pm07_control(cpu, i, 0); |
@@ -1024,99 +1450,162 @@ static int cell_global_start_ppu(struct op_counter_config *ctr) | |||
1024 | 1450 | ||
1025 | static int cell_global_start(struct op_counter_config *ctr) | 1451 | static int cell_global_start(struct op_counter_config *ctr) |
1026 | { | 1452 | { |
1027 | if (spu_cycle_reset) | 1453 | if (profiling_mode == SPU_PROFILING_CYCLES) |
1028 | return cell_global_start_spu(ctr); | 1454 | return cell_global_start_spu_cycles(ctr); |
1455 | else if (profiling_mode == SPU_PROFILING_EVENTS) | ||
1456 | return cell_global_start_spu_events(ctr); | ||
1029 | else | 1457 | else |
1030 | return cell_global_start_ppu(ctr); | 1458 | return cell_global_start_ppu(ctr); |
1031 | } | 1459 | } |
1032 | 1460 | ||
1033 | /* | 1461 | |
1034 | * Note the generic OProfile stop calls do not support returning | 1462 | /* The SPU interrupt handler |
1035 | * an error on stop. Hence, will not return an error if the FW | 1463 | * |
1036 | * calls fail on stop. Failure to reset the debug bus is not an issue. | 1464 | * SPU event profiling works as follows: |
1037 | * Failure to disable the SPU profiling is not an issue. The FW calls | 1465 | * The pm_signal[0] holds the one SPU event to be measured. It is routed on |
1038 | * to enable the performance counters and debug bus will work even if | 1466 | * the debug bus using word 0 or 1. The value of pm_signal[1] and |
1039 | * the hardware was not cleanly reset. | 1467 | * pm_signal[2] contain the necessary events to route the SPU program |
1468 | * counter for the selected SPU onto the debug bus using words 2 and 3. | ||
1469 | * The pm_interval register is setup to write the SPU PC value into the | ||
1470 | * trace buffer at the maximum rate possible. The trace buffer is configured | ||
1471 | * to store the PCs, wrapping when it is full. The performance counter is | ||
1472 | * intialized to the max hardware count minus the number of events, N, between | ||
1473 | * samples. Once the N events have occured, a HW counter overflow occurs | ||
1474 | * causing the generation of a HW counter interrupt which also stops the | ||
1475 | * writing of the SPU PC values to the trace buffer. Hence the last PC | ||
1476 | * written to the trace buffer is the SPU PC that we want. Unfortunately, | ||
1477 | * we have to read from the beginning of the trace buffer to get to the | ||
1478 | * last value written. We just hope the PPU has nothing better to do then | ||
1479 | * service this interrupt. The PC for the specific SPU being profiled is | ||
1480 | * extracted from the trace buffer processed and stored. The trace buffer | ||
1481 | * is cleared, interrupts are cleared, the counter is reset to max - N. | ||
1482 | * A kernel timer is used to periodically call the routine spu_evnt_swap() | ||
1483 | * to switch to the next physical SPU in the node to profile in round robbin | ||
1484 | * order. This way data is collected for all SPUs on the node. It does mean | ||
1485 | * that we need to use a relatively small value of N to ensure enough samples | ||
1486 | * on each SPU are collected each SPU is being profiled 1/8 of the time. | ||
1487 | * It may also be necessary to use a longer sample collection period. | ||
1040 | */ | 1488 | */ |
1041 | static void cell_global_stop_spu(void) | 1489 | static void cell_handle_interrupt_spu(struct pt_regs *regs, |
1490 | struct op_counter_config *ctr) | ||
1042 | { | 1491 | { |
1043 | int subfunc, rtn_value; | 1492 | u32 cpu, cpu_tmp; |
1044 | unsigned int lfsr_value; | 1493 | u64 trace_entry; |
1045 | int cpu; | 1494 | u32 interrupt_mask; |
1495 | u64 trace_buffer[2]; | ||
1496 | u64 last_trace_buffer; | ||
1497 | u32 sample; | ||
1498 | u32 trace_addr; | ||
1499 | unsigned long sample_array_lock_flags; | ||
1500 | int spu_num; | ||
1501 | unsigned long flags; | ||
1046 | 1502 | ||
1047 | oprofile_running = 0; | 1503 | /* Make sure spu event interrupt handler and spu event swap |
1504 | * don't access the counters simultaneously. | ||
1505 | */ | ||
1506 | cpu = smp_processor_id(); | ||
1507 | spin_lock_irqsave(&cntr_lock, flags); | ||
1048 | 1508 | ||
1049 | #ifdef CONFIG_CPU_FREQ | 1509 | cpu_tmp = cpu; |
1050 | cpufreq_unregister_notifier(&cpu_freq_notifier_block, | 1510 | cbe_disable_pm(cpu); |
1051 | CPUFREQ_TRANSITION_NOTIFIER); | ||
1052 | #endif | ||
1053 | 1511 | ||
1054 | for_each_online_cpu(cpu) { | 1512 | interrupt_mask = cbe_get_and_clear_pm_interrupts(cpu); |
1055 | if (cbe_get_hw_thread_id(cpu)) | ||
1056 | continue; | ||
1057 | 1513 | ||
1058 | subfunc = 3; /* | 1514 | sample = 0xABCDEF; |
1059 | * 2 - activate SPU tracing, | 1515 | trace_entry = 0xfedcba; |
1060 | * 3 - deactivate | 1516 | last_trace_buffer = 0xdeadbeaf; |
1061 | */ | ||
1062 | lfsr_value = 0x8f100000; | ||
1063 | 1517 | ||
1064 | rtn_value = rtas_call(spu_rtas_token, 3, 1, NULL, | 1518 | if ((oprofile_running == 1) && (interrupt_mask != 0)) { |
1065 | subfunc, cbe_cpu_to_node(cpu), | 1519 | /* disable writes to trace buff */ |
1066 | lfsr_value); | 1520 | cbe_write_pm(cpu, pm_interval, 0); |
1067 | 1521 | ||
1068 | if (unlikely(rtn_value != 0)) { | 1522 | /* only have one perf cntr being used, cntr 0 */ |
1069 | printk(KERN_ERR | 1523 | if ((interrupt_mask & CBE_PM_CTR_OVERFLOW_INTR(0)) |
1070 | "%s: rtas call ibm,cbe-spu-perftools failed, return = %d\n", | 1524 | && ctr[0].enabled) |
1071 | __func__, rtn_value); | 1525 | /* The SPU PC values will be read |
1526 | * from the trace buffer, reset counter | ||
1527 | */ | ||
1528 | |||
1529 | cbe_write_ctr(cpu, 0, reset_value[0]); | ||
1530 | |||
1531 | trace_addr = cbe_read_pm(cpu, trace_address); | ||
1532 | |||
1533 | while (!(trace_addr & CBE_PM_TRACE_BUF_EMPTY)) { | ||
1534 | /* There is data in the trace buffer to process | ||
1535 | * Read the buffer until you get to the last | ||
1536 | * entry. This is the value we want. | ||
1537 | */ | ||
1538 | |||
1539 | cbe_read_trace_buffer(cpu, trace_buffer); | ||
1540 | trace_addr = cbe_read_pm(cpu, trace_address); | ||
1072 | } | 1541 | } |
1073 | 1542 | ||
1074 | /* Deactivate the signals */ | 1543 | /* SPU Address 16 bit count format for 128 bit |
1075 | pm_rtas_reset_signals(cbe_cpu_to_node(cpu)); | 1544 | * HW trace buffer is used for the SPU PC storage |
1076 | } | 1545 | * HDR bits 0:15 |
1546 | * SPU Addr 0 bits 16:31 | ||
1547 | * SPU Addr 1 bits 32:47 | ||
1548 | * unused bits 48:127 | ||
1549 | * | ||
1550 | * HDR: bit4 = 1 SPU Address 0 valid | ||
1551 | * HDR: bit5 = 1 SPU Address 1 valid | ||
1552 | * - unfortunately, the valid bits don't seem to work | ||
1553 | * | ||
1554 | * Note trace_buffer[0] holds bits 0:63 of the HW | ||
1555 | * trace buffer, trace_buffer[1] holds bits 64:127 | ||
1556 | */ | ||
1077 | 1557 | ||
1078 | stop_spu_profiling(); | 1558 | trace_entry = trace_buffer[0] |
1079 | } | 1559 | & 0x00000000FFFF0000; |
1080 | 1560 | ||
1081 | static void cell_global_stop_ppu(void) | 1561 | /* only top 16 of the 18 bit SPU PC address |
1082 | { | 1562 | * is stored in trace buffer, hence shift right |
1083 | int cpu; | 1563 | * by 16 -2 bits */ |
1564 | sample = trace_entry >> 14; | ||
1565 | last_trace_buffer = trace_buffer[0]; | ||
1084 | 1566 | ||
1085 | /* | 1567 | spu_num = spu_evnt_phys_spu_indx |
1086 | * This routine will be called once for the system. | 1568 | + (cbe_cpu_to_node(cpu) * NUM_SPUS_PER_NODE); |
1087 | * There is one performance monitor per node, so we | ||
1088 | * only need to perform this function once per node. | ||
1089 | */ | ||
1090 | del_timer_sync(&timer_virt_cntr); | ||
1091 | oprofile_running = 0; | ||
1092 | smp_wmb(); | ||
1093 | 1569 | ||
1094 | for_each_online_cpu(cpu) { | 1570 | /* make sure only one process at a time is calling |
1095 | if (cbe_get_hw_thread_id(cpu)) | 1571 | * spu_sync_buffer() |
1096 | continue; | 1572 | */ |
1573 | spin_lock_irqsave(&oprof_spu_smpl_arry_lck, | ||
1574 | sample_array_lock_flags); | ||
1575 | spu_sync_buffer(spu_num, &sample, 1); | ||
1576 | spin_unlock_irqrestore(&oprof_spu_smpl_arry_lck, | ||
1577 | sample_array_lock_flags); | ||
1097 | 1578 | ||
1098 | cbe_sync_irq(cbe_cpu_to_node(cpu)); | 1579 | smp_wmb(); /* insure spu event buffer updates are written |
1099 | /* Stop the counters */ | 1580 | * don't want events intermingled... */ |
1100 | cbe_disable_pm(cpu); | ||
1101 | 1581 | ||
1102 | /* Deactivate the signals */ | 1582 | /* The counters were frozen by the interrupt. |
1103 | pm_rtas_reset_signals(cbe_cpu_to_node(cpu)); | 1583 | * Reenable the interrupt and restart the counters. |
1584 | */ | ||
1585 | cbe_write_pm(cpu, pm_interval, NUM_INTERVAL_CYC); | ||
1586 | cbe_enable_pm_interrupts(cpu, hdw_thread, | ||
1587 | virt_cntr_inter_mask); | ||
1104 | 1588 | ||
1105 | /* Deactivate interrupts */ | 1589 | /* clear the trace buffer, re-enable writes to trace buff */ |
1106 | cbe_disable_pm_interrupts(cpu); | 1590 | cbe_write_pm(cpu, trace_address, 0); |
1107 | } | 1591 | cbe_write_pm(cpu, pm_interval, NUM_INTERVAL_CYC); |
1108 | } | ||
1109 | 1592 | ||
1110 | static void cell_global_stop(void) | 1593 | /* The writes to the various performance counters only writes |
1111 | { | 1594 | * to a latch. The new values (interrupt setting bits, reset |
1112 | if (spu_cycle_reset) | 1595 | * counter value etc.) are not copied to the actual registers |
1113 | cell_global_stop_spu(); | 1596 | * until the performance monitor is enabled. In order to get |
1114 | else | 1597 | * this to work as desired, the permormance monitor needs to |
1115 | cell_global_stop_ppu(); | 1598 | * be disabled while writing to the latches. This is a |
1599 | * HW design issue. | ||
1600 | */ | ||
1601 | write_pm_cntrl(cpu); | ||
1602 | cbe_enable_pm(cpu); | ||
1603 | } | ||
1604 | spin_unlock_irqrestore(&cntr_lock, flags); | ||
1116 | } | 1605 | } |
1117 | 1606 | ||
1118 | static void cell_handle_interrupt(struct pt_regs *regs, | 1607 | static void cell_handle_interrupt_ppu(struct pt_regs *regs, |
1119 | struct op_counter_config *ctr) | 1608 | struct op_counter_config *ctr) |
1120 | { | 1609 | { |
1121 | u32 cpu; | 1610 | u32 cpu; |
1122 | u64 pc; | 1611 | u64 pc; |
@@ -1132,7 +1621,7 @@ static void cell_handle_interrupt(struct pt_regs *regs, | |||
1132 | * routine are not running at the same time. See the | 1621 | * routine are not running at the same time. See the |
1133 | * cell_virtual_cntr() routine for additional comments. | 1622 | * cell_virtual_cntr() routine for additional comments. |
1134 | */ | 1623 | */ |
1135 | spin_lock_irqsave(&virt_cntr_lock, flags); | 1624 | spin_lock_irqsave(&cntr_lock, flags); |
1136 | 1625 | ||
1137 | /* | 1626 | /* |
1138 | * Need to disable and reenable the performance counters | 1627 | * Need to disable and reenable the performance counters |
@@ -1185,7 +1674,16 @@ static void cell_handle_interrupt(struct pt_regs *regs, | |||
1185 | */ | 1674 | */ |
1186 | cbe_enable_pm(cpu); | 1675 | cbe_enable_pm(cpu); |
1187 | } | 1676 | } |
1188 | spin_unlock_irqrestore(&virt_cntr_lock, flags); | 1677 | spin_unlock_irqrestore(&cntr_lock, flags); |
1678 | } | ||
1679 | |||
1680 | static void cell_handle_interrupt(struct pt_regs *regs, | ||
1681 | struct op_counter_config *ctr) | ||
1682 | { | ||
1683 | if (profiling_mode == PPU_PROFILING) | ||
1684 | cell_handle_interrupt_ppu(regs, ctr); | ||
1685 | else | ||
1686 | cell_handle_interrupt_spu(regs, ctr); | ||
1189 | } | 1687 | } |
1190 | 1688 | ||
1191 | /* | 1689 | /* |
@@ -1195,7 +1693,8 @@ static void cell_handle_interrupt(struct pt_regs *regs, | |||
1195 | */ | 1693 | */ |
1196 | static int cell_sync_start(void) | 1694 | static int cell_sync_start(void) |
1197 | { | 1695 | { |
1198 | if (spu_cycle_reset) | 1696 | if ((profiling_mode == SPU_PROFILING_CYCLES) || |
1697 | (profiling_mode == SPU_PROFILING_EVENTS)) | ||
1199 | return spu_sync_start(); | 1698 | return spu_sync_start(); |
1200 | else | 1699 | else |
1201 | return DO_GENERIC_SYNC; | 1700 | return DO_GENERIC_SYNC; |
@@ -1203,7 +1702,8 @@ static int cell_sync_start(void) | |||
1203 | 1702 | ||
1204 | static int cell_sync_stop(void) | 1703 | static int cell_sync_stop(void) |
1205 | { | 1704 | { |
1206 | if (spu_cycle_reset) | 1705 | if ((profiling_mode == SPU_PROFILING_CYCLES) || |
1706 | (profiling_mode == SPU_PROFILING_EVENTS)) | ||
1207 | return spu_sync_stop(); | 1707 | return spu_sync_stop(); |
1208 | else | 1708 | else |
1209 | return 1; | 1709 | return 1; |
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c index ae7c34f37e1c..98367a0255f3 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_common.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c | |||
@@ -42,7 +42,7 @@ static struct of_device_id mpc52xx_bus_ids[] __initdata = { | |||
42 | * from interrupt context while node mapping (which calls ioremap()) | 42 | * from interrupt context while node mapping (which calls ioremap()) |
43 | * cannot be used at such point. | 43 | * cannot be used at such point. |
44 | */ | 44 | */ |
45 | static spinlock_t mpc52xx_lock = SPIN_LOCK_UNLOCKED; | 45 | static DEFINE_SPINLOCK(mpc52xx_lock); |
46 | static struct mpc52xx_gpt __iomem *mpc52xx_wdt; | 46 | static struct mpc52xx_gpt __iomem *mpc52xx_wdt; |
47 | static struct mpc52xx_cdm __iomem *mpc52xx_cdm; | 47 | static struct mpc52xx_cdm __iomem *mpc52xx_cdm; |
48 | 48 | ||
diff --git a/arch/powerpc/platforms/83xx/mpc831x_rdb.c b/arch/powerpc/platforms/83xx/mpc831x_rdb.c index a428f8d1ac80..5177bdd2c62a 100644 --- a/arch/powerpc/platforms/83xx/mpc831x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc831x_rdb.c | |||
@@ -42,7 +42,7 @@ static void __init mpc831x_rdb_setup_arch(void) | |||
42 | mpc831x_usb_cfg(); | 42 | mpc831x_usb_cfg(); |
43 | } | 43 | } |
44 | 44 | ||
45 | void __init mpc831x_rdb_init_IRQ(void) | 45 | static void __init mpc831x_rdb_init_IRQ(void) |
46 | { | 46 | { |
47 | struct device_node *np; | 47 | struct device_node *np; |
48 | 48 | ||
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c index ec43477caa63..ec0b401bc9cf 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c | |||
@@ -49,8 +49,6 @@ | |||
49 | #define DBG(fmt...) | 49 | #define DBG(fmt...) |
50 | #endif | 50 | #endif |
51 | 51 | ||
52 | static u8 *bcsr_regs = NULL; | ||
53 | |||
54 | /* ************************************************************************ | 52 | /* ************************************************************************ |
55 | * | 53 | * |
56 | * Setup the architecture | 54 | * Setup the architecture |
@@ -59,13 +57,14 @@ static u8 *bcsr_regs = NULL; | |||
59 | static void __init mpc832x_sys_setup_arch(void) | 57 | static void __init mpc832x_sys_setup_arch(void) |
60 | { | 58 | { |
61 | struct device_node *np; | 59 | struct device_node *np; |
60 | u8 __iomem *bcsr_regs = NULL; | ||
62 | 61 | ||
63 | if (ppc_md.progress) | 62 | if (ppc_md.progress) |
64 | ppc_md.progress("mpc832x_sys_setup_arch()", 0); | 63 | ppc_md.progress("mpc832x_sys_setup_arch()", 0); |
65 | 64 | ||
66 | /* Map BCSR area */ | 65 | /* Map BCSR area */ |
67 | np = of_find_node_by_name(NULL, "bcsr"); | 66 | np = of_find_node_by_name(NULL, "bcsr"); |
68 | if (np != 0) { | 67 | if (np) { |
69 | struct resource res; | 68 | struct resource res; |
70 | 69 | ||
71 | of_address_to_resource(np, 0, &res); | 70 | of_address_to_resource(np, 0, &res); |
@@ -93,9 +92,9 @@ static void __init mpc832x_sys_setup_arch(void) | |||
93 | != NULL){ | 92 | != NULL){ |
94 | /* Reset the Ethernet PHYs */ | 93 | /* Reset the Ethernet PHYs */ |
95 | #define BCSR8_FETH_RST 0x50 | 94 | #define BCSR8_FETH_RST 0x50 |
96 | bcsr_regs[8] &= ~BCSR8_FETH_RST; | 95 | clrbits8(&bcsr_regs[8], BCSR8_FETH_RST); |
97 | udelay(1000); | 96 | udelay(1000); |
98 | bcsr_regs[8] |= BCSR8_FETH_RST; | 97 | setbits8(&bcsr_regs[8], BCSR8_FETH_RST); |
99 | iounmap(bcsr_regs); | 98 | iounmap(bcsr_regs); |
100 | of_node_put(np); | 99 | of_node_put(np); |
101 | } | 100 | } |
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c index 0300268ce5b8..2a1295f19832 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #define DBG(fmt...) | 38 | #define DBG(fmt...) |
39 | #endif | 39 | #endif |
40 | 40 | ||
41 | #ifdef CONFIG_QUICC_ENGINE | ||
41 | static void mpc83xx_spi_activate_cs(u8 cs, u8 polarity) | 42 | static void mpc83xx_spi_activate_cs(u8 cs, u8 polarity) |
42 | { | 43 | { |
43 | pr_debug("%s %d %d\n", __func__, cs, polarity); | 44 | pr_debug("%s %d %d\n", __func__, cs, polarity); |
@@ -77,8 +78,8 @@ static int __init mpc832x_spi_init(void) | |||
77 | mpc83xx_spi_activate_cs, | 78 | mpc83xx_spi_activate_cs, |
78 | mpc83xx_spi_deactivate_cs); | 79 | mpc83xx_spi_deactivate_cs); |
79 | } | 80 | } |
80 | |||
81 | machine_device_initcall(mpc832x_rdb, mpc832x_spi_init); | 81 | machine_device_initcall(mpc832x_rdb, mpc832x_spi_init); |
82 | #endif /* CONFIG_QUICC_ENGINE */ | ||
82 | 83 | ||
83 | /* ************************************************************************ | 84 | /* ************************************************************************ |
84 | * | 85 | * |
@@ -130,7 +131,7 @@ static int __init mpc832x_declare_of_platform_devices(void) | |||
130 | } | 131 | } |
131 | machine_device_initcall(mpc832x_rdb, mpc832x_declare_of_platform_devices); | 132 | machine_device_initcall(mpc832x_rdb, mpc832x_declare_of_platform_devices); |
132 | 133 | ||
133 | void __init mpc832x_rdb_init_IRQ(void) | 134 | static void __init mpc832x_rdb_init_IRQ(void) |
134 | { | 135 | { |
135 | 136 | ||
136 | struct device_node *np; | 137 | struct device_node *np; |
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c index 9d46e5bdd101..09e9d6fb7411 100644 --- a/arch/powerpc/platforms/83xx/mpc836x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | #include <linux/stddef.h> | 19 | #include <linux/stddef.h> |
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/compiler.h> | ||
21 | #include <linux/init.h> | 22 | #include <linux/init.h> |
22 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
23 | #include <linux/reboot.h> | 24 | #include <linux/reboot.h> |
@@ -43,6 +44,7 @@ | |||
43 | #include <asm/udbg.h> | 44 | #include <asm/udbg.h> |
44 | #include <sysdev/fsl_soc.h> | 45 | #include <sysdev/fsl_soc.h> |
45 | #include <sysdev/fsl_pci.h> | 46 | #include <sysdev/fsl_pci.h> |
47 | #include <sysdev/simple_gpio.h> | ||
46 | #include <asm/qe.h> | 48 | #include <asm/qe.h> |
47 | #include <asm/qe_ic.h> | 49 | #include <asm/qe_ic.h> |
48 | 50 | ||
@@ -55,8 +57,6 @@ | |||
55 | #define DBG(fmt...) | 57 | #define DBG(fmt...) |
56 | #endif | 58 | #endif |
57 | 59 | ||
58 | static u8 *bcsr_regs = NULL; | ||
59 | |||
60 | /* ************************************************************************ | 60 | /* ************************************************************************ |
61 | * | 61 | * |
62 | * Setup the architecture | 62 | * Setup the architecture |
@@ -65,13 +65,14 @@ static u8 *bcsr_regs = NULL; | |||
65 | static void __init mpc836x_mds_setup_arch(void) | 65 | static void __init mpc836x_mds_setup_arch(void) |
66 | { | 66 | { |
67 | struct device_node *np; | 67 | struct device_node *np; |
68 | u8 __iomem *bcsr_regs = NULL; | ||
68 | 69 | ||
69 | if (ppc_md.progress) | 70 | if (ppc_md.progress) |
70 | ppc_md.progress("mpc836x_mds_setup_arch()", 0); | 71 | ppc_md.progress("mpc836x_mds_setup_arch()", 0); |
71 | 72 | ||
72 | /* Map BCSR area */ | 73 | /* Map BCSR area */ |
73 | np = of_find_node_by_name(NULL, "bcsr"); | 74 | np = of_find_node_by_name(NULL, "bcsr"); |
74 | if (np != 0) { | 75 | if (np) { |
75 | struct resource res; | 76 | struct resource res; |
76 | 77 | ||
77 | of_address_to_resource(np, 0, &res); | 78 | of_address_to_resource(np, 0, &res); |
@@ -93,6 +94,16 @@ static void __init mpc836x_mds_setup_arch(void) | |||
93 | 94 | ||
94 | for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;) | 95 | for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;) |
95 | par_io_of_config(np); | 96 | par_io_of_config(np); |
97 | #ifdef CONFIG_QE_USB | ||
98 | /* Must fixup Par IO before QE GPIO chips are registered. */ | ||
99 | par_io_config_pin(1, 2, 1, 0, 3, 0); /* USBOE */ | ||
100 | par_io_config_pin(1, 3, 1, 0, 3, 0); /* USBTP */ | ||
101 | par_io_config_pin(1, 8, 1, 0, 1, 0); /* USBTN */ | ||
102 | par_io_config_pin(1, 10, 2, 0, 3, 0); /* USBRXD */ | ||
103 | par_io_config_pin(1, 9, 2, 1, 3, 0); /* USBRP */ | ||
104 | par_io_config_pin(1, 11, 2, 1, 3, 0); /* USBRN */ | ||
105 | par_io_config_pin(2, 20, 2, 0, 1, 0); /* CLK21 */ | ||
106 | #endif /* CONFIG_QE_USB */ | ||
96 | } | 107 | } |
97 | 108 | ||
98 | if ((np = of_find_compatible_node(NULL, "network", "ucc_geth")) | 109 | if ((np = of_find_compatible_node(NULL, "network", "ucc_geth")) |
@@ -151,6 +162,70 @@ static int __init mpc836x_declare_of_platform_devices(void) | |||
151 | } | 162 | } |
152 | machine_device_initcall(mpc836x_mds, mpc836x_declare_of_platform_devices); | 163 | machine_device_initcall(mpc836x_mds, mpc836x_declare_of_platform_devices); |
153 | 164 | ||
165 | #ifdef CONFIG_QE_USB | ||
166 | static int __init mpc836x_usb_cfg(void) | ||
167 | { | ||
168 | u8 __iomem *bcsr; | ||
169 | struct device_node *np; | ||
170 | const char *mode; | ||
171 | int ret = 0; | ||
172 | |||
173 | np = of_find_compatible_node(NULL, NULL, "fsl,mpc8360mds-bcsr"); | ||
174 | if (!np) | ||
175 | return -ENODEV; | ||
176 | |||
177 | bcsr = of_iomap(np, 0); | ||
178 | of_node_put(np); | ||
179 | if (!bcsr) | ||
180 | return -ENOMEM; | ||
181 | |||
182 | np = of_find_compatible_node(NULL, NULL, "fsl,mpc8323-qe-usb"); | ||
183 | if (!np) { | ||
184 | ret = -ENODEV; | ||
185 | goto err; | ||
186 | } | ||
187 | |||
188 | #define BCSR8_TSEC1M_MASK (0x3 << 6) | ||
189 | #define BCSR8_TSEC1M_RGMII (0x0 << 6) | ||
190 | #define BCSR8_TSEC2M_MASK (0x3 << 4) | ||
191 | #define BCSR8_TSEC2M_RGMII (0x0 << 4) | ||
192 | /* | ||
193 | * Default is GMII (2), but we should set it to RGMII (0) if we use | ||
194 | * USB (Eth PHY is in RGMII mode anyway). | ||
195 | */ | ||
196 | clrsetbits_8(&bcsr[8], BCSR8_TSEC1M_MASK | BCSR8_TSEC2M_MASK, | ||
197 | BCSR8_TSEC1M_RGMII | BCSR8_TSEC2M_RGMII); | ||
198 | |||
199 | #define BCSR13_USBMASK 0x0f | ||
200 | #define BCSR13_nUSBEN 0x08 /* 1 - Disable, 0 - Enable */ | ||
201 | #define BCSR13_USBSPEED 0x04 /* 1 - Full, 0 - Low */ | ||
202 | #define BCSR13_USBMODE 0x02 /* 1 - Host, 0 - Function */ | ||
203 | #define BCSR13_nUSBVCC 0x01 /* 1 - gets VBUS, 0 - supplies VBUS */ | ||
204 | |||
205 | clrsetbits_8(&bcsr[13], BCSR13_USBMASK, BCSR13_USBSPEED); | ||
206 | |||
207 | mode = of_get_property(np, "mode", NULL); | ||
208 | if (mode && !strcmp(mode, "peripheral")) { | ||
209 | setbits8(&bcsr[13], BCSR13_nUSBVCC); | ||
210 | qe_usb_clock_set(QE_CLK21, 48000000); | ||
211 | } else { | ||
212 | setbits8(&bcsr[13], BCSR13_USBMODE); | ||
213 | /* | ||
214 | * The BCSR GPIOs are used to control power and | ||
215 | * speed of the USB transceiver. This is needed for | ||
216 | * the USB Host only. | ||
217 | */ | ||
218 | simple_gpiochip_init("fsl,mpc8360mds-bcsr-gpio"); | ||
219 | } | ||
220 | |||
221 | of_node_put(np); | ||
222 | err: | ||
223 | iounmap(bcsr); | ||
224 | return ret; | ||
225 | } | ||
226 | machine_arch_initcall(mpc836x_mds, mpc836x_usb_cfg); | ||
227 | #endif /* CONFIG_QE_USB */ | ||
228 | |||
154 | static void __init mpc836x_mds_init_IRQ(void) | 229 | static void __init mpc836x_mds_init_IRQ(void) |
155 | { | 230 | { |
156 | struct device_node *np; | 231 | struct device_node *np; |
diff --git a/arch/powerpc/platforms/83xx/mpc836x_rdk.c b/arch/powerpc/platforms/83xx/mpc836x_rdk.c index a5273bb28e1b..b0090aac9642 100644 --- a/arch/powerpc/platforms/83xx/mpc836x_rdk.c +++ b/arch/powerpc/platforms/83xx/mpc836x_rdk.c | |||
@@ -51,8 +51,9 @@ static void __init mpc836x_rdk_setup_arch(void) | |||
51 | for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") | 51 | for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") |
52 | mpc83xx_add_bridge(np); | 52 | mpc83xx_add_bridge(np); |
53 | #endif | 53 | #endif |
54 | 54 | #ifdef CONFIG_QUICC_ENGINE | |
55 | qe_reset(); | 55 | qe_reset(); |
56 | #endif | ||
56 | } | 57 | } |
57 | 58 | ||
58 | static void __init mpc836x_rdk_init_IRQ(void) | 59 | static void __init mpc836x_rdk_init_IRQ(void) |
@@ -71,13 +72,14 @@ static void __init mpc836x_rdk_init_IRQ(void) | |||
71 | */ | 72 | */ |
72 | ipic_set_default_priority(); | 73 | ipic_set_default_priority(); |
73 | of_node_put(np); | 74 | of_node_put(np); |
74 | 75 | #ifdef CONFIG_QUICC_ENGINE | |
75 | np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic"); | 76 | np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic"); |
76 | if (!np) | 77 | if (!np) |
77 | return; | 78 | return; |
78 | 79 | ||
79 | qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic); | 80 | qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic); |
80 | of_node_put(np); | 81 | of_node_put(np); |
82 | #endif | ||
81 | } | 83 | } |
82 | 84 | ||
83 | /* | 85 | /* |
diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c index 8bb13c807142..530ef990ca7c 100644 --- a/arch/powerpc/platforms/83xx/mpc837x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #define BCSR12_USB_SER_MASK 0x8a | 26 | #define BCSR12_USB_SER_MASK 0x8a |
27 | #define BCSR12_USB_SER_PIN 0x80 | 27 | #define BCSR12_USB_SER_PIN 0x80 |
28 | #define BCSR12_USB_SER_DEVICE 0x02 | 28 | #define BCSR12_USB_SER_DEVICE 0x02 |
29 | extern int mpc837x_usb_cfg(void); | ||
30 | 29 | ||
31 | static int mpc837xmds_usb_cfg(void) | 30 | static int mpc837xmds_usb_cfg(void) |
32 | { | 31 | { |
diff --git a/arch/powerpc/platforms/83xx/mpc837x_rdb.c b/arch/powerpc/platforms/83xx/mpc837x_rdb.c index da030afa2e2c..1d096545322b 100644 --- a/arch/powerpc/platforms/83xx/mpc837x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc837x_rdb.c | |||
@@ -21,8 +21,6 @@ | |||
21 | 21 | ||
22 | #include "mpc83xx.h" | 22 | #include "mpc83xx.h" |
23 | 23 | ||
24 | extern int mpc837x_usb_cfg(void); | ||
25 | |||
26 | /* ************************************************************************ | 24 | /* ************************************************************************ |
27 | * | 25 | * |
28 | * Setup the architecture | 26 | * Setup the architecture |
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h index 2a7cbabb410a..83cfe51526ec 100644 --- a/arch/powerpc/platforms/83xx/mpc83xx.h +++ b/arch/powerpc/platforms/83xx/mpc83xx.h | |||
@@ -61,6 +61,7 @@ | |||
61 | 61 | ||
62 | extern void mpc83xx_restart(char *cmd); | 62 | extern void mpc83xx_restart(char *cmd); |
63 | extern long mpc83xx_time_init(void); | 63 | extern long mpc83xx_time_init(void); |
64 | extern int mpc837x_usb_cfg(void); | ||
64 | extern int mpc834x_usb_cfg(void); | 65 | extern int mpc834x_usb_cfg(void); |
65 | extern int mpc831x_usb_cfg(void); | 66 | extern int mpc831x_usb_cfg(void); |
66 | 67 | ||
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c index a8301c8ad537..7326d904202c 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c | |||
@@ -148,6 +148,9 @@ static int mpc85xx_exclude_device(struct pci_controller *hose, | |||
148 | /* | 148 | /* |
149 | * Setup the architecture | 149 | * Setup the architecture |
150 | */ | 150 | */ |
151 | #ifdef CONFIG_SMP | ||
152 | extern void __init mpc85xx_smp_init(void); | ||
153 | #endif | ||
151 | static void __init mpc85xx_ds_setup_arch(void) | 154 | static void __init mpc85xx_ds_setup_arch(void) |
152 | { | 155 | { |
153 | #ifdef CONFIG_PCI | 156 | #ifdef CONFIG_PCI |
@@ -173,6 +176,10 @@ static void __init mpc85xx_ds_setup_arch(void) | |||
173 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; | 176 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; |
174 | #endif | 177 | #endif |
175 | 178 | ||
179 | #ifdef CONFIG_SMP | ||
180 | mpc85xx_smp_init(); | ||
181 | #endif | ||
182 | |||
176 | printk("MPC85xx DS board from Freescale Semiconductor\n"); | 183 | printk("MPC85xx DS board from Freescale Semiconductor\n"); |
177 | } | 184 | } |
178 | 185 | ||
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index d652c713f496..79a0df17078b 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c | |||
@@ -58,6 +58,7 @@ smp_85xx_kick_cpu(int nr) | |||
58 | 58 | ||
59 | if (cpu_rel_addr == NULL) { | 59 | if (cpu_rel_addr == NULL) { |
60 | printk(KERN_ERR "No cpu-release-addr for cpu %d\n", nr); | 60 | printk(KERN_ERR "No cpu-release-addr for cpu %d\n", nr); |
61 | local_irq_restore(flags); | ||
61 | return; | 62 | return; |
62 | } | 63 | } |
63 | 64 | ||
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 47e956c871fe..47fe2bea9865 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
@@ -312,4 +312,15 @@ config MPC8xxx_GPIO | |||
312 | Say Y here if you're going to use hardware that connects to the | 312 | Say Y here if you're going to use hardware that connects to the |
313 | MPC831x/834x/837x/8572/8610 GPIOs. | 313 | MPC831x/834x/837x/8572/8610 GPIOs. |
314 | 314 | ||
315 | config SIMPLE_GPIO | ||
316 | bool "Support for simple, memory-mapped GPIO controllers" | ||
317 | depends on PPC | ||
318 | select GENERIC_GPIO | ||
319 | select ARCH_REQUIRE_GPIOLIB | ||
320 | help | ||
321 | Say Y here to support simple, memory-mapped GPIO controllers. | ||
322 | These are usually BCSRs used to control board's switches, LEDs, | ||
323 | chip-selects, Ethernet/USB PHY's power and various other small | ||
324 | on-board peripherals. | ||
325 | |||
315 | endmenu | 326 | endmenu |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index 3d0c776f888d..e868b5c50723 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
@@ -231,7 +231,7 @@ config VIRT_CPU_ACCOUNTING | |||
231 | If in doubt, say Y here. | 231 | If in doubt, say Y here. |
232 | 232 | ||
233 | config SMP | 233 | config SMP |
234 | depends on PPC_STD_MMU | 234 | depends on PPC_STD_MMU || FSL_BOOKE |
235 | bool "Symmetric multi-processing support" | 235 | bool "Symmetric multi-processing support" |
236 | ---help--- | 236 | ---help--- |
237 | This enables support for systems with more than one CPU. If you have | 237 | This enables support for systems with more than one CPU. If you have |
diff --git a/arch/powerpc/platforms/cell/beat_htab.c b/arch/powerpc/platforms/cell/beat_htab.c index 2e67bd840e01..35b1ec492715 100644 --- a/arch/powerpc/platforms/cell/beat_htab.c +++ b/arch/powerpc/platforms/cell/beat_htab.c | |||
@@ -44,8 +44,8 @@ static DEFINE_SPINLOCK(beat_htab_lock); | |||
44 | 44 | ||
45 | static inline unsigned int beat_read_mask(unsigned hpte_group) | 45 | static inline unsigned int beat_read_mask(unsigned hpte_group) |
46 | { | 46 | { |
47 | unsigned long hpte_v[5]; | ||
48 | unsigned long rmask = 0; | 47 | unsigned long rmask = 0; |
48 | u64 hpte_v[5]; | ||
49 | 49 | ||
50 | beat_read_htab_entries(0, hpte_group + 0, hpte_v); | 50 | beat_read_htab_entries(0, hpte_group + 0, hpte_v); |
51 | if (!(hpte_v[0] & HPTE_V_BOLTED)) | 51 | if (!(hpte_v[0] & HPTE_V_BOLTED)) |
@@ -93,8 +93,7 @@ static long beat_lpar_hpte_insert(unsigned long hpte_group, | |||
93 | int psize, int ssize) | 93 | int psize, int ssize) |
94 | { | 94 | { |
95 | unsigned long lpar_rc; | 95 | unsigned long lpar_rc; |
96 | unsigned long slot; | 96 | u64 hpte_v, hpte_r, slot; |
97 | unsigned long hpte_v, hpte_r; | ||
98 | 97 | ||
99 | /* same as iseries */ | 98 | /* same as iseries */ |
100 | if (vflags & HPTE_V_SECONDARY) | 99 | if (vflags & HPTE_V_SECONDARY) |
@@ -153,8 +152,9 @@ static long beat_lpar_hpte_remove(unsigned long hpte_group) | |||
153 | 152 | ||
154 | static unsigned long beat_lpar_hpte_getword0(unsigned long slot) | 153 | static unsigned long beat_lpar_hpte_getword0(unsigned long slot) |
155 | { | 154 | { |
156 | unsigned long dword0, dword[5]; | 155 | unsigned long dword0; |
157 | unsigned long lpar_rc; | 156 | unsigned long lpar_rc; |
157 | u64 dword[5]; | ||
158 | 158 | ||
159 | lpar_rc = beat_read_htab_entries(0, slot & ~3UL, dword); | 159 | lpar_rc = beat_read_htab_entries(0, slot & ~3UL, dword); |
160 | 160 | ||
@@ -170,7 +170,7 @@ static void beat_lpar_hptab_clear(void) | |||
170 | unsigned long size_bytes = 1UL << ppc64_pft_size; | 170 | unsigned long size_bytes = 1UL << ppc64_pft_size; |
171 | unsigned long hpte_count = size_bytes >> 4; | 171 | unsigned long hpte_count = size_bytes >> 4; |
172 | int i; | 172 | int i; |
173 | unsigned long dummy0, dummy1; | 173 | u64 dummy0, dummy1; |
174 | 174 | ||
175 | /* TODO: Use bulk call */ | 175 | /* TODO: Use bulk call */ |
176 | for (i = 0; i < hpte_count; i++) | 176 | for (i = 0; i < hpte_count; i++) |
@@ -189,7 +189,8 @@ static long beat_lpar_hpte_updatepp(unsigned long slot, | |||
189 | int psize, int ssize, int local) | 189 | int psize, int ssize, int local) |
190 | { | 190 | { |
191 | unsigned long lpar_rc; | 191 | unsigned long lpar_rc; |
192 | unsigned long dummy0, dummy1, want_v; | 192 | u64 dummy0, dummy1; |
193 | unsigned long want_v; | ||
193 | 194 | ||
194 | want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M); | 195 | want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M); |
195 | 196 | ||
@@ -255,7 +256,8 @@ static void beat_lpar_hpte_updateboltedpp(unsigned long newpp, | |||
255 | unsigned long ea, | 256 | unsigned long ea, |
256 | int psize, int ssize) | 257 | int psize, int ssize) |
257 | { | 258 | { |
258 | unsigned long lpar_rc, slot, vsid, va, dummy0, dummy1; | 259 | unsigned long lpar_rc, slot, vsid, va; |
260 | u64 dummy0, dummy1; | ||
259 | 261 | ||
260 | vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M); | 262 | vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M); |
261 | va = (vsid << 28) | (ea & 0x0fffffff); | 263 | va = (vsid << 28) | (ea & 0x0fffffff); |
@@ -276,7 +278,7 @@ static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va, | |||
276 | { | 278 | { |
277 | unsigned long want_v; | 279 | unsigned long want_v; |
278 | unsigned long lpar_rc; | 280 | unsigned long lpar_rc; |
279 | unsigned long dummy1, dummy2; | 281 | u64 dummy1, dummy2; |
280 | unsigned long flags; | 282 | unsigned long flags; |
281 | 283 | ||
282 | DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n", | 284 | DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n", |
@@ -315,8 +317,7 @@ static long beat_lpar_hpte_insert_v3(unsigned long hpte_group, | |||
315 | int psize, int ssize) | 317 | int psize, int ssize) |
316 | { | 318 | { |
317 | unsigned long lpar_rc; | 319 | unsigned long lpar_rc; |
318 | unsigned long slot; | 320 | u64 hpte_v, hpte_r, slot; |
319 | unsigned long hpte_v, hpte_r; | ||
320 | 321 | ||
321 | /* same as iseries */ | 322 | /* same as iseries */ |
322 | if (vflags & HPTE_V_SECONDARY) | 323 | if (vflags & HPTE_V_SECONDARY) |
diff --git a/arch/powerpc/platforms/cell/beat_udbg.c b/arch/powerpc/platforms/cell/beat_udbg.c index 6b418f6b6175..350735bc8888 100644 --- a/arch/powerpc/platforms/cell/beat_udbg.c +++ b/arch/powerpc/platforms/cell/beat_udbg.c | |||
@@ -40,8 +40,8 @@ static void udbg_putc_beat(char c) | |||
40 | } | 40 | } |
41 | 41 | ||
42 | /* Buffered chars getc */ | 42 | /* Buffered chars getc */ |
43 | static long inbuflen; | 43 | static u64 inbuflen; |
44 | static long inbuf[2]; /* must be 2 longs */ | 44 | static u64 inbuf[2]; /* must be 2 u64s */ |
45 | 45 | ||
46 | static int udbg_getc_poll_beat(void) | 46 | static int udbg_getc_poll_beat(void) |
47 | { | 47 | { |
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c index ec7c8f45a215..e6506cd0ff94 100644 --- a/arch/powerpc/platforms/cell/cbe_cpufreq.c +++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c | |||
@@ -118,7 +118,7 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
118 | policy->cur = cbe_freqs[cur_pmode].frequency; | 118 | policy->cur = cbe_freqs[cur_pmode].frequency; |
119 | 119 | ||
120 | #ifdef CONFIG_SMP | 120 | #ifdef CONFIG_SMP |
121 | policy->cpus = per_cpu(cpu_sibling_map, policy->cpu); | 121 | cpumask_copy(policy->cpus, &per_cpu(cpu_sibling_map, policy->cpu)); |
122 | #endif | 122 | #endif |
123 | 123 | ||
124 | cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu); | 124 | cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu); |
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c b/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c index 70fa7aef5edd..20472e487b6f 100644 --- a/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c +++ b/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c | |||
@@ -54,7 +54,7 @@ int cbe_cpufreq_set_pmode(int cpu, unsigned int pmode) | |||
54 | { | 54 | { |
55 | struct cbe_pmd_regs __iomem *pmd_regs; | 55 | struct cbe_pmd_regs __iomem *pmd_regs; |
56 | struct cbe_mic_tm_regs __iomem *mic_tm_regs; | 56 | struct cbe_mic_tm_regs __iomem *mic_tm_regs; |
57 | u64 flags; | 57 | unsigned long flags; |
58 | u64 value; | 58 | u64 value; |
59 | #ifdef DEBUG | 59 | #ifdef DEBUG |
60 | long time; | 60 | long time; |
diff --git a/arch/powerpc/platforms/cell/cpufreq_spudemand.c b/arch/powerpc/platforms/cell/cpufreq_spudemand.c index a3c6c01bd6db..968c1c0b4d5b 100644 --- a/arch/powerpc/platforms/cell/cpufreq_spudemand.c +++ b/arch/powerpc/platforms/cell/cpufreq_spudemand.c | |||
@@ -110,7 +110,7 @@ static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event) | |||
110 | } | 110 | } |
111 | 111 | ||
112 | /* initialize spu_gov_info for all affected cpus */ | 112 | /* initialize spu_gov_info for all affected cpus */ |
113 | for_each_cpu_mask(i, policy->cpus) { | 113 | for_each_cpu(i, policy->cpus) { |
114 | affected_info = &per_cpu(spu_gov_info, i); | 114 | affected_info = &per_cpu(spu_gov_info, i); |
115 | affected_info->policy = policy; | 115 | affected_info->policy = policy; |
116 | } | 116 | } |
@@ -127,7 +127,7 @@ static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event) | |||
127 | spu_gov_cancel_work(info); | 127 | spu_gov_cancel_work(info); |
128 | 128 | ||
129 | /* clean spu_gov_info for all affected cpus */ | 129 | /* clean spu_gov_info for all affected cpus */ |
130 | for_each_cpu_mask (i, policy->cpus) { | 130 | for_each_cpu (i, policy->cpus) { |
131 | info = &per_cpu(spu_gov_info, i); | 131 | info = &per_cpu(spu_gov_info, i); |
132 | info->policy = NULL; | 132 | info->policy = NULL; |
133 | } | 133 | } |
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 2d5bb22d6c09..28c04dab2633 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c | |||
@@ -148,7 +148,7 @@ static unsigned int iic_get_irq(void) | |||
148 | 148 | ||
149 | iic = &__get_cpu_var(iic); | 149 | iic = &__get_cpu_var(iic); |
150 | *(unsigned long *) &pending = | 150 | *(unsigned long *) &pending = |
151 | in_be64((unsigned long __iomem *) &iic->regs->pending_destr); | 151 | in_be64((u64 __iomem *) &iic->regs->pending_destr); |
152 | if (!(pending.flags & CBE_IIC_IRQ_VALID)) | 152 | if (!(pending.flags & CBE_IIC_IRQ_VALID)) |
153 | return NO_IRQ; | 153 | return NO_IRQ; |
154 | virq = irq_linear_revmap(iic_host, iic_pending_to_hwnum(pending)); | 154 | virq = irq_linear_revmap(iic_host, iic_pending_to_hwnum(pending)); |
diff --git a/arch/powerpc/platforms/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c index b5f84e8f0899..059cad6c3f69 100644 --- a/arch/powerpc/platforms/cell/io-workarounds.c +++ b/arch/powerpc/platforms/cell/io-workarounds.c | |||
@@ -130,14 +130,14 @@ static const struct ppc_pci_io __devinitconst iowa_pci_io = { | |||
130 | 130 | ||
131 | }; | 131 | }; |
132 | 132 | ||
133 | static void __iomem *iowa_ioremap(unsigned long addr, unsigned long size, | 133 | static void __iomem *iowa_ioremap(phys_addr_t addr, unsigned long size, |
134 | unsigned long flags) | 134 | unsigned long flags) |
135 | { | 135 | { |
136 | struct iowa_bus *bus; | 136 | struct iowa_bus *bus; |
137 | void __iomem *res = __ioremap(addr, size, flags); | 137 | void __iomem *res = __ioremap(addr, size, flags); |
138 | int busno; | 138 | int busno; |
139 | 139 | ||
140 | bus = iowa_pci_find(0, addr); | 140 | bus = iowa_pci_find(0, (unsigned long)addr); |
141 | if (bus != NULL) { | 141 | if (bus != NULL) { |
142 | busno = bus - iowa_busses; | 142 | busno = bus - iowa_busses; |
143 | PCI_SET_ADDR_TOKEN(res, busno + 1); | 143 | PCI_SET_ADDR_TOKEN(res, busno + 1); |
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index 86db4dd170a0..88d94b59a7cb 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c | |||
@@ -150,8 +150,8 @@ static int cbe_nr_iommus; | |||
150 | static void invalidate_tce_cache(struct cbe_iommu *iommu, unsigned long *pte, | 150 | static void invalidate_tce_cache(struct cbe_iommu *iommu, unsigned long *pte, |
151 | long n_ptes) | 151 | long n_ptes) |
152 | { | 152 | { |
153 | unsigned long __iomem *reg; | 153 | u64 __iomem *reg; |
154 | unsigned long val; | 154 | u64 val; |
155 | long n; | 155 | long n; |
156 | 156 | ||
157 | reg = iommu->xlate_regs + IOC_IOPT_CacheInvd; | 157 | reg = iommu->xlate_regs + IOC_IOPT_CacheInvd; |
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 15c62d3ca129..3bf908e2873a 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h | |||
@@ -314,7 +314,7 @@ extern char *isolated_loader; | |||
314 | * we need to call spu_release(ctx) before sleeping, and | 314 | * we need to call spu_release(ctx) before sleeping, and |
315 | * then spu_acquire(ctx) when awoken. | 315 | * then spu_acquire(ctx) when awoken. |
316 | * | 316 | * |
317 | * Returns with state_mutex re-acquired when successfull or | 317 | * Returns with state_mutex re-acquired when successful or |
318 | * with -ERESTARTSYS and the state_mutex dropped when interrupted. | 318 | * with -ERESTARTSYS and the state_mutex dropped when interrupted. |
319 | */ | 319 | */ |
320 | 320 | ||
diff --git a/arch/powerpc/platforms/iseries/Kconfig b/arch/powerpc/platforms/iseries/Kconfig index ed3753d8c109..7ddd0a2c8027 100644 --- a/arch/powerpc/platforms/iseries/Kconfig +++ b/arch/powerpc/platforms/iseries/Kconfig | |||
@@ -10,18 +10,21 @@ menu "iSeries device drivers" | |||
10 | config VIODASD | 10 | config VIODASD |
11 | tristate "iSeries Virtual I/O disk support" | 11 | tristate "iSeries Virtual I/O disk support" |
12 | depends on BLOCK | 12 | depends on BLOCK |
13 | select VIOPATH | ||
13 | help | 14 | help |
14 | If you are running on an iSeries system and you want to use | 15 | If you are running on an iSeries system and you want to use |
15 | virtual disks created and managed by OS/400, say Y. | 16 | virtual disks created and managed by OS/400, say Y. |
16 | 17 | ||
17 | config VIOCD | 18 | config VIOCD |
18 | tristate "iSeries Virtual I/O CD support" | 19 | tristate "iSeries Virtual I/O CD support" |
20 | select VIOPATH | ||
19 | help | 21 | help |
20 | If you are running Linux on an IBM iSeries system and you want to | 22 | If you are running Linux on an IBM iSeries system and you want to |
21 | read a CD drive owned by OS/400, say Y here. | 23 | read a CD drive owned by OS/400, say Y here. |
22 | 24 | ||
23 | config VIOTAPE | 25 | config VIOTAPE |
24 | tristate "iSeries Virtual Tape Support" | 26 | tristate "iSeries Virtual Tape Support" |
27 | select VIOPATH | ||
25 | help | 28 | help |
26 | If you are running Linux on an iSeries system and you want Linux | 29 | If you are running Linux on an iSeries system and you want Linux |
27 | to read and/or write a tape drive owned by OS/400, say Y here. | 30 | to read and/or write a tape drive owned by OS/400, say Y here. |
@@ -30,5 +33,3 @@ endmenu | |||
30 | 33 | ||
31 | config VIOPATH | 34 | config VIOPATH |
32 | bool | 35 | bool |
33 | depends on VIODASD || VIOCD || VIOTAPE || ISERIES_VETH | ||
34 | default y | ||
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 70b688c1aefb..24519b96d6ad 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/string.h> | 23 | #include <linux/string.h> |
24 | #include <linux/seq_file.h> | 24 | #include <linux/seq_file.h> |
25 | #include <linux/kdev_t.h> | 25 | #include <linux/kdev_t.h> |
26 | #include <linux/kexec.h> | ||
26 | #include <linux/major.h> | 27 | #include <linux/major.h> |
27 | #include <linux/root_dev.h> | 28 | #include <linux/root_dev.h> |
28 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
@@ -638,6 +639,13 @@ static int __init iseries_probe(void) | |||
638 | return 1; | 639 | return 1; |
639 | } | 640 | } |
640 | 641 | ||
642 | #ifdef CONFIG_KEXEC | ||
643 | static int iseries_kexec_prepare(struct kimage *image) | ||
644 | { | ||
645 | return -ENOSYS; | ||
646 | } | ||
647 | #endif | ||
648 | |||
641 | define_machine(iseries) { | 649 | define_machine(iseries) { |
642 | .name = "iSeries", | 650 | .name = "iSeries", |
643 | .setup_arch = iSeries_setup_arch, | 651 | .setup_arch = iSeries_setup_arch, |
@@ -658,6 +666,9 @@ define_machine(iseries) { | |||
658 | .probe = iseries_probe, | 666 | .probe = iseries_probe, |
659 | .ioremap = iseries_ioremap, | 667 | .ioremap = iseries_ioremap, |
660 | .iounmap = iseries_iounmap, | 668 | .iounmap = iseries_iounmap, |
669 | #ifdef CONFIG_KEXEC | ||
670 | .machine_kexec_prepare = iseries_kexec_prepare, | ||
671 | #endif | ||
661 | /* XXX Implement enable_pmcs for iSeries */ | 672 | /* XXX Implement enable_pmcs for iSeries */ |
662 | }; | 673 | }; |
663 | 674 | ||
diff --git a/arch/powerpc/platforms/pasemi/cpufreq.c b/arch/powerpc/platforms/pasemi/cpufreq.c index 58556b028a4c..be2527a516ea 100644 --- a/arch/powerpc/platforms/pasemi/cpufreq.c +++ b/arch/powerpc/platforms/pasemi/cpufreq.c | |||
@@ -112,7 +112,7 @@ static int get_gizmo_latency(void) | |||
112 | 112 | ||
113 | static void set_astate(int cpu, unsigned int astate) | 113 | static void set_astate(int cpu, unsigned int astate) |
114 | { | 114 | { |
115 | u64 flags; | 115 | unsigned long flags; |
116 | 116 | ||
117 | /* Return if called before init has run */ | 117 | /* Return if called before init has run */ |
118 | if (unlikely(!sdcasr_mapbase)) | 118 | if (unlikely(!sdcasr_mapbase)) |
@@ -213,7 +213,7 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
213 | pr_debug("current astate is at %d\n",cur_astate); | 213 | pr_debug("current astate is at %d\n",cur_astate); |
214 | 214 | ||
215 | policy->cur = pas_freqs[cur_astate].frequency; | 215 | policy->cur = pas_freqs[cur_astate].frequency; |
216 | policy->cpus = cpu_online_map; | 216 | cpumask_copy(policy->cpus, &cpu_online_map); |
217 | 217 | ||
218 | ppc_proc_freq = policy->cur * 1000ul; | 218 | ppc_proc_freq = policy->cur * 1000ul; |
219 | 219 | ||
diff --git a/arch/powerpc/platforms/pasemi/dma_lib.c b/arch/powerpc/platforms/pasemi/dma_lib.c index 217af321b0ca..a6152d922243 100644 --- a/arch/powerpc/platforms/pasemi/dma_lib.c +++ b/arch/powerpc/platforms/pasemi/dma_lib.c | |||
@@ -509,7 +509,7 @@ fallback: | |||
509 | */ | 509 | */ |
510 | int pasemi_dma_init(void) | 510 | int pasemi_dma_init(void) |
511 | { | 511 | { |
512 | static spinlock_t init_lock = SPIN_LOCK_UNLOCKED; | 512 | static DEFINE_SPINLOCK(init_lock); |
513 | struct pci_dev *iob_pdev; | 513 | struct pci_dev *iob_pdev; |
514 | struct pci_dev *pdev; | 514 | struct pci_dev *pdev; |
515 | struct resource res; | 515 | struct resource res; |
diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c index 4dfb4bc242b5..beb38333b6d2 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_64.c +++ b/arch/powerpc/platforms/powermac/cpufreq_64.c | |||
@@ -362,7 +362,7 @@ static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
362 | /* secondary CPUs are tied to the primary one by the | 362 | /* secondary CPUs are tied to the primary one by the |
363 | * cpufreq core if in the secondary policy we tell it that | 363 | * cpufreq core if in the secondary policy we tell it that |
364 | * it actually must be one policy together with all others. */ | 364 | * it actually must be one policy together with all others. */ |
365 | policy->cpus = cpu_online_map; | 365 | cpumask_copy(policy->cpus, &cpu_online_map); |
366 | cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu); | 366 | cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu); |
367 | 367 | ||
368 | return cpufreq_frequency_table_cpuinfo(policy, | 368 | return cpufreq_frequency_table_cpuinfo(policy, |
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index 54b7b76ed4f0..04cdd32624d4 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c | |||
@@ -661,6 +661,7 @@ static void __init init_second_ohare(void) | |||
661 | pci_find_hose_for_OF_device(np); | 661 | pci_find_hose_for_OF_device(np); |
662 | if (!hose) { | 662 | if (!hose) { |
663 | printk(KERN_ERR "Can't find PCI hose for OHare2 !\n"); | 663 | printk(KERN_ERR "Can't find PCI hose for OHare2 !\n"); |
664 | of_node_put(np); | ||
664 | return; | 665 | return; |
665 | } | 666 | } |
666 | early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd); | 667 | early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd); |
@@ -669,6 +670,7 @@ static void __init init_second_ohare(void) | |||
669 | early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd); | 670 | early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd); |
670 | } | 671 | } |
671 | has_second_ohare = 1; | 672 | has_second_ohare = 1; |
673 | of_node_put(np); | ||
672 | } | 674 | } |
673 | 675 | ||
674 | /* | 676 | /* |
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c index 59eb840d8ce2..1810e4226e56 100644 --- a/arch/powerpc/platforms/powermac/time.c +++ b/arch/powerpc/platforms/powermac/time.c | |||
@@ -265,12 +265,15 @@ int __init via_calibrate_decr(void) | |||
265 | struct resource rsrc; | 265 | struct resource rsrc; |
266 | 266 | ||
267 | vias = of_find_node_by_name(NULL, "via-cuda"); | 267 | vias = of_find_node_by_name(NULL, "via-cuda"); |
268 | if (vias == 0) | 268 | if (vias == NULL) |
269 | vias = of_find_node_by_name(NULL, "via-pmu"); | 269 | vias = of_find_node_by_name(NULL, "via-pmu"); |
270 | if (vias == 0) | 270 | if (vias == NULL) |
271 | vias = of_find_node_by_name(NULL, "via"); | 271 | vias = of_find_node_by_name(NULL, "via"); |
272 | if (vias == 0 || of_address_to_resource(vias, 0, &rsrc)) | 272 | if (vias == NULL || of_address_to_resource(vias, 0, &rsrc)) { |
273 | of_node_put(vias); | ||
273 | return 0; | 274 | return 0; |
275 | } | ||
276 | of_node_put(vias); | ||
274 | via = ioremap(rsrc.start, rsrc.end - rsrc.start + 1); | 277 | via = ioremap(rsrc.start, rsrc.end - rsrc.start + 1); |
275 | if (via == NULL) { | 278 | if (via == NULL) { |
276 | printk(KERN_ERR "Failed to map VIA for timer calibration !\n"); | 279 | printk(KERN_ERR "Failed to map VIA for timer calibration !\n"); |
@@ -297,7 +300,7 @@ int __init via_calibrate_decr(void) | |||
297 | ppc_tb_freq = (dstart - dend) * 100 / 6; | 300 | ppc_tb_freq = (dstart - dend) * 100 / 6; |
298 | 301 | ||
299 | iounmap(via); | 302 | iounmap(via); |
300 | 303 | ||
301 | return 1; | 304 | return 1; |
302 | } | 305 | } |
303 | #endif | 306 | #endif |
diff --git a/arch/powerpc/platforms/ps3/device-init.c b/arch/powerpc/platforms/ps3/device-init.c index dbc124e05646..ca71a12b764c 100644 --- a/arch/powerpc/platforms/ps3/device-init.c +++ b/arch/powerpc/platforms/ps3/device-init.c | |||
@@ -518,6 +518,41 @@ fail_device_register: | |||
518 | return result; | 518 | return result; |
519 | } | 519 | } |
520 | 520 | ||
521 | static int __init ps3_register_ramdisk_device(void) | ||
522 | { | ||
523 | int result; | ||
524 | struct layout { | ||
525 | struct ps3_system_bus_device dev; | ||
526 | } *p; | ||
527 | |||
528 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
529 | |||
530 | p = kzalloc(sizeof(struct layout), GFP_KERNEL); | ||
531 | |||
532 | if (!p) | ||
533 | return -ENOMEM; | ||
534 | |||
535 | p->dev.match_id = PS3_MATCH_ID_GPU; | ||
536 | p->dev.match_sub_id = PS3_MATCH_SUB_ID_GPU_RAMDISK; | ||
537 | p->dev.dev_type = PS3_DEVICE_TYPE_IOC0; | ||
538 | |||
539 | result = ps3_system_bus_device_register(&p->dev); | ||
540 | |||
541 | if (result) { | ||
542 | pr_debug("%s:%d ps3_system_bus_device_register failed\n", | ||
543 | __func__, __LINE__); | ||
544 | goto fail_device_register; | ||
545 | } | ||
546 | |||
547 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
548 | return 0; | ||
549 | |||
550 | fail_device_register: | ||
551 | kfree(p); | ||
552 | pr_debug(" <- %s:%d failed\n", __func__, __LINE__); | ||
553 | return result; | ||
554 | } | ||
555 | |||
521 | /** | 556 | /** |
522 | * ps3_setup_dynamic_device - Setup a dynamic device from the repository | 557 | * ps3_setup_dynamic_device - Setup a dynamic device from the repository |
523 | */ | 558 | */ |
@@ -946,6 +981,8 @@ static int __init ps3_register_devices(void) | |||
946 | 981 | ||
947 | ps3_register_lpm_devices(); | 982 | ps3_register_lpm_devices(); |
948 | 983 | ||
984 | ps3_register_ramdisk_device(); | ||
985 | |||
949 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | 986 | pr_debug(" <- %s:%d\n", __func__, __LINE__); |
950 | return 0; | 987 | return 0; |
951 | } | 988 | } |
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 5afce115ab1f..b33b28a6fe12 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile | |||
@@ -17,6 +17,7 @@ obj-$(CONFIG_FSL_PCI) += fsl_pci.o $(fsl-msi-obj-y) | |||
17 | obj-$(CONFIG_FSL_LBC) += fsl_lbc.o | 17 | obj-$(CONFIG_FSL_LBC) += fsl_lbc.o |
18 | obj-$(CONFIG_FSL_GTM) += fsl_gtm.o | 18 | obj-$(CONFIG_FSL_GTM) += fsl_gtm.o |
19 | obj-$(CONFIG_MPC8xxx_GPIO) += mpc8xxx_gpio.o | 19 | obj-$(CONFIG_MPC8xxx_GPIO) += mpc8xxx_gpio.o |
20 | obj-$(CONFIG_SIMPLE_GPIO) += simple_gpio.o | ||
20 | obj-$(CONFIG_RAPIDIO) += fsl_rio.o | 21 | obj-$(CONFIG_RAPIDIO) += fsl_rio.o |
21 | obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o | 22 | obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o |
22 | obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ | 23 | obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ |
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index d5f9ae0f1b75..f611d0369cc8 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c | |||
@@ -29,7 +29,8 @@ | |||
29 | 29 | ||
30 | #if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx) | 30 | #if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx) |
31 | /* atmu setup for fsl pci/pcie controller */ | 31 | /* atmu setup for fsl pci/pcie controller */ |
32 | void __init setup_pci_atmu(struct pci_controller *hose, struct resource *rsrc) | 32 | static void __init setup_pci_atmu(struct pci_controller *hose, |
33 | struct resource *rsrc) | ||
33 | { | 34 | { |
34 | struct ccsr_pci __iomem *pci; | 35 | struct ccsr_pci __iomem *pci; |
35 | int i; | 36 | int i; |
@@ -86,7 +87,7 @@ void __init setup_pci_atmu(struct pci_controller *hose, struct resource *rsrc) | |||
86 | out_be32(&pci->piw[2].piwar, PIWAR_2G); | 87 | out_be32(&pci->piw[2].piwar, PIWAR_2G); |
87 | } | 88 | } |
88 | 89 | ||
89 | void __init setup_pci_cmd(struct pci_controller *hose) | 90 | static void __init setup_pci_cmd(struct pci_controller *hose) |
90 | { | 91 | { |
91 | u16 cmd; | 92 | u16 cmd; |
92 | int cap_x; | 93 | int cap_x; |
@@ -130,7 +131,7 @@ static void __init quirk_fsl_pcie_header(struct pci_dev *dev) | |||
130 | return ; | 131 | return ; |
131 | } | 132 | } |
132 | 133 | ||
133 | int __init fsl_pcie_check_link(struct pci_controller *hose) | 134 | static int __init fsl_pcie_check_link(struct pci_controller *hose) |
134 | { | 135 | { |
135 | u32 val; | 136 | u32 val; |
136 | early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val); | 137 | early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val); |
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h index 60f7f227327c..9c744e4285a0 100644 --- a/arch/powerpc/sysdev/fsl_soc.h +++ b/arch/powerpc/sysdev/fsl_soc.h | |||
@@ -5,8 +5,13 @@ | |||
5 | #include <asm/mmu.h> | 5 | #include <asm/mmu.h> |
6 | 6 | ||
7 | extern phys_addr_t get_immrbase(void); | 7 | extern phys_addr_t get_immrbase(void); |
8 | #if defined(CONFIG_CPM2) || defined(CONFIG_QUICC_ENGINE) || defined(CONFIG_8xx) | ||
8 | extern u32 get_brgfreq(void); | 9 | extern u32 get_brgfreq(void); |
9 | extern u32 get_baudrate(void); | 10 | extern u32 get_baudrate(void); |
11 | #else | ||
12 | static inline u32 get_brgfreq(void) { return -1; } | ||
13 | static inline u32 get_baudrate(void) { return -1; } | ||
14 | #endif | ||
10 | extern u32 fsl_get_sys_freq(void); | 15 | extern u32 fsl_get_sys_freq(void); |
11 | 16 | ||
12 | struct spi_board_info; | 17 | struct spi_board_info; |
diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig index 76ffbc48d4b9..41ac3dfac98e 100644 --- a/arch/powerpc/sysdev/qe_lib/Kconfig +++ b/arch/powerpc/sysdev/qe_lib/Kconfig | |||
@@ -22,5 +22,6 @@ config UCC | |||
22 | 22 | ||
23 | config QE_USB | 23 | config QE_USB |
24 | bool | 24 | bool |
25 | default y if USB_GADGET_FSL_QE | ||
25 | help | 26 | help |
26 | QE USB Host Controller support | 27 | QE USB Controller support |
diff --git a/arch/powerpc/sysdev/qe_lib/gpio.c b/arch/powerpc/sysdev/qe_lib/gpio.c index 8e5a0bc36d0b..3485288dce31 100644 --- a/arch/powerpc/sysdev/qe_lib/gpio.c +++ b/arch/powerpc/sysdev/qe_lib/gpio.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/spinlock.h> | 16 | #include <linux/spinlock.h> |
17 | #include <linux/err.h> | ||
17 | #include <linux/io.h> | 18 | #include <linux/io.h> |
18 | #include <linux/of.h> | 19 | #include <linux/of.h> |
19 | #include <linux/of_gpio.h> | 20 | #include <linux/of_gpio.h> |
@@ -24,8 +25,14 @@ struct qe_gpio_chip { | |||
24 | struct of_mm_gpio_chip mm_gc; | 25 | struct of_mm_gpio_chip mm_gc; |
25 | spinlock_t lock; | 26 | spinlock_t lock; |
26 | 27 | ||
28 | unsigned long pin_flags[QE_PIO_PINS]; | ||
29 | #define QE_PIN_REQUESTED 0 | ||
30 | |||
27 | /* shadowed data register to clear/set bits safely */ | 31 | /* shadowed data register to clear/set bits safely */ |
28 | u32 cpdata; | 32 | u32 cpdata; |
33 | |||
34 | /* saved_regs used to restore dedicated functions */ | ||
35 | struct qe_pio_regs saved_regs; | ||
29 | }; | 36 | }; |
30 | 37 | ||
31 | static inline struct qe_gpio_chip * | 38 | static inline struct qe_gpio_chip * |
@@ -40,6 +47,12 @@ static void qe_gpio_save_regs(struct of_mm_gpio_chip *mm_gc) | |||
40 | struct qe_pio_regs __iomem *regs = mm_gc->regs; | 47 | struct qe_pio_regs __iomem *regs = mm_gc->regs; |
41 | 48 | ||
42 | qe_gc->cpdata = in_be32(®s->cpdata); | 49 | qe_gc->cpdata = in_be32(®s->cpdata); |
50 | qe_gc->saved_regs.cpdata = qe_gc->cpdata; | ||
51 | qe_gc->saved_regs.cpdir1 = in_be32(®s->cpdir1); | ||
52 | qe_gc->saved_regs.cpdir2 = in_be32(®s->cpdir2); | ||
53 | qe_gc->saved_regs.cppar1 = in_be32(®s->cppar1); | ||
54 | qe_gc->saved_regs.cppar2 = in_be32(®s->cppar2); | ||
55 | qe_gc->saved_regs.cpodr = in_be32(®s->cpodr); | ||
43 | } | 56 | } |
44 | 57 | ||
45 | static int qe_gpio_get(struct gpio_chip *gc, unsigned int gpio) | 58 | static int qe_gpio_get(struct gpio_chip *gc, unsigned int gpio) |
@@ -103,6 +116,188 @@ static int qe_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | |||
103 | return 0; | 116 | return 0; |
104 | } | 117 | } |
105 | 118 | ||
119 | struct qe_pin { | ||
120 | /* | ||
121 | * The qe_gpio_chip name is unfortunate, we should change that to | ||
122 | * something like qe_pio_controller. Someday. | ||
123 | */ | ||
124 | struct qe_gpio_chip *controller; | ||
125 | int num; | ||
126 | }; | ||
127 | |||
128 | /** | ||
129 | * qe_pin_request - Request a QE pin | ||
130 | * @np: device node to get a pin from | ||
131 | * @index: index of a pin in the device tree | ||
132 | * Context: non-atomic | ||
133 | * | ||
134 | * This function return qe_pin so that you could use it with the rest of | ||
135 | * the QE Pin Multiplexing API. | ||
136 | */ | ||
137 | struct qe_pin *qe_pin_request(struct device_node *np, int index) | ||
138 | { | ||
139 | struct qe_pin *qe_pin; | ||
140 | struct device_node *gc; | ||
141 | struct of_gpio_chip *of_gc = NULL; | ||
142 | struct of_mm_gpio_chip *mm_gc; | ||
143 | struct qe_gpio_chip *qe_gc; | ||
144 | int err; | ||
145 | int size; | ||
146 | const void *gpio_spec; | ||
147 | const u32 *gpio_cells; | ||
148 | unsigned long flags; | ||
149 | |||
150 | qe_pin = kzalloc(sizeof(*qe_pin), GFP_KERNEL); | ||
151 | if (!qe_pin) { | ||
152 | pr_debug("%s: can't allocate memory\n", __func__); | ||
153 | return ERR_PTR(-ENOMEM); | ||
154 | } | ||
155 | |||
156 | err = of_parse_phandles_with_args(np, "gpios", "#gpio-cells", index, | ||
157 | &gc, &gpio_spec); | ||
158 | if (err) { | ||
159 | pr_debug("%s: can't parse gpios property\n", __func__); | ||
160 | goto err0; | ||
161 | } | ||
162 | |||
163 | if (!of_device_is_compatible(gc, "fsl,mpc8323-qe-pario-bank")) { | ||
164 | pr_debug("%s: tried to get a non-qe pin\n", __func__); | ||
165 | err = -EINVAL; | ||
166 | goto err1; | ||
167 | } | ||
168 | |||
169 | of_gc = gc->data; | ||
170 | if (!of_gc) { | ||
171 | pr_debug("%s: gpio controller %s isn't registered\n", | ||
172 | np->full_name, gc->full_name); | ||
173 | err = -ENODEV; | ||
174 | goto err1; | ||
175 | } | ||
176 | |||
177 | gpio_cells = of_get_property(gc, "#gpio-cells", &size); | ||
178 | if (!gpio_cells || size != sizeof(*gpio_cells) || | ||
179 | *gpio_cells != of_gc->gpio_cells) { | ||
180 | pr_debug("%s: wrong #gpio-cells for %s\n", | ||
181 | np->full_name, gc->full_name); | ||
182 | err = -EINVAL; | ||
183 | goto err1; | ||
184 | } | ||
185 | |||
186 | err = of_gc->xlate(of_gc, np, gpio_spec, NULL); | ||
187 | if (err < 0) | ||
188 | goto err1; | ||
189 | |||
190 | mm_gc = to_of_mm_gpio_chip(&of_gc->gc); | ||
191 | qe_gc = to_qe_gpio_chip(mm_gc); | ||
192 | |||
193 | spin_lock_irqsave(&qe_gc->lock, flags); | ||
194 | |||
195 | if (test_and_set_bit(QE_PIN_REQUESTED, &qe_gc->pin_flags[err]) == 0) { | ||
196 | qe_pin->controller = qe_gc; | ||
197 | qe_pin->num = err; | ||
198 | err = 0; | ||
199 | } else { | ||
200 | err = -EBUSY; | ||
201 | } | ||
202 | |||
203 | spin_unlock_irqrestore(&qe_gc->lock, flags); | ||
204 | |||
205 | if (!err) | ||
206 | return qe_pin; | ||
207 | err1: | ||
208 | of_node_put(gc); | ||
209 | err0: | ||
210 | kfree(qe_pin); | ||
211 | pr_debug("%s failed with status %d\n", __func__, err); | ||
212 | return ERR_PTR(err); | ||
213 | } | ||
214 | EXPORT_SYMBOL(qe_pin_request); | ||
215 | |||
216 | /** | ||
217 | * qe_pin_free - Free a pin | ||
218 | * @qe_pin: pointer to the qe_pin structure | ||
219 | * Context: any | ||
220 | * | ||
221 | * This function frees the qe_pin structure and makes a pin available | ||
222 | * for further qe_pin_request() calls. | ||
223 | */ | ||
224 | void qe_pin_free(struct qe_pin *qe_pin) | ||
225 | { | ||
226 | struct qe_gpio_chip *qe_gc = qe_pin->controller; | ||
227 | unsigned long flags; | ||
228 | const int pin = qe_pin->num; | ||
229 | |||
230 | spin_lock_irqsave(&qe_gc->lock, flags); | ||
231 | test_and_clear_bit(QE_PIN_REQUESTED, &qe_gc->pin_flags[pin]); | ||
232 | spin_unlock_irqrestore(&qe_gc->lock, flags); | ||
233 | |||
234 | kfree(qe_pin); | ||
235 | } | ||
236 | EXPORT_SYMBOL(qe_pin_free); | ||
237 | |||
238 | /** | ||
239 | * qe_pin_set_dedicated - Revert a pin to a dedicated peripheral function mode | ||
240 | * @qe_pin: pointer to the qe_pin structure | ||
241 | * Context: any | ||
242 | * | ||
243 | * This function resets a pin to a dedicated peripheral function that | ||
244 | * has been set up by the firmware. | ||
245 | */ | ||
246 | void qe_pin_set_dedicated(struct qe_pin *qe_pin) | ||
247 | { | ||
248 | struct qe_gpio_chip *qe_gc = qe_pin->controller; | ||
249 | struct qe_pio_regs __iomem *regs = qe_gc->mm_gc.regs; | ||
250 | struct qe_pio_regs *sregs = &qe_gc->saved_regs; | ||
251 | int pin = qe_pin->num; | ||
252 | u32 mask1 = 1 << (QE_PIO_PINS - (pin + 1)); | ||
253 | u32 mask2 = 0x3 << (QE_PIO_PINS - (pin % (QE_PIO_PINS / 2) + 1) * 2); | ||
254 | bool second_reg = pin > (QE_PIO_PINS / 2) - 1; | ||
255 | unsigned long flags; | ||
256 | |||
257 | spin_lock_irqsave(&qe_gc->lock, flags); | ||
258 | |||
259 | if (second_reg) { | ||
260 | clrsetbits_be32(®s->cpdir2, mask2, sregs->cpdir2 & mask2); | ||
261 | clrsetbits_be32(®s->cppar2, mask2, sregs->cppar2 & mask2); | ||
262 | } else { | ||
263 | clrsetbits_be32(®s->cpdir1, mask2, sregs->cpdir1 & mask2); | ||
264 | clrsetbits_be32(®s->cppar1, mask2, sregs->cppar1 & mask2); | ||
265 | } | ||
266 | |||
267 | if (sregs->cpdata & mask1) | ||
268 | qe_gc->cpdata |= mask1; | ||
269 | else | ||
270 | qe_gc->cpdata &= ~mask1; | ||
271 | |||
272 | out_be32(®s->cpdata, qe_gc->cpdata); | ||
273 | clrsetbits_be32(®s->cpodr, mask1, sregs->cpodr & mask1); | ||
274 | |||
275 | spin_unlock_irqrestore(&qe_gc->lock, flags); | ||
276 | } | ||
277 | EXPORT_SYMBOL(qe_pin_set_dedicated); | ||
278 | |||
279 | /** | ||
280 | * qe_pin_set_gpio - Set a pin to the GPIO mode | ||
281 | * @qe_pin: pointer to the qe_pin structure | ||
282 | * Context: any | ||
283 | * | ||
284 | * This function sets a pin to the GPIO mode. | ||
285 | */ | ||
286 | void qe_pin_set_gpio(struct qe_pin *qe_pin) | ||
287 | { | ||
288 | struct qe_gpio_chip *qe_gc = qe_pin->controller; | ||
289 | struct qe_pio_regs __iomem *regs = qe_gc->mm_gc.regs; | ||
290 | unsigned long flags; | ||
291 | |||
292 | spin_lock_irqsave(&qe_gc->lock, flags); | ||
293 | |||
294 | /* Let's make it input by default, GPIO API is able to change that. */ | ||
295 | __par_io_config_pin(regs, qe_pin->num, QE_PIO_DIR_IN, 0, 0, 0); | ||
296 | |||
297 | spin_unlock_irqrestore(&qe_gc->lock, flags); | ||
298 | } | ||
299 | EXPORT_SYMBOL(qe_pin_set_gpio); | ||
300 | |||
106 | static int __init qe_add_gpiochips(void) | 301 | static int __init qe_add_gpiochips(void) |
107 | { | 302 | { |
108 | struct device_node *np; | 303 | struct device_node *np; |
diff --git a/arch/powerpc/sysdev/simple_gpio.c b/arch/powerpc/sysdev/simple_gpio.c new file mode 100644 index 000000000000..43c4569e24b7 --- /dev/null +++ b/arch/powerpc/sysdev/simple_gpio.c | |||
@@ -0,0 +1,155 @@ | |||
1 | /* | ||
2 | * Simple Memory-Mapped GPIOs | ||
3 | * | ||
4 | * Copyright (c) MontaVista Software, Inc. 2008. | ||
5 | * | ||
6 | * Author: Anton Vorontsov <avorontsov@ru.mvista.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/init.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/spinlock.h> | ||
18 | #include <linux/types.h> | ||
19 | #include <linux/ioport.h> | ||
20 | #include <linux/io.h> | ||
21 | #include <linux/of.h> | ||
22 | #include <linux/of_gpio.h> | ||
23 | #include <linux/gpio.h> | ||
24 | #include <asm/prom.h> | ||
25 | #include "simple_gpio.h" | ||
26 | |||
27 | struct u8_gpio_chip { | ||
28 | struct of_mm_gpio_chip mm_gc; | ||
29 | spinlock_t lock; | ||
30 | |||
31 | /* shadowed data register to clear/set bits safely */ | ||
32 | u8 data; | ||
33 | }; | ||
34 | |||
35 | static struct u8_gpio_chip *to_u8_gpio_chip(struct of_mm_gpio_chip *mm_gc) | ||
36 | { | ||
37 | return container_of(mm_gc, struct u8_gpio_chip, mm_gc); | ||
38 | } | ||
39 | |||
40 | static u8 u8_pin2mask(unsigned int pin) | ||
41 | { | ||
42 | return 1 << (8 - 1 - pin); | ||
43 | } | ||
44 | |||
45 | static int u8_gpio_get(struct gpio_chip *gc, unsigned int gpio) | ||
46 | { | ||
47 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
48 | |||
49 | return in_8(mm_gc->regs) & u8_pin2mask(gpio); | ||
50 | } | ||
51 | |||
52 | static void u8_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) | ||
53 | { | ||
54 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
55 | struct u8_gpio_chip *u8_gc = to_u8_gpio_chip(mm_gc); | ||
56 | unsigned long flags; | ||
57 | |||
58 | spin_lock_irqsave(&u8_gc->lock, flags); | ||
59 | |||
60 | if (val) | ||
61 | u8_gc->data |= u8_pin2mask(gpio); | ||
62 | else | ||
63 | u8_gc->data &= ~u8_pin2mask(gpio); | ||
64 | |||
65 | out_8(mm_gc->regs, u8_gc->data); | ||
66 | |||
67 | spin_unlock_irqrestore(&u8_gc->lock, flags); | ||
68 | } | ||
69 | |||
70 | static int u8_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) | ||
71 | { | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | static int u8_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | ||
76 | { | ||
77 | u8_gpio_set(gc, gpio, val); | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static void u8_gpio_save_regs(struct of_mm_gpio_chip *mm_gc) | ||
82 | { | ||
83 | struct u8_gpio_chip *u8_gc = to_u8_gpio_chip(mm_gc); | ||
84 | |||
85 | u8_gc->data = in_8(mm_gc->regs); | ||
86 | } | ||
87 | |||
88 | static int __init u8_simple_gpiochip_add(struct device_node *np) | ||
89 | { | ||
90 | int ret; | ||
91 | struct u8_gpio_chip *u8_gc; | ||
92 | struct of_mm_gpio_chip *mm_gc; | ||
93 | struct of_gpio_chip *of_gc; | ||
94 | struct gpio_chip *gc; | ||
95 | |||
96 | u8_gc = kzalloc(sizeof(*u8_gc), GFP_KERNEL); | ||
97 | if (!u8_gc) | ||
98 | return -ENOMEM; | ||
99 | |||
100 | spin_lock_init(&u8_gc->lock); | ||
101 | |||
102 | mm_gc = &u8_gc->mm_gc; | ||
103 | of_gc = &mm_gc->of_gc; | ||
104 | gc = &of_gc->gc; | ||
105 | |||
106 | mm_gc->save_regs = u8_gpio_save_regs; | ||
107 | of_gc->gpio_cells = 2; | ||
108 | gc->ngpio = 8; | ||
109 | gc->direction_input = u8_gpio_dir_in; | ||
110 | gc->direction_output = u8_gpio_dir_out; | ||
111 | gc->get = u8_gpio_get; | ||
112 | gc->set = u8_gpio_set; | ||
113 | |||
114 | ret = of_mm_gpiochip_add(np, mm_gc); | ||
115 | if (ret) | ||
116 | goto err; | ||
117 | return 0; | ||
118 | err: | ||
119 | kfree(u8_gc); | ||
120 | return ret; | ||
121 | } | ||
122 | |||
123 | void __init simple_gpiochip_init(const char *compatible) | ||
124 | { | ||
125 | struct device_node *np; | ||
126 | |||
127 | for_each_compatible_node(np, NULL, compatible) { | ||
128 | int ret; | ||
129 | struct resource r; | ||
130 | |||
131 | ret = of_address_to_resource(np, 0, &r); | ||
132 | if (ret) | ||
133 | goto err; | ||
134 | |||
135 | switch (resource_size(&r)) { | ||
136 | case 1: | ||
137 | ret = u8_simple_gpiochip_add(np); | ||
138 | if (ret) | ||
139 | goto err; | ||
140 | break; | ||
141 | default: | ||
142 | /* | ||
143 | * Whenever you need support for GPIO bank width > 1, | ||
144 | * please just turn u8_ code into huge macros, and | ||
145 | * construct needed uX_ code with it. | ||
146 | */ | ||
147 | ret = -ENOSYS; | ||
148 | goto err; | ||
149 | } | ||
150 | continue; | ||
151 | err: | ||
152 | pr_err("%s: registration failed, status %d\n", | ||
153 | np->full_name, ret); | ||
154 | } | ||
155 | } | ||
diff --git a/arch/powerpc/sysdev/simple_gpio.h b/arch/powerpc/sysdev/simple_gpio.h new file mode 100644 index 000000000000..3a7b0c513c76 --- /dev/null +++ b/arch/powerpc/sysdev/simple_gpio.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifndef __SYSDEV_SIMPLE_GPIO_H | ||
2 | #define __SYSDEV_SIMPLE_GPIO_H | ||
3 | |||
4 | #include <linux/errno.h> | ||
5 | |||
6 | #ifdef CONFIG_SIMPLE_GPIO | ||
7 | extern void simple_gpiochip_init(const char *compatible); | ||
8 | #else | ||
9 | static inline void simple_gpiochip_init(const char *compatible) {} | ||
10 | #endif /* CONFIG_SIMPLE_GPIO */ | ||
11 | |||
12 | #endif /* __SYSDEV_SIMPLE_GPIO_H */ | ||