diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-08 12:10:16 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-08 12:10:16 -0500 |
| commit | 85da1fb545e5fe51c35e0576f71780cc557f4277 (patch) | |
| tree | 59566f93ed45a4c8481b43aadff784c80aebacdc | |
| parent | 73ac36ea14fd18ea3dc057e41b16ff31a3c0bd5a (diff) | |
| parent | 5886188dc7ba9a76babcd37452f44079a9a77f71 (diff) | |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (53 commits)
serial: Add driver for the Cell Network Processor serial port NWP device
powerpc: enable dynamic ftrace
powerpc/cell: Fix the prototype of create_vma_map()
powerpc/mm: Make clear_fixmap() actually work
powerpc/kdump: Use ppc_save_regs() in crash_setup_regs()
powerpc: Export cacheable_memzero as its now used in a driver
powerpc: Fix missing semicolons in mmu_decl.h
powerpc/pasemi: local_irq_save uses an unsigned long
powerpc/cell: Fix some u64 vs. long types
powerpc/cell: Use correct types in beat files
powerpc: Use correct type in prom_init.c
powerpc: Remove unnecessary casts
mtd/ps3vram: Use _PAGE_NO_CACHE in memory ioremap
mtd/ps3vram: Use msleep in waits
mtd/ps3vram: Use proper kernel types
mtd/ps3vram: Cleanup ps3vram driver messages
mtd/ps3vram: Remove ps3vram debug routines
mtd/ps3vram: Add modalias support to the ps3vram driver
mtd/ps3vram: Add ps3vram driver for accessing video RAM as MTD
powerpc: Fix iseries drivers build failure without CONFIG_VIOPATH
...
74 files changed, 3089 insertions, 502 deletions
diff --git a/Documentation/powerpc/dts-bindings/fsl/board.txt b/Documentation/powerpc/dts-bindings/fsl/board.txt index 81a917ef96e9..6c974d28eeb4 100644 --- a/Documentation/powerpc/dts-bindings/fsl/board.txt +++ b/Documentation/powerpc/dts-bindings/fsl/board.txt | |||
| @@ -18,7 +18,7 @@ This is the memory-mapped registers for on board FPGA. | |||
| 18 | 18 | ||
| 19 | Required properities: | 19 | Required properities: |
| 20 | - compatible : should be "fsl,fpga-pixis". | 20 | - compatible : should be "fsl,fpga-pixis". |
| 21 | - reg : should contain the address and the lenght of the FPPGA register | 21 | - reg : should contain the address and the length of the FPPGA register |
| 22 | set. | 22 | set. |
| 23 | 23 | ||
| 24 | Example (MPC8610HPCD): | 24 | Example (MPC8610HPCD): |
| @@ -27,3 +27,33 @@ Example (MPC8610HPCD): | |||
| 27 | compatible = "fsl,fpga-pixis"; | 27 | compatible = "fsl,fpga-pixis"; |
| 28 | reg = <0xe8000000 32>; | 28 | reg = <0xe8000000 32>; |
| 29 | }; | 29 | }; |
| 30 | |||
| 31 | * Freescale BCSR GPIO banks | ||
| 32 | |||
| 33 | Some BCSR registers act as simple GPIO controllers, each such | ||
| 34 | register can be represented by the gpio-controller node. | ||
| 35 | |||
| 36 | Required properities: | ||
| 37 | - compatible : Should be "fsl,<board>-bcsr-gpio". | ||
| 38 | - reg : Should contain the address and the length of the GPIO bank | ||
| 39 | register. | ||
| 40 | - #gpio-cells : Should be two. The first cell is the pin number and the | ||
| 41 | second cell is used to specify optional paramters (currently unused). | ||
| 42 | - gpio-controller : Marks the port as GPIO controller. | ||
| 43 | |||
| 44 | Example: | ||
| 45 | |||
| 46 | bcsr@1,0 { | ||
| 47 | #address-cells = <1>; | ||
| 48 | #size-cells = <1>; | ||
| 49 | compatible = "fsl,mpc8360mds-bcsr"; | ||
| 50 | reg = <1 0 0x8000>; | ||
| 51 | ranges = <0 1 0 0x8000>; | ||
| 52 | |||
| 53 | bcsr13: gpio-controller@d { | ||
| 54 | #gpio-cells = <2>; | ||
| 55 | compatible = "fsl,mpc8360mds-bcsr-gpio"; | ||
| 56 | reg = <0xd 1>; | ||
| 57 | gpio-controller; | ||
| 58 | }; | ||
| 59 | }; | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 4bb5d4be8105..57e0309243cc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -3489,6 +3489,12 @@ L: linuxppc-dev@ozlabs.org | |||
| 3489 | L: cbe-oss-dev@ozlabs.org | 3489 | L: cbe-oss-dev@ozlabs.org |
| 3490 | S: Supported | 3490 | S: Supported |
| 3491 | 3491 | ||
| 3492 | PS3VRAM DRIVER | ||
| 3493 | P: Jim Paris | ||
| 3494 | M: jim@jtan.com | ||
| 3495 | L: cbe-oss-dev@ozlabs.org | ||
| 3496 | S: Maintained | ||
| 3497 | |||
| 3492 | PVRUSB2 VIDEO4LINUX DRIVER | 3498 | PVRUSB2 VIDEO4LINUX DRIVER |
| 3493 | P: Mike Isely | 3499 | P: Mike Isely |
| 3494 | M: isely@pobox.com | 3500 | M: isely@pobox.com |
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/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/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/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..dfdbffa06818 100644 --- a/arch/powerpc/oprofile/cell/pr_util.h +++ b/arch/powerpc/oprofile/cell/pr_util.h | |||
| @@ -79,7 +79,7 @@ struct spu_buffer { | |||
| 79 | * the vma-to-fileoffset map. | 79 | * the vma-to-fileoffset map. |
| 80 | */ | 80 | */ |
| 81 | struct vma_to_fileoffset_map *create_vma_map(const struct spu *spu, | 81 | struct vma_to_fileoffset_map *create_vma_map(const struct spu *spu, |
| 82 | u64 objectid); | 82 | unsigned long objectid); |
| 83 | unsigned int vma_map_lookup(struct vma_to_fileoffset_map *map, | 83 | unsigned int vma_map_lookup(struct vma_to_fileoffset_map *map, |
| 84 | unsigned int vma, const struct spu *aSpu, | 84 | unsigned int vma, const struct spu *aSpu, |
| 85 | int *grd_val); | 85 | int *grd_val); |
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_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/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/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..86db47c1b665 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)) |
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/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 */ | ||
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 35914b6e1d2a..f5be8081cd81 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
| @@ -616,6 +616,7 @@ config HVC_ISERIES | |||
| 616 | default y | 616 | default y |
| 617 | select HVC_DRIVER | 617 | select HVC_DRIVER |
| 618 | select HVC_IRQ | 618 | select HVC_IRQ |
| 619 | select VIOPATH | ||
| 619 | help | 620 | help |
| 620 | iSeries machines support a hypervisor virtual console. | 621 | iSeries machines support a hypervisor virtual console. |
| 621 | 622 | ||
diff --git a/drivers/char/hvc_beat.c b/drivers/char/hvc_beat.c index 91cdb35a9204..0afc8b82212e 100644 --- a/drivers/char/hvc_beat.c +++ b/drivers/char/hvc_beat.c | |||
| @@ -44,7 +44,7 @@ static int hvc_beat_get_chars(uint32_t vtermno, char *buf, int cnt) | |||
| 44 | static unsigned char q[sizeof(unsigned long) * 2] | 44 | static unsigned char q[sizeof(unsigned long) * 2] |
| 45 | __attribute__((aligned(sizeof(unsigned long)))); | 45 | __attribute__((aligned(sizeof(unsigned long)))); |
| 46 | static int qlen = 0; | 46 | static int qlen = 0; |
| 47 | unsigned long got; | 47 | u64 got; |
| 48 | 48 | ||
| 49 | again: | 49 | again: |
| 50 | if (qlen) { | 50 | if (qlen) { |
| @@ -63,7 +63,7 @@ again: | |||
| 63 | } | 63 | } |
| 64 | } | 64 | } |
| 65 | if (beat_get_term_char(vtermno, &got, | 65 | if (beat_get_term_char(vtermno, &got, |
| 66 | ((unsigned long *)q), ((unsigned long *)q) + 1) == 0) { | 66 | ((u64 *)q), ((u64 *)q) + 1) == 0) { |
| 67 | qlen = got; | 67 | qlen = got; |
| 68 | goto again; | 68 | goto again; |
| 69 | } | 69 | } |
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 6fde0a2e3567..bc33200535fc 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig | |||
| @@ -120,6 +120,13 @@ config MTD_PHRAM | |||
| 120 | doesn't have access to, memory beyond the mem=xxx limit, nvram, | 120 | doesn't have access to, memory beyond the mem=xxx limit, nvram, |
| 121 | memory on the video card, etc... | 121 | memory on the video card, etc... |
| 122 | 122 | ||
| 123 | config MTD_PS3VRAM | ||
| 124 | tristate "PS3 video RAM" | ||
| 125 | depends on FB_PS3 | ||
| 126 | help | ||
| 127 | This driver allows you to use excess PS3 video RAM as volatile | ||
| 128 | storage or system swap. | ||
| 129 | |||
| 123 | config MTD_LART | 130 | config MTD_LART |
| 124 | tristate "28F160xx flash driver for LART" | 131 | tristate "28F160xx flash driver for LART" |
| 125 | depends on SA1100_LART | 132 | depends on SA1100_LART |
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index 0993d5cf3923..e51521df4e40 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile | |||
| @@ -16,3 +16,4 @@ obj-$(CONFIG_MTD_LART) += lart.o | |||
| 16 | obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o | 16 | obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o |
| 17 | obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o | 17 | obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o |
| 18 | obj-$(CONFIG_MTD_M25P80) += m25p80.o | 18 | obj-$(CONFIG_MTD_M25P80) += m25p80.o |
| 19 | obj-$(CONFIG_MTD_PS3VRAM) += ps3vram.o | ||
diff --git a/drivers/mtd/devices/ps3vram.c b/drivers/mtd/devices/ps3vram.c new file mode 100644 index 000000000000..d21e9beb7ed2 --- /dev/null +++ b/drivers/mtd/devices/ps3vram.c | |||
| @@ -0,0 +1,768 @@ | |||
| 1 | /** | ||
| 2 | * ps3vram - Use extra PS3 video ram as MTD block device. | ||
| 3 | * | ||
| 4 | * Copyright (c) 2007-2008 Jim Paris <jim@jtan.com> | ||
| 5 | * Added support RSX DMA Vivien Chappelier <vivien.chappelier@free.fr> | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/io.h> | ||
| 9 | #include <linux/mm.h> | ||
| 10 | #include <linux/init.h> | ||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/list.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/moduleparam.h> | ||
| 15 | #include <linux/slab.h> | ||
| 16 | #include <linux/version.h> | ||
| 17 | #include <linux/gfp.h> | ||
| 18 | #include <linux/delay.h> | ||
| 19 | #include <linux/mtd/mtd.h> | ||
| 20 | |||
| 21 | #include <asm/lv1call.h> | ||
| 22 | #include <asm/ps3.h> | ||
| 23 | |||
| 24 | #define DEVICE_NAME "ps3vram" | ||
| 25 | |||
| 26 | #define XDR_BUF_SIZE (2 * 1024 * 1024) /* XDR buffer (must be 1MiB aligned) */ | ||
| 27 | #define XDR_IOIF 0x0c000000 | ||
| 28 | |||
| 29 | #define FIFO_BASE XDR_IOIF | ||
| 30 | #define FIFO_SIZE (64 * 1024) | ||
| 31 | |||
| 32 | #define DMA_PAGE_SIZE (4 * 1024) | ||
| 33 | |||
| 34 | #define CACHE_PAGE_SIZE (256 * 1024) | ||
| 35 | #define CACHE_PAGE_COUNT ((XDR_BUF_SIZE - FIFO_SIZE) / CACHE_PAGE_SIZE) | ||
| 36 | |||
| 37 | #define CACHE_OFFSET CACHE_PAGE_SIZE | ||
| 38 | #define FIFO_OFFSET 0 | ||
| 39 | |||
| 40 | #define CTRL_PUT 0x10 | ||
| 41 | #define CTRL_GET 0x11 | ||
| 42 | #define CTRL_TOP 0x15 | ||
| 43 | |||
| 44 | #define UPLOAD_SUBCH 1 | ||
| 45 | #define DOWNLOAD_SUBCH 2 | ||
| 46 | |||
| 47 | #define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN 0x0000030c | ||
| 48 | #define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY 0x00000104 | ||
| 49 | |||
| 50 | #define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT 0x601 | ||
| 51 | |||
| 52 | struct mtd_info ps3vram_mtd; | ||
| 53 | |||
| 54 | #define CACHE_PAGE_PRESENT 1 | ||
| 55 | #define CACHE_PAGE_DIRTY 2 | ||
| 56 | |||
| 57 | struct ps3vram_tag { | ||
| 58 | unsigned int address; | ||
| 59 | unsigned int flags; | ||
| 60 | }; | ||
| 61 | |||
| 62 | struct ps3vram_cache { | ||
| 63 | unsigned int page_count; | ||
| 64 | unsigned int page_size; | ||
| 65 | struct ps3vram_tag *tags; | ||
| 66 | }; | ||
| 67 | |||
| 68 | struct ps3vram_priv { | ||
| 69 | u64 memory_handle; | ||
| 70 | u64 context_handle; | ||
| 71 | u32 *ctrl; | ||
| 72 | u32 *reports; | ||
| 73 | u8 __iomem *ddr_base; | ||
| 74 | u8 *xdr_buf; | ||
| 75 | |||
| 76 | u32 *fifo_base; | ||
| 77 | u32 *fifo_ptr; | ||
| 78 | |||
| 79 | struct device *dev; | ||
| 80 | struct ps3vram_cache cache; | ||
| 81 | |||
| 82 | /* Used to serialize cache/DMA operations */ | ||
| 83 | struct mutex lock; | ||
| 84 | }; | ||
| 85 | |||
| 86 | #define DMA_NOTIFIER_HANDLE_BASE 0x66604200 /* first DMA notifier handle */ | ||
| 87 | #define DMA_NOTIFIER_OFFSET_BASE 0x1000 /* first DMA notifier offset */ | ||
| 88 | #define DMA_NOTIFIER_SIZE 0x40 | ||
| 89 | #define NOTIFIER 7 /* notifier used for completion report */ | ||
| 90 | |||
| 91 | /* A trailing '-' means to subtract off ps3fb_videomemory.size */ | ||
| 92 | char *size = "256M-"; | ||
| 93 | module_param(size, charp, 0); | ||
| 94 | MODULE_PARM_DESC(size, "memory size"); | ||
| 95 | |||
| 96 | static u32 *ps3vram_get_notifier(u32 *reports, int notifier) | ||
| 97 | { | ||
| 98 | return (void *) reports + | ||
| 99 | DMA_NOTIFIER_OFFSET_BASE + | ||
| 100 | DMA_NOTIFIER_SIZE * notifier; | ||
| 101 | } | ||
| 102 | |||
| 103 | static void ps3vram_notifier_reset(struct mtd_info *mtd) | ||
| 104 | { | ||
| 105 | int i; | ||
| 106 | |||
| 107 | struct ps3vram_priv *priv = mtd->priv; | ||
| 108 | u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); | ||
| 109 | for (i = 0; i < 4; i++) | ||
| 110 | notify[i] = 0xffffffff; | ||
| 111 | } | ||
| 112 | |||
| 113 | static int ps3vram_notifier_wait(struct mtd_info *mtd, unsigned int timeout_ms) | ||
| 114 | { | ||
| 115 | struct ps3vram_priv *priv = mtd->priv; | ||
| 116 | u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); | ||
| 117 | unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); | ||
| 118 | |||
| 119 | do { | ||
| 120 | if (!notify[3]) | ||
| 121 | return 0; | ||
| 122 | msleep(1); | ||
| 123 | } while (time_before(jiffies, timeout)); | ||
| 124 | |||
| 125 | return -ETIMEDOUT; | ||
| 126 | } | ||
| 127 | |||
| 128 | static void ps3vram_init_ring(struct mtd_info *mtd) | ||
| 129 | { | ||
| 130 | struct ps3vram_priv *priv = mtd->priv; | ||
| 131 | |||
| 132 | priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET; | ||
| 133 | priv->ctrl[CTRL_GET] = FIFO_BASE + FIFO_OFFSET; | ||
| 134 | } | ||
| 135 | |||
| 136 | static int ps3vram_wait_ring(struct mtd_info *mtd, unsigned int timeout_ms) | ||
| 137 | { | ||
| 138 | struct ps3vram_priv *priv = mtd->priv; | ||
| 139 | unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); | ||
| 140 | |||
| 141 | do { | ||
| 142 | if (priv->ctrl[CTRL_PUT] == priv->ctrl[CTRL_GET]) | ||
| 143 | return 0; | ||
| 144 | msleep(1); | ||
| 145 | } while (time_before(jiffies, timeout)); | ||
| 146 | |||
| 147 | dev_dbg(priv->dev, "%s:%d: FIFO timeout (%08x/%08x/%08x)\n", __func__, | ||
| 148 | __LINE__, priv->ctrl[CTRL_PUT], priv->ctrl[CTRL_GET], | ||
| 149 | priv->ctrl[CTRL_TOP]); | ||
| 150 | |||
| 151 | return -ETIMEDOUT; | ||
| 152 | } | ||
| 153 | |||
| 154 | static void ps3vram_out_ring(struct ps3vram_priv *priv, u32 data) | ||
| 155 | { | ||
| 156 | *(priv->fifo_ptr)++ = data; | ||
| 157 | } | ||
| 158 | |||
| 159 | static void ps3vram_begin_ring(struct ps3vram_priv *priv, u32 chan, | ||
| 160 | u32 tag, u32 size) | ||
| 161 | { | ||
| 162 | ps3vram_out_ring(priv, (size << 18) | (chan << 13) | tag); | ||
| 163 | } | ||
| 164 | |||
| 165 | static void ps3vram_rewind_ring(struct mtd_info *mtd) | ||
| 166 | { | ||
| 167 | struct ps3vram_priv *priv = mtd->priv; | ||
| 168 | u64 status; | ||
| 169 | |||
| 170 | ps3vram_out_ring(priv, 0x20000000 | (FIFO_BASE + FIFO_OFFSET)); | ||
| 171 | |||
| 172 | priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET; | ||
| 173 | |||
| 174 | /* asking the HV for a blit will kick the fifo */ | ||
| 175 | status = lv1_gpu_context_attribute(priv->context_handle, | ||
| 176 | L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, | ||
| 177 | 0, 0, 0, 0); | ||
| 178 | if (status) | ||
| 179 | dev_err(priv->dev, "%s:%d: lv1_gpu_context_attribute failed\n", | ||
| 180 | __func__, __LINE__); | ||
| 181 | |||
| 182 | priv->fifo_ptr = priv->fifo_base; | ||
| 183 | } | ||
| 184 | |||
| 185 | static void ps3vram_fire_ring(struct mtd_info *mtd) | ||
| 186 | { | ||
| 187 | struct ps3vram_priv *priv = mtd->priv; | ||
| 188 | u64 status; | ||
| 189 | |||
| 190 | mutex_lock(&ps3_gpu_mutex); | ||
| 191 | |||
| 192 | priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET + | ||
| 193 | (priv->fifo_ptr - priv->fifo_base) * sizeof(u32); | ||
| 194 | |||
| 195 | /* asking the HV for a blit will kick the fifo */ | ||
| 196 | status = lv1_gpu_context_attribute(priv->context_handle, | ||
| 197 | L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, | ||
| 198 | 0, 0, 0, 0); | ||
| 199 | if (status) | ||
| 200 | dev_err(priv->dev, "%s:%d: lv1_gpu_context_attribute failed\n", | ||
| 201 | __func__, __LINE__); | ||
| 202 | |||
| 203 | if ((priv->fifo_ptr - priv->fifo_base) * sizeof(u32) > | ||
| 204 | FIFO_SIZE - 1024) { | ||
| 205 | dev_dbg(priv->dev, "%s:%d: fifo full, rewinding\n", __func__, | ||
| 206 | __LINE__); | ||
| 207 | ps3vram_wait_ring(mtd, 200); | ||
| 208 | ps3vram_rewind_ring(mtd); | ||
| 209 | } | ||
| 210 | |||
| 211 | mutex_unlock(&ps3_gpu_mutex); | ||
| 212 | } | ||
| 213 | |||
| 214 | static void ps3vram_bind(struct mtd_info *mtd) | ||
| 215 | { | ||
| 216 | struct ps3vram_priv *priv = mtd->priv; | ||
| 217 | |||
| 218 | ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0, 1); | ||
| 219 | ps3vram_out_ring(priv, 0x31337303); | ||
| 220 | ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x180, 3); | ||
| 221 | ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER); | ||
| 222 | ps3vram_out_ring(priv, 0xfeed0001); /* DMA system RAM instance */ | ||
| 223 | ps3vram_out_ring(priv, 0xfeed0000); /* DMA video RAM instance */ | ||
| 224 | |||
| 225 | ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0, 1); | ||
| 226 | ps3vram_out_ring(priv, 0x3137c0de); | ||
| 227 | ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x180, 3); | ||
| 228 | ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER); | ||
| 229 | ps3vram_out_ring(priv, 0xfeed0000); /* DMA video RAM instance */ | ||
| 230 | ps3vram_out_ring(priv, 0xfeed0001); /* DMA system RAM instance */ | ||
| 231 | |||
| 232 | ps3vram_fire_ring(mtd); | ||
| 233 | } | ||
| 234 | |||
| 235 | static int ps3vram_upload(struct mtd_info *mtd, unsigned int src_offset, | ||
| 236 | unsigned int dst_offset, int len, int count) | ||
| 237 | { | ||
| 238 | struct ps3vram_priv *priv = mtd->priv; | ||
| 239 | |||
| 240 | ps3vram_begin_ring(priv, UPLOAD_SUBCH, | ||
| 241 | NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); | ||
| 242 | ps3vram_out_ring(priv, XDR_IOIF + src_offset); | ||
| 243 | ps3vram_out_ring(priv, dst_offset); | ||
| 244 | ps3vram_out_ring(priv, len); | ||
| 245 | ps3vram_out_ring(priv, len); | ||
| 246 | ps3vram_out_ring(priv, len); | ||
| 247 | ps3vram_out_ring(priv, count); | ||
| 248 | ps3vram_out_ring(priv, (1 << 8) | 1); | ||
| 249 | ps3vram_out_ring(priv, 0); | ||
| 250 | |||
| 251 | ps3vram_notifier_reset(mtd); | ||
| 252 | ps3vram_begin_ring(priv, UPLOAD_SUBCH, | ||
| 253 | NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1); | ||
| 254 | ps3vram_out_ring(priv, 0); | ||
| 255 | ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x100, 1); | ||
| 256 | ps3vram_out_ring(priv, 0); | ||
| 257 | ps3vram_fire_ring(mtd); | ||
| 258 | if (ps3vram_notifier_wait(mtd, 200) < 0) { | ||
| 259 | dev_dbg(priv->dev, "%s:%d: notifier timeout\n", __func__, | ||
| 260 | __LINE__); | ||
| 261 | return -1; | ||
| 262 | } | ||
| 263 | |||
| 264 | return 0; | ||
| 265 | } | ||
| 266 | |||
| 267 | static int ps3vram_download(struct mtd_info *mtd, unsigned int src_offset, | ||
| 268 | unsigned int dst_offset, int len, int count) | ||
| 269 | { | ||
| 270 | struct ps3vram_priv *priv = mtd->priv; | ||
| 271 | |||
| 272 | ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, | ||
| 273 | NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); | ||
| 274 | ps3vram_out_ring(priv, src_offset); | ||
| 275 | ps3vram_out_ring(priv, XDR_IOIF + dst_offset); | ||
| 276 | ps3vram_out_ring(priv, len); | ||
| 277 | ps3vram_out_ring(priv, len); | ||
| 278 | ps3vram_out_ring(priv, len); | ||
| 279 | ps3vram_out_ring(priv, count); | ||
| 280 | ps3vram_out_ring(priv, (1 << 8) | 1); | ||
| 281 | ps3vram_out_ring(priv, 0); | ||
| 282 | |||
| 283 | ps3vram_notifier_reset(mtd); | ||
| 284 | ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, | ||
| 285 | NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1); | ||
| 286 | ps3vram_out_ring(priv, 0); | ||
| 287 | ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x100, 1); | ||
| 288 | ps3vram_out_ring(priv, 0); | ||
| 289 | ps3vram_fire_ring(mtd); | ||
| 290 | if (ps3vram_notifier_wait(mtd, 200) < 0) { | ||
| 291 | dev_dbg(priv->dev, "%s:%d: notifier timeout\n", __func__, | ||
| 292 | __LINE__); | ||
| 293 | return -1; | ||
| 294 | } | ||
| 295 | |||
| 296 | return 0; | ||
| 297 | } | ||
| 298 | |||
| 299 | static void ps3vram_cache_evict(struct mtd_info *mtd, int entry) | ||
| 300 | { | ||
| 301 | struct ps3vram_priv *priv = mtd->priv; | ||
| 302 | struct ps3vram_cache *cache = &priv->cache; | ||
| 303 | |||
| 304 | if (cache->tags[entry].flags & CACHE_PAGE_DIRTY) { | ||
| 305 | dev_dbg(priv->dev, "%s:%d: flushing %d : 0x%08x\n", __func__, | ||
| 306 | __LINE__, entry, cache->tags[entry].address); | ||
| 307 | if (ps3vram_upload(mtd, | ||
| 308 | CACHE_OFFSET + entry * cache->page_size, | ||
| 309 | cache->tags[entry].address, | ||
| 310 | DMA_PAGE_SIZE, | ||
| 311 | cache->page_size / DMA_PAGE_SIZE) < 0) { | ||
| 312 | dev_dbg(priv->dev, "%s:%d: failed to upload from " | ||
| 313 | "0x%x to 0x%x size 0x%x\n", __func__, __LINE__, | ||
| 314 | entry * cache->page_size, | ||
| 315 | cache->tags[entry].address, cache->page_size); | ||
| 316 | } | ||
| 317 | cache->tags[entry].flags &= ~CACHE_PAGE_DIRTY; | ||
| 318 | } | ||
| 319 | } | ||
| 320 | |||
| 321 | static void ps3vram_cache_load(struct mtd_info *mtd, int entry, | ||
| 322 | unsigned int address) | ||
| 323 | { | ||
| 324 | struct ps3vram_priv *priv = mtd->priv; | ||
| 325 | struct ps3vram_cache *cache = &priv->cache; | ||
| 326 | |||
| 327 | dev_dbg(priv->dev, "%s:%d: fetching %d : 0x%08x\n", __func__, __LINE__, | ||
| 328 | entry, address); | ||
| 329 | if (ps3vram_download(mtd, | ||
| 330 | address, | ||
| 331 | CACHE_OFFSET + entry * cache->page_size, | ||
| 332 | DMA_PAGE_SIZE, | ||
| 333 | cache->page_size / DMA_PAGE_SIZE) < 0) { | ||
| 334 | dev_err(priv->dev, "%s:%d: failed to download from " | ||
| 335 | "0x%x to 0x%x size 0x%x\n", __func__, __LINE__, address, | ||
| 336 | entry * cache->page_size, cache->page_size); | ||
| 337 | } | ||
| 338 | |||
| 339 | cache->tags[entry].address = address; | ||
| 340 | cache->tags[entry].flags |= CACHE_PAGE_PRESENT; | ||
| 341 | } | ||
| 342 | |||
| 343 | |||
| 344 | static void ps3vram_cache_flush(struct mtd_info *mtd) | ||
| 345 | { | ||
| 346 | struct ps3vram_priv *priv = mtd->priv; | ||
| 347 | struct ps3vram_cache *cache = &priv->cache; | ||
| 348 | int i; | ||
| 349 | |||
| 350 | dev_dbg(priv->dev, "%s:%d: FLUSH\n", __func__, __LINE__); | ||
| 351 | for (i = 0; i < cache->page_count; i++) { | ||
| 352 | ps3vram_cache_evict(mtd, i); | ||
| 353 | cache->tags[i].flags = 0; | ||
| 354 | } | ||
| 355 | } | ||
| 356 | |||
| 357 | static unsigned int ps3vram_cache_match(struct mtd_info *mtd, loff_t address) | ||
| 358 | { | ||
| 359 | struct ps3vram_priv *priv = mtd->priv; | ||
| 360 | struct ps3vram_cache *cache = &priv->cache; | ||
| 361 | unsigned int base; | ||
| 362 | unsigned int offset; | ||
| 363 | int i; | ||
| 364 | static int counter; | ||
| 365 | |||
| 366 | offset = (unsigned int) (address & (cache->page_size - 1)); | ||
| 367 | base = (unsigned int) (address - offset); | ||
| 368 | |||
| 369 | /* fully associative check */ | ||
| 370 | for (i = 0; i < cache->page_count; i++) { | ||
| 371 | if ((cache->tags[i].flags & CACHE_PAGE_PRESENT) && | ||
| 372 | cache->tags[i].address == base) { | ||
| 373 | dev_dbg(priv->dev, "%s:%d: found entry %d : 0x%08x\n", | ||
| 374 | __func__, __LINE__, i, cache->tags[i].address); | ||
| 375 | return i; | ||
| 376 | } | ||
| 377 | } | ||
| 378 | |||
| 379 | /* choose a random entry */ | ||
| 380 | i = (jiffies + (counter++)) % cache->page_count; | ||
| 381 | dev_dbg(priv->dev, "%s:%d: using entry %d\n", __func__, __LINE__, i); | ||
| 382 | |||
| 383 | ps3vram_cache_evict(mtd, i); | ||
| 384 | ps3vram_cache_load(mtd, i, base); | ||
| 385 | |||
| 386 | return i; | ||
| 387 | } | ||
| 388 | |||
| 389 | static int ps3vram_cache_init(struct mtd_info *mtd) | ||
| 390 | { | ||
| 391 | struct ps3vram_priv *priv = mtd->priv; | ||
| 392 | |||
| 393 | priv->cache.page_count = CACHE_PAGE_COUNT; | ||
| 394 | priv->cache.page_size = CACHE_PAGE_SIZE; | ||
| 395 | priv->cache.tags = kzalloc(sizeof(struct ps3vram_tag) * | ||
| 396 | CACHE_PAGE_COUNT, GFP_KERNEL); | ||
| 397 | if (priv->cache.tags == NULL) { | ||
| 398 | dev_err(priv->dev, "%s:%d: could not allocate cache tags\n", | ||
| 399 | __func__, __LINE__); | ||
| 400 | return -ENOMEM; | ||
| 401 | } | ||
| 402 | |||
| 403 | dev_info(priv->dev, "created ram cache: %d entries, %d KiB each\n", | ||
| 404 | CACHE_PAGE_COUNT, CACHE_PAGE_SIZE / 1024); | ||
| 405 | |||
| 406 | return 0; | ||
| 407 | } | ||
| 408 | |||
| 409 | static void ps3vram_cache_cleanup(struct mtd_info *mtd) | ||
| 410 | { | ||
| 411 | struct ps3vram_priv *priv = mtd->priv; | ||
| 412 | |||
| 413 | ps3vram_cache_flush(mtd); | ||
| 414 | kfree(priv->cache.tags); | ||
| 415 | } | ||
| 416 | |||
| 417 | static int ps3vram_erase(struct mtd_info *mtd, struct erase_info *instr) | ||
| 418 | { | ||
| 419 | struct ps3vram_priv *priv = mtd->priv; | ||
| 420 | |||
| 421 | if (instr->addr + instr->len > mtd->size) | ||
| 422 | return -EINVAL; | ||
| 423 | |||
| 424 | mutex_lock(&priv->lock); | ||
| 425 | |||
| 426 | ps3vram_cache_flush(mtd); | ||
| 427 | |||
| 428 | /* Set bytes to 0xFF */ | ||
| 429 | memset_io(priv->ddr_base + instr->addr, 0xFF, instr->len); | ||
| 430 | |||
| 431 | mutex_unlock(&priv->lock); | ||
| 432 | |||
| 433 | instr->state = MTD_ERASE_DONE; | ||
| 434 | mtd_erase_callback(instr); | ||
| 435 | |||
| 436 | return 0; | ||
| 437 | } | ||
| 438 | |||
| 439 | static int ps3vram_read(struct mtd_info *mtd, loff_t from, size_t len, | ||
| 440 | size_t *retlen, u_char *buf) | ||
| 441 | { | ||
| 442 | struct ps3vram_priv *priv = mtd->priv; | ||
| 443 | unsigned int cached, count; | ||
| 444 | |||
| 445 | dev_dbg(priv->dev, "%s:%d: from=0x%08x len=0x%zx\n", __func__, __LINE__, | ||
| 446 | (unsigned int)from, len); | ||
| 447 | |||
| 448 | if (from >= mtd->size) | ||
| 449 | return -EINVAL; | ||
| 450 | |||
| 451 | if (len > mtd->size - from) | ||
| 452 | len = mtd->size - from; | ||
| 453 | |||
| 454 | /* Copy from vram to buf */ | ||
| 455 | count = len; | ||
| 456 | while (count) { | ||
| 457 | unsigned int offset, avail; | ||
| 458 | unsigned int entry; | ||
| 459 | |||
| 460 | offset = (unsigned int) (from & (priv->cache.page_size - 1)); | ||
| 461 | avail = priv->cache.page_size - offset; | ||
| 462 | |||
| 463 | mutex_lock(&priv->lock); | ||
| 464 | |||
| 465 | entry = ps3vram_cache_match(mtd, from); | ||
| 466 | cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; | ||
| 467 | |||
| 468 | dev_dbg(priv->dev, "%s:%d: from=%08x cached=%08x offset=%08x " | ||
| 469 | "avail=%08x count=%08x\n", __func__, __LINE__, | ||
| 470 | (unsigned int)from, cached, offset, avail, count); | ||
| 471 | |||
| 472 | if (avail > count) | ||
| 473 | avail = count; | ||
| 474 | memcpy(buf, priv->xdr_buf + cached, avail); | ||
| 475 | |||
| 476 | mutex_unlock(&priv->lock); | ||
| 477 | |||
| 478 | buf += avail; | ||
| 479 | count -= avail; | ||
| 480 | from += avail; | ||
| 481 | } | ||
| 482 | |||
| 483 | *retlen = len; | ||
| 484 | return 0; | ||
| 485 | } | ||
| 486 | |||
| 487 | static int ps3vram_write(struct mtd_info *mtd, loff_t to, size_t len, | ||
| 488 | size_t *retlen, const u_char *buf) | ||
| 489 | { | ||
| 490 | struct ps3vram_priv *priv = mtd->priv; | ||
| 491 | unsigned int cached, count; | ||
| 492 | |||
| 493 | if (to >= mtd->size) | ||
| 494 | return -EINVAL; | ||
| 495 | |||
| 496 | if (len > mtd->size - to) | ||
| 497 | len = mtd->size - to; | ||
| 498 | |||
| 499 | /* Copy from buf to vram */ | ||
| 500 | count = len; | ||
| 501 | while (count) { | ||
| 502 | unsigned int offset, avail; | ||
| 503 | unsigned int entry; | ||
| 504 | |||
| 505 | offset = (unsigned int) (to & (priv->cache.page_size - 1)); | ||
| 506 | avail = priv->cache.page_size - offset; | ||
| 507 | |||
| 508 | mutex_lock(&priv->lock); | ||
| 509 | |||
| 510 | entry = ps3vram_cache_match(mtd, to); | ||
| 511 | cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; | ||
| 512 | |||
| 513 | dev_dbg(priv->dev, "%s:%d: to=%08x cached=%08x offset=%08x " | ||
| 514 | "avail=%08x count=%08x\n", __func__, __LINE__, | ||
| 515 | (unsigned int)to, cached, offset, avail, count); | ||
| 516 | |||
| 517 | if (avail > count) | ||
| 518 | avail = count; | ||
| 519 | memcpy(priv->xdr_buf + cached, buf, avail); | ||
| 520 | |||
| 521 | priv->cache.tags[entry].flags |= CACHE_PAGE_DIRTY; | ||
| 522 | |||
| 523 | mutex_unlock(&priv->lock); | ||
| 524 | |||
| 525 | buf += avail; | ||
| 526 | count -= avail; | ||
| 527 | to += avail; | ||
| 528 | } | ||
| 529 | |||
| 530 | *retlen = len; | ||
| 531 | return 0; | ||
| 532 | } | ||
| 533 | |||
| 534 | static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev) | ||
| 535 | { | ||
| 536 | struct ps3vram_priv *priv; | ||
| 537 | int status; | ||
| 538 | u64 ddr_lpar; | ||
| 539 | u64 ctrl_lpar; | ||
| 540 | u64 info_lpar; | ||
| 541 | u64 reports_lpar; | ||
| 542 | u64 ddr_size; | ||
| 543 | u64 reports_size; | ||
| 544 | int ret = -ENOMEM; | ||
| 545 | char *rest; | ||
| 546 | |||
| 547 | ret = -EIO; | ||
| 548 | ps3vram_mtd.priv = kzalloc(sizeof(struct ps3vram_priv), GFP_KERNEL); | ||
| 549 | if (!ps3vram_mtd.priv) | ||
| 550 | goto out; | ||
| 551 | priv = ps3vram_mtd.priv; | ||
| 552 | |||
| 553 | mutex_init(&priv->lock); | ||
| 554 | priv->dev = &dev->core; | ||
| 555 | |||
| 556 | /* Allocate XDR buffer (1MiB aligned) */ | ||
| 557 | priv->xdr_buf = (void *)__get_free_pages(GFP_KERNEL, | ||
| 558 | get_order(XDR_BUF_SIZE)); | ||
| 559 | if (priv->xdr_buf == NULL) { | ||
| 560 | dev_dbg(&dev->core, "%s:%d: could not allocate XDR buffer\n", | ||
| 561 | __func__, __LINE__); | ||
| 562 | ret = -ENOMEM; | ||
| 563 | goto out_free_priv; | ||
| 564 | } | ||
| 565 | |||
| 566 | /* Put FIFO at begginning of XDR buffer */ | ||
| 567 | priv->fifo_base = (u32 *) (priv->xdr_buf + FIFO_OFFSET); | ||
| 568 | priv->fifo_ptr = priv->fifo_base; | ||
| 569 | |||
| 570 | /* XXX: Need to open GPU, in case ps3fb or snd_ps3 aren't loaded */ | ||
| 571 | if (ps3_open_hv_device(dev)) { | ||
| 572 | dev_err(&dev->core, "%s:%d: ps3_open_hv_device failed\n", | ||
| 573 | __func__, __LINE__); | ||
| 574 | ret = -EAGAIN; | ||
| 575 | goto out_close_gpu; | ||
| 576 | } | ||
| 577 | |||
| 578 | /* Request memory */ | ||
| 579 | status = -1; | ||
| 580 | ddr_size = memparse(size, &rest); | ||
| 581 | if (*rest == '-') | ||
| 582 | ddr_size -= ps3fb_videomemory.size; | ||
| 583 | ddr_size = ALIGN(ddr_size, 1024*1024); | ||
| 584 | if (ddr_size <= 0) { | ||
| 585 | dev_err(&dev->core, "%s:%d: specified size is too small\n", | ||
| 586 | __func__, __LINE__); | ||
| 587 | ret = -EINVAL; | ||
| 588 | goto out_close_gpu; | ||
| 589 | } | ||
| 590 | |||
| 591 | while (ddr_size > 0) { | ||
| 592 | status = lv1_gpu_memory_allocate(ddr_size, 0, 0, 0, 0, | ||
| 593 | &priv->memory_handle, | ||
| 594 | &ddr_lpar); | ||
| 595 | if (!status) | ||
| 596 | break; | ||
| 597 | ddr_size -= 1024*1024; | ||
| 598 | } | ||
| 599 | if (status || ddr_size <= 0) { | ||
| 600 | dev_err(&dev->core, "%s:%d: lv1_gpu_memory_allocate failed\n", | ||
| 601 | __func__, __LINE__); | ||
| 602 | ret = -ENOMEM; | ||
| 603 | goto out_free_xdr_buf; | ||
| 604 | } | ||
| 605 | |||
| 606 | /* Request context */ | ||
| 607 | status = lv1_gpu_context_allocate(priv->memory_handle, | ||
| 608 | 0, | ||
| 609 | &priv->context_handle, | ||
| 610 | &ctrl_lpar, | ||
| 611 | &info_lpar, | ||
| 612 | &reports_lpar, | ||
| 613 | &reports_size); | ||
| 614 | if (status) { | ||
| 615 | dev_err(&dev->core, "%s:%d: lv1_gpu_context_allocate failed\n", | ||
| 616 | __func__, __LINE__); | ||
| 617 | ret = -ENOMEM; | ||
| 618 | goto out_free_memory; | ||
| 619 | } | ||
| 620 | |||
| 621 | /* Map XDR buffer to RSX */ | ||
| 622 | status = lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF, | ||
| 623 | ps3_mm_phys_to_lpar(__pa(priv->xdr_buf)), | ||
| 624 | XDR_BUF_SIZE, 0); | ||
| 625 | if (status) { | ||
| 626 | dev_err(&dev->core, "%s:%d: lv1_gpu_context_iomap failed\n", | ||
| 627 | __func__, __LINE__); | ||
| 628 | ret = -ENOMEM; | ||
| 629 | goto out_free_context; | ||
| 630 | } | ||
| 631 | |||
| 632 | priv->ddr_base = ioremap_flags(ddr_lpar, ddr_size, _PAGE_NO_CACHE); | ||
| 633 | |||
| 634 | if (!priv->ddr_base) { | ||
| 635 | dev_err(&dev->core, "%s:%d: ioremap failed\n", __func__, | ||
| 636 | __LINE__); | ||
| 637 | ret = -ENOMEM; | ||
| 638 | goto out_free_context; | ||
| 639 | } | ||
| 640 | |||
| 641 | priv->ctrl = ioremap(ctrl_lpar, 64 * 1024); | ||
| 642 | if (!priv->ctrl) { | ||
| 643 | dev_err(&dev->core, "%s:%d: ioremap failed\n", __func__, | ||
| 644 | __LINE__); | ||
| 645 | ret = -ENOMEM; | ||
| 646 | goto out_unmap_vram; | ||
| 647 | } | ||
| 648 | |||
| 649 | priv->reports = ioremap(reports_lpar, reports_size); | ||
| 650 | if (!priv->reports) { | ||
| 651 | dev_err(&dev->core, "%s:%d: ioremap failed\n", __func__, | ||
| 652 | __LINE__); | ||
| 653 | ret = -ENOMEM; | ||
| 654 | goto out_unmap_ctrl; | ||
| 655 | } | ||
| 656 | |||
| 657 | mutex_lock(&ps3_gpu_mutex); | ||
| 658 | ps3vram_init_ring(&ps3vram_mtd); | ||
| 659 | mutex_unlock(&ps3_gpu_mutex); | ||
| 660 | |||
| 661 | ps3vram_mtd.name = "ps3vram"; | ||
| 662 | ps3vram_mtd.size = ddr_size; | ||
| 663 | ps3vram_mtd.flags = MTD_CAP_RAM; | ||
| 664 | ps3vram_mtd.erase = ps3vram_erase; | ||
| 665 | ps3vram_mtd.point = NULL; | ||
| 666 | ps3vram_mtd.unpoint = NULL; | ||
| 667 | ps3vram_mtd.read = ps3vram_read; | ||
| 668 | ps3vram_mtd.write = ps3vram_write; | ||
| 669 | ps3vram_mtd.owner = THIS_MODULE; | ||
| 670 | ps3vram_mtd.type = MTD_RAM; | ||
| 671 | ps3vram_mtd.erasesize = CACHE_PAGE_SIZE; | ||
| 672 | ps3vram_mtd.writesize = 1; | ||
| 673 | |||
| 674 | ps3vram_bind(&ps3vram_mtd); | ||
| 675 | |||
| 676 | mutex_lock(&ps3_gpu_mutex); | ||
| 677 | ret = ps3vram_wait_ring(&ps3vram_mtd, 100); | ||
| 678 | mutex_unlock(&ps3_gpu_mutex); | ||
| 679 | if (ret < 0) { | ||
| 680 | dev_err(&dev->core, "%s:%d: failed to initialize channels\n", | ||
| 681 | __func__, __LINE__); | ||
| 682 | ret = -ETIMEDOUT; | ||
| 683 | goto out_unmap_reports; | ||
| 684 | } | ||
| 685 | |||
| 686 | ps3vram_cache_init(&ps3vram_mtd); | ||
| 687 | |||
| 688 | if (add_mtd_device(&ps3vram_mtd)) { | ||
| 689 | dev_err(&dev->core, "%s:%d: add_mtd_device failed\n", | ||
| 690 | __func__, __LINE__); | ||
| 691 | ret = -EAGAIN; | ||
| 692 | goto out_cache_cleanup; | ||
| 693 | } | ||
| 694 | |||
| 695 | dev_info(&dev->core, "reserved %u MiB of gpu memory\n", | ||
| 696 | (unsigned int)(ddr_size / 1024 / 1024)); | ||
| 697 | |||
| 698 | return 0; | ||
| 699 | |||
| 700 | out_cache_cleanup: | ||
| 701 | ps3vram_cache_cleanup(&ps3vram_mtd); | ||
| 702 | out_unmap_reports: | ||
| 703 | iounmap(priv->reports); | ||
| 704 | out_unmap_ctrl: | ||
| 705 | iounmap(priv->ctrl); | ||
| 706 | out_unmap_vram: | ||
| 707 | iounmap(priv->ddr_base); | ||
| 708 | out_free_context: | ||
| 709 | lv1_gpu_context_free(priv->context_handle); | ||
| 710 | out_free_memory: | ||
| 711 | lv1_gpu_memory_free(priv->memory_handle); | ||
| 712 | out_close_gpu: | ||
| 713 | ps3_close_hv_device(dev); | ||
| 714 | out_free_xdr_buf: | ||
| 715 | free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); | ||
| 716 | out_free_priv: | ||
| 717 | kfree(ps3vram_mtd.priv); | ||
| 718 | ps3vram_mtd.priv = NULL; | ||
| 719 | out: | ||
| 720 | return ret; | ||
| 721 | } | ||
| 722 | |||
| 723 | static int ps3vram_shutdown(struct ps3_system_bus_device *dev) | ||
| 724 | { | ||
| 725 | struct ps3vram_priv *priv; | ||
| 726 | |||
| 727 | priv = ps3vram_mtd.priv; | ||
| 728 | |||
| 729 | del_mtd_device(&ps3vram_mtd); | ||
| 730 | ps3vram_cache_cleanup(&ps3vram_mtd); | ||
| 731 | iounmap(priv->reports); | ||
| 732 | iounmap(priv->ctrl); | ||
| 733 | iounmap(priv->ddr_base); | ||
| 734 | lv1_gpu_context_free(priv->context_handle); | ||
| 735 | lv1_gpu_memory_free(priv->memory_handle); | ||
| 736 | ps3_close_hv_device(dev); | ||
| 737 | free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); | ||
| 738 | kfree(priv); | ||
| 739 | return 0; | ||
| 740 | } | ||
| 741 | |||
| 742 | static struct ps3_system_bus_driver ps3vram_driver = { | ||
| 743 | .match_id = PS3_MATCH_ID_GPU, | ||
| 744 | .match_sub_id = PS3_MATCH_SUB_ID_GPU_RAMDISK, | ||
| 745 | .core.name = DEVICE_NAME, | ||
| 746 | .core.owner = THIS_MODULE, | ||
| 747 | .probe = ps3vram_probe, | ||
| 748 | .remove = ps3vram_shutdown, | ||
| 749 | .shutdown = ps3vram_shutdown, | ||
| 750 | }; | ||
| 751 | |||
| 752 | static int __init ps3vram_init(void) | ||
| 753 | { | ||
| 754 | return ps3_system_bus_driver_register(&ps3vram_driver); | ||
| 755 | } | ||
| 756 | |||
| 757 | static void __exit ps3vram_exit(void) | ||
| 758 | { | ||
| 759 | ps3_system_bus_driver_unregister(&ps3vram_driver); | ||
| 760 | } | ||
| 761 | |||
| 762 | module_init(ps3vram_init); | ||
| 763 | module_exit(ps3vram_exit); | ||
| 764 | |||
| 765 | MODULE_LICENSE("GPL"); | ||
| 766 | MODULE_AUTHOR("Jim Paris <jim@jtan.com>"); | ||
| 767 | MODULE_DESCRIPTION("MTD driver for PS3 video RAM"); | ||
| 768 | MODULE_ALIAS(PS3_MODULE_ALIAS_GPU_RAMDISK); | ||
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index b7322976d2b7..256c7bec7bd7 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
| @@ -884,6 +884,7 @@ config SCSI_IBMVSCSI | |||
| 884 | tristate "IBM Virtual SCSI support" | 884 | tristate "IBM Virtual SCSI support" |
| 885 | depends on PPC_PSERIES || PPC_ISERIES | 885 | depends on PPC_PSERIES || PPC_ISERIES |
| 886 | select SCSI_SRP_ATTRS | 886 | select SCSI_SRP_ATTRS |
| 887 | select VIOPATH if PPC_ISERIES | ||
| 887 | help | 888 | help |
| 888 | This is the IBM POWER Virtual SCSI Client | 889 | This is the IBM POWER Virtual SCSI Client |
| 889 | 890 | ||
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index b695ab3142d8..64fcf8c20821 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
| @@ -1320,13 +1320,30 @@ config SERIAL_NETX_CONSOLE | |||
| 1320 | config SERIAL_OF_PLATFORM | 1320 | config SERIAL_OF_PLATFORM |
| 1321 | tristate "Serial port on Open Firmware platform bus" | 1321 | tristate "Serial port on Open Firmware platform bus" |
| 1322 | depends on PPC_OF | 1322 | depends on PPC_OF |
| 1323 | depends on SERIAL_8250 | 1323 | depends on SERIAL_8250 || SERIAL_OF_PLATFORM_NWPSERIAL |
| 1324 | help | 1324 | help |
| 1325 | If you have a PowerPC based system that has serial ports | 1325 | If you have a PowerPC based system that has serial ports |
| 1326 | on a platform specific bus, you should enable this option. | 1326 | on a platform specific bus, you should enable this option. |
| 1327 | Currently, only 8250 compatible ports are supported, but | 1327 | Currently, only 8250 compatible ports are supported, but |
| 1328 | others can easily be added. | 1328 | others can easily be added. |
| 1329 | 1329 | ||
| 1330 | config SERIAL_OF_PLATFORM_NWPSERIAL | ||
| 1331 | tristate "NWP serial port driver" | ||
| 1332 | depends on PPC_OF && PPC_DCR | ||
| 1333 | select SERIAL_OF_PLATFORM | ||
| 1334 | select SERIAL_CORE_CONSOLE | ||
| 1335 | select SERIAL_CORE | ||
| 1336 | help | ||
| 1337 | This driver supports the cell network processor nwp serial | ||
| 1338 | device. | ||
| 1339 | |||
| 1340 | config SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE | ||
| 1341 | bool "Console on NWP serial port" | ||
| 1342 | depends on SERIAL_OF_PLATFORM_NWPSERIAL=y | ||
| 1343 | select SERIAL_CORE_CONSOLE | ||
| 1344 | help | ||
| 1345 | Support for Console on the NWP serial ports. | ||
| 1346 | |||
| 1330 | config SERIAL_QE | 1347 | config SERIAL_QE |
| 1331 | tristate "Freescale QUICC Engine serial port support" | 1348 | tristate "Freescale QUICC Engine serial port support" |
| 1332 | depends on QUICC_ENGINE | 1349 | depends on QUICC_ENGINE |
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index dfe775ac45b2..8844c0a03929 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile | |||
| @@ -72,6 +72,7 @@ obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o | |||
| 72 | obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o | 72 | obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o |
| 73 | obj-$(CONFIG_SERIAL_NETX) += netx-serial.o | 73 | obj-$(CONFIG_SERIAL_NETX) += netx-serial.o |
| 74 | obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o | 74 | obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o |
| 75 | obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o | ||
| 75 | obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o | 76 | obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o |
| 76 | obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o | 77 | obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o |
| 77 | obj-$(CONFIG_SERIAL_QE) += ucc_uart.o | 78 | obj-$(CONFIG_SERIAL_QE) += ucc_uart.o |
diff --git a/drivers/serial/nwpserial.c b/drivers/serial/nwpserial.c new file mode 100644 index 000000000000..32f3eaf0d262 --- /dev/null +++ b/drivers/serial/nwpserial.c | |||
| @@ -0,0 +1,475 @@ | |||
| 1 | /* | ||
| 2 | * Serial Port driver for a NWP uart device | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 IBM Corp., Benjamin Krill <ben@codiert.org> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | * | ||
| 11 | */ | ||
| 12 | #include <linux/init.h> | ||
| 13 | #include <linux/console.h> | ||
| 14 | #include <linux/serial.h> | ||
| 15 | #include <linux/serial_reg.h> | ||
| 16 | #include <linux/serial_core.h> | ||
| 17 | #include <linux/tty.h> | ||
| 18 | #include <linux/irqreturn.h> | ||
| 19 | #include <linux/mutex.h> | ||
| 20 | #include <linux/of_platform.h> | ||
| 21 | #include <linux/of_device.h> | ||
| 22 | #include <linux/nwpserial.h> | ||
| 23 | #include <asm/prom.h> | ||
| 24 | #include <asm/dcr.h> | ||
| 25 | |||
| 26 | #define NWPSERIAL_NR 2 | ||
| 27 | |||
| 28 | #define NWPSERIAL_STATUS_RXVALID 0x1 | ||
| 29 | #define NWPSERIAL_STATUS_TXFULL 0x2 | ||
| 30 | |||
| 31 | struct nwpserial_port { | ||
| 32 | struct uart_port port; | ||
| 33 | dcr_host_t dcr_host; | ||
| 34 | unsigned int ier; | ||
| 35 | unsigned int mcr; | ||
| 36 | }; | ||
| 37 | |||
| 38 | static DEFINE_MUTEX(nwpserial_mutex); | ||
| 39 | static struct nwpserial_port nwpserial_ports[NWPSERIAL_NR]; | ||
| 40 | |||
| 41 | static void wait_for_bits(struct nwpserial_port *up, int bits) | ||
| 42 | { | ||
| 43 | unsigned int status, tmout = 10000; | ||
| 44 | |||
| 45 | /* Wait up to 10ms for the character(s) to be sent. */ | ||
| 46 | do { | ||
| 47 | status = dcr_read(up->dcr_host, UART_LSR); | ||
| 48 | |||
| 49 | if (--tmout == 0) | ||
| 50 | break; | ||
| 51 | udelay(1); | ||
| 52 | } while ((status & bits) != bits); | ||
| 53 | } | ||
| 54 | |||
| 55 | #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE | ||
| 56 | static void nwpserial_console_putchar(struct uart_port *port, int c) | ||
| 57 | { | ||
| 58 | struct nwpserial_port *up; | ||
| 59 | up = container_of(port, struct nwpserial_port, port); | ||
| 60 | /* check if tx buffer is full */ | ||
| 61 | wait_for_bits(up, UART_LSR_THRE); | ||
| 62 | dcr_write(up->dcr_host, UART_TX, c); | ||
| 63 | up->port.icount.tx++; | ||
| 64 | } | ||
| 65 | |||
| 66 | static void | ||
| 67 | nwpserial_console_write(struct console *co, const char *s, unsigned int count) | ||
| 68 | { | ||
| 69 | struct nwpserial_port *up = &nwpserial_ports[co->index]; | ||
| 70 | unsigned long flags; | ||
| 71 | int locked = 1; | ||
| 72 | |||
| 73 | if (oops_in_progress) | ||
| 74 | locked = spin_trylock_irqsave(&up->port.lock, flags); | ||
| 75 | else | ||
| 76 | spin_lock_irqsave(&up->port.lock, flags); | ||
| 77 | |||
| 78 | /* save and disable interrupt */ | ||
| 79 | up->ier = dcr_read(up->dcr_host, UART_IER); | ||
| 80 | dcr_write(up->dcr_host, UART_IER, up->ier & ~UART_IER_RDI); | ||
| 81 | |||
| 82 | uart_console_write(&up->port, s, count, nwpserial_console_putchar); | ||
| 83 | |||
| 84 | /* wait for transmitter to become emtpy */ | ||
| 85 | while ((dcr_read(up->dcr_host, UART_LSR) & UART_LSR_THRE) == 0) | ||
| 86 | cpu_relax(); | ||
| 87 | |||
| 88 | /* restore interrupt state */ | ||
| 89 | dcr_write(up->dcr_host, UART_IER, up->ier); | ||
| 90 | |||
| 91 | if (locked) | ||
| 92 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
| 93 | } | ||
| 94 | |||
| 95 | static struct uart_driver nwpserial_reg; | ||
| 96 | static struct console nwpserial_console = { | ||
| 97 | .name = "ttySQ", | ||
| 98 | .write = nwpserial_console_write, | ||
| 99 | .device = uart_console_device, | ||
| 100 | .flags = CON_PRINTBUFFER, | ||
| 101 | .index = -1, | ||
| 102 | .data = &nwpserial_reg, | ||
| 103 | }; | ||
| 104 | #define NWPSERIAL_CONSOLE (&nwpserial_console) | ||
| 105 | #else | ||
| 106 | #define NWPSERIAL_CONSOLE NULL | ||
| 107 | #endif /* CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE */ | ||
| 108 | |||
| 109 | /**************************************************************************/ | ||
| 110 | |||
| 111 | static int nwpserial_request_port(struct uart_port *port) | ||
| 112 | { | ||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | static void nwpserial_release_port(struct uart_port *port) | ||
| 117 | { | ||
| 118 | /* N/A */ | ||
| 119 | } | ||
| 120 | |||
| 121 | static void nwpserial_config_port(struct uart_port *port, int flags) | ||
| 122 | { | ||
| 123 | port->type = PORT_NWPSERIAL; | ||
| 124 | } | ||
| 125 | |||
| 126 | static irqreturn_t nwpserial_interrupt(int irq, void *dev_id) | ||
| 127 | { | ||
| 128 | struct nwpserial_port *up = dev_id; | ||
| 129 | struct tty_struct *tty = up->port.info->port.tty; | ||
| 130 | irqreturn_t ret; | ||
| 131 | unsigned int iir; | ||
| 132 | unsigned char ch; | ||
| 133 | |||
| 134 | spin_lock(&up->port.lock); | ||
| 135 | |||
| 136 | /* check if the uart was the interrupt source. */ | ||
| 137 | iir = dcr_read(up->dcr_host, UART_IIR); | ||
| 138 | if (!iir) { | ||
| 139 | ret = IRQ_NONE; | ||
| 140 | goto out; | ||
| 141 | } | ||
| 142 | |||
| 143 | do { | ||
| 144 | up->port.icount.rx++; | ||
| 145 | ch = dcr_read(up->dcr_host, UART_RX); | ||
| 146 | if (up->port.ignore_status_mask != NWPSERIAL_STATUS_RXVALID) | ||
| 147 | tty_insert_flip_char(tty, ch, TTY_NORMAL); | ||
| 148 | } while (dcr_read(up->dcr_host, UART_RX) & UART_LSR_DR); | ||
| 149 | |||
| 150 | tty_flip_buffer_push(tty); | ||
| 151 | ret = IRQ_HANDLED; | ||
| 152 | |||
| 153 | out: | ||
| 154 | spin_unlock(&up->port.lock); | ||
| 155 | return ret; | ||
| 156 | } | ||
| 157 | |||
| 158 | static int nwpserial_startup(struct uart_port *port) | ||
| 159 | { | ||
| 160 | struct nwpserial_port *up; | ||
| 161 | int err; | ||
| 162 | |||
| 163 | up = container_of(port, struct nwpserial_port, port); | ||
| 164 | |||
| 165 | /* disable flow control by default */ | ||
| 166 | up->mcr = dcr_read(up->dcr_host, UART_MCR) & ~UART_MCR_AFE; | ||
| 167 | dcr_write(up->dcr_host, UART_MCR, up->mcr); | ||
| 168 | |||
| 169 | /* register interrupt handler */ | ||
| 170 | err = request_irq(up->port.irq, nwpserial_interrupt, | ||
| 171 | IRQF_SHARED, "nwpserial", up); | ||
| 172 | if (err) | ||
| 173 | return err; | ||
| 174 | |||
| 175 | /* enable interrupts */ | ||
| 176 | up->ier = UART_IER_RDI; | ||
| 177 | dcr_write(up->dcr_host, UART_IER, up->ier); | ||
| 178 | |||
| 179 | /* enable receiving */ | ||
| 180 | up->port.ignore_status_mask &= ~NWPSERIAL_STATUS_RXVALID; | ||
| 181 | |||
| 182 | return 0; | ||
| 183 | } | ||
| 184 | |||
| 185 | static void nwpserial_shutdown(struct uart_port *port) | ||
| 186 | { | ||
| 187 | struct nwpserial_port *up; | ||
| 188 | up = container_of(port, struct nwpserial_port, port); | ||
| 189 | |||
| 190 | /* disable receiving */ | ||
| 191 | up->port.ignore_status_mask |= NWPSERIAL_STATUS_RXVALID; | ||
| 192 | |||
| 193 | /* disable interrupts from this port */ | ||
| 194 | up->ier = 0; | ||
| 195 | dcr_write(up->dcr_host, UART_IER, up->ier); | ||
| 196 | |||
| 197 | /* free irq */ | ||
| 198 | free_irq(up->port.irq, port); | ||
| 199 | } | ||
| 200 | |||
| 201 | static int nwpserial_verify_port(struct uart_port *port, | ||
| 202 | struct serial_struct *ser) | ||
| 203 | { | ||
| 204 | return -EINVAL; | ||
| 205 | } | ||
| 206 | |||
| 207 | static const char *nwpserial_type(struct uart_port *port) | ||
| 208 | { | ||
| 209 | return port->type == PORT_NWPSERIAL ? "nwpserial" : NULL; | ||
| 210 | } | ||
| 211 | |||
| 212 | static void nwpserial_set_termios(struct uart_port *port, | ||
| 213 | struct ktermios *termios, struct ktermios *old) | ||
| 214 | { | ||
| 215 | struct nwpserial_port *up; | ||
| 216 | up = container_of(port, struct nwpserial_port, port); | ||
| 217 | |||
| 218 | up->port.read_status_mask = NWPSERIAL_STATUS_RXVALID | ||
| 219 | | NWPSERIAL_STATUS_TXFULL; | ||
| 220 | |||
| 221 | up->port.ignore_status_mask = 0; | ||
| 222 | /* ignore all characters if CREAD is not set */ | ||
| 223 | if ((termios->c_cflag & CREAD) == 0) | ||
| 224 | up->port.ignore_status_mask |= NWPSERIAL_STATUS_RXVALID; | ||
| 225 | |||
| 226 | /* Copy back the old hardware settings */ | ||
| 227 | if (old) | ||
| 228 | tty_termios_copy_hw(termios, old); | ||
| 229 | } | ||
| 230 | |||
| 231 | static void nwpserial_break_ctl(struct uart_port *port, int ctl) | ||
| 232 | { | ||
| 233 | /* N/A */ | ||
| 234 | } | ||
| 235 | |||
| 236 | static void nwpserial_enable_ms(struct uart_port *port) | ||
| 237 | { | ||
| 238 | /* N/A */ | ||
| 239 | } | ||
| 240 | |||
| 241 | static void nwpserial_stop_rx(struct uart_port *port) | ||
| 242 | { | ||
| 243 | struct nwpserial_port *up; | ||
| 244 | up = container_of(port, struct nwpserial_port, port); | ||
| 245 | /* don't forward any more data (like !CREAD) */ | ||
| 246 | up->port.ignore_status_mask = NWPSERIAL_STATUS_RXVALID; | ||
| 247 | } | ||
| 248 | |||
| 249 | static void nwpserial_putchar(struct nwpserial_port *up, unsigned char c) | ||
| 250 | { | ||
| 251 | /* check if tx buffer is full */ | ||
| 252 | wait_for_bits(up, UART_LSR_THRE); | ||
| 253 | dcr_write(up->dcr_host, UART_TX, c); | ||
| 254 | up->port.icount.tx++; | ||
| 255 | } | ||
| 256 | |||
| 257 | static void nwpserial_start_tx(struct uart_port *port) | ||
| 258 | { | ||
| 259 | struct nwpserial_port *up; | ||
| 260 | struct circ_buf *xmit; | ||
| 261 | up = container_of(port, struct nwpserial_port, port); | ||
| 262 | xmit = &up->port.info->xmit; | ||
| 263 | |||
| 264 | if (port->x_char) { | ||
| 265 | nwpserial_putchar(up, up->port.x_char); | ||
| 266 | port->x_char = 0; | ||
| 267 | } | ||
| 268 | |||
| 269 | while (!(uart_circ_empty(xmit) || uart_tx_stopped(&up->port))) { | ||
| 270 | nwpserial_putchar(up, xmit->buf[xmit->tail]); | ||
| 271 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1); | ||
| 272 | } | ||
| 273 | } | ||
| 274 | |||
| 275 | static unsigned int nwpserial_get_mctrl(struct uart_port *port) | ||
| 276 | { | ||
| 277 | return 0; | ||
| 278 | } | ||
| 279 | |||
| 280 | static void nwpserial_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
| 281 | { | ||
| 282 | /* N/A */ | ||
| 283 | } | ||
| 284 | |||
| 285 | static void nwpserial_stop_tx(struct uart_port *port) | ||
| 286 | { | ||
| 287 | /* N/A */ | ||
| 288 | } | ||
| 289 | |||
| 290 | static unsigned int nwpserial_tx_empty(struct uart_port *port) | ||
| 291 | { | ||
| 292 | struct nwpserial_port *up; | ||
| 293 | unsigned long flags; | ||
| 294 | int ret; | ||
| 295 | up = container_of(port, struct nwpserial_port, port); | ||
| 296 | |||
| 297 | spin_lock_irqsave(&up->port.lock, flags); | ||
| 298 | ret = dcr_read(up->dcr_host, UART_LSR); | ||
| 299 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
| 300 | |||
| 301 | return ret & UART_LSR_TEMT ? TIOCSER_TEMT : 0; | ||
| 302 | } | ||
| 303 | |||
| 304 | static struct uart_ops nwpserial_pops = { | ||
| 305 | .tx_empty = nwpserial_tx_empty, | ||
| 306 | .set_mctrl = nwpserial_set_mctrl, | ||
| 307 | .get_mctrl = nwpserial_get_mctrl, | ||
| 308 | .stop_tx = nwpserial_stop_tx, | ||
| 309 | .start_tx = nwpserial_start_tx, | ||
| 310 | .stop_rx = nwpserial_stop_rx, | ||
| 311 | .enable_ms = nwpserial_enable_ms, | ||
| 312 | .break_ctl = nwpserial_break_ctl, | ||
| 313 | .startup = nwpserial_startup, | ||
| 314 | .shutdown = nwpserial_shutdown, | ||
| 315 | .set_termios = nwpserial_set_termios, | ||
| 316 | .type = nwpserial_type, | ||
| 317 | .release_port = nwpserial_release_port, | ||
| 318 | .request_port = nwpserial_request_port, | ||
| 319 | .config_port = nwpserial_config_port, | ||
| 320 | .verify_port = nwpserial_verify_port, | ||
| 321 | }; | ||
| 322 | |||
| 323 | static struct uart_driver nwpserial_reg = { | ||
| 324 | .owner = THIS_MODULE, | ||
| 325 | .driver_name = "nwpserial", | ||
| 326 | .dev_name = "ttySQ", | ||
| 327 | .major = TTY_MAJOR, | ||
| 328 | .minor = 68, | ||
| 329 | .nr = NWPSERIAL_NR, | ||
| 330 | .cons = NWPSERIAL_CONSOLE, | ||
| 331 | }; | ||
| 332 | |||
| 333 | int nwpserial_register_port(struct uart_port *port) | ||
| 334 | { | ||
| 335 | struct nwpserial_port *up = NULL; | ||
| 336 | int ret = -1; | ||
| 337 | int i; | ||
| 338 | static int first = 1; | ||
| 339 | int dcr_len; | ||
| 340 | int dcr_base; | ||
| 341 | struct device_node *dn; | ||
| 342 | |||
| 343 | mutex_lock(&nwpserial_mutex); | ||
| 344 | |||
| 345 | dn = to_of_device(port->dev)->node; | ||
| 346 | if (dn == NULL) | ||
| 347 | goto out; | ||
| 348 | |||
| 349 | /* get dcr base. */ | ||
| 350 | dcr_base = dcr_resource_start(dn, 0); | ||
| 351 | |||
| 352 | /* find matching entry */ | ||
| 353 | for (i = 0; i < NWPSERIAL_NR; i++) | ||
| 354 | if (nwpserial_ports[i].port.iobase == dcr_base) { | ||
| 355 | up = &nwpserial_ports[i]; | ||
| 356 | break; | ||
| 357 | } | ||
| 358 | |||
| 359 | /* we didn't find a mtching entry, search for a free port */ | ||
| 360 | if (up == NULL) | ||
| 361 | for (i = 0; i < NWPSERIAL_NR; i++) | ||
| 362 | if (nwpserial_ports[i].port.type == PORT_UNKNOWN && | ||
| 363 | nwpserial_ports[i].port.iobase == 0) { | ||
| 364 | up = &nwpserial_ports[i]; | ||
| 365 | break; | ||
| 366 | } | ||
| 367 | |||
| 368 | if (up == NULL) { | ||
| 369 | ret = -EBUSY; | ||
| 370 | goto out; | ||
| 371 | } | ||
| 372 | |||
| 373 | if (first) | ||
| 374 | uart_register_driver(&nwpserial_reg); | ||
| 375 | first = 0; | ||
| 376 | |||
| 377 | up->port.membase = port->membase; | ||
| 378 | up->port.irq = port->irq; | ||
| 379 | up->port.uartclk = port->uartclk; | ||
| 380 | up->port.fifosize = port->fifosize; | ||
| 381 | up->port.regshift = port->regshift; | ||
| 382 | up->port.iotype = port->iotype; | ||
| 383 | up->port.flags = port->flags; | ||
| 384 | up->port.mapbase = port->mapbase; | ||
| 385 | up->port.private_data = port->private_data; | ||
| 386 | |||
| 387 | if (port->dev) | ||
| 388 | up->port.dev = port->dev; | ||
| 389 | |||
| 390 | if (up->port.iobase != dcr_base) { | ||
| 391 | up->port.ops = &nwpserial_pops; | ||
| 392 | up->port.fifosize = 16; | ||
| 393 | |||
| 394 | spin_lock_init(&up->port.lock); | ||
| 395 | |||
| 396 | up->port.iobase = dcr_base; | ||
| 397 | dcr_len = dcr_resource_len(dn, 0); | ||
| 398 | |||
| 399 | up->dcr_host = dcr_map(dn, dcr_base, dcr_len); | ||
| 400 | if (!DCR_MAP_OK(up->dcr_host)) { | ||
| 401 | printk(KERN_ERR "Cannot map DCR resources for NWPSERIAL"); | ||
| 402 | goto out; | ||
| 403 | } | ||
| 404 | } | ||
| 405 | |||
| 406 | ret = uart_add_one_port(&nwpserial_reg, &up->port); | ||
| 407 | if (ret == 0) | ||
| 408 | ret = up->port.line; | ||
| 409 | |||
| 410 | out: | ||
| 411 | mutex_unlock(&nwpserial_mutex); | ||
| 412 | |||
| 413 | return ret; | ||
| 414 | } | ||
| 415 | EXPORT_SYMBOL(nwpserial_register_port); | ||
| 416 | |||
| 417 | void nwpserial_unregister_port(int line) | ||
| 418 | { | ||
| 419 | struct nwpserial_port *up = &nwpserial_ports[line]; | ||
| 420 | mutex_lock(&nwpserial_mutex); | ||
| 421 | uart_remove_one_port(&nwpserial_reg, &up->port); | ||
| 422 | |||
| 423 | up->port.type = PORT_UNKNOWN; | ||
| 424 | |||
| 425 | mutex_unlock(&nwpserial_mutex); | ||
| 426 | } | ||
| 427 | EXPORT_SYMBOL(nwpserial_unregister_port); | ||
| 428 | |||
| 429 | #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE | ||
| 430 | static int __init nwpserial_console_init(void) | ||
| 431 | { | ||
| 432 | struct nwpserial_port *up = NULL; | ||
| 433 | struct device_node *dn; | ||
| 434 | const char *name; | ||
| 435 | int dcr_base; | ||
| 436 | int dcr_len; | ||
| 437 | int i; | ||
| 438 | |||
| 439 | /* search for a free port */ | ||
| 440 | for (i = 0; i < NWPSERIAL_NR; i++) | ||
| 441 | if (nwpserial_ports[i].port.type == PORT_UNKNOWN) { | ||
| 442 | up = &nwpserial_ports[i]; | ||
| 443 | break; | ||
| 444 | } | ||
| 445 | |||
| 446 | if (up == NULL) | ||
| 447 | return -1; | ||
| 448 | |||
| 449 | name = of_get_property(of_chosen, "linux,stdout-path", NULL); | ||
| 450 | if (name == NULL) | ||
| 451 | return -1; | ||
| 452 | |||
| 453 | dn = of_find_node_by_path(name); | ||
| 454 | if (!dn) | ||
| 455 | return -1; | ||
| 456 | |||
| 457 | spin_lock_init(&up->port.lock); | ||
| 458 | up->port.ops = &nwpserial_pops; | ||
| 459 | up->port.type = PORT_NWPSERIAL; | ||
| 460 | up->port.fifosize = 16; | ||
| 461 | |||
| 462 | dcr_base = dcr_resource_start(dn, 0); | ||
| 463 | dcr_len = dcr_resource_len(dn, 0); | ||
| 464 | up->port.iobase = dcr_base; | ||
| 465 | |||
| 466 | up->dcr_host = dcr_map(dn, dcr_base, dcr_len); | ||
| 467 | if (!DCR_MAP_OK(up->dcr_host)) { | ||
| 468 | printk("Cannot map DCR resources for SERIAL"); | ||
| 469 | return -1; | ||
| 470 | } | ||
| 471 | register_console(&nwpserial_console); | ||
| 472 | return 0; | ||
| 473 | } | ||
| 474 | console_initcall(nwpserial_console_init); | ||
| 475 | #endif /* CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE */ | ||
diff --git a/drivers/serial/of_serial.c b/drivers/serial/of_serial.c index 8fa0ff561e9f..a821e3a3d664 100644 --- a/drivers/serial/of_serial.c +++ b/drivers/serial/of_serial.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/serial_core.h> | 14 | #include <linux/serial_core.h> |
| 15 | #include <linux/serial_8250.h> | 15 | #include <linux/serial_8250.h> |
| 16 | #include <linux/of_platform.h> | 16 | #include <linux/of_platform.h> |
| 17 | #include <linux/nwpserial.h> | ||
| 17 | 18 | ||
| 18 | #include <asm/prom.h> | 19 | #include <asm/prom.h> |
| 19 | 20 | ||
| @@ -99,9 +100,16 @@ static int __devinit of_platform_serial_probe(struct of_device *ofdev, | |||
| 99 | goto out; | 100 | goto out; |
| 100 | 101 | ||
| 101 | switch (port_type) { | 102 | switch (port_type) { |
| 103 | #ifdef CONFIG_SERIAL_8250 | ||
| 102 | case PORT_8250 ... PORT_MAX_8250: | 104 | case PORT_8250 ... PORT_MAX_8250: |
| 103 | ret = serial8250_register_port(&port); | 105 | ret = serial8250_register_port(&port); |
| 104 | break; | 106 | break; |
| 107 | #endif | ||
| 108 | #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL | ||
| 109 | case PORT_NWPSERIAL: | ||
| 110 | ret = nwpserial_register_port(&port); | ||
| 111 | break; | ||
| 112 | #endif | ||
| 105 | default: | 113 | default: |
| 106 | /* need to add code for these */ | 114 | /* need to add code for these */ |
| 107 | case PORT_UNKNOWN: | 115 | case PORT_UNKNOWN: |
| @@ -129,9 +137,16 @@ static int of_platform_serial_remove(struct of_device *ofdev) | |||
| 129 | { | 137 | { |
| 130 | struct of_serial_info *info = ofdev->dev.driver_data; | 138 | struct of_serial_info *info = ofdev->dev.driver_data; |
| 131 | switch (info->type) { | 139 | switch (info->type) { |
| 140 | #ifdef CONFIG_SERIAL_8250 | ||
| 132 | case PORT_8250 ... PORT_MAX_8250: | 141 | case PORT_8250 ... PORT_MAX_8250: |
| 133 | serial8250_unregister_port(info->line); | 142 | serial8250_unregister_port(info->line); |
| 134 | break; | 143 | break; |
| 144 | #endif | ||
| 145 | #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL | ||
| 146 | case PORT_NWPSERIAL: | ||
| 147 | nwpserial_unregister_port(info->line); | ||
| 148 | break; | ||
| 149 | #endif | ||
| 135 | default: | 150 | default: |
| 136 | /* need to add code for these */ | 151 | /* need to add code for these */ |
| 137 | break; | 152 | break; |
| @@ -148,6 +163,10 @@ static struct of_device_id __devinitdata of_platform_serial_table[] = { | |||
| 148 | { .type = "serial", .compatible = "ns16450", .data = (void *)PORT_16450, }, | 163 | { .type = "serial", .compatible = "ns16450", .data = (void *)PORT_16450, }, |
| 149 | { .type = "serial", .compatible = "ns16550", .data = (void *)PORT_16550, }, | 164 | { .type = "serial", .compatible = "ns16550", .data = (void *)PORT_16550, }, |
| 150 | { .type = "serial", .compatible = "ns16750", .data = (void *)PORT_16750, }, | 165 | { .type = "serial", .compatible = "ns16750", .data = (void *)PORT_16750, }, |
| 166 | #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL | ||
| 167 | { .type = "serial", .compatible = "ibm,qpace-nwp-serial", | ||
| 168 | .data = (void *)PORT_NWPSERIAL, }, | ||
| 169 | #endif | ||
| 151 | { .type = "serial", .data = (void *)PORT_UNKNOWN, }, | 170 | { .type = "serial", .data = (void *)PORT_UNKNOWN, }, |
| 152 | { /* end of list */ }, | 171 | { /* end of list */ }, |
| 153 | }; | 172 | }; |
diff --git a/include/linux/nwpserial.h b/include/linux/nwpserial.h new file mode 100644 index 000000000000..9acb21572eaf --- /dev/null +++ b/include/linux/nwpserial.h | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | /* | ||
| 2 | * Serial Port driver for a NWP uart device | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 IBM Corp., Benjamin Krill <ben@codiert.org> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | * | ||
| 11 | */ | ||
| 12 | #ifndef _NWPSERIAL_H | ||
| 13 | #define _NWPSERIAL_H | ||
| 14 | |||
| 15 | int nwpserial_register_port(struct uart_port *port); | ||
| 16 | void nwpserial_unregister_port(int line); | ||
| 17 | |||
| 18 | #endif /* _NWPSERIAL_H */ | ||
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index b4199841f1fc..90bbbf0b1161 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h | |||
| @@ -161,6 +161,9 @@ | |||
| 161 | 161 | ||
| 162 | #define PORT_S3C6400 84 | 162 | #define PORT_S3C6400 84 |
| 163 | 163 | ||
| 164 | /* NWPSERIAL */ | ||
| 165 | #define PORT_NWPSERIAL 85 | ||
| 166 | |||
| 164 | #ifdef __KERNEL__ | 167 | #ifdef __KERNEL__ |
| 165 | 168 | ||
| 166 | #include <linux/compiler.h> | 169 | #include <linux/compiler.h> |
