diff options
| author | David S. Miller <davem@davemloft.net> | 2010-01-04 18:33:22 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2010-01-04 18:33:22 -0500 |
| commit | 5958eed76ccc8c361f872829bdc4b8c6dc9cd379 (patch) | |
| tree | 8f8dfcced082db674b0ae3ca3af9fdb6dde59dae /arch/powerpc | |
| parent | c7c17c2779075e675cb3c7fe2ecde67e226771fb (diff) | |
| parent | c5974b835a909ff15c3b7e6cf6789b5eb919f419 (diff) | |
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
Diffstat (limited to 'arch/powerpc')
266 files changed, 15557 insertions, 2116 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 2ba14e77296c..ba3948c70072 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
| @@ -56,6 +56,16 @@ config IRQ_PER_CPU | |||
| 56 | bool | 56 | bool |
| 57 | default y | 57 | default y |
| 58 | 58 | ||
| 59 | config NR_IRQS | ||
| 60 | int "Number of virtual interrupt numbers" | ||
| 61 | range 32 512 | ||
| 62 | default "512" | ||
| 63 | help | ||
| 64 | This defines the number of virtual interrupt numbers the kernel | ||
| 65 | can manage. Virtual interrupt numbers are what you see in | ||
| 66 | /proc/interrupts. If you configure your system to have too few, | ||
| 67 | drivers will fail to load or worse - handle with care. | ||
| 68 | |||
| 59 | config STACKTRACE_SUPPORT | 69 | config STACKTRACE_SUPPORT |
| 60 | bool | 70 | bool |
| 61 | default y | 71 | default y |
| @@ -199,24 +209,14 @@ config DEFAULT_UIMAGE | |||
| 199 | config REDBOOT | 209 | config REDBOOT |
| 200 | bool | 210 | bool |
| 201 | 211 | ||
| 202 | config HIBERNATE_32 | ||
| 203 | bool | ||
| 204 | depends on (PPC_PMAC && !SMP) || BROKEN | ||
| 205 | default y | ||
| 206 | |||
| 207 | config HIBERNATE_64 | ||
| 208 | bool | ||
| 209 | depends on BROKEN || (PPC_PMAC64 && EXPERIMENTAL) | ||
| 210 | default y | ||
| 211 | |||
| 212 | config ARCH_HIBERNATION_POSSIBLE | 212 | config ARCH_HIBERNATION_POSSIBLE |
| 213 | bool | 213 | bool |
| 214 | depends on (PPC64 && HIBERNATE_64) || (PPC32 && HIBERNATE_32) | ||
| 215 | default y | 214 | default y |
| 216 | 215 | ||
| 217 | config ARCH_SUSPEND_POSSIBLE | 216 | config ARCH_SUSPEND_POSSIBLE |
| 218 | def_bool y | 217 | def_bool y |
| 219 | depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx | 218 | depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \ |
| 219 | PPC_85xx || PPC_86xx | ||
| 220 | 220 | ||
| 221 | config PPC_DCR_NATIVE | 221 | config PPC_DCR_NATIVE |
| 222 | bool | 222 | bool |
| @@ -320,6 +320,10 @@ config HOTPLUG_CPU | |||
| 320 | 320 | ||
| 321 | Say N if you are unsure. | 321 | Say N if you are unsure. |
| 322 | 322 | ||
| 323 | config ARCH_CPU_PROBE_RELEASE | ||
| 324 | def_bool y | ||
| 325 | depends on HOTPLUG_CPU | ||
| 326 | |||
| 323 | config ARCH_ENABLE_MEMORY_HOTPLUG | 327 | config ARCH_ENABLE_MEMORY_HOTPLUG |
| 324 | def_bool y | 328 | def_bool y |
| 325 | 329 | ||
| @@ -378,6 +382,19 @@ config IRQ_ALL_CPUS | |||
| 378 | CPU. Generally saying Y is safe, although some problems have been | 382 | CPU. Generally saying Y is safe, although some problems have been |
| 379 | reported with SMP Power Macintoshes with this option enabled. | 383 | reported with SMP Power Macintoshes with this option enabled. |
| 380 | 384 | ||
| 385 | config SPARSE_IRQ | ||
| 386 | bool "Support sparse irq numbering" | ||
| 387 | default y | ||
| 388 | help | ||
| 389 | This enables support for sparse irqs. This is useful for distro | ||
| 390 | kernels that want to define a high CONFIG_NR_CPUS value but still | ||
| 391 | want to have low kernel memory footprint on smaller machines. | ||
| 392 | |||
| 393 | ( Sparse IRQs can also be beneficial on NUMA boxes, as they spread | ||
| 394 | out the irq_desc[] array in a more NUMA-friendly way. ) | ||
| 395 | |||
| 396 | If you don't know what to do here, say Y. | ||
| 397 | |||
| 381 | config NUMA | 398 | config NUMA |
| 382 | bool "NUMA support" | 399 | bool "NUMA support" |
| 383 | depends on PPC64 | 400 | depends on PPC64 |
| @@ -652,6 +669,14 @@ config FSL_PCI | |||
| 652 | select PPC_INDIRECT_PCI | 669 | select PPC_INDIRECT_PCI |
| 653 | select PCI_QUIRKS | 670 | select PCI_QUIRKS |
| 654 | 671 | ||
| 672 | config FSL_PMC | ||
| 673 | bool | ||
| 674 | default y | ||
| 675 | depends on SUSPEND && (PPC_85xx || PPC_86xx) | ||
| 676 | help | ||
| 677 | Freescale MPC85xx/MPC86xx power management controller support | ||
| 678 | (suspend/resume). For MPC83xx see platforms/83xx/suspend.c | ||
| 679 | |||
| 655 | config 4xx_SOC | 680 | config 4xx_SOC |
| 656 | bool | 681 | bool |
| 657 | 682 | ||
| @@ -679,7 +704,7 @@ config PPC_PCI_CHOICE | |||
| 679 | config PCI | 704 | config PCI |
| 680 | bool "PCI support" if PPC_PCI_CHOICE | 705 | bool "PCI support" if PPC_PCI_CHOICE |
| 681 | default y if !40x && !CPM2 && !8xx && !PPC_83xx \ | 706 | default y if !40x && !CPM2 && !8xx && !PPC_83xx \ |
| 682 | && !PPC_85xx && !PPC_86xx | 707 | && !PPC_85xx && !PPC_86xx && !GAMECUBE_COMMON |
| 683 | default PCI_PERMEDIA if !4xx && !CPM2 && !8xx | 708 | default PCI_PERMEDIA if !4xx && !CPM2 && !8xx |
| 684 | default PCI_QSPAN if !4xx && !CPM2 && 8xx | 709 | default PCI_QSPAN if !4xx && !CPM2 && 8xx |
| 685 | select ARCH_SUPPORTS_MSI | 710 | select ARCH_SUPPORTS_MSI |
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index bf3382f1904d..5cdd7ed9a12e 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug | |||
| @@ -254,6 +254,14 @@ config PPC_EARLY_DEBUG_CPM | |||
| 254 | using a CPM-based serial port. This assumes that the bootwrapper | 254 | using a CPM-based serial port. This assumes that the bootwrapper |
| 255 | has run, and set up the CPM in a particular way. | 255 | has run, and set up the CPM in a particular way. |
| 256 | 256 | ||
| 257 | config PPC_EARLY_DEBUG_USBGECKO | ||
| 258 | bool "Early debugging through the USB Gecko adapter" | ||
| 259 | depends on GAMECUBE_COMMON | ||
| 260 | select USBGECKO_UDBG | ||
| 261 | help | ||
| 262 | Select this to enable early debugging for Nintendo GameCube/Wii | ||
| 263 | consoles via an external USB Gecko adapter. | ||
| 264 | |||
| 257 | endchoice | 265 | endchoice |
| 258 | 266 | ||
| 259 | config PPC_EARLY_DEBUG_44x_PHYSLOW | 267 | config PPC_EARLY_DEBUG_44x_PHYSLOW |
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 7bfc8ad87798..bb2465bcb327 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile | |||
| @@ -66,7 +66,7 @@ src-wlib := string.S crt0.S crtsavres.S stdio.c main.c \ | |||
| 66 | gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \ | 66 | gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \ |
| 67 | 4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \ | 67 | 4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \ |
| 68 | cpm-serial.c stdlib.c mpc52xx-psc.c planetcore.c uartlite.c \ | 68 | cpm-serial.c stdlib.c mpc52xx-psc.c planetcore.c uartlite.c \ |
| 69 | fsl-soc.c mpc8xx.c pq2.c | 69 | fsl-soc.c mpc8xx.c pq2.c ugecon.c |
| 70 | src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c \ | 70 | src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c \ |
| 71 | cuboot-ebony.c cuboot-hotfoot.c treeboot-ebony.c prpmc2800.c \ | 71 | cuboot-ebony.c cuboot-hotfoot.c treeboot-ebony.c prpmc2800.c \ |
| 72 | ps3-head.S ps3-hvcall.S ps3.c treeboot-bamboo.c cuboot-8xx.c \ | 72 | ps3-head.S ps3-hvcall.S ps3.c treeboot-bamboo.c cuboot-8xx.c \ |
| @@ -76,7 +76,8 @@ src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c | |||
| 76 | cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c \ | 76 | cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c \ |
| 77 | cuboot-warp.c cuboot-85xx-cpm2.c cuboot-yosemite.c simpleboot.c \ | 77 | cuboot-warp.c cuboot-85xx-cpm2.c cuboot-yosemite.c simpleboot.c \ |
| 78 | virtex405-head.S virtex.c redboot-83xx.c cuboot-sam440ep.c \ | 78 | virtex405-head.S virtex.c redboot-83xx.c cuboot-sam440ep.c \ |
| 79 | cuboot-acadia.c cuboot-amigaone.c cuboot-kilauea.c | 79 | cuboot-acadia.c cuboot-amigaone.c cuboot-kilauea.c \ |
| 80 | gamecube-head.S gamecube.c wii-head.S wii.c | ||
| 80 | src-boot := $(src-wlib) $(src-plat) empty.c | 81 | src-boot := $(src-wlib) $(src-plat) empty.c |
| 81 | 82 | ||
| 82 | src-boot := $(addprefix $(obj)/, $(src-boot)) | 83 | src-boot := $(addprefix $(obj)/, $(src-boot)) |
| @@ -254,6 +255,8 @@ image-$(CONFIG_KSI8560) += cuImage.ksi8560 | |||
| 254 | image-$(CONFIG_STORCENTER) += cuImage.storcenter | 255 | image-$(CONFIG_STORCENTER) += cuImage.storcenter |
| 255 | image-$(CONFIG_MPC7448HPC2) += cuImage.mpc7448hpc2 | 256 | image-$(CONFIG_MPC7448HPC2) += cuImage.mpc7448hpc2 |
| 256 | image-$(CONFIG_PPC_C2K) += cuImage.c2k | 257 | image-$(CONFIG_PPC_C2K) += cuImage.c2k |
| 258 | image-$(CONFIG_GAMECUBE) += dtbImage.gamecube | ||
| 259 | image-$(CONFIG_WII) += dtbImage.wii | ||
| 257 | 260 | ||
| 258 | # Board port in arch/powerpc/platform/amigaone/Kconfig | 261 | # Board port in arch/powerpc/platform/amigaone/Kconfig |
| 259 | image-$(CONFIG_AMIGAONE) += cuImage.amigaone | 262 | image-$(CONFIG_AMIGAONE) += cuImage.amigaone |
diff --git a/arch/powerpc/boot/dts/canyonlands.dts b/arch/powerpc/boot/dts/canyonlands.dts index c920170b7dfe..cd56bb5b347b 100644 --- a/arch/powerpc/boot/dts/canyonlands.dts +++ b/arch/powerpc/boot/dts/canyonlands.dts | |||
| @@ -352,6 +352,7 @@ | |||
| 352 | max-frame-size = <9000>; | 352 | max-frame-size = <9000>; |
| 353 | rx-fifo-size = <4096>; | 353 | rx-fifo-size = <4096>; |
| 354 | tx-fifo-size = <2048>; | 354 | tx-fifo-size = <2048>; |
| 355 | rx-fifo-size-gige = <16384>; | ||
| 355 | phy-mode = "rgmii"; | 356 | phy-mode = "rgmii"; |
| 356 | phy-map = <0x00000000>; | 357 | phy-map = <0x00000000>; |
| 357 | rgmii-device = <&RGMII0>; | 358 | rgmii-device = <&RGMII0>; |
| @@ -381,6 +382,7 @@ | |||
| 381 | max-frame-size = <9000>; | 382 | max-frame-size = <9000>; |
| 382 | rx-fifo-size = <4096>; | 383 | rx-fifo-size = <4096>; |
| 383 | tx-fifo-size = <2048>; | 384 | tx-fifo-size = <2048>; |
| 385 | rx-fifo-size-gige = <16384>; | ||
| 384 | phy-mode = "rgmii"; | 386 | phy-mode = "rgmii"; |
| 385 | phy-map = <0x00000000>; | 387 | phy-map = <0x00000000>; |
| 386 | rgmii-device = <&RGMII0>; | 388 | rgmii-device = <&RGMII0>; |
diff --git a/arch/powerpc/boot/dts/eiger.dts b/arch/powerpc/boot/dts/eiger.dts index c4a934f2e886..48bcf7187924 100644 --- a/arch/powerpc/boot/dts/eiger.dts +++ b/arch/powerpc/boot/dts/eiger.dts | |||
| @@ -316,6 +316,7 @@ | |||
| 316 | max-frame-size = <9000>; | 316 | max-frame-size = <9000>; |
| 317 | rx-fifo-size = <4096>; | 317 | rx-fifo-size = <4096>; |
| 318 | tx-fifo-size = <2048>; | 318 | tx-fifo-size = <2048>; |
| 319 | rx-fifo-size-gige = <16384>; | ||
| 319 | phy-mode = "rgmii"; | 320 | phy-mode = "rgmii"; |
| 320 | phy-map = <0x00000000>; | 321 | phy-map = <0x00000000>; |
| 321 | rgmii-device = <&RGMII0>; | 322 | rgmii-device = <&RGMII0>; |
| @@ -345,6 +346,7 @@ | |||
| 345 | max-frame-size = <9000>; | 346 | max-frame-size = <9000>; |
| 346 | rx-fifo-size = <4096>; | 347 | rx-fifo-size = <4096>; |
| 347 | tx-fifo-size = <2048>; | 348 | tx-fifo-size = <2048>; |
| 349 | rx-fifo-size-gige = <16384>; | ||
| 348 | phy-mode = "rgmii"; | 350 | phy-mode = "rgmii"; |
| 349 | phy-map = <0x00000000>; | 351 | phy-map = <0x00000000>; |
| 350 | rgmii-device = <&RGMII0>; | 352 | rgmii-device = <&RGMII0>; |
| @@ -375,6 +377,8 @@ | |||
| 375 | max-frame-size = <9000>; | 377 | max-frame-size = <9000>; |
| 376 | rx-fifo-size = <4096>; | 378 | rx-fifo-size = <4096>; |
| 377 | tx-fifo-size = <2048>; | 379 | tx-fifo-size = <2048>; |
| 380 | rx-fifo-size-gige = <16384>; | ||
| 381 | tx-fifo-size-gige = <16384>; /* emac2&3 only */ | ||
| 378 | phy-mode = "rgmii"; | 382 | phy-mode = "rgmii"; |
| 379 | phy-map = <0x00000000>; | 383 | phy-map = <0x00000000>; |
| 380 | rgmii-device = <&RGMII1>; | 384 | rgmii-device = <&RGMII1>; |
| @@ -403,6 +407,8 @@ | |||
| 403 | max-frame-size = <9000>; | 407 | max-frame-size = <9000>; |
| 404 | rx-fifo-size = <4096>; | 408 | rx-fifo-size = <4096>; |
| 405 | tx-fifo-size = <2048>; | 409 | tx-fifo-size = <2048>; |
| 410 | rx-fifo-size-gige = <16384>; | ||
| 411 | tx-fifo-size-gige = <16384>; /* emac2&3 only */ | ||
| 406 | phy-mode = "rgmii"; | 412 | phy-mode = "rgmii"; |
| 407 | phy-map = <0x00000000>; | 413 | phy-map = <0x00000000>; |
| 408 | rgmii-device = <&RGMII1>; | 414 | rgmii-device = <&RGMII1>; |
diff --git a/arch/powerpc/boot/dts/gamecube.dts b/arch/powerpc/boot/dts/gamecube.dts new file mode 100644 index 000000000000..ef3be0e58b02 --- /dev/null +++ b/arch/powerpc/boot/dts/gamecube.dts | |||
| @@ -0,0 +1,114 @@ | |||
| 1 | /* | ||
| 2 | * arch/powerpc/boot/dts/gamecube.dts | ||
| 3 | * | ||
| 4 | * Nintendo GameCube platform device tree source | ||
| 5 | * Copyright (C) 2007-2009 The GameCube Linux Team | ||
| 6 | * Copyright (C) 2007,2008,2009 Albert Herranz | ||
| 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 | ||
| 10 | * as published by the Free Software Foundation; either version 2 | ||
| 11 | * of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | /dts-v1/; | ||
| 16 | |||
| 17 | / { | ||
| 18 | model = "nintendo,gamecube"; | ||
| 19 | compatible = "nintendo,gamecube"; | ||
| 20 | #address-cells = <1>; | ||
| 21 | #size-cells = <1>; | ||
| 22 | |||
| 23 | chosen { | ||
| 24 | bootargs = "root=/dev/gcnsda2 rootwait udbg-immortal"; | ||
| 25 | }; | ||
| 26 | |||
| 27 | memory { | ||
| 28 | device_type = "memory"; | ||
| 29 | reg = <0x00000000 0x01800000>; | ||
| 30 | }; | ||
| 31 | |||
| 32 | cpus { | ||
| 33 | #address-cells = <1>; | ||
| 34 | #size-cells = <0>; | ||
| 35 | |||
| 36 | PowerPC,gekko@0 { | ||
| 37 | device_type = "cpu"; | ||
| 38 | reg = <0>; | ||
| 39 | clock-frequency = <486000000>; /* 486MHz */ | ||
| 40 | bus-frequency = <162000000>; /* 162MHz core-to-bus 3x */ | ||
| 41 | timebase-frequency = <40500000>; /* 162MHz / 4 */ | ||
| 42 | i-cache-line-size = <32>; | ||
| 43 | d-cache-line-size = <32>; | ||
| 44 | i-cache-size = <32768>; | ||
| 45 | d-cache-size = <32768>; | ||
| 46 | }; | ||
| 47 | }; | ||
| 48 | |||
| 49 | /* devices contained int the flipper chipset */ | ||
| 50 | flipper { | ||
| 51 | #address-cells = <1>; | ||
| 52 | #size-cells = <1>; | ||
| 53 | compatible = "nintendo,flipper"; | ||
| 54 | ranges = <0x0c000000 0x0c000000 0x00010000>; | ||
| 55 | interrupt-parent = <&PIC>; | ||
| 56 | |||
| 57 | video@0c002000 { | ||
| 58 | compatible = "nintendo,flipper-vi"; | ||
| 59 | reg = <0x0c002000 0x100>; | ||
| 60 | interrupts = <8>; | ||
| 61 | }; | ||
| 62 | |||
| 63 | processor-interface@0c003000 { | ||
| 64 | compatible = "nintendo,flipper-pi"; | ||
| 65 | reg = <0x0c003000 0x100>; | ||
| 66 | |||
| 67 | PIC: pic { | ||
| 68 | #interrupt-cells = <1>; | ||
| 69 | compatible = "nintendo,flipper-pic"; | ||
| 70 | interrupt-controller; | ||
| 71 | }; | ||
| 72 | }; | ||
| 73 | |||
| 74 | dsp@0c005000 { | ||
| 75 | #address-cells = <1>; | ||
| 76 | #size-cells = <1>; | ||
| 77 | compatible = "nintendo,flipper-dsp"; | ||
| 78 | reg = <0x0c005000 0x200>; | ||
| 79 | interrupts = <6>; | ||
| 80 | |||
| 81 | memory@0 { | ||
| 82 | compatible = "nintendo,flipper-aram"; | ||
| 83 | reg = <0 0x1000000>; /* 16MB */ | ||
| 84 | }; | ||
| 85 | }; | ||
| 86 | |||
| 87 | disk@0c006000 { | ||
| 88 | compatible = "nintendo,flipper-di"; | ||
| 89 | reg = <0x0c006000 0x40>; | ||
| 90 | interrupts = <2>; | ||
| 91 | }; | ||
| 92 | |||
| 93 | audio@0c006c00 { | ||
| 94 | compatible = "nintendo,flipper-ai"; | ||
| 95 | reg = <0x0c006c00 0x20>; | ||
| 96 | interrupts = <6>; | ||
| 97 | }; | ||
| 98 | |||
| 99 | gamepad-controller@0c006400 { | ||
| 100 | compatible = "nintendo,flipper-si"; | ||
| 101 | reg = <0x0c006400 0x100>; | ||
| 102 | interrupts = <3>; | ||
| 103 | }; | ||
| 104 | |||
| 105 | /* External Interface bus */ | ||
| 106 | exi@0c006800 { | ||
| 107 | compatible = "nintendo,flipper-exi"; | ||
| 108 | reg = <0x0c006800 0x40>; | ||
| 109 | virtual-reg = <0x0c006800>; | ||
| 110 | interrupts = <4>; | ||
| 111 | }; | ||
| 112 | }; | ||
| 113 | }; | ||
| 114 | |||
diff --git a/arch/powerpc/boot/dts/gef_ppc9a.dts b/arch/powerpc/boot/dts/gef_ppc9a.dts index 910944edd886..c86114e93f1e 100644 --- a/arch/powerpc/boot/dts/gef_ppc9a.dts +++ b/arch/powerpc/boot/dts/gef_ppc9a.dts | |||
| @@ -118,6 +118,12 @@ | |||
| 118 | }; | 118 | }; |
| 119 | }; | 119 | }; |
| 120 | 120 | ||
| 121 | nvram@3,0 { | ||
| 122 | device_type = "nvram"; | ||
| 123 | compatible = "simtek,stk14ca8"; | ||
| 124 | reg = <0x3 0x0 0x20000>; | ||
| 125 | }; | ||
| 126 | |||
| 121 | fpga@4,0 { | 127 | fpga@4,0 { |
| 122 | compatible = "gef,ppc9a-fpga-regs"; | 128 | compatible = "gef,ppc9a-fpga-regs"; |
| 123 | reg = <0x4 0x0 0x40>; | 129 | reg = <0x4 0x0 0x40>; |
diff --git a/arch/powerpc/boot/dts/gef_sbc310.dts b/arch/powerpc/boot/dts/gef_sbc310.dts index 2107d3c7cfe1..820c2b355ab1 100644 --- a/arch/powerpc/boot/dts/gef_sbc310.dts +++ b/arch/powerpc/boot/dts/gef_sbc310.dts | |||
| @@ -115,6 +115,12 @@ | |||
| 115 | }; | 115 | }; |
| 116 | }; | 116 | }; |
| 117 | 117 | ||
| 118 | nvram@3,0 { | ||
| 119 | device_type = "nvram"; | ||
| 120 | compatible = "simtek,stk14ca8"; | ||
| 121 | reg = <0x3 0x0 0x20000>; | ||
| 122 | }; | ||
| 123 | |||
| 118 | fpga@4,0 { | 124 | fpga@4,0 { |
| 119 | compatible = "gef,fpga-regs"; | 125 | compatible = "gef,fpga-regs"; |
| 120 | reg = <0x4 0x0 0x40>; | 126 | reg = <0x4 0x0 0x40>; |
diff --git a/arch/powerpc/boot/dts/gef_sbc610.dts b/arch/powerpc/boot/dts/gef_sbc610.dts index 35a63183eecc..30911adefc8e 100644 --- a/arch/powerpc/boot/dts/gef_sbc610.dts +++ b/arch/powerpc/boot/dts/gef_sbc610.dts | |||
| @@ -84,6 +84,12 @@ | |||
| 84 | 6 0 0xfd000000 0x00800000 // IO FPGA (8-bit) | 84 | 6 0 0xfd000000 0x00800000 // IO FPGA (8-bit) |
| 85 | 7 0 0xfd800000 0x00800000>; // IO FPGA (32-bit) | 85 | 7 0 0xfd800000 0x00800000>; // IO FPGA (32-bit) |
| 86 | 86 | ||
| 87 | nvram@3,0 { | ||
| 88 | device_type = "nvram"; | ||
| 89 | compatible = "simtek,stk14ca8"; | ||
| 90 | reg = <0x3 0x0 0x20000>; | ||
| 91 | }; | ||
| 92 | |||
| 87 | fpga@4,0 { | 93 | fpga@4,0 { |
| 88 | compatible = "gef,fpga-regs"; | 94 | compatible = "gef,fpga-regs"; |
| 89 | reg = <0x4 0x0 0x40>; | 95 | reg = <0x4 0x0 0x40>; |
diff --git a/arch/powerpc/boot/dts/glacier.dts b/arch/powerpc/boot/dts/glacier.dts index f3787a27f634..f6f618939293 100644 --- a/arch/powerpc/boot/dts/glacier.dts +++ b/arch/powerpc/boot/dts/glacier.dts | |||
| @@ -292,6 +292,7 @@ | |||
| 292 | max-frame-size = <9000>; | 292 | max-frame-size = <9000>; |
| 293 | rx-fifo-size = <4096>; | 293 | rx-fifo-size = <4096>; |
| 294 | tx-fifo-size = <2048>; | 294 | tx-fifo-size = <2048>; |
| 295 | rx-fifo-size-gige = <16384>; | ||
| 295 | phy-mode = "rgmii"; | 296 | phy-mode = "rgmii"; |
| 296 | phy-map = <0x00000000>; | 297 | phy-map = <0x00000000>; |
| 297 | rgmii-device = <&RGMII0>; | 298 | rgmii-device = <&RGMII0>; |
| @@ -321,6 +322,7 @@ | |||
| 321 | max-frame-size = <9000>; | 322 | max-frame-size = <9000>; |
| 322 | rx-fifo-size = <4096>; | 323 | rx-fifo-size = <4096>; |
| 323 | tx-fifo-size = <2048>; | 324 | tx-fifo-size = <2048>; |
| 325 | rx-fifo-size-gige = <16384>; | ||
| 324 | phy-mode = "rgmii"; | 326 | phy-mode = "rgmii"; |
| 325 | phy-map = <0x00000000>; | 327 | phy-map = <0x00000000>; |
| 326 | rgmii-device = <&RGMII0>; | 328 | rgmii-device = <&RGMII0>; |
| @@ -351,6 +353,8 @@ | |||
| 351 | max-frame-size = <9000>; | 353 | max-frame-size = <9000>; |
| 352 | rx-fifo-size = <4096>; | 354 | rx-fifo-size = <4096>; |
| 353 | tx-fifo-size = <2048>; | 355 | tx-fifo-size = <2048>; |
| 356 | rx-fifo-size-gige = <16384>; | ||
| 357 | tx-fifo-size-gige = <16384>; /* emac2&3 only */ | ||
| 354 | phy-mode = "rgmii"; | 358 | phy-mode = "rgmii"; |
| 355 | phy-map = <0x00000000>; | 359 | phy-map = <0x00000000>; |
| 356 | rgmii-device = <&RGMII1>; | 360 | rgmii-device = <&RGMII1>; |
| @@ -379,6 +383,8 @@ | |||
| 379 | max-frame-size = <9000>; | 383 | max-frame-size = <9000>; |
| 380 | rx-fifo-size = <4096>; | 384 | rx-fifo-size = <4096>; |
| 381 | tx-fifo-size = <2048>; | 385 | tx-fifo-size = <2048>; |
| 386 | rx-fifo-size-gige = <16384>; | ||
| 387 | tx-fifo-size-gige = <16384>; /* emac2&3 only */ | ||
| 382 | phy-mode = "rgmii"; | 388 | phy-mode = "rgmii"; |
| 383 | phy-map = <0x00000000>; | 389 | phy-map = <0x00000000>; |
| 384 | rgmii-device = <&RGMII1>; | 390 | rgmii-device = <&RGMII1>; |
diff --git a/arch/powerpc/boot/dts/haleakala.dts b/arch/powerpc/boot/dts/haleakala.dts index 5b2a4947bf82..2b256694eca6 100644 --- a/arch/powerpc/boot/dts/haleakala.dts +++ b/arch/powerpc/boot/dts/haleakala.dts | |||
| @@ -226,6 +226,8 @@ | |||
| 226 | max-frame-size = <9000>; | 226 | max-frame-size = <9000>; |
| 227 | rx-fifo-size = <4096>; | 227 | rx-fifo-size = <4096>; |
| 228 | tx-fifo-size = <2048>; | 228 | tx-fifo-size = <2048>; |
| 229 | rx-fifo-size-gige = <16384>; | ||
| 230 | tx-fifo-size-gige = <16384>; | ||
| 229 | phy-mode = "rgmii"; | 231 | phy-mode = "rgmii"; |
| 230 | phy-map = <0x00000000>; | 232 | phy-map = <0x00000000>; |
| 231 | rgmii-device = <&RGMII0>; | 233 | rgmii-device = <&RGMII0>; |
diff --git a/arch/powerpc/boot/dts/katmai.dts b/arch/powerpc/boot/dts/katmai.dts index 077819bc3cbd..8f345de960cd 100644 --- a/arch/powerpc/boot/dts/katmai.dts +++ b/arch/powerpc/boot/dts/katmai.dts | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | / { | 17 | / { |
| 18 | #address-cells = <2>; | 18 | #address-cells = <2>; |
| 19 | #size-cells = <1>; | 19 | #size-cells = <2>; |
| 20 | model = "amcc,katmai"; | 20 | model = "amcc,katmai"; |
| 21 | compatible = "amcc,katmai"; | 21 | compatible = "amcc,katmai"; |
| 22 | dcr-parent = <&{/cpus/cpu@0}>; | 22 | dcr-parent = <&{/cpus/cpu@0}>; |
| @@ -49,7 +49,7 @@ | |||
| 49 | 49 | ||
| 50 | memory { | 50 | memory { |
| 51 | device_type = "memory"; | 51 | device_type = "memory"; |
| 52 | reg = <0x00000000 0x00000000 0x00000000>; /* Filled in by zImage */ | 52 | reg = <0x0 0x00000000 0x0 0x00000000>; /* Filled in by U-Boot */ |
| 53 | }; | 53 | }; |
| 54 | 54 | ||
| 55 | UIC0: interrupt-controller0 { | 55 | UIC0: interrupt-controller0 { |
| @@ -108,11 +108,26 @@ | |||
| 108 | dcr-reg = <0x00c 0x002>; | 108 | dcr-reg = <0x00c 0x002>; |
| 109 | }; | 109 | }; |
| 110 | 110 | ||
| 111 | MQ0: mq { | ||
| 112 | compatible = "ibm,mq-440spe"; | ||
| 113 | dcr-reg = <0x040 0x020>; | ||
| 114 | }; | ||
| 115 | |||
| 111 | plb { | 116 | plb { |
| 112 | compatible = "ibm,plb-440spe", "ibm,plb-440gp", "ibm,plb4"; | 117 | compatible = "ibm,plb-440spe", "ibm,plb-440gp", "ibm,plb4"; |
| 113 | #address-cells = <2>; | 118 | #address-cells = <2>; |
| 114 | #size-cells = <1>; | 119 | #size-cells = <1>; |
| 115 | ranges; | 120 | /* addr-child addr-parent size */ |
| 121 | ranges = <0x4 0x00100000 0x4 0x00100000 0x00001000 | ||
| 122 | 0x4 0x00200000 0x4 0x00200000 0x00000400 | ||
| 123 | 0x4 0xe0000000 0x4 0xe0000000 0x20000000 | ||
| 124 | 0xc 0x00000000 0xc 0x00000000 0x20000000 | ||
| 125 | 0xd 0x00000000 0xd 0x00000000 0x80000000 | ||
| 126 | 0xd 0x80000000 0xd 0x80000000 0x80000000 | ||
| 127 | 0xe 0x00000000 0xe 0x00000000 0x80000000 | ||
| 128 | 0xe 0x80000000 0xe 0x80000000 0x80000000 | ||
| 129 | 0xf 0x00000000 0xf 0x00000000 0x80000000 | ||
| 130 | 0xf 0x80000000 0xf 0x80000000 0x80000000>; | ||
| 116 | clock-frequency = <0>; /* Filled in by zImage */ | 131 | clock-frequency = <0>; /* Filled in by zImage */ |
| 117 | 132 | ||
| 118 | SDRAM0: sdram { | 133 | SDRAM0: sdram { |
| @@ -245,8 +260,8 @@ | |||
| 245 | ranges = <0x02000000 0x00000000 0x80000000 0x0000000d 0x80000000 0x00000000 0x80000000 | 260 | ranges = <0x02000000 0x00000000 0x80000000 0x0000000d 0x80000000 0x00000000 0x80000000 |
| 246 | 0x01000000 0x00000000 0x00000000 0x0000000c 0x08000000 0x00000000 0x00010000>; | 261 | 0x01000000 0x00000000 0x00000000 0x0000000c 0x08000000 0x00000000 0x00010000>; |
| 247 | 262 | ||
| 248 | /* Inbound 2GB range starting at 0 */ | 263 | /* Inbound 4GB range starting at 0 */ |
| 249 | dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>; | 264 | dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x1 0x00000000>; |
| 250 | 265 | ||
| 251 | /* This drives busses 0 to 0xf */ | 266 | /* This drives busses 0 to 0xf */ |
| 252 | bus-range = <0x0 0xf>; | 267 | bus-range = <0x0 0xf>; |
| @@ -289,10 +304,10 @@ | |||
| 289 | ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x00000000 0x00000000 0x80000000 | 304 | ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x00000000 0x00000000 0x80000000 |
| 290 | 0x01000000 0x00000000 0x00000000 0x0000000f 0x80000000 0x00000000 0x00010000>; | 305 | 0x01000000 0x00000000 0x00000000 0x0000000f 0x80000000 0x00000000 0x00010000>; |
| 291 | 306 | ||
| 292 | /* Inbound 2GB range starting at 0 */ | 307 | /* Inbound 4GB range starting at 0 */ |
| 293 | dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>; | 308 | dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x1 0x00000000>; |
| 294 | 309 | ||
| 295 | /* This drives busses 10 to 0x1f */ | 310 | /* This drives busses 0x10 to 0x1f */ |
| 296 | bus-range = <0x10 0x1f>; | 311 | bus-range = <0x10 0x1f>; |
| 297 | 312 | ||
| 298 | /* Legacy interrupts (note the weird polarity, the bridge seems | 313 | /* Legacy interrupts (note the weird polarity, the bridge seems |
| @@ -330,10 +345,10 @@ | |||
| 330 | ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x80000000 0x00000000 0x80000000 | 345 | ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x80000000 0x00000000 0x80000000 |
| 331 | 0x01000000 0x00000000 0x00000000 0x0000000f 0x80010000 0x00000000 0x00010000>; | 346 | 0x01000000 0x00000000 0x00000000 0x0000000f 0x80010000 0x00000000 0x00010000>; |
| 332 | 347 | ||
| 333 | /* Inbound 2GB range starting at 0 */ | 348 | /* Inbound 4GB range starting at 0 */ |
| 334 | dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>; | 349 | dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x1 0x00000000>; |
| 335 | 350 | ||
| 336 | /* This drives busses 10 to 0x1f */ | 351 | /* This drives busses 0x20 to 0x2f */ |
| 337 | bus-range = <0x20 0x2f>; | 352 | bus-range = <0x20 0x2f>; |
| 338 | 353 | ||
| 339 | /* Legacy interrupts (note the weird polarity, the bridge seems | 354 | /* Legacy interrupts (note the weird polarity, the bridge seems |
| @@ -371,10 +386,10 @@ | |||
| 371 | ranges = <0x02000000 0x00000000 0x80000000 0x0000000f 0x00000000 0x00000000 0x80000000 | 386 | ranges = <0x02000000 0x00000000 0x80000000 0x0000000f 0x00000000 0x00000000 0x80000000 |
| 372 | 0x01000000 0x00000000 0x00000000 0x0000000f 0x80020000 0x00000000 0x00010000>; | 387 | 0x01000000 0x00000000 0x00000000 0x0000000f 0x80020000 0x00000000 0x00010000>; |
| 373 | 388 | ||
| 374 | /* Inbound 2GB range starting at 0 */ | 389 | /* Inbound 4GB range starting at 0 */ |
| 375 | dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>; | 390 | dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x1 0x00000000>; |
| 376 | 391 | ||
| 377 | /* This drives busses 10 to 0x1f */ | 392 | /* This drives busses 0x30 to 0x3f */ |
| 378 | bus-range = <0x30 0x3f>; | 393 | bus-range = <0x30 0x3f>; |
| 379 | 394 | ||
| 380 | /* Legacy interrupts (note the weird polarity, the bridge seems | 395 | /* Legacy interrupts (note the weird polarity, the bridge seems |
| @@ -392,6 +407,49 @@ | |||
| 392 | 0x0 0x0 0x0 0x3 &UIC3 0xa 0x4 /* swizzled int C */ | 407 | 0x0 0x0 0x0 0x3 &UIC3 0xa 0x4 /* swizzled int C */ |
| 393 | 0x0 0x0 0x0 0x4 &UIC3 0xb 0x4 /* swizzled int D */>; | 408 | 0x0 0x0 0x0 0x4 &UIC3 0xb 0x4 /* swizzled int D */>; |
| 394 | }; | 409 | }; |
| 410 | |||
| 411 | I2O: i2o@400100000 { | ||
| 412 | compatible = "ibm,i2o-440spe"; | ||
| 413 | reg = <0x00000004 0x00100000 0x100>; | ||
| 414 | dcr-reg = <0x060 0x020>; | ||
| 415 | }; | ||
| 416 | |||
| 417 | DMA0: dma0@400100100 { | ||
| 418 | compatible = "ibm,dma-440spe"; | ||
| 419 | cell-index = <0>; | ||
| 420 | reg = <0x00000004 0x00100100 0x100>; | ||
| 421 | dcr-reg = <0x060 0x020>; | ||
| 422 | interrupt-parent = <&DMA0>; | ||
| 423 | interrupts = <0 1>; | ||
| 424 | #interrupt-cells = <1>; | ||
| 425 | #address-cells = <0>; | ||
| 426 | #size-cells = <0>; | ||
| 427 | interrupt-map = < | ||
| 428 | 0 &UIC0 0x14 4 | ||
| 429 | 1 &UIC1 0x16 4>; | ||
| 430 | }; | ||
| 431 | |||
| 432 | DMA1: dma1@400100200 { | ||
| 433 | compatible = "ibm,dma-440spe"; | ||
| 434 | cell-index = <1>; | ||
| 435 | reg = <0x00000004 0x00100200 0x100>; | ||
| 436 | dcr-reg = <0x060 0x020>; | ||
| 437 | interrupt-parent = <&DMA1>; | ||
| 438 | interrupts = <0 1>; | ||
| 439 | #interrupt-cells = <1>; | ||
| 440 | #address-cells = <0>; | ||
| 441 | #size-cells = <0>; | ||
| 442 | interrupt-map = < | ||
| 443 | 0 &UIC0 0x16 4 | ||
| 444 | 1 &UIC1 0x16 4>; | ||
| 445 | }; | ||
| 446 | |||
| 447 | xor-accel@400200000 { | ||
| 448 | compatible = "amcc,xor-accelerator"; | ||
| 449 | reg = <0x00000004 0x00200000 0x400>; | ||
| 450 | interrupt-parent = <&UIC1>; | ||
| 451 | interrupts = <0x1f 4>; | ||
| 452 | }; | ||
| 395 | }; | 453 | }; |
| 396 | 454 | ||
| 397 | chosen { | 455 | chosen { |
diff --git a/arch/powerpc/boot/dts/kilauea.dts b/arch/powerpc/boot/dts/kilauea.dts index c46561456ede..083e68eeaca4 100644 --- a/arch/powerpc/boot/dts/kilauea.dts +++ b/arch/powerpc/boot/dts/kilauea.dts | |||
| @@ -272,6 +272,8 @@ | |||
| 272 | max-frame-size = <9000>; | 272 | max-frame-size = <9000>; |
| 273 | rx-fifo-size = <4096>; | 273 | rx-fifo-size = <4096>; |
| 274 | tx-fifo-size = <2048>; | 274 | tx-fifo-size = <2048>; |
| 275 | rx-fifo-size-gige = <16384>; | ||
| 276 | tx-fifo-size-gige = <16384>; | ||
| 275 | phy-mode = "rgmii"; | 277 | phy-mode = "rgmii"; |
| 276 | phy-map = <0x00000000>; | 278 | phy-map = <0x00000000>; |
| 277 | rgmii-device = <&RGMII0>; | 279 | rgmii-device = <&RGMII0>; |
| @@ -300,6 +302,8 @@ | |||
| 300 | max-frame-size = <9000>; | 302 | max-frame-size = <9000>; |
| 301 | rx-fifo-size = <4096>; | 303 | rx-fifo-size = <4096>; |
| 302 | tx-fifo-size = <2048>; | 304 | tx-fifo-size = <2048>; |
| 305 | rx-fifo-size-gige = <16384>; | ||
| 306 | tx-fifo-size-gige = <16384>; | ||
| 303 | phy-mode = "rgmii"; | 307 | phy-mode = "rgmii"; |
| 304 | phy-map = <0x00000000>; | 308 | phy-map = <0x00000000>; |
| 305 | rgmii-device = <&RGMII0>; | 309 | rgmii-device = <&RGMII0>; |
diff --git a/arch/powerpc/boot/dts/kmeter1.dts b/arch/powerpc/boot/dts/kmeter1.dts index 167044f7de1d..65b8b4f27efe 100644 --- a/arch/powerpc/boot/dts/kmeter1.dts +++ b/arch/powerpc/boot/dts/kmeter1.dts | |||
| @@ -59,6 +59,13 @@ | |||
| 59 | reg = <0xe0000000 0x00000200>; | 59 | reg = <0xe0000000 0x00000200>; |
| 60 | bus-frequency = <0>; /* Filled in by U-Boot */ | 60 | bus-frequency = <0>; /* Filled in by U-Boot */ |
| 61 | 61 | ||
| 62 | pmc: power@b00 { | ||
| 63 | compatible = "fsl,mpc8360-pmc", "fsl,mpc8349-pmc"; | ||
| 64 | reg = <0xb00 0x100 0xa00 0x100>; | ||
| 65 | interrupts = <80 0x8>; | ||
| 66 | interrupt-parent = <&ipic>; | ||
| 67 | }; | ||
| 68 | |||
| 62 | i2c@3000 { | 69 | i2c@3000 { |
| 63 | #address-cells = <1>; | 70 | #address-cells = <1>; |
| 64 | #size-cells = <0>; | 71 | #size-cells = <0>; |
diff --git a/arch/powerpc/boot/dts/makalu.dts b/arch/powerpc/boot/dts/makalu.dts index ffc246e72670..63d48b632c84 100644 --- a/arch/powerpc/boot/dts/makalu.dts +++ b/arch/powerpc/boot/dts/makalu.dts | |||
| @@ -227,6 +227,8 @@ | |||
| 227 | max-frame-size = <9000>; | 227 | max-frame-size = <9000>; |
| 228 | rx-fifo-size = <4096>; | 228 | rx-fifo-size = <4096>; |
| 229 | tx-fifo-size = <2048>; | 229 | tx-fifo-size = <2048>; |
| 230 | rx-fifo-size-gige = <16384>; | ||
| 231 | tx-fifo-size-gige = <16384>; | ||
| 230 | phy-mode = "rgmii"; | 232 | phy-mode = "rgmii"; |
| 231 | phy-map = <0x0000003f>; /* Start at 6 */ | 233 | phy-map = <0x0000003f>; /* Start at 6 */ |
| 232 | rgmii-device = <&RGMII0>; | 234 | rgmii-device = <&RGMII0>; |
| @@ -255,6 +257,8 @@ | |||
| 255 | max-frame-size = <9000>; | 257 | max-frame-size = <9000>; |
| 256 | rx-fifo-size = <4096>; | 258 | rx-fifo-size = <4096>; |
| 257 | tx-fifo-size = <2048>; | 259 | tx-fifo-size = <2048>; |
| 260 | rx-fifo-size-gige = <16384>; | ||
| 261 | tx-fifo-size-gige = <16384>; | ||
| 258 | phy-mode = "rgmii"; | 262 | phy-mode = "rgmii"; |
| 259 | phy-map = <0x00000000>; | 263 | phy-map = <0x00000000>; |
| 260 | rgmii-device = <&RGMII0>; | 264 | rgmii-device = <&RGMII0>; |
diff --git a/arch/powerpc/boot/dts/mpc8315erdb.dts b/arch/powerpc/boot/dts/mpc8315erdb.dts index 32e10f588c1d..8a3a4f3ef831 100644 --- a/arch/powerpc/boot/dts/mpc8315erdb.dts +++ b/arch/powerpc/boot/dts/mpc8315erdb.dts | |||
| @@ -204,6 +204,7 @@ | |||
| 204 | interrupt-parent = <&ipic>; | 204 | interrupt-parent = <&ipic>; |
| 205 | tbi-handle = <&tbi0>; | 205 | tbi-handle = <&tbi0>; |
| 206 | phy-handle = < &phy0 >; | 206 | phy-handle = < &phy0 >; |
| 207 | fsl,magic-packet; | ||
| 207 | 208 | ||
| 208 | mdio@520 { | 209 | mdio@520 { |
| 209 | #address-cells = <1>; | 210 | #address-cells = <1>; |
| @@ -246,6 +247,7 @@ | |||
| 246 | interrupt-parent = <&ipic>; | 247 | interrupt-parent = <&ipic>; |
| 247 | tbi-handle = <&tbi1>; | 248 | tbi-handle = <&tbi1>; |
| 248 | phy-handle = < &phy1 >; | 249 | phy-handle = < &phy1 >; |
| 250 | fsl,magic-packet; | ||
| 249 | 251 | ||
| 250 | mdio@520 { | 252 | mdio@520 { |
| 251 | #address-cells = <1>; | 253 | #address-cells = <1>; |
| @@ -309,6 +311,22 @@ | |||
| 309 | interrupt-parent = <&ipic>; | 311 | interrupt-parent = <&ipic>; |
| 310 | }; | 312 | }; |
| 311 | 313 | ||
| 314 | gtm1: timer@500 { | ||
| 315 | compatible = "fsl,mpc8315-gtm", "fsl,gtm"; | ||
| 316 | reg = <0x500 0x100>; | ||
| 317 | interrupts = <90 8 78 8 84 8 72 8>; | ||
| 318 | interrupt-parent = <&ipic>; | ||
| 319 | clock-frequency = <133333333>; | ||
| 320 | }; | ||
| 321 | |||
| 322 | timer@600 { | ||
| 323 | compatible = "fsl,mpc8315-gtm", "fsl,gtm"; | ||
| 324 | reg = <0x600 0x100>; | ||
| 325 | interrupts = <91 8 79 8 85 8 73 8>; | ||
| 326 | interrupt-parent = <&ipic>; | ||
| 327 | clock-frequency = <133333333>; | ||
| 328 | }; | ||
| 329 | |||
| 312 | /* IPIC | 330 | /* IPIC |
| 313 | * interrupts cell = <intr #, sense> | 331 | * interrupts cell = <intr #, sense> |
| 314 | * sense values match linux IORESOURCE_IRQ_* defines: | 332 | * sense values match linux IORESOURCE_IRQ_* defines: |
| @@ -337,6 +355,15 @@ | |||
| 337 | 0x59 0x8>; | 355 | 0x59 0x8>; |
| 338 | interrupt-parent = < &ipic >; | 356 | interrupt-parent = < &ipic >; |
| 339 | }; | 357 | }; |
| 358 | |||
| 359 | pmc: power@b00 { | ||
| 360 | compatible = "fsl,mpc8315-pmc", "fsl,mpc8313-pmc", | ||
| 361 | "fsl,mpc8349-pmc"; | ||
| 362 | reg = <0xb00 0x100 0xa00 0x100>; | ||
| 363 | interrupts = <80 8>; | ||
| 364 | interrupt-parent = <&ipic>; | ||
| 365 | fsl,mpc8313-wakeup-timer = <>m1>; | ||
| 366 | }; | ||
| 340 | }; | 367 | }; |
| 341 | 368 | ||
| 342 | pci0: pci@e0008500 { | 369 | pci0: pci@e0008500 { |
diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts index 436c9c671dd9..05ad8c98e527 100644 --- a/arch/powerpc/boot/dts/mpc832x_mds.dts +++ b/arch/powerpc/boot/dts/mpc832x_mds.dts | |||
| @@ -79,6 +79,13 @@ | |||
| 79 | reg = <0x200 0x100>; | 79 | reg = <0x200 0x100>; |
| 80 | }; | 80 | }; |
| 81 | 81 | ||
| 82 | pmc: power@b00 { | ||
| 83 | compatible = "fsl,mpc8323-pmc", "fsl,mpc8349-pmc"; | ||
| 84 | reg = <0xb00 0x100 0xa00 0x100>; | ||
| 85 | interrupts = <80 0x8>; | ||
| 86 | interrupt-parent = <&ipic>; | ||
| 87 | }; | ||
| 88 | |||
| 82 | i2c@3000 { | 89 | i2c@3000 { |
| 83 | #address-cells = <1>; | 90 | #address-cells = <1>; |
| 84 | #size-cells = <0>; | 91 | #size-cells = <0>; |
| @@ -163,6 +170,7 @@ | |||
| 163 | fsl,channel-fifo-len = <24>; | 170 | fsl,channel-fifo-len = <24>; |
| 164 | fsl,exec-units-mask = <0x4c>; | 171 | fsl,exec-units-mask = <0x4c>; |
| 165 | fsl,descriptor-types-mask = <0x0122003f>; | 172 | fsl,descriptor-types-mask = <0x0122003f>; |
| 173 | sleep = <&pmc 0x03000000>; | ||
| 166 | }; | 174 | }; |
| 167 | 175 | ||
| 168 | ipic: pic@700 { | 176 | ipic: pic@700 { |
| @@ -428,5 +436,6 @@ | |||
| 428 | 0xe0008300 0x8>; /* config space access registers */ | 436 | 0xe0008300 0x8>; /* config space access registers */ |
| 429 | compatible = "fsl,mpc8349-pci"; | 437 | compatible = "fsl,mpc8349-pci"; |
| 430 | device_type = "pci"; | 438 | device_type = "pci"; |
| 439 | sleep = <&pmc 0x00010000>; | ||
| 431 | }; | 440 | }; |
| 432 | }; | 441 | }; |
diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts index 9a0952f74b81..f4fadb23ad6f 100644 --- a/arch/powerpc/boot/dts/mpc832x_rdb.dts +++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts | |||
| @@ -62,6 +62,13 @@ | |||
| 62 | reg = <0x200 0x100>; | 62 | reg = <0x200 0x100>; |
| 63 | }; | 63 | }; |
| 64 | 64 | ||
| 65 | pmc: power@b00 { | ||
| 66 | compatible = "fsl,mpc8323-pmc", "fsl,mpc8349-pmc"; | ||
| 67 | reg = <0xb00 0x100 0xa00 0x100>; | ||
| 68 | interrupts = <80 0x8>; | ||
| 69 | interrupt-parent = <&ipic>; | ||
| 70 | }; | ||
| 71 | |||
| 65 | i2c@3000 { | 72 | i2c@3000 { |
| 66 | #address-cells = <1>; | 73 | #address-cells = <1>; |
| 67 | #size-cells = <0>; | 74 | #size-cells = <0>; |
| @@ -141,6 +148,7 @@ | |||
| 141 | fsl,channel-fifo-len = <24>; | 148 | fsl,channel-fifo-len = <24>; |
| 142 | fsl,exec-units-mask = <0x4c>; | 149 | fsl,exec-units-mask = <0x4c>; |
| 143 | fsl,descriptor-types-mask = <0x0122003f>; | 150 | fsl,descriptor-types-mask = <0x0122003f>; |
| 151 | sleep = <&pmc 0x03000000>; | ||
| 144 | }; | 152 | }; |
| 145 | 153 | ||
| 146 | ipic:pic@700 { | 154 | ipic:pic@700 { |
| @@ -360,5 +368,6 @@ | |||
| 360 | 0xe0008300 0x8>; /* config space access registers */ | 368 | 0xe0008300 0x8>; /* config space access registers */ |
| 361 | compatible = "fsl,mpc8349-pci"; | 369 | compatible = "fsl,mpc8349-pci"; |
| 362 | device_type = "pci"; | 370 | device_type = "pci"; |
| 371 | sleep = <&pmc 0x00010000>; | ||
| 363 | }; | 372 | }; |
| 364 | }; | 373 | }; |
diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts index feeeb7f9d609..b53d1df11e2d 100644 --- a/arch/powerpc/boot/dts/mpc8349emitx.dts +++ b/arch/powerpc/boot/dts/mpc8349emitx.dts | |||
| @@ -63,6 +63,24 @@ | |||
| 63 | reg = <0x200 0x100>; | 63 | reg = <0x200 0x100>; |
| 64 | }; | 64 | }; |
| 65 | 65 | ||
| 66 | gpio1: gpio-controller@c00 { | ||
| 67 | #gpio-cells = <2>; | ||
| 68 | compatible = "fsl,mpc8349-gpio"; | ||
| 69 | reg = <0xc00 0x100>; | ||
| 70 | interrupts = <74 0x8>; | ||
| 71 | interrupt-parent = <&ipic>; | ||
| 72 | gpio-controller; | ||
| 73 | }; | ||
| 74 | |||
| 75 | gpio2: gpio-controller@d00 { | ||
| 76 | #gpio-cells = <2>; | ||
| 77 | compatible = "fsl,mpc8349-gpio"; | ||
| 78 | reg = <0xd00 0x100>; | ||
| 79 | interrupts = <75 0x8>; | ||
| 80 | interrupt-parent = <&ipic>; | ||
| 81 | gpio-controller; | ||
| 82 | }; | ||
| 83 | |||
| 66 | i2c@3000 { | 84 | i2c@3000 { |
| 67 | #address-cells = <1>; | 85 | #address-cells = <1>; |
| 68 | #size-cells = <0>; | 86 | #size-cells = <0>; |
| @@ -72,6 +90,12 @@ | |||
| 72 | interrupts = <14 0x8>; | 90 | interrupts = <14 0x8>; |
| 73 | interrupt-parent = <&ipic>; | 91 | interrupt-parent = <&ipic>; |
| 74 | dfsrr; | 92 | dfsrr; |
| 93 | |||
| 94 | eeprom: at24@50 { | ||
| 95 | compatible = "st-micro,24c256"; | ||
| 96 | reg = <0x50>; | ||
| 97 | }; | ||
| 98 | |||
| 75 | }; | 99 | }; |
| 76 | 100 | ||
| 77 | i2c@3100 { | 101 | i2c@3100 { |
| @@ -91,6 +115,25 @@ | |||
| 91 | interrupt-parent = <&ipic>; | 115 | interrupt-parent = <&ipic>; |
| 92 | }; | 116 | }; |
| 93 | 117 | ||
| 118 | pcf1: iexp@38 { | ||
| 119 | #gpio-cells = <2>; | ||
| 120 | compatible = "ti,pcf8574a"; | ||
| 121 | reg = <0x38>; | ||
| 122 | gpio-controller; | ||
| 123 | }; | ||
| 124 | |||
| 125 | pcf2: iexp@39 { | ||
| 126 | #gpio-cells = <2>; | ||
| 127 | compatible = "ti,pcf8574a"; | ||
| 128 | reg = <0x39>; | ||
| 129 | gpio-controller; | ||
| 130 | }; | ||
| 131 | |||
| 132 | spd: at24@51 { | ||
| 133 | compatible = "at24,spd"; | ||
| 134 | reg = <0x51>; | ||
| 135 | }; | ||
| 136 | |||
| 94 | mcu_pio: mcu@a { | 137 | mcu_pio: mcu@a { |
| 95 | #gpio-cells = <2>; | 138 | #gpio-cells = <2>; |
| 96 | compatible = "fsl,mc9s08qg8-mpc8349emitx", | 139 | compatible = "fsl,mc9s08qg8-mpc8349emitx", |
| @@ -275,6 +318,24 @@ | |||
| 275 | reg = <0x700 0x100>; | 318 | reg = <0x700 0x100>; |
| 276 | device_type = "ipic"; | 319 | device_type = "ipic"; |
| 277 | }; | 320 | }; |
| 321 | |||
| 322 | gpio-leds { | ||
| 323 | compatible = "gpio-leds"; | ||
| 324 | |||
| 325 | green { | ||
| 326 | label = "Green"; | ||
| 327 | gpios = <&pcf1 0 1>; | ||
| 328 | linux,default-trigger = "heartbeat"; | ||
| 329 | }; | ||
| 330 | |||
| 331 | yellow { | ||
| 332 | label = "Yellow"; | ||
| 333 | gpios = <&pcf1 1 1>; | ||
| 334 | /* linux,default-trigger = "heartbeat"; */ | ||
| 335 | default-state = "on"; | ||
| 336 | }; | ||
| 337 | }; | ||
| 338 | |||
| 278 | }; | 339 | }; |
| 279 | 340 | ||
| 280 | pci0: pci@e0008500 { | 341 | pci0: pci@e0008500 { |
| @@ -331,7 +392,26 @@ | |||
| 331 | compatible = "fsl,mpc8349e-localbus", | 392 | compatible = "fsl,mpc8349e-localbus", |
| 332 | "fsl,pq2pro-localbus"; | 393 | "fsl,pq2pro-localbus"; |
| 333 | reg = <0xe0005000 0xd8>; | 394 | reg = <0xe0005000 0xd8>; |
| 334 | ranges = <0x3 0x0 0xf0000000 0x210>; | 395 | ranges = <0x0 0x0 0xfe000000 0x1000000 /* flash */ |
| 396 | 0x1 0x0 0xf8000000 0x20000 /* VSC 7385 */ | ||
| 397 | 0x2 0x0 0xf9000000 0x200000 /* exp slot */ | ||
| 398 | 0x3 0x0 0xf0000000 0x210>; /* CF slot */ | ||
| 399 | |||
| 400 | flash@0,0 { | ||
| 401 | compatible = "cfi-flash"; | ||
| 402 | reg = <0x0 0x0 0x800000>; | ||
| 403 | bank-width = <2>; | ||
| 404 | device-width = <1>; | ||
| 405 | }; | ||
| 406 | |||
| 407 | flash@0,800000 { | ||
| 408 | #address-cells = <1>; | ||
| 409 | #size-cells = <1>; | ||
| 410 | compatible = "cfi-flash"; | ||
| 411 | reg = <0x0 0x800000 0x800000>; | ||
| 412 | bank-width = <2>; | ||
| 413 | device-width = <1>; | ||
| 414 | }; | ||
| 335 | 415 | ||
| 336 | pata@3,0 { | 416 | pata@3,0 { |
| 337 | compatible = "fsl,mpc8349emitx-pata", "ata-generic"; | 417 | compatible = "fsl,mpc8349emitx-pata", "ata-generic"; |
diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts index 39ff4c829caf..45cfa1c50a2a 100644 --- a/arch/powerpc/boot/dts/mpc836x_mds.dts +++ b/arch/powerpc/boot/dts/mpc836x_mds.dts | |||
| @@ -99,6 +99,13 @@ | |||
| 99 | reg = <0x200 0x100>; | 99 | reg = <0x200 0x100>; |
| 100 | }; | 100 | }; |
| 101 | 101 | ||
| 102 | pmc: power@b00 { | ||
| 103 | compatible = "fsl,mpc8360-pmc", "fsl,mpc8349-pmc"; | ||
| 104 | reg = <0xb00 0x100 0xa00 0x100>; | ||
| 105 | interrupts = <80 0x8>; | ||
| 106 | interrupt-parent = <&ipic>; | ||
| 107 | }; | ||
| 108 | |||
| 102 | i2c@3000 { | 109 | i2c@3000 { |
| 103 | #address-cells = <1>; | 110 | #address-cells = <1>; |
| 104 | #size-cells = <0>; | 111 | #size-cells = <0>; |
| @@ -194,6 +201,7 @@ | |||
| 194 | fsl,channel-fifo-len = <24>; | 201 | fsl,channel-fifo-len = <24>; |
| 195 | fsl,exec-units-mask = <0x7e>; | 202 | fsl,exec-units-mask = <0x7e>; |
| 196 | fsl,descriptor-types-mask = <0x01010ebf>; | 203 | fsl,descriptor-types-mask = <0x01010ebf>; |
| 204 | sleep = <&pmc 0x03000000>; | ||
| 197 | }; | 205 | }; |
| 198 | 206 | ||
| 199 | ipic: pic@700 { | 207 | ipic: pic@700 { |
| @@ -470,5 +478,6 @@ | |||
| 470 | 0xe0008300 0x8>; /* config space access registers */ | 478 | 0xe0008300 0x8>; /* config space access registers */ |
| 471 | compatible = "fsl,mpc8349-pci"; | 479 | compatible = "fsl,mpc8349-pci"; |
| 472 | device_type = "pci"; | 480 | device_type = "pci"; |
| 481 | sleep = <&pmc 0x00010000>; | ||
| 473 | }; | 482 | }; |
| 474 | }; | 483 | }; |
diff --git a/arch/powerpc/boot/dts/mpc836x_rdk.dts b/arch/powerpc/boot/dts/mpc836x_rdk.dts index 6315d6fcc58a..bdf4459677b1 100644 --- a/arch/powerpc/boot/dts/mpc836x_rdk.dts +++ b/arch/powerpc/boot/dts/mpc836x_rdk.dts | |||
| @@ -71,6 +71,13 @@ | |||
| 71 | reg = <0x200 0x100>; | 71 | reg = <0x200 0x100>; |
| 72 | }; | 72 | }; |
| 73 | 73 | ||
| 74 | pmc: power@b00 { | ||
| 75 | compatible = "fsl,mpc8360-pmc", "fsl,mpc8349-pmc"; | ||
| 76 | reg = <0xb00 0x100 0xa00 0x100>; | ||
| 77 | interrupts = <80 0x8>; | ||
| 78 | interrupt-parent = <&ipic>; | ||
| 79 | }; | ||
| 80 | |||
| 74 | i2c@3000 { | 81 | i2c@3000 { |
| 75 | #address-cells = <1>; | 82 | #address-cells = <1>; |
| 76 | #size-cells = <0>; | 83 | #size-cells = <0>; |
| @@ -161,6 +168,7 @@ | |||
| 161 | fsl,channel-fifo-len = <24>; | 168 | fsl,channel-fifo-len = <24>; |
| 162 | fsl,exec-units-mask = <0x7e>; | 169 | fsl,exec-units-mask = <0x7e>; |
| 163 | fsl,descriptor-types-mask = <0x01010ebf>; | 170 | fsl,descriptor-types-mask = <0x01010ebf>; |
| 171 | sleep = <&pmc 0x03000000>; | ||
| 164 | }; | 172 | }; |
| 165 | 173 | ||
| 166 | ipic: interrupt-controller@700 { | 174 | ipic: interrupt-controller@700 { |
| @@ -455,6 +463,7 @@ | |||
| 455 | 0xa800 0 0 2 &ipic 20 8 | 463 | 0xa800 0 0 2 &ipic 20 8 |
| 456 | 0xa800 0 0 3 &ipic 21 8 | 464 | 0xa800 0 0 3 &ipic 21 8 |
| 457 | 0xa800 0 0 4 &ipic 18 8>; | 465 | 0xa800 0 0 4 &ipic 18 8>; |
| 466 | sleep = <&pmc 0x00010000>; | ||
| 458 | /* filled by u-boot */ | 467 | /* filled by u-boot */ |
| 459 | bus-range = <0 0>; | 468 | bus-range = <0 0>; |
| 460 | clock-frequency = <0>; | 469 | clock-frequency = <0>; |
diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts index 00c2bbda7013..6d892ba74e55 100644 --- a/arch/powerpc/boot/dts/mpc8568mds.dts +++ b/arch/powerpc/boot/dts/mpc8568mds.dts | |||
| @@ -40,6 +40,8 @@ | |||
| 40 | i-cache-line-size = <32>; // 32 bytes | 40 | i-cache-line-size = <32>; // 32 bytes |
| 41 | d-cache-size = <0x8000>; // L1, 32K | 41 | d-cache-size = <0x8000>; // L1, 32K |
| 42 | i-cache-size = <0x8000>; // L1, 32K | 42 | i-cache-size = <0x8000>; // L1, 32K |
| 43 | sleep = <&pmc 0x00008000 // core | ||
| 44 | &pmc 0x00004000>; // timebase | ||
| 43 | timebase-frequency = <0>; | 45 | timebase-frequency = <0>; |
| 44 | bus-frequency = <0>; | 46 | bus-frequency = <0>; |
| 45 | clock-frequency = <0>; | 47 | clock-frequency = <0>; |
| @@ -94,31 +96,41 @@ | |||
| 94 | interrupts = <16 2>; | 96 | interrupts = <16 2>; |
| 95 | }; | 97 | }; |
| 96 | 98 | ||
| 97 | i2c@3000 { | 99 | i2c-sleep-nexus { |
| 98 | #address-cells = <1>; | 100 | #address-cells = <1>; |
| 99 | #size-cells = <0>; | 101 | #size-cells = <1>; |
| 100 | cell-index = <0>; | 102 | compatible = "simple-bus"; |
| 101 | compatible = "fsl-i2c"; | 103 | sleep = <&pmc 0x00000004>; |
| 102 | reg = <0x3000 0x100>; | 104 | ranges; |
| 103 | interrupts = <43 2>; | ||
| 104 | interrupt-parent = <&mpic>; | ||
| 105 | dfsrr; | ||
| 106 | 105 | ||
| 107 | rtc@68 { | 106 | i2c@3000 { |
| 108 | compatible = "dallas,ds1374"; | 107 | #address-cells = <1>; |
| 109 | reg = <0x68>; | 108 | #size-cells = <0>; |
| 109 | cell-index = <0>; | ||
| 110 | compatible = "fsl-i2c"; | ||
| 111 | reg = <0x3000 0x100>; | ||
| 112 | interrupts = <43 2>; | ||
| 113 | interrupt-parent = <&mpic>; | ||
| 114 | dfsrr; | ||
| 115 | |||
| 116 | rtc@68 { | ||
| 117 | compatible = "dallas,ds1374"; | ||
| 118 | reg = <0x68>; | ||
| 119 | interrupts = <3 1>; | ||
| 120 | interrupt-parent = <&mpic>; | ||
| 121 | }; | ||
| 110 | }; | 122 | }; |
| 111 | }; | ||
| 112 | 123 | ||
| 113 | i2c@3100 { | 124 | i2c@3100 { |
| 114 | #address-cells = <1>; | 125 | #address-cells = <1>; |
| 115 | #size-cells = <0>; | 126 | #size-cells = <0>; |
| 116 | cell-index = <1>; | 127 | cell-index = <1>; |
| 117 | compatible = "fsl-i2c"; | 128 | compatible = "fsl-i2c"; |
| 118 | reg = <0x3100 0x100>; | 129 | reg = <0x3100 0x100>; |
| 119 | interrupts = <43 2>; | 130 | interrupts = <43 2>; |
| 120 | interrupt-parent = <&mpic>; | 131 | interrupt-parent = <&mpic>; |
| 121 | dfsrr; | 132 | dfsrr; |
| 133 | }; | ||
| 122 | }; | 134 | }; |
| 123 | 135 | ||
| 124 | dma@21300 { | 136 | dma@21300 { |
| @@ -128,6 +140,8 @@ | |||
| 128 | reg = <0x21300 0x4>; | 140 | reg = <0x21300 0x4>; |
| 129 | ranges = <0x0 0x21100 0x200>; | 141 | ranges = <0x0 0x21100 0x200>; |
| 130 | cell-index = <0>; | 142 | cell-index = <0>; |
| 143 | sleep = <&pmc 0x00000400>; | ||
| 144 | |||
| 131 | dma-channel@0 { | 145 | dma-channel@0 { |
| 132 | compatible = "fsl,mpc8568-dma-channel", | 146 | compatible = "fsl,mpc8568-dma-channel", |
| 133 | "fsl,eloplus-dma-channel"; | 147 | "fsl,eloplus-dma-channel"; |
| @@ -176,6 +190,7 @@ | |||
| 176 | interrupt-parent = <&mpic>; | 190 | interrupt-parent = <&mpic>; |
| 177 | tbi-handle = <&tbi0>; | 191 | tbi-handle = <&tbi0>; |
| 178 | phy-handle = <&phy2>; | 192 | phy-handle = <&phy2>; |
| 193 | sleep = <&pmc 0x00000080>; | ||
| 179 | 194 | ||
| 180 | mdio@520 { | 195 | mdio@520 { |
| 181 | #address-cells = <1>; | 196 | #address-cells = <1>; |
| @@ -228,6 +243,7 @@ | |||
| 228 | interrupt-parent = <&mpic>; | 243 | interrupt-parent = <&mpic>; |
| 229 | tbi-handle = <&tbi1>; | 244 | tbi-handle = <&tbi1>; |
| 230 | phy-handle = <&phy3>; | 245 | phy-handle = <&phy3>; |
| 246 | sleep = <&pmc 0x00000040>; | ||
| 231 | 247 | ||
| 232 | mdio@520 { | 248 | mdio@520 { |
| 233 | #address-cells = <1>; | 249 | #address-cells = <1>; |
| @@ -242,30 +258,47 @@ | |||
| 242 | }; | 258 | }; |
| 243 | }; | 259 | }; |
| 244 | 260 | ||
| 245 | serial0: serial@4500 { | 261 | duart-sleep-nexus { |
| 246 | cell-index = <0>; | 262 | #address-cells = <1>; |
| 247 | device_type = "serial"; | 263 | #size-cells = <1>; |
| 248 | compatible = "ns16550"; | 264 | compatible = "simple-bus"; |
| 249 | reg = <0x4500 0x100>; | 265 | sleep = <&pmc 0x00000002>; |
| 250 | clock-frequency = <0>; | 266 | ranges; |
| 251 | interrupts = <42 2>; | 267 | |
| 252 | interrupt-parent = <&mpic>; | 268 | serial0: serial@4500 { |
| 269 | cell-index = <0>; | ||
| 270 | device_type = "serial"; | ||
| 271 | compatible = "ns16550"; | ||
| 272 | reg = <0x4500 0x100>; | ||
| 273 | clock-frequency = <0>; | ||
| 274 | interrupts = <42 2>; | ||
| 275 | interrupt-parent = <&mpic>; | ||
| 276 | }; | ||
| 277 | |||
| 278 | serial1: serial@4600 { | ||
| 279 | cell-index = <1>; | ||
| 280 | device_type = "serial"; | ||
| 281 | compatible = "ns16550"; | ||
| 282 | reg = <0x4600 0x100>; | ||
| 283 | clock-frequency = <0>; | ||
| 284 | interrupts = <42 2>; | ||
| 285 | interrupt-parent = <&mpic>; | ||
| 286 | }; | ||
| 253 | }; | 287 | }; |
| 254 | 288 | ||
| 255 | global-utilities@e0000 { //global utilities block | 289 | global-utilities@e0000 { |
| 256 | compatible = "fsl,mpc8548-guts"; | 290 | #address-cells = <1>; |
| 291 | #size-cells = <1>; | ||
| 292 | compatible = "fsl,mpc8568-guts", "fsl,mpc8548-guts"; | ||
| 257 | reg = <0xe0000 0x1000>; | 293 | reg = <0xe0000 0x1000>; |
| 294 | ranges = <0 0xe0000 0x1000>; | ||
| 258 | fsl,has-rstcr; | 295 | fsl,has-rstcr; |
| 259 | }; | ||
| 260 | 296 | ||
| 261 | serial1: serial@4600 { | 297 | pmc: power@70 { |
| 262 | cell-index = <1>; | 298 | compatible = "fsl,mpc8568-pmc", |
| 263 | device_type = "serial"; | 299 | "fsl,mpc8548-pmc"; |
| 264 | compatible = "ns16550"; | 300 | reg = <0x70 0x20>; |
| 265 | reg = <0x4600 0x100>; | 301 | }; |
| 266 | clock-frequency = <0>; | ||
| 267 | interrupts = <42 2>; | ||
| 268 | interrupt-parent = <&mpic>; | ||
| 269 | }; | 302 | }; |
| 270 | 303 | ||
| 271 | crypto@30000 { | 304 | crypto@30000 { |
| @@ -277,6 +310,7 @@ | |||
| 277 | fsl,channel-fifo-len = <24>; | 310 | fsl,channel-fifo-len = <24>; |
| 278 | fsl,exec-units-mask = <0xfe>; | 311 | fsl,exec-units-mask = <0xfe>; |
| 279 | fsl,descriptor-types-mask = <0x12b0ebf>; | 312 | fsl,descriptor-types-mask = <0x12b0ebf>; |
| 313 | sleep = <&pmc 0x01000000>; | ||
| 280 | }; | 314 | }; |
| 281 | 315 | ||
| 282 | mpic: pic@40000 { | 316 | mpic: pic@40000 { |
| @@ -376,6 +410,7 @@ | |||
| 376 | compatible = "fsl,qe"; | 410 | compatible = "fsl,qe"; |
| 377 | ranges = <0x0 0xe0080000 0x40000>; | 411 | ranges = <0x0 0xe0080000 0x40000>; |
| 378 | reg = <0xe0080000 0x480>; | 412 | reg = <0xe0080000 0x480>; |
| 413 | sleep = <&pmc 0x00000800>; | ||
| 379 | brg-frequency = <0>; | 414 | brg-frequency = <0>; |
| 380 | bus-frequency = <396000000>; | 415 | bus-frequency = <396000000>; |
| 381 | fsl,qe-num-riscs = <2>; | 416 | fsl,qe-num-riscs = <2>; |
| @@ -509,6 +544,7 @@ | |||
| 509 | bus-range = <0 255>; | 544 | bus-range = <0 255>; |
| 510 | ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000 | 545 | ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000 |
| 511 | 0x1000000 0x0 0x0 0xe2000000 0x0 0x800000>; | 546 | 0x1000000 0x0 0x0 0xe2000000 0x0 0x800000>; |
| 547 | sleep = <&pmc 0x80000000>; | ||
| 512 | clock-frequency = <66666666>; | 548 | clock-frequency = <66666666>; |
| 513 | #interrupt-cells = <1>; | 549 | #interrupt-cells = <1>; |
| 514 | #size-cells = <2>; | 550 | #size-cells = <2>; |
| @@ -534,6 +570,7 @@ | |||
| 534 | bus-range = <0 255>; | 570 | bus-range = <0 255>; |
| 535 | ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000 | 571 | ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000 |
| 536 | 0x1000000 0x0 0x0 0xe2800000 0x0 0x800000>; | 572 | 0x1000000 0x0 0x0 0xe2800000 0x0 0x800000>; |
| 573 | sleep = <&pmc 0x20000000>; | ||
| 537 | clock-frequency = <33333333>; | 574 | clock-frequency = <33333333>; |
| 538 | #interrupt-cells = <1>; | 575 | #interrupt-cells = <1>; |
| 539 | #size-cells = <2>; | 576 | #size-cells = <2>; |
| @@ -570,5 +607,7 @@ | |||
| 570 | 55 2 /* msg2_tx */ | 607 | 55 2 /* msg2_tx */ |
| 571 | 56 2 /* msg2_rx */>; | 608 | 56 2 /* msg2_rx */>; |
| 572 | interrupt-parent = <&mpic>; | 609 | interrupt-parent = <&mpic>; |
| 610 | sleep = <&pmc 0x00080000 /* controller */ | ||
| 611 | &pmc 0x00040000>; /* message unit */ | ||
| 573 | }; | 612 | }; |
| 574 | }; | 613 | }; |
diff --git a/arch/powerpc/boot/dts/mpc8569mds.dts b/arch/powerpc/boot/dts/mpc8569mds.dts index 1e3ec8f059bf..795eb362fcf9 100644 --- a/arch/powerpc/boot/dts/mpc8569mds.dts +++ b/arch/powerpc/boot/dts/mpc8569mds.dts | |||
| @@ -41,6 +41,8 @@ | |||
| 41 | i-cache-line-size = <32>; // 32 bytes | 41 | i-cache-line-size = <32>; // 32 bytes |
| 42 | d-cache-size = <0x8000>; // L1, 32K | 42 | d-cache-size = <0x8000>; // L1, 32K |
| 43 | i-cache-size = <0x8000>; // L1, 32K | 43 | i-cache-size = <0x8000>; // L1, 32K |
| 44 | sleep = <&pmc 0x00008000 // core | ||
| 45 | &pmc 0x00004000>; // timebase | ||
| 44 | timebase-frequency = <0>; | 46 | timebase-frequency = <0>; |
| 45 | bus-frequency = <0>; | 47 | bus-frequency = <0>; |
| 46 | clock-frequency = <0>; | 48 | clock-frequency = <0>; |
| @@ -59,6 +61,7 @@ | |||
| 59 | reg = <0xe0005000 0x1000>; | 61 | reg = <0xe0005000 0x1000>; |
| 60 | interrupts = <19 2>; | 62 | interrupts = <19 2>; |
| 61 | interrupt-parent = <&mpic>; | 63 | interrupt-parent = <&mpic>; |
| 64 | sleep = <&pmc 0x08000000>; | ||
| 62 | 65 | ||
| 63 | ranges = <0x0 0x0 0xfe000000 0x02000000 | 66 | ranges = <0x0 0x0 0xfe000000 0x02000000 |
| 64 | 0x1 0x0 0xf8000000 0x00008000 | 67 | 0x1 0x0 0xf8000000 0x00008000 |
| @@ -158,51 +161,69 @@ | |||
| 158 | interrupts = <18 2>; | 161 | interrupts = <18 2>; |
| 159 | }; | 162 | }; |
| 160 | 163 | ||
| 161 | i2c@3000 { | 164 | i2c-sleep-nexus { |
| 162 | #address-cells = <1>; | 165 | #address-cells = <1>; |
| 163 | #size-cells = <0>; | 166 | #size-cells = <1>; |
| 164 | cell-index = <0>; | 167 | compatible = "simple-bus"; |
| 165 | compatible = "fsl-i2c"; | 168 | sleep = <&pmc 0x00000004>; |
| 166 | reg = <0x3000 0x100>; | 169 | ranges; |
| 167 | interrupts = <43 2>; | 170 | |
| 168 | interrupt-parent = <&mpic>; | 171 | i2c@3000 { |
| 169 | dfsrr; | 172 | #address-cells = <1>; |
| 173 | #size-cells = <0>; | ||
| 174 | cell-index = <0>; | ||
| 175 | compatible = "fsl-i2c"; | ||
| 176 | reg = <0x3000 0x100>; | ||
| 177 | interrupts = <43 2>; | ||
| 178 | interrupt-parent = <&mpic>; | ||
| 179 | dfsrr; | ||
| 180 | |||
| 181 | rtc@68 { | ||
| 182 | compatible = "dallas,ds1374"; | ||
| 183 | reg = <0x68>; | ||
| 184 | interrupts = <3 1>; | ||
| 185 | interrupt-parent = <&mpic>; | ||
| 186 | }; | ||
| 187 | }; | ||
| 170 | 188 | ||
| 171 | rtc@68 { | 189 | i2c@3100 { |
| 172 | compatible = "dallas,ds1374"; | 190 | #address-cells = <1>; |
| 173 | reg = <0x68>; | 191 | #size-cells = <0>; |
| 192 | cell-index = <1>; | ||
| 193 | compatible = "fsl-i2c"; | ||
| 194 | reg = <0x3100 0x100>; | ||
| 195 | interrupts = <43 2>; | ||
| 196 | interrupt-parent = <&mpic>; | ||
| 197 | dfsrr; | ||
| 174 | }; | 198 | }; |
| 175 | }; | 199 | }; |
| 176 | 200 | ||
| 177 | i2c@3100 { | 201 | duart-sleep-nexus { |
| 178 | #address-cells = <1>; | 202 | #address-cells = <1>; |
| 179 | #size-cells = <0>; | 203 | #size-cells = <1>; |
| 180 | cell-index = <1>; | 204 | compatible = "simple-bus"; |
| 181 | compatible = "fsl-i2c"; | 205 | sleep = <&pmc 0x00000002>; |
| 182 | reg = <0x3100 0x100>; | 206 | ranges; |
| 183 | interrupts = <43 2>; | ||
| 184 | interrupt-parent = <&mpic>; | ||
| 185 | dfsrr; | ||
| 186 | }; | ||
| 187 | 207 | ||
| 188 | serial0: serial@4500 { | 208 | serial0: serial@4500 { |
| 189 | cell-index = <0>; | 209 | cell-index = <0>; |
| 190 | device_type = "serial"; | 210 | device_type = "serial"; |
| 191 | compatible = "ns16550"; | 211 | compatible = "ns16550"; |
| 192 | reg = <0x4500 0x100>; | 212 | reg = <0x4500 0x100>; |
| 193 | clock-frequency = <0>; | 213 | clock-frequency = <0>; |
| 194 | interrupts = <42 2>; | 214 | interrupts = <42 2>; |
| 195 | interrupt-parent = <&mpic>; | 215 | interrupt-parent = <&mpic>; |
| 196 | }; | 216 | }; |
| 197 | 217 | ||
| 198 | serial1: serial@4600 { | 218 | serial1: serial@4600 { |
| 199 | cell-index = <1>; | 219 | cell-index = <1>; |
| 200 | device_type = "serial"; | 220 | device_type = "serial"; |
| 201 | compatible = "ns16550"; | 221 | compatible = "ns16550"; |
| 202 | reg = <0x4600 0x100>; | 222 | reg = <0x4600 0x100>; |
| 203 | clock-frequency = <0>; | 223 | clock-frequency = <0>; |
| 204 | interrupts = <42 2>; | 224 | interrupts = <42 2>; |
| 205 | interrupt-parent = <&mpic>; | 225 | interrupt-parent = <&mpic>; |
| 226 | }; | ||
| 206 | }; | 227 | }; |
| 207 | 228 | ||
| 208 | L2: l2-cache-controller@20000 { | 229 | L2: l2-cache-controller@20000 { |
| @@ -260,6 +281,7 @@ | |||
| 260 | reg = <0x2e000 0x1000>; | 281 | reg = <0x2e000 0x1000>; |
| 261 | interrupts = <72 0x8>; | 282 | interrupts = <72 0x8>; |
| 262 | interrupt-parent = <&mpic>; | 283 | interrupt-parent = <&mpic>; |
| 284 | sleep = <&pmc 0x00200000>; | ||
| 263 | /* Filled in by U-Boot */ | 285 | /* Filled in by U-Boot */ |
| 264 | clock-frequency = <0>; | 286 | clock-frequency = <0>; |
| 265 | status = "disabled"; | 287 | status = "disabled"; |
| @@ -276,6 +298,7 @@ | |||
| 276 | fsl,channel-fifo-len = <24>; | 298 | fsl,channel-fifo-len = <24>; |
| 277 | fsl,exec-units-mask = <0xbfe>; | 299 | fsl,exec-units-mask = <0xbfe>; |
| 278 | fsl,descriptor-types-mask = <0x3ab0ebf>; | 300 | fsl,descriptor-types-mask = <0x3ab0ebf>; |
| 301 | sleep = <&pmc 0x01000000>; | ||
| 279 | }; | 302 | }; |
| 280 | 303 | ||
| 281 | mpic: pic@40000 { | 304 | mpic: pic@40000 { |
| @@ -304,9 +327,18 @@ | |||
| 304 | }; | 327 | }; |
| 305 | 328 | ||
| 306 | global-utilities@e0000 { | 329 | global-utilities@e0000 { |
| 307 | compatible = "fsl,mpc8569-guts"; | 330 | #address-cells = <1>; |
| 331 | #size-cells = <1>; | ||
| 332 | compatible = "fsl,mpc8569-guts", "fsl,mpc8548-guts"; | ||
| 308 | reg = <0xe0000 0x1000>; | 333 | reg = <0xe0000 0x1000>; |
| 334 | ranges = <0 0xe0000 0x1000>; | ||
| 309 | fsl,has-rstcr; | 335 | fsl,has-rstcr; |
| 336 | |||
| 337 | pmc: power@70 { | ||
| 338 | compatible = "fsl,mpc8569-pmc", | ||
| 339 | "fsl,mpc8548-pmc"; | ||
| 340 | reg = <0x70 0x20>; | ||
| 341 | }; | ||
| 310 | }; | 342 | }; |
| 311 | 343 | ||
| 312 | par_io@e0100 { | 344 | par_io@e0100 { |
| @@ -422,6 +454,7 @@ | |||
| 422 | compatible = "fsl,qe"; | 454 | compatible = "fsl,qe"; |
| 423 | ranges = <0x0 0xe0080000 0x40000>; | 455 | ranges = <0x0 0xe0080000 0x40000>; |
| 424 | reg = <0xe0080000 0x480>; | 456 | reg = <0xe0080000 0x480>; |
| 457 | sleep = <&pmc 0x00000800>; | ||
| 425 | brg-frequency = <0>; | 458 | brg-frequency = <0>; |
| 426 | bus-frequency = <0>; | 459 | bus-frequency = <0>; |
| 427 | fsl,qe-num-riscs = <4>; | 460 | fsl,qe-num-riscs = <4>; |
| @@ -684,6 +717,7 @@ | |||
| 684 | bus-range = <0 255>; | 717 | bus-range = <0 255>; |
| 685 | ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000 | 718 | ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000 |
| 686 | 0x1000000 0x0 0x00000000 0xe2800000 0x0 0x00800000>; | 719 | 0x1000000 0x0 0x00000000 0xe2800000 0x0 0x00800000>; |
| 720 | sleep = <&pmc 0x20000000>; | ||
| 687 | clock-frequency = <33333333>; | 721 | clock-frequency = <33333333>; |
| 688 | pcie@0 { | 722 | pcie@0 { |
| 689 | reg = <0x0 0x0 0x0 0x0 0x0>; | 723 | reg = <0x0 0x0 0x0 0x0 0x0>; |
| @@ -714,5 +748,6 @@ | |||
| 714 | 55 2 /* msg2_tx */ | 748 | 55 2 /* msg2_tx */ |
| 715 | 56 2 /* msg2_rx */>; | 749 | 56 2 /* msg2_rx */>; |
| 716 | interrupt-parent = <&mpic>; | 750 | interrupt-parent = <&mpic>; |
| 751 | sleep = <&pmc 0x00080000>; | ||
| 717 | }; | 752 | }; |
| 718 | }; | 753 | }; |
diff --git a/arch/powerpc/boot/dts/mpc8610_hpcd.dts b/arch/powerpc/boot/dts/mpc8610_hpcd.dts index f468d215f716..9535ce68caae 100644 --- a/arch/powerpc/boot/dts/mpc8610_hpcd.dts +++ b/arch/powerpc/boot/dts/mpc8610_hpcd.dts | |||
| @@ -35,6 +35,8 @@ | |||
| 35 | i-cache-line-size = <32>; | 35 | i-cache-line-size = <32>; |
| 36 | d-cache-size = <32768>; // L1 | 36 | d-cache-size = <32768>; // L1 |
| 37 | i-cache-size = <32768>; // L1 | 37 | i-cache-size = <32768>; // L1 |
| 38 | sleep = <&pmc 0x00008000 0 // core | ||
| 39 | &pmc 0x00004000 0>; // timebase | ||
| 38 | timebase-frequency = <0>; // From uboot | 40 | timebase-frequency = <0>; // From uboot |
| 39 | bus-frequency = <0>; // From uboot | 41 | bus-frequency = <0>; // From uboot |
| 40 | clock-frequency = <0>; // From uboot | 42 | clock-frequency = <0>; // From uboot |
| @@ -60,6 +62,7 @@ | |||
| 60 | 5 0 0xe8480000 0x00008000 | 62 | 5 0 0xe8480000 0x00008000 |
| 61 | 6 0 0xe84c0000 0x00008000 | 63 | 6 0 0xe84c0000 0x00008000 |
| 62 | 3 0 0xe8000000 0x00000020>; | 64 | 3 0 0xe8000000 0x00000020>; |
| 65 | sleep = <&pmc 0x08000000 0>; | ||
| 63 | 66 | ||
| 64 | flash@0,0 { | 67 | flash@0,0 { |
| 65 | compatible = "cfi-flash"; | 68 | compatible = "cfi-flash"; |
| @@ -105,6 +108,8 @@ | |||
| 105 | compatible = "fsl,fpga-pixis"; | 108 | compatible = "fsl,fpga-pixis"; |
| 106 | reg = <3 0 0x20>; | 109 | reg = <3 0 0x20>; |
| 107 | ranges = <0 3 0 0x20>; | 110 | ranges = <0 3 0 0x20>; |
| 111 | interrupt-parent = <&mpic>; | ||
| 112 | interrupts = <8 8>; | ||
| 108 | 113 | ||
| 109 | sdcsr_pio: gpio-controller@a { | 114 | sdcsr_pio: gpio-controller@a { |
| 110 | #gpio-cells = <2>; | 115 | #gpio-cells = <2>; |
| @@ -163,6 +168,7 @@ | |||
| 163 | reg = <0x3100 0x100>; | 168 | reg = <0x3100 0x100>; |
| 164 | interrupts = <43 2>; | 169 | interrupts = <43 2>; |
| 165 | interrupt-parent = <&mpic>; | 170 | interrupt-parent = <&mpic>; |
| 171 | sleep = <&pmc 0x00000004 0>; | ||
| 166 | dfsrr; | 172 | dfsrr; |
| 167 | }; | 173 | }; |
| 168 | 174 | ||
| @@ -174,6 +180,7 @@ | |||
| 174 | clock-frequency = <0>; | 180 | clock-frequency = <0>; |
| 175 | interrupts = <42 2>; | 181 | interrupts = <42 2>; |
| 176 | interrupt-parent = <&mpic>; | 182 | interrupt-parent = <&mpic>; |
| 183 | sleep = <&pmc 0x00000002 0>; | ||
| 177 | }; | 184 | }; |
| 178 | 185 | ||
| 179 | serial1: serial@4600 { | 186 | serial1: serial@4600 { |
| @@ -184,6 +191,7 @@ | |||
| 184 | clock-frequency = <0>; | 191 | clock-frequency = <0>; |
| 185 | interrupts = <42 2>; | 192 | interrupts = <42 2>; |
| 186 | interrupt-parent = <&mpic>; | 193 | interrupt-parent = <&mpic>; |
| 194 | sleep = <&pmc 0x00000008 0>; | ||
| 187 | }; | 195 | }; |
| 188 | 196 | ||
| 189 | spi@7000 { | 197 | spi@7000 { |
| @@ -196,6 +204,7 @@ | |||
| 196 | interrupt-parent = <&mpic>; | 204 | interrupt-parent = <&mpic>; |
| 197 | mode = "cpu"; | 205 | mode = "cpu"; |
| 198 | gpios = <&sdcsr_pio 7 0>; | 206 | gpios = <&sdcsr_pio 7 0>; |
| 207 | sleep = <&pmc 0x00000800 0>; | ||
| 199 | 208 | ||
| 200 | mmc-slot@0 { | 209 | mmc-slot@0 { |
| 201 | compatible = "fsl,mpc8610hpcd-mmc-slot", | 210 | compatible = "fsl,mpc8610hpcd-mmc-slot", |
| @@ -213,6 +222,7 @@ | |||
| 213 | reg = <0x2c000 100>; | 222 | reg = <0x2c000 100>; |
| 214 | interrupts = <72 2>; | 223 | interrupts = <72 2>; |
| 215 | interrupt-parent = <&mpic>; | 224 | interrupt-parent = <&mpic>; |
| 225 | sleep = <&pmc 0x04000000 0>; | ||
| 216 | }; | 226 | }; |
| 217 | 227 | ||
| 218 | mpic: interrupt-controller@40000 { | 228 | mpic: interrupt-controller@40000 { |
| @@ -241,9 +251,18 @@ | |||
| 241 | }; | 251 | }; |
| 242 | 252 | ||
| 243 | global-utilities@e0000 { | 253 | global-utilities@e0000 { |
| 254 | #address-cells = <1>; | ||
| 255 | #size-cells = <1>; | ||
| 244 | compatible = "fsl,mpc8610-guts"; | 256 | compatible = "fsl,mpc8610-guts"; |
| 245 | reg = <0xe0000 0x1000>; | 257 | reg = <0xe0000 0x1000>; |
| 258 | ranges = <0 0xe0000 0x1000>; | ||
| 246 | fsl,has-rstcr; | 259 | fsl,has-rstcr; |
| 260 | |||
| 261 | pmc: power@70 { | ||
| 262 | compatible = "fsl,mpc8610-pmc", | ||
| 263 | "fsl,mpc8641d-pmc"; | ||
| 264 | reg = <0x70 0x20>; | ||
| 265 | }; | ||
| 247 | }; | 266 | }; |
| 248 | 267 | ||
| 249 | wdt@e4000 { | 268 | wdt@e4000 { |
| @@ -262,6 +281,7 @@ | |||
| 262 | fsl,playback-dma = <&dma00>; | 281 | fsl,playback-dma = <&dma00>; |
| 263 | fsl,capture-dma = <&dma01>; | 282 | fsl,capture-dma = <&dma01>; |
| 264 | fsl,fifo-depth = <8>; | 283 | fsl,fifo-depth = <8>; |
| 284 | sleep = <&pmc 0 0x08000000>; | ||
| 265 | }; | 285 | }; |
| 266 | 286 | ||
| 267 | ssi@16100 { | 287 | ssi@16100 { |
| @@ -271,6 +291,7 @@ | |||
| 271 | interrupt-parent = <&mpic>; | 291 | interrupt-parent = <&mpic>; |
| 272 | interrupts = <63 2>; | 292 | interrupts = <63 2>; |
| 273 | fsl,fifo-depth = <8>; | 293 | fsl,fifo-depth = <8>; |
| 294 | sleep = <&pmc 0 0x04000000>; | ||
| 274 | }; | 295 | }; |
| 275 | 296 | ||
| 276 | dma@21300 { | 297 | dma@21300 { |
| @@ -280,6 +301,7 @@ | |||
| 280 | cell-index = <0>; | 301 | cell-index = <0>; |
| 281 | reg = <0x21300 0x4>; /* DMA general status register */ | 302 | reg = <0x21300 0x4>; /* DMA general status register */ |
| 282 | ranges = <0x0 0x21100 0x200>; | 303 | ranges = <0x0 0x21100 0x200>; |
| 304 | sleep = <&pmc 0x00000400 0>; | ||
| 283 | 305 | ||
| 284 | dma00: dma-channel@0 { | 306 | dma00: dma-channel@0 { |
| 285 | compatible = "fsl,mpc8610-dma-channel", | 307 | compatible = "fsl,mpc8610-dma-channel", |
| @@ -322,6 +344,7 @@ | |||
| 322 | cell-index = <1>; | 344 | cell-index = <1>; |
| 323 | reg = <0xc300 0x4>; /* DMA general status register */ | 345 | reg = <0xc300 0x4>; /* DMA general status register */ |
| 324 | ranges = <0x0 0xc100 0x200>; | 346 | ranges = <0x0 0xc100 0x200>; |
| 347 | sleep = <&pmc 0x00000200 0>; | ||
| 325 | 348 | ||
| 326 | dma-channel@0 { | 349 | dma-channel@0 { |
| 327 | compatible = "fsl,mpc8610-dma-channel", | 350 | compatible = "fsl,mpc8610-dma-channel", |
| @@ -369,6 +392,7 @@ | |||
| 369 | bus-range = <0 0>; | 392 | bus-range = <0 0>; |
| 370 | ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x10000000 | 393 | ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x10000000 |
| 371 | 0x01000000 0x0 0x00000000 0xe1000000 0x0 0x00100000>; | 394 | 0x01000000 0x0 0x00000000 0xe1000000 0x0 0x00100000>; |
| 395 | sleep = <&pmc 0x80000000 0>; | ||
| 372 | clock-frequency = <33333333>; | 396 | clock-frequency = <33333333>; |
| 373 | interrupt-parent = <&mpic>; | 397 | interrupt-parent = <&mpic>; |
| 374 | interrupts = <24 2>; | 398 | interrupts = <24 2>; |
| @@ -398,6 +422,7 @@ | |||
| 398 | bus-range = <1 3>; | 422 | bus-range = <1 3>; |
| 399 | ranges = <0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000 | 423 | ranges = <0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000 |
| 400 | 0x01000000 0x0 0x00000000 0xe3000000 0x0 0x00100000>; | 424 | 0x01000000 0x0 0x00000000 0xe3000000 0x0 0x00100000>; |
| 425 | sleep = <&pmc 0x40000000 0>; | ||
| 401 | clock-frequency = <33333333>; | 426 | clock-frequency = <33333333>; |
| 402 | interrupt-parent = <&mpic>; | 427 | interrupt-parent = <&mpic>; |
| 403 | interrupts = <26 2>; | 428 | interrupts = <26 2>; |
| @@ -474,6 +499,7 @@ | |||
| 474 | 0x0000 0 0 4 &mpic 7 1>; | 499 | 0x0000 0 0 4 &mpic 7 1>; |
| 475 | interrupt-parent = <&mpic>; | 500 | interrupt-parent = <&mpic>; |
| 476 | interrupts = <25 2>; | 501 | interrupts = <25 2>; |
| 502 | sleep = <&pmc 0x20000000 0>; | ||
| 477 | clock-frequency = <33333333>; | 503 | clock-frequency = <33333333>; |
| 478 | }; | 504 | }; |
| 479 | }; | 505 | }; |
diff --git a/arch/powerpc/boot/dts/p1020rdb.dts b/arch/powerpc/boot/dts/p1020rdb.dts new file mode 100644 index 000000000000..df5269093af8 --- /dev/null +++ b/arch/powerpc/boot/dts/p1020rdb.dts | |||
| @@ -0,0 +1,477 @@ | |||
| 1 | /* | ||
| 2 | * P1020 RDB Device Tree Source | ||
| 3 | * | ||
| 4 | * Copyright 2009 Freescale Semiconductor Inc. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published by the | ||
| 8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 9 | * option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | /dts-v1/; | ||
| 13 | / { | ||
| 14 | model = "fsl,P1020"; | ||
| 15 | compatible = "fsl,P1020RDB"; | ||
| 16 | #address-cells = <2>; | ||
| 17 | #size-cells = <2>; | ||
| 18 | |||
| 19 | aliases { | ||
| 20 | serial0 = &serial0; | ||
| 21 | serial1 = &serial1; | ||
| 22 | pci0 = &pci0; | ||
| 23 | pci1 = &pci1; | ||
| 24 | }; | ||
| 25 | |||
| 26 | cpus { | ||
| 27 | #address-cells = <1>; | ||
| 28 | #size-cells = <0>; | ||
| 29 | |||
| 30 | PowerPC,P1020@0 { | ||
| 31 | device_type = "cpu"; | ||
| 32 | reg = <0x0>; | ||
| 33 | next-level-cache = <&L2>; | ||
| 34 | }; | ||
| 35 | |||
| 36 | PowerPC,P1020@1 { | ||
| 37 | device_type = "cpu"; | ||
| 38 | reg = <0x1>; | ||
| 39 | next-level-cache = <&L2>; | ||
| 40 | }; | ||
| 41 | }; | ||
| 42 | |||
| 43 | memory { | ||
| 44 | device_type = "memory"; | ||
| 45 | }; | ||
| 46 | |||
| 47 | localbus@ffe05000 { | ||
| 48 | #address-cells = <2>; | ||
| 49 | #size-cells = <1>; | ||
| 50 | compatible = "fsl,p1020-elbc", "fsl,elbc", "simple-bus"; | ||
| 51 | reg = <0 0xffe05000 0 0x1000>; | ||
| 52 | interrupts = <19 2>; | ||
| 53 | interrupt-parent = <&mpic>; | ||
| 54 | |||
| 55 | /* NOR, NAND Flashes and Vitesse 5 port L2 switch */ | ||
| 56 | ranges = <0x0 0x0 0x0 0xef000000 0x01000000 | ||
| 57 | 0x1 0x0 0x0 0xffa00000 0x00040000 | ||
| 58 | 0x2 0x0 0x0 0xffb00000 0x00020000>; | ||
| 59 | |||
| 60 | nor@0,0 { | ||
| 61 | #address-cells = <1>; | ||
| 62 | #size-cells = <1>; | ||
| 63 | compatible = "cfi-flash"; | ||
| 64 | reg = <0x0 0x0 0x1000000>; | ||
| 65 | bank-width = <2>; | ||
| 66 | device-width = <1>; | ||
| 67 | |||
| 68 | partition@0 { | ||
| 69 | /* This location must not be altered */ | ||
| 70 | /* 256KB for Vitesse 7385 Switch firmware */ | ||
| 71 | reg = <0x0 0x00040000>; | ||
| 72 | label = "NOR (RO) Vitesse-7385 Firmware"; | ||
| 73 | read-only; | ||
| 74 | }; | ||
| 75 | |||
| 76 | partition@40000 { | ||
| 77 | /* 256KB for DTB Image */ | ||
| 78 | reg = <0x00040000 0x00040000>; | ||
| 79 | label = "NOR (RO) DTB Image"; | ||
| 80 | read-only; | ||
| 81 | }; | ||
| 82 | |||
| 83 | partition@80000 { | ||
| 84 | /* 3.5 MB for Linux Kernel Image */ | ||
| 85 | reg = <0x00080000 0x00380000>; | ||
| 86 | label = "NOR (RO) Linux Kernel Image"; | ||
| 87 | read-only; | ||
| 88 | }; | ||
| 89 | |||
| 90 | partition@400000 { | ||
| 91 | /* 11MB for JFFS2 based Root file System */ | ||
| 92 | reg = <0x00400000 0x00b00000>; | ||
| 93 | label = "NOR (RW) JFFS2 Root File System"; | ||
| 94 | }; | ||
| 95 | |||
| 96 | partition@f00000 { | ||
| 97 | /* This location must not be altered */ | ||
| 98 | /* 512KB for u-boot Bootloader Image */ | ||
| 99 | /* 512KB for u-boot Environment Variables */ | ||
| 100 | reg = <0x00f00000 0x00100000>; | ||
| 101 | label = "NOR (RO) U-Boot Image"; | ||
| 102 | read-only; | ||
| 103 | }; | ||
| 104 | }; | ||
| 105 | |||
| 106 | nand@1,0 { | ||
| 107 | #address-cells = <1>; | ||
| 108 | #size-cells = <1>; | ||
| 109 | compatible = "fsl,p1020-fcm-nand", | ||
| 110 | "fsl,elbc-fcm-nand"; | ||
| 111 | reg = <0x1 0x0 0x40000>; | ||
| 112 | |||
| 113 | partition@0 { | ||
| 114 | /* This location must not be altered */ | ||
| 115 | /* 1MB for u-boot Bootloader Image */ | ||
| 116 | reg = <0x0 0x00100000>; | ||
| 117 | label = "NAND (RO) U-Boot Image"; | ||
| 118 | read-only; | ||
| 119 | }; | ||
| 120 | |||
| 121 | partition@100000 { | ||
| 122 | /* 1MB for DTB Image */ | ||
| 123 | reg = <0x00100000 0x00100000>; | ||
| 124 | label = "NAND (RO) DTB Image"; | ||
| 125 | read-only; | ||
| 126 | }; | ||
| 127 | |||
| 128 | partition@200000 { | ||
| 129 | /* 4MB for Linux Kernel Image */ | ||
| 130 | reg = <0x00200000 0x00400000>; | ||
| 131 | label = "NAND (RO) Linux Kernel Image"; | ||
| 132 | read-only; | ||
| 133 | }; | ||
| 134 | |||
| 135 | partition@600000 { | ||
| 136 | /* 4MB for Compressed Root file System Image */ | ||
| 137 | reg = <0x00600000 0x00400000>; | ||
| 138 | label = "NAND (RO) Compressed RFS Image"; | ||
| 139 | read-only; | ||
| 140 | }; | ||
| 141 | |||
| 142 | partition@a00000 { | ||
| 143 | /* 7MB for JFFS2 based Root file System */ | ||
| 144 | reg = <0x00a00000 0x00700000>; | ||
| 145 | label = "NAND (RW) JFFS2 Root File System"; | ||
| 146 | }; | ||
| 147 | |||
| 148 | partition@1100000 { | ||
| 149 | /* 15MB for JFFS2 based Root file System */ | ||
| 150 | reg = <0x01100000 0x00f00000>; | ||
| 151 | label = "NAND (RW) Writable User area"; | ||
| 152 | }; | ||
| 153 | }; | ||
| 154 | |||
| 155 | L2switch@2,0 { | ||
| 156 | #address-cells = <1>; | ||
| 157 | #size-cells = <1>; | ||
| 158 | compatible = "vitesse-7385"; | ||
| 159 | reg = <0x2 0x0 0x20000>; | ||
| 160 | }; | ||
| 161 | |||
| 162 | }; | ||
| 163 | |||
| 164 | soc@ffe00000 { | ||
| 165 | #address-cells = <1>; | ||
| 166 | #size-cells = <1>; | ||
| 167 | device_type = "soc"; | ||
| 168 | compatible = "fsl,p1020-immr", "simple-bus"; | ||
| 169 | ranges = <0x0 0x0 0xffe00000 0x100000>; | ||
| 170 | bus-frequency = <0>; // Filled out by uboot. | ||
| 171 | |||
| 172 | ecm-law@0 { | ||
| 173 | compatible = "fsl,ecm-law"; | ||
| 174 | reg = <0x0 0x1000>; | ||
| 175 | fsl,num-laws = <12>; | ||
| 176 | }; | ||
| 177 | |||
| 178 | ecm@1000 { | ||
| 179 | compatible = "fsl,p1020-ecm", "fsl,ecm"; | ||
| 180 | reg = <0x1000 0x1000>; | ||
| 181 | interrupts = <16 2>; | ||
| 182 | interrupt-parent = <&mpic>; | ||
| 183 | }; | ||
| 184 | |||
| 185 | memory-controller@2000 { | ||
| 186 | compatible = "fsl,p1020-memory-controller"; | ||
| 187 | reg = <0x2000 0x1000>; | ||
| 188 | interrupt-parent = <&mpic>; | ||
| 189 | interrupts = <16 2>; | ||
| 190 | }; | ||
| 191 | |||
| 192 | i2c@3000 { | ||
| 193 | #address-cells = <1>; | ||
| 194 | #size-cells = <0>; | ||
| 195 | cell-index = <0>; | ||
| 196 | compatible = "fsl-i2c"; | ||
| 197 | reg = <0x3000 0x100>; | ||
| 198 | interrupts = <43 2>; | ||
| 199 | interrupt-parent = <&mpic>; | ||
| 200 | dfsrr; | ||
| 201 | rtc@68 { | ||
| 202 | compatible = "dallas,ds1339"; | ||
| 203 | reg = <0x68>; | ||
| 204 | }; | ||
| 205 | }; | ||
| 206 | |||
| 207 | i2c@3100 { | ||
| 208 | #address-cells = <1>; | ||
| 209 | #size-cells = <0>; | ||
| 210 | cell-index = <1>; | ||
| 211 | compatible = "fsl-i2c"; | ||
| 212 | reg = <0x3100 0x100>; | ||
| 213 | interrupts = <43 2>; | ||
| 214 | interrupt-parent = <&mpic>; | ||
| 215 | dfsrr; | ||
| 216 | }; | ||
| 217 | |||
| 218 | serial0: serial@4500 { | ||
| 219 | cell-index = <0>; | ||
| 220 | device_type = "serial"; | ||
| 221 | compatible = "ns16550"; | ||
| 222 | reg = <0x4500 0x100>; | ||
| 223 | clock-frequency = <0>; | ||
| 224 | interrupts = <42 2>; | ||
| 225 | interrupt-parent = <&mpic>; | ||
| 226 | }; | ||
| 227 | |||
| 228 | serial1: serial@4600 { | ||
| 229 | cell-index = <1>; | ||
| 230 | device_type = "serial"; | ||
| 231 | compatible = "ns16550"; | ||
| 232 | reg = <0x4600 0x100>; | ||
| 233 | clock-frequency = <0>; | ||
| 234 | interrupts = <42 2>; | ||
| 235 | interrupt-parent = <&mpic>; | ||
| 236 | }; | ||
| 237 | |||
| 238 | spi@7000 { | ||
| 239 | cell-index = <0>; | ||
| 240 | #address-cells = <1>; | ||
| 241 | #size-cells = <0>; | ||
| 242 | compatible = "fsl,espi"; | ||
| 243 | reg = <0x7000 0x1000>; | ||
| 244 | interrupts = <59 0x2>; | ||
| 245 | interrupt-parent = <&mpic>; | ||
| 246 | mode = "cpu"; | ||
| 247 | |||
| 248 | fsl_m25p80@0 { | ||
| 249 | #address-cells = <1>; | ||
| 250 | #size-cells = <1>; | ||
| 251 | compatible = "fsl,espi-flash"; | ||
| 252 | reg = <0>; | ||
| 253 | linux,modalias = "fsl_m25p80"; | ||
| 254 | modal = "s25sl128b"; | ||
| 255 | spi-max-frequency = <50000000>; | ||
| 256 | mode = <0>; | ||
| 257 | |||
| 258 | partition@0 { | ||
| 259 | /* 512KB for u-boot Bootloader Image */ | ||
| 260 | reg = <0x0 0x00080000>; | ||
| 261 | label = "SPI (RO) U-Boot Image"; | ||
| 262 | read-only; | ||
| 263 | }; | ||
| 264 | |||
| 265 | partition@80000 { | ||
| 266 | /* 512KB for DTB Image */ | ||
| 267 | reg = <0x00080000 0x00080000>; | ||
| 268 | label = "SPI (RO) DTB Image"; | ||
| 269 | read-only; | ||
| 270 | }; | ||
| 271 | |||
| 272 | partition@100000 { | ||
| 273 | /* 4MB for Linux Kernel Image */ | ||
| 274 | reg = <0x00100000 0x00400000>; | ||
| 275 | label = "SPI (RO) Linux Kernel Image"; | ||
| 276 | read-only; | ||
| 277 | }; | ||
| 278 | |||
| 279 | partition@500000 { | ||
| 280 | /* 4MB for Compressed RFS Image */ | ||
| 281 | reg = <0x00500000 0x00400000>; | ||
| 282 | label = "SPI (RO) Compressed RFS Image"; | ||
| 283 | read-only; | ||
| 284 | }; | ||
| 285 | |||
| 286 | partition@900000 { | ||
| 287 | /* 7MB for JFFS2 based RFS */ | ||
| 288 | reg = <0x00900000 0x00700000>; | ||
| 289 | label = "SPI (RW) JFFS2 RFS"; | ||
| 290 | }; | ||
| 291 | }; | ||
| 292 | }; | ||
| 293 | |||
| 294 | gpio: gpio-controller@f000 { | ||
| 295 | #gpio-cells = <2>; | ||
| 296 | compatible = "fsl,mpc8572-gpio"; | ||
| 297 | reg = <0xf000 0x100>; | ||
| 298 | interrupts = <47 0x2>; | ||
| 299 | interrupt-parent = <&mpic>; | ||
| 300 | gpio-controller; | ||
| 301 | }; | ||
| 302 | |||
| 303 | L2: l2-cache-controller@20000 { | ||
| 304 | compatible = "fsl,p1020-l2-cache-controller"; | ||
| 305 | reg = <0x20000 0x1000>; | ||
| 306 | cache-line-size = <32>; // 32 bytes | ||
| 307 | cache-size = <0x40000>; // L2,256K | ||
| 308 | interrupt-parent = <&mpic>; | ||
| 309 | interrupts = <16 2>; | ||
| 310 | }; | ||
| 311 | |||
| 312 | dma@21300 { | ||
| 313 | #address-cells = <1>; | ||
| 314 | #size-cells = <1>; | ||
| 315 | compatible = "fsl,eloplus-dma"; | ||
| 316 | reg = <0x21300 0x4>; | ||
| 317 | ranges = <0x0 0x21100 0x200>; | ||
| 318 | cell-index = <0>; | ||
| 319 | dma-channel@0 { | ||
| 320 | compatible = "fsl,eloplus-dma-channel"; | ||
| 321 | reg = <0x0 0x80>; | ||
| 322 | cell-index = <0>; | ||
| 323 | interrupt-parent = <&mpic>; | ||
| 324 | interrupts = <20 2>; | ||
| 325 | }; | ||
| 326 | dma-channel@80 { | ||
| 327 | compatible = "fsl,eloplus-dma-channel"; | ||
| 328 | reg = <0x80 0x80>; | ||
| 329 | cell-index = <1>; | ||
| 330 | interrupt-parent = <&mpic>; | ||
| 331 | interrupts = <21 2>; | ||
| 332 | }; | ||
| 333 | dma-channel@100 { | ||
| 334 | compatible = "fsl,eloplus-dma-channel"; | ||
| 335 | reg = <0x100 0x80>; | ||
| 336 | cell-index = <2>; | ||
| 337 | interrupt-parent = <&mpic>; | ||
| 338 | interrupts = <22 2>; | ||
| 339 | }; | ||
| 340 | dma-channel@180 { | ||
| 341 | compatible = "fsl,eloplus-dma-channel"; | ||
| 342 | reg = <0x180 0x80>; | ||
| 343 | cell-index = <3>; | ||
| 344 | interrupt-parent = <&mpic>; | ||
| 345 | interrupts = <23 2>; | ||
| 346 | }; | ||
| 347 | }; | ||
| 348 | |||
| 349 | usb@22000 { | ||
| 350 | #address-cells = <1>; | ||
| 351 | #size-cells = <0>; | ||
| 352 | compatible = "fsl-usb2-dr"; | ||
| 353 | reg = <0x22000 0x1000>; | ||
| 354 | interrupt-parent = <&mpic>; | ||
| 355 | interrupts = <28 0x2>; | ||
| 356 | phy_type = "ulpi"; | ||
| 357 | }; | ||
| 358 | |||
| 359 | usb@23000 { | ||
| 360 | #address-cells = <1>; | ||
| 361 | #size-cells = <0>; | ||
| 362 | compatible = "fsl-usb2-dr"; | ||
| 363 | reg = <0x23000 0x1000>; | ||
| 364 | interrupt-parent = <&mpic>; | ||
| 365 | interrupts = <46 0x2>; | ||
| 366 | phy_type = "ulpi"; | ||
| 367 | }; | ||
| 368 | |||
| 369 | sdhci@2e000 { | ||
| 370 | compatible = "fsl,p1020-esdhc", "fsl,esdhc"; | ||
| 371 | reg = <0x2e000 0x1000>; | ||
| 372 | interrupts = <72 0x2>; | ||
| 373 | interrupt-parent = <&mpic>; | ||
| 374 | /* Filled in by U-Boot */ | ||
| 375 | clock-frequency = <0>; | ||
| 376 | }; | ||
| 377 | |||
| 378 | crypto@30000 { | ||
| 379 | compatible = "fsl,sec3.1", "fsl,sec3.0", "fsl,sec2.4", | ||
| 380 | "fsl,sec2.2", "fsl,sec2.1", "fsl,sec2.0"; | ||
| 381 | reg = <0x30000 0x10000>; | ||
| 382 | interrupts = <45 2 58 2>; | ||
| 383 | interrupt-parent = <&mpic>; | ||
| 384 | fsl,num-channels = <4>; | ||
| 385 | fsl,channel-fifo-len = <24>; | ||
| 386 | fsl,exec-units-mask = <0xbfe>; | ||
| 387 | fsl,descriptor-types-mask = <0x3ab0ebf>; | ||
| 388 | }; | ||
| 389 | |||
| 390 | mpic: pic@40000 { | ||
| 391 | interrupt-controller; | ||
| 392 | #address-cells = <0>; | ||
| 393 | #interrupt-cells = <2>; | ||
| 394 | reg = <0x40000 0x40000>; | ||
| 395 | compatible = "chrp,open-pic"; | ||
| 396 | device_type = "open-pic"; | ||
| 397 | }; | ||
| 398 | |||
| 399 | msi@41600 { | ||
| 400 | compatible = "fsl,p1020-msi", "fsl,mpic-msi"; | ||
| 401 | reg = <0x41600 0x80>; | ||
| 402 | msi-available-ranges = <0 0x100>; | ||
| 403 | interrupts = < | ||
| 404 | 0xe0 0 | ||
| 405 | 0xe1 0 | ||
| 406 | 0xe2 0 | ||
| 407 | 0xe3 0 | ||
| 408 | 0xe4 0 | ||
| 409 | 0xe5 0 | ||
| 410 | 0xe6 0 | ||
| 411 | 0xe7 0>; | ||
| 412 | interrupt-parent = <&mpic>; | ||
| 413 | }; | ||
| 414 | |||
| 415 | global-utilities@e0000 { //global utilities block | ||
| 416 | compatible = "fsl,p1020-guts"; | ||
| 417 | reg = <0xe0000 0x1000>; | ||
| 418 | fsl,has-rstcr; | ||
| 419 | }; | ||
| 420 | }; | ||
| 421 | |||
| 422 | pci0: pcie@ffe09000 { | ||
| 423 | compatible = "fsl,mpc8548-pcie"; | ||
| 424 | device_type = "pci"; | ||
| 425 | #interrupt-cells = <1>; | ||
| 426 | #size-cells = <2>; | ||
| 427 | #address-cells = <3>; | ||
| 428 | reg = <0 0xffe09000 0 0x1000>; | ||
| 429 | bus-range = <0 255>; | ||
| 430 | ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000 | ||
| 431 | 0x1000000 0x0 0x00000000 0 0xffc30000 0x0 0x10000>; | ||
| 432 | clock-frequency = <33333333>; | ||
| 433 | interrupt-parent = <&mpic>; | ||
| 434 | interrupts = <16 2>; | ||
| 435 | pcie@0 { | ||
| 436 | reg = <0x0 0x0 0x0 0x0 0x0>; | ||
| 437 | #size-cells = <2>; | ||
| 438 | #address-cells = <3>; | ||
| 439 | device_type = "pci"; | ||
| 440 | ranges = <0x2000000 0x0 0xa0000000 | ||
| 441 | 0x2000000 0x0 0xa0000000 | ||
| 442 | 0x0 0x20000000 | ||
| 443 | |||
| 444 | 0x1000000 0x0 0x0 | ||
| 445 | 0x1000000 0x0 0x0 | ||
| 446 | 0x0 0x100000>; | ||
| 447 | }; | ||
| 448 | }; | ||
| 449 | |||
| 450 | pci1: pcie@ffe0a000 { | ||
| 451 | compatible = "fsl,mpc8548-pcie"; | ||
| 452 | device_type = "pci"; | ||
| 453 | #interrupt-cells = <1>; | ||
| 454 | #size-cells = <2>; | ||
| 455 | #address-cells = <3>; | ||
| 456 | reg = <0 0xffe0a000 0 0x1000>; | ||
| 457 | bus-range = <0 255>; | ||
| 458 | ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x20000000 | ||
| 459 | 0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>; | ||
| 460 | clock-frequency = <33333333>; | ||
| 461 | interrupt-parent = <&mpic>; | ||
| 462 | interrupts = <16 2>; | ||
| 463 | pcie@0 { | ||
| 464 | reg = <0x0 0x0 0x0 0x0 0x0>; | ||
| 465 | #size-cells = <2>; | ||
| 466 | #address-cells = <3>; | ||
| 467 | device_type = "pci"; | ||
| 468 | ranges = <0x2000000 0x0 0xc0000000 | ||
| 469 | 0x2000000 0x0 0xc0000000 | ||
| 470 | 0x0 0x20000000 | ||
| 471 | |||
| 472 | 0x1000000 0x0 0x0 | ||
| 473 | 0x1000000 0x0 0x0 | ||
| 474 | 0x0 0x100000>; | ||
| 475 | }; | ||
| 476 | }; | ||
| 477 | }; | ||
diff --git a/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts b/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts new file mode 100644 index 000000000000..0fe93d0c8b2e --- /dev/null +++ b/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts | |||
| @@ -0,0 +1,363 @@ | |||
| 1 | /* | ||
| 2 | * P2020 RDB Core0 Device Tree Source in CAMP mode. | ||
| 3 | * | ||
| 4 | * In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache | ||
| 5 | * can be shared, all the other devices must be assigned to one core only. | ||
| 6 | * This dts file allows core0 to have memory, l2, i2c, spi, gpio, dma1, usb, | ||
| 7 | * eth1, eth2, sdhc, crypto, global-util, pci0. | ||
| 8 | * | ||
| 9 | * Copyright 2009 Freescale Semiconductor Inc. | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify it | ||
| 12 | * under the terms of the GNU General Public License as published by the | ||
| 13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 14 | * option) any later version. | ||
| 15 | */ | ||
| 16 | |||
| 17 | /dts-v1/; | ||
| 18 | / { | ||
| 19 | model = "fsl,P2020"; | ||
| 20 | compatible = "fsl,P2020RDB", "fsl,MPC85XXRDB-CAMP"; | ||
| 21 | #address-cells = <2>; | ||
| 22 | #size-cells = <2>; | ||
| 23 | |||
| 24 | aliases { | ||
| 25 | ethernet1 = &enet1; | ||
| 26 | ethernet2 = &enet2; | ||
| 27 | serial0 = &serial0; | ||
| 28 | pci0 = &pci0; | ||
| 29 | }; | ||
| 30 | |||
| 31 | cpus { | ||
| 32 | #address-cells = <1>; | ||
| 33 | #size-cells = <0>; | ||
| 34 | |||
| 35 | PowerPC,P2020@0 { | ||
| 36 | device_type = "cpu"; | ||
| 37 | reg = <0x0>; | ||
| 38 | next-level-cache = <&L2>; | ||
| 39 | }; | ||
| 40 | }; | ||
| 41 | |||
| 42 | memory { | ||
| 43 | device_type = "memory"; | ||
| 44 | }; | ||
| 45 | |||
| 46 | soc@ffe00000 { | ||
| 47 | #address-cells = <1>; | ||
| 48 | #size-cells = <1>; | ||
| 49 | device_type = "soc"; | ||
| 50 | compatible = "fsl,p2020-immr", "simple-bus"; | ||
| 51 | ranges = <0x0 0x0 0xffe00000 0x100000>; | ||
| 52 | bus-frequency = <0>; // Filled out by uboot. | ||
| 53 | |||
| 54 | ecm-law@0 { | ||
| 55 | compatible = "fsl,ecm-law"; | ||
| 56 | reg = <0x0 0x1000>; | ||
| 57 | fsl,num-laws = <12>; | ||
| 58 | }; | ||
| 59 | |||
| 60 | ecm@1000 { | ||
| 61 | compatible = "fsl,p2020-ecm", "fsl,ecm"; | ||
| 62 | reg = <0x1000 0x1000>; | ||
| 63 | interrupts = <17 2>; | ||
| 64 | interrupt-parent = <&mpic>; | ||
| 65 | }; | ||
| 66 | |||
| 67 | memory-controller@2000 { | ||
| 68 | compatible = "fsl,p2020-memory-controller"; | ||
| 69 | reg = <0x2000 0x1000>; | ||
| 70 | interrupt-parent = <&mpic>; | ||
| 71 | interrupts = <18 2>; | ||
| 72 | }; | ||
| 73 | |||
| 74 | i2c@3000 { | ||
| 75 | #address-cells = <1>; | ||
| 76 | #size-cells = <0>; | ||
| 77 | cell-index = <0>; | ||
| 78 | compatible = "fsl-i2c"; | ||
| 79 | reg = <0x3000 0x100>; | ||
| 80 | interrupts = <43 2>; | ||
| 81 | interrupt-parent = <&mpic>; | ||
| 82 | dfsrr; | ||
| 83 | rtc@68 { | ||
| 84 | compatible = "dallas,ds1339"; | ||
| 85 | reg = <0x68>; | ||
| 86 | }; | ||
| 87 | }; | ||
| 88 | |||
| 89 | i2c@3100 { | ||
| 90 | #address-cells = <1>; | ||
| 91 | #size-cells = <0>; | ||
| 92 | cell-index = <1>; | ||
| 93 | compatible = "fsl-i2c"; | ||
| 94 | reg = <0x3100 0x100>; | ||
| 95 | interrupts = <43 2>; | ||
| 96 | interrupt-parent = <&mpic>; | ||
| 97 | dfsrr; | ||
| 98 | }; | ||
| 99 | |||
| 100 | serial0: serial@4500 { | ||
| 101 | cell-index = <0>; | ||
| 102 | device_type = "serial"; | ||
| 103 | compatible = "ns16550"; | ||
| 104 | reg = <0x4500 0x100>; | ||
| 105 | clock-frequency = <0>; | ||
| 106 | }; | ||
| 107 | |||
| 108 | spi@7000 { | ||
| 109 | cell-index = <0>; | ||
| 110 | #address-cells = <1>; | ||
| 111 | #size-cells = <0>; | ||
| 112 | compatible = "fsl,espi"; | ||
| 113 | reg = <0x7000 0x1000>; | ||
| 114 | interrupts = <59 0x2>; | ||
| 115 | interrupt-parent = <&mpic>; | ||
| 116 | mode = "cpu"; | ||
| 117 | |||
| 118 | fsl_m25p80@0 { | ||
| 119 | #address-cells = <1>; | ||
| 120 | #size-cells = <1>; | ||
| 121 | compatible = "fsl,espi-flash"; | ||
| 122 | reg = <0>; | ||
| 123 | linux,modalias = "fsl_m25p80"; | ||
| 124 | modal = "s25sl128b"; | ||
| 125 | spi-max-frequency = <50000000>; | ||
| 126 | mode = <0>; | ||
| 127 | |||
| 128 | partition@0 { | ||
| 129 | /* 512KB for u-boot Bootloader Image */ | ||
| 130 | reg = <0x0 0x00080000>; | ||
| 131 | label = "SPI (RO) U-Boot Image"; | ||
| 132 | read-only; | ||
| 133 | }; | ||
| 134 | |||
| 135 | partition@80000 { | ||
| 136 | /* 512KB for DTB Image */ | ||
| 137 | reg = <0x00080000 0x00080000>; | ||
| 138 | label = "SPI (RO) DTB Image"; | ||
| 139 | read-only; | ||
| 140 | }; | ||
| 141 | |||
| 142 | partition@100000 { | ||
| 143 | /* 4MB for Linux Kernel Image */ | ||
| 144 | reg = <0x00100000 0x00400000>; | ||
| 145 | label = "SPI (RO) Linux Kernel Image"; | ||
| 146 | read-only; | ||
| 147 | }; | ||
| 148 | |||
| 149 | partition@500000 { | ||
| 150 | /* 4MB for Compressed RFS Image */ | ||
| 151 | reg = <0x00500000 0x00400000>; | ||
| 152 | label = "SPI (RO) Compressed RFS Image"; | ||
| 153 | read-only; | ||
| 154 | }; | ||
| 155 | |||
| 156 | partition@900000 { | ||
| 157 | /* 7MB for JFFS2 based RFS */ | ||
| 158 | reg = <0x00900000 0x00700000>; | ||
| 159 | label = "SPI (RW) JFFS2 RFS"; | ||
| 160 | }; | ||
| 161 | }; | ||
| 162 | }; | ||
| 163 | |||
| 164 | gpio: gpio-controller@f000 { | ||
| 165 | #gpio-cells = <2>; | ||
| 166 | compatible = "fsl,mpc8572-gpio"; | ||
| 167 | reg = <0xf000 0x100>; | ||
| 168 | interrupts = <47 0x2>; | ||
| 169 | interrupt-parent = <&mpic>; | ||
| 170 | gpio-controller; | ||
| 171 | }; | ||
| 172 | |||
| 173 | L2: l2-cache-controller@20000 { | ||
| 174 | compatible = "fsl,p2020-l2-cache-controller"; | ||
| 175 | reg = <0x20000 0x1000>; | ||
| 176 | cache-line-size = <32>; // 32 bytes | ||
| 177 | cache-size = <0x80000>; // L2,512K | ||
| 178 | interrupt-parent = <&mpic>; | ||
| 179 | interrupts = <16 2>; | ||
| 180 | }; | ||
| 181 | |||
| 182 | dma@21300 { | ||
| 183 | #address-cells = <1>; | ||
| 184 | #size-cells = <1>; | ||
| 185 | compatible = "fsl,eloplus-dma"; | ||
| 186 | reg = <0x21300 0x4>; | ||
| 187 | ranges = <0x0 0x21100 0x200>; | ||
| 188 | cell-index = <0>; | ||
| 189 | dma-channel@0 { | ||
| 190 | compatible = "fsl,eloplus-dma-channel"; | ||
| 191 | reg = <0x0 0x80>; | ||
| 192 | cell-index = <0>; | ||
| 193 | interrupt-parent = <&mpic>; | ||
| 194 | interrupts = <20 2>; | ||
| 195 | }; | ||
| 196 | dma-channel@80 { | ||
| 197 | compatible = "fsl,eloplus-dma-channel"; | ||
| 198 | reg = <0x80 0x80>; | ||
| 199 | cell-index = <1>; | ||
| 200 | interrupt-parent = <&mpic>; | ||
| 201 | interrupts = <21 2>; | ||
| 202 | }; | ||
| 203 | dma-channel@100 { | ||
| 204 | compatible = "fsl,eloplus-dma-channel"; | ||
| 205 | reg = <0x100 0x80>; | ||
| 206 | cell-index = <2>; | ||
| 207 | interrupt-parent = <&mpic>; | ||
| 208 | interrupts = <22 2>; | ||
| 209 | }; | ||
| 210 | dma-channel@180 { | ||
| 211 | compatible = "fsl,eloplus-dma-channel"; | ||
| 212 | reg = <0x180 0x80>; | ||
| 213 | cell-index = <3>; | ||
| 214 | interrupt-parent = <&mpic>; | ||
| 215 | interrupts = <23 2>; | ||
| 216 | }; | ||
| 217 | }; | ||
| 218 | |||
| 219 | usb@22000 { | ||
| 220 | #address-cells = <1>; | ||
| 221 | #size-cells = <0>; | ||
| 222 | compatible = "fsl-usb2-dr"; | ||
| 223 | reg = <0x22000 0x1000>; | ||
| 224 | interrupt-parent = <&mpic>; | ||
| 225 | interrupts = <28 0x2>; | ||
| 226 | phy_type = "ulpi"; | ||
| 227 | }; | ||
| 228 | |||
| 229 | mdio@24520 { | ||
| 230 | #address-cells = <1>; | ||
| 231 | #size-cells = <0>; | ||
| 232 | compatible = "fsl,gianfar-mdio"; | ||
| 233 | reg = <0x24520 0x20>; | ||
| 234 | |||
| 235 | phy0: ethernet-phy@0 { | ||
| 236 | interrupt-parent = <&mpic>; | ||
| 237 | interrupts = <3 1>; | ||
| 238 | reg = <0x0>; | ||
| 239 | }; | ||
| 240 | phy1: ethernet-phy@1 { | ||
| 241 | interrupt-parent = <&mpic>; | ||
| 242 | interrupts = <3 1>; | ||
| 243 | reg = <0x1>; | ||
| 244 | }; | ||
| 245 | }; | ||
| 246 | |||
| 247 | mdio@25520 { | ||
| 248 | #address-cells = <1>; | ||
| 249 | #size-cells = <0>; | ||
| 250 | compatible = "fsl,gianfar-tbi"; | ||
| 251 | reg = <0x26520 0x20>; | ||
| 252 | |||
| 253 | tbi0: tbi-phy@11 { | ||
| 254 | reg = <0x11>; | ||
| 255 | device_type = "tbi-phy"; | ||
| 256 | }; | ||
| 257 | }; | ||
| 258 | |||
| 259 | enet1: ethernet@25000 { | ||
| 260 | #address-cells = <1>; | ||
| 261 | #size-cells = <1>; | ||
| 262 | cell-index = <1>; | ||
| 263 | device_type = "network"; | ||
| 264 | model = "eTSEC"; | ||
| 265 | compatible = "gianfar"; | ||
| 266 | reg = <0x25000 0x1000>; | ||
| 267 | ranges = <0x0 0x25000 0x1000>; | ||
| 268 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 269 | interrupts = <35 2 36 2 40 2>; | ||
| 270 | interrupt-parent = <&mpic>; | ||
| 271 | tbi-handle = <&tbi0>; | ||
| 272 | phy-handle = <&phy0>; | ||
| 273 | phy-connection-type = "sgmii"; | ||
| 274 | |||
| 275 | }; | ||
| 276 | |||
| 277 | enet2: ethernet@26000 { | ||
| 278 | #address-cells = <1>; | ||
| 279 | #size-cells = <1>; | ||
| 280 | cell-index = <2>; | ||
| 281 | device_type = "network"; | ||
| 282 | model = "eTSEC"; | ||
| 283 | compatible = "gianfar"; | ||
| 284 | reg = <0x26000 0x1000>; | ||
| 285 | ranges = <0x0 0x26000 0x1000>; | ||
| 286 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 287 | interrupts = <31 2 32 2 33 2>; | ||
| 288 | interrupt-parent = <&mpic>; | ||
| 289 | phy-handle = <&phy1>; | ||
| 290 | phy-connection-type = "rgmii-id"; | ||
| 291 | }; | ||
| 292 | |||
| 293 | sdhci@2e000 { | ||
| 294 | compatible = "fsl,p2020-esdhc", "fsl,esdhc"; | ||
| 295 | reg = <0x2e000 0x1000>; | ||
| 296 | interrupts = <72 0x2>; | ||
| 297 | interrupt-parent = <&mpic>; | ||
| 298 | /* Filled in by U-Boot */ | ||
| 299 | clock-frequency = <0>; | ||
| 300 | }; | ||
| 301 | |||
| 302 | crypto@30000 { | ||
| 303 | compatible = "fsl,sec3.1", "fsl,sec3.0", "fsl,sec2.4", | ||
| 304 | "fsl,sec2.2", "fsl,sec2.1", "fsl,sec2.0"; | ||
| 305 | reg = <0x30000 0x10000>; | ||
| 306 | interrupts = <45 2 58 2>; | ||
| 307 | interrupt-parent = <&mpic>; | ||
| 308 | fsl,num-channels = <4>; | ||
| 309 | fsl,channel-fifo-len = <24>; | ||
| 310 | fsl,exec-units-mask = <0xbfe>; | ||
| 311 | fsl,descriptor-types-mask = <0x3ab0ebf>; | ||
| 312 | }; | ||
| 313 | |||
| 314 | mpic: pic@40000 { | ||
| 315 | interrupt-controller; | ||
| 316 | #address-cells = <0>; | ||
| 317 | #interrupt-cells = <2>; | ||
| 318 | reg = <0x40000 0x40000>; | ||
| 319 | compatible = "chrp,open-pic"; | ||
| 320 | device_type = "open-pic"; | ||
| 321 | protected-sources = < | ||
| 322 | 42 76 77 78 79 /* serial1 , dma2 */ | ||
| 323 | 29 30 34 26 /* enet0, pci1 */ | ||
| 324 | 0xe0 0xe1 0xe2 0xe3 /* msi */ | ||
| 325 | 0xe4 0xe5 0xe6 0xe7 | ||
| 326 | >; | ||
| 327 | }; | ||
| 328 | |||
| 329 | global-utilities@e0000 { | ||
| 330 | compatible = "fsl,p2020-guts"; | ||
| 331 | reg = <0xe0000 0x1000>; | ||
| 332 | fsl,has-rstcr; | ||
| 333 | }; | ||
| 334 | }; | ||
| 335 | |||
| 336 | pci0: pcie@ffe09000 { | ||
| 337 | compatible = "fsl,mpc8548-pcie"; | ||
| 338 | device_type = "pci"; | ||
| 339 | #interrupt-cells = <1>; | ||
| 340 | #size-cells = <2>; | ||
| 341 | #address-cells = <3>; | ||
| 342 | reg = <0 0xffe09000 0 0x1000>; | ||
| 343 | bus-range = <0 255>; | ||
| 344 | ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000 | ||
| 345 | 0x1000000 0x0 0x00000000 0 0xffc30000 0x0 0x10000>; | ||
| 346 | clock-frequency = <33333333>; | ||
| 347 | interrupt-parent = <&mpic>; | ||
| 348 | interrupts = <25 2>; | ||
| 349 | pcie@0 { | ||
| 350 | reg = <0x0 0x0 0x0 0x0 0x0>; | ||
| 351 | #size-cells = <2>; | ||
| 352 | #address-cells = <3>; | ||
| 353 | device_type = "pci"; | ||
| 354 | ranges = <0x2000000 0x0 0xa0000000 | ||
| 355 | 0x2000000 0x0 0xa0000000 | ||
| 356 | 0x0 0x20000000 | ||
| 357 | |||
| 358 | 0x1000000 0x0 0x0 | ||
| 359 | 0x1000000 0x0 0x0 | ||
| 360 | 0x0 0x100000>; | ||
| 361 | }; | ||
| 362 | }; | ||
| 363 | }; | ||
diff --git a/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts b/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts new file mode 100644 index 000000000000..e95a51285328 --- /dev/null +++ b/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts | |||
| @@ -0,0 +1,184 @@ | |||
| 1 | /* | ||
| 2 | * P2020 RDB Core1 Device Tree Source in CAMP mode. | ||
| 3 | * | ||
| 4 | * In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache | ||
| 5 | * can be shared, all the other devices must be assigned to one core only. | ||
| 6 | * This dts allows core1 to have l2, dma2, eth0, pci1, msi. | ||
| 7 | * | ||
| 8 | * Please note to add "-b 1" for core1's dts compiling. | ||
| 9 | * | ||
| 10 | * Copyright 2009 Freescale Semiconductor Inc. | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify it | ||
| 13 | * under the terms of the GNU General Public License as published by the | ||
| 14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 15 | * option) any later version. | ||
| 16 | */ | ||
| 17 | |||
| 18 | /dts-v1/; | ||
| 19 | / { | ||
| 20 | model = "fsl,P2020"; | ||
| 21 | compatible = "fsl,P2020RDB", "fsl,MPC85XXRDB-CAMP"; | ||
| 22 | #address-cells = <2>; | ||
| 23 | #size-cells = <2>; | ||
| 24 | |||
| 25 | aliases { | ||
| 26 | ethernet0 = &enet0; | ||
| 27 | serial0 = &serial0; | ||
| 28 | pci1 = &pci1; | ||
| 29 | }; | ||
| 30 | |||
| 31 | cpus { | ||
| 32 | #address-cells = <1>; | ||
| 33 | #size-cells = <0>; | ||
| 34 | |||
| 35 | PowerPC,P2020@1 { | ||
| 36 | device_type = "cpu"; | ||
| 37 | reg = <0x1>; | ||
| 38 | next-level-cache = <&L2>; | ||
| 39 | }; | ||
| 40 | }; | ||
| 41 | |||
| 42 | memory { | ||
| 43 | device_type = "memory"; | ||
| 44 | }; | ||
| 45 | |||
| 46 | soc@ffe00000 { | ||
| 47 | #address-cells = <1>; | ||
| 48 | #size-cells = <1>; | ||
| 49 | device_type = "soc"; | ||
| 50 | compatible = "fsl,p2020-immr", "simple-bus"; | ||
| 51 | ranges = <0x0 0x0 0xffe00000 0x100000>; | ||
| 52 | bus-frequency = <0>; // Filled out by uboot. | ||
| 53 | |||
| 54 | serial0: serial@4600 { | ||
| 55 | cell-index = <1>; | ||
| 56 | device_type = "serial"; | ||
| 57 | compatible = "ns16550"; | ||
| 58 | reg = <0x4600 0x100>; | ||
| 59 | clock-frequency = <0>; | ||
| 60 | }; | ||
| 61 | |||
| 62 | dma@c300 { | ||
| 63 | #address-cells = <1>; | ||
| 64 | #size-cells = <1>; | ||
| 65 | compatible = "fsl,eloplus-dma"; | ||
| 66 | reg = <0xc300 0x4>; | ||
| 67 | ranges = <0x0 0xc100 0x200>; | ||
| 68 | cell-index = <1>; | ||
| 69 | dma-channel@0 { | ||
| 70 | compatible = "fsl,eloplus-dma-channel"; | ||
| 71 | reg = <0x0 0x80>; | ||
| 72 | cell-index = <0>; | ||
| 73 | interrupt-parent = <&mpic>; | ||
| 74 | interrupts = <76 2>; | ||
| 75 | }; | ||
| 76 | dma-channel@80 { | ||
| 77 | compatible = "fsl,eloplus-dma-channel"; | ||
| 78 | reg = <0x80 0x80>; | ||
| 79 | cell-index = <1>; | ||
| 80 | interrupt-parent = <&mpic>; | ||
| 81 | interrupts = <77 2>; | ||
| 82 | }; | ||
| 83 | dma-channel@100 { | ||
| 84 | compatible = "fsl,eloplus-dma-channel"; | ||
| 85 | reg = <0x100 0x80>; | ||
| 86 | cell-index = <2>; | ||
| 87 | interrupt-parent = <&mpic>; | ||
| 88 | interrupts = <78 2>; | ||
| 89 | }; | ||
| 90 | dma-channel@180 { | ||
| 91 | compatible = "fsl,eloplus-dma-channel"; | ||
| 92 | reg = <0x180 0x80>; | ||
| 93 | cell-index = <3>; | ||
| 94 | interrupt-parent = <&mpic>; | ||
| 95 | interrupts = <79 2>; | ||
| 96 | }; | ||
| 97 | }; | ||
| 98 | |||
| 99 | L2: l2-cache-controller@20000 { | ||
| 100 | compatible = "fsl,p2020-l2-cache-controller"; | ||
| 101 | reg = <0x20000 0x1000>; | ||
| 102 | cache-line-size = <32>; // 32 bytes | ||
| 103 | cache-size = <0x80000>; // L2,512K | ||
| 104 | interrupt-parent = <&mpic>; | ||
| 105 | }; | ||
| 106 | |||
| 107 | |||
| 108 | enet0: ethernet@24000 { | ||
| 109 | #address-cells = <1>; | ||
| 110 | #size-cells = <1>; | ||
| 111 | cell-index = <0>; | ||
| 112 | device_type = "network"; | ||
| 113 | model = "eTSEC"; | ||
| 114 | compatible = "gianfar"; | ||
| 115 | reg = <0x24000 0x1000>; | ||
| 116 | ranges = <0x0 0x24000 0x1000>; | ||
| 117 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 118 | interrupts = <29 2 30 2 34 2>; | ||
| 119 | interrupt-parent = <&mpic>; | ||
| 120 | fixed-link = <1 1 1000 0 0>; | ||
| 121 | phy-connection-type = "rgmii-id"; | ||
| 122 | |||
| 123 | }; | ||
| 124 | |||
| 125 | mpic: pic@40000 { | ||
| 126 | interrupt-controller; | ||
| 127 | #address-cells = <0>; | ||
| 128 | #interrupt-cells = <2>; | ||
| 129 | reg = <0x40000 0x40000>; | ||
| 130 | compatible = "chrp,open-pic"; | ||
| 131 | device_type = "open-pic"; | ||
| 132 | protected-sources = < | ||
| 133 | 17 18 43 42 59 47 /*ecm, mem, i2c, serial0, spi,gpio */ | ||
| 134 | 16 20 21 22 23 28 /* L2, dma1, USB */ | ||
| 135 | 03 35 36 40 31 32 33 /* mdio, enet1, enet2 */ | ||
| 136 | 72 45 58 25 /* sdhci, crypto , pci */ | ||
| 137 | >; | ||
| 138 | }; | ||
| 139 | |||
| 140 | msi@41600 { | ||
| 141 | compatible = "fsl,p2020-msi", "fsl,mpic-msi"; | ||
| 142 | reg = <0x41600 0x80>; | ||
| 143 | msi-available-ranges = <0 0x100>; | ||
| 144 | interrupts = < | ||
| 145 | 0xe0 0 | ||
| 146 | 0xe1 0 | ||
| 147 | 0xe2 0 | ||
| 148 | 0xe3 0 | ||
| 149 | 0xe4 0 | ||
| 150 | 0xe5 0 | ||
| 151 | 0xe6 0 | ||
| 152 | 0xe7 0>; | ||
| 153 | interrupt-parent = <&mpic>; | ||
| 154 | }; | ||
| 155 | }; | ||
| 156 | |||
| 157 | pci1: pcie@ffe0a000 { | ||
| 158 | compatible = "fsl,mpc8548-pcie"; | ||
| 159 | device_type = "pci"; | ||
| 160 | #interrupt-cells = <1>; | ||
| 161 | #size-cells = <2>; | ||
| 162 | #address-cells = <3>; | ||
| 163 | reg = <0 0xffe0a000 0 0x1000>; | ||
| 164 | bus-range = <0 255>; | ||
| 165 | ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x20000000 | ||
| 166 | 0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>; | ||
| 167 | clock-frequency = <33333333>; | ||
| 168 | interrupt-parent = <&mpic>; | ||
| 169 | interrupts = <26 2>; | ||
| 170 | pcie@0 { | ||
| 171 | reg = <0x0 0x0 0x0 0x0 0x0>; | ||
| 172 | #size-cells = <2>; | ||
| 173 | #address-cells = <3>; | ||
| 174 | device_type = "pci"; | ||
| 175 | ranges = <0x2000000 0x0 0xc0000000 | ||
| 176 | 0x2000000 0x0 0xc0000000 | ||
| 177 | 0x0 0x20000000 | ||
| 178 | |||
| 179 | 0x1000000 0x0 0x0 | ||
| 180 | 0x1000000 0x0 0x0 | ||
| 181 | 0x0 0x100000>; | ||
| 182 | }; | ||
| 183 | }; | ||
| 184 | }; | ||
diff --git a/arch/powerpc/boot/dts/p4080ds.dts b/arch/powerpc/boot/dts/p4080ds.dts new file mode 100644 index 000000000000..6b29eab05362 --- /dev/null +++ b/arch/powerpc/boot/dts/p4080ds.dts | |||
| @@ -0,0 +1,554 @@ | |||
| 1 | /* | ||
| 2 | * P4080DS Device Tree Source | ||
| 3 | * | ||
| 4 | * Copyright 2009 Freescale Semiconductor Inc. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published by the | ||
| 8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 9 | * option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | /dts-v1/; | ||
| 13 | |||
| 14 | / { | ||
| 15 | model = "fsl,P4080DS"; | ||
| 16 | compatible = "fsl,P4080DS"; | ||
| 17 | #address-cells = <2>; | ||
| 18 | #size-cells = <2>; | ||
| 19 | |||
| 20 | aliases { | ||
| 21 | ccsr = &soc; | ||
| 22 | |||
| 23 | serial0 = &serial0; | ||
| 24 | serial1 = &serial1; | ||
| 25 | serial2 = &serial2; | ||
| 26 | serial3 = &serial3; | ||
| 27 | pci0 = &pci0; | ||
| 28 | pci1 = &pci1; | ||
| 29 | pci2 = &pci2; | ||
| 30 | usb0 = &usb0; | ||
| 31 | usb1 = &usb1; | ||
| 32 | dma0 = &dma0; | ||
| 33 | dma1 = &dma1; | ||
| 34 | sdhc = &sdhc; | ||
| 35 | |||
| 36 | rio0 = &rapidio0; | ||
| 37 | }; | ||
| 38 | |||
| 39 | cpus { | ||
| 40 | #address-cells = <1>; | ||
| 41 | #size-cells = <0>; | ||
| 42 | |||
| 43 | cpu0: PowerPC,4080@0 { | ||
| 44 | device_type = "cpu"; | ||
| 45 | reg = <0>; | ||
| 46 | next-level-cache = <&L2_0>; | ||
| 47 | L2_0: l2-cache { | ||
| 48 | }; | ||
| 49 | }; | ||
| 50 | cpu1: PowerPC,4080@1 { | ||
| 51 | device_type = "cpu"; | ||
| 52 | reg = <1>; | ||
| 53 | next-level-cache = <&L2_1>; | ||
| 54 | L2_1: l2-cache { | ||
| 55 | }; | ||
| 56 | }; | ||
| 57 | cpu2: PowerPC,4080@2 { | ||
| 58 | device_type = "cpu"; | ||
| 59 | reg = <2>; | ||
| 60 | next-level-cache = <&L2_2>; | ||
| 61 | L2_2: l2-cache { | ||
| 62 | }; | ||
| 63 | }; | ||
| 64 | cpu3: PowerPC,4080@3 { | ||
| 65 | device_type = "cpu"; | ||
| 66 | reg = <3>; | ||
| 67 | next-level-cache = <&L2_3>; | ||
| 68 | L2_3: l2-cache { | ||
| 69 | }; | ||
| 70 | }; | ||
| 71 | cpu4: PowerPC,4080@4 { | ||
| 72 | device_type = "cpu"; | ||
| 73 | reg = <4>; | ||
| 74 | next-level-cache = <&L2_4>; | ||
| 75 | L2_4: l2-cache { | ||
| 76 | }; | ||
| 77 | }; | ||
| 78 | cpu5: PowerPC,4080@5 { | ||
| 79 | device_type = "cpu"; | ||
| 80 | reg = <5>; | ||
| 81 | next-level-cache = <&L2_5>; | ||
| 82 | L2_5: l2-cache { | ||
| 83 | }; | ||
| 84 | }; | ||
| 85 | cpu6: PowerPC,4080@6 { | ||
| 86 | device_type = "cpu"; | ||
| 87 | reg = <6>; | ||
| 88 | next-level-cache = <&L2_6>; | ||
| 89 | L2_6: l2-cache { | ||
| 90 | }; | ||
| 91 | }; | ||
| 92 | cpu7: PowerPC,4080@7 { | ||
| 93 | device_type = "cpu"; | ||
| 94 | reg = <7>; | ||
| 95 | next-level-cache = <&L2_7>; | ||
| 96 | L2_7: l2-cache { | ||
| 97 | }; | ||
| 98 | }; | ||
| 99 | }; | ||
| 100 | |||
| 101 | memory { | ||
| 102 | device_type = "memory"; | ||
| 103 | }; | ||
| 104 | |||
| 105 | soc: soc@ffe000000 { | ||
| 106 | #address-cells = <1>; | ||
| 107 | #size-cells = <1>; | ||
| 108 | device_type = "soc"; | ||
| 109 | compatible = "simple-bus"; | ||
| 110 | ranges = <0x00000000 0xf 0xfe000000 0x1000000>; | ||
| 111 | reg = <0xf 0xfe000000 0 0x00001000>; | ||
| 112 | |||
| 113 | corenet-law@0 { | ||
| 114 | compatible = "fsl,corenet-law"; | ||
| 115 | reg = <0x0 0x1000>; | ||
| 116 | fsl,num-laws = <32>; | ||
| 117 | }; | ||
| 118 | |||
| 119 | memory-controller@8000 { | ||
| 120 | compatible = "fsl,p4080-memory-controller"; | ||
| 121 | reg = <0x8000 0x1000>; | ||
| 122 | interrupt-parent = <&mpic>; | ||
| 123 | interrupts = <0x12 2>; | ||
| 124 | }; | ||
| 125 | |||
| 126 | memory-controller@9000 { | ||
| 127 | compatible = "fsl,p4080-memory-controller"; | ||
| 128 | reg = <0x9000 0x1000>; | ||
| 129 | interrupt-parent = <&mpic>; | ||
| 130 | interrupts = <0x12 2>; | ||
| 131 | }; | ||
| 132 | |||
| 133 | corenet-cf@18000 { | ||
| 134 | compatible = "fsl,corenet-cf"; | ||
| 135 | reg = <0x18000 0x1000>; | ||
| 136 | fsl,ccf-num-csdids = <32>; | ||
| 137 | fsl,ccf-num-snoopids = <32>; | ||
| 138 | }; | ||
| 139 | |||
| 140 | iommu@20000 { | ||
| 141 | compatible = "fsl,p4080-pamu"; | ||
| 142 | reg = <0x20000 0x10000>; | ||
| 143 | interrupts = <24 2>; | ||
| 144 | interrupt-parent = <&mpic>; | ||
| 145 | }; | ||
| 146 | |||
| 147 | mpic: pic@40000 { | ||
| 148 | interrupt-controller; | ||
| 149 | #address-cells = <0>; | ||
| 150 | #interrupt-cells = <2>; | ||
| 151 | reg = <0x40000 0x40000>; | ||
| 152 | compatible = "chrp,open-pic"; | ||
| 153 | device_type = "open-pic"; | ||
| 154 | }; | ||
| 155 | |||
| 156 | dma0: dma@100300 { | ||
| 157 | #address-cells = <1>; | ||
| 158 | #size-cells = <1>; | ||
| 159 | compatible = "fsl,p4080-dma", "fsl,eloplus-dma"; | ||
| 160 | reg = <0x100300 0x4>; | ||
| 161 | ranges = <0x0 0x100100 0x200>; | ||
| 162 | cell-index = <0>; | ||
| 163 | dma-channel@0 { | ||
| 164 | compatible = "fsl,p4080-dma-channel", | ||
| 165 | "fsl,eloplus-dma-channel"; | ||
| 166 | reg = <0x0 0x80>; | ||
| 167 | cell-index = <0>; | ||
| 168 | interrupt-parent = <&mpic>; | ||
| 169 | interrupts = <28 2>; | ||
| 170 | }; | ||
| 171 | dma-channel@80 { | ||
| 172 | compatible = "fsl,p4080-dma-channel", | ||
| 173 | "fsl,eloplus-dma-channel"; | ||
| 174 | reg = <0x80 0x80>; | ||
| 175 | cell-index = <1>; | ||
| 176 | interrupt-parent = <&mpic>; | ||
| 177 | interrupts = <29 2>; | ||
| 178 | }; | ||
| 179 | dma-channel@100 { | ||
| 180 | compatible = "fsl,p4080-dma-channel", | ||
| 181 | "fsl,eloplus-dma-channel"; | ||
| 182 | reg = <0x100 0x80>; | ||
| 183 | cell-index = <2>; | ||
| 184 | interrupt-parent = <&mpic>; | ||
| 185 | interrupts = <30 2>; | ||
| 186 | }; | ||
| 187 | dma-channel@180 { | ||
| 188 | compatible = "fsl,p4080-dma-channel", | ||
| 189 | "fsl,eloplus-dma-channel"; | ||
| 190 | reg = <0x180 0x80>; | ||
| 191 | cell-index = <3>; | ||
| 192 | interrupt-parent = <&mpic>; | ||
| 193 | interrupts = <31 2>; | ||
| 194 | }; | ||
| 195 | }; | ||
| 196 | |||
| 197 | dma1: dma@101300 { | ||
| 198 | #address-cells = <1>; | ||
| 199 | #size-cells = <1>; | ||
| 200 | compatible = "fsl,p4080-dma", "fsl,eloplus-dma"; | ||
| 201 | reg = <0x101300 0x4>; | ||
| 202 | ranges = <0x0 0x101100 0x200>; | ||
| 203 | cell-index = <1>; | ||
| 204 | dma-channel@0 { | ||
| 205 | compatible = "fsl,p4080-dma-channel", | ||
| 206 | "fsl,eloplus-dma-channel"; | ||
| 207 | reg = <0x0 0x80>; | ||
| 208 | cell-index = <0>; | ||
| 209 | interrupt-parent = <&mpic>; | ||
| 210 | interrupts = <32 2>; | ||
| 211 | }; | ||
| 212 | dma-channel@80 { | ||
| 213 | compatible = "fsl,p4080-dma-channel", | ||
| 214 | "fsl,eloplus-dma-channel"; | ||
| 215 | reg = <0x80 0x80>; | ||
| 216 | cell-index = <1>; | ||
| 217 | interrupt-parent = <&mpic>; | ||
| 218 | interrupts = <33 2>; | ||
| 219 | }; | ||
| 220 | dma-channel@100 { | ||
| 221 | compatible = "fsl,p4080-dma-channel", | ||
| 222 | "fsl,eloplus-dma-channel"; | ||
| 223 | reg = <0x100 0x80>; | ||
| 224 | cell-index = <2>; | ||
| 225 | interrupt-parent = <&mpic>; | ||
| 226 | interrupts = <34 2>; | ||
| 227 | }; | ||
| 228 | dma-channel@180 { | ||
| 229 | compatible = "fsl,p4080-dma-channel", | ||
| 230 | "fsl,eloplus-dma-channel"; | ||
| 231 | reg = <0x180 0x80>; | ||
| 232 | cell-index = <3>; | ||
| 233 | interrupt-parent = <&mpic>; | ||
| 234 | interrupts = <35 2>; | ||
| 235 | }; | ||
| 236 | }; | ||
| 237 | |||
| 238 | spi@110000 { | ||
| 239 | cell-index = <0>; | ||
| 240 | #address-cells = <1>; | ||
| 241 | #size-cells = <0>; | ||
| 242 | compatible = "fsl,espi"; | ||
| 243 | reg = <0x110000 0x1000>; | ||
| 244 | interrupts = <53 0x2>; | ||
| 245 | interrupt-parent = <&mpic>; | ||
| 246 | espi,num-ss-bits = <4>; | ||
| 247 | mode = "cpu"; | ||
| 248 | |||
| 249 | fsl_m25p80@0 { | ||
| 250 | #address-cells = <1>; | ||
| 251 | #size-cells = <1>; | ||
| 252 | compatible = "fsl,espi-flash"; | ||
| 253 | reg = <0>; | ||
| 254 | linux,modalias = "fsl_m25p80"; | ||
| 255 | spi-max-frequency = <40000000>; /* input clock */ | ||
| 256 | partition@u-boot { | ||
| 257 | label = "u-boot"; | ||
| 258 | reg = <0x00000000 0x00100000>; | ||
| 259 | read-only; | ||
| 260 | }; | ||
| 261 | partition@kernel { | ||
| 262 | label = "kernel"; | ||
| 263 | reg = <0x00100000 0x00500000>; | ||
| 264 | read-only; | ||
| 265 | }; | ||
| 266 | partition@dtb { | ||
| 267 | label = "dtb"; | ||
| 268 | reg = <0x00600000 0x00100000>; | ||
| 269 | read-only; | ||
| 270 | }; | ||
| 271 | partition@fs { | ||
| 272 | label = "file system"; | ||
| 273 | reg = <0x00700000 0x00900000>; | ||
| 274 | }; | ||
| 275 | }; | ||
| 276 | }; | ||
| 277 | |||
| 278 | sdhc: sdhc@114000 { | ||
| 279 | compatible = "fsl,p4080-esdhc", "fsl,esdhc"; | ||
| 280 | reg = <0x114000 0x1000>; | ||
| 281 | interrupts = <48 2>; | ||
| 282 | interrupt-parent = <&mpic>; | ||
| 283 | }; | ||
| 284 | |||
| 285 | i2c@118000 { | ||
| 286 | #address-cells = <1>; | ||
| 287 | #size-cells = <0>; | ||
| 288 | cell-index = <0>; | ||
| 289 | compatible = "fsl-i2c"; | ||
| 290 | reg = <0x118000 0x100>; | ||
| 291 | interrupts = <38 2>; | ||
| 292 | interrupt-parent = <&mpic>; | ||
| 293 | dfsrr; | ||
| 294 | }; | ||
| 295 | |||
| 296 | i2c@118100 { | ||
| 297 | #address-cells = <1>; | ||
| 298 | #size-cells = <0>; | ||
| 299 | cell-index = <1>; | ||
| 300 | compatible = "fsl-i2c"; | ||
| 301 | reg = <0x118100 0x100>; | ||
| 302 | interrupts = <38 2>; | ||
| 303 | interrupt-parent = <&mpic>; | ||
| 304 | dfsrr; | ||
| 305 | eeprom@51 { | ||
| 306 | compatible = "at24,24c256"; | ||
| 307 | reg = <0x51>; | ||
| 308 | }; | ||
| 309 | eeprom@52 { | ||
| 310 | compatible = "at24,24c256"; | ||
| 311 | reg = <0x52>; | ||
| 312 | }; | ||
| 313 | rtc@68 { | ||
| 314 | compatible = "dallas,ds3232"; | ||
| 315 | reg = <0x68>; | ||
| 316 | interrupts = <0 0x1>; | ||
| 317 | interrupt-parent = <&mpic>; | ||
| 318 | }; | ||
| 319 | }; | ||
| 320 | |||
| 321 | i2c@119000 { | ||
| 322 | #address-cells = <1>; | ||
| 323 | #size-cells = <0>; | ||
| 324 | cell-index = <2>; | ||
| 325 | compatible = "fsl-i2c"; | ||
| 326 | reg = <0x119000 0x100>; | ||
| 327 | interrupts = <39 2>; | ||
| 328 | interrupt-parent = <&mpic>; | ||
| 329 | dfsrr; | ||
| 330 | }; | ||
| 331 | |||
| 332 | i2c@119100 { | ||
| 333 | #address-cells = <1>; | ||
| 334 | #size-cells = <0>; | ||
| 335 | cell-index = <3>; | ||
| 336 | compatible = "fsl-i2c"; | ||
| 337 | reg = <0x119100 0x100>; | ||
| 338 | interrupts = <39 2>; | ||
| 339 | interrupt-parent = <&mpic>; | ||
| 340 | dfsrr; | ||
| 341 | }; | ||
| 342 | |||
| 343 | serial0: serial@11c500 { | ||
| 344 | cell-index = <0>; | ||
| 345 | device_type = "serial"; | ||
| 346 | compatible = "ns16550"; | ||
| 347 | reg = <0x11c500 0x100>; | ||
| 348 | clock-frequency = <0>; | ||
| 349 | interrupts = <36 2>; | ||
| 350 | interrupt-parent = <&mpic>; | ||
| 351 | }; | ||
| 352 | |||
| 353 | serial1: serial@11c600 { | ||
| 354 | cell-index = <1>; | ||
| 355 | device_type = "serial"; | ||
| 356 | compatible = "ns16550"; | ||
| 357 | reg = <0x11c600 0x100>; | ||
| 358 | clock-frequency = <0>; | ||
| 359 | interrupts = <36 2>; | ||
| 360 | interrupt-parent = <&mpic>; | ||
| 361 | }; | ||
| 362 | |||
| 363 | serial2: serial@11d500 { | ||
| 364 | cell-index = <2>; | ||
| 365 | device_type = "serial"; | ||
| 366 | compatible = "ns16550"; | ||
| 367 | reg = <0x11d500 0x100>; | ||
| 368 | clock-frequency = <0>; | ||
| 369 | interrupts = <37 2>; | ||
| 370 | interrupt-parent = <&mpic>; | ||
| 371 | }; | ||
| 372 | |||
| 373 | serial3: serial@11d600 { | ||
| 374 | cell-index = <3>; | ||
| 375 | device_type = "serial"; | ||
| 376 | compatible = "ns16550"; | ||
| 377 | reg = <0x11d600 0x100>; | ||
| 378 | clock-frequency = <0>; | ||
| 379 | interrupts = <37 2>; | ||
| 380 | interrupt-parent = <&mpic>; | ||
| 381 | }; | ||
| 382 | |||
| 383 | gpio0: gpio@130000 { | ||
| 384 | compatible = "fsl,p4080-gpio"; | ||
| 385 | reg = <0x130000 0x1000>; | ||
| 386 | interrupts = <55 2>; | ||
| 387 | interrupt-parent = <&mpic>; | ||
| 388 | #gpio-cells = <2>; | ||
| 389 | gpio-controller; | ||
| 390 | }; | ||
| 391 | |||
| 392 | usb0: usb@210000 { | ||
| 393 | compatible = "fsl,p4080-usb2-mph", | ||
| 394 | "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph"; | ||
| 395 | reg = <0x210000 0x1000>; | ||
| 396 | #address-cells = <1>; | ||
| 397 | #size-cells = <0>; | ||
| 398 | interrupt-parent = <&mpic>; | ||
| 399 | interrupts = <44 0x2>; | ||
| 400 | phy_type = "ulpi"; | ||
| 401 | }; | ||
| 402 | |||
| 403 | usb1: usb@211000 { | ||
| 404 | compatible = "fsl,p4080-usb2-dr", | ||
| 405 | "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr"; | ||
| 406 | reg = <0x211000 0x1000>; | ||
| 407 | #address-cells = <1>; | ||
| 408 | #size-cells = <0>; | ||
| 409 | interrupt-parent = <&mpic>; | ||
| 410 | interrupts = <45 0x2>; | ||
| 411 | dr_mode = "host"; | ||
| 412 | phy_type = "ulpi"; | ||
| 413 | }; | ||
| 414 | }; | ||
| 415 | |||
| 416 | rapidio0: rapidio@ffe0c0000 { | ||
| 417 | #address-cells = <2>; | ||
| 418 | #size-cells = <2>; | ||
| 419 | compatible = "fsl,rapidio-delta"; | ||
| 420 | reg = <0xf 0xfe0c0000 0 0x20000>; | ||
| 421 | ranges = <0 0 0xf 0xf5000000 0 0x01000000>; | ||
| 422 | interrupt-parent = <&mpic>; | ||
| 423 | /* err_irq bell_outb_irq bell_inb_irq | ||
| 424 | msg1_tx_irq msg1_rx_irq msg2_tx_irq msg2_rx_irq */ | ||
| 425 | interrupts = <16 2 56 2 57 2 60 2 61 2 62 2 63 2>; | ||
| 426 | }; | ||
| 427 | |||
| 428 | localbus@ffe124000 { | ||
| 429 | compatible = "fsl,p4080-elbc", "fsl,elbc", "simple-bus"; | ||
| 430 | reg = <0xf 0xfe124000 0 0x1000>; | ||
| 431 | interrupts = <25 2>; | ||
| 432 | #address-cells = <2>; | ||
| 433 | #size-cells = <1>; | ||
| 434 | |||
| 435 | ranges = <0 0 0xf 0xe8000000 0x08000000>; | ||
| 436 | |||
| 437 | flash@0,0 { | ||
| 438 | compatible = "cfi-flash"; | ||
| 439 | reg = <0 0 0x08000000>; | ||
| 440 | bank-width = <2>; | ||
| 441 | device-width = <2>; | ||
| 442 | }; | ||
| 443 | }; | ||
| 444 | |||
| 445 | pci0: pcie@ffe200000 { | ||
| 446 | compatible = "fsl,p4080-pcie"; | ||
| 447 | device_type = "pci"; | ||
| 448 | #interrupt-cells = <1>; | ||
| 449 | #size-cells = <2>; | ||
| 450 | #address-cells = <3>; | ||
| 451 | reg = <0xf 0xfe200000 0 0x1000>; | ||
| 452 | bus-range = <0x0 0xff>; | ||
| 453 | ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000 | ||
| 454 | 0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>; | ||
| 455 | clock-frequency = <0x1fca055>; | ||
| 456 | interrupt-parent = <&mpic>; | ||
| 457 | interrupts = <16 2>; | ||
| 458 | |||
| 459 | interrupt-map-mask = <0xf800 0 0 7>; | ||
| 460 | interrupt-map = < | ||
| 461 | /* IDSEL 0x0 */ | ||
| 462 | 0000 0 0 1 &mpic 40 1 | ||
| 463 | 0000 0 0 2 &mpic 1 1 | ||
| 464 | 0000 0 0 3 &mpic 2 1 | ||
| 465 | 0000 0 0 4 &mpic 3 1 | ||
| 466 | >; | ||
| 467 | pcie@0 { | ||
| 468 | reg = <0 0 0 0 0>; | ||
| 469 | #size-cells = <2>; | ||
| 470 | #address-cells = <3>; | ||
| 471 | device_type = "pci"; | ||
| 472 | ranges = <0x02000000 0 0xe0000000 | ||
| 473 | 0x02000000 0 0xe0000000 | ||
| 474 | 0 0x20000000 | ||
| 475 | |||
| 476 | 0x01000000 0 0x00000000 | ||
| 477 | 0x01000000 0 0x00000000 | ||
| 478 | 0 0x00010000>; | ||
| 479 | }; | ||
| 480 | }; | ||
| 481 | |||
| 482 | pci1: pcie@ffe201000 { | ||
| 483 | compatible = "fsl,p4080-pcie"; | ||
| 484 | device_type = "pci"; | ||
| 485 | #interrupt-cells = <1>; | ||
| 486 | #size-cells = <2>; | ||
| 487 | #address-cells = <3>; | ||
| 488 | reg = <0xf 0xfe201000 0 0x1000>; | ||
| 489 | bus-range = <0 0xff>; | ||
| 490 | ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000 | ||
| 491 | 0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>; | ||
| 492 | clock-frequency = <0x1fca055>; | ||
| 493 | interrupt-parent = <&mpic>; | ||
| 494 | interrupts = <16 2>; | ||
| 495 | interrupt-map-mask = <0xf800 0 0 7>; | ||
| 496 | interrupt-map = < | ||
| 497 | /* IDSEL 0x0 */ | ||
| 498 | 0000 0 0 1 &mpic 41 1 | ||
| 499 | 0000 0 0 2 &mpic 5 1 | ||
| 500 | 0000 0 0 3 &mpic 6 1 | ||
| 501 | 0000 0 0 4 &mpic 7 1 | ||
| 502 | >; | ||
| 503 | pcie@0 { | ||
| 504 | reg = <0 0 0 0 0>; | ||
| 505 | #size-cells = <2>; | ||
| 506 | #address-cells = <3>; | ||
| 507 | device_type = "pci"; | ||
| 508 | ranges = <0x02000000 0 0xe0000000 | ||
| 509 | 0x02000000 0 0xe0000000 | ||
| 510 | 0 0x20000000 | ||
| 511 | |||
| 512 | 0x01000000 0 0x00000000 | ||
| 513 | 0x01000000 0 0x00000000 | ||
| 514 | 0 0x00010000>; | ||
| 515 | }; | ||
| 516 | }; | ||
| 517 | |||
| 518 | pci2: pcie@ffe202000 { | ||
| 519 | compatible = "fsl,p4080-pcie"; | ||
| 520 | device_type = "pci"; | ||
| 521 | #interrupt-cells = <1>; | ||
| 522 | #size-cells = <2>; | ||
| 523 | #address-cells = <3>; | ||
| 524 | reg = <0xf 0xfe202000 0 0x1000>; | ||
| 525 | bus-range = <0x0 0xff>; | ||
| 526 | ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000 | ||
| 527 | 0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>; | ||
| 528 | clock-frequency = <0x1fca055>; | ||
| 529 | interrupt-parent = <&mpic>; | ||
| 530 | interrupts = <16 2>; | ||
| 531 | interrupt-map-mask = <0xf800 0 0 7>; | ||
| 532 | interrupt-map = < | ||
| 533 | /* IDSEL 0x0 */ | ||
| 534 | 0000 0 0 1 &mpic 42 1 | ||
| 535 | 0000 0 0 2 &mpic 9 1 | ||
| 536 | 0000 0 0 3 &mpic 10 1 | ||
| 537 | 0000 0 0 4 &mpic 11 1 | ||
| 538 | >; | ||
| 539 | pcie@0 { | ||
| 540 | reg = <0 0 0 0 0>; | ||
| 541 | #size-cells = <2>; | ||
| 542 | #address-cells = <3>; | ||
| 543 | device_type = "pci"; | ||
| 544 | ranges = <0x02000000 0 0xe0000000 | ||
| 545 | 0x02000000 0 0xe0000000 | ||
| 546 | 0 0x20000000 | ||
| 547 | |||
| 548 | 0x01000000 0 0x00000000 | ||
| 549 | 0x01000000 0 0x00000000 | ||
| 550 | 0 0x00010000>; | ||
| 551 | }; | ||
| 552 | }; | ||
| 553 | |||
| 554 | }; | ||
diff --git a/arch/powerpc/boot/dts/redwood.dts b/arch/powerpc/boot/dts/redwood.dts index ad402c488741..d2af32e2bf7a 100644 --- a/arch/powerpc/boot/dts/redwood.dts +++ b/arch/powerpc/boot/dts/redwood.dts | |||
| @@ -226,6 +226,7 @@ | |||
| 226 | max-frame-size = <9000>; | 226 | max-frame-size = <9000>; |
| 227 | rx-fifo-size = <4096>; | 227 | rx-fifo-size = <4096>; |
| 228 | tx-fifo-size = <2048>; | 228 | tx-fifo-size = <2048>; |
| 229 | rx-fifo-size-gige = <16384>; | ||
| 229 | phy-mode = "rgmii"; | 230 | phy-mode = "rgmii"; |
| 230 | phy-map = <0x00000000>; | 231 | phy-map = <0x00000000>; |
| 231 | rgmii-device = <&RGMII0>; | 232 | rgmii-device = <&RGMII0>; |
diff --git a/arch/powerpc/boot/dts/warp.dts b/arch/powerpc/boot/dts/warp.dts index 31605ee4afb6..e576ee85c42f 100644 --- a/arch/powerpc/boot/dts/warp.dts +++ b/arch/powerpc/boot/dts/warp.dts | |||
| @@ -146,7 +146,7 @@ | |||
| 146 | 146 | ||
| 147 | fpga@2,4000 { | 147 | fpga@2,4000 { |
| 148 | compatible = "pika,fpga-sd"; | 148 | compatible = "pika,fpga-sd"; |
| 149 | reg = <0x00000002 0x00004000 0x00000A00>; | 149 | reg = <0x00000002 0x00004000 0x00004000>; |
| 150 | }; | 150 | }; |
| 151 | 151 | ||
| 152 | nor@0,0 { | 152 | nor@0,0 { |
diff --git a/arch/powerpc/boot/dts/wii.dts b/arch/powerpc/boot/dts/wii.dts new file mode 100644 index 000000000000..77528c9a8dbd --- /dev/null +++ b/arch/powerpc/boot/dts/wii.dts | |||
| @@ -0,0 +1,218 @@ | |||
| 1 | /* | ||
| 2 | * arch/powerpc/boot/dts/wii.dts | ||
| 3 | * | ||
| 4 | * Nintendo Wii platform device tree source | ||
| 5 | * Copyright (C) 2008-2009 The GameCube Linux Team | ||
| 6 | * Copyright (C) 2008,2009 Albert Herranz | ||
| 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 | ||
| 10 | * as published by the Free Software Foundation; either version 2 | ||
| 11 | * of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | /dts-v1/; | ||
| 16 | |||
| 17 | /* | ||
| 18 | * This is commented-out for now. | ||
| 19 | * Until a later patch is merged, the kernel can use only the first | ||
| 20 | * contiguous RAM range and will BUG() if the memreserve is outside | ||
| 21 | * that range. | ||
| 22 | */ | ||
| 23 | /*/memreserve/ 0x10000000 0x0004000;*/ /* DSP RAM */ | ||
| 24 | |||
| 25 | / { | ||
| 26 | model = "nintendo,wii"; | ||
| 27 | compatible = "nintendo,wii"; | ||
| 28 | #address-cells = <1>; | ||
| 29 | #size-cells = <1>; | ||
| 30 | |||
| 31 | chosen { | ||
| 32 | bootargs = "root=/dev/mmcblk0p2 rootwait udbg-immortal"; | ||
| 33 | }; | ||
| 34 | |||
| 35 | memory { | ||
| 36 | device_type = "memory"; | ||
| 37 | reg = <0x00000000 0x01800000 /* MEM1 24MB 1T-SRAM */ | ||
| 38 | 0x10000000 0x04000000>; /* MEM2 64MB GDDR3 */ | ||
| 39 | }; | ||
| 40 | |||
| 41 | cpus { | ||
| 42 | #address-cells = <1>; | ||
| 43 | #size-cells = <0>; | ||
| 44 | |||
| 45 | PowerPC,broadway@0 { | ||
| 46 | device_type = "cpu"; | ||
| 47 | reg = <0>; | ||
| 48 | clock-frequency = <729000000>; /* 729MHz */ | ||
| 49 | bus-frequency = <243000000>; /* 243MHz core-to-bus 3x */ | ||
| 50 | timebase-frequency = <60750000>; /* 243MHz / 4 */ | ||
| 51 | i-cache-line-size = <32>; | ||
| 52 | d-cache-line-size = <32>; | ||
| 53 | i-cache-size = <32768>; | ||
| 54 | d-cache-size = <32768>; | ||
| 55 | }; | ||
| 56 | }; | ||
| 57 | |||
| 58 | /* devices contained in the hollywood chipset */ | ||
| 59 | hollywood { | ||
| 60 | #address-cells = <1>; | ||
| 61 | #size-cells = <1>; | ||
| 62 | compatible = "nintendo,hollywood"; | ||
| 63 | ranges = <0x0c000000 0x0c000000 0x01000000 | ||
| 64 | 0x0d000000 0x0d000000 0x00800000 | ||
| 65 | 0x0d800000 0x0d800000 0x00800000>; | ||
| 66 | interrupt-parent = <&PIC0>; | ||
| 67 | |||
| 68 | video@0c002000 { | ||
| 69 | compatible = "nintendo,hollywood-vi", | ||
| 70 | "nintendo,flipper-vi"; | ||
| 71 | reg = <0x0c002000 0x100>; | ||
| 72 | interrupts = <8>; | ||
| 73 | }; | ||
| 74 | |||
| 75 | processor-interface@0c003000 { | ||
| 76 | compatible = "nintendo,hollywood-pi", | ||
| 77 | "nintendo,flipper-pi"; | ||
| 78 | reg = <0x0c003000 0x100>; | ||
| 79 | |||
| 80 | PIC0: pic0 { | ||
| 81 | #interrupt-cells = <1>; | ||
| 82 | compatible = "nintendo,flipper-pic"; | ||
| 83 | interrupt-controller; | ||
| 84 | }; | ||
| 85 | }; | ||
| 86 | |||
| 87 | dsp@0c005000 { | ||
| 88 | #address-cells = <1>; | ||
| 89 | #size-cells = <1>; | ||
| 90 | compatible = "nintendo,hollywood-dsp", | ||
| 91 | "nintendo,flipper-dsp"; | ||
| 92 | reg = <0x0c005000 0x200>; | ||
| 93 | interrupts = <6>; | ||
| 94 | }; | ||
| 95 | |||
| 96 | gamepad-controller@0d006400 { | ||
| 97 | compatible = "nintendo,hollywood-si", | ||
| 98 | "nintendo,flipper-si"; | ||
| 99 | reg = <0x0d006400 0x100>; | ||
| 100 | interrupts = <3>; | ||
| 101 | }; | ||
| 102 | |||
| 103 | audio@0c006c00 { | ||
| 104 | compatible = "nintendo,hollywood-ai", | ||
| 105 | "nintendo,flipper-ai"; | ||
| 106 | reg = <0x0d006c00 0x20>; | ||
| 107 | interrupts = <6>; | ||
| 108 | }; | ||
| 109 | |||
| 110 | /* External Interface bus */ | ||
| 111 | exi@0d006800 { | ||
| 112 | compatible = "nintendo,hollywood-exi", | ||
| 113 | "nintendo,flipper-exi"; | ||
| 114 | reg = <0x0d006800 0x40>; | ||
| 115 | virtual-reg = <0x0d006800>; | ||
| 116 | interrupts = <4>; | ||
| 117 | }; | ||
| 118 | |||
| 119 | usb@0d040000 { | ||
| 120 | compatible = "nintendo,hollywood-usb-ehci", | ||
| 121 | "usb-ehci"; | ||
| 122 | reg = <0x0d040000 0x100>; | ||
| 123 | interrupts = <4>; | ||
| 124 | interrupt-parent = <&PIC1>; | ||
| 125 | }; | ||
| 126 | |||
| 127 | usb@0d050000 { | ||
| 128 | compatible = "nintendo,hollywood-usb-ohci", | ||
| 129 | "usb-ohci"; | ||
| 130 | reg = <0x0d050000 0x100>; | ||
| 131 | interrupts = <5>; | ||
| 132 | interrupt-parent = <&PIC1>; | ||
| 133 | }; | ||
| 134 | |||
| 135 | usb@0d060000 { | ||
| 136 | compatible = "nintendo,hollywood-usb-ohci", | ||
| 137 | "usb-ohci"; | ||
| 138 | reg = <0x0d060000 0x100>; | ||
| 139 | interrupts = <6>; | ||
| 140 | interrupt-parent = <&PIC1>; | ||
| 141 | }; | ||
| 142 | |||
| 143 | sd@0d070000 { | ||
| 144 | compatible = "nintendo,hollywood-sdhci", | ||
| 145 | "sdhci"; | ||
| 146 | reg = <0x0d070000 0x200>; | ||
| 147 | interrupts = <7>; | ||
| 148 | interrupt-parent = <&PIC1>; | ||
| 149 | }; | ||
| 150 | |||
| 151 | sdio@0d080000 { | ||
| 152 | compatible = "nintendo,hollywood-sdhci", | ||
| 153 | "sdhci"; | ||
| 154 | reg = <0x0d080000 0x200>; | ||
| 155 | interrupts = <8>; | ||
| 156 | interrupt-parent = <&PIC1>; | ||
| 157 | }; | ||
| 158 | |||
| 159 | ipc@0d000000 { | ||
| 160 | compatible = "nintendo,hollywood-ipc"; | ||
| 161 | reg = <0x0d000000 0x10>; | ||
| 162 | interrupts = <30>; | ||
| 163 | interrupt-parent = <&PIC1>; | ||
| 164 | }; | ||
| 165 | |||
| 166 | PIC1: pic1@0d800030 { | ||
| 167 | #interrupt-cells = <1>; | ||
| 168 | compatible = "nintendo,hollywood-pic"; | ||
| 169 | reg = <0x0d800030 0x10>; | ||
| 170 | interrupt-controller; | ||
| 171 | interrupts = <14>; | ||
| 172 | }; | ||
| 173 | |||
| 174 | GPIO: gpio@0d8000c0 { | ||
| 175 | #gpio-cells = <2>; | ||
| 176 | compatible = "nintendo,hollywood-gpio"; | ||
| 177 | reg = <0x0d8000c0 0x40>; | ||
| 178 | gpio-controller; | ||
| 179 | |||
| 180 | /* | ||
| 181 | * This is commented out while a standard binding | ||
| 182 | * for i2c over gpio is defined. | ||
| 183 | */ | ||
| 184 | /* | ||
| 185 | i2c-video { | ||
| 186 | #address-cells = <1>; | ||
| 187 | #size-cells = <0>; | ||
| 188 | compatible = "i2c-gpio"; | ||
| 189 | |||
| 190 | gpios = <&GPIO 15 0 | ||
| 191 | &GPIO 14 0>; | ||
| 192 | clock-frequency = <250000>; | ||
| 193 | no-clock-stretching; | ||
| 194 | scl-is-open-drain; | ||
| 195 | sda-is-open-drain; | ||
| 196 | sda-enforce-dir; | ||
| 197 | |||
| 198 | AVE: audio-video-encoder@70 { | ||
| 199 | compatible = "nintendo,wii-audio-video-encoder"; | ||
| 200 | reg = <0x70>; | ||
| 201 | }; | ||
| 202 | }; | ||
| 203 | */ | ||
| 204 | }; | ||
| 205 | |||
| 206 | control@0d800100 { | ||
| 207 | compatible = "nintendo,hollywood-control"; | ||
| 208 | reg = <0x0d800100 0x300>; | ||
| 209 | }; | ||
| 210 | |||
| 211 | disk@0d806000 { | ||
| 212 | compatible = "nintendo,hollywood-di"; | ||
| 213 | reg = <0x0d806000 0x40>; | ||
| 214 | interrupts = <2>; | ||
| 215 | }; | ||
| 216 | }; | ||
| 217 | }; | ||
| 218 | |||
diff --git a/arch/powerpc/boot/dts/yosemite.dts b/arch/powerpc/boot/dts/yosemite.dts index 1fa3cb4c4ebb..64923245f0e5 100644 --- a/arch/powerpc/boot/dts/yosemite.dts +++ b/arch/powerpc/boot/dts/yosemite.dts | |||
| @@ -282,20 +282,10 @@ | |||
| 282 | /* Inbound 2GB range starting at 0 */ | 282 | /* Inbound 2GB range starting at 0 */ |
| 283 | dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>; | 283 | dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>; |
| 284 | 284 | ||
| 285 | /* Bamboo has all 4 IRQ pins tied together per slot */ | ||
| 286 | interrupt-map-mask = <0xf800 0x0 0x0 0x0>; | 285 | interrupt-map-mask = <0xf800 0x0 0x0 0x0>; |
| 287 | interrupt-map = < | 286 | interrupt-map = < |
| 288 | /* IDSEL 1 */ | 287 | /* IDSEL 12 */ |
| 289 | 0x800 0x0 0x0 0x0 &UIC0 0x1c 0x8 | 288 | 0x6000 0x0 0x0 0x0 &UIC0 0x19 0x8 |
| 290 | |||
| 291 | /* IDSEL 2 */ | ||
| 292 | 0x1000 0x0 0x0 0x0 &UIC0 0x1b 0x8 | ||
| 293 | |||
| 294 | /* IDSEL 3 */ | ||
| 295 | 0x1800 0x0 0x0 0x0 &UIC0 0x1a 0x8 | ||
| 296 | |||
| 297 | /* IDSEL 4 */ | ||
| 298 | 0x2000 0x0 0x0 0x0 &UIC0 0x19 0x8 | ||
| 299 | >; | 289 | >; |
| 300 | }; | 290 | }; |
| 301 | }; | 291 | }; |
diff --git a/arch/powerpc/boot/gamecube-head.S b/arch/powerpc/boot/gamecube-head.S new file mode 100644 index 000000000000..65a9b2a3bf33 --- /dev/null +++ b/arch/powerpc/boot/gamecube-head.S | |||
| @@ -0,0 +1,111 @@ | |||
| 1 | /* | ||
| 2 | * arch/powerpc/boot/gamecube-head.S | ||
| 3 | * | ||
| 4 | * Nintendo GameCube bootwrapper entry. | ||
| 5 | * Copyright (C) 2004-2009 The GameCube Linux Team | ||
| 6 | * Copyright (C) 2008,2009 Albert Herranz | ||
| 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 | ||
| 10 | * as published by the Free Software Foundation; either version 2 | ||
| 11 | * of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include "ppc_asm.h" | ||
| 16 | |||
| 17 | /* | ||
| 18 | * The entry code does no assumptions regarding: | ||
| 19 | * - if the data and instruction caches are enabled or not | ||
| 20 | * - if the MMU is enabled or not | ||
| 21 | * | ||
| 22 | * We enable the caches if not already enabled, enable the MMU with an | ||
| 23 | * identity mapping scheme and jump to the start code. | ||
| 24 | */ | ||
| 25 | |||
| 26 | .text | ||
| 27 | |||
| 28 | .globl _zimage_start | ||
| 29 | _zimage_start: | ||
| 30 | |||
| 31 | /* turn the MMU off */ | ||
| 32 | mfmsr 9 | ||
| 33 | rlwinm 9, 9, 0, ~((1<<4)|(1<<5)) /* MSR_DR|MSR_IR */ | ||
| 34 | bcl 20, 31, 1f | ||
| 35 | 1: | ||
| 36 | mflr 8 | ||
| 37 | clrlwi 8, 8, 3 /* convert to a real address */ | ||
| 38 | addi 8, 8, _mmu_off - 1b | ||
| 39 | mtsrr0 8 | ||
| 40 | mtsrr1 9 | ||
| 41 | rfi | ||
| 42 | _mmu_off: | ||
| 43 | /* MMU disabled */ | ||
| 44 | |||
| 45 | /* setup BATs */ | ||
| 46 | isync | ||
| 47 | li 8, 0 | ||
| 48 | mtspr 0x210, 8 /* IBAT0U */ | ||
| 49 | mtspr 0x212, 8 /* IBAT1U */ | ||
| 50 | mtspr 0x214, 8 /* IBAT2U */ | ||
| 51 | mtspr 0x216, 8 /* IBAT3U */ | ||
| 52 | mtspr 0x218, 8 /* DBAT0U */ | ||
| 53 | mtspr 0x21a, 8 /* DBAT1U */ | ||
| 54 | mtspr 0x21c, 8 /* DBAT2U */ | ||
| 55 | mtspr 0x21e, 8 /* DBAT3U */ | ||
| 56 | |||
| 57 | li 8, 0x01ff /* first 16MiB */ | ||
| 58 | li 9, 0x0002 /* rw */ | ||
| 59 | mtspr 0x211, 9 /* IBAT0L */ | ||
| 60 | mtspr 0x210, 8 /* IBAT0U */ | ||
| 61 | mtspr 0x219, 9 /* DBAT0L */ | ||
| 62 | mtspr 0x218, 8 /* DBAT0U */ | ||
| 63 | |||
| 64 | lis 8, 0x0c00 /* I/O mem */ | ||
| 65 | ori 8, 8, 0x3ff /* 32MiB */ | ||
| 66 | lis 9, 0x0c00 | ||
| 67 | ori 9, 9, 0x002a /* uncached, guarded, rw */ | ||
| 68 | mtspr 0x21b, 9 /* DBAT1L */ | ||
| 69 | mtspr 0x21a, 8 /* DBAT1U */ | ||
| 70 | |||
| 71 | lis 8, 0x0100 /* next 8MiB */ | ||
| 72 | ori 8, 8, 0x00ff /* 8MiB */ | ||
| 73 | lis 9, 0x0100 | ||
| 74 | ori 9, 9, 0x0002 /* rw */ | ||
| 75 | mtspr 0x215, 9 /* IBAT2L */ | ||
| 76 | mtspr 0x214, 8 /* IBAT2U */ | ||
| 77 | mtspr 0x21d, 9 /* DBAT2L */ | ||
| 78 | mtspr 0x21c, 8 /* DBAT2U */ | ||
| 79 | |||
| 80 | /* enable and invalidate the caches if not already enabled */ | ||
| 81 | mfspr 8, 0x3f0 /* HID0 */ | ||
| 82 | andi. 0, 8, (1<<15) /* HID0_ICE */ | ||
| 83 | bne 1f | ||
| 84 | ori 8, 8, (1<<15)|(1<<11) /* HID0_ICE|HID0_ICFI*/ | ||
| 85 | 1: | ||
| 86 | andi. 0, 8, (1<<14) /* HID0_DCE */ | ||
| 87 | bne 1f | ||
| 88 | ori 8, 8, (1<<14)|(1<<10) /* HID0_DCE|HID0_DCFI*/ | ||
| 89 | 1: | ||
| 90 | mtspr 0x3f0, 8 /* HID0 */ | ||
| 91 | isync | ||
| 92 | |||
| 93 | /* initialize arguments */ | ||
| 94 | li 3, 0 | ||
| 95 | li 4, 0 | ||
| 96 | li 5, 0 | ||
| 97 | |||
| 98 | /* turn the MMU on */ | ||
| 99 | bcl 20, 31, 1f | ||
| 100 | 1: | ||
| 101 | mflr 8 | ||
| 102 | addi 8, 8, _mmu_on - 1b | ||
| 103 | mfmsr 9 | ||
| 104 | ori 9, 9, (1<<4)|(1<<5) /* MSR_DR|MSR_IR */ | ||
| 105 | mtsrr0 8 | ||
| 106 | mtsrr1 9 | ||
| 107 | sync | ||
| 108 | rfi | ||
| 109 | _mmu_on: | ||
| 110 | b _zimage_start_lib | ||
| 111 | |||
diff --git a/arch/powerpc/boot/gamecube.c b/arch/powerpc/boot/gamecube.c new file mode 100644 index 000000000000..28ae7057be5e --- /dev/null +++ b/arch/powerpc/boot/gamecube.c | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | /* | ||
| 2 | * arch/powerpc/boot/gamecube.c | ||
| 3 | * | ||
| 4 | * Nintendo GameCube bootwrapper support | ||
| 5 | * Copyright (C) 2004-2009 The GameCube Linux Team | ||
| 6 | * Copyright (C) 2008,2009 Albert Herranz | ||
| 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 | ||
| 10 | * as published by the Free Software Foundation; either version 2 | ||
| 11 | * of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <stddef.h> | ||
| 16 | #include "stdio.h" | ||
| 17 | #include "types.h" | ||
| 18 | #include "io.h" | ||
| 19 | #include "ops.h" | ||
| 20 | |||
| 21 | #include "ugecon.h" | ||
| 22 | |||
| 23 | BSS_STACK(8192); | ||
| 24 | |||
| 25 | void platform_init(unsigned long r3, unsigned long r4, unsigned long r5) | ||
| 26 | { | ||
| 27 | u32 heapsize = 16*1024*1024 - (u32)_end; | ||
| 28 | |||
| 29 | simple_alloc_init(_end, heapsize, 32, 64); | ||
| 30 | fdt_init(_dtb_start); | ||
| 31 | |||
| 32 | if (ug_probe()) | ||
| 33 | console_ops.write = ug_console_write; | ||
| 34 | } | ||
| 35 | |||
diff --git a/arch/powerpc/boot/ugecon.c b/arch/powerpc/boot/ugecon.c new file mode 100644 index 000000000000..8f2a6b311534 --- /dev/null +++ b/arch/powerpc/boot/ugecon.c | |||
| @@ -0,0 +1,147 @@ | |||
| 1 | /* | ||
| 2 | * arch/powerpc/boot/ugecon.c | ||
| 3 | * | ||
| 4 | * USB Gecko bootwrapper console. | ||
| 5 | * Copyright (C) 2008-2009 The GameCube Linux Team | ||
| 6 | * Copyright (C) 2008,2009 Albert Herranz | ||
| 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 | ||
| 10 | * as published by the Free Software Foundation; either version 2 | ||
| 11 | * of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <stddef.h> | ||
| 16 | #include "stdio.h" | ||
| 17 | #include "types.h" | ||
| 18 | #include "io.h" | ||
| 19 | #include "ops.h" | ||
| 20 | |||
| 21 | |||
| 22 | #define EXI_CLK_32MHZ 5 | ||
| 23 | |||
| 24 | #define EXI_CSR 0x00 | ||
| 25 | #define EXI_CSR_CLKMASK (0x7<<4) | ||
| 26 | #define EXI_CSR_CLK_32MHZ (EXI_CLK_32MHZ<<4) | ||
| 27 | #define EXI_CSR_CSMASK (0x7<<7) | ||
| 28 | #define EXI_CSR_CS_0 (0x1<<7) /* Chip Select 001 */ | ||
| 29 | |||
| 30 | #define EXI_CR 0x0c | ||
| 31 | #define EXI_CR_TSTART (1<<0) | ||
| 32 | #define EXI_CR_WRITE (1<<2) | ||
| 33 | #define EXI_CR_READ_WRITE (2<<2) | ||
| 34 | #define EXI_CR_TLEN(len) (((len)-1)<<4) | ||
| 35 | |||
| 36 | #define EXI_DATA 0x10 | ||
| 37 | |||
| 38 | |||
| 39 | /* virtual address base for input/output, retrieved from device tree */ | ||
| 40 | static void *ug_io_base; | ||
| 41 | |||
| 42 | |||
| 43 | static u32 ug_io_transaction(u32 in) | ||
| 44 | { | ||
| 45 | u32 *csr_reg = ug_io_base + EXI_CSR; | ||
| 46 | u32 *data_reg = ug_io_base + EXI_DATA; | ||
| 47 | u32 *cr_reg = ug_io_base + EXI_CR; | ||
| 48 | u32 csr, data, cr; | ||
| 49 | |||
| 50 | /* select */ | ||
| 51 | csr = EXI_CSR_CLK_32MHZ | EXI_CSR_CS_0; | ||
| 52 | out_be32(csr_reg, csr); | ||
| 53 | |||
| 54 | /* read/write */ | ||
| 55 | data = in; | ||
| 56 | out_be32(data_reg, data); | ||
| 57 | cr = EXI_CR_TLEN(2) | EXI_CR_READ_WRITE | EXI_CR_TSTART; | ||
| 58 | out_be32(cr_reg, cr); | ||
| 59 | |||
| 60 | while (in_be32(cr_reg) & EXI_CR_TSTART) | ||
| 61 | barrier(); | ||
| 62 | |||
| 63 | /* deselect */ | ||
| 64 | out_be32(csr_reg, 0); | ||
| 65 | |||
| 66 | data = in_be32(data_reg); | ||
| 67 | return data; | ||
| 68 | } | ||
| 69 | |||
| 70 | static int ug_is_txfifo_ready(void) | ||
| 71 | { | ||
| 72 | return ug_io_transaction(0xc0000000) & 0x04000000; | ||
| 73 | } | ||
| 74 | |||
| 75 | static void ug_raw_putc(char ch) | ||
| 76 | { | ||
| 77 | ug_io_transaction(0xb0000000 | (ch << 20)); | ||
| 78 | } | ||
| 79 | |||
| 80 | static void ug_putc(char ch) | ||
| 81 | { | ||
| 82 | int count = 16; | ||
| 83 | |||
| 84 | if (!ug_io_base) | ||
| 85 | return; | ||
| 86 | |||
| 87 | while (!ug_is_txfifo_ready() && count--) | ||
| 88 | barrier(); | ||
| 89 | if (count >= 0) | ||
| 90 | ug_raw_putc(ch); | ||
| 91 | } | ||
| 92 | |||
| 93 | void ug_console_write(const char *buf, int len) | ||
| 94 | { | ||
| 95 | char *b = (char *)buf; | ||
| 96 | |||
| 97 | while (len--) { | ||
| 98 | if (*b == '\n') | ||
| 99 | ug_putc('\r'); | ||
| 100 | ug_putc(*b++); | ||
| 101 | } | ||
| 102 | } | ||
| 103 | |||
| 104 | static int ug_is_adapter_present(void) | ||
| 105 | { | ||
| 106 | if (!ug_io_base) | ||
| 107 | return 0; | ||
| 108 | return ug_io_transaction(0x90000000) == 0x04700000; | ||
| 109 | } | ||
| 110 | |||
| 111 | static void *ug_grab_exi_io_base(void) | ||
| 112 | { | ||
| 113 | u32 v; | ||
| 114 | void *devp; | ||
| 115 | |||
| 116 | devp = find_node_by_compatible(NULL, "nintendo,flipper-exi"); | ||
| 117 | if (devp == NULL) | ||
| 118 | goto err_out; | ||
| 119 | if (getprop(devp, "virtual-reg", &v, sizeof(v)) != sizeof(v)) | ||
| 120 | goto err_out; | ||
| 121 | |||
| 122 | return (void *)v; | ||
| 123 | |||
| 124 | err_out: | ||
| 125 | return NULL; | ||
| 126 | } | ||
| 127 | |||
| 128 | void *ug_probe(void) | ||
| 129 | { | ||
| 130 | void *exi_io_base; | ||
| 131 | int i; | ||
| 132 | |||
| 133 | exi_io_base = ug_grab_exi_io_base(); | ||
| 134 | if (!exi_io_base) | ||
| 135 | return NULL; | ||
| 136 | |||
| 137 | /* look for a usbgecko on memcard slots A and B */ | ||
| 138 | for (i = 0; i < 2; i++) { | ||
| 139 | ug_io_base = exi_io_base + 0x14 * i; | ||
| 140 | if (ug_is_adapter_present()) | ||
| 141 | break; | ||
| 142 | } | ||
| 143 | if (i == 2) | ||
| 144 | ug_io_base = NULL; | ||
| 145 | return ug_io_base; | ||
| 146 | } | ||
| 147 | |||
diff --git a/arch/powerpc/boot/ugecon.h b/arch/powerpc/boot/ugecon.h new file mode 100644 index 000000000000..43737539169b --- /dev/null +++ b/arch/powerpc/boot/ugecon.h | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | /* | ||
| 2 | * arch/powerpc/boot/ugecon.h | ||
| 3 | * | ||
| 4 | * USB Gecko early bootwrapper console. | ||
| 5 | * Copyright (C) 2008-2009 The GameCube Linux Team | ||
| 6 | * Copyright (C) 2008,2009 Albert Herranz | ||
| 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 | ||
| 10 | * as published by the Free Software Foundation; either version 2 | ||
| 11 | * of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #ifndef __UGECON_H | ||
| 16 | #define __UGECON_H | ||
| 17 | |||
| 18 | extern void *ug_probe(void); | ||
| 19 | |||
| 20 | extern void ug_putc(char ch); | ||
| 21 | extern void ug_console_write(const char *buf, int len); | ||
| 22 | |||
| 23 | #endif /* __UGECON_H */ | ||
| 24 | |||
diff --git a/arch/powerpc/boot/wii-head.S b/arch/powerpc/boot/wii-head.S new file mode 100644 index 000000000000..edd79b836fcf --- /dev/null +++ b/arch/powerpc/boot/wii-head.S | |||
| @@ -0,0 +1,142 @@ | |||
| 1 | /* | ||
| 2 | * arch/powerpc/boot/wii-head.S | ||
| 3 | * | ||
| 4 | * Nintendo Wii bootwrapper entry. | ||
| 5 | * Copyright (C) 2008-2009 The GameCube Linux Team | ||
| 6 | * Copyright (C) 2008,2009 Albert Herranz | ||
| 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 | ||
| 10 | * as published by the Free Software Foundation; either version 2 | ||
| 11 | * of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include "ppc_asm.h" | ||
| 16 | |||
| 17 | /* | ||
| 18 | * The entry code does no assumptions regarding: | ||
| 19 | * - if the data and instruction caches are enabled or not | ||
| 20 | * - if the MMU is enabled or not | ||
| 21 | * - if the high BATs are enabled or not | ||
| 22 | * | ||
| 23 | * We enable the high BATs, enable the caches if not already enabled, | ||
| 24 | * enable the MMU with an identity mapping scheme and jump to the start code. | ||
| 25 | */ | ||
| 26 | |||
| 27 | .text | ||
| 28 | |||
| 29 | .globl _zimage_start | ||
| 30 | _zimage_start: | ||
| 31 | |||
| 32 | /* turn the MMU off */ | ||
| 33 | mfmsr 9 | ||
| 34 | rlwinm 9, 9, 0, ~((1<<4)|(1<<5)) /* MSR_DR|MSR_IR */ | ||
| 35 | bcl 20, 31, 1f | ||
| 36 | 1: | ||
| 37 | mflr 8 | ||
| 38 | clrlwi 8, 8, 3 /* convert to a real address */ | ||
| 39 | addi 8, 8, _mmu_off - 1b | ||
| 40 | mtsrr0 8 | ||
| 41 | mtsrr1 9 | ||
| 42 | rfi | ||
| 43 | _mmu_off: | ||
| 44 | /* MMU disabled */ | ||
| 45 | |||
| 46 | /* setup BATs */ | ||
| 47 | isync | ||
| 48 | li 8, 0 | ||
| 49 | mtspr 0x210, 8 /* IBAT0U */ | ||
| 50 | mtspr 0x212, 8 /* IBAT1U */ | ||
| 51 | mtspr 0x214, 8 /* IBAT2U */ | ||
| 52 | mtspr 0x216, 8 /* IBAT3U */ | ||
| 53 | mtspr 0x218, 8 /* DBAT0U */ | ||
| 54 | mtspr 0x21a, 8 /* DBAT1U */ | ||
| 55 | mtspr 0x21c, 8 /* DBAT2U */ | ||
| 56 | mtspr 0x21e, 8 /* DBAT3U */ | ||
| 57 | |||
| 58 | mtspr 0x230, 8 /* IBAT4U */ | ||
| 59 | mtspr 0x232, 8 /* IBAT5U */ | ||
| 60 | mtspr 0x234, 8 /* IBAT6U */ | ||
| 61 | mtspr 0x236, 8 /* IBAT7U */ | ||
| 62 | mtspr 0x238, 8 /* DBAT4U */ | ||
| 63 | mtspr 0x23a, 8 /* DBAT5U */ | ||
| 64 | mtspr 0x23c, 8 /* DBAT6U */ | ||
| 65 | mtspr 0x23e, 8 /* DBAT7U */ | ||
| 66 | |||
| 67 | li 8, 0x01ff /* first 16MiB */ | ||
| 68 | li 9, 0x0002 /* rw */ | ||
| 69 | mtspr 0x211, 9 /* IBAT0L */ | ||
| 70 | mtspr 0x210, 8 /* IBAT0U */ | ||
| 71 | mtspr 0x219, 9 /* DBAT0L */ | ||
| 72 | mtspr 0x218, 8 /* DBAT0U */ | ||
| 73 | |||
| 74 | lis 8, 0x0c00 /* I/O mem */ | ||
| 75 | ori 8, 8, 0x3ff /* 32MiB */ | ||
| 76 | lis 9, 0x0c00 | ||
| 77 | ori 9, 9, 0x002a /* uncached, guarded, rw */ | ||
| 78 | mtspr 0x21b, 9 /* DBAT1L */ | ||
| 79 | mtspr 0x21a, 8 /* DBAT1U */ | ||
| 80 | |||
| 81 | lis 8, 0x0100 /* next 8MiB */ | ||
| 82 | ori 8, 8, 0x00ff /* 8MiB */ | ||
| 83 | lis 9, 0x0100 | ||
| 84 | ori 9, 9, 0x0002 /* rw */ | ||
| 85 | mtspr 0x215, 9 /* IBAT2L */ | ||
| 86 | mtspr 0x214, 8 /* IBAT2U */ | ||
| 87 | mtspr 0x21d, 9 /* DBAT2L */ | ||
| 88 | mtspr 0x21c, 8 /* DBAT2U */ | ||
| 89 | |||
| 90 | lis 8, 0x1000 /* MEM2 */ | ||
| 91 | ori 8, 8, 0x07ff /* 64MiB */ | ||
| 92 | lis 9, 0x1000 | ||
| 93 | ori 9, 9, 0x0002 /* rw */ | ||
| 94 | mtspr 0x216, 8 /* IBAT3U */ | ||
| 95 | mtspr 0x217, 9 /* IBAT3L */ | ||
| 96 | mtspr 0x21e, 8 /* DBAT3U */ | ||
| 97 | mtspr 0x21f, 9 /* DBAT3L */ | ||
| 98 | |||
| 99 | /* enable the high BATs */ | ||
| 100 | mfspr 8, 0x3f3 /* HID4 */ | ||
| 101 | oris 8, 8, 0x0200 | ||
| 102 | mtspr 0x3f3, 8 /* HID4 */ | ||
| 103 | |||
| 104 | /* enable and invalidate the caches if not already enabled */ | ||
| 105 | mfspr 8, 0x3f0 /* HID0 */ | ||
| 106 | andi. 0, 8, (1<<15) /* HID0_ICE */ | ||
| 107 | bne 1f | ||
| 108 | ori 8, 8, (1<<15)|(1<<11) /* HID0_ICE|HID0_ICFI*/ | ||
| 109 | 1: | ||
| 110 | andi. 0, 8, (1<<14) /* HID0_DCE */ | ||
| 111 | bne 1f | ||
| 112 | ori 8, 8, (1<<14)|(1<<10) /* HID0_DCE|HID0_DCFI*/ | ||
| 113 | 1: | ||
| 114 | mtspr 0x3f0, 8 /* HID0 */ | ||
| 115 | isync | ||
| 116 | |||
| 117 | /* initialize arguments */ | ||
| 118 | li 3, 0 | ||
| 119 | li 4, 0 | ||
| 120 | li 5, 0 | ||
| 121 | |||
| 122 | /* turn the MMU on */ | ||
| 123 | bcl 20, 31, 1f | ||
| 124 | 1: | ||
| 125 | mflr 8 | ||
| 126 | addi 8, 8, _mmu_on - 1b | ||
| 127 | mfmsr 9 | ||
| 128 | ori 9, 9, (1<<4)|(1<<5) /* MSR_DR|MSR_IR */ | ||
| 129 | mtsrr0 8 | ||
| 130 | mtsrr1 9 | ||
| 131 | sync | ||
| 132 | rfi | ||
| 133 | _mmu_on: | ||
| 134 | /* turn on the front blue led (aka: yay! we got here!) */ | ||
| 135 | lis 8, 0x0d00 | ||
| 136 | ori 8, 8, 0x00c0 | ||
| 137 | lwz 9, 0(8) | ||
| 138 | ori 9, 9, 0x20 | ||
| 139 | stw 9, 0(8) | ||
| 140 | |||
| 141 | b _zimage_start_lib | ||
| 142 | |||
diff --git a/arch/powerpc/boot/wii.c b/arch/powerpc/boot/wii.c new file mode 100644 index 000000000000..2ebaec0344dd --- /dev/null +++ b/arch/powerpc/boot/wii.c | |||
| @@ -0,0 +1,158 @@ | |||
| 1 | /* | ||
| 2 | * arch/powerpc/boot/wii.c | ||
| 3 | * | ||
| 4 | * Nintendo Wii bootwrapper support | ||
| 5 | * Copyright (C) 2008-2009 The GameCube Linux Team | ||
| 6 | * Copyright (C) 2008,2009 Albert Herranz | ||
| 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 | ||
| 10 | * as published by the Free Software Foundation; either version 2 | ||
| 11 | * of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <stddef.h> | ||
| 16 | #include "stdio.h" | ||
| 17 | #include "types.h" | ||
| 18 | #include "io.h" | ||
| 19 | #include "ops.h" | ||
| 20 | |||
| 21 | #include "ugecon.h" | ||
| 22 | |||
| 23 | BSS_STACK(8192); | ||
| 24 | |||
| 25 | #define HW_REG(x) ((void *)(x)) | ||
| 26 | |||
| 27 | #define EXI_CTRL HW_REG(0x0d800070) | ||
| 28 | #define EXI_CTRL_ENABLE (1<<0) | ||
| 29 | |||
| 30 | #define MEM2_TOP (0x10000000 + 64*1024*1024) | ||
| 31 | #define FIRMWARE_DEFAULT_SIZE (12*1024*1024) | ||
| 32 | |||
| 33 | |||
| 34 | struct mipc_infohdr { | ||
| 35 | char magic[3]; | ||
| 36 | u8 version; | ||
| 37 | u32 mem2_boundary; | ||
| 38 | u32 ipc_in; | ||
| 39 | size_t ipc_in_size; | ||
| 40 | u32 ipc_out; | ||
| 41 | size_t ipc_out_size; | ||
| 42 | }; | ||
| 43 | |||
| 44 | static int mipc_check_address(u32 pa) | ||
| 45 | { | ||
| 46 | /* only MEM2 addresses */ | ||
| 47 | if (pa < 0x10000000 || pa > 0x14000000) | ||
| 48 | return -EINVAL; | ||
| 49 | return 0; | ||
| 50 | } | ||
| 51 | |||
| 52 | static struct mipc_infohdr *mipc_get_infohdr(void) | ||
| 53 | { | ||
| 54 | struct mipc_infohdr **hdrp, *hdr; | ||
| 55 | |||
| 56 | /* 'mini' header pointer is the last word of MEM2 memory */ | ||
| 57 | hdrp = (struct mipc_infohdr **)0x13fffffc; | ||
| 58 | if (mipc_check_address((u32)hdrp)) { | ||
| 59 | printf("mini: invalid hdrp %08X\n", (u32)hdrp); | ||
| 60 | hdr = NULL; | ||
| 61 | goto out; | ||
| 62 | } | ||
| 63 | |||
| 64 | hdr = *hdrp; | ||
| 65 | if (mipc_check_address((u32)hdr)) { | ||
| 66 | printf("mini: invalid hdr %08X\n", (u32)hdr); | ||
| 67 | hdr = NULL; | ||
| 68 | goto out; | ||
| 69 | } | ||
| 70 | if (memcmp(hdr->magic, "IPC", 3)) { | ||
| 71 | printf("mini: invalid magic\n"); | ||
| 72 | hdr = NULL; | ||
| 73 | goto out; | ||
| 74 | } | ||
| 75 | |||
| 76 | out: | ||
| 77 | return hdr; | ||
| 78 | } | ||
| 79 | |||
| 80 | static int mipc_get_mem2_boundary(u32 *mem2_boundary) | ||
| 81 | { | ||
| 82 | struct mipc_infohdr *hdr; | ||
| 83 | int error; | ||
| 84 | |||
| 85 | hdr = mipc_get_infohdr(); | ||
| 86 | if (!hdr) { | ||
| 87 | error = -1; | ||
| 88 | goto out; | ||
| 89 | } | ||
| 90 | |||
| 91 | if (mipc_check_address(hdr->mem2_boundary)) { | ||
| 92 | printf("mini: invalid mem2_boundary %08X\n", | ||
| 93 | hdr->mem2_boundary); | ||
| 94 | error = -EINVAL; | ||
| 95 | goto out; | ||
| 96 | } | ||
| 97 | *mem2_boundary = hdr->mem2_boundary; | ||
| 98 | error = 0; | ||
| 99 | out: | ||
| 100 | return error; | ||
| 101 | |||
| 102 | } | ||
| 103 | |||
| 104 | static void platform_fixups(void) | ||
| 105 | { | ||
| 106 | void *mem; | ||
| 107 | u32 reg[4]; | ||
| 108 | u32 mem2_boundary; | ||
| 109 | int len; | ||
| 110 | int error; | ||
| 111 | |||
| 112 | mem = finddevice("/memory"); | ||
| 113 | if (!mem) | ||
| 114 | fatal("Can't find memory node\n"); | ||
| 115 | |||
| 116 | /* two ranges of (address, size) words */ | ||
| 117 | len = getprop(mem, "reg", reg, sizeof(reg)); | ||
| 118 | if (len != sizeof(reg)) { | ||
| 119 | /* nothing to do */ | ||
| 120 | goto out; | ||
| 121 | } | ||
| 122 | |||
| 123 | /* retrieve MEM2 boundary from 'mini' */ | ||
| 124 | error = mipc_get_mem2_boundary(&mem2_boundary); | ||
| 125 | if (error) { | ||
| 126 | /* if that fails use a sane value */ | ||
| 127 | mem2_boundary = MEM2_TOP - FIRMWARE_DEFAULT_SIZE; | ||
| 128 | } | ||
| 129 | |||
| 130 | if (mem2_boundary > reg[2] && mem2_boundary < reg[2] + reg[3]) { | ||
| 131 | reg[3] = mem2_boundary - reg[2]; | ||
| 132 | printf("top of MEM2 @ %08X\n", reg[2] + reg[3]); | ||
| 133 | setprop(mem, "reg", reg, sizeof(reg)); | ||
| 134 | } | ||
| 135 | |||
| 136 | out: | ||
| 137 | return; | ||
| 138 | } | ||
| 139 | |||
| 140 | void platform_init(unsigned long r3, unsigned long r4, unsigned long r5) | ||
| 141 | { | ||
| 142 | u32 heapsize = 24*1024*1024 - (u32)_end; | ||
| 143 | |||
| 144 | simple_alloc_init(_end, heapsize, 32, 64); | ||
| 145 | fdt_init(_dtb_start); | ||
| 146 | |||
| 147 | /* | ||
| 148 | * 'mini' boots the Broadway processor with EXI disabled. | ||
| 149 | * We need it enabled before probing for the USB Gecko. | ||
| 150 | */ | ||
| 151 | out_be32(EXI_CTRL, in_be32(EXI_CTRL) | EXI_CTRL_ENABLE); | ||
| 152 | |||
| 153 | if (ug_probe()) | ||
| 154 | console_ops.write = ug_console_write; | ||
| 155 | |||
| 156 | platform_ops.fixups = platform_fixups; | ||
| 157 | } | ||
| 158 | |||
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper index ac9e9a58b2b0..390512ae7f86 100755 --- a/arch/powerpc/boot/wrapper +++ b/arch/powerpc/boot/wrapper | |||
| @@ -230,6 +230,10 @@ xpedite52*) | |||
| 230 | link_address='0x1400000' | 230 | link_address='0x1400000' |
| 231 | platformo=$object/cuboot-85xx.o | 231 | platformo=$object/cuboot-85xx.o |
| 232 | ;; | 232 | ;; |
| 233 | gamecube|wii) | ||
| 234 | link_address='0x600000' | ||
| 235 | platformo="$object/$platform-head.o $object/$platform.o" | ||
| 236 | ;; | ||
| 233 | esac | 237 | esac |
| 234 | 238 | ||
| 235 | vmz="$tmpdir/`basename \"$kernel\"`.$ext" | 239 | vmz="$tmpdir/`basename \"$kernel\"`.$ext" |
diff --git a/arch/powerpc/configs/86xx/gef_ppc9a_defconfig b/arch/powerpc/configs/86xx/gef_ppc9a_defconfig index 28980738776c..6cd2cd65c2cd 100644 --- a/arch/powerpc/configs/86xx/gef_ppc9a_defconfig +++ b/arch/powerpc/configs/86xx/gef_ppc9a_defconfig | |||
| @@ -218,7 +218,7 @@ CONFIG_MPIC=y | |||
| 218 | # CONFIG_MPIC_WEIRD is not set | 218 | # CONFIG_MPIC_WEIRD is not set |
| 219 | # CONFIG_PPC_I8259 is not set | 219 | # CONFIG_PPC_I8259 is not set |
| 220 | # CONFIG_PPC_RTAS is not set | 220 | # CONFIG_PPC_RTAS is not set |
| 221 | # CONFIG_MMIO_NVRAM is not set | 221 | CONFIG_MMIO_NVRAM=y |
| 222 | # CONFIG_PPC_MPC106 is not set | 222 | # CONFIG_PPC_MPC106 is not set |
| 223 | # CONFIG_PPC_970_NAP is not set | 223 | # CONFIG_PPC_970_NAP is not set |
| 224 | # CONFIG_PPC_INDIRECT_IO is not set | 224 | # CONFIG_PPC_INDIRECT_IO is not set |
diff --git a/arch/powerpc/configs/86xx/gef_sbc310_defconfig b/arch/powerpc/configs/86xx/gef_sbc310_defconfig index e199d1cacbaf..a6a3768f7304 100644 --- a/arch/powerpc/configs/86xx/gef_sbc310_defconfig +++ b/arch/powerpc/configs/86xx/gef_sbc310_defconfig | |||
| @@ -218,7 +218,7 @@ CONFIG_MPIC=y | |||
| 218 | # CONFIG_MPIC_WEIRD is not set | 218 | # CONFIG_MPIC_WEIRD is not set |
| 219 | # CONFIG_PPC_I8259 is not set | 219 | # CONFIG_PPC_I8259 is not set |
| 220 | # CONFIG_PPC_RTAS is not set | 220 | # CONFIG_PPC_RTAS is not set |
| 221 | # CONFIG_MMIO_NVRAM is not set | 221 | CONFIG_MMIO_NVRAM=y |
| 222 | # CONFIG_PPC_MPC106 is not set | 222 | # CONFIG_PPC_MPC106 is not set |
| 223 | # CONFIG_PPC_970_NAP is not set | 223 | # CONFIG_PPC_970_NAP is not set |
| 224 | # CONFIG_PPC_INDIRECT_IO is not set | 224 | # CONFIG_PPC_INDIRECT_IO is not set |
diff --git a/arch/powerpc/configs/86xx/gef_sbc610_defconfig b/arch/powerpc/configs/86xx/gef_sbc610_defconfig index 3b0fbfb28efd..1975d41e0763 100644 --- a/arch/powerpc/configs/86xx/gef_sbc610_defconfig +++ b/arch/powerpc/configs/86xx/gef_sbc610_defconfig | |||
| @@ -219,7 +219,7 @@ CONFIG_MPIC=y | |||
| 219 | # CONFIG_MPIC_WEIRD is not set | 219 | # CONFIG_MPIC_WEIRD is not set |
| 220 | # CONFIG_PPC_I8259 is not set | 220 | # CONFIG_PPC_I8259 is not set |
| 221 | # CONFIG_PPC_RTAS is not set | 221 | # CONFIG_PPC_RTAS is not set |
| 222 | # CONFIG_MMIO_NVRAM is not set | 222 | CONFIG_MMIO_NVRAM=y |
| 223 | # CONFIG_PPC_MPC106 is not set | 223 | # CONFIG_PPC_MPC106 is not set |
| 224 | # CONFIG_PPC_970_NAP is not set | 224 | # CONFIG_PPC_970_NAP is not set |
| 225 | # CONFIG_PPC_INDIRECT_IO is not set | 225 | # CONFIG_PPC_INDIRECT_IO is not set |
| @@ -1124,7 +1124,7 @@ CONFIG_UNIX98_PTYS=y | |||
| 1124 | # CONFIG_IPMI_HANDLER is not set | 1124 | # CONFIG_IPMI_HANDLER is not set |
| 1125 | CONFIG_HW_RANDOM=y | 1125 | CONFIG_HW_RANDOM=y |
| 1126 | # CONFIG_HW_RANDOM_TIMERIOMEM is not set | 1126 | # CONFIG_HW_RANDOM_TIMERIOMEM is not set |
| 1127 | # CONFIG_NVRAM is not set | 1127 | CONFIG_NVRAM=y |
| 1128 | # CONFIG_R3964 is not set | 1128 | # CONFIG_R3964 is not set |
| 1129 | # CONFIG_APPLICOM is not set | 1129 | # CONFIG_APPLICOM is not set |
| 1130 | # CONFIG_RAW_DRIVER is not set | 1130 | # CONFIG_RAW_DRIVER is not set |
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig index fc905924c022..826a65d3f002 100644 --- a/arch/powerpc/configs/g5_defconfig +++ b/arch/powerpc/configs/g5_defconfig | |||
| @@ -757,7 +757,7 @@ CONFIG_SUNGEM=y | |||
| 757 | # CONFIG_B44 is not set | 757 | # CONFIG_B44 is not set |
| 758 | # CONFIG_ATL2 is not set | 758 | # CONFIG_ATL2 is not set |
| 759 | CONFIG_NETDEV_1000=y | 759 | CONFIG_NETDEV_1000=y |
| 760 | CONFIG_ACENIC=y | 760 | CONFIG_ACENIC=m |
| 761 | CONFIG_ACENIC_OMIT_TIGON_I=y | 761 | CONFIG_ACENIC_OMIT_TIGON_I=y |
| 762 | # CONFIG_DL2K is not set | 762 | # CONFIG_DL2K is not set |
| 763 | CONFIG_E1000=y | 763 | CONFIG_E1000=y |
| @@ -794,8 +794,8 @@ CONFIG_NETDEV_10000=y | |||
| 794 | # CONFIG_BNX2X is not set | 794 | # CONFIG_BNX2X is not set |
| 795 | # CONFIG_QLGE is not set | 795 | # CONFIG_QLGE is not set |
| 796 | # CONFIG_SFC is not set | 796 | # CONFIG_SFC is not set |
| 797 | CONFIG_TR=y | 797 | # CONFIG_TR is not set |
| 798 | CONFIG_IBMOL=y | 798 | # CONFIG_IBMOL is not set |
| 799 | # CONFIG_3C359 is not set | 799 | # CONFIG_3C359 is not set |
| 800 | # CONFIG_TMS380TR is not set | 800 | # CONFIG_TMS380TR is not set |
| 801 | 801 | ||
diff --git a/arch/powerpc/configs/gamecube_defconfig b/arch/powerpc/configs/gamecube_defconfig new file mode 100644 index 000000000000..942e1193e9e4 --- /dev/null +++ b/arch/powerpc/configs/gamecube_defconfig | |||
| @@ -0,0 +1,1061 @@ | |||
| 1 | # | ||
| 2 | # Automatically generated make config: don't edit | ||
| 3 | # Linux kernel version: 2.6.32-rc8 | ||
| 4 | # Sun Nov 22 21:07:30 2009 | ||
| 5 | # | ||
| 6 | # CONFIG_PPC64 is not set | ||
| 7 | |||
| 8 | # | ||
| 9 | # Processor support | ||
| 10 | # | ||
| 11 | CONFIG_PPC_BOOK3S_32=y | ||
| 12 | # CONFIG_PPC_85xx is not set | ||
| 13 | # CONFIG_PPC_8xx is not set | ||
| 14 | # CONFIG_40x is not set | ||
| 15 | # CONFIG_44x is not set | ||
| 16 | # CONFIG_E200 is not set | ||
| 17 | CONFIG_PPC_BOOK3S=y | ||
| 18 | CONFIG_6xx=y | ||
| 19 | CONFIG_PPC_FPU=y | ||
| 20 | # CONFIG_ALTIVEC is not set | ||
| 21 | CONFIG_PPC_STD_MMU=y | ||
| 22 | CONFIG_PPC_STD_MMU_32=y | ||
| 23 | # CONFIG_PPC_MM_SLICES is not set | ||
| 24 | CONFIG_PPC_HAVE_PMU_SUPPORT=y | ||
| 25 | CONFIG_PPC_PERF_CTRS=y | ||
| 26 | # CONFIG_SMP is not set | ||
| 27 | CONFIG_NOT_COHERENT_CACHE=y | ||
| 28 | CONFIG_PPC32=y | ||
| 29 | CONFIG_WORD_SIZE=32 | ||
| 30 | # CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set | ||
| 31 | CONFIG_MMU=y | ||
| 32 | CONFIG_GENERIC_CMOS_UPDATE=y | ||
| 33 | CONFIG_GENERIC_TIME=y | ||
| 34 | CONFIG_GENERIC_TIME_VSYSCALL=y | ||
| 35 | CONFIG_GENERIC_CLOCKEVENTS=y | ||
| 36 | CONFIG_GENERIC_HARDIRQS=y | ||
| 37 | CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y | ||
| 38 | # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set | ||
| 39 | # CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK is not set | ||
| 40 | CONFIG_IRQ_PER_CPU=y | ||
| 41 | CONFIG_STACKTRACE_SUPPORT=y | ||
| 42 | CONFIG_HAVE_LATENCYTOP_SUPPORT=y | ||
| 43 | CONFIG_TRACE_IRQFLAGS_SUPPORT=y | ||
| 44 | CONFIG_LOCKDEP_SUPPORT=y | ||
| 45 | CONFIG_RWSEM_XCHGADD_ALGORITHM=y | ||
| 46 | CONFIG_ARCH_HAS_ILOG2_U32=y | ||
| 47 | CONFIG_GENERIC_HWEIGHT=y | ||
| 48 | CONFIG_GENERIC_FIND_NEXT_BIT=y | ||
| 49 | # CONFIG_ARCH_NO_VIRT_TO_BUS is not set | ||
| 50 | CONFIG_PPC=y | ||
| 51 | CONFIG_EARLY_PRINTK=y | ||
| 52 | CONFIG_GENERIC_NVRAM=y | ||
| 53 | CONFIG_SCHED_OMIT_FRAME_POINTER=y | ||
| 54 | CONFIG_ARCH_MAY_HAVE_PC_FDC=y | ||
| 55 | CONFIG_PPC_OF=y | ||
| 56 | CONFIG_OF=y | ||
| 57 | # CONFIG_PPC_UDBG_16550 is not set | ||
| 58 | # CONFIG_GENERIC_TBSYNC is not set | ||
| 59 | CONFIG_AUDIT_ARCH=y | ||
| 60 | CONFIG_GENERIC_BUG=y | ||
| 61 | CONFIG_DTC=y | ||
| 62 | # CONFIG_DEFAULT_UIMAGE is not set | ||
| 63 | # CONFIG_PPC_DCR_NATIVE is not set | ||
| 64 | # CONFIG_PPC_DCR_MMIO is not set | ||
| 65 | CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y | ||
| 66 | CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" | ||
| 67 | CONFIG_CONSTRUCTORS=y | ||
| 68 | |||
| 69 | # | ||
| 70 | # General setup | ||
| 71 | # | ||
| 72 | CONFIG_EXPERIMENTAL=y | ||
| 73 | CONFIG_BROKEN_ON_SMP=y | ||
| 74 | CONFIG_LOCK_KERNEL=y | ||
| 75 | CONFIG_INIT_ENV_ARG_LIMIT=32 | ||
| 76 | CONFIG_LOCALVERSION="-gcn" | ||
| 77 | CONFIG_LOCALVERSION_AUTO=y | ||
| 78 | CONFIG_SWAP=y | ||
| 79 | CONFIG_SYSVIPC=y | ||
| 80 | CONFIG_SYSVIPC_SYSCTL=y | ||
| 81 | # CONFIG_POSIX_MQUEUE is not set | ||
| 82 | # CONFIG_BSD_PROCESS_ACCT is not set | ||
| 83 | # CONFIG_TASKSTATS is not set | ||
| 84 | # CONFIG_AUDIT is not set | ||
| 85 | |||
| 86 | # | ||
| 87 | # RCU Subsystem | ||
| 88 | # | ||
| 89 | CONFIG_TREE_RCU=y | ||
| 90 | # CONFIG_TREE_PREEMPT_RCU is not set | ||
| 91 | # CONFIG_RCU_TRACE is not set | ||
| 92 | CONFIG_RCU_FANOUT=32 | ||
| 93 | # CONFIG_RCU_FANOUT_EXACT is not set | ||
| 94 | # CONFIG_TREE_RCU_TRACE is not set | ||
| 95 | CONFIG_IKCONFIG=y | ||
| 96 | CONFIG_IKCONFIG_PROC=y | ||
| 97 | CONFIG_LOG_BUF_SHIFT=14 | ||
| 98 | CONFIG_GROUP_SCHED=y | ||
| 99 | CONFIG_FAIR_GROUP_SCHED=y | ||
| 100 | # CONFIG_RT_GROUP_SCHED is not set | ||
| 101 | CONFIG_USER_SCHED=y | ||
| 102 | # CONFIG_CGROUP_SCHED is not set | ||
| 103 | # CONFIG_CGROUPS is not set | ||
| 104 | CONFIG_SYSFS_DEPRECATED=y | ||
| 105 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
| 106 | # CONFIG_RELAY is not set | ||
| 107 | # CONFIG_NAMESPACES is not set | ||
| 108 | CONFIG_BLK_DEV_INITRD=y | ||
| 109 | CONFIG_INITRAMFS_SOURCE="" | ||
| 110 | CONFIG_RD_GZIP=y | ||
| 111 | # CONFIG_RD_BZIP2 is not set | ||
| 112 | # CONFIG_RD_LZMA is not set | ||
| 113 | # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set | ||
| 114 | CONFIG_SYSCTL=y | ||
| 115 | CONFIG_ANON_INODES=y | ||
| 116 | CONFIG_EMBEDDED=y | ||
| 117 | CONFIG_SYSCTL_SYSCALL=y | ||
| 118 | CONFIG_KALLSYMS=y | ||
| 119 | CONFIG_KALLSYMS_ALL=y | ||
| 120 | # CONFIG_KALLSYMS_EXTRA_PASS is not set | ||
| 121 | CONFIG_HOTPLUG=y | ||
| 122 | CONFIG_PRINTK=y | ||
| 123 | CONFIG_BUG=y | ||
| 124 | # CONFIG_ELF_CORE is not set | ||
| 125 | CONFIG_BASE_FULL=y | ||
| 126 | CONFIG_FUTEX=y | ||
| 127 | CONFIG_EPOLL=y | ||
| 128 | CONFIG_SIGNALFD=y | ||
| 129 | CONFIG_TIMERFD=y | ||
| 130 | CONFIG_EVENTFD=y | ||
| 131 | CONFIG_SHMEM=y | ||
| 132 | CONFIG_AIO=y | ||
| 133 | CONFIG_HAVE_PERF_EVENTS=y | ||
| 134 | |||
| 135 | # | ||
| 136 | # Kernel Performance Events And Counters | ||
| 137 | # | ||
| 138 | CONFIG_PERF_EVENTS=y | ||
| 139 | CONFIG_EVENT_PROFILE=y | ||
| 140 | CONFIG_PERF_COUNTERS=y | ||
| 141 | # CONFIG_DEBUG_PERF_USE_VMALLOC is not set | ||
| 142 | # CONFIG_VM_EVENT_COUNTERS is not set | ||
| 143 | CONFIG_COMPAT_BRK=y | ||
| 144 | CONFIG_SLAB=y | ||
| 145 | # CONFIG_SLUB is not set | ||
| 146 | # CONFIG_SLOB is not set | ||
| 147 | # CONFIG_PROFILING is not set | ||
| 148 | CONFIG_TRACEPOINTS=y | ||
| 149 | CONFIG_HAVE_OPROFILE=y | ||
| 150 | # CONFIG_KPROBES is not set | ||
| 151 | CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y | ||
| 152 | CONFIG_HAVE_IOREMAP_PROT=y | ||
| 153 | CONFIG_HAVE_KPROBES=y | ||
| 154 | CONFIG_HAVE_KRETPROBES=y | ||
| 155 | CONFIG_HAVE_ARCH_TRACEHOOK=y | ||
| 156 | CONFIG_HAVE_DMA_ATTRS=y | ||
| 157 | CONFIG_HAVE_DMA_API_DEBUG=y | ||
| 158 | |||
| 159 | # | ||
| 160 | # GCOV-based kernel profiling | ||
| 161 | # | ||
| 162 | # CONFIG_GCOV_KERNEL is not set | ||
| 163 | CONFIG_SLOW_WORK=y | ||
| 164 | # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set | ||
| 165 | CONFIG_SLABINFO=y | ||
| 166 | CONFIG_RT_MUTEXES=y | ||
| 167 | CONFIG_BASE_SMALL=0 | ||
| 168 | CONFIG_MODULES=y | ||
| 169 | # CONFIG_MODULE_FORCE_LOAD is not set | ||
| 170 | CONFIG_MODULE_UNLOAD=y | ||
| 171 | # CONFIG_MODULE_FORCE_UNLOAD is not set | ||
| 172 | # CONFIG_MODVERSIONS is not set | ||
| 173 | # CONFIG_MODULE_SRCVERSION_ALL is not set | ||
| 174 | CONFIG_BLOCK=y | ||
| 175 | CONFIG_LBDAF=y | ||
| 176 | # CONFIG_BLK_DEV_BSG is not set | ||
| 177 | # CONFIG_BLK_DEV_INTEGRITY is not set | ||
| 178 | |||
| 179 | # | ||
| 180 | # IO Schedulers | ||
| 181 | # | ||
| 182 | CONFIG_IOSCHED_NOOP=y | ||
| 183 | CONFIG_IOSCHED_AS=y | ||
| 184 | CONFIG_IOSCHED_DEADLINE=y | ||
| 185 | CONFIG_IOSCHED_CFQ=y | ||
| 186 | CONFIG_DEFAULT_AS=y | ||
| 187 | # CONFIG_DEFAULT_DEADLINE is not set | ||
| 188 | # CONFIG_DEFAULT_CFQ is not set | ||
| 189 | # CONFIG_DEFAULT_NOOP is not set | ||
| 190 | CONFIG_DEFAULT_IOSCHED="anticipatory" | ||
| 191 | # CONFIG_FREEZER is not set | ||
| 192 | |||
| 193 | # | ||
| 194 | # Platform support | ||
| 195 | # | ||
| 196 | # CONFIG_PPC_CHRP is not set | ||
| 197 | # CONFIG_MPC5121_ADS is not set | ||
| 198 | # CONFIG_MPC5121_GENERIC is not set | ||
| 199 | # CONFIG_PPC_MPC52xx is not set | ||
| 200 | # CONFIG_PPC_PMAC is not set | ||
| 201 | # CONFIG_PPC_CELL is not set | ||
| 202 | # CONFIG_PPC_CELL_NATIVE is not set | ||
| 203 | # CONFIG_PPC_82xx is not set | ||
| 204 | # CONFIG_PQ2ADS is not set | ||
| 205 | # CONFIG_PPC_83xx is not set | ||
| 206 | # CONFIG_PPC_86xx is not set | ||
| 207 | CONFIG_EMBEDDED6xx=y | ||
| 208 | # CONFIG_LINKSTATION is not set | ||
| 209 | # CONFIG_STORCENTER is not set | ||
| 210 | # CONFIG_MPC7448HPC2 is not set | ||
| 211 | # CONFIG_PPC_HOLLY is not set | ||
| 212 | # CONFIG_PPC_PRPMC2800 is not set | ||
| 213 | # CONFIG_PPC_C2K is not set | ||
| 214 | CONFIG_GAMECUBE_COMMON=y | ||
| 215 | CONFIG_USBGECKO_UDBG=y | ||
| 216 | CONFIG_FLIPPER_PIC=y | ||
| 217 | CONFIG_GAMECUBE=y | ||
| 218 | # CONFIG_WII is not set | ||
| 219 | # CONFIG_AMIGAONE is not set | ||
| 220 | # CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set | ||
| 221 | # CONFIG_IPIC is not set | ||
| 222 | # CONFIG_MPIC is not set | ||
| 223 | # CONFIG_MPIC_WEIRD is not set | ||
| 224 | # CONFIG_PPC_I8259 is not set | ||
| 225 | # CONFIG_PPC_RTAS is not set | ||
| 226 | # CONFIG_MMIO_NVRAM is not set | ||
| 227 | # CONFIG_PPC_MPC106 is not set | ||
| 228 | # CONFIG_PPC_970_NAP is not set | ||
| 229 | # CONFIG_PPC_INDIRECT_IO is not set | ||
| 230 | # CONFIG_GENERIC_IOMAP is not set | ||
| 231 | # CONFIG_CPU_FREQ is not set | ||
| 232 | # CONFIG_TAU is not set | ||
| 233 | # CONFIG_FSL_ULI1575 is not set | ||
| 234 | # CONFIG_SIMPLE_GPIO is not set | ||
| 235 | |||
| 236 | # | ||
| 237 | # Kernel options | ||
| 238 | # | ||
| 239 | # CONFIG_HIGHMEM is not set | ||
| 240 | # CONFIG_NO_HZ is not set | ||
| 241 | # CONFIG_HIGH_RES_TIMERS is not set | ||
| 242 | CONFIG_GENERIC_CLOCKEVENTS_BUILD=y | ||
| 243 | # CONFIG_HZ_100 is not set | ||
| 244 | CONFIG_HZ_250=y | ||
| 245 | # CONFIG_HZ_300 is not set | ||
| 246 | # CONFIG_HZ_1000 is not set | ||
| 247 | CONFIG_HZ=250 | ||
| 248 | # CONFIG_SCHED_HRTICK is not set | ||
| 249 | # CONFIG_PREEMPT_NONE is not set | ||
| 250 | # CONFIG_PREEMPT_VOLUNTARY is not set | ||
| 251 | CONFIG_PREEMPT=y | ||
| 252 | CONFIG_BINFMT_ELF=y | ||
| 253 | # CONFIG_HAVE_AOUT is not set | ||
| 254 | CONFIG_BINFMT_MISC=m | ||
| 255 | # CONFIG_IOMMU_HELPER is not set | ||
| 256 | # CONFIG_SWIOTLB is not set | ||
| 257 | CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y | ||
| 258 | CONFIG_ARCH_HAS_WALK_MEMORY=y | ||
| 259 | CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y | ||
| 260 | CONFIG_KEXEC=y | ||
| 261 | # CONFIG_CRASH_DUMP is not set | ||
| 262 | CONFIG_MAX_ACTIVE_REGIONS=32 | ||
| 263 | CONFIG_ARCH_FLATMEM_ENABLE=y | ||
| 264 | CONFIG_ARCH_POPULATES_NODE_MAP=y | ||
| 265 | CONFIG_SELECT_MEMORY_MODEL=y | ||
| 266 | CONFIG_FLATMEM_MANUAL=y | ||
| 267 | # CONFIG_DISCONTIGMEM_MANUAL is not set | ||
| 268 | # CONFIG_SPARSEMEM_MANUAL is not set | ||
| 269 | CONFIG_FLATMEM=y | ||
| 270 | CONFIG_FLAT_NODE_MEM_MAP=y | ||
| 271 | CONFIG_PAGEFLAGS_EXTENDED=y | ||
| 272 | CONFIG_SPLIT_PTLOCK_CPUS=4 | ||
| 273 | # CONFIG_MIGRATION is not set | ||
| 274 | # CONFIG_PHYS_ADDR_T_64BIT is not set | ||
| 275 | CONFIG_ZONE_DMA_FLAG=1 | ||
| 276 | CONFIG_BOUNCE=y | ||
| 277 | CONFIG_VIRT_TO_BUS=y | ||
| 278 | CONFIG_HAVE_MLOCK=y | ||
| 279 | CONFIG_HAVE_MLOCKED_PAGE_BIT=y | ||
| 280 | # CONFIG_KSM is not set | ||
| 281 | CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 | ||
| 282 | CONFIG_PPC_4K_PAGES=y | ||
| 283 | # CONFIG_PPC_16K_PAGES is not set | ||
| 284 | # CONFIG_PPC_64K_PAGES is not set | ||
| 285 | # CONFIG_PPC_256K_PAGES is not set | ||
| 286 | CONFIG_FORCE_MAX_ZONEORDER=11 | ||
| 287 | CONFIG_PROC_DEVICETREE=y | ||
| 288 | # CONFIG_CMDLINE_BOOL is not set | ||
| 289 | CONFIG_EXTRA_TARGETS="" | ||
| 290 | # CONFIG_PM is not set | ||
| 291 | # CONFIG_SECCOMP is not set | ||
| 292 | CONFIG_ISA_DMA_API=y | ||
| 293 | |||
| 294 | # | ||
| 295 | # Bus options | ||
| 296 | # | ||
| 297 | CONFIG_ZONE_DMA=y | ||
| 298 | CONFIG_GENERIC_ISA_DMA=y | ||
| 299 | # CONFIG_PCI is not set | ||
| 300 | # CONFIG_PCI_DOMAINS is not set | ||
| 301 | # CONFIG_PCI_SYSCALL is not set | ||
| 302 | # CONFIG_ARCH_SUPPORTS_MSI is not set | ||
| 303 | # CONFIG_PCCARD is not set | ||
| 304 | # CONFIG_HAS_RAPIDIO is not set | ||
| 305 | |||
| 306 | # | ||
| 307 | # Advanced setup | ||
| 308 | # | ||
| 309 | CONFIG_ADVANCED_OPTIONS=y | ||
| 310 | # CONFIG_LOWMEM_SIZE_BOOL is not set | ||
| 311 | CONFIG_LOWMEM_SIZE=0x30000000 | ||
| 312 | # CONFIG_PAGE_OFFSET_BOOL is not set | ||
| 313 | CONFIG_PAGE_OFFSET=0xc0000000 | ||
| 314 | # CONFIG_KERNEL_START_BOOL is not set | ||
| 315 | CONFIG_KERNEL_START=0xc0000000 | ||
| 316 | CONFIG_PHYSICAL_START=0x00000000 | ||
| 317 | # CONFIG_TASK_SIZE_BOOL is not set | ||
| 318 | CONFIG_TASK_SIZE=0xc0000000 | ||
| 319 | # CONFIG_CONSISTENT_SIZE_BOOL is not set | ||
| 320 | CONFIG_CONSISTENT_SIZE=0x00200000 | ||
| 321 | CONFIG_NET=y | ||
| 322 | |||
| 323 | # | ||
| 324 | # Networking options | ||
| 325 | # | ||
| 326 | CONFIG_PACKET=y | ||
| 327 | # CONFIG_PACKET_MMAP is not set | ||
| 328 | CONFIG_UNIX=y | ||
| 329 | # CONFIG_NET_KEY is not set | ||
| 330 | CONFIG_INET=y | ||
| 331 | # CONFIG_IP_MULTICAST is not set | ||
| 332 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
| 333 | CONFIG_IP_FIB_HASH=y | ||
| 334 | CONFIG_IP_PNP=y | ||
| 335 | CONFIG_IP_PNP_DHCP=y | ||
| 336 | # CONFIG_IP_PNP_BOOTP is not set | ||
| 337 | CONFIG_IP_PNP_RARP=y | ||
| 338 | # CONFIG_NET_IPIP is not set | ||
| 339 | # CONFIG_NET_IPGRE is not set | ||
| 340 | # CONFIG_ARPD is not set | ||
| 341 | # CONFIG_SYN_COOKIES is not set | ||
| 342 | # CONFIG_INET_AH is not set | ||
| 343 | # CONFIG_INET_ESP is not set | ||
| 344 | # CONFIG_INET_IPCOMP is not set | ||
| 345 | # CONFIG_INET_XFRM_TUNNEL is not set | ||
| 346 | # CONFIG_INET_TUNNEL is not set | ||
| 347 | # CONFIG_INET_XFRM_MODE_TRANSPORT is not set | ||
| 348 | # CONFIG_INET_XFRM_MODE_TUNNEL is not set | ||
| 349 | # CONFIG_INET_XFRM_MODE_BEET is not set | ||
| 350 | # CONFIG_INET_LRO is not set | ||
| 351 | # CONFIG_INET_DIAG is not set | ||
| 352 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
| 353 | CONFIG_TCP_CONG_CUBIC=y | ||
| 354 | CONFIG_DEFAULT_TCP_CONG="cubic" | ||
| 355 | # CONFIG_TCP_MD5SIG is not set | ||
| 356 | # CONFIG_IPV6 is not set | ||
| 357 | # CONFIG_NETWORK_SECMARK is not set | ||
| 358 | # CONFIG_NETFILTER is not set | ||
| 359 | # CONFIG_IP_DCCP is not set | ||
| 360 | # CONFIG_IP_SCTP is not set | ||
| 361 | # CONFIG_RDS is not set | ||
| 362 | # CONFIG_TIPC is not set | ||
| 363 | # CONFIG_ATM is not set | ||
| 364 | # CONFIG_BRIDGE is not set | ||
| 365 | # CONFIG_NET_DSA is not set | ||
| 366 | # CONFIG_VLAN_8021Q is not set | ||
| 367 | # CONFIG_DECNET is not set | ||
| 368 | # CONFIG_LLC2 is not set | ||
| 369 | # CONFIG_IPX is not set | ||
| 370 | # CONFIG_ATALK is not set | ||
| 371 | # CONFIG_X25 is not set | ||
| 372 | # CONFIG_LAPB is not set | ||
| 373 | # CONFIG_ECONET is not set | ||
| 374 | # CONFIG_WAN_ROUTER is not set | ||
| 375 | # CONFIG_PHONET is not set | ||
| 376 | # CONFIG_IEEE802154 is not set | ||
| 377 | # CONFIG_NET_SCHED is not set | ||
| 378 | # CONFIG_DCB is not set | ||
| 379 | |||
| 380 | # | ||
| 381 | # Network testing | ||
| 382 | # | ||
| 383 | # CONFIG_NET_PKTGEN is not set | ||
| 384 | # CONFIG_NET_DROP_MONITOR is not set | ||
| 385 | # CONFIG_HAMRADIO is not set | ||
| 386 | # CONFIG_CAN is not set | ||
| 387 | # CONFIG_IRDA is not set | ||
| 388 | # CONFIG_BT is not set | ||
| 389 | # CONFIG_AF_RXRPC is not set | ||
| 390 | # CONFIG_WIRELESS is not set | ||
| 391 | # CONFIG_WIMAX is not set | ||
| 392 | # CONFIG_RFKILL is not set | ||
| 393 | # CONFIG_NET_9P is not set | ||
| 394 | |||
| 395 | # | ||
| 396 | # Device Drivers | ||
| 397 | # | ||
| 398 | |||
| 399 | # | ||
| 400 | # Generic Driver Options | ||
| 401 | # | ||
| 402 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
| 403 | # CONFIG_DEVTMPFS is not set | ||
| 404 | # CONFIG_STANDALONE is not set | ||
| 405 | CONFIG_PREVENT_FIRMWARE_BUILD=y | ||
| 406 | # CONFIG_FW_LOADER is not set | ||
| 407 | # CONFIG_DEBUG_DRIVER is not set | ||
| 408 | # CONFIG_DEBUG_DEVRES is not set | ||
| 409 | # CONFIG_SYS_HYPERVISOR is not set | ||
| 410 | # CONFIG_CONNECTOR is not set | ||
| 411 | # CONFIG_MTD is not set | ||
| 412 | CONFIG_OF_DEVICE=y | ||
| 413 | # CONFIG_PARPORT is not set | ||
| 414 | CONFIG_BLK_DEV=y | ||
| 415 | # CONFIG_BLK_DEV_FD is not set | ||
| 416 | # CONFIG_BLK_DEV_COW_COMMON is not set | ||
| 417 | CONFIG_BLK_DEV_LOOP=y | ||
| 418 | # CONFIG_BLK_DEV_CRYPTOLOOP is not set | ||
| 419 | CONFIG_BLK_DEV_NBD=m | ||
| 420 | CONFIG_BLK_DEV_RAM=y | ||
| 421 | CONFIG_BLK_DEV_RAM_COUNT=2 | ||
| 422 | CONFIG_BLK_DEV_RAM_SIZE=4096 | ||
| 423 | # CONFIG_BLK_DEV_XIP is not set | ||
| 424 | # CONFIG_CDROM_PKTCDVD is not set | ||
| 425 | # CONFIG_ATA_OVER_ETH is not set | ||
| 426 | # CONFIG_BLK_DEV_HD is not set | ||
| 427 | CONFIG_MISC_DEVICES=y | ||
| 428 | # CONFIG_ENCLOSURE_SERVICES is not set | ||
| 429 | # CONFIG_C2PORT is not set | ||
| 430 | |||
| 431 | # | ||
| 432 | # EEPROM support | ||
| 433 | # | ||
| 434 | # CONFIG_EEPROM_93CX6 is not set | ||
| 435 | CONFIG_HAVE_IDE=y | ||
| 436 | # CONFIG_IDE is not set | ||
| 437 | |||
| 438 | # | ||
| 439 | # SCSI device support | ||
| 440 | # | ||
| 441 | # CONFIG_RAID_ATTRS is not set | ||
| 442 | # CONFIG_SCSI is not set | ||
| 443 | # CONFIG_SCSI_DMA is not set | ||
| 444 | # CONFIG_SCSI_NETLINK is not set | ||
| 445 | # CONFIG_ATA is not set | ||
| 446 | # CONFIG_MD is not set | ||
| 447 | # CONFIG_MACINTOSH_DRIVERS is not set | ||
| 448 | CONFIG_NETDEVICES=y | ||
| 449 | # CONFIG_DUMMY is not set | ||
| 450 | # CONFIG_BONDING is not set | ||
| 451 | # CONFIG_MACVLAN is not set | ||
| 452 | # CONFIG_EQUALIZER is not set | ||
| 453 | # CONFIG_TUN is not set | ||
| 454 | # CONFIG_VETH is not set | ||
| 455 | # CONFIG_PHYLIB is not set | ||
| 456 | CONFIG_NET_ETHERNET=y | ||
| 457 | # CONFIG_MII is not set | ||
| 458 | # CONFIG_ETHOC is not set | ||
| 459 | # CONFIG_DNET is not set | ||
| 460 | # CONFIG_IBM_NEW_EMAC_ZMII is not set | ||
| 461 | # CONFIG_IBM_NEW_EMAC_RGMII is not set | ||
| 462 | # CONFIG_IBM_NEW_EMAC_TAH is not set | ||
| 463 | # CONFIG_IBM_NEW_EMAC_EMAC4 is not set | ||
| 464 | # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set | ||
| 465 | # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set | ||
| 466 | # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set | ||
| 467 | # CONFIG_B44 is not set | ||
| 468 | # CONFIG_KS8842 is not set | ||
| 469 | # CONFIG_KS8851_MLL is not set | ||
| 470 | # CONFIG_XILINX_EMACLITE is not set | ||
| 471 | # CONFIG_NETDEV_1000 is not set | ||
| 472 | # CONFIG_NETDEV_10000 is not set | ||
| 473 | # CONFIG_WLAN is not set | ||
| 474 | |||
| 475 | # | ||
| 476 | # Enable WiMAX (Networking options) to see the WiMAX drivers | ||
| 477 | # | ||
| 478 | # CONFIG_WAN is not set | ||
| 479 | # CONFIG_PPP is not set | ||
| 480 | # CONFIG_SLIP is not set | ||
| 481 | # CONFIG_NETCONSOLE is not set | ||
| 482 | # CONFIG_NETPOLL is not set | ||
| 483 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
| 484 | # CONFIG_ISDN is not set | ||
| 485 | # CONFIG_PHONE is not set | ||
| 486 | |||
| 487 | # | ||
| 488 | # Input device support | ||
| 489 | # | ||
| 490 | CONFIG_INPUT=y | ||
| 491 | CONFIG_INPUT_FF_MEMLESS=m | ||
| 492 | # CONFIG_INPUT_POLLDEV is not set | ||
| 493 | |||
| 494 | # | ||
| 495 | # Userland interfaces | ||
| 496 | # | ||
| 497 | # CONFIG_INPUT_MOUSEDEV is not set | ||
| 498 | CONFIG_INPUT_JOYDEV=y | ||
| 499 | CONFIG_INPUT_EVDEV=y | ||
| 500 | # CONFIG_INPUT_EVBUG is not set | ||
| 501 | |||
| 502 | # | ||
| 503 | # Input Device Drivers | ||
| 504 | # | ||
| 505 | CONFIG_INPUT_KEYBOARD=y | ||
| 506 | # CONFIG_KEYBOARD_ATKBD is not set | ||
| 507 | # CONFIG_KEYBOARD_LKKBD is not set | ||
| 508 | # CONFIG_KEYBOARD_NEWTON is not set | ||
| 509 | # CONFIG_KEYBOARD_OPENCORES is not set | ||
| 510 | # CONFIG_KEYBOARD_STOWAWAY is not set | ||
| 511 | # CONFIG_KEYBOARD_SUNKBD is not set | ||
| 512 | # CONFIG_KEYBOARD_XTKBD is not set | ||
| 513 | # CONFIG_INPUT_MOUSE is not set | ||
| 514 | CONFIG_INPUT_JOYSTICK=y | ||
| 515 | # CONFIG_JOYSTICK_ANALOG is not set | ||
| 516 | # CONFIG_JOYSTICK_A3D is not set | ||
| 517 | # CONFIG_JOYSTICK_ADI is not set | ||
| 518 | # CONFIG_JOYSTICK_COBRA is not set | ||
| 519 | # CONFIG_JOYSTICK_GF2K is not set | ||
| 520 | # CONFIG_JOYSTICK_GRIP is not set | ||
| 521 | # CONFIG_JOYSTICK_GRIP_MP is not set | ||
| 522 | # CONFIG_JOYSTICK_GUILLEMOT is not set | ||
| 523 | # CONFIG_JOYSTICK_INTERACT is not set | ||
| 524 | # CONFIG_JOYSTICK_SIDEWINDER is not set | ||
| 525 | # CONFIG_JOYSTICK_TMDC is not set | ||
| 526 | # CONFIG_JOYSTICK_IFORCE is not set | ||
| 527 | # CONFIG_JOYSTICK_WARRIOR is not set | ||
| 528 | # CONFIG_JOYSTICK_MAGELLAN is not set | ||
| 529 | # CONFIG_JOYSTICK_SPACEORB is not set | ||
| 530 | # CONFIG_JOYSTICK_SPACEBALL is not set | ||
| 531 | # CONFIG_JOYSTICK_STINGER is not set | ||
| 532 | # CONFIG_JOYSTICK_TWIDJOY is not set | ||
| 533 | # CONFIG_JOYSTICK_ZHENHUA is not set | ||
| 534 | # CONFIG_JOYSTICK_JOYDUMP is not set | ||
| 535 | # CONFIG_INPUT_TABLET is not set | ||
| 536 | # CONFIG_INPUT_TOUCHSCREEN is not set | ||
| 537 | # CONFIG_INPUT_MISC is not set | ||
| 538 | |||
| 539 | # | ||
| 540 | # Hardware I/O ports | ||
| 541 | # | ||
| 542 | CONFIG_SERIO=y | ||
| 543 | # CONFIG_SERIO_I8042 is not set | ||
| 544 | # CONFIG_SERIO_SERPORT is not set | ||
| 545 | # CONFIG_SERIO_LIBPS2 is not set | ||
| 546 | # CONFIG_SERIO_RAW is not set | ||
| 547 | # CONFIG_SERIO_XILINX_XPS_PS2 is not set | ||
| 548 | # CONFIG_GAMEPORT is not set | ||
| 549 | |||
| 550 | # | ||
| 551 | # Character devices | ||
| 552 | # | ||
| 553 | CONFIG_VT=y | ||
| 554 | CONFIG_CONSOLE_TRANSLATIONS=y | ||
| 555 | CONFIG_VT_CONSOLE=y | ||
| 556 | CONFIG_HW_CONSOLE=y | ||
| 557 | # CONFIG_VT_HW_CONSOLE_BINDING is not set | ||
| 558 | # CONFIG_DEVKMEM is not set | ||
| 559 | # CONFIG_SERIAL_NONSTANDARD is not set | ||
| 560 | |||
| 561 | # | ||
| 562 | # Serial drivers | ||
| 563 | # | ||
| 564 | # CONFIG_SERIAL_8250 is not set | ||
| 565 | |||
| 566 | # | ||
| 567 | # Non-8250 serial port support | ||
| 568 | # | ||
| 569 | # CONFIG_SERIAL_UARTLITE is not set | ||
| 570 | CONFIG_UNIX98_PTYS=y | ||
| 571 | # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set | ||
| 572 | CONFIG_LEGACY_PTYS=y | ||
| 573 | CONFIG_LEGACY_PTY_COUNT=64 | ||
| 574 | # CONFIG_HVC_UDBG is not set | ||
| 575 | # CONFIG_IPMI_HANDLER is not set | ||
| 576 | # CONFIG_HW_RANDOM is not set | ||
| 577 | # CONFIG_NVRAM is not set | ||
| 578 | # CONFIG_R3964 is not set | ||
| 579 | # CONFIG_RAW_DRIVER is not set | ||
| 580 | # CONFIG_TCG_TPM is not set | ||
| 581 | # CONFIG_I2C is not set | ||
| 582 | # CONFIG_SPI is not set | ||
| 583 | |||
| 584 | # | ||
| 585 | # PPS support | ||
| 586 | # | ||
| 587 | # CONFIG_PPS is not set | ||
| 588 | CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y | ||
| 589 | # CONFIG_GPIOLIB is not set | ||
| 590 | # CONFIG_W1 is not set | ||
| 591 | # CONFIG_POWER_SUPPLY is not set | ||
| 592 | # CONFIG_HWMON is not set | ||
| 593 | # CONFIG_THERMAL is not set | ||
| 594 | # CONFIG_WATCHDOG is not set | ||
| 595 | CONFIG_SSB_POSSIBLE=y | ||
| 596 | |||
| 597 | # | ||
| 598 | # Sonics Silicon Backplane | ||
| 599 | # | ||
| 600 | # CONFIG_SSB is not set | ||
| 601 | |||
| 602 | # | ||
| 603 | # Multifunction device drivers | ||
| 604 | # | ||
| 605 | # CONFIG_MFD_CORE is not set | ||
| 606 | # CONFIG_MFD_SM501 is not set | ||
| 607 | # CONFIG_HTC_PASIC3 is not set | ||
| 608 | # CONFIG_MFD_TMIO is not set | ||
| 609 | # CONFIG_REGULATOR is not set | ||
| 610 | # CONFIG_MEDIA_SUPPORT is not set | ||
| 611 | |||
| 612 | # | ||
| 613 | # Graphics support | ||
| 614 | # | ||
| 615 | # CONFIG_VGASTATE is not set | ||
| 616 | # CONFIG_VIDEO_OUTPUT_CONTROL is not set | ||
| 617 | CONFIG_FB=y | ||
| 618 | # CONFIG_FIRMWARE_EDID is not set | ||
| 619 | # CONFIG_FB_DDC is not set | ||
| 620 | # CONFIG_FB_BOOT_VESA_SUPPORT is not set | ||
| 621 | # CONFIG_FB_CFB_FILLRECT is not set | ||
| 622 | # CONFIG_FB_CFB_COPYAREA is not set | ||
| 623 | # CONFIG_FB_CFB_IMAGEBLIT is not set | ||
| 624 | # CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set | ||
| 625 | # CONFIG_FB_SYS_FILLRECT is not set | ||
| 626 | # CONFIG_FB_SYS_COPYAREA is not set | ||
| 627 | # CONFIG_FB_SYS_IMAGEBLIT is not set | ||
| 628 | # CONFIG_FB_FOREIGN_ENDIAN is not set | ||
| 629 | # CONFIG_FB_SYS_FOPS is not set | ||
| 630 | # CONFIG_FB_SVGALIB is not set | ||
| 631 | # CONFIG_FB_MACMODES is not set | ||
| 632 | # CONFIG_FB_BACKLIGHT is not set | ||
| 633 | # CONFIG_FB_MODE_HELPERS is not set | ||
| 634 | # CONFIG_FB_TILEBLITTING is not set | ||
| 635 | |||
| 636 | # | ||
| 637 | # Frame buffer hardware drivers | ||
| 638 | # | ||
| 639 | # CONFIG_FB_OF is not set | ||
| 640 | # CONFIG_FB_VGA16 is not set | ||
| 641 | # CONFIG_FB_S1D13XXX is not set | ||
| 642 | # CONFIG_FB_IBM_GXT4500 is not set | ||
| 643 | # CONFIG_FB_VIRTUAL is not set | ||
| 644 | # CONFIG_FB_METRONOME is not set | ||
| 645 | # CONFIG_FB_MB862XX is not set | ||
| 646 | # CONFIG_FB_BROADSHEET is not set | ||
| 647 | # CONFIG_BACKLIGHT_LCD_SUPPORT is not set | ||
| 648 | |||
| 649 | # | ||
| 650 | # Display device support | ||
| 651 | # | ||
| 652 | # CONFIG_DISPLAY_SUPPORT is not set | ||
| 653 | |||
| 654 | # | ||
| 655 | # Console display driver support | ||
| 656 | # | ||
| 657 | # CONFIG_VGA_CONSOLE is not set | ||
| 658 | CONFIG_DUMMY_CONSOLE=y | ||
| 659 | CONFIG_FRAMEBUFFER_CONSOLE=y | ||
| 660 | # CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set | ||
| 661 | # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set | ||
| 662 | # CONFIG_FONTS is not set | ||
| 663 | CONFIG_FONT_8x8=y | ||
| 664 | CONFIG_FONT_8x16=y | ||
| 665 | CONFIG_LOGO=y | ||
| 666 | # CONFIG_LOGO_LINUX_MONO is not set | ||
| 667 | # CONFIG_LOGO_LINUX_VGA16 is not set | ||
| 668 | # CONFIG_LOGO_LINUX_CLUT224 is not set | ||
| 669 | CONFIG_SOUND=y | ||
| 670 | CONFIG_SOUND_OSS_CORE=y | ||
| 671 | CONFIG_SOUND_OSS_CORE_PRECLAIM=y | ||
| 672 | CONFIG_SND=y | ||
| 673 | CONFIG_SND_TIMER=y | ||
| 674 | CONFIG_SND_PCM=y | ||
| 675 | CONFIG_SND_SEQUENCER=y | ||
| 676 | # CONFIG_SND_SEQ_DUMMY is not set | ||
| 677 | CONFIG_SND_OSSEMUL=y | ||
| 678 | CONFIG_SND_MIXER_OSS=y | ||
| 679 | CONFIG_SND_PCM_OSS=y | ||
| 680 | CONFIG_SND_PCM_OSS_PLUGINS=y | ||
| 681 | CONFIG_SND_SEQUENCER_OSS=y | ||
| 682 | # CONFIG_SND_DYNAMIC_MINORS is not set | ||
| 683 | CONFIG_SND_SUPPORT_OLD_API=y | ||
| 684 | # CONFIG_SND_VERBOSE_PROCFS is not set | ||
| 685 | # CONFIG_SND_VERBOSE_PRINTK is not set | ||
| 686 | # CONFIG_SND_DEBUG is not set | ||
| 687 | # CONFIG_SND_RAWMIDI_SEQ is not set | ||
| 688 | # CONFIG_SND_OPL3_LIB_SEQ is not set | ||
| 689 | # CONFIG_SND_OPL4_LIB_SEQ is not set | ||
| 690 | # CONFIG_SND_SBAWE_SEQ is not set | ||
| 691 | # CONFIG_SND_EMU10K1_SEQ is not set | ||
| 692 | CONFIG_SND_DRIVERS=y | ||
| 693 | # CONFIG_SND_DUMMY is not set | ||
| 694 | # CONFIG_SND_VIRMIDI is not set | ||
| 695 | # CONFIG_SND_MTPAV is not set | ||
| 696 | # CONFIG_SND_SERIAL_U16550 is not set | ||
| 697 | # CONFIG_SND_MPU401 is not set | ||
| 698 | CONFIG_SND_PPC=y | ||
| 699 | # CONFIG_SND_SOC is not set | ||
| 700 | # CONFIG_SOUND_PRIME is not set | ||
| 701 | CONFIG_HID_SUPPORT=y | ||
| 702 | CONFIG_HID=y | ||
| 703 | # CONFIG_HIDRAW is not set | ||
| 704 | # CONFIG_HID_PID is not set | ||
| 705 | |||
| 706 | # | ||
| 707 | # Special HID drivers | ||
| 708 | # | ||
| 709 | # CONFIG_USB_SUPPORT is not set | ||
| 710 | # CONFIG_MMC is not set | ||
| 711 | # CONFIG_MEMSTICK is not set | ||
| 712 | # CONFIG_NEW_LEDS is not set | ||
| 713 | # CONFIG_ACCESSIBILITY is not set | ||
| 714 | # CONFIG_EDAC is not set | ||
| 715 | CONFIG_RTC_LIB=y | ||
| 716 | CONFIG_RTC_CLASS=y | ||
| 717 | CONFIG_RTC_HCTOSYS=y | ||
| 718 | CONFIG_RTC_HCTOSYS_DEVICE="rtc0" | ||
| 719 | # CONFIG_RTC_DEBUG is not set | ||
| 720 | |||
| 721 | # | ||
| 722 | # RTC interfaces | ||
| 723 | # | ||
| 724 | CONFIG_RTC_INTF_SYSFS=y | ||
| 725 | CONFIG_RTC_INTF_PROC=y | ||
| 726 | CONFIG_RTC_INTF_DEV=y | ||
| 727 | # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set | ||
| 728 | # CONFIG_RTC_DRV_TEST is not set | ||
| 729 | |||
| 730 | # | ||
| 731 | # SPI RTC drivers | ||
| 732 | # | ||
| 733 | |||
| 734 | # | ||
| 735 | # Platform RTC drivers | ||
| 736 | # | ||
| 737 | # CONFIG_RTC_DRV_CMOS is not set | ||
| 738 | # CONFIG_RTC_DRV_DS1286 is not set | ||
| 739 | # CONFIG_RTC_DRV_DS1511 is not set | ||
| 740 | # CONFIG_RTC_DRV_DS1553 is not set | ||
| 741 | # CONFIG_RTC_DRV_DS1742 is not set | ||
| 742 | # CONFIG_RTC_DRV_STK17TA8 is not set | ||
| 743 | # CONFIG_RTC_DRV_M48T86 is not set | ||
| 744 | # CONFIG_RTC_DRV_M48T35 is not set | ||
| 745 | # CONFIG_RTC_DRV_M48T59 is not set | ||
| 746 | # CONFIG_RTC_DRV_BQ4802 is not set | ||
| 747 | # CONFIG_RTC_DRV_V3020 is not set | ||
| 748 | |||
| 749 | # | ||
| 750 | # on-CPU RTC drivers | ||
| 751 | # | ||
| 752 | CONFIG_RTC_DRV_GENERIC=y | ||
| 753 | # CONFIG_DMADEVICES is not set | ||
| 754 | # CONFIG_AUXDISPLAY is not set | ||
| 755 | # CONFIG_UIO is not set | ||
| 756 | |||
| 757 | # | ||
| 758 | # TI VLYNQ | ||
| 759 | # | ||
| 760 | # CONFIG_STAGING is not set | ||
| 761 | |||
| 762 | # | ||
| 763 | # File systems | ||
| 764 | # | ||
| 765 | CONFIG_EXT2_FS=y | ||
| 766 | # CONFIG_EXT2_FS_XATTR is not set | ||
| 767 | # CONFIG_EXT2_FS_XIP is not set | ||
| 768 | CONFIG_EXT3_FS=y | ||
| 769 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
| 770 | # CONFIG_EXT3_FS_XATTR is not set | ||
| 771 | # CONFIG_EXT4_FS is not set | ||
| 772 | CONFIG_JBD=y | ||
| 773 | # CONFIG_JBD_DEBUG is not set | ||
| 774 | # CONFIG_REISERFS_FS is not set | ||
| 775 | # CONFIG_JFS_FS is not set | ||
| 776 | # CONFIG_FS_POSIX_ACL is not set | ||
| 777 | # CONFIG_XFS_FS is not set | ||
| 778 | # CONFIG_GFS2_FS is not set | ||
| 779 | # CONFIG_OCFS2_FS is not set | ||
| 780 | # CONFIG_BTRFS_FS is not set | ||
| 781 | # CONFIG_NILFS2_FS is not set | ||
| 782 | CONFIG_FILE_LOCKING=y | ||
| 783 | CONFIG_FSNOTIFY=y | ||
| 784 | CONFIG_DNOTIFY=y | ||
| 785 | CONFIG_INOTIFY=y | ||
| 786 | CONFIG_INOTIFY_USER=y | ||
| 787 | # CONFIG_QUOTA is not set | ||
| 788 | # CONFIG_AUTOFS_FS is not set | ||
| 789 | # CONFIG_AUTOFS4_FS is not set | ||
| 790 | # CONFIG_FUSE_FS is not set | ||
| 791 | |||
| 792 | # | ||
| 793 | # Caches | ||
| 794 | # | ||
| 795 | # CONFIG_FSCACHE is not set | ||
| 796 | |||
| 797 | # | ||
| 798 | # CD-ROM/DVD Filesystems | ||
| 799 | # | ||
| 800 | CONFIG_ISO9660_FS=y | ||
| 801 | CONFIG_JOLIET=y | ||
| 802 | # CONFIG_ZISOFS is not set | ||
| 803 | # CONFIG_UDF_FS is not set | ||
| 804 | |||
| 805 | # | ||
| 806 | # DOS/FAT/NT Filesystems | ||
| 807 | # | ||
| 808 | CONFIG_FAT_FS=y | ||
| 809 | CONFIG_MSDOS_FS=y | ||
| 810 | CONFIG_VFAT_FS=y | ||
| 811 | CONFIG_FAT_DEFAULT_CODEPAGE=437 | ||
| 812 | CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" | ||
| 813 | # CONFIG_NTFS_FS is not set | ||
| 814 | |||
| 815 | # | ||
| 816 | # Pseudo filesystems | ||
| 817 | # | ||
| 818 | CONFIG_PROC_FS=y | ||
| 819 | CONFIG_PROC_KCORE=y | ||
| 820 | CONFIG_PROC_SYSCTL=y | ||
| 821 | # CONFIG_PROC_PAGE_MONITOR is not set | ||
| 822 | CONFIG_SYSFS=y | ||
| 823 | CONFIG_TMPFS=y | ||
| 824 | # CONFIG_TMPFS_POSIX_ACL is not set | ||
| 825 | # CONFIG_HUGETLB_PAGE is not set | ||
| 826 | # CONFIG_CONFIGFS_FS is not set | ||
| 827 | CONFIG_MISC_FILESYSTEMS=y | ||
| 828 | # CONFIG_ADFS_FS is not set | ||
| 829 | # CONFIG_AFFS_FS is not set | ||
| 830 | # CONFIG_HFS_FS is not set | ||
| 831 | # CONFIG_HFSPLUS_FS is not set | ||
| 832 | # CONFIG_BEFS_FS is not set | ||
| 833 | # CONFIG_BFS_FS is not set | ||
| 834 | # CONFIG_EFS_FS is not set | ||
| 835 | # CONFIG_CRAMFS is not set | ||
| 836 | # CONFIG_SQUASHFS is not set | ||
| 837 | # CONFIG_VXFS_FS is not set | ||
| 838 | # CONFIG_MINIX_FS is not set | ||
| 839 | # CONFIG_OMFS_FS is not set | ||
| 840 | # CONFIG_HPFS_FS is not set | ||
| 841 | # CONFIG_QNX4FS_FS is not set | ||
| 842 | # CONFIG_ROMFS_FS is not set | ||
| 843 | # CONFIG_SYSV_FS is not set | ||
| 844 | # CONFIG_UFS_FS is not set | ||
| 845 | CONFIG_NETWORK_FILESYSTEMS=y | ||
| 846 | CONFIG_NFS_FS=y | ||
| 847 | CONFIG_NFS_V3=y | ||
| 848 | # CONFIG_NFS_V3_ACL is not set | ||
| 849 | # CONFIG_NFS_V4 is not set | ||
| 850 | CONFIG_ROOT_NFS=y | ||
| 851 | # CONFIG_NFSD is not set | ||
| 852 | CONFIG_LOCKD=y | ||
| 853 | CONFIG_LOCKD_V4=y | ||
| 854 | CONFIG_NFS_COMMON=y | ||
| 855 | CONFIG_SUNRPC=y | ||
| 856 | # CONFIG_RPCSEC_GSS_KRB5 is not set | ||
| 857 | # CONFIG_RPCSEC_GSS_SPKM3 is not set | ||
| 858 | # CONFIG_SMB_FS is not set | ||
| 859 | CONFIG_CIFS=y | ||
| 860 | # CONFIG_CIFS_STATS is not set | ||
| 861 | # CONFIG_CIFS_WEAK_PW_HASH is not set | ||
| 862 | # CONFIG_CIFS_XATTR is not set | ||
| 863 | # CONFIG_CIFS_DEBUG2 is not set | ||
| 864 | # CONFIG_CIFS_EXPERIMENTAL is not set | ||
| 865 | # CONFIG_NCP_FS is not set | ||
| 866 | # CONFIG_CODA_FS is not set | ||
| 867 | # CONFIG_AFS_FS is not set | ||
| 868 | |||
| 869 | # | ||
| 870 | # Partition Types | ||
| 871 | # | ||
| 872 | # CONFIG_PARTITION_ADVANCED is not set | ||
| 873 | CONFIG_MSDOS_PARTITION=y | ||
| 874 | CONFIG_NLS=y | ||
| 875 | CONFIG_NLS_DEFAULT="iso8859-1" | ||
| 876 | CONFIG_NLS_CODEPAGE_437=y | ||
| 877 | # CONFIG_NLS_CODEPAGE_737 is not set | ||
| 878 | # CONFIG_NLS_CODEPAGE_775 is not set | ||
| 879 | # CONFIG_NLS_CODEPAGE_850 is not set | ||
| 880 | # CONFIG_NLS_CODEPAGE_852 is not set | ||
| 881 | # CONFIG_NLS_CODEPAGE_855 is not set | ||
| 882 | # CONFIG_NLS_CODEPAGE_857 is not set | ||
| 883 | # CONFIG_NLS_CODEPAGE_860 is not set | ||
| 884 | # CONFIG_NLS_CODEPAGE_861 is not set | ||
| 885 | # CONFIG_NLS_CODEPAGE_862 is not set | ||
| 886 | # CONFIG_NLS_CODEPAGE_863 is not set | ||
| 887 | # CONFIG_NLS_CODEPAGE_864 is not set | ||
| 888 | # CONFIG_NLS_CODEPAGE_865 is not set | ||
| 889 | # CONFIG_NLS_CODEPAGE_866 is not set | ||
| 890 | # CONFIG_NLS_CODEPAGE_869 is not set | ||
| 891 | # CONFIG_NLS_CODEPAGE_936 is not set | ||
| 892 | # CONFIG_NLS_CODEPAGE_950 is not set | ||
| 893 | # CONFIG_NLS_CODEPAGE_932 is not set | ||
| 894 | # CONFIG_NLS_CODEPAGE_949 is not set | ||
| 895 | # CONFIG_NLS_CODEPAGE_874 is not set | ||
| 896 | # CONFIG_NLS_ISO8859_8 is not set | ||
| 897 | # CONFIG_NLS_CODEPAGE_1250 is not set | ||
| 898 | # CONFIG_NLS_CODEPAGE_1251 is not set | ||
| 899 | # CONFIG_NLS_ASCII is not set | ||
| 900 | CONFIG_NLS_ISO8859_1=y | ||
| 901 | # CONFIG_NLS_ISO8859_2 is not set | ||
| 902 | # CONFIG_NLS_ISO8859_3 is not set | ||
| 903 | # CONFIG_NLS_ISO8859_4 is not set | ||
| 904 | # CONFIG_NLS_ISO8859_5 is not set | ||
| 905 | # CONFIG_NLS_ISO8859_6 is not set | ||
| 906 | # CONFIG_NLS_ISO8859_7 is not set | ||
| 907 | # CONFIG_NLS_ISO8859_9 is not set | ||
| 908 | # CONFIG_NLS_ISO8859_13 is not set | ||
| 909 | # CONFIG_NLS_ISO8859_14 is not set | ||
| 910 | # CONFIG_NLS_ISO8859_15 is not set | ||
| 911 | # CONFIG_NLS_KOI8_R is not set | ||
| 912 | # CONFIG_NLS_KOI8_U is not set | ||
| 913 | # CONFIG_NLS_UTF8 is not set | ||
| 914 | # CONFIG_DLM is not set | ||
| 915 | CONFIG_BINARY_PRINTF=y | ||
| 916 | |||
| 917 | # | ||
| 918 | # Library routines | ||
| 919 | # | ||
| 920 | CONFIG_BITREVERSE=y | ||
| 921 | CONFIG_GENERIC_FIND_LAST_BIT=y | ||
| 922 | CONFIG_CRC_CCITT=y | ||
| 923 | # CONFIG_CRC16 is not set | ||
| 924 | # CONFIG_CRC_T10DIF is not set | ||
| 925 | # CONFIG_CRC_ITU_T is not set | ||
| 926 | CONFIG_CRC32=y | ||
| 927 | # CONFIG_CRC7 is not set | ||
| 928 | # CONFIG_LIBCRC32C is not set | ||
| 929 | CONFIG_ZLIB_INFLATE=y | ||
| 930 | CONFIG_DECOMPRESS_GZIP=y | ||
| 931 | CONFIG_HAS_IOMEM=y | ||
| 932 | CONFIG_HAS_IOPORT=y | ||
| 933 | CONFIG_HAS_DMA=y | ||
| 934 | CONFIG_HAVE_LMB=y | ||
| 935 | CONFIG_NLATTR=y | ||
| 936 | CONFIG_GENERIC_ATOMIC64=y | ||
| 937 | |||
| 938 | # | ||
| 939 | # Kernel hacking | ||
| 940 | # | ||
| 941 | CONFIG_PRINTK_TIME=y | ||
| 942 | CONFIG_ENABLE_WARN_DEPRECATED=y | ||
| 943 | CONFIG_ENABLE_MUST_CHECK=y | ||
| 944 | CONFIG_FRAME_WARN=1024 | ||
| 945 | # CONFIG_MAGIC_SYSRQ is not set | ||
| 946 | # CONFIG_STRIP_ASM_SYMS is not set | ||
| 947 | # CONFIG_UNUSED_SYMBOLS is not set | ||
| 948 | CONFIG_DEBUG_FS=y | ||
| 949 | # CONFIG_HEADERS_CHECK is not set | ||
| 950 | CONFIG_DEBUG_KERNEL=y | ||
| 951 | # CONFIG_DEBUG_SHIRQ is not set | ||
| 952 | CONFIG_DETECT_SOFTLOCKUP=y | ||
| 953 | # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set | ||
| 954 | CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 | ||
| 955 | # CONFIG_DETECT_HUNG_TASK is not set | ||
| 956 | CONFIG_SCHED_DEBUG=y | ||
| 957 | CONFIG_SCHEDSTATS=y | ||
| 958 | # CONFIG_TIMER_STATS is not set | ||
| 959 | # CONFIG_DEBUG_OBJECTS is not set | ||
| 960 | # CONFIG_DEBUG_SLAB is not set | ||
| 961 | # CONFIG_DEBUG_KMEMLEAK is not set | ||
| 962 | CONFIG_DEBUG_PREEMPT=y | ||
| 963 | # CONFIG_DEBUG_RT_MUTEXES is not set | ||
| 964 | # CONFIG_RT_MUTEX_TESTER is not set | ||
| 965 | CONFIG_DEBUG_SPINLOCK=y | ||
| 966 | CONFIG_DEBUG_MUTEXES=y | ||
| 967 | # CONFIG_DEBUG_LOCK_ALLOC is not set | ||
| 968 | # CONFIG_PROVE_LOCKING is not set | ||
| 969 | # CONFIG_LOCK_STAT is not set | ||
| 970 | CONFIG_DEBUG_SPINLOCK_SLEEP=y | ||
| 971 | # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set | ||
| 972 | CONFIG_STACKTRACE=y | ||
| 973 | # CONFIG_DEBUG_KOBJECT is not set | ||
| 974 | CONFIG_DEBUG_BUGVERBOSE=y | ||
| 975 | # CONFIG_DEBUG_INFO is not set | ||
| 976 | # CONFIG_DEBUG_VM is not set | ||
| 977 | # CONFIG_DEBUG_WRITECOUNT is not set | ||
| 978 | # CONFIG_DEBUG_MEMORY_INIT is not set | ||
| 979 | # CONFIG_DEBUG_LIST is not set | ||
| 980 | # CONFIG_DEBUG_SG is not set | ||
| 981 | # CONFIG_DEBUG_NOTIFIERS is not set | ||
| 982 | # CONFIG_DEBUG_CREDENTIALS is not set | ||
| 983 | # CONFIG_RCU_TORTURE_TEST is not set | ||
| 984 | # CONFIG_RCU_CPU_STALL_DETECTOR is not set | ||
| 985 | # CONFIG_BACKTRACE_SELF_TEST is not set | ||
| 986 | # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set | ||
| 987 | # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set | ||
| 988 | # CONFIG_FAULT_INJECTION is not set | ||
| 989 | CONFIG_LATENCYTOP=y | ||
| 990 | CONFIG_SYSCTL_SYSCALL_CHECK=y | ||
| 991 | # CONFIG_DEBUG_PAGEALLOC is not set | ||
| 992 | CONFIG_NOP_TRACER=y | ||
| 993 | CONFIG_HAVE_FUNCTION_TRACER=y | ||
| 994 | CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y | ||
| 995 | CONFIG_HAVE_DYNAMIC_FTRACE=y | ||
| 996 | CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y | ||
| 997 | CONFIG_TRACER_MAX_TRACE=y | ||
| 998 | CONFIG_RING_BUFFER=y | ||
| 999 | CONFIG_EVENT_TRACING=y | ||
| 1000 | CONFIG_CONTEXT_SWITCH_TRACER=y | ||
| 1001 | CONFIG_TRACING=y | ||
| 1002 | CONFIG_GENERIC_TRACER=y | ||
| 1003 | CONFIG_TRACING_SUPPORT=y | ||
| 1004 | CONFIG_FTRACE=y | ||
| 1005 | # CONFIG_FUNCTION_TRACER is not set | ||
| 1006 | # CONFIG_IRQSOFF_TRACER is not set | ||
| 1007 | # CONFIG_PREEMPT_TRACER is not set | ||
| 1008 | CONFIG_SCHED_TRACER=y | ||
| 1009 | CONFIG_BOOT_TRACER=y | ||
| 1010 | CONFIG_BRANCH_PROFILE_NONE=y | ||
| 1011 | # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set | ||
| 1012 | # CONFIG_PROFILE_ALL_BRANCHES is not set | ||
| 1013 | # CONFIG_STACK_TRACER is not set | ||
| 1014 | # CONFIG_KMEMTRACE is not set | ||
| 1015 | # CONFIG_WORKQUEUE_TRACER is not set | ||
| 1016 | # CONFIG_BLK_DEV_IO_TRACE is not set | ||
| 1017 | # CONFIG_FTRACE_STARTUP_TEST is not set | ||
| 1018 | # CONFIG_RING_BUFFER_BENCHMARK is not set | ||
| 1019 | # CONFIG_DYNAMIC_DEBUG is not set | ||
| 1020 | CONFIG_DMA_API_DEBUG=y | ||
| 1021 | # CONFIG_SAMPLES is not set | ||
| 1022 | CONFIG_HAVE_ARCH_KGDB=y | ||
| 1023 | # CONFIG_KGDB is not set | ||
| 1024 | # CONFIG_PPC_DISABLE_WERROR is not set | ||
| 1025 | CONFIG_PPC_WERROR=y | ||
| 1026 | CONFIG_PRINT_STACK_DEPTH=64 | ||
| 1027 | # CONFIG_DEBUG_STACKOVERFLOW is not set | ||
| 1028 | # CONFIG_DEBUG_STACK_USAGE is not set | ||
| 1029 | # CONFIG_PPC_EMULATED_STATS is not set | ||
| 1030 | # CONFIG_CODE_PATCHING_SELFTEST is not set | ||
| 1031 | # CONFIG_FTR_FIXUP_SELFTEST is not set | ||
| 1032 | # CONFIG_MSI_BITMAP_SELFTEST is not set | ||
| 1033 | # CONFIG_XMON is not set | ||
| 1034 | # CONFIG_IRQSTACKS is not set | ||
| 1035 | # CONFIG_VIRQ_DEBUG is not set | ||
| 1036 | # CONFIG_BDI_SWITCH is not set | ||
| 1037 | # CONFIG_BOOTX_TEXT is not set | ||
| 1038 | CONFIG_PPC_EARLY_DEBUG=y | ||
| 1039 | # CONFIG_PPC_EARLY_DEBUG_LPAR is not set | ||
| 1040 | # CONFIG_PPC_EARLY_DEBUG_G5 is not set | ||
| 1041 | # CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set | ||
| 1042 | # CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set | ||
| 1043 | # CONFIG_PPC_EARLY_DEBUG_MAPLE is not set | ||
| 1044 | # CONFIG_PPC_EARLY_DEBUG_ISERIES is not set | ||
| 1045 | # CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set | ||
| 1046 | # CONFIG_PPC_EARLY_DEBUG_BEAT is not set | ||
| 1047 | # CONFIG_PPC_EARLY_DEBUG_44x is not set | ||
| 1048 | # CONFIG_PPC_EARLY_DEBUG_40x is not set | ||
| 1049 | # CONFIG_PPC_EARLY_DEBUG_CPM is not set | ||
| 1050 | CONFIG_PPC_EARLY_DEBUG_USBGECKO=y | ||
| 1051 | |||
| 1052 | # | ||
| 1053 | # Security options | ||
| 1054 | # | ||
| 1055 | # CONFIG_KEYS is not set | ||
| 1056 | # CONFIG_SECURITY is not set | ||
| 1057 | # CONFIG_SECURITYFS is not set | ||
| 1058 | # CONFIG_SECURITY_FILE_CAPABILITIES is not set | ||
| 1059 | # CONFIG_CRYPTO is not set | ||
| 1060 | # CONFIG_PPC_CLOCK is not set | ||
| 1061 | # CONFIG_VIRTUALIZATION is not set | ||
diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig index f925c555508e..76982c51a4c7 100644 --- a/arch/powerpc/configs/iseries_defconfig +++ b/arch/powerpc/configs/iseries_defconfig | |||
| @@ -714,8 +714,8 @@ CONFIG_NETDEV_10000=y | |||
| 714 | # CONFIG_BNX2X is not set | 714 | # CONFIG_BNX2X is not set |
| 715 | # CONFIG_QLGE is not set | 715 | # CONFIG_QLGE is not set |
| 716 | # CONFIG_SFC is not set | 716 | # CONFIG_SFC is not set |
| 717 | CONFIG_TR=y | 717 | # CONFIG_TR is not set |
| 718 | CONFIG_IBMOL=y | 718 | # CONFIG_IBMOL is not set |
| 719 | # CONFIG_3C359 is not set | 719 | # CONFIG_3C359 is not set |
| 720 | # CONFIG_TMS380TR is not set | 720 | # CONFIG_TMS380TR is not set |
| 721 | 721 | ||
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 252401824575..7b3804a6e363 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig | |||
| @@ -304,11 +304,11 @@ CONFIG_TICK_ONESHOT=y | |||
| 304 | CONFIG_NO_HZ=y | 304 | CONFIG_NO_HZ=y |
| 305 | CONFIG_HIGH_RES_TIMERS=y | 305 | CONFIG_HIGH_RES_TIMERS=y |
| 306 | CONFIG_GENERIC_CLOCKEVENTS_BUILD=y | 306 | CONFIG_GENERIC_CLOCKEVENTS_BUILD=y |
| 307 | # CONFIG_HZ_100 is not set | 307 | CONFIG_HZ_100=y |
| 308 | CONFIG_HZ_250=y | 308 | # CONFIG_HZ_250 is not set |
| 309 | # CONFIG_HZ_300 is not set | 309 | # CONFIG_HZ_300 is not set |
| 310 | # CONFIG_HZ_1000 is not set | 310 | # CONFIG_HZ_1000 is not set |
| 311 | CONFIG_HZ=250 | 311 | CONFIG_HZ=100 |
| 312 | CONFIG_SCHED_HRTICK=y | 312 | CONFIG_SCHED_HRTICK=y |
| 313 | CONFIG_PREEMPT_NONE=y | 313 | CONFIG_PREEMPT_NONE=y |
| 314 | # CONFIG_PREEMPT_VOLUNTARY is not set | 314 | # CONFIG_PREEMPT_VOLUNTARY is not set |
| @@ -980,7 +980,7 @@ CONFIG_E100=y | |||
| 980 | # CONFIG_SC92031 is not set | 980 | # CONFIG_SC92031 is not set |
| 981 | # CONFIG_ATL2 is not set | 981 | # CONFIG_ATL2 is not set |
| 982 | CONFIG_NETDEV_1000=y | 982 | CONFIG_NETDEV_1000=y |
| 983 | CONFIG_ACENIC=y | 983 | CONFIG_ACENIC=m |
| 984 | CONFIG_ACENIC_OMIT_TIGON_I=y | 984 | CONFIG_ACENIC_OMIT_TIGON_I=y |
| 985 | # CONFIG_DL2K is not set | 985 | # CONFIG_DL2K is not set |
| 986 | CONFIG_E1000=y | 986 | CONFIG_E1000=y |
| @@ -1023,8 +1023,8 @@ CONFIG_PASEMI_MAC=y | |||
| 1023 | # CONFIG_BNX2X is not set | 1023 | # CONFIG_BNX2X is not set |
| 1024 | # CONFIG_QLGE is not set | 1024 | # CONFIG_QLGE is not set |
| 1025 | # CONFIG_SFC is not set | 1025 | # CONFIG_SFC is not set |
| 1026 | CONFIG_TR=y | 1026 | # CONFIG_TR is not set |
| 1027 | CONFIG_IBMOL=y | 1027 | # CONFIG_IBMOL is not set |
| 1028 | # CONFIG_3C359 is not set | 1028 | # CONFIG_3C359 is not set |
| 1029 | # CONFIG_TMS380TR is not set | 1029 | # CONFIG_TMS380TR is not set |
| 1030 | 1030 | ||
| @@ -1863,7 +1863,7 @@ CONFIG_HFSPLUS_FS=m | |||
| 1863 | # CONFIG_BEFS_FS is not set | 1863 | # CONFIG_BEFS_FS is not set |
| 1864 | # CONFIG_BFS_FS is not set | 1864 | # CONFIG_BFS_FS is not set |
| 1865 | # CONFIG_EFS_FS is not set | 1865 | # CONFIG_EFS_FS is not set |
| 1866 | CONFIG_CRAMFS=y | 1866 | CONFIG_CRAMFS=m |
| 1867 | # CONFIG_VXFS_FS is not set | 1867 | # CONFIG_VXFS_FS is not set |
| 1868 | # CONFIG_MINIX_FS is not set | 1868 | # CONFIG_MINIX_FS is not set |
| 1869 | # CONFIG_OMFS_FS is not set | 1869 | # CONFIG_OMFS_FS is not set |
diff --git a/arch/powerpc/configs/ppc64e_defconfig b/arch/powerpc/configs/ppc64e_defconfig index 18af46036258..8195f1650cbf 100644 --- a/arch/powerpc/configs/ppc64e_defconfig +++ b/arch/powerpc/configs/ppc64e_defconfig | |||
| @@ -1008,8 +1008,8 @@ CONFIG_IXGB=m | |||
| 1008 | # CONFIG_QLGE is not set | 1008 | # CONFIG_QLGE is not set |
| 1009 | # CONFIG_SFC is not set | 1009 | # CONFIG_SFC is not set |
| 1010 | # CONFIG_BE2NET is not set | 1010 | # CONFIG_BE2NET is not set |
| 1011 | CONFIG_TR=y | 1011 | # CONFIG_TR is not set |
| 1012 | CONFIG_IBMOL=y | 1012 | # CONFIG_IBMOL is not set |
| 1013 | # CONFIG_3C359 is not set | 1013 | # CONFIG_3C359 is not set |
| 1014 | # CONFIG_TMS380TR is not set | 1014 | # CONFIG_TMS380TR is not set |
| 1015 | CONFIG_WLAN=y | 1015 | CONFIG_WLAN=y |
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index c568329723b8..ca9ff9aad74a 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig | |||
| @@ -230,11 +230,11 @@ CONFIG_TICK_ONESHOT=y | |||
| 230 | CONFIG_NO_HZ=y | 230 | CONFIG_NO_HZ=y |
| 231 | CONFIG_HIGH_RES_TIMERS=y | 231 | CONFIG_HIGH_RES_TIMERS=y |
| 232 | CONFIG_GENERIC_CLOCKEVENTS_BUILD=y | 232 | CONFIG_GENERIC_CLOCKEVENTS_BUILD=y |
| 233 | # CONFIG_HZ_100 is not set | 233 | CONFIG_HZ_100=y |
| 234 | CONFIG_HZ_250=y | 234 | # CONFIG_HZ_250 is not set |
| 235 | # CONFIG_HZ_300 is not set | 235 | # CONFIG_HZ_300 is not set |
| 236 | # CONFIG_HZ_1000 is not set | 236 | # CONFIG_HZ_1000 is not set |
| 237 | CONFIG_HZ=250 | 237 | CONFIG_HZ=100 |
| 238 | CONFIG_SCHED_HRTICK=y | 238 | CONFIG_SCHED_HRTICK=y |
| 239 | CONFIG_PREEMPT_NONE=y | 239 | CONFIG_PREEMPT_NONE=y |
| 240 | # CONFIG_PREEMPT_VOLUNTARY is not set | 240 | # CONFIG_PREEMPT_VOLUNTARY is not set |
| @@ -796,7 +796,7 @@ CONFIG_E100=y | |||
| 796 | # CONFIG_NET_POCKET is not set | 796 | # CONFIG_NET_POCKET is not set |
| 797 | # CONFIG_ATL2 is not set | 797 | # CONFIG_ATL2 is not set |
| 798 | CONFIG_NETDEV_1000=y | 798 | CONFIG_NETDEV_1000=y |
| 799 | CONFIG_ACENIC=y | 799 | CONFIG_ACENIC=m |
| 800 | CONFIG_ACENIC_OMIT_TIGON_I=y | 800 | CONFIG_ACENIC_OMIT_TIGON_I=y |
| 801 | # CONFIG_DL2K is not set | 801 | # CONFIG_DL2K is not set |
| 802 | CONFIG_E1000=y | 802 | CONFIG_E1000=y |
| @@ -834,8 +834,8 @@ CONFIG_S2IO=m | |||
| 834 | # CONFIG_BNX2X is not set | 834 | # CONFIG_BNX2X is not set |
| 835 | # CONFIG_QLGE is not set | 835 | # CONFIG_QLGE is not set |
| 836 | # CONFIG_SFC is not set | 836 | # CONFIG_SFC is not set |
| 837 | CONFIG_TR=y | 837 | # CONFIG_TR is not set |
| 838 | CONFIG_IBMOL=y | 838 | # CONFIG_IBMOL is not set |
| 839 | # CONFIG_3C359 is not set | 839 | # CONFIG_3C359 is not set |
| 840 | # CONFIG_TMS380TR is not set | 840 | # CONFIG_TMS380TR is not set |
| 841 | 841 | ||
| @@ -1494,7 +1494,7 @@ CONFIG_CONFIGFS_FS=m | |||
| 1494 | # CONFIG_BEFS_FS is not set | 1494 | # CONFIG_BEFS_FS is not set |
| 1495 | # CONFIG_BFS_FS is not set | 1495 | # CONFIG_BFS_FS is not set |
| 1496 | # CONFIG_EFS_FS is not set | 1496 | # CONFIG_EFS_FS is not set |
| 1497 | CONFIG_CRAMFS=y | 1497 | CONFIG_CRAMFS=m |
| 1498 | # CONFIG_VXFS_FS is not set | 1498 | # CONFIG_VXFS_FS is not set |
| 1499 | # CONFIG_MINIX_FS is not set | 1499 | # CONFIG_MINIX_FS is not set |
| 1500 | # CONFIG_OMFS_FS is not set | 1500 | # CONFIG_OMFS_FS is not set |
diff --git a/arch/powerpc/configs/wii_defconfig b/arch/powerpc/configs/wii_defconfig new file mode 100644 index 000000000000..c386828c639a --- /dev/null +++ b/arch/powerpc/configs/wii_defconfig | |||
| @@ -0,0 +1,1406 @@ | |||
| 1 | # | ||
| 2 | # Automatically generated make config: don't edit | ||
| 3 | # Linux kernel version: 2.6.32-rc8 | ||
| 4 | # Sun Nov 22 20:37:21 2009 | ||
| 5 | # | ||
| 6 | # CONFIG_PPC64 is not set | ||
| 7 | |||
| 8 | # | ||
| 9 | # Processor support | ||
| 10 | # | ||
| 11 | CONFIG_PPC_BOOK3S_32=y | ||
| 12 | # CONFIG_PPC_85xx is not set | ||
| 13 | # CONFIG_PPC_8xx is not set | ||
| 14 | # CONFIG_40x is not set | ||
| 15 | # CONFIG_44x is not set | ||
| 16 | # CONFIG_E200 is not set | ||
| 17 | CONFIG_PPC_BOOK3S=y | ||
| 18 | CONFIG_6xx=y | ||
| 19 | CONFIG_PPC_FPU=y | ||
| 20 | # CONFIG_ALTIVEC is not set | ||
| 21 | CONFIG_PPC_STD_MMU=y | ||
| 22 | CONFIG_PPC_STD_MMU_32=y | ||
| 23 | # CONFIG_PPC_MM_SLICES is not set | ||
| 24 | CONFIG_PPC_HAVE_PMU_SUPPORT=y | ||
| 25 | CONFIG_PPC_PERF_CTRS=y | ||
| 26 | # CONFIG_SMP is not set | ||
| 27 | CONFIG_NOT_COHERENT_CACHE=y | ||
| 28 | CONFIG_PPC32=y | ||
| 29 | CONFIG_WORD_SIZE=32 | ||
| 30 | # CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set | ||
| 31 | CONFIG_MMU=y | ||
| 32 | CONFIG_GENERIC_CMOS_UPDATE=y | ||
| 33 | CONFIG_GENERIC_TIME=y | ||
| 34 | CONFIG_GENERIC_TIME_VSYSCALL=y | ||
| 35 | CONFIG_GENERIC_CLOCKEVENTS=y | ||
| 36 | CONFIG_GENERIC_HARDIRQS=y | ||
| 37 | CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y | ||
| 38 | # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set | ||
| 39 | # CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK is not set | ||
| 40 | CONFIG_IRQ_PER_CPU=y | ||
| 41 | CONFIG_STACKTRACE_SUPPORT=y | ||
| 42 | CONFIG_HAVE_LATENCYTOP_SUPPORT=y | ||
| 43 | CONFIG_TRACE_IRQFLAGS_SUPPORT=y | ||
| 44 | CONFIG_LOCKDEP_SUPPORT=y | ||
| 45 | CONFIG_RWSEM_XCHGADD_ALGORITHM=y | ||
| 46 | CONFIG_ARCH_HAS_ILOG2_U32=y | ||
| 47 | CONFIG_GENERIC_HWEIGHT=y | ||
| 48 | CONFIG_GENERIC_FIND_NEXT_BIT=y | ||
| 49 | CONFIG_GENERIC_GPIO=y | ||
| 50 | # CONFIG_ARCH_NO_VIRT_TO_BUS is not set | ||
| 51 | CONFIG_PPC=y | ||
| 52 | CONFIG_EARLY_PRINTK=y | ||
| 53 | CONFIG_GENERIC_NVRAM=y | ||
| 54 | CONFIG_SCHED_OMIT_FRAME_POINTER=y | ||
| 55 | CONFIG_ARCH_MAY_HAVE_PC_FDC=y | ||
| 56 | CONFIG_PPC_OF=y | ||
| 57 | CONFIG_OF=y | ||
| 58 | # CONFIG_PPC_UDBG_16550 is not set | ||
| 59 | # CONFIG_GENERIC_TBSYNC is not set | ||
| 60 | CONFIG_AUDIT_ARCH=y | ||
| 61 | CONFIG_GENERIC_BUG=y | ||
| 62 | CONFIG_DTC=y | ||
| 63 | # CONFIG_DEFAULT_UIMAGE is not set | ||
| 64 | # CONFIG_PPC_DCR_NATIVE is not set | ||
| 65 | # CONFIG_PPC_DCR_MMIO is not set | ||
| 66 | CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y | ||
| 67 | CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" | ||
| 68 | CONFIG_CONSTRUCTORS=y | ||
| 69 | |||
| 70 | # | ||
| 71 | # General setup | ||
| 72 | # | ||
| 73 | CONFIG_EXPERIMENTAL=y | ||
| 74 | CONFIG_BROKEN_ON_SMP=y | ||
| 75 | CONFIG_LOCK_KERNEL=y | ||
| 76 | CONFIG_INIT_ENV_ARG_LIMIT=32 | ||
| 77 | CONFIG_LOCALVERSION="-wii" | ||
| 78 | # CONFIG_LOCALVERSION_AUTO is not set | ||
| 79 | CONFIG_SWAP=y | ||
| 80 | CONFIG_SYSVIPC=y | ||
| 81 | CONFIG_SYSVIPC_SYSCTL=y | ||
| 82 | # CONFIG_POSIX_MQUEUE is not set | ||
| 83 | # CONFIG_BSD_PROCESS_ACCT is not set | ||
| 84 | # CONFIG_TASKSTATS is not set | ||
| 85 | # CONFIG_AUDIT is not set | ||
| 86 | |||
| 87 | # | ||
| 88 | # RCU Subsystem | ||
| 89 | # | ||
| 90 | CONFIG_TREE_RCU=y | ||
| 91 | # CONFIG_TREE_PREEMPT_RCU is not set | ||
| 92 | # CONFIG_RCU_TRACE is not set | ||
| 93 | CONFIG_RCU_FANOUT=32 | ||
| 94 | # CONFIG_RCU_FANOUT_EXACT is not set | ||
| 95 | # CONFIG_TREE_RCU_TRACE is not set | ||
| 96 | CONFIG_IKCONFIG=y | ||
| 97 | CONFIG_IKCONFIG_PROC=y | ||
| 98 | CONFIG_LOG_BUF_SHIFT=14 | ||
| 99 | CONFIG_GROUP_SCHED=y | ||
| 100 | CONFIG_FAIR_GROUP_SCHED=y | ||
| 101 | # CONFIG_RT_GROUP_SCHED is not set | ||
| 102 | CONFIG_USER_SCHED=y | ||
| 103 | # CONFIG_CGROUP_SCHED is not set | ||
| 104 | # CONFIG_CGROUPS is not set | ||
| 105 | CONFIG_SYSFS_DEPRECATED=y | ||
| 106 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
| 107 | CONFIG_RELAY=y | ||
| 108 | # CONFIG_NAMESPACES is not set | ||
| 109 | CONFIG_BLK_DEV_INITRD=y | ||
| 110 | CONFIG_INITRAMFS_SOURCE="" | ||
| 111 | CONFIG_RD_GZIP=y | ||
| 112 | # CONFIG_RD_BZIP2 is not set | ||
| 113 | # CONFIG_RD_LZMA is not set | ||
| 114 | # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set | ||
| 115 | CONFIG_SYSCTL=y | ||
| 116 | CONFIG_ANON_INODES=y | ||
| 117 | CONFIG_EMBEDDED=y | ||
| 118 | CONFIG_SYSCTL_SYSCALL=y | ||
| 119 | CONFIG_KALLSYMS=y | ||
| 120 | CONFIG_KALLSYMS_ALL=y | ||
| 121 | # CONFIG_KALLSYMS_EXTRA_PASS is not set | ||
| 122 | CONFIG_HOTPLUG=y | ||
| 123 | CONFIG_PRINTK=y | ||
| 124 | CONFIG_BUG=y | ||
| 125 | # CONFIG_ELF_CORE is not set | ||
| 126 | CONFIG_BASE_FULL=y | ||
| 127 | CONFIG_FUTEX=y | ||
| 128 | CONFIG_EPOLL=y | ||
| 129 | CONFIG_SIGNALFD=y | ||
| 130 | CONFIG_TIMERFD=y | ||
| 131 | CONFIG_EVENTFD=y | ||
| 132 | CONFIG_SHMEM=y | ||
| 133 | CONFIG_AIO=y | ||
| 134 | CONFIG_HAVE_PERF_EVENTS=y | ||
| 135 | |||
| 136 | # | ||
| 137 | # Kernel Performance Events And Counters | ||
| 138 | # | ||
| 139 | CONFIG_PERF_EVENTS=y | ||
| 140 | CONFIG_EVENT_PROFILE=y | ||
| 141 | CONFIG_PERF_COUNTERS=y | ||
| 142 | # CONFIG_DEBUG_PERF_USE_VMALLOC is not set | ||
| 143 | # CONFIG_VM_EVENT_COUNTERS is not set | ||
| 144 | CONFIG_COMPAT_BRK=y | ||
| 145 | CONFIG_SLAB=y | ||
| 146 | # CONFIG_SLUB is not set | ||
| 147 | # CONFIG_SLOB is not set | ||
| 148 | # CONFIG_PROFILING is not set | ||
| 149 | CONFIG_TRACEPOINTS=y | ||
| 150 | CONFIG_HAVE_OPROFILE=y | ||
| 151 | # CONFIG_KPROBES is not set | ||
| 152 | CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y | ||
| 153 | CONFIG_HAVE_IOREMAP_PROT=y | ||
| 154 | CONFIG_HAVE_KPROBES=y | ||
| 155 | CONFIG_HAVE_KRETPROBES=y | ||
| 156 | CONFIG_HAVE_ARCH_TRACEHOOK=y | ||
| 157 | CONFIG_HAVE_DMA_ATTRS=y | ||
| 158 | CONFIG_HAVE_DMA_API_DEBUG=y | ||
| 159 | |||
| 160 | # | ||
| 161 | # GCOV-based kernel profiling | ||
| 162 | # | ||
| 163 | # CONFIG_GCOV_KERNEL is not set | ||
| 164 | CONFIG_SLOW_WORK=y | ||
| 165 | # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set | ||
| 166 | CONFIG_SLABINFO=y | ||
| 167 | CONFIG_RT_MUTEXES=y | ||
| 168 | CONFIG_BASE_SMALL=0 | ||
| 169 | CONFIG_MODULES=y | ||
| 170 | # CONFIG_MODULE_FORCE_LOAD is not set | ||
| 171 | CONFIG_MODULE_UNLOAD=y | ||
| 172 | # CONFIG_MODULE_FORCE_UNLOAD is not set | ||
| 173 | # CONFIG_MODVERSIONS is not set | ||
| 174 | # CONFIG_MODULE_SRCVERSION_ALL is not set | ||
| 175 | CONFIG_BLOCK=y | ||
| 176 | CONFIG_LBDAF=y | ||
| 177 | CONFIG_BLK_DEV_BSG=y | ||
| 178 | # CONFIG_BLK_DEV_INTEGRITY is not set | ||
| 179 | |||
| 180 | # | ||
| 181 | # IO Schedulers | ||
| 182 | # | ||
| 183 | CONFIG_IOSCHED_NOOP=y | ||
| 184 | CONFIG_IOSCHED_AS=y | ||
| 185 | CONFIG_IOSCHED_DEADLINE=y | ||
| 186 | CONFIG_IOSCHED_CFQ=y | ||
| 187 | CONFIG_DEFAULT_AS=y | ||
| 188 | # CONFIG_DEFAULT_DEADLINE is not set | ||
| 189 | # CONFIG_DEFAULT_CFQ is not set | ||
| 190 | # CONFIG_DEFAULT_NOOP is not set | ||
| 191 | CONFIG_DEFAULT_IOSCHED="anticipatory" | ||
| 192 | # CONFIG_FREEZER is not set | ||
| 193 | |||
| 194 | # | ||
| 195 | # Platform support | ||
| 196 | # | ||
| 197 | # CONFIG_PPC_CHRP is not set | ||
| 198 | # CONFIG_MPC5121_ADS is not set | ||
| 199 | # CONFIG_MPC5121_GENERIC is not set | ||
| 200 | # CONFIG_PPC_MPC52xx is not set | ||
| 201 | # CONFIG_PPC_PMAC is not set | ||
| 202 | # CONFIG_PPC_CELL is not set | ||
| 203 | # CONFIG_PPC_CELL_NATIVE is not set | ||
| 204 | # CONFIG_PPC_82xx is not set | ||
| 205 | # CONFIG_PQ2ADS is not set | ||
| 206 | # CONFIG_PPC_83xx is not set | ||
| 207 | # CONFIG_PPC_86xx is not set | ||
| 208 | CONFIG_EMBEDDED6xx=y | ||
| 209 | # CONFIG_LINKSTATION is not set | ||
| 210 | # CONFIG_STORCENTER is not set | ||
| 211 | # CONFIG_MPC7448HPC2 is not set | ||
| 212 | # CONFIG_PPC_HOLLY is not set | ||
| 213 | # CONFIG_PPC_PRPMC2800 is not set | ||
| 214 | # CONFIG_PPC_C2K is not set | ||
| 215 | CONFIG_GAMECUBE_COMMON=y | ||
| 216 | CONFIG_USBGECKO_UDBG=y | ||
| 217 | CONFIG_FLIPPER_PIC=y | ||
| 218 | # CONFIG_GAMECUBE is not set | ||
| 219 | CONFIG_HLWD_PIC=y | ||
| 220 | CONFIG_STARLET_MINI=y | ||
| 221 | CONFIG_WII=y | ||
| 222 | # CONFIG_AMIGAONE is not set | ||
| 223 | # CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set | ||
| 224 | # CONFIG_IPIC is not set | ||
| 225 | # CONFIG_MPIC is not set | ||
| 226 | # CONFIG_MPIC_WEIRD is not set | ||
| 227 | # CONFIG_PPC_I8259 is not set | ||
| 228 | # CONFIG_PPC_RTAS is not set | ||
| 229 | # CONFIG_MMIO_NVRAM is not set | ||
| 230 | # CONFIG_PPC_MPC106 is not set | ||
| 231 | # CONFIG_PPC_970_NAP is not set | ||
| 232 | # CONFIG_PPC_INDIRECT_IO is not set | ||
| 233 | # CONFIG_GENERIC_IOMAP is not set | ||
| 234 | # CONFIG_CPU_FREQ is not set | ||
| 235 | # CONFIG_TAU is not set | ||
| 236 | # CONFIG_FSL_ULI1575 is not set | ||
| 237 | # CONFIG_SIMPLE_GPIO is not set | ||
| 238 | |||
| 239 | # | ||
| 240 | # Kernel options | ||
| 241 | # | ||
| 242 | # CONFIG_HIGHMEM is not set | ||
| 243 | # CONFIG_NO_HZ is not set | ||
| 244 | # CONFIG_HIGH_RES_TIMERS is not set | ||
| 245 | CONFIG_GENERIC_CLOCKEVENTS_BUILD=y | ||
| 246 | # CONFIG_HZ_100 is not set | ||
| 247 | CONFIG_HZ_250=y | ||
| 248 | # CONFIG_HZ_300 is not set | ||
| 249 | # CONFIG_HZ_1000 is not set | ||
| 250 | CONFIG_HZ=250 | ||
| 251 | # CONFIG_SCHED_HRTICK is not set | ||
| 252 | # CONFIG_PREEMPT_NONE is not set | ||
| 253 | # CONFIG_PREEMPT_VOLUNTARY is not set | ||
| 254 | CONFIG_PREEMPT=y | ||
| 255 | CONFIG_BINFMT_ELF=y | ||
| 256 | # CONFIG_HAVE_AOUT is not set | ||
| 257 | CONFIG_BINFMT_MISC=m | ||
| 258 | # CONFIG_IOMMU_HELPER is not set | ||
| 259 | # CONFIG_SWIOTLB is not set | ||
| 260 | CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y | ||
| 261 | CONFIG_ARCH_HAS_WALK_MEMORY=y | ||
| 262 | CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y | ||
| 263 | CONFIG_KEXEC=y | ||
| 264 | # CONFIG_CRASH_DUMP is not set | ||
| 265 | CONFIG_MAX_ACTIVE_REGIONS=32 | ||
| 266 | CONFIG_ARCH_FLATMEM_ENABLE=y | ||
| 267 | CONFIG_ARCH_POPULATES_NODE_MAP=y | ||
| 268 | CONFIG_SELECT_MEMORY_MODEL=y | ||
| 269 | CONFIG_FLATMEM_MANUAL=y | ||
| 270 | # CONFIG_DISCONTIGMEM_MANUAL is not set | ||
| 271 | # CONFIG_SPARSEMEM_MANUAL is not set | ||
| 272 | CONFIG_FLATMEM=y | ||
| 273 | CONFIG_FLAT_NODE_MEM_MAP=y | ||
| 274 | CONFIG_PAGEFLAGS_EXTENDED=y | ||
| 275 | CONFIG_SPLIT_PTLOCK_CPUS=4 | ||
| 276 | # CONFIG_MIGRATION is not set | ||
| 277 | # CONFIG_PHYS_ADDR_T_64BIT is not set | ||
| 278 | CONFIG_ZONE_DMA_FLAG=1 | ||
| 279 | CONFIG_BOUNCE=y | ||
| 280 | CONFIG_VIRT_TO_BUS=y | ||
| 281 | CONFIG_HAVE_MLOCK=y | ||
| 282 | CONFIG_HAVE_MLOCKED_PAGE_BIT=y | ||
| 283 | # CONFIG_KSM is not set | ||
| 284 | CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 | ||
| 285 | CONFIG_PPC_4K_PAGES=y | ||
| 286 | # CONFIG_PPC_16K_PAGES is not set | ||
| 287 | # CONFIG_PPC_64K_PAGES is not set | ||
| 288 | # CONFIG_PPC_256K_PAGES is not set | ||
| 289 | CONFIG_FORCE_MAX_ZONEORDER=11 | ||
| 290 | CONFIG_PROC_DEVICETREE=y | ||
| 291 | # CONFIG_CMDLINE_BOOL is not set | ||
| 292 | CONFIG_EXTRA_TARGETS="" | ||
| 293 | # CONFIG_PM is not set | ||
| 294 | # CONFIG_SECCOMP is not set | ||
| 295 | CONFIG_ISA_DMA_API=y | ||
| 296 | |||
| 297 | # | ||
| 298 | # Bus options | ||
| 299 | # | ||
| 300 | CONFIG_ZONE_DMA=y | ||
| 301 | CONFIG_GENERIC_ISA_DMA=y | ||
| 302 | # CONFIG_PCI is not set | ||
| 303 | # CONFIG_PCI_DOMAINS is not set | ||
| 304 | # CONFIG_PCI_SYSCALL is not set | ||
| 305 | # CONFIG_ARCH_SUPPORTS_MSI is not set | ||
| 306 | # CONFIG_PCCARD is not set | ||
| 307 | # CONFIG_HAS_RAPIDIO is not set | ||
| 308 | |||
| 309 | # | ||
| 310 | # Advanced setup | ||
| 311 | # | ||
| 312 | CONFIG_ADVANCED_OPTIONS=y | ||
| 313 | # CONFIG_LOWMEM_SIZE_BOOL is not set | ||
| 314 | CONFIG_LOWMEM_SIZE=0x30000000 | ||
| 315 | # CONFIG_PAGE_OFFSET_BOOL is not set | ||
| 316 | CONFIG_PAGE_OFFSET=0xc0000000 | ||
| 317 | # CONFIG_KERNEL_START_BOOL is not set | ||
| 318 | CONFIG_KERNEL_START=0xc0000000 | ||
| 319 | CONFIG_PHYSICAL_START=0x00000000 | ||
| 320 | # CONFIG_TASK_SIZE_BOOL is not set | ||
| 321 | CONFIG_TASK_SIZE=0xc0000000 | ||
| 322 | # CONFIG_CONSISTENT_SIZE_BOOL is not set | ||
| 323 | CONFIG_CONSISTENT_SIZE=0x00200000 | ||
| 324 | CONFIG_NET=y | ||
| 325 | |||
| 326 | # | ||
| 327 | # Networking options | ||
| 328 | # | ||
| 329 | CONFIG_PACKET=y | ||
| 330 | # CONFIG_PACKET_MMAP is not set | ||
| 331 | CONFIG_UNIX=y | ||
| 332 | # CONFIG_NET_KEY is not set | ||
| 333 | CONFIG_INET=y | ||
| 334 | # CONFIG_IP_MULTICAST is not set | ||
| 335 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
| 336 | CONFIG_IP_FIB_HASH=y | ||
| 337 | CONFIG_IP_PNP=y | ||
| 338 | CONFIG_IP_PNP_DHCP=y | ||
| 339 | # CONFIG_IP_PNP_BOOTP is not set | ||
| 340 | CONFIG_IP_PNP_RARP=y | ||
| 341 | # CONFIG_NET_IPIP is not set | ||
| 342 | # CONFIG_NET_IPGRE is not set | ||
| 343 | # CONFIG_ARPD is not set | ||
| 344 | # CONFIG_SYN_COOKIES is not set | ||
| 345 | # CONFIG_INET_AH is not set | ||
| 346 | # CONFIG_INET_ESP is not set | ||
| 347 | # CONFIG_INET_IPCOMP is not set | ||
| 348 | # CONFIG_INET_XFRM_TUNNEL is not set | ||
| 349 | # CONFIG_INET_TUNNEL is not set | ||
| 350 | # CONFIG_INET_XFRM_MODE_TRANSPORT is not set | ||
| 351 | # CONFIG_INET_XFRM_MODE_TUNNEL is not set | ||
| 352 | # CONFIG_INET_XFRM_MODE_BEET is not set | ||
| 353 | # CONFIG_INET_LRO is not set | ||
| 354 | # CONFIG_INET_DIAG is not set | ||
| 355 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
| 356 | CONFIG_TCP_CONG_CUBIC=y | ||
| 357 | CONFIG_DEFAULT_TCP_CONG="cubic" | ||
| 358 | # CONFIG_TCP_MD5SIG is not set | ||
| 359 | # CONFIG_IPV6 is not set | ||
| 360 | # CONFIG_NETWORK_SECMARK is not set | ||
| 361 | # CONFIG_NETFILTER is not set | ||
| 362 | # CONFIG_IP_DCCP is not set | ||
| 363 | # CONFIG_IP_SCTP is not set | ||
| 364 | # CONFIG_RDS is not set | ||
| 365 | # CONFIG_TIPC is not set | ||
| 366 | # CONFIG_ATM is not set | ||
| 367 | # CONFIG_BRIDGE is not set | ||
| 368 | # CONFIG_NET_DSA is not set | ||
| 369 | # CONFIG_VLAN_8021Q is not set | ||
| 370 | # CONFIG_DECNET is not set | ||
| 371 | # CONFIG_LLC2 is not set | ||
| 372 | # CONFIG_IPX is not set | ||
| 373 | # CONFIG_ATALK is not set | ||
| 374 | # CONFIG_X25 is not set | ||
| 375 | # CONFIG_LAPB is not set | ||
| 376 | # CONFIG_ECONET is not set | ||
| 377 | # CONFIG_WAN_ROUTER is not set | ||
| 378 | # CONFIG_PHONET is not set | ||
| 379 | # CONFIG_IEEE802154 is not set | ||
| 380 | # CONFIG_NET_SCHED is not set | ||
| 381 | # CONFIG_DCB is not set | ||
| 382 | |||
| 383 | # | ||
| 384 | # Network testing | ||
| 385 | # | ||
| 386 | # CONFIG_NET_PKTGEN is not set | ||
| 387 | # CONFIG_NET_DROP_MONITOR is not set | ||
| 388 | # CONFIG_HAMRADIO is not set | ||
| 389 | # CONFIG_CAN is not set | ||
| 390 | # CONFIG_IRDA is not set | ||
| 391 | CONFIG_BT=y | ||
| 392 | CONFIG_BT_L2CAP=y | ||
| 393 | # CONFIG_BT_SCO is not set | ||
| 394 | CONFIG_BT_RFCOMM=y | ||
| 395 | # CONFIG_BT_RFCOMM_TTY is not set | ||
| 396 | CONFIG_BT_BNEP=y | ||
| 397 | CONFIG_BT_BNEP_MC_FILTER=y | ||
| 398 | # CONFIG_BT_BNEP_PROTO_FILTER is not set | ||
| 399 | CONFIG_BT_HIDP=y | ||
| 400 | |||
| 401 | # | ||
| 402 | # Bluetooth device drivers | ||
| 403 | # | ||
| 404 | # CONFIG_BT_HCIBTSDIO is not set | ||
| 405 | # CONFIG_BT_HCIUART is not set | ||
| 406 | # CONFIG_BT_HCIVHCI is not set | ||
| 407 | # CONFIG_BT_MRVL is not set | ||
| 408 | # CONFIG_AF_RXRPC is not set | ||
| 409 | CONFIG_WIRELESS=y | ||
| 410 | CONFIG_CFG80211=y | ||
| 411 | # CONFIG_NL80211_TESTMODE is not set | ||
| 412 | # CONFIG_CFG80211_DEVELOPER_WARNINGS is not set | ||
| 413 | # CONFIG_CFG80211_REG_DEBUG is not set | ||
| 414 | CONFIG_CFG80211_DEFAULT_PS=y | ||
| 415 | CONFIG_CFG80211_DEFAULT_PS_VALUE=1 | ||
| 416 | # CONFIG_CFG80211_DEBUGFS is not set | ||
| 417 | CONFIG_WIRELESS_OLD_REGULATORY=y | ||
| 418 | CONFIG_WIRELESS_EXT=y | ||
| 419 | CONFIG_WIRELESS_EXT_SYSFS=y | ||
| 420 | # CONFIG_LIB80211 is not set | ||
| 421 | CONFIG_MAC80211=y | ||
| 422 | # CONFIG_MAC80211_RC_PID is not set | ||
| 423 | CONFIG_MAC80211_RC_MINSTREL=y | ||
| 424 | # CONFIG_MAC80211_RC_DEFAULT_PID is not set | ||
| 425 | CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y | ||
| 426 | CONFIG_MAC80211_RC_DEFAULT="minstrel" | ||
| 427 | # CONFIG_MAC80211_MESH is not set | ||
| 428 | # CONFIG_MAC80211_LEDS is not set | ||
| 429 | # CONFIG_MAC80211_DEBUGFS is not set | ||
| 430 | # CONFIG_MAC80211_DEBUG_MENU is not set | ||
| 431 | # CONFIG_WIMAX is not set | ||
| 432 | # CONFIG_RFKILL is not set | ||
| 433 | # CONFIG_NET_9P is not set | ||
| 434 | |||
| 435 | # | ||
| 436 | # Device Drivers | ||
| 437 | # | ||
| 438 | |||
| 439 | # | ||
| 440 | # Generic Driver Options | ||
| 441 | # | ||
| 442 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
| 443 | # CONFIG_DEVTMPFS is not set | ||
| 444 | # CONFIG_STANDALONE is not set | ||
| 445 | CONFIG_PREVENT_FIRMWARE_BUILD=y | ||
| 446 | CONFIG_FW_LOADER=y | ||
| 447 | # CONFIG_FIRMWARE_IN_KERNEL is not set | ||
| 448 | CONFIG_EXTRA_FIRMWARE="" | ||
| 449 | # CONFIG_DEBUG_DRIVER is not set | ||
| 450 | # CONFIG_DEBUG_DEVRES is not set | ||
| 451 | # CONFIG_SYS_HYPERVISOR is not set | ||
| 452 | # CONFIG_CONNECTOR is not set | ||
| 453 | # CONFIG_MTD is not set | ||
| 454 | CONFIG_OF_DEVICE=y | ||
| 455 | CONFIG_OF_GPIO=y | ||
| 456 | CONFIG_OF_I2C=y | ||
| 457 | # CONFIG_PARPORT is not set | ||
| 458 | CONFIG_BLK_DEV=y | ||
| 459 | # CONFIG_BLK_DEV_FD is not set | ||
| 460 | # CONFIG_BLK_DEV_COW_COMMON is not set | ||
| 461 | CONFIG_BLK_DEV_LOOP=y | ||
| 462 | # CONFIG_BLK_DEV_CRYPTOLOOP is not set | ||
| 463 | # CONFIG_BLK_DEV_NBD is not set | ||
| 464 | CONFIG_BLK_DEV_RAM=y | ||
| 465 | CONFIG_BLK_DEV_RAM_COUNT=2 | ||
| 466 | CONFIG_BLK_DEV_RAM_SIZE=4096 | ||
| 467 | # CONFIG_BLK_DEV_XIP is not set | ||
| 468 | # CONFIG_CDROM_PKTCDVD is not set | ||
| 469 | # CONFIG_ATA_OVER_ETH is not set | ||
| 470 | # CONFIG_BLK_DEV_HD is not set | ||
| 471 | CONFIG_MISC_DEVICES=y | ||
| 472 | # CONFIG_ICS932S401 is not set | ||
| 473 | # CONFIG_ENCLOSURE_SERVICES is not set | ||
| 474 | # CONFIG_ISL29003 is not set | ||
| 475 | # CONFIG_C2PORT is not set | ||
| 476 | |||
| 477 | # | ||
| 478 | # EEPROM support | ||
| 479 | # | ||
| 480 | # CONFIG_EEPROM_AT24 is not set | ||
| 481 | # CONFIG_EEPROM_LEGACY is not set | ||
| 482 | # CONFIG_EEPROM_MAX6875 is not set | ||
| 483 | # CONFIG_EEPROM_93CX6 is not set | ||
| 484 | CONFIG_HAVE_IDE=y | ||
| 485 | # CONFIG_IDE is not set | ||
| 486 | |||
| 487 | # | ||
| 488 | # SCSI device support | ||
| 489 | # | ||
| 490 | # CONFIG_RAID_ATTRS is not set | ||
| 491 | CONFIG_SCSI=y | ||
| 492 | CONFIG_SCSI_DMA=y | ||
| 493 | # CONFIG_SCSI_TGT is not set | ||
| 494 | # CONFIG_SCSI_NETLINK is not set | ||
| 495 | CONFIG_SCSI_PROC_FS=y | ||
| 496 | |||
| 497 | # | ||
| 498 | # SCSI support type (disk, tape, CD-ROM) | ||
| 499 | # | ||
| 500 | CONFIG_BLK_DEV_SD=y | ||
| 501 | # CONFIG_CHR_DEV_ST is not set | ||
| 502 | # CONFIG_CHR_DEV_OSST is not set | ||
| 503 | # CONFIG_BLK_DEV_SR is not set | ||
| 504 | # CONFIG_CHR_DEV_SG is not set | ||
| 505 | # CONFIG_CHR_DEV_SCH is not set | ||
| 506 | CONFIG_SCSI_MULTI_LUN=y | ||
| 507 | # CONFIG_SCSI_CONSTANTS is not set | ||
| 508 | # CONFIG_SCSI_LOGGING is not set | ||
| 509 | # CONFIG_SCSI_SCAN_ASYNC is not set | ||
| 510 | CONFIG_SCSI_WAIT_SCAN=m | ||
| 511 | |||
| 512 | # | ||
| 513 | # SCSI Transports | ||
| 514 | # | ||
| 515 | # CONFIG_SCSI_SPI_ATTRS is not set | ||
| 516 | # CONFIG_SCSI_FC_ATTRS is not set | ||
| 517 | # CONFIG_SCSI_ISCSI_ATTRS is not set | ||
| 518 | # CONFIG_SCSI_SAS_ATTRS is not set | ||
| 519 | # CONFIG_SCSI_SAS_LIBSAS is not set | ||
| 520 | # CONFIG_SCSI_SRP_ATTRS is not set | ||
| 521 | CONFIG_SCSI_LOWLEVEL=y | ||
| 522 | # CONFIG_ISCSI_TCP is not set | ||
| 523 | # CONFIG_LIBFC is not set | ||
| 524 | # CONFIG_LIBFCOE is not set | ||
| 525 | # CONFIG_SCSI_DEBUG is not set | ||
| 526 | # CONFIG_SCSI_DH is not set | ||
| 527 | # CONFIG_SCSI_OSD_INITIATOR is not set | ||
| 528 | # CONFIG_ATA is not set | ||
| 529 | # CONFIG_MD is not set | ||
| 530 | # CONFIG_MACINTOSH_DRIVERS is not set | ||
| 531 | CONFIG_NETDEVICES=y | ||
| 532 | # CONFIG_DUMMY is not set | ||
| 533 | # CONFIG_BONDING is not set | ||
| 534 | # CONFIG_MACVLAN is not set | ||
| 535 | # CONFIG_EQUALIZER is not set | ||
| 536 | # CONFIG_TUN is not set | ||
| 537 | # CONFIG_VETH is not set | ||
| 538 | # CONFIG_PHYLIB is not set | ||
| 539 | CONFIG_NET_ETHERNET=y | ||
| 540 | CONFIG_MII=y | ||
| 541 | # CONFIG_ETHOC is not set | ||
| 542 | # CONFIG_DNET is not set | ||
| 543 | # CONFIG_IBM_NEW_EMAC_ZMII is not set | ||
| 544 | # CONFIG_IBM_NEW_EMAC_RGMII is not set | ||
| 545 | # CONFIG_IBM_NEW_EMAC_TAH is not set | ||
| 546 | # CONFIG_IBM_NEW_EMAC_EMAC4 is not set | ||
| 547 | # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set | ||
| 548 | # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set | ||
| 549 | # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set | ||
| 550 | # CONFIG_B44 is not set | ||
| 551 | # CONFIG_KS8842 is not set | ||
| 552 | # CONFIG_KS8851_MLL is not set | ||
| 553 | # CONFIG_XILINX_EMACLITE is not set | ||
| 554 | # CONFIG_NETDEV_1000 is not set | ||
| 555 | # CONFIG_NETDEV_10000 is not set | ||
| 556 | CONFIG_WLAN=y | ||
| 557 | # CONFIG_WLAN_PRE80211 is not set | ||
| 558 | CONFIG_WLAN_80211=y | ||
| 559 | # CONFIG_LIBERTAS is not set | ||
| 560 | # CONFIG_LIBERTAS_THINFIRM is not set | ||
| 561 | # CONFIG_MAC80211_HWSIM is not set | ||
| 562 | # CONFIG_P54_COMMON is not set | ||
| 563 | # CONFIG_ATH_COMMON is not set | ||
| 564 | # CONFIG_HOSTAP is not set | ||
| 565 | CONFIG_B43=y | ||
| 566 | CONFIG_B43_SDIO=y | ||
| 567 | CONFIG_B43_PIO=y | ||
| 568 | # CONFIG_B43_PHY_LP is not set | ||
| 569 | CONFIG_B43_DEBUG=y | ||
| 570 | # CONFIG_B43_FORCE_PIO is not set | ||
| 571 | # CONFIG_B43LEGACY is not set | ||
| 572 | # CONFIG_RT2X00 is not set | ||
| 573 | # CONFIG_WL12XX is not set | ||
| 574 | # CONFIG_IWM is not set | ||
| 575 | |||
| 576 | # | ||
| 577 | # Enable WiMAX (Networking options) to see the WiMAX drivers | ||
| 578 | # | ||
| 579 | # CONFIG_WAN is not set | ||
| 580 | # CONFIG_PPP is not set | ||
| 581 | # CONFIG_SLIP is not set | ||
| 582 | # CONFIG_NETCONSOLE is not set | ||
| 583 | # CONFIG_NETPOLL is not set | ||
| 584 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
| 585 | # CONFIG_ISDN is not set | ||
| 586 | # CONFIG_PHONE is not set | ||
| 587 | |||
| 588 | # | ||
| 589 | # Input device support | ||
| 590 | # | ||
| 591 | CONFIG_INPUT=y | ||
| 592 | CONFIG_INPUT_FF_MEMLESS=m | ||
| 593 | # CONFIG_INPUT_POLLDEV is not set | ||
| 594 | |||
| 595 | # | ||
| 596 | # Userland interfaces | ||
| 597 | # | ||
| 598 | CONFIG_INPUT_MOUSEDEV=y | ||
| 599 | # CONFIG_INPUT_MOUSEDEV_PSAUX is not set | ||
| 600 | CONFIG_INPUT_MOUSEDEV_SCREEN_X=640 | ||
| 601 | CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480 | ||
| 602 | CONFIG_INPUT_JOYDEV=y | ||
| 603 | CONFIG_INPUT_EVDEV=y | ||
| 604 | # CONFIG_INPUT_EVBUG is not set | ||
| 605 | |||
| 606 | # | ||
| 607 | # Input Device Drivers | ||
| 608 | # | ||
| 609 | CONFIG_INPUT_KEYBOARD=y | ||
| 610 | # CONFIG_KEYBOARD_ADP5588 is not set | ||
| 611 | # CONFIG_KEYBOARD_ATKBD is not set | ||
| 612 | # CONFIG_QT2160 is not set | ||
| 613 | # CONFIG_KEYBOARD_LKKBD is not set | ||
| 614 | # CONFIG_KEYBOARD_GPIO is not set | ||
| 615 | # CONFIG_KEYBOARD_MATRIX is not set | ||
| 616 | # CONFIG_KEYBOARD_MAX7359 is not set | ||
| 617 | # CONFIG_KEYBOARD_NEWTON is not set | ||
| 618 | # CONFIG_KEYBOARD_OPENCORES is not set | ||
| 619 | # CONFIG_KEYBOARD_STOWAWAY is not set | ||
| 620 | # CONFIG_KEYBOARD_SUNKBD is not set | ||
| 621 | # CONFIG_KEYBOARD_XTKBD is not set | ||
| 622 | CONFIG_INPUT_MOUSE=y | ||
| 623 | # CONFIG_MOUSE_PS2 is not set | ||
| 624 | # CONFIG_MOUSE_SERIAL is not set | ||
| 625 | # CONFIG_MOUSE_VSXXXAA is not set | ||
| 626 | # CONFIG_MOUSE_GPIO is not set | ||
| 627 | # CONFIG_MOUSE_SYNAPTICS_I2C is not set | ||
| 628 | CONFIG_INPUT_JOYSTICK=y | ||
| 629 | # CONFIG_JOYSTICK_ANALOG is not set | ||
| 630 | # CONFIG_JOYSTICK_A3D is not set | ||
| 631 | # CONFIG_JOYSTICK_ADI is not set | ||
| 632 | # CONFIG_JOYSTICK_COBRA is not set | ||
| 633 | # CONFIG_JOYSTICK_GF2K is not set | ||
| 634 | # CONFIG_JOYSTICK_GRIP is not set | ||
| 635 | # CONFIG_JOYSTICK_GRIP_MP is not set | ||
| 636 | # CONFIG_JOYSTICK_GUILLEMOT is not set | ||
| 637 | # CONFIG_JOYSTICK_INTERACT is not set | ||
| 638 | # CONFIG_JOYSTICK_SIDEWINDER is not set | ||
| 639 | # CONFIG_JOYSTICK_TMDC is not set | ||
| 640 | # CONFIG_JOYSTICK_IFORCE is not set | ||
| 641 | # CONFIG_JOYSTICK_WARRIOR is not set | ||
| 642 | # CONFIG_JOYSTICK_MAGELLAN is not set | ||
| 643 | # CONFIG_JOYSTICK_SPACEORB is not set | ||
| 644 | # CONFIG_JOYSTICK_SPACEBALL is not set | ||
| 645 | # CONFIG_JOYSTICK_STINGER is not set | ||
| 646 | # CONFIG_JOYSTICK_TWIDJOY is not set | ||
| 647 | # CONFIG_JOYSTICK_ZHENHUA is not set | ||
| 648 | # CONFIG_JOYSTICK_JOYDUMP is not set | ||
| 649 | # CONFIG_INPUT_TABLET is not set | ||
| 650 | # CONFIG_INPUT_TOUCHSCREEN is not set | ||
| 651 | CONFIG_INPUT_MISC=y | ||
| 652 | CONFIG_INPUT_UINPUT=y | ||
| 653 | # CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set | ||
| 654 | |||
| 655 | # | ||
| 656 | # Hardware I/O ports | ||
| 657 | # | ||
| 658 | CONFIG_SERIO=y | ||
| 659 | # CONFIG_SERIO_I8042 is not set | ||
| 660 | # CONFIG_SERIO_SERPORT is not set | ||
| 661 | # CONFIG_SERIO_LIBPS2 is not set | ||
| 662 | # CONFIG_SERIO_RAW is not set | ||
| 663 | # CONFIG_SERIO_XILINX_XPS_PS2 is not set | ||
| 664 | # CONFIG_GAMEPORT is not set | ||
| 665 | |||
| 666 | # | ||
| 667 | # Character devices | ||
| 668 | # | ||
| 669 | CONFIG_VT=y | ||
| 670 | CONFIG_CONSOLE_TRANSLATIONS=y | ||
| 671 | CONFIG_VT_CONSOLE=y | ||
| 672 | CONFIG_HW_CONSOLE=y | ||
| 673 | # CONFIG_VT_HW_CONSOLE_BINDING is not set | ||
| 674 | # CONFIG_DEVKMEM is not set | ||
| 675 | # CONFIG_SERIAL_NONSTANDARD is not set | ||
| 676 | |||
| 677 | # | ||
| 678 | # Serial drivers | ||
| 679 | # | ||
| 680 | # CONFIG_SERIAL_8250 is not set | ||
| 681 | |||
| 682 | # | ||
| 683 | # Non-8250 serial port support | ||
| 684 | # | ||
| 685 | # CONFIG_SERIAL_UARTLITE is not set | ||
| 686 | CONFIG_UNIX98_PTYS=y | ||
| 687 | # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set | ||
| 688 | CONFIG_LEGACY_PTYS=y | ||
| 689 | CONFIG_LEGACY_PTY_COUNT=64 | ||
| 690 | # CONFIG_HVC_UDBG is not set | ||
| 691 | # CONFIG_IPMI_HANDLER is not set | ||
| 692 | # CONFIG_HW_RANDOM is not set | ||
| 693 | CONFIG_NVRAM=y | ||
| 694 | # CONFIG_R3964 is not set | ||
| 695 | # CONFIG_RAW_DRIVER is not set | ||
| 696 | # CONFIG_TCG_TPM is not set | ||
| 697 | CONFIG_I2C=y | ||
| 698 | CONFIG_I2C_BOARDINFO=y | ||
| 699 | CONFIG_I2C_COMPAT=y | ||
| 700 | CONFIG_I2C_CHARDEV=y | ||
| 701 | CONFIG_I2C_HELPER_AUTO=y | ||
| 702 | CONFIG_I2C_ALGOBIT=y | ||
| 703 | |||
| 704 | # | ||
| 705 | # I2C Hardware Bus support | ||
| 706 | # | ||
| 707 | |||
| 708 | # | ||
| 709 | # I2C system bus drivers (mostly embedded / system-on-chip) | ||
| 710 | # | ||
| 711 | CONFIG_I2C_GPIO=y | ||
| 712 | # CONFIG_I2C_MPC is not set | ||
| 713 | # CONFIG_I2C_OCORES is not set | ||
| 714 | # CONFIG_I2C_SIMTEC is not set | ||
| 715 | |||
| 716 | # | ||
| 717 | # External I2C/SMBus adapter drivers | ||
| 718 | # | ||
| 719 | # CONFIG_I2C_PARPORT_LIGHT is not set | ||
| 720 | # CONFIG_I2C_TAOS_EVM is not set | ||
| 721 | |||
| 722 | # | ||
| 723 | # Other I2C/SMBus bus drivers | ||
| 724 | # | ||
| 725 | # CONFIG_I2C_PCA_PLATFORM is not set | ||
| 726 | # CONFIG_I2C_STUB is not set | ||
| 727 | |||
| 728 | # | ||
| 729 | # Miscellaneous I2C Chip support | ||
| 730 | # | ||
| 731 | # CONFIG_DS1682 is not set | ||
| 732 | # CONFIG_SENSORS_TSL2550 is not set | ||
| 733 | # CONFIG_I2C_DEBUG_CORE is not set | ||
| 734 | # CONFIG_I2C_DEBUG_ALGO is not set | ||
| 735 | # CONFIG_I2C_DEBUG_BUS is not set | ||
| 736 | # CONFIG_I2C_DEBUG_CHIP is not set | ||
| 737 | # CONFIG_SPI is not set | ||
| 738 | |||
| 739 | # | ||
| 740 | # PPS support | ||
| 741 | # | ||
| 742 | # CONFIG_PPS is not set | ||
| 743 | CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y | ||
| 744 | CONFIG_GPIOLIB=y | ||
| 745 | # CONFIG_DEBUG_GPIO is not set | ||
| 746 | CONFIG_GPIO_SYSFS=y | ||
| 747 | |||
| 748 | # | ||
| 749 | # Memory mapped GPIO expanders: | ||
| 750 | # | ||
| 751 | # CONFIG_GPIO_XILINX is not set | ||
| 752 | |||
| 753 | # | ||
| 754 | # I2C GPIO expanders: | ||
| 755 | # | ||
| 756 | # CONFIG_GPIO_MAX732X is not set | ||
| 757 | # CONFIG_GPIO_PCA953X is not set | ||
| 758 | # CONFIG_GPIO_PCF857X is not set | ||
| 759 | |||
| 760 | # | ||
| 761 | # PCI GPIO expanders: | ||
| 762 | # | ||
| 763 | |||
| 764 | # | ||
| 765 | # SPI GPIO expanders: | ||
| 766 | # | ||
| 767 | |||
| 768 | # | ||
| 769 | # AC97 GPIO expanders: | ||
| 770 | # | ||
| 771 | # CONFIG_W1 is not set | ||
| 772 | # CONFIG_POWER_SUPPLY is not set | ||
| 773 | # CONFIG_HWMON is not set | ||
| 774 | # CONFIG_THERMAL is not set | ||
| 775 | # CONFIG_WATCHDOG is not set | ||
| 776 | CONFIG_SSB_POSSIBLE=y | ||
| 777 | |||
| 778 | # | ||
| 779 | # Sonics Silicon Backplane | ||
| 780 | # | ||
| 781 | CONFIG_SSB=y | ||
| 782 | CONFIG_SSB_BLOCKIO=y | ||
| 783 | CONFIG_SSB_SDIOHOST_POSSIBLE=y | ||
| 784 | CONFIG_SSB_SDIOHOST=y | ||
| 785 | # CONFIG_SSB_SILENT is not set | ||
| 786 | CONFIG_SSB_DEBUG=y | ||
| 787 | |||
| 788 | # | ||
| 789 | # Multifunction device drivers | ||
| 790 | # | ||
| 791 | # CONFIG_MFD_CORE is not set | ||
| 792 | # CONFIG_MFD_SM501 is not set | ||
| 793 | # CONFIG_HTC_PASIC3 is not set | ||
| 794 | # CONFIG_TPS65010 is not set | ||
| 795 | # CONFIG_TWL4030_CORE is not set | ||
| 796 | # CONFIG_MFD_TMIO is not set | ||
| 797 | # CONFIG_PMIC_DA903X is not set | ||
| 798 | # CONFIG_MFD_WM8400 is not set | ||
| 799 | # CONFIG_MFD_WM831X is not set | ||
| 800 | # CONFIG_MFD_WM8350_I2C is not set | ||
| 801 | # CONFIG_MFD_PCF50633 is not set | ||
| 802 | # CONFIG_AB3100_CORE is not set | ||
| 803 | # CONFIG_REGULATOR is not set | ||
| 804 | # CONFIG_MEDIA_SUPPORT is not set | ||
| 805 | |||
| 806 | # | ||
| 807 | # Graphics support | ||
| 808 | # | ||
| 809 | # CONFIG_VGASTATE is not set | ||
| 810 | # CONFIG_VIDEO_OUTPUT_CONTROL is not set | ||
| 811 | CONFIG_FB=y | ||
| 812 | # CONFIG_FIRMWARE_EDID is not set | ||
| 813 | # CONFIG_FB_DDC is not set | ||
| 814 | # CONFIG_FB_BOOT_VESA_SUPPORT is not set | ||
| 815 | # CONFIG_FB_CFB_FILLRECT is not set | ||
| 816 | # CONFIG_FB_CFB_COPYAREA is not set | ||
| 817 | # CONFIG_FB_CFB_IMAGEBLIT is not set | ||
| 818 | # CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set | ||
| 819 | # CONFIG_FB_SYS_FILLRECT is not set | ||
| 820 | # CONFIG_FB_SYS_COPYAREA is not set | ||
| 821 | # CONFIG_FB_SYS_IMAGEBLIT is not set | ||
| 822 | # CONFIG_FB_FOREIGN_ENDIAN is not set | ||
| 823 | # CONFIG_FB_SYS_FOPS is not set | ||
| 824 | # CONFIG_FB_SVGALIB is not set | ||
| 825 | # CONFIG_FB_MACMODES is not set | ||
| 826 | # CONFIG_FB_BACKLIGHT is not set | ||
| 827 | # CONFIG_FB_MODE_HELPERS is not set | ||
| 828 | # CONFIG_FB_TILEBLITTING is not set | ||
| 829 | |||
| 830 | # | ||
| 831 | # Frame buffer hardware drivers | ||
| 832 | # | ||
| 833 | # CONFIG_FB_OF is not set | ||
| 834 | # CONFIG_FB_VGA16 is not set | ||
| 835 | # CONFIG_FB_S1D13XXX is not set | ||
| 836 | # CONFIG_FB_IBM_GXT4500 is not set | ||
| 837 | # CONFIG_FB_VIRTUAL is not set | ||
| 838 | # CONFIG_FB_METRONOME is not set | ||
| 839 | # CONFIG_FB_MB862XX is not set | ||
| 840 | # CONFIG_FB_BROADSHEET is not set | ||
| 841 | # CONFIG_BACKLIGHT_LCD_SUPPORT is not set | ||
| 842 | |||
| 843 | # | ||
| 844 | # Display device support | ||
| 845 | # | ||
| 846 | # CONFIG_DISPLAY_SUPPORT is not set | ||
| 847 | |||
| 848 | # | ||
| 849 | # Console display driver support | ||
| 850 | # | ||
| 851 | # CONFIG_VGA_CONSOLE is not set | ||
| 852 | CONFIG_DUMMY_CONSOLE=y | ||
| 853 | CONFIG_FRAMEBUFFER_CONSOLE=y | ||
| 854 | # CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set | ||
| 855 | # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set | ||
| 856 | # CONFIG_FONTS is not set | ||
| 857 | CONFIG_FONT_8x8=y | ||
| 858 | CONFIG_FONT_8x16=y | ||
| 859 | # CONFIG_LOGO is not set | ||
| 860 | CONFIG_SOUND=y | ||
| 861 | CONFIG_SOUND_OSS_CORE=y | ||
| 862 | CONFIG_SOUND_OSS_CORE_PRECLAIM=y | ||
| 863 | CONFIG_SND=y | ||
| 864 | CONFIG_SND_TIMER=y | ||
| 865 | CONFIG_SND_PCM=y | ||
| 866 | CONFIG_SND_SEQUENCER=y | ||
| 867 | # CONFIG_SND_SEQ_DUMMY is not set | ||
| 868 | CONFIG_SND_OSSEMUL=y | ||
| 869 | CONFIG_SND_MIXER_OSS=y | ||
| 870 | CONFIG_SND_PCM_OSS=y | ||
| 871 | CONFIG_SND_PCM_OSS_PLUGINS=y | ||
| 872 | CONFIG_SND_SEQUENCER_OSS=y | ||
| 873 | # CONFIG_SND_DYNAMIC_MINORS is not set | ||
| 874 | CONFIG_SND_SUPPORT_OLD_API=y | ||
| 875 | # CONFIG_SND_VERBOSE_PROCFS is not set | ||
| 876 | # CONFIG_SND_VERBOSE_PRINTK is not set | ||
| 877 | # CONFIG_SND_DEBUG is not set | ||
| 878 | # CONFIG_SND_RAWMIDI_SEQ is not set | ||
| 879 | # CONFIG_SND_OPL3_LIB_SEQ is not set | ||
| 880 | # CONFIG_SND_OPL4_LIB_SEQ is not set | ||
| 881 | # CONFIG_SND_SBAWE_SEQ is not set | ||
| 882 | # CONFIG_SND_EMU10K1_SEQ is not set | ||
| 883 | CONFIG_SND_DRIVERS=y | ||
| 884 | # CONFIG_SND_DUMMY is not set | ||
| 885 | # CONFIG_SND_VIRMIDI is not set | ||
| 886 | # CONFIG_SND_MTPAV is not set | ||
| 887 | # CONFIG_SND_SERIAL_U16550 is not set | ||
| 888 | # CONFIG_SND_MPU401 is not set | ||
| 889 | CONFIG_SND_PPC=y | ||
| 890 | # CONFIG_SND_SOC is not set | ||
| 891 | # CONFIG_SOUND_PRIME is not set | ||
| 892 | CONFIG_HID_SUPPORT=y | ||
| 893 | CONFIG_HID=y | ||
| 894 | # CONFIG_HIDRAW is not set | ||
| 895 | # CONFIG_HID_PID is not set | ||
| 896 | |||
| 897 | # | ||
| 898 | # Special HID drivers | ||
| 899 | # | ||
| 900 | CONFIG_HID_APPLE=m | ||
| 901 | CONFIG_HID_WACOM=m | ||
| 902 | CONFIG_USB_SUPPORT=y | ||
| 903 | # CONFIG_USB_ARCH_HAS_HCD is not set | ||
| 904 | # CONFIG_USB_ARCH_HAS_OHCI is not set | ||
| 905 | # CONFIG_USB_ARCH_HAS_EHCI is not set | ||
| 906 | # CONFIG_USB_OTG_WHITELIST is not set | ||
| 907 | # CONFIG_USB_OTG_BLACKLIST_HUB is not set | ||
| 908 | |||
| 909 | # | ||
| 910 | # Enable Host or Gadget support to see Inventra options | ||
| 911 | # | ||
| 912 | |||
| 913 | # | ||
| 914 | # NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may | ||
| 915 | # | ||
| 916 | # CONFIG_USB_GADGET is not set | ||
| 917 | |||
| 918 | # | ||
| 919 | # OTG and related infrastructure | ||
| 920 | # | ||
| 921 | CONFIG_MMC=y | ||
| 922 | # CONFIG_MMC_DEBUG is not set | ||
| 923 | # CONFIG_MMC_UNSAFE_RESUME is not set | ||
| 924 | |||
| 925 | # | ||
| 926 | # MMC/SD/SDIO Card Drivers | ||
| 927 | # | ||
| 928 | CONFIG_MMC_BLOCK=y | ||
| 929 | CONFIG_MMC_BLOCK_BOUNCE=y | ||
| 930 | # CONFIG_SDIO_UART is not set | ||
| 931 | # CONFIG_MMC_TEST is not set | ||
| 932 | |||
| 933 | # | ||
| 934 | # MMC/SD/SDIO Host Controller Drivers | ||
| 935 | # | ||
| 936 | CONFIG_MMC_SDHCI=y | ||
| 937 | # CONFIG_MMC_SDHCI_OF is not set | ||
| 938 | # CONFIG_MMC_SDHCI_PLTFM is not set | ||
| 939 | # CONFIG_MMC_WBSD is not set | ||
| 940 | # CONFIG_MMC_AT91 is not set | ||
| 941 | # CONFIG_MMC_ATMELMCI is not set | ||
| 942 | # CONFIG_MEMSTICK is not set | ||
| 943 | # CONFIG_NEW_LEDS is not set | ||
| 944 | # CONFIG_ACCESSIBILITY is not set | ||
| 945 | # CONFIG_EDAC is not set | ||
| 946 | CONFIG_RTC_LIB=y | ||
| 947 | CONFIG_RTC_CLASS=y | ||
| 948 | CONFIG_RTC_HCTOSYS=y | ||
| 949 | CONFIG_RTC_HCTOSYS_DEVICE="rtc0" | ||
| 950 | # CONFIG_RTC_DEBUG is not set | ||
| 951 | |||
| 952 | # | ||
| 953 | # RTC interfaces | ||
| 954 | # | ||
| 955 | CONFIG_RTC_INTF_SYSFS=y | ||
| 956 | CONFIG_RTC_INTF_PROC=y | ||
| 957 | CONFIG_RTC_INTF_DEV=y | ||
| 958 | # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set | ||
| 959 | # CONFIG_RTC_DRV_TEST is not set | ||
| 960 | |||
| 961 | # | ||
| 962 | # I2C RTC drivers | ||
| 963 | # | ||
| 964 | # CONFIG_RTC_DRV_DS1307 is not set | ||
| 965 | # CONFIG_RTC_DRV_DS1374 is not set | ||
| 966 | # CONFIG_RTC_DRV_DS1672 is not set | ||
| 967 | # CONFIG_RTC_DRV_MAX6900 is not set | ||
| 968 | # CONFIG_RTC_DRV_RS5C372 is not set | ||
| 969 | # CONFIG_RTC_DRV_ISL1208 is not set | ||
| 970 | # CONFIG_RTC_DRV_X1205 is not set | ||
| 971 | # CONFIG_RTC_DRV_PCF8563 is not set | ||
| 972 | # CONFIG_RTC_DRV_PCF8583 is not set | ||
| 973 | # CONFIG_RTC_DRV_M41T80 is not set | ||
| 974 | # CONFIG_RTC_DRV_S35390A is not set | ||
| 975 | # CONFIG_RTC_DRV_FM3130 is not set | ||
| 976 | # CONFIG_RTC_DRV_RX8581 is not set | ||
| 977 | # CONFIG_RTC_DRV_RX8025 is not set | ||
| 978 | |||
| 979 | # | ||
| 980 | # SPI RTC drivers | ||
| 981 | # | ||
| 982 | |||
| 983 | # | ||
| 984 | # Platform RTC drivers | ||
| 985 | # | ||
| 986 | # CONFIG_RTC_DRV_CMOS is not set | ||
| 987 | # CONFIG_RTC_DRV_DS1286 is not set | ||
| 988 | # CONFIG_RTC_DRV_DS1511 is not set | ||
| 989 | # CONFIG_RTC_DRV_DS1553 is not set | ||
| 990 | # CONFIG_RTC_DRV_DS1742 is not set | ||
| 991 | # CONFIG_RTC_DRV_STK17TA8 is not set | ||
| 992 | # CONFIG_RTC_DRV_M48T86 is not set | ||
| 993 | # CONFIG_RTC_DRV_M48T35 is not set | ||
| 994 | # CONFIG_RTC_DRV_M48T59 is not set | ||
| 995 | # CONFIG_RTC_DRV_BQ4802 is not set | ||
| 996 | # CONFIG_RTC_DRV_V3020 is not set | ||
| 997 | |||
| 998 | # | ||
| 999 | # on-CPU RTC drivers | ||
| 1000 | # | ||
| 1001 | CONFIG_RTC_DRV_GENERIC=y | ||
| 1002 | # CONFIG_DMADEVICES is not set | ||
| 1003 | # CONFIG_AUXDISPLAY is not set | ||
| 1004 | # CONFIG_UIO is not set | ||
| 1005 | |||
| 1006 | # | ||
| 1007 | # TI VLYNQ | ||
| 1008 | # | ||
| 1009 | # CONFIG_STAGING is not set | ||
| 1010 | |||
| 1011 | # | ||
| 1012 | # File systems | ||
| 1013 | # | ||
| 1014 | CONFIG_EXT2_FS=y | ||
| 1015 | # CONFIG_EXT2_FS_XATTR is not set | ||
| 1016 | # CONFIG_EXT2_FS_XIP is not set | ||
| 1017 | CONFIG_EXT3_FS=y | ||
| 1018 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
| 1019 | # CONFIG_EXT3_FS_XATTR is not set | ||
| 1020 | # CONFIG_EXT4_FS is not set | ||
| 1021 | CONFIG_JBD=y | ||
| 1022 | # CONFIG_JBD_DEBUG is not set | ||
| 1023 | # CONFIG_REISERFS_FS is not set | ||
| 1024 | # CONFIG_JFS_FS is not set | ||
| 1025 | # CONFIG_FS_POSIX_ACL is not set | ||
| 1026 | # CONFIG_XFS_FS is not set | ||
| 1027 | # CONFIG_GFS2_FS is not set | ||
| 1028 | # CONFIG_OCFS2_FS is not set | ||
| 1029 | # CONFIG_BTRFS_FS is not set | ||
| 1030 | # CONFIG_NILFS2_FS is not set | ||
| 1031 | CONFIG_FILE_LOCKING=y | ||
| 1032 | CONFIG_FSNOTIFY=y | ||
| 1033 | CONFIG_DNOTIFY=y | ||
| 1034 | CONFIG_INOTIFY=y | ||
| 1035 | CONFIG_INOTIFY_USER=y | ||
| 1036 | # CONFIG_QUOTA is not set | ||
| 1037 | # CONFIG_AUTOFS_FS is not set | ||
| 1038 | # CONFIG_AUTOFS4_FS is not set | ||
| 1039 | CONFIG_FUSE_FS=m | ||
| 1040 | # CONFIG_CUSE is not set | ||
| 1041 | |||
| 1042 | # | ||
| 1043 | # Caches | ||
| 1044 | # | ||
| 1045 | # CONFIG_FSCACHE is not set | ||
| 1046 | |||
| 1047 | # | ||
| 1048 | # CD-ROM/DVD Filesystems | ||
| 1049 | # | ||
| 1050 | CONFIG_ISO9660_FS=y | ||
| 1051 | CONFIG_JOLIET=y | ||
| 1052 | # CONFIG_ZISOFS is not set | ||
| 1053 | # CONFIG_UDF_FS is not set | ||
| 1054 | |||
| 1055 | # | ||
| 1056 | # DOS/FAT/NT Filesystems | ||
| 1057 | # | ||
| 1058 | CONFIG_FAT_FS=y | ||
| 1059 | CONFIG_MSDOS_FS=y | ||
| 1060 | CONFIG_VFAT_FS=y | ||
| 1061 | CONFIG_FAT_DEFAULT_CODEPAGE=437 | ||
| 1062 | CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" | ||
| 1063 | # CONFIG_NTFS_FS is not set | ||
| 1064 | |||
| 1065 | # | ||
| 1066 | # Pseudo filesystems | ||
| 1067 | # | ||
| 1068 | CONFIG_PROC_FS=y | ||
| 1069 | CONFIG_PROC_KCORE=y | ||
| 1070 | CONFIG_PROC_SYSCTL=y | ||
| 1071 | # CONFIG_PROC_PAGE_MONITOR is not set | ||
| 1072 | CONFIG_SYSFS=y | ||
| 1073 | CONFIG_TMPFS=y | ||
| 1074 | # CONFIG_TMPFS_POSIX_ACL is not set | ||
| 1075 | # CONFIG_HUGETLB_PAGE is not set | ||
| 1076 | # CONFIG_CONFIGFS_FS is not set | ||
| 1077 | CONFIG_MISC_FILESYSTEMS=y | ||
| 1078 | # CONFIG_ADFS_FS is not set | ||
| 1079 | # CONFIG_AFFS_FS is not set | ||
| 1080 | # CONFIG_HFS_FS is not set | ||
| 1081 | # CONFIG_HFSPLUS_FS is not set | ||
| 1082 | # CONFIG_BEFS_FS is not set | ||
| 1083 | # CONFIG_BFS_FS is not set | ||
| 1084 | # CONFIG_EFS_FS is not set | ||
| 1085 | # CONFIG_CRAMFS is not set | ||
| 1086 | # CONFIG_SQUASHFS is not set | ||
| 1087 | # CONFIG_VXFS_FS is not set | ||
| 1088 | # CONFIG_MINIX_FS is not set | ||
| 1089 | # CONFIG_OMFS_FS is not set | ||
| 1090 | # CONFIG_HPFS_FS is not set | ||
| 1091 | # CONFIG_QNX4FS_FS is not set | ||
| 1092 | # CONFIG_ROMFS_FS is not set | ||
| 1093 | # CONFIG_SYSV_FS is not set | ||
| 1094 | # CONFIG_UFS_FS is not set | ||
| 1095 | CONFIG_NETWORK_FILESYSTEMS=y | ||
| 1096 | CONFIG_NFS_FS=y | ||
| 1097 | CONFIG_NFS_V3=y | ||
| 1098 | # CONFIG_NFS_V3_ACL is not set | ||
| 1099 | # CONFIG_NFS_V4 is not set | ||
| 1100 | CONFIG_ROOT_NFS=y | ||
| 1101 | # CONFIG_NFSD is not set | ||
| 1102 | CONFIG_LOCKD=y | ||
| 1103 | CONFIG_LOCKD_V4=y | ||
| 1104 | CONFIG_NFS_COMMON=y | ||
| 1105 | CONFIG_SUNRPC=y | ||
| 1106 | # CONFIG_RPCSEC_GSS_KRB5 is not set | ||
| 1107 | # CONFIG_RPCSEC_GSS_SPKM3 is not set | ||
| 1108 | # CONFIG_SMB_FS is not set | ||
| 1109 | CONFIG_CIFS=m | ||
| 1110 | # CONFIG_CIFS_STATS is not set | ||
| 1111 | # CONFIG_CIFS_WEAK_PW_HASH is not set | ||
| 1112 | # CONFIG_CIFS_XATTR is not set | ||
| 1113 | # CONFIG_CIFS_DEBUG2 is not set | ||
| 1114 | # CONFIG_CIFS_EXPERIMENTAL is not set | ||
| 1115 | # CONFIG_NCP_FS is not set | ||
| 1116 | # CONFIG_CODA_FS is not set | ||
| 1117 | # CONFIG_AFS_FS is not set | ||
| 1118 | |||
| 1119 | # | ||
| 1120 | # Partition Types | ||
| 1121 | # | ||
| 1122 | # CONFIG_PARTITION_ADVANCED is not set | ||
| 1123 | CONFIG_MSDOS_PARTITION=y | ||
| 1124 | CONFIG_NLS=y | ||
| 1125 | CONFIG_NLS_DEFAULT="iso8859-1" | ||
| 1126 | CONFIG_NLS_CODEPAGE_437=y | ||
| 1127 | # CONFIG_NLS_CODEPAGE_737 is not set | ||
| 1128 | # CONFIG_NLS_CODEPAGE_775 is not set | ||
| 1129 | # CONFIG_NLS_CODEPAGE_850 is not set | ||
| 1130 | # CONFIG_NLS_CODEPAGE_852 is not set | ||
| 1131 | # CONFIG_NLS_CODEPAGE_855 is not set | ||
| 1132 | # CONFIG_NLS_CODEPAGE_857 is not set | ||
| 1133 | # CONFIG_NLS_CODEPAGE_860 is not set | ||
| 1134 | # CONFIG_NLS_CODEPAGE_861 is not set | ||
| 1135 | # CONFIG_NLS_CODEPAGE_862 is not set | ||
| 1136 | # CONFIG_NLS_CODEPAGE_863 is not set | ||
| 1137 | # CONFIG_NLS_CODEPAGE_864 is not set | ||
| 1138 | # CONFIG_NLS_CODEPAGE_865 is not set | ||
| 1139 | # CONFIG_NLS_CODEPAGE_866 is not set | ||
| 1140 | # CONFIG_NLS_CODEPAGE_869 is not set | ||
| 1141 | # CONFIG_NLS_CODEPAGE_936 is not set | ||
| 1142 | # CONFIG_NLS_CODEPAGE_950 is not set | ||
| 1143 | # CONFIG_NLS_CODEPAGE_932 is not set | ||
| 1144 | # CONFIG_NLS_CODEPAGE_949 is not set | ||
| 1145 | # CONFIG_NLS_CODEPAGE_874 is not set | ||
| 1146 | # CONFIG_NLS_ISO8859_8 is not set | ||
| 1147 | # CONFIG_NLS_CODEPAGE_1250 is not set | ||
| 1148 | # CONFIG_NLS_CODEPAGE_1251 is not set | ||
| 1149 | # CONFIG_NLS_ASCII is not set | ||
| 1150 | CONFIG_NLS_ISO8859_1=y | ||
| 1151 | # CONFIG_NLS_ISO8859_2 is not set | ||
| 1152 | # CONFIG_NLS_ISO8859_3 is not set | ||
| 1153 | # CONFIG_NLS_ISO8859_4 is not set | ||
| 1154 | # CONFIG_NLS_ISO8859_5 is not set | ||
| 1155 | # CONFIG_NLS_ISO8859_6 is not set | ||
| 1156 | # CONFIG_NLS_ISO8859_7 is not set | ||
| 1157 | # CONFIG_NLS_ISO8859_9 is not set | ||
| 1158 | # CONFIG_NLS_ISO8859_13 is not set | ||
| 1159 | # CONFIG_NLS_ISO8859_14 is not set | ||
| 1160 | # CONFIG_NLS_ISO8859_15 is not set | ||
| 1161 | # CONFIG_NLS_KOI8_R is not set | ||
| 1162 | # CONFIG_NLS_KOI8_U is not set | ||
| 1163 | # CONFIG_NLS_UTF8 is not set | ||
| 1164 | # CONFIG_DLM is not set | ||
| 1165 | CONFIG_BINARY_PRINTF=y | ||
| 1166 | |||
| 1167 | # | ||
| 1168 | # Library routines | ||
| 1169 | # | ||
| 1170 | CONFIG_BITREVERSE=y | ||
| 1171 | CONFIG_GENERIC_FIND_LAST_BIT=y | ||
| 1172 | CONFIG_CRC_CCITT=y | ||
| 1173 | CONFIG_CRC16=y | ||
| 1174 | # CONFIG_CRC_T10DIF is not set | ||
| 1175 | # CONFIG_CRC_ITU_T is not set | ||
| 1176 | CONFIG_CRC32=y | ||
| 1177 | # CONFIG_CRC7 is not set | ||
| 1178 | # CONFIG_LIBCRC32C is not set | ||
| 1179 | CONFIG_ZLIB_INFLATE=y | ||
| 1180 | CONFIG_DECOMPRESS_GZIP=y | ||
| 1181 | CONFIG_HAS_IOMEM=y | ||
| 1182 | CONFIG_HAS_IOPORT=y | ||
| 1183 | CONFIG_HAS_DMA=y | ||
| 1184 | CONFIG_HAVE_LMB=y | ||
| 1185 | CONFIG_NLATTR=y | ||
| 1186 | CONFIG_GENERIC_ATOMIC64=y | ||
| 1187 | |||
| 1188 | # | ||
| 1189 | # Kernel hacking | ||
| 1190 | # | ||
| 1191 | CONFIG_PRINTK_TIME=y | ||
| 1192 | CONFIG_ENABLE_WARN_DEPRECATED=y | ||
| 1193 | CONFIG_ENABLE_MUST_CHECK=y | ||
| 1194 | CONFIG_FRAME_WARN=1024 | ||
| 1195 | CONFIG_MAGIC_SYSRQ=y | ||
| 1196 | # CONFIG_STRIP_ASM_SYMS is not set | ||
| 1197 | # CONFIG_UNUSED_SYMBOLS is not set | ||
| 1198 | CONFIG_DEBUG_FS=y | ||
| 1199 | # CONFIG_HEADERS_CHECK is not set | ||
| 1200 | CONFIG_DEBUG_KERNEL=y | ||
| 1201 | # CONFIG_DEBUG_SHIRQ is not set | ||
| 1202 | CONFIG_DETECT_SOFTLOCKUP=y | ||
| 1203 | # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set | ||
| 1204 | CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 | ||
| 1205 | # CONFIG_DETECT_HUNG_TASK is not set | ||
| 1206 | CONFIG_SCHED_DEBUG=y | ||
| 1207 | CONFIG_SCHEDSTATS=y | ||
| 1208 | # CONFIG_TIMER_STATS is not set | ||
| 1209 | # CONFIG_DEBUG_OBJECTS is not set | ||
| 1210 | # CONFIG_DEBUG_SLAB is not set | ||
| 1211 | # CONFIG_DEBUG_KMEMLEAK is not set | ||
| 1212 | CONFIG_DEBUG_PREEMPT=y | ||
| 1213 | # CONFIG_DEBUG_RT_MUTEXES is not set | ||
| 1214 | # CONFIG_RT_MUTEX_TESTER is not set | ||
| 1215 | CONFIG_DEBUG_SPINLOCK=y | ||
| 1216 | CONFIG_DEBUG_MUTEXES=y | ||
| 1217 | # CONFIG_DEBUG_LOCK_ALLOC is not set | ||
| 1218 | # CONFIG_PROVE_LOCKING is not set | ||
| 1219 | # CONFIG_LOCK_STAT is not set | ||
| 1220 | CONFIG_DEBUG_SPINLOCK_SLEEP=y | ||
| 1221 | # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set | ||
| 1222 | CONFIG_STACKTRACE=y | ||
| 1223 | # CONFIG_DEBUG_KOBJECT is not set | ||
| 1224 | CONFIG_DEBUG_BUGVERBOSE=y | ||
| 1225 | # CONFIG_DEBUG_INFO is not set | ||
| 1226 | # CONFIG_DEBUG_VM is not set | ||
| 1227 | # CONFIG_DEBUG_WRITECOUNT is not set | ||
| 1228 | # CONFIG_DEBUG_MEMORY_INIT is not set | ||
| 1229 | # CONFIG_DEBUG_LIST is not set | ||
| 1230 | # CONFIG_DEBUG_SG is not set | ||
| 1231 | # CONFIG_DEBUG_NOTIFIERS is not set | ||
| 1232 | # CONFIG_DEBUG_CREDENTIALS is not set | ||
| 1233 | # CONFIG_RCU_TORTURE_TEST is not set | ||
| 1234 | # CONFIG_RCU_CPU_STALL_DETECTOR is not set | ||
| 1235 | # CONFIG_BACKTRACE_SELF_TEST is not set | ||
| 1236 | # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set | ||
| 1237 | # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set | ||
| 1238 | # CONFIG_FAULT_INJECTION is not set | ||
| 1239 | CONFIG_LATENCYTOP=y | ||
| 1240 | CONFIG_SYSCTL_SYSCALL_CHECK=y | ||
| 1241 | # CONFIG_DEBUG_PAGEALLOC is not set | ||
| 1242 | CONFIG_NOP_TRACER=y | ||
| 1243 | CONFIG_HAVE_FUNCTION_TRACER=y | ||
| 1244 | CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y | ||
| 1245 | CONFIG_HAVE_DYNAMIC_FTRACE=y | ||
| 1246 | CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y | ||
| 1247 | CONFIG_TRACER_MAX_TRACE=y | ||
| 1248 | CONFIG_RING_BUFFER=y | ||
| 1249 | CONFIG_EVENT_TRACING=y | ||
| 1250 | CONFIG_CONTEXT_SWITCH_TRACER=y | ||
| 1251 | CONFIG_TRACING=y | ||
| 1252 | CONFIG_GENERIC_TRACER=y | ||
| 1253 | CONFIG_TRACING_SUPPORT=y | ||
| 1254 | CONFIG_FTRACE=y | ||
| 1255 | # CONFIG_FUNCTION_TRACER is not set | ||
| 1256 | # CONFIG_IRQSOFF_TRACER is not set | ||
| 1257 | # CONFIG_PREEMPT_TRACER is not set | ||
| 1258 | CONFIG_SCHED_TRACER=y | ||
| 1259 | CONFIG_BOOT_TRACER=y | ||
| 1260 | CONFIG_BRANCH_PROFILE_NONE=y | ||
| 1261 | # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set | ||
| 1262 | # CONFIG_PROFILE_ALL_BRANCHES is not set | ||
| 1263 | # CONFIG_STACK_TRACER is not set | ||
| 1264 | # CONFIG_KMEMTRACE is not set | ||
| 1265 | # CONFIG_WORKQUEUE_TRACER is not set | ||
| 1266 | CONFIG_BLK_DEV_IO_TRACE=y | ||
| 1267 | # CONFIG_FTRACE_STARTUP_TEST is not set | ||
| 1268 | # CONFIG_RING_BUFFER_BENCHMARK is not set | ||
| 1269 | # CONFIG_DYNAMIC_DEBUG is not set | ||
| 1270 | CONFIG_DMA_API_DEBUG=y | ||
| 1271 | # CONFIG_SAMPLES is not set | ||
| 1272 | CONFIG_HAVE_ARCH_KGDB=y | ||
| 1273 | # CONFIG_KGDB is not set | ||
| 1274 | # CONFIG_PPC_DISABLE_WERROR is not set | ||
| 1275 | CONFIG_PPC_WERROR=y | ||
| 1276 | CONFIG_PRINT_STACK_DEPTH=64 | ||
| 1277 | # CONFIG_DEBUG_STACKOVERFLOW is not set | ||
| 1278 | # CONFIG_DEBUG_STACK_USAGE is not set | ||
| 1279 | # CONFIG_PPC_EMULATED_STATS is not set | ||
| 1280 | # CONFIG_CODE_PATCHING_SELFTEST is not set | ||
| 1281 | # CONFIG_FTR_FIXUP_SELFTEST is not set | ||
| 1282 | # CONFIG_MSI_BITMAP_SELFTEST is not set | ||
| 1283 | # CONFIG_XMON is not set | ||
| 1284 | # CONFIG_IRQSTACKS is not set | ||
| 1285 | # CONFIG_VIRQ_DEBUG is not set | ||
| 1286 | # CONFIG_BDI_SWITCH is not set | ||
| 1287 | # CONFIG_BOOTX_TEXT is not set | ||
| 1288 | CONFIG_PPC_EARLY_DEBUG=y | ||
| 1289 | # CONFIG_PPC_EARLY_DEBUG_LPAR is not set | ||
| 1290 | # CONFIG_PPC_EARLY_DEBUG_G5 is not set | ||
| 1291 | # CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set | ||
| 1292 | # CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set | ||
| 1293 | # CONFIG_PPC_EARLY_DEBUG_MAPLE is not set | ||
| 1294 | # CONFIG_PPC_EARLY_DEBUG_ISERIES is not set | ||
| 1295 | # CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set | ||
| 1296 | # CONFIG_PPC_EARLY_DEBUG_BEAT is not set | ||
| 1297 | # CONFIG_PPC_EARLY_DEBUG_44x is not set | ||
| 1298 | # CONFIG_PPC_EARLY_DEBUG_40x is not set | ||
| 1299 | # CONFIG_PPC_EARLY_DEBUG_CPM is not set | ||
| 1300 | CONFIG_PPC_EARLY_DEBUG_USBGECKO=y | ||
| 1301 | |||
| 1302 | # | ||
| 1303 | # Security options | ||
| 1304 | # | ||
| 1305 | # CONFIG_KEYS is not set | ||
| 1306 | # CONFIG_SECURITY is not set | ||
| 1307 | # CONFIG_SECURITYFS is not set | ||
| 1308 | # CONFIG_SECURITY_FILE_CAPABILITIES is not set | ||
| 1309 | CONFIG_CRYPTO=y | ||
| 1310 | |||
| 1311 | # | ||
| 1312 | # Crypto core or helper | ||
| 1313 | # | ||
| 1314 | CONFIG_CRYPTO_ALGAPI=y | ||
| 1315 | CONFIG_CRYPTO_ALGAPI2=y | ||
| 1316 | CONFIG_CRYPTO_AEAD2=y | ||
| 1317 | CONFIG_CRYPTO_BLKCIPHER=y | ||
| 1318 | CONFIG_CRYPTO_BLKCIPHER2=y | ||
| 1319 | CONFIG_CRYPTO_HASH2=y | ||
| 1320 | CONFIG_CRYPTO_RNG2=y | ||
| 1321 | CONFIG_CRYPTO_PCOMP=y | ||
| 1322 | CONFIG_CRYPTO_MANAGER=y | ||
| 1323 | CONFIG_CRYPTO_MANAGER2=y | ||
| 1324 | # CONFIG_CRYPTO_GF128MUL is not set | ||
| 1325 | # CONFIG_CRYPTO_NULL is not set | ||
| 1326 | CONFIG_CRYPTO_WORKQUEUE=y | ||
| 1327 | # CONFIG_CRYPTO_CRYPTD is not set | ||
| 1328 | # CONFIG_CRYPTO_AUTHENC is not set | ||
| 1329 | # CONFIG_CRYPTO_TEST is not set | ||
| 1330 | |||
| 1331 | # | ||
| 1332 | # Authenticated Encryption with Associated Data | ||
| 1333 | # | ||
| 1334 | # CONFIG_CRYPTO_CCM is not set | ||
| 1335 | # CONFIG_CRYPTO_GCM is not set | ||
| 1336 | # CONFIG_CRYPTO_SEQIV is not set | ||
| 1337 | |||
| 1338 | # | ||
| 1339 | # Block modes | ||
| 1340 | # | ||
| 1341 | # CONFIG_CRYPTO_CBC is not set | ||
| 1342 | # CONFIG_CRYPTO_CTR is not set | ||
| 1343 | # CONFIG_CRYPTO_CTS is not set | ||
| 1344 | CONFIG_CRYPTO_ECB=y | ||
| 1345 | # CONFIG_CRYPTO_LRW is not set | ||
| 1346 | # CONFIG_CRYPTO_PCBC is not set | ||
| 1347 | # CONFIG_CRYPTO_XTS is not set | ||
| 1348 | |||
| 1349 | # | ||
| 1350 | # Hash modes | ||
| 1351 | # | ||
| 1352 | # CONFIG_CRYPTO_HMAC is not set | ||
| 1353 | # CONFIG_CRYPTO_XCBC is not set | ||
| 1354 | # CONFIG_CRYPTO_VMAC is not set | ||
| 1355 | |||
| 1356 | # | ||
| 1357 | # Digest | ||
| 1358 | # | ||
| 1359 | # CONFIG_CRYPTO_CRC32C is not set | ||
| 1360 | # CONFIG_CRYPTO_GHASH is not set | ||
| 1361 | # CONFIG_CRYPTO_MD4 is not set | ||
| 1362 | # CONFIG_CRYPTO_MD5 is not set | ||
| 1363 | # CONFIG_CRYPTO_MICHAEL_MIC is not set | ||
| 1364 | # CONFIG_CRYPTO_RMD128 is not set | ||
| 1365 | # CONFIG_CRYPTO_RMD160 is not set | ||
| 1366 | # CONFIG_CRYPTO_RMD256 is not set | ||
| 1367 | # CONFIG_CRYPTO_RMD320 is not set | ||
| 1368 | # CONFIG_CRYPTO_SHA1 is not set | ||
| 1369 | # CONFIG_CRYPTO_SHA256 is not set | ||
| 1370 | # CONFIG_CRYPTO_SHA512 is not set | ||
| 1371 | # CONFIG_CRYPTO_TGR192 is not set | ||
| 1372 | # CONFIG_CRYPTO_WP512 is not set | ||
| 1373 | |||
| 1374 | # | ||
| 1375 | # Ciphers | ||
| 1376 | # | ||
| 1377 | CONFIG_CRYPTO_AES=y | ||
| 1378 | # CONFIG_CRYPTO_ANUBIS is not set | ||
| 1379 | CONFIG_CRYPTO_ARC4=y | ||
| 1380 | # CONFIG_CRYPTO_BLOWFISH is not set | ||
| 1381 | # CONFIG_CRYPTO_CAMELLIA is not set | ||
| 1382 | # CONFIG_CRYPTO_CAST5 is not set | ||
| 1383 | # CONFIG_CRYPTO_CAST6 is not set | ||
| 1384 | # CONFIG_CRYPTO_DES is not set | ||
| 1385 | # CONFIG_CRYPTO_FCRYPT is not set | ||
| 1386 | # CONFIG_CRYPTO_KHAZAD is not set | ||
| 1387 | # CONFIG_CRYPTO_SALSA20 is not set | ||
| 1388 | # CONFIG_CRYPTO_SEED is not set | ||
| 1389 | # CONFIG_CRYPTO_SERPENT is not set | ||
| 1390 | # CONFIG_CRYPTO_TEA is not set | ||
| 1391 | # CONFIG_CRYPTO_TWOFISH is not set | ||
| 1392 | |||
| 1393 | # | ||
| 1394 | # Compression | ||
| 1395 | # | ||
| 1396 | # CONFIG_CRYPTO_DEFLATE is not set | ||
| 1397 | # CONFIG_CRYPTO_ZLIB is not set | ||
| 1398 | # CONFIG_CRYPTO_LZO is not set | ||
| 1399 | |||
| 1400 | # | ||
| 1401 | # Random Number Generation | ||
| 1402 | # | ||
| 1403 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | ||
| 1404 | # CONFIG_CRYPTO_HW is not set | ||
| 1405 | # CONFIG_PPC_CLOCK is not set | ||
| 1406 | # CONFIG_VIRTUALIZATION is not set | ||
diff --git a/arch/powerpc/include/asm/asm-offsets.h b/arch/powerpc/include/asm/asm-offsets.h new file mode 100644 index 000000000000..d370ee36a182 --- /dev/null +++ b/arch/powerpc/include/asm/asm-offsets.h | |||
| @@ -0,0 +1 @@ | |||
| #include <generated/asm-offsets.h> | |||
diff --git a/arch/powerpc/include/asm/async_tx.h b/arch/powerpc/include/asm/async_tx.h new file mode 100644 index 000000000000..8b2dc55d01ab --- /dev/null +++ b/arch/powerpc/include/asm/async_tx.h | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2008-2009 DENX Software Engineering. | ||
| 3 | * | ||
| 4 | * Author: Yuri Tikhonov <yur@emcraft.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published by the Free | ||
| 8 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 9 | * any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 14 | * more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along with | ||
| 17 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
| 18 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 19 | * | ||
| 20 | * The full GNU General Public License is included in this distribution in the | ||
| 21 | * file called COPYING. | ||
| 22 | */ | ||
| 23 | #ifndef _ASM_POWERPC_ASYNC_TX_H_ | ||
| 24 | #define _ASM_POWERPC_ASYNC_TX_H_ | ||
| 25 | |||
| 26 | #if defined(CONFIG_440SPe) || defined(CONFIG_440SP) | ||
| 27 | extern struct dma_chan * | ||
| 28 | ppc440spe_async_tx_find_best_channel(enum dma_transaction_type cap, | ||
| 29 | struct page **dst_lst, int dst_cnt, struct page **src_lst, | ||
| 30 | int src_cnt, size_t src_sz); | ||
| 31 | |||
| 32 | #define async_tx_find_channel(dep, cap, dst_lst, dst_cnt, src_lst, \ | ||
| 33 | src_cnt, src_sz) \ | ||
| 34 | ppc440spe_async_tx_find_best_channel(cap, dst_lst, dst_cnt, src_lst, \ | ||
| 35 | src_cnt, src_sz) | ||
| 36 | #else | ||
| 37 | |||
| 38 | #define async_tx_find_channel(dep, type, dst, dst_count, src, src_count, len) \ | ||
| 39 | __async_tx_find_channel(dep, type) | ||
| 40 | |||
| 41 | struct dma_chan * | ||
| 42 | __async_tx_find_channel(struct async_submit_ctl *submit, | ||
| 43 | enum dma_transaction_type tx_type); | ||
| 44 | |||
| 45 | #endif | ||
| 46 | |||
| 47 | #endif | ||
diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h index 64e1fdca233e..2c15212e1700 100644 --- a/arch/powerpc/include/asm/bug.h +++ b/arch/powerpc/include/asm/bug.h | |||
| @@ -68,7 +68,7 @@ | |||
| 68 | _EMIT_BUG_ENTRY \ | 68 | _EMIT_BUG_ENTRY \ |
| 69 | : : "i" (__FILE__), "i" (__LINE__), \ | 69 | : : "i" (__FILE__), "i" (__LINE__), \ |
| 70 | "i" (0), "i" (sizeof(struct bug_entry))); \ | 70 | "i" (0), "i" (sizeof(struct bug_entry))); \ |
| 71 | for(;;) ; \ | 71 | unreachable(); \ |
| 72 | } while (0) | 72 | } while (0) |
| 73 | 73 | ||
| 74 | #define BUG_ON(x) do { \ | 74 | #define BUG_ON(x) do { \ |
diff --git a/arch/powerpc/include/asm/cpm.h b/arch/powerpc/include/asm/cpm.h index 24d79e3abd8e..0835eb977ba9 100644 --- a/arch/powerpc/include/asm/cpm.h +++ b/arch/powerpc/include/asm/cpm.h | |||
| @@ -3,8 +3,47 @@ | |||
| 3 | 3 | ||
| 4 | #include <linux/compiler.h> | 4 | #include <linux/compiler.h> |
| 5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
| 6 | #include <linux/errno.h> | ||
| 6 | #include <linux/of.h> | 7 | #include <linux/of.h> |
| 7 | 8 | ||
| 9 | /* | ||
| 10 | * USB Controller pram common to QE and CPM. | ||
| 11 | */ | ||
| 12 | struct usb_ctlr { | ||
| 13 | u8 usb_usmod; | ||
| 14 | u8 usb_usadr; | ||
| 15 | u8 usb_uscom; | ||
| 16 | u8 res1[1]; | ||
| 17 | __be16 usb_usep[4]; | ||
| 18 | u8 res2[4]; | ||
| 19 | __be16 usb_usber; | ||
| 20 | u8 res3[2]; | ||
| 21 | __be16 usb_usbmr; | ||
| 22 | u8 res4[1]; | ||
| 23 | u8 usb_usbs; | ||
| 24 | /* Fields down below are QE-only */ | ||
| 25 | __be16 usb_ussft; | ||
| 26 | u8 res5[2]; | ||
| 27 | __be16 usb_usfrn; | ||
| 28 | u8 res6[0x22]; | ||
| 29 | } __attribute__ ((packed)); | ||
| 30 | |||
| 31 | /* | ||
| 32 | * Function code bits, usually generic to devices. | ||
| 33 | */ | ||
| 34 | #ifdef CONFIG_CPM1 | ||
| 35 | #define CPMFCR_GBL ((u_char)0x00) /* Flag doesn't exist in CPM1 */ | ||
| 36 | #define CPMFCR_TC2 ((u_char)0x00) /* Flag doesn't exist in CPM1 */ | ||
| 37 | #define CPMFCR_DTB ((u_char)0x00) /* Flag doesn't exist in CPM1 */ | ||
| 38 | #define CPMFCR_BDB ((u_char)0x00) /* Flag doesn't exist in CPM1 */ | ||
| 39 | #else | ||
| 40 | #define CPMFCR_GBL ((u_char)0x20) /* Set memory snooping */ | ||
| 41 | #define CPMFCR_TC2 ((u_char)0x04) /* Transfer code 2 value */ | ||
| 42 | #define CPMFCR_DTB ((u_char)0x02) /* Use local bus for data when set */ | ||
| 43 | #define CPMFCR_BDB ((u_char)0x01) /* Use local bus for BD when set */ | ||
| 44 | #endif | ||
| 45 | #define CPMFCR_EB ((u_char)0x10) /* Set big endian byte order */ | ||
| 46 | |||
| 8 | /* Opcodes common to CPM1 and CPM2 | 47 | /* Opcodes common to CPM1 and CPM2 |
| 9 | */ | 48 | */ |
| 10 | #define CPM_CR_INIT_TRX ((ushort)0x0000) | 49 | #define CPM_CR_INIT_TRX ((ushort)0x0000) |
| @@ -93,13 +132,56 @@ typedef struct cpm_buf_desc { | |||
| 93 | #define BD_I2C_START (0x0400) | 132 | #define BD_I2C_START (0x0400) |
| 94 | 133 | ||
| 95 | int cpm_muram_init(void); | 134 | int cpm_muram_init(void); |
| 135 | |||
| 136 | #if defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE) | ||
| 96 | unsigned long cpm_muram_alloc(unsigned long size, unsigned long align); | 137 | unsigned long cpm_muram_alloc(unsigned long size, unsigned long align); |
| 97 | int cpm_muram_free(unsigned long offset); | 138 | int cpm_muram_free(unsigned long offset); |
| 98 | unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size); | 139 | unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size); |
| 99 | void __iomem *cpm_muram_addr(unsigned long offset); | 140 | void __iomem *cpm_muram_addr(unsigned long offset); |
| 100 | unsigned long cpm_muram_offset(void __iomem *addr); | 141 | unsigned long cpm_muram_offset(void __iomem *addr); |
| 101 | dma_addr_t cpm_muram_dma(void __iomem *addr); | 142 | dma_addr_t cpm_muram_dma(void __iomem *addr); |
| 143 | #else | ||
| 144 | static inline unsigned long cpm_muram_alloc(unsigned long size, | ||
| 145 | unsigned long align) | ||
| 146 | { | ||
| 147 | return -ENOSYS; | ||
| 148 | } | ||
| 149 | |||
| 150 | static inline int cpm_muram_free(unsigned long offset) | ||
| 151 | { | ||
| 152 | return -ENOSYS; | ||
| 153 | } | ||
| 154 | |||
| 155 | static inline unsigned long cpm_muram_alloc_fixed(unsigned long offset, | ||
| 156 | unsigned long size) | ||
| 157 | { | ||
| 158 | return -ENOSYS; | ||
| 159 | } | ||
| 160 | |||
| 161 | static inline void __iomem *cpm_muram_addr(unsigned long offset) | ||
| 162 | { | ||
| 163 | return NULL; | ||
| 164 | } | ||
| 165 | |||
| 166 | static inline unsigned long cpm_muram_offset(void __iomem *addr) | ||
| 167 | { | ||
| 168 | return -ENOSYS; | ||
| 169 | } | ||
| 170 | |||
| 171 | static inline dma_addr_t cpm_muram_dma(void __iomem *addr) | ||
| 172 | { | ||
| 173 | return 0; | ||
| 174 | } | ||
| 175 | #endif /* defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE) */ | ||
| 176 | |||
| 177 | #ifdef CONFIG_CPM | ||
| 102 | int cpm_command(u32 command, u8 opcode); | 178 | int cpm_command(u32 command, u8 opcode); |
| 179 | #else | ||
| 180 | static inline int cpm_command(u32 command, u8 opcode) | ||
| 181 | { | ||
| 182 | return -ENOSYS; | ||
| 183 | } | ||
| 184 | #endif /* CONFIG_CPM */ | ||
| 103 | 185 | ||
| 104 | int cpm2_gpiochip_add32(struct device_node *np); | 186 | int cpm2_gpiochip_add32(struct device_node *np); |
| 105 | 187 | ||
diff --git a/arch/powerpc/include/asm/cpm1.h b/arch/powerpc/include/asm/cpm1.h index 7685ffde8821..81b01192f440 100644 --- a/arch/powerpc/include/asm/cpm1.h +++ b/arch/powerpc/include/asm/cpm1.h | |||
| @@ -478,51 +478,6 @@ typedef struct iic { | |||
| 478 | char res2[2]; /* Reserved */ | 478 | char res2[2]; /* Reserved */ |
| 479 | } iic_t; | 479 | } iic_t; |
| 480 | 480 | ||
| 481 | /* SPI parameter RAM. | ||
| 482 | */ | ||
| 483 | typedef struct spi { | ||
| 484 | ushort spi_rbase; /* Rx Buffer descriptor base address */ | ||
| 485 | ushort spi_tbase; /* Tx Buffer descriptor base address */ | ||
| 486 | u_char spi_rfcr; /* Rx function code */ | ||
| 487 | u_char spi_tfcr; /* Tx function code */ | ||
| 488 | ushort spi_mrblr; /* Max receive buffer length */ | ||
| 489 | uint spi_rstate; /* Internal */ | ||
| 490 | uint spi_rdp; /* Internal */ | ||
| 491 | ushort spi_rbptr; /* Internal */ | ||
| 492 | ushort spi_rbc; /* Internal */ | ||
| 493 | uint spi_rxtmp; /* Internal */ | ||
| 494 | uint spi_tstate; /* Internal */ | ||
| 495 | uint spi_tdp; /* Internal */ | ||
| 496 | ushort spi_tbptr; /* Internal */ | ||
| 497 | ushort spi_tbc; /* Internal */ | ||
| 498 | uint spi_txtmp; /* Internal */ | ||
| 499 | uint spi_res; | ||
| 500 | ushort spi_rpbase; /* Relocation pointer */ | ||
| 501 | ushort spi_res2; | ||
| 502 | } spi_t; | ||
| 503 | |||
| 504 | /* SPI Mode register. | ||
| 505 | */ | ||
| 506 | #define SPMODE_LOOP ((ushort)0x4000) /* Loopback */ | ||
| 507 | #define SPMODE_CI ((ushort)0x2000) /* Clock Invert */ | ||
| 508 | #define SPMODE_CP ((ushort)0x1000) /* Clock Phase */ | ||
| 509 | #define SPMODE_DIV16 ((ushort)0x0800) /* BRG/16 mode */ | ||
| 510 | #define SPMODE_REV ((ushort)0x0400) /* Reversed Data */ | ||
| 511 | #define SPMODE_MSTR ((ushort)0x0200) /* SPI Master */ | ||
| 512 | #define SPMODE_EN ((ushort)0x0100) /* Enable */ | ||
| 513 | #define SPMODE_LENMSK ((ushort)0x00f0) /* character length */ | ||
| 514 | #define SPMODE_LEN4 ((ushort)0x0030) /* 4 bits per char */ | ||
| 515 | #define SPMODE_LEN8 ((ushort)0x0070) /* 8 bits per char */ | ||
| 516 | #define SPMODE_LEN16 ((ushort)0x00f0) /* 16 bits per char */ | ||
| 517 | #define SPMODE_PMMSK ((ushort)0x000f) /* prescale modulus */ | ||
| 518 | |||
| 519 | /* SPIE fields */ | ||
| 520 | #define SPIE_MME 0x20 | ||
| 521 | #define SPIE_TXE 0x10 | ||
| 522 | #define SPIE_BSY 0x04 | ||
| 523 | #define SPIE_TXB 0x02 | ||
| 524 | #define SPIE_RXB 0x01 | ||
| 525 | |||
| 526 | /* | 481 | /* |
| 527 | * RISC Controller Configuration Register definitons | 482 | * RISC Controller Configuration Register definitons |
| 528 | */ | 483 | */ |
diff --git a/arch/powerpc/include/asm/cpm2.h b/arch/powerpc/include/asm/cpm2.h index 990ff191da8b..f42e9baf3a4e 100644 --- a/arch/powerpc/include/asm/cpm2.h +++ b/arch/powerpc/include/asm/cpm2.h | |||
| @@ -124,14 +124,6 @@ static inline void cpm2_fastbrg(uint brg, uint rate, int div16) | |||
| 124 | __cpm2_setbrg(brg, rate, CPM2_BRG_INT_CLK, div16, CPM_BRG_EXTC_INT); | 124 | __cpm2_setbrg(brg, rate, CPM2_BRG_INT_CLK, div16, CPM_BRG_EXTC_INT); |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | /* Function code bits, usually generic to devices. | ||
| 128 | */ | ||
| 129 | #define CPMFCR_GBL ((u_char)0x20) /* Set memory snooping */ | ||
| 130 | #define CPMFCR_EB ((u_char)0x10) /* Set big endian byte order */ | ||
| 131 | #define CPMFCR_TC2 ((u_char)0x04) /* Transfer code 2 value */ | ||
| 132 | #define CPMFCR_DTB ((u_char)0x02) /* Use local bus for data when set */ | ||
| 133 | #define CPMFCR_BDB ((u_char)0x01) /* Use local bus for BD when set */ | ||
| 134 | |||
| 135 | /* Parameter RAM offsets from the base. | 127 | /* Parameter RAM offsets from the base. |
| 136 | */ | 128 | */ |
| 137 | #define PROFF_SCC1 ((uint)0x8000) | 129 | #define PROFF_SCC1 ((uint)0x8000) |
| @@ -654,45 +646,6 @@ typedef struct iic { | |||
| 654 | uint iic_txtmp; /* Internal */ | 646 | uint iic_txtmp; /* Internal */ |
| 655 | } iic_t; | 647 | } iic_t; |
| 656 | 648 | ||
| 657 | /* SPI parameter RAM. | ||
| 658 | */ | ||
| 659 | typedef struct spi { | ||
| 660 | ushort spi_rbase; /* Rx Buffer descriptor base address */ | ||
| 661 | ushort spi_tbase; /* Tx Buffer descriptor base address */ | ||
| 662 | u_char spi_rfcr; /* Rx function code */ | ||
| 663 | u_char spi_tfcr; /* Tx function code */ | ||
| 664 | ushort spi_mrblr; /* Max receive buffer length */ | ||
| 665 | uint spi_rstate; /* Internal */ | ||
| 666 | uint spi_rdp; /* Internal */ | ||
| 667 | ushort spi_rbptr; /* Internal */ | ||
| 668 | ushort spi_rbc; /* Internal */ | ||
| 669 | uint spi_rxtmp; /* Internal */ | ||
| 670 | uint spi_tstate; /* Internal */ | ||
| 671 | uint spi_tdp; /* Internal */ | ||
| 672 | ushort spi_tbptr; /* Internal */ | ||
| 673 | ushort spi_tbc; /* Internal */ | ||
| 674 | uint spi_txtmp; /* Internal */ | ||
| 675 | uint spi_res; /* Tx temp. */ | ||
| 676 | uint spi_res1[4]; /* SDMA temp. */ | ||
| 677 | } spi_t; | ||
| 678 | |||
| 679 | /* SPI Mode register. | ||
| 680 | */ | ||
| 681 | #define SPMODE_LOOP ((ushort)0x4000) /* Loopback */ | ||
| 682 | #define SPMODE_CI ((ushort)0x2000) /* Clock Invert */ | ||
| 683 | #define SPMODE_CP ((ushort)0x1000) /* Clock Phase */ | ||
| 684 | #define SPMODE_DIV16 ((ushort)0x0800) /* BRG/16 mode */ | ||
| 685 | #define SPMODE_REV ((ushort)0x0400) /* Reversed Data */ | ||
| 686 | #define SPMODE_MSTR ((ushort)0x0200) /* SPI Master */ | ||
| 687 | #define SPMODE_EN ((ushort)0x0100) /* Enable */ | ||
| 688 | #define SPMODE_LENMSK ((ushort)0x00f0) /* character length */ | ||
| 689 | #define SPMODE_PMMSK ((ushort)0x000f) /* prescale modulus */ | ||
| 690 | |||
| 691 | #define SPMODE_LEN(x) ((((x)-1)&0xF)<<4) | ||
| 692 | #define SPMODE_PM(x) ((x) &0xF) | ||
| 693 | |||
| 694 | #define SPI_EB ((u_char)0x10) /* big endian byte order */ | ||
| 695 | |||
| 696 | /* IDMA parameter RAM | 649 | /* IDMA parameter RAM |
| 697 | */ | 650 | */ |
| 698 | typedef struct idma { | 651 | typedef struct idma { |
diff --git a/arch/powerpc/include/asm/dcr-regs.h b/arch/powerpc/include/asm/dcr-regs.h index 828e3aa1f2fc..380274de429f 100644 --- a/arch/powerpc/include/asm/dcr-regs.h +++ b/arch/powerpc/include/asm/dcr-regs.h | |||
| @@ -157,4 +157,27 @@ | |||
| 157 | #define L2C_SNP_SSR_32G 0x0000f000 | 157 | #define L2C_SNP_SSR_32G 0x0000f000 |
| 158 | #define L2C_SNP_ESR 0x00000800 | 158 | #define L2C_SNP_ESR 0x00000800 |
| 159 | 159 | ||
| 160 | /* | ||
| 161 | * DCR register offsets for 440SP/440SPe I2O/DMA controller. | ||
| 162 | * The base address is configured in the device tree. | ||
| 163 | */ | ||
| 164 | #define DCRN_I2O0_IBAL 0x006 | ||
| 165 | #define DCRN_I2O0_IBAH 0x007 | ||
| 166 | #define I2O_REG_ENABLE 0x00000001 /* Enable I2O/DMA access */ | ||
| 167 | |||
| 168 | /* 440SP/440SPe Software Reset DCR */ | ||
| 169 | #define DCRN_SDR0_SRST 0x0200 | ||
| 170 | #define DCRN_SDR0_SRST_I2ODMA (0x80000000 >> 15) /* Reset I2O/DMA */ | ||
| 171 | |||
| 172 | /* 440SP/440SPe Memory Queue DCR offsets */ | ||
| 173 | #define DCRN_MQ0_XORBA 0x04 | ||
| 174 | #define DCRN_MQ0_CF2H 0x06 | ||
| 175 | #define DCRN_MQ0_CFBHL 0x0f | ||
| 176 | #define DCRN_MQ0_BAUH 0x10 | ||
| 177 | |||
| 178 | /* HB/LL Paths Configuration Register */ | ||
| 179 | #define MQ0_CFBHL_TPLM 28 | ||
| 180 | #define MQ0_CFBHL_HBCL 23 | ||
| 181 | #define MQ0_CFBHL_POLY 15 | ||
| 182 | |||
| 160 | #endif /* __DCR_REGS_H__ */ | 183 | #endif /* __DCR_REGS_H__ */ |
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h index e281daebddca..80a973bb9e71 100644 --- a/arch/powerpc/include/asm/dma-mapping.h +++ b/arch/powerpc/include/asm/dma-mapping.h | |||
| @@ -197,7 +197,7 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) | |||
| 197 | if (!dev->dma_mask) | 197 | if (!dev->dma_mask) |
| 198 | return 0; | 198 | return 0; |
| 199 | 199 | ||
| 200 | return addr + size <= *dev->dma_mask; | 200 | return addr + size - 1 <= *dev->dma_mask; |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) | 203 | static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) |
diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h index 014a624f4c8e..17828ad411eb 100644 --- a/arch/powerpc/include/asm/elf.h +++ b/arch/powerpc/include/asm/elf.h | |||
| @@ -170,7 +170,6 @@ typedef elf_fpreg_t elf_vsrreghalf_t32[ELF_NVSRHALFREG]; | |||
| 170 | #define elf_check_arch(x) ((x)->e_machine == ELF_ARCH) | 170 | #define elf_check_arch(x) ((x)->e_machine == ELF_ARCH) |
| 171 | #define compat_elf_check_arch(x) ((x)->e_machine == EM_PPC) | 171 | #define compat_elf_check_arch(x) ((x)->e_machine == EM_PPC) |
| 172 | 172 | ||
| 173 | #define USE_ELF_CORE_DUMP | ||
| 174 | #define CORE_DUMP_USE_REGSET | 173 | #define CORE_DUMP_USE_REGSET |
| 175 | #define ELF_EXEC_PAGESIZE PAGE_SIZE | 174 | #define ELF_EXEC_PAGESIZE PAGE_SIZE |
| 176 | 175 | ||
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index a98653b26231..57c400071995 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h | |||
| @@ -147,6 +147,7 @@ | |||
| 147 | .globl label##_pSeries; \ | 147 | .globl label##_pSeries; \ |
| 148 | label##_pSeries: \ | 148 | label##_pSeries: \ |
| 149 | HMT_MEDIUM; \ | 149 | HMT_MEDIUM; \ |
| 150 | DO_KVM n; \ | ||
| 150 | mtspr SPRN_SPRG_SCRATCH0,r13; /* save r13 */ \ | 151 | mtspr SPRN_SPRG_SCRATCH0,r13; /* save r13 */ \ |
| 151 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) | 152 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) |
| 152 | 153 | ||
| @@ -170,6 +171,7 @@ label##_pSeries: \ | |||
| 170 | .globl label##_pSeries; \ | 171 | .globl label##_pSeries; \ |
| 171 | label##_pSeries: \ | 172 | label##_pSeries: \ |
| 172 | HMT_MEDIUM; \ | 173 | HMT_MEDIUM; \ |
| 174 | DO_KVM n; \ | ||
| 173 | mtspr SPRN_SPRG_SCRATCH0,r13; /* save r13 */ \ | 175 | mtspr SPRN_SPRG_SCRATCH0,r13; /* save r13 */ \ |
| 174 | mfspr r13,SPRN_SPRG_PACA; /* get paca address into r13 */ \ | 176 | mfspr r13,SPRN_SPRG_PACA; /* get paca address into r13 */ \ |
| 175 | std r9,PACA_EXGEN+EX_R9(r13); /* save r9, r10 */ \ | 177 | std r9,PACA_EXGEN+EX_R9(r13); /* save r9, r10 */ \ |
diff --git a/arch/powerpc/include/asm/fixmap.h b/arch/powerpc/include/asm/fixmap.h index f1f4e23a84e9..5c2c0233175e 100644 --- a/arch/powerpc/include/asm/fixmap.h +++ b/arch/powerpc/include/asm/fixmap.h | |||
| @@ -44,6 +44,9 @@ | |||
| 44 | */ | 44 | */ |
| 45 | enum fixed_addresses { | 45 | enum fixed_addresses { |
| 46 | FIX_HOLE, | 46 | FIX_HOLE, |
| 47 | /* reserve the top 128K for early debugging purposes */ | ||
| 48 | FIX_EARLY_DEBUG_TOP = FIX_HOLE, | ||
| 49 | FIX_EARLY_DEBUG_BASE = FIX_EARLY_DEBUG_TOP+((128*1024)/PAGE_SIZE)-1, | ||
| 47 | #ifdef CONFIG_HIGHMEM | 50 | #ifdef CONFIG_HIGHMEM |
| 48 | FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ | 51 | FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ |
| 49 | FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, | 52 | FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, |
diff --git a/arch/powerpc/include/asm/gpio.h b/arch/powerpc/include/asm/gpio.h index ea04632399d8..38762edb5e58 100644 --- a/arch/powerpc/include/asm/gpio.h +++ b/arch/powerpc/include/asm/gpio.h | |||
| @@ -38,12 +38,9 @@ static inline int gpio_cansleep(unsigned int gpio) | |||
| 38 | return __gpio_cansleep(gpio); | 38 | return __gpio_cansleep(gpio); |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | /* | ||
| 42 | * Not implemented, yet. | ||
| 43 | */ | ||
| 44 | static inline int gpio_to_irq(unsigned int gpio) | 41 | static inline int gpio_to_irq(unsigned int gpio) |
| 45 | { | 42 | { |
| 46 | return -ENOSYS; | 43 | return __gpio_to_irq(gpio); |
| 47 | } | 44 | } |
| 48 | 45 | ||
| 49 | static inline int irq_to_gpio(unsigned int irq) | 46 | static inline int irq_to_gpio(unsigned int irq) |
diff --git a/arch/powerpc/include/asm/hugetlb.h b/arch/powerpc/include/asm/hugetlb.h index b1dafb6a9743..5856a66ab404 100644 --- a/arch/powerpc/include/asm/hugetlb.h +++ b/arch/powerpc/include/asm/hugetlb.h | |||
| @@ -3,6 +3,10 @@ | |||
| 3 | 3 | ||
| 4 | #include <asm/page.h> | 4 | #include <asm/page.h> |
| 5 | 5 | ||
| 6 | pte_t *huge_pte_offset_and_shift(struct mm_struct *mm, | ||
| 7 | unsigned long addr, unsigned *shift); | ||
| 8 | |||
| 9 | void flush_dcache_icache_hugepage(struct page *page); | ||
| 6 | 10 | ||
| 7 | int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr, | 11 | int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr, |
| 8 | unsigned long len); | 12 | unsigned long len); |
| @@ -11,12 +15,6 @@ void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr, | |||
| 11 | unsigned long end, unsigned long floor, | 15 | unsigned long end, unsigned long floor, |
| 12 | unsigned long ceiling); | 16 | unsigned long ceiling); |
| 13 | 17 | ||
| 14 | void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, | ||
| 15 | pte_t *ptep, pte_t pte); | ||
| 16 | |||
| 17 | pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, | ||
| 18 | pte_t *ptep); | ||
| 19 | |||
| 20 | /* | 18 | /* |
| 21 | * The version of vma_mmu_pagesize() in arch/powerpc/mm/hugetlbpage.c needs | 19 | * The version of vma_mmu_pagesize() in arch/powerpc/mm/hugetlbpage.c needs |
| 22 | * to override the version in mm/hugetlb.c | 20 | * to override the version in mm/hugetlb.c |
| @@ -42,9 +40,26 @@ static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm) | |||
| 42 | { | 40 | { |
| 43 | } | 41 | } |
| 44 | 42 | ||
| 43 | |||
| 44 | static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, | ||
| 45 | pte_t *ptep, pte_t pte) | ||
| 46 | { | ||
| 47 | set_pte_at(mm, addr, ptep, pte); | ||
| 48 | } | ||
| 49 | |||
| 50 | static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, | ||
| 51 | unsigned long addr, pte_t *ptep) | ||
| 52 | { | ||
| 53 | unsigned long old = pte_update(mm, addr, ptep, ~0UL, 1); | ||
| 54 | return __pte(old); | ||
| 55 | } | ||
| 56 | |||
| 45 | static inline void huge_ptep_clear_flush(struct vm_area_struct *vma, | 57 | static inline void huge_ptep_clear_flush(struct vm_area_struct *vma, |
| 46 | unsigned long addr, pte_t *ptep) | 58 | unsigned long addr, pte_t *ptep) |
| 47 | { | 59 | { |
| 60 | pte_t pte; | ||
| 61 | pte = huge_ptep_get_and_clear(vma->vm_mm, addr, ptep); | ||
| 62 | flush_tlb_page(vma, addr); | ||
| 48 | } | 63 | } |
| 49 | 64 | ||
| 50 | static inline int huge_pte_none(pte_t pte) | 65 | static inline int huge_pte_none(pte_t pte) |
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h index c27caac47ad1..f0275818b95c 100644 --- a/arch/powerpc/include/asm/hvcall.h +++ b/arch/powerpc/include/asm/hvcall.h | |||
| @@ -212,6 +212,19 @@ | |||
| 212 | #define H_QUERY_INT_STATE 0x1E4 | 212 | #define H_QUERY_INT_STATE 0x1E4 |
| 213 | #define H_POLL_PENDING 0x1D8 | 213 | #define H_POLL_PENDING 0x1D8 |
| 214 | #define H_ILLAN_ATTRIBUTES 0x244 | 214 | #define H_ILLAN_ATTRIBUTES 0x244 |
| 215 | #define H_MODIFY_HEA_QP 0x250 | ||
| 216 | #define H_QUERY_HEA_QP 0x254 | ||
| 217 | #define H_QUERY_HEA 0x258 | ||
| 218 | #define H_QUERY_HEA_PORT 0x25C | ||
| 219 | #define H_MODIFY_HEA_PORT 0x260 | ||
| 220 | #define H_REG_BCMC 0x264 | ||
| 221 | #define H_DEREG_BCMC 0x268 | ||
| 222 | #define H_REGISTER_HEA_RPAGES 0x26C | ||
| 223 | #define H_DISABLE_AND_GET_HEA 0x270 | ||
| 224 | #define H_GET_HEA_INFO 0x274 | ||
| 225 | #define H_ALLOC_HEA_RESOURCE 0x278 | ||
| 226 | #define H_ADD_CONN 0x284 | ||
| 227 | #define H_DEL_CONN 0x288 | ||
| 215 | #define H_JOIN 0x298 | 228 | #define H_JOIN 0x298 |
| 216 | #define H_VASI_STATE 0x2A4 | 229 | #define H_VASI_STATE 0x2A4 |
| 217 | #define H_ENABLE_CRQ 0x2B0 | 230 | #define H_ENABLE_CRQ 0x2B0 |
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h index abbc2aaaced5..9f4c9d4f5803 100644 --- a/arch/powerpc/include/asm/hw_irq.h +++ b/arch/powerpc/include/asm/hw_irq.h | |||
| @@ -64,11 +64,6 @@ extern void iseries_handle_interrupts(void); | |||
| 64 | get_paca()->hard_enabled = 0; \ | 64 | get_paca()->hard_enabled = 0; \ |
| 65 | } while(0) | 65 | } while(0) |
| 66 | 66 | ||
| 67 | static inline int irqs_disabled_flags(unsigned long flags) | ||
| 68 | { | ||
| 69 | return flags == 0; | ||
| 70 | } | ||
| 71 | |||
| 72 | #else | 67 | #else |
| 73 | 68 | ||
| 74 | #if defined(CONFIG_BOOKE) | 69 | #if defined(CONFIG_BOOKE) |
diff --git a/arch/powerpc/include/asm/immap_cpm2.h b/arch/powerpc/include/asm/immap_cpm2.h index d4f069bf0e57..7c64fda5357b 100644 --- a/arch/powerpc/include/asm/immap_cpm2.h +++ b/arch/powerpc/include/asm/immap_cpm2.h | |||
| @@ -549,7 +549,7 @@ typedef struct comm_proc { | |||
| 549 | 549 | ||
| 550 | /* USB Controller. | 550 | /* USB Controller. |
| 551 | */ | 551 | */ |
| 552 | typedef struct usb_ctlr { | 552 | typedef struct cpm_usb_ctlr { |
| 553 | u8 usb_usmod; | 553 | u8 usb_usmod; |
| 554 | u8 usb_usadr; | 554 | u8 usb_usadr; |
| 555 | u8 usb_uscom; | 555 | u8 usb_uscom; |
diff --git a/arch/powerpc/include/asm/immap_qe.h b/arch/powerpc/include/asm/immap_qe.h index c346d0bcd230..4e10f508570a 100644 --- a/arch/powerpc/include/asm/immap_qe.h +++ b/arch/powerpc/include/asm/immap_qe.h | |||
| @@ -210,7 +210,7 @@ struct sir { | |||
| 210 | } __attribute__ ((packed)); | 210 | } __attribute__ ((packed)); |
| 211 | 211 | ||
| 212 | /* USB Controller */ | 212 | /* USB Controller */ |
| 213 | struct usb_ctlr { | 213 | struct qe_usb_ctlr { |
| 214 | u8 usb_usmod; | 214 | u8 usb_usmod; |
| 215 | u8 usb_usadr; | 215 | u8 usb_usadr; |
| 216 | u8 usb_uscom; | 216 | u8 usb_uscom; |
| @@ -229,7 +229,7 @@ struct usb_ctlr { | |||
| 229 | } __attribute__ ((packed)); | 229 | } __attribute__ ((packed)); |
| 230 | 230 | ||
| 231 | /* MCC */ | 231 | /* MCC */ |
| 232 | struct mcc { | 232 | struct qe_mcc { |
| 233 | __be32 mcce; /* MCC event register */ | 233 | __be32 mcce; /* MCC event register */ |
| 234 | __be32 mccm; /* MCC mask register */ | 234 | __be32 mccm; /* MCC mask register */ |
| 235 | __be32 mccf; /* MCC configuration register */ | 235 | __be32 mccf; /* MCC configuration register */ |
| @@ -431,9 +431,9 @@ struct qe_immap { | |||
| 431 | struct qe_mux qmx; /* QE Multiplexer */ | 431 | struct qe_mux qmx; /* QE Multiplexer */ |
| 432 | struct qe_timers qet; /* QE Timers */ | 432 | struct qe_timers qet; /* QE Timers */ |
| 433 | struct spi spi[0x2]; /* spi */ | 433 | struct spi spi[0x2]; /* spi */ |
| 434 | struct mcc mcc; /* mcc */ | 434 | struct qe_mcc mcc; /* mcc */ |
| 435 | struct qe_brg brg; /* brg */ | 435 | struct qe_brg brg; /* brg */ |
| 436 | struct usb_ctlr usb; /* USB */ | 436 | struct qe_usb_ctlr usb; /* USB */ |
| 437 | struct si1 si1; /* SI */ | 437 | struct si1 si1; /* SI */ |
| 438 | u8 res11[0x800]; | 438 | u8 res11[0x800]; |
| 439 | struct sir sir; /* SI Routing Tables */ | 439 | struct sir sir; /* SI Routing Tables */ |
diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h index bbcd1aaf3dfd..e054baef1845 100644 --- a/arch/powerpc/include/asm/irq.h +++ b/arch/powerpc/include/asm/irq.h | |||
| @@ -17,8 +17,6 @@ | |||
| 17 | #include <asm/atomic.h> | 17 | #include <asm/atomic.h> |
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | #define get_irq_desc(irq) (&irq_desc[(irq)]) | ||
| 21 | |||
| 22 | /* Define a way to iterate across irqs. */ | 20 | /* Define a way to iterate across irqs. */ |
| 23 | #define for_each_irq(i) \ | 21 | #define for_each_irq(i) \ |
| 24 | for ((i) = 0; (i) < NR_IRQS; ++(i)) | 22 | for ((i) = 0; (i) < NR_IRQS; ++(i)) |
| @@ -34,12 +32,15 @@ extern atomic_t ppc_n_lost_interrupts; | |||
| 34 | */ | 32 | */ |
| 35 | #define NO_IRQ_IGNORE ((unsigned int)-1) | 33 | #define NO_IRQ_IGNORE ((unsigned int)-1) |
| 36 | 34 | ||
| 37 | /* Total number of virq in the platform (make it a CONFIG_* option ? */ | 35 | /* Total number of virq in the platform */ |
| 38 | #define NR_IRQS 512 | 36 | #define NR_IRQS CONFIG_NR_IRQS |
| 39 | 37 | ||
| 40 | /* Number of irqs reserved for the legacy controller */ | 38 | /* Number of irqs reserved for the legacy controller */ |
| 41 | #define NUM_ISA_INTERRUPTS 16 | 39 | #define NUM_ISA_INTERRUPTS 16 |
| 42 | 40 | ||
| 41 | /* Same thing, used by the generic IRQ code */ | ||
| 42 | #define NR_IRQS_LEGACY NUM_ISA_INTERRUPTS | ||
| 43 | |||
| 43 | /* This type is the placeholder for a hardware interrupt number. It has to | 44 | /* This type is the placeholder for a hardware interrupt number. It has to |
| 44 | * be big enough to enclose whatever representation is used by a given | 45 | * be big enough to enclose whatever representation is used by a given |
| 45 | * platform. | 46 | * platform. |
| @@ -99,7 +100,7 @@ struct irq_host_ops { | |||
| 99 | * interrupt controller has for that line) | 100 | * interrupt controller has for that line) |
| 100 | */ | 101 | */ |
| 101 | int (*xlate)(struct irq_host *h, struct device_node *ctrler, | 102 | int (*xlate)(struct irq_host *h, struct device_node *ctrler, |
| 102 | u32 *intspec, unsigned int intsize, | 103 | const u32 *intspec, unsigned int intsize, |
| 103 | irq_hw_number_t *out_hwirq, unsigned int *out_type); | 104 | irq_hw_number_t *out_hwirq, unsigned int *out_type); |
| 104 | }; | 105 | }; |
| 105 | 106 | ||
| @@ -313,7 +314,7 @@ extern void irq_free_virt(unsigned int virq, unsigned int count); | |||
| 313 | * of the of_irq_map_*() functions. | 314 | * of the of_irq_map_*() functions. |
| 314 | */ | 315 | */ |
| 315 | extern unsigned int irq_create_of_mapping(struct device_node *controller, | 316 | extern unsigned int irq_create_of_mapping(struct device_node *controller, |
| 316 | u32 *intspec, unsigned int intsize); | 317 | const u32 *intspec, unsigned int intsize); |
| 317 | 318 | ||
| 318 | /** | 319 | /** |
| 319 | * irq_of_parse_and_map - Parse and Map an interrupt into linux virq space | 320 | * irq_of_parse_and_map - Parse and Map an interrupt into linux virq space |
diff --git a/arch/powerpc/include/asm/kvm.h b/arch/powerpc/include/asm/kvm.h index bb2de6aa5ce0..81f3b0b5601e 100644 --- a/arch/powerpc/include/asm/kvm.h +++ b/arch/powerpc/include/asm/kvm.h | |||
| @@ -46,6 +46,24 @@ struct kvm_regs { | |||
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | struct kvm_sregs { | 48 | struct kvm_sregs { |
| 49 | __u32 pvr; | ||
| 50 | union { | ||
| 51 | struct { | ||
| 52 | __u64 sdr1; | ||
| 53 | struct { | ||
| 54 | struct { | ||
| 55 | __u64 slbe; | ||
| 56 | __u64 slbv; | ||
| 57 | } slb[64]; | ||
| 58 | } ppc64; | ||
| 59 | struct { | ||
| 60 | __u32 sr[16]; | ||
| 61 | __u64 ibat[8]; | ||
| 62 | __u64 dbat[8]; | ||
| 63 | } ppc32; | ||
| 64 | } s; | ||
| 65 | __u8 pad[1020]; | ||
| 66 | } u; | ||
| 49 | }; | 67 | }; |
| 50 | 68 | ||
| 51 | struct kvm_fpu { | 69 | struct kvm_fpu { |
diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h index 56bfae59837f..af2abe74f544 100644 --- a/arch/powerpc/include/asm/kvm_asm.h +++ b/arch/powerpc/include/asm/kvm_asm.h | |||
| @@ -49,6 +49,46 @@ | |||
| 49 | #define BOOKE_INTERRUPT_SPE_FP_ROUND 34 | 49 | #define BOOKE_INTERRUPT_SPE_FP_ROUND 34 |
| 50 | #define BOOKE_INTERRUPT_PERFORMANCE_MONITOR 35 | 50 | #define BOOKE_INTERRUPT_PERFORMANCE_MONITOR 35 |
| 51 | 51 | ||
| 52 | /* book3s */ | ||
| 53 | |||
| 54 | #define BOOK3S_INTERRUPT_SYSTEM_RESET 0x100 | ||
| 55 | #define BOOK3S_INTERRUPT_MACHINE_CHECK 0x200 | ||
| 56 | #define BOOK3S_INTERRUPT_DATA_STORAGE 0x300 | ||
| 57 | #define BOOK3S_INTERRUPT_DATA_SEGMENT 0x380 | ||
| 58 | #define BOOK3S_INTERRUPT_INST_STORAGE 0x400 | ||
| 59 | #define BOOK3S_INTERRUPT_INST_SEGMENT 0x480 | ||
| 60 | #define BOOK3S_INTERRUPT_EXTERNAL 0x500 | ||
| 61 | #define BOOK3S_INTERRUPT_ALIGNMENT 0x600 | ||
| 62 | #define BOOK3S_INTERRUPT_PROGRAM 0x700 | ||
| 63 | #define BOOK3S_INTERRUPT_FP_UNAVAIL 0x800 | ||
| 64 | #define BOOK3S_INTERRUPT_DECREMENTER 0x900 | ||
| 65 | #define BOOK3S_INTERRUPT_SYSCALL 0xc00 | ||
| 66 | #define BOOK3S_INTERRUPT_TRACE 0xd00 | ||
| 67 | #define BOOK3S_INTERRUPT_PERFMON 0xf00 | ||
| 68 | #define BOOK3S_INTERRUPT_ALTIVEC 0xf20 | ||
| 69 | #define BOOK3S_INTERRUPT_VSX 0xf40 | ||
| 70 | |||
| 71 | #define BOOK3S_IRQPRIO_SYSTEM_RESET 0 | ||
| 72 | #define BOOK3S_IRQPRIO_DATA_SEGMENT 1 | ||
| 73 | #define BOOK3S_IRQPRIO_INST_SEGMENT 2 | ||
| 74 | #define BOOK3S_IRQPRIO_DATA_STORAGE 3 | ||
| 75 | #define BOOK3S_IRQPRIO_INST_STORAGE 4 | ||
| 76 | #define BOOK3S_IRQPRIO_ALIGNMENT 5 | ||
| 77 | #define BOOK3S_IRQPRIO_PROGRAM 6 | ||
| 78 | #define BOOK3S_IRQPRIO_FP_UNAVAIL 7 | ||
| 79 | #define BOOK3S_IRQPRIO_ALTIVEC 8 | ||
| 80 | #define BOOK3S_IRQPRIO_VSX 9 | ||
| 81 | #define BOOK3S_IRQPRIO_SYSCALL 10 | ||
| 82 | #define BOOK3S_IRQPRIO_MACHINE_CHECK 11 | ||
| 83 | #define BOOK3S_IRQPRIO_DEBUG 12 | ||
| 84 | #define BOOK3S_IRQPRIO_EXTERNAL 13 | ||
| 85 | #define BOOK3S_IRQPRIO_DECREMENTER 14 | ||
| 86 | #define BOOK3S_IRQPRIO_PERFORMANCE_MONITOR 15 | ||
| 87 | #define BOOK3S_IRQPRIO_MAX 16 | ||
| 88 | |||
| 89 | #define BOOK3S_HFLAG_DCBZ32 0x1 | ||
| 90 | #define BOOK3S_HFLAG_SLB 0x2 | ||
| 91 | |||
| 52 | #define RESUME_FLAG_NV (1<<0) /* Reload guest nonvolatile state? */ | 92 | #define RESUME_FLAG_NV (1<<0) /* Reload guest nonvolatile state? */ |
| 53 | #define RESUME_FLAG_HOST (1<<1) /* Resume host? */ | 93 | #define RESUME_FLAG_HOST (1<<1) /* Resume host? */ |
| 54 | 94 | ||
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h new file mode 100644 index 000000000000..74b7369770d0 --- /dev/null +++ b/arch/powerpc/include/asm/kvm_book3s.h | |||
| @@ -0,0 +1,139 @@ | |||
| 1 | /* | ||
| 2 | * This program is free software; you can redistribute it and/or modify | ||
| 3 | * it under the terms of the GNU General Public License, version 2, as | ||
| 4 | * published by the Free Software Foundation. | ||
| 5 | * | ||
| 6 | * This program is distributed in the hope that it will be useful, | ||
| 7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 9 | * GNU General Public License for more details. | ||
| 10 | * | ||
| 11 | * You should have received a copy of the GNU General Public License | ||
| 12 | * along with this program; if not, write to the Free Software | ||
| 13 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 14 | * | ||
| 15 | * Copyright SUSE Linux Products GmbH 2009 | ||
| 16 | * | ||
| 17 | * Authors: Alexander Graf <agraf@suse.de> | ||
| 18 | */ | ||
| 19 | |||
| 20 | #ifndef __ASM_KVM_BOOK3S_H__ | ||
| 21 | #define __ASM_KVM_BOOK3S_H__ | ||
| 22 | |||
| 23 | #include <linux/types.h> | ||
| 24 | #include <linux/kvm_host.h> | ||
| 25 | #include <asm/kvm_ppc.h> | ||
| 26 | |||
| 27 | struct kvmppc_slb { | ||
| 28 | u64 esid; | ||
| 29 | u64 vsid; | ||
| 30 | u64 orige; | ||
| 31 | u64 origv; | ||
| 32 | bool valid; | ||
| 33 | bool Ks; | ||
| 34 | bool Kp; | ||
| 35 | bool nx; | ||
| 36 | bool large; | ||
| 37 | bool class; | ||
| 38 | }; | ||
| 39 | |||
| 40 | struct kvmppc_sr { | ||
| 41 | u32 raw; | ||
| 42 | u32 vsid; | ||
| 43 | bool Ks; | ||
| 44 | bool Kp; | ||
| 45 | bool nx; | ||
| 46 | }; | ||
| 47 | |||
| 48 | struct kvmppc_bat { | ||
| 49 | u64 raw; | ||
| 50 | u32 bepi; | ||
| 51 | u32 bepi_mask; | ||
| 52 | bool vs; | ||
| 53 | bool vp; | ||
| 54 | u32 brpn; | ||
| 55 | u8 wimg; | ||
| 56 | u8 pp; | ||
| 57 | }; | ||
| 58 | |||
| 59 | struct kvmppc_sid_map { | ||
| 60 | u64 guest_vsid; | ||
| 61 | u64 guest_esid; | ||
| 62 | u64 host_vsid; | ||
| 63 | bool valid; | ||
| 64 | }; | ||
| 65 | |||
| 66 | #define SID_MAP_BITS 9 | ||
| 67 | #define SID_MAP_NUM (1 << SID_MAP_BITS) | ||
| 68 | #define SID_MAP_MASK (SID_MAP_NUM - 1) | ||
| 69 | |||
| 70 | struct kvmppc_vcpu_book3s { | ||
| 71 | struct kvm_vcpu vcpu; | ||
| 72 | struct kvmppc_sid_map sid_map[SID_MAP_NUM]; | ||
| 73 | struct kvmppc_slb slb[64]; | ||
| 74 | struct { | ||
| 75 | u64 esid; | ||
| 76 | u64 vsid; | ||
| 77 | } slb_shadow[64]; | ||
| 78 | u8 slb_shadow_max; | ||
| 79 | struct kvmppc_sr sr[16]; | ||
| 80 | struct kvmppc_bat ibat[8]; | ||
| 81 | struct kvmppc_bat dbat[8]; | ||
| 82 | u64 hid[6]; | ||
| 83 | int slb_nr; | ||
| 84 | u64 sdr1; | ||
| 85 | u64 dsisr; | ||
| 86 | u64 hior; | ||
| 87 | u64 msr_mask; | ||
| 88 | u64 vsid_first; | ||
| 89 | u64 vsid_next; | ||
| 90 | u64 vsid_max; | ||
| 91 | int context_id; | ||
| 92 | }; | ||
| 93 | |||
| 94 | #define CONTEXT_HOST 0 | ||
| 95 | #define CONTEXT_GUEST 1 | ||
| 96 | #define CONTEXT_GUEST_END 2 | ||
| 97 | |||
| 98 | #define VSID_REAL 0xfffffffffff00000 | ||
| 99 | #define VSID_REAL_DR 0xffffffffffe00000 | ||
| 100 | #define VSID_REAL_IR 0xffffffffffd00000 | ||
| 101 | #define VSID_BAT 0xffffffffffc00000 | ||
| 102 | #define VSID_PR 0x8000000000000000 | ||
| 103 | |||
| 104 | extern void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, u64 ea, u64 ea_mask); | ||
| 105 | extern void kvmppc_mmu_pte_vflush(struct kvm_vcpu *vcpu, u64 vp, u64 vp_mask); | ||
| 106 | extern void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, u64 pa_start, u64 pa_end); | ||
| 107 | extern void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 new_msr); | ||
| 108 | extern void kvmppc_mmu_book3s_64_init(struct kvm_vcpu *vcpu); | ||
| 109 | extern void kvmppc_mmu_book3s_32_init(struct kvm_vcpu *vcpu); | ||
| 110 | extern int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte); | ||
| 111 | extern int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr); | ||
| 112 | extern void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu); | ||
| 113 | extern struct kvmppc_pte *kvmppc_mmu_find_pte(struct kvm_vcpu *vcpu, u64 ea, bool data); | ||
| 114 | extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong eaddr, int size, void *ptr, bool data); | ||
| 115 | extern int kvmppc_st(struct kvm_vcpu *vcpu, ulong eaddr, int size, void *ptr); | ||
| 116 | extern void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec); | ||
| 117 | extern void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat, | ||
| 118 | bool upper, u32 val); | ||
| 119 | |||
| 120 | extern u32 kvmppc_trampoline_lowmem; | ||
| 121 | extern u32 kvmppc_trampoline_enter; | ||
| 122 | |||
| 123 | static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu) | ||
| 124 | { | ||
| 125 | return container_of(vcpu, struct kvmppc_vcpu_book3s, vcpu); | ||
| 126 | } | ||
| 127 | |||
| 128 | static inline ulong dsisr(void) | ||
| 129 | { | ||
| 130 | ulong r; | ||
| 131 | asm ( "mfdsisr %0 " : "=r" (r) ); | ||
| 132 | return r; | ||
| 133 | } | ||
| 134 | |||
| 135 | extern void kvm_return_point(void); | ||
| 136 | |||
| 137 | #define INS_DCBZ 0x7c0007ec | ||
| 138 | |||
| 139 | #endif /* __ASM_KVM_BOOK3S_H__ */ | ||
diff --git a/arch/powerpc/include/asm/kvm_book3s_64_asm.h b/arch/powerpc/include/asm/kvm_book3s_64_asm.h new file mode 100644 index 000000000000..2e06ee8184ef --- /dev/null +++ b/arch/powerpc/include/asm/kvm_book3s_64_asm.h | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | /* | ||
| 2 | * This program is free software; you can redistribute it and/or modify | ||
| 3 | * it under the terms of the GNU General Public License, version 2, as | ||
| 4 | * published by the Free Software Foundation. | ||
| 5 | * | ||
| 6 | * This program is distributed in the hope that it will be useful, | ||
| 7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 9 | * GNU General Public License for more details. | ||
| 10 | * | ||
| 11 | * You should have received a copy of the GNU General Public License | ||
| 12 | * along with this program; if not, write to the Free Software | ||
| 13 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 14 | * | ||
| 15 | * Copyright SUSE Linux Products GmbH 2009 | ||
| 16 | * | ||
| 17 | * Authors: Alexander Graf <agraf@suse.de> | ||
| 18 | */ | ||
| 19 | |||
| 20 | #ifndef __ASM_KVM_BOOK3S_ASM_H__ | ||
| 21 | #define __ASM_KVM_BOOK3S_ASM_H__ | ||
| 22 | |||
| 23 | #ifdef CONFIG_KVM_BOOK3S_64_HANDLER | ||
| 24 | |||
| 25 | #include <asm/kvm_asm.h> | ||
| 26 | |||
| 27 | .macro DO_KVM intno | ||
| 28 | .if (\intno == BOOK3S_INTERRUPT_SYSTEM_RESET) || \ | ||
| 29 | (\intno == BOOK3S_INTERRUPT_MACHINE_CHECK) || \ | ||
| 30 | (\intno == BOOK3S_INTERRUPT_DATA_STORAGE) || \ | ||
| 31 | (\intno == BOOK3S_INTERRUPT_INST_STORAGE) || \ | ||
| 32 | (\intno == BOOK3S_INTERRUPT_DATA_SEGMENT) || \ | ||
| 33 | (\intno == BOOK3S_INTERRUPT_INST_SEGMENT) || \ | ||
| 34 | (\intno == BOOK3S_INTERRUPT_EXTERNAL) || \ | ||
| 35 | (\intno == BOOK3S_INTERRUPT_ALIGNMENT) || \ | ||
| 36 | (\intno == BOOK3S_INTERRUPT_PROGRAM) || \ | ||
| 37 | (\intno == BOOK3S_INTERRUPT_FP_UNAVAIL) || \ | ||
| 38 | (\intno == BOOK3S_INTERRUPT_DECREMENTER) || \ | ||
| 39 | (\intno == BOOK3S_INTERRUPT_SYSCALL) || \ | ||
| 40 | (\intno == BOOK3S_INTERRUPT_TRACE) || \ | ||
| 41 | (\intno == BOOK3S_INTERRUPT_PERFMON) || \ | ||
| 42 | (\intno == BOOK3S_INTERRUPT_ALTIVEC) || \ | ||
| 43 | (\intno == BOOK3S_INTERRUPT_VSX) | ||
| 44 | |||
| 45 | b kvmppc_trampoline_\intno | ||
| 46 | kvmppc_resume_\intno: | ||
| 47 | |||
| 48 | .endif | ||
| 49 | .endm | ||
| 50 | |||
| 51 | #else | ||
| 52 | |||
| 53 | .macro DO_KVM intno | ||
| 54 | .endm | ||
| 55 | |||
| 56 | #endif /* CONFIG_KVM_BOOK3S_64_HANDLER */ | ||
| 57 | |||
| 58 | #endif /* __ASM_KVM_BOOK3S_ASM_H__ */ | ||
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index c9c930ed11d7..1201f62d0d73 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h | |||
| @@ -21,7 +21,8 @@ | |||
| 21 | #define __POWERPC_KVM_HOST_H__ | 21 | #define __POWERPC_KVM_HOST_H__ |
| 22 | 22 | ||
| 23 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
| 24 | #include <linux/timer.h> | 24 | #include <linux/hrtimer.h> |
| 25 | #include <linux/interrupt.h> | ||
| 25 | #include <linux/types.h> | 26 | #include <linux/types.h> |
| 26 | #include <linux/kvm_types.h> | 27 | #include <linux/kvm_types.h> |
| 27 | #include <asm/kvm_asm.h> | 28 | #include <asm/kvm_asm.h> |
| @@ -37,6 +38,8 @@ | |||
| 37 | #define KVM_NR_PAGE_SIZES 1 | 38 | #define KVM_NR_PAGE_SIZES 1 |
| 38 | #define KVM_PAGES_PER_HPAGE(x) (1UL<<31) | 39 | #define KVM_PAGES_PER_HPAGE(x) (1UL<<31) |
| 39 | 40 | ||
| 41 | #define HPTEG_CACHE_NUM 1024 | ||
| 42 | |||
| 40 | struct kvm; | 43 | struct kvm; |
| 41 | struct kvm_run; | 44 | struct kvm_run; |
| 42 | struct kvm_vcpu; | 45 | struct kvm_vcpu; |
| @@ -63,6 +66,17 @@ struct kvm_vcpu_stat { | |||
| 63 | u32 dec_exits; | 66 | u32 dec_exits; |
| 64 | u32 ext_intr_exits; | 67 | u32 ext_intr_exits; |
| 65 | u32 halt_wakeup; | 68 | u32 halt_wakeup; |
| 69 | #ifdef CONFIG_PPC64 | ||
| 70 | u32 pf_storage; | ||
| 71 | u32 pf_instruc; | ||
| 72 | u32 sp_storage; | ||
| 73 | u32 sp_instruc; | ||
| 74 | u32 queue_intr; | ||
| 75 | u32 ld; | ||
| 76 | u32 ld_slow; | ||
| 77 | u32 st; | ||
| 78 | u32 st_slow; | ||
| 79 | #endif | ||
| 66 | }; | 80 | }; |
| 67 | 81 | ||
| 68 | enum kvm_exit_types { | 82 | enum kvm_exit_types { |
| @@ -109,9 +123,53 @@ struct kvmppc_exit_timing { | |||
| 109 | struct kvm_arch { | 123 | struct kvm_arch { |
| 110 | }; | 124 | }; |
| 111 | 125 | ||
| 126 | struct kvmppc_pte { | ||
| 127 | u64 eaddr; | ||
| 128 | u64 vpage; | ||
| 129 | u64 raddr; | ||
| 130 | bool may_read; | ||
| 131 | bool may_write; | ||
| 132 | bool may_execute; | ||
| 133 | }; | ||
| 134 | |||
| 135 | struct kvmppc_mmu { | ||
| 136 | /* book3s_64 only */ | ||
| 137 | void (*slbmte)(struct kvm_vcpu *vcpu, u64 rb, u64 rs); | ||
| 138 | u64 (*slbmfee)(struct kvm_vcpu *vcpu, u64 slb_nr); | ||
| 139 | u64 (*slbmfev)(struct kvm_vcpu *vcpu, u64 slb_nr); | ||
| 140 | void (*slbie)(struct kvm_vcpu *vcpu, u64 slb_nr); | ||
| 141 | void (*slbia)(struct kvm_vcpu *vcpu); | ||
| 142 | /* book3s */ | ||
| 143 | void (*mtsrin)(struct kvm_vcpu *vcpu, u32 srnum, ulong value); | ||
| 144 | u32 (*mfsrin)(struct kvm_vcpu *vcpu, u32 srnum); | ||
| 145 | int (*xlate)(struct kvm_vcpu *vcpu, gva_t eaddr, struct kvmppc_pte *pte, bool data); | ||
| 146 | void (*reset_msr)(struct kvm_vcpu *vcpu); | ||
| 147 | void (*tlbie)(struct kvm_vcpu *vcpu, ulong addr, bool large); | ||
| 148 | int (*esid_to_vsid)(struct kvm_vcpu *vcpu, u64 esid, u64 *vsid); | ||
| 149 | u64 (*ea_to_vp)(struct kvm_vcpu *vcpu, gva_t eaddr, bool data); | ||
| 150 | bool (*is_dcbz32)(struct kvm_vcpu *vcpu); | ||
| 151 | }; | ||
| 152 | |||
| 153 | struct hpte_cache { | ||
| 154 | u64 host_va; | ||
| 155 | u64 pfn; | ||
| 156 | ulong slot; | ||
| 157 | struct kvmppc_pte pte; | ||
| 158 | }; | ||
| 159 | |||
| 112 | struct kvm_vcpu_arch { | 160 | struct kvm_vcpu_arch { |
| 113 | u32 host_stack; | 161 | ulong host_stack; |
| 114 | u32 host_pid; | 162 | u32 host_pid; |
| 163 | #ifdef CONFIG_PPC64 | ||
| 164 | ulong host_msr; | ||
| 165 | ulong host_r2; | ||
| 166 | void *host_retip; | ||
| 167 | ulong trampoline_lowmem; | ||
| 168 | ulong trampoline_enter; | ||
| 169 | ulong highmem_handler; | ||
| 170 | ulong host_paca_phys; | ||
| 171 | struct kvmppc_mmu mmu; | ||
| 172 | #endif | ||
| 115 | 173 | ||
| 116 | u64 fpr[32]; | 174 | u64 fpr[32]; |
| 117 | ulong gpr[32]; | 175 | ulong gpr[32]; |
| @@ -123,6 +181,10 @@ struct kvm_vcpu_arch { | |||
| 123 | ulong xer; | 181 | ulong xer; |
| 124 | 182 | ||
| 125 | ulong msr; | 183 | ulong msr; |
| 184 | #ifdef CONFIG_PPC64 | ||
| 185 | ulong shadow_msr; | ||
| 186 | ulong hflags; | ||
| 187 | #endif | ||
| 126 | u32 mmucr; | 188 | u32 mmucr; |
| 127 | ulong sprg0; | 189 | ulong sprg0; |
| 128 | ulong sprg1; | 190 | ulong sprg1; |
| @@ -149,6 +211,7 @@ struct kvm_vcpu_arch { | |||
| 149 | u32 ivor[64]; | 211 | u32 ivor[64]; |
| 150 | ulong ivpr; | 212 | ulong ivpr; |
| 151 | u32 pir; | 213 | u32 pir; |
| 214 | u32 pvr; | ||
| 152 | 215 | ||
| 153 | u32 shadow_pid; | 216 | u32 shadow_pid; |
| 154 | u32 pid; | 217 | u32 pid; |
| @@ -174,6 +237,9 @@ struct kvm_vcpu_arch { | |||
| 174 | #endif | 237 | #endif |
| 175 | 238 | ||
| 176 | u32 last_inst; | 239 | u32 last_inst; |
| 240 | #ifdef CONFIG_PPC64 | ||
| 241 | ulong fault_dsisr; | ||
| 242 | #endif | ||
| 177 | ulong fault_dear; | 243 | ulong fault_dear; |
| 178 | ulong fault_esr; | 244 | ulong fault_esr; |
| 179 | gpa_t paddr_accessed; | 245 | gpa_t paddr_accessed; |
| @@ -185,8 +251,15 @@ struct kvm_vcpu_arch { | |||
| 185 | 251 | ||
| 186 | u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */ | 252 | u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */ |
| 187 | 253 | ||
| 188 | struct timer_list dec_timer; | 254 | struct hrtimer dec_timer; |
| 255 | struct tasklet_struct tasklet; | ||
| 256 | u64 dec_jiffies; | ||
| 189 | unsigned long pending_exceptions; | 257 | unsigned long pending_exceptions; |
| 258 | |||
| 259 | #ifdef CONFIG_PPC64 | ||
| 260 | struct hpte_cache hpte_cache[HPTEG_CACHE_NUM]; | ||
| 261 | int hpte_cache_offset; | ||
| 262 | #endif | ||
| 190 | }; | 263 | }; |
| 191 | 264 | ||
| 192 | #endif /* __POWERPC_KVM_HOST_H__ */ | 265 | #endif /* __POWERPC_KVM_HOST_H__ */ |
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 2c6ee349df5e..269ee46ab028 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h | |||
| @@ -39,6 +39,7 @@ enum emulation_result { | |||
| 39 | extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu); | 39 | extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu); |
| 40 | extern char kvmppc_handlers_start[]; | 40 | extern char kvmppc_handlers_start[]; |
| 41 | extern unsigned long kvmppc_handler_len; | 41 | extern unsigned long kvmppc_handler_len; |
| 42 | extern void kvmppc_handler_highmem(void); | ||
| 42 | 43 | ||
| 43 | extern void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu); | 44 | extern void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu); |
| 44 | extern int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu, | 45 | extern int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu, |
diff --git a/arch/powerpc/include/asm/lppaca.h b/arch/powerpc/include/asm/lppaca.h index f78f65c38f05..14b592dfb4e8 100644 --- a/arch/powerpc/include/asm/lppaca.h +++ b/arch/powerpc/include/asm/lppaca.h | |||
| @@ -100,7 +100,14 @@ struct lppaca { | |||
| 100 | // Used to pass parms from the OS to PLIC for SetAsrAndRfid | 100 | // Used to pass parms from the OS to PLIC for SetAsrAndRfid |
| 101 | u64 saved_gpr3; // Saved GPR3 x20-x27 | 101 | u64 saved_gpr3; // Saved GPR3 x20-x27 |
| 102 | u64 saved_gpr4; // Saved GPR4 x28-x2F | 102 | u64 saved_gpr4; // Saved GPR4 x28-x2F |
| 103 | u64 saved_gpr5; // Saved GPR5 x30-x37 | 103 | union { |
| 104 | u64 saved_gpr5; /* Saved GPR5 x30-x37 */ | ||
| 105 | struct { | ||
| 106 | u8 cede_latency_hint; /* x30 */ | ||
| 107 | u8 reserved[7]; /* x31-x36 */ | ||
| 108 | } fields; | ||
| 109 | } gpr5_dword; | ||
| 110 | |||
| 104 | 111 | ||
| 105 | u8 dtl_enable_mask; // Dispatch Trace Log mask x38-x38 | 112 | u8 dtl_enable_mask; // Dispatch Trace Log mask x38-x38 |
| 106 | u8 donate_dedicated_cpu; // Donate dedicated CPU cycles x39-x39 | 113 | u8 donate_dedicated_cpu; // Donate dedicated CPU cycles x39-x39 |
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index 9efa2be78331..9f0fc9e6ce0d 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h | |||
| @@ -266,6 +266,11 @@ struct machdep_calls { | |||
| 266 | void (*suspend_disable_irqs)(void); | 266 | void (*suspend_disable_irqs)(void); |
| 267 | void (*suspend_enable_irqs)(void); | 267 | void (*suspend_enable_irqs)(void); |
| 268 | #endif | 268 | #endif |
| 269 | |||
| 270 | #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE | ||
| 271 | ssize_t (*cpu_probe)(const char *, size_t); | ||
| 272 | ssize_t (*cpu_release)(const char *, size_t); | ||
| 273 | #endif | ||
| 269 | }; | 274 | }; |
| 270 | 275 | ||
| 271 | extern void e500_idle(void); | 276 | extern void e500_idle(void); |
diff --git a/arch/powerpc/include/asm/macio.h b/arch/powerpc/include/asm/macio.h index 079c06eae446..a062c57696d0 100644 --- a/arch/powerpc/include/asm/macio.h +++ b/arch/powerpc/include/asm/macio.h | |||
| @@ -39,6 +39,7 @@ struct macio_dev | |||
| 39 | struct macio_bus *bus; /* macio bus this device is on */ | 39 | struct macio_bus *bus; /* macio bus this device is on */ |
| 40 | struct macio_dev *media_bay; /* Device is part of a media bay */ | 40 | struct macio_dev *media_bay; /* Device is part of a media bay */ |
| 41 | struct of_device ofdev; | 41 | struct of_device ofdev; |
| 42 | struct device_dma_parameters dma_parms; /* ide needs that */ | ||
| 42 | int n_resources; | 43 | int n_resources; |
| 43 | struct resource resource[MACIO_DEV_COUNT_RESOURCES]; | 44 | struct resource resource[MACIO_DEV_COUNT_RESOURCES]; |
| 44 | int n_interrupts; | 45 | int n_interrupts; |
| @@ -78,6 +79,8 @@ static inline unsigned long macio_resource_len(struct macio_dev *dev, int resour | |||
| 78 | return res->end - res->start + 1; | 79 | return res->end - res->start + 1; |
| 79 | } | 80 | } |
| 80 | 81 | ||
| 82 | extern int macio_enable_devres(struct macio_dev *dev); | ||
| 83 | |||
| 81 | extern int macio_request_resource(struct macio_dev *dev, int resource_no, const char *name); | 84 | extern int macio_request_resource(struct macio_dev *dev, int resource_no, const char *name); |
| 82 | extern void macio_release_resource(struct macio_dev *dev, int resource_no); | 85 | extern void macio_release_resource(struct macio_dev *dev, int resource_no); |
| 83 | extern int macio_request_resources(struct macio_dev *dev, const char *name); | 86 | extern int macio_request_resources(struct macio_dev *dev, const char *name); |
| @@ -131,6 +134,9 @@ struct macio_driver | |||
| 131 | int (*resume)(struct macio_dev* dev); | 134 | int (*resume)(struct macio_dev* dev); |
| 132 | int (*shutdown)(struct macio_dev* dev); | 135 | int (*shutdown)(struct macio_dev* dev); |
| 133 | 136 | ||
| 137 | #ifdef CONFIG_PMAC_MEDIABAY | ||
| 138 | void (*mediabay_event)(struct macio_dev* dev, int mb_state); | ||
| 139 | #endif | ||
| 134 | struct device_driver driver; | 140 | struct device_driver driver; |
| 135 | }; | 141 | }; |
| 136 | #define to_macio_driver(drv) container_of(drv,struct macio_driver, driver) | 142 | #define to_macio_driver(drv) container_of(drv,struct macio_driver, driver) |
diff --git a/arch/powerpc/include/asm/mediabay.h b/arch/powerpc/include/asm/mediabay.h index b2efb3325808..11037a4133ee 100644 --- a/arch/powerpc/include/asm/mediabay.h +++ b/arch/powerpc/include/asm/mediabay.h | |||
| @@ -17,26 +17,31 @@ | |||
| 17 | #define MB_POWER 6 /* media bay contains a Power device (???) */ | 17 | #define MB_POWER 6 /* media bay contains a Power device (???) */ |
| 18 | #define MB_NO 7 /* media bay contains nothing */ | 18 | #define MB_NO 7 /* media bay contains nothing */ |
| 19 | 19 | ||
| 20 | /* Number of bays in the machine or 0 */ | 20 | struct macio_dev; |
| 21 | extern int media_bay_count; | ||
| 22 | 21 | ||
| 23 | #ifdef CONFIG_BLK_DEV_IDE_PMAC | 22 | #ifdef CONFIG_PMAC_MEDIABAY |
| 24 | #include <linux/ide.h> | ||
| 25 | 23 | ||
| 26 | int check_media_bay_by_base(unsigned long base, int what); | 24 | /* Check the content type of the bay, returns MB_NO if the bay is still |
| 27 | /* called by IDE PMAC host driver to register IDE controller for media bay */ | 25 | * transitionning |
| 28 | int media_bay_set_ide_infos(struct device_node *which_bay, unsigned long base, | 26 | */ |
| 29 | int irq, ide_hwif_t *hwif); | 27 | extern int check_media_bay(struct macio_dev *bay); |
| 30 | 28 | ||
| 31 | int check_media_bay(struct device_node *which_bay, int what); | 29 | /* The ATA driver uses the calls below to temporarily hold on the |
| 30 | * media bay callbacks while initializing the interface | ||
| 31 | */ | ||
| 32 | extern void lock_media_bay(struct macio_dev *bay); | ||
| 33 | extern void unlock_media_bay(struct macio_dev *bay); | ||
| 32 | 34 | ||
| 33 | #else | 35 | #else |
| 34 | 36 | ||
| 35 | static inline int check_media_bay(struct device_node *which_bay, int what) | 37 | static inline int check_media_bay(struct macio_dev *bay) |
| 36 | { | 38 | { |
| 37 | return -ENODEV; | 39 | return MB_NO; |
| 38 | } | 40 | } |
| 39 | 41 | ||
| 42 | static inline void lock_media_bay(struct macio_dev *bay) { } | ||
| 43 | static inline void unlock_media_bay(struct macio_dev *bay) { } | ||
| 44 | |||
| 40 | #endif | 45 | #endif |
| 41 | 46 | ||
| 42 | #endif /* __KERNEL__ */ | 47 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h index bebe31c2e907..2102b214a87c 100644 --- a/arch/powerpc/include/asm/mmu-hash64.h +++ b/arch/powerpc/include/asm/mmu-hash64.h | |||
| @@ -173,14 +173,6 @@ extern unsigned long tce_alloc_start, tce_alloc_end; | |||
| 173 | */ | 173 | */ |
| 174 | extern int mmu_ci_restrictions; | 174 | extern int mmu_ci_restrictions; |
| 175 | 175 | ||
| 176 | #ifdef CONFIG_HUGETLB_PAGE | ||
| 177 | /* | ||
| 178 | * The page size indexes of the huge pages for use by hugetlbfs | ||
| 179 | */ | ||
| 180 | extern unsigned int mmu_huge_psizes[MMU_PAGE_COUNT]; | ||
| 181 | |||
| 182 | #endif /* CONFIG_HUGETLB_PAGE */ | ||
| 183 | |||
| 184 | /* | 176 | /* |
| 185 | * This function sets the AVPN and L fields of the HPTE appropriately | 177 | * This function sets the AVPN and L fields of the HPTE appropriately |
| 186 | * for the page size | 178 | * for the page size |
| @@ -253,10 +245,11 @@ extern int __hash_page_64K(unsigned long ea, unsigned long access, | |||
| 253 | unsigned long vsid, pte_t *ptep, unsigned long trap, | 245 | unsigned long vsid, pte_t *ptep, unsigned long trap, |
| 254 | unsigned int local, int ssize); | 246 | unsigned int local, int ssize); |
| 255 | struct mm_struct; | 247 | struct mm_struct; |
| 248 | unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap); | ||
| 256 | extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); | 249 | extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); |
| 257 | extern int hash_huge_page(struct mm_struct *mm, unsigned long access, | 250 | int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid, |
| 258 | unsigned long ea, unsigned long vsid, int local, | 251 | pte_t *ptep, unsigned long trap, int local, int ssize, |
| 259 | unsigned long trap); | 252 | unsigned int shift, unsigned int mmu_psize); |
| 260 | 253 | ||
| 261 | extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend, | 254 | extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend, |
| 262 | unsigned long pstart, unsigned long prot, | 255 | unsigned long pstart, unsigned long prot, |
| @@ -380,6 +373,38 @@ extern void slb_set_size(u16 size); | |||
| 380 | 373 | ||
| 381 | #ifndef __ASSEMBLY__ | 374 | #ifndef __ASSEMBLY__ |
| 382 | 375 | ||
| 376 | #ifdef CONFIG_PPC_SUBPAGE_PROT | ||
| 377 | /* | ||
| 378 | * For the sub-page protection option, we extend the PGD with one of | ||
| 379 | * these. Basically we have a 3-level tree, with the top level being | ||
| 380 | * the protptrs array. To optimize speed and memory consumption when | ||
| 381 | * only addresses < 4GB are being protected, pointers to the first | ||
| 382 | * four pages of sub-page protection words are stored in the low_prot | ||
| 383 | * array. | ||
| 384 | * Each page of sub-page protection words protects 1GB (4 bytes | ||
| 385 | * protects 64k). For the 3-level tree, each page of pointers then | ||
| 386 | * protects 8TB. | ||
| 387 | */ | ||
| 388 | struct subpage_prot_table { | ||
| 389 | unsigned long maxaddr; /* only addresses < this are protected */ | ||
| 390 | unsigned int **protptrs[2]; | ||
| 391 | unsigned int *low_prot[4]; | ||
| 392 | }; | ||
| 393 | |||
| 394 | #define SBP_L1_BITS (PAGE_SHIFT - 2) | ||
| 395 | #define SBP_L2_BITS (PAGE_SHIFT - 3) | ||
| 396 | #define SBP_L1_COUNT (1 << SBP_L1_BITS) | ||
| 397 | #define SBP_L2_COUNT (1 << SBP_L2_BITS) | ||
| 398 | #define SBP_L2_SHIFT (PAGE_SHIFT + SBP_L1_BITS) | ||
| 399 | #define SBP_L3_SHIFT (SBP_L2_SHIFT + SBP_L2_BITS) | ||
| 400 | |||
| 401 | extern void subpage_prot_free(struct mm_struct *mm); | ||
| 402 | extern void subpage_prot_init_new_context(struct mm_struct *mm); | ||
| 403 | #else | ||
| 404 | static inline void subpage_prot_free(struct mm_struct *mm) {} | ||
| 405 | static inline void subpage_prot_init_new_context(struct mm_struct *mm) { } | ||
| 406 | #endif /* CONFIG_PPC_SUBPAGE_PROT */ | ||
| 407 | |||
| 383 | typedef unsigned long mm_context_id_t; | 408 | typedef unsigned long mm_context_id_t; |
| 384 | 409 | ||
| 385 | typedef struct { | 410 | typedef struct { |
| @@ -393,6 +418,9 @@ typedef struct { | |||
| 393 | u16 sllp; /* SLB page size encoding */ | 418 | u16 sllp; /* SLB page size encoding */ |
| 394 | #endif | 419 | #endif |
| 395 | unsigned long vdso_base; | 420 | unsigned long vdso_base; |
| 421 | #ifdef CONFIG_PPC_SUBPAGE_PROT | ||
| 422 | struct subpage_prot_table spt; | ||
| 423 | #endif /* CONFIG_PPC_SUBPAGE_PROT */ | ||
| 396 | } mm_context_t; | 424 | } mm_context_t; |
| 397 | 425 | ||
| 398 | 426 | ||
diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index b34e94d94435..26383e0778aa 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h | |||
| @@ -23,6 +23,8 @@ extern void switch_slb(struct task_struct *tsk, struct mm_struct *mm); | |||
| 23 | extern void set_context(unsigned long id, pgd_t *pgd); | 23 | extern void set_context(unsigned long id, pgd_t *pgd); |
| 24 | 24 | ||
| 25 | #ifdef CONFIG_PPC_BOOK3S_64 | 25 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 26 | extern int __init_new_context(void); | ||
| 27 | extern void __destroy_context(int context_id); | ||
| 26 | static inline void mmu_context_init(void) { } | 28 | static inline void mmu_context_init(void) { } |
| 27 | #else | 29 | #else |
| 28 | extern void mmu_context_init(void); | 30 | extern void mmu_context_init(void); |
diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h index 08454880a2c0..0192a4ee2bc2 100644 --- a/arch/powerpc/include/asm/module.h +++ b/arch/powerpc/include/asm/module.h | |||
| @@ -87,5 +87,10 @@ struct exception_table_entry; | |||
| 87 | void sort_ex_table(struct exception_table_entry *start, | 87 | void sort_ex_table(struct exception_table_entry *start, |
| 88 | struct exception_table_entry *finish); | 88 | struct exception_table_entry *finish); |
| 89 | 89 | ||
| 90 | #ifdef CONFIG_MODVERSIONS | ||
| 91 | #define ARCH_RELOCATES_KCRCTAB | ||
| 92 | |||
| 93 | extern const unsigned long reloc_start[]; | ||
| 94 | #endif | ||
| 90 | #endif /* __KERNEL__ */ | 95 | #endif /* __KERNEL__ */ |
| 91 | #endif /* _ASM_POWERPC_MODULE_H */ | 96 | #endif /* _ASM_POWERPC_MODULE_H */ |
diff --git a/arch/powerpc/include/asm/mpc52xx.h b/arch/powerpc/include/asm/mpc52xx.h index 1b4f697abbdd..b664ce79a172 100644 --- a/arch/powerpc/include/asm/mpc52xx.h +++ b/arch/powerpc/include/asm/mpc52xx.h | |||
| @@ -276,6 +276,53 @@ extern int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv); | |||
| 276 | extern unsigned int mpc52xx_get_xtal_freq(struct device_node *node); | 276 | extern unsigned int mpc52xx_get_xtal_freq(struct device_node *node); |
| 277 | extern void mpc52xx_restart(char *cmd); | 277 | extern void mpc52xx_restart(char *cmd); |
| 278 | 278 | ||
| 279 | /* mpc52xx_gpt.c */ | ||
| 280 | struct mpc52xx_gpt_priv; | ||
| 281 | extern struct mpc52xx_gpt_priv *mpc52xx_gpt_from_irq(int irq); | ||
| 282 | extern int mpc52xx_gpt_start_timer(struct mpc52xx_gpt_priv *gpt, u64 period, | ||
| 283 | int continuous); | ||
| 284 | extern u64 mpc52xx_gpt_timer_period(struct mpc52xx_gpt_priv *gpt); | ||
| 285 | extern int mpc52xx_gpt_stop_timer(struct mpc52xx_gpt_priv *gpt); | ||
| 286 | |||
| 287 | /* mpc52xx_lpbfifo.c */ | ||
| 288 | #define MPC52XX_LPBFIFO_FLAG_READ (0) | ||
| 289 | #define MPC52XX_LPBFIFO_FLAG_WRITE (1<<0) | ||
| 290 | #define MPC52XX_LPBFIFO_FLAG_NO_INCREMENT (1<<1) | ||
| 291 | #define MPC52XX_LPBFIFO_FLAG_NO_DMA (1<<2) | ||
| 292 | #define MPC52XX_LPBFIFO_FLAG_POLL_DMA (1<<3) | ||
| 293 | |||
| 294 | struct mpc52xx_lpbfifo_request { | ||
| 295 | struct list_head list; | ||
| 296 | |||
| 297 | /* localplus bus address */ | ||
| 298 | unsigned int cs; | ||
| 299 | size_t offset; | ||
| 300 | |||
| 301 | /* Memory address */ | ||
| 302 | void *data; | ||
| 303 | phys_addr_t data_phys; | ||
| 304 | |||
| 305 | /* Details of transfer */ | ||
| 306 | size_t size; | ||
| 307 | size_t pos; /* current position of transfer */ | ||
| 308 | int flags; | ||
| 309 | |||
| 310 | /* What to do when finished */ | ||
| 311 | void (*callback)(struct mpc52xx_lpbfifo_request *); | ||
| 312 | |||
| 313 | void *priv; /* Driver private data */ | ||
| 314 | |||
| 315 | /* statistics */ | ||
| 316 | int irq_count; | ||
| 317 | int irq_ticks; | ||
| 318 | u8 last_byte; | ||
| 319 | int buffer_not_done_cnt; | ||
| 320 | }; | ||
| 321 | |||
| 322 | extern int mpc52xx_lpbfifo_submit(struct mpc52xx_lpbfifo_request *req); | ||
| 323 | extern void mpc52xx_lpbfifo_abort(struct mpc52xx_lpbfifo_request *req); | ||
| 324 | extern void mpc52xx_lpbfifo_poll(void); | ||
| 325 | |||
| 279 | /* mpc52xx_pic.c */ | 326 | /* mpc52xx_pic.c */ |
| 280 | extern void mpc52xx_init_irq(void); | 327 | extern void mpc52xx_init_irq(void); |
| 281 | extern unsigned int mpc52xx_get_irq(void); | 328 | extern unsigned int mpc52xx_get_irq(void); |
diff --git a/arch/powerpc/include/asm/nvram.h b/arch/powerpc/include/asm/nvram.h index 6c587eddee59..850b72f27445 100644 --- a/arch/powerpc/include/asm/nvram.h +++ b/arch/powerpc/include/asm/nvram.h | |||
| @@ -73,7 +73,6 @@ extern int nvram_write_error_log(char * buff, int length, | |||
| 73 | extern int nvram_read_error_log(char * buff, int length, | 73 | extern int nvram_read_error_log(char * buff, int length, |
| 74 | unsigned int * err_type, unsigned int *err_seq); | 74 | unsigned int * err_type, unsigned int *err_seq); |
| 75 | extern int nvram_clear_error_log(void); | 75 | extern int nvram_clear_error_log(void); |
| 76 | extern struct nvram_partition *nvram_find_partition(int sig, const char *name); | ||
| 77 | 76 | ||
| 78 | extern int pSeries_nvram_init(void); | 77 | extern int pSeries_nvram_init(void); |
| 79 | 78 | ||
diff --git a/arch/powerpc/include/asm/pSeries_reconfig.h b/arch/powerpc/include/asm/pSeries_reconfig.h index e482e5352e69..d4b4bfa26fb3 100644 --- a/arch/powerpc/include/asm/pSeries_reconfig.h +++ b/arch/powerpc/include/asm/pSeries_reconfig.h | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #ifdef CONFIG_PPC_PSERIES | 17 | #ifdef CONFIG_PPC_PSERIES |
| 18 | extern int pSeries_reconfig_notifier_register(struct notifier_block *); | 18 | extern int pSeries_reconfig_notifier_register(struct notifier_block *); |
| 19 | extern void pSeries_reconfig_notifier_unregister(struct notifier_block *); | 19 | extern void pSeries_reconfig_notifier_unregister(struct notifier_block *); |
| 20 | extern struct blocking_notifier_head pSeries_reconfig_chain; | ||
| 20 | #else /* !CONFIG_PPC_PSERIES */ | 21 | #else /* !CONFIG_PPC_PSERIES */ |
| 21 | static inline int pSeries_reconfig_notifier_register(struct notifier_block *nb) | 22 | static inline int pSeries_reconfig_notifier_register(struct notifier_block *nb) |
| 22 | { | 23 | { |
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index 7d8514ceceae..5e9b4ef71415 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h | |||
| @@ -129,6 +129,15 @@ struct paca_struct { | |||
| 129 | u64 system_time; /* accumulated system TB ticks */ | 129 | u64 system_time; /* accumulated system TB ticks */ |
| 130 | u64 startpurr; /* PURR/TB value snapshot */ | 130 | u64 startpurr; /* PURR/TB value snapshot */ |
| 131 | u64 startspurr; /* SPURR value snapshot */ | 131 | u64 startspurr; /* SPURR value snapshot */ |
| 132 | |||
| 133 | #ifdef CONFIG_KVM_BOOK3S_64_HANDLER | ||
| 134 | struct { | ||
| 135 | u64 esid; | ||
| 136 | u64 vsid; | ||
| 137 | } kvm_slb[64]; /* guest SLB */ | ||
| 138 | u8 kvm_slb_max; /* highest used guest slb entry */ | ||
| 139 | u8 kvm_in_guest; /* are we inside the guest? */ | ||
| 140 | #endif | ||
| 132 | }; | 141 | }; |
| 133 | 142 | ||
| 134 | extern struct paca_struct paca[]; | 143 | extern struct paca_struct paca[]; |
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h index ff24254990e1..e96d52a516ba 100644 --- a/arch/powerpc/include/asm/page.h +++ b/arch/powerpc/include/asm/page.h | |||
| @@ -229,6 +229,20 @@ typedef unsigned long pgprot_t; | |||
| 229 | 229 | ||
| 230 | #endif | 230 | #endif |
| 231 | 231 | ||
| 232 | typedef struct { signed long pd; } hugepd_t; | ||
| 233 | #define HUGEPD_SHIFT_MASK 0x3f | ||
| 234 | |||
| 235 | #ifdef CONFIG_HUGETLB_PAGE | ||
| 236 | static inline int hugepd_ok(hugepd_t hpd) | ||
| 237 | { | ||
| 238 | return (hpd.pd > 0); | ||
| 239 | } | ||
| 240 | |||
| 241 | #define is_hugepd(pdep) (hugepd_ok(*((hugepd_t *)(pdep)))) | ||
| 242 | #else /* CONFIG_HUGETLB_PAGE */ | ||
| 243 | #define is_hugepd(pdep) 0 | ||
| 244 | #endif /* CONFIG_HUGETLB_PAGE */ | ||
| 245 | |||
| 232 | struct page; | 246 | struct page; |
| 233 | extern void clear_user_page(void *page, unsigned long vaddr, struct page *pg); | 247 | extern void clear_user_page(void *page, unsigned long vaddr, struct page *pg); |
| 234 | extern void copy_user_page(void *to, void *from, unsigned long vaddr, | 248 | extern void copy_user_page(void *to, void *from, unsigned long vaddr, |
diff --git a/arch/powerpc/include/asm/page_64.h b/arch/powerpc/include/asm/page_64.h index 3f17b83f55a1..bfc4e027e2ad 100644 --- a/arch/powerpc/include/asm/page_64.h +++ b/arch/powerpc/include/asm/page_64.h | |||
| @@ -90,7 +90,7 @@ extern unsigned int HPAGE_SHIFT; | |||
| 90 | #define HPAGE_SIZE ((1UL) << HPAGE_SHIFT) | 90 | #define HPAGE_SIZE ((1UL) << HPAGE_SHIFT) |
| 91 | #define HPAGE_MASK (~(HPAGE_SIZE - 1)) | 91 | #define HPAGE_MASK (~(HPAGE_SIZE - 1)) |
| 92 | #define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) | 92 | #define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) |
| 93 | #define HUGE_MAX_HSTATE 3 | 93 | #define HUGE_MAX_HSTATE (MMU_PAGE_COUNT-1) |
| 94 | 94 | ||
| 95 | #endif /* __ASSEMBLY__ */ | 95 | #endif /* __ASSEMBLY__ */ |
| 96 | 96 | ||
diff --git a/arch/powerpc/include/asm/pgalloc-32.h b/arch/powerpc/include/asm/pgalloc-32.h index c9500d666a1d..580cf73b96e8 100644 --- a/arch/powerpc/include/asm/pgalloc-32.h +++ b/arch/powerpc/include/asm/pgalloc-32.h | |||
| @@ -3,7 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | #include <linux/threads.h> | 4 | #include <linux/threads.h> |
| 5 | 5 | ||
| 6 | #define PTE_NONCACHE_NUM 0 /* dummy for now to share code w/ppc64 */ | 6 | /* For 32-bit, all levels of page tables are just drawn from get_free_page() */ |
| 7 | #define MAX_PGTABLE_INDEX_SIZE 0 | ||
| 7 | 8 | ||
| 8 | extern void __bad_pte(pmd_t *pmd); | 9 | extern void __bad_pte(pmd_t *pmd); |
| 9 | 10 | ||
| @@ -36,11 +37,10 @@ extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); | |||
| 36 | extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr); | 37 | extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr); |
| 37 | extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr); | 38 | extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr); |
| 38 | 39 | ||
| 39 | static inline void pgtable_free(pgtable_free_t pgf) | 40 | static inline void pgtable_free(void *table, unsigned index_size) |
| 40 | { | 41 | { |
| 41 | void *p = (void *)(pgf.val & ~PGF_CACHENUM_MASK); | 42 | BUG_ON(index_size); /* 32-bit doesn't use this */ |
| 42 | 43 | free_page((unsigned long)table); | |
| 43 | free_page((unsigned long)p); | ||
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | #define check_pgt_cache() do { } while (0) | 46 | #define check_pgt_cache() do { } while (0) |
diff --git a/arch/powerpc/include/asm/pgalloc-64.h b/arch/powerpc/include/asm/pgalloc-64.h index e6f069c4f713..605f5c5398d1 100644 --- a/arch/powerpc/include/asm/pgalloc-64.h +++ b/arch/powerpc/include/asm/pgalloc-64.h | |||
| @@ -11,27 +11,34 @@ | |||
| 11 | #include <linux/cpumask.h> | 11 | #include <linux/cpumask.h> |
| 12 | #include <linux/percpu.h> | 12 | #include <linux/percpu.h> |
| 13 | 13 | ||
| 14 | #ifndef CONFIG_PPC_SUBPAGE_PROT | 14 | /* |
| 15 | static inline void subpage_prot_free(pgd_t *pgd) {} | 15 | * Functions that deal with pagetables that could be at any level of |
| 16 | #endif | 16 | * the table need to be passed an "index_size" so they know how to |
| 17 | * handle allocation. For PTE pages (which are linked to a struct | ||
| 18 | * page for now, and drawn from the main get_free_pages() pool), the | ||
| 19 | * allocation size will be (2^index_size * sizeof(pointer)) and | ||
| 20 | * allocations are drawn from the kmem_cache in PGT_CACHE(index_size). | ||
| 21 | * | ||
| 22 | * The maximum index size needs to be big enough to allow any | ||
| 23 | * pagetable sizes we need, but small enough to fit in the low bits of | ||
| 24 | * any page table pointer. In other words all pagetables, even tiny | ||
| 25 | * ones, must be aligned to allow at least enough low 0 bits to | ||
| 26 | * contain this value. This value is also used as a mask, so it must | ||
| 27 | * be one less than a power of two. | ||
| 28 | */ | ||
| 29 | #define MAX_PGTABLE_INDEX_SIZE 0xf | ||
| 17 | 30 | ||
| 18 | extern struct kmem_cache *pgtable_cache[]; | 31 | extern struct kmem_cache *pgtable_cache[]; |
| 19 | 32 | #define PGT_CACHE(shift) (pgtable_cache[(shift)-1]) | |
| 20 | #define PGD_CACHE_NUM 0 | ||
| 21 | #define PUD_CACHE_NUM 1 | ||
| 22 | #define PMD_CACHE_NUM 1 | ||
| 23 | #define HUGEPTE_CACHE_NUM 2 | ||
| 24 | #define PTE_NONCACHE_NUM 7 /* from GFP rather than kmem_cache */ | ||
| 25 | 33 | ||
| 26 | static inline pgd_t *pgd_alloc(struct mm_struct *mm) | 34 | static inline pgd_t *pgd_alloc(struct mm_struct *mm) |
| 27 | { | 35 | { |
| 28 | return kmem_cache_alloc(pgtable_cache[PGD_CACHE_NUM], GFP_KERNEL); | 36 | return kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE), GFP_KERNEL); |
| 29 | } | 37 | } |
| 30 | 38 | ||
| 31 | static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) | 39 | static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) |
| 32 | { | 40 | { |
| 33 | subpage_prot_free(pgd); | 41 | kmem_cache_free(PGT_CACHE(PGD_INDEX_SIZE), pgd); |
| 34 | kmem_cache_free(pgtable_cache[PGD_CACHE_NUM], pgd); | ||
| 35 | } | 42 | } |
| 36 | 43 | ||
| 37 | #ifndef CONFIG_PPC_64K_PAGES | 44 | #ifndef CONFIG_PPC_64K_PAGES |
| @@ -40,13 +47,13 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) | |||
| 40 | 47 | ||
| 41 | static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) | 48 | static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) |
| 42 | { | 49 | { |
| 43 | return kmem_cache_alloc(pgtable_cache[PUD_CACHE_NUM], | 50 | return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE), |
| 44 | GFP_KERNEL|__GFP_REPEAT); | 51 | GFP_KERNEL|__GFP_REPEAT); |
| 45 | } | 52 | } |
| 46 | 53 | ||
| 47 | static inline void pud_free(struct mm_struct *mm, pud_t *pud) | 54 | static inline void pud_free(struct mm_struct *mm, pud_t *pud) |
| 48 | { | 55 | { |
| 49 | kmem_cache_free(pgtable_cache[PUD_CACHE_NUM], pud); | 56 | kmem_cache_free(PGT_CACHE(PUD_INDEX_SIZE), pud); |
| 50 | } | 57 | } |
| 51 | 58 | ||
| 52 | static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) | 59 | static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) |
| @@ -78,13 +85,13 @@ static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, | |||
| 78 | 85 | ||
| 79 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) | 86 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) |
| 80 | { | 87 | { |
| 81 | return kmem_cache_alloc(pgtable_cache[PMD_CACHE_NUM], | 88 | return kmem_cache_alloc(PGT_CACHE(PMD_INDEX_SIZE), |
| 82 | GFP_KERNEL|__GFP_REPEAT); | 89 | GFP_KERNEL|__GFP_REPEAT); |
| 83 | } | 90 | } |
| 84 | 91 | ||
| 85 | static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) | 92 | static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) |
| 86 | { | 93 | { |
| 87 | kmem_cache_free(pgtable_cache[PMD_CACHE_NUM], pmd); | 94 | kmem_cache_free(PGT_CACHE(PMD_INDEX_SIZE), pmd); |
| 88 | } | 95 | } |
| 89 | 96 | ||
| 90 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, | 97 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, |
| @@ -107,24 +114,22 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm, | |||
| 107 | return page; | 114 | return page; |
| 108 | } | 115 | } |
| 109 | 116 | ||
| 110 | static inline void pgtable_free(pgtable_free_t pgf) | 117 | static inline void pgtable_free(void *table, unsigned index_size) |
| 111 | { | 118 | { |
| 112 | void *p = (void *)(pgf.val & ~PGF_CACHENUM_MASK); | 119 | if (!index_size) |
| 113 | int cachenum = pgf.val & PGF_CACHENUM_MASK; | 120 | free_page((unsigned long)table); |
| 114 | 121 | else { | |
| 115 | if (cachenum == PTE_NONCACHE_NUM) | 122 | BUG_ON(index_size > MAX_PGTABLE_INDEX_SIZE); |
| 116 | free_page((unsigned long)p); | 123 | kmem_cache_free(PGT_CACHE(index_size), table); |
| 117 | else | 124 | } |
| 118 | kmem_cache_free(pgtable_cache[cachenum], p); | ||
| 119 | } | 125 | } |
| 120 | 126 | ||
| 121 | #define __pmd_free_tlb(tlb, pmd,addr) \ | 127 | #define __pmd_free_tlb(tlb, pmd, addr) \ |
| 122 | pgtable_free_tlb(tlb, pgtable_free_cache(pmd, \ | 128 | pgtable_free_tlb(tlb, pmd, PMD_INDEX_SIZE) |
| 123 | PMD_CACHE_NUM, PMD_TABLE_SIZE-1)) | ||
| 124 | #ifndef CONFIG_PPC_64K_PAGES | 129 | #ifndef CONFIG_PPC_64K_PAGES |
| 125 | #define __pud_free_tlb(tlb, pud, addr) \ | 130 | #define __pud_free_tlb(tlb, pud, addr) \ |
| 126 | pgtable_free_tlb(tlb, pgtable_free_cache(pud, \ | 131 | pgtable_free_tlb(tlb, pud, PUD_INDEX_SIZE) |
| 127 | PUD_CACHE_NUM, PUD_TABLE_SIZE-1)) | 132 | |
| 128 | #endif /* CONFIG_PPC_64K_PAGES */ | 133 | #endif /* CONFIG_PPC_64K_PAGES */ |
| 129 | 134 | ||
| 130 | #define check_pgt_cache() do { } while (0) | 135 | #define check_pgt_cache() do { } while (0) |
diff --git a/arch/powerpc/include/asm/pgalloc.h b/arch/powerpc/include/asm/pgalloc.h index f2e812de7c3c..abe8532bd14e 100644 --- a/arch/powerpc/include/asm/pgalloc.h +++ b/arch/powerpc/include/asm/pgalloc.h | |||
| @@ -24,25 +24,6 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage) | |||
| 24 | __free_page(ptepage); | 24 | __free_page(ptepage); |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | typedef struct pgtable_free { | ||
| 28 | unsigned long val; | ||
| 29 | } pgtable_free_t; | ||
| 30 | |||
| 31 | /* This needs to be big enough to allow for MMU_PAGE_COUNT + 2 to be stored | ||
| 32 | * and small enough to fit in the low bits of any naturally aligned page | ||
| 33 | * table cache entry. Arbitrarily set to 0x1f, that should give us some | ||
| 34 | * room to grow | ||
| 35 | */ | ||
| 36 | #define PGF_CACHENUM_MASK 0x1f | ||
| 37 | |||
| 38 | static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum, | ||
| 39 | unsigned long mask) | ||
| 40 | { | ||
| 41 | BUG_ON(cachenum > PGF_CACHENUM_MASK); | ||
| 42 | |||
| 43 | return (pgtable_free_t){.val = ((unsigned long) p & ~mask) | cachenum}; | ||
| 44 | } | ||
| 45 | |||
| 46 | #ifdef CONFIG_PPC64 | 27 | #ifdef CONFIG_PPC64 |
| 47 | #include <asm/pgalloc-64.h> | 28 | #include <asm/pgalloc-64.h> |
| 48 | #else | 29 | #else |
| @@ -50,12 +31,12 @@ static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum, | |||
| 50 | #endif | 31 | #endif |
| 51 | 32 | ||
| 52 | #ifdef CONFIG_SMP | 33 | #ifdef CONFIG_SMP |
| 53 | extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf); | 34 | extern void pgtable_free_tlb(struct mmu_gather *tlb, void *table, unsigned shift); |
| 54 | extern void pte_free_finish(void); | 35 | extern void pte_free_finish(void); |
| 55 | #else /* CONFIG_SMP */ | 36 | #else /* CONFIG_SMP */ |
| 56 | static inline void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf) | 37 | static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, unsigned shift) |
| 57 | { | 38 | { |
| 58 | pgtable_free(pgf); | 39 | pgtable_free(table, shift); |
| 59 | } | 40 | } |
| 60 | static inline void pte_free_finish(void) { } | 41 | static inline void pte_free_finish(void) { } |
| 61 | #endif /* !CONFIG_SMP */ | 42 | #endif /* !CONFIG_SMP */ |
| @@ -63,12 +44,9 @@ static inline void pte_free_finish(void) { } | |||
| 63 | static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage, | 44 | static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage, |
| 64 | unsigned long address) | 45 | unsigned long address) |
| 65 | { | 46 | { |
| 66 | pgtable_free_t pgf = pgtable_free_cache(page_address(ptepage), | ||
| 67 | PTE_NONCACHE_NUM, | ||
| 68 | PTE_TABLE_SIZE-1); | ||
| 69 | tlb_flush_pgtable(tlb, address); | 47 | tlb_flush_pgtable(tlb, address); |
| 70 | pgtable_page_dtor(ptepage); | 48 | pgtable_page_dtor(ptepage); |
| 71 | pgtable_free_tlb(tlb, pgf); | 49 | pgtable_free_tlb(tlb, page_address(ptepage), 0); |
| 72 | } | 50 | } |
| 73 | 51 | ||
| 74 | #endif /* __KERNEL__ */ | 52 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h index 806abe7a3fa5..49865045d56f 100644 --- a/arch/powerpc/include/asm/pgtable-ppc64.h +++ b/arch/powerpc/include/asm/pgtable-ppc64.h | |||
| @@ -354,6 +354,7 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry) | |||
| 354 | #define pgoff_to_pte(off) ((pte_t) {((off) << PTE_RPN_SHIFT)|_PAGE_FILE}) | 354 | #define pgoff_to_pte(off) ((pte_t) {((off) << PTE_RPN_SHIFT)|_PAGE_FILE}) |
| 355 | #define PTE_FILE_MAX_BITS (BITS_PER_LONG - PTE_RPN_SHIFT) | 355 | #define PTE_FILE_MAX_BITS (BITS_PER_LONG - PTE_RPN_SHIFT) |
| 356 | 356 | ||
| 357 | void pgtable_cache_add(unsigned shift, void (*ctor)(void *)); | ||
| 357 | void pgtable_cache_init(void); | 358 | void pgtable_cache_init(void); |
| 358 | 359 | ||
| 359 | /* | 360 | /* |
| @@ -378,7 +379,18 @@ void pgtable_cache_init(void); | |||
| 378 | return pt; | 379 | return pt; |
| 379 | } | 380 | } |
| 380 | 381 | ||
| 381 | pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long address); | 382 | #ifdef CONFIG_HUGETLB_PAGE |
| 383 | pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, | ||
| 384 | unsigned *shift); | ||
| 385 | #else | ||
| 386 | static inline pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, | ||
| 387 | unsigned *shift) | ||
| 388 | { | ||
| 389 | if (shift) | ||
| 390 | *shift = 0; | ||
| 391 | return find_linux_pte(pgdir, ea); | ||
| 392 | } | ||
| 393 | #endif /* !CONFIG_HUGETLB_PAGE */ | ||
| 382 | 394 | ||
| 383 | #endif /* __ASSEMBLY__ */ | 395 | #endif /* __ASSEMBLY__ */ |
| 384 | 396 | ||
diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h index 2a5da069714e..21207e54825b 100644 --- a/arch/powerpc/include/asm/pgtable.h +++ b/arch/powerpc/include/asm/pgtable.h | |||
| @@ -211,6 +211,9 @@ extern void paging_init(void); | |||
| 211 | */ | 211 | */ |
| 212 | extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); | 212 | extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); |
| 213 | 213 | ||
| 214 | extern int gup_hugepd(hugepd_t *hugepd, unsigned pdshift, unsigned long addr, | ||
| 215 | unsigned long end, int write, struct page **pages, int *nr); | ||
| 216 | |||
| 214 | #endif /* __ASSEMBLY__ */ | 217 | #endif /* __ASSEMBLY__ */ |
| 215 | 218 | ||
| 216 | #endif /* __KERNEL__ */ | 219 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/include/asm/pte-8xx.h b/arch/powerpc/include/asm/pte-8xx.h index dd5ea95fe61e..d44826e4ff97 100644 --- a/arch/powerpc/include/asm/pte-8xx.h +++ b/arch/powerpc/include/asm/pte-8xx.h | |||
| @@ -33,21 +33,21 @@ | |||
| 33 | #define _PAGE_NO_CACHE 0x0002 /* I: cache inhibit */ | 33 | #define _PAGE_NO_CACHE 0x0002 /* I: cache inhibit */ |
| 34 | #define _PAGE_SHARED 0x0004 /* No ASID (context) compare */ | 34 | #define _PAGE_SHARED 0x0004 /* No ASID (context) compare */ |
| 35 | #define _PAGE_SPECIAL 0x0008 /* SW entry, forced to 0 by the TLB miss */ | 35 | #define _PAGE_SPECIAL 0x0008 /* SW entry, forced to 0 by the TLB miss */ |
| 36 | #define _PAGE_DIRTY 0x0100 /* C: page changed */ | ||
| 36 | 37 | ||
| 37 | /* These five software bits must be masked out when the entry is loaded | 38 | /* These 4 software bits must be masked out when the entry is loaded |
| 38 | * into the TLB. | 39 | * into the TLB, 1 SW bit left(0x0080). |
| 39 | */ | 40 | */ |
| 40 | #define _PAGE_GUARDED 0x0010 /* software: guarded access */ | 41 | #define _PAGE_GUARDED 0x0010 /* software: guarded access */ |
| 41 | #define _PAGE_DIRTY 0x0020 /* software: page changed */ | 42 | #define _PAGE_ACCESSED 0x0020 /* software: page referenced */ |
| 42 | #define _PAGE_RW 0x0040 /* software: user write access allowed */ | 43 | #define _PAGE_WRITETHRU 0x0040 /* software: caching is write through */ |
| 43 | #define _PAGE_ACCESSED 0x0080 /* software: page referenced */ | ||
| 44 | 44 | ||
| 45 | /* Setting any bits in the nibble with the follow two controls will | 45 | /* Setting any bits in the nibble with the follow two controls will |
| 46 | * require a TLB exception handler change. It is assumed unused bits | 46 | * require a TLB exception handler change. It is assumed unused bits |
| 47 | * are always zero. | 47 | * are always zero. |
| 48 | */ | 48 | */ |
| 49 | #define _PAGE_HWWRITE 0x0100 /* h/w write enable: never set in Linux PTE */ | 49 | #define _PAGE_RW 0x0400 /* lsb PP bits, inverted in HW */ |
| 50 | #define _PAGE_USER 0x0800 /* One of the PP bits, the other is USER&~RW */ | 50 | #define _PAGE_USER 0x0800 /* msb PP bits */ |
| 51 | 51 | ||
| 52 | #define _PMD_PRESENT 0x0001 | 52 | #define _PMD_PRESENT 0x0001 |
| 53 | #define _PMD_BAD 0x0ff0 | 53 | #define _PMD_BAD 0x0ff0 |
diff --git a/arch/powerpc/include/asm/pte-hash64-64k.h b/arch/powerpc/include/asm/pte-hash64-64k.h index 82b72207c51c..c4490f9c67c4 100644 --- a/arch/powerpc/include/asm/pte-hash64-64k.h +++ b/arch/powerpc/include/asm/pte-hash64-64k.h | |||
| @@ -76,41 +76,4 @@ | |||
| 76 | remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, \ | 76 | remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, \ |
| 77 | __pgprot(pgprot_val((prot)) | _PAGE_4K_PFN)) | 77 | __pgprot(pgprot_val((prot)) | _PAGE_4K_PFN)) |
| 78 | 78 | ||
| 79 | |||
| 80 | #ifdef CONFIG_PPC_SUBPAGE_PROT | ||
| 81 | /* | ||
| 82 | * For the sub-page protection option, we extend the PGD with one of | ||
| 83 | * these. Basically we have a 3-level tree, with the top level being | ||
| 84 | * the protptrs array. To optimize speed and memory consumption when | ||
| 85 | * only addresses < 4GB are being protected, pointers to the first | ||
| 86 | * four pages of sub-page protection words are stored in the low_prot | ||
| 87 | * array. | ||
| 88 | * Each page of sub-page protection words protects 1GB (4 bytes | ||
| 89 | * protects 64k). For the 3-level tree, each page of pointers then | ||
| 90 | * protects 8TB. | ||
| 91 | */ | ||
| 92 | struct subpage_prot_table { | ||
| 93 | unsigned long maxaddr; /* only addresses < this are protected */ | ||
| 94 | unsigned int **protptrs[2]; | ||
| 95 | unsigned int *low_prot[4]; | ||
| 96 | }; | ||
| 97 | |||
| 98 | #undef PGD_TABLE_SIZE | ||
| 99 | #define PGD_TABLE_SIZE ((sizeof(pgd_t) << PGD_INDEX_SIZE) + \ | ||
| 100 | sizeof(struct subpage_prot_table)) | ||
| 101 | |||
| 102 | #define SBP_L1_BITS (PAGE_SHIFT - 2) | ||
| 103 | #define SBP_L2_BITS (PAGE_SHIFT - 3) | ||
| 104 | #define SBP_L1_COUNT (1 << SBP_L1_BITS) | ||
| 105 | #define SBP_L2_COUNT (1 << SBP_L2_BITS) | ||
| 106 | #define SBP_L2_SHIFT (PAGE_SHIFT + SBP_L1_BITS) | ||
| 107 | #define SBP_L3_SHIFT (SBP_L2_SHIFT + SBP_L2_BITS) | ||
| 108 | |||
| 109 | extern void subpage_prot_free(pgd_t *pgd); | ||
| 110 | |||
| 111 | static inline struct subpage_prot_table *pgd_subpage_prot(pgd_t *pgd) | ||
| 112 | { | ||
| 113 | return (struct subpage_prot_table *)(pgd + PTRS_PER_PGD); | ||
| 114 | } | ||
| 115 | #endif /* CONFIG_PPC_SUBPAGE_PROT */ | ||
| 116 | #endif /* __ASSEMBLY__ */ | 79 | #endif /* __ASSEMBLY__ */ |
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h index 8c341490cfc5..cbd759e3cd78 100644 --- a/arch/powerpc/include/asm/ptrace.h +++ b/arch/powerpc/include/asm/ptrace.h | |||
| @@ -140,6 +140,8 @@ extern void user_enable_single_step(struct task_struct *); | |||
| 140 | extern void user_enable_block_step(struct task_struct *); | 140 | extern void user_enable_block_step(struct task_struct *); |
| 141 | extern void user_disable_single_step(struct task_struct *); | 141 | extern void user_disable_single_step(struct task_struct *); |
| 142 | 142 | ||
| 143 | #define ARCH_HAS_USER_SINGLE_STEP_INFO | ||
| 144 | |||
| 143 | #endif /* __ASSEMBLY__ */ | 145 | #endif /* __ASSEMBLY__ */ |
| 144 | 146 | ||
| 145 | #endif /* __KERNEL__ */ | 147 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/include/asm/qe.h b/arch/powerpc/include/asm/qe.h index f388f0ab193f..0947b36e534c 100644 --- a/arch/powerpc/include/asm/qe.h +++ b/arch/powerpc/include/asm/qe.h | |||
| @@ -87,7 +87,7 @@ extern spinlock_t cmxgcr_lock; | |||
| 87 | 87 | ||
| 88 | /* Export QE common operations */ | 88 | /* Export QE common operations */ |
| 89 | #ifdef CONFIG_QUICC_ENGINE | 89 | #ifdef CONFIG_QUICC_ENGINE |
| 90 | extern void __init qe_reset(void); | 90 | extern void qe_reset(void); |
| 91 | #else | 91 | #else |
| 92 | static inline void qe_reset(void) {} | 92 | static inline void qe_reset(void) {} |
| 93 | #endif | 93 | #endif |
| @@ -145,8 +145,17 @@ static inline void qe_pin_set_gpio(struct qe_pin *qe_pin) {} | |||
| 145 | static inline void qe_pin_set_dedicated(struct qe_pin *pin) {} | 145 | static inline void qe_pin_set_dedicated(struct qe_pin *pin) {} |
| 146 | #endif /* CONFIG_QE_GPIO */ | 146 | #endif /* CONFIG_QE_GPIO */ |
| 147 | 147 | ||
| 148 | /* QE internal API */ | 148 | #ifdef CONFIG_QUICC_ENGINE |
| 149 | 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); |
| 150 | #else | ||
| 151 | static inline int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, | ||
| 152 | u32 cmd_input) | ||
| 153 | { | ||
| 154 | return -ENOSYS; | ||
| 155 | } | ||
| 156 | #endif /* CONFIG_QUICC_ENGINE */ | ||
| 157 | |||
| 158 | /* QE internal API */ | ||
| 150 | enum qe_clock qe_clock_source(const char *source); | 159 | enum qe_clock qe_clock_source(const char *source); |
| 151 | unsigned int qe_get_brg_clk(void); | 160 | unsigned int qe_get_brg_clk(void); |
| 152 | int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier); | 161 | int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier); |
| @@ -154,7 +163,28 @@ int qe_get_snum(void); | |||
| 154 | void qe_put_snum(u8 snum); | 163 | void qe_put_snum(u8 snum); |
| 155 | unsigned int qe_get_num_of_risc(void); | 164 | unsigned int qe_get_num_of_risc(void); |
| 156 | unsigned int qe_get_num_of_snums(void); | 165 | unsigned int qe_get_num_of_snums(void); |
| 157 | int qe_alive_during_sleep(void); | 166 | |
| 167 | static inline int qe_alive_during_sleep(void) | ||
| 168 | { | ||
| 169 | /* | ||
| 170 | * MPC8568E reference manual says: | ||
| 171 | * | ||
| 172 | * "...power down sequence waits for all I/O interfaces to become idle. | ||
| 173 | * In some applications this may happen eventually without actively | ||
| 174 | * shutting down interfaces, but most likely, software will have to | ||
| 175 | * take steps to shut down the eTSEC, QUICC Engine Block, and PCI | ||
| 176 | * interfaces before issuing the command (either the write to the core | ||
| 177 | * MSR[WE] as described above or writing to POWMGTCSR) to put the | ||
| 178 | * device into sleep state." | ||
| 179 | * | ||
| 180 | * MPC8569E reference manual has a similar paragraph. | ||
| 181 | */ | ||
| 182 | #ifdef CONFIG_PPC_85xx | ||
| 183 | return 0; | ||
| 184 | #else | ||
| 185 | return 1; | ||
| 186 | #endif | ||
| 187 | } | ||
| 158 | 188 | ||
| 159 | /* we actually use cpm_muram implementation, define this for convenience */ | 189 | /* we actually use cpm_muram implementation, define this for convenience */ |
| 160 | #define qe_muram_init cpm_muram_init | 190 | #define qe_muram_init cpm_muram_init |
| @@ -210,8 +240,15 @@ struct qe_firmware_info { | |||
| 210 | u64 extended_modes; /* Extended modes */ | 240 | u64 extended_modes; /* Extended modes */ |
| 211 | }; | 241 | }; |
| 212 | 242 | ||
| 243 | #ifdef CONFIG_QUICC_ENGINE | ||
| 213 | /* Upload a firmware to the QE */ | 244 | /* Upload a firmware to the QE */ |
| 214 | int qe_upload_firmware(const struct qe_firmware *firmware); | 245 | int qe_upload_firmware(const struct qe_firmware *firmware); |
| 246 | #else | ||
| 247 | static inline int qe_upload_firmware(const struct qe_firmware *firmware) | ||
| 248 | { | ||
| 249 | return -ENOSYS; | ||
| 250 | } | ||
| 251 | #endif /* CONFIG_QUICC_ENGINE */ | ||
| 215 | 252 | ||
| 216 | /* Obtain information on the uploaded firmware */ | 253 | /* Obtain information on the uploaded firmware */ |
| 217 | struct qe_firmware_info *qe_get_firmware_info(void); | 254 | struct qe_firmware_info *qe_get_firmware_info(void); |
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index 168fce726201..20de73c36682 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h | |||
| @@ -58,7 +58,7 @@ struct rtas_t { | |||
| 58 | unsigned long entry; /* physical address pointer */ | 58 | unsigned long entry; /* physical address pointer */ |
| 59 | unsigned long base; /* physical address pointer */ | 59 | unsigned long base; /* physical address pointer */ |
| 60 | unsigned long size; | 60 | unsigned long size; |
| 61 | raw_spinlock_t lock; | 61 | arch_spinlock_t lock; |
| 62 | struct rtas_args args; | 62 | struct rtas_args args; |
| 63 | struct device_node *dev; /* virtual address pointer */ | 63 | struct device_node *dev; /* virtual address pointer */ |
| 64 | }; | 64 | }; |
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h index d9ea8d39c342..1d3b270d3083 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h | |||
| @@ -37,7 +37,7 @@ extern void cpu_die(void); | |||
| 37 | extern void smp_send_debugger_break(int cpu); | 37 | extern void smp_send_debugger_break(int cpu); |
| 38 | extern void smp_message_recv(int); | 38 | extern void smp_message_recv(int); |
| 39 | 39 | ||
| 40 | DECLARE_PER_CPU(unsigned int, pvr); | 40 | DECLARE_PER_CPU(unsigned int, cpu_pvr); |
| 41 | 41 | ||
| 42 | #ifdef CONFIG_HOTPLUG_CPU | 42 | #ifdef CONFIG_HOTPLUG_CPU |
| 43 | extern void fixup_irqs(cpumask_t map); | 43 | extern void fixup_irqs(cpumask_t map); |
diff --git a/arch/powerpc/include/asm/spinlock.h b/arch/powerpc/include/asm/spinlock.h index 198266cf9e2d..764094cff681 100644 --- a/arch/powerpc/include/asm/spinlock.h +++ b/arch/powerpc/include/asm/spinlock.h | |||
| @@ -28,7 +28,7 @@ | |||
| 28 | #include <asm/asm-compat.h> | 28 | #include <asm/asm-compat.h> |
| 29 | #include <asm/synch.h> | 29 | #include <asm/synch.h> |
| 30 | 30 | ||
| 31 | #define __raw_spin_is_locked(x) ((x)->slock != 0) | 31 | #define arch_spin_is_locked(x) ((x)->slock != 0) |
| 32 | 32 | ||
| 33 | #ifdef CONFIG_PPC64 | 33 | #ifdef CONFIG_PPC64 |
| 34 | /* use 0x800000yy when locked, where yy == CPU number */ | 34 | /* use 0x800000yy when locked, where yy == CPU number */ |
| @@ -54,7 +54,7 @@ | |||
| 54 | * This returns the old value in the lock, so we succeeded | 54 | * This returns the old value in the lock, so we succeeded |
| 55 | * in getting the lock if the return value is 0. | 55 | * in getting the lock if the return value is 0. |
| 56 | */ | 56 | */ |
| 57 | static inline unsigned long arch_spin_trylock(raw_spinlock_t *lock) | 57 | static inline unsigned long __arch_spin_trylock(arch_spinlock_t *lock) |
| 58 | { | 58 | { |
| 59 | unsigned long tmp, token; | 59 | unsigned long tmp, token; |
| 60 | 60 | ||
| @@ -73,10 +73,10 @@ static inline unsigned long arch_spin_trylock(raw_spinlock_t *lock) | |||
| 73 | return tmp; | 73 | return tmp; |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | static inline int __raw_spin_trylock(raw_spinlock_t *lock) | 76 | static inline int arch_spin_trylock(arch_spinlock_t *lock) |
| 77 | { | 77 | { |
| 78 | CLEAR_IO_SYNC; | 78 | CLEAR_IO_SYNC; |
| 79 | return arch_spin_trylock(lock) == 0; | 79 | return __arch_spin_trylock(lock) == 0; |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | /* | 82 | /* |
| @@ -96,19 +96,19 @@ static inline int __raw_spin_trylock(raw_spinlock_t *lock) | |||
| 96 | #if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES) | 96 | #if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES) |
| 97 | /* We only yield to the hypervisor if we are in shared processor mode */ | 97 | /* We only yield to the hypervisor if we are in shared processor mode */ |
| 98 | #define SHARED_PROCESSOR (get_lppaca()->shared_proc) | 98 | #define SHARED_PROCESSOR (get_lppaca()->shared_proc) |
| 99 | extern void __spin_yield(raw_spinlock_t *lock); | 99 | extern void __spin_yield(arch_spinlock_t *lock); |
| 100 | extern void __rw_yield(raw_rwlock_t *lock); | 100 | extern void __rw_yield(arch_rwlock_t *lock); |
| 101 | #else /* SPLPAR || ISERIES */ | 101 | #else /* SPLPAR || ISERIES */ |
| 102 | #define __spin_yield(x) barrier() | 102 | #define __spin_yield(x) barrier() |
| 103 | #define __rw_yield(x) barrier() | 103 | #define __rw_yield(x) barrier() |
| 104 | #define SHARED_PROCESSOR 0 | 104 | #define SHARED_PROCESSOR 0 |
| 105 | #endif | 105 | #endif |
| 106 | 106 | ||
| 107 | static inline void __raw_spin_lock(raw_spinlock_t *lock) | 107 | static inline void arch_spin_lock(arch_spinlock_t *lock) |
| 108 | { | 108 | { |
| 109 | CLEAR_IO_SYNC; | 109 | CLEAR_IO_SYNC; |
| 110 | while (1) { | 110 | while (1) { |
| 111 | if (likely(arch_spin_trylock(lock) == 0)) | 111 | if (likely(__arch_spin_trylock(lock) == 0)) |
| 112 | break; | 112 | break; |
| 113 | do { | 113 | do { |
| 114 | HMT_low(); | 114 | HMT_low(); |
| @@ -120,13 +120,13 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock) | |||
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | static inline | 122 | static inline |
| 123 | void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags) | 123 | void arch_spin_lock_flags(arch_spinlock_t *lock, unsigned long flags) |
| 124 | { | 124 | { |
| 125 | unsigned long flags_dis; | 125 | unsigned long flags_dis; |
| 126 | 126 | ||
| 127 | CLEAR_IO_SYNC; | 127 | CLEAR_IO_SYNC; |
| 128 | while (1) { | 128 | while (1) { |
| 129 | if (likely(arch_spin_trylock(lock) == 0)) | 129 | if (likely(__arch_spin_trylock(lock) == 0)) |
| 130 | break; | 130 | break; |
| 131 | local_save_flags(flags_dis); | 131 | local_save_flags(flags_dis); |
| 132 | local_irq_restore(flags); | 132 | local_irq_restore(flags); |
| @@ -140,19 +140,19 @@ void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags) | |||
| 140 | } | 140 | } |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | static inline void __raw_spin_unlock(raw_spinlock_t *lock) | 143 | static inline void arch_spin_unlock(arch_spinlock_t *lock) |
| 144 | { | 144 | { |
| 145 | SYNC_IO; | 145 | SYNC_IO; |
| 146 | __asm__ __volatile__("# __raw_spin_unlock\n\t" | 146 | __asm__ __volatile__("# arch_spin_unlock\n\t" |
| 147 | LWSYNC_ON_SMP: : :"memory"); | 147 | LWSYNC_ON_SMP: : :"memory"); |
| 148 | lock->slock = 0; | 148 | lock->slock = 0; |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | #ifdef CONFIG_PPC64 | 151 | #ifdef CONFIG_PPC64 |
| 152 | extern void __raw_spin_unlock_wait(raw_spinlock_t *lock); | 152 | extern void arch_spin_unlock_wait(arch_spinlock_t *lock); |
| 153 | #else | 153 | #else |
| 154 | #define __raw_spin_unlock_wait(lock) \ | 154 | #define arch_spin_unlock_wait(lock) \ |
| 155 | do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0) | 155 | do { while (arch_spin_is_locked(lock)) cpu_relax(); } while (0) |
| 156 | #endif | 156 | #endif |
| 157 | 157 | ||
| 158 | /* | 158 | /* |
| @@ -166,8 +166,8 @@ extern void __raw_spin_unlock_wait(raw_spinlock_t *lock); | |||
| 166 | * read-locks. | 166 | * read-locks. |
| 167 | */ | 167 | */ |
| 168 | 168 | ||
| 169 | #define __raw_read_can_lock(rw) ((rw)->lock >= 0) | 169 | #define arch_read_can_lock(rw) ((rw)->lock >= 0) |
| 170 | #define __raw_write_can_lock(rw) (!(rw)->lock) | 170 | #define arch_write_can_lock(rw) (!(rw)->lock) |
| 171 | 171 | ||
| 172 | #ifdef CONFIG_PPC64 | 172 | #ifdef CONFIG_PPC64 |
| 173 | #define __DO_SIGN_EXTEND "extsw %0,%0\n" | 173 | #define __DO_SIGN_EXTEND "extsw %0,%0\n" |
| @@ -181,7 +181,7 @@ extern void __raw_spin_unlock_wait(raw_spinlock_t *lock); | |||
| 181 | * This returns the old value in the lock + 1, | 181 | * This returns the old value in the lock + 1, |
| 182 | * so we got a read lock if the return value is > 0. | 182 | * so we got a read lock if the return value is > 0. |
| 183 | */ | 183 | */ |
| 184 | static inline long arch_read_trylock(raw_rwlock_t *rw) | 184 | static inline long __arch_read_trylock(arch_rwlock_t *rw) |
| 185 | { | 185 | { |
| 186 | long tmp; | 186 | long tmp; |
| 187 | 187 | ||
| @@ -205,7 +205,7 @@ static inline long arch_read_trylock(raw_rwlock_t *rw) | |||
| 205 | * This returns the old value in the lock, | 205 | * This returns the old value in the lock, |
| 206 | * so we got the write lock if the return value is 0. | 206 | * so we got the write lock if the return value is 0. |
| 207 | */ | 207 | */ |
| 208 | static inline long arch_write_trylock(raw_rwlock_t *rw) | 208 | static inline long __arch_write_trylock(arch_rwlock_t *rw) |
| 209 | { | 209 | { |
| 210 | long tmp, token; | 210 | long tmp, token; |
| 211 | 211 | ||
| @@ -225,10 +225,10 @@ static inline long arch_write_trylock(raw_rwlock_t *rw) | |||
| 225 | return tmp; | 225 | return tmp; |
| 226 | } | 226 | } |
| 227 | 227 | ||
| 228 | static inline void __raw_read_lock(raw_rwlock_t *rw) | 228 | static inline void arch_read_lock(arch_rwlock_t *rw) |
| 229 | { | 229 | { |
| 230 | while (1) { | 230 | while (1) { |
| 231 | if (likely(arch_read_trylock(rw) > 0)) | 231 | if (likely(__arch_read_trylock(rw) > 0)) |
| 232 | break; | 232 | break; |
| 233 | do { | 233 | do { |
| 234 | HMT_low(); | 234 | HMT_low(); |
| @@ -239,10 +239,10 @@ static inline void __raw_read_lock(raw_rwlock_t *rw) | |||
| 239 | } | 239 | } |
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | static inline void __raw_write_lock(raw_rwlock_t *rw) | 242 | static inline void arch_write_lock(arch_rwlock_t *rw) |
| 243 | { | 243 | { |
| 244 | while (1) { | 244 | while (1) { |
| 245 | if (likely(arch_write_trylock(rw) == 0)) | 245 | if (likely(__arch_write_trylock(rw) == 0)) |
| 246 | break; | 246 | break; |
| 247 | do { | 247 | do { |
| 248 | HMT_low(); | 248 | HMT_low(); |
| @@ -253,17 +253,17 @@ static inline void __raw_write_lock(raw_rwlock_t *rw) | |||
| 253 | } | 253 | } |
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | static inline int __raw_read_trylock(raw_rwlock_t *rw) | 256 | static inline int arch_read_trylock(arch_rwlock_t *rw) |
| 257 | { | 257 | { |
| 258 | return arch_read_trylock(rw) > 0; | 258 | return __arch_read_trylock(rw) > 0; |
| 259 | } | 259 | } |
| 260 | 260 | ||
| 261 | static inline int __raw_write_trylock(raw_rwlock_t *rw) | 261 | static inline int arch_write_trylock(arch_rwlock_t *rw) |
| 262 | { | 262 | { |
| 263 | return arch_write_trylock(rw) == 0; | 263 | return __arch_write_trylock(rw) == 0; |
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | static inline void __raw_read_unlock(raw_rwlock_t *rw) | 266 | static inline void arch_read_unlock(arch_rwlock_t *rw) |
| 267 | { | 267 | { |
| 268 | long tmp; | 268 | long tmp; |
| 269 | 269 | ||
| @@ -280,19 +280,19 @@ static inline void __raw_read_unlock(raw_rwlock_t *rw) | |||
| 280 | : "cr0", "xer", "memory"); | 280 | : "cr0", "xer", "memory"); |
| 281 | } | 281 | } |
| 282 | 282 | ||
| 283 | static inline void __raw_write_unlock(raw_rwlock_t *rw) | 283 | static inline void arch_write_unlock(arch_rwlock_t *rw) |
| 284 | { | 284 | { |
| 285 | __asm__ __volatile__("# write_unlock\n\t" | 285 | __asm__ __volatile__("# write_unlock\n\t" |
| 286 | LWSYNC_ON_SMP: : :"memory"); | 286 | LWSYNC_ON_SMP: : :"memory"); |
| 287 | rw->lock = 0; | 287 | rw->lock = 0; |
| 288 | } | 288 | } |
| 289 | 289 | ||
| 290 | #define __raw_read_lock_flags(lock, flags) __raw_read_lock(lock) | 290 | #define arch_read_lock_flags(lock, flags) arch_read_lock(lock) |
| 291 | #define __raw_write_lock_flags(lock, flags) __raw_write_lock(lock) | 291 | #define arch_write_lock_flags(lock, flags) arch_write_lock(lock) |
| 292 | 292 | ||
| 293 | #define _raw_spin_relax(lock) __spin_yield(lock) | 293 | #define arch_spin_relax(lock) __spin_yield(lock) |
| 294 | #define _raw_read_relax(lock) __rw_yield(lock) | 294 | #define arch_read_relax(lock) __rw_yield(lock) |
| 295 | #define _raw_write_relax(lock) __rw_yield(lock) | 295 | #define arch_write_relax(lock) __rw_yield(lock) |
| 296 | 296 | ||
| 297 | #endif /* __KERNEL__ */ | 297 | #endif /* __KERNEL__ */ |
| 298 | #endif /* __ASM_SPINLOCK_H */ | 298 | #endif /* __ASM_SPINLOCK_H */ |
diff --git a/arch/powerpc/include/asm/spinlock_types.h b/arch/powerpc/include/asm/spinlock_types.h index 74236c9f05b1..2351adc4fdc4 100644 --- a/arch/powerpc/include/asm/spinlock_types.h +++ b/arch/powerpc/include/asm/spinlock_types.h | |||
| @@ -7,14 +7,14 @@ | |||
| 7 | 7 | ||
| 8 | typedef struct { | 8 | typedef struct { |
| 9 | volatile unsigned int slock; | 9 | volatile unsigned int slock; |
| 10 | } raw_spinlock_t; | 10 | } arch_spinlock_t; |
| 11 | 11 | ||
| 12 | #define __RAW_SPIN_LOCK_UNLOCKED { 0 } | 12 | #define __ARCH_SPIN_LOCK_UNLOCKED { 0 } |
| 13 | 13 | ||
| 14 | typedef struct { | 14 | typedef struct { |
| 15 | volatile signed int lock; | 15 | volatile signed int lock; |
| 16 | } raw_rwlock_t; | 16 | } arch_rwlock_t; |
| 17 | 17 | ||
| 18 | #define __RAW_RW_LOCK_UNLOCKED { 0 } | 18 | #define __ARCH_RW_LOCK_UNLOCKED { 0 } |
| 19 | 19 | ||
| 20 | #endif | 20 | #endif |
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h index c7d671a7d9a1..07d2d19ab5e9 100644 --- a/arch/powerpc/include/asm/systbl.h +++ b/arch/powerpc/include/asm/systbl.h | |||
| @@ -145,7 +145,7 @@ SYSCALL_SPU(setfsuid) | |||
| 145 | SYSCALL_SPU(setfsgid) | 145 | SYSCALL_SPU(setfsgid) |
| 146 | SYSCALL_SPU(llseek) | 146 | SYSCALL_SPU(llseek) |
| 147 | COMPAT_SYS_SPU(getdents) | 147 | COMPAT_SYS_SPU(getdents) |
| 148 | SYSX_SPU(sys_select,ppc32_select,ppc_select) | 148 | SYSX_SPU(sys_select,ppc32_select,sys_select) |
| 149 | SYSCALL_SPU(flock) | 149 | SYSCALL_SPU(flock) |
| 150 | SYSCALL_SPU(msync) | 150 | SYSCALL_SPU(msync) |
| 151 | COMPAT_SYS_SPU(readv) | 151 | COMPAT_SYS_SPU(readv) |
diff --git a/arch/powerpc/include/asm/udbg.h b/arch/powerpc/include/asm/udbg.h index cd21e5e6b04f..11ae699135ba 100644 --- a/arch/powerpc/include/asm/udbg.h +++ b/arch/powerpc/include/asm/udbg.h | |||
| @@ -51,6 +51,7 @@ extern void __init udbg_init_btext(void); | |||
| 51 | extern void __init udbg_init_44x_as1(void); | 51 | extern void __init udbg_init_44x_as1(void); |
| 52 | extern void __init udbg_init_40x_realmode(void); | 52 | extern void __init udbg_init_40x_realmode(void); |
| 53 | extern void __init udbg_init_cpm(void); | 53 | extern void __init udbg_init_cpm(void); |
| 54 | extern void __init udbg_init_usbgecko(void); | ||
| 54 | 55 | ||
| 55 | #endif /* __KERNEL__ */ | 56 | #endif /* __KERNEL__ */ |
| 56 | #endif /* _ASM_POWERPC_UDBG_H */ | 57 | #endif /* _ASM_POWERPC_UDBG_H */ |
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index b23664a0b86c..c002b0410219 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
| @@ -42,10 +42,11 @@ obj-$(CONFIG_ALTIVEC) += vecemu.o | |||
| 42 | obj-$(CONFIG_PPC_970_NAP) += idle_power4.o | 42 | obj-$(CONFIG_PPC_970_NAP) += idle_power4.o |
| 43 | obj-$(CONFIG_PPC_OF) += of_device.o of_platform.o prom_parse.o | 43 | obj-$(CONFIG_PPC_OF) += of_device.o of_platform.o prom_parse.o |
| 44 | obj-$(CONFIG_PPC_CLOCK) += clock.o | 44 | obj-$(CONFIG_PPC_CLOCK) += clock.o |
| 45 | procfs-$(CONFIG_PPC64) := proc_ppc64.o | 45 | procfs-y := proc_powerpc.o |
| 46 | obj-$(CONFIG_PROC_FS) += $(procfs-y) | 46 | obj-$(CONFIG_PROC_FS) += $(procfs-y) |
| 47 | rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o | 47 | rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o |
| 48 | obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y-y) | 48 | obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y-y) |
| 49 | obj-$(CONFIG_PPC_RTAS_DAEMON) += rtasd.o | ||
| 49 | obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o | 50 | obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o |
| 50 | obj-$(CONFIG_RTAS_PROC) += rtas-proc.o | 51 | obj-$(CONFIG_RTAS_PROC) += rtas-proc.o |
| 51 | obj-$(CONFIG_LPARCFG) += lparcfg.o | 52 | obj-$(CONFIG_LPARCFG) += lparcfg.o |
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index 3839839f83c7..b876e989220b 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c | |||
| @@ -642,10 +642,14 @@ static int emulate_spe(struct pt_regs *regs, unsigned int reg, | |||
| 642 | */ | 642 | */ |
| 643 | static int emulate_vsx(unsigned char __user *addr, unsigned int reg, | 643 | static int emulate_vsx(unsigned char __user *addr, unsigned int reg, |
| 644 | unsigned int areg, struct pt_regs *regs, | 644 | unsigned int areg, struct pt_regs *regs, |
| 645 | unsigned int flags, unsigned int length) | 645 | unsigned int flags, unsigned int length, |
| 646 | unsigned int elsize) | ||
| 646 | { | 647 | { |
| 647 | char *ptr; | 648 | char *ptr; |
| 649 | unsigned long *lptr; | ||
| 648 | int ret = 0; | 650 | int ret = 0; |
| 651 | int sw = 0; | ||
| 652 | int i, j; | ||
| 649 | 653 | ||
| 650 | flush_vsx_to_thread(current); | 654 | flush_vsx_to_thread(current); |
| 651 | 655 | ||
| @@ -654,19 +658,35 @@ static int emulate_vsx(unsigned char __user *addr, unsigned int reg, | |||
| 654 | else | 658 | else |
| 655 | ptr = (char *) ¤t->thread.vr[reg - 32]; | 659 | ptr = (char *) ¤t->thread.vr[reg - 32]; |
| 656 | 660 | ||
| 657 | if (flags & ST) | 661 | lptr = (unsigned long *) ptr; |
| 658 | ret = __copy_to_user(addr, ptr, length); | 662 | |
| 659 | else { | 663 | if (flags & SW) |
| 660 | if (flags & SPLT){ | 664 | sw = elsize-1; |
| 661 | ret = __copy_from_user(ptr, addr, length); | 665 | |
| 662 | ptr += length; | 666 | for (j = 0; j < length; j += elsize) { |
| 667 | for (i = 0; i < elsize; ++i) { | ||
| 668 | if (flags & ST) | ||
| 669 | ret |= __put_user(ptr[i^sw], addr + i); | ||
| 670 | else | ||
| 671 | ret |= __get_user(ptr[i^sw], addr + i); | ||
| 663 | } | 672 | } |
| 664 | ret |= __copy_from_user(ptr, addr, length); | 673 | ptr += elsize; |
| 674 | addr += elsize; | ||
| 665 | } | 675 | } |
| 666 | if (flags & U) | 676 | |
| 667 | regs->gpr[areg] = regs->dar; | 677 | if (!ret) { |
| 668 | if (ret) | 678 | if (flags & U) |
| 679 | regs->gpr[areg] = regs->dar; | ||
| 680 | |||
| 681 | /* Splat load copies the same data to top and bottom 8 bytes */ | ||
| 682 | if (flags & SPLT) | ||
| 683 | lptr[1] = lptr[0]; | ||
| 684 | /* For 8 byte loads, zero the top 8 bytes */ | ||
| 685 | else if (!(flags & ST) && (8 == length)) | ||
| 686 | lptr[1] = 0; | ||
| 687 | } else | ||
| 669 | return -EFAULT; | 688 | return -EFAULT; |
| 689 | |||
| 670 | return 1; | 690 | return 1; |
| 671 | } | 691 | } |
| 672 | #endif | 692 | #endif |
| @@ -767,16 +787,25 @@ int fix_alignment(struct pt_regs *regs) | |||
| 767 | 787 | ||
| 768 | #ifdef CONFIG_VSX | 788 | #ifdef CONFIG_VSX |
| 769 | if ((instruction & 0xfc00003e) == 0x7c000018) { | 789 | if ((instruction & 0xfc00003e) == 0x7c000018) { |
| 770 | /* Additional register addressing bit (64 VSX vs 32 FPR/GPR */ | 790 | unsigned int elsize; |
| 791 | |||
| 792 | /* Additional register addressing bit (64 VSX vs 32 FPR/GPR) */ | ||
| 771 | reg |= (instruction & 0x1) << 5; | 793 | reg |= (instruction & 0x1) << 5; |
| 772 | /* Simple inline decoder instead of a table */ | 794 | /* Simple inline decoder instead of a table */ |
| 795 | /* VSX has only 8 and 16 byte memory accesses */ | ||
| 796 | nb = 8; | ||
| 773 | if (instruction & 0x200) | 797 | if (instruction & 0x200) |
| 774 | nb = 16; | 798 | nb = 16; |
| 775 | else if (instruction & 0x080) | 799 | |
| 776 | nb = 8; | 800 | /* Vector stores in little-endian mode swap individual |
| 777 | else | 801 | elements, so process them separately */ |
| 778 | nb = 4; | 802 | elsize = 4; |
| 803 | if (instruction & 0x80) | ||
| 804 | elsize = 8; | ||
| 805 | |||
| 779 | flags = 0; | 806 | flags = 0; |
| 807 | if (regs->msr & MSR_LE) | ||
| 808 | flags |= SW; | ||
| 780 | if (instruction & 0x100) | 809 | if (instruction & 0x100) |
| 781 | flags |= ST; | 810 | flags |= ST; |
| 782 | if (instruction & 0x040) | 811 | if (instruction & 0x040) |
| @@ -787,7 +816,7 @@ int fix_alignment(struct pt_regs *regs) | |||
| 787 | nb = 8; | 816 | nb = 8; |
| 788 | } | 817 | } |
| 789 | PPC_WARN_ALIGNMENT(vsx, regs); | 818 | PPC_WARN_ALIGNMENT(vsx, regs); |
| 790 | return emulate_vsx(addr, reg, areg, regs, flags, nb); | 819 | return emulate_vsx(addr, reg, areg, regs, flags, nb, elsize); |
| 791 | } | 820 | } |
| 792 | #endif | 821 | #endif |
| 793 | /* A size of 0 indicates an instruction we don't support, with | 822 | /* A size of 0 indicates an instruction we don't support, with |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 0812b0f414bb..a6c2b63227b3 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
| @@ -190,6 +190,11 @@ int main(void) | |||
| 190 | DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); | 190 | DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); |
| 191 | DEFINE(PACA_DATA_OFFSET, offsetof(struct paca_struct, data_offset)); | 191 | DEFINE(PACA_DATA_OFFSET, offsetof(struct paca_struct, data_offset)); |
| 192 | DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save)); | 192 | DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save)); |
| 193 | #ifdef CONFIG_KVM_BOOK3S_64_HANDLER | ||
| 194 | DEFINE(PACA_KVM_IN_GUEST, offsetof(struct paca_struct, kvm_in_guest)); | ||
| 195 | DEFINE(PACA_KVM_SLB, offsetof(struct paca_struct, kvm_slb)); | ||
| 196 | DEFINE(PACA_KVM_SLB_MAX, offsetof(struct paca_struct, kvm_slb_max)); | ||
| 197 | #endif | ||
| 193 | #endif /* CONFIG_PPC64 */ | 198 | #endif /* CONFIG_PPC64 */ |
| 194 | 199 | ||
| 195 | /* RTAS */ | 200 | /* RTAS */ |
| @@ -398,14 +403,24 @@ int main(void) | |||
| 398 | DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst)); | 403 | DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst)); |
| 399 | DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear)); | 404 | DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear)); |
| 400 | DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr)); | 405 | DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr)); |
| 406 | |||
| 407 | /* book3s_64 */ | ||
| 408 | #ifdef CONFIG_PPC64 | ||
| 409 | DEFINE(VCPU_FAULT_DSISR, offsetof(struct kvm_vcpu, arch.fault_dsisr)); | ||
| 410 | DEFINE(VCPU_HOST_RETIP, offsetof(struct kvm_vcpu, arch.host_retip)); | ||
| 411 | DEFINE(VCPU_HOST_R2, offsetof(struct kvm_vcpu, arch.host_r2)); | ||
| 412 | DEFINE(VCPU_HOST_MSR, offsetof(struct kvm_vcpu, arch.host_msr)); | ||
| 413 | DEFINE(VCPU_SHADOW_MSR, offsetof(struct kvm_vcpu, arch.shadow_msr)); | ||
| 414 | DEFINE(VCPU_TRAMPOLINE_LOWMEM, offsetof(struct kvm_vcpu, arch.trampoline_lowmem)); | ||
| 415 | DEFINE(VCPU_TRAMPOLINE_ENTER, offsetof(struct kvm_vcpu, arch.trampoline_enter)); | ||
| 416 | DEFINE(VCPU_HIGHMEM_HANDLER, offsetof(struct kvm_vcpu, arch.highmem_handler)); | ||
| 417 | DEFINE(VCPU_HFLAGS, offsetof(struct kvm_vcpu, arch.hflags)); | ||
| 418 | #endif | ||
| 401 | #endif | 419 | #endif |
| 402 | #ifdef CONFIG_44x | 420 | #ifdef CONFIG_44x |
| 403 | DEFINE(PGD_T_LOG2, PGD_T_LOG2); | 421 | DEFINE(PGD_T_LOG2, PGD_T_LOG2); |
| 404 | DEFINE(PTE_T_LOG2, PTE_T_LOG2); | 422 | DEFINE(PTE_T_LOG2, PTE_T_LOG2); |
| 405 | #endif | 423 | #endif |
| 406 | #ifdef CONFIG_FSL_BOOKE | ||
| 407 | DEFINE(TLBCAM_SIZE, sizeof(struct tlbcam)); | ||
| 408 | #endif | ||
| 409 | 424 | ||
| 410 | #ifdef CONFIG_KVM_EXIT_TIMING | 425 | #ifdef CONFIG_KVM_EXIT_TIMING |
| 411 | DEFINE(VCPU_TIMING_EXIT_TBU, offsetof(struct kvm_vcpu, | 426 | DEFINE(VCPU_TIMING_EXIT_TBU, offsetof(struct kvm_vcpu, |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 03c862b6a9c4..2fc82bac3bbc 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
| @@ -697,9 +697,9 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
| 697 | .machine_check = machine_check_generic, | 697 | .machine_check = machine_check_generic, |
| 698 | .platform = "ppc750", | 698 | .platform = "ppc750", |
| 699 | }, | 699 | }, |
| 700 | { /* 750CL */ | 700 | { /* 750CL (and "Broadway") */ |
| 701 | .pvr_mask = 0xfffff0f0, | 701 | .pvr_mask = 0xfffff0e0, |
| 702 | .pvr_value = 0x00087010, | 702 | .pvr_value = 0x00087000, |
| 703 | .cpu_name = "750CL", | 703 | .cpu_name = "750CL", |
| 704 | .cpu_features = CPU_FTRS_750CL, | 704 | .cpu_features = CPU_FTRS_750CL, |
| 705 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, | 705 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 0a8439aafdd1..6f4613dd05ef 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c | |||
| @@ -373,7 +373,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs) | |||
| 373 | hard_irq_disable(); | 373 | hard_irq_disable(); |
| 374 | 374 | ||
| 375 | for_each_irq(i) { | 375 | for_each_irq(i) { |
| 376 | struct irq_desc *desc = irq_desc + i; | 376 | struct irq_desc *desc = irq_to_desc(i); |
| 377 | 377 | ||
| 378 | if (desc->status & IRQ_INPROGRESS) | 378 | if (desc->status & IRQ_INPROGRESS) |
| 379 | desc->chip->eoi(i); | 379 | desc->chip->eoi(i); |
diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c index e96cbbd9b449..59c928564a03 100644 --- a/arch/powerpc/kernel/dma-swiotlb.c +++ b/arch/powerpc/kernel/dma-swiotlb.c | |||
| @@ -21,7 +21,6 @@ | |||
| 21 | #include <asm/dma.h> | 21 | #include <asm/dma.h> |
| 22 | #include <asm/abs_addr.h> | 22 | #include <asm/abs_addr.h> |
| 23 | 23 | ||
| 24 | int swiotlb __read_mostly; | ||
| 25 | unsigned int ppc_swiotlb_enable; | 24 | unsigned int ppc_swiotlb_enable; |
| 26 | 25 | ||
| 27 | /* | 26 | /* |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index c7eb4e0eb86c..e3be98ffe2a7 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
| @@ -41,6 +41,7 @@ __start_interrupts: | |||
| 41 | . = 0x200 | 41 | . = 0x200 |
| 42 | _machine_check_pSeries: | 42 | _machine_check_pSeries: |
| 43 | HMT_MEDIUM | 43 | HMT_MEDIUM |
| 44 | DO_KVM 0x200 | ||
| 44 | mtspr SPRN_SPRG_SCRATCH0,r13 /* save r13 */ | 45 | mtspr SPRN_SPRG_SCRATCH0,r13 /* save r13 */ |
| 45 | EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) | 46 | EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) |
| 46 | 47 | ||
| @@ -48,6 +49,7 @@ _machine_check_pSeries: | |||
| 48 | .globl data_access_pSeries | 49 | .globl data_access_pSeries |
| 49 | data_access_pSeries: | 50 | data_access_pSeries: |
| 50 | HMT_MEDIUM | 51 | HMT_MEDIUM |
| 52 | DO_KVM 0x300 | ||
| 51 | mtspr SPRN_SPRG_SCRATCH0,r13 | 53 | mtspr SPRN_SPRG_SCRATCH0,r13 |
| 52 | BEGIN_FTR_SECTION | 54 | BEGIN_FTR_SECTION |
| 53 | mfspr r13,SPRN_SPRG_PACA | 55 | mfspr r13,SPRN_SPRG_PACA |
| @@ -77,6 +79,7 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_SLB) | |||
| 77 | .globl data_access_slb_pSeries | 79 | .globl data_access_slb_pSeries |
| 78 | data_access_slb_pSeries: | 80 | data_access_slb_pSeries: |
| 79 | HMT_MEDIUM | 81 | HMT_MEDIUM |
| 82 | DO_KVM 0x380 | ||
| 80 | mtspr SPRN_SPRG_SCRATCH0,r13 | 83 | mtspr SPRN_SPRG_SCRATCH0,r13 |
| 81 | mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */ | 84 | mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */ |
| 82 | std r3,PACA_EXSLB+EX_R3(r13) | 85 | std r3,PACA_EXSLB+EX_R3(r13) |
| @@ -115,6 +118,7 @@ data_access_slb_pSeries: | |||
| 115 | .globl instruction_access_slb_pSeries | 118 | .globl instruction_access_slb_pSeries |
| 116 | instruction_access_slb_pSeries: | 119 | instruction_access_slb_pSeries: |
| 117 | HMT_MEDIUM | 120 | HMT_MEDIUM |
| 121 | DO_KVM 0x480 | ||
| 118 | mtspr SPRN_SPRG_SCRATCH0,r13 | 122 | mtspr SPRN_SPRG_SCRATCH0,r13 |
| 119 | mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */ | 123 | mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */ |
| 120 | std r3,PACA_EXSLB+EX_R3(r13) | 124 | std r3,PACA_EXSLB+EX_R3(r13) |
| @@ -154,6 +158,7 @@ instruction_access_slb_pSeries: | |||
| 154 | .globl system_call_pSeries | 158 | .globl system_call_pSeries |
| 155 | system_call_pSeries: | 159 | system_call_pSeries: |
| 156 | HMT_MEDIUM | 160 | HMT_MEDIUM |
| 161 | DO_KVM 0xc00 | ||
| 157 | BEGIN_FTR_SECTION | 162 | BEGIN_FTR_SECTION |
| 158 | cmpdi r0,0x1ebe | 163 | cmpdi r0,0x1ebe |
| 159 | beq- 1f | 164 | beq- 1f |
| @@ -187,14 +192,17 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) | |||
| 187 | */ | 192 | */ |
| 188 | performance_monitor_pSeries_1: | 193 | performance_monitor_pSeries_1: |
| 189 | . = 0xf00 | 194 | . = 0xf00 |
| 195 | DO_KVM 0xf00 | ||
| 190 | b performance_monitor_pSeries | 196 | b performance_monitor_pSeries |
| 191 | 197 | ||
| 192 | altivec_unavailable_pSeries_1: | 198 | altivec_unavailable_pSeries_1: |
| 193 | . = 0xf20 | 199 | . = 0xf20 |
| 200 | DO_KVM 0xf20 | ||
| 194 | b altivec_unavailable_pSeries | 201 | b altivec_unavailable_pSeries |
| 195 | 202 | ||
| 196 | vsx_unavailable_pSeries_1: | 203 | vsx_unavailable_pSeries_1: |
| 197 | . = 0xf40 | 204 | . = 0xf40 |
| 205 | DO_KVM 0xf40 | ||
| 198 | b vsx_unavailable_pSeries | 206 | b vsx_unavailable_pSeries |
| 199 | 207 | ||
| 200 | #ifdef CONFIG_CBE_RAS | 208 | #ifdef CONFIG_CBE_RAS |
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S index 829c3fe7c5a2..e025e89fe93e 100644 --- a/arch/powerpc/kernel/head_32.S +++ b/arch/powerpc/kernel/head_32.S | |||
| @@ -164,6 +164,9 @@ __after_mmu_off: | |||
| 164 | #ifdef CONFIG_PPC_EARLY_DEBUG_CPM | 164 | #ifdef CONFIG_PPC_EARLY_DEBUG_CPM |
| 165 | bl setup_cpm_bat | 165 | bl setup_cpm_bat |
| 166 | #endif | 166 | #endif |
| 167 | #ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO | ||
| 168 | bl setup_usbgecko_bat | ||
| 169 | #endif | ||
| 167 | 170 | ||
| 168 | /* | 171 | /* |
| 169 | * Call setup_cpu for CPU 0 and initialize 6xx Idle | 172 | * Call setup_cpu for CPU 0 and initialize 6xx Idle |
| @@ -1203,6 +1206,28 @@ setup_cpm_bat: | |||
| 1203 | blr | 1206 | blr |
| 1204 | #endif | 1207 | #endif |
| 1205 | 1208 | ||
| 1209 | #ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO | ||
| 1210 | setup_usbgecko_bat: | ||
| 1211 | /* prepare a BAT for early io */ | ||
| 1212 | #if defined(CONFIG_GAMECUBE) | ||
| 1213 | lis r8, 0x0c00 | ||
| 1214 | #elif defined(CONFIG_WII) | ||
| 1215 | lis r8, 0x0d00 | ||
| 1216 | #else | ||
| 1217 | #error Invalid platform for USB Gecko based early debugging. | ||
| 1218 | #endif | ||
| 1219 | /* | ||
| 1220 | * The virtual address used must match the virtual address | ||
| 1221 | * associated to the fixmap entry FIX_EARLY_DEBUG_BASE. | ||
| 1222 | */ | ||
| 1223 | lis r11, 0xfffe /* top 128K */ | ||
| 1224 | ori r8, r8, 0x002a /* uncached, guarded ,rw */ | ||
| 1225 | ori r11, r11, 0x2 /* 128K, Vs=1, Vp=0 */ | ||
| 1226 | mtspr SPRN_DBAT1L, r8 | ||
| 1227 | mtspr SPRN_DBAT1U, r11 | ||
| 1228 | blr | ||
| 1229 | #endif | ||
| 1230 | |||
| 1206 | #ifdef CONFIG_8260 | 1231 | #ifdef CONFIG_8260 |
| 1207 | /* Jump into the system reset for the rom. | 1232 | /* Jump into the system reset for the rom. |
| 1208 | * We first disable the MMU, and then jump to the ROM reset address. | 1233 | * We first disable the MMU, and then jump to the ROM reset address. |
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index c38afdb45d7b..925807488022 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <asm/firmware.h> | 37 | #include <asm/firmware.h> |
| 38 | #include <asm/page_64.h> | 38 | #include <asm/page_64.h> |
| 39 | #include <asm/irqflags.h> | 39 | #include <asm/irqflags.h> |
| 40 | #include <asm/kvm_book3s_64_asm.h> | ||
| 40 | 41 | ||
| 41 | /* The physical memory is layed out such that the secondary processor | 42 | /* The physical memory is layed out such that the secondary processor |
| 42 | * spin code sits at 0x0000...0x00ff. On server, the vectors follow | 43 | * spin code sits at 0x0000...0x00ff. On server, the vectors follow |
| @@ -165,6 +166,12 @@ exception_marker: | |||
| 165 | #include "exceptions-64s.S" | 166 | #include "exceptions-64s.S" |
| 166 | #endif | 167 | #endif |
| 167 | 168 | ||
| 169 | /* KVM trampoline code needs to be close to the interrupt handlers */ | ||
| 170 | |||
| 171 | #ifdef CONFIG_KVM_BOOK3S_64_HANDLER | ||
| 172 | #include "../kvm/book3s_64_rmhandlers.S" | ||
| 173 | #endif | ||
| 174 | |||
| 168 | _GLOBAL(generic_secondary_thread_init) | 175 | _GLOBAL(generic_secondary_thread_init) |
| 169 | mr r24,r3 | 176 | mr r24,r3 |
| 170 | 177 | ||
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index 6ded19d01891..678f98cd5e64 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S | |||
| @@ -206,6 +206,8 @@ MachineCheck: | |||
| 206 | EXCEPTION_PROLOG | 206 | EXCEPTION_PROLOG |
| 207 | mfspr r4,SPRN_DAR | 207 | mfspr r4,SPRN_DAR |
| 208 | stw r4,_DAR(r11) | 208 | stw r4,_DAR(r11) |
| 209 | li r5,0x00f0 | ||
| 210 | mtspr SPRN_DAR,r5 /* Tag DAR, to be used in DTLB Error */ | ||
| 209 | mfspr r5,SPRN_DSISR | 211 | mfspr r5,SPRN_DSISR |
| 210 | stw r5,_DSISR(r11) | 212 | stw r5,_DSISR(r11) |
| 211 | addi r3,r1,STACK_FRAME_OVERHEAD | 213 | addi r3,r1,STACK_FRAME_OVERHEAD |
| @@ -222,6 +224,8 @@ DataAccess: | |||
| 222 | stw r10,_DSISR(r11) | 224 | stw r10,_DSISR(r11) |
| 223 | mr r5,r10 | 225 | mr r5,r10 |
| 224 | mfspr r4,SPRN_DAR | 226 | mfspr r4,SPRN_DAR |
| 227 | li r10,0x00f0 | ||
| 228 | mtspr SPRN_DAR,r10 /* Tag DAR, to be used in DTLB Error */ | ||
| 225 | EXC_XFER_EE_LITE(0x300, handle_page_fault) | 229 | EXC_XFER_EE_LITE(0x300, handle_page_fault) |
| 226 | 230 | ||
| 227 | /* Instruction access exception. | 231 | /* Instruction access exception. |
| @@ -244,6 +248,8 @@ Alignment: | |||
| 244 | EXCEPTION_PROLOG | 248 | EXCEPTION_PROLOG |
| 245 | mfspr r4,SPRN_DAR | 249 | mfspr r4,SPRN_DAR |
| 246 | stw r4,_DAR(r11) | 250 | stw r4,_DAR(r11) |
| 251 | li r5,0x00f0 | ||
| 252 | mtspr SPRN_DAR,r5 /* Tag DAR, to be used in DTLB Error */ | ||
| 247 | mfspr r5,SPRN_DSISR | 253 | mfspr r5,SPRN_DSISR |
| 248 | stw r5,_DSISR(r11) | 254 | stw r5,_DSISR(r11) |
| 249 | addi r3,r1,STACK_FRAME_OVERHEAD | 255 | addi r3,r1,STACK_FRAME_OVERHEAD |
| @@ -333,26 +339,20 @@ InstructionTLBMiss: | |||
| 333 | mfspr r11, SPRN_MD_TWC /* ....and get the pte address */ | 339 | mfspr r11, SPRN_MD_TWC /* ....and get the pte address */ |
| 334 | lwz r10, 0(r11) /* Get the pte */ | 340 | lwz r10, 0(r11) /* Get the pte */ |
| 335 | 341 | ||
| 336 | #ifdef CONFIG_SWAP | 342 | andi. r11, r10, _PAGE_ACCESSED | _PAGE_PRESENT |
| 337 | /* do not set the _PAGE_ACCESSED bit of a non-present page */ | 343 | cmpwi cr0, r11, _PAGE_ACCESSED | _PAGE_PRESENT |
| 338 | andi. r11, r10, _PAGE_PRESENT | 344 | bne- cr0, 2f |
| 339 | beq 4f | 345 | |
| 340 | ori r10, r10, _PAGE_ACCESSED | 346 | /* Clear PP lsb, 0x400 */ |
| 341 | mfspr r11, SPRN_MD_TWC /* get the pte address again */ | 347 | rlwinm r10, r10, 0, 22, 20 |
| 342 | stw r10, 0(r11) | ||
| 343 | 4: | ||
| 344 | #else | ||
| 345 | ori r10, r10, _PAGE_ACCESSED | ||
| 346 | stw r10, 0(r11) | ||
| 347 | #endif | ||
| 348 | 348 | ||
| 349 | /* The Linux PTE won't go exactly into the MMU TLB. | 349 | /* The Linux PTE won't go exactly into the MMU TLB. |
| 350 | * Software indicator bits 21, 22 and 28 must be clear. | 350 | * Software indicator bits 22 and 28 must be clear. |
| 351 | * Software indicator bits 24, 25, 26, and 27 must be | 351 | * Software indicator bits 24, 25, 26, and 27 must be |
| 352 | * set. All other Linux PTE bits control the behavior | 352 | * set. All other Linux PTE bits control the behavior |
| 353 | * of the MMU. | 353 | * of the MMU. |
| 354 | */ | 354 | */ |
| 355 | 2: li r11, 0x00f0 | 355 | li r11, 0x00f0 |
| 356 | rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ | 356 | rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ |
| 357 | DO_8xx_CPU6(0x2d80, r3) | 357 | DO_8xx_CPU6(0x2d80, r3) |
| 358 | mtspr SPRN_MI_RPN, r10 /* Update TLB entry */ | 358 | mtspr SPRN_MI_RPN, r10 /* Update TLB entry */ |
| @@ -365,6 +365,22 @@ InstructionTLBMiss: | |||
| 365 | lwz r3, 8(r0) | 365 | lwz r3, 8(r0) |
| 366 | #endif | 366 | #endif |
| 367 | rfi | 367 | rfi |
| 368 | 2: | ||
| 369 | mfspr r11, SPRN_SRR1 | ||
| 370 | /* clear all error bits as TLB Miss | ||
| 371 | * sets a few unconditionally | ||
| 372 | */ | ||
| 373 | rlwinm r11, r11, 0, 0xffff | ||
| 374 | mtspr SPRN_SRR1, r11 | ||
| 375 | |||
| 376 | mfspr r10, SPRN_M_TW /* Restore registers */ | ||
| 377 | lwz r11, 0(r0) | ||
| 378 | mtcr r11 | ||
| 379 | lwz r11, 4(r0) | ||
| 380 | #ifdef CONFIG_8xx_CPU6 | ||
| 381 | lwz r3, 8(r0) | ||
| 382 | #endif | ||
| 383 | b InstructionAccess | ||
| 368 | 384 | ||
| 369 | . = 0x1200 | 385 | . = 0x1200 |
| 370 | DataStoreTLBMiss: | 386 | DataStoreTLBMiss: |
| @@ -406,29 +422,45 @@ DataStoreTLBMiss: | |||
| 406 | * above. | 422 | * above. |
| 407 | */ | 423 | */ |
| 408 | rlwimi r11, r10, 0, 27, 27 | 424 | rlwimi r11, r10, 0, 27, 27 |
| 425 | /* Insert the WriteThru flag into the TWC from the Linux PTE. | ||
| 426 | * It is bit 25 in the Linux PTE and bit 30 in the TWC | ||
| 427 | */ | ||
| 428 | rlwimi r11, r10, 32-5, 30, 30 | ||
| 409 | DO_8xx_CPU6(0x3b80, r3) | 429 | DO_8xx_CPU6(0x3b80, r3) |
| 410 | mtspr SPRN_MD_TWC, r11 | 430 | mtspr SPRN_MD_TWC, r11 |
| 411 | 431 | ||
| 412 | #ifdef CONFIG_SWAP | 432 | /* Both _PAGE_ACCESSED and _PAGE_PRESENT has to be set. |
| 413 | /* do not set the _PAGE_ACCESSED bit of a non-present page */ | 433 | * We also need to know if the insn is a load/store, so: |
| 414 | andi. r11, r10, _PAGE_PRESENT | 434 | * Clear _PAGE_PRESENT and load that which will |
| 415 | beq 4f | 435 | * trap into DTLB Error with store bit set accordinly. |
| 416 | ori r10, r10, _PAGE_ACCESSED | 436 | */ |
| 417 | 4: | 437 | /* PRESENT=0x1, ACCESSED=0x20 |
| 418 | /* and update pte in table */ | 438 | * r11 = ((r10 & PRESENT) & ((r10 & ACCESSED) >> 5)); |
| 419 | #else | 439 | * r10 = (r10 & ~PRESENT) | r11; |
| 420 | ori r10, r10, _PAGE_ACCESSED | 440 | */ |
| 421 | #endif | 441 | rlwinm r11, r10, 32-5, _PAGE_PRESENT |
| 422 | mfspr r11, SPRN_MD_TWC /* get the pte address again */ | 442 | and r11, r11, r10 |
| 423 | stw r10, 0(r11) | 443 | rlwimi r10, r11, 0, _PAGE_PRESENT |
| 444 | |||
| 445 | /* Honour kernel RO, User NA */ | ||
| 446 | /* 0x200 == Extended encoding, bit 22 */ | ||
| 447 | /* r11 = (r10 & _PAGE_USER) >> 2 */ | ||
| 448 | rlwinm r11, r10, 32-2, 0x200 | ||
| 449 | or r10, r11, r10 | ||
| 450 | /* r11 = (r10 & _PAGE_RW) >> 1 */ | ||
| 451 | rlwinm r11, r10, 32-1, 0x200 | ||
| 452 | or r10, r11, r10 | ||
| 453 | /* invert RW and 0x200 bits */ | ||
| 454 | xori r10, r10, _PAGE_RW | 0x200 | ||
| 424 | 455 | ||
| 425 | /* The Linux PTE won't go exactly into the MMU TLB. | 456 | /* The Linux PTE won't go exactly into the MMU TLB. |
| 426 | * Software indicator bits 21, 22 and 28 must be clear. | 457 | * Software indicator bits 22 and 28 must be clear. |
| 427 | * Software indicator bits 24, 25, 26, and 27 must be | 458 | * Software indicator bits 24, 25, 26, and 27 must be |
| 428 | * set. All other Linux PTE bits control the behavior | 459 | * set. All other Linux PTE bits control the behavior |
| 429 | * of the MMU. | 460 | * of the MMU. |
| 430 | */ | 461 | */ |
| 431 | 2: li r11, 0x00f0 | 462 | 2: li r11, 0x00f0 |
| 463 | mtspr SPRN_DAR,r11 /* Tag DAR */ | ||
| 432 | rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ | 464 | rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ |
| 433 | DO_8xx_CPU6(0x3d80, r3) | 465 | DO_8xx_CPU6(0x3d80, r3) |
| 434 | mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ | 466 | mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ |
| @@ -469,97 +501,10 @@ DataTLBError: | |||
| 469 | stw r10, 0(r0) | 501 | stw r10, 0(r0) |
| 470 | stw r11, 4(r0) | 502 | stw r11, 4(r0) |
| 471 | 503 | ||
| 472 | /* First, make sure this was a store operation. | ||
| 473 | */ | ||
| 474 | mfspr r10, SPRN_DSISR | ||
| 475 | andis. r11, r10, 0x0200 /* If set, indicates store op */ | ||
| 476 | beq 2f | ||
| 477 | |||
| 478 | /* The EA of a data TLB miss is automatically stored in the MD_EPN | ||
| 479 | * register. The EA of a data TLB error is automatically stored in | ||
| 480 | * the DAR, but not the MD_EPN register. We must copy the 20 most | ||
| 481 | * significant bits of the EA from the DAR to MD_EPN before we | ||
| 482 | * start walking the page tables. We also need to copy the CASID | ||
| 483 | * value from the M_CASID register. | ||
| 484 | * Addendum: The EA of a data TLB error is _supposed_ to be stored | ||
| 485 | * in DAR, but it seems that this doesn't happen in some cases, such | ||
| 486 | * as when the error is due to a dcbi instruction to a page with a | ||
| 487 | * TLB that doesn't have the changed bit set. In such cases, there | ||
| 488 | * does not appear to be any way to recover the EA of the error | ||
| 489 | * since it is neither in DAR nor MD_EPN. As a workaround, the | ||
| 490 | * _PAGE_HWWRITE bit is set for all kernel data pages when the PTEs | ||
| 491 | * are initialized in mapin_ram(). This will avoid the problem, | ||
| 492 | * assuming we only use the dcbi instruction on kernel addresses. | ||
| 493 | */ | ||
| 494 | mfspr r10, SPRN_DAR | 504 | mfspr r10, SPRN_DAR |
| 495 | rlwinm r11, r10, 0, 0, 19 | 505 | cmpwi cr0, r10, 0x00f0 |
| 496 | ori r11, r11, MD_EVALID | 506 | beq- FixupDAR /* must be a buggy dcbX, icbi insn. */ |
| 497 | mfspr r10, SPRN_M_CASID | 507 | DARFixed:/* Return from dcbx instruction bug workaround, r10 holds value of DAR */ |
| 498 | rlwimi r11, r10, 0, 28, 31 | ||
| 499 | DO_8xx_CPU6(0x3780, r3) | ||
| 500 | mtspr SPRN_MD_EPN, r11 | ||
| 501 | |||
| 502 | mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */ | ||
| 503 | |||
| 504 | /* If we are faulting a kernel address, we have to use the | ||
| 505 | * kernel page tables. | ||
| 506 | */ | ||
| 507 | andi. r11, r10, 0x0800 | ||
| 508 | beq 3f | ||
| 509 | lis r11, swapper_pg_dir@h | ||
| 510 | ori r11, r11, swapper_pg_dir@l | ||
| 511 | rlwimi r10, r11, 0, 2, 19 | ||
| 512 | 3: | ||
| 513 | lwz r11, 0(r10) /* Get the level 1 entry */ | ||
| 514 | rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ | ||
| 515 | beq 2f /* If zero, bail */ | ||
| 516 | |||
| 517 | /* We have a pte table, so fetch the pte from the table. | ||
| 518 | */ | ||
| 519 | ori r11, r11, 1 /* Set valid bit in physical L2 page */ | ||
| 520 | DO_8xx_CPU6(0x3b80, r3) | ||
| 521 | mtspr SPRN_MD_TWC, r11 /* Load pte table base address */ | ||
| 522 | mfspr r11, SPRN_MD_TWC /* ....and get the pte address */ | ||
| 523 | lwz r10, 0(r11) /* Get the pte */ | ||
| 524 | |||
| 525 | andi. r11, r10, _PAGE_RW /* Is it writeable? */ | ||
| 526 | beq 2f /* Bail out if not */ | ||
| 527 | |||
| 528 | /* Update 'changed', among others. | ||
| 529 | */ | ||
| 530 | #ifdef CONFIG_SWAP | ||
| 531 | ori r10, r10, _PAGE_DIRTY|_PAGE_HWWRITE | ||
| 532 | /* do not set the _PAGE_ACCESSED bit of a non-present page */ | ||
| 533 | andi. r11, r10, _PAGE_PRESENT | ||
| 534 | beq 4f | ||
| 535 | ori r10, r10, _PAGE_ACCESSED | ||
| 536 | 4: | ||
| 537 | #else | ||
| 538 | ori r10, r10, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE | ||
| 539 | #endif | ||
| 540 | mfspr r11, SPRN_MD_TWC /* Get pte address again */ | ||
| 541 | stw r10, 0(r11) /* and update pte in table */ | ||
| 542 | |||
| 543 | /* The Linux PTE won't go exactly into the MMU TLB. | ||
| 544 | * Software indicator bits 21, 22 and 28 must be clear. | ||
| 545 | * Software indicator bits 24, 25, 26, and 27 must be | ||
| 546 | * set. All other Linux PTE bits control the behavior | ||
| 547 | * of the MMU. | ||
| 548 | */ | ||
| 549 | li r11, 0x00f0 | ||
| 550 | rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ | ||
| 551 | DO_8xx_CPU6(0x3d80, r3) | ||
| 552 | mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ | ||
| 553 | |||
| 554 | mfspr r10, SPRN_M_TW /* Restore registers */ | ||
| 555 | lwz r11, 0(r0) | ||
| 556 | mtcr r11 | ||
| 557 | lwz r11, 4(r0) | ||
| 558 | #ifdef CONFIG_8xx_CPU6 | ||
| 559 | lwz r3, 8(r0) | ||
| 560 | #endif | ||
| 561 | rfi | ||
| 562 | 2: | ||
| 563 | mfspr r10, SPRN_M_TW /* Restore registers */ | 508 | mfspr r10, SPRN_M_TW /* Restore registers */ |
| 564 | lwz r11, 0(r0) | 509 | lwz r11, 0(r0) |
| 565 | mtcr r11 | 510 | mtcr r11 |
| @@ -588,6 +533,140 @@ DataTLBError: | |||
| 588 | 533 | ||
| 589 | . = 0x2000 | 534 | . = 0x2000 |
| 590 | 535 | ||
| 536 | /* This is the procedure to calculate the data EA for buggy dcbx,dcbi instructions | ||
| 537 | * by decoding the registers used by the dcbx instruction and adding them. | ||
| 538 | * DAR is set to the calculated address and r10 also holds the EA on exit. | ||
| 539 | */ | ||
| 540 | /* define if you don't want to use self modifying code */ | ||
| 541 | #define NO_SELF_MODIFYING_CODE | ||
| 542 | FixupDAR:/* Entry point for dcbx workaround. */ | ||
| 543 | /* fetch instruction from memory. */ | ||
| 544 | mfspr r10, SPRN_SRR0 | ||
| 545 | DO_8xx_CPU6(0x3780, r3) | ||
| 546 | mtspr SPRN_MD_EPN, r10 | ||
| 547 | mfspr r11, SPRN_M_TWB /* Get level 1 table entry address */ | ||
| 548 | cmplwi cr0, r11, 0x0800 | ||
| 549 | blt- 3f /* Branch if user space */ | ||
| 550 | lis r11, (swapper_pg_dir-PAGE_OFFSET)@h | ||
| 551 | ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l | ||
| 552 | rlwimi r11, r10, 32-20, 0xffc /* r11 = r11&~0xffc|(r10>>20)&0xffc */ | ||
| 553 | 3: lwz r11, 0(r11) /* Get the level 1 entry */ | ||
| 554 | DO_8xx_CPU6(0x3b80, r3) | ||
| 555 | mtspr SPRN_MD_TWC, r11 /* Load pte table base address */ | ||
| 556 | mfspr r11, SPRN_MD_TWC /* ....and get the pte address */ | ||
| 557 | lwz r11, 0(r11) /* Get the pte */ | ||
| 558 | /* concat physical page address(r11) and page offset(r10) */ | ||
| 559 | rlwimi r11, r10, 0, 20, 31 | ||
| 560 | lwz r11,0(r11) | ||
| 561 | /* Check if it really is a dcbx instruction. */ | ||
| 562 | /* dcbt and dcbtst does not generate DTLB Misses/Errors, | ||
| 563 | * no need to include them here */ | ||
| 564 | srwi r10, r11, 26 /* check if major OP code is 31 */ | ||
| 565 | cmpwi cr0, r10, 31 | ||
| 566 | bne- 141f | ||
| 567 | rlwinm r10, r11, 0, 21, 30 | ||
| 568 | cmpwi cr0, r10, 2028 /* Is dcbz? */ | ||
| 569 | beq+ 142f | ||
| 570 | cmpwi cr0, r10, 940 /* Is dcbi? */ | ||
| 571 | beq+ 142f | ||
| 572 | cmpwi cr0, r10, 108 /* Is dcbst? */ | ||
| 573 | beq+ 144f /* Fix up store bit! */ | ||
| 574 | cmpwi cr0, r10, 172 /* Is dcbf? */ | ||
| 575 | beq+ 142f | ||
| 576 | cmpwi cr0, r10, 1964 /* Is icbi? */ | ||
| 577 | beq+ 142f | ||
| 578 | 141: mfspr r10, SPRN_DAR /* r10 must hold DAR at exit */ | ||
| 579 | b DARFixed /* Nope, go back to normal TLB processing */ | ||
| 580 | |||
| 581 | 144: mfspr r10, SPRN_DSISR | ||
| 582 | rlwinm r10, r10,0,7,5 /* Clear store bit for buggy dcbst insn */ | ||
| 583 | mtspr SPRN_DSISR, r10 | ||
| 584 | 142: /* continue, it was a dcbx, dcbi instruction. */ | ||
| 585 | #ifdef CONFIG_8xx_CPU6 | ||
| 586 | lwz r3, 8(r0) /* restore r3 from memory */ | ||
| 587 | #endif | ||
| 588 | #ifndef NO_SELF_MODIFYING_CODE | ||
| 589 | andis. r10,r11,0x1f /* test if reg RA is r0 */ | ||
| 590 | li r10,modified_instr@l | ||
| 591 | dcbtst r0,r10 /* touch for store */ | ||
| 592 | rlwinm r11,r11,0,0,20 /* Zero lower 10 bits */ | ||
| 593 | oris r11,r11,640 /* Transform instr. to a "add r10,RA,RB" */ | ||
| 594 | ori r11,r11,532 | ||
| 595 | stw r11,0(r10) /* store add/and instruction */ | ||
| 596 | dcbf 0,r10 /* flush new instr. to memory. */ | ||
| 597 | icbi 0,r10 /* invalidate instr. cache line */ | ||
| 598 | lwz r11, 4(r0) /* restore r11 from memory */ | ||
| 599 | mfspr r10, SPRN_M_TW /* restore r10 from M_TW */ | ||
| 600 | isync /* Wait until new instr is loaded from memory */ | ||
| 601 | modified_instr: | ||
| 602 | .space 4 /* this is where the add instr. is stored */ | ||
| 603 | bne+ 143f | ||
| 604 | subf r10,r0,r10 /* r10=r10-r0, only if reg RA is r0 */ | ||
| 605 | 143: mtdar r10 /* store faulting EA in DAR */ | ||
| 606 | b DARFixed /* Go back to normal TLB handling */ | ||
| 607 | #else | ||
| 608 | mfctr r10 | ||
| 609 | mtdar r10 /* save ctr reg in DAR */ | ||
| 610 | rlwinm r10, r11, 24, 24, 28 /* offset into jump table for reg RB */ | ||
| 611 | addi r10, r10, 150f@l /* add start of table */ | ||
| 612 | mtctr r10 /* load ctr with jump address */ | ||
| 613 | xor r10, r10, r10 /* sum starts at zero */ | ||
| 614 | bctr /* jump into table */ | ||
| 615 | 150: | ||
| 616 | add r10, r10, r0 ;b 151f | ||
| 617 | add r10, r10, r1 ;b 151f | ||
| 618 | add r10, r10, r2 ;b 151f | ||
| 619 | add r10, r10, r3 ;b 151f | ||
| 620 | add r10, r10, r4 ;b 151f | ||
| 621 | add r10, r10, r5 ;b 151f | ||
| 622 | add r10, r10, r6 ;b 151f | ||
| 623 | add r10, r10, r7 ;b 151f | ||
| 624 | add r10, r10, r8 ;b 151f | ||
| 625 | add r10, r10, r9 ;b 151f | ||
| 626 | mtctr r11 ;b 154f /* r10 needs special handling */ | ||
| 627 | mtctr r11 ;b 153f /* r11 needs special handling */ | ||
| 628 | add r10, r10, r12 ;b 151f | ||
| 629 | add r10, r10, r13 ;b 151f | ||
| 630 | add r10, r10, r14 ;b 151f | ||
| 631 | add r10, r10, r15 ;b 151f | ||
| 632 | add r10, r10, r16 ;b 151f | ||
| 633 | add r10, r10, r17 ;b 151f | ||
| 634 | add r10, r10, r18 ;b 151f | ||
| 635 | add r10, r10, r19 ;b 151f | ||
| 636 | add r10, r10, r20 ;b 151f | ||
| 637 | add r10, r10, r21 ;b 151f | ||
| 638 | add r10, r10, r22 ;b 151f | ||
| 639 | add r10, r10, r23 ;b 151f | ||
| 640 | add r10, r10, r24 ;b 151f | ||
| 641 | add r10, r10, r25 ;b 151f | ||
| 642 | add r10, r10, r26 ;b 151f | ||
| 643 | add r10, r10, r27 ;b 151f | ||
| 644 | add r10, r10, r28 ;b 151f | ||
| 645 | add r10, r10, r29 ;b 151f | ||
| 646 | add r10, r10, r30 ;b 151f | ||
| 647 | add r10, r10, r31 | ||
| 648 | 151: | ||
| 649 | rlwinm. r11,r11,19,24,28 /* offset into jump table for reg RA */ | ||
| 650 | beq 152f /* if reg RA is zero, don't add it */ | ||
| 651 | addi r11, r11, 150b@l /* add start of table */ | ||
| 652 | mtctr r11 /* load ctr with jump address */ | ||
| 653 | rlwinm r11,r11,0,16,10 /* make sure we don't execute this more than once */ | ||
| 654 | bctr /* jump into table */ | ||
| 655 | 152: | ||
| 656 | mfdar r11 | ||
| 657 | mtctr r11 /* restore ctr reg from DAR */ | ||
| 658 | mtdar r10 /* save fault EA to DAR */ | ||
| 659 | b DARFixed /* Go back to normal TLB handling */ | ||
| 660 | |||
| 661 | /* special handling for r10,r11 since these are modified already */ | ||
| 662 | 153: lwz r11, 4(r0) /* load r11 from memory */ | ||
| 663 | b 155f | ||
| 664 | 154: mfspr r11, SPRN_M_TW /* load r10 from M_TW */ | ||
| 665 | 155: add r10, r10, r11 /* add it */ | ||
| 666 | mfctr r11 /* restore r11 */ | ||
| 667 | b 151b | ||
| 668 | #endif | ||
| 669 | |||
| 591 | .globl giveup_fpu | 670 | .globl giveup_fpu |
| 592 | giveup_fpu: | 671 | giveup_fpu: |
| 593 | blr | 672 | blr |
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 975788ca05d2..7f4bd7f3b6af 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S | |||
| @@ -944,28 +944,6 @@ _GLOBAL(__setup_e500mc_ivors) | |||
| 944 | blr | 944 | blr |
| 945 | 945 | ||
| 946 | /* | 946 | /* |
| 947 | * extern void loadcam_entry(unsigned int index) | ||
| 948 | * | ||
| 949 | * Load TLBCAM[index] entry in to the L2 CAM MMU | ||
| 950 | */ | ||
| 951 | _GLOBAL(loadcam_entry) | ||
| 952 | lis r4,TLBCAM@ha | ||
| 953 | addi r4,r4,TLBCAM@l | ||
| 954 | mulli r5,r3,TLBCAM_SIZE | ||
| 955 | add r3,r5,r4 | ||
| 956 | lwz r4,0(r3) | ||
| 957 | mtspr SPRN_MAS0,r4 | ||
| 958 | lwz r4,4(r3) | ||
| 959 | mtspr SPRN_MAS1,r4 | ||
| 960 | lwz r4,8(r3) | ||
| 961 | mtspr SPRN_MAS2,r4 | ||
| 962 | lwz r4,12(r3) | ||
| 963 | mtspr SPRN_MAS3,r4 | ||
| 964 | tlbwe | ||
| 965 | isync | ||
| 966 | blr | ||
| 967 | |||
| 968 | /* | ||
| 969 | * extern void giveup_altivec(struct task_struct *prev) | 947 | * extern void giveup_altivec(struct task_struct *prev) |
| 970 | * | 948 | * |
| 971 | * The e500 core does not have an AltiVec unit. | 949 | * The e500 core does not have an AltiVec unit. |
diff --git a/arch/powerpc/kernel/io.c b/arch/powerpc/kernel/io.c index 1882bf419fa6..8dc7547c2377 100644 --- a/arch/powerpc/kernel/io.c +++ b/arch/powerpc/kernel/io.c | |||
| @@ -161,7 +161,7 @@ void _memcpy_fromio(void *dest, const volatile void __iomem *src, | |||
| 161 | dest++; | 161 | dest++; |
| 162 | n--; | 162 | n--; |
| 163 | } | 163 | } |
| 164 | while(n > 4) { | 164 | while(n >= 4) { |
| 165 | *((u32 *)dest) = *((volatile u32 *)vsrc); | 165 | *((u32 *)dest) = *((volatile u32 *)vsrc); |
| 166 | eieio(); | 166 | eieio(); |
| 167 | vsrc += 4; | 167 | vsrc += 4; |
| @@ -190,7 +190,7 @@ void _memcpy_toio(volatile void __iomem *dest, const void *src, unsigned long n) | |||
| 190 | vdest++; | 190 | vdest++; |
| 191 | n--; | 191 | n--; |
| 192 | } | 192 | } |
| 193 | while(n > 4) { | 193 | while(n >= 4) { |
| 194 | *((volatile u32 *)vdest) = *((volatile u32 *)src); | 194 | *((volatile u32 *)vdest) = *((volatile u32 *)src); |
| 195 | src += 4; | 195 | src += 4; |
| 196 | vdest += 4; | 196 | vdest += 4; |
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index fd51578e29dd..5547ae6e6b0b 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c | |||
| @@ -30,7 +30,7 @@ | |||
| 30 | #include <linux/spinlock.h> | 30 | #include <linux/spinlock.h> |
| 31 | #include <linux/string.h> | 31 | #include <linux/string.h> |
| 32 | #include <linux/dma-mapping.h> | 32 | #include <linux/dma-mapping.h> |
| 33 | #include <linux/bitops.h> | 33 | #include <linux/bitmap.h> |
| 34 | #include <linux/iommu-helper.h> | 34 | #include <linux/iommu-helper.h> |
| 35 | #include <linux/crash_dump.h> | 35 | #include <linux/crash_dump.h> |
| 36 | #include <asm/io.h> | 36 | #include <asm/io.h> |
| @@ -251,7 +251,7 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, | |||
| 251 | } | 251 | } |
| 252 | 252 | ||
| 253 | ppc_md.tce_free(tbl, entry, npages); | 253 | ppc_md.tce_free(tbl, entry, npages); |
| 254 | iommu_area_free(tbl->it_map, free_entry, npages); | 254 | bitmap_clear(tbl->it_map, free_entry, npages); |
| 255 | } | 255 | } |
| 256 | 256 | ||
| 257 | static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, | 257 | static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 02a334662cc0..9040330b0530 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
| @@ -87,7 +87,10 @@ extern int tau_interrupts(int); | |||
| 87 | #endif /* CONFIG_PPC32 */ | 87 | #endif /* CONFIG_PPC32 */ |
| 88 | 88 | ||
| 89 | #ifdef CONFIG_PPC64 | 89 | #ifdef CONFIG_PPC64 |
| 90 | |||
| 91 | #ifndef CONFIG_SPARSE_IRQ | ||
| 90 | EXPORT_SYMBOL(irq_desc); | 92 | EXPORT_SYMBOL(irq_desc); |
| 93 | #endif | ||
| 91 | 94 | ||
| 92 | int distribute_irqs = 1; | 95 | int distribute_irqs = 1; |
| 93 | 96 | ||
| @@ -189,33 +192,7 @@ int show_interrupts(struct seq_file *p, void *v) | |||
| 189 | for_each_online_cpu(j) | 192 | for_each_online_cpu(j) |
| 190 | seq_printf(p, "CPU%d ", j); | 193 | seq_printf(p, "CPU%d ", j); |
| 191 | seq_putc(p, '\n'); | 194 | seq_putc(p, '\n'); |
| 192 | } | 195 | } else if (i == nr_irqs) { |
| 193 | |||
| 194 | if (i < NR_IRQS) { | ||
| 195 | desc = get_irq_desc(i); | ||
| 196 | spin_lock_irqsave(&desc->lock, flags); | ||
| 197 | action = desc->action; | ||
| 198 | if (!action || !action->handler) | ||
| 199 | goto skip; | ||
| 200 | seq_printf(p, "%3d: ", i); | ||
| 201 | #ifdef CONFIG_SMP | ||
| 202 | for_each_online_cpu(j) | ||
| 203 | seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); | ||
| 204 | #else | ||
| 205 | seq_printf(p, "%10u ", kstat_irqs(i)); | ||
| 206 | #endif /* CONFIG_SMP */ | ||
| 207 | if (desc->chip) | ||
| 208 | seq_printf(p, " %s ", desc->chip->typename); | ||
| 209 | else | ||
| 210 | seq_puts(p, " None "); | ||
| 211 | seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge "); | ||
| 212 | seq_printf(p, " %s", action->name); | ||
| 213 | for (action = action->next; action; action = action->next) | ||
| 214 | seq_printf(p, ", %s", action->name); | ||
| 215 | seq_putc(p, '\n'); | ||
| 216 | skip: | ||
| 217 | spin_unlock_irqrestore(&desc->lock, flags); | ||
| 218 | } else if (i == NR_IRQS) { | ||
| 219 | #if defined(CONFIG_PPC32) && defined(CONFIG_TAU_INT) | 196 | #if defined(CONFIG_PPC32) && defined(CONFIG_TAU_INT) |
| 220 | if (tau_initialized){ | 197 | if (tau_initialized){ |
| 221 | seq_puts(p, "TAU: "); | 198 | seq_puts(p, "TAU: "); |
| @@ -225,30 +202,68 @@ skip: | |||
| 225 | } | 202 | } |
| 226 | #endif /* CONFIG_PPC32 && CONFIG_TAU_INT*/ | 203 | #endif /* CONFIG_PPC32 && CONFIG_TAU_INT*/ |
| 227 | seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); | 204 | seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); |
| 205 | |||
| 206 | return 0; | ||
| 228 | } | 207 | } |
| 208 | |||
| 209 | desc = irq_to_desc(i); | ||
| 210 | if (!desc) | ||
| 211 | return 0; | ||
| 212 | |||
| 213 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
| 214 | |||
| 215 | action = desc->action; | ||
| 216 | if (!action || !action->handler) | ||
| 217 | goto skip; | ||
| 218 | |||
| 219 | seq_printf(p, "%3d: ", i); | ||
| 220 | #ifdef CONFIG_SMP | ||
| 221 | for_each_online_cpu(j) | ||
| 222 | seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); | ||
| 223 | #else | ||
| 224 | seq_printf(p, "%10u ", kstat_irqs(i)); | ||
| 225 | #endif /* CONFIG_SMP */ | ||
| 226 | |||
| 227 | if (desc->chip) | ||
| 228 | seq_printf(p, " %s ", desc->chip->name); | ||
| 229 | else | ||
| 230 | seq_puts(p, " None "); | ||
| 231 | |||
| 232 | seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge "); | ||
| 233 | seq_printf(p, " %s", action->name); | ||
| 234 | |||
| 235 | for (action = action->next; action; action = action->next) | ||
| 236 | seq_printf(p, ", %s", action->name); | ||
| 237 | seq_putc(p, '\n'); | ||
| 238 | |||
| 239 | skip: | ||
| 240 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
| 241 | |||
| 229 | return 0; | 242 | return 0; |
| 230 | } | 243 | } |
| 231 | 244 | ||
| 232 | #ifdef CONFIG_HOTPLUG_CPU | 245 | #ifdef CONFIG_HOTPLUG_CPU |
| 233 | void fixup_irqs(cpumask_t map) | 246 | void fixup_irqs(cpumask_t map) |
| 234 | { | 247 | { |
| 248 | struct irq_desc *desc; | ||
| 235 | unsigned int irq; | 249 | unsigned int irq; |
| 236 | static int warned; | 250 | static int warned; |
| 237 | 251 | ||
| 238 | for_each_irq(irq) { | 252 | for_each_irq(irq) { |
| 239 | cpumask_t mask; | 253 | cpumask_t mask; |
| 240 | 254 | ||
| 241 | if (irq_desc[irq].status & IRQ_PER_CPU) | 255 | desc = irq_to_desc(irq); |
| 256 | if (desc && desc->status & IRQ_PER_CPU) | ||
| 242 | continue; | 257 | continue; |
| 243 | 258 | ||
| 244 | cpumask_and(&mask, irq_desc[irq].affinity, &map); | 259 | cpumask_and(&mask, desc->affinity, &map); |
| 245 | if (any_online_cpu(mask) == NR_CPUS) { | 260 | if (any_online_cpu(mask) == NR_CPUS) { |
| 246 | printk("Breaking affinity for irq %i\n", irq); | 261 | printk("Breaking affinity for irq %i\n", irq); |
| 247 | mask = map; | 262 | mask = map; |
| 248 | } | 263 | } |
| 249 | if (irq_desc[irq].chip->set_affinity) | 264 | if (desc->chip->set_affinity) |
| 250 | irq_desc[irq].chip->set_affinity(irq, &mask); | 265 | desc->chip->set_affinity(irq, &mask); |
| 251 | else if (irq_desc[irq].action && !(warned++)) | 266 | else if (desc->action && !(warned++)) |
| 252 | printk("Cannot set affinity for irq %i\n", irq); | 267 | printk("Cannot set affinity for irq %i\n", irq); |
| 253 | } | 268 | } |
| 254 | 269 | ||
| @@ -275,7 +290,7 @@ static inline void handle_one_irq(unsigned int irq) | |||
| 275 | return; | 290 | return; |
| 276 | } | 291 | } |
| 277 | 292 | ||
| 278 | desc = irq_desc + irq; | 293 | desc = irq_to_desc(irq); |
| 279 | saved_sp_limit = current->thread.ksp_limit; | 294 | saved_sp_limit = current->thread.ksp_limit; |
| 280 | 295 | ||
| 281 | irqtp->task = curtp->task; | 296 | irqtp->task = curtp->task; |
| @@ -541,7 +556,7 @@ struct irq_host *irq_alloc_host(struct device_node *of_node, | |||
| 541 | smp_wmb(); | 556 | smp_wmb(); |
| 542 | 557 | ||
| 543 | /* Clear norequest flags */ | 558 | /* Clear norequest flags */ |
| 544 | get_irq_desc(i)->status &= ~IRQ_NOREQUEST; | 559 | irq_to_desc(i)->status &= ~IRQ_NOREQUEST; |
| 545 | 560 | ||
| 546 | /* Legacy flags are left to default at this point, | 561 | /* Legacy flags are left to default at this point, |
| 547 | * one can then use irq_create_mapping() to | 562 | * one can then use irq_create_mapping() to |
| @@ -607,8 +622,16 @@ void irq_set_virq_count(unsigned int count) | |||
| 607 | static int irq_setup_virq(struct irq_host *host, unsigned int virq, | 622 | static int irq_setup_virq(struct irq_host *host, unsigned int virq, |
| 608 | irq_hw_number_t hwirq) | 623 | irq_hw_number_t hwirq) |
| 609 | { | 624 | { |
| 625 | struct irq_desc *desc; | ||
| 626 | |||
| 627 | desc = irq_to_desc_alloc_node(virq, 0); | ||
| 628 | if (!desc) { | ||
| 629 | pr_debug("irq: -> allocating desc failed\n"); | ||
| 630 | goto error; | ||
| 631 | } | ||
| 632 | |||
| 610 | /* Clear IRQ_NOREQUEST flag */ | 633 | /* Clear IRQ_NOREQUEST flag */ |
| 611 | get_irq_desc(virq)->status &= ~IRQ_NOREQUEST; | 634 | desc->status &= ~IRQ_NOREQUEST; |
| 612 | 635 | ||
| 613 | /* map it */ | 636 | /* map it */ |
| 614 | smp_wmb(); | 637 | smp_wmb(); |
| @@ -617,11 +640,14 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq, | |||
| 617 | 640 | ||
| 618 | if (host->ops->map(host, virq, hwirq)) { | 641 | if (host->ops->map(host, virq, hwirq)) { |
| 619 | pr_debug("irq: -> mapping failed, freeing\n"); | 642 | pr_debug("irq: -> mapping failed, freeing\n"); |
| 620 | irq_free_virt(virq, 1); | 643 | goto error; |
| 621 | return -1; | ||
| 622 | } | 644 | } |
| 623 | 645 | ||
| 624 | return 0; | 646 | return 0; |
| 647 | |||
| 648 | error: | ||
| 649 | irq_free_virt(virq, 1); | ||
| 650 | return -1; | ||
| 625 | } | 651 | } |
| 626 | 652 | ||
| 627 | unsigned int irq_create_direct_mapping(struct irq_host *host) | 653 | unsigned int irq_create_direct_mapping(struct irq_host *host) |
| @@ -705,7 +731,7 @@ unsigned int irq_create_mapping(struct irq_host *host, | |||
| 705 | EXPORT_SYMBOL_GPL(irq_create_mapping); | 731 | EXPORT_SYMBOL_GPL(irq_create_mapping); |
| 706 | 732 | ||
| 707 | unsigned int irq_create_of_mapping(struct device_node *controller, | 733 | unsigned int irq_create_of_mapping(struct device_node *controller, |
| 708 | u32 *intspec, unsigned int intsize) | 734 | const u32 *intspec, unsigned int intsize) |
| 709 | { | 735 | { |
| 710 | struct irq_host *host; | 736 | struct irq_host *host; |
| 711 | irq_hw_number_t hwirq; | 737 | irq_hw_number_t hwirq; |
| @@ -738,7 +764,7 @@ unsigned int irq_create_of_mapping(struct device_node *controller, | |||
| 738 | 764 | ||
| 739 | /* Set type if specified and different than the current one */ | 765 | /* Set type if specified and different than the current one */ |
| 740 | if (type != IRQ_TYPE_NONE && | 766 | if (type != IRQ_TYPE_NONE && |
| 741 | type != (get_irq_desc(virq)->status & IRQF_TRIGGER_MASK)) | 767 | type != (irq_to_desc(virq)->status & IRQF_TRIGGER_MASK)) |
| 742 | set_irq_type(virq, type); | 768 | set_irq_type(virq, type); |
| 743 | return virq; | 769 | return virq; |
| 744 | } | 770 | } |
| @@ -810,7 +836,7 @@ void irq_dispose_mapping(unsigned int virq) | |||
| 810 | irq_map[virq].hwirq = host->inval_irq; | 836 | irq_map[virq].hwirq = host->inval_irq; |
| 811 | 837 | ||
| 812 | /* Set some flags */ | 838 | /* Set some flags */ |
| 813 | get_irq_desc(virq)->status |= IRQ_NOREQUEST; | 839 | irq_to_desc(virq)->status |= IRQ_NOREQUEST; |
| 814 | 840 | ||
| 815 | /* Free it */ | 841 | /* Free it */ |
| 816 | irq_free_virt(virq, 1); | 842 | irq_free_virt(virq, 1); |
| @@ -1002,12 +1028,24 @@ void irq_free_virt(unsigned int virq, unsigned int count) | |||
| 1002 | spin_unlock_irqrestore(&irq_big_lock, flags); | 1028 | spin_unlock_irqrestore(&irq_big_lock, flags); |
| 1003 | } | 1029 | } |
| 1004 | 1030 | ||
| 1005 | void irq_early_init(void) | 1031 | int arch_early_irq_init(void) |
| 1006 | { | 1032 | { |
| 1007 | unsigned int i; | 1033 | struct irq_desc *desc; |
| 1034 | int i; | ||
| 1035 | |||
| 1036 | for (i = 0; i < NR_IRQS; i++) { | ||
| 1037 | desc = irq_to_desc(i); | ||
| 1038 | if (desc) | ||
| 1039 | desc->status |= IRQ_NOREQUEST; | ||
| 1040 | } | ||
| 1008 | 1041 | ||
| 1009 | for (i = 0; i < NR_IRQS; i++) | 1042 | return 0; |
| 1010 | get_irq_desc(i)->status |= IRQ_NOREQUEST; | 1043 | } |
| 1044 | |||
| 1045 | int arch_init_chip_data(struct irq_desc *desc, int node) | ||
| 1046 | { | ||
| 1047 | desc->status |= IRQ_NOREQUEST; | ||
| 1048 | return 0; | ||
| 1011 | } | 1049 | } |
| 1012 | 1050 | ||
| 1013 | /* We need to create the radix trees late */ | 1051 | /* We need to create the radix trees late */ |
| @@ -1069,16 +1107,19 @@ static int virq_debug_show(struct seq_file *m, void *private) | |||
| 1069 | seq_printf(m, "%-5s %-7s %-15s %s\n", "virq", "hwirq", | 1107 | seq_printf(m, "%-5s %-7s %-15s %s\n", "virq", "hwirq", |
| 1070 | "chip name", "host name"); | 1108 | "chip name", "host name"); |
| 1071 | 1109 | ||
| 1072 | for (i = 1; i < NR_IRQS; i++) { | 1110 | for (i = 1; i < nr_irqs; i++) { |
| 1073 | desc = get_irq_desc(i); | 1111 | desc = irq_to_desc(i); |
| 1074 | spin_lock_irqsave(&desc->lock, flags); | 1112 | if (!desc) |
| 1113 | continue; | ||
| 1114 | |||
| 1115 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
| 1075 | 1116 | ||
| 1076 | if (desc->action && desc->action->handler) { | 1117 | if (desc->action && desc->action->handler) { |
| 1077 | seq_printf(m, "%5d ", i); | 1118 | seq_printf(m, "%5d ", i); |
| 1078 | seq_printf(m, "0x%05lx ", virq_to_hw(i)); | 1119 | seq_printf(m, "0x%05lx ", virq_to_hw(i)); |
| 1079 | 1120 | ||
| 1080 | if (desc->chip && desc->chip->typename) | 1121 | if (desc->chip && desc->chip->name) |
| 1081 | p = desc->chip->typename; | 1122 | p = desc->chip->name; |
| 1082 | else | 1123 | else |
| 1083 | p = none; | 1124 | p = none; |
| 1084 | seq_printf(m, "%-15s ", p); | 1125 | seq_printf(m, "%-15s ", p); |
| @@ -1090,7 +1131,7 @@ static int virq_debug_show(struct seq_file *m, void *private) | |||
| 1090 | seq_printf(m, "%s\n", p); | 1131 | seq_printf(m, "%s\n", p); |
| 1091 | } | 1132 | } |
| 1092 | 1133 | ||
| 1093 | spin_unlock_irqrestore(&desc->lock, flags); | 1134 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| 1094 | } | 1135 | } |
| 1095 | 1136 | ||
| 1096 | return 0; | 1137 | return 0; |
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index ed0ac4e4b8d8..79a00bb9c64c 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c | |||
| @@ -781,9 +781,9 @@ static int __init lparcfg_init(void) | |||
| 781 | !firmware_has_feature(FW_FEATURE_ISERIES)) | 781 | !firmware_has_feature(FW_FEATURE_ISERIES)) |
| 782 | mode |= S_IWUSR; | 782 | mode |= S_IWUSR; |
| 783 | 783 | ||
| 784 | ent = proc_create("ppc64/lparcfg", mode, NULL, &lparcfg_fops); | 784 | ent = proc_create("powerpc/lparcfg", mode, NULL, &lparcfg_fops); |
| 785 | if (!ent) { | 785 | if (!ent) { |
| 786 | printk(KERN_ERR "Failed to create ppc64/lparcfg\n"); | 786 | printk(KERN_ERR "Failed to create powerpc/lparcfg\n"); |
| 787 | return -EIO; | 787 | return -EIO; |
| 788 | } | 788 | } |
| 789 | 789 | ||
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index da9c0c4c10f3..8649f536f8df 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S | |||
| @@ -502,15 +502,7 @@ _GLOBAL(clear_pages) | |||
| 502 | li r0,PAGE_SIZE/L1_CACHE_BYTES | 502 | li r0,PAGE_SIZE/L1_CACHE_BYTES |
| 503 | slw r0,r0,r4 | 503 | slw r0,r0,r4 |
| 504 | mtctr r0 | 504 | mtctr r0 |
| 505 | #ifdef CONFIG_8xx | ||
| 506 | li r4, 0 | ||
| 507 | 1: stw r4, 0(r3) | ||
| 508 | stw r4, 4(r3) | ||
| 509 | stw r4, 8(r3) | ||
| 510 | stw r4, 12(r3) | ||
| 511 | #else | ||
| 512 | 1: dcbz 0,r3 | 505 | 1: dcbz 0,r3 |
| 513 | #endif | ||
| 514 | addi r3,r3,L1_CACHE_BYTES | 506 | addi r3,r3,L1_CACHE_BYTES |
| 515 | bdnz 1b | 507 | bdnz 1b |
| 516 | blr | 508 | blr |
| @@ -535,15 +527,6 @@ _GLOBAL(copy_page) | |||
| 535 | addi r3,r3,-4 | 527 | addi r3,r3,-4 |
| 536 | addi r4,r4,-4 | 528 | addi r4,r4,-4 |
| 537 | 529 | ||
| 538 | #ifdef CONFIG_8xx | ||
| 539 | /* don't use prefetch on 8xx */ | ||
| 540 | li r0,4096/L1_CACHE_BYTES | ||
| 541 | mtctr r0 | ||
| 542 | 1: COPY_16_BYTES | ||
| 543 | bdnz 1b | ||
| 544 | blr | ||
| 545 | |||
| 546 | #else /* not 8xx, we can prefetch */ | ||
| 547 | li r5,4 | 530 | li r5,4 |
| 548 | 531 | ||
| 549 | #if MAX_COPY_PREFETCH > 1 | 532 | #if MAX_COPY_PREFETCH > 1 |
| @@ -584,7 +567,6 @@ _GLOBAL(copy_page) | |||
| 584 | li r0,MAX_COPY_PREFETCH | 567 | li r0,MAX_COPY_PREFETCH |
| 585 | li r11,4 | 568 | li r11,4 |
| 586 | b 2b | 569 | b 2b |
| 587 | #endif /* CONFIG_8xx */ | ||
| 588 | 570 | ||
| 589 | /* | 571 | /* |
| 590 | * void atomic_clear_mask(atomic_t mask, atomic_t *addr) | 572 | * void atomic_clear_mask(atomic_t mask, atomic_t *addr) |
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index 0ed31f220482..ad461e735aec 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c | |||
| @@ -139,8 +139,8 @@ out: | |||
| 139 | 139 | ||
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | static int dev_nvram_ioctl(struct inode *inode, struct file *file, | 142 | static long dev_nvram_ioctl(struct file *file, unsigned int cmd, |
| 143 | unsigned int cmd, unsigned long arg) | 143 | unsigned long arg) |
| 144 | { | 144 | { |
| 145 | switch(cmd) { | 145 | switch(cmd) { |
| 146 | #ifdef CONFIG_PPC_PMAC | 146 | #ifdef CONFIG_PPC_PMAC |
| @@ -169,11 +169,11 @@ static int dev_nvram_ioctl(struct inode *inode, struct file *file, | |||
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | const struct file_operations nvram_fops = { | 171 | const struct file_operations nvram_fops = { |
| 172 | .owner = THIS_MODULE, | 172 | .owner = THIS_MODULE, |
| 173 | .llseek = dev_nvram_llseek, | 173 | .llseek = dev_nvram_llseek, |
| 174 | .read = dev_nvram_read, | 174 | .read = dev_nvram_read, |
| 175 | .write = dev_nvram_write, | 175 | .write = dev_nvram_write, |
| 176 | .ioctl = dev_nvram_ioctl, | 176 | .unlocked_ioctl = dev_nvram_ioctl, |
| 177 | }; | 177 | }; |
| 178 | 178 | ||
| 179 | static struct miscdevice nvram_dev = { | 179 | static struct miscdevice nvram_dev = { |
| @@ -184,7 +184,7 @@ static struct miscdevice nvram_dev = { | |||
| 184 | 184 | ||
| 185 | 185 | ||
| 186 | #ifdef DEBUG_NVRAM | 186 | #ifdef DEBUG_NVRAM |
| 187 | static void nvram_print_partitions(char * label) | 187 | static void __init nvram_print_partitions(char * label) |
| 188 | { | 188 | { |
| 189 | struct list_head * p; | 189 | struct list_head * p; |
| 190 | struct nvram_partition * tmp_part; | 190 | struct nvram_partition * tmp_part; |
| @@ -202,7 +202,7 @@ static void nvram_print_partitions(char * label) | |||
| 202 | #endif | 202 | #endif |
| 203 | 203 | ||
| 204 | 204 | ||
| 205 | static int nvram_write_header(struct nvram_partition * part) | 205 | static int __init nvram_write_header(struct nvram_partition * part) |
| 206 | { | 206 | { |
| 207 | loff_t tmp_index; | 207 | loff_t tmp_index; |
| 208 | int rc; | 208 | int rc; |
| @@ -214,7 +214,7 @@ static int nvram_write_header(struct nvram_partition * part) | |||
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | 216 | ||
| 217 | static unsigned char nvram_checksum(struct nvram_header *p) | 217 | static unsigned char __init nvram_checksum(struct nvram_header *p) |
| 218 | { | 218 | { |
| 219 | unsigned int c_sum, c_sum2; | 219 | unsigned int c_sum, c_sum2; |
| 220 | unsigned short *sp = (unsigned short *)p->name; /* assume 6 shorts */ | 220 | unsigned short *sp = (unsigned short *)p->name; /* assume 6 shorts */ |
| @@ -228,32 +228,7 @@ static unsigned char nvram_checksum(struct nvram_header *p) | |||
| 228 | return c_sum; | 228 | return c_sum; |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | 231 | static int __init nvram_remove_os_partition(void) | |
| 232 | /* | ||
| 233 | * Find an nvram partition, sig can be 0 for any | ||
| 234 | * partition or name can be NULL for any name, else | ||
| 235 | * tries to match both | ||
| 236 | */ | ||
| 237 | struct nvram_partition *nvram_find_partition(int sig, const char *name) | ||
| 238 | { | ||
| 239 | struct nvram_partition * part; | ||
| 240 | struct list_head * p; | ||
| 241 | |||
| 242 | list_for_each(p, &nvram_part->partition) { | ||
| 243 | part = list_entry(p, struct nvram_partition, partition); | ||
| 244 | |||
| 245 | if (sig && part->header.signature != sig) | ||
| 246 | continue; | ||
| 247 | if (name && 0 != strncmp(name, part->header.name, 12)) | ||
| 248 | continue; | ||
| 249 | return part; | ||
| 250 | } | ||
| 251 | return NULL; | ||
| 252 | } | ||
| 253 | EXPORT_SYMBOL(nvram_find_partition); | ||
| 254 | |||
| 255 | |||
| 256 | static int nvram_remove_os_partition(void) | ||
| 257 | { | 232 | { |
| 258 | struct list_head *i; | 233 | struct list_head *i; |
| 259 | struct list_head *j; | 234 | struct list_head *j; |
| @@ -319,7 +294,7 @@ static int nvram_remove_os_partition(void) | |||
| 319 | * Will create a partition starting at the first free | 294 | * Will create a partition starting at the first free |
| 320 | * space found if space has enough room. | 295 | * space found if space has enough room. |
| 321 | */ | 296 | */ |
| 322 | static int nvram_create_os_partition(void) | 297 | static int __init nvram_create_os_partition(void) |
| 323 | { | 298 | { |
| 324 | struct nvram_partition *part; | 299 | struct nvram_partition *part; |
| 325 | struct nvram_partition *new_part; | 300 | struct nvram_partition *new_part; |
| @@ -422,7 +397,7 @@ static int nvram_create_os_partition(void) | |||
| 422 | * 5.) If the max chunk cannot be allocated then try finding a chunk | 397 | * 5.) If the max chunk cannot be allocated then try finding a chunk |
| 423 | * that will satisfy the minum needed (NVRAM_MIN_REQ). | 398 | * that will satisfy the minum needed (NVRAM_MIN_REQ). |
| 424 | */ | 399 | */ |
| 425 | static int nvram_setup_partition(void) | 400 | static int __init nvram_setup_partition(void) |
| 426 | { | 401 | { |
| 427 | struct list_head * p; | 402 | struct list_head * p; |
| 428 | struct nvram_partition * part; | 403 | struct nvram_partition * part; |
| @@ -480,7 +455,7 @@ static int nvram_setup_partition(void) | |||
| 480 | } | 455 | } |
| 481 | 456 | ||
| 482 | 457 | ||
| 483 | static int nvram_scan_partitions(void) | 458 | static int __init nvram_scan_partitions(void) |
| 484 | { | 459 | { |
| 485 | loff_t cur_index = 0; | 460 | loff_t cur_index = 0; |
| 486 | struct nvram_header phead; | 461 | struct nvram_header phead; |
| @@ -706,6 +681,9 @@ int nvram_clear_error_log(void) | |||
| 706 | int clear_word = ERR_FLAG_ALREADY_LOGGED; | 681 | int clear_word = ERR_FLAG_ALREADY_LOGGED; |
| 707 | int rc; | 682 | int rc; |
| 708 | 683 | ||
| 684 | if (nvram_error_log_index == -1) | ||
| 685 | return -1; | ||
| 686 | |||
| 709 | tmp_index = nvram_error_log_index; | 687 | tmp_index = nvram_error_log_index; |
| 710 | 688 | ||
| 711 | rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index); | 689 | rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index); |
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index e8dfdbd9327a..cadbed679fbb 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
| @@ -1107,6 +1107,12 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus) | |||
| 1107 | list_for_each_entry(dev, &bus->devices, bus_list) { | 1107 | list_for_each_entry(dev, &bus->devices, bus_list) { |
| 1108 | struct dev_archdata *sd = &dev->dev.archdata; | 1108 | struct dev_archdata *sd = &dev->dev.archdata; |
| 1109 | 1109 | ||
| 1110 | /* Cardbus can call us to add new devices to a bus, so ignore | ||
| 1111 | * those who are already fully discovered | ||
| 1112 | */ | ||
| 1113 | if (dev->is_added) | ||
| 1114 | continue; | ||
| 1115 | |||
| 1110 | /* Setup OF node pointer in archdata */ | 1116 | /* Setup OF node pointer in archdata */ |
| 1111 | sd->of_node = pci_device_to_OF_node(dev); | 1117 | sd->of_node = pci_device_to_OF_node(dev); |
| 1112 | 1118 | ||
| @@ -1147,6 +1153,13 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) | |||
| 1147 | } | 1153 | } |
| 1148 | EXPORT_SYMBOL(pcibios_fixup_bus); | 1154 | EXPORT_SYMBOL(pcibios_fixup_bus); |
| 1149 | 1155 | ||
| 1156 | void __devinit pci_fixup_cardbus(struct pci_bus *bus) | ||
| 1157 | { | ||
| 1158 | /* Now fixup devices on that bus */ | ||
| 1159 | pcibios_setup_bus_devices(bus); | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | |||
| 1150 | static int skip_isa_ioresource_align(struct pci_dev *dev) | 1163 | static int skip_isa_ioresource_align(struct pci_dev *dev) |
| 1151 | { | 1164 | { |
| 1152 | if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) && | 1165 | if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) && |
diff --git a/arch/powerpc/kernel/perf_callchain.c b/arch/powerpc/kernel/perf_callchain.c index 0a03cf70d247..a3c11cac3d71 100644 --- a/arch/powerpc/kernel/perf_callchain.c +++ b/arch/powerpc/kernel/perf_callchain.c | |||
| @@ -119,13 +119,6 @@ static void perf_callchain_kernel(struct pt_regs *regs, | |||
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | #ifdef CONFIG_PPC64 | 121 | #ifdef CONFIG_PPC64 |
| 122 | |||
| 123 | #ifdef CONFIG_HUGETLB_PAGE | ||
| 124 | #define is_huge_psize(pagesize) (HPAGE_SHIFT && mmu_huge_psizes[pagesize]) | ||
| 125 | #else | ||
| 126 | #define is_huge_psize(pagesize) 0 | ||
| 127 | #endif | ||
| 128 | |||
| 129 | /* | 122 | /* |
| 130 | * On 64-bit we don't want to invoke hash_page on user addresses from | 123 | * On 64-bit we don't want to invoke hash_page on user addresses from |
| 131 | * interrupt context, so if the access faults, we read the page tables | 124 | * interrupt context, so if the access faults, we read the page tables |
| @@ -135,7 +128,7 @@ static int read_user_stack_slow(void __user *ptr, void *ret, int nb) | |||
| 135 | { | 128 | { |
| 136 | pgd_t *pgdir; | 129 | pgd_t *pgdir; |
| 137 | pte_t *ptep, pte; | 130 | pte_t *ptep, pte; |
| 138 | int pagesize; | 131 | unsigned shift; |
| 139 | unsigned long addr = (unsigned long) ptr; | 132 | unsigned long addr = (unsigned long) ptr; |
| 140 | unsigned long offset; | 133 | unsigned long offset; |
| 141 | unsigned long pfn; | 134 | unsigned long pfn; |
| @@ -145,17 +138,14 @@ static int read_user_stack_slow(void __user *ptr, void *ret, int nb) | |||
| 145 | if (!pgdir) | 138 | if (!pgdir) |
| 146 | return -EFAULT; | 139 | return -EFAULT; |
| 147 | 140 | ||
| 148 | pagesize = get_slice_psize(current->mm, addr); | 141 | ptep = find_linux_pte_or_hugepte(pgdir, addr, &shift); |
| 142 | if (!shift) | ||
| 143 | shift = PAGE_SHIFT; | ||
| 149 | 144 | ||
| 150 | /* align address to page boundary */ | 145 | /* align address to page boundary */ |
| 151 | offset = addr & ((1ul << mmu_psize_defs[pagesize].shift) - 1); | 146 | offset = addr & ((1UL << shift) - 1); |
| 152 | addr -= offset; | 147 | addr -= offset; |
| 153 | 148 | ||
| 154 | if (is_huge_psize(pagesize)) | ||
| 155 | ptep = huge_pte_offset(current->mm, addr); | ||
| 156 | else | ||
| 157 | ptep = find_linux_pte(pgdir, addr); | ||
| 158 | |||
| 159 | if (ptep == NULL) | 149 | if (ptep == NULL) |
| 160 | return -EFAULT; | 150 | return -EFAULT; |
| 161 | pte = *ptep; | 151 | pte = *ptep; |
| @@ -497,11 +487,11 @@ static void perf_callchain_user_32(struct pt_regs *regs, | |||
| 497 | * Since we can't get PMU interrupts inside a PMU interrupt handler, | 487 | * Since we can't get PMU interrupts inside a PMU interrupt handler, |
| 498 | * we don't need separate irq and nmi entries here. | 488 | * we don't need separate irq and nmi entries here. |
| 499 | */ | 489 | */ |
| 500 | static DEFINE_PER_CPU(struct perf_callchain_entry, callchain); | 490 | static DEFINE_PER_CPU(struct perf_callchain_entry, cpu_perf_callchain); |
| 501 | 491 | ||
| 502 | struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) | 492 | struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) |
| 503 | { | 493 | { |
| 504 | struct perf_callchain_entry *entry = &__get_cpu_var(callchain); | 494 | struct perf_callchain_entry *entry = &__get_cpu_var(cpu_perf_callchain); |
| 505 | 495 | ||
| 506 | entry->nr = 0; | 496 | entry->nr = 0; |
| 507 | 497 | ||
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index c8b27bb4dbde..425451453e96 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
| @@ -96,8 +96,6 @@ EXPORT_SYMBOL(copy_4K_page); | |||
| 96 | EXPORT_SYMBOL(isa_io_base); | 96 | EXPORT_SYMBOL(isa_io_base); |
| 97 | EXPORT_SYMBOL(isa_mem_base); | 97 | EXPORT_SYMBOL(isa_mem_base); |
| 98 | EXPORT_SYMBOL(pci_dram_offset); | 98 | EXPORT_SYMBOL(pci_dram_offset); |
| 99 | EXPORT_SYMBOL(pci_alloc_consistent); | ||
| 100 | EXPORT_SYMBOL(pci_free_consistent); | ||
| 101 | #endif /* CONFIG_PCI */ | 99 | #endif /* CONFIG_PCI */ |
| 102 | 100 | ||
| 103 | EXPORT_SYMBOL(start_thread); | 101 | EXPORT_SYMBOL(start_thread); |
| @@ -162,7 +160,6 @@ EXPORT_SYMBOL(screen_info); | |||
| 162 | 160 | ||
| 163 | #ifdef CONFIG_PPC32 | 161 | #ifdef CONFIG_PPC32 |
| 164 | EXPORT_SYMBOL(timer_interrupt); | 162 | EXPORT_SYMBOL(timer_interrupt); |
| 165 | EXPORT_SYMBOL(irq_desc); | ||
| 166 | EXPORT_SYMBOL(tb_ticks_per_jiffy); | 163 | EXPORT_SYMBOL(tb_ticks_per_jiffy); |
| 167 | EXPORT_SYMBOL(cacheable_memcpy); | 164 | EXPORT_SYMBOL(cacheable_memcpy); |
| 168 | EXPORT_SYMBOL(cacheable_memzero); | 165 | EXPORT_SYMBOL(cacheable_memzero); |
diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_powerpc.c index c647ddef40dc..1ed3b8d7981e 100644 --- a/arch/powerpc/kernel/proc_ppc64.c +++ b/arch/powerpc/kernel/proc_powerpc.c | |||
| @@ -28,55 +28,7 @@ | |||
| 28 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
| 29 | #include <asm/prom.h> | 29 | #include <asm/prom.h> |
| 30 | 30 | ||
| 31 | static loff_t page_map_seek( struct file *file, loff_t off, int whence); | 31 | #ifdef CONFIG_PPC64 |
| 32 | static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes, | ||
| 33 | loff_t *ppos); | ||
| 34 | static int page_map_mmap( struct file *file, struct vm_area_struct *vma ); | ||
| 35 | |||
| 36 | static const struct file_operations page_map_fops = { | ||
| 37 | .llseek = page_map_seek, | ||
| 38 | .read = page_map_read, | ||
| 39 | .mmap = page_map_mmap | ||
| 40 | }; | ||
| 41 | |||
| 42 | /* | ||
| 43 | * Create the ppc64 and ppc64/rtas directories early. This allows us to | ||
| 44 | * assume that they have been previously created in drivers. | ||
| 45 | */ | ||
| 46 | static int __init proc_ppc64_create(void) | ||
| 47 | { | ||
| 48 | struct proc_dir_entry *root; | ||
| 49 | |||
| 50 | root = proc_mkdir("ppc64", NULL); | ||
| 51 | if (!root) | ||
| 52 | return 1; | ||
| 53 | |||
| 54 | if (!of_find_node_by_path("/rtas")) | ||
| 55 | return 0; | ||
| 56 | |||
| 57 | if (!proc_mkdir("rtas", root)) | ||
| 58 | return 1; | ||
| 59 | |||
| 60 | if (!proc_symlink("rtas", NULL, "ppc64/rtas")) | ||
| 61 | return 1; | ||
| 62 | |||
| 63 | return 0; | ||
| 64 | } | ||
| 65 | core_initcall(proc_ppc64_create); | ||
| 66 | |||
| 67 | static int __init proc_ppc64_init(void) | ||
| 68 | { | ||
| 69 | struct proc_dir_entry *pde; | ||
| 70 | |||
| 71 | pde = proc_create_data("ppc64/systemcfg", S_IFREG|S_IRUGO, NULL, | ||
| 72 | &page_map_fops, vdso_data); | ||
| 73 | if (!pde) | ||
| 74 | return 1; | ||
| 75 | pde->size = PAGE_SIZE; | ||
| 76 | |||
| 77 | return 0; | ||
| 78 | } | ||
| 79 | __initcall(proc_ppc64_init); | ||
| 80 | 32 | ||
| 81 | static loff_t page_map_seek( struct file *file, loff_t off, int whence) | 33 | static loff_t page_map_seek( struct file *file, loff_t off, int whence) |
| 82 | { | 34 | { |
| @@ -120,3 +72,55 @@ static int page_map_mmap( struct file *file, struct vm_area_struct *vma ) | |||
| 120 | return 0; | 72 | return 0; |
| 121 | } | 73 | } |
| 122 | 74 | ||
| 75 | static const struct file_operations page_map_fops = { | ||
| 76 | .llseek = page_map_seek, | ||
| 77 | .read = page_map_read, | ||
| 78 | .mmap = page_map_mmap | ||
| 79 | }; | ||
| 80 | |||
| 81 | |||
| 82 | static int __init proc_ppc64_init(void) | ||
| 83 | { | ||
| 84 | struct proc_dir_entry *pde; | ||
| 85 | |||
| 86 | pde = proc_create_data("powerpc/systemcfg", S_IFREG|S_IRUGO, NULL, | ||
| 87 | &page_map_fops, vdso_data); | ||
| 88 | if (!pde) | ||
| 89 | return 1; | ||
| 90 | pde->size = PAGE_SIZE; | ||
| 91 | |||
| 92 | return 0; | ||
| 93 | } | ||
| 94 | __initcall(proc_ppc64_init); | ||
| 95 | |||
| 96 | #endif /* CONFIG_PPC64 */ | ||
| 97 | |||
| 98 | /* | ||
| 99 | * Create the ppc64 and ppc64/rtas directories early. This allows us to | ||
| 100 | * assume that they have been previously created in drivers. | ||
| 101 | */ | ||
| 102 | static int __init proc_ppc64_create(void) | ||
| 103 | { | ||
| 104 | struct proc_dir_entry *root; | ||
| 105 | |||
| 106 | root = proc_mkdir("powerpc", NULL); | ||
| 107 | if (!root) | ||
| 108 | return 1; | ||
| 109 | |||
| 110 | #ifdef CONFIG_PPC64 | ||
| 111 | if (!proc_symlink("ppc64", NULL, "powerpc")) | ||
| 112 | pr_err("Failed to create link /proc/ppc64 -> /proc/powerpc\n"); | ||
| 113 | #endif | ||
| 114 | |||
| 115 | if (!of_find_node_by_path("/rtas")) | ||
| 116 | return 0; | ||
| 117 | |||
| 118 | if (!proc_mkdir("rtas", root)) | ||
| 119 | return 1; | ||
| 120 | |||
| 121 | if (!proc_symlink("rtas", NULL, "powerpc/rtas")) | ||
| 122 | return 1; | ||
| 123 | |||
| 124 | return 0; | ||
| 125 | } | ||
| 126 | core_initcall(proc_ppc64_create); | ||
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index bf90361bb70f..fd0d29493fd6 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
| @@ -42,7 +42,7 @@ | |||
| 42 | #include <asm/mmu.h> | 42 | #include <asm/mmu.h> |
| 43 | 43 | ||
| 44 | struct rtas_t rtas = { | 44 | struct rtas_t rtas = { |
| 45 | .lock = __RAW_SPIN_LOCK_UNLOCKED | 45 | .lock = __ARCH_SPIN_LOCK_UNLOCKED |
| 46 | }; | 46 | }; |
| 47 | EXPORT_SYMBOL(rtas); | 47 | EXPORT_SYMBOL(rtas); |
| 48 | 48 | ||
| @@ -80,13 +80,13 @@ static unsigned long lock_rtas(void) | |||
| 80 | 80 | ||
| 81 | local_irq_save(flags); | 81 | local_irq_save(flags); |
| 82 | preempt_disable(); | 82 | preempt_disable(); |
| 83 | __raw_spin_lock_flags(&rtas.lock, flags); | 83 | arch_spin_lock_flags(&rtas.lock, flags); |
| 84 | return flags; | 84 | return flags; |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | static void unlock_rtas(unsigned long flags) | 87 | static void unlock_rtas(unsigned long flags) |
| 88 | { | 88 | { |
| 89 | __raw_spin_unlock(&rtas.lock); | 89 | arch_spin_unlock(&rtas.lock); |
| 90 | local_irq_restore(flags); | 90 | local_irq_restore(flags); |
| 91 | preempt_enable(); | 91 | preempt_enable(); |
| 92 | } | 92 | } |
| @@ -978,7 +978,7 @@ int __init early_init_dt_scan_rtas(unsigned long node, | |||
| 978 | return 1; | 978 | return 1; |
| 979 | } | 979 | } |
| 980 | 980 | ||
| 981 | static raw_spinlock_t timebase_lock; | 981 | static arch_spinlock_t timebase_lock; |
| 982 | static u64 timebase = 0; | 982 | static u64 timebase = 0; |
| 983 | 983 | ||
| 984 | void __cpuinit rtas_give_timebase(void) | 984 | void __cpuinit rtas_give_timebase(void) |
| @@ -987,10 +987,10 @@ void __cpuinit rtas_give_timebase(void) | |||
| 987 | 987 | ||
| 988 | local_irq_save(flags); | 988 | local_irq_save(flags); |
| 989 | hard_irq_disable(); | 989 | hard_irq_disable(); |
| 990 | __raw_spin_lock(&timebase_lock); | 990 | arch_spin_lock(&timebase_lock); |
| 991 | rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL); | 991 | rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL); |
| 992 | timebase = get_tb(); | 992 | timebase = get_tb(); |
| 993 | __raw_spin_unlock(&timebase_lock); | 993 | arch_spin_unlock(&timebase_lock); |
| 994 | 994 | ||
| 995 | while (timebase) | 995 | while (timebase) |
| 996 | barrier(); | 996 | barrier(); |
| @@ -1002,8 +1002,8 @@ void __cpuinit rtas_take_timebase(void) | |||
| 1002 | { | 1002 | { |
| 1003 | while (!timebase) | 1003 | while (!timebase) |
| 1004 | barrier(); | 1004 | barrier(); |
| 1005 | __raw_spin_lock(&timebase_lock); | 1005 | arch_spin_lock(&timebase_lock); |
| 1006 | set_tb(timebase >> 32, timebase & 0xffffffff); | 1006 | set_tb(timebase >> 32, timebase & 0xffffffff); |
| 1007 | timebase = 0; | 1007 | timebase = 0; |
| 1008 | __raw_spin_unlock(&timebase_lock); | 1008 | arch_spin_unlock(&timebase_lock); |
| 1009 | } | 1009 | } |
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index 13011a96a977..a85117d5c9a4 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * as published by the Free Software Foundation; either version | 6 | * as published by the Free Software Foundation; either version |
| 7 | * 2 of the License, or (at your option) any later version. | 7 | * 2 of the License, or (at your option) any later version. |
| 8 | * | 8 | * |
| 9 | * /proc/ppc64/rtas/firmware_flash interface | 9 | * /proc/powerpc/rtas/firmware_flash interface |
| 10 | * | 10 | * |
| 11 | * This file implements a firmware_flash interface to pump a firmware | 11 | * This file implements a firmware_flash interface to pump a firmware |
| 12 | * image into the kernel. At reboot time rtas_restart() will see the | 12 | * image into the kernel. At reboot time rtas_restart() will see the |
| @@ -740,7 +740,7 @@ static int __init rtas_flash_init(void) | |||
| 740 | return 1; | 740 | return 1; |
| 741 | } | 741 | } |
| 742 | 742 | ||
| 743 | firmware_flash_pde = create_flash_pde("ppc64/rtas/" | 743 | firmware_flash_pde = create_flash_pde("powerpc/rtas/" |
| 744 | FIRMWARE_FLASH_NAME, | 744 | FIRMWARE_FLASH_NAME, |
| 745 | &rtas_flash_operations); | 745 | &rtas_flash_operations); |
| 746 | if (firmware_flash_pde == NULL) { | 746 | if (firmware_flash_pde == NULL) { |
| @@ -754,7 +754,7 @@ static int __init rtas_flash_init(void) | |||
| 754 | if (rc != 0) | 754 | if (rc != 0) |
| 755 | goto cleanup; | 755 | goto cleanup; |
| 756 | 756 | ||
| 757 | firmware_update_pde = create_flash_pde("ppc64/rtas/" | 757 | firmware_update_pde = create_flash_pde("powerpc/rtas/" |
| 758 | FIRMWARE_UPDATE_NAME, | 758 | FIRMWARE_UPDATE_NAME, |
| 759 | &rtas_flash_operations); | 759 | &rtas_flash_operations); |
| 760 | if (firmware_update_pde == NULL) { | 760 | if (firmware_update_pde == NULL) { |
| @@ -768,7 +768,7 @@ static int __init rtas_flash_init(void) | |||
| 768 | if (rc != 0) | 768 | if (rc != 0) |
| 769 | goto cleanup; | 769 | goto cleanup; |
| 770 | 770 | ||
| 771 | validate_pde = create_flash_pde("ppc64/rtas/" VALIDATE_FLASH_NAME, | 771 | validate_pde = create_flash_pde("powerpc/rtas/" VALIDATE_FLASH_NAME, |
| 772 | &validate_flash_operations); | 772 | &validate_flash_operations); |
| 773 | if (validate_pde == NULL) { | 773 | if (validate_pde == NULL) { |
| 774 | rc = -ENOMEM; | 774 | rc = -ENOMEM; |
| @@ -781,7 +781,7 @@ static int __init rtas_flash_init(void) | |||
| 781 | if (rc != 0) | 781 | if (rc != 0) |
| 782 | goto cleanup; | 782 | goto cleanup; |
| 783 | 783 | ||
| 784 | manage_pde = create_flash_pde("ppc64/rtas/" MANAGE_FLASH_NAME, | 784 | manage_pde = create_flash_pde("powerpc/rtas/" MANAGE_FLASH_NAME, |
| 785 | &manage_flash_operations); | 785 | &manage_flash_operations); |
| 786 | if (manage_pde == NULL) { | 786 | if (manage_pde == NULL) { |
| 787 | rc = -ENOMEM; | 787 | rc = -ENOMEM; |
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/kernel/rtasd.c index b3cbac855924..2e4832ab2108 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/kernel/rtasd.c | |||
| @@ -39,6 +39,7 @@ static unsigned long rtas_log_start; | |||
| 39 | static unsigned long rtas_log_size; | 39 | static unsigned long rtas_log_size; |
| 40 | 40 | ||
| 41 | static int surveillance_timeout = -1; | 41 | static int surveillance_timeout = -1; |
| 42 | |||
| 42 | static unsigned int rtas_error_log_max; | 43 | static unsigned int rtas_error_log_max; |
| 43 | static unsigned int rtas_error_log_buffer_max; | 44 | static unsigned int rtas_error_log_buffer_max; |
| 44 | 45 | ||
| @@ -213,9 +214,11 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal) | |||
| 213 | return; | 214 | return; |
| 214 | } | 215 | } |
| 215 | 216 | ||
| 217 | #ifdef CONFIG_PPC64 | ||
| 216 | /* Write error to NVRAM */ | 218 | /* Write error to NVRAM */ |
| 217 | if (logging_enabled && !(err_type & ERR_FLAG_BOOT)) | 219 | if (logging_enabled && !(err_type & ERR_FLAG_BOOT)) |
| 218 | nvram_write_error_log(buf, len, err_type, error_log_cnt); | 220 | nvram_write_error_log(buf, len, err_type, error_log_cnt); |
| 221 | #endif /* CONFIG_PPC64 */ | ||
| 219 | 222 | ||
| 220 | /* | 223 | /* |
| 221 | * rtas errors can occur during boot, and we do want to capture | 224 | * rtas errors can occur during boot, and we do want to capture |
| @@ -264,7 +267,6 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal) | |||
| 264 | 267 | ||
| 265 | } | 268 | } |
| 266 | 269 | ||
| 267 | |||
| 268 | static int rtas_log_open(struct inode * inode, struct file * file) | 270 | static int rtas_log_open(struct inode * inode, struct file * file) |
| 269 | { | 271 | { |
| 270 | return 0; | 272 | return 0; |
| @@ -300,6 +302,7 @@ static ssize_t rtas_log_read(struct file * file, char __user * buf, | |||
| 300 | return -ENOMEM; | 302 | return -ENOMEM; |
| 301 | 303 | ||
| 302 | spin_lock_irqsave(&rtasd_log_lock, s); | 304 | spin_lock_irqsave(&rtasd_log_lock, s); |
| 305 | |||
| 303 | /* if it's 0, then we know we got the last one (the one in NVRAM) */ | 306 | /* if it's 0, then we know we got the last one (the one in NVRAM) */ |
| 304 | while (rtas_log_size == 0) { | 307 | while (rtas_log_size == 0) { |
| 305 | if (file->f_flags & O_NONBLOCK) { | 308 | if (file->f_flags & O_NONBLOCK) { |
| @@ -313,7 +316,9 @@ static ssize_t rtas_log_read(struct file * file, char __user * buf, | |||
| 313 | error = -ENODATA; | 316 | error = -ENODATA; |
| 314 | goto out; | 317 | goto out; |
| 315 | } | 318 | } |
| 319 | #ifdef CONFIG_PPC64 | ||
| 316 | nvram_clear_error_log(); | 320 | nvram_clear_error_log(); |
| 321 | #endif /* CONFIG_PPC64 */ | ||
| 317 | 322 | ||
| 318 | spin_unlock_irqrestore(&rtasd_log_lock, s); | 323 | spin_unlock_irqrestore(&rtasd_log_lock, s); |
| 319 | error = wait_event_interruptible(rtas_log_wait, rtas_log_size); | 324 | error = wait_event_interruptible(rtas_log_wait, rtas_log_size); |
| @@ -427,14 +432,11 @@ static void rtas_event_scan(struct work_struct *w) | |||
| 427 | put_online_cpus(); | 432 | put_online_cpus(); |
| 428 | } | 433 | } |
| 429 | 434 | ||
| 430 | static void start_event_scan(void) | 435 | #ifdef CONFIG_PPC64 |
| 436 | static void retreive_nvram_error_log(void) | ||
| 431 | { | 437 | { |
| 432 | unsigned int err_type; | 438 | unsigned int err_type ; |
| 433 | int rc; | 439 | int rc ; |
| 434 | |||
| 435 | printk(KERN_DEBUG "RTAS daemon started\n"); | ||
| 436 | pr_debug("rtasd: will sleep for %d milliseconds\n", | ||
| 437 | (30000 / rtas_event_scan_rate)); | ||
| 438 | 440 | ||
| 439 | /* See if we have any error stored in NVRAM */ | 441 | /* See if we have any error stored in NVRAM */ |
| 440 | memset(logdata, 0, rtas_error_log_max); | 442 | memset(logdata, 0, rtas_error_log_max); |
| @@ -442,12 +444,26 @@ static void start_event_scan(void) | |||
| 442 | &err_type, &error_log_cnt); | 444 | &err_type, &error_log_cnt); |
| 443 | /* We can use rtas_log_buf now */ | 445 | /* We can use rtas_log_buf now */ |
| 444 | logging_enabled = 1; | 446 | logging_enabled = 1; |
| 445 | |||
| 446 | if (!rc) { | 447 | if (!rc) { |
| 447 | if (err_type != ERR_FLAG_ALREADY_LOGGED) { | 448 | if (err_type != ERR_FLAG_ALREADY_LOGGED) { |
| 448 | pSeries_log_error(logdata, err_type | ERR_FLAG_BOOT, 0); | 449 | pSeries_log_error(logdata, err_type | ERR_FLAG_BOOT, 0); |
| 449 | } | 450 | } |
| 450 | } | 451 | } |
| 452 | } | ||
| 453 | #else /* CONFIG_PPC64 */ | ||
| 454 | static void retreive_nvram_error_log(void) | ||
| 455 | { | ||
| 456 | } | ||
| 457 | #endif /* CONFIG_PPC64 */ | ||
| 458 | |||
| 459 | static void start_event_scan(void) | ||
| 460 | { | ||
| 461 | printk(KERN_DEBUG "RTAS daemon started\n"); | ||
| 462 | pr_debug("rtasd: will sleep for %d milliseconds\n", | ||
| 463 | (30000 / rtas_event_scan_rate)); | ||
| 464 | |||
| 465 | /* Retreive errors from nvram if any */ | ||
| 466 | retreive_nvram_error_log(); | ||
| 451 | 467 | ||
| 452 | schedule_delayed_work_on(first_cpu(cpu_online_map), &event_scan_work, | 468 | schedule_delayed_work_on(first_cpu(cpu_online_map), &event_scan_work, |
| 453 | event_scan_delay); | 469 | event_scan_delay); |
| @@ -457,13 +473,13 @@ static int __init rtas_init(void) | |||
| 457 | { | 473 | { |
| 458 | struct proc_dir_entry *entry; | 474 | struct proc_dir_entry *entry; |
| 459 | 475 | ||
| 460 | if (!machine_is(pseries)) | 476 | if (!machine_is(pseries) && !machine_is(chrp)) |
| 461 | return 0; | 477 | return 0; |
| 462 | 478 | ||
| 463 | /* No RTAS */ | 479 | /* No RTAS */ |
| 464 | event_scan = rtas_token("event-scan"); | 480 | event_scan = rtas_token("event-scan"); |
| 465 | if (event_scan == RTAS_UNKNOWN_SERVICE) { | 481 | if (event_scan == RTAS_UNKNOWN_SERVICE) { |
| 466 | printk(KERN_DEBUG "rtasd: no event-scan on system\n"); | 482 | printk(KERN_INFO "rtasd: No event-scan on system\n"); |
| 467 | return -ENODEV; | 483 | return -ENODEV; |
| 468 | } | 484 | } |
| 469 | 485 | ||
| @@ -483,7 +499,7 @@ static int __init rtas_init(void) | |||
| 483 | return -ENOMEM; | 499 | return -ENOMEM; |
| 484 | } | 500 | } |
| 485 | 501 | ||
| 486 | entry = proc_create("ppc64/rtas/error_log", S_IRUSR, NULL, | 502 | entry = proc_create("powerpc/rtas/error_log", S_IRUSR, NULL, |
| 487 | &proc_rtas_log_operations); | 503 | &proc_rtas_log_operations); |
| 488 | if (!entry) | 504 | if (!entry) |
| 489 | printk(KERN_ERR "Failed to create error_log proc entry\n"); | 505 | printk(KERN_ERR "Failed to create error_log proc entry\n"); |
| @@ -492,11 +508,16 @@ static int __init rtas_init(void) | |||
| 492 | 508 | ||
| 493 | return 0; | 509 | return 0; |
| 494 | } | 510 | } |
| 511 | __initcall(rtas_init); | ||
| 495 | 512 | ||
| 496 | static int __init surveillance_setup(char *str) | 513 | static int __init surveillance_setup(char *str) |
| 497 | { | 514 | { |
| 498 | int i; | 515 | int i; |
| 499 | 516 | ||
| 517 | /* We only do surveillance on pseries */ | ||
| 518 | if (!machine_is(pseries)) | ||
| 519 | return 0; | ||
| 520 | |||
| 500 | if (get_option(&str,&i)) { | 521 | if (get_option(&str,&i)) { |
| 501 | if (i >= 0 && i <= 255) | 522 | if (i >= 0 && i <= 255) |
| 502 | surveillance_timeout = i; | 523 | surveillance_timeout = i; |
| @@ -504,6 +525,7 @@ static int __init surveillance_setup(char *str) | |||
| 504 | 525 | ||
| 505 | return 1; | 526 | return 1; |
| 506 | } | 527 | } |
| 528 | __setup("surveillance=", surveillance_setup); | ||
| 507 | 529 | ||
| 508 | static int __init rtasmsgs_setup(char *str) | 530 | static int __init rtasmsgs_setup(char *str) |
| 509 | { | 531 | { |
| @@ -514,6 +536,4 @@ static int __init rtasmsgs_setup(char *str) | |||
| 514 | 536 | ||
| 515 | return 1; | 537 | return 1; |
| 516 | } | 538 | } |
| 517 | __initcall(rtas_init); | ||
| 518 | __setup("surveillance=", surveillance_setup); | ||
| 519 | __setup("rtasmsgs=", rtasmsgs_setup); | 539 | __setup("rtasmsgs=", rtasmsgs_setup); |
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 845c72ab7357..03dd6a248198 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c | |||
| @@ -157,7 +157,7 @@ extern u32 cpu_temp_both(unsigned long cpu); | |||
| 157 | #endif /* CONFIG_TAU */ | 157 | #endif /* CONFIG_TAU */ |
| 158 | 158 | ||
| 159 | #ifdef CONFIG_SMP | 159 | #ifdef CONFIG_SMP |
| 160 | DEFINE_PER_CPU(unsigned int, pvr); | 160 | DEFINE_PER_CPU(unsigned int, cpu_pvr); |
| 161 | #endif | 161 | #endif |
| 162 | 162 | ||
| 163 | static int show_cpuinfo(struct seq_file *m, void *v) | 163 | static int show_cpuinfo(struct seq_file *m, void *v) |
| @@ -209,7 +209,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
| 209 | } | 209 | } |
| 210 | 210 | ||
| 211 | #ifdef CONFIG_SMP | 211 | #ifdef CONFIG_SMP |
| 212 | pvr = per_cpu(pvr, cpu_id); | 212 | pvr = per_cpu(cpu_pvr, cpu_id); |
| 213 | #else | 213 | #else |
| 214 | pvr = mfspr(SPRN_PVR); | 214 | pvr = mfspr(SPRN_PVR); |
| 215 | #endif | 215 | #endif |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index df2c9e932b37..6568406b2a30 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
| @@ -356,11 +356,6 @@ void __init setup_system(void) | |||
| 356 | */ | 356 | */ |
| 357 | initialize_cache_info(); | 357 | initialize_cache_info(); |
| 358 | 358 | ||
| 359 | /* | ||
| 360 | * Initialize irq remapping subsystem | ||
| 361 | */ | ||
| 362 | irq_early_init(); | ||
| 363 | |||
| 364 | #ifdef CONFIG_PPC_RTAS | 359 | #ifdef CONFIG_PPC_RTAS |
| 365 | /* | 360 | /* |
| 366 | * Initialize RTAS if available | 361 | * Initialize RTAS if available |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 9b86a74d2815..a521fb8a40ee 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
| @@ -218,6 +218,9 @@ void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *)) | |||
| 218 | 218 | ||
| 219 | static void stop_this_cpu(void *dummy) | 219 | static void stop_this_cpu(void *dummy) |
| 220 | { | 220 | { |
| 221 | /* Remove this CPU */ | ||
| 222 | set_cpu_online(smp_processor_id(), false); | ||
| 223 | |||
| 221 | local_irq_disable(); | 224 | local_irq_disable(); |
| 222 | while (1) | 225 | while (1) |
| 223 | ; | 226 | ; |
| @@ -232,7 +235,7 @@ struct thread_info *current_set[NR_CPUS]; | |||
| 232 | 235 | ||
| 233 | static void __devinit smp_store_cpu_info(int id) | 236 | static void __devinit smp_store_cpu_info(int id) |
| 234 | { | 237 | { |
| 235 | per_cpu(pvr, id) = mfspr(SPRN_PVR); | 238 | per_cpu(cpu_pvr, id) = mfspr(SPRN_PVR); |
| 236 | } | 239 | } |
| 237 | 240 | ||
| 238 | static void __init smp_create_idle(unsigned int cpu) | 241 | static void __init smp_create_idle(unsigned int cpu) |
diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c index c04832c4a02e..3370e62e43d4 100644 --- a/arch/powerpc/kernel/syscalls.c +++ b/arch/powerpc/kernel/syscalls.c | |||
| @@ -140,7 +140,6 @@ static inline unsigned long do_mmap2(unsigned long addr, size_t len, | |||
| 140 | unsigned long prot, unsigned long flags, | 140 | unsigned long prot, unsigned long flags, |
| 141 | unsigned long fd, unsigned long off, int shift) | 141 | unsigned long fd, unsigned long off, int shift) |
| 142 | { | 142 | { |
| 143 | struct file * file = NULL; | ||
| 144 | unsigned long ret = -EINVAL; | 143 | unsigned long ret = -EINVAL; |
| 145 | 144 | ||
| 146 | if (!arch_validate_prot(prot)) | 145 | if (!arch_validate_prot(prot)) |
| @@ -151,20 +150,8 @@ static inline unsigned long do_mmap2(unsigned long addr, size_t len, | |||
| 151 | goto out; | 150 | goto out; |
| 152 | off >>= shift; | 151 | off >>= shift; |
| 153 | } | 152 | } |
| 154 | |||
| 155 | ret = -EBADF; | ||
| 156 | if (!(flags & MAP_ANONYMOUS)) { | ||
| 157 | if (!(file = fget(fd))) | ||
| 158 | goto out; | ||
| 159 | } | ||
| 160 | |||
| 161 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
| 162 | 153 | ||
| 163 | down_write(¤t->mm->mmap_sem); | 154 | ret = sys_mmap_pgoff(addr, len, prot, flags, fd, off); |
| 164 | ret = do_mmap_pgoff(file, addr, len, prot, flags, off); | ||
| 165 | up_write(¤t->mm->mmap_sem); | ||
| 166 | if (file) | ||
| 167 | fput(file); | ||
| 168 | out: | 155 | out: |
| 169 | return ret; | 156 | return ret; |
| 170 | } | 157 | } |
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 956ab33fd73f..e235e52dc4fe 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c | |||
| @@ -461,6 +461,25 @@ static void unregister_cpu_online(unsigned int cpu) | |||
| 461 | 461 | ||
| 462 | cacheinfo_cpu_offline(cpu); | 462 | cacheinfo_cpu_offline(cpu); |
| 463 | } | 463 | } |
| 464 | |||
| 465 | #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE | ||
| 466 | ssize_t arch_cpu_probe(const char *buf, size_t count) | ||
| 467 | { | ||
| 468 | if (ppc_md.cpu_probe) | ||
| 469 | return ppc_md.cpu_probe(buf, count); | ||
| 470 | |||
| 471 | return -EINVAL; | ||
| 472 | } | ||
| 473 | |||
| 474 | ssize_t arch_cpu_release(const char *buf, size_t count) | ||
| 475 | { | ||
| 476 | if (ppc_md.cpu_release) | ||
| 477 | return ppc_md.cpu_release(buf, count); | ||
| 478 | |||
| 479 | return -EINVAL; | ||
| 480 | } | ||
| 481 | #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ | ||
| 482 | |||
| 464 | #endif /* CONFIG_HOTPLUG_CPU */ | 483 | #endif /* CONFIG_HOTPLUG_CPU */ |
| 465 | 484 | ||
| 466 | static int __cpuinit sysfs_cpu_notify(struct notifier_block *self, | 485 | static int __cpuinit sysfs_cpu_notify(struct notifier_block *self, |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 674800b242d6..9ba2cc88591d 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
| @@ -269,6 +269,7 @@ void account_system_vtime(struct task_struct *tsk) | |||
| 269 | per_cpu(cputime_scaled_last_delta, smp_processor_id()) = deltascaled; | 269 | per_cpu(cputime_scaled_last_delta, smp_processor_id()) = deltascaled; |
| 270 | local_irq_restore(flags); | 270 | local_irq_restore(flags); |
| 271 | } | 271 | } |
| 272 | EXPORT_SYMBOL_GPL(account_system_vtime); | ||
| 272 | 273 | ||
| 273 | /* | 274 | /* |
| 274 | * Transfer the user and system times accumulated in the paca | 275 | * Transfer the user and system times accumulated in the paca |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 9d1f9354d6ca..d069ff8a7e03 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
| @@ -174,6 +174,15 @@ int die(const char *str, struct pt_regs *regs, long err) | |||
| 174 | return 0; | 174 | return 0; |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | void user_single_step_siginfo(struct task_struct *tsk, | ||
| 178 | struct pt_regs *regs, siginfo_t *info) | ||
| 179 | { | ||
| 180 | memset(info, 0, sizeof(*info)); | ||
| 181 | info->si_signo = SIGTRAP; | ||
| 182 | info->si_code = TRAP_TRACE; | ||
| 183 | info->si_addr = (void __user *)regs->nip; | ||
| 184 | } | ||
| 185 | |||
| 177 | void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) | 186 | void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) |
| 178 | { | 187 | { |
| 179 | siginfo_t info; | 188 | siginfo_t info; |
| @@ -198,28 +207,6 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) | |||
| 198 | info.si_code = code; | 207 | info.si_code = code; |
| 199 | info.si_addr = (void __user *) addr; | 208 | info.si_addr = (void __user *) addr; |
| 200 | force_sig_info(signr, &info, current); | 209 | force_sig_info(signr, &info, current); |
| 201 | |||
| 202 | /* | ||
| 203 | * Init gets no signals that it doesn't have a handler for. | ||
| 204 | * That's all very well, but if it has caused a synchronous | ||
| 205 | * exception and we ignore the resulting signal, it will just | ||
| 206 | * generate the same exception over and over again and we get | ||
| 207 | * nowhere. Better to kill it and let the kernel panic. | ||
| 208 | */ | ||
| 209 | if (is_global_init(current)) { | ||
| 210 | __sighandler_t handler; | ||
| 211 | |||
| 212 | spin_lock_irq(¤t->sighand->siglock); | ||
| 213 | handler = current->sighand->action[signr-1].sa.sa_handler; | ||
| 214 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 215 | if (handler == SIG_DFL) { | ||
| 216 | /* init has generated a synchronous exception | ||
| 217 | and it doesn't have a handler for the signal */ | ||
| 218 | printk(KERN_CRIT "init has generated signal %d " | ||
| 219 | "but has no handler for it\n", signr); | ||
| 220 | do_exit(signr); | ||
| 221 | } | ||
| 222 | } | ||
| 223 | } | 210 | } |
| 224 | 211 | ||
| 225 | #ifdef CONFIG_PPC64 | 212 | #ifdef CONFIG_PPC64 |
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c index fc9af47e2128..e39cad83c884 100644 --- a/arch/powerpc/kernel/udbg.c +++ b/arch/powerpc/kernel/udbg.c | |||
| @@ -60,6 +60,8 @@ void __init udbg_early_init(void) | |||
| 60 | udbg_init_40x_realmode(); | 60 | udbg_init_40x_realmode(); |
| 61 | #elif defined(CONFIG_PPC_EARLY_DEBUG_CPM) | 61 | #elif defined(CONFIG_PPC_EARLY_DEBUG_CPM) |
| 62 | udbg_init_cpm(); | 62 | udbg_init_cpm(); |
| 63 | #elif defined(CONFIG_PPC_EARLY_DEBUG_USBGECKO) | ||
| 64 | udbg_init_usbgecko(); | ||
| 63 | #endif | 65 | #endif |
| 64 | 66 | ||
| 65 | #ifdef CONFIG_PPC_EARLY_DEBUG | 67 | #ifdef CONFIG_PPC_EARLY_DEBUG |
diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S index 67b6916f0e94..fe460482fa68 100644 --- a/arch/powerpc/kernel/vector.S +++ b/arch/powerpc/kernel/vector.S | |||
| @@ -58,7 +58,7 @@ _GLOBAL(load_up_altivec) | |||
| 58 | * all 1's | 58 | * all 1's |
| 59 | */ | 59 | */ |
| 60 | mfspr r4,SPRN_VRSAVE | 60 | mfspr r4,SPRN_VRSAVE |
| 61 | cmpdi 0,r4,0 | 61 | cmpwi 0,r4,0 |
| 62 | bne+ 1f | 62 | bne+ 1f |
| 63 | li r4,-1 | 63 | li r4,-1 |
| 64 | mtspr SPRN_VRSAVE,r4 | 64 | mtspr SPRN_VRSAVE,r4 |
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 27735a7ac12b..dcd01c82e701 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S | |||
| @@ -38,6 +38,9 @@ jiffies = jiffies_64 + 4; | |||
| 38 | #endif | 38 | #endif |
| 39 | SECTIONS | 39 | SECTIONS |
| 40 | { | 40 | { |
| 41 | . = 0; | ||
| 42 | reloc_start = .; | ||
| 43 | |||
| 41 | . = KERNELBASE; | 44 | . = KERNELBASE; |
| 42 | 45 | ||
| 43 | /* | 46 | /* |
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig index c29926846613..07703f72330e 100644 --- a/arch/powerpc/kvm/Kconfig +++ b/arch/powerpc/kvm/Kconfig | |||
| @@ -21,6 +21,23 @@ config KVM | |||
| 21 | select PREEMPT_NOTIFIERS | 21 | select PREEMPT_NOTIFIERS |
| 22 | select ANON_INODES | 22 | select ANON_INODES |
| 23 | 23 | ||
| 24 | config KVM_BOOK3S_64_HANDLER | ||
| 25 | bool | ||
| 26 | |||
| 27 | config KVM_BOOK3S_64 | ||
| 28 | tristate "KVM support for PowerPC book3s_64 processors" | ||
| 29 | depends on EXPERIMENTAL && PPC64 | ||
| 30 | select KVM | ||
| 31 | select KVM_BOOK3S_64_HANDLER | ||
| 32 | ---help--- | ||
| 33 | Support running unmodified book3s_64 and book3s_32 guest kernels | ||
| 34 | in virtual machines on book3s_64 host processors. | ||
| 35 | |||
| 36 | This module provides access to the hardware capabilities through | ||
| 37 | a character device node named /dev/kvm. | ||
| 38 | |||
| 39 | If unsure, say N. | ||
| 40 | |||
| 24 | config KVM_440 | 41 | config KVM_440 |
| 25 | bool "KVM support for PowerPC 440 processors" | 42 | bool "KVM support for PowerPC 440 processors" |
| 26 | depends on EXPERIMENTAL && 44x | 43 | depends on EXPERIMENTAL && 44x |
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile index 37655fe19f2f..56484d652377 100644 --- a/arch/powerpc/kvm/Makefile +++ b/arch/powerpc/kvm/Makefile | |||
| @@ -12,26 +12,45 @@ CFLAGS_44x_tlb.o := -I. | |||
| 12 | CFLAGS_e500_tlb.o := -I. | 12 | CFLAGS_e500_tlb.o := -I. |
| 13 | CFLAGS_emulate.o := -I. | 13 | CFLAGS_emulate.o := -I. |
| 14 | 14 | ||
| 15 | kvm-objs := $(common-objs-y) powerpc.o emulate.o | 15 | common-objs-y += powerpc.o emulate.o |
| 16 | obj-$(CONFIG_KVM_EXIT_TIMING) += timing.o | 16 | obj-$(CONFIG_KVM_EXIT_TIMING) += timing.o |
| 17 | obj-$(CONFIG_KVM) += kvm.o | 17 | obj-$(CONFIG_KVM_BOOK3S_64_HANDLER) += book3s_64_exports.o |
| 18 | 18 | ||
| 19 | AFLAGS_booke_interrupts.o := -I$(obj) | 19 | AFLAGS_booke_interrupts.o := -I$(obj) |
| 20 | 20 | ||
| 21 | kvm-440-objs := \ | 21 | kvm-440-objs := \ |
| 22 | $(common-objs-y) \ | ||
| 22 | booke.o \ | 23 | booke.o \ |
| 23 | booke_emulate.o \ | 24 | booke_emulate.o \ |
| 24 | booke_interrupts.o \ | 25 | booke_interrupts.o \ |
| 25 | 44x.o \ | 26 | 44x.o \ |
| 26 | 44x_tlb.o \ | 27 | 44x_tlb.o \ |
| 27 | 44x_emulate.o | 28 | 44x_emulate.o |
| 28 | obj-$(CONFIG_KVM_440) += kvm-440.o | 29 | kvm-objs-$(CONFIG_KVM_440) := $(kvm-440-objs) |
| 29 | 30 | ||
| 30 | kvm-e500-objs := \ | 31 | kvm-e500-objs := \ |
| 32 | $(common-objs-y) \ | ||
| 31 | booke.o \ | 33 | booke.o \ |
| 32 | booke_emulate.o \ | 34 | booke_emulate.o \ |
| 33 | booke_interrupts.o \ | 35 | booke_interrupts.o \ |
| 34 | e500.o \ | 36 | e500.o \ |
| 35 | e500_tlb.o \ | 37 | e500_tlb.o \ |
| 36 | e500_emulate.o | 38 | e500_emulate.o |
| 37 | obj-$(CONFIG_KVM_E500) += kvm-e500.o | 39 | kvm-objs-$(CONFIG_KVM_E500) := $(kvm-e500-objs) |
| 40 | |||
| 41 | kvm-book3s_64-objs := \ | ||
| 42 | $(common-objs-y) \ | ||
| 43 | book3s.o \ | ||
| 44 | book3s_64_emulate.o \ | ||
| 45 | book3s_64_interrupts.o \ | ||
| 46 | book3s_64_mmu_host.o \ | ||
| 47 | book3s_64_mmu.o \ | ||
| 48 | book3s_32_mmu.o | ||
| 49 | kvm-objs-$(CONFIG_KVM_BOOK3S_64) := $(kvm-book3s_64-objs) | ||
| 50 | |||
| 51 | kvm-objs := $(kvm-objs-m) $(kvm-objs-y) | ||
| 52 | |||
| 53 | obj-$(CONFIG_KVM_440) += kvm.o | ||
| 54 | obj-$(CONFIG_KVM_E500) += kvm.o | ||
| 55 | obj-$(CONFIG_KVM_BOOK3S_64) += kvm.o | ||
| 56 | |||
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c new file mode 100644 index 000000000000..3e294bd9b8c6 --- /dev/null +++ b/arch/powerpc/kvm/book3s.c | |||
| @@ -0,0 +1,974 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2009. SUSE Linux Products GmbH. All rights reserved. | ||
| 3 | * | ||
| 4 | * Authors: | ||
| 5 | * Alexander Graf <agraf@suse.de> | ||
| 6 | * Kevin Wolf <mail@kevin-wolf.de> | ||
| 7 | * | ||
| 8 | * Description: | ||
| 9 | * This file is derived from arch/powerpc/kvm/44x.c, | ||
| 10 | * by Hollis Blanchard <hollisb@us.ibm.com>. | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify | ||
| 13 | * it under the terms of the GNU General Public License, version 2, as | ||
| 14 | * published by the Free Software Foundation. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/kvm_host.h> | ||
| 18 | #include <linux/err.h> | ||
| 19 | |||
| 20 | #include <asm/reg.h> | ||
| 21 | #include <asm/cputable.h> | ||
| 22 | #include <asm/cacheflush.h> | ||
| 23 | #include <asm/tlbflush.h> | ||
| 24 | #include <asm/uaccess.h> | ||
| 25 | #include <asm/io.h> | ||
| 26 | #include <asm/kvm_ppc.h> | ||
| 27 | #include <asm/kvm_book3s.h> | ||
| 28 | #include <asm/mmu_context.h> | ||
| 29 | #include <linux/sched.h> | ||
| 30 | #include <linux/vmalloc.h> | ||
| 31 | |||
| 32 | #define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU | ||
| 33 | |||
| 34 | /* #define EXIT_DEBUG */ | ||
| 35 | /* #define EXIT_DEBUG_SIMPLE */ | ||
| 36 | |||
| 37 | /* Without AGGRESSIVE_DEC we only fire off a DEC interrupt when DEC turns 0. | ||
| 38 | * When set, we retrigger a DEC interrupt after that if DEC <= 0. | ||
| 39 | * PPC32 Linux runs faster without AGGRESSIVE_DEC, PPC64 Linux requires it. */ | ||
| 40 | |||
| 41 | /* #define AGGRESSIVE_DEC */ | ||
| 42 | |||
| 43 | struct kvm_stats_debugfs_item debugfs_entries[] = { | ||
| 44 | { "exits", VCPU_STAT(sum_exits) }, | ||
| 45 | { "mmio", VCPU_STAT(mmio_exits) }, | ||
| 46 | { "sig", VCPU_STAT(signal_exits) }, | ||
| 47 | { "sysc", VCPU_STAT(syscall_exits) }, | ||
| 48 | { "inst_emu", VCPU_STAT(emulated_inst_exits) }, | ||
| 49 | { "dec", VCPU_STAT(dec_exits) }, | ||
| 50 | { "ext_intr", VCPU_STAT(ext_intr_exits) }, | ||
| 51 | { "queue_intr", VCPU_STAT(queue_intr) }, | ||
| 52 | { "halt_wakeup", VCPU_STAT(halt_wakeup) }, | ||
| 53 | { "pf_storage", VCPU_STAT(pf_storage) }, | ||
| 54 | { "sp_storage", VCPU_STAT(sp_storage) }, | ||
| 55 | { "pf_instruc", VCPU_STAT(pf_instruc) }, | ||
| 56 | { "sp_instruc", VCPU_STAT(sp_instruc) }, | ||
| 57 | { "ld", VCPU_STAT(ld) }, | ||
| 58 | { "ld_slow", VCPU_STAT(ld_slow) }, | ||
| 59 | { "st", VCPU_STAT(st) }, | ||
| 60 | { "st_slow", VCPU_STAT(st_slow) }, | ||
| 61 | { NULL } | ||
| 62 | }; | ||
| 63 | |||
| 64 | void kvmppc_core_load_host_debugstate(struct kvm_vcpu *vcpu) | ||
| 65 | { | ||
| 66 | } | ||
| 67 | |||
| 68 | void kvmppc_core_load_guest_debugstate(struct kvm_vcpu *vcpu) | ||
| 69 | { | ||
| 70 | } | ||
| 71 | |||
| 72 | void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | ||
| 73 | { | ||
| 74 | memcpy(get_paca()->kvm_slb, to_book3s(vcpu)->slb_shadow, sizeof(get_paca()->kvm_slb)); | ||
| 75 | get_paca()->kvm_slb_max = to_book3s(vcpu)->slb_shadow_max; | ||
| 76 | } | ||
| 77 | |||
| 78 | void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) | ||
| 79 | { | ||
| 80 | memcpy(to_book3s(vcpu)->slb_shadow, get_paca()->kvm_slb, sizeof(get_paca()->kvm_slb)); | ||
| 81 | to_book3s(vcpu)->slb_shadow_max = get_paca()->kvm_slb_max; | ||
| 82 | } | ||
| 83 | |||
| 84 | #if defined(AGGRESSIVE_DEC) || defined(EXIT_DEBUG) | ||
| 85 | static u32 kvmppc_get_dec(struct kvm_vcpu *vcpu) | ||
| 86 | { | ||
| 87 | u64 jd = mftb() - vcpu->arch.dec_jiffies; | ||
| 88 | return vcpu->arch.dec - jd; | ||
| 89 | } | ||
| 90 | #endif | ||
| 91 | |||
| 92 | void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr) | ||
| 93 | { | ||
| 94 | ulong old_msr = vcpu->arch.msr; | ||
| 95 | |||
| 96 | #ifdef EXIT_DEBUG | ||
| 97 | printk(KERN_INFO "KVM: Set MSR to 0x%llx\n", msr); | ||
| 98 | #endif | ||
| 99 | msr &= to_book3s(vcpu)->msr_mask; | ||
| 100 | vcpu->arch.msr = msr; | ||
| 101 | vcpu->arch.shadow_msr = msr | MSR_USER32; | ||
| 102 | vcpu->arch.shadow_msr &= ( MSR_VEC | MSR_VSX | MSR_FP | MSR_FE0 | | ||
| 103 | MSR_USER64 | MSR_SE | MSR_BE | MSR_DE | | ||
| 104 | MSR_FE1); | ||
| 105 | |||
| 106 | if (msr & (MSR_WE|MSR_POW)) { | ||
| 107 | if (!vcpu->arch.pending_exceptions) { | ||
| 108 | kvm_vcpu_block(vcpu); | ||
| 109 | vcpu->stat.halt_wakeup++; | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 113 | if (((vcpu->arch.msr & (MSR_IR|MSR_DR)) != (old_msr & (MSR_IR|MSR_DR))) || | ||
| 114 | (vcpu->arch.msr & MSR_PR) != (old_msr & MSR_PR)) { | ||
| 115 | kvmppc_mmu_flush_segments(vcpu); | ||
| 116 | kvmppc_mmu_map_segment(vcpu, vcpu->arch.pc); | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags) | ||
| 121 | { | ||
| 122 | vcpu->arch.srr0 = vcpu->arch.pc; | ||
| 123 | vcpu->arch.srr1 = vcpu->arch.msr | flags; | ||
| 124 | vcpu->arch.pc = to_book3s(vcpu)->hior + vec; | ||
| 125 | vcpu->arch.mmu.reset_msr(vcpu); | ||
| 126 | } | ||
| 127 | |||
| 128 | void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec) | ||
| 129 | { | ||
| 130 | unsigned int prio; | ||
| 131 | |||
| 132 | vcpu->stat.queue_intr++; | ||
| 133 | switch (vec) { | ||
| 134 | case 0x100: prio = BOOK3S_IRQPRIO_SYSTEM_RESET; break; | ||
| 135 | case 0x200: prio = BOOK3S_IRQPRIO_MACHINE_CHECK; break; | ||
| 136 | case 0x300: prio = BOOK3S_IRQPRIO_DATA_STORAGE; break; | ||
| 137 | case 0x380: prio = BOOK3S_IRQPRIO_DATA_SEGMENT; break; | ||
| 138 | case 0x400: prio = BOOK3S_IRQPRIO_INST_STORAGE; break; | ||
| 139 | case 0x480: prio = BOOK3S_IRQPRIO_INST_SEGMENT; break; | ||
| 140 | case 0x500: prio = BOOK3S_IRQPRIO_EXTERNAL; break; | ||
| 141 | case 0x600: prio = BOOK3S_IRQPRIO_ALIGNMENT; break; | ||
| 142 | case 0x700: prio = BOOK3S_IRQPRIO_PROGRAM; break; | ||
| 143 | case 0x800: prio = BOOK3S_IRQPRIO_FP_UNAVAIL; break; | ||
| 144 | case 0x900: prio = BOOK3S_IRQPRIO_DECREMENTER; break; | ||
| 145 | case 0xc00: prio = BOOK3S_IRQPRIO_SYSCALL; break; | ||
| 146 | case 0xd00: prio = BOOK3S_IRQPRIO_DEBUG; break; | ||
| 147 | case 0xf20: prio = BOOK3S_IRQPRIO_ALTIVEC; break; | ||
| 148 | case 0xf40: prio = BOOK3S_IRQPRIO_VSX; break; | ||
| 149 | default: prio = BOOK3S_IRQPRIO_MAX; break; | ||
| 150 | } | ||
| 151 | |||
| 152 | set_bit(prio, &vcpu->arch.pending_exceptions); | ||
| 153 | #ifdef EXIT_DEBUG | ||
| 154 | printk(KERN_INFO "Queueing interrupt %x\n", vec); | ||
| 155 | #endif | ||
| 156 | } | ||
| 157 | |||
| 158 | |||
| 159 | void kvmppc_core_queue_program(struct kvm_vcpu *vcpu) | ||
| 160 | { | ||
| 161 | kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_PROGRAM); | ||
| 162 | } | ||
| 163 | |||
| 164 | void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu) | ||
| 165 | { | ||
| 166 | kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_DECREMENTER); | ||
| 167 | } | ||
| 168 | |||
| 169 | int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu) | ||
| 170 | { | ||
| 171 | return test_bit(BOOK3S_INTERRUPT_DECREMENTER >> 7, &vcpu->arch.pending_exceptions); | ||
| 172 | } | ||
| 173 | |||
| 174 | void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, | ||
| 175 | struct kvm_interrupt *irq) | ||
| 176 | { | ||
| 177 | kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL); | ||
| 178 | } | ||
| 179 | |||
| 180 | int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority) | ||
| 181 | { | ||
| 182 | int deliver = 1; | ||
| 183 | int vec = 0; | ||
| 184 | |||
| 185 | switch (priority) { | ||
| 186 | case BOOK3S_IRQPRIO_DECREMENTER: | ||
| 187 | deliver = vcpu->arch.msr & MSR_EE; | ||
| 188 | vec = BOOK3S_INTERRUPT_DECREMENTER; | ||
| 189 | break; | ||
| 190 | case BOOK3S_IRQPRIO_EXTERNAL: | ||
| 191 | deliver = vcpu->arch.msr & MSR_EE; | ||
| 192 | vec = BOOK3S_INTERRUPT_EXTERNAL; | ||
| 193 | break; | ||
| 194 | case BOOK3S_IRQPRIO_SYSTEM_RESET: | ||
| 195 | vec = BOOK3S_INTERRUPT_SYSTEM_RESET; | ||
| 196 | break; | ||
| 197 | case BOOK3S_IRQPRIO_MACHINE_CHECK: | ||
| 198 | vec = BOOK3S_INTERRUPT_MACHINE_CHECK; | ||
| 199 | break; | ||
| 200 | case BOOK3S_IRQPRIO_DATA_STORAGE: | ||
| 201 | vec = BOOK3S_INTERRUPT_DATA_STORAGE; | ||
| 202 | break; | ||
| 203 | case BOOK3S_IRQPRIO_INST_STORAGE: | ||
| 204 | vec = BOOK3S_INTERRUPT_INST_STORAGE; | ||
| 205 | break; | ||
| 206 | case BOOK3S_IRQPRIO_DATA_SEGMENT: | ||
| 207 | vec = BOOK3S_INTERRUPT_DATA_SEGMENT; | ||
| 208 | break; | ||
| 209 | case BOOK3S_IRQPRIO_INST_SEGMENT: | ||
| 210 | vec = BOOK3S_INTERRUPT_INST_SEGMENT; | ||
| 211 | break; | ||
| 212 | case BOOK3S_IRQPRIO_ALIGNMENT: | ||
| 213 | vec = BOOK3S_INTERRUPT_ALIGNMENT; | ||
| 214 | break; | ||
| 215 | case BOOK3S_IRQPRIO_PROGRAM: | ||
| 216 | vec = BOOK3S_INTERRUPT_PROGRAM; | ||
| 217 | break; | ||
| 218 | case BOOK3S_IRQPRIO_VSX: | ||
| 219 | vec = BOOK3S_INTERRUPT_VSX; | ||
| 220 | break; | ||
| 221 | case BOOK3S_IRQPRIO_ALTIVEC: | ||
| 222 | vec = BOOK3S_INTERRUPT_ALTIVEC; | ||
| 223 | break; | ||
| 224 | case BOOK3S_IRQPRIO_FP_UNAVAIL: | ||
| 225 | vec = BOOK3S_INTERRUPT_FP_UNAVAIL; | ||
| 226 | break; | ||
| 227 | case BOOK3S_IRQPRIO_SYSCALL: | ||
| 228 | vec = BOOK3S_INTERRUPT_SYSCALL; | ||
| 229 | break; | ||
| 230 | case BOOK3S_IRQPRIO_DEBUG: | ||
| 231 | vec = BOOK3S_INTERRUPT_TRACE; | ||
| 232 | break; | ||
| 233 | case BOOK3S_IRQPRIO_PERFORMANCE_MONITOR: | ||
| 234 | vec = BOOK3S_INTERRUPT_PERFMON; | ||
| 235 | break; | ||
| 236 | default: | ||
| 237 | deliver = 0; | ||
| 238 | printk(KERN_ERR "KVM: Unknown interrupt: 0x%x\n", priority); | ||
| 239 | break; | ||
| 240 | } | ||
| 241 | |||
| 242 | #if 0 | ||
| 243 | printk(KERN_INFO "Deliver interrupt 0x%x? %x\n", vec, deliver); | ||
| 244 | #endif | ||
| 245 | |||
| 246 | if (deliver) | ||
| 247 | kvmppc_inject_interrupt(vcpu, vec, 0ULL); | ||
| 248 | |||
| 249 | return deliver; | ||
| 250 | } | ||
| 251 | |||
| 252 | void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) | ||
| 253 | { | ||
| 254 | unsigned long *pending = &vcpu->arch.pending_exceptions; | ||
| 255 | unsigned int priority; | ||
| 256 | |||
| 257 | /* XXX be more clever here - no need to mftb() on every entry */ | ||
| 258 | /* Issue DEC again if it's still active */ | ||
| 259 | #ifdef AGGRESSIVE_DEC | ||
| 260 | if (vcpu->arch.msr & MSR_EE) | ||
| 261 | if (kvmppc_get_dec(vcpu) & 0x80000000) | ||
| 262 | kvmppc_core_queue_dec(vcpu); | ||
| 263 | #endif | ||
| 264 | |||
| 265 | #ifdef EXIT_DEBUG | ||
| 266 | if (vcpu->arch.pending_exceptions) | ||
| 267 | printk(KERN_EMERG "KVM: Check pending: %lx\n", vcpu->arch.pending_exceptions); | ||
| 268 | #endif | ||
| 269 | priority = __ffs(*pending); | ||
| 270 | while (priority <= (sizeof(unsigned int) * 8)) { | ||
| 271 | if (kvmppc_book3s_irqprio_deliver(vcpu, priority)) { | ||
| 272 | clear_bit(priority, &vcpu->arch.pending_exceptions); | ||
| 273 | break; | ||
| 274 | } | ||
| 275 | |||
| 276 | priority = find_next_bit(pending, | ||
| 277 | BITS_PER_BYTE * sizeof(*pending), | ||
| 278 | priority + 1); | ||
| 279 | } | ||
| 280 | } | ||
| 281 | |||
| 282 | void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr) | ||
| 283 | { | ||
| 284 | vcpu->arch.hflags &= ~BOOK3S_HFLAG_SLB; | ||
| 285 | vcpu->arch.pvr = pvr; | ||
| 286 | if ((pvr >= 0x330000) && (pvr < 0x70330000)) { | ||
| 287 | kvmppc_mmu_book3s_64_init(vcpu); | ||
| 288 | to_book3s(vcpu)->hior = 0xfff00000; | ||
| 289 | to_book3s(vcpu)->msr_mask = 0xffffffffffffffffULL; | ||
| 290 | } else { | ||
| 291 | kvmppc_mmu_book3s_32_init(vcpu); | ||
| 292 | to_book3s(vcpu)->hior = 0; | ||
| 293 | to_book3s(vcpu)->msr_mask = 0xffffffffULL; | ||
| 294 | } | ||
| 295 | |||
| 296 | /* If we are in hypervisor level on 970, we can tell the CPU to | ||
| 297 | * treat DCBZ as 32 bytes store */ | ||
| 298 | vcpu->arch.hflags &= ~BOOK3S_HFLAG_DCBZ32; | ||
| 299 | if (vcpu->arch.mmu.is_dcbz32(vcpu) && (mfmsr() & MSR_HV) && | ||
| 300 | !strcmp(cur_cpu_spec->platform, "ppc970")) | ||
| 301 | vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32; | ||
| 302 | |||
| 303 | } | ||
| 304 | |||
| 305 | /* Book3s_32 CPUs always have 32 bytes cache line size, which Linux assumes. To | ||
| 306 | * make Book3s_32 Linux work on Book3s_64, we have to make sure we trap dcbz to | ||
| 307 | * emulate 32 bytes dcbz length. | ||
| 308 | * | ||
| 309 | * The Book3s_64 inventors also realized this case and implemented a special bit | ||
| 310 | * in the HID5 register, which is a hypervisor ressource. Thus we can't use it. | ||
| 311 | * | ||
| 312 | * My approach here is to patch the dcbz instruction on executing pages. | ||
| 313 | */ | ||
| 314 | static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte) | ||
| 315 | { | ||
| 316 | bool touched = false; | ||
| 317 | hva_t hpage; | ||
| 318 | u32 *page; | ||
| 319 | int i; | ||
| 320 | |||
| 321 | hpage = gfn_to_hva(vcpu->kvm, pte->raddr >> PAGE_SHIFT); | ||
| 322 | if (kvm_is_error_hva(hpage)) | ||
| 323 | return; | ||
| 324 | |||
| 325 | hpage |= pte->raddr & ~PAGE_MASK; | ||
| 326 | hpage &= ~0xFFFULL; | ||
| 327 | |||
| 328 | page = vmalloc(HW_PAGE_SIZE); | ||
| 329 | |||
| 330 | if (copy_from_user(page, (void __user *)hpage, HW_PAGE_SIZE)) | ||
| 331 | goto out; | ||
| 332 | |||
| 333 | for (i=0; i < HW_PAGE_SIZE / 4; i++) | ||
| 334 | if ((page[i] & 0xff0007ff) == INS_DCBZ) { | ||
| 335 | page[i] &= 0xfffffff7; // reserved instruction, so we trap | ||
| 336 | touched = true; | ||
| 337 | } | ||
| 338 | |||
| 339 | if (touched) | ||
| 340 | copy_to_user((void __user *)hpage, page, HW_PAGE_SIZE); | ||
| 341 | |||
| 342 | out: | ||
| 343 | vfree(page); | ||
| 344 | } | ||
| 345 | |||
| 346 | static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data, | ||
| 347 | struct kvmppc_pte *pte) | ||
| 348 | { | ||
| 349 | int relocated = (vcpu->arch.msr & (data ? MSR_DR : MSR_IR)); | ||
| 350 | int r; | ||
| 351 | |||
| 352 | if (relocated) { | ||
| 353 | r = vcpu->arch.mmu.xlate(vcpu, eaddr, pte, data); | ||
| 354 | } else { | ||
| 355 | pte->eaddr = eaddr; | ||
| 356 | pte->raddr = eaddr & 0xffffffff; | ||
| 357 | pte->vpage = eaddr >> 12; | ||
| 358 | switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) { | ||
| 359 | case 0: | ||
| 360 | pte->vpage |= VSID_REAL; | ||
| 361 | case MSR_DR: | ||
| 362 | pte->vpage |= VSID_REAL_DR; | ||
| 363 | case MSR_IR: | ||
| 364 | pte->vpage |= VSID_REAL_IR; | ||
| 365 | } | ||
| 366 | pte->may_read = true; | ||
| 367 | pte->may_write = true; | ||
| 368 | pte->may_execute = true; | ||
| 369 | r = 0; | ||
| 370 | } | ||
| 371 | |||
| 372 | return r; | ||
| 373 | } | ||
| 374 | |||
| 375 | static hva_t kvmppc_bad_hva(void) | ||
| 376 | { | ||
| 377 | return PAGE_OFFSET; | ||
| 378 | } | ||
| 379 | |||
| 380 | static hva_t kvmppc_pte_to_hva(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte, | ||
| 381 | bool read) | ||
| 382 | { | ||
| 383 | hva_t hpage; | ||
| 384 | |||
| 385 | if (read && !pte->may_read) | ||
| 386 | goto err; | ||
| 387 | |||
| 388 | if (!read && !pte->may_write) | ||
| 389 | goto err; | ||
| 390 | |||
| 391 | hpage = gfn_to_hva(vcpu->kvm, pte->raddr >> PAGE_SHIFT); | ||
| 392 | if (kvm_is_error_hva(hpage)) | ||
| 393 | goto err; | ||
| 394 | |||
| 395 | return hpage | (pte->raddr & ~PAGE_MASK); | ||
| 396 | err: | ||
| 397 | return kvmppc_bad_hva(); | ||
| 398 | } | ||
| 399 | |||
| 400 | int kvmppc_st(struct kvm_vcpu *vcpu, ulong eaddr, int size, void *ptr) | ||
| 401 | { | ||
| 402 | struct kvmppc_pte pte; | ||
| 403 | hva_t hva = eaddr; | ||
| 404 | |||
| 405 | vcpu->stat.st++; | ||
| 406 | |||
| 407 | if (kvmppc_xlate(vcpu, eaddr, false, &pte)) | ||
| 408 | goto err; | ||
| 409 | |||
| 410 | hva = kvmppc_pte_to_hva(vcpu, &pte, false); | ||
| 411 | if (kvm_is_error_hva(hva)) | ||
| 412 | goto err; | ||
| 413 | |||
| 414 | if (copy_to_user((void __user *)hva, ptr, size)) { | ||
| 415 | printk(KERN_INFO "kvmppc_st at 0x%lx failed\n", hva); | ||
| 416 | goto err; | ||
| 417 | } | ||
| 418 | |||
| 419 | return 0; | ||
| 420 | |||
| 421 | err: | ||
| 422 | return -ENOENT; | ||
| 423 | } | ||
| 424 | |||
| 425 | int kvmppc_ld(struct kvm_vcpu *vcpu, ulong eaddr, int size, void *ptr, | ||
| 426 | bool data) | ||
| 427 | { | ||
| 428 | struct kvmppc_pte pte; | ||
| 429 | hva_t hva = eaddr; | ||
| 430 | |||
| 431 | vcpu->stat.ld++; | ||
| 432 | |||
| 433 | if (kvmppc_xlate(vcpu, eaddr, data, &pte)) | ||
| 434 | goto err; | ||
| 435 | |||
| 436 | hva = kvmppc_pte_to_hva(vcpu, &pte, true); | ||
| 437 | if (kvm_is_error_hva(hva)) | ||
| 438 | goto err; | ||
| 439 | |||
| 440 | if (copy_from_user(ptr, (void __user *)hva, size)) { | ||
| 441 | printk(KERN_INFO "kvmppc_ld at 0x%lx failed\n", hva); | ||
| 442 | goto err; | ||
| 443 | } | ||
| 444 | |||
| 445 | return 0; | ||
| 446 | |||
| 447 | err: | ||
| 448 | return -ENOENT; | ||
| 449 | } | ||
| 450 | |||
| 451 | static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn) | ||
| 452 | { | ||
| 453 | return kvm_is_visible_gfn(vcpu->kvm, gfn); | ||
| 454 | } | ||
| 455 | |||
| 456 | int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, | ||
| 457 | ulong eaddr, int vec) | ||
| 458 | { | ||
| 459 | bool data = (vec == BOOK3S_INTERRUPT_DATA_STORAGE); | ||
| 460 | int r = RESUME_GUEST; | ||
| 461 | int relocated; | ||
| 462 | int page_found = 0; | ||
| 463 | struct kvmppc_pte pte; | ||
| 464 | bool is_mmio = false; | ||
| 465 | |||
| 466 | if ( vec == BOOK3S_INTERRUPT_DATA_STORAGE ) { | ||
| 467 | relocated = (vcpu->arch.msr & MSR_DR); | ||
| 468 | } else { | ||
| 469 | relocated = (vcpu->arch.msr & MSR_IR); | ||
| 470 | } | ||
| 471 | |||
| 472 | /* Resolve real address if translation turned on */ | ||
| 473 | if (relocated) { | ||
| 474 | page_found = vcpu->arch.mmu.xlate(vcpu, eaddr, &pte, data); | ||
| 475 | } else { | ||
| 476 | pte.may_execute = true; | ||
| 477 | pte.may_read = true; | ||
| 478 | pte.may_write = true; | ||
| 479 | pte.raddr = eaddr & 0xffffffff; | ||
| 480 | pte.eaddr = eaddr; | ||
| 481 | pte.vpage = eaddr >> 12; | ||
| 482 | switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) { | ||
| 483 | case 0: | ||
| 484 | pte.vpage |= VSID_REAL; | ||
| 485 | case MSR_DR: | ||
| 486 | pte.vpage |= VSID_REAL_DR; | ||
| 487 | case MSR_IR: | ||
| 488 | pte.vpage |= VSID_REAL_IR; | ||
| 489 | } | ||
| 490 | } | ||
| 491 | |||
| 492 | if (vcpu->arch.mmu.is_dcbz32(vcpu) && | ||
| 493 | (!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32))) { | ||
| 494 | /* | ||
| 495 | * If we do the dcbz hack, we have to NX on every execution, | ||
| 496 | * so we can patch the executing code. This renders our guest | ||
| 497 | * NX-less. | ||
| 498 | */ | ||
| 499 | pte.may_execute = !data; | ||
| 500 | } | ||
| 501 | |||
| 502 | if (page_found == -ENOENT) { | ||
| 503 | /* Page not found in guest PTE entries */ | ||
| 504 | vcpu->arch.dear = vcpu->arch.fault_dear; | ||
| 505 | to_book3s(vcpu)->dsisr = vcpu->arch.fault_dsisr; | ||
| 506 | vcpu->arch.msr |= (vcpu->arch.shadow_msr & 0x00000000f8000000ULL); | ||
| 507 | kvmppc_book3s_queue_irqprio(vcpu, vec); | ||
| 508 | } else if (page_found == -EPERM) { | ||
| 509 | /* Storage protection */ | ||
| 510 | vcpu->arch.dear = vcpu->arch.fault_dear; | ||
| 511 | to_book3s(vcpu)->dsisr = vcpu->arch.fault_dsisr & ~DSISR_NOHPTE; | ||
| 512 | to_book3s(vcpu)->dsisr |= DSISR_PROTFAULT; | ||
| 513 | vcpu->arch.msr |= (vcpu->arch.shadow_msr & 0x00000000f8000000ULL); | ||
| 514 | kvmppc_book3s_queue_irqprio(vcpu, vec); | ||
| 515 | } else if (page_found == -EINVAL) { | ||
| 516 | /* Page not found in guest SLB */ | ||
| 517 | vcpu->arch.dear = vcpu->arch.fault_dear; | ||
| 518 | kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80); | ||
| 519 | } else if (!is_mmio && | ||
| 520 | kvmppc_visible_gfn(vcpu, pte.raddr >> PAGE_SHIFT)) { | ||
| 521 | /* The guest's PTE is not mapped yet. Map on the host */ | ||
| 522 | kvmppc_mmu_map_page(vcpu, &pte); | ||
| 523 | if (data) | ||
| 524 | vcpu->stat.sp_storage++; | ||
| 525 | else if (vcpu->arch.mmu.is_dcbz32(vcpu) && | ||
| 526 | (!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32))) | ||
| 527 | kvmppc_patch_dcbz(vcpu, &pte); | ||
| 528 | } else { | ||
| 529 | /* MMIO */ | ||
| 530 | vcpu->stat.mmio_exits++; | ||
| 531 | vcpu->arch.paddr_accessed = pte.raddr; | ||
| 532 | r = kvmppc_emulate_mmio(run, vcpu); | ||
| 533 | if ( r == RESUME_HOST_NV ) | ||
| 534 | r = RESUME_HOST; | ||
| 535 | if ( r == RESUME_GUEST_NV ) | ||
| 536 | r = RESUME_GUEST; | ||
| 537 | } | ||
| 538 | |||
| 539 | return r; | ||
| 540 | } | ||
| 541 | |||
| 542 | int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | ||
| 543 | unsigned int exit_nr) | ||
| 544 | { | ||
| 545 | int r = RESUME_HOST; | ||
| 546 | |||
| 547 | vcpu->stat.sum_exits++; | ||
| 548 | |||
| 549 | run->exit_reason = KVM_EXIT_UNKNOWN; | ||
| 550 | run->ready_for_interrupt_injection = 1; | ||
| 551 | #ifdef EXIT_DEBUG | ||
| 552 | printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | dar=0x%lx | dec=0x%x | msr=0x%lx\n", | ||
| 553 | exit_nr, vcpu->arch.pc, vcpu->arch.fault_dear, | ||
| 554 | kvmppc_get_dec(vcpu), vcpu->arch.msr); | ||
| 555 | #elif defined (EXIT_DEBUG_SIMPLE) | ||
| 556 | if ((exit_nr != 0x900) && (exit_nr != 0x500)) | ||
| 557 | printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | dar=0x%lx | msr=0x%lx\n", | ||
| 558 | exit_nr, vcpu->arch.pc, vcpu->arch.fault_dear, | ||
| 559 | vcpu->arch.msr); | ||
| 560 | #endif | ||
| 561 | kvm_resched(vcpu); | ||
| 562 | switch (exit_nr) { | ||
| 563 | case BOOK3S_INTERRUPT_INST_STORAGE: | ||
| 564 | vcpu->stat.pf_instruc++; | ||
| 565 | /* only care about PTEG not found errors, but leave NX alone */ | ||
| 566 | if (vcpu->arch.shadow_msr & 0x40000000) { | ||
| 567 | r = kvmppc_handle_pagefault(run, vcpu, vcpu->arch.pc, exit_nr); | ||
| 568 | vcpu->stat.sp_instruc++; | ||
| 569 | } else if (vcpu->arch.mmu.is_dcbz32(vcpu) && | ||
| 570 | (!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32))) { | ||
| 571 | /* | ||
| 572 | * XXX If we do the dcbz hack we use the NX bit to flush&patch the page, | ||
| 573 | * so we can't use the NX bit inside the guest. Let's cross our fingers, | ||
| 574 | * that no guest that needs the dcbz hack does NX. | ||
| 575 | */ | ||
| 576 | kvmppc_mmu_pte_flush(vcpu, vcpu->arch.pc, ~0xFFFULL); | ||
| 577 | } else { | ||
| 578 | vcpu->arch.msr |= (vcpu->arch.shadow_msr & 0x58000000); | ||
| 579 | kvmppc_book3s_queue_irqprio(vcpu, exit_nr); | ||
| 580 | kvmppc_mmu_pte_flush(vcpu, vcpu->arch.pc, ~0xFFFULL); | ||
| 581 | r = RESUME_GUEST; | ||
| 582 | } | ||
| 583 | break; | ||
| 584 | case BOOK3S_INTERRUPT_DATA_STORAGE: | ||
| 585 | vcpu->stat.pf_storage++; | ||
| 586 | /* The only case we need to handle is missing shadow PTEs */ | ||
| 587 | if (vcpu->arch.fault_dsisr & DSISR_NOHPTE) { | ||
| 588 | r = kvmppc_handle_pagefault(run, vcpu, vcpu->arch.fault_dear, exit_nr); | ||
| 589 | } else { | ||
| 590 | vcpu->arch.dear = vcpu->arch.fault_dear; | ||
| 591 | to_book3s(vcpu)->dsisr = vcpu->arch.fault_dsisr; | ||
| 592 | kvmppc_book3s_queue_irqprio(vcpu, exit_nr); | ||
| 593 | kvmppc_mmu_pte_flush(vcpu, vcpu->arch.dear, ~0xFFFULL); | ||
| 594 | r = RESUME_GUEST; | ||
| 595 | } | ||
| 596 | break; | ||
| 597 | case BOOK3S_INTERRUPT_DATA_SEGMENT: | ||
| 598 | if (kvmppc_mmu_map_segment(vcpu, vcpu->arch.fault_dear) < 0) { | ||
| 599 | vcpu->arch.dear = vcpu->arch.fault_dear; | ||
| 600 | kvmppc_book3s_queue_irqprio(vcpu, | ||
| 601 | BOOK3S_INTERRUPT_DATA_SEGMENT); | ||
| 602 | } | ||
| 603 | r = RESUME_GUEST; | ||
| 604 | break; | ||
| 605 | case BOOK3S_INTERRUPT_INST_SEGMENT: | ||
| 606 | if (kvmppc_mmu_map_segment(vcpu, vcpu->arch.pc) < 0) { | ||
| 607 | kvmppc_book3s_queue_irqprio(vcpu, | ||
| 608 | BOOK3S_INTERRUPT_INST_SEGMENT); | ||
| 609 | } | ||
| 610 | r = RESUME_GUEST; | ||
| 611 | break; | ||
| 612 | /* We're good on these - the host merely wanted to get our attention */ | ||
| 613 | case BOOK3S_INTERRUPT_DECREMENTER: | ||
| 614 | vcpu->stat.dec_exits++; | ||
| 615 | r = RESUME_GUEST; | ||
| 616 | break; | ||
| 617 | case BOOK3S_INTERRUPT_EXTERNAL: | ||
| 618 | vcpu->stat.ext_intr_exits++; | ||
| 619 | r = RESUME_GUEST; | ||
| 620 | break; | ||
| 621 | case BOOK3S_INTERRUPT_PROGRAM: | ||
| 622 | { | ||
| 623 | enum emulation_result er; | ||
| 624 | |||
| 625 | if (vcpu->arch.msr & MSR_PR) { | ||
| 626 | #ifdef EXIT_DEBUG | ||
| 627 | printk(KERN_INFO "Userspace triggered 0x700 exception at 0x%lx (0x%x)\n", vcpu->arch.pc, vcpu->arch.last_inst); | ||
| 628 | #endif | ||
| 629 | if ((vcpu->arch.last_inst & 0xff0007ff) != | ||
| 630 | (INS_DCBZ & 0xfffffff7)) { | ||
| 631 | kvmppc_book3s_queue_irqprio(vcpu, exit_nr); | ||
| 632 | r = RESUME_GUEST; | ||
| 633 | break; | ||
| 634 | } | ||
| 635 | } | ||
| 636 | |||
| 637 | vcpu->stat.emulated_inst_exits++; | ||
| 638 | er = kvmppc_emulate_instruction(run, vcpu); | ||
| 639 | switch (er) { | ||
| 640 | case EMULATE_DONE: | ||
| 641 | r = RESUME_GUEST; | ||
| 642 | break; | ||
| 643 | case EMULATE_FAIL: | ||
| 644 | printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n", | ||
| 645 | __func__, vcpu->arch.pc, vcpu->arch.last_inst); | ||
| 646 | kvmppc_book3s_queue_irqprio(vcpu, exit_nr); | ||
| 647 | r = RESUME_GUEST; | ||
| 648 | break; | ||
| 649 | default: | ||
| 650 | BUG(); | ||
| 651 | } | ||
| 652 | break; | ||
| 653 | } | ||
| 654 | case BOOK3S_INTERRUPT_SYSCALL: | ||
| 655 | #ifdef EXIT_DEBUG | ||
| 656 | printk(KERN_INFO "Syscall Nr %d\n", (int)vcpu->arch.gpr[0]); | ||
| 657 | #endif | ||
| 658 | vcpu->stat.syscall_exits++; | ||
| 659 | kvmppc_book3s_queue_irqprio(vcpu, exit_nr); | ||
| 660 | r = RESUME_GUEST; | ||
| 661 | break; | ||
| 662 | case BOOK3S_INTERRUPT_MACHINE_CHECK: | ||
| 663 | case BOOK3S_INTERRUPT_FP_UNAVAIL: | ||
| 664 | case BOOK3S_INTERRUPT_TRACE: | ||
| 665 | case BOOK3S_INTERRUPT_ALTIVEC: | ||
| 666 | case BOOK3S_INTERRUPT_VSX: | ||
| 667 | kvmppc_book3s_queue_irqprio(vcpu, exit_nr); | ||
| 668 | r = RESUME_GUEST; | ||
| 669 | break; | ||
| 670 | default: | ||
| 671 | /* Ugh - bork here! What did we get? */ | ||
| 672 | printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | msr=0x%lx\n", exit_nr, vcpu->arch.pc, vcpu->arch.shadow_msr); | ||
| 673 | r = RESUME_HOST; | ||
| 674 | BUG(); | ||
| 675 | break; | ||
| 676 | } | ||
| 677 | |||
| 678 | |||
| 679 | if (!(r & RESUME_HOST)) { | ||
| 680 | /* To avoid clobbering exit_reason, only check for signals if | ||
| 681 | * we aren't already exiting to userspace for some other | ||
| 682 | * reason. */ | ||
| 683 | if (signal_pending(current)) { | ||
| 684 | #ifdef EXIT_DEBUG | ||
| 685 | printk(KERN_EMERG "KVM: Going back to host\n"); | ||
| 686 | #endif | ||
| 687 | vcpu->stat.signal_exits++; | ||
| 688 | run->exit_reason = KVM_EXIT_INTR; | ||
| 689 | r = -EINTR; | ||
| 690 | } else { | ||
| 691 | /* In case an interrupt came in that was triggered | ||
| 692 | * from userspace (like DEC), we need to check what | ||
| 693 | * to inject now! */ | ||
| 694 | kvmppc_core_deliver_interrupts(vcpu); | ||
| 695 | } | ||
| 696 | } | ||
| 697 | |||
| 698 | #ifdef EXIT_DEBUG | ||
| 699 | printk(KERN_EMERG "KVM exit: vcpu=0x%p pc=0x%lx r=0x%x\n", vcpu, vcpu->arch.pc, r); | ||
| 700 | #endif | ||
| 701 | |||
| 702 | return r; | ||
| 703 | } | ||
| 704 | |||
| 705 | int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) | ||
| 706 | { | ||
| 707 | return 0; | ||
| 708 | } | ||
| 709 | |||
| 710 | int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) | ||
| 711 | { | ||
| 712 | int i; | ||
| 713 | |||
| 714 | regs->pc = vcpu->arch.pc; | ||
| 715 | regs->cr = vcpu->arch.cr; | ||
| 716 | regs->ctr = vcpu->arch.ctr; | ||
| 717 | regs->lr = vcpu->arch.lr; | ||
| 718 | regs->xer = vcpu->arch.xer; | ||
| 719 | regs->msr = vcpu->arch.msr; | ||
| 720 | regs->srr0 = vcpu->arch.srr0; | ||
| 721 | regs->srr1 = vcpu->arch.srr1; | ||
| 722 | regs->pid = vcpu->arch.pid; | ||
| 723 | regs->sprg0 = vcpu->arch.sprg0; | ||
| 724 | regs->sprg1 = vcpu->arch.sprg1; | ||
| 725 | regs->sprg2 = vcpu->arch.sprg2; | ||
| 726 | regs->sprg3 = vcpu->arch.sprg3; | ||
| 727 | regs->sprg5 = vcpu->arch.sprg4; | ||
| 728 | regs->sprg6 = vcpu->arch.sprg5; | ||
| 729 | regs->sprg7 = vcpu->arch.sprg6; | ||
| 730 | |||
| 731 | for (i = 0; i < ARRAY_SIZE(regs->gpr); i++) | ||
| 732 | regs->gpr[i] = vcpu->arch.gpr[i]; | ||
| 733 | |||
| 734 | return 0; | ||
| 735 | } | ||
| 736 | |||
| 737 | int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) | ||
| 738 | { | ||
| 739 | int i; | ||
| 740 | |||
| 741 | vcpu->arch.pc = regs->pc; | ||
| 742 | vcpu->arch.cr = regs->cr; | ||
| 743 | vcpu->arch.ctr = regs->ctr; | ||
| 744 | vcpu->arch.lr = regs->lr; | ||
| 745 | vcpu->arch.xer = regs->xer; | ||
| 746 | kvmppc_set_msr(vcpu, regs->msr); | ||
| 747 | vcpu->arch.srr0 = regs->srr0; | ||
| 748 | vcpu->arch.srr1 = regs->srr1; | ||
| 749 | vcpu->arch.sprg0 = regs->sprg0; | ||
| 750 | vcpu->arch.sprg1 = regs->sprg1; | ||
| 751 | vcpu->arch.sprg2 = regs->sprg2; | ||
| 752 | vcpu->arch.sprg3 = regs->sprg3; | ||
| 753 | vcpu->arch.sprg5 = regs->sprg4; | ||
| 754 | vcpu->arch.sprg6 = regs->sprg5; | ||
| 755 | vcpu->arch.sprg7 = regs->sprg6; | ||
| 756 | |||
| 757 | for (i = 0; i < ARRAY_SIZE(vcpu->arch.gpr); i++) | ||
| 758 | vcpu->arch.gpr[i] = regs->gpr[i]; | ||
| 759 | |||
| 760 | return 0; | ||
| 761 | } | ||
| 762 | |||
| 763 | int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, | ||
| 764 | struct kvm_sregs *sregs) | ||
| 765 | { | ||
| 766 | struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu); | ||
| 767 | int i; | ||
| 768 | |||
| 769 | sregs->pvr = vcpu->arch.pvr; | ||
| 770 | |||
| 771 | sregs->u.s.sdr1 = to_book3s(vcpu)->sdr1; | ||
| 772 | if (vcpu->arch.hflags & BOOK3S_HFLAG_SLB) { | ||
| 773 | for (i = 0; i < 64; i++) { | ||
| 774 | sregs->u.s.ppc64.slb[i].slbe = vcpu3s->slb[i].orige | i; | ||
| 775 | sregs->u.s.ppc64.slb[i].slbv = vcpu3s->slb[i].origv; | ||
| 776 | } | ||
| 777 | } else { | ||
| 778 | for (i = 0; i < 16; i++) { | ||
| 779 | sregs->u.s.ppc32.sr[i] = vcpu3s->sr[i].raw; | ||
| 780 | sregs->u.s.ppc32.sr[i] = vcpu3s->sr[i].raw; | ||
| 781 | } | ||
| 782 | for (i = 0; i < 8; i++) { | ||
| 783 | sregs->u.s.ppc32.ibat[i] = vcpu3s->ibat[i].raw; | ||
| 784 | sregs->u.s.ppc32.dbat[i] = vcpu3s->dbat[i].raw; | ||
| 785 | } | ||
| 786 | } | ||
| 787 | return 0; | ||
| 788 | } | ||
| 789 | |||
| 790 | int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, | ||
| 791 | struct kvm_sregs *sregs) | ||
| 792 | { | ||
| 793 | struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu); | ||
| 794 | int i; | ||
| 795 | |||
| 796 | kvmppc_set_pvr(vcpu, sregs->pvr); | ||
| 797 | |||
| 798 | vcpu3s->sdr1 = sregs->u.s.sdr1; | ||
| 799 | if (vcpu->arch.hflags & BOOK3S_HFLAG_SLB) { | ||
| 800 | for (i = 0; i < 64; i++) { | ||
| 801 | vcpu->arch.mmu.slbmte(vcpu, sregs->u.s.ppc64.slb[i].slbv, | ||
| 802 | sregs->u.s.ppc64.slb[i].slbe); | ||
| 803 | } | ||
| 804 | } else { | ||
| 805 | for (i = 0; i < 16; i++) { | ||
| 806 | vcpu->arch.mmu.mtsrin(vcpu, i, sregs->u.s.ppc32.sr[i]); | ||
| 807 | } | ||
| 808 | for (i = 0; i < 8; i++) { | ||
| 809 | kvmppc_set_bat(vcpu, &(vcpu3s->ibat[i]), false, | ||
| 810 | (u32)sregs->u.s.ppc32.ibat[i]); | ||
| 811 | kvmppc_set_bat(vcpu, &(vcpu3s->ibat[i]), true, | ||
| 812 | (u32)(sregs->u.s.ppc32.ibat[i] >> 32)); | ||
| 813 | kvmppc_set_bat(vcpu, &(vcpu3s->dbat[i]), false, | ||
| 814 | (u32)sregs->u.s.ppc32.dbat[i]); | ||
| 815 | kvmppc_set_bat(vcpu, &(vcpu3s->dbat[i]), true, | ||
| 816 | (u32)(sregs->u.s.ppc32.dbat[i] >> 32)); | ||
| 817 | } | ||
| 818 | } | ||
| 819 | |||
| 820 | /* Flush the MMU after messing with the segments */ | ||
| 821 | kvmppc_mmu_pte_flush(vcpu, 0, 0); | ||
| 822 | return 0; | ||
| 823 | } | ||
| 824 | |||
| 825 | int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) | ||
| 826 | { | ||
| 827 | return -ENOTSUPP; | ||
| 828 | } | ||
| 829 | |||
| 830 | int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) | ||
| 831 | { | ||
| 832 | return -ENOTSUPP; | ||
| 833 | } | ||
| 834 | |||
| 835 | int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, | ||
| 836 | struct kvm_translation *tr) | ||
| 837 | { | ||
| 838 | return 0; | ||
| 839 | } | ||
| 840 | |||
| 841 | /* | ||
| 842 | * Get (and clear) the dirty memory log for a memory slot. | ||
| 843 | */ | ||
| 844 | int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, | ||
| 845 | struct kvm_dirty_log *log) | ||
| 846 | { | ||
| 847 | struct kvm_memory_slot *memslot; | ||
| 848 | struct kvm_vcpu *vcpu; | ||
| 849 | ulong ga, ga_end; | ||
| 850 | int is_dirty = 0; | ||
| 851 | int r, n; | ||
| 852 | |||
| 853 | down_write(&kvm->slots_lock); | ||
| 854 | |||
| 855 | r = kvm_get_dirty_log(kvm, log, &is_dirty); | ||
| 856 | if (r) | ||
| 857 | goto out; | ||
| 858 | |||
| 859 | /* If nothing is dirty, don't bother messing with page tables. */ | ||
| 860 | if (is_dirty) { | ||
| 861 | memslot = &kvm->memslots[log->slot]; | ||
| 862 | |||
| 863 | ga = memslot->base_gfn << PAGE_SHIFT; | ||
| 864 | ga_end = ga + (memslot->npages << PAGE_SHIFT); | ||
| 865 | |||
| 866 | kvm_for_each_vcpu(n, vcpu, kvm) | ||
| 867 | kvmppc_mmu_pte_pflush(vcpu, ga, ga_end); | ||
| 868 | |||
| 869 | n = ALIGN(memslot->npages, BITS_PER_LONG) / 8; | ||
| 870 | memset(memslot->dirty_bitmap, 0, n); | ||
| 871 | } | ||
| 872 | |||
| 873 | r = 0; | ||
| 874 | out: | ||
| 875 | up_write(&kvm->slots_lock); | ||
| 876 | return r; | ||
| 877 | } | ||
| 878 | |||
| 879 | int kvmppc_core_check_processor_compat(void) | ||
| 880 | { | ||
| 881 | return 0; | ||
| 882 | } | ||
| 883 | |||
| 884 | struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) | ||
| 885 | { | ||
| 886 | struct kvmppc_vcpu_book3s *vcpu_book3s; | ||
| 887 | struct kvm_vcpu *vcpu; | ||
| 888 | int err; | ||
| 889 | |||
| 890 | vcpu_book3s = (struct kvmppc_vcpu_book3s *)__get_free_pages( GFP_KERNEL | __GFP_ZERO, | ||
| 891 | get_order(sizeof(struct kvmppc_vcpu_book3s))); | ||
| 892 | if (!vcpu_book3s) { | ||
| 893 | err = -ENOMEM; | ||
| 894 | goto out; | ||
| 895 | } | ||
| 896 | |||
| 897 | vcpu = &vcpu_book3s->vcpu; | ||
| 898 | err = kvm_vcpu_init(vcpu, kvm, id); | ||
| 899 | if (err) | ||
| 900 | goto free_vcpu; | ||
| 901 | |||
| 902 | vcpu->arch.host_retip = kvm_return_point; | ||
| 903 | vcpu->arch.host_msr = mfmsr(); | ||
| 904 | /* default to book3s_64 (970fx) */ | ||
| 905 | vcpu->arch.pvr = 0x3C0301; | ||
| 906 | kvmppc_set_pvr(vcpu, vcpu->arch.pvr); | ||
| 907 | vcpu_book3s->slb_nr = 64; | ||
| 908 | |||
| 909 | /* remember where some real-mode handlers are */ | ||
| 910 | vcpu->arch.trampoline_lowmem = kvmppc_trampoline_lowmem; | ||
| 911 | vcpu->arch.trampoline_enter = kvmppc_trampoline_enter; | ||
| 912 | vcpu->arch.highmem_handler = (ulong)kvmppc_handler_highmem; | ||
| 913 | |||
| 914 | vcpu->arch.shadow_msr = MSR_USER64; | ||
| 915 | |||
| 916 | err = __init_new_context(); | ||
| 917 | if (err < 0) | ||
| 918 | goto free_vcpu; | ||
| 919 | vcpu_book3s->context_id = err; | ||
| 920 | |||
| 921 | vcpu_book3s->vsid_max = ((vcpu_book3s->context_id + 1) << USER_ESID_BITS) - 1; | ||
| 922 | vcpu_book3s->vsid_first = vcpu_book3s->context_id << USER_ESID_BITS; | ||
| 923 | vcpu_book3s->vsid_next = vcpu_book3s->vsid_first; | ||
| 924 | |||
| 925 | return vcpu; | ||
| 926 | |||
| 927 | free_vcpu: | ||
| 928 | free_pages((long)vcpu_book3s, get_order(sizeof(struct kvmppc_vcpu_book3s))); | ||
| 929 | out: | ||
| 930 | return ERR_PTR(err); | ||
| 931 | } | ||
| 932 | |||
| 933 | void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) | ||
| 934 | { | ||
| 935 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | ||
| 936 | |||
| 937 | __destroy_context(vcpu_book3s->context_id); | ||
| 938 | kvm_vcpu_uninit(vcpu); | ||
| 939 | free_pages((long)vcpu_book3s, get_order(sizeof(struct kvmppc_vcpu_book3s))); | ||
| 940 | } | ||
| 941 | |||
| 942 | extern int __kvmppc_vcpu_entry(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu); | ||
| 943 | int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | ||
| 944 | { | ||
| 945 | int ret; | ||
| 946 | |||
| 947 | /* No need to go into the guest when all we do is going out */ | ||
| 948 | if (signal_pending(current)) { | ||
| 949 | kvm_run->exit_reason = KVM_EXIT_INTR; | ||
| 950 | return -EINTR; | ||
| 951 | } | ||
| 952 | |||
| 953 | /* XXX we get called with irq disabled - change that! */ | ||
| 954 | local_irq_enable(); | ||
| 955 | |||
| 956 | ret = __kvmppc_vcpu_entry(kvm_run, vcpu); | ||
| 957 | |||
| 958 | local_irq_disable(); | ||
| 959 | |||
| 960 | return ret; | ||
| 961 | } | ||
| 962 | |||
| 963 | static int kvmppc_book3s_init(void) | ||
| 964 | { | ||
| 965 | return kvm_init(NULL, sizeof(struct kvmppc_vcpu_book3s), THIS_MODULE); | ||
| 966 | } | ||
| 967 | |||
| 968 | static void kvmppc_book3s_exit(void) | ||
| 969 | { | ||
| 970 | kvm_exit(); | ||
| 971 | } | ||
| 972 | |||
| 973 | module_init(kvmppc_book3s_init); | ||
| 974 | module_exit(kvmppc_book3s_exit); | ||
diff --git a/arch/powerpc/kvm/book3s_32_mmu.c b/arch/powerpc/kvm/book3s_32_mmu.c new file mode 100644 index 000000000000..faf99f20d993 --- /dev/null +++ b/arch/powerpc/kvm/book3s_32_mmu.c | |||
| @@ -0,0 +1,372 @@ | |||
| 1 | /* | ||
| 2 | * This program is free software; you can redistribute it and/or modify | ||
| 3 | * it under the terms of the GNU General Public License, version 2, as | ||
| 4 | * published by the Free Software Foundation. | ||
| 5 | * | ||
| 6 | * This program is distributed in the hope that it will be useful, | ||
| 7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 9 | * GNU General Public License for more details. | ||
| 10 | * | ||
| 11 | * You should have received a copy of the GNU General Public License | ||
| 12 | * along with this program; if not, write to the Free Software | ||
| 13 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 14 | * | ||
| 15 | * Copyright SUSE Linux Products GmbH 2009 | ||
| 16 | * | ||
| 17 | * Authors: Alexander Graf <agraf@suse.de> | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/types.h> | ||
| 21 | #include <linux/string.h> | ||
| 22 | #include <linux/kvm.h> | ||
| 23 | #include <linux/kvm_host.h> | ||
| 24 | #include <linux/highmem.h> | ||
| 25 | |||
| 26 | #include <asm/tlbflush.h> | ||
| 27 | #include <asm/kvm_ppc.h> | ||
| 28 | #include <asm/kvm_book3s.h> | ||
| 29 | |||
| 30 | /* #define DEBUG_MMU */ | ||
| 31 | /* #define DEBUG_MMU_PTE */ | ||
| 32 | /* #define DEBUG_MMU_PTE_IP 0xfff14c40 */ | ||
| 33 | |||
| 34 | #ifdef DEBUG_MMU | ||
| 35 | #define dprintk(X...) printk(KERN_INFO X) | ||
| 36 | #else | ||
| 37 | #define dprintk(X...) do { } while(0) | ||
| 38 | #endif | ||
| 39 | |||
| 40 | #ifdef DEBUG_PTE | ||
| 41 | #define dprintk_pte(X...) printk(KERN_INFO X) | ||
| 42 | #else | ||
| 43 | #define dprintk_pte(X...) do { } while(0) | ||
| 44 | #endif | ||
| 45 | |||
| 46 | #define PTEG_FLAG_ACCESSED 0x00000100 | ||
| 47 | #define PTEG_FLAG_DIRTY 0x00000080 | ||
| 48 | |||
| 49 | static inline bool check_debug_ip(struct kvm_vcpu *vcpu) | ||
| 50 | { | ||
| 51 | #ifdef DEBUG_MMU_PTE_IP | ||
| 52 | return vcpu->arch.pc == DEBUG_MMU_PTE_IP; | ||
| 53 | #else | ||
| 54 | return true; | ||
| 55 | #endif | ||
| 56 | } | ||
| 57 | |||
| 58 | static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr, | ||
| 59 | struct kvmppc_pte *pte, bool data); | ||
| 60 | |||
| 61 | static struct kvmppc_sr *find_sr(struct kvmppc_vcpu_book3s *vcpu_book3s, gva_t eaddr) | ||
| 62 | { | ||
| 63 | return &vcpu_book3s->sr[(eaddr >> 28) & 0xf]; | ||
| 64 | } | ||
| 65 | |||
| 66 | static u64 kvmppc_mmu_book3s_32_ea_to_vp(struct kvm_vcpu *vcpu, gva_t eaddr, | ||
| 67 | bool data) | ||
| 68 | { | ||
| 69 | struct kvmppc_sr *sre = find_sr(to_book3s(vcpu), eaddr); | ||
| 70 | struct kvmppc_pte pte; | ||
| 71 | |||
| 72 | if (!kvmppc_mmu_book3s_32_xlate_bat(vcpu, eaddr, &pte, data)) | ||
| 73 | return pte.vpage; | ||
| 74 | |||
| 75 | return (((u64)eaddr >> 12) & 0xffff) | (((u64)sre->vsid) << 16); | ||
| 76 | } | ||
| 77 | |||
| 78 | static void kvmppc_mmu_book3s_32_reset_msr(struct kvm_vcpu *vcpu) | ||
| 79 | { | ||
| 80 | kvmppc_set_msr(vcpu, 0); | ||
| 81 | } | ||
| 82 | |||
| 83 | static hva_t kvmppc_mmu_book3s_32_get_pteg(struct kvmppc_vcpu_book3s *vcpu_book3s, | ||
| 84 | struct kvmppc_sr *sre, gva_t eaddr, | ||
| 85 | bool primary) | ||
| 86 | { | ||
| 87 | u32 page, hash, pteg, htabmask; | ||
| 88 | hva_t r; | ||
| 89 | |||
| 90 | page = (eaddr & 0x0FFFFFFF) >> 12; | ||
| 91 | htabmask = ((vcpu_book3s->sdr1 & 0x1FF) << 16) | 0xFFC0; | ||
| 92 | |||
| 93 | hash = ((sre->vsid ^ page) << 6); | ||
| 94 | if (!primary) | ||
| 95 | hash = ~hash; | ||
| 96 | hash &= htabmask; | ||
| 97 | |||
| 98 | pteg = (vcpu_book3s->sdr1 & 0xffff0000) | hash; | ||
| 99 | |||
| 100 | dprintk("MMU: pc=0x%lx eaddr=0x%lx sdr1=0x%llx pteg=0x%x vsid=0x%x\n", | ||
| 101 | vcpu_book3s->vcpu.arch.pc, eaddr, vcpu_book3s->sdr1, pteg, | ||
| 102 | sre->vsid); | ||
| 103 | |||
| 104 | r = gfn_to_hva(vcpu_book3s->vcpu.kvm, pteg >> PAGE_SHIFT); | ||
| 105 | if (kvm_is_error_hva(r)) | ||
| 106 | return r; | ||
| 107 | return r | (pteg & ~PAGE_MASK); | ||
| 108 | } | ||
| 109 | |||
| 110 | static u32 kvmppc_mmu_book3s_32_get_ptem(struct kvmppc_sr *sre, gva_t eaddr, | ||
| 111 | bool primary) | ||
| 112 | { | ||
| 113 | return ((eaddr & 0x0fffffff) >> 22) | (sre->vsid << 7) | | ||
| 114 | (primary ? 0 : 0x40) | 0x80000000; | ||
| 115 | } | ||
| 116 | |||
| 117 | static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr, | ||
| 118 | struct kvmppc_pte *pte, bool data) | ||
| 119 | { | ||
| 120 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | ||
| 121 | struct kvmppc_bat *bat; | ||
| 122 | int i; | ||
| 123 | |||
| 124 | for (i = 0; i < 8; i++) { | ||
| 125 | if (data) | ||
| 126 | bat = &vcpu_book3s->dbat[i]; | ||
| 127 | else | ||
| 128 | bat = &vcpu_book3s->ibat[i]; | ||
| 129 | |||
| 130 | if (vcpu->arch.msr & MSR_PR) { | ||
| 131 | if (!bat->vp) | ||
| 132 | continue; | ||
| 133 | } else { | ||
| 134 | if (!bat->vs) | ||
| 135 | continue; | ||
| 136 | } | ||
| 137 | |||
| 138 | if (check_debug_ip(vcpu)) | ||
| 139 | { | ||
| 140 | dprintk_pte("%cBAT %02d: 0x%lx - 0x%x (0x%x)\n", | ||
| 141 | data ? 'd' : 'i', i, eaddr, bat->bepi, | ||
| 142 | bat->bepi_mask); | ||
| 143 | } | ||
| 144 | if ((eaddr & bat->bepi_mask) == bat->bepi) { | ||
| 145 | pte->raddr = bat->brpn | (eaddr & ~bat->bepi_mask); | ||
| 146 | pte->vpage = (eaddr >> 12) | VSID_BAT; | ||
| 147 | pte->may_read = bat->pp; | ||
| 148 | pte->may_write = bat->pp > 1; | ||
| 149 | pte->may_execute = true; | ||
| 150 | if (!pte->may_read) { | ||
| 151 | printk(KERN_INFO "BAT is not readable!\n"); | ||
| 152 | continue; | ||
| 153 | } | ||
| 154 | if (!pte->may_write) { | ||
| 155 | /* let's treat r/o BATs as not-readable for now */ | ||
| 156 | dprintk_pte("BAT is read-only!\n"); | ||
| 157 | continue; | ||
| 158 | } | ||
| 159 | |||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | return -ENOENT; | ||
| 165 | } | ||
| 166 | |||
| 167 | static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr, | ||
| 168 | struct kvmppc_pte *pte, bool data, | ||
| 169 | bool primary) | ||
| 170 | { | ||
| 171 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | ||
| 172 | struct kvmppc_sr *sre; | ||
| 173 | hva_t ptegp; | ||
| 174 | u32 pteg[16]; | ||
| 175 | u64 ptem = 0; | ||
| 176 | int i; | ||
| 177 | int found = 0; | ||
| 178 | |||
| 179 | sre = find_sr(vcpu_book3s, eaddr); | ||
| 180 | |||
| 181 | dprintk_pte("SR 0x%lx: vsid=0x%x, raw=0x%x\n", eaddr >> 28, | ||
| 182 | sre->vsid, sre->raw); | ||
| 183 | |||
| 184 | pte->vpage = kvmppc_mmu_book3s_32_ea_to_vp(vcpu, eaddr, data); | ||
| 185 | |||
| 186 | ptegp = kvmppc_mmu_book3s_32_get_pteg(vcpu_book3s, sre, eaddr, primary); | ||
| 187 | if (kvm_is_error_hva(ptegp)) { | ||
| 188 | printk(KERN_INFO "KVM: Invalid PTEG!\n"); | ||
| 189 | goto no_page_found; | ||
| 190 | } | ||
| 191 | |||
| 192 | ptem = kvmppc_mmu_book3s_32_get_ptem(sre, eaddr, primary); | ||
| 193 | |||
| 194 | if(copy_from_user(pteg, (void __user *)ptegp, sizeof(pteg))) { | ||
| 195 | printk(KERN_ERR "KVM: Can't copy data from 0x%lx!\n", ptegp); | ||
| 196 | goto no_page_found; | ||
| 197 | } | ||
| 198 | |||
| 199 | for (i=0; i<16; i+=2) { | ||
| 200 | if (ptem == pteg[i]) { | ||
| 201 | u8 pp; | ||
| 202 | |||
| 203 | pte->raddr = (pteg[i+1] & ~(0xFFFULL)) | (eaddr & 0xFFF); | ||
| 204 | pp = pteg[i+1] & 3; | ||
| 205 | |||
| 206 | if ((sre->Kp && (vcpu->arch.msr & MSR_PR)) || | ||
| 207 | (sre->Ks && !(vcpu->arch.msr & MSR_PR))) | ||
| 208 | pp |= 4; | ||
| 209 | |||
| 210 | pte->may_write = false; | ||
| 211 | pte->may_read = false; | ||
| 212 | pte->may_execute = true; | ||
| 213 | switch (pp) { | ||
| 214 | case 0: | ||
| 215 | case 1: | ||
| 216 | case 2: | ||
| 217 | case 6: | ||
| 218 | pte->may_write = true; | ||
| 219 | case 3: | ||
| 220 | case 5: | ||
| 221 | case 7: | ||
| 222 | pte->may_read = true; | ||
| 223 | break; | ||
| 224 | } | ||
| 225 | |||
| 226 | if ( !pte->may_read ) | ||
| 227 | continue; | ||
| 228 | |||
| 229 | dprintk_pte("MMU: Found PTE -> %x %x - %x\n", | ||
| 230 | pteg[i], pteg[i+1], pp); | ||
| 231 | found = 1; | ||
| 232 | break; | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | /* Update PTE C and A bits, so the guest's swapper knows we used the | ||
| 237 | page */ | ||
| 238 | if (found) { | ||
| 239 | u32 oldpte = pteg[i+1]; | ||
| 240 | |||
| 241 | if (pte->may_read) | ||
| 242 | pteg[i+1] |= PTEG_FLAG_ACCESSED; | ||
| 243 | if (pte->may_write) | ||
| 244 | pteg[i+1] |= PTEG_FLAG_DIRTY; | ||
| 245 | else | ||
| 246 | dprintk_pte("KVM: Mapping read-only page!\n"); | ||
| 247 | |||
| 248 | /* Write back into the PTEG */ | ||
| 249 | if (pteg[i+1] != oldpte) | ||
| 250 | copy_to_user((void __user *)ptegp, pteg, sizeof(pteg)); | ||
| 251 | |||
| 252 | return 0; | ||
| 253 | } | ||
| 254 | |||
| 255 | no_page_found: | ||
| 256 | |||
| 257 | if (check_debug_ip(vcpu)) { | ||
| 258 | dprintk_pte("KVM MMU: No PTE found (sdr1=0x%llx ptegp=0x%lx)\n", | ||
| 259 | to_book3s(vcpu)->sdr1, ptegp); | ||
| 260 | for (i=0; i<16; i+=2) { | ||
| 261 | dprintk_pte(" %02d: 0x%x - 0x%x (0x%llx)\n", | ||
| 262 | i, pteg[i], pteg[i+1], ptem); | ||
| 263 | } | ||
| 264 | } | ||
| 265 | |||
| 266 | return -ENOENT; | ||
| 267 | } | ||
| 268 | |||
| 269 | static int kvmppc_mmu_book3s_32_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, | ||
| 270 | struct kvmppc_pte *pte, bool data) | ||
| 271 | { | ||
| 272 | int r; | ||
| 273 | |||
| 274 | pte->eaddr = eaddr; | ||
| 275 | r = kvmppc_mmu_book3s_32_xlate_bat(vcpu, eaddr, pte, data); | ||
| 276 | if (r < 0) | ||
| 277 | r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte, data, true); | ||
| 278 | if (r < 0) | ||
| 279 | r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte, data, false); | ||
| 280 | |||
| 281 | return r; | ||
| 282 | } | ||
| 283 | |||
| 284 | |||
| 285 | static u32 kvmppc_mmu_book3s_32_mfsrin(struct kvm_vcpu *vcpu, u32 srnum) | ||
| 286 | { | ||
| 287 | return to_book3s(vcpu)->sr[srnum].raw; | ||
| 288 | } | ||
| 289 | |||
| 290 | static void kvmppc_mmu_book3s_32_mtsrin(struct kvm_vcpu *vcpu, u32 srnum, | ||
| 291 | ulong value) | ||
| 292 | { | ||
| 293 | struct kvmppc_sr *sre; | ||
| 294 | |||
| 295 | sre = &to_book3s(vcpu)->sr[srnum]; | ||
| 296 | |||
| 297 | /* Flush any left-over shadows from the previous SR */ | ||
| 298 | |||
| 299 | /* XXX Not necessary? */ | ||
| 300 | /* kvmppc_mmu_pte_flush(vcpu, ((u64)sre->vsid) << 28, 0xf0000000ULL); */ | ||
| 301 | |||
| 302 | /* And then put in the new SR */ | ||
| 303 | sre->raw = value; | ||
| 304 | sre->vsid = (value & 0x0fffffff); | ||
| 305 | sre->Ks = (value & 0x40000000) ? true : false; | ||
| 306 | sre->Kp = (value & 0x20000000) ? true : false; | ||
| 307 | sre->nx = (value & 0x10000000) ? true : false; | ||
| 308 | |||
| 309 | /* Map the new segment */ | ||
| 310 | kvmppc_mmu_map_segment(vcpu, srnum << SID_SHIFT); | ||
| 311 | } | ||
| 312 | |||
| 313 | static void kvmppc_mmu_book3s_32_tlbie(struct kvm_vcpu *vcpu, ulong ea, bool large) | ||
| 314 | { | ||
| 315 | kvmppc_mmu_pte_flush(vcpu, ea, ~0xFFFULL); | ||
| 316 | } | ||
| 317 | |||
| 318 | static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, u64 esid, | ||
| 319 | u64 *vsid) | ||
| 320 | { | ||
| 321 | /* In case we only have one of MSR_IR or MSR_DR set, let's put | ||
| 322 | that in the real-mode context (and hope RM doesn't access | ||
| 323 | high memory) */ | ||
| 324 | switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) { | ||
| 325 | case 0: | ||
| 326 | *vsid = (VSID_REAL >> 16) | esid; | ||
| 327 | break; | ||
| 328 | case MSR_IR: | ||
| 329 | *vsid = (VSID_REAL_IR >> 16) | esid; | ||
| 330 | break; | ||
| 331 | case MSR_DR: | ||
| 332 | *vsid = (VSID_REAL_DR >> 16) | esid; | ||
| 333 | break; | ||
| 334 | case MSR_DR|MSR_IR: | ||
| 335 | { | ||
| 336 | ulong ea; | ||
| 337 | ea = esid << SID_SHIFT; | ||
| 338 | *vsid = find_sr(to_book3s(vcpu), ea)->vsid; | ||
| 339 | break; | ||
| 340 | } | ||
| 341 | default: | ||
| 342 | BUG(); | ||
| 343 | } | ||
| 344 | |||
| 345 | return 0; | ||
| 346 | } | ||
| 347 | |||
| 348 | static bool kvmppc_mmu_book3s_32_is_dcbz32(struct kvm_vcpu *vcpu) | ||
| 349 | { | ||
| 350 | return true; | ||
| 351 | } | ||
| 352 | |||
| 353 | |||
| 354 | void kvmppc_mmu_book3s_32_init(struct kvm_vcpu *vcpu) | ||
| 355 | { | ||
| 356 | struct kvmppc_mmu *mmu = &vcpu->arch.mmu; | ||
| 357 | |||
| 358 | mmu->mtsrin = kvmppc_mmu_book3s_32_mtsrin; | ||
| 359 | mmu->mfsrin = kvmppc_mmu_book3s_32_mfsrin; | ||
| 360 | mmu->xlate = kvmppc_mmu_book3s_32_xlate; | ||
| 361 | mmu->reset_msr = kvmppc_mmu_book3s_32_reset_msr; | ||
| 362 | mmu->tlbie = kvmppc_mmu_book3s_32_tlbie; | ||
| 363 | mmu->esid_to_vsid = kvmppc_mmu_book3s_32_esid_to_vsid; | ||
| 364 | mmu->ea_to_vp = kvmppc_mmu_book3s_32_ea_to_vp; | ||
| 365 | mmu->is_dcbz32 = kvmppc_mmu_book3s_32_is_dcbz32; | ||
| 366 | |||
| 367 | mmu->slbmte = NULL; | ||
| 368 | mmu->slbmfee = NULL; | ||
| 369 | mmu->slbmfev = NULL; | ||
| 370 | mmu->slbie = NULL; | ||
| 371 | mmu->slbia = NULL; | ||
| 372 | } | ||
diff --git a/arch/powerpc/kvm/book3s_64_emulate.c b/arch/powerpc/kvm/book3s_64_emulate.c new file mode 100644 index 000000000000..1027eac6d474 --- /dev/null +++ b/arch/powerpc/kvm/book3s_64_emulate.c | |||
| @@ -0,0 +1,345 @@ | |||
| 1 | /* | ||
| 2 | * This program is free software; you can redistribute it and/or modify | ||
| 3 | * it under the terms of the GNU General Public License, version 2, as | ||
| 4 | * published by the Free Software Foundation. | ||
| 5 | * | ||
| 6 | * This program is distributed in the hope that it will be useful, | ||
| 7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 9 | * GNU General Public License for more details. | ||
| 10 | * | ||
| 11 | * You should have received a copy of the GNU General Public License | ||
| 12 | * along with this program; if not, write to the Free Software | ||
| 13 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 14 | * | ||
| 15 | * Copyright SUSE Linux Products GmbH 2009 | ||
| 16 | * | ||
| 17 | * Authors: Alexander Graf <agraf@suse.de> | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <asm/kvm_ppc.h> | ||
| 21 | #include <asm/disassemble.h> | ||
| 22 | #include <asm/kvm_book3s.h> | ||
| 23 | #include <asm/reg.h> | ||
| 24 | |||
| 25 | #define OP_19_XOP_RFID 18 | ||
| 26 | #define OP_19_XOP_RFI 50 | ||
| 27 | |||
| 28 | #define OP_31_XOP_MFMSR 83 | ||
| 29 | #define OP_31_XOP_MTMSR 146 | ||
| 30 | #define OP_31_XOP_MTMSRD 178 | ||
| 31 | #define OP_31_XOP_MTSRIN 242 | ||
| 32 | #define OP_31_XOP_TLBIEL 274 | ||
| 33 | #define OP_31_XOP_TLBIE 306 | ||
| 34 | #define OP_31_XOP_SLBMTE 402 | ||
| 35 | #define OP_31_XOP_SLBIE 434 | ||
| 36 | #define OP_31_XOP_SLBIA 498 | ||
| 37 | #define OP_31_XOP_MFSRIN 659 | ||
| 38 | #define OP_31_XOP_SLBMFEV 851 | ||
| 39 | #define OP_31_XOP_EIOIO 854 | ||
| 40 | #define OP_31_XOP_SLBMFEE 915 | ||
| 41 | |||
| 42 | /* DCBZ is actually 1014, but we patch it to 1010 so we get a trap */ | ||
| 43 | #define OP_31_XOP_DCBZ 1010 | ||
| 44 | |||
| 45 | int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | ||
| 46 | unsigned int inst, int *advance) | ||
| 47 | { | ||
| 48 | int emulated = EMULATE_DONE; | ||
| 49 | |||
| 50 | switch (get_op(inst)) { | ||
| 51 | case 19: | ||
| 52 | switch (get_xop(inst)) { | ||
| 53 | case OP_19_XOP_RFID: | ||
| 54 | case OP_19_XOP_RFI: | ||
| 55 | vcpu->arch.pc = vcpu->arch.srr0; | ||
| 56 | kvmppc_set_msr(vcpu, vcpu->arch.srr1); | ||
| 57 | *advance = 0; | ||
| 58 | break; | ||
| 59 | |||
| 60 | default: | ||
| 61 | emulated = EMULATE_FAIL; | ||
| 62 | break; | ||
| 63 | } | ||
| 64 | break; | ||
| 65 | case 31: | ||
| 66 | switch (get_xop(inst)) { | ||
| 67 | case OP_31_XOP_MFMSR: | ||
| 68 | vcpu->arch.gpr[get_rt(inst)] = vcpu->arch.msr; | ||
| 69 | break; | ||
| 70 | case OP_31_XOP_MTMSRD: | ||
| 71 | { | ||
| 72 | ulong rs = vcpu->arch.gpr[get_rs(inst)]; | ||
| 73 | if (inst & 0x10000) { | ||
| 74 | vcpu->arch.msr &= ~(MSR_RI | MSR_EE); | ||
| 75 | vcpu->arch.msr |= rs & (MSR_RI | MSR_EE); | ||
| 76 | } else | ||
| 77 | kvmppc_set_msr(vcpu, rs); | ||
| 78 | break; | ||
| 79 | } | ||
| 80 | case OP_31_XOP_MTMSR: | ||
| 81 | kvmppc_set_msr(vcpu, vcpu->arch.gpr[get_rs(inst)]); | ||
| 82 | break; | ||
| 83 | case OP_31_XOP_MFSRIN: | ||
| 84 | { | ||
| 85 | int srnum; | ||
| 86 | |||
| 87 | srnum = (vcpu->arch.gpr[get_rb(inst)] >> 28) & 0xf; | ||
| 88 | if (vcpu->arch.mmu.mfsrin) { | ||
| 89 | u32 sr; | ||
| 90 | sr = vcpu->arch.mmu.mfsrin(vcpu, srnum); | ||
| 91 | vcpu->arch.gpr[get_rt(inst)] = sr; | ||
| 92 | } | ||
| 93 | break; | ||
| 94 | } | ||
| 95 | case OP_31_XOP_MTSRIN: | ||
| 96 | vcpu->arch.mmu.mtsrin(vcpu, | ||
| 97 | (vcpu->arch.gpr[get_rb(inst)] >> 28) & 0xf, | ||
| 98 | vcpu->arch.gpr[get_rs(inst)]); | ||
| 99 | break; | ||
| 100 | case OP_31_XOP_TLBIE: | ||
| 101 | case OP_31_XOP_TLBIEL: | ||
| 102 | { | ||
| 103 | bool large = (inst & 0x00200000) ? true : false; | ||
| 104 | ulong addr = vcpu->arch.gpr[get_rb(inst)]; | ||
| 105 | vcpu->arch.mmu.tlbie(vcpu, addr, large); | ||
| 106 | break; | ||
| 107 | } | ||
| 108 | case OP_31_XOP_EIOIO: | ||
| 109 | break; | ||
| 110 | case OP_31_XOP_SLBMTE: | ||
| 111 | if (!vcpu->arch.mmu.slbmte) | ||
| 112 | return EMULATE_FAIL; | ||
| 113 | |||
| 114 | vcpu->arch.mmu.slbmte(vcpu, vcpu->arch.gpr[get_rs(inst)], | ||
| 115 | vcpu->arch.gpr[get_rb(inst)]); | ||
| 116 | break; | ||
| 117 | case OP_31_XOP_SLBIE: | ||
| 118 | if (!vcpu->arch.mmu.slbie) | ||
| 119 | return EMULATE_FAIL; | ||
| 120 | |||
| 121 | vcpu->arch.mmu.slbie(vcpu, vcpu->arch.gpr[get_rb(inst)]); | ||
| 122 | break; | ||
| 123 | case OP_31_XOP_SLBIA: | ||
| 124 | if (!vcpu->arch.mmu.slbia) | ||
| 125 | return EMULATE_FAIL; | ||
| 126 | |||
| 127 | vcpu->arch.mmu.slbia(vcpu); | ||
| 128 | break; | ||
| 129 | case OP_31_XOP_SLBMFEE: | ||
| 130 | if (!vcpu->arch.mmu.slbmfee) { | ||
| 131 | emulated = EMULATE_FAIL; | ||
| 132 | } else { | ||
| 133 | ulong t, rb; | ||
| 134 | |||
| 135 | rb = vcpu->arch.gpr[get_rb(inst)]; | ||
| 136 | t = vcpu->arch.mmu.slbmfee(vcpu, rb); | ||
| 137 | vcpu->arch.gpr[get_rt(inst)] = t; | ||
| 138 | } | ||
| 139 | break; | ||
| 140 | case OP_31_XOP_SLBMFEV: | ||
| 141 | if (!vcpu->arch.mmu.slbmfev) { | ||
| 142 | emulated = EMULATE_FAIL; | ||
| 143 | } else { | ||
| 144 | ulong t, rb; | ||
| 145 | |||
| 146 | rb = vcpu->arch.gpr[get_rb(inst)]; | ||
| 147 | t = vcpu->arch.mmu.slbmfev(vcpu, rb); | ||
| 148 | vcpu->arch.gpr[get_rt(inst)] = t; | ||
| 149 | } | ||
| 150 | break; | ||
| 151 | case OP_31_XOP_DCBZ: | ||
| 152 | { | ||
| 153 | ulong rb = vcpu->arch.gpr[get_rb(inst)]; | ||
| 154 | ulong ra = 0; | ||
| 155 | ulong addr; | ||
| 156 | u32 zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 157 | |||
| 158 | if (get_ra(inst)) | ||
| 159 | ra = vcpu->arch.gpr[get_ra(inst)]; | ||
| 160 | |||
| 161 | addr = (ra + rb) & ~31ULL; | ||
| 162 | if (!(vcpu->arch.msr & MSR_SF)) | ||
| 163 | addr &= 0xffffffff; | ||
| 164 | |||
| 165 | if (kvmppc_st(vcpu, addr, 32, zeros)) { | ||
| 166 | vcpu->arch.dear = addr; | ||
| 167 | vcpu->arch.fault_dear = addr; | ||
| 168 | to_book3s(vcpu)->dsisr = DSISR_PROTFAULT | | ||
| 169 | DSISR_ISSTORE; | ||
| 170 | kvmppc_book3s_queue_irqprio(vcpu, | ||
| 171 | BOOK3S_INTERRUPT_DATA_STORAGE); | ||
| 172 | kvmppc_mmu_pte_flush(vcpu, addr, ~0xFFFULL); | ||
| 173 | } | ||
| 174 | |||
| 175 | break; | ||
| 176 | } | ||
| 177 | default: | ||
| 178 | emulated = EMULATE_FAIL; | ||
| 179 | } | ||
| 180 | break; | ||
| 181 | default: | ||
| 182 | emulated = EMULATE_FAIL; | ||
| 183 | } | ||
| 184 | |||
| 185 | return emulated; | ||
| 186 | } | ||
| 187 | |||
| 188 | void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat, bool upper, | ||
| 189 | u32 val) | ||
| 190 | { | ||
| 191 | if (upper) { | ||
| 192 | /* Upper BAT */ | ||
| 193 | u32 bl = (val >> 2) & 0x7ff; | ||
| 194 | bat->bepi_mask = (~bl << 17); | ||
| 195 | bat->bepi = val & 0xfffe0000; | ||
| 196 | bat->vs = (val & 2) ? 1 : 0; | ||
| 197 | bat->vp = (val & 1) ? 1 : 0; | ||
| 198 | bat->raw = (bat->raw & 0xffffffff00000000ULL) | val; | ||
| 199 | } else { | ||
| 200 | /* Lower BAT */ | ||
| 201 | bat->brpn = val & 0xfffe0000; | ||
| 202 | bat->wimg = (val >> 3) & 0xf; | ||
| 203 | bat->pp = val & 3; | ||
| 204 | bat->raw = (bat->raw & 0x00000000ffffffffULL) | ((u64)val << 32); | ||
| 205 | } | ||
| 206 | } | ||
| 207 | |||
| 208 | static void kvmppc_write_bat(struct kvm_vcpu *vcpu, int sprn, u32 val) | ||
| 209 | { | ||
| 210 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | ||
| 211 | struct kvmppc_bat *bat; | ||
| 212 | |||
| 213 | switch (sprn) { | ||
| 214 | case SPRN_IBAT0U ... SPRN_IBAT3L: | ||
| 215 | bat = &vcpu_book3s->ibat[(sprn - SPRN_IBAT0U) / 2]; | ||
| 216 | break; | ||
| 217 | case SPRN_IBAT4U ... SPRN_IBAT7L: | ||
| 218 | bat = &vcpu_book3s->ibat[(sprn - SPRN_IBAT4U) / 2]; | ||
| 219 | break; | ||
| 220 | case SPRN_DBAT0U ... SPRN_DBAT3L: | ||
| 221 | bat = &vcpu_book3s->dbat[(sprn - SPRN_DBAT0U) / 2]; | ||
| 222 | break; | ||
| 223 | case SPRN_DBAT4U ... SPRN_DBAT7L: | ||
| 224 | bat = &vcpu_book3s->dbat[(sprn - SPRN_DBAT4U) / 2]; | ||
| 225 | break; | ||
| 226 | default: | ||
| 227 | BUG(); | ||
| 228 | } | ||
| 229 | |||
| 230 | kvmppc_set_bat(vcpu, bat, !(sprn % 2), val); | ||
| 231 | } | ||
| 232 | |||
| 233 | int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) | ||
| 234 | { | ||
| 235 | int emulated = EMULATE_DONE; | ||
| 236 | |||
| 237 | switch (sprn) { | ||
| 238 | case SPRN_SDR1: | ||
| 239 | to_book3s(vcpu)->sdr1 = vcpu->arch.gpr[rs]; | ||
| 240 | break; | ||
| 241 | case SPRN_DSISR: | ||
| 242 | to_book3s(vcpu)->dsisr = vcpu->arch.gpr[rs]; | ||
| 243 | break; | ||
| 244 | case SPRN_DAR: | ||
| 245 | vcpu->arch.dear = vcpu->arch.gpr[rs]; | ||
| 246 | break; | ||
| 247 | case SPRN_HIOR: | ||
| 248 | to_book3s(vcpu)->hior = vcpu->arch.gpr[rs]; | ||
| 249 | break; | ||
| 250 | case SPRN_IBAT0U ... SPRN_IBAT3L: | ||
| 251 | case SPRN_IBAT4U ... SPRN_IBAT7L: | ||
| 252 | case SPRN_DBAT0U ... SPRN_DBAT3L: | ||
| 253 | case SPRN_DBAT4U ... SPRN_DBAT7L: | ||
| 254 | kvmppc_write_bat(vcpu, sprn, (u32)vcpu->arch.gpr[rs]); | ||
| 255 | /* BAT writes happen so rarely that we're ok to flush | ||
| 256 | * everything here */ | ||
| 257 | kvmppc_mmu_pte_flush(vcpu, 0, 0); | ||
| 258 | break; | ||
| 259 | case SPRN_HID0: | ||
| 260 | to_book3s(vcpu)->hid[0] = vcpu->arch.gpr[rs]; | ||
| 261 | break; | ||
| 262 | case SPRN_HID1: | ||
| 263 | to_book3s(vcpu)->hid[1] = vcpu->arch.gpr[rs]; | ||
| 264 | break; | ||
| 265 | case SPRN_HID2: | ||
| 266 | to_book3s(vcpu)->hid[2] = vcpu->arch.gpr[rs]; | ||
| 267 | break; | ||
| 268 | case SPRN_HID4: | ||
| 269 | to_book3s(vcpu)->hid[4] = vcpu->arch.gpr[rs]; | ||
| 270 | break; | ||
| 271 | case SPRN_HID5: | ||
| 272 | to_book3s(vcpu)->hid[5] = vcpu->arch.gpr[rs]; | ||
| 273 | /* guest HID5 set can change is_dcbz32 */ | ||
| 274 | if (vcpu->arch.mmu.is_dcbz32(vcpu) && | ||
| 275 | (mfmsr() & MSR_HV)) | ||
| 276 | vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32; | ||
| 277 | break; | ||
| 278 | case SPRN_ICTC: | ||
| 279 | case SPRN_THRM1: | ||
| 280 | case SPRN_THRM2: | ||
| 281 | case SPRN_THRM3: | ||
| 282 | case SPRN_CTRLF: | ||
| 283 | case SPRN_CTRLT: | ||
| 284 | break; | ||
| 285 | default: | ||
| 286 | printk(KERN_INFO "KVM: invalid SPR write: %d\n", sprn); | ||
| 287 | #ifndef DEBUG_SPR | ||
| 288 | emulated = EMULATE_FAIL; | ||
| 289 | #endif | ||
| 290 | break; | ||
| 291 | } | ||
| 292 | |||
| 293 | return emulated; | ||
| 294 | } | ||
| 295 | |||
| 296 | int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) | ||
| 297 | { | ||
| 298 | int emulated = EMULATE_DONE; | ||
| 299 | |||
| 300 | switch (sprn) { | ||
| 301 | case SPRN_SDR1: | ||
| 302 | vcpu->arch.gpr[rt] = to_book3s(vcpu)->sdr1; | ||
| 303 | break; | ||
| 304 | case SPRN_DSISR: | ||
| 305 | vcpu->arch.gpr[rt] = to_book3s(vcpu)->dsisr; | ||
| 306 | break; | ||
| 307 | case SPRN_DAR: | ||
| 308 | vcpu->arch.gpr[rt] = vcpu->arch.dear; | ||
| 309 | break; | ||
| 310 | case SPRN_HIOR: | ||
| 311 | vcpu->arch.gpr[rt] = to_book3s(vcpu)->hior; | ||
| 312 | break; | ||
| 313 | case SPRN_HID0: | ||
| 314 | vcpu->arch.gpr[rt] = to_book3s(vcpu)->hid[0]; | ||
| 315 | break; | ||
| 316 | case SPRN_HID1: | ||
| 317 | vcpu->arch.gpr[rt] = to_book3s(vcpu)->hid[1]; | ||
| 318 | break; | ||
| 319 | case SPRN_HID2: | ||
| 320 | vcpu->arch.gpr[rt] = to_book3s(vcpu)->hid[2]; | ||
| 321 | break; | ||
| 322 | case SPRN_HID4: | ||
| 323 | vcpu->arch.gpr[rt] = to_book3s(vcpu)->hid[4]; | ||
| 324 | break; | ||
| 325 | case SPRN_HID5: | ||
| 326 | vcpu->arch.gpr[rt] = to_book3s(vcpu)->hid[5]; | ||
| 327 | break; | ||
| 328 | case SPRN_THRM1: | ||
| 329 | case SPRN_THRM2: | ||
| 330 | case SPRN_THRM3: | ||
| 331 | case SPRN_CTRLF: | ||
| 332 | case SPRN_CTRLT: | ||
| 333 | vcpu->arch.gpr[rt] = 0; | ||
| 334 | break; | ||
| 335 | default: | ||
| 336 | printk(KERN_INFO "KVM: invalid SPR read: %d\n", sprn); | ||
| 337 | #ifndef DEBUG_SPR | ||
| 338 | emulated = EMULATE_FAIL; | ||
| 339 | #endif | ||
| 340 | break; | ||
| 341 | } | ||
| 342 | |||
| 343 | return emulated; | ||
| 344 | } | ||
| 345 | |||
diff --git a/arch/powerpc/kvm/book3s_64_exports.c b/arch/powerpc/kvm/book3s_64_exports.c new file mode 100644 index 000000000000..5b2db38ed86c --- /dev/null +++ b/arch/powerpc/kvm/book3s_64_exports.c | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | /* | ||
| 2 | * This program is free software; you can redistribute it and/or modify | ||
| 3 | * it under the terms of the GNU General Public License, version 2, as | ||
| 4 | * published by the Free Software Foundation. | ||
| 5 | * | ||
| 6 | * This program is distributed in the hope that it will be useful, | ||
| 7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 9 | * GNU General Public License for more details. | ||
| 10 | * | ||
| 11 | * You should have received a copy of the GNU General Public License | ||
| 12 | * along with this program; if not, write to the Free Software | ||
| 13 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 14 | * | ||
| 15 | * Copyright SUSE Linux Products GmbH 2009 | ||
| 16 | * | ||
| 17 | * Authors: Alexander Graf <agraf@suse.de> | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/module.h> | ||
| 21 | #include <asm/kvm_book3s.h> | ||
| 22 | |||
| 23 | EXPORT_SYMBOL_GPL(kvmppc_trampoline_enter); | ||
| 24 | EXPORT_SYMBOL_GPL(kvmppc_trampoline_lowmem); | ||
diff --git a/arch/powerpc/kvm/book3s_64_interrupts.S b/arch/powerpc/kvm/book3s_64_interrupts.S new file mode 100644 index 000000000000..7b55d8094c8b --- /dev/null +++ b/arch/powerpc/kvm/book3s_64_interrupts.S | |||
| @@ -0,0 +1,392 @@ | |||
| 1 | /* | ||
| 2 | * This program is free software; you can redistribute it and/or modify | ||
| 3 | * it under the terms of the GNU General Public License, version 2, as | ||
| 4 | * published by the Free Software Foundation. | ||
| 5 | * | ||
| 6 | * This program is distributed in the hope that it will be useful, | ||
| 7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 9 | * GNU General Public License for more details. | ||
| 10 | * | ||
| 11 | * You should have received a copy of the GNU General Public License | ||
| 12 | * along with this program; if not, write to the Free Software | ||
| 13 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 14 | * | ||
| 15 | * Copyright SUSE Linux Products GmbH 2009 | ||
| 16 | * | ||
| 17 | * Authors: Alexander Graf <agraf@suse.de> | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <asm/ppc_asm.h> | ||
| 21 | #include <asm/kvm_asm.h> | ||
| 22 | #include <asm/reg.h> | ||
| 23 | #include <asm/page.h> | ||
| 24 | #include <asm/asm-offsets.h> | ||
| 25 | #include <asm/exception-64s.h> | ||
| 26 | |||
| 27 | #define KVMPPC_HANDLE_EXIT .kvmppc_handle_exit | ||
| 28 | #define ULONG_SIZE 8 | ||
| 29 | #define VCPU_GPR(n) (VCPU_GPRS + (n * ULONG_SIZE)) | ||
| 30 | |||
| 31 | .macro mfpaca tmp_reg, src_reg, offset, vcpu_reg | ||
| 32 | ld \tmp_reg, (PACA_EXMC+\offset)(r13) | ||
| 33 | std \tmp_reg, VCPU_GPR(\src_reg)(\vcpu_reg) | ||
| 34 | .endm | ||
| 35 | |||
| 36 | .macro DISABLE_INTERRUPTS | ||
| 37 | mfmsr r0 | ||
| 38 | rldicl r0,r0,48,1 | ||
| 39 | rotldi r0,r0,16 | ||
| 40 | mtmsrd r0,1 | ||
| 41 | .endm | ||
| 42 | |||
| 43 | /***************************************************************************** | ||
| 44 | * * | ||
| 45 | * Guest entry / exit code that is in kernel module memory (highmem) * | ||
| 46 | * * | ||
| 47 | ****************************************************************************/ | ||
| 48 | |||
| 49 | /* Registers: | ||
| 50 | * r3: kvm_run pointer | ||
| 51 | * r4: vcpu pointer | ||
| 52 | */ | ||
| 53 | _GLOBAL(__kvmppc_vcpu_entry) | ||
| 54 | |||
| 55 | kvm_start_entry: | ||
| 56 | /* Write correct stack frame */ | ||
| 57 | mflr r0 | ||
| 58 | std r0,16(r1) | ||
| 59 | |||
| 60 | /* Save host state to the stack */ | ||
| 61 | stdu r1, -SWITCH_FRAME_SIZE(r1) | ||
| 62 | |||
| 63 | /* Save r3 (kvm_run) and r4 (vcpu) */ | ||
| 64 | SAVE_2GPRS(3, r1) | ||
| 65 | |||
| 66 | /* Save non-volatile registers (r14 - r31) */ | ||
| 67 | SAVE_NVGPRS(r1) | ||
| 68 | |||
| 69 | /* Save LR */ | ||
| 70 | mflr r14 | ||
| 71 | std r14, _LINK(r1) | ||
| 72 | |||
| 73 | /* XXX optimize non-volatile loading away */ | ||
| 74 | kvm_start_lightweight: | ||
| 75 | |||
| 76 | DISABLE_INTERRUPTS | ||
| 77 | |||
| 78 | /* Save R1/R2 in the PACA */ | ||
| 79 | std r1, PACAR1(r13) | ||
| 80 | std r2, (PACA_EXMC+EX_SRR0)(r13) | ||
| 81 | ld r3, VCPU_HIGHMEM_HANDLER(r4) | ||
| 82 | std r3, PACASAVEDMSR(r13) | ||
| 83 | |||
| 84 | /* Load non-volatile guest state from the vcpu */ | ||
| 85 | ld r14, VCPU_GPR(r14)(r4) | ||
| 86 | ld r15, VCPU_GPR(r15)(r4) | ||
| 87 | ld r16, VCPU_GPR(r16)(r4) | ||
| 88 | ld r17, VCPU_GPR(r17)(r4) | ||
| 89 | ld r18, VCPU_GPR(r18)(r4) | ||
| 90 | ld r19, VCPU_GPR(r19)(r4) | ||
| 91 | ld r20, VCPU_GPR(r20)(r4) | ||
| 92 | ld r21, VCPU_GPR(r21)(r4) | ||
| 93 | ld r22, VCPU_GPR(r22)(r4) | ||
| 94 | ld r23, VCPU_GPR(r23)(r4) | ||
| 95 | ld r24, VCPU_GPR(r24)(r4) | ||
| 96 | ld r25, VCPU_GPR(r25)(r4) | ||
| 97 | ld r26, VCPU_GPR(r26)(r4) | ||
| 98 | ld r27, VCPU_GPR(r27)(r4) | ||
| 99 | ld r28, VCPU_GPR(r28)(r4) | ||
| 100 | ld r29, VCPU_GPR(r29)(r4) | ||
| 101 | ld r30, VCPU_GPR(r30)(r4) | ||
| 102 | ld r31, VCPU_GPR(r31)(r4) | ||
| 103 | |||
| 104 | ld r9, VCPU_PC(r4) /* r9 = vcpu->arch.pc */ | ||
| 105 | ld r10, VCPU_SHADOW_MSR(r4) /* r10 = vcpu->arch.shadow_msr */ | ||
| 106 | |||
| 107 | ld r3, VCPU_TRAMPOLINE_ENTER(r4) | ||
| 108 | mtsrr0 r3 | ||
| 109 | |||
| 110 | LOAD_REG_IMMEDIATE(r3, MSR_KERNEL & ~(MSR_IR | MSR_DR)) | ||
| 111 | mtsrr1 r3 | ||
| 112 | |||
| 113 | /* Load guest state in the respective registers */ | ||
| 114 | lwz r3, VCPU_CR(r4) /* r3 = vcpu->arch.cr */ | ||
| 115 | stw r3, (PACA_EXMC + EX_CCR)(r13) | ||
| 116 | |||
| 117 | ld r3, VCPU_CTR(r4) /* r3 = vcpu->arch.ctr */ | ||
| 118 | mtctr r3 /* CTR = r3 */ | ||
| 119 | |||
| 120 | ld r3, VCPU_LR(r4) /* r3 = vcpu->arch.lr */ | ||
| 121 | mtlr r3 /* LR = r3 */ | ||
| 122 | |||
| 123 | ld r3, VCPU_XER(r4) /* r3 = vcpu->arch.xer */ | ||
| 124 | std r3, (PACA_EXMC + EX_R3)(r13) | ||
| 125 | |||
| 126 | /* Some guests may need to have dcbz set to 32 byte length. | ||
| 127 | * | ||
| 128 | * Usually we ensure that by patching the guest's instructions | ||
| 129 | * to trap on dcbz and emulate it in the hypervisor. | ||
| 130 | * | ||
| 131 | * If we can, we should tell the CPU to use 32 byte dcbz though, | ||
| 132 | * because that's a lot faster. | ||
| 133 | */ | ||
| 134 | |||
| 135 | ld r3, VCPU_HFLAGS(r4) | ||
| 136 | rldicl. r3, r3, 0, 63 /* CR = ((r3 & 1) == 0) */ | ||
| 137 | beq no_dcbz32_on | ||
| 138 | |||
| 139 | mfspr r3,SPRN_HID5 | ||
| 140 | ori r3, r3, 0x80 /* XXX HID5_dcbz32 = 0x80 */ | ||
| 141 | mtspr SPRN_HID5,r3 | ||
| 142 | |||
| 143 | no_dcbz32_on: | ||
| 144 | /* Load guest GPRs */ | ||
| 145 | |||
| 146 | ld r3, VCPU_GPR(r9)(r4) | ||
| 147 | std r3, (PACA_EXMC + EX_R9)(r13) | ||
| 148 | ld r3, VCPU_GPR(r10)(r4) | ||
| 149 | std r3, (PACA_EXMC + EX_R10)(r13) | ||
| 150 | ld r3, VCPU_GPR(r11)(r4) | ||
| 151 | std r3, (PACA_EXMC + EX_R11)(r13) | ||
| 152 | ld r3, VCPU_GPR(r12)(r4) | ||
| 153 | std r3, (PACA_EXMC + EX_R12)(r13) | ||
| 154 | ld r3, VCPU_GPR(r13)(r4) | ||
| 155 | std r3, (PACA_EXMC + EX_R13)(r13) | ||
| 156 | |||
| 157 | ld r0, VCPU_GPR(r0)(r4) | ||
| 158 | ld r1, VCPU_GPR(r1)(r4) | ||
| 159 | ld r2, VCPU_GPR(r2)(r4) | ||
| 160 | ld r3, VCPU_GPR(r3)(r4) | ||
| 161 | ld r5, VCPU_GPR(r5)(r4) | ||
| 162 | ld r6, VCPU_GPR(r6)(r4) | ||
| 163 | ld r7, VCPU_GPR(r7)(r4) | ||
| 164 | ld r8, VCPU_GPR(r8)(r4) | ||
| 165 | ld r4, VCPU_GPR(r4)(r4) | ||
| 166 | |||
| 167 | /* This sets the Magic value for the trampoline */ | ||
| 168 | |||
| 169 | li r11, 1 | ||
| 170 | stb r11, PACA_KVM_IN_GUEST(r13) | ||
| 171 | |||
| 172 | /* Jump to SLB patching handlder and into our guest */ | ||
| 173 | RFI | ||
| 174 | |||
| 175 | /* | ||
| 176 | * This is the handler in module memory. It gets jumped at from the | ||
| 177 | * lowmem trampoline code, so it's basically the guest exit code. | ||
| 178 | * | ||
| 179 | */ | ||
| 180 | |||
| 181 | .global kvmppc_handler_highmem | ||
| 182 | kvmppc_handler_highmem: | ||
| 183 | |||
| 184 | /* | ||
| 185 | * Register usage at this point: | ||
| 186 | * | ||
| 187 | * R00 = guest R13 | ||
| 188 | * R01 = host R1 | ||
| 189 | * R02 = host R2 | ||
| 190 | * R10 = guest PC | ||
| 191 | * R11 = guest MSR | ||
| 192 | * R12 = exit handler id | ||
| 193 | * R13 = PACA | ||
| 194 | * PACA.exmc.R9 = guest R1 | ||
| 195 | * PACA.exmc.R10 = guest R10 | ||
| 196 | * PACA.exmc.R11 = guest R11 | ||
| 197 | * PACA.exmc.R12 = guest R12 | ||
| 198 | * PACA.exmc.R13 = guest R2 | ||
| 199 | * PACA.exmc.DAR = guest DAR | ||
| 200 | * PACA.exmc.DSISR = guest DSISR | ||
| 201 | * PACA.exmc.LR = guest instruction | ||
| 202 | * PACA.exmc.CCR = guest CR | ||
| 203 | * PACA.exmc.SRR0 = guest R0 | ||
| 204 | * | ||
| 205 | */ | ||
| 206 | |||
| 207 | std r3, (PACA_EXMC+EX_R3)(r13) | ||
| 208 | |||
| 209 | /* save the exit id in R3 */ | ||
| 210 | mr r3, r12 | ||
| 211 | |||
| 212 | /* R12 = vcpu */ | ||
| 213 | ld r12, GPR4(r1) | ||
| 214 | |||
| 215 | /* Now save the guest state */ | ||
| 216 | |||
| 217 | std r0, VCPU_GPR(r13)(r12) | ||
| 218 | std r4, VCPU_GPR(r4)(r12) | ||
| 219 | std r5, VCPU_GPR(r5)(r12) | ||
| 220 | std r6, VCPU_GPR(r6)(r12) | ||
| 221 | std r7, VCPU_GPR(r7)(r12) | ||
| 222 | std r8, VCPU_GPR(r8)(r12) | ||
| 223 | std r9, VCPU_GPR(r9)(r12) | ||
| 224 | |||
| 225 | /* get registers from PACA */ | ||
| 226 | mfpaca r5, r0, EX_SRR0, r12 | ||
| 227 | mfpaca r5, r3, EX_R3, r12 | ||
| 228 | mfpaca r5, r1, EX_R9, r12 | ||
| 229 | mfpaca r5, r10, EX_R10, r12 | ||
| 230 | mfpaca r5, r11, EX_R11, r12 | ||
| 231 | mfpaca r5, r12, EX_R12, r12 | ||
| 232 | mfpaca r5, r2, EX_R13, r12 | ||
| 233 | |||
| 234 | lwz r5, (PACA_EXMC+EX_LR)(r13) | ||
| 235 | stw r5, VCPU_LAST_INST(r12) | ||
| 236 | |||
| 237 | lwz r5, (PACA_EXMC+EX_CCR)(r13) | ||
| 238 | stw r5, VCPU_CR(r12) | ||
| 239 | |||
| 240 | ld r5, VCPU_HFLAGS(r12) | ||
| 241 | rldicl. r5, r5, 0, 63 /* CR = ((r5 & 1) == 0) */ | ||
| 242 | beq no_dcbz32_off | ||
| 243 | |||
| 244 | mfspr r5,SPRN_HID5 | ||
| 245 | rldimi r5,r5,6,56 | ||
| 246 | mtspr SPRN_HID5,r5 | ||
| 247 | |||
| 248 | no_dcbz32_off: | ||
| 249 | |||
| 250 | /* XXX maybe skip on lightweight? */ | ||
| 251 | std r14, VCPU_GPR(r14)(r12) | ||
| 252 | std r15, VCPU_GPR(r15)(r12) | ||
| 253 | std r16, VCPU_GPR(r16)(r12) | ||
| 254 | std r17, VCPU_GPR(r17)(r12) | ||
| 255 | std r18, VCPU_GPR(r18)(r12) | ||
| 256 | std r19, VCPU_GPR(r19)(r12) | ||
| 257 | std r20, VCPU_GPR(r20)(r12) | ||
| 258 | std r21, VCPU_GPR(r21)(r12) | ||
| 259 | std r22, VCPU_GPR(r22)(r12) | ||
| 260 | std r23, VCPU_GPR(r23)(r12) | ||
| 261 | std r24, VCPU_GPR(r24)(r12) | ||
| 262 | std r25, VCPU_GPR(r25)(r12) | ||
| 263 | std r26, VCPU_GPR(r26)(r12) | ||
| 264 | std r27, VCPU_GPR(r27)(r12) | ||
| 265 | std r28, VCPU_GPR(r28)(r12) | ||
| 266 | std r29, VCPU_GPR(r29)(r12) | ||
| 267 | std r30, VCPU_GPR(r30)(r12) | ||
| 268 | std r31, VCPU_GPR(r31)(r12) | ||
| 269 | |||
| 270 | /* Restore non-volatile host registers (r14 - r31) */ | ||
| 271 | REST_NVGPRS(r1) | ||
| 272 | |||
| 273 | /* Save guest PC (R10) */ | ||
| 274 | std r10, VCPU_PC(r12) | ||
| 275 | |||
| 276 | /* Save guest msr (R11) */ | ||
| 277 | std r11, VCPU_SHADOW_MSR(r12) | ||
| 278 | |||
| 279 | /* Save guest CTR (in R12) */ | ||
| 280 | mfctr r5 | ||
| 281 | std r5, VCPU_CTR(r12) | ||
| 282 | |||
| 283 | /* Save guest LR */ | ||
| 284 | mflr r5 | ||
| 285 | std r5, VCPU_LR(r12) | ||
| 286 | |||
| 287 | /* Save guest XER */ | ||
| 288 | mfxer r5 | ||
| 289 | std r5, VCPU_XER(r12) | ||
| 290 | |||
| 291 | /* Save guest DAR */ | ||
| 292 | ld r5, (PACA_EXMC+EX_DAR)(r13) | ||
| 293 | std r5, VCPU_FAULT_DEAR(r12) | ||
| 294 | |||
| 295 | /* Save guest DSISR */ | ||
| 296 | lwz r5, (PACA_EXMC+EX_DSISR)(r13) | ||
| 297 | std r5, VCPU_FAULT_DSISR(r12) | ||
| 298 | |||
| 299 | /* Restore host msr -> SRR1 */ | ||
| 300 | ld r7, VCPU_HOST_MSR(r12) | ||
| 301 | mtsrr1 r7 | ||
| 302 | |||
| 303 | /* Restore host IP -> SRR0 */ | ||
| 304 | ld r6, VCPU_HOST_RETIP(r12) | ||
| 305 | mtsrr0 r6 | ||
| 306 | |||
| 307 | /* | ||
| 308 | * For some interrupts, we need to call the real Linux | ||
| 309 | * handler, so it can do work for us. This has to happen | ||
| 310 | * as if the interrupt arrived from the kernel though, | ||
| 311 | * so let's fake it here where most state is restored. | ||
| 312 | * | ||
| 313 | * Call Linux for hardware interrupts/decrementer | ||
| 314 | * r3 = address of interrupt handler (exit reason) | ||
| 315 | */ | ||
| 316 | |||
| 317 | cmpwi r3, BOOK3S_INTERRUPT_EXTERNAL | ||
| 318 | beq call_linux_handler | ||
| 319 | cmpwi r3, BOOK3S_INTERRUPT_DECREMENTER | ||
| 320 | beq call_linux_handler | ||
| 321 | |||
| 322 | /* Back to Interruptable Mode! (goto kvm_return_point) */ | ||
| 323 | RFI | ||
| 324 | |||
| 325 | call_linux_handler: | ||
| 326 | |||
| 327 | /* | ||
| 328 | * If we land here we need to jump back to the handler we | ||
| 329 | * came from. | ||
| 330 | * | ||
| 331 | * We have a page that we can access from real mode, so let's | ||
| 332 | * jump back to that and use it as a trampoline to get back into the | ||
| 333 | * interrupt handler! | ||
| 334 | * | ||
| 335 | * R3 still contains the exit code, | ||
| 336 | * R6 VCPU_HOST_RETIP and | ||
| 337 | * R7 VCPU_HOST_MSR | ||
| 338 | */ | ||
| 339 | |||
| 340 | mtlr r3 | ||
| 341 | |||
| 342 | ld r5, VCPU_TRAMPOLINE_LOWMEM(r12) | ||
| 343 | mtsrr0 r5 | ||
| 344 | LOAD_REG_IMMEDIATE(r5, MSR_KERNEL & ~(MSR_IR | MSR_DR)) | ||
| 345 | mtsrr1 r5 | ||
| 346 | |||
| 347 | RFI | ||
| 348 | |||
| 349 | .global kvm_return_point | ||
| 350 | kvm_return_point: | ||
| 351 | |||
| 352 | /* Jump back to lightweight entry if we're supposed to */ | ||
| 353 | /* go back into the guest */ | ||
| 354 | mr r5, r3 | ||
| 355 | /* Restore r3 (kvm_run) and r4 (vcpu) */ | ||
| 356 | REST_2GPRS(3, r1) | ||
| 357 | bl KVMPPC_HANDLE_EXIT | ||
| 358 | |||
| 359 | #if 0 /* XXX get lightweight exits back */ | ||
| 360 | cmpwi r3, RESUME_GUEST | ||
| 361 | bne kvm_exit_heavyweight | ||
| 362 | |||
| 363 | /* put VCPU and KVM_RUN back into place and roll again! */ | ||
| 364 | REST_2GPRS(3, r1) | ||
| 365 | b kvm_start_lightweight | ||
| 366 | |||
| 367 | kvm_exit_heavyweight: | ||
| 368 | /* Restore non-volatile host registers */ | ||
| 369 | ld r14, _LINK(r1) | ||
| 370 | mtlr r14 | ||
| 371 | REST_NVGPRS(r1) | ||
| 372 | |||
| 373 | addi r1, r1, SWITCH_FRAME_SIZE | ||
| 374 | #else | ||
| 375 | ld r4, _LINK(r1) | ||
| 376 | mtlr r4 | ||
| 377 | |||
| 378 | cmpwi r3, RESUME_GUEST | ||
| 379 | bne kvm_exit_heavyweight | ||
| 380 | |||
| 381 | REST_2GPRS(3, r1) | ||
| 382 | |||
| 383 | addi r1, r1, SWITCH_FRAME_SIZE | ||
| 384 | |||
| 385 | b kvm_start_entry | ||
| 386 | |||
| 387 | kvm_exit_heavyweight: | ||
| 388 | |||
| 389 | addi r1, r1, SWITCH_FRAME_SIZE | ||
| 390 | #endif | ||
| 391 | |||
| 392 | blr | ||
diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c new file mode 100644 index 000000000000..e4beeb371a73 --- /dev/null +++ b/arch/powerpc/kvm/book3s_64_mmu.c | |||
| @@ -0,0 +1,498 @@ | |||
| 1 | /* | ||
| 2 | * This program is free software; you can redistribute it and/or modify | ||
| 3 | * it under the terms of the GNU General Public License, version 2, as | ||
| 4 | * published by the Free Software Foundation. | ||
| 5 | * | ||
| 6 | * This program is distributed in the hope that it will be useful, | ||
| 7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 9 | * GNU General Public License for more details. | ||
| 10 | * | ||
| 11 | * You should have received a copy of the GNU General Public License | ||
| 12 | * along with this program; if not, write to the Free Software | ||
| 13 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 14 | * | ||
| 15 | * Copyright SUSE Linux Products GmbH 2009 | ||
| 16 | * | ||
| 17 | * Authors: Alexander Graf <agraf@suse.de> | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/types.h> | ||
| 21 | #include <linux/string.h> | ||
| 22 | #include <linux/kvm.h> | ||
| 23 | #include <linux/kvm_host.h> | ||
| 24 | #include <linux/highmem.h> | ||
| 25 | |||
| 26 | #include <asm/tlbflush.h> | ||
| 27 | #include <asm/kvm_ppc.h> | ||
| 28 | #include <asm/kvm_book3s.h> | ||
| 29 | |||
| 30 | /* #define DEBUG_MMU */ | ||
| 31 | |||
| 32 | #ifdef DEBUG_MMU | ||
| 33 | #define dprintk(X...) printk(KERN_INFO X) | ||
| 34 | #else | ||
| 35 | #define dprintk(X...) do { } while(0) | ||
| 36 | #endif | ||
| 37 | |||
| 38 | static void kvmppc_mmu_book3s_64_reset_msr(struct kvm_vcpu *vcpu) | ||
| 39 | { | ||
| 40 | kvmppc_set_msr(vcpu, MSR_SF); | ||
| 41 | } | ||
| 42 | |||
| 43 | static struct kvmppc_slb *kvmppc_mmu_book3s_64_find_slbe( | ||
| 44 | struct kvmppc_vcpu_book3s *vcpu_book3s, | ||
| 45 | gva_t eaddr) | ||
| 46 | { | ||
| 47 | int i; | ||
| 48 | u64 esid = GET_ESID(eaddr); | ||
| 49 | u64 esid_1t = GET_ESID_1T(eaddr); | ||
| 50 | |||
| 51 | for (i = 0; i < vcpu_book3s->slb_nr; i++) { | ||
| 52 | u64 cmp_esid = esid; | ||
| 53 | |||
| 54 | if (!vcpu_book3s->slb[i].valid) | ||
| 55 | continue; | ||
| 56 | |||
| 57 | if (vcpu_book3s->slb[i].large) | ||
| 58 | cmp_esid = esid_1t; | ||
| 59 | |||
| 60 | if (vcpu_book3s->slb[i].esid == cmp_esid) | ||
| 61 | return &vcpu_book3s->slb[i]; | ||
| 62 | } | ||
| 63 | |||
| 64 | dprintk("KVM: No SLB entry found for 0x%lx [%llx | %llx]\n", | ||
| 65 | eaddr, esid, esid_1t); | ||
| 66 | for (i = 0; i < vcpu_book3s->slb_nr; i++) { | ||
| 67 | if (vcpu_book3s->slb[i].vsid) | ||
| 68 | dprintk(" %d: %c%c %llx %llx\n", i, | ||
| 69 | vcpu_book3s->slb[i].valid ? 'v' : ' ', | ||
| 70 | vcpu_book3s->slb[i].large ? 'l' : ' ', | ||
| 71 | vcpu_book3s->slb[i].esid, | ||
| 72 | vcpu_book3s->slb[i].vsid); | ||
| 73 | } | ||
| 74 | |||
| 75 | return NULL; | ||
| 76 | } | ||
| 77 | |||
| 78 | static u64 kvmppc_mmu_book3s_64_ea_to_vp(struct kvm_vcpu *vcpu, gva_t eaddr, | ||
| 79 | bool data) | ||
| 80 | { | ||
| 81 | struct kvmppc_slb *slb; | ||
| 82 | |||
| 83 | slb = kvmppc_mmu_book3s_64_find_slbe(to_book3s(vcpu), eaddr); | ||
| 84 | if (!slb) | ||
| 85 | return 0; | ||
| 86 | |||
| 87 | if (slb->large) | ||
| 88 | return (((u64)eaddr >> 12) & 0xfffffff) | | ||
| 89 | (((u64)slb->vsid) << 28); | ||
| 90 | |||
| 91 | return (((u64)eaddr >> 12) & 0xffff) | (((u64)slb->vsid) << 16); | ||
| 92 | } | ||
| 93 | |||
| 94 | static int kvmppc_mmu_book3s_64_get_pagesize(struct kvmppc_slb *slbe) | ||
| 95 | { | ||
| 96 | return slbe->large ? 24 : 12; | ||
| 97 | } | ||
| 98 | |||
| 99 | static u32 kvmppc_mmu_book3s_64_get_page(struct kvmppc_slb *slbe, gva_t eaddr) | ||
| 100 | { | ||
| 101 | int p = kvmppc_mmu_book3s_64_get_pagesize(slbe); | ||
| 102 | return ((eaddr & 0xfffffff) >> p); | ||
| 103 | } | ||
| 104 | |||
| 105 | static hva_t kvmppc_mmu_book3s_64_get_pteg( | ||
| 106 | struct kvmppc_vcpu_book3s *vcpu_book3s, | ||
| 107 | struct kvmppc_slb *slbe, gva_t eaddr, | ||
| 108 | bool second) | ||
| 109 | { | ||
| 110 | u64 hash, pteg, htabsize; | ||
| 111 | u32 page; | ||
| 112 | hva_t r; | ||
| 113 | |||
| 114 | page = kvmppc_mmu_book3s_64_get_page(slbe, eaddr); | ||
| 115 | htabsize = ((1 << ((vcpu_book3s->sdr1 & 0x1f) + 11)) - 1); | ||
| 116 | |||
| 117 | hash = slbe->vsid ^ page; | ||
| 118 | if (second) | ||
| 119 | hash = ~hash; | ||
| 120 | hash &= ((1ULL << 39ULL) - 1ULL); | ||
| 121 | hash &= htabsize; | ||
| 122 | hash <<= 7ULL; | ||
| 123 | |||
| 124 | pteg = vcpu_book3s->sdr1 & 0xfffffffffffc0000ULL; | ||
| 125 | pteg |= hash; | ||
| 126 | |||
| 127 | dprintk("MMU: page=0x%x sdr1=0x%llx pteg=0x%llx vsid=0x%llx\n", | ||
| 128 | page, vcpu_book3s->sdr1, pteg, slbe->vsid); | ||
| 129 | |||
| 130 | r = gfn_to_hva(vcpu_book3s->vcpu.kvm, pteg >> PAGE_SHIFT); | ||
| 131 | if (kvm_is_error_hva(r)) | ||
| 132 | return r; | ||
| 133 | return r | (pteg & ~PAGE_MASK); | ||
| 134 | } | ||
| 135 | |||
| 136 | static u64 kvmppc_mmu_book3s_64_get_avpn(struct kvmppc_slb *slbe, gva_t eaddr) | ||
| 137 | { | ||
| 138 | int p = kvmppc_mmu_book3s_64_get_pagesize(slbe); | ||
| 139 | u64 avpn; | ||
| 140 | |||
| 141 | avpn = kvmppc_mmu_book3s_64_get_page(slbe, eaddr); | ||
| 142 | avpn |= slbe->vsid << (28 - p); | ||
| 143 | |||
| 144 | if (p < 24) | ||
| 145 | avpn >>= ((80 - p) - 56) - 8; | ||
| 146 | else | ||
| 147 | avpn <<= 8; | ||
| 148 | |||
| 149 | return avpn; | ||
| 150 | } | ||
| 151 | |||
| 152 | static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, | ||
| 153 | struct kvmppc_pte *gpte, bool data) | ||
| 154 | { | ||
| 155 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | ||
| 156 | struct kvmppc_slb *slbe; | ||
| 157 | hva_t ptegp; | ||
| 158 | u64 pteg[16]; | ||
| 159 | u64 avpn = 0; | ||
| 160 | int i; | ||
| 161 | u8 key = 0; | ||
| 162 | bool found = false; | ||
| 163 | bool perm_err = false; | ||
| 164 | int second = 0; | ||
| 165 | |||
| 166 | slbe = kvmppc_mmu_book3s_64_find_slbe(vcpu_book3s, eaddr); | ||
| 167 | if (!slbe) | ||
| 168 | goto no_seg_found; | ||
| 169 | |||
| 170 | do_second: | ||
| 171 | ptegp = kvmppc_mmu_book3s_64_get_pteg(vcpu_book3s, slbe, eaddr, second); | ||
| 172 | if (kvm_is_error_hva(ptegp)) | ||
| 173 | goto no_page_found; | ||
| 174 | |||
| 175 | avpn = kvmppc_mmu_book3s_64_get_avpn(slbe, eaddr); | ||
| 176 | |||
| 177 | if(copy_from_user(pteg, (void __user *)ptegp, sizeof(pteg))) { | ||
| 178 | printk(KERN_ERR "KVM can't copy data from 0x%lx!\n", ptegp); | ||
| 179 | goto no_page_found; | ||
| 180 | } | ||
| 181 | |||
| 182 | if ((vcpu->arch.msr & MSR_PR) && slbe->Kp) | ||
| 183 | key = 4; | ||
| 184 | else if (!(vcpu->arch.msr & MSR_PR) && slbe->Ks) | ||
| 185 | key = 4; | ||
| 186 | |||
| 187 | for (i=0; i<16; i+=2) { | ||
| 188 | u64 v = pteg[i]; | ||
| 189 | u64 r = pteg[i+1]; | ||
| 190 | |||
| 191 | /* Valid check */ | ||
| 192 | if (!(v & HPTE_V_VALID)) | ||
| 193 | continue; | ||
| 194 | /* Hash check */ | ||
| 195 | if ((v & HPTE_V_SECONDARY) != second) | ||
| 196 | continue; | ||
| 197 | |||
| 198 | /* AVPN compare */ | ||
| 199 | if (HPTE_V_AVPN_VAL(avpn) == HPTE_V_AVPN_VAL(v)) { | ||
| 200 | u8 pp = (r & HPTE_R_PP) | key; | ||
| 201 | int eaddr_mask = 0xFFF; | ||
| 202 | |||
| 203 | gpte->eaddr = eaddr; | ||
| 204 | gpte->vpage = kvmppc_mmu_book3s_64_ea_to_vp(vcpu, | ||
| 205 | eaddr, | ||
| 206 | data); | ||
| 207 | if (slbe->large) | ||
| 208 | eaddr_mask = 0xFFFFFF; | ||
| 209 | gpte->raddr = (r & HPTE_R_RPN) | (eaddr & eaddr_mask); | ||
| 210 | gpte->may_execute = ((r & HPTE_R_N) ? false : true); | ||
| 211 | gpte->may_read = false; | ||
| 212 | gpte->may_write = false; | ||
| 213 | |||
| 214 | switch (pp) { | ||
| 215 | case 0: | ||
| 216 | case 1: | ||
| 217 | case 2: | ||
| 218 | case 6: | ||
| 219 | gpte->may_write = true; | ||
| 220 | /* fall through */ | ||
| 221 | case 3: | ||
| 222 | case 5: | ||
| 223 | case 7: | ||
| 224 | gpte->may_read = true; | ||
| 225 | break; | ||
| 226 | } | ||
| 227 | |||
| 228 | if (!gpte->may_read) { | ||
| 229 | perm_err = true; | ||
| 230 | continue; | ||
| 231 | } | ||
| 232 | |||
| 233 | dprintk("KVM MMU: Translated 0x%lx [0x%llx] -> 0x%llx " | ||
| 234 | "-> 0x%llx\n", | ||
| 235 | eaddr, avpn, gpte->vpage, gpte->raddr); | ||
| 236 | found = true; | ||
| 237 | break; | ||
| 238 | } | ||
| 239 | } | ||
| 240 | |||
| 241 | /* Update PTE R and C bits, so the guest's swapper knows we used the | ||
| 242 | * page */ | ||
| 243 | if (found) { | ||
| 244 | u32 oldr = pteg[i+1]; | ||
| 245 | |||
| 246 | if (gpte->may_read) { | ||
| 247 | /* Set the accessed flag */ | ||
| 248 | pteg[i+1] |= HPTE_R_R; | ||
| 249 | } | ||
| 250 | if (gpte->may_write) { | ||
| 251 | /* Set the dirty flag */ | ||
| 252 | pteg[i+1] |= HPTE_R_C; | ||
| 253 | } else { | ||
| 254 | dprintk("KVM: Mapping read-only page!\n"); | ||
| 255 | } | ||
| 256 | |||
| 257 | /* Write back into the PTEG */ | ||
| 258 | if (pteg[i+1] != oldr) | ||
| 259 | copy_to_user((void __user *)ptegp, pteg, sizeof(pteg)); | ||
| 260 | |||
| 261 | return 0; | ||
| 262 | } else { | ||
| 263 | dprintk("KVM MMU: No PTE found (ea=0x%lx sdr1=0x%llx " | ||
| 264 | "ptegp=0x%lx)\n", | ||
| 265 | eaddr, to_book3s(vcpu)->sdr1, ptegp); | ||
| 266 | for (i = 0; i < 16; i += 2) | ||
| 267 | dprintk(" %02d: 0x%llx - 0x%llx (0x%llx)\n", | ||
| 268 | i, pteg[i], pteg[i+1], avpn); | ||
| 269 | |||
| 270 | if (!second) { | ||
| 271 | second = HPTE_V_SECONDARY; | ||
| 272 | goto do_second; | ||
| 273 | } | ||
| 274 | } | ||
| 275 | |||
| 276 | |||
| 277 | no_page_found: | ||
| 278 | |||
| 279 | |||
| 280 | if (perm_err) | ||
| 281 | return -EPERM; | ||
| 282 | |||
| 283 | return -ENOENT; | ||
| 284 | |||
| 285 | no_seg_found: | ||
| 286 | |||
| 287 | dprintk("KVM MMU: Trigger segment fault\n"); | ||
| 288 | return -EINVAL; | ||
| 289 | } | ||
| 290 | |||
| 291 | static void kvmppc_mmu_book3s_64_slbmte(struct kvm_vcpu *vcpu, u64 rs, u64 rb) | ||
| 292 | { | ||
| 293 | struct kvmppc_vcpu_book3s *vcpu_book3s; | ||
| 294 | u64 esid, esid_1t; | ||
| 295 | int slb_nr; | ||
| 296 | struct kvmppc_slb *slbe; | ||
| 297 | |||
| 298 | dprintk("KVM MMU: slbmte(0x%llx, 0x%llx)\n", rs, rb); | ||
| 299 | |||
| 300 | vcpu_book3s = to_book3s(vcpu); | ||
| 301 | |||
| 302 | esid = GET_ESID(rb); | ||
| 303 | esid_1t = GET_ESID_1T(rb); | ||
| 304 | slb_nr = rb & 0xfff; | ||
| 305 | |||
| 306 | if (slb_nr > vcpu_book3s->slb_nr) | ||
| 307 | return; | ||
| 308 | |||
| 309 | slbe = &vcpu_book3s->slb[slb_nr]; | ||
| 310 | |||
| 311 | slbe->large = (rs & SLB_VSID_L) ? 1 : 0; | ||
| 312 | slbe->esid = slbe->large ? esid_1t : esid; | ||
| 313 | slbe->vsid = rs >> 12; | ||
| 314 | slbe->valid = (rb & SLB_ESID_V) ? 1 : 0; | ||
| 315 | slbe->Ks = (rs & SLB_VSID_KS) ? 1 : 0; | ||
| 316 | slbe->Kp = (rs & SLB_VSID_KP) ? 1 : 0; | ||
| 317 | slbe->nx = (rs & SLB_VSID_N) ? 1 : 0; | ||
| 318 | slbe->class = (rs & SLB_VSID_C) ? 1 : 0; | ||
| 319 | |||
| 320 | slbe->orige = rb & (ESID_MASK | SLB_ESID_V); | ||
| 321 | slbe->origv = rs; | ||
| 322 | |||
| 323 | /* Map the new segment */ | ||
| 324 | kvmppc_mmu_map_segment(vcpu, esid << SID_SHIFT); | ||
| 325 | } | ||
| 326 | |||
| 327 | static u64 kvmppc_mmu_book3s_64_slbmfee(struct kvm_vcpu *vcpu, u64 slb_nr) | ||
| 328 | { | ||
| 329 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | ||
| 330 | struct kvmppc_slb *slbe; | ||
| 331 | |||
| 332 | if (slb_nr > vcpu_book3s->slb_nr) | ||
| 333 | return 0; | ||
| 334 | |||
| 335 | slbe = &vcpu_book3s->slb[slb_nr]; | ||
| 336 | |||
| 337 | return slbe->orige; | ||
| 338 | } | ||
| 339 | |||
| 340 | static u64 kvmppc_mmu_book3s_64_slbmfev(struct kvm_vcpu *vcpu, u64 slb_nr) | ||
| 341 | { | ||
| 342 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | ||
| 343 | struct kvmppc_slb *slbe; | ||
| 344 | |||
| 345 | if (slb_nr > vcpu_book3s->slb_nr) | ||
| 346 | return 0; | ||
| 347 | |||
| 348 | slbe = &vcpu_book3s->slb[slb_nr]; | ||
| 349 | |||
| 350 | return slbe->origv; | ||
| 351 | } | ||
| 352 | |||
| 353 | static void kvmppc_mmu_book3s_64_slbie(struct kvm_vcpu *vcpu, u64 ea) | ||
| 354 | { | ||
| 355 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | ||
| 356 | struct kvmppc_slb *slbe; | ||
| 357 | |||
| 358 | dprintk("KVM MMU: slbie(0x%llx)\n", ea); | ||
| 359 | |||
| 360 | slbe = kvmppc_mmu_book3s_64_find_slbe(vcpu_book3s, ea); | ||
| 361 | |||
| 362 | if (!slbe) | ||
| 363 | return; | ||
| 364 | |||
| 365 | dprintk("KVM MMU: slbie(0x%llx, 0x%llx)\n", ea, slbe->esid); | ||
| 366 | |||
| 367 | slbe->valid = false; | ||
| 368 | |||
| 369 | kvmppc_mmu_map_segment(vcpu, ea); | ||
| 370 | } | ||
| 371 | |||
| 372 | static void kvmppc_mmu_book3s_64_slbia(struct kvm_vcpu *vcpu) | ||
| 373 | { | ||
| 374 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | ||
| 375 | int i; | ||
| 376 | |||
| 377 | dprintk("KVM MMU: slbia()\n"); | ||
| 378 | |||
| 379 | for (i = 1; i < vcpu_book3s->slb_nr; i++) | ||
| 380 | vcpu_book3s->slb[i].valid = false; | ||
| 381 | |||
| 382 | if (vcpu->arch.msr & MSR_IR) { | ||
| 383 | kvmppc_mmu_flush_segments(vcpu); | ||
| 384 | kvmppc_mmu_map_segment(vcpu, vcpu->arch.pc); | ||
| 385 | } | ||
| 386 | } | ||
| 387 | |||
| 388 | static void kvmppc_mmu_book3s_64_mtsrin(struct kvm_vcpu *vcpu, u32 srnum, | ||
| 389 | ulong value) | ||
| 390 | { | ||
| 391 | u64 rb = 0, rs = 0; | ||
| 392 | |||
| 393 | /* | ||
| 394 | * According to Book3 2.01 mtsrin is implemented as: | ||
| 395 | * | ||
| 396 | * The SLB entry specified by (RB)32:35 is loaded from register | ||
| 397 | * RS, as follows. | ||
| 398 | * | ||
| 399 | * SLBE Bit Source SLB Field | ||
| 400 | * | ||
| 401 | * 0:31 0x0000_0000 ESID-0:31 | ||
| 402 | * 32:35 (RB)32:35 ESID-32:35 | ||
| 403 | * 36 0b1 V | ||
| 404 | * 37:61 0x00_0000|| 0b0 VSID-0:24 | ||
| 405 | * 62:88 (RS)37:63 VSID-25:51 | ||
| 406 | * 89:91 (RS)33:35 Ks Kp N | ||
| 407 | * 92 (RS)36 L ((RS)36 must be 0b0) | ||
| 408 | * 93 0b0 C | ||
| 409 | */ | ||
| 410 | |||
| 411 | dprintk("KVM MMU: mtsrin(0x%x, 0x%lx)\n", srnum, value); | ||
| 412 | |||
| 413 | /* ESID = srnum */ | ||
| 414 | rb |= (srnum & 0xf) << 28; | ||
| 415 | /* Set the valid bit */ | ||
| 416 | rb |= 1 << 27; | ||
| 417 | /* Index = ESID */ | ||
| 418 | rb |= srnum; | ||
| 419 | |||
| 420 | /* VSID = VSID */ | ||
| 421 | rs |= (value & 0xfffffff) << 12; | ||
| 422 | /* flags = flags */ | ||
| 423 | rs |= ((value >> 28) & 0x7) << 9; | ||
| 424 | |||
| 425 | kvmppc_mmu_book3s_64_slbmte(vcpu, rs, rb); | ||
| 426 | } | ||
| 427 | |||
| 428 | static void kvmppc_mmu_book3s_64_tlbie(struct kvm_vcpu *vcpu, ulong va, | ||
| 429 | bool large) | ||
| 430 | { | ||
| 431 | u64 mask = 0xFFFFFFFFFULL; | ||
| 432 | |||
| 433 | dprintk("KVM MMU: tlbie(0x%lx)\n", va); | ||
| 434 | |||
| 435 | if (large) | ||
| 436 | mask = 0xFFFFFF000ULL; | ||
| 437 | kvmppc_mmu_pte_vflush(vcpu, va >> 12, mask); | ||
| 438 | } | ||
| 439 | |||
| 440 | static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, u64 esid, | ||
| 441 | u64 *vsid) | ||
| 442 | { | ||
| 443 | switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) { | ||
| 444 | case 0: | ||
| 445 | *vsid = (VSID_REAL >> 16) | esid; | ||
| 446 | break; | ||
| 447 | case MSR_IR: | ||
| 448 | *vsid = (VSID_REAL_IR >> 16) | esid; | ||
| 449 | break; | ||
| 450 | case MSR_DR: | ||
| 451 | *vsid = (VSID_REAL_DR >> 16) | esid; | ||
| 452 | break; | ||
| 453 | case MSR_DR|MSR_IR: | ||
| 454 | { | ||
| 455 | ulong ea; | ||
| 456 | struct kvmppc_slb *slb; | ||
| 457 | ea = esid << SID_SHIFT; | ||
| 458 | slb = kvmppc_mmu_book3s_64_find_slbe(to_book3s(vcpu), ea); | ||
| 459 | if (slb) | ||
| 460 | *vsid = slb->vsid; | ||
| 461 | else | ||
| 462 | return -ENOENT; | ||
| 463 | |||
| 464 | break; | ||
| 465 | } | ||
| 466 | default: | ||
| 467 | BUG(); | ||
| 468 | break; | ||
| 469 | } | ||
| 470 | |||
| 471 | return 0; | ||
| 472 | } | ||
| 473 | |||
| 474 | static bool kvmppc_mmu_book3s_64_is_dcbz32(struct kvm_vcpu *vcpu) | ||
| 475 | { | ||
| 476 | return (to_book3s(vcpu)->hid[5] & 0x80); | ||
| 477 | } | ||
| 478 | |||
| 479 | void kvmppc_mmu_book3s_64_init(struct kvm_vcpu *vcpu) | ||
| 480 | { | ||
| 481 | struct kvmppc_mmu *mmu = &vcpu->arch.mmu; | ||
| 482 | |||
| 483 | mmu->mfsrin = NULL; | ||
| 484 | mmu->mtsrin = kvmppc_mmu_book3s_64_mtsrin; | ||
| 485 | mmu->slbmte = kvmppc_mmu_book3s_64_slbmte; | ||
| 486 | mmu->slbmfee = kvmppc_mmu_book3s_64_slbmfee; | ||
| 487 | mmu->slbmfev = kvmppc_mmu_book3s_64_slbmfev; | ||
| 488 | mmu->slbie = kvmppc_mmu_book3s_64_slbie; | ||
| 489 | mmu->slbia = kvmppc_mmu_book3s_64_slbia; | ||
| 490 | mmu->xlate = kvmppc_mmu_book3s_64_xlate; | ||
| 491 | mmu->reset_msr = kvmppc_mmu_book3s_64_reset_msr; | ||
| 492 | mmu->tlbie = kvmppc_mmu_book3s_64_tlbie; | ||
| 493 | mmu->esid_to_vsid = kvmppc_mmu_book3s_64_esid_to_vsid; | ||
| 494 | mmu->ea_to_vp = kvmppc_mmu_book3s_64_ea_to_vp; | ||
| 495 | mmu->is_dcbz32 = kvmppc_mmu_book3s_64_is_dcbz32; | ||
| 496 | |||
| 497 | vcpu->arch.hflags |= BOOK3S_HFLAG_SLB; | ||
| 498 | } | ||
diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c new file mode 100644 index 000000000000..f2899b297ffd --- /dev/null +++ b/arch/powerpc/kvm/book3s_64_mmu_host.c | |||
| @@ -0,0 +1,408 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2009 SUSE Linux Products GmbH. All rights reserved. | ||
| 3 | * | ||
| 4 | * Authors: | ||
| 5 | * Alexander Graf <agraf@suse.de> | ||
| 6 | * Kevin Wolf <mail@kevin-wolf.de> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License, version 2, as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/kvm_host.h> | ||
| 23 | |||
| 24 | #include <asm/kvm_ppc.h> | ||
| 25 | #include <asm/kvm_book3s.h> | ||
| 26 | #include <asm/mmu-hash64.h> | ||
| 27 | #include <asm/machdep.h> | ||
| 28 | #include <asm/mmu_context.h> | ||
| 29 | #include <asm/hw_irq.h> | ||
| 30 | |||
| 31 | #define PTE_SIZE 12 | ||
| 32 | #define VSID_ALL 0 | ||
| 33 | |||
| 34 | /* #define DEBUG_MMU */ | ||
| 35 | /* #define DEBUG_SLB */ | ||
| 36 | |||
| 37 | #ifdef DEBUG_MMU | ||
| 38 | #define dprintk_mmu(a, ...) printk(KERN_INFO a, __VA_ARGS__) | ||
| 39 | #else | ||
| 40 | #define dprintk_mmu(a, ...) do { } while(0) | ||
| 41 | #endif | ||
| 42 | |||
| 43 | #ifdef DEBUG_SLB | ||
| 44 | #define dprintk_slb(a, ...) printk(KERN_INFO a, __VA_ARGS__) | ||
| 45 | #else | ||
| 46 | #define dprintk_slb(a, ...) do { } while(0) | ||
| 47 | #endif | ||
| 48 | |||
| 49 | static void invalidate_pte(struct hpte_cache *pte) | ||
| 50 | { | ||
| 51 | dprintk_mmu("KVM: Flushing SPT %d: 0x%llx (0x%llx) -> 0x%llx\n", | ||
| 52 | i, pte->pte.eaddr, pte->pte.vpage, pte->host_va); | ||
| 53 | |||
| 54 | ppc_md.hpte_invalidate(pte->slot, pte->host_va, | ||
| 55 | MMU_PAGE_4K, MMU_SEGSIZE_256M, | ||
| 56 | false); | ||
| 57 | pte->host_va = 0; | ||
| 58 | kvm_release_pfn_dirty(pte->pfn); | ||
| 59 | } | ||
| 60 | |||
| 61 | void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, u64 guest_ea, u64 ea_mask) | ||
| 62 | { | ||
| 63 | int i; | ||
| 64 | |||
| 65 | dprintk_mmu("KVM: Flushing %d Shadow PTEs: 0x%llx & 0x%llx\n", | ||
| 66 | vcpu->arch.hpte_cache_offset, guest_ea, ea_mask); | ||
| 67 | BUG_ON(vcpu->arch.hpte_cache_offset > HPTEG_CACHE_NUM); | ||
| 68 | |||
| 69 | guest_ea &= ea_mask; | ||
| 70 | for (i = 0; i < vcpu->arch.hpte_cache_offset; i++) { | ||
| 71 | struct hpte_cache *pte; | ||
| 72 | |||
| 73 | pte = &vcpu->arch.hpte_cache[i]; | ||
| 74 | if (!pte->host_va) | ||
| 75 | continue; | ||
| 76 | |||
| 77 | if ((pte->pte.eaddr & ea_mask) == guest_ea) { | ||
| 78 | invalidate_pte(pte); | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | /* Doing a complete flush -> start from scratch */ | ||
| 83 | if (!ea_mask) | ||
| 84 | vcpu->arch.hpte_cache_offset = 0; | ||
| 85 | } | ||
| 86 | |||
| 87 | void kvmppc_mmu_pte_vflush(struct kvm_vcpu *vcpu, u64 guest_vp, u64 vp_mask) | ||
| 88 | { | ||
| 89 | int i; | ||
| 90 | |||
| 91 | dprintk_mmu("KVM: Flushing %d Shadow vPTEs: 0x%llx & 0x%llx\n", | ||
| 92 | vcpu->arch.hpte_cache_offset, guest_vp, vp_mask); | ||
| 93 | BUG_ON(vcpu->arch.hpte_cache_offset > HPTEG_CACHE_NUM); | ||
| 94 | |||
| 95 | guest_vp &= vp_mask; | ||
| 96 | for (i = 0; i < vcpu->arch.hpte_cache_offset; i++) { | ||
| 97 | struct hpte_cache *pte; | ||
| 98 | |||
| 99 | pte = &vcpu->arch.hpte_cache[i]; | ||
| 100 | if (!pte->host_va) | ||
| 101 | continue; | ||
| 102 | |||
| 103 | if ((pte->pte.vpage & vp_mask) == guest_vp) { | ||
| 104 | invalidate_pte(pte); | ||
| 105 | } | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, u64 pa_start, u64 pa_end) | ||
| 110 | { | ||
| 111 | int i; | ||
| 112 | |||
| 113 | dprintk_mmu("KVM: Flushing %d Shadow pPTEs: 0x%llx & 0x%llx\n", | ||
| 114 | vcpu->arch.hpte_cache_offset, guest_pa, pa_mask); | ||
| 115 | BUG_ON(vcpu->arch.hpte_cache_offset > HPTEG_CACHE_NUM); | ||
| 116 | |||
| 117 | for (i = 0; i < vcpu->arch.hpte_cache_offset; i++) { | ||
| 118 | struct hpte_cache *pte; | ||
| 119 | |||
| 120 | pte = &vcpu->arch.hpte_cache[i]; | ||
| 121 | if (!pte->host_va) | ||
| 122 | continue; | ||
| 123 | |||
| 124 | if ((pte->pte.raddr >= pa_start) && | ||
| 125 | (pte->pte.raddr < pa_end)) { | ||
| 126 | invalidate_pte(pte); | ||
| 127 | } | ||
| 128 | } | ||
| 129 | } | ||
| 130 | |||
| 131 | struct kvmppc_pte *kvmppc_mmu_find_pte(struct kvm_vcpu *vcpu, u64 ea, bool data) | ||
| 132 | { | ||
| 133 | int i; | ||
| 134 | u64 guest_vp; | ||
| 135 | |||
| 136 | guest_vp = vcpu->arch.mmu.ea_to_vp(vcpu, ea, false); | ||
| 137 | for (i=0; i<vcpu->arch.hpte_cache_offset; i++) { | ||
| 138 | struct hpte_cache *pte; | ||
| 139 | |||
| 140 | pte = &vcpu->arch.hpte_cache[i]; | ||
| 141 | if (!pte->host_va) | ||
| 142 | continue; | ||
| 143 | |||
| 144 | if (pte->pte.vpage == guest_vp) | ||
| 145 | return &pte->pte; | ||
| 146 | } | ||
| 147 | |||
| 148 | return NULL; | ||
| 149 | } | ||
| 150 | |||
| 151 | static int kvmppc_mmu_hpte_cache_next(struct kvm_vcpu *vcpu) | ||
| 152 | { | ||
| 153 | if (vcpu->arch.hpte_cache_offset == HPTEG_CACHE_NUM) | ||
| 154 | kvmppc_mmu_pte_flush(vcpu, 0, 0); | ||
| 155 | |||
| 156 | return vcpu->arch.hpte_cache_offset++; | ||
| 157 | } | ||
| 158 | |||
| 159 | /* We keep 512 gvsid->hvsid entries, mapping the guest ones to the array using | ||
| 160 | * a hash, so we don't waste cycles on looping */ | ||
| 161 | static u16 kvmppc_sid_hash(struct kvm_vcpu *vcpu, u64 gvsid) | ||
| 162 | { | ||
| 163 | return (u16)(((gvsid >> (SID_MAP_BITS * 7)) & SID_MAP_MASK) ^ | ||
| 164 | ((gvsid >> (SID_MAP_BITS * 6)) & SID_MAP_MASK) ^ | ||
| 165 | ((gvsid >> (SID_MAP_BITS * 5)) & SID_MAP_MASK) ^ | ||
| 166 | ((gvsid >> (SID_MAP_BITS * 4)) & SID_MAP_MASK) ^ | ||
| 167 | ((gvsid >> (SID_MAP_BITS * 3)) & SID_MAP_MASK) ^ | ||
| 168 | ((gvsid >> (SID_MAP_BITS * 2)) & SID_MAP_MASK) ^ | ||
| 169 | ((gvsid >> (SID_MAP_BITS * 1)) & SID_MAP_MASK) ^ | ||
| 170 | ((gvsid >> (SID_MAP_BITS * 0)) & SID_MAP_MASK)); | ||
| 171 | } | ||
| 172 | |||
| 173 | |||
| 174 | static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid) | ||
| 175 | { | ||
| 176 | struct kvmppc_sid_map *map; | ||
| 177 | u16 sid_map_mask; | ||
| 178 | |||
| 179 | if (vcpu->arch.msr & MSR_PR) | ||
| 180 | gvsid |= VSID_PR; | ||
| 181 | |||
| 182 | sid_map_mask = kvmppc_sid_hash(vcpu, gvsid); | ||
| 183 | map = &to_book3s(vcpu)->sid_map[sid_map_mask]; | ||
| 184 | if (map->guest_vsid == gvsid) { | ||
| 185 | dprintk_slb("SLB: Searching 0x%llx -> 0x%llx\n", | ||
| 186 | gvsid, map->host_vsid); | ||
| 187 | return map; | ||
| 188 | } | ||
| 189 | |||
| 190 | map = &to_book3s(vcpu)->sid_map[SID_MAP_MASK - sid_map_mask]; | ||
| 191 | if (map->guest_vsid == gvsid) { | ||
| 192 | dprintk_slb("SLB: Searching 0x%llx -> 0x%llx\n", | ||
| 193 | gvsid, map->host_vsid); | ||
| 194 | return map; | ||
| 195 | } | ||
| 196 | |||
| 197 | dprintk_slb("SLB: Searching 0x%llx -> not found\n", gvsid); | ||
| 198 | return NULL; | ||
| 199 | } | ||
| 200 | |||
| 201 | int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte) | ||
| 202 | { | ||
| 203 | pfn_t hpaddr; | ||
| 204 | ulong hash, hpteg, va; | ||
| 205 | u64 vsid; | ||
| 206 | int ret; | ||
| 207 | int rflags = 0x192; | ||
| 208 | int vflags = 0; | ||
| 209 | int attempt = 0; | ||
| 210 | struct kvmppc_sid_map *map; | ||
| 211 | |||
| 212 | /* Get host physical address for gpa */ | ||
| 213 | hpaddr = gfn_to_pfn(vcpu->kvm, orig_pte->raddr >> PAGE_SHIFT); | ||
| 214 | if (kvm_is_error_hva(hpaddr)) { | ||
| 215 | printk(KERN_INFO "Couldn't get guest page for gfn %llx!\n", orig_pte->eaddr); | ||
| 216 | return -EINVAL; | ||
| 217 | } | ||
| 218 | hpaddr <<= PAGE_SHIFT; | ||
| 219 | #if PAGE_SHIFT == 12 | ||
| 220 | #elif PAGE_SHIFT == 16 | ||
| 221 | hpaddr |= orig_pte->raddr & 0xf000; | ||
| 222 | #else | ||
| 223 | #error Unknown page size | ||
| 224 | #endif | ||
| 225 | |||
| 226 | /* and write the mapping ea -> hpa into the pt */ | ||
| 227 | vcpu->arch.mmu.esid_to_vsid(vcpu, orig_pte->eaddr >> SID_SHIFT, &vsid); | ||
| 228 | map = find_sid_vsid(vcpu, vsid); | ||
| 229 | if (!map) { | ||
| 230 | kvmppc_mmu_map_segment(vcpu, orig_pte->eaddr); | ||
| 231 | map = find_sid_vsid(vcpu, vsid); | ||
| 232 | } | ||
| 233 | BUG_ON(!map); | ||
| 234 | |||
| 235 | vsid = map->host_vsid; | ||
| 236 | va = hpt_va(orig_pte->eaddr, vsid, MMU_SEGSIZE_256M); | ||
| 237 | |||
| 238 | if (!orig_pte->may_write) | ||
| 239 | rflags |= HPTE_R_PP; | ||
| 240 | else | ||
| 241 | mark_page_dirty(vcpu->kvm, orig_pte->raddr >> PAGE_SHIFT); | ||
| 242 | |||
| 243 | if (!orig_pte->may_execute) | ||
| 244 | rflags |= HPTE_R_N; | ||
| 245 | |||
| 246 | hash = hpt_hash(va, PTE_SIZE, MMU_SEGSIZE_256M); | ||
| 247 | |||
| 248 | map_again: | ||
| 249 | hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); | ||
| 250 | |||
| 251 | /* In case we tried normal mapping already, let's nuke old entries */ | ||
| 252 | if (attempt > 1) | ||
| 253 | if (ppc_md.hpte_remove(hpteg) < 0) | ||
| 254 | return -1; | ||
| 255 | |||
| 256 | ret = ppc_md.hpte_insert(hpteg, va, hpaddr, rflags, vflags, MMU_PAGE_4K, MMU_SEGSIZE_256M); | ||
| 257 | |||
| 258 | if (ret < 0) { | ||
| 259 | /* If we couldn't map a primary PTE, try a secondary */ | ||
| 260 | #ifdef USE_SECONDARY | ||
| 261 | hash = ~hash; | ||
| 262 | attempt++; | ||
| 263 | if (attempt % 2) | ||
| 264 | vflags = HPTE_V_SECONDARY; | ||
| 265 | else | ||
| 266 | vflags = 0; | ||
| 267 | #else | ||
| 268 | attempt = 2; | ||
| 269 | #endif | ||
| 270 | goto map_again; | ||
| 271 | } else { | ||
| 272 | int hpte_id = kvmppc_mmu_hpte_cache_next(vcpu); | ||
| 273 | struct hpte_cache *pte = &vcpu->arch.hpte_cache[hpte_id]; | ||
| 274 | |||
| 275 | dprintk_mmu("KVM: %c%c Map 0x%llx: [%lx] 0x%lx (0x%llx) -> %lx\n", | ||
| 276 | ((rflags & HPTE_R_PP) == 3) ? '-' : 'w', | ||
| 277 | (rflags & HPTE_R_N) ? '-' : 'x', | ||
| 278 | orig_pte->eaddr, hpteg, va, orig_pte->vpage, hpaddr); | ||
| 279 | |||
| 280 | pte->slot = hpteg + (ret & 7); | ||
| 281 | pte->host_va = va; | ||
| 282 | pte->pte = *orig_pte; | ||
| 283 | pte->pfn = hpaddr >> PAGE_SHIFT; | ||
| 284 | } | ||
| 285 | |||
| 286 | return 0; | ||
| 287 | } | ||
| 288 | |||
| 289 | static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid) | ||
| 290 | { | ||
| 291 | struct kvmppc_sid_map *map; | ||
| 292 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | ||
| 293 | u16 sid_map_mask; | ||
| 294 | static int backwards_map = 0; | ||
| 295 | |||
| 296 | if (vcpu->arch.msr & MSR_PR) | ||
| 297 | gvsid |= VSID_PR; | ||
| 298 | |||
| 299 | /* We might get collisions that trap in preceding order, so let's | ||
| 300 | map them differently */ | ||
| 301 | |||
| 302 | sid_map_mask = kvmppc_sid_hash(vcpu, gvsid); | ||
| 303 | if (backwards_map) | ||
| 304 | sid_map_mask = SID_MAP_MASK - sid_map_mask; | ||
| 305 | |||
| 306 | map = &to_book3s(vcpu)->sid_map[sid_map_mask]; | ||
| 307 | |||
| 308 | /* Make sure we're taking the other map next time */ | ||
| 309 | backwards_map = !backwards_map; | ||
| 310 | |||
| 311 | /* Uh-oh ... out of mappings. Let's flush! */ | ||
| 312 | if (vcpu_book3s->vsid_next == vcpu_book3s->vsid_max) { | ||
| 313 | vcpu_book3s->vsid_next = vcpu_book3s->vsid_first; | ||
| 314 | memset(vcpu_book3s->sid_map, 0, | ||
| 315 | sizeof(struct kvmppc_sid_map) * SID_MAP_NUM); | ||
| 316 | kvmppc_mmu_pte_flush(vcpu, 0, 0); | ||
| 317 | kvmppc_mmu_flush_segments(vcpu); | ||
| 318 | } | ||
| 319 | map->host_vsid = vcpu_book3s->vsid_next++; | ||
| 320 | |||
| 321 | map->guest_vsid = gvsid; | ||
| 322 | map->valid = true; | ||
| 323 | |||
| 324 | return map; | ||
| 325 | } | ||
| 326 | |||
| 327 | static int kvmppc_mmu_next_segment(struct kvm_vcpu *vcpu, ulong esid) | ||
| 328 | { | ||
| 329 | int i; | ||
| 330 | int max_slb_size = 64; | ||
| 331 | int found_inval = -1; | ||
| 332 | int r; | ||
| 333 | |||
| 334 | if (!get_paca()->kvm_slb_max) | ||
| 335 | get_paca()->kvm_slb_max = 1; | ||
| 336 | |||
| 337 | /* Are we overwriting? */ | ||
| 338 | for (i = 1; i < get_paca()->kvm_slb_max; i++) { | ||
| 339 | if (!(get_paca()->kvm_slb[i].esid & SLB_ESID_V)) | ||
| 340 | found_inval = i; | ||
| 341 | else if ((get_paca()->kvm_slb[i].esid & ESID_MASK) == esid) | ||
| 342 | return i; | ||
| 343 | } | ||
| 344 | |||
| 345 | /* Found a spare entry that was invalidated before */ | ||
| 346 | if (found_inval > 0) | ||
| 347 | return found_inval; | ||
| 348 | |||
| 349 | /* No spare invalid entry, so create one */ | ||
| 350 | |||
| 351 | if (mmu_slb_size < 64) | ||
| 352 | max_slb_size = mmu_slb_size; | ||
| 353 | |||
| 354 | /* Overflowing -> purge */ | ||
| 355 | if ((get_paca()->kvm_slb_max) == max_slb_size) | ||
| 356 | kvmppc_mmu_flush_segments(vcpu); | ||
| 357 | |||
| 358 | r = get_paca()->kvm_slb_max; | ||
| 359 | get_paca()->kvm_slb_max++; | ||
| 360 | |||
| 361 | return r; | ||
| 362 | } | ||
| 363 | |||
| 364 | int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr) | ||
| 365 | { | ||
| 366 | u64 esid = eaddr >> SID_SHIFT; | ||
| 367 | u64 slb_esid = (eaddr & ESID_MASK) | SLB_ESID_V; | ||
| 368 | u64 slb_vsid = SLB_VSID_USER; | ||
| 369 | u64 gvsid; | ||
| 370 | int slb_index; | ||
| 371 | struct kvmppc_sid_map *map; | ||
| 372 | |||
| 373 | slb_index = kvmppc_mmu_next_segment(vcpu, eaddr & ESID_MASK); | ||
| 374 | |||
| 375 | if (vcpu->arch.mmu.esid_to_vsid(vcpu, esid, &gvsid)) { | ||
| 376 | /* Invalidate an entry */ | ||
| 377 | get_paca()->kvm_slb[slb_index].esid = 0; | ||
| 378 | return -ENOENT; | ||
| 379 | } | ||
| 380 | |||
| 381 | map = find_sid_vsid(vcpu, gvsid); | ||
| 382 | if (!map) | ||
| 383 | map = create_sid_map(vcpu, gvsid); | ||
| 384 | |||
| 385 | map->guest_esid = esid; | ||
| 386 | |||
| 387 | slb_vsid |= (map->host_vsid << 12); | ||
| 388 | slb_vsid &= ~SLB_VSID_KP; | ||
| 389 | slb_esid |= slb_index; | ||
| 390 | |||
| 391 | get_paca()->kvm_slb[slb_index].esid = slb_esid; | ||
| 392 | get_paca()->kvm_slb[slb_index].vsid = slb_vsid; | ||
| 393 | |||
| 394 | dprintk_slb("slbmte %#llx, %#llx\n", slb_vsid, slb_esid); | ||
| 395 | |||
| 396 | return 0; | ||
| 397 | } | ||
| 398 | |||
| 399 | void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu) | ||
| 400 | { | ||
| 401 | get_paca()->kvm_slb_max = 1; | ||
| 402 | get_paca()->kvm_slb[0].esid = 0; | ||
| 403 | } | ||
| 404 | |||
| 405 | void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu) | ||
| 406 | { | ||
| 407 | kvmppc_mmu_pte_flush(vcpu, 0, 0); | ||
| 408 | } | ||
diff --git a/arch/powerpc/kvm/book3s_64_rmhandlers.S b/arch/powerpc/kvm/book3s_64_rmhandlers.S new file mode 100644 index 000000000000..fb7dd2e9ac88 --- /dev/null +++ b/arch/powerpc/kvm/book3s_64_rmhandlers.S | |||
| @@ -0,0 +1,131 @@ | |||
| 1 | /* | ||
| 2 | * This program is free software; you can redistribute it and/or modify | ||
| 3 | * it under the terms of the GNU General Public License, version 2, as | ||
| 4 | * published by the Free Software Foundation. | ||
| 5 | * | ||
| 6 | * This program is distributed in the hope that it will be useful, | ||
| 7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 9 | * GNU General Public License for more details. | ||
| 10 | * | ||
| 11 | * You should have received a copy of the GNU General Public License | ||
| 12 | * along with this program; if not, write to the Free Software | ||
| 13 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 14 | * | ||
| 15 | * Copyright SUSE Linux Products GmbH 2009 | ||
| 16 | * | ||
| 17 | * Authors: Alexander Graf <agraf@suse.de> | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <asm/ppc_asm.h> | ||
| 21 | #include <asm/kvm_asm.h> | ||
| 22 | #include <asm/reg.h> | ||
| 23 | #include <asm/page.h> | ||
| 24 | #include <asm/asm-offsets.h> | ||
| 25 | #include <asm/exception-64s.h> | ||
| 26 | |||
| 27 | /***************************************************************************** | ||
| 28 | * * | ||
| 29 | * Real Mode handlers that need to be in low physical memory * | ||
| 30 | * * | ||
| 31 | ****************************************************************************/ | ||
| 32 | |||
| 33 | |||
| 34 | .macro INTERRUPT_TRAMPOLINE intno | ||
| 35 | |||
| 36 | .global kvmppc_trampoline_\intno | ||
| 37 | kvmppc_trampoline_\intno: | ||
| 38 | |||
| 39 | mtspr SPRN_SPRG_SCRATCH0, r13 /* Save r13 */ | ||
| 40 | |||
| 41 | /* | ||
| 42 | * First thing to do is to find out if we're coming | ||
| 43 | * from a KVM guest or a Linux process. | ||
| 44 | * | ||
| 45 | * To distinguish, we check a magic byte in the PACA | ||
| 46 | */ | ||
| 47 | mfspr r13, SPRN_SPRG_PACA /* r13 = PACA */ | ||
| 48 | std r12, (PACA_EXMC + EX_R12)(r13) | ||
| 49 | mfcr r12 | ||
| 50 | stw r12, (PACA_EXMC + EX_CCR)(r13) | ||
| 51 | lbz r12, PACA_KVM_IN_GUEST(r13) | ||
| 52 | cmpwi r12, 0 | ||
| 53 | bne ..kvmppc_handler_hasmagic_\intno | ||
| 54 | /* No KVM guest? Then jump back to the Linux handler! */ | ||
| 55 | lwz r12, (PACA_EXMC + EX_CCR)(r13) | ||
| 56 | mtcr r12 | ||
| 57 | ld r12, (PACA_EXMC + EX_R12)(r13) | ||
| 58 | mfspr r13, SPRN_SPRG_SCRATCH0 /* r13 = original r13 */ | ||
| 59 | b kvmppc_resume_\intno /* Get back original handler */ | ||
| 60 | |||
| 61 | /* Now we know we're handling a KVM guest */ | ||
| 62 | ..kvmppc_handler_hasmagic_\intno: | ||
| 63 | /* Unset guest state */ | ||
| 64 | li r12, 0 | ||
| 65 | stb r12, PACA_KVM_IN_GUEST(r13) | ||
| 66 | |||
| 67 | std r1, (PACA_EXMC+EX_R9)(r13) | ||
| 68 | std r10, (PACA_EXMC+EX_R10)(r13) | ||
| 69 | std r11, (PACA_EXMC+EX_R11)(r13) | ||
| 70 | std r2, (PACA_EXMC+EX_R13)(r13) | ||
| 71 | |||
| 72 | mfsrr0 r10 | ||
| 73 | mfsrr1 r11 | ||
| 74 | |||
| 75 | /* Restore R1/R2 so we can handle faults */ | ||
| 76 | ld r1, PACAR1(r13) | ||
| 77 | ld r2, (PACA_EXMC+EX_SRR0)(r13) | ||
| 78 | |||
| 79 | /* Let's store which interrupt we're handling */ | ||
| 80 | li r12, \intno | ||
| 81 | |||
| 82 | /* Jump into the SLB exit code that goes to the highmem handler */ | ||
| 83 | b kvmppc_handler_trampoline_exit | ||
| 84 | |||
| 85 | .endm | ||
| 86 | |||
| 87 | INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_SYSTEM_RESET | ||
| 88 | INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_MACHINE_CHECK | ||
| 89 | INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_DATA_STORAGE | ||
| 90 | INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_DATA_SEGMENT | ||
| 91 | INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_INST_STORAGE | ||
| 92 | INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_INST_SEGMENT | ||
| 93 | INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_EXTERNAL | ||
| 94 | INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_ALIGNMENT | ||
| 95 | INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_PROGRAM | ||
| 96 | INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_FP_UNAVAIL | ||
| 97 | INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_DECREMENTER | ||
| 98 | INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_SYSCALL | ||
| 99 | INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_TRACE | ||
| 100 | INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_PERFMON | ||
| 101 | INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_ALTIVEC | ||
| 102 | INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_VSX | ||
| 103 | |||
| 104 | /* | ||
| 105 | * This trampoline brings us back to a real mode handler | ||
| 106 | * | ||
| 107 | * Input Registers: | ||
| 108 | * | ||
| 109 | * R6 = SRR0 | ||
| 110 | * R7 = SRR1 | ||
| 111 | * LR = real-mode IP | ||
| 112 | * | ||
| 113 | */ | ||
| 114 | .global kvmppc_handler_lowmem_trampoline | ||
| 115 | kvmppc_handler_lowmem_trampoline: | ||
| 116 | |||
| 117 | mtsrr0 r6 | ||
| 118 | mtsrr1 r7 | ||
| 119 | blr | ||
| 120 | kvmppc_handler_lowmem_trampoline_end: | ||
| 121 | |||
| 122 | .global kvmppc_trampoline_lowmem | ||
| 123 | kvmppc_trampoline_lowmem: | ||
| 124 | .long kvmppc_handler_lowmem_trampoline - _stext | ||
| 125 | |||
| 126 | .global kvmppc_trampoline_enter | ||
| 127 | kvmppc_trampoline_enter: | ||
| 128 | .long kvmppc_handler_trampoline_enter - _stext | ||
| 129 | |||
| 130 | #include "book3s_64_slb.S" | ||
| 131 | |||
diff --git a/arch/powerpc/kvm/book3s_64_slb.S b/arch/powerpc/kvm/book3s_64_slb.S new file mode 100644 index 000000000000..ecd237a03fd0 --- /dev/null +++ b/arch/powerpc/kvm/book3s_64_slb.S | |||
| @@ -0,0 +1,262 @@ | |||
| 1 | /* | ||
| 2 | * This program is free software; you can redistribute it and/or modify | ||
| 3 | * it under the terms of the GNU General Public License, version 2, as | ||
| 4 | * published by the Free Software Foundation. | ||
| 5 | * | ||
| 6 | * This program is distributed in the hope that it will be useful, | ||
| 7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 9 | * GNU General Public License for more details. | ||
| 10 | * | ||
| 11 | * You should have received a copy of the GNU General Public License | ||
| 12 | * along with this program; if not, write to the Free Software | ||
| 13 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 14 | * | ||
| 15 | * Copyright SUSE Linux Products GmbH 2009 | ||
| 16 | * | ||
| 17 | * Authors: Alexander Graf <agraf@suse.de> | ||
| 18 | */ | ||
| 19 | |||
| 20 | #define SHADOW_SLB_ESID(num) (SLBSHADOW_SAVEAREA + (num * 0x10)) | ||
| 21 | #define SHADOW_SLB_VSID(num) (SLBSHADOW_SAVEAREA + (num * 0x10) + 0x8) | ||
| 22 | #define UNBOLT_SLB_ENTRY(num) \ | ||
| 23 | ld r9, SHADOW_SLB_ESID(num)(r12); \ | ||
| 24 | /* Invalid? Skip. */; \ | ||
| 25 | rldicl. r0, r9, 37, 63; \ | ||
| 26 | beq slb_entry_skip_ ## num; \ | ||
| 27 | xoris r9, r9, SLB_ESID_V@h; \ | ||
| 28 | std r9, SHADOW_SLB_ESID(num)(r12); \ | ||
| 29 | slb_entry_skip_ ## num: | ||
| 30 | |||
| 31 | #define REBOLT_SLB_ENTRY(num) \ | ||
| 32 | ld r10, SHADOW_SLB_ESID(num)(r11); \ | ||
| 33 | cmpdi r10, 0; \ | ||
| 34 | beq slb_exit_skip_1; \ | ||
| 35 | oris r10, r10, SLB_ESID_V@h; \ | ||
| 36 | ld r9, SHADOW_SLB_VSID(num)(r11); \ | ||
| 37 | slbmte r9, r10; \ | ||
| 38 | std r10, SHADOW_SLB_ESID(num)(r11); \ | ||
| 39 | slb_exit_skip_ ## num: | ||
| 40 | |||
| 41 | /****************************************************************************** | ||
| 42 | * * | ||
| 43 | * Entry code * | ||
| 44 | * * | ||
| 45 | *****************************************************************************/ | ||
| 46 | |||
| 47 | .global kvmppc_handler_trampoline_enter | ||
| 48 | kvmppc_handler_trampoline_enter: | ||
| 49 | |||
| 50 | /* Required state: | ||
| 51 | * | ||
| 52 | * MSR = ~IR|DR | ||
| 53 | * R13 = PACA | ||
| 54 | * R9 = guest IP | ||
| 55 | * R10 = guest MSR | ||
| 56 | * R11 = free | ||
| 57 | * R12 = free | ||
| 58 | * PACA[PACA_EXMC + EX_R9] = guest R9 | ||
| 59 | * PACA[PACA_EXMC + EX_R10] = guest R10 | ||
| 60 | * PACA[PACA_EXMC + EX_R11] = guest R11 | ||
| 61 | * PACA[PACA_EXMC + EX_R12] = guest R12 | ||
| 62 | * PACA[PACA_EXMC + EX_R13] = guest R13 | ||
| 63 | * PACA[PACA_EXMC + EX_CCR] = guest CR | ||
| 64 | * PACA[PACA_EXMC + EX_R3] = guest XER | ||
| 65 | */ | ||
| 66 | |||
| 67 | mtsrr0 r9 | ||
| 68 | mtsrr1 r10 | ||
| 69 | |||
| 70 | mtspr SPRN_SPRG_SCRATCH0, r0 | ||
| 71 | |||
| 72 | /* Remove LPAR shadow entries */ | ||
| 73 | |||
| 74 | #if SLB_NUM_BOLTED == 3 | ||
| 75 | |||
| 76 | ld r12, PACA_SLBSHADOWPTR(r13) | ||
| 77 | |||
| 78 | /* Save off the first entry so we can slbie it later */ | ||
| 79 | ld r10, SHADOW_SLB_ESID(0)(r12) | ||
| 80 | ld r11, SHADOW_SLB_VSID(0)(r12) | ||
| 81 | |||
| 82 | /* Remove bolted entries */ | ||
| 83 | UNBOLT_SLB_ENTRY(0) | ||
| 84 | UNBOLT_SLB_ENTRY(1) | ||
| 85 | UNBOLT_SLB_ENTRY(2) | ||
| 86 | |||
| 87 | #else | ||
| 88 | #error unknown number of bolted entries | ||
| 89 | #endif | ||
| 90 | |||
| 91 | /* Flush SLB */ | ||
| 92 | |||
| 93 | slbia | ||
| 94 | |||
| 95 | /* r0 = esid & ESID_MASK */ | ||
| 96 | rldicr r10, r10, 0, 35 | ||
| 97 | /* r0 |= CLASS_BIT(VSID) */ | ||
| 98 | rldic r12, r11, 56 - 36, 36 | ||
| 99 | or r10, r10, r12 | ||
| 100 | slbie r10 | ||
| 101 | |||
| 102 | isync | ||
| 103 | |||
| 104 | /* Fill SLB with our shadow */ | ||
| 105 | |||
| 106 | lbz r12, PACA_KVM_SLB_MAX(r13) | ||
| 107 | mulli r12, r12, 16 | ||
| 108 | addi r12, r12, PACA_KVM_SLB | ||
| 109 | add r12, r12, r13 | ||
| 110 | |||
| 111 | /* for (r11 = kvm_slb; r11 < kvm_slb + kvm_slb_size; r11+=slb_entry) */ | ||
| 112 | li r11, PACA_KVM_SLB | ||
| 113 | add r11, r11, r13 | ||
| 114 | |||
| 115 | slb_loop_enter: | ||
| 116 | |||
| 117 | ld r10, 0(r11) | ||
| 118 | |||
| 119 | rldicl. r0, r10, 37, 63 | ||
| 120 | beq slb_loop_enter_skip | ||
| 121 | |||
| 122 | ld r9, 8(r11) | ||
| 123 | slbmte r9, r10 | ||
| 124 | |||
| 125 | slb_loop_enter_skip: | ||
| 126 | addi r11, r11, 16 | ||
| 127 | cmpd cr0, r11, r12 | ||
| 128 | blt slb_loop_enter | ||
| 129 | |||
| 130 | slb_do_enter: | ||
| 131 | |||
| 132 | /* Enter guest */ | ||
| 133 | |||
| 134 | mfspr r0, SPRN_SPRG_SCRATCH0 | ||
| 135 | |||
| 136 | ld r9, (PACA_EXMC+EX_R9)(r13) | ||
| 137 | ld r10, (PACA_EXMC+EX_R10)(r13) | ||
| 138 | ld r12, (PACA_EXMC+EX_R12)(r13) | ||
| 139 | |||
| 140 | lwz r11, (PACA_EXMC+EX_CCR)(r13) | ||
| 141 | mtcr r11 | ||
| 142 | |||
| 143 | ld r11, (PACA_EXMC+EX_R3)(r13) | ||
| 144 | mtxer r11 | ||
| 145 | |||
| 146 | ld r11, (PACA_EXMC+EX_R11)(r13) | ||
| 147 | ld r13, (PACA_EXMC+EX_R13)(r13) | ||
| 148 | |||
| 149 | RFI | ||
| 150 | kvmppc_handler_trampoline_enter_end: | ||
| 151 | |||
| 152 | |||
| 153 | |||
| 154 | /****************************************************************************** | ||
| 155 | * * | ||
| 156 | * Exit code * | ||
| 157 | * * | ||
| 158 | *****************************************************************************/ | ||
| 159 | |||
| 160 | .global kvmppc_handler_trampoline_exit | ||
| 161 | kvmppc_handler_trampoline_exit: | ||
| 162 | |||
| 163 | /* Register usage at this point: | ||
| 164 | * | ||
| 165 | * SPRG_SCRATCH0 = guest R13 | ||
| 166 | * R01 = host R1 | ||
| 167 | * R02 = host R2 | ||
| 168 | * R10 = guest PC | ||
| 169 | * R11 = guest MSR | ||
| 170 | * R12 = exit handler id | ||
| 171 | * R13 = PACA | ||
| 172 | * PACA.exmc.CCR = guest CR | ||
| 173 | * PACA.exmc.R9 = guest R1 | ||
| 174 | * PACA.exmc.R10 = guest R10 | ||
| 175 | * PACA.exmc.R11 = guest R11 | ||
| 176 | * PACA.exmc.R12 = guest R12 | ||
| 177 | * PACA.exmc.R13 = guest R2 | ||
| 178 | * | ||
| 179 | */ | ||
| 180 | |||
| 181 | /* Save registers */ | ||
| 182 | |||
| 183 | std r0, (PACA_EXMC+EX_SRR0)(r13) | ||
| 184 | std r9, (PACA_EXMC+EX_R3)(r13) | ||
| 185 | std r10, (PACA_EXMC+EX_LR)(r13) | ||
| 186 | std r11, (PACA_EXMC+EX_DAR)(r13) | ||
| 187 | |||
| 188 | /* | ||
| 189 | * In order for us to easily get the last instruction, | ||
| 190 | * we got the #vmexit at, we exploit the fact that the | ||
| 191 | * virtual layout is still the same here, so we can just | ||
| 192 | * ld from the guest's PC address | ||
| 193 | */ | ||
| 194 | |||
| 195 | /* We only load the last instruction when it's safe */ | ||
| 196 | cmpwi r12, BOOK3S_INTERRUPT_DATA_STORAGE | ||
| 197 | beq ld_last_inst | ||
| 198 | cmpwi r12, BOOK3S_INTERRUPT_PROGRAM | ||
| 199 | beq ld_last_inst | ||
| 200 | |||
| 201 | b no_ld_last_inst | ||
| 202 | |||
| 203 | ld_last_inst: | ||
| 204 | /* Save off the guest instruction we're at */ | ||
| 205 | /* 1) enable paging for data */ | ||
| 206 | mfmsr r9 | ||
| 207 | ori r11, r9, MSR_DR /* Enable paging for data */ | ||
| 208 | mtmsr r11 | ||
| 209 | /* 2) fetch the instruction */ | ||
| 210 | lwz r0, 0(r10) | ||
| 211 | /* 3) disable paging again */ | ||
| 212 | mtmsr r9 | ||
| 213 | |||
| 214 | no_ld_last_inst: | ||
| 215 | |||
| 216 | /* Restore bolted entries from the shadow and fix it along the way */ | ||
| 217 | |||
| 218 | /* We don't store anything in entry 0, so we don't need to take care of it */ | ||
| 219 | slbia | ||
| 220 | isync | ||
| 221 | |||
| 222 | #if SLB_NUM_BOLTED == 3 | ||
| 223 | |||
| 224 | ld r11, PACA_SLBSHADOWPTR(r13) | ||
| 225 | |||
| 226 | REBOLT_SLB_ENTRY(0) | ||
| 227 | REBOLT_SLB_ENTRY(1) | ||
| 228 | REBOLT_SLB_ENTRY(2) | ||
| 229 | |||
| 230 | #else | ||
| 231 | #error unknown number of bolted entries | ||
| 232 | #endif | ||
| 233 | |||
| 234 | slb_do_exit: | ||
| 235 | |||
| 236 | /* Restore registers */ | ||
| 237 | |||
| 238 | ld r11, (PACA_EXMC+EX_DAR)(r13) | ||
| 239 | ld r10, (PACA_EXMC+EX_LR)(r13) | ||
| 240 | ld r9, (PACA_EXMC+EX_R3)(r13) | ||
| 241 | |||
| 242 | /* Save last inst */ | ||
| 243 | stw r0, (PACA_EXMC+EX_LR)(r13) | ||
| 244 | |||
| 245 | /* Save DAR and DSISR before going to paged mode */ | ||
| 246 | mfdar r0 | ||
| 247 | std r0, (PACA_EXMC+EX_DAR)(r13) | ||
| 248 | mfdsisr r0 | ||
| 249 | stw r0, (PACA_EXMC+EX_DSISR)(r13) | ||
| 250 | |||
| 251 | /* RFI into the highmem handler */ | ||
| 252 | mfmsr r0 | ||
| 253 | ori r0, r0, MSR_IR|MSR_DR|MSR_RI /* Enable paging */ | ||
| 254 | mtsrr1 r0 | ||
| 255 | ld r0, PACASAVEDMSR(r13) /* Highmem handler address */ | ||
| 256 | mtsrr0 r0 | ||
| 257 | |||
| 258 | mfspr r0, SPRN_SPRG_SCRATCH0 | ||
| 259 | |||
| 260 | RFI | ||
| 261 | kvmppc_handler_trampoline_exit_end: | ||
| 262 | |||
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index e7bf4d029484..06f5a9ecc42c 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c | |||
| @@ -520,6 +520,11 @@ int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, | |||
| 520 | return kvmppc_core_vcpu_translate(vcpu, tr); | 520 | return kvmppc_core_vcpu_translate(vcpu, tr); |
| 521 | } | 521 | } |
| 522 | 522 | ||
| 523 | int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) | ||
| 524 | { | ||
| 525 | return -ENOTSUPP; | ||
| 526 | } | ||
| 527 | |||
| 523 | int __init kvmppc_booke_init(void) | 528 | int __init kvmppc_booke_init(void) |
| 524 | { | 529 | { |
| 525 | unsigned long ivor[16]; | 530 | unsigned long ivor[16]; |
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c index 7737146af3fb..4a9ac6640fad 100644 --- a/arch/powerpc/kvm/emulate.c +++ b/arch/powerpc/kvm/emulate.c | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | */ | 18 | */ |
| 19 | 19 | ||
| 20 | #include <linux/jiffies.h> | 20 | #include <linux/jiffies.h> |
| 21 | #include <linux/timer.h> | 21 | #include <linux/hrtimer.h> |
| 22 | #include <linux/types.h> | 22 | #include <linux/types.h> |
| 23 | #include <linux/string.h> | 23 | #include <linux/string.h> |
| 24 | #include <linux/kvm_host.h> | 24 | #include <linux/kvm_host.h> |
| @@ -32,6 +32,7 @@ | |||
| 32 | #include "trace.h" | 32 | #include "trace.h" |
| 33 | 33 | ||
| 34 | #define OP_TRAP 3 | 34 | #define OP_TRAP 3 |
| 35 | #define OP_TRAP_64 2 | ||
| 35 | 36 | ||
| 36 | #define OP_31_XOP_LWZX 23 | 37 | #define OP_31_XOP_LWZX 23 |
| 37 | #define OP_31_XOP_LBZX 87 | 38 | #define OP_31_XOP_LBZX 87 |
| @@ -64,19 +65,45 @@ | |||
| 64 | #define OP_STH 44 | 65 | #define OP_STH 44 |
| 65 | #define OP_STHU 45 | 66 | #define OP_STHU 45 |
| 66 | 67 | ||
| 68 | #ifdef CONFIG_PPC64 | ||
| 69 | static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu) | ||
| 70 | { | ||
| 71 | return 1; | ||
| 72 | } | ||
| 73 | #else | ||
| 74 | static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu) | ||
| 75 | { | ||
| 76 | return vcpu->arch.tcr & TCR_DIE; | ||
| 77 | } | ||
| 78 | #endif | ||
| 79 | |||
| 67 | void kvmppc_emulate_dec(struct kvm_vcpu *vcpu) | 80 | void kvmppc_emulate_dec(struct kvm_vcpu *vcpu) |
| 68 | { | 81 | { |
| 69 | if (vcpu->arch.tcr & TCR_DIE) { | 82 | unsigned long dec_nsec; |
| 83 | |||
| 84 | pr_debug("mtDEC: %x\n", vcpu->arch.dec); | ||
| 85 | #ifdef CONFIG_PPC64 | ||
| 86 | /* POWER4+ triggers a dec interrupt if the value is < 0 */ | ||
| 87 | if (vcpu->arch.dec & 0x80000000) { | ||
| 88 | hrtimer_try_to_cancel(&vcpu->arch.dec_timer); | ||
| 89 | kvmppc_core_queue_dec(vcpu); | ||
| 90 | return; | ||
| 91 | } | ||
| 92 | #endif | ||
| 93 | if (kvmppc_dec_enabled(vcpu)) { | ||
| 70 | /* The decrementer ticks at the same rate as the timebase, so | 94 | /* The decrementer ticks at the same rate as the timebase, so |
| 71 | * that's how we convert the guest DEC value to the number of | 95 | * that's how we convert the guest DEC value to the number of |
| 72 | * host ticks. */ | 96 | * host ticks. */ |
| 73 | unsigned long nr_jiffies; | ||
| 74 | 97 | ||
| 75 | nr_jiffies = vcpu->arch.dec / tb_ticks_per_jiffy; | 98 | hrtimer_try_to_cancel(&vcpu->arch.dec_timer); |
| 76 | mod_timer(&vcpu->arch.dec_timer, | 99 | dec_nsec = vcpu->arch.dec; |
| 77 | get_jiffies_64() + nr_jiffies); | 100 | dec_nsec *= 1000; |
| 101 | dec_nsec /= tb_ticks_per_usec; | ||
| 102 | hrtimer_start(&vcpu->arch.dec_timer, ktime_set(0, dec_nsec), | ||
| 103 | HRTIMER_MODE_REL); | ||
| 104 | vcpu->arch.dec_jiffies = get_tb(); | ||
| 78 | } else { | 105 | } else { |
| 79 | del_timer(&vcpu->arch.dec_timer); | 106 | hrtimer_try_to_cancel(&vcpu->arch.dec_timer); |
| 80 | } | 107 | } |
| 81 | } | 108 | } |
| 82 | 109 | ||
| @@ -111,9 +138,15 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
| 111 | /* this default type might be overwritten by subcategories */ | 138 | /* this default type might be overwritten by subcategories */ |
| 112 | kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS); | 139 | kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS); |
| 113 | 140 | ||
| 141 | pr_debug(KERN_INFO "Emulating opcode %d / %d\n", get_op(inst), get_xop(inst)); | ||
| 142 | |||
| 114 | switch (get_op(inst)) { | 143 | switch (get_op(inst)) { |
| 115 | case OP_TRAP: | 144 | case OP_TRAP: |
| 145 | #ifdef CONFIG_PPC64 | ||
| 146 | case OP_TRAP_64: | ||
| 147 | #else | ||
| 116 | vcpu->arch.esr |= ESR_PTR; | 148 | vcpu->arch.esr |= ESR_PTR; |
| 149 | #endif | ||
| 117 | kvmppc_core_queue_program(vcpu); | 150 | kvmppc_core_queue_program(vcpu); |
| 118 | advance = 0; | 151 | advance = 0; |
| 119 | break; | 152 | break; |
| @@ -188,17 +221,19 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
| 188 | case SPRN_SRR1: | 221 | case SPRN_SRR1: |
| 189 | vcpu->arch.gpr[rt] = vcpu->arch.srr1; break; | 222 | vcpu->arch.gpr[rt] = vcpu->arch.srr1; break; |
| 190 | case SPRN_PVR: | 223 | case SPRN_PVR: |
| 191 | vcpu->arch.gpr[rt] = mfspr(SPRN_PVR); break; | 224 | vcpu->arch.gpr[rt] = vcpu->arch.pvr; break; |
| 192 | case SPRN_PIR: | 225 | case SPRN_PIR: |
| 193 | vcpu->arch.gpr[rt] = mfspr(SPRN_PIR); break; | 226 | vcpu->arch.gpr[rt] = vcpu->vcpu_id; break; |
| 227 | case SPRN_MSSSR0: | ||
| 228 | vcpu->arch.gpr[rt] = 0; break; | ||
| 194 | 229 | ||
| 195 | /* Note: mftb and TBRL/TBWL are user-accessible, so | 230 | /* Note: mftb and TBRL/TBWL are user-accessible, so |
| 196 | * the guest can always access the real TB anyways. | 231 | * the guest can always access the real TB anyways. |
| 197 | * In fact, we probably will never see these traps. */ | 232 | * In fact, we probably will never see these traps. */ |
| 198 | case SPRN_TBWL: | 233 | case SPRN_TBWL: |
| 199 | vcpu->arch.gpr[rt] = mftbl(); break; | 234 | vcpu->arch.gpr[rt] = get_tb() >> 32; break; |
| 200 | case SPRN_TBWU: | 235 | case SPRN_TBWU: |
| 201 | vcpu->arch.gpr[rt] = mftbu(); break; | 236 | vcpu->arch.gpr[rt] = get_tb(); break; |
| 202 | 237 | ||
| 203 | case SPRN_SPRG0: | 238 | case SPRN_SPRG0: |
| 204 | vcpu->arch.gpr[rt] = vcpu->arch.sprg0; break; | 239 | vcpu->arch.gpr[rt] = vcpu->arch.sprg0; break; |
| @@ -211,6 +246,13 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
| 211 | /* Note: SPRG4-7 are user-readable, so we don't get | 246 | /* Note: SPRG4-7 are user-readable, so we don't get |
| 212 | * a trap. */ | 247 | * a trap. */ |
| 213 | 248 | ||
| 249 | case SPRN_DEC: | ||
| 250 | { | ||
| 251 | u64 jd = get_tb() - vcpu->arch.dec_jiffies; | ||
| 252 | vcpu->arch.gpr[rt] = vcpu->arch.dec - jd; | ||
| 253 | pr_debug(KERN_INFO "mfDEC: %x - %llx = %lx\n", vcpu->arch.dec, jd, vcpu->arch.gpr[rt]); | ||
| 254 | break; | ||
| 255 | } | ||
| 214 | default: | 256 | default: |
| 215 | emulated = kvmppc_core_emulate_mfspr(vcpu, sprn, rt); | 257 | emulated = kvmppc_core_emulate_mfspr(vcpu, sprn, rt); |
| 216 | if (emulated == EMULATE_FAIL) { | 258 | if (emulated == EMULATE_FAIL) { |
| @@ -260,6 +302,8 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
| 260 | case SPRN_TBWL: break; | 302 | case SPRN_TBWL: break; |
| 261 | case SPRN_TBWU: break; | 303 | case SPRN_TBWU: break; |
| 262 | 304 | ||
| 305 | case SPRN_MSSSR0: break; | ||
| 306 | |||
| 263 | case SPRN_DEC: | 307 | case SPRN_DEC: |
| 264 | vcpu->arch.dec = vcpu->arch.gpr[rs]; | 308 | vcpu->arch.dec = vcpu->arch.gpr[rs]; |
| 265 | kvmppc_emulate_dec(vcpu); | 309 | kvmppc_emulate_dec(vcpu); |
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 5902bbc2411e..f06cf93b178e 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/kvm_host.h> | 23 | #include <linux/kvm_host.h> |
| 24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
| 25 | #include <linux/vmalloc.h> | 25 | #include <linux/vmalloc.h> |
| 26 | #include <linux/hrtimer.h> | ||
| 26 | #include <linux/fs.h> | 27 | #include <linux/fs.h> |
| 27 | #include <asm/cputable.h> | 28 | #include <asm/cputable.h> |
| 28 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
| @@ -144,6 +145,9 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
| 144 | int r; | 145 | int r; |
| 145 | 146 | ||
| 146 | switch (ext) { | 147 | switch (ext) { |
| 148 | case KVM_CAP_PPC_SEGSTATE: | ||
| 149 | r = 1; | ||
| 150 | break; | ||
| 147 | case KVM_CAP_COALESCED_MMIO: | 151 | case KVM_CAP_COALESCED_MMIO: |
| 148 | r = KVM_COALESCED_MMIO_PAGE_OFFSET; | 152 | r = KVM_COALESCED_MMIO_PAGE_OFFSET; |
| 149 | break; | 153 | break; |
| @@ -209,10 +213,25 @@ static void kvmppc_decrementer_func(unsigned long data) | |||
| 209 | } | 213 | } |
| 210 | } | 214 | } |
| 211 | 215 | ||
| 216 | /* | ||
| 217 | * low level hrtimer wake routine. Because this runs in hardirq context | ||
| 218 | * we schedule a tasklet to do the real work. | ||
| 219 | */ | ||
| 220 | enum hrtimer_restart kvmppc_decrementer_wakeup(struct hrtimer *timer) | ||
| 221 | { | ||
| 222 | struct kvm_vcpu *vcpu; | ||
| 223 | |||
| 224 | vcpu = container_of(timer, struct kvm_vcpu, arch.dec_timer); | ||
| 225 | tasklet_schedule(&vcpu->arch.tasklet); | ||
| 226 | |||
| 227 | return HRTIMER_NORESTART; | ||
| 228 | } | ||
| 229 | |||
| 212 | int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) | 230 | int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) |
| 213 | { | 231 | { |
| 214 | setup_timer(&vcpu->arch.dec_timer, kvmppc_decrementer_func, | 232 | hrtimer_init(&vcpu->arch.dec_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); |
| 215 | (unsigned long)vcpu); | 233 | tasklet_init(&vcpu->arch.tasklet, kvmppc_decrementer_func, (ulong)vcpu); |
| 234 | vcpu->arch.dec_timer.function = kvmppc_decrementer_wakeup; | ||
| 216 | 235 | ||
| 217 | return 0; | 236 | return 0; |
| 218 | } | 237 | } |
| @@ -410,11 +429,6 @@ out: | |||
| 410 | return r; | 429 | return r; |
| 411 | } | 430 | } |
| 412 | 431 | ||
| 413 | int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) | ||
| 414 | { | ||
| 415 | return -ENOTSUPP; | ||
| 416 | } | ||
| 417 | |||
| 418 | long kvm_arch_vm_ioctl(struct file *filp, | 432 | long kvm_arch_vm_ioctl(struct file *filp, |
| 419 | unsigned int ioctl, unsigned long arg) | 433 | unsigned int ioctl, unsigned long arg) |
| 420 | { | 434 | { |
diff --git a/arch/powerpc/kvm/timing.c b/arch/powerpc/kvm/timing.c index 2aa371e30079..70378551c0cc 100644 --- a/arch/powerpc/kvm/timing.c +++ b/arch/powerpc/kvm/timing.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/seq_file.h> | 23 | #include <linux/seq_file.h> |
| 24 | #include <linux/debugfs.h> | 24 | #include <linux/debugfs.h> |
| 25 | #include <linux/uaccess.h> | 25 | #include <linux/uaccess.h> |
| 26 | #include <linux/module.h> | ||
| 26 | 27 | ||
| 27 | #include <asm/time.h> | 28 | #include <asm/time.h> |
| 28 | #include <asm-generic/div64.h> | 29 | #include <asm-generic/div64.h> |
diff --git a/arch/powerpc/kvm/trace.h b/arch/powerpc/kvm/trace.h index 67f219de0455..a8e840018052 100644 --- a/arch/powerpc/kvm/trace.h +++ b/arch/powerpc/kvm/trace.h | |||
| @@ -12,8 +12,8 @@ | |||
| 12 | * Tracepoint for guest mode entry. | 12 | * Tracepoint for guest mode entry. |
| 13 | */ | 13 | */ |
| 14 | TRACE_EVENT(kvm_ppc_instr, | 14 | TRACE_EVENT(kvm_ppc_instr, |
| 15 | TP_PROTO(unsigned int inst, unsigned long pc, unsigned int emulate), | 15 | TP_PROTO(unsigned int inst, unsigned long _pc, unsigned int emulate), |
| 16 | TP_ARGS(inst, pc, emulate), | 16 | TP_ARGS(inst, _pc, emulate), |
| 17 | 17 | ||
| 18 | TP_STRUCT__entry( | 18 | TP_STRUCT__entry( |
| 19 | __field( unsigned int, inst ) | 19 | __field( unsigned int, inst ) |
| @@ -23,7 +23,7 @@ TRACE_EVENT(kvm_ppc_instr, | |||
| 23 | 23 | ||
| 24 | TP_fast_assign( | 24 | TP_fast_assign( |
| 25 | __entry->inst = inst; | 25 | __entry->inst = inst; |
| 26 | __entry->pc = pc; | 26 | __entry->pc = _pc; |
| 27 | __entry->emulate = emulate; | 27 | __entry->emulate = emulate; |
| 28 | ), | 28 | ), |
| 29 | 29 | ||
diff --git a/arch/powerpc/lib/copy_32.S b/arch/powerpc/lib/copy_32.S index c657de59abca..74a7f4130b4c 100644 --- a/arch/powerpc/lib/copy_32.S +++ b/arch/powerpc/lib/copy_32.S | |||
| @@ -98,20 +98,7 @@ _GLOBAL(cacheable_memzero) | |||
| 98 | bdnz 4b | 98 | bdnz 4b |
| 99 | 3: mtctr r9 | 99 | 3: mtctr r9 |
| 100 | li r7,4 | 100 | li r7,4 |
| 101 | #if !defined(CONFIG_8xx) | ||
| 102 | 10: dcbz r7,r6 | 101 | 10: dcbz r7,r6 |
| 103 | #else | ||
| 104 | 10: stw r4, 4(r6) | ||
| 105 | stw r4, 8(r6) | ||
| 106 | stw r4, 12(r6) | ||
| 107 | stw r4, 16(r6) | ||
| 108 | #if CACHE_LINE_SIZE >= 32 | ||
| 109 | stw r4, 20(r6) | ||
| 110 | stw r4, 24(r6) | ||
| 111 | stw r4, 28(r6) | ||
| 112 | stw r4, 32(r6) | ||
| 113 | #endif /* CACHE_LINE_SIZE */ | ||
| 114 | #endif | ||
| 115 | addi r6,r6,CACHELINE_BYTES | 102 | addi r6,r6,CACHELINE_BYTES |
| 116 | bdnz 10b | 103 | bdnz 10b |
| 117 | clrlwi r5,r8,32-LG_CACHELINE_BYTES | 104 | clrlwi r5,r8,32-LG_CACHELINE_BYTES |
| @@ -200,9 +187,7 @@ _GLOBAL(cacheable_memcpy) | |||
| 200 | mtctr r0 | 187 | mtctr r0 |
| 201 | beq 63f | 188 | beq 63f |
| 202 | 53: | 189 | 53: |
| 203 | #if !defined(CONFIG_8xx) | ||
| 204 | dcbz r11,r6 | 190 | dcbz r11,r6 |
| 205 | #endif | ||
| 206 | COPY_16_BYTES | 191 | COPY_16_BYTES |
| 207 | #if L1_CACHE_BYTES >= 32 | 192 | #if L1_CACHE_BYTES >= 32 |
| 208 | COPY_16_BYTES | 193 | COPY_16_BYTES |
| @@ -356,14 +341,6 @@ _GLOBAL(__copy_tofrom_user) | |||
| 356 | li r11,4 | 341 | li r11,4 |
| 357 | beq 63f | 342 | beq 63f |
| 358 | 343 | ||
| 359 | #ifdef CONFIG_8xx | ||
| 360 | /* Don't use prefetch on 8xx */ | ||
| 361 | mtctr r0 | ||
| 362 | li r0,0 | ||
| 363 | 53: COPY_16_BYTES_WITHEX(0) | ||
| 364 | bdnz 53b | ||
| 365 | |||
| 366 | #else /* not CONFIG_8xx */ | ||
| 367 | /* Here we decide how far ahead to prefetch the source */ | 344 | /* Here we decide how far ahead to prefetch the source */ |
| 368 | li r3,4 | 345 | li r3,4 |
| 369 | cmpwi r0,1 | 346 | cmpwi r0,1 |
| @@ -416,7 +393,6 @@ _GLOBAL(__copy_tofrom_user) | |||
| 416 | li r3,4 | 393 | li r3,4 |
| 417 | li r7,0 | 394 | li r7,0 |
| 418 | bne 114b | 395 | bne 114b |
| 419 | #endif /* CONFIG_8xx */ | ||
| 420 | 396 | ||
| 421 | 63: srwi. r0,r5,2 | 397 | 63: srwi. r0,r5,2 |
| 422 | mtctr r0 | 398 | mtctr r0 |
diff --git a/arch/powerpc/lib/locks.c b/arch/powerpc/lib/locks.c index 79d0fa3a470d..58e14fba11b1 100644 --- a/arch/powerpc/lib/locks.c +++ b/arch/powerpc/lib/locks.c | |||
| @@ -25,7 +25,7 @@ | |||
| 25 | #include <asm/smp.h> | 25 | #include <asm/smp.h> |
| 26 | #include <asm/firmware.h> | 26 | #include <asm/firmware.h> |
| 27 | 27 | ||
| 28 | void __spin_yield(raw_spinlock_t *lock) | 28 | void __spin_yield(arch_spinlock_t *lock) |
| 29 | { | 29 | { |
| 30 | unsigned int lock_value, holder_cpu, yield_count; | 30 | unsigned int lock_value, holder_cpu, yield_count; |
| 31 | 31 | ||
| @@ -55,7 +55,7 @@ void __spin_yield(raw_spinlock_t *lock) | |||
| 55 | * This turns out to be the same for read and write locks, since | 55 | * This turns out to be the same for read and write locks, since |
| 56 | * we only know the holder if it is write-locked. | 56 | * we only know the holder if it is write-locked. |
| 57 | */ | 57 | */ |
| 58 | void __rw_yield(raw_rwlock_t *rw) | 58 | void __rw_yield(arch_rwlock_t *rw) |
| 59 | { | 59 | { |
| 60 | int lock_value; | 60 | int lock_value; |
| 61 | unsigned int holder_cpu, yield_count; | 61 | unsigned int holder_cpu, yield_count; |
| @@ -82,7 +82,7 @@ void __rw_yield(raw_rwlock_t *rw) | |||
| 82 | } | 82 | } |
| 83 | #endif | 83 | #endif |
| 84 | 84 | ||
| 85 | void __raw_spin_unlock_wait(raw_spinlock_t *lock) | 85 | void arch_spin_unlock_wait(arch_spinlock_t *lock) |
| 86 | { | 86 | { |
| 87 | while (lock->slock) { | 87 | while (lock->slock) { |
| 88 | HMT_low(); | 88 | HMT_low(); |
| @@ -92,4 +92,4 @@ void __raw_spin_unlock_wait(raw_spinlock_t *lock) | |||
| 92 | HMT_medium(); | 92 | HMT_medium(); |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | EXPORT_SYMBOL(__raw_spin_unlock_wait); | 95 | EXPORT_SYMBOL(arch_spin_unlock_wait); |
diff --git a/arch/powerpc/mm/40x_mmu.c b/arch/powerpc/mm/40x_mmu.c index f5e7b9ce63dd..08dfa8e6d86f 100644 --- a/arch/powerpc/mm/40x_mmu.c +++ b/arch/powerpc/mm/40x_mmu.c | |||
| @@ -91,7 +91,7 @@ void __init MMU_init_hw(void) | |||
| 91 | #define LARGE_PAGE_SIZE_16M (1<<24) | 91 | #define LARGE_PAGE_SIZE_16M (1<<24) |
| 92 | #define LARGE_PAGE_SIZE_4M (1<<22) | 92 | #define LARGE_PAGE_SIZE_4M (1<<22) |
| 93 | 93 | ||
| 94 | unsigned long __init mmu_mapin_ram(void) | 94 | unsigned long __init mmu_mapin_ram(unsigned long top) |
| 95 | { | 95 | { |
| 96 | unsigned long v, s, mapped; | 96 | unsigned long v, s, mapped; |
| 97 | phys_addr_t p; | 97 | phys_addr_t p; |
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c index 98052ac96580..3986264b0993 100644 --- a/arch/powerpc/mm/44x_mmu.c +++ b/arch/powerpc/mm/44x_mmu.c | |||
| @@ -88,7 +88,7 @@ void __init MMU_init_hw(void) | |||
| 88 | flush_instruction_cache(); | 88 | flush_instruction_cache(); |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | unsigned long __init mmu_mapin_ram(void) | 91 | unsigned long __init mmu_mapin_ram(unsigned long top) |
| 92 | { | 92 | { |
| 93 | unsigned long addr; | 93 | unsigned long addr; |
| 94 | 94 | ||
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index 6fb8fc8d2fea..ce68708bbad5 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile | |||
| @@ -28,7 +28,10 @@ obj-$(CONFIG_44x) += 44x_mmu.o | |||
| 28 | obj-$(CONFIG_FSL_BOOKE) += fsl_booke_mmu.o | 28 | obj-$(CONFIG_FSL_BOOKE) += fsl_booke_mmu.o |
| 29 | obj-$(CONFIG_NEED_MULTIPLE_NODES) += numa.o | 29 | obj-$(CONFIG_NEED_MULTIPLE_NODES) += numa.o |
| 30 | obj-$(CONFIG_PPC_MM_SLICES) += slice.o | 30 | obj-$(CONFIG_PPC_MM_SLICES) += slice.o |
| 31 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o | 31 | ifeq ($(CONFIG_HUGETLB_PAGE),y) |
| 32 | obj-y += hugetlbpage.o | ||
| 33 | obj-$(CONFIG_PPC_STD_MMU_64) += hugetlbpage-hash64.o | ||
| 34 | endif | ||
| 32 | obj-$(CONFIG_PPC_SUBPAGE_PROT) += subpage-prot.o | 35 | obj-$(CONFIG_PPC_SUBPAGE_PROT) += subpage-prot.o |
| 33 | obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o | 36 | obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o |
| 34 | obj-$(CONFIG_HIGHMEM) += highmem.o | 37 | obj-$(CONFIG_HIGHMEM) += highmem.o |
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index e7dae82c1285..26fb6b990b0a 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
| @@ -40,7 +40,7 @@ | |||
| 40 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
| 41 | #include <asm/tlbflush.h> | 41 | #include <asm/tlbflush.h> |
| 42 | #include <asm/siginfo.h> | 42 | #include <asm/siginfo.h> |
| 43 | 43 | #include <mm/mmu_decl.h> | |
| 44 | 44 | ||
| 45 | #ifdef CONFIG_KPROBES | 45 | #ifdef CONFIG_KPROBES |
| 46 | static inline int notify_page_fault(struct pt_regs *regs) | 46 | static inline int notify_page_fault(struct pt_regs *regs) |
| @@ -246,6 +246,12 @@ good_area: | |||
| 246 | goto bad_area; | 246 | goto bad_area; |
| 247 | #endif /* CONFIG_6xx */ | 247 | #endif /* CONFIG_6xx */ |
| 248 | #if defined(CONFIG_8xx) | 248 | #if defined(CONFIG_8xx) |
| 249 | /* 8xx sometimes need to load a invalid/non-present TLBs. | ||
| 250 | * These must be invalidated separately as linux mm don't. | ||
| 251 | */ | ||
| 252 | if (error_code & 0x40000000) /* no translation? */ | ||
| 253 | _tlbil_va(address, 0, 0, 0); | ||
| 254 | |||
| 249 | /* The MPC8xx seems to always set 0x80000000, which is | 255 | /* The MPC8xx seems to always set 0x80000000, which is |
| 250 | * "undefined". Of those that can be set, this is the only | 256 | * "undefined". Of those that can be set, this is the only |
| 251 | * one which seems bad. | 257 | * one which seems bad. |
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c index dc93e95b256e..c5394728bf2e 100644 --- a/arch/powerpc/mm/fsl_booke_mmu.c +++ b/arch/powerpc/mm/fsl_booke_mmu.c | |||
| @@ -54,26 +54,35 @@ | |||
| 54 | 54 | ||
| 55 | #include "mmu_decl.h" | 55 | #include "mmu_decl.h" |
| 56 | 56 | ||
| 57 | extern void loadcam_entry(unsigned int index); | ||
| 58 | unsigned int tlbcam_index; | 57 | unsigned int tlbcam_index; |
| 59 | static unsigned long cam[CONFIG_LOWMEM_CAM_NUM]; | ||
| 60 | 58 | ||
| 61 | #define NUM_TLBCAMS (16) | 59 | #define NUM_TLBCAMS (64) |
| 62 | 60 | ||
| 63 | #if defined(CONFIG_LOWMEM_CAM_NUM_BOOL) && (CONFIG_LOWMEM_CAM_NUM >= NUM_TLBCAMS) | 61 | #if defined(CONFIG_LOWMEM_CAM_NUM_BOOL) && (CONFIG_LOWMEM_CAM_NUM >= NUM_TLBCAMS) |
| 64 | #error "LOWMEM_CAM_NUM must be less than NUM_TLBCAMS" | 62 | #error "LOWMEM_CAM_NUM must be less than NUM_TLBCAMS" |
| 65 | #endif | 63 | #endif |
| 66 | 64 | ||
| 67 | struct tlbcam TLBCAM[NUM_TLBCAMS]; | 65 | struct tlbcam { |
| 66 | u32 MAS0; | ||
| 67 | u32 MAS1; | ||
| 68 | unsigned long MAS2; | ||
| 69 | u32 MAS3; | ||
| 70 | u32 MAS7; | ||
| 71 | } TLBCAM[NUM_TLBCAMS]; | ||
| 68 | 72 | ||
| 69 | struct tlbcamrange { | 73 | struct tlbcamrange { |
| 70 | unsigned long start; | 74 | unsigned long start; |
| 71 | unsigned long limit; | 75 | unsigned long limit; |
| 72 | phys_addr_t phys; | 76 | phys_addr_t phys; |
| 73 | } tlbcam_addrs[NUM_TLBCAMS]; | 77 | } tlbcam_addrs[NUM_TLBCAMS]; |
| 74 | 78 | ||
| 75 | extern unsigned int tlbcam_index; | 79 | extern unsigned int tlbcam_index; |
| 76 | 80 | ||
| 81 | unsigned long tlbcam_sz(int idx) | ||
| 82 | { | ||
| 83 | return tlbcam_addrs[idx].limit - tlbcam_addrs[idx].start + 1; | ||
| 84 | } | ||
| 85 | |||
| 77 | /* | 86 | /* |
| 78 | * Return PA for this VA if it is mapped by a CAM, or 0 | 87 | * Return PA for this VA if it is mapped by a CAM, or 0 |
| 79 | */ | 88 | */ |
| @@ -94,23 +103,36 @@ unsigned long p_mapped_by_tlbcam(phys_addr_t pa) | |||
| 94 | int b; | 103 | int b; |
| 95 | for (b = 0; b < tlbcam_index; ++b) | 104 | for (b = 0; b < tlbcam_index; ++b) |
| 96 | if (pa >= tlbcam_addrs[b].phys | 105 | if (pa >= tlbcam_addrs[b].phys |
| 97 | && pa < (tlbcam_addrs[b].limit-tlbcam_addrs[b].start) | 106 | && pa < (tlbcam_addrs[b].limit-tlbcam_addrs[b].start) |
| 98 | +tlbcam_addrs[b].phys) | 107 | +tlbcam_addrs[b].phys) |
| 99 | return tlbcam_addrs[b].start+(pa-tlbcam_addrs[b].phys); | 108 | return tlbcam_addrs[b].start+(pa-tlbcam_addrs[b].phys); |
| 100 | return 0; | 109 | return 0; |
| 101 | } | 110 | } |
| 102 | 111 | ||
| 112 | void loadcam_entry(int idx) | ||
| 113 | { | ||
| 114 | mtspr(SPRN_MAS0, TLBCAM[idx].MAS0); | ||
| 115 | mtspr(SPRN_MAS1, TLBCAM[idx].MAS1); | ||
| 116 | mtspr(SPRN_MAS2, TLBCAM[idx].MAS2); | ||
| 117 | mtspr(SPRN_MAS3, TLBCAM[idx].MAS3); | ||
| 118 | |||
| 119 | if (cur_cpu_spec->cpu_features & MMU_FTR_BIG_PHYS) | ||
| 120 | mtspr(SPRN_MAS7, TLBCAM[idx].MAS7); | ||
| 121 | |||
| 122 | asm volatile("isync;tlbwe;isync" : : : "memory"); | ||
| 123 | } | ||
| 124 | |||
| 103 | /* | 125 | /* |
| 104 | * Set up one of the I/D BAT (block address translation) register pairs. | 126 | * Set up one of the I/D BAT (block address translation) register pairs. |
| 105 | * The parameters are not checked; in particular size must be a power | 127 | * The parameters are not checked; in particular size must be a power |
| 106 | * of 4 between 4k and 256M. | 128 | * of 4 between 4k and 256M. |
| 107 | */ | 129 | */ |
| 108 | void settlbcam(int index, unsigned long virt, phys_addr_t phys, | 130 | static void settlbcam(int index, unsigned long virt, phys_addr_t phys, |
| 109 | unsigned int size, int flags, unsigned int pid) | 131 | unsigned long size, unsigned long flags, unsigned int pid) |
| 110 | { | 132 | { |
| 111 | unsigned int tsize, lz; | 133 | unsigned int tsize, lz; |
| 112 | 134 | ||
| 113 | asm ("cntlzw %0,%1" : "=r" (lz) : "r" (size)); | 135 | asm (PPC_CNTLZL "%0,%1" : "=r" (lz) : "r" (size)); |
| 114 | tsize = 21 - lz; | 136 | tsize = 21 - lz; |
| 115 | 137 | ||
| 116 | #ifdef CONFIG_SMP | 138 | #ifdef CONFIG_SMP |
| @@ -128,8 +150,10 @@ void settlbcam(int index, unsigned long virt, phys_addr_t phys, | |||
| 128 | TLBCAM[index].MAS2 |= (flags & _PAGE_GUARDED) ? MAS2_G : 0; | 150 | TLBCAM[index].MAS2 |= (flags & _PAGE_GUARDED) ? MAS2_G : 0; |
| 129 | TLBCAM[index].MAS2 |= (flags & _PAGE_ENDIAN) ? MAS2_E : 0; | 151 | TLBCAM[index].MAS2 |= (flags & _PAGE_ENDIAN) ? MAS2_E : 0; |
| 130 | 152 | ||
| 131 | TLBCAM[index].MAS3 = (phys & PAGE_MASK) | MAS3_SX | MAS3_SR; | 153 | TLBCAM[index].MAS3 = (phys & MAS3_RPN) | MAS3_SX | MAS3_SR; |
| 132 | TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_SW : 0); | 154 | TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_SW : 0); |
| 155 | if (cur_cpu_spec->cpu_features & MMU_FTR_BIG_PHYS) | ||
| 156 | TLBCAM[index].MAS7 = (u64)phys >> 32; | ||
| 133 | 157 | ||
| 134 | #ifndef CONFIG_KGDB /* want user access for breakpoints */ | 158 | #ifndef CONFIG_KGDB /* want user access for breakpoints */ |
| 135 | if (flags & _PAGE_USER) { | 159 | if (flags & _PAGE_USER) { |
| @@ -148,27 +172,44 @@ void settlbcam(int index, unsigned long virt, phys_addr_t phys, | |||
| 148 | loadcam_entry(index); | 172 | loadcam_entry(index); |
| 149 | } | 173 | } |
| 150 | 174 | ||
| 151 | void invalidate_tlbcam_entry(int index) | 175 | unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx) |
| 152 | { | ||
| 153 | TLBCAM[index].MAS0 = MAS0_TLBSEL(1) | MAS0_ESEL(index); | ||
| 154 | TLBCAM[index].MAS1 = ~MAS1_VALID; | ||
| 155 | |||
| 156 | loadcam_entry(index); | ||
| 157 | } | ||
| 158 | |||
| 159 | unsigned long __init mmu_mapin_ram(void) | ||
| 160 | { | 176 | { |
| 177 | int i; | ||
| 161 | unsigned long virt = PAGE_OFFSET; | 178 | unsigned long virt = PAGE_OFFSET; |
| 162 | phys_addr_t phys = memstart_addr; | 179 | phys_addr_t phys = memstart_addr; |
| 180 | unsigned long amount_mapped = 0; | ||
| 181 | unsigned long max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xf; | ||
| 182 | |||
| 183 | /* Convert (4^max) kB to (2^max) bytes */ | ||
| 184 | max_cam = max_cam * 2 + 10; | ||
| 163 | 185 | ||
| 164 | while (tlbcam_index < ARRAY_SIZE(cam) && cam[tlbcam_index]) { | 186 | /* Calculate CAM values */ |
| 165 | settlbcam(tlbcam_index, virt, phys, cam[tlbcam_index], PAGE_KERNEL_X, 0); | 187 | for (i = 0; ram && i < max_cam_idx; i++) { |
| 166 | virt += cam[tlbcam_index]; | 188 | unsigned int camsize = __ilog2(ram) & ~1U; |
| 167 | phys += cam[tlbcam_index]; | 189 | unsigned int align = __ffs(virt | phys) & ~1U; |
| 168 | tlbcam_index++; | 190 | unsigned long cam_sz; |
| 191 | |||
| 192 | if (camsize > align) | ||
| 193 | camsize = align; | ||
| 194 | if (camsize > max_cam) | ||
| 195 | camsize = max_cam; | ||
| 196 | |||
| 197 | cam_sz = 1UL << camsize; | ||
| 198 | settlbcam(i, virt, phys, cam_sz, PAGE_KERNEL_X, 0); | ||
| 199 | |||
| 200 | ram -= cam_sz; | ||
| 201 | amount_mapped += cam_sz; | ||
| 202 | virt += cam_sz; | ||
| 203 | phys += cam_sz; | ||
| 169 | } | 204 | } |
| 205 | tlbcam_index = i; | ||
| 170 | 206 | ||
| 171 | return virt - PAGE_OFFSET; | 207 | return amount_mapped; |
| 208 | } | ||
| 209 | |||
| 210 | unsigned long __init mmu_mapin_ram(unsigned long top) | ||
| 211 | { | ||
| 212 | return tlbcam_addrs[tlbcam_index - 1].limit - PAGE_OFFSET + 1; | ||
| 172 | } | 213 | } |
| 173 | 214 | ||
| 174 | /* | 215 | /* |
| @@ -179,46 +220,21 @@ void __init MMU_init_hw(void) | |||
| 179 | flush_instruction_cache(); | 220 | flush_instruction_cache(); |
| 180 | } | 221 | } |
| 181 | 222 | ||
| 182 | void __init | 223 | void __init adjust_total_lowmem(void) |
| 183 | adjust_total_lowmem(void) | ||
| 184 | { | 224 | { |
| 185 | phys_addr_t ram; | 225 | unsigned long ram; |
| 186 | unsigned int max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xff; | ||
| 187 | char buf[ARRAY_SIZE(cam) * 5 + 1], *p = buf; | ||
| 188 | int i; | 226 | int i; |
| 189 | unsigned long virt = PAGE_OFFSET & 0xffffffffUL; | ||
| 190 | unsigned long phys = memstart_addr & 0xffffffffUL; | ||
| 191 | |||
| 192 | /* Convert (4^max) kB to (2^max) bytes */ | ||
| 193 | max_cam = max_cam * 2 + 10; | ||
| 194 | 227 | ||
| 195 | /* adjust lowmem size to __max_low_memory */ | 228 | /* adjust lowmem size to __max_low_memory */ |
| 196 | ram = min((phys_addr_t)__max_low_memory, (phys_addr_t)total_lowmem); | 229 | ram = min((phys_addr_t)__max_low_memory, (phys_addr_t)total_lowmem); |
| 197 | 230 | ||
| 198 | /* Calculate CAM values */ | 231 | __max_low_memory = map_mem_in_cams(ram, CONFIG_LOWMEM_CAM_NUM); |
| 199 | __max_low_memory = 0; | ||
| 200 | for (i = 0; ram && i < ARRAY_SIZE(cam); i++) { | ||
| 201 | unsigned int camsize = __ilog2(ram) & ~1U; | ||
| 202 | unsigned int align = __ffs(virt | phys) & ~1U; | ||
| 203 | |||
| 204 | if (camsize > align) | ||
| 205 | camsize = align; | ||
| 206 | if (camsize > max_cam) | ||
| 207 | camsize = max_cam; | ||
| 208 | |||
| 209 | cam[i] = 1UL << camsize; | ||
| 210 | ram -= cam[i]; | ||
| 211 | __max_low_memory += cam[i]; | ||
| 212 | virt += cam[i]; | ||
| 213 | phys += cam[i]; | ||
| 214 | 232 | ||
| 215 | p += sprintf(p, "%lu/", cam[i] >> 20); | 233 | pr_info("Memory CAM mapping: "); |
| 216 | } | 234 | for (i = 0; i < tlbcam_index - 1; i++) |
| 217 | for (; i < ARRAY_SIZE(cam); i++) | 235 | pr_cont("%lu/", tlbcam_sz(i) >> 20); |
| 218 | p += sprintf(p, "0/"); | 236 | pr_cont("%lu Mb, residual: %dMb\n", tlbcam_sz(tlbcam_index - 1) >> 20, |
| 219 | p[-1] = '\0'; | ||
| 220 | |||
| 221 | pr_info("Memory CAM mapping: %s Mb, residual: %dMb\n", buf, | ||
| 222 | (unsigned int)((total_lowmem - __max_low_memory) >> 20)); | 237 | (unsigned int)((total_lowmem - __max_low_memory) >> 20)); |
| 238 | |||
| 223 | __initial_memory_limit_addr = memstart_addr + __max_low_memory; | 239 | __initial_memory_limit_addr = memstart_addr + __max_low_memory; |
| 224 | } | 240 | } |
diff --git a/arch/powerpc/mm/gup.c b/arch/powerpc/mm/gup.c index bc122a120bf0..d7efdbf640c7 100644 --- a/arch/powerpc/mm/gup.c +++ b/arch/powerpc/mm/gup.c | |||
| @@ -55,57 +55,6 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr, | |||
| 55 | return 1; | 55 | return 1; |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | #ifdef CONFIG_HUGETLB_PAGE | ||
| 59 | static noinline int gup_huge_pte(pte_t *ptep, struct hstate *hstate, | ||
| 60 | unsigned long *addr, unsigned long end, | ||
| 61 | int write, struct page **pages, int *nr) | ||
| 62 | { | ||
| 63 | unsigned long mask; | ||
| 64 | unsigned long pte_end; | ||
| 65 | struct page *head, *page; | ||
| 66 | pte_t pte; | ||
| 67 | int refs; | ||
| 68 | |||
| 69 | pte_end = (*addr + huge_page_size(hstate)) & huge_page_mask(hstate); | ||
| 70 | if (pte_end < end) | ||
| 71 | end = pte_end; | ||
| 72 | |||
| 73 | pte = *ptep; | ||
| 74 | mask = _PAGE_PRESENT|_PAGE_USER; | ||
| 75 | if (write) | ||
| 76 | mask |= _PAGE_RW; | ||
| 77 | if ((pte_val(pte) & mask) != mask) | ||
| 78 | return 0; | ||
| 79 | /* hugepages are never "special" */ | ||
| 80 | VM_BUG_ON(!pfn_valid(pte_pfn(pte))); | ||
| 81 | |||
| 82 | refs = 0; | ||
| 83 | head = pte_page(pte); | ||
| 84 | page = head + ((*addr & ~huge_page_mask(hstate)) >> PAGE_SHIFT); | ||
| 85 | do { | ||
| 86 | VM_BUG_ON(compound_head(page) != head); | ||
| 87 | pages[*nr] = page; | ||
| 88 | (*nr)++; | ||
| 89 | page++; | ||
| 90 | refs++; | ||
| 91 | } while (*addr += PAGE_SIZE, *addr != end); | ||
| 92 | |||
| 93 | if (!page_cache_add_speculative(head, refs)) { | ||
| 94 | *nr -= refs; | ||
| 95 | return 0; | ||
| 96 | } | ||
| 97 | if (unlikely(pte_val(pte) != pte_val(*ptep))) { | ||
| 98 | /* Could be optimized better */ | ||
| 99 | while (*nr) { | ||
| 100 | put_page(page); | ||
| 101 | (*nr)--; | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | return 1; | ||
| 106 | } | ||
| 107 | #endif /* CONFIG_HUGETLB_PAGE */ | ||
| 108 | |||
| 109 | static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end, | 58 | static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end, |
| 110 | int write, struct page **pages, int *nr) | 59 | int write, struct page **pages, int *nr) |
| 111 | { | 60 | { |
| @@ -119,7 +68,11 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end, | |||
| 119 | next = pmd_addr_end(addr, end); | 68 | next = pmd_addr_end(addr, end); |
| 120 | if (pmd_none(pmd)) | 69 | if (pmd_none(pmd)) |
| 121 | return 0; | 70 | return 0; |
| 122 | if (!gup_pte_range(pmd, addr, next, write, pages, nr)) | 71 | if (is_hugepd(pmdp)) { |
| 72 | if (!gup_hugepd((hugepd_t *)pmdp, PMD_SHIFT, | ||
| 73 | addr, next, write, pages, nr)) | ||
| 74 | return 0; | ||
| 75 | } else if (!gup_pte_range(pmd, addr, next, write, pages, nr)) | ||
| 123 | return 0; | 76 | return 0; |
| 124 | } while (pmdp++, addr = next, addr != end); | 77 | } while (pmdp++, addr = next, addr != end); |
| 125 | 78 | ||
| @@ -139,7 +92,11 @@ static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end, | |||
| 139 | next = pud_addr_end(addr, end); | 92 | next = pud_addr_end(addr, end); |
| 140 | if (pud_none(pud)) | 93 | if (pud_none(pud)) |
| 141 | return 0; | 94 | return 0; |
| 142 | if (!gup_pmd_range(pud, addr, next, write, pages, nr)) | 95 | if (is_hugepd(pudp)) { |
| 96 | if (!gup_hugepd((hugepd_t *)pudp, PUD_SHIFT, | ||
| 97 | addr, next, write, pages, nr)) | ||
| 98 | return 0; | ||
| 99 | } else if (!gup_pmd_range(pud, addr, next, write, pages, nr)) | ||
| 143 | return 0; | 100 | return 0; |
| 144 | } while (pudp++, addr = next, addr != end); | 101 | } while (pudp++, addr = next, addr != end); |
| 145 | 102 | ||
| @@ -154,10 +111,6 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, | |||
| 154 | unsigned long next; | 111 | unsigned long next; |
| 155 | pgd_t *pgdp; | 112 | pgd_t *pgdp; |
| 156 | int nr = 0; | 113 | int nr = 0; |
| 157 | #ifdef CONFIG_PPC64 | ||
| 158 | unsigned int shift; | ||
| 159 | int psize; | ||
| 160 | #endif | ||
| 161 | 114 | ||
| 162 | pr_devel("%s(%lx,%x,%s)\n", __func__, start, nr_pages, write ? "write" : "read"); | 115 | pr_devel("%s(%lx,%x,%s)\n", __func__, start, nr_pages, write ? "write" : "read"); |
| 163 | 116 | ||
| @@ -172,25 +125,6 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, | |||
| 172 | 125 | ||
| 173 | pr_devel(" aligned: %lx .. %lx\n", start, end); | 126 | pr_devel(" aligned: %lx .. %lx\n", start, end); |
| 174 | 127 | ||
| 175 | #ifdef CONFIG_HUGETLB_PAGE | ||
| 176 | /* We bail out on slice boundary crossing when hugetlb is | ||
| 177 | * enabled in order to not have to deal with two different | ||
| 178 | * page table formats | ||
| 179 | */ | ||
| 180 | if (addr < SLICE_LOW_TOP) { | ||
| 181 | if (end > SLICE_LOW_TOP) | ||
| 182 | goto slow_irqon; | ||
| 183 | |||
| 184 | if (unlikely(GET_LOW_SLICE_INDEX(addr) != | ||
| 185 | GET_LOW_SLICE_INDEX(end - 1))) | ||
| 186 | goto slow_irqon; | ||
| 187 | } else { | ||
| 188 | if (unlikely(GET_HIGH_SLICE_INDEX(addr) != | ||
| 189 | GET_HIGH_SLICE_INDEX(end - 1))) | ||
| 190 | goto slow_irqon; | ||
| 191 | } | ||
| 192 | #endif /* CONFIG_HUGETLB_PAGE */ | ||
| 193 | |||
| 194 | /* | 128 | /* |
| 195 | * XXX: batch / limit 'nr', to avoid large irq off latency | 129 | * XXX: batch / limit 'nr', to avoid large irq off latency |
| 196 | * needs some instrumenting to determine the common sizes used by | 130 | * needs some instrumenting to determine the common sizes used by |
| @@ -210,54 +144,23 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, | |||
| 210 | */ | 144 | */ |
| 211 | local_irq_disable(); | 145 | local_irq_disable(); |
| 212 | 146 | ||
| 213 | #ifdef CONFIG_PPC64 | 147 | pgdp = pgd_offset(mm, addr); |
| 214 | /* Those bits are related to hugetlbfs implementation and only exist | 148 | do { |
| 215 | * on 64-bit for now | 149 | pgd_t pgd = *pgdp; |
| 216 | */ | 150 | |
| 217 | psize = get_slice_psize(mm, addr); | 151 | pr_devel(" %016lx: normal pgd %p\n", addr, |
| 218 | shift = mmu_psize_defs[psize].shift; | 152 | (void *)pgd_val(pgd)); |
| 219 | #endif /* CONFIG_PPC64 */ | 153 | next = pgd_addr_end(addr, end); |
| 220 | 154 | if (pgd_none(pgd)) | |
| 221 | #ifdef CONFIG_HUGETLB_PAGE | 155 | goto slow; |
| 222 | if (unlikely(mmu_huge_psizes[psize])) { | 156 | if (is_hugepd(pgdp)) { |
| 223 | pte_t *ptep; | 157 | if (!gup_hugepd((hugepd_t *)pgdp, PGDIR_SHIFT, |
| 224 | unsigned long a = addr; | 158 | addr, next, write, pages, &nr)) |
| 225 | unsigned long sz = ((1UL) << shift); | ||
| 226 | struct hstate *hstate = size_to_hstate(sz); | ||
| 227 | |||
| 228 | BUG_ON(!hstate); | ||
| 229 | /* | ||
| 230 | * XXX: could be optimized to avoid hstate | ||
| 231 | * lookup entirely (just use shift) | ||
| 232 | */ | ||
| 233 | |||
| 234 | do { | ||
| 235 | VM_BUG_ON(shift != mmu_psize_defs[get_slice_psize(mm, a)].shift); | ||
| 236 | ptep = huge_pte_offset(mm, a); | ||
| 237 | pr_devel(" %016lx: huge ptep %p\n", a, ptep); | ||
| 238 | if (!ptep || !gup_huge_pte(ptep, hstate, &a, end, write, pages, | ||
| 239 | &nr)) | ||
| 240 | goto slow; | ||
| 241 | } while (a != end); | ||
| 242 | } else | ||
| 243 | #endif /* CONFIG_HUGETLB_PAGE */ | ||
| 244 | { | ||
| 245 | pgdp = pgd_offset(mm, addr); | ||
| 246 | do { | ||
| 247 | pgd_t pgd = *pgdp; | ||
| 248 | |||
| 249 | #ifdef CONFIG_PPC64 | ||
| 250 | VM_BUG_ON(shift != mmu_psize_defs[get_slice_psize(mm, addr)].shift); | ||
| 251 | #endif | ||
| 252 | pr_devel(" %016lx: normal pgd %p\n", addr, | ||
| 253 | (void *)pgd_val(pgd)); | ||
| 254 | next = pgd_addr_end(addr, end); | ||
| 255 | if (pgd_none(pgd)) | ||
| 256 | goto slow; | ||
| 257 | if (!gup_pud_range(pgd, addr, next, write, pages, &nr)) | ||
| 258 | goto slow; | 159 | goto slow; |
| 259 | } while (pgdp++, addr = next, addr != end); | 160 | } else if (!gup_pud_range(pgd, addr, next, write, pages, &nr)) |
| 260 | } | 161 | goto slow; |
| 162 | } while (pgdp++, addr = next, addr != end); | ||
| 163 | |||
| 261 | local_irq_enable(); | 164 | local_irq_enable(); |
| 262 | 165 | ||
| 263 | VM_BUG_ON(nr != (end - start) >> PAGE_SHIFT); | 166 | VM_BUG_ON(nr != (end - start) >> PAGE_SHIFT); |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 1ade7eb6ae00..3ecdcec0a39e 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
| @@ -92,6 +92,7 @@ struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; | |||
| 92 | struct hash_pte *htab_address; | 92 | struct hash_pte *htab_address; |
| 93 | unsigned long htab_size_bytes; | 93 | unsigned long htab_size_bytes; |
| 94 | unsigned long htab_hash_mask; | 94 | unsigned long htab_hash_mask; |
| 95 | EXPORT_SYMBOL_GPL(htab_hash_mask); | ||
| 95 | int mmu_linear_psize = MMU_PAGE_4K; | 96 | int mmu_linear_psize = MMU_PAGE_4K; |
| 96 | int mmu_virtual_psize = MMU_PAGE_4K; | 97 | int mmu_virtual_psize = MMU_PAGE_4K; |
| 97 | int mmu_vmalloc_psize = MMU_PAGE_4K; | 98 | int mmu_vmalloc_psize = MMU_PAGE_4K; |
| @@ -102,6 +103,7 @@ int mmu_io_psize = MMU_PAGE_4K; | |||
| 102 | int mmu_kernel_ssize = MMU_SEGSIZE_256M; | 103 | int mmu_kernel_ssize = MMU_SEGSIZE_256M; |
| 103 | int mmu_highuser_ssize = MMU_SEGSIZE_256M; | 104 | int mmu_highuser_ssize = MMU_SEGSIZE_256M; |
| 104 | u16 mmu_slb_size = 64; | 105 | u16 mmu_slb_size = 64; |
| 106 | EXPORT_SYMBOL_GPL(mmu_slb_size); | ||
| 105 | #ifdef CONFIG_HUGETLB_PAGE | 107 | #ifdef CONFIG_HUGETLB_PAGE |
| 106 | unsigned int HPAGE_SHIFT; | 108 | unsigned int HPAGE_SHIFT; |
| 107 | #endif | 109 | #endif |
| @@ -338,7 +340,7 @@ static int __init htab_dt_scan_page_sizes(unsigned long node, | |||
| 338 | else | 340 | else |
| 339 | def->tlbiel = 0; | 341 | def->tlbiel = 0; |
| 340 | 342 | ||
| 341 | DBG(" %d: shift=%02x, sllp=%04x, avpnm=%08x, " | 343 | DBG(" %d: shift=%02x, sllp=%04lx, avpnm=%08lx, " |
| 342 | "tlbiel=%d, penc=%d\n", | 344 | "tlbiel=%d, penc=%d\n", |
| 343 | idx, shift, def->sllp, def->avpnm, def->tlbiel, | 345 | idx, shift, def->sllp, def->avpnm, def->tlbiel, |
| 344 | def->penc); | 346 | def->penc); |
| @@ -481,16 +483,6 @@ static void __init htab_init_page_sizes(void) | |||
| 481 | #ifdef CONFIG_HUGETLB_PAGE | 483 | #ifdef CONFIG_HUGETLB_PAGE |
| 482 | /* Reserve 16G huge page memory sections for huge pages */ | 484 | /* Reserve 16G huge page memory sections for huge pages */ |
| 483 | of_scan_flat_dt(htab_dt_scan_hugepage_blocks, NULL); | 485 | of_scan_flat_dt(htab_dt_scan_hugepage_blocks, NULL); |
| 484 | |||
| 485 | /* Set default large page size. Currently, we pick 16M or 1M depending | ||
| 486 | * on what is available | ||
| 487 | */ | ||
| 488 | if (mmu_psize_defs[MMU_PAGE_16M].shift) | ||
| 489 | HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_16M].shift; | ||
| 490 | /* With 4k/4level pagetables, we can't (for now) cope with a | ||
| 491 | * huge page size < PMD_SIZE */ | ||
| 492 | else if (mmu_psize_defs[MMU_PAGE_1M].shift) | ||
| 493 | HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_1M].shift; | ||
| 494 | #endif /* CONFIG_HUGETLB_PAGE */ | 486 | #endif /* CONFIG_HUGETLB_PAGE */ |
| 495 | } | 487 | } |
| 496 | 488 | ||
| @@ -671,7 +663,7 @@ static void __init htab_initialize(void) | |||
| 671 | base = (unsigned long)__va(lmb.memory.region[i].base); | 663 | base = (unsigned long)__va(lmb.memory.region[i].base); |
| 672 | size = lmb.memory.region[i].size; | 664 | size = lmb.memory.region[i].size; |
| 673 | 665 | ||
| 674 | DBG("creating mapping for region: %lx..%lx (prot: %x)\n", | 666 | DBG("creating mapping for region: %lx..%lx (prot: %lx)\n", |
| 675 | base, size, prot); | 667 | base, size, prot); |
| 676 | 668 | ||
| 677 | #ifdef CONFIG_U3_DART | 669 | #ifdef CONFIG_U3_DART |
| @@ -785,7 +777,7 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap) | |||
| 785 | /* page is dirty */ | 777 | /* page is dirty */ |
| 786 | if (!test_bit(PG_arch_1, &page->flags) && !PageReserved(page)) { | 778 | if (!test_bit(PG_arch_1, &page->flags) && !PageReserved(page)) { |
| 787 | if (trap == 0x400) { | 779 | if (trap == 0x400) { |
| 788 | __flush_dcache_icache(page_address(page)); | 780 | flush_dcache_icache_page(page); |
| 789 | set_bit(PG_arch_1, &page->flags); | 781 | set_bit(PG_arch_1, &page->flags); |
| 790 | } else | 782 | } else |
| 791 | pp |= HPTE_R_N; | 783 | pp |= HPTE_R_N; |
| @@ -843,9 +835,9 @@ void demote_segment_4k(struct mm_struct *mm, unsigned long addr) | |||
| 843 | * Result is 0: full permissions, _PAGE_RW: read-only, | 835 | * Result is 0: full permissions, _PAGE_RW: read-only, |
| 844 | * _PAGE_USER or _PAGE_USER|_PAGE_RW: no access. | 836 | * _PAGE_USER or _PAGE_USER|_PAGE_RW: no access. |
| 845 | */ | 837 | */ |
| 846 | static int subpage_protection(pgd_t *pgdir, unsigned long ea) | 838 | static int subpage_protection(struct mm_struct *mm, unsigned long ea) |
| 847 | { | 839 | { |
| 848 | struct subpage_prot_table *spt = pgd_subpage_prot(pgdir); | 840 | struct subpage_prot_table *spt = &mm->context.spt; |
| 849 | u32 spp = 0; | 841 | u32 spp = 0; |
| 850 | u32 **sbpm, *sbpp; | 842 | u32 **sbpm, *sbpp; |
| 851 | 843 | ||
| @@ -873,7 +865,7 @@ static int subpage_protection(pgd_t *pgdir, unsigned long ea) | |||
| 873 | } | 865 | } |
| 874 | 866 | ||
| 875 | #else /* CONFIG_PPC_SUBPAGE_PROT */ | 867 | #else /* CONFIG_PPC_SUBPAGE_PROT */ |
| 876 | static inline int subpage_protection(pgd_t *pgdir, unsigned long ea) | 868 | static inline int subpage_protection(struct mm_struct *mm, unsigned long ea) |
| 877 | { | 869 | { |
| 878 | return 0; | 870 | return 0; |
| 879 | } | 871 | } |
| @@ -887,10 +879,11 @@ static inline int subpage_protection(pgd_t *pgdir, unsigned long ea) | |||
| 887 | */ | 879 | */ |
| 888 | int hash_page(unsigned long ea, unsigned long access, unsigned long trap) | 880 | int hash_page(unsigned long ea, unsigned long access, unsigned long trap) |
| 889 | { | 881 | { |
| 890 | void *pgdir; | 882 | pgd_t *pgdir; |
| 891 | unsigned long vsid; | 883 | unsigned long vsid; |
| 892 | struct mm_struct *mm; | 884 | struct mm_struct *mm; |
| 893 | pte_t *ptep; | 885 | pte_t *ptep; |
| 886 | unsigned hugeshift; | ||
| 894 | const struct cpumask *tmp; | 887 | const struct cpumask *tmp; |
| 895 | int rc, user_region = 0, local = 0; | 888 | int rc, user_region = 0, local = 0; |
| 896 | int psize, ssize; | 889 | int psize, ssize; |
| @@ -943,30 +936,31 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) | |||
| 943 | if (user_region && cpumask_equal(mm_cpumask(mm), tmp)) | 936 | if (user_region && cpumask_equal(mm_cpumask(mm), tmp)) |
| 944 | local = 1; | 937 | local = 1; |
| 945 | 938 | ||
| 946 | #ifdef CONFIG_HUGETLB_PAGE | ||
| 947 | /* Handle hugepage regions */ | ||
| 948 | if (HPAGE_SHIFT && mmu_huge_psizes[psize]) { | ||
| 949 | DBG_LOW(" -> huge page !\n"); | ||
| 950 | return hash_huge_page(mm, access, ea, vsid, local, trap); | ||
| 951 | } | ||
| 952 | #endif /* CONFIG_HUGETLB_PAGE */ | ||
| 953 | |||
| 954 | #ifndef CONFIG_PPC_64K_PAGES | 939 | #ifndef CONFIG_PPC_64K_PAGES |
| 955 | /* If we use 4K pages and our psize is not 4K, then we are hitting | 940 | /* If we use 4K pages and our psize is not 4K, then we might |
| 956 | * a special driver mapping, we need to align the address before | 941 | * be hitting a special driver mapping, and need to align the |
| 957 | * we fetch the PTE | 942 | * address before we fetch the PTE. |
| 943 | * | ||
| 944 | * It could also be a hugepage mapping, in which case this is | ||
| 945 | * not necessary, but it's not harmful, either. | ||
| 958 | */ | 946 | */ |
| 959 | if (psize != MMU_PAGE_4K) | 947 | if (psize != MMU_PAGE_4K) |
| 960 | ea &= ~((1ul << mmu_psize_defs[psize].shift) - 1); | 948 | ea &= ~((1ul << mmu_psize_defs[psize].shift) - 1); |
| 961 | #endif /* CONFIG_PPC_64K_PAGES */ | 949 | #endif /* CONFIG_PPC_64K_PAGES */ |
| 962 | 950 | ||
| 963 | /* Get PTE and page size from page tables */ | 951 | /* Get PTE and page size from page tables */ |
| 964 | ptep = find_linux_pte(pgdir, ea); | 952 | ptep = find_linux_pte_or_hugepte(pgdir, ea, &hugeshift); |
| 965 | if (ptep == NULL || !pte_present(*ptep)) { | 953 | if (ptep == NULL || !pte_present(*ptep)) { |
| 966 | DBG_LOW(" no PTE !\n"); | 954 | DBG_LOW(" no PTE !\n"); |
| 967 | return 1; | 955 | return 1; |
| 968 | } | 956 | } |
| 969 | 957 | ||
| 958 | #ifdef CONFIG_HUGETLB_PAGE | ||
| 959 | if (hugeshift) | ||
| 960 | return __hash_page_huge(ea, access, vsid, ptep, trap, local, | ||
| 961 | ssize, hugeshift, psize); | ||
| 962 | #endif /* CONFIG_HUGETLB_PAGE */ | ||
| 963 | |||
| 970 | #ifndef CONFIG_PPC_64K_PAGES | 964 | #ifndef CONFIG_PPC_64K_PAGES |
| 971 | DBG_LOW(" i-pte: %016lx\n", pte_val(*ptep)); | 965 | DBG_LOW(" i-pte: %016lx\n", pte_val(*ptep)); |
| 972 | #else | 966 | #else |
| @@ -1031,7 +1025,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) | |||
| 1031 | else | 1025 | else |
| 1032 | #endif /* CONFIG_PPC_HAS_HASH_64K */ | 1026 | #endif /* CONFIG_PPC_HAS_HASH_64K */ |
| 1033 | { | 1027 | { |
| 1034 | int spp = subpage_protection(pgdir, ea); | 1028 | int spp = subpage_protection(mm, ea); |
| 1035 | if (access & spp) | 1029 | if (access & spp) |
| 1036 | rc = -2; | 1030 | rc = -2; |
| 1037 | else | 1031 | else |
| @@ -1121,7 +1115,7 @@ void flush_hash_page(unsigned long va, real_pte_t pte, int psize, int ssize, | |||
| 1121 | { | 1115 | { |
| 1122 | unsigned long hash, index, shift, hidx, slot; | 1116 | unsigned long hash, index, shift, hidx, slot; |
| 1123 | 1117 | ||
| 1124 | DBG_LOW("flush_hash_page(va=%016x)\n", va); | 1118 | DBG_LOW("flush_hash_page(va=%016lx)\n", va); |
| 1125 | pte_iterate_hashed_subpages(pte, psize, va, index, shift) { | 1119 | pte_iterate_hashed_subpages(pte, psize, va, index, shift) { |
| 1126 | hash = hpt_hash(va, shift, ssize); | 1120 | hash = hpt_hash(va, shift, ssize); |
| 1127 | hidx = __rpte_to_hidx(pte, index); | 1121 | hidx = __rpte_to_hidx(pte, index); |
| @@ -1129,7 +1123,7 @@ void flush_hash_page(unsigned long va, real_pte_t pte, int psize, int ssize, | |||
| 1129 | hash = ~hash; | 1123 | hash = ~hash; |
| 1130 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | 1124 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; |
| 1131 | slot += hidx & _PTEIDX_GROUP_IX; | 1125 | slot += hidx & _PTEIDX_GROUP_IX; |
| 1132 | DBG_LOW(" sub %d: hash=%x, hidx=%x\n", index, slot, hidx); | 1126 | DBG_LOW(" sub %ld: hash=%lx, hidx=%lx\n", index, slot, hidx); |
| 1133 | ppc_md.hpte_invalidate(slot, va, psize, ssize, local); | 1127 | ppc_md.hpte_invalidate(slot, va, psize, ssize, local); |
| 1134 | } pte_iterate_hashed_end(); | 1128 | } pte_iterate_hashed_end(); |
| 1135 | } | 1129 | } |
diff --git a/arch/powerpc/mm/hugetlbpage-hash64.c b/arch/powerpc/mm/hugetlbpage-hash64.c new file mode 100644 index 000000000000..199539882f92 --- /dev/null +++ b/arch/powerpc/mm/hugetlbpage-hash64.c | |||
| @@ -0,0 +1,139 @@ | |||
| 1 | /* | ||
| 2 | * PPC64 Huge TLB Page Support for hash based MMUs (POWER4 and later) | ||
| 3 | * | ||
| 4 | * Copyright (C) 2003 David Gibson, IBM Corporation. | ||
| 5 | * | ||
| 6 | * Based on the IA-32 version: | ||
| 7 | * Copyright (C) 2002, Rohit Seth <rohit.seth@intel.com> | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/mm.h> | ||
| 11 | #include <linux/hugetlb.h> | ||
| 12 | #include <asm/pgtable.h> | ||
| 13 | #include <asm/pgalloc.h> | ||
| 14 | #include <asm/cacheflush.h> | ||
| 15 | #include <asm/machdep.h> | ||
| 16 | |||
| 17 | int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid, | ||
| 18 | pte_t *ptep, unsigned long trap, int local, int ssize, | ||
| 19 | unsigned int shift, unsigned int mmu_psize) | ||
| 20 | { | ||
| 21 | unsigned long old_pte, new_pte; | ||
| 22 | unsigned long va, rflags, pa, sz; | ||
| 23 | long slot; | ||
| 24 | int err = 1; | ||
| 25 | |||
| 26 | BUG_ON(shift != mmu_psize_defs[mmu_psize].shift); | ||
| 27 | |||
| 28 | /* Search the Linux page table for a match with va */ | ||
| 29 | va = hpt_va(ea, vsid, ssize); | ||
| 30 | |||
| 31 | /* | ||
| 32 | * Check the user's access rights to the page. If access should be | ||
| 33 | * prevented then send the problem up to do_page_fault. | ||
| 34 | */ | ||
| 35 | if (unlikely(access & ~pte_val(*ptep))) | ||
| 36 | goto out; | ||
| 37 | /* | ||
| 38 | * At this point, we have a pte (old_pte) which can be used to build | ||
| 39 | * or update an HPTE. There are 2 cases: | ||
| 40 | * | ||
| 41 | * 1. There is a valid (present) pte with no associated HPTE (this is | ||
| 42 | * the most common case) | ||
| 43 | * 2. There is a valid (present) pte with an associated HPTE. The | ||
| 44 | * current values of the pp bits in the HPTE prevent access | ||
| 45 | * because we are doing software DIRTY bit management and the | ||
| 46 | * page is currently not DIRTY. | ||
| 47 | */ | ||
| 48 | |||
| 49 | |||
| 50 | do { | ||
| 51 | old_pte = pte_val(*ptep); | ||
| 52 | if (old_pte & _PAGE_BUSY) | ||
| 53 | goto out; | ||
| 54 | new_pte = old_pte | _PAGE_BUSY | _PAGE_ACCESSED; | ||
| 55 | } while(old_pte != __cmpxchg_u64((unsigned long *)ptep, | ||
| 56 | old_pte, new_pte)); | ||
| 57 | |||
| 58 | rflags = 0x2 | (!(new_pte & _PAGE_RW)); | ||
| 59 | /* _PAGE_EXEC -> HW_NO_EXEC since it's inverted */ | ||
| 60 | rflags |= ((new_pte & _PAGE_EXEC) ? 0 : HPTE_R_N); | ||
| 61 | sz = ((1UL) << shift); | ||
| 62 | if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) | ||
| 63 | /* No CPU has hugepages but lacks no execute, so we | ||
| 64 | * don't need to worry about that case */ | ||
| 65 | rflags = hash_page_do_lazy_icache(rflags, __pte(old_pte), trap); | ||
| 66 | |||
| 67 | /* Check if pte already has an hpte (case 2) */ | ||
| 68 | if (unlikely(old_pte & _PAGE_HASHPTE)) { | ||
| 69 | /* There MIGHT be an HPTE for this pte */ | ||
| 70 | unsigned long hash, slot; | ||
| 71 | |||
| 72 | hash = hpt_hash(va, shift, ssize); | ||
| 73 | if (old_pte & _PAGE_F_SECOND) | ||
| 74 | hash = ~hash; | ||
| 75 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | ||
| 76 | slot += (old_pte & _PAGE_F_GIX) >> 12; | ||
| 77 | |||
| 78 | if (ppc_md.hpte_updatepp(slot, rflags, va, mmu_psize, | ||
| 79 | ssize, local) == -1) | ||
| 80 | old_pte &= ~_PAGE_HPTEFLAGS; | ||
| 81 | } | ||
| 82 | |||
| 83 | if (likely(!(old_pte & _PAGE_HASHPTE))) { | ||
| 84 | unsigned long hash = hpt_hash(va, shift, ssize); | ||
| 85 | unsigned long hpte_group; | ||
| 86 | |||
| 87 | pa = pte_pfn(__pte(old_pte)) << PAGE_SHIFT; | ||
| 88 | |||
| 89 | repeat: | ||
| 90 | hpte_group = ((hash & htab_hash_mask) * | ||
| 91 | HPTES_PER_GROUP) & ~0x7UL; | ||
| 92 | |||
| 93 | /* clear HPTE slot informations in new PTE */ | ||
| 94 | #ifdef CONFIG_PPC_64K_PAGES | ||
| 95 | new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | _PAGE_HPTE_SUB0; | ||
| 96 | #else | ||
| 97 | new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE; | ||
| 98 | #endif | ||
| 99 | /* Add in WIMG bits */ | ||
| 100 | rflags |= (new_pte & (_PAGE_WRITETHRU | _PAGE_NO_CACHE | | ||
| 101 | _PAGE_COHERENT | _PAGE_GUARDED)); | ||
| 102 | |||
| 103 | /* Insert into the hash table, primary slot */ | ||
| 104 | slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags, 0, | ||
| 105 | mmu_psize, ssize); | ||
| 106 | |||
| 107 | /* Primary is full, try the secondary */ | ||
| 108 | if (unlikely(slot == -1)) { | ||
| 109 | hpte_group = ((~hash & htab_hash_mask) * | ||
| 110 | HPTES_PER_GROUP) & ~0x7UL; | ||
| 111 | slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags, | ||
| 112 | HPTE_V_SECONDARY, | ||
| 113 | mmu_psize, ssize); | ||
| 114 | if (slot == -1) { | ||
| 115 | if (mftb() & 0x1) | ||
| 116 | hpte_group = ((hash & htab_hash_mask) * | ||
| 117 | HPTES_PER_GROUP)&~0x7UL; | ||
| 118 | |||
| 119 | ppc_md.hpte_remove(hpte_group); | ||
| 120 | goto repeat; | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | if (unlikely(slot == -2)) | ||
| 125 | panic("hash_huge_page: pte_insert failed\n"); | ||
| 126 | |||
| 127 | new_pte |= (slot << 12) & (_PAGE_F_SECOND | _PAGE_F_GIX); | ||
| 128 | } | ||
| 129 | |||
| 130 | /* | ||
| 131 | * No need to use ldarx/stdcx here | ||
| 132 | */ | ||
| 133 | *ptep = __pte(new_pte & ~_PAGE_BUSY); | ||
| 134 | |||
| 135 | err = 0; | ||
| 136 | |||
| 137 | out: | ||
| 138 | return err; | ||
| 139 | } | ||
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 90df6ffe3a43..123f7070238a 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c | |||
| @@ -7,29 +7,17 @@ | |||
| 7 | * Copyright (C) 2002, Rohit Seth <rohit.seth@intel.com> | 7 | * Copyright (C) 2002, Rohit Seth <rohit.seth@intel.com> |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #include <linux/init.h> | ||
| 11 | #include <linux/fs.h> | ||
| 12 | #include <linux/mm.h> | 10 | #include <linux/mm.h> |
| 11 | #include <linux/io.h> | ||
| 13 | #include <linux/hugetlb.h> | 12 | #include <linux/hugetlb.h> |
| 14 | #include <linux/pagemap.h> | 13 | #include <asm/pgtable.h> |
| 15 | #include <linux/slab.h> | ||
| 16 | #include <linux/err.h> | ||
| 17 | #include <linux/sysctl.h> | ||
| 18 | #include <asm/mman.h> | ||
| 19 | #include <asm/pgalloc.h> | 14 | #include <asm/pgalloc.h> |
| 20 | #include <asm/tlb.h> | 15 | #include <asm/tlb.h> |
| 21 | #include <asm/tlbflush.h> | ||
| 22 | #include <asm/mmu_context.h> | ||
| 23 | #include <asm/machdep.h> | ||
| 24 | #include <asm/cputable.h> | ||
| 25 | #include <asm/spu.h> | ||
| 26 | 16 | ||
| 27 | #define PAGE_SHIFT_64K 16 | 17 | #define PAGE_SHIFT_64K 16 |
| 28 | #define PAGE_SHIFT_16M 24 | 18 | #define PAGE_SHIFT_16M 24 |
| 29 | #define PAGE_SHIFT_16G 34 | 19 | #define PAGE_SHIFT_16G 34 |
| 30 | 20 | ||
| 31 | #define NUM_LOW_AREAS (0x100000000UL >> SID_SHIFT) | ||
| 32 | #define NUM_HIGH_AREAS (PGTABLE_RANGE >> HTLB_AREA_SHIFT) | ||
| 33 | #define MAX_NUMBER_GPAGES 1024 | 21 | #define MAX_NUMBER_GPAGES 1024 |
| 34 | 22 | ||
| 35 | /* Tracks the 16G pages after the device tree is scanned and before the | 23 | /* Tracks the 16G pages after the device tree is scanned and before the |
| @@ -37,53 +25,17 @@ | |||
| 37 | static unsigned long gpage_freearray[MAX_NUMBER_GPAGES]; | 25 | static unsigned long gpage_freearray[MAX_NUMBER_GPAGES]; |
| 38 | static unsigned nr_gpages; | 26 | static unsigned nr_gpages; |
| 39 | 27 | ||
| 40 | /* Array of valid huge page sizes - non-zero value(hugepte_shift) is | ||
| 41 | * stored for the huge page sizes that are valid. | ||
| 42 | */ | ||
| 43 | unsigned int mmu_huge_psizes[MMU_PAGE_COUNT] = { }; /* initialize all to 0 */ | ||
| 44 | |||
| 45 | #define hugepte_shift mmu_huge_psizes | ||
| 46 | #define PTRS_PER_HUGEPTE(psize) (1 << hugepte_shift[psize]) | ||
| 47 | #define HUGEPTE_TABLE_SIZE(psize) (sizeof(pte_t) << hugepte_shift[psize]) | ||
| 48 | |||
| 49 | #define HUGEPD_SHIFT(psize) (mmu_psize_to_shift(psize) \ | ||
| 50 | + hugepte_shift[psize]) | ||
| 51 | #define HUGEPD_SIZE(psize) (1UL << HUGEPD_SHIFT(psize)) | ||
| 52 | #define HUGEPD_MASK(psize) (~(HUGEPD_SIZE(psize)-1)) | ||
| 53 | |||
| 54 | /* Subtract one from array size because we don't need a cache for 4K since | ||
| 55 | * is not a huge page size */ | ||
| 56 | #define HUGE_PGTABLE_INDEX(psize) (HUGEPTE_CACHE_NUM + psize - 1) | ||
| 57 | #define HUGEPTE_CACHE_NAME(psize) (huge_pgtable_cache_name[psize]) | ||
| 58 | |||
| 59 | static const char *huge_pgtable_cache_name[MMU_PAGE_COUNT] = { | ||
| 60 | [MMU_PAGE_64K] = "hugepte_cache_64K", | ||
| 61 | [MMU_PAGE_1M] = "hugepte_cache_1M", | ||
| 62 | [MMU_PAGE_16M] = "hugepte_cache_16M", | ||
| 63 | [MMU_PAGE_16G] = "hugepte_cache_16G", | ||
| 64 | }; | ||
| 65 | |||
| 66 | /* Flag to mark huge PD pointers. This means pmd_bad() and pud_bad() | 28 | /* Flag to mark huge PD pointers. This means pmd_bad() and pud_bad() |
| 67 | * will choke on pointers to hugepte tables, which is handy for | 29 | * will choke on pointers to hugepte tables, which is handy for |
| 68 | * catching screwups early. */ | 30 | * catching screwups early. */ |
| 69 | #define HUGEPD_OK 0x1 | ||
| 70 | |||
| 71 | typedef struct { unsigned long pd; } hugepd_t; | ||
| 72 | |||
| 73 | #define hugepd_none(hpd) ((hpd).pd == 0) | ||
| 74 | 31 | ||
| 75 | static inline int shift_to_mmu_psize(unsigned int shift) | 32 | static inline int shift_to_mmu_psize(unsigned int shift) |
| 76 | { | 33 | { |
| 77 | switch (shift) { | 34 | int psize; |
| 78 | #ifndef CONFIG_PPC_64K_PAGES | 35 | |
| 79 | case PAGE_SHIFT_64K: | 36 | for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) |
| 80 | return MMU_PAGE_64K; | 37 | if (mmu_psize_defs[psize].shift == shift) |
| 81 | #endif | 38 | return psize; |
| 82 | case PAGE_SHIFT_16M: | ||
| 83 | return MMU_PAGE_16M; | ||
| 84 | case PAGE_SHIFT_16G: | ||
| 85 | return MMU_PAGE_16G; | ||
| 86 | } | ||
| 87 | return -1; | 39 | return -1; |
| 88 | } | 40 | } |
| 89 | 41 | ||
| @@ -94,71 +46,126 @@ static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize) | |||
| 94 | BUG(); | 46 | BUG(); |
| 95 | } | 47 | } |
| 96 | 48 | ||
| 49 | #define hugepd_none(hpd) ((hpd).pd == 0) | ||
| 50 | |||
| 97 | static inline pte_t *hugepd_page(hugepd_t hpd) | 51 | static inline pte_t *hugepd_page(hugepd_t hpd) |
| 98 | { | 52 | { |
| 99 | BUG_ON(!(hpd.pd & HUGEPD_OK)); | 53 | BUG_ON(!hugepd_ok(hpd)); |
| 100 | return (pte_t *)(hpd.pd & ~HUGEPD_OK); | 54 | return (pte_t *)((hpd.pd & ~HUGEPD_SHIFT_MASK) | 0xc000000000000000); |
| 55 | } | ||
| 56 | |||
| 57 | static inline unsigned int hugepd_shift(hugepd_t hpd) | ||
| 58 | { | ||
| 59 | return hpd.pd & HUGEPD_SHIFT_MASK; | ||
| 101 | } | 60 | } |
| 102 | 61 | ||
| 103 | static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr, | 62 | static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr, unsigned pdshift) |
| 104 | struct hstate *hstate) | ||
| 105 | { | 63 | { |
| 106 | unsigned int shift = huge_page_shift(hstate); | 64 | unsigned long idx = (addr & ((1UL << pdshift) - 1)) >> hugepd_shift(*hpdp); |
| 107 | int psize = shift_to_mmu_psize(shift); | ||
| 108 | unsigned long idx = ((addr >> shift) & (PTRS_PER_HUGEPTE(psize)-1)); | ||
| 109 | pte_t *dir = hugepd_page(*hpdp); | 65 | pte_t *dir = hugepd_page(*hpdp); |
| 110 | 66 | ||
| 111 | return dir + idx; | 67 | return dir + idx; |
| 112 | } | 68 | } |
| 113 | 69 | ||
| 70 | pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift) | ||
| 71 | { | ||
| 72 | pgd_t *pg; | ||
| 73 | pud_t *pu; | ||
| 74 | pmd_t *pm; | ||
| 75 | hugepd_t *hpdp = NULL; | ||
| 76 | unsigned pdshift = PGDIR_SHIFT; | ||
| 77 | |||
| 78 | if (shift) | ||
| 79 | *shift = 0; | ||
| 80 | |||
| 81 | pg = pgdir + pgd_index(ea); | ||
| 82 | if (is_hugepd(pg)) { | ||
| 83 | hpdp = (hugepd_t *)pg; | ||
| 84 | } else if (!pgd_none(*pg)) { | ||
| 85 | pdshift = PUD_SHIFT; | ||
| 86 | pu = pud_offset(pg, ea); | ||
| 87 | if (is_hugepd(pu)) | ||
| 88 | hpdp = (hugepd_t *)pu; | ||
| 89 | else if (!pud_none(*pu)) { | ||
| 90 | pdshift = PMD_SHIFT; | ||
| 91 | pm = pmd_offset(pu, ea); | ||
| 92 | if (is_hugepd(pm)) | ||
| 93 | hpdp = (hugepd_t *)pm; | ||
| 94 | else if (!pmd_none(*pm)) { | ||
| 95 | return pte_offset_map(pm, ea); | ||
| 96 | } | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | if (!hpdp) | ||
| 101 | return NULL; | ||
| 102 | |||
| 103 | if (shift) | ||
| 104 | *shift = hugepd_shift(*hpdp); | ||
| 105 | return hugepte_offset(hpdp, ea, pdshift); | ||
| 106 | } | ||
| 107 | |||
| 108 | pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) | ||
| 109 | { | ||
| 110 | return find_linux_pte_or_hugepte(mm->pgd, addr, NULL); | ||
| 111 | } | ||
| 112 | |||
| 114 | static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp, | 113 | static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp, |
| 115 | unsigned long address, unsigned int psize) | 114 | unsigned long address, unsigned pdshift, unsigned pshift) |
| 116 | { | 115 | { |
| 117 | pte_t *new = kmem_cache_zalloc(pgtable_cache[HUGE_PGTABLE_INDEX(psize)], | 116 | pte_t *new = kmem_cache_zalloc(PGT_CACHE(pdshift - pshift), |
| 118 | GFP_KERNEL|__GFP_REPEAT); | 117 | GFP_KERNEL|__GFP_REPEAT); |
| 118 | |||
| 119 | BUG_ON(pshift > HUGEPD_SHIFT_MASK); | ||
| 120 | BUG_ON((unsigned long)new & HUGEPD_SHIFT_MASK); | ||
| 119 | 121 | ||
| 120 | if (! new) | 122 | if (! new) |
| 121 | return -ENOMEM; | 123 | return -ENOMEM; |
| 122 | 124 | ||
| 123 | spin_lock(&mm->page_table_lock); | 125 | spin_lock(&mm->page_table_lock); |
| 124 | if (!hugepd_none(*hpdp)) | 126 | if (!hugepd_none(*hpdp)) |
| 125 | kmem_cache_free(pgtable_cache[HUGE_PGTABLE_INDEX(psize)], new); | 127 | kmem_cache_free(PGT_CACHE(pdshift - pshift), new); |
| 126 | else | 128 | else |
| 127 | hpdp->pd = (unsigned long)new | HUGEPD_OK; | 129 | hpdp->pd = ((unsigned long)new & ~0x8000000000000000) | pshift; |
| 128 | spin_unlock(&mm->page_table_lock); | 130 | spin_unlock(&mm->page_table_lock); |
| 129 | return 0; | 131 | return 0; |
| 130 | } | 132 | } |
| 131 | 133 | ||
| 132 | 134 | pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz) | |
| 133 | static pud_t *hpud_offset(pgd_t *pgd, unsigned long addr, struct hstate *hstate) | ||
| 134 | { | ||
| 135 | if (huge_page_shift(hstate) < PUD_SHIFT) | ||
| 136 | return pud_offset(pgd, addr); | ||
| 137 | else | ||
| 138 | return (pud_t *) pgd; | ||
| 139 | } | ||
| 140 | static pud_t *hpud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long addr, | ||
| 141 | struct hstate *hstate) | ||
| 142 | { | 135 | { |
| 143 | if (huge_page_shift(hstate) < PUD_SHIFT) | 136 | pgd_t *pg; |
| 144 | return pud_alloc(mm, pgd, addr); | 137 | pud_t *pu; |
| 145 | else | 138 | pmd_t *pm; |
| 146 | return (pud_t *) pgd; | 139 | hugepd_t *hpdp = NULL; |
| 147 | } | 140 | unsigned pshift = __ffs(sz); |
| 148 | static pmd_t *hpmd_offset(pud_t *pud, unsigned long addr, struct hstate *hstate) | 141 | unsigned pdshift = PGDIR_SHIFT; |
| 149 | { | 142 | |
| 150 | if (huge_page_shift(hstate) < PMD_SHIFT) | 143 | addr &= ~(sz-1); |
| 151 | return pmd_offset(pud, addr); | 144 | |
| 152 | else | 145 | pg = pgd_offset(mm, addr); |
| 153 | return (pmd_t *) pud; | 146 | if (pshift >= PUD_SHIFT) { |
| 154 | } | 147 | hpdp = (hugepd_t *)pg; |
| 155 | static pmd_t *hpmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long addr, | 148 | } else { |
| 156 | struct hstate *hstate) | 149 | pdshift = PUD_SHIFT; |
| 157 | { | 150 | pu = pud_alloc(mm, pg, addr); |
| 158 | if (huge_page_shift(hstate) < PMD_SHIFT) | 151 | if (pshift >= PMD_SHIFT) { |
| 159 | return pmd_alloc(mm, pud, addr); | 152 | hpdp = (hugepd_t *)pu; |
| 160 | else | 153 | } else { |
| 161 | return (pmd_t *) pud; | 154 | pdshift = PMD_SHIFT; |
| 155 | pm = pmd_alloc(mm, pu, addr); | ||
| 156 | hpdp = (hugepd_t *)pm; | ||
| 157 | } | ||
| 158 | } | ||
| 159 | |||
| 160 | if (!hpdp) | ||
| 161 | return NULL; | ||
| 162 | |||
| 163 | BUG_ON(!hugepd_none(*hpdp) && !hugepd_ok(*hpdp)); | ||
| 164 | |||
| 165 | if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr, pdshift, pshift)) | ||
| 166 | return NULL; | ||
| 167 | |||
| 168 | return hugepte_offset(hpdp, addr, pdshift); | ||
| 162 | } | 169 | } |
| 163 | 170 | ||
| 164 | /* Build list of addresses of gigantic pages. This function is used in early | 171 | /* Build list of addresses of gigantic pages. This function is used in early |
| @@ -192,94 +199,38 @@ int alloc_bootmem_huge_page(struct hstate *hstate) | |||
| 192 | return 1; | 199 | return 1; |
| 193 | } | 200 | } |
| 194 | 201 | ||
| 195 | |||
| 196 | /* Modelled after find_linux_pte() */ | ||
| 197 | pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) | ||
| 198 | { | ||
| 199 | pgd_t *pg; | ||
| 200 | pud_t *pu; | ||
| 201 | pmd_t *pm; | ||
| 202 | |||
| 203 | unsigned int psize; | ||
| 204 | unsigned int shift; | ||
| 205 | unsigned long sz; | ||
| 206 | struct hstate *hstate; | ||
| 207 | psize = get_slice_psize(mm, addr); | ||
| 208 | shift = mmu_psize_to_shift(psize); | ||
| 209 | sz = ((1UL) << shift); | ||
| 210 | hstate = size_to_hstate(sz); | ||
| 211 | |||
| 212 | addr &= hstate->mask; | ||
| 213 | |||
| 214 | pg = pgd_offset(mm, addr); | ||
| 215 | if (!pgd_none(*pg)) { | ||
| 216 | pu = hpud_offset(pg, addr, hstate); | ||
| 217 | if (!pud_none(*pu)) { | ||
| 218 | pm = hpmd_offset(pu, addr, hstate); | ||
| 219 | if (!pmd_none(*pm)) | ||
| 220 | return hugepte_offset((hugepd_t *)pm, addr, | ||
| 221 | hstate); | ||
| 222 | } | ||
| 223 | } | ||
| 224 | |||
| 225 | return NULL; | ||
| 226 | } | ||
| 227 | |||
| 228 | pte_t *huge_pte_alloc(struct mm_struct *mm, | ||
| 229 | unsigned long addr, unsigned long sz) | ||
| 230 | { | ||
| 231 | pgd_t *pg; | ||
| 232 | pud_t *pu; | ||
| 233 | pmd_t *pm; | ||
| 234 | hugepd_t *hpdp = NULL; | ||
| 235 | struct hstate *hstate; | ||
| 236 | unsigned int psize; | ||
| 237 | hstate = size_to_hstate(sz); | ||
| 238 | |||
| 239 | psize = get_slice_psize(mm, addr); | ||
| 240 | BUG_ON(!mmu_huge_psizes[psize]); | ||
| 241 | |||
| 242 | addr &= hstate->mask; | ||
| 243 | |||
| 244 | pg = pgd_offset(mm, addr); | ||
| 245 | pu = hpud_alloc(mm, pg, addr, hstate); | ||
| 246 | |||
| 247 | if (pu) { | ||
| 248 | pm = hpmd_alloc(mm, pu, addr, hstate); | ||
| 249 | if (pm) | ||
| 250 | hpdp = (hugepd_t *)pm; | ||
| 251 | } | ||
| 252 | |||
| 253 | if (! hpdp) | ||
| 254 | return NULL; | ||
| 255 | |||
| 256 | if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr, psize)) | ||
| 257 | return NULL; | ||
| 258 | |||
| 259 | return hugepte_offset(hpdp, addr, hstate); | ||
| 260 | } | ||
| 261 | |||
| 262 | int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep) | 202 | int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep) |
| 263 | { | 203 | { |
| 264 | return 0; | 204 | return 0; |
| 265 | } | 205 | } |
| 266 | 206 | ||
| 267 | static void free_hugepte_range(struct mmu_gather *tlb, hugepd_t *hpdp, | 207 | static void free_hugepd_range(struct mmu_gather *tlb, hugepd_t *hpdp, int pdshift, |
| 268 | unsigned int psize) | 208 | unsigned long start, unsigned long end, |
| 209 | unsigned long floor, unsigned long ceiling) | ||
| 269 | { | 210 | { |
| 270 | pte_t *hugepte = hugepd_page(*hpdp); | 211 | pte_t *hugepte = hugepd_page(*hpdp); |
| 212 | unsigned shift = hugepd_shift(*hpdp); | ||
| 213 | unsigned long pdmask = ~((1UL << pdshift) - 1); | ||
| 214 | |||
| 215 | start &= pdmask; | ||
| 216 | if (start < floor) | ||
| 217 | return; | ||
| 218 | if (ceiling) { | ||
| 219 | ceiling &= pdmask; | ||
| 220 | if (! ceiling) | ||
| 221 | return; | ||
| 222 | } | ||
| 223 | if (end - 1 > ceiling - 1) | ||
| 224 | return; | ||
| 271 | 225 | ||
| 272 | hpdp->pd = 0; | 226 | hpdp->pd = 0; |
| 273 | tlb->need_flush = 1; | 227 | tlb->need_flush = 1; |
| 274 | pgtable_free_tlb(tlb, pgtable_free_cache(hugepte, | 228 | pgtable_free_tlb(tlb, hugepte, pdshift - shift); |
| 275 | HUGEPTE_CACHE_NUM+psize-1, | ||
| 276 | PGF_CACHENUM_MASK)); | ||
| 277 | } | 229 | } |
| 278 | 230 | ||
| 279 | static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud, | 231 | static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud, |
| 280 | unsigned long addr, unsigned long end, | 232 | unsigned long addr, unsigned long end, |
| 281 | unsigned long floor, unsigned long ceiling, | 233 | unsigned long floor, unsigned long ceiling) |
| 282 | unsigned int psize) | ||
| 283 | { | 234 | { |
| 284 | pmd_t *pmd; | 235 | pmd_t *pmd; |
| 285 | unsigned long next; | 236 | unsigned long next; |
| @@ -291,7 +242,8 @@ static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud, | |||
| 291 | next = pmd_addr_end(addr, end); | 242 | next = pmd_addr_end(addr, end); |
| 292 | if (pmd_none(*pmd)) | 243 | if (pmd_none(*pmd)) |
| 293 | continue; | 244 | continue; |
| 294 | free_hugepte_range(tlb, (hugepd_t *)pmd, psize); | 245 | free_hugepd_range(tlb, (hugepd_t *)pmd, PMD_SHIFT, |
| 246 | addr, next, floor, ceiling); | ||
| 295 | } while (pmd++, addr = next, addr != end); | 247 | } while (pmd++, addr = next, addr != end); |
| 296 | 248 | ||
| 297 | start &= PUD_MASK; | 249 | start &= PUD_MASK; |
| @@ -317,23 +269,19 @@ static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd, | |||
| 317 | pud_t *pud; | 269 | pud_t *pud; |
| 318 | unsigned long next; | 270 | unsigned long next; |
| 319 | unsigned long start; | 271 | unsigned long start; |
| 320 | unsigned int shift; | ||
| 321 | unsigned int psize = get_slice_psize(tlb->mm, addr); | ||
| 322 | shift = mmu_psize_to_shift(psize); | ||
| 323 | 272 | ||
| 324 | start = addr; | 273 | start = addr; |
| 325 | pud = pud_offset(pgd, addr); | 274 | pud = pud_offset(pgd, addr); |
| 326 | do { | 275 | do { |
| 327 | next = pud_addr_end(addr, end); | 276 | next = pud_addr_end(addr, end); |
| 328 | if (shift < PMD_SHIFT) { | 277 | if (!is_hugepd(pud)) { |
| 329 | if (pud_none_or_clear_bad(pud)) | 278 | if (pud_none_or_clear_bad(pud)) |
| 330 | continue; | 279 | continue; |
| 331 | hugetlb_free_pmd_range(tlb, pud, addr, next, floor, | 280 | hugetlb_free_pmd_range(tlb, pud, addr, next, floor, |
| 332 | ceiling, psize); | 281 | ceiling); |
| 333 | } else { | 282 | } else { |
| 334 | if (pud_none(*pud)) | 283 | free_hugepd_range(tlb, (hugepd_t *)pud, PUD_SHIFT, |
| 335 | continue; | 284 | addr, next, floor, ceiling); |
| 336 | free_hugepte_range(tlb, (hugepd_t *)pud, psize); | ||
| 337 | } | 285 | } |
| 338 | } while (pud++, addr = next, addr != end); | 286 | } while (pud++, addr = next, addr != end); |
| 339 | 287 | ||
| @@ -364,121 +312,56 @@ void hugetlb_free_pgd_range(struct mmu_gather *tlb, | |||
| 364 | { | 312 | { |
| 365 | pgd_t *pgd; | 313 | pgd_t *pgd; |
| 366 | unsigned long next; | 314 | unsigned long next; |
| 367 | unsigned long start; | ||
| 368 | 315 | ||
| 369 | /* | 316 | /* |
| 370 | * Comments below take from the normal free_pgd_range(). They | 317 | * Because there are a number of different possible pagetable |
| 371 | * apply here too. The tests against HUGEPD_MASK below are | 318 | * layouts for hugepage ranges, we limit knowledge of how |
| 372 | * essential, because we *don't* test for this at the bottom | 319 | * things should be laid out to the allocation path |
| 373 | * level. Without them we'll attempt to free a hugepte table | 320 | * (huge_pte_alloc(), above). Everything else works out the |
| 374 | * when we unmap just part of it, even if there are other | 321 | * structure as it goes from information in the hugepd |
| 375 | * active mappings using it. | 322 | * pointers. That means that we can't here use the |
| 376 | * | 323 | * optimization used in the normal page free_pgd_range(), of |
| 377 | * The next few lines have given us lots of grief... | 324 | * checking whether we're actually covering a large enough |
| 378 | * | 325 | * range to have to do anything at the top level of the walk |
| 379 | * Why are we testing HUGEPD* at this top level? Because | 326 | * instead of at the bottom. |
| 380 | * often there will be no work to do at all, and we'd prefer | ||
| 381 | * not to go all the way down to the bottom just to discover | ||
| 382 | * that. | ||
| 383 | * | ||
| 384 | * Why all these "- 1"s? Because 0 represents both the bottom | ||
| 385 | * of the address space and the top of it (using -1 for the | ||
| 386 | * top wouldn't help much: the masks would do the wrong thing). | ||
| 387 | * The rule is that addr 0 and floor 0 refer to the bottom of | ||
| 388 | * the address space, but end 0 and ceiling 0 refer to the top | ||
| 389 | * Comparisons need to use "end - 1" and "ceiling - 1" (though | ||
| 390 | * that end 0 case should be mythical). | ||
| 391 | * | 327 | * |
| 392 | * Wherever addr is brought up or ceiling brought down, we | 328 | * To make sense of this, you should probably go read the big |
| 393 | * must be careful to reject "the opposite 0" before it | 329 | * block comment at the top of the normal free_pgd_range(), |
| 394 | * confuses the subsequent tests. But what about where end is | 330 | * too. |
| 395 | * brought down by HUGEPD_SIZE below? no, end can't go down to | ||
| 396 | * 0 there. | ||
| 397 | * | ||
| 398 | * Whereas we round start (addr) and ceiling down, by different | ||
| 399 | * masks at different levels, in order to test whether a table | ||
| 400 | * now has no other vmas using it, so can be freed, we don't | ||
| 401 | * bother to round floor or end up - the tests don't need that. | ||
| 402 | */ | 331 | */ |
| 403 | unsigned int psize = get_slice_psize(tlb->mm, addr); | ||
| 404 | |||
| 405 | addr &= HUGEPD_MASK(psize); | ||
| 406 | if (addr < floor) { | ||
| 407 | addr += HUGEPD_SIZE(psize); | ||
| 408 | if (!addr) | ||
| 409 | return; | ||
| 410 | } | ||
| 411 | if (ceiling) { | ||
| 412 | ceiling &= HUGEPD_MASK(psize); | ||
| 413 | if (!ceiling) | ||
| 414 | return; | ||
| 415 | } | ||
| 416 | if (end - 1 > ceiling - 1) | ||
| 417 | end -= HUGEPD_SIZE(psize); | ||
| 418 | if (addr > end - 1) | ||
| 419 | return; | ||
| 420 | 332 | ||
| 421 | start = addr; | ||
| 422 | pgd = pgd_offset(tlb->mm, addr); | 333 | pgd = pgd_offset(tlb->mm, addr); |
| 423 | do { | 334 | do { |
| 424 | psize = get_slice_psize(tlb->mm, addr); | ||
| 425 | BUG_ON(!mmu_huge_psizes[psize]); | ||
| 426 | next = pgd_addr_end(addr, end); | 335 | next = pgd_addr_end(addr, end); |
| 427 | if (mmu_psize_to_shift(psize) < PUD_SHIFT) { | 336 | if (!is_hugepd(pgd)) { |
| 428 | if (pgd_none_or_clear_bad(pgd)) | 337 | if (pgd_none_or_clear_bad(pgd)) |
| 429 | continue; | 338 | continue; |
| 430 | hugetlb_free_pud_range(tlb, pgd, addr, next, floor, ceiling); | 339 | hugetlb_free_pud_range(tlb, pgd, addr, next, floor, ceiling); |
| 431 | } else { | 340 | } else { |
| 432 | if (pgd_none(*pgd)) | 341 | free_hugepd_range(tlb, (hugepd_t *)pgd, PGDIR_SHIFT, |
| 433 | continue; | 342 | addr, next, floor, ceiling); |
| 434 | free_hugepte_range(tlb, (hugepd_t *)pgd, psize); | ||
| 435 | } | 343 | } |
| 436 | } while (pgd++, addr = next, addr != end); | 344 | } while (pgd++, addr = next, addr != end); |
| 437 | } | 345 | } |
| 438 | 346 | ||
| 439 | void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, | ||
| 440 | pte_t *ptep, pte_t pte) | ||
| 441 | { | ||
| 442 | if (pte_present(*ptep)) { | ||
| 443 | /* We open-code pte_clear because we need to pass the right | ||
| 444 | * argument to hpte_need_flush (huge / !huge). Might not be | ||
| 445 | * necessary anymore if we make hpte_need_flush() get the | ||
| 446 | * page size from the slices | ||
| 447 | */ | ||
| 448 | unsigned int psize = get_slice_psize(mm, addr); | ||
| 449 | unsigned int shift = mmu_psize_to_shift(psize); | ||
| 450 | unsigned long sz = ((1UL) << shift); | ||
| 451 | struct hstate *hstate = size_to_hstate(sz); | ||
| 452 | pte_update(mm, addr & hstate->mask, ptep, ~0UL, 1); | ||
| 453 | } | ||
| 454 | *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); | ||
| 455 | } | ||
| 456 | |||
| 457 | pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, | ||
| 458 | pte_t *ptep) | ||
| 459 | { | ||
| 460 | unsigned long old = pte_update(mm, addr, ptep, ~0UL, 1); | ||
| 461 | return __pte(old); | ||
| 462 | } | ||
| 463 | |||
| 464 | struct page * | 347 | struct page * |
| 465 | follow_huge_addr(struct mm_struct *mm, unsigned long address, int write) | 348 | follow_huge_addr(struct mm_struct *mm, unsigned long address, int write) |
| 466 | { | 349 | { |
| 467 | pte_t *ptep; | 350 | pte_t *ptep; |
| 468 | struct page *page; | 351 | struct page *page; |
| 469 | unsigned int mmu_psize = get_slice_psize(mm, address); | 352 | unsigned shift; |
| 353 | unsigned long mask; | ||
| 354 | |||
| 355 | ptep = find_linux_pte_or_hugepte(mm->pgd, address, &shift); | ||
| 470 | 356 | ||
| 471 | /* Verify it is a huge page else bail. */ | 357 | /* Verify it is a huge page else bail. */ |
| 472 | if (!mmu_huge_psizes[mmu_psize]) | 358 | if (!ptep || !shift) |
| 473 | return ERR_PTR(-EINVAL); | 359 | return ERR_PTR(-EINVAL); |
| 474 | 360 | ||
| 475 | ptep = huge_pte_offset(mm, address); | 361 | mask = (1UL << shift) - 1; |
| 476 | page = pte_page(*ptep); | 362 | page = pte_page(*ptep); |
| 477 | if (page) { | 363 | if (page) |
| 478 | unsigned int shift = mmu_psize_to_shift(mmu_psize); | 364 | page += (address & mask) / PAGE_SIZE; |
| 479 | unsigned long sz = ((1UL) << shift); | ||
| 480 | page += (address % sz) / PAGE_SIZE; | ||
| 481 | } | ||
| 482 | 365 | ||
| 483 | return page; | 366 | return page; |
| 484 | } | 367 | } |
| @@ -501,6 +384,82 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address, | |||
| 501 | return NULL; | 384 | return NULL; |
| 502 | } | 385 | } |
| 503 | 386 | ||
| 387 | static noinline int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr, | ||
| 388 | unsigned long end, int write, struct page **pages, int *nr) | ||
| 389 | { | ||
| 390 | unsigned long mask; | ||
| 391 | unsigned long pte_end; | ||
| 392 | struct page *head, *page; | ||
| 393 | pte_t pte; | ||
| 394 | int refs; | ||
| 395 | |||
| 396 | pte_end = (addr + sz) & ~(sz-1); | ||
| 397 | if (pte_end < end) | ||
| 398 | end = pte_end; | ||
| 399 | |||
| 400 | pte = *ptep; | ||
| 401 | mask = _PAGE_PRESENT | _PAGE_USER; | ||
| 402 | if (write) | ||
| 403 | mask |= _PAGE_RW; | ||
| 404 | |||
| 405 | if ((pte_val(pte) & mask) != mask) | ||
| 406 | return 0; | ||
| 407 | |||
| 408 | /* hugepages are never "special" */ | ||
| 409 | VM_BUG_ON(!pfn_valid(pte_pfn(pte))); | ||
| 410 | |||
| 411 | refs = 0; | ||
| 412 | head = pte_page(pte); | ||
| 413 | |||
| 414 | page = head + ((addr & (sz-1)) >> PAGE_SHIFT); | ||
| 415 | do { | ||
| 416 | VM_BUG_ON(compound_head(page) != head); | ||
| 417 | pages[*nr] = page; | ||
| 418 | (*nr)++; | ||
| 419 | page++; | ||
| 420 | refs++; | ||
| 421 | } while (addr += PAGE_SIZE, addr != end); | ||
| 422 | |||
| 423 | if (!page_cache_add_speculative(head, refs)) { | ||
| 424 | *nr -= refs; | ||
| 425 | return 0; | ||
| 426 | } | ||
| 427 | |||
| 428 | if (unlikely(pte_val(pte) != pte_val(*ptep))) { | ||
| 429 | /* Could be optimized better */ | ||
| 430 | while (*nr) { | ||
| 431 | put_page(page); | ||
| 432 | (*nr)--; | ||
| 433 | } | ||
| 434 | } | ||
| 435 | |||
| 436 | return 1; | ||
| 437 | } | ||
| 438 | |||
| 439 | static unsigned long hugepte_addr_end(unsigned long addr, unsigned long end, | ||
| 440 | unsigned long sz) | ||
| 441 | { | ||
| 442 | unsigned long __boundary = (addr + sz) & ~(sz-1); | ||
| 443 | return (__boundary - 1 < end - 1) ? __boundary : end; | ||
| 444 | } | ||
| 445 | |||
| 446 | int gup_hugepd(hugepd_t *hugepd, unsigned pdshift, | ||
| 447 | unsigned long addr, unsigned long end, | ||
| 448 | int write, struct page **pages, int *nr) | ||
| 449 | { | ||
| 450 | pte_t *ptep; | ||
| 451 | unsigned long sz = 1UL << hugepd_shift(*hugepd); | ||
| 452 | unsigned long next; | ||
| 453 | |||
| 454 | ptep = hugepte_offset(hugepd, addr, pdshift); | ||
| 455 | do { | ||
| 456 | next = hugepte_addr_end(addr, end, sz); | ||
| 457 | if (!gup_hugepte(ptep, sz, addr, end, write, pages, nr)) | ||
| 458 | return 0; | ||
| 459 | } while (ptep++, addr = next, addr != end); | ||
| 460 | |||
| 461 | return 1; | ||
| 462 | } | ||
| 504 | 463 | ||
| 505 | unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, | 464 | unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, |
| 506 | unsigned long len, unsigned long pgoff, | 465 | unsigned long len, unsigned long pgoff, |
| @@ -509,8 +468,6 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, | |||
| 509 | struct hstate *hstate = hstate_file(file); | 468 | struct hstate *hstate = hstate_file(file); |
| 510 | int mmu_psize = shift_to_mmu_psize(huge_page_shift(hstate)); | 469 | int mmu_psize = shift_to_mmu_psize(huge_page_shift(hstate)); |
| 511 | 470 | ||
| 512 | if (!mmu_huge_psizes[mmu_psize]) | ||
| 513 | return -EINVAL; | ||
| 514 | return slice_get_unmapped_area(addr, len, flags, mmu_psize, 1, 0); | 471 | return slice_get_unmapped_area(addr, len, flags, mmu_psize, 1, 0); |
| 515 | } | 472 | } |
| 516 | 473 | ||
| @@ -521,229 +478,46 @@ unsigned long vma_mmu_pagesize(struct vm_area_struct *vma) | |||
| 521 | return 1UL << mmu_psize_to_shift(psize); | 478 | return 1UL << mmu_psize_to_shift(psize); |
| 522 | } | 479 | } |
| 523 | 480 | ||
| 524 | /* | 481 | static int __init add_huge_page_size(unsigned long long size) |
| 525 | * Called by asm hashtable.S for doing lazy icache flush | ||
| 526 | */ | ||
| 527 | static unsigned int hash_huge_page_do_lazy_icache(unsigned long rflags, | ||
| 528 | pte_t pte, int trap, unsigned long sz) | ||
| 529 | { | 482 | { |
| 530 | struct page *page; | 483 | int shift = __ffs(size); |
| 531 | int i; | 484 | int mmu_psize; |
| 532 | |||
| 533 | if (!pfn_valid(pte_pfn(pte))) | ||
| 534 | return rflags; | ||
| 535 | |||
| 536 | page = pte_page(pte); | ||
| 537 | |||
| 538 | /* page is dirty */ | ||
| 539 | if (!test_bit(PG_arch_1, &page->flags) && !PageReserved(page)) { | ||
| 540 | if (trap == 0x400) { | ||
| 541 | for (i = 0; i < (sz / PAGE_SIZE); i++) | ||
| 542 | __flush_dcache_icache(page_address(page+i)); | ||
| 543 | set_bit(PG_arch_1, &page->flags); | ||
| 544 | } else { | ||
| 545 | rflags |= HPTE_R_N; | ||
| 546 | } | ||
| 547 | } | ||
| 548 | return rflags; | ||
| 549 | } | ||
| 550 | 485 | ||
| 551 | int hash_huge_page(struct mm_struct *mm, unsigned long access, | 486 | /* Check that it is a page size supported by the hardware and |
| 552 | unsigned long ea, unsigned long vsid, int local, | 487 | * that it fits within pagetable and slice limits. */ |
| 553 | unsigned long trap) | 488 | if (!is_power_of_2(size) |
| 554 | { | 489 | || (shift > SLICE_HIGH_SHIFT) || (shift <= PAGE_SHIFT)) |
| 555 | pte_t *ptep; | 490 | return -EINVAL; |
| 556 | unsigned long old_pte, new_pte; | ||
| 557 | unsigned long va, rflags, pa, sz; | ||
| 558 | long slot; | ||
| 559 | int err = 1; | ||
| 560 | int ssize = user_segment_size(ea); | ||
| 561 | unsigned int mmu_psize; | ||
| 562 | int shift; | ||
| 563 | mmu_psize = get_slice_psize(mm, ea); | ||
| 564 | |||
| 565 | if (!mmu_huge_psizes[mmu_psize]) | ||
| 566 | goto out; | ||
| 567 | ptep = huge_pte_offset(mm, ea); | ||
| 568 | |||
| 569 | /* Search the Linux page table for a match with va */ | ||
| 570 | va = hpt_va(ea, vsid, ssize); | ||
| 571 | 491 | ||
| 572 | /* | 492 | if ((mmu_psize = shift_to_mmu_psize(shift)) < 0) |
| 573 | * If no pte found or not present, send the problem up to | 493 | return -EINVAL; |
| 574 | * do_page_fault | ||
| 575 | */ | ||
| 576 | if (unlikely(!ptep || pte_none(*ptep))) | ||
| 577 | goto out; | ||
| 578 | 494 | ||
| 579 | /* | 495 | #ifdef CONFIG_SPU_FS_64K_LS |
| 580 | * Check the user's access rights to the page. If access should be | 496 | /* Disable support for 64K huge pages when 64K SPU local store |
| 581 | * prevented then send the problem up to do_page_fault. | 497 | * support is enabled as the current implementation conflicts. |
| 582 | */ | 498 | */ |
| 583 | if (unlikely(access & ~pte_val(*ptep))) | 499 | if (shift == PAGE_SHIFT_64K) |
| 584 | goto out; | 500 | return -EINVAL; |
| 585 | /* | 501 | #endif /* CONFIG_SPU_FS_64K_LS */ |
| 586 | * At this point, we have a pte (old_pte) which can be used to build | ||
| 587 | * or update an HPTE. There are 2 cases: | ||
| 588 | * | ||
| 589 | * 1. There is a valid (present) pte with no associated HPTE (this is | ||
| 590 | * the most common case) | ||
| 591 | * 2. There is a valid (present) pte with an associated HPTE. The | ||
| 592 | * current values of the pp bits in the HPTE prevent access | ||
| 593 | * because we are doing software DIRTY bit management and the | ||
| 594 | * page is currently not DIRTY. | ||
| 595 | */ | ||
| 596 | |||
| 597 | |||
| 598 | do { | ||
| 599 | old_pte = pte_val(*ptep); | ||
| 600 | if (old_pte & _PAGE_BUSY) | ||
| 601 | goto out; | ||
| 602 | new_pte = old_pte | _PAGE_BUSY | _PAGE_ACCESSED; | ||
| 603 | } while(old_pte != __cmpxchg_u64((unsigned long *)ptep, | ||
| 604 | old_pte, new_pte)); | ||
| 605 | |||
| 606 | rflags = 0x2 | (!(new_pte & _PAGE_RW)); | ||
| 607 | /* _PAGE_EXEC -> HW_NO_EXEC since it's inverted */ | ||
| 608 | rflags |= ((new_pte & _PAGE_EXEC) ? 0 : HPTE_R_N); | ||
| 609 | shift = mmu_psize_to_shift(mmu_psize); | ||
| 610 | sz = ((1UL) << shift); | ||
| 611 | if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) | ||
| 612 | /* No CPU has hugepages but lacks no execute, so we | ||
| 613 | * don't need to worry about that case */ | ||
| 614 | rflags = hash_huge_page_do_lazy_icache(rflags, __pte(old_pte), | ||
| 615 | trap, sz); | ||
| 616 | |||
| 617 | /* Check if pte already has an hpte (case 2) */ | ||
| 618 | if (unlikely(old_pte & _PAGE_HASHPTE)) { | ||
| 619 | /* There MIGHT be an HPTE for this pte */ | ||
| 620 | unsigned long hash, slot; | ||
| 621 | |||
| 622 | hash = hpt_hash(va, shift, ssize); | ||
| 623 | if (old_pte & _PAGE_F_SECOND) | ||
| 624 | hash = ~hash; | ||
| 625 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | ||
| 626 | slot += (old_pte & _PAGE_F_GIX) >> 12; | ||
| 627 | |||
| 628 | if (ppc_md.hpte_updatepp(slot, rflags, va, mmu_psize, | ||
| 629 | ssize, local) == -1) | ||
| 630 | old_pte &= ~_PAGE_HPTEFLAGS; | ||
| 631 | } | ||
| 632 | |||
| 633 | if (likely(!(old_pte & _PAGE_HASHPTE))) { | ||
| 634 | unsigned long hash = hpt_hash(va, shift, ssize); | ||
| 635 | unsigned long hpte_group; | ||
| 636 | |||
| 637 | pa = pte_pfn(__pte(old_pte)) << PAGE_SHIFT; | ||
| 638 | |||
| 639 | repeat: | ||
| 640 | hpte_group = ((hash & htab_hash_mask) * | ||
| 641 | HPTES_PER_GROUP) & ~0x7UL; | ||
| 642 | |||
| 643 | /* clear HPTE slot informations in new PTE */ | ||
| 644 | #ifdef CONFIG_PPC_64K_PAGES | ||
| 645 | new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | _PAGE_HPTE_SUB0; | ||
| 646 | #else | ||
| 647 | new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE; | ||
| 648 | #endif | ||
| 649 | /* Add in WIMG bits */ | ||
| 650 | rflags |= (new_pte & (_PAGE_WRITETHRU | _PAGE_NO_CACHE | | ||
| 651 | _PAGE_COHERENT | _PAGE_GUARDED)); | ||
| 652 | |||
| 653 | /* Insert into the hash table, primary slot */ | ||
| 654 | slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags, 0, | ||
| 655 | mmu_psize, ssize); | ||
| 656 | |||
| 657 | /* Primary is full, try the secondary */ | ||
| 658 | if (unlikely(slot == -1)) { | ||
| 659 | hpte_group = ((~hash & htab_hash_mask) * | ||
| 660 | HPTES_PER_GROUP) & ~0x7UL; | ||
| 661 | slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags, | ||
| 662 | HPTE_V_SECONDARY, | ||
| 663 | mmu_psize, ssize); | ||
| 664 | if (slot == -1) { | ||
| 665 | if (mftb() & 0x1) | ||
| 666 | hpte_group = ((hash & htab_hash_mask) * | ||
| 667 | HPTES_PER_GROUP)&~0x7UL; | ||
| 668 | |||
| 669 | ppc_md.hpte_remove(hpte_group); | ||
| 670 | goto repeat; | ||
| 671 | } | ||
| 672 | } | ||
| 673 | |||
| 674 | if (unlikely(slot == -2)) | ||
| 675 | panic("hash_huge_page: pte_insert failed\n"); | ||
| 676 | |||
| 677 | new_pte |= (slot << 12) & (_PAGE_F_SECOND | _PAGE_F_GIX); | ||
| 678 | } | ||
| 679 | 502 | ||
| 680 | /* | 503 | BUG_ON(mmu_psize_defs[mmu_psize].shift != shift); |
| 681 | * No need to use ldarx/stdcx here | ||
| 682 | */ | ||
| 683 | *ptep = __pte(new_pte & ~_PAGE_BUSY); | ||
| 684 | 504 | ||
| 685 | err = 0; | 505 | /* Return if huge page size has already been setup */ |
| 506 | if (size_to_hstate(size)) | ||
| 507 | return 0; | ||
| 686 | 508 | ||
| 687 | out: | 509 | hugetlb_add_hstate(shift - PAGE_SHIFT); |
| 688 | return err; | ||
| 689 | } | ||
| 690 | 510 | ||
| 691 | static void __init set_huge_psize(int psize) | 511 | return 0; |
| 692 | { | ||
| 693 | /* Check that it is a page size supported by the hardware and | ||
| 694 | * that it fits within pagetable limits. */ | ||
| 695 | if (mmu_psize_defs[psize].shift && | ||
| 696 | mmu_psize_defs[psize].shift < SID_SHIFT_1T && | ||
| 697 | (mmu_psize_defs[psize].shift > MIN_HUGEPTE_SHIFT || | ||
| 698 | mmu_psize_defs[psize].shift == PAGE_SHIFT_64K || | ||
| 699 | mmu_psize_defs[psize].shift == PAGE_SHIFT_16G)) { | ||
| 700 | /* Return if huge page size has already been setup or is the | ||
| 701 | * same as the base page size. */ | ||
| 702 | if (mmu_huge_psizes[psize] || | ||
| 703 | mmu_psize_defs[psize].shift == PAGE_SHIFT) | ||
| 704 | return; | ||
| 705 | if (WARN_ON(HUGEPTE_CACHE_NAME(psize) == NULL)) | ||
| 706 | return; | ||
| 707 | hugetlb_add_hstate(mmu_psize_defs[psize].shift - PAGE_SHIFT); | ||
| 708 | |||
| 709 | switch (mmu_psize_defs[psize].shift) { | ||
| 710 | case PAGE_SHIFT_64K: | ||
| 711 | /* We only allow 64k hpages with 4k base page, | ||
| 712 | * which was checked above, and always put them | ||
| 713 | * at the PMD */ | ||
| 714 | hugepte_shift[psize] = PMD_SHIFT; | ||
| 715 | break; | ||
| 716 | case PAGE_SHIFT_16M: | ||
| 717 | /* 16M pages can be at two different levels | ||
| 718 | * of pagestables based on base page size */ | ||
| 719 | if (PAGE_SHIFT == PAGE_SHIFT_64K) | ||
| 720 | hugepte_shift[psize] = PMD_SHIFT; | ||
| 721 | else /* 4k base page */ | ||
| 722 | hugepte_shift[psize] = PUD_SHIFT; | ||
| 723 | break; | ||
| 724 | case PAGE_SHIFT_16G: | ||
| 725 | /* 16G pages are always at PGD level */ | ||
| 726 | hugepte_shift[psize] = PGDIR_SHIFT; | ||
| 727 | break; | ||
| 728 | } | ||
| 729 | hugepte_shift[psize] -= mmu_psize_defs[psize].shift; | ||
| 730 | } else | ||
| 731 | hugepte_shift[psize] = 0; | ||
| 732 | } | 512 | } |
| 733 | 513 | ||
| 734 | static int __init hugepage_setup_sz(char *str) | 514 | static int __init hugepage_setup_sz(char *str) |
| 735 | { | 515 | { |
| 736 | unsigned long long size; | 516 | unsigned long long size; |
| 737 | int mmu_psize; | ||
| 738 | int shift; | ||
| 739 | 517 | ||
| 740 | size = memparse(str, &str); | 518 | size = memparse(str, &str); |
| 741 | 519 | ||
| 742 | shift = __ffs(size); | 520 | if (add_huge_page_size(size) != 0) |
| 743 | mmu_psize = shift_to_mmu_psize(shift); | ||
| 744 | if (mmu_psize >= 0 && mmu_psize_defs[mmu_psize].shift) | ||
| 745 | set_huge_psize(mmu_psize); | ||
| 746 | else | ||
| 747 | printk(KERN_WARNING "Invalid huge page size specified(%llu)\n", size); | 521 | printk(KERN_WARNING "Invalid huge page size specified(%llu)\n", size); |
| 748 | 522 | ||
| 749 | return 1; | 523 | return 1; |
| @@ -752,41 +526,55 @@ __setup("hugepagesz=", hugepage_setup_sz); | |||
| 752 | 526 | ||
| 753 | static int __init hugetlbpage_init(void) | 527 | static int __init hugetlbpage_init(void) |
| 754 | { | 528 | { |
| 755 | unsigned int psize; | 529 | int psize; |
| 756 | 530 | ||
| 757 | if (!cpu_has_feature(CPU_FTR_16M_PAGE)) | 531 | if (!cpu_has_feature(CPU_FTR_16M_PAGE)) |
| 758 | return -ENODEV; | 532 | return -ENODEV; |
| 759 | 533 | ||
| 760 | /* Add supported huge page sizes. Need to change HUGE_MAX_HSTATE | 534 | for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { |
| 761 | * and adjust PTE_NONCACHE_NUM if the number of supported huge page | 535 | unsigned shift; |
| 762 | * sizes changes. | 536 | unsigned pdshift; |
| 763 | */ | ||
| 764 | set_huge_psize(MMU_PAGE_16M); | ||
| 765 | set_huge_psize(MMU_PAGE_16G); | ||
| 766 | 537 | ||
| 767 | /* Temporarily disable support for 64K huge pages when 64K SPU local | 538 | if (!mmu_psize_defs[psize].shift) |
| 768 | * store support is enabled as the current implementation conflicts. | 539 | continue; |
| 769 | */ | ||
| 770 | #ifndef CONFIG_SPU_FS_64K_LS | ||
| 771 | set_huge_psize(MMU_PAGE_64K); | ||
| 772 | #endif | ||
| 773 | 540 | ||
| 774 | for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { | 541 | shift = mmu_psize_to_shift(psize); |
| 775 | if (mmu_huge_psizes[psize]) { | 542 | |
| 776 | pgtable_cache[HUGE_PGTABLE_INDEX(psize)] = | 543 | if (add_huge_page_size(1ULL << shift) < 0) |
| 777 | kmem_cache_create( | 544 | continue; |
| 778 | HUGEPTE_CACHE_NAME(psize), | 545 | |
| 779 | HUGEPTE_TABLE_SIZE(psize), | 546 | if (shift < PMD_SHIFT) |
| 780 | HUGEPTE_TABLE_SIZE(psize), | 547 | pdshift = PMD_SHIFT; |
| 781 | 0, | 548 | else if (shift < PUD_SHIFT) |
| 782 | NULL); | 549 | pdshift = PUD_SHIFT; |
| 783 | if (!pgtable_cache[HUGE_PGTABLE_INDEX(psize)]) | 550 | else |
| 784 | panic("hugetlbpage_init(): could not create %s"\ | 551 | pdshift = PGDIR_SHIFT; |
| 785 | "\n", HUGEPTE_CACHE_NAME(psize)); | 552 | |
| 786 | } | 553 | pgtable_cache_add(pdshift - shift, NULL); |
| 554 | if (!PGT_CACHE(pdshift - shift)) | ||
| 555 | panic("hugetlbpage_init(): could not create " | ||
| 556 | "pgtable cache for %d bit pagesize\n", shift); | ||
| 787 | } | 557 | } |
| 788 | 558 | ||
| 559 | /* Set default large page size. Currently, we pick 16M or 1M | ||
| 560 | * depending on what is available | ||
| 561 | */ | ||
| 562 | if (mmu_psize_defs[MMU_PAGE_16M].shift) | ||
| 563 | HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_16M].shift; | ||
| 564 | else if (mmu_psize_defs[MMU_PAGE_1M].shift) | ||
| 565 | HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_1M].shift; | ||
| 566 | |||
| 789 | return 0; | 567 | return 0; |
| 790 | } | 568 | } |
| 791 | 569 | ||
| 792 | module_init(hugetlbpage_init); | 570 | module_init(hugetlbpage_init); |
| 571 | |||
| 572 | void flush_dcache_icache_hugepage(struct page *page) | ||
| 573 | { | ||
| 574 | int i; | ||
| 575 | |||
| 576 | BUG_ON(!PageCompound(page)); | ||
| 577 | |||
| 578 | for (i = 0; i < (1UL << compound_order(page)); i++) | ||
| 579 | __flush_dcache_icache(page_address(page+i)); | ||
| 580 | } | ||
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index 9ddcfb4dc139..4ec900af332f 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c | |||
| @@ -82,6 +82,11 @@ extern struct task_struct *current_set[NR_CPUS]; | |||
| 82 | int __map_without_bats; | 82 | int __map_without_bats; |
| 83 | int __map_without_ltlbs; | 83 | int __map_without_ltlbs; |
| 84 | 84 | ||
| 85 | /* | ||
| 86 | * This tells the system to allow ioremapping memory marked as reserved. | ||
| 87 | */ | ||
| 88 | int __allow_ioremap_reserved; | ||
| 89 | |||
| 85 | /* max amount of low RAM to map in */ | 90 | /* max amount of low RAM to map in */ |
| 86 | unsigned long __max_low_memory = MAX_LOW_MEM; | 91 | unsigned long __max_low_memory = MAX_LOW_MEM; |
| 87 | 92 | ||
| @@ -131,9 +136,13 @@ void __init MMU_init(void) | |||
| 131 | MMU_setup(); | 136 | MMU_setup(); |
| 132 | 137 | ||
| 133 | if (lmb.memory.cnt > 1) { | 138 | if (lmb.memory.cnt > 1) { |
| 139 | #ifndef CONFIG_WII | ||
| 134 | lmb.memory.cnt = 1; | 140 | lmb.memory.cnt = 1; |
| 135 | lmb_analyze(); | 141 | lmb_analyze(); |
| 136 | printk(KERN_WARNING "Only using first contiguous memory region"); | 142 | printk(KERN_WARNING "Only using first contiguous memory region"); |
| 143 | #else | ||
| 144 | wii_memory_fixups(); | ||
| 145 | #endif | ||
| 137 | } | 146 | } |
| 138 | 147 | ||
| 139 | total_lowmem = total_memory = lmb_end_of_DRAM() - memstart_addr; | 148 | total_lowmem = total_memory = lmb_end_of_DRAM() - memstart_addr; |
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 335c578b9cc3..776f28d02b6b 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #include <linux/module.h> | 41 | #include <linux/module.h> |
| 42 | #include <linux/poison.h> | 42 | #include <linux/poison.h> |
| 43 | #include <linux/lmb.h> | 43 | #include <linux/lmb.h> |
| 44 | #include <linux/hugetlb.h> | ||
| 44 | 45 | ||
| 45 | #include <asm/pgalloc.h> | 46 | #include <asm/pgalloc.h> |
| 46 | #include <asm/page.h> | 47 | #include <asm/page.h> |
| @@ -119,30 +120,63 @@ static void pmd_ctor(void *addr) | |||
| 119 | memset(addr, 0, PMD_TABLE_SIZE); | 120 | memset(addr, 0, PMD_TABLE_SIZE); |
| 120 | } | 121 | } |
| 121 | 122 | ||
| 122 | static const unsigned int pgtable_cache_size[2] = { | 123 | struct kmem_cache *pgtable_cache[MAX_PGTABLE_INDEX_SIZE]; |
| 123 | PGD_TABLE_SIZE, PMD_TABLE_SIZE | 124 | |
| 124 | }; | 125 | /* |
| 125 | static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { | 126 | * Create a kmem_cache() for pagetables. This is not used for PTE |
| 126 | #ifdef CONFIG_PPC_64K_PAGES | 127 | * pages - they're linked to struct page, come from the normal free |
| 127 | "pgd_cache", "pmd_cache", | 128 | * pages pool and have a different entry size (see real_pte_t) to |
| 128 | #else | 129 | * everything else. Caches created by this function are used for all |
| 129 | "pgd_cache", "pud_pmd_cache", | 130 | * the higher level pagetables, and for hugepage pagetables. |
| 130 | #endif /* CONFIG_PPC_64K_PAGES */ | 131 | */ |
| 131 | }; | 132 | void pgtable_cache_add(unsigned shift, void (*ctor)(void *)) |
| 132 | 133 | { | |
| 133 | #ifdef CONFIG_HUGETLB_PAGE | 134 | char *name; |
| 134 | /* Hugepages need an extra cache per hugepagesize, initialized in | 135 | unsigned long table_size = sizeof(void *) << shift; |
| 135 | * hugetlbpage.c. We can't put into the tables above, because HPAGE_SHIFT | 136 | unsigned long align = table_size; |
| 136 | * is not compile time constant. */ | 137 | |
| 137 | struct kmem_cache *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)+MMU_PAGE_COUNT]; | 138 | /* When batching pgtable pointers for RCU freeing, we store |
| 138 | #else | 139 | * the index size in the low bits. Table alignment must be |
| 139 | struct kmem_cache *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)]; | 140 | * big enough to fit it. |
| 140 | #endif | 141 | * |
| 142 | * Likewise, hugeapge pagetable pointers contain a (different) | ||
| 143 | * shift value in the low bits. All tables must be aligned so | ||
| 144 | * as to leave enough 0 bits in the address to contain it. */ | ||
| 145 | unsigned long minalign = max(MAX_PGTABLE_INDEX_SIZE + 1, | ||
| 146 | HUGEPD_SHIFT_MASK + 1); | ||
| 147 | struct kmem_cache *new; | ||
| 148 | |||
| 149 | /* It would be nice if this was a BUILD_BUG_ON(), but at the | ||
| 150 | * moment, gcc doesn't seem to recognize is_power_of_2 as a | ||
| 151 | * constant expression, so so much for that. */ | ||
| 152 | BUG_ON(!is_power_of_2(minalign)); | ||
| 153 | BUG_ON((shift < 1) || (shift > MAX_PGTABLE_INDEX_SIZE)); | ||
| 154 | |||
| 155 | if (PGT_CACHE(shift)) | ||
| 156 | return; /* Already have a cache of this size */ | ||
| 157 | |||
| 158 | align = max_t(unsigned long, align, minalign); | ||
| 159 | name = kasprintf(GFP_KERNEL, "pgtable-2^%d", shift); | ||
| 160 | new = kmem_cache_create(name, table_size, align, 0, ctor); | ||
| 161 | PGT_CACHE(shift) = new; | ||
| 162 | |||
| 163 | pr_debug("Allocated pgtable cache for order %d\n", shift); | ||
| 164 | } | ||
| 165 | |||
| 141 | 166 | ||
| 142 | void pgtable_cache_init(void) | 167 | void pgtable_cache_init(void) |
| 143 | { | 168 | { |
| 144 | pgtable_cache[0] = kmem_cache_create(pgtable_cache_name[0], PGD_TABLE_SIZE, PGD_TABLE_SIZE, SLAB_PANIC, pgd_ctor); | 169 | pgtable_cache_add(PGD_INDEX_SIZE, pgd_ctor); |
| 145 | pgtable_cache[1] = kmem_cache_create(pgtable_cache_name[1], PMD_TABLE_SIZE, PMD_TABLE_SIZE, SLAB_PANIC, pmd_ctor); | 170 | pgtable_cache_add(PMD_INDEX_SIZE, pmd_ctor); |
| 171 | if (!PGT_CACHE(PGD_INDEX_SIZE) || !PGT_CACHE(PMD_INDEX_SIZE)) | ||
| 172 | panic("Couldn't allocate pgtable caches"); | ||
| 173 | |||
| 174 | /* In all current configs, when the PUD index exists it's the | ||
| 175 | * same size as either the pgd or pmd index. Verify that the | ||
| 176 | * initialization above has also created a PUD cache. This | ||
| 177 | * will need re-examiniation if we add new possibilities for | ||
| 178 | * the pagetable layout. */ | ||
| 179 | BUG_ON(PUD_INDEX_SIZE && !PGT_CACHE(PUD_INDEX_SIZE)); | ||
| 146 | } | 180 | } |
| 147 | 181 | ||
| 148 | #ifdef CONFIG_SPARSEMEM_VMEMMAP | 182 | #ifdef CONFIG_SPARSEMEM_VMEMMAP |
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 59736317bf0e..b9b152558f9c 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/pagemap.h> | 32 | #include <linux/pagemap.h> |
| 33 | #include <linux/suspend.h> | 33 | #include <linux/suspend.h> |
| 34 | #include <linux/lmb.h> | 34 | #include <linux/lmb.h> |
| 35 | #include <linux/hugetlb.h> | ||
| 35 | 36 | ||
| 36 | #include <asm/pgalloc.h> | 37 | #include <asm/pgalloc.h> |
| 37 | #include <asm/prom.h> | 38 | #include <asm/prom.h> |
| @@ -417,18 +418,26 @@ EXPORT_SYMBOL(flush_dcache_page); | |||
| 417 | 418 | ||
| 418 | void flush_dcache_icache_page(struct page *page) | 419 | void flush_dcache_icache_page(struct page *page) |
| 419 | { | 420 | { |
| 421 | #ifdef CONFIG_HUGETLB_PAGE | ||
| 422 | if (PageCompound(page)) { | ||
| 423 | flush_dcache_icache_hugepage(page); | ||
| 424 | return; | ||
| 425 | } | ||
| 426 | #endif | ||
| 420 | #ifdef CONFIG_BOOKE | 427 | #ifdef CONFIG_BOOKE |
| 421 | void *start = kmap_atomic(page, KM_PPC_SYNC_ICACHE); | 428 | { |
| 422 | __flush_dcache_icache(start); | 429 | void *start = kmap_atomic(page, KM_PPC_SYNC_ICACHE); |
| 423 | kunmap_atomic(start, KM_PPC_SYNC_ICACHE); | 430 | __flush_dcache_icache(start); |
| 431 | kunmap_atomic(start, KM_PPC_SYNC_ICACHE); | ||
| 432 | } | ||
| 424 | #elif defined(CONFIG_8xx) || defined(CONFIG_PPC64) | 433 | #elif defined(CONFIG_8xx) || defined(CONFIG_PPC64) |
| 425 | /* On 8xx there is no need to kmap since highmem is not supported */ | 434 | /* On 8xx there is no need to kmap since highmem is not supported */ |
| 426 | __flush_dcache_icache(page_address(page)); | 435 | __flush_dcache_icache(page_address(page)); |
| 427 | #else | 436 | #else |
| 428 | __flush_dcache_icache_phys(page_to_pfn(page) << PAGE_SHIFT); | 437 | __flush_dcache_icache_phys(page_to_pfn(page) << PAGE_SHIFT); |
| 429 | #endif | 438 | #endif |
| 430 | |||
| 431 | } | 439 | } |
| 440 | |||
| 432 | void clear_user_page(void *page, unsigned long vaddr, struct page *pg) | 441 | void clear_user_page(void *page, unsigned long vaddr, struct page *pg) |
| 433 | { | 442 | { |
| 434 | clear_page(page); | 443 | clear_page(page); |
diff --git a/arch/powerpc/mm/mmu_context_hash64.c b/arch/powerpc/mm/mmu_context_hash64.c index dbeb86ac90cd..b910d37aea1a 100644 --- a/arch/powerpc/mm/mmu_context_hash64.c +++ b/arch/powerpc/mm/mmu_context_hash64.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
| 19 | #include <linux/spinlock.h> | 19 | #include <linux/spinlock.h> |
| 20 | #include <linux/idr.h> | 20 | #include <linux/idr.h> |
| 21 | #include <linux/module.h> | ||
| 21 | 22 | ||
| 22 | #include <asm/mmu_context.h> | 23 | #include <asm/mmu_context.h> |
| 23 | 24 | ||
| @@ -32,7 +33,7 @@ static DEFINE_IDR(mmu_context_idr); | |||
| 32 | #define NO_CONTEXT 0 | 33 | #define NO_CONTEXT 0 |
| 33 | #define MAX_CONTEXT ((1UL << 19) - 1) | 34 | #define MAX_CONTEXT ((1UL << 19) - 1) |
| 34 | 35 | ||
| 35 | int init_new_context(struct task_struct *tsk, struct mm_struct *mm) | 36 | int __init_new_context(void) |
| 36 | { | 37 | { |
| 37 | int index; | 38 | int index; |
| 38 | int err; | 39 | int err; |
| @@ -57,22 +58,41 @@ again: | |||
| 57 | return -ENOMEM; | 58 | return -ENOMEM; |
| 58 | } | 59 | } |
| 59 | 60 | ||
| 61 | return index; | ||
| 62 | } | ||
| 63 | EXPORT_SYMBOL_GPL(__init_new_context); | ||
| 64 | |||
| 65 | int init_new_context(struct task_struct *tsk, struct mm_struct *mm) | ||
| 66 | { | ||
| 67 | int index; | ||
| 68 | |||
| 69 | index = __init_new_context(); | ||
| 70 | if (index < 0) | ||
| 71 | return index; | ||
| 72 | |||
| 60 | /* The old code would re-promote on fork, we don't do that | 73 | /* The old code would re-promote on fork, we don't do that |
| 61 | * when using slices as it could cause problem promoting slices | 74 | * when using slices as it could cause problem promoting slices |
| 62 | * that have been forced down to 4K | 75 | * that have been forced down to 4K |
| 63 | */ | 76 | */ |
| 64 | if (slice_mm_new_context(mm)) | 77 | if (slice_mm_new_context(mm)) |
| 65 | slice_set_user_psize(mm, mmu_virtual_psize); | 78 | slice_set_user_psize(mm, mmu_virtual_psize); |
| 79 | subpage_prot_init_new_context(mm); | ||
| 66 | mm->context.id = index; | 80 | mm->context.id = index; |
| 67 | 81 | ||
| 68 | return 0; | 82 | return 0; |
| 69 | } | 83 | } |
| 70 | 84 | ||
| 71 | void destroy_context(struct mm_struct *mm) | 85 | void __destroy_context(int context_id) |
| 72 | { | 86 | { |
| 73 | spin_lock(&mmu_context_lock); | 87 | spin_lock(&mmu_context_lock); |
| 74 | idr_remove(&mmu_context_idr, mm->context.id); | 88 | idr_remove(&mmu_context_idr, context_id); |
| 75 | spin_unlock(&mmu_context_lock); | 89 | spin_unlock(&mmu_context_lock); |
| 90 | } | ||
| 91 | EXPORT_SYMBOL_GPL(__destroy_context); | ||
| 76 | 92 | ||
| 93 | void destroy_context(struct mm_struct *mm) | ||
| 94 | { | ||
| 95 | __destroy_context(mm->context.id); | ||
| 96 | subpage_prot_free(mm); | ||
| 77 | mm->context.id = NO_CONTEXT; | 97 | mm->context.id = NO_CONTEXT; |
| 78 | } | 98 | } |
diff --git a/arch/powerpc/mm/mmu_context_nohash.c b/arch/powerpc/mm/mmu_context_nohash.c index be4f34c30a0b..1044a634b6d0 100644 --- a/arch/powerpc/mm/mmu_context_nohash.c +++ b/arch/powerpc/mm/mmu_context_nohash.c | |||
| @@ -353,7 +353,7 @@ static int __cpuinit mmu_context_cpu_notify(struct notifier_block *self, | |||
| 353 | read_lock(&tasklist_lock); | 353 | read_lock(&tasklist_lock); |
| 354 | for_each_process(p) { | 354 | for_each_process(p) { |
| 355 | if (p->mm) | 355 | if (p->mm) |
| 356 | cpu_mask_clear_cpu(cpu, mm_cpumask(p->mm)); | 356 | cpumask_clear_cpu(cpu, mm_cpumask(p->mm)); |
| 357 | } | 357 | } |
| 358 | read_unlock(&tasklist_lock); | 358 | read_unlock(&tasklist_lock); |
| 359 | break; | 359 | break; |
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h index d2e5321d5ea6..d49a77503e19 100644 --- a/arch/powerpc/mm/mmu_decl.h +++ b/arch/powerpc/mm/mmu_decl.h | |||
| @@ -98,23 +98,13 @@ extern void _tlbia(void); | |||
| 98 | 98 | ||
| 99 | #ifdef CONFIG_PPC32 | 99 | #ifdef CONFIG_PPC32 |
| 100 | 100 | ||
| 101 | struct tlbcam { | ||
| 102 | u32 MAS0; | ||
| 103 | u32 MAS1; | ||
| 104 | u32 MAS2; | ||
| 105 | u32 MAS3; | ||
| 106 | u32 MAS7; | ||
| 107 | }; | ||
| 108 | |||
| 109 | extern void mapin_ram(void); | 101 | extern void mapin_ram(void); |
| 110 | extern int map_page(unsigned long va, phys_addr_t pa, int flags); | 102 | extern int map_page(unsigned long va, phys_addr_t pa, int flags); |
| 111 | extern void setbat(int index, unsigned long virt, phys_addr_t phys, | 103 | extern void setbat(int index, unsigned long virt, phys_addr_t phys, |
| 112 | unsigned int size, int flags); | 104 | unsigned int size, int flags); |
| 113 | extern void settlbcam(int index, unsigned long virt, phys_addr_t phys, | ||
| 114 | unsigned int size, int flags, unsigned int pid); | ||
| 115 | extern void invalidate_tlbcam_entry(int index); | ||
| 116 | 105 | ||
| 117 | extern int __map_without_bats; | 106 | extern int __map_without_bats; |
| 107 | extern int __allow_ioremap_reserved; | ||
| 118 | extern unsigned long ioremap_base; | 108 | extern unsigned long ioremap_base; |
| 119 | extern unsigned int rtas_data, rtas_size; | 109 | extern unsigned int rtas_data, rtas_size; |
| 120 | 110 | ||
| @@ -136,24 +126,32 @@ extern phys_addr_t total_lowmem; | |||
| 136 | extern phys_addr_t memstart_addr; | 126 | extern phys_addr_t memstart_addr; |
| 137 | extern phys_addr_t lowmem_end_addr; | 127 | extern phys_addr_t lowmem_end_addr; |
| 138 | 128 | ||
| 129 | #ifdef CONFIG_WII | ||
| 130 | extern unsigned long wii_hole_start; | ||
| 131 | extern unsigned long wii_hole_size; | ||
| 132 | |||
| 133 | extern unsigned long wii_mmu_mapin_mem2(unsigned long top); | ||
| 134 | extern void wii_memory_fixups(void); | ||
| 135 | #endif | ||
| 136 | |||
| 139 | /* ...and now those things that may be slightly different between processor | 137 | /* ...and now those things that may be slightly different between processor |
| 140 | * architectures. -- Dan | 138 | * architectures. -- Dan |
| 141 | */ | 139 | */ |
| 142 | #if defined(CONFIG_8xx) | 140 | #if defined(CONFIG_8xx) |
| 143 | #define MMU_init_hw() do { } while(0) | 141 | #define MMU_init_hw() do { } while(0) |
| 144 | #define mmu_mapin_ram() (0UL) | 142 | #define mmu_mapin_ram(top) (0UL) |
| 145 | 143 | ||
| 146 | #elif defined(CONFIG_4xx) | 144 | #elif defined(CONFIG_4xx) |
| 147 | extern void MMU_init_hw(void); | 145 | extern void MMU_init_hw(void); |
| 148 | extern unsigned long mmu_mapin_ram(void); | 146 | extern unsigned long mmu_mapin_ram(unsigned long top); |
| 149 | 147 | ||
| 150 | #elif defined(CONFIG_FSL_BOOKE) | 148 | #elif defined(CONFIG_FSL_BOOKE) |
| 151 | extern void MMU_init_hw(void); | 149 | extern void MMU_init_hw(void); |
| 152 | extern unsigned long mmu_mapin_ram(void); | 150 | extern unsigned long mmu_mapin_ram(unsigned long top); |
| 153 | extern void adjust_total_lowmem(void); | 151 | extern void adjust_total_lowmem(void); |
| 154 | 152 | ||
| 155 | #elif defined(CONFIG_PPC32) | 153 | #elif defined(CONFIG_PPC32) |
| 156 | /* anything 32-bit except 4xx or 8xx */ | 154 | /* anything 32-bit except 4xx or 8xx */ |
| 157 | extern void MMU_init_hw(void); | 155 | extern void MMU_init_hw(void); |
| 158 | extern unsigned long mmu_mapin_ram(void); | 156 | extern unsigned long mmu_mapin_ram(unsigned long top); |
| 159 | #endif | 157 | #endif |
diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c index 53040931de32..99df697c601a 100644 --- a/arch/powerpc/mm/pgtable.c +++ b/arch/powerpc/mm/pgtable.c | |||
| @@ -49,12 +49,12 @@ struct pte_freelist_batch | |||
| 49 | { | 49 | { |
| 50 | struct rcu_head rcu; | 50 | struct rcu_head rcu; |
| 51 | unsigned int index; | 51 | unsigned int index; |
| 52 | pgtable_free_t tables[0]; | 52 | unsigned long tables[0]; |
| 53 | }; | 53 | }; |
| 54 | 54 | ||
| 55 | #define PTE_FREELIST_SIZE \ | 55 | #define PTE_FREELIST_SIZE \ |
| 56 | ((PAGE_SIZE - sizeof(struct pte_freelist_batch)) \ | 56 | ((PAGE_SIZE - sizeof(struct pte_freelist_batch)) \ |
| 57 | / sizeof(pgtable_free_t)) | 57 | / sizeof(unsigned long)) |
| 58 | 58 | ||
| 59 | static void pte_free_smp_sync(void *arg) | 59 | static void pte_free_smp_sync(void *arg) |
| 60 | { | 60 | { |
| @@ -64,13 +64,13 @@ static void pte_free_smp_sync(void *arg) | |||
| 64 | /* This is only called when we are critically out of memory | 64 | /* This is only called when we are critically out of memory |
| 65 | * (and fail to get a page in pte_free_tlb). | 65 | * (and fail to get a page in pte_free_tlb). |
| 66 | */ | 66 | */ |
| 67 | static void pgtable_free_now(pgtable_free_t pgf) | 67 | static void pgtable_free_now(void *table, unsigned shift) |
| 68 | { | 68 | { |
| 69 | pte_freelist_forced_free++; | 69 | pte_freelist_forced_free++; |
| 70 | 70 | ||
| 71 | smp_call_function(pte_free_smp_sync, NULL, 1); | 71 | smp_call_function(pte_free_smp_sync, NULL, 1); |
| 72 | 72 | ||
| 73 | pgtable_free(pgf); | 73 | pgtable_free(table, shift); |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | static void pte_free_rcu_callback(struct rcu_head *head) | 76 | static void pte_free_rcu_callback(struct rcu_head *head) |
| @@ -79,8 +79,12 @@ static void pte_free_rcu_callback(struct rcu_head *head) | |||
| 79 | container_of(head, struct pte_freelist_batch, rcu); | 79 | container_of(head, struct pte_freelist_batch, rcu); |
| 80 | unsigned int i; | 80 | unsigned int i; |
| 81 | 81 | ||
| 82 | for (i = 0; i < batch->index; i++) | 82 | for (i = 0; i < batch->index; i++) { |
| 83 | pgtable_free(batch->tables[i]); | 83 | void *table = (void *)(batch->tables[i] & ~MAX_PGTABLE_INDEX_SIZE); |
| 84 | unsigned shift = batch->tables[i] & MAX_PGTABLE_INDEX_SIZE; | ||
| 85 | |||
| 86 | pgtable_free(table, shift); | ||
| 87 | } | ||
| 84 | 88 | ||
| 85 | free_page((unsigned long)batch); | 89 | free_page((unsigned long)batch); |
| 86 | } | 90 | } |
| @@ -91,25 +95,28 @@ static void pte_free_submit(struct pte_freelist_batch *batch) | |||
| 91 | call_rcu(&batch->rcu, pte_free_rcu_callback); | 95 | call_rcu(&batch->rcu, pte_free_rcu_callback); |
| 92 | } | 96 | } |
| 93 | 97 | ||
| 94 | void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf) | 98 | void pgtable_free_tlb(struct mmu_gather *tlb, void *table, unsigned shift) |
| 95 | { | 99 | { |
| 96 | /* This is safe since tlb_gather_mmu has disabled preemption */ | 100 | /* This is safe since tlb_gather_mmu has disabled preemption */ |
| 97 | struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur); | 101 | struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur); |
| 102 | unsigned long pgf; | ||
| 98 | 103 | ||
| 99 | if (atomic_read(&tlb->mm->mm_users) < 2 || | 104 | if (atomic_read(&tlb->mm->mm_users) < 2 || |
| 100 | cpumask_equal(mm_cpumask(tlb->mm), cpumask_of(smp_processor_id()))){ | 105 | cpumask_equal(mm_cpumask(tlb->mm), cpumask_of(smp_processor_id()))){ |
| 101 | pgtable_free(pgf); | 106 | pgtable_free(table, shift); |
| 102 | return; | 107 | return; |
| 103 | } | 108 | } |
| 104 | 109 | ||
| 105 | if (*batchp == NULL) { | 110 | if (*batchp == NULL) { |
| 106 | *batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC); | 111 | *batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC); |
| 107 | if (*batchp == NULL) { | 112 | if (*batchp == NULL) { |
| 108 | pgtable_free_now(pgf); | 113 | pgtable_free_now(table, shift); |
| 109 | return; | 114 | return; |
| 110 | } | 115 | } |
| 111 | (*batchp)->index = 0; | 116 | (*batchp)->index = 0; |
| 112 | } | 117 | } |
| 118 | BUG_ON(shift > MAX_PGTABLE_INDEX_SIZE); | ||
| 119 | pgf = (unsigned long)table | shift; | ||
| 113 | (*batchp)->tables[(*batchp)->index++] = pgf; | 120 | (*batchp)->tables[(*batchp)->index++] = pgf; |
| 114 | if ((*batchp)->index == PTE_FREELIST_SIZE) { | 121 | if ((*batchp)->index == PTE_FREELIST_SIZE) { |
| 115 | pte_free_submit(*batchp); | 122 | pte_free_submit(*batchp); |
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index cb96cb2e17cc..573b3bd1c45b 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/vmalloc.h> | 26 | #include <linux/vmalloc.h> |
| 27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
| 28 | #include <linux/highmem.h> | 28 | #include <linux/highmem.h> |
| 29 | #include <linux/lmb.h> | ||
| 29 | 30 | ||
| 30 | #include <asm/pgtable.h> | 31 | #include <asm/pgtable.h> |
| 31 | #include <asm/pgalloc.h> | 32 | #include <asm/pgalloc.h> |
| @@ -191,7 +192,8 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags, | |||
| 191 | * Don't allow anybody to remap normal RAM that we're using. | 192 | * Don't allow anybody to remap normal RAM that we're using. |
| 192 | * mem_init() sets high_memory so only do the check after that. | 193 | * mem_init() sets high_memory so only do the check after that. |
| 193 | */ | 194 | */ |
| 194 | if (mem_init_done && (p < virt_to_phys(high_memory))) { | 195 | if (mem_init_done && (p < virt_to_phys(high_memory)) && |
| 196 | !(__allow_ioremap_reserved && lmb_is_region_reserved(p, size))) { | ||
| 195 | printk("__ioremap(): phys addr 0x%llx is RAM lr %p\n", | 197 | printk("__ioremap(): phys addr 0x%llx is RAM lr %p\n", |
| 196 | (unsigned long long)p, __builtin_return_address(0)); | 198 | (unsigned long long)p, __builtin_return_address(0)); |
| 197 | return NULL; | 199 | return NULL; |
| @@ -283,18 +285,18 @@ int map_page(unsigned long va, phys_addr_t pa, int flags) | |||
| 283 | } | 285 | } |
| 284 | 286 | ||
| 285 | /* | 287 | /* |
| 286 | * Map in a big chunk of physical memory starting at PAGE_OFFSET. | 288 | * Map in a chunk of physical memory starting at start. |
| 287 | */ | 289 | */ |
| 288 | void __init mapin_ram(void) | 290 | void __init __mapin_ram_chunk(unsigned long offset, unsigned long top) |
| 289 | { | 291 | { |
| 290 | unsigned long v, s, f; | 292 | unsigned long v, s, f; |
| 291 | phys_addr_t p; | 293 | phys_addr_t p; |
| 292 | int ktext; | 294 | int ktext; |
| 293 | 295 | ||
| 294 | s = mmu_mapin_ram(); | 296 | s = offset; |
| 295 | v = PAGE_OFFSET + s; | 297 | v = PAGE_OFFSET + s; |
| 296 | p = memstart_addr + s; | 298 | p = memstart_addr + s; |
| 297 | for (; s < total_lowmem; s += PAGE_SIZE) { | 299 | for (; s < top; s += PAGE_SIZE) { |
| 298 | ktext = ((char *) v >= _stext && (char *) v < etext); | 300 | ktext = ((char *) v >= _stext && (char *) v < etext); |
| 299 | f = ktext ? PAGE_KERNEL_TEXT : PAGE_KERNEL; | 301 | f = ktext ? PAGE_KERNEL_TEXT : PAGE_KERNEL; |
| 300 | map_page(v, p, f); | 302 | map_page(v, p, f); |
| @@ -307,6 +309,30 @@ void __init mapin_ram(void) | |||
| 307 | } | 309 | } |
| 308 | } | 310 | } |
| 309 | 311 | ||
| 312 | void __init mapin_ram(void) | ||
| 313 | { | ||
| 314 | unsigned long s, top; | ||
| 315 | |||
| 316 | #ifndef CONFIG_WII | ||
| 317 | top = total_lowmem; | ||
| 318 | s = mmu_mapin_ram(top); | ||
| 319 | __mapin_ram_chunk(s, top); | ||
| 320 | #else | ||
| 321 | if (!wii_hole_size) { | ||
| 322 | s = mmu_mapin_ram(total_lowmem); | ||
| 323 | __mapin_ram_chunk(s, total_lowmem); | ||
| 324 | } else { | ||
| 325 | top = wii_hole_start; | ||
| 326 | s = mmu_mapin_ram(top); | ||
| 327 | __mapin_ram_chunk(s, top); | ||
| 328 | |||
| 329 | top = lmb_end_of_DRAM(); | ||
| 330 | s = wii_mmu_mapin_mem2(top); | ||
| 331 | __mapin_ram_chunk(s, top); | ||
| 332 | } | ||
| 333 | #endif | ||
| 334 | } | ||
| 335 | |||
| 310 | /* Scan the real Linux page tables and return a PTE pointer for | 336 | /* Scan the real Linux page tables and return a PTE pointer for |
| 311 | * a virtual address in a context. | 337 | * a virtual address in a context. |
| 312 | * Returns true (1) if PTE was found, zero otherwise. The pointer to | 338 | * Returns true (1) if PTE was found, zero otherwise. The pointer to |
| @@ -356,7 +382,7 @@ static int __change_page_attr(struct page *page, pgprot_t prot) | |||
| 356 | return 0; | 382 | return 0; |
| 357 | if (!get_pteptr(&init_mm, address, &kpte, &kpmd)) | 383 | if (!get_pteptr(&init_mm, address, &kpte, &kpmd)) |
| 358 | return -EINVAL; | 384 | return -EINVAL; |
| 359 | set_pte_at(&init_mm, address, kpte, mk_pte(page, prot)); | 385 | __set_pte_at(&init_mm, address, kpte, mk_pte(page, prot), 0); |
| 360 | wmb(); | 386 | wmb(); |
| 361 | #ifdef CONFIG_PPC_STD_MMU | 387 | #ifdef CONFIG_PPC_STD_MMU |
| 362 | flush_hash_pages(0, address, pmd_val(*kpmd), 1); | 388 | flush_hash_pages(0, address, pmd_val(*kpmd), 1); |
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index 2d2a87e10154..f11c2cdcb0fe 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c | |||
| @@ -72,7 +72,7 @@ unsigned long p_mapped_by_bats(phys_addr_t pa) | |||
| 72 | return 0; | 72 | return 0; |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | unsigned long __init mmu_mapin_ram(void) | 75 | unsigned long __init mmu_mapin_ram(unsigned long top) |
| 76 | { | 76 | { |
| 77 | unsigned long tot, bl, done; | 77 | unsigned long tot, bl, done; |
| 78 | unsigned long max_size = (256<<20); | 78 | unsigned long max_size = (256<<20); |
| @@ -86,7 +86,7 @@ unsigned long __init mmu_mapin_ram(void) | |||
| 86 | 86 | ||
| 87 | /* Make sure we don't map a block larger than the | 87 | /* Make sure we don't map a block larger than the |
| 88 | smallest alignment of the physical address. */ | 88 | smallest alignment of the physical address. */ |
| 89 | tot = total_lowmem; | 89 | tot = top; |
| 90 | for (bl = 128<<10; bl < max_size; bl <<= 1) { | 90 | for (bl = 128<<10; bl < max_size; bl <<= 1) { |
| 91 | if (bl * 2 > tot) | 91 | if (bl * 2 > tot) |
| 92 | break; | 92 | break; |
diff --git a/arch/powerpc/mm/subpage-prot.c b/arch/powerpc/mm/subpage-prot.c index 4cafc0c33d0a..a040b81e93bd 100644 --- a/arch/powerpc/mm/subpage-prot.c +++ b/arch/powerpc/mm/subpage-prot.c | |||
| @@ -24,9 +24,9 @@ | |||
| 24 | * Also makes sure that the subpage_prot_table structure is | 24 | * Also makes sure that the subpage_prot_table structure is |
| 25 | * reinitialized for the next user. | 25 | * reinitialized for the next user. |
| 26 | */ | 26 | */ |
| 27 | void subpage_prot_free(pgd_t *pgd) | 27 | void subpage_prot_free(struct mm_struct *mm) |
| 28 | { | 28 | { |
| 29 | struct subpage_prot_table *spt = pgd_subpage_prot(pgd); | 29 | struct subpage_prot_table *spt = &mm->context.spt; |
| 30 | unsigned long i, j, addr; | 30 | unsigned long i, j, addr; |
| 31 | u32 **p; | 31 | u32 **p; |
| 32 | 32 | ||
| @@ -51,6 +51,13 @@ void subpage_prot_free(pgd_t *pgd) | |||
| 51 | spt->maxaddr = 0; | 51 | spt->maxaddr = 0; |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | void subpage_prot_init_new_context(struct mm_struct *mm) | ||
| 55 | { | ||
| 56 | struct subpage_prot_table *spt = &mm->context.spt; | ||
| 57 | |||
| 58 | memset(spt, 0, sizeof(*spt)); | ||
| 59 | } | ||
| 60 | |||
| 54 | static void hpte_flush_range(struct mm_struct *mm, unsigned long addr, | 61 | static void hpte_flush_range(struct mm_struct *mm, unsigned long addr, |
| 55 | int npages) | 62 | int npages) |
| 56 | { | 63 | { |
| @@ -87,7 +94,7 @@ static void hpte_flush_range(struct mm_struct *mm, unsigned long addr, | |||
| 87 | static void subpage_prot_clear(unsigned long addr, unsigned long len) | 94 | static void subpage_prot_clear(unsigned long addr, unsigned long len) |
| 88 | { | 95 | { |
| 89 | struct mm_struct *mm = current->mm; | 96 | struct mm_struct *mm = current->mm; |
| 90 | struct subpage_prot_table *spt = pgd_subpage_prot(mm->pgd); | 97 | struct subpage_prot_table *spt = &mm->context.spt; |
| 91 | u32 **spm, *spp; | 98 | u32 **spm, *spp; |
| 92 | int i, nw; | 99 | int i, nw; |
| 93 | unsigned long next, limit; | 100 | unsigned long next, limit; |
| @@ -136,7 +143,7 @@ static void subpage_prot_clear(unsigned long addr, unsigned long len) | |||
| 136 | long sys_subpage_prot(unsigned long addr, unsigned long len, u32 __user *map) | 143 | long sys_subpage_prot(unsigned long addr, unsigned long len, u32 __user *map) |
| 137 | { | 144 | { |
| 138 | struct mm_struct *mm = current->mm; | 145 | struct mm_struct *mm = current->mm; |
| 139 | struct subpage_prot_table *spt = pgd_subpage_prot(mm->pgd); | 146 | struct subpage_prot_table *spt = &mm->context.spt; |
| 140 | u32 **spm, *spp; | 147 | u32 **spm, *spp; |
| 141 | int i, nw; | 148 | int i, nw; |
| 142 | unsigned long next, limit; | 149 | unsigned long next, limit; |
diff --git a/arch/powerpc/mm/tlb_hash64.c b/arch/powerpc/mm/tlb_hash64.c index 2b2f35f6985e..282d9306361f 100644 --- a/arch/powerpc/mm/tlb_hash64.c +++ b/arch/powerpc/mm/tlb_hash64.c | |||
| @@ -53,11 +53,6 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr, | |||
| 53 | 53 | ||
| 54 | i = batch->index; | 54 | i = batch->index; |
| 55 | 55 | ||
| 56 | /* We mask the address for the base page size. Huge pages will | ||
| 57 | * have applied their own masking already | ||
| 58 | */ | ||
| 59 | addr &= PAGE_MASK; | ||
| 60 | |||
| 61 | /* Get page size (maybe move back to caller). | 56 | /* Get page size (maybe move back to caller). |
| 62 | * | 57 | * |
| 63 | * NOTE: when using special 64K mappings in 4K environment like | 58 | * NOTE: when using special 64K mappings in 4K environment like |
| @@ -75,6 +70,9 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr, | |||
| 75 | } else | 70 | } else |
| 76 | psize = pte_pagesize_index(mm, addr, pte); | 71 | psize = pte_pagesize_index(mm, addr, pte); |
| 77 | 72 | ||
| 73 | /* Mask the address for the correct page size */ | ||
| 74 | addr &= ~((1UL << mmu_psize_defs[psize].shift) - 1); | ||
| 75 | |||
| 78 | /* Build full vaddr */ | 76 | /* Build full vaddr */ |
| 79 | if (!is_kernel_addr(addr)) { | 77 | if (!is_kernel_addr(addr)) { |
| 80 | ssize = user_segment_size(addr); | 78 | ssize = user_segment_size(addr); |
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c index a6ce80566625..da9b20a63769 100644 --- a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c +++ b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c | |||
| @@ -79,7 +79,7 @@ cpld_unmask_irq(unsigned int irq) | |||
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | static struct irq_chip cpld_pic = { | 81 | static struct irq_chip cpld_pic = { |
| 82 | .typename = " CPLD PIC ", | 82 | .name = " CPLD PIC ", |
| 83 | .mask = cpld_mask_irq, | 83 | .mask = cpld_mask_irq, |
| 84 | .ack = cpld_mask_irq, | 84 | .ack = cpld_mask_irq, |
| 85 | .unmask = cpld_unmask_irq, | 85 | .unmask = cpld_unmask_irq, |
| @@ -132,7 +132,7 @@ static int | |||
| 132 | cpld_pic_host_map(struct irq_host *h, unsigned int virq, | 132 | cpld_pic_host_map(struct irq_host *h, unsigned int virq, |
| 133 | irq_hw_number_t hw) | 133 | irq_hw_number_t hw) |
| 134 | { | 134 | { |
| 135 | get_irq_desc(virq)->status |= IRQ_LEVEL; | 135 | irq_to_desc(virq)->status |= IRQ_LEVEL; |
| 136 | set_irq_chip_and_handler(virq, &cpld_pic, handle_level_irq); | 136 | set_irq_chip_and_handler(virq, &cpld_pic, handle_level_irq); |
| 137 | return 0; | 137 | return 0; |
| 138 | } | 138 | } |
diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig index 8b8e9560a315..47ea1be1481b 100644 --- a/arch/powerpc/platforms/52xx/Kconfig +++ b/arch/powerpc/platforms/52xx/Kconfig | |||
| @@ -62,3 +62,8 @@ config PPC_MPC5200_GPIO | |||
| 62 | select GENERIC_GPIO | 62 | select GENERIC_GPIO |
| 63 | help | 63 | help |
| 64 | Enable gpiolib support for mpc5200 based boards | 64 | Enable gpiolib support for mpc5200 based boards |
| 65 | |||
| 66 | config PPC_MPC5200_LPBFIFO | ||
| 67 | tristate "MPC5200 LocalPlus bus FIFO driver" | ||
| 68 | depends on PPC_MPC52xx | ||
| 69 | select PPC_BESTCOMM_GEN_BD | ||
diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile index bfd4f52cf3dd..2bc8cd0c5cfc 100644 --- a/arch/powerpc/platforms/52xx/Makefile +++ b/arch/powerpc/platforms/52xx/Makefile | |||
| @@ -15,3 +15,4 @@ ifeq ($(CONFIG_PPC_LITE5200),y) | |||
| 15 | endif | 15 | endif |
| 16 | 16 | ||
| 17 | obj-$(CONFIG_PPC_MPC5200_GPIO) += mpc52xx_gpio.o | 17 | obj-$(CONFIG_PPC_MPC5200_GPIO) += mpc52xx_gpio.o |
| 18 | obj-$(CONFIG_PPC_MPC5200_LPBFIFO) += mpc52xx_lpbfifo.o | ||
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c index bcc69e1f77c1..45c0cb9b67e6 100644 --- a/arch/powerpc/platforms/52xx/efika.c +++ b/arch/powerpc/platforms/52xx/efika.c | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
| 13 | #include <linux/utsrelease.h> | 13 | #include <generated/utsrelease.h> |
| 14 | #include <linux/pci.h> | 14 | #include <linux/pci.h> |
| 15 | #include <linux/of.h> | 15 | #include <linux/of.h> |
| 16 | #include <asm/prom.h> | 16 | #include <asm/prom.h> |
diff --git a/arch/powerpc/platforms/52xx/media5200.c b/arch/powerpc/platforms/52xx/media5200.c index 68e4f1696d14..0bac3a3dbecf 100644 --- a/arch/powerpc/platforms/52xx/media5200.c +++ b/arch/powerpc/platforms/52xx/media5200.c | |||
| @@ -74,7 +74,7 @@ static void media5200_irq_mask(unsigned int virq) | |||
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | static struct irq_chip media5200_irq_chip = { | 76 | static struct irq_chip media5200_irq_chip = { |
| 77 | .typename = "Media5200 FPGA", | 77 | .name = "Media5200 FPGA", |
| 78 | .unmask = media5200_irq_unmask, | 78 | .unmask = media5200_irq_unmask, |
| 79 | .mask = media5200_irq_mask, | 79 | .mask = media5200_irq_mask, |
| 80 | .mask_ack = media5200_irq_mask, | 80 | .mask_ack = media5200_irq_mask, |
| @@ -86,9 +86,9 @@ void media5200_irq_cascade(unsigned int virq, struct irq_desc *desc) | |||
| 86 | u32 status, enable; | 86 | u32 status, enable; |
| 87 | 87 | ||
| 88 | /* Mask off the cascaded IRQ */ | 88 | /* Mask off the cascaded IRQ */ |
| 89 | spin_lock(&desc->lock); | 89 | raw_spin_lock(&desc->lock); |
| 90 | desc->chip->mask(virq); | 90 | desc->chip->mask(virq); |
| 91 | spin_unlock(&desc->lock); | 91 | raw_spin_unlock(&desc->lock); |
| 92 | 92 | ||
| 93 | /* Ask the FPGA for IRQ status. If 'val' is 0, then no irqs | 93 | /* Ask the FPGA for IRQ status. If 'val' is 0, then no irqs |
| 94 | * are pending. 'ffs()' is 1 based */ | 94 | * are pending. 'ffs()' is 1 based */ |
| @@ -104,17 +104,17 @@ void media5200_irq_cascade(unsigned int virq, struct irq_desc *desc) | |||
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | /* Processing done; can reenable the cascade now */ | 106 | /* Processing done; can reenable the cascade now */ |
| 107 | spin_lock(&desc->lock); | 107 | raw_spin_lock(&desc->lock); |
| 108 | desc->chip->ack(virq); | 108 | desc->chip->ack(virq); |
| 109 | if (!(desc->status & IRQ_DISABLED)) | 109 | if (!(desc->status & IRQ_DISABLED)) |
| 110 | desc->chip->unmask(virq); | 110 | desc->chip->unmask(virq); |
| 111 | spin_unlock(&desc->lock); | 111 | raw_spin_unlock(&desc->lock); |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | static int media5200_irq_map(struct irq_host *h, unsigned int virq, | 114 | static int media5200_irq_map(struct irq_host *h, unsigned int virq, |
| 115 | irq_hw_number_t hw) | 115 | irq_hw_number_t hw) |
| 116 | { | 116 | { |
| 117 | struct irq_desc *desc = get_irq_desc(virq); | 117 | struct irq_desc *desc = irq_to_desc(virq); |
| 118 | 118 | ||
| 119 | pr_debug("%s: h=%p, virq=%i, hwirq=%i\n", __func__, h, virq, (int)hw); | 119 | pr_debug("%s: h=%p, virq=%i, hwirq=%i\n", __func__, h, virq, (int)hw); |
| 120 | set_irq_chip_data(virq, &media5200_irq); | 120 | set_irq_chip_data(virq, &media5200_irq); |
| @@ -127,7 +127,7 @@ static int media5200_irq_map(struct irq_host *h, unsigned int virq, | |||
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | static int media5200_irq_xlate(struct irq_host *h, struct device_node *ct, | 129 | static int media5200_irq_xlate(struct irq_host *h, struct device_node *ct, |
| 130 | u32 *intspec, unsigned int intsize, | 130 | const u32 *intspec, unsigned int intsize, |
| 131 | irq_hw_number_t *out_hwirq, | 131 | irq_hw_number_t *out_hwirq, |
| 132 | unsigned int *out_flags) | 132 | unsigned int *out_flags) |
| 133 | { | 133 | { |
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c index bfbcd418e690..6f8ebe1085b3 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c | |||
| @@ -16,8 +16,14 @@ | |||
| 16 | * output signals or measure input signals. | 16 | * output signals or measure input signals. |
| 17 | * | 17 | * |
| 18 | * This driver supports the GPIO and IRQ controller functions of the GPT | 18 | * This driver supports the GPIO and IRQ controller functions of the GPT |
| 19 | * device. Timer functions are not yet supported, nor is the watchdog | 19 | * device. Timer functions are not yet supported. |
| 20 | * timer. | 20 | * |
| 21 | * The timer gpt0 can be used as watchdog (wdt). If the wdt mode is used, | ||
| 22 | * this prevents the use of any gpt0 gpt function (i.e. they will fail with | ||
| 23 | * -EBUSY). Thus, the safety wdt function always has precedence over the gpt | ||
| 24 | * function. If the kernel has been compiled with CONFIG_WATCHDOG_NOWAYOUT, | ||
| 25 | * this means that gpt0 is locked in wdt mode until the next reboot - this | ||
| 26 | * may be a requirement in safety applications. | ||
| 21 | * | 27 | * |
| 22 | * To use the GPIO function, the following two properties must be added | 28 | * To use the GPIO function, the following two properties must be added |
| 23 | * to the device tree node for the gpt device (typically in the .dts file | 29 | * to the device tree node for the gpt device (typically in the .dts file |
| @@ -46,17 +52,24 @@ | |||
| 46 | * the output mode. This driver does not change the output mode setting. | 52 | * the output mode. This driver does not change the output mode setting. |
| 47 | */ | 53 | */ |
| 48 | 54 | ||
| 55 | #include <linux/device.h> | ||
| 49 | #include <linux/irq.h> | 56 | #include <linux/irq.h> |
| 50 | #include <linux/interrupt.h> | 57 | #include <linux/interrupt.h> |
| 51 | #include <linux/io.h> | 58 | #include <linux/io.h> |
| 59 | #include <linux/list.h> | ||
| 60 | #include <linux/mutex.h> | ||
| 52 | #include <linux/of.h> | 61 | #include <linux/of.h> |
| 53 | #include <linux/of_platform.h> | 62 | #include <linux/of_platform.h> |
| 54 | #include <linux/of_gpio.h> | 63 | #include <linux/of_gpio.h> |
| 55 | #include <linux/kernel.h> | 64 | #include <linux/kernel.h> |
| 65 | #include <linux/watchdog.h> | ||
| 66 | #include <linux/miscdevice.h> | ||
| 67 | #include <linux/uaccess.h> | ||
| 68 | #include <asm/div64.h> | ||
| 56 | #include <asm/mpc52xx.h> | 69 | #include <asm/mpc52xx.h> |
| 57 | 70 | ||
| 58 | MODULE_DESCRIPTION("Freescale MPC52xx gpt driver"); | 71 | MODULE_DESCRIPTION("Freescale MPC52xx gpt driver"); |
| 59 | MODULE_AUTHOR("Sascha Hauer, Grant Likely"); | 72 | MODULE_AUTHOR("Sascha Hauer, Grant Likely, Albrecht Dreß"); |
| 60 | MODULE_LICENSE("GPL"); | 73 | MODULE_LICENSE("GPL"); |
| 61 | 74 | ||
| 62 | /** | 75 | /** |
| @@ -66,18 +79,27 @@ MODULE_LICENSE("GPL"); | |||
| 66 | * @lock: spinlock to coordinate between different functions. | 79 | * @lock: spinlock to coordinate between different functions. |
| 67 | * @of_gc: of_gpio_chip instance structure; used when GPIO is enabled | 80 | * @of_gc: of_gpio_chip instance structure; used when GPIO is enabled |
| 68 | * @irqhost: Pointer to irq_host instance; used when IRQ mode is supported | 81 | * @irqhost: Pointer to irq_host instance; used when IRQ mode is supported |
| 82 | * @wdt_mode: only relevant for gpt0: bit 0 (MPC52xx_GPT_CAN_WDT) indicates | ||
| 83 | * if the gpt may be used as wdt, bit 1 (MPC52xx_GPT_IS_WDT) indicates | ||
| 84 | * if the timer is actively used as wdt which blocks gpt functions | ||
| 69 | */ | 85 | */ |
| 70 | struct mpc52xx_gpt_priv { | 86 | struct mpc52xx_gpt_priv { |
| 87 | struct list_head list; /* List of all GPT devices */ | ||
| 71 | struct device *dev; | 88 | struct device *dev; |
| 72 | struct mpc52xx_gpt __iomem *regs; | 89 | struct mpc52xx_gpt __iomem *regs; |
| 73 | spinlock_t lock; | 90 | spinlock_t lock; |
| 74 | struct irq_host *irqhost; | 91 | struct irq_host *irqhost; |
| 92 | u32 ipb_freq; | ||
| 93 | u8 wdt_mode; | ||
| 75 | 94 | ||
| 76 | #if defined(CONFIG_GPIOLIB) | 95 | #if defined(CONFIG_GPIOLIB) |
| 77 | struct of_gpio_chip of_gc; | 96 | struct of_gpio_chip of_gc; |
| 78 | #endif | 97 | #endif |
| 79 | }; | 98 | }; |
| 80 | 99 | ||
| 100 | LIST_HEAD(mpc52xx_gpt_list); | ||
| 101 | DEFINE_MUTEX(mpc52xx_gpt_list_mutex); | ||
| 102 | |||
| 81 | #define MPC52xx_GPT_MODE_MS_MASK (0x07) | 103 | #define MPC52xx_GPT_MODE_MS_MASK (0x07) |
| 82 | #define MPC52xx_GPT_MODE_MS_IC (0x01) | 104 | #define MPC52xx_GPT_MODE_MS_IC (0x01) |
| 83 | #define MPC52xx_GPT_MODE_MS_OC (0x02) | 105 | #define MPC52xx_GPT_MODE_MS_OC (0x02) |
| @@ -88,15 +110,25 @@ struct mpc52xx_gpt_priv { | |||
| 88 | #define MPC52xx_GPT_MODE_GPIO_OUT_LOW (0x20) | 110 | #define MPC52xx_GPT_MODE_GPIO_OUT_LOW (0x20) |
| 89 | #define MPC52xx_GPT_MODE_GPIO_OUT_HIGH (0x30) | 111 | #define MPC52xx_GPT_MODE_GPIO_OUT_HIGH (0x30) |
| 90 | 112 | ||
| 113 | #define MPC52xx_GPT_MODE_COUNTER_ENABLE (0x1000) | ||
| 114 | #define MPC52xx_GPT_MODE_CONTINUOUS (0x0400) | ||
| 115 | #define MPC52xx_GPT_MODE_OPEN_DRAIN (0x0200) | ||
| 91 | #define MPC52xx_GPT_MODE_IRQ_EN (0x0100) | 116 | #define MPC52xx_GPT_MODE_IRQ_EN (0x0100) |
| 117 | #define MPC52xx_GPT_MODE_WDT_EN (0x8000) | ||
| 92 | 118 | ||
| 93 | #define MPC52xx_GPT_MODE_ICT_MASK (0x030000) | 119 | #define MPC52xx_GPT_MODE_ICT_MASK (0x030000) |
| 94 | #define MPC52xx_GPT_MODE_ICT_RISING (0x010000) | 120 | #define MPC52xx_GPT_MODE_ICT_RISING (0x010000) |
| 95 | #define MPC52xx_GPT_MODE_ICT_FALLING (0x020000) | 121 | #define MPC52xx_GPT_MODE_ICT_FALLING (0x020000) |
| 96 | #define MPC52xx_GPT_MODE_ICT_TOGGLE (0x030000) | 122 | #define MPC52xx_GPT_MODE_ICT_TOGGLE (0x030000) |
| 97 | 123 | ||
| 124 | #define MPC52xx_GPT_MODE_WDT_PING (0xa5) | ||
| 125 | |||
| 98 | #define MPC52xx_GPT_STATUS_IRQMASK (0x000f) | 126 | #define MPC52xx_GPT_STATUS_IRQMASK (0x000f) |
| 99 | 127 | ||
| 128 | #define MPC52xx_GPT_CAN_WDT (1 << 0) | ||
| 129 | #define MPC52xx_GPT_IS_WDT (1 << 1) | ||
| 130 | |||
| 131 | |||
| 100 | /* --------------------------------------------------------------------- | 132 | /* --------------------------------------------------------------------- |
| 101 | * Cascaded interrupt controller hooks | 133 | * Cascaded interrupt controller hooks |
| 102 | */ | 134 | */ |
| @@ -149,7 +181,7 @@ static int mpc52xx_gpt_irq_set_type(unsigned int virq, unsigned int flow_type) | |||
| 149 | } | 181 | } |
| 150 | 182 | ||
| 151 | static struct irq_chip mpc52xx_gpt_irq_chip = { | 183 | static struct irq_chip mpc52xx_gpt_irq_chip = { |
| 152 | .typename = "MPC52xx GPT", | 184 | .name = "MPC52xx GPT", |
| 153 | .unmask = mpc52xx_gpt_irq_unmask, | 185 | .unmask = mpc52xx_gpt_irq_unmask, |
| 154 | .mask = mpc52xx_gpt_irq_mask, | 186 | .mask = mpc52xx_gpt_irq_mask, |
| 155 | .ack = mpc52xx_gpt_irq_ack, | 187 | .ack = mpc52xx_gpt_irq_ack, |
| @@ -182,7 +214,7 @@ static int mpc52xx_gpt_irq_map(struct irq_host *h, unsigned int virq, | |||
| 182 | } | 214 | } |
| 183 | 215 | ||
| 184 | static int mpc52xx_gpt_irq_xlate(struct irq_host *h, struct device_node *ct, | 216 | static int mpc52xx_gpt_irq_xlate(struct irq_host *h, struct device_node *ct, |
| 185 | u32 *intspec, unsigned int intsize, | 217 | const u32 *intspec, unsigned int intsize, |
| 186 | irq_hw_number_t *out_hwirq, | 218 | irq_hw_number_t *out_hwirq, |
| 187 | unsigned int *out_flags) | 219 | unsigned int *out_flags) |
| 188 | { | 220 | { |
| @@ -190,7 +222,7 @@ static int mpc52xx_gpt_irq_xlate(struct irq_host *h, struct device_node *ct, | |||
| 190 | 222 | ||
| 191 | dev_dbg(gpt->dev, "%s: flags=%i\n", __func__, intspec[0]); | 223 | dev_dbg(gpt->dev, "%s: flags=%i\n", __func__, intspec[0]); |
| 192 | 224 | ||
| 193 | if ((intsize < 1) || (intspec[0] < 1) || (intspec[0] > 3)) { | 225 | if ((intsize < 1) || (intspec[0] > 3)) { |
| 194 | dev_err(gpt->dev, "bad irq specifier in %s\n", ct->full_name); | 226 | dev_err(gpt->dev, "bad irq specifier in %s\n", ct->full_name); |
| 195 | return -EINVAL; | 227 | return -EINVAL; |
| 196 | } | 228 | } |
| @@ -211,13 +243,11 @@ mpc52xx_gpt_irq_setup(struct mpc52xx_gpt_priv *gpt, struct device_node *node) | |||
| 211 | { | 243 | { |
| 212 | int cascade_virq; | 244 | int cascade_virq; |
| 213 | unsigned long flags; | 245 | unsigned long flags; |
| 214 | 246 | u32 mode; | |
| 215 | /* Only setup cascaded IRQ if device tree claims the GPT is | ||
| 216 | * an interrupt controller */ | ||
| 217 | if (!of_find_property(node, "interrupt-controller", NULL)) | ||
| 218 | return; | ||
| 219 | 247 | ||
| 220 | cascade_virq = irq_of_parse_and_map(node, 0); | 248 | cascade_virq = irq_of_parse_and_map(node, 0); |
| 249 | if (!cascade_virq) | ||
| 250 | return; | ||
| 221 | 251 | ||
| 222 | gpt->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR, 1, | 252 | gpt->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR, 1, |
| 223 | &mpc52xx_gpt_irq_ops, -1); | 253 | &mpc52xx_gpt_irq_ops, -1); |
| @@ -227,14 +257,16 @@ mpc52xx_gpt_irq_setup(struct mpc52xx_gpt_priv *gpt, struct device_node *node) | |||
| 227 | } | 257 | } |
| 228 | 258 | ||
| 229 | gpt->irqhost->host_data = gpt; | 259 | gpt->irqhost->host_data = gpt; |
| 230 | |||
| 231 | set_irq_data(cascade_virq, gpt); | 260 | set_irq_data(cascade_virq, gpt); |
| 232 | set_irq_chained_handler(cascade_virq, mpc52xx_gpt_irq_cascade); | 261 | set_irq_chained_handler(cascade_virq, mpc52xx_gpt_irq_cascade); |
| 233 | 262 | ||
| 234 | /* Set to Input Capture mode */ | 263 | /* If the GPT is currently disabled, then change it to be in Input |
| 264 | * Capture mode. If the mode is non-zero, then the pin could be | ||
| 265 | * already in use for something. */ | ||
| 235 | spin_lock_irqsave(&gpt->lock, flags); | 266 | spin_lock_irqsave(&gpt->lock, flags); |
| 236 | clrsetbits_be32(&gpt->regs->mode, MPC52xx_GPT_MODE_MS_MASK, | 267 | mode = in_be32(&gpt->regs->mode); |
| 237 | MPC52xx_GPT_MODE_MS_IC); | 268 | if ((mode & MPC52xx_GPT_MODE_MS_MASK) == 0) |
| 269 | out_be32(&gpt->regs->mode, mode | MPC52xx_GPT_MODE_MS_IC); | ||
| 238 | spin_unlock_irqrestore(&gpt->lock, flags); | 270 | spin_unlock_irqrestore(&gpt->lock, flags); |
| 239 | 271 | ||
| 240 | dev_dbg(gpt->dev, "%s() complete. virq=%i\n", __func__, cascade_virq); | 272 | dev_dbg(gpt->dev, "%s() complete. virq=%i\n", __func__, cascade_virq); |
| @@ -335,6 +367,354 @@ static void | |||
| 335 | mpc52xx_gpt_gpio_setup(struct mpc52xx_gpt_priv *p, struct device_node *np) { } | 367 | mpc52xx_gpt_gpio_setup(struct mpc52xx_gpt_priv *p, struct device_node *np) { } |
| 336 | #endif /* defined(CONFIG_GPIOLIB) */ | 368 | #endif /* defined(CONFIG_GPIOLIB) */ |
| 337 | 369 | ||
| 370 | /*********************************************************************** | ||
| 371 | * Timer API | ||
| 372 | */ | ||
| 373 | |||
| 374 | /** | ||
| 375 | * mpc52xx_gpt_from_irq - Return the GPT device associated with an IRQ number | ||
| 376 | * @irq: irq of timer. | ||
| 377 | */ | ||
| 378 | struct mpc52xx_gpt_priv *mpc52xx_gpt_from_irq(int irq) | ||
| 379 | { | ||
| 380 | struct mpc52xx_gpt_priv *gpt; | ||
| 381 | struct list_head *pos; | ||
| 382 | |||
| 383 | /* Iterate over the list of timers looking for a matching device */ | ||
| 384 | mutex_lock(&mpc52xx_gpt_list_mutex); | ||
| 385 | list_for_each(pos, &mpc52xx_gpt_list) { | ||
| 386 | gpt = container_of(pos, struct mpc52xx_gpt_priv, list); | ||
| 387 | if (gpt->irqhost && irq == irq_linear_revmap(gpt->irqhost, 0)) { | ||
| 388 | mutex_unlock(&mpc52xx_gpt_list_mutex); | ||
| 389 | return gpt; | ||
| 390 | } | ||
| 391 | } | ||
| 392 | mutex_unlock(&mpc52xx_gpt_list_mutex); | ||
| 393 | |||
| 394 | return NULL; | ||
| 395 | } | ||
| 396 | EXPORT_SYMBOL(mpc52xx_gpt_from_irq); | ||
| 397 | |||
| 398 | static int mpc52xx_gpt_do_start(struct mpc52xx_gpt_priv *gpt, u64 period, | ||
| 399 | int continuous, int as_wdt) | ||
| 400 | { | ||
| 401 | u32 clear, set; | ||
| 402 | u64 clocks; | ||
| 403 | u32 prescale; | ||
| 404 | unsigned long flags; | ||
| 405 | |||
| 406 | clear = MPC52xx_GPT_MODE_MS_MASK | MPC52xx_GPT_MODE_CONTINUOUS; | ||
| 407 | set = MPC52xx_GPT_MODE_MS_GPIO | MPC52xx_GPT_MODE_COUNTER_ENABLE; | ||
| 408 | if (as_wdt) { | ||
| 409 | clear |= MPC52xx_GPT_MODE_IRQ_EN; | ||
| 410 | set |= MPC52xx_GPT_MODE_WDT_EN; | ||
| 411 | } else if (continuous) | ||
| 412 | set |= MPC52xx_GPT_MODE_CONTINUOUS; | ||
| 413 | |||
| 414 | /* Determine the number of clocks in the requested period. 64 bit | ||
| 415 | * arithmatic is done here to preserve the precision until the value | ||
| 416 | * is scaled back down into the u32 range. Period is in 'ns', bus | ||
| 417 | * frequency is in Hz. */ | ||
| 418 | clocks = period * (u64)gpt->ipb_freq; | ||
| 419 | do_div(clocks, 1000000000); /* Scale it down to ns range */ | ||
| 420 | |||
| 421 | /* This device cannot handle a clock count greater than 32 bits */ | ||
| 422 | if (clocks > 0xffffffff) | ||
| 423 | return -EINVAL; | ||
| 424 | |||
| 425 | /* Calculate the prescaler and count values from the clocks value. | ||
| 426 | * 'clocks' is the number of clock ticks in the period. The timer | ||
| 427 | * has 16 bit precision and a 16 bit prescaler. Prescaler is | ||
| 428 | * calculated by integer dividing the clocks by 0x10000 (shifting | ||
| 429 | * down 16 bits) to obtain the smallest possible divisor for clocks | ||
| 430 | * to get a 16 bit count value. | ||
| 431 | * | ||
| 432 | * Note: the prescale register is '1' based, not '0' based. ie. a | ||
| 433 | * value of '1' means divide the clock by one. 0xffff divides the | ||
| 434 | * clock by 0xffff. '0x0000' does not divide by zero, but wraps | ||
| 435 | * around and divides by 0x10000. That is why prescale must be | ||
| 436 | * a u32 variable, not a u16, for this calculation. */ | ||
| 437 | prescale = (clocks >> 16) + 1; | ||
| 438 | do_div(clocks, prescale); | ||
| 439 | if (clocks > 0xffff) { | ||
| 440 | pr_err("calculation error; prescale:%x clocks:%llx\n", | ||
| 441 | prescale, clocks); | ||
| 442 | return -EINVAL; | ||
| 443 | } | ||
| 444 | |||
| 445 | /* Set and enable the timer, reject an attempt to use a wdt as gpt */ | ||
| 446 | spin_lock_irqsave(&gpt->lock, flags); | ||
| 447 | if (as_wdt) | ||
| 448 | gpt->wdt_mode |= MPC52xx_GPT_IS_WDT; | ||
| 449 | else if ((gpt->wdt_mode & MPC52xx_GPT_IS_WDT) != 0) { | ||
| 450 | spin_unlock_irqrestore(&gpt->lock, flags); | ||
| 451 | return -EBUSY; | ||
| 452 | } | ||
| 453 | out_be32(&gpt->regs->count, prescale << 16 | clocks); | ||
| 454 | clrsetbits_be32(&gpt->regs->mode, clear, set); | ||
| 455 | spin_unlock_irqrestore(&gpt->lock, flags); | ||
| 456 | |||
| 457 | return 0; | ||
| 458 | } | ||
| 459 | |||
| 460 | /** | ||
| 461 | * mpc52xx_gpt_start_timer - Set and enable the GPT timer | ||
| 462 | * @gpt: Pointer to gpt private data structure | ||
| 463 | * @period: period of timer in ns; max. ~130s @ 33MHz IPB clock | ||
| 464 | * @continuous: set to 1 to make timer continuous free running | ||
| 465 | * | ||
| 466 | * An interrupt will be generated every time the timer fires | ||
| 467 | */ | ||
| 468 | int mpc52xx_gpt_start_timer(struct mpc52xx_gpt_priv *gpt, u64 period, | ||
| 469 | int continuous) | ||
| 470 | { | ||
| 471 | return mpc52xx_gpt_do_start(gpt, period, continuous, 0); | ||
| 472 | } | ||
| 473 | EXPORT_SYMBOL(mpc52xx_gpt_start_timer); | ||
| 474 | |||
| 475 | /** | ||
| 476 | * mpc52xx_gpt_stop_timer - Stop a gpt | ||
| 477 | * @gpt: Pointer to gpt private data structure | ||
| 478 | * | ||
| 479 | * Returns an error if attempting to stop a wdt | ||
| 480 | */ | ||
| 481 | int mpc52xx_gpt_stop_timer(struct mpc52xx_gpt_priv *gpt) | ||
| 482 | { | ||
| 483 | unsigned long flags; | ||
| 484 | |||
| 485 | /* reject the operation if the timer is used as watchdog (gpt 0 only) */ | ||
| 486 | spin_lock_irqsave(&gpt->lock, flags); | ||
| 487 | if ((gpt->wdt_mode & MPC52xx_GPT_IS_WDT) != 0) { | ||
| 488 | spin_unlock_irqrestore(&gpt->lock, flags); | ||
| 489 | return -EBUSY; | ||
| 490 | } | ||
| 491 | |||
| 492 | clrbits32(&gpt->regs->mode, MPC52xx_GPT_MODE_COUNTER_ENABLE); | ||
| 493 | spin_unlock_irqrestore(&gpt->lock, flags); | ||
| 494 | return 0; | ||
| 495 | } | ||
| 496 | EXPORT_SYMBOL(mpc52xx_gpt_stop_timer); | ||
| 497 | |||
| 498 | /** | ||
| 499 | * mpc52xx_gpt_timer_period - Read the timer period | ||
| 500 | * @gpt: Pointer to gpt private data structure | ||
| 501 | * | ||
| 502 | * Returns the timer period in ns | ||
| 503 | */ | ||
| 504 | u64 mpc52xx_gpt_timer_period(struct mpc52xx_gpt_priv *gpt) | ||
| 505 | { | ||
| 506 | u64 period; | ||
| 507 | u64 prescale; | ||
| 508 | unsigned long flags; | ||
| 509 | |||
| 510 | spin_lock_irqsave(&gpt->lock, flags); | ||
| 511 | period = in_be32(&gpt->regs->count); | ||
| 512 | spin_unlock_irqrestore(&gpt->lock, flags); | ||
| 513 | |||
| 514 | prescale = period >> 16; | ||
| 515 | period &= 0xffff; | ||
| 516 | if (prescale == 0) | ||
| 517 | prescale = 0x10000; | ||
| 518 | period = period * prescale * 1000000000ULL; | ||
| 519 | do_div(period, (u64)gpt->ipb_freq); | ||
| 520 | return period; | ||
| 521 | } | ||
| 522 | EXPORT_SYMBOL(mpc52xx_gpt_timer_period); | ||
| 523 | |||
| 524 | #if defined(CONFIG_MPC5200_WDT) | ||
| 525 | /*********************************************************************** | ||
| 526 | * Watchdog API for gpt0 | ||
| 527 | */ | ||
| 528 | |||
| 529 | #define WDT_IDENTITY "mpc52xx watchdog on GPT0" | ||
| 530 | |||
| 531 | /* wdt_is_active stores wether or not the /dev/watchdog device is opened */ | ||
| 532 | static unsigned long wdt_is_active; | ||
| 533 | |||
| 534 | /* wdt-capable gpt */ | ||
| 535 | static struct mpc52xx_gpt_priv *mpc52xx_gpt_wdt; | ||
| 536 | |||
| 537 | /* low-level wdt functions */ | ||
| 538 | static inline void mpc52xx_gpt_wdt_ping(struct mpc52xx_gpt_priv *gpt_wdt) | ||
| 539 | { | ||
| 540 | unsigned long flags; | ||
| 541 | |||
| 542 | spin_lock_irqsave(&gpt_wdt->lock, flags); | ||
| 543 | out_8((u8 *) &gpt_wdt->regs->mode, MPC52xx_GPT_MODE_WDT_PING); | ||
| 544 | spin_unlock_irqrestore(&gpt_wdt->lock, flags); | ||
| 545 | } | ||
| 546 | |||
| 547 | /* wdt misc device api */ | ||
| 548 | static ssize_t mpc52xx_wdt_write(struct file *file, const char __user *data, | ||
| 549 | size_t len, loff_t *ppos) | ||
| 550 | { | ||
| 551 | struct mpc52xx_gpt_priv *gpt_wdt = file->private_data; | ||
| 552 | mpc52xx_gpt_wdt_ping(gpt_wdt); | ||
| 553 | return 0; | ||
| 554 | } | ||
| 555 | |||
| 556 | static struct watchdog_info mpc5200_wdt_info = { | ||
| 557 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | ||
| 558 | .identity = WDT_IDENTITY, | ||
| 559 | }; | ||
| 560 | |||
| 561 | static long mpc52xx_wdt_ioctl(struct file *file, unsigned int cmd, | ||
| 562 | unsigned long arg) | ||
| 563 | { | ||
| 564 | struct mpc52xx_gpt_priv *gpt_wdt = file->private_data; | ||
| 565 | int __user *data = (int __user *)arg; | ||
| 566 | int timeout; | ||
| 567 | u64 real_timeout; | ||
| 568 | int ret = 0; | ||
| 569 | |||
| 570 | switch (cmd) { | ||
| 571 | case WDIOC_GETSUPPORT: | ||
| 572 | ret = copy_to_user(data, &mpc5200_wdt_info, | ||
| 573 | sizeof(mpc5200_wdt_info)); | ||
| 574 | if (ret) | ||
| 575 | ret = -EFAULT; | ||
| 576 | break; | ||
| 577 | |||
| 578 | case WDIOC_GETSTATUS: | ||
| 579 | case WDIOC_GETBOOTSTATUS: | ||
| 580 | ret = put_user(0, data); | ||
| 581 | break; | ||
| 582 | |||
| 583 | case WDIOC_KEEPALIVE: | ||
| 584 | mpc52xx_gpt_wdt_ping(gpt_wdt); | ||
| 585 | break; | ||
| 586 | |||
| 587 | case WDIOC_SETTIMEOUT: | ||
| 588 | ret = get_user(timeout, data); | ||
| 589 | if (ret) | ||
| 590 | break; | ||
| 591 | real_timeout = (u64) timeout * 1000000000ULL; | ||
| 592 | ret = mpc52xx_gpt_do_start(gpt_wdt, real_timeout, 0, 1); | ||
| 593 | if (ret) | ||
| 594 | break; | ||
| 595 | /* fall through and return the timeout */ | ||
| 596 | |||
| 597 | case WDIOC_GETTIMEOUT: | ||
| 598 | /* we need to round here as to avoid e.g. the following | ||
| 599 | * situation: | ||
| 600 | * - timeout requested is 1 second; | ||
| 601 | * - real timeout @33MHz is 999997090ns | ||
| 602 | * - the int divide by 10^9 will return 0. | ||
| 603 | */ | ||
| 604 | real_timeout = | ||
| 605 | mpc52xx_gpt_timer_period(gpt_wdt) + 500000000ULL; | ||
| 606 | do_div(real_timeout, 1000000000ULL); | ||
| 607 | timeout = (int) real_timeout; | ||
| 608 | ret = put_user(timeout, data); | ||
| 609 | break; | ||
| 610 | |||
| 611 | default: | ||
| 612 | ret = -ENOTTY; | ||
| 613 | } | ||
| 614 | return ret; | ||
| 615 | } | ||
| 616 | |||
| 617 | static int mpc52xx_wdt_open(struct inode *inode, struct file *file) | ||
| 618 | { | ||
| 619 | int ret; | ||
| 620 | |||
| 621 | /* sanity check */ | ||
| 622 | if (!mpc52xx_gpt_wdt) | ||
| 623 | return -ENODEV; | ||
| 624 | |||
| 625 | /* /dev/watchdog can only be opened once */ | ||
| 626 | if (test_and_set_bit(0, &wdt_is_active)) | ||
| 627 | return -EBUSY; | ||
| 628 | |||
| 629 | /* Set and activate the watchdog with 30 seconds timeout */ | ||
| 630 | ret = mpc52xx_gpt_do_start(mpc52xx_gpt_wdt, 30ULL * 1000000000ULL, | ||
| 631 | 0, 1); | ||
| 632 | if (ret) { | ||
| 633 | clear_bit(0, &wdt_is_active); | ||
| 634 | return ret; | ||
| 635 | } | ||
| 636 | |||
| 637 | file->private_data = mpc52xx_gpt_wdt; | ||
| 638 | return nonseekable_open(inode, file); | ||
| 639 | } | ||
| 640 | |||
| 641 | static int mpc52xx_wdt_release(struct inode *inode, struct file *file) | ||
| 642 | { | ||
| 643 | /* note: releasing the wdt in NOWAYOUT-mode does not stop it */ | ||
| 644 | #if !defined(CONFIG_WATCHDOG_NOWAYOUT) | ||
| 645 | struct mpc52xx_gpt_priv *gpt_wdt = file->private_data; | ||
| 646 | unsigned long flags; | ||
| 647 | |||
| 648 | spin_lock_irqsave(&gpt_wdt->lock, flags); | ||
| 649 | clrbits32(&gpt_wdt->regs->mode, | ||
| 650 | MPC52xx_GPT_MODE_COUNTER_ENABLE | MPC52xx_GPT_MODE_WDT_EN); | ||
| 651 | gpt_wdt->wdt_mode &= ~MPC52xx_GPT_IS_WDT; | ||
| 652 | spin_unlock_irqrestore(&gpt_wdt->lock, flags); | ||
| 653 | #endif | ||
| 654 | clear_bit(0, &wdt_is_active); | ||
| 655 | return 0; | ||
| 656 | } | ||
| 657 | |||
| 658 | |||
| 659 | static const struct file_operations mpc52xx_wdt_fops = { | ||
| 660 | .owner = THIS_MODULE, | ||
| 661 | .llseek = no_llseek, | ||
| 662 | .write = mpc52xx_wdt_write, | ||
| 663 | .unlocked_ioctl = mpc52xx_wdt_ioctl, | ||
| 664 | .open = mpc52xx_wdt_open, | ||
| 665 | .release = mpc52xx_wdt_release, | ||
| 666 | }; | ||
| 667 | |||
| 668 | static struct miscdevice mpc52xx_wdt_miscdev = { | ||
| 669 | .minor = WATCHDOG_MINOR, | ||
| 670 | .name = "watchdog", | ||
| 671 | .fops = &mpc52xx_wdt_fops, | ||
| 672 | }; | ||
| 673 | |||
| 674 | static int __devinit mpc52xx_gpt_wdt_init(void) | ||
| 675 | { | ||
| 676 | int err; | ||
| 677 | |||
| 678 | /* try to register the watchdog misc device */ | ||
| 679 | err = misc_register(&mpc52xx_wdt_miscdev); | ||
| 680 | if (err) | ||
| 681 | pr_err("%s: cannot register watchdog device\n", WDT_IDENTITY); | ||
| 682 | else | ||
| 683 | pr_info("%s: watchdog device registered\n", WDT_IDENTITY); | ||
| 684 | return err; | ||
| 685 | } | ||
| 686 | |||
| 687 | static int mpc52xx_gpt_wdt_setup(struct mpc52xx_gpt_priv *gpt, | ||
| 688 | const u32 *period) | ||
| 689 | { | ||
| 690 | u64 real_timeout; | ||
| 691 | |||
| 692 | /* remember the gpt for the wdt operation */ | ||
| 693 | mpc52xx_gpt_wdt = gpt; | ||
| 694 | |||
| 695 | /* configure the wdt if the device tree contained a timeout */ | ||
| 696 | if (!period || *period == 0) | ||
| 697 | return 0; | ||
| 698 | |||
| 699 | real_timeout = (u64) *period * 1000000000ULL; | ||
| 700 | if (mpc52xx_gpt_do_start(gpt, real_timeout, 0, 1)) | ||
| 701 | dev_warn(gpt->dev, "starting as wdt failed\n"); | ||
| 702 | else | ||
| 703 | dev_info(gpt->dev, "watchdog set to %us timeout\n", *period); | ||
| 704 | return 0; | ||
| 705 | } | ||
| 706 | |||
| 707 | #else | ||
| 708 | |||
| 709 | static int __devinit mpc52xx_gpt_wdt_init(void) | ||
| 710 | { | ||
| 711 | return 0; | ||
| 712 | } | ||
| 713 | |||
| 714 | #define mpc52xx_gpt_wdt_setup(x, y) (0) | ||
| 715 | |||
| 716 | #endif /* CONFIG_MPC5200_WDT */ | ||
| 717 | |||
| 338 | /* --------------------------------------------------------------------- | 718 | /* --------------------------------------------------------------------- |
| 339 | * of_platform bus binding code | 719 | * of_platform bus binding code |
| 340 | */ | 720 | */ |
| @@ -349,6 +729,7 @@ static int __devinit mpc52xx_gpt_probe(struct of_device *ofdev, | |||
| 349 | 729 | ||
| 350 | spin_lock_init(&gpt->lock); | 730 | spin_lock_init(&gpt->lock); |
| 351 | gpt->dev = &ofdev->dev; | 731 | gpt->dev = &ofdev->dev; |
| 732 | gpt->ipb_freq = mpc5xxx_get_bus_frequency(ofdev->node); | ||
| 352 | gpt->regs = of_iomap(ofdev->node, 0); | 733 | gpt->regs = of_iomap(ofdev->node, 0); |
| 353 | if (!gpt->regs) { | 734 | if (!gpt->regs) { |
| 354 | kfree(gpt); | 735 | kfree(gpt); |
| @@ -360,6 +741,26 @@ static int __devinit mpc52xx_gpt_probe(struct of_device *ofdev, | |||
| 360 | mpc52xx_gpt_gpio_setup(gpt, ofdev->node); | 741 | mpc52xx_gpt_gpio_setup(gpt, ofdev->node); |
| 361 | mpc52xx_gpt_irq_setup(gpt, ofdev->node); | 742 | mpc52xx_gpt_irq_setup(gpt, ofdev->node); |
| 362 | 743 | ||
| 744 | mutex_lock(&mpc52xx_gpt_list_mutex); | ||
| 745 | list_add(&gpt->list, &mpc52xx_gpt_list); | ||
| 746 | mutex_unlock(&mpc52xx_gpt_list_mutex); | ||
| 747 | |||
| 748 | /* check if this device could be a watchdog */ | ||
| 749 | if (of_get_property(ofdev->node, "fsl,has-wdt", NULL) || | ||
| 750 | of_get_property(ofdev->node, "has-wdt", NULL)) { | ||
| 751 | const u32 *on_boot_wdt; | ||
| 752 | |||
| 753 | gpt->wdt_mode = MPC52xx_GPT_CAN_WDT; | ||
| 754 | on_boot_wdt = of_get_property(ofdev->node, "fsl,wdt-on-boot", | ||
| 755 | NULL); | ||
| 756 | if (on_boot_wdt) { | ||
| 757 | dev_info(gpt->dev, "used as watchdog\n"); | ||
| 758 | gpt->wdt_mode |= MPC52xx_GPT_IS_WDT; | ||
| 759 | } else | ||
| 760 | dev_info(gpt->dev, "can function as watchdog\n"); | ||
| 761 | mpc52xx_gpt_wdt_setup(gpt, on_boot_wdt); | ||
| 762 | } | ||
| 763 | |||
| 363 | return 0; | 764 | return 0; |
| 364 | } | 765 | } |
| 365 | 766 | ||
| @@ -394,3 +795,4 @@ static int __init mpc52xx_gpt_init(void) | |||
| 394 | 795 | ||
| 395 | /* Make sure GPIOs and IRQs get set up before anyone tries to use them */ | 796 | /* Make sure GPIOs and IRQs get set up before anyone tries to use them */ |
| 396 | subsys_initcall(mpc52xx_gpt_init); | 797 | subsys_initcall(mpc52xx_gpt_init); |
| 798 | device_initcall(mpc52xx_gpt_wdt_init); | ||
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c new file mode 100644 index 000000000000..929d017535a3 --- /dev/null +++ b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c | |||
| @@ -0,0 +1,560 @@ | |||
| 1 | /* | ||
| 2 | * LocalPlus Bus FIFO driver for the Freescale MPC52xx. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Secret Lab Technologies Ltd. | ||
| 5 | * | ||
| 6 | * This file is released under the GPLv2 | ||
| 7 | * | ||
| 8 | * Todo: | ||
| 9 | * - Add support for multiple requests to be queued. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/interrupt.h> | ||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/of.h> | ||
| 15 | #include <linux/of_platform.h> | ||
| 16 | #include <linux/spinlock.h> | ||
| 17 | #include <asm/io.h> | ||
| 18 | #include <asm/prom.h> | ||
| 19 | #include <asm/mpc52xx.h> | ||
| 20 | #include <asm/time.h> | ||
| 21 | |||
| 22 | #include <sysdev/bestcomm/bestcomm.h> | ||
| 23 | #include <sysdev/bestcomm/bestcomm_priv.h> | ||
| 24 | #include <sysdev/bestcomm/gen_bd.h> | ||
| 25 | |||
| 26 | MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>"); | ||
| 27 | MODULE_DESCRIPTION("MPC5200 LocalPlus FIFO device driver"); | ||
| 28 | MODULE_LICENSE("GPL"); | ||
| 29 | |||
| 30 | #define LPBFIFO_REG_PACKET_SIZE (0x00) | ||
| 31 | #define LPBFIFO_REG_START_ADDRESS (0x04) | ||
| 32 | #define LPBFIFO_REG_CONTROL (0x08) | ||
| 33 | #define LPBFIFO_REG_ENABLE (0x0C) | ||
| 34 | #define LPBFIFO_REG_BYTES_DONE_STATUS (0x14) | ||
| 35 | #define LPBFIFO_REG_FIFO_DATA (0x40) | ||
| 36 | #define LPBFIFO_REG_FIFO_STATUS (0x44) | ||
| 37 | #define LPBFIFO_REG_FIFO_CONTROL (0x48) | ||
| 38 | #define LPBFIFO_REG_FIFO_ALARM (0x4C) | ||
| 39 | |||
| 40 | struct mpc52xx_lpbfifo { | ||
| 41 | struct device *dev; | ||
| 42 | phys_addr_t regs_phys; | ||
| 43 | void __iomem *regs; | ||
| 44 | int irq; | ||
| 45 | spinlock_t lock; | ||
| 46 | |||
| 47 | struct bcom_task *bcom_tx_task; | ||
| 48 | struct bcom_task *bcom_rx_task; | ||
| 49 | struct bcom_task *bcom_cur_task; | ||
| 50 | |||
| 51 | /* Current state data */ | ||
| 52 | struct mpc52xx_lpbfifo_request *req; | ||
| 53 | int dma_irqs_enabled; | ||
| 54 | }; | ||
| 55 | |||
| 56 | /* The MPC5200 has only one fifo, so only need one instance structure */ | ||
| 57 | static struct mpc52xx_lpbfifo lpbfifo; | ||
| 58 | |||
| 59 | /** | ||
| 60 | * mpc52xx_lpbfifo_kick - Trigger the next block of data to be transfered | ||
| 61 | */ | ||
| 62 | static void mpc52xx_lpbfifo_kick(struct mpc52xx_lpbfifo_request *req) | ||
| 63 | { | ||
| 64 | size_t transfer_size = req->size - req->pos; | ||
| 65 | struct bcom_bd *bd; | ||
| 66 | void __iomem *reg; | ||
| 67 | u32 *data; | ||
| 68 | int i; | ||
| 69 | int bit_fields; | ||
| 70 | int dma = !(req->flags & MPC52XX_LPBFIFO_FLAG_NO_DMA); | ||
| 71 | int write = req->flags & MPC52XX_LPBFIFO_FLAG_WRITE; | ||
| 72 | int poll_dma = req->flags & MPC52XX_LPBFIFO_FLAG_POLL_DMA; | ||
| 73 | |||
| 74 | /* Set and clear the reset bits; is good practice in User Manual */ | ||
| 75 | out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000); | ||
| 76 | |||
| 77 | /* set master enable bit */ | ||
| 78 | out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x00000001); | ||
| 79 | if (!dma) { | ||
| 80 | /* While the FIFO can be setup for transfer sizes as large as | ||
| 81 | * 16M-1, the FIFO itself is only 512 bytes deep and it does | ||
| 82 | * not generate interrupts for FIFO full events (only transfer | ||
| 83 | * complete will raise an IRQ). Therefore when not using | ||
| 84 | * Bestcomm to drive the FIFO it needs to either be polled, or | ||
| 85 | * transfers need to constrained to the size of the fifo. | ||
| 86 | * | ||
| 87 | * This driver restricts the size of the transfer | ||
| 88 | */ | ||
| 89 | if (transfer_size > 512) | ||
| 90 | transfer_size = 512; | ||
| 91 | |||
| 92 | /* Load the FIFO with data */ | ||
| 93 | if (write) { | ||
| 94 | reg = lpbfifo.regs + LPBFIFO_REG_FIFO_DATA; | ||
| 95 | data = req->data + req->pos; | ||
| 96 | for (i = 0; i < transfer_size; i += 4) | ||
| 97 | out_be32(reg, *data++); | ||
| 98 | } | ||
| 99 | |||
| 100 | /* Unmask both error and completion irqs */ | ||
| 101 | out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x00000301); | ||
| 102 | } else { | ||
| 103 | /* Choose the correct direction | ||
| 104 | * | ||
| 105 | * Configure the watermarks so DMA will always complete correctly. | ||
| 106 | * It may be worth experimenting with the ALARM value to see if | ||
| 107 | * there is a performance impacit. However, if it is wrong there | ||
| 108 | * is a risk of DMA not transferring the last chunk of data | ||
| 109 | */ | ||
| 110 | if (write) { | ||
| 111 | out_be32(lpbfifo.regs + LPBFIFO_REG_FIFO_ALARM, 0x1e4); | ||
| 112 | out_8(lpbfifo.regs + LPBFIFO_REG_FIFO_CONTROL, 7); | ||
| 113 | lpbfifo.bcom_cur_task = lpbfifo.bcom_tx_task; | ||
| 114 | } else { | ||
| 115 | out_be32(lpbfifo.regs + LPBFIFO_REG_FIFO_ALARM, 0x1ff); | ||
| 116 | out_8(lpbfifo.regs + LPBFIFO_REG_FIFO_CONTROL, 0); | ||
| 117 | lpbfifo.bcom_cur_task = lpbfifo.bcom_rx_task; | ||
| 118 | |||
| 119 | if (poll_dma) { | ||
| 120 | if (lpbfifo.dma_irqs_enabled) { | ||
| 121 | disable_irq(bcom_get_task_irq(lpbfifo.bcom_rx_task)); | ||
| 122 | lpbfifo.dma_irqs_enabled = 0; | ||
| 123 | } | ||
| 124 | } else { | ||
| 125 | if (!lpbfifo.dma_irqs_enabled) { | ||
| 126 | enable_irq(bcom_get_task_irq(lpbfifo.bcom_rx_task)); | ||
| 127 | lpbfifo.dma_irqs_enabled = 1; | ||
| 128 | } | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | bd = bcom_prepare_next_buffer(lpbfifo.bcom_cur_task); | ||
| 133 | bd->status = transfer_size; | ||
| 134 | if (!write) { | ||
| 135 | /* | ||
| 136 | * In the DMA read case, the DMA doesn't complete, | ||
| 137 | * possibly due to incorrect watermarks in the ALARM | ||
| 138 | * and CONTROL regs. For now instead of trying to | ||
| 139 | * determine the right watermarks that will make this | ||
| 140 | * work, just increase the number of bytes the FIFO is | ||
| 141 | * expecting. | ||
| 142 | * | ||
| 143 | * When submitting another operation, the FIFO will get | ||
| 144 | * reset, so the condition of the FIFO waiting for a | ||
| 145 | * non-existent 4 bytes will get cleared. | ||
| 146 | */ | ||
| 147 | transfer_size += 4; /* BLECH! */ | ||
| 148 | } | ||
| 149 | bd->data[0] = req->data_phys + req->pos; | ||
| 150 | bcom_submit_next_buffer(lpbfifo.bcom_cur_task, NULL); | ||
| 151 | |||
| 152 | /* error irq & master enabled bit */ | ||
| 153 | bit_fields = 0x00000201; | ||
| 154 | |||
| 155 | /* Unmask irqs */ | ||
| 156 | if (write && (!poll_dma)) | ||
| 157 | bit_fields |= 0x00000100; /* completion irq too */ | ||
| 158 | out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, bit_fields); | ||
| 159 | } | ||
| 160 | |||
| 161 | /* Set transfer size, width, chip select and READ mode */ | ||
| 162 | out_be32(lpbfifo.regs + LPBFIFO_REG_START_ADDRESS, | ||
| 163 | req->offset + req->pos); | ||
| 164 | out_be32(lpbfifo.regs + LPBFIFO_REG_PACKET_SIZE, transfer_size); | ||
| 165 | |||
| 166 | bit_fields = req->cs << 24 | 0x000008; | ||
| 167 | if (!write) | ||
| 168 | bit_fields |= 0x010000; /* read mode */ | ||
| 169 | out_be32(lpbfifo.regs + LPBFIFO_REG_CONTROL, bit_fields); | ||
| 170 | |||
| 171 | /* Kick it off */ | ||
| 172 | out_8(lpbfifo.regs + LPBFIFO_REG_PACKET_SIZE, 0x01); | ||
| 173 | if (dma) | ||
| 174 | bcom_enable(lpbfifo.bcom_cur_task); | ||
| 175 | } | ||
| 176 | |||
| 177 | /** | ||
| 178 | * mpc52xx_lpbfifo_irq - IRQ handler for LPB FIFO | ||
| 179 | * | ||
| 180 | * On transmit, the dma completion irq triggers before the fifo completion | ||
| 181 | * triggers. Handle the dma completion here instead of the LPB FIFO Bestcomm | ||
| 182 | * task completion irq becuase everyting is not really done until the LPB FIFO | ||
| 183 | * completion irq triggers. | ||
| 184 | * | ||
| 185 | * In other words: | ||
| 186 | * For DMA, on receive, the "Fat Lady" is the bestcom completion irq. on | ||
| 187 | * transmit, the fifo completion irq is the "Fat Lady". The opera (or in this | ||
| 188 | * case the DMA/FIFO operation) is not finished until the "Fat Lady" sings. | ||
| 189 | * | ||
| 190 | * Reasons for entering this routine: | ||
| 191 | * 1) PIO mode rx and tx completion irq | ||
| 192 | * 2) DMA interrupt mode tx completion irq | ||
| 193 | * 3) DMA polled mode tx | ||
| 194 | * | ||
| 195 | * Exit conditions: | ||
| 196 | * 1) Transfer aborted | ||
| 197 | * 2) FIFO complete without DMA; more data to do | ||
| 198 | * 3) FIFO complete without DMA; all data transfered | ||
| 199 | * 4) FIFO complete using DMA | ||
| 200 | * | ||
| 201 | * Condition 1 can occur regardless of whether or not DMA is used. | ||
| 202 | * It requires executing the callback to report the error and exiting | ||
| 203 | * immediately. | ||
| 204 | * | ||
| 205 | * Condition 2 requires programming the FIFO with the next block of data | ||
| 206 | * | ||
| 207 | * Condition 3 requires executing the callback to report completion | ||
| 208 | * | ||
| 209 | * Condition 4 means the same as 3, except that we also retrieve the bcom | ||
| 210 | * buffer so DMA doesn't get clogged up. | ||
| 211 | * | ||
| 212 | * To make things trickier, the spinlock must be dropped before | ||
| 213 | * executing the callback, otherwise we could end up with a deadlock | ||
| 214 | * or nested spinlock condition. The out path is non-trivial, so | ||
| 215 | * extra fiddling is done to make sure all paths lead to the same | ||
| 216 | * outbound code. | ||
| 217 | */ | ||
| 218 | static irqreturn_t mpc52xx_lpbfifo_irq(int irq, void *dev_id) | ||
| 219 | { | ||
| 220 | struct mpc52xx_lpbfifo_request *req; | ||
| 221 | u32 status = in_8(lpbfifo.regs + LPBFIFO_REG_BYTES_DONE_STATUS); | ||
| 222 | void __iomem *reg; | ||
| 223 | u32 *data; | ||
| 224 | int count, i; | ||
| 225 | int do_callback = 0; | ||
| 226 | u32 ts; | ||
| 227 | unsigned long flags; | ||
| 228 | int dma, write, poll_dma; | ||
| 229 | |||
| 230 | spin_lock_irqsave(&lpbfifo.lock, flags); | ||
| 231 | ts = get_tbl(); | ||
| 232 | |||
| 233 | req = lpbfifo.req; | ||
| 234 | if (!req) { | ||
| 235 | spin_unlock_irqrestore(&lpbfifo.lock, flags); | ||
| 236 | pr_err("bogus LPBFIFO IRQ\n"); | ||
| 237 | return IRQ_HANDLED; | ||
| 238 | } | ||
| 239 | |||
| 240 | dma = !(req->flags & MPC52XX_LPBFIFO_FLAG_NO_DMA); | ||
| 241 | write = req->flags & MPC52XX_LPBFIFO_FLAG_WRITE; | ||
| 242 | poll_dma = req->flags & MPC52XX_LPBFIFO_FLAG_POLL_DMA; | ||
| 243 | |||
| 244 | if (dma && !write) { | ||
| 245 | spin_unlock_irqrestore(&lpbfifo.lock, flags); | ||
| 246 | pr_err("bogus LPBFIFO IRQ (dma and not writting)\n"); | ||
| 247 | return IRQ_HANDLED; | ||
| 248 | } | ||
| 249 | |||
| 250 | if ((status & 0x01) == 0) { | ||
| 251 | goto out; | ||
| 252 | } | ||
| 253 | |||
| 254 | /* check abort bit */ | ||
| 255 | if (status & 0x10) { | ||
| 256 | out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000); | ||
| 257 | do_callback = 1; | ||
| 258 | goto out; | ||
| 259 | } | ||
| 260 | |||
| 261 | /* Read result from hardware */ | ||
| 262 | count = in_be32(lpbfifo.regs + LPBFIFO_REG_BYTES_DONE_STATUS); | ||
| 263 | count &= 0x00ffffff; | ||
| 264 | |||
| 265 | if (!dma && !write) { | ||
| 266 | /* copy the data out of the FIFO */ | ||
| 267 | reg = lpbfifo.regs + LPBFIFO_REG_FIFO_DATA; | ||
| 268 | data = req->data + req->pos; | ||
| 269 | for (i = 0; i < count; i += 4) | ||
| 270 | *data++ = in_be32(reg); | ||
| 271 | } | ||
| 272 | |||
| 273 | /* Update transfer position and count */ | ||
| 274 | req->pos += count; | ||
| 275 | |||
| 276 | /* Decide what to do next */ | ||
| 277 | if (req->size - req->pos) | ||
| 278 | mpc52xx_lpbfifo_kick(req); /* more work to do */ | ||
| 279 | else | ||
| 280 | do_callback = 1; | ||
| 281 | |||
| 282 | out: | ||
| 283 | /* Clear the IRQ */ | ||
| 284 | out_8(lpbfifo.regs + LPBFIFO_REG_BYTES_DONE_STATUS, 0x01); | ||
| 285 | |||
| 286 | if (dma && (status & 0x11)) { | ||
| 287 | /* | ||
| 288 | * Count the DMA as complete only when the FIFO completion | ||
| 289 | * status or abort bits are set. | ||
| 290 | * | ||
| 291 | * (status & 0x01) should always be the case except sometimes | ||
| 292 | * when using polled DMA. | ||
| 293 | * | ||
| 294 | * (status & 0x10) {transfer aborted}: This case needs more | ||
| 295 | * testing. | ||
| 296 | */ | ||
| 297 | bcom_retrieve_buffer(lpbfifo.bcom_cur_task, &status, NULL); | ||
| 298 | } | ||
| 299 | req->last_byte = ((u8 *)req->data)[req->size - 1]; | ||
| 300 | |||
| 301 | /* When the do_callback flag is set; it means the transfer is finished | ||
| 302 | * so set the FIFO as idle */ | ||
| 303 | if (do_callback) | ||
| 304 | lpbfifo.req = NULL; | ||
| 305 | |||
| 306 | if (irq != 0) /* don't increment on polled case */ | ||
| 307 | req->irq_count++; | ||
| 308 | |||
| 309 | req->irq_ticks += get_tbl() - ts; | ||
| 310 | spin_unlock_irqrestore(&lpbfifo.lock, flags); | ||
| 311 | |||
| 312 | /* Spinlock is released; it is now safe to call the callback */ | ||
| 313 | if (do_callback && req->callback) | ||
| 314 | req->callback(req); | ||
| 315 | |||
| 316 | return IRQ_HANDLED; | ||
| 317 | } | ||
| 318 | |||
| 319 | /** | ||
| 320 | * mpc52xx_lpbfifo_bcom_irq - IRQ handler for LPB FIFO Bestcomm task | ||
| 321 | * | ||
| 322 | * Only used when receiving data. | ||
| 323 | */ | ||
| 324 | static irqreturn_t mpc52xx_lpbfifo_bcom_irq(int irq, void *dev_id) | ||
| 325 | { | ||
| 326 | struct mpc52xx_lpbfifo_request *req; | ||
| 327 | unsigned long flags; | ||
| 328 | u32 status; | ||
| 329 | u32 ts; | ||
| 330 | |||
| 331 | spin_lock_irqsave(&lpbfifo.lock, flags); | ||
| 332 | ts = get_tbl(); | ||
| 333 | |||
| 334 | req = lpbfifo.req; | ||
| 335 | if (!req || (req->flags & MPC52XX_LPBFIFO_FLAG_NO_DMA)) { | ||
| 336 | spin_unlock_irqrestore(&lpbfifo.lock, flags); | ||
| 337 | return IRQ_HANDLED; | ||
| 338 | } | ||
| 339 | |||
| 340 | if (irq != 0) /* don't increment on polled case */ | ||
| 341 | req->irq_count++; | ||
| 342 | |||
| 343 | if (!bcom_buffer_done(lpbfifo.bcom_cur_task)) { | ||
| 344 | spin_unlock_irqrestore(&lpbfifo.lock, flags); | ||
| 345 | |||
| 346 | req->buffer_not_done_cnt++; | ||
| 347 | if ((req->buffer_not_done_cnt % 1000) == 0) | ||
| 348 | pr_err("transfer stalled\n"); | ||
| 349 | |||
| 350 | return IRQ_HANDLED; | ||
| 351 | } | ||
| 352 | |||
| 353 | bcom_retrieve_buffer(lpbfifo.bcom_cur_task, &status, NULL); | ||
| 354 | |||
| 355 | req->last_byte = ((u8 *)req->data)[req->size - 1]; | ||
| 356 | |||
| 357 | req->pos = status & 0x00ffffff; | ||
| 358 | |||
| 359 | /* Mark the FIFO as idle */ | ||
| 360 | lpbfifo.req = NULL; | ||
| 361 | |||
| 362 | /* Release the lock before calling out to the callback. */ | ||
| 363 | req->irq_ticks += get_tbl() - ts; | ||
| 364 | spin_unlock_irqrestore(&lpbfifo.lock, flags); | ||
| 365 | |||
| 366 | if (req->callback) | ||
| 367 | req->callback(req); | ||
| 368 | |||
| 369 | return IRQ_HANDLED; | ||
| 370 | } | ||
| 371 | |||
| 372 | /** | ||
| 373 | * mpc52xx_lpbfifo_bcom_poll - Poll for DMA completion | ||
| 374 | */ | ||
| 375 | void mpc52xx_lpbfifo_poll(void) | ||
| 376 | { | ||
| 377 | struct mpc52xx_lpbfifo_request *req = lpbfifo.req; | ||
| 378 | int dma = !(req->flags & MPC52XX_LPBFIFO_FLAG_NO_DMA); | ||
| 379 | int write = req->flags & MPC52XX_LPBFIFO_FLAG_WRITE; | ||
| 380 | |||
| 381 | /* | ||
| 382 | * For more information, see comments on the "Fat Lady" | ||
| 383 | */ | ||
| 384 | if (dma && write) | ||
| 385 | mpc52xx_lpbfifo_irq(0, NULL); | ||
| 386 | else | ||
| 387 | mpc52xx_lpbfifo_bcom_irq(0, NULL); | ||
| 388 | } | ||
| 389 | EXPORT_SYMBOL(mpc52xx_lpbfifo_poll); | ||
| 390 | |||
| 391 | /** | ||
| 392 | * mpc52xx_lpbfifo_submit - Submit an LPB FIFO transfer request. | ||
| 393 | * @req: Pointer to request structure | ||
| 394 | */ | ||
| 395 | int mpc52xx_lpbfifo_submit(struct mpc52xx_lpbfifo_request *req) | ||
| 396 | { | ||
| 397 | unsigned long flags; | ||
| 398 | |||
| 399 | if (!lpbfifo.regs) | ||
| 400 | return -ENODEV; | ||
| 401 | |||
| 402 | spin_lock_irqsave(&lpbfifo.lock, flags); | ||
| 403 | |||
| 404 | /* If the req pointer is already set, then a transfer is in progress */ | ||
| 405 | if (lpbfifo.req) { | ||
| 406 | spin_unlock_irqrestore(&lpbfifo.lock, flags); | ||
| 407 | return -EBUSY; | ||
| 408 | } | ||
| 409 | |||
| 410 | /* Setup the transfer */ | ||
| 411 | lpbfifo.req = req; | ||
| 412 | req->irq_count = 0; | ||
| 413 | req->irq_ticks = 0; | ||
| 414 | req->buffer_not_done_cnt = 0; | ||
| 415 | req->pos = 0; | ||
| 416 | |||
| 417 | mpc52xx_lpbfifo_kick(req); | ||
| 418 | spin_unlock_irqrestore(&lpbfifo.lock, flags); | ||
| 419 | return 0; | ||
| 420 | } | ||
| 421 | EXPORT_SYMBOL(mpc52xx_lpbfifo_submit); | ||
| 422 | |||
| 423 | void mpc52xx_lpbfifo_abort(struct mpc52xx_lpbfifo_request *req) | ||
| 424 | { | ||
| 425 | unsigned long flags; | ||
| 426 | |||
| 427 | spin_lock_irqsave(&lpbfifo.lock, flags); | ||
| 428 | if (lpbfifo.req == req) { | ||
| 429 | /* Put it into reset and clear the state */ | ||
| 430 | bcom_gen_bd_rx_reset(lpbfifo.bcom_rx_task); | ||
| 431 | bcom_gen_bd_tx_reset(lpbfifo.bcom_tx_task); | ||
| 432 | out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000); | ||
| 433 | lpbfifo.req = NULL; | ||
| 434 | } | ||
| 435 | spin_unlock_irqrestore(&lpbfifo.lock, flags); | ||
| 436 | } | ||
| 437 | EXPORT_SYMBOL(mpc52xx_lpbfifo_abort); | ||
| 438 | |||
| 439 | static int __devinit | ||
| 440 | mpc52xx_lpbfifo_probe(struct of_device *op, const struct of_device_id *match) | ||
| 441 | { | ||
| 442 | struct resource res; | ||
| 443 | int rc = -ENOMEM; | ||
| 444 | |||
| 445 | if (lpbfifo.dev != NULL) | ||
| 446 | return -ENOSPC; | ||
| 447 | |||
| 448 | lpbfifo.irq = irq_of_parse_and_map(op->node, 0); | ||
| 449 | if (!lpbfifo.irq) | ||
| 450 | return -ENODEV; | ||
| 451 | |||
| 452 | if (of_address_to_resource(op->node, 0, &res)) | ||
| 453 | return -ENODEV; | ||
| 454 | lpbfifo.regs_phys = res.start; | ||
| 455 | lpbfifo.regs = of_iomap(op->node, 0); | ||
| 456 | if (!lpbfifo.regs) | ||
| 457 | return -ENOMEM; | ||
| 458 | |||
| 459 | spin_lock_init(&lpbfifo.lock); | ||
| 460 | |||
| 461 | /* Put FIFO into reset */ | ||
| 462 | out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000); | ||
| 463 | |||
| 464 | /* Register the interrupt handler */ | ||
| 465 | rc = request_irq(lpbfifo.irq, mpc52xx_lpbfifo_irq, 0, | ||
| 466 | "mpc52xx-lpbfifo", &lpbfifo); | ||
| 467 | if (rc) | ||
| 468 | goto err_irq; | ||
| 469 | |||
| 470 | /* Request the Bestcomm receive (fifo --> memory) task and IRQ */ | ||
| 471 | lpbfifo.bcom_rx_task = | ||
| 472 | bcom_gen_bd_rx_init(2, res.start + LPBFIFO_REG_FIFO_DATA, | ||
| 473 | BCOM_INITIATOR_SCLPC, BCOM_IPR_SCLPC, | ||
| 474 | 16*1024*1024); | ||
| 475 | if (!lpbfifo.bcom_rx_task) | ||
| 476 | goto err_bcom_rx; | ||
| 477 | |||
| 478 | rc = request_irq(bcom_get_task_irq(lpbfifo.bcom_rx_task), | ||
| 479 | mpc52xx_lpbfifo_bcom_irq, 0, | ||
| 480 | "mpc52xx-lpbfifo-rx", &lpbfifo); | ||
| 481 | if (rc) | ||
| 482 | goto err_bcom_rx_irq; | ||
| 483 | |||
| 484 | /* Request the Bestcomm transmit (memory --> fifo) task and IRQ */ | ||
| 485 | lpbfifo.bcom_tx_task = | ||
| 486 | bcom_gen_bd_tx_init(2, res.start + LPBFIFO_REG_FIFO_DATA, | ||
| 487 | BCOM_INITIATOR_SCLPC, BCOM_IPR_SCLPC); | ||
| 488 | if (!lpbfifo.bcom_tx_task) | ||
| 489 | goto err_bcom_tx; | ||
| 490 | |||
| 491 | lpbfifo.dev = &op->dev; | ||
| 492 | return 0; | ||
| 493 | |||
| 494 | err_bcom_tx: | ||
| 495 | free_irq(bcom_get_task_irq(lpbfifo.bcom_rx_task), &lpbfifo); | ||
| 496 | err_bcom_rx_irq: | ||
| 497 | bcom_gen_bd_rx_release(lpbfifo.bcom_rx_task); | ||
| 498 | err_bcom_rx: | ||
| 499 | err_irq: | ||
| 500 | iounmap(lpbfifo.regs); | ||
| 501 | lpbfifo.regs = NULL; | ||
| 502 | |||
| 503 | dev_err(&op->dev, "mpc52xx_lpbfifo_probe() failed\n"); | ||
| 504 | return -ENODEV; | ||
| 505 | } | ||
| 506 | |||
| 507 | |||
| 508 | static int __devexit mpc52xx_lpbfifo_remove(struct of_device *op) | ||
| 509 | { | ||
| 510 | if (lpbfifo.dev != &op->dev) | ||
| 511 | return 0; | ||
| 512 | |||
| 513 | /* Put FIFO in reset */ | ||
| 514 | out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000); | ||
| 515 | |||
| 516 | /* Release the bestcomm transmit task */ | ||
| 517 | free_irq(bcom_get_task_irq(lpbfifo.bcom_tx_task), &lpbfifo); | ||
| 518 | bcom_gen_bd_tx_release(lpbfifo.bcom_tx_task); | ||
| 519 | |||
| 520 | /* Release the bestcomm receive task */ | ||
| 521 | free_irq(bcom_get_task_irq(lpbfifo.bcom_rx_task), &lpbfifo); | ||
| 522 | bcom_gen_bd_rx_release(lpbfifo.bcom_rx_task); | ||
| 523 | |||
| 524 | free_irq(lpbfifo.irq, &lpbfifo); | ||
| 525 | iounmap(lpbfifo.regs); | ||
| 526 | lpbfifo.regs = NULL; | ||
| 527 | lpbfifo.dev = NULL; | ||
| 528 | |||
| 529 | return 0; | ||
| 530 | } | ||
| 531 | |||
| 532 | static struct of_device_id mpc52xx_lpbfifo_match[] __devinitconst = { | ||
| 533 | { .compatible = "fsl,mpc5200-lpbfifo", }, | ||
| 534 | {}, | ||
| 535 | }; | ||
| 536 | |||
| 537 | static struct of_platform_driver mpc52xx_lpbfifo_driver = { | ||
| 538 | .owner = THIS_MODULE, | ||
| 539 | .name = "mpc52xx-lpbfifo", | ||
| 540 | .match_table = mpc52xx_lpbfifo_match, | ||
| 541 | .probe = mpc52xx_lpbfifo_probe, | ||
| 542 | .remove = __devexit_p(mpc52xx_lpbfifo_remove), | ||
| 543 | }; | ||
| 544 | |||
| 545 | /*********************************************************************** | ||
| 546 | * Module init/exit | ||
| 547 | */ | ||
| 548 | static int __init mpc52xx_lpbfifo_init(void) | ||
| 549 | { | ||
| 550 | pr_debug("Registering LocalPlus bus FIFO driver\n"); | ||
| 551 | return of_register_platform_driver(&mpc52xx_lpbfifo_driver); | ||
| 552 | } | ||
| 553 | module_init(mpc52xx_lpbfifo_init); | ||
| 554 | |||
| 555 | static void __exit mpc52xx_lpbfifo_exit(void) | ||
| 556 | { | ||
| 557 | pr_debug("Unregistering LocalPlus bus FIFO driver\n"); | ||
| 558 | of_unregister_platform_driver(&mpc52xx_lpbfifo_driver); | ||
| 559 | } | ||
| 560 | module_exit(mpc52xx_lpbfifo_exit); | ||
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c index 480f806fd0a9..4bf4bf7b063e 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c | |||
| @@ -220,7 +220,7 @@ static int mpc52xx_extirq_set_type(unsigned int virq, unsigned int flow_type) | |||
| 220 | } | 220 | } |
| 221 | 221 | ||
| 222 | static struct irq_chip mpc52xx_extirq_irqchip = { | 222 | static struct irq_chip mpc52xx_extirq_irqchip = { |
| 223 | .typename = "MPC52xx External", | 223 | .name = "MPC52xx External", |
| 224 | .mask = mpc52xx_extirq_mask, | 224 | .mask = mpc52xx_extirq_mask, |
| 225 | .unmask = mpc52xx_extirq_unmask, | 225 | .unmask = mpc52xx_extirq_unmask, |
| 226 | .ack = mpc52xx_extirq_ack, | 226 | .ack = mpc52xx_extirq_ack, |
| @@ -258,7 +258,7 @@ static void mpc52xx_main_unmask(unsigned int virq) | |||
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | static struct irq_chip mpc52xx_main_irqchip = { | 260 | static struct irq_chip mpc52xx_main_irqchip = { |
| 261 | .typename = "MPC52xx Main", | 261 | .name = "MPC52xx Main", |
| 262 | .mask = mpc52xx_main_mask, | 262 | .mask = mpc52xx_main_mask, |
| 263 | .mask_ack = mpc52xx_main_mask, | 263 | .mask_ack = mpc52xx_main_mask, |
| 264 | .unmask = mpc52xx_main_unmask, | 264 | .unmask = mpc52xx_main_unmask, |
| @@ -291,7 +291,7 @@ static void mpc52xx_periph_unmask(unsigned int virq) | |||
| 291 | } | 291 | } |
| 292 | 292 | ||
| 293 | static struct irq_chip mpc52xx_periph_irqchip = { | 293 | static struct irq_chip mpc52xx_periph_irqchip = { |
| 294 | .typename = "MPC52xx Peripherals", | 294 | .name = "MPC52xx Peripherals", |
| 295 | .mask = mpc52xx_periph_mask, | 295 | .mask = mpc52xx_periph_mask, |
| 296 | .mask_ack = mpc52xx_periph_mask, | 296 | .mask_ack = mpc52xx_periph_mask, |
| 297 | .unmask = mpc52xx_periph_unmask, | 297 | .unmask = mpc52xx_periph_unmask, |
| @@ -335,7 +335,7 @@ static void mpc52xx_sdma_ack(unsigned int virq) | |||
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | static struct irq_chip mpc52xx_sdma_irqchip = { | 337 | static struct irq_chip mpc52xx_sdma_irqchip = { |
| 338 | .typename = "MPC52xx SDMA", | 338 | .name = "MPC52xx SDMA", |
| 339 | .mask = mpc52xx_sdma_mask, | 339 | .mask = mpc52xx_sdma_mask, |
| 340 | .unmask = mpc52xx_sdma_unmask, | 340 | .unmask = mpc52xx_sdma_unmask, |
| 341 | .ack = mpc52xx_sdma_ack, | 341 | .ack = mpc52xx_sdma_ack, |
| @@ -355,7 +355,7 @@ static int mpc52xx_is_extirq(int l1, int l2) | |||
| 355 | * mpc52xx_irqhost_xlate - translate virq# from device tree interrupts property | 355 | * mpc52xx_irqhost_xlate - translate virq# from device tree interrupts property |
| 356 | */ | 356 | */ |
| 357 | static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct, | 357 | static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct, |
| 358 | u32 *intspec, unsigned int intsize, | 358 | const u32 *intspec, unsigned int intsize, |
| 359 | irq_hw_number_t *out_hwirq, | 359 | irq_hw_number_t *out_hwirq, |
| 360 | unsigned int *out_flags) | 360 | unsigned int *out_flags) |
| 361 | { | 361 | { |
diff --git a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c index 7ee979f323d1..9d962d7c72c1 100644 --- a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c +++ b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c | |||
| @@ -69,7 +69,6 @@ static void pq2ads_pci_unmask_irq(unsigned int virq) | |||
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | static struct irq_chip pq2ads_pci_ic = { | 71 | static struct irq_chip pq2ads_pci_ic = { |
| 72 | .typename = "PQ2 ADS PCI", | ||
| 73 | .name = "PQ2 ADS PCI", | 72 | .name = "PQ2 ADS PCI", |
| 74 | .end = pq2ads_pci_unmask_irq, | 73 | .end = pq2ads_pci_unmask_irq, |
| 75 | .mask = pq2ads_pci_mask_irq, | 74 | .mask = pq2ads_pci_mask_irq, |
| @@ -107,7 +106,7 @@ static void pq2ads_pci_irq_demux(unsigned int irq, struct irq_desc *desc) | |||
| 107 | static int pci_pic_host_map(struct irq_host *h, unsigned int virq, | 106 | static int pci_pic_host_map(struct irq_host *h, unsigned int virq, |
| 108 | irq_hw_number_t hw) | 107 | irq_hw_number_t hw) |
| 109 | { | 108 | { |
| 110 | get_irq_desc(virq)->status |= IRQ_LEVEL; | 109 | irq_to_desc(virq)->status |= IRQ_LEVEL; |
| 111 | set_irq_chip_data(virq, h->host_data); | 110 | set_irq_chip_data(virq, h->host_data); |
| 112 | set_irq_chip_and_handler(virq, &pq2ads_pci_ic, handle_level_irq); | 111 | set_irq_chip_and_handler(virq, &pq2ads_pci_ic, handle_level_irq); |
| 113 | return 0; | 112 | return 0; |
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c index 567ded7c3b9b..17f99745f0e4 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c | |||
| @@ -74,7 +74,7 @@ static int __init of_fsl_spi_probe(char *type, char *compatible, u32 sysclk, | |||
| 74 | 74 | ||
| 75 | prop = of_get_property(np, "mode", NULL); | 75 | prop = of_get_property(np, "mode", NULL); |
| 76 | if (prop && !strcmp(prop, "cpu-qe")) | 76 | if (prop && !strcmp(prop, "cpu-qe")) |
| 77 | pdata.qe_mode = 1; | 77 | pdata.flags = SPI_QE_CPU_MODE; |
| 78 | 78 | ||
| 79 | for (j = 0; j < num_board_infos; j++) { | 79 | for (j = 0; j < num_board_infos; j++) { |
| 80 | if (board_infos[j].bus_num == pdata.bus_num) | 80 | if (board_infos[j].bus_num == pdata.bus_num) |
diff --git a/arch/powerpc/platforms/83xx/suspend.c b/arch/powerpc/platforms/83xx/suspend.c index 08e65fc8b98c..43805348b81e 100644 --- a/arch/powerpc/platforms/83xx/suspend.c +++ b/arch/powerpc/platforms/83xx/suspend.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #define PMCCR1_NEXT_STATE 0x0C /* Next state for power management */ | 32 | #define PMCCR1_NEXT_STATE 0x0C /* Next state for power management */ |
| 33 | #define PMCCR1_NEXT_STATE_SHIFT 2 | 33 | #define PMCCR1_NEXT_STATE_SHIFT 2 |
| 34 | #define PMCCR1_CURR_STATE 0x03 /* Current state for power management*/ | 34 | #define PMCCR1_CURR_STATE 0x03 /* Current state for power management*/ |
| 35 | #define IMMR_SYSCR_OFFSET 0x100 | ||
| 35 | #define IMMR_RCW_OFFSET 0x900 | 36 | #define IMMR_RCW_OFFSET 0x900 |
| 36 | #define RCW_PCI_HOST 0x80000000 | 37 | #define RCW_PCI_HOST 0x80000000 |
| 37 | 38 | ||
| @@ -78,6 +79,22 @@ struct mpc83xx_clock { | |||
| 78 | u32 sccr; | 79 | u32 sccr; |
| 79 | }; | 80 | }; |
| 80 | 81 | ||
| 82 | struct mpc83xx_syscr { | ||
| 83 | __be32 sgprl; | ||
| 84 | __be32 sgprh; | ||
| 85 | __be32 spridr; | ||
| 86 | __be32 :32; | ||
| 87 | __be32 spcr; | ||
| 88 | __be32 sicrl; | ||
| 89 | __be32 sicrh; | ||
| 90 | }; | ||
| 91 | |||
| 92 | struct mpc83xx_saved { | ||
| 93 | u32 sicrl; | ||
| 94 | u32 sicrh; | ||
| 95 | u32 sccr; | ||
| 96 | }; | ||
| 97 | |||
| 81 | struct pmc_type { | 98 | struct pmc_type { |
| 82 | int has_deep_sleep; | 99 | int has_deep_sleep; |
| 83 | }; | 100 | }; |
| @@ -87,6 +104,8 @@ static int has_deep_sleep, deep_sleeping; | |||
| 87 | static int pmc_irq; | 104 | static int pmc_irq; |
| 88 | static struct mpc83xx_pmc __iomem *pmc_regs; | 105 | static struct mpc83xx_pmc __iomem *pmc_regs; |
| 89 | static struct mpc83xx_clock __iomem *clock_regs; | 106 | static struct mpc83xx_clock __iomem *clock_regs; |
| 107 | static struct mpc83xx_syscr __iomem *syscr_regs; | ||
| 108 | static struct mpc83xx_saved saved_regs; | ||
| 90 | static int is_pci_agent, wake_from_pci; | 109 | static int is_pci_agent, wake_from_pci; |
| 91 | static phys_addr_t immrbase; | 110 | static phys_addr_t immrbase; |
| 92 | static int pci_pm_state; | 111 | static int pci_pm_state; |
| @@ -96,6 +115,7 @@ int fsl_deep_sleep(void) | |||
| 96 | { | 115 | { |
| 97 | return deep_sleeping; | 116 | return deep_sleeping; |
| 98 | } | 117 | } |
| 118 | EXPORT_SYMBOL(fsl_deep_sleep); | ||
| 99 | 119 | ||
| 100 | static int mpc83xx_change_state(void) | 120 | static int mpc83xx_change_state(void) |
| 101 | { | 121 | { |
| @@ -136,6 +156,20 @@ static irqreturn_t pmc_irq_handler(int irq, void *dev_id) | |||
| 136 | return ret; | 156 | return ret; |
| 137 | } | 157 | } |
| 138 | 158 | ||
| 159 | static void mpc83xx_suspend_restore_regs(void) | ||
| 160 | { | ||
| 161 | out_be32(&syscr_regs->sicrl, saved_regs.sicrl); | ||
| 162 | out_be32(&syscr_regs->sicrh, saved_regs.sicrh); | ||
| 163 | out_be32(&clock_regs->sccr, saved_regs.sccr); | ||
| 164 | } | ||
| 165 | |||
| 166 | static void mpc83xx_suspend_save_regs(void) | ||
| 167 | { | ||
| 168 | saved_regs.sicrl = in_be32(&syscr_regs->sicrl); | ||
| 169 | saved_regs.sicrh = in_be32(&syscr_regs->sicrh); | ||
| 170 | saved_regs.sccr = in_be32(&clock_regs->sccr); | ||
| 171 | } | ||
| 172 | |||
| 139 | static int mpc83xx_suspend_enter(suspend_state_t state) | 173 | static int mpc83xx_suspend_enter(suspend_state_t state) |
| 140 | { | 174 | { |
| 141 | int ret = -EAGAIN; | 175 | int ret = -EAGAIN; |
| @@ -165,6 +199,8 @@ static int mpc83xx_suspend_enter(suspend_state_t state) | |||
| 165 | */ | 199 | */ |
| 166 | 200 | ||
| 167 | if (deep_sleeping) { | 201 | if (deep_sleeping) { |
| 202 | mpc83xx_suspend_save_regs(); | ||
| 203 | |||
| 168 | out_be32(&pmc_regs->mask, PMCER_ALL); | 204 | out_be32(&pmc_regs->mask, PMCER_ALL); |
| 169 | 205 | ||
| 170 | out_be32(&pmc_regs->config1, | 206 | out_be32(&pmc_regs->config1, |
| @@ -178,6 +214,8 @@ static int mpc83xx_suspend_enter(suspend_state_t state) | |||
| 178 | in_be32(&pmc_regs->config1) & ~PMCCR1_POWER_OFF); | 214 | in_be32(&pmc_regs->config1) & ~PMCCR1_POWER_OFF); |
| 179 | 215 | ||
| 180 | out_be32(&pmc_regs->mask, PMCER_PMCI); | 216 | out_be32(&pmc_regs->mask, PMCER_PMCI); |
| 217 | |||
| 218 | mpc83xx_suspend_restore_regs(); | ||
| 181 | } else { | 219 | } else { |
| 182 | out_be32(&pmc_regs->mask, PMCER_PMCI); | 220 | out_be32(&pmc_regs->mask, PMCER_PMCI); |
| 183 | 221 | ||
| @@ -193,7 +231,7 @@ out: | |||
| 193 | return ret; | 231 | return ret; |
| 194 | } | 232 | } |
| 195 | 233 | ||
| 196 | static void mpc83xx_suspend_finish(void) | 234 | static void mpc83xx_suspend_end(void) |
| 197 | { | 235 | { |
| 198 | deep_sleeping = 0; | 236 | deep_sleeping = 0; |
| 199 | } | 237 | } |
| @@ -277,7 +315,7 @@ static struct platform_suspend_ops mpc83xx_suspend_ops = { | |||
| 277 | .valid = mpc83xx_suspend_valid, | 315 | .valid = mpc83xx_suspend_valid, |
| 278 | .begin = mpc83xx_suspend_begin, | 316 | .begin = mpc83xx_suspend_begin, |
| 279 | .enter = mpc83xx_suspend_enter, | 317 | .enter = mpc83xx_suspend_enter, |
| 280 | .finish = mpc83xx_suspend_finish, | 318 | .end = mpc83xx_suspend_end, |
| 281 | }; | 319 | }; |
| 282 | 320 | ||
| 283 | static int pmc_probe(struct of_device *ofdev, | 321 | static int pmc_probe(struct of_device *ofdev, |
| @@ -332,12 +370,23 @@ static int pmc_probe(struct of_device *ofdev, | |||
| 332 | goto out_pmc; | 370 | goto out_pmc; |
| 333 | } | 371 | } |
| 334 | 372 | ||
| 373 | if (has_deep_sleep) { | ||
| 374 | syscr_regs = ioremap(immrbase + IMMR_SYSCR_OFFSET, | ||
| 375 | sizeof(*syscr_regs)); | ||
| 376 | if (!syscr_regs) { | ||
| 377 | ret = -ENOMEM; | ||
| 378 | goto out_syscr; | ||
| 379 | } | ||
| 380 | } | ||
| 381 | |||
| 335 | if (is_pci_agent) | 382 | if (is_pci_agent) |
| 336 | mpc83xx_set_agent(); | 383 | mpc83xx_set_agent(); |
| 337 | 384 | ||
| 338 | suspend_set_ops(&mpc83xx_suspend_ops); | 385 | suspend_set_ops(&mpc83xx_suspend_ops); |
| 339 | return 0; | 386 | return 0; |
| 340 | 387 | ||
| 388 | out_syscr: | ||
| 389 | iounmap(clock_regs); | ||
| 341 | out_pmc: | 390 | out_pmc: |
| 342 | iounmap(pmc_regs); | 391 | iounmap(pmc_regs); |
| 343 | out: | 392 | out: |
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index d3a975e8fd3e..d95121894eb7 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | menuconfig MPC85xx | 1 | menuconfig FSL_SOC_BOOKE |
| 2 | bool "Machine Type" | 2 | bool "Freescale Book-E Machine Type" |
| 3 | depends on PPC_85xx | 3 | depends on PPC_85xx || PPC_BOOK3E |
| 4 | select FSL_SOC | ||
| 4 | select PPC_UDBG_16550 | 5 | select PPC_UDBG_16550 |
| 5 | select MPIC | 6 | select MPIC |
| 6 | select PPC_PCI_CHOICE | 7 | select PPC_PCI_CHOICE |
| @@ -8,7 +9,7 @@ menuconfig MPC85xx | |||
| 8 | select SERIAL_8250_SHARE_IRQ if SERIAL_8250 | 9 | select SERIAL_8250_SHARE_IRQ if SERIAL_8250 |
| 9 | default y | 10 | default y |
| 10 | 11 | ||
| 11 | if MPC85xx | 12 | if FSL_SOC_BOOKE |
| 12 | 13 | ||
| 13 | config MPC8540_ADS | 14 | config MPC8540_ADS |
| 14 | bool "Freescale MPC8540 ADS" | 15 | bool "Freescale MPC8540 ADS" |
| @@ -144,7 +145,19 @@ config SBC8560 | |||
| 144 | help | 145 | help |
| 145 | This option enables support for the Wind River SBC8560 board | 146 | This option enables support for the Wind River SBC8560 board |
| 146 | 147 | ||
| 147 | endif # MPC85xx | 148 | config P4080_DS |
| 149 | bool "Freescale P4080 DS" | ||
| 150 | select DEFAULT_UIMAGE | ||
| 151 | select PPC_FSL_BOOK3E | ||
| 152 | select PPC_E500MC | ||
| 153 | select PHYS_64BIT | ||
| 154 | select SWIOTLB | ||
| 155 | select MPC8xxx_GPIO | ||
| 156 | select HAS_RAPIDIO | ||
| 157 | help | ||
| 158 | This option enables support for the P4080 DS board | ||
| 159 | |||
| 160 | endif # FSL_SOC_BOOKE | ||
| 148 | 161 | ||
| 149 | config TQM85xx | 162 | config TQM85xx |
| 150 | bool | 163 | bool |
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index 9098aea0cf32..387c128f2c8c 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile | |||
| @@ -10,6 +10,7 @@ obj-$(CONFIG_MPC8536_DS) += mpc8536_ds.o | |||
| 10 | obj-$(CONFIG_MPC85xx_DS) += mpc85xx_ds.o | 10 | obj-$(CONFIG_MPC85xx_DS) += mpc85xx_ds.o |
| 11 | obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o | 11 | obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o |
| 12 | obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o | 12 | obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o |
| 13 | obj-$(CONFIG_P4080_DS) += p4080_ds.o corenet_ds.o | ||
| 13 | obj-$(CONFIG_STX_GP3) += stx_gp3.o | 14 | obj-$(CONFIG_STX_GP3) += stx_gp3.o |
| 14 | obj-$(CONFIG_TQM85xx) += tqm85xx.o | 15 | obj-$(CONFIG_TQM85xx) += tqm85xx.o |
| 15 | obj-$(CONFIG_SBC8560) += sbc8560.o | 16 | obj-$(CONFIG_SBC8560) += sbc8560.o |
diff --git a/arch/powerpc/platforms/85xx/corenet_ds.c b/arch/powerpc/platforms/85xx/corenet_ds.c new file mode 100644 index 000000000000..534c2ecc89d9 --- /dev/null +++ b/arch/powerpc/platforms/85xx/corenet_ds.c | |||
| @@ -0,0 +1,125 @@ | |||
| 1 | /* | ||
| 2 | * Corenet based SoC DS Setup | ||
| 3 | * | ||
| 4 | * Maintained by Kumar Gala (see MAINTAINERS for contact information) | ||
| 5 | * | ||
| 6 | * Copyright 2009 Freescale Semiconductor Inc. | ||
| 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/kernel.h> | ||
| 15 | #include <linux/pci.h> | ||
| 16 | #include <linux/kdev_t.h> | ||
| 17 | #include <linux/delay.h> | ||
| 18 | #include <linux/interrupt.h> | ||
| 19 | #include <linux/lmb.h> | ||
| 20 | |||
| 21 | #include <asm/system.h> | ||
| 22 | #include <asm/time.h> | ||
| 23 | #include <asm/machdep.h> | ||
| 24 | #include <asm/pci-bridge.h> | ||
| 25 | #include <mm/mmu_decl.h> | ||
| 26 | #include <asm/prom.h> | ||
| 27 | #include <asm/udbg.h> | ||
| 28 | #include <asm/mpic.h> | ||
| 29 | |||
| 30 | #include <linux/of_platform.h> | ||
| 31 | #include <sysdev/fsl_soc.h> | ||
| 32 | #include <sysdev/fsl_pci.h> | ||
| 33 | |||
| 34 | void __init corenet_ds_pic_init(void) | ||
| 35 | { | ||
| 36 | struct mpic *mpic; | ||
| 37 | struct resource r; | ||
| 38 | struct device_node *np = NULL; | ||
| 39 | unsigned int flags = MPIC_PRIMARY | MPIC_BIG_ENDIAN | | ||
| 40 | MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU; | ||
| 41 | |||
| 42 | np = of_find_node_by_type(np, "open-pic"); | ||
| 43 | |||
| 44 | if (np == NULL) { | ||
| 45 | printk(KERN_ERR "Could not find open-pic node\n"); | ||
| 46 | return; | ||
| 47 | } | ||
| 48 | |||
| 49 | if (of_address_to_resource(np, 0, &r)) { | ||
| 50 | printk(KERN_ERR "Failed to map mpic register space\n"); | ||
| 51 | of_node_put(np); | ||
| 52 | return; | ||
| 53 | } | ||
| 54 | |||
| 55 | if (ppc_md.get_irq == mpic_get_coreint_irq) | ||
| 56 | flags |= MPIC_ENABLE_COREINT; | ||
| 57 | |||
| 58 | mpic = mpic_alloc(np, r.start, flags, 0, 256, " OpenPIC "); | ||
| 59 | BUG_ON(mpic == NULL); | ||
| 60 | |||
| 61 | mpic_init(mpic); | ||
| 62 | } | ||
| 63 | |||
| 64 | #ifdef CONFIG_PCI | ||
| 65 | static int primary_phb_addr; | ||
| 66 | #endif | ||
| 67 | |||
| 68 | /* | ||
| 69 | * Setup the architecture | ||
| 70 | */ | ||
| 71 | #ifdef CONFIG_SMP | ||
| 72 | void __init mpc85xx_smp_init(void); | ||
| 73 | #endif | ||
| 74 | |||
| 75 | void __init corenet_ds_setup_arch(void) | ||
| 76 | { | ||
| 77 | #ifdef CONFIG_PCI | ||
| 78 | struct device_node *np; | ||
| 79 | struct pci_controller *hose; | ||
| 80 | #endif | ||
| 81 | dma_addr_t max = 0xffffffff; | ||
| 82 | |||
| 83 | #ifdef CONFIG_SMP | ||
| 84 | mpc85xx_smp_init(); | ||
| 85 | #endif | ||
| 86 | |||
| 87 | #ifdef CONFIG_PCI | ||
| 88 | for_each_compatible_node(np, "pci", "fsl,p4080-pcie") { | ||
| 89 | struct resource rsrc; | ||
| 90 | of_address_to_resource(np, 0, &rsrc); | ||
| 91 | if ((rsrc.start & 0xfffff) == primary_phb_addr) | ||
| 92 | fsl_add_bridge(np, 1); | ||
| 93 | else | ||
| 94 | fsl_add_bridge(np, 0); | ||
| 95 | |||
| 96 | hose = pci_find_hose_for_OF_device(np); | ||
| 97 | max = min(max, hose->dma_window_base_cur + | ||
| 98 | hose->dma_window_size); | ||
| 99 | } | ||
| 100 | #endif | ||
| 101 | |||
| 102 | #ifdef CONFIG_SWIOTLB | ||
| 103 | if (lmb_end_of_DRAM() > max) { | ||
| 104 | ppc_swiotlb_enable = 1; | ||
| 105 | set_pci_dma_ops(&swiotlb_dma_ops); | ||
| 106 | ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; | ||
| 107 | } | ||
| 108 | #endif | ||
| 109 | pr_info("%s board from Freescale Semiconductor\n", ppc_md.name); | ||
| 110 | } | ||
| 111 | |||
| 112 | static const struct of_device_id of_device_ids[] __devinitconst = { | ||
| 113 | { | ||
| 114 | .compatible = "simple-bus" | ||
| 115 | }, | ||
| 116 | { | ||
| 117 | .compatible = "fsl,rapidio-delta", | ||
| 118 | }, | ||
| 119 | {} | ||
| 120 | }; | ||
| 121 | |||
| 122 | int __init corenet_ds_publish_devices(void) | ||
| 123 | { | ||
| 124 | return of_platform_bus_probe(NULL, of_device_ids, NULL); | ||
| 125 | } | ||
diff --git a/arch/powerpc/platforms/85xx/corenet_ds.h b/arch/powerpc/platforms/85xx/corenet_ds.h new file mode 100644 index 000000000000..ddd700b23031 --- /dev/null +++ b/arch/powerpc/platforms/85xx/corenet_ds.h | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | /* | ||
| 2 | * Corenet based SoC DS Setup | ||
| 3 | * | ||
| 4 | * Copyright 2009 Freescale Semiconductor Inc. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 12 | #ifndef CORENET_DS_H | ||
| 13 | #define CORENET_DS_H | ||
| 14 | |||
| 15 | extern void __init corenet_ds_pic_init(void); | ||
| 16 | extern void __init corenet_ds_setup_arch(void); | ||
| 17 | extern int __init corenet_ds_publish_devices(void); | ||
| 18 | |||
| 19 | #endif | ||
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index 3909d57b86e3..21f61b8c445b 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c | |||
| @@ -86,7 +86,7 @@ static int mpc8568_fixup_125_clock(struct phy_device *phydev) | |||
| 86 | scr = phy_read(phydev, MV88E1111_SCR); | 86 | scr = phy_read(phydev, MV88E1111_SCR); |
| 87 | 87 | ||
| 88 | if (scr < 0) | 88 | if (scr < 0) |
| 89 | return err; | 89 | return scr; |
| 90 | 90 | ||
| 91 | err = phy_write(phydev, MV88E1111_SCR, scr | 0x0008); | 91 | err = phy_write(phydev, MV88E1111_SCR, scr | 0x0008); |
| 92 | 92 | ||
| @@ -301,6 +301,7 @@ static struct of_device_id mpc85xx_ids[] = { | |||
| 301 | { .compatible = "fsl,qe", }, | 301 | { .compatible = "fsl,qe", }, |
| 302 | { .compatible = "gianfar", }, | 302 | { .compatible = "gianfar", }, |
| 303 | { .compatible = "fsl,rapidio-delta", }, | 303 | { .compatible = "fsl,rapidio-delta", }, |
| 304 | { .compatible = "fsl,mpc8548-guts", }, | ||
| 304 | {}, | 305 | {}, |
| 305 | }; | 306 | }; |
| 306 | 307 | ||
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c index c8468de4acf6..088f30b0c088 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c | |||
| @@ -44,6 +44,7 @@ void __init mpc85xx_rdb_pic_init(void) | |||
| 44 | struct mpic *mpic; | 44 | struct mpic *mpic; |
| 45 | struct resource r; | 45 | struct resource r; |
| 46 | struct device_node *np; | 46 | struct device_node *np; |
| 47 | unsigned long root = of_get_flat_dt_root(); | ||
| 47 | 48 | ||
| 48 | np = of_find_node_by_type(NULL, "open-pic"); | 49 | np = of_find_node_by_type(NULL, "open-pic"); |
| 49 | if (np == NULL) { | 50 | if (np == NULL) { |
| @@ -57,11 +58,18 @@ void __init mpc85xx_rdb_pic_init(void) | |||
| 57 | return; | 58 | return; |
| 58 | } | 59 | } |
| 59 | 60 | ||
| 60 | mpic = mpic_alloc(np, r.start, | 61 | if (of_flat_dt_is_compatible(root, "fsl,85XXRDB-CAMP")) { |
| 62 | mpic = mpic_alloc(np, r.start, | ||
| 63 | MPIC_PRIMARY | | ||
| 64 | MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS, | ||
| 65 | 0, 256, " OpenPIC "); | ||
| 66 | } else { | ||
| 67 | mpic = mpic_alloc(np, r.start, | ||
| 61 | MPIC_PRIMARY | MPIC_WANTS_RESET | | 68 | MPIC_PRIMARY | MPIC_WANTS_RESET | |
| 62 | MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | | 69 | MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | |
| 63 | MPIC_SINGLE_DEST_CPU, | 70 | MPIC_SINGLE_DEST_CPU, |
| 64 | 0, 256, " OpenPIC "); | 71 | 0, 256, " OpenPIC "); |
| 72 | } | ||
| 65 | 73 | ||
| 66 | BUG_ON(mpic == NULL); | 74 | BUG_ON(mpic == NULL); |
| 67 | of_node_put(np); | 75 | of_node_put(np); |
| @@ -113,6 +121,7 @@ static int __init mpc85xxrdb_publish_devices(void) | |||
| 113 | return of_platform_bus_probe(NULL, mpc85xxrdb_ids, NULL); | 121 | return of_platform_bus_probe(NULL, mpc85xxrdb_ids, NULL); |
| 114 | } | 122 | } |
| 115 | machine_device_initcall(p2020_rdb, mpc85xxrdb_publish_devices); | 123 | machine_device_initcall(p2020_rdb, mpc85xxrdb_publish_devices); |
| 124 | machine_device_initcall(p1020_rdb, mpc85xxrdb_publish_devices); | ||
| 116 | 125 | ||
| 117 | /* | 126 | /* |
| 118 | * Called very early, device-tree isn't unflattened | 127 | * Called very early, device-tree isn't unflattened |
| @@ -126,6 +135,15 @@ static int __init p2020_rdb_probe(void) | |||
| 126 | return 0; | 135 | return 0; |
| 127 | } | 136 | } |
| 128 | 137 | ||
| 138 | static int __init p1020_rdb_probe(void) | ||
| 139 | { | ||
| 140 | unsigned long root = of_get_flat_dt_root(); | ||
| 141 | |||
| 142 | if (of_flat_dt_is_compatible(root, "fsl,P1020RDB")) | ||
| 143 | return 1; | ||
| 144 | return 0; | ||
| 145 | } | ||
| 146 | |||
| 129 | define_machine(p2020_rdb) { | 147 | define_machine(p2020_rdb) { |
| 130 | .name = "P2020 RDB", | 148 | .name = "P2020 RDB", |
| 131 | .probe = p2020_rdb_probe, | 149 | .probe = p2020_rdb_probe, |
| @@ -139,3 +157,17 @@ define_machine(p2020_rdb) { | |||
| 139 | .calibrate_decr = generic_calibrate_decr, | 157 | .calibrate_decr = generic_calibrate_decr, |
| 140 | .progress = udbg_progress, | 158 | .progress = udbg_progress, |
| 141 | }; | 159 | }; |
| 160 | |||
| 161 | define_machine(p1020_rdb) { | ||
| 162 | .name = "P1020 RDB", | ||
| 163 | .probe = p1020_rdb_probe, | ||
| 164 | .setup_arch = mpc85xx_rdb_setup_arch, | ||
| 165 | .init_IRQ = mpc85xx_rdb_pic_init, | ||
| 166 | #ifdef CONFIG_PCI | ||
| 167 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
| 168 | #endif | ||
| 169 | .get_irq = mpic_get_irq, | ||
| 170 | .restart = fsl_rstcr_restart, | ||
| 171 | .calibrate_decr = generic_calibrate_decr, | ||
| 172 | .progress = udbg_progress, | ||
| 173 | }; | ||
diff --git a/arch/powerpc/platforms/85xx/p4080_ds.c b/arch/powerpc/platforms/85xx/p4080_ds.c new file mode 100644 index 000000000000..84170460497b --- /dev/null +++ b/arch/powerpc/platforms/85xx/p4080_ds.c | |||
| @@ -0,0 +1,74 @@ | |||
| 1 | /* | ||
| 2 | * P4080 DS Setup | ||
| 3 | * | ||
| 4 | * Maintained by Kumar Gala (see MAINTAINERS for contact information) | ||
| 5 | * | ||
| 6 | * Copyright 2009 Freescale Semiconductor Inc. | ||
| 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/kernel.h> | ||
| 15 | #include <linux/pci.h> | ||
| 16 | #include <linux/kdev_t.h> | ||
| 17 | #include <linux/delay.h> | ||
| 18 | #include <linux/interrupt.h> | ||
| 19 | |||
| 20 | #include <asm/system.h> | ||
| 21 | #include <asm/time.h> | ||
| 22 | #include <asm/machdep.h> | ||
| 23 | #include <asm/pci-bridge.h> | ||
| 24 | #include <mm/mmu_decl.h> | ||
| 25 | #include <asm/prom.h> | ||
| 26 | #include <asm/udbg.h> | ||
| 27 | #include <asm/mpic.h> | ||
| 28 | |||
| 29 | #include <linux/of_platform.h> | ||
| 30 | #include <sysdev/fsl_soc.h> | ||
| 31 | #include <sysdev/fsl_pci.h> | ||
| 32 | |||
| 33 | #include "corenet_ds.h" | ||
| 34 | |||
| 35 | #ifdef CONFIG_PCI | ||
| 36 | static int primary_phb_addr; | ||
| 37 | #endif | ||
| 38 | |||
| 39 | /* | ||
| 40 | * Called very early, device-tree isn't unflattened | ||
| 41 | */ | ||
| 42 | static int __init p4080_ds_probe(void) | ||
| 43 | { | ||
| 44 | unsigned long root = of_get_flat_dt_root(); | ||
| 45 | |||
| 46 | if (of_flat_dt_is_compatible(root, "fsl,P4080DS")) { | ||
| 47 | #ifdef CONFIG_PCI | ||
| 48 | /* treat PCIe1 as primary, | ||
| 49 | * shouldn't matter as we have no ISA on the board | ||
| 50 | */ | ||
| 51 | primary_phb_addr = 0x0000; | ||
| 52 | #endif | ||
| 53 | return 1; | ||
| 54 | } else { | ||
| 55 | return 0; | ||
| 56 | } | ||
| 57 | } | ||
| 58 | |||
| 59 | define_machine(p4080_ds) { | ||
| 60 | .name = "P4080 DS", | ||
| 61 | .probe = p4080_ds_probe, | ||
| 62 | .setup_arch = corenet_ds_setup_arch, | ||
| 63 | .init_IRQ = corenet_ds_pic_init, | ||
| 64 | #ifdef CONFIG_PCI | ||
| 65 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
| 66 | #endif | ||
| 67 | .get_irq = mpic_get_coreint_irq, | ||
| 68 | .restart = fsl_rstcr_restart, | ||
| 69 | .calibrate_decr = generic_calibrate_decr, | ||
| 70 | .progress = udbg_progress, | ||
| 71 | }; | ||
| 72 | |||
| 73 | machine_device_initcall(p4080_ds, corenet_ds_publish_devices); | ||
| 74 | machine_arch_initcall(p4080_ds, swiotlb_setup_bus_notifier); | ||
diff --git a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c index 60edf63d0157..e5da5f62b24a 100644 --- a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c +++ b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c | |||
| @@ -232,7 +232,7 @@ static int socrates_fpga_pic_set_type(unsigned int virq, | |||
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | static struct irq_chip socrates_fpga_pic_chip = { | 234 | static struct irq_chip socrates_fpga_pic_chip = { |
| 235 | .typename = " FPGA-PIC ", | 235 | .name = " FPGA-PIC ", |
| 236 | .ack = socrates_fpga_pic_ack, | 236 | .ack = socrates_fpga_pic_ack, |
| 237 | .mask = socrates_fpga_pic_mask, | 237 | .mask = socrates_fpga_pic_mask, |
| 238 | .mask_ack = socrates_fpga_pic_mask_ack, | 238 | .mask_ack = socrates_fpga_pic_mask_ack, |
| @@ -245,7 +245,7 @@ static int socrates_fpga_pic_host_map(struct irq_host *h, unsigned int virq, | |||
| 245 | irq_hw_number_t hwirq) | 245 | irq_hw_number_t hwirq) |
| 246 | { | 246 | { |
| 247 | /* All interrupts are LEVEL sensitive */ | 247 | /* All interrupts are LEVEL sensitive */ |
| 248 | get_irq_desc(virq)->status |= IRQ_LEVEL; | 248 | irq_to_desc(virq)->status |= IRQ_LEVEL; |
| 249 | set_irq_chip_and_handler(virq, &socrates_fpga_pic_chip, | 249 | set_irq_chip_and_handler(virq, &socrates_fpga_pic_chip, |
| 250 | handle_fasteoi_irq); | 250 | handle_fasteoi_irq); |
| 251 | 251 | ||
| @@ -253,7 +253,7 @@ static int socrates_fpga_pic_host_map(struct irq_host *h, unsigned int virq, | |||
| 253 | } | 253 | } |
| 254 | 254 | ||
| 255 | static int socrates_fpga_pic_host_xlate(struct irq_host *h, | 255 | static int socrates_fpga_pic_host_xlate(struct irq_host *h, |
| 256 | struct device_node *ct, u32 *intspec, unsigned int intsize, | 256 | struct device_node *ct, const u32 *intspec, unsigned int intsize, |
| 257 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) | 257 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) |
| 258 | { | 258 | { |
| 259 | struct socrates_fpga_irq_info *fpga_irq = &fpga_irqs[intspec[0]]; | 259 | struct socrates_fpga_irq_info *fpga_irq = &fpga_irqs[intspec[0]]; |
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig index 9c7b64a3402b..2bbfd530d6d8 100644 --- a/arch/powerpc/platforms/86xx/Kconfig +++ b/arch/powerpc/platforms/86xx/Kconfig | |||
| @@ -35,6 +35,7 @@ config MPC8610_HPCD | |||
| 35 | config GEF_PPC9A | 35 | config GEF_PPC9A |
| 36 | bool "GE Fanuc PPC9A" | 36 | bool "GE Fanuc PPC9A" |
| 37 | select DEFAULT_UIMAGE | 37 | select DEFAULT_UIMAGE |
| 38 | select MMIO_NVRAM | ||
| 38 | select GENERIC_GPIO | 39 | select GENERIC_GPIO |
| 39 | select ARCH_REQUIRE_GPIOLIB | 40 | select ARCH_REQUIRE_GPIOLIB |
| 40 | help | 41 | help |
| @@ -43,6 +44,7 @@ config GEF_PPC9A | |||
| 43 | config GEF_SBC310 | 44 | config GEF_SBC310 |
| 44 | bool "GE Fanuc SBC310" | 45 | bool "GE Fanuc SBC310" |
| 45 | select DEFAULT_UIMAGE | 46 | select DEFAULT_UIMAGE |
| 47 | select MMIO_NVRAM | ||
| 46 | select GENERIC_GPIO | 48 | select GENERIC_GPIO |
| 47 | select ARCH_REQUIRE_GPIOLIB | 49 | select ARCH_REQUIRE_GPIOLIB |
| 48 | help | 50 | help |
| @@ -51,6 +53,7 @@ config GEF_SBC310 | |||
| 51 | config GEF_SBC610 | 53 | config GEF_SBC610 |
| 52 | bool "GE Fanuc SBC610" | 54 | bool "GE Fanuc SBC610" |
| 53 | select DEFAULT_UIMAGE | 55 | select DEFAULT_UIMAGE |
| 56 | select MMIO_NVRAM | ||
| 54 | select GENERIC_GPIO | 57 | select GENERIC_GPIO |
| 55 | select ARCH_REQUIRE_GPIOLIB | 58 | select ARCH_REQUIRE_GPIOLIB |
| 56 | select HAS_RAPIDIO | 59 | select HAS_RAPIDIO |
diff --git a/arch/powerpc/platforms/86xx/gef_pic.c b/arch/powerpc/platforms/86xx/gef_pic.c index 50d0a2b63809..0110a8736d33 100644 --- a/arch/powerpc/platforms/86xx/gef_pic.c +++ b/arch/powerpc/platforms/86xx/gef_pic.c | |||
| @@ -149,7 +149,7 @@ static void gef_pic_unmask(unsigned int virq) | |||
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | static struct irq_chip gef_pic_chip = { | 151 | static struct irq_chip gef_pic_chip = { |
| 152 | .typename = "gefp", | 152 | .name = "gefp", |
| 153 | .mask = gef_pic_mask, | 153 | .mask = gef_pic_mask, |
| 154 | .mask_ack = gef_pic_mask_ack, | 154 | .mask_ack = gef_pic_mask_ack, |
| 155 | .unmask = gef_pic_unmask, | 155 | .unmask = gef_pic_unmask, |
| @@ -163,14 +163,14 @@ static int gef_pic_host_map(struct irq_host *h, unsigned int virq, | |||
| 163 | irq_hw_number_t hwirq) | 163 | irq_hw_number_t hwirq) |
| 164 | { | 164 | { |
| 165 | /* All interrupts are LEVEL sensitive */ | 165 | /* All interrupts are LEVEL sensitive */ |
| 166 | get_irq_desc(virq)->status |= IRQ_LEVEL; | 166 | irq_to_desc(virq)->status |= IRQ_LEVEL; |
| 167 | set_irq_chip_and_handler(virq, &gef_pic_chip, handle_level_irq); | 167 | set_irq_chip_and_handler(virq, &gef_pic_chip, handle_level_irq); |
| 168 | 168 | ||
| 169 | return 0; | 169 | return 0; |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | static int gef_pic_host_xlate(struct irq_host *h, struct device_node *ct, | 172 | static int gef_pic_host_xlate(struct irq_host *h, struct device_node *ct, |
| 173 | u32 *intspec, unsigned int intsize, | 173 | const u32 *intspec, unsigned int intsize, |
| 174 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) | 174 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) |
| 175 | { | 175 | { |
| 176 | 176 | ||
diff --git a/arch/powerpc/platforms/86xx/gef_ppc9a.c b/arch/powerpc/platforms/86xx/gef_ppc9a.c index 287f7bd17dd9..a792e5d85813 100644 --- a/arch/powerpc/platforms/86xx/gef_ppc9a.c +++ b/arch/powerpc/platforms/86xx/gef_ppc9a.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <asm/udbg.h> | 33 | #include <asm/udbg.h> |
| 34 | 34 | ||
| 35 | #include <asm/mpic.h> | 35 | #include <asm/mpic.h> |
| 36 | #include <asm/nvram.h> | ||
| 36 | 37 | ||
| 37 | #include <sysdev/fsl_pci.h> | 38 | #include <sysdev/fsl_pci.h> |
| 38 | #include <sysdev/fsl_soc.h> | 39 | #include <sysdev/fsl_soc.h> |
| @@ -95,6 +96,10 @@ static void __init gef_ppc9a_setup_arch(void) | |||
| 95 | printk(KERN_WARNING "Unable to map board registers\n"); | 96 | printk(KERN_WARNING "Unable to map board registers\n"); |
| 96 | of_node_put(regs); | 97 | of_node_put(regs); |
| 97 | } | 98 | } |
| 99 | |||
| 100 | #if defined(CONFIG_MMIO_NVRAM) | ||
| 101 | mmio_nvram_init(); | ||
| 102 | #endif | ||
| 98 | } | 103 | } |
| 99 | 104 | ||
| 100 | /* Return the PCB revision */ | 105 | /* Return the PCB revision */ |
diff --git a/arch/powerpc/platforms/86xx/gef_sbc310.c b/arch/powerpc/platforms/86xx/gef_sbc310.c index 90754e752bd8..6a1a613836c2 100644 --- a/arch/powerpc/platforms/86xx/gef_sbc310.c +++ b/arch/powerpc/platforms/86xx/gef_sbc310.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <asm/udbg.h> | 33 | #include <asm/udbg.h> |
| 34 | 34 | ||
| 35 | #include <asm/mpic.h> | 35 | #include <asm/mpic.h> |
| 36 | #include <asm/nvram.h> | ||
| 36 | 37 | ||
| 37 | #include <sysdev/fsl_pci.h> | 38 | #include <sysdev/fsl_pci.h> |
| 38 | #include <sysdev/fsl_soc.h> | 39 | #include <sysdev/fsl_soc.h> |
| @@ -95,6 +96,10 @@ static void __init gef_sbc310_setup_arch(void) | |||
| 95 | printk(KERN_WARNING "Unable to map board registers\n"); | 96 | printk(KERN_WARNING "Unable to map board registers\n"); |
| 96 | of_node_put(regs); | 97 | of_node_put(regs); |
| 97 | } | 98 | } |
| 99 | |||
| 100 | #if defined(CONFIG_MMIO_NVRAM) | ||
| 101 | mmio_nvram_init(); | ||
| 102 | #endif | ||
| 98 | } | 103 | } |
| 99 | 104 | ||
| 100 | /* Return the PCB revision */ | 105 | /* Return the PCB revision */ |
diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c index 72b31a6010a0..e10688a0fc4e 100644 --- a/arch/powerpc/platforms/86xx/gef_sbc610.c +++ b/arch/powerpc/platforms/86xx/gef_sbc610.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <asm/udbg.h> | 33 | #include <asm/udbg.h> |
| 34 | 34 | ||
| 35 | #include <asm/mpic.h> | 35 | #include <asm/mpic.h> |
| 36 | #include <asm/nvram.h> | ||
| 36 | 37 | ||
| 37 | #include <sysdev/fsl_pci.h> | 38 | #include <sysdev/fsl_pci.h> |
| 38 | #include <sysdev/fsl_soc.h> | 39 | #include <sysdev/fsl_soc.h> |
| @@ -95,6 +96,10 @@ static void __init gef_sbc610_setup_arch(void) | |||
| 95 | printk(KERN_WARNING "Unable to map board registers\n"); | 96 | printk(KERN_WARNING "Unable to map board registers\n"); |
| 96 | of_node_put(regs); | 97 | of_node_put(regs); |
| 97 | } | 98 | } |
| 99 | |||
| 100 | #if defined(CONFIG_MMIO_NVRAM) | ||
| 101 | mmio_nvram_init(); | ||
| 102 | #endif | ||
| 98 | } | 103 | } |
| 99 | 104 | ||
| 100 | /* Return the PCB revision */ | 105 | /* Return the PCB revision */ |
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c index 627908a4cd77..5abe137f6309 100644 --- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c +++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/stddef.h> | 19 | #include <linux/stddef.h> |
| 20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
| 21 | #include <linux/pci.h> | 21 | #include <linux/pci.h> |
| 22 | #include <linux/interrupt.h> | ||
| 22 | #include <linux/kdev_t.h> | 23 | #include <linux/kdev_t.h> |
| 23 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
| 24 | #include <linux/seq_file.h> | 25 | #include <linux/seq_file.h> |
| @@ -41,10 +42,46 @@ | |||
| 41 | 42 | ||
| 42 | #include "mpc86xx.h" | 43 | #include "mpc86xx.h" |
| 43 | 44 | ||
| 45 | static struct device_node *pixis_node; | ||
| 44 | static unsigned char *pixis_bdcfg0, *pixis_arch; | 46 | static unsigned char *pixis_bdcfg0, *pixis_arch; |
| 45 | 47 | ||
| 48 | #ifdef CONFIG_SUSPEND | ||
| 49 | static irqreturn_t mpc8610_sw9_irq(int irq, void *data) | ||
| 50 | { | ||
| 51 | pr_debug("%s: PIXIS' event (sw9/wakeup) IRQ handled\n", __func__); | ||
| 52 | return IRQ_HANDLED; | ||
| 53 | } | ||
| 54 | |||
| 55 | static void __init mpc8610_suspend_init(void) | ||
| 56 | { | ||
| 57 | int irq; | ||
| 58 | int ret; | ||
| 59 | |||
| 60 | if (!pixis_node) | ||
| 61 | return; | ||
| 62 | |||
| 63 | irq = irq_of_parse_and_map(pixis_node, 0); | ||
| 64 | if (!irq) { | ||
| 65 | pr_err("%s: can't map pixis event IRQ.\n", __func__); | ||
| 66 | return; | ||
| 67 | } | ||
| 68 | |||
| 69 | ret = request_irq(irq, mpc8610_sw9_irq, 0, "sw9/wakeup", NULL); | ||
| 70 | if (ret) { | ||
| 71 | pr_err("%s: can't request pixis event IRQ: %d\n", | ||
| 72 | __func__, ret); | ||
| 73 | irq_dispose_mapping(irq); | ||
| 74 | } | ||
| 75 | |||
| 76 | enable_irq_wake(irq); | ||
| 77 | } | ||
| 78 | #else | ||
| 79 | static inline void mpc8610_suspend_init(void) { } | ||
| 80 | #endif /* CONFIG_SUSPEND */ | ||
| 81 | |||
| 46 | static struct of_device_id __initdata mpc8610_ids[] = { | 82 | static struct of_device_id __initdata mpc8610_ids[] = { |
| 47 | { .compatible = "fsl,mpc8610-immr", }, | 83 | { .compatible = "fsl,mpc8610-immr", }, |
| 84 | { .compatible = "fsl,mpc8610-guts", }, | ||
| 48 | { .compatible = "simple-bus", }, | 85 | { .compatible = "simple-bus", }, |
| 49 | { .compatible = "gianfar", }, | 86 | { .compatible = "gianfar", }, |
| 50 | {} | 87 | {} |
| @@ -55,6 +92,9 @@ static int __init mpc8610_declare_of_platform_devices(void) | |||
| 55 | /* Firstly, register PIXIS GPIOs. */ | 92 | /* Firstly, register PIXIS GPIOs. */ |
| 56 | simple_gpiochip_init("fsl,fpga-pixis-gpio-bank"); | 93 | simple_gpiochip_init("fsl,fpga-pixis-gpio-bank"); |
| 57 | 94 | ||
| 95 | /* Enable wakeup on PIXIS' event IRQ. */ | ||
| 96 | mpc8610_suspend_init(); | ||
| 97 | |||
| 58 | /* Without this call, the SSI device driver won't get probed. */ | 98 | /* Without this call, the SSI device driver won't get probed. */ |
| 59 | of_platform_bus_probe(NULL, mpc8610_ids, NULL); | 99 | of_platform_bus_probe(NULL, mpc8610_ids, NULL); |
| 60 | 100 | ||
| @@ -250,10 +290,10 @@ static void __init mpc86xx_hpcd_setup_arch(void) | |||
| 250 | diu_ops.set_sysfs_monitor_port = mpc8610hpcd_set_sysfs_monitor_port; | 290 | diu_ops.set_sysfs_monitor_port = mpc8610hpcd_set_sysfs_monitor_port; |
| 251 | #endif | 291 | #endif |
| 252 | 292 | ||
| 253 | np = of_find_compatible_node(NULL, NULL, "fsl,fpga-pixis"); | 293 | pixis_node = of_find_compatible_node(NULL, NULL, "fsl,fpga-pixis"); |
| 254 | if (np) { | 294 | if (pixis_node) { |
| 255 | of_address_to_resource(np, 0, &r); | 295 | of_address_to_resource(pixis_node, 0, &r); |
| 256 | of_node_put(np); | 296 | of_node_put(pixis_node); |
| 257 | pixis = ioremap(r.start, 32); | 297 | pixis = ioremap(r.start, 32); |
| 258 | if (!pixis) { | 298 | if (!pixis) { |
| 259 | printk(KERN_ERR "Err: can't map FPGA cfg register!\n"); | 299 | printk(KERN_ERR "Err: can't map FPGA cfg register!\n"); |
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c index 385acfc48397..242954c4293f 100644 --- a/arch/powerpc/platforms/8xx/m8xx_setup.c +++ b/arch/powerpc/platforms/8xx/m8xx_setup.c | |||
| @@ -222,7 +222,7 @@ static void cpm_cascade(unsigned int irq, struct irq_desc *desc) | |||
| 222 | int cascade_irq; | 222 | int cascade_irq; |
| 223 | 223 | ||
| 224 | if ((cascade_irq = cpm_get_irq()) >= 0) { | 224 | if ((cascade_irq = cpm_get_irq()) >= 0) { |
| 225 | struct irq_desc *cdesc = irq_desc + cascade_irq; | 225 | struct irq_desc *cdesc = irq_to_desc(cascade_irq); |
| 226 | 226 | ||
| 227 | generic_handle_irq(cascade_irq); | 227 | generic_handle_irq(cascade_irq); |
| 228 | cdesc->chip->eoi(cascade_irq); | 228 | cdesc->chip->eoi(cascade_irq); |
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 04a8061045c4..d1663db7810f 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
| @@ -86,6 +86,11 @@ config RTAS_ERROR_LOGGING | |||
| 86 | depends on PPC_RTAS | 86 | depends on PPC_RTAS |
| 87 | default n | 87 | default n |
| 88 | 88 | ||
| 89 | config PPC_RTAS_DAEMON | ||
| 90 | bool | ||
| 91 | depends on PPC_RTAS | ||
| 92 | default n | ||
| 93 | |||
| 89 | config RTAS_PROC | 94 | config RTAS_PROC |
| 90 | bool "Proc interface to RTAS" | 95 | bool "Proc interface to RTAS" |
| 91 | depends on PPC_RTAS | 96 | depends on PPC_RTAS |
| @@ -255,7 +260,7 @@ config QE_GPIO | |||
| 255 | 260 | ||
| 256 | config CPM2 | 261 | config CPM2 |
| 257 | bool "Enable support for the CPM2 (Communications Processor Module)" | 262 | bool "Enable support for the CPM2 (Communications Processor Module)" |
| 258 | depends on MPC85xx || 8260 | 263 | depends on (FSL_SOC_BOOKE && PPC32) || 8260 |
| 259 | select CPM | 264 | select CPM |
| 260 | select PPC_LIB_RHEAP | 265 | select PPC_LIB_RHEAP |
| 261 | select PPC_PCI_CHOICE | 266 | select PPC_PCI_CHOICE |
| @@ -300,7 +305,7 @@ source "arch/powerpc/sysdev/bestcomm/Kconfig" | |||
| 300 | 305 | ||
| 301 | config MPC8xxx_GPIO | 306 | config MPC8xxx_GPIO |
| 302 | bool "MPC8xxx GPIO support" | 307 | bool "MPC8xxx GPIO support" |
| 303 | depends on PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || PPC_85xx || PPC_86xx | 308 | depends on PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || FSL_SOC_BOOKE || PPC_86xx |
| 304 | select GENERIC_GPIO | 309 | select GENERIC_GPIO |
| 305 | select ARCH_REQUIRE_GPIOLIB | 310 | select ARCH_REQUIRE_GPIOLIB |
| 306 | help | 311 | help |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index e382cae678b8..fa0f690d3867 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
| @@ -28,8 +28,6 @@ config PPC_BOOK3S_32 | |||
| 28 | config PPC_85xx | 28 | config PPC_85xx |
| 29 | bool "Freescale 85xx" | 29 | bool "Freescale 85xx" |
| 30 | select E500 | 30 | select E500 |
| 31 | select FSL_SOC | ||
| 32 | select MPC85xx | ||
| 33 | 31 | ||
| 34 | config PPC_8xx | 32 | config PPC_8xx |
| 35 | bool "Freescale 8xx" | 33 | bool "Freescale 8xx" |
| @@ -138,6 +136,14 @@ config PPC_FPU | |||
| 138 | bool | 136 | bool |
| 139 | default y if PPC64 | 137 | default y if PPC64 |
| 140 | 138 | ||
| 139 | config FSL_EMB_PERFMON | ||
| 140 | bool "Freescale Embedded Perfmon" | ||
| 141 | depends on E500 || PPC_83xx | ||
| 142 | help | ||
| 143 | This is the Performance Monitor support found on the e500 core | ||
| 144 | and some e300 cores (c3 and c4). Select this only if your | ||
| 145 | core supports the Embedded Performance Monitor APU | ||
| 146 | |||
| 141 | config 4xx | 147 | config 4xx |
| 142 | bool | 148 | bool |
| 143 | depends on 40x || 44x | 149 | depends on 40x || 44x |
| @@ -153,13 +159,6 @@ config FSL_BOOKE | |||
| 153 | depends on E200 || E500 | 159 | depends on E200 || E500 |
| 154 | default y | 160 | default y |
| 155 | 161 | ||
| 156 | config FSL_EMB_PERFMON | ||
| 157 | bool "Freescale Embedded Perfmon" | ||
| 158 | depends on E500 || PPC_83xx | ||
| 159 | help | ||
| 160 | This is the Performance Monitor support found on the e500 core | ||
| 161 | and some e300 cores (c3 and c4). Select this only if your | ||
| 162 | core supports the Embedded Performance Monitor APU | ||
| 163 | 162 | ||
| 164 | config PTE_64BIT | 163 | config PTE_64BIT |
| 165 | bool | 164 | bool |
| @@ -312,7 +311,7 @@ config NR_CPUS | |||
| 312 | 311 | ||
| 313 | config NOT_COHERENT_CACHE | 312 | config NOT_COHERENT_CACHE |
| 314 | bool | 313 | bool |
| 315 | depends on 4xx || 8xx || E200 || PPC_MPC512x | 314 | depends on 4xx || 8xx || E200 || PPC_MPC512x || GAMECUBE_COMMON |
| 316 | default y | 315 | default y |
| 317 | 316 | ||
| 318 | config CHECK_CACHE_COHERENCY | 317 | config CHECK_CACHE_COHERENCY |
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile index a6812ee00100..fdb9f0b0d7a8 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile | |||
| @@ -12,7 +12,7 @@ obj-$(CONFIG_PPC_MPC52xx) += 52xx/ | |||
| 12 | obj-$(CONFIG_PPC_8xx) += 8xx/ | 12 | obj-$(CONFIG_PPC_8xx) += 8xx/ |
| 13 | obj-$(CONFIG_PPC_82xx) += 82xx/ | 13 | obj-$(CONFIG_PPC_82xx) += 82xx/ |
| 14 | obj-$(CONFIG_PPC_83xx) += 83xx/ | 14 | obj-$(CONFIG_PPC_83xx) += 83xx/ |
| 15 | obj-$(CONFIG_PPC_85xx) += 85xx/ | 15 | obj-$(CONFIG_FSL_SOC_BOOKE) += 85xx/ |
| 16 | obj-$(CONFIG_PPC_86xx) += 86xx/ | 16 | obj-$(CONFIG_PPC_86xx) += 86xx/ |
| 17 | obj-$(CONFIG_PPC_PSERIES) += pseries/ | 17 | obj-$(CONFIG_PPC_PSERIES) += pseries/ |
| 18 | obj-$(CONFIG_PPC_ISERIES) += iseries/ | 18 | obj-$(CONFIG_PPC_ISERIES) += iseries/ |
diff --git a/arch/powerpc/platforms/amigaone/setup.c b/arch/powerpc/platforms/amigaone/setup.c index 9290a7a442d0..fb4eb0df054c 100644 --- a/arch/powerpc/platforms/amigaone/setup.c +++ b/arch/powerpc/platforms/amigaone/setup.c | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
| 16 | #include <linux/seq_file.h> | 16 | #include <linux/seq_file.h> |
| 17 | #include <linux/utsrelease.h> | 17 | #include <generated/utsrelease.h> |
| 18 | 18 | ||
| 19 | #include <asm/machdep.h> | 19 | #include <asm/machdep.h> |
| 20 | #include <asm/cputable.h> | 20 | #include <asm/cputable.h> |
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c index a86c34b3bb84..96fe896f6df3 100644 --- a/arch/powerpc/platforms/cell/axon_msi.c +++ b/arch/powerpc/platforms/cell/axon_msi.c | |||
| @@ -312,7 +312,7 @@ static struct irq_chip msic_irq_chip = { | |||
| 312 | .mask = mask_msi_irq, | 312 | .mask = mask_msi_irq, |
| 313 | .unmask = unmask_msi_irq, | 313 | .unmask = unmask_msi_irq, |
| 314 | .shutdown = unmask_msi_irq, | 314 | .shutdown = unmask_msi_irq, |
| 315 | .typename = "AXON-MSI", | 315 | .name = "AXON-MSI", |
| 316 | }; | 316 | }; |
| 317 | 317 | ||
| 318 | static int msic_host_map(struct irq_host *h, unsigned int virq, | 318 | static int msic_host_map(struct irq_host *h, unsigned int virq, |
diff --git a/arch/powerpc/platforms/cell/beat_interrupt.c b/arch/powerpc/platforms/cell/beat_interrupt.c index 72254848a228..36052a9ebcda 100644 --- a/arch/powerpc/platforms/cell/beat_interrupt.c +++ b/arch/powerpc/platforms/cell/beat_interrupt.c | |||
| @@ -110,7 +110,7 @@ static void beatic_end_irq(unsigned int irq_plug) | |||
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | static struct irq_chip beatic_pic = { | 112 | static struct irq_chip beatic_pic = { |
| 113 | .typename = " CELL-BEAT ", | 113 | .name = " CELL-BEAT ", |
| 114 | .unmask = beatic_unmask_irq, | 114 | .unmask = beatic_unmask_irq, |
| 115 | .mask = beatic_mask_irq, | 115 | .mask = beatic_mask_irq, |
| 116 | .eoi = beatic_end_irq, | 116 | .eoi = beatic_end_irq, |
| @@ -136,7 +136,7 @@ static void beatic_pic_host_unmap(struct irq_host *h, unsigned int virq) | |||
| 136 | static int beatic_pic_host_map(struct irq_host *h, unsigned int virq, | 136 | static int beatic_pic_host_map(struct irq_host *h, unsigned int virq, |
| 137 | irq_hw_number_t hw) | 137 | irq_hw_number_t hw) |
| 138 | { | 138 | { |
| 139 | struct irq_desc *desc = get_irq_desc(virq); | 139 | struct irq_desc *desc = irq_to_desc(virq); |
| 140 | int64_t err; | 140 | int64_t err; |
| 141 | 141 | ||
| 142 | err = beat_construct_and_connect_irq_plug(virq, hw); | 142 | err = beat_construct_and_connect_irq_plug(virq, hw); |
| @@ -166,11 +166,11 @@ static void beatic_pic_host_remap(struct irq_host *h, unsigned int virq, | |||
| 166 | * Note: We have only 1 entry to translate. | 166 | * Note: We have only 1 entry to translate. |
| 167 | */ | 167 | */ |
| 168 | static int beatic_pic_host_xlate(struct irq_host *h, struct device_node *ct, | 168 | static int beatic_pic_host_xlate(struct irq_host *h, struct device_node *ct, |
| 169 | u32 *intspec, unsigned int intsize, | 169 | const u32 *intspec, unsigned int intsize, |
| 170 | irq_hw_number_t *out_hwirq, | 170 | irq_hw_number_t *out_hwirq, |
| 171 | unsigned int *out_flags) | 171 | unsigned int *out_flags) |
| 172 | { | 172 | { |
| 173 | u64 *intspec2 = (u64 *)intspec; | 173 | const u64 *intspec2 = (const u64 *)intspec; |
| 174 | 174 | ||
| 175 | *out_hwirq = *intspec2; | 175 | *out_hwirq = *intspec2; |
| 176 | *out_flags |= IRQ_TYPE_LEVEL_LOW; | 176 | *out_flags |= IRQ_TYPE_LEVEL_LOW; |
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 882e47080e74..6829cf7e2bda 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c | |||
| @@ -54,7 +54,7 @@ struct iic { | |||
| 54 | struct device_node *node; | 54 | struct device_node *node; |
| 55 | }; | 55 | }; |
| 56 | 56 | ||
| 57 | static DEFINE_PER_CPU(struct iic, iic); | 57 | static DEFINE_PER_CPU(struct iic, cpu_iic); |
| 58 | #define IIC_NODE_COUNT 2 | 58 | #define IIC_NODE_COUNT 2 |
| 59 | static struct irq_host *iic_host; | 59 | static struct irq_host *iic_host; |
| 60 | 60 | ||
| @@ -82,13 +82,13 @@ static void iic_unmask(unsigned int irq) | |||
| 82 | 82 | ||
| 83 | static void iic_eoi(unsigned int irq) | 83 | static void iic_eoi(unsigned int irq) |
| 84 | { | 84 | { |
| 85 | struct iic *iic = &__get_cpu_var(iic); | 85 | struct iic *iic = &__get_cpu_var(cpu_iic); |
| 86 | out_be64(&iic->regs->prio, iic->eoi_stack[--iic->eoi_ptr]); | 86 | out_be64(&iic->regs->prio, iic->eoi_stack[--iic->eoi_ptr]); |
| 87 | BUG_ON(iic->eoi_ptr < 0); | 87 | BUG_ON(iic->eoi_ptr < 0); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | static struct irq_chip iic_chip = { | 90 | static struct irq_chip iic_chip = { |
| 91 | .typename = " CELL-IIC ", | 91 | .name = " CELL-IIC ", |
| 92 | .mask = iic_mask, | 92 | .mask = iic_mask, |
| 93 | .unmask = iic_unmask, | 93 | .unmask = iic_unmask, |
| 94 | .eoi = iic_eoi, | 94 | .eoi = iic_eoi, |
| @@ -133,7 +133,7 @@ static void iic_ioexc_cascade(unsigned int irq, struct irq_desc *desc) | |||
| 133 | 133 | ||
| 134 | 134 | ||
| 135 | static struct irq_chip iic_ioexc_chip = { | 135 | static struct irq_chip iic_ioexc_chip = { |
| 136 | .typename = " CELL-IOEX", | 136 | .name = " CELL-IOEX", |
| 137 | .mask = iic_mask, | 137 | .mask = iic_mask, |
| 138 | .unmask = iic_unmask, | 138 | .unmask = iic_unmask, |
| 139 | .eoi = iic_ioexc_eoi, | 139 | .eoi = iic_ioexc_eoi, |
| @@ -146,7 +146,7 @@ static unsigned int iic_get_irq(void) | |||
| 146 | struct iic *iic; | 146 | struct iic *iic; |
| 147 | unsigned int virq; | 147 | unsigned int virq; |
| 148 | 148 | ||
| 149 | iic = &__get_cpu_var(iic); | 149 | iic = &__get_cpu_var(cpu_iic); |
| 150 | *(unsigned long *) &pending = | 150 | *(unsigned long *) &pending = |
| 151 | in_be64((u64 __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)) |
| @@ -161,12 +161,12 @@ static unsigned int iic_get_irq(void) | |||
| 161 | 161 | ||
| 162 | void iic_setup_cpu(void) | 162 | void iic_setup_cpu(void) |
| 163 | { | 163 | { |
| 164 | out_be64(&__get_cpu_var(iic).regs->prio, 0xff); | 164 | out_be64(&__get_cpu_var(cpu_iic).regs->prio, 0xff); |
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | u8 iic_get_target_id(int cpu) | 167 | u8 iic_get_target_id(int cpu) |
| 168 | { | 168 | { |
| 169 | return per_cpu(iic, cpu).target_id; | 169 | return per_cpu(cpu_iic, cpu).target_id; |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | EXPORT_SYMBOL_GPL(iic_get_target_id); | 172 | EXPORT_SYMBOL_GPL(iic_get_target_id); |
| @@ -181,7 +181,7 @@ static inline int iic_ipi_to_irq(int ipi) | |||
| 181 | 181 | ||
| 182 | void iic_cause_IPI(int cpu, int mesg) | 182 | void iic_cause_IPI(int cpu, int mesg) |
| 183 | { | 183 | { |
| 184 | out_be64(&per_cpu(iic, cpu).regs->generate, (0xf - mesg) << 4); | 184 | out_be64(&per_cpu(cpu_iic, cpu).regs->generate, (0xf - mesg) << 4); |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | struct irq_host *iic_get_irq_host(int node) | 187 | struct irq_host *iic_get_irq_host(int node) |
| @@ -237,7 +237,7 @@ extern int noirqdebug; | |||
| 237 | 237 | ||
| 238 | static void handle_iic_irq(unsigned int irq, struct irq_desc *desc) | 238 | static void handle_iic_irq(unsigned int irq, struct irq_desc *desc) |
| 239 | { | 239 | { |
| 240 | spin_lock(&desc->lock); | 240 | raw_spin_lock(&desc->lock); |
| 241 | 241 | ||
| 242 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | 242 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); |
| 243 | 243 | ||
| @@ -265,18 +265,18 @@ static void handle_iic_irq(unsigned int irq, struct irq_desc *desc) | |||
| 265 | goto out_eoi; | 265 | goto out_eoi; |
| 266 | 266 | ||
| 267 | desc->status &= ~IRQ_PENDING; | 267 | desc->status &= ~IRQ_PENDING; |
| 268 | spin_unlock(&desc->lock); | 268 | raw_spin_unlock(&desc->lock); |
| 269 | action_ret = handle_IRQ_event(irq, action); | 269 | action_ret = handle_IRQ_event(irq, action); |
| 270 | if (!noirqdebug) | 270 | if (!noirqdebug) |
| 271 | note_interrupt(irq, desc, action_ret); | 271 | note_interrupt(irq, desc, action_ret); |
| 272 | spin_lock(&desc->lock); | 272 | raw_spin_lock(&desc->lock); |
| 273 | 273 | ||
| 274 | } while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING); | 274 | } while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING); |
| 275 | 275 | ||
| 276 | desc->status &= ~IRQ_INPROGRESS; | 276 | desc->status &= ~IRQ_INPROGRESS; |
| 277 | out_eoi: | 277 | out_eoi: |
| 278 | desc->chip->eoi(irq); | 278 | desc->chip->eoi(irq); |
| 279 | spin_unlock(&desc->lock); | 279 | raw_spin_unlock(&desc->lock); |
| 280 | } | 280 | } |
| 281 | 281 | ||
| 282 | static int iic_host_map(struct irq_host *h, unsigned int virq, | 282 | static int iic_host_map(struct irq_host *h, unsigned int virq, |
| @@ -297,7 +297,7 @@ static int iic_host_map(struct irq_host *h, unsigned int virq, | |||
| 297 | } | 297 | } |
| 298 | 298 | ||
| 299 | static int iic_host_xlate(struct irq_host *h, struct device_node *ct, | 299 | static int iic_host_xlate(struct irq_host *h, struct device_node *ct, |
| 300 | u32 *intspec, unsigned int intsize, | 300 | const u32 *intspec, unsigned int intsize, |
| 301 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) | 301 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) |
| 302 | 302 | ||
| 303 | { | 303 | { |
| @@ -348,7 +348,7 @@ static void __init init_one_iic(unsigned int hw_cpu, unsigned long addr, | |||
| 348 | /* XXX FIXME: should locate the linux CPU number from the HW cpu | 348 | /* XXX FIXME: should locate the linux CPU number from the HW cpu |
| 349 | * number properly. We are lucky for now | 349 | * number properly. We are lucky for now |
| 350 | */ | 350 | */ |
| 351 | struct iic *iic = &per_cpu(iic, hw_cpu); | 351 | struct iic *iic = &per_cpu(cpu_iic, hw_cpu); |
| 352 | 352 | ||
| 353 | iic->regs = ioremap(addr, sizeof(struct cbe_iic_thread_regs)); | 353 | iic->regs = ioremap(addr, sizeof(struct cbe_iic_thread_regs)); |
| 354 | BUG_ON(iic->regs == NULL); | 354 | BUG_ON(iic->regs == NULL); |
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c index 4e5655624ae8..01244f254a11 100644 --- a/arch/powerpc/platforms/cell/spider-pic.c +++ b/arch/powerpc/platforms/cell/spider-pic.c | |||
| @@ -102,7 +102,7 @@ static void spider_ack_irq(unsigned int virq) | |||
| 102 | 102 | ||
| 103 | /* Reset edge detection logic if necessary | 103 | /* Reset edge detection logic if necessary |
| 104 | */ | 104 | */ |
| 105 | if (get_irq_desc(virq)->status & IRQ_LEVEL) | 105 | if (irq_to_desc(virq)->status & IRQ_LEVEL) |
| 106 | return; | 106 | return; |
| 107 | 107 | ||
| 108 | /* Only interrupts 47 to 50 can be set to edge */ | 108 | /* Only interrupts 47 to 50 can be set to edge */ |
| @@ -119,7 +119,7 @@ static int spider_set_irq_type(unsigned int virq, unsigned int type) | |||
| 119 | struct spider_pic *pic = spider_virq_to_pic(virq); | 119 | struct spider_pic *pic = spider_virq_to_pic(virq); |
| 120 | unsigned int hw = irq_map[virq].hwirq; | 120 | unsigned int hw = irq_map[virq].hwirq; |
| 121 | void __iomem *cfg = spider_get_irq_config(pic, hw); | 121 | void __iomem *cfg = spider_get_irq_config(pic, hw); |
| 122 | struct irq_desc *desc = get_irq_desc(virq); | 122 | struct irq_desc *desc = irq_to_desc(virq); |
| 123 | u32 old_mask; | 123 | u32 old_mask; |
| 124 | u32 ic; | 124 | u32 ic; |
| 125 | 125 | ||
| @@ -168,7 +168,7 @@ static int spider_set_irq_type(unsigned int virq, unsigned int type) | |||
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | static struct irq_chip spider_pic = { | 170 | static struct irq_chip spider_pic = { |
| 171 | .typename = " SPIDER ", | 171 | .name = " SPIDER ", |
| 172 | .unmask = spider_unmask_irq, | 172 | .unmask = spider_unmask_irq, |
| 173 | .mask = spider_mask_irq, | 173 | .mask = spider_mask_irq, |
| 174 | .ack = spider_ack_irq, | 174 | .ack = spider_ack_irq, |
| @@ -187,7 +187,7 @@ static int spider_host_map(struct irq_host *h, unsigned int virq, | |||
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | static int spider_host_xlate(struct irq_host *h, struct device_node *ct, | 189 | static int spider_host_xlate(struct irq_host *h, struct device_node *ct, |
| 190 | u32 *intspec, unsigned int intsize, | 190 | const u32 *intspec, unsigned int intsize, |
| 191 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) | 191 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) |
| 192 | 192 | ||
| 193 | { | 193 | { |
diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile index b93f877ba504..b9d5d678aa44 100644 --- a/arch/powerpc/platforms/cell/spufs/Makefile +++ b/arch/powerpc/platforms/cell/spufs/Makefile | |||
| @@ -13,10 +13,8 @@ SPU_CC := $(SPU_CROSS)gcc | |||
| 13 | SPU_AS := $(SPU_CROSS)gcc | 13 | SPU_AS := $(SPU_CROSS)gcc |
| 14 | SPU_LD := $(SPU_CROSS)ld | 14 | SPU_LD := $(SPU_CROSS)ld |
| 15 | SPU_OBJCOPY := $(SPU_CROSS)objcopy | 15 | SPU_OBJCOPY := $(SPU_CROSS)objcopy |
| 16 | SPU_CFLAGS := -O2 -Wall -I$(srctree)/include \ | 16 | SPU_CFLAGS := -O2 -Wall -I$(srctree)/include -D__KERNEL__ |
| 17 | -I$(objtree)/include2 -D__KERNEL__ | 17 | SPU_AFLAGS := -c -D__ASSEMBLY__ -I$(srctree)/include -D__KERNEL__ |
| 18 | SPU_AFLAGS := -c -D__ASSEMBLY__ -I$(srctree)/include \ | ||
| 19 | -I$(objtree)/include2 -D__KERNEL__ | ||
| 20 | SPU_LDFLAGS := -N -Ttext=0x0 | 18 | SPU_LDFLAGS := -N -Ttext=0x0 |
| 21 | 19 | ||
| 22 | $(obj)/switch.o: $(obj)/spu_save_dump.h $(obj)/spu_restore_dump.h | 20 | $(obj)/switch.o: $(obj)/spu_save_dump.h $(obj)/spu_restore_dump.h |
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 884e8bcec499..64a4c2d85f7c 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c | |||
| @@ -2494,7 +2494,7 @@ static ssize_t spufs_switch_log_read(struct file *file, char __user *buf, | |||
| 2494 | struct spu_context *ctx = SPUFS_I(inode)->i_ctx; | 2494 | struct spu_context *ctx = SPUFS_I(inode)->i_ctx; |
| 2495 | int error = 0, cnt = 0; | 2495 | int error = 0, cnt = 0; |
| 2496 | 2496 | ||
| 2497 | if (!buf || len < 0) | 2497 | if (!buf) |
| 2498 | return -EINVAL; | 2498 | return -EINVAL; |
| 2499 | 2499 | ||
| 2500 | error = spu_acquire(ctx); | 2500 | error = spu_acquire(ctx); |
diff --git a/arch/powerpc/platforms/chrp/Kconfig b/arch/powerpc/platforms/chrp/Kconfig index 37d438bd5b7a..bc0b0efdc5fe 100644 --- a/arch/powerpc/platforms/chrp/Kconfig +++ b/arch/powerpc/platforms/chrp/Kconfig | |||
| @@ -5,6 +5,8 @@ config PPC_CHRP | |||
| 5 | select PPC_I8259 | 5 | select PPC_I8259 |
| 6 | select PPC_INDIRECT_PCI | 6 | select PPC_INDIRECT_PCI |
| 7 | select PPC_RTAS | 7 | select PPC_RTAS |
| 8 | select PPC_RTAS_DAEMON | ||
| 9 | select RTAS_ERROR_LOGGING | ||
| 8 | select PPC_MPC106 | 10 | select PPC_MPC106 |
| 9 | select PPC_UDBG_16550 | 11 | select PPC_UDBG_16550 |
| 10 | select PPC_NATIVE | 12 | select PPC_NATIVE |
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index cd4ad9aea760..8f41685d8f42 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | #include <linux/reboot.h> | 23 | #include <linux/reboot.h> |
| 24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
| 25 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
| 26 | #include <linux/utsrelease.h> | 26 | #include <generated/utsrelease.h> |
| 27 | #include <linux/adb.h> | 27 | #include <linux/adb.h> |
| 28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
| 29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
| @@ -364,19 +364,6 @@ void __init chrp_setup_arch(void) | |||
| 364 | if (ppc_md.progress) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0); | 364 | if (ppc_md.progress) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0); |
| 365 | } | 365 | } |
| 366 | 366 | ||
| 367 | void | ||
| 368 | chrp_event_scan(unsigned long unused) | ||
| 369 | { | ||
| 370 | unsigned char log[1024]; | ||
| 371 | int ret = 0; | ||
| 372 | |||
| 373 | /* XXX: we should loop until the hardware says no more error logs -- Cort */ | ||
| 374 | rtas_call(rtas_token("event-scan"), 4, 1, &ret, 0xffffffff, 0, | ||
| 375 | __pa(log), 1024); | ||
| 376 | mod_timer(&__get_cpu_var(heartbeat_timer), | ||
| 377 | jiffies + event_scan_interval); | ||
| 378 | } | ||
| 379 | |||
| 380 | static void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc) | 367 | static void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc) |
| 381 | { | 368 | { |
| 382 | unsigned int cascade_irq = i8259_irq(); | 369 | unsigned int cascade_irq = i8259_irq(); |
| @@ -568,9 +555,6 @@ void __init chrp_init_IRQ(void) | |||
| 568 | void __init | 555 | void __init |
| 569 | chrp_init2(void) | 556 | chrp_init2(void) |
| 570 | { | 557 | { |
| 571 | struct device_node *device; | ||
| 572 | const unsigned int *p = NULL; | ||
| 573 | |||
| 574 | #ifdef CONFIG_NVRAM | 558 | #ifdef CONFIG_NVRAM |
| 575 | chrp_nvram_init(); | 559 | chrp_nvram_init(); |
| 576 | #endif | 560 | #endif |
| @@ -582,40 +566,6 @@ chrp_init2(void) | |||
| 582 | request_region(0x80,0x10,"dma page reg"); | 566 | request_region(0x80,0x10,"dma page reg"); |
| 583 | request_region(0xc0,0x20,"dma2"); | 567 | request_region(0xc0,0x20,"dma2"); |
| 584 | 568 | ||
| 585 | /* Get the event scan rate for the rtas so we know how | ||
| 586 | * often it expects a heartbeat. -- Cort | ||
| 587 | */ | ||
| 588 | device = of_find_node_by_name(NULL, "rtas"); | ||
| 589 | if (device) | ||
| 590 | p = of_get_property(device, "rtas-event-scan-rate", NULL); | ||
| 591 | if (p && *p) { | ||
| 592 | /* | ||
| 593 | * Arrange to call chrp_event_scan at least *p times | ||
| 594 | * per minute. We use 59 rather than 60 here so that | ||
| 595 | * the rate will be slightly higher than the minimum. | ||
| 596 | * This all assumes we don't do hotplug CPU on any | ||
| 597 | * machine that needs the event scans done. | ||
| 598 | */ | ||
| 599 | unsigned long interval, offset; | ||
| 600 | int cpu, ncpus; | ||
| 601 | struct timer_list *timer; | ||
| 602 | |||
| 603 | interval = HZ * 59 / *p; | ||
| 604 | offset = HZ; | ||
| 605 | ncpus = num_online_cpus(); | ||
| 606 | event_scan_interval = ncpus * interval; | ||
| 607 | for (cpu = 0; cpu < ncpus; ++cpu) { | ||
| 608 | timer = &per_cpu(heartbeat_timer, cpu); | ||
| 609 | setup_timer(timer, chrp_event_scan, 0); | ||
| 610 | timer->expires = jiffies + offset; | ||
| 611 | add_timer_on(timer, cpu); | ||
| 612 | offset += interval; | ||
| 613 | } | ||
| 614 | printk("RTAS Event Scan Rate: %u (%lu jiffies)\n", | ||
| 615 | *p, interval); | ||
| 616 | } | ||
| 617 | of_node_put(device); | ||
| 618 | |||
| 619 | if (ppc_md.progress) | 569 | if (ppc_md.progress) |
| 620 | ppc_md.progress(" Have fun! ", 0x7777); | 570 | ppc_md.progress(" Have fun! ", 0x7777); |
| 621 | } | 571 | } |
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig index 291ac9d8cbee..524d971a1478 100644 --- a/arch/powerpc/platforms/embedded6xx/Kconfig +++ b/arch/powerpc/platforms/embedded6xx/Kconfig | |||
| @@ -90,3 +90,36 @@ config MPC10X_OPENPIC | |||
| 90 | config MPC10X_STORE_GATHERING | 90 | config MPC10X_STORE_GATHERING |
| 91 | bool "Enable MPC10x store gathering" | 91 | bool "Enable MPC10x store gathering" |
| 92 | depends on MPC10X_BRIDGE | 92 | depends on MPC10X_BRIDGE |
| 93 | |||
| 94 | config GAMECUBE_COMMON | ||
| 95 | bool | ||
| 96 | |||
| 97 | config USBGECKO_UDBG | ||
| 98 | bool "USB Gecko udbg console for the Nintendo GameCube/Wii" | ||
| 99 | depends on GAMECUBE_COMMON | ||
| 100 | help | ||
| 101 | If you say yes to this option, support will be included for the | ||
| 102 | USB Gecko adapter as an udbg console. | ||
| 103 | The USB Gecko is a EXI to USB Serial converter that can be plugged | ||
| 104 | into a memcard slot in the Nintendo GameCube/Wii. | ||
| 105 | |||
| 106 | This driver bypasses the EXI layer completely. | ||
| 107 | |||
| 108 | If in doubt, say N here. | ||
| 109 | |||
| 110 | config GAMECUBE | ||
| 111 | bool "Nintendo-GameCube" | ||
| 112 | depends on EMBEDDED6xx | ||
| 113 | select GAMECUBE_COMMON | ||
| 114 | help | ||
| 115 | Select GAMECUBE if configuring for the Nintendo GameCube. | ||
| 116 | More information at: <http://gc-linux.sourceforge.net/> | ||
| 117 | |||
| 118 | config WII | ||
| 119 | bool "Nintendo-Wii" | ||
| 120 | depends on EMBEDDED6xx | ||
| 121 | select GAMECUBE_COMMON | ||
| 122 | help | ||
| 123 | Select WII if configuring for the Nintendo Wii. | ||
| 124 | More information at: <http://gc-linux.sourceforge.net/> | ||
| 125 | |||
diff --git a/arch/powerpc/platforms/embedded6xx/Makefile b/arch/powerpc/platforms/embedded6xx/Makefile index 0773c08bd444..66c23e423f40 100644 --- a/arch/powerpc/platforms/embedded6xx/Makefile +++ b/arch/powerpc/platforms/embedded6xx/Makefile | |||
| @@ -7,3 +7,7 @@ obj-$(CONFIG_STORCENTER) += storcenter.o | |||
| 7 | obj-$(CONFIG_PPC_HOLLY) += holly.o | 7 | obj-$(CONFIG_PPC_HOLLY) += holly.o |
| 8 | obj-$(CONFIG_PPC_PRPMC2800) += prpmc2800.o | 8 | obj-$(CONFIG_PPC_PRPMC2800) += prpmc2800.o |
| 9 | obj-$(CONFIG_PPC_C2K) += c2k.o | 9 | obj-$(CONFIG_PPC_C2K) += c2k.o |
| 10 | obj-$(CONFIG_USBGECKO_UDBG) += usbgecko_udbg.o | ||
| 11 | obj-$(CONFIG_GAMECUBE_COMMON) += flipper-pic.o | ||
| 12 | obj-$(CONFIG_GAMECUBE) += gamecube.o | ||
| 13 | obj-$(CONFIG_WII) += wii.o hlwd-pic.o | ||
diff --git a/arch/powerpc/platforms/embedded6xx/flipper-pic.c b/arch/powerpc/platforms/embedded6xx/flipper-pic.c new file mode 100644 index 000000000000..c278bd3a8fec --- /dev/null +++ b/arch/powerpc/platforms/embedded6xx/flipper-pic.c | |||
| @@ -0,0 +1,263 @@ | |||
| 1 | /* | ||
| 2 | * arch/powerpc/platforms/embedded6xx/flipper-pic.c | ||
| 3 | * | ||
| 4 | * Nintendo GameCube/Wii "Flipper" interrupt controller support. | ||
| 5 | * Copyright (C) 2004-2009 The GameCube Linux Team | ||
| 6 | * Copyright (C) 2007,2008,2009 Albert Herranz | ||
| 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 | ||
| 10 | * as published by the Free Software Foundation; either version 2 | ||
| 11 | * of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | #define DRV_MODULE_NAME "flipper-pic" | ||
| 15 | #define pr_fmt(fmt) DRV_MODULE_NAME ": " fmt | ||
| 16 | |||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/irq.h> | ||
| 20 | #include <linux/of.h> | ||
| 21 | #include <asm/io.h> | ||
| 22 | |||
| 23 | #include "flipper-pic.h" | ||
| 24 | |||
| 25 | #define FLIPPER_NR_IRQS 32 | ||
| 26 | |||
| 27 | /* | ||
| 28 | * Each interrupt has a corresponding bit in both | ||
| 29 | * the Interrupt Cause (ICR) and Interrupt Mask (IMR) registers. | ||
| 30 | * | ||
| 31 | * Enabling/disabling an interrupt line involves setting/clearing | ||
| 32 | * the corresponding bit in IMR. | ||
| 33 | * Except for the RSW interrupt, all interrupts get deasserted automatically | ||
| 34 | * when the source deasserts the interrupt. | ||
| 35 | */ | ||
| 36 | #define FLIPPER_ICR 0x00 | ||
| 37 | #define FLIPPER_ICR_RSS (1<<16) /* reset switch state */ | ||
| 38 | |||
| 39 | #define FLIPPER_IMR 0x04 | ||
| 40 | |||
| 41 | #define FLIPPER_RESET 0x24 | ||
| 42 | |||
| 43 | |||
| 44 | /* | ||
| 45 | * IRQ chip hooks. | ||
| 46 | * | ||
| 47 | */ | ||
| 48 | |||
| 49 | static void flipper_pic_mask_and_ack(unsigned int virq) | ||
| 50 | { | ||
| 51 | int irq = virq_to_hw(virq); | ||
| 52 | void __iomem *io_base = get_irq_chip_data(virq); | ||
| 53 | u32 mask = 1 << irq; | ||
| 54 | |||
| 55 | clrbits32(io_base + FLIPPER_IMR, mask); | ||
| 56 | /* this is at least needed for RSW */ | ||
| 57 | out_be32(io_base + FLIPPER_ICR, mask); | ||
| 58 | } | ||
| 59 | |||
| 60 | static void flipper_pic_ack(unsigned int virq) | ||
| 61 | { | ||
| 62 | int irq = virq_to_hw(virq); | ||
| 63 | void __iomem *io_base = get_irq_chip_data(virq); | ||
| 64 | |||
| 65 | /* this is at least needed for RSW */ | ||
| 66 | out_be32(io_base + FLIPPER_ICR, 1 << irq); | ||
| 67 | } | ||
| 68 | |||
| 69 | static void flipper_pic_mask(unsigned int virq) | ||
| 70 | { | ||
| 71 | int irq = virq_to_hw(virq); | ||
| 72 | void __iomem *io_base = get_irq_chip_data(virq); | ||
| 73 | |||
| 74 | clrbits32(io_base + FLIPPER_IMR, 1 << irq); | ||
| 75 | } | ||
| 76 | |||
| 77 | static void flipper_pic_unmask(unsigned int virq) | ||
| 78 | { | ||
| 79 | int irq = virq_to_hw(virq); | ||
| 80 | void __iomem *io_base = get_irq_chip_data(virq); | ||
| 81 | |||
| 82 | setbits32(io_base + FLIPPER_IMR, 1 << irq); | ||
| 83 | } | ||
| 84 | |||
| 85 | |||
| 86 | static struct irq_chip flipper_pic = { | ||
| 87 | .name = "flipper-pic", | ||
| 88 | .ack = flipper_pic_ack, | ||
| 89 | .mask_ack = flipper_pic_mask_and_ack, | ||
| 90 | .mask = flipper_pic_mask, | ||
| 91 | .unmask = flipper_pic_unmask, | ||
| 92 | }; | ||
| 93 | |||
| 94 | /* | ||
| 95 | * IRQ host hooks. | ||
| 96 | * | ||
| 97 | */ | ||
| 98 | |||
| 99 | static struct irq_host *flipper_irq_host; | ||
| 100 | |||
| 101 | static int flipper_pic_map(struct irq_host *h, unsigned int virq, | ||
| 102 | irq_hw_number_t hwirq) | ||
| 103 | { | ||
| 104 | set_irq_chip_data(virq, h->host_data); | ||
| 105 | irq_to_desc(virq)->status |= IRQ_LEVEL; | ||
| 106 | set_irq_chip_and_handler(virq, &flipper_pic, handle_level_irq); | ||
| 107 | return 0; | ||
| 108 | } | ||
| 109 | |||
| 110 | static void flipper_pic_unmap(struct irq_host *h, unsigned int irq) | ||
| 111 | { | ||
| 112 | set_irq_chip_data(irq, NULL); | ||
| 113 | set_irq_chip(irq, NULL); | ||
| 114 | } | ||
| 115 | |||
| 116 | static int flipper_pic_match(struct irq_host *h, struct device_node *np) | ||
| 117 | { | ||
| 118 | return 1; | ||
| 119 | } | ||
| 120 | |||
| 121 | |||
| 122 | static struct irq_host_ops flipper_irq_host_ops = { | ||
| 123 | .map = flipper_pic_map, | ||
| 124 | .unmap = flipper_pic_unmap, | ||
| 125 | .match = flipper_pic_match, | ||
| 126 | }; | ||
| 127 | |||
| 128 | /* | ||
| 129 | * Platform hooks. | ||
| 130 | * | ||
| 131 | */ | ||
| 132 | |||
| 133 | static void __flipper_quiesce(void __iomem *io_base) | ||
| 134 | { | ||
| 135 | /* mask and ack all IRQs */ | ||
| 136 | out_be32(io_base + FLIPPER_IMR, 0x00000000); | ||
| 137 | out_be32(io_base + FLIPPER_ICR, 0xffffffff); | ||
| 138 | } | ||
| 139 | |||
| 140 | struct irq_host * __init flipper_pic_init(struct device_node *np) | ||
| 141 | { | ||
| 142 | struct device_node *pi; | ||
| 143 | struct irq_host *irq_host = NULL; | ||
| 144 | struct resource res; | ||
| 145 | void __iomem *io_base; | ||
| 146 | int retval; | ||
| 147 | |||
| 148 | pi = of_get_parent(np); | ||
| 149 | if (!pi) { | ||
| 150 | pr_err("no parent found\n"); | ||
| 151 | goto out; | ||
| 152 | } | ||
| 153 | if (!of_device_is_compatible(pi, "nintendo,flipper-pi")) { | ||
| 154 | pr_err("unexpected parent compatible\n"); | ||
| 155 | goto out; | ||
| 156 | } | ||
| 157 | |||
| 158 | retval = of_address_to_resource(pi, 0, &res); | ||
| 159 | if (retval) { | ||
| 160 | pr_err("no io memory range found\n"); | ||
| 161 | goto out; | ||
| 162 | } | ||
| 163 | io_base = ioremap(res.start, resource_size(&res)); | ||
| 164 | |||
| 165 | pr_info("controller at 0x%08x mapped to 0x%p\n", res.start, io_base); | ||
| 166 | |||
| 167 | __flipper_quiesce(io_base); | ||
| 168 | |||
| 169 | irq_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, FLIPPER_NR_IRQS, | ||
| 170 | &flipper_irq_host_ops, -1); | ||
| 171 | if (!irq_host) { | ||
| 172 | pr_err("failed to allocate irq_host\n"); | ||
| 173 | return NULL; | ||
| 174 | } | ||
| 175 | |||
| 176 | irq_host->host_data = io_base; | ||
| 177 | |||
| 178 | out: | ||
| 179 | return irq_host; | ||
| 180 | } | ||
| 181 | |||
| 182 | unsigned int flipper_pic_get_irq(void) | ||
| 183 | { | ||
| 184 | void __iomem *io_base = flipper_irq_host->host_data; | ||
| 185 | int irq; | ||
| 186 | u32 irq_status; | ||
| 187 | |||
| 188 | irq_status = in_be32(io_base + FLIPPER_ICR) & | ||
| 189 | in_be32(io_base + FLIPPER_IMR); | ||
| 190 | if (irq_status == 0) | ||
| 191 | return NO_IRQ; /* no more IRQs pending */ | ||
| 192 | |||
| 193 | irq = __ffs(irq_status); | ||
| 194 | return irq_linear_revmap(flipper_irq_host, irq); | ||
| 195 | } | ||
| 196 | |||
| 197 | /* | ||
| 198 | * Probe function. | ||
| 199 | * | ||
| 200 | */ | ||
| 201 | |||
| 202 | void __init flipper_pic_probe(void) | ||
| 203 | { | ||
| 204 | struct device_node *np; | ||
| 205 | |||
| 206 | np = of_find_compatible_node(NULL, NULL, "nintendo,flipper-pic"); | ||
| 207 | BUG_ON(!np); | ||
| 208 | |||
| 209 | flipper_irq_host = flipper_pic_init(np); | ||
| 210 | BUG_ON(!flipper_irq_host); | ||
| 211 | |||
| 212 | irq_set_default_host(flipper_irq_host); | ||
| 213 | |||
| 214 | of_node_put(np); | ||
| 215 | } | ||
| 216 | |||
| 217 | /* | ||
| 218 | * Misc functions related to the flipper chipset. | ||
| 219 | * | ||
| 220 | */ | ||
| 221 | |||
| 222 | /** | ||
| 223 | * flipper_quiesce() - quiesce flipper irq controller | ||
| 224 | * | ||
| 225 | * Mask and ack all interrupt sources. | ||
| 226 | * | ||
| 227 | */ | ||
| 228 | void flipper_quiesce(void) | ||
| 229 | { | ||
| 230 | void __iomem *io_base = flipper_irq_host->host_data; | ||
| 231 | |||
| 232 | __flipper_quiesce(io_base); | ||
| 233 | } | ||
| 234 | |||
| 235 | /* | ||
| 236 | * Resets the platform. | ||
| 237 | */ | ||
| 238 | void flipper_platform_reset(void) | ||
| 239 | { | ||
| 240 | void __iomem *io_base; | ||
| 241 | |||
| 242 | if (flipper_irq_host && flipper_irq_host->host_data) { | ||
| 243 | io_base = flipper_irq_host->host_data; | ||
| 244 | out_8(io_base + FLIPPER_RESET, 0x00); | ||
| 245 | } | ||
| 246 | } | ||
| 247 | |||
| 248 | /* | ||
| 249 | * Returns non-zero if the reset button is pressed. | ||
| 250 | */ | ||
| 251 | int flipper_is_reset_button_pressed(void) | ||
| 252 | { | ||
| 253 | void __iomem *io_base; | ||
| 254 | u32 icr; | ||
| 255 | |||
| 256 | if (flipper_irq_host && flipper_irq_host->host_data) { | ||
| 257 | io_base = flipper_irq_host->host_data; | ||
| 258 | icr = in_be32(io_base + FLIPPER_ICR); | ||
| 259 | return !(icr & FLIPPER_ICR_RSS); | ||
| 260 | } | ||
| 261 | return 0; | ||
| 262 | } | ||
| 263 | |||
diff --git a/arch/powerpc/platforms/embedded6xx/flipper-pic.h b/arch/powerpc/platforms/embedded6xx/flipper-pic.h new file mode 100644 index 000000000000..e339186b5663 --- /dev/null +++ b/arch/powerpc/platforms/embedded6xx/flipper-pic.h | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | /* | ||
| 2 | * arch/powerpc/platforms/embedded6xx/flipper-pic.h | ||
| 3 | * | ||
| 4 | * Nintendo GameCube/Wii "Flipper" interrupt controller support. | ||
| 5 | * Copyright (C) 2004-2009 The GameCube Linux Team | ||
| 6 | * Copyright (C) 2007,2008,2009 Albert Herranz | ||
| 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 | ||
| 10 | * as published by the Free Software Foundation; either version 2 | ||
| 11 | * of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #ifndef __FLIPPER_PIC_H | ||
| 16 | #define __FLIPPER_PIC_H | ||
| 17 | |||
| 18 | unsigned int flipper_pic_get_irq(void); | ||
| 19 | void __init flipper_pic_probe(void); | ||
| 20 | |||
| 21 | void flipper_quiesce(void); | ||
| 22 | void flipper_platform_reset(void); | ||
| 23 | int flipper_is_reset_button_pressed(void); | ||
| 24 | |||
| 25 | #endif | ||
diff --git a/arch/powerpc/platforms/embedded6xx/gamecube.c b/arch/powerpc/platforms/embedded6xx/gamecube.c new file mode 100644 index 000000000000..1106fd99627f --- /dev/null +++ b/arch/powerpc/platforms/embedded6xx/gamecube.c | |||
| @@ -0,0 +1,118 @@ | |||
| 1 | /* | ||
| 2 | * arch/powerpc/platforms/embedded6xx/gamecube.c | ||
| 3 | * | ||
| 4 | * Nintendo GameCube board-specific support | ||
| 5 | * Copyright (C) 2004-2009 The GameCube Linux Team | ||
| 6 | * Copyright (C) 2007,2008,2009 Albert Herranz | ||
| 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 | ||
| 10 | * as published by the Free Software Foundation; either version 2 | ||
| 11 | * of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/init.h> | ||
| 17 | #include <linux/irq.h> | ||
| 18 | #include <linux/kexec.h> | ||
| 19 | #include <linux/seq_file.h> | ||
| 20 | #include <linux/of_platform.h> | ||
| 21 | |||
| 22 | #include <asm/io.h> | ||
| 23 | #include <asm/machdep.h> | ||
| 24 | #include <asm/prom.h> | ||
| 25 | #include <asm/time.h> | ||
| 26 | #include <asm/udbg.h> | ||
| 27 | |||
| 28 | #include "flipper-pic.h" | ||
| 29 | #include "usbgecko_udbg.h" | ||
| 30 | |||
| 31 | |||
| 32 | static void gamecube_spin(void) | ||
| 33 | { | ||
| 34 | /* spin until power button pressed */ | ||
| 35 | for (;;) | ||
| 36 | cpu_relax(); | ||
| 37 | } | ||
| 38 | |||
| 39 | static void gamecube_restart(char *cmd) | ||
| 40 | { | ||
| 41 | local_irq_disable(); | ||
| 42 | flipper_platform_reset(); | ||
| 43 | gamecube_spin(); | ||
| 44 | } | ||
| 45 | |||
| 46 | static void gamecube_power_off(void) | ||
| 47 | { | ||
| 48 | local_irq_disable(); | ||
| 49 | gamecube_spin(); | ||
| 50 | } | ||
| 51 | |||
| 52 | static void gamecube_halt(void) | ||
| 53 | { | ||
| 54 | gamecube_restart(NULL); | ||
| 55 | } | ||
| 56 | |||
| 57 | static void __init gamecube_init_early(void) | ||
| 58 | { | ||
| 59 | ug_udbg_init(); | ||
| 60 | } | ||
| 61 | |||
| 62 | static int __init gamecube_probe(void) | ||
| 63 | { | ||
| 64 | unsigned long dt_root; | ||
| 65 | |||
| 66 | dt_root = of_get_flat_dt_root(); | ||
| 67 | if (!of_flat_dt_is_compatible(dt_root, "nintendo,gamecube")) | ||
| 68 | return 0; | ||
| 69 | |||
| 70 | return 1; | ||
| 71 | } | ||
| 72 | |||
| 73 | static void gamecube_shutdown(void) | ||
| 74 | { | ||
| 75 | flipper_quiesce(); | ||
| 76 | } | ||
| 77 | |||
| 78 | #ifdef CONFIG_KEXEC | ||
| 79 | static int gamecube_kexec_prepare(struct kimage *image) | ||
| 80 | { | ||
| 81 | return 0; | ||
| 82 | } | ||
| 83 | #endif /* CONFIG_KEXEC */ | ||
| 84 | |||
| 85 | |||
| 86 | define_machine(gamecube) { | ||
| 87 | .name = "gamecube", | ||
| 88 | .probe = gamecube_probe, | ||
| 89 | .init_early = gamecube_init_early, | ||
| 90 | .restart = gamecube_restart, | ||
| 91 | .power_off = gamecube_power_off, | ||
| 92 | .halt = gamecube_halt, | ||
| 93 | .init_IRQ = flipper_pic_probe, | ||
| 94 | .get_irq = flipper_pic_get_irq, | ||
| 95 | .calibrate_decr = generic_calibrate_decr, | ||
| 96 | .progress = udbg_progress, | ||
| 97 | .machine_shutdown = gamecube_shutdown, | ||
| 98 | #ifdef CONFIG_KEXEC | ||
| 99 | .machine_kexec_prepare = gamecube_kexec_prepare, | ||
| 100 | #endif | ||
| 101 | }; | ||
| 102 | |||
| 103 | |||
| 104 | static struct of_device_id gamecube_of_bus[] = { | ||
| 105 | { .compatible = "nintendo,flipper", }, | ||
| 106 | { }, | ||
| 107 | }; | ||
| 108 | |||
| 109 | static int __init gamecube_device_probe(void) | ||
| 110 | { | ||
| 111 | if (!machine_is(gamecube)) | ||
| 112 | return 0; | ||
| 113 | |||
| 114 | of_platform_bus_probe(NULL, gamecube_of_bus, NULL); | ||
| 115 | return 0; | ||
| 116 | } | ||
| 117 | device_initcall(gamecube_device_probe); | ||
| 118 | |||
diff --git a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c new file mode 100644 index 000000000000..a771f91e215b --- /dev/null +++ b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c | |||
| @@ -0,0 +1,241 @@ | |||
| 1 | /* | ||
| 2 | * arch/powerpc/platforms/embedded6xx/hlwd-pic.c | ||
| 3 | * | ||
| 4 | * Nintendo Wii "Hollywood" interrupt controller support. | ||
| 5 | * Copyright (C) 2009 The GameCube Linux Team | ||
| 6 | * Copyright (C) 2009 Albert Herranz | ||
| 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 | ||
| 10 | * as published by the Free Software Foundation; either version 2 | ||
| 11 | * of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | #define DRV_MODULE_NAME "hlwd-pic" | ||
| 15 | #define pr_fmt(fmt) DRV_MODULE_NAME ": " fmt | ||
| 16 | |||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/irq.h> | ||
| 20 | #include <linux/of.h> | ||
| 21 | #include <asm/io.h> | ||
| 22 | |||
| 23 | #include "hlwd-pic.h" | ||
| 24 | |||
| 25 | #define HLWD_NR_IRQS 32 | ||
| 26 | |||
| 27 | /* | ||
| 28 | * Each interrupt has a corresponding bit in both | ||
| 29 | * the Interrupt Cause (ICR) and Interrupt Mask (IMR) registers. | ||
| 30 | * | ||
| 31 | * Enabling/disabling an interrupt line involves asserting/clearing | ||
| 32 | * the corresponding bit in IMR. ACK'ing a request simply involves | ||
| 33 | * asserting the corresponding bit in ICR. | ||
| 34 | */ | ||
| 35 | #define HW_BROADWAY_ICR 0x00 | ||
| 36 | #define HW_BROADWAY_IMR 0x04 | ||
| 37 | |||
| 38 | |||
| 39 | /* | ||
| 40 | * IRQ chip hooks. | ||
| 41 | * | ||
| 42 | */ | ||
| 43 | |||
| 44 | static void hlwd_pic_mask_and_ack(unsigned int virq) | ||
| 45 | { | ||
| 46 | int irq = virq_to_hw(virq); | ||
| 47 | void __iomem *io_base = get_irq_chip_data(virq); | ||
| 48 | u32 mask = 1 << irq; | ||
| 49 | |||
| 50 | clrbits32(io_base + HW_BROADWAY_IMR, mask); | ||
| 51 | out_be32(io_base + HW_BROADWAY_ICR, mask); | ||
| 52 | } | ||
| 53 | |||
| 54 | static void hlwd_pic_ack(unsigned int virq) | ||
| 55 | { | ||
| 56 | int irq = virq_to_hw(virq); | ||
| 57 | void __iomem *io_base = get_irq_chip_data(virq); | ||
| 58 | |||
| 59 | out_be32(io_base + HW_BROADWAY_ICR, 1 << irq); | ||
| 60 | } | ||
| 61 | |||
| 62 | static void hlwd_pic_mask(unsigned int virq) | ||
| 63 | { | ||
| 64 | int irq = virq_to_hw(virq); | ||
| 65 | void __iomem *io_base = get_irq_chip_data(virq); | ||
| 66 | |||
| 67 | clrbits32(io_base + HW_BROADWAY_IMR, 1 << irq); | ||
| 68 | } | ||
| 69 | |||
| 70 | static void hlwd_pic_unmask(unsigned int virq) | ||
| 71 | { | ||
| 72 | int irq = virq_to_hw(virq); | ||
| 73 | void __iomem *io_base = get_irq_chip_data(virq); | ||
| 74 | |||
| 75 | setbits32(io_base + HW_BROADWAY_IMR, 1 << irq); | ||
| 76 | } | ||
| 77 | |||
| 78 | |||
| 79 | static struct irq_chip hlwd_pic = { | ||
| 80 | .name = "hlwd-pic", | ||
| 81 | .ack = hlwd_pic_ack, | ||
| 82 | .mask_ack = hlwd_pic_mask_and_ack, | ||
| 83 | .mask = hlwd_pic_mask, | ||
| 84 | .unmask = hlwd_pic_unmask, | ||
| 85 | }; | ||
| 86 | |||
| 87 | /* | ||
| 88 | * IRQ host hooks. | ||
| 89 | * | ||
| 90 | */ | ||
| 91 | |||
| 92 | static struct irq_host *hlwd_irq_host; | ||
| 93 | |||
| 94 | static int hlwd_pic_map(struct irq_host *h, unsigned int virq, | ||
| 95 | irq_hw_number_t hwirq) | ||
| 96 | { | ||
| 97 | set_irq_chip_data(virq, h->host_data); | ||
| 98 | irq_to_desc(virq)->status |= IRQ_LEVEL; | ||
| 99 | set_irq_chip_and_handler(virq, &hlwd_pic, handle_level_irq); | ||
| 100 | return 0; | ||
| 101 | } | ||
| 102 | |||
| 103 | static void hlwd_pic_unmap(struct irq_host *h, unsigned int irq) | ||
| 104 | { | ||
| 105 | set_irq_chip_data(irq, NULL); | ||
| 106 | set_irq_chip(irq, NULL); | ||
| 107 | } | ||
| 108 | |||
| 109 | static struct irq_host_ops hlwd_irq_host_ops = { | ||
| 110 | .map = hlwd_pic_map, | ||
| 111 | .unmap = hlwd_pic_unmap, | ||
| 112 | }; | ||
| 113 | |||
| 114 | static unsigned int __hlwd_pic_get_irq(struct irq_host *h) | ||
| 115 | { | ||
| 116 | void __iomem *io_base = h->host_data; | ||
| 117 | int irq; | ||
| 118 | u32 irq_status; | ||
| 119 | |||
| 120 | irq_status = in_be32(io_base + HW_BROADWAY_ICR) & | ||
| 121 | in_be32(io_base + HW_BROADWAY_IMR); | ||
| 122 | if (irq_status == 0) | ||
| 123 | return NO_IRQ; /* no more IRQs pending */ | ||
| 124 | |||
| 125 | irq = __ffs(irq_status); | ||
| 126 | return irq_linear_revmap(h, irq); | ||
| 127 | } | ||
| 128 | |||
| 129 | static void hlwd_pic_irq_cascade(unsigned int cascade_virq, | ||
| 130 | struct irq_desc *desc) | ||
| 131 | { | ||
| 132 | struct irq_host *irq_host = get_irq_data(cascade_virq); | ||
| 133 | unsigned int virq; | ||
| 134 | |||
| 135 | raw_spin_lock(&desc->lock); | ||
| 136 | desc->chip->mask(cascade_virq); /* IRQ_LEVEL */ | ||
| 137 | raw_spin_unlock(&desc->lock); | ||
| 138 | |||
| 139 | virq = __hlwd_pic_get_irq(irq_host); | ||
| 140 | if (virq != NO_IRQ) | ||
| 141 | generic_handle_irq(virq); | ||
| 142 | else | ||
| 143 | pr_err("spurious interrupt!\n"); | ||
| 144 | |||
| 145 | raw_spin_lock(&desc->lock); | ||
| 146 | desc->chip->ack(cascade_virq); /* IRQ_LEVEL */ | ||
| 147 | if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) | ||
| 148 | desc->chip->unmask(cascade_virq); | ||
| 149 | raw_spin_unlock(&desc->lock); | ||
| 150 | } | ||
| 151 | |||
| 152 | /* | ||
| 153 | * Platform hooks. | ||
| 154 | * | ||
| 155 | */ | ||
| 156 | |||
| 157 | static void __hlwd_quiesce(void __iomem *io_base) | ||
| 158 | { | ||
| 159 | /* mask and ack all IRQs */ | ||
| 160 | out_be32(io_base + HW_BROADWAY_IMR, 0); | ||
| 161 | out_be32(io_base + HW_BROADWAY_ICR, 0xffffffff); | ||
| 162 | } | ||
| 163 | |||
| 164 | struct irq_host *hlwd_pic_init(struct device_node *np) | ||
| 165 | { | ||
| 166 | struct irq_host *irq_host; | ||
| 167 | struct resource res; | ||
| 168 | void __iomem *io_base; | ||
| 169 | int retval; | ||
| 170 | |||
| 171 | retval = of_address_to_resource(np, 0, &res); | ||
| 172 | if (retval) { | ||
| 173 | pr_err("no io memory range found\n"); | ||
| 174 | return NULL; | ||
| 175 | } | ||
| 176 | io_base = ioremap(res.start, resource_size(&res)); | ||
| 177 | if (!io_base) { | ||
| 178 | pr_err("ioremap failed\n"); | ||
| 179 | return NULL; | ||
| 180 | } | ||
| 181 | |||
| 182 | pr_info("controller at 0x%08x mapped to 0x%p\n", res.start, io_base); | ||
| 183 | |||
| 184 | __hlwd_quiesce(io_base); | ||
| 185 | |||
| 186 | irq_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, HLWD_NR_IRQS, | ||
| 187 | &hlwd_irq_host_ops, -1); | ||
| 188 | if (!irq_host) { | ||
| 189 | pr_err("failed to allocate irq_host\n"); | ||
| 190 | return NULL; | ||
| 191 | } | ||
| 192 | irq_host->host_data = io_base; | ||
| 193 | |||
| 194 | return irq_host; | ||
| 195 | } | ||
| 196 | |||
| 197 | unsigned int hlwd_pic_get_irq(void) | ||
| 198 | { | ||
| 199 | return __hlwd_pic_get_irq(hlwd_irq_host); | ||
| 200 | } | ||
| 201 | |||
| 202 | /* | ||
| 203 | * Probe function. | ||
| 204 | * | ||
| 205 | */ | ||
| 206 | |||
| 207 | void hlwd_pic_probe(void) | ||
| 208 | { | ||
| 209 | struct irq_host *host; | ||
| 210 | struct device_node *np; | ||
| 211 | const u32 *interrupts; | ||
| 212 | int cascade_virq; | ||
| 213 | |||
| 214 | for_each_compatible_node(np, NULL, "nintendo,hollywood-pic") { | ||
| 215 | interrupts = of_get_property(np, "interrupts", NULL); | ||
| 216 | if (interrupts) { | ||
| 217 | host = hlwd_pic_init(np); | ||
| 218 | BUG_ON(!host); | ||
| 219 | cascade_virq = irq_of_parse_and_map(np, 0); | ||
| 220 | set_irq_data(cascade_virq, host); | ||
| 221 | set_irq_chained_handler(cascade_virq, | ||
| 222 | hlwd_pic_irq_cascade); | ||
| 223 | hlwd_irq_host = host; | ||
| 224 | break; | ||
| 225 | } | ||
| 226 | } | ||
| 227 | } | ||
| 228 | |||
| 229 | /** | ||
| 230 | * hlwd_quiesce() - quiesce hollywood irq controller | ||
| 231 | * | ||
| 232 | * Mask and ack all interrupt sources. | ||
| 233 | * | ||
| 234 | */ | ||
| 235 | void hlwd_quiesce(void) | ||
| 236 | { | ||
| 237 | void __iomem *io_base = hlwd_irq_host->host_data; | ||
| 238 | |||
| 239 | __hlwd_quiesce(io_base); | ||
| 240 | } | ||
| 241 | |||
diff --git a/arch/powerpc/platforms/embedded6xx/hlwd-pic.h b/arch/powerpc/platforms/embedded6xx/hlwd-pic.h new file mode 100644 index 000000000000..d2e5a092761e --- /dev/null +++ b/arch/powerpc/platforms/embedded6xx/hlwd-pic.h | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | /* | ||
| 2 | * arch/powerpc/platforms/embedded6xx/hlwd-pic.h | ||
| 3 | * | ||
| 4 | * Nintendo Wii "Hollywood" interrupt controller support. | ||
| 5 | * Copyright (C) 2009 The GameCube Linux Team | ||
| 6 | * Copyright (C) 2009 Albert Herranz | ||
| 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 | ||
| 10 | * as published by the Free Software Foundation; either version 2 | ||
| 11 | * of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #ifndef __HLWD_PIC_H | ||
| 16 | #define __HLWD_PIC_H | ||
| 17 | |||
| 18 | extern unsigned int hlwd_pic_get_irq(void); | ||
| 19 | extern void hlwd_pic_probe(void); | ||
| 20 | extern void hlwd_quiesce(void); | ||
| 21 | |||
| 22 | #endif | ||
diff --git a/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c new file mode 100644 index 000000000000..20a8ed91962e --- /dev/null +++ b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c | |||
| @@ -0,0 +1,328 @@ | |||
| 1 | /* | ||
| 2 | * arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c | ||
| 3 | * | ||
| 4 | * udbg serial input/output routines for the USB Gecko adapter. | ||
| 5 | * Copyright (C) 2008-2009 The GameCube Linux Team | ||
| 6 | * Copyright (C) 2008,2009 Albert Herranz | ||
| 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 | ||
| 10 | * as published by the Free Software Foundation; either version 2 | ||
| 11 | * of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <mm/mmu_decl.h> | ||
| 16 | |||
| 17 | #include <asm/io.h> | ||
| 18 | #include <asm/prom.h> | ||
| 19 | #include <asm/udbg.h> | ||
| 20 | #include <asm/fixmap.h> | ||
| 21 | |||
| 22 | #include "usbgecko_udbg.h" | ||
| 23 | |||
| 24 | |||
| 25 | #define EXI_CLK_32MHZ 5 | ||
| 26 | |||
| 27 | #define EXI_CSR 0x00 | ||
| 28 | #define EXI_CSR_CLKMASK (0x7<<4) | ||
| 29 | #define EXI_CSR_CLK_32MHZ (EXI_CLK_32MHZ<<4) | ||
| 30 | #define EXI_CSR_CSMASK (0x7<<7) | ||
| 31 | #define EXI_CSR_CS_0 (0x1<<7) /* Chip Select 001 */ | ||
| 32 | |||
| 33 | #define EXI_CR 0x0c | ||
| 34 | #define EXI_CR_TSTART (1<<0) | ||
| 35 | #define EXI_CR_WRITE (1<<2) | ||
| 36 | #define EXI_CR_READ_WRITE (2<<2) | ||
| 37 | #define EXI_CR_TLEN(len) (((len)-1)<<4) | ||
| 38 | |||
| 39 | #define EXI_DATA 0x10 | ||
| 40 | |||
| 41 | #define UG_READ_ATTEMPTS 100 | ||
| 42 | #define UG_WRITE_ATTEMPTS 100 | ||
| 43 | |||
| 44 | |||
| 45 | static void __iomem *ug_io_base; | ||
| 46 | |||
| 47 | /* | ||
| 48 | * Performs one input/output transaction between the exi host and the usbgecko. | ||
| 49 | */ | ||
| 50 | static u32 ug_io_transaction(u32 in) | ||
| 51 | { | ||
| 52 | u32 __iomem *csr_reg = ug_io_base + EXI_CSR; | ||
| 53 | u32 __iomem *data_reg = ug_io_base + EXI_DATA; | ||
| 54 | u32 __iomem *cr_reg = ug_io_base + EXI_CR; | ||
| 55 | u32 csr, data, cr; | ||
| 56 | |||
| 57 | /* select */ | ||
| 58 | csr = EXI_CSR_CLK_32MHZ | EXI_CSR_CS_0; | ||
| 59 | out_be32(csr_reg, csr); | ||
| 60 | |||
| 61 | /* read/write */ | ||
| 62 | data = in; | ||
| 63 | out_be32(data_reg, data); | ||
| 64 | cr = EXI_CR_TLEN(2) | EXI_CR_READ_WRITE | EXI_CR_TSTART; | ||
| 65 | out_be32(cr_reg, cr); | ||
| 66 | |||
| 67 | while (in_be32(cr_reg) & EXI_CR_TSTART) | ||
| 68 | barrier(); | ||
| 69 | |||
| 70 | /* deselect */ | ||
| 71 | out_be32(csr_reg, 0); | ||
| 72 | |||
| 73 | /* result */ | ||
| 74 | data = in_be32(data_reg); | ||
| 75 | |||
| 76 | return data; | ||
| 77 | } | ||
| 78 | |||
| 79 | /* | ||
| 80 | * Returns true if an usbgecko adapter is found. | ||
| 81 | */ | ||
| 82 | static int ug_is_adapter_present(void) | ||
| 83 | { | ||
| 84 | if (!ug_io_base) | ||
| 85 | return 0; | ||
| 86 | |||
| 87 | return ug_io_transaction(0x90000000) == 0x04700000; | ||
| 88 | } | ||
| 89 | |||
| 90 | /* | ||
| 91 | * Returns true if the TX fifo is ready for transmission. | ||
| 92 | */ | ||
| 93 | static int ug_is_txfifo_ready(void) | ||
| 94 | { | ||
| 95 | return ug_io_transaction(0xc0000000) & 0x04000000; | ||
| 96 | } | ||
| 97 | |||
| 98 | /* | ||
| 99 | * Tries to transmit a character. | ||
| 100 | * If the TX fifo is not ready the result is undefined. | ||
| 101 | */ | ||
| 102 | static void ug_raw_putc(char ch) | ||
| 103 | { | ||
| 104 | ug_io_transaction(0xb0000000 | (ch << 20)); | ||
| 105 | } | ||
| 106 | |||
| 107 | /* | ||
| 108 | * Transmits a character. | ||
| 109 | * It silently fails if the TX fifo is not ready after a number of retries. | ||
| 110 | */ | ||
| 111 | static void ug_putc(char ch) | ||
| 112 | { | ||
| 113 | int count = UG_WRITE_ATTEMPTS; | ||
| 114 | |||
| 115 | if (!ug_io_base) | ||
| 116 | return; | ||
| 117 | |||
| 118 | if (ch == '\n') | ||
| 119 | ug_putc('\r'); | ||
| 120 | |||
| 121 | while (!ug_is_txfifo_ready() && count--) | ||
| 122 | barrier(); | ||
| 123 | if (count >= 0) | ||
| 124 | ug_raw_putc(ch); | ||
| 125 | } | ||
| 126 | |||
| 127 | /* | ||
| 128 | * Returns true if the RX fifo is ready for transmission. | ||
| 129 | */ | ||
| 130 | static int ug_is_rxfifo_ready(void) | ||
| 131 | { | ||
| 132 | return ug_io_transaction(0xd0000000) & 0x04000000; | ||
| 133 | } | ||
| 134 | |||
| 135 | /* | ||
| 136 | * Tries to receive a character. | ||
| 137 | * If a character is unavailable the function returns -1. | ||
| 138 | */ | ||
| 139 | static int ug_raw_getc(void) | ||
| 140 | { | ||
| 141 | u32 data = ug_io_transaction(0xa0000000); | ||
| 142 | if (data & 0x08000000) | ||
| 143 | return (data >> 16) & 0xff; | ||
| 144 | else | ||
| 145 | return -1; | ||
| 146 | } | ||
| 147 | |||
| 148 | /* | ||
| 149 | * Receives a character. | ||
| 150 | * It fails if the RX fifo is not ready after a number of retries. | ||
| 151 | */ | ||
| 152 | static int ug_getc(void) | ||
| 153 | { | ||
| 154 | int count = UG_READ_ATTEMPTS; | ||
| 155 | |||
| 156 | if (!ug_io_base) | ||
| 157 | return -1; | ||
| 158 | |||
| 159 | while (!ug_is_rxfifo_ready() && count--) | ||
| 160 | barrier(); | ||
| 161 | return ug_raw_getc(); | ||
| 162 | } | ||
| 163 | |||
| 164 | /* | ||
| 165 | * udbg functions. | ||
| 166 | * | ||
| 167 | */ | ||
| 168 | |||
| 169 | /* | ||
| 170 | * Transmits a character. | ||
| 171 | */ | ||
| 172 | void ug_udbg_putc(char ch) | ||
| 173 | { | ||
| 174 | ug_putc(ch); | ||
| 175 | } | ||
| 176 | |||
| 177 | /* | ||
| 178 | * Receives a character. Waits until a character is available. | ||
| 179 | */ | ||
| 180 | static int ug_udbg_getc(void) | ||
| 181 | { | ||
| 182 | int ch; | ||
| 183 | |||
| 184 | while ((ch = ug_getc()) == -1) | ||
| 185 | barrier(); | ||
| 186 | return ch; | ||
| 187 | } | ||
| 188 | |||
| 189 | /* | ||
| 190 | * Receives a character. If a character is not available, returns -1. | ||
| 191 | */ | ||
| 192 | static int ug_udbg_getc_poll(void) | ||
| 193 | { | ||
| 194 | if (!ug_is_rxfifo_ready()) | ||
| 195 | return -1; | ||
| 196 | return ug_getc(); | ||
| 197 | } | ||
| 198 | |||
| 199 | /* | ||
| 200 | * Retrieves and prepares the virtual address needed to access the hardware. | ||
| 201 | */ | ||
| 202 | static void __iomem *ug_udbg_setup_exi_io_base(struct device_node *np) | ||
| 203 | { | ||
| 204 | void __iomem *exi_io_base = NULL; | ||
| 205 | phys_addr_t paddr; | ||
| 206 | const unsigned int *reg; | ||
| 207 | |||
| 208 | reg = of_get_property(np, "reg", NULL); | ||
| 209 | if (reg) { | ||
| 210 | paddr = of_translate_address(np, reg); | ||
| 211 | if (paddr) | ||
| 212 | exi_io_base = ioremap(paddr, reg[1]); | ||
| 213 | } | ||
| 214 | return exi_io_base; | ||
| 215 | } | ||
| 216 | |||
| 217 | /* | ||
| 218 | * Checks if a USB Gecko adapter is inserted in any memory card slot. | ||
| 219 | */ | ||
| 220 | static void __iomem *ug_udbg_probe(void __iomem *exi_io_base) | ||
| 221 | { | ||
| 222 | int i; | ||
| 223 | |||
| 224 | /* look for a usbgecko on memcard slots A and B */ | ||
| 225 | for (i = 0; i < 2; i++) { | ||
| 226 | ug_io_base = exi_io_base + 0x14 * i; | ||
| 227 | if (ug_is_adapter_present()) | ||
| 228 | break; | ||
| 229 | } | ||
| 230 | if (i == 2) | ||
| 231 | ug_io_base = NULL; | ||
| 232 | return ug_io_base; | ||
| 233 | |||
| 234 | } | ||
| 235 | |||
| 236 | /* | ||
| 237 | * USB Gecko udbg support initialization. | ||
| 238 | */ | ||
| 239 | void __init ug_udbg_init(void) | ||
| 240 | { | ||
| 241 | struct device_node *np; | ||
| 242 | void __iomem *exi_io_base; | ||
| 243 | |||
| 244 | if (ug_io_base) | ||
| 245 | udbg_printf("%s: early -> final\n", __func__); | ||
| 246 | |||
| 247 | np = of_find_compatible_node(NULL, NULL, "nintendo,flipper-exi"); | ||
| 248 | if (!np) { | ||
| 249 | udbg_printf("%s: EXI node not found\n", __func__); | ||
| 250 | goto done; | ||
| 251 | } | ||
| 252 | |||
| 253 | exi_io_base = ug_udbg_setup_exi_io_base(np); | ||
| 254 | if (!exi_io_base) { | ||
| 255 | udbg_printf("%s: failed to setup EXI io base\n", __func__); | ||
| 256 | goto done; | ||
| 257 | } | ||
| 258 | |||
| 259 | if (!ug_udbg_probe(exi_io_base)) { | ||
| 260 | udbg_printf("usbgecko_udbg: not found\n"); | ||
| 261 | iounmap(exi_io_base); | ||
| 262 | } else { | ||
| 263 | udbg_putc = ug_udbg_putc; | ||
| 264 | udbg_getc = ug_udbg_getc; | ||
| 265 | udbg_getc_poll = ug_udbg_getc_poll; | ||
| 266 | udbg_printf("usbgecko_udbg: ready\n"); | ||
| 267 | } | ||
| 268 | |||
| 269 | done: | ||
| 270 | if (np) | ||
| 271 | of_node_put(np); | ||
| 272 | return; | ||
| 273 | } | ||
| 274 | |||
| 275 | #ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO | ||
| 276 | |||
| 277 | static phys_addr_t __init ug_early_grab_io_addr(void) | ||
| 278 | { | ||
| 279 | #if defined(CONFIG_GAMECUBE) | ||
| 280 | return 0x0c000000; | ||
| 281 | #elif defined(CONFIG_WII) | ||
| 282 | return 0x0d000000; | ||
| 283 | #else | ||
| 284 | #error Invalid platform for USB Gecko based early debugging. | ||
| 285 | #endif | ||
| 286 | } | ||
| 287 | |||
| 288 | /* | ||
| 289 | * USB Gecko early debug support initialization for udbg. | ||
| 290 | */ | ||
| 291 | void __init udbg_init_usbgecko(void) | ||
| 292 | { | ||
| 293 | void __iomem *early_debug_area; | ||
| 294 | void __iomem *exi_io_base; | ||
| 295 | |||
| 296 | /* | ||
| 297 | * At this point we have a BAT already setup that enables I/O | ||
| 298 | * to the EXI hardware. | ||
| 299 | * | ||
| 300 | * The BAT uses a virtual address range reserved at the fixmap. | ||
| 301 | * This must match the virtual address configured in | ||
| 302 | * head_32.S:setup_usbgecko_bat(). | ||
| 303 | */ | ||
| 304 | early_debug_area = (void __iomem *)__fix_to_virt(FIX_EARLY_DEBUG_BASE); | ||
| 305 | exi_io_base = early_debug_area + 0x00006800; | ||
| 306 | |||
| 307 | /* try to detect a USB Gecko */ | ||
| 308 | if (!ug_udbg_probe(exi_io_base)) | ||
| 309 | return; | ||
| 310 | |||
| 311 | /* we found a USB Gecko, load udbg hooks */ | ||
| 312 | udbg_putc = ug_udbg_putc; | ||
| 313 | udbg_getc = ug_udbg_getc; | ||
| 314 | udbg_getc_poll = ug_udbg_getc_poll; | ||
| 315 | |||
| 316 | /* | ||
| 317 | * Prepare again the same BAT for MMU_init. | ||
| 318 | * This allows udbg I/O to continue working after the MMU is | ||
| 319 | * turned on for real. | ||
| 320 | * It is safe to continue using the same virtual address as it is | ||
| 321 | * a reserved fixmap area. | ||
| 322 | */ | ||
| 323 | setbat(1, (unsigned long)early_debug_area, | ||
| 324 | ug_early_grab_io_addr(), 128*1024, PAGE_KERNEL_NCG); | ||
| 325 | } | ||
| 326 | |||
| 327 | #endif /* CONFIG_PPC_EARLY_DEBUG_USBGECKO */ | ||
| 328 | |||
diff --git a/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h new file mode 100644 index 000000000000..bb6cde4ad764 --- /dev/null +++ b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | /* | ||
| 2 | * arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h | ||
| 3 | * | ||
| 4 | * udbg serial input/output routines for the USB Gecko adapter. | ||
| 5 | * Copyright (C) 2008-2009 The GameCube Linux Team | ||
| 6 | * Copyright (C) 2008,2009 Albert Herranz | ||
| 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 | ||
| 10 | * as published by the Free Software Foundation; either version 2 | ||
| 11 | * of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #ifndef __USBGECKO_UDBG_H | ||
| 16 | #define __USBGECKO_UDBG_H | ||
| 17 | |||
| 18 | #ifdef CONFIG_USBGECKO_UDBG | ||
| 19 | |||
| 20 | extern void __init ug_udbg_init(void); | ||
| 21 | |||
| 22 | #else | ||
| 23 | |||
| 24 | static inline void __init ug_udbg_init(void) | ||
| 25 | { | ||
| 26 | } | ||
| 27 | |||
| 28 | #endif /* CONFIG_USBGECKO_UDBG */ | ||
| 29 | |||
| 30 | void __init udbg_init_usbgecko(void); | ||
| 31 | |||
| 32 | #endif /* __USBGECKO_UDBG_H */ | ||
diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c new file mode 100644 index 000000000000..57e5b608fa1a --- /dev/null +++ b/arch/powerpc/platforms/embedded6xx/wii.c | |||
| @@ -0,0 +1,268 @@ | |||
| 1 | /* | ||
| 2 | * arch/powerpc/platforms/embedded6xx/wii.c | ||
| 3 | * | ||
| 4 | * Nintendo Wii board-specific support | ||
| 5 | * Copyright (C) 2008-2009 The GameCube Linux Team | ||
| 6 | * Copyright (C) 2008,2009 Albert Herranz | ||
| 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 | ||
| 10 | * as published by the Free Software Foundation; either version 2 | ||
| 11 | * of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | #define DRV_MODULE_NAME "wii" | ||
| 15 | #define pr_fmt(fmt) DRV_MODULE_NAME ": " fmt | ||
| 16 | |||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/irq.h> | ||
| 20 | #include <linux/seq_file.h> | ||
| 21 | #include <linux/kexec.h> | ||
| 22 | #include <linux/of_platform.h> | ||
| 23 | #include <linux/lmb.h> | ||
| 24 | #include <mm/mmu_decl.h> | ||
| 25 | |||
| 26 | #include <asm/io.h> | ||
| 27 | #include <asm/machdep.h> | ||
| 28 | #include <asm/prom.h> | ||
| 29 | #include <asm/time.h> | ||
| 30 | #include <asm/udbg.h> | ||
| 31 | |||
| 32 | #include "flipper-pic.h" | ||
| 33 | #include "hlwd-pic.h" | ||
| 34 | #include "usbgecko_udbg.h" | ||
| 35 | |||
| 36 | /* control block */ | ||
| 37 | #define HW_CTRL_COMPATIBLE "nintendo,hollywood-control" | ||
| 38 | |||
| 39 | #define HW_CTRL_RESETS 0x94 | ||
| 40 | #define HW_CTRL_RESETS_SYS (1<<0) | ||
| 41 | |||
| 42 | /* gpio */ | ||
| 43 | #define HW_GPIO_COMPATIBLE "nintendo,hollywood-gpio" | ||
| 44 | |||
| 45 | #define HW_GPIO_BASE(idx) (idx * 0x20) | ||
| 46 | #define HW_GPIO_OUT(idx) (HW_GPIO_BASE(idx) + 0) | ||
| 47 | #define HW_GPIO_DIR(idx) (HW_GPIO_BASE(idx) + 4) | ||
| 48 | |||
| 49 | #define HW_GPIO_SHUTDOWN (1<<1) | ||
| 50 | #define HW_GPIO_SLOT_LED (1<<5) | ||
| 51 | #define HW_GPIO_SENSOR_BAR (1<<8) | ||
| 52 | |||
| 53 | |||
| 54 | static void __iomem *hw_ctrl; | ||
| 55 | static void __iomem *hw_gpio; | ||
| 56 | |||
| 57 | unsigned long wii_hole_start; | ||
| 58 | unsigned long wii_hole_size; | ||
| 59 | |||
| 60 | |||
| 61 | static int __init page_aligned(unsigned long x) | ||
| 62 | { | ||
| 63 | return !(x & (PAGE_SIZE-1)); | ||
| 64 | } | ||
| 65 | |||
| 66 | void __init wii_memory_fixups(void) | ||
| 67 | { | ||
| 68 | struct lmb_property *p = lmb.memory.region; | ||
| 69 | |||
| 70 | /* | ||
| 71 | * This is part of a workaround to allow the use of two | ||
| 72 | * discontiguous RAM ranges on the Wii, even if this is | ||
| 73 | * currently unsupported on 32-bit PowerPC Linux. | ||
| 74 | * | ||
| 75 | * We coealesce the two memory ranges of the Wii into a | ||
| 76 | * single range, then create a reservation for the "hole" | ||
| 77 | * between both ranges. | ||
| 78 | */ | ||
| 79 | |||
| 80 | BUG_ON(lmb.memory.cnt != 2); | ||
| 81 | BUG_ON(!page_aligned(p[0].base) || !page_aligned(p[1].base)); | ||
| 82 | |||
| 83 | p[0].size = _ALIGN_DOWN(p[0].size, PAGE_SIZE); | ||
| 84 | p[1].size = _ALIGN_DOWN(p[1].size, PAGE_SIZE); | ||
| 85 | |||
| 86 | wii_hole_start = p[0].base + p[0].size; | ||
| 87 | wii_hole_size = p[1].base - wii_hole_start; | ||
| 88 | |||
| 89 | pr_info("MEM1: <%08llx %08llx>\n", p[0].base, p[0].size); | ||
| 90 | pr_info("HOLE: <%08lx %08lx>\n", wii_hole_start, wii_hole_size); | ||
| 91 | pr_info("MEM2: <%08llx %08llx>\n", p[1].base, p[1].size); | ||
| 92 | |||
| 93 | p[0].size += wii_hole_size + p[1].size; | ||
| 94 | |||
| 95 | lmb.memory.cnt = 1; | ||
| 96 | lmb_analyze(); | ||
| 97 | |||
| 98 | /* reserve the hole */ | ||
| 99 | lmb_reserve(wii_hole_start, wii_hole_size); | ||
| 100 | |||
| 101 | /* allow ioremapping the address space in the hole */ | ||
| 102 | __allow_ioremap_reserved = 1; | ||
| 103 | } | ||
| 104 | |||
| 105 | unsigned long __init wii_mmu_mapin_mem2(unsigned long top) | ||
| 106 | { | ||
| 107 | unsigned long delta, size, bl; | ||
| 108 | unsigned long max_size = (256<<20); | ||
| 109 | |||
| 110 | /* MEM2 64MB@0x10000000 */ | ||
| 111 | delta = wii_hole_start + wii_hole_size; | ||
| 112 | size = top - delta; | ||
| 113 | for (bl = 128<<10; bl < max_size; bl <<= 1) { | ||
| 114 | if (bl * 2 > size) | ||
| 115 | break; | ||
| 116 | } | ||
| 117 | setbat(4, PAGE_OFFSET+delta, delta, bl, PAGE_KERNEL_X); | ||
| 118 | return delta + bl; | ||
| 119 | } | ||
| 120 | |||
| 121 | static void wii_spin(void) | ||
| 122 | { | ||
| 123 | local_irq_disable(); | ||
| 124 | for (;;) | ||
| 125 | cpu_relax(); | ||
| 126 | } | ||
| 127 | |||
| 128 | static void __iomem *wii_ioremap_hw_regs(char *name, char *compatible) | ||
| 129 | { | ||
| 130 | void __iomem *hw_regs = NULL; | ||
| 131 | struct device_node *np; | ||
| 132 | struct resource res; | ||
| 133 | int error = -ENODEV; | ||
| 134 | |||
| 135 | np = of_find_compatible_node(NULL, NULL, compatible); | ||
| 136 | if (!np) { | ||
| 137 | pr_err("no compatible node found for %s\n", compatible); | ||
| 138 | goto out; | ||
| 139 | } | ||
| 140 | error = of_address_to_resource(np, 0, &res); | ||
| 141 | if (error) { | ||
| 142 | pr_err("no valid reg found for %s\n", np->name); | ||
| 143 | goto out_put; | ||
| 144 | } | ||
| 145 | |||
| 146 | hw_regs = ioremap(res.start, resource_size(&res)); | ||
| 147 | if (hw_regs) { | ||
| 148 | pr_info("%s at 0x%08x mapped to 0x%p\n", name, | ||
| 149 | res.start, hw_regs); | ||
| 150 | } | ||
| 151 | |||
| 152 | out_put: | ||
| 153 | of_node_put(np); | ||
| 154 | out: | ||
| 155 | return hw_regs; | ||
| 156 | } | ||
| 157 | |||
| 158 | static void __init wii_setup_arch(void) | ||
| 159 | { | ||
| 160 | hw_ctrl = wii_ioremap_hw_regs("hw_ctrl", HW_CTRL_COMPATIBLE); | ||
| 161 | hw_gpio = wii_ioremap_hw_regs("hw_gpio", HW_GPIO_COMPATIBLE); | ||
| 162 | if (hw_gpio) { | ||
| 163 | /* turn off the front blue led and IR light */ | ||
| 164 | clrbits32(hw_gpio + HW_GPIO_OUT(0), | ||
| 165 | HW_GPIO_SLOT_LED | HW_GPIO_SENSOR_BAR); | ||
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | static void wii_restart(char *cmd) | ||
| 170 | { | ||
| 171 | local_irq_disable(); | ||
| 172 | |||
| 173 | if (hw_ctrl) { | ||
| 174 | /* clear the system reset pin to cause a reset */ | ||
| 175 | clrbits32(hw_ctrl + HW_CTRL_RESETS, HW_CTRL_RESETS_SYS); | ||
| 176 | } | ||
| 177 | wii_spin(); | ||
| 178 | } | ||
| 179 | |||
| 180 | static void wii_power_off(void) | ||
| 181 | { | ||
| 182 | local_irq_disable(); | ||
| 183 | |||
| 184 | if (hw_gpio) { | ||
| 185 | /* make sure that the poweroff GPIO is configured as output */ | ||
| 186 | setbits32(hw_gpio + HW_GPIO_DIR(1), HW_GPIO_SHUTDOWN); | ||
| 187 | |||
| 188 | /* drive the poweroff GPIO high */ | ||
| 189 | setbits32(hw_gpio + HW_GPIO_OUT(1), HW_GPIO_SHUTDOWN); | ||
| 190 | } | ||
| 191 | wii_spin(); | ||
| 192 | } | ||
| 193 | |||
| 194 | static void wii_halt(void) | ||
| 195 | { | ||
| 196 | if (ppc_md.restart) | ||
| 197 | ppc_md.restart(NULL); | ||
| 198 | wii_spin(); | ||
| 199 | } | ||
| 200 | |||
| 201 | static void __init wii_init_early(void) | ||
| 202 | { | ||
| 203 | ug_udbg_init(); | ||
| 204 | } | ||
| 205 | |||
| 206 | static void __init wii_pic_probe(void) | ||
| 207 | { | ||
| 208 | flipper_pic_probe(); | ||
| 209 | hlwd_pic_probe(); | ||
| 210 | } | ||
| 211 | |||
| 212 | static int __init wii_probe(void) | ||
| 213 | { | ||
| 214 | unsigned long dt_root; | ||
| 215 | |||
| 216 | dt_root = of_get_flat_dt_root(); | ||
| 217 | if (!of_flat_dt_is_compatible(dt_root, "nintendo,wii")) | ||
| 218 | return 0; | ||
| 219 | |||
| 220 | return 1; | ||
| 221 | } | ||
| 222 | |||
| 223 | static void wii_shutdown(void) | ||
| 224 | { | ||
| 225 | hlwd_quiesce(); | ||
| 226 | flipper_quiesce(); | ||
| 227 | } | ||
| 228 | |||
| 229 | #ifdef CONFIG_KEXEC | ||
| 230 | static int wii_machine_kexec_prepare(struct kimage *image) | ||
| 231 | { | ||
| 232 | return 0; | ||
| 233 | } | ||
| 234 | #endif /* CONFIG_KEXEC */ | ||
| 235 | |||
| 236 | define_machine(wii) { | ||
| 237 | .name = "wii", | ||
| 238 | .probe = wii_probe, | ||
| 239 | .init_early = wii_init_early, | ||
| 240 | .setup_arch = wii_setup_arch, | ||
| 241 | .restart = wii_restart, | ||
| 242 | .power_off = wii_power_off, | ||
| 243 | .halt = wii_halt, | ||
| 244 | .init_IRQ = wii_pic_probe, | ||
| 245 | .get_irq = flipper_pic_get_irq, | ||
| 246 | .calibrate_decr = generic_calibrate_decr, | ||
| 247 | .progress = udbg_progress, | ||
| 248 | .machine_shutdown = wii_shutdown, | ||
| 249 | #ifdef CONFIG_KEXEC | ||
| 250 | .machine_kexec_prepare = wii_machine_kexec_prepare, | ||
| 251 | #endif | ||
| 252 | }; | ||
| 253 | |||
| 254 | static struct of_device_id wii_of_bus[] = { | ||
| 255 | { .compatible = "nintendo,hollywood", }, | ||
| 256 | { }, | ||
| 257 | }; | ||
| 258 | |||
| 259 | static int __init wii_device_probe(void) | ||
| 260 | { | ||
| 261 | if (!machine_is(wii)) | ||
| 262 | return 0; | ||
| 263 | |||
| 264 | of_platform_bus_probe(NULL, wii_of_bus, NULL); | ||
| 265 | return 0; | ||
| 266 | } | ||
| 267 | device_initcall(wii_device_probe); | ||
| 268 | |||
diff --git a/arch/powerpc/platforms/iseries/htab.c b/arch/powerpc/platforms/iseries/htab.c index f99c6c4b6985..3ae66ab9d5e7 100644 --- a/arch/powerpc/platforms/iseries/htab.c +++ b/arch/powerpc/platforms/iseries/htab.c | |||
| @@ -19,8 +19,7 @@ | |||
| 19 | 19 | ||
| 20 | #include "call_hpt.h" | 20 | #include "call_hpt.h" |
| 21 | 21 | ||
| 22 | static spinlock_t iSeries_hlocks[64] __cacheline_aligned_in_smp = | 22 | static spinlock_t iSeries_hlocks[64] __cacheline_aligned_in_smp; |
| 23 | { [0 ... 63] = SPIN_LOCK_UNLOCKED}; | ||
| 24 | 23 | ||
| 25 | /* | 24 | /* |
| 26 | * Very primitive algorithm for picking up a lock | 25 | * Very primitive algorithm for picking up a lock |
| @@ -245,6 +244,11 @@ static void iSeries_hpte_invalidate(unsigned long slot, unsigned long va, | |||
| 245 | 244 | ||
| 246 | void __init hpte_init_iSeries(void) | 245 | void __init hpte_init_iSeries(void) |
| 247 | { | 246 | { |
| 247 | int i; | ||
| 248 | |||
| 249 | for (i = 0; i < ARRAY_SIZE(iSeries_hlocks); i++) | ||
| 250 | spin_lock_init(&iSeries_hlocks[i]); | ||
| 251 | |||
| 248 | ppc_md.hpte_invalidate = iSeries_hpte_invalidate; | 252 | ppc_md.hpte_invalidate = iSeries_hpte_invalidate; |
| 249 | ppc_md.hpte_updatepp = iSeries_hpte_updatepp; | 253 | ppc_md.hpte_updatepp = iSeries_hpte_updatepp; |
| 250 | ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp; | 254 | ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp; |
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index 94f444758836..86c4b29eea89 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c | |||
| @@ -214,12 +214,12 @@ void __init iSeries_activate_IRQs() | |||
| 214 | unsigned long flags; | 214 | unsigned long flags; |
| 215 | 215 | ||
| 216 | for_each_irq (irq) { | 216 | for_each_irq (irq) { |
| 217 | struct irq_desc *desc = get_irq_desc(irq); | 217 | struct irq_desc *desc = irq_to_desc(irq); |
| 218 | 218 | ||
| 219 | if (desc && desc->chip && desc->chip->startup) { | 219 | if (desc && desc->chip && desc->chip->startup) { |
| 220 | spin_lock_irqsave(&desc->lock, flags); | 220 | raw_spin_lock_irqsave(&desc->lock, flags); |
| 221 | desc->chip->startup(irq); | 221 | desc->chip->startup(irq); |
| 222 | spin_unlock_irqrestore(&desc->lock, flags); | 222 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| 223 | } | 223 | } |
| 224 | } | 224 | } |
| 225 | } | 225 | } |
| @@ -273,7 +273,7 @@ static void iseries_end_IRQ(unsigned int irq) | |||
| 273 | } | 273 | } |
| 274 | 274 | ||
| 275 | static struct irq_chip iseries_pic = { | 275 | static struct irq_chip iseries_pic = { |
| 276 | .typename = "iSeries irq controller", | 276 | .name = "iSeries irq controller", |
| 277 | .startup = iseries_startup_IRQ, | 277 | .startup = iseries_startup_IRQ, |
| 278 | .shutdown = iseries_shutdown_IRQ, | 278 | .shutdown = iseries_shutdown_IRQ, |
| 279 | .unmask = iseries_enable_IRQ, | 279 | .unmask = iseries_enable_IRQ, |
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index 0d9343df35bc..6617915bcb1a 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c | |||
| @@ -855,59 +855,58 @@ static int mf_get_boot_rtc(struct rtc_time *tm) | |||
| 855 | } | 855 | } |
| 856 | 856 | ||
| 857 | #ifdef CONFIG_PROC_FS | 857 | #ifdef CONFIG_PROC_FS |
| 858 | 858 | static int mf_cmdline_proc_show(struct seq_file *m, void *v) | |
| 859 | static int proc_mf_dump_cmdline(char *page, char **start, off_t off, | ||
| 860 | int count, int *eof, void *data) | ||
| 861 | { | 859 | { |
| 862 | int len; | 860 | char *page, *p; |
| 863 | char *p; | ||
| 864 | struct vsp_cmd_data vsp_cmd; | 861 | struct vsp_cmd_data vsp_cmd; |
| 865 | int rc; | 862 | int rc; |
| 866 | dma_addr_t dma_addr; | 863 | dma_addr_t dma_addr; |
| 867 | 864 | ||
| 868 | /* The HV appears to return no more than 256 bytes of command line */ | 865 | /* The HV appears to return no more than 256 bytes of command line */ |
| 869 | if (off >= 256) | 866 | page = kmalloc(256, GFP_KERNEL); |
| 870 | return 0; | 867 | if (!page) |
| 871 | if ((off + count) > 256) | 868 | return -ENOMEM; |
| 872 | count = 256 - off; | ||
| 873 | 869 | ||
| 874 | dma_addr = iseries_hv_map(page, off + count, DMA_FROM_DEVICE); | 870 | dma_addr = iseries_hv_map(page, 256, DMA_FROM_DEVICE); |
| 875 | if (dma_addr == DMA_ERROR_CODE) | 871 | if (dma_addr == DMA_ERROR_CODE) { |
| 872 | kfree(page); | ||
| 876 | return -ENOMEM; | 873 | return -ENOMEM; |
| 877 | memset(page, 0, off + count); | 874 | } |
| 875 | memset(page, 0, 256); | ||
| 878 | memset(&vsp_cmd, 0, sizeof(vsp_cmd)); | 876 | memset(&vsp_cmd, 0, sizeof(vsp_cmd)); |
| 879 | vsp_cmd.cmd = 33; | 877 | vsp_cmd.cmd = 33; |
| 880 | vsp_cmd.sub_data.kern.token = dma_addr; | 878 | vsp_cmd.sub_data.kern.token = dma_addr; |
| 881 | vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex; | 879 | vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex; |
| 882 | vsp_cmd.sub_data.kern.side = (u64)data; | 880 | vsp_cmd.sub_data.kern.side = (u64)m->private; |
| 883 | vsp_cmd.sub_data.kern.length = off + count; | 881 | vsp_cmd.sub_data.kern.length = 256; |
| 884 | mb(); | 882 | mb(); |
| 885 | rc = signal_vsp_instruction(&vsp_cmd); | 883 | rc = signal_vsp_instruction(&vsp_cmd); |
| 886 | iseries_hv_unmap(dma_addr, off + count, DMA_FROM_DEVICE); | 884 | iseries_hv_unmap(dma_addr, 256, DMA_FROM_DEVICE); |
| 887 | if (rc) | 885 | if (rc) { |
| 886 | kfree(page); | ||
| 888 | return rc; | 887 | return rc; |
| 889 | if (vsp_cmd.result_code != 0) | 888 | } |
| 889 | if (vsp_cmd.result_code != 0) { | ||
| 890 | kfree(page); | ||
| 890 | return -ENOMEM; | 891 | return -ENOMEM; |
| 892 | } | ||
| 891 | p = page; | 893 | p = page; |
| 892 | len = 0; | 894 | while (p - page < 256) { |
| 893 | while (len < (off + count)) { | 895 | if (*p == '\0' || *p == '\n') { |
| 894 | if ((*p == '\0') || (*p == '\n')) { | 896 | *p = '\n'; |
| 895 | if (*p == '\0') | ||
| 896 | *p = '\n'; | ||
| 897 | p++; | ||
| 898 | len++; | ||
| 899 | *eof = 1; | ||
| 900 | break; | 897 | break; |
| 901 | } | 898 | } |
| 902 | p++; | 899 | p++; |
| 903 | len++; | ||
| 904 | } | ||
| 905 | 900 | ||
| 906 | if (len < off) { | ||
| 907 | *eof = 1; | ||
| 908 | len = 0; | ||
| 909 | } | 901 | } |
| 910 | return len; | 902 | seq_write(m, page, p - page); |
| 903 | kfree(page); | ||
| 904 | return 0; | ||
| 905 | } | ||
| 906 | |||
| 907 | static int mf_cmdline_proc_open(struct inode *inode, struct file *file) | ||
| 908 | { | ||
| 909 | return single_open(file, mf_cmdline_proc_show, PDE(inode)->data); | ||
| 911 | } | 910 | } |
| 912 | 911 | ||
| 913 | #if 0 | 912 | #if 0 |
| @@ -962,10 +961,8 @@ static int proc_mf_dump_vmlinux(char *page, char **start, off_t off, | |||
| 962 | } | 961 | } |
| 963 | #endif | 962 | #endif |
| 964 | 963 | ||
| 965 | static int proc_mf_dump_side(char *page, char **start, off_t off, | 964 | static int mf_side_proc_show(struct seq_file *m, void *v) |
| 966 | int count, int *eof, void *data) | ||
| 967 | { | 965 | { |
| 968 | int len; | ||
| 969 | char mf_current_side = ' '; | 966 | char mf_current_side = ' '; |
| 970 | struct vsp_cmd_data vsp_cmd; | 967 | struct vsp_cmd_data vsp_cmd; |
| 971 | 968 | ||
| @@ -989,21 +986,17 @@ static int proc_mf_dump_side(char *page, char **start, off_t off, | |||
| 989 | } | 986 | } |
| 990 | } | 987 | } |
| 991 | 988 | ||
| 992 | len = sprintf(page, "%c\n", mf_current_side); | 989 | seq_printf(m, "%c\n", mf_current_side); |
| 990 | return 0; | ||
| 991 | } | ||
| 993 | 992 | ||
| 994 | if (len <= (off + count)) | 993 | static int mf_side_proc_open(struct inode *inode, struct file *file) |
| 995 | *eof = 1; | 994 | { |
| 996 | *start = page + off; | 995 | return single_open(file, mf_side_proc_show, NULL); |
| 997 | len -= off; | ||
| 998 | if (len > count) | ||
| 999 | len = count; | ||
| 1000 | if (len < 0) | ||
| 1001 | len = 0; | ||
| 1002 | return len; | ||
| 1003 | } | 996 | } |
| 1004 | 997 | ||
| 1005 | static int proc_mf_change_side(struct file *file, const char __user *buffer, | 998 | static ssize_t mf_side_proc_write(struct file *file, const char __user *buffer, |
| 1006 | unsigned long count, void *data) | 999 | size_t count, loff_t *pos) |
| 1007 | { | 1000 | { |
| 1008 | char side; | 1001 | char side; |
| 1009 | u64 newSide; | 1002 | u64 newSide; |
| @@ -1041,6 +1034,15 @@ static int proc_mf_change_side(struct file *file, const char __user *buffer, | |||
| 1041 | return count; | 1034 | return count; |
| 1042 | } | 1035 | } |
| 1043 | 1036 | ||
| 1037 | static const struct file_operations mf_side_proc_fops = { | ||
| 1038 | .owner = THIS_MODULE, | ||
| 1039 | .open = mf_side_proc_open, | ||
| 1040 | .read = seq_read, | ||
| 1041 | .llseek = seq_lseek, | ||
| 1042 | .release = single_release, | ||
| 1043 | .write = mf_side_proc_write, | ||
| 1044 | }; | ||
| 1045 | |||
| 1044 | #if 0 | 1046 | #if 0 |
| 1045 | static void mf_getSrcHistory(char *buffer, int size) | 1047 | static void mf_getSrcHistory(char *buffer, int size) |
| 1046 | { | 1048 | { |
| @@ -1087,8 +1089,7 @@ static void mf_getSrcHistory(char *buffer, int size) | |||
| 1087 | } | 1089 | } |
| 1088 | #endif | 1090 | #endif |
| 1089 | 1091 | ||
| 1090 | static int proc_mf_dump_src(char *page, char **start, off_t off, | 1092 | static int mf_src_proc_show(struct seq_file *m, void *v) |
| 1091 | int count, int *eof, void *data) | ||
| 1092 | { | 1093 | { |
| 1093 | #if 0 | 1094 | #if 0 |
| 1094 | int len; | 1095 | int len; |
| @@ -1109,8 +1110,13 @@ static int proc_mf_dump_src(char *page, char **start, off_t off, | |||
| 1109 | #endif | 1110 | #endif |
| 1110 | } | 1111 | } |
| 1111 | 1112 | ||
| 1112 | static int proc_mf_change_src(struct file *file, const char __user *buffer, | 1113 | static int mf_src_proc_open(struct inode *inode, struct file *file) |
| 1113 | unsigned long count, void *data) | 1114 | { |
| 1115 | return single_open(file, mf_src_proc_show, NULL); | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | static ssize_t mf_src_proc_write(struct file *file, const char __user *buffer, | ||
| 1119 | size_t count, loff_t *pos) | ||
| 1114 | { | 1120 | { |
| 1115 | char stkbuf[10]; | 1121 | char stkbuf[10]; |
| 1116 | 1122 | ||
| @@ -1135,9 +1141,19 @@ static int proc_mf_change_src(struct file *file, const char __user *buffer, | |||
| 1135 | return count; | 1141 | return count; |
| 1136 | } | 1142 | } |
| 1137 | 1143 | ||
| 1138 | static int proc_mf_change_cmdline(struct file *file, const char __user *buffer, | 1144 | static const struct file_operations mf_src_proc_fops = { |
| 1139 | unsigned long count, void *data) | 1145 | .owner = THIS_MODULE, |
| 1146 | .open = mf_src_proc_open, | ||
| 1147 | .read = seq_read, | ||
| 1148 | .llseek = seq_lseek, | ||
| 1149 | .release = single_release, | ||
| 1150 | .write = mf_src_proc_write, | ||
| 1151 | }; | ||
| 1152 | |||
| 1153 | static ssize_t mf_cmdline_proc_write(struct file *file, const char __user *buffer, | ||
| 1154 | size_t count, loff_t *pos) | ||
| 1140 | { | 1155 | { |
| 1156 | void *data = PDE(file->f_path.dentry->d_inode)->data; | ||
| 1141 | struct vsp_cmd_data vsp_cmd; | 1157 | struct vsp_cmd_data vsp_cmd; |
| 1142 | dma_addr_t dma_addr; | 1158 | dma_addr_t dma_addr; |
| 1143 | char *page; | 1159 | char *page; |
| @@ -1172,6 +1188,15 @@ out: | |||
| 1172 | return ret; | 1188 | return ret; |
| 1173 | } | 1189 | } |
| 1174 | 1190 | ||
| 1191 | static const struct file_operations mf_cmdline_proc_fops = { | ||
| 1192 | .owner = THIS_MODULE, | ||
| 1193 | .open = mf_cmdline_proc_open, | ||
| 1194 | .read = seq_read, | ||
| 1195 | .llseek = seq_lseek, | ||
| 1196 | .release = single_release, | ||
| 1197 | .write = mf_cmdline_proc_write, | ||
| 1198 | }; | ||
| 1199 | |||
| 1175 | static ssize_t proc_mf_change_vmlinux(struct file *file, | 1200 | static ssize_t proc_mf_change_vmlinux(struct file *file, |
| 1176 | const char __user *buf, | 1201 | const char __user *buf, |
| 1177 | size_t count, loff_t *ppos) | 1202 | size_t count, loff_t *ppos) |
| @@ -1246,12 +1271,10 @@ static int __init mf_proc_init(void) | |||
| 1246 | if (!mf) | 1271 | if (!mf) |
| 1247 | return 1; | 1272 | return 1; |
| 1248 | 1273 | ||
| 1249 | ent = create_proc_entry("cmdline", S_IFREG|S_IRUSR|S_IWUSR, mf); | 1274 | ent = proc_create_data("cmdline", S_IRUSR|S_IWUSR, mf, |
| 1275 | &mf_cmdline_proc_fops, (void *)(long)i); | ||
| 1250 | if (!ent) | 1276 | if (!ent) |
| 1251 | return 1; | 1277 | return 1; |
| 1252 | ent->data = (void *)(long)i; | ||
| 1253 | ent->read_proc = proc_mf_dump_cmdline; | ||
| 1254 | ent->write_proc = proc_mf_change_cmdline; | ||
| 1255 | 1278 | ||
| 1256 | if (i == 3) /* no vmlinux entry for 'D' */ | 1279 | if (i == 3) /* no vmlinux entry for 'D' */ |
| 1257 | continue; | 1280 | continue; |
| @@ -1263,19 +1286,15 @@ static int __init mf_proc_init(void) | |||
| 1263 | return 1; | 1286 | return 1; |
| 1264 | } | 1287 | } |
| 1265 | 1288 | ||
| 1266 | ent = create_proc_entry("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root); | 1289 | ent = proc_create("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root, |
| 1290 | &mf_side_proc_fops); | ||
| 1267 | if (!ent) | 1291 | if (!ent) |
| 1268 | return 1; | 1292 | return 1; |
| 1269 | ent->data = (void *)0; | ||
| 1270 | ent->read_proc = proc_mf_dump_side; | ||
| 1271 | ent->write_proc = proc_mf_change_side; | ||
| 1272 | 1293 | ||
| 1273 | ent = create_proc_entry("src", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root); | 1294 | ent = proc_create("src", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root, |
| 1295 | &mf_src_proc_fops); | ||
| 1274 | if (!ent) | 1296 | if (!ent) |
| 1275 | return 1; | 1297 | return 1; |
| 1276 | ent->data = (void *)0; | ||
| 1277 | ent->read_proc = proc_mf_dump_src; | ||
| 1278 | ent->write_proc = proc_mf_change_src; | ||
| 1279 | 1298 | ||
| 1280 | return 0; | 1299 | return 0; |
| 1281 | } | 1300 | } |
diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c index 49ff4dc422b7..5aea94f30836 100644 --- a/arch/powerpc/platforms/iseries/viopath.c +++ b/arch/powerpc/platforms/iseries/viopath.c | |||
| @@ -116,7 +116,7 @@ static int proc_viopath_show(struct seq_file *m, void *v) | |||
| 116 | u16 vlanMap; | 116 | u16 vlanMap; |
| 117 | dma_addr_t handle; | 117 | dma_addr_t handle; |
| 118 | HvLpEvent_Rc hvrc; | 118 | HvLpEvent_Rc hvrc; |
| 119 | DECLARE_COMPLETION(done); | 119 | DECLARE_COMPLETION_ONSTACK(done); |
| 120 | struct device_node *node; | 120 | struct device_node *node; |
| 121 | const char *sysid; | 121 | const char *sysid; |
| 122 | 122 | ||
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index a4619347aa7e..242f8095c2df 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c | |||
| @@ -71,7 +71,7 @@ static void pas_restart(char *cmd) | |||
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | #ifdef CONFIG_SMP | 73 | #ifdef CONFIG_SMP |
| 74 | static raw_spinlock_t timebase_lock; | 74 | static arch_spinlock_t timebase_lock; |
| 75 | static unsigned long timebase; | 75 | static unsigned long timebase; |
| 76 | 76 | ||
| 77 | static void __devinit pas_give_timebase(void) | 77 | static void __devinit pas_give_timebase(void) |
| @@ -80,11 +80,11 @@ static void __devinit pas_give_timebase(void) | |||
| 80 | 80 | ||
| 81 | local_irq_save(flags); | 81 | local_irq_save(flags); |
| 82 | hard_irq_disable(); | 82 | hard_irq_disable(); |
| 83 | __raw_spin_lock(&timebase_lock); | 83 | arch_spin_lock(&timebase_lock); |
| 84 | mtspr(SPRN_TBCTL, TBCTL_FREEZE); | 84 | mtspr(SPRN_TBCTL, TBCTL_FREEZE); |
| 85 | isync(); | 85 | isync(); |
| 86 | timebase = get_tb(); | 86 | timebase = get_tb(); |
| 87 | __raw_spin_unlock(&timebase_lock); | 87 | arch_spin_unlock(&timebase_lock); |
| 88 | 88 | ||
| 89 | while (timebase) | 89 | while (timebase) |
| 90 | barrier(); | 90 | barrier(); |
| @@ -97,10 +97,10 @@ static void __devinit pas_take_timebase(void) | |||
| 97 | while (!timebase) | 97 | while (!timebase) |
| 98 | smp_rmb(); | 98 | smp_rmb(); |
| 99 | 99 | ||
| 100 | __raw_spin_lock(&timebase_lock); | 100 | arch_spin_lock(&timebase_lock); |
| 101 | set_tb(timebase >> 32, timebase & 0xffffffff); | 101 | set_tb(timebase >> 32, timebase & 0xffffffff); |
| 102 | timebase = 0; | 102 | timebase = 0; |
| 103 | __raw_spin_unlock(&timebase_lock); | 103 | arch_spin_unlock(&timebase_lock); |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | struct smp_ops_t pas_smp_ops = { | 106 | struct smp_ops_t pas_smp_ops = { |
diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c index cf660916ae0b..9dd789a7370d 100644 --- a/arch/powerpc/platforms/powermac/bootx_init.c +++ b/arch/powerpc/platforms/powermac/bootx_init.c | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
| 13 | #include <linux/string.h> | 13 | #include <linux/string.h> |
| 14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 15 | #include <linux/utsrelease.h> | 15 | #include <generated/utsrelease.h> |
| 16 | #include <asm/sections.h> | 16 | #include <asm/sections.h> |
| 17 | #include <asm/prom.h> | 17 | #include <asm/prom.h> |
| 18 | #include <asm/page.h> | 18 | #include <asm/page.h> |
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index d212006a5b3c..09e827296276 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c | |||
| @@ -152,12 +152,12 @@ static unsigned int pmac_startup_irq(unsigned int virq) | |||
| 152 | unsigned long bit = 1UL << (src & 0x1f); | 152 | unsigned long bit = 1UL << (src & 0x1f); |
| 153 | int i = src >> 5; | 153 | int i = src >> 5; |
| 154 | 154 | ||
| 155 | spin_lock_irqsave(&pmac_pic_lock, flags); | 155 | spin_lock_irqsave(&pmac_pic_lock, flags); |
| 156 | if ((irq_desc[virq].status & IRQ_LEVEL) == 0) | 156 | if ((irq_to_desc(virq)->status & IRQ_LEVEL) == 0) |
| 157 | out_le32(&pmac_irq_hw[i]->ack, bit); | 157 | out_le32(&pmac_irq_hw[i]->ack, bit); |
| 158 | __set_bit(src, ppc_cached_irq_mask); | 158 | __set_bit(src, ppc_cached_irq_mask); |
| 159 | __pmac_set_irq_mask(src, 0); | 159 | __pmac_set_irq_mask(src, 0); |
| 160 | spin_unlock_irqrestore(&pmac_pic_lock, flags); | 160 | spin_unlock_irqrestore(&pmac_pic_lock, flags); |
| 161 | 161 | ||
| 162 | return 0; | 162 | return 0; |
| 163 | } | 163 | } |
| @@ -195,7 +195,7 @@ static int pmac_retrigger(unsigned int virq) | |||
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | static struct irq_chip pmac_pic = { | 197 | static struct irq_chip pmac_pic = { |
| 198 | .typename = " PMAC-PIC ", | 198 | .name = " PMAC-PIC ", |
| 199 | .startup = pmac_startup_irq, | 199 | .startup = pmac_startup_irq, |
| 200 | .mask = pmac_mask_irq, | 200 | .mask = pmac_mask_irq, |
| 201 | .ack = pmac_ack_irq, | 201 | .ack = pmac_ack_irq, |
| @@ -285,7 +285,7 @@ static int pmac_pic_host_match(struct irq_host *h, struct device_node *node) | |||
| 285 | static int pmac_pic_host_map(struct irq_host *h, unsigned int virq, | 285 | static int pmac_pic_host_map(struct irq_host *h, unsigned int virq, |
| 286 | irq_hw_number_t hw) | 286 | irq_hw_number_t hw) |
| 287 | { | 287 | { |
| 288 | struct irq_desc *desc = get_irq_desc(virq); | 288 | struct irq_desc *desc = irq_to_desc(virq); |
| 289 | int level; | 289 | int level; |
| 290 | 290 | ||
| 291 | if (hw >= max_irqs) | 291 | if (hw >= max_irqs) |
| @@ -303,7 +303,7 @@ static int pmac_pic_host_map(struct irq_host *h, unsigned int virq, | |||
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | static int pmac_pic_host_xlate(struct irq_host *h, struct device_node *ct, | 305 | static int pmac_pic_host_xlate(struct irq_host *h, struct device_node *ct, |
| 306 | u32 *intspec, unsigned int intsize, | 306 | const u32 *intspec, unsigned int intsize, |
| 307 | irq_hw_number_t *out_hwirq, | 307 | irq_hw_number_t *out_hwirq, |
| 308 | unsigned int *out_flags) | 308 | unsigned int *out_flags) |
| 309 | 309 | ||
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c index 8ec5ccf76b19..59d9712d7364 100644 --- a/arch/powerpc/platforms/ps3/interrupt.c +++ b/arch/powerpc/platforms/ps3/interrupt.c | |||
| @@ -152,7 +152,7 @@ static void ps3_chip_eoi(unsigned int virq) | |||
| 152 | */ | 152 | */ |
| 153 | 153 | ||
| 154 | static struct irq_chip ps3_irq_chip = { | 154 | static struct irq_chip ps3_irq_chip = { |
| 155 | .typename = "ps3", | 155 | .name = "ps3", |
| 156 | .mask = ps3_chip_mask, | 156 | .mask = ps3_chip_mask, |
| 157 | .unmask = ps3_chip_unmask, | 157 | .unmask = ps3_chip_unmask, |
| 158 | .eoi = ps3_chip_eoi, | 158 | .eoi = ps3_chip_eoi, |
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c index 189a25b80735..e81b028a2a48 100644 --- a/arch/powerpc/platforms/ps3/mm.c +++ b/arch/powerpc/platforms/ps3/mm.c | |||
| @@ -34,7 +34,7 @@ | |||
| 34 | #if defined(DEBUG) | 34 | #if defined(DEBUG) |
| 35 | #define DBG udbg_printf | 35 | #define DBG udbg_printf |
| 36 | #else | 36 | #else |
| 37 | #define DBG pr_debug | 37 | #define DBG pr_devel |
| 38 | #endif | 38 | #endif |
| 39 | 39 | ||
| 40 | enum { | 40 | enum { |
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index f0e6f28427bd..c667f0f02c34 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig | |||
| @@ -2,8 +2,11 @@ config PPC_PSERIES | |||
| 2 | depends on PPC64 && PPC_BOOK3S | 2 | depends on PPC64 && PPC_BOOK3S |
| 3 | bool "IBM pSeries & new (POWER5-based) iSeries" | 3 | bool "IBM pSeries & new (POWER5-based) iSeries" |
| 4 | select MPIC | 4 | select MPIC |
| 5 | select PCI_MSI | ||
| 6 | select XICS | ||
| 5 | select PPC_I8259 | 7 | select PPC_I8259 |
| 6 | select PPC_RTAS | 8 | select PPC_RTAS |
| 9 | select PPC_RTAS_DAEMON | ||
| 7 | select RTAS_ERROR_LOGGING | 10 | select RTAS_ERROR_LOGGING |
| 8 | select PPC_UDBG_16550 | 11 | select PPC_UDBG_16550 |
| 9 | select PPC_NATIVE | 12 | select PPC_NATIVE |
| @@ -59,7 +62,7 @@ config PPC_SMLPAR | |||
| 59 | 62 | ||
| 60 | config CMM | 63 | config CMM |
| 61 | tristate "Collaborative memory management" | 64 | tristate "Collaborative memory management" |
| 62 | depends on PPC_SMLPAR && !CRASH_DUMP | 65 | depends on PPC_SMLPAR |
| 63 | default y | 66 | default y |
| 64 | help | 67 | help |
| 65 | Select this option, if you want to enable the kernel interface | 68 | Select this option, if you want to enable the kernel interface |
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 790c0b872d4f..0ff5174ae4f5 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
| @@ -7,8 +7,8 @@ EXTRA_CFLAGS += -DDEBUG | |||
| 7 | endif | 7 | endif |
| 8 | 8 | ||
| 9 | obj-y := lpar.o hvCall.o nvram.o reconfig.o \ | 9 | obj-y := lpar.o hvCall.o nvram.o reconfig.o \ |
| 10 | setup.o iommu.o ras.o rtasd.o \ | 10 | setup.o iommu.o ras.o \ |
| 11 | firmware.o power.o | 11 | firmware.o power.o dlpar.o |
| 12 | obj-$(CONFIG_SMP) += smp.o | 12 | obj-$(CONFIG_SMP) += smp.o |
| 13 | obj-$(CONFIG_XICS) += xics.o | 13 | obj-$(CONFIG_XICS) += xics.o |
| 14 | obj-$(CONFIG_SCANLOG) += scanlog.o | 14 | obj-$(CONFIG_SCANLOG) += scanlog.o |
diff --git a/arch/powerpc/platforms/pseries/cmm.c b/arch/powerpc/platforms/pseries/cmm.c index 6567439fe78d..a277f2e28dbc 100644 --- a/arch/powerpc/platforms/pseries/cmm.c +++ b/arch/powerpc/platforms/pseries/cmm.c | |||
| @@ -38,19 +38,28 @@ | |||
| 38 | #include <asm/mmu.h> | 38 | #include <asm/mmu.h> |
| 39 | #include <asm/pgalloc.h> | 39 | #include <asm/pgalloc.h> |
| 40 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
| 41 | #include <linux/memory.h> | ||
| 41 | 42 | ||
| 42 | #include "plpar_wrappers.h" | 43 | #include "plpar_wrappers.h" |
| 43 | 44 | ||
| 44 | #define CMM_DRIVER_VERSION "1.0.0" | 45 | #define CMM_DRIVER_VERSION "1.0.0" |
| 45 | #define CMM_DEFAULT_DELAY 1 | 46 | #define CMM_DEFAULT_DELAY 1 |
| 47 | #define CMM_HOTPLUG_DELAY 5 | ||
| 46 | #define CMM_DEBUG 0 | 48 | #define CMM_DEBUG 0 |
| 47 | #define CMM_DISABLE 0 | 49 | #define CMM_DISABLE 0 |
| 48 | #define CMM_OOM_KB 1024 | 50 | #define CMM_OOM_KB 1024 |
| 49 | #define CMM_MIN_MEM_MB 256 | 51 | #define CMM_MIN_MEM_MB 256 |
| 50 | #define KB2PAGES(_p) ((_p)>>(PAGE_SHIFT-10)) | 52 | #define KB2PAGES(_p) ((_p)>>(PAGE_SHIFT-10)) |
| 51 | #define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10)) | 53 | #define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10)) |
| 54 | /* | ||
| 55 | * The priority level tries to ensure that this notifier is called as | ||
| 56 | * late as possible to reduce thrashing in the shared memory pool. | ||
| 57 | */ | ||
| 58 | #define CMM_MEM_HOTPLUG_PRI 1 | ||
| 59 | #define CMM_MEM_ISOLATE_PRI 15 | ||
| 52 | 60 | ||
| 53 | static unsigned int delay = CMM_DEFAULT_DELAY; | 61 | static unsigned int delay = CMM_DEFAULT_DELAY; |
| 62 | static unsigned int hotplug_delay = CMM_HOTPLUG_DELAY; | ||
| 54 | static unsigned int oom_kb = CMM_OOM_KB; | 63 | static unsigned int oom_kb = CMM_OOM_KB; |
| 55 | static unsigned int cmm_debug = CMM_DEBUG; | 64 | static unsigned int cmm_debug = CMM_DEBUG; |
| 56 | static unsigned int cmm_disabled = CMM_DISABLE; | 65 | static unsigned int cmm_disabled = CMM_DISABLE; |
| @@ -65,6 +74,10 @@ MODULE_VERSION(CMM_DRIVER_VERSION); | |||
| 65 | module_param_named(delay, delay, uint, S_IRUGO | S_IWUSR); | 74 | module_param_named(delay, delay, uint, S_IRUGO | S_IWUSR); |
| 66 | MODULE_PARM_DESC(delay, "Delay (in seconds) between polls to query hypervisor paging requests. " | 75 | MODULE_PARM_DESC(delay, "Delay (in seconds) between polls to query hypervisor paging requests. " |
| 67 | "[Default=" __stringify(CMM_DEFAULT_DELAY) "]"); | 76 | "[Default=" __stringify(CMM_DEFAULT_DELAY) "]"); |
| 77 | module_param_named(hotplug_delay, hotplug_delay, uint, S_IRUGO | S_IWUSR); | ||
| 78 | MODULE_PARM_DESC(delay, "Delay (in seconds) after memory hotplug remove " | ||
| 79 | "before loaning resumes. " | ||
| 80 | "[Default=" __stringify(CMM_HOTPLUG_DELAY) "]"); | ||
| 68 | module_param_named(oom_kb, oom_kb, uint, S_IRUGO | S_IWUSR); | 81 | module_param_named(oom_kb, oom_kb, uint, S_IRUGO | S_IWUSR); |
| 69 | MODULE_PARM_DESC(oom_kb, "Amount of memory in kb to free on OOM. " | 82 | MODULE_PARM_DESC(oom_kb, "Amount of memory in kb to free on OOM. " |
| 70 | "[Default=" __stringify(CMM_OOM_KB) "]"); | 83 | "[Default=" __stringify(CMM_OOM_KB) "]"); |
| @@ -92,6 +105,9 @@ static unsigned long oom_freed_pages; | |||
| 92 | static struct cmm_page_array *cmm_page_list; | 105 | static struct cmm_page_array *cmm_page_list; |
| 93 | static DEFINE_SPINLOCK(cmm_lock); | 106 | static DEFINE_SPINLOCK(cmm_lock); |
| 94 | 107 | ||
| 108 | static DEFINE_MUTEX(hotplug_mutex); | ||
| 109 | static int hotplug_occurred; /* protected by the hotplug mutex */ | ||
| 110 | |||
| 95 | static struct task_struct *cmm_thread_ptr; | 111 | static struct task_struct *cmm_thread_ptr; |
| 96 | 112 | ||
| 97 | /** | 113 | /** |
| @@ -110,6 +126,17 @@ static long cmm_alloc_pages(long nr) | |||
| 110 | cmm_dbg("Begin request for %ld pages\n", nr); | 126 | cmm_dbg("Begin request for %ld pages\n", nr); |
| 111 | 127 | ||
| 112 | while (nr) { | 128 | while (nr) { |
| 129 | /* Exit if a hotplug operation is in progress or occurred */ | ||
| 130 | if (mutex_trylock(&hotplug_mutex)) { | ||
| 131 | if (hotplug_occurred) { | ||
| 132 | mutex_unlock(&hotplug_mutex); | ||
| 133 | break; | ||
| 134 | } | ||
| 135 | mutex_unlock(&hotplug_mutex); | ||
| 136 | } else { | ||
| 137 | break; | ||
| 138 | } | ||
| 139 | |||
| 113 | addr = __get_free_page(GFP_NOIO | __GFP_NOWARN | | 140 | addr = __get_free_page(GFP_NOIO | __GFP_NOWARN | |
| 114 | __GFP_NORETRY | __GFP_NOMEMALLOC); | 141 | __GFP_NORETRY | __GFP_NOMEMALLOC); |
| 115 | if (!addr) | 142 | if (!addr) |
| @@ -119,8 +146,9 @@ static long cmm_alloc_pages(long nr) | |||
| 119 | if (!pa || pa->index >= CMM_NR_PAGES) { | 146 | if (!pa || pa->index >= CMM_NR_PAGES) { |
| 120 | /* Need a new page for the page list. */ | 147 | /* Need a new page for the page list. */ |
| 121 | spin_unlock(&cmm_lock); | 148 | spin_unlock(&cmm_lock); |
| 122 | npa = (struct cmm_page_array *)__get_free_page(GFP_NOIO | __GFP_NOWARN | | 149 | npa = (struct cmm_page_array *)__get_free_page( |
| 123 | __GFP_NORETRY | __GFP_NOMEMALLOC); | 150 | GFP_NOIO | __GFP_NOWARN | |
| 151 | __GFP_NORETRY | __GFP_NOMEMALLOC); | ||
| 124 | if (!npa) { | 152 | if (!npa) { |
| 125 | pr_info("%s: Can not allocate new page list\n", __func__); | 153 | pr_info("%s: Can not allocate new page list\n", __func__); |
| 126 | free_page(addr); | 154 | free_page(addr); |
| @@ -229,8 +257,9 @@ static void cmm_get_mpp(void) | |||
| 229 | { | 257 | { |
| 230 | int rc; | 258 | int rc; |
| 231 | struct hvcall_mpp_data mpp_data; | 259 | struct hvcall_mpp_data mpp_data; |
| 232 | unsigned long active_pages_target; | 260 | signed long active_pages_target, page_loan_request, target; |
| 233 | signed long page_loan_request; | 261 | signed long total_pages = totalram_pages + loaned_pages; |
| 262 | signed long min_mem_pages = (min_mem_mb * 1024 * 1024) / PAGE_SIZE; | ||
| 234 | 263 | ||
| 235 | rc = h_get_mpp(&mpp_data); | 264 | rc = h_get_mpp(&mpp_data); |
| 236 | 265 | ||
| @@ -238,17 +267,25 @@ static void cmm_get_mpp(void) | |||
| 238 | return; | 267 | return; |
| 239 | 268 | ||
| 240 | page_loan_request = div_s64((s64)mpp_data.loan_request, PAGE_SIZE); | 269 | page_loan_request = div_s64((s64)mpp_data.loan_request, PAGE_SIZE); |
| 241 | loaned_pages_target = page_loan_request + loaned_pages; | 270 | target = page_loan_request + (signed long)loaned_pages; |
| 242 | if (loaned_pages_target > oom_freed_pages) | 271 | |
| 243 | loaned_pages_target -= oom_freed_pages; | 272 | if (target < 0 || total_pages < min_mem_pages) |
| 273 | target = 0; | ||
| 274 | |||
| 275 | if (target > oom_freed_pages) | ||
| 276 | target -= oom_freed_pages; | ||
| 244 | else | 277 | else |
| 245 | loaned_pages_target = 0; | 278 | target = 0; |
| 279 | |||
| 280 | active_pages_target = total_pages - target; | ||
| 246 | 281 | ||
| 247 | active_pages_target = totalram_pages + loaned_pages - loaned_pages_target; | 282 | if (min_mem_pages > active_pages_target) |
| 283 | target = total_pages - min_mem_pages; | ||
| 248 | 284 | ||
| 249 | if ((min_mem_mb * 1024 * 1024) > (active_pages_target * PAGE_SIZE)) | 285 | if (target < 0) |
| 250 | loaned_pages_target = totalram_pages + loaned_pages - | 286 | target = 0; |
| 251 | ((min_mem_mb * 1024 * 1024) / PAGE_SIZE); | 287 | |
| 288 | loaned_pages_target = target; | ||
| 252 | 289 | ||
| 253 | cmm_dbg("delta = %ld, loaned = %lu, target = %lu, oom = %lu, totalram = %lu\n", | 290 | cmm_dbg("delta = %ld, loaned = %lu, target = %lu, oom = %lu, totalram = %lu\n", |
| 254 | page_loan_request, loaned_pages, loaned_pages_target, | 291 | page_loan_request, loaned_pages, loaned_pages_target, |
| @@ -273,9 +310,28 @@ static int cmm_thread(void *dummy) | |||
| 273 | while (1) { | 310 | while (1) { |
| 274 | timeleft = msleep_interruptible(delay * 1000); | 311 | timeleft = msleep_interruptible(delay * 1000); |
| 275 | 312 | ||
| 276 | if (kthread_should_stop() || timeleft) { | 313 | if (kthread_should_stop() || timeleft) |
| 277 | loaned_pages_target = loaned_pages; | ||
| 278 | break; | 314 | break; |
| 315 | |||
| 316 | if (mutex_trylock(&hotplug_mutex)) { | ||
| 317 | if (hotplug_occurred) { | ||
| 318 | hotplug_occurred = 0; | ||
| 319 | mutex_unlock(&hotplug_mutex); | ||
| 320 | cmm_dbg("Hotplug operation has occurred, " | ||
| 321 | "loaning activity suspended " | ||
| 322 | "for %d seconds.\n", | ||
| 323 | hotplug_delay); | ||
| 324 | timeleft = msleep_interruptible(hotplug_delay * | ||
| 325 | 1000); | ||
| 326 | if (kthread_should_stop() || timeleft) | ||
| 327 | break; | ||
| 328 | continue; | ||
| 329 | } | ||
| 330 | mutex_unlock(&hotplug_mutex); | ||
| 331 | } else { | ||
| 332 | cmm_dbg("Hotplug operation in progress, activity " | ||
| 333 | "suspended\n"); | ||
| 334 | continue; | ||
| 279 | } | 335 | } |
| 280 | 336 | ||
| 281 | cmm_get_mpp(); | 337 | cmm_get_mpp(); |
| @@ -405,6 +461,193 @@ static struct notifier_block cmm_reboot_nb = { | |||
| 405 | }; | 461 | }; |
| 406 | 462 | ||
| 407 | /** | 463 | /** |
| 464 | * cmm_count_pages - Count the number of pages loaned in a particular range. | ||
| 465 | * | ||
| 466 | * @arg: memory_isolate_notify structure with address range and count | ||
| 467 | * | ||
| 468 | * Return value: | ||
| 469 | * 0 on success | ||
| 470 | **/ | ||
| 471 | static unsigned long cmm_count_pages(void *arg) | ||
| 472 | { | ||
| 473 | struct memory_isolate_notify *marg = arg; | ||
| 474 | struct cmm_page_array *pa; | ||
| 475 | unsigned long start = (unsigned long)pfn_to_kaddr(marg->start_pfn); | ||
| 476 | unsigned long end = start + (marg->nr_pages << PAGE_SHIFT); | ||
| 477 | unsigned long idx; | ||
| 478 | |||
| 479 | spin_lock(&cmm_lock); | ||
| 480 | pa = cmm_page_list; | ||
| 481 | while (pa) { | ||
| 482 | if ((unsigned long)pa >= start && (unsigned long)pa < end) | ||
| 483 | marg->pages_found++; | ||
| 484 | for (idx = 0; idx < pa->index; idx++) | ||
| 485 | if (pa->page[idx] >= start && pa->page[idx] < end) | ||
| 486 | marg->pages_found++; | ||
| 487 | pa = pa->next; | ||
| 488 | } | ||
| 489 | spin_unlock(&cmm_lock); | ||
| 490 | return 0; | ||
| 491 | } | ||
| 492 | |||
| 493 | /** | ||
| 494 | * cmm_memory_isolate_cb - Handle memory isolation notifier calls | ||
| 495 | * @self: notifier block struct | ||
| 496 | * @action: action to take | ||
| 497 | * @arg: struct memory_isolate_notify data for handler | ||
| 498 | * | ||
| 499 | * Return value: | ||
| 500 | * NOTIFY_OK or notifier error based on subfunction return value | ||
| 501 | **/ | ||
| 502 | static int cmm_memory_isolate_cb(struct notifier_block *self, | ||
| 503 | unsigned long action, void *arg) | ||
| 504 | { | ||
| 505 | int ret = 0; | ||
| 506 | |||
| 507 | if (action == MEM_ISOLATE_COUNT) | ||
| 508 | ret = cmm_count_pages(arg); | ||
| 509 | |||
| 510 | if (ret) | ||
| 511 | ret = notifier_from_errno(ret); | ||
| 512 | else | ||
| 513 | ret = NOTIFY_OK; | ||
| 514 | |||
| 515 | return ret; | ||
| 516 | } | ||
| 517 | |||
| 518 | static struct notifier_block cmm_mem_isolate_nb = { | ||
| 519 | .notifier_call = cmm_memory_isolate_cb, | ||
| 520 | .priority = CMM_MEM_ISOLATE_PRI | ||
| 521 | }; | ||
| 522 | |||
| 523 | /** | ||
| 524 | * cmm_mem_going_offline - Unloan pages where memory is to be removed | ||
| 525 | * @arg: memory_notify structure with page range to be offlined | ||
| 526 | * | ||
| 527 | * Return value: | ||
| 528 | * 0 on success | ||
| 529 | **/ | ||
| 530 | static int cmm_mem_going_offline(void *arg) | ||
| 531 | { | ||
| 532 | struct memory_notify *marg = arg; | ||
| 533 | unsigned long start_page = (unsigned long)pfn_to_kaddr(marg->start_pfn); | ||
| 534 | unsigned long end_page = start_page + (marg->nr_pages << PAGE_SHIFT); | ||
| 535 | struct cmm_page_array *pa_curr, *pa_last, *npa; | ||
| 536 | unsigned long idx; | ||
| 537 | unsigned long freed = 0; | ||
| 538 | |||
| 539 | cmm_dbg("Memory going offline, searching 0x%lx (%ld pages).\n", | ||
| 540 | start_page, marg->nr_pages); | ||
| 541 | spin_lock(&cmm_lock); | ||
| 542 | |||
| 543 | /* Search the page list for pages in the range to be offlined */ | ||
| 544 | pa_last = pa_curr = cmm_page_list; | ||
| 545 | while (pa_curr) { | ||
| 546 | for (idx = (pa_curr->index - 1); (idx + 1) > 0; idx--) { | ||
| 547 | if ((pa_curr->page[idx] < start_page) || | ||
| 548 | (pa_curr->page[idx] >= end_page)) | ||
| 549 | continue; | ||
| 550 | |||
| 551 | plpar_page_set_active(__pa(pa_curr->page[idx])); | ||
| 552 | free_page(pa_curr->page[idx]); | ||
| 553 | freed++; | ||
| 554 | loaned_pages--; | ||
| 555 | totalram_pages++; | ||
| 556 | pa_curr->page[idx] = pa_last->page[--pa_last->index]; | ||
| 557 | if (pa_last->index == 0) { | ||
| 558 | if (pa_curr == pa_last) | ||
| 559 | pa_curr = pa_last->next; | ||
| 560 | pa_last = pa_last->next; | ||
| 561 | free_page((unsigned long)cmm_page_list); | ||
| 562 | cmm_page_list = pa_last; | ||
| 563 | continue; | ||
| 564 | } | ||
| 565 | } | ||
| 566 | pa_curr = pa_curr->next; | ||
| 567 | } | ||
| 568 | |||
| 569 | /* Search for page list structures in the range to be offlined */ | ||
| 570 | pa_last = NULL; | ||
| 571 | pa_curr = cmm_page_list; | ||
| 572 | while (pa_curr) { | ||
| 573 | if (((unsigned long)pa_curr >= start_page) && | ||
| 574 | ((unsigned long)pa_curr < end_page)) { | ||
| 575 | npa = (struct cmm_page_array *)__get_free_page( | ||
| 576 | GFP_NOIO | __GFP_NOWARN | | ||
| 577 | __GFP_NORETRY | __GFP_NOMEMALLOC); | ||
| 578 | if (!npa) { | ||
| 579 | spin_unlock(&cmm_lock); | ||
| 580 | cmm_dbg("Failed to allocate memory for list " | ||
| 581 | "management. Memory hotplug " | ||
| 582 | "failed.\n"); | ||
| 583 | return ENOMEM; | ||
| 584 | } | ||
| 585 | memcpy(npa, pa_curr, PAGE_SIZE); | ||
| 586 | if (pa_curr == cmm_page_list) | ||
| 587 | cmm_page_list = npa; | ||
| 588 | if (pa_last) | ||
| 589 | pa_last->next = npa; | ||
| 590 | free_page((unsigned long) pa_curr); | ||
| 591 | freed++; | ||
| 592 | pa_curr = npa; | ||
| 593 | } | ||
| 594 | |||
| 595 | pa_last = pa_curr; | ||
| 596 | pa_curr = pa_curr->next; | ||
| 597 | } | ||
| 598 | |||
| 599 | spin_unlock(&cmm_lock); | ||
| 600 | cmm_dbg("Released %ld pages in the search range.\n", freed); | ||
| 601 | |||
| 602 | return 0; | ||
| 603 | } | ||
| 604 | |||
| 605 | /** | ||
| 606 | * cmm_memory_cb - Handle memory hotplug notifier calls | ||
| 607 | * @self: notifier block struct | ||
| 608 | * @action: action to take | ||
| 609 | * @arg: struct memory_notify data for handler | ||
| 610 | * | ||
| 611 | * Return value: | ||
| 612 | * NOTIFY_OK or notifier error based on subfunction return value | ||
| 613 | * | ||
| 614 | **/ | ||
| 615 | static int cmm_memory_cb(struct notifier_block *self, | ||
| 616 | unsigned long action, void *arg) | ||
| 617 | { | ||
| 618 | int ret = 0; | ||
| 619 | |||
| 620 | switch (action) { | ||
| 621 | case MEM_GOING_OFFLINE: | ||
| 622 | mutex_lock(&hotplug_mutex); | ||
| 623 | hotplug_occurred = 1; | ||
| 624 | ret = cmm_mem_going_offline(arg); | ||
| 625 | break; | ||
| 626 | case MEM_OFFLINE: | ||
| 627 | case MEM_CANCEL_OFFLINE: | ||
| 628 | mutex_unlock(&hotplug_mutex); | ||
| 629 | cmm_dbg("Memory offline operation complete.\n"); | ||
| 630 | break; | ||
| 631 | case MEM_GOING_ONLINE: | ||
| 632 | case MEM_ONLINE: | ||
| 633 | case MEM_CANCEL_ONLINE: | ||
| 634 | break; | ||
| 635 | } | ||
| 636 | |||
| 637 | if (ret) | ||
| 638 | ret = notifier_from_errno(ret); | ||
| 639 | else | ||
| 640 | ret = NOTIFY_OK; | ||
| 641 | |||
| 642 | return ret; | ||
| 643 | } | ||
| 644 | |||
| 645 | static struct notifier_block cmm_mem_nb = { | ||
| 646 | .notifier_call = cmm_memory_cb, | ||
| 647 | .priority = CMM_MEM_HOTPLUG_PRI | ||
| 648 | }; | ||
| 649 | |||
| 650 | /** | ||
| 408 | * cmm_init - Module initialization | 651 | * cmm_init - Module initialization |
| 409 | * | 652 | * |
| 410 | * Return value: | 653 | * Return value: |
| @@ -426,18 +669,24 @@ static int cmm_init(void) | |||
| 426 | if ((rc = cmm_sysfs_register(&cmm_sysdev))) | 669 | if ((rc = cmm_sysfs_register(&cmm_sysdev))) |
| 427 | goto out_reboot_notifier; | 670 | goto out_reboot_notifier; |
| 428 | 671 | ||
| 672 | if (register_memory_notifier(&cmm_mem_nb) || | ||
| 673 | register_memory_isolate_notifier(&cmm_mem_isolate_nb)) | ||
| 674 | goto out_unregister_notifier; | ||
| 675 | |||
| 429 | if (cmm_disabled) | 676 | if (cmm_disabled) |
| 430 | return rc; | 677 | return rc; |
| 431 | 678 | ||
| 432 | cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread"); | 679 | cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread"); |
| 433 | if (IS_ERR(cmm_thread_ptr)) { | 680 | if (IS_ERR(cmm_thread_ptr)) { |
| 434 | rc = PTR_ERR(cmm_thread_ptr); | 681 | rc = PTR_ERR(cmm_thread_ptr); |
| 435 | goto out_unregister_sysfs; | 682 | goto out_unregister_notifier; |
| 436 | } | 683 | } |
| 437 | 684 | ||
| 438 | return rc; | 685 | return rc; |
| 439 | 686 | ||
| 440 | out_unregister_sysfs: | 687 | out_unregister_notifier: |
| 688 | unregister_memory_notifier(&cmm_mem_nb); | ||
| 689 | unregister_memory_isolate_notifier(&cmm_mem_isolate_nb); | ||
| 441 | cmm_unregister_sysfs(&cmm_sysdev); | 690 | cmm_unregister_sysfs(&cmm_sysdev); |
| 442 | out_reboot_notifier: | 691 | out_reboot_notifier: |
| 443 | unregister_reboot_notifier(&cmm_reboot_nb); | 692 | unregister_reboot_notifier(&cmm_reboot_nb); |
| @@ -458,6 +707,8 @@ static void cmm_exit(void) | |||
| 458 | kthread_stop(cmm_thread_ptr); | 707 | kthread_stop(cmm_thread_ptr); |
| 459 | unregister_oom_notifier(&cmm_oom_nb); | 708 | unregister_oom_notifier(&cmm_oom_nb); |
| 460 | unregister_reboot_notifier(&cmm_reboot_nb); | 709 | unregister_reboot_notifier(&cmm_reboot_nb); |
| 710 | unregister_memory_notifier(&cmm_mem_nb); | ||
| 711 | unregister_memory_isolate_notifier(&cmm_mem_isolate_nb); | ||
| 461 | cmm_free_pages(loaned_pages); | 712 | cmm_free_pages(loaned_pages); |
| 462 | cmm_unregister_sysfs(&cmm_sysdev); | 713 | cmm_unregister_sysfs(&cmm_sysdev); |
| 463 | } | 714 | } |
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c new file mode 100644 index 000000000000..67b7a10f9fce --- /dev/null +++ b/arch/powerpc/platforms/pseries/dlpar.c | |||
| @@ -0,0 +1,560 @@ | |||
| 1 | /* | ||
| 2 | * Support for dynamic reconfiguration for PCI, Memory, and CPU | ||
| 3 | * Hotplug and Dynamic Logical Partitioning on RPA platforms. | ||
| 4 | * | ||
| 5 | * Copyright (C) 2009 Nathan Fontenot | ||
| 6 | * Copyright (C) 2009 IBM Corporation | ||
| 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/kernel.h> | ||
| 14 | #include <linux/kref.h> | ||
| 15 | #include <linux/notifier.h> | ||
| 16 | #include <linux/proc_fs.h> | ||
| 17 | #include <linux/spinlock.h> | ||
| 18 | #include <linux/cpu.h> | ||
| 19 | #include "offline_states.h" | ||
| 20 | |||
| 21 | #include <asm/prom.h> | ||
| 22 | #include <asm/machdep.h> | ||
| 23 | #include <asm/uaccess.h> | ||
| 24 | #include <asm/rtas.h> | ||
| 25 | #include <asm/pSeries_reconfig.h> | ||
| 26 | |||
| 27 | struct cc_workarea { | ||
| 28 | u32 drc_index; | ||
| 29 | u32 zero; | ||
| 30 | u32 name_offset; | ||
| 31 | u32 prop_length; | ||
| 32 | u32 prop_offset; | ||
| 33 | }; | ||
| 34 | |||
| 35 | static void dlpar_free_cc_property(struct property *prop) | ||
| 36 | { | ||
| 37 | kfree(prop->name); | ||
| 38 | kfree(prop->value); | ||
| 39 | kfree(prop); | ||
| 40 | } | ||
| 41 | |||
| 42 | static struct property *dlpar_parse_cc_property(struct cc_workarea *ccwa) | ||
| 43 | { | ||
| 44 | struct property *prop; | ||
| 45 | char *name; | ||
| 46 | char *value; | ||
| 47 | |||
| 48 | prop = kzalloc(sizeof(*prop), GFP_KERNEL); | ||
| 49 | if (!prop) | ||
| 50 | return NULL; | ||
| 51 | |||
| 52 | name = (char *)ccwa + ccwa->name_offset; | ||
| 53 | prop->name = kstrdup(name, GFP_KERNEL); | ||
| 54 | |||
| 55 | prop->length = ccwa->prop_length; | ||
| 56 | value = (char *)ccwa + ccwa->prop_offset; | ||
| 57 | prop->value = kzalloc(prop->length, GFP_KERNEL); | ||
| 58 | if (!prop->value) { | ||
| 59 | dlpar_free_cc_property(prop); | ||
| 60 | return NULL; | ||
| 61 | } | ||
| 62 | |||
| 63 | memcpy(prop->value, value, prop->length); | ||
| 64 | return prop; | ||
| 65 | } | ||
| 66 | |||
| 67 | static struct device_node *dlpar_parse_cc_node(struct cc_workarea *ccwa) | ||
| 68 | { | ||
| 69 | struct device_node *dn; | ||
| 70 | char *name; | ||
| 71 | |||
| 72 | dn = kzalloc(sizeof(*dn), GFP_KERNEL); | ||
| 73 | if (!dn) | ||
| 74 | return NULL; | ||
| 75 | |||
| 76 | /* The configure connector reported name does not contain a | ||
| 77 | * preceeding '/', so we allocate a buffer large enough to | ||
| 78 | * prepend this to the full_name. | ||
| 79 | */ | ||
| 80 | name = (char *)ccwa + ccwa->name_offset; | ||
| 81 | dn->full_name = kmalloc(strlen(name) + 2, GFP_KERNEL); | ||
| 82 | if (!dn->full_name) { | ||
| 83 | kfree(dn); | ||
| 84 | return NULL; | ||
| 85 | } | ||
| 86 | |||
| 87 | sprintf(dn->full_name, "/%s", name); | ||
| 88 | return dn; | ||
| 89 | } | ||
| 90 | |||
| 91 | static void dlpar_free_one_cc_node(struct device_node *dn) | ||
| 92 | { | ||
| 93 | struct property *prop; | ||
| 94 | |||
| 95 | while (dn->properties) { | ||
| 96 | prop = dn->properties; | ||
| 97 | dn->properties = prop->next; | ||
| 98 | dlpar_free_cc_property(prop); | ||
| 99 | } | ||
| 100 | |||
| 101 | kfree(dn->full_name); | ||
| 102 | kfree(dn); | ||
| 103 | } | ||
| 104 | |||
| 105 | static void dlpar_free_cc_nodes(struct device_node *dn) | ||
| 106 | { | ||
| 107 | if (dn->child) | ||
| 108 | dlpar_free_cc_nodes(dn->child); | ||
| 109 | |||
| 110 | if (dn->sibling) | ||
| 111 | dlpar_free_cc_nodes(dn->sibling); | ||
| 112 | |||
| 113 | dlpar_free_one_cc_node(dn); | ||
| 114 | } | ||
| 115 | |||
| 116 | #define NEXT_SIBLING 1 | ||
| 117 | #define NEXT_CHILD 2 | ||
| 118 | #define NEXT_PROPERTY 3 | ||
| 119 | #define PREV_PARENT 4 | ||
| 120 | #define MORE_MEMORY 5 | ||
| 121 | #define CALL_AGAIN -2 | ||
| 122 | #define ERR_CFG_USE -9003 | ||
| 123 | |||
| 124 | struct device_node *dlpar_configure_connector(u32 drc_index) | ||
| 125 | { | ||
| 126 | struct device_node *dn; | ||
| 127 | struct device_node *first_dn = NULL; | ||
| 128 | struct device_node *last_dn = NULL; | ||
| 129 | struct property *property; | ||
| 130 | struct property *last_property = NULL; | ||
| 131 | struct cc_workarea *ccwa; | ||
| 132 | int cc_token; | ||
| 133 | int rc; | ||
| 134 | |||
| 135 | cc_token = rtas_token("ibm,configure-connector"); | ||
| 136 | if (cc_token == RTAS_UNKNOWN_SERVICE) | ||
| 137 | return NULL; | ||
| 138 | |||
| 139 | spin_lock(&rtas_data_buf_lock); | ||
| 140 | ccwa = (struct cc_workarea *)&rtas_data_buf[0]; | ||
| 141 | ccwa->drc_index = drc_index; | ||
| 142 | ccwa->zero = 0; | ||
| 143 | |||
| 144 | rc = rtas_call(cc_token, 2, 1, NULL, rtas_data_buf, NULL); | ||
| 145 | while (rc) { | ||
| 146 | switch (rc) { | ||
| 147 | case NEXT_SIBLING: | ||
| 148 | dn = dlpar_parse_cc_node(ccwa); | ||
| 149 | if (!dn) | ||
| 150 | goto cc_error; | ||
| 151 | |||
| 152 | dn->parent = last_dn->parent; | ||
| 153 | last_dn->sibling = dn; | ||
| 154 | last_dn = dn; | ||
| 155 | break; | ||
| 156 | |||
| 157 | case NEXT_CHILD: | ||
| 158 | dn = dlpar_parse_cc_node(ccwa); | ||
| 159 | if (!dn) | ||
| 160 | goto cc_error; | ||
| 161 | |||
| 162 | if (!first_dn) | ||
| 163 | first_dn = dn; | ||
| 164 | else { | ||
| 165 | dn->parent = last_dn; | ||
| 166 | if (last_dn) | ||
| 167 | last_dn->child = dn; | ||
| 168 | } | ||
| 169 | |||
| 170 | last_dn = dn; | ||
| 171 | break; | ||
| 172 | |||
| 173 | case NEXT_PROPERTY: | ||
| 174 | property = dlpar_parse_cc_property(ccwa); | ||
| 175 | if (!property) | ||
| 176 | goto cc_error; | ||
| 177 | |||
| 178 | if (!last_dn->properties) | ||
| 179 | last_dn->properties = property; | ||
| 180 | else | ||
| 181 | last_property->next = property; | ||
| 182 | |||
| 183 | last_property = property; | ||
| 184 | break; | ||
| 185 | |||
| 186 | case PREV_PARENT: | ||
| 187 | last_dn = last_dn->parent; | ||
| 188 | break; | ||
| 189 | |||
| 190 | case CALL_AGAIN: | ||
| 191 | break; | ||
| 192 | |||
| 193 | case MORE_MEMORY: | ||
| 194 | case ERR_CFG_USE: | ||
| 195 | default: | ||
| 196 | printk(KERN_ERR "Unexpected Error (%d) " | ||
| 197 | "returned from configure-connector\n", rc); | ||
| 198 | goto cc_error; | ||
| 199 | } | ||
| 200 | |||
| 201 | rc = rtas_call(cc_token, 2, 1, NULL, rtas_data_buf, NULL); | ||
| 202 | } | ||
| 203 | |||
| 204 | spin_unlock(&rtas_data_buf_lock); | ||
| 205 | return first_dn; | ||
| 206 | |||
| 207 | cc_error: | ||
| 208 | if (first_dn) | ||
| 209 | dlpar_free_cc_nodes(first_dn); | ||
| 210 | spin_unlock(&rtas_data_buf_lock); | ||
| 211 | return NULL; | ||
| 212 | } | ||
| 213 | |||
| 214 | static struct device_node *derive_parent(const char *path) | ||
| 215 | { | ||
| 216 | struct device_node *parent; | ||
| 217 | char *last_slash; | ||
| 218 | |||
| 219 | last_slash = strrchr(path, '/'); | ||
| 220 | if (last_slash == path) { | ||
| 221 | parent = of_find_node_by_path("/"); | ||
| 222 | } else { | ||
| 223 | char *parent_path; | ||
| 224 | int parent_path_len = last_slash - path + 1; | ||
| 225 | parent_path = kmalloc(parent_path_len, GFP_KERNEL); | ||
| 226 | if (!parent_path) | ||
| 227 | return NULL; | ||
| 228 | |||
| 229 | strlcpy(parent_path, path, parent_path_len); | ||
| 230 | parent = of_find_node_by_path(parent_path); | ||
| 231 | kfree(parent_path); | ||
| 232 | } | ||
| 233 | |||
| 234 | return parent; | ||
| 235 | } | ||
| 236 | |||
| 237 | int dlpar_attach_node(struct device_node *dn) | ||
| 238 | { | ||
| 239 | struct proc_dir_entry *ent; | ||
| 240 | int rc; | ||
| 241 | |||
| 242 | of_node_set_flag(dn, OF_DYNAMIC); | ||
| 243 | kref_init(&dn->kref); | ||
| 244 | dn->parent = derive_parent(dn->full_name); | ||
| 245 | if (!dn->parent) | ||
| 246 | return -ENOMEM; | ||
| 247 | |||
| 248 | rc = blocking_notifier_call_chain(&pSeries_reconfig_chain, | ||
| 249 | PSERIES_RECONFIG_ADD, dn); | ||
| 250 | if (rc == NOTIFY_BAD) { | ||
| 251 | printk(KERN_ERR "Failed to add device node %s\n", | ||
| 252 | dn->full_name); | ||
| 253 | return -ENOMEM; /* For now, safe to assume kmalloc failure */ | ||
| 254 | } | ||
| 255 | |||
| 256 | of_attach_node(dn); | ||
| 257 | |||
| 258 | #ifdef CONFIG_PROC_DEVICETREE | ||
| 259 | ent = proc_mkdir(strrchr(dn->full_name, '/') + 1, dn->parent->pde); | ||
| 260 | if (ent) | ||
| 261 | proc_device_tree_add_node(dn, ent); | ||
| 262 | #endif | ||
| 263 | |||
| 264 | of_node_put(dn->parent); | ||
| 265 | return 0; | ||
| 266 | } | ||
| 267 | |||
| 268 | int dlpar_detach_node(struct device_node *dn) | ||
| 269 | { | ||
| 270 | struct device_node *parent = dn->parent; | ||
| 271 | struct property *prop = dn->properties; | ||
| 272 | |||
| 273 | #ifdef CONFIG_PROC_DEVICETREE | ||
| 274 | while (prop) { | ||
| 275 | remove_proc_entry(prop->name, dn->pde); | ||
| 276 | prop = prop->next; | ||
| 277 | } | ||
| 278 | |||
| 279 | if (dn->pde) | ||
| 280 | remove_proc_entry(dn->pde->name, parent->pde); | ||
| 281 | #endif | ||
| 282 | |||
| 283 | blocking_notifier_call_chain(&pSeries_reconfig_chain, | ||
| 284 | PSERIES_RECONFIG_REMOVE, dn); | ||
| 285 | of_detach_node(dn); | ||
| 286 | of_node_put(dn); /* Must decrement the refcount */ | ||
| 287 | |||
| 288 | return 0; | ||
| 289 | } | ||
| 290 | |||
| 291 | #define DR_ENTITY_SENSE 9003 | ||
| 292 | #define DR_ENTITY_PRESENT 1 | ||
| 293 | #define DR_ENTITY_UNUSABLE 2 | ||
| 294 | #define ALLOCATION_STATE 9003 | ||
| 295 | #define ALLOC_UNUSABLE 0 | ||
| 296 | #define ALLOC_USABLE 1 | ||
| 297 | #define ISOLATION_STATE 9001 | ||
| 298 | #define ISOLATE 0 | ||
| 299 | #define UNISOLATE 1 | ||
| 300 | |||
| 301 | int dlpar_acquire_drc(u32 drc_index) | ||
| 302 | { | ||
| 303 | int dr_status, rc; | ||
| 304 | |||
| 305 | rc = rtas_call(rtas_token("get-sensor-state"), 2, 2, &dr_status, | ||
| 306 | DR_ENTITY_SENSE, drc_index); | ||
| 307 | if (rc || dr_status != DR_ENTITY_UNUSABLE) | ||
| 308 | return -1; | ||
| 309 | |||
| 310 | rc = rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_USABLE); | ||
| 311 | if (rc) | ||
| 312 | return rc; | ||
| 313 | |||
| 314 | rc = rtas_set_indicator(ISOLATION_STATE, drc_index, UNISOLATE); | ||
| 315 | if (rc) { | ||
| 316 | rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_UNUSABLE); | ||
| 317 | return rc; | ||
| 318 | } | ||
| 319 | |||
| 320 | return 0; | ||
| 321 | } | ||
| 322 | |||
| 323 | int dlpar_release_drc(u32 drc_index) | ||
| 324 | { | ||
| 325 | int dr_status, rc; | ||
| 326 | |||
| 327 | rc = rtas_call(rtas_token("get-sensor-state"), 2, 2, &dr_status, | ||
| 328 | DR_ENTITY_SENSE, drc_index); | ||
| 329 | if (rc || dr_status != DR_ENTITY_PRESENT) | ||
| 330 | return -1; | ||
| 331 | |||
| 332 | rc = rtas_set_indicator(ISOLATION_STATE, drc_index, ISOLATE); | ||
| 333 | if (rc) | ||
| 334 | return rc; | ||
| 335 | |||
| 336 | rc = rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_UNUSABLE); | ||
| 337 | if (rc) { | ||
| 338 | rtas_set_indicator(ISOLATION_STATE, drc_index, UNISOLATE); | ||
| 339 | return rc; | ||
| 340 | } | ||
| 341 | |||
| 342 | return 0; | ||
| 343 | } | ||
| 344 | |||
| 345 | #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE | ||
| 346 | |||
| 347 | static DEFINE_MUTEX(pseries_cpu_hotplug_mutex); | ||
| 348 | |||
| 349 | void cpu_hotplug_driver_lock(void) | ||
| 350 | __acquires(pseries_cpu_hotplug_mutex) | ||
| 351 | { | ||
| 352 | mutex_lock(&pseries_cpu_hotplug_mutex); | ||
| 353 | } | ||
| 354 | |||
| 355 | void cpu_hotplug_driver_unlock(void) | ||
| 356 | __releases(pseries_cpu_hotplug_mutex) | ||
| 357 | { | ||
| 358 | mutex_unlock(&pseries_cpu_hotplug_mutex); | ||
| 359 | } | ||
| 360 | |||
| 361 | static int dlpar_online_cpu(struct device_node *dn) | ||
| 362 | { | ||
| 363 | int rc = 0; | ||
| 364 | unsigned int cpu; | ||
| 365 | int len, nthreads, i; | ||
| 366 | const u32 *intserv; | ||
| 367 | |||
| 368 | intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", &len); | ||
| 369 | if (!intserv) | ||
| 370 | return -EINVAL; | ||
| 371 | |||
| 372 | nthreads = len / sizeof(u32); | ||
| 373 | |||
| 374 | cpu_maps_update_begin(); | ||
| 375 | for (i = 0; i < nthreads; i++) { | ||
| 376 | for_each_present_cpu(cpu) { | ||
| 377 | if (get_hard_smp_processor_id(cpu) != intserv[i]) | ||
| 378 | continue; | ||
| 379 | BUG_ON(get_cpu_current_state(cpu) | ||
| 380 | != CPU_STATE_OFFLINE); | ||
| 381 | cpu_maps_update_done(); | ||
| 382 | rc = cpu_up(cpu); | ||
| 383 | if (rc) | ||
| 384 | goto out; | ||
| 385 | cpu_maps_update_begin(); | ||
| 386 | |||
| 387 | break; | ||
| 388 | } | ||
| 389 | if (cpu == num_possible_cpus()) | ||
| 390 | printk(KERN_WARNING "Could not find cpu to online " | ||
| 391 | "with physical id 0x%x\n", intserv[i]); | ||
| 392 | } | ||
| 393 | cpu_maps_update_done(); | ||
| 394 | |||
| 395 | out: | ||
| 396 | return rc; | ||
| 397 | |||
| 398 | } | ||
| 399 | |||
| 400 | static ssize_t dlpar_cpu_probe(const char *buf, size_t count) | ||
| 401 | { | ||
| 402 | struct device_node *dn; | ||
| 403 | unsigned long drc_index; | ||
| 404 | char *cpu_name; | ||
| 405 | int rc; | ||
| 406 | |||
| 407 | cpu_hotplug_driver_lock(); | ||
| 408 | rc = strict_strtoul(buf, 0, &drc_index); | ||
| 409 | if (rc) { | ||
| 410 | rc = -EINVAL; | ||
| 411 | goto out; | ||
| 412 | } | ||
| 413 | |||
| 414 | dn = dlpar_configure_connector(drc_index); | ||
| 415 | if (!dn) { | ||
| 416 | rc = -EINVAL; | ||
| 417 | goto out; | ||
| 418 | } | ||
| 419 | |||
| 420 | /* configure-connector reports cpus as living in the base | ||
| 421 | * directory of the device tree. CPUs actually live in the | ||
| 422 | * cpus directory so we need to fixup the full_name. | ||
| 423 | */ | ||
| 424 | cpu_name = kzalloc(strlen(dn->full_name) + strlen("/cpus") + 1, | ||
| 425 | GFP_KERNEL); | ||
| 426 | if (!cpu_name) { | ||
| 427 | dlpar_free_cc_nodes(dn); | ||
| 428 | rc = -ENOMEM; | ||
| 429 | goto out; | ||
| 430 | } | ||
| 431 | |||
| 432 | sprintf(cpu_name, "/cpus%s", dn->full_name); | ||
| 433 | kfree(dn->full_name); | ||
| 434 | dn->full_name = cpu_name; | ||
| 435 | |||
| 436 | rc = dlpar_acquire_drc(drc_index); | ||
| 437 | if (rc) { | ||
| 438 | dlpar_free_cc_nodes(dn); | ||
| 439 | rc = -EINVAL; | ||
| 440 | goto out; | ||
| 441 | } | ||
| 442 | |||
| 443 | rc = dlpar_attach_node(dn); | ||
| 444 | if (rc) { | ||
| 445 | dlpar_release_drc(drc_index); | ||
| 446 | dlpar_free_cc_nodes(dn); | ||
| 447 | } | ||
| 448 | |||
| 449 | rc = dlpar_online_cpu(dn); | ||
| 450 | out: | ||
| 451 | cpu_hotplug_driver_unlock(); | ||
| 452 | |||
| 453 | return rc ? rc : count; | ||
| 454 | } | ||
| 455 | |||
| 456 | static int dlpar_offline_cpu(struct device_node *dn) | ||
| 457 | { | ||
| 458 | int rc = 0; | ||
| 459 | unsigned int cpu; | ||
| 460 | int len, nthreads, i; | ||
| 461 | const u32 *intserv; | ||
| 462 | |||
| 463 | intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", &len); | ||
| 464 | if (!intserv) | ||
| 465 | return -EINVAL; | ||
| 466 | |||
| 467 | nthreads = len / sizeof(u32); | ||
| 468 | |||
| 469 | cpu_maps_update_begin(); | ||
| 470 | for (i = 0; i < nthreads; i++) { | ||
| 471 | for_each_present_cpu(cpu) { | ||
| 472 | if (get_hard_smp_processor_id(cpu) != intserv[i]) | ||
| 473 | continue; | ||
| 474 | |||
| 475 | if (get_cpu_current_state(cpu) == CPU_STATE_OFFLINE) | ||
| 476 | break; | ||
| 477 | |||
| 478 | if (get_cpu_current_state(cpu) == CPU_STATE_ONLINE) { | ||
| 479 | cpu_maps_update_done(); | ||
| 480 | rc = cpu_down(cpu); | ||
| 481 | if (rc) | ||
| 482 | goto out; | ||
| 483 | cpu_maps_update_begin(); | ||
| 484 | break; | ||
| 485 | |||
| 486 | } | ||
| 487 | |||
| 488 | /* | ||
| 489 | * The cpu is in CPU_STATE_INACTIVE. | ||
| 490 | * Upgrade it's state to CPU_STATE_OFFLINE. | ||
| 491 | */ | ||
| 492 | set_preferred_offline_state(cpu, CPU_STATE_OFFLINE); | ||
| 493 | BUG_ON(plpar_hcall_norets(H_PROD, intserv[i]) | ||
| 494 | != H_SUCCESS); | ||
| 495 | __cpu_die(cpu); | ||
| 496 | break; | ||
| 497 | } | ||
| 498 | if (cpu == num_possible_cpus()) | ||
| 499 | printk(KERN_WARNING "Could not find cpu to offline " | ||
| 500 | "with physical id 0x%x\n", intserv[i]); | ||
| 501 | } | ||
| 502 | cpu_maps_update_done(); | ||
| 503 | |||
| 504 | out: | ||
| 505 | return rc; | ||
| 506 | |||
| 507 | } | ||
| 508 | |||
| 509 | static ssize_t dlpar_cpu_release(const char *buf, size_t count) | ||
| 510 | { | ||
| 511 | struct device_node *dn; | ||
| 512 | const u32 *drc_index; | ||
| 513 | int rc; | ||
| 514 | |||
| 515 | dn = of_find_node_by_path(buf); | ||
| 516 | if (!dn) | ||
| 517 | return -EINVAL; | ||
| 518 | |||
| 519 | drc_index = of_get_property(dn, "ibm,my-drc-index", NULL); | ||
| 520 | if (!drc_index) { | ||
| 521 | of_node_put(dn); | ||
| 522 | return -EINVAL; | ||
| 523 | } | ||
| 524 | |||
| 525 | cpu_hotplug_driver_lock(); | ||
| 526 | rc = dlpar_offline_cpu(dn); | ||
| 527 | if (rc) { | ||
| 528 | of_node_put(dn); | ||
| 529 | rc = -EINVAL; | ||
| 530 | goto out; | ||
| 531 | } | ||
| 532 | |||
| 533 | rc = dlpar_release_drc(*drc_index); | ||
| 534 | if (rc) { | ||
| 535 | of_node_put(dn); | ||
| 536 | goto out; | ||
| 537 | } | ||
| 538 | |||
| 539 | rc = dlpar_detach_node(dn); | ||
| 540 | if (rc) { | ||
| 541 | dlpar_acquire_drc(*drc_index); | ||
| 542 | goto out; | ||
| 543 | } | ||
| 544 | |||
| 545 | of_node_put(dn); | ||
| 546 | out: | ||
| 547 | cpu_hotplug_driver_unlock(); | ||
| 548 | return rc ? rc : count; | ||
| 549 | } | ||
| 550 | |||
| 551 | static int __init pseries_dlpar_init(void) | ||
| 552 | { | ||
| 553 | ppc_md.cpu_probe = dlpar_cpu_probe; | ||
| 554 | ppc_md.cpu_release = dlpar_cpu_release; | ||
| 555 | |||
| 556 | return 0; | ||
| 557 | } | ||
| 558 | machine_device_initcall(pseries, pseries_dlpar_init); | ||
| 559 | |||
| 560 | #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ | ||
diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c index 937a544a236d..c5f3116b6ca5 100644 --- a/arch/powerpc/platforms/pseries/dtl.c +++ b/arch/powerpc/platforms/pseries/dtl.c | |||
| @@ -54,7 +54,7 @@ struct dtl { | |||
| 54 | int buf_entries; | 54 | int buf_entries; |
| 55 | u64 last_idx; | 55 | u64 last_idx; |
| 56 | }; | 56 | }; |
| 57 | static DEFINE_PER_CPU(struct dtl, dtl); | 57 | static DEFINE_PER_CPU(struct dtl, cpu_dtl); |
| 58 | 58 | ||
| 59 | /* | 59 | /* |
| 60 | * Dispatch trace log event mask: | 60 | * Dispatch trace log event mask: |
| @@ -261,7 +261,7 @@ static int dtl_init(void) | |||
| 261 | 261 | ||
| 262 | /* set up the per-cpu log structures */ | 262 | /* set up the per-cpu log structures */ |
| 263 | for_each_possible_cpu(i) { | 263 | for_each_possible_cpu(i) { |
| 264 | struct dtl *dtl = &per_cpu(dtl, i); | 264 | struct dtl *dtl = &per_cpu(cpu_dtl, i); |
| 265 | dtl->cpu = i; | 265 | dtl->cpu = i; |
| 266 | 266 | ||
| 267 | rc = dtl_setup_file(dtl); | 267 | rc = dtl_setup_file(dtl); |
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index 0e8db6771252..ef8e45448480 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c | |||
| @@ -63,22 +63,6 @@ static void print_device_node_tree(struct pci_dn *pdn, int dent) | |||
| 63 | } | 63 | } |
| 64 | #endif | 64 | #endif |
| 65 | 65 | ||
| 66 | /** | ||
| 67 | * irq_in_use - return true if this irq is being used | ||
| 68 | */ | ||
| 69 | static int irq_in_use(unsigned int irq) | ||
| 70 | { | ||
| 71 | int rc = 0; | ||
| 72 | unsigned long flags; | ||
| 73 | struct irq_desc *desc = irq_desc + irq; | ||
| 74 | |||
| 75 | spin_lock_irqsave(&desc->lock, flags); | ||
| 76 | if (desc->action) | ||
| 77 | rc = 1; | ||
| 78 | spin_unlock_irqrestore(&desc->lock, flags); | ||
| 79 | return rc; | ||
| 80 | } | ||
| 81 | |||
| 82 | /** | 66 | /** |
| 83 | * eeh_disable_irq - disable interrupt for the recovering device | 67 | * eeh_disable_irq - disable interrupt for the recovering device |
| 84 | */ | 68 | */ |
| @@ -93,7 +77,7 @@ static void eeh_disable_irq(struct pci_dev *dev) | |||
| 93 | if (dev->msi_enabled || dev->msix_enabled) | 77 | if (dev->msi_enabled || dev->msix_enabled) |
| 94 | return; | 78 | return; |
| 95 | 79 | ||
| 96 | if (!irq_in_use(dev->irq)) | 80 | if (!irq_has_action(dev->irq)) |
| 97 | return; | 81 | return; |
| 98 | 82 | ||
| 99 | PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED; | 83 | PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED; |
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index ebff6d9a4e39..6ea4698d9176 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <asm/pSeries_reconfig.h> | 30 | #include <asm/pSeries_reconfig.h> |
| 31 | #include "xics.h" | 31 | #include "xics.h" |
| 32 | #include "plpar_wrappers.h" | 32 | #include "plpar_wrappers.h" |
| 33 | #include "offline_states.h" | ||
| 33 | 34 | ||
| 34 | /* This version can't take the spinlock, because it never returns */ | 35 | /* This version can't take the spinlock, because it never returns */ |
| 35 | static struct rtas_args rtas_stop_self_args = { | 36 | static struct rtas_args rtas_stop_self_args = { |
| @@ -39,6 +40,55 @@ static struct rtas_args rtas_stop_self_args = { | |||
| 39 | .rets = &rtas_stop_self_args.args[0], | 40 | .rets = &rtas_stop_self_args.args[0], |
| 40 | }; | 41 | }; |
| 41 | 42 | ||
| 43 | static DEFINE_PER_CPU(enum cpu_state_vals, preferred_offline_state) = | ||
| 44 | CPU_STATE_OFFLINE; | ||
| 45 | static DEFINE_PER_CPU(enum cpu_state_vals, current_state) = CPU_STATE_OFFLINE; | ||
| 46 | |||
| 47 | static enum cpu_state_vals default_offline_state = CPU_STATE_OFFLINE; | ||
| 48 | |||
| 49 | static int cede_offline_enabled __read_mostly = 1; | ||
| 50 | |||
| 51 | /* | ||
| 52 | * Enable/disable cede_offline when available. | ||
| 53 | */ | ||
| 54 | static int __init setup_cede_offline(char *str) | ||
| 55 | { | ||
| 56 | if (!strcmp(str, "off")) | ||
| 57 | cede_offline_enabled = 0; | ||
| 58 | else if (!strcmp(str, "on")) | ||
| 59 | cede_offline_enabled = 1; | ||
| 60 | else | ||
| 61 | return 0; | ||
| 62 | return 1; | ||
| 63 | } | ||
| 64 | |||
| 65 | __setup("cede_offline=", setup_cede_offline); | ||
| 66 | |||
| 67 | enum cpu_state_vals get_cpu_current_state(int cpu) | ||
| 68 | { | ||
| 69 | return per_cpu(current_state, cpu); | ||
| 70 | } | ||
| 71 | |||
| 72 | void set_cpu_current_state(int cpu, enum cpu_state_vals state) | ||
| 73 | { | ||
| 74 | per_cpu(current_state, cpu) = state; | ||
| 75 | } | ||
| 76 | |||
| 77 | enum cpu_state_vals get_preferred_offline_state(int cpu) | ||
| 78 | { | ||
| 79 | return per_cpu(preferred_offline_state, cpu); | ||
| 80 | } | ||
| 81 | |||
| 82 | void set_preferred_offline_state(int cpu, enum cpu_state_vals state) | ||
| 83 | { | ||
| 84 | per_cpu(preferred_offline_state, cpu) = state; | ||
| 85 | } | ||
| 86 | |||
| 87 | void set_default_offline_state(int cpu) | ||
| 88 | { | ||
| 89 | per_cpu(preferred_offline_state, cpu) = default_offline_state; | ||
| 90 | } | ||
| 91 | |||
| 42 | static void rtas_stop_self(void) | 92 | static void rtas_stop_self(void) |
| 43 | { | 93 | { |
| 44 | struct rtas_args *args = &rtas_stop_self_args; | 94 | struct rtas_args *args = &rtas_stop_self_args; |
| @@ -56,11 +106,61 @@ static void rtas_stop_self(void) | |||
| 56 | 106 | ||
| 57 | static void pseries_mach_cpu_die(void) | 107 | static void pseries_mach_cpu_die(void) |
| 58 | { | 108 | { |
| 109 | unsigned int cpu = smp_processor_id(); | ||
| 110 | unsigned int hwcpu = hard_smp_processor_id(); | ||
| 111 | u8 cede_latency_hint = 0; | ||
| 112 | |||
| 59 | local_irq_disable(); | 113 | local_irq_disable(); |
| 60 | idle_task_exit(); | 114 | idle_task_exit(); |
| 61 | xics_teardown_cpu(); | 115 | xics_teardown_cpu(); |
| 62 | unregister_slb_shadow(hard_smp_processor_id(), __pa(get_slb_shadow())); | 116 | |
| 63 | rtas_stop_self(); | 117 | if (get_preferred_offline_state(cpu) == CPU_STATE_INACTIVE) { |
| 118 | set_cpu_current_state(cpu, CPU_STATE_INACTIVE); | ||
| 119 | cede_latency_hint = 2; | ||
| 120 | |||
| 121 | get_lppaca()->idle = 1; | ||
| 122 | if (!get_lppaca()->shared_proc) | ||
| 123 | get_lppaca()->donate_dedicated_cpu = 1; | ||
| 124 | |||
| 125 | printk(KERN_INFO | ||
| 126 | "cpu %u (hwid %u) ceding for offline with hint %d\n", | ||
| 127 | cpu, hwcpu, cede_latency_hint); | ||
| 128 | while (get_preferred_offline_state(cpu) == CPU_STATE_INACTIVE) { | ||
| 129 | extended_cede_processor(cede_latency_hint); | ||
| 130 | printk(KERN_INFO "cpu %u (hwid %u) returned from cede.\n", | ||
| 131 | cpu, hwcpu); | ||
| 132 | printk(KERN_INFO | ||
| 133 | "Decrementer value = %x Timebase value = %llx\n", | ||
| 134 | get_dec(), get_tb()); | ||
| 135 | } | ||
| 136 | |||
| 137 | printk(KERN_INFO "cpu %u (hwid %u) got prodded to go online\n", | ||
| 138 | cpu, hwcpu); | ||
| 139 | |||
| 140 | if (!get_lppaca()->shared_proc) | ||
| 141 | get_lppaca()->donate_dedicated_cpu = 0; | ||
| 142 | get_lppaca()->idle = 0; | ||
| 143 | } | ||
| 144 | |||
| 145 | if (get_preferred_offline_state(cpu) == CPU_STATE_ONLINE) { | ||
| 146 | unregister_slb_shadow(hwcpu, __pa(get_slb_shadow())); | ||
| 147 | |||
| 148 | /* | ||
| 149 | * NOTE: Calling start_secondary() here for now to | ||
| 150 | * start new context. | ||
| 151 | * However, need to do it cleanly by resetting the | ||
| 152 | * stack pointer. | ||
| 153 | */ | ||
| 154 | start_secondary(); | ||
| 155 | |||
| 156 | } else if (get_preferred_offline_state(cpu) == CPU_STATE_OFFLINE) { | ||
| 157 | |||
| 158 | set_cpu_current_state(cpu, CPU_STATE_OFFLINE); | ||
| 159 | unregister_slb_shadow(hard_smp_processor_id(), | ||
| 160 | __pa(get_slb_shadow())); | ||
| 161 | rtas_stop_self(); | ||
| 162 | } | ||
| 163 | |||
| 64 | /* Should never get here... */ | 164 | /* Should never get here... */ |
| 65 | BUG(); | 165 | BUG(); |
| 66 | for(;;); | 166 | for(;;); |
| @@ -106,18 +206,43 @@ static int pseries_cpu_disable(void) | |||
| 106 | return 0; | 206 | return 0; |
| 107 | } | 207 | } |
| 108 | 208 | ||
| 209 | /* | ||
| 210 | * pseries_cpu_die: Wait for the cpu to die. | ||
| 211 | * @cpu: logical processor id of the CPU whose death we're awaiting. | ||
| 212 | * | ||
| 213 | * This function is called from the context of the thread which is performing | ||
| 214 | * the cpu-offline. Here we wait for long enough to allow the cpu in question | ||
| 215 | * to self-destroy so that the cpu-offline thread can send the CPU_DEAD | ||
| 216 | * notifications. | ||
| 217 | * | ||
| 218 | * OTOH, pseries_mach_cpu_die() is called by the @cpu when it wants to | ||
| 219 | * self-destruct. | ||
| 220 | */ | ||
| 109 | static void pseries_cpu_die(unsigned int cpu) | 221 | static void pseries_cpu_die(unsigned int cpu) |
| 110 | { | 222 | { |
| 111 | int tries; | 223 | int tries; |
| 112 | int cpu_status; | 224 | int cpu_status = 1; |
| 113 | unsigned int pcpu = get_hard_smp_processor_id(cpu); | 225 | unsigned int pcpu = get_hard_smp_processor_id(cpu); |
| 114 | 226 | ||
| 115 | for (tries = 0; tries < 25; tries++) { | 227 | if (get_preferred_offline_state(cpu) == CPU_STATE_INACTIVE) { |
| 116 | cpu_status = query_cpu_stopped(pcpu); | 228 | cpu_status = 1; |
| 117 | if (cpu_status == 0 || cpu_status == -1) | 229 | for (tries = 0; tries < 1000; tries++) { |
| 118 | break; | 230 | if (get_cpu_current_state(cpu) == CPU_STATE_INACTIVE) { |
| 119 | cpu_relax(); | 231 | cpu_status = 0; |
| 232 | break; | ||
| 233 | } | ||
| 234 | cpu_relax(); | ||
| 235 | } | ||
| 236 | } else if (get_preferred_offline_state(cpu) == CPU_STATE_OFFLINE) { | ||
| 237 | |||
| 238 | for (tries = 0; tries < 25; tries++) { | ||
| 239 | cpu_status = query_cpu_stopped(pcpu); | ||
| 240 | if (cpu_status == 0 || cpu_status == -1) | ||
| 241 | break; | ||
| 242 | cpu_relax(); | ||
| 243 | } | ||
| 120 | } | 244 | } |
| 245 | |||
| 121 | if (cpu_status != 0) { | 246 | if (cpu_status != 0) { |
| 122 | printk("Querying DEAD? cpu %i (%i) shows %i\n", | 247 | printk("Querying DEAD? cpu %i (%i) shows %i\n", |
| 123 | cpu, pcpu, cpu_status); | 248 | cpu, pcpu, cpu_status); |
| @@ -252,10 +377,41 @@ static struct notifier_block pseries_smp_nb = { | |||
| 252 | .notifier_call = pseries_smp_notifier, | 377 | .notifier_call = pseries_smp_notifier, |
| 253 | }; | 378 | }; |
| 254 | 379 | ||
| 380 | #define MAX_CEDE_LATENCY_LEVELS 4 | ||
| 381 | #define CEDE_LATENCY_PARAM_LENGTH 10 | ||
| 382 | #define CEDE_LATENCY_PARAM_MAX_LENGTH \ | ||
| 383 | (MAX_CEDE_LATENCY_LEVELS * CEDE_LATENCY_PARAM_LENGTH * sizeof(char)) | ||
| 384 | #define CEDE_LATENCY_TOKEN 45 | ||
| 385 | |||
| 386 | static char cede_parameters[CEDE_LATENCY_PARAM_MAX_LENGTH]; | ||
| 387 | |||
| 388 | static int parse_cede_parameters(void) | ||
| 389 | { | ||
| 390 | int call_status; | ||
| 391 | |||
| 392 | memset(cede_parameters, 0, CEDE_LATENCY_PARAM_MAX_LENGTH); | ||
| 393 | call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1, | ||
| 394 | NULL, | ||
| 395 | CEDE_LATENCY_TOKEN, | ||
| 396 | __pa(cede_parameters), | ||
| 397 | CEDE_LATENCY_PARAM_MAX_LENGTH); | ||
| 398 | |||
| 399 | if (call_status != 0) | ||
| 400 | printk(KERN_INFO "CEDE_LATENCY: \ | ||
| 401 | %s %s Error calling get-system-parameter(0x%x)\n", | ||
| 402 | __FILE__, __func__, call_status); | ||
| 403 | else | ||
| 404 | printk(KERN_INFO "CEDE_LATENCY: \ | ||
| 405 | get-system-parameter successful.\n"); | ||
| 406 | |||
| 407 | return call_status; | ||
| 408 | } | ||
| 409 | |||
| 255 | static int __init pseries_cpu_hotplug_init(void) | 410 | static int __init pseries_cpu_hotplug_init(void) |
| 256 | { | 411 | { |
| 257 | struct device_node *np; | 412 | struct device_node *np; |
| 258 | const char *typep; | 413 | const char *typep; |
| 414 | int cpu; | ||
| 259 | 415 | ||
| 260 | for_each_node_by_name(np, "interrupt-controller") { | 416 | for_each_node_by_name(np, "interrupt-controller") { |
| 261 | typep = of_get_property(np, "compatible", NULL); | 417 | typep = of_get_property(np, "compatible", NULL); |
| @@ -283,8 +439,16 @@ static int __init pseries_cpu_hotplug_init(void) | |||
| 283 | smp_ops->cpu_die = pseries_cpu_die; | 439 | smp_ops->cpu_die = pseries_cpu_die; |
| 284 | 440 | ||
| 285 | /* Processors can be added/removed only on LPAR */ | 441 | /* Processors can be added/removed only on LPAR */ |
| 286 | if (firmware_has_feature(FW_FEATURE_LPAR)) | 442 | if (firmware_has_feature(FW_FEATURE_LPAR)) { |
| 287 | pSeries_reconfig_notifier_register(&pseries_smp_nb); | 443 | pSeries_reconfig_notifier_register(&pseries_smp_nb); |
| 444 | cpu_maps_update_begin(); | ||
| 445 | if (cede_offline_enabled && parse_cede_parameters() == 0) { | ||
| 446 | default_offline_state = CPU_STATE_INACTIVE; | ||
| 447 | for_each_online_cpu(cpu) | ||
| 448 | set_default_offline_state(cpu); | ||
| 449 | } | ||
| 450 | cpu_maps_update_done(); | ||
| 451 | } | ||
| 288 | 452 | ||
| 289 | return 0; | 453 | return 0; |
| 290 | } | 454 | } |
diff --git a/arch/powerpc/platforms/pseries/offline_states.h b/arch/powerpc/platforms/pseries/offline_states.h new file mode 100644 index 000000000000..22574e0d9d91 --- /dev/null +++ b/arch/powerpc/platforms/pseries/offline_states.h | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | #ifndef _OFFLINE_STATES_H_ | ||
| 2 | #define _OFFLINE_STATES_H_ | ||
| 3 | |||
| 4 | /* Cpu offline states go here */ | ||
| 5 | enum cpu_state_vals { | ||
| 6 | CPU_STATE_OFFLINE, | ||
| 7 | CPU_STATE_INACTIVE, | ||
| 8 | CPU_STATE_ONLINE, | ||
| 9 | CPU_MAX_OFFLINE_STATES | ||
| 10 | }; | ||
| 11 | |||
| 12 | extern enum cpu_state_vals get_cpu_current_state(int cpu); | ||
| 13 | extern void set_cpu_current_state(int cpu, enum cpu_state_vals state); | ||
| 14 | extern enum cpu_state_vals get_preferred_offline_state(int cpu); | ||
| 15 | extern void set_preferred_offline_state(int cpu, enum cpu_state_vals state); | ||
| 16 | extern void set_default_offline_state(int cpu); | ||
| 17 | extern int start_secondary(void); | ||
| 18 | #endif | ||
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h index a24a6b2333b2..0603c91538ae 100644 --- a/arch/powerpc/platforms/pseries/plpar_wrappers.h +++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h | |||
| @@ -9,11 +9,33 @@ static inline long poll_pending(void) | |||
| 9 | return plpar_hcall_norets(H_POLL_PENDING); | 9 | return plpar_hcall_norets(H_POLL_PENDING); |
| 10 | } | 10 | } |
| 11 | 11 | ||
| 12 | static inline u8 get_cede_latency_hint(void) | ||
| 13 | { | ||
| 14 | return get_lppaca()->gpr5_dword.fields.cede_latency_hint; | ||
| 15 | } | ||
| 16 | |||
| 17 | static inline void set_cede_latency_hint(u8 latency_hint) | ||
| 18 | { | ||
| 19 | get_lppaca()->gpr5_dword.fields.cede_latency_hint = latency_hint; | ||
| 20 | } | ||
| 21 | |||
| 12 | static inline long cede_processor(void) | 22 | static inline long cede_processor(void) |
| 13 | { | 23 | { |
| 14 | return plpar_hcall_norets(H_CEDE); | 24 | return plpar_hcall_norets(H_CEDE); |
| 15 | } | 25 | } |
| 16 | 26 | ||
| 27 | static inline long extended_cede_processor(unsigned long latency_hint) | ||
| 28 | { | ||
| 29 | long rc; | ||
| 30 | u8 old_latency_hint = get_cede_latency_hint(); | ||
| 31 | |||
| 32 | set_cede_latency_hint(latency_hint); | ||
| 33 | rc = cede_processor(); | ||
| 34 | set_cede_latency_hint(old_latency_hint); | ||
| 35 | |||
| 36 | return rc; | ||
| 37 | } | ||
| 38 | |||
| 17 | static inline long vpa_call(unsigned long flags, unsigned long cpu, | 39 | static inline long vpa_call(unsigned long flags, unsigned long cpu, |
| 18 | unsigned long vpa) | 40 | unsigned long vpa) |
| 19 | { | 41 | { |
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 2e2bbe120b90..a2305d29bbbd 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c | |||
| @@ -96,7 +96,7 @@ static struct device_node *derive_parent(const char *path) | |||
| 96 | return parent; | 96 | return parent; |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | static BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain); | 99 | BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain); |
| 100 | 100 | ||
| 101 | int pSeries_reconfig_notifier_register(struct notifier_block *nb) | 101 | int pSeries_reconfig_notifier_register(struct notifier_block *nb) |
| 102 | { | 102 | { |
| @@ -184,7 +184,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np) | |||
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | /* | 186 | /* |
| 187 | * /proc/ppc64/ofdt - yucky binary interface for adding and removing | 187 | * /proc/powerpc/ofdt - yucky binary interface for adding and removing |
| 188 | * OF device nodes. Should be deprecated as soon as we get an | 188 | * OF device nodes. Should be deprecated as soon as we get an |
| 189 | * in-kernel wrapper for the RTAS ibm,configure-connector call. | 189 | * in-kernel wrapper for the RTAS ibm,configure-connector call. |
| 190 | */ | 190 | */ |
| @@ -543,7 +543,7 @@ static const struct file_operations ofdt_fops = { | |||
| 543 | .write = ofdt_write | 543 | .write = ofdt_write |
| 544 | }; | 544 | }; |
| 545 | 545 | ||
| 546 | /* create /proc/ppc64/ofdt write-only by root */ | 546 | /* create /proc/powerpc/ofdt write-only by root */ |
| 547 | static int proc_ppc64_create_ofdt(void) | 547 | static int proc_ppc64_create_ofdt(void) |
| 548 | { | 548 | { |
| 549 | struct proc_dir_entry *ent; | 549 | struct proc_dir_entry *ent; |
| @@ -551,7 +551,7 @@ static int proc_ppc64_create_ofdt(void) | |||
| 551 | if (!machine_is(pseries)) | 551 | if (!machine_is(pseries)) |
| 552 | return 0; | 552 | return 0; |
| 553 | 553 | ||
| 554 | ent = proc_create("ppc64/ofdt", S_IWUSR, NULL, &ofdt_fops); | 554 | ent = proc_create("powerpc/ofdt", S_IWUSR, NULL, &ofdt_fops); |
| 555 | if (ent) | 555 | if (ent) |
| 556 | ent->size = 0; | 556 | ent->size = 0; |
| 557 | 557 | ||
diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c index 417eca79df69..1b45c458f952 100644 --- a/arch/powerpc/platforms/pseries/scanlog.c +++ b/arch/powerpc/platforms/pseries/scanlog.c | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | * of this data using this driver. A dump exists if the device-tree | 13 | * of this data using this driver. A dump exists if the device-tree |
| 14 | * /chosen/ibm,scan-log-data property exists. | 14 | * /chosen/ibm,scan-log-data property exists. |
| 15 | * | 15 | * |
| 16 | * This driver exports /proc/ppc64/scan-log-dump which can be read. | 16 | * This driver exports /proc/powerpc/scan-log-dump which can be read. |
| 17 | * The driver supports only sequential reads. | 17 | * The driver supports only sequential reads. |
| 18 | * | 18 | * |
| 19 | * The driver looks at a write to the driver for the single word "reset". | 19 | * The driver looks at a write to the driver for the single word "reset". |
| @@ -186,7 +186,7 @@ static int __init scanlog_init(void) | |||
| 186 | if (!data) | 186 | if (!data) |
| 187 | goto err; | 187 | goto err; |
| 188 | 188 | ||
| 189 | ent = proc_create_data("ppc64/rtas/scan-log-dump", S_IRUSR, NULL, | 189 | ent = proc_create_data("powerpc/rtas/scan-log-dump", S_IRUSR, NULL, |
| 190 | &scanlog_fops, data); | 190 | &scanlog_fops, data); |
| 191 | if (!ent) | 191 | if (!ent) |
| 192 | goto err; | 192 | goto err; |
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 440000cc7130..b4886635972c 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c | |||
| @@ -48,6 +48,7 @@ | |||
| 48 | #include "plpar_wrappers.h" | 48 | #include "plpar_wrappers.h" |
| 49 | #include "pseries.h" | 49 | #include "pseries.h" |
| 50 | #include "xics.h" | 50 | #include "xics.h" |
| 51 | #include "offline_states.h" | ||
| 51 | 52 | ||
| 52 | 53 | ||
| 53 | /* | 54 | /* |
| @@ -84,6 +85,9 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu) | |||
| 84 | /* Fixup atomic count: it exited inside IRQ handler. */ | 85 | /* Fixup atomic count: it exited inside IRQ handler. */ |
| 85 | task_thread_info(paca[lcpu].__current)->preempt_count = 0; | 86 | task_thread_info(paca[lcpu].__current)->preempt_count = 0; |
| 86 | 87 | ||
| 88 | if (get_cpu_current_state(lcpu) == CPU_STATE_INACTIVE) | ||
| 89 | goto out; | ||
| 90 | |||
| 87 | /* | 91 | /* |
| 88 | * If the RTAS start-cpu token does not exist then presume the | 92 | * If the RTAS start-cpu token does not exist then presume the |
| 89 | * cpu is already spinning. | 93 | * cpu is already spinning. |
| @@ -98,6 +102,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu) | |||
| 98 | return 0; | 102 | return 0; |
| 99 | } | 103 | } |
| 100 | 104 | ||
| 105 | out: | ||
| 101 | return 1; | 106 | return 1; |
| 102 | } | 107 | } |
| 103 | 108 | ||
| @@ -111,12 +116,16 @@ static void __devinit smp_xics_setup_cpu(int cpu) | |||
| 111 | vpa_init(cpu); | 116 | vpa_init(cpu); |
| 112 | 117 | ||
| 113 | cpu_clear(cpu, of_spin_map); | 118 | cpu_clear(cpu, of_spin_map); |
| 119 | set_cpu_current_state(cpu, CPU_STATE_ONLINE); | ||
| 120 | set_default_offline_state(cpu); | ||
| 114 | 121 | ||
| 115 | } | 122 | } |
| 116 | #endif /* CONFIG_XICS */ | 123 | #endif /* CONFIG_XICS */ |
| 117 | 124 | ||
| 118 | static void __devinit smp_pSeries_kick_cpu(int nr) | 125 | static void __devinit smp_pSeries_kick_cpu(int nr) |
| 119 | { | 126 | { |
| 127 | long rc; | ||
| 128 | unsigned long hcpuid; | ||
| 120 | BUG_ON(nr < 0 || nr >= NR_CPUS); | 129 | BUG_ON(nr < 0 || nr >= NR_CPUS); |
| 121 | 130 | ||
| 122 | if (!smp_startup_cpu(nr)) | 131 | if (!smp_startup_cpu(nr)) |
| @@ -128,6 +137,16 @@ static void __devinit smp_pSeries_kick_cpu(int nr) | |||
| 128 | * the processor will continue on to secondary_start | 137 | * the processor will continue on to secondary_start |
| 129 | */ | 138 | */ |
| 130 | paca[nr].cpu_start = 1; | 139 | paca[nr].cpu_start = 1; |
| 140 | |||
| 141 | set_preferred_offline_state(nr, CPU_STATE_ONLINE); | ||
| 142 | |||
| 143 | if (get_cpu_current_state(nr) == CPU_STATE_INACTIVE) { | ||
| 144 | hcpuid = get_hard_smp_processor_id(nr); | ||
| 145 | rc = plpar_hcall_norets(H_PROD, hcpuid); | ||
| 146 | if (rc != H_SUCCESS) | ||
| 147 | printk(KERN_ERR "Error: Prod to wake up processor %d\ | ||
| 148 | Ret= %ld\n", nr, rc); | ||
| 149 | } | ||
| 131 | } | 150 | } |
| 132 | 151 | ||
| 133 | static int smp_pSeries_cpu_bootable(unsigned int nr) | 152 | static int smp_pSeries_cpu_bootable(unsigned int nr) |
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index b9bf0eedccf2..b9b9e11609ec 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/cpu.h> | 20 | #include <linux/cpu.h> |
| 21 | #include <linux/msi.h> | 21 | #include <linux/msi.h> |
| 22 | #include <linux/of.h> | 22 | #include <linux/of.h> |
| 23 | #include <linux/percpu.h> | ||
| 23 | 24 | ||
| 24 | #include <asm/firmware.h> | 25 | #include <asm/firmware.h> |
| 25 | #include <asm/io.h> | 26 | #include <asm/io.h> |
| @@ -46,6 +47,12 @@ static struct irq_host *xics_host; | |||
| 46 | */ | 47 | */ |
| 47 | #define IPI_PRIORITY 4 | 48 | #define IPI_PRIORITY 4 |
| 48 | 49 | ||
| 50 | /* The least favored priority */ | ||
| 51 | #define LOWEST_PRIORITY 0xFF | ||
| 52 | |||
| 53 | /* The number of priorities defined above */ | ||
| 54 | #define MAX_NUM_PRIORITIES 3 | ||
| 55 | |||
| 49 | static unsigned int default_server = 0xFF; | 56 | static unsigned int default_server = 0xFF; |
| 50 | static unsigned int default_distrib_server = 0; | 57 | static unsigned int default_distrib_server = 0; |
| 51 | static unsigned int interrupt_server_size = 8; | 58 | static unsigned int interrupt_server_size = 8; |
| @@ -56,6 +63,12 @@ static int ibm_set_xive; | |||
| 56 | static int ibm_int_on; | 63 | static int ibm_int_on; |
| 57 | static int ibm_int_off; | 64 | static int ibm_int_off; |
| 58 | 65 | ||
| 66 | struct xics_cppr { | ||
| 67 | unsigned char stack[MAX_NUM_PRIORITIES]; | ||
| 68 | int index; | ||
| 69 | }; | ||
| 70 | |||
| 71 | static DEFINE_PER_CPU(struct xics_cppr, xics_cppr); | ||
| 59 | 72 | ||
| 60 | /* Direct hardware low level accessors */ | 73 | /* Direct hardware low level accessors */ |
| 61 | 74 | ||
| @@ -157,7 +170,7 @@ static int get_irq_server(unsigned int virq, unsigned int strict_check) | |||
| 157 | cpumask_t cpumask; | 170 | cpumask_t cpumask; |
| 158 | cpumask_t tmp = CPU_MASK_NONE; | 171 | cpumask_t tmp = CPU_MASK_NONE; |
| 159 | 172 | ||
| 160 | cpumask_copy(&cpumask, irq_desc[virq].affinity); | 173 | cpumask_copy(&cpumask, irq_to_desc(virq)->affinity); |
| 161 | if (!distribute_irqs) | 174 | if (!distribute_irqs) |
| 162 | return default_server; | 175 | return default_server; |
| 163 | 176 | ||
| @@ -284,6 +297,19 @@ static inline unsigned int xics_xirr_vector(unsigned int xirr) | |||
| 284 | return xirr & 0x00ffffff; | 297 | return xirr & 0x00ffffff; |
| 285 | } | 298 | } |
| 286 | 299 | ||
| 300 | static void push_cppr(unsigned int vec) | ||
| 301 | { | ||
| 302 | struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); | ||
| 303 | |||
| 304 | if (WARN_ON(os_cppr->index >= MAX_NUM_PRIORITIES - 1)) | ||
| 305 | return; | ||
| 306 | |||
| 307 | if (vec == XICS_IPI) | ||
| 308 | os_cppr->stack[++os_cppr->index] = IPI_PRIORITY; | ||
| 309 | else | ||
| 310 | os_cppr->stack[++os_cppr->index] = DEFAULT_PRIORITY; | ||
| 311 | } | ||
| 312 | |||
| 287 | static unsigned int xics_get_irq_direct(void) | 313 | static unsigned int xics_get_irq_direct(void) |
| 288 | { | 314 | { |
| 289 | unsigned int xirr = direct_xirr_info_get(); | 315 | unsigned int xirr = direct_xirr_info_get(); |
| @@ -294,8 +320,10 @@ static unsigned int xics_get_irq_direct(void) | |||
| 294 | return NO_IRQ; | 320 | return NO_IRQ; |
| 295 | 321 | ||
| 296 | irq = irq_radix_revmap_lookup(xics_host, vec); | 322 | irq = irq_radix_revmap_lookup(xics_host, vec); |
| 297 | if (likely(irq != NO_IRQ)) | 323 | if (likely(irq != NO_IRQ)) { |
| 324 | push_cppr(vec); | ||
| 298 | return irq; | 325 | return irq; |
| 326 | } | ||
| 299 | 327 | ||
| 300 | /* We don't have a linux mapping, so have rtas mask it. */ | 328 | /* We don't have a linux mapping, so have rtas mask it. */ |
| 301 | xics_mask_unknown_vec(vec); | 329 | xics_mask_unknown_vec(vec); |
| @@ -315,8 +343,10 @@ static unsigned int xics_get_irq_lpar(void) | |||
| 315 | return NO_IRQ; | 343 | return NO_IRQ; |
| 316 | 344 | ||
| 317 | irq = irq_radix_revmap_lookup(xics_host, vec); | 345 | irq = irq_radix_revmap_lookup(xics_host, vec); |
| 318 | if (likely(irq != NO_IRQ)) | 346 | if (likely(irq != NO_IRQ)) { |
| 347 | push_cppr(vec); | ||
| 319 | return irq; | 348 | return irq; |
| 349 | } | ||
| 320 | 350 | ||
| 321 | /* We don't have a linux mapping, so have RTAS mask it. */ | 351 | /* We don't have a linux mapping, so have RTAS mask it. */ |
| 322 | xics_mask_unknown_vec(vec); | 352 | xics_mask_unknown_vec(vec); |
| @@ -326,12 +356,22 @@ static unsigned int xics_get_irq_lpar(void) | |||
| 326 | return NO_IRQ; | 356 | return NO_IRQ; |
| 327 | } | 357 | } |
| 328 | 358 | ||
| 359 | static unsigned char pop_cppr(void) | ||
| 360 | { | ||
| 361 | struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); | ||
| 362 | |||
| 363 | if (WARN_ON(os_cppr->index < 1)) | ||
| 364 | return LOWEST_PRIORITY; | ||
| 365 | |||
| 366 | return os_cppr->stack[--os_cppr->index]; | ||
| 367 | } | ||
| 368 | |||
| 329 | static void xics_eoi_direct(unsigned int virq) | 369 | static void xics_eoi_direct(unsigned int virq) |
| 330 | { | 370 | { |
| 331 | unsigned int irq = (unsigned int)irq_map[virq].hwirq; | 371 | unsigned int irq = (unsigned int)irq_map[virq].hwirq; |
| 332 | 372 | ||
| 333 | iosync(); | 373 | iosync(); |
| 334 | direct_xirr_info_set((0xff << 24) | irq); | 374 | direct_xirr_info_set((pop_cppr() << 24) | irq); |
| 335 | } | 375 | } |
| 336 | 376 | ||
| 337 | static void xics_eoi_lpar(unsigned int virq) | 377 | static void xics_eoi_lpar(unsigned int virq) |
| @@ -339,7 +379,7 @@ static void xics_eoi_lpar(unsigned int virq) | |||
| 339 | unsigned int irq = (unsigned int)irq_map[virq].hwirq; | 379 | unsigned int irq = (unsigned int)irq_map[virq].hwirq; |
| 340 | 380 | ||
| 341 | iosync(); | 381 | iosync(); |
| 342 | lpar_xirr_info_set((0xff << 24) | irq); | 382 | lpar_xirr_info_set((pop_cppr() << 24) | irq); |
| 343 | } | 383 | } |
| 344 | 384 | ||
| 345 | static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask) | 385 | static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask) |
| @@ -388,7 +428,7 @@ static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask) | |||
| 388 | } | 428 | } |
| 389 | 429 | ||
| 390 | static struct irq_chip xics_pic_direct = { | 430 | static struct irq_chip xics_pic_direct = { |
| 391 | .typename = " XICS ", | 431 | .name = " XICS ", |
| 392 | .startup = xics_startup, | 432 | .startup = xics_startup, |
| 393 | .mask = xics_mask_irq, | 433 | .mask = xics_mask_irq, |
| 394 | .unmask = xics_unmask_irq, | 434 | .unmask = xics_unmask_irq, |
| @@ -397,7 +437,7 @@ static struct irq_chip xics_pic_direct = { | |||
| 397 | }; | 437 | }; |
| 398 | 438 | ||
| 399 | static struct irq_chip xics_pic_lpar = { | 439 | static struct irq_chip xics_pic_lpar = { |
| 400 | .typename = " XICS ", | 440 | .name = " XICS ", |
| 401 | .startup = xics_startup, | 441 | .startup = xics_startup, |
| 402 | .mask = xics_mask_irq, | 442 | .mask = xics_mask_irq, |
| 403 | .unmask = xics_unmask_irq, | 443 | .unmask = xics_unmask_irq, |
| @@ -428,13 +468,13 @@ static int xics_host_map(struct irq_host *h, unsigned int virq, | |||
| 428 | /* Insert the interrupt mapping into the radix tree for fast lookup */ | 468 | /* Insert the interrupt mapping into the radix tree for fast lookup */ |
| 429 | irq_radix_revmap_insert(xics_host, virq, hw); | 469 | irq_radix_revmap_insert(xics_host, virq, hw); |
| 430 | 470 | ||
| 431 | get_irq_desc(virq)->status |= IRQ_LEVEL; | 471 | irq_to_desc(virq)->status |= IRQ_LEVEL; |
| 432 | set_irq_chip_and_handler(virq, xics_irq_chip, handle_fasteoi_irq); | 472 | set_irq_chip_and_handler(virq, xics_irq_chip, handle_fasteoi_irq); |
| 433 | return 0; | 473 | return 0; |
| 434 | } | 474 | } |
| 435 | 475 | ||
| 436 | static int xics_host_xlate(struct irq_host *h, struct device_node *ct, | 476 | static int xics_host_xlate(struct irq_host *h, struct device_node *ct, |
| 437 | u32 *intspec, unsigned int intsize, | 477 | const u32 *intspec, unsigned int intsize, |
| 438 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) | 478 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) |
| 439 | 479 | ||
| 440 | { | 480 | { |
| @@ -746,6 +786,12 @@ void __init xics_init_IRQ(void) | |||
| 746 | 786 | ||
| 747 | static void xics_set_cpu_priority(unsigned char cppr) | 787 | static void xics_set_cpu_priority(unsigned char cppr) |
| 748 | { | 788 | { |
| 789 | struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); | ||
| 790 | |||
| 791 | BUG_ON(os_cppr->index != 0); | ||
| 792 | |||
| 793 | os_cppr->stack[os_cppr->index] = cppr; | ||
| 794 | |||
| 749 | if (firmware_has_feature(FW_FEATURE_LPAR)) | 795 | if (firmware_has_feature(FW_FEATURE_LPAR)) |
| 750 | lpar_cppr_info(cppr); | 796 | lpar_cppr_info(cppr); |
| 751 | else | 797 | else |
| @@ -772,7 +818,7 @@ static void xics_set_cpu_giq(unsigned int gserver, unsigned int join) | |||
| 772 | 818 | ||
| 773 | void xics_setup_cpu(void) | 819 | void xics_setup_cpu(void) |
| 774 | { | 820 | { |
| 775 | xics_set_cpu_priority(0xff); | 821 | xics_set_cpu_priority(LOWEST_PRIORITY); |
| 776 | 822 | ||
| 777 | xics_set_cpu_giq(default_distrib_server, 1); | 823 | xics_set_cpu_giq(default_distrib_server, 1); |
| 778 | } | 824 | } |
| @@ -852,7 +898,7 @@ void xics_migrate_irqs_away(void) | |||
| 852 | /* We need to get IPIs still. */ | 898 | /* We need to get IPIs still. */ |
| 853 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) | 899 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) |
| 854 | continue; | 900 | continue; |
| 855 | desc = get_irq_desc(virq); | 901 | desc = irq_to_desc(virq); |
| 856 | 902 | ||
| 857 | /* We only need to migrate enabled IRQS */ | 903 | /* We only need to migrate enabled IRQS */ |
| 858 | if (desc == NULL || desc->chip == NULL | 904 | if (desc == NULL || desc->chip == NULL |
| @@ -860,7 +906,7 @@ void xics_migrate_irqs_away(void) | |||
| 860 | || desc->chip->set_affinity == NULL) | 906 | || desc->chip->set_affinity == NULL) |
| 861 | continue; | 907 | continue; |
| 862 | 908 | ||
| 863 | spin_lock_irqsave(&desc->lock, flags); | 909 | raw_spin_lock_irqsave(&desc->lock, flags); |
| 864 | 910 | ||
| 865 | status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq); | 911 | status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq); |
| 866 | if (status) { | 912 | if (status) { |
| @@ -881,10 +927,10 @@ void xics_migrate_irqs_away(void) | |||
| 881 | virq, cpu); | 927 | virq, cpu); |
| 882 | 928 | ||
| 883 | /* Reset affinity to all cpus */ | 929 | /* Reset affinity to all cpus */ |
| 884 | cpumask_setall(irq_desc[virq].affinity); | 930 | cpumask_setall(irq_to_desc(virq)->affinity); |
| 885 | desc->chip->set_affinity(virq, cpu_all_mask); | 931 | desc->chip->set_affinity(virq, cpu_all_mask); |
| 886 | unlock: | 932 | unlock: |
| 887 | spin_unlock_irqrestore(&desc->lock, flags); | 933 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| 888 | } | 934 | } |
| 889 | } | 935 | } |
| 890 | #endif | 936 | #endif |
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 9d4b17462f13..5642924fb9fb 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile | |||
| @@ -16,6 +16,7 @@ obj-$(CONFIG_U3_DART) += dart_iommu.o | |||
| 16 | obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o | 16 | obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o |
| 17 | obj-$(CONFIG_FSL_SOC) += fsl_soc.o | 17 | obj-$(CONFIG_FSL_SOC) += fsl_soc.o |
| 18 | obj-$(CONFIG_FSL_PCI) += fsl_pci.o $(fsl-msi-obj-y) | 18 | obj-$(CONFIG_FSL_PCI) += fsl_pci.o $(fsl-msi-obj-y) |
| 19 | obj-$(CONFIG_FSL_PMC) += fsl_pmc.o | ||
| 19 | obj-$(CONFIG_FSL_LBC) += fsl_lbc.o | 20 | obj-$(CONFIG_FSL_LBC) += fsl_lbc.o |
| 20 | obj-$(CONFIG_FSL_GTM) += fsl_gtm.o | 21 | obj-$(CONFIG_FSL_GTM) += fsl_gtm.o |
| 21 | obj-$(CONFIG_MPC8xxx_GPIO) += mpc8xxx_gpio.o | 22 | obj-$(CONFIG_MPC8xxx_GPIO) += mpc8xxx_gpio.o |
diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c index 82424cd7e128..a4b41dbde128 100644 --- a/arch/powerpc/sysdev/cpm1.c +++ b/arch/powerpc/sysdev/cpm1.c | |||
| @@ -77,7 +77,7 @@ static void cpm_end_irq(unsigned int irq) | |||
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | static struct irq_chip cpm_pic = { | 79 | static struct irq_chip cpm_pic = { |
| 80 | .typename = " CPM PIC ", | 80 | .name = " CPM PIC ", |
| 81 | .mask = cpm_mask_irq, | 81 | .mask = cpm_mask_irq, |
| 82 | .unmask = cpm_unmask_irq, | 82 | .unmask = cpm_unmask_irq, |
| 83 | .eoi = cpm_end_irq, | 83 | .eoi = cpm_end_irq, |
| @@ -102,7 +102,7 @@ static int cpm_pic_host_map(struct irq_host *h, unsigned int virq, | |||
| 102 | { | 102 | { |
| 103 | pr_debug("cpm_pic_host_map(%d, 0x%lx)\n", virq, hw); | 103 | pr_debug("cpm_pic_host_map(%d, 0x%lx)\n", virq, hw); |
| 104 | 104 | ||
| 105 | get_irq_desc(virq)->status |= IRQ_LEVEL; | 105 | irq_to_desc(virq)->status |= IRQ_LEVEL; |
| 106 | set_irq_chip_and_handler(virq, &cpm_pic, handle_fasteoi_irq); | 106 | set_irq_chip_and_handler(virq, &cpm_pic, handle_fasteoi_irq); |
| 107 | return 0; | 107 | return 0; |
| 108 | } | 108 | } |
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c index 78f1f7cca0a0..1709ac5aac7c 100644 --- a/arch/powerpc/sysdev/cpm2_pic.c +++ b/arch/powerpc/sysdev/cpm2_pic.c | |||
| @@ -115,11 +115,13 @@ static void cpm2_ack(unsigned int virq) | |||
| 115 | 115 | ||
| 116 | static void cpm2_end_irq(unsigned int virq) | 116 | static void cpm2_end_irq(unsigned int virq) |
| 117 | { | 117 | { |
| 118 | struct irq_desc *desc; | ||
| 118 | int bit, word; | 119 | int bit, word; |
| 119 | unsigned int irq_nr = virq_to_hw(virq); | 120 | unsigned int irq_nr = virq_to_hw(virq); |
| 120 | 121 | ||
| 121 | if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS)) | 122 | desc = irq_to_desc(irq_nr); |
| 122 | && irq_desc[irq_nr].action) { | 123 | if (!(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)) |
| 124 | && desc->action) { | ||
| 123 | 125 | ||
| 124 | bit = irq_to_siubit[irq_nr]; | 126 | bit = irq_to_siubit[irq_nr]; |
| 125 | word = irq_to_siureg[irq_nr]; | 127 | word = irq_to_siureg[irq_nr]; |
| @@ -138,16 +140,26 @@ static void cpm2_end_irq(unsigned int virq) | |||
| 138 | static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type) | 140 | static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type) |
| 139 | { | 141 | { |
| 140 | unsigned int src = virq_to_hw(virq); | 142 | unsigned int src = virq_to_hw(virq); |
| 141 | struct irq_desc *desc = get_irq_desc(virq); | 143 | struct irq_desc *desc = irq_to_desc(virq); |
| 142 | unsigned int vold, vnew, edibit; | 144 | unsigned int vold, vnew, edibit; |
| 143 | 145 | ||
| 144 | if (flow_type == IRQ_TYPE_NONE) | 146 | /* Port C interrupts are either IRQ_TYPE_EDGE_FALLING or |
| 145 | flow_type = IRQ_TYPE_LEVEL_LOW; | 147 | * IRQ_TYPE_EDGE_BOTH (default). All others are IRQ_TYPE_EDGE_FALLING |
| 146 | 148 | * or IRQ_TYPE_LEVEL_LOW (default) | |
| 147 | if (flow_type & IRQ_TYPE_EDGE_RISING) { | 149 | */ |
| 148 | printk(KERN_ERR "CPM2 PIC: sense type 0x%x not supported\n", | 150 | if (src >= CPM2_IRQ_PORTC15 && src <= CPM2_IRQ_PORTC0) { |
| 149 | flow_type); | 151 | if (flow_type == IRQ_TYPE_NONE) |
| 150 | return -EINVAL; | 152 | flow_type = IRQ_TYPE_EDGE_BOTH; |
| 153 | |||
| 154 | if (flow_type != IRQ_TYPE_EDGE_BOTH && | ||
| 155 | flow_type != IRQ_TYPE_EDGE_FALLING) | ||
| 156 | goto err_sense; | ||
| 157 | } else { | ||
| 158 | if (flow_type == IRQ_TYPE_NONE) | ||
| 159 | flow_type = IRQ_TYPE_LEVEL_LOW; | ||
| 160 | |||
| 161 | if (flow_type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)) | ||
| 162 | goto err_sense; | ||
| 151 | } | 163 | } |
| 152 | 164 | ||
| 153 | desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); | 165 | desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); |
| @@ -179,10 +191,14 @@ static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type) | |||
| 179 | if (vold != vnew) | 191 | if (vold != vnew) |
| 180 | out_be32(&cpm2_intctl->ic_siexr, vnew); | 192 | out_be32(&cpm2_intctl->ic_siexr, vnew); |
| 181 | return 0; | 193 | return 0; |
| 194 | |||
| 195 | err_sense: | ||
| 196 | pr_err("CPM2 PIC: sense type 0x%x not supported\n", flow_type); | ||
| 197 | return -EINVAL; | ||
| 182 | } | 198 | } |
| 183 | 199 | ||
| 184 | static struct irq_chip cpm2_pic = { | 200 | static struct irq_chip cpm2_pic = { |
| 185 | .typename = " CPM2 SIU ", | 201 | .name = " CPM2 SIU ", |
| 186 | .mask = cpm2_mask_irq, | 202 | .mask = cpm2_mask_irq, |
| 187 | .unmask = cpm2_unmask_irq, | 203 | .unmask = cpm2_unmask_irq, |
| 188 | .ack = cpm2_ack, | 204 | .ack = cpm2_ack, |
| @@ -210,13 +226,13 @@ static int cpm2_pic_host_map(struct irq_host *h, unsigned int virq, | |||
| 210 | { | 226 | { |
| 211 | pr_debug("cpm2_pic_host_map(%d, 0x%lx)\n", virq, hw); | 227 | pr_debug("cpm2_pic_host_map(%d, 0x%lx)\n", virq, hw); |
| 212 | 228 | ||
| 213 | get_irq_desc(virq)->status |= IRQ_LEVEL; | 229 | irq_to_desc(virq)->status |= IRQ_LEVEL; |
| 214 | set_irq_chip_and_handler(virq, &cpm2_pic, handle_level_irq); | 230 | set_irq_chip_and_handler(virq, &cpm2_pic, handle_level_irq); |
| 215 | return 0; | 231 | return 0; |
| 216 | } | 232 | } |
| 217 | 233 | ||
| 218 | static int cpm2_pic_host_xlate(struct irq_host *h, struct device_node *ct, | 234 | static int cpm2_pic_host_xlate(struct irq_host *h, struct device_node *ct, |
| 219 | u32 *intspec, unsigned int intsize, | 235 | const u32 *intspec, unsigned int intsize, |
| 220 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) | 236 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) |
| 221 | { | 237 | { |
| 222 | *out_hwirq = intspec[0]; | 238 | *out_hwirq = intspec[0]; |
diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c index e4b6d66d93de..9de72c96e6d1 100644 --- a/arch/powerpc/sysdev/cpm_common.c +++ b/arch/powerpc/sysdev/cpm_common.c | |||
| @@ -72,7 +72,7 @@ static phys_addr_t muram_pbase; | |||
| 72 | /* Max address size we deal with */ | 72 | /* Max address size we deal with */ |
| 73 | #define OF_MAX_ADDR_CELLS 4 | 73 | #define OF_MAX_ADDR_CELLS 4 |
| 74 | 74 | ||
| 75 | int __init cpm_muram_init(void) | 75 | int cpm_muram_init(void) |
| 76 | { | 76 | { |
| 77 | struct device_node *np; | 77 | struct device_node *np; |
| 78 | struct resource r; | 78 | struct resource r; |
| @@ -81,6 +81,9 @@ int __init cpm_muram_init(void) | |||
| 81 | int i = 0; | 81 | int i = 0; |
| 82 | int ret = 0; | 82 | int ret = 0; |
| 83 | 83 | ||
| 84 | if (muram_pbase) | ||
| 85 | return 0; | ||
| 86 | |||
| 84 | spin_lock_init(&cpm_muram_lock); | 87 | spin_lock_init(&cpm_muram_lock); |
| 85 | /* initialize the info header */ | 88 | /* initialize the info header */ |
| 86 | rh_init(&cpm_muram_info, 1, | 89 | rh_init(&cpm_muram_info, 1, |
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index da38a1ff97bb..c6e11b077108 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c | |||
| @@ -47,7 +47,7 @@ static struct irq_chip fsl_msi_chip = { | |||
| 47 | .mask = mask_msi_irq, | 47 | .mask = mask_msi_irq, |
| 48 | .unmask = unmask_msi_irq, | 48 | .unmask = unmask_msi_irq, |
| 49 | .ack = fsl_msi_end_irq, | 49 | .ack = fsl_msi_end_irq, |
| 50 | .typename = " FSL-MSI ", | 50 | .name = " FSL-MSI ", |
| 51 | }; | 51 | }; |
| 52 | 52 | ||
| 53 | static int fsl_msi_host_map(struct irq_host *h, unsigned int virq, | 53 | static int fsl_msi_host_map(struct irq_host *h, unsigned int virq, |
| @@ -55,7 +55,7 @@ static int fsl_msi_host_map(struct irq_host *h, unsigned int virq, | |||
| 55 | { | 55 | { |
| 56 | struct irq_chip *chip = &fsl_msi_chip; | 56 | struct irq_chip *chip = &fsl_msi_chip; |
| 57 | 57 | ||
| 58 | get_irq_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING; | 58 | irq_to_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING; |
| 59 | 59 | ||
| 60 | set_irq_chip_and_handler(virq, chip, handle_edge_irq); | 60 | set_irq_chip_and_handler(virq, chip, handle_edge_irq); |
| 61 | 61 | ||
| @@ -173,7 +173,7 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) | |||
| 173 | u32 intr_index; | 173 | u32 intr_index; |
| 174 | u32 have_shift = 0; | 174 | u32 have_shift = 0; |
| 175 | 175 | ||
| 176 | spin_lock(&desc->lock); | 176 | raw_spin_lock(&desc->lock); |
| 177 | if ((msi_data->feature & FSL_PIC_IP_MASK) == FSL_PIC_IP_IPIC) { | 177 | if ((msi_data->feature & FSL_PIC_IP_MASK) == FSL_PIC_IP_IPIC) { |
| 178 | if (desc->chip->mask_ack) | 178 | if (desc->chip->mask_ack) |
| 179 | desc->chip->mask_ack(irq); | 179 | desc->chip->mask_ack(irq); |
| @@ -225,7 +225,7 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) | |||
| 225 | break; | 225 | break; |
| 226 | } | 226 | } |
| 227 | unlock: | 227 | unlock: |
| 228 | spin_unlock(&desc->lock); | 228 | raw_spin_unlock(&desc->lock); |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | static int __devinit fsl_of_msi_probe(struct of_device *dev, | 231 | static int __devinit fsl_of_msi_probe(struct of_device *dev, |
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index ae88b1448018..e1a028c1f18d 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c | |||
| @@ -56,7 +56,7 @@ static int __init fsl_pcie_check_link(struct pci_controller *hose) | |||
| 56 | return 0; | 56 | return 0; |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | #if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx) | 59 | #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) |
| 60 | static int __init setup_one_atmu(struct ccsr_pci __iomem *pci, | 60 | static int __init setup_one_atmu(struct ccsr_pci __iomem *pci, |
| 61 | unsigned int index, const struct resource *res, | 61 | unsigned int index, const struct resource *res, |
| 62 | resource_size_t offset) | 62 | resource_size_t offset) |
| @@ -392,9 +392,23 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8536, quirk_fsl_pcie_header); | |||
| 392 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641, quirk_fsl_pcie_header); | 392 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641, quirk_fsl_pcie_header); |
| 393 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_header); | 393 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_header); |
| 394 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, quirk_fsl_pcie_header); | 394 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, quirk_fsl_pcie_header); |
| 395 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1011E, quirk_fsl_pcie_header); | ||
| 396 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1011, quirk_fsl_pcie_header); | ||
| 397 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1013E, quirk_fsl_pcie_header); | ||
| 398 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1013, quirk_fsl_pcie_header); | ||
| 399 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1020E, quirk_fsl_pcie_header); | ||
| 400 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1020, quirk_fsl_pcie_header); | ||
| 401 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1022E, quirk_fsl_pcie_header); | ||
| 402 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1022, quirk_fsl_pcie_header); | ||
| 403 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010E, quirk_fsl_pcie_header); | ||
| 404 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010, quirk_fsl_pcie_header); | ||
| 395 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020E, quirk_fsl_pcie_header); | 405 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020E, quirk_fsl_pcie_header); |
| 396 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020, quirk_fsl_pcie_header); | 406 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020, quirk_fsl_pcie_header); |
| 397 | #endif /* CONFIG_PPC_85xx || CONFIG_PPC_86xx */ | 407 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040E, quirk_fsl_pcie_header); |
| 408 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040, quirk_fsl_pcie_header); | ||
| 409 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080E, quirk_fsl_pcie_header); | ||
| 410 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080, quirk_fsl_pcie_header); | ||
| 411 | #endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */ | ||
| 398 | 412 | ||
| 399 | #if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x) | 413 | #if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x) |
| 400 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8314E, quirk_fsl_pcie_header); | 414 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8314E, quirk_fsl_pcie_header); |
| @@ -450,8 +464,7 @@ static void __iomem *mpc83xx_pcie_remap_cfg(struct pci_bus *bus, | |||
| 450 | { | 464 | { |
| 451 | struct pci_controller *hose = pci_bus_to_host(bus); | 465 | struct pci_controller *hose = pci_bus_to_host(bus); |
| 452 | struct mpc83xx_pcie_priv *pcie = hose->dn->data; | 466 | struct mpc83xx_pcie_priv *pcie = hose->dn->data; |
| 453 | u8 bus_no = bus->number - hose->first_busno; | 467 | u32 dev_base = bus->number << 24 | devfn << 16; |
| 454 | u32 dev_base = bus_no << 24 | devfn << 16; | ||
| 455 | int ret; | 468 | int ret; |
| 456 | 469 | ||
| 457 | ret = mpc83xx_pcie_exclude_device(bus, devfn); | 470 | ret = mpc83xx_pcie_exclude_device(bus, devfn); |
| @@ -501,12 +514,17 @@ static int mpc83xx_pcie_read_config(struct pci_bus *bus, unsigned int devfn, | |||
| 501 | static int mpc83xx_pcie_write_config(struct pci_bus *bus, unsigned int devfn, | 514 | static int mpc83xx_pcie_write_config(struct pci_bus *bus, unsigned int devfn, |
| 502 | int offset, int len, u32 val) | 515 | int offset, int len, u32 val) |
| 503 | { | 516 | { |
| 517 | struct pci_controller *hose = pci_bus_to_host(bus); | ||
| 504 | void __iomem *cfg_addr; | 518 | void __iomem *cfg_addr; |
| 505 | 519 | ||
| 506 | cfg_addr = mpc83xx_pcie_remap_cfg(bus, devfn, offset); | 520 | cfg_addr = mpc83xx_pcie_remap_cfg(bus, devfn, offset); |
| 507 | if (!cfg_addr) | 521 | if (!cfg_addr) |
| 508 | return PCIBIOS_DEVICE_NOT_FOUND; | 522 | return PCIBIOS_DEVICE_NOT_FOUND; |
| 509 | 523 | ||
| 524 | /* PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS */ | ||
| 525 | if (offset == PCI_PRIMARY_BUS && bus->number == hose->first_busno) | ||
| 526 | val &= 0xffffff00; | ||
| 527 | |||
| 510 | switch (len) { | 528 | switch (len) { |
| 511 | case 1: | 529 | case 1: |
| 512 | out_8(cfg_addr, val); | 530 | out_8(cfg_addr, val); |
diff --git a/arch/powerpc/sysdev/fsl_pmc.c b/arch/powerpc/sysdev/fsl_pmc.c new file mode 100644 index 000000000000..a7635a993dca --- /dev/null +++ b/arch/powerpc/sysdev/fsl_pmc.c | |||
| @@ -0,0 +1,88 @@ | |||
| 1 | /* | ||
| 2 | * Suspend/resume support | ||
| 3 | * | ||
| 4 | * Copyright 2009 MontaVista Software, Inc. | ||
| 5 | * | ||
| 6 | * Author: Anton Vorontsov <avorontsov@ru.mvista.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/init.h> | ||
| 15 | #include <linux/types.h> | ||
| 16 | #include <linux/errno.h> | ||
| 17 | #include <linux/suspend.h> | ||
| 18 | #include <linux/delay.h> | ||
| 19 | #include <linux/device.h> | ||
| 20 | #include <linux/of_platform.h> | ||
| 21 | |||
| 22 | struct pmc_regs { | ||
| 23 | __be32 devdisr; | ||
| 24 | __be32 devdisr2; | ||
| 25 | __be32 :32; | ||
| 26 | __be32 :32; | ||
| 27 | __be32 pmcsr; | ||
| 28 | #define PMCSR_SLP (1 << 17) | ||
| 29 | }; | ||
| 30 | |||
| 31 | static struct device *pmc_dev; | ||
| 32 | static struct pmc_regs __iomem *pmc_regs; | ||
| 33 | |||
| 34 | static int pmc_suspend_enter(suspend_state_t state) | ||
| 35 | { | ||
| 36 | int ret; | ||
| 37 | |||
| 38 | setbits32(&pmc_regs->pmcsr, PMCSR_SLP); | ||
| 39 | /* At this point, the CPU is asleep. */ | ||
| 40 | |||
| 41 | /* Upon resume, wait for SLP bit to be clear. */ | ||
| 42 | ret = spin_event_timeout((in_be32(&pmc_regs->pmcsr) & PMCSR_SLP) == 0, | ||
| 43 | 10000, 10) ? 0 : -ETIMEDOUT; | ||
| 44 | if (ret) | ||
| 45 | dev_err(pmc_dev, "tired waiting for SLP bit to clear\n"); | ||
| 46 | return ret; | ||
| 47 | } | ||
| 48 | |||
| 49 | static int pmc_suspend_valid(suspend_state_t state) | ||
| 50 | { | ||
| 51 | if (state != PM_SUSPEND_STANDBY) | ||
| 52 | return 0; | ||
| 53 | return 1; | ||
| 54 | } | ||
| 55 | |||
| 56 | static struct platform_suspend_ops pmc_suspend_ops = { | ||
| 57 | .valid = pmc_suspend_valid, | ||
| 58 | .enter = pmc_suspend_enter, | ||
| 59 | }; | ||
| 60 | |||
| 61 | static int pmc_probe(struct of_device *ofdev, const struct of_device_id *id) | ||
| 62 | { | ||
| 63 | pmc_regs = of_iomap(ofdev->node, 0); | ||
| 64 | if (!pmc_regs) | ||
| 65 | return -ENOMEM; | ||
| 66 | |||
| 67 | pmc_dev = &ofdev->dev; | ||
| 68 | suspend_set_ops(&pmc_suspend_ops); | ||
| 69 | return 0; | ||
| 70 | } | ||
| 71 | |||
| 72 | static const struct of_device_id pmc_ids[] = { | ||
| 73 | { .compatible = "fsl,mpc8548-pmc", }, | ||
| 74 | { .compatible = "fsl,mpc8641d-pmc", }, | ||
| 75 | { }, | ||
| 76 | }; | ||
| 77 | |||
| 78 | static struct of_platform_driver pmc_driver = { | ||
| 79 | .driver.name = "fsl-pmc", | ||
| 80 | .match_table = pmc_ids, | ||
| 81 | .probe = pmc_probe, | ||
| 82 | }; | ||
| 83 | |||
| 84 | static int __init pmc_init(void) | ||
| 85 | { | ||
| 86 | return of_register_platform_driver(&pmc_driver); | ||
| 87 | } | ||
| 88 | device_initcall(pmc_init); | ||
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index adca4affcf1f..b91f7acdda6f 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c | |||
| @@ -372,7 +372,7 @@ err: | |||
| 372 | 372 | ||
| 373 | arch_initcall(fsl_usb_of_init); | 373 | arch_initcall(fsl_usb_of_init); |
| 374 | 374 | ||
| 375 | #if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx) | 375 | #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) |
| 376 | static __be32 __iomem *rstcr; | 376 | static __be32 __iomem *rstcr; |
| 377 | 377 | ||
| 378 | static int __init setup_rstcr(void) | 378 | static int __init setup_rstcr(void) |
diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c index a96584ab33dd..0a55db8a5a29 100644 --- a/arch/powerpc/sysdev/i8259.c +++ b/arch/powerpc/sysdev/i8259.c | |||
| @@ -135,7 +135,7 @@ static void i8259_unmask_irq(unsigned int irq_nr) | |||
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | static struct irq_chip i8259_pic = { | 137 | static struct irq_chip i8259_pic = { |
| 138 | .typename = " i8259 ", | 138 | .name = " i8259 ", |
| 139 | .mask = i8259_mask_irq, | 139 | .mask = i8259_mask_irq, |
| 140 | .disable = i8259_mask_irq, | 140 | .disable = i8259_mask_irq, |
| 141 | .unmask = i8259_unmask_irq, | 141 | .unmask = i8259_unmask_irq, |
| @@ -175,12 +175,12 @@ static int i8259_host_map(struct irq_host *h, unsigned int virq, | |||
| 175 | 175 | ||
| 176 | /* We block the internal cascade */ | 176 | /* We block the internal cascade */ |
| 177 | if (hw == 2) | 177 | if (hw == 2) |
| 178 | get_irq_desc(virq)->status |= IRQ_NOREQUEST; | 178 | irq_to_desc(virq)->status |= IRQ_NOREQUEST; |
| 179 | 179 | ||
| 180 | /* We use the level handler only for now, we might want to | 180 | /* We use the level handler only for now, we might want to |
| 181 | * be more cautious here but that works for now | 181 | * be more cautious here but that works for now |
| 182 | */ | 182 | */ |
| 183 | get_irq_desc(virq)->status |= IRQ_LEVEL; | 183 | irq_to_desc(virq)->status |= IRQ_LEVEL; |
| 184 | set_irq_chip_and_handler(virq, &i8259_pic, handle_level_irq); | 184 | set_irq_chip_and_handler(virq, &i8259_pic, handle_level_irq); |
| 185 | return 0; | 185 | return 0; |
| 186 | } | 186 | } |
| @@ -198,7 +198,7 @@ static void i8259_host_unmap(struct irq_host *h, unsigned int virq) | |||
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | static int i8259_host_xlate(struct irq_host *h, struct device_node *ct, | 200 | static int i8259_host_xlate(struct irq_host *h, struct device_node *ct, |
| 201 | u32 *intspec, unsigned int intsize, | 201 | const u32 *intspec, unsigned int intsize, |
| 202 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) | 202 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) |
| 203 | { | 203 | { |
| 204 | static unsigned char map_isa_senses[4] = { | 204 | static unsigned char map_isa_senses[4] = { |
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c index cb7689c4bfbd..28cdddd2f89e 100644 --- a/arch/powerpc/sysdev/ipic.c +++ b/arch/powerpc/sysdev/ipic.c | |||
| @@ -605,7 +605,7 @@ static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type) | |||
| 605 | { | 605 | { |
| 606 | struct ipic *ipic = ipic_from_irq(virq); | 606 | struct ipic *ipic = ipic_from_irq(virq); |
| 607 | unsigned int src = ipic_irq_to_hw(virq); | 607 | unsigned int src = ipic_irq_to_hw(virq); |
| 608 | struct irq_desc *desc = get_irq_desc(virq); | 608 | struct irq_desc *desc = irq_to_desc(virq); |
| 609 | unsigned int vold, vnew, edibit; | 609 | unsigned int vold, vnew, edibit; |
| 610 | 610 | ||
| 611 | if (flow_type == IRQ_TYPE_NONE) | 611 | if (flow_type == IRQ_TYPE_NONE) |
| @@ -660,7 +660,7 @@ static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type) | |||
| 660 | 660 | ||
| 661 | /* level interrupts and edge interrupts have different ack operations */ | 661 | /* level interrupts and edge interrupts have different ack operations */ |
| 662 | static struct irq_chip ipic_level_irq_chip = { | 662 | static struct irq_chip ipic_level_irq_chip = { |
| 663 | .typename = " IPIC ", | 663 | .name = " IPIC ", |
| 664 | .unmask = ipic_unmask_irq, | 664 | .unmask = ipic_unmask_irq, |
| 665 | .mask = ipic_mask_irq, | 665 | .mask = ipic_mask_irq, |
| 666 | .mask_ack = ipic_mask_irq, | 666 | .mask_ack = ipic_mask_irq, |
| @@ -668,7 +668,7 @@ static struct irq_chip ipic_level_irq_chip = { | |||
| 668 | }; | 668 | }; |
| 669 | 669 | ||
| 670 | static struct irq_chip ipic_edge_irq_chip = { | 670 | static struct irq_chip ipic_edge_irq_chip = { |
| 671 | .typename = " IPIC ", | 671 | .name = " IPIC ", |
| 672 | .unmask = ipic_unmask_irq, | 672 | .unmask = ipic_unmask_irq, |
| 673 | .mask = ipic_mask_irq, | 673 | .mask = ipic_mask_irq, |
| 674 | .mask_ack = ipic_mask_irq_and_ack, | 674 | .mask_ack = ipic_mask_irq_and_ack, |
| @@ -697,7 +697,7 @@ static int ipic_host_map(struct irq_host *h, unsigned int virq, | |||
| 697 | } | 697 | } |
| 698 | 698 | ||
| 699 | static int ipic_host_xlate(struct irq_host *h, struct device_node *ct, | 699 | static int ipic_host_xlate(struct irq_host *h, struct device_node *ct, |
| 700 | u32 *intspec, unsigned int intsize, | 700 | const u32 *intspec, unsigned int intsize, |
| 701 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) | 701 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) |
| 702 | 702 | ||
| 703 | { | 703 | { |
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c index 5d2d5522ef41..69bd6f4dff83 100644 --- a/arch/powerpc/sysdev/mpc8xx_pic.c +++ b/arch/powerpc/sysdev/mpc8xx_pic.c | |||
| @@ -72,7 +72,7 @@ static void mpc8xx_end_irq(unsigned int virq) | |||
| 72 | 72 | ||
| 73 | static int mpc8xx_set_irq_type(unsigned int virq, unsigned int flow_type) | 73 | static int mpc8xx_set_irq_type(unsigned int virq, unsigned int flow_type) |
| 74 | { | 74 | { |
| 75 | struct irq_desc *desc = get_irq_desc(virq); | 75 | struct irq_desc *desc = irq_to_desc(virq); |
| 76 | 76 | ||
| 77 | desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); | 77 | desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); |
| 78 | desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; | 78 | desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; |
| @@ -94,7 +94,7 @@ static int mpc8xx_set_irq_type(unsigned int virq, unsigned int flow_type) | |||
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | static struct irq_chip mpc8xx_pic = { | 96 | static struct irq_chip mpc8xx_pic = { |
| 97 | .typename = " MPC8XX SIU ", | 97 | .name = " MPC8XX SIU ", |
| 98 | .unmask = mpc8xx_unmask_irq, | 98 | .unmask = mpc8xx_unmask_irq, |
| 99 | .mask = mpc8xx_mask_irq, | 99 | .mask = mpc8xx_mask_irq, |
| 100 | .ack = mpc8xx_ack, | 100 | .ack = mpc8xx_ack, |
| @@ -130,7 +130,7 @@ static int mpc8xx_pic_host_map(struct irq_host *h, unsigned int virq, | |||
| 130 | 130 | ||
| 131 | 131 | ||
| 132 | static int mpc8xx_pic_host_xlate(struct irq_host *h, struct device_node *ct, | 132 | static int mpc8xx_pic_host_xlate(struct irq_host *h, struct device_node *ct, |
| 133 | u32 *intspec, unsigned int intsize, | 133 | const u32 *intspec, unsigned int intsize, |
| 134 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) | 134 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) |
| 135 | { | 135 | { |
| 136 | static unsigned char map_pic_senses[4] = { | 136 | static unsigned char map_pic_senses[4] = { |
diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c b/arch/powerpc/sysdev/mpc8xxx_gpio.c index 103eace36194..ee1c0e1cf4a7 100644 --- a/arch/powerpc/sysdev/mpc8xxx_gpio.c +++ b/arch/powerpc/sysdev/mpc8xxx_gpio.c | |||
| @@ -54,6 +54,22 @@ static void mpc8xxx_gpio_save_regs(struct of_mm_gpio_chip *mm) | |||
| 54 | mpc8xxx_gc->data = in_be32(mm->regs + GPIO_DAT); | 54 | mpc8xxx_gc->data = in_be32(mm->regs + GPIO_DAT); |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | /* Workaround GPIO 1 errata on MPC8572/MPC8536. The status of GPIOs | ||
| 58 | * defined as output cannot be determined by reading GPDAT register, | ||
| 59 | * so we use shadow data register instead. The status of input pins | ||
| 60 | * is determined by reading GPDAT register. | ||
| 61 | */ | ||
| 62 | static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio) | ||
| 63 | { | ||
| 64 | u32 val; | ||
| 65 | struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); | ||
| 66 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); | ||
| 67 | |||
| 68 | val = in_be32(mm->regs + GPIO_DAT) & ~in_be32(mm->regs + GPIO_DIR); | ||
| 69 | |||
| 70 | return (val | mpc8xxx_gc->data) & mpc8xxx_gpio2mask(gpio); | ||
| 71 | } | ||
| 72 | |||
| 57 | static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio) | 73 | static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio) |
| 58 | { | 74 | { |
| 59 | struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); | 75 | struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); |
| @@ -136,7 +152,10 @@ static void __init mpc8xxx_add_controller(struct device_node *np) | |||
| 136 | gc->ngpio = MPC8XXX_GPIO_PINS; | 152 | gc->ngpio = MPC8XXX_GPIO_PINS; |
| 137 | gc->direction_input = mpc8xxx_gpio_dir_in; | 153 | gc->direction_input = mpc8xxx_gpio_dir_in; |
| 138 | gc->direction_output = mpc8xxx_gpio_dir_out; | 154 | gc->direction_output = mpc8xxx_gpio_dir_out; |
| 139 | gc->get = mpc8xxx_gpio_get; | 155 | if (of_device_is_compatible(np, "fsl,mpc8572-gpio")) |
| 156 | gc->get = mpc8572_gpio_get; | ||
| 157 | else | ||
| 158 | gc->get = mpc8xxx_gpio_get; | ||
| 140 | gc->set = mpc8xxx_gpio_set; | 159 | gc->set = mpc8xxx_gpio_set; |
| 141 | 160 | ||
| 142 | ret = of_mm_gpiochip_add(np, mm_gc); | 161 | ret = of_mm_gpiochip_add(np, mm_gc); |
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 30c44e6b0413..470dc6c11d57 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
| @@ -567,13 +567,11 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic) | |||
| 567 | #endif /* CONFIG_MPIC_U3_HT_IRQS */ | 567 | #endif /* CONFIG_MPIC_U3_HT_IRQS */ |
| 568 | 568 | ||
| 569 | #ifdef CONFIG_SMP | 569 | #ifdef CONFIG_SMP |
| 570 | static int irq_choose_cpu(unsigned int virt_irq) | 570 | static int irq_choose_cpu(const cpumask_t *mask) |
| 571 | { | 571 | { |
| 572 | cpumask_t mask; | ||
| 573 | int cpuid; | 572 | int cpuid; |
| 574 | 573 | ||
| 575 | cpumask_copy(&mask, irq_desc[virt_irq].affinity); | 574 | if (cpumask_equal(mask, cpu_all_mask)) { |
| 576 | if (cpus_equal(mask, CPU_MASK_ALL)) { | ||
| 577 | static int irq_rover; | 575 | static int irq_rover; |
| 578 | static DEFINE_SPINLOCK(irq_rover_lock); | 576 | static DEFINE_SPINLOCK(irq_rover_lock); |
| 579 | unsigned long flags; | 577 | unsigned long flags; |
| @@ -594,20 +592,15 @@ static int irq_choose_cpu(unsigned int virt_irq) | |||
| 594 | 592 | ||
| 595 | spin_unlock_irqrestore(&irq_rover_lock, flags); | 593 | spin_unlock_irqrestore(&irq_rover_lock, flags); |
| 596 | } else { | 594 | } else { |
| 597 | cpumask_t tmp; | 595 | cpuid = cpumask_first_and(mask, cpu_online_mask); |
| 598 | 596 | if (cpuid >= nr_cpu_ids) | |
| 599 | cpus_and(tmp, cpu_online_map, mask); | ||
| 600 | |||
| 601 | if (cpus_empty(tmp)) | ||
| 602 | goto do_round_robin; | 597 | goto do_round_robin; |
| 603 | |||
| 604 | cpuid = first_cpu(tmp); | ||
| 605 | } | 598 | } |
| 606 | 599 | ||
| 607 | return get_hard_smp_processor_id(cpuid); | 600 | return get_hard_smp_processor_id(cpuid); |
| 608 | } | 601 | } |
| 609 | #else | 602 | #else |
| 610 | static int irq_choose_cpu(unsigned int virt_irq) | 603 | static int irq_choose_cpu(const cpumask_t *mask) |
| 611 | { | 604 | { |
| 612 | return hard_smp_processor_id(); | 605 | return hard_smp_processor_id(); |
| 613 | } | 606 | } |
| @@ -621,7 +614,7 @@ static struct mpic *mpic_find(unsigned int irq) | |||
| 621 | if (irq < NUM_ISA_INTERRUPTS) | 614 | if (irq < NUM_ISA_INTERRUPTS) |
| 622 | return NULL; | 615 | return NULL; |
| 623 | 616 | ||
| 624 | return irq_desc[irq].chip_data; | 617 | return irq_to_desc(irq)->chip_data; |
| 625 | } | 618 | } |
| 626 | 619 | ||
| 627 | /* Determine if the linux irq is an IPI */ | 620 | /* Determine if the linux irq is an IPI */ |
| @@ -648,14 +641,14 @@ static inline u32 mpic_physmask(u32 cpumask) | |||
| 648 | /* Get the mpic structure from the IPI number */ | 641 | /* Get the mpic structure from the IPI number */ |
| 649 | static inline struct mpic * mpic_from_ipi(unsigned int ipi) | 642 | static inline struct mpic * mpic_from_ipi(unsigned int ipi) |
| 650 | { | 643 | { |
| 651 | return irq_desc[ipi].chip_data; | 644 | return irq_to_desc(ipi)->chip_data; |
| 652 | } | 645 | } |
| 653 | #endif | 646 | #endif |
| 654 | 647 | ||
| 655 | /* Get the mpic structure from the irq number */ | 648 | /* Get the mpic structure from the irq number */ |
| 656 | static inline struct mpic * mpic_from_irq(unsigned int irq) | 649 | static inline struct mpic * mpic_from_irq(unsigned int irq) |
| 657 | { | 650 | { |
| 658 | return irq_desc[irq].chip_data; | 651 | return irq_to_desc(irq)->chip_data; |
| 659 | } | 652 | } |
| 660 | 653 | ||
| 661 | /* Send an EOI */ | 654 | /* Send an EOI */ |
| @@ -735,7 +728,7 @@ static void mpic_unmask_ht_irq(unsigned int irq) | |||
| 735 | 728 | ||
| 736 | mpic_unmask_irq(irq); | 729 | mpic_unmask_irq(irq); |
| 737 | 730 | ||
| 738 | if (irq_desc[irq].status & IRQ_LEVEL) | 731 | if (irq_to_desc(irq)->status & IRQ_LEVEL) |
| 739 | mpic_ht_end_irq(mpic, src); | 732 | mpic_ht_end_irq(mpic, src); |
| 740 | } | 733 | } |
| 741 | 734 | ||
| @@ -745,7 +738,7 @@ static unsigned int mpic_startup_ht_irq(unsigned int irq) | |||
| 745 | unsigned int src = mpic_irq_to_hw(irq); | 738 | unsigned int src = mpic_irq_to_hw(irq); |
| 746 | 739 | ||
| 747 | mpic_unmask_irq(irq); | 740 | mpic_unmask_irq(irq); |
| 748 | mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status); | 741 | mpic_startup_ht_interrupt(mpic, src, irq_to_desc(irq)->status); |
| 749 | 742 | ||
| 750 | return 0; | 743 | return 0; |
| 751 | } | 744 | } |
| @@ -755,7 +748,7 @@ static void mpic_shutdown_ht_irq(unsigned int irq) | |||
| 755 | struct mpic *mpic = mpic_from_irq(irq); | 748 | struct mpic *mpic = mpic_from_irq(irq); |
| 756 | unsigned int src = mpic_irq_to_hw(irq); | 749 | unsigned int src = mpic_irq_to_hw(irq); |
| 757 | 750 | ||
| 758 | mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status); | 751 | mpic_shutdown_ht_interrupt(mpic, src, irq_to_desc(irq)->status); |
| 759 | mpic_mask_irq(irq); | 752 | mpic_mask_irq(irq); |
| 760 | } | 753 | } |
| 761 | 754 | ||
| @@ -772,7 +765,7 @@ static void mpic_end_ht_irq(unsigned int irq) | |||
| 772 | * latched another edge interrupt coming in anyway | 765 | * latched another edge interrupt coming in anyway |
| 773 | */ | 766 | */ |
| 774 | 767 | ||
| 775 | if (irq_desc[irq].status & IRQ_LEVEL) | 768 | if (irq_to_desc(irq)->status & IRQ_LEVEL) |
| 776 | mpic_ht_end_irq(mpic, src); | 769 | mpic_ht_end_irq(mpic, src); |
| 777 | mpic_eoi(mpic); | 770 | mpic_eoi(mpic); |
| 778 | } | 771 | } |
| @@ -816,7 +809,7 @@ int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask) | |||
| 816 | unsigned int src = mpic_irq_to_hw(irq); | 809 | unsigned int src = mpic_irq_to_hw(irq); |
| 817 | 810 | ||
| 818 | if (mpic->flags & MPIC_SINGLE_DEST_CPU) { | 811 | if (mpic->flags & MPIC_SINGLE_DEST_CPU) { |
| 819 | int cpuid = irq_choose_cpu(irq); | 812 | int cpuid = irq_choose_cpu(cpumask); |
| 820 | 813 | ||
| 821 | mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid); | 814 | mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid); |
| 822 | } else { | 815 | } else { |
| @@ -856,7 +849,7 @@ int mpic_set_irq_type(unsigned int virq, unsigned int flow_type) | |||
| 856 | { | 849 | { |
| 857 | struct mpic *mpic = mpic_from_irq(virq); | 850 | struct mpic *mpic = mpic_from_irq(virq); |
| 858 | unsigned int src = mpic_irq_to_hw(virq); | 851 | unsigned int src = mpic_irq_to_hw(virq); |
| 859 | struct irq_desc *desc = get_irq_desc(virq); | 852 | struct irq_desc *desc = irq_to_desc(virq); |
| 860 | unsigned int vecpri, vold, vnew; | 853 | unsigned int vecpri, vold, vnew; |
| 861 | 854 | ||
| 862 | DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n", | 855 | DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n", |
| @@ -994,7 +987,7 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq, | |||
| 994 | } | 987 | } |
| 995 | 988 | ||
| 996 | static int mpic_host_xlate(struct irq_host *h, struct device_node *ct, | 989 | static int mpic_host_xlate(struct irq_host *h, struct device_node *ct, |
| 997 | u32 *intspec, unsigned int intsize, | 990 | const u32 *intspec, unsigned int intsize, |
| 998 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) | 991 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) |
| 999 | 992 | ||
| 1000 | { | 993 | { |
| @@ -1062,19 +1055,19 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
| 1062 | mpic->name = name; | 1055 | mpic->name = name; |
| 1063 | 1056 | ||
| 1064 | mpic->hc_irq = mpic_irq_chip; | 1057 | mpic->hc_irq = mpic_irq_chip; |
| 1065 | mpic->hc_irq.typename = name; | 1058 | mpic->hc_irq.name = name; |
| 1066 | if (flags & MPIC_PRIMARY) | 1059 | if (flags & MPIC_PRIMARY) |
| 1067 | mpic->hc_irq.set_affinity = mpic_set_affinity; | 1060 | mpic->hc_irq.set_affinity = mpic_set_affinity; |
| 1068 | #ifdef CONFIG_MPIC_U3_HT_IRQS | 1061 | #ifdef CONFIG_MPIC_U3_HT_IRQS |
| 1069 | mpic->hc_ht_irq = mpic_irq_ht_chip; | 1062 | mpic->hc_ht_irq = mpic_irq_ht_chip; |
| 1070 | mpic->hc_ht_irq.typename = name; | 1063 | mpic->hc_ht_irq.name = name; |
| 1071 | if (flags & MPIC_PRIMARY) | 1064 | if (flags & MPIC_PRIMARY) |
| 1072 | mpic->hc_ht_irq.set_affinity = mpic_set_affinity; | 1065 | mpic->hc_ht_irq.set_affinity = mpic_set_affinity; |
| 1073 | #endif /* CONFIG_MPIC_U3_HT_IRQS */ | 1066 | #endif /* CONFIG_MPIC_U3_HT_IRQS */ |
| 1074 | 1067 | ||
| 1075 | #ifdef CONFIG_SMP | 1068 | #ifdef CONFIG_SMP |
| 1076 | mpic->hc_ipi = mpic_ipi_chip; | 1069 | mpic->hc_ipi = mpic_ipi_chip; |
| 1077 | mpic->hc_ipi.typename = name; | 1070 | mpic->hc_ipi.name = name; |
| 1078 | #endif /* CONFIG_SMP */ | 1071 | #endif /* CONFIG_SMP */ |
| 1079 | 1072 | ||
| 1080 | mpic->flags = flags; | 1073 | mpic->flags = flags; |
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c index 1d44eee80fa1..0f67cd79d481 100644 --- a/arch/powerpc/sysdev/mpic_msi.c +++ b/arch/powerpc/sysdev/mpic_msi.c | |||
| @@ -39,7 +39,12 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) | |||
| 39 | 39 | ||
| 40 | pr_debug("mpic: found U3, guessing msi allocator setup\n"); | 40 | pr_debug("mpic: found U3, guessing msi allocator setup\n"); |
| 41 | 41 | ||
| 42 | /* Reserve source numbers we know are reserved in the HW */ | 42 | /* Reserve source numbers we know are reserved in the HW. |
| 43 | * | ||
| 44 | * This is a bit of a mix of U3 and U4 reserves but that's going | ||
| 45 | * to work fine, we have plenty enugh numbers left so let's just | ||
| 46 | * mark anything we don't like reserved. | ||
| 47 | */ | ||
| 43 | for (i = 0; i < 8; i++) | 48 | for (i = 0; i < 8; i++) |
| 44 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); | 49 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); |
| 45 | 50 | ||
| @@ -49,6 +54,10 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) | |||
| 49 | for (i = 100; i < 105; i++) | 54 | for (i = 100; i < 105; i++) |
| 50 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); | 55 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); |
| 51 | 56 | ||
| 57 | for (i = 124; i < mpic->irq_count; i++) | ||
| 58 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); | ||
| 59 | |||
| 60 | |||
| 52 | np = NULL; | 61 | np = NULL; |
| 53 | while ((np = of_find_all_nodes(np))) { | 62 | while ((np = of_find_all_nodes(np))) { |
| 54 | pr_debug("mpic: mapping hwirqs for %s\n", np->full_name); | 63 | pr_debug("mpic: mapping hwirqs for %s\n", np->full_name); |
diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c index 656cb772b691..0f6ab06f8474 100644 --- a/arch/powerpc/sysdev/mpic_pasemi_msi.c +++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c | |||
| @@ -60,7 +60,7 @@ static struct irq_chip mpic_pasemi_msi_chip = { | |||
| 60 | .eoi = mpic_end_irq, | 60 | .eoi = mpic_end_irq, |
| 61 | .set_type = mpic_set_irq_type, | 61 | .set_type = mpic_set_irq_type, |
| 62 | .set_affinity = mpic_set_affinity, | 62 | .set_affinity = mpic_set_affinity, |
| 63 | .typename = "PASEMI-MSI ", | 63 | .name = "PASEMI-MSI ", |
| 64 | }; | 64 | }; |
| 65 | 65 | ||
| 66 | static int pasemi_msi_check_device(struct pci_dev *pdev, int nvec, int type) | 66 | static int pasemi_msi_check_device(struct pci_dev *pdev, int nvec, int type) |
diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c index 0a8f5a9e87c9..bcbfe79c704b 100644 --- a/arch/powerpc/sysdev/mpic_u3msi.c +++ b/arch/powerpc/sysdev/mpic_u3msi.c | |||
| @@ -42,7 +42,7 @@ static struct irq_chip mpic_u3msi_chip = { | |||
| 42 | .eoi = mpic_end_irq, | 42 | .eoi = mpic_end_irq, |
| 43 | .set_type = mpic_set_irq_type, | 43 | .set_type = mpic_set_irq_type, |
| 44 | .set_affinity = mpic_set_affinity, | 44 | .set_affinity = mpic_set_affinity, |
| 45 | .typename = "MPIC-U3MSI", | 45 | .name = "MPIC-U3MSI", |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | static u64 read_ht_magic_addr(struct pci_dev *pdev, unsigned int pos) | 48 | static u64 read_ht_magic_addr(struct pci_dev *pdev, unsigned int pos) |
| @@ -64,12 +64,12 @@ static u64 read_ht_magic_addr(struct pci_dev *pdev, unsigned int pos) | |||
| 64 | return addr; | 64 | return addr; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | static u64 find_ht_magic_addr(struct pci_dev *pdev) | 67 | static u64 find_ht_magic_addr(struct pci_dev *pdev, unsigned int hwirq) |
| 68 | { | 68 | { |
| 69 | struct pci_bus *bus; | 69 | struct pci_bus *bus; |
| 70 | unsigned int pos; | 70 | unsigned int pos; |
| 71 | 71 | ||
| 72 | for (bus = pdev->bus; bus; bus = bus->parent) { | 72 | for (bus = pdev->bus; bus && bus->self; bus = bus->parent) { |
| 73 | pos = pci_find_ht_capability(bus->self, HT_CAPTYPE_MSI_MAPPING); | 73 | pos = pci_find_ht_capability(bus->self, HT_CAPTYPE_MSI_MAPPING); |
| 74 | if (pos) | 74 | if (pos) |
| 75 | return read_ht_magic_addr(bus->self, pos); | 75 | return read_ht_magic_addr(bus->self, pos); |
| @@ -78,13 +78,41 @@ static u64 find_ht_magic_addr(struct pci_dev *pdev) | |||
| 78 | return 0; | 78 | return 0; |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | static u64 find_u4_magic_addr(struct pci_dev *pdev, unsigned int hwirq) | ||
| 82 | { | ||
| 83 | struct pci_controller *hose = pci_bus_to_host(pdev->bus); | ||
| 84 | |||
| 85 | /* U4 PCIe MSIs need to write to the special register in | ||
| 86 | * the bridge that generates interrupts. There should be | ||
| 87 | * theorically a register at 0xf8005000 where you just write | ||
| 88 | * the MSI number and that triggers the right interrupt, but | ||
| 89 | * unfortunately, this is busted in HW, the bridge endian swaps | ||
| 90 | * the value and hits the wrong nibble in the register. | ||
| 91 | * | ||
| 92 | * So instead we use another register set which is used normally | ||
| 93 | * for converting HT interrupts to MPIC interrupts, which decodes | ||
| 94 | * the interrupt number as part of the low address bits | ||
| 95 | * | ||
| 96 | * This will not work if we ever use more than one legacy MSI in | ||
| 97 | * a block but we never do. For one MSI or multiple MSI-X where | ||
| 98 | * each interrupt address can be specified separately, it works | ||
| 99 | * just fine. | ||
| 100 | */ | ||
| 101 | if (of_device_is_compatible(hose->dn, "u4-pcie") || | ||
| 102 | of_device_is_compatible(hose->dn, "U4-pcie")) | ||
| 103 | return 0xf8004000 | (hwirq << 4); | ||
| 104 | |||
| 105 | return 0; | ||
| 106 | } | ||
| 107 | |||
| 81 | static int u3msi_msi_check_device(struct pci_dev *pdev, int nvec, int type) | 108 | static int u3msi_msi_check_device(struct pci_dev *pdev, int nvec, int type) |
| 82 | { | 109 | { |
| 83 | if (type == PCI_CAP_ID_MSIX) | 110 | if (type == PCI_CAP_ID_MSIX) |
| 84 | pr_debug("u3msi: MSI-X untested, trying anyway.\n"); | 111 | pr_debug("u3msi: MSI-X untested, trying anyway.\n"); |
| 85 | 112 | ||
| 86 | /* If we can't find a magic address then MSI ain't gonna work */ | 113 | /* If we can't find a magic address then MSI ain't gonna work */ |
| 87 | if (find_ht_magic_addr(pdev) == 0) { | 114 | if (find_ht_magic_addr(pdev, 0) == 0 && |
| 115 | find_u4_magic_addr(pdev, 0) == 0) { | ||
| 88 | pr_debug("u3msi: no magic address found for %s\n", | 116 | pr_debug("u3msi: no magic address found for %s\n", |
| 89 | pci_name(pdev)); | 117 | pci_name(pdev)); |
| 90 | return -ENXIO; | 118 | return -ENXIO; |
| @@ -118,10 +146,6 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
| 118 | u64 addr; | 146 | u64 addr; |
| 119 | int hwirq; | 147 | int hwirq; |
| 120 | 148 | ||
| 121 | addr = find_ht_magic_addr(pdev); | ||
| 122 | msg.address_lo = addr & 0xFFFFFFFF; | ||
| 123 | msg.address_hi = addr >> 32; | ||
| 124 | |||
| 125 | list_for_each_entry(entry, &pdev->msi_list, list) { | 149 | list_for_each_entry(entry, &pdev->msi_list, list) { |
| 126 | hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1); | 150 | hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1); |
| 127 | if (hwirq < 0) { | 151 | if (hwirq < 0) { |
| @@ -129,6 +153,12 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
| 129 | return hwirq; | 153 | return hwirq; |
| 130 | } | 154 | } |
| 131 | 155 | ||
| 156 | addr = find_ht_magic_addr(pdev, hwirq); | ||
| 157 | if (addr == 0) | ||
| 158 | addr = find_u4_magic_addr(pdev, hwirq); | ||
| 159 | msg.address_lo = addr & 0xFFFFFFFF; | ||
| 160 | msg.address_hi = addr >> 32; | ||
| 161 | |||
| 132 | virq = irq_create_mapping(msi_mpic->irqhost, hwirq); | 162 | virq = irq_create_mapping(msi_mpic->irqhost, hwirq); |
| 133 | if (virq == NO_IRQ) { | 163 | if (virq == NO_IRQ) { |
| 134 | pr_debug("u3msi: failed mapping hwirq 0x%x\n", hwirq); | 164 | pr_debug("u3msi: failed mapping hwirq 0x%x\n", hwirq); |
| @@ -143,6 +173,8 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
| 143 | pr_debug("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n", | 173 | pr_debug("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n", |
| 144 | virq, hwirq, (unsigned long)addr); | 174 | virq, hwirq, (unsigned long)addr); |
| 145 | 175 | ||
| 176 | printk("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n", | ||
| 177 | virq, hwirq, (unsigned long)addr); | ||
| 146 | msg.data = hwirq; | 178 | msg.data = hwirq; |
| 147 | write_msi_msg(virq, &msg); | 179 | write_msi_msg(virq, &msg); |
| 148 | 180 | ||
diff --git a/arch/powerpc/sysdev/mv64x60_pic.c b/arch/powerpc/sysdev/mv64x60_pic.c index 2aa4ed066db1..485b92477d7c 100644 --- a/arch/powerpc/sysdev/mv64x60_pic.c +++ b/arch/powerpc/sysdev/mv64x60_pic.c | |||
| @@ -213,7 +213,7 @@ static int mv64x60_host_map(struct irq_host *h, unsigned int virq, | |||
| 213 | { | 213 | { |
| 214 | int level1; | 214 | int level1; |
| 215 | 215 | ||
| 216 | get_irq_desc(virq)->status |= IRQ_LEVEL; | 216 | irq_to_desc(virq)->status |= IRQ_LEVEL; |
| 217 | 217 | ||
| 218 | level1 = (hwirq & MV64x60_LEVEL1_MASK) >> MV64x60_LEVEL1_OFFSET; | 218 | level1 = (hwirq & MV64x60_LEVEL1_MASK) >> MV64x60_LEVEL1_OFFSET; |
| 219 | BUG_ON(level1 > MV64x60_LEVEL1_GPP); | 219 | BUG_ON(level1 > MV64x60_LEVEL1_GPP); |
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c index 464271bea6c9..149393c02c3f 100644 --- a/arch/powerpc/sysdev/qe_lib/qe.c +++ b/arch/powerpc/sysdev/qe_lib/qe.c | |||
| @@ -27,6 +27,8 @@ | |||
| 27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
| 28 | #include <linux/ioport.h> | 28 | #include <linux/ioport.h> |
| 29 | #include <linux/crc32.h> | 29 | #include <linux/crc32.h> |
| 30 | #include <linux/mod_devicetable.h> | ||
| 31 | #include <linux/of_platform.h> | ||
| 30 | #include <asm/irq.h> | 32 | #include <asm/irq.h> |
| 31 | #include <asm/page.h> | 33 | #include <asm/page.h> |
| 32 | #include <asm/pgtable.h> | 34 | #include <asm/pgtable.h> |
| @@ -65,19 +67,6 @@ static unsigned int qe_num_of_snum; | |||
| 65 | 67 | ||
| 66 | static phys_addr_t qebase = -1; | 68 | static phys_addr_t qebase = -1; |
| 67 | 69 | ||
| 68 | int qe_alive_during_sleep(void) | ||
| 69 | { | ||
| 70 | static int ret = -1; | ||
| 71 | |||
| 72 | if (ret != -1) | ||
| 73 | return ret; | ||
| 74 | |||
| 75 | ret = !of_find_compatible_node(NULL, NULL, "fsl,mpc8569-pmc"); | ||
| 76 | |||
| 77 | return ret; | ||
| 78 | } | ||
| 79 | EXPORT_SYMBOL(qe_alive_during_sleep); | ||
| 80 | |||
| 81 | phys_addr_t get_qe_base(void) | 70 | phys_addr_t get_qe_base(void) |
| 82 | { | 71 | { |
| 83 | struct device_node *qe; | 72 | struct device_node *qe; |
| @@ -104,7 +93,7 @@ phys_addr_t get_qe_base(void) | |||
| 104 | 93 | ||
| 105 | EXPORT_SYMBOL(get_qe_base); | 94 | EXPORT_SYMBOL(get_qe_base); |
| 106 | 95 | ||
| 107 | void __init qe_reset(void) | 96 | void qe_reset(void) |
| 108 | { | 97 | { |
| 109 | if (qe_immr == NULL) | 98 | if (qe_immr == NULL) |
| 110 | qe_immr = ioremap(get_qe_base(), QE_IMMAP_SIZE); | 99 | qe_immr = ioremap(get_qe_base(), QE_IMMAP_SIZE); |
| @@ -330,16 +319,18 @@ EXPORT_SYMBOL(qe_put_snum); | |||
| 330 | static int qe_sdma_init(void) | 319 | static int qe_sdma_init(void) |
| 331 | { | 320 | { |
| 332 | struct sdma __iomem *sdma = &qe_immr->sdma; | 321 | struct sdma __iomem *sdma = &qe_immr->sdma; |
| 333 | unsigned long sdma_buf_offset; | 322 | static unsigned long sdma_buf_offset = (unsigned long)-ENOMEM; |
| 334 | 323 | ||
| 335 | if (!sdma) | 324 | if (!sdma) |
| 336 | return -ENODEV; | 325 | return -ENODEV; |
| 337 | 326 | ||
| 338 | /* allocate 2 internal temporary buffers (512 bytes size each) for | 327 | /* allocate 2 internal temporary buffers (512 bytes size each) for |
| 339 | * the SDMA */ | 328 | * the SDMA */ |
| 340 | sdma_buf_offset = qe_muram_alloc(512 * 2, 4096); | 329 | if (IS_ERR_VALUE(sdma_buf_offset)) { |
| 341 | if (IS_ERR_VALUE(sdma_buf_offset)) | 330 | sdma_buf_offset = qe_muram_alloc(512 * 2, 4096); |
| 342 | return -ENOMEM; | 331 | if (IS_ERR_VALUE(sdma_buf_offset)) |
| 332 | return -ENOMEM; | ||
| 333 | } | ||
| 343 | 334 | ||
| 344 | out_be32(&sdma->sdebcr, (u32) sdma_buf_offset & QE_SDEBCR_BA_MASK); | 335 | out_be32(&sdma->sdebcr, (u32) sdma_buf_offset & QE_SDEBCR_BA_MASK); |
| 345 | out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK | | 336 | out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK | |
| @@ -349,7 +340,7 @@ static int qe_sdma_init(void) | |||
| 349 | } | 340 | } |
| 350 | 341 | ||
| 351 | /* The maximum number of RISCs we support */ | 342 | /* The maximum number of RISCs we support */ |
| 352 | #define MAX_QE_RISC 2 | 343 | #define MAX_QE_RISC 4 |
| 353 | 344 | ||
| 354 | /* Firmware information stored here for qe_get_firmware_info() */ | 345 | /* Firmware information stored here for qe_get_firmware_info() */ |
| 355 | static struct qe_firmware_info qe_firmware_info; | 346 | static struct qe_firmware_info qe_firmware_info; |
| @@ -658,3 +649,35 @@ unsigned int qe_get_num_of_snums(void) | |||
| 658 | return num_of_snums; | 649 | return num_of_snums; |
| 659 | } | 650 | } |
| 660 | EXPORT_SYMBOL(qe_get_num_of_snums); | 651 | EXPORT_SYMBOL(qe_get_num_of_snums); |
| 652 | |||
| 653 | #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx) | ||
| 654 | static int qe_resume(struct of_device *ofdev) | ||
| 655 | { | ||
| 656 | if (!qe_alive_during_sleep()) | ||
| 657 | qe_reset(); | ||
| 658 | return 0; | ||
| 659 | } | ||
| 660 | |||
| 661 | static int qe_probe(struct of_device *ofdev, const struct of_device_id *id) | ||
| 662 | { | ||
| 663 | return 0; | ||
| 664 | } | ||
| 665 | |||
| 666 | static const struct of_device_id qe_ids[] = { | ||
| 667 | { .compatible = "fsl,qe", }, | ||
| 668 | { }, | ||
| 669 | }; | ||
| 670 | |||
| 671 | static struct of_platform_driver qe_driver = { | ||
| 672 | .driver.name = "fsl-qe", | ||
| 673 | .match_table = qe_ids, | ||
| 674 | .probe = qe_probe, | ||
| 675 | .resume = qe_resume, | ||
| 676 | }; | ||
| 677 | |||
| 678 | static int __init qe_drv_init(void) | ||
| 679 | { | ||
| 680 | return of_register_platform_driver(&qe_driver); | ||
| 681 | } | ||
| 682 | device_initcall(qe_drv_init); | ||
| 683 | #endif /* defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx) */ | ||
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c index 3faa42e03a85..2acc928d1920 100644 --- a/arch/powerpc/sysdev/qe_lib/qe_ic.c +++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c | |||
| @@ -189,7 +189,7 @@ static inline void qe_ic_write(volatile __be32 __iomem * base, unsigned int reg | |||
| 189 | 189 | ||
| 190 | static inline struct qe_ic *qe_ic_from_irq(unsigned int virq) | 190 | static inline struct qe_ic *qe_ic_from_irq(unsigned int virq) |
| 191 | { | 191 | { |
| 192 | return irq_desc[virq].chip_data; | 192 | return irq_to_desc(virq)->chip_data; |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | #define virq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq) | 195 | #define virq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq) |
| @@ -237,7 +237,7 @@ static void qe_ic_mask_irq(unsigned int virq) | |||
| 237 | } | 237 | } |
| 238 | 238 | ||
| 239 | static struct irq_chip qe_ic_irq_chip = { | 239 | static struct irq_chip qe_ic_irq_chip = { |
| 240 | .typename = " QEIC ", | 240 | .name = " QEIC ", |
| 241 | .unmask = qe_ic_unmask_irq, | 241 | .unmask = qe_ic_unmask_irq, |
| 242 | .mask = qe_ic_mask_irq, | 242 | .mask = qe_ic_mask_irq, |
| 243 | .mask_ack = qe_ic_mask_irq, | 243 | .mask_ack = qe_ic_mask_irq, |
| @@ -263,7 +263,7 @@ static int qe_ic_host_map(struct irq_host *h, unsigned int virq, | |||
| 263 | chip = &qe_ic->hc_irq; | 263 | chip = &qe_ic->hc_irq; |
| 264 | 264 | ||
| 265 | set_irq_chip_data(virq, qe_ic); | 265 | set_irq_chip_data(virq, qe_ic); |
| 266 | get_irq_desc(virq)->status |= IRQ_LEVEL; | 266 | irq_to_desc(virq)->status |= IRQ_LEVEL; |
| 267 | 267 | ||
| 268 | set_irq_chip_and_handler(virq, chip, handle_level_irq); | 268 | set_irq_chip_and_handler(virq, chip, handle_level_irq); |
| 269 | 269 | ||
| @@ -271,7 +271,7 @@ static int qe_ic_host_map(struct irq_host *h, unsigned int virq, | |||
| 271 | } | 271 | } |
| 272 | 272 | ||
| 273 | static int qe_ic_host_xlate(struct irq_host *h, struct device_node *ct, | 273 | static int qe_ic_host_xlate(struct irq_host *h, struct device_node *ct, |
| 274 | u32 * intspec, unsigned int intsize, | 274 | const u32 * intspec, unsigned int intsize, |
| 275 | irq_hw_number_t * out_hwirq, | 275 | irq_hw_number_t * out_hwirq, |
| 276 | unsigned int *out_flags) | 276 | unsigned int *out_flags) |
| 277 | { | 277 | { |
diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c index cf244a419e96..595034cfb85a 100644 --- a/arch/powerpc/sysdev/tsi108_pci.c +++ b/arch/powerpc/sysdev/tsi108_pci.c | |||
| @@ -376,7 +376,7 @@ static void tsi108_pci_irq_end(u_int irq) | |||
| 376 | */ | 376 | */ |
| 377 | 377 | ||
| 378 | static struct irq_chip tsi108_pci_irq = { | 378 | static struct irq_chip tsi108_pci_irq = { |
| 379 | .typename = "tsi108_PCI_int", | 379 | .name = "tsi108_PCI_int", |
| 380 | .mask = tsi108_pci_irq_disable, | 380 | .mask = tsi108_pci_irq_disable, |
| 381 | .ack = tsi108_pci_irq_ack, | 381 | .ack = tsi108_pci_irq_ack, |
| 382 | .end = tsi108_pci_irq_end, | 382 | .end = tsi108_pci_irq_end, |
| @@ -384,7 +384,7 @@ static struct irq_chip tsi108_pci_irq = { | |||
| 384 | }; | 384 | }; |
| 385 | 385 | ||
| 386 | static int pci_irq_host_xlate(struct irq_host *h, struct device_node *ct, | 386 | static int pci_irq_host_xlate(struct irq_host *h, struct device_node *ct, |
| 387 | u32 *intspec, unsigned int intsize, | 387 | const u32 *intspec, unsigned int intsize, |
| 388 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) | 388 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) |
| 389 | { | 389 | { |
| 390 | *out_hwirq = intspec[0]; | 390 | *out_hwirq = intspec[0]; |
| @@ -398,7 +398,7 @@ static int pci_irq_host_map(struct irq_host *h, unsigned int virq, | |||
| 398 | DBG("%s(%d, 0x%lx)\n", __func__, virq, hw); | 398 | DBG("%s(%d, 0x%lx)\n", __func__, virq, hw); |
| 399 | if ((virq >= 1) && (virq <= 4)){ | 399 | if ((virq >= 1) && (virq <= 4)){ |
| 400 | irq = virq + IRQ_PCI_INTAD_BASE - 1; | 400 | irq = virq + IRQ_PCI_INTAD_BASE - 1; |
| 401 | get_irq_desc(irq)->status |= IRQ_LEVEL; | 401 | irq_to_desc(irq)->status |= IRQ_LEVEL; |
| 402 | set_irq_chip(irq, &tsi108_pci_irq); | 402 | set_irq_chip(irq, &tsi108_pci_irq); |
| 403 | } | 403 | } |
| 404 | return 0; | 404 | return 0; |
diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c index 466ce9ace127..6f220a913e42 100644 --- a/arch/powerpc/sysdev/uic.c +++ b/arch/powerpc/sysdev/uic.c | |||
| @@ -57,7 +57,7 @@ struct uic { | |||
| 57 | 57 | ||
| 58 | static void uic_unmask_irq(unsigned int virq) | 58 | static void uic_unmask_irq(unsigned int virq) |
| 59 | { | 59 | { |
| 60 | struct irq_desc *desc = get_irq_desc(virq); | 60 | struct irq_desc *desc = irq_to_desc(virq); |
| 61 | struct uic *uic = get_irq_chip_data(virq); | 61 | struct uic *uic = get_irq_chip_data(virq); |
| 62 | unsigned int src = uic_irq_to_hw(virq); | 62 | unsigned int src = uic_irq_to_hw(virq); |
| 63 | unsigned long flags; | 63 | unsigned long flags; |
| @@ -101,7 +101,7 @@ static void uic_ack_irq(unsigned int virq) | |||
| 101 | 101 | ||
| 102 | static void uic_mask_ack_irq(unsigned int virq) | 102 | static void uic_mask_ack_irq(unsigned int virq) |
| 103 | { | 103 | { |
| 104 | struct irq_desc *desc = get_irq_desc(virq); | 104 | struct irq_desc *desc = irq_to_desc(virq); |
| 105 | struct uic *uic = get_irq_chip_data(virq); | 105 | struct uic *uic = get_irq_chip_data(virq); |
| 106 | unsigned int src = uic_irq_to_hw(virq); | 106 | unsigned int src = uic_irq_to_hw(virq); |
| 107 | unsigned long flags; | 107 | unsigned long flags; |
| @@ -129,7 +129,7 @@ static int uic_set_irq_type(unsigned int virq, unsigned int flow_type) | |||
| 129 | { | 129 | { |
| 130 | struct uic *uic = get_irq_chip_data(virq); | 130 | struct uic *uic = get_irq_chip_data(virq); |
| 131 | unsigned int src = uic_irq_to_hw(virq); | 131 | unsigned int src = uic_irq_to_hw(virq); |
| 132 | struct irq_desc *desc = get_irq_desc(virq); | 132 | struct irq_desc *desc = irq_to_desc(virq); |
| 133 | unsigned long flags; | 133 | unsigned long flags; |
| 134 | int trigger, polarity; | 134 | int trigger, polarity; |
| 135 | u32 tr, pr, mask; | 135 | u32 tr, pr, mask; |
| @@ -177,7 +177,7 @@ static int uic_set_irq_type(unsigned int virq, unsigned int flow_type) | |||
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | static struct irq_chip uic_irq_chip = { | 179 | static struct irq_chip uic_irq_chip = { |
| 180 | .typename = " UIC ", | 180 | .name = " UIC ", |
| 181 | .unmask = uic_unmask_irq, | 181 | .unmask = uic_unmask_irq, |
| 182 | .mask = uic_mask_irq, | 182 | .mask = uic_mask_irq, |
| 183 | .mask_ack = uic_mask_ack_irq, | 183 | .mask_ack = uic_mask_ack_irq, |
| @@ -202,7 +202,7 @@ static int uic_host_map(struct irq_host *h, unsigned int virq, | |||
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | static int uic_host_xlate(struct irq_host *h, struct device_node *ct, | 204 | static int uic_host_xlate(struct irq_host *h, struct device_node *ct, |
| 205 | u32 *intspec, unsigned int intsize, | 205 | const u32 *intspec, unsigned int intsize, |
| 206 | irq_hw_number_t *out_hwirq, unsigned int *out_type) | 206 | irq_hw_number_t *out_hwirq, unsigned int *out_type) |
| 207 | 207 | ||
| 208 | { | 208 | { |
| @@ -225,12 +225,12 @@ void uic_irq_cascade(unsigned int virq, struct irq_desc *desc) | |||
| 225 | int src; | 225 | int src; |
| 226 | int subvirq; | 226 | int subvirq; |
| 227 | 227 | ||
| 228 | spin_lock(&desc->lock); | 228 | raw_spin_lock(&desc->lock); |
| 229 | if (desc->status & IRQ_LEVEL) | 229 | if (desc->status & IRQ_LEVEL) |
| 230 | desc->chip->mask(virq); | 230 | desc->chip->mask(virq); |
| 231 | else | 231 | else |
| 232 | desc->chip->mask_ack(virq); | 232 | desc->chip->mask_ack(virq); |
| 233 | spin_unlock(&desc->lock); | 233 | raw_spin_unlock(&desc->lock); |
| 234 | 234 | ||
| 235 | msr = mfdcr(uic->dcrbase + UIC_MSR); | 235 | msr = mfdcr(uic->dcrbase + UIC_MSR); |
| 236 | if (!msr) /* spurious interrupt */ | 236 | if (!msr) /* spurious interrupt */ |
| @@ -242,12 +242,12 @@ void uic_irq_cascade(unsigned int virq, struct irq_desc *desc) | |||
| 242 | generic_handle_irq(subvirq); | 242 | generic_handle_irq(subvirq); |
| 243 | 243 | ||
| 244 | uic_irq_ret: | 244 | uic_irq_ret: |
| 245 | spin_lock(&desc->lock); | 245 | raw_spin_lock(&desc->lock); |
| 246 | if (desc->status & IRQ_LEVEL) | 246 | if (desc->status & IRQ_LEVEL) |
| 247 | desc->chip->ack(virq); | 247 | desc->chip->ack(virq); |
| 248 | if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) | 248 | if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) |
| 249 | desc->chip->unmask(virq); | 249 | desc->chip->unmask(virq); |
| 250 | spin_unlock(&desc->lock); | 250 | raw_spin_unlock(&desc->lock); |
| 251 | } | 251 | } |
| 252 | 252 | ||
| 253 | static struct uic * __init uic_init_one(struct device_node *node) | 253 | static struct uic * __init uic_init_one(struct device_node *node) |
diff --git a/arch/powerpc/sysdev/xilinx_intc.c b/arch/powerpc/sysdev/xilinx_intc.c index 40edad520770..1e0ccfaf403e 100644 --- a/arch/powerpc/sysdev/xilinx_intc.c +++ b/arch/powerpc/sysdev/xilinx_intc.c | |||
| @@ -79,7 +79,7 @@ static void xilinx_intc_mask(unsigned int virq) | |||
| 79 | 79 | ||
| 80 | static int xilinx_intc_set_type(unsigned int virq, unsigned int flow_type) | 80 | static int xilinx_intc_set_type(unsigned int virq, unsigned int flow_type) |
| 81 | { | 81 | { |
| 82 | struct irq_desc *desc = get_irq_desc(virq); | 82 | struct irq_desc *desc = irq_to_desc(virq); |
| 83 | 83 | ||
| 84 | desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); | 84 | desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); |
| 85 | desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; | 85 | desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; |
| @@ -106,7 +106,7 @@ static void xilinx_intc_level_unmask(unsigned int virq) | |||
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | static struct irq_chip xilinx_intc_level_irqchip = { | 108 | static struct irq_chip xilinx_intc_level_irqchip = { |
| 109 | .typename = "Xilinx Level INTC", | 109 | .name = "Xilinx Level INTC", |
| 110 | .mask = xilinx_intc_mask, | 110 | .mask = xilinx_intc_mask, |
| 111 | .mask_ack = xilinx_intc_mask, | 111 | .mask_ack = xilinx_intc_mask, |
| 112 | .unmask = xilinx_intc_level_unmask, | 112 | .unmask = xilinx_intc_level_unmask, |
| @@ -133,7 +133,7 @@ static void xilinx_intc_edge_ack(unsigned int virq) | |||
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | static struct irq_chip xilinx_intc_edge_irqchip = { | 135 | static struct irq_chip xilinx_intc_edge_irqchip = { |
| 136 | .typename = "Xilinx Edge INTC", | 136 | .name = "Xilinx Edge INTC", |
| 137 | .mask = xilinx_intc_mask, | 137 | .mask = xilinx_intc_mask, |
| 138 | .unmask = xilinx_intc_edge_unmask, | 138 | .unmask = xilinx_intc_edge_unmask, |
| 139 | .ack = xilinx_intc_edge_ack, | 139 | .ack = xilinx_intc_edge_ack, |
| @@ -148,7 +148,7 @@ static struct irq_chip xilinx_intc_edge_irqchip = { | |||
| 148 | * xilinx_intc_xlate - translate virq# from device tree interrupts property | 148 | * xilinx_intc_xlate - translate virq# from device tree interrupts property |
| 149 | */ | 149 | */ |
| 150 | static int xilinx_intc_xlate(struct irq_host *h, struct device_node *ct, | 150 | static int xilinx_intc_xlate(struct irq_host *h, struct device_node *ct, |
| 151 | u32 *intspec, unsigned int intsize, | 151 | const u32 *intspec, unsigned int intsize, |
| 152 | irq_hw_number_t *out_hwirq, | 152 | irq_hw_number_t *out_hwirq, |
| 153 | unsigned int *out_flags) | 153 | unsigned int *out_flags) |
| 154 | { | 154 | { |
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index bdbe96c8a7e4..4e6152c13764 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
| @@ -1641,7 +1641,8 @@ static void super_regs(void) | |||
| 1641 | ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1); | 1641 | ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1); |
| 1642 | printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n", | 1642 | printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n", |
| 1643 | ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4); | 1643 | ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4); |
| 1644 | printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5); | 1644 | printf(" Saved Gpr5=%.16lx \n", |
| 1645 | ptrLpPaca->gpr5_dword.saved_gpr5); | ||
| 1645 | } | 1646 | } |
| 1646 | #endif | 1647 | #endif |
| 1647 | 1648 | ||
